private void SwitchToP(AtsP.States state) { if (this.State == AtsP.States.Standby) { if (this.Train.AtsSx == null || this.Train.AtsSx.State != AtsSx.States.Emergency) { this.State = state; if (!this.Blocked) { if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } return; } } } else if (state == AtsP.States.Service | state == AtsP.States.Emergency) { if (this.State != AtsP.States.Brake & this.State != AtsP.States.Service & this.State != AtsP.States.Emergency && !this.Blocked) { if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } this.State = state; } }
private void SwitchToSx() { if (this.Train.AtsSx != null) { AtsP.Pattern[] patterns = this.Patterns; for (int i = 0; i < (int)patterns.Length; i++) { patterns[i].Clear(); } this.State = AtsP.States.Standby; if (!this.Blocked) { if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } this.Train.AtsSx.State = AtsSx.States.Chime; } else if (this.State != AtsP.States.Emergency) { this.State = AtsP.States.Emergency; if (this.State != AtsP.States.Brake & this.State != AtsP.States.Service && !this.Blocked) { if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } } } this.SwitchToAtsSxPosition = double.MaxValue; this.DAtsPActive = false; }
internal override void Elapse(ElapseData data, ref bool blocking) { if (this.State == AtsSx.States.Suppressed && this.Train.TractionManager.CurrentInterventionBrakeNotch <= this.Train.Specs.BrakeNotches) { this.AlarmCountdown = this.DurationOfInitialization; this.State = AtsSx.States.Initializing; } if (this.State == AtsSx.States.Initializing) { if (!SoundManager.IsPlaying(CommonSounds.ATSBell)) { SoundManager.Play(CommonSounds.ATSBell, 1.0, 1.0, false); } AtsSx alarmCountdown = this; alarmCountdown.AlarmCountdown = alarmCountdown.AlarmCountdown - data.ElapsedTime.Seconds; if (this.AlarmCountdown <= 0) { this.State = AtsSx.States.Chime; } } if (!blocking) { if (this.State == AtsSx.States.Blocked) { this.State = AtsSx.States.Chime; } if (this.State == AtsSx.States.Chime) { if (!SoundManager.IsPlaying(CommonSounds.ATSChime)) { SoundManager.Play(CommonSounds.ATSChime, 1.0, 1.0, false); } } else if (this.State == AtsSx.States.Alarm) { if (!SoundManager.IsPlaying(CommonSounds.ATSBell)) { SoundManager.Play(CommonSounds.ATSBell, 1.0, 1.0, false); } AtsSx atsSx = this; atsSx.AlarmCountdown = atsSx.AlarmCountdown - data.ElapsedTime.Seconds; if (this.AlarmCountdown <= 0) { this.State = AtsSx.States.Emergency; } } else if (this.State == AtsSx.States.Emergency) { if (!SoundManager.IsPlaying(CommonSounds.ATSBell)) { SoundManager.Play(CommonSounds.ATSBell, 1.0, 1.0, false); } if (!Train.TractionManager.BrakeInterventionDemanded) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches, "Brake application demanded by ATS-Sx"); } } if (this.SpeedCheckCountdown > 0 & data.ElapsedTime.Seconds > 0) { AtsSx speedCheckCountdown = this; speedCheckCountdown.SpeedCheckCountdown = speedCheckCountdown.SpeedCheckCountdown - data.ElapsedTime.Seconds; } if (this.CompatibilityDistanceAccumulator != 0) { AtsSx compatibilityDistanceAccumulator = this; compatibilityDistanceAccumulator.CompatibilityDistanceAccumulator = compatibilityDistanceAccumulator.CompatibilityDistanceAccumulator + data.Vehicle.Speed.MetersPerSecond * data.ElapsedTime.Seconds; if (this.CompatibilityDistanceAccumulator > 27.7) { this.CompatibilityDistanceAccumulator = 0; } } } else if (this.State != AtsSx.States.Disabled & this.State != AtsSx.States.Suppressed) { this.State = AtsSx.States.Blocked; } AtsSx compatibilityAccidentalDepartureCounter = this; compatibilityAccidentalDepartureCounter.CompatibilityAccidentalDepartureCounter = compatibilityAccidentalDepartureCounter.CompatibilityAccidentalDepartureCounter + data.ElapsedTime.Seconds; if (this.State == AtsSx.States.Chime | this.State == AtsSx.States.Normal) { this.Train.Panel[0] = 1; this.Train.Panel[256] = 1; } if (this.State == AtsSx.States.Initializing | this.State == AtsSx.States.Alarm) { this.Train.Panel[1] = 1; this.Train.Panel[257] = 1; this.Train.Panel[258] = 1; return; } if (this.State == AtsSx.States.Emergency) { int num = ((int)data.TotalTime.Milliseconds % 1000 < 500 ? 1 : 0); this.Train.Panel[1] = num; this.Train.Panel[257] = 2; this.Train.Panel[258] = num; } }
/// <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) { //Check we've got a maximum temperature and a heating part if (overheat != 0 && heatingpart != 0) { this.heatingtimer += data.ElapsedTime.Milliseconds; if (heatingpart == 0 || overheat == 0) { //No heating part or overheat temperature not set this.temperature = 0.0; this.heatingtimer = 0.0; } else if (heatingpart == 1) { //Heats based upon power notch if (this.heatingtimer > 1000) { this.heatingtimer = 0.0; if (Train.Handles.PowerNotch == 0) { currentheat = heatingarray[0]; } else if (Train.Handles.PowerNotch < heatingarray.Length) { currentheat = heatingarray[Train.Handles.PowerNotch]; } else { currentheat = heatingarray[heatingarray.Length - 1]; } temperature += currentheat; } } else { //Heats based upon RPM- Not on a steam loco! this.temperature = 0.0; this.heatingtimer = 0.0; } //Keep temperature below max & above zero if (temperature > overheat) { temperature = overheat; if (overheatresult == 1) { Train.TractionManager.DemandPowerCutoff("Traction power cutoff was demanded due to the steam engine overheating"); Train.TractionManager.EngineOverheated = true; } } else if (temperature < overheat && temperature > 0) { Train.TractionManager.ResetPowerCutoff(); Train.TractionManager.EngineOverheated = false; } else if (temperature < 0) { temperature = 0; } } //First try to set automatic cutoff without calculating if (this.Train.TractionManager.AutomaticAdvancedFunctions == true && Train.CurrentSpeed == 0) { if (Train.Handles.Reverser == 0) { //If reverser is in neutral, reset cutoff to 30 cutoff = 30; } else if (Train.Handles.Reverser == 1 && cutoff >= cutoffineffective) { cutoff = cutoffmax; } else if (Train.Handles.Reverser == -1 && cutoff >= cutoffineffective) { cutoff = cutoffmin; } } else { double setcutoff = cutoff; if (cutoffstate == 1) { //Set Cutoff Up if (cutoff < cutoffmax) { this.cutofftimer += data.ElapsedTime.Milliseconds; if (this.cutofftimer > cutoffchangespeed) { setcutoff = setcutoff + 1; cutofftimer = 0.0; } } } else if (cutoffstate == -1) { //Set Cutoff Down if (cutoff > cutoffmin) { this.cutofftimer += data.ElapsedTime.Milliseconds; if (this.cutofftimer > cutoffchangespeed) { setcutoff = setcutoff - 1; cutofftimer = 0.0; } } } else { //twiddle our thumbs } cutoff = setcutoff; } //Manual { //This section of code operates the reverser & cutoff if (cutoff > cutoffineffective && (cutoffdeviation != 0)) { new_reverser = 1; //Called to workout the optimum cutoff if we're over the optimum max cutoff speed FW if (data.Vehicle.Speed.KilometersPerHour > cutoffratiobase) { speed = data.Vehicle.Speed.KilometersPerHour - cutoffratiobase; optimalcutoff = cutoffmax - speed * cutoffratio / 10; new_power = Math.Max((int)(this.Train.Specs.PowerNotches - ((optimalcutoff - cutoff) < 0 ? -(optimalcutoff - cutoff) : (optimalcutoff - cutoff)) / (int)cutoffdeviation), 0); //Automagically set cutofff if (this.Train.TractionManager.AutomaticAdvancedFunctions == true) { cutoff = (int)Math.Max(optimalcutoff, cutoffineffective + 1); } } else { new_power = Math.Max((int)(this.Train.Specs.PowerNotches - (((int)cutoffmax - cutoff) < 0 ? -((int)cutoffmax - cutoff) : ((int)cutoffmax - cutoff)) / cutoffdeviation), 0); } } else if (cutoff < cutoffineffective && cutoffdeviation != 0) { new_reverser = -1; //Called to workout the optimum cutoff if we're over the optimum max cutoff speed RV if (Math.Abs(data.Vehicle.Speed.KilometersPerHour) > cutoffratiobase) { speed = Math.Abs(data.Vehicle.Speed.KilometersPerHour) - cutoffratiobase; optimalcutoff = cutoffmin + speed * cutoffratio / 10; new_power = Math.Max((int)(this.Train.Specs.PowerNotches - ((optimalcutoff - cutoff) < 0 ? -(optimalcutoff - cutoff) : (optimalcutoff - cutoff)) / (int)cutoffdeviation), 0); //Automagically set cutoff if (this.Train.TractionManager.AutomaticAdvancedFunctions == true) { cutoff = (int)Math.Min(optimalcutoff, -cutoffineffective - 1); } } else { new_power = Math.Max((int)(this.Train.Specs.PowerNotches - ((Math.Abs(cutoffmin) - Math.Abs(cutoff)) < 0 ? -((int)Math.Abs(cutoffmin) - Math.Abs(cutoff)) : ((int)Math.Abs(cutoffmin) - Math.Abs(cutoff))) / cutoffdeviation), 0); } } else { new_reverser = 0; new_power = 0; } } //CALL NEW FUNCTION TO SET THE REVERSER STATE if (new_reverser != stm_reverser) { stm_reverser = new_reverser; data.Handles.Reverser = stm_reverser; } else { data.Handles.Reverser = stm_reverser; } { //This section of code operates the pressure power drop double bp = Math.Max(stm_boilerpressure - boilerminpressure, 0); int bp_range = (int)boilermaxpressure - (int)boilerminpressure; int pwr_limit = Math.Min(new_power, (int)((bp / (float)(bp_range) + (1.0 / this.Train.Specs.PowerNotches - 0.01)) * this.Train.Specs.PowerNotches)); new_power = Math.Max(Train.Handles.PowerNotch - this.Train.Specs.PowerNotches + pwr_limit, 0); //CALL NEW FUNCTION TO CHANGE POWER } if (Train.drastate != true) { stm_power = new_power; LastPower = new_power; Train.TractionManager.SetMaxPowerNotch(stm_power, false); } { //This section of code generates pressure and operates the blowoff //First elapse the main timer function this.maintimer += data.ElapsedTime.Seconds; //This section of code handles the fire simulator if (advancedfiring == false) { //Advanced firing is not enabled, use the standard boiler water to steam rate finalsteamrate = calculatedsteamrate; } else { //Advanced firing if (this.maintimer > 1) { //Check whether we can shovel coal //Firemass must be below maximum and shovelling true [Non automatic] //If automatic firing is on, only shovel coal if we are below 50% of max fire mass- Change??? //Use automatic behaviour if no shovelling key is set as obviously we can't shovel coal manually with no key if (shovelling == true && firemass < maximumfiremass || this.Train.TractionManager.AutomaticAdvancedFunctions == true && firemass < (firemass / 2) && firemass < maximumfiremass || Train.CurrentKeyConfiguration.ShovelFuel == null && firemass < (firemass / 2) && firemass < maximumfiremass) { //Add the amount of coal shovelled per second to the fire mass & decrease it from the fire temperature firemass += (int)shovellingrate; firetemp -= (int)shovellingrate; } int fire_tempchange; if (firemass != 0) { if (Blowers.Active) { fire_tempchange = (int)Math.Ceiling((double)(((firemass * 0.5) - 10) / (firemass * 0.05)) * Blowers.FireTempIncreaseFactor); } else { fire_tempchange = (int)Math.Ceiling((double)(((firemass * 0.5) - 10) / (firemass * 0.05))); } } else { //Temperature change must be zero if our fire mass is zero //Otherwise causes a division by zero error.... fire_tempchange = 0; } firemass = (int)((double)firemass * 0.9875); if (firetemp < 1000) { //Add calculated temperature increase to the fire temperature firetemp += fire_tempchange; } else { //Otherwise set to max firetemp = 1000; } if (Blowers.Active == true) { finalsteamrate = (int)((((double)calculatedsteamrate / 1000) * firetemp) * Blowers.PressureIncreaseFactor); } else { finalsteamrate = (int)(((double)calculatedsteamrate / 1000) * firetemp); } } } if (this.maintimer > 1) { if (Blowers.Active == true) { pressureup = (int)(((boilerwatertosteamrate / 60) * maintimer) * Blowers.PressureIncreaseFactor); } else { pressureup = (int)((boilerwatertosteamrate / 60) * maintimer); } stm_boilerpressure = stm_boilerpressure + pressureup; stm_boilerwater = stm_boilerwater - pressureup; //Newer standard blowoff handling if (stm_boilerpressure > boilermaxpressure) { switch (Blowoff.BlowoffState) { case Blowoff.BlowoffStates.None: //Switch to the over maximum pressure state, as we are over the max pressure Blowoff.BlowoffState = Blowoff.BlowoffStates.OverMaxPressure; Blowoff.Played = false; break; case Blowoff.BlowoffStates.OverMaxPressure: if (stm_boilerpressure > Blowoff.TriggerPressure) { //If our boiler pressure is over the blowoff pressure, then switch to blowoff Blowoff.BlowoffState = Blowoff.BlowoffStates.Blowoff; break; } //Otherwise, reduce the pressure by 4 //This is an OS_ATS quirk, remove??? stm_boilerpressure = stm_boilerpressure - 4; break; case Blowoff.BlowoffStates.Blowoff: //Trigger the sound- Play only once if (!SoundManager.IsPlaying(Blowoff.SoundIndex) && Blowoff.Played == false) { SoundManager.Play(Blowoff.SoundIndex, 1.0, 1.0, false); } Blowoff.Timer += maintimer; if (Blowoff.BlowoffRate != 0) { //If a blowoff time has been set, then reduce the pressure by the calculated blowoff rate stm_boilerpressure -= (int)Blowoff.BlowoffRate; } else { //Otherwise, just run a simple 10-second timer if (Blowoff.Timer > 10) { //Now reduce the boiler pressure to max, and drop the state back to none stm_boilerpressure = (int)boilermaxpressure; Blowoff.BlowoffState = Blowoff.BlowoffStates.None; } } break; } } else { Blowoff.BlowoffState = Blowoff.BlowoffStates.None; } } } if (this.Train.TractionManager.AutomaticAdvancedFunctions == true) { Blowers.Timer += data.ElapsedTime.Milliseconds; //This section of code operates the automatic injectors if (stm_boilerwater > boilermaxwaterlevel / 2 && stm_boilerpressure > boilermaxpressure / 4) { if (LiveSteamInjector.Active == true && Blowers.Timer > 10000) { LiveSteamInjector.Active = false; Train.DebugLogger.LogMessage("The automatic fireman de-activated the injectors"); Blowers.Timer = 0.0; } if (pressureuse > ((boilerwatertosteamrate / 60) * maintimer) * 1.5) { //Turn on the blowers if we're using 50% more pressure than we're generating if (Blowers.Active == false && Blowers.Timer > 10000) { Train.DebugLogger.LogMessage("The automatic fireman activated the blowers"); Blowers.Active = true; Blowers.Timer = 0.0; } } else { if (Blowers.Active == true && Blowers.Timer > 10000) { Train.DebugLogger.LogMessage("The automatic fireman de-activated the blowers"); Blowers.Active = false; Blowers.Timer = 0.0; } } } else { //Blowers shouldn't be on at the same time as the injectors if (LiveSteamInjector.Active == false && Blowers.Timer > 10000) { Train.DebugLogger.LogMessage("The automatic fireman activated the injectors"); LiveSteamInjector.Active = true; Blowers.Timer = 0.0; } Blowers.Active = false; } } LiveSteamInjector.Update(data.ElapsedTime.Seconds, ref stm_boilerwater, ref stm_boilerpressure, ref fuel); //This section of code governs pressure usage if (stm_reverser != 0) { double regpruse = ((double)Train.Handles.PowerNotch / (double)this.Train.Specs.PowerNotches) * regulatorpressureuse; //32 float cutprboost = Math.Abs((float)cutoff) / Math.Abs((float)cutoffmax); //1 float spdpruse = 1 + Math.Abs((float)data.Vehicle.Speed.KilometersPerHour) / 25; if (maintimer > 1) { pressureuse = (int)(regpruse * cutprboost * spdpruse); stm_boilerpressure = stm_boilerpressure - pressureuse; } } //This section of code governs the pressure used by the horn if (klaxonpressureuse != -1 && (Train.TractionManager.primaryklaxonplaying || Train.TractionManager.secondaryklaxonplaying || Train.TractionManager.musicklaxonplaying)) { if (this.maintimer > 1) { stm_boilerpressure = stm_boilerpressure - (int)klaxonpressureuse; } } //This section of code defines the pressure used by the train's steam heating system if (steamheatpressureuse != -1 && steamheatlevel != 0) { if (maintimer > 1) { stm_boilerpressure -= (int)(steamheatlevel * steamheatpressureuse); } } //This section of code fills our tanks from a water tower if (fuelling == true) { if (maintimer > 1) { fuel += (int)fuelfillspeed; } if (fuel > fuelcapacity) { fuel = (int)fuelcapacity; } } //Pass data to the debug window if (AdvancedDriving.CheckInst != null) { //Calculate total pressure usage figure int debugpressureuse = pressureuse; if (Train.TractionManager.primaryklaxonplaying || Train.TractionManager.secondaryklaxonplaying || Train.TractionManager.musicklaxonplaying) { debugpressureuse += (int)klaxonpressureuse; } if (steamheatpressureuse != -1 && steamheatlevel != 0) { debugpressureuse += (int)(steamheatlevel * steamheatpressureuse); } if (CylinderCocks.Active == true) { debugpressureuse += (int)(cylindercocks_basepressureuse + (cylindercocks_notchpressureuse * Train.Handles.PowerNotch)); } this.Train.TractionManager.DebugWindowData.SteamEngine.BoilerPressure = (int)stm_boilerpressure; this.Train.TractionManager.DebugWindowData.SteamEngine.PressureGenerationRate = pressureup; this.Train.TractionManager.DebugWindowData.SteamEngine.PressureUsageRate = debugpressureuse; this.Train.TractionManager.DebugWindowData.SteamEngine.CurrentCutoff = (int)cutoff; this.Train.TractionManager.DebugWindowData.SteamEngine.OptimalCutoff = (int)optimalcutoff; this.Train.TractionManager.DebugWindowData.SteamEngine.FireMass = firemass; this.Train.TractionManager.DebugWindowData.SteamEngine.FireTemperature = firetemp; this.Train.TractionManager.DebugWindowData.SteamEngine.Injectors = LiveSteamInjector.Active; this.Train.TractionManager.DebugWindowData.SteamEngine.Blowers = Blowers.Active; this.Train.TractionManager.DebugWindowData.SteamEngine.BoilerWaterLevel = Convert.ToString(stm_boilerwater) + " of " + Convert.ToString(boilermaxwaterlevel, CultureInfo.InvariantCulture); this.Train.TractionManager.DebugWindowData.SteamEngine.TanksWaterLevel = Convert.ToString(fuel) + " of " + Convert.ToString(fuelcapacity, CultureInfo.InvariantCulture); this.Train.TractionManager.DebugWindowData.SteamEngine.AutoCutoff = this.Train.TractionManager.AutomaticAdvancedFunctions; if (cylindercocks == true) { this.Train.TractionManager.DebugWindowData.SteamEngine.CylinderCocks = "Open"; } else { this.Train.TractionManager.DebugWindowData.SteamEngine.CylinderCocks = "Closed"; } } { //Set Panel Indicators if (cutoffindicator != -1) { this.Train.Panel[(cutoffindicator)] = (int)cutoff; } if (boilerpressureindicator != -1) { this.Train.Panel[boilerpressureindicator] = (int)stm_boilerpressure; } if (boilerwaterlevelindicator != -1) { this.Train.Panel[boilerwaterlevelindicator] = (int)stm_boilerwater; } if (fuelindicator != -1) { this.Train.Panel[fuelindicator] = (int)fuel; } if (automaticindicator != -1) { if (this.Train.TractionManager.AutomaticAdvancedFunctions == false) { this.Train.Panel[automaticindicator] = 0; } else { this.Train.Panel[automaticindicator] = 1; } } if (thermometer != -1) { this.Train.Panel[thermometer] = (int)temperature; } if (overheatindicator != -1) { if (temperature > overheatwarn) { this.Train.Panel[overheatindicator] = 1; } else { this.Train.Panel[overheatindicator] = 0; } } if (fuelfillindicator != -1) { if (fuelling == true) { this.Train.Panel[fuelfillindicator] = 1; } } if (Blowoff.PanelIndex != -1) { if (Blowoff.BlowoffState == Blowoff.BlowoffStates.Blowoff) { this.Train.Panel[Blowoff.PanelIndex] = 1; } else { this.Train.Panel[Blowoff.PanelIndex] = 0; } } if (steamheatindicator != -1) { this.Train.Panel[steamheatindicator] = steamheatlevel; } } //Reset the main timer if it's over 1 second if (this.maintimer > 1) { this.maintimer = 0.0; } }
internal static void PlayLoop(VirtualKeys key) { VirtualKeys virtualKey = key; switch (virtualKey) { case VirtualKeys.S: if (SoundManager.IsPlaying(Keysloop[10])) { SoundManager.Stop(Keysloop[10]); } else { SoundManager.Play(Keysloop[10], 1.0, 1.0, true); } break; case VirtualKeys.A1: if (SoundManager.IsPlaying(Keysloop[37])) { SoundManager.Stop(Keysloop[37]); } else { SoundManager.Play(Keysloop[37], 1.0, 1.0, true); } break; case VirtualKeys.A2: if (SoundManager.IsPlaying(Keysloop[36])) { SoundManager.Stop(Keysloop[36]); } else { SoundManager.Play(Keysloop[36], 1.0, 1.0, true); } break; case VirtualKeys.B1: if (SoundManager.IsPlaying(Keysloop[35])) { SoundManager.Stop(Keysloop[35]); } else { SoundManager.Play(Keysloop[35], 1.0, 1.0, true); } break; case VirtualKeys.B2: if (SoundManager.IsPlaying(Keysloop[34])) { SoundManager.Stop(Keysloop[34]); } else { SoundManager.Play(Keysloop[34], 1.0, 1.0, true); } break; case VirtualKeys.C1: if (SoundManager.IsPlaying(Keysloop[33])) { SoundManager.Stop(Keysloop[33]); } else { SoundManager.Play(Keysloop[33], 1.0, 1.0, true); } break; case VirtualKeys.C2: if (SoundManager.IsPlaying(Keysloop[32])) { SoundManager.Stop(Keysloop[32]); } else { SoundManager.Play(Keysloop[32], 1.0, 1.0, true); } break; case VirtualKeys.D: if (SoundManager.IsPlaying(Keysloop[2])) { SoundManager.Stop(Keysloop[2]); } else { SoundManager.Play(Keysloop[2], 1.0, 1.0, true); } break; case VirtualKeys.E: if (SoundManager.IsPlaying(Keysloop[3])) { SoundManager.Stop(Keysloop[3]); } else { SoundManager.Play(Keysloop[3], 1.0, 1.0, true); } break; case VirtualKeys.F: if (SoundManager.IsPlaying(Keysloop[4])) { SoundManager.Stop(Keysloop[4]); } else { SoundManager.Play(Keysloop[4], 1.0, 1.0, true); } break; case VirtualKeys.G: if (SoundManager.IsPlaying(Keysloop[5])) { SoundManager.Stop(Keysloop[5]); } else { SoundManager.Play(Keysloop[5], 1.0, 1.0, true); } break; case VirtualKeys.H: if (SoundManager.IsPlaying(Keysloop[6])) { SoundManager.Stop(Keysloop[6]); } else { SoundManager.Play(Keysloop[6], 1.0, 1.0, true); } break; case VirtualKeys.I: if (SoundManager.IsPlaying(Keysloop[7])) { SoundManager.Stop(Keysloop[7]); } else { SoundManager.Play(Keysloop[7], 1.0, 1.0, true); } break; case VirtualKeys.J: if (SoundManager.IsPlaying(Keysloop[8])) { SoundManager.Stop(Keysloop[8]); } else { SoundManager.Play(Keysloop[8], 1.0, 1.0, true); } break; case VirtualKeys.K: if (SoundManager.IsPlaying(Keysloop[9])) { SoundManager.Stop(Keysloop[9]); } else { SoundManager.Play(Keysloop[9], 1.0, 1.0, true); } break; case VirtualKeys.L: if (SoundManager.IsPlaying(Keysloop[0])) { SoundManager.Stop(Keysloop[0]); } else { SoundManager.Play(Keysloop[0], 1.0, 1.0, true); } break; case VirtualKeys.EngineStart: if (SoundManager.IsPlaying(Keysloop[31])) { SoundManager.Stop(Keysloop[31]); } else { SoundManager.Play(Keysloop[31], 1.0, 1.0, true); } break; case VirtualKeys.EngineStop: if (SoundManager.IsPlaying(Keysloop[30])) { SoundManager.Stop(Keysloop[30]); } else { SoundManager.Play(Keysloop[30], 1.0, 1.0, true); } break; case VirtualKeys.Blowers: if (SoundManager.IsPlaying(Keysloop[29])) { SoundManager.Stop(Keysloop[29]); } else { SoundManager.Play(Keysloop[29], 1.0, 1.0, true); } break; case VirtualKeys.ExhaustSteamInjector: if (SoundManager.IsPlaying(Keysloop[28])) { SoundManager.Stop(Keysloop[28]); } else { SoundManager.Play(Keysloop[28], 1.0, 1.0, true); } break; case VirtualKeys.IncreaseCutoff: if (SoundManager.IsPlaying(Keysloop[27])) { SoundManager.Stop(Keysloop[27]); } else { SoundManager.Play(Keysloop[27], 1.0, 1.0, true); } break; case VirtualKeys.DecreaseCutoff: if (SoundManager.IsPlaying(Keysloop[26])) { SoundManager.Stop(Keysloop[26]); } else { SoundManager.Play(Keysloop[26], 1.0, 1.0, true); } break; case VirtualKeys.FillFuel: if (SoundManager.IsPlaying(Keysloop[25])) { SoundManager.Stop(Keysloop[25]); } else { SoundManager.Play(Keysloop[25], 1.0, 1.0, true); } break; case VirtualKeys.GearDown: if (SoundManager.IsPlaying(Keysloop[24])) { SoundManager.Stop(Keysloop[24]); } else { SoundManager.Play(Keysloop[24], 1.0, 1.0, true); } break; case VirtualKeys.GearUp: if (SoundManager.IsPlaying(Keysloop[23])) { SoundManager.Stop(Keysloop[23]); } else { SoundManager.Play(Keysloop[23], 1.0, 1.0, true); } break; case VirtualKeys.LeftDoors: if (SoundManager.IsPlaying(Keysloop[22])) { SoundManager.Stop(Keysloop[22]); } else { SoundManager.Play(Keysloop[22], 1.0, 1.0, true); } break; case VirtualKeys.RightDoors: if (SoundManager.IsPlaying(Keysloop[21])) { SoundManager.Stop(Keysloop[21]); } else { SoundManager.Play(Keysloop[21], 1.0, 1.0, true); } break; case VirtualKeys.LiveSteamInjector: if (SoundManager.IsPlaying(Keysloop[20])) { SoundManager.Stop(Keysloop[20]); } else { SoundManager.Play(Keysloop[20], 1.0, 1.0, true); } break; case VirtualKeys.LowerPantograph: if (SoundManager.IsPlaying(Keysloop[19])) { SoundManager.Stop(Keysloop[19]); } else { SoundManager.Play(Keysloop[19], 1.0, 1.0, true); } break; case VirtualKeys.RaisePantograph: if (SoundManager.IsPlaying(Keysloop[18])) { SoundManager.Stop(Keysloop[18]); } else { SoundManager.Play(Keysloop[18], 1.0, 1.0, true); } break; case VirtualKeys.MainBreaker: if (SoundManager.IsPlaying(Keysloop[17])) { SoundManager.Stop(Keysloop[17]); } else { SoundManager.Play(Keysloop[17], 1.0, 1.0, true); } break; case VirtualKeys.WiperSpeedDown: if (SoundManager.IsPlaying(Keysloop[16])) { SoundManager.Stop(Keysloop[20]); } else { SoundManager.Play(Keysloop[16], 1.0, 1.0, true); } break; case VirtualKeys.WiperSpeedUp: if (SoundManager.IsPlaying(Keysloop[15])) { SoundManager.Stop(Keysloop[20]); } else { SoundManager.Play(Keysloop[15], 1.0, 1.0, true); } break; default: break; } }
/// <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); } } } }
internal override void SetBeacon(BeaconData beacon) { int num; if (this.State != AtsP.States.Disabled & this.State != AtsP.States.Suppressed & this.State != AtsP.States.Initializing) { switch (beacon.Type) { case 3: case 4: case 5: { this.Position = this.Train.State.Location; if (!(this.State != AtsP.States.Service & this.State != AtsP.States.Emergency)) { break; } if (this.State == AtsP.States.Standby & beacon.Optional != -1) { this.SwitchToP(AtsP.States.Normal); } if (this.State == AtsP.States.Standby) { break; } if (!(beacon.Type == 3 & beacon.Optional >= 10 & beacon.Optional <= 19)) { num = (!(beacon.Type == 3 & beacon.Optional >= 1 & beacon.Optional <= 9) ? 0 : beacon.Optional); double position = this.Position + beacon.Signal.Distance; bool flag = false; if (num != 0) { flag = true; } else if (this.SignalPatterns[num].Position == double.MaxValue) { flag = true; } else if (position > this.SignalPatterns[num].Position - 30) { flag = true; } if (!flag) { break; } if (!(beacon.Signal.Aspect == 0 | beacon.Signal.Aspect >= 10)) { this.SignalPatterns[num].SetGreenSignal(position); break; } else { this.SignalPatterns[num].SetRedSignal(position); if (!(beacon.Type != 3 & beacon.Signal.Distance < 50 & !this.BrakeRelease)) { break; } if (beacon.Type != 4) { this.SwitchToP(AtsP.States.Service); break; } else { this.SwitchToP(AtsP.States.Emergency); break; } } } else { this.SignalPatterns[beacon.Optional - 10].Clear(); break; } } case 6: { int optional = beacon.Optional / 1000; if (optional <= 0) { break; } if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } this.Position = this.Train.State.Location; int optional1 = beacon.Optional % 1000; this.DivergencePattern.SetLimit((double)optional1 / 3.6, this.Position + (double)optional); break; } case 7: { this.Position = this.Train.State.Location; if (beacon.Optional <= 0) { this.SwitchToP(AtsP.States.Emergency); break; } else { if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } this.RoutePermanentPattern.SetLimit((double)beacon.Optional / 3.6, double.MinValue); break; } } case 8: { int num1 = beacon.Optional / 1000; if (num1 <= 0) { break; } if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } this.Position = this.Train.State.Location; int optional2 = beacon.Optional % 1000; this.DownslopePattern.SetLimit((double)optional2 / 3.6, this.Position + (double)num1); break; } case 9: { int num2 = beacon.Optional / 1000; if (num2 <= 0) { break; } if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } this.Position = this.Train.State.Location; int optional3 = beacon.Optional % 1000; this.CurvePattern.SetLimit((double)optional3 / 3.6, this.Position + (double)num2); break; } case 10: { int num3 = beacon.Optional / 1000; int optional4 = beacon.Optional % 1000; if (num3 == 0) { if (!(num3 == 0 & optional4 != 0)) { break; } this.Position = this.Train.State.Location; this.SwitchToAtsSxPosition = this.Position + (double)optional4; break; } else { if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } this.Position = this.Train.State.Location; this.TemporaryPattern.SetLimit((double)optional4 / 3.6, this.Position + (double)num3); break; } } case 16: { if (beacon.Optional != 0) { break; } this.Position = this.Train.State.Location; this.DivergencePattern.Clear(); break; } case 18: { if (beacon.Optional != 0) { break; } this.Position = this.Train.State.Location; this.DownslopePattern.Clear(); break; } case 19: { if (beacon.Optional != 0) { break; } this.Position = this.Train.State.Location; this.CurvePattern.Clear(); break; } case 20: { if (beacon.Optional != 0) { break; } this.Position = this.Train.State.Location; this.TemporaryPattern.Clear(); break; } case 25: { if (beacon.Optional == 0) { this.Position = this.Train.State.Location; 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)) { break; } this.SwitchToAtsSxPosition = this.Position; break; } else if (beacon.Optional != 1) { if (beacon.Optional != 2) { break; } this.Position = this.Train.State.Location; if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } if (this.AtsSxPMode) { break; } this.AtsSxPMode = true; if (!(this.Train.AtsSx != null & !this.Blocked)) { break; } if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } break; } else { this.Position = this.Train.State.Location; if (this.State == AtsP.States.Standby) { this.SwitchToP(AtsP.States.Normal); } if (!this.AtsSxPMode) { break; } this.AtsSxPMode = false; if (!(this.Train.AtsSx != null & !this.Blocked)) { break; } if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } break; } } } } switch (beacon.Type) { case -16777213: { double num4 = (double)(beacon.Optional & 4095) / 3.6; double optional5 = (double)(beacon.Optional >> 12); AtsP.CompatibilityLimit compatibilityLimit = new AtsP.CompatibilityLimit(num4, optional5); if (this.CompatibilityLimits.Contains(compatibilityLimit)) { break; } this.CompatibilityLimits.Add(compatibilityLimit); return; } case -16777212: { if (beacon.Optional == 0) { this.CompatibilityPermanentPattern.Clear(); return; } double num5 = (double)beacon.Optional / 3.6; this.CompatibilityPermanentPattern.SetLimit(num5, double.MinValue); break; } default: { return; } } }
internal override void KeyDown(VirtualKeys key) { VirtualKeys virtualKey = key; switch (virtualKey) { case VirtualKeys.B1: { if (!((this.State == AtsP.States.Brake | this.State == AtsP.States.Service | this.State == AtsP.States.Emergency) & this.Train.Handles.Reverser == 0 & this.Train.Handles.PowerNotch == 0 & this.Train.Handles.BrakeNotch >= this.Train.Specs.BrakeNotches)) { break; } AtsP.Pattern[] patterns = this.Patterns; for (int i = 0; i < (int)patterns.Length; i++) { AtsP.Pattern pattern = patterns[i]; if (Math.Abs(this.Train.State.Speed.MetersPerSecond) >= pattern.WarningPattern) { pattern.Clear(); } } this.State = AtsP.States.Normal; Train.TractionManager.ResetBrakeApplication(); if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } return; } case VirtualKeys.B2: { if (!((this.State == AtsP.States.Normal | this.State == AtsP.States.Pattern) & !this.BrakeRelease & this.DurationOfBrakeRelease > 0)) { break; } this.BrakeRelease = true; this.BrakeReleaseCountdown = this.DurationOfBrakeRelease; if (!SoundManager.IsPlaying(CommonSounds.ATSPBell)) { SoundManager.Play(CommonSounds.ATSPBell, 1.0, 1.0, false); } return; } default: { if (virtualKey != VirtualKeys.E) { return; } if (this.State == AtsP.States.Disabled) { this.State = AtsP.States.Suppressed; return; } this.State = AtsP.States.Disabled; break; } } }
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()); } }
/// <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.suppressionactive) { /* Cancel any suppression which is in effect, if the train is not within range of the last suppression magnet location */ if (Train.CurrentSpeed > 0) { if (Train.TrainLocation > this.suppressionlocation + 2) { this.suppressionlocation = 0; this.suppressionactive = false; } } else { if (Train.TrainLocation < this.suppressionlocation - 2) { this.suppressionlocation = 0; this.suppressionactive = false; } } } else if (this.MySafetyState == SafetyStates.Primed) { /* An AWS magnet south pole has primed the AWS */ this.SunflowerState = SunflowerStates.Clear; this.detectiontimer = this.detectiontimer + (int)data.ElapsedTime.Milliseconds; if (this.detectiontimer > 1000) { /* No north pole has been detected within the timeout period, so reset the detection timer and issue an AWS warning */ this.detectiontimer = 0; this.MySafetyState = SafetyStates.CancelTimerActive; } } else if (this.MySafetyState == SafetyStates.Clear) { /* The AWS indicates a clear signal */ this.Reset(); this.SunflowerState = SunflowerStates.Clear; if (this.ClearSound != -1) { SoundManager.Play(ClearSound, 1.0, 1.0, false); } if (this.WarningSound != -1) { SoundManager.Stop(WarningSound); } } else if (this.MySafetyState == SafetyStates.CancelTimerActive) { /* An AWS warning has been issued */ if (this.WarningSound != -1) { SoundManager.Play(WarningSound, 1.0, 1.0, true); } this.SunflowerState = SunflowerStates.Clear; this.canceltimer -= (int)data.ElapsedTime.Milliseconds; if (this.canceltimer < 0) { this.canceltimer = 0; this.MySafetyState = SafetyStates.CancelTimerExpired; } } else if (this.MySafetyState == SafetyStates.WarningAcknowledged) { /* An AWS warning was acknowledged in time */ if (this.WarningSound != -1) { SoundManager.Stop(WarningSound); } this.Reset(); } else if (this.MySafetyState == SafetyStates.CancelTimerExpired) { /* An AWS warning was not acknowledged in time */ if (this.WarningSound != -1) { SoundManager.Play(WarningSound, 1.0, 1.0, true); } if (Train.TPWS.Enabled) { Train.TPWS.IssueBrakeDemand(); } else { if (Train.TractionManager.PowerCutoffDemanded == false) { Train.TractionManager.DemandPowerCutoff("Power cutoff was demanded by the AWS due to a warning not being acknowledged in time"); } if (Train.TractionManager.CurrentInterventionBrakeNotch != this.Train.Specs.BrakeNotches + 1) { Train.TractionManager.DemandBrakeApplication(this.Train.Specs.BrakeNotches + 1, "Emergency brakes were demanded by the AWS due to a warning not being acknowledged in time"); } } } else if (this.MySafetyState == SafetyStates.SelfTest) { blinktimer += (int)data.ElapsedTime.Milliseconds; if (blinktimer > 1200) { if (Train.AWS.WarningSound != -1) { if (startuphorntriggered == false) { SoundManager.Play(WarningSound, 1.0, 1.0, true); startuphorntriggered = true; } } } else if (blinktimer > 1000) { this.SunflowerState = SunflowerStates.Clear; } else if (blinktimer > 400) { this.SunflowerState = SunflowerStates.Warn; } } else if (this.MySafetyState == SafetyStates.TPWSAWSBrakeDemandIssued) { /* The TPWS issued an AWS Brake Demand due to the AWS not being acknowledged in time */ if (TPWSWarningSound != -1) { SoundManager.Play(TPWSWarningSound, 1.0, 1.0, true); } } } else if (this.SafetyState == SafetyStates.Isolated) { if (WarningSound != -1) { if (SoundManager.IsPlaying(WarningSound)) { SoundManager.Stop(WarningSound); } } if (TPWSWarningSound != -1) { if (SoundManager.IsPlaying(TPWSWarningSound)) { SoundManager.Stop(TPWSWarningSound); } } this.canceltimer = (int)this.canceltimeout; this.SunflowerState = SunflowerStates.Warn; } /* Set the state of the AWS Sunflower instrument */ if (awsindicator != -1) { if (this.SunflowerState == SunflowerStates.Warn) { this.Train.Panel[awsindicator] = 1; } else { this.Train.Panel[awsindicator] = 0; } } } //Set the state of the cancel button panel index //As this is a physical button, it can be pressed at any time if (CancelButtonIndex != -1) { if (CancelButtonPressed) { this.Train.Panel[CancelButtonIndex] = 1; } else { this.Train.Panel[CancelButtonIndex] = 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) { //Required to reset the max notch before each frame this.Train.TractionManager.SetMaxPowerNotch(this.Train.Specs.PowerNotches, false); //Check we've got a maximum temperature and a heating part if (overheat != 0 && heatingpart != 0) { this.heatingtimer += data.ElapsedTime.Milliseconds; if (heatingpart == 0 || overheat == 0) { //No heating part or overheat temperature not set this.temperature = 0.0; this.heatingtimer = 0.0; } else if (heatingpart == 1) { //Heats based upon power notch if (this.heatingtimer > 1000) { this.heatingtimer = 0.0; if (Train.Handles.PowerNotch == 0) { currentheat = HeatingRates[0]; } else if (Train.Handles.PowerNotch < HeatingRates.Length) { currentheat = HeatingRates[Train.Handles.PowerNotch]; } else { currentheat = HeatingRates[HeatingRates.Length - 1]; } temperature += currentheat; } } else { //Heats based upon RPM- Not on an electric loco! this.temperature = 0.0; this.heatingtimer = 0.0; } //Keep temperature below max & above zero if (temperature > overheat) { temperature = overheat; if (overheatresult == 1 && Train.TractionManager.EngineOverheated == false) { DemandPowerCutoff("Power cutoff was demanded due to the electric engine overheating"); Train.TractionManager.EngineOverheated = true; } } else if (temperature < overheat && temperature > 0) { if (BreakerTripped == false && ((FrontPantograph.State == PantographStates.Disabled && RearPantograph.State == PantographStates.OnService) || (RearPantograph.State == PantographStates.Disabled && FrontPantograph.State == PantographStates.OnService))) { ResetPowerCutoff("Power cutoff was released due to the electric engine temperature returning to safe levels"); } Train.TractionManager.EngineOverheated = false; } else if (temperature < 0) { temperature = 0; } } { //If we're in a power gap, check whether we have a pickup available if (PowerGap) { int new_power; //First check to see whether the first pickup is in the neutral section if (Train.TrainLocation - PickupLocations[0] > firstmagnet && Train.TrainLocation - PickupLocations[0] < nextmagnet) { //Cycle through the other pickups int j = 0; foreach (int t in PickupLocations) { if (Train.TrainLocation - t < firstmagnet) { j++; } } switch (PowerGapBehaviour) { case PowerGapBehaviour.ProportionalReduction: //Reduce max throttle by percentage of how many pickups are in the gap double throttlemultiplier = (double)j / (double)PickupLocations.Length; new_power = (int)(this.Train.Specs.PowerNotches * throttlemultiplier); this.Train.TractionManager.SetMaxPowerNotch(new_power, false); //data.Handles.PowerNotch = new_power; break; case PowerGapBehaviour.InactiveAny: //Kill traction power if any pickup is on the gap if (j != 0 && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to a neutral gap in the overhead line"); } break; case PowerGapBehaviour.InactiveAll: if (j == PickupLocations.Length && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to a neutral gap in the overhead line"); } break; } } //Now, check to see if the last pickup is in the neutral section else if (Train.TrainLocation - PickupLocations[PickupLocations.Length - 1] > firstmagnet && Train.TrainLocation - PickupLocations[PickupLocations.Length - 1] < nextmagnet) { //Cycle through the other pickups int j = 0; foreach (int t in PickupLocations) { if (Train.TrainLocation - t < firstmagnet) { j++; } } switch (PowerGapBehaviour) { case PowerGapBehaviour.ProportionalReduction: //Reduce max throttle by percentage of how many pickups are in the gap double throttlemultiplier = (double)j / (double)PickupLocations.Length; new_power = (int)(this.Train.Specs.PowerNotches * throttlemultiplier); this.Train.TractionManager.SetMaxPowerNotch(new_power, false); //data.Handles.PowerNotch = new_power; break; case PowerGapBehaviour.InactiveAny: //Kill traction power if any pickup is on the gap if (j != 0 && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to a neutral gap in the overhead line"); } break; case PowerGapBehaviour.InactiveAll: //Kill traction power when all pickups are on the gap if (j == PickupLocations.Length && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to a neutral gap in the overhead line"); } break; } } //Neither the first or last pickups are in the power gap, reset the power //However also check that the breaker has not been tripped by a UKTrainSys beacon else if (nextmagnet != 0 && (Train.TrainLocation - PickupLocations[PickupLocations.Length - 1]) > nextmagnet && (Train.TrainLocation - PickupLocations[0]) > nextmagnet) { PowerGap = false; if (LegacyPowerCut == true) { //Reset legacy power cutoff state and retrip breaker Train.ElectricEngine.TripBreaker(); LegacyPowerCut = false; } if (BreakerTripped == false && ((FrontPantograph.State == PantographStates.Disabled && RearPantograph.State == PantographStates.OnService) || (RearPantograph.State == PantographStates.Disabled && FrontPantograph.State == PantographStates.OnService))) { ResetPowerCutoff("Power cutoff was released due to leaving the neutral gap"); } } //If the final pickup has passed the UKTrainSys standard power gap location else if (Train.TrainLocation - PickupLocations[PickupLocations.Length - 1] < lastmagnet) { PowerGap = false; } } //This section of code handles a UKTrainSys compatible ACB/VCB // //If the ACB/VCB has tripped, always demand power cutoff if (BreakerTripped == true && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to the ACB/VCB state"); } //If we're in a power gap, also always demand power cutoff else if (BreakerTripped == false && PowerGap == true && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to a neutral gap in the overhead line"); } //If the ACB/VCB has now been reset with a pantograph available & we're not in a powergap reset traction power if (BreakerTripped == false && PowerGap == false && (FrontPantograph.State == PantographStates.OnService || RearPantograph.State == PantographStates.OnService)) { ResetPowerCutoff("Power cutoff was released due to the availability of overhead power"); } } { //This section of code handles raising the pantographs and the alarm state // //If both pantographs are lowered or disabled, then there are no line volts if ((FrontPantograph.State == PantographStates.Lowered || FrontPantograph.State == PantographStates.Disabled) && (RearPantograph.State == PantographStates.Lowered || RearPantograph.State == PantographStates.Disabled) && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to no available pantographs"); PowerGap = true; } //If the powergap behaviour cuts power when *any* pantograph is disabled / lowered // //Line volts is lit, but power is still cut off else if (FrontPantograph.State != PantographStates.Disabled && RearPantograph.State != PantographStates.Disabled && (FrontPantograph.State != PantographStates.OnService || RearPantograph.State != PantographStates.OnService) && PowerGapBehaviour == PowerGapBehaviour.InactiveAny && Train.TractionManager.PowerCutoffDemanded == false) { DemandPowerCutoff("Power cutoff was demanded due to no available pantographs"); } //Pantographs //One pantograph has been raised, and the line volts indicator has lit, but the timer is active //Power cutoff is still in force FrontPantograph.Update(data.ElapsedTime.Milliseconds); RearPantograph.Update(data.ElapsedTime.Milliseconds); if ((FrontPantograph.State == PantographStates.RaisedTimer && RearPantograph.State != PantographStates.OnService) || (RearPantograph.State == PantographStates.RaisedTimer && FrontPantograph.State != PantographStates.OnService)) { PowerGap = false; DemandPowerCutoff(null); } if (Train.CurrentSpeed > AutomaticPantographLowerSpeed) { //Automatic pantograph lowering switch (PantographLoweringMode) { case AutomaticPantographLoweringModes.LowerAll: //In lower all mode, we don't need to check anything if (FrontPantograph.State == PantographStates.OnService || FrontPantograph.State == PantographStates.RaisedTimer || FrontPantograph.State == PantographStates.VCBReady) { FrontPantograph.Lower(true); } if (RearPantograph.State == PantographStates.OnService || RearPantograph.State == PantographStates.RaisedTimer || RearPantograph.State == PantographStates.VCBReady) { RearPantograph.Lower(true); } Train.DebugLogger.LogMessage("Automatically lowered all pantographs due to reaching the setspeed."); break; case AutomaticPantographLoweringModes.LowerFront: if (RearPantograph.State == PantographStates.OnService) { if (FrontPantograph.State == PantographStates.OnService || FrontPantograph.State == PantographStates.RaisedTimer || FrontPantograph.State == PantographStates.VCBReady) { FrontPantograph.Lower(true); Train.DebugLogger.LogMessage("Automatically lowered the front pantograph due to reaching the setspeed."); } } break; case AutomaticPantographLoweringModes.LowerRear: if (FrontPantograph.State == PantographStates.OnService) { if (RearPantograph.State == PantographStates.OnService || RearPantograph.State == PantographStates.RaisedTimer || RearPantograph.State == PantographStates.VCBReady) { RearPantograph.Lower(true); Train.DebugLogger.LogMessage("Automatically lowered the rear pantograph due to reaching the setspeed."); } } break; case AutomaticPantographLoweringModes.LowerFrontRegardless: if (FrontPantograph.State == PantographStates.OnService || FrontPantograph.State == PantographStates.RaisedTimer || FrontPantograph.State == PantographStates.VCBReady) { FrontPantograph.Lower(true); Train.DebugLogger.LogMessage("Automatically lowered the front pantograph due to reaching the setspeed."); } break; case AutomaticPantographLoweringModes.LowerRearRegardless: if (RearPantograph.State == PantographStates.OnService || RearPantograph.State == PantographStates.RaisedTimer || RearPantograph.State == PantographStates.VCBReady) { RearPantograph.Lower(true); Train.DebugLogger.LogMessage("Automatically lowered the rear pantograph due to reaching the setspeed."); } break; } } } //This section of code runs the power notch loop sound if (powerloopsound != -1 && data.Handles.PowerNotch != 0) { if (BreakerTripped == false) { //Start the timer powerlooptimer += data.ElapsedTime.Milliseconds; if (powerlooptimer > powerlooptime && powerloop == false) { //Start playback and reset our conditions powerloop = true; SoundManager.Play(powerloopsound, 1.0, 1.0, true); } else if (powerloop == false) { SoundManager.Stop(powerloopsound); } } else { SoundManager.Stop(powerloopsound); } } else if (powerloopsound != -1 && this.Train.Handles.PowerNotch == 0) { SoundManager.Stop(powerloopsound); } //This section of code runs the breaker loop sound if (breakerloopsound != -1 && BreakerTripped == false) { if (!PowerGap && SoundManager.IsPlaying(breakerloopsound) == false) { breakerlooptimer += data.ElapsedTime.Milliseconds; if (breakerlooptimer > breakerlooptime) { SoundManager.Play(breakerloopsound, 1.0, 1.0, true); breakerlooptimer = 0.0; } } } else if (breakerloopsound != -1 && BreakerTripped == true) { SoundManager.Stop(breakerloopsound); breakerlooptimer = 0.0; } //Panel Indicies { //Ammeter if (Ammeter.PanelIndex != -1) { if (PowerGap == true || BreakerTripped == true || Train.TractionManager.PowerCutoffDemanded == true) { this.Train.Panel[Ammeter.PanelIndex] = 0; } else { this.Train.Panel[Ammeter.PanelIndex] = Ammeter.GetCurrentValue(); } } //Line Volts indicator if (powerindicator != -1) { if (!PowerGap) { this.Train.Panel[powerindicator] = 1; } else { this.Train.Panel[powerindicator] = 0; } } //ACB/VCB Breaker Indicator if (breakerindicator != -1) { if (!BreakerTripped) { this.Train.Panel[breakerindicator] = 1; } else { this.Train.Panel[breakerindicator] = 0; } } if (thermometer != -1) { this.Train.Panel[(thermometer)] = (int)temperature; } if (overheatindicator != -1) { if (temperature > overheatwarn) { this.Train.Panel[(overheatindicator)] = 1; } else { this.Train.Panel[(overheatindicator)] = 0; } } //Pantograph Indicators if (FrontPantograph.PanelIndex != -1) { if (FrontPantograph.Raised() == true) { this.Train.Panel[FrontPantograph.PanelIndex] = 1; } else { this.Train.Panel[FrontPantograph.PanelIndex] = 0; } } if (RearPantograph.PanelIndex != -1) { if (RearPantograph.Raised() == true) { this.Train.Panel[RearPantograph.PanelIndex] = 1; } else { this.Train.Panel[RearPantograph.PanelIndex] = 0; } } } //Sounds { if (overheatalarm != -1) { if (temperature > overheatalarm) { SoundManager.Play(overheatalarm, 1.0, 1.0, true); } else { SoundManager.Stop(overheatalarm); } } } //Pass information to the advanced driving window if (AdvancedDriving.CheckInst != null) { TractionManager.debuginformation[14] = Convert.ToString(FrontPantograph.State); TractionManager.debuginformation[15] = Convert.ToString(RearPantograph.State); TractionManager.debuginformation[16] = Convert.ToString(!BreakerTripped); TractionManager.debuginformation[17] = Convert.ToString(!PowerGap); } }