| Scripting Discuss scripting and programming for SL and other platforms |
![]() |
| | LinkBack | Thread Tools | Display Modes |
| | #1 (permalink) |
| Senior Member ![]() ![]() ![]()
Praying for intelligent life
somewhere up in space, 'cause
there's bugger all down here
on Earth
Join Date: Jul 2011
Posts: 1,836
| Using llSensorRepeat as a second timer I'm finding myself using llSensorRepeat as an additional timer quite a lot recently. While I realise I'm being lazy in not using something like llGetTime and coding my timer calls and events accordingly, I'm also not distributing any of my stuff, which tends to remain in a constant private beta state. However, I would be interested to learn what parameters would make for the most efficient use of this hack. I'm currently using Code: llSensorRepeat ("", "", AGENT, 0.001, 0.0, time); |
| | |
| |
| | #2 (permalink) |
| The Purple ![]() ![]() ![]() ![]() ![]() ![]()
HEYOO!
Join Date: Dec 2007 Location: Somewhere purple, Germany
Posts: 7,773
My Mood: SL Join Date: 20. January 2007 Client: NaCl | AAAAAAAAAAAAAAAAAARRRRRRRGH
__________________ "Have you ever noticed that anybody driving slower than you is an idiot, and anyone going faster than you is a maniac?" - George Carlin |
| | |
| 3 Users Laughed: |
| 1 User Said Thanks: |
| 1 User Agreed: |
| | #3 (permalink) |
| Senior Member ![]() ![]() ![]()
Praying for intelligent life
somewhere up in space, 'cause
there's bugger all down here
on Earth
Join Date: Jul 2011
Posts: 1,836
| Maybe I should mention that I'm doing that only for things that don't run continuously and which use a repeat time of several seconds – like dialog timeouts, and I'm scrupulously removing the sensor immediately in the no_sensor event! |
| | |
| | #4 (permalink) | |
| Senior Member ![]() ![]() Join Date: Apr 2012
Posts: 105
My Mood: SL Join Date: March 2004 | Quote:
Code: llSensorRepeat ("", llGetKey(), AGENT, 0.001, 0.0, time); | |
| | |
| 1 User Said Thanks: |
| 4 Users Like This: |
| | #5 (permalink) |
| Banned ![]() ![]() ![]() Join Date: Mar 2011 Location: Pennsylvania
Posts: 1,213
SL Join Date: Jan 2007 | Linus Torvalds once said, "If it compiles, it is good; if it boots up, it is perfect." I wouldn't worry about performance so long as you get it to do what you want. Just get the functionality working and then go back and optimize things like this later. You already know how to do it right, so no need to sweat the details if you find this easier to work with while developing your ideas. Just please don't sell a million copies of something with a script like this in it. |
| | |
| | #6 (permalink) | ||
| That Bitch ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]()
Innocent as far as you know
Join Date: Nov 2011 Location: Online
Posts: 6,370
My Mood: SL Join Date: late 04... that account is deleted now | when I use this method I always use the the objects key, and the set the type filter for agent, as Strife demonstrated. That's a guaranteed "no match / not found" and the agent filter probably cuts down on search complexity on the back end. You play catch in the no_sensor event, but you may need an empty sensor event for safety (not sure of the status on that bug) I generally only use this when my timer is heavily scripted and under regular use, for other things of a transitory/asynchronous nature. to cut down overhead from multiplexing or continual flag checking in the actual timer event. ETA: and some people can scream all they want it actually works out cheap to the region if your timer is already bloated... I'm not sure that using it for dialog timers is a good idea though, since you often have to push those further out on successive dialog choices.
__________________ - These eyes can do more than see Quote:
Quote:
| ||
| | |
| 3 Users Agreed: |
| | #7 (permalink) | |
| The Purple ![]() ![]() ![]() ![]() ![]() ![]()
HEYOO!
Join Date: Dec 2007 Location: Somewhere purple, Germany
Posts: 7,773
My Mood: SL Join Date: 20. January 2007 Client: NaCl | Quote:
AAAAAAAAAAAAAAAAAAARRRRGHHH | |
| | |
| 1 User Laughed: |
| 1 User Hugged You: |
| 1 User Said Thanks: |
| | #8 (permalink) |
| Senior Member ![]() ![]() ![]()
Praying for intelligent life
somewhere up in space, 'cause
there's bugger all down here
on Earth
Join Date: Jul 2011
Posts: 1,836
| OK – so I heard your screams and howls of derisory laughter. (My thanks to those of you who offered words of comfort.) So I went to work and came up with this, a system that will allow an unlimited number (well ok, memory-limited number) of different timer events with their individual timer intervals within a single script. Obviously it's way too scripty and list-processy for the pretty simple stuff I've done which really only needs to store a couple of time floats and do a simple test in the timer () event, but I thought I'd put it up here for comment and criticism anyway. This script includes the core functions and variable as well as example usage. Code: //Compound timer
//These three functions enable you to set up multiple timer events, each with their own interval, simultaneously
//(In this example you can trigger a simple dialog by clicking and holding for one second)
//list of timer events
list timer_events;//strided 3: next event due time, event id, interval between events
//store the returned key to identify this particular event in the timer () event
//specify the interval between triggering of the timer () event
key SetTimerEvent (float interval)
{
//convert negative and zero intervals to immediate (use a seperate function to stop timer events)
if (interval <= 0.0) interval = 0.01;
//create a (hopefully) unique UUID for this event
key id = (key) llInsertString (llInsertString (llInsertString (llInsertString (llMD5String (llGetTimestamp (), 0), 8, "-"), 13, "-"), 18, "-"), 23, "-");
//add this event to the list and sort the list
timer_events = llListSort ([llGetTime () + interval, id, interval] + timer_events, 3, TRUE);
//calculate how long till the next event
interval = llList2Float (timer_events, 0) - llGetTime ();
//if we're already late for the next event do it immediately
if (interval <= 0.0) interval = 0.01;
//wait until the next event is due
llSetTimerEvent (interval);
return id;
}
//use a stored event key to specify it for removal
StopTimerEvent (key id)
{
//find this event in the list
integer index = llListFindList (timer_events, [id]);
//if it's there...
if (index > -1)
{
//remove this event from the list
timer_events = llDeleteSubList (timer_events, index - 1, index + 1);
//if there's no events left in the list stop the timer
if (llGetListLength (timer_events) == 0) llSetTimerEvent (0.0);
//if there are, and we've just removed the next scheduled event...
else if (index == 1)
{
//calculate how long till the next event
float interval = llList2Float (timer_events, 0) - llGetTime ();
//if we're already late for it do it immediately
if (interval <= 0.0) interval = 0.01;
//wait until it's due
llSetTimerEvent (interval);
}
}
}
//get the UUID of the current event in the timer () event to identify which event it is responding to
key GetTimerEventKey ()
{
//get the UUID for the current event
key id = llList2Key (timer_events, 1);
//get the timer interval for this event
float interval = llList2Float (timer_events, 2);
//replace the current event with it's next ocurrence and sort the list
timer_events = llListSort (llListReplaceList (timer_events, [llGetTime () + interval, id, interval], 0, 2), 3, TRUE);
//calculate how long till the next event
interval = llList2Float (timer_events, 0) - llGetTime ();
//if we're already late for the next event do it immediately
if (interval <= 0.0) interval = 0.01;
//wait until the next event is due
llSetTimerEvent (interval);
return id;
}
//UUIDs of example timer events
key regular_timer;
key touch_timer;
key long_touch_timer;
key dialog_timeout;
//flag for when a long click-and-hold is encountered
integer long_touch;
//listener for dialog response
integer listener;
default
{
state_entry ()
{
//set up a regular timer event (switchable on/off by dialog)
regular_timer = SetTimerEvent (10.0);
}
touch_start (integer count)
{
if (llDetectedKey (0) == llGetOwner ())//ignore curious bystanders
{
//set up a timer to see if this is a long click-and-hold
long_touch_timer = SetTimerEvent (1.0);
}
}
touch_end (integer count)
{
if (llDetectedKey (0) == llGetOwner ())//ignore curious bystanders
{
//if this was a long click-and-hold reset the flag and do nothing else
if (long_touch) long_touch = FALSE;
//otherwise this was just a normal click...
else
{
//stop waiting for a long click-and-hold
StopTimerEvent (long_touch_timer);
//precess the result of a normal click (in this case, trigger an event in 5s time)
touch_timer = SetTimerEvent (5.0);
}
}
}
timer ()
{
//get the UUID of the current event
key event_id = GetTimerEventKey ();
//process the different events according to their UUID...
if (event_id == regular_timer) llOwnerSay ("Regular 10s timer.");//the regular timer
else if (event_id == touch_timer)//triggered 5s after a normal click
{
//stop further occurences of this event
StopTimerEvent (touch_timer);
//process the event
llOwnerSay ("Touch triggered 5s timer.");
}
else if (event_id == long_touch_timer)//triggered 1s after a click that hasn't yet been released
{
//stop further occurences of this event
StopTimerEvent (long_touch_timer);
//set the flag so nothing happens in the touch_end () event
long_touch = TRUE;
//open a listener for the dialog
listener = llListen (-5678, "", llGetOwner (), "");
//initiate the dialog
llDialog (llGetOwner (), "\nRegular timer:", llList2List (["Stop", "Start"], regular_timer == NULL_KEY, regular_timer == NULL_KEY) + ["CANCEL"], -5678);
//create an event for a dialog timeout
dialog_timeout = SetTimerEvent (60.0);
}
else if (event_id == dialog_timeout)//triggered 60s after a dialog has been initated but not responded to
{
//stop further occurences of this event
StopTimerEvent (dialog_timeout);
//remove the listener
llListenRemove (listener);
//kill the original dialog with a timeout info message (this works great in V2/3 viewers, maybe not no great elsewhere)
llDialog (llGetOwner (), "\nDialog timeout", [], -999);
}
else
{
//this event hasn't been recognised so remove it from the list (you could try and do something about it, but here we'll just forget about it)
//(in this example this can happen after multiple normal clicks, each overriding the previously stored UUID for a normal click)
StopTimerEvent (event_id);
//unnecessary spam
llOwnerSay ("Unprocessed timer event.");
}
}
listen (integer channel, string name, key id, string message)
{
//we've had a response to the dialog so we won't want a dialog timeout
StopTimerEvent (dialog_timeout);
//remove the listener
llListenRemove (listener);
//process the dialog message...
if (message == "Start")
{
//start a regular timer
regular_timer = SetTimerEvent (10.0);
//unnecessary spam
llOwnerSay ("Starting regular timer.");
}
else if (message == "Stop")
{
//stop the regular timer
StopTimerEvent (regular_timer);
//specifically set NULL_KEY to simplify selecting which button to display in the dialog
regular_timer = NULL_KEY;
//unnecessary spam
llOwnerSay ("Stopping regular timer.");
}
//do nothing: either the dialog has been cancelled deliberately, or a spurious message has managed to sneak in
//unnecessary spam
else llOwnerSay (message + " – dialog cancelled.");
}
} Last edited by KT Kingsley; 07-25-2012 at 10:40 AM. |
| | |
| 1 User Laughed: |
| 1 User Hugged You: |
| | #9 (permalink) |
| Senior Member ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]()
post_count++;
Join Date: Sep 2007 Location: Austin, TX
Posts: 1,046
My Mood: SL Join Date: 11/01/2005
Business: The Wastelands Client: Official Newest | Juggle timestamps! integer time_stamp_one; integer time_stamp_two; timer() { integer unix_time = llGetUnixTime();}
__________________ Tin Man Rant - Blog Alright, I've been thinking. When life gives you lemons, don't make lemonade - make life take the lemons back! Get mad! I don't want your damn lemons, what am I supposed to do with these? Demand to see life's manager. Make life rue the day it thought it could give Cave Johnson lemons. Do you know who I am? I'm the man who's gonna burn your house down! With the lemons. I'm going to to get my engineers to invent a combustible lemon that burns your house down! -- Cave Johnson |
| | |
| 2 Users Agreed: |
| | #10 (permalink) |
| The Purple ![]() ![]() ![]() ![]() ![]() ![]()
HEYOO!
Join Date: Dec 2007 Location: Somewhere purple, Germany
Posts: 7,773
My Mood: SL Join Date: 20. January 2007 Client: NaCl | Don't take my screams too seriously ;P LSL often requires tons of hacks to be more efficient, so whatever works for you is fine, as long as it doesn't take up much resources. Even if it's abuse of...the..sensor..for....f....fff.. |
| | |
| 1 User Hugged You: |
| | #11 (permalink) |
| Senior Member ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]()
post_count++;
Join Date: Sep 2007 Location: Austin, TX
Posts: 1,046
My Mood: SL Join Date: 11/01/2005
Business: The Wastelands Client: Official Newest | |
| | |
| 2 Users Said Thanks : |
| 1 User Likes This: |
| | #12 (permalink) | |
| The Purple ![]() ![]() ![]() ![]() ![]() ![]()
HEYOO!
Join Date: Dec 2007 Location: Somewhere purple, Germany
Posts: 7,773
My Mood: SL Join Date: 20. January 2007 Client: NaCl | Quote:
Seems like there is at least some documentation..but yeah, I think there was no server release note about it ![]() iiiinteresting. | |
| | |
| 1 User Agreed: |
| | #13 (permalink) | |
| Senior Member ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]()
post_count++;
Join Date: Sep 2007 Location: Austin, TX
Posts: 1,046
My Mood: SL Join Date: 11/01/2005
Business: The Wastelands Client: Official Newest | Quote:
Another thing to note it that even though the documentation says version 3 UUID, it's actually version 5 Last edited by NeoBokrug Elytis; 07-25-2012 at 10:53 AM. Reason: I really need caffeine. | |
| | |
| | #16 (permalink) |
| That Bitch ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]()
Innocent as far as you know
Join Date: Nov 2011 Location: Online
Posts: 6,370
My Mood: SL Join Date: late 04... that account is deleted now | side note: generate key is nice if you want psuedo-random and non repeating (as in the case of the md5 hack), but if you want actually random, spit out random numbers, convert them to hex and drop in your dashes). the problem with timers is that there's multiple paradigms for them to work on... for instance, the continually delayed "push" used for most dialog and dataserver handling..... much simpler than running a faster timer with a timestamp that gets checked repeatedly, but it doesn't behave well when coupled with a simple frequency timer paradigm. multiple frequency timers can be multiplexed together with a single counter and check... push timers can't unless you speed up the timer (to keep it roughly accurate) and check against multiple timestamps... an lsl annoyance to be sure, but the lack of multiple independant timers kinda makes it necessary, and more painful than it should be. all we can really do is damage control. Last edited by Void; 07-25-2012 at 11:56 AM. |
| | |
| | #17 (permalink) |
| Senior Member ![]() ![]() Join Date: Apr 2012
Posts: 105
My Mood: SL Join Date: March 2004 | Thanks for the heads up NeoBokrug, I've updated the docs (which is stupid since I've requested they do a rollback...) It is true, it was never in the release notes. Drives me nuts when they do this and don't update the compiler in the client. *inspiration* I should read the tooltips from strings.xml! Last edited by Strife; 07-26-2012 at 12:59 AM. |
| | |
| 1 User Said Thanks: |
| | #19 (permalink) |
| That Bitch ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]()
Innocent as far as you know
Join Date: Nov 2011 Location: Online
Posts: 6,370
My Mood: SL Join Date: late 04... that account is deleted now | well yeah, I think that was assumed from the code =P @chalice: could be worse, people could use http as a timer =D |
| | |
| | #22 (permalink) |
| That Bitch ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]()
Innocent as far as you know
Join Date: Nov 2011 Location: Online
Posts: 6,370
My Mood: SL Join Date: late 04... that account is deleted now | I've actually done something close to that scary changed loop before =X ... granted I actually was changing something with it and it's ungodly fast PS don't use Frand, use a boolean switch, and ditch the (really bad) test =D *I'm kidding, don't do that shit |
| | |
| | #23 (permalink) | |
| Senior Member ![]() ![]() ![]()
Mayan Time Lord
Join Date: Apr 2008 Location: Cali
Posts: 2,102
My Mood: SL Join Date: 10/12/2006
Business: [H]arsh Styles
Client: Always changing, and too lazy to edit. | Quote:
Dialog timers are a good idea if you're putting your listen on a busy channel like, um, 1. But I sure hope nobody is doing that. | |
| | |
| | #25 (permalink) |
| Senior Member ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2010
Posts: 6,183
| I don't bother timing it out. My scripts just only have one listen open at a time. I don't time them out, I just use only one handle, which I llListenRemove before reusing it. I just close it on other events if it makes sense to. |
| | |
| 1 User Likes This: |
![]() |
| Thread Tools | |
| Display Modes | |
| |
| |