Example #1
0
 public void Apply(KerbalHealthStatus khs)
 {
     //Core.Log("Applying the following effect to " + khs.Name + ": " + this);
     if (!Logic.Test(khs.PCM))
     {
         Core.Log("Logic is false for this effect. Application canceled.");
         return;
     }
     else
     {
         Core.Log("Logic is true for this effect.");
     }
     khs.Exposure *= Exposure;
     khs.VesselHealthInfo.HPChange          += HPChangePerDay;
     khs.VesselHealthInfo.RecuperationPower += Recuperation;
     khs.VesselHealthInfo.MaxRecuperaction   = Math.Max(khs.VesselHealthInfo.MaxRecuperaction, Recuperation);
     khs.VesselHealthInfo.Decay             += Decay;
     if (khs.VesselHealthInfo.FreeMultipliers.ContainsKey(MultiplyFactor))
     {
         khs.VesselHealthInfo.FreeMultipliers[MultiplyFactor] *= Multiplier;
     }
     else
     {
         khs.VesselHealthInfo.FreeMultipliers[MultiplyFactor] = Multiplier;
     }
     khs.VesselHealthInfo.Space          += Space;
     khs.VesselHealthInfo.Shielding      += Shielding;
     khs.VesselHealthInfo.PartsRadiation += Radioactivity;
 }
        public void FixedUpdate()
        {
            if (Core.IsInEditor)
            {
                return;
            }

            if (!isActiveAndEnabled || !vessel.IsControllable || !KerbalHealthGeneralSettings.Instance.modEnabled || !KerbalHealthRadiationSettings.Instance.RadiationEnabled || KerbalHealthRadiationSettings.Instance.UseKerbalismRadiation)
            {
                Core.Log($"{vessel.vesselName} is not controllable, the ModuleHealthEnvironmentSensor is inactive, radiation feature is disabled or Kerbalism radiation is used. No data is displayed by {part.name}.");
                Fields["displayData"].guiActive = false;
                return;
            }
            else
            {
                Fields["displayData"].guiActive = true;
            }

            switch (type.ToLowerInvariant())
            {
            case "radiation":
                displayData = (float)KerbalHealthStatus.GetCosmicRadiation(vessel);
                break;

            case "magnetosphere":
                displayData = 1 - (float)KerbalHealthStatus.GetMagnetosphereCoefficient(vessel);
                break;

            default:
                Fields["displayData"].guiActive = false;
                break;
            }
        }
Example #3
0
        public override double ChangePerDay(KerbalHealthStatus khs)
        {
            if (Core.IsInEditor)
            {
                return(IsEnabledInEditor() ? BaseChangePerDay : 0);
            }
            if (khs.PCM.rosterStatus != ProtoCrewMember.RosterStatus.Assigned)
            {
                Core.Log("Home factor is off when kerbal is not assigned.");
                return(0);
            }
            Vessel        vessel = khs.PCM.GetVessel();
            CelestialBody body   = vessel?.mainBody;

            if (body == null)
            {
                Core.Log($"Could not find main body for {khs.Name}.", LogLevel.Error);
                return(0);
            }
            if (body.isHomeWorld && (vessel.altitude < body.scienceValues.flyingAltitudeThreshold))
            {
                Core.Log("Home factor is on.");
                return(BaseChangePerDay);
            }
            Core.Log($"Home factor is off. Main body: {body.name}; altitude: {vessel.altitude:N0}.");
            return(0);
        }
Example #4
0
        public override double ChangePerDay(KerbalHealthStatus khs)
        {
            if (Core.IsInEditor)
            {
                return(IsEnabledInEditor() ? BaseChangePerDay : 0);
            }
            Vessel vessel = khs.PCM.GetVessel();

            if (vessel == null)
            {
                Core.Log($"MicrogravityFactor.ChangePerDay: Core.GetVessel(pcm) is null for {khs.Name}! EVA is {khs.IsOnEVA}.", LogLevel.Error);
                return(0);
            }
            if ((vessel.situation & (Vessel.Situations.ORBITING | Vessel.Situations.SUB_ORBITAL | Vessel.Situations.ESCAPING)) != 0)
            {
                Core.Log($"Microgravity is on due to being in a {vessel.situation} situation.");
                return(BaseChangePerDay);
            }
            if (khs.PCM.geeForce < 0.1)
            {
                Core.Log($"Microgravity is on due to g = {khs.PCM.geeForce:F2}.");
                return(BaseChangePerDay);
            }
            Core.Log($"Microgravity is off, g = {khs.PCM.geeForce:F2}.");
            return(0);
        }
Example #5
0
 public override double ChangePerDay(KerbalHealthStatus khs)
 {
     if (Core.IsInEditor && !IsEnabledInEditor())
     {
         return(0);
     }
     return((Core.GetCrewCount(khs.PCM) <= 1) && !khs.PCM.isBadass ? BaseChangePerDay : 0);
 }
