Ejemplo n.º 1
0
        internal static void RegisterExperienceTrait(RMKerbal rmkerbal)
        {
            Vessel vsl = FlightGlobals.Vessels.FirstOrDefault(a => a.id == rmkerbal.VesselId);

            if (vsl == null)
            {
                return;
            }
            if (!vsl.loaded)
            {
                return;
            }
            List <Part> .Enumerator parts = vsl.parts.GetEnumerator();
            while (parts.MoveNext())
            {
                if (parts.Current == null)
                {
                    continue;
                }
                bool found = false;
                if (parts.Current.protoModuleCrew.Any(partcrew => partcrew == rmkerbal.Kerbal))
                {
                    rmkerbal.Kerbal.RegisterExperienceTraits(parts.Current);
                    found = true;
                }
                if (found)
                {
                    break;
                }
            }
            parts.Dispose();
        }
Ejemplo n.º 2
0
        internal void Load(ConfigNode node)
        {
            AllrmKerbals.Clear();

            if (node.HasNode(ConfigNodeName))
            {
                ConfigNode kerbalLifeRecordNode = node.GetNode(ConfigNodeName);

                List <ConfigNode> .Enumerator kerbalNodes = kerbalLifeRecordNode.GetNodes(RMKerbal.ConfigNodeName).ToList().GetEnumerator();
                while (kerbalNodes.MoveNext())
                {
                    if (kerbalNodes.Current == null)
                    {
                        continue;
                    }
                    if (!kerbalNodes.Current.HasValue("kerbalName"))
                    {
                        continue;
                    }
                    string id = kerbalNodes.Current.GetValue("kerbalName");
                    RmUtils.LogMessage("RosterManagerLifeSpan.RMKerbals Loading kerbal = " + id, "info", RMSettings.VerboseLogging);
                    RMKerbal kerballifeinfo = RMKerbal.Load(kerbalNodes.Current, id);
                    AllrmKerbals[id] = kerballifeinfo;
                }
                kerbalNodes.Dispose();
            }
            RmUtils.LogMessage("RosterManagerLifeSpan.RMKerbals Loading Completed", "info", RMSettings.VerboseLogging);
        }
Ejemplo n.º 3
0
        internal static void RegisterExperienceTrait(RMKerbal rmkerbal)
        {
            var vsl = FlightGlobals.Vessels.FirstOrDefault(a => a.id == rmkerbal.VesselId);

            if (vsl == null)
            {
                return;
            }
            if (!vsl.loaded)
            {
                return;
            }
            foreach (var part in vsl.parts)
            {
                var found = false;
                if (part.protoModuleCrew.Any(partcrew => partcrew == rmkerbal.Kerbal))
                {
                    rmkerbal.Kerbal.RegisterExperienceTraits(part);
                    found = true;
                }
                if (found)
                {
                    break;
                }
            }
        }
        private void OnKerbalHired(ProtoCrewMember crew, int num)
        {
            var currentTime = Planetarium.GetUniversalTime();
            var rmkerbal    = RMLifeSpan.Instance.RMKerbals.AllrmKerbals.FirstOrDefault(a => a.Key == crew.name);

            rmkerbal.Value.Timelastsalary = currentTime;
            rmkerbal.Value.TimeSalaryDue  = RMKerbal.SalaryNextDue(currentTime);
            Utilities.LogMessage("RosterManagerLifeSpanAddon.onKerbalHired " + crew.name + " has been hired to the crew roster.", "info", RMSettings.VerboseLogging);
        }
