@@ -61,18 +61,20 @@ public class AirSinglePipe : MSTSBrakeSystem
6161 protected string RetainerDebugState = string . Empty ;
6262 protected bool MRPAuxResCharging ;
6363 protected float CylVolumeM3 ;
64- protected bool EmergResQuickRelease = false ;
64+ protected bool EmergResQuickRelease ;
6565 protected float UniformChargingThresholdPSI = 3.0f ;
66- protected float UniformChargingRatio = 0 ;
67- protected bool QuickServiceActive = false ;
68- protected float QuickServiceLimitPSI = 0 ;
69- protected float QuickServiceApplicationRatePSIpS = 0 ;
70- protected float QuickServiceVentRatePSIpS = 0 ;
71- protected float AcceleratedApplicationRatio = 0 ;
66+ protected float UniformChargingRatio ;
67+ protected bool UniformChargingActive ;
68+ protected bool QuickServiceActive ;
69+ protected float QuickServiceLimitPSI ;
70+ protected float QuickServiceApplicationRatePSIpS ;
71+ protected float QuickServiceVentRatePSIpS ;
72+ protected float AcceleratedApplicationRatio ;
7273 protected float AcceleratedApplicationLimitPSIpS = 10.0f ;
7374 protected float InitialApplicationThresholdPSI = 1.0f ;
74- protected float BrakeCylinderSpringPressurePSI = 0 ;
75- protected float ServiceMaxCylPressurePSI = 0 ;
75+ protected float BrakeCylinderSpringPressurePSI ;
76+ protected float ServiceMaxCylPressurePSI ;
77+ protected float AcceleratedEmergencyReleaseThresholdPSI = 20.0f ;
7678
7779
7880 protected bool TrainBrakePressureChanging = false ;
@@ -301,6 +303,7 @@ public override void Save(BinaryWriter outf)
301303 outf . Write ( BleedOffValveOpen ) ;
302304 outf . Write ( ( int ) HoldingValve ) ;
303305 outf . Write ( CylVolumeM3 ) ;
306+ outf . Write ( UniformChargingActive ) ;
304307 outf . Write ( QuickServiceActive ) ;
305308 }
306309
@@ -324,6 +327,7 @@ public override void Restore(BinaryReader inf)
324327 BleedOffValveOpen = inf . ReadBoolean ( ) ;
325328 HoldingValve = ( ValveState ) inf . ReadInt32 ( ) ;
326329 CylVolumeM3 = inf . ReadSingle ( ) ;
330+ UniformChargingActive = inf . ReadBoolean ( ) ;
327331 QuickServiceActive = inf . ReadBoolean ( ) ;
328332 }
329333
@@ -399,20 +403,27 @@ public void UpdateTripleValveState(float elapsedClockSeconds)
399403 var prevState = TripleValveState ;
400404 var valveType = ( Car as MSTSWagon ) . BrakeValve ;
401405 bool disableGradient = ! ( Car . Train . LeadLocomotive is MSTSLocomotive ) && Car . Train . TrainType != Orts . Simulation . Physics . Train . TRAINTYPE . STATIC ;
406+
402407 if ( valveType == MSTSWagon . BrakeValveType . Distributor )
403408 {
404409 float targetPressurePSI = ( ControlResPressurePSI - BrakeLine1PressurePSI ) * AuxCylVolumeRatio ;
405410 if ( ! disableGradient && EmergencyValveActuationRatePSIpS > 0 && ( prevBrakePipePressurePSI - BrakeLine1PressurePSI ) > Math . Max ( elapsedClockSeconds , 0.0001f ) * EmergencyValveActuationRatePSIpS )
406411 {
407- if ( TripleValveState == ValveState . Release ) // If valve transitions from release to emergency, quick service activates
412+ if ( prevState == ValveState . Release ) // If valve transitions from release to emergency, quick service activates
413+ {
408414 QuickServiceActive = true ;
415+ UniformChargingActive = false ;
416+ }
409417 TripleValveState = ValveState . Emergency ;
410418 }
411419 else if ( TripleValveState != ValveState . Emergency &&
412420 targetPressurePSI > AutoCylPressurePSI + ( TripleValveState == ValveState . Release ? AuxCylVolumeRatio * InitialApplicationThresholdPSI : ( TripleValveState == ValveState . Apply ? 0.0f : 2.2f ) ) )
413421 {
414- if ( TripleValveState == ValveState . Release ) // If valve transitions from release to apply, quick service activates
422+ if ( prevState == ValveState . Release ) // If valve transitions from release to apply, quick service activates
423+ {
415424 QuickServiceActive = true ;
425+ UniformChargingActive = false ;
426+ }
416427 TripleValveState = ValveState . Apply ;
417428 }
418429 else if ( targetPressurePSI < AutoCylPressurePSI - ( TripleValveState == ValveState . Release ? 0.0f : 2.2f ) || targetPressurePSI < 2.2f )
@@ -428,15 +439,21 @@ public void UpdateTripleValveState(float elapsedClockSeconds)
428439 {
429440 if ( ! disableGradient && EmergencyValveActuationRatePSIpS > 0 && ( prevBrakePipePressurePSI - BrakeLine1PressurePSI ) > Math . Max ( elapsedClockSeconds , 0.0001f ) * EmergencyValveActuationRatePSIpS )
430441 {
431- if ( TripleValveState == ValveState . Release ) // If valve transitions from release to emergency, quick service activates
442+ if ( prevState == ValveState . Release ) // If valve transitions from release to emergency, quick service activates
443+ {
432444 QuickServiceActive = true ;
445+ UniformChargingActive = false ;
446+ }
433447 TripleValveState = ValveState . Emergency ;
434448 }
435449 else if ( TripleValveState != ValveState . Emergency &&
436450 BrakeLine1PressurePSI < AuxResPressurePSI - ( TripleValveState == ValveState . Release ? InitialApplicationThresholdPSI : ( TripleValveState == ValveState . Apply ? 0.0f : 1.0f ) ) )
437451 {
438- if ( TripleValveState == ValveState . Release ) // If valve transitions from release to apply, quick service activates
452+ if ( prevState == ValveState . Release ) // If valve transitions from release to apply, quick service activates
453+ {
439454 QuickServiceActive = true ;
455+ UniformChargingActive = false ;
456+ }
440457 TripleValveState = ValveState . Apply ;
441458 }
442459 else if ( BrakeLine1PressurePSI > AuxResPressurePSI + ( TripleValveState == ValveState . Release ? 0.0f : 2.0f ) )
@@ -515,18 +532,24 @@ public override void Update(float elapsedClockSeconds)
515532 {
516533 dpPipe = Math . Abs ( elapsedClockSeconds * QuickServiceVentRatePSIpS ) ;
517534 if ( CylPressurePSI > QuickServiceLimitPSI * 0.75f ) // Vent rate is reduced when quick service is nearly complete
535+ {
518536 dpPipe /= 3 ;
537+ }
519538 }
520539 dp = elapsedClockSeconds * Math . Max ( QuickServiceApplicationRatePSIpS , MaxApplicationRatePSIpS ) ;
521540 }
522541 else
523542 {
524543 if ( TripleValveState == ValveState . Apply && AcceleratedApplicationRatio > 0 ) // Accelerated application: Air is vented from the brake pipe to speed up service applications
544+ {
525545 dpPipe = Math . Min ( BrakePipeChange * AcceleratedApplicationRatio , elapsedClockSeconds * AcceleratedApplicationLimitPSIpS ) ; // Amount of air vented is proportional to pressure reduction from external sources
546+ }
526547 dp = elapsedClockSeconds * MaxApplicationRatePSIpS ;
527548 }
528549 if ( BrakeLine1PressurePSI - dpPipe < 0 )
550+ {
529551 dpPipe = BrakeLine1PressurePSI ;
552+ }
530553
531554 if ( TripleValveState != ValveState . Emergency && BrakeLine1PressurePSI < AuxResPressurePSI + 1 )
532555 dp *= MathHelper . Clamp ( AuxResPressurePSI - BrakeLine1PressurePSI , 0.1f , 1.0f ) ; // Reduce application rate if nearing equalization to prevent rapid toggling between apply and lap
@@ -556,12 +579,33 @@ public override void Update(float elapsedClockSeconds)
556579 {
557580 if ( ( Car as MSTSWagon ) . EmergencyReservoirPresent )
558581 {
559- dp = elapsedClockSeconds * MaxApplicationRatePSIpS ;
560- if ( EmergResPressurePSI - dp < AuxResPressurePSI + dp * EmergAuxVolumeRatio )
561- dp = ( EmergResPressurePSI - AuxResPressurePSI ) / ( 1 + EmergAuxVolumeRatio ) ;
562- EmergResPressurePSI -= dp ;
563- AuxResPressurePSI += dp * EmergAuxVolumeRatio ;
582+ if ( EmergencyDumpValveTimerS != 0 && EmergencyDumpStartTime == null && BrakeLine1PressurePSI > AcceleratedEmergencyReleaseThresholdPSI )
583+ {
584+ // Accelerated emergency release: Aux res and BP air are routed into the brake pipe once the emergency application is complete, speeds up emergency release
585+ // Triggers at 20 psi brake pipe pressure
586+
587+ dp = elapsedClockSeconds * MaxReleaseRatePSIpS ;
588+ if ( AutoCylPressurePSI - dp < AuxResPressurePSI + dp / AuxCylVolumeRatio )
589+ dp = Math . Max ( ( AutoCylPressurePSI - AuxResPressurePSI ) * ( AuxCylVolumeRatio / ( 1 + AuxCylVolumeRatio ) ) , 0 ) ;
590+ AutoCylPressurePSI -= dp ;
591+ AuxResPressurePSI += dp / AuxCylVolumeRatio ;
592+
593+ dp = elapsedClockSeconds * MaxAuxilaryChargingRatePSIpS ;
594+ if ( AuxResPressurePSI - dp < BrakeLine1PressurePSI + dp * AuxBrakeLineVolumeRatio )
595+ dp = Math . Max ( ( AuxResPressurePSI - BrakeLine1PressurePSI ) / ( 1 + AuxBrakeLineVolumeRatio ) , 0 ) ;
596+ AuxResPressurePSI -= dp ;
597+ BrakeLine1PressurePSI += dp * AuxBrakeLineVolumeRatio ;
598+ }
599+ else
600+ {
601+ dp = elapsedClockSeconds * MaxApplicationRatePSIpS ;
602+ if ( EmergResPressurePSI - dp < AuxResPressurePSI + dp * EmergAuxVolumeRatio )
603+ dp = ( EmergResPressurePSI - AuxResPressurePSI ) / ( 1 + EmergAuxVolumeRatio ) ;
604+ EmergResPressurePSI -= dp ;
605+ AuxResPressurePSI += dp * EmergAuxVolumeRatio ;
606+ }
564607 }
608+
565609 if ( EmergencyDumpValveTimerS == 0 )
566610 {
567611 if ( BrakeLine1PressurePSI < 1 ) EmergencyDumpStartTime = null ;
@@ -636,7 +680,6 @@ public override void Update(float elapsedClockSeconds)
636680 }
637681 else // Quick recharge: Emergency res air used to recharge aux res on older control valves
638682 {
639-
640683 float dp = elapsedClockSeconds * MaxAuxilaryChargingRatePSIpS ;
641684 if ( AuxResPressurePSI + dp > EmergResPressurePSI - dp / EmergAuxVolumeRatio )
642685 dp = ( EmergResPressurePSI - AuxResPressurePSI ) * EmergAuxVolumeRatio / ( 1 + EmergAuxVolumeRatio ) ;
@@ -674,8 +717,15 @@ public override void Update(float elapsedClockSeconds)
674717 {
675718 if ( AuxResPressurePSI < BrakeLine1PressurePSI && ( valveType == MSTSWagon . BrakeValveType . Distributor ? true : TripleValveState == ValveState . Release ) && ! BleedOffValveOpen )
676719 {
677- if ( UniformChargingRatio > 0 && AuxResPressurePSI < BrakeLine1PressurePSI - UniformChargingThresholdPSI )
678- dpAux /= UniformChargingRatio ; // Uniform charging: Aux res charging is slowed down when the brake pipe is substantially higher than the aux res
720+ if ( UniformChargingRatio > 0 ) // Uniform charging: Aux res charging is slowed down when the brake pipe is substantially higher than the aux res
721+ {
722+ if ( ! UniformChargingActive && AuxResPressurePSI < BrakeLine1PressurePSI - UniformChargingThresholdPSI )
723+ UniformChargingActive = true ;
724+ else if ( UniformChargingActive && AuxResPressurePSI > BrakeLine1PressurePSI - UniformChargingThresholdPSI / 2 )
725+ UniformChargingActive = false ;
726+ if ( UniformChargingActive )
727+ dpAux /= UniformChargingRatio ;
728+ }
679729 if ( AuxResPressurePSI + dpAux > BrakeLine1PressurePSI - dpAux * AuxBrakeLineVolumeRatio )
680730 dpAux = ( BrakeLine1PressurePSI - AuxResPressurePSI ) / ( 1 + AuxBrakeLineVolumeRatio ) ;
681731 AuxResPressurePSI += dpAux ;
@@ -949,7 +999,6 @@ public override void Update(float elapsedClockSeconds)
949999 lead . BrakeOverchargeSoundOn = false ;
9501000 }
9511001 }
952-
9531002 }
9541003 prevBrakePipePressurePSI = BrakeLine1PressurePSI ;
9551004 SoundTriggerCounter += elapsedClockSeconds ;
0 commit comments