Smooth Sliding Door
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Smooth Sliding Door Script
Introduction
It really annoys me that there are so many bad looking doors out there that jerk around. While you can use llSetPos for a sliding door you have no control at what speed it moves. This sliding door script i created because i wanted to time my sliding door movements with the door sounds i had. It uses llMoveToTarget to move the door, with the door temporally turning phantom as it moves.
In laggy sims it will behave a little bit funky .. the door somtimes seeming to zoom off to the side as the door becomes a physical object. However, even with that defect it still looks much better IMHO
The Script
<lsl> // ******************************************************************** // // Basic Physical Sliding Door Script // by SimonT Quinnell // 11/07/2009 // // If a notecard is in the prim it will be read as a configuration notecard // // NOTE: If you are going to reposition the door, do it while the door is closed. // Otherwise it will try and use the old close position as a reference point. // // Licensed under the "OpenCollar License" // Ie. Licensed under the GPLv2, with the additional requirement that these scripts remain "full perms" in Second Life. // // ********************************************************************
// ********************************************************************
// CONSTANTS
// ********************************************************************
// NOTE: All of these constants can be set in the contained notecard // Movement Constants vector OFFSET = <-2.0, 0.0, 0.0>; // Directional offset for moving the door float OPENTIME = 3.5; // Time taken to open door float CLOSETIME = 3.5; // Time taken to close door
// Sound/volume to play on open and close, either a UUID or a name in the door contents
string OPENSOUND = "";
float OPENVOL = 1.0;
string CLOSESOUND = "";
float CLOSEVOL = 1.0;
// Misc. Constants float MAX_DISTANCE = 10.00; // Maximum distance the touching avatar can be away integer DEBUG = FALSE;
// ********************************************************************
// Variables
// ********************************************************************
vector vPosition; rotation rRot; float omega=0.0; vector vTargetPos; integer bOpen = FALSE;
// internals for reading notecards string strNotecard; integer intLine1; key keyConfigQueryhandle; key keyConfigUUID;
// ******************************************************************** // Functions // ********************************************************************
debug(string debug) {
if (DEBUG) llWhisper(0,"DEBUG:"+llGetScriptName()+":"+debug);
}
string CropName(string name) {// Crops avatar's name to first name
return llDeleteSubString(name,llSubStringIndex(name," "),llStringLength(name) - 1);
}
LoadNotecard() {
if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0) { // First notecard is used as the configuration notecard strNotecard = llGetInventoryName(INVENTORY_NOTECARD,0);
keyConfigQueryhandle = llGetNotecardLine(strNotecard, intLine1 = 0); keyConfigUUID = llGetInventoryKey(strNotecard); } else llOwnerSay("Door Configuration Notecard is missing!");
}
CheckVariable(string token, string data)
{
if (token == "offset") OFFSET = (vector)data; else if (token == "max_distance") MAX_DISTANCE = (float)data; else if (token == "open_time") OPENTIME = (float)data; else if (token == "close_time") CLOSETIME = (float)data; else if (token == "open_sound") OPENSOUND = data; else if (token == "open_volume") OPENVOL = (float)data; else if (token == "close_sound") CLOSESOUND = data; else if (token == "close_volume") CLOSEVOL = (float)data; else if (token == "debug") DEBUG = (integer)data;
}
MoveDoor() {
if(!bOpen) { // Initial conditions rRot = llGetRot(); vPosition = llGetPos(); // Target Position omega=OPENTIME/llVecDist(<0,0,0>,OFFSET); vTargetPos = vPosition+OFFSET*rRot; // Set the timer to cleanup position .. nesessary for laggy sims llSetTimerEvent(OPENTIME); bOpen = TRUE; if(OPENSOUND != "") llTriggerSound(OPENSOUND, OPENVOL); }else { // Target Position omega=CLOSETIME/llVecDist(<0,0,0>,OFFSET); vTargetPos = vPosition; // Set the timer to cleanup position .. nesessary for laggy sims llSetTimerEvent(CLOSETIME);
bOpen = FALSE; if(CLOSESOUND != "") llTriggerSound(CLOSESOUND, CLOSEVOL); } // Set Door Physical and move it llSetStatus(STATUS_PHANTOM, TRUE); llSetStatus(STATUS_PHYSICS, TRUE); llMoveToTarget(vTargetPos,omega);
}
default
{
state_entry() { debug("STATE:default"); LoadNotecard(); } touch_start(integer num_detected) { // Empty Touch State. Fixes problems with missing touch events } dataserver(key keyQueryId, string strData) { if (keyQueryId == keyConfigQueryhandle) { if (strData != EOF) { string strToken; strData = llStringTrim(strData, STRING_TRIM_HEAD); // Trim Whitespace if (llGetSubString (strData, 0, 0) != "#") // is it a comment? { integer s = llSubStringIndex(strData, "="); if(~s)//does it have an "=" in it? { strToken = llToLower(llStringTrim(llDeleteSubString(strData, s, -1), STRING_TRIM)); strData = llStringTrim(llDeleteSubString(strData, 0, s), STRING_TRIM); CheckVariable(strToken, strData); } } keyConfigQueryhandle = llGetNotecardLine(strNotecard, ++intLine1); } else { llOwnerSay("Done Reading Config Notecard"); state stopped; } } } changed(integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } }
}
state stopped
{
state_entry() { debug("STATE:stopped"); } touch_start(integer num_detected) { key keyTouchingAvatar = llDetectedKey(0); float distance = llVecDist(llGetPos(),llDetectedPos(0));
if (distance < MAX_DISTANCE) { state moving; } else llInstantMessage(keyTouchingAvatar, "You need to get a little closer to the door "+CropName(llKey2Name(keyTouchingAvatar))); } changed(integer change) { if (change & CHANGED_INVENTORY && llGetInventoryNumber(INVENTORY_NOTECARD) > 0) { state default; } }
}
state moving {
state_entry() { debug("STATE:moving"); MoveDoor(); } state_exit() { llSetTimerEvent(0.0); } touch_start(integer num_detected) { // Empty Touch State. Fixes problems with missing touch events } timer() { // Clean up Position llSetStatus(STATUS_PHYSICS, FALSE); llSetStatus(STATUS_PHANTOM, FALSE); llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]); state stopped; }
}</lsl>
Example Configuration Notecard
<lsl># Configuration Notecard for Physical Door
- Touching
max_distance = 10.0
- Door Action Details
offset = <3.5,0.0,0.0> open_time = 4.0 close_time = 4.0
- Door Sound Details
open_sound = open_volume = 1.0 close_sound = close_volume = 1.0</lsl>