Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Timeless Linked Door

DancesWithRobots Soyer
Registered User
Join date: 7 Apr 2006
Posts: 701
01-06-2009 18:07
From: followmeimthe Piedpiper
Hi, I've used this great script on normal doors with no probs. However now I want to get a train to activate a semaphore signal, with the signal-timeless script listening on a channel other than 0. The train gives out the signal perfectly but the script refuses to respond. Does it only work with avatars?? What do I need to do? Help please.


At the risk of necroposting. . .

Replacing the three instances of llListen(channel,"",llGetOwner(),"";) with llListen(channel,"",NULL_KEY,"";) will get it to listen to other prims. Not sure I'd want to use it as a door in that configuration tho.

Also, you'll probably want to change listenchannel to another number, and have the train shout on that channel.
_____________________
"Two lives I have.
One life I live. One life I dream.
In dreams I remember the better in me."
xanadu Kuhn
Registered User
Join date: 5 Mar 2007
Posts: 3
01-07-2009 09:32
it was a bad day for scripting apparently
it worked as soon as i got on
today
Jacquelyn Carfield
Registered User
Join date: 20 Oct 2009
Posts: 1
Multiple Prim Doors or Drawers
01-28-2010 11:16
Okay- I'm feeling really stupid right about now. I have limited knowledge on scripting experience, so the code is giving me a major headache. That having been said, for a Multiprim Door (or Drawer in this case) how do you get the linkset to work on this script? This particular 'door' has 5 prims that need to open and close together when clicked. Any assistance on this is greatly appreciated.

Thank you,

Jacque

From: Vida Orenstein
Here is a multi prims version modified from Yabu's post(#46)

The changes are:
- Removed Scaling and original door API
- Add doorSetID and Sound Enable

This script uses LLMessageLinked instead of some animator, so its only useful for doors with less prims (I have one with 10..)
You need to insert a script in every door prim to make them work.

If you have 1+ multi prim doors in a linked set, each doorset need to have a unique doorSetID. And it's better to enable sound for only one prim in each doorset. (unless you like another way.)

The door prims will toggle together on click, the one little bug I found is that if you say open/close to the door in a position where only some prims hears you, the internal open/closed status of each script can go out of sync. You can reset it by walk close and say "close" or just wait for auto close.

Cheers.

//------------------------------------------------------
// Timeless Linked Door Script by Timeless Prototype
//------------------------------------------------------

//======================================================
// Modified by Vida Orenstein (Jun 2008)
// Modify for multi prim door using link message.
// Removed scaling and the original Door API.
// Add doorSetID and SoundEnable
// If you have multi prim door in a linked set, they need
// to have the same doorSetID, and only enable one sound
// (or they will play the same sound together, LOL)
//======================================================
// Modified by Yabu Kurosawa (feb 2008)
// As of server version 1.19.0, the length of the object
// name is always truncated to 63 characters, the length of the
// description to 127 characters. See also:
// http://blog.secondlife.com/2008/02/01/scripters-object-name-and-description-changes/
// The original script exceeds the maximum name length.
// This problem is solved by compressing the 20 float
// values into 5-character strings and storing them all
// in the description field. Total string length is 105.
//======================================================


// The original version of this script can always be found
// in the Library section of the wiki:
// http://www.secondlife.com/badgeo/
// This script is free to use, but whereever it is used
// the SCRIPT's permissions MUST be set to:
// [x] Next owner can modify
// [x] Next owner can copy
// [x] Next owner can transfer
// [x] Allow anyone to copy
// [x] Share with group

//------------------------------------------------------
// USAGE INSTRUCTIONS FOR EVERYDAY USE:
//------------------------------------------------------
// Say the following commands on channel 0:
// 'unlock' - Unlocks all doors in range.
// 'lock' - Locks all doors in range and allows
// only the permitted users to open it.
// To open the door, either Touch it, Walk into it or
// say 'open' or say 'close'.

