diff --git a/FOR_RELEASE/GameData/UmbraSpaceIndustries/LifeSupport/Settings.cfg b/FOR_RELEASE/GameData/UmbraSpaceIndustries/LifeSupport/Settings.cfg index 2d4c8f1..6652875 100644 --- a/FOR_RELEASE/GameData/UmbraSpaceIndustries/LifeSupport/Settings.cfg +++ b/FOR_RELEASE/GameData/UmbraSpaceIndustries/LifeSupport/Settings.cfg @@ -20,6 +20,7 @@ LIFE_SUPPORT_SETTINGS BaseHabTime = 0.25 //How long can 1 crew capacity support 1 Kerbal, expressed in Kerbal Months ReplacementPartAmount = 0 //How fast life support equipment and habs 'wears out' HabRange = 150 //How close we need to be to use other vessel's habitation modules and recyclers. + RecoverySpeed = 1 //Rate at which Kerbals recover cabin time while in a habitat (seconds per second) EnableRecyclers = true //Use resource recyclers? Not the same as resource converteres like greenhouses! VetNames = Jebediah,Valentina,Bill,Bob ScoutHabTime = 9180000 diff --git a/Source/USILifeSupport/Converters/USILS_HabitationSwapOption.cs b/Source/USILifeSupport/Converters/USILS_HabitationSwapOption.cs index 9f5e21e..ebbe543 100644 --- a/Source/USILifeSupport/Converters/USILS_HabitationSwapOption.cs +++ b/Source/USILifeSupport/Converters/USILS_HabitationSwapOption.cs @@ -33,7 +33,7 @@ public override string GetInfo() var output = new StringBuilder(); output.AppendLine(); output.AppendLine(base.GetInfo()); - output.AppendLine(string.Format("Kerbal-Months: {0}", BaseKerbalMonths + part.CrewCapacity)); + output.AppendLine(string.Format("Kerbal-Months: {0}", BaseKerbalMonths)); output.AppendLine(string.Format("Crew Affected: {0}", CrewCapacity)); output.AppendLine(string.Format("Hab Multipler: {0}", BaseHabMultiplier)); diff --git a/Source/USILifeSupport/Converters/USILS_LifeSupportExtenderConverterAddon.cs b/Source/USILifeSupport/Converters/USILS_LifeSupportExtenderConverterAddon.cs index b4f3be8..8537e0f 100644 --- a/Source/USILifeSupport/Converters/USILS_LifeSupportExtenderConverterAddon.cs +++ b/Source/USILifeSupport/Converters/USILS_LifeSupportExtenderConverterAddon.cs @@ -61,10 +61,11 @@ public override void PostProcess(ConverterResults result, double deltaTime) { var k = kerbals[i]; var lsKerbal = LifeSupportManager.Instance.FetchKerbal(k); - if (AffectsHomeTimer) - lsKerbal.MaxOffKerbinTime += timePerKerbal; - if (AffectsHabTimer) - lsKerbal.TimeEnteredVessel += timePerKerbal; + + // Experimental patch. + // I don't like changing LastAtHome but the alternative is that we add another variable... + if (AffectsHomeTimer || AffectsHabTimer) + lsKerbal.LastAtHome += timePerKerbal; LifeSupportManager.Instance.TrackKerbal(lsKerbal); } diff --git a/Source/USILifeSupport/LifeSupportConfig.cs b/Source/USILifeSupport/LifeSupportConfig.cs index f40ed4d..d7b6590 100644 --- a/Source/USILifeSupport/LifeSupportConfig.cs +++ b/Source/USILifeSupport/LifeSupportConfig.cs @@ -23,6 +23,7 @@ public class LifeSupportConfig public double BaseHabTime { get; set; } public bool EnableRecyclers { get; set; } public double HabRange { get; set; } + public float RecoverySpeed { get; set; } public double ScoutHabTime { get; set; } public double PermaHabTime { get; set; } } diff --git a/Source/USILifeSupport/LifeSupportManager.cs b/Source/USILifeSupport/LifeSupportManager.cs index 6f62fae..90f7bcc 100644 --- a/Source/USILifeSupport/LifeSupportManager.cs +++ b/Source/USILifeSupport/LifeSupportManager.cs @@ -112,10 +112,10 @@ public LifeSupportStatus FetchKerbal(ProtoCrewMember crew) k.LastEC = Planetarium.GetUniversalTime(); k.LastAtHome = Planetarium.GetUniversalTime(); k.LastSOIChange = Planetarium.GetUniversalTime(); - k.MaxOffKerbinTime = Planetarium.GetUniversalTime() + 648000; - k.TimeEnteredVessel = Planetarium.GetUniversalTime(); k.CurrentVesselId = "?UNKNOWN?"; k.PreviousVesselId = "??UNKNOWN??"; + k.RemainingCabinTime = LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime + * LifeSupportUtilities.SecondsPerMonth(); k.LastUpdate = Planetarium.GetUniversalTime(); k.IsGrouchy = false; k.OldTrait = crew.experienceTrait.Config.Name; @@ -391,7 +391,6 @@ internal static double GetHabChecksum(VesselSupplyStatus sourceVessel, Vessel vs double totHabSpace = sourceVessel.ExtraHabSpace; double totHabMult = CalculateVesselHabMultiplier(vsl, 1); - totHabSpace += (LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime * totMaxCrew); var hCount = hList.Count; for (int i = 0; i < hCount; ++i) @@ -439,7 +438,6 @@ internal static double GetTotalHabTime(VesselSupplyStatus sourceVessel, Vessel v } double totHabSpace = sourceVessel.ExtraHabSpace; double totHabMult = CalculateVesselHabMultiplier(vessel,totCurCrew); - totHabSpace += (LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime * totMaxCrew); var hCount = hList.Count; for (int i = 0; i < hCount; ++i) diff --git a/Source/USILifeSupport/LifeSupportMonitor.cs b/Source/USILifeSupport/LifeSupportMonitor.cs index 067b082..ab1c0fe 100644 --- a/Source/USILifeSupport/LifeSupportMonitor.cs +++ b/Source/USILifeSupport/LifeSupportMonitor.cs @@ -109,16 +109,37 @@ private LifeSupportVesselDisplayStat GetEvaKerbalStats(Vessel kerbal) vstat.LastUpdate = kerbal.missionTime; var sitString = "(EVA)"; + var evaKerbal = kerbal.GetVesselCrew()[0]; + var kerbalStatus = LifeSupportManager.Instance.FetchKerbal(evaKerbal); + var cabinTime = kerbalStatus.RemainingCabinTime; + var cabinTimeString = LifeSupportUtilities.SmartDurationDisplay(Math.Max(0, cabinTime)); + var remEVATime = LifeSupportScenario.Instance.settings.GetSettings().EVATime - kerbal.missionTime; var timeString = LifeSupportUtilities.SmartDurationDisplay(Math.Max(0, remEVATime)); + var secondsPerDay = LifeSupportUtilities.SecondsPerDay(); + + + var lblCabin = "6FFF00"; + if (cabinTime < secondsPerDay * 3) + { + lblCabin = "FFE100"; + } + if (cabinTime < secondsPerDay * 1) + { + lblCabin = "FFAE00"; + } + if (remEVATime > 0) { vstat.SummaryLabel = String.Format( - "{0}/{1} - {2} time remaining" + "{0}/{1} - {2} time remaining - " + + "{4} cabin time" , kerbal.mainBody.bodyName , sitString - , timeString.Substring(timeString.IndexOf(':') + 1)); + , timeString + , lblCabin + , cabinTimeString); } else { @@ -190,9 +211,12 @@ private LifeSupportVesselDisplayStat GetVesselStats(VesselSupplyStatus vsl) LifeSupportScenario.Instance.settings.GetSettings().HabRange); } + var numCrew = vsl.NumCrew; + var crewCap = vsl.CrewCap; + var vesselHabMultiplier = vsl.VesselHabMultiplier; foreach (var c in thisVessel.GetVesselCrew()) { - var crewStat = GetCrewStat(c, thisVessel, suppliesTimeLeft, ecTimeLeft, ecAmount, habTime); + var crewStat = GetCrewStat(c, thisVessel, suppliesTimeLeft, ecTimeLeft, ecAmount, habTime, numCrew, crewCap, vesselHabMultiplier); vstat.crew.Add(crewStat); } vstat.crew = vstat.crew.OrderBy(crewStat => crewStat.EarliestExpiration).ToList(); @@ -284,8 +308,8 @@ private void DisplayCrewStats(LifeSupportCrewDisplayStat c) GUILayout.Label(c.ECLabel, _labelStyle, GUILayout.Width(145)); GUILayout.Label("hab:", _labelStyle, GUILayout.Width(40)); GUILayout.Label(c.HabLabel, _labelStyle, GUILayout.Width(145)); - GUILayout.Label("home:", _labelStyle, GUILayout.Width(40)); - GUILayout.Label(c.HomeLabel, _labelStyle, GUILayout.Width(145)); + GUILayout.Label("cabin:", _labelStyle, GUILayout.Width(40)); + GUILayout.Label(c.CabinLabel, _labelStyle, GUILayout.Width(145)); GUILayout.EndHorizontal(); } @@ -320,7 +344,7 @@ private string GetSituationString(Vessel vessel) return sitString; } - private LifeSupportCrewDisplayStat GetCrewStat(ProtoCrewMember c, Vessel vessel, double vesselSuppliesTimeLeft, double vesselEcTimeLeft, double vesselEcAmount, double vesselHabTime) + private LifeSupportCrewDisplayStat GetCrewStat(ProtoCrewMember c, Vessel vessel, double vesselSuppliesTimeLeft, double vesselEcTimeLeft, double vesselEcAmount, double vesselHabTime, int numCrew, int crewCap, double vesselHabMultiplier) { var cls = LifeSupportManager.Instance.FetchKerbal(c); //Guard clause in case we just changed vessels @@ -329,7 +353,6 @@ private LifeSupportCrewDisplayStat GetCrewStat(ProtoCrewMember c, Vessel vessel, { cls.PreviousVesselId = cls.CurrentVesselId; cls.CurrentVesselId = vessel.id.ToString(); - cls.TimeEnteredVessel = Planetarium.GetUniversalTime(); LifeSupportManager.Instance.TrackKerbal(cls); } @@ -345,7 +368,7 @@ private LifeSupportCrewDisplayStat GetCrewStat(ProtoCrewMember c, Vessel vessel, cStat.ComputeEc(ecTimeLeft, c); cStat.ComputeSupply(vesselSuppliesTimeLeft, c); cStat.ComputeHab(vesselHabTime, c, cls); - cStat.ComputeHome(c, cls); + cStat.ComputeCabin(c, cls, numCrew, crewCap, vesselHabMultiplier); LifeSupportManager.Instance.TrackKerbal(cls); return cStat; @@ -399,7 +422,7 @@ public class LifeSupportCrewDisplayStat public string ECLabel { get; set; } public string SupplyLabel { get; set; } public string HabLabel { get; set; } - public string HomeLabel { get; set; } + public string CabinLabel { get; set; } public double EarliestExpiration { get; set; } public LifeSupportCrewDisplayStat() @@ -424,7 +447,7 @@ internal void ComputeHab(double vesselHabTime, ProtoCrewMember c, LifeSupportSta if (useHabPenalties) { UpdateEarliestExpiration(vesselHabTime); - var habTimeLeft = vesselHabTime - (Planetarium.GetUniversalTime() - cls.TimeEnteredVessel); + var habTimeLeft = vesselHabTime - (Planetarium.GetUniversalTime() - cls.LastAtHome); var isScout = c.HasEffect("ExplorerSkill") && habTimeLeft >= LifeSupportScenario.Instance.settings.GetSettings().ScoutHabTime; var isPermaHab = habTimeLeft >= LifeSupportScenario.Instance.settings.GetSettings().PermaHabTime; @@ -454,43 +477,46 @@ internal void ComputeHab(double vesselHabTime, ProtoCrewMember c, LifeSupportSta HabLabel = String.Format("{1}", lblHab, crewHabString); } - internal void ComputeHome(ProtoCrewMember c, LifeSupportStatus cls) + internal void ComputeCabin(ProtoCrewMember c, LifeSupportStatus cls, int numCrew, int crewCap, double vesselHabMultiplier) { - var crewHomeString = "indefinite"; - var lblHome = "6FFF00"; + var crewCabinString = "indefinite"; + var lblCabin = "6FFF00"; var useHabPenalties = LifeSupportManager.GetNoHomeEffect(c.name) > 0; if (useHabPenalties) { - var homeTimeLeft = cls.MaxOffKerbinTime - Planetarium.GetUniversalTime(); - UpdateEarliestExpiration(homeTimeLeft); + var adjustedCabinTimeLeft = cls.RemainingCabinTime * ((double)crewCap / (double)numCrew) * (1 + vesselHabMultiplier); + UpdateEarliestExpiration(adjustedCabinTimeLeft); - var isScout = c.HasEffect("ExplorerSkill") && homeTimeLeft >= LifeSupportScenario.Instance.settings.GetSettings().ScoutHabTime; - var isPermaHab = homeTimeLeft >= LifeSupportScenario.Instance.settings.GetSettings().PermaHabTime; + // Debug.Log(String.Format("{0} has {1} remaining CabinTime", cls.KerbalName, cabinTimeLeft )); + + var isScout = c.HasEffect("ExplorerSkill") && adjustedCabinTimeLeft >= LifeSupportScenario.Instance.settings.GetSettings().ScoutHabTime; + var isPermaHab = adjustedCabinTimeLeft >= LifeSupportScenario.Instance.settings.GetSettings().PermaHabTime; if (isScout || isPermaHab) { - crewHomeString = "indefinite"; + crewCabinString = "indefinite"; } - else if (homeTimeLeft < 0) + else if (adjustedCabinTimeLeft < 0) { - lblHome = "FF5E5E"; - crewHomeString = "expired"; + lblCabin = "FF5E5E"; + crewCabinString = "expired"; } else { - crewHomeString = LifeSupportUtilities.SmartDurationDisplay(homeTimeLeft); + + crewCabinString = LifeSupportUtilities.SmartDurationDisplay(adjustedCabinTimeLeft); var secondsPerDay = LifeSupportUtilities.SecondsPerDay(); - if (homeTimeLeft < secondsPerDay * 30) //15 days + if (adjustedCabinTimeLeft < secondsPerDay * 3) { - lblHome = "FFE100"; + lblCabin = "FFE100"; } - if (homeTimeLeft < secondsPerDay * 15) + if (adjustedCabinTimeLeft < secondsPerDay * 1) { - lblHome = "FFAE00"; + lblCabin = "FFAE00"; } } } - HomeLabel = String.Format("{1}", lblHome, crewHomeString); + CabinLabel = String.Format("{1}", lblCabin, crewCabinString); } private string GetRemainingTimeWithGraceLabel(double timeLeft, double graceTime, string graceTimeDisplay, string inGraceTimeMessage, int effectWhenExpires) diff --git a/Source/USILifeSupport/LifeSupportMonitor_Editor.cs b/Source/USILifeSupport/LifeSupportMonitor_Editor.cs index 2069853..a8c8350 100644 --- a/Source/USILifeSupport/LifeSupportMonitor_Editor.cs +++ b/Source/USILifeSupport/LifeSupportMonitor_Editor.cs @@ -127,6 +127,8 @@ private void ResetValues() private string hab_maxCrew = ""; private string supply_curCrew = ""; private string supply_maxCrew = ""; + private string cabin_curCrew = ""; + private string cabin_maxCrew = ""; private string habExt_curCrew = ""; private string habExt_maxCrew = ""; @@ -203,7 +205,7 @@ private void UpdateGUIInfo(ShipConstruct ship) } } - totalHabSpace = (LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime * maxCrew) + extraHabTime; + totalHabSpace = extraHabTime; //A Kerbal month is 30 six-hour Kerbin days. totalHabMult = habMult * LifeSupportScenario.Instance.settings.GetSettings().HabMultiplier * LifeSupportUtilities.SecondsPerMonth(); totalBatteryTime = batteryAmount / LifeSupportScenario.Instance.settings.GetSettings().ECAmount; @@ -247,6 +249,19 @@ private void UpdateGUIInfo(ShipConstruct ship) hab_curCrew = LifeSupportUtilities.DurationDisplay(totalHabSpace / Math.Max(1, curCrew) * totalHabMult); hab_maxCrew = LifeSupportUtilities.DurationDisplay(totalHabSpace / Math.Max(1, maxCrew) * totalHabMult); + cabin_curCrew = LifeSupportUtilities.DurationDisplay( + LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime * + LifeSupportUtilities.SecondsPerMonth() * + ((double)maxCrew / (double)Math.Max(1, curCrew)) * + habMult + ); + cabin_maxCrew = LifeSupportUtilities.DurationDisplay( + LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime * + LifeSupportUtilities.SecondsPerMonth() * + ((double)maxCrew / (double)Math.Max(1, maxCrew)) * + habMult + ); + supplyExt_curCrew = LifeSupportUtilities.DurationDisplay( (totalSupplyTime + totalFertilizerTime) / Math.Max(1, curCrew) / @@ -364,42 +379,39 @@ private void GenerateWindow() { // column widths const int c1 = 150; - const int c2 = 80; + const int c2 = 90; const int c3 = 80; - const int c4 = 90; - const int c5 = 80; - const int c6 = 50; - const int c7 = 50; + const int c4 = 50; + const int c5 = 50; + const int c6 = 120; GUILayout.BeginHorizontal(); GUILayout.Label("Habitation", _labelStyle, GUILayout.Width(c1 - 30)); - GUILayout.Label(CTag("= ( (", operColor), _labelStyle, GUILayout.Width(30)); - GUILayout.Label("BaseTime " + CTag("*", operColor), _labelStyle, GUILayout.Width(c2)); - GUILayout.Label("MaxCrew " + CTag(") +", operColor), _labelStyle, GUILayout.Width(c3)); - GUILayout.Label("ExtraTime " + CTag(") *", operColor), _labelStyle, GUILayout.Width(c4)); - GUILayout.Label("Multiplier " + CTag("/", operColor), _labelStyle, GUILayout.Width(c5)); - GUILayout.Label("Crew " + CTag("*", operColor), _labelStyle, GUILayout.Width(c6)); - GUILayout.Label("Months", _labelStyle, GUILayout.Width(c7)); + GUILayout.Label(CTag(" = ", operColor), _labelStyle, GUILayout.Width(30)); + GUILayout.Label("ExtraTime " + CTag("*", operColor), _labelStyle, GUILayout.Width(c2)); + GUILayout.Label("Multiplier " + CTag("/", operColor), _labelStyle, GUILayout.Width(c3)); + GUILayout.Label("Crew " + CTag("*", operColor), _labelStyle, GUILayout.Width(c4)); + GUILayout.Label("Months", _labelStyle, GUILayout.Width(c5)); + GUILayout.Label("+CabinTime", _labelStyle, GUILayout.Width(c6)); + GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(CTag(hab_curCrew, textColor), _labelStyle, GUILayout.Width(c1)); - GUILayout.Label(CTag(LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime.ToString(), fadeColor), _labelStyle, GUILayout.Width(c2)); - GUILayout.Label(CTag(maxCrew.ToString(), crewColor), _labelStyle, GUILayout.Width(c3)); - GUILayout.Label(CTag(extraHabTime.ToString(), textColor), _labelStyle, GUILayout.Width(c4)); - GUILayout.Label(CTag("(1+" + (habMult-1d) +")", textColor), _labelStyle, GUILayout.Width(c5)); - GUILayout.Label(CTag(Math.Max(1, curCrew).ToString(), crewColor), _labelStyle, GUILayout.Width(c6)); - GUILayout.Label(CTag(LifeSupportScenario.Instance.settings.GetSettings().HabMultiplier.ToString(), fadeColor), _labelStyle, GUILayout.Width(c7)); + GUILayout.Label(CTag(extraHabTime.ToString(), textColor), _labelStyle, GUILayout.Width(c2)); + GUILayout.Label(CTag("(1+" + (habMult-1d) +")", textColor), _labelStyle, GUILayout.Width(c3)); + GUILayout.Label(CTag(Math.Max(1, curCrew).ToString(), crewColor), _labelStyle, GUILayout.Width(c4)); + GUILayout.Label(CTag(LifeSupportScenario.Instance.settings.GetSettings().HabMultiplier.ToString(), fadeColor), _labelStyle, GUILayout.Width(c5)); + GUILayout.Label(CTag(cabin_curCrew, textColor), _labelStyle, GUILayout.Width(c6)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(CTag(hab_maxCrew, textColor), _labelStyle, GUILayout.Width(c1)); - GUILayout.Label(CTag(LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime.ToString(), fadeColor), _labelStyle, GUILayout.Width(c2)); - GUILayout.Label(CTag(maxCrew.ToString(), crewColor), _labelStyle, GUILayout.Width(c3)); - GUILayout.Label(CTag(extraHabTime.ToString(), textColor), _labelStyle, GUILayout.Width(c4)); - GUILayout.Label(CTag("(1+" + (habMult - 1d) + ")", textColor), _labelStyle, GUILayout.Width(c5)); - GUILayout.Label(CTag(Math.Max(1, maxCrew).ToString(), crewColor), _labelStyle, GUILayout.Width(c6)); - GUILayout.Label(CTag(LifeSupportScenario.Instance.settings.GetSettings().HabMultiplier.ToString(), fadeColor), _labelStyle, GUILayout.Width(c7)); + GUILayout.Label(CTag(extraHabTime.ToString(), textColor), _labelStyle, GUILayout.Width(c2)); + GUILayout.Label(CTag("(1+" + (habMult - 1d) + ")", textColor), _labelStyle, GUILayout.Width(c3)); + GUILayout.Label(CTag(Math.Max(1, maxCrew).ToString(), crewColor), _labelStyle, GUILayout.Width(c4)); + GUILayout.Label(CTag(LifeSupportScenario.Instance.settings.GetSettings().HabMultiplier.ToString(), fadeColor), _labelStyle, GUILayout.Width(c5)); + GUILayout.Label(CTag(cabin_maxCrew, textColor), _labelStyle, GUILayout.Width(c6)); GUILayout.EndHorizontal(); } diff --git a/Source/USILifeSupport/LifeSupportMonitor_SpaceCenter.cs b/Source/USILifeSupport/LifeSupportMonitor_SpaceCenter.cs index 2b323de..085e072 100644 --- a/Source/USILifeSupport/LifeSupportMonitor_SpaceCenter.cs +++ b/Source/USILifeSupport/LifeSupportMonitor_SpaceCenter.cs @@ -11,7 +11,7 @@ namespace LifeSupport public class LifeSupportMonitor_SpaceCenter : MonoBehaviour { private ApplicationLauncherButton orbLogButton; - private Rect _windowPosition = new Rect(300, 60, 500, 550); + private Rect _windowPosition = new Rect(300, 60, 500, 560); private GUIStyle _windowStyle; private GUIStyle _labelStyle; private GUIStyle _smButtonStyle; @@ -62,6 +62,7 @@ private void GuiOn() habRange = config.HabRange.ToString(); homeAltitude = config.HomeWorldAltitude.ToString(); baseHabTime = config.BaseHabTime.ToString(); + recoverySpeed = config.RecoverySpeed.ToString(); vetNames = config.VetNames; } @@ -123,6 +124,7 @@ private void OnWindow(int windowId) private string habRange; private string homeAltitude; private string baseHabTime; + private string recoverySpeed; private string vetNames; private void GenerateWindow() @@ -220,13 +222,18 @@ private void GenerateWindow() GUILayout.Label("Hab Multiplier:", _labelStyle, GUILayout.Width(c1)); habMulti = GUILayout.TextField(habMulti, 3, GUILayout.Width(c4)); GUILayout.Label("", _labelStyle, GUILayout.Width(c6)); - GUILayout.Label("Hab Months:", _labelStyle, GUILayout.Width(80)); + GUILayout.Label("Cabin Months:", _labelStyle, GUILayout.Width(90)); baseHabTime = GUILayout.TextField(baseHabTime, 10, GUILayout.Width(c4)); GUILayout.Label("", _labelStyle, GUILayout.Width(c6)); GUILayout.Label("Hab Range:", _labelStyle, GUILayout.Width(c7)); habRange = GUILayout.TextField(habRange, 4, GUILayout.Width(c4)); GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Label("Recovery Speed:", _labelStyle, GUILayout.Width(c1)); + recoverySpeed = GUILayout.TextField(recoverySpeed, 4, GUILayout.Width(c4)); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); GUILayout.Label("Homeworld Altitude:", _labelStyle, GUILayout.Width(130)); homeAltitude = GUILayout.TextField(homeAltitude, 8, GUILayout.Width(c7)); @@ -286,6 +293,7 @@ private void SaveSettings(LifeSupportConfig config) config.HabRange = SaveDouble(config.HabRange,habRange); config.HomeWorldAltitude = SaveInt(config.HomeWorldAltitude,homeAltitude); config.BaseHabTime = SaveDouble(config.BaseHabTime,baseHabTime); + config.RecoverySpeed = SaveFloat(config.RecoverySpeed,recoverySpeed); config.VetNames = vetNames; LifeSupportScenario.Instance.settings.SaveConfig(config); GuiOff(); diff --git a/Source/USILifeSupport/LifeSupportPersistance.cs b/Source/USILifeSupport/LifeSupportPersistance.cs index bf200d9..ec2bf7c 100644 --- a/Source/USILifeSupport/LifeSupportPersistance.cs +++ b/Source/USILifeSupport/LifeSupportPersistance.cs @@ -88,6 +88,7 @@ private LifeSupportConfig LoadLifeSupportConfig() ScoutHabTime = 9180000, PermaHabTime = 459000000, HabRange = 2000, + RecoverySpeed = 1f, VetNames = "" }; @@ -125,6 +126,7 @@ private LifeSupportConfig LoadLifeSupportConfig() finalSettings.EVAEffectVets = Math.Max(settings.EVAEffectVets, finalSettings.EVAEffectVets); finalSettings.VetNames += settings.VetNames + ","; finalSettings.HabRange = Math.Min(settings.HabRange, finalSettings.HabRange); + finalSettings.RecoverySpeed = Math.Min(settings.RecoverySpeed, finalSettings.RecoverySpeed); if (settings.EnableRecyclers) finalSettings.EnableRecyclers = true; } @@ -197,10 +199,9 @@ public void Save(ConfigNode node) rNode.AddValue("LastAtHome", r.LastAtHome); rNode.AddValue("LastSOIChange", r.LastSOIChange); rNode.AddValue("LastPlanet", r.LastPlanet); - rNode.AddValue("MaxOffKerbinTime", r.MaxOffKerbinTime); rNode.AddValue("CurrentVesselId", r.CurrentVesselId); rNode.AddValue("PreviousVesselId", r.PreviousVesselId); - rNode.AddValue("TimeEnteredVessel", r.TimeEnteredVessel); + rNode.AddValue("RemainingCabinTime", r.RemainingCabinTime); rNode.AddValue("IsGrouchy", r.IsGrouchy); rNode.AddValue("OldTrait", r.OldTrait); rNode.AddValue("LastUpdate", r.LastUpdate); @@ -258,6 +259,7 @@ public void Save(ConfigNode node) sNode.AddValue("ReplacementPartAmount", _Settings.ReplacementPartAmount); sNode.AddValue("EnableRecyclers", _Settings.EnableRecyclers); sNode.AddValue("HabRange", _Settings.HabRange); + sNode.AddValue("RecoverySpeed", _Settings.RecoverySpeed); sNode.AddValue("VetNames", _Settings.VetNames); SettingsNode.AddNode(sNode); } @@ -400,6 +402,7 @@ public void SaveConfig(LifeSupportConfig config) _Settings.ReplacementPartAmount = config.ReplacementPartAmount; _Settings.EnableRecyclers = config.EnableRecyclers; _Settings.HabRange = config.HabRange; + _Settings.RecoverySpeed = config.RecoverySpeed; _Settings.VetNames = config.VetNames; } @@ -429,10 +432,9 @@ public void SaveStatusNode(LifeSupportStatus status) kerbInfo.LastSOIChange = status.LastSOIChange; kerbInfo.HomeBodyId = status.HomeBodyId; kerbInfo.LastPlanet = status.LastPlanet; - kerbInfo.MaxOffKerbinTime = status.MaxOffKerbinTime; - kerbInfo.TimeEnteredVessel = status.TimeEnteredVessel; kerbInfo.CurrentVesselId = status.CurrentVesselId; kerbInfo.PreviousVesselId = status.PreviousVesselId; + kerbInfo.RemainingCabinTime = status.RemainingCabinTime; kerbInfo.IsGrouchy = status.IsGrouchy; kerbInfo.OldTrait = status.OldTrait; kerbInfo.LastUpdate = status.LastUpdate; diff --git a/Source/USILifeSupport/LifeSupportStatus.cs b/Source/USILifeSupport/LifeSupportStatus.cs index 65a10c1..37dcba0 100644 --- a/Source/USILifeSupport/LifeSupportStatus.cs +++ b/Source/USILifeSupport/LifeSupportStatus.cs @@ -16,5 +16,6 @@ public class LifeSupportStatus public double TimeEnteredVessel { get; set; } public string CurrentVesselId { get; set; } public string PreviousVesselId { get; set; } + public double RemainingCabinTime { get; set; } } } \ No newline at end of file diff --git a/Source/USILifeSupport/ModuleLifeSupportSystem.cs b/Source/USILifeSupport/ModuleLifeSupportSystem.cs index 48cc715..b13f23d 100644 --- a/Source/USILifeSupport/ModuleLifeSupportSystem.cs +++ b/Source/USILifeSupport/ModuleLifeSupportSystem.cs @@ -247,30 +247,66 @@ public void FixedUpdate() // Update life support stats if (_isStatusRefreshRequired) { - trackedKerbal.TimeEnteredVessel = now; - _isStatusRefreshRequired = false; LifeSupportManager.Instance.TrackKerbal(trackedKerbal); } // Update Hab effects + + // I guess if you've colonized a planet, Kerbals starting there should get cabin time refills? + if (!offKerbin || isHomeWorld) + { + trackedKerbal.RemainingCabinTime = LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime + * LifeSupportUtilities.SecondsPerMonth(); + } if (!offKerbin || isScout || isHomeWorld || isPermaHab) { - trackedKerbal.TimeEnteredVessel = now; trackedKerbal.LastAtHome = now; - trackedKerbal.MaxOffKerbinTime = habTime + trackedKerbal.LastAtHome; } else { if (vessel.id.ToString() != trackedKerbal.CurrentVesselId) { - if (vessel.id.ToString() != trackedKerbal.PreviousVesselId) - trackedKerbal.TimeEnteredVessel = now; - trackedKerbal.PreviousVesselId = trackedKerbal.CurrentVesselId; trackedKerbal.CurrentVesselId = vessel.id.ToString(); LifeSupportManager.Instance.TrackKerbal(trackedKerbal); } + // Handle cabin time consumption or regeneration... + + var timeSinceUpdate = now - trackedKerbal.LastUpdate; + var timePermittedWithinHab = Math.Max(0, VesselStatus.CachedHabTime - (now - trackedKerbal.LastAtHome)); + + // First regenerate based on the amount of hab time we had left. + if (timePermittedWithinHab > 0) + { + // Count just the remaining hab time if we don't have enough to span the full update + var habTimeCountingTowardsRegen = Math.Min(timeSinceUpdate, timePermittedWithinHab); + // Regenerate + trackedKerbal.RemainingCabinTime += (habTimeCountingTowardsRegen) * + LifeSupportScenario.Instance.settings.GetSettings().RecoverySpeed; + // Now cap it before trying to remove any + if (trackedKerbal.RemainingCabinTime > LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime + * LifeSupportUtilities.SecondsPerMonth()) + { + trackedKerbal.RemainingCabinTime = LifeSupportScenario.Instance.settings.GetSettings().BaseHabTime + * LifeSupportUtilities.SecondsPerMonth(); + } + } + + // If we ran out of hab time, any remaining time in the update consumes cabin time. + if (timePermittedWithinHab < timeSinceUpdate) + { + // Consume the remaining amount in cabin time, scaling by seat fraction filled and multiplier. + trackedKerbal.RemainingCabinTime -= (timeSinceUpdate - timePermittedWithinHab) + * ((double)VesselStatus.NumCrew / (double)VesselStatus.CrewCap) + * (1.0 / (1 + VesselStatus.VesselHabMultiplier)); + // Now cap it so we don't have cabin time going crazy negative when loading a vessel after a while + if (trackedKerbal.RemainingCabinTime < -2) + { + trackedKerbal.RemainingCabinTime = -2; + } + } + isGrouchyHab = CheckHabSideEffects(trackedKerbal); } @@ -332,6 +368,10 @@ public void FixedUpdate() LifeSupportManager.Instance.TrackKerbal(trackedKerbal); } + if (_isStatusRefreshRequired) + { + _isStatusRefreshRequired = false; + } } #endregion - Crew @@ -374,10 +414,25 @@ private void CheckEVA(Vessel evaKerbal) var kerbal = evaKerbal.GetVesselCrew()[0]; //Check their status. var kerbalStatus = LifeSupportManager.Instance.FetchKerbal(kerbal); + + //Update cabin time while EVA - this won't cause any effects until they board something, which is fine for now + var now = Planetarium.GetUniversalTime(); + kerbalStatus.RemainingCabinTime -= now - kerbalStatus.LastUpdate; + if (kerbalStatus.RemainingCabinTime < -2) + { + kerbalStatus.RemainingCabinTime = -2; + } + kerbalStatus.LastUpdate = now; + if (evaKerbal.missionTime > LifeSupportScenario.Instance.settings.GetSettings().EVATime) { var effect = LifeSupportManager.GetEVAExcessEffect(kerbalStatus.KerbalName); - ApplyEVAEffect(kerbalStatus, kerbal, evaKerbal, effect); + ApplyEVAEffect(kerbalStatus, kerbal, evaKerbal, effect, "excessive EVA time"); + } + else if (kerbalStatus.RemainingCabinTime < 0) + { + var effect = LifeSupportManager.GetNoHomeEffect(kerbalStatus.KerbalName); + ApplyEVAEffect(kerbalStatus, kerbal, evaKerbal, effect, "homesickness"); } } @@ -387,7 +442,7 @@ private bool IsAtHomeForEva(Vessel evaKerbal) (evaKerbal.altitude < LifeSupportScenario.Instance.settings.GetSettings().HomeWorldAltitude); } - private void ApplyEVAEffect(LifeSupportStatus trackedKerbal, ProtoCrewMember crewMember, Vessel vessel, int effectId) + private void ApplyEVAEffect(LifeSupportStatus trackedKerbal, ProtoCrewMember crewMember, Vessel vessel, int effectId, string reason) { if (crewMember.type == ProtoCrewMember.KerbalType.Tourist || crewMember.experienceTrait.Config.Name == "Tourist") return; @@ -409,7 +464,7 @@ private void ApplyEVAEffect(LifeSupportStatus trackedKerbal, ProtoCrewMember cre case 1: //Grouchy if (crewMember.type != ProtoCrewMember.KerbalType.Tourist) { - screenMessage = string.Format("{0} refuses to work", crewMember.name); + screenMessage = string.Format("{0} refuses to work due to {1}", crewMember.name, reason); trackedKerbal.OldTrait = crewMember.experienceTrait.Config.Name; crewMember.type = ProtoCrewMember.KerbalType.Tourist; KerbalRoster.SetExperienceTrait(crewMember, "Tourist"); @@ -419,32 +474,31 @@ private void ApplyEVAEffect(LifeSupportStatus trackedKerbal, ProtoCrewMember cre break; case 2: //Mutinous { - screenMessage = string.Format("{0} has become mutinous", crewMember.name); + screenMessage = string.Format("{0} has become mutinous due to {1}", crewMember.name, reason); trackedKerbal.OldTrait = crewMember.experienceTrait.Config.Name; crewMember.type = ProtoCrewMember.KerbalType.Tourist; KerbalRoster.SetExperienceTrait(crewMember, "Tourist"); trackedKerbal.IsGrouchy = true; LifeSupportManager.Instance.TrackKerbal(trackedKerbal); - DestroyRandomPart(vessel); } break; case 3: //Return to KSC - screenMessage = string.Format("{0} gets fed up and wanders back to the KSC", crewMember.name); + screenMessage = string.Format("{0} gets fed up and wanders back to the KSC due to {1}", crewMember.name, reason); LifeSupportManager.Instance.UntrackKerbal(crewMember.name); crewMember.rosterStatus = ProtoCrewMember.RosterStatus.Available; - DestroyVessel(vessel); + vessel.Die(); break; case 4: //Despawn - screenMessage = string.Format("{0} has gone missing", crewMember.name); + screenMessage = string.Format("{0} has gone missing due to {1}", crewMember.name, reason); LifeSupportManager.Instance.UntrackKerbal(crewMember.name); crewMember.rosterStatus = ProtoCrewMember.RosterStatus.Missing; - DestroyVessel(vessel); + vessel.Die(); break; case 5: //Kill - screenMessage = string.Format("{0} has died", crewMember.name); + screenMessage = string.Format("{0} has died due to {1}", crewMember.name, reason); LifeSupportManager.Instance.UntrackKerbal(crewMember.name); crewMember.rosterStatus = ProtoCrewMember.RosterStatus.Dead; - DestroyVessel(vessel); + vessel.Die(); break; } @@ -704,17 +758,9 @@ private bool CheckIfHomeWorld() private bool CheckHabSideEffects(LifeSupportStatus trackedKerbal) { - var now = Planetarium.GetUniversalTime(); - var habTime = LifeSupportManager.GetTotalHabTime(VesselStatus, vessel); - - if (trackedKerbal.LastAtHome < 1) - trackedKerbal.LastAtHome = now; - if (habTime + trackedKerbal.LastAtHome > trackedKerbal.MaxOffKerbinTime) - trackedKerbal.MaxOffKerbinTime = habTime + trackedKerbal.LastAtHome; - LifeSupportManager.Instance.TrackKerbal(trackedKerbal); - return (now > trackedKerbal.MaxOffKerbinTime || (now - trackedKerbal.TimeEnteredVessel) > habTime); + return (trackedKerbal.RemainingCabinTime < 0); } private bool CheckSupplySideEffects(LifeSupportStatus trackedKerbal) @@ -785,7 +831,7 @@ private void ApplyEffect(LifeSupportStatus trackedKerbal, ProtoCrewMember crewMe case 0: // No effect return; // No need to print case 1: //Grouchy - msg = string.Format("{0} refuses to work {1}", crewMember.name, reason); + msg = string.Format("{0} refuses to work due to {1}", crewMember.name, reason); trackedKerbal.OldTrait = crewMember.experienceTrait.Config.Name; crewMember.type = ProtoCrewMember.KerbalType.Tourist; KerbalRoster.SetExperienceTrait(crewMember, "Tourist"); diff --git a/Source/USILifeSupport/USILifeSupport.csproj b/Source/USILifeSupport/USILifeSupport.csproj index eda6ce0..0dac672 100644 --- a/Source/USILifeSupport/USILifeSupport.csproj +++ b/Source/USILifeSupport/USILifeSupport.csproj @@ -32,7 +32,7 @@ - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\Assembly-CSharp.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\Assembly-CSharp.dll False @@ -42,31 +42,31 @@ - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\UnityEngine.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\UnityEngine.dll False - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\UnityEngine.AnimationModule.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\UnityEngine.AnimationModule.dll False - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\UnityEngine.CoreModule.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\UnityEngine.CoreModule.dll False - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\UnityEngine.ImageConversionModule.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\UnityEngine.ImageConversionModule.dll False - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\UnityEngine.IMGUIModule.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\UnityEngine.IMGUIModule.dll False - ..\..\..\..\KSP_DEV\KSP_x64_Data\Managed\UnityEngine.UI.dll + ..\..\..\..\Desktop\Kerbal Space Program\KSP_x64_Data\Managed\UnityEngine.UI.dll False - ..\..\..\..\KSP_DEV\GameData\000_USITools\USITools.dll + ..\..\..\..\Desktop\Kerbal Space Program\GameData\000_USITools\USITools.dll False @@ -95,7 +95,11 @@ - + + + + + "D:\Games\pdb2mdb\pdb2mdb.exe" "$(TargetFileName)"