// ===================================================================== // 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(); } }