Here is my submission to the community.
This a realistic car script. Three main features make it more realistic than your average car script.
1. You can't turn the car if you are not moving.
2. The tires rotate when you move and the front wheels turn when you turn.
3. Reverse steering works the right way.
There are three parts to this script.
1. car_main: Goes on the root prim of your vehicle. The "front" of the vehicle will the the postive X axis.
2. car_seat: Goes on each seat the vehicle has. The avatar's will be oreinted along the positive X axis when seated.
3. car_front and car_rear_wheel: Goes on the wheels of the vehicle.
I stole peices of code from all around these fourms to build this. So sorry if I offend anyone by releasing this.
car_main
CODE
//**********************************************
//Title: Car
//Author: Aaron Perkins
//Date: 3/17/2004
//**********************************************
//Feel free to modify these basic parameters to suit your needs.
float forward_power = 30; //Power used to go forward (1 to 30)
float reverse_power = -15; //Power ued to go reverse (-1 to -30)
float turning_ratio = 4.0; //How sharply the vehicle turns. Less is more sharply. (.1 to 10)
string sit_message = "Jump In!"; //Sit message
string not_owner_message = "You are not the owner of this vehicle ..."; //Not owner message
//Anything past this point should only be modfied if you know what you are doing
string last_wheel_direction;
string cur_wheel_direction;
default
{
state_entry()
{
llSetSitText(sit_message);
llSetCameraEyeOffset(<-10.0, 0.0, 2.0>);
llSetCameraAtOffset(<10.0, 0.0, 2.0>);
//car
llSetVehicleType(VEHICLE_TYPE_CAR);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.2);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.80);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 0.10);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.10);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 1.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.2);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.5);
llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1000.0, 2.0, 1000.0>);
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <10.0, 10.0, 1000.0>);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.50);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 0.50);
}
changed(integer change)
{
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();
if (agent)
{
if (agent != llGetOwner())
{
llSay(0, not_owner_message);
llUnSit(agent);
llPushObject(agent, <0,0,50>, ZERO_VECTOR, FALSE);
}
else
{
llTriggerSound("car_start",1);
llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DRIVING", NULL_KEY);
llSleep(.4);
llSetStatus(STATUS_PHYSICS, TRUE);
llSleep(.1);
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
llSetTimerEvent(0.1);
llLoopSound("car_idle",1);
}
}
else
{
llSetTimerEvent(0);
llStopSound();
llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(.1);
llMessageLinked(LINK_ALL_CHILDREN , 0, "WHEEL_DEFAULT", NULL_KEY);
llSleep(.4);
llReleaseControls();
llResetScript();
}
}
}
run_time_permissions(integer perm)
{
if (perm)
{
llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT |
CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
}
}
control(key id, integer level, integer edge)
{
integer reverse=1;
vector angular_motor;
//get current speed
vector vel = llGetVel();
float speed = llVecMag(vel);
//car controls
if(level & CONTROL_FWD)
{
cur_wheel_direction = "WHEEL_FORWARD";
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <forward_power,0,0>);
reverse=1;
}
if(level & CONTROL_BACK)
{
cur_wheel_direction = "WHEEL_REVERSE";
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <reverse_power,0,0>);
reverse = -1;
}
if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
cur_wheel_direction = "WHEEL_RIGHT";
angular_motor.z -= speed / turning_ratio * reverse;
}
if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
cur_wheel_direction = "WHEEL_LEFT";
angular_motor.z += speed / turning_ratio * reverse;
}
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);
} //end control
timer()
{
if (cur_wheel_direction != last_wheel_direction)
{
llMessageLinked(LINK_ALL_CHILDREN , 0, cur_wheel_direction, NULL_KEY);
last_wheel_direction = cur_wheel_direction;
}
}
} //end default
car_seat
CODE
//**********************************************
//Title: Car Seat
//Author: Aaron Perkins
//Date: 2/17/2004
//**********************************************
default
{
state_entry()
{
llSitTarget(<0,0,0.5>, llEuler2Rot(<0,-0.4,0>));
}
}
car_front_wheel
CODE
//**********************************************
//Title: Car Front Wheel
//Author: Aaron Perkins
//Date: 2/17/2004
//**********************************************
rotation Inverse(rotation r)
{
r.x = -r.x;
r.y = -r.y;
r.z = -r.z;
return r;
}
rotation GetParentRot()
{
return Inverse(llGetLocalRot())*llGetRot();
}
SetLocalRot(rotation x)
{
llSetRot(x*Inverse(GetParentRot()));
}
default
{
state_entry()
{
}
link_message(integer sender_num, integer num, string str, key id)
{
if(str == "WHEEL_DRIVING")
{
state driving;
}
}
}
state driving
{
state_entry()
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO,0,0>));
llSetTimerEvent(0.5);
}
timer()
{
vector vel = llGetVel();
float speed = llVecMag(vel);
llSetTextureAnim(ANIM_ON|LOOP|SMOOTH|ROTATE,ALL_SIDES,0,0,0,0,speed);
}
link_message(integer sender_num, integer num, string str, key id)
{
if(str == "WHEEL_DEFAULT")
{
state default;
}
if(str == "WHEEL_FORWARD")
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO,0,0>));
}
if(str == "WHEEL_REVERSE")
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO,0,0>));
}
if(str == "WHEEL_LEFT")
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO, -1 * PI_BY_TWO / 2, 0>));
}
if(str == "WHEEL_RIGHT")
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO, PI_BY_TWO / 2, 0>));
}
}
state_exit()
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO,0,0>));
llSetTextureAnim(0,ALL_SIDES,0,0,0,0,0);
}
}
car_rear_wheel
CODE
//**********************************************
//Title: Car Rear Wheel
//Author: Aaron Perkins
//Date: 2/17/2004
//**********************************************
rotation Inverse(rotation r)
{
r.x = -r.x;
r.y = -r.y;
r.z = -r.z;
return r;
}
rotation GetParentRot()
{
return Inverse(llGetLocalRot())*llGetRot();
}
SetLocalRot(rotation x)
{
llSetRot(x*Inverse(GetParentRot()));
}
default
{
state_entry()
{
}
link_message(integer sender_num, integer num, string str, key id)
{
if(str == "WHEEL_DRIVING")
{
state driving;
}
}
}
state driving
{
state_entry()
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO,0,0>));
llSetTimerEvent(0.5);
}
timer()
{
vector vel = llGetVel();
float speed = llVecMag(vel);
llSetTextureAnim(ANIM_ON|LOOP|SMOOTH|ROTATE,ALL_SIDES,0,0,0,0,speed);
}
link_message(integer sender_num, integer num, string str, key id)
{
if(str == "WHEEL_DEFAULT")
{
state default;
}
}
state_exit()
{
SetLocalRot(llEuler2Rot(<-1 * PI_BY_TWO,0,0>));
llSetTextureAnim(0,ALL_SIDES,0,0,0,0,0);
}
}