|
Rachel Corleone
Registered User
Join date: 9 Oct 2006
Posts: 21
|
11-04-2007 05:18
I put this script in a prim which I then attach to the HUD. I touch it to start, then detach it while the loop is still running. When I rez it again, the loop starts up where it left off. But I want the script to reset when it is re-rezed. I thought putting the reset command in the on_rez event would do so, but it doesn't. In fact, on_rez isn't called at all when the loop was left running. Any ideas how to get it to reset under these conditions? (Besides editing the script and pressing the Reset button!) Rachel default { state_entry() { llWhisper(0, "Touch me to start"  ; } on_rez( integer start_param ) { llWhisper( 0, "rezed" ); llResetScript(); } touch_start(integer total_number) { integer i; for( i = 0; i < 10000; i++ ) { llWhisper( 0, (string)i ); } } }
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
11-04-2007 07:20
The problem with loops is that cannot receive any events... including the on_rez event.  To get out of this you can use a timer. integer i; default { state_entry() { llWhisper(0, "Touch me to start"  ; } on_rez( integer start_param ) { llWhisper( 0, "rezed" ); llResetScript(); } touch_start(integer total_number) { llSetTimerEvent(0.1); } timer() { llWhisper( 0, (string)i ); i++; if (i > 10000) llSetTimerEvent(0); } } ...loops realy shouldn't be used at all except to facilitate a specific calculation.
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
11-04-2007 22:20
10k counted whispers? OMG WHY? pale is right about about the on_rez not firing while you are in the loop, I think it gets queued and fires when you exit the touch event. small things 1) the counter 'i' will need to be declared as a global to use in a timer loop, as there is no way to declare a static variable in lsl 2) 0.1 seconds is a little fast for a timer, and for complex code won't fire nearly that often as your code will take longer than that to complete
you CAN make a fast timer loop that's throttled to your calculation time by changing if (i ==10000){ llSetTimer (0.0); }
to
if (i < 10000){ llSetTimerEvent( 0.1 ); }else{ llSetTimerEvent( 0.0 ); }
_____________________
| | . "Cat-Like Typing Detected" | . This post may contain errors in logic, spelling, and | . grammar known to the SL populace to cause confusion | | - Please Use PHP tags when posting scripts/code, Thanks. | - Can't See PHP or URL Tags Correctly? Check Out This Link... | - 
|
|
Rachel Corleone
Registered User
Join date: 9 Oct 2006
Posts: 21
|
Nested loops using timer()
11-05-2007 09:30
Here's how I'd do a nested loop, using Pale Spectre's suggestion:
integer x; integer y; integer count;
SomethingUseful() { llWhisper( 0, "X = " + (string)x + ", Y = " + (string)y ); count++; }
default { state_entry() { x = 0; state OuterLoop; } }
state OuterLoop { state_entry() { if( x == 5 ) { state LoopEnded; } y = 0; state InnerLoop; } }
state InnerLoop { state_entry() { llSetTimerEvent( 0.1 ); } timer() { if( y == 5 ) { llSetTimerEvent( 0.0 ); x++; state OuterLoop; } SomethingUseful(); y++; } }
state LoopEnded { state_entry() { llWhisper( 0, "End of loop, " + (string)count + " iterations" ); } }
To Void Singer: I wanted to see what happened if i de-rezed the prim when the loop was running, so I set the limit to 10k to give me lots of time to "take" the object.
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
11-05-2007 10:56
I actually think your solution is really clever, and it may even be more efficient than what I'm going to counter it with... I just think your code looks heavy maintenance (aka scary  ), so here we go with just the one state: // Globals integer x; integer y = 6; //Just showing the timer Event Handler timer() { if (y < 6) { SomethingUsefulY(); y++; } else { if (x < 6) { SomethingUsefulX(); x++; y = 0; } else llSetTimerEvent(0.0); } } Which should give: x = 0 y = 0, 1, 2, 3, 4, 5 x = 1 y = 0, 1, 2, 3, 4, 5 x = 2 y = 0, 1, 2, 3, 4, 5 x = 3 y = 0, 1, 2, 3, 4, 5 x = 4 y = 0, 1, 2, 3, 4, 5 x = 5 y = 0, 1, 2, 3, 4, 5
|
|
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
|
11-05-2007 12:00
Using Rachel's form, I would increment x inside the outer loop state code, just to make it clearer. That is, x is handled in the outer loop, y is handled in the inner loop. Something_useful() can use both variables, of course. But I'd probably use code more like Pale's. I also might use something like this, if readability is preferable to efficiency:
// advance indices and return TRUE if we're still working advance() { if (y < MAX_Y) { y++; return TRUE; } y = 0; if (x < MAX_X) { x++; return TRUE; } x = 0; return FALSE; } ...
timer() { Something_useful(); if (! advance()) { llSetTimer(0.0); state S_normal; // only if you have a "normal" state when not looping return; } }
Whether you put the Something_useful() call before or after Pale, when you post code, please include the indentation? Then we can see it by hitting the "quote" button below your post. I hate trying to read unindented code! Rachel, good for you for thinking of an interesting test case. As you can see, you want to avoid big loops in event-driven code. (And virtually all LSL scripts are event-driven code.)
|