Difference between revisions of "One Script, many doors"
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 11: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)