public void TrashPart() { if (!doNotRecover) { doNotRecover = true; ScreenMessages.PostScreenMessage(part.partInfo.title + " will not be recovered"); } else { List <BaseFailureModule> modules = part.FindModulesImplementing <BaseFailureModule>(); if (modules.Count == 0) { return; } for (int i = 0; i < modules.Count; i++) { BaseFailureModule bfm = modules.ElementAt(i); if (bfm.hasFailed) { ScreenMessages.PostScreenMessage(part.partInfo.title + " cannot be saved"); return; } } doNotRecover = false; ScreenMessages.PostScreenMessage(part.partInfo.title + " will be recovered"); } Debug.Log("[OhScrap]: TrashPart " + SYP.ID + " " + doNotRecover); }
//When the Editor Vessel is modified check the safety ratings and update the UI private void onEditorShipModified(ShipConstruct shipConstruct) { vesselSafetyRating = 0; float worstPartChance = 1; int bfmCount = 0; editorConstruct = shipConstruct; for (int i = 0; i < shipConstruct.parts.Count(); i++) { Part p = shipConstruct.parts.ElementAt(i); List <BaseFailureModule> bfmList = p.FindModulesImplementing <BaseFailureModule>(); for (int b = 0; b < bfmList.Count(); b++) { BaseFailureModule bfm = bfmList.ElementAt(b); if (bfm == null) { continue; } if (bfm.chanceOfFailure > worstPartChance && !bfm.isSRB && !bfm.hasFailed) { worstPart = p; worstPartChance = bfm.chanceOfFailure; } vesselSafetyRating += bfm.safetyRating; bfmCount++; } vesselSafetyRating = vesselSafetyRating / bfmCount; } }
bool Repaired() { List <BaseFailureModule> failedList = part.FindModulesImplementing <BaseFailureModule>(); if (failedList.Count() == 0) { return(true); } //Loop through everything that inherits BaseFailureModule on this part and check the hasFailed flag. If true, return false, otherwise return true. for (int i = 0; i < failedList.Count(); i++) { BaseFailureModule bfm = failedList.ElementAt(i); if (bfm == null) { continue; } if (!bfm.hasFailed) { continue; } repair = bfm; return(false); } Events["RepairChecks"].active = false; Events["ToggleHighlight"].active = false; doNotRecover = false; return(true); }
//When the Editor Vessel is modified check the safety ratings and update the UI private void onEditorShipModified(ShipConstruct shipConstruct) { vesselSafetyRating = 6; editorConstruct = shipConstruct; for (int i = 0; i < shipConstruct.parts.Count(); i++) { Part p = shipConstruct.parts.ElementAt(i); List <BaseFailureModule> bfmList = p.FindModulesImplementing <BaseFailureModule>(); for (int b = 0; b < bfmList.Count(); b++) { BaseFailureModule bfm = bfmList.ElementAt(b); if (bfm == null) { continue; } if (bfm.safetyRating < vesselSafetyRating && !bfm.excluded && !bfm.hasFailed) { vesselSafetyRating = bfm.safetyRating; worstPart = p; } } } }
private void StartFailure(BaseFailureModule failedModule) { failedModule.FailPart(); failedModule.hasFailed = true; ModuleUPFMEvents eventModule = failedModule.part.FindModuleImplementing <ModuleUPFMEvents>(); eventModule.highlight = true; eventModule.SetFailedHighlight(); eventModule.Events["ToggleHighlight"].active = true; eventModule.Events["RepairChecks"].active = true; eventModule.doNotRecover = true; ScreenMessages.PostScreenMessage(failedModule.part.partInfo.title + ": " + failedModule.failureType); StringBuilder msg = new StringBuilder(); msg.AppendLine(failedModule.part.vessel.vesselName); msg.AppendLine(""); msg.AppendLine(failedModule.part.partInfo.title + " has suffered a " + failedModule.failureType); msg.AppendLine(""); MessageSystem.Message m = new MessageSystem.Message("OhScrap", msg.ToString(), MessageSystemButton.MessageButtonColor.ORANGE, MessageSystemButton.ButtonIcons.ALERT); MessageSystem.Instance.AddMessage(m); Debug.Log("[OhScrap]: " + failedModule.SYP.ID + " of type " + failedModule.part.partInfo.title + " has suffered a " + failedModule.failureType); TimeWarp.SetRate(0, true); Logger.instance.Log("Failure Successful"); }
public void RepairChecks() { Debug.Log("[OhScrap]: Attempting repairs"); bool repairAllowed = true; List <BaseFailureModule> bfm = part.FindModulesImplementing <BaseFailureModule>(); //If no kerbal on EVA we can assume this is a remote repair. if (FlightGlobals.ActiveVessel.FindPartModuleImplementing <KerbalEVA>() == null) { Debug.Log("[OhScrap]: Attempting Remote Repair"); //If CommNet or RemoteTech is enabled, check if vessel is connected. (can't upload a software fix with no connection) if (ModWrapper.RemoteTechWrapper.available && !ModWrapper.RemoteTechWrapper.HasConnectionToKSC(FlightGlobals.ActiveVessel.id)) { ScreenMessages.PostScreenMessage("Vessel must be connected to Homeworld before remote repair can be attempted"); Debug.Log("[OhScrap]:(RemoteTech) Remote Repair aborted. Vessel not connected home"); return; } else if (CommNet.CommNetScenario.CommNetEnabled && !FlightGlobals.ActiveVessel.Connection.IsConnectedHome) { ScreenMessages.PostScreenMessage("Vessel must be connected to Homeworld before remote repair can be attempted"); Debug.Log("[OhScrap]: Remote Repair aborted. Vessel not connected home"); return; } //Check if the part is actually remote repairable. This will fail if any of the failed modules are not remote repairable. for (int i = 0; i < bfm.Count(); i++) { BaseFailureModule b = bfm.ElementAt(i); if (b.hasFailed) { if (!b.remoteRepairable) { ScreenMessages.PostScreenMessage(part.partInfo.title + "cannot be repaired remotely"); repairAllowed = false; Debug.Log("[OhScrap]: Remote Repair not allowed on " + SYP.ID + " " + b.ClassName); continue; } } else { continue; } } } if (!repairAllowed) { return; } //Repaired loops through all modules and checks them for the hasFailed == true flag //If it finds it, it will return false and the repair checks will continue. //This will carry on until either a module cant be repaired, or all modules are repaired. while (!Repaired()) { //If the module fails the check or it's already been marked as irrepairable will stop trying. if (!RepairFailCheck() || repairTried) { ScreenMessages.PostScreenMessage("This part is beyond repair"); repairTried = true; Debug.Log("[OhScrap]: " + SYP.ID + " is too badly damaged to be fixed"); return; } //reset the failure status on the module and disables the highlight. repair.hasFailed = false; repair.willFail = false; repair.RepairPart(); if (!customFailureEvent) { ScreenMessages.PostScreenMessage("The part should be ok to use now"); } repair.numberOfRepairs++; Debug.Log("[OhScrap]: " + SYP.ID + " " + repair.moduleName + " was successfully repaired"); part.highlightType = Part.HighlightType.OnMouseOver; part.SetHighlightColor(Color.green); part.SetHighlight(false, false); } //Once the part has been repaired run the Initialise Event again (possibly another fail) for (int i = 0; i < bfm.Count; i++) { BaseFailureModule bf = bfm.ElementAt(i); bf.Initialise(); } }
//This is mostly for use in the flight scene, will only run once assuming everything goes ok. void Update() { try { int bfmCount = 0; vesselSafetyRating = 0; double worstPartChance = 0; if (!HighLogic.LoadedSceneIsEditor && FlightGlobals.ready) { for (int i = 0; i < FlightGlobals.ActiveVessel.parts.Count(); i++) { Part p = FlightGlobals.ActiveVessel.parts.ElementAt(i); List <BaseFailureModule> bfmList = p.FindModulesImplementing <BaseFailureModule>(); for (int b = 0; b < bfmList.Count(); b++) { BaseFailureModule bfm = bfmList.ElementAt(b); if (bfm == null) { continue; } if (!bfm.ready) { return; } if (bfm.chanceOfFailure > worstPartChance && !bfm.isSRB && !bfm.hasFailed) { worstPart = p; worstPartChance = bfm.chanceOfFailure; } vesselSafetyRating += bfm.safetyRating; bfmCount++; } } } if (HighLogic.LoadedSceneIsEditor) { if (editorConstruct == null || editorConstruct.parts.Count() == 0) { editorConstruct = EditorLogic.fetch.ship; } for (int i = 0; i < editorConstruct.parts.Count(); i++) { Part p = editorConstruct.parts.ElementAt(i); List <BaseFailureModule> bfmList = p.FindModulesImplementing <BaseFailureModule>(); for (int b = 0; b < bfmList.Count(); b++) { BaseFailureModule bfm = bfmList.ElementAt(b); if (bfm == null) { continue; } if (!bfm.ready) { return; } if (bfm.chanceOfFailure > worstPartChance) { worstPart = p; worstPartChance = bfm.chanceOfFailure; } vesselSafetyRating += bfm.safetyRating; bfmCount++; } } if (bfmCount == 0) { editorConstruct = null; } } vesselSafetyRating = vesselSafetyRating / bfmCount; } catch (DivideByZeroException) { return; } finally { if (worstPart != null) { if (highlightWorstPart && worstPart.highlightType == Part.HighlightType.OnMouseOver) { worstPart.SetHighlightColor(Color.yellow); worstPart.SetHighlightType(Part.HighlightType.AlwaysOn); worstPart.SetHighlight(true, false); } if (!highlightWorstPart && worstPart.highlightType == Part.HighlightType.AlwaysOn && !worstPart.FindModuleImplementing <ModuleUPFMEvents>().highlightOverride) { worstPart.SetHighlightType(Part.HighlightType.OnMouseOver); worstPart.SetHighlightColor(Color.green); worstPart.SetHighlight(false, false); } } } }
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"); } }
//This is mostly for use in the flight scene, will only run once assuming everything goes ok. void Update() { if (vesselSafetyRating == 6) { if (!HighLogic.LoadedSceneIsEditor && FlightGlobals.ready) { for (int i = 0; i < FlightGlobals.ActiveVessel.parts.Count(); i++) { Part p = FlightGlobals.ActiveVessel.parts.ElementAt(i); List <BaseFailureModule> bfmList = p.FindModulesImplementing <BaseFailureModule>(); for (int b = 0; b < bfmList.Count(); b++) { BaseFailureModule bfm = bfmList.ElementAt(b); if (bfm == null) { continue; } if (bfm.safetyRating < vesselSafetyRating && !bfm.excluded) { vesselSafetyRating = bfm.safetyRating; worstPart = p; } } } } if (HighLogic.LoadedSceneIsEditor && editorConstruct != null) { for (int i = 0; i < editorConstruct.parts.Count(); i++) { Part p = editorConstruct.parts.ElementAt(i); List <BaseFailureModule> bfmList = p.FindModulesImplementing <BaseFailureModule>(); for (int b = 0; b < bfmList.Count(); b++) { BaseFailureModule bfm = bfmList.ElementAt(b); if (bfm == null) { continue; } if (bfm.safetyRating < vesselSafetyRating) { vesselSafetyRating = bfm.safetyRating; worstPart = p; } } } } } if (worstPart != null) { if (highlightWorstPart && worstPart.highlightType == Part.HighlightType.OnMouseOver) { worstPart.SetHighlightColor(Color.yellow); worstPart.SetHighlightType(Part.HighlightType.AlwaysOn); worstPart.SetHighlight(true, false); } if (!highlightWorstPart && worstPart.highlightType == Part.HighlightType.AlwaysOn && !worstPart.FindModuleImplementing <ModuleUPFMEvents>().highlightOverride) { worstPart.SetHighlightType(Part.HighlightType.OnMouseOver); worstPart.SetHighlightColor(Color.green); worstPart.SetHighlight(false, false); } } }