User:Zai Lynch/Sandbox/LSL Goodies
IntroSo just for the record: I'm a complete LSL n00b. So don't expect much from this page. 'Cause I love the Open Source concept, I'd like to share some of my scripts with other SL Residents =)
Simple CountdownThis script displays a hovering countdown above the item it's placed in. Need to provide time difference between start and end of the countdown. Another implementation, needing date and time when the countdown is supposed to finish, can be found below.
llSetText(TEXT+"\n"+(string)(SECONDS/86400)+" days, " +(string)((SECONDS%86400)/3600)+" hours, " +(string)(((SECONDS%86400)%3600)/60)+" minutes, " +(string)(((SECONDS%86400)%3600)%60)+ "seconds.",COLOR,1); }
default { state_entry() { SECONDS = SECONDS + MINUTES * 60 + HOURS * 3600 + DAYS * 86400; llSetTimerEvent(1); countdown(); } timer() { if (SECONDS > 0) { SECONDS = SECONDS - 1; countdown(); } else { llSetText(FINISHED, COLOR,1); llSetTimerEvent(0); } } } </lsl>
<lsl> // _ _ _ // (_) | | | | // __ ____ _ _ | |_ _ _ __ ___| |__ // |_ / _` | | | | | | | '_ \ / __| '_ \ // / / (_| | | | | |_| | | | | (__| | | | // /___\__,_|_| |_|\__, |_| |_|\___|_| |_| // __/ | // |___/ // // released this script under // Creative Commons Attribution-Share Alike 3.0 // // Based on a timestamp -> unixtime // conversion script by Trinity Coulter // taken from // http://tinyurl.com/6hyf4z // at September 4th 2008 //
string Date = "2009.09.04"; // YYYY.MM.DD string Time = "15:44:00"; // hh:mm:ss string TEXT = "The end of the world will come in"; // Additional text defining the event string FINISHED = "uh oh..."; // Text displayed when event happened vector COLOR = <1,1,1>; // Color of the displayed text
countdown() { llSetText(TEXT+"\n"+(string)(SECONDS/86400)+" days, " +(string)((SECONDS%86400)/3600)+" hours, " +(string)(((SECONDS%86400)%3600)/60)+" minutes, " +(string)(((SECONDS%86400)%3600)%60)+ "seconds.",COLOR,1); }
default { state_entry() { myGMTTime = Date +"."+Time; string toUnix = "http://www.iwebtool.com/tool/tools/unix_time_converter/unix_time_converter.php?year=" + llGetSubString(myGMTTime,0,3) + "&mon=" + llGetSubString(myGMTTime,5,6) + "&day=" + llGetSubString(myGMTTime,8,9) + "&hour=" + llGetSubString(myGMTTime,11,12) + "&min=" + llGetSubString(myGMTTime,14,15) + "&sec=" + llGetSubString(myGMTTime,17,18); SECONDS = llGetUnixTime(); llHTTPRequest(toUnix,[HTTP_METHOD,"GET"],""); } http_response(key request_id,integer status, list metadata, string body) { body = llGetSubString(body, 50, -9); SECONDS = (integer)body + 18000 - (2 * llGetUnixTime()) + SECONDS; llSetTimerEvent(1); } timer() { if (SECONDS > 0) { SECONDS = SECONDS - 1; countdown(); } else { llSetText(FINISHED, COLOR,1); llSetTimerEvent(0); } } } </lsl>
Basic Notecard-ReaderThis script reads notecards placed in the same prim as the script itself. <lsl> ////////////////////////////////////////////////////// // // // Basic Notecard-Reader // // released under // // Creative Commons Attribution-Share Alike 3.0 // // by Zai Lynch // // // //////////////////////////////////////////////////////
integer CHANNEL = 2130214; list MENU = ["Forward", "Backward", "Load", "Play", "Stop", "Time"]; // Variables list gMenuNC; integer gLine = 0; integer gTime = 5; string gNC = ""; key owner; zlGenerateList(){ integer i; integer n = llGetInventoryNumber(INVENTORY_NOTECARD); string name; gMenuNC = []; if (n > 0){ for (i=0; i<n; i++){ name = llGetInventoryName(INVENTORY_NOTECARD, i); if (llStringLength(name) < 25) gMenuNC = gMenuNC + [name]; else { llSay(0, "Name: "+name + " is to long."); llRemoveInventory(name); llSay(0, "Notecard removed."); } } } if (gNC == "") gNC=llGetInventoryName(INVENTORY_NOTECARD,0); }
default { state_entry(){ zlGenerateList(); owner = llGetOwner(); llListen(CHANNEL, "", owner, ""); llListen(CHANNEL+1, "", owner, ""); } on_rez(integer start_param){ llResetScript(); } changed(integer change){ if (change & CHANGED_INVENTORY) zlGenerateList(); else if (change & CHANGED_OWNER) llResetScript(); } touch_start(integer num){ if (llDetectedKey(0) == owner) llDialog(owner," ",MENU,CHANNEL); } listen(integer cha, string name, key id, string msg){ if (cha == CHANNEL){ if (msg == "Stop") { llSetTimerEvent(0); } else if (msg == "Play") { llSetTimerEvent(gTime); llGetNotecardLine(gNC, gLine); } else if (msg == "Forward") { gLine = gLine + 1; llGetNotecardLine(gNC, gLine); llSetTimerEvent(0); } else if ((msg == "Backward") && (gLine > 0)) { gLine = gLine - 1; llGetNotecardLine(gNC, gLine); llSetTimerEvent(0); } else if (msg == "Load") { llDialog(owner, " ", gMenuNC, CHANNEL+1); return; } else if (msg == "Time") state listening; } else { gNC = msg; gLine = 0; } llDialog(owner," ",MENU,CHANNEL); } timer(){ gLine = gLine+1; llGetNotecardLine(gNC, gLine); } dataserver(key qid, string data){ llSay(0, data); } state_exit(){ llSetTimerEvent(0); } } state listening{ state_entry(){ llSetTimerEvent(30); llListen(0, "", owner, ""); llSay(0,"Please tell me the desired updatetime in seconds."); } listen(integer cha, string name, key id, string msg){ gTime = (integer)msg; llSay(0, "Time set."); state default; } timer(){ llSay(0,"Sorry, the request timed out."); state default; } state_exit(){ llSetTimerEvent(0); llDialog(owner," ",MENU,CHANNEL); } } </lsl>
Teleport via MapSet the description of the prim this script is attached to, to: SIMNAME/X/Y/Z <lsl> ////////////////////////////////////////////////////// // // // Teleport via Map // // released under // // Creative Commons Attribution-Share Alike 3.0 // // by Zai Lynch // // // ////////////////////////////////////////////////////// string simname; vector pos; integer touchStartTime;
init() { if (llGetObjectDesc() != "") { string desc = llGetObjectDesc(); simname = llGetSubString(desc,0,llSubStringIndex(desc,"/")-1); desc = llGetSubString(desc,llSubStringIndex(desc,"/")+1,llStringLength(desc)+1); integer x = (integer)llGetSubString(desc,0,llSubStringIndex(desc,"/")-1); desc = llGetSubString(desc,llSubStringIndex(desc,"/")+1,llStringLength(desc)+1); integer y = (integer)llGetSubString(desc,0,llSubStringIndex(desc,"/")-1); desc = llGetSubString(desc,llSubStringIndex(desc,"/")+1,llStringLength(desc)+1); integer z = (integer)llGetSubString(desc,0,llStringLength(desc)-1); pos = <x,y,z>; } else { simname="Omidyar"; pos=<130,86,200>; } }
state_entry() { init(); } touch_start(integer num_detected) { touchStartTime = llGetUnixTime(); } touch_end(integer num_detected) { if (llGetUnixTime() > touchStartTime + 4) { llSay(0,"Resetting..."); init(); } else llMapDestination(simname, pos, <1,1,1> ); } } </lsl>
BuzzerThis script is supposed to be used during meetings so a speaker isn't interrupted by questions while people can still indicate that they would like to speak. Up to 8 people might leave their indication by clicking the item where the script is attached to. Every name will only be listed once. Click and hold it clicked for more than 3 seconds to delete the upmost name. <lsl> // _ _ _ // (_) | | | | // __ ____ _ _ | |_ _ _ __ ___| |__ // |_ / _` | | | | | | | '_ \ / __| '_ \ // / / (_| | | | | |_| | | | | (__| | | | // /___\__,_|_| |_|\__, |_| |_|\___|_| |_| // __/ | // |___/ // // released this script under // Creative Commons Attribution-Share Alike 3.0 // integer time; list q = [];
state_entry(){ llSetText("User with questions:",<1,1,1>,1); } on_rez(integer startparam){ llResetScript(); } touch_start(integer total_number){ time = llGetUnixTime(); } touch_end(integer num_detected){ if (llGetUnixTime() < time + 3){ string name = llDetectedName(0); if(!(~llListFindList(q,(list)name))) q += [name]; } else q = llDeleteSubList(q,0,0); string text = "User with questions:"; integer i; for (i = 0; ((i < llGetListLength(q))&&(i < 8));i++){ text += "\n"+llList2String(q,i); } llSetText(text, <1,1,1>,1); } } </lsl> Landmark ReplacerThe following two scripts are supposed to be used by shop owners who are moving their store to a new spot. Since most owners box their items with a landmark to their shop, all these landmarks need to be updated after the move. Depending on the number of items, this can become an exhausting exercise. It will still remain an exhausting exercise, even with the use of these scripts, but it will at least make it a little faster. The first script zlLandmarkSender is supposed to be placed in a single prim, which contains the landmark to the new store. Alter the LM variable that way, that it's value equals the exact name of the landmark in the objects inventory. Afterwards, rez all your boxes and place the zlLandmarkCleaner&Replacer script inside them. This script will search for exisiting landmarks and remove them. Afterwards, it will ask the previously rezzed prim (server) for the uptated landmark. When you finished placing your scripts in the old boxes, you can click the initially rezzed serverprim and answer the upcoming question with yes in order to remove all zlLandmarkCleaner&Replacer scripts from the boxes and to de-rez the server prim. zlLandmarkSender<lsl> // _ _ _ // (_) | | | | // __ ____ _ _ | |_ _ _ __ ___| |__ // |_ / _` | | | | | | | '_ \ / __| '_ \ // / / (_| | | | | |_| | | | | (__| | | | // /___\__,_|_| |_|\__, |_| |_|\___|_| |_| // __/ | // |___/ // // released this script under // Creative Commons Attribution-Share Alike 3.0 //
state_entry() { llListen(CHANNEL, "", "", "Gimme LM plz"); llListen(CHANNEL + 1, "", llGetOwner(), ""); } listen(integer cha, string name, key id, string msg) { if (cha == CHANNEL) llGiveInventory(id, LM); else { if (msg == "Yes") { llShout(CHANNEL, "kill"); llOwnerSay("All scripts killed. Job done. Removing myself."); llDie(); } } } touch_start(integer num) { if (llDetectedKey(0) == llGetOwner()) llDialog(llDetectedKey(0), "Kill all scripts?", ["Yes", "No"], CHANNEL+1); } } </lsl>
zlLandmarkCleaner&Receiver<lsl> // _ _ _ // (_) | | | | // __ ____ _ _ | |_ _ _ __ ___| |__ // |_ / _` | | | | | | | '_ \ / __| '_ \ // / / (_| | | | | |_| | | | | (__| | | | // /___\__,_|_| |_|\__, |_| |_|\___|_| |_| // __/ | // |___/ // // released this script under // Creative Commons Attribution-Share Alike 3.0 //
state_entry() { integer b = llGetInventoryNumber(INVENTORY_LANDMARK); integer a; if (b > 0) { for (a = 0; a < b; a++) llRemoveInventory(llGetInventoryName(INVENTORY_LANDMARK,0)); } llShout(CHANNEL, "Gimme LM plz"); llListen(CHANNEL, "", "", "kill"); } listen(integer cha, string name, key id, string msg) { if (llGetOwnerKey(id) == llGetOwner()) llRemoveInventory(llGetScriptName()); } } </lsl> IM GreeterThis is supposed to be a low spam IM greeter. <lsl> // _ _ _ // (_) | | | | // __ ____ _ _ | |_ _ _ __ ___| |__ // |_ / _` | | | | | | | '_ \ / __| '_ \ // / / (_| | | | | |_| | | | | (__| | | | // /___\__,_|_| |_|\__, |_| |_|\___|_| |_| // __/ | // |___/ // // released this script under // Creative Commons Attribution-Share Alike 3.0 //
integer RANGE = 5; // Scans RANGE meter. integer RATE = 5; // Scans every RATE seconds. integer CLEANTIME = 300; // List is cleaned every CLEANTIME seconds. integer ABSENTTIME = 300; // Time ava is allowed to // be out of scanning range before getting removed // from the list. list MyAvatarList = []; // List that stores avas and timestamps.
state_entry(){ llSensorRepeat("", "", AGENT, RANGE, PI, RATE); // start scanner llSetTimerEvent(CLEANTIME); // start timer for cleanup } on_rez(integer start){ llResetScript(); // Reset script when greeter rezzed } sensor(integer num_detected){ integer i = 0; for (;i < num_detected; i++){ // for each detected ava do key ava = llDetectedKey(i); // grab the key integer index = llListFindList(MyAvatarList, (list)ava); // grab position in list if(~index){ // if ava in list // update the timestamp MyAvatarList = llListReplaceList(MyAvatarList, [llGetUnixTime()], index+1, index+1); } else { // else MyAvatarList += [ava, llGetUnixTime()]; // add ava to list llInstantMessage(ava, MESSAGE); // greet ava via IM } } } timer(){ // start to clean obsolete entries integer length = llGetListLength(MyAvatarList); integer i = 1; integer time = llGetUnixTime(); // store current time for (; i < length; i += 2) { // for all timestamps if (time - llList2Integer(MyAvatarList,i) > ABSENTTIME){ // compare timestamp with current time // delete ava from list when absent for to long MyAvatarList = llDeleteSubList(MyAvatarList, i-1, i); i -= 2; // offset length -= 2; // offset } } } }</lsl>
Simple RadarThis is supposed to be a simple radar, scanning the surrounding (96m) and showing distance as well as agent infos. The output is very similar to (and inspired by) a functionality of Mystical Cookie's famous Mysti-Tool HUD. <lsl> // _ _ _ // (_) | | | | // __ ____ _ _ | |_ _ _ __ ___| |__ // |_ / _` | | | | | | | '_ \ / __| '_ \ // / / (_| | | | | |_| | | | | (__| | | | // /___\__,_|_| |_|\__, |_| |_|\___|_| |_| // __/ | // |___/ // // released this script under // Creative Commons Attribution-Share Alike 3.0 //
default{ state_entry(){ // some hack to make it run in no script areas llReleaseControls(); llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS); // remove hovertext llSetText("", <1,1,1>,1); // tell the owner that the device is currently off llOwnerSay("Radar off. Click to activate."); } sensor(integer num){ // prepare output string string text = "Detected "+(string)(num)+" Resident"; // distinguish for plural or singular if (num == 1) text += ":\n"; else text += "s:\n"; // define a local info variable integer info; // define a local index variable integer i = 0; // store the current position so we can later calculate the distance vector pos = llGetPos(); // loop through all detected Residents for (; i < num; i++){ // add name and distance to the output string text += llDetectedName(i)+" ("+ (string)((integer)llVecDist(llDetectedPos(i),pos)) +"m) "; // retrieve information about that Resident and store it in the variable info = llGetAgentInfo(llDetectedKey(i)); // add letter W in case the Resident is walking if (info & AGENT_WALKING) text += "W"; // add letter F in case the Resident is flying (or hovering) if (info & AGENT_FLYING) text += "F"; // add letter S in case the Resident is sitting if (info & AGENT_SITTING) text += "S"; // add letter T in case the Resident is typing (AND has typing animation) if (info & AGENT_TYPING) text += "T"; // add letter M in case the Resident is in mouselook if (info & AGENT_MOUSELOOK) text += "M"; // add a linebreak text += "\n"; } // display the text above the prim llSetText(text, <1.0, 1.0, 1.0>, 1.0); } touch_start(integer num){ if (off){ // scan the surrounding for Residents llSensorRepeat("", "", AGENT, 96.0, PI, RATE); // give a notice that it's on llOwnerSay("Radar on."); // set the check variable to FALSE so we know that it's on off = FALSE; } else llResetScript(); } // this part belongs to the no script area hack run_time_permissions(integer perms){ llTakeControls(CONTROL_FWD, 0, 1); } no_sensor() { llSetText("Detected 0 Residents.", <1.0, 1.0, 1.0>, 1.0); } }</lsl> |
|