skimi3d Grid Log in Visit the grid
All scripts
Make things move

Platform Lift

Sit on it and it takes you up. Stand up at the top and it comes back down on its own, ready for the next person.

Goes inThe platform, its root prim
Setup7 to set
Code177 lines
Open toOpen to everyone

What it does

Sitting down sends it up; sitting down at the top sends it back. When the rider steps off at the top it waits a few seconds and returns by itself, and it does the same after an empty trip, so it is never left waiting upstairs. It moves with keyframed motion, which is what actually carries the rider: the platform and whoever is sitting on it travel as one thing. It also says something when it cannot move, because the two reasons it silently refuses are worth being told about.

What you can build with it

A lift between two floors, a hoist up to a treehouse, a platform to a skybox, a cliff lift, a mine cage, the way up to a DJ booth. Two floors, no shaft, no doors, no call buttons: the simplest thing that will actually carry somebody.

How to use it

1 Build the platform and link it, then put this script in the ROOT prim.
2 Make sure Physical is switched OFF in the build tool.
3 Stand the platform at the BOTTOM. Wherever it is when the script starts counts as the bottom.
4 Set TRAVEL to how far up it should go, in metres, and TIME to how long the trip should take.
5 Sit on it. If you land in the wrong place, nudge SIT_POSITION.

Settings you can change

7

Edit these at the top of the script. Everything works on the defaults · change them only when you need to.

TRAVEL How far up it goes, in metres. 6.0
TIME How long the trip takes, in seconds, each way. 5.0
SIT_POSITION Where the rider sits, measured from the middle of the platform. Never exactly zero: that is how you say there is no seat at all. <0.0, 0.0, 0.6>
MENU_TEXT What the right-click menu says. Ride up
CLICK_TO_RIDE A left click sits somebody straight down, with no menu. TRUE
RETURN_WHEN_EMPTY Come back down by itself once the rider has stepped off at the top. TRUE
RETURN_AFTER How many seconds to wait before it does. 8.0
The code LSL · 177 lines · updated 8 Sep 2026 Download .lsl
// =====================================================================
//  Platform Lift
//  skimi3d script library
//  https://grid.skimi3d.com/scripts/platform-lift
//
//  Sit on it and it takes you up. Stand up at the top and it comes back
//  down on its own, ready for the next person.
//
//  Two floors, no shaft, no doors, no call buttons. It is the simplest
//  thing that will actually carry somebody, and simple is the reason it
//  works: most home-made lifts fail because the avatar was standing on
//  the platform rather than sitting on it.
//
//  Plain LSL.
// =====================================================================


// ---------------------------------------------------------------------
//  Settings
// ---------------------------------------------------------------------

// How far up it goes, in metres.
float TRAVEL = 6.0;

// How long the trip takes, in seconds, each way.
float TIME = 5.0;

// Where the rider sits, measured from the middle of the platform. Never
// exactly zero: that is how you say there is no seat at all.
vector SIT_POSITION = <0.0, 0.0, 0.6>;

// What the right-click menu says.
string MENU_TEXT = "Ride up";

// A left click sits somebody straight down, with no menu.
integer CLICK_TO_RIDE = TRUE;

// Come back down by itself once the rider has stepped off at the top,
// and how many seconds to wait first.
integer RETURN_WHEN_EMPTY = TRUE;
float   RETURN_AFTER = 8.0;


// ---------------------------------------------------------------------
//  Everything below here is the machinery
// ---------------------------------------------------------------------

integer gUp     = FALSE;    // is it at the top?
integer gMoving = FALSE;
integer gJob    = 0;        // 0 nothing, 1 arriving, 2 waiting to come down
key     gRider  = NULL_KEY;


ride(integer up)
{
    // Both of these make keyframed motion do nothing at all, silently.
    if (llGetStatus(STATUS_PHYSICS))
    {
        llOwnerSay("I cannot move: I am physical, and keyframed motion only works on things that are not. Turn Physical off in the build tool.");
        return;
    }
    if (llGetAttached())
    {
        llOwnerSay("I cannot move while I am worn.");
        return;
    }

    float far = TRAVEL;
    if (!up) far = -TRAVEL;

    // One step, straight up or straight down. Keyframed motion is what
    // carries the rider: the platform and whoever is sitting on it move
    // as one thing, which llSetPos would not manage.
    llSetKeyframedMotion([<0.0, 0.0, far>, ZERO_ROTATION, TIME],
                         [KFM_MODE, KFM_FORWARD]);

    gMoving = TRUE;
    gUp     = up;
    gJob    = 1;
    llSetTimerEvent(TIME);
}


seat()
{
    llSitTarget(SIT_POSITION, ZERO_ROTATION);
    llSetSitText(MENU_TEXT);

    if (CLICK_TO_RIDE)  llSetClickAction(CLICK_ACTION_SIT);
    if (!CLICK_TO_RIDE) llSetClickAction(CLICK_ACTION_TOUCH);
}


default
{
    state_entry()
    {
        seat();

        // Wherever it is standing now counts as the bottom. Put it at
        // the bottom before you drop the script in.
        gUp     = FALSE;
        gMoving = FALSE;
        gJob    = 0;
        gRider  = NULL_KEY;
        llSetTimerEvent(0.0);
    }

    changed(integer what)
    {
        if (!(what & CHANGED_LINK)) return;

        key who = llAvatarOnSitTarget();

        if (who)
        {
            gRider = who;

            // Somebody got on at the bottom, so up we go. Somebody
            // getting on at the top is riding back down.
            if (!gMoving) ride(!gUp);
            return;
        }

        // The rider stepped off.
        if (gRider)
        {
            gRider = NULL_KEY;

            if (RETURN_WHEN_EMPTY && gUp && !gMoving)
            {
                gJob = 2;
                llSetTimerEvent(RETURN_AFTER);
            }
        }
    }

    timer()
    {
        if (gJob == 1)
        {
            // Arrived.
            gMoving = FALSE;
            gJob    = 0;
            llSetTimerEvent(0.0);

            // Nobody got off, because nobody was ever on: an empty trip
            // up should still come back down.
            if (RETURN_WHEN_EMPTY && gUp && !gRider)
            {
                gJob = 2;
                llSetTimerEvent(RETURN_AFTER);
            }
            return;
        }

        if (gJob == 2)
        {
            gJob = 0;
            llSetTimerEvent(0.0);

            // Somebody stepped on while it was waiting. Leave it where
            // it is; their sitting down will have already sent it.
            if (gRider) return;
            if (!gUp) return;

            ride(FALSE);
        }
    }

    on_rez(integer start)
    {
        // A rezzed copy is standing at its new bottom, whatever it was
        // doing when it was taken.
        llResetScript();
    }
}

Copy it, make a new script inworld, paste over what is there and save. Nothing here phones home.