I have been working on a scripted system that lets vehicles "see" the road and then drive by themselves. The road script replicates, sets the name with the key to the next prim and then removes itself from the prim. The vehicle can then use llKey2Name calls to get the road position and the next key.
http://www.lslwiki.com/lslwiki/wakka.php?wakka=AutobahnRoad
The problem is that I suck at math.
This script works fine when the prim is made so that ZERO_ROTATION points east, but I built my test road with the prims at 90,0,180 so that I could use the taper functions.
The problem is with m_RotationAdjustment in the UpdateDescr() function
CODE
//public Road configuration script
//
//Released into the public domain by grumble Loudon and LaserFur Leonov
//
//V0.4 (not done)
//
//defaults are used if not in notecard
integer m_Channel = 65;
integer m_lane = 1;
string m_RoadName = "TestRoad";
//Rotate the road prim east and touch to get "Actual Prim rotation"
rotation m_RotationAdjustment = <-0.70711, 0.00000, 0.00000, 0.70711>;
vector m_LaneAdjustment = <0.0,0.0,1.5>; //adjust to 1m above surface
//****************************************************************************************
integer m_DetectedScan = -1;
integer m_UpdateScript = 0;
integer m_MessageTimer = 0;
integer m_reSendMessage = 0;
string m_reSendMessageStr = "";
//current data
key m_lane1Key;
vector m_LanePos;
rotation m_LaneRot;
vector m_testPos;
//****************************************************************************************
UpdateFloatText()
{
string Text;
Text ="";
Text += "Lane " + (string)m_lane + "\n";
if (m_DetectedScan >= 0){
Text += "Road is sensing " + (string)m_DetectedScan + " Road Prims";
};
Text += "\n Actual Prim rotation = " + (string)llGetRot();
Text += "\n Lane pos = " + (string)m_LanePos;
Text += "\n Lane Rot = " + (string)m_LaneRot;
Text += "\n Adj pos = " + (string)m_testPos;
llSetText(Text ,<1,1,1>,1);
}
//*******************************************************************************
UpdateDescr(){
//object name = PublicRoad;0;Lane;speed;name;<pos 1m Up>;<Rotation>;key1;key2 ect...
vector myPos = llGetPos();
rotation myRot = llGetRot();
// rotation tRot = m_RotationAdjustment; //inverse //ZERO_ROTATION /
m_LaneRot = myRot;// * tRot; // adjust for custom direction from prims view
vector LaneAdj = m_LaneAdjustment * m_LaneRot ; //adjust the lane surface
m_testPos = LaneAdj;
m_LanePos = myPos + LaneAdj; //1m above road surface
string name;
name = "PublicRoad;0;"; //prim name and version
name += (string)m_lane + ";"; // Lane number
name += "20;"; //recomended Speed limit in m/sec
name += m_RoadName + ";"; //road name
name += (string)m_LanePos + ";"; // X,y,z Lane position
name += (string)m_LaneRot + ";"; // rotation.
//<0,0,0,1> points east,
//<0,0,-1,0> points west
//<0,0, 0.707, 0.707 points north
//<0,0, -0.707, 0.707 points south
name += (string)m_lane1Key; //Key to next prim
llSetObjectName(name);
UpdateFloatText();
}// update
//********************************************************************************
integer ProcessCommand(string message,integer FromNotecard) // from either chat or notecard
{// processes message
//returns true if message should be re sent on chat
integer resend = -1;
if (message == "Scan"){
llSensorRepeat("",NULL_KEY,PASSIVE|ACTIVE,18,0.5,3.1);
resend = 0;
}else if (message == "stop"){
llSensorRemove();
m_DetectedScan = -1;
if (!FromNotecard){
llSleep(.2);
llWhisper(m_Channel,message);
};
}else if (message == "remove"){
if (!FromNotecard){
llSetText("" ,<1,1,1>,1);
llSleep(.2);
llWhisper(m_Channel,message);
llRemoveInventory(llGetScriptName());
};
resend = 0;
}else if (message == "update"){
if (!FromNotecard){
m_UpdateScript = TRUE; //rez start pram tells next script
};
}else{
UpdateDescr();
};//
return resend ;
}//ProcessCommand
//********************************************************************************
default
{
state_entry()
{
//used to get m_RotationAdjustment
//llOwnerSay( (string) (ZERO_ROTATION / llGetRot()));
llSetRemoteScriptAccessPin(123);
llListen(m_Channel,"",NULL_KEY,"");
UpdateDescr();
m_lane1Key = NULL_KEY;
if (llGetStartParameter() == 1) m_UpdateScript = TRUE; //replicate
llSensorRepeat("",NULL_KEY,PASSIVE|ACTIVE,18,0.5,2.4);
llSetTimerEvent(1.2);
} //Entry
//*****************************************************************************
on_rez(integer Reznumber){
if (Reznumber == 1){
// replicate
m_UpdateScript = TRUE;
}else{
llResetScript();
};
}
//*****************************************************************************
timer(){
if (m_MessageTimer != 0) --m_MessageTimer;
} //timer
//*****************************************************************************
touch(integer num){
llOwnerSay(" Actual Prim rotation = " + (string)llGetRot());
}
//*****************************************************************************
listen(integer channel, string name, key id, string message){
if (m_MessageTimer == 0) //we only respond to one command every 3 seconds
{
m_MessageTimer = 2;
if ( m_reSendMessageStr != message ) //repeating message?
{
m_reSendMessageStr = message;
m_reSendMessage = ProcessCommand(message,FALSE);
}; //same
}; //timer
}// listen
//*****************************************************************************
sensor(integer Num_Detected)
{
m_DetectedScan = 0;
integer useNum = -1;
vector myPos = llGetPos();
float closest = 100;
integer i;
for (i = 0 ; i < Num_Detected; ++i){
string name = llDetectedName(i);
key dKey = llDetectedKey(i);
if (llGetSubString(name,0,10) == "PublicRoad;"){
if ( llDetectedOwner(i) == llGetOwner()){
//does it need upating
if (m_UpdateScript){
if (llDetectedType(i) == PASSIVE){ //no script running
if ( llDetectedOwner(i) == llGetOwner()){
llRemoteLoadScriptPin(dKey, llGetScriptName(), 123, TRUE, 1);
jump ExitFor; //rescan
};//owner
};//passive
}; // update
//is it my lane?
list Prams = llParseStringKeepNulls(name,[";"],[]);
integer listLenght = llGetListLength(Prams);
if (listLenght >= 7 ){
//0 PublicRoad
//1 version
integer DetLane = (integer)llList2String(Prams,2);//2 Lane
//3 speed
//m_DetectedRoadName = llList2String(Prams,4); //4 Name
if (DetLane == m_lane){
//is it ahead of me?
vector NextPos = llDetectedPos(i);
float dist = llVecDist(myPos , NextPos);
// check angle
// To do
if (dist < closest ){
useNum = i;
closest = dist;
};
++m_DetectedScan;
};//lane
};//list
}; // owner
};//name
}; //sensor for
if (useNum != -1){
key nearestKey = llDetectedKey(useNum);
if (m_lane1Key != nearestKey){
m_lane1Key = nearestKey;
UpdateDescr();
};
m_UpdateScript = FALSE;
};
@ExitFor;
//UpdateDescr(); //test
UpdateFloatText();
}//sensor
no_sensor()
{
m_DetectedScan = 0;
//UpdateDescr(); //test
UpdateFloatText();
}//no sensor
//*****************************************************************************
} //default
//*****************************************************************************