This is the converse of the environmental with medicine backpack applied to stress levels. In this variant, the bar starts at 0
on green
and fills up progressively to 1000
on red
. It is used in cases where you want the progress bar to start empty and eventually reach the top - perhaps something like danger meter.
/////////////////////////////////////////////////////////////////////////// // 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) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueGet(string k, string data) { if (llStringLength(data) == 0) return ""; if (llStringLength(k) == 0) return ""; list a = llParseStringKeepNulls(data, ["&", "="], []); integer i = llListFindList(a, [ k ]); if (i != -1) return llList2String(a, i + 1); return ""; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueSet(string k, string v, string data) { if (llStringLength(data) == 0) return k + "=" + v; if (llStringLength(k) == 0) return ""; if (llStringLength(v) == 0) return ""; integer i = llListFindList( llList2ListStrided( llParseString2List(data, ["&", "="], []), 0, -1, 2 ), [ k ]); if (i != -1) return llDumpList2String( llListReplaceList( llParseString2List(data, ["&"], []), [ k + "=" + v ], i, i), "&"); return data + "&" + k + "=" + v; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueEncode(list data) { list k = llList2ListStrided(data, 0, -1, 2); list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); data = []; do { data += llList2String(k, 0) + "=" + llList2String(v, 0); k = llDeleteSubList(k, 0, 0); v = llDeleteSubList(v, 0, 0); } while (llGetListLength(k) != 0); return llDumpList2String(data, "&"); } // Quick function to list AoE. string getExposures() { if (llGetListLength(exposures)) return "Exposures: " + "[ " + llDumpList2String(exposures, ",") + " ]"; return ""; } integer stress = 0; integer damage = 0; list exposures = []; list penalties = []; default { state_entry() { stress = (integer)wasKeyValueGet("stress", 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 stress. dh = wasKeyValueGet("stress", data); // If it does not, ignore and continue and don't waste time. if (dh == "") jump continue; // Get the stress and add it to the current stress, 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 (llStringLength(exposure) == 0) 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() { stress += damage; if (stress <= 0) stress = 0; if (stress > 1000) stress = 1000; llSetObjectDesc(wasKeyValueSet("stress", (string)stress, llGetObjectDesc())); integer p = (integer)(100.0 * (float)stress / 1000.0); llSetText("Stress: " + wasProgress(p, 10, ["[", "█", "░", "]"]) + "\n" + getExposures(), wasPercentToGradient(p, "gr"), 1.0); llRegionSay(-2104156, wasKeyValueEncode(["owner", llKey2Name(llGetOwner()), "stress", 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(); } }