As most know already, rally cars tend to slide around corners and the such much more than any other vehicles. Using external forces to turn your vehicle works perfect for rally car simulations. Though, it works horrible for anyone who wants their vehicles to turn precisly. Since you have to decrease the friction, the vehicle also slides very far while performing a turn. Again, good for rally car racers, very bad for anything else according to my current observations.
Could you add a feature that allows precise turning regardless of the friction value? I would really like to be able to change a models orientation using pan while in the physics engine, since phent_addtorque and phent_addforce do not turn the vehicle very precisly. Thanks, I hope to hear what type of a solution you can come up with for this, since I'm almost all out of ideas.

Here's my current script, you will be able to understand what I mean about turning and the such by implementing this. Remember, call "Flex" from the main function. Also, be sure to have 2 completely horizontal vertex positions on your vehicle. You will notice that I use these 2 vertices to find the angle of the vehicle, that way I know what direction to apply the force in. As always, please share any insight on the script, since I am not a complete expert with external forces, and perhaps - there is a great way to have precise turning after all. Hope this helps. Thanks.

Code:
  



//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::Variables(Defines)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

//Wheel & Kart Defines
entity* player;
entity* wheel_fr;
entity* wheel_fl;
entity* wheel_bl;
entity* wheel_br;

var FR_wheel_ID;
var FL_wheel_ID;
var RL_wheel_ID;
var RR_wheel_ID;

var p1[3];
var p2[3];
var p3[3];
var p4[3];
var p5[3];
var p6[3];

//Environment Defines

var earth_gravity[3] = 0,0, -316;
var mars_gravity[3] = 0,0, -316;

var wheel_friction = 90;
var wheel_mass = 90;
var wheel_bounciness = 0;
var wheel_minimumSpeed = 0;

var kart_mass = 30;
var kart_friction = 40;
var kart_bounciness = 0;
var kart_minimumSpeed = 0;

// Movement Defines
var m1_1[3];
var m1_2[3];
var m2[3];
var wheel_target;

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::PowerSlide(settings)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------


//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::Kart(settings)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

var air[3];
var force[3];

