Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Timeless Linked Door

ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
02-02-2007 00:00
255 is not likely to be the link number. They start from the root as "1". You may have to alter the door code to ignore the num value if that door is the only one in the set.
David DiPrima
Registered User
Join date: 29 Sep 2006
Posts: 15
door lock
04-18-2007 15:35
Firstly, this is the best door script in the history of door scripts and is in fact called "worldsbestdoorscript" in my inventory.

I'm having only one issue thus far and that is locking the door when 'access list' is set to TRUE. When I do that I get the 'unable to comply' sound, but when I set it to FALSE all is well. It's very possible I'm missing something here, but I have only so much hair to rip before I figure it out lol.
Amore Lykin
Registered User
Join date: 30 Jul 2007
Posts: 1
10-09-2007 13:09
Im having the same problem David is. When I set the accesslist to True, the access list itself actually works, but I cannot lock or unlock the door. Its as if its permalocked unless you are on the access list. Is this working as intended?
Ania Babii
Registered User
Join date: 7 May 2007
Posts: 1
Problems with this script
11-12-2007 21:31
I've recently tried to use this script again, and while it worked fine the first time, i cannot seem to get it to work at all this time, when I type in /door closed or /door open it doesn't seem to do anything, it doesn't change the object or description name. It does seem to 'hear' commands but of course none work since it isn't set up. Any advice would be appreciated.
Miles Beck
MilesBeck.com
Join date: 20 Mar 2007
Posts: 537
Help
02-01-2008 14:57
Like many other residents, I've used this script dozens of times. I appreciate the work Timeless put into it.

With LL's changes of Jan. 31, 2008, scripts can no longer store more than 63 characters in the name field or 127 characters in the description. In items I've made that include Timeless' script, it puts more than 63 characters in the name field. The script will work, but resetting the script breaks it.

Can someone please post a workaround? I realize people have proposed ideas in JIRA for new features to compensate for the recent change, but we all know how long that may take to be implemented. In the meantime, what can be done to make this great script workable again?
Timeless Prototype
Humble
Join date: 14 Aug 2004
Posts: 216
02-01-2008 15:40
From: Miles Beck
Like many other residents, I've used this script dozens of times. I appreciate the work Timeless put into it.

With LL's changes of Jan. 31, 2008, scripts can no longer store more than 63 characters in the name field or 127 characters in the description. In items I've made that include Timeless' script, it puts more than 63 characters in the name field. The script will work, but resetting the script breaks it.

Can someone please post a workaround? I realize people have proposed ideas in JIRA for new features to compensate for the recent change, but we all know how long that may take to be implemented. In the meantime, what can be done to make this great script workable again?

Hmmm, Lindens biting the hand that feeds them again I see. :mad:
_____________________
Tyken Hightower
Automagical
Join date: 15 Feb 2006
Posts: 472
02-01-2008 16:00
From: Timeless Prototype
Hmmm, Lindens biting the hand that feeds them again I see. :mad:

It's a security and content loss issue, not much to be done there.

Just taking a quick glance, is there any reason why you'd need to store data in the name/description besides to make room for a larger access list? The script itself has 10k free memory when I first drop it into a prim, at least.. If you were interested in shaving memory, particularly for the access list, use a CSV string instead of a list to store the UUID's allowed to access the door. That would already save a ton by preventing it from wasting extra space.
_____________________
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-01-2008 16:55
funny I can't even find a copy of this script anymore.... so I have no idea what it was using the description field to store...
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Tyken Hightower
Automagical
Join date: 15 Feb 2006
Posts: 472
02-01-2008 16:57
From: Void Singer
funny I can't even find a copy of this script anymore.... so I have no idea what it was using the description field to store...

It's on the lslwiki.net script library, I think.

Edit: Here it is.

http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryTimelessLinkedDoor
_____________________
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-01-2008 17:07
actually I found it on page 2...

so it used the name and description to store the open and closed states of the doors position, rotation, and scale.

I think all of that could be easily eliminated by storing them in the script, and really not hurt the ability to store access lists. description probably isn't even flling out, just name.

all that really needs stored is the default state, and what changes to apply, which could probably all fit in the description still. then again they could also all fit in globals or a notecard....
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Henry Grumiaux
Registered User
Join date: 23 Jan 2007
Posts: 142
02-01-2008 19:19
From: Miles Beck
Like many other residents, I've used this script dozens of times. I appreciate the work Timeless put into it.

