Jump to content

Hover bike


Quistess Alpha
 Share

You are about to reply to a thread that has been inactive for 715 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Just kinda dumping this here because I don't plan on doing much with it, other than using it in my own personal vehicle of course.

Normally I'd push important configuration constants to global variables but the script's so short it's not much of a pain to find the lines on which specific numbers are used, and I think I have it mostly to where I'm comfortable with how it handles.

rotation uVectorRoll2Rot(vector v,float r) // only used for less sticky version and mouselook.
{   v = <llAtan2(v.y,v.x), // Yaw
        -llAtan2(v.z,llVecMag(<v.x,v.y,0>)), // Pitch
        r>; // Roll
    return  <llSin(v.z/2),0,0,llCos(v.z/2)> *
            <0,llSin(v.y/2),0,llCos(v.y/2)> *
            <0,0,llSin(v.x/2),llCos(v.x/2)> ;
}
float gHalfHeight = 0.25; // distance from center to a bit below vehicle.
float gSpeed = 2.0;
float gHover = 2.5;
default
{
    state_entry()
    {   llSitTarget(<0,0.05,0.25>,ZERO_ROTATION);
        llSetCameraEyeOffset(<-5, 0, 2>);
        llSetCameraAtOffset(<2, 0, 0.5>);
        llSetSoundQueueing(TRUE);
    }
    changed(integer c)
    {   if(c&CHANGED_LINK)
        {   key who = llAvatarOnSitTarget();
            if(who)
            {   llRequestPermissions(who,PERMISSION_TAKE_CONTROLS|PERMISSION_TRIGGER_ANIMATION);
            }else
            {   llReleaseControls();
                llSetStatus(STATUS_PHYSICS,FALSE);
                // be level with ground after unsat:
                rotation r = llGetRot();
                llSetRot(r*llRotBetween(llRot2Up(r),<0,0,1>));
                
                llStopSound();
                //llSleep(0.2);
                llPlaySound("1ee264f8-b19d-b691-ee0e-5e922826740d",1.0);
            }
        }
        if(c&CHANGED_REGION) // not perfect but works well enough.
        {   llSetStatus(STATUS_PHYSICS,FALSE);
            do{
                llSleep(0.1);
            }while(llAvatarOnSitTarget()==NULL_KEY);
            llSetStatus(STATUS_PHYSICS,TRUE);
        }
    }
    run_time_permissions(integer perms)
    {   if(perms&PERMISSION_TRIGGER_ANIMATION)
        {   llStartAnimation("motorcycle_sit");
            llStopAnimation("sit");
        }
        if(perms&PERMISSION_TAKE_CONTROLS)
        {   llTakeControls(CONTROL_FWD|CONTROL_BACK|CONTROL_LEFT|CONTROL_RIGHT
                |CONTROL_ROT_LEFT|CONTROL_ROT_RIGHT|CONTROL_UP|CONTROL_DOWN,TRUE,FALSE);
            llPlaySound("2f61da29-8665-34d2-8433-68e2abbbc69a",1.0);
            llSleep(9.0); // only needs to be >0.5 or so, but neat to not start while reving up.
            llLoopSound("b7362489-73ac-36c9-8f25-573054fe9db5",0.75); 
            // occasionaly loops wrong sound becaus eSL is buggy :/
            llSetStatus(STATUS_PHYSICS,TRUE);
        }
    }
    control(key ID, integer level, integer edge)
    {   
        rotation vehicleRot = llGetRot();
        vector vehicleFwd = llRot2Fwd(vehicleRot);
        vector vehicleUp = llRot2Up(vehicleRot);
        
        vector pos = llGetPos();
        list ray = llCastRay(pos-(gHalfHeight*vehicleUp),
            pos-((2.5+gHover)*vehicleUp)/*+(0.75*vehicleFwd)*/,
            [RC_DATA_FLAGS,RC_GET_NORMAL,RC_REJECT_TYPES,RC_REJECT_PHYSICAL|RC_REJECT_AGENTS]);
        key rayKey = llList2Key(ray,0);
        vector rayPos = llList2Vector(ray,1);
        vector rayNormal = llList2Vector(ray,2);
        integer raySuccess = llList2Integer(ray,-1);
        
        vector velocity;
        if(raySuccess)
        {   velocity.z = gHover-llVecDist(pos,rayPos);
        }else
        {   rayNormal = <0,0,1>;
        }
        
        // - - - Ride on water - - -
        float water = llWater(<0,0,0>);
        // if near water height and the raycast failed, or hit something under the water
        if(pos.z<(water+gHover) && (!raySuccess || rayPos.z<water))
        {   velocity.z = gHover-(pos.z-water);
            rayNormal = <0,0,1>;
            raySuccess = TRUE;
        }
        // - - - End Ride on Water
        
        integer mouselook = llGetAgentInfo( ID ) & AGENT_MOUSELOOK;
        integer turn = !!(level&CONTROL_ROT_LEFT)-!!(level&CONTROL_ROT_RIGHT);
        if(level&CONTROL_FWD)
        {   velocity = velocity + <gSpeed,0,0>;
            if(mouselook)
            {   rotation driverRot = llList2Rot(llGetObjectDetails(ID,[OBJECT_ROT]),0);
                vector driverFwd = llRot2Fwd(driverRot);
                vector fwdCross = vehicleFwd%driverFwd; // used for banking.
                llRotLookAt(uVectorRoll2Rot(driverFwd,-0.3*PI_BY_TWO*fwdCross.z),2.0,0.3);
                /* // use this rather than the line above for perfect alignment with ground normal
                    // I'm not 100% happy with how it handles though; more number tuning required.
                vector vehicleLeft = rayNormal%driverFwd; 
                vector vehicleFwd = vehicleLeft%rayNormal;
                if(llFabs(fwdCross.z)<0.05) fwdCross.z = 0; // make it easier to go straight.
                llRotLookAt(
                    llAxisAngle2Rot(<1,0,0>,-45*DEG_TO_RAD*fwdCross.z)* // banking
                    llAxisAngle2Rot(<0,0,1>,fwdCross.z)* // turning
                    llAxes2Rot(vehicleFwd,vehicleLeft,rayNormal) // intrinsic rotation fixed to normal
                    ,1.15,0.125);
                */
            } 
        }
        if(level&CONTROL_BACK)
        {   rayNormal = <0,0,1>;
            //raySuccess = TRUE;
            //velocity = <0,0,0.25>; // don't fall.
        }
        if(!mouselook)
        {   /* //This version doesn't sticky to surfaces, so no loop-de loop. Boring!
            vehicleFwd = vehicleFwd*llRotBetween(vehicleUp,rayNormal);
            vector vehicleLeft = llVecNorm(rayNormal%vehicleFwd);
            llRotLookAt(uVectorRoll2Rot(
                vehicleFwd+(0.35*vehicleLeft*turn), -20*DEG_TO_RAD*turn),
                1.15,0.125);
            */
            // Wiki says llAxes2Rot needs normalized vectors, but SL doesn't explode
                // without a llVecNorm() on either of these. 
            vector vehicleLeft = rayNormal%vehicleFwd; 
            vector vehicleFwd = vehicleLeft%rayNormal;
            llRotLookAt(
                llAxisAngle2Rot(<1,0,0>,-15*DEG_TO_RAD*turn)* // banking
                llAxisAngle2Rot(<0,0,1>,20*DEG_TO_RAD*turn)* // turning
                llAxes2Rot(vehicleFwd,vehicleLeft,rayNormal) // intrinsic rotation fixed to normal
                ,1.15,0.125);
        }
        if(level&CONTROL_RIGHT)
        {   gSpeed+=0.1;
        }else if(level&CONTROL_LEFT)
        {   gSpeed-=0.1;
        }
        if(level&CONTROL_UP)
        {   gHover+=0.05;
        }else if(level&CONTROL_DOWN)
        {   gHover-=0.05;
        }
        if(raySuccess)
        {   llSetVelocity(velocity,TRUE);
            //llOwnerSay(llKey2Name(rayKey));
        }
    }
}

