Shortnote

The code below reads a notecard called Simulators that contains a list of simulators line-by-line. For example, the following could be the contents of the Simulators notecard:

Royal Palm
Exploration Island
Layton Keys

The script implements an endless menu with ⇐ Back and Next ⇒ and lists all the simulators in the notecard. Do not forget to leave a blank line after the simulators or the script will not be able to read the notecard successfully.

Code

simscape_control.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2011 - 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    //
///////////////////////////////////////////////////////////////////////////
integer wasMenuIndex = 0;
list wasDialogMenu(list input, list actions, string direction) {
    integer cut = 11-wasListCountExclude(actions, [""]);
    if(direction == ">" &&  (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) {
        ++wasMenuIndex;
        jump slice;
    }
    if(direction == "<" && wasMenuIndex-1 >= 0) {
        --wasMenuIndex;
        jump slice;
    }
@slice;
    integer multiple = wasMenuIndex*cut;
    input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex);
    input = wasListMerge(input, actions, "");
    return input;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
integer wasListCountExclude(list input, list exclude) {
    if(llGetListLength(input) == 0) return 0;
    if(llListFindList(exclude, (list)llList2String(input, 0)) == -1) 
        return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
    return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
list wasListMerge(list l, list m, string merge) {
    if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return [];
    string a = llList2String(m, 0);
    if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge);
    return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge);
}
 
key nQuery = NULL_KEY;
integer nLine = 0;
list nList = [];
integer comHandle;
string simulator = "";
string URL = "";
 
default {
    state_entry() {
        llSetText("", <0,0,0>, 1);
        llRequestURL();
    }
    http_request(key id, string method, string body) {
        if(method != URL_REQUEST_GRANTED) llResetScript();
        URL = body;
        state notecard;
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        llResetScript();
    }
}
 
state notecard
{
    state_entry()
    {
        integer i = llGetInventoryNumber(INVENTORY_NOTECARD)-1;
        do {
            if(llGetInventoryName(INVENTORY_NOTECARD, i) == "Simulators")
            jump found_notecard;
        } while(--i>-1);
        llOwnerSay("Failed to find notecard.");
        return;
@found_notecard;
        nQuery = llGetNotecardLine("Simulators", nLine);
    }
 
    dataserver(key id, string data) {
        if(id != nQuery) return;
        if(data == EOF) state menu;
        if(data == "") jump next_line;
        nList +=  llGetSubString(data, 0, 23);
@next_line;
        nQuery = llGetNotecardLine("Simulators", ++nLine);
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        llResetScript();
    }
}
 
state menu {
    state_entry() {
        llSetText("Touch to teleport...", <0,1,0>, 1);
    }
    touch_start(integer num) {
        //if(llDetectedKey(0) != llGetOwner()) return;
        key av = llDetectedKey(0);
        integer comChannel = (integer)("0x8" + llGetSubString(av, 0, 6));
        comHandle = llListen(comChannel, "", av, "");
        llDialog(av, "Please choose a simulator from the following list.", wasDialogMenu(nList, ["<= Back", "", "Next =>"], ""), comChannel);
    }
    listen(integer channel, string name, key id, string message) {
        if(message == "<= Back") {
            llDialog(id, "Please choose a simulator from the following list.", wasDialogMenu(nList, ["<= Back", "", "Next =>"], "<"), channel);
            return;
        }
        if(message == "Next =>") {
            llDialog(id, "Please choose a simulator from the following list.", wasDialogMenu(nList, ["<= Back", "", "Next =>"], ">"), channel);
            return;
        }
        llListenRemove(comHandle);
        llSetText("Traveling, please wait...", <1,1,0>, 1);
        llInstantMessage("9fde451d-b77e-4fef-b7b7-ab7994dbbb41", "auth k15@4");
        llSleep(1.1-llGetRegionTimeDilation());
        llInstantMessage("9fde451d-b77e-4fef-b7b7-ab7994dbbb41", "o" + " " +  URL + " " + message);
    }
    http_request(key id, string method, string body) {
        if(method == "PUT") {
            list stats = llParseString2List(body, ["|"], []);
            llSetText(llDumpList2String(stats, "\n"), <0,1,0>, 1);
            llHTTPResponse(id, 200, "OK");
            return;
        }
        list data = llParseString2List(body, [":"], []);
        if(llList2String(data, 0) != "Teleport") return;
        if(llList2String(data, 1) == "SUCCESS") {
            llHTTPResponse(id, 200, "OK");
            return;
        }
        if(llList2String(data, 1) == "FAILED") {
            llHTTPResponse(id, 200, "OK");
            return;
        }
    }
    on_rez(integer num) {
        llResetScript();
    }
    changed(integer change) {
        llResetScript();
    }
}