/// <summary> /// 1フレームごとに呼び出される関数 /// </summary> /// <param name="data">The data.</param> /// <param name="blocking">保安装置がブロックされているか、後続の保安装置をブロックするかどうか。</param> internal override void Elapse(ElapseData data, ref bool blocking) { CalcAccel(data.Vehicle.Speed.KilometersPerHour, data.ElapsedTime.Seconds); CalcEmaAccel(); }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- if (this.State == States.Suppressed) { if (data.Handles.BrakeNotch <= this.Train.Specs.BrakeNotches) { this.AlarmCountdown = DurationOfInitialization; this.State = States.Initializing; } } if (this.State == States.Initializing) { this.AlarmCountdown -= data.ElapsedTime.Seconds; if (this.AlarmCountdown <= 0.0) { this.State = States.Chime; } else { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches + 1; this.Train.Sounds.AtsBell.Play(); } } if (blocking) { if (this.State != States.Disabled & this.State != States.Suppressed) { this.State = States.Normal; } } else { if (this.State == States.Chime) { this.Train.Sounds.AtsChime.Play(); } else if (this.State == States.Alarm) { this.Train.Sounds.AtsBell.Play(); this.AlarmCountdown -= data.ElapsedTime.Seconds; if (this.AlarmCountdown <= 0.0) { this.State = States.Emergency; } } else if (this.State == States.Emergency) { this.Train.Sounds.AtsBell.Play(); data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches + 1; } if (this.SpeedCheckCountdown > 0.0 & data.ElapsedTime.Seconds > 0.0) { this.SpeedCheckCountdown -= data.ElapsedTime.Seconds; } if (this.CompatibilityDistanceAccumulator != 0.0) { this.CompatibilityDistanceAccumulator += data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; if (this.CompatibilityDistanceAccumulator > 27.7) { this.CompatibilityDistanceAccumulator = 0.0; } } if (this.State != States.Disabled & (this.Train.Doors != DoorStates.None | data.Handles.BrakeNotch > 0)) { data.Handles.PowerNotch = 0; } } // --- panel --- if ((this.State == States.Chime | this.State == States.Normal) & !blocking) { this.Train.Panel[256] = 1; } if (this.State == States.Initializing | this.State == States.Alarm) { this.Train.Panel[257] = 1; this.Train.Panel[258] = 1; } else if (this.State == States.Emergency) { int value = (int)data.TotalTime.Milliseconds % 1000 < 500 ? 1 : 0; this.Train.Panel[257] = 2; this.Train.Panel[258] = value; } }
/// <summary> /// The function what notify to the plugin that the train existing status /// </summary> /// <param name="data">Data</param> public void SetElapseData(ElapseData data) { }
/// <summary>Is called every frame.</summary> /// <param name="data">The data passed to the plugin.</param> public void Elapse(ElapseData data) { this.Train.Elapse(data); }
/// <summary>Called every frame to update the plugin.</summary> internal void UpdatePlugin() { if (Train.Cars == null || Train.Cars.Length == 0) { return; } /* * Prepare the vehicle state. * */ double location = this.Train.Cars[0].FrontAxle.Follower.TrackPosition - this.Train.Cars[0].FrontAxle.Position + 0.5 * this.Train.Cars[0].Length; //Curve Radius, Cant and Pitch Added double CurrentRadius = this.Train.Cars[0].FrontAxle.Follower.CurveRadius; double CurrentCant = this.Train.Cars[0].FrontAxle.Follower.CurveCant; double CurrentPitch = this.Train.Cars[0].FrontAxle.Follower.Pitch; //If the list of stations has not been loaded, do so if (!StationsLoaded) { currentRouteStations = new List <Station>(); int s = 0; foreach (RouteStation selectedStation in Game.Stations) { double stopPosition = -1; int stopIdx = Game.Stations[s].GetStopIndex(Train.Cars.Length); if (selectedStation.Stops.Length != 0) { stopPosition = selectedStation.Stops[stopIdx].TrackPosition; } Station i = new Station(selectedStation, stopPosition); currentRouteStations.Add(i); s++; } StationsLoaded = true; } //End of additions double speed = this.Train.Cars[this.Train.DriverCar].Specs.CurrentPerceivedSpeed; double bcPressure = this.Train.Cars[this.Train.DriverCar].CarBrake.brakeCylinder.CurrentPressure; double mrPressure = this.Train.Cars[this.Train.DriverCar].CarBrake.mainReservoir.CurrentPressure; double erPressure = this.Train.Cars[this.Train.DriverCar].CarBrake.equalizingReservoir.CurrentPressure; double bpPressure = this.Train.Cars[this.Train.DriverCar].CarBrake.brakePipe.CurrentPressure; double sapPressure = this.Train.Cars[this.Train.DriverCar].CarBrake.straightAirPipe.CurrentPressure; VehicleState vehicle = new VehicleState(location, new Speed(speed), bcPressure, mrPressure, erPressure, bpPressure, sapPressure, CurrentRadius, CurrentCant, CurrentPitch); /* * Prepare the preceding vehicle state. * */ double bestLocation = double.MaxValue; double bestSpeed = 0.0; PrecedingVehicleState precedingVehicle; try { for (int i = 0; i < TrainManager.Trains.Length; i++) { if (TrainManager.Trains[i] != this.Train & TrainManager.Trains[i].State == TrainState.Available & Train.Cars.Length > 0) { int c = TrainManager.Trains[i].Cars.Length - 1; double z = TrainManager.Trains[i].Cars[c].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[c].RearAxle.Position - 0.5 * TrainManager.Trains[i].Cars[c].Length; if (z >= location & z < bestLocation) { bestLocation = z; bestSpeed = TrainManager.Trains[i].CurrentSpeed; } } } precedingVehicle = bestLocation != double.MaxValue ? new PrecedingVehicleState(bestLocation, bestLocation - location, new Speed(bestSpeed)) : null; } catch { precedingVehicle = null; } /* * Get the driver handles. * */ Handles handles = GetHandles(); /* * Update the plugin. * */ double totalTime = Game.SecondsSinceMidnight; double elapsedTime = Game.SecondsSinceMidnight - LastTime; ElapseData data = new ElapseData(vehicle, precedingVehicle, handles, this.Train.Specs.DoorInterlockState, new Time(totalTime), new Time(elapsedTime), currentRouteStations, Camera.CurrentMode, Translations.CurrentLanguageCode, this.Train.Destination); ElapseData inputDevicePluginData = data; LastTime = Game.SecondsSinceMidnight; Elapse(data); this.PluginMessage = data.DebugMessage; this.Train.Specs.DoorInterlockState = data.DoorInterlockState; DisableTimeAcceleration = data.DisableTimeAcceleration; for (int i = 0; i < InputDevicePlugin.AvailablePluginInfos.Count; i++) { if (InputDevicePlugin.AvailablePluginInfos[i].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable) { InputDevicePlugin.AvailablePlugins[i].SetElapseData(inputDevicePluginData); } } /* * Set the virtual handles. * */ this.PluginValid = true; SetHandles(data.Handles, true); this.Train.Destination = data.Destination; }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { //The Western requires special handling- Return if AWS has not been switched in from the cab if (Train.WesternDiesel != null && Train.AWS.Enabled == false) { if (Train.WesternDiesel.StartupManager.StartupState == WesternStartupManager.SequenceStates.AWSOnline) { //Enable AWS if the Western has switched it online Train.AWS.Enabled = true; } else { //Otherwise, we don't want to do any processing so back out //Doing anything else messes up the timing of the self-test sequence return; } } if (MySequenceState == SequenceStates.Pending) { Train.MasterSwitch = false; Train.selftest = false; /* Check the reverser state to see if the master switch has been set to on */ if (Train.Handles.Reverser == 1 || Train.Handles.Reverser == -1) { MySequenceState = SequenceStates.WaitingToStart; } } else if (MySequenceState == SequenceStates.WaitingToStart) { if (Train.Handles.Reverser == 0) { /* Turn the master switch on, and begin the startup and self-test procedure */ Train.selftest = true; Train.MasterSwitch = true; MySequenceState = SequenceStates.Initialising; /* Start the in-cab blower */ // if (PowerSupplyManager.SelectedPowerSupply != Plugin.MainBattery) { // Plugin.Fan.Reset(); // } /* Place the Automatic Warning System, and Train Protection and Warning System, into self-test mode */ Train.AWS.SelfTest(); Train.TPWS.SelfTest(); } } else if (MySequenceState != SequenceStates.Initialised) { /* Make sure that the master switch is on after reinitialisation */ Train.selftest = true; Train.MasterSwitch = true; /* Hold the brakes on until the AWS button is depressed */ if (MySequenceState == SequenceStates.AwaitingDriverInteraction) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application was demanded by the startup self-test sequence"); } else if (MySequenceState == SequenceStates.Finalising) { if (Train.AWS.WarningSound != -1) { if (SoundManager.IsPlaying(Train.AWS.WarningSound)) { SoundManager.Stop(Train.AWS.WarningSound); } } MySequenceState = SequenceStates.Initialised; Train.TractionManager.ResetBrakeApplication(); } /* Lastly, decrement the timer */ if (MySequenceState == SequenceStates.Initialising) { MySequenceTimer = MySequenceTimer - (int)data.ElapsedTime.Milliseconds; if (MySequenceTimer < 0) { MySequenceTimer = 0; MySequenceState = SequenceStates.AwaitingDriverInteraction; } } } else { if (this.firststart == false) { this.firststart = true; if (Train.AWS.Enabled == true) { Train.AWS.OnStartUp(SunflowerState); } if (Train.TPWS.Enabled) { Train.TPWS.Initialize(InitializationModes.OnService); } } } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { if (this.Enabled) { if (this.SafetyState != SafetyStates.Isolated) { if (this.MySafetyState == SafetyStates.LegacyOssArmed) { /* TPWS OSS is enabled with legacy behaviour, so check the train's current speed, and issue a Brake Demand if travelling too fast */ if (Train.CurrentSpeed > this.osslastspeed) { if (Train.TractionManager.CurrentInterventionBrakeNotch != this.Train.Specs.BrakeNotches + 1) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches + 1, "Emergency brakes were demanded by the TPWS Overspeed system"); } this.MySafetyState = SafetyStates.TssBrakeDemand; this.osslastspeed = 0; } else { this.MySafetyState = SafetyStates.None; } } else if (this.MySafetyState == SafetyStates.OssArmed) { /* TPWS OSS is armed, so handle the OSS timers */ if (this.ossndtimeractive) { this.ossndtimer = this.ossndtimer + (int)data.ElapsedTime.Milliseconds; } if (this.ossodtimeractive) { this.ossodtimer = this.ossodtimer + (int)data.ElapsedTime.Milliseconds; } if (this.ossndtimer > this.osstimeout) { /* The OSS ND timer has expired and no matching trigger loop has been detected, so the train is travelling within the permitted speed */ this.ossndtimer = 0; this.ossndtimeractive = false; } if (this.ossodtimer > this.osstimeout) { /* The OSS OD timer has expired and no matching trigger loop has been detected, so the train is travelling within the permitted speed */ this.ossodtimer = 0; this.ossodtimeractive = false; } if (!this.ossndtimeractive && !this.ossodtimeractive) { /* Disarm the OSS when neither ND or OD timer is active */ this.MySafetyState = SafetyStates.None; } } else if (this.MySafetyState == SafetyStates.TssArmed) { /* Check whether the maximum allowable distance between a TSS arming and trigger loop has been exceeded, and if so, reset the TSS */ if (this.tssndactive) { if (Train.TrainLocation >= this.tssndlastlocation + this.loopmaxspacing || Train.TrainLocation < this.tssndlastlocation - this.loopmaxspacing) { /* The TSS ND timer has expired and no matching trigger loop has been detected, so the train has not encountered a valid TSS */ this.tssndactive = false; this.tssndlastlocation = 0; } } if (this.tssodactive) { if (Train.TrainLocation >= this.tssodlastlocation + this.loopmaxspacing || Train.TrainLocation < this.tssodlastlocation - this.loopmaxspacing) { /* The TSS OD timer has expired and no matching trigger loop has been detected, so the train has not encountered a valid TSS */ this.tssodactive = false; this.tssodlastlocation = 0; } } if (!this.tssndactive && !this.tssodactive) { /* Disarm the TSS when neither ND or OD detection is present */ this.MySafetyState = SafetyStates.None; } } else if (this.MySafetyState == SafetyStates.TemporaryOverride) { /* The TPWS Temporary Override is active */ if (tpwsoverrideblinkrate != -1) { this.overrideblinktimer = this.overrideblinktimer + (int)data.ElapsedTime.Milliseconds; if (this.overrideblinktimer >= 0 && overrideblinktimer < this.tpwsoverrideblinkrate) { if (this.twpsoverrideindicator != -1) { this.Train.Panel[twpsoverrideindicator] = 1; } } else if (this.indicatorblinktimer >= (this.brakeindicatorblinkrate * 2)) { this.indicatorblinktimer = 0; } } else { this.Train.Panel[twpsoverrideindicator] = 1; } /* Handle the countdown timer */ this.overridetimer = this.overridetimer - (int)data.ElapsedTime.Milliseconds; if (this.overridetimer < 0) { this.overridetimer = (int)this.overridetimeout; this.MySafetyState = SafetyStates.None; } } else if (this.MySafetyState == SafetyStates.TssBrakeDemand) { /* A TPWS Brake Demand has been issued. * Increment the blink timer to enable the Brake Demand indicator to flash */ if (Train.TractionManager.CurrentInterventionBrakeNotch != this.Train.Specs.BrakeNotches + 1) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches + 1, "Emergency brakes were demanded by the TPWS Trainstop system"); } this.indicatorblinktimer = this.indicatorblinktimer + (int)data.ElapsedTime.Milliseconds; if (this.indicatorblinktimer >= 0 && indicatorblinktimer < this.brakeindicatorblinkrate) { if (brakedemandindicator != -1) { this.Train.Panel[brakedemandindicator] = 1; } } else if (this.indicatorblinktimer >= (this.brakeindicatorblinkrate * 2)) { this.indicatorblinktimer = 0; } } else if (this.MySafetyState == SafetyStates.BrakeDemandAcknowledged) { /* The TPWS Brake Demand indication has been acknowledged by pressing the AWS Reset button, * so stop the blinking light, wait for the train to stop, and start the timer */ //If the AWS triggered this, set it's state to warning acknowledged if (Train.AWS.SafetyState == AWS.SafetyStates.TPWSAWSBrakeDemandIssued) { Train.AWS.Acknowlege(); } if (brakedemandindicator != -1) { this.Train.Panel[brakedemandindicator] = 1; } if (Train.CurrentSpeed == 0) { this.MySafetyState = SafetyStates.BrakesAppliedCountingDown; } } else if (this.MySafetyState == SafetyStates.BrakesAppliedCountingDown) { /* The train has been brought to a stand, so wait for the timeout to expire * before stopping the TPWS safety intervention */ if (brakedemandindicator != -1) { this.Train.Panel[brakedemandindicator] = 1; } /* * if (Plugin.Diesel.Enabled) { * InterlockManager.DemandTractionPowerCutoff(); * } */ /* Handle the countdown timer */ this.brakesappliedtimer = this.brakesappliedtimer - (int)data.ElapsedTime.Milliseconds; if (this.brakesappliedtimer < 0 && Train.Handles.PowerNotch == 0) { this.brakesappliedtimer = (int)this.brakesappliedtimeout; this.MySafetyState = SafetyStates.None; Train.TractionManager.ResetBrakeApplication(); //InterlockManager.RequestTractionPowerReset(); } } else if (this.MySafetyState == SafetyStates.SelfTest) { if (brakedemandindicator != -1) { this.Train.Panel[brakedemandindicator] = 1; } if (this.twpsoverrideindicator != -1) { this.Train.Panel[twpsoverrideindicator] = 1; } if (tpwsisolatedindicator != -1) { this.Train.Panel[tpwsisolatedindicator] = 1; } } } else if (this.MySafetyState == SafetyStates.Isolated) { /* The TPWS has been isolated */ if (tpwsisolatedindicator != -1) { this.Train.Panel[tpwsisolatedindicator] = 1; } } } }
// --- functions --- /// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- if (this.Train.Doors != DoorStates.None & this.AutomaticallyDeactivates) { this.State = States.Disabled; } if (this.State != States.Disabled) { if (this.Train.Atc != null && (this.Train.Atc.State == Atc.States.Normal | this.Train.Atc.State == Atc.States.ServiceHalf | this.Train.Atc.State == Atc.States.ServiceFull | this.Train.Atc.State == Atc.States.Emergency)) { if (this.Train.Atc.State == Atc.States.Normal & data.Handles.Reverser == 1 & data.Handles.BrakeNotch == 0) { double speed = this.Train.State.Speed.MetersPerSecond; double limit = this.Train.Atc.Pattern.CurrentSpeed; if (this.Train.Tasc != null && this.Train.Tasc.State == Tasc.States.Pattern && !this.Train.Tasc.Override) { const double tascLimit = 25.0 / 3.6; if (tascLimit < limit) { limit = tascLimit; } } double minimumSpeed = limit - 15.0 / 3.6; double maximumSpeed = limit - 5.0 / 3.6; if (speed <= minimumSpeed) { this.State = States.Power; } else if (speed >= maximumSpeed) { this.State = States.Idle; } if (this.State == States.Power) { const double threshold = 5.0 / 3.6; int notch = (int)Math.Ceiling((maximumSpeed - speed) / threshold * (double)this.Train.Specs.PowerNotches); if (notch < 1) { notch = 1; } else if (notch > this.Train.Specs.PowerNotches) { notch = this.Train.Specs.PowerNotches; } if (this.Notch < notch) { if (this.Countdown <= 0.0) { this.Notch++; this.Countdown = this.PowerApplicationTime / (double)this.Train.Specs.PowerNotches; } } else { this.Notch = notch; } data.Handles.PowerNotch = this.Notch; } else { this.Notch = 0; data.Handles.PowerNotch = 0; } } else { this.Notch = 0; data.Handles.PowerNotch = 0; } } else { this.Notch = 0; data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches + 1; } } else { this.Notch = 0; } if (this.Countdown > 0.0) { this.Countdown -= data.ElapsedTime.Seconds; } // --- panel --- if (this.State != States.Disabled) { this.Train.Panel[91] = 1; if (this.Train.Atc == null || (this.Train.Atc.State != Atc.States.Normal & this.Train.Atc.State != Atc.States.ServiceHalf | this.Train.Atc.State == Atc.States.ServiceFull & this.Train.Atc.State != Atc.States.Emergency)) { this.Train.Panel[92] = 1; } } }
internal override void Elapse(ElapseData data, ref bool blocking) { if (awsTimer.TimerActive && awsTimer.TimeElapsed != -2) { awsTimer.TimeElapsed += data.ElapsedTime.Milliseconds; if (awsTimer.TimeElapsed > awsDelay && awsStop == false) { awsTimer.TimeElapsed = -2; awsStop = true; Train.TractionManager.DemandBrakeApplication(Train.Specs.BrakeNotches + 1, "Brake application demanded by the LU Trainstop system."); awsRelease = false; } } brakeDemandIndicatorLit = true; stopOverrideIndicatorLit = true; if (data.Vehicle.Speed.KilometersPerHour == 0) { if (stopTimer.TimerActive == false) { stopTimer.TimerActive = true; stopTimer.TimeElapsed = 0; } if (awsRelease) { Train.TractionManager.DemandBrakeApplication(Train.Specs.BrakeNotches + 1, "Brake application demanded by the LU Trainstop system."); awsIndicatorLit = true; awsTimer.TimerActive = false; awsStop = false; awsRelease = false; } stopTimer.TimeElapsed += data.ElapsedTime.Milliseconds; if (tpwsRelease && stopTimer.TimeElapsed > tpwsStopDelay * 1000) { Train.TractionManager.DemandBrakeApplication(Train.Specs.BrakeNotches + 1, "Brake application demanded by the LU Trainstop system."); brakeDemandIndicatorLit = true; tpwsTrainstop = false; tpwsRelease = false; } } if (overrideTimer.TimerActive) { overrideTimer.TimeElapsed += data.ElapsedTime.Milliseconds; if (overrideTimer.TimeElapsed > tpwsOverrideLifetime * 1000) { overrideTimer.TimerActive = false; overrideTimer.TimeElapsed = 0; stopOverrideIndicatorLit = false; } } //Set panel if (awsIndicator != -1) { Train.Panel[awsIndicator] = awsIndicatorLit ? 1 : 0; } if (brakeDemandIndicator != -1) { Train.Panel[brakeDemandIndicator] = brakeDemandIndicatorLit ? 1 : 0; } if (stopOverrideIndicator != -1) { Train.Panel[stopOverrideIndicator] = stopOverrideIndicatorLit ? 1 : 0; } if (awsKeyIndicator != -1) { Train.Panel[awsKeyIndicator] = awsKeyPressed ? 1 : 0; } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { { if (TripcockActive == true) { if (DeadmansDeviceActive == true) { //We can accelerate! //If the throttle button is held down, then the train will accelerate towards the selected speed switch (CurrentSpeed) { case SelectorSpeeds.B25: data.Handles.Reverser = -1; if (Train.CurrentSpeed < 25 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; case SelectorSpeeds.B15: data.Handles.Reverser = -1; if (Train.CurrentSpeed < 15 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; case SelectorSpeeds.Neutral: data.Handles.Reverser = 0; data.Handles.PowerNotch = 0; break; case SelectorSpeeds.F15: data.Handles.Reverser = 1; if (Train.CurrentSpeed < 15 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; case SelectorSpeeds.F25: data.Handles.Reverser = 1; if (Train.CurrentSpeed < 25 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; case SelectorSpeeds.F50: data.Handles.Reverser = 1; if (Train.CurrentSpeed < 50 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; case SelectorSpeeds.F60: data.Handles.Reverser = 1; if (Train.CurrentSpeed < 60 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; case SelectorSpeeds.F70: data.Handles.Reverser = 1; if (Train.CurrentSpeed < 70 && Train.TractionManager.PowerCutoffDemanded == false) { data.Handles.PowerNotch = Train.Specs.PowerNotches; } else { data.Handles.PowerNotch = 0; } break; } } else { //The F92 has a counter for unwanted EB applications if (Train.TractionManager.BrakeInterventionDemanded == false) { EmergencyBrakeCounter++; } //If deadman's device is inactive, apply EB Train.TractionManager.DemandBrakeApplication(Train.Specs.BrakeNotches + 1, "Brake application demanded by the F92"); } } else { //If our tripcock is not currently turned on, then power must be cut off Train.TractionManager.DemandPowerCutoff("Power cutoff demanded by the F92 tripcock"); } //Max speed device if (Train.CurrentSpeed > 70 && Overspeed == false) { //I'm presuming that the overspeed device will also up the EB counter, need to check this.... EmergencyBrakeCounter++; Train.TractionManager.DemandBrakeApplication(Train.Specs.BrakeNotches, "Brake application demanded by the F92 overspeed device"); SoundManager.Play(OverspeedSound, 1.0, 1.0, true); Overspeed = true; } else { if (Overspeed == true) { //Only attempt to reset the brake application once, else this causes log spam Train.TractionManager.ResetBrakeApplication(); SoundManager.Stop(OverspeedSound); Overspeed = false; } } } //Sounds { //If our trainspeed is greater than 50km/h then we should play the curve flange sound if (Train.CurrentSpeed > 50 && CurveFlangeNoise == true) { //Requires fade-in sound SoundManager.Play(CurveFlangeSound, 1.0, 1.0, true); } else { SoundManager.Stop(CurveFlangeSound); //Requires fade-out sound } //This sound is played whilst in tight curves (Rumbling noise) whilst the speed is above 25km/h if (Train.CurrentSpeed > 25 && TightCurveNoise == true) { //Requires fade-in sound SoundManager.Play(TightCurveSound, 1.0, 1.0, true); } else { //Requires fade-out sound SoundManager.Stop(CurveFlangeSound); } } }
protected override void Elapse(ref ElapseData data) { if (externalCrashed) { //Yuck for (int i = 0; i < Train.Cars[Train.DriverCar].Sounds.Plugin.Length; i++) { if (Train.Cars[Train.DriverCar].Sounds.Plugin[i].IsPlaying) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Stop(); } } Train.UnloadPlugin(); return; } if (!string.IsNullOrEmpty(lastError)) { //TrainManagercurrentHost.A("ERROR: The proxy plugin " + PluginFile + " generated the following error:"); //Program.FileSystem.AppendToLogFile(pluginProxy.callback.lastError); lastError = string.Empty; } try { ElapseProxy e = new ElapseProxy(data, Panel, Sound); ElapseProxy proxyData = pipeProxy.Elapse(e); Panel = proxyData.Panel; Sound = proxyData.Sound; for (int i = 0; i < Sound.Length; i++) { if (Sound[i] != LastSound[i]) { if (Sound[i] == SoundInstructions.Stop) { if (i < Train.Cars[Train.DriverCar].Sounds.Plugin.Length) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Stop(); } } else if (Sound[i] > SoundInstructions.Stop & Sound[i] <= SoundInstructions.PlayLooping) { if (i < Train.Cars[Train.DriverCar].Sounds.Plugin.Length) { SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.Plugin[i].Buffer; if (buffer != null) { double volume = (double)(Sound[i] - SoundInstructions.Stop) / (SoundInstructions.PlayLooping - SoundInstructions.Stop); if (Train.Cars[Train.DriverCar].Sounds.Plugin[i].IsPlaying) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Source.Volume = volume; } else { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Play(1.0, volume, Train.Cars[Train.DriverCar], true); } } } } else if (Sound[i] == SoundInstructions.PlayOnce) { if (i < Train.Cars[Train.DriverCar].Sounds.Plugin.Length) { SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.Plugin[i].Buffer; if (buffer != null) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Play(1.0, 1.0, Train.Cars[Train.DriverCar], false); } } Sound[i] = SoundInstructions.Continue; } else if (Sound[i] != SoundInstructions.Continue) { PluginValid = false; } LastSound[i] = Sound[i]; } else { if ((Sound[i] < SoundInstructions.Stop | Sound[i] > SoundInstructions.PlayLooping) && Sound[i] != SoundInstructions.PlayOnce & Sound[i] != SoundInstructions.Continue) { PluginValid = false; } } } data = proxyData.Data; } catch { lastError = externalCrashed.ToString(); externalCrashed = true; } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- this.PrecedingTrain = data.PrecedingVehicle; if (this.StateSwitch) { this.State = States.Normal; this.StateSwitch = false; } if (this.State == States.Suppressed) { if (data.Handles.BrakeNotch <= this.Train.Specs.BrakeNotches) { if (this.Train.AtsSx != null | this.Train.AtsP != null) { this.State = States.Ats; } else { this.State = States.Normal; } } } if (blocking) { if (this.State != States.Disabled & this.State != States.Suppressed) { this.State = States.Ats; } } else { if (this.State == States.Normal | this.State == States.Service | this.State == States.Emergency) { var speed = GetCurrentAtcSpeed(); if (speed != this.CurrentAtcSpeed) { this.Train.Sounds.AtcBell.Play(); } this.CurrentAtcSpeed = speed; if (speed < 0.0) { if (this.State != States.Emergency) { this.State = States.Emergency; this.Train.Sounds.AtcBell.Play(); } } else if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) > speed) { if (this.State != States.Service) { this.State = States.Service; this.Train.Sounds.AtcBell.Play(); } } else if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) < speed - 1.0 / 3.6) { if (this.State != States.Normal) { this.State = States.Normal; this.Train.Sounds.AtcBell.Play(); } } if (this.State == States.Service) { if (data.Handles.BrakeNotch < this.Train.Specs.BrakeNotches) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches; } } else if (this.State == States.Emergency) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches + 1; } blocking = true; } if (this.State != States.Disabled & (this.Train.Doors != DoorStates.None | data.Handles.BrakeNotch > 0)) { data.Handles.PowerNotch = 0; } } // --- panel --- if (this.State == States.Ats) { this.Train.Panel[271] = 12; } else if (this.State == States.Normal | this.State == States.Service | this.State == States.Emergency) { this.Train.Panel[265] = 1; if (this.CurrentAtcSpeed < 0.0) { this.Train.Panel[271] = 0; } else { int value = this.CompatibilitySpeeds.Length - 1; for (int i = 2; i < this.CompatibilitySpeeds.Length; i++) { if (this.CompatibilitySpeeds[i] > this.CurrentAtcSpeed) { value = i - 1; break; } } this.Train.Panel[271] = value; } } if (this.State == States.Service) { this.Train.Panel[267] = 1; } else if (this.State == States.Emergency) { this.Train.Panel[268] = 1; } if (this.State != States.Disabled & this.State != States.Suppressed) { this.Train.Panel[266] = 1; } // --- manual or automatic switch --- if (ShouldSwitchToAts()) { if (this.AutomaticSwitch & Math.Abs(data.Vehicle.Speed.MetersPerSecond) < 1.0 / 3.6) { KeyDown(VirtualKeys.C1); } } else if (ShouldSwitchToAtc()) { if (this.AutomaticSwitch & Math.Abs(data.Vehicle.Speed.MetersPerSecond) < 1.0 / 3.6) { KeyDown(VirtualKeys.C2); } } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- if (this.State == States.Suppressed) { if (data.Handles.BrakeNotch <= this.Train.Specs.BrakeNotches) { this.InitializationCountdown = DurationOfInitialization; this.State = States.Initializing; } } if (this.State == States.Initializing) { this.InitializationCountdown -= data.ElapsedTime.Seconds; if (this.InitializationCountdown <= 0.0) { this.State = States.Standby; foreach (Pattern pattern in this.Patterns) { if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.WarningPattern) { pattern.Clear(); } } this.Train.Sounds.AtsPBell.Play(); } } if (BrakeRelease) { BrakeReleaseCountdown -= data.ElapsedTime.Seconds; if (BrakeReleaseCountdown <= 0.0) { BrakeRelease = false; this.Train.Sounds.AtsPBell.Play(); } } if (this.State != States.Disabled & this.State != States.Initializing) { this.Position += data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; } if (blocking) { if (this.State != States.Disabled & this.State != States.Suppressed) { this.State = States.Standby; } } else { if (this.State == States.Normal | this.State == States.Pattern | this.State == States.Brake) { bool brake = false; bool warning = false; UpdateCompatibilityTemporarySpeedPattern(); foreach (Pattern pattern in this.Patterns) { pattern.Perform(this, data); if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.WarningPattern) { warning = true; } if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.BrakePattern) { brake = true; } } if (BrakeRelease) { brake = false; } if (brake & this.State != States.Brake) { this.State = States.Brake; this.Train.Sounds.AtsPBell.Play(); } else if (warning & this.State == States.Normal) { this.State = States.Pattern; this.Train.Sounds.AtsPBell.Play(); } else if (!brake & !warning & (this.State == States.Pattern | this.State == States.Brake)) { this.State = States.Normal; this.Train.Sounds.AtsPBell.Play(); } if (this.State == States.Brake) { if (data.Handles.BrakeNotch < this.Train.Specs.BrakeNotches) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches; } } blocking = true; } else if (this.State == States.Service) { if (data.Handles.BrakeNotch < this.Train.Specs.BrakeNotches) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches; } blocking = true; } else if (this.State == States.Emergency) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches + 1; blocking = true; } if (this.State != States.Disabled & this.Train.Doors != DoorStates.None) { data.Handles.PowerNotch = 0; } } // --- panel --- if (this.State != States.Disabled & this.State != States.Suppressed) { this.Train.Panel[2] = 1; this.Train.Panel[259] = 1; } if (this.State == States.Pattern | this.State == States.Brake | this.State == States.Service | this.State == States.Emergency) { this.Train.Panel[3] = 1; this.Train.Panel[260] = 1; } if (this.State == States.Brake | this.State == States.Service | this.State == States.Emergency) { this.Train.Panel[5] = 1; this.Train.Panel[262] = 1; } if (this.State != States.Disabled & this.State != States.Suppressed & this.State != States.Standby) { this.Train.Panel[6] = 1; this.Train.Panel[263] = 1; } if (this.State == States.Initializing) { this.Train.Panel[7] = 1; this.Train.Panel[264] = 1; } if (this.State == States.Disabled) { this.Train.Panel[50] = 1; } if (this.BrakeRelease) { this.Train.Panel[4] = 1; this.Train.Panel[261] = 1; } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- if (this.State == States.Pattern | this.State == States.Released) { this.Distance -= data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; } if (this.State == States.Pattern) { if (this.Override) { // --- override --- this.BrakeNotch = 0; if (this.Distance < -this.TascBrakeTolerance) { this.State = States.Released; } data.DebugMessage = "TASC override"; } else if (this.Train.Doors == DoorStates.None) { // --- doors closed --- int notchOffset = this.Train.Specs.HasHoldBrake ? 1 : 0; double distance = this.Distance; bool hold = false; if (data.Vehicle.Speed.MetersPerSecond >= this.BrakeControlSpeed) { distance -= this.BrakeControlSpeed * this.BrakeControlDelay; this.BrakeControlTimer = 0.0; } else { double delay = this.BrakeControlDelay * (double)(this.BrakeNotch - notchOffset) / (double)(this.Train.Specs.BrakeNotches - notchOffset); if (this.BrakeControlTimer < delay) { this.BrakeControlTimer += data.ElapsedTime.Seconds; hold = true; } else { this.BrakeControlTimer = this.BrakeControlDelay; } } if (!hold) { bool adjust; if (this.BrakeNotch == 0) { adjust = true; } else { double deceleration = this.ServiceBrakeDeceleration * (double)(this.BrakeNotch - notchOffset) / (double)(this.Train.Specs.BrakeNotches - notchOffset); double deviation = distance - data.Vehicle.Speed.MetersPerSecond * data.Vehicle.Speed.MetersPerSecond / (2.0 * deceleration); adjust = Math.Abs(deviation) > this.TascBrakeTolerance; } if (adjust) { if (distance > 0.0) { double requiredDeceleration = data.Vehicle.Speed.MetersPerSecond * data.Vehicle.Speed.MetersPerSecond / (2.0 * distance); double requiredBrakeNotch = notchOffset + requiredDeceleration / this.ServiceBrakeDeceleration * (this.Train.Specs.BrakeNotches - notchOffset); if (!this.Approach) { const double amplifier = 5.0; requiredDeceleration = (requiredDeceleration - this.TascBrakeDeceleration) * amplifier + this.TascBrakeDeceleration; double notch = notchOffset + requiredDeceleration / this.ServiceBrakeDeceleration * (this.Train.Specs.BrakeNotches - notchOffset); if ((int)Math.Round(notch) < (int)Math.Round(requiredBrakeNotch)) { requiredBrakeNotch = notch; } else { this.Approach = true; } } if (requiredBrakeNotch < this.BrakeNotch) { this.BrakeNotch = (int)Math.Ceiling(requiredBrakeNotch - 0.25); } else if (requiredBrakeNotch > this.BrakeNotch) { this.BrakeNotch = (int)Math.Ceiling(requiredBrakeNotch - 0.75); } if (this.BrakeNotch <= notchOffset) { this.BrakeNotch = 0; } else if (this.BrakeNotch > this.Train.Specs.BrakeNotches) { this.BrakeNotch = this.Train.Specs.BrakeNotches; } } else { this.BrakeNotch = this.Train.Specs.BrakeNotches; } } } if (data.Handles.BrakeNotch < this.BrakeNotch) { data.Handles.BrakeNotch = this.BrakeNotch; } data.DebugMessage = "TASC pattern @" + this.Distance.ToString("0.00"); } else { // --- doors opened --- if (data.Handles.BrakeNotch < this.Train.Specs.BrakeNotches) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches; } data.DebugMessage = "TASC doorblock"; } } else if (this.State == States.Released) { this.BrakeNotch = 0; if (Math.Abs(this.Distance) > 5.0) { this.State = States.Normal; this.Distance = 0.0; this.Approach = false; this.HomeDoors = false; } data.DebugMessage = "TASC released"; } // --- panel --- if (this.Override) { this.Train.Panel[83] = 1; } this.Train.Panel[56] = 0; this.Train.Panel[80] = 1; if (this.State == States.Pattern) { this.Train.Panel[81] = 1; } if (this.BrakeNotch > 0) { this.Train.Panel[82] = 1; } if ((this.State == States.Pattern) & this.Distance >= -HomeDoorsTolerance & this.Distance <= HomeDoorsTolerance) { this.Train.Panel[85] = 1; } if (this.Train.Doors == DoorStates.None) { this.Train.Panel[86] = 1; } if (!this.HomeDoors | this.Distance <-HomeDoorsTolerance | this.Distance> HomeDoorsTolerance | this.Train.Doors == DoorStates.None) { this.Train.Panel[87] = 1; } this.Train.Panel[90] = this.BrakeNotch; }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- if (this.CompatibilityLimitsNeedsSort) { CompatibilityLimit.Sort(this, this.CompatibilityLimits); this.CompatibilityLimitsNeedsSort = false; } this.Blocked = blocking; if (this.State == States.Suppressed) { if (data.Handles.BrakeNotch <= this.Train.Specs.BrakeNotches) { this.InitializationCountdown = DurationOfInitialization; this.State = States.Initializing; } } if (this.State == States.Initializing) { this.InitializationCountdown -= data.ElapsedTime.Seconds; if (this.InitializationCountdown <= 0.0) { this.State = States.Standby; this.BrakeRelease = false; this.SwitchToAtsSxPosition = double.MaxValue; foreach (var pattern in this.Patterns) { if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.WarningPattern) { pattern.Clear(); } } this.Train.Sounds.AtsPBell.Play(); } } if (BrakeRelease) { BrakeReleaseCountdown -= data.ElapsedTime.Seconds; if (BrakeReleaseCountdown <= 0.0) { BrakeRelease = false; this.Train.Sounds.AtsPBell.Play(); } } if (this.State != States.Disabled & this.State != States.Initializing) { this.Position += data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; } if (blocking) { if (this.State != States.Disabled & this.State != States.Suppressed) { this.State = States.Standby; } } else { if (this.State == States.Normal | this.State == States.Pattern | this.State == States.Brake) { bool brake = false; bool warning = false; bool normal = true; if (this.DivergencePattern.Position > double.MinValue & this.DivergencePattern.Position < double.MaxValue) { if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) < this.DivergencePattern.BrakePattern) { double distance = this.DivergencePattern.Position - this.Position; if (distance < -50.0) { this.DivergencePattern.Clear(); } } } this.UpdateCompatibilityTemporarySpeedPattern(); foreach (var pattern in this.Patterns) { pattern.Perform(this); if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.WarningPattern - 1.0 / 3.6) { normal = false; } if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.WarningPattern) { warning = true; } if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.BrakePattern) { brake = true; } } for (int i = 0; i < this.SignalPatterns.Count; i++) { if (this.SignalPatterns[i].Position > double.MinValue & this.SignalPatterns[i].Position < double.MaxValue) { if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) < this.DivergencePattern.BrakePattern) { double distance = this.DivergencePattern.Position - this.Position; if (distance < -50.0) { this.Patterns.Remove(this.SignalPatterns[i]); this.SignalPatterns[i] = this.SignalPatterns[this.SignalPatterns.Count - 1]; this.SignalPatterns.RemoveAt(this.SignalPatterns.Count - 1); i--; } } } } if (BrakeRelease) { brake = false; } if (brake & this.State != States.Brake) { this.State = States.Brake; this.Train.Sounds.AtsPBell.Play(); } else if (warning & this.State == States.Normal) { this.State = States.Pattern; this.Train.Sounds.AtsPBell.Play(); } else if (!brake & !warning & normal & (this.State == States.Pattern | this.State == States.Brake)) { this.State = States.Normal; this.Train.Sounds.AtsPBell.Play(); } if (this.State == States.Brake) { if (data.Handles.BrakeNotch < this.Train.Specs.BrakeNotches) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches; } } if (this.Position > this.SwitchToAtsSxPosition & this.State != States.Brake & this.State != States.Service & this.State != States.Emergency) { SwitchToSx(); } } else if (this.State == States.Service) { if (data.Handles.BrakeNotch < this.Train.Specs.BrakeNotches) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches; } } else if (this.State == States.Emergency) { data.Handles.BrakeNotch = this.Train.Specs.BrakeNotches + 1; } if (!this.AtsSxPMode & (this.State == States.Normal | this.State == States.Pattern | this.State == States.Brake | this.State == States.Service | this.State == States.Emergency)) { blocking = true; } if (this.State != States.Disabled & this.Train.Doors != DoorStates.None) { data.Handles.PowerNotch = 0; } } // --- panel --- if (this.State != States.Disabled & this.State != States.Suppressed) { this.Train.Panel[2] = 1; this.Train.Panel[259] = 1; } if (this.State == States.Pattern | this.State == States.Brake | this.State == States.Service | this.State == States.Emergency) { this.Train.Panel[3] = 1; this.Train.Panel[260] = 1; } if (this.State == States.Brake | this.State == States.Service | this.State == States.Emergency) { this.Train.Panel[5] = 1; this.Train.Panel[262] = 1; } if (this.State != States.Disabled & this.State != States.Suppressed & this.State != States.Standby) { this.Train.Panel[6] = 1; this.Train.Panel[263] = 1; } if (this.State == States.Initializing) { this.Train.Panel[7] = 1; this.Train.Panel[264] = 1; } if (this.State == States.Disabled) { this.Train.Panel[50] = 1; } if (this.State != States.Disabled & this.State != States.Suppressed & this.State != States.Standby & this.BrakeRelease) { this.Train.Panel[4] = 1; this.Train.Panel[261] = 1; } // --- debug --- if (this.State == States.Normal | this.State == States.Pattern | this.State == States.Brake | this.State == States.Service | this.State == States.Emergency) { var builder = new StringBuilder(); for (int i = 0; i < this.SignalPatterns.Count; i++) { this.SignalPatterns[i].AddToStringBuilder(i.ToString() + ":", builder); } this.DivergencePattern.AddToStringBuilder("分岐/D:", builder); this.TemporaryPattern.AddToStringBuilder("臨時/T:", builder); this.CurvePattern.AddToStringBuilder("曲線/C:", builder); this.DownslopePattern.AddToStringBuilder("勾配/S:", builder); this.RoutePermanentPattern.AddToStringBuilder("最高/Max:", builder); this.TrainPermanentPattern.AddToStringBuilder("電車/Train:", builder); if (this.SwitchToAtsSxPosition != double.MaxValue) { if (builder.Length != 0) { builder.Append(", "); } builder.Append("Sx@" + (this.SwitchToAtsSxPosition - this.Position).ToString("0")); } this.CompatibilityTemporaryPattern.AddToStringBuilder("CompTemp", builder); this.CompatibilityPermanentPattern.AddToStringBuilder("CompPerm", builder); if (builder.Length == 0) { data.DebugMessage = this.State.ToString(); } else { data.DebugMessage = this.State.ToString() + " - " + builder.ToString(); } } }
/// <summary>Called every frame to update the plugin.</summary> /// <param name="data">The data passed to the plugin on Elapse.</param> /// <remarks>This function should not be called directly. Call UpdatePlugin instead.</remarks> internal abstract void Elapse(ElapseData data);
protected override void Elapse(ElapseData data) { try { double time = data.TotalTime.Milliseconds; Win32VehicleState win32State; win32State.Location = data.Vehicle.Location; win32State.Speed = (float)data.Vehicle.Speed.KilometersPerHour; win32State.Time = (int)Math.Floor(time - 2073600000.0 * Math.Floor(time / 2073600000.0)); win32State.BcPressure = (float)data.Vehicle.BcPressure; win32State.MrPressure = (float)data.Vehicle.MrPressure; win32State.ErPressure = (float)data.Vehicle.ErPressure; win32State.BpPressure = (float)data.Vehicle.BpPressure; win32State.SapPressure = (float)data.Vehicle.SapPressure; win32State.Current = 0.0f; Win32Handles win32Handles; win32Handles.Brake = data.Handles.BrakeNotch; win32Handles.Power = data.Handles.PowerNotch; win32Handles.Reverser = data.Handles.Reverser; win32Handles.ConstantSpeed = data.Handles.ConstSpeed ? ConstSpeedInstructions.Enable : ConstSpeedInstructions.Disable; Win32Elapse(ref win32Handles.Brake, ref win32State.Location, ref base.Panel[0], ref this.Sound[0]); data.Handles.Reverser = win32Handles.Reverser; data.Handles.PowerNotch = win32Handles.Power; data.Handles.BrakeNotch = win32Handles.Brake; if (win32Handles.ConstantSpeed == ConstSpeedInstructions.Enable) { data.Handles.ConstSpeed = true; } else if (win32Handles.ConstantSpeed == ConstSpeedInstructions.Disable) { data.Handles.ConstSpeed = false; } else if (win32Handles.ConstantSpeed != ConstSpeedInstructions.Continue) { this.PluginValid = false; } /* * Process the sound instructions * */ for (int i = 0; i < this.Sound.Length; i++) { if (this.Sound[i] != this.LastSound[i]) { if (this.Sound[i] == SoundInstructions.Stop) { if (i < base.Train.Cars[base.Train.DriverCar].Sounds.Plugin.Length) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Stop(); } } else if (this.Sound[i] > SoundInstructions.Stop & this.Sound[i] <= SoundInstructions.PlayLooping) { if (i < base.Train.Cars[base.Train.DriverCar].Sounds.Plugin.Length) { if (Train.Cars[Train.DriverCar].Sounds.Plugin[i].Buffer != null) { double volume = (double)(this.Sound[i] - SoundInstructions.Stop) / (double)(SoundInstructions.PlayLooping - SoundInstructions.Stop); if (Train.Cars[Train.DriverCar].Sounds.Plugin[i].IsPlaying) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Source.Volume = volume; } else { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Play(1.0, volume, Train.Cars[Train.DriverCar], true); } } } } else if (this.Sound[i] == SoundInstructions.PlayOnce) { if (i < base.Train.Cars[base.Train.DriverCar].Sounds.Plugin.Length) { if (Train.Cars[Train.DriverCar].Sounds.Plugin[i].Buffer != null) { Train.Cars[Train.DriverCar].Sounds.Plugin[i].Play(Train.Cars[Train.DriverCar], false); } } this.Sound[i] = SoundInstructions.Continue; } else if (this.Sound[i] != SoundInstructions.Continue) { this.PluginValid = false; } this.LastSound[i] = this.Sound[i]; } else { if ((this.Sound[i] < SoundInstructions.Stop | this.Sound[i] > SoundInstructions.PlayLooping) && this.Sound[i] != SoundInstructions.PlayOnce & this.Sound[i] != SoundInstructions.Continue) { this.PluginValid = false; } } } } catch (Exception ex) { base.LastException = ex; throw; } }
internal void Perform(AtsP system, ElapseData data) { if (this.Position == double.MaxValue | this.TargetSpeed == double.MaxValue) { this.WarningPattern = double.MaxValue; this.BrakePattern = double.MaxValue; return; } if (this.Position != double.MinValue) { double designDeceleration = this.Device.DesignDeceleration + 9.81 * this.Gradient; double position = this.Position - system.Position; double warningPatternOffset = 2 * designDeceleration * (position - this.Device.WarningPatternOffset) + designDeceleration * designDeceleration * this.Device.WarningPatternDelay * this.Device.WarningPatternDelay + this.TargetSpeed * this.TargetSpeed; if (warningPatternOffset > 0) { this.WarningPattern = Math.Sqrt(warningPatternOffset) - designDeceleration * this.Device.WarningPatternDelay; } else { this.WarningPattern = -designDeceleration * this.Device.WarningPatternDelay; } if (this.TargetSpeed > 0.277777777777778) { if (this.WarningPattern < this.TargetSpeed + this.Device.WarningPatternTolerance) { this.WarningPattern = this.TargetSpeed + this.Device.WarningPatternTolerance; } } else if (this.WarningPattern < this.TargetSpeed) { this.WarningPattern = this.TargetSpeed; } double brakePatternOffset = 2 * designDeceleration * (position - this.Device.BrakePatternOffset) + designDeceleration * designDeceleration * this.Device.BrakePatternDelay * this.Device.BrakePatternDelay + this.TargetSpeed * this.TargetSpeed; if (brakePatternOffset > 0) { this.BrakePattern = Math.Sqrt(brakePatternOffset) - designDeceleration * this.Device.BrakePatternDelay; } else { this.BrakePattern = -designDeceleration * this.Device.BrakePatternDelay; } if (this.TargetSpeed > 0.277777777777778) { if (this.BrakePattern < this.TargetSpeed + this.Device.BrakePatternTolerance) { this.BrakePattern = this.TargetSpeed + this.Device.BrakePatternTolerance; } } else if (this.BrakePattern < this.TargetSpeed) { this.BrakePattern = this.TargetSpeed; } if (this.BrakePattern < this.Device.ReleaseSpeed) { this.BrakePattern = this.Device.ReleaseSpeed; } } else { if (this.TargetSpeed <= 0.277777777777778) { this.WarningPattern = this.TargetSpeed; this.BrakePattern = this.TargetSpeed; } else { this.WarningPattern = this.TargetSpeed + this.Device.WarningPatternTolerance; this.BrakePattern = this.TargetSpeed + this.Device.BrakePatternTolerance; } if (this.BrakePattern < this.Device.ReleaseSpeed) { this.BrakePattern = this.Device.ReleaseSpeed; return; } } }
internal override int?Elapse(ElapseData data) { currentLocation = data.Vehicle.Location; //Calculate signalling status //Distance to next train UpdateAtpSpeeds(data, data.PrecedingVehicle); //Naive overspeed prevention that applies FSB if (train.trainModeActual == Train.TrainModes.CodedManual) { if (data.Vehicle.Speed.KilometersPerHour > train.atpSafetySpeed) { return(-train.specs.BrakeNotches); } else if (data.Vehicle.Speed.KilometersPerHour > train.atpSafetySpeed - ATP_OVERSPEED_COAST_THRESHOLD) { return(0); } if (data.Vehicle.Speed.KilometersPerHour > train.atpSafetySpeed - ATP_OVERSPEED_ALERT_THRESHOLD) { //play sound if (atpOverspeedSoundHandle == null) { atpOverspeedSoundHandle = train.PlaySound(0, 1, 1, true); } } else { if (atpOverspeedSoundHandle != null) { atpOverspeedSoundHandle.Stop(); atpOverspeedSoundHandle = null; } } } return(null); //Check trip count //Check for speed limits //ElapseTripTimer(data); //Is train in RM? /*if (train.trainModeActual == Train.TrainModes.RestrictedManualForward || * train.trainModeActual == Train.TrainModes.RestrictedManualReverse || * train.trainModeActual == Train.TrainModes.Off) * { * atpState = AtpStates.Off; * } * else * { * switch (atpState) * { * case AtpStates.Active: * if (atpTripTimer <= 0.0) * { * atpState = AtpStates.Tripped; * } * return null; * case AtpStates.Tripped: * * return -train.specs.BrakeNotches - 1; * default: * return null; * } * }*/ }
internal override void Elapse(ElapseData data, ref bool blocking) { this.Blocked = blocking; if (this.State == AtsP.States.Suppressed && this.Train.TractionManager.CurrentInterventionBrakeNotch <= this.Train.Specs.BrakeNotches) { this.InitializationCountdown = this.DurationOfInitialization; this.State = AtsP.States.Initializing; } if (this.State == AtsP.States.Initializing) { AtsP initializationCountdown = this; initializationCountdown.InitializationCountdown = initializationCountdown.InitializationCountdown - data.ElapsedTime.Seconds; if (this.InitializationCountdown <= 0) { this.State = AtsP.States.Standby; this.BrakeRelease = false; this.SwitchToAtsSxPosition = double.MaxValue; AtsP.Pattern[] patterns = this.Patterns; for (int i = 0; i < (int)patterns.Length; i++) { AtsP.Pattern pattern = patterns[i]; if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern.WarningPattern) { pattern.Clear(); } } if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } } if (this.BrakeRelease) { AtsP brakeReleaseCountdown = this; brakeReleaseCountdown.BrakeReleaseCountdown = brakeReleaseCountdown.BrakeReleaseCountdown - data.ElapsedTime.Seconds; if (this.BrakeReleaseCountdown <= 0) { this.BrakeRelease = false; if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } } if (this.State != AtsP.States.Disabled & this.State != AtsP.States.Initializing) { AtsP position = this; position.Position = position.Position + data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; } if (!blocking) { if (this.DAtsPSupported && this.DAtsPFirstSignalPattern.Position - this.Train.State.Location < 0) { this.DAtsPZerothSignalPattern.Position = this.DAtsPFirstSignalPattern.Position; this.DAtsPZerothSignalPattern.TargetSpeed = this.DAtsPFirstSignalPattern.TargetSpeed; this.DAtsPFirstSignalPattern.Position = this.DAtsPSecondSignalPattern.Position; this.DAtsPFirstSignalPattern.TargetSpeed = this.DAtsPSecondSignalPattern.TargetSpeed; this.DAtsPSecondSignalPattern.Position = double.MaxValue; this.DAtsPSecondSignalPattern.TargetSpeed = double.MaxValue; } if (this.DAtsPActive & this.DAtsPContinuous) { switch (this.DAtsPAspect) { case 1: { this.DAtsPFirstSignalPattern.TargetSpeed = 6.94444444444444; break; } case 2: { this.DAtsPFirstSignalPattern.TargetSpeed = 12.5; break; } case 3: { this.DAtsPFirstSignalPattern.TargetSpeed = 20.8333333333333; break; } case 4: case 5: case 6: { this.DAtsPFirstSignalPattern.TargetSpeed = double.MaxValue; break; } default: { this.DAtsPFirstSignalPattern.TargetSpeed = 0; break; } } if (this.DAtsPZerothSignalPattern.TargetSpeed < this.DAtsPFirstSignalPattern.TargetSpeed) { this.DAtsPZerothSignalPattern.TargetSpeed = this.DAtsPFirstSignalPattern.TargetSpeed; } } if (this.State == AtsP.States.Normal | this.State == AtsP.States.Pattern | this.State == AtsP.States.Brake) { bool flag = false; bool flag1 = false; bool flag2 = true; if (this.DivergencePattern.Position > double.MinValue & this.DivergencePattern.Position < double.MaxValue && Math.Abs(data.Vehicle.Speed.MetersPerSecond) < this.DivergencePattern.BrakePattern && this.DivergencePattern.Position - this.Position < -50) { this.DivergencePattern.Clear(); } this.UpdateCompatibilityTemporarySpeedPattern(); AtsP.Pattern[] patternArray = this.Patterns; for (int j = 0; j < (int)patternArray.Length; j++) { AtsP.Pattern pattern1 = patternArray[j]; pattern1.Perform(this, data); if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern1.WarningPattern - 0.277777777777778) { flag2 = false; } if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern1.WarningPattern) { flag1 = true; } if (Math.Abs(data.Vehicle.Speed.MetersPerSecond) >= pattern1.BrakePattern) { flag = true; } } if (this.BrakeRelease) { flag = false; } if (flag & this.State != AtsP.States.Brake) { this.State = AtsP.States.Brake; if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } else if (flag1 & this.State == AtsP.States.Normal) { this.State = AtsP.States.Pattern; if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } else if (!flag & !flag1 & flag2 & (this.State == AtsP.States.Pattern | this.State == AtsP.States.Brake)) { this.State = AtsP.States.Normal; if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } if (this.State == AtsP.States.Brake) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application demanded by ATS-P"); } if (this.Position > this.SwitchToAtsSxPosition & this.State != AtsP.States.Brake & this.State != AtsP.States.Service & this.State != AtsP.States.Emergency) { this.SwitchToSx(); } } else if (this.State == AtsP.States.Service) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application demanded by ATS-P"); } else if (this.State == AtsP.States.Emergency) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches + 1, "Brake application demanded by ATS-P"); } if (!this.AtsSxPMode & (this.State == AtsP.States.Normal | this.State == AtsP.States.Pattern | this.State == AtsP.States.Brake | this.State == AtsP.States.Service | this.State == AtsP.States.Emergency)) { blocking = true; } } else if (this.State != AtsP.States.Disabled & this.State != AtsP.States.Suppressed) { this.State = AtsP.States.Standby; } if (this.State != AtsP.States.Disabled & this.State != AtsP.States.Suppressed) { this.Train.Panel[2] = 1; this.Train.Panel[259] = 1; } if (this.State == AtsP.States.Pattern | this.State == AtsP.States.Brake | this.State == AtsP.States.Service | this.State == AtsP.States.Emergency) { this.Train.Panel[3] = 1; this.Train.Panel[260] = 1; } if (this.State == AtsP.States.Brake | this.State == AtsP.States.Service | this.State == AtsP.States.Emergency) { this.Train.Panel[5] = 1; this.Train.Panel[262] = 1; } if (this.State != AtsP.States.Disabled & this.State != AtsP.States.Suppressed & this.State != AtsP.States.Standby) { this.Train.Panel[6] = 1; this.Train.Panel[263] = 1; } if (this.State == AtsP.States.Initializing) { this.Train.Panel[7] = 1; this.Train.Panel[264] = 1; } if (this.State == AtsP.States.Disabled) { this.Train.Panel[50] = 1; } if (this.State != AtsP.States.Disabled & this.State != AtsP.States.Suppressed & this.State != AtsP.States.Standby & this.BrakeRelease) { this.Train.Panel[4] = 1; this.Train.Panel[261] = 1; } if (this.State == AtsP.States.Normal | this.State == AtsP.States.Pattern | this.State == AtsP.States.Brake | this.State == AtsP.States.Service | this.State == AtsP.States.Emergency) { StringBuilder stringBuilder = new StringBuilder(); for (int k = 0; k < (int)this.SignalPatterns.Length; k++) { this.SignalPatterns[k].AddToStringBuilder(string.Concat(k.ToString(), ":"), stringBuilder); } this.DivergencePattern.AddToStringBuilder("分岐/D:", stringBuilder); this.TemporaryPattern.AddToStringBuilder("臨時/T:", stringBuilder); this.CurvePattern.AddToStringBuilder("曲線/C:", stringBuilder); this.DownslopePattern.AddToStringBuilder("勾配/S:", stringBuilder); this.RoutePermanentPattern.AddToStringBuilder("P:", stringBuilder); this.TrainPermanentPattern.AddToStringBuilder("M:", stringBuilder); if (this.SwitchToAtsSxPosition != double.MaxValue) { if (stringBuilder.Length != 0) { stringBuilder.Append(", "); } double switchToAtsSxPosition = this.SwitchToAtsSxPosition - this.Position; stringBuilder.Append(string.Concat("Sx@", switchToAtsSxPosition.ToString("0"))); } if (stringBuilder.Length == 0) { data.DebugMessage = this.State.ToString(); return; } data.DebugMessage = string.Concat(this.State.ToString(), " - ", stringBuilder.ToString()); } }
public void Elapse(ElapseData _p1) { EData = _p1; try { Func.UpdateTimer(); Impl.Elapse(); } catch (Exception ex) { RuntimeExceptionBlocking(ex); } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { // --- behavior --- if (this.State == States.Pattern | this.State == States.Released) { this.Distance -= data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; } if (this.State == States.Pattern) { if (this.Train.Doors == DoorStates.None) { // --- doors closed --- const double maximumDeceleration = 4.2 / 3.6; const double delay = 0.5; const double exagerationFactor = 3.0; double offset = data.Vehicle.Speed.MetersPerSecond > 15.0 / 3.6 ? 3.0 : 0.0; int maximumBrakeNotch = this.Train.Specs.BrakeNotches - this.Train.Specs.AtsNotch + 1; int designBrakeNotch = (int)Math.Round(this.DesignDeceleration / maximumDeceleration * (double)maximumBrakeNotch); double denominator = 2.0 * (this.Distance - offset - delay * data.Vehicle.Speed.MetersPerSecond); if (denominator > 0.0) { // --- before the stop point --- double deceleration = data.Vehicle.Speed.MetersPerSecond * data.Vehicle.Speed.MetersPerSecond / denominator; double requiredBrakeNotch = deceleration / maximumDeceleration * (double)maximumBrakeNotch; requiredBrakeNotch = designBrakeNotch + (requiredBrakeNotch - designBrakeNotch) * exagerationFactor; int minimum; int maximum; if (requiredBrakeNotch < designBrakeNotch) { minimum = (int)Math.Floor(requiredBrakeNotch - 0.5); maximum = (int)Math.Floor(requiredBrakeNotch + 0.5); } else { minimum = (int)Math.Floor(requiredBrakeNotch + 0.5); maximum = (int)Math.Floor(requiredBrakeNotch + 1.5); } if (data.Vehicle.Speed.MetersPerSecond < 1.0 / 3.6 & this.Distance < 1.0) { this.BrakeNotch = maximumBrakeNotch; } else if (data.Vehicle.Speed.MetersPerSecond <13.0 / 3.6 | data.Vehicle.Speed.MetersPerSecond> 15.0 / 3.6) { if (this.BrakeNotch < minimum) { this.BrakeNotch = minimum; } else if (this.BrakeNotch > maximum) { this.BrakeNotch = maximum; } } else { this.BrakeNotch = designBrakeNotch; } if (!this.Override) { if (this.BrakeNotch > maximumBrakeNotch) { if (this.Train.TractionManager.CurrentInterventionBrakeNotch < this.Train.Specs.BrakeNotches) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application demanded by TASC"); } } else if (this.BrakeNotch > 0) { if (this.Train.TractionManager.CurrentInterventionBrakeNotch < this.BrakeNotch + this.Train.Specs.AtsNotch - 1) { Train.TractionManager.DemandBrakeApplication(this.BrakeNotch + this.Train.Specs.AtsNotch - 1, "Brake application demanded by TASC"); } } else if (requiredBrakeNotch > 0.0) { Train.TractionManager.DemandPowerCutoff("Power cutoff was demanded by the TASC"); } } data.DebugMessage = "TASC -- " + requiredBrakeNotch.ToString("0.0") + " @ " + this.Distance.ToString("0.00"); } else if (!this.Override) { // --- after the stop point --- if (this.Train.TractionManager.CurrentInterventionBrakeNotch < this.Train.Specs.BrakeNotches) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application demanded by TASC"); } data.DebugMessage = "TASC -- OVERRUN"; } } else if (!this.Override) { // --- doors opened --- if (this.Train.TractionManager.CurrentInterventionBrakeNotch < this.Train.Specs.BrakeNotches) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application demanded by TASC"); } data.DebugMessage = "TASC -- DOORBLOCK"; } } else if (this.State == States.Released) { if (Math.Abs(this.Distance) > 1.0) { this.State = States.Normal; this.BrakeNotch = 0; this.Distance = 0.0; this.HomeDoors = false; } data.DebugMessage = "TASC -- RELEASED"; } // --- panel --- if (this.Override) { this.Train.Panel[83] = 1; } this.Train.Panel[56] = 1; this.Train.Panel[80] = 1; if (this.State == States.Pattern) { this.Train.Panel[81] = 1; } if (this.BrakeNotch > 0) { this.Train.Panel[82] = 1; } if (this.Distance >= -0.35 & this.Distance <= 0.35) { this.Train.Panel[85] = 1; } if (this.Train.Doors == DoorStates.None) { this.Train.Panel[86] = 1; } if (!this.HomeDoors | this.Distance <-0.35 | this.Distance> 0.35 | this.Train.Doors == DoorStates.None) { this.Train.Panel[87] = 1; } this.Train.Panel[90] = this.BrakeNotch + this.Train.Specs.AtsNotch - 1; }
/// <summary>Called every frame to update the plugin.</summary> /// <param name="data">The data passed to the plugin on Elapse.</param> /// <remarks>This function should not be called directly. Call UpdatePlugin instead.</remarks> protected abstract void Elapse(ElapseData data);
public float Current; // Current (A) public ATS_VEHICLESTATE(ElapseData data) : this(data.Vehicle.Location, (float)data.Vehicle.Speed.KilometersPerHour, (int)data.TotalTime.Milliseconds, (float)data.Vehicle.BcPressure, (float)data.Vehicle.MrPressure, (float)data.Vehicle.ErPressure, (float)data.Vehicle.BpPressure, (float)data.Vehicle.SapPressure, 0.0f) { }
internal override int?Elapse(ElapseData data) { train.debugMessage = ""; //Detect jump to station if (lastFrameTrackPosition != null) { if (Math.Abs(lastFrameTrackPosition.Value - data.Vehicle.Location) > STATION_JUMP_THRESHOLD_DISTANCE) { //Reset ATO stopping pos atoStoppingPosition = null; } } lastFrameTrackPosition = data.Vehicle.Location; //Is train in Auto? if (train.trainModeSelected != Train.TrainModes.Auto) { atoState = AtoStates.Stopped; return(null); } if (atoState == AtoStates.Stopped) { atoStoppingPosition = null; return(-train.specs.BrakeNotches); } //Calculate current acceleration rate if (data.TotalTime.Seconds - accelerationLastPoll.Seconds >= ACCELERATION_POLL_RATE) { UpdateAcceleration(data); } //Calculate distance to stop double?distanceToNextStop = null; if (atoStoppingPosition != null) { distanceToNextStop = atoStoppingPosition - data.Vehicle.Location; } train.debugMessage = $"{atoState}"; if (atoState == AtoStates.Ready) { //At station counting down to departure atoDemands = -train.specs.BrakeNotches; readyTimer -= data.ElapsedTime.Seconds; if (readyTimer <= 0.0) { atoState = AtoStates.Enroute; } //Reset stop pos if closer than 25m else if (atoStoppingPosition != null && distanceToNextStop < 25) { atoStoppingPosition = null; } } else if (atoState == AtoStates.Enroute) { //Travelling to next station //Get the train to stick to the ATP Target Speed int atoTargetSpeedDemand = CalculateTargetSpeedNotchChange(data); //Run function for stopping at station int?atoStoppingDemand = null; if (atoStoppingPosition != null) { //Call a function that returns the desired brake/power notch (or null if none) atoStoppingDemand = CalculateStationStopNotchChange(data, distanceToNextStop ?? 0); } //Select the lowest notch between "TASC" and the target speed code above int notch = (atoDemands ?? 0) + Math.Min(atoStoppingDemand ?? train.specs.PowerNotches, atoTargetSpeedDemand); //Limit powering below 2km/h if (data.Vehicle.Speed.KilometersPerHour < 2.0) { notch = Math.Min(notch, 1); } //Call ChangeAtoDemands with appropriate time between notch ChangeAtoDemands(data, notch, ATO_TIME_BETWEEN_NOTCH_CHANGE, true, true); train.debugMessage = $"Enroute. TS {atoTargetSpeedDemand}, TASC {atoStoppingDemand}. Req {notch}. Actual {atoDemands}. Target speed {train.atpTargetSpeed}"; } if (atoReceivedData != null) { atoStoppingPosition = atoReceivedData + data.Vehicle.Location; atoReceivedData = null; } //train.debugMessage = $" Ato: {atoState} demanding {atoDemands} for {train.atpTargetSpeed}"; return(atoDemands); }
public void SetElapseData(ElapseData data) { chp.R = data.Handles.Reverser; chp.P = data.Handles.PowerNotch; chp.B = data.Handles.BrakeNotch; BIDSSharedMemoryData BSMD = new BIDSSharedMemoryData() { HandleData = new Hand() { B = data.Handles.BrakeNotch, P = data.Handles.PowerNotch, R = data.Handles.Reverser, C = data.Handles.ConstSpeed ? 1 : 0 }, StateData = new State() { BC = data.Vehicle.BcPressure.ToFloat(), BP = data.Vehicle.BpPressure.ToFloat(), ER = data.Vehicle.ErPressure.ToFloat(), I = 0, MR = data.Vehicle.MrPressure.ToFloat(), SAP = data.Vehicle.SapPressure.ToFloat(), T = (int)data.TotalTime.Milliseconds, V = data.Vehicle.Speed.KilometersPerHour.ToFloat(), Z = data.Vehicle.Location }, IsDoorClosed = data.DoorInterlockState == DoorInterlockStates.Locked, IsEnabled = true, VersionNum = int.Parse(StaticSMemLib.VersionNum), SpecData = new Spec() { B = hd.B, P = hd.P } }; OpenD OD = new OpenD() { Cant = data.Vehicle.Cant, ElapTime = data.ElapsedTime.Milliseconds, IsEnabled = true, Pitch = data.Vehicle.Pitch, Radius = data.Vehicle.Radius, SelfBPosition = data.Handles.LocoBrakeNotch, }; if (data.PrecedingVehicle != null) { OD.PreTrain = new OpenD.PreTrainD() { IsEnabled = true, Distance = data.PrecedingVehicle.Distance, Location = data.PrecedingVehicle.Location, Speed = data.PrecedingVehicle.Speed.KilometersPerHour }; } else { OD.PreTrain = new OpenD.PreTrainD() { IsEnabled = false } }; StaticSMemLib.Write(in BSMD); StaticSMemLib.Write(in OD); } Hand hd = new Hand();
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal override void Elapse(ElapseData data, ref bool blocking) { //Steam Locomotive Valve Gear distancetravelled = Train.TrainLocation - Train.PreviousLocation; //Then divide the distance travelled by the circumference to get us the percentage around the wheel travelled in this turn double percentage = ((distancetravelled * 1000) / wheelcircumference) * 35; //Multiply by 1000 to get the distance travelled in millimeters //Then divide by the wheel's circumference //Finally multiply by 100 to get a figure out of 100 if (Math.Abs(percentage) > 100) { //If percentage is above 100%, set to zero //This should never go above 100% unless with tiny wheels at silly speed //When initialising, the train location returns zero until everything has fully loaded //This can produce very large percentage values when the starting location is 100s of m //down the route percentage = 0; } //Figure out where we are in relation to 100% if (wheelpercentage - percentage <= 100 && wheelpercentage - percentage >= 0) { wheelpercentage -= percentage; } else { wheelpercentage = 100 - percentage; } //Now calculate the number of degrees turn this represents degreesturned = 3.6 * wheelpercentage; //Right Gear Position if (gear_Yvariable_R != -1 && gear_Zvariable_R != -1 && rodradius != 0) { //Calculate the Y and Z positions gear_Ylocation_R = (-rodradius * Math.Sin((Math.PI / 180) * degreesturned)); gear_Zlocation_R = (rodradius * Math.Cos((Math.PI / 180) * degreesturned)); this.Train.Panel[gear_Yvariable_R] = (int)gear_Ylocation_R; this.Train.Panel[gear_Zvariable_R] = (int)gear_Zlocation_R; } //Left Gear Position if (gear_Yvariable_L != -1 && gear_Zvariable_L != -1 && rodradius != 0) { //Calculate the Y and Z positions gear_Ylocation_L = (-rodradius * Math.Sin((Math.PI / 180) * (degreesturned + 90))); gear_Zlocation_L = (rodradius * Math.Cos((Math.PI / 180) * (degreesturned + 90))); this.Train.Panel[gear_Yvariable_L] = (int)gear_Ylocation_L; this.Train.Panel[gear_Zvariable_L] = (int)gear_Zlocation_L; } if (wheelrotation_variable != -1) { //Calculate the wheel rotation value- Use this rather than an animated formula, as otherwise the gear and wheel may become out of sync this.Train.Panel[wheelrotation_variable] = (int)(((Math.PI / 180) * (360 - degreesturned)) * 1000); } //Piston Crosshead Location Right if (crankvariable_R != -1 && crankrotation_R != -1 && crankradius != 0 && cranklength != 0) { //We've already worked out the number of degrees turned for the main crankshaft. //Work out the crank throw distance cranklocation_R = crankradius * Math.Cos((Math.PI / 180) * (degreesturned + 90)) + Math.Sqrt(Math.Pow(cranklength, 2) - Math.Pow(crankradius, 2) * Math.Pow(Math.Sin((Math.PI / 180) * (degreesturned + 90)), 2)); this.Train.Panel[crankvariable_R] = (int)cranklocation_R; crankangle_R = Math.Asin(crankradius * Math.Sin((Math.PI / 180) * (degreesturned + 90)) / cranklength); this.Train.Panel[crankrotation_R] = (int)((crankangle_R * 1000) / 2); } //Piston Crosshead Location Left if (crankvariable_L != -1 && crankrotation_L != -1 && crankradius != 0 && cranklength != 0) { //We've already worked out the number of degrees turned for the main crankshaft. //Work out the crank throw distance cranklocation_L = crankradius * Math.Cos((Math.PI / 180) * (degreesturned + 180)) + Math.Sqrt(Math.Pow(cranklength, 2) - Math.Pow(crankradius, 2) * Math.Pow(Math.Sin((Math.PI / 180) * (degreesturned + 180)), 2)); this.Train.Panel[crankvariable_L] = (int)cranklocation_L; crankangle_L = Math.Asin(crankradius * Math.Sin((Math.PI / 180) * (degreesturned + 180)) / cranklength); this.Train.Panel[crankrotation_L] = (int)((crankangle_L * 1000) / 2); } //Cylinder cocks puff state is handled in the animations class, but pressure usage is handled in the steam traction class if (this.Train.SteamEngine != null && cylinderpuff_L != -1) { if (Train.SteamEngine.cylindercocks == true) { if (Train.CurrentSpeed == 0 && Train.Handles.PowerNotch == 0) { CylinderPuffState_L = CylinderPuffStates.OpenStationary; } else if (Train.CurrentSpeed == 0 && Train.Handles.PowerNotch > 0) { CylinderPuffState_L = CylinderPuffStates.OpenStationaryPowered; } else if (Train.CurrentSpeed > 0 && Train.Handles.PowerNotch == 0) { if (wheelpercentage > 25 && wheelpercentage < 65) { CylinderPuffState_L = CylinderPuffStates.OpenPuffingUnpowered; } else { CylinderPuffState_L = CylinderPuffState_L = CylinderPuffStates.OpenNoPuff; } } else { if (wheelpercentage > 30 && wheelpercentage < 70) { CylinderPuffState_L = CylinderPuffStates.OpenPuffingPowered; } else { CylinderPuffState_L = CylinderPuffState_L = CylinderPuffStates.OpenNoPuff; } } } else { CylinderPuffState_L = CylinderPuffStates.CockClosed; } this.Train.Panel[(cylinderpuff_L)] = (int)CylinderPuffState_L; } if (this.Train.SteamEngine != null && cylinderpuff_R != -1) { if (Train.SteamEngine.cylindercocks == true) { if (Train.CurrentSpeed == 0 && Train.Handles.PowerNotch == 0) { CylinderPuffState_R = CylinderPuffStates.OpenStationary; } else if (Train.CurrentSpeed == 0 && Train.Handles.PowerNotch > 0) { CylinderPuffState_R = CylinderPuffStates.OpenStationaryPowered; } else if (Train.CurrentSpeed > 0 && Train.Handles.PowerNotch == 0) { if (wheelpercentage > 5 && wheelpercentage < 45) { CylinderPuffState_R = CylinderPuffStates.OpenPuffingUnpowered; } else { CylinderPuffState_R = CylinderPuffState_L = CylinderPuffStates.OpenNoPuff; } } else { if (wheelpercentage > 5 && wheelpercentage < 45) { CylinderPuffState_R = CylinderPuffStates.OpenPuffingPowered; } else { CylinderPuffState_R = CylinderPuffState_L = CylinderPuffStates.OpenNoPuff; } } } else { CylinderPuffState_R = CylinderPuffStates.CockClosed; } this.Train.Panel[(cylinderpuff_R)] = (int)CylinderPuffState_R; } //Flashing door light { if (MyDoorLightState == DoorLightStates.InMotion) { doorlighttimer = 0; } else if (MyDoorLightState == DoorLightStates.Primed) { if (Train.CurrentSpeed == 0) { if (Train.Doors != DoorStates.None) { MyDoorLightState = DoorLightStates.DoorsOpen; } } } else if (MyDoorLightState == DoorLightStates.DoorsOpen) { MyDoorLightState = DoorLightStates.Countdown; } else if (MyDoorLightState == DoorLightStates.Countdown) { //We've opened our train doors- //Compare the current time with the departure time //Do nothing if we are early, just wait if (Train.SecondsSinceMidnight > (departuretime - stoptime)) { doorlighttimer += data.ElapsedTime.Milliseconds; if (doorlighttimer > stoptime) { MyDoorLightState = DoorLightStates.DoorsClosing; doorlighttimer = 0; } } } else if (MyDoorLightState == DoorLightStates.DoorsClosing) { doorlighttimer += data.ElapsedTime.Milliseconds; doorlighttimer2 += data.ElapsedTime.Milliseconds; if (doorlighttimer2 > 1000) { if (doorlighton == true) { doorlighton = false; } else { doorlighton = true; } doorlighttimer2 = 0; } if (doorlighttimer > 30000) { doorlighton = false; MyDoorLightState = DoorLightStates.DoorsClosed; } } else if (MyDoorLightState == DoorLightStates.DoorsClosed) { if (Train.CurrentSpeed > 0) { MyDoorLightState = DoorLightStates.InMotion; } } } //Headcode state { if (headcodeindex != -1) { this.Train.Panel[headcodeindex] = headcodestate; } } }
/// <summary>Is called every frame.</summary> /// <param name="data">The data.</param> /// <param name="blocking">Whether the device is blocked or will block subsequent devices.</param> internal abstract void Elapse(ElapseData data, ref bool blocking);
public void Elapse(ElapseData data) { }
/// <summary> /// 1フレームごとに呼び出される関数 /// </summary> /// <param name="data">The data.</param> /// <param name="blocking">保安装置がブロックされているか、後続の保安装置をブロックするかどうか。</param> internal override void Elapse(ElapseData data, ref bool blocking) { PlayAtcAirSound(); // --- パネル --- }