With LL's changes of Jan. 31, 2008, scripts can no longer store more than 63 characters in the name field or 127 characters in the description. In items I've made that include Timeless' script, it puts more than 63 characters in the name field. The script will work, but resetting the script breaks it.

Can someone please post a workaround? I realize people have proposed ideas in JIRA for new features to compensate for the recent change, but we all know how long that may take to be implemented. In the meantime, what can be done to make this great script workable again?


Miles, use this script instead....this is a modified version that I made...
Instead write to the name and description on the prim...this will appear on the chat window 2 parameters to put in a notecard...After you create the notecard and put into the prim...All is ready ;)

Ok, this is not exactly a very clean solution for this problem, I know...but it's a quick way to solve, indeed....I hope this can help ya !

ty

CODE


//------------------------------------------------------
// Timeless Linked Door Script by Timeless Prototype
//------------------------------------------------------
// The latest 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 Name and Description of the door prim
// (these are where the position information is
// stored), and then follow the steps above again.
// Note: deleting the object name won't save, so set
// the object name to 'Object' to reset the object
// name.

//------------------------------------------------------
// 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;
key kQuery;
integer iLine = 0;

//------------------------------------------------------
// 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 openScale = ZERO_VECTOR;
vector closedPos = ZERO_VECTOR;
rotation closedRot = ZERO_ROTATION;
vector closedScale = ZERO_VECTOR;
key openerKey = NULL_KEY;
key closerKey = NULL_KEY;
integer isSetup = FALSE;
integer listenHandle = 0;
string avatarName = "";
string pars_opened;
string pars_closed;


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 != "")
{
llTriggerSound(confirmedSound, 1.0);
}
}

mySoundAccessDenied()
{
if (accessDeniedSound != "")
{
llTriggerSound(accessDeniedSound, 1.0);
}
}
myCheckVars()
{
if (llSubStringIndex(pars_closed, "door;") == 0 && llSubStringIndex(pars_opened, "door;") == 0)
{
llOwnerSay("Plz, create a notecard and paste the following code at the notecard.After saved, put this into the same prim of this script: \nopened=" + pars_opened + " \nclosed=" + pars_closed);
}
}
myGetDoorParams()
{
isSetup = FALSE;
if (llSubStringIndex(pars_closed, "door;") == 0 && llSubStringIndex(pars_opened, "door;") == 0)
{
list nameWords = llParseString2List(pars_opened, [";"], []);
list descWords = llParseString2List(pars_closed, [";"], []);
if (llGetListLength(nameWords) != 4 || llGetListLength(descWords) != 4)
{
myOwnerSay("The door prim's name and/or description has invalid syntax and/or number of parameters. Delete the door prim's name and description and setup the door prim again.");
}
else
{
openPos = (vector)llList2String(nameWords, 1);
openRot = (rotation)llList2String(nameWords, 2);
openScale = (vector)llList2String(nameWords, 3);
closedPos = (vector)llList2String(descWords, 1);
closedRot = (rotation)llList2String(descWords, 2);
closedScale = (vector)llList2String(descWords, 3);
isSetup = TRUE;
}
}
}

mySetDoorParams(vector openPos, rotation openRot, vector openScale, vector closedPos, rotation closedRot, vector closedScale)
{
pars_opened = "door;" +
(string)openPos + ";" +
(string)openRot + ";" +
(string)openScale;
pars_closed = "door;" +
(string)closedPos + ";" +
(string)closedRot + ";" +
(string)closedScale;

isSetup = TRUE;
}

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 != "")
{
llTriggerSound(doorBellSound, 1.0);
if (avatarName != "")
{
mySayName(0, avatarName, "is at the door.");
avatarName = "";
}
}
if (doorOpenSound != "")
{
llTriggerSound(doorOpenSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, openPos, PRIM_ROTATION, ZERO_ROTATION * openRot / llGetRootRotation(), PRIM_SIZE, openScale ]);
// Door API.
llMessageLinked(LINK_SET, 255, "cmd|door|opened", NULL_KEY);
}
else
{
if (doorCloseSound != "")
{
llTriggerSound(doorCloseSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, closedPos, PRIM_ROTATION, ZERO_ROTATION * closedRot / llGetRootRotation(), PRIM_SIZE, closedScale ]);
// Door API.
llMessageLinked(LINK_SET, 255, "cmd|door|closed", NULL_KEY);
}

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