Example #6
0
 public override double ChangePerDay(KerbalHealthStatus khs)
 {
     if (Core.IsInEditor)
     {
         return(IsEnabledInEditor() ? BaseChangePerDay : 0);
     }
     return((khs.PCM.rosterStatus == ProtoCrewMember.RosterStatus.Available) ? BaseChangePerDay : 0);
 }
Example #7
0
 public override double ChangePerDay(KerbalHealthStatus khs)
 {
     if (Core.IsInEditor)
     {
         return(IsEnabledInEditor() ? BaseChangePerDay : 0);
     }
     return(khs.IsOnEVA ? BaseChangePerDay : 0);
 }
Example #8
0
        double TrainingTime(KerbalHealthStatus khs, List <ModuleKerbalHealth> parts)
        {
            double c = 0;

            foreach (ModuleKerbalHealth mkh in parts)
            {
                c += (Core.TrainingCap - khs.TrainingLevelForPart(mkh.id)) * khs.GetPartTrainingComplexity(mkh);
            }
            return(c / khs.TrainingPerDay * KSPUtil.dateTimeFormatter.Day);
        }
Example #9
0
        public override double ChangePerDay(KerbalHealthStatus khs)
        {
            if (Core.IsInEditor)
            {
                return(IsEnabledInEditor() ? BaseChangePerDay : 0);
            }
            Vessel v = khs.PCM.GetVessel();

            return((v.loaded && (v.Connection != null) && v.Connection.IsConnectedHome)
                ? BaseChangePerDay
                : 0);
        }
Example #10
0
        public void OnKerbalNameChange(ProtoCrewMember pcm, string name1, string name2)
        {
            Core.Log("OnKerbalNameChange('" + pcm.name + "', '" + name1 + "', '" + name2 + "')", Core.LogLevel.Important);
            KerbalHealthStatus khs = Core.KerbalHealthList.Find(name1);

            if (khs == null)
            {
                Core.Log(name1 + " not found in KerbalHealthList (contains " + Core.KerbalHealthList.Count + " records). He/she is " + pcm.rosterStatus + ".", Core.LogLevel.Important);
                return;
            }
            khs.Name = name2;
            dirty    = true;
        }
Example #11
0
 /// <summary>
 /// Checks condition and chance, runs the event and displays the message (if applicable). To be called once a day for every event class, for every kerbal
 /// </summary>
 /// <param name="status">Kerbal to process the event for</param>
 public void Process(KerbalHealthStatus status)
 {
     khs = status;
     if (Condition() && (Core.rand.NextDouble() < ChancePerDay()))
     {
         Core.Log(Name + " event has fired for " + khs.Name + ".", Core.LogLevel.Important);
         string msg = Message();
         if ((msg != null) && !IsSilent)
         {
             Core.ShowMessage(msg, khs.PCM);
         }
         Run();
     }
 }
Example #12
0
        public override double ChangePerDay(KerbalHealthStatus khs)
        {
            if (!KerbalHealthQuirkSettings.Instance.ConditionsEnabled)
            {
                return(0);
            }
            double res = 0;

            foreach (HealthCondition hc in khs.Conditions)
            {
                res += hc.HPChangePerDay * KerbalHealthQuirkSettings.Instance.ConditionsEffect;
            }
            Core.Log($"Conditions HP change per day: {res}");
            return(Core.IsInEditor ? (IsEnabledInEditor() ? res : 0) : res);
        }
Example #13
0
 public override double ChangePerDay(KerbalHealthStatus khs)
 {
     if (Core.IsInEditor)
     {
         if (IsEnabledInEditor())
         {
             return((!KerbalHealthFactorsSettings.Instance.TrainingEnabled || KerbalHealthEditorReport.TrainingEnabled)
                 ? BaseChangePerDay * (1 - Core.TrainingCap)
                 : BaseChangePerDay);
         }
         else
         {
             return(0);
         }
     }
     return((khs.PCM.rosterStatus == ProtoCrewMember.RosterStatus.Assigned) ? ChangePerDayActual(khs) : 0);
 }
Example #14
0
 /// <summary>
 /// Checks condition and chance, runs the event and displays the message (if applicable). To be called once a day for every event class, for every kerbal
 /// </summary>
 /// <param name="status">Kerbal to process the event for</param>
 public void Process(KerbalHealthStatus status)
 {
     khs = status;
     if (Condition())
     {
         double roll = Core.rand.NextDouble(), chance = ChancePerDay();
         Core.Log(Name + " event for " + khs.Name + ": rolled " + roll + " with a chance of " + chance + ".");
         if (roll < chance)
         {
             Core.Log(Name + " event has fired for " + khs.Name + ".", Core.LogLevel.Important);
             string msg = Message();
             if ((msg != null) && !IsSilent)
             {
                 Core.ShowMessage(msg, khs.PCM);
             }
             Run();
         }
     }
 }
