skimi3d Grid Log in Visit the grid
All scripts
Sit down

Sit Here

Turns any prim into a proper seat: the sitter lands where you say, faces the way you meant, and plays a pose from the prim's own Contents.

Goes inThe prim you want to sit on
Setup7 to set
Code167 lines
Open toOpen to everyone

What it does

Without a script, sitting on a prim drops the avatar somewhere near the top of it, in the default hunch, facing whichever way the region felt like. This script sets the seat position and facing yourself, renames the menu entry, turns a left click straight into sitting down, and swaps the default pose for whatever animation is lying in the prim's Contents. When the sitter stands up it puts the pose away again.

What you can build with it

Chairs, benches, bar stools, a window seat, a hammock, the driver's seat of a vehicle, a pose stand for a photo booth. Drop a different animation into the Contents and the same seat becomes a different seat, without touching a line of the script.

How to use it

1 Drop this script into the prim you want to sit on.
2 Drop a pose animation into the same prim's Contents. The seat uses the first one it finds, so one pose per seat is the simple arrangement.
3 Sit down and look at yourself. Nudge SIT_POSITION a few centimetres at a time until you are in the chair rather than through it or above it.
4 Turn yourself with SIT_ROTATION, which is in degrees: the third number is the one that swings you round.
5 Change MENU_TEXT to something better than Sit Here, and it appears in the right-click menu.

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.

SIT_POSITION Where the avatar sits, measured from the middle of this prim and in its own body. Must never be exactly zero, because that is how you say there is no seat at all. <0.0, 0.0, 0.4>
SIT_ROTATION Which way the sitter faces, in degrees, as pitch, roll and yaw. The third number is the one that swings them round. <0.0, 0.0, 0.0>
MENU_TEXT What the right-click menu says instead of Sit Here. Keep it short, the viewer gives it little room. Sit down
CLICK_TO_SIT A left click sits the visitor down straight away, with no menu at all. TRUE
ANIMATION The pose to play, by name. Left empty, the seat uses the first animation it finds in its own Contents, which is what makes it re-usable. (empty)
GREETING Something said quietly to whoever sits down. Empty says nothing. (empty)
WHO_MAY_SIT 0 for everyone, 1 for the owner alone, 2 for anyone wearing the same group tag. Anyone else is stood back up with a word of explanation. 0
The code LSL · 167 lines · updated 8 Sep 2026 Download .lsl
// =====================================================================
//  Sit Here
//  skimi3d script library · https://grid.skimi3d.com/scripts/sit-here
//
//  Turns any prim into a proper seat: the avatar lands where you say
//  rather than wherever the region guesses, the menu says something
//  better than "Sit Here", and a pose from the prim's own contents
//  replaces the default hunch.
//
//  Without a script, sitting on a prim puts the avatar somewhere near
//  the top of it in a default pose, facing whichever way it feels like.
//  Four lines below fix all of that.
//
//  Plain LSL. Works on a lone prim and on any prim in a linkset.
// =====================================================================


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

// Where the avatar sits, measured from the middle of this prim and in
// this prim's own body. Up is Z. Expect to nudge this by a few
// centimetres once you can see somebody sitting in it.
//
// IT MUST NOT BE EXACTLY <0.0, 0.0, 0.0>. That is not "the middle", it
// is the way of saying "no seat at all", and the whole script goes
// quiet. If you really want the middle, use <0.0, 0.0, 0.01>.
vector SIT_POSITION = <0.0, 0.0, 0.4>;

// Which way the sitter faces, in degrees, as pitch, roll and yaw.
// <0.0, 0.0, 0.0> faces the same way as the prim.
vector SIT_ROTATION = <0.0, 0.0, 0.0>;

// What the menu says instead of "Sit Here". Keep it short, the viewer
// gives it little room.
string MENU_TEXT = "Sit down";

// Left click sits the visitor down straight away, with no menu at all.
integer CLICK_TO_SIT = TRUE;

// The pose to play, by name. Leave it empty and the seat uses the first
// animation it finds in its own Contents, which is usually what you
// want: drop a pose in, and it is used.
string ANIMATION = "";

// Something said quietly to whoever sits down. Empty says nothing.
string GREETING = "";

// Who may sit. 0 = everyone, 1 = only the owner, 2 = only people
// wearing the same group tag.
integer WHO_MAY_SIT = 0;


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

key    gSitter = NULL_KEY;
string gPose   = "";


// The pose this seat should play, or an empty string for none.
string findPose()
{
    if (ANIMATION != "") return ANIMATION;

    // Nothing named, so take the first animation lying in Contents.
    // This is what makes the seat re-usable: drop a different pose in
    // and reset, and the seat is a different seat.
    if (llGetInventoryNumber(INVENTORY_ANIMATION) > 0)
    {
        return llGetInventoryName(INVENTORY_ANIMATION, 0);
    }

    return "";
}


integer maySit(key who)
{
    if (WHO_MAY_SIT == 1) return who == llGetOwner();
    if (WHO_MAY_SIT == 2) return llSameGroup(who);
    return TRUE;
}


seat()
{
    llSitTarget(SIT_POSITION, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD));
    llSetSitText(MENU_TEXT);

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


default
{
    state_entry()
    {
        seat();
        gPose   = findPose();
        gSitter = NULL_KEY;
    }

    changed(integer what)
    {
        // Somebody sitting down or standing up both arrive as a change
        // of links, which is why this one event has to sort out which
        // of the two just happened.
        if (what & CHANGED_LINK)
        {
            key who = llAvatarOnSitTarget();

            if (who)
            {
                // Somebody sat down.
                if (!maySit(who))
                {
                    llRegionSayTo(who, 0, "This seat is not for you.");
                    llUnSit(who);
                    return;
                }

                gSitter = who;

                // Sitting on an object grants this by itself, with no
                // dialog for the visitor to dismiss. Asking is still
                // required; it is the asking that is free, not the
                // permission.
                llRequestPermissions(who, PERMISSION_TRIGGER_ANIMATION);

                if (GREETING != "") llRegionSayTo(who, 0, GREETING);
                return;
            }

            // Nobody on the target any more, so whoever it was stood up.
            if (gSitter)
            {
                if (gPose != "") llStopAnimation(gPose);
                gSitter = NULL_KEY;
            }
        }

        // A pose dropped in after the seat was built should be picked
        // up without anyone having to remember to reset the script.
        if (what & CHANGED_INVENTORY) gPose = findPose();
    }

    run_time_permissions(integer granted)
    {
        if (!(granted & PERMISSION_TRIGGER_ANIMATION)) return;
        if (gPose == "") return;

        // The default sit has to be stopped by name, and it has to be
        // stopped AFTER the avatar is seated, which is why this lives
        // here and not next to llSitTarget.
        llStopAnimation("sit");
        llStartAnimation(gPose);
    }

    on_rez(integer start)
    {
        llResetScript();
    }
}

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