Code: Jump Gates

multiple_destination_teleport.lsl
//////////////////////////////////////////////////////////
// (c) Wizardry and Steamworks - 2012, License GPLv3    //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
// Calculate jump gates
list jumpGates(vector iPos, vector dPos, integer jumpDistance) {
    list gates = [];
    if(jumpDistance == 0) return gates;
    float dist = llVecDist(iPos, dPos);
    if(dist > jumpDistance) {
        // We move 1/jumpDistance from the initial position
        // towards the final destination in the description.
        iPos = iPos + jumpDistance * (dPos-iPos) / dist;
        gates += iPos;
        return gates + jumpGates(iPos, dPos, jumpDistance);
    }
    return gates + jumpGates(iPos, dPos, --jumpDistance);
}
 
list dNames = [];
list dCoord = [];
list jumps = [];
vector sPos = ZERO_VECTOR;
key avSit = NULL_KEY;
key ncKey = NULL_KEY;
integer gItra = 0;
 
default
{
    state_entry() {
        llSetClickAction(CLICK_ACTION_NONE);
 
        // Grab local position.
        sPos = llGetPos();
        llSitTarget(ZERO_VECTOR,ZERO_ROTATION);
 
        // Read notecard.
        if(llGetInventoryType("Destinations") == INVENTORY_NOTECARD) jump found_notecard;
        llOwnerSay("Failed to find notecard.");
        return;
@found_notecard;
        gItra = 0;
        ncKey = llGetNotecardLine("Destinations", gItra);
    }
 
    changed(integer change) {
        if(change & CHANGED_INVENTORY) {
            llResetScript();
        }
    }
    dataserver(key id, string data) {
        if(id != ncKey) return;
        if(data == EOF) {
            llSay(0, "Teleporter ready.");
            state sit;
            return;
        }
        if(data == "") jump next_line;
        list dc = llParseString2List(data, ["#"], []);
        dNames += llList2String(dc, 0);
        dCoord += llList2String(dc, 1);
@next_line;
        ncKey = llGetNotecardLine("Destinations", ++gItra);
    }
}
 
state sit
{
    touch_start(integer total_numer) {
        avSit = llDetectedKey(0);
        integer comChannel = ((integer)("0x"+llGetSubString((string)avSit,-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
        llListen(comChannel, "", avSit, "");
        llDialog(avSit, "Please chose a destination:\n", dNames, comChannel);
        llSetTimerEvent(30);
    }
 
    listen(integer channel, string name, key id, string message) {
        llInstantMessage(avSit, "Please sit on the teleporter for transport.");
        llSetClickAction(CLICK_ACTION_SIT);
        llSitTarget(<0,0,1>,ZERO_ROTATION);
        dCoord = (list)llList2String(dCoord, llListFindList(dNames, (list)message));
    }
    changed(integer change) {
        if(change & CHANGED_LINK) {
            key av = llAvatarOnSitTarget();
            if(av) if(av == avSit) {
              state move;
            }
            llUnSit(av);
        }
    }
    timer() {
        llInstantMessage(avSit, "Teleporter timeout. Please touch the teleporter again for destinations.");
        llResetScript();
    }
}
 
state move
{
    state_entry() {
        // Grab local position again.
        sPos = llGetPos();
        // Grab distance from description
        vector oPos = ZERO_VECTOR;
        list oDesc = llParseString2List(llList2String(dCoord, 0), ["<", ">", ","], []);
        oPos.x = llList2Float(oDesc, 0);
        oPos.y = llList2Float(oDesc, 1);
        oPos.z = llList2Float(oDesc, 2);
 
        // Calculate list of intermediary jump gates.
        jumps = jumpGates(llGetPos(), oPos, 10);
        // 1.175494351E-38 is the smallest float.
        llSetTimerEvent(1.175494351E-38);
 
    }
    timer() {
        if(llGetListLength(jumps) == 0) {
            llSetTimerEvent(0);
            key a = llAvatarOnSitTarget();
            if(a) llUnSit(llAvatarOnSitTarget());
            state recall;
        }
        vector nPos = llList2Vector(jumps, 0);
        jumps = llDeleteSubList(jumps, 0, 0);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, nPos]);
    }
}
 
state recall
{
    state_entry() {
        jumps = jumpGates(llGetPos(), sPos, 10);
        // 1.175494351E-38 is the smallest float.
        llSetTimerEvent(1.175494351E-38);
    }
    timer() {
        if(llGetListLength(jumps) == 0) {
            llSetTimerEvent(0);
            llResetScript();
        }
        vector nPos = llList2Vector(jumps, 0);
        jumps = llDeleteSubList(jumps, 0, 0);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, nPos]);
    }
}