Elevators are a common mode of transportation in the Second Life world. The Heaton Research office building, where many of the examples from this book can be found, includes an elevator. It is the same elevator that will be covered in this recipe. The elevator in the Heaton Research Tower can be found at:

http://slurl.com/secondlife/Encogia/197/197/23

    The above SLURL leads to the lobby of the Heaton Research tower. The elevator is located there. If the elevator is not present, click the green cone to call the elevator. Figure 3.4.

Figure 3.4: An Elevator

An Elevator

    The elevator consists of three objects:

  • The Elevator Car
  • Elevator Call Cone
  • Elevator Call Cone with Repeater

    Each of these objects contains its own script and serves its own function.

The Elevator Car

    The elevator car is the heart of the elevator system. It is also has the most complex script of any of the elevator parts. The elevator car can be seen in Figure 3.4. The script for the elevator car is shown in Listing 3.6.

Listing 3.6: Elevator Car (Elevator.lsl)

// From the book:
//
// Scripting Recipes for Second Life
// by Jeff Heaton (Encog Dod in SL)
// ISBN: 160439000X
// Copyright 2007 by Heaton Research, Inc.
//
// This script may be freely copied and modified so long as this header
// remains unmodified.
//
// For more information about this book visit the following web site:
//
// http://www.heatonresearch.com/articles/series/22/

integer CHANNEL = 42; // dialog channel
list MENU_MAIN = ["Floor 1", "Floor 2", "Floor 3", "Floor 4", "Floor 5", "Floor 6", "Floor 7", "Floor 8", "Floor 9", "Floor 10","Roof"]; // the main menu

float BOTTOM = 22.260;
float FLOOR_HEIGHT = 10;
float SPEED = 2;
float target;


default
{
    state_entry()
    {
        llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users)
        llSitTarget(<0,-0.5,0.5>, llEuler2Rot(<0,0,-90>) );
        llSetText("Sit Here to Ride Elevator",<0,0,0>,1.0);
        target = BOTTOM;
    }
    
    listen(integer channel, string name, key id, string message) 
    {
        integer idx = llListFindList(MENU_MAIN, [message]);
        if( idx!=-1 )
        {
            llSay(0,"Elevator heading to " + message + "." );
            target = BOTTOM + (idx*10);
            state moving;
        } 
    }

    changed(integer Change) 
    {
        llDialog(llAvatarOnSitTarget(), "Where to?", MENU_MAIN, CHANNEL);
    }
    
}

state moving
{
    
    
    state_entry()
    {
        llSetTimerEvent(0.1);
    }
    
    timer()
    {
        vector pos = llGetPos();
        
        if( pos.z!=target )
        {
            if( pos.z>target )
            {
                pos.z = pos.z - SPEED;
            }
            else
            {
                pos.z = pos.z + SPEED;
            }
        }
        
        if(  llFabs(pos.z - target) < SPEED )
        {
            pos.z = target;
            llSetTimerEvent(0);
            llSetPos(pos);
            llSay(0,"Elevator has reached its target." );
            state default;
        }   
        
        llSetPos(pos);
        
    }
}

    The elevator car begins by defining several global variables. These are.

integer CHANNEL = 42; // dialog channel
list MENU_MAIN = ["Floor 1", "Floor 2", "Floor 3", "Floor 4", "Floor 5", "Floor 6", "Floor 7", "Floor 8", "Floor 9", "Floor 10","Roof"]; // the main menu
float BOTTOM = 22.260;
float FLOOR_HEIGHT = 10;
float SPEED = 2;
float target;

    The first is the CHANNEL. The elevator needs its target floor communicated to it. This will be communicated using either a menu or one of the elevator call cones. The MAIN_MENU defines the labels for each of the floors. The BOTTOM variable defines the height of the ground floor. The FLOOR_HEIGHT variable defines the height of each of the floors in meters. The SPEED defines how fast the elevator travels, lower is slower. The target variable holds the target z-coordinate, in meters, when the elevator is in motion.

    The default state of the elevator is to be still. After the default state is entered, the elevator sets up. It defines the sit target, as well as the sit text. The elevator also begins listening for commands.

