GetAxisIn() public static method

public static GetAxisIn ( JoyControls c ) : double
c JoyControls
return double
コード例 #1
0
        public void TickControls()
        {
            bool wasActive = Active;

            //
            if (Main.GetButtonIn(JoyControls.LaneAssistance) && ButtonActive)
            {
                Active = !Active;
                ButtonCooldownPeriod = DateTime.Now.Add(new TimeSpan(0, 0, 0, 1));
                LockedSteerAngle     = Main.GetAxisIn(JoyControls.Steering);
                Debug.WriteLine("Setting lane assistance to: " + Active);
            }

            var currentSteerAngle = Main.GetAxisIn(JoyControls.Steering);

            // User overrides steering
            if (Active && Math.Abs(currentSteerAngle - LockedSteerAngle) > 0.05)
            {
                Active = false;
                Debug.WriteLine("[LA] User override steering");
            }

            if (wasActive && !Active)
            {
                beep.Play();
            }
        }
コード例 #2
0
        public void TickTelemetry(IDataMiner data)
        {
            Speed = data.Telemetry.Speed;

            if (Main.GetAxisIn(JoyControls.Brake) > 0.05)
            {
                Cruising = false;
            }

            // Any tracked car?
            if (dlDebugInfo.TrackedCar != null)
            {
                // Gap control?
                var distanceTarget = 20;
                var distanceError  = distanceTarget - dlDebugInfo.TrackedCar.Distance;

                var speedBias = 9 * distanceError / distanceTarget; // 3m/s max decrement
                if (distanceError < 0)
                {
                    speedBias /= 6;
                }
                var targetSpeed = dlDebugInfo.TrackedCar.Speed - speedBias;

                if (targetSpeed >= SpeedCruise)
                {
                    targetSpeed = (float)SpeedCruise;
                }

                var speedErr = data.Telemetry.Speed - targetSpeed - 2;
                if (speedErr > 0) // too fast
                {
                    t = 0;
                    if (speedErr > 1.5f)
                    {
                        b = (float)Math.Pow(speedErr - 1.5f, 4) * 0.015f;
                    }
                }
                else
                {
                    t = -speedErr * 0.2f;
                    b = 0;
                }
            }
            else
            {
                // Speed control
                var speedErr = data.Telemetry.Speed - (float)SpeedCruise;
                if (speedErr > 0) // too fast
                {
                    t = 0;
                }
                else
                {
                    t = -speedErr * 0.4f;
                    b = 0;
                }
            }
        }
コード例 #3
0
        public void TickControls()
        {
            var br = Main.GetAxisIn(JoyControls.Brake);
            var th = Main.GetAxisIn(JoyControls.Throttle);

            switch (state)
            {
            case LaunchControlState.Inactive:
                if (Main.GetButtonIn(JoyControls.LaunchControl) && br > 0.05)
                {
                    Debug.WriteLine("LC activated - waiting");
                    state = LaunchControlState.Waiting;
                }
                break;

            case LaunchControlState.Waiting:
                if (th > 0.1 && br > 0.05)
                {
                    Debug.WriteLine("Revving up engine, waiting for brake to be released");
                    state = LaunchControlState.Revving;
                }
                else if (br < 0.05)
                {
                    Debug.WriteLine("Brake released,  stopped waiting");
                    state = LaunchControlState.Inactive;
                }
                break;

            case LaunchControlState.Revving:
                if (revvedUp && br < 0.05)     // engine is ready & user lets go of brake
                {
                    Debug.WriteLine("GO GO GO");
                    state = LaunchControlState.Pulling;
                }

                if (th < 0.1)     // user lets go of throttle
                {
                    Debug.WriteLine("Back to idle");
                    state = LaunchControlState.Waiting;
                }

                break;

            case LaunchControlState.Pulling:
            case LaunchControlState.Slipping:
                if (th < 0.1 || br > 0.05)
                {
                    Debug.WriteLine("aborting");
                    state = LaunchControlState.Inactive;     // abort
                }
                break;
            }
        }
