Outerra forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Download Outerra Tech Demo. Unofficial Outerra Discord server, MicroProse Discord server for OWS.

Pages: 1 2 3 [4] 5 6 ... 8

Author Topic: Vehicle script [version 1.4.0]  (Read 82828 times)

M7

  • Hero Member
  • *****
  • Posts: 736
  • newbie
Re: Vehicle script [version 1.2.2]
« Reply #45 on: May 22, 2013, 01:31:22 am »

Almost perfect!!!! i just love the manual transmission. But now i'm getting something new in the log window. Instead of seing the gear changes, i get 'info with fast scrolling numbers '. Not a big deal though.


Logged

Chaoz

  • Full Member
  • ***
  • Posts: 156
  • newbie
Re: Vehicle script [version 1.2.2]
« Reply #46 on: May 22, 2013, 02:35:29 am »

you have to remove "this.log_inf(this.engineRPM);" from the script to get rid of the numbers, probably a left over from debugging ;)
Logged

M7

  • Hero Member
  • *****
  • Posts: 736
  • newbie
Re: Vehicle script [version 1.2.2]
« Reply #47 on: May 22, 2013, 09:48:42 am »

Good that did it!

Next i think i'll try to bring that manual transmission script to the monster truck. It sure is one of my favorite vehicle. I already found a better sound for the engine (taken from the batman tumbler engineoff.ogg) and made some offroad circuit with unpaved road and big bumps. All is missing is the mud and some mesh trashing  ;D
Logged

giucam

  • Full Member
  • ***
  • Posts: 171
  • It's an ugly pile of bones... like me.
Re: Vehicle script [version 1.3.0]
« Reply #48 on: May 27, 2013, 12:35:57 pm »

Version 1.3.0

