LSL is an event-driven language. Literally, scripts are divided into blocks of code that are triggered when a certain event happens. Scripts can provide event handlers, like moving_end or touch_start. If a script provides an event handler, and an event of this type occurs, thesimulator will add this event to the script’s event queue.
The script’s event handlers will then be called in the order the events are queued in (FIFO). According to Cory Linden, the event queue can hold up to 64 events. If the event queue is filled, it will silently drop any new events. Remember: LSL is not multi-threaded. Only one event will be run at a time; events cannot interupt each other. There is no way to interact with the event queue directly.
Changing states clears the event queue. Different states can have different event handlers. Be wary of bugs though. For instance, when an event handler is called, all of the arguments for that event handler are passed by value, and thus placed on the script’s stack. If a script has insufficient memory to hold all of the arguments, the script is halted with a “stack/heap collision” error and no code in the event handler will run.
Unlike functions, it’s not possible for scripters to create our own custom event handlers. If you need to check whether or not something has occurred, and it’s not covered by an existing event handler, you’ll need to use the timer() event.
The function llMinEventDelay may be of some use in coordinating events.
|at_rot_target||when a rotational target set with llRotTarget is reached|
|at_target||when a target set with llTarget is reached|
|attach||when an object attaches or detaches from agent|
|changed||when certain aspects of the object are changed (inventory, color, shape, scale, texture, link, ownership)|
|collision||while task is colliding with another task|
|collision_end||when task stops colliding with another task, or stops being penetrated while llVolumeDetect is set|
|collision_start||when task starts colliding with another task, or starts being penetrated while llVolumeDetect is set|
|control||when one of the controls taken with llTakeControls is pressed/held/released|
|dataserver||when task receives asynchronous data|
|when task receives email|
|http_response||when task receives response to request made with llHTTPRequest|
|http_request||when task receives response to request made with an external HTTP Request|
|land_collision||while task is colliding with land|
|land_collision_end||when task stops colliding with land|
|land_collision_start||when task starts colliding with land|
|link_message||when task receives a link message sent via llMessageLinked|
|listen||when task is within hearing range of chat matching the critera set in llListen|
|money||when money is given to task|
|moving_end||when task stops moving or when task exits a sim.|
|moving_start||when task begins moving or when task enters a sim.|
|no_sensor||when a call to llSensor or llSensorRepeat results in no targets sensed|
|not_at_rot_target||when a rotational target set with llRotTarget is not yet reached|
|not_at_target||when a target set with llTarget is not yet reached|
|object_rez||when task rezzes another task using llRezObject|
|on_rez||when task is rezzed (from inventory or another task, includes attaching directly from inventory)|
|remote_data||any kind of XML-RPC communication|
|run_time_permissions||when an agent grants run-time permissions to task that were requested via llRequestPermissions|
|sensor||Result of llSensor or llSensorRepeat functions|
|state_entry||on any transition into the state and on startup|
|state_exit||on any state transition out of the state|
|timer||in intervals set by llSetTimerEvent|
|touch||while agent clicks on task|
|touch_start||when agent starts clicking on task|
|touch_end||when agent stops clicking on task|
|transaction_result||fired by llTransferLindenDollars|
Q: Wait, what’s a “task”?
A: In LSL parlance, a task is an avatar/agent or an object. Both can collide with an object, though only objects can contain scripts. In the above list, you can generally take “task” to mean “the object containing the script.”
Q: How do I get input from one event and act on that in another?
Q: How do I know which event is going to be triggered, and in what order? This is complicated!
A: It is, but you can get the hang of it pretty quickly. Say you have state_entry, on_rez and attach events in a script, and you attach the object from inventory. What’s going to happen? Well, state_entry will already have triggered when the script first ran, so it’s not that. on_rez always executes first, even if you attach it, so that’s what will happen first. attach will happen afterwards, unless on_rez contains a state change, or something else to interrupt the state, such as llResetScript or llDie. See: Example Event Order.
Q: Okay, but what about other events? How do I know when they’ll be triggered?
A: As soon as something happens to trigger them, in the order that the event occurs in. So if you click on an object, you’ll see touch_start, touch and touch_end, in that order. If the listen event is triggered while you’re still touching the object, you’ll get that after touch. It can be difficult to structure a script, if you need some input from a listen event, and some from touch_start, but you can use global variables to hold data between events.
Q: What’s the different between an “event” and an “event handler”? I’ve seen both terms used, but they seem to both apply to the same thing.
A: Properly, an “event” is the thing that happens and an “event handler” is the thing that handles it. In practice, most scripters use the terms interchangably, or favour “event” over “event handler”. This is technically incorrect, but is very common usage.
Q: Can events interrupt each other?
A: No, events are run to their completion, in the order that they were received. For example, if you have a while(TRUE); statement (a statement that never finishes executing) in your state_entry event, and someone touches the object (triggering a touch_start event) the touch_start event will never run, because the state_entry event never finishes.