public void DrawWindow(int windowID) { if (selectedPart != null) { ITestFlightCore core = TestFlightUtil.GetCore(selectedPart); if (core != null) { GUILayout.Label(selectedPart.partInfo.title, Styles.styleEditorTitle); if (show) { List <string> infoParts = core.GetTestFlightInfo(); GUILayout.BeginVertical(); foreach (string info in infoParts) { GUILayout.Label(info, Styles.styleEditorText); } GUILayout.EndVertical(); } else { GUILayout.Space(2.0f); GUILayout.Label("Middle click to show TestFlight info...", Styles.styleEditorText); } } } }
private void InitializeParts(Vessel vessel) { foreach (Part part in vessel.parts) { // Each KSP part can be composed of N virtual parts List <string> cores = TestFlightInterface.GetActiveCores(part); if (cores == null || cores.Count <= 0) { continue; } foreach (string activeCore in cores) { ITestFlightCore core = TestFlightUtil.GetCore(part, activeCore); if (core != null) { if (TestFlightManagerScenario.Instance.SettingsAlwaysMaxData) { core.InitializeFlightData(core.GetMaximumData()); } else { TestFlightPartData partData = tfScenario.GetPartDataForPart(activeCore); if (partData != null) { core.InitializeFlightData(partData.GetFloat("flightData")); } else { core.InitializeFlightData(0f); } } } } } }
private void InitializeParts(Vessel vessel) { Log("TestFlightManager: Initializing parts for vessel " + vessel.GetName()); // Launch time is equal to current UT unless we have already chached this vessel's launch time double launchTime = Planetarium.GetUniversalTime(); if (knownVessels.ContainsKey(vessel.id)) { launchTime = knownVessels[vessel.id]; } foreach (Part part in vessel.parts) { ITestFlightCore core = TestFlightUtil.GetCore(part); if (core != null) { Log("TestFlightManager: Found core. Getting part data"); PartFlightData partData = tfScenario.GetFlightDataForPartName(TestFlightUtil.GetFullPartName(part)); if (partData == null) { Log("TestFlightManager: Unable to find part data. Starting fresh."); core.InitializeFlightData(null); } else { core.InitializeFlightData(partData.GetFlightData()); } } } }
public override void OnStart(StartState state) { base.OnStart(state); core = TestFlightUtil.GetCore(this.part, Configuration); if (core != null) { Startup(); } }
// Failure methods public override void DoFailure() { if (!TestFlightEnabled) { return; } Failed = true; float multiplier = 0; ITestFlightCore core = TestFlightUtil.GetCore(this.part, Configuration); if (core != null) { core.ModifyFlightData(duFail, true); 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; } } if (multiplier > float.Epsilon) { FlightLogger.eventLog.Add($"[{met}] {core.Title} failed: Ignition Failure. {(float)(part.dynamicPressurekPa * 1000d)}Pa dynamic pressure cased a {(1f-multiplier) * 100f}% reduction in normal ignition reliability."); } else { FlightLogger.eventLog.Add($"[{met}] {core.Title} failed: Ignition Failure."); } } Log(String.Format("IgnitionFail: Failing {0} engine(s)", engines.Count)); for (int i = 0; i < engines.Count; i++) { EngineHandler engine = engines[i]; if (engine.failEngine) { engine.engine.Shutdown(); if (severity.ToLowerInvariant() == "major") { // For some reason, need to disable GUI as well engine.engine.Events["Activate"].active = false; engine.engine.Events["Shutdown"].active = false; engine.engine.Events["Activate"].guiActive = false; engine.engine.Events["Shutdown"].guiActive = false; } if ((restoreIgnitionCharge) || (this.vessel.situation == Vessel.Situations.PRELAUNCH)) { RestoreIgnitor(); } engines[i].failEngine = false; } } }
public void OnEnable() { if (core == null) { core = TestFlightUtil.GetCore(this.part, Configuration); } if (core != null) { Startup(); } }
/// <summary> /// Triggers the failure controlled by the failure module /// </summary> public override void DoFailure() { base.DoFailure(); // for each engine change its fuelFlow which will affect thrust foreach (EngineHandler engine in engines) { float jitter = ispMultiplierJitter - ((float)TestFlightUtil.GetCore(this.part, Configuration).RandomGenerator.NextDouble() * (ispMultiplierJitter * 2)); float actualMultiplier = ispMultiplier + jitter; engine.engine.SetFuelIspMult(actualMultiplier); } }
public void AddResearchTeam(Part part, string alias, int team) { Log(String.Format("Assign team #{0} to part", team)); if (IsPartBeingResearched(alias)) { return; } ITestFlightCore core = TestFlightUtil.GetCore(part, alias); if (core == null) { return; } if (TestFlightManagerScenario.Instance == null) { return; } if (!TestFlightManagerScenario.Instance.SettingsEnabled) { return; } if (availableTeams == null) { CreateTeams(); } if (team < availableTeams.Count) { float techTransfer = core.GetTechTransfer(); if (techTransfer > 0f) { TestFlightManagerScenario.Instance.AddFlightDataForPartName(alias, techTransfer); } TestFlightRnDTeam template = availableTeams[team]; activeTeams.Add(alias, new TestFlightRnDTeam(template.Points, template.CostFactor)); activeTeams[alias].PartInResearch = alias; activeTeams[alias].MaxData = core.GetMaximumRnDData() + techTransfer; activeTeams[alias].PartRnDCost = core.GetRnDCost(); activeTeams[alias].PartRnDRate = core.GetRnDRate(); activeTeams[alias].ResearchActive = true; Log(String.Format("Team #{0} has been assigned to part {1}", team, alias)); } else { Log(String.Format("Team #{0} is not valid. There are {1} teams.", team, availableTeams.Count)); } Log(String.Format("New active team count is {0}", activeTeams.Count)); }
public override void OnStart(StartState state) { base.OnStart(state); core = TestFlightUtil.GetCore(this.part, Configuration); if (core != null) { Startup(); } // Get the in-game setting for Launch Pad Ignition Failures preLaunchFailures = HighLogic.CurrentGame.Parameters.CustomParams <TestFlightGameSettings>().preLaunchFailures; }
public static bool TestFlightAvailable(Part part) { ITestFlightCore core = TestFlightUtil.GetCore(part); if (core == null) { return(false); } else { return(true); } }
/// <summary> /// Triggers the failure controlled by the failure module /// </summary> public override void DoFailure() { base.DoFailure(); if (resourceToLeak.ToLower() == "all") { foreach (PartResource r in this.part.Resources) { int resId = r.info.id; ParseResourceValues(resId); leaks.Add(new ResourceLeak(resId, _perSecondAmount, _initialAmount)); } } else { int resId = 0; bool found = false; if (resourceToLeak.ToLower() == "random") { if (part.Resources.Count > 0) { List <PartResource> allResources = this.part.Resources.list; int randomResource = TestFlightUtil.GetCore(this.part, Configuration).RandomGenerator.Next(0, allResources.Count()); resId = allResources[randomResource].info.id; found = true; } } else { List <PartResource> resources = this.part.Resources.list.Where(n => n.resourceName == resourceToLeak).ToList(); if (resources != null && resources.Count > 0) { resId = resources[0].info.id; found = true; } } if (found) { ParseResourceValues(resId); leaks.Add(new ResourceLeak(resId, _perSecondAmount, _initialAmount)); } } if (leaks.Count > 0 && !isLeaking) { isLeaking = true; foreach (ResourceLeak leak in leaks) { this.part.RequestResource(leak.id, leak.initialAmount, ResourceFlowMode.NO_FLOW); } } }
IEnumerator Attach() { while (this.part == null || this.part.partInfo == null || this.part.partInfo.partPrefab == null || this.part.Modules == null) { yield return(null); } while (core == null) { core = TestFlightUtil.GetCore(this.part, Configuration); yield return(null); } Startup(); }
public override void OnStart(StartState state) { base.OnStart(state); core = TestFlightUtil.GetCore(this.part, Configuration); if (core != null) { Startup(); } verboseDebugging = core.DebugEnabled; // Get the in-game settings preLaunchFailures = HighLogic.CurrentGame.Parameters.CustomParams <TestFlightGameSettings>().preLaunchFailures; dynPressurePenalties = HighLogic.CurrentGame.Parameters.CustomParams <TestFlightGameSettings>().dynPressurePenalties; }
IEnumerator Attach() { while (this.part == null || this.part.Modules == null) { yield return(null); } while (core == null) { core = TestFlightUtil.GetCore(this.part); yield return(null); } Startup(); }
public void OnGUI() { if (selectedPart == null) { return; } ITestFlightCore core = TestFlightUtil.GetCore(selectedPart); if (core == null) { return; } position = GUILayout.Window(GetInstanceID(), position, DrawWindow, String.Empty, Styles.styleEditorPanel); }
private void InitializeParts(Vessel vessel) { if (!tfScenario.SettingsEnabled) { return; } // Launch time is equal to current UT unless we have already cached this vessel's launch time double launchTime = Planetarium.GetUniversalTime(); if (knownVessels.ContainsKey(vessel.id)) { launchTime = knownVessels[vessel.id]; } foreach (Part part in vessel.parts) { // Each KSP part can be composed of N virtual parts List <string> cores = TestFlightInterface.GetActiveCores(part); if (cores == null || cores.Count <= 0) { continue; } foreach (string activeCore in cores) { ITestFlightCore core = TestFlightUtil.GetCore(part, activeCore); if (core != null) { Log("TestFlightManager: Found core. Getting part data"); if (TestFlightManagerScenario.Instance.SettingsAlwaysMaxData) { core.InitializeFlightData(core.GetMaximumData()); } else { TestFlightPartData partData = tfScenario.GetPartDataForPart(activeCore); if (partData != null) { core.InitializeFlightData(partData.GetFloat("flightData")); } else { core.InitializeFlightData(0f); } } } } } }
private void InitializeParts(Vessel vessel) { Log("TestFlightManager: Initializing parts for vessel " + vessel.GetName()); // Launch time is equal to current UT unless we have already cached this vessel's launch time double launchTime = Planetarium.GetUniversalTime(); if (knownVessels.ContainsKey(vessel.id)) { launchTime = knownVessels[vessel.id]; } foreach (Part part in vessel.parts) { ITestFlightCore core = TestFlightUtil.GetCore(part); if (core != null) { Log("TestFlightManager: Found core. Getting part data"); if (TestFlightManagerScenario.Instance.SettingsAlwaysMaxData) { core.InitializeFlightData(core.GetMaximumData()); } else { TestFlightPartData partData = tfScenario.GetPartDataForPart(TestFlightUtil.GetFullPartName(part)); if (partData != null) { core.InitializeFlightData(partData.GetFloat("flightData")); } else { core.InitializeFlightData(0f); } } } } }
internal override void DrawWindow(int id) { if (!isReady) { return; } if (SelectedPart == null) { GUILayout.BeginVertical(); GUILayout.Label("Select a part to display its details", Styles.styleEditorTitle); GUILayout.Label("MouseOver part in bin or 3D view to quickview", Styles.styleEditorText); GUILayout.Label("RightClick part in bin (not 3D) to toggle window lock on that part", Styles.styleEditorText); GUILayout.EndVertical(); if (DrawToggle(ref tfScenario.userSettings.editorWindowLocked, "Lock Window", Styles.styleToggle)) { if (tfScenario.userSettings.editorWindowLocked) { CalculateWindowBounds(); tfScenario.userSettings.editorWindowPosition = WindowRect; DragEnabled = false; } else { DragEnabled = true; } tfScenario.userSettings.Save(); } return; } ITestFlightCore core = null; GUILayout.BeginVertical(); GUILayout.Label(String.Format("Selected Part: {0}", TestFlightUtil.GetFullPartName(SelectedPart)), Styles.styleEditorTitle); tfScenario.userSettings.currentEditorScrollPosition = GUILayout.BeginScrollView(tfScenario.userSettings.currentEditorScrollPosition); TestFlightPartData partData = tfScenario.GetPartDataForPart(TestFlightUtil.GetFullPartName(SelectedPart)); if (partData != null) { float flightData = partData.GetFloat("flightData"); core = TestFlightUtil.GetCore(SelectedPart); if (core != null) { core.InitializeFlightData(flightData); GUILayout.BeginHorizontal(); double failureRate = core.GetBaseFailureRate(); String mtbfString = core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, 999); // 10 characters for body max plus 10 characters for situation plus underscore = 21 characters needed for longest scope string GUILayout.Label(String.Format("{0,-7:F2}<b>du</b>", flightData), GUILayout.Width(75)); GUILayout.Label(String.Format("{0,-5:F2} MTBF", mtbfString), GUILayout.Width(125)); GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); if (DrawToggle(ref tfScenario.userSettings.editorWindowLocked, "Lock Window", Styles.styleToggle)) { if (tfScenario.userSettings.editorWindowLocked) { CalculateWindowBounds(); tfScenario.userSettings.editorWindowPosition = WindowRect; DragEnabled = false; } else { DragEnabled = true; } tfScenario.userSettings.Save(); } GUILayout.EndVertical(); }
internal override void Update() { if (!isReady) { return; } if (masterStatus == null) { masterStatus = new Dictionary <Guid, MasterStatusItem>(); } currentUTC = Planetarium.GetUniversalTime(); // ensure out vessel list is up to date CacheVessels(); if (currentUTC >= lastMasterStatusUpdate + tfScenario.userSettings.masterStatusUpdateFrequency) { lastMasterStatusUpdate = currentUTC; VerifyMasterStatus(); } // process vessels foreach (var entry in knownVessels) { Vessel vessel = FlightGlobals.Vessels.Find(v => v.id == entry.Key); if (vessel.loaded) { foreach (Part part in vessel.parts) { ITestFlightCore core = TestFlightUtil.GetCore(part); if (core != null) { // Poll for flight data and part status if (currentUTC >= lastDataPoll + tfScenario.userSettings.masterStatusUpdateFrequency) { TestFlightData currentFlightData = new TestFlightData(); currentFlightData.scope = core.GetScope(); currentFlightData.flightData = core.GetFlightData(); currentFlightData.flightTime = core.GetFlightTime(); PartStatus partStatus = new PartStatus(); partStatus.flightCore = core; partStatus.partName = TestFlightUtil.GetPartTitle(part); partStatus.partID = part.flightID; partStatus.flightData = currentFlightData.flightData; partStatus.flightTime = currentFlightData.flightTime; partStatus.partStatus = core.GetPartStatus(); partStatus.timeToRepair = core.GetRepairTime(); double failureRate = core.GetBaseFailureRate(); MomentaryFailureRate momentaryFailureRate = core.GetWorstMomentaryFailureRate(); if (momentaryFailureRate.valid && momentaryFailureRate.failureRate > failureRate) { failureRate = momentaryFailureRate.failureRate; } partStatus.momentaryFailureRate = failureRate; partStatus.repairRequirements = core.GetRequirementsTooltip(); partStatus.acknowledged = core.IsFailureAcknowledged(); partStatus.activeFailure = core.GetFailureModule(); partStatus.mtbfString = core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, 999); // Update or Add part status in Master Status if (masterStatus.ContainsKey(vessel.id)) { // Vessel is already in the Master Status, so check if part is in there as well int numItems = masterStatus[vessel.id].allPartsStatus.Count(p => p.partID == part.flightID); int existingPartIndex; if (numItems == 1) { existingPartIndex = masterStatus[vessel.id].allPartsStatus.FindIndex(p => p.partID == part.flightID); masterStatus[vessel.id].allPartsStatus[existingPartIndex] = partStatus; } else if (numItems == 0) { masterStatus[vessel.id].allPartsStatus.Add(partStatus); } else { existingPartIndex = masterStatus[vessel.id].allPartsStatus.FindIndex(p => p.partID == part.flightID); masterStatus[vessel.id].allPartsStatus[existingPartIndex] = partStatus; Log("[ERROR] TestFlightManager: Found " + numItems + " matching parts in Master Status Display!"); } } else { // Vessel is not in the Master Status so create a new entry for it and add this part MasterStatusItem masterStatusItem = new MasterStatusItem(); masterStatusItem.vesselID = vessel.id; masterStatusItem.vesselName = vessel.GetName(); masterStatusItem.allPartsStatus = new List <PartStatus>(); masterStatusItem.allPartsStatus.Add(partStatus); masterStatus.Add(vessel.id, masterStatusItem); } PartFlightData data = tfScenario.GetFlightDataForPartName(TestFlightUtil.GetFullPartName(part)); if (data != null) { data.AddFlightData(part.name, currentFlightData); } else { data = new PartFlightData(); data.AddFlightData(TestFlightUtil.GetFullPartName(part), currentFlightData); tfScenario.SetFlightDataForPartName(TestFlightUtil.GetFullPartName(part), data); } } } } } if (currentUTC >= lastDataPoll + tfScenario.userSettings.minTimeBetweenDataPoll) { lastDataPoll = currentUTC; } if (currentUTC >= lastFailurePoll + tfScenario.userSettings.minTimeBetweenFailurePoll) { lastFailurePoll = currentUTC; } } }
internal override void DrawWindow(int id) { if (!isReady) { return; } if (SelectedPart == null) { return; } ITestFlightCore core = null; GUILayout.BeginVertical(); GUILayout.Label(String.Format("Selected Part: {0}", selectedAlias), Styles.styleEditorTitle); float flightData = TestFlightManagerScenario.Instance.GetFlightDataForPartName(selectedAlias); if (flightData < 0f) { flightData = 0f; } core = TestFlightUtil.GetCore(SelectedPart, selectedAlias); if (core != null) { core.InitializeFlightData(flightData); GUILayout.BeginHorizontal(); double failureRate = core.GetBaseFailureRate(); Log(String.Format("Failure rate is {0:f2}", failureRate)); String mtbfString = core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, 999); GUILayout.Label(String.Format("{0,-7:F2}<b>du</b>", flightData), GUILayout.Width(75)); GUILayout.Label(String.Format("{0,-5:F2} MTBF", mtbfString), GUILayout.Width(125)); GUILayout.EndHorizontal(); Log("Checking for RnD Status"); string partName = selectedAlias; float maxRnDData = core.GetMaximumRnDData(); if (flightData >= maxRnDData) { Log("Part has reached Max RnD"); GUILayout.Label("Part flight data meets or exceeds maximum lab R&D amount", Styles.styleEditorText); } else { Log("Part is RnD Eligible"); if (!tfRnDScenario.IsPartBeingResearched(partName)) { Log("Part is not being researched. Show research buttons"); int frequency = (int)tfRnDScenario.updateFrequency; Log(String.Format("Update Frequency is {0}", frequency)); TimeSpan span = new TimeSpan(0, 0, frequency); string cycleString; if (span.TotalDays > 1d) { cycleString = String.Format("{0:F2} days", span.TotalDays); } else { cycleString = String.Format("{0:F2} day", span.TotalDays); } GUILayout.Label("Hire Research Team", Styles.styleEditorTitle); GUILayout.Label("Research teams deduct funds and add flight data to your part", Styles.styleEditorText); GUILayout.Label("A research cycle lasts <b>" + cycleString + "</b>", Styles.styleEditorText); GUILayout.Label("At the end of each cycle, funds will be deducted and data added", Styles.styleEditorText); GUILayout.Label("The costs and research rate varies by team", Styles.styleEditorText); List <TestFlightRNDTeamSettings> teams = tfRnDScenario.GetAvailableTeams(); if (teams != null) { int numTeams = teams.Count; for (int i = 0; i < numTeams; i++) { GUILayout.BeginHorizontal(); if (GUILayout.Button(String.Format("Hire Team"), GUILayout.Width(100))) { tfRnDScenario.AddResearchTeam(SelectedPart, selectedAlias, i); } Log(String.Format("cycle is {0}", cycleString)); float points = teams[i].points; float cost = teams[i].costFactor * points; points = points * core.GetRnDRate(); cost = cost * core.GetRnDCost(); GUILayout.Label(String.Format("<b>{0,7:F2}</b> data, <b>{1,7:F2}</b> funds", points, cost), Styles.styleEditorTextAligned); GUILayout.EndHorizontal(); } } } else { Log("Part is already being researched. Show button to stop"); if (GUILayout.Button("Stop Research", GUILayout.Width(200))) { tfRnDScenario.RemoveResearch(partName); } } } } if (DrawToggle(ref tfScenario.userSettings.editorWindowLocked, "Lock Window", Styles.styleToggle)) { if (tfScenario.userSettings.editorWindowLocked) { CalculateWindowBounds(); tfScenario.userSettings.editorWindowPosition = WindowRect; DragEnabled = false; } else { DragEnabled = true; } tfScenario.userSettings.Save(); } GUILayout.EndVertical(); }
internal override void Update() { if (!isReady) { return; } if (masterStatus == null) { masterStatus = new Dictionary <Guid, MasterStatusItem>(); } currentUTC = Planetarium.GetUniversalTime(); // ensure out vessel list is up to date CacheVessels(); if (currentUTC >= lastMasterStatusUpdate + tfScenario.userSettings.masterStatusUpdateFrequency) { lastMasterStatusUpdate = currentUTC; VerifyMasterStatus(); } // process vessels foreach (var entry in knownVessels) { Vessel vessel = FlightGlobals.Vessels.Find(v => v.id == entry.Key); if (vessel.loaded) { foreach (Part part in vessel.parts) { // Each KSP part can be composed of N virtual parts List <string> cores = TestFlightInterface.GetActiveCores(part); if (cores == null || cores.Count <= 0) { continue; } foreach (string activeCore in cores) { ITestFlightCore core = TestFlightUtil.GetCore(part, activeCore); if (core != null) { // Poll for flight data and part status if (currentUTC >= lastDataPoll + tfScenario.userSettings.masterStatusUpdateFrequency) { // Old data structure deprecated v1.3 PartStatus partStatus = new PartStatus(); partStatus.lastSeen = currentUTC; partStatus.flightCore = core; partStatus.partName = core.Title; partStatus.partID = part.flightID; partStatus.partStatus = core.GetPartStatus(); // get any failures partStatus.failures = core.GetActiveFailures(); partStatus.flightData = core.GetFlightData(); double failureRate = core.GetBaseFailureRate(); MomentaryFailureRate momentaryFailureRate = core.GetWorstMomentaryFailureRate(); if (momentaryFailureRate.valid && momentaryFailureRate.failureRate > failureRate) { failureRate = momentaryFailureRate.failureRate; } partStatus.momentaryFailureRate = failureRate; partStatus.acknowledged = false; partStatus.mtbfString = core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, 999); // Update or Add part status in Master Status if (masterStatus.ContainsKey(vessel.id)) { // Vessel is already in the Master Status, so check if part is in there as well int numItems = masterStatus[vessel.id].allPartsStatus.Count(p => p.partID == part.flightID); int existingPartIndex; if (numItems == 1) { existingPartIndex = masterStatus[vessel.id].allPartsStatus.FindIndex(p => p.partID == part.flightID); masterStatus[vessel.id].allPartsStatus[existingPartIndex] = partStatus; } else if (numItems == 0) { masterStatus[vessel.id].allPartsStatus.Add(partStatus); } else { existingPartIndex = masterStatus[vessel.id].allPartsStatus.FindIndex(p => p.partID == part.flightID); masterStatus[vessel.id].allPartsStatus[existingPartIndex] = partStatus; Log("[ERROR] TestFlightManager: Found " + numItems + " matching parts in Master Status Display!"); } } else { // Vessel is not in the Master Status so create a new entry for it and add this part MasterStatusItem masterStatusItem = new MasterStatusItem(); masterStatusItem.vesselID = vessel.id; masterStatusItem.vesselName = vessel.GetName(); masterStatusItem.allPartsStatus = new List <PartStatus>(); masterStatusItem.allPartsStatus.Add(partStatus); masterStatus.Add(vessel.id, masterStatusItem); } } } } } } if (currentUTC >= lastDataPoll + tfScenario.userSettings.minTimeBetweenDataPoll) { lastDataPoll = currentUTC; } if (currentUTC >= lastFailurePoll + tfScenario.userSettings.minTimeBetweenFailurePoll) { lastFailurePoll = currentUTC; } } }
// Methods for accessing the TestFlight modules on a given part // Get the active Core Modules that are bound to a given alias public static ITestFlightCore GetCore(Part part, string alias) { return(TestFlightUtil.GetCore(part, alias)); }
internal override void Update() { if (!isReady) { return; } if (!tfScenario.SettingsEnabled) { return; } if (masterStatus == null) { masterStatus = new Dictionary <Guid, MasterStatusItem>(); } currentUTC = Planetarium.GetUniversalTime(); // ensure out vessel list is up to date Profiler.BeginSample("CacheVessels"); CacheVessels(); Profiler.EndSample(); if (currentUTC >= lastMasterStatusUpdate + tfScenario.userSettings.masterStatusUpdateFrequency) { lastMasterStatusUpdate = currentUTC; Profiler.BeginSample("VerifyMasterStatus"); VerifyMasterStatus(); Profiler.EndSample(); } // process vessels Profiler.BeginSample("ProcessVessels"); knownVesselsEnumerator = knownVessels.GetEnumerator(); while (knownVesselsEnumerator.MoveNext()) { KeyValuePair <Guid, double> entry = knownVesselsEnumerator.Current; Vessel vessel = null; Profiler.BeginSample("FindVessel"); for (int i = 0; i < FlightGlobals.Vessels.Count; i++) { if (FlightGlobals.Vessels[i].id == entry.Key) { vessel = FlightGlobals.Vessels[i]; } } Profiler.EndSample(); if (vessel == null) { continue; } if (vessel.loaded) { Profiler.BeginSample("ProcessParts"); List <Part> parts = vessel.Parts; for (int j = 0; j < parts.Count; j++) { // Each KSP part can be composed of N virtual parts Profiler.BeginSample("Reset Core List"); cores.Clear(); Profiler.EndSample(); Profiler.BeginSample("Get Cores"); for (int k = 0; k < parts[j].Modules.Count; k++) { ITestFlightCore core = parts[j].Modules[k] as ITestFlightCore; if (core != null && core.TestFlightEnabled) { cores.Add(core.Alias); } } Profiler.EndSample(); //cores = TestFlightInterface.GetActiveCores(vessel.parts[j]); if (cores == null || cores.Count <= 0) { continue; } Profiler.BeginSample("ProcessCores"); for (int k = 0; k < cores.Count; k++) { ITestFlightCore core = TestFlightUtil.GetCore(vessel.parts[j], cores[k]); if (core == null) { continue; } // Poll for flight data and part status if (!(currentUTC >= lastDataPoll + tfScenario.userSettings.masterStatusUpdateFrequency)) { continue; } // Update or Add part status in Master Status if (masterStatus.ContainsKey(vessel.id)) { Profiler.BeginSample("MasterStatus Existing Vessel"); // Vessel is already in the Master Status, so check if part is in there as well int existingPartIndex = -1; Profiler.BeginSample("Find Part"); for (int msIndex = 0; msIndex < masterStatus[vessel.id].allPartsStatus.Count; msIndex++) { if (masterStatus[vessel.id].allPartsStatus[msIndex].partID != vessel.parts[j].flightID) { continue; } existingPartIndex = msIndex; break; } Profiler.EndSample(); if (existingPartIndex > -1) { Profiler.BeginSample("Existing Part"); //PartStatus partStatus = masterStatus[vessel.id].allPartsStatus[existingPartIndex]; PartStatus partStatus = new PartStatus(); partStatus.lastSeen = currentUTC; partStatus.flightCore = core; partStatus.partName = core.Title; partStatus.partID = vessel.parts[j].flightID; Profiler.BeginSample("Part - GetPartStatus"); partStatus.partStatus = core.GetPartStatus(); Profiler.EndSample(); // get any failures Profiler.BeginSample("Part - GetActiveFailures"); partStatus.failures = core.GetActiveFailures(); Profiler.EndSample(); Profiler.BeginSample("Part - GetFlightData"); partStatus.flightData = core.GetFlightData(); Profiler.EndSample(); Profiler.BeginSample("Part - GetBaseFailureRate"); double failureRate = core.GetBaseFailureRate(); Profiler.EndSample(); Profiler.BeginSample("Part - GetWorstMomentaryFailureRate"); MomentaryFailureRate momentaryFailureRate = core.GetWorstMomentaryFailureRate(); if (momentaryFailureRate.valid && momentaryFailureRate.failureRate > failureRate) { failureRate = momentaryFailureRate.failureRate; } Profiler.EndSample(); partStatus.momentaryFailureRate = failureRate; partStatus.acknowledged = false; Profiler.BeginSample("Part - FailureRateToMTBFString"); core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, false, 999, out partStatus.mtbfString); //partStatus.mtbfString = core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, 999); Profiler.EndSample(); masterStatus[vessel.id].allPartsStatus[existingPartIndex] = partStatus; Profiler.EndSample(); } else { Profiler.BeginSample("New Part"); PartStatus partStatus = new PartStatus(); partStatus.lastSeen = currentUTC; partStatus.flightCore = core; partStatus.partName = core.Title; partStatus.partID = vessel.parts[j].flightID; partStatus.partStatus = core.GetPartStatus(); // get any failures partStatus.failures = core.GetActiveFailures(); partStatus.flightData = core.GetFlightData(); double failureRate = core.GetBaseFailureRate(); MomentaryFailureRate momentaryFailureRate = core.GetWorstMomentaryFailureRate(); if (momentaryFailureRate.valid && momentaryFailureRate.failureRate > failureRate) { failureRate = momentaryFailureRate.failureRate; } partStatus.momentaryFailureRate = failureRate; partStatus.acknowledged = false; core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, false, 999, out partStatus.mtbfString); masterStatus[vessel.id].allPartsStatus.Add(partStatus); Profiler.EndSample(); } Profiler.EndSample(); } else { Profiler.BeginSample("MasterStatus New Vessel"); // Vessel is not in the Master Status so create a new entry for it and add this part PartStatus partStatus = new PartStatus(); partStatus.lastSeen = currentUTC; partStatus.flightCore = core; partStatus.partName = core.Title; partStatus.partID = vessel.parts[j].flightID; partStatus.partStatus = core.GetPartStatus(); // get any failures partStatus.failures = core.GetActiveFailures(); partStatus.flightData = core.GetFlightData(); double failureRate = core.GetBaseFailureRate(); MomentaryFailureRate momentaryFailureRate = core.GetWorstMomentaryFailureRate(); if (momentaryFailureRate.valid && momentaryFailureRate.failureRate > failureRate) { failureRate = momentaryFailureRate.failureRate; } partStatus.momentaryFailureRate = failureRate; partStatus.acknowledged = false; partStatus.mtbfString = core.FailureRateToMTBFString(failureRate, TestFlightUtil.MTBFUnits.SECONDS, 999); MasterStatusItem masterStatusItem = new MasterStatusItem(); masterStatusItem.vesselID = vessel.id; masterStatusItem.vesselName = vessel.GetName(); masterStatusItem.allPartsStatus = new List <PartStatus>(); masterStatusItem.allPartsStatus.Add(partStatus); masterStatus.Add(vessel.id, masterStatusItem); Profiler.EndSample(); } } Profiler.EndSample(); } } Profiler.EndSample(); if (currentUTC >= lastDataPoll + tfScenario.userSettings.minTimeBetweenDataPoll) { lastDataPoll = currentUTC; } if (currentUTC >= lastFailurePoll + tfScenario.userSettings.minTimeBetweenFailurePoll) { lastFailurePoll = currentUTC; } } Profiler.EndSample(); }
// Methods for accessing the TestFlight modules on a given part // Get the active Core Module - can only ever be one. public static ITestFlightCore GetCore(Part part) { return(TestFlightUtil.GetCore(part)); }