Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
siimav committed Nov 5, 2023
2 parents 1e5181a + b71745f commit d75c593
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 45 deletions.
17 changes: 16 additions & 1 deletion TestFlightCore/TestFlightCore/TestFlightCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -732,9 +732,20 @@ public List<ITestFlightFailure> 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();
}
Expand Down Expand Up @@ -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();
}
Expand All @@ -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()
Expand Down
162 changes: 118 additions & 44 deletions TestFlightFailure_IgnitionFail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class TestFlightFailure_IgnitionFail : TestFlightFailure_Engine

private readonly Dictionary<uint, EngineRunData> engineRunData = new Dictionary<uint, EngineRunData>(8);

private static bool dynPressureReminderShown;
private static bool restartWindowPenaltyReminderShown;
private bool preLaunchFailures;
private bool dynPressurePenalties;
private bool verboseDebugging;
Expand Down Expand Up @@ -126,8 +128,22 @@ public override void OnStart(StartState state)
{
base.OnStart(state);
verboseDebugging = core.DebugEnabled;
preLaunchFailures = HighLogic.CurrentGame.Parameters.CustomParams<TestFlightGameSettings>().preLaunchFailures;
dynPressurePenalties = HighLogic.CurrentGame.Parameters.CustomParams<TestFlightGameSettings>().dynPressurePenalties;
TestFlightGameSettings tfSettings = HighLogic.CurrentGame.Parameters.CustomParams<TestFlightGameSettings>();
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;

if (restartWindowPenaltyReminderShown)
{
tfSettings.restartWindowPenaltyReminderShown = true;
}
restartWindowPenaltyReminderShown |= tfSettings.restartWindowPenaltyReminderShown;
}

public override void OnLoad(ConfigNode node)
Expand Down Expand Up @@ -183,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;
Expand All @@ -222,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)
Expand All @@ -241,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}");
Expand All @@ -267,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();
Expand All @@ -278,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)
{
Expand All @@ -288,24 +292,38 @@ 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)
{
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)
{
ShowDynPressurePenaltyInfo(sPenaltyPercent);
}
}
else
{
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++)
{
Expand All @@ -324,8 +342,8 @@ public override void DoFailure()
engines[i].failEngine = false;
}
}

}

public override float DoRepair()
{
base.DoRepair();
Expand All @@ -345,6 +363,7 @@ public override float DoRepair()
}
return 0;
}

public void RestoreIgnitor()
{
// part.Modules["ModuleEngineIgnitor"].GetType().GetField("ignitionsRemained").GetValue(part.Modules["ModuleEngineIgnitor"]));
Expand Down Expand Up @@ -541,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<TestFlightGameSettings>();
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<TestFlightGameSettings>();
tfSettings.restartWindowPenaltyReminderShown = restartWindowPenaltyReminderShown = true;
}
}
}

4 changes: 4 additions & 0 deletions TestFlightSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ 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 bool restartWindowPenaltyReminderShown = false;

public override void SetDifficultyPreset(GameParameters.Preset preset)
{
switch (preset)
Expand Down

0 comments on commit d75c593

Please sign in to comment.