//------------------------------------------------------
// USAGE INSTRUCTIONS FOR BUILDERS:
//------------------------------------------------------
// 1. Copy and paste this script into the door prim and
// change the settings (see further down).
// 2. The door prim must be linked to at least one other
// prim (could be linked to the house for example).
// 3. The door prim MUST NOT be the root prim.
// 4. Use Edit Linked Parts to move, rotate and size the
// door prim for the closed state.
// 5. When ready, stand close to the door and say
// '/door closed' (this records the closed door
// position, rotation and size to the object's
// name and description).
// 6. Use the Edit Linked parts to move, rotate and size
// the door prim for the opened state.
// 7. When ready, stand close to the door and say
// '/door opened' (this records the opened door
// position, rotation and size).
// 8. Once recorded it will not accept these commands
// again. If you do need to redo the settings then
// delete the Description of the door prim
// (these are where the position information is
// stored), and then follow the steps above again.

//------------------------------------------------------
// Change these settings to suit your needs.
//------------------------------------------------------
// To mute any/all of the sounds set the sound string(s)
// to "" (empty string).
// To get the UUID of a sound, right click on the sound
// in your inventory and choose "Copy Asset UUID", then
// paste the UUID in here.

string doorOpenSound = "cb340647-9680-dd5e-49c0-86edfa01b3ac";
string doorCloseSound = "e7ff1054-003d-d134-66be-207573f2b535";
string confirmedSound = "69743cb2-e509-ed4d-4e52-e697dc13d7ac";
string accessDeniedSound = "58da0f9f-42e5-8a8f-ee51-4fac6c247c98";
string doorBellSound = "ee871042-e272-d8ec-3d40-0b0cb3371346"; // Setting to empty stops door announcements too.
float autoCloseTime = 120.0; // 0 seconds to disable auto close.
integer allowGroupToo = TRUE; // Set to FALSE to disallow same group access to door.
list allowedAgentUUIDs = ["8efecbac-35de-4f40-89c1-2c772b83cafa"]; // Comma-separated, quoted list of avatar UUIDs who are allowed access to this door.
integer listenChannel = 0;

string doorSetID = "door1"; // Door groupID, unique in linked set
integer SoundEnable = 1; // Sound enable, set to 1 for only 1 prim in the door group

//------------------------------------------------------
// Leave the rest of the settings alone, these are
// handled by the script itself.
//------------------------------------------------------
integer isLocked = FALSE; // Only when the door is locked do the permissions apply.
integer isOpen = TRUE;
vector openPos = ZERO_VECTOR;
rotation openRot = ZERO_ROTATION;
vector closedPos = ZERO_VECTOR;
rotation closedRot = ZERO_ROTATION;
key openerKey = NULL_KEY;
key closerKey = NULL_KEY;
integer isSetup = FALSE;
integer listenHandle = 0;
string avatarName = "";

// code string used for the parameter encoding/decoding
string code68 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@$#&!?";

mySayName(integer channel, string objectName, string message)
{
string name = llGetObjectName();
llSetObjectName(objectName);
llSay(0, "/me " + message);
llSetObjectName(name);
}

mySay(integer channel, string message)
{
string name = llGetObjectName();
llSetObjectName("Door";);
llSay(0, message);
llSetObjectName(name);
}

myOwnerSay(string message)
{
string name = llGetObjectName();
llSetObjectName("Door";);
llOwnerSay(message);
llSetObjectName(name);
}

mySoundConfirmed()
{
if (confirmedSound != "" && SoundEnable == 1)
{
llTriggerSound(confirmedSound, 1.0);
}
}

mySoundAccessDenied()
{
if (accessDeniedSound != "" && SoundEnable == 1)
{
llTriggerSound(accessDeniedSound, 1.0);
}
}

myGetDoorParams()
{
isSetup = FALSE;
if (llSubStringIndex(llGetObjectDesc(), "door:";) == 0)
{
string s = llGetObjectDesc();
integer k = 5;

openPos.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openPos.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openPos.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;

openRot.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
openRot.s = decode_float( llGetSubString(s,k,k+4) ); k += 5;

closedPos.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedPos.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedPos.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;

closedRot.x = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.y = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.z = decode_float( llGetSubString(s,k,k+4) ); k += 5;
closedRot.s = decode_float( llGetSubString(s,k,k+4) ); k += 5;

isSetup = TRUE;
}
else
{
myOwnerSay("The door prim's description is empty of has invalid syntax. Delete the door prim's description and setup the door prim again.";);
}

}