default
{
changed(integer change) { if (change & CHANGED_INVENTORY ) { llResetScript(); }}
state_entry()
{
listenHandle = llListen(listenChannel, "", NULL_KEY, "");
kQuery = llGetNotecardLine(llGetInventoryName(INVENTORY_NOTECARD, 0), iLine);
}
dataserver(key query_id, string data)
{
if (data != EOF)
{
list fdc = llParseString2List(data, ["="], []);
string fdc_a = llList2String(fdc, 0);
if (fdc_a =="opened")
{
pars_opened = llList2String(fdc, 1);
}
if (fdc_a =="closed")
{
pars_closed = llList2String(fdc, 1);
}
iLine++;
kQuery = llGetNotecardLine(llGetInventoryName(INVENTORY_NOTECARD, 0), iLine);
}
else
{
myGetDoorParams();
}
}

touch_start(integer total_number)
{
if (myPermissionCheck(llDetectedKey(0)) == TRUE)
{
avatarName = llDetectedName(0);
myToggleDoor();
}
else
{
mySoundAccessDenied();
}
}

timer()
{
myCloseDoor();
}

link_message(integer sender_num, integer num, string str, key id)
{
// Door API. The API is here in case you want to create PIN entry keypads or whatever.
if (num == llGetLinkNumber())
{
if (str == "cmd|door|doOpen")
{
myOpenDoor();
}
else if (str == "cmd|door|doClose")
{
myCloseDoor();
}
}
if (str == "cmd|door|discover")
{
llMessageLinked(LINK_SET, 255, "cmd|door|discovered|" + (string)llGetKey(), id);
}
}

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(llGetObjectName(), "door;") == -1)
{
if (llGetOwnerKey(id) == llGetOwner())
{
mySoundConfirmed();
openPos = llGetLocalPos();
openRot = llGetLocalRot();
openScale = llGetScale();
isOpen = TRUE;
if (! (closedPos == ZERO_VECTOR && closedRot == ZERO_ROTATION && closedScale == ZERO_VECTOR))
{
mySetDoorParams(openPos, openRot, openScale, closedPos, closedRot, closedScale);
myCheckVars();
}
}
else
{
mySoundAccessDenied();
}
}
else if (message == "/door closed" && llSubStringIndex(llGetObjectDesc(), "door;") == -1)
{
if (llGetOwnerKey(id) == llGetOwner())
{
mySoundConfirmed();
closedPos = llGetLocalPos();
closedRot = llGetLocalRot();
closedScale = llGetScale();
isOpen = FALSE;
if (! (openPos == ZERO_VECTOR && openRot == ZERO_ROTATION && openScale == ZERO_VECTOR))
{
mySetDoorParams(openPos, openRot, openScale, closedPos, closedRot, closedScale);
myCheckVars();
}
}
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.


Miles Beck
MilesBeck.com
Join date: 20 Mar 2007
Posts: 537
02-01-2008 19:25
From: Henry Grumiaux
Miles, use this script instead....this is a modified version that I made...
Instead write to the name and description on the prim...this will appear on the chat window 2 parameters to put in a notecard...After you create the notecard and put into the prim...All is ready ;)

Ok, this is not exactly a very clean solution for this problem, I know...but it's a quick way to solve, indeed....I hope this can help ya !
Thank you, Henry!
Min Fairweather
Registered User
Join date: 21 Feb 2007
Posts: 202
02-02-2008 01:57
Awesome! Thanks :)
Timeless Prototype
Humble
Join date: 14 Aug 2004
Posts: 216
02-02-2008 03:09
From: Tyken Hightower
It's a security and content loss issue, not much to be done there.

Just taking a quick glance, is there any reason why you'd need to store data in the name/description besides to make room for a larger access list? The script itself has 10k free memory when I first drop it into a prim, at least.. If you were interested in shaving memory, particularly for the access list, use a CSV string instead of a list to store the UUID's allowed to access the door. That would already save a ton by preventing it from wasting extra space.

FYI. The only reason for storing it in object name and description is so that when a builder/user Shift Drags a copy of the build the data is not lost in the script reset.
_____________________
Timeless Prototype
Humble
Join date: 14 Aug 2004
Posts: 216
02-02-2008 03:15
Also seen in blog comments:
DR Dahlgren's modifications
_____________________
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-02-2008 03:38
From: Timeless Prototype
FYI. The only reason for storing it in object name and description is so that when a builder/user Shift Drags a copy of the build the data is not lost in the script reset.

