About

This is a version of the script that detects, adds and subtracts health points depending on the objects in the environment.

Code

This script was tested and works on OpenSim version 0.7.4!

contagion.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) 2015 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(llList2ListStrided(a, 0, -1, 2), [ k ]);
    if(i != -1) return llList2String(a, 2*i+1);
    return "";
}
 
///////////////////////////////////////////////////////////////////////////
//    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);
}
 
// Quick function to list AoE.
string getEffects() {
    if(llGetListLength(effects)) return "Effects: " + "[ " + llDumpList2String(effects, ",") + " ]";
    return "";
}
 
integer health = 100;
list effects = [];
 
default
{
    state_entry() {
        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 effect from the effects 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) {
                // AoE effect range does not reach us, delete it if in effects and continue.
                string name = wasKeyValueGet("name", data);
                if(llListFindList(effects, (list)name) != -1) {
                    effects = wasDeleteSubListMatch(effects, name);
                }
                jump continue;
            }
            // Check if the effect has a properly formatted name.
            dh = wasKeyValueGet("name", data);
            // If it doesn't ignore it, and jump to AoE processing.
            if(dh == "") jump effect;
            // If it does, add it to the list of AoE effects.
            if(llListFindList(effects, (list)dh) == -1) {
                effects += dh;
                jump effect;
            }
            // If the effect is already active, ignore the AoE (non-stacking AoE)
            return;
@effect;
            // Check if the effect 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).
            integer mod = (integer)dh;
            if(health + mod > 100) {
                health = 100;
                jump continue;
            }
            if(health + mod < 0) {
                health = 0;
                jump continue;
            }
            // It does not overstep, so just perform the arithmetic.
            health += mod;
@continue;
        } while(--num>-1);
    }
 
    // If no AoE objects are detected, consequently wipe the list.
    no_sensor() { effects = []; }
 
    // 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(); }
 
    // Every tick, display overhead status.
    timer() { llSetText("Health: " + wasProgress(health, 10, ["[", "█", "░", "]"]) + "\n" + getEffects(), wasPercentToGradient(health, "rg"), 1); }
 
}

secondlife/contagion/environmental.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.