About

This variant goes together with the pharmaceutics backpack and will increase health if the script receives the name of an exposure on its listening channel. Additionally, the script is made to permanently store the health in the description of the HUD such that detaching and re-attaching will preserve the health value to prevent cheating.

Code

contagionwithmedicine.lsl
///////////////////////////////////////////////////////////////////////////
//  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 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 (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() {
        health += damage;
        if (health <= 0) health = 0;
        if (health > 1000) health = 1000;
        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(-2104156, 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();
    }
}

secondlife/contagion/environmental_with_medicine_backpack.txt · Last modified: 2022/11/24 07:46 by 127.0.0.1

Access website using Tor Access website using i2p Wizardry and Steamworks PGP Key


For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.