Example #15
0
        public override double ChangePerDay(ProtoCrewMember pcm)
        {
            if (!KerbalHealthQuirkSettings.Instance.ConditionsEnabled)
            {
                return(0);
            }
            KerbalHealthStatus khs = Core.KerbalHealthList[pcm];

            if (khs == null)
            {
                return(0);
            }
            double res = 0;

            foreach (HealthCondition hc in khs.Conditions)
            {
                res += hc.HPChangePerDay * KerbalHealthQuirkSettings.Instance.ConditionsEffect;
            }
            Core.Log("Conditions HP chande per day: " + res);
            return(Core.IsInEditor ? (IsEnabledInEditor() ? res : 0) : res);
        }
        public override double ChangePerDay(ProtoCrewMember pcm)
        {
            if (!Core.ConditionsEnabled)
            {
                return(0);
            }
            KerbalHealthStatus khs = Core.KerbalHealthList.Find(pcm);

            if (khs == null)
            {
                return(0);
            }
            float  k   = Core.ConditionsEffect;
            double res = 0;

            foreach (HealthCondition hc in khs.Conditions)
            {
                res += hc.HPChangePerDay * k;
            }
            Core.Log("Conditions HP chande per day: " + res);
            return(Core.IsInEditor ? (IsEnabledInEditor() ? res : 0) : res);
        }
