About

Each probe is rezzed by passing the starting coordinates and will rise from ground-zero, scan the vicinity and then advance the altitude.

Code

probe.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) 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, "&");
}
 
///////////////////////////////////////////////////////////////////////////
//    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 "";
}
 
list mem = [];
integer comHandle = 0;
key owner = NULL_KEY;
 
default {
    listen(integer channel, string name, key id, string message) {
        if(message == "die") llDie();
        llListenRemove(comHandle);
        llListen((integer)("0x8" + llGetSubString(owner, 0, 6)), "", "", "die");
        integer scan = (integer)wasKeyValueGet("scan", message);
        if(scan == 0) scan = AGENT|PASSIVE|ACTIVE;
        string name = wasKeyValueGet("name", message);
        string uuid = wasKeyValueGet("uuid", message);
        llSensorRepeat(name, uuid, scan, 96, TWO_PI, 0.05);
        llSetTimerEvent(1);
    }
    on_rez(integer num) {
        if(num == 0) return;
        owner = llGetOwner();
        comHandle = llListen((integer)("0x8" + llGetSubString(owner, 0, 6)), "", "", "");
        llSetRegionPos(<num & 0xFFFF, num >> 16, 96>);
    }
    sensor(integer num) {
        num = --num;
        do {
            string detectedName = llDetectedName(num);
            key detectedOwner = llDetectedOwner(num);
            if(detectedName == llGetObjectName() && owner == llDetectedOwner(num)) jump continue;
            key ok = llDetectedKey(num);
            if(llListFindList(mem, (list)ok) != -1) jump continue;
            mem += ok;
            llRegionSay(
                (integer)("0x8" + 
                    llGetSubString(owner, 0, 6)
                ),
                wasKeyValueEncode(
                    [
                        "type", (string)llDetectedType(num),
                        "position", (string)llDetectedPos(num),
                        "name", detectedName, 
                        "owner", detectedOwner, 
                        "velocity", (string)llDetectedVel(num)
                    ]
                )
            );
@continue;
        } while(--num>-1);
    }
    timer() {
        vector position = llGetPos() + <0, 0, 96>;
        if(position.z >= 4096) llDie();
        mem = [];
        llSetRegionPos(position);
    }
}