Code: [Select]
/*
    Vehicle script file
    Copyright (C) 2012 - 2013  Giulio Camuffo <giuliocamuffo@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 3.0 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//see http://xtrac.outerraworld.com/trac.fcgi/wiki/vehicle for example and documentation

// VERSION 1.3.0

var chassis = {};

// --- Vehicle specific stuff ---
function chassis_setup() {
    var wheelparam = {
        radius: 0.30,
        width: 0.20,
        suspension_max: 0.1,
        suspension_min: -0.05,
        suspension_stiffness: 50.0,
        damping_compression: 0.06,
        damping_relaxation: 0.05,
        slip: 3.0,
        roll_influence: 0.1,
        rotation: -1
    };

    this.add_wheel('wheel_FL', wheelparam);
    this.add_wheel('wheel_FR', wheelparam);
    this.add_wheel('wheel_RL', wheelparam);
    this.add_wheel('wheel_RR', wheelparam);

    this.load_sound("e90_onidle.ogg"); //idle
    this.load_sound("e90_offlow.ogg"); //off
    this.load_sound("e90_onlow.ogg"); //on
    chassis.basePitch = [ 1, 0.4, 0.4 ];             //base pitch for idle, off, on
    chassis.relVolumes = [ 0.8, 1, 1 ];
    this.add_sound_emitter("hood");

    //engine properties -- modify these to change the engine behaviour
    chassis.wheelRadius = 0.24;

    chassis.torquePoints = [ { rpm: 500,  torque: 0},
                             { rpm: 1000, torque: 250},
                             { rpm: 2000, torque: 335},
                             { rpm: 3000, torque: 380},
                             { rpm: 4000, torque: 400},
                             { rpm: 5000, torque: 395},
                             { rpm: 6000, torque: 400},
                             { rpm: 7000, torque: 390},
                             { rpm: 8000, torque: 365},
                             { rpm: 9000, torque: 0  } ];

    chassis.forwardGears = [ { ratio: 4.06, shiftUp: 8000, shiftDown: -1   },
                             { ratio: 2.40, shiftUp: 8000, shiftDown: 4500 },
                             { ratio: 1.58, shiftUp: 8000, shiftDown: 5000 },
                             { ratio: 1.19, shiftUp: 8000, shiftDown: 5500 },
                             { ratio: 1.00, shiftUp: 8000, shiftDown: 6000 },
                             { ratio: 0.87, shiftUp: -1,   shiftDown: 6000 } ];
    chassis.reverseGears = [ { ratio: 4.68, shiftUp: -1, shiftDown: -1 } ];

    chassis.differentialRatio = 3.85;
    chassis.efficiency = 0.9;
    chassis.speedLimiter = -1; // maximum speed in m/s. a value < 0 means there's no limiter
    chassis.engineBrakeCoefficient = 0.4;
    chassis.breakingForce = 3000.0;
    chassis.pitchMultiplier = 1.5;
    chassis.engineInertia = 0.015;
    chassis.minimumRPM = 1500;
    chassis.minimum = 0.2;
    //end of engine properties

    return { mass:1570, steering:1.2, steering_ecf:70, centering: 5.0, centering_ecf: 40, com: { z:0.1 } };
}

function vehicle_setup() {
    this.set_fps_camera_pos( {x: -0.33,y: -0.20, z: 1.15});
    this.soundRefDistance = 5;
    this.automaticTransmission = false;
    this.clutchMode = ClutchMode.Automatic;
}

// --- End of vehicle specific stuff ---



//invoked only the first time the model is loaded, or upon reload
function init_chassis() {
    this.setup = chassis_setup;
    var ret = this.setup();

    chassis.maxPowerTP = chassis.torquePoints[0];
    chassis.maxRPM = 0;
    var maxPw = 0;
    for (var i = 1; i < chassis.torquePoints.length; ++i) {
        var tp = chassis.torquePoints[i];
        if (tp.rpm * tp.torque > maxPw) {
            chassis.maxPowerTP = tp;
        }
        if (tp.rpm > chassis.maxRPM) {
            chassis.maxRPM = tp.rpm;
        }
    }

    chassis.neutroGear = { ratio: 0.0, shiftUp: -1, shiftDown: -1, index: 0 };
    var prev = null;
    for (var i = 0; i < chassis.forwardGears.length; ++i) {
        var gear = chassis.forwardGears[i];
        if (prev)
            prev.next = gear;
        gear.prev = prev;
        gear.index = i + 1;
        prev = gear;
    }

    prev = null;
    for (var i = 0; i < chassis.reverseGears.length; ++i) {
        var gear = chassis.reverseGears[i];
        if (prev)
            prev.prev = gear;
        gear.next = prev;
        gear.index = -i - 1;
        prev = gear;
    }

    return ret;
}

var ClutchMode = { Manual: 0, Automatic: 1, Mixed: 2 };
var ClutchState = { Engaged: 0, Disengaged: 1, Engaging: 2, Disengaging: 3 };

//invoked for each new instance of the vehicle
function init_vehicle() {
    this.snd = this.sound();

    this.torque = engineTorque;
    this.shiftUp = shift_up;
    this.shiftDown = shift_down;
    this.selectGear = select_gear;
    this.updateAutomaticTransmission = automatic_transmission;
    this.automaticClutch = automatic_clutch;
    this.clutchValue = clutch_value;
    this.animate = animate;
    this.setup = vehicle_setup;

    this.setup();

    this.idleSource = this.snd.create_source(0);
    this.onSource = this.snd.create_source(0);
    this.offSource = this.snd.create_source(0);
    this.idleSound = 1;
    this.snd.set_ref_distance(this.idleSource, this.soundRefDistance);
    this.snd.set_ref_distance(this.onSource, this.soundRefDistance);
    this.snd.set_ref_distance(this.offSource, this.soundRefDistance);
    this.snd.play(this.idleSource, 0, true, false);
    this.snd.play(this.offSource, 1, true, false);
    this.snd.play(this.onSource, 2, true, false);

    this.clutch = 1.0;
    this.clutchState = ClutchState.Disengaged;
    this.started = false;
    this.gear = chassis.neutroGear;
    this.direction = 0;
    this.engineRPM = 0;
    this.starting = false;
    this.clutchOverride = false;
}

//invoked when engine starts or stops
function engine(start) {
    this.started = false;
    this.idleSound = 1.0;
    if (start) {
        this.starting = true;
    }
}

function engineTorque(rpm) {
    var min = 0;
    var max = chassis.torquePoints.length - 1;

    if (rpm > chassis.torquePoints[max].rpm || rpm < chassis.torquePoints[min].rpm)
        return 0;

    while (max - min > 1) {
        var mid = Math.floor(min + (max - min) / 2);
        var tp = chassis.torquePoints[mid];
        if (tp.rpm == rpm) {
            return tp.torque;
        } else if (tp.rpm > rpm) {
            max = mid;
        } else {
            min = mid;
        }
    }

    var minTp = chassis.torquePoints[min];
    var maxTp = chassis.torquePoints[max];
    var TM = maxTp.torque;
    var Tm = minTp.torque;
    var RM = maxTp.rpm;
    var Rm = minTp.rpm;

    var a = (TM - Tm) / (RM - Rm);

    return rpm * a + Tm - Rm * a;
}

function sign(x) {
    return (x > 0.0 ? 1 : (x < 0.0 ? -1 : 0));
}

function action(key, value, dt)
{
    if (key == AAuxb1 && value == 0) {
        this.automaticTransmission = !this.automaticTransmission;
        this.log_inf("Automatic transmission " + (this.automaticTransmission ? "enabled" : "disabled"));
    }

    if (key == AAuxb2) {
        if (this.clutchMode != ClutchMode.Manual) {
            this.clutchState = (value == 0 ? ClutchState.Disengaging : ClutchState.Engaging);
        } else {
            this.clutchState = (value == 0 ? ClutchState.Disengaged : ClutchState.Engaged);
            this.clutch = 1 - value;
        }
        this.clutchOverride = value;
    }

    if (value == 1 && !this.automaticTransmission) {
        switch(key) {
            case AShiftUp:
                this.shiftUp();
                break;
            case AShiftDown:
                this.shiftDown();
                break;
            default:
                break;
        }
    }
}

function select_gear(gear)
{
    if (this.gear == gear) {
        return;
    }

    var i = this.gear.index;
    this.gear = gear;
    if (i == 0 && this.clutchMode == ClutchMode.Automatic && (this.started || this.starting)) {
        this.clutchState = ClutchState.Engaging;
    }
    this.log_inf("gear " + i + " => " + this.gear.index);
}

function shift_up()
{
    var i = this.gear.index;
    if (this.gear.next) {
        this.selectGear(this.gear.next);
    } else if (i == 0) {
        this.selectGear(chassis.forwardGears[0]);
    } else if (i == -1) {
        this.selectGear(chassis.neutroGear);
    }
}

function shift_down()
{
    var i = this.gear.index;
    if (this.gear.prev) {
        this.selectGear(this.gear.prev);
    } else if (i == 0) {
        this.selectGear(chassis.reverseGears[0]);
    } else if (i == 1) {
        this.selectGear(chassis.neutroGear);
    }
}

function automatic_transmission(engine)
{
    if (this.engineRPM < 10 && this.gear.index != 0) {
        this.gear = chassis.neutroGear;
        this.direction = 0;
        this.selectGear(chassis.neutroGear);
    }
    if (engine != 0.0) {
        if (sign(engine) != this.direction) {
            this.direction = sign(engine);
            if (this.direction == 1.0) {
                this.selectGear(chassis.forwardGears[0]);
            } else if (this.direction == -1.0) {
                this.selectGear(chassis.reverseGears[0]);
            }
        }

        if (this.engineRPM > this.gear.shiftUp && this.gear.next) {
            this.shiftUp();
        } else if (this.engineRPM < this.gear.shiftDown && this.gear.prev) {
            this.shiftDown();
        }
    }
}

function automatic_clutch(wheelsRpm)
{
    var clutched = (this.clutchState == ClutchState.Disengaged  || this.clutchState == ClutchState.Disengaging) && this.gear.index != 0;
    var clutchRPM = chassis.minimumRPM + 2000;
    var w = wheelsRpm * this.gear.ratio * chassis.differentialRatio;

    if (this.clutchMode == ClutchMode.Automatic && !this.clutchOverride && (this.started || this.starting)) {
        if (clutched && this.engineRPM < chassis.minimumRPM && w < chassis.minimumRPM) {
            this.clutchState = ClutchState.Engaging;
        } else if (!clutched && (this.engineRPM > clutchRPM || w > chassis.minimumRPM)) {
            this.clutchState = ClutchState.Disengaging;
        }
    }

    if (this.clutchState == ClutchState.Disengaging) {
        if (this.gear.index != 0) {
            this.clutch = (w > chassis.minimumRPM ? chassis.minimumRPM : w) / chassis.minimumRPM;

            // This makes an horizontal S-like shape. (mirrored, like Z)
            var f = this.clutch * 2;
            if (f < 0.5) {
                this.clutch = -(f * f * f * f - 1) / 5;
            } else {
                f = f - 1;
                this.clutch = (f * f * f * f) + 0.2;
            }
            this.clutch += 0.4;
            var r = (this.engineRPM - chassis.minimumRPM) / clutchRPM;
            r = (r > 1 ? 1 : (r < 0 ? 0 : r));
            r = Math.sqrt(r);
            this.clutch *= r
        } else {
            this.clutch = 1;
        }

        if (this.clutch >= 1) {
            this.clutch = 1;
            this.clutchState = ClutchState.Disengaged;
        }
    } else if (this.clutchState == ClutchState.Engaging) {
        this.clutch = 0;
        this.clutchState = ClutchState.Engaged;
    }
    return this.clutch;
}

function clutch_value(wheelsRpm)
{
    var clutch = this.clutch;
    if (this.clutchMode != ClutchMode.Manual) {
        clutch = this.automaticClutch(wheelsRpm);
    }
    if (this.gear.index == 0) {
        clutch = 0;
    }
    return clutch;
}

function animate()
{
    this.animate_wheels();
}

//invoked each frame to handle the inputs and animate the model
function update_frame(dt, engine, brake, steering) {
    steering *= 0.6;
    this.steer(-2, steering);

    var wheelsRpm = this.max_rpm();
    if (sign(this.speed()) != sign(this.gear.index) && this.gear.index != 0) {
        wheelsRpm = 0;
    }

    if (this.automaticTransmission) {
        this.updateAutomaticTransmission(engine);
    }
    if (engine < 0) {
        engine = -engine;
    }

    var appliedTorque = 0;
    if (this.starting) {
        if (this.engineRPM > chassis.minimumRPM) {
            this.starting = false;
            this.started = true;
        } else {
            appliedTorque = 200 * (1 - this.engineRPM / chassis.minimumRPM);
        }
    }

    var oldRPM = this.engineRPM;
    var clutch = this.clutchValue(wheelsRpm);
    this.engineRPM = this.engineRPM * (1 - clutch) + wheelsRpm * clutch * this.gear.ratio * chassis.differentialRatio;

    var running = this.started || this.starting;
    if (running) {
        if (this.engineRPM < chassis.minimumRPM && engine < chassis.minimum) {
            engine = chassis.minimum;
        }
        if (chassis.speedLimiter < 0 || Math.abs(this.speed()) < chassis.speedLimiter) {
            appliedTorque += engine * this.torque(this.engineRPM);
        }
    }

    this.engineRPM += appliedTorque * dt / chassis.engineInertia;

    var s = sign(this.engineRPM);
    var friction = 0.2;
    var eb = -sign(this.engineRPM) * chassis.maxPowerTP.torque * chassis.engineBrakeCoefficient *
                  (friction + (1.0 - friction) * this.engineRPM / chassis.maxRPM);

    this.engineRPM += eb * dt / chassis.engineInertia;
    if (s != sign(this.engineRPM)) {
        this.engineRPM = 0;
    } else {
        appliedTorque += eb;
    }

    var tq = appliedTorque + chassis.engineInertia * (oldRPM - this.engineRPM) / dt;
    var force = tq * clutch * this.gear.ratio * chassis.differentialRatio * chassis.efficiency / chassis.wheelRadius;
    if (this.gear.index < 0) {
        force = -force;
    }

    this.wheel_force(2, force / 2);
    this.wheel_force(3, force / 2);

    brake *= chassis.breakingForce;
    this.wheel_brake(-1, brake);

    this.animate();

    var rpm = (this.engineRPM + oldRPM) / 2.0; // stabilize the fluctuations when the wheelsRpm and engineRPM
                                               // are very different
    var pitch = chassis.pitchMultiplier * (rpm - chassis.minimumRPM) / chassis.maxRPM;
    var vol = rpm / chassis.minimumRPM * 2.0;
    vol = (vol > 1 ? 1 : (vol < 0 ? 0 : vol));

    this.snd.set_pitch(this.onSource, pitch + chassis.basePitch[2]);
    this.snd.set_gain(this.onSource, chassis.relVolumes[2] * engine * vol);

    var speed = Math.abs(this.speed());
    this.snd.set_pitch(this.offSource, pitch + chassis.basePitch[1]);
    var v = speed / 5;
    this.snd.set_gain(this.offSource, chassis.relVolumes[1] * (1 - engine * vol) * Math.min(v, 1.0));

    var v = speed / 20;
    if (!clutch) {
        v = rpm / chassis.maxRPM;
    }
    if (!running && this.idleSound > 0) {
        this.idleSound -= dt;
        this.idleSound = (this.idleSound < 0 ? 0 : this.idleSound);
    }
    this.snd.set_pitch(this.idleSource, pitch + chassis.basePitch[0]);
    this.snd.set_gain(this.idleSource, this.idleSound * chassis.relVolumes[0] * (1 - engine) * Math.max(vol - v, 0));

    if (rpm < 100) { //dead
        if (!this.clutchOverride) {
            this.clutch = 1.0;
            this.clutchState = ClutchState.Disengaged;
        }
        this.started = false;
    }
}

Changelog:
  • Better sound management
  • Better separation between vehicle specific code and generic code
  • Various behavioural improvements when using the clutch, when the engine dies, ...
Logged
ResidualVM 0.1.1 is OUT! www.residualvm.org

ZeosPantera

  • ||>>-Z-<<||
  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2520
  • #1 Outerra Fan Boy
    • My Youtube
Re: Vehicle script [version 1.3.0]
« Reply #49 on: May 27, 2013, 12:44:14 pm »

I still think you should have a separate front and rear wheel description and you don't have lateral slip in there.
Logged
"Fear accompanies the possibility of death, Calm shepherds its certainty" - General Ka Dargo

giucam

  • Full Member
  • ***
  • Posts: 171
  • It's an ugly pile of bones... like me.
Re: Vehicle script [version 1.3.0]
« Reply #50 on: May 27, 2013, 12:51:02 pm »

Those are all vehicle specific things. While this script works with the BMW out od the box (actually not anymore, an update of it is coming), it's not the focus of my work here.
Besides, I wouldn't know what to use as the lateral slip and in what the front and rear wheels would differ.

P.S. I just noticed 1.3.0 has a bug with automatic transmission. 1.3.1 coming. Testing is never enough...
Logged
ResidualVM 0.1.1 is OUT! www.residualvm.org

giucam

  • Full Member
  • ***
  • Posts: 171
  • It's an ugly pile of bones... like me.
Re: Vehicle script [version 1.3.1]
« Reply #51 on: May 27, 2013, 01:15:59 pm »

1.3.1:

Code: [Select]
/*
    Vehicle script file
    Copyright (C) 2012 - 2013  Giulio Camuffo <giuliocamuffo@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 3.0 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//see http://xtrac.outerraworld.com/trac.fcgi/wiki/vehicle for example and documentation

// VERSION 1.3.1

var chassis = {};

// --- Vehicle specific stuff ---
function chassis_setup() {
    var wheelparam = {
        radius: 0.30,
        width: 0.20,
        suspension_max: 0.1,
        suspension_min: -0.05,
        suspension_stiffness: 50.0,
        damping_compression: 0.06,
        damping_relaxation: 0.05,
        slip: 3.0,
        roll_influence: 0.1,
        rotation: -1
    };

    this.add_wheel('wheel_FL', wheelparam);
    this.add_wheel('wheel_FR', wheelparam);
    this.add_wheel('wheel_RL', wheelparam);
    this.add_wheel('wheel_RR', wheelparam);

    this.load_sound("e90_onidle.ogg"); //idle
    this.load_sound("e90_offlow.ogg"); //off
    this.load_sound("e90_onlow.ogg"); //on
    chassis.basePitch = [ 1, 0.4, 0.4 ];             //base pitch for idle, off, on
    chassis.relVolumes = [ 0.8, 1, 1 ];
    this.add_sound_emitter("hood");

    //engine properties -- modify these to change the engine behaviour
    chassis.wheelRadius = 0.24;

    chassis.torquePoints = [ { rpm: 500,  torque: 0},
                             { rpm: 1000, torque: 250},
                             { rpm: 2000, torque: 335},
                             { rpm: 3000, torque: 380},
                             { rpm: 4000, torque: 400},
                             { rpm: 5000, torque: 395},
                             { rpm: 6000, torque: 400},
                             { rpm: 7000, torque: 390},
                             { rpm: 8000, torque: 365},
                             { rpm: 9000, torque: 0  } ];

    chassis.forwardGears = [ { ratio: 4.06, shiftUp: 8000, shiftDown: -1   },
                             { ratio: 2.40, shiftUp: 8000, shiftDown: 4500 },
                             { ratio: 1.58, shiftUp: 8000, shiftDown: 5000 },
                             { ratio: 1.19, shiftUp: 8000, shiftDown: 5500 },
                             { ratio: 1.00, shiftUp: 8000, shiftDown: 6000 },
                             { ratio: 0.87, shiftUp: -1,   shiftDown: 6000 } ];
    chassis.reverseGears = [ { ratio: 4.68, shiftUp: -1, shiftDown: -1 } ];

    chassis.differentialRatio = 3.85;
    chassis.efficiency = 0.9;
    chassis.speedLimiter = -1; // maximum speed in m/s. a value < 0 means there's no limiter
    chassis.engineBrakeCoefficient = 0.4;
    chassis.breakingForce = 3000.0;
    chassis.pitchMultiplier = 1.5;
    chassis.engineInertia = 0.015;
    chassis.minimumRPM = 1500;
    chassis.minimum = 0.2;
    //end of engine properties

    return { mass:1570, steering:1.2, steering_ecf:70, centering: 5.0, centering_ecf: 40, com: { z:0.1 } };
}

function vehicle_setup() {
    this.set_fps_camera_pos( {x: -0.33,y: -0.20, z: 1.15});
    this.soundRefDistance = 5;
    this.automaticTransmission = false;
    this.clutchMode = ClutchMode.Automatic;
}

// --- End of vehicle specific stuff ---



//invoked only the first time the model is loaded, or upon reload
function init_chassis() {
    this.setup = chassis_setup;
    var ret = this.setup();

    chassis.maxPowerTP = chassis.torquePoints[0];
    chassis.maxRPM = 0;
    var maxPw = 0;
    for (var i = 1; i < chassis.torquePoints.length; ++i) {
        var tp = chassis.torquePoints[i];
        if (tp.rpm * tp.torque > maxPw) {
            chassis.maxPowerTP = tp;
        }
        if (tp.rpm > chassis.maxRPM) {
            chassis.maxRPM = tp.rpm;
        }
    }

    chassis.neutroGear = { ratio: 0.0, shiftUp: -1, shiftDown: -1, index: 0 };
    var prev = null;
    for (var i = 0; i < chassis.forwardGears.length; ++i) {
        var gear = chassis.forwardGears[i];
        if (prev)
            prev.next = gear;
        gear.prev = prev;
        gear.index = i + 1;
        prev = gear;
    }

    prev = null;
    for (var i = 0; i < chassis.reverseGears.length; ++i) {
        var gear = chassis.reverseGears[i];
        if (prev)
            prev.prev = gear;
        gear.next = prev;
        gear.index = -i - 1;
        prev = gear;
    }

    return ret;
}

var ClutchMode = { Manual: 0, Automatic: 1, Mixed: 2 };
var ClutchState = { Engaged: 0, Disengaged: 1, Engaging: 2, Disengaging: 3 };

//invoked for each new instance of the vehicle
function init_vehicle() {
    this.snd = this.sound();

    this.torque = engineTorque;
    this.shiftUp = shift_up;
    this.shiftDown = shift_down;
    this.selectGear = select_gear;
    this.updateAutomaticTransmission = automatic_transmission;
    this.automaticClutch = automatic_clutch;
    this.clutchValue = clutch_value;
    this.animate = animate;
    this.setup = vehicle_setup;

    this.setup();

    this.idleSource = this.snd.create_source(0);
    this.onSource = this.snd.create_source(0);
    this.offSource = this.snd.create_source(0);
    this.idleSound = 1;
    this.snd.set_ref_distance(this.idleSource, this.soundRefDistance);
    this.snd.set_ref_distance(this.onSource, this.soundRefDistance);
    this.snd.set_ref_distance(this.offSource, this.soundRefDistance);
    this.snd.play(this.idleSource, 0, true, false);
    this.snd.play(this.offSource, 1, true, false);
    this.snd.play(this.onSource, 2, true, false);

    this.clutch = 1.0;
    this.clutchState = ClutchState.Disengaged;
    this.started = false;
    this.gear = chassis.neutroGear;
    this.direction = 0;
    this.engineRPM = 0;
    this.starting = false;
    this.clutchOverride = false;
}

//invoked when engine starts or stops
function engine(start) {
    this.started = false;
    this.idleSound = 1.0;
    if (start) {
        this.starting = true;
    }
}

function engineTorque(rpm) {
    var min = 0;
    var max = chassis.torquePoints.length - 1;

    if (rpm > chassis.torquePoints[max].rpm || rpm < chassis.torquePoints[min].rpm)
        return 0;

    while (max - min > 1) {
        var mid = Math.floor(min + (max - min) / 2);
        var tp = chassis.torquePoints[mid];
        if (tp.rpm == rpm) {
            return tp.torque;
        } else if (tp.rpm > rpm) {
            max = mid;
        } else {
            min = mid;
        }
    }

    var minTp = chassis.torquePoints[min];
    var maxTp = chassis.torquePoints[max];
    var TM = maxTp.torque;
    var Tm = minTp.torque;
    var RM = maxTp.rpm;
    var Rm = minTp.rpm;

    var a = (TM - Tm) / (RM - Rm);

    return rpm * a + Tm - Rm * a;
}

function sign(x) {
    return (x > 0.0 ? 1 : (x < 0.0 ? -1 : 0));
}

function action(key, value, dt)
{
    if (key == AAuxb1 && value == 0) {
        this.automaticTransmission = !this.automaticTransmission;
        this.log_inf("Automatic transmission " + (this.automaticTransmission ? "enabled" : "disabled"));
    }

    if (key == AAuxb2) {
        if (this.clutchMode != ClutchMode.Manual) {
            this.clutchState = (value == 0 ? ClutchState.Disengaging : ClutchState.Engaging);
        } else {
            this.clutchState = (value == 0 ? ClutchState.Disengaged : ClutchState.Engaged);
            this.clutch = 1 - value;
        }
        this.clutchOverride = value;
    }

    if (value == 1 && !this.automaticTransmission) {
        switch(key) {
            case AShiftUp:
                this.shiftUp();
                break;
            case AShiftDown:
                this.shiftDown();
                break;
            default:
                break;
        }
    }
}

function select_gear(gear)
{
    if (this.gear == gear) {
        return;
    }

    var i = this.gear.index;
    this.gear = gear;
    if (i == 0 && this.clutchMode == ClutchMode.Automatic && (this.started || this.starting)) {
        this.clutchState = ClutchState.Engaging;
    }
    this.log_inf("gear " + i + " => " + this.gear.index);
}

function shift_up()
{
    var i = this.gear.index;
    if (this.gear.next) {
        this.selectGear(this.gear.next);
    } else if (i == 0) {
        this.selectGear(chassis.forwardGears[0]);
    } else if (i == -1) {
        this.selectGear(chassis.neutroGear);
    }
}

function shift_down()
{
    var i = this.gear.index;
    if (this.gear.prev) {
        this.selectGear(this.gear.prev);
    } else if (i == 0) {
        this.selectGear(chassis.reverseGears[0]);
    } else if (i == 1) {
        this.selectGear(chassis.neutroGear);
    }
}

function automatic_transmission(engine)
{
    if (this.engineRPM < 10 && this.gear.index != 0) {
        this.direction = 0;
        this.selectGear(chassis.neutroGear);
    }
    if (engine != 0.0) {
        if (sign(engine) != this.direction) {
            this.direction = sign(engine);
            this.selectGear(chassis.neutroGear);
            if (this.direction == 1.0) {
                this.selectGear(chassis.forwardGears[0]);
            } else if (this.direction == -1.0) {
                this.selectGear(chassis.reverseGears[0]);
            }
        }
    }

    if (this.clutch != 0) {
        if (this.engineRPM > this.gear.shiftUp && this.gear.next) {
            this.shiftUp();
        } else if (this.engineRPM < this.gear.shiftDown && this.gear.prev) {
            this.shiftDown();
        }
    }
}

function automatic_clutch(wheelsRpm)
{
    var clutched = (this.clutchState == ClutchState.Disengaged  || this.clutchState == ClutchState.Disengaging) && this.gear.index != 0;
    var clutchRPM = chassis.minimumRPM * 7 / 4;
    var w = wheelsRpm * this.gear.ratio * chassis.differentialRatio;

    if (this.clutchMode == ClutchMode.Automatic && !this.clutchOverride && (this.started || this.starting)) {
        if (clutched && this.engineRPM < chassis.minimumRPM && w < chassis.minimumRPM) {
            this.clutchState = ClutchState.Engaging;
        } else if (!clutched && (this.engineRPM > clutchRPM || w > chassis.minimumRPM)) {
            this.clutchState = ClutchState.Disengaging;
        }
    }

    if (this.clutchState == ClutchState.Disengaging) {
        if (this.gear.index != 0) {
            this.clutch = (w > chassis.minimumRPM ? chassis.minimumRPM : w) / chassis.minimumRPM;

            // This makes an horizontal S-like shape. (mirrored, like Z)
            var f = this.clutch * 2;
            if (f < 0.5) {
                this.clutch = -(f * f * f * f - 1) / 5;
            } else {
                f = f - 1;
                this.clutch = (f * f * f * f) + 0.2;
            }
            this.clutch += 0.4;
            var r = (this.engineRPM - chassis.minimumRPM) / clutchRPM;
            r = (r > 1 ? 1 : (r < 0 ? 0 : r));
            r = Math.sqrt(r);
            this.clutch *= r
        } else {
            this.clutch = 1;
        }

        if (this.clutch >= 1) {
            this.clutch = 1;
            this.clutchState = ClutchState.Disengaged;
        }
    } else if (this.clutchState == ClutchState.Engaging) {
        this.clutch = 0;
        this.clutchState = ClutchState.Engaged;
    }
    return this.clutch;
}

function clutch_value(wheelsRpm)
{
    var clutch = this.clutch;
    if (this.clutchMode != ClutchMode.Manual) {
        clutch = this.automaticClutch(wheelsRpm);
    }
    if (this.gear.index == 0) {
        clutch = 0;
    }
    return clutch;
}

function animate()
{
    this.animate_wheels();
}

//invoked each frame to handle the inputs and animate the model
function update_frame(dt, engine, brake, steering) {
    steering *= 0.6;
    this.steer(-2, steering);

    if (this.automaticTransmission) {
        this.updateAutomaticTransmission(engine);
    }

    var wheelsRpm = this.max_rpm();
    if (sign(this.speed()) != sign(this.gear.index) && this.gear.index != 0) {
        wheelsRpm = 0;
    }

    if (engine < 0) {
        engine = -engine;
    }

    var appliedTorque = 0;
    if (this.starting) {
        if (this.engineRPM > chassis.minimumRPM) {
            this.starting = false;
            this.started = true;
        } else {
            appliedTorque = 200 * (1 - this.engineRPM / chassis.minimumRPM);
        }
    }

    var oldRPM = this.engineRPM;
    var clutch = this.clutchValue(wheelsRpm);
    this.engineRPM = this.engineRPM * (1 - clutch) + wheelsRpm * clutch * this.gear.ratio * chassis.differentialRatio;

    var running = this.started || this.starting;
    if (running) {
        if (this.engineRPM < chassis.minimumRPM && engine < chassis.minimum) {
            engine = chassis.minimum;
        }
        if (chassis.speedLimiter < 0 || Math.abs(this.speed()) < chassis.speedLimiter) {
            appliedTorque += engine * this.torque(this.engineRPM);
        }
    }

    this.engineRPM += appliedTorque * dt / chassis.engineInertia;

    var s = sign(this.engineRPM);
    var friction = 0.2;
    var eb = -sign(this.engineRPM) * chassis.maxPowerTP.torque * chassis.engineBrakeCoefficient *
                  (friction + (1.0 - friction) * this.engineRPM / chassis.maxRPM);

    this.engineRPM += eb * dt / chassis.engineInertia;
    if (s != sign(this.engineRPM)) {
        this.engineRPM = 0;
    } else {
        appliedTorque += eb;
    }

    var tq = appliedTorque + chassis.engineInertia * (oldRPM - this.engineRPM) / dt;
    var force = tq * clutch * this.gear.ratio * chassis.differentialRatio * chassis.efficiency / chassis.wheelRadius;
    if (this.gear.index < 0) {
        force = -force;
    }

    this.wheel_force(2, force / 2);
    this.wheel_force(3, force / 2);

    brake *= chassis.breakingForce;
    this.wheel_brake(-1, brake);

    this.animate();

    var rpm = (this.engineRPM + oldRPM) / 2.0; // stabilize the fluctuations when the wheelsRpm and engineRPM
                                               // are very different
    var pitch = chassis.pitchMultiplier * (rpm - chassis.minimumRPM) / chassis.maxRPM;
    var vol = rpm / chassis.minimumRPM * 2.0;
    vol = (vol > 1 ? 1 : (vol < 0 ? 0 : vol));

    this.snd.set_pitch(this.onSource, pitch + chassis.basePitch[2]);
    this.snd.set_gain(this.onSource, chassis.relVolumes[2] * engine * vol);

    var speed = Math.abs(this.speed());
    this.snd.set_pitch(this.offSource, pitch + chassis.basePitch[1]);
    var v = speed / 5;
    this.snd.set_gain(this.offSource, chassis.relVolumes[1] * (1 - engine * vol) * Math.min(v, 1.0));

    var v = speed / 20;
    if (!clutch) {
        v = rpm / chassis.maxRPM;
    }
    if (!running && this.idleSound > 0) {
        this.idleSound -= dt;
        this.idleSound = (this.idleSound < 0 ? 0 : this.idleSound);
    }
    this.snd.set_pitch(this.idleSource, pitch + chassis.basePitch[0]);
    this.snd.set_gain(this.idleSource, this.idleSound * chassis.relVolumes[0] * (1 - engine) * Math.max(vol - v, 0));

    if (rpm < 100) { //dead
        if (!this.clutchOverride) {
            this.clutch = 1.0;
            this.clutchState = ClutchState.Disengaged;
        }
        this.started = false;
    }
}

  • Fixed automatic transmission
Logged
ResidualVM 0.1.1 is OUT! www.residualvm.org

ZeosPantera

  • ||>>-Z-<<||
  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2520
  • #1 Outerra Fan Boy
    • My Youtube
Re: Vehicle script [version 1.3.1]
« Reply #52 on: May 27, 2013, 03:55:38 pm »

Setting the Lateral slip to 1.0 is what happens when you don't add that line.. It means the lateral slip is equal to the slip. A higher value means more lateral grip than longitudinal and less means less.
Logged
"Fear accompanies the possibility of death, Calm shepherds its certainty" - General Ka Dargo

giucam

  • Full Member
  • ***
  • Posts: 171
  • It's an ugly pile of bones... like me.
Re: Vehicle script [version 1.3.1]
« Reply #53 on: May 27, 2013, 04:05:23 pm »

Mmh... http://xtrac.outerraworld.com/trac.fcgi/wiki/wheel says the lateral slip is by default 0.5 the slip.
Logged
ResidualVM 0.1.1 is OUT! www.residualvm.org

Atrax

  • Full Member
  • ***
  • Posts: 119
  • newbie
    • AtraxGaming Game Shop
Re: Vehicle script [version 1.3.1]
« Reply #54 on: May 29, 2013, 03:59:11 am »

Hi guys, I have a tiny problem with the M3, when I turn (let's say left) my car leans to the left like a bike, but it should lean to the right when turning left (centrifugal force). I hope you get what I mean. Is there a way to fix this?
I also noticed like many others that car sticks to the ground like a tiger no matter what speed you're doing and rear doesn't break out at all at any speed (at higher speeds it just flips it over). I guess that b/c of current tyre physics, but I'm no expert.
« Last Edit: May 29, 2013, 04:08:41 am by Atrax »
Logged

mLichy

  • Full Member
  • ***
  • Posts: 104
  • newbie
Re: Vehicle script [version 1.3.1]
« Reply #55 on: May 29, 2013, 09:14:06 am »

Not sure about the leaning. My belair will break free. This is one thing I worked on a bit, since I agree, other cars stuck to the ground too much.
Logged

ZeosPantera

  • ||>>-Z-<<||
  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2520
  • #1 Outerra Fan Boy
    • My Youtube
Re: Vehicle script [version 1.3.1]
« Reply #56 on: May 29, 2013, 01:40:40 pm »

Make the slip < 0.7 and it should be better.
Logged
"Fear accompanies the possibility of death, Calm shepherds its certainty" - General Ka Dargo

Atrax

  • Full Member
  • ***
  • Posts: 119
  • newbie
    • AtraxGaming Game Shop
Re: Vehicle script [version 1.3.1]
« Reply #57 on: May 29, 2013, 03:27:16 pm »

I'll try that now. Thanks!

Oh yea, I love how Belair drives, lot better than others imo, also Thumbler is pretty good to drive as it can slide a bit, other cars are getting better every time someone fiddles with those values. :)

giucam

  • Full Member
  • ***
  • Posts: 171
  • It's an ugly pile of bones... like me.
Re: Vehicle script [version 1.3.2]
« Reply #58 on: June 03, 2013, 12:42:39 pm »

1.3.2:

Code: [Select]
/*
    Vehicle script file
    Copyright (C) 2012 - 2013  Giulio Camuffo <giuliocamuffo@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 3.0 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//see http://xtrac.outerraworld.com/trac.fcgi/wiki/vehicle for example and documentation

// VERSION 1.3.2

var chassis = {};

// --- Vehicle specific stuff ---
function chassis_setup() {
    var wheelparam = {
        radius: 0.30,
        width: 0.20,
        suspension_max: 0.1,
        suspension_min: -0.05,
        suspension_stiffness: 50.0,
        damping_compression: 0.06,
        damping_relaxation: 0.05,
        slip: 2.0,
        roll_influence: 0.1,
        rotation: -1
    };

    this.add_wheel('wheel_FL', wheelparam);
    this.add_wheel('wheel_FR', wheelparam);
    this.add_wheel('wheel_RL', wheelparam);
    this.add_wheel('wheel_RR', wheelparam);

    this.load_sound("e90_onidle.ogg"); //idle
    this.load_sound("e90_offlow.ogg"); //off
    this.load_sound("e90_onlow.ogg"); //on
    chassis.basePitch = [ 1, 0.4, 0.4 ];             //base pitch for idle, off, on
    chassis.relVolumes = [ 0.8, 1, 1 ];
    this.add_sound_emitter("hood");

    //engine properties -- modify these to change the engine behaviour
    chassis.wheelRadius = 0.24;

    chassis.torquePoints = [ { rpm: 500,  torque: 0},
                             { rpm: 1000, torque: 250},
                             { rpm: 2000, torque: 335},
                             { rpm: 3000, torque: 380},
                             { rpm: 4000, torque: 400},
                             { rpm: 5000, torque: 395},
                             { rpm: 6000, torque: 400},
                             { rpm: 7000, torque: 390},
                             { rpm: 8000, torque: 365},
                             { rpm: 9000, torque: 0  } ];

    chassis.forwardGears = [ { ratio: 4.06, shiftUp: 8000, shiftDown: -1   },
                             { ratio: 2.40, shiftUp: 8000, shiftDown: 4500 },
                             { ratio: 1.58, shiftUp: 8000, shiftDown: 5000 },
                             { ratio: 1.19, shiftUp: 8000, shiftDown: 5500 },
                             { ratio: 1.00, shiftUp: 8000, shiftDown: 6000 },
                             { ratio: 0.87, shiftUp: -1,   shiftDown: 6000 } ];
    chassis.reverseGears = [ { ratio: 4.68, shiftUp: -1, shiftDown: -1 } ];

    chassis.differentialRatio = 3.85;
    chassis.efficiency = 0.9;
    chassis.speedLimiter = -1; // maximum speed in m/s. a value < 0 means there's no limiter
    chassis.engineBrakeCoefficient = 0.4;
    chassis.breakingForce = 3000.0;
    chassis.pitchMultiplier = 1.5;
    chassis.engineInertia = 0.015;
    chassis.minimumRPM = 1500;
    chassis.minimum = 0.2;
    //end of engine properties

    return { mass:1570, steering:1.2, steering_ecf:700, centering: 5.0, centering_ecf: 40, com: { z:0.1 } };
}

function vehicle_setup() {
    this.set_fps_camera_pos( {x: -0.33,y: -0.20, z: 1.15});
    this.soundRefDistance = 5;
    this.automaticTransmission = false;
    this.clutchMode = ClutchMode.Automatic;
}

function animate()
{
    this.animate_wheels();
}

// --- End of vehicle specific stuff ---



//invoked only the first time the model is loaded, or upon reload
function init_chassis() {
    this.setup = chassis_setup;
    var ret = this.setup();

    chassis.maxPowerTP = chassis.torquePoints[0];
    chassis.maxRPM = 0;
    var maxPw = 0;
    for (var i = 1; i < chassis.torquePoints.length; ++i) {
        var tp = chassis.torquePoints[i];
        if (tp.rpm * tp.torque > maxPw) {
            chassis.maxPowerTP = tp;
        }
        if (tp.rpm > chassis.maxRPM) {
            chassis.maxRPM = tp.rpm;
        }
    }

    chassis.neutroGear = { ratio: 0.0, shiftUp: -1, shiftDown: -1, index: 0 };
    var prev = null;
    for (var i = 0; i < chassis.forwardGears.length; ++i) {
        var gear = chassis.forwardGears[i];
        if (prev)
            prev.next = gear;
        gear.prev = prev;
        gear.index = i + 1;
        prev = gear;
    }

    prev = null;
    for (var i = 0; i < chassis.reverseGears.length; ++i) {
        var gear = chassis.reverseGears[i];
        if (prev)
            prev.prev = gear;
        gear.next = prev;
        gear.index = -i - 1;
        prev = gear;
    }

    return ret;
}

var ClutchMode = { Manual: 0, Automatic: 1, Mixed: 2 };
var ClutchState = { Engaged: 0, Disengaged: 1, Engaging: 2, Disengaging: 3 };

//invoked for each new instance of the vehicle
function init_vehicle() {
    this.snd = this.sound();

    this.torque = engineTorque;
    this.shiftUp = shift_up;
    this.shiftDown = shift_down;
    this.selectGear = select_gear;
    this.updateAutomaticTransmission = automatic_transmission;
    this.automaticClutch = automatic_clutch;
    this.clutchValue = clutch_value;
    this.animate = animate;
    this.setup = vehicle_setup;

    this.setup();

    this.idleSource = this.snd.create_source(0);
    this.onSource = this.snd.create_source(0);
    this.offSource = this.snd.create_source(0);
    this.idleSound = 1;
    this.snd.set_ref_distance(this.idleSource, this.soundRefDistance);
    this.snd.set_ref_distance(this.onSource, this.soundRefDistance);
    this.snd.set_ref_distance(this.offSource, this.soundRefDistance);
    this.snd.play(this.idleSource, 0, true, false);
    this.snd.play(this.offSource, 1, true, false);
    this.snd.play(this.onSource, 2, true, false);

    this.clutch = 1.0;
    this.clutchState = ClutchState.Disengaged;
    this.started = false;
    this.gear = chassis.neutroGear;
    this.direction = 0;
    this.engineRPM = 0;
    this.starting = false;
    this.clutchOverride = false;
}

//invoked when engine starts or stops
function engine(start) {
    this.started = false;
    this.starting = start;
    this.idleSound = 1.0;
}

function engineTorque(rpm) {
    var min = 0;
    var max = chassis.torquePoints.length - 1;

    if (rpm > chassis.torquePoints[max].rpm || rpm < chassis.torquePoints[min].rpm)
        return 0;

    while (max - min > 1) {
        var mid = Math.floor(min + (max - min) / 2);
        var tp = chassis.torquePoints[mid];
        if (tp.rpm == rpm) {
            return tp.torque;
        } else if (tp.rpm > rpm) {
            max = mid;
        } else {
            min = mid;
        }
    }

    var minTp = chassis.torquePoints[min];
    var maxTp = chassis.torquePoints[max];
    var TM = maxTp.torque;
    var Tm = minTp.torque;
    var RM = maxTp.rpm;
    var Rm = minTp.rpm;

    var a = (TM - Tm) / (RM - Rm);

    return rpm * a + Tm - Rm * a;
}

function sign(x) {
    return (x > 0.0 ? 1 : (x < 0.0 ? -1 : 0));
}

function action(key, value, dt)
{
    if (key == AAuxb1 && value == 0) {
        this.automaticTransmission = !this.automaticTransmission;
        this.log_inf("Automatic transmission " + (this.automaticTransmission ? "enabled" : "disabled"));
    }

    if (key == AAuxb2 || key == AAuxa2) {
        if (key == AAuxa2) {
            value = 1 - (value + 1) / 2;
        }

        this.clutchState = (value == 0 ? ClutchState.Disengaged : ClutchState.Engaged);
        this.clutch = 1 - value;
        this.clutchOverride = value != 0;
    }

    if (value == 1 && !this.automaticTransmission) {
        switch(key) {
            case AShiftUp:
                this.shiftUp();
                break;
            case AShiftDown:
                this.shiftDown();
                break;
            default:
                break;
        }
    }
}

function select_gear(gear)
{
    if (this.gear == gear) {
        return;
    }

    var i = this.gear.index;
    this.gear = gear;
    if (i == 0 && this.clutchMode == ClutchMode.Automatic && (this.started || this.starting)) {
        this.clutchState = ClutchState.Engaging;
    }
    this.log_inf("gear " + i + " => " + this.gear.index);
}

function shift_up()
{
    var i = this.gear.index;
    if (this.gear.next) {
        this.selectGear(this.gear.next);
    } else if (i == 0) {
        this.selectGear(chassis.forwardGears[0]);
    } else if (i == -1) {
        this.selectGear(chassis.neutroGear);
    }
}

function shift_down()
{
    var i = this.gear.index;
    if (this.gear.prev) {
        this.selectGear(this.gear.prev);
    } else if (i == 0) {
        this.selectGear(chassis.reverseGears[0]);
    } else if (i == 1) {
        this.selectGear(chassis.neutroGear);
    }
}

function automatic_transmission(engine)
{
    if (this.engineRPM < 10 && this.gear.index != 0) {
        this.direction = 0;
        this.selectGear(chassis.neutroGear);
    }
    if (engine != 0.0) {
        if (sign(engine) != this.direction) {
            this.direction = sign(engine);
            this.selectGear(chassis.neutroGear);
            if (this.direction == 1.0) {
                this.selectGear(chassis.forwardGears[0]);
            } else if (this.direction == -1.0) {
                this.selectGear(chassis.reverseGears[0]);
            }
        }
    }

    if (this.clutch != 0) {
        if (this.engineRPM > this.gear.shiftUp && this.gear.next) {
            this.shiftUp();
        } else if (this.engineRPM < this.gear.shiftDown && this.gear.prev) {
            this.shiftDown();
        }
    }
}

function automatic_clutch(wheelsRpm)
{
    var clutched = (this.clutchState == ClutchState.Disengaged  || this.clutchState == ClutchState.Disengaging) && this.gear.index != 0;
    var clutchRPM = chassis.minimumRPM * 7 / 4;
    var w = wheelsRpm * this.gear.ratio * chassis.differentialRatio;

    if (this.clutchMode == ClutchMode.Automatic && !this.clutchOverride && (this.started || this.starting)) {
        if (clutched && this.engineRPM < chassis.minimumRPM && w < chassis.minimumRPM) {
            this.clutchState = ClutchState.Engaging;
        } else if (!clutched && (this.engineRPM > clutchRPM || w > chassis.minimumRPM)) {
            this.clutchState = ClutchState.Disengaging;
        }
    }

    if (this.clutchState == ClutchState.Disengaging) {
        if (this.gear.index != 0) {
            this.clutch = (w > chassis.minimumRPM ? chassis.minimumRPM : w) / chassis.minimumRPM;

            // This makes an horizontal S-like shape. (mirrored, like Z)
            var f = this.clutch * 2;
            if (f < 0.5) {
                this.clutch = -(f * f * f * f - 1) / 5;
            } else {
                f = f - 1;
                this.clutch = (f * f * f * f) + 0.2;
            }
            this.clutch += 0.4;
            var r = (this.engineRPM - chassis.minimumRPM) / clutchRPM;
            r = (r > 1 ? 1 : (r < 0 ? 0 : r));
            r = Math.sqrt(r);
            this.clutch *= r
        } else {
            this.clutch = 1;
        }

        if (this.clutch >= 1) {
            this.clutch = 1;
            this.clutchState = ClutchState.Disengaged;
        }
    } else if (this.clutchState == ClutchState.Engaging) {
        this.clutch = 0;
        this.clutchState = ClutchState.Engaged;
    }
    return this.clutch;
}

function clutch_value(wheelsRpm)
{
    var clutch = this.clutch;
    if (this.clutchMode != ClutchMode.Manual && !this.clutchOverride) {
        clutch = this.automaticClutch(wheelsRpm);
    }
    if (this.gear.index == 0) {
        clutch = 0;
    }
    return clutch;
}

//invoked each frame to handle the inputs and animate the model
function update_frame(dt, engine, brake, steering) {
    steering *= 0.6;
    this.steer(-2, steering);

    if (this.automaticTransmission) {
        this.updateAutomaticTransmission(engine);
    }

    var wheelsRpm = Math.abs(this.max_rpm());
    if (sign(this.speed()) != sign(this.gear.index) && this.gear.index != 0) {
        wheelsRpm = 0;
    }

    if (engine < 0) {
        engine = -engine;
    }

    var appliedTorque = 0;
    if (this.starting) {
        if (this.engineRPM > chassis.minimumRPM) {
            this.starting = false;
            this.started = true;
        } else {
            appliedTorque = 200 * (1 - this.engineRPM / chassis.minimumRPM);
        }
    }

    var oldRPM = this.engineRPM;
    var clutch = this.clutchValue(wheelsRpm);
    this.engineRPM = this.engineRPM * (1 - clutch) + wheelsRpm * clutch * this.gear.ratio * chassis.differentialRatio;

    var running = this.started || this.starting;
    if (running) {
        if (this.engineRPM < chassis.minimumRPM && engine < chassis.minimum) {
            engine = chassis.minimum;
        }
        if (chassis.speedLimiter < 0 || Math.abs(this.speed()) < chassis.speedLimiter) {
            appliedTorque += engine * this.torque(this.engineRPM);
        }
    }

    this.engineRPM += appliedTorque * dt / chassis.engineInertia;

    var s = sign(this.engineRPM);
    var friction = 0.2;
    var eb = -sign(this.engineRPM) * chassis.maxPowerTP.torque * chassis.engineBrakeCoefficient *
                  (friction + (1.0 - friction) * this.engineRPM / chassis.maxRPM);

    this.engineRPM += eb * dt / chassis.engineInertia;
    if (s != sign(this.engineRPM)) {
        this.engineRPM = 0;
    } else {
        appliedTorque += eb;
    }

    var tq = appliedTorque + chassis.engineInertia * (oldRPM - this.engineRPM) / dt;
    var force = tq * clutch * this.gear.ratio * chassis.differentialRatio * chassis.efficiency / chassis.wheelRadius;
    if (this.gear.index < 0) {
        force = -force;
    }

    this.wheel_force(2, force / 2);
    this.wheel_force(3, force / 2);

    brake *= chassis.breakingForce;
    this.wheel_brake(-1, brake);

    this.animate();

    var rpm = (this.engineRPM + oldRPM) / 2.0; // stabilize the fluctuations when the wheelsRpm and engineRPM
                                               // are very different
    var pitch = chassis.pitchMultiplier * (rpm - chassis.minimumRPM) / chassis.maxRPM;
    var vol = rpm / chassis.minimumRPM * 2.0;
    vol = (vol > 1 ? 1 : (vol < 0 ? 0 : vol));

    this.snd.set_pitch(this.onSource, pitch + chassis.basePitch[2]);
    this.snd.set_gain(this.onSource, chassis.relVolumes[2] * engine * vol);

    var speed = Math.abs(this.speed());
    this.snd.set_pitch(this.offSource, pitch + chassis.basePitch[1]);
    var v = speed / 5;
    this.snd.set_gain(this.offSource, chassis.relVolumes[1] * (1 - engine * vol) * Math.min(v, 1.0));

    var v = speed / 20;
    if (!clutch) {
        v = Math.min(v, rpm / chassis.maxRPM);
    }
    if (!running && this.idleSound > 0) {
        this.idleSound -= dt;
        this.idleSound = (this.idleSound < 0 ? 0 : this.idleSound);
    }
    this.snd.set_pitch(this.idleSource, pitch + chassis.basePitch[0]);
    this.snd.set_gain(this.idleSource, this.idleSound * chassis.relVolumes[0] * (1 - engine) * Math.max(vol - v, 0));

    if (rpm < 100) { //dead
        if (!this.clutchOverride) {
            this.clutch = 1.0;
            this.clutchState = ClutchState.Disengaged;
        }
        this.started = false;
    }
}

  • Support for manual control of the clutch with a controller axis
  • Can now use the manual clutch when in automatic clutch mode too
  • Fixed a bug with engine sound when revving up while still

Using the clutch manually now shows how bad the automatic clutch works when starting. I'll have to work on that  :-\
Logged
ResidualVM 0.1.1 is OUT! www.residualvm.org

bugsblake

  • Sr. Member
  • ****
  • Posts: 255
  • jedi master
Re: Vehicle script [version 1.3.2]
« Reply #59 on: June 03, 2013, 01:09:21 pm »

sounds good! will try it out later! just one thing, when i copy and paste this into notepad or notepad++, the lines get all messed up! is there another way im ment to be doing it? or maybe you can upload the .js file! thanks
Logged
Intel 6 core i7 Xeon - 4930k @3.40 GHz
GTX 770 4GB X2 in SLI
Asus P9X79 Extreme MOBO
Patriot 16GB DDR3 1600MHz
SSD 250GB + SATA 500GB + SATA 1TB
Pages: 1 2 3 [4] 5 6 ... 8