multi_destination_region_teleport.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) 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);
}
 
list names = [];
list safe_names = [];
list coord = [];
 
key sit = NULL_KEY;
string firstname = "";
string selected = "false";
integer line = 0;
string destName = "";
vector dest = ZERO_VECTOR;
integer seconds = 30;
 
default {
    state_entry() {
        // set the origin
        llSetObjectDesc(wasKeyValueSet("origin", (string)llGetPos(), llGetObjectDesc()));
        // clear sit position and action
        llSetClickAction(CLICK_ACTION_NONE);
        llSitTarget(ZERO_VECTOR,ZERO_ROTATION);
        // read the destination notecard
        if(llGetInventoryType("destinations") != INVENTORY_NOTECARD) {
            llOwnerSay("Failed to find destinations notecard in inventory.\nPlease add a notecard containing the destinations");
            return;
        }
        llSetText("Reading destinations.", <1, 1, 0>, 1.0);
        llGetNotecardLine("destinations", line);
    }
    dataserver(key id, string data) {
        if(data == EOF) {
            llSetText("Read destinations.", <1, 0, 0>, 1.0);
            // check for consistency
            if(llGetListLength(names) != llGetListLength(coord)) {
                llSetText("Error reading destinations.", <1, 0, 0>, 1.0);
                llSetTimerEvent(1);
                return;
            }
            state select;
            return;
        }
        if(data == "") jump next_line;
        list dc = llParseString2List(data, ["#"], []);
        names += llList2String(dc, 0);
        coord += (vector)llList2String(dc, 1);
@next_line;
        llGetNotecardLine("destinations", ++line);
    }
    timer() {
        llResetScript();
    }
    changed(integer change) {
        llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
}
 
state select {
    state_entry() {
        llSetText("Touch me to select a destination.", <0, 1, 0>, 1.0);
    }
    touch_start(integer total_numer) {
        key click = llDetectedKey(0);
        // check if the teleport is locked to owner or unlocked
        if(wasKeyValueGet("lock", llGetObjectDesc()) == "true" && click != llGetOwner()) return;
        // block if teleporter is in use
        if(sit != NULL_KEY && click != sit) return;
        // grab user key and name
        sit = click;
        firstname = llList2String(llParseString2List(llDetectedName(0), [" "], []), 0);
        // display overhead text and set the countdown
        llSetText(firstname + " is using the teleporter (" + (string)seconds + ").", <1, 1, 0>, 1.0);
        llSetTimerEvent(1);
        // generate the list of destinations and send the dialog
        integer channel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6));
        llListen(channel, "", sit, "");
        integer i = llGetListLength(names)-1;
        safe_names = [];
        do {
            safe_names += llGetSubString(llList2String(names, i), 0, 8);
        } while(--i>-1);
        llDialog(sit, "Choose a destination to teleport to from the provided list of destinations.", wasDialogMenu(safe_names, ["⟵ Back", "◉ Options", "Next ⟶"], ""), channel);
    }
    listen(integer channel, string name, key id, string message) {
        if(message == "⟵ Back") {
            llDialog(sit, "Choose a destination to teleport to from the provided list of destinations.", wasDialogMenu(safe_names, ["⟵ Back", "◉ Options", "Next ⟶"], "<"), channel);
            return;
        }
        if(message == "Next ⟶") {
            llDialog(sit, "Choose a destination to teleport to from the provided list of destinations.", wasDialogMenu(safe_names, ["⟵ Back", "◉ Options", "Next ⟶"], ">"), channel);
            return;
        }
        if(message == "◉ Options") {
            message = "Here you can toggle the teleporter so it is restricted to the owner or not.";
            if(wasKeyValueGet("lock", llGetObjectDesc()) != "false") {
                message += "\n\nThe teleporter is currently locked to the owner.";
                jump set_message;
            }
            message += "\n\nThe teleporter is currently unlocked.";
@set_message;
            llDialog(sit, message, ["✗ Lock", "✔ Unlock", "⏏ Exit"], channel);
            return;
        }
        if(message == "✗ Lock") {
            llSetObjectDesc(wasKeyValueSet("lock", "true", llGetObjectDesc()));
            llDialog(sit, "Here you can toggle the teleporter so it is restricted to the owner or not.\n\nThe teleporter is currently locked to the owner.", ["✗ Lock", "✔ Unlock", "⏏ Exit"], channel);
            return;
        }
        if(message == "✔ Unlock") {
            llSetObjectDesc(wasKeyValueSet("lock", "false", llGetObjectDesc()));
            llDialog(sit, "Here you can toggle the teleporter so it is restricted to the owner or not.\n\nThe teleporter is currently unlocked.", ["✗ Lock", "✔ Unlock", "⏏ Exit"], channel);
            return;
        }
        if(message == "⏏ Exit") {
            llDialog(sit, "Choose a destination to teleport to from the provided list of destinations.", wasDialogMenu(safe_names, ["⟵ Back", "◉ Options", "Next ⟶"], ""), channel);
            return;
        }
        do {
            destName = llList2String(names, 0);
            if(llSubStringIndex(destName, message) != -1) {
                dest = llList2Vector(coord, 0);
                jump ready;
            }
            names = llDeleteSubList(names, 0, 0);
            coord = llDeleteSubList(coord, 0, 0);
        } while(llGetListLength(names) != 0);
        llSetText("Could not find destination.", <1, 0, 0>, 1.0);
        seconds = 1;
        return;
@ready;
        selected = "true";
        seconds = 10;
        llSitTarget(<0,0,1>,ZERO_ROTATION);
        llSetClickAction(CLICK_ACTION_SIT);
    }
    changed(integer change) {
        if(change & CHANGED_LINK) {
            key a = llAvatarOnSitTarget();
            if(a) if(a == sit) state teleport;
            llUnSit(a);
            return;
        }
        llResetScript();
    }
    timer() {
        if(selected == "true") {
            llSetText(firstname + ", touch to teleport to " + destName + " (" + (string)seconds + ").", <1, 1, 0>, 1.0);
            jump continue;
        }
        if(selected == "false") {
            llSetText(firstname + " is using the teleporter (" + (string)seconds + ").", <1, 1, 0>, 1.0);
            jump continue;
        }
@continue;
        if(--seconds == 0) llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
}
 
