Hi there! You are currently browsing as a guest. Why not create an account? Then you get less ads, can thank creators, post feedback, keep a list of your favourites, and more!
Virtual gardener
staff: administrator
Original Poster
#1 Old 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
Default 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 Old 29th Mar 2020 at 3:04 PM
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
Virtual gardener
staff: administrator
Original Poster
#3 Old 30th Mar 2020 at 8:56 AM
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


Skintone example
I might give this a try! Since indeed currently the code is not as optimised as I'd love to have it. In fact, it's giving me Wordpress flashbacks where it has you loop through all the posts to only get 1 entry :p (I know, super unrelated to sims stuff.)

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.
Back to top