Commented out sections can be swapped in to change how the vehicle aligns to surfaces at odd angles. I think loop-de-loops are fun, but allowing them might make crashes more likely. So, if you're not doing lots of upside-down driving or driving on the sides of hills, maybe uncomment lines 119-125 and comment out lines 128-134.

Also, if anyone knows if it's possible to get the camera to exactly match the orientation of the vehicle while not in mouse-look (Drive around on a sphere or do a loop-de-loop and you'll quickly get rather annoyed at SL's camera) I'd love to hear how.

Link to comment
Share on other sites

Oh right controls, assuming you use wasd:

(non - mouselook)

  • w: forward
  • a: left
  • s: stop and reset orientation
  • d: right
  • shift-a : decrease speed (vehicle uses continuous gearing)
  • shift-d : increase speed (||)
  • e: increase hover height (makes sudden changes in ground elevation (sudden steep hills) less likely to crash)
  • d: decrease hover height

(mouselook)

  • a,d increase/decrease speed regardless of whether shift is held.
  • The vehicle turns to look where you are looking. If you look to the left you will keep turning left until you turn back to look forward.
    • This takes a lot of getting used to, but I don't think it's possible to make this more intuitive within the limitations of LSL.
Edited by Quistess Alpha
No, your other left.
  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 715 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...