// Simple airplane script example // THIS SCRIPT IS PUBLIC DOMAIN! Do not delete the credits at the top of this script! // Nov 25, 2003 - created by Andrew Linden and posted in the Second Life scripting forum // Jan 05, 2004 - Cubey Terra - minor changes: customized controls, added enable/disable physics events // Feel free to copy, modify, and use this script. // Always give credit to Andrew Linden and all people who modify it in a readme or in the object description. // assumes that the root primitive is oriented such that its // local x-axis points toward the nose of the plane, and its // local z-axis points toward the top // control flags that we set later integer gAngularControls = 0; integer gLinearControls = 0; // we keep track of angular history for more responsive turns integer gOldAngularLevel = 0; // the linear motor uses an accumulator model rather than keeping track // of the linear control level history vector gLinearMotor = <0, 0, 0>; default { state_entry() { llSetSitText("Fly"); llCollisionSound("", 0.0); // the sit and camera placement is very shape dependent // so modify these to suit your vehicle llSitTarget(<0.6, 0.0, 0.20>, ZERO_ROTATION); llSetCameraEyeOffset(<-10.0, 0.0, 2.0> ); llSetCameraAtOffset(<3.0, 0.0, 1.0> ); llSetVehicleType(VEHICLE_TYPE_AIRPLANE); // weak angular deflection llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.1); llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 1.0); // strong linear deflection llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1.0); llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.2); // somewhat responsive linear motor llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.5); llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 20); // somewhat responsive angular motor, but with 3 second decay timescale llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.5); llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 3); // very weak friction //llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000.0, 1000.0, 1000.0> ); // CUBEY - original line llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, <200, 20, 20> ); // CUBEY - increased friction llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <1000.0, 1000.0, 1000.0> ); llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.65); // almost wobbly - CUBEY - increased from .25 to improve stability llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1.5); // mediocre response llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.4); // medium strength llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1); // very responsive llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 0.95); // more banking when moving // hover can be better than sliding along the ground during takeoff and landing // but it only works over the terrain (not objects) //llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, 3.0); //llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.5); //llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 2.0); //llSetVehicleFlags(VEHICLE_FLAG_HOVER_UP_ONLY); // non-zero buoyancy helps the airplane stay up // set to zero if you don't want this crutch llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.2); // define these here for convenience later // CUBEY - modified these as per Shadow's prefs gAngularControls = CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_BACK | CONTROL_FWD; gLinearControls = CONTROL_UP | CONTROL_DOWN; llSetStatus(STATUS_PHYSICS, FALSE); //CUBEY - ensure that physics are disabled when plane is rezzed so it doesn't fly off } changed(integer change) { if (change & CHANGED_LINK) { key agent = llAvatarOnSitTarget(); if (agent) { if (agent != llGetOwner()) { // only the owner can use this vehicle llSay(0, "You aren't the owner -- only the owner can fly this plane."); llUnSit(agent); llPushObject(agent, <0,0,10>, ZERO_VECTOR, FALSE); } else { // clear linear motor on successful sit gLinearMotor = <0, 0, 0>; llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor); //llSetStatus(STATUS_PHYSICS, TRUE); llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 1000.0); llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 1000.0); llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS); } } else { // stop the motors gLinearMotor = <0, 0, 0>; llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, gLinearMotor); // use friction to stop the vehicle rather than pinning it in place //llSetStatus(STATUS_PHYSICS, FALSE); llSetVehicleFloatParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, 1.0); llSetVehicleFloatParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, 1.0); // driver is getting up llReleaseControls(); llStopAnimation("sit"); llSetStatus(STATUS_PHYSICS, FALSE); //CUBEY - turn off physics to make sure the parked plane can't be moved } } } run_time_permissions(integer perm) { if (perm) { llStartAnimation("sit"); llTakeControls(gAngularControls | gLinearControls, TRUE, FALSE); llSetStatus(STATUS_PHYSICS, TRUE); //CUBEY - enable physics when avatar sits } } control(key id, integer level, integer edge) { // only change linear motor if one of the linear controls are pressed vector motor; integer motor_changed = level & gLinearControls; if (motor_changed) { if(level & CONTROL_UP) //CUBEY { if (gLinearMotor.x < 0) { gLinearMotor.x = 0; } else if (gLinearMotor.x < 30) { gLinearMotor.x += 5; } motor_changed = TRUE; } if(level & CONTROL_DOWN) //CUBEY { if (gLinearMotor.x > 0) { gLinearMotor.x = 0; } else if (gLinearMotor.x > -30) { gLinearMotor.x -= 5; }; motor_changed = TRUE; } llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, gLinearMotor); } // only change angular motor if the angular levels have changed motor_changed = (edge & gOldAngularLevel) + (level & gAngularControls); if (motor_changed) { motor = <0,0,0>; if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) { // add roll component ==> triggers banking behavior motor.x += 10; } if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT)) { motor.x -= 10; } if(level & (CONTROL_BACK)) // CUBEY { // add pitch component ==> causes vehicle lift nose (in local frame) motor.y -= 8; } if(level & (CONTROL_FWD)) // CUBEY { motor.y += 8; } llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, motor); } // store the angular level history for the next control callback gOldAngularLevel = level & gAngularControls; } }