Don't click here unless you want to be banned.

LSL Wiki : LibraryTimerEnhancer

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are crawl338.us.archive.org
This script allows you to more precisely control the code that executes in a timer event. Since a script can only have one timer at a time, scripters must use complex global variables to have, for example, code that executes after 3 seconds pass, and code that executes after 1 second passes using the same timer event "clock". This is an attempt to standardize that process.

When a script calls setTimeout, a new timeout is created, unless the identifier is already in use. If the identifier is already in use, then the function removes the old timeout associated with that identifier, and creates a new one. If the time passed to setTimeout is 0, then setTimeout removes the timeout associated with the identifier.

After the specified time has passed, the timeout function is called with the timeout's identifier. After timeout is called with the identifier, it will no longer be called with that identifier unless the timeout is recreated using setTimeout.

The timeouts can only be as accurate as the TIMER_INTERVAL specifies, a timeout of 2.4 will only trigger at exactly 2.4 seconds after setTimeout is called, if and only if 2.4 is a multiple of the TIMER_INTERVAL. If not, the timeout will be triggered as soon as the amount of time between timer events exceeds 2.4. For example, if TIMER_INTERVAL is 1, and setTimeout is asked to trigger timeout after 2.4 seconds, then the timeout will be triggered after 3 seconds. If TIMER_INTERVAL is 0.5, then timeout will be triggered after 2.5 seconds. Note that a smaller TIMER_INTERVAL creates more calls to the timer() event, which may contribute to lag.

float TIMER_INTERVAL = 1;

list timeoutData;
float timePassed;
setTimeout(string identifyer, float time) {
    if(timeoutData == [])
        llSetTimerEvent(TIMER_INTERVAL); // This helps reduce lag, thanks BW :-)
    integer identifyerIndex = llListFindList(timeoutData, [identifyer]);
    if (identifyerIndex != -1)
        timeoutData = llDeleteSubList(timeoutData, identifyerIndex - 1, identifyerIndex);
    if (time != 0) {
        timeoutData += time + timePassed;
        timeoutData += identifyer;
    }
    timeoutData = llListSort(timeoutData, 2, TRUE);
}

timeout(string identifyer) {
    // Stuff to do for each timeout goes here.
}

timerTick() {
    // Code that executes every timer event, 
    // which manages the timeouts.
    timePassed += TIMER_INTERVAL;
    integer i;
    integer numTimers = llGetListLength(timeoutData);
    for (i = 0; i < numTimers; i += 2) {
        float triggerTime = llList2Float(timeoutData, i);
        if (triggerTime <= timePassed) {
            // Timeout will be triggered, remove it from list.
            string identifyer = llList2String(timeoutData, i + 1);
            timeoutData = llDeleteSubList(timeoutData, i, i + 1);
            // Execute the timeout code.
            timeout(identifyer);
            if (timeoutData == [])
                llSetTimerEvent(0); // This helps reduce lag, thanks BW :-)
        } else {
            // Since the list is sorted, when we encounter a timeout
            // that shouldn't trigger yet, we can stop iterating over the list.
            return;
        }
    }
}

default {
    timer() {
        // This function allows timeouts to execute.
        timerTick();
    }
}


Example Usage:

float TIMER_INTERVAL = 1;

list timeoutData;
float timePassed;
setTimeout(string identifyer, float time) {
    if(timeoutData == [])
        llSetTimerEvent(TIMER_INTERVAL);
    integer identifyerIndex = llListFindList(timeoutData, [identifyer]);
    if (identifyerIndex != -1)
        timeoutData = llDeleteSubList(timeoutData, identifyerIndex - 1, identifyerIndex);
    if (time != 0) {
        timeoutData += time + timePassed;
        timeoutData += identifyer;
    }
    timeoutData = llListSort(timeoutData, 2, TRUE);
}

timeout(string identifyer) {
    if (identifyer == "touched") {
        llSay(0, "Three seconds have passed since someone last touched me!");
    } else if (identifyer == "30 second ping") {
        llSay(0, "ping");
        // Say ping again, after 30 seconds.
        setTimeout("30 second ping", 30);
    }
}

timerTick() {
    timePassed += TIMER_INTERVAL;
    integer i;
    integer numTimers = llGetListLength(timeoutData);
    for (i = 0; i < numTimers; i += 2) {
        float triggerTime = llList2Float(timeoutData, i);
        if (triggerTime <= timePassed) {
            string identifyer = llList2String(timeoutData, i + 1);
            timeoutData = llDeleteSubList(timeoutData, i, i + 1);
            timeout(identifyer);
            if (timeoutData == [])
                llSetTimerEvent(0);
        } else {
            return;
        }
    }
}

default {
    state_entry() {
        setTimeout("30 second ping", 30);
    }
    
    touch_start(integer touchers) {
        // The "touched" timeout will execute after 3 seconds.
        setTimeout("touched", 3.0);
    }
    
    timer() {
        timerTick();
    }
}

Creative Commons License
This work is licensed under a Creative Commons Public Domain License.
There is one comment on this page. [Display comments/form]