|
All scripts must have a ’default’ state, which is the first state entered when the script starts. States contain event handlers that are triggered by the LSL virtual machine. All states must supply at least one event handler - it’s not really a state without one.
When state changes, all callback settings are retained and all pending events are cleared. For example, if you have set a listen callback in the default state and do not remove it during state_exit(), the listen callback will be called in your new state if a new listen event passes the filter set in the default state. 5.1. state_entry()
The state_entry event occurs whenever a new state is entered, including program start, and is always the first event handled. No data is passed to this event handler.
You will usually want to set callbacks for things such as timers and seonsor in the state_entry() callback of the state to put your object into a useful condition for that state. | Warning | | It is a common mistake to assume that the state_entry() callback is called when you rez an object out of your inventory. When you derez an object into your inventory the current state of the script is saved, so there will not be a call to state_entry() during the rez. If you need to provide startup code every time an object is created, you should create a global function and call it from both state_entry() and the on_rez() callbacks. // global initialization function. init() { // Set up a listen callback for whoever owns this object. key owner = llGetOwner(); llListen(0, "", owner, ""); } default { state_entry() { init(); } on_rez(integer start_param) { init(); } listen(integer channel, string name, key id, string message) { llSay(0, "Hi " + name + "! You own me."); } } | 5.2. state_exit() The state_entry event occurs whenever the state command is used to transition to another state. It is handled before the new state’s state_entry event.
You will want to provide a state_exit() if you need to clean up any events that you have requested in the current state, but do not expect in the next state. default { state_entry() { state TimerState; } } state TimerState { state_entry() { // set a timer event for 5 seconds in the future. llSetTimerEvent(5.0); } timer() { llSay(0, "timer"); state ListenState; } state_exit() { // turn off future timer events. llSetTimerEvent(0.0); } } integer g_listen_control; state ListenState { state_entry() { // listen for anything on the public channel g_listen_control = llListen(0, "", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { llSay(0, "listen"); state TimerState; } state_exit() { // turn off the listener llListenRemove(g_listen_control); } } The state_exit() handler is not called when an object is being deleted - all callbacks, handlers, sounds, etc, will be cleaned up automatically for you. 5.3. States vs. Global variables A state and a set of global variables can serve the same purpose, and each can be expressed in terms of the other. In general, you should prefer the use of states over global variables since states allow you to immediately assume script state without making comparisons. The less comparisons a script makes, the more regular code statements it can run.
|