Difference between revisions of "Smooth Sliding Door"

From Second Life Wiki
Jump to navigation Jump to search
(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...')
 
Line 15: Line 15:
// by SimonT Quinnell  
// by SimonT Quinnell  
// 11/07/2009
// 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.
// NOTE: If you are going to reposition the door, do it while the door is closed.
Line 31: Line 29:
// ********************************************************************
// ********************************************************************


// NOTE: All of these constants can be set in the contained notecard
// Movement Constants
// Movement Constants
vector      OFFSET = <-2.0, 0.0, 0.0>;      // Directional offset for moving the door
vector      OFFSET = <-2.0, 0.0, 0.0>;      // Directional offset for moving the door
Line 46: Line 43:
// Misc. Constants
// Misc. Constants
float      MAX_DISTANCE = 10.00;          // Maximum distance the touching avatar can be away  
float      MAX_DISTANCE = 10.00;          // Maximum distance the touching avatar can be away  
integer    DEBUG = FALSE;




Line 58: Line 54:
vector      vTargetPos;
vector      vTargetPos;
integer    bOpen = FALSE;
integer    bOpen = FALSE;
integer    bMoving = FALSE;


// internals for reading notecards
string      strNotecard;
integer    intLine1;
key        keyConfigQueryhandle;                 
key        keyConfigUUID;


// ********************************************************************
// ********************************************************************
// Functions
// 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;
}




Line 137: Line 92:
      
      
     // Set Door Physical and move it
     // Set Door Physical and move it
    bMoving = TRUE;
     llSetStatus(STATUS_PHANTOM, TRUE);
     llSetStatus(STATUS_PHANTOM, TRUE);
     llSetStatus(STATUS_PHYSICS, TRUE);
     llSetStatus(STATUS_PHYSICS, TRUE);
Line 146: Line 102:
{             
{             
     state_entry()
     state_entry()
     {
     {   // Initial conditions
        debug("STATE:default");
         rRot = llGetRot();
        LoadNotecard();
         vPosition = llGetPos();
    }
     }  
   
    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)
     touch_start(integer num_detected)
Line 208: Line 112:
         float      distance = llVecDist(llGetPos(),llDetectedPos(0));
         float      distance = llVecDist(llGetPos(),llDetectedPos(0));


         if (distance < MAX_DISTANCE)
         if (distance < MAX_DISTANCE && !bMoving) MoveDoor();
        {
            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()
     timer()
     {
     {
         // Clean up Position
         // Clean up Position
        bMoving = FALSE;
        llSetTimerEvent(0.0);
         llSetStatus(STATUS_PHYSICS, FALSE);
         llSetStatus(STATUS_PHYSICS, FALSE);
         llSetStatus(STATUS_PHANTOM, FALSE);         
         llSetStatus(STATUS_PHANTOM, FALSE);         
         llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]);         
         llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]);         
       
        state stopped;
     }
     }
}</lsl>
}</lsl>

Revision as of 22:33, 10 July 2009

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 // // 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 // ********************************************************************

// 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


// ******************************************************************** // Variables // ********************************************************************

vector vPosition; rotation rRot; float omega=0.0; vector vTargetPos; integer bOpen = FALSE; integer bMoving = FALSE;


// ******************************************************************** // Functions // ********************************************************************


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
   bMoving = TRUE;
   llSetStatus(STATUS_PHANTOM, TRUE);
   llSetStatus(STATUS_PHYSICS, TRUE);
   llMoveToTarget(vTargetPos,omega);

}


default {

   state_entry()
   {   // Initial conditions
       rRot = llGetRot();
       vPosition = llGetPos();
   }    
       
   touch_start(integer num_detected)
   {
       key         keyTouchingAvatar = llDetectedKey(0);
       float       distance = llVecDist(llGetPos(),llDetectedPos(0));
       if (distance < MAX_DISTANCE && !bMoving) MoveDoor();
   } 
       
   timer()
   {
       // Clean up Position
       bMoving = FALSE;
       llSetTimerEvent(0.0);
       llSetStatus(STATUS_PHYSICS, FALSE);
       llSetStatus(STATUS_PHANTOM, FALSE);         
       llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]);        
   }

}</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