Guest Messenjah Posted June 1, 2011 Share Posted June 1, 2011 So things are running smoothly with my strip club mod but I would like to create a different lighting setup. However, I need to set them up with timers so I need a better understanding of how timer scripts work. I'm still having a lot of difficulty grasping it and I want to understand it for myself if at all possible so that I can use it in future projects as timers will become very useful for me. Does anyone know of a guide (other than GECK wiki) or a tutorial to help explain how to set these timers up? A couple of snippets of code I am looking at are: Sample 1 (GECK Wiki): float timer begin gamemode if timer < 5 set timer to timer + GetSecondsPassed else ;5 seconds have passed, do something special set timer to 0 endif end Sample 2 (MJSkull): if PurpleEmitter == 0 && BlueEmitter == 0 && WhiteEmitter == 0 if Timer > 0 set Timer to Timer - getsecondspassed else Purplelight.enable 0 set PurpleEmitter to 2 set Timer to 2 endif Why did the author in example 1 use a + sign and the author in example 2 use a minus sign? Is this an honest mistake? In example 1, why does it say Timer < 5 (Timer less than 5) seconds yet the code seems to claim that it says that if 5 seconds have passed, do something special? I'm not sure why it would be a less than 5 seconds rather than a greater than 5 seconds sign? In other words, why would it say, if the timer is greater than 5 seconds, do something special? Instead it seems to say, if you are less than five seconds, do something special? Does a timer float just set up a timer that automatically keeps turning over every few seconds as designated by the author? In other words, just it just keep resetting itself over and over when the designated time runs out or does it disable itself after running? I want to set up a series of three lights that turn on and off in sequence using a timer. Should be pretty easy but I'm not sure how to do it myself. MJSkull set up a lighting timer but I never did get it to work properly due to my lack of knowledge in scripting and the fact that I actually want to understand how the script works before I implement it. :) Link to comment Share on other sites More sharing options...
Skevitj Posted June 1, 2011 Share Posted June 1, 2011 (edited) They're both equivalent. GetSecondsPassed returns a float which contains the time since the script was last called, ie, if a script is being run 3 times a second, GetSecondsPassed would return 0.33333333... every time the script was run. What the first script is doing is simply counting up from 0, resetting the counter and doing the result events when a particular time is reached (5s). The second script sets the time value initially (2s) and then counts down, triggering the activation events when the counter reaches 0, before resetting the timer. Basically, they're identical, except one counts up, one counts down. Since variables are automatically initialized to 0, using the timer which counts up is probably the better option (since the count down timer needs to be initialized), but the difference between the two is trivial. The idea as far as I understand is that you want 3 lights which will alternate 1->2->3->1->2... with a constant and controllable delay between each light?scn LightsScript short StateVar ;State: 0=Off, 1=Light 1, 2=Light 2, 3=Light 3, State 0 is not implemented in this script short OldState ;Just a check to avoid trying to enable/disable lights every frame float TimerVar ; Current timer value begin gamemode ;****Detemine and set state**** set TimerVar to TimerVar+GetSecondsPassed if (TimerVar<2)&&(StateVar!=1) set StateVar to 1 elseif (TimerVar>=2)&&(TimerVar<4)&&(StateVar!=2) set StateVar to 2 elseif (TimerVar>=4)&&(TimerVar<6)&&(StateVar!=3) set StateVar to 3 elseif TimerVar>=6 set TimerVar to 0 set StateVar to 1 endif ;****State Set**** ;****Update Lights**** if StateVar==OldState return endif if StateVar==1 Light1.Enable Light3.Disable elseif StateVar==2 Light2.Enable Light1.Disable elseif StateVar==3 Light3.Enable Light2.Disable endif set OldState to StateVar ;****Lights Updated**** endIn this example, I used a count-up timer, so state 1 is from time=0 to time=2s, state 2 from time=2s to time=4s and state 3 from time=4s to time=6s (which is immediately reset to 0 upon reaching 6s starting the sequence again at state 1). You can easily adjust when each stage is triggered by adjusting the value in the "if TimeVar<X" tests, with X being time since Light 1 turned on. EDIT: Fixed the state error reported below and neatened it up a little. Edited June 3, 2011 by Skevitj Link to comment Share on other sites More sharing options...
drakeelvin Posted June 2, 2011 Share Posted June 2, 2011 Here is a simple tip if you want events to follow a steady, accurate cycle according to the game clock. Don't simply reset your timer to 0: instead, do something like the following. scn MyTimerScript int iDoOnce float fTimer Begin GameMode set fTimer to fTimer + GetSecondsPassed ; Use this section to trigger the first event immediately. if iDoOnce == 0 set iDoOnce to 1 set fTimer to 120.0 ;;; Override and ignore the first GetSecondsPassed endif ; Main body for a timed event that will keep a regular clock schedule and not "drift" if fTimer >= 120.0 set fTimer to fTimer - 120.0 ;;; dont just set to 0, save any leftover seconds ; do my timed event stuff endif End I would even go so far as to say that if in the above example you want the first event to trigger after 120.0, not immediately, then in the section "if iDoOnce == 0" it is a good idea to explicity set fTimer to 0.0. This ensures your clock starts ticking the moment the script is first run. When I tested without this, I believe the very first time a script is ever run, GetSecondsPassed may return the time since the beginning of the game. Thus I simply discarded the first result, but on 2nd and subsequent invocations of the script, GetSecondsPassed returns a value with the expected mean of approximately 5 seconds +/- variance. I did not find any definite statement about what GetSecondsPassed returns the very first time, but my observations led me to suspect it was the time since the start of the game. Maybe someone else can clarify this. Link to comment Share on other sites More sharing options...
Guest Messenjah Posted June 2, 2011 Share Posted June 2, 2011 Skevitj: I plugged that script into my mod and it works.... sorta. The first light is fine and the second two appear to flicker really fast like they are updating or constantly checking and enabling themselves over and over again..... I've tried to figure out what is going on but I am a bit stumped. If you could help me with figuring out what is wrong, I'd appreciate it. drakeelvin: I think I kind-of get what you are saying but I'm a bit confused. What is the DoOnce part of the script and how does it work? I'm suspecting it tells the game to only perform something once? But I'm not sure how to set it up. So, you set the 120 seconds up to delay the script, correct? So if I set it at 0 it will remove that delay and the script will run immediately Also, note that for this lighting script, is a sequence of lights that are intended to loop over and over again like lights in a dance club. It is for a dancer stage. :) Also, why is that if I set certain scripts to run OnActivate, they won't activate if I set up a trigger to activate it? Am I missing something in my scripts somewhere to make this happen? Link to comment Share on other sites More sharing options...
Skevitj Posted June 2, 2011 Share Posted June 2, 2011 (edited) I'm pretty sure I know what's wrong with it, and it's most probably due to me writing it while being sleep deprived. For the last two elseif tests in the set state block, you need to add a "&&TimerVar>=2" and "&&TimerVar>=4" (first for the 2nd test, and 2nd for the last test). The logic I used in determining the states is flawed, meaning as soon as it's in the correct state, it jumps into the next state incorrectly then corrects itself, over and over again. Won't happen for the State 3 -> State 1 transition though, hence why light 1 works. if TimerVar<2&&StateVar!=1 set StateVar to 1 elseif TimerVar>=2&&StateVar!=2&&TimerVar<4 set StateVar to 2 elseif TimerVar>=4&&StateVar!=3&&TimerVar<6 ... That's what it should be drakeelvin's example is just a more precise timer. When resetting the timer, mine ignores any overflow, ie, If it is to be reset at 6.5s that 0.5s would be "lost" instead of being subtracted from the next delay as it should be. All it means is his is the superior option when you want a timer which don't drift, ie, if controlling a clock's animation. However for simply controlling a lighting sequence it's pretty much overkill. The Doonce block just ensures that the trigger actions are carried out the first time the script is run, instead of waiting for the first delay to elapse, good for doing variable initialization etc, if you need it, but not overly important when managing lights. As for Activate, are you using the "RunOnActivateBlockFlag=1" RunOnActivateBlockFlag: 0 or unspecified The object will perform its default activation, bypassing any OnActivate Block in its script. RunOnActivateBlockFlag 1 The OnActivate block of the object will be run instead of the default activation. (Note, you must specify an ActionRef in this case) Taken from the wiki page Edited June 2, 2011 by Skevitj Link to comment Share on other sites More sharing options...
drakeelvin Posted June 3, 2011 Share Posted June 3, 2011 (edited) scn MyTimerScript int iDoOnce float fTimer Begin GameMode set fTimer to fTimer + GetSecondsPassed ; Use this section to trigger the first event immediately. if iDoOnce == 0 set iDoOnce to 1 set fTimer to 120.0 ;;; Override and ignore the first GetSecondsPassed endif ; Main body for a timed event that will keep a regular clock schedule and not "drift" if fTimer >= 120.0 set fTimer to fTimer - 120.0 ;;; dont just set to 0, save any leftover seconds ; TIMED EVENT GOES HERE endif End What is the DoOnce part of the script and how does it work? I'm suspecting it tells the game to only perform something once? Exactly. The first time any script is run, all variables are initialized to 0 by the script engine. A code walkthrough reveals that the first time the script runs, "if iDoOnce == 0" will be true and the conditional block will run. Inside the conditional block I use "set iDoOnce to 1" to ensure that code never gets run again. So, you set the 120 seconds up to delay the script, correct? So if I set it at 0 it will remove that delay and the script will run immediately. It's the exact reverse of what you said. As Skevitj mentioned there are two different styles used to count timers and my style is to set the timer counter (fTimer) to 0.0 and increment it. ( There is nothing inherently good or bad about either style of tracking timers, its purely a personal preference. It is a good idea to become familiar with both styles if you want to study different scripts, because you will run across both methods.) When fTimer reaches 120.0 I trigger my timed event. If I set fTimer to 0.0 the first time the script runs, my timed event won't first occur until 120.0 has elapsed. If I set fTimer to 120.0 the first time the script runs, my timed event will first occur immediately. The seeming reverse logic of these numbers is a bit confusing, but if you do a code walkthrough it will become clear. I may have confused you about my reference to setting fTimer to 0.0 in the iDoOnce conditional. The most important reason I would always initialize fTimer is to discard the first result returned by GetSecondsPassed. With some types of scripts you cannot know for certain what value it will return the first time it gets run. With a quest or object script you could be hours into a game before it gets run the first time. So rather than worry about such things I always just discard the first result from GetSecondsPassed and initialze fTimer to my own starting value. Edited June 3, 2011 by drakeelvin Link to comment Share on other sites More sharing options...
Guest Messenjah Posted June 4, 2011 Share Posted June 4, 2011 Cool! Lights seem to be working great after a bit of work. I need to figure something out. I need to set the script up as an activator script used on it's own activator and then have a trigger, activate the activator.... if that makes sense? IE: A light switch uses this script and a trigger box activates the light switch. The reason for this is that is that I have two different sets of stage lights. One stage light script will disable the timed lights and activate a set of plain white spotlights when it the OnTriggerEnter is activated. However, if the OnTriggerLeave is activated, the spotlights will turn off and the timed lights will turn on. This is so that when Hadrian does his comedy act, the disco lights will not interfere with his show but a set of normal stage spotlights will shine on him instead. However, when he is off-stage, I plan to have pole dancers perform and the disco lights will play. :) What I need specifically then, is a way to set the switch to activate when referenced by the trigger's OnTriggerEnter and deactivate when it is referenced by the trigger's OnTriggerExit. Link to comment Share on other sites More sharing options...
Skevitj Posted June 4, 2011 Share Posted June 4, 2011 (edited) EDIT: I just re-read your post and realized I completely missed half of it... Don't place the script on an activator, what you're trying to do is pretty much the main purpose of quest scripts, attaching it to a quest will allow switching of the lights via any source very easily (and allow easy additions to the quest to control other aspects of the mod, ie Inventory restocking, changing decorations/NPCs regularly and many more possible future additions). I'm assuming this script is attached to a quest? That would be the most sensible IMO, and would allow you to switch the lights very easily. A few slight modifications would allow you to implement State 0 -> Turn off timer lights -> turn on spot lights, and allow you to switch between them from an external source. They way I'm thinking is to use TimerVar, so that the Trigger enter block just needs to set it to be <0 to switch the script to state 0 and activate the spot lights, and the the trigger leave would just reset it to 0 or any >=0 number. This would require it being a quest script though so the variable is available outside the script. (Think global variables). That's probably not overly clear, but I've got it mapped out in my head, it just depends on exactly what you have the lights script attached to (activator/quest) and what/how the switch it to be triggered. Edited June 4, 2011 by Skevitj Link to comment Share on other sites More sharing options...
stevie70 Posted June 4, 2011 Share Posted June 4, 2011 Here is a simple tip if you want events to follow a steady, accurate cycle according to the game clock. Don't simply reset your timer to 0: instead, do something like the following. [...]sweet & elegant, like that. Link to comment Share on other sites More sharing options...
Recommended Posts