Example #17
0
        /// <summary>
        /// Shows Health monitor when the AppLauncher/Blizzy's Toolbar button is clicked
        /// </summary>
        public void DisplayData()
        {
            Core.Log("KerbalHealthScenario.DisplayData", Core.LogLevel.Important);
            UpdateKerbals(true);
            if (selectedKHS == null)
            {
                Core.Log("No kerbal selected, showing overall list.");
                DialogGUILayoutBase layout = new DialogGUIVerticalLayout(true, true);
                if (page > PageCount)
                {
                    page = PageCount;
                }
                if (ShowPages)
                {
                    layout.AddChild(new DialogGUIHorizontalLayout(true, false,
                                                                  new DialogGUIButton("<<", FirstPage, () => (page > 1), true),
                                                                  new DialogGUIButton("<", PageUp, () => (page > 1), false),
                                                                  new DialogGUIHorizontalLayout(TextAnchor.LowerCenter, new DialogGUILabel("Page " + page + "/" + PageCount)),
                                                                  new DialogGUIButton(">", PageDown, () => (page < PageCount), false),
                                                                  new DialogGUIButton(">>", LastPage, () => (page < PageCount), true)));
                }
                gridContents = new List <DialogGUIBase>((Core.KerbalHealthList.Count + 1) * colNumMain);
                // Creating column titles
                gridContents.Add(new DialogGUILabel("Name", true));
                gridContents.Add(new DialogGUILabel("Condition", true));
                gridContents.Add(new DialogGUILabel("Health", true));
                gridContents.Add(new DialogGUILabel("Change/day", true));
                gridContents.Add(new DialogGUILabel("Time Left", true));
                gridContents.Add(new DialogGUILabel("Radiation", true));
                gridContents.Add(new DialogGUILabel("", true));
                // Initializing Health Monitor's grid with empty labels, to be filled in Update()
                List <KerbalHealthStatus> kerbals = new List <KerbalHealth.KerbalHealthStatus>(Core.KerbalHealthList.Values);
                for (int i = FirstLine; i < FirstLine + LineCount; i++)
                {
                    for (int j = 0; j < colNumMain - 1; j++)
                    {
                        gridContents.Add(new DialogGUILabel("", true));
                    }
                    gridContents.Add(new DialogGUIButton <int>("Details", (n) => { selectedKHS = kerbals[n]; Invalidate(); }, i));
                }
                layout.AddChild(new DialogGUIGridLayout(new RectOffset(0, 0, 0, 0), new Vector2(colWidth, 30), new Vector2(colSpacing, 10), UnityEngine.UI.GridLayoutGroup.Corner.UpperLeft, UnityEngine.UI.GridLayoutGroup.Axis.Horizontal, TextAnchor.MiddleCenter, UnityEngine.UI.GridLayoutGroup.Constraint.FixedColumnCount, colNumMain, gridContents.ToArray()));
                monitorPosition.width = gridWidthMain + 10;
                monitorWindow         = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog("Health Monitor", "", "Health Monitor", HighLogic.UISkin, monitorPosition, layout), false, HighLogic.UISkin, false);
            }

            else
            {
                Core.Log("Showing details for " + selectedKHS.Name + ".");
                gridContents = new List <DialogGUIBase>();
                gridContents.Add(new DialogGUILabel("Name:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Level:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Quirks:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Status:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Max HP:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("HP:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("HP Change:"));
                gridContents.Add(new DialogGUILabel(""));
                if (Core.IsKerbalLoaded(selectedKHS.PCM) && !selectedKHS.HasCondition("Frozen"))
                {
                    foreach (HealthFactor f in Core.Factors)
                    {
                        gridContents.Add(new DialogGUILabel(f.Title + ":"));
                        gridContents.Add(new DialogGUILabel(""));
                    }
                }
                gridContents.Add(new DialogGUILabel("Recuperation:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Condition:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Exposure:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Radiation:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Accumulated Dose:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Radiation HP Loss:"));
                gridContents.Add(new DialogGUILabel(""));
                monitorPosition.width = gridWidthDetails + 10;
                monitorWindow         = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog("Health Monitor", "", "Health Details", HighLogic.UISkin, monitorPosition, new DialogGUIVerticalLayout(new DialogGUIGridLayout(new RectOffset(0, 0, 0, 0), new Vector2(colWidth, 30), new Vector2(colSpacing, 10), UnityEngine.UI.GridLayoutGroup.Corner.UpperLeft, UnityEngine.UI.GridLayoutGroup.Axis.Horizontal, TextAnchor.MiddleCenter, UnityEngine.UI.GridLayoutGroup.Constraint.FixedColumnCount, colNumDetails, gridContents.ToArray()), new DialogGUIButton("Back", () => { selectedKHS = null; Invalidate(); }, gridWidthDetails, 20, false))), false, HighLogic.UISkin, false);
            }
            dirty = true;
        }
 public void Update()
 {
     if (!Core.ModEnabled)
     {
         if (reportWindow != null)
         {
             reportWindow.Dismiss();
         }
         return;
     }
     if ((reportWindow != null) && dirty)
     {
         if (gridContents == null)
         {
             Core.Log("gridContents is null.", Core.LogLevel.Error);
             return;
         }
         if (gridContents.Count != (ShipConstruction.ShipManifest.CrewCount + 1) * colNum)  // # of tracked kerbals has changed => close & reopen the window
         {
             Core.Log("Kerbals' number has changed. Recreating the Health Report window.", Core.LogLevel.Important);
             UndisplayData();
             DisplayData();
         }
         // Fill the Health Report's grid with kerbals' health data
         int i = 0;
         KerbalHealthStatus khs = null;
         VesselHealthInfo.Cache.Clear();
         foreach (ProtoCrewMember pcm in ShipConstruction.ShipManifest.GetAllCrew(false))
         {
             if (pcm == null)
             {
                 continue;
             }
             gridContents[(i + 1) * colNum].SetOptionText(pcm.name);
             khs = Core.KerbalHealthList?.Find(pcm)?.Clone();
             if (khs == null)
             {
                 Core.Log("Could not create a clone of KerbalHealthStatus for " + pcm.name + ". It is " + ((Core.KerbalHealthList?.Find(pcm) == null) ? "not " : "") + "found in KerbalHealthList, which contains " + Core.KerbalHealthList.Count + " records.", Core.LogLevel.Error);
                 i++;
                 continue;
             }
             khs.HP = khs.MaxHP;
             double ch = khs.HealthChangePerDay();
             double b  = khs.GetBalanceHP();
             string s  = "";
             if (b > 0)
             {
                 s = "-> " + b.ToString("F0") + " HP (" + (b / khs.MaxHP * 100).ToString("F0") + "%)";
             }
             else
             {
                 s = ch.ToString("F1") + " HP/day";
             }
             gridContents[(i + 1) * colNum + 1].SetOptionText(s);
             if (b > khs.NextConditionHP())
             {
                 s = "—";
             }
             else
             {
                 s = ((khs.LastRecuperation > khs.LastDecay) ? "> " : "") + Core.ParseUT(khs.TimeToNextCondition());
             }
             gridContents[(i + 1) * colNum + 2].SetOptionText(s);
             i++;
         }
         spaceLbl.SetOptionText(khs.VesselHealthInfo.Space.ToString("F1"));
         recupLbl.SetOptionText(khs.VesselHealthInfo.Recuperation.ToString("F1") + "%");
         shieldingLbl.SetOptionText(khs.VesselHealthInfo.Shielding.ToString("F1"));
         exposureLbl.SetOptionText(khs.Exposure.ToString("P1"));
         dirty = false;
     }
 }
Example #19
0
 public override double ChangePerDay(KerbalHealthStatus khs)
 => ((Core.IsInEditor && !IsEnabledInEditor()) || (!Core.IsInEditor && khs.IsOnEVA))
     ? 0
     : BaseChangePerDay *Core.GetCrewCount(khs.PCM) / Math.Max(khs.HealthEffects.Space, 0.1);
Example #20
0
 public bool IsApplicable(KerbalHealthStatus khs) => Logic.Test(khs.PCM);
