It seems to be accurate to a few 100ths. It also slowly adjusts itself. If it is running too slow, it speeds up, and vice versa.
enjoy
CODE
integer ch = 0; // ch == 0 means read from object description
integer repeat = 1;
float delay = .1;
float fudge = -0.1;
float wt1 = .9;
float wt2 = .1;
// send a message to all the others on the channel
sending()
{
vector color = <llFrand(1), llFrand(1), llFrand(1)>;
integer r = repeat;
float now = getTime();
float when = now + delay;
string msg = (string)color + "," + (string)when;
// if you want to be sure, send the message more than once.
llOwnerSay( "sending:" + msg );
while( r > 0 ) {
llShout( ch, msg );
--r;
}
llSleep( when - getTime() + fudge );
action( color, when );
}
// Do whatever the action is.
action( vector c, float when)
{
float d = when - getTime();
llSetColor( c, ALL_SIDES );
llOwnerSay("action: " + (string)d + "\t" + (string)fudge );
fudge = wt1*fudge + wt2*( d );
}
parse( string m )
{
list rec = llCSV2List( m );
//llOwnerSay( (string)rec );
vector color = (vector)llList2String( rec, 0 );
float when = llList2Float( rec, 1 );
float now = getTime();
//llOwnerSay( (string)color + " " + (string)when + " " + (string)now );
if ( when > now ) {
llSleep( when - now + fudge );
}
action( color, when );
}
float getTime()
{
// thanks to Chromal Brodsky
string sTime = llGetTimestamp();
integer iHour = (integer)llGetSubString( sTime, 11, 12 );
integer iMin = (integer)llGetSubString( sTime, 14, 15 );
float fSec = (float)llGetSubString( sTime, 17, 22 );
return (iHour*3600 + iMin*60 +fSec);
}
default
{
state_entry()
{
if( ch == 0)
ch = (integer) llGetObjectDesc();
llListen( ch, "", "", "" );
}
listen(integer c, string n, key k, string m)
{
parse(m);
}
touch_start(integer total_number)
{
//llSay(0, "Sending...");
sending();
}
}