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>Renders a graphical visualisation of any events within camera range</summary> /// <param name="Camera">The absolute camera position</param> private static void RenderEvents(Vector3 Camera) { if (Interface.CurrentOptions.ShowEvents == false || TrackManager.Tracks[0].Elements == null) { return; } if (!Initialized) { Init(); Initialized = true; } GL.Enable(EnableCap.CullFace); LibRender.Renderer.CullEnabled = true; GL.Enable(EnableCap.DepthTest); GL.DepthMask(true); if (LibRender.Renderer.LightingEnabled) { GL.Disable(EnableCap.Lighting); LibRender.Renderer.LightingEnabled = false; } if (LibRender.Renderer.AlphaTestEnabled) { GL.Disable(EnableCap.AlphaTest); LibRender.Renderer.AlphaTestEnabled = false; } double da = -World.BackwardViewingDistance - World.ExtraViewingDistance; double db = World.ForwardViewingDistance + World.ExtraViewingDistance; bool[] sta = new bool[CurrentRoute.Stations.Length]; // events for (int i = 0; i < TrackManager.Tracks[0].Elements.Length; i++) { double p = TrackManager.Tracks[0].Elements[i].StartingTrackPosition; double d = p - World.CameraTrackFollower.TrackPosition; if (d >= da & d <= db) { for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++) { dynamic e = TrackManager.Tracks[0].Elements[i].Events[j]; double dy, dx = 0.0, dz = 0.0; double s; Texture t; if (e is TrackManager.BrightnessChangeEvent) { s = 0.15; dy = 4.0; t = BrightnessChangeTexture; } else if (e is BackgroundChangeEvent) { s = 0.25; dy = 3.5; t = BackgroundChangeTexture; } else if (e is TrackManager.StationStartEvent) { s = 0.25; dy = 1.6; t = StationStartTexture; TrackManager.StationStartEvent f = (TrackManager.StationStartEvent)e; sta[f.StationIndex] = true; } else if (e is TrackManager.StationEndEvent) { s = 0.25; dy = 1.6; t = StationEndTexture; TrackManager.StationEndEvent f = (TrackManager.StationEndEvent)e; sta[f.StationIndex] = true; } else if (e is TrackManager.LimitChangeEvent) { s = 0.2; dy = 1.1; t = LimitTexture; } else if (e is TrackManager.SectionChangeEvent) { s = 0.2; dy = 0.8; t = SectionTexture; } else if (e is TrackManager.TransponderEvent) { s = 0.15; dy = 0.4; t = TransponderTexture; } else if (e is TrackManager.SoundEvent) { TrackManager.SoundEvent f = (TrackManager.SoundEvent)e; s = 0.2; dx = f.Position.X; dy = f.Position.Y < 0.1 ? 0.1 : f.Position.Y; dz = f.Position.Z; t = SoundTexture; } else if (e is TrackManager.PointSoundEvent) { s = 0.2; dx = 0; dy = 0.2; dz = 0; t = PointSoundTexture; } else { s = 0.2; dy = 1.0; t = null; } if (t != null) { TrackManager.TrackFollower f = new TrackManager.TrackFollower(); f.TriggerType = EventTriggerType.None; f.TrackPosition = p; f.Update(p + e.TrackPositionDelta, true, false); f.WorldPosition.X += dx * f.WorldSide.X + dy * f.WorldUp.X + dz * f.WorldDirection.X; f.WorldPosition.Y += dx * f.WorldSide.Y + dy * f.WorldUp.Y + dz * f.WorldDirection.Y; f.WorldPosition.Z += dx * f.WorldSide.Z + dy * f.WorldUp.Z + dz * f.WorldDirection.Z; LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, t); } } } } // stops for (int i = 0; i < sta.Length; i++) { if (sta[i]) { for (int j = 0; j < CurrentRoute.Stations[i].Stops.Length; j++) { const double dy = 1.4; const double s = 0.2; double p = CurrentRoute.Stations[i].Stops[j].TrackPosition; TrackManager.TrackFollower f = new TrackManager.TrackFollower(); f.TriggerType = EventTriggerType.None; f.TrackPosition = p; f.Update(p, true, false); f.WorldPosition.X += dy * f.WorldUp.X; f.WorldPosition.Y += dy * f.WorldUp.Y; f.WorldPosition.Z += dy * f.WorldUp.Z; LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, StopTexture); } } } // buffers for (int i = 0; i < Game.BufferTrackPositions.Length; i++) { double p = Game.BufferTrackPositions[i]; double d = p - World.CameraTrackFollower.TrackPosition; if (d >= da & d <= db) { const double dy = 2.5; const double s = 0.25; TrackManager.TrackFollower f = new TrackManager.TrackFollower(); f.TriggerType = EventTriggerType.None; f.TrackPosition = p; f.Update(p, true, false); f.WorldPosition.X += dy * f.WorldUp.X; f.WorldPosition.Y += dy * f.WorldUp.Y; f.WorldPosition.Z += dy * f.WorldUp.Z; LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, BufferTexture); } } }