Example #21
0
        /// <summary>
        /// Displays actual values in Health Monitor
        /// </summary>
        public void Update()
        {
            if (!Core.ModEnabled)
            {
                if (monitorWindow != null)
                {
                    monitorWindow.Dismiss();
                }
                return;
            }

            if ((monitorWindow == null) || !dirty)
            {
                return;
            }

            if (gridContents == null)
            {
                Core.Log("KerbalHealthScenario.gridContents is null.", Core.LogLevel.Error);
                monitorWindow.Dismiss();
                return;
            }

            if (selectedKHS == null)  // Showing list of all kerbals
            {
                if (crewChanged)
                {
                    Core.KerbalHealthList.RegisterKerbals();
                    Invalidate();
                    crewChanged = false;
                }
                Core.Log(kerbals.Count + " kerbals in Health Monitor list.");
                // Fill the Health Monitor's grid with kerbals' health data
                for (int i = 0; i < LineCount; i++)
                {
                    KerbalHealthStatus khs = kerbals.Values[FirstLine + i];
                    bool   healthFrozen    = khs.IsFrozen || khs.IsDecontaminating;
                    double ch = khs.LastChangeTotal;
                    double b = khs.GetBalanceHP();
                    string formatTag = "", formatUntag = "";
                    string s = "";
                    if (healthFrozen || ((b - khs.NextConditionHP()) * ch <= 0))
                    {
                        s = "—";
                    }
                    else
                    {
                        s = Core.ParseUT(khs.TimeToNextCondition(), true, 100);
                        if (ch < 0)
                        {
                            if (khs.TimeToNextCondition() < KSPUtil.dateTimeFormatter.Day)
                            {
                                formatTag = "<color=\"red\">";
                            }
                            else
                            {
                                formatTag = "<color=\"orange\">";
                            }
                            formatUntag = "</color>";
                        }
                    }
                    gridContents[(i + 1) * colNumMain].SetOptionText(formatTag + khs.Name + formatUntag);
                    gridContents[(i + 1) * colNumMain + 1].SetOptionText(formatTag + khs.LocationString + formatUntag);
                    gridContents[(i + 1) * colNumMain + 2].SetOptionText(formatTag + khs.ConditionString + formatUntag);
                    gridContents[(i + 1) * colNumMain + 3].SetOptionText(formatTag + (100 * khs.Health).ToString("F2") + "% (" + khs.HP.ToString("F2") + ")" + formatUntag);
                    gridContents[(i + 1) * colNumMain + 4].SetOptionText(formatTag + ((healthFrozen || (khs.Health >= 1)) ? "—" : (((ch > 0) ? "+" : "") + ch.ToString("F2"))) + formatUntag);
                    gridContents[(i + 1) * colNumMain + 5].SetOptionText(formatTag + s + formatUntag);
                    gridContents[(i + 1) * colNumMain + 6].SetOptionText(formatTag + Core.PrefixFormat(khs.Dose, 5) + (khs.Radiation != 0 ? " (" + Core.PrefixFormat(khs.Radiation, 4, true) + "/day)" : "") + formatUntag);
                }
            }
            else  // Showing details for one particular kerbal
            {
                ProtoCrewMember pcm = selectedKHS.PCM;
                if (pcm == null)
                {
                    selectedKHS = null;
                    Invalidate();
                }
                bool healthFrozen = selectedKHS.IsFrozen || selectedKHS.IsDecontaminating;
                gridContents[1].SetOptionText("<color=\"white\">" + selectedKHS.Name + "</color>");
                gridContents[3].SetOptionText("<color=\"white\">" + pcm.experienceLevel + "</color>");
                gridContents[5].SetOptionText("<color=\"white\">" + selectedKHS.ConditionString + "</color>");
                string s = "";
                foreach (Quirk q in selectedKHS.Quirks)
                {
                    if (q.IsVisible)
                    {
                        s += ((s != "") ? ", " : "") + q.Title;
                    }
                }
                if (s == "")
                {
                    s = "None";
                }
                gridContents[7].SetOptionText("<color=\"white\">" + s + "</color>");
                gridContents[9].SetOptionText("<color=\"white\">" + selectedKHS.MaxHP.ToString("F2") + "</color>");
                gridContents[11].SetOptionText("<color=\"white\">" + selectedKHS.HP.ToString("F2") + " (" + selectedKHS.Health.ToString("P2") + ")" + "</color>");
                gridContents[13].SetOptionText("<color=\"white\">" + (healthFrozen ? "—" : selectedKHS.LastChangeTotal.ToString("F2")) + "</color>");
                int i = 15;
                if (Core.IsKerbalLoaded(selectedKHS.PCM) && !healthFrozen)
                {
                    foreach (HealthFactor f in Core.Factors)
                    {
                        gridContents[i].SetOptionText("<color=\"white\">" + (selectedKHS.Factors.ContainsKey(f.Name) ? selectedKHS.Factors[f.Name].ToString("F2") : "N/A") + "</color>");
                        i += 2;
                    }
                }
                gridContents[i].SetOptionText("<color=\"white\">" + (healthFrozen ? "N/A" : (selectedKHS.LastRecuperation.ToString("F1") + "%" + (selectedKHS.LastDecay != 0 ? ("/ " + (-selectedKHS.LastDecay).ToString("F1") + "%") : "") + " (" + selectedKHS.MarginalChange.ToString("F2") + " HP)")) + "</color>");
                gridContents[i + 2].SetOptionText("<color=\"white\">" + selectedKHS.LastExposure.ToString("P2") + "</color>");
                gridContents[i + 4].SetOptionText("<color=\"white\">" + selectedKHS.Radiation.ToString("N0") + "/day</color>");
                gridContents[i + 6].children[0].SetOptionText("<color=\"white\">" + selectedKHS.Dose.ToString("N0") + "</color>");
                gridContents[i + 8].SetOptionText("<color=\"white\">" + (1 - selectedKHS.RadiationMaxHPModifier).ToString("P2") + "</color>");
            }
            dirty = false;
        }
