/// <summary> /// Manages the true condition which enables the "Fill EVA" button. /// </summary> /// <returns></returns> private bool EnableFillButton() { var info = EVALifeSupportTracker.GetEVALSInfo(kerbal.name); return(info.ls_current < info.ls_max && !FlightGlobals.ActiveVessel.isEVA && fillButtonEnable); }
private static void FillEVAResource(string kerbalName) { // This works right now because the tracker updates live. // May break in the future. var info = EVALifeSupportTracker.GetEVALSInfo(kerbalName); double eva_request = info.ls_max - info.ls_current; Cons2LSModule module = FlightGlobals.ActiveVessel.FindPartModuleImplementing <Cons2LSModule>(); double obtained = module.part.RequestResource(C.NAME_CONSUMABLES, C.CONS_PER_EVA_LS * eva_request); double add = obtained / C.CONS_PER_EVA_LS; EVALifeSupportTracker.AddEVAAmount(kerbalName, add, EVA_Resource.LifeSupport); Util.Log(" EVA Request = " + eva_request); Util.Log(" Amt Obtained = " + obtained); }
public void FixedUpdate() { // If part is unmanned, nothing to do if (part.protoModuleCrew.Count == 0) { showed_eva_warning = false; return; } // If vessel is below this altitude in an atmosphere with oxygen, // LifeSupport is irrelevant if (Util.BreathableAir(vessel)) { return; } int crew_count = part.protoModuleCrew.Count; // How much lifesupport to request double ls_request = crew_count * C.LS_DRAIN_PER_SEC * TimeWarp.fixedDeltaTime; // Request resource based on rates defined by constants double ret_rs = part.RequestResource(C.NAME_LIFESUPPORT, ls_request, C.FLOWMODE_LIFESUPPORT); // If LifeSupport exists or is restored, reset EVA warning and return if (ret_rs > 0.0) { showed_eva_warning = false; return; } // Otherwise, begin deducting EVA LifeSupport if (!showed_eva_warning) { TimeWarp.SetRate(0, true); string vessel_name = vessel.isActiveVessel ? part.partInfo.title : vessel.vesselName; showed_eva_warning = true; Util.PostUpperMessage("Crew in " + vessel_name + " has run out of " + C.NAME_LIFESUPPORT + ",\n is consuming " + C.NAME_EVA_LIFESUPPORT, 1); } // Modify crew list in place int i = 0; while (i < part.protoModuleCrew.Count) { ProtoCrewMember kerbal = part.protoModuleCrew[i]; double request = C.EVA_LS_DRAIN_PER_SEC * TimeWarp.fixedDeltaTime; double current_eva = EVALifeSupportTracker.AddEVAAmount(kerbal.name, -request, EVA_Resource.LifeSupport); if (current_eva + request > C.EVA_LS_30_SECONDS && current_eva <= C.EVA_LS_30_SECONDS) { TimeWarp.SetRate(0, true); Util.PostUpperMessage(kerbal.name + " has 30 seconds to live!", 1); // Set to 30 seconds in case of large timewarp. EVALifeSupportTracker.SetCurrentAmount(kerbal.name, C.EVA_LS_30_SECONDS, EVA_Resource.LifeSupport); } if (EVALifeSupportTracker.GetEVALSInfo(kerbal.name).ls_current < C.DOUBLE_MARGIN) { Util.KillKerbal(this, kerbal); continue; } i++; } }
private void UpdateGUI() { drewgui = true; Vessel vessel = FlightGlobals.ActiveVessel; int crewCount = vessel.GetCrewCount(); var parts = vessel.FindPartModulesImplementing <LifeSupportReportable>(); // Update live Kerbal numbers foreach (LifeSupportReportable module in parts) { bool empty; string timestr = module.ReportLifeSupport(out empty); if (emptyPartLabels.ContainsKey(module.part)) { emptyPartLabels[module.part].SetOptionText($"{ORANGE}{timestr}</color>"); continue; } foreach (ProtoCrewMember kerbal in module.part.protoModuleCrew) { double evaLS = EVALifeSupportTracker.GetEVALSInfo(kerbal.name).ls_current; if (compress) { if (!vessel.isEVA && !empty) { labelMap[kerbal.name].nameLabel.SetOptionText(labelMap[kerbal.name].compressNames[0]); labelMap[kerbal.name].shipLS.SetOptionText(timestr); } else { labelMap[kerbal.name].nameLabel.SetOptionText(labelMap[kerbal.name].compressNames[1]); string evastr = Util.DaysToString(evaLS / C.EVA_LS_DRAIN_PER_DAY); labelMap[kerbal.name].shipLS.SetOptionText(evastr); } } else { string evastr = Util.DaysToString(evaLS / C.EVA_LS_DRAIN_PER_DAY); labelMap[kerbal.name].shipLS.SetOptionText(timestr); labelMap[kerbal.name].evaLS.SetOptionText(evastr); } if (Config.DEBUG_SHOW_EVA) { var info = EVALifeSupportTracker.GetEVALSInfo(kerbal.name); labelMap[kerbal.name].evaLS_Value.SetOptionText(info.ls_current.ToString()); labelMap[kerbal.name].evaProp.SetOptionText(info.prop_current.ToString()); } } } // Any Kerbals not found above are assumed KIA // Would be great to move this to a GameEvent // such as GameEvents.onKerbalRemoved() if (crewCount < labelMap.Count) { List <string> fullcrew = vessel.GetVesselCrew().ConvertAll(a => a.name); foreach (string name in labelMap.Keys.ToArray()) { if (!fullcrew.Contains(name)) { labelMap[name].shipLS.SetOptionText("KIA"); labelMap[name].evaLS.SetOptionText("KIA"); labelMap.Remove(name); } } } // Update status double curr, max; vessel.GetConnectedResourceTotals(lsID, out curr, out max); string statusOne; // Status (no crew/breathable/active) string statusTwo; // Remaining Consumables/EVA Life Support string lsActive; if (crewCount == 0) { lsActive = "No crew"; } else if (Util.BreathableAir(vessel)) { lsActive = "Breathable air"; } else { lsActive = "ACTIVE"; } statusOne = $"{(compress ? "" : "Status: ")}{lsActive}"; if (FlightGlobals.ActiveVessel.isEVA) { vessel.GetConnectedResourceTotals(evapropID, out curr, out max); string prefix = ""; string suffix = "</color>"; if (curr < 0.5) { prefix = C.GUI_HARDWARN_COLOR; } else if (curr < 1.0) { prefix = C.GUI_LITEWARN_COLOR; } else { suffix = ""; } statusTwo = $"Propellant: {prefix}{string.Format("{0:0.00}", curr)}{suffix}"; } else { vessel.GetConnectedResourceTotals(consID, out curr, out max); double consDays = curr / C.CONS_PER_LS; statusTwo = $"{(compress ? "" : "Consumables: ")}{Util.DaysToString(consDays)}"; } statusLabel.SetOptionText($"{statusOne}\n{statusTwo}"); }
public override void OnStart(StartState state) { Util.Log("EVALifeSupportModule OnStart()"); // Check if EVA Kerbal has exactly one ProtoCrewMember if (part.protoModuleCrew.Count == 0) { string msg = "0 PMCs found in EVA Kerbal: " + part.name; Util.Log(msg); throw new IndexOutOfRangeException(msg); } else if (part.protoModuleCrew.Count > 1) { Util.Log("Weird...multiple PMCs found in EVA Kerbal: " + part.name); } // To avoid conflicts with Unity variable "name" string kerbal_name = part.protoModuleCrew[0].name; PartResource ls_resource = null; foreach (PartResource pr in part.Resources) { if (pr.resourceName == C.NAME_EVA_LIFESUPPORT) { ls_resource = pr; break; } } // Kerbals assigned after this mod's installation should already be tracked, // but for Kerbals already in flight, add EVA LS according to current state // of astronaut complex EVALifeSupportTracker.AddKerbalToTracking(kerbal_name); if (ls_resource == null) { // If not found, add EVA LS resource to this PartModule. Util.Log("Adding " + C.NAME_EVA_LIFESUPPORT + " resource to " + part.name); var info = EVALifeSupportTracker.GetEVALSInfo(kerbal_name); ConfigNode resource_node = new ConfigNode("RESOURCE"); resource_node.AddValue("name", C.NAME_EVA_LIFESUPPORT); resource_node.AddValue("amount", info.ls_current.ToString()); resource_node.AddValue("maxAmount", info.ls_max.ToString()); ls_resource = part.AddResource(resource_node); Util.Log("Added EVA LS resource to " + part.name); } else { // If found, this EVA is already active - deduct LS. Util.StartupRequest(this, C.NAME_EVA_LIFESUPPORT, C.EVA_LS_DRAIN_PER_SEC); if (ls_resource.amount < C.KILL_BUFFER) { ls_resource.amount = C.KILL_BUFFER; } else if (ls_resource.amount < C.EVA_LS_30_SECONDS) { Util.PostUpperMessage(kerbal_name + " has " + (int)(ls_resource.amount / C.EVA_LS_DRAIN_PER_SEC) + " seconds to live!", 1); } } PartResource prop_resource = part.Resources[C.NAME_EVA_PROPELLANT]; // Necessary to override game's default behavior, which refills // EVA Propellant automatically every time EVA Kerbal is reset var eva_info = EVALifeSupportTracker.GetEVALSInfo(kerbal_name); prop_resource.maxAmount = eva_info.prop_max; prop_resource.amount = eva_info.prop_current; // Will this add safety Propellant on every load? // Should only be added when Kerbal first leaves ship // // Confirmed (1.0.5). At the time of this comment, the Propellant // threshold is brutally low (0.1), so it's okay, // but this should be changed in the future. if (prop_resource.amount < C.EVA_PROP_SAFE_MIN) { prop_resource.amount = C.EVA_PROP_SAFE_MIN; } // If difficulty option "Immediate Level Up" is selected, // immediately set this Kerbal's EVA to new max if (this.vessel.CanUpdateEVAStat(Config.EVA_MAX_UPDATE)) { ls_resource.maxAmount = Util.MaxAllowedEVA(EVA_Resource.LifeSupport); prop_resource.maxAmount = Util.MaxAllowedEVA(EVA_Resource.Propellant); } base.OnStart(state); }