public override void OnUpdate() { if (!TestFlightEnabled) { return; } EngineModuleWrapper.EngineIgnitionState currentIgnitionState = engine.IgnitionState; // If we are transitioning from not ignited to ignited, we do our check // The ignitionFailueRate defines the failure rate per flight data if (currentIgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED) { if (previousIgnitionState == EngineModuleWrapper.EngineIgnitionState.NOT_IGNITED || previousIgnitionState == EngineModuleWrapper.EngineIgnitionState.UNKNOWN) { // We want the initial flight data, not the current here double initialFlightData = core.GetInitialFlightData(); double failureRate = ignitionFailureRate.Evaluate((float)initialFlightData); failureRate = Mathf.Max((float)failureRate, (float)TestFlightUtil.MIN_FAILURE_RATE); // r1 = the chance of survival right now at time index 1 // r2 = the chance of survival through ignition and into initial run up double r1 = Mathf.Exp((float)-failureRate * 1f); double r2 = Mathf.Exp((float)-failureRate * 3f); double survivalChance = r2 / r1; double failureRoll = core.RandomGenerator.NextDouble(); if (failureRoll > survivalChance) { core.TriggerNamedFailure("TestFlightFailure_IgnitionFail"); } } } previousIgnitionState = currentIgnitionState; }
public override void OnUpdate() { if (!TestFlightEnabled) { return; } // For each engine we are tracking, compare its current ignition state to our last known ignition state for (int i = 0; i < engines.Count; i++) { EngineHandler engine = engines[i]; EngineModuleWrapper.EngineIgnitionState currentIgnitionState = engine.engine.IgnitionState; // 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) { if (engine.ignitionState == EngineModuleWrapper.EngineIgnitionState.NOT_IGNITED || engine.ignitionState == EngineModuleWrapper.EngineIgnitionState.UNKNOWN) { double failureRoll = 0d; if (verboseDebugging) { Log(String.Format("IgnitionFail: Engine {0} transitioning to INGITED state", engine.engine.Module.GetInstanceID())); Log(String.Format("IgnitionFail: Checking curves...")); } numIgnitions++; double initialFlightData = core.GetInitialFlightData(); float ignitionChance = 1f; float multiplier = 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) { multiplier = pressureCurve.Evaluate((float)(part.dynamicPressurekPa * 1000d)); if (multiplier <= 0f) { multiplier = 1f; } } float minValue, maxValue = -1f; baseIgnitionChance.FindMinMaxValue(out minValue, out maxValue); if (verboseDebugging) { Log(String.Format("TestFlightFailure_IgnitionFail: IgnitionChance Curve, Min Value {0:F2}:{1:F6}, Max Value {2:F2}:{3:F6}", baseIgnitionChance.minTime, minValue, baseIgnitionChance.maxTime, maxValue)); } if (this.vessel.situation != Vessel.Situations.PRELAUNCH) { ignitionChance = ignitionChance * multiplier * ignitionUseMultiplier.Evaluate(numIgnitions); } failureRoll = core.RandomGenerator.NextDouble(); if (verboseDebugging) { Log(String.Format("IgnitionFail: Engine {0} ignition chance {1:F4}, roll {2:F4}", engine.engine.Module.GetInstanceID(), ignitionChance, failureRoll)); } if (failureRoll > ignitionChance) { engine.failEngine = true; core.TriggerNamedFailure("TestFlightFailure_IgnitionFail"); failureRoll = core.RandomGenerator.NextDouble(); if (failureRoll < additionalFailureChance) { core.TriggerFailure(); } } } } engine.ignitionState = currentIgnitionState; } }
public override void OnUpdate() { if (!TestFlightEnabled) { return; } // For each engine we are tracking, compare its current ignition state to our last known ignition state for (int i = 0; i < engines.Count; i++) { EngineHandler engine = engines[i]; EngineModuleWrapper.EngineIgnitionState currentIgnitionState = engine.engine.IgnitionState; // If we are transitioning from not ignited to ignited, we do our check // The ignitionFailueRate defines the failure rate per flight data if (currentIgnitionState == EngineModuleWrapper.EngineIgnitionState.IGNITED) { if (engine.ignitionState == EngineModuleWrapper.EngineIgnitionState.NOT_IGNITED || engine.ignitionState == EngineModuleWrapper.EngineIgnitionState.UNKNOWN) { Log(String.Format("IgnitionFail: Engine {0} transitioning to INGITED state", engine.engine.Module.GetInstanceID())); Log(String.Format("IgnitionFail: Checking curves...")); if (baseIgnitionChance != null) { Log("IgnitionFail: baseIgnitionChance is valid"); } else { Log("IgnitionFail: baseIgnitionChance is NULL"); } if (pressureCurve != null) { Log("IgnitionFail: pressureCurve is valid"); } else { Log("IgnitionFail: pressureCurve is NULL"); } double initialFlightData = core.GetInitialFlightData(); float ignitionChance = 1f; float multiplier = 1f; ignitionChance = baseIgnitionChance.Evaluate((float)initialFlightData); if (ignitionChance <= 0) { ignitionChance = 1f; } if (pressureCurve != null) { multiplier = pressureCurve.Evaluate((float)DynamicPressure); } if (multiplier <= 0f) { multiplier = 1f; } if (this.vessel.situation != Vessel.Situations.PRELAUNCH) { ignitionChance *= multiplier; } double failureRoll = core.RandomGenerator.NextDouble(); Log(String.Format("IgnitionFail: Engine {0} ignition chance {1:F4}, roll {2:F4}", engine.engine.Module.GetInstanceID(), ignitionChance, failureRoll)); if (failureRoll > ignitionChance) { engine.failEngine = true; core.TriggerNamedFailure("TestFlightFailure_IgnitionFail"); } } } engine.ignitionState = currentIgnitionState; } }