this becomes unnecessary if the door rotation/movement isn't based it's initial position or rotation (though can be slightly borked if you don't close the doors first when doing a shift+drag, easy to fix though, just edit the dorr rotation back to closed)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Henry Grumiaux
Registered User
Join date: 23 Jan 2007
Posts: 142
02-02-2008 08:02
In attachment the source code of the notecard version if someone need it.

ty
Galena Qi
Registered User
Join date: 9 Sep 2006
Posts: 249
02-02-2008 12:26
I couldn't get this notecard version to work. Are the commands still /door opened and /door closed? Please list the exact sequence of actions to obtain the parameters and load them into the notecard. Then let's revise the Builder's Instructions so that newbie scripters like me can figure it out in the future.
Miles Beck
MilesBeck.com
Join date: 20 Mar 2007
Posts: 537
02-02-2008 15:13
From: Galena Qi
I couldn't get this notecard version to work. Are the commands still /door opened and /door closed? Please list the exact sequence of actions to obtain the parameters and load them into the notecard. Then let's revise the Builder's Instructions so that newbie scripters like me can figure it out in the future.
Galena, It worked for me. Yes, you use the same commands as in the original Timeless Linked Door script: put the door in its closed position, then type "/door closed"; put the door in its opened position, and type "/door opened"

After you type "/door opened" you should see a message in chat. It will be helpful if you open your chat history window. Create a notecard, copy and paste the chat message into the notecard, save the notecard, and then put that notecard in the contents of the same prim that contains the script. It doesn't matter what you name the notecard.

If this isn't clear, please respond and I'll be happy to help.
Galena Qi
Registered User
Join date: 9 Sep 2006
Posts: 249
02-02-2008 16:41
I figured out what was wrong - the long prim description and name need to be deleted from the prim before the script will work. This fact needs to be added to the script or lots of people trying to modify old doors will get confused. Here's a revision that makes it clearer.


//------------------------------------------------------
// Timeless Linked Door Script by Timeless Prototype
//------------------------------------------------------
//------------------------------------------------------
// Notecard Version by Henry Grumiaux
//------------------------------------------------------
// The latest 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:
//------------------------------------------------------

// Note: If you are replacing an original Timeless Linked
// Door script with this notecard version, you need to delete
// the original script and the door prim name and description
// before beginning the steps below.

// 1. Copy and paste this script into the door prim.
// 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).
// 6. Use 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. Two lines of text will appear in Chat - open your Chat History
// window to see them. Copy these lines into a new, blank notecard.
// Save the notecard into your inventory.
// 9. Copy the notecard into the contents of the door prim.
// The door should now open and close at a touch.
Reno Katscher
Registered User
Join date: 2 Jun 2007
Posts: 18
02-03-2008 09:25
Fantastic script! I am using the notecard version since LL borked the other one.

I have made a set of curtains, and I would like to use a menu to change colors of the curtain and transparency. I have a menu that works to change textures on another object, but when I have both the door script and the menu script in the door, only the door script works. I am guess because they are both touch events.

Any pointers in the right direction? Do I need a seperate prim for the menu and use linked messages?

Thanks in advance!

Reno
Yabu Kurosawa
Registered User
Join date: 29 Jan 2007
Posts: 3
02-06-2008 11:13
OK, here's another replacement for the Timeless Door script. This one is a 100% compatible drop-in replacement for the original one (no notecards). The problem of exceeding the maximum length of the Name and Description fields is solved by compressing the 20 float values into 5-character strings and storing them all in the Description field (the Name field is not needed anymore). The total Description length is 105 and that should easily fit.

The encoding/decoding is not super efficient, but works fast enough for this purpose. If you want to use the encoding/decoding routines for other purposes (inter-prim communication for instance), some optimization might be worthwhile.
Yabu Kurosawa
Registered User
Join date: 29 Jan 2007
Posts: 3
02-06-2008 23:48
One more thing: for those who customized the original Timeless linked door script, here's a recipe for upgrading to my version:

1) replace myGetDoorParams() and mySetDoorParams()
2) add encode_float() and decode_float()
3) add string code68 = "..." (somewhere on top)
4) modify the two lines in the listen() section:
- if (message == "/door opened" ....
- if (message == "/door closed" ....

For the rest I didn't touch anything (I think...)
DR Dahlgren
Content Creator
Join date: 27 Aug 2006
Posts: 79
DED Update of Timeless Door Script
02-09-2008 20:19
Here is the update I have made available. I removed the scaling, no one I know used it, and converted the rotations to euler and stored them. That saved enough to continue to use the fields as they were previously. If you don't mind notecards, I have script for sale that works as a single door or door sets and multiple doors can be used in the same linkset without issue. DRD

// Modified 2-2-2008
// DR Dahlgren - Dahlgren Engineering and Design
// Removed Scale function and changed door coordinate data storage to work
// within name and description field length rules per Linden Labs
// adopted 2-1-2008 in V1.19 of the server code.

//------------------------------------------------------
// Timeless Linked Door Script by Timeless Prototype
//------------------------------------------------------
// The latest 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 Name and Description of the door prim
// (these are where the position information is
// stored), and then follow the steps above again.
// Note: deleting the object name won't save, so set
// the object name to 'Object' to reset the object
// name.

//------------------------------------------------------
// 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 = "9589df4c-ce1b-82bb-9ce6-35247d4a802b";
string doorCloseSound = "9589df4c-ce1b-82bb-9ce6-35247d4a802b";
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;


//------------------------------------------------------
// 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;
vector store_openRot;
rotation openRot = ZERO_ROTATION;
vector closedPos = ZERO_VECTOR;
vector store_closedRot;
rotation closedRot = ZERO_ROTATION;
key openerKey = NULL_KEY;
key closerKey = NULL_KEY;
integer isSetup = FALSE;
integer listenHandle = 0;
string avatarName = "";

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 != "";)
{
llTriggerSound(confirmedSound, 1.0);
}
}

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