Example #22
0
 /// <summary>
 /// Returns HP change per day due to stress at the current training level for the kerbal
 /// </summary>
 /// <param name="pcm"></param>
 /// <returns></returns>
 double ChangePerDayActual(KerbalHealthStatus khs) => BaseChangePerDay * (1 - khs.TrainingLevel);
Example #23
0
        /// <summary>
        /// Displays actual values in Health Monitor
        /// </summary>
        public void Update()
        {
            if (!Core.ModEnabled)
            {
                if (monitorWindow != null)
                {
                    monitorWindow.Dismiss();
                }
                return;
            }

            if ((monitorWindow == null) || !dirty)
            {
                return;
            }

            if (gridContents == null)
            {
                Core.Log("KerbalHealthScenario.gridContents is null.", Core.LogLevel.Error);
                return;
            }

            if (selectedKHS == null)  // Showing list of all kerbals
            {
                if (crewChanged)
                {
                    Core.KerbalHealthList.RegisterKerbals();
                    if ((page >= PageCount) || (Core.KerbalHealthList.Count == LinesPerPage + 1))
                    {
                        Invalidate();
                    }
                    crewChanged = false;
                }
                // Fill the Health Monitor's grid with kerbals' health data
                for (int i = 0; i < LineCount; i++)
                {
                    List <KerbalHealthStatus> kerbals = new List <KerbalHealth.KerbalHealthStatus>(Core.KerbalHealthList.Values);
                    KerbalHealthStatus        khs     = kerbals[FirstLine + i];
                    bool   frozen = khs.HasCondition("Frozen");
                    double ch     = khs.LastChangeTotal;
                    gridContents[(i + 1) * colNumMain].SetOptionText(khs.Name);
                    gridContents[(i + 1) * colNumMain + 1].SetOptionText(khs.ConditionString);
                    gridContents[(i + 1) * colNumMain + 2].SetOptionText((100 * khs.Health).ToString("F2") + "% (" + khs.HP.ToString("F2") + ")");
                    gridContents[(i + 1) * colNumMain + 3].SetOptionText((frozen || (khs.Health >= 1)) ? "—" : (((ch > 0) ? "+" : "") + ch.ToString("F2")));
                    double b = khs.GetBalanceHP();
                    string s = "";
                    if (frozen || (b > khs.NextConditionHP()))
                    {
                        s = "—";
                    }
                    else
                    {
                        s = ((b > 0) ? "> " : "") + Core.ParseUT(khs.TimeToNextCondition(), true, 100);
                    }
                    gridContents[(i + 1) * colNumMain + 4].SetOptionText(s);
                    gridContents[(i + 1) * colNumMain + 5].SetOptionText(khs.Dose.ToString("N0") + (khs.Radiation != 0 ? " (+" + khs.Radiation.ToString("N0") + "/day)" : ""));
                }
            }
            else  // Showing details for one particular kerbal
            {
                ProtoCrewMember pcm    = selectedKHS.PCM;
                bool            frozen = selectedKHS.HasCondition("Frozen");
                gridContents[1].SetOptionText(selectedKHS.Name);
                gridContents[3].SetOptionText(pcm.experienceLevel.ToString());
                string s = "";
                foreach (Quirk q in selectedKHS.Quirks)
                {
                    if (q.IsVisible)
                    {
                        s += ((s != "") ? ", " : "") + q.Title;
                    }
                }
                if (s == "")
                {
                    s = "None";
                }
                gridContents[5].SetOptionText(s);
                gridContents[7].SetOptionText(pcm.rosterStatus.ToString());
                gridContents[9].SetOptionText(selectedKHS.MaxHP.ToString("F2"));
                gridContents[11].SetOptionText(selectedKHS.HP.ToString("F2") + " (" + selectedKHS.Health.ToString("P2") + ")");
                gridContents[13].SetOptionText(frozen ? "—" : selectedKHS.LastChangeTotal.ToString("F2"));
                int i = 15;
                if (Core.IsKerbalLoaded(selectedKHS.PCM) && !frozen)
                {
                    foreach (HealthFactor f in Core.Factors)
                    {
                        gridContents[i].SetOptionText(selectedKHS.Factors.ContainsKey(f.Name) ? selectedKHS.Factors[f.Name].ToString("F2") : "N/A");
                        i += 2;
                    }
                }
                gridContents[i].SetOptionText(frozen ? "N/A" : selectedKHS.LastRecuperation.ToString("F1") + "% (" + selectedKHS.MarginalChange.ToString("F2") + " HP/day)");
                gridContents[i + 2].SetOptionText(selectedKHS.ConditionString);
                gridContents[i + 4].SetOptionText(selectedKHS.Exposure.ToString("P2"));
                gridContents[i + 6].SetOptionText(selectedKHS.Radiation.ToString("N2") + "/day");
                gridContents[i + 8].SetOptionText(selectedKHS.Dose.ToString("N2"));
                gridContents[i + 10].SetOptionText((1 - selectedKHS.RadiationMaxHPModifier).ToString("P2"));
            }
            dirty = false;
        }
