Can support vehicles up to 256 Prims

 

float LINEAR_TAU = 0.75;             
float TARGET_INCREMENT = 90;
float ANGULAR_TAU = 10;
float ANGULAR_DAMPING = 0;
float THETA_INCREMENT = 10;// 0.3 
integer LEVELS = 0;
vector pos;
vector face;
float brake = 0.5;
key gOwnerKey; 
string gOwnerName;
key gToucher;
key Driver;

string gFLYING = "FALSE";
key id;
integer nudge = FALSE;
vector POSITION; 
integer auto=FALSE;



default
{  on_rez(integer start_param)
    {
        llResetScript();
    } 
    state_entry()
    {

        llSetTimerEvent(0.0);
        llMessageLinked(LINK_ALL_CHILDREN, 0, "stop", id);
        llSetPos(llGetPos());
        llRotLookAt(llGetRot(), 0, 0);
        LEVELS = CONTROL_FWD | CONTROL_BACK | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT | CONTROL_UP | CONTROL_DOWN | CONTROL_LEFT | CONTROL_RIGHT | CONTROL_ML_LBUTTON;

        TARGET_INCREMENT = 0.5;
        llSitTarget(<0.3, 0.0, 0.50>, ZERO_ROTATION);  // good for default cube.
        llSetCameraEyeOffset(<-10.0, 1.0, 3.0>);
        llSetSitText("Drive");
        llSetTouchText("Remote");
        llSetCameraAtOffset(<0, 1.0, 0>);
        }
         touch_start(integer total_number)
    {
           if (gFLYING == "FALSE")
            {
                gFLYING = "TRUE";
               // llSetStatus(STATUS_PHYSICS, TRUE);
                Driver=llDetectedKey(total_number - 1);
                state StateDriving;
            }
    
}


}state StateDriving
{
    state_entry()
    {
        llRequestPermissions(Driver, PERMISSION_TAKE_CONTROLS);
        llSetPos(llGetPos());
        llSetRot(llGetRot());
        
     
    }
    
    touch_start(integer total_number)
    {
        if (llDetectedKey(total_number - 1)==Driver)
        {
            gFLYING = "FALSE";
            auto=FALSE;
            llSleep(1.5);
            llMessageLinked(LINK_ALL_CHILDREN, 0, "stop", id);
            llSetTimerEvent(0.0);
            llReleaseControls();
            llResetScript();
        }
    }
        
   

    run_time_permissions(integer perm)
    {
        if (perm == PERMISSION_TAKE_CONTROLS)
        {
            llTakeControls(LEVELS, TRUE, FALSE);

        }
        else
        {
           
            llSetTimerEvent(0.0);
            gFLYING = "FALSE";
            llSleep(1.5);
            llResetScript();
        }
    }
    control(key driver, integer levels, integer edges)
    {
        pos *= brake;
        face.x *= brake;
        face.z *= brake;
        nudge = FALSE;
        
        if (levels & CONTROL_FWD)
        {
            if (pos.x < 0) { pos.x=0; }
            else { pos.x += TARGET_INCREMENT; }
            nudge = TRUE;
        }
        if (levels & CONTROL_BACK)
        {
            if (pos.x > 0) { pos.x=0; }
            else { pos.x -= TARGET_INCREMENT; }
            nudge = TRUE;
        }
        if (levels & CONTROL_UP)
        {
            
            if(pos.z<0) { pos.z=0; }
            else { pos.z += TARGET_INCREMENT; }
            face.x=0;
            nudge = TRUE;
        }
        if (levels & CONTROL_DOWN)
        {
            
            if(pos.z>0) { pos.z=0; }
            else { pos.z -= TARGET_INCREMENT; }
            face.x=0;
            nudge = TRUE;
        }
        if ((levels) & (CONTROL_LEFT|CONTROL_ROT_LEFT))
        {
            if (face.z < 0) { face.z=0; }
            else { face.z += THETA_INCREMENT; }
            nudge = TRUE;
        }
        if ((levels) & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
        {
            if (face.z > 0) { face.z=0; }
            else { face.z -= THETA_INCREMENT; }
            nudge = TRUE;
        }
               
        if (nudge)
        {
            vector world_target = pos * llGetRot(); 
            llSetPos(llGetPos() + world_target);
    
            vector eul = face; 
            eul *= DEG_TO_RAD; 
            rotation quat = llEuler2Rot( eul ); 
            rotation rot = quat * llGetRot();
            llSetRot(rot);
        }
    }
    
    timer()
    {
        pos *= brake;
        if (pos.x < 0) { pos.x=0; }
        else { pos.x += TARGET_INCREMENT; }
        vector world_target = pos * llGetRot(); 
        llSetPos(llGetPos() + world_target);
    }
    
}