myGetDoorParams()
{
isSetup = FALSE;
if (llSubStringIndex(llGetObjectDesc(), "d;";) == 0 && llSubStringIndex(llGetObjectName(), "d;";) == 0)
{
list nameWords = llParseString2List(llGetObjectName(), [";"], []);
list descWords = llParseString2List(llGetObjectDesc(), [";"], []);
if (llGetListLength(nameWords) != 3 || llGetListLength(descWords) != 3)
{
myOwnerSay("The door prim's name and/or description has invalid syntax and/or number of parameters. Delete the door prim's name and description and setup the door prim again.";);
}
else
{
openPos = (vector)llList2String(nameWords, 1);
store_openRot = (vector)llList2String(nameWords, 2);
openRot = llEuler2Rot(store_openRot);
closedPos = (vector)llList2String(descWords, 1);
store_closedRot = (vector)llList2String(descWords, 2);
closedRot = llEuler2Rot(store_closedRot);
isSetup = TRUE;
}
}
}

mySetDoorParams(vector openPos, rotation openRot, vector closedPos, rotation closedRot)
{
store_openRot = llRot2Euler(openRot);
store_closedRot = llRot2Euler(closedRot);
llSetObjectName("d;" +
(string)openPos + ";" +
(string)store_openRot);
llSetObjectDesc("d;" +
(string)closedPos + ";" +
(string)store_closedRot);
isSetup = TRUE;
}

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 != "";)
{
//llTriggerSound(doorBellSound, 1.0);
if (avatarName != "";)
{
//mySayName(0, avatarName, "is at the door.";);
avatarName = "";
}
}
if (doorOpenSound != "";)
{
llTriggerSound(doorOpenSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, openPos, PRIM_ROTATION, ZERO_ROTATION * openRot / llGetRootRotation()]);
// Door API.
llMessageLinked(LINK_SET, 255, "cmd|door|opened", NULL_KEY);
}
else
{
if (doorCloseSound != "";)
{
llTriggerSound(doorCloseSound, 1.0);
}
llSetPrimitiveParams([ PRIM_POSITION, closedPos, PRIM_ROTATION, ZERO_ROTATION * closedRot / llGetRootRotation()]);
// Door API.
llMessageLinked(LINK_SET, 255, "cmd|door|closed", NULL_KEY);
}

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

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

touch_start(integer total_number)
{
if (myPermissionCheck(llDetectedKey(0)) == TRUE)
{
avatarName = llDetectedName(0);
myToggleDoor();
}
else
{
mySoundAccessDenied();
}
}

timer()
{
myCloseDoor();
}

link_message(integer sender_num, integer num, string str, key id)
{
// Door API. The API is here in case you want to create PIN entry keypads or whatever.
if (num == llGetLinkNumber())
{
if (str == "cmd|door|doOpen";)
{
myOpenDoor();
}
else if (str == "cmd|door|doClose";)
{
myCloseDoor();
}
}
if (str == "cmd|door|discover";)
{
llMessageLinked(LINK_SET, 255, "cmd|door|discovered|" + (string)llGetKey(), id);
}
}

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(llGetObjectName(), "d;";) == -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(), "d;";) == -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.
Dioxide DeSantis
Registered User
Join date: 2 Feb 2007
Posts: 63
02-15-2008 15:25
Has anyone tried to make this script usable with a access notecard?
Its not all that user friendly to use the uuid all the time to change users on the door.
1 2 3 4