Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

question about timers

Jeremy Bender
anachronistic iconoclast
Join date: 12 Aug 2006
Posts: 99
11-02-2006 15:06
I haven't been able to find any info on this so don't jump all over me if it's too obvious, cause I *did* look, okay?

I am trying to use a timer to make a door open in a three stages and then close again in three stages. I am using an integer to store the state of the door as it goes through the three open stages and the three closing stages etc., but as soon as I add in any kind of "if else" logic, it fails completely. (the logic loop is necessary to test for if the door is open or closed and what did the owner say etc.)

The question is can a timer not be used inside a loop? Cause that's how it seems to me right now.

I have tried setting the timer function in the default state and surrounding my whole if-else structure with the timer() event and it fails.

I have tried setting both the timer function and the event within the if-else structure and it fails.

The only time I can get the timer to work at all is when it is sitting all by itself sort of speak. Do timers hate logic loops?

I am prepared to believe it's just my crappy coding, but if I could get some information on when the timer can and can't be used (the wiki is way less than helpful of course), then I would know with some certainty that it is my fault and to keep on looking for whatever comma or semi-colon is out of place.

Thanks for any help anyone can offer.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
11-02-2006 15:26
Events in LSL do not interrupt each other and LSL scripts are single threaded, the event stack is first in first out. Events can only exist in a state, at no other level may they exist; nor can they be called like a function.

Take a look at:
http://lslwiki.com/lslwiki/wakka.php?wakka=timer
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
11-02-2006 15:28
Not exactly sure what you mean about timers in side a loop.
The llSetTimerEvent(n) call will trigger a timer event every n seconds.
Inside the event you can pretty much do what you like.

Post your code and we can have a look at it.

But a quick question, why do you need a timer at all?
If all you want is the door to change position from a to b to c with slight delays use llSleep
Jopsy Pendragon
Perpetual Outsider
Join date: 15 Jan 2004
Posts: 1,906
11-02-2006 15:38
It's been a while since I experimented with this, I may be remembering it incorrectly... but does the following code resemble yours?

CODE

default {
state_entry() { // Will timer events interrupt code blocks?
integer i;

// do something in 2 seconds...every 2 seconds.
llSetTimerEvent(2.0);

for ( i=0; i<100; i++ ) {
llSleep(15.0);
// do something every 15 seconds 100 times.
}

llSetTimerEvent(0.0); // turn off the timer.
llOwnerSay("I give up.");
}

timer() {
llOwnerSay( "this code probably won't ever be executed." );
}
}



As far as I can tell, if code is being processed it won't be interrupted to handle a timer event... it waits until the current block completes and then checks.

Even something like: llParticleSystem( [ something] ); llSleep(15); llParticleSystem( [ another pattern ] ); seems to have trouble.

When designing scripts now I try to make sure that they spend as little time inside a block as possible.. instead of while/for, I tend to use timer() and a counter, for example. :)

Does that help any? :)
_____________________
* The Particle Laboratory * - One of SecondLife's Oldest Learning Resources.
Free particle, control and targetting scripts. Numerous in-depth visual demonstrations, and multiple sandbox areas.
-
Stop by and try out Jopsy's new "Porgan 1800" an advanced steampunk styled 'particle organ' and the new particle texture store!
Jeremy Bender
anachronistic iconoclast
Join date: 12 Aug 2006
Posts: 99
11-02-2006 18:17
From: Jopsy Pendragon
It's been a while since I experimented with this, I may be remembering it incorrectly... but does the following code resemble yours? ...
Well if I posted the code I am using I would be in danger of destroying what little credibility I have. ;)

After a long carefull study and translation of Strife's very efficient comment, I think that what I was doing was putting events inside of events.

What I was describing as my "if-else" structure was really a way of keeping track of the doors status as well as testing the owner's requests ("open,"close","status", etc.). So I was basically trying to wrap a listen event in a timer event (or sometimes put several timers inside of a listen). If I am reading you guys right they have to be eternally seperate and you can't call anything from insided anything else?

The good news, is that getting that one simple fact straight in my head makes the whole job of learning scripting that much easier. Declare the functions at the top, and then make a big stack of events. Good to know.
From: Jopsy Pendragon
... When designing scripts now I try to make sure that they spend as little time inside a block as possible.. instead of while/for, I tend to use timer() and a counter, for example. :)

Does that help any? :)
Yes! :)

Your post clarifies Strife's and also mentions llSleep (as does Newgates), which I was not aware of. Thanks to both of you for that as it allows me to eliminate the timer altogether becasue it wouldn't work any other way it seems.

Now if I could only figure out why the rotations seem to just pick a random axis half the time...
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
11-03-2006 00:21
From: Jopsy Pendragon
It's been a while since I experimented with this, I may be remembering it incorrectly... but does the following code resemble yours?

CODE

default {
state_entry() { // Will timer events interrupt code blocks?
integer i;

// do something in 2 seconds...every 2 seconds.
llSetTimerEvent(2.0);

for ( i=0; i<100; i++ ) {
llSleep(15.0);
// do something every 15 seconds 100 times.
}

llSetTimerEvent(0.0); // turn off the timer.
llOwnerSay("I give up.");
}

timer() {
llOwnerSay( "this code probably won't ever be executed." );
}
}




sorta

CODE
integer ctl = 24; // cycles to live (seconds .. give or take) 
integer ctv; // current cycle count

