Smooth Sliding Door

From Second Life Wiki
Revision as of 23:15, 10 July 2009 by SimonT Quinnell (talk | contribs) (Created page with '{{LSL Header}} 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 f...')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

  1. Touching

max_distance = 10.0

  1. Door Action Details

offset = <3.5,0.0,0.0> open_time = 4.0 close_time = 4.0

  1. Door Sound Details

open_sound = open_volume = 1.0 close_sound = close_volume = 1.0</lsl>

See also