This script assumes that the root prim has ZERO_ROTATION and assumes the presence of a sound effect on the root prim.
CODE
// Prototype Car
// (c) 2006, Tamaria Vixen @ Second Life
// This program may be modified for personal use only! This program may
// be freely distributed so long as it is distributed as is, without
// modification.
// Change the following line to suit your vehicle.
vector SIT = <1.5,-0.9,0.9>;
// You probably don't want to change these.
string cursim = "";
string sound = "";
vector coords = ZERO_VECTOR;
integer phys = FALSE;
float motor = 0.0;
default {
// State Entry and On Rez mainly just make sure the vehicle starts in a sane state.
state_entry() {
llSetStatus(STATUS_SANDBOX | STATUS_DIE_AT_EDGE | STATUS_RETURN_AT_EDGE | STATUS_BLOCK_GRAB | STATUS_PHANTOM | STATUS_PHYSICS, FALSE);
llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, TRUE);
llSetTimerEvent(0.0);
llSitTarget(SIT,ZERO_ROTATION);
llSetCameraEyeOffset(<-10.0,0.0,4.0>);
llSetCameraAtOffset(ZERO_VECTOR);
llStopSound();
llSetAlpha(0.25,ALL_SIDES);
// I remove a bunch of flags because I may be using this script to debug a vehicle after breaking it with ANOTHER script!
llSetVehicleType(VEHICLE_TYPE_CAR);
llRemoveVehicleFlags(VEHICLE_FLAG_LIMIT_ROLL_ONLY | VEHICLE_FLAG_MOUSELOOK_STEER | VEHICLE_FLAG_MOUSELOOK_BANK | VEHICLE_FLAG_CAMERA_DECOUPLED);
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, ZERO_VECTOR);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 2.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 2.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.2);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 10);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.2);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 1.0);
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_OFFSET, ZERO_VECTOR);
llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1,1,1>);
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <1,1,1>);
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.5);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 1.0);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1.0);
llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.0);
cursim = llGetRegionName();
sound = llGetInventoryName(INVENTORY_SOUND,0);
}
on_rez(integer x) {
llSetRot(ZERO_ROTATION);
llResetScript();
}
// Did an avatar stand up or sit down? Check that here.
changed(integer change) {
if(change & CHANGED_LINK) {
key agent = llAvatarOnSitTarget();
if(agent) {
llRequestPermissions(agent, PERMISSION_TAKE_CONTROLS);
}
else llResetScript();
}
}
// Take controls and start up reocurring events, like timers.
run_time_permissions(integer x) {
if(x == PERMISSION_TAKE_CONTROLS) {
if(sound != "") llLoopSound(sound,0.1);
llSetTimerEvent(0.25);
llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_UP | CONTROL_DOWN, TRUE, FALSE);
llSetAlpha(0.0,ALL_SIDES);
}
}
// We only concern ourselves with up arrow, down arrow, right arrow and left arrow.
// Press says whether or not a key has been pressed.
// Change says whether or not a key's state has changed.
control(key agent, integer press, integer change) {
if(press & CONTROL_ROT_LEFT) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,1>);
else if (change & CONTROL_ROT_LEFT) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,0>);
else if(press & CONTROL_ROT_RIGHT) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,-1>);
else if (change & CONTROL_ROT_RIGHT) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,0>);
if(press & CONTROL_FWD) motor = 10;
else if(change & CONTROL_FWD) motor = 0;
else if(press & CONTROL_BACK) motor = -5;
else if(change & CONTROL_BACK) motor = 0;
}
timer() {
coords = llGetPos();
phys = llGetStatus(STATUS_PHYSICS);
// The following lines stop the vehicle if the lag is too high or a border has been crossed.
// Greatly reduces the chances of losing the vehicle or the vehicle sinking into the ground.
if (llGetRegionName() != cursim) {
if(phys) llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(1 - llGetRegionTimeDilation());
cursim = llGetRegionName();
}
else if(llGetRegionTimeDilation() < 0.5 || llGetRegionFPS() < 5) {
if(phys) llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(5 - (llGetRegionTimeDilation() * 5));
}
// If the vehicle is being effected by physics, move it around.
// If it's not, try to get it 'unstuck'.
// Do the sound effects here, too!
if (phys) {
if(llAbs((integer)motor) > 1) llAdjustSoundVolume(1.0);
else llAdjustSoundVolume(0.5);
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<motor,0,0>);
}
else {
llAdjustSoundVolume(0.5);
llSetPos(coords + <0,0,0.25>);
llSetStatus(STATUS_PHYSICS, TRUE);
}
}
}