This script is one I wrote for a barrier which prohibits entry unless the barrier's owner touches or collides with it; when this happens, it will set itself to PHANTOM and turn partially transparent for five seconds, and then return to its previous opaque solidity.
It's also a good demonstration of how to modify prim parameters, set timers, and use multiple states.
default {
collision_start(integer total_number) {
if (llDetectedKey( 0 ) == llGetOwner()) state open;
}
touch_start(integer total_number) {
if (llDetectedKey( 0 ) == llGetOwner()) state open;
}
}
state open {
state_entry() {
llSetPrimitiveParams( [PRIM_PHANTOM,TRUE,
PRIM_COLOR,4,<1,1,1>,0.75,
PRIM_COLOR,2,<1,1,1>,0.75] );
llSetTimerEvent( 5 );
}
timer() {
llSetPrimitiveParams( [PRIM_PHANTOM,FALSE,
PRIM_COLOR,4,<1,1,1>,1.0,
PRIM_COLOR,2,<1,1,1>,1.0] );
llSetTimerEvent( 0 );
state default;
}
}
Okay, now the first line in this script is the
default state. States are a way for the script to behave differently based on certain criteria; without states, we would have to use variables to keep track of things. In this script, I have two states: the default state (in which a touch or collision by the owner will "open" the barrier), and the "open" state, in which it opens itself, waits five seconds, and then closes again; in this state, further touches and collisions will do nothing.
We have two functions in the default state:
collision_start and
touch_start. These two functions are called, if they exist, when an avatar or object starts to collide with the prim containing the script, or when an avatar starts touching the prim containing the script.
These two functions are passed a parameter, an integer value indicating how many objects or avatars have started colliding with (or touching) the prim. This number is usually one (it's theoretically possible for two avatars to start colliding with or touching the prim at the exact same instant, but for the sake of simplicity we're going to assume that it's only one).
As it happens, I want both of these conditions to do exactly the same thing, so the code within each function is identical:
if (llDetectedKey( 0 ) == llGetOwner()) state open;
llDetectedKey() gets the UUID of the object detected by the function. Index number 0, which we're using here, is the first object or avatar detected. (We could check the "total_number" variable, and if it's greater than one, we could loop through and check all of them, using
llDetectedKey( 1 ),
llDetectedKey( 2 ), and so on.)
The statement then compares the value returned by
llDetectedKey() against the key of the person who owns the barrier, which is returned by the
llGetOwner() function. If they're equal, then it switches into the
state I've named "open".
Tip: The default state must occur first in the script. If you try to insert another state above default, the LSL compiler will produce a syntax error when you try to save the script.
The "open" state contains a function named
state_entry. This gets called, if it exists, whenever the script enters the state the function is contained within. All states may have a
state_entry function; like with all predefined functions, whichever one exists in the currently active state is the one that gets called.
The
state_entry function calls
llSetPrimitiveParams(). This is a function which can change nearly every feature of a prim, including what shape it is! It takes a list of things you want to change, and what you want to change them to. (The wiki has a
great page describing all the things it can do.)
Here, we're changing the
PRIM_PHANTOM parameter, and setting it to
TRUE. I also decided to give a little visual feedback, so I'm setting the front and back faces of the barrier to partially transparent. With
llSetPrimitiveParams(), you have to change both the color and the alpha setting simultaneously. Fortunately, I know that the faces should be completely white, so for each face I pass the
PRIM_COLOR keyword (which tells
llSetPrimitiveParams() what I want to change), the number of the first face to change, the RGB value <1,1,1> (white), and the alpha value of 0.75, (75% opaque). I then pass the same sequence again for the other face.
Tip: To find out what face you want to change, edit the prim and click on the "Select Texture" radio button in the edit dialog. You should see crosshairs appear on all faces of the prim. Click on the face you want to find the number for, and hit Ctrl-Alt-Shift-T. Your chat window will give you certain information about the texture on that face, including the face number.
After setting the prim parameters, I then set a timer event to trigger five seconds later (and subsequently in five-second intervals until the timer is killed), and that's the end of the
state_entry function.
The next function is the
timer function, which gets called when the timer event is triggered. In this function, I call
llSetPrimitiveParams() again to reverse the changes I made earlier (I set the
PRIM_PHANTOM parameter back to
FALSE, and set the alpha on the front and back faces to 1.0 (fully opaque).
The next line kills the timer events (by passing a parameter of 0), and then the next line after that sets the script back into the
default state again so that it will "listen" for collisions and touches again.