Precision Timer
This is a chunk of code to show you two things.
1) llSetTimerEvent's precision is ridiculously low.
2) You can easily improve the precision by setting the timer a bit short and then waiting until your target time.
How do you use this script?
1) If you cut and paste this code into a script and put it into a box, it will send periodic messages displaying how far off llSetTimerEvent is from where it should be, in seconds.
2) If you change the first line to "integer useprectimer = 1;" it will send periodic messages displaying how close a precision timer can get.
3) If you read the timer event at the bottom, and precTimer() function at the top, they demonstrate the precision timer.
//--------------------------
// precision timer
//--------------------------
integer useprectimer = 0; // 0 for settimerevent, 1 for precision timer
float timetotest = 0.2; // how fast should the timer run?
// these two functions set timers with and without precision, and mark the desired time target
vector timeTarget;
precTimer( float secdiff )
{
timeTarget = vecTime();
timeTarget.z += secdiff;
llSetTimerEvent(secdiff - 0.05);
}
nonprecTimer( float secdiff )
{
timeTarget = vecTime();
timeTarget.z += secdiff;
llSetTimerEvent(secdiff);
}
// run a report of how well the timer is doing
runReport()
{
float min;
float max;
float avg;
float total;
float cur;
integer i;
integer len;
llSetTimerEvent(0.0); // try to clear the event queue up a bit, altho reset should do it
if( useprectimer == 1 ) {
llOwnerSay("Precision timer stats:");
} else {
llOwnerSay("llSetTimerEvent stats:");
}
len = llGetListLength(lDiffs);
total = 0.0;
min = 1.0;
max = 0.0;
for( i = 0; i < len; i++ ) {
cur = llList2Float(lDiffs, i);
total += cur;
if( cur < min ) {
min = cur;
}
if( cur > max ) {
max = cur;
}
}
avg = total/(float)len;
llOwnerSay("Total drift: " + (string)total + ", timers run: " + (string)len);
llOwnerSay("Avg drift: " + (string)avg);
llOwnerSay("Min drift: " + (string)min);
llOwnerSay("Max drift: " + (string)max);
llOwnerSay("Starting another run.");
llResetScript();
}
//--------------------------
// time utility functions
//--------------------------
vector vecTime()
{
vector tsp;
list tsv;
tsv = llParseString2List( llGetTimestamp(), ["T", ":", "Z"], [] );
tsp.x = llList2Integer(tsv, 1) - 8;
if( tsp.x < 0 ) {
tsp.x += 24;
}
tsp.y = llList2Integer(tsv, 2);
tsp.z = llList2Float(tsv, 3);
return tsp;
}
vector fixTime( vector inTime )
{
vector oTime = inTime;
while( oTime.z >= 60.0 ) {
oTime.z -= 60.0;
oTime.y++;
}
while( oTime.y >= 60.0 ) {
oTime.y -= 60.0;
oTime.z++;
}
return oTime;
}
float timeDiffNow( vector vTarget )
{
vector vTime = vecTime();
return (vTarget.x - vTime.x)*3600.0 + (vTarget.y - vTime.y) * 60.0 + (vTarget.z - vTime.z);
}
// included for reference:
float timeDiff( vector vMore, vector vLess )
{
float hours = vMore.x - vLess.x;
float minutes = vMore.y - vLess.y;
float seconds = vMore.z - vLess.z;
float tics = hours * 3600.0 + minutes * 60.0 + seconds;
// llOwnerSay("Diff between " + (string)vMore + " and " + (string)vLess );
// llOwnerSay("Diff returned approx. " + (string)( (integer)tics ) + " seconds.");
return tics;
}
//--------------------------
// PrecTimer script: report the drift in llSetTimerEvent, and show an easy way to fix it:
//--------------------------
list lDiffs; // used to store statistics
default
{
state_entry()
{
lDiffs = [];
if( useprectimer == 1 ) {
precTimer(timetotest);
} else {
nonprecTimer(timetotest);
}
}
timer()
{
float timeleft = timeDiffNow(timeTarget); // ETA to target time
if( useprectimer == 1 ) {
//Begin very simple precision countdown:
llResetTime();
while( (timeleft -= llGetAndResetTime()) > 0.01 );
//Reset the target of the precision timer:
precTimer(timetotest);
} else {
//Reset the target of the nonprecision timer:
timeTarget.z += timetotest;
}
lDiffs = (lDiffs=[]) + lDiffs + [llFabs(timeleft)];
if( llGetListLength(lDiffs) > 100 ) {
runReport();
}
}
touch_start(integer nd)
{
runReport();
}
}
Example output:
[15:57] Object: Precision timer stats:
[15:57] Object: Total drift: 0.110259, timers run: 101
[15:57] Object: Avg drift: 0.001092
[15:57] Object: Min drift: 0.000000
[15:57] Object: Max drift: 0.080150
[15:59] Object: llSetTimerEvent stats:
[15:59] Object: Total drift: 2.131889, timers run: 101
[15:59] Object: Avg drift: 0.021108
[15:59] Object: Min drift: 0.000084
[15:59] Object: Max drift: 0.101887
That's right... which do you want, a drift of 1/50th of a second, or of 1/1000th of a second? Yes. Use a precision timer.
ScriptLibrary