////////////////////////////////////////////////////////////////
// 1000m Menu-driven Intra-Sim Teleporter
/////////////////////////////////////////////////////////////////
// Design:
//
// Menu system sets target location from pre-defined list
// When a user sits on the object it moves to the target location,
// unists the avatar, and returns. Use of WarpPos by Keknehv
// Psaltery makes this possible beyond the 10 metre limit normally
// associated with position changes.
/////////////////////////////////////////////////////////////////
// Quirks:
//
// If you move the teleporter after placing it you need to
// reset this script so it learns it's new home position
//
// All target locations must be under 768m in height
//
// All target locations must be in teh same sim as teh teleport
//
// Max distance is 1000m... but it's impossible to move more than
// 850m in a single sim without going higher than 768m.
//
// If use of llSetPrimitiveParams to bypass the 10m movement
// restriction is ever nerfed then this script will stop working.
/////////////////////////////////////////////////////////////////
// Usage
//
// Edit the list of locations.
// Place script in a prim
// Touch to get a menu to set destination
// Right click -> sit to teleport
/////////////////////////////////////////////////////////////////
//user variables, you should set these.
// A list of locations (names and position)
// This is for one sim only; teh sim the teleporter is in.
// No more than 12 locations or you'll get an error from llDialog
// Buttons are drawn left to right, bottom to top, in row of three.
list gLocations=[
"2nd Level",<196,119,241>,
"3rd Level",<195,119,341>,
"4th Level",<195,119,442>
];
// Text for the "pie menu"
string gSitText="Teleport";
// If you don't enable this teh teleport object will be left at the destination.
integer gReturnToStartPos=TRUE;
// Alpha for hovertext
float gTextAlpha=0.5;
// colour for hovertext
vector gTextColour=<1.0,1.0,1.0>;
/////////////////////////////////////////////////////////////////
//Runtime variables. You should leave these alone.
vector gStartPos=<0,0,0>;
key gAvatarID=NULL_KEY;
integer gChannel=574368374;
vector gTargetPos=<0,0,0>;
//////////////////////////////////////////////////////////////////
// Function for instant intra-sim movement
warpPos( vector destpos )
{
integer jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1;
if (jumps > 100 )
{
jumps = 100;
}
list rules = [ PRIM_POSITION, destpos ];
integer count = 1;
while (( count = count << 1 ) < jumps)
{
rules = (rules=[]) + rules + rules;
}
llSetPrimitiveParams( rules + llList2List( rules, (count - jumps) << 1, count) );
if (llVecDist(destpos, llGetPos()) > 0.01)
{
jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1;
count = 0;
while ( count < jumps)
{
llSetPos(destpos);
count++;
}
}
}
//////////////////////////////////////////////////////////////////
// Main codeblock.
default
{
state_entry() {
llSetSitText(gSitText);
gStartPos = llGetPos();
llSitTarget(<0,0,1>,ZERO_ROTATION);
gChannel=(integer)llFrand(1000000000)+1000000000;
llSetText(llList2String(gLocations,0),gTextColour, gTextAlpha);
gTargetPos=(llList2Vector(gLocations,1));
llListen(gChannel,"",NULL_KEY,""

;
}
on_rez(integer start_param){
llResetScript();
}
changed(integer change){
if(change & CHANGED_LINK)
{
gAvatarID = llAvatarOnSitTarget();
if(gAvatarID != NULL_KEY)
{
warpPos(gTargetPos);
llSleep(1);
llUnSit(gAvatarID);
llSleep(1);
if (gReturnToStartPos){
warpPos(gStartPos);
}
}
}
}
touch_start(integer number){
list options=[];
integer i =0;
for(i=0;i<llGetListLength(gLocations);i=i+2){
options+=[llList2String(gLocations,i)];
}
llDialog(llDetectedKey(0),"Choose target location",options,gChannel);
}
listen(integer channel, string name, key id, string message){
integer index=llListFindList(gLocations,[message]);
if (index==-1) return;
llSetText(llList2String(gLocations,index),gTextColour,gTextAlpha);
gTargetPos=llList2Vector(gLocations,index+1);
} }