default
{
    state_entry()
    {
        llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users)
        llSitTarget(<0,-0.5,0.5>, llEuler2Rot(<0,0,-90>) );
        llSetText("Sit Here to Ride Elevator",<0,0,0>,1.0);
        target = BOTTOM;
    }

    The listen event handler allows the elevator to receive commands from both the elevator's menu and the elevator call cones placed on each of the floors. The listen event handler begins by finding the index of the string sent to it. This tells the elevator which floor to visit. The elevator then announces which floor it is heading to and enters the moving state.

    listen(integer channel, string name, key id, string message) 
    {
        integer idx = llListFindList(MENU_MAIN, [message]);
        if( idx!=-1 )
        {
            llSay(0,"Elevator heading to " + message + "." );
            target = BOTTOM + (idx*10);
            state moving;
        } 
    }

    When an avatar sits on the elevator car, a dialog is displayed to prompt for which floor to visit. This will be a list of floors specified in the MAIN_MENU variable. When the user picks one of these options, the text of that option is sent to the elevator car's listen event handler.

    changed(integer Change) 
    {
        llDialog(llAvatarOnSitTarget(), "Where to?", MENU_MAIN, CHANNEL);
    }
}

    Once the elevator enters the moving state, a timer is created that will occur ten times a second.

state moving
{
    state_entry()
    {
        llSetTimerEvent(0.1);
    }

    Each time the timer event handler is called, the elevator moves closer to its target. The timer event handler begins by obtaining the current position of the elevator.

    timer()
    {
        vector pos = llGetPos();

    If the elevator is not at its target, the current z-coordinate will be increased or decreased, depending on which is necessary to move the elevator closer to its target.

        if( pos.z!=target )
        {
            if( pos.z>target )
            {
                pos.z = pos.z - SPEED;
            }
            else
            {
                pos.z = pos.z + SPEED;
            }
        }

    If the elevator is reasonably close to its target, move the elevator directly to its target. The timer is then stopped and the elevator returns to its default state.

        if(  llFabs(pos.z - target) < SPEED )
        {
            pos.z = target;
            llSetTimerEvent(0);
            llSetPos(pos);
            llSay(0,"Elevator has reached its target." );
            state default;
        }   
        
        llSetPos(pos);
        
    }
}

    The elevator car is only part of the elevator system. An elevator call must be placed on each of the floors to call the elevator to that floor.

Calling the Elevator

    One of the elevator call cones is present in Figure 3.4. It is the green cone. Once clicked, it will call the elevator to the specified floor. The call elevator script is very simple. Once clicked, it calls the elevator to the floor specified in its script. The call elevator script can be seen in Listing 3.8.

Listing 3.7: Call Elevator (Call.lsl)

// From the book:
//
// Scripting Recipes for Second Life
// by Jeff Heaton (Encog Dod in SL)
// ISBN: 160439000X
// Copyright 2007 by Heaton Research, Inc.
//
// This script may be freely copied and modified so long as this header
// remains unmodified.
//
// For more information about this book visit the following web site:
//
// http://www.heatonresearch.com/articles/series/22/

integer CHANNEL = 42; // dialog channel

default
{
    state_entry()
    {
        llSetText("Touch to Call Elevator",<0,0,0>,1.0);
    }

    touch_start(integer total_number)
    {
                
        llRegionSay(42, "Floor 1");
    }
}

    Once the call elevator cone is clicked, the touch_start event handler announces the target floor to the region on the same channel to which the elevator is listening.

llRegionSay(42, "Floor 7");

    The llRegionSay has much more distance than llShout. Commands sent with llRegionSay can be heard anywhere in the region. However, llRegion may say not be used on the general chat channel (0). The shout command sends the command to the elevator car.


Copyright 2005 - 2010 by Heaton Research, Inc.. Heaton Research™ and Encog™ are trademarks of Heaton Research. Click here for copyright and trademark information.