mySetDoorParams(vector openPos, rotation openRot, vector closedPos, rotation closedRot)
{
string s = "door:";

s += encode_float(openPos.x);
s += encode_float(openPos.y);
s += encode_float(openPos.z);

s += encode_float(openRot.x);
s += encode_float(openRot.y);
s += encode_float(openRot.z);
s += encode_float(openRot.s);

s += encode_float(closedPos.x);
s += encode_float(closedPos.y);
s += encode_float(closedPos.z);

s += encode_float(closedRot.x);
s += encode_float(closedRot.y);
s += encode_float(closedRot.z);
s += encode_float(closedRot.s);

llSetObjectDesc(s);

isSetup = TRUE;
mySay(0,"Parameters are stored";);
}

integer myPermissionCheck(key id)
{
integer hasPermission = FALSE;
if (isLocked == FALSE)
{
hasPermission = TRUE;
}
else if (llGetOwnerKey(id) == llGetOwner())
{
hasPermission = TRUE;
}
else if (allowGroupToo == TRUE && llSameGroup(id))
{
hasPermission = TRUE;
}
else if (llListFindList(allowedAgentUUIDs, [(string)id]) != -1)
{
hasPermission = TRUE;
}
return hasPermission;
}

myOpenDoor()
{
isOpen = FALSE;
myToggleDoor();
}

myCloseDoor()
{
isOpen = TRUE;
myToggleDoor();
}

myToggleDoor()
{
if (isSetup == FALSE)
{
myOwnerSay("The door prim has not been configured yet. Please read the usage instructions in the door script.";);
}
else if (llGetLinkNumber() == 0 || llGetLinkNumber() == 1)
{
myOwnerSay("The door prim must be linked to at least one other prim and the door prim must not be the root prim";);
}
else
{
isOpen = !isOpen;
if (isOpen)
{
if (doorBellSound != "" && SoundEnable == 1)
{
llTriggerSound(doorBellSound, 1.0);
if (avatarName != "";)
{
mySayName(0, avatarName, "is at the door.";);
avatarName = "";
}
}
if (doorOpenSound != "" && SoundEnable == 1)
{
llTriggerSound(doorOpenSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, openPos, PRIM_ROTATION, ZERO_ROTATION * openRot / llGetRootRotation() ]);
}
else
{
if (doorCloseSound != "" && SoundEnable == 1)
{
llTriggerSound(doorCloseSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, closedPos, PRIM_ROTATION, ZERO_ROTATION * closedRot / llGetRootRotation() ]);
}

llSetTimerEvent(0.0);
if (isOpen == TRUE && autoCloseTime != 0.0)
{
llSetTimerEvent(autoCloseTime);
}
}
}

//==========================================================================
// encode a float with 7 digits precision into a 5-character string
// minimum=1e-31, maximum=1e+31
// example: 1.234567 --> "hAM70"
//==========================================================================

string encode_float(float value)
{
integer neg = 0;
integer exp = 0;
integer k = 0;
integer i;
integer n;
string s;

// get sign, make value positive
if( value < 0 )
{
neg = 1;
value = -value;
}

// scale value to 7 digits before decimal dot
if( value > 0 )
{
if( value > 1e31 ) value = 1e31;
if( value < 1e-31) value = 1e-31;
while( value >= 10000000 )
{
exp += 1;
value = value / 10;
}
while( value < 1000000 )
{
exp -= 1;
value = value * 10;
}
}

// round to integer, discard decimals
k = (integer)(value+0.5);

// encode exponent and sign into integer (should fit into 32 bit)
k = k*64 + (exp+38);
k = k*2 + neg;

// encode integer into string
s = "";
for( i=0; i<5; i++ )
{
n = k % 68;
k = k / 68;
s = llGetSubString(code68,n,n) + s;
}

return s;
}

//==========================================================================
// decode a 5-character string into a float with 7 digits precision
// example: "hAM70" --> 1.234567
//==========================================================================

float decode_float(string s)
{
integer k = 0;
integer i;
integer neg;
float value;
integer exp;

// decode string into integer
for( i=0; i<5; i++ )
{
k = k*68 + llSubStringIndex(code68,llGetSubString(s,i,i));
}

// extract sign and exponent
neg = k % 2;
k = k/2;

exp = k % 64 - 38;
k = k/64;

// convert into float
value = (float)k;

// scale according to exponent
while( exp > 0 )
{
value = value * 10;
exp -= 1;
}
while( exp < 0 )
{
value = value / 10;
exp += 1;
}

// insert sign
if( neg ) value = -value;

return value;
}

