/////////////////////////////////////////////////////////////////////////// // 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. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasProgress(integer percent, integer length, list symbols) { percent /= (integer)((float)100.0/(length)); string p = llList2String(symbols,0); integer itra = 0; do { if(itra>percent-1) p += llList2String(symbols,2); else p += llList2String(symbols,1); } while(++itra<length); return p + llList2String(symbols,3); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// vector wasPercentToGradient(float percent, string rgb) { if(llStringLength(rgb) != 2) { llSay(DEBUG_CHANNEL, "Assert failed, rgb parameter must consist of a pair of either r, g, or b."); return ZERO_VECTOR; } string a = llGetSubString(rgb, 0, 0); string b = llGetSubString(rgb, 1, 1); list col = [ "r", "g", "b" ]; integer ax = llListFindList(col, (list)a); integer bx = llListFindList(col, (list)b); if(ax == -1 || bx == -1) { llSay(DEBUG_CHANNEL, "Asset failed, rgb parameters must contain either r, g, or b letters."); return ZERO_VECTOR; } col = llListReplaceList(col, (list)((100-percent)/100), ax, ax); col = llListReplaceList(col, (list)(percent/100), bx, bx); return 2*<llList2Float(col, 0), llList2Float(col, 1), llList2Float(col, 2)>; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2012 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasDeleteSubListMatch(list in, string match) { if(llGetListLength(in) == 0) return []; string first = llList2String(in, 0); in = llDeleteSubList(in, 0, 0); if(llSubStringIndex(first, match) == -1) jump next; return wasDeleteSubListMatch(in, match); @next; return first + wasDeleteSubListMatch(in, match); } /////////////////////////////////////////////////////////////////////////// // 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 wasKeyValueEncode(list kvp) { if(llGetListLength(kvp) < 2) return ""; string k = llList2String(kvp, 0); kvp = llDeleteSubList(kvp, 0, 0); string v = llList2String(kvp, 0); kvp = llDeleteSubList(kvp, 0, 0); if(llGetListLength(kvp) < 2) return k + "=" + v; return k + "=" + v + "&" + wasKeyValueEncode(kvp); } // Quick function to list AoE. string getExposures() { if(llGetListLength(exposures)) return "Exposures: " + "[ " + llDumpList2String(exposures, ",") + " ]"; return ""; } integer health = 1000; integer damage = 0; list exposures = []; list penalties = []; default { state_entry() { health = (integer)wasKeyValueGet("health", llGetObjectDesc()); integer comChannel = (integer)("0x8" + llGetSubString(llGetOwner(), 0, 6)); llListen(comChannel, "Medicine Backpack", "", ""); llSetTimerEvent(1); llSensorRepeat("", "", ACTIVE|PASSIVE, 96, TWO_PI, 1); } // When an AoE objects are detected, go through all off them and process them. sensor(integer num) { --num; do { // First grab the formatted name. string data = llDetectedName(num); // If the range of the AoE is smaller than the distance between the AV and the // trigger point, then remove the AoE exposure from the exposures list and continue. string dh = wasKeyValueGet("range", data); // If the object does not have a range set, it's not going to affect the avatar // and is most likely just a static object not part of the project. Quickly ignore. if(dh == "") jump continue; if(llVecDist(llGetPos(), llDetectedPos(num)) > (float)dh) jump continue; // Check if the exposure has a properly formatted name. dh = wasKeyValueGet("name", data); // If it doesn't ignore it, and jump to AoE processing. if(dh == "") jump exposure; // If it does, add it to the list of AoE exposures. if(llListFindList(exposures, (list)dh) == -1) { exposures += dh; jump exposure; } // If the exposure is already active, ignore the AoE (non-stacking AoE) return; @exposure; // Check if the exposure has a properly formatted health. dh = wasKeyValueGet("health", data); // If it does not, ignore and continue and don't waste time. if(dh == "") jump continue; // Get the health and add it to the current health, either increasing or decreasing // while making sure that it doesn't underrun 0, respectively 100 (Hard cap). damage += (integer)dh; penalties += (integer)dh; @continue; } while(--num>-1); } listen(integer channel, string name, key id, string message) { if(llGetOwnerKey(id) != llGetOwner()) return; string exposure = wasKeyValueGet(message, llGetObjectDesc()); if(exposure == "") return; integer i = llListFindList(exposures, (list)exposure); if(i == -1) return; exposures = llDeleteSubList(exposures, i, i); integer d = llList2Integer(penalties, i); damage -= d; penalties = llDeleteSubList(penalties, i, i); llOwnerSay("You prevent the " + exposure + " exposure."); } // Every tick, display overhead status. timer() { health += damage; if(health <= 0) health=0; llSetObjectDesc(wasKeyValueSet("health", (string)health, llGetObjectDesc())); integer p = (integer)(100.0*(float)health/1000.0); llSetText("Health: " + wasProgress(p, 10, ["[", "█", "░", "]"]) + "\n" + getExposures(), wasPercentToGradient(p, "rg"), 1.0); llRegionSay((integer)("0x8" + llGetSubString(llGetCreator(), 0, 6)), wasKeyValueEncode(["owner", llKey2Name(llGetOwner()), "health", p])); } // Restart the script on rez and attach to make sure that llGetOwner() returns a correct key (BUG) on_rez(integer num) { llResetScript(); } attach(key id) { llResetScript(); } }