Building in Second Life, By Example3.5 Scripting a Phantom Door |
- Next Section: 3.6 Authorizing Who Can Use a Door
- Previous Section: 3.4 Scripting a Swinging Door, with Linking
- Main Table of Contents
Building in Second Life, By Example3.5 Scripting a Phantom Door |
So far we've created a one-prim sliding door and a two-prim swinging door. The scripts associated with these can be used in many ways. A door might slide up and sideways instead of just left or right. You could build a castle door and bridge over a moat by having a heavy wooden door swing down over a gap, pivoting on a "hinge" at the base of the door.

In this section we're going to work with the door pictured on the right. It's a simple 2m wide and 4m high door that has a purchased door texture on it. For a bit of extra detail, I also made a round doorknob and linked it to the door itself.
If there were no door and just a door opening, everyone would be free just to walk through that. It doesn't give much privacy, but it allows passage through what would otherwise be a solid wall. If you do want a door but don't want the trouble of having it slide or swing out of the way, the simplest approach would just to make it into a phantom object.
A phantom object looks like any other object except that it doesn't collide with other objects or avatars. That is, if you walk into a phantom object you won't crash into or bounce off it. Rather, you'll just pass right through it as if you (or it) were a ghost.

The picture on the right shows me standing in the middle of the door. If the door were not phantom, I couldn't do this, and I would have to be on one side of the door or the other. When prims are linked together, either they all are phantom or none are. That is, you cannot have just one prim being phantom and linked to others that are not.

While building, you turn the phantom property on and off via a checkbox on the Object tab of the Edit dialog box. See the picture on the right.
When I am constructing a building, I sometimes temporarily make a wall or a roof phantom so that I can easily get inside or outside. Then, once I have have added doors, I'll go back and remove the phantom status, for security. Since people won't know if an object is phantom unless they try to pass through it, you can keep certain walls or wall sections phantom so you can "disappear" through them whenever you want to!
It's very common to make landscape objects like trees phantom so that people can walk or fly through them without getting tangled up in the branches.
If you just want to have a visible door that you can walk through, we're done. Just check the phantom box and you can pass right through.
We can do more, though. How could we accomplish the following?
There are a lot of other options and combinations possible. I'll tackle the first two tasks here and then turn to authorization in the next section. Let's start with the first job of controlling phantomness.
The function we will use to control whether the door is phantom or solid is
llSetStatus together with the

STATUS_PHANTOM flag.
When we set the phantom status to true, the door becomes phantom, as you might expect.
When we set it to false, the door becomes solid.

This script handles turning the phantom property on and off.
// Phantom door LSL script #1
// Handles the touch event.
// Processing for the script when it first starts up
default {
// What we do when we first enter this state
state_entry() {
state closed; // Move to the closed state
}
}
// Processing for the script when it is in the closed state
state closed {
// What we do when we first enter this state
state_entry() {
llSetStatus(STATUS_PHANTOM,FALSE); // Turn off phantom property
}
// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
state open; // Move to the open state
}
}
// Processing for the script when it is in the open state
state open {
// What we do when we first enter this state
state_entry() {
llSetStatus(STATUS_PHANTOM,TRUE); // Turn on phantom property
}
// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
state closed; // Move to the closed state
}
}
When the script starts, we move into the "closed" state, which here means that the door is solid, not phantom. When the closed state begins, we set the phantom status of the door to false via
llSetStatus(STATUS_PHANTOM,FALSE); // Turn off phantom property
When the closed solid door is touched, that is, clicked with the mouse, we move to the "open" state. When the open state begins, we set the phantom status of the door to true via
llSetStatus(STATUS_PHANTOM,TRUE); // Turn on phantom property
If the open phantom door is clicked, we move to the closed solid state. And so on and so on.
This is pretty much the most basic script on an object that toggles some behavior when the object is clicked.
It is similar to the first sliding door script, but there we needed to save some extra information about
the previous position of the door and know how much to move it. All the real action in this script takes place
in the state_entry functions for the open and closed states.