action kart // the kart action
{
my.pan += 180;
p_player = me;

p_player.overlay = off;
p_player.flare = off;
p_player.bright = off;
p_player.transparent = off;
p_player.ambient = 50;

ph_setgravity(earth_gravity);
phent_settype(my,PH_RIGID,PH_box);
phent_setgroup(my,2);
phent_setmass(my,kart_mass,PH_poly);
phent_setfriction(my,kart_friction);
phent_setelasticity(my,kart_bounciness,kart_minimumspeed);

wait(10);

while(1)
{

if(key_f == 1) //Jump Up
{
wheel_target = 0;

phent_addcentralforce( p_FR_tyre, vector(0,0,90000000)); // this is the jump strength
phent_addcentralforce( p_FL_tyre, vector(0,0,90000000));
phent_addcentralforce( p_RL_tyre, vector(0,0,90000000));
phent_addcentralforce( p_RR_tyre, vector(0,0,90000000));

phent_addcentralforce( p_player, vector(0,0,900000));
}
wait(1);
}
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::Control::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------


Function Flex() // Call this from main
{
var s_vert1[3];
var s_vert2[3];
var s_angle[3];
var s_force[3];
var z_force[3];
var f_orce[3] = 8880,0,0;
var f_orcer[3] = -8880,0,0;

phent_setdamping (p_FR_tyre, 0, 100 );
phent_setdamping (p_FL_tyre, 0, 100 );
phent_setdamping (p_RL_tyre, 0, 100 );
phent_setdamping (p_RR_tyre, 0, 100 );

phent_setdamping (p_player, 0, 100 );

while(1)
{
vec_for_vertex(s_vert1.x,p_player,49); // base vertex
vec_for_vertex(s_vert2.x,p_player,51); // tip vertex

// Get the angle from the base to the tip of the kart, and store it in angle[3]
vec_set(temp,s_vert2.x);
vec_sub(temp,s_vert1.x);
vec_to_angle(s_angle,temp);

vec_inverse(temp);
vec_scale(temp, 0.5);
vec_set(s_force.x,nullvector);
s_force.x = 90000; // how fast the skid is
vec_rotate(s_force.x,s_angle);

vec_set(z_force.x,nullvector);
z_force.x = -90000;
vec_rotate(z_force.x,s_angle);

if(key_d == 1) // Turn
{
phent_addtorqueglobal(p_player, vector(0,0,-8000));
//phent_addforceglobal (p_player, f_orce, vector(2000, 2000, 0));
}

if(key_a == 1) // Turn
{
//phent_addforceglobal (p_player, f_orcer, vector(2000, 2000, 0));
phent_addtorqueglobal(p_player, vector(0,0,8000));
}

if(key_w == 1) //Accelerate
{
wheel_target = 0;

phent_addcentralforce( p_FR_tyre, s_force.x); //Accelerate
phent_addcentralforce( p_FL_tyre, s_force.x);
phent_addcentralforce( p_RL_tyre, s_force.x);
phent_addcentralforce( p_RR_tyre, s_force.x);

phent_addcentralforce( p_player, s_force.x);
}

if(key_s == 1) //Reverse
{
wheel_target = 0;
phent_addcentralforce( p_FR_tyre, z_force.x); // Reverse
phent_addcentralforce( p_FL_tyre, z_force.x);
phent_addcentralforce( p_RL_tyre, z_force.x);
phent_addcentralforce( p_RR_tyre, z_force.x);

phent_addcentralforce( p_player, z_force.x);
}

wait(1);
}
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::FrontLeft(Wheel)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

action fl_wheel
{
my.pan += 180;

p_FL_tyre=my;

phent_settype(my,PH_RIGID,PH_sphere);
phent_setgroup(my,2);
phent_setmass(my,wheel_mass,PH_sphere);

phent_setfriction(my,wheel_friction);
phent_setelasticity(my,wheel_bounciness ,wheel_minimumSpeed);
phent_setdamping(my,20,20);

vec_set(p2,vector(0,0,1));
vec_set(p3,vector(0,1,0));
vec_set(p4,vector(-40,40,0));
vec_set(p6,vector(0,0,0));
FL_wheel_ID=phcon_add(PH_WHEEL,p_player,my);
phcon_setparams1(FL_wheel_ID,my.x,p2,p3);
phcon_setparams2(FL_wheel_ID,p4,nullvector,p6);
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::FrontRight(Wheel)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

action fr_wheel//front right tire
{
my.pan += 180;

p_FR_tyre=my;

phent_settype(my,PH_RIGID,PH_sphere);
phent_setgroup(my,2);
phent_setmass(my,wheel_mass,PH_sphere);

phent_setfriction(my,wheel_friction);
phent_setelasticity(my,wheel_bounciness ,wheel_minimumSpeed);
phent_setdamping(my,20,20);

vec_set(p2,vector(0,0,1));
vec_set(p3,vector(0,1,0));
vec_set(p4,vector(-40,40,0));
vec_set(p6,vector(0,0,0));
FR_wheel_ID=phcon_add(PH_WHEEL,p_player,my);
phcon_setparams1(FR_wheel_ID,my.x,p2,p3);
phcon_setparams2(FR_wheel_ID,p4,nullvector,p6);
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::BackLeft(Wheel)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

action bl_wheel //back left tire
{
my.pan += 180;

p_RL_tyre=my;

phent_settype(my,PH_RIGID,PH_sphere);
phent_setgroup(my,2);
phent_setmass(my,wheel_mass,PH_sphere);

phent_setfriction(my,wheel_friction);
phent_setelasticity(my,wheel_bounciness ,wheel_minimumSpeed);
phent_setdamping(my,20,20);

vec_set(p2,vector(0,0,1));
vec_set(p3,vector(0,1,0));
vec_set(p4,vector(0,0,0));
vec_set(p6,vector(0,0,0));
RL_wheel_ID=phcon_add(PH_WHEEL,p_player,my);
phcon_setparams1(RL_wheel_ID,my.x,p2,p3);
phcon_setparams2(RL_wheel_ID,p4,nullvector,p6);
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::BackRight(Wheel)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

action br_wheel
{
my.pan += 180;

p_RR_tyre=my;

phent_settype(my,PH_RIGID,PH_sphere);
phent_setgroup(my,2);
phent_setmass(my,wheel_mass,PH_sphere);

phent_setfriction(my,wheel_friction);
phent_setelasticity(my,wheel_bounciness ,wheel_minimumSpeed);
phent_setdamping(my,20,20);

vec_set(p2,vector(0,0,1));
vec_set(p3,vector(0,1,0));
vec_set(p4,vector(0,0,0));
vec_set(p6,vector(0,0,0));
RR_wheel_ID=phcon_add(PH_WHEEL,p_player,my);
phcon_setparams1(RR_wheel_ID,my.x,p2,p3);
phcon_setparams2(RR_wheel_ID,p4,nullvector,p6);
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::Control(Input)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

function control()
{
while(1)
{
if(key_a == 1)
{
wheel_target=-40;
}

if(key_d == 1)
{
wheel_target= 40;
}

if(key_a == 1 && key_d == 1)||(key_a == 0 && key_d == 0)
{
wheel_target=0;
}


vec_set(temp, p_player.x); // makes it so temp is always starts at my.x
temp.z -= 4000; // set how far to trace
air = c_trace(p_player.x, temp,ignore_me+ignore_sprites+ignore_models); // see's if player will hit ground sometime

if(air > 30) //if the player is still in the air
{
ph_setgravity(mars_gravity);
wheel_target=0;
}
else
{
ph_setgravity(earth_gravity);
}
phcon_getposition(FR_wheel_ID,temp);
vec_set(m1_1,vector((wheel_target-temp.x)*0.2,500,0));

phcon_getposition(FL_wheel_ID,temp);
vec_set(m1_2,vector((wheel_target-temp.x)*0.2,500,0));

phcon_setmotor(FR_wheel_ID,m1_1,m2,nullvector);
phcon_setmotor(FL_wheel_ID,m1_2,m2,nullvector);
wait(1);
}
}

//---------------------------------------------------------------------------------------------------------------------------
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::Create(Player)::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//---------------------------------------------------------------------------------------------------------------------------

action Need_Me //faulty action
{
phent_settype(my,PH_RIGID,PH_sphere);
phent_setgroup(my,2);
phent_setmass(my,wheel_mass,PH_box);
}

function create_player()
{
ph_setgravity(vector(0,0,-380));
ph_setcorrections(30000,0.05);

ent_create(mdl_car, temp, kart);

vec_for_vertex(temp,p_player,627);
wheel_fr = ent_create(mdl_tyrefr,temp,fr_wheel);

vec_for_vertex(temp,p_player,618);
wheel_fl = ent_create(mdl_tyrefl,temp,fl_wheel);

vec_for_vertex(temp,p_player,614);
wheel_bl = ent_create(mdl_tyrebl,temp,br_wheel);

vec_for_vertex(temp,p_player,634);
wheel_br = ent_create(mdl_tyrebr,temp,bl_wheel);

vec_for_vertex(temp,p_player,634);
wheel_br = ent_create(mdl_tyrebr,temp,Need_Me);
}







Check out Silas. www.kartsilas.com

Hear my band Finding Fire - www.myspace.com/findingfire

Daily dev updates - http://kartsilas.blogspot.com/