diff --git a/CCL_GameScripts/Effects/ControllableLightSetup.cs b/CCL_GameScripts/Effects/ControllableLightSetup.cs index a698d0bd..b16b23a1 100644 --- a/CCL_GameScripts/Effects/ControllableLightSetup.cs +++ b/CCL_GameScripts/Effects/ControllableLightSetup.cs @@ -5,7 +5,7 @@ namespace CCL_GameScripts.Effects { - public class ControllableLightSetup : IndicatorSetupBase + public class ControllableLightSetup : ComponentInitSpec { public override string TargetTypeName => "DVCustomCarLoader.Effects.ControllableLight"; public override bool DestroyAfterCreation => true; @@ -20,5 +20,13 @@ public class ControllableLightSetup : IndicatorSetupBase [ProxyField] public float Lag = 0.05f; + + [Header("Binding")] + [ProxyField] + public SimEventType OutputBinding; + [ProxyField] + public float MinValue = 0; + [ProxyField] + public float MaxValue = 1; } } \ No newline at end of file diff --git a/DVCustomCarLoader/Effects/ControllableLight.cs b/DVCustomCarLoader/Effects/ControllableLight.cs index 146da99d..1e667bad 100644 --- a/DVCustomCarLoader/Effects/ControllableLight.cs +++ b/DVCustomCarLoader/Effects/ControllableLight.cs @@ -6,7 +6,7 @@ namespace DVCustomCarLoader.Effects { - public class ControllableLight : Indicator + public class ControllableLight : MonoBehaviour, ILocoEventAcceptor { public Light[] Lights; public float MinLevel = 0; @@ -17,44 +17,56 @@ public class ControllableLight : Indicator protected float SmoothingVelo = 0; protected float TargetLevel = 0; + public SimEventType OutputBinding; + public SimEventType[] EventTypes => new[] { OutputBinding }; + public float MinValue = 0; + public float MaxValue = 1; + + private float MapInputValue(float input) + { + return (input - MinValue) / (MaxValue - MinValue); + } + public void ApplyNormalizedLevel(float newLevel) { - float mapped = Mathf.Lerp(MinLevel, MaxLevel, newLevel); + float mapped = Mathf.LerpUnclamped(MinLevel, MaxLevel, newLevel); foreach (Light l in Lights) { l.intensity = mapped; - SmoothedLevel = mapped; } } - protected override void Start() + protected void Start() { - base.Start(); - ApplyNormalizedLevel(MinLevel); + TargetLevel = 0; + ApplyNormalizedLevel(0); } - protected override void OnValueSet() + protected void Update() { - if (!Application.isPlaying) + if (Lag > 0) { - return; + SmoothedLevel = Mathf.SmoothDamp(SmoothedLevel, TargetLevel, ref SmoothingVelo, Lag); + ApplyNormalizedLevel(SmoothedLevel); } + } - TargetLevel = GetNormalizedValue(true); - - if (Lag == 0) + public void HandleEvent(LocoEventInfo eventInfo) + { + if (eventInfo.NewValue is float value) { - ApplyNormalizedLevel(TargetLevel); + TargetLevel = MapInputValue(value); } - } + else if (eventInfo.NewValue is bool onOff) + { + TargetLevel = onOff ? 1 : 0; + } + else return; - protected void Update() - { - if (Lag > 0) + if (Lag == 0) { - float smoothedLevel = Mathf.SmoothDamp(SmoothedLevel, TargetLevel, ref SmoothingVelo, Lag); - ApplyNormalizedLevel(smoothedLevel); + ApplyNormalizedLevel(TargetLevel); } } } diff --git a/DVCustomCarLoader/Effects/SteamParticlesController.cs b/DVCustomCarLoader/Effects/SteamParticlesController.cs index 0a5afe46..1f61b4d0 100644 --- a/DVCustomCarLoader/Effects/SteamParticlesController.cs +++ b/DVCustomCarLoader/Effects/SteamParticlesController.cs @@ -118,7 +118,7 @@ protected IEnumerator UpdateSmokeParticles(float period) var main = chimneyParticles.main; float burnRatePercent = controller.FuelConsumptionRate / controller.MaxFuelConsumptionRate; - Main.LogVerbose($"Chimney burn rate: {burnRatePercent} ({controller.FuelConsumptionRate}/{controller.MaxFuelConsumptionRate})"); + //Main.LogVerbose($"Chimney burn rate: {burnRatePercent} ({controller.FuelConsumptionRate}/{controller.MaxFuelConsumptionRate})"); if ((burnRatePercent == 0) && chimneyParticles.isPlaying) { diff --git a/DVCustomCarLoader/LocoComponents/CustomFuseController.cs b/DVCustomCarLoader/LocoComponents/CustomFuseController.cs index 7ca66e4c..0165bf7a 100644 --- a/DVCustomCarLoader/LocoComponents/CustomFuseController.cs +++ b/DVCustomCarLoader/LocoComponents/CustomFuseController.cs @@ -21,6 +21,8 @@ public class CustomFuseController : MonoBehaviour, ILocoEventProvider, ICabContr protected const float LATE_INIT_DELAY = 0.5f; protected const float MAIN_BREAKER_DELAY = 0.2f; + protected bool StartupComplete = false; + protected bool AreAllSideFusesOn() { return SideFuses.TrueForAll(fuse => fuse.Value > SWITCH_THRESHOLD); @@ -38,16 +40,7 @@ public void SetMasterPower( bool on ) } MainFuse.Value = relayPos; - - EventManager.Dispatch(this, SimEventType.PowerOn, on); - if( on ) - { - TryStarter(); - } - else - { - KillEngine(); - } + SetLocoPowerState(on); } public void TryStarter() @@ -66,6 +59,12 @@ public void KillEngine() locoController.EngineRunning = false; } + protected void SetLocoPowerState(bool newState) + { + EventManager.Dispatch(this, SimEventType.PowerOn, newState); + locoController.MasterPower = newState; + } + public void Start() { var car = TrainCar.Resolve(gameObject); @@ -82,6 +81,7 @@ public void Start() return; } + StartupComplete = false; StartCoroutine(DelayedEnable()); } @@ -89,6 +89,7 @@ private IEnumerator DelayedEnable() { yield return WaitFor.SecondsRealtime(LATE_INIT_DELAY); SetMasterPower(locoController.EngineRunning); + StartupComplete = true; yield break; } @@ -97,7 +98,7 @@ private IEnumerator DelayedMainFuseOff() yield return WaitFor.SecondsRealtime(MAIN_BREAKER_DELAY); if( !AreAllSideFusesOn() ) { - EventManager.Dispatch(this, SimEventType.PowerOn, false); + SetLocoPowerState(false); MainFuse.Value = 0; } @@ -110,6 +111,7 @@ private IEnumerator DelayedMainFuseOff() protected void OnSideFuseChanged( float newVal ) { + if (!StartupComplete) return; if( newVal <= SWITCH_THRESHOLD ) { if( locoController.EngineRunning ) KillEngine(); @@ -122,6 +124,7 @@ protected void OnSideFuseChanged( float newVal ) protected void OnMainFuseChanged( float newVal ) { + if (!StartupComplete) return; bool nowOn = (newVal > SWITCH_THRESHOLD); if( nowOn ) @@ -134,18 +137,19 @@ protected void OnMainFuseChanged( float newVal ) } return; } - EventManager.Dispatch(this, SimEventType.PowerOn, nowOn); + SetLocoPowerState(nowOn); } else { // turned off - EventManager.Dispatch(this, SimEventType.PowerOn, nowOn); + SetLocoPowerState(nowOn); KillEngine(); } } protected void OnStarterChanged( float newVal ) { + if (!StartupComplete) return; if( (newVal > SWITCH_THRESHOLD) && !locoController.EngineRunning ) { TryStarter(); @@ -159,6 +163,7 @@ protected void OnStarterChanged( float newVal ) protected void OnEStopChanged( float newVal ) { + if (!StartupComplete) return; if( (newVal > SWITCH_THRESHOLD) && locoController.EngineRunning ) { KillEngine(); @@ -200,5 +205,10 @@ public void RegisterControl( CabInputRelay inputRelay ) } #endregion + + public void ForceDispatchAll() + { + if (locoController != null) EventManager.Dispatch(this, SimEventType.PowerOn, locoController.MasterPower); + } } } \ No newline at end of file diff --git a/DVCustomCarLoader/LocoComponents/CustomLocoController.cs b/DVCustomCarLoader/LocoComponents/CustomLocoController.cs index 9793509d..3ca70c4c 100644 --- a/DVCustomCarLoader/LocoComponents/CustomLocoController.cs +++ b/DVCustomCarLoader/LocoComponents/CustomLocoController.cs @@ -36,7 +36,10 @@ public void SetReverserFromCab( float position ) } public float GetReverserCabPosition() => (reverser + 1f) / 2f; + protected abstract float AccessoryPowerLevel { get; } + // Headlights + protected float _HeadlightControlLevel; protected float _Headlights; public float Headlights => _Headlights; @@ -48,20 +51,24 @@ public void SetReverserFromCab( float position ) public void SetHeadlight( float value ) { - if( value != Headlights ) + if( value != _HeadlightControlLevel ) { - //headlights.SetActive(HeadlightsOn); + _HeadlightControlLevel = value; + value = _HeadlightControlLevel * AccessoryPowerLevel; EventManager.UpdateValueDispatchOnChange(this, ref _Headlights, value, SimEventType.Headlights); } } // Cab Lights + protected float _CabLightControlLevel; protected float _CabLights; public float CabLights => _CabLights; public void SetCabLight( float value ) { - if (value != CabLights) + if (value != _CabLightControlLevel) { + _CabLightControlLevel = value; + value = _CabLightControlLevel * AccessoryPowerLevel; EventManager.UpdateValueDispatchOnChange(this, ref _CabLights, value, SimEventType.CabLights); } } @@ -84,15 +91,34 @@ public override void Update() EventManager.UpdateValueDispatchOnChange(this, ref _BrakeResPressure, GetBrakeResPressure(), SimEventType.BrakeReservoir); EventManager.UpdateValueDispatchOnChange(this, ref _IndependentPressure, GetIndependentPressure(), SimEventType.IndependentPipe); + float light = _HeadlightControlLevel * AccessoryPowerLevel; + EventManager.UpdateValueDispatchOnChange(this, ref _Headlights, light, SimEventType.Headlights); + + float cab = _CabLightControlLevel * AccessoryPowerLevel; + EventManager.UpdateValueDispatchOnChange(this, ref _CabLights, cab, SimEventType.CabLights); + float fwdLight = Mathf.Lerp(0, _Headlights, Mathf.InverseLerp(0, 1, reverser)); EventManager.UpdateValueDispatchOnChange(this, ref _ForwardLights, fwdLight, SimEventType.LightsForward); - float revLight = Mathf.Lerp(0, _RearLights, Mathf.InverseLerp(0, -1, reverser)); + float revLight = Mathf.Lerp(0, _Headlights, Mathf.InverseLerp(0, -1, reverser)); EventManager.UpdateValueDispatchOnChange(this, ref _RearLights, revLight, SimEventType.LightsReverse); base.Update(); } + public virtual void ForceDispatchAll() + { + EventManager.Dispatch(this, SimEventType.Speed, Speed); + EventManager.Dispatch(this, SimEventType.BrakePipe, _BrakePipePressure); + EventManager.Dispatch(this, SimEventType.BrakeReservoir, _BrakeResPressure); + EventManager.Dispatch(this, SimEventType.IndependentPipe, _IndependentPressure); + + EventManager.Dispatch(this, SimEventType.Headlights, _Headlights); + EventManager.Dispatch(this, SimEventType.CabLights, _CabLights); + EventManager.Dispatch(this, SimEventType.LightsForward, _ForwardLights); + EventManager.Dispatch(this, SimEventType.LightsReverse, _RearLights); + } + #region ICabControlAcceptor public virtual void RegisterControl( CabInputRelay inputRelay ) diff --git a/DVCustomCarLoader/LocoComponents/CustomLocoSimEvents.cs b/DVCustomCarLoader/LocoComponents/CustomLocoSimEvents.cs index 9d8af4f7..51fbc309 100644 --- a/DVCustomCarLoader/LocoComponents/CustomLocoSimEvents.cs +++ b/DVCustomCarLoader/LocoComponents/CustomLocoSimEvents.cs @@ -51,6 +51,13 @@ private IEnumerator CheckTankDamageStateRoutine() } protected abstract void CheckTankAndDamageLevels(); + + public virtual void ForceDispatchAll() + { + SandEvent.ForceDispatch(); + WheelslipEvent.ForceDispatch(); + CoupleEvent.ForceDispatch(); + } } public abstract class CustomLocoSimEvents : CustomLocoSimEvents diff --git a/DVCustomCarLoader/LocoComponents/DieselElectric/CustomDieselSimEvents.cs b/DVCustomCarLoader/LocoComponents/DieselElectric/CustomDieselSimEvents.cs index e8af5fdc..63c96a89 100644 --- a/DVCustomCarLoader/LocoComponents/DieselElectric/CustomDieselSimEvents.cs +++ b/DVCustomCarLoader/LocoComponents/DieselElectric/CustomDieselSimEvents.cs @@ -152,5 +152,16 @@ protected override void CheckTankAndDamageLevels() EngineDamageChanged.Invoke(newDamageLevel); } } + + public override void ForceDispatchAll() + { + base.ForceDispatchAll(); + + FuelEvent.ForceDispatch(); + OilEvent.ForceDispatch(); + EngineRunningEvent.ForceDispatch(); + EngineTempEvent.ForceDispatch(); + EngineDamageEvent.ForceDispatch(); + } } } \ No newline at end of file diff --git a/DVCustomCarLoader/LocoComponents/DieselElectric/CustomLocoControllerDiesel.cs b/DVCustomCarLoader/LocoComponents/DieselElectric/CustomLocoControllerDiesel.cs index 8deaccf0..5e523d0b 100644 --- a/DVCustomCarLoader/LocoComponents/DieselElectric/CustomLocoControllerDiesel.cs +++ b/DVCustomCarLoader/LocoComponents/DieselElectric/CustomLocoControllerDiesel.cs @@ -41,9 +41,12 @@ public bool EngineRunning } } } - public bool CanEngineStart => !EngineRunning && (FuelLevel > 0); + public bool CanEngineStart => (FuelLevel > 0); public bool AutoStart => autostart; + public bool MasterPower { get; set; } + protected override float AccessoryPowerLevel => + MasterPower ? (0.6f + sim.engineRPM.value * 0.4f) : 0; private float GetFuel() => sim.fuel.value; private float GetOil() => sim.oil.value; @@ -85,6 +88,20 @@ public void SetFanControl(float value) EventManager.UpdateValueDispatchOnChange(this, ref FanOn, value > 0.5f, SimEventType.Fan); } + public override void ForceDispatchAll() + { + base.ForceDispatchAll(); + + EventManager.Dispatch(this, SimEventType.Fuel, _FuelLevel); + EventManager.Dispatch(this, SimEventType.Oil, _OilLevel); + EventManager.Dispatch(this, SimEventType.Sand, _SandLevel); + EventManager.Dispatch(this, SimEventType.EngineTemp, _EngineTemp); + EventManager.Dispatch(this, SimEventType.EngineRPMGauge, _EngineRPMGauge); + EventManager.Dispatch(this, SimEventType.Amperage, _Amperage); + + EventManager.Dispatch(this, SimEventType.Fan, FanOn); + } + private void UpdateWatchables() { EventManager.UpdateValueDispatchOnChange(this, ref _FuelLevel, GetFuel(), SimEventType.Fuel); @@ -177,7 +194,13 @@ public override void SetReverser( float position ) base.SetReverser(position); } - public override float GetTractionForce() + public override void UpdateHorn(float value) + { + if (BrakeResPressure < 2) value = 0; + base.UpdateHorn(value); + } + + public override float GetTractionForce() { float num = (sim.engineRPM.value > 0f) ? tractionTorqueCurve.Evaluate(GetSpeedKmH() / sim.engineRPM.value) : 0f; float num2 = (Mathf.Sign(GetForwardSpeed() * reverser) > 0f) ? num : 1f; diff --git a/DVCustomCarLoader/LocoComponents/IFusedLocoController.cs b/DVCustomCarLoader/LocoComponents/IFusedLocoController.cs index e1a057de..ae339cdc 100644 --- a/DVCustomCarLoader/LocoComponents/IFusedLocoController.cs +++ b/DVCustomCarLoader/LocoComponents/IFusedLocoController.cs @@ -13,5 +13,7 @@ public interface IFusedLocoController bool CanEngineStart { get; } bool AutoStart { get; } + + bool MasterPower { get; set; } } } diff --git a/DVCustomCarLoader/LocoComponents/LocoComponentManager.cs b/DVCustomCarLoader/LocoComponents/LocoComponentManager.cs index 5060ba4c..3158bbd1 100644 --- a/DVCustomCarLoader/LocoComponents/LocoComponentManager.cs +++ b/DVCustomCarLoader/LocoComponents/LocoComponentManager.cs @@ -91,6 +91,7 @@ public static void AddDieselSimulation( GameObject prefab, SimParamsDiesel simPa muModule.rearCableAdapter = muHoseAdapter; } } + locoController.muModule = muModule; Main.LogVerbose("Added multiple unit module"); } diff --git a/DVCustomCarLoader/LocoComponents/LocoEventManager.cs b/DVCustomCarLoader/LocoComponents/LocoEventManager.cs index c30ebfb9..63e8f056 100644 --- a/DVCustomCarLoader/LocoComponents/LocoEventManager.cs +++ b/DVCustomCarLoader/LocoComponents/LocoEventManager.cs @@ -25,13 +25,16 @@ public LocoEventInfo(ILocoEventProvider provider, SimEventType type, object val) public interface ILocoEventProvider { LocoEventManager EventManager { get; set; } + void ForceDispatchAll(); } - public class LocoEventWrapper + public class LocoEventWrapper where T : struct { public readonly ILocoEventProvider Provider; public readonly SimEventType EventType; + public T? LastValue = null; + private LocoEventWrapper(ILocoEventProvider parent, SimEventType eventType) { Provider = parent; @@ -40,9 +43,18 @@ private LocoEventWrapper(ILocoEventProvider parent, SimEventType eventType) public void OnChange(T newVal) { + LastValue = newVal; Provider.EventManager?.Dispatch(Provider, EventType, newVal); } + public void ForceDispatch() + { + if (LastValue.HasValue) + { + Provider.EventManager?.Dispatch(Provider, EventType, LastValue.Value); + } + } + public static LocoEventWrapper Create(ref event_ e, ILocoEventProvider parent, SimEventType eventType) { var wrapper = new LocoEventWrapper(parent, eventType); @@ -64,6 +76,8 @@ public class EventCollection protected Dictionary> EventAcceptors = new Dictionary>(); + protected List Providers = new List(); + protected void Add(SimEventType eventType, ILocoEventAcceptor acceptor) { if (!EventAcceptors.TryGetValue(eventType, out var acceptList)) @@ -87,6 +101,7 @@ public IEnumerable GetAcceptors(SimEventType eventType) public void Clear() { EventAcceptors.Clear(); + Providers.Clear(); } public void Initialize(GameObject prefab, LocoEventManager dispatcher) @@ -104,16 +119,21 @@ public void Initialize(GameObject prefab, LocoEventManager dispatcher) } var providers = prefab.GetComponentsInChildrenByInterface(); - int pCount = 0; + Providers.AddRange(providers); foreach (var provider in providers) { - pCount++; provider.EventManager = dispatcher; } -#if DEBUG - Main.LogVerbose($"EventManager Start: {pCount} providers, {aCount} acceptors"); -#endif + Main.LogVerbose($"EventManager Start: {Providers.Count} providers, {aCount} acceptors"); + } + + public void ForceDispatchAll() + { + foreach (var provider in Providers) + { + provider.ForceDispatchAll(); + } } } @@ -147,11 +167,16 @@ public void UpdateValueDispatchOnChange(ILocoEventProvider provider, ref T public void Start() { ExteriorEvents.Initialize(gameObject, this); + + ExteriorEvents.ForceDispatchAll(); } public void OnInteriorLoaded(GameObject interior) { InteriorEvents.Initialize(interior, this); + + ExteriorEvents.ForceDispatchAll(); + InteriorEvents.ForceDispatchAll(); } public void OnInteriorUnloaded() diff --git a/DVCustomCarLoader/LocoComponents/Steam/CustomLocoControllerSteam.cs b/DVCustomCarLoader/LocoComponents/Steam/CustomLocoControllerSteam.cs index 26397dac..8d37f532 100644 --- a/DVCustomCarLoader/LocoComponents/Steam/CustomLocoControllerSteam.cs +++ b/DVCustomCarLoader/LocoComponents/Steam/CustomLocoControllerSteam.cs @@ -34,6 +34,8 @@ protected override void Start() var keyboardCtrl = gameObject.AddComponent(); keyboardCtrl.control = this; } + + maxPowerPressure = sim.boilerPressure.max / 3f; } private void OnRearCouple(object _, CoupleEventArgs e) @@ -247,6 +249,16 @@ public override void RegisterControl(CabInputRelay inputRelay) //================================================================================ #region Watchable Values + private float maxPowerPressure; + protected override float AccessoryPowerLevel + { + get + { + if (sim.boilerPressure.value > maxPowerPressure) return 1; + return Mathf.InverseLerp(0, maxPowerPressure, sim.boilerPressure.value); + } + } + protected float _SandLevel; protected float _Cutoff; protected float _BoilerPressure; @@ -264,6 +276,18 @@ private void UpdateWatchables() EventManager.UpdateValueDispatchOnChange(this, ref _FireFuelLevel, sim.fireboxFuel.value, SimEventType.FireboxLevel); } + public override void ForceDispatchAll() + { + base.ForceDispatchAll(); + + EventManager.Dispatch(this, SimEventType.Sand, _SandLevel); + EventManager.Dispatch(this, SimEventType.Cutoff, _Cutoff); + EventManager.Dispatch(this, SimEventType.BoilerPressure, _BoilerPressure); + EventManager.Dispatch(this, SimEventType.WaterLevel, _BoilerWater); + EventManager.Dispatch(this, SimEventType.FireTemp, _FireTemp); + EventManager.Dispatch(this, SimEventType.FireboxLevel, _FireFuelLevel); + } + public bool IsFireOn { get => sim.fireOn.value > 0;