Example #24
0
        /// <summary>
        /// Shows Health monitor when the AppLauncher/Blizzy's Toolbar button is clicked
        /// </summary>
        public void DisplayData()
        {
            Core.Log("KerbalHealthScenario.DisplayData", Core.LogLevel.Important);
            UpdateKerbals(true);
            if (selectedKHS == null)
            {
                Core.Log("No kerbal selected, showing overall list.");

                // Preparing a sorted list of kerbals
                kerbals = new SortedList <ProtoCrewMember, KerbalHealthStatus>(new KerbalComparer(HighLogic.CurrentGame.Parameters.CustomParams <KerbalHealthGeneralSettings>().SortByLocation));
                foreach (KerbalHealthStatus khs in Core.KerbalHealthList.Values)
                {
                    kerbals.Add(khs.PCM, khs);
                }

                DialogGUILayoutBase layout = new DialogGUIVerticalLayout(true, true);
                if (page > PageCount)
                {
                    page = PageCount;
                }
                if (ShowPages)
                {
                    layout.AddChild(new DialogGUIHorizontalLayout(true, false,
                                                                  new DialogGUIButton("<<", FirstPage, () => (page > 1), true),
                                                                  new DialogGUIButton("<", PageUp, () => (page > 1), false),
                                                                  new DialogGUIHorizontalLayout(TextAnchor.LowerCenter, new DialogGUILabel("Page " + page + "/" + PageCount)),
                                                                  new DialogGUIButton(">", PageDown, () => (page < PageCount), false),
                                                                  new DialogGUIButton(">>", LastPage, () => (page < PageCount), true)));
                }
                gridContents = new List <DialogGUIBase>((Core.KerbalHealthList.Count + 1) * colNumMain);

                // Creating column titles
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Name</color></b>", true));
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Location</color></b>", true));
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Condition</color></b>", true));
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Health</color></b>", true));
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Change/day</color></b>", true));
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Time Left</color></b>", true));
                gridContents.Add(new DialogGUILabel("<b><color=\"white\">Radiation</color></b>", true));
                gridContents.Add(new DialogGUILabel("", true));

                // Initializing Health Monitor's grid with empty labels, to be filled in Update()
                for (int i = FirstLine; i < FirstLine + LineCount; i++)
                {
                    for (int j = 0; j < colNumMain - 1; j++)
                    {
                        gridContents.Add(new DialogGUILabel("", true));
                    }
                    gridContents.Add(new DialogGUIButton <int>("Details", (n) => { selectedKHS = kerbals.Values[n]; Invalidate(); }, i));
                }
                layout.AddChild(new DialogGUIGridLayout(new RectOffset(0, 0, 0, 0), new Vector2(colWidth, 30), new Vector2(colSpacing, 10), UnityEngine.UI.GridLayoutGroup.Corner.UpperLeft, UnityEngine.UI.GridLayoutGroup.Axis.Horizontal, TextAnchor.MiddleCenter, UnityEngine.UI.GridLayoutGroup.Constraint.FixedColumnCount, colNumMain, gridContents.ToArray()));
                monitorPosition.width = gridWidthList + 10;
                monitorWindow         = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog("Health Monitor", "", "Health Monitor", HighLogic.UISkin, monitorPosition, layout), false, HighLogic.UISkin, false);
            }

            else
            {
                // Creating the grid for detailed view, which will be filled in Update method
                Core.Log("Showing details for " + selectedKHS.Name + ".");
                gridContents = new List <DialogGUIBase>();
                gridContents.Add(new DialogGUILabel("Name:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Level:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Condition:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Quirks:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Max HP:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("HP:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("HP Change:"));
                gridContents.Add(new DialogGUILabel(""));
                if (Core.IsKerbalLoaded(selectedKHS.PCM) && !selectedKHS.HasCondition("Frozen"))
                {
                    foreach (HealthFactor f in Core.Factors)
                    {
                        gridContents.Add(new DialogGUILabel(f.Title + ":"));
                        gridContents.Add(new DialogGUILabel(""));
                    }
                }
                gridContents.Add(new DialogGUILabel("Recuperation:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Exposure:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Radiation:"));
                gridContents.Add(new DialogGUILabel(""));
                gridContents.Add(new DialogGUILabel("Lifetime Dose:"));
                gridContents.Add(new DialogGUIHorizontalLayout(
                                     new DialogGUILabel(""),
                                     new DialogGUIButton("Decon", OnDecontamination, 50, 20, false)));
                gridContents.Add(new DialogGUILabel("Rad HP Loss:"));
                gridContents.Add(new DialogGUILabel(""));
                monitorPosition.width = gridWidthDetails + 10;
                monitorWindow         = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new MultiOptionDialog("Health Monitor", "", "Health Details", HighLogic.UISkin, monitorPosition, new DialogGUIVerticalLayout(new DialogGUIGridLayout(new RectOffset(3, 3, 3, 3), new Vector2(colWidth, 40), new Vector2(colSpacing, 10), UnityEngine.UI.GridLayoutGroup.Corner.UpperLeft, UnityEngine.UI.GridLayoutGroup.Axis.Horizontal, TextAnchor.MiddleCenter, UnityEngine.UI.GridLayoutGroup.Constraint.FixedColumnCount, colNumDetails, gridContents.ToArray()), new DialogGUIButton("Back", () => { selectedKHS = null; Invalidate(); }, gridWidthDetails, 20, false))), false, HighLogic.UISkin, false);
            }
            dirty = true;
        }