default
{
state_entry()
{
listenHandle = llListen(listenChannel, "", NULL_KEY, "";);
myGetDoorParams();
}

touch_start(integer total_number)
{
if (myPermissionCheck(llDetectedKey(0)) == TRUE)
{
avatarName = llDetectedName(0);
myToggleDoor();
llMessageLinked(LINK_ALL_OTHERS, 255, "cmd|door|doToggle", doorSetID);
}
else
{
mySoundAccessDenied();
}
}

timer()
{
myCloseDoor();
}

link_message(integer sender_num, integer num, string str, key id)
{
if (id == doorSetID)
{
if (str == "cmd|door|doToggle";)
{
myToggleDoor();
}
}
}

listen(integer channel, string name, key id, string message)
{
// Performance note: it's quicker to compare the strings than to compare
// permissions each time anyone says anything on this channel.
if (message == "open";)
{
if (myPermissionCheck(id) == TRUE)
{
// Only open the door if the person is quite close to this door.
openerKey = id;
closerKey = NULL_KEY;
avatarName = name;
llSensor(name, id, AGENT, 5.0, TWO_PI);
}
else
{
mySoundAccessDenied();
}
}
else if (message == "close";)
{
if (myPermissionCheck(id) == TRUE)
{
openerKey = NULL_KEY;
closerKey = id;
avatarName = name;
// Only close the door if the person is quite close to this door.
llSensor(name, id, AGENT, 5.0, TWO_PI);
}
else
{
mySoundAccessDenied();
}
}
else if (message == "lock";)
{
if (myPermissionCheck(id) == TRUE)
{
isLocked = TRUE;
mySoundConfirmed();
}
else
{
mySoundAccessDenied();
}
}
else if (message == "unlock";)
{
if (myPermissionCheck(id) == TRUE)
{
isLocked = FALSE;
mySoundConfirmed();
}
else
{
mySoundAccessDenied();
}
}
else if (message == "/door opened" && llSubStringIndex(llGetObjectDesc(), "door:";) == -1)
{
if (llGetOwnerKey(id) == llGetOwner())
{
mySoundConfirmed();
openPos = llGetLocalPos();
openRot = llGetLocalRot();
isOpen = TRUE;
if (! (closedPos == ZERO_VECTOR && closedRot == ZERO_ROTATION))
{
mySetDoorParams(openPos, openRot, closedPos, closedRot );
}
}
else
{
mySoundAccessDenied();
}
}
else if (message == "/door closed" && llSubStringIndex(llGetObjectDesc(), "door:";) == -1)
{
if (llGetOwnerKey(id) == llGetOwner())
{
mySoundConfirmed();
closedPos = llGetLocalPos();
closedRot = llGetLocalRot();
isOpen = FALSE;
if (! (openPos == ZERO_VECTOR && openRot == ZERO_ROTATION ))
{
mySetDoorParams(openPos, openRot, closedPos, closedRot);
}
}
else
{
mySoundAccessDenied();
}
}
}

sensor(integer num_detected)
{
if (openerKey != NULL_KEY)
{
integer i;
for (i = 0; i < num_detected; i++)
{
if (llDetectedKey(i) == openerKey && myPermissionCheck(llDetectedKey(i)) == TRUE)
{
myOpenDoor();
}
}
openerKey = NULL_KEY;
}
else
{
integer i;
for (i = 0; i < num_detected; i++)
{
if (llDetectedKey(i) == closerKey && myPermissionCheck(llDetectedKey(i)) == TRUE)
{
myCloseDoor();
}
}
closerKey = NULL_KEY;
}
}

//------------------------------------------------------
// Uncomment the following code if you particularly want
// collisions to affect the door state.
//------------------------------------------------------

// collision_start(integer num_detected)
// {
// integer i;
// for (i = 0; i < num_detected; i++)
// {
// if (myPermissionCheck(llDetectedKey(i)) == TRUE)
// {
// avatarName = llDetectedName(i);
// myOpenDoor();
// }
// else if (llDetectedType(i) & AGENT)
// {
// mySoundAccessDenied();
// }
// }
// }

} // End of default state and end of script.
1 2 3 4