コード例 #4
0
        public void TickTelemetry(IDataMiner data)
        {
            if (data.Telemetry.Speed * 3.6 > 55)
            {
                triggered = true;
            }

            if (triggered && data.Telemetry.Speed * 3.6 < 35)
            {
                clutchctrl = true;
            }
            else if (data.Telemetry.Speed * 3.6 > 35)
            {
                clutchctrl = false;
            }
            if (data.Telemetry.Speed * 3.6 < 10 && Main.GetAxisIn(JoyControls.Throttle) > 0.1)
            {
                clutchctrl = false;
                triggered  = false;
            }
        }
コード例 #5
0
        public void TickTelemetry(IDataMiner data)
        {
            Enabled = true;
            Active  = true;

            var f = 1.0;

            if (Main.Drivetrain.GearRatios != null && data.Telemetry.Gear >= 1)
            {
                f = Main.Drivetrain.GearRatios[data.Telemetry.Gear - 1] / 5.5;
            }
            var throttle = Math.Max(Main.GetAxisIn(JoyControls.Throttle), data.Telemetry.Throttle);

            TorqueLimit = 1;
            var NotGood = false;

            do
            {
                var wheelTorque = Main.Drivetrain.CalculateTorqueP(data.Telemetry.EngineRpm, TorqueLimit * throttle) * f;
                if (wheelTorque > 20000)
                {
                    TorqueLimit *= 0.999f;
                    NotGood      = true;
                }
                else
                {
                    NotGood = false;
                }
                if (TorqueLimit <= 0.2f)
                {
                    TorqueLimit = 0.2f;
                    break;
                }
            } while (NotGood);

            TorqueLimit = 1.0f;
        }
コード例 #6
0
        public void TickTelemetry(IDataMiner data)
        {
            var rpm = data.Telemetry.EngineRpm;

            err = calRpm - rpm;
            if (err > 500)
            {
                err = 500;
            }
            if (err < -500)
            {
                err = -500;
            }

            switch (state)
            {
            case TransmissionCalibratorStatus.Idle:
                Main.Transmission.OverruleShifts = false;

                // If we're stationary for a few seconds, we can apply brakes and calibrate the clutch
                bool wasStationary = isStationary;
                isStationary = Math.Abs(data.Telemetry.Speed) < 1 && Main.GetAxisIn(JoyControls.Throttle) < 0.05 && data.Telemetry.EngineRpm > 200;

                if (isStationary && !wasStationary)
                {
                    stationary = DateTime.Now;
                }

                if (isStationary && DateTime.Now.Subtract(stationary).TotalMilliseconds > 2500)
                {
                    clutch = 1.0f;

                    // CALIBRATE
                    state = TransmissionCalibratorStatus.IterateCalibrationCycle;
                }
                break;

            case TransmissionCalibratorStatus.FindThrottlePoint:

                throttle += err / 500000.0f;
                if (throttle >= 0.8)
                {
                    // Cannot rev the engine
                }

                var wasRpmInRange = rpmInRange;
                rpmInRange = Math.Abs(err) < 5;

                if (!wasRpmInRange && rpmInRange)
                {
                    rpmInRangeTimer = DateTime.Now;
                }

                // stable at RPM
                if (rpmInRange && DateTime.Now.Subtract(rpmInRangeTimer).TotalMilliseconds > 250)
                {
                    // set error to 0
                    calRpm = rpm;
                    state  = TransmissionCalibratorStatus.FindClutchBitePoint;
                }

                break;

            case TransmissionCalibratorStatus.FindClutchBitePoint:

                if (Main.Transmission.IsShifting)
                {
                    break;
                }
                if (data.Telemetry.Gear != gearTest)
                {
                    Main.Transmission.Shift(data.Telemetry.Gear, gearTest, "normal");
                    break;
                }

                // Decrease clutch 0.25% at a time to find the bite point
                clutch -= 0.25f / 100.0f;

                if (err > 50)
                {
                    // We found the clutch bite point
                    var fs = File.AppendText("./gear-clutch");
                    fs.WriteLine(gearTest + "," + calRpm + "," + clutch);
                    fs.Close();
                    state = TransmissionCalibratorStatus.IterateCalibrationCycle;
                }

                break;

            case TransmissionCalibratorStatus.IterateCalibrationCycle:

                clutch = 1;
                gearTest++;

                calRpm = 700.0f;
                // Find throttle point
                state    = TransmissionCalibratorStatus.FindThrottlePoint;
                throttle = 0.001f;

                rpmInRange = false;

                break;
            }

            //abort when we give power
            if (Main.GetAxisIn(JoyControls.Throttle) > 0.1)
            {
                stationary = DateTime.Now;
                state      = TransmissionCalibratorStatus.Idle;
            }

            Active = state != TransmissionCalibratorStatus.Idle;
        }
