One Script, many doors: Difference between revisions
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
This script is my attempt at solving the massive amount of simple door scripts one can have in a sim ( | This script is my attempt at solving the massive amount of simple door scripts one can have in a sim (I removed about 110 door scripts in my sim using this system) | ||
It handle clockwise and counter clockwise door direction, a name based access control list, play sounds | It handle clockwise and counter clockwise door direction, a name based access control list, and play sounds | ||
HOW TO USE IT | HOW TO USE IT | ||
| Line 9: | Line 9: | ||
* All your doors must be linked to a root prim wich won't be a door. | * All your doors must be linked to a root prim wich won't be a door. | ||
* All the doors must be uniquely named | * All the doors must be uniquely named. | ||
* All the doors must have "left" or "right" in their description depending of the direction you want them to swing to. | * All the doors must have "left" or "right" in their description depending of the direction you want them to swing to. | ||
* In the root prim you will need 3 rezzable objects (simple cubes will do) named "open" , "close" and "lock" with, in them, the corresponding scripts (see at the bottom of the page) in order to play sounds at the right place. | * In the root prim you will need 3 rezzable objects (simple cubes will do) named "open" , "close" and "lock" with, in them, the corresponding scripts (see at the bottom of the page) in order to play sounds at the right place. | ||
* You need a configuration notecard called "config" | * You need a configuration notecard called "config" | ||
main door script: must be in the root prim of the door link set. | main door script: must be in the root prim of the door link set. | ||
| Line 377: | Line 370: | ||
} | } | ||
</lsl> | </lsl> | ||
Example "config" notecard: | |||
<lsl> | |||
//lines starting with "//" are ignored | |||
//Syntax: one line per door in the format door_name=user name,user name | |||
My fancy front door=Kyrah Abattoir | |||
My secret playroom door=Kyrah Abattoir,Timeless Prototype | |||
//of course if you want to lock a door from anybody you can set it to something like this: | |||
Mine entrance=condemned until further notice | |||
</lsl | |||
--[[User:Kyrah Abattoir|Kyrah Abattoir]] 18:46, 7 March 2010 (UTC) | --[[User:Kyrah Abattoir|Kyrah Abattoir]] 18:46, 7 March 2010 (UTC) | ||
Revision as of 12:10, 7 March 2010
This script is my attempt at solving the massive amount of simple door scripts one can have in a sim (I removed about 110 door scripts in my sim using this system)
It handle clockwise and counter clockwise door direction, a name based access control list, and play sounds
HOW TO USE IT
All your doors have to be one prim, typical cube with a path cut of 0.125 0.625 .
- All your doors must be linked to a root prim wich won't be a door.
- All the doors must be uniquely named.
- All the doors must have "left" or "right" in their description depending of the direction you want them to swing to.
- In the root prim you will need 3 rezzable objects (simple cubes will do) named "open" , "close" and "lock" with, in them, the corresponding scripts (see at the bottom of the page) in order to play sounds at the right place.
- You need a configuration notecard called "config"
main door script: must be in the root prim of the door link set. <lsl> /******************************************* Single script, linked, lockable, door system by Kyrah Abattoir
allow you to control many doors from a single core script, complete with sound projectors and name based access control!
- /
float autoclose_time = 30.0;//define how long the script will wait before closing a door. float activation_distance = 2.0;//define how long the script will wait before closing a door.
//This functions is from Nomad Padar, pretty awesome! //encode from vector to integer integer vec2int(vector v) {
integer x = (integer)(v.x); integer y = (integer)(v.y); integer z = (integer)(v.z); integer out; //Rounds to 0, .5, or 1.0 float delta = v.x-x; if((delta>.25) && (delta<.75)) out += 0x10000000; else if(delta>.75) out += 0x1; delta = v.y-y; if((delta>.25) && (delta<.75)) out += 0x20000000; else if(delta>.75) out += 0x100; delta = v.z-z; if((delta>.25) && (delta<.75)) out += 0x40000000; else if(delta>.75) out += 0x10000; out += x+(y<<8)+(z<<16); return out;
}
list door_names = [];//door list list door_num = [];//corresponding link numbers list door_closed_rot = [];//corresponding closed state rotation list door_direction = [];//wich direction the door spin open list door_open = [];//is the door open? list door_open_time = [];//when was it open? list door_acl = [];//who can open the door (by user id) list door_pos = [];//the position of the door
list user_indexes = [];//list of users (user ids)
integer is_active = FALSE;//if this is false the script ignore touches
recount_doors() { //this function recount the doors and record all the different door characteristics //only ran after script reset/when an object is linked/unlinked is_active = FALSE; llSetText("recounting doors...",<1,1,1>,1.0); integer prims = llGetNumberOfPrims();
integer i; for(i=2;i<=prims;i++) { key prim = llGetLinkKey(i); list tmp = llGetObjectDetails(prim,[OBJECT_NAME,OBJECT_DESC,OBJECT_ROT,OBJECT_POS]); string prim_name = llList2String(tmp,0); string prim_descr = llList2String(tmp,1); rotation prim_rot = (rotation)llList2String(tmp,2); vector prim_pos = (vector)llList2String(tmp,3);
door_num += [i]; door_names += [prim_name]; door_closed_rot += [prim_rot]; door_open += [FALSE]; door_open_time += [0]; if(prim_descr == "right") door_direction += [TRUE]; else door_direction += [FALSE]; door_acl += [""]; door_pos += [prim_pos]; } llSetText("...done!",<1,1,1>,1.0); reload_acl(); }
string config = "config";//name of the configuration file integer nLine = 0;//current line we are reading
//this function re read the config notecard and populate the //user list and acl table reload_acl() {
llSetText("reloading access controls...",<1,1,1>,1.0); is_active = FALSE; nLine = 0; //remove all acl integer i; for(i=0;i<llGetListLength(door_num);i++) door_acl = llListReplaceList(door_acl,[""],i,i);
user_indexes = []; llGetNotecardLine(config,nLine); }
//close a door (by index) using the stored rotation close(integer index) { integer linknum = llList2Integer(door_num,index);
rotation closed = llList2Rot(door_closed_rot,index); llSetLinkPrimitiveParams(linknum,[PRIM_ROTATION,closed]);
door_open = llListReplaceList(door_open,[FALSE],index,index); }
//close a door (by index) using the stored rotation and adding or substracting 90 degrees //on the Z world axis depending of the direction recorded for the door. //also record it's opening time (unix timestamp) open(integer index) { integer linknum = llList2Integer(door_num,index); rotation closed = llList2Rot(door_closed_rot,index); rotation open; if( llList2Integer(door_direction,index) ) open = llEuler2Rot(llRot2Euler(closed)+ (<0,0,90> *DEG_TO_RAD)); else open = llEuler2Rot(llRot2Euler(closed)+ (<0,0,-90> *DEG_TO_RAD)); llSetLinkPrimitiveParams(linknum,[PRIM_ROTATION,open]);
door_open_time = llListReplaceList(door_open_time,[llGetUnixTime()],index,index); door_open = llListReplaceList(door_open,[TRUE],index,index);
llSetTimerEvent(1.0); }
//those 3 functions rez a sound emitter with it's destination position encoded in integer play_open(vector pos) { llRezObject("open",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,vec2int(pos)); } play_close(vector pos) { llRezObject("close",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,vec2int(pos)); } play_lock(vector pos) { llRezObject("lock",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,vec2int(pos)); }
default
{
touch_start(integer total_number)
{
integer userid;
if(!is_active)
return;
//considering we MAY receive more than one touch at the same time since
//we can manage many doors.
for(userid=0;userid<total_number;userid++)
{
integer door_id = llDetectedLinkNumber(userid);
string clicker_name = llDetectedName(userid);
integer door_index = llListFindList(door_num,[door_id]);
if(door_index == -1)
return;//unknown door? do nothing
integer is_open = llList2Integer(door_open,door_index);
vector door_vec = llList2Vector(door_pos,door_index);
//we do not accept touches that are further away from activation_distance
if( llVecDist(door_vec,llDetectedPos(userid) )> activation_distance )
llInstantMessage(llDetectedKey(userid),"You can't use this from this distance.");
else
{
if(is_open)
{ //if the door is open, simply play sound and close it.
play_close(door_vec);
close(door_index);
}
else
{
string acl_string = llList2String(door_acl,door_index);
//if the acl string is empty for this door we simply open it
if(acl_string == "") //no specific locking
{ play_open(door_vec);
open(door_index);
}
else
{
//otherwise we lookup if the userid that correspond to the person who touched
//the door match any of the ones in the ACL string
integer user_index = llListFindList(user_indexes,[clicker_name]);
if(user_index == -1)//we don't even know this user? sure as hell there is no acl about him
play_lock(door_vec);
else
{
list acl_list = llParseString2List(acl_string,[","],[]);
if(llListFindList(acl_list,[(string)user_index]) != -1)
{
play_open(door_vec);
open(door_index);
}
else
play_lock(door_vec);
}
}
}
}
}
}
dataserver(key id,string data)
{
//notecard reading stuff
if(data != EOF)
{
if(data != "" && data != " " && llGetSubString(data,0,1) != "//")
{
list command_and_data = llParseString2List(data,["="],[]);
string door_name = llList2String(command_and_data,0);
string user_names_string = llList2String(command_and_data,1);
integer index = llListFindList(door_names,[door_name]);
if(index != -1)
{
list user_names_list = llParseString2List(user_names_string,[","],[]);
integer j;
list pre_acl_list;
for(j=0;j<llGetListLength(user_names_list);j++)
{
string user_name = llList2String(user_names_list,j);
integer index2 = llListFindList(user_indexes,[user_name]);
if( index2 == -1)
{
pre_acl_list += llGetListLength(user_indexes);
user_indexes += [user_name];
}
else
pre_acl_list += [index2];
}
string pre_acl_string = llDumpList2String(pre_acl_list,",");
door_acl = llListReplaceList(door_acl,[pre_acl_string],index,index);
}
}
nLine++;
llGetNotecardLine(config,nLine);
}
else
{
is_active = TRUE;
llOwnerSay("config reloaded");
llSetText((string)llGetFreeMemory()+"bits free",<.5,.5,.5>,.5);
}
}
state_entry()
{
recount_doors();
}
changed(integer change)
{
//if we detect an inventory change we reread the notecard
//if we detect a linkchange we reset the script and recount doors first
if( (change & CHANGED_INVENTORY) == CHANGED_INVENTORY)
reload_acl();
if( (change & CHANGED_LINK) == CHANGED_LINK)
llResetScript();
}
timer()
{
//timer will run once a second as long as at least one door is open.
if(llListFindList(door_open,[TRUE]) == -1)
{
llSetTimerEvent(0.0);
return;
}
integer i;
//each run of the timer we loop through the timestamps to check if one of them is too old
//(wich means we can force close the assossiated door
for(i=0;i<llGetListLength(door_open_time);i++)
{
integer is_open = llList2Integer(door_open,i);
integer time = llList2Integer(door_open_time,i);
if( is_open && ((time + autoclose_time) < llGetUnixTime()))
{
vector door_vec = llList2Vector(door_pos,i);
llRezObject("close",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,vec2int(door_vec));
close(i);
}
}
}
} </lsl>
Sound emitter script
You need this script in the 3 rezzable objects "open" "close" and "lock" in order to play your door sounds at the right place (At the time i wrote this , lsl doesn't allow yet to play sounds from an unscripted prim in a link set)
<lsl> string sound_to_play = "my door sound";// put your sound name/key here
//This functions is from Nomad Padar, pretty awesome! //decode from integer to vector vector int2vec(integer n) {
//0zyx ZZZZ ZZZZ ZZZZ YYYY YYYY XXXX XXXX return <n&0xFF, (n>>8)&0xFF, ((n>>16)&0xFF)> + <((n&0x10000000)!=0)*.5,((n&0x20000000)!=0)*.5,((n&0x40000000)!=0)*.5>;
}
default {
state_entry()
{
llSetStatus(STATUS_PHANTOM, TRUE);
llSetPrimitiveParams([PRIM_TEMP_ON_REZ, TRUE]);
}
on_rez(integer a)
{
if(a == 0)
return;
vector destination = int2vec(a);
integer i;
for(i=0 ; i<50 && (llGetPos() != destination) ; i++)
llSetPos(destination);
if(llGetPos() == destination)
llTriggerSound(sound_to_play,1.0);
llDie();
}
} </lsl> Example "config" notecard: <lsl> //lines starting with "//" are ignored //Syntax: one line per door in the format door_name=user name,user name
My fancy front door=Kyrah Abattoir My secret playroom door=Kyrah Abattoir,Timeless Prototype
//of course if you want to lock a door from anybody you can set it to something like this:
Mine entrance=condemned until further notice </lsl --Kyrah Abattoir 18:46, 7 March 2010 (UTC)