/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// list WORN_SLOTS = []; list ATTACHED_SLOTS = []; list C = []; list A = []; /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasMenuIndex = 0; list wasDialogMenu(list input, list actions, string direction) { integer cut = 11-wasListCountExclude(actions, [""]); if(direction == ">" && (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) { ++wasMenuIndex; jump slice; } if(direction == "<" && wasMenuIndex-1 >= 0) { --wasMenuIndex; jump slice; } @slice; integer multiple = wasMenuIndex*cut; input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex); input = wasListMerge(input, actions, ""); return input; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasListCountExclude(list input, list exclude) { if(llGetListLength(input) == 0) return 0; if(llListFindList(exclude, (list)llList2String(input, 0)) == -1) return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude); return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasListMerge(list l, list m, string merge) { if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return []; string a = llList2String(m, 0); if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge); return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueGet(string var, string kvp) { list dVars = llParseString2List(kvp, ["&"], []); do { list data = llParseString2List(llList2String(dVars, 0), ["="], []); string k = llList2String(data, 0); if(k != var) jump continue; return llList2String(data, 1); @continue; dVars = llDeleteSubList(dVars, 0, 0); } while(llGetListLength(dVars)); return ""; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueSet(string var, string val, string kvp) { list dVars = llParseString2List(kvp, ["&"], []); if(llGetListLength(dVars) == 0) return var + "=" + val; list result = []; do { list data = llParseString2List(llList2String(dVars, 0), ["="], []); string k = llList2String(data, 0); if(k == "") jump continue; if(k == var && val == "") jump continue; if(k == var) { result += k + "=" + val; val = ""; jump continue; } string v = llList2String(data, 1); if(v == "") jump continue; result += k + "=" + v; @continue; dVars = llDeleteSubList(dVars, 0, 0); } while(llGetListLength(dVars)); if(val != "") result += var + "=" + val; return llDumpList2String(result, "&"); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueDelete(string var, string kvp) { list dVars = llParseString2List(kvp, ["&"], []); list result = []; list added = []; do { list data = llParseString2List(llList2String(dVars, 0), ["="], []); string k = llList2String(data, 0); if(k == var) jump continue; string v = llList2String(data, 1); if(v == "") jump continue; if(llListFindList(added, (list)k) != -1) jump continue; result += k + "=" + v; added += k; @continue; dVars = llDeleteSubList(dVars, 0 ,0); } while(llGetListLength(dVars)); return llDumpList2String(result, "&"); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// LID(key id) { if(id != NULL_KEY && llGetAttached() != 0) { llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", (string)((integer)wasKeyValueGet("login", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))+1), llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); llResetScript(); } llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", "-1", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); } default { state_entry() { // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments // if LID™, then login = 1 // else login = 0 - script running | parameter undefined if((integer)wasKeyValueGet("login", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0)) > 0) { llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", "0", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); llSetTimerEvent(25); return; } llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", "0", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); state check; } timer() { state check; } changed(integer change) { if(change & CHANGED_INVENTORY || change & CHANGED_REGION || change & CHANGED_OWNER) llResetScript(); } // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments attach(key id) { LID(id); } } state check { state_entry() { llSetTimerEvent(5); integer channel = 10+(integer)llFrand(10); llListen(channel, "", llGetOwner(), ""); llOwnerSay("@version=" + (string)channel); } timer() { llSetTimerEvent(0); llOwnerSay("Your viewer is not RLV-enabled. This gizmo requires a RLV-enabled viewer. Cannot proceed."); } listen(integer channel, string name, key owner, string message) { llSetTimerEvent(0); // mark -> t=0 llGetAndResetTime(); state read; } changed(integer change) { if(change & CHANGED_INVENTORY || change & CHANGED_REGION || change & CHANGED_OWNER) llResetScript(); } // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments attach(key id) { LID(id); } } state read { state_entry() { WORN_SLOTS = ["◎ gloves", "◎ jacket", "◎ pants", "◎ shirt", "◎ shoes", "◎ skirt", "◎ socks", "◎ underpants", "◎ undershirt", "◎ skin", "◎ eyes", "◎ hair", "◎ shape", "◎ alpha", "◎ tattoo"]; ATTACHED_SLOTS = [ "◎ none", "◎ chest", "◎ skull", "◎ left shoulder", "◎ right shoulder", "◎ left hand", "◎ right hand", "◎ left foot", "◎ right foot", "◎ spine", "◎ pelvis", "◎ mouth", "◎ chin", "◎ left ear", "◎ right ear", "◎ left eyeball", "◎ right eyeball", "◎ nose", "◎ r upper arm", "◎ r forearm", "◎ l upper arm", "◎ l forearm", "◎ right hip", "◎ r upper leg", "◎ r lower leg", "◎ left hip", "◎ l upper leg", "◎ l lower leg", "◎ stomach", "◎ left pec", "◎ right pec", "◎ center 2", "◎ top right", "◎ top", "◎ top left", "◎ center", "◎ bottom left", "◎ bottom", "◎ bottom right" ]; llListen(2, "", llGetOwner(), ""); llListen(3, "", llGetOwner(), ""); llOwnerSay("@getoutfit=2"); llOwnerSay("@getattach=3"); llSetTimerEvent(1); } listen(integer channel, string name, key owner, string message) { if(channel == 2) { C = llParseString2List(message, [""], ["0", "1"]); jump alarm; } if(channel == 3) { A = llParseString2List(message, [""], ["0", "1"]); jump alarm; } @alarm; llSetTimerEvent(1); } timer() { if(llGetListLength(C) == 0 || llGetListLength(A) == 0) return; list mem = llParseString2List( wasKeyValueGet("mem", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0)) , [","], []); integer i = llGetListLength(C)-1; do { string slot = llDeleteSubString(llList2String(WORN_SLOTS, i), 0, 1); if(llGetListLength(mem) == 0) jump skip_mem_worn; integer idx = llListFindList(mem, (list)slot); if(idx != -1) { mem = llDeleteSubList(mem, idx, idx); WORN_SLOTS = llListReplaceList(WORN_SLOTS, (list)("◉ " + slot), i, i); llOwnerSay("@remoutfit:" + slot + "=n"); jump nextC; } @skip_mem_worn; if(llList2Integer(C, i) != 0) { llOwnerSay("@remoutfit:" + slot + "=y"); jump nextC; } WORN_SLOTS = llDeleteSubList(WORN_SLOTS, i, i); @nextC; } while(--i>-1); C = []; i = llGetListLength(A)-1; do { string slot = llDeleteSubString(llList2String(ATTACHED_SLOTS, i), 0, 1); if(llGetListLength(mem) == 0) jump skip_mem_attached; integer idx = llListFindList(mem, (list)slot); if(idx != -1) { mem = llDeleteSubList(mem, idx, idx); ATTACHED_SLOTS = llListReplaceList(ATTACHED_SLOTS, (list)("◉ " + slot), i, i); llOwnerSay("@remattach:" + slot + "=n"); jump nextA; } @skip_mem_attached; if(llList2Integer(A, i) != 0) { llOwnerSay("@remattach:" + slot + "=y"); jump nextA; } ATTACHED_SLOTS = llDeleteSubList(ATTACHED_SLOTS, i, i); @nextA; } while(--i>-1); A = []; llSetTimerEvent(0); // alarm -> t = t + [3..4] state main; } changed(integer change) { if(change & CHANGED_INVENTORY || change & CHANGED_REGION || change & CHANGED_OWNER) llResetScript(); } // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments attach(key id) { LID(id); } } state main { state_entry() { llListen(1, "", llGetOwner(), ""); // if t < 3 then script reset, so wait for /1ock // if t >> 3 then returning from lock_worn or lock_attached, so re-menu if(llGetAndResetTime() < 4) return; llDialog(llGetOwner(), "\n Welcome to the Outfit Locker.\nCreated in 2013 by Wizardry and Steamworks\n 10 August 2013: Version: 1.0\n", ["▦ Worn", "▣ Attached", "⎚ Clear"], 1); } listen(integer channel, string name, key owner, string message) { if(message == "ock") { llDialog(owner, "\n Welcome to the Outfit Locker.\nCreated in 2013 by Wizardry and Steamworks\n 10 August 2013: Version: 1.0\n", ["▦ Worn", "▣ Attached", "⎚ Clear"], channel); return; } if(message == "⎚ Clear") state clear; if(message == "▦ Worn") state lock_worn; if(message == "▣ Attached") state lock_attached; } changed(integer change) { if(change & CHANGED_INVENTORY || change & CHANGED_REGION || change & CHANGED_OWNER) llResetScript(); } // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments attach(key id) { LID(id); } } state clear { state_entry() { llSetTimerEvent(3); } timer() { list mem = llParseString2List(wasKeyValueGet("mem", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0)), [","], []); do { string slot = llList2String(mem, 0); llOwnerSay("@remoutfit:" + slot + "=y"); llOwnerSay("@remattach:" + slot + "=y"); mem = llDeleteSubList(mem, 0, 0); } while(llGetListLength(mem) != 0); llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueDelete("mem", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); state read; } } state lock_worn { state_entry() { llListen(1, "", llGetOwner(), ""); llDialog(llGetOwner(), "\n Welcome to the Outfit Locker.\nCreated in 2013 by Wizardry and Steamworks\n 10 August 2013: Version: 1.0\n", wasDialogMenu(WORN_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], ""), 1); } listen(integer channel, string name, key owner, string message) { if(message == "⏏ Exit" || message == "ock") state read; if(message == "⟵ Back") { llDialog(owner, "Please browse the available items:\n", wasDialogMenu(WORN_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], "<"), channel); return; } if(message == "Next ⟶") { llDialog(owner, "Please browse the available items:\n", wasDialogMenu(WORN_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], ">"), channel); return; } integer idx = llListFindList(WORN_SLOTS, (list)message); string status = llGetSubString(message, 0, 0); message = llDeleteSubString(message, 0, 1); list mem = llParseString2List(wasKeyValueGet("mem", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0)), [","], []); // if all slots are occupied, bail out. if(status == "◎" && llGetListLength(mem) == 10) { llOwnerSay("Sorry, only 10 slots are supported. Please untick some items to lock this item."); jump remenu; } // lock if(status == "◎" && llListFindList(mem, (list)message) == -1) { WORN_SLOTS = llListReplaceList(WORN_SLOTS, (list)("◉ " + message), idx, idx); mem += message; llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("mem", llDumpList2String(mem, ","), llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); llOwnerSay("@remoutfit:" + message + "=n"); jump remenu; } // unlock WORN_SLOTS = llListReplaceList(WORN_SLOTS, (list)("◎ " + message), idx, idx); idx = llListFindList(mem, (list)message); mem = llDeleteSubList(mem, idx, idx); llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("mem", llDumpList2String(mem, ","), llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); llOwnerSay("@remoutfit:" + message + "=y"); @remenu; llDialog(owner, "Please browse the available items:\n", wasDialogMenu(WORN_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], ""), channel); } changed(integer change) { if(change & CHANGED_INVENTORY || change & CHANGED_REGION || change & CHANGED_OWNER) llResetScript(); } // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments attach(key id) { LID(id); } } state lock_attached { state_entry() { llListen(1, "", llGetOwner(), ""); llDialog(llGetOwner(), "\n Welcome to the Outfit Locker.\nCreated in 2013 by Wizardry and Steamworks\n 10 August 2013: Version: 1.0\n", wasDialogMenu(ATTACHED_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], ""), 1); } listen(integer channel, string name, key owner, string message) { if(message == "⏏ Exit" || message == "ock") state read; if(message == "⟵ Back") { llDialog(owner, "Please browse the available items:\n", wasDialogMenu(ATTACHED_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], "<"), channel); return; } if(message == "Next ⟶") { llDialog(owner, "Please browse the available items:\n", wasDialogMenu(ATTACHED_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], ">"), channel); return; } integer idx = llListFindList(ATTACHED_SLOTS, (list)message); string status = llGetSubString(message, 0, 0); message = llDeleteSubString(message, 0, 1); list mem = llParseString2List(wasKeyValueGet("mem", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0)), [","], []); // if all slots are occupied, bail out. if(status == "◎" && llGetListLength(mem) == 10) { llOwnerSay("Sorry, only 10 slots are supported. Please untick some items to lock this item."); jump remenu; } // lock if(status == "◎" && llListFindList(mem, (list)message) == -1) { ATTACHED_SLOTS = llListReplaceList(ATTACHED_SLOTS, (list)("◉ " + message), idx, idx); mem += message; llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("mem", llDumpList2String(mem, ","), llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); llOwnerSay("@remattach:" + message + "=n"); jump remenu; } // unlock ATTACHED_SLOTS = llListReplaceList(ATTACHED_SLOTS, (list)("◎ " + message), idx, idx); idx = llListFindList(mem, (list)message); mem = llDeleteSubList(mem, idx, idx); llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("mem", llDumpList2String(mem, ","), llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]); llOwnerSay("@remattach:" + message + "=y"); @remenu; llDialog(owner, "Please browse the available items:\n", wasDialogMenu(ATTACHED_SLOTS, ["⟵ Back", "Next ⟶", "⏏ Exit"], ""), channel); } changed(integer change) { if(change & CHANGED_INVENTORY || change & CHANGED_REGION || change & CHANGED_OWNER) llResetScript(); } // LID™ - http://grimore.org/fuss:lsl#log-in_detection_with_attachments attach(key id) { LID(id); } }