PJMail Posted September 25, 2021 Author Share Posted September 25, 2021 @DlinnyLag - you could be right, I will test some other conditional functions and see.@SKK - trust you to do a "thorough" job of testing, that's one s**t load of boxes!!! Any scripting 'gems' from that you can pass on? Link to comment Share on other sites More sharing options...
PJMail Posted September 25, 2021 Author Share Posted September 25, 2021 (edited) I tested IsChild() and IsDead() - both should not involve any real processing - but both were Not Latent + Delayed.By that I mean FPS locked and Blocking - Same as Is3Dloaded().Probably just lazy programming to have them Delayed... It's not like an Actor can change to a child between frames... Edited September 26, 2021 by PJMail Link to comment Share on other sites More sharing options...
SKKmods Posted September 26, 2021 Share Posted September 26, 2021 @SKK - trust you to do a "thorough" job of testing, that's one s**t load of boxes!!! Any scripting 'gems' from that you can pass on? Scripts attached to non persistent objects still run (while loops & such) even when they are unloaded. Non persistent objects with running scripts (while loops & such) are not removed from the game when unloaded even flusihing pcb/cellreset. Scripts that are idle but have a property to Object itself make it persistent. Scripts that are idle but refer to self as Self.Function do not prevent a non persistent object from being cleaned up. LinkedRefrences that involve non persistent objects can not be resolved when unloaded. All the sorta kinda stuff you would expect & other stuff I cant rememebr thats peppered through this forum over time. Link to comment Share on other sites More sharing options...
PJMail Posted September 26, 2021 Author Share Posted September 26, 2021 @SKK - Thanks. All as expected but good to have it confirmed.Just not sure what you mean by "Scripts that are idle but have a property to Object itself make it persistent."I know this happens if another object has a reference to a temporary object (it acts persistent while being referred to) but are you saying an object can 'self refer'? Like it has a property on it's script that resolves to itself? Link to comment Share on other sites More sharing options...
SKKmods Posted September 26, 2021 Share Posted September 26, 2021 Yes any script with a permanet property to an ObjectReference will make that target persistent. Which is why using Self is best for scripts refering to their parent object/actor/quest/whatever. One could declare a property as Auto but not Const Mandatory and then clear the property when the script is done to release the Object (itself). See the example script I posted on the recent [ Newbie Modder, Scripting Help for Settlement Mod ] thread. Link to comment Share on other sites More sharing options...
PJMail Posted September 27, 2021 Author Share Posted September 27, 2021 (edited) @SKK - I have used that for other objects (that I want to keep existent while I am) but not effectively 'self'. Thanks. Some last (?) cleanup questions:- under what conditions are ALL timers cancelled? Does 'unregisterforallevents()' do it?- Similarly does that also unregister remote events (such as OnPlayerLoadGame)? And is that all unnecessary on Actor death (ondeath, OnWorkshopObjectDestroyed, etc) - ie. the game automaticall does it? Edited September 27, 2021 by PJMail Link to comment Share on other sites More sharing options...
SKKmods Posted September 27, 2021 Share Posted September 27, 2021 I have not observed unregisterforallevents() cancelling timers. If cleaning up a script to shudown I always explicity cancel all unique timers that can be started, and set any LinkedRefs to null. Unregisterforallevents() should unregister native remote and custom events, but again my cleanups always explicity unregister all unique custom events that could be registered by the script just to be sure. Yes each unregistration could take a frame, but in this case accuracy is more important than performance. It would be a comlex test harness to validate custom events so I never found the time to explore that. Here is a standard cleanup script I attach to workshop constructible objects that is called when they are stored/destroyed Function Cleanup() If (bCleanupRunning == False) && (Self.IsBoundGameObjectAvailable() == TRUE) ;handle multiple calls bCleanupRunning = True ;if this is a Const script can set an ActorValue flag on the object Self.CancelTimer(iSummoningTimer) Self.UnregisterForAllEvents() Self.UnRegisterForCustomEvent(pWorkshopParentScript, "WorkshopPlayerOwnershipChanged") Self.SetLinkedRef(None, pWorkshopLinkCenter) Alias_SummoningSpeakerLocation.Clear() ;release me Alias_SummoningSpeakerActors.RemoveAll() ;release my bitches Self.Disable() Self.Delete() ; bCleanupRunning = False ; not unsetting this as who now cares, and could hold the script open blocking delete. EndIf EndFunction Some may say "hey you dont need to specify Self. as thats implicit", for maintainability I prefer my fully qualified explicit notation. Link to comment Share on other sites More sharing options...
PJMail Posted September 29, 2021 Author Share Posted September 29, 2021 I do exactly as you do... Shame though, was hoping I could dump a few 'canceltimer' etc statements to 'save a few frames'... Oh well. Link to comment Share on other sites More sharing options...
niston Posted September 30, 2021 Share Posted September 30, 2021 Something I do: Instead of using Const Properties to obtain references, I obtain them through GetFormFromFile and later explicitly discard them all during shutdown/cleanup. I do like to put the formIDs to load in properties sometimes tho, so I have an easy configuration block. IsBoundGameObjectAvailable() comes in handy as well to abort loops and other long running procedures. Especially those that might get stuck when references become invalid because a plugin was yanked from the load order or whatever. And as always, remember: Running loops are stored on the stack and thus in the save. As a consequence of this, they will continue running until the abort condition is met, even if their corresponding PEX file was removed entirely. Link to comment Share on other sites More sharing options...
PJMail Posted September 30, 2021 Author Share Posted September 30, 2021 I agree IsBoundGameObjectAvailable() is very useful for cleanup when someone removes your mod 'badly' (not the way you instructed because... noone reads instructions...). I have it on remote events (such as ongamestart) as they still fire after the pex is gone. As far as I have found, though, local events, and events attached to objects that have now gone don't seem to fire. I may just be lucky in my testing though. However I am not going to spread that call at intervals throughout my longer procedures on the off chance someone saves in the middle of them then deletes the mod. A very low likelyhood - and that practice will cause them grief in the end anyway... And I ALWAYS have a count limit on loops so they can never run forever, though very few scripts I have seen do that. Many times I have seen "While (condition) Endwhile" loops used to wait for a condition... Horrors... Link to comment Share on other sites More sharing options...
Recommended Posts