Ejemplo n.º 5
0
 private void ProcessContractDispute(ProtoCrewMember crew, KeyValuePair <string, RMKerbal> kerbal, double currentTime, bool start, bool extend)
 {
     // They will continue to work for RMLifeSpan.Instance.rmGameSettings.MaxContractDisputePeriods of salaryperiod, with a payrise that must be accepted each time. All backpay is accrued.
     // Or they quit/strike after RMLifeSpan.Instance.rmGameSettings.MaxContractDisputePeriods or if user does not accept the payrise.
     RmUtils.LogMessage($"RosterManagerLifeSpanAddon.CheckSalary unable to pay {crew.name} salary.", "info", RMSettings.VerboseLogging);
     if (start)                                                                                                                          //Start a new contract dispute
     {
         ScreenMessages.PostScreenMessage($"{Localizer.Format("#autoLOC_RM_1103")} {crew.name}", 5.0f, ScreenMessageStyle.UPPER_CENTER); // #autoLOC_RM_1103 = Insufficient funds to pay {0} salary at this time.
         kerbal.Value.SalaryContractDispute = true;
         kerbal.Value.RealTrait             = kerbal.Value.Trait;
         //Start processing dispute, increase the periods we have been in dispute, user must accept payrise as well (if they don't the kerbal Quits) and calculate and store their backpay owed.
         ExtendContractDispute(crew, kerbal);
     }
     else // Process existing contract dispute
     {
         //Check if we have funds now?
         //If we have pay them.
         //Else extend the contract dispute.
         if (Funding.CanAfford((float)kerbal.Value.Salary + (float)kerbal.Value.OwedSalary))
         {
             Funding.Instance.AddFunds(-(kerbal.Value.Salary + kerbal.Value.OwedSalary), TransactionReasons.CrewRecruited);
             kerbal.Value.Timelastsalary                 = currentTime;
             kerbal.Value.SalaryContractDispute          = false;
             kerbal.Value.SalaryContractDisputeProcessed = true;
             kerbal.Value.SalaryContractDisputePeriods   = 0;
             kerbal.Value.PayriseRequired                = 0d;
             kerbal.Value.OwedSalary = 0d;
             //If they are a tourist (dispute) and not dead (DeepFreeze frozen/comatose) set them back to crew
             if (kerbal.Value.Type == ProtoCrewMember.KerbalType.Tourist && crew.rosterStatus != ProtoCrewMember.RosterStatus.Dead)
             {
                 kerbal.Value.Type  = ProtoCrewMember.KerbalType.Crew;
                 crew.type          = ProtoCrewMember.KerbalType.Crew;
                 kerbal.Value.Trait = kerbal.Value.RealTrait;
                 crew.trait         = kerbal.Value.RealTrait;
                 KerbalRoster.SetExperienceTrait(crew, crew.trait);
                 RMKerbal.RegisterExperienceTrait(kerbal.Value);
             }
             RmUtils.LogMessage($"RosterManagerLifeSpanAddon.CheckSalary paid {crew.name} salary.", "info", RMSettings.VerboseLogging);
             RmUtils.LogMessage($"RosterManagerLifeSpanAddon.CheckSalary contract dispute ended {crew.name}", "info", RMSettings.VerboseLogging);
             ScreenMessages.PostScreenMessage(
                 $"{crew.name} {Localizer.Format("#autoLOC_RM_1104")} {kerbal.Value.Salary + kerbal.Value.OwedSalary}", 5.0f, ScreenMessageStyle.UPPER_CENTER); // #autoLOC_RM_1104 = Paid {0} salary of {1}
             ScreenMessages.PostScreenMessage($"{crew.name} {Localizer.Format("#autoLOC_RM_1105")}", 5.0f, ScreenMessageStyle.UPPER_CENTER);                    // #autoLOC_RM_1105 = {0} contract dispute ended.
         }
         else //Can't end dispute
         {
             if (!extend)
             {
                 return;
             }
             kerbal.Value.Timelastsalary = currentTime;
             ExtendContractDispute(crew, kerbal);
         }
     }
 }
Ejemplo n.º 6
0
 public static RMKerbal Load(ConfigNode node, string name)
 {
     try
     {
         double lastUpdate = GetNodes.GetNodeValue(node, "lastUpdate", 0d);
         List <ProtoCrewMember> crewList = HighLogic.CurrentGame.CrewRoster.Crew.Concat(HighLogic.CurrentGame.CrewRoster.Applicants).ToList();
         //If Deepfreeze is installed add Unowned and Tourists to the list (could be frozen or comatose).
         if (Api.InstalledMods.IsDfInstalled)
         {
             crewList = crewList.Concat(HighLogic.CurrentGame.CrewRoster.Unowned).Concat(HighLogic.CurrentGame.CrewRoster.Tourist).ToList();
         }
         //var tmpvesselId = GetNodes.GetNodeValue(node, "vesselID", "");
         ProtoCrewMember kerbal = crewList.FirstOrDefault(a => a.name == name);
         RMKerbal        info   = new RMKerbal(lastUpdate, kerbal, false, false)
         {
             Status                         = GetNodes.GetNodeValue(node, "status", ProtoCrewMember.RosterStatus.Available),
             Type                           = GetNodes.GetNodeValue(node, "type", ProtoCrewMember.KerbalType.Crew),
             VesselId                       = GetNodes.GetNodeValue(node, "vesselID", Guid.Empty),
             PartId                         = GetNodes.GetNodeValue(node, "partID", (uint)0),
             VesselName                     = GetNodes.GetNodeValue(node, "VesselName", " "),
             SeatIdx                        = GetNodes.GetNodeValue(node, "seatIdx", 0),
             SeatName                       = GetNodes.GetNodeValue(node, "seatName", ""),
             Age                            = GetNodes.GetNodeValue(node, "age", 25.0d),
             Lifespan                       = GetNodes.GetNodeValue(node, "lifespan", 75.0d),
             TimelastBirthday               = GetNodes.GetNodeValue(node, "timelastBirthday", lastUpdate),
             TimeDfFrozen                   = GetNodes.GetNodeValue(node, "timeDFFrozen", 0d),
             Salary                         = GetNodes.GetNodeValue(node, "salary", 0d),
             TimeSalaryDue                  = GetNodes.GetNodeValue(node, "timeSalaryDue", lastUpdate),
             Timelastsalary                 = GetNodes.GetNodeValue(node, "timelastsalary", lastUpdate),
             Notes                          = GetNodes.GetNodeValue(node, "notes", ""),
             SalaryContractDispute          = GetNodes.GetNodeValue(node, "salaryContractDispute", false),
             OwedSalary                     = GetNodes.GetNodeValue(node, "owedSalary", 0d),
             SalaryContractDisputePeriods   = GetNodes.GetNodeValue(node, "salaryContractDisputePeriods", 0),
             SalaryContractDisputeProcessed = GetNodes.GetNodeValue(node, "salaryContractDisputeProcessed", false),
             PayriseRequired                = GetNodes.GetNodeValue(node, "payriseRequired", 0d),
             Stupidity                      = GetNodes.GetNodeValue(node, "Stupidity", 0f),
             Courage                        = GetNodes.GetNodeValue(node, "Courage", 0f),
             Badass                         = GetNodes.GetNodeValue(node, "Badass", false),
             Trait                          = GetNodes.GetNodeValue(node, "Trait", "Pilot"),
             RealTrait                      = GetNodes.GetNodeValue(node, "RealTrait", "Pilot"),
             Gender                         = GetNodes.GetNodeValue(node, "Gender", ProtoCrewMember.Gender.Male),
             Skill                          = GetNodes.GetNodeValue(node, "Skill", 0),
             Experience                     = GetNodes.GetNodeValue(node, "Experience", 0f)
         };
         info.TimeNextBirthday = GetNodes.GetNodeValue(node, "timeNextBirthday", BirthdayNextDue(info.TimelastBirthday));
         return(info);
     }
     catch (Exception ex)
     {
         RmUtils.LogMessage("RosterManagerLifeSpan.RMKerbal Load error... " + ex, "Error", RMSettings.VerboseLogging);
         return(null);
     }
 }
Ejemplo n.º 7
0
        internal void UpdateKerbal(ProtoCrewMember crew, bool addifNotFound)
        {
            double currentTime = Planetarium.GetUniversalTime();
            //First find them in the internal Dictionary.
            KeyValuePair <string, RMKerbal> kerbal = RMLifeSpan.Instance.RMKerbals.AllrmKerbals.FirstOrDefault(a => a.Key == crew.name);

            //If not found and addifNotFound is true create a new entry
            if (kerbal.Value == null && addifNotFound)
            {
                RmUtils.LogMessage(
                    $"RosterManagerLifeSpanAddon.updateKerbal {crew.name} not found in ALLRMKerbals, adding new entry.", "info", RMSettings.VerboseLogging);
                RMKerbal rmkerbal = new RMKerbal(Planetarium.GetUniversalTime(), crew, true, false);
                RMLifeSpan.Instance.RMKerbals.AllrmKerbals.Add(crew.name, rmkerbal);
            }
            //If found update their entry
            else if (kerbal.Value != null)
            {
                if (!(currentTime - kerbal.Value.LastUpdate > RMSettings.LifeInfoUpdatePeriod))
                {
                    return;
                }
                RmUtils.LogMessage($"RosterManagerLifeSpanAddon.updateKerbal {crew.name} updating entry.", "info", RMSettings.VerboseLogging);
                if (RMLifeSpan.Instance.RMGameSettings.EnableAging)
                {
                    CheckAge(crew, kerbal, currentTime);
                }
                if (RMLifeSpan.Instance.RMGameSettings.EnableSalaries)
                {
                    //We only pay salaries to Crew or Dead/Unowned (frozen)
                    if (kerbal.Value.Type == ProtoCrewMember.KerbalType.Crew ||
                        kerbal.Value.Status == ProtoCrewMember.RosterStatus.Dead && kerbal.Value.Type == ProtoCrewMember.KerbalType.Unowned)
                    {
                        CheckSalary(crew, kerbal, currentTime);
                    }
                }
                kerbal.Value.LastUpdate = currentTime;
                kerbal.Value.Trait      = crew.trait;
                kerbal.Value.Type       = crew.type;
                kerbal.Value.Status     = crew.rosterStatus;
                if (crew.rosterStatus != ProtoCrewMember.RosterStatus.Available)
                {
                    return;
                }
                kerbal.Value.VesselId   = Guid.Empty;
                kerbal.Value.VesselName = string.Empty;
            }
        }
 internal void ResignKerbal(ProtoCrewMember crew, KeyValuePair <string, RMKerbal> kerbal)
 {
     Utilities.LogMessage("RosterManagerLifeSpanAddon.resignKerbal " + crew.name + " contract in dispute. They will remain a tourist until they are paid.", "info", RMSettings.VerboseLogging);
     ScreenMessages.PostScreenMessage(crew.name + " contract in dispute. They will remain a tourist until they are paid.", 5.0f, ScreenMessageStyle.UPPER_CENTER);
     //We don't change their status if they are unowned/dead (DeepFreeze Frozen)
     if (crew.type == ProtoCrewMember.KerbalType.Unowned || crew.rosterStatus == ProtoCrewMember.RosterStatus.Dead)
     {
         return;
     }
     RMKerbal.UnregisterExperienceTrait(kerbal.Value);
     //kerbal.Value.RealTrait = kerbal.Value.Trait;
     kerbal.Value.Type  = ProtoCrewMember.KerbalType.Tourist;
     crew.type          = ProtoCrewMember.KerbalType.Tourist;
     kerbal.Value.Trait = "Tourist";
     crew.trait         = "Tourist";
     KerbalRoster.SetExperienceTrait(crew, crew.trait);
     kerbal.Value.PayriseRequired = 0d;
     kerbal.Value.SalaryContractDisputeProcessed = true;
     kerbal.Value.SalaryContractDispute          = true;
 }
Ejemplo n.º 9
0
 private void CheckSalary(ProtoCrewMember crew, KeyValuePair <string, RMKerbal> kerbal, double currentTime)
 {
     if (currentTime >= kerbal.Value.TimeSalaryDue) // Salary Due??
     {
         //Set time next salary due
         kerbal.Value.TimeSalaryDue = RMKerbal.SalaryNextDue(currentTime);
         //Pay Salary
         if (HighLogic.CurrentGame.Mode != Game.Modes.CAREER)
         {
             return;
         }
         //Check if contractdispute is active and if it is process that
         if (kerbal.Value.SalaryContractDispute && kerbal.Value.SalaryContractDisputeProcessed)
         {
             //If they are a Tourist they are on strike. We don't process dispute.
             if (kerbal.Value.Type == ProtoCrewMember.KerbalType.Tourist)
             {
                 return;
             }
             ProcessContractDispute(crew, kerbal, currentTime, false, true);
         }
         else //No contract dispute so process normal salary.
         {
             if (Funding.CanAfford((float)kerbal.Value.Salary))
             {
                 Funding.Instance.AddFunds(-kerbal.Value.Salary, TransactionReasons.CrewRecruited);
                 kerbal.Value.Timelastsalary = currentTime;
                 RmUtils.LogMessage($"RosterManagerLifeSpanAddon.CheckSalary paid {crew.name} salary.", "info", RMSettings.VerboseLogging);
                 ScreenMessages.PostScreenMessage(
                     $"{crew.name} {Localizer.Format("#autoLOC_RM_1102")} {kerbal.Value.Salary}", 5.0f, ScreenMessageStyle.UPPER_CENTER); // #autoLOC_RM_1102 = Paid {0} salary of {1}
             }
             else //Unable to pay, start a contract dispute.
             {
                 if (!kerbal.Value.SalaryContractDispute && kerbal.Value.SalaryContractDisputeProcessed)
                 {
                     ProcessContractDispute(crew, kerbal, currentTime, true, true);
                 }
             }
         }
     }
 }
Ejemplo n.º 10
0
        internal void Load(ConfigNode node)
        {
            AllrmKerbals.Clear();

            if (node.HasNode(ConfigNodeName))
            {
                var kerbalLifeRecordNode = node.GetNode(ConfigNodeName);

                var kerbalNodes = kerbalLifeRecordNode.GetNodes(RMKerbal.ConfigNodeName);
                foreach (var kerbalNode in kerbalNodes)
                {
                    if (kerbalNode.HasValue("kerbalName"))
                    {
                        var id = kerbalNode.GetValue("kerbalName");
                        Utilities.LogMessage("RosterManagerLifeSpan.RMKerbals Loading kerbal = " + id, "info", RMSettings.VerboseLogging);
                        var kerballifeinfo = RMKerbal.Load(kerbalNode, id);
                        AllrmKerbals[id] = kerballifeinfo;
                    }
                }
            }
            Utilities.LogMessage("RosterManagerLifeSpan.RMKerbals Loading Completed", "info", RMSettings.VerboseLogging);
        }
Ejemplo n.º 11
0
        internal static void SaveSettings()
        {
            //If EnableAging has been turned ON when it was previously OFF, we reset age processing, otherwise they could all die instantly.
            if (RMLifeSpan.Instance.RMGameSettings.EnableAging && PrevEnableAging == false)
            {
                RmUtils.LogMessage("RosterManagerWindowSettings.Display Save settings, aging has been enabled. Reset all birthdays.", "info", RMSettings.VerboseLogging);
                double currentTime = Planetarium.GetUniversalTime();
                foreach (KeyValuePair <string, RMKerbal> rmkerbal in RMLifeSpan.Instance.RMKerbals.AllrmKerbals)
                {
                    rmkerbal.Value.TimelastBirthday = currentTime;
                    rmkerbal.Value.TimeNextBirthday = RMKerbal.BirthdayNextDue(currentTime);
                }
            }
            //If EnableSalaries has been turned OFF when it was previously ON, reset any kerbals from tourist back to active.
            if (!RMLifeSpan.Instance.RMGameSettings.EnableSalaries && PrevEnableSalaries)
            {
                RmUtils.LogMessage("RosterManagerWindowSettings.Display Save settings, salaries have been turned off. Reset all salary related fields for all kerbals.", "info", RMSettings.VerboseLogging);
                foreach (KeyValuePair <string, RMKerbal> rmkerbal in RMLifeSpan.Instance.RMKerbals.AllrmKerbals)
                {
                    if (rmkerbal.Value.Type == ProtoCrewMember.KerbalType.Tourist && rmkerbal.Value.Kerbal.rosterStatus != ProtoCrewMember.RosterStatus.Dead)
                    {
                        rmkerbal.Value.Type         = ProtoCrewMember.KerbalType.Crew;
                        rmkerbal.Value.Kerbal.type  = ProtoCrewMember.KerbalType.Crew;
                        rmkerbal.Value.Trait        = rmkerbal.Value.RealTrait;
                        rmkerbal.Value.Kerbal.trait = rmkerbal.Value.RealTrait;
                        KerbalRoster.SetExperienceTrait(rmkerbal.Value.Kerbal, rmkerbal.Value.Trait);
                        RMKerbal.RegisterExperienceTrait(rmkerbal.Value);
                    }
                    rmkerbal.Value.SalaryContractDispute          = false;
                    rmkerbal.Value.SalaryContractDisputePeriods   = 0;
                    rmkerbal.Value.SalaryContractDisputeProcessed = true;
                }
            }
            //If EnableSalaries has been turned ON when it was previously OFF, reset all kerbals salary time to now.
            if (RMLifeSpan.Instance.RMGameSettings.EnableSalaries && PrevEnableSalaries == false)
            {
                RmUtils.LogMessage("RosterManagerWindowSettings.Display Save settings, salaries have been turned on. Reset all salary related fields for all kerbals.", "info", RMSettings.VerboseLogging);
                double currentTime = Planetarium.GetUniversalTime();
                foreach (KeyValuePair <string, RMKerbal> rmkerbal in RMLifeSpan.Instance.RMKerbals.AllrmKerbals)
                {
                    rmkerbal.Value.Timelastsalary = currentTime;
                    rmkerbal.Value.TimeSalaryDue  = RMKerbal.SalaryNextDue(currentTime);
                }
            }
            if (Settings == null)
            {
                Settings = LoadSettingsFile();
            }

            ConfigNode windowsNode  = Settings.HasNode("RM_Windows") ? Settings.GetNode("RM_Windows") : Settings.AddNode("RM_Windows");
            ConfigNode settingsNode = Settings.HasNode("RM_Settings") ? Settings.GetNode("RM_Settings") : Settings.AddNode("RM_Settings");
            ConfigNode hiddenNode   = Settings.HasNode("RM_Hidden") ? Settings.GetNode("RM_Hidden") : Settings.AddNode("RM_Hidden");

            // Write window positions
            WriteRectangle(windowsNode, "DebuggerPosition", WindowDebugger.Position);
            WriteRectangle(windowsNode, "SettingsPosition", WindowSettings.Position);
            WriteRectangle(windowsNode, "RosterPosition", WindowRoster.Position);
            WriteRectangle(windowsNode, "ContractDisputePosition", WindowContracts.Position);

            //Write settings...
            // Realism Settings
            WriteValue(settingsNode, "LockSettings", LockSettings);

            // ToolTip Settings
            WriteValue(settingsNode, "ShowToolTips", ShowToolTips);
            WriteValue(settingsNode, "SettingsToolTips", WindowSettings.ShowToolTips);
            WriteValue(settingsNode, "RosterToolTips", WindowRoster.ShowToolTips);
            WriteValue(settingsNode, "DebuggerToolTips", WindowDebugger.ShowToolTips);
            WriteValue(settingsNode, "ContractDisputeToolTips", WindowContracts.ShowToolTips);

            // Config Settings
            WriteValue(settingsNode, "ShowDebugger", WindowDebugger.ShowWindow);
            WriteValue(settingsNode, "EnableBlizzyToolbar", EnableBlizzyToolbar);
            WriteValue(settingsNode, "VerboseLogging", VerboseLogging);
            WriteValue(settingsNode, "AutoDebug", AutoDebug);
            WriteValue(settingsNode, "DebugLogPath", DebugLogPath);
            WriteValue(settingsNode, "ErrorLogLength", ErrorLogLength);
            WriteValue(settingsNode, "SaveLogOnExit", SaveLogOnExit);
            WriteValue(settingsNode, "EnableKerbalRename", EnableKerbalRename);

            // Hidden Settings
            WriteValue(hiddenNode, "LifeInfoUpdatePeriod", LifeInfoUpdatePeriod);

            if (!Directory.Exists(SettingsPath))
            {
                Directory.CreateDirectory(SettingsPath);
            }
            Settings.Save(SettingsFile);
        }
        private void CheckAge(ProtoCrewMember crew, KeyValuePair <string, RMKerbal> kerbal, double currentTime)
        {
            //Calculate and update their age.
            //If they are DeepFreeze Frozen - They Don't Age, until they are thawed.
            if (Api.InstalledMods.IsDfInstalled)
            {
                if (crew.rosterStatus == ProtoCrewMember.RosterStatus.Dead && crew.type == ProtoCrewMember.KerbalType.Unowned)
                {
                    //Frozen - check if we are tracking when they were frozen, if not, set it to the time they were frozen
                    if (Math.Abs(kerbal.Value.TimeDfFrozen) < Tolerance)
                    {
                        if (RMAddon.FrozenKerbals.ContainsKey(crew.name))
                        {
                            kerbal.Value.TimeDfFrozen = RMAddon.FrozenKerbals[crew.name].lastUpdate;
                        }
                    }
                    return; //We don't process age any further if they are frozen.
                }
                if (crew.rosterStatus == ProtoCrewMember.RosterStatus.Dead && (crew.type != ProtoCrewMember.KerbalType.Unowned || crew.type != ProtoCrewMember.KerbalType.Tourist))
                {
                    //They are really dead. Should this ever occur? Just in case.
                    return;
                }
                //If we get here, they aren't frozen and they aren't really dead... so were they frozen?
                //IE: we know that if they are now crew, but their KerbalLifeInfo record has their status as dead and time frozen > 0
                if (crew.type == ProtoCrewMember.KerbalType.Crew && kerbal.Value.Status == ProtoCrewMember.RosterStatus.Dead && kerbal.Value.TimeDfFrozen > 0d)
                {
                    //We add the time they were frozen onto their time of last birthday - effectively extending their life.
                    var timeFrozen = currentTime - kerbal.Value.TimeDfFrozen; //The amount of time they were frozen
                    kerbal.Value.TimelastBirthday += timeFrozen;
                    kerbal.Value.TimeDfFrozen      = 0d;
                }
            }

            //Is it their Birthday?

            if (currentTime >= kerbal.Value.TimeNextBirthday)
            {
                //It's their Birthday!!!!
                kerbal.Value.Age += 1;
                kerbal.Value.TimelastBirthday = currentTime;
                kerbal.Value.TimeNextBirthday = RMKerbal.BirthdayNextDue(currentTime);
                if (kerbal.Value.Type != ProtoCrewMember.KerbalType.Applicant)
                {
                    ScreenMessages.PostScreenMessage("It's " + crew.name + " Birthday! They are now " + kerbal.Value.Age.ToString("###0"), 5.0f, ScreenMessageStyle.UPPER_CENTER);
                }
                Utilities.LogMessage("RosterManagerLifeSpanAddon.checkAge " + crew.name + " just had a birthday. They are now " + kerbal.Value.Age.ToString("###0"), "info", RMSettings.VerboseLogging);
            }

            //Check if they Die of Old Age
            if (!(kerbal.Value.Lifespan - 2 <= kerbal.Value.Age))
            {
                return;
            }
            int percentage;

            //Set random range based on:- if age is less than lifespan have 20% chance of death, if age is = or up to 2 years greater than lifespan have 40% chance of death.
            // if age is > than 2 years past lifespan have 60% chance of death. If age is > than 4 years past lifespan have 80% chance of death.
            if (kerbal.Value.Age < kerbal.Value.Lifespan)
            {
                percentage = 20;
            }
            else if (kerbal.Value.Lifespan + 2 < kerbal.Value.Age)
            {
                percentage = 40;
            }
            else if (kerbal.Value.Lifespan + 4 < kerbal.Value.Age)
            {
                percentage = 60;
            }
            else
            {
                percentage = 80;
            }
            if (_gen.Next(100) < percentage)
            {
                //Their Time has Come. As long as they aren't currently DeepFreeze Frozen/comatose
                if (crew.rosterStatus == ProtoCrewMember.RosterStatus.Dead ||
                    (crew.type == ProtoCrewMember.KerbalType.Unowned && crew.type == ProtoCrewMember.KerbalType.Tourist))
                {
                    return;
                }
                TimeWarp.SetRate(0, false);
                if (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA)
                {
                    CameraManager.Instance.SetCameraFlight();
                }
                Utilities.LogMessage("RosterManagerLifeSpanAddon.CheckAge " + crew.name + " died from old age.", "info", RMSettings.VerboseLogging);
                ScreenMessages.PostScreenMessage(crew.name + " died at the old age of " + kerbal.Value.Age.ToString("###0"), 5.0f, ScreenMessageStyle.UPPER_CENTER);

                if (crew.rosterStatus == ProtoCrewMember.RosterStatus.Assigned) //On active duty, need to find their vessel and remove them.
                {
                    var foundcrew = false;
                    //First try to find their assigned vessel and remove them.
                    if (kerbal.Value.VesselId != Guid.Empty)
                    {
                        var v = FlightGlobals.Vessels.FirstOrDefault(a => a.id == kerbal.Value.VesselId);
                        if (v != null)
                        {
                            if (v.loaded)
                            {
                                var part = v.Parts.Find(p => p.protoModuleCrew.Contains(crew));
                                if (part != null)
                                {
                                    part.RemoveCrewmember(crew);
                                    crew.Die();
                                    foundcrew = true;
                                }
                            }
                            else
                            {
                                var part = v.protoVessel.protoPartSnapshots.Find(p => p.protoModuleCrew.Contains(crew));
                                if (part != null)
                                {
                                    part.RemoveCrew(crew);
                                    crew.Die();
                                    foundcrew = true;
                                }
                            }
                        }
                    }
                    if (!foundcrew) //We didn't find their vessel and remove them so now search all vessels in game.
                    {
                        foreach (var v in FlightGlobals.Vessels)
                        {
                            if (v.isEVA && v.name.Contains(crew.name))
                            {
                                if (v.name.Contains(crew.name))
                                {
                                    v.rootPart.Die();
                                    foundcrew = true;
                                    break;
                                }
                            }
                            if (v.loaded)
                            {
                                var part = v.Parts.Find(p => p.protoModuleCrew.Contains(crew));
                                if (part == null)
                                {
                                    continue;
                                }
                                part.RemoveCrewmember(crew);
                                crew.Die();
                                foundcrew = true;
                                break;
                            }
                            else
                            {
                                var part = v.protoVessel.protoPartSnapshots.Find(p => p.protoModuleCrew.Contains(crew));
                                if (part == null)
                                {
                                    continue;
                                }
                                part.RemoveCrew(crew);
                                crew.Die();
                                foundcrew = true;
                                break;
                            }
                        }
                    }

                    if (!foundcrew) //We still didn't find them, log error and kill them anyway.
                    {
                        Utilities.LogMessage("RosterManagerLifeSpanAddon.CheckAge " + crew.name + " couldn't find them to remove them from vessel.", "Error", RMSettings.VerboseLogging);
                        crew.Die();
                    }
                }
                else //Not on active duty
                {
                    crew.Die();
                }

                //Remove from LifeSpan.Instance.kerbalLifeRecord.KerbalLifeRecords
                RemoveKerbal(crew);

                // set ReSpawn
                if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn)
                {
                    crew.StartRespawnPeriod();
                }
            }
        }