fishulus.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - 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) 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) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueSet(string k, string v, string data) {
    if(llStringLength(k) == 0) return "";
    if(llStringLength(v) == 0) return "";
    if(llStringLength(data) == 0) return k + "=" + v;
    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) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
vector wasRectanglePoint(float x, float y) {
    x = llPow(-1, 1 + (integer)llFrand(2)) * llFrand(x/2);
    y = llPow(-1, 1 + (integer)llFrand(2)) * llFrand(y/2);
    return <x, y, 0.005>;
}
 
///////////////////////////////////////////////////////////////////////////
//    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);
}
 
list MODS = [ "Bloody Me", "Gramps", "Mr. Fatman", "Wormington", "Lil' Chubby", "Gossipish" ];
list CRITTERS = [ "Paul", "Maggie" ];
 
integer MAX_CRITTERS = 10;
integer channel = -1;
 
default
{
    state_entry() {
        llSetObjectDesc(wasKeyValueSet("critters", "0", llGetObjectDesc()));
        channel = (integer)("0x8" + llGetSubString(llGetOwner(), 0, 6));
        llListen(channel, "", "", "");
        llRegionSay(channel, wasKeyValueEncode(["die", llGetCreator()]));
        llSensorRepeat("", NULL_KEY, AGENT, 0.1, 0.1, 1);
        llSetTimerEvent(1);
    }
    listen(integer channel, string name, key id, string message) {
        if(llGetOwner() != llGetOwnerKey(id)) return;
        if(wasKeyValueGet("creator", message) != llGetCreator()) return;
        string mod = wasKeyValueGet("die", message);
        if(llListFindList(MODS, (list)mod) == -1) return;
        integer c = (integer)wasKeyValueGet("critters", llGetObjectDesc());
        if(c <= 0) c = 1;
        llSetObjectDesc(wasKeyValueSet("critters", (string)(--c), llGetObjectDesc()));
    }
    // for mods
    timer() {
        llSetTimerEvent(120);
        integer c = (integer)wasKeyValueGet("critters", llGetObjectDesc());
        if(c >= MAX_CRITTERS) return;
        string m = llList2String(MODS, (integer)llFrand(llGetListLength(MODS)));
        llRezObject(m, llGetPos() + wasRectanglePoint(.3137, .3137), ZERO_VECTOR, ZERO_ROTATION, channel);
        llSetObjectDesc(wasKeyValueSet("critters", (string)(++c), llGetObjectDesc()));
    }
    // for critters
    no_sensor() {
        llSensorRepeat("", NULL_KEY, AGENT, 0.1, 0.1, 60);
        llRezObject(llList2String(CRITTERS, (integer)llFrand(llGetListLength(CRITTERS))), llGetPos() + <0,0,0.005>, ZERO_VECTOR, ZERO_ROTATION, channel);
    }
}