- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- Importing Your own unique Object GroupId's for Game Objects!
- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- Importing Your own unique Object GroupId's for Game Objects!
Replies: 2 (Who?), Viewed: 675 times.
#1
29th Mar 2020 at 2:34 PM
Last edited by Lyralei : 29th Mar 2020 at 2:36 PM.
Reason: Changing the i to a j in the code block since bbcode got confused :p
Posts: 3,856
Thanks: 8483 in 67 Posts
Importing Your own unique Object GroupId's for Game Objects!
Hi everyone!Today, I just wanted to share another method I discovered as to how to import custom objects that are meant for just your creation!
So, the way that we currently do it is through XMLs (mainly used for books, fruits, etc), and a tad differently, (Also, see the way Zoe22 described it, which is Ani's method ) which is fine, but if you happen to have a script object (Like my Sewing table) where people might make their own GameObjects but simply aren't familiar to how to actually mod it to have their stuff show up. It's simply too complex or just a hassle.
The second thing that doesn't work really well with this method, is that you end up having to update your own download a lot (Unless it's CCLoader, but even that process is considered quite advanced for many regular content creators). Since the script is always reading from the same XML
Third thing, Most of the time people end up having to download CCLoader as a way to get it to work. (Depending on how you coded it of course!)
My method:
The game has actually a few goodies which can be used, as long as you got the unprotected scriptcore.dll as a reference (Oops!).
Now, to get to the method. With this method, the only thing we ask Content creators to edit is literally the group of a particular type (In my case OBJD). The code will loop through all object that has a group I want it to get and voila, you can do anything with it!
First off, this is a super quickly written code, so the whole Array/List thing makes no sense and will slightly slow down the code due to the conversion of List > Array, I know :p So it's okay to alter the hell out of this!
Code:
public override void OnStartup() { /* *Your start up code goes here of course, after that we run the GetAllSimulationObjectKeysLyralei() *function to call and fire the method. */ GetAllKeysForSewables(); // OR Print it in a notification to get a list of your resources you're looking for! :D StyledNotification.Show(new StyledNotification.Format(GetAllKeysForSewables().ToString(), StyledNotification.NotificationStyle.kDebugAlert)); } public static ResourceKey[] CustomGameObjectsArray; public static List<ResourceKey> CustomGameObjectsList; public static ResourceKey[] GetAllKeysForSewables() { ulong[] array = ScriptCore.Simulator.Simulator_GetAllSimulationObjectKeysImpl(); int num = array.Length; ResourceKey[] array2 = new ResourceKey[num]; for (int j = 0; j < num; j++) { //Has the OBJD(0x319E4F1D) type, but can also be used for OBJK(0x02DC343F) or any other type // MAKE SURE YOUR GROUP IS UNIQUE AND DOESN'T OVERRIDE SOMEONE ELSE'S GROUP ID!! ResourceKey customObjKey = new ResourceKey(array[j], 0x319E4F1D, 0x08008135); uint count = Sims3.SimIFace.Simulator.CountResources(customObjKey); if(count > 0) { CustomGameObjectsList.Add(customObjKey); } } return CustomGameObjectsArray = CustomGameObjectsList.ToArray(); }
How it works
Let's take a look at Simulator_GetAllSimulationObjectKeysImpl(), this is a function straight from Sims3Common.dll, which can be found in the Scriptcore.dll Simulator class. It makes a direct call to the engine where it will get us all instance IDs of ALL objects that are in the game. (Which is about 6000 for me :p). Keep in mind that this is all the loaded, but not instantiated, objects. They don't have to be in the world to be seen by this function unlike "GetObjects<T>()"
Simulator_GetAllSimulationObjectKeysImpl() will therefore return a ulong string which is the object's instance.
We go into the For loop where we first need to convert our ulong instances into something the game can use. Luckily for us, the ResourceKey can take care of that. Additionally, we add the 'Type' (Which in my case is an OBJD) and my own custom Group. Feel free to use S3PE as a reference!
Quote:
"But doesn't all entries that 'Simulator_GetAllSimulationObjectKeysImpl()''s get then get replaced??" - Me, when discussing the code logistics with tashiketh. I hear you say :p It does, but really all it alters is the "ulong' it returns to us. It won't harm the object inside the game whatsoever, it's just the output that's altered to a ResourceKey. |
After that, we call the Simulator.CountResources() Function. It expects us to give it a ResourceKey value in the overload, which we just got for ourselves (See customObjKey)! Now, CountResources actually looks at all package resources and files that the game currently loaded, despite it being on the world or not, and will find any existing resources that have the group ID of 0x08008135.
Add it to an Array or List and voila! You got yourself a filtered out resource that you can later use in functions like "createObjectOutOfWorld" and such!
Advantages:
- Object creators only have to alter the group in S3PE and that's it!
- The ResourceKey is more dynamic, making it possible to alter it in particular ways later on if you really want it. (Wouldn't recommend it though)
- No need to update the code or any other files constantly when someone wants to join the project.
- Downloaders don't have to download additional resources, like CCLoader.
Disadvantages:
- Because it loads literally 6000 on startup/on world load, it will take it 3 seconds to fire this script. On Startup for objects, it will, therefore, take 3 seconds before you can place your object down in the world.
- Every Script modders need to take into account that they have their OWN UNIQUE group Id for each project.
- This method, afaik, only works with GameObjects and not for Ingredient items (Like Books, Recipes, Ingredients).
- Simulator_GetAllSimulationObjectKeysImpl()' will only get OBJD/OBJK instances. (These are always the same, but I assume it's originally the OBJDs)
Any feedback or thought are always welcome! I just thought it was cool to mention it for the people who wanted to have a different method to importing 'third-party' content
Advertisement
Space Pony
#2
29th Mar 2020 at 3:04 PM
Posts: 433
Thanks: 782 in 6 Posts
Hey @Lyralei
I "use" something similar but i take advantage of the keysearch maybe this could be useful to you aswell (since its quite a bit faster)
Generic
Skintone example
I "use" something similar but i take advantage of the keysearch maybe this could be useful to you aswell (since its quite a bit faster)
Generic
Code:
public static List<ResourceKey> GetResourcekeysByTypeID(uint TypeID) { KeySearch keySearch = new KeySearch(TypeID); List<ResourceKey> keys = new List<ResourceKey>(); foreach (ResourceKey resourceKey in keySearch) { keys.Add(resourceKey); } return keys; }
Skintone example
Code:
public static List<ResourceKey> GetInstalledSkintones() { KeySearch keySearch = new KeySearch(55867754u); List<ResourceKey> keys = new List<ResourceKey>(); foreach (ResourceKey resourceKey in keySearch) { keys.Add(resourceKey); } return keys; }
#3
30th Mar 2020 at 8:56 AM
Posts: 3,856
Thanks: 8483 in 67 Posts
Quote: Originally posted by Battery
Hey @Lyralei I "use" something similar but i take advantage of the keysearch maybe this could be useful to you aswell (since its quite a bit faster) Generic
Code:
public static List<ResourceKey> GetResourcekeysByTypeID(uint TypeID) { KeySearch keySearch = new KeySearch(TypeID); List<ResourceKey> keys = new List<ResourceKey>(); foreach (ResourceKey resourceKey in keySearch) { keys.Add(resourceKey); } return keys; } Skintone example
Code:
public static List<ResourceKey> GetInstalledSkintones() { KeySearch keySearch = new KeySearch(55867754u); List<ResourceKey> keys = new List<ResourceKey>(); foreach (ResourceKey resourceKey in keySearch) { keys.Add(resourceKey); } return keys; } |
So if I do, I'll include that piece of code here too, since I do think that grabbing it from the groupID (So not Type or instance) is a really good practise for communicating your script with that of someone who wants to make an GameObject compatible with your mod, rather than a XML file.
Who Posted
|