private void SetNextCheck(List <BaseFailureModule> failureModules) { double chanceOfEvent = 0; double chanceOfIndividualFailure = 0; double exponent = 0; double preparedNumber; int moduleCount = 0; for (int i = 0; i < failureModules.Count(); i++) { BaseFailureModule failedModule = failureModules.ElementAt(i); if (failedModule.hasFailed) { continue; } if (failedModule.isSRB) { continue; } if (failedModule.excluded) { continue; } if (!failedModule.launched) { return; } if (!failedModule.FailureAllowed()) { continue; } moduleCount++; } preparedNumber = 1 - chanceOfFailure; preparedNumber = Math.Pow(preparedNumber, moduleCount); chanceOfIndividualFailure = 1 - preparedNumber; if (FlightGlobals.ActiveVessel.situation == Vessel.Situations.FLYING && FlightGlobals.ActiveVessel.mainBody == FlightGlobals.GetHomeBody()) { if (FlightGlobals.ActiveVessel.missionTime < timeToOrbit) { nextFailureCheck = Planetarium.GetUniversalTime() + timeBetweenChecksRocketsAtmosphere; failureMode = "Atmosphere"; sampleTime = timeToOrbit / 60 + " minutes"; } else { nextFailureCheck = Planetarium.GetUniversalTime() + timeBetweenChecksPlanes; failureMode = "Plane"; sampleTime = "15 minutes"; } } else if (VesselIsInLocalSpace()) { nextFailureCheck = Planetarium.GetUniversalTime() + timeBetweenChecksRocketsLocalSpace; failureMode = "Local Space"; sampleTime = "7 days"; } else { nextFailureCheck = Planetarium.GetUniversalTime() + timeBetweenChecksRocketsDeepSpace; failureMode = "Deep Space"; sampleTime = "30 days"; } switch (failureMode) { case "Atmosphere": exponent = timeToOrbit / timeBetweenChecksRocketsAtmosphere; break; case "Plane": exponent = 900 / timeBetweenChecksPlanes; break; case "Local Space": exponent = 25200 / timeBetweenChecksRocketsLocalSpace; break; case "Deep Space": exponent = 648000 / timeBetweenChecksRocketsDeepSpace; break; } preparedNumber = vesselSafetyRating * 0.01; preparedNumber = 0.11f - preparedNumber; preparedNumber = 1 - preparedNumber; preparedNumber = Math.Pow(preparedNumber, exponent); chanceOfEvent = 1 - preparedNumber; displayFailureChance = Math.Round(chanceOfEvent * chanceOfIndividualFailure * 100, 0); if (HighLogic.CurrentGame.Parameters.CustomParams <UPFMSettings>().logging) { Logger.instance.Log("[OhScrap]: Next Failure Check in " + (nextFailureCheck - Planetarium.GetUniversalTime())); Logger.instance.Log("[OhScrap]: Calculated chance of failure in next " + sampleTime + " is " + displayFailureChance + "%"); } }
private void CheckForFailures() { if (!FlightGlobals.ready) { return; } if (KRASHWrapper.simulationActive()) { return; } if (FlightGlobals.ActiveVessel.FindPartModuleImplementing <ModuleUPFMEvents>() != null) { if (FlightGlobals.ActiveVessel.FindPartModuleImplementing <ModuleUPFMEvents>().tested == false) { return; } } if (Planetarium.GetUniversalTime() < nextFailureCheck) { return; } if (vesselSafetyRating == -1) { return; } List <BaseFailureModule> failureModules = FlightGlobals.ActiveVessel.FindPartModulesImplementing <BaseFailureModule>(); if (failureModules.Count == 0) { return; } if (!VesselIsLaunched()) { return; } chanceOfFailure = 0.11 - (vesselSafetyRating * 0.01); if (chanceOfFailure < minimumFailureChance) { chanceOfFailure = minimumFailureChance; } SetNextCheck(failureModules); double failureRoll = _randomiser.NextDouble(); if (HighLogic.CurrentGame.Parameters.CustomParams <UPFMSettings>().logging) { Logger.instance.Log("Failure Chance: " + chanceOfFailure + ", Rolled: " + failureRoll + " Succeeded: " + (failureRoll <= chanceOfFailure).ToString()); } if (failureRoll > chanceOfFailure) { return; } Logger.instance.Log("Failure Event! Safety Rating: " + vesselSafetyRating + ", MET: " + FlightGlobals.ActiveVessel.missionTime); BaseFailureModule failedModule = null; int counter = failureModules.Count() - 1; failureModules = failureModules.OrderBy(f => f.chanceOfFailure).ToList(); while (counter >= 0) { failedModule = failureModules.ElementAt(counter); counter--; if (failedModule.hasFailed) { continue; } if (failedModule.isSRB) { continue; } if (failedModule.excluded) { continue; } if (!failedModule.launched) { return; } if (!failedModule.FailureAllowed()) { continue; } if (_randomiser.NextDouble() < failedModule.chanceOfFailure) { if (failedModule.hasFailed) { continue; } StartFailure(failedModule); Logger.instance.Log("Failing " + failedModule.part.partInfo.title); break; } } if (counter < 0) { Logger.instance.Log("No parts failed this time. Aborted failure"); } }