I made the "size" of the waypoints 10m as I expect vehicles to be used in the races and that's the standard width of most roads. this does mean that you can't make waypoints too close together or else the slight delay in the script with the timer function will skip over a waypoint when you reach it. the example racetrack is a boattrack for a single sim called "central park". I included a series of 3 waypoints that are too close together on a bend to illustrate this example. hopefully someone with greater scripting knowledge will be able to make this into an actual usable item for races.
**The script for the HUD arrow** make sure that when you create the prim it "points" up with zero rotations.
CODE
string notecard = "Central Park Boat Track";
integer current_noteline = 0;
integer current_target = -1;
integer listener;
list locations;
list descriptions;
string passed_text;
PointToTarget() {
if (llGetAttached() == 0) { llSetRot(ZERO_ROTATION); }
else {
vector gpos = llGetRegionCorner() + llGetPos();
vector target = llList2Vector(locations,current_target);
rotation rot = llRotBetween(<0,0,1>,llVecNorm(target-gpos));
llSetRot(rot/llGetRot());
}
}
default {
state_entry() {
llSetRot(ZERO_ROTATION);
llGetNotecardLine(notecard,current_noteline);
}
attach(key id) { llResetScript(); }
dataserver(key qid, string data) {
if (data == EOF) {
llInstantMessage(llGetOwner(),(string)current_noteline+" locations loaded into memory.");
state wait;
}
else {
current_noteline++;
list words = llParseString2List(data,[" //","//"],[]);
//hack - llList2Vector returned NULL_VECTOR
locations += (vector)llList2String(words,0);
descriptions += llList2String(words,1);
llGetNotecardLine(notecard,current_noteline);
}
}
}
state wait {
state_entry() { llSetRot(ZERO_ROTATION); }
//touch_start(integer total) { llInstantMessage(llGetOwner(),(string)(llGetRegionCorner() + llGetPos())); }
touch_start(integer total) { state ready; }
}
state ready {
on_rez(integer arg) { llResetScript(); }
attach(key id) { llResetScript(); }
state_entry() {
current_target++;
listener = llListen(0,"",llGetOwner(),"");
llSetTimerEvent(0.01);
PointToTarget();
llInstantMessage(llGetOwner(),passed_text+" "+llList2String(descriptions,current_target));
}
timer() {
PointToTarget();
float distance = llVecDist(llGetRegionCorner() + llGetPos(),llList2Vector(locations,current_target));
llSetText( (string) distance, <1,1,1>,1);
if (distance < 10) { state next; }
}
listen(integer channel, string name, key id, string message) {
}
}
state next {
on_rez(integer arg) { llResetScript(); }
attach(key id) { llResetScript(); }
state_entry() {
passed_text = " ";
if (current_target == llGetListLength(locations) - 1) {
current_target = -1; passed_text = "";
llSetText("",<0,0,0>,1);
llInstantMessage(llGetOwner(),"Track Complete!");
state wait;
} else {
state ready;
}
}
}
***The notecard*** make a notecard in the pointer's inventory called "Central Park Boat Track" with this info
CODE
250652.71875, 264432.09375, 20.40334> // Starting Line
<250636.64062, 264389.09375, 19.83364> //
<250633.89062, 264341.37500, 20.22007> //
<250637.37500, 264295.71875, 19.97462> //
<250657.70312, 264269.59375, 20.15921> //1st Bridge
<250685.76562, 264258.12500, 20.14636>//
<250735.96875, 264273.25000, 20.37091>//
<250767.14062, 264302.59375, 20.74835>//
<250788.43750, 264314.62500, 20.54906> //
<250820.73438, 264311.15625, 20.60225> //
<250836.12500, 264299.46875, 20.49066> //
<250838.53125, 264275.03125, 19.94985> //
<250824.96875, 264263.62500, 20.18031> //Hard Right
<250791.42188, 264287.65625, 19.70562> // 2nd Bridge
<250786.14062, 264317.96875, 20.00567> //Counter clock wise around the Fountain
<250783.48438, 264336.06250, 19.51165> //
<250755.95312, 264326.59375, 20.02677> //
<250745.54688, 264286.62500, 19.73256> //
<250719.06250, 264269.28125, 19.98258> //
<250669.93750, 264266.15625, 20.08066> //1st Bridge
<250642.95312, 264291.18750, 20.00258> //Hard right
<250637.43750, 264417.28125, 22.76606> //Finish Line
I must thank Dirty McLean for all the help he provided with the notecard reader