コード例 #7
0
 public void TickControls()
 {
     CameraAngle = Main.GetAxisIn(JoyControls.CameraHorizon) * 0.1 + CameraAngle * 0.9;
 }
コード例 #8
0
        public void TickTelemetry(IDataMiner data)
        {
            int idealGear = data.Telemetry.Gear;

            if (data.TransmissionSupportsRanges)
            {
                RangeSize = 6;
            }
            else
            {
                RangeSize = 8;
            }

            // TODO: Add generic telemetry object
            GameGear = data.Telemetry.Gear;
            if (IsShifting)
            {
                return;
            }
            if (TransmissionFrozen && !GetHomeMode)
            {
                return;
            }
            if (OverruleShifts)
            {
                return;
            }
            shiftRetry = 0;

            if (GetHomeMode)
            {
                if (idealGear < 1)
                {
                    idealGear = 1;
                }

                var lowRpm  = Main.Drivetrain.StallRpm * 1.5;
                var highRpm = Main.Drivetrain.StallRpm * 3;

                if (data.Telemetry.EngineRpm < lowRpm && idealGear > 1)
                {
                    idealGear--;
                }
                if (data.Telemetry.EngineRpm > highRpm && idealGear < Main.Drivetrain.Gears)
                {
                    idealGear++;
                }
            }
            else
            {
                if (EnableSportShiftdown)
                {
                    transmissionThrottle = Math.Max(Main.GetAxisIn(JoyControls.Brake) * 8, transmissionThrottle);
                }
                transmissionThrottle = Math.Min(1, Math.Max(0, transmissionThrottle));
                var lookupResult = configuration.Lookup(data.Telemetry.Speed * 3.6, transmissionThrottle);
                idealGear     = lookupResult.Gear;
                ThrottleScale = GetHomeMode ? 1 : lookupResult.ThrottleScale;

                if (Main.Data.Active.Application == "eurotrucks2")
                {
                    var ets2Miner = (Ets2DataMiner)(data);
                    var maxGears  = (int)Math.Round(Main.Drivetrain.Gears * (1 - ets2Miner.MyTelemetry.Damage.WearTransmission));

                    if (idealGear >= maxGears)
                    {
                        idealGear = maxGears;
                    }
                }

                if (data.Telemetry.Gear == 0 && ShiftCtrlNewGear != 0)
                {
                    Debug.WriteLine("Timeout");
                    ShiftCtrlNewGear         = 0;
                    TransmissionFreezeUntill = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, 250));
                    return;
                }
            }

            if (InReverse)
            {
                if (GameGear != -1 && Math.Abs(data.Telemetry.Speed) < 1)
                {
                    Debug.WriteLine("Shift from " + data.Telemetry.Gear + " to  " + idealGear);
                    Shift(data.Telemetry.Gear, -1, "up_1thr");
                }
                return;
            }

            // Kickdown?
            // What is basically does, is making this very-anxious gearbox tone down a bit in it's aggressive shift pattern.
            // With kickdown we specify 2 rules to make the gear "stick" longer with varying throttle positions.
            if (KickdownEnable)
            {
                if (KickdownCooldown)
                {
                    // We're on cooldown. Check if power/speed/rpm is able to reset this
// The scheme is as follow:
                    // if (delta of [current speed] and [speed of last shift] ) > speedReset: then reset cooldown
                    // if ([generated power this gear] / [generated power new gear]) > 1+powerReset: then reset cooldown
                    // if (currentRpm < [rpm * stationaryValue]) : then reset cooldown

                    // This makes sure the gearbox shifts down if on very low revs and almost about to stall.

                    // Note: only for speeding up
                    if ((data.Telemetry.Speed - KickdownLockedSpeed) > KickdownSpeedReset)
                    {
                        Debug.WriteLine("[Kickdown] Reset on overspeed");
                        KickdownCooldown = false;
                    }

                    var maxPwr = Main.Drivetrain.CalculateMaxPower();

                    var engineRpmCurrentGear = Main.Drivetrain.CalculateRpmForSpeed(ShifterOldGear - 1, data.Telemetry.Speed);
                    var pwrCurrentGear       = Main.Drivetrain.CalculatePower(engineRpmCurrentGear, data.Telemetry.Throttle);

                    var engineRpmNewGear = Main.Drivetrain.CalculateRpmForSpeed(idealGear - 1, data.Telemetry.Speed);
                    var pwrNewGear       = Main.Drivetrain.CalculatePower(engineRpmNewGear, data.Telemetry.Throttle);
                    //Debug.WriteLine("N"+pwrCurrentGear.ToString("000") + " I:" + pwrNewGear.ToString("000"));
                    // This makes sure the gearbox shifts down if on low revs and the user is requesting power from the engine
                    if (pwrNewGear / pwrCurrentGear > 1 + KickdownPowerReset &&
                        pwrNewGear / maxPwr > KickdownPowerReset)
                    {
                        Debug.WriteLine("[Kickdown] Reset on power / " + pwrCurrentGear + " / " + pwrNewGear);
                        KickdownCooldown = false;
                    }

                    // This makes sure the gearbox shifts up in decent time when reaching end of gears
                    if (Main.Drivetrain.StallRpm * KickdownRpmReset > data.Telemetry.EngineRpm)
                    {
                        Debug.WriteLine("[Kickdown] Reset on stalling RPM");
                        KickdownCooldown = true;
                    }
                }
                else
                {
                }
            }

            if (idealGear != data.Telemetry.Gear)
            {
                if (KickdownEnable && KickdownCooldown && !GetHomeMode)
                {
                    return;
                }
                KickdownLockedSpeed = Main.Data.Telemetry.Speed;
                var upShift      = idealGear > data.Telemetry.Gear;
                var fullThrottle = data.Telemetry.Throttle > 0.6;

                var shiftStyle = (upShift ? "up" : "down") + "_" + (fullThrottle ? "1" : "0") + "thr";

                Debug.WriteLine("Shift from " + data.Telemetry.Gear + " to  " + idealGear);
                Shift(data.Telemetry.Gear, idealGear, shiftStyle);
            }
        }
