File: http://svn.grimore.org/corrade-lsl-templates/source/heads-up-display/grid-follow/grid-follow.lsl -

///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0      //
///////////////////////////////////////////////////////////////////////////
//
// This is an automatic grid follower for the Corrade Second Life / OpenSim 
// bot. It uses two different engines: the simulator's built-in autopilot
// and a fly engine that will make Corrade fly to your location.
// You can find more details about the bot by following the URL: 
// http://grimore.org/secondlife/scripted_agents/corrade
//
// The follower script works together with a "configuration" notecard and 
// that must be placed in the same primitive as this script. 
// You are free to use, change, and commercialize it under the CC BY 2.0 
// license at: https://creativecommons.org/licenses/by/2.0
//
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueGet(string k, string data) {
    if(llStringLength(data) == 0) return "";
    if(llStringLength(k) == 0) return "";
    list a = llParseString2List(data, ["&", "="], []);
    integer i = llListFindList(a, [ k ]);
    if(i != -1) return llList2String(a, i+1);
    return "";
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0    //
///////////////////////////////////////////////////////////////////////////
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) 2011 Wizardry and Steamworks - License: CC BY 2.0    //
///////////////////////////////////////////////////////////////////////////
vector wasCirclePoint(float radius) {
    float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
    float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
    if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
        return <x, y, 0>;
    return wasCirclePoint(radius);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0    //
///////////////////////////////////////////////////////////////////////////
integer wasIsAvatarInSensorRange(key avatar) {
    return llListFindList(
        llGetAgentList(
            AGENT_LIST_REGION, 
            []
        ), 
        (list)((key)avatar)
    ) != -1 && 
        llVecDist(
            llGetPos(), 
            llList2Vector(
                llGetObjectDetails(
                    avatar, 
                    [OBJECT_POS]
                ), 
            0
        )
    ) <= 96;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0    //
///////////////////////////////////////////////////////////////////////////
// escapes a string in conformance with RFC1738
string wasURLEscape(string i) {
    string o = "";
    do {
        string c = llGetSubString(i, 0, 0);
        i = llDeleteSubString(i, 0, 0);
        if(c == "") jump continue;
        if(c == " ") {
            o += "+";
            jump continue;
        }
        if(c == "\n") {
            o += "%0D" + llEscapeURL(c);
            jump continue;
        }
        o += llEscapeURL(c);
@continue;
    } while(i != "");
    return o;
}
 
// for holding the callback URL
string callback = "";
 
// key-value data will be read into this list
string configuration = "";
 
default {
    state_entry() {
        llSetTimerEvent(1);
    }
    link_message(integer sender, integer num, string message, key id) {
        if(sender != 1 || id != "configuration") return;
        configuration = message;
        state off;
    }
    timer() {
        llMessageLinked(LINK_ROOT, 0, "configuration", NULL_KEY);
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
    state_exit() {
        llSetTimerEvent(0);
    }
}
 
state off {
    state_entry() {
        llSetColor(<.5,0,0>, ALL_SIDES);
    }
    touch_end(integer num) {
        state on;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
    }
}
 
state on {
    state_entry() {
        llSetColor(<0,.5,0>, ALL_SIDES);
        state url;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
    }
}
 
state url {
    state_entry() {
        // DEBUG
        llOwnerSay("Requesting URL...");
        llRequestURL();
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    http_request(key id, string method, string body) {
        if(method != URL_REQUEST_GRANTED) return;
        callback = body;
        // DEBUG
        llOwnerSay("Got URL...");
        state detect;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
}
 
state detect {
    state_entry() {
        // set color for button
        llSetColor(<0,.5,0>, ALL_SIDES);
        // if Corrade is in-range then just follow
        if(wasIsAvatarInSensorRange(
                (key)wasKeyValueGet(
                    "corrade", 
                    configuration
                )
            )
        ) state select;
        // DEBUG
        llOwnerSay("Detecting if Corrade is online...");
        llRequestAgentData(
            (key)wasKeyValueGet(
                "corrade", 
                configuration
            ),
            DATA_ONLINE
        );
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    dataserver(key id, string data) {
        if(data != "1") {
            // DEBUG
            llOwnerSay("Corrade is not online, sleeping...");
            llResetScript();
            return;
        }
        llSensorRepeat("", 
            (key)wasKeyValueGet(
                "corrade", 
                configuration
            ),
            AGENT,
            (integer)wasURLEscape(
                wasKeyValueGet(
                    "range", 
                    configuration
                )
            ),
            TWO_PI,
            5
        );
    }
    no_sensor() {
        // DEBUG
        llOwnerSay("Teleporting Corrade...");
        llInstantMessage(
            (key)wasKeyValueGet(
                "corrade", 
                configuration
            ), 
            wasKeyValueEncode(
                [
                    "command", "teleport",
                    "group", wasURLEscape(
                        wasKeyValueGet(
                            "group", 
                            configuration
                        )
                    ),
                    "password", wasURLEscape(
                        wasKeyValueGet(
                            "password", 
                            configuration
                        )
                    ),
                    "entity", "region",
                    "region", wasURLEscape(llGetRegionName()),
                    "position", llGetPos() + wasCirclePoint(
                        (integer)wasURLEscape(
                            wasKeyValueGet(
                                "range", 
                                configuration
                            )
                        )
                    ),
                    "deanimate", "True",
                    "callback", callback
                ]
            )
        );
    }
    sensor(integer num) {
        state select;
    }
    http_request(key id, string method, string body) {
        llHTTPResponse(id, 200, "OK");
        if(wasKeyValueGet("command", body) != "teleport" ||
            wasKeyValueGet("success", body) != "True") {
            // DEBUG
            llOwnerSay("Teleport failed...");
            return;
        }
        state select;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
}
 
state select {
    state_entry() {
        // DEBUG
        llOwnerSay("Selecting follow engine...");
        llSetTimerEvent(1);
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    timer() {
        vector cPos = llList2Vector(
            llGetObjectDetails(
                (key)wasKeyValueGet(
                    "corrade", 
                    configuration
                ),
                [OBJECT_POS]
            ),
            0
        );
        vector mPos = llGetPos();
        // If Corrade is in range then stop.
        if(llVecDist(mPos, cPos) < 5) return;
        // If we are flying or the distance between us and Corrade
        // is larger than a given distance then make Corrade fly. 
        if(
            (
                llGetAgentInfo(llGetOwner()) & AGENT_FLYING
            ) || 
            llFabs(mPos.z - cPos.z) > 5) {
            state stop_pilot;
        }
        // Otherwise, stop flight and walk.
        if(llGetAgentInfo(
            (key)wasKeyValueGet(
                "corrade", 
                configuration
            )
        ) & AGENT_FLYING) state stop_flight;
        // If Corrade is not flying then walk.
        state walk;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
    state_exit() {
        llSetTimerEvent(0);
    }
}
 
state stop_pilot {
    state_entry() {
        state fly;
        llSetTimerEvent(60);
    }
    timer() {
        state on;
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
    state_exit() {
        llSetTimerEvent(0);
    }
}
 
state fly {
    state_entry() {
        // DEBUG
        llOwnerSay("Flying to agent...");
        llRegionSayTo(
            (key)wasKeyValueGet(
                "corrade", 
                configuration
            ),
            0,
            wasKeyValueEncode(
                [
                    "command", "flyto",
                    "group", wasURLEscape(
                        wasKeyValueGet(
                            "group", 
                            configuration
                        )
                    ),
                    "password", wasURLEscape(
                        wasKeyValueGet(
                            "password", 
                            configuration
                        )
                    ),
                    // move in a radius around the current primitive.
                    "position", llGetPos() + wasCirclePoint(
                        (integer)wasURLEscape(
                            wasKeyValueGet(
                                "range", 
                                configuration
                            )
                        )
                    ),
                    "fly", "True",
                    "vicinity", wasCirclePoint(
                        (integer)wasURLEscape(
                            wasKeyValueGet(
                                "range", 
                                configuration
                            )
                        )
                    ),
                    "duration", "2500",
                    "callback", wasURLEscape(callback)
                ]
            )
        );
        llSetTimerEvent(60);
    }
    timer() {
        state on;
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    http_request(key id, string method, string body) {
        llHTTPResponse(id, 200, "OK");
        if(wasKeyValueGet("command", body) != "flyto" ||
            wasKeyValueGet("success", body) != "True") {
            // DEBUG
            llOwnerSay("Flight failed...");
            state on;
        }
        state select;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
    state_exit() {
        llSetTimerEvent(0);
    }
}
 
state stop_flight {
    state_entry() {
        // DEBUG
        llOwnerSay("Landing agent for walking...");
        llRegionSayTo(
            wasKeyValueGet(
                "corrade", 
                configuration
            ),
            0,
            wasKeyValueEncode(
                [
                    "command", "fly",
                    "group", wasURLEscape(
                        wasKeyValueGet(
                            "group", 
                            configuration
                        )
                    ),
                    "password", wasURLEscape(
                        wasKeyValueGet(
                            "password", 
                            configuration
                        )
                    ),
                    "action", "stop",
                    "callback", wasURLEscape(callback)
                ]
            )
        );
        llSetTimerEvent(60);
    }
    timer() {
        state on;
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    http_request(key id, string method, string body) {
        llHTTPResponse(id, 200, "OK");
        if(wasKeyValueGet("command", body) != "fly" ||
            wasKeyValueGet("success", body) != "True") {
            // DEBUG
            llOwnerSay("Landing failed...");
            state on;
        }
        llOwnerSay("Landed...");
        state walk;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
    state_exit() {
        llSetTimerEvent(0);
    }
}
 
state walk {
    state_entry() {
        // DEBUG
        llOwnerSay("Walking to agent...");
        llRegionSayTo(
            (key)wasKeyValueGet(
                "corrade", 
                configuration
            ),
            0,
            wasKeyValueEncode(
                [
                    "command", "walkto",
                    "group", wasURLEscape(
                        wasKeyValueGet(
                            "group", 
                            configuration
                        )
                    ),
                    "password", wasURLEscape(
                        wasKeyValueGet(
                            "password", 
                            configuration
                        )
                    ),
                    // move in a radius around the current primitive.
                    "position", llGetPos() + wasCirclePoint(
                        (integer)wasURLEscape(
                            wasKeyValueGet(
                                "range", 
                                configuration
                            )
                        )
                    ),
                    "vicinity", wasCirclePoint(
                        (integer)wasURLEscape(
                            wasKeyValueGet(
                                "range", 
                                configuration
                            )
                        )
                    ),
                    "duration", "2500",
                    "callback", wasURLEscape(callback)
                ]
            )
        );
        llSetTimerEvent(60);
    }
    timer() {
        state on;
    }
    touch_end(integer num) {
        llSetColor(<.5,0,0>, ALL_SIDES);
        llResetScript();
    }
    http_request(key id, string method, string body) {
        llHTTPResponse(id, 200, "OK");
        if(wasKeyValueGet("command", body) != "walkto" ||
            wasKeyValueGet("success", body) != "True") {
            // DEBUG
            llOwnerSay("Failed to start walkto...");
            state on;
        }
        state select;
    }
    attach(key id) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
            llResetScript();
        if(
            (change & CHANGED_REGION_START) || 
            (change & CHANGED_REGION)) {
            state on;
        }
    }
    state_exit() {
        llSetTimerEvent(0);
    }
}

secondlife/scripted_agents/corrade/projects/in_world/movmement_heads-up_display/grid_follow.txt ยท Last modified: 2019/01/03 01:36 (external edit)

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


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