- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- Tip/brains needed for instantiating objects on world loading
- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- Tip/brains needed for instantiating objects on world loading
Replies: 10 (Who?), Viewed: 1518 times.
#1
22nd Sep 2019 at 2:19 PM
Last edited by Lyralei : 22nd Sep 2019 at 3:16 PM.
Posts: 3,860
Thanks: 8546 in 67 Posts
Tip/brains needed for instantiating objects on world loading
Yes! Another coding thread I am so sorry.However, currently i'm working on a script where I'd add new thingies and features for snow, which includes the worst idea ever, but adding more meshes to (most or all) trees. Because SpeedTree's TOU simply does not allow ANY mesh-y tweaking done and reuploaded (Unless this is done inside of EA), I want to add the meshes through a script. Also because we somehow need to have a condition where we know that it's snowing and then adding the mesh.
Now the code currently isn't exactly done, it's in it's very testy and debugging state, so currently it will create meteors at every position of a tree and basically logging the position into notification in the worst way possible, but it does the job (So still need to finetune it ) And it's not winter-compatible yet (aka, that the mesh would show up and get destroyed if it isn't winter or is winter).
Code:
public static void OnWorldLoadFinished(object sender, EventArgs e) { // Load in all the alarms after 5 min of the world being loaded. AlarmManager.Global.AddAlarm(5f, TimeUnit.Minutes, new AlarmTimerCallback(LoadNotificationAfter_5_SimMinutes), "LoadLyraleiSnowModloader", AlarmType.DeleteOnReset, null); AlarmManager.Global.AddAlarm(0f, TimeUnit.Minutes, new AlarmTimerCallback(GetAllFrozenObjects), "LoadFrozenObjects", AlarmType.DeleteOnReset, null); } public static void LoadNotificationAfter_5_SimMinutes() { StyledNotification.Format format = new StyledNotification.Format("Snow Additions has loaded!", StyledNotification.NotificationStyle.kGameMessagePositive); StyledNotification.Show(format); } public static void GetAllFrozenObjects() { // Here we get an array of all the Flora being loaded into the world (So trees and bushes) Flora[] objects = Sims3.Gameplay.Queries.GetObjects<Flora>(); if(objects.Length == 0) { Exception exception = new Exception(); ShowException(exception); } else { foreach(Flora flora in Sims3.Gameplay.Queries.GetObjects<Flora>()) { // Get the object id of the tree/bush ObjectGuid objectId = flora.ObjectId; // Store the tree/bush position/transform into a var mTransform = flora.Transform; mPosition = flora.Position; mForwardVector = flora.ForwardVector; mDisplayPosition = flora.DisplayPosition; mPositionXZ = flora.PositionXZ; mPositionOnFloor = flora.PositionOnFloor; mBoundingBox = flora.Dimensions; // Convert them to strings for now to use in the debug log mTransformString = mTransform.ToString(); mPositionString = mPosition.ToString(); mForwardString = mForwardVector.ToString(); mDisplayPositionString = mDisplayPosition.ToString(); mPositionXZString = mPositionXZ.ToString(); mPositionOnFloorString = mPositionOnFloor.ToString(); mBoundingBoxString = mBoundingBox.ToString(); StyledNotification.Format objectReactionLog = new StyledNotification.Format(LogDebugInfo(), StyledNotification.NotificationStyle.kSystemMessage); StyledNotification.Show(objectReactionLog); GameObject meteor = GlobalFunctions.CreateObject("MeteorHuge", mPosition, 0, mForwardVector) as GameObject; } // end for loop } // end else } // end GetAllFrozenObjects public static string LogDebugInfo() { StringBuilder stringBuilder = new StringBuilder(); try { stringBuilder.AppendFormat(string.Format("\n Tree or bush position: {0}", mPositionString)); stringBuilder.AppendFormat(string.Format("\n Tree or bush transform: {0}", mTransformString)); stringBuilder.AppendFormat(string.Format("\n Tree or bush ForwardVector: {0}", mForwardString)); stringBuilder.AppendFormat(string.Format("\n Tree or bush Display Position: {0}", mDisplayPositionString)); stringBuilder.AppendFormat(string.Format("\n Tree or bush Position XZ: {0}", mPositionXZString)); stringBuilder.AppendFormat(string.Format("\n Tree or bush Position on Floor: {0}", mPositionOnFloorString)); stringBuilder.AppendFormat(string.Format("\n Tree or bush Bounding Box: {0}", mBoundingBoxString)); } catch { stringBuilder.AppendFormat(string.Format("\n Exception was thrown in LogDebugInfo(). Couldn't load everything properly ")); } return stringBuilder.ToString(); }
Now, I noticed that OnWorldLoadFinished() Seems to have a few lasting minutes before it would stop, because, of course, it's an event! Those are supposed to stop at some point. However, the time given for that event isn't long enough for my code to execute.
All the other events I've found don't seem to meet the needs, and I'm not sure if at "OnWorldLoadStartedEventHandler()" or "OnStartupAppEventHandler()" Would do the trick since it has to be done at a point that all the trees are instantiated.
Thoughts?
Advertisement
Space Pony
#2
22nd Sep 2019 at 4:11 PM
Posts: 433
Thanks: 792 in 6 Posts
Hmm well events dont have a livetime theyre more like delegates
My gut feeling says maybe theres an object limit in place, im off to do some testing
E: OPTIMIZE !!!
you already have the flora there loop through it and use
instead of
I know this was not your problem, i couldnt help it but to point that out
My gut feeling says maybe theres an object limit in place, im off to do some testing
E: OPTIMIZE !!!
Code:
// Here we get an array of all the Flora being loaded into the world (So trees and bushes) Flora[] objects = Sims3.Gameplay.Queries.GetObjects<Flora>();
you already have the flora there loop through it and use
Code:
foreach(Flora flora in objects ) { }
instead of
Code:
foreach(Flora flora in Sims3.Gameplay.Queries.GetObjects<Flora>()) { }
I know this was not your problem, i couldnt help it but to point that out
#3
22nd Sep 2019 at 4:34 PM
Posts: 3,860
Thanks: 8546 in 67 Posts
LOL I actually noticed that after I posted this Thanks for poiting it out though!
I actually did some debugging on having it not load an object but a notification. The Notification would show 140 trees and bushes reacting on it, but it seems indeed only shows a few meshes (so not for all 140 trees). I'll also check if there's a limit
I actually did some debugging on having it not load an object but a notification. The Notification would show 140 trees and bushes reacting on it, but it seems indeed only shows a few meshes (so not for all 140 trees). I'll also check if there's a limit
#4
22nd Sep 2019 at 5:38 PM
Posts: 3,860
Thanks: 8546 in 67 Posts
You might be right on the limits. I noticed that on every lot it adds 4 meteorites for only 1 type of each (So like if there's 5 sunflowers, 3 spruces, 4 high grass and 7 other trees it would place 4 meteorites on 1 of each kind, so you end up with 1 at a random sunflower, 1 at a random spruce and 1 at a random highgrass and 1 at a random tree).
#5
24th Sep 2019 at 10:20 AM
Posts: 3,860
Thanks: 8546 in 67 Posts
Battery and I discussed this a bit more on PM so, just wanted to say for anyone with this issue or looking for the cause, is batching. Basically what happens to this line:
Filters out copies (Or returns only one of each tree/bush kind). Here's the code EA uses to batches the array (thanks to battery ):
So, looking at the "Return new T[0]" (And then imagine T being ea's Flora class I used). It will always return the very first entry. Which if you know arrays you probably might have figured that out already
This exact thing is also filtered by lot. So world trees/bushes won't even be affected by this array or even the "GetObjects()" function. Which kind of sucks! But I feel like if you ever check out this tutorial: http://www.simlogical.com/ContentUp..._script_mod.pdf
That you should be aware of the following things:
Code:
Flora flora in Sims3.Gameplay.Queries.GetObjects<Flora>()
Filters out copies (Or returns only one of each tree/bush kind). Here's the code EA uses to batches the array (thanks to battery ):
Code:
public static T[] GetObjects<T>() where T : class { Array objects = Queries.GetObjects(typeof(T)); if (objects != null) { return objects as T[]; } return new T[0]; }
So, looking at the "Return new T[0]" (And then imagine T being ea's Flora class I used). It will always return the very first entry. Which if you know arrays you probably might have figured that out already
This exact thing is also filtered by lot. So world trees/bushes won't even be affected by this array or even the "GetObjects()" function. Which kind of sucks! But I feel like if you ever check out this tutorial: http://www.simlogical.com/ContentUp..._script_mod.pdf
That you should be aware of the following things:
- Two of the same items on a lot will only affect 1. In NonaMena's case, they are also applying it to an event listener so that by itself would trigger it on duplicates I believe. But sometimes the code logistics don't need you to have an "OnBought" listener. (Like my code)
- There's not an easy way around this.
- It's not the OnWorldLoadFinished()
#6
28th Sep 2019 at 1:14 PM
Posts: 3,860
Thanks: 8546 in 67 Posts
Hey @battery , Rereading the code, I actually realised something which is basically this line:
Basically, it's not returning T[0] (Aka the first entry) it's actually returning a Type. Which means, Of all types it can find, it creates an array, which means that the Typeof here is the issue.
Now I'm wondering if it's possible to return it as a Class specifically rather than a type. but I feel like that could be a workaround for this
Code:
Array objects = Queries.GetObjects(typeof(T));
Basically, it's not returning T[0] (Aka the first entry) it's actually returning a Type. Which means, Of all types it can find, it creates an array, which means that the Typeof here is the issue.
Now I'm wondering if it's possible to return it as a Class specifically rather than a type. but I feel like that could be a workaround for this
Space Pony
#7
28th Sep 2019 at 2:22 PM
Posts: 433
Thanks: 792 in 6 Posts
Hey @Lyralei,
the GetObjects Method takes in a Type as a parameter and returns an array filled with instances of this type. Unfortunately i have no insight into the actual Function since its hidden away in the Sims3Common.dll
Our problem really seems to be the batching we have mentioned.
Will actually return ALL Sittable Object instances and not one of each type like with our Trees. So these Objects are treated differently (e: and dont seem to be batched)... This is why your Candle Example you did link will work but our Tree stuff wont. I will try a few more things but at this point i have little hope that i can figure something out
the GetObjects Method takes in a Type as a parameter and returns an array filled with instances of this type. Unfortunately i have no insight into the actual Function since its hidden away in the Sims3Common.dll
Our problem really seems to be the batching we have mentioned.
Code:
ISittable[] HeyLookLyraleiHeresTheSuffASimCanSitOn = Queries.GetObjects(typeof(ISittable),Sim.ActiveActor.LotHome.LotId);
Will actually return ALL Sittable Object instances and not one of each type like with our Trees. So these Objects are treated differently (e: and dont seem to be batched)... This is why your Candle Example you did link will work but our Tree stuff wont. I will try a few more things but at this point i have little hope that i can figure something out
#8
28th Sep 2019 at 3:27 PM
Posts: 3,860
Thanks: 8546 in 67 Posts
not sure if i'm just screwing it up, but I was just curious as to what your code outputs if you were to log it in a notification or whatever. To me, this:
Is throwing numerous of compiling errors actually, mainly because it's not sure whether to use Sims3.gameplay.queries or sims3.SimIface queries. Also, if I do use the sims3.SimIface queries, this creates an infinite loading loop (Aka the world will never be loaded). If I do:
Then this funnily enough also returns exactly what the trees are doing, aka, returning Sims3.Gameplay.Interfaces.ISittable[] on all 3 chairs I placed on an empty world
Code:
Sittable[] HeyLookLyraleiHeresTheSuffASimCanSitOn = Queries.GetObjects(typeof(ISittable),Sim.ActiveActor.LotHome.LotId);
Is throwing numerous of compiling errors actually, mainly because it's not sure whether to use Sims3.gameplay.queries or sims3.SimIface queries. Also, if I do use the sims3.SimIface queries, this creates an infinite loading loop (Aka the world will never be loaded). If I do:
Code:
Sittable[] HeyLookLyraleiHeresTheSuffASimCanSitOn = Sims3.Gameplay.Queries.GetObjects<iSittable>;
Then this funnily enough also returns exactly what the trees are doing, aka, returning Sims3.Gameplay.Interfaces.ISittable[] on all 3 chairs I placed on an empty world
Space Pony
#9
28th Sep 2019 at 4:43 PM
Last edited by Battery : 28th Sep 2019 at 4:59 PM.
Posts: 433
Thanks: 792 in 6 Posts
Quote: Originally posted by Lyralei
Code:
Sittable[] HeyLookLyraleiHeresTheSuffASimCanSitOn = Sims3.Gameplay.Queries.GetObjects<iSittable>; Then this funnily enough also returns exactly what the trees are doing, aka, returning Sims3.Gameplay.Interfaces.ISittable[] on all 3 chairs I placed on an empty world |
Yes it does that but it doesnt for the trees so if you would have a total of 3 of the same trees you would only get one object back
This is the out put i get for that bit of code (After the game finished loading and an alarm was triggered
#10
29th Sep 2019 at 4:07 PM
Posts: 3,860
Thanks: 8546 in 67 Posts
I could be totally not understanding the instances, or my limited C# knowledge here so please bear with me :p
When one would actually do something like:
It would output something like:
Could that maybe indicate that maybe it has all those trees inside that array? I couldn't seem to apply the same trick on the Doors or ISittable to see what they'd return but I get the feeling it would be the same. Just a thought really!
But I will be honest, I'm this close to leave it as is. I did however look at how EA finds all the "Fire Objects". Which is pretty much done with this:
But I feel like if this would be applied to trees instead it would possibly not do much.
When one would actually do something like:
Code:
Array treebirch = Sims3.SimIFace.Queries.GetObjects(TreeBirch.GetType());
It would output something like:
Code:
Sims3.Gameplay.Objects.Mimics.TreePear[]
Could that maybe indicate that maybe it has all those trees inside that array? I couldn't seem to apply the same trick on the Doors or ISittable to see what they'd return but I get the feeling it would be the same. Just a thought really!
But I will be honest, I'm this close to leave it as is. I did however look at how EA finds all the "Fire Objects". Which is pretty much done with this:
Code:
public override IExtinguishable[] GetObjects(Lot lot) { return lot.GetObjects<Fire>(); }
But I feel like if this would be applied to trees instead it would possibly not do much.
#11
5th Oct 2019 at 2:16 PM
Posts: 3,860
Thanks: 8546 in 67 Posts
I was thinking, Upon some diving into code and such, I did notice there was a function called "CountSpeedTrees()" Coming straight from the engine dll (Sims3Common).
Now, thinking about the logic, would it be a good idea (Or even a stupid idea) to take the result of that count and see if that can be stored in a variable that can later be used for a foreach loop to apply a mesh?
Now, thinking about the logic, would it be a good idea (Or even a stupid idea) to take the result of that count and see if that can be stored in a variable that can later be used for a foreach loop to apply a mesh?
Who Posted
|