/// <summary>Returns the track distance to the nearest car of the selected train</summary> /// <param name="Train">The selected train</param> /// <param name="TrackPosition">The object's track position</param> /// <returns>The distance to the object</returns> public static double trackDistance(TrainManager.Train Train, double TrackPosition) { if (Train == null) { return(0.0); } double t0 = Train.FrontCarTrackPosition(); double t1 = Train.RearCarTrackPosition(); return(TrackPosition > t0 ? TrackPosition - t0 : TrackPosition < t1 ? TrackPosition - t1 : 0.0); }
private void PerformDefault() { if (Train.Derailed) { if (Train.Handles.EmergencyBrake.Driver != true) { Train.ApplyEmergencyBrake(); } return; } // personality double spd = Train.CurrentSpeed; if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Boarding) { if (Train.Station != this.LastStation) { this.LastStation = Train.Station; double time; if (Stations[Train.Station].ArrivalTime >= 0.0) { time = Stations[Train.Station].ArrivalTime - Train.TimetableDelta; } else if (Stations[Train.Station].DepartureTime >= 0.0) { time = Stations[Train.Station].DepartureTime - Train.TimetableDelta; if (time > SecondsSinceMidnight) { time -= Stations[Train.Station].StopTime; if (time > SecondsSinceMidnight) { time = double.MinValue; } } } else { time = double.MinValue; } if (time != double.MinValue) { const double largeThreshold = 30.0; const double largeChangeFactor = 0.0025; const double smallThreshold = 15.0; const double smallChange = 0.05; double diff = SecondsSinceMidnight - time; if (diff < -largeThreshold) { /* The AI is too fast. Decrease the preferred speed. */ this.CurrentSpeedFactor -= largeChangeFactor * (-diff - largeThreshold); if (this.CurrentSpeedFactor < 0.7) { this.CurrentSpeedFactor = 0.7; } } else if (diff > largeThreshold) { /* The AI is too slow. Increase the preferred speed. */ this.CurrentSpeedFactor += largeChangeFactor * (diff - largeThreshold); if (this.CurrentSpeedFactor > 1.1) { this.CurrentSpeedFactor = 1.1; } } else if (Math.Abs(diff) < smallThreshold) { /* The AI is at about the right speed. Change the preferred speed toward the personality default. */ if (this.CurrentSpeedFactor < this.PersonalitySpeedFactor) { this.CurrentSpeedFactor += smallChange; if (this.CurrentSpeedFactor > this.PersonalitySpeedFactor) { this.CurrentSpeedFactor = this.PersonalitySpeedFactor; } } else if (this.CurrentSpeedFactor > this.PersonalitySpeedFactor) { this.CurrentSpeedFactor -= smallChange; if (this.CurrentSpeedFactor < this.PersonalitySpeedFactor) { this.CurrentSpeedFactor = this.PersonalitySpeedFactor; } } } } } } // door states bool doorsopen = false; for (int i = 0; i < Train.Cars.Length; i++) { for (int j = 0; j < Train.Cars[i].Doors.Length; j++) { if (Train.Cars[i].Doors[j].State != 0.0) { doorsopen = true; break; } if (doorsopen) { break; } } } // do the ai Train.Specs.CurrentConstSpeed = false; Train.ApplyHoldBrake(false); int stopIndex = Train.Station >= 0 ? Game.Stations[Train.Station].GetStopIndex(Train.Cars.Length) : -1; if (Train.CurrentSectionLimit == 0.0) { // passing red signal Train.ApplyEmergencyBrake(); Train.ApplyNotch(-1, true, 1, true); CurrentInterval = 0.5; } else if (doorsopen | Train.StationState == TrainManager.TrainStopState.Boarding) { // door opened or boarding at station this.PowerNotchAtWhichWheelSlipIsObserved = Train.Handles.Power.MaximumNotch + 1; if (Train.Station >= 0 && Stations[Train.Station].Type != StationType.Normal && Stations[Train.Station].Type != StationType.RequestStop && Train == TrainManager.PlayerTrain) { // player's terminal station if (Train.Plugin == null || Train.Plugin.LastReverser == -2) { Train.ApplyReverser(0, false); } Train.ApplyNotch(-1, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); Train.ApplyEmergencyBrake(); CurrentInterval = 1.0; } else { CurrentInterval = 1.0; Train.ApplyNotch(-1, true, 0, true); if (Train.Handles.Brake is TrainManager.AirBrakeHandle) { if (Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.CurrentPressure < 0.3 * Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.ServiceMaximumPressure) { Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); } else if (Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.CurrentPressure > 0.9 * Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.EmergencyMaximumPressure) { Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); } else { Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Lap); } } else { int b; if (Math.Abs(spd) < 0.02) { b = (int)Math.Ceiling(0.5 * (double)Train.Handles.Brake.MaximumNotch); CurrentInterval = 0.3; } else { b = Train.Handles.Brake.MaximumNotch; } if (Train.Handles.Brake.Driver < b) { Train.ApplyNotch(0, true, 1, true); } else if (Train.Handles.Brake.Driver > b) { Train.ApplyNotch(0, true, -1, true); } } Train.UnapplyEmergencyBrake(); if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Completed) { // ready for departure - close doors if (Train.Specs.DoorOpenMode != TrainManager.DoorMode.Automatic && Train.Specs.DoorInterlockState == DoorInterlockStates.Unlocked) { TrainManager.CloseTrainDoors(Train, true, true); } } else if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Boarding) { } else { // not at station - close doors if (Train.Specs.DoorOpenMode != TrainManager.DoorMode.Automatic && Train.Specs.DoorInterlockState == DoorInterlockStates.Unlocked) { TrainManager.CloseTrainDoors(Train, true, true); } } } } else if (Train.Station >= 0 && stopIndex >= 0 && Train.StationDistanceToStopPoint < Stations[Train.Station].Stops[stopIndex].BackwardTolerance && (StopsAtStation(Train.Station, Train) & (Stations[Train.Station].OpenLeftDoors | Stations[Train.Station].OpenRightDoors) & Math.Abs(Train.CurrentSpeed) < 0.25 & Train.StationState == TrainManager.TrainStopState.Pending)) { // arrived at station - open doors if (Train.Specs.DoorOpenMode != TrainManager.DoorMode.Automatic && Train.Specs.DoorInterlockState == DoorInterlockStates.Unlocked) { TrainManager.OpenTrainDoors(Train, Stations[Train.Station].OpenLeftDoors, Stations[Train.Station].OpenRightDoors); } CurrentInterval = 1.0; } else if (Train.Station >= 0 && stopIndex >= 0 && Stations[Train.Station].Type != StationType.Normal && Stations[Train.Station].Type != StationType.RequestStop && Train == TrainManager.PlayerTrain && Train.StationDistanceToStopPoint < Stations[Train.Station].Stops[stopIndex].BackwardTolerance && -Train.StationDistanceToStopPoint < Stations[Train.Station].Stops[stopIndex].ForwardTolerance && Math.Abs(Train.CurrentSpeed) < 0.25) { // player's terminal station (not boarding any longer) if (Train.Plugin != null || Train.Plugin.LastReverser == -2) { Train.ApplyReverser(0, false); } Train.ApplyNotch(-1, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); Train.ApplyEmergencyBrake(); CurrentInterval = 10.0; } else { // drive Train.ApplyReverser(1, false); if (Train.Cars[Train.DriverCar].FrontAxle.CurrentWheelSlip | Train.Cars[Train.DriverCar].RearAxle.CurrentWheelSlip) { // react to wheel slip if (Train.Handles.Power.Driver > 1) { this.PowerNotchAtWhichWheelSlipIsObserved = Train.Handles.Power.Driver; Train.ApplyNotch(-1, true, -1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); this.CurrentInterval = 2.5; return; } } // initialize double acc = Train.Specs.CurrentAverageAcceleration; double lim = PrecedingTrainSpeedLimit * 1.2; if (Train.CurrentRouteLimit < lim) { lim = Train.CurrentRouteLimit; } if (Train.CurrentSectionLimit < lim) { lim = Train.CurrentSectionLimit; } double powerstart, powerend, brakestart; if (double.IsPositiveInfinity(lim)) { powerstart = lim; powerend = lim; brakestart = lim; } else { lim *= this.CurrentSpeedFactor; if (spd < 8.0) { powerstart = 0.75 * lim; powerend = 0.95 * lim; } else { powerstart = lim - 2.5; powerend = lim - 1.5; } if (this.BrakeMode) { brakestart = powerend; } else { brakestart = lim + 0.5; } } double dec = 0.0; double decelerationCruise; /* power below this deceleration, cruise above */ double decelerationStart; /* brake above this deceleration, cruise below */ double decelerationStep; /* the deceleration step per brake notch */ double BrakeDeceleration = Train.Cars[Train.DriverCar].CarBrake.DecelerationAtServiceMaximumPressure(Train.Handles.Brake.Actual, Train.Cars[Train.DriverCar].Specs.CurrentSpeed); for (int i = 0; i < Train.Cars.Length; i++) { if (Train.Cars[i].Specs.IsMotorCar) { if (Train.Cars[Train.DriverCar].Specs.MotorDeceleration != 0 && Train.Cars[Train.DriverCar].Specs.MotorDeceleration < BrakeDeceleration) { BrakeDeceleration = Train.Cars[Train.DriverCar].Specs.MotorDeceleration; } break; } } if (Train.Handles.Brake is TrainManager.AirBrakeHandle | Train.Handles.Brake.MaximumNotch <= 0) { decelerationCruise = 0.3 * BrakeDeceleration; decelerationStart = 0.5 * BrakeDeceleration; decelerationStep = 0.1 * BrakeDeceleration; } else if (Train.Handles.Brake.MaximumNotch <= 2) { decelerationCruise = 0.2 * BrakeDeceleration; decelerationStart = 0.4 * BrakeDeceleration; decelerationStep = 0.5 * BrakeDeceleration; } else { decelerationCruise = 0.2 * BrakeDeceleration; decelerationStart = 0.5 * BrakeDeceleration; decelerationStep = BrakeDeceleration / (double)Train.Handles.Brake.MaximumNotch; } if (this.CurrentSpeedFactor >= 1.0) { decelerationCruise *= 1.25; decelerationStart *= 1.25; decelerationStep *= 1.25; } if (spd > 0.0 & spd > brakestart) { dec = decelerationStep + 0.1 * (spd - brakestart); } bool reduceDecelerationCruiseAndStart = false; // look ahead double lookahead = (Train.Station >= 0 ? 150.0 : 50.0) + (spd * spd) / (2.0 * decelerationCruise); double tp = Train.FrontCarTrackPosition(); double stopDistance = double.MaxValue; { // next station stop int te = Train.Cars[0].FrontAxle.Follower.LastTrackElement; for (int i = te; i < TrackManager.Tracks[0].Elements.Length; i++) { double stp = TrackManager.Tracks[0].Elements[i].StartingTrackPosition; if (tp + lookahead <= stp) { break; } for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++) { if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationStartEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.None) { TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.Tracks[0].Elements[i].Events[j]; if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex) { int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length); if (s >= 0) { double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp; if (dist > 0.0 & dist < stopDistance) { stopDistance = dist; } } } } } } } { // events int te = Train.Cars[0].FrontAxle.Follower.LastTrackElement; for (int i = te; i < TrackManager.Tracks[0].Elements.Length; i++) { double stp = TrackManager.Tracks[0].Elements[i].StartingTrackPosition; if (tp + lookahead <= stp) { break; } for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++) { if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.LimitChangeEvent) { // speed limit TrackManager.LimitChangeEvent e = (TrackManager.LimitChangeEvent)TrackManager.Tracks[0].Elements[i].Events[j]; if (e.NextSpeedLimit < spd) { double dist = stp + e.TrackPositionDelta - tp; double edec = (spd * spd - e.NextSpeedLimit * e.NextSpeedLimit * this.CurrentSpeedFactor) / (2.0 * dist); if (edec > dec) { dec = edec; } } } else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.SectionChangeEvent) { // section TrackManager.SectionChangeEvent e = (TrackManager.SectionChangeEvent)TrackManager.Tracks[0].Elements[i].Events[j]; if (stp + e.TrackPositionDelta > tp) { if (!CurrentRoute.Sections[e.NextSectionIndex].Invisible & CurrentRoute.Sections[e.NextSectionIndex].CurrentAspect >= 0) { double elim = CurrentRoute.Sections[e.NextSectionIndex].Aspects[CurrentRoute.Sections[e.NextSectionIndex].CurrentAspect].Speed * this.CurrentSpeedFactor; if (elim < spd | spd <= 0.0) { double dist = stp + e.TrackPositionDelta - tp; double edec; if (elim == 0.0) { double redstopdist; if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Completed & dist < 120.0) { dist = 1.0; redstopdist = 25.0; } else if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Pending | stopDistance < dist) { redstopdist = 1.0; } else if (spd > 9.72222222222222) { redstopdist = 55.0; } else { redstopdist = 35.0; } if (dist > redstopdist) { edec = (spd * spd) / (2.0 * (dist - redstopdist)); } else { edec = BrakeDeceleration; } if (dist < 100.0) { reduceDecelerationCruiseAndStart = true; } } else { if (dist >= 1.0) { edec = (spd * spd - elim * elim) / (2.0 * dist); } else { edec = 0.0; } } if (edec > dec) { dec = edec; } } } } } else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationStartEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.None) { // station start if (Train.Station == -1) { TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.Tracks[0].Elements[i].Events[j]; if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex) { int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length); if (s >= 0) { double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp; if (dist > -Stations[e.StationIndex].Stops[s].ForwardTolerance) { if (dist < 25.0) { reduceDecelerationCruiseAndStart = true; } else if (this.CurrentSpeedFactor < 1.0) { dist -= 5.0; } var edec = spd * spd / (2.0 * dist); if (edec > dec) { dec = edec; } } } } } } else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationStartEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.Decelerate) { // Brakes the train when passing through a request stop, which is not to be passed at linespeed if (Train.Station == -1) { TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.Tracks[0].Elements[i].Events[j]; if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex) { int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length); if (s >= 0) { double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp; if (dist > -Stations[e.StationIndex].Stops[s].ForwardTolerance) { if (dist < 25.0) { reduceDecelerationCruiseAndStart = true; } else if (this.CurrentSpeedFactor < 1.0) { dist -= 5.0; } if (dist > 25) { var edec = spd * spd / (2.0 * dist); if (edec > dec) { dec = edec; } } } } } } } else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationEndEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.None) { // station end if (Train.Station == -1) { TrackManager.StationEndEvent e = (TrackManager.StationEndEvent)TrackManager.Tracks[0].Elements[i].Events[j]; if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex) { int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length); if (s >= 0) { double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp; if (dist > -Stations[e.StationIndex].Stops[s].ForwardTolerance) { if (dist < 25.0) { reduceDecelerationCruiseAndStart = true; } else if (this.CurrentSpeedFactor < 1.0) { dist -= 5.0; } var edec = spd * spd / (2.0 * dist); if (edec > dec) { dec = edec; } } } } } } else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.TrackEndEvent) { // track end if (Train == TrainManager.PlayerTrain) { TrackManager.TrackEndEvent e = (TrackManager.TrackEndEvent)TrackManager.Tracks[0].Elements[i].Events[j]; double dist = stp + e.TrackPositionDelta - tp; double edec; if (dist >= 15.0) { edec = spd * spd / (2.0 * dist); } else { edec = BrakeDeceleration; } if (edec > dec) { dec = edec; } } } } } } // buffers ahead if (Train == TrainManager.PlayerTrain) { for (int i = 0; i < BufferTrackPositions.Length; i++) { double dist = BufferTrackPositions[i] - tp; if (dist > 0.0) { double edec; if (dist >= 10.0) { edec = spd * spd / (2.0 * dist); } else if (dist >= 5.0) { Train.ApplyNotch(-1, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); this.CurrentInterval = 0.1; return; } else { Train.ApplyNotch(-1, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); Train.ApplyEmergencyBrake(); this.CurrentInterval = 10.0; return; } if (edec > dec) { dec = edec; } } } } // trains ahead for (int i = 0; i < TrainManager.Trains.Length; i++) { if (TrainManager.Trains[i] != Train && TrainManager.Trains[i].State == TrainState.Available) { double pos = TrainManager.Trains[i].Cars[TrainManager.Trains[i].Cars.Length - 1].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[TrainManager.Trains[i].Cars.Length - 1].RearAxle.Position - 0.5 * TrainManager.Trains[i].Cars[TrainManager.Trains[i].Cars.Length - 1].Length; double dist = pos - tp; if (dist > -10.0 & dist < lookahead) { const double minDistance = 10.0; const double maxDistance = 100.0; double edec; if (dist > minDistance) { double shift = 0.75 * minDistance + 1.0 * spd; edec = spd * spd / (2.0 * (dist - shift)); } else if (dist > 0.5 * minDistance) { Train.ApplyNotch(-1, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); this.CurrentInterval = 0.1; return; } else { Train.ApplyNotch(-1, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); Train.ApplyEmergencyBrake(); this.CurrentInterval = 1.0; return; } if (dist < maxDistance) { reduceDecelerationCruiseAndStart = true; } if (edec > dec) { dec = edec; } } } } Train.UnapplyEmergencyBrake(); // current station if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Pending) { if (StopsAtStation(Train.Station, Train)) { int s = Game.Stations[Train.Station].GetStopIndex(Train.Cars.Length); if (s >= 0) { double dist = Stations[Train.Station].Stops[s].TrackPosition - tp; if (dist > 0.0) { if (dist < 25.0) { reduceDecelerationCruiseAndStart = true; } else if (this.CurrentSpeedFactor < 1.0) { dist -= 5.0; } var edec = spd * spd / (2.0 * dist); if (edec > dec) { dec = edec; } } else { dec = BrakeDeceleration; } } } } // power / brake if (reduceDecelerationCruiseAndStart) { decelerationCruise *= 0.3; decelerationStart *= 0.3; } double brakeModeBrakeThreshold = 0.75 * decelerationStart + 0.25 * decelerationCruise; if (!BrakeMode & dec > decelerationStart | BrakeMode & dec > brakeModeBrakeThreshold | false) { // brake BrakeMode = true; double decdiff = -acc - dec; if (decdiff < -decelerationStep) { // brake start if (Train.Handles.Power.Driver == 0) { Train.ApplyNotch(0, true, 1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service); } else { Train.ApplyNotch(-1, true, 0, true); } CurrentInterval *= 0.4; if (CurrentInterval < 0.3) { CurrentInterval = 0.3; } } else if (decdiff > decelerationStep) { // brake stop Train.ApplyNotch(-1, true, -1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); CurrentInterval *= 0.4; if (CurrentInterval < 0.3) { CurrentInterval = 0.3; } } else { // keep brake Train.ApplyNotch(-1, true, 0, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Lap); CurrentInterval *= 1.2; if (CurrentInterval > 1.0) { CurrentInterval = 1.0; } } if (Train.Handles.Power.Driver == 0 & Train.Handles.Brake.Driver == 0) { Train.ApplyHoldBrake(Train.Handles.HasHoldBrake); } if (Train.Handles.Brake is TrainManager.AirBrakeHandle) { CurrentInterval = 0.1; } } else if (dec > decelerationCruise) { // cut power/brake BrakeMode = false; Train.ApplyNotch(-1, true, -1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); if (Train.Handles.Power.Driver == 0 & Train.Handles.Brake.Driver == 0) { Train.ApplyHoldBrake(Train.Handles.HasHoldBrake); } CurrentInterval *= 0.4; if (CurrentInterval < 0.3) { CurrentInterval = 0.3; } } else { // power BrakeMode = false; double acclim; if (!double.IsInfinity(lim)) { double d = lim - spd; if (d > 0.0) { acclim = 0.1 / (0.1 * d + 1.0) - 0.12; } else { acclim = -1.0; } } else { acclim = -1.0; } if (spd < powerstart) { // power start (under-speed) if (Train.Handles.Brake.Driver == 0) { if (Train.Handles.Power.Driver < this.PowerNotchAtWhichWheelSlipIsObserved - 1) { Train.ApplyNotch(1, true, 0, true); } } else { Train.ApplyNotch(0, true, -1, true); } Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); if (double.IsPositiveInfinity(powerstart)) { CurrentInterval = 0.3 + 0.1 * Train.Handles.Power.Driver; } else { double p = (double)Train.Handles.Power.Driver / (double)Train.Handles.Power.MaximumNotch; CurrentInterval = 0.3 + 15.0 * p / (powerstart - spd + 1.0); } if (CurrentInterval > 1.3) { CurrentInterval = 1.3; } } else if (spd > powerend) { // power end (over-speed) Train.ApplyNotch(-1, true, -1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); CurrentInterval *= 0.3; if (CurrentInterval < 0.2) { CurrentInterval = 0.2; } } else if (acc < acclim) { // power start (under-acceleration) if (Train.Handles.Brake.Driver == 0) { if (Train.Handles.Power.Driver < this.PowerNotchAtWhichWheelSlipIsObserved - 1) { if (Train.Handles.Power.Driver == Train.Handles.Power.Actual) { Train.ApplyNotch(1, true, 0, true); } } } else { Train.ApplyNotch(0, true, -1, true); } Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); CurrentInterval = 1.3; } else { // keep power Train.ApplyNotch(0, true, -1, true); Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release); if (Train.Handles.Power.Driver != 0) { Train.Specs.CurrentConstSpeed = Train.Specs.HasConstSpeed; } if (Train.Handles.Power.Driver == 0 & Train.Handles.Brake.Driver == 0) { Train.ApplyHoldBrake(Train.Handles.HasHoldBrake); } CurrentInterval *= 1.1; if (CurrentInterval > 1.5) { CurrentInterval = 1.5; } } } } }
/// <summary>Updates the specified signal section</summary> /// <param name="SectionIndex">The index of the section to update</param> internal static void UpdateSection(int SectionIndex) { if (SectionIndex >= CurrentRoute.Sections.Length || CurrentRoute.Sections == null) { return; } // preparations int zeroaspect; bool settored = false; if (CurrentRoute.Sections[SectionIndex].Type == SectionType.ValueBased) { // value-based zeroaspect = 0; for (int i = 1; i < CurrentRoute.Sections[SectionIndex].Aspects.Length; i++) { if (CurrentRoute.Sections[SectionIndex].Aspects[i].Number < CurrentRoute.Sections[SectionIndex].Aspects[zeroaspect].Number) { zeroaspect = i; } } } else { // index-based zeroaspect = 0; } // hold station departure signal at red int d = CurrentRoute.Sections[SectionIndex].StationIndex; if (d >= 0) { // look for train in previous blocks int l = CurrentRoute.Sections[SectionIndex].PreviousSection; TrainManager.Train train = null; while (true) { if (l >= 0) { train = (TrainManager.Train)CurrentRoute.Sections[l].GetFirstTrain(false); if (train != null) { break; } l = CurrentRoute.Sections[l].PreviousSection; } else { break; } } if (train == null) { double b = -double.MaxValue; for (int i = 0; i < TrainManager.Trains.Length; i++) { if (TrainManager.Trains[i].State == TrainState.Available) { if (TrainManager.Trains[i].TimetableDelta > b) { b = TrainManager.Trains[i].TimetableDelta; train = TrainManager.Trains[i]; } } } } // set to red where applicable if (train != null) { if (!CurrentRoute.Sections[SectionIndex].TrainReachedStopPoint) { if (train.Station == d) { int c = Game.Stations[d].GetStopIndex(train.Cars.Length); if (c >= 0) { double p0 = train.FrontCarTrackPosition(); double p1 = Stations[d].Stops[c].TrackPosition - Stations[d].Stops[c].BackwardTolerance; if (p0 >= p1) { CurrentRoute.Sections[SectionIndex].TrainReachedStopPoint = true; } } else { CurrentRoute.Sections[SectionIndex].TrainReachedStopPoint = true; } } } double t = -15.0; if (Stations[d].DepartureTime >= 0.0) { t = Stations[d].DepartureTime - 15.0; } else if (Stations[d].ArrivalTime >= 0.0) { t = Stations[d].ArrivalTime; } if (train == TrainManager.PlayerTrain & Stations[d].Type != StationType.Normal & Stations[d].DepartureTime < 0.0) { settored = true; } else if (t >= 0.0 & SecondsSinceMidnight < t - train.TimetableDelta) { settored = true; } else if (!CurrentRoute.Sections[SectionIndex].TrainReachedStopPoint) { settored = true; } } else if (Stations[d].Type != StationType.Normal) { settored = true; } } // train in block if (!CurrentRoute.Sections[SectionIndex].IsFree()) { settored = true; } // free sections int newaspect = -1; if (settored) { CurrentRoute.Sections[SectionIndex].FreeSections = 0; newaspect = zeroaspect; } else { int n = CurrentRoute.Sections[SectionIndex].NextSection; if (n >= 0) { if (CurrentRoute.Sections[n].FreeSections == -1) { CurrentRoute.Sections[SectionIndex].FreeSections = -1; } else { CurrentRoute.Sections[SectionIndex].FreeSections = CurrentRoute.Sections[n].FreeSections + 1; } } else { CurrentRoute.Sections[SectionIndex].FreeSections = -1; } } // change aspect if (newaspect == -1) { if (CurrentRoute.Sections[SectionIndex].Type == SectionType.ValueBased) { // value-based int n = CurrentRoute.Sections[SectionIndex].NextSection; int a = CurrentRoute.Sections[SectionIndex].Aspects[CurrentRoute.Sections[SectionIndex].Aspects.Length - 1].Number; if (n >= 0 && CurrentRoute.Sections[n].CurrentAspect >= 0) { a = CurrentRoute.Sections[n].Aspects[CurrentRoute.Sections[n].CurrentAspect].Number; } for (int i = CurrentRoute.Sections[SectionIndex].Aspects.Length - 1; i >= 0; i--) { if (CurrentRoute.Sections[SectionIndex].Aspects[i].Number > a) { newaspect = i; } } if (newaspect == -1) { newaspect = CurrentRoute.Sections[SectionIndex].Aspects.Length - 1; } } else { // index-based if (CurrentRoute.Sections[SectionIndex].FreeSections >= 0 & CurrentRoute.Sections[SectionIndex].FreeSections < CurrentRoute.Sections[SectionIndex].Aspects.Length) { newaspect = CurrentRoute.Sections[SectionIndex].FreeSections; } else { newaspect = CurrentRoute.Sections[SectionIndex].Aspects.Length - 1; } } } // apply new aspect CurrentRoute.Sections[SectionIndex].CurrentAspect = newaspect; // update previous section if (CurrentRoute.Sections[SectionIndex].PreviousSection >= 0) { UpdateSection(CurrentRoute.Sections[SectionIndex].PreviousSection); } }