It is in these functions where we could add some kind of state indicator to show whether the door is solid or phantom. One possibility is that we create a separate light over the door that is green when the door is phantom and red when solid. That's a bit complicated at this point, so let's go with a simpler plan.
At the beginning of this section I referred to the phantom property as being ghostly because avatars can just pass right through. How about we make the door partially transparent when it is phantom and then non-transparent when it is solid?
If we make the door completely transparent, people might not know that it is even there. If we don't make it transparent enough, then they won't be able to notice any real difference. What value of alpha will work for us? In this particular case, using 0.75 seems about right and that's what is pictured to the right. For your particular door, you should experiment until you get something that works for your situation. Remember to look at it in different lighting conditions.
There's a technical point I need to make here that you might want to skip on first reading. The alpha value applies to each side in each prim in your object. In a one-prim door, there are 6 sides: front, back, top, bottom, left side, and right side. If we link in more prims, we must deal with each of their sides as well. LSL makes it easy to set the alpha values for all the sides on all the prims at once. However, it makes no sense to ask for THE single alpha for an object, because there is one for each contained side. They might happen to be all the same, but in the general case they will be different.
In our example here I'm going to make a significant simplifying assumption: we can set the alpha value to 1.0 for every side in every linked prim when we want the door to be solid.
I'll do this by changing the
alpha
value for the door.
When this is set to 0.0, we have have complete transparency.
When it is 1.0, we have no transparency other than what might be in the textures themselves.
Here is the version of our script that includes transparency:
// Phantom door LSL script #2
// Handles the touch event.
// Handles partial transparency when the door is in phantom mode.
// Processing for the script when it first starts up
float alpha = 0.75; // alpha value for partial transparency
// of the door when in phantom mode.
// 1.0 is solid, 0.0 is transparent.
default {
// What we do when we first enter this state
state_entry() {
state closed; // Move to the closed state
}
}
// Processing for the script when it is in the closed state
state closed {
// What we do when we first enter this state
state_entry() {
llSetStatus(STATUS_PHANTOM,FALSE); // Turn off phantom property
llSetLinkAlpha(LINK_SET, // Turn off transparency
1.0, ALL_SIDES);
}
// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
state open; // Move to the open state
}
}
// Processing for the script when it is in the open state
state open {
// What we do when we first enter this state
state_entry() {
llSetStatus(STATUS_PHANTOM,TRUE); // Turn on phantom property
llSetLinkAlpha(LINK_SET, // Turn on partial transparency
alpha, ALL_SIDES);
}
// What we do when the door is clicked ("touched") with the mouse
touch_start(integer total_number) {
state closed; // Move to the closed state
}
}
I put the declaration and definition of alpha at the top of the script so that it can be
easily found and changed.
When programming it's important to do this and not embed magic numbers like "0.75" somewhere in the code.
They can be hard to find and change, especially if a lot of time goes by or someone other than the
original author is trying to use the script.
float alpha = 0.75; // alpha value for partial transparency
// of the door when in phantom mode.
// 1.0 is solid, 0.0 is transparent.
When the door is closed, that is, solid, we turn off transparency using llSetLinkAlpha :

llSetLinkAlpha(LINK_SET, // Turn off transparency
1.0, ALL_SIDES);
When the door is open, that is, phantom, we turn on partial transparency using our chosen alpha value:
llSetLinkAlpha(LINK_SET, // Turn on partial transparency
alpha, ALL_SIDES);
This function call used two special LSL constants.
LINK_SET means that the operation, here setting the alpha value, should be applied
to every prim that is linked together into our door. This works even if there is only one prim.

ALL_SIDES means that for each prim to which the operation is applied, all sides of
the prim should be processed.
It's possible using 
llSetLinkAlpha to reach in and change the alpha value on one
particular side of one particular prim linked into the object.
We don't need that here given my simplifying assumption above.