コード例 #9
0
        public void Shift(int fromGear, int toGear, string style)
        {
            if (IsShifting)
            {
                return;
            }

            if (EnableSportShiftdown && Main.GetAxisIn(JoyControls.Throttle) < 0.2)
            {
                KickdownTime = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, (int)KickdownTimeout / 10));
            }
            else
            {
                KickdownTime = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, (int)KickdownTimeout));
            }

            if (PowerShift)
            {
                style = "PowerShift";
            }

            if (ShiftPatterns.ContainsKey(style))
            {
                ActiveShiftPatternStr = style;
            }
            else
            {
                ActiveShiftPatternStr = ShiftPatterns.Keys.FirstOrDefault();
            }

            // Copy old control to new control values
            ShiftCtrlOldGear = fromGear;
            if (ShiftCtrlOldGear == -1)
            {
                ShiftCtrlOldRange = 0;
            }
            else if (ShiftCtrlOldGear == 0)
            {
                ShiftCtrlOldRange = 0;
            }
            else if (ShiftCtrlOldGear >= 1 && ShiftCtrlOldGear <= RangeSize)
            {
                ShiftCtrlOldRange = 0;
            }
            else if (ShiftCtrlOldGear >= RangeSize + 1 && ShiftCtrlOldGear <= 2 * RangeSize)
            {
                ShiftCtrlOldRange = 1;
            }
            else if (ShiftCtrlOldGear >= 2 * RangeSize + 1 && ShiftCtrlOldGear <= 3 * RangeSize)
            {
                ShiftCtrlOldRange = 2;
            }
            ShiftCtrlOldGear -= ShiftCtrlOldRange * RangeSize;

            // Determine new range
            if (toGear == -1)
            {
                ShiftCtrlNewGear  = -1;
                ShiftCtrlNewRange = 0;
            }
            else if (toGear == 0)
            {
                ShiftCtrlNewGear  = 0;
                ShiftCtrlNewRange = 0;
            }
            else if (toGear >= 1 && toGear <= RangeSize)
            {
                ShiftCtrlNewGear  = toGear;
                ShiftCtrlNewRange = 0;
            }
            else if (toGear >= RangeSize + 1 && toGear <= RangeSize * 2)
            {
                ShiftCtrlNewGear  = toGear - RangeSize;
                ShiftCtrlNewRange = 1;
            }
            else if (toGear >= RangeSize * 2 + 1 && toGear <= RangeSize * 3)
            {
                ShiftCtrlNewGear  = toGear - RangeSize * 2;
                ShiftCtrlNewRange = 2;
            }

            ShiftFrame      = 0;
            IsShifting      = true;
            powerShiftStage = 0;
        }
コード例 #10
0
        public void TickTelemetry(IDataMiner data)
        {
            bool copyTargetThr = false;

            /** VARIABLE SPEED CONTROL **/
            var actualSpeed = data.Telemetry.Speed * 3.6;

            double thrP, thrI;

            if (data.Telemetry.Gear == -1)
            {
                SetSpeed     = Main.GetAxisIn(JoyControls.VstLever) * 50;
                actualSpeed *= -1;

                thrP = 0.1;
                thrI = 0;
            }
            else
            {
                SetSpeed = Main.GetAxisIn(JoyControls.VstLever) * ((fast) ? 200 : 100);

                thrP = 0.015 + 0.15 * actualSpeed / 120;
                thrI = 0.02 - 0.015 * actualSpeed / 120;
                if (Efficiency)
                {
                    thrP *= 0.5;
                    thrI  = 0.00025;
                }
                if (Efficiency != wasEfficiency)
                {
                    copyTargetThr  = true;
                    staticThrError = variableThrottle - 2 * thrP * lastSpeedError;
                }
                wasEfficiency = Efficiency;
            }
            var speedErrorThr = SetSpeed - actualSpeed;

            staticThrError += speedErrorThr * thrI;
            if (staticThrError > 0.8)
            {
                staticThrError = 0.8;
            }
            if (staticThrError < -0.8)
            {
                staticThrError = -0.8;
            }
            lastSpeedError = speedErrorThr;
            var oldThr = variableThrottle;

            if (copyTargetThr)
            {
                variableThrottle  = thrP * speedErrorThr;
                variableThrottle *= UserThrottle;

                // Theoratical value required to copy last throttle
                staticThrError = (1 - variableThrottle) / UserThrottle;

                //Deduce at low speeds
                var deductor = actualSpeed / 50;
                if (deductor > 1)
                {
                    deductor = 1;
                }
                if (deductor < 0.01)
                {
                    deductor = 0.01;
                }
                staticThrError *= deductor;

                // Add it.
                variableThrottle += staticThrError;
            }
            else
            {
                variableThrottle  = thrP * speedErrorThr + staticThrError;
                variableThrottle *= UserThrottle;
            }
            if (variableThrottle > 1)
            {
                variableThrottle = 1;
            }
            if (variableThrottle < 0)
            {
                variableThrottle = 0;
            }

            var speedErrorBr = (actualSpeed - 3) - SetSpeed;

            if (speedErrorBr < 0)
            {
                speedErrorBr = 0;
            }
            if (actualSpeed < 50)
            {
                speedErrorBr *= (50 - actualSpeed) / 15 + 1;
            }
            variableBrake = 0.01 * speedErrorBr * speedErrorBr;
            if (variableBrake > 0.2)
            {
                variableBrake = 0.2;
            }
            if (variableBrake < 0)
            {
                variableBrake = 0;
            }

            if (variableBrake > 0.01)
            {
                variableThrottle = 0;
            }
            /** TRANSMISSION **/
            if (Main.Data.Active.Application == "eurotrucks2")
            {
                var ets2 = (Ets2DataMiner)Main.Data.Active;
                if (ets2.MyTelemetry.Job.TrailerAttached == false && !fast)
                {
                    Efficiency = true;
                }
                else
                {
                    if (Efficiency)
                    {
                        if ((SetSpeed - actualSpeed) > 5)
                        {
                            Efficiency = false;
                        }
                    }
                    else
                    {
                        if ((SetSpeed - actualSpeed) < 2)
                        {
                            Efficiency = true;
                        }
                    }
                }
            }
            //Efficiency = (SetSpeed - actualSpeed) < 5;
            if (DateTime.Now.Subtract(lastShifterTick).TotalMilliseconds > 40)
            {
                Active          = ShiftingPhase == ShiftPhase.None ? false : true;
                lastShifterTick = DateTime.Now;
                switch (ShiftingPhase)
                {
                case ShiftPhase.WaitButton:
                    if (Main.GetButtonIn(JoyControls.GearUp) == false && Main.GetButtonIn(JoyControls.GearDown) == false)
                    {
                        ShiftingPhase = ShiftPhase.None;
                    }
                    break;

                case ShiftPhase.None:

                    // Reverse pressed?
                    if (Main.GetButtonIn(JoyControls.VstChange))
                    {
                        fast          = !fast;
                        ShiftingPhase = ShiftPhase.WaitButton;
                    }
                    if (Main.GetButtonIn(JoyControls.GearDown))
                    {
                        Reverse       = !Reverse;
                        ShiftingPhase = ShiftPhase.WaitButton;
                    }

                    if (Reverse)
                    {
                        if (data.Telemetry.Gear != -1)
                        {
                            Gear          = -1;
                            ShiftingPhase = ShiftPhase.OffThrottle;
                        }
                    }
                    else
                    {
                        // Do nothing
                        if (data.Telemetry.Gear != Gear || Gear == 0)
                        {
                            if (Gear == 0)
                            {
                                Gear++;
                            }
                            if (Gear == -1)
                            {
                                Gear = 1;
                            }
                            ShiftingPhase = ShiftPhase.OffThrottle;
                        }
                        else
                        {
                            var curPower = Main.Drivetrain.CalculatePower(data.Telemetry.EngineRpm, data.Telemetry.Throttle);
                            if (curPower < 1)
                            {
                                curPower = 1;
                            }
                            var curEfficiency = Main.Drivetrain.CalculateFuelConsumption(data.Telemetry.EngineRpm, data.Telemetry.Throttle) / curPower;
                            var reqPower      = curPower * (variableThrottle - 0.5) * 2;
                            if (reqPower < 25)
                            {
                                reqPower = 25;
                            }
                            if (reqPower > 0.5 * Main.Drivetrain.CalculateMaxPower())
                            {
                                reqPower = 0.5 * Main.Drivetrain.CalculateMaxPower();
                            }
                            reqpower = reqPower;
                            int maxgears           = Main.Drivetrain.Gears;
                            var calcEfficiency     = Efficiency ? double.MaxValue : 0;
                            var calcEfficiencyGear = -1;
                            var calcThrottle       = variableThrottle;
                            var calcPower          = curPower;

                            var allStalled = true;
                            for (int k = 0; k < maxgears; k++)
                            {
                                if (maxgears >= 12 && (k == 5))
                                {
                                    continue;
                                }
                                if (maxgears >= 10 && (k == 1 || k == 3))
                                {
                                    continue;
                                }
                                if (!Efficiency && k < 3)
                                {
                                    continue;
                                }

                                // Always pick best efficient gear with power requirement met
                                var rpm            = Main.Drivetrain.CalculateRpmForSpeed(k, data.Telemetry.Speed);
                                var orpm           = Main.Drivetrain.CalculateRpmForSpeed(k, data.Telemetry.Speed);
                                var estimatedPower = Main.Drivetrain.CalculatePower(rpm, variableThrottle);

                                // RPM increase linear to throttle:
                                rpm += estimatedPower / 1200 * 190 * variableThrottle;

                                if (rpm < Main.Drivetrain.StallRpm && k > 0)
                                {
                                    continue;
                                }
                                allStalled = false;
                                if (orpm > Main.Drivetrain.MaximumRpm)
                                {
                                    continue;
                                }

                                var thr = Main.Drivetrain.CalculateThrottleByPower(rpm, reqPower);
                                if (thr > 1)
                                {
                                    thr = 1;
                                }
                                if (thr < 0)
                                {
                                    thr = 0;
                                }
                                var eff = Main.Drivetrain.CalculateFuelConsumption(rpm, thr) / reqPower;
                                var pwr = Main.Drivetrain.CalculatePower(rpm, variableThrottle);

                                if (Efficiency)
                                {
                                    if (calcEfficiency > eff && eff * 1.1 < curEfficiency)
                                    {
                                        calcEfficiency     = eff;
                                        calcEfficiencyGear = k;
                                        calcThrottle       = thr;
                                        calcPower          = pwr;
                                    }
                                }
                                else
                                {
                                    if (pwr > calcEfficiency)
                                    {
                                        calcEfficiency     = pwr;
                                        calcEfficiencyGear = k;
                                        calcPower          = pwr;
                                    }
                                }
                            }

                            if (allStalled)
                            {
                                if (maxgears >= 10)
                                {
                                    Gear = 3;
                                }
                                else
                                {
                                    Gear = 1;
                                }
                            }
                            else if (calcEfficiencyGear >= 0 && calcEfficiencyGear + 1 != Gear)
                            {
                                // Hysterisis
                                if (Math.Abs(curPower - calcPower) > 25)
                                {
                                    Gear = calcEfficiencyGear + 1;
                                }
                            }
                            if (Efficiency)
                            {
                                //variableThrottle = Main.Drivetrain.CalculateThrottleByPower(
                                //    data.Telemetry.EngineRpm,
                                //    reqPower);
                            }
                            else
                            {
                                //
                            }
                            if (Gear > 0 && Gear != data.Telemetry.Gear)
                            {
                                ShiftingPhase = ShiftPhase.OffThrottle;
                            }
                        }
                    }
                    break;

                case ShiftPhase.OffThrottle:
                    ShiftingPhase++;
                    break;

                case ShiftPhase.OnClutch:
                    ShiftingPhase++;
                    break;

                case ShiftPhase.EngageRange:
                    ShiftingPhase++;
                    break;

                case ShiftPhase.EngageGear:
                    ShiftingPhase++;
                    break;

                case ShiftPhase.Evaluate:
                    if (Gear == data.Telemetry.Gear)
                    {
                        LastSeenRange = DeductRangeFromGear(Gear);
                        ShiftingPhase++;
                    }
                    else
                    {
                        shiftingRetry++;
                        if (shiftingRetry > 50)
                        {
                            if (Gear > 0)
                            {
                                Gear--;
                            }
                            else
                            {
                                Gear = -1;
                            }
                            shiftingRetry = 0;
                            ShiftingPhase = ShiftPhase.EngageGear;
                        }
                        else if (shiftingRetry > 2)
                        {
                            LastSeenRange++;
                            LastSeenRange = LastSeenRange % 4;
                            ShiftingPhase = ShiftPhase.OnClutch;
                        }
                        else
                        {
                            ShiftingPhase = ShiftPhase.EngageGear;
                        }
                    }
                    break;

                case ShiftPhase.OffClutch:
                    ShiftingPhase++;
                    break;

                case ShiftPhase.OnThrottle:
                    shiftingRetry = 0;
                    ShiftingPhase = ShiftPhase.Cooldown;
                    break;

                case ShiftPhase.Cooldown:
                    shiftingRetry++;
                    if (shiftingRetry > 4)
                    {
                        shiftingRetry = 0;
                        ShiftingPhase = ShiftPhase.None;
                    }
                    break;
                }
            }
        }