float timer_del = 2.0;
// timer and mutiple of ctl (in default its 12 timers @ 2 seconds ea .. ctl = 24)

set_timer(float time){llSetTimerEvent(time);}


default
{
state_entry(){set_timer(timer_del);}

timer()
{
if (ctv != (ctl/2) )
{
++ctv;
llOwnerSay((string)ctv); //DEBUG
}

else
{
set_timer(0.0);
llOwnerSay((string)llGetTime() + " end"); //DEBUG
}
}
}
Jopsy Pendragon
Perpetual Outsider
Join date: 15 Jan 2004
Posts: 1,906
11-03-2006 01:38
hmm... for a 3 stage door open/close thing... I might set up something like:

CODE


rotation orig_rot;
vector orig_pos;

default { // waiting for activation.
state_entry() { // remember where we started...
orig_rot = llGetRot();
orig_pos = llGetPos();
state closed_waiting;
}
}

state closed_waiting {
touch_start(integer n) {
// set rot/pos to 1/3rd open
llSleep(0.5);
// set rot/pos to 2/3rds open
llSleep(0.5);
// set rot/pos to completely open.
state open_waiting;
}
on_rez(integer n) { llResetScript(); }
}

state open_waiting {
touch_start(integer n) {
// set rot/pos 1/3rd of the way closed
llSleep(0.5);
// set rot/pos2 to 2/3rds of the way closed
llSleep(0.5);
// set back to orig_rot and orig_pos
state open_waiting;
}
on_rez(integer n) { llResetScript(); }
}
// standard warning... this is untested code written on the fly.
_____________________
* The Particle Laboratory * - One of SecondLife's Oldest Learning Resources.
Free particle, control and targetting scripts. Numerous in-depth visual demonstrations, and multiple sandbox areas.
-
Stop by and try out Jopsy's new "Porgan 1800" an advanced steampunk styled 'particle organ' and the new particle texture store!
Jeremy Bender
anachronistic iconoclast
Join date: 12 Aug 2006
Posts: 99
11-03-2006 13:33
From: Jopsy Pendragon
hmm... for a 3 stage door open/close thing... I might set up something like....
I know very little about using more than one state, so I used something like this (which now works except for the actual rotations are wrong)...

Main activation script
CODE

string _status = "deactivated";

default
{
state_entry()
{
llListen(0, "", llGetOwner(), "");
llSay(0,"Cometary Car is ready ...");
}

listen(integer channel, string name, key id, string message)
{
if (message == "activate"){
llMessageLinked(LINK_ALL_OTHERS, 0, "activate", llGetOwner());
llSay(0, "car is activated");
_status = "active";
}
else if (message == "deactivate")
{
llMessageLinked(LINK_ALL_OTHERS, 0, "deactivate", llGetOwner());
llSay(0, "car is deactivated");
_status = "deactivated";
}
else if (message == "status")
{
llSay(0, _status);
}
else
llSay(0,"commands are 'activate', 'deactivate', and 'status'");

}

}

righthand door script
CODE

integer _DoorOpen = FALSE;
integer _ListenHandle;

default
{
state_entry()
{
_ListenHandle = llListen(0, "", llGetOwner(), "");
}

link_message(integer sender_num, integer num, string str, key id)
{
if (str == "activate"){
llListenControl(_ListenHandle, TRUE);
llPreloadSound("1_sound");
llPreloadSound("2_sound");
}
else if (str == "deactivate"){
llListenControl(_ListenHandle, FALSE);
}
}

listen(integer channel, string name, key id, string message)
{
if (message == "open"){
if (_DoorOpen){
llSay(0, "the door is already open");
}
else{
llSetPrimitiveParams([PRIM_SIZE, <5.2, 10, 10>]);
llPlaySound("1_sound", 1.0);
llSleep(1);
llSetPrimitiveParams([PRIM_ROTATION, <-0.13795, 0.69352, 0.13795, 0.69352>]);
llPlaySound("2_sound", 1.0);
_DoorOpen = TRUE;
}
}
else if (message == "close"){
if (_DoorOpen){
llSetPrimitiveParams([PRIM_ROTATION, <0.00000, 0.70711, 0.00000, 0.70711>]);
llPlaySound("2_sound", 1.0);
_DoorOpen = FALSE;
llSleep(1);
llPlaySound("1_sound", 1.0);
llSetPrimitiveParams([PRIM_SIZE, <5.0, 9.8, 9.8>]);
_DoorOpen = FALSE;
}
else
llSay(0, "the door is already closed");
}
}
}

I originaly was using llGetRot and so on to do the rotations, but that seemed to just rotate arbitrarily around the wrong axis about 50% of the time so I switched to quaternions since they seemed not to but now they do the same thing.

The llSleep really solves my original problem though. :)
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
11-03-2006 13:34
From: Jeremy Bender
After a long carefull study and translation of Strife's very efficient comment, I think that what I was doing was putting events inside of events.

...

Your post clarifies Strife's and also mentions llSleep (as does Newgates), which I was not aware of. Thanks to both of you for that as it allows me to eliminate the timer altogether becasue it wouldn't work any other way it seems.

Now if I could only figure out why the rotations seem to just pick a random axis half the time...


Efficient isn't how many people would describe it; you have been very kind in your comments. I suspected that you were trying to have events in events.

You may want to try reversing the order to which you combine your rotations, it sounds like you have them backwards (a * b vs. b * a); Consider using llSetLocalRot & llGetLocalRot as they will work nicely when an object is linked and unlinked.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey