Over my head with a reset Timer
|
|
Tyrehl Byk
Registered User
Join date: 4 Dec 2008
Posts: 24
|
04-19-2009 06:26
I've successfully edited a Particle Laboratory Script to randomly change the PSYS_SCR_BURST_RATE adding float val = llFrand(1); before the particle settings. Unfortunately, I'm so mystified by scripting syntax that I've been unable to introduce a timer event to tell the script to regenerate this random value every "x" number of seconds. I think it's a combination of timer() and llSetTimerEvent but I have burned myself out fooling with these and am now simply pleading for someone to show me how to do this. (I could simply sit behind a tree and constantly push the reset button on the script once per second but I don't really want to be the Wizzard of Oz.) PLEASE someone help a clueless noob! and thanks in advance! Here is the script as it stands right now. \ //** The original 'free' version of this script came from THE PARTICLE LABORATORY. **//
string CONTROLLER_ID = "A"; // See comments at end regarding CONTROLLERS. integer AUTO_START = TRUE; // Optionally FALSE only if using CONTROLLERS.
list particle_parameters=[]; // stores your custom particle effect, defined below. list target_parameters=[]; // remembers targets found using TARGET TEMPLATE scripts.
default { state_entry()
{ float val = llFrand(1); // random variation of any value - change as required. particle_parameters = [ // start of particle settings PSYS_PART_START_SCALE, <0.09, .09, FALSE>, PSYS_PART_END_SCALE, <.05, .05, FALSE>, PSYS_PART_START_COLOR, <1,1,.5>, PSYS_PART_END_COLOR, <1,1,0>, PSYS_PART_START_ALPHA, 1.0, PSYS_PART_END_ALPHA, (float) 0.5, // Production Parameters: PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_RATE,(float) val, PSYS_PART_MAX_AGE, (float) 4.0, PSYS_SRC_MAX_AGE,(float) 0.0, // Placement Parameters: PSYS_SRC_PATTERN, (integer)8, // 1=DROP, 2=EXPLODE, 4=ANGLE, 8=ANGLE_CONE, // Placement Parameters (for any non-DROP pattern): PSYS_SRC_BURST_SPEED_MIN, (float)0.0, PSYS_SRC_BURST_SPEED_MAX, (float)0.0, PSYS_SRC_BURST_RADIUS, 0.5, // Placement Parameters (only for ANGLE & CONE patterns): PSYS_SRC_ANGLE_BEGIN, (float) 0.50*PI, PSYS_SRC_ANGLE_END, (float) PI, // After-Effect & Influence Parameters: PSYS_SRC_ACCEL, <0.0,0.0, 1.1 >, PSYS_PART_FLAGS, (integer)( 0 // Texture Options: | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_EMISSIVE_MASK ) //end of particle settings ]; if ( AUTO_START ) llParticleSystem( particle_parameters ); } link_message( integer sibling, integer num, string mesg, key target_key ) { if ( mesg != CONTROLLER_ID ) { // this message isn't for me. Bail out. return; } else if ( num == 0 ) { // Message says to turn particles OFF: llParticleSystem( [ ] ); } else if ( num == 1 ) { // Message says to turn particles ON: llParticleSystem( particle_parameters + target_parameters ); } else if ( num == 2 ) { // Turn on, and remember and use the key sent us as a target: target_parameters = [ PSYS_SRC_TARGET_KEY, target_key ]; llParticleSystem( particle_parameters + target_parameters ); } else { // bad instruction number // do nothing. } } }
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
04-19-2009 06:58
Setting the timer is easy but you need to consider what needs to happen each time the timer is triggered. In this case its all that stuff in state_entry... which isn't very convenient. So, task 1 is to get all that code in state_entry into its own function so that it can be executed by other triggers, for example, a timer.  Then, as you say, you just need a timer() event handler, and llSetTimerEvent to activate and deactivate the timer. string CONTROLLER_ID = "A"; // See comments at end regarding CONTROLLERS. integer AUTO_START = TRUE; // Optionally FALSE only if using CONTROLLERS.
list particle_parameters=[]; // stores your custom particle effect, defined below. list target_parameters=[]; // remembers targets found using TARGET TEMPLATE scripts. float delay = 1.0; //timer interval
SetParams() { float val = llFrand(1); // random variation of any value - change as required.
particle_parameters = [ // start of particle settings PSYS_PART_START_SCALE, <0.09, .09, FALSE>, PSYS_PART_END_SCALE, <.05, .05, FALSE>, PSYS_PART_START_COLOR, <1,1,.5>, PSYS_PART_END_COLOR, <1,1,0>, PSYS_PART_START_ALPHA, 1.0, PSYS_PART_END_ALPHA, (float) 0.5, // Production Parameters: PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_RATE,(float) val, PSYS_PART_MAX_AGE, (float) 4.0, PSYS_SRC_MAX_AGE,(float) 0.0, // Placement Parameters: PSYS_SRC_PATTERN, (integer)8, // 1=DROP, 2=EXPLODE, 4=ANGLE, 8=ANGLE_CONE, // Placement Parameters (for any non-DROP pattern): PSYS_SRC_BURST_SPEED_MIN, (float)0.0, PSYS_SRC_BURST_SPEED_MAX, (float)0.0, PSYS_SRC_BURST_RADIUS, 0.5, // Placement Parameters (only for ANGLE & CONE patterns): PSYS_SRC_ANGLE_BEGIN, (float) 0.50*PI, PSYS_SRC_ANGLE_END, (float) PI, // After-Effect & Influence Parameters: PSYS_SRC_ACCEL, <0.0,0.0, 1.1 >, PSYS_PART_FLAGS, (integer)( 0 // Texture Options: | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_EMISSIVE_MASK ) //end of particle settings ]; }
default { state_entry() { SetParams(); if (AUTO_START) { llParticleSystem(particle_parameters); llSetTimerEvent(delay); } }
link_message( integer sibling, integer num, string mesg, key target_key ) { if (mesg != CONTROLLER_ID) { // this message isn't for me. Bail out. return; } else if (num == 0) { // Message says to turn particles OFF: llSetTimerEvent(0.0); llParticleSystem([ ]); } else if (num == 1) { // Message says to turn particles ON: llParticleSystem(particle_parameters + target_parameters); llSetTimerEvent(delay); } else if (num == 2) { // Turn on, and remember and use the key sent us as a target: target_parameters = [ PSYS_SRC_TARGET_KEY, target_key ]; llParticleSystem(particle_parameters + target_parameters); } else { // bad instruction number // do nothing. } }
timer() { SetParams(); llParticleSystem(particle_parameters); } }
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
04-19-2009 07:18
As the comments at the head of the script hint, there are separate controller scripts available at the Particle Laboratory that are meant to control this and other particle-generating scripts in a variety of ways. If you visit the site and look in the sandbox area, you should find them. THAT's the part that you need to modify when you need different ways to control the effects.
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask....  Look for my work in XStreetSL at 
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
04-19-2009 07:48
nevermind
_____________________
| | . "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... | - 
|
|
Tyrehl Byk
Registered User
Join date: 4 Dec 2008
Posts: 24
|
04-19-2009 09:57
From: Pale Spectre Setting the timer is easy but you need to consider what needs to happen each time the timer is triggered. In this case its all that stuff in state_entry... which isn't very convenient. So, task 1 is to get all that code in state_entry into its own function so that it can be executed by other triggers, for example, a timer.  Then, as you say, you just need a timer() event handler, and llSetTimerEvent to activate and deactivate the timer. Thanks Pale, that was pretty helpful. I sensed that I had to do something like this but every time I tried I got errors. I've really stripped out all the non-essential stuff and have something that I think reflects what you suggested. I can manually change the numbers, but now I can't seem to randomize the PSYS_SRC-BURST_RATE like I could in the previous example. Every place I try to put llFrand, just keeps returning syntax errors. Obviously a timer event in the script as it exists right now would be meaningless since I can't randomize the burst rate yet. I think a lot my problems stem from the fact that I don't yet have a solid understanding of the concepts of events and states and how they relate to each other in the context of a script. Here's the simplified script as it exists now after a lot of sweat and errors, but I've lost the random val I had before and can't get it back again. // // Variable Fire Sparks // By Tyrehl Byk //
list variable_sparks = [
PSYS_PART_FLAGS, 259, // PSYS_PART_EMISSIVE_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE, PSYS_PART_START_SCALE, <0.09, .09, FALSE>, PSYS_PART_END_SCALE, <.05, .05, FALSE>, PSYS_PART_START_COLOR, <1,1,.5>, PSYS_PART_END_COLOR, <1,1,0>, PSYS_PART_START_ALPHA, 1.0, PSYS_PART_END_ALPHA, 0.5, // Production Parameters PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_RATE, 0.01, PSYS_PART_MAX_AGE, 4.0, PSYS_SRC_MAX_AGE, 0.0, // Placement Parameters PSYS_SRC_BURST_SPEED_MIN, 0.0, PSYS_SRC_BURST_SPEED_MAX, 0.0, PSYS_SRC_BURST_RADIUS, 1.5, PSYS_SRC_ANGLE_BEGIN, PI_BY_TWO, PSYS_SRC_ANGLE_END, PI, PSYS_SRC_ACCEL, <0.0, 0.0, 1.1>, // After-Effect & Influence Parameters PSYS_SRC_ACCEL, <0.0,0.0, 1.1 >, PSYS_SRC_OMEGA, <0.0, 0.0, 0> ];
default { state_entry() { llParticleSystem(variable_sparks); } }
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
04-19-2009 11:50
Your original script was working fine... all I did was shift the state_entry code to the function SerParams(), and put in some code to trigger SetParams() from a timer.
Your original code has these two lines:
float val = llFrand(1); // random variation of any value - change as required. PSYS_SRC_BURST_RATE,(float) val,
Now you just have:
PSYS_SRC_BURST_RATE, 0.01,
Also, in your later code the whole assignment for: 'list variable_sparks =', is a global variable declaration. It needs to be put into a user defined function. User defined functions must come after global variable declaration and before the default{} state. So...
list variable_sparks;
MyFunction() { float val = llFrand(1); variable_sparks = etc. : }
default { state_entry() { MyFunction(); llParticleSystem(variable_sparks); } }
|
|
Tyrehl Byk
Registered User
Join date: 4 Dec 2008
Posts: 24
|
04-19-2009 21:54
From: Pale Spectre Your original script was working fine... all I did was shift the state_entry code to the function SerParams(), and put in some code to trigger SetParams() from a timer.
Your original code has these two lines:
float val = llFrand(1); // random variation of any value - change as required. PSYS_SRC_BURST_RATE,(float) val,
Now you just have:
PSYS_SRC_BURST_RATE, 0.01,
Thanks for the followup. Unfortunately I was pretty confused by the edits you made to my original code (as well as much of the original code itself) and that’s why I completely revised it down to just the essentials. A lot of stuff in there was really unnecessary to my needs and getting in the way of my understanding. Yup, I’m aware of the differences of those lines you called out because those two lines in the original were the edits I made to the original script. In the second version I was unable to restore the variable functionality so I posted a clean, functioning script so that I could learn how to revise the syntax to bring the variable functionality back again. Now after looking at your example I am back to the point I was when I began this topic, with a little better understanding of the “why” behind it, thanks to your comments about global variable declarations and user defined functions though the relationships between them are still somewhat fuzzy. I appreciate that you didn’t just simply write out the solution to my problem. In that case I would have learned nothing. Although now have a different form of the script I started with that I can again reset manually, unfortunately I still don’t have the experience or understanding as to how to reset it with the timer functions. I’ve seen it done in other scripts but my attempts to apply those examples in this context are sort of like using the words without understanding the concepts. I could be off by a single character or something much more massive and the feedback from the script editor is so limited that there is no way to tell. One thing I’ve noticed from my very limited experience with SL scripting is that while there seems to be a great deal of fragmented information on the web about the individual parts that make up SL scripting, I have yet to locate any sort of general primer that discusses the concepts that make a script function and how they relate to each other. As someone with no programming experience, but a reasonable amount of intelligence, I can burn hours fooling around with reasoned guess work and get lucky, or I can ask in a place like this for a solution, but neither one of these options really puts me on a footing that allows me to build a solid foundation of understanding on which to build good scripting practices. From where I sit right now, In the second version of the script I’m guessing I have to do something similar to the default state that you did in your original revision with llSetTimerEvent and Timer() but I’m just guessing. Everything I’ve tried so far on the new version in that regard keeps returning syntax errors. Does this ever stop feeling like voodoo?
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
04-19-2009 22:27
Think of it this way...... A timer event is a clock. As soon as it is called, any tasks listed inside the clock are performed. The llSetTimerEvent function tells the timer event how often to activate. So, if you want particles to fire every ten seconds, you have to write llSetTimerEvent(10.0) someplace outside the timer event and then you need to put a command to spew particles in the timer event itself. Your user-defined function is intended to do the heavy lifting of creating particles. It simply needs to know when to do it. If you want the timer event to occur at random times up to, say, 15 seconds, then instead of putting a specific floating point number in llSetTimerEvent, you need to put in a random number generator: llFrand(15.0). All the pieces are there. You just need to get your head around what an event is, and what starts an event. It's not really voodoo. If it starts to feel like voodoo, back off for a while and look for the big ideas instead of focusing on the details. 
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask....  Look for my work in XStreetSL at 
|
|
Lazink Maeterlinck
Registered User
Join date: 8 Nov 2005
Posts: 332
|
04-19-2009 22:32
If your looking for an actual printed book for scripting in Second Life, there is only one book I know of that is totally dedicated to it. It's called Scripting Your World, it's one of the official second life guides. You might look into that, it teaches you the basics, and has you try a bit of everything, with enough information to help you delve deeper.
Also realize you've picked one of the hardest things to understand when starting out, particles.. they are evil, mean, and FULL of different things.
|
|
Tyrehl Byk
Registered User
Join date: 4 Dec 2008
Posts: 24
|
04-20-2009 06:42
Thanks, Lazink, for the lead on the book. From: Rolig Loon Think of it this way...... A timer event is a clock. As soon as it is called, any tasks listed inside the clock are performed. The llSetTimerEvent function tells the timer event how often to activate. So, if you want particles to fire every ten seconds, you have to write llSetTimerEvent(10.0) someplace outside the timer event and then you need to put a command to spew particles in the timer event itself. Wow Roig, that statement tuned up some things in my head. Thanks! It also probably highlighted the most difficult concept in scripting that I struggle with. Inside and outside. Something can be inside the timer event which also makes it inside the default state. Something can be outside the timer event but still inside the default state. Something can be outside the default state, but invoked from inside the default state. (here, my user defined function) Something can be EITHER outside both the default state and the user defined function. (lots of stuff I've seen in various scripts like string, integer, float) OR inside and outside a user defined function, or the default state. (huh?) Without any codified rules in front of me and with so many variables, it is a wonder I ever get anything working right. (yeah, like that's never happened to anyone else before either!) I studied your original revision and tried to use that example plus the analogy you made in your last post and keep coming up with the organization of the default state as follows. (Of course it informs me of a syntax error in the timer function, but I haven't a clue as to why. If I leave everything out from timer() to the end, I get no errors. (and of course, no timer!) {[I think I've left something open, or closed something twice,] or maybe I should be in the bathroom instead of the kitchen} ROFL
default { state_entry() { MyFunction(); llParticleSystem(variable_sparks); llSetTimerEvent(1.0); } }
timer() { MyFunction(); llParticleSystem(variable_sparks); } }
|
|
Tyrehl Byk
Registered User
Join date: 4 Dec 2008
Posts: 24
|
04-20-2009 07:01
I have a very strange relationship with time. Leave it to me to spend hours dicking around with something, finally give up and ask for help and then stumble on the solution minutes after asking for help. Why was the script editor telling me that the problem was with the timer? This default state works! default { state_entry() { llSetTimerEvent(1.0); }
timer() { MyFunction(); llParticleSystem(variable_sparks); } }
WTF?
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
04-20-2009 08:13
Excellent! Now all that's missing is your user-defined function itself. You have the call to it in the timer event, where it belongs, but you don't have the function itself in the script yet. Here's the general order of things. I'm feeling silly and haven't had my coffee yet, so bear with me .... When you think of a "state," think of it as you might think of a "state of being." You might be in a personal state of sleep, or hunger, or arousement, or anger ..... While you're in that state, any number of events might occur, prompted by some action. If your state is "hungry," you might salivate when you hear a bell, for example. The "bell" event is therefore inside the "hungry" state. Salivation might be a single system-defined function (llSalivate()) or a set of steps that you do in sequence inside the "bell" event. It might also be a sequence of things that you do in many different events. For example, you might salivate in a "thirsty" event as well as a "hungry" event. It would be silly to write the same set of commands for salivation in each different event, so you can write them as a user-defined function, salivate(), instead. If so, you set that function off to one side and call it whenever you need it. The place to put the salivate() function is outside of the "hungry" state, obviously, because you'll want it available in "thirsty" and other states too. There are other things to put outside the "hungry" state .... things that will be universally useful in multiple states. These things (air, water, .... ) are global variables. So here's what it looks like schematically (using some phony "standard" functions ... integer air; float water; integer bell; salivate() // Here's the user-defined function { llSlobber(); //OK, so this is a very short function. ;-) } default //this is the "normal" state you're in. { state_entry() // Do background stuff to define this state { llBreathe(air); llSetTimerEvent(21600.0); // Set the timer to check for hunger every six hours } timer() { state hungry; // It's time. Go to the hungry state } } state hungry() { state_entry() // Do background stuff to define this new state { llBreathe(air); bell = 0; llListen (34,"",NULL_KEY,""); // Get ready to listen on channel 34 } listen (integer channel, string name, key id, string message) { if (message == "ding") { bell = 1; } llSetBellEvent(bell); } bell(loudness) { if (loudness >= 1) { salivate(); // Do the stuff in the user-defined function llDrink(water); } else // If the bell wasn't loud enough { state default; // Go back to the "normal" state and wait another six hours } } }
If you can figure this out, you're doing OK. (Unless I screwed up. I need my coffee.)
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask....  Look for my work in XStreetSL at 
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
04-20-2009 11:46
Lets try something really basic - forget the llParticleSystem stuff for the moment (that's another herd of cats all by itself): MyFunction() { float val = llFrand(1); llOwnerSay((string)val); }
default { state_entry() { MyFunction(); llSetTimerEvent(1.0); }
timer() { MyFunction(); } }
When I read your original post this was always a question begging for a User Defined Function (UDF). A UDF allows you to withdraw code from a single event handler (state_entry(), timer(), etc.) so that you can re-use it. The example below is functionally the same as that above: default { state_entry() { float val = llFrand(1); llOwnerSay((string)val); llSetTimerEvent(1.0); }
timer() { float val = llFrand(1); llOwnerSay((string)val); } }
But I hope you can see that as the code complexity grows this is not a good model. It becomes very verbose, and a pain to maintain. UDFs are about recognising the chunks of code that you want to evoke in different contexts. With experience you should actually design your code to exploit cunningly crafted UDFs that take the burden of raw code away from the individual event handlers. Debugging, and extending the code, then becomes a lot simpler. I could have originally suggested that you simply duplicate that whole mess of llParticleSystem code into a timer - job done, but ugly. when I say ugly, I don't mean rough looking, I mean hideous (with apologies to The Stranglers).  )
|
|
Tyrehl Byk
Registered User
Join date: 4 Dec 2008
Posts: 24
|
04-20-2009 13:17
You folks ROCK! ...and yeah that, Pale about clean code. I used to build my websites writing raw HTML 'cause the drag'n drop HTML programs wrote such cluttered code. I'll now wait in the default state 'till my next event is triggered. Good things to you both! T.
|