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>