ItHadToComeToThis Posted January 1, 2020 Share Posted January 1, 2020 I needed to write myself a multi timer so thought I would post it here for you fine people. Chances are it can probably be improved, if so, post your improvements in the comments. float timerA=2.0; float timerB=3.3; float timerC=7.0; float decimalPlace(float d, integer p){ string s=(string)d; s=llDeleteSubString(s,llSubStringIndex(s,".")+p,-1); return ((float)s); } float div(float a, float b){ return a-b*llFloor(a/b); } integer checkTimer(float mTimer){ if(div(decimalPlace(llGetTime(),2),mTimer)==0.0){ return 1; } return 0; } default{ state_entry(){ llResetTime(); llSetTimerEvent(0.1); } timer(){ //Timer A if(checkTimer(timerA)){ llOwnerSay("TIMER A : "+(string)decimalPlace(llGetTime(),2)); } //Timer B if(checkTimer(timerB)){ llOwnerSay("TIMER B : "+(string)decimalPlace(llGetTime(),2)); } //Timer C if(checkTimer(timerC)){ llOwnerSay("TIMER C : "+(string)decimalPlace(llGetTime(),2)); } } } /* RETURNS [13:16] Object: TIMER A : 2.000000 [13:16] Object: TIMER B : 3.300000 [13:16] Object: TIMER A : 4.000000 [13:16] Object: TIMER A : 6.000000 [13:16] Object: TIMER B : 6.600000 [13:16] Object: TIMER C : 7.000000 [13:16] Object: TIMER A : 8.000000 [13:16] Object: TIMER A : 10.000000 [13:16] Object: TIMER A : 12.000000 [13:16] Object: TIMER B : 13.200000 [13:16] Object: TIMER A : 14.000000 [13:16] Object: TIMER C : 14.000000 [13:16] Object: TIMER A : 16.000000 [13:16] Object: TIMER A : 18.000000 [13:16] Object: TIMER A : 20.000000 [13:16] Object: TIMER C : 21.000000 [13:16] Object: TIMER A : 22.000000 */ Link to comment Share on other sites More sharing options...
Mollymews Posted January 1, 2020 Share Posted January 1, 2020 some thoughts casting float to string always results in 6 chars following the decimal point. For an efficiency gain we can remove the llSubStringIndex() function call and get the same result float decimalPlace(float d, integer p) { return (float)llDeleteSubString((string)d, p-6, -1); } checkTimer() evaluates to TRUE or FALSE so we can do an inline evaluation for a tiny gain: integer checkTimer(float mTimer) { return (div(decimalPlace(llGetTime(), 2), mTimer) == 0.0); } and a different way to do this. A multi-timer that uses a ticker float TICK_PERIOD = 0.1; // tick the timer every 0.1 seconds integer TimerA = 20; // fire timerA every 20 * TICK_PERIOD = 2.0 seconds integer TimerB = 33; // fire timerB every 33 * TICK_PERIOD = 3.3 seconds integer TimerC = 70; // fire timerC every 70 * TICK_PERIOD = 7.0 seconds integer ticker; // add 1 to ticker every TICK_PERIOD integer range; // prevent the ticker from overflowing default { state_entry() { llResetTime(); range = TimerA * TimerB * TimerC; llSetTimerEvent(TICK_PERIOD); } timer() { ticker = (++ticker) % range; if (!(ticker % TimerA)) // fire TimerA { llOwnerSay("TimerA: " + (string)llGetTime()); } if (!(ticker % TimerB)) // fire TimerB { llOwnerSay("TimerB: " + (string)llGetTime()); } if (!(ticker % TimerC)) // fire TimerC { llOwnerSay("TimerC: " + (string)llGetTime()); } } } 1 Link to comment Share on other sites More sharing options...
ItHadToComeToThis Posted January 1, 2020 Author Share Posted January 1, 2020 7 hours ago, Mollymews said: That’s an interesting way to do it and thanks for the comments, il make changes to my one. One thing I realised I never added a way to stop the timers on mine so thinking I may add that later. Debating whether to use lists or if I can use a bit wise switch to keep track of the timer numbers. Or maybe I am over thinking it Link to comment Share on other sites More sharing options...
Mollymews Posted January 2, 2020 Share Posted January 2, 2020 5 hours ago, ItHadToComeToThis said: One thing I realised I never added a way to stop the timers on mine so thinking I may add that later Debating whether to use lists or if I can use a bit wise switch to keep track of the timer numbers. Or maybe I am over thinking it some thoughts on these with floats then we have to guard against precision errors. Example this: div(decimalPlace(llGetTime(), 2), mTimer) == 0.0; llGetTime() cannot be exactly 9.9. It is 9.913491. Which after casting and trimming returns as 9.91 9.91 modulus 3.3 is 0.01 0.01 != 0.0 so the function returns FALSE when for the purposes of the timer it should return TRUE we can fix this by bounding the precision deviation to some range. Example: div(decimalPlace(llGetTime(), 2), mTimer) <= 0.05; // where 0.05 is the deviation we have chosen with managing the timers a way it can be done is to set the timer values to 0.0 when not used. Checking for this in checkTimer() which also prevents a division by zero error in the div() function. Example: integer checkTimer(float mTimer) { if (mTimer <= 0.0) return FALSE; return div(decimalPlace(llGetTime(), 2), mTimer) <= 0.05; } to start/stop the timer event then a way is to use the sum total of the individual timers. Example: llSetTimerEvent( 0.1 * (float)(TimerA + TimerB + TimerC > 0.0)); // when any of the timers are greater than 0.0 then // 0.1 * (float)TRUE = 0.1 // when they are all 0.0 then // 0.1 * (float)FALSE = 0.0 on using a list for the timers rather than named variables then this is the way I prefer also as with a list we can add/remove timers dynamically at runtime, which we often need to do when making multi-player and/or multi-level games Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now