Would this always-running script work?

Post » Thu Jun 21, 2012 1:06 am

I've been pretty confused as to how to make an always-checking script. Here's my theory script:

I'm setting the initial value of loop as 0.
Scriptname Looper Extends ObjectReferenceInt Property Loop AutoFloat Property Health AutoEvent OnLoad()While Loop == 0 ;Do crap while Loop is zero. Should always run.Health = Self.GetAV("Health") ;This should repeatedly get the actors health. Please tell me if not.		  If Self.GetAV("Health") < 5 ;Check if the players health is less than 5.				 Debug.Notification("Oh No! May Talos Save You!") ;Sample Message... But wouldn't it cause a loop?								 Return ;Go back to the start.		  EndIfEndWhileEndEvent
User avatar
TOYA toys
 
Posts: 3455
Joined: Sat Jan 13, 2007 4:22 am

Post » Wed Jun 20, 2012 2:33 pm

Why are you trying to create a loop? The game engine is event driven. Is there not an event that suits your needs?
User avatar
Jordan Fletcher
 
Posts: 3355
Joined: Tue Oct 16, 2007 5:27 am

Post » Wed Jun 20, 2012 7:42 pm

Why are you trying to create a loop? The game engine is event driven. Is there not an event that suits your needs?

Because many of the event's don't check every second. For example, you could apply this to a spell effect.

Normally, OnEffectStart() will only run when the spell starts.

Using this would theoretically run all the time, even during the duration of the spell:
Scriptname Looper Extends ActiveMagicEffectInt Property Loop AutoEvent OnEffectStart(Actor Target, Actor Caster)While Loop == 0 ;Do crap while Loop is zero. Should always run.	 Debug.SendAnimationEvent(Target, "GetAttention") ;Causes the actor to always do the anim.EndWhileEndEvent

This (theoretically) would be helpful because when you play an event/Idle, I would need to normally cast the spell again to get him to play the animation again.
User avatar
Mimi BC
 
Posts: 3282
Joined: Sat Oct 07, 2006 10:30 pm

Post » Wed Jun 20, 2012 10:21 pm

Papyrus/Skyrim is REALLY bad at tight loops, as I've discovered and re-discovered. A tightly looped script will behave unpredictably, will slow down other scripts and is generally something to be avoided.

At the VERY least, you need to put a utility.wait(0.01) in the loop. If you really, REALLY want to monitor the player's health that closely without severely impacting performance, use Self.RegisterForUpdate(0.2) and put the health-checking code in the OnUpdate event. That'll still check the player's health ~5 times per second without screwing up scripting performance.

Scriptname Looper Extends ObjectReferenceFloat HealthBool LowHealthWarningEnabled = TrueEvent OnLoad()  Self.RegisterForSingleUpdate(0.2) ; Register the script for a single update event in 0.2 secondsEndEventEvent OnUpdate()  Health = Self.GetAV("Health")  If Health < 5 && LowHealthWarning	Debug.Notification("Oh No! May Talos Save You!")	LowHealthWarningEnabled = False ; set this to keep the player from being notified repeatedly while his health is < 5  ElseIf Health >= 5	LowHealthWarningEnabled = True ; Player has regained health and so should be warned if it drops again.  EndIf  Self.RegisterForSingleUpdate(0.2) ; Reregister the script for another update in 0.2 secondsEndEvent

Note that I prefer to use RegisterForSingleUpdate and reregister it in the Update event because I believe the standard RegisterForUpdate chews up memory even after the script is disabled.
User avatar
C.L.U.T.C.H
 
Posts: 3385
Joined: Tue Aug 14, 2007 6:23 pm

Post » Wed Jun 20, 2012 10:10 pm

RegisterForUpdate() and OnUpdate().

RegisterForUpdate(1) will send an OnUpdate() event every second. RegisterForUpdate(10) will send an OnUpdate() event every ten seconds.
User avatar
Carolyne Bolt
 
Posts: 3401
Joined: Mon Jul 10, 2006 4:56 am

Post » Wed Jun 20, 2012 10:08 pm

Note that I prefer to use RegisterForSingleUpdate and reregister it in the Update event because I believe the standard RegisterForUpdate chews up memory even after the script is disabled.

You need to UnregisterForUpdate() before you end the script or it will keep the script running permanently.
User avatar
Alex Blacke
 
Posts: 3460
Joined: Sun Feb 18, 2007 10:46 pm

Post » Thu Jun 21, 2012 3:25 am

As MoopusMaximus stated, the idea is to run the script permanently, so unregisterforupdate is out of order here.

Registerforupdate shouldn't be used at all. Especially if the script is supposed to run for more than a few seconds. No matter what you do, there will be momments where your script won't regain the control for some time and registerforupdate will continue starting new onupdate events regardless previous ones not having time to end or even start. This will bloat your save exponentially.

Registerforsingleupdate with an additional registerforsingleupdate in the last line of the onupdate event, will call a new onupdate only when the previous one has been processed. In theory this could make the script update sometimes slower, but it will happen only in those times where a registerforupdate will be corrupting your file.

So. Don't use registerforupdate. Use registerforsingleupdate instead.
User avatar
..xX Vin Xx..
 
Posts: 3531
Joined: Sun Jun 18, 2006 6:33 pm

Post » Thu Jun 21, 2012 2:58 am

aWes0m3: I recall there being a thread around here somewhere that implied even with UnregisterForUpdate that the Update register did not always get cleared. Plus there are times when a script thread dies without firing the UnLoad event. Maybe that's been fixed, but I'm still paranoid about it :smile:

Edit: Ninja'd by amgepo!
User avatar
Jessica Colville
 
Posts: 3349
Joined: Wed Oct 18, 2006 6:53 pm


Return to V - Skyrim