Alternating Between Two States
|
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-23-2007 09:30
I am trying to do a simple task, script a switch that will rezz an object or kill it, alternately on a touch of the switch. The commands themselves work, it's the switching that has me in a spin. Here's where I am at the moment. //====================================================================== // Mandarin Water Switch -- kills or rezzes tub water - modifying Siggy's Water button //====================================================================== // Variables //---------------------------------------------------------------------- integer TUB_CHANNEL = 51; // Commmand channel for hottub integer HOTTUB_CHANNEL = 50; // Commmand channel for water //====================================================================== // States //---------------------------------------------------------------------- default { touch_start(integer a) { state full; } } state full { state_entry() { llSay(TUB_CHANNEL, "WATER REZZ"  ; // Command to rezz water //state default; } state_exit() { llSay(HOTTUB_CHANNEL, "WATER DIE"  ; // Command to delete water state default; } }
|
|
Shadow Subagja
Registered User
Join date: 29 Apr 2007
Posts: 354
|
07-23-2007 09:52
You almost had it  . basically states work like this: 1 - switch into state, do state_entry code 2 - handle events while in the state, timers, sensors, touch, etc 3 - switch out of the state, do state_exit code So each state stands alone and follows that model. When your script starts, it automatically switches into the default state, which is like every other state except it has a special name. When you switch to full, you first do the state_exit of the state you are in (default), then the state_entry() of the new state (full). At this point it stops and just handles events. You had no code to tell it to switch back to the default state unless it was already in the process of switching back (since the code was in state_exit). By moving it to state_entry(), your full state will automatically switch back to default, and because of how states work your state_exit() should still get called on the way out. default { touch_start(integer a) { state full; } } state full { state_entry() { llSay(TUB_CHANNEL, "WATER REZZ"  ; // Command to rezz water state default; } state_exit() { llSay(HOTTUB_CHANNEL, "WATER DIE"  ; // Command to delete water } }
|
|
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
|
07-23-2007 11:05
Well, from what I read in the script and from what you say you want to do, it seems a bit off.
You want to have a rez toggle is my assumption. Click once to rez, click again to derez.
default { state_entry() { state exit; } } state full { state_entry() { //rez stuff here and whatever else } touch_start(integer Tot) { state exit; } } state exit { state_entry() { //derez if applicable and whatever else } touch_start(integer Tot) { state full; } }
What this does is drops the script automatically in the unrezzed state which will send the command to derez(which will do nothing if nothing is rez'd, or if restarted will remove any leftovers which is an added failsafe), and when you touch it, it goes to the rez state that rezzes the object at the start and waits for you to touch it again. Touch it again and it goes right back to the state exit and thereby completes the loop and will toggle back and forth as long as the script is running.
|
|
Shadow Subagja
Registered User
Join date: 29 Apr 2007
Posts: 354
|
07-23-2007 11:43
I think I misread, the version I put up would automatically rez/derez with one touch. The behavior would be similar/the same as what Tiarnalalon has posted if you moved the "state default" from the state_entry() to a touch_start() in the full state
|
|
Zen Zeddmore
3dprinter Enthusiast
Join date: 31 Jul 2006
Posts: 604
|
07-23-2007 16:40
I'm thinking what you're asking for here is a working faucet. integer Faucet_CHANNEL = 50; default { touch_start(integer total_number) {llSay(Faucet_CHANNEL, "WATER REZZ"  ; state water_Is_Up; } } state water_Is_Up { touch_start(integer total_number) {llSay(Faucet_CHANNEL, "WATER DIE"  ; state default; } } you don't need separate listens for this as your "if messege= "WATER REZZ" or any billion other ifs are as easily accomodated are we getting closer?
_____________________
A kilogram of programmable nanobots can lower the certainty of both death AND taxes.
|
|
Squirrel Wood
Nuteater. Beware!
Join date: 14 Jun 2006
Posts: 471
|
07-23-2007 23:43
integer Toggle = FALSE; default() { touch_start(integer x) { Toggle = !Toggle; if (TRUE == Toggle) { llSay(Faucet_CHANNEL, "WATER REZZ"  ; } else { llSay(Faucet_CHANNEL, "WATER DIE"  ; } } } no separate states required.
|
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-24-2007 05:36
Shadow, Zen, Tiarnalalon, and Squirrel - Thanks so much. The approaches you suggested were all excellent - and with the diversity of coding approaches taught me more in seeing the logic the possible paths to a solution. Yes you were all right, by the way, if my original post was unclear, i did want it to toggle from one to another on a touch. I tested each solution and both the use of states and if then..else work well. I really liked the elegance of your coding. It helped in simplifying the use of states (something I had not used before, but wanted to understand) as well as what I did not know how to do correctly with the if..else approach (the use of the conditional variable). So I got the problem itself resolved  . Thanks again for the quality of your mentoring, it's most appreciated.
|
|
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
|
07-24-2007 06:58
All you needed in your original code was a touch handler in the full state:
touch_start(integer a) { state default; }
and the state default in the state_exit is not needed, you're already on your way out of the state in state_exit().
|