This is the main script which needs to go in the Pilots seat:
// Cubey Terra DIY Plane 1.0 // September 10, 2005 // Distribute freely. Go ahead and modify it for your own uses. Improve it and share it around. // Some portions based on the Linden airplane script originall posted in the forums. // llSitTarget parameters: vector avPosition = <0.0,0.0,-0.6>; // position of avatar in plane, relative to parent rotation avRotation = <0,-0.2,0,1>; // rotation of avatar, relative to parent // Thrust variables: // thrust = fwd * thrust_multiplier // Edit the maxThrottle and thrustMultiplier to determine max speed. integer fwd; // this changes when pilot uses throttle controls integer maxThrottle = 10; // Number of "clicks" in throttle control. Arbitrary, really. integer thrustMultiplier = 3; // Amount thrust increases per click. // Lift and speed float cruiseSpeed = 25.0; // speed at which plane achieves full lift float lift; float liftMax = 0.977; // Maximum allowable lift float speed; float timerFreq = 0.5; integer fwdLast; integer sit; key owner; default { state_entry() { llSitTarget(avPosition, avRotation); // Position and rotation of pilot's avatar. llSetCameraEyeOffset(<-7, 0, 1.5>); // Position of camera, relative to parent. llSetCameraAtOffset(<0, 0, 1.9>); // Point to look at, relative to parent. llSetSitText("Fly"); // Text that appears in pie menu when you sit llCollisionSound("", 0.0); // Remove the annoying thump sound from collisions //SET VEHICLE PARAMETERS -- See www.secondlife.com/badgeo for an explanation llSetVehicleType(VEHICLE_TYPE_AIRPLANE); // uniform angular friction llSetVehicleFloatParam( VEHICLE_ANGULAR_FRICTION_TIMESCALE, 2 ); // linear motor llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, <200, 20, 20> ); llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0> ); llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_TIMESCALE, 2 ); llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 120 ); // agular motor llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, <0, 0, 0> ); llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0 ); llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.4); // hover llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 0 ); llSetVehicleFloatParam( VEHICLE_HOVER_EFFICIENCY, 0 ); llSetVehicleFloatParam( VEHICLE_HOVER_TIMESCALE, 10 ); llSetVehicleFloatParam( VEHICLE_BUOYANCY, .977 ); // no linear deflection llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.2 ); llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.5 ); // no angular deflection llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 1); llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 0.6); // no vertical attractor llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.8 ); llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 2 ); /// banking llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 1); llSetVehicleFloatParam( VEHICLE_BANKING_MIX, .85); llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 0.01); // default rotation of local frame llSetVehicleRotationParam( VEHICLE_REFERENCE_FRAME, <0,0,0,1>); // remove these flags llRemoveVehicleFlags( VEHICLE_FLAG_NO_DEFLECTION_UP | VEHICLE_FLAG_HOVER_WATER_ONLY | VEHICLE_FLAG_HOVER_TERRAIN_ONLY | VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT | VEHICLE_FLAG_HOVER_UP_ONLY | VEHICLE_FLAG_LIMIT_MOTOR_UP ); // set these flags llSetVehicleFlags( VEHICLE_FLAG_LIMIT_ROLL_ONLY ); } on_rez(integer num) { llResetScript(); } // DETECT AV SITTING/UNSITTING AND TAKE CONTROLS changed(integer change) { if(change & CHANGED_LINK) { key agent = llAvatarOnSitTarget(); // Pilot gets off vehicle if((agent == NULL_KEY) && (sit)) { llSetStatus(STATUS_PHYSICS, FALSE); llSetTimerEvent(0.0); llMessageLinked(LINK_SET, 0, "unseated", ""); llStopSound(); llReleaseControls(); sit = FALSE; } // Pilot sits on vehicle else if((agent == llGetOwner()) && (!sit)) { llRequestPermissions(agent, PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION); llSetTimerEvent(timerFreq); llMessageLinked(LINK_SET, 0, "seated", ""); sit = TRUE; llSetStatus(STATUS_PHYSICS, TRUE); } } } //CHECK PERMISSIONS AND TAKE CONTROLS run_time_permissions(integer perm) { if (perm & (PERMISSION_TAKE_CONTROLS)) { llTakeControls(CONTROL_UP | CONTROL_DOWN | CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE); } } //FLIGHT CONTROLS control(key id, integer level, integer edge) { integer throttle_up = CONTROL_UP; integer throttle_down = CONTROL_DOWN; integer yoke_fwd = CONTROL_FWD; integer yoke_back = CONTROL_BACK; vector angular_motor; // THROTTLE CONTROL-------------- if (level & throttle_up) { if (fwd < maxThrottle) { fwd += 1; } } else if (level & throttle_down) { if (fwd > 0) { fwd -= 1; } } if (fwd != fwdLast) { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <(fwd * thrustMultiplier),0,0>); // calculate percent of max throttle and send to child prims as link message float thrustPercent = (((float)fwd/(float)maxThrottle) * 100); llMessageLinked(LINK_SET, (integer)thrustPercent, "throttle", ""); llOwnerSay("Throttle at "+(string)((integer)thrustPercent)+"%"); fwdLast = fwd; llSleep(0.15); // crappy kludge :P } // PITCH CONTROL ---------------- if (level & yoke_fwd) { angular_motor.y = 3.0; } else if (level & yoke_back) { angular_motor.y = -3.0; } else { angular_motor.y = 0; } // BANKING CONTROL---------------- if ((level & CONTROL_RIGHT) || (level & CONTROL_ROT_RIGHT)) { angular_motor.x = TWO_PI; } else if ((level & CONTROL_LEFT) || (level & CONTROL_ROT_LEFT)) { angular_motor.x = -TWO_PI; } else { angular_motor.x = 0; } llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor); } timer() { // Calculate speed in knots speed = (integer)(llVecMag(llGetVel()) * 1.94384449 + 0.5); // Provide lift proportionally to speed cruiseSpeed = 25.0; // speed at which you achieve full lift lift = (speed/cruiseSpeed); //Lift is varied proportionally to the speed if (lift > liftMax) lift = liftMax; llSetVehicleFloatParam( VEHICLE_BUOYANCY, lift ); } }
This is for the passenger's seat:
default { state_entry() { llSitTarget(<0.0,0.0,-0.6>, <0,-0.2,0,1>); } }