Example #25
0
        public void Update()
        {
            if (!KerbalHealthGeneralSettings.Instance.modEnabled)
            {
                if (reportWindow != null)
                {
                    reportWindow.Dismiss();
                }
                return;
            }

            if ((reportWindow != null) && dirty)
            {
                if (gridContents == null)
                {
                    Core.Log("gridContents is null.", LogLevel.Error);
                    return;
                }

                // # of tracked kerbals has changed => close & reopen the window
                if (gridContents.Count != (ShipConstruction.ShipManifest.CrewCount + 1) * colNum)
                {
                    Core.Log("Kerbals' number has changed. Recreating the Health Report window.", LogLevel.Important);
                    UndisplayData();
                    DisplayData();
                }

                // Fill the Health Report's grid with kerbals' health data
                int i = 0;
                KerbalHealthStatus khs = null;
                HealthModifierSet.VesselCache.Clear();

                List <ModuleKerbalHealth> trainingParts = Core.GetTrainingCapableParts(EditorLogic.SortedShipList);

                foreach (ProtoCrewMember pcm in ShipConstruction.ShipManifest.GetAllCrew(false).Where(pcm => pcm != null))
                {
                    khs = Core.KerbalHealthList[pcm]?.Clone();
                    if (khs == null)
                    {
                        Core.Log("Could not create a clone of KerbalHealthStatus for " + pcm.name + ". It is " + ((Core.KerbalHealthList[pcm] == null) ? "not " : "") + "found in KerbalHealthList, which contains " + Core.KerbalHealthList.Count + " records.", LogLevel.Error);
                        i++;
                        continue;
                    }

                    gridContents[(i + 1) * colNum].SetOptionText(khs.FullName);
                    khs.HP = khs.MaxHP;
                    // Making this call here, so that GetBalanceHP doesn't have to:
                    double changePerDay = khs.HealthChangePerDay();
                    double balanceHP    = khs.GetBalanceHP();
                    string s            = balanceHP > 0
                        ? "-> " + balanceHP.ToString("F0") + " HP (" + (balanceHP / khs.MaxHP * 100).ToString("F0") + "%)"
                        : Localizer.Format("#KH_ER_HealthPerDay", changePerDay.ToString("F1")); // + " HP/day"
                    gridContents[(i + 1) * colNum + 1].SetOptionText(s);
                    s = balanceHP > khs.NextConditionHP()
                        ? "—"
                        : ((khs.LastRecuperation > khs.LastDecay) ? "> " : "") + Core.ParseUT(khs.TimeToNextCondition(), false, 100);
                    gridContents[(i + 1) * colNum + 2].SetOptionText(s);
                    gridContents[(i + 1) * colNum + 3].SetOptionText(KerbalHealthFactorsSettings.Instance.TrainingEnabled ? Core.ParseUT(TrainingTime(khs, trainingParts), false, 100) : "N/A");
                    i++;
                }

                spaceLbl.SetOptionText("<color=\"white\">" + khs.VesselModifiers.Space.ToString("F1") + "</color>");
                recupLbl.SetOptionText("<color=\"white\">" + khs.VesselModifiers.Recuperation.ToString("F1") + "%</color>");
                shieldingLbl.SetOptionText("<color=\"white\">" + khs.VesselModifiers.Shielding.ToString("F1") + "</color>");
                exposureLbl.SetOptionText("<color=\"white\">" + khs.LastExposure.ToString("P1") + "</color>");
                shelterExposureLbl.SetOptionText("<color=\"white\">" + khs.VesselModifiers.ShelterExposure.ToString("P1") + "</color>");

                dirty = false;
            }
        }
Example #26
0
 double TrainingTime(KerbalHealthStatus khs, List <ModuleKerbalHealth> modules) =>
 modules.Sum(mkh => (Core.TrainingCap - khs.TrainingLevelForPart(mkh.id)) * khs.GetPartTrainingComplexity(mkh)) / khs.TrainingPerDay * KSPUtil.dateTimeFormatter.Day;