state teleport {
    state_entry() {
        // set timeout
        llSetTimerEvent(10);
        // clear sit position and action
        llSetRegionPos(dest);
        // request to set camera
        llRequestPermissions(sit, PERMISSION_CONTROL_CAMERA);
    }
    run_time_permissions(integer perm) {
        // set the camera so the viewer follows the agent
        // this works if the viewer is not zoomed-in on
        // the teleport pad
        if(perm & PERMISSION_CONTROL_CAMERA) {
            llSetCameraParams([
                CAMERA_ACTIVE, 1,
                CAMERA_BEHINDNESS_ANGLE, 45.0,
                CAMERA_BEHINDNESS_LAG, 0.5,
                CAMERA_DISTANCE, 8.0,
                CAMERA_FOCUS_LAG, 0.05 ,
                CAMERA_FOCUS_LOCKED, TRUE,
                CAMERA_FOCUS_THRESHOLD, 0.0,
                CAMERA_PITCH, 20.0,
                CAMERA_POSITION_LAG, 0.1,
                CAMERA_POSITION_LOCKED, TRUE,
                CAMERA_POSITION_THRESHOLD, 0.0,
                CAMERA_FOCUS_OFFSET, <3,0,2>
            ]);
            llReleaseCamera(sit);
        }
        llSetTimerEvent(0.05);
    }
    timer() {
        key a = llAvatarOnSitTarget();
        if(a) llUnSit(a);
        llSetRegionPos((vector)wasKeyValueGet("origin", llGetObjectDesc()));
    }
    on_rez(integer num) {
        llSetRegionPos((vector)wasKeyValueGet("origin", llGetObjectDesc()));
        llResetScript();
    }
    changed(integer change) {
        llSetRegionPos((vector)wasKeyValueGet("origin", llGetObjectDesc()));
        llResetScript();
    }
}

secondlife/multiple_destination_teleport/region_teleport.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.