07-17-2007 09:03
CODE
// Menu Driven Transport Script, by Shadow Subagja 07/17/2007
//
// Reads a notecard called "TransportLocations" with each line formatted
// as follows:
// LOCATION|<X,Y,Z>|DIRECTION_TO_FACE
// where:
// LOCATION = name of destination, which will show up on the touch menu
// <x,y,z> = global vector coordinates of destination
// DIRECTION_TO_FACE = direction Transport should face at destination
// (NORTH,SOUTH,EAST,WEST)
// Example:
// GROUND|<245.984,251.110,47.994>|SOUTH


//Communication Channel for llDialog
integer Transport_channel=990;
integer listenHandle;

//NoteCard
string PositionCardName="TransportLocations";
integer PositionCardLine=0;
key DataQueryId;

//Lists To Populate from NoteCard
list PositionNameList;
list PositionVectorList;
list PositionDirectionList;


// warpPos - movement function
// R&D by Keknehv Psaltery, 05/25/2006
// with a little pokeing by Strife, and a bit more
// some more munging by Talarus Luan
// Final cleanup by Keknehv Psaltery
// Compute the number of jumps necessary
warpPos( vector destpos )
{
integer jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1;
// Try and avoid stack/heap collisions
if (jumps > 100 )
jumps = 100; // 1km should be plenty
list rules = [ PRIM_POSITION, destpos ]; //The start for the rules list
integer count = 1;
while ( ( count = count << 1 ) < jumps)
rules = (rules=[]) + rules + rules; //should tighten memory use.
llSetPrimitiveParams( rules + llList2List( rules, (count - jumps) << 1, count) );
}

// Rotate the Transport to face a compass direction
RotateTransport(string direction)
{
if(direction=="NORTH")
{
llSetRot(llEuler2Rot( < 0, 0, 180 * DEG_TO_RAD > ));
}
else if(direction=="SOUTH")
{
llSetRot(llEuler2Rot( < 0, 0, 0 * DEG_TO_RAD > ));
}
else if(direction=="EAST")
{
llSetRot(llEuler2Rot( < 0, 0, 90 * DEG_TO_RAD > ));
}
else if(direction=="WEST")
{
llSetRot(llEuler2Rot( < 0, 0, 270 * DEG_TO_RAD > ));
}
}

default
{
state_entry()
{
// Set the camera to behind and slightly above, assuming
// an initial facing direction of SOUTH.
// +ve Y values are to the north of object
// -ve Y values are to the south of object

// Location of Camera itself
llSetCameraEyeOffset(<0, 3, 3>);

// point in space that camera is facing
llSetCameraAtOffset(<0, -2, 2>);

// go parse notecard
state readingLocs;
}
}

state readingLocs
{
state_entry()
{
llOwnerSay("Reading: "+PositionCardName);
PositionCardLine = 0;

//read first line of card, then wait for callback
DataQueryId = llGetNotecardLine(PositionCardName,PositionCardLine);
}

// handler for llGetNotecardLine function
dataserver(key queryid, string data)
{
if(queryid == DataQueryId)
{
// check if note card end is reached
if(EOF!=data)
{
// parse line into a list based on | separator character
list tmp = llParseString2List(data, ["|"], []);

// store values from card based on expected line format
PositionNameList += llList2String(tmp,0);
PositionVectorList += (vector)llList2String(tmp,1);
PositionDirectionList += llList2String(tmp,2);

// read next line
DataQueryId = llGetNotecardLine(PositionCardName,++PositionCardLine);
}
else
{
// done parsing card, move on to next state
state active;
}
}
}

// since it uses notecards, reset when inventory changes
changed(integer change)
{
if (change&CHANGED_INVENTORY)
llResetScript();
}

}

state active
{

// when touched raise a dialog with destination options
touch_start(integer total_number)
{
// here is a good place to check for owner, or in this case whether
// the user's gorup is the same as that of the Transport
if(llDetectedGroup(0))
{
// activate listener
listenHandle=llListen( Transport_channel, "", "", "");
// raise dialog
llDialog( llDetectedKey( 0 ), "Transport", PositionNameList, Transport_channel);
}
else
{
llSay(0, "Only group members may use the Transport");
}
}

// listener will be called when dialog selection is made
listen( integer channel, string name, key id, string message )
{
// find index of selection in name list
integer index = llListFindList(PositionNameList,[message]);
// move to corresponding index in position list
warpPos(llList2Vector(PositionVectorList,index));
// rotate Transport to corresponding index in direction list
RotateTransport(llList2String(PositionDirectionList,index));
llListenRemove(listenHandle);
}

// since it uses notecards, reset when inventory changes
changed(integer change)
{
if (change&CHANGED_INVENTORY)
llResetScript();
}

}