MultiTimer

From Second Life Wiki
Revision as of 16:00, 20 September 2015 by Ravenmists Resident (talk | contribs)
Jump to navigation Jump to search

Small library to simplify the use of multiple timers in a script.

/* *** ------------------------------------------- *** */
/* ***   Copyright (c) 2013 by Craftish Resident   *** */
/* ***    Attribution 3.0 Unported (CC BY 3.0)     *** */
/* *** http://creativecommons.org/licenses/by/3.0/ *** */
/* *** ------------------------------------------- *** */
float   c_check_interval=0.5;
integer s_running_timers=0;
list    s_timers_nexts=[];
list    s_timers_intervals=[];
startTimer(integer x_id,float x_interval){
    integer shift=1<<x_id;
    if(s_running_timers==0)llSetTimerEvent(c_check_interval);
    if(!(s_running_timers&shift)){
        while(llGetListLength(s_timers_nexts)<=x_id){s_timers_nexts+=0.0;s_timers_intervals+=60.0;}
        s_timers_nexts=llListReplaceList(s_timers_nexts,[llGetTime()+x_interval],x_id,x_id);
        s_timers_intervals=llListReplaceList(s_timers_intervals,[x_interval],x_id,x_id);
        s_running_timers=s_running_timers|shift;
    }
}
stopTimer(integer x){
    integer shift=1<<x;
    if(s_running_timers&shift)s_running_timers=s_running_timers&(~shift);
    if(s_running_timers==0)llSetTimerEvent(0);
}
quickTimer(integer x){
    s_timers_nexts=llListReplaceList(s_timers_nexts,[llGetTime()],x,x);
}
restartTimer(integer x){
    if(s_running_timers&(1<<x)){
        stopTimer(x);
        startTimer(x,llList2Float(s_timers_intervals,x));
    }
}
integer checkTimer(integer x_timer){
    if(s_running_timers&(1<<x_timer)){
        float now=llGetTime();
        float next=llList2Float(s_timers_nexts,x_timer);
        if(now>next){
            float interval=llList2Float(s_timers_intervals,x_timer);
            next=next+interval;
            if(now>next+interval)next=now+interval;
            s_timers_nexts=llListReplaceList(s_timers_nexts,[next],x_timer,x_timer);
            return 1;
        }
    }
    return 0;
}
/* *** ------------------------------------------- *** */

//    Timers can be set from 0 to 31

default
{
    state_entry()
    {
        startTimer(0, 10.0);	//Set timer 0 to happen every 10 seconds
        startTimer(1, 5.0);	//Set timer 1 to happen every 5 seconds
        quickTimer(1);		//Tell timer 1 to happen right away
    }
    timer()
    {
        if(checkTimer(0))	//Check if timer 0 is ready to go off
        {
            llOwnerSay("10!");
            stopTimer(0);	//Stop timer 0
        }
        if(checkTimer(1))	//Check if timer 1 is ready to go off
        {
            llOwnerSay("5!");
        }
    }
    touch_end(integer x)
    {
        restartTimer(1);	//Restart timer 1
    }
}

/*    Output:
5! (Because we told timer 1 to go off right away)
[pause for 5 seconds]
5!
[pause for 5 seconds]
10! (Only happens once because the timer is stopped here)
5!
[pause for 5 seconds]
5!
[pause for 5 seconds]
...
*/

Alternate simplified version of the same idea. Scripted by Ravenmists Resident

list timers=[];
integer rTimers=0;
float time;
integer index;
float tCheck=0.5;

startTimer(integer n, float l){
    index=llListFindList(timers,[n]);
    if(index==-1){
        timers+=[n]+[l];
    }
    if(rTimers==0){
        llSetTimerEvent(tCheck); 
    }
    rTimers++;
}

integer checkTimer(integer n){
    index=llListFindList(timers,[n]);
    if(index!=-1){
        float test=div(time,llList2Float(timers,index+1));
        if(test==0){
            return 1;
        }
    }
    return 0;
}

stopTimer(integer n){
    index=llListFindList(timers,[n]);
    timers=llListReplaceList(timers,[-1],index+1,index+1);
}

restartTimer(integer n, float l){
    index=llListFindList(timers,[n]);
    timers=llListReplaceList(timers,[l],index+1,index+1);
}

float div(float a, float b){
    return a-b*llFloor(a/b);
}

integer a=0;
default{
    touch_start(integer x){
        if(a){
            stopTimer(0);
        }else{
            startTimer(0,10.0);
        }
        a= !a;
        startTimer(1,5.0);
    }
    timer(){
        time+=tCheck;
        if(checkTimer(0)){
            llOwnerSay("Timer 0");
        }
        if(checkTimer(1)){
            llOwnerSay("Timer 1");
        }
    }
}