public void CheckChutes() { Vessel vessel = FlightGlobals.ActiveVessel; //Get the vessel cache bool createdNewRecord = false; LoadedQualitySummary qualitySummary = BARISScenario.Instance.GetLoadedQualitySummary(vessel, out createdNewRecord); if (qualitySummary == null) { return; } //Get failure candidates ModuleQualityControl[] failureCandidates = qualitySummary.GetStagingFailureCandidates(stagingID); List <ModuleBreakableParachute> parachutes; int count; for (int index = 0; index < failureCandidates.Length; index++) { parachutes = failureCandidates[index].part.FindModulesImplementing <ModuleBreakableParachute>(); count = parachutes.Count; for (int chuteIndex = 0; chuteIndex < count; chuteIndex++) { parachutes[chuteIndex].isStaged = true; } } }
/// <summary> /// This method performs the staging reliability check. If successful, then all parts in the stage may contribute to their type of part's flight experience. /// If it fails, then one or more parts in the stage may fail regardless of their MTBF rating. If it critically fails, the vessel blows up. /// </summary> public void CheckYoStaging() { debugLog("CheckYoStaging!"); Vessel vessel = FlightGlobals.ActiveVessel; bool isCascadeFailure = false; bool isSuccessfulStaging = false; bool astronautAverted = false; bool isFailure = false; ModuleQualityControl qualityControl = null; int totalBreakables = 0; string message; bool updateEditorBays = false; //Stage check flag stageCheckInProgress = true; disableTestModeIfNeeded(); //Debug stuff if (BARISScenario.showDebug) { isCascadeFailure = NextStagingIsCascadeFailure; NextStagingIsCascadeFailure = false; isSuccessfulStaging = NextStagingIsSuccessful; NextStagingIsSuccessful = false; astronautAverted = NextStagingAstonautAverted; NextStagingAstonautAverted = false; isFailure = NextStagingFails; NextStagingFails = false; } //Get the vessel cache bool createdNewRecord = false; LoadedQualitySummary qualitySummary = BARISScenario.Instance.GetLoadedQualitySummary(vessel, out createdNewRecord); if (qualitySummary == null) { return; } //Get failure candidates ModuleQualityControl[] failureCandidates = qualitySummary.GetStagingFailureCandidates(stagingID); //Make a vessel reliability check QualityCheckResult result = BARISScenario.Instance.PerformQualityCheck(qualitySummary.reliability, qualitySummary.highestRank, 0, false); //Debug checks if (BARISScenario.showDebug) { if (isSuccessfulStaging) { result.statusResult = QualityCheckStatus.success; } else if (astronautAverted) { result.statusResult = QualityCheckStatus.astronautAverted; } else if (isFailure) { result.statusResult = QualityCheckStatus.fail; } else if (isCascadeFailure) { result.statusResult = QualityCheckStatus.criticalFail; } debugLog("DEBUG: New reliability check result: " + result.statusResult); } switch (result.statusResult) { //All the failure candidates explode! case QualityCheckStatus.criticalFail: if (failureCandidates != null) { //Fire the catastrophic failure event to give others a chance to avert disaster somehow. onStagingCriticalFailure?.Invoke(); if (criticalFailureAverted) { //Reset the flag criticalFailureAverted = false; break; } //Ok we're go for vessel destruction! //Cause stress. Lots of it. snacksWrapper.AddStressToCrew(vessel, BARISStressCategories.stressCategoryHigh); //Inform player of cascade failure message = vessel.vesselName + Localizer.Format(BARISScenario.CascadeFailureMsg); BARISScenario.Instance.LogPlayerMessage(message); //Mark a quality module for death. This will blow up the vessel it is attached to. //It cannot be a module that is marked as an escape pod. This part will initiate vessel destruction. //Vessel might or might not be the active vessel depending upon how the abort sequence is set up. ModuleEscapePod escapePod = null; for (int index = failureCandidates.Length - 1; index >= 0; index--) { escapePod = failureCandidates[index].part.FindModuleImplementing <ModuleEscapePod>(); if (escapePod == null || escapePod.escapePodEnabled == false) { failureCandidates[index].SetMarkedForDeath(true); break; } escapePod = null; } //Make an escape check to see if we can trigger an abort sequence. launchEscapeBase = getHighestStupidity(); QualityCheckResult escapeResult = BARISScenario.Instance.PerformQualityCheck(vessel, launchEscapeBase, escapeCheckSkill, false); //Go for abort sequence! if (escapeResult.statusResult != QualityCheckStatus.fail && escapeResult.statusResult != QualityCheckStatus.criticalFail) { //Give crew a chance to get to the escape pods. abandonShip(vessel); //If there is an astronaut aboard with the escape skill then assume the astronaut hit the launch abort. if (escapeResult.astronaut != null) { message = escapeResult.astronaut.name + Localizer.Format(BARISScenario.LASActivatedMsg); BARISScenario.Instance.LogPlayerMessage(message); } //Hit the abort button vessel.ActionGroups.SetGroup(KSPActionGroup.Abort, true); } } else { debugLog("No failure candidates to blow up! Picking a random part to explode..."); int failedPartIndex = UnityEngine.Random.Range(0, qualitySummary.qualityModules.Length - 1); qualitySummary.qualityModules[failedPartIndex].part.explode(); } break; //Log successful flight experience case QualityCheckStatus.success: totalBreakables = qualitySummary.qualityModules.Length; for (int index = 0; index < totalBreakables; index++) { qualitySummary.qualityModules[index].UpdateFlightLog(); } updateEditorBays = true; break; //Any number of the failure candidates can fail. case QualityCheckStatus.fail: if (failureCandidates != null) { int expGainTarget = BARISSettingsLaunch.StagingFailExpTarget; debugLog("Target number to gain flight experience: " + expGainTarget); //Crew gets stressed from parts failing snacksWrapper.AddStressToCrew(vessel, BARISStressCategories.stressCategoryMedium); int failedModules = UnityEngine.Random.Range(1, failureCandidates.Length); for (int index = 0; index < failedModules; index++) { qualityControl = failureCandidates[index]; if (!qualityControl.IsBroken) { qualityControl.DeclarePartBroken(); } else { qualityControl.BreakAPartModule(); } //There's a chance that the part will also gain flight experience if (UnityEngine.Random.Range(1, 100) >= expGainTarget) { debugLog(qualityControl.part.partInfo.title + " has gained flight experience during part failure."); qualityControl.UpdateFlightLog(); updateEditorBays = true; } //There's a chance that the part will explode! if (BARISBridge.FailuresCanExplode) { if (UnityEngine.Random.Range(1, 100) >= BARISBridge.ExplosivePotentialLaunches) { message = qualityControl.part.partInfo.title + Localizer.Format(BARISScenario.CatastrophicFailure); BARISScenario.Instance.LogPlayerMessage(message); qualityControl.part.explosionPotential = 0.01f; qualityControl.part.explode(); } } } } else { debugLog("No failureCandidates have MTBF = 0"); } break; //Add a failure averted event card case QualityCheckStatus.criticalSuccess: totalBreakables = qualitySummary.qualityModules.Length; for (int index = 0; index < totalBreakables; index++) { qualitySummary.qualityModules[index].UpdateFlightLog(); } break; //Show event card result case QualityCheckStatus.eventCardAverted: break; //Shout out to the astronaut that saved the day case QualityCheckStatus.astronautAverted: if (qualitySummary.rankingAstronaut != null) { //Astronaut gets a small amount of stress snacksWrapper.AddStressToCrew(vessel, BARISStressCategories.stressCategoryLow); message = qualitySummary.rankingAstronaut.name + Localizer.Format(BARISScenario.QualityCheckFailAvertedAstronaut3); if (BARISSettings.LogAstronautAvertMsg) { BARISScenario.Instance.LogPlayerMessage(message); } else { FlightLogger.fetch.LogEvent(message); } } break; default: break; } //Cleanup if (updateEditorBays) { BARISScenario.Instance.UpdateEditorBayFlightBonuses(); } BARISAppButton.flightAppView.UpdateCachedData(); stageCheckInProgress = false; }