From b906404985b34abe7c20dfd0f5141936b9e6c409 Mon Sep 17 00:00:00 2001 From: siimav Date: Sun, 5 Nov 2023 01:24:06 +0200 Subject: [PATCH 1/3] Fix TF not fully working when a launch was initiated in a way other than staging --- TestFlightCore/TestFlightCore/TestFlightCore.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/TestFlightCore/TestFlightCore/TestFlightCore.cs b/TestFlightCore/TestFlightCore/TestFlightCore.cs index 7445ae4..3ed4468 100644 --- a/TestFlightCore/TestFlightCore/TestFlightCore.cs +++ b/TestFlightCore/TestFlightCore/TestFlightCore.cs @@ -732,9 +732,20 @@ public List GetActiveFailures() return failures; } - public void OnStageActivate(int stage) + private void OnStageActivate(int stage) + { + OnFlightStart(); + } + + private void OnEngineActiveChange(ModuleEngines data) + { + OnFlightStart(); + } + + private void OnFlightStart() { GameEvents.onStageActivate.Remove(OnStageActivate); + GameEvents.onEngineActiveChange.Remove(OnEngineActiveChange); firstStaged = true; missionStartTime = Planetarium.GetUniversalTime(); } @@ -815,7 +826,10 @@ public override void Start() _OnCrewChange(); firstStaged = vessel.situation != Vessel.Situations.PRELAUNCH; if (vessel.situation == Vessel.Situations.PRELAUNCH) + { GameEvents.onStageActivate.Add(OnStageActivate); + GameEvents.onEngineActiveChange.Add(OnEngineActiveChange); + } else missionStartTime = Planetarium.GetUniversalTime(); } @@ -826,6 +840,7 @@ public override void OnDestroy() base.OnDestroy(); GameEvents.onCrewTransferred.Remove(OnCrewChange); GameEvents.onStageActivate.Remove(OnStageActivate); + GameEvents.onEngineActiveChange.Remove(OnEngineActiveChange); } public override void OnAwake() From 9e7bdd8ad057d3f5aa673fe08f16595e0aeede25 Mon Sep 17 00:00:00 2001 From: siimav Date: Sun, 5 Nov 2023 16:47:05 +0200 Subject: [PATCH 2/3] Add one-time reminder about ignition dyn pressure penalties --- TestFlightFailure_IgnitionFail.cs | 31 ++++++++++++++++++++++++++++--- TestFlightSettings.cs | 3 +++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/TestFlightFailure_IgnitionFail.cs b/TestFlightFailure_IgnitionFail.cs index 44fa22a..aec59d3 100644 --- a/TestFlightFailure_IgnitionFail.cs +++ b/TestFlightFailure_IgnitionFail.cs @@ -31,6 +31,7 @@ public class TestFlightFailure_IgnitionFail : TestFlightFailure_Engine private readonly Dictionary engineRunData = new Dictionary(8); + private static bool dynPressureReminderShown; private bool preLaunchFailures; private bool dynPressurePenalties; private bool verboseDebugging; @@ -126,8 +127,16 @@ public override void OnStart(StartState state) { base.OnStart(state); verboseDebugging = core.DebugEnabled; - preLaunchFailures = HighLogic.CurrentGame.Parameters.CustomParams().preLaunchFailures; - dynPressurePenalties = HighLogic.CurrentGame.Parameters.CustomParams().dynPressurePenalties; + TestFlightGameSettings tfSettings = HighLogic.CurrentGame.Parameters.CustomParams(); + preLaunchFailures = tfSettings.preLaunchFailures; + dynPressurePenalties = tfSettings.dynPressurePenalties; + + // Nothing gets saved in simulations. Use static fields to pass the information over to the editor scene where it gets correctly persisted. + if (dynPressureReminderShown) + { + tfSettings.dynPressurePenaltyReminderShown = true; + } + dynPressureReminderShown |= tfSettings.dynPressurePenaltyReminderShown; } public override void OnLoad(ConfigNode node) @@ -297,7 +306,23 @@ public override void DoFailure() if (multiplier < 0.99) { - FlightLogger.eventLog.Add($"[{met}] {core.Title} failed: Ignition Failure. {(float)(part.dynamicPressurekPa * 1000d)}Pa dynamic pressure caused a {(1f-multiplier) * 100f:0.#}% reduction in normal ignition reliability."); + string sPenaltyPercent = $"{(1f - multiplier) * 100f:0.#}%"; + FlightLogger.eventLog.Add($"[{met}] {core.Title} failed: Ignition Failure. {(float)(part.dynamicPressurekPa * 1000d)}Pa dynamic pressure caused a {sPenaltyPercent} reduction in normal ignition reliability."); + + if (!dynPressureReminderShown && multiplier < 0.95) + { + string msg = $"High dynamic pressure caused a {sPenaltyPercent} reduction in normal ignition reliability. Consider lighting the engine on the ground or higher up in the atmosphere.\nThese penalties are listed in both the flight log (F3) and in the Part Action Window."; + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), + new Vector2(0.5f, 0.5f), + "IgnitionDynPressurePenaltyTip", + "Ignition Failure", + msg, + "OK", + false, + HighLogic.UISkin); + TestFlightGameSettings tfSettings = HighLogic.CurrentGame.Parameters.CustomParams(); + tfSettings.dynPressurePenaltyReminderShown = dynPressureReminderShown = true; + } } else { diff --git a/TestFlightSettings.cs b/TestFlightSettings.cs index 20a372c..d8f3c54 100644 --- a/TestFlightSettings.cs +++ b/TestFlightSettings.cs @@ -26,6 +26,9 @@ public class TestFlightGameSettings : GameParameters.CustomParameterNode [GameParameters.CustomParameterUI("Ignition Chance Penalty For High Dynamic Pressure", toolTip = "Whether engine ignition chance will suffer a penalty based on dynamic pressure.")] public bool dynPressurePenalties = true; + // The following values are persisted to the savegame but are not shown in the difficulty settings UI + public bool dynPressurePenaltyReminderShown = false; + public override void SetDifficultyPreset(GameParameters.Preset preset) { switch (preset) From b71745fbfa4f4868907d4dbff6c3d7e75b6e28e8 Mon Sep 17 00:00:00 2001 From: siimav Date: Sun, 5 Nov 2023 23:03:54 +0200 Subject: [PATCH 3/3] Add one-time reminder about ignition restart window penalties --- TestFlightFailure_IgnitionFail.cs | 153 ++++++++++++++++++++---------- TestFlightSettings.cs | 1 + 2 files changed, 102 insertions(+), 52 deletions(-) diff --git a/TestFlightFailure_IgnitionFail.cs b/TestFlightFailure_IgnitionFail.cs index aec59d3..d134ede 100644 --- a/TestFlightFailure_IgnitionFail.cs +++ b/TestFlightFailure_IgnitionFail.cs @@ -32,6 +32,7 @@ public class TestFlightFailure_IgnitionFail : TestFlightFailure_Engine private readonly Dictionary engineRunData = new Dictionary(8); private static bool dynPressureReminderShown; + private static bool restartWindowPenaltyReminderShown; private bool preLaunchFailures; private bool dynPressurePenalties; private bool verboseDebugging; @@ -137,6 +138,12 @@ public override void OnStart(StartState state) tfSettings.dynPressurePenaltyReminderShown = true; } dynPressureReminderShown |= tfSettings.dynPressurePenaltyReminderShown; + + if (restartWindowPenaltyReminderShown) + { + tfSettings.restartWindowPenaltyReminderShown = true; + } + restartWindowPenaltyReminderShown |= tfSettings.restartWindowPenaltyReminderShown; } public override void OnLoad(ConfigNode node) @@ -192,36 +199,25 @@ public override void OnUpdate() { EngineHandler engine = engines[i]; EngineModuleWrapper.EngineIgnitionState currentIgnitionState = engine.engine.IgnitionState; - var engineData = GetEngineRunDataForID(engine.engine.Module.PersistentId); + EngineRunData engineData = GetEngineRunDataForID(engine.engine.Module.PersistentId); double initialFlightData = core.GetInitialFlightData(); - float ignitionChance = 1f; - float pressureModifier = 1f; - float restartWindowModifier = 1f; - - // Check to see if the vessel has not launched and if the player disabled pad failures - if (this.vessel.situation == Vessel.Situations.PRELAUNCH && !preLaunchFailures) { - ignitionChance = 1.0f; - } else { - ignitionChance = baseIgnitionChance.Evaluate((float)initialFlightData); - if (ignitionChance <= 0) - ignitionChance = 1f; - } - if (dynPressurePenalties) + float ignitionChance; + // Check to see if the vessel has not launched and if the player disabled pad failures + if (this.vessel.situation == Vessel.Situations.PRELAUNCH && !preLaunchFailures) { - pressureModifier = Mathf.Clamp(pressureCurve.Evaluate((float)(part.dynamicPressurekPa * 1000d)), 0, 1); - if (pressureModifier <= 0f) - pressureModifier = 1f; + ignitionChance = 1.0f; } - - // if this engine has run before, and our config defines a restart window, we need to check against that and modify our ignition chance accordingly - if (hasRestartWindow && engineData.hasBeenRun) + else { - engineIdleTime = engineData.timeSinceLastShutdown; - restartWindowModifier = Mathf.Clamp(restartWindowPenalty.Evaluate(engineIdleTime), 0, 1); + ignitionChance = baseIgnitionChance.Evaluate((float)initialFlightData); + if (ignitionChance <= 0) + ignitionChance = 1f; } + float pressureModifier = GetDynPressureModifier(); + float restartWindowModifier = GetRestartWindowModifier(engineData); if (this.vessel.situation != Vessel.Situations.PRELAUNCH) ignitionChance = ignitionChance * pressureModifier * ignitionUseMultiplier.Evaluate(numIgnitions) * restartWindowModifier; @@ -231,15 +227,6 @@ public override void OnUpdate() restartPenalty = 1f - restartWindowModifier; engineHasRun = engineData.hasBeenRun; - if (currentIgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED) - { - engineData.timeSinceLastShutdown = 0; - } - else - { - engineData.timeSinceLastShutdown += (float)deltaTime; - } - // If we are transitioning from not ignited to ignited, we do our check // The ignitionFailureRate defines the failure rate per flight data if (currentIgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED) @@ -250,12 +237,12 @@ public override void OnUpdate() { Log($"IgnitionFail: Engine {engine.engine.Module.GetInstanceID()} transitioning to INGITED state"); Log("IgnitionFail: Checking curves..."); - } + } numIgnitions++; double failureRoll = core.RandomGenerator.NextDouble(); restartRollString = $"Roll: {failureRoll:P}, Chance: {ignitionChance:P}"; - + if (verboseDebugging) { Log($"IgnitionFail: Engine {engine.engine.Module.GetInstanceID()} ignition chance {ignitionChance:F4}, roll {failureRoll:F4}"); @@ -276,6 +263,15 @@ public override void OnUpdate() } } } + + if (currentIgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED) + { + engineData.timeSinceLastShutdown = 0; + } + else + { + engineData.timeSinceLastShutdown += (float)deltaTime; + } engine.ignitionState = currentIgnitionState; } Profiler.EndSample(); @@ -287,7 +283,6 @@ public override void DoFailure() if (!TestFlightEnabled) return; Failed = true; - float multiplier = 1f; ITestFlightCore core = TestFlightUtil.GetCore(this.part, Configuration); if (core != null) { @@ -297,12 +292,7 @@ public override void DoFailure() } string met = KSPUtil.PrintTimeCompact((int)Math.Floor(this.vessel.missionTime), false); - if (dynPressurePenalties) - { - multiplier = pressureCurve.Evaluate((float)(part.dynamicPressurekPa * 1000d)); - if (multiplier <= 0f) - multiplier = 1f; - } + float multiplier = GetDynPressureModifier(); if (multiplier < 0.99) { @@ -311,17 +301,7 @@ public override void DoFailure() if (!dynPressureReminderShown && multiplier < 0.95) { - string msg = $"High dynamic pressure caused a {sPenaltyPercent} reduction in normal ignition reliability. Consider lighting the engine on the ground or higher up in the atmosphere.\nThese penalties are listed in both the flight log (F3) and in the Part Action Window."; - PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), - new Vector2(0.5f, 0.5f), - "IgnitionDynPressurePenaltyTip", - "Ignition Failure", - msg, - "OK", - false, - HighLogic.UISkin); - TestFlightGameSettings tfSettings = HighLogic.CurrentGame.Parameters.CustomParams(); - tfSettings.dynPressurePenaltyReminderShown = dynPressureReminderShown = true; + ShowDynPressurePenaltyInfo(sPenaltyPercent); } } else @@ -329,8 +309,21 @@ public override void DoFailure() FlightLogger.eventLog.Add($"[{met}] {core.Title} failed: Ignition Failure."); } + EngineHandler engine = engines.Find(e => e.failEngine); + if (!restartWindowPenaltyReminderShown && engine != null) + { + EngineRunData engineData = GetEngineRunDataForID(engine.engine.Module.PersistentId); + float restartWindowModifier = GetRestartWindowModifier(engineData); + if (restartWindowModifier < 0.95) + { + string sPenaltyPercent = $"{(1f - restartWindowModifier) * 100f:0.#}%"; + ShowRestartWindowPenaltyInfo(sPenaltyPercent); + } + } + core.LogCareerFailure(vessel, failureTitle); } + Log($"IgnitionFail: Failing {engines.Count} engine(s)"); for (int i = 0; i < engines.Count; i++) { @@ -349,8 +342,8 @@ public override void DoFailure() engines[i].failEngine = false; } } - } + public override float DoRepair() { base.DoRepair(); @@ -370,6 +363,7 @@ public override float DoRepair() } return 0; } + public void RestoreIgnitor() { // part.Modules["ModuleEngineIgnitor"].GetType().GetField("ignitionsRemained").GetValue(part.Modules["ModuleEngineIgnitor"])); @@ -566,6 +560,61 @@ private void GetIgnitionChance(ref float currentIgnitionChance, ref float maxIgn } } } + + private float GetDynPressureModifier() + { + float pressureModifier = 1f; + if (dynPressurePenalties) + { + pressureModifier = Mathf.Clamp(pressureCurve.Evaluate((float)(part.dynamicPressurekPa * 1000d)), 0, 1); + if (pressureModifier <= 0f) + pressureModifier = 1f; + } + + return pressureModifier; + } + + private float GetRestartWindowModifier(EngineRunData engineData) + { + // if this engine has run before, and our config defines a restart window, we need to check against that and modify our ignition chance accordingly + if (hasRestartWindow && engineData.hasBeenRun) + { + engineIdleTime = engineData.timeSinceLastShutdown; + return Mathf.Clamp(restartWindowPenalty.Evaluate(engineIdleTime), 0, 1); + } + + return 1f; + } + + private static void ShowDynPressurePenaltyInfo(string sPenaltyPercent) + { + string msg = $"High dynamic pressure caused a {sPenaltyPercent} reduction in normal ignition reliability. Consider lighting the engine on the ground or higher up in the atmosphere.\nThese penalties are listed in both the flight log (F3) and in the Part Action Window."; + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), + new Vector2(0.5f, 0.5f), + "IgnitionDynPressurePenaltyTip", + "Ignition Failure", + msg, + "OK", + false, + HighLogic.UISkin); + TestFlightGameSettings tfSettings = HighLogic.CurrentGame.Parameters.CustomParams(); + tfSettings.dynPressurePenaltyReminderShown = dynPressureReminderShown = true; + } + + private void ShowRestartWindowPenaltyInfo(string sPenaltyPercent) + { + string msg = $"{core.Title} has restart window modifiers which caused a {sPenaltyPercent} reduction in normal ignition reliability. Please refer to the Part Action Window to see the current penalty in-flight or middle click on the engine while in editor."; + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), + new Vector2(0.5f, 0.5f), + "RestartWindowPressurePenaltyTip", + "Ignition Failure", + msg, + "OK", + false, + HighLogic.UISkin); + TestFlightGameSettings tfSettings = HighLogic.CurrentGame.Parameters.CustomParams(); + tfSettings.restartWindowPenaltyReminderShown = restartWindowPenaltyReminderShown = true; + } } } diff --git a/TestFlightSettings.cs b/TestFlightSettings.cs index d8f3c54..24eb6fe 100644 --- a/TestFlightSettings.cs +++ b/TestFlightSettings.cs @@ -28,6 +28,7 @@ public class TestFlightGameSettings : GameParameters.CustomParameterNode // The following values are persisted to the savegame but are not shown in the difficulty settings UI public bool dynPressurePenaltyReminderShown = false; + public bool restartWindowPenaltyReminderShown = false; public override void SetDifficultyPreset(GameParameters.Preset preset) {