diff --git a/Source/ORTS.Common/Input/UserCommand.cs b/Source/ORTS.Common/Input/UserCommand.cs index b5e7fd587e..3aba61f06b 100644 --- a/Source/ORTS.Common/Input/UserCommand.cs +++ b/Source/ORTS.Common/Input/UserCommand.cs @@ -203,5 +203,37 @@ public enum UserCommand [GetString("Control AI Fire Reset")] ControlAIFireReset, [GetString("Control Battery")] ControlBattery, [GetString("Control PowerKey")] ControlPowerKey, + [GetString("Control Speed Regulator Mode Increase")] ControlSpeedRegulatorModeIncrease, + [GetString("Control Speed Regulator Mode Descrease")] ControlSpeedRegulatorModeDecrease, + [GetString("Control Selected Speed Increase")] ControlSpeedRegulatorSelectedSpeedIncrease, + [GetString("Control Selected Speed Decrease")] ControlSpeedRegulatorSelectedSpeedDecrease, + [GetString("Control Speed Regulator Max Acceleration Increase")] ControlSpeedRegulatorMaxAccelerationIncrease, + [GetString("Control Speed Regulator Max Acceleration Decrease")] ControlSpeedRegulatorMaxAccelerationDecrease, + [GetString("Control Number Of Axles Increase")] ControlNumberOfAxlesIncrease, + [GetString("Control Number Of Axles Decrease")] ControlNumberOfAxlesDecrease, + [GetString("Control Restricted Speed Zone Active")] ControlRestrictedSpeedZoneActive, + [GetString("Control Cruise Control Mode Increase")] ControlCruiseControlModeIncrease, + [GetString("Control Cruise Control Mode Decrease")] ControlCruiseControlModeDecrease, + [GetString("Control Train Type Change (Passenger/Cargo)")] ControlTrainTypePaxCargo, + [GetString("Control Select Speed 10 kph/mph")] ControlSelectSpeed10, + [GetString("Control Select Speed 20 kph/mph")] ControlSelectSpeed20, + [GetString("Control Select Speed 30 kph/mph")] ControlSelectSpeed30, + [GetString("Control Select Speed 40 kph/mph")] ControlSelectSpeed40, + [GetString("Control Select Speed 50 kph/mph")] ControlSelectSpeed50, + [GetString("Control Select Speed 60 kph/mph")] ControlSelectSpeed60, + [GetString("Control Select Speed 70 kph/mph")] ControlSelectSpeed70, + [GetString("Control Select Speed 80 kph/mph")] ControlSelectSpeed80, + [GetString("Control Select Speed 90 kph/mph")] ControlSelectSpeed90, + [GetString("Control Select Speed 100 kph/mph")] ControlSelectSpeed100, + [GetString("Control Select Speed 110 kph/mph")] ControlSelectSpeed110, + [GetString("Control Select Speed 120 kph/mph")] ControlSelectSpeed120, + [GetString("Control Select Speed 130 kph/mph")] ControlSelectSpeed130, + [GetString("Control Select Speed 140 kph/mph")] ControlSelectSpeed140, + [GetString("Control Select Speed 150 kph/mph")] ControlSelectSpeed150, + [GetString("Control Select Speed 160 kph/mph")] ControlSelectSpeed160, + [GetString("Control Select Speed 170 kph/mph")] ControlSelectSpeed170, + [GetString("Control Select Speed 180 kph/mph")] ControlSelectSpeed180, + [GetString("Control Select Speed 190 kph/mph")] ControlSelectSpeed190, + [GetString("Control Select Speed 200 kph/mph")] ControlSelectSpeed200, } } diff --git a/Source/ORTS.Settings/InputSettings.cs b/Source/ORTS.Settings/InputSettings.cs index dac8536ae2..3564274c63 100644 --- a/Source/ORTS.Settings/InputSettings.cs +++ b/Source/ORTS.Settings/InputSettings.cs @@ -97,7 +97,7 @@ UserCommand[] GetCommands() public override object GetDefaultValue(string name) { - return DefaultCommands[(int)GetCommand(name)].PersistentDescriptor; + return DefaultCommands[(int)GetCommand(name)].PersistentDescriptor; } protected override object GetValue(string name) @@ -434,6 +434,42 @@ static void InitializeCommands(UserCommandInput[] Commands) Commands[(int)UserCommand.ControlWaterScoop] = new UserCommandKeyInput(0x15); Commands[(int)UserCommand.ControlWiper] = new UserCommandKeyInput(0x2F); + // Jindrich + Commands[(int)UserCommand.ControlSpeedRegulatorModeIncrease] = new UserCommandKeyInput(0x11, KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSpeedRegulatorModeDecrease] = new UserCommandKeyInput(0x1F, KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSpeedRegulatorMaxAccelerationIncrease] = new UserCommandKeyInput(0x20, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSpeedRegulatorMaxAccelerationDecrease] = new UserCommandKeyInput(0x1E, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSpeedRegulatorSelectedSpeedIncrease] = new UserCommandKeyInput(0x20, KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSpeedRegulatorSelectedSpeedDecrease] = new UserCommandKeyInput(0x1E, KeyModifiers.Shift); + Commands[(int)UserCommand.ControlNumberOfAxlesIncrease] = new UserCommandKeyInput(0x48, KeyModifiers.Shift); + Commands[(int)UserCommand.ControlNumberOfAxlesDecrease] = new UserCommandKeyInput(0x50, KeyModifiers.Shift); + Commands[(int)UserCommand.ControlRestrictedSpeedZoneActive] = new UserCommandKeyInput(0x13, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlCruiseControlModeDecrease] = new UserCommandKeyInput(0x1E, KeyModifiers.Control); + Commands[(int)UserCommand.ControlCruiseControlModeIncrease] = new UserCommandKeyInput(0x20, KeyModifiers.Control); + Commands[(int)UserCommand.ControlTrainTypePaxCargo] = new UserCommandKeyInput(0x31, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed10] = new UserCommandKeyInput(0x3B, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed20] = new UserCommandKeyInput(0x3C, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed30] = new UserCommandKeyInput(0x3D, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed40] = new UserCommandKeyInput(0x3E, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed50] = new UserCommandKeyInput(0x3F, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed60] = new UserCommandKeyInput(0x40, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed70] = new UserCommandKeyInput(0x41, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed80] = new UserCommandKeyInput(0x42, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed90] = new UserCommandKeyInput(0x43, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed100] = new UserCommandKeyInput(0x44, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed110] = new UserCommandKeyInput(0x57, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed120] = new UserCommandKeyInput(0x58, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed110] = new UserCommandKeyInput(0x02, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed120] = new UserCommandKeyInput(0x03, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed130] = new UserCommandKeyInput(0x04, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed140] = new UserCommandKeyInput(0x05, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed150] = new UserCommandKeyInput(0x06, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed160] = new UserCommandKeyInput(0x07, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed170] = new UserCommandKeyInput(0x08, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed180] = new UserCommandKeyInput(0x09, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed190] = new UserCommandKeyInput(0x0A, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.ControlSelectSpeed200] = new UserCommandKeyInput(0x0B, KeyModifiers.Control | KeyModifiers.Shift); + Commands[(int)UserCommand.DebugClockBackwards] = new UserCommandKeyInput(0x0C); Commands[(int)UserCommand.DebugClockForwards] = new UserCommandKeyInput(0x0D); Commands[(int)UserCommand.DebugDumpKeymap] = new UserCommandKeyInput(0x3B, KeyModifiers.Alt); diff --git a/Source/Orts.Formats.Msts/CabViewFile.cs b/Source/Orts.Formats.Msts/CabViewFile.cs index 7896d80d52..53c93a1ade 100644 --- a/Source/Orts.Formats.Msts/CabViewFile.cs +++ b/Source/Orts.Formats.Msts/CabViewFile.cs @@ -235,6 +235,30 @@ public enum CABViewControlTypes ORTS_TCS47, ORTS_TCS48, ORTS_ETCS, + ORTS_SELECTED_SPEED, + ORTS_SELECTED_SPEED_DISPLAY, + ORTS_SELECTED_SPEED_MODE, + ORTS_SELECTED_SPEED_REGULATOR_MODE, + ORTS_SELECTED_SPEED_MAXIMUM_ACCELERATION, + ORTS_RESTRICTED_SPEED_ZONE_ACTIVE, + ORTS_NUMBER_OF_AXES_DISPLAY_UNITS, + ORTS_NUMBER_OF_AXES_DISPLAY_TENS, + ORTS_NUMBER_OF_AXES_DISPLAY_HUNDREDS, + ORTS_TRAIN_LENGTH_METERS, + ORTS_REMAINING_TRAIN_LENGHT_SPEED_RESTRICTED, + ORTS_REMAINING_TRAIN_LENGTH_PERCENT, + ORTS_MOTIVE_FORCE, + ORTS_MOTIVE_FORCE_KILONEWTON, + ORTS_MAXIMUM_FORCE, + ORTS_FORCE_IN_PERCENT_THROTTLE_AND_DYNAMIC_BRAKE, + ORTS_TRAIN_TYPE_PAX_OR_CARGO, + ORTS_CONTROLLER_VOLTAGE, + ORTS_AMPERS_BY_CONTROLLER_VOLTAGE, + ORTS_ODOMETER, + ORTS_CC_SELECT_SPEED, + ORTS_NUMBER_OF_AXES_INCREASE, + ORTS_NUMBER_OF_AXES_DECREASE, + // Further CabViewControlTypes must be added above this line, to avoid their malfunction in 3DCabs EXTERNALWIPERS, @@ -292,7 +316,9 @@ public enum CABViewControlUnits INCHES_OF_MERCURY, MILI_AMPS, RPM, - LBS + LBS, + + KILOMETRES } public class CabViewControls : List diff --git a/Source/Orts.Simulation/Common/Events.cs b/Source/Orts.Simulation/Common/Events.cs index 7ca37a040c..f681b89f0a 100644 --- a/Source/Orts.Simulation/Common/Events.cs +++ b/Source/Orts.Simulation/Common/Events.cs @@ -207,6 +207,12 @@ public enum Event GearPosition7, GearPosition8, + // Jindrich + CruiseControlSpeedRegulator, + CruiseControlSpeedSelector, + CruiseControlMaxForce, + Alert, + Alert1, } @@ -429,6 +435,13 @@ public static Event From(bool mstsBinEnabled, Source source, int eventID) case 207: return Event.GearPosition7; case 208: return Event.GearPosition8; + // Jindrich + case 300: return Event.CruiseControlSpeedRegulator; + case 301: return Event.CruiseControlSpeedSelector; + case 302: return Event.CruiseControlMaxForce; + case 303: return Event.Alert; + case 304: return Event.Alert1; + default: return 0; } case Source.MSTSCrossing: diff --git a/Source/Orts.Simulation/Orts.Simulation.csproj b/Source/Orts.Simulation/Orts.Simulation.csproj index c3349f8242..772838dd74 100644 --- a/Source/Orts.Simulation/Orts.Simulation.csproj +++ b/Source/Orts.Simulation/Orts.Simulation.csproj @@ -117,6 +117,8 @@ + + diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs index 7b76a1a0d3..19099935bf 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs @@ -330,7 +330,7 @@ public float OdometerM protected bool DynamicBrakeBlended; // dynamic brake blending is currently active protected bool DynamicBrakeBlendingEnabled; // dynamic brake blending is configured - protected bool DynamicBrakeAvailable; // dynamic brake is available + public bool DynamicBrakeAvailable; // dynamic brake is available AirSinglePipe airPipeSystem; public double DynamicBrakeCommandStartTime; protected bool DynamicBrakeBlendingOverride; // true when DB lever >0% should always override the blending. When false, the bigger command is applied. @@ -404,6 +404,14 @@ public float OdometerM public float PowerReduction = 0; + // Jindrich + public CruiseControl CruiseControl; + public MultiPositionController MultiPositionController; + public bool SelectingSpeedPressed = false; + public bool EngineBrakePriority = false; + public bool IsAPartOfPlayerTrain = false; + public float ThrottleOverriden = 0; + public MSTSLocomotive(Simulator simulator, string wagPath) : base(simulator, wagPath) { @@ -824,7 +832,7 @@ public override void Parse(string lowercasetoken, STFReader stf) case "engine(ortsbrakepipechargingrate": BrakePipeChargingRatePSIorInHgpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null); break; case "engine(ortsbrakepipequickchargingrate": BrakePipeQuickChargingRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null); break; case "engine(ortsbrakepipedischargetimemult": BrakePipeDischargeTimeFactor = stf.ReadFloatBlock(STFReader.UNITS.None, null); break; - case "engine(ortsmaxtractiveforcecurves": TractiveForceCurves = new InterpolatorDiesel2D(stf, false); TractiveForceCurves.HasNegativeValue(); break; + case "engine(ortsmaxtractiveforcecurves": TractiveForceCurves = new InterpolatorDiesel2D(stf, false); TractiveForceCurves.HasNegativeValue(); break; case "engine(ortstractioncharacteristics": TractiveForceCurves = new InterpolatorDiesel2D(stf, true); break; case "engine(ortsdynamicbrakeforcecurves": DynamicBrakeForceCurves = new InterpolatorDiesel2D(stf, false); break; case "engine(ortscontinuousforcetimefactor": ContinuousForceTimeFactor = stf.ReadFloatBlock(STFReader.UNITS.None, null); break; @@ -866,7 +874,7 @@ public override void Parse(string lowercasetoken, STFReader stf) { switch (brakesenginecontrollers) { - case "blended": + case "blended": DynamicBrakeBlendingEnabled = true; break; case "dynamic": @@ -883,13 +891,13 @@ public override void Parse(string lowercasetoken, STFReader stf) foreach (var brakestrainbraketype in stf.ReadStringBlock("").ToLower().Replace(" ", "").Split(',')) { switch (brakestrainbraketype) - { - case "vacuum_single_pipe_eq": - VacuumBrakeEQFitted = true; - break; - default: - break; - } + { + case "vacuum_single_pipe_eq": + VacuumBrakeEQFitted = true; + break; + default: + break; + } } break; @@ -922,8 +930,9 @@ public override void Parse(string lowercasetoken, STFReader stf) case "engine(ortsmaxtracksanderboxcapacity": MaxTrackSandBoxCapacityM3 = stf.ReadFloatBlock(STFReader.UNITS.Volume, null); break; case "engine(ortsmaxtracksandersandconsumption": TrackSanderSandConsumptionM3pS = stf.ReadFloatBlock(STFReader.UNITS.Volume, null); break; case "engine(ortsmaxtracksanderairconsumption": TrackSanderAirComsumptionM3pS = stf.ReadFloatBlock(STFReader.UNITS.Volume, null); break; - default: base.Parse(lowercasetoken, stf); break; - + case "engine(ortscruisecontrol": SetUpCruiseControl(); break; + case "engine(multipositioncontroller": SetUpMPC(); break; + default: base.Parse(lowercasetoken, stf); if (CruiseControl != null) CruiseControl.Parse(lowercasetoken, stf); break; } } @@ -1024,6 +1033,8 @@ public override void Copy(MSTSWagon copy) WaterScoopDepthM = locoCopy.WaterScoopDepthM; WaterScoopWidthM = locoCopy.WaterScoopWidthM; MoveParamsToAxle(); + if (locoCopy.CruiseControl != null) + CruiseControl = locoCopy.CruiseControl; } @@ -1081,11 +1092,12 @@ public override void Save(BinaryWriter outf) outf.Write(ScoopIsBroken); outf.Write(IsWaterScoopDown); outf.Write(CurrentTrackSandBoxCapacityM3); - base.Save(outf); TrainControlSystem.Save(outf); LocomotiveAxle.Save(outf); + if (CruiseControl != null) + CruiseControl.Save(outf); } /// @@ -1132,6 +1144,8 @@ public override void Restore(BinaryReader inf) TrainControlSystem.Restore(inf); LocomotiveAxle = new Axle(inf); + if (CruiseControl != null) + CruiseControl.Restore(inf); } public bool IsLeadLocomotive() @@ -1429,6 +1443,24 @@ public override void Initialize() DrvWheelWeightKg = InitialDrvWheelWeightKg; } + /// + /// Make instance of Cruise Control and Initialize it + /// + public void SetUpCruiseControl() + { + CruiseControl = new CruiseControl(this); + CruiseControl.Initialize(); + CruiseControl.Equipped = true; + } + + /// + /// Make instance of multi position controller + /// + public void SetUpMPC() + { + MultiPositionController = new MultiPositionController(this); + } + //================================================================================================// /// /// Set starting conditions when initial speed > 0 @@ -1579,8 +1611,17 @@ public override void Update(float elapsedClockSeconds) if (!AdvancedAdhesionModel) // Advanced adhesion model turned off. AbsWheelSpeedMpS = AbsSpeedMpS; - - UpdateMotiveForce(elapsedClockSeconds, t, AbsSpeedMpS, AbsWheelSpeedMpS); + // Jindrich + //UpdateMotiveForce(elapsedClockSeconds, t, AbsSpeedMpS, AbsWheelSpeedMpS); + if (CruiseControl != null) + { + if (!IsPlayerTrain || CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Manual || CruiseControl.UseThrottle) + UpdateMotiveForce(elapsedClockSeconds, t, AbsSpeedMpS, AbsWheelSpeedMpS); + else if (IsPlayerTrain || CruiseControl.SpeedRegulatorOptions.Contains("engageforceonnonzerospeed")) + CruiseControl.Update(elapsedClockSeconds, AbsWheelSpeedMpS); + } + else + UpdateMotiveForce(elapsedClockSeconds, t, AbsSpeedMpS, AbsWheelSpeedMpS); ApplyDirectionToMotiveForce(); @@ -2853,6 +2894,22 @@ public void StartThrottleIncrease(float? target) public void StartThrottleIncrease() { + if (CruiseControl != null) + { + if (CruiseControl.UseThrottleAsForceSelector && CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SpeedRegulatorMaxForceStartIncrease(); + return; + } + else + { + if (CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SpeedSelectorModeStartIncrease(); + return; + } + } + } if (DynamicBrakeController != null && DynamicBrakeController.CurrentValue >= 0 && (DynamicBrakePercent >= 0 || !(DynamicBrakePercent == -1 && !DynamicBrake || DynamicBrakePercent >= 0 && DynamicBrake))) { if (!(CombinedControlType == CombinedControl.ThrottleDynamic @@ -2873,6 +2930,22 @@ public void StartThrottleIncrease() public void StopThrottleIncrease() { + if (CruiseControl != null) + { + if (CruiseControl.UseThrottleAsForceSelector && CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SpeedRegulatorMaxForceStopIncrease(); + return; + } + else + { + if (CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SpeedSelectorModeStopIncrease(); + return; + } + } + } AlerterReset(TCSEvent.ThrottleChanged); ThrottleController.StopIncrease(); @@ -2897,8 +2970,29 @@ public void StartThrottleDecrease(float? target) CommandStartTime = Simulator.ClockTime; } + protected bool speedSelectorModeDecreasing = false; public void StartThrottleDecrease() { + if (CruiseControl != null) + { + if (CruiseControl.UseThrottleAsForceSelector && CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SpeedRegulatorMaxForceStartDecrease(); + return; + } + else + { + if (CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + if (!speedSelectorModeDecreasing) + { + CruiseControl.SpeedSelectorModeDecrease(); + speedSelectorModeDecreasing = true; + } + return; + } + } + } if (CombinedControlType == CombinedControl.ThrottleDynamic && ThrottleController.CurrentValue <= 0) StartDynamicBrakeIncrease(null); else if (CombinedControlType == CombinedControl.ThrottleAir && ThrottleController.CurrentValue <= 0) @@ -2909,6 +3003,22 @@ public void StartThrottleDecrease() public void StopThrottleDecrease() { + if (CruiseControl != null) + { + if (CruiseControl.UseThrottleAsForceSelector && CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SpeedRegulatorMaxForceStopDecrease(); + return; + } + else + { + if (CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + speedSelectorModeDecreasing = false; + return; + } + } + } AlerterReset(TCSEvent.ThrottleChanged); ThrottleController.StopDecrease(); @@ -3050,6 +3160,14 @@ public void AdjustNotchedThrottle(bool increase) public void SetThrottleValue(float value) { + if (CruiseControl != null) + { + if (CruiseControl.UseThrottleAsForceSelector && CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SetMaxForcePercent((float)Math.Round(value * 100, 0)); + return; + } + } var controller = ThrottleController; var oldValue = controller.IntermediateValue; var change = controller.SetValue(value); @@ -3068,7 +3186,18 @@ public void SetThrottleValue(float value) public void SetThrottlePercent(float percent) { - ThrottleController.SetPercent(percent); + if (CruiseControl != null) + { + if (CruiseControl.UseThrottleAsForceSelector && CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + CruiseControl.SetMaxForcePercent(percent); + return; + } + else + ThrottleController.SetPercent(percent); + } + else + ThrottleController.SetPercent(percent); } public void SetThrottlePercentWithSound(float percent) @@ -3087,7 +3216,6 @@ public void ThrottleToZero() StartTrainBrakeIncrease(null); else StartThrottleToZero(0.0f); - } public void StartThrottleToZero(float? target) @@ -3374,6 +3502,7 @@ public void StartEngineBrakeIncrease(float? target) if (EngineBrakeController == null) return; + EngineBrakePriority = true; EngineBrakeController.StartIncrease(target); Simulator.Confirmer.Confirm(CabControl.EngineBrake, CabSetting.Increase, GetEngineBrakeStatus()); SignalEvent(Event.EngineBrakeChange); @@ -3601,6 +3730,11 @@ public override string GetBrakemanBrakeStatus() public void StartDynamicBrakeIncrease(float? target) { AlerterReset(TCSEvent.DynamicBrakeChanged); + if (CruiseControl != null) + { + SetThrottlePercent(0); + CruiseControl.DynamicBrakePriority = true; + } if (!CanUseDynamicBrake()) return; @@ -3659,6 +3793,11 @@ public void StopDynamicBrakeDecrease() { DynamicBrakeController.StopDecrease(); new DynamicBrakeCommand(Simulator.Log, false, DynamicBrakeController.CurrentValue, DynamicBrakeController.CommandStartTime); + if (CruiseControl != null) + { + if (DynamicBrakePercent < 1) + CruiseControl.DynamicBrakePriority = false; + } } } @@ -3929,6 +4068,13 @@ public void AlerterPressed(bool pressed) TrainControlSystem.AlerterPressed(pressed); } + public enum TrainType { Pax, Cargo }; + public TrainType SelectedTrainType = TrainType.Pax; + public void ChangeTrainTypePaxCargo() + { + SelectedTrainType = SelectedTrainType == TrainType.Pax ? SelectedTrainType = TrainType.Cargo : TrainType.Pax; + } + //put here because you can have diesel helpers and electric player locomotive public void ToggleHelpersEngine() { @@ -4092,9 +4238,10 @@ public override void SignalEvent(Event evt) } //used by remote train locomotives - /* public virtual void RemoteUpdate() - { - }*/ + /* public virtual void RemoteUpdate() + { + }*/ + private float previousSelectedSpeed = 0; public virtual float GetDataOf(CabViewControl cvc) { @@ -4467,6 +4614,8 @@ public virtual float GetDataOf(CabViewControl cvc) case CABViewControlTypes.THROTTLE_DISPLAY: case CABViewControlTypes.CPH_DISPLAY: { + if (CruiseControl != null) + if (CruiseControl.SkipThrottleDisplay) break; data = Train.TrainType == Train.TRAINTYPE.AI_PLAYERHOSTING? ThrottlePercent / 100f : LocalThrottlePercent / 100f; break; } @@ -4854,12 +5003,12 @@ public virtual float GetDataOf(CabViewControl cvc) case CABViewControlTypes.ORTS_TCS48: data = TrainControlSystem.CabDisplayControls[(int)cvc.ControlType - (int)CABViewControlTypes.ORTS_TCS1]; break; - default: - { + if (CruiseControl != null) + data = CruiseControl.GetDataOf(cvc); + else data = 0; - break; - } + break; } return data; } diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Controllers/MultiPositionController.cs b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Controllers/MultiPositionController.cs new file mode 100644 index 0000000000..e407d2313b --- /dev/null +++ b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Controllers/MultiPositionController.cs @@ -0,0 +1,828 @@ +// COPYRIGHT 2010 - 2021 by the Open Rails project. +// +// This file is part of Open Rails. +// +// Open Rails 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 of the License, or +// (at your option) any later version. +// +// Open Rails 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 Open Rails. If not, see . + +using System; +using System.Collections.Generic; +using System.IO; +using ORTS.Common; + +namespace Orts.Simulation.RollingStocks.SubSystems.Controllers +{ + public class MultiPositionController + { + public MultiPositionController(MSTSLocomotive locomotive) + { + Locomotive = locomotive; + Simulator = Locomotive.Simulator; + controllerPosition = ControllerPosition.Neutral; + } + MSTSLocomotive Locomotive; + Simulator Simulator; + + public Dictionary PositionsList = new Dictionary(); + + public bool Equipped = false; + public bool StateChanged = false; + + public ControllerPosition controllerPosition = new ControllerPosition(); + public ControllerCruiseControlLogic cruiseControlLogic = new ControllerCruiseControlLogic(); + protected float elapsedSecondsFromLastChange = 0; + protected bool checkNeutral = false; + protected bool noKeyPressed = true; + protected string currentPosition = ""; + protected bool emergencyBrake = false; + protected bool previousDriveModeWasAddPower = false; + protected bool isBraking = false; + protected bool needPowerUpAfterBrake = false; + public bool CanControlTrainBrake = false; + protected bool initialized = false; + protected bool movedForward = false; + protected bool movedAft = false; + + public void Save(BinaryWriter outf) + { + outf.Write(this.checkNeutral); + outf.Write((int)this.controllerPosition); + outf.Write(this.currentPosition); + outf.Write(this.elapsedSecondsFromLastChange); + outf.Write(this.emergencyBrake); + outf.Write(this.Equipped); + outf.Write(this.isBraking); + outf.Write(this.needPowerUpAfterBrake); + outf.Write(this.noKeyPressed); + outf.Write(this.previousDriveModeWasAddPower); + outf.Write(this.StateChanged); + } + + public void Restore(BinaryReader inf) + { + initialized = true; + checkNeutral = inf.ReadBoolean(); + int fControllerPosition = inf.ReadInt32(); + controllerPosition = (ControllerPosition)fControllerPosition; + currentPosition = inf.ReadString(); + elapsedSecondsFromLastChange = inf.ReadSingle(); + emergencyBrake = inf.ReadBoolean(); + Equipped = inf.ReadBoolean(); + isBraking = inf.ReadBoolean(); + needPowerUpAfterBrake = inf.ReadBoolean(); + noKeyPressed = inf.ReadBoolean(); + previousDriveModeWasAddPower = inf.ReadBoolean(); + StateChanged = inf.ReadBoolean(); + } + + public void Update(float elapsedClockSeconds) + { + if (!initialized) + { + foreach (KeyValuePair pair in PositionsList) + { + if (pair.Value.ToLower() == "default") + { + currentPosition = pair.Key; + break; + } + } + initialized = true; + } + if (!Locomotive.IsPlayerTrain) return; + + if (Locomotive.CruiseControl.DynamicBrakePriority) return; + ReloadPositions(); + if (!Locomotive.Battery) return; + if (Locomotive.AbsSpeedMpS > 0) + { + if (emergencyBrake) + { + Locomotive.TrainBrakeController.TCSEmergencyBraking = true; + return; + } + } + else + { + emergencyBrake = false; + } + if (Locomotive.TrainBrakeController.TCSEmergencyBraking) + Locomotive.TrainBrakeController.TCSEmergencyBraking = false; + elapsedSecondsFromLastChange += elapsedClockSeconds; + // Simulator.Confirmer.MSG(currentPosition.ToString()); + if (checkNeutral) + { + if (elapsedSecondsFromLastChange > 0.2f) + { + CheckNeutralPosition(); + checkNeutral = false; + } + } + if (!Locomotive.CruiseControl.Equipped || Locomotive.CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Manual) + { + if (controllerPosition == ControllerPosition.ThrottleIncrease) + { + if (Locomotive.DynamicBrakePercent < 1) + { + if (Locomotive.ThrottlePercent < 100) + { + float step = 100 / Locomotive.CruiseControl.ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent + step); + } + } + } + if (controllerPosition == ControllerPosition.ThrottleIncreaseFast) + { + if (Locomotive.DynamicBrakePercent < 1) + { + if (Locomotive.ThrottlePercent < 100) + { + float step = 100 / Locomotive.CruiseControl.ThrottleFullRangeIncreaseTimeSeconds * 2; + step *= elapsedClockSeconds; + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent + step); + } + } + } + if (controllerPosition == ControllerPosition.ThrottleDecrease) + { + if (Locomotive.ThrottlePercent > 0) + { + float step = 100 / Locomotive.CruiseControl.ThrottleFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent - step); + } + } + if (controllerPosition == ControllerPosition.ThrottleDecreaseFast) + { + if (Locomotive.ThrottlePercent > 0) + { + float step = 100 / Locomotive.CruiseControl.ThrottleFullRangeDecreaseTimeSeconds * 2; + step *= elapsedClockSeconds; + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent - step); + } + } + if (controllerPosition == ControllerPosition.Neutral || controllerPosition == ControllerPosition.DynamicBrakeHold) + { + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "apply") + { + Locomotive.StartTrainBrakeDecrease(null); + } + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "neutral") + { + Locomotive.StopTrainBrakeDecrease(); + } + } + if (Locomotive.ThrottlePercent < 2) + { + if (Locomotive.ThrottlePercent != 0) + Locomotive.SetThrottlePercent(0); + } + if (Locomotive.ThrottlePercent > 1) + { + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent - 1f); + } + if (Locomotive.ThrottlePercent > 100) + { + Locomotive.ThrottlePercent = 100; + } + + } + if (controllerPosition == ControllerPosition.DynamicBrakeIncrease) + { + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "apply") + { + Locomotive.StartTrainBrakeDecrease(null); + } + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "neutral") + { + Locomotive.StopTrainBrakeDecrease(); + } + } + if (Locomotive.DynamicBrakePercent == -1) Locomotive.SetDynamicBrakePercent(0); + if (Locomotive.ThrottlePercent < 1 && Locomotive.DynamicBrakePercent < 100) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent + 2f); + } + } + if (controllerPosition == ControllerPosition.DynamicBrakeIncreaseFast) + { + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "apply") + { + Locomotive.StartTrainBrakeDecrease(null); + } + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "neutral") + { + Locomotive.StopTrainBrakeDecrease(); + } + } + if (Locomotive.DynamicBrakePercent == -1) Locomotive.SetDynamicBrakePercent(0); + if (Locomotive.ThrottlePercent < 1 && Locomotive.DynamicBrakePercent < 100) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent + 2f); + } + } + if (controllerPosition == ControllerPosition.DynamicBrakeDecrease) + { + if (Locomotive.DynamicBrakePercent > 0) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent - 1); + } + } + if (controllerPosition == ControllerPosition.Drive || controllerPosition == ControllerPosition.ThrottleHold) + { + if (Locomotive.DynamicBrakePercent < 2) + { + Locomotive.SetDynamicBrakePercent(-1); + } + if (Locomotive.DynamicBrakePercent > 1) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent - 1); + } + } + if (controllerPosition == ControllerPosition.TrainBrakeIncrease) + { + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() != "apply") + { + String test = Locomotive.TrainBrakeController.GetStatus().ToLower(); + Locomotive.StartTrainBrakeIncrease(null); + } + else + { + Locomotive.StopTrainBrakeIncrease(); + } + } + } + else if (controllerPosition == ControllerPosition.Drive) + { + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() != "release") + { + String boom = Locomotive.TrainBrakeController.GetStatus().ToString(); + Locomotive.StartTrainBrakeDecrease(null); + } + else + Locomotive.StopTrainBrakeDecrease(); + } + } + if (controllerPosition == ControllerPosition.TrainBrakeDecrease) + { + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() != "release") + { + String boom = Locomotive.TrainBrakeController.GetStatus().ToString(); + Locomotive.StartTrainBrakeDecrease(null); + } + else + Locomotive.StopTrainBrakeDecrease(); + } + } + if (controllerPosition == ControllerPosition.EmergencyBrake) + { + EmergencyBrakes(); + emergencyBrake = true; + } + if (controllerPosition == ControllerPosition.ThrottleIncreaseOrDynamicBrakeDecrease) + { + if (Locomotive.DynamicBrakePercent > 0) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent - 0.2f); + if (Locomotive.DynamicBrakePercent < 2) + { + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + } + else + { + if (Locomotive.ThrottlePercent < 100) + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent + 0.2f); + if (Locomotive.ThrottlePercent > 100) + Locomotive.SetThrottlePercent(100); + } + } + if (controllerPosition == ControllerPosition.ThrottleIncreaseOrDynamicBrakeDecreaseFast) + { + if (Locomotive.DynamicBrakePercent > 0) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent - 1); + if (Locomotive.DynamicBrakePercent < 2) + { + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + } + else + { + if (Locomotive.ThrottlePercent < 100) + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent + 1); + if (Locomotive.ThrottlePercent > 100) + Locomotive.SetThrottlePercent(100); + } + } + + if (controllerPosition == ControllerPosition.DynamicBrakeIncreaseOrThrottleDecrease) + { + if (Locomotive.ThrottlePercent > 0) + { + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent - 0.2f); + if (Locomotive.ThrottlePercent < 0) + Locomotive.ThrottlePercent = 0; + } + else + { + if (Locomotive.DynamicBrakePercent < 100) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent + 0.2f); + } + if (Locomotive.DynamicBrakePercent > 100) + Locomotive.SetDynamicBrakePercent(100); + } + } + if (controllerPosition == ControllerPosition.DynamicBrakeIncreaseOrThrottleDecreaseFast) + { + if (Locomotive.ThrottlePercent > 0) + { + Locomotive.SetThrottlePercent(Locomotive.ThrottlePercent - 1); + if (Locomotive.ThrottlePercent < 0) + Locomotive.ThrottlePercent = 0; + } + else + { + if (Locomotive.DynamicBrakePercent < 100) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent + 1); + } + if (Locomotive.DynamicBrakePercent > 100) + Locomotive.SetDynamicBrakePercent(100); + } + } + } + else if (Locomotive.CruiseControl.Equipped && Locomotive.CruiseControl.SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + if (cruiseControlLogic == ControllerCruiseControlLogic.SpeedOnly) + { + if (controllerPosition == ControllerPosition.ThrottleIncrease || controllerPosition == ControllerPosition.ThrottleIncreaseFast) + { + if (!Locomotive.CruiseControl.ContinuousSpeedIncreasing && movedForward) return; + movedForward = true; + Locomotive.CruiseControl.SelectedSpeedMpS = Locomotive.CruiseControl.SelectedSpeedMpS + Locomotive.CruiseControl.SpeedRegulatorNominalSpeedStepMpS; + if (Locomotive.CruiseControl.SelectedSpeedMpS > Locomotive.MaxSpeedMpS) Locomotive.CruiseControl.SelectedSpeedMpS = Locomotive.MaxSpeedMpS; + } + if (controllerPosition == ControllerPosition.ThrottleDecrease || controllerPosition == ControllerPosition.ThrottleDecreaseFast) + { + if (!Locomotive.CruiseControl.ContinuousSpeedDecreasing && movedAft) return; + movedAft = true; + Locomotive.CruiseControl.SelectedSpeedMpS = Locomotive.CruiseControl.SelectedSpeedMpS - Locomotive.CruiseControl.SpeedRegulatorNominalSpeedStepMpS; + if (Locomotive.CruiseControl.SelectedSpeedMpS < 0) Locomotive.CruiseControl.SelectedSpeedMpS = 0; + } + return; + } + if (controllerPosition == ControllerPosition.ThrottleIncrease) + { + isBraking = false; + Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.Start; + previousDriveModeWasAddPower = true; + } + if (controllerPosition == ControllerPosition.Neutral) + { + Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.Neutral; + } + if (controllerPosition == ControllerPosition.Drive) + { + bool applyPower = true; + if (isBraking && needPowerUpAfterBrake) + { + if (Locomotive.DynamicBrakePercent < 2) + { + Locomotive.SetDynamicBrakePercent(-1); + } + if (Locomotive.DynamicBrakePercent > 1) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent - 1); + } + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() != "release") + { + Locomotive.StartTrainBrakeDecrease(null); + } + else + Locomotive.StopTrainBrakeDecrease(); + } + applyPower = false; + } + if (applyPower) Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.On; + } + if (controllerPosition == ControllerPosition.DynamicBrakeIncrease) + { + isBraking = true; + previousDriveModeWasAddPower = false; + Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.Neutral; + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "apply") + { + Locomotive.StartTrainBrakeDecrease(null); + } + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "neutral") + { + Locomotive.StopTrainBrakeDecrease(); + } + } + if (Locomotive.ThrottlePercent < 1 && Locomotive.DynamicBrakePercent < 100) + { + if (Locomotive.DynamicBrakePercent < 0) + Locomotive.DynamicBrakeChangeActiveState(true); + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent + 1f); + } + } + if (controllerPosition == ControllerPosition.DynamicBrakeIncreaseFast) + { + isBraking = true; + previousDriveModeWasAddPower = false; + Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.Neutral; + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "apply") + { + Locomotive.StartTrainBrakeDecrease(null); + } + if (Locomotive.TrainBrakeController.GetStatus().ToLower() == "neutral") + { + Locomotive.StopTrainBrakeDecrease(); + } + } + if (Locomotive.ThrottlePercent < 1 && Locomotive.DynamicBrakePercent < 100) + { + Locomotive.SetDynamicBrakePercent(Locomotive.DynamicBrakePercent + 2f); + } + } + if (controllerPosition == ControllerPosition.TrainBrakeIncrease) + { + isBraking = true; + previousDriveModeWasAddPower = false; + Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.Neutral; + if (CanControlTrainBrake) + { + if (Locomotive.TrainBrakeController.GetStatus().ToLower() != "apply") + { + String test = Locomotive.TrainBrakeController.GetStatus().ToLower(); + Locomotive.StartTrainBrakeIncrease(null); + } + else + { + Locomotive.StopTrainBrakeIncrease(); + } + } + } + if (controllerPosition == ControllerPosition.EmergencyBrake) + { + isBraking = true; + previousDriveModeWasAddPower = false; + Locomotive.CruiseControl.SpeedSelMode = CruiseControl.SpeedSelectorMode.Neutral; + EmergencyBrakes(); + emergencyBrake = true; + } + if (controllerPosition == ControllerPosition.CruiseControlSpeedIncrease) + { + Locomotive.CruiseControl.SelectedSpeedMpS = MpS.FromKpH((MpS.ToKpH(Locomotive.CruiseControl.SelectedSpeedMpS) + 1)); + } + if (controllerPosition == ControllerPosition.CruiseControlSpeedDecrease) + { + Locomotive.CruiseControl.SelectedSpeedMpS = MpS.FromKpH((MpS.ToKpH(Locomotive.CruiseControl.SelectedSpeedMpS) + 1)); + } + if (controllerPosition == ControllerPosition.CruiseControlSpeedSetZero) + { + Locomotive.CruiseControl.SelectedSpeedMpS = 0; + } + } + } + + private bool messageDisplayed = false; + public void DoMovement(Movement movement) + { + if (movement == Movement.Aft) movedForward = false; + if (movement == Movement.Forward) movedAft = false; + if (movement == Movement.Neutral) movedForward = movedAft = false; + messageDisplayed = false; + if (String.IsNullOrEmpty(currentPosition)) + { + foreach (KeyValuePair pair in PositionsList) + { + if (pair.Value.ToLower() == "default") + { + currentPosition = pair.Key; + break; + } + } + } + if (movement == Movement.Forward) + { + noKeyPressed = false; + checkNeutral = false; + bool isFirst = true; + string previous = ""; + foreach (KeyValuePair pair in PositionsList) + { + if (pair.Key == currentPosition) + { + if (isFirst) + break; + currentPosition = previous; + break; + } + isFirst = false; + previous = pair.Key; + } + } + if (movement == Movement.Aft) + { + noKeyPressed = false; + checkNeutral = false; + bool selectNext = false; + foreach (KeyValuePair pair in PositionsList) + { + if (selectNext) + { + currentPosition = pair.Key; + break; + } + if (pair.Key == currentPosition) selectNext = true; + } + } + if (movement == Movement.Neutral) + { + noKeyPressed = true; + foreach (KeyValuePair pair in PositionsList) + { + if (pair.Key == currentPosition) + { + if (pair.Value.ToLower() == "springloadedbackwards" || pair.Value.ToLower() == "springloadedforwards") + { + checkNeutral = true; + elapsedSecondsFromLastChange = 0; + } + if (pair.Value.ToLower() == "springloadedbackwardsimmediatelly" || pair.Value.ToLower() == "springloadedforwardsimmediatelly") + { + CheckNeutralPosition(); + ReloadPositions(); + } + } + } + } + + } + + protected void ReloadPositions() + { + if (noKeyPressed) + { + foreach (KeyValuePair pair in PositionsList) + { + if (pair.Key == currentPosition) + { + if (pair.Value.ToLower() == "cruisecontrol.needincreaseafteranybrake") + { + needPowerUpAfterBrake = true; + } + if (pair.Value.ToLower() == "springloadedforwards" || pair.Value.ToLower() == "springloadedbackwards") + { + if (elapsedSecondsFromLastChange > 0.2f) + { + elapsedSecondsFromLastChange = 0; + checkNeutral = true; + } + } + } + } + } + switch (currentPosition) + { + case "ThrottleIncrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: S"); + controllerPosition = ControllerPosition.ThrottleIncrease; + break; + } + case "ThrottleIncreaseFast": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: S"); + controllerPosition = ControllerPosition.ThrottleIncreaseFast; + break; + } + case "ThrottleIncreaseOrDynamicBrakeDecrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: +"); + controllerPosition = ControllerPosition.ThrottleIncreaseOrDynamicBrakeDecrease; + break; + } + case "ThrottleIncreaseOrDynamicBrakeDecreaseFast": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: ++"); + controllerPosition = ControllerPosition.ThrottleIncreaseOrDynamicBrakeDecreaseFast; + break; + } + case "DynamicBrakeIncreaseOrThrottleDecrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: -"); + controllerPosition = ControllerPosition.DynamicBrakeIncreaseOrThrottleDecrease; + break; + } + case "DynamicBrakeIncreaseOrThrottleDecreaseFast": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: --"); + controllerPosition = ControllerPosition.DynamicBrakeIncreaseOrThrottleDecreaseFast; + break; + } + case "ThrottleDecrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: V"); + controllerPosition = ControllerPosition.ThrottleDecrease; + break; + } + case "ThrottleDecreaseFast": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: V"); + controllerPosition = ControllerPosition.ThrottleDecreaseFast; + break; + } + case "Drive": + { + //Locomotive.TrainBrakePriority = false; + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: J"); + controllerPosition = ControllerPosition.Drive; + break; + } + case "ThrottleHold": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: J"); + controllerPosition = ControllerPosition.ThrottleHold; + break; + } + case "Neutral": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: V"); + controllerPosition = ControllerPosition.Neutral; + break; + } + case "KeepCurrent": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: 0"); + controllerPosition = ControllerPosition.KeepCurrent; + break; + } + case "DynamicBrakeHold": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: V"); + controllerPosition = ControllerPosition.DynamicBrakeHold; + break; + } + case "DynamicBrakeIncrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: BE"); + controllerPosition = ControllerPosition.DynamicBrakeIncrease; + break; + } + case "DynamicBrakeIncreaseFast": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: BE2"); + controllerPosition = ControllerPosition.DynamicBrakeIncreaseFast; + break; + } + case "DynamicBrakeDecrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: V"); + controllerPosition = ControllerPosition.DynamicBrakeDecrease; + break; + } + case "TrainBrakeIncrease": + { + //Locomotive.TrainBrakePriority = true; + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: BP"); + controllerPosition = ControllerPosition.TrainBrakeIncrease; + break; + } + case "TrainBrakeDecrease": + { + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: V"); + controllerPosition = ControllerPosition.TrainBrakeDecrease; + break; + } + case "EmergencyBrake": + { + //Locomotive.TrainBrakePriority = true; + if (!messageDisplayed) Simulator.Confirmer.Information("Controller: R"); + controllerPosition = ControllerPosition.EmergencyBrake; + break; + } + case "CruiseControlSpeedIncrease": + { + controllerPosition = ControllerPosition.CruiseControlSpeedIncrease; + break; + } + case "CruiseControlSpeedDecrease": + { + controllerPosition = ControllerPosition.CruiseControlSpeedIncrease; + break; + } + case "CruiseControlSpeedSetZero": + { + controllerPosition = ControllerPosition.CruiseControlSpeedSetZero; + break; + } + } + messageDisplayed = true; + } + + protected void CheckNeutralPosition() + { + bool setNext = false; + String previous = ""; + foreach (KeyValuePair pair in PositionsList) + { + if (setNext) + { + currentPosition = pair.Key; + break; + } + if (pair.Key == currentPosition) + { + if (pair.Value.ToLower() == "springloadedbackwards" || pair.Value.ToLower() == "springloadedbackwardsimmediatelly") + { + setNext = true; + } + if (pair.Value.ToLower() == "springloadedforwards" || pair.Value.ToLower() == "springloadedforwardsimmediatelly") + { + currentPosition = previous; + break; + } + } + previous = pair.Key; + } + } + + protected void EmergencyBrakes() + { + Locomotive.SetThrottlePercent(0); + Locomotive.SetDynamicBrakePercent(100); + Locomotive.TrainBrakeController.TCSEmergencyBraking = true; + } + public enum Movement + { + Forward, + Neutral, + Aft + }; + public enum ControllerPosition + { + Neutral, + Drive, + ThrottleIncrease, + ThrottleDecrease, + ThrottleIncreaseFast, + ThrottleDecreaseFast, + DynamicBrakeIncrease, DynamicBrakeDecrease, + DynamicBrakeIncreaseFast, + TrainBrakeIncrease, + TrainBrakeDecrease, + EmergencyBrake, + ThrottleHold, + DynamicBrakeHold, + ThrottleIncreaseOrDynamicBrakeDecreaseFast, + ThrottleIncreaseOrDynamicBrakeDecrease, + DynamicBrakeIncreaseOrThrottleDecreaseFast, + DynamicBrakeIncreaseOrThrottleDecrease, + KeepCurrent, + CruiseControlSpeedIncrease, + CruiseControlSpeedDecrease, + CruiseControlSpeedSetZero + }; + public enum ControllerCruiseControlLogic + { + None, + Full, + SpeedOnly + } + } +} \ No newline at end of file diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/CruiseControl.cs b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/CruiseControl.cs new file mode 100644 index 0000000000..8ebac7cd5c --- /dev/null +++ b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/CruiseControl.cs @@ -0,0 +1,1421 @@ +// COPYRIGHT 2013 - 2021 by the Open Rails project. +// +// This file is part of Open Rails. +// +// Open Rails 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 of the License, or +// (at your option) any later version. +// +// Open Rails 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 Open Rails. If not, see . + +using Orts.Formats.Msts; +using Orts.Parsers.Msts; +using ORTS.Common; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Orts.Simulation.RollingStocks.SubSystems +{ + public class CruiseControl + + { + public CruiseControl(MSTSLocomotive locomotive) + { + Locomotive = locomotive; + } + MSTSLocomotive Locomotive; + Simulator Simulator; + + public bool Equipped = false; + public bool SpeedIsMph = false; + public bool SpeedRegulatorMaxForcePercentUnits = false; + public float SpeedRegulatorMaxForceSteps = 0; + public bool MaxForceSetSingleStep = false; + public bool MaxForceKeepSelectedStepWhenManualModeSet = false; + public bool ForceRegulatorAutoWhenNonZeroSpeedSelected = false; + public List SpeedRegulatorOptions = new List(); + public SpeedRegulatorMode SpeedRegMode = SpeedRegulatorMode.Manual; + public SpeedSelectorMode SpeedSelMode = SpeedSelectorMode.Neutral; + public float SelectedMaxAccelerationPercent = 0; + public float SelectedMaxAccelerationStep = 0; + public float SelectedSpeedMpS = 0; + public int SelectedNumberOfAxles = 0; + public float SpeedRegulatorNominalSpeedStepMpS = 0; + public float MaxAccelerationMpSS = 0; + public float MaxDecelerationMpSS = 0; + public bool UseThrottle = false; + public bool AntiWheelSpinEquipped = false; + public float DynamicBrakeMaxForceAtSelectorStep = 0; + public float DynamicBrakeDescentCoefficient = 0; + public float DeltaCoefficient = 0; + public float ForceThrottleAndDynamicBrake = 0; + protected float maxForceN = 0; + protected float trainBrakePercent = 0; + protected float trainLength = 0; + public int TrainLengthMeters = 0; + public int RemainingTrainLengthToPassRestrictedZone = 0; + public bool RestrictedSpeedActive = false; + public float CurrentSelectedSpeedMpS = 0; + protected float nextSelectedSpeedMps = 0; + protected float restrictedRegionTravelledDistance = 0; + protected float currentThrottlePercent = 0; + protected double clockTime = 0; + protected bool dynamicBrakeSetToZero = false; + public float StartReducingSpeedDelta = 0.5f; + public float ThrottleIncreaseSpeed = 0.1f; + public float ThrottleDecreaseSpeed = 0.2f; + public bool Battery = false; + public bool DynamicBrakePriority = false; + public List ForceStepsThrottleTable = new List(); + public List AccelerationTable = new List(); + public enum SpeedRegulatorMode { Manual, Auto, Testing, AVV } + public enum SpeedSelectorMode { Parking, Neutral, On, Start } + protected float absMaxForceN = 0; + protected float brakePercent = 0; + public float DynamicBrakeIncreaseSpeed = 0; + public float DynamicBrakeDecreaseSpeed = 0; + public uint MinimumMetersToPass = 19; + protected float relativeAcceleration; + public float AccelerationRampMaxMpSSS = 0.7f; + public float AccelerationDemandMpSS; + public float AccelerationRampMinMpSSS = 0.01f; + public float ThrottleFullRangeIncreaseTimeSeconds = 0; + public float ThrottleFullRangeDecreaseTimeSeconds = 0; + public float DynamicBrakeFullRangeIncreaseTimeSeconds; + public float DynamicBrakeFullRangeDecreaseTimeSeconds; + public float ParkingBrakeEngageSpeed = 0; + public float ParkingBrakePercent = 0; + public bool SkipThrottleDisplay = false; + public bool DisableZeroForceStep = false; + public bool UseThrottleAsSpeedSelector = false; + public bool UseThrottleAsForceSelector = false; + public float Ampers = 0; + public bool ContinuousSpeedIncreasing = false; + public bool ContinuousSpeedDecreasing = false; + public float PowerBreakoutAmpers = 0; + public float PowerBreakoutSpeedDelta = 0; + public float PowerResumeSpeedDelta = 0; + public float PowerReductionDelayPaxTrain = 0; + public float PowerReductionDelayCargoTrain = 0; + public float PowerReductionValue = 100; + public float MaxPowerThreshold = 0; + public float SafeSpeedForAutomaticOperationMpS = 0; + protected float SpeedSelectorStepTimeSeconds = 0; + protected float elapsedTime = 0; + + public void Parse(string lowercasetoken, STFReader stf) + { + switch (lowercasetoken) + { + case "engine(ortscruisecontrol(speedismph": SpeedIsMph = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(usethrottle": UseThrottle = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(throttleincreasespeed": ThrottleIncreaseSpeed = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.1f); break; + case "engine(ortscruisecontrol(speedselectorsteptimeseconds": SpeedSelectorStepTimeSeconds = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.1f); break; + case "engine(ortscruisecontrol(throttledecreasespeed": ThrottleDecreaseSpeed = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.2f); break; + case "engine(ortscruisecontrol(throttlefullrangeincreasetimeseconds": ThrottleFullRangeIncreaseTimeSeconds = stf.ReadFloatBlock(STFReader.UNITS.Any, 5); break; + case "engine(ortscruisecontrol(throttlefullrangedecreasetimeseconds": ThrottleFullRangeDecreaseTimeSeconds = stf.ReadFloatBlock(STFReader.UNITS.Any, 5); break; + case "engine(ortscruisecontrol(dynamicbrakefullrangeincreasetimeseconds": DynamicBrakeFullRangeIncreaseTimeSeconds = stf.ReadFloatBlock(STFReader.UNITS.Any, 5); break; + case "engine(ortscruisecontrol(dynamicbrakefullrangedecreasetimeseconds": DynamicBrakeFullRangeDecreaseTimeSeconds = stf.ReadFloatBlock(STFReader.UNITS.Any, 5); break; + case "engine(ortscruisecontrol(parkingbrakeengagespeed": ParkingBrakeEngageSpeed = stf.ReadFloatBlock(STFReader.UNITS.Speed, 0); break; + case "engine(ortscruisecontrol(parkingbrakepercent": ParkingBrakePercent = stf.ReadFloatBlock(STFReader.UNITS.Any, 0); break; + case "engine(ortscruisecontrol(maxpowerthreshold": MaxPowerThreshold = stf.ReadFloatBlock(STFReader.UNITS.Any, 0); break; + case "engine(ortscruisecontrol(maxforcepercentunits": SpeedRegulatorMaxForcePercentUnits = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(maxforcesteps": SpeedRegulatorMaxForceSteps = stf.ReadIntBlock(0); break; + case "engine(ortscruisecontrol(maxforcesetsinglestep": MaxForceSetSingleStep = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(maxforcekeepselectedstepwhenmanualmodeset": MaxForceKeepSelectedStepWhenManualModeSet = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(forceregulatorautowhennonzerospeedselected": ForceRegulatorAutoWhenNonZeroSpeedSelected = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(forcestepsthrottletable": + foreach (var forceStepThrottleValue in stf.ReadStringBlock("").Replace(" ", "").Split(',')) + { + ForceStepsThrottleTable.Add(int.Parse(forceStepThrottleValue)); + } + break; + case "engine(ortscruisecontrol(accelerationtable": + foreach (var accelerationValue in stf.ReadStringBlock("").Replace(" ", "").Split(',')) + { + AccelerationTable.Add(float.Parse(accelerationValue)); + } + break; + case "engine(ortscruisecontrol(powerbreakoutampers": PowerBreakoutAmpers = stf.ReadFloatBlock(STFReader.UNITS.Any, 100.0f); break; + case "engine(ortscruisecontrol(powerbreakoutspeeddelta": PowerBreakoutSpeedDelta = stf.ReadFloatBlock(STFReader.UNITS.Any, 100.0f); break; + case "engine(ortscruisecontrol(powerresumespeeddelta": PowerResumeSpeedDelta = stf.ReadFloatBlock(STFReader.UNITS.Any, 100.0f); break; + case "engine(ortscruisecontrol(powerreductiondelaypaxtrain": PowerReductionDelayPaxTrain = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.0f); break; + case "engine(ortscruisecontrol(powerreductiondelaycargotrain": PowerReductionDelayCargoTrain = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.0f); break; + case "engine(ortscruisecontrol(powerreductionvalue": PowerReductionValue = stf.ReadFloatBlock(STFReader.UNITS.Any, 100.0f); break; + + case "engine(ortscruisecontrol(disablezeroforcestep": DisableZeroForceStep = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(defaultforcestep": SelectedMaxAccelerationStep = stf.ReadFloatBlock(STFReader.UNITS.Any, 1.0f); break; + case "engine(ortscruisecontrol(dynamicbrakemaxforceatselectorstep": DynamicBrakeMaxForceAtSelectorStep = stf.ReadFloatBlock(STFReader.UNITS.Any, 1.0f); break; + case "engine(ortscruisecontrol(startreducingspeeddelta": StartReducingSpeedDelta = stf.ReadFloatBlock(STFReader.UNITS.Any, 1.0f); break; + case "engine(ortscruisecontrol(dynamicbrakedescentcoefficient": DynamicBrakeDescentCoefficient = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.5f); break; + case "engine(ortscruisecontrol(climbdeltacoefficient": DeltaCoefficient = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.8f); break; + case "engine(ortscruisecontrol(maxacceleration": MaxAccelerationMpSS = stf.ReadFloatBlock(STFReader.UNITS.Any, 1); break; + case "engine(ortscruisecontrol(maxdeceleration": MaxDecelerationMpSS = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.5f); break; + case "engine(ortscruisecontrol(antiwheelspinequipped": AntiWheelSpinEquipped = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(nominalspeedstep": SpeedRegulatorNominalSpeedStepMpS = SpeedIsMph ? MpS.FromMpH(stf.ReadFloatBlock(STFReader.UNITS.Speed, 0)) : MpS.FromKpH(stf.ReadFloatBlock(STFReader.UNITS.Speed, 0)); break; + case "engine(ortscruisecontrol(usethrottleasspeedselector": UseThrottleAsSpeedSelector = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(usethrottleasforceselector": UseThrottleAsForceSelector = stf.ReadBoolBlock(false); break; + case "engine(ortscruisecontrol(dynamicbrakeincreasespeed": DynamicBrakeIncreaseSpeed = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.5f); break; + case "engine(ortscruisecontrol(dynamicbrakedecreasespeed": DynamicBrakeDecreaseSpeed = stf.ReadFloatBlock(STFReader.UNITS.Any, 0.5f); break; + case "engine(ortscruisecontrol(options": + foreach (var speedRegulatorOption in stf.ReadStringBlock("").ToLower().Replace(" ", "").Split(',')) + { + SpeedRegulatorOptions.Add(speedRegulatorOption.ToLower()); + } + break; + } + } + public float AccelerationRampMpSSS + { + get + { + if ((Locomotive.Train.MassKg > 0f) && (Locomotive.MassKG > 0)) + { + float accelerationRampMpSS = AccelerationRampMaxMpSSS / (Locomotive.Train.MassKg / Locomotive.MassKG); + accelerationRampMpSS = accelerationRampMpSS > AccelerationRampMaxMpSSS ? AccelerationRampMaxMpSSS : accelerationRampMpSS; + accelerationRampMpSS = accelerationRampMpSS < AccelerationRampMinMpSSS ? AccelerationRampMinMpSSS : accelerationRampMpSS; + return accelerationRampMpSS; + } + else + return AccelerationRampMaxMpSSS; + + + } + } + + public void Initialize() + { + Simulator = Locomotive.Simulator; + clockTime = Simulator.ClockTime * 100; + } + + public void Update(float elapsedClockSeconds, float AbsWheelSpeedMpS) + { + elapsedTime += elapsedClockSeconds; + if (maxForceIncreasing) SpeedRegulatorMaxForceIncrease(); + if (maxForceDecreasing) SpeedRegulatorMaxForceDecrease(); + if (SpeedRegMode == SpeedRegulatorMode.Manual) + return; + + if (absMaxForceN == 0) absMaxForceN = Locomotive.MaxForceN; + + if (selectedSpeedIncreasing) SpeedRegulatorSelectedSpeedIncrease(); + if (selectedSpeedDecreasing) SpeedRegulatorSelectedSpeedDecrease(); + + if (Locomotive.DynamicBrakePercent > 0) + if (Locomotive.DynamicBrakePercent > 100) + Locomotive.DynamicBrakePercent = 100; + ForceThrottleAndDynamicBrake = Locomotive.DynamicBrakePercent; + + UpdateMotiveForce(elapsedClockSeconds, AbsWheelSpeedMpS); + } + + public void Save(BinaryWriter outf) + { + outf.Write(this.applyingPneumaticBrake); + outf.Write(this.Battery); + outf.Write(this.brakeIncreasing); + outf.Write(this.clockTime); + outf.Write(this.controllerTime); + outf.Write(this.CurrentSelectedSpeedMpS); + outf.Write(this.currentThrottlePercent); + outf.Write(this.dynamicBrakeSetToZero); + outf.Write(this.fromAcceleration); + outf.Write(this.maxForceDecreasing); + outf.Write(this.maxForceIncreasing); + outf.Write(this.maxForceN); + outf.Write(this.nextSelectedSpeedMps); + outf.Write(this.restrictedRegionTravelledDistance); + outf.Write(this.RestrictedSpeedActive); + outf.Write(this.SelectedMaxAccelerationPercent); + outf.Write(this.SelectedMaxAccelerationStep); + outf.Write(this.SelectedNumberOfAxles); + outf.Write(this.SelectedSpeedMpS); + outf.Write((int)this.SpeedRegMode); + outf.Write((int)this.SpeedSelMode); + outf.Write(this.throttleIsZero); + outf.Write(this.trainBrakePercent); + outf.Write(this.TrainLengthMeters); + } + + public void Restore(BinaryReader inf) + { + applyingPneumaticBrake = inf.ReadBoolean(); + Battery = inf.ReadBoolean(); + brakeIncreasing = inf.ReadBoolean(); + clockTime = inf.ReadDouble(); + controllerTime = inf.ReadSingle(); + CurrentSelectedSpeedMpS = inf.ReadSingle(); + currentThrottlePercent = inf.ReadSingle(); + dynamicBrakeSetToZero = inf.ReadBoolean(); + fromAcceleration = inf.ReadSingle(); + maxForceDecreasing = inf.ReadBoolean(); + maxForceIncreasing = inf.ReadBoolean(); + maxForceN = inf.ReadSingle(); + nextSelectedSpeedMps = inf.ReadSingle(); + restrictedRegionTravelledDistance = inf.ReadSingle(); + RestrictedSpeedActive = inf.ReadBoolean(); + SelectedMaxAccelerationPercent = inf.ReadSingle(); + SelectedMaxAccelerationStep = inf.ReadSingle(); + SelectedNumberOfAxles = inf.ReadInt32(); + SelectedSpeedMpS = inf.ReadSingle(); + int fSpeedRegMode = inf.ReadInt32(); + SpeedRegMode = (SpeedRegulatorMode)fSpeedRegMode; + int fSpeedSelMode = inf.ReadInt32(); + SpeedSelMode = (SpeedSelectorMode)fSpeedSelMode; + throttleIsZero = inf.ReadBoolean(); + trainBrakePercent = inf.ReadSingle(); + TrainLengthMeters = inf.ReadInt32(); + } + + public void SpeedRegulatorModeIncrease() + { + if (!Locomotive.IsPlayerTrain) return; + Locomotive.SignalEvent(Common.Event.CruiseControlSpeedRegulator); + SpeedRegulatorMode previousMode = SpeedRegMode; + if (!Equipped) return; + if (SpeedRegMode == SpeedRegulatorMode.Testing) return; + bool test = false; + while (!test) + { + SpeedRegMode++; + switch (SpeedRegMode) + { + case SpeedRegulatorMode.Auto: + { + if (SpeedRegulatorOptions.Contains("regulatorauto")) test = true; + SelectedSpeedMpS = Locomotive.AbsSpeedMpS; + break; + } + case SpeedRegulatorMode.Testing: if (SpeedRegulatorOptions.Contains("regulatortest")) test = true; break; + } + if (!test && SpeedRegMode == SpeedRegulatorMode.Testing) // if we're here, then it means no higher option, return to previous state and get out + { + SpeedRegMode = previousMode; + return; + } + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed regulator mode changed to") + " " + Simulator.Catalog.GetString(SpeedRegMode.ToString())); + } + public void SpeedRegulatorModeDecrease() + { + Locomotive.SignalEvent(Common.Event.CruiseControlSpeedRegulator); + if (!Equipped) return; + if (SpeedRegMode == SpeedRegulatorMode.Manual) return; + bool test = false; + while (!test) + { + SpeedRegMode--; + switch (SpeedRegMode) + { + case SpeedRegulatorMode.Auto: if (SpeedRegulatorOptions.Contains("regulatorauto")) test = true; break; + case SpeedRegulatorMode.Manual: + { + Locomotive.ThrottleController.SetPercent(0); + currentThrottlePercent = 0; + if (SpeedRegulatorOptions.Contains("regulatormanual")) test = true; + SelectedSpeedMpS = 0; + break; + } + } + if (!test && SpeedRegMode == SpeedRegulatorMode.Manual) + return; + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed regulator mode changed to") + " " + Simulator.Catalog.GetString(SpeedRegMode.ToString())); + } + public void SpeedSelectorModeStartIncrease() + { + Locomotive.SignalEvent(Common.Event.CruiseControlSpeedSelector); + if (!Equipped) return; + if (SpeedSelMode == SpeedSelectorMode.Start) return; + bool test = false; + while (!test) + { + SpeedSelMode++; + if (SpeedSelMode != SpeedSelectorMode.Parking && !Locomotive.EngineBrakePriority) Locomotive.SetEngineBrakePercent(0); + switch (SpeedSelMode) + { + case SpeedSelectorMode.Neutral: if (SpeedRegulatorOptions.Contains("selectorneutral")) test = true; break; + case SpeedSelectorMode.On: if (SpeedRegulatorOptions.Contains("selectoron")) test = true; break; + case SpeedSelectorMode.Start: if (SpeedRegulatorOptions.Contains("selectorstart")) test = true; break; + } + if (!test && SpeedSelMode == SpeedSelectorMode.Start) + return; + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed selector mode changed to") + " " + Simulator.Catalog.GetString(SpeedSelMode.ToString())); + } + public void SpeedSelectorModeStopIncrease() + { + Locomotive.SignalEvent(Common.Event.CruiseControlSpeedSelector); + //Locomotive.Mirel.ResetVigilance(); + if (!Equipped) return; + if (SpeedSelMode == SpeedSelectorMode.Start) + { + bool test = false; + while (!test) + { + SpeedSelMode--; + switch (SpeedSelMode) + { + case SpeedSelectorMode.On: if (SpeedRegulatorOptions.Contains("selectoron")) test = true; break; + case SpeedSelectorMode.Neutral: if (SpeedRegulatorOptions.Contains("selectorneutral")) test = true; break; + case SpeedSelectorMode.Parking: if (SpeedRegulatorOptions.Contains("selectorparking")) test = true; break; + } + if (!test && SpeedSelMode == SpeedSelectorMode.Parking && !Locomotive.EngineBrakePriority) + return; + } + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed selector mode changed to") + " " + Simulator.Catalog.GetString(SpeedSelMode.ToString())); + } + public void SpeedSelectorModeDecrease() + { + Locomotive.SignalEvent(Common.Event.CruiseControlSpeedSelector); + SpeedSelectorMode previousMode = SpeedSelMode; + if (!Equipped) return; + if (SpeedSelMode == SpeedSelectorMode.Parking && !Locomotive.EngineBrakePriority) return; + bool test = false; + while (!test) + { + SpeedSelMode--; + switch (SpeedSelMode) + { + case SpeedSelectorMode.On: if (SpeedRegulatorOptions.Contains("selectoron")) test = true; break; + case SpeedSelectorMode.Neutral: if (SpeedRegulatorOptions.Contains("selectorneutral")) test = true; break; + case SpeedSelectorMode.Parking: if (SpeedRegulatorOptions.Contains("selectorparking")) test = true; break; + } + if (!test && SpeedSelMode == SpeedSelectorMode.Parking && !Locomotive.EngineBrakePriority) + { + SpeedSelMode = previousMode; + return; + } + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed selector mode changed to") + " " + Simulator.Catalog.GetString(SpeedSelMode.ToString())); + } + + public void SetMaxForcePercent(float percent) + { + if (SelectedMaxAccelerationPercent == percent) return; + SelectedMaxAccelerationPercent = percent; + SelectedMaxAccelerationPercent = (float)Math.Round(SelectedMaxAccelerationStep, 0); + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed regulator max acceleration percent changed to") + " " + Simulator.Catalog.GetString(SelectedMaxAccelerationPercent.ToString()) + "%"); + } + + bool maxForceIncreasing = false; + public void SpeedRegulatorMaxForceStartIncrease() + { + maxForceIncreasing = true; + } + public void SpeedRegulatorMaxForceStopIncrease() + { + maxForceIncreasing = false; + } + protected void SpeedRegulatorMaxForceIncrease() + { + Locomotive.SignalEvent(Common.Event.CruiseControlMaxForce); + if (MaxForceSetSingleStep) maxForceIncreasing = false; + if (SelectedMaxAccelerationStep == 0.5f) SelectedMaxAccelerationStep = 0; + if (!Equipped) return; + if (SpeedRegulatorMaxForcePercentUnits) + { + if (SelectedMaxAccelerationPercent == 100) + return; + SelectedMaxAccelerationPercent += 1f; + SelectedMaxAccelerationPercent = (float)Math.Round(SelectedMaxAccelerationStep, 0); + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed regulator max acceleration percent changed to") + " " + Simulator.Catalog.GetString(SelectedMaxAccelerationPercent.ToString()) + "%"); + } + else + { + if (SelectedMaxAccelerationStep == SpeedRegulatorMaxForceSteps) + return; + SelectedMaxAccelerationStep++; + SelectedMaxAccelerationStep = (float)Math.Round(SelectedMaxAccelerationStep, 0); + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed regulator max acceleration changed to") + " " + Simulator.Catalog.GetString(SelectedMaxAccelerationStep.ToString())); + } + } + + protected bool maxForceDecreasing = false; + public void SpeedRegulatorMaxForceStartDecrease() + { + maxForceDecreasing = true; + } + public void SpeedRegulatorMaxForceStopDecrease() + { + maxForceDecreasing = false; + } + protected void SpeedRegulatorMaxForceDecrease() + { + Locomotive.SignalEvent(Common.Event.CruiseControlMaxForce); + if (MaxForceSetSingleStep) maxForceDecreasing = false; + if (!Equipped) return; + if (DisableZeroForceStep) + { + if (SelectedMaxAccelerationStep <= 1) return; + } + else + { + if (SelectedMaxAccelerationStep <= 0) return; + } + SelectedMaxAccelerationStep--; + SelectedMaxAccelerationStep = (float)Math.Round(SelectedMaxAccelerationStep, 0); + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed regulator max acceleration changed to") + " " + Simulator.Catalog.GetString(SelectedMaxAccelerationStep.ToString())); + } + + protected bool selectedSpeedIncreasing = false; + public void SpeedRegulatorSelectedSpeedStartIncrease() + { + if (SpeedRegMode != SpeedRegulatorMode.Auto && ForceRegulatorAutoWhenNonZeroSpeedSelected) + { + SpeedRegMode = SpeedRegulatorMode.Auto; + } + if (!UseThrottleAsSpeedSelector) + selectedSpeedIncreasing = true; + else + SpeedSelectorModeStartIncrease(); + } + public void SpeedRegulatorSelectedSpeedStopIncrease() + { + if (!UseThrottleAsSpeedSelector) + selectedSpeedIncreasing = false; + else + SpeedSelectorModeStopIncrease(); + } + + protected double selectedSpeedLeverHoldTime = 0; + public void SpeedRegulatorSelectedSpeedIncrease() + { + if (!Equipped) return; + + if (selectedSpeedLeverHoldTime + SpeedSelectorStepTimeSeconds > elapsedTime) + return; + selectedSpeedLeverHoldTime = elapsedTime; + + SelectedSpeedMpS += SpeedRegulatorNominalSpeedStepMpS; + if (SelectedSpeedMpS > Locomotive.MaxSpeedMpS) + SelectedSpeedMpS = Locomotive.MaxSpeedMpS; + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Selected speed changed to ") + Math.Round(MpS.FromMpS(SelectedSpeedMpS, true), 0, MidpointRounding.AwayFromZero).ToString() + " km/h"); + } + + protected bool selectedSpeedDecreasing = false; + public void SpeedRegulatorSelectedSpeedStartDecrease() + { + if (!UseThrottleAsSpeedSelector) + selectedSpeedDecreasing = true; + else + SpeedSelectorModeDecrease(); + } + public void SpeedRegulatorSelectedSpeedStopDecrease() + { + selectedSpeedDecreasing = false; + } + public void SpeedRegulatorSelectedSpeedDecrease() + { + if (!Equipped) return; + + if (selectedSpeedLeverHoldTime + SpeedSelectorStepTimeSeconds > elapsedTime) + return; + selectedSpeedLeverHoldTime = elapsedTime; + + SelectedSpeedMpS -= SpeedRegulatorNominalSpeedStepMpS; + if (SelectedSpeedMpS < 0) + SelectedSpeedMpS = 0f; + if (SpeedRegMode == SpeedRegulatorMode.Auto && ForceRegulatorAutoWhenNonZeroSpeedSelected && SelectedSpeedMpS == 0) + { + // return back to manual, clear all we have controlled before and let the driver to set up new stuff + SpeedRegMode = SpeedRegulatorMode.Manual; + Locomotive.ThrottleController.SetPercent(0); + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Selected speed changed to ") + Math.Round(MpS.FromMpS(SelectedSpeedMpS, true), 0, MidpointRounding.AwayFromZero).ToString() + " km/h"); + } + public void NumerOfAxlesIncrease() + { + NumerOfAxlesIncrease(1); + } + public void NumerOfAxlesIncrease(int ByAmount) + { + SelectedNumberOfAxles += ByAmount; + trainLength = SelectedNumberOfAxles * 6.6f; + TrainLengthMeters = (int)Math.Round(trainLength + 0.5, 0); + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Number of axles increased to ") + SelectedNumberOfAxles.ToString()); + } + public void NumberOfAxlesDecrease() + { + NumberOfAxlesDecrease(1); + } + public void NumberOfAxlesDecrease(int ByAmount) + { + if ((SelectedNumberOfAxles - ByAmount) < 1) return; + SelectedNumberOfAxles -= ByAmount; + trainLength = SelectedNumberOfAxles * 6.6f; + TrainLengthMeters = (int)Math.Round(trainLength + 0.5, 0); + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Number of axles decreased to ") + SelectedNumberOfAxles.ToString()); + } + public void ActivateRestrictedSpeedZone() + { + RemainingTrainLengthToPassRestrictedZone = TrainLengthMeters; + if (!RestrictedSpeedActive) + { + restrictedRegionTravelledDistance = Simulator.PlayerLocomotive.Train.DistanceTravelledM; + CurrentSelectedSpeedMpS = SelectedSpeedMpS; + RestrictedSpeedActive = true; + } + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed restricted zone active.")); + } + + public virtual void CheckRestrictedSpeedZone() + { + RemainingTrainLengthToPassRestrictedZone = (int)Math.Round((Simulator.PlayerLocomotive.Train.DistanceTravelledM - restrictedRegionTravelledDistance)); + if (RemainingTrainLengthToPassRestrictedZone < 0) RemainingTrainLengthToPassRestrictedZone = 0; + if ((Simulator.PlayerLocomotive.Train.DistanceTravelledM - restrictedRegionTravelledDistance) >= trainLength) + { + RestrictedSpeedActive = false; + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Speed restricted zone off.")); + Locomotive.SignalEvent(Common.Event.Alert); + } + } + + public void SetSpeed(float Speed) + { + if (SpeedRegMode == SpeedRegulatorMode.Manual && ForceRegulatorAutoWhenNonZeroSpeedSelected) + SpeedRegMode = SpeedRegulatorMode.Auto; + Locomotive.SignalEvent(Common.Event.Alert1); + if (!Equipped) return; + SelectedSpeedMpS = SpeedIsMph ? MpS.FromMpH(Speed) : MpS.FromKpH(Speed); + if (SelectedSpeedMpS > Locomotive.MaxSpeedMpS) + SelectedSpeedMpS = Locomotive.MaxSpeedMpS; + Simulator.Confirmer.Message(ConfirmLevel.Information, Simulator.Catalog.GetString("Selected speed set to ") + Speed.ToString() + (SpeedIsMph? "mph" : "kmh")); + } + + protected List playerNotDriveableTrainLocomotives = new List(); + float _AccelerationMpSS = 0; + protected bool throttleIsZero = false; + protected bool brakeIncreasing = false; + protected float controllerTime = 0; + protected float fromAcceleration = 0; + protected bool applyingPneumaticBrake = false; + protected bool firstIteration = true; + protected float previousMotiveForce = 0; + protected float addPowerTimeCount = 0; + public float controllerVolts = 0; + protected float throttleChangeTime = 0; + protected bool breakout = false; + protected float timeFromEngineMoved = 0; + protected bool reducingForce = false; + protected bool canAddForce = true; + List concurrentAccelerationList = new List(); + public float TrainElevation = 0; + protected float skidSpeedDegratation = 0; + protected float previousAccelerationDemand = 0; + + protected virtual void UpdateMotiveForce(float elapsedClockSeconds, float AbsWheelSpeedMpS) + { + if (DynamicBrakeFullRangeIncreaseTimeSeconds == 0) + DynamicBrakeFullRangeIncreaseTimeSeconds = 4; + if (DynamicBrakeFullRangeDecreaseTimeSeconds == 0) + DynamicBrakeFullRangeDecreaseTimeSeconds = 6; + float speedDiff = AbsWheelSpeedMpS - Locomotive.AbsSpeedMpS; + float newThrotte = 0; + // calculate new max force if MaxPowerThreshold is set + if (MaxPowerThreshold > 0) + { + float currentSpeed = SpeedIsMph ? MpS.ToMpH(AbsWheelSpeedMpS) : MpS.ToKpH(AbsWheelSpeedMpS); + float percentComplete = (int)Math.Round((double)(100 * currentSpeed) / MaxPowerThreshold); + if (percentComplete > 100) + percentComplete = 100; + newThrotte = percentComplete; + } + + int count = 0; + TrainElevation = 0; + foreach (TrainCar tc in Locomotive.Train.Cars) + { + count++; + TrainElevation += tc.Flipped ? tc.CurrentElevationPercent : -tc.CurrentElevationPercent; + } + TrainElevation = TrainElevation / count; + + if (SpeedSelMode == SpeedSelectorMode.On || SpeedSelMode == SpeedSelectorMode.Start) + { + canAddForce = true; + } + else + { + canAddForce = false; + timeFromEngineMoved = 0; + reducingForce = true; + } + if (canAddForce) + { + if (Locomotive.AbsSpeedMpS == 0) + { + timeFromEngineMoved = 0; + reducingForce = true; + } + else if (reducingForce) + { + timeFromEngineMoved += elapsedClockSeconds; + float timeToReduce = Locomotive.SelectedTrainType == MSTSLocomotive.TrainType.Pax ? PowerReductionDelayPaxTrain : PowerReductionDelayCargoTrain; + if (timeFromEngineMoved > timeToReduce) + reducingForce = false; + } + } + if (Bar.FromPSI(Locomotive.BrakeSystem.BrakeLine1PressurePSI) < 4.98) + { + canAddForce = false; + reducingForce = true; + timeFromEngineMoved = 0; + maxForceN = 0; + if (controllerVolts > 0) + controllerVolts = 0; + Ampers = 0; + Locomotive.ThrottleController.SetPercent(0); + return; + } + else if (Bar.FromPSI(Locomotive.BrakeSystem.BrakeLine1PressurePSI) > 4.7) + { + canAddForce = true; + } + if (SpeedRegulatorOptions.Contains("engageforceonnonzerospeed") && SelectedSpeedMpS > 0) + { + SpeedSelMode = SpeedSelectorMode.On; + SpeedRegMode = SpeedRegulatorMode.Auto; + SkipThrottleDisplay = true; + } + if (SpeedRegulatorOptions.Contains("engageforceonnonzerospeed") && SelectedSpeedMpS == 0) return; + + float t = 0; + if (SpeedRegMode == SpeedRegulatorMode.Manual) DynamicBrakePriority = false; + + if (RestrictedSpeedActive) + CheckRestrictedSpeedZone(); + if (DynamicBrakePriority) + { + Locomotive.ThrottleController.SetPercent(0); + ForceThrottleAndDynamicBrake = -Locomotive.DynamicBrakePercent; + return; + } + + if (firstIteration) // if this is exetuted the first time, let's check all other than player engines in the consist, and record them for further throttle manipulation + { + SelectedNumberOfAxles = (int)(Locomotive.Train.Length / 6.6f); // also set the axles, for better delta computing, if user omits to set it + foreach (TrainCar tc in Locomotive.Train.Cars) + { + if (tc.GetType() == typeof(MSTSLocomotive) || tc.GetType() == typeof(MSTSDieselLocomotive) || tc.GetType() == typeof(MSTSElectricLocomotive)) + { + if (tc != Locomotive) + { + try + { + playerNotDriveableTrainLocomotives.Add((MSTSLocomotive)tc); + } + catch { } + } + } + } + firstIteration = false; + } + + if (SpeedRegMode == SpeedRegulatorMode.Auto) + { + if (SpeedSelMode == SpeedSelectorMode.Parking && !Locomotive.EngineBrakePriority) + { + if (Locomotive.DynamicBrakePercent > 0) + { + if (AbsWheelSpeedMpS == 0) + { + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + } + if (!UseThrottle) Locomotive.ThrottleController.SetPercent(0); + throttleIsZero = true; + + if (AbsWheelSpeedMpS < (SpeedIsMph ? MpS.FromMpH(ParkingBrakeEngageSpeed) : MpS.FromKpH(ParkingBrakeEngageSpeed))) + Locomotive.SetEngineBrakePercent(ParkingBrakePercent); + } + else if (SpeedSelMode == SpeedSelectorMode.Neutral || SpeedSelMode < SpeedSelectorMode.Start && !SpeedRegulatorOptions.Contains("startfromzero") && AbsWheelSpeedMpS < SafeSpeedForAutomaticOperationMpS) + { + if (controllerVolts > 0) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + if (controllerVolts < 0) controllerVolts = 0; + if (controllerVolts > 0 && controllerVolts < 0.1) controllerVolts = 0; + } + + float delta = 0; + if (!RestrictedSpeedActive) + delta = SelectedSpeedMpS - AbsWheelSpeedMpS; + else + delta = CurrentSelectedSpeedMpS - AbsWheelSpeedMpS; + + if (delta > 0) + { + if (controllerVolts < -0.1) + { + float step = 100 / ThrottleFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + else if (controllerVolts > 0.1) + { + + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + else + { + controllerVolts = 0; + } + } + + if (delta < 0) // start braking + { + if (maxForceN > 0) + { + if (controllerVolts > 0) + { + float step = 100 / ThrottleFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + else + { + if (Locomotive.DynamicBrakeAvailable) + { + delta = 0; + if (!RestrictedSpeedActive) + delta = (SelectedSpeedMpS + (TrainElevation < -0.01 ? TrainElevation * (SelectedNumberOfAxles / 12) : 0)) - AbsWheelSpeedMpS; + else + delta = (CurrentSelectedSpeedMpS + (TrainElevation < -0.01 ? TrainElevation * (SelectedNumberOfAxles / 12) : 0)) - AbsWheelSpeedMpS; + + relativeAcceleration = (float)-Math.Sqrt(-StartReducingSpeedDelta * delta); + AccelerationDemandMpSS = (float)-Math.Sqrt(-StartReducingSpeedDelta * AccelerationRampMpSSS * delta); + if (maxForceN > 0) + { + if (controllerVolts > 0) + { + float step = 100 / ThrottleFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + if (maxForceN == 0) + { + if (!UseThrottle) Locomotive.ThrottleController.SetPercent(0); + if (relativeAcceleration < -1) relativeAcceleration = -1; + if (Locomotive.DynamicBrakePercent < -(AccelerationDemandMpSS * 100) && AccelerationDemandMpSS < -0.05f) + { + if (controllerVolts > -100) + { + float step = 100 / DynamicBrakeFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + if (Locomotive.DynamicBrakePercent > -((AccelerationDemandMpSS - 0.05f) * 100)) + { + if (controllerVolts < 0) + { + float step = 100 / DynamicBrakeFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + } + } + } + else // use TrainBrake + { + if (delta > -0.1) + { + if (!UseThrottle) + Locomotive.ThrottleController.SetPercent(100); + throttleIsZero = false; + maxForceN = 0; + } + else if (delta > -1) + { + if (!UseThrottle) + Locomotive.ThrottleController.SetPercent(0); + throttleIsZero = true; + + brakePercent = 10 + (-delta * 10); + } + else + { + Locomotive.TractiveForceN = 0; + if (!UseThrottle) + Locomotive.ThrottleController.SetPercent(0); + throttleIsZero = true; + + if (_AccelerationMpSS > -MaxDecelerationMpSS) + brakePercent += 0.5f; + else if (_AccelerationMpSS < -MaxDecelerationMpSS) + brakePercent -= 1; + if (brakePercent > 100) + brakePercent = 100; + } + } + } + } + else + { + if (Locomotive.DynamicBrakeAvailable) + { + if (Locomotive.DynamicBrakePercent > 0) + { + if (controllerVolts < 0) + { + float step = 100 / DynamicBrakeFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + } + } + } + } + + if ((AbsWheelSpeedMpS > SafeSpeedForAutomaticOperationMpS || SpeedSelMode == SpeedSelectorMode.Start || SpeedRegulatorOptions.Contains("startfromzero")) && (SpeedSelMode != SpeedSelectorMode.Neutral && SpeedSelMode != SpeedSelectorMode.Parking)) + { + float delta = 0; + if (!RestrictedSpeedActive) + delta = SelectedSpeedMpS - AbsWheelSpeedMpS; + else + delta = CurrentSelectedSpeedMpS - AbsWheelSpeedMpS; + float coeff = 1; + float speed = SpeedIsMph ? MpS.ToMpH(Locomotive.WheelSpeedMpS) : MpS.ToKpH(Locomotive.WheelSpeedMpS); + if (speed > 100) + { + coeff = (speed / 100) * 1.2f; + } + else + { + coeff = 1; + } + float numAxesCoeff = 0; + numAxesCoeff = (SelectedNumberOfAxles) / 12; + AccelerationDemandMpSS = (float)Math.Sqrt((StartReducingSpeedDelta + numAxesCoeff) * coeff * coeff * AccelerationRampMpSSS * (delta)); + if (delta > 0.0f) + { + if (Locomotive.DynamicBrakePercent > 0) + { + float step = 100 / DynamicBrakeFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + if (Locomotive.DynamicBrakePercent < 2 && Locomotive.DynamicBrake) + { + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + relativeAcceleration = (float)Math.Sqrt(AccelerationRampMaxMpSSS * delta); + } + else // start braking + { + if (controllerVolts > 0) + { + float step = 100 / ThrottleFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + if (controllerVolts < 0) controllerVolts = 0; + if (controllerVolts > 0 && controllerVolts < 0.1) controllerVolts = 0; + } + + if (delta < 0) // start braking + { + if (maxForceN > 0) + { + if (controllerVolts > 0) + { + float step = 100 / ThrottleFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + else + { + if (Locomotive.DynamicBrakeAvailable) + { + relativeAcceleration = (float)-Math.Sqrt(-StartReducingSpeedDelta * delta); + AccelerationDemandMpSS = (float)-Math.Sqrt(-StartReducingSpeedDelta * AccelerationRampMpSSS * delta); + if (maxForceN == 0) + { + if (!UseThrottle) Locomotive.ThrottleController.SetPercent(0); + if (Locomotive.AccelerationMpSS > AccelerationDemandMpSS) + { + if (controllerVolts > -100) + { + float step = 100 / DynamicBrakeFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + if (step > (Locomotive.AccelerationMpSS - AccelerationDemandMpSS) * 2) + step = (Locomotive.AccelerationMpSS - AccelerationDemandMpSS) * 2; + controllerVolts -= step; + } + } + if (Locomotive.AccelerationMpSS + 0.01f < AccelerationDemandMpSS) + { + if (controllerVolts < 0) + { + float step = 100 / DynamicBrakeFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + if (step > (AccelerationDemandMpSS - Locomotive.AccelerationMpSS) * 2) + step = (AccelerationDemandMpSS - Locomotive.AccelerationMpSS) * 2; + controllerVolts += step; + } + } + } + } + else // use TrainBrake + { + if (delta > -0.1) + { + if (!UseThrottle) + Locomotive.ThrottleController.SetPercent(100); + throttleIsZero = false; + maxForceN = 0; + } + else if (delta > -1) + { + if (!UseThrottle) + Locomotive.ThrottleController.SetPercent(0); + throttleIsZero = true; + + brakePercent = 10 + (-delta * 10); + } + else + { + Locomotive.TractiveForceN = 0; + if (!UseThrottle) + Locomotive.ThrottleController.SetPercent(0); + throttleIsZero = true; + + if (_AccelerationMpSS > -MaxDecelerationMpSS) + brakePercent += 0.5f; + else if (_AccelerationMpSS < -MaxDecelerationMpSS) + brakePercent -= 1; + if (brakePercent > 100) + brakePercent = 100; + } + } + } + } + } + if (relativeAcceleration > 1.0f) + relativeAcceleration = 1.0f; + + if ((SpeedSelMode == SpeedSelectorMode.On || SpeedSelMode == SpeedSelectorMode.Start) && delta > 0) + { + if (Locomotive.DynamicBrakePercent > 0) + { + if (controllerVolts <= 0) + { + float step = 100 / DynamicBrakeFullRangeDecreaseTimeSeconds; + step *= elapsedClockSeconds; + if (step > (AccelerationDemandMpSS - Locomotive.AccelerationMpSS) * 2) + step = (AccelerationDemandMpSS - Locomotive.AccelerationMpSS) * 2; + controllerVolts += step; + } + } + else + { + if (!UseThrottle) + { + Locomotive.ThrottleController.SetPercent(100); + } + throttleIsZero = false; + } + } + float a = 0; + if (Locomotive.PowerOn && Locomotive.Direction != Direction.N) + { + if (Locomotive.DynamicBrakePercent < 0) + { + if (Locomotive.AccelerationMpSS < AccelerationDemandMpSS) + { + if (ForceStepsThrottleTable.Count > 0) + { + t = ForceStepsThrottleTable[(int)SelectedMaxAccelerationStep - 1]; + if (AccelerationTable.Count > 0) + a = AccelerationTable[(int)SelectedMaxAccelerationStep - 1]; + } + else + t = SelectedMaxAccelerationStep; + if (t < newThrotte) + t = newThrotte; + t /= 100; + } + else + { + if (controllerVolts > 0) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + } + if (reducingForce) + { + if (t > PowerReductionValue / 100) + t = PowerReductionValue / 100; + } + float demandedVolts = t * 100; + if (demandedVolts < PowerBreakoutAmpers) + breakout = true; + if (demandedVolts > 13.5f) + breakout = false; + if (UseThrottle) // not valid for diesel engines. + breakout = false; + if ((controllerVolts != demandedVolts) && delta > 0) + { + if (a > 0 && (SpeedIsMph ? MpS.ToMpH(Locomotive.WheelSpeedMpS) : MpS.ToKpH(Locomotive.WheelSpeedMpS)) > 5) + { + if (controllerVolts < demandedVolts && Locomotive.AccelerationMpSS < a - 0.02) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + } + else + { + if (controllerVolts < demandedVolts && controllerVolts >= 0) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + } + if (a > 0 && (SpeedIsMph ? MpS.ToMpH(Locomotive.WheelSpeedMpS) : MpS.ToKpH(Locomotive.WheelSpeedMpS)) > 5) + { + if (controllerVolts > demandedVolts && Locomotive.AccelerationMpSS > a + 0.02) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + else + { + if (controllerVolts > demandedVolts) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + if (controllerVolts > demandedVolts && delta < 0.8) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + if (a > 0 && (SpeedIsMph ? MpS.ToMpH(Locomotive.WheelSpeedMpS) : MpS.ToKpH(Locomotive.WheelSpeedMpS)) > 5) + { + if ((a != Locomotive.AccelerationMpSS) && delta > 0.8) + { + if (Locomotive.AccelerationMpSS < a + 0.02) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts += step; + } + if (Locomotive.AccelerationMpSS > a - 0.02) + { + float step = 100 / ThrottleFullRangeIncreaseTimeSeconds; + step *= elapsedClockSeconds; + controllerVolts -= step; + } + } + } + + if (UseThrottle) + { + if (controllerVolts > 0) + Locomotive.ThrottleController.SetPercent(controllerVolts); + } + } + } + else if (UseThrottle) + { + if (Locomotive.ThrottlePercent > 0) + { + float newValue = (Locomotive.ThrottlePercent - 1) / 100; + if (newValue < 0) + newValue = 0; + Locomotive.StartThrottleDecrease(newValue); + } + } + + if (Locomotive.WheelSpeedMpS == 0 && controllerVolts < 0) + controllerVolts = 0; + ForceThrottleAndDynamicBrake = controllerVolts; + + if (controllerVolts > 0) + { + if (speedDiff > 0.5) + { + skidSpeedDegratation += 0.05f; + } + else if (skidSpeedDegratation > 0) + { + skidSpeedDegratation -= 0.1f; + } + if (speedDiff < 0.4) + skidSpeedDegratation = 0; + controllerVolts -= skidSpeedDegratation; + if (breakout || Bar.FromPSI(Locomotive.BrakeSystem.BrakeLine1PressurePSI) < 4.98) + { + maxForceN = 0; + controllerVolts = 0; + Ampers = 0; + if (!UseThrottle) Locomotive.ThrottleController.SetPercent(0); + } + else + { + if (Locomotive.ThrottlePercent < 100 && SpeedSelMode != SpeedSelectorMode.Parking && !UseThrottle) + { + Locomotive.ThrottleController.SetPercent(100); + throttleIsZero = false; + } + if (Locomotive.DynamicBrakePercent > -1) + { + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + + if (Locomotive.TractiveForceCurves != null && !UseThrottle) + { + maxForceN = Locomotive.TractiveForceCurves.Get(controllerVolts / 100, AbsWheelSpeedMpS) * (1 - Locomotive.PowerReduction); + } + else + { + if (Locomotive.TractiveForceCurves == null) + maxForceN = Locomotive.MaxForceN * (controllerVolts / 100); + else + maxForceN = Locomotive.TractiveForceCurves.Get(controllerVolts / 100, AbsWheelSpeedMpS) * (1 - Locomotive.PowerReduction); + } + } + } + else if (controllerVolts < 0) + { + if (maxForceN > 0) maxForceN = 0; + if (Locomotive.ThrottlePercent > 0) Locomotive.ThrottleController.SetPercent(0); + if (Locomotive.DynamicBrakePercent <= 0) + { + string status = Locomotive.GetDynamicBrakeStatus(); + Locomotive.DynamicBrakeChangeActiveState(true); + } + Locomotive.SetDynamicBrakePercent(-controllerVolts); + Locomotive.DynamicBrakePercent = -controllerVolts; + } + else if (controllerVolts == 0) + { + if (!breakout) + { + + /*if (Locomotive.MultiPositionController.controllerPosition == Controllers.MultiPositionController.ControllerPosition.DynamicBrakeIncrease || Locomotive.MultiPositionController.controllerPosition == Controllers.MultiPositionController.ControllerPosition.DynamicBrakeIncreaseFast) + { + controllerVolts = -Locomotive.DynamicBrakePercent; + } + else + {*/ + if (maxForceN > 0) maxForceN = 0; + if (Locomotive.ThrottlePercent > 0 && !UseThrottle) Locomotive.ThrottleController.SetPercent(0); + if (Locomotive.DynamicBrakePercent > -1) + { + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeChangeActiveState(false); + } + } + } + + if (!Locomotive.PowerOn) // || Locomotive.Mirel.NZ1 || Locomotive.Mirel.NZ2 || Locomotive.Mirel.NZ3 || Locomotive.Mirel.NZ4 || Locomotive.Mirel.NZ5) + { + controllerVolts = 0; + Locomotive.ThrottleController.SetPercent(0); + if (Locomotive.DynamicBrakePercent > 0) + Locomotive.SetDynamicBrakePercent(0); + Locomotive.DynamicBrakeIntervention = -1; + maxForceN = 0; + ForceThrottleAndDynamicBrake = 0; + Ampers = 0; + } + else + ForceThrottleAndDynamicBrake = controllerVolts; + + Locomotive.MotiveForceN = maxForceN; + Locomotive.TractiveForceN = maxForceN; + } + + if (playerNotDriveableTrainLocomotives.Count > 0) // update any other than the player's locomotive in the consist throttles to percentage of the current force and the max force + { + foreach (MSTSLocomotive lc in playerNotDriveableTrainLocomotives) + { + if (UseThrottle) + { + lc.SetThrottlePercent(Locomotive.ThrottlePercent); + } + else + { + lc.IsAPartOfPlayerTrain = true; + float locoPercent = Locomotive.MaxForceN - (Locomotive.MaxForceN - Locomotive.MotiveForceN); + lc.ThrottleOverriden = locoPercent / Locomotive.MaxForceN; + } + } + } + } + + private float previousSelectedSpeed = 0; + + public float GetDataOf(CabViewControl cvc) + { + float data = 0; + switch (cvc.ControlType) + { + case CABViewControlTypes.ORTS_SELECTED_SPEED: + case CABViewControlTypes.ORTS_SELECTED_SPEED_DISPLAY: + bool metric = cvc.Units == CABViewControlUnits.KM_PER_HOUR; + float temp =RestrictedSpeedActive ? MpS.FromMpS(CurrentSelectedSpeedMpS, metric) : temp = MpS.FromMpS(SelectedSpeedMpS, metric); + if (previousSelectedSpeed < temp) previousSelectedSpeed += 1f; + if (previousSelectedSpeed > temp) previousSelectedSpeed -= 1f; + data = previousSelectedSpeed; + break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_MODE: + data = (float)SpeedSelMode; + break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_REGULATOR_MODE: + data = (float)SpeedRegMode; + break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_MAXIMUM_ACCELERATION: + if (SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto || MaxForceKeepSelectedStepWhenManualModeSet) + { + data = (SelectedMaxAccelerationStep - 1) * (float)cvc.MaxValue / 100; + } + else + data = 0; + break; + case CABViewControlTypes.ORTS_RESTRICTED_SPEED_ZONE_ACTIVE: + data = RestrictedSpeedActive ? 1 : 0; + break; + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DISPLAY_UNITS: + data = SelectedNumberOfAxles % 10; + break; + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DISPLAY_TENS: + data = (SelectedNumberOfAxles / 10) % 10; + break; + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DISPLAY_HUNDREDS: + data = (SelectedNumberOfAxles / 100) % 10; + break; + case CABViewControlTypes.ORTS_TRAIN_LENGTH_METERS: + data = TrainLengthMeters; + break; + case CABViewControlTypes.ORTS_REMAINING_TRAIN_LENGHT_SPEED_RESTRICTED: + if (RemainingTrainLengthToPassRestrictedZone == 0) + data = 0; + else + data = TrainLengthMeters - RemainingTrainLengthToPassRestrictedZone; + break; + case CABViewControlTypes.ORTS_REMAINING_TRAIN_LENGTH_PERCENT: + if (SpeedRegMode != CruiseControl.SpeedRegulatorMode.Auto) + { + data = 0; + break; + } + if (TrainLengthMeters > 0 && RemainingTrainLengthToPassRestrictedZone > 0) + { + data = (((float)TrainLengthMeters - (float)RemainingTrainLengthToPassRestrictedZone) / (float)TrainLengthMeters) * 100; + } + break; + case CABViewControlTypes.ORTS_MOTIVE_FORCE: + data = Locomotive.FilteredMotiveForceN; + break; + case CABViewControlTypes.ORTS_MOTIVE_FORCE_KILONEWTON: + if (Locomotive.FilteredMotiveForceN > Locomotive.DynamicBrakeForceN) + data = (float)Math.Round(Locomotive.FilteredMotiveForceN / 1000, 0); + else if (Locomotive.DynamicBrakeForceN > 0) + data = -(float)Math.Round(Locomotive.DynamicBrakeForceN / 1000, 0); + break; + case CABViewControlTypes.ORTS_MAXIMUM_FORCE: + data = Locomotive.MaxForceN; + break; + case CABViewControlTypes.ORTS_FORCE_IN_PERCENT_THROTTLE_AND_DYNAMIC_BRAKE: + if (SpeedRegMode == CruiseControl.SpeedRegulatorMode.Auto) + { + data = ForceThrottleAndDynamicBrake; + if (Locomotive.DynamicBrakePercent > 0 && data > -Locomotive.DynamicBrakePercent) data = -Locomotive.DynamicBrakePercent; + } + else + { + if (Locomotive.ThrottlePercent > 0) + { + data = Locomotive.ThrottlePercent; + } + else if (Locomotive.DynamicBrakePercent > 0 && Locomotive.AbsSpeedMpS > 0) + { + data = -Locomotive.DynamicBrakePercent; + } + else data = 0; + } + break; + case CABViewControlTypes.ORTS_TRAIN_TYPE_PAX_OR_CARGO: + data = (int)Locomotive.SelectedTrainType; + break; + case CABViewControlTypes.ORTS_CONTROLLER_VOLTAGE: + data = controllerVolts; + break; + case CABViewControlTypes.ORTS_AMPERS_BY_CONTROLLER_VOLTAGE: + if (SpeedRegMode == SpeedRegulatorMode.Auto) + { + if (controllerVolts < 0) data = -controllerVolts / 100 * (Locomotive.MaxCurrentA * 0.8f); + else data = controllerVolts / 100 * (Locomotive.MaxCurrentA * 0.8f); + if (data == 0 && Locomotive.DynamicBrakePercent > 0 && Locomotive.AbsSpeedMpS > 0) data = Locomotive.DynamicBrakePercent / 100 * (Locomotive.MaxCurrentA * 0.8f); + } + else + { + if (Locomotive.DynamicBrakePercent > 0 && Locomotive.AbsSpeedMpS > 0) data = Locomotive.DynamicBrakePercent / 200 * (Locomotive.MaxCurrentA * 0.8f); + else data = Locomotive.ThrottlePercent / 100 * (Locomotive.MaxCurrentA * 0.8f); + } + break; + case CABViewControlTypes.ORTS_ODOMETER: + data = cvc.Units == CABViewControlUnits.KILOMETRES ? float.Parse(Math.Round(Locomotive.OdometerM / 1000, 0).ToString()) : Locomotive.OdometerM; + break; + case CABViewControlTypes.ORTS_CC_SELECT_SPEED: + data = Locomotive.SelectingSpeedPressed ? 1 : 0; + break; + default: + data = 0; + break; + } + return data; + } + + public enum AvvSignal { + Stop, + Restricted, + Restricting40, + Clear, + Restricting60, + Restricting80, + Restricting100 + }; + public AvvSignal avvSignal = AvvSignal.Stop; + public void DrawAvvSignal(AvvSignal ToState) + { + avvSignal = ToState; + } + } +} \ No newline at end of file diff --git a/Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs b/Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs index 587b4612a2..403df78965 100644 --- a/Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs +++ b/Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs @@ -32,6 +32,7 @@ using Orts.Simulation.RollingStocks.SubSystems.Controllers; using Orts.Viewer3D.Common; using Orts.Viewer3D.Popups; +using Orts.Viewer3D.RollingStock.SubSystems; using Orts.Viewer3D.RollingStock.Subsystems.ETCS; using ORTS.Common; using ORTS.Common.Input; @@ -196,6 +197,42 @@ public override void InitializeUserInputCommands() new TCSSwitchCommand(Viewer.Log, !Locomotive.TrainControlSystem.TCSCommandSwitchOn[1], 1); } }); + if ((Car as MSTSLocomotive).CruiseControl != null) + { + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorMaxAccelerationDecrease, new Action[] { () => Locomotive.CruiseControl.SpeedRegulatorMaxForceStopDecrease(), () => Locomotive.CruiseControl.SpeedRegulatorMaxForceStartDecrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorMaxAccelerationIncrease, new Action[] { () => Locomotive.CruiseControl.SpeedRegulatorMaxForceStopIncrease(), () => Locomotive.CruiseControl.SpeedRegulatorMaxForceStartIncrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorModeDecrease, new Action[] { Noop, () => Locomotive.CruiseControl.SpeedRegulatorModeDecrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorModeIncrease, new Action[] { Noop, () => Locomotive.CruiseControl.SpeedRegulatorModeIncrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorSelectedSpeedDecrease, new Action[] { () => Locomotive.CruiseControl.SpeedRegulatorSelectedSpeedStopDecrease(), () => Locomotive.CruiseControl.SpeedRegulatorSelectedSpeedStartDecrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorSelectedSpeedIncrease, new Action[] { () => Locomotive.CruiseControl.SpeedRegulatorSelectedSpeedStopIncrease(), () => Locomotive.CruiseControl.SpeedRegulatorSelectedSpeedStartIncrease() }); + UserInputCommands.Add(UserCommand.ControlNumberOfAxlesDecrease, new Action[] { Noop, () => Locomotive.CruiseControl.NumberOfAxlesDecrease() }); + UserInputCommands.Add(UserCommand.ControlNumberOfAxlesIncrease, new Action[] { Noop, () => Locomotive.CruiseControl.NumerOfAxlesIncrease() }); + UserInputCommands.Add(UserCommand.ControlRestrictedSpeedZoneActive, new Action[] { Noop, () => Locomotive.CruiseControl.ActivateRestrictedSpeedZone() }); + UserInputCommands.Add(UserCommand.ControlCruiseControlModeIncrease, new Action[] { () => Locomotive.CruiseControl.SpeedSelectorModeStopIncrease(), () => Locomotive.CruiseControl.SpeedSelectorModeStartIncrease() }); + UserInputCommands.Add(UserCommand.ControlCruiseControlModeDecrease, new Action[] { Noop, () => Locomotive.CruiseControl.SpeedSelectorModeDecrease() }); + UserInputCommands.Add(UserCommand.ControlTrainTypePaxCargo, new Action[] { Noop, () => Locomotive.ChangeTrainTypePaxCargo() }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed10, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(10) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed20, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(20) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed30, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(30) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed40, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(40) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed50, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(50) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed60, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(60) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed70, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(70) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed80, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(80) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed90, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(90) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed100, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(100) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed110, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(110) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed120, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(120) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed130, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(130) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed140, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(140) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed150, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(150) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed160, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(160) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed170, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(170) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed180, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(180) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed190, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(190) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed200, new Action[] { Noop, () => Locomotive.CruiseControl.SetSpeed(200) }); + } + base.InitializeUserInputCommands(); } @@ -1931,7 +1968,19 @@ public virtual int GetDrawIndex() index = Locomotive.DynamicBrakeController != null ? Locomotive.DynamicBrakeController.CurrentNotch : 0; } else - index = PercentToIndex(dynBrakePercent); + { + if (Locomotive.CruiseControl != null) + { + if ((Locomotive.CruiseControl.SpeedRegMode == Simulation.RollingStocks.SubSystems.CruiseControl.SpeedRegulatorMode.Auto && !Locomotive.CruiseControl.DynamicBrakePriority) || Locomotive.DynamicBrakeIntervention > 0) + { + index = 0; + } + else + index = PercentToIndex(dynBrakePercent); + } + else + index = PercentToIndex(dynBrakePercent); + } } else { @@ -1949,12 +1998,28 @@ public virtual int GetDrawIndex() index = PercentToIndex(Locomotive.GetCombinedHandleValue(false)); break; case CABViewControlTypes.CP_HANDLE: + if (Locomotive.CruiseControl != null) + { + if (Locomotive.CruiseControl.SpeedRegMode == Simulation.RollingStocks.SubSystems.CruiseControl.SpeedRegulatorMode.Auto) + { + index = PercentToIndex(50); + break; + } + } if (Locomotive.CombinedControlType == MSTSLocomotive.CombinedControl.ThrottleDynamic && Locomotive.DynamicBrakePercent >= 0 || Locomotive.CombinedControlType == MSTSLocomotive.CombinedControl.ThrottleAir && Locomotive.TrainBrakeController.CurrentValue > 0) index = PercentToIndex(Locomotive.GetCombinedHandleValue(false)); else index = PercentToIndex(Locomotive.GetCombinedHandleValue(false)); break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_DISPLAY: + if (Locomotive.CruiseControl == null) + { + index = 0; + break; + } + index = (int)MpS.ToKpH(Locomotive.CruiseControl.SelectedSpeedMpS) / 10; + break; case CABViewControlTypes.ALERTER_DISPLAY: case CABViewControlTypes.RESET: case CABViewControlTypes.WIPERS: @@ -2064,6 +2129,28 @@ public virtual int GetDrawIndex() case CABViewControlTypes.ORTS_TCS46: case CABViewControlTypes.ORTS_TCS47: case CABViewControlTypes.ORTS_TCS48: + + // Jindrich + case CABViewControlTypes.ORTS_RESTRICTED_SPEED_ZONE_ACTIVE: + case CABViewControlTypes.ORTS_SELECTED_SPEED_MODE: + case CABViewControlTypes.ORTS_SELECTED_SPEED_REGULATOR_MODE: + case CABViewControlTypes.ORTS_SELECTED_SPEED_MAXIMUM_ACCELERATION: + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DISPLAY_UNITS: + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DISPLAY_TENS: + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DISPLAY_HUNDREDS: + case CABViewControlTypes.ORTS_TRAIN_LENGTH_METERS: + case CABViewControlTypes.ORTS_REMAINING_TRAIN_LENGHT_SPEED_RESTRICTED: + case CABViewControlTypes.ORTS_REMAINING_TRAIN_LENGTH_PERCENT: + case CABViewControlTypes.ORTS_MOTIVE_FORCE: + case CABViewControlTypes.ORTS_MOTIVE_FORCE_KILONEWTON: + case CABViewControlTypes.ORTS_MAXIMUM_FORCE: + case CABViewControlTypes.ORTS_SELECTED_SPEED: + case CABViewControlTypes.ORTS_FORCE_IN_PERCENT_THROTTLE_AND_DYNAMIC_BRAKE: + case CABViewControlTypes.ORTS_TRAIN_TYPE_PAX_OR_CARGO: + case CABViewControlTypes.ORTS_CONTROLLER_VOLTAGE: + case CABViewControlTypes.ORTS_AMPERS_BY_CONTROLLER_VOLTAGE: + case CABViewControlTypes.ORTS_CC_SELECT_SPEED: + index = (int)data; break; } @@ -2105,6 +2192,7 @@ public string GetControlLabel() /// /// Handles cabview mouse events, and changes the corresponding locomotive control values. /// + public void HandleUserInput() { switch (Control.ControlType) @@ -2130,7 +2218,7 @@ public void HandleUserInput() break; case CABViewControlTypes.PANTOGRAPH2: var p2 = Locomotive.UsingRearCab ? 1 : 2; - new PantographCommand(Viewer.Log, p2 , ChangedValue(Locomotive.Pantographs[p2].CommandUp ? 1 : 0) > 0); + new PantographCommand(Viewer.Log, p2, ChangedValue(Locomotive.Pantographs[p2].CommandUp ? 1 : 0) > 0); break; case CABViewControlTypes.ORTS_PANTOGRAPH3: var p3 = Locomotive.UsingRearCab && Locomotive.Pantographs.List.Count > 3 ? 4 : 3; @@ -2184,8 +2272,8 @@ public void HandleUserInput() case CABViewControlTypes.ORTS_OVERCHARGE: new BrakeOverchargeCommand(Viewer.Log, ChangedValue(Locomotive.TrainBrakeController.OverchargeButtonPressed ? 1 : 0) > 0); break; case CABViewControlTypes.RESET: new AlerterCommand(Viewer.Log, ChangedValue(Locomotive.TrainControlSystem.AlerterButtonPressed ? 1 : 0) > 0); break; case CABViewControlTypes.CP_HANDLE: Locomotive.SetCombinedHandleValue(ChangedValue(Locomotive.GetCombinedHandleValue(true))); break; - - // Steam locomotives only: + + // Steam locomotives only: case CABViewControlTypes.CUTOFF: (Locomotive as MSTSSteamLocomotive).SetCutoffValue(ChangedValue((Locomotive as MSTSSteamLocomotive).CutoffController.IntermediateValue)); break; case CABViewControlTypes.BLOWER: (Locomotive as MSTSSteamLocomotive).SetBlowerValue(ChangedValue((Locomotive as MSTSSteamLocomotive).BlowerController.IntermediateValue)); break; case CABViewControlTypes.DAMPERS_FRONT: (Locomotive as MSTSSteamLocomotive).SetDamperValue(ChangedValue((Locomotive as MSTSSteamLocomotive).DamperController.IntermediateValue)); break; @@ -2307,6 +2395,85 @@ public void HandleUserInput() new TCSButtonCommand(Viewer.Log, !Locomotive.TrainControlSystem.TCSCommandButtonDown[commandIndex], commandIndex); new TCSSwitchCommand(Viewer.Log, ChangedValue(Locomotive.TrainControlSystem.TCSCommandSwitchOn[commandIndex] ? 1 : 0) > 0, commandIndex); break; + + // Jindrich + case CABViewControlTypes.ORTS_CC_SELECT_SPEED: + if (Locomotive.CruiseControl == null) + break; + var p = ChangedValue(0); + if (p == 1) + { + Locomotive.CruiseControl.SetSpeed((float)Control.MaxValue); + Locomotive.SelectingSpeedPressed = true; + } + else if (p == 0) Locomotive.SelectingSpeedPressed = false; + break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_REGULATOR_MODE: + p = ChangedValue(0); + if (p == 1) + { + Locomotive.CruiseControl.SpeedRegulatorModeIncrease(); + } + else if (p == -1) + { + Locomotive.CruiseControl.SpeedRegulatorModeDecrease(); + } + break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_MODE: + p = ChangedValue(0); + if (p == 1) + { + Locomotive.CruiseControl.SpeedSelectorModeStartIncrease(); + } + else if (Locomotive.CruiseControl.SpeedSelMode == Simulation.RollingStocks.SubSystems.CruiseControl.SpeedSelectorMode.Start) + { + if (UserInput.IsMouseLeftButtonReleased) + { + Locomotive.CruiseControl.SpeedSelectorModeStopIncrease(); + } + } + else if (p == -1) + { + Locomotive.CruiseControl.SpeedSelectorModeDecrease(); + } + break; + case CABViewControlTypes.ORTS_RESTRICTED_SPEED_ZONE_ACTIVE: + if (ChangedValue(0) == 1) + { + Locomotive.CruiseControl.ActivateRestrictedSpeedZone(); + } + break; + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_INCREASE: + if (ChangedValue(0) == 1) + { + Locomotive.CruiseControl.NumerOfAxlesIncrease(); + } + break; + case CABViewControlTypes.ORTS_NUMBER_OF_AXES_DECREASE: + if (ChangedValue(0) == 1) + { + Locomotive.CruiseControl.NumberOfAxlesDecrease(); + } + break; + case CABViewControlTypes.ORTS_SELECTED_SPEED_MAXIMUM_ACCELERATION: + if (ChangedValue(0) == 1) + { + Locomotive.CruiseControl.SelectedMaxAccelerationStep += 1; + } + if (ChangedValue(0) == -1) + { + Locomotive.CruiseControl.SelectedMaxAccelerationStep -= 1; + } + if (ChangedValue(0) != 0) + { + Locomotive.CruiseControl.SelectedMaxAccelerationStep += ChangedValue(0) * (float)Control.MaxValue; + if (Locomotive.CruiseControl.SelectedMaxAccelerationStep > 100) + Locomotive.CruiseControl.SelectedMaxAccelerationStep = 100; + if (Locomotive.CruiseControl.SelectedMaxAccelerationStep < 0) + Locomotive.CruiseControl.SelectedMaxAccelerationStep = 0; + Locomotive.Simulator.Confirmer.Information("Selected maximum acceleration was changed to " + Math.Round(Locomotive.CruiseControl.SelectedMaxAccelerationStep, 0).ToString() + " percent"); + } + break; } } diff --git a/Source/RunActivity/Viewer3D/RollingStock/SubSystems/CruiseControlViewer.cs b/Source/RunActivity/Viewer3D/RollingStock/SubSystems/CruiseControlViewer.cs new file mode 100644 index 0000000000..bedd3fa1a3 --- /dev/null +++ b/Source/RunActivity/Viewer3D/RollingStock/SubSystems/CruiseControlViewer.cs @@ -0,0 +1,79 @@ +// COPYRIGHT 2015 by the Open Rails project. +// +// This file is part of Open Rails. +// +// Open Rails 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 of the License, or +// (at your option) any later version. +// +// Open Rails 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 Open Rails. If not, see . + +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using Orts.Simulation.RollingStocks; +using Orts.Simulation.RollingStocks.SubSystems; +using Orts.Viewer3D.RollingStock; +using ORTS.Common; +using ORTS.Common.Input; + +namespace Orts.Viewer3D.RollingStock.SubSystems +{ + public class CruiseControlViewer + { + MSTSLocomotiveViewer MSTSLocomotiveViewer; + MSTSLocomotive Locomotive; + CruiseControl CruiseControl; + public CruiseControlViewer(MSTSLocomotiveViewer locomotiveViewer, MSTSLocomotive locomotive, CruiseControl cruiseControl) + { + MSTSLocomotiveViewer = locomotiveViewer; + Locomotive = locomotive; + CruiseControl = cruiseControl; + } + + public void InitializeUserInputCommands() + { + var UserInputCommands = MSTSLocomotiveViewer.UserInputCommands; + var Noop = MSTSLocomotiveViewer.Noop; + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorMaxAccelerationDecrease, new Action[] { () => CruiseControl.SpeedRegulatorMaxForceStopDecrease(), () => CruiseControl.SpeedRegulatorMaxForceStartDecrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorMaxAccelerationIncrease, new Action[] { () => CruiseControl.SpeedRegulatorMaxForceStopIncrease(), () => CruiseControl.SpeedRegulatorMaxForceStartIncrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorModeDecrease, new Action[] { Noop, () => CruiseControl.SpeedRegulatorModeDecrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorModeIncrease, new Action[] { Noop, () => CruiseControl.SpeedRegulatorModeIncrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorSelectedSpeedDecrease, new Action[] { () => CruiseControl.SpeedRegulatorSelectedSpeedStopDecrease(), () => CruiseControl.SpeedRegulatorSelectedSpeedStartDecrease() }); + UserInputCommands.Add(UserCommand.ControlSpeedRegulatorSelectedSpeedIncrease, new Action[] { () => CruiseControl.SpeedRegulatorSelectedSpeedStopIncrease(), () => CruiseControl.SpeedRegulatorSelectedSpeedStartIncrease() }); + UserInputCommands.Add(UserCommand.ControlNumberOfAxlesDecrease, new Action[] { Noop, () => CruiseControl.NumberOfAxlesDecrease() }); + UserInputCommands.Add(UserCommand.ControlNumberOfAxlesIncrease, new Action[] { Noop, () => CruiseControl.NumerOfAxlesIncrease() }); + UserInputCommands.Add(UserCommand.ControlRestrictedSpeedZoneActive, new Action[] { Noop, () => CruiseControl.ActivateRestrictedSpeedZone() }); + UserInputCommands.Add(UserCommand.ControlCruiseControlModeIncrease, new Action[] { () => CruiseControl.SpeedSelectorModeStopIncrease(), () => CruiseControl.SpeedSelectorModeStartIncrease() }); + UserInputCommands.Add(UserCommand.ControlCruiseControlModeDecrease, new Action[] { Noop, () => CruiseControl.SpeedSelectorModeDecrease() }); + UserInputCommands.Add(UserCommand.ControlTrainTypePaxCargo, new Action[] { Noop, () => Locomotive.ChangeTrainTypePaxCargo() }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed10, new Action[] { Noop, () => CruiseControl.SetSpeed(10) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed20, new Action[] { Noop, () => CruiseControl.SetSpeed(20) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed30, new Action[] { Noop, () => CruiseControl.SetSpeed(30) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed40, new Action[] { Noop, () => CruiseControl.SetSpeed(40) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed50, new Action[] { Noop, () => CruiseControl.SetSpeed(50) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed60, new Action[] { Noop, () => CruiseControl.SetSpeed(60) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed70, new Action[] { Noop, () => CruiseControl.SetSpeed(70) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed80, new Action[] { Noop, () => CruiseControl.SetSpeed(80) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed90, new Action[] { Noop, () => CruiseControl.SetSpeed(90) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed100, new Action[] { Noop, () => CruiseControl.SetSpeed(100) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed110, new Action[] { Noop, () => CruiseControl.SetSpeed(110) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed120, new Action[] { Noop, () => CruiseControl.SetSpeed(120) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed130, new Action[] { Noop, () => CruiseControl.SetSpeed(130) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed140, new Action[] { Noop, () => CruiseControl.SetSpeed(140) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed150, new Action[] { Noop, () => CruiseControl.SetSpeed(150) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed160, new Action[] { Noop, () => CruiseControl.SetSpeed(160) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed170, new Action[] { Noop, () => CruiseControl.SetSpeed(170) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed180, new Action[] { Noop, () => CruiseControl.SetSpeed(180) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed190, new Action[] { Noop, () => CruiseControl.SetSpeed(190) }); + UserInputCommands.Add(UserCommand.ControlSelectSpeed200, new Action[] { Noop, () => CruiseControl.SetSpeed(200) }); + } + } +} diff --git a/Source/RunActivity/Viewer3D/Signals.cs b/Source/RunActivity/Viewer3D/Signals.cs index 1fc7b5a942..2ac80bac5c 100644 --- a/Source/RunActivity/Viewer3D/Signals.cs +++ b/Source/RunActivity/Viewer3D/Signals.cs @@ -466,9 +466,11 @@ public SignalTypeData(Viewer viewer, Orts.Formats.Msts.SignalType mstsSignalType if (mstsSignalType.Semaphore) glowDay = 0.0f; + /* Jindrich + * Why is this here? I want all my lights glowing, when I have glowing on if (mstsSignalType.FnType == MstsSignalFunction.INFO || mstsSignalType.FnType == MstsSignalFunction.SHUNTING) // These are good at identifying theatre boxes. glowDay = glowNight = 0.0f; - + */ // use values from signal if defined if (mstsSignalType.DayGlow.HasValue) {