States, events and methods, oh my
|
|
Zaylor Tokugawa
Registered User
Join date: 16 Feb 2005
Posts: 5
|
02-16-2005 06:26
Hi, I am trying to undertand how to use states, but I am having difficulties listening for events. I have looked at Hank Ramo's excellent explanation of states and have used his format to create a script that passes from state to state. The skeleton of this code is below. Most of the action occurs in the 'doSomething' state where a calls a method which in turn calls another method that rez's an item from the object's inventory. This all works fine, except that rezzing an object doesn't appear to fire the object_rez event. Listening for the rez'd inventory item say it's key in it's on_rez method doesn't appear to hear the message either. Am I completely missing something fundamental about States, Methods and Events? BTW, pardon my bracketing style. I know a lot of SL code is not written this way, but it's a carry over from my own Java stylebook and it does compile. And sorry, I don't know how to place code in those scrolling windows :-/. Thanks rezAnItem(){ llRezObject("inventoryItem",llGetPos()+cardPosition,ZERO_VECTOR,llEuler2Rot(rot),cardFace); } someMethod() { rezAnItem(); } default { state_entry() { llRequestPermissions(llGetOwner(),PERMISSION_CHANGE_LINKS && PERMISSION_DEBIT); state waiting; } } state waiting { state_entry() { llSay(0,"Entering waiting state"  ; } money(key id, integer amount) { key playerID = id; integer amountPaid = amount; state doSomething; } } state doSomething { state_entry() { llListen(617,"inventoryItem","",""  ; someMethod(); if (TRUE) { state conclusionA; } else { state conclusionB; } } listen(integer channel,string name,key id,string message ){ llSay(0,"heard inventoryItem's on_rez say it's key"+(string)id); } object_rez(key id) { llSay(0,"doSomething State: rezzing an inventoryItem: "+(string)id); llCreateLink(id,TRUE); } } state conclusionA { state_entry() { state waiting; } } state conclusionB { state_entry() { state waiting; } }
|
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
02-16-2005 08:52
Your indentation style is just fine (that's how I indent my code, anyway), but please edit your post and enclose your code in [ code ] [ / code ] tags (take out those spaces). next up, you need to change this line llRequestPermissions(llGetOwner(),PERMISSION_CHANGE_LINKS && PERMISSION_DEBIT); to have only one &. That's a bitwise & operation, not the standard boolean && used in if/else. The reason your object_rez isn't being called is because your code instantly jumps to another state right after it calls the functions that rez the object. LSL doesn't trigger your object_rez event instantly -- it may even take it a few seconds to rez that object. Either way, you never gave it the chance to trigger the object_rez event, because you jumped straight to the conclusion state. New events that arrive don't interrupt the event that is already being executed -- this is not multi-threaded execution.
|
|
Zaylor Tokugawa
Registered User
Join date: 16 Feb 2005
Posts: 5
|
02-16-2005 09:35
Lex, Thanks for code formatting tip and your thoughts on the failure. I was wondering if I was racing through the states too fast to register an event. What's the best-practice for slowing the process down, through llSleep or a timer? Or something else? Thanks again From: Lex Neva
The reason your object_rez isn't being called is because your code instantly jumps to another state right after it calls the functions that rez the object. LSL doesn't trigger your object_rez event instantly -- it may even take it a few seconds to rez that object. Either way, you never gave it the chance to trigger the object_rez event, because you jumped straight to the conclusion state. New events that arrive don't interrupt the event that is already being executed -- this is not multi-threaded execution.
rezAnItem(){ llRezObject("inventoryItem",llGetPos()+cardPosition,ZERO_VECTOR,llEuler2Rot(rot),cardFace); }
someMethod() { rezAnItem(); }
default { state_entry() { llRequestPermissions(llGetOwner(),PERMISSION_CHANGE_LINKS & PERMISSION_DEBIT); state waiting; } }
state waiting { state_entry() { llSay(0,"Entering waiting state");
} money(key id, integer amount) { ikey playerID = id; integer amountPaid = amount; state doSomething; }
}
state doSomething { state_entry() { llListen(617,"inventoryItem","",""); someMethod(); if (TRUE) { state conclusionA; } else { state conclusionB; } } listen(integer channel,string name,key id,string message ){ llSay(0,"heard inventoryItem's on_rez say it's key"+(string)id); } object_rez(key id) { llSay(0,"doSomething State: rezzing an inventoryItem: "+(string)id); llCreateLink(id,TRUE); } }
state conclusionA { state_entry() {
state waiting; } }
state conclusionB { state_entry() { state waiting; } }
|
|
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
|
02-16-2005 12:20
Depending on how, precisely you are doing it, and what you are doing there are several ways.
llSetTimerEvent() and llSleep() are both acceptable choices.
A message by llMessageLinke() or llWhisper() would be other options - you could (to avoid listener load on the server) set up a listener, rez the object, and have in the listen event something to turn the listener off [llListenRemove()] and then change states. If it is a linked object you do similar in the link_message event.
That would guarantee that, however laggy, you rezzed the object before moving over to the new state, and would also mean that if things were going quickly you would move on basically as fast as the object rezzed.
|
|
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
|
02-16-2005 12:34
From: Zaylor Tokugawa state doSomething { state_entry() { llListen(617,"inventoryItem","",""); someMethod(); if (TRUE) { state conclusionA; } else { state conclusionB; } } listen(integer channel,string name,key id,string message ){ llSay(0,"heard inventoryItem's on_rez say it's key"+(string)id); } object_rez(key id) { llSay(0,"doSomething State: rezzing an inventoryItem: "+(string)id); llCreateLink(id,TRUE); } }
You might need to rethink how you structure this state. Ill walk you through what happens: When you enter this state, the state_entry() event is queued, and then it is called. The event sets up a listen handle on channel 617, and calls the function someMethod(), which eventually leads to a call to llRezObject. When llRezObject is called, the object_rez event is queued. When someMethod() returns, the script changes state to conclusionA and clears the event queue. object_rez is never executed, because the script never leaves state_entry within state doSomething. What is the state change to the conclusion states trying to accomplish? Here's what I think you might be trying to do: state doSomething { state_entry() { llListen(617, "inventoryItem", "", ""); someMethod(); }
listen(integer channel, string name, key id, string message) { llSay(0, "heard inventoryItem's on_rez say it's key" + (string)id); } object_rez(key id) { llSay(0, "doSomething State: rezzing an inventoryItem: " + (string)id); llCreateLink(id, TRUE); state conclusionA; // Rezzing successful. } }
Hope this helps!  ==Chris
|