public void LegacyGetModifier_Base()
        {
            FactionValue factionValue = new FactionValue();

            factionValue.Name = "1";

            HumanDescriptionDef humanDescDef = new HumanDescriptionDef("-1", "Test", "FNAME", "LNAME", "CSIGN", Gender.Male, factionValue, 1, "foo", "");

            Traverse.Create(humanDescDef).Field("factionValue").SetValue(factionValue);
            Traverse.Create(humanDescDef).Field("factionID").SetValue("1");

            // gun, pilot, guts, tactics
            PilotDef pilotDefHigh = new PilotDef(humanDescDef, 10, 9, 8, 7, 0, 3, false, 0, "voice",
                                                 new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotHigh = new Pilot(pilotDefHigh, "-1", false);

            Assert.AreEqual(5, SkillUtils.GetGunneryModifier(pilotHigh));
            Assert.AreEqual(4, SkillUtils.GetPilotingModifier(pilotHigh));
            Assert.AreEqual(4, SkillUtils.GetGutsModifier(pilotHigh));
            Assert.AreEqual(3, SkillUtils.GetTacticsModifier(pilotHigh));

            PilotDef pilotDefMed = new PilotDef(humanDescDef, 7, 6, 5, 4, 0, 3, false, 0, "voice",
                                                new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotMed = new Pilot(pilotDefMed, "-1", false);

            Assert.AreEqual(3, SkillUtils.GetGunneryModifier(pilotMed));
            Assert.AreEqual(3, SkillUtils.GetPilotingModifier(pilotMed));
            Assert.AreEqual(2, SkillUtils.GetGutsModifier(pilotMed));
            Assert.AreEqual(2, SkillUtils.GetTacticsModifier(pilotMed));

            PilotDef pilotDefLog = new PilotDef(humanDescDef, 4, 3, 2, 1, 0, 3, false, 0, "voice",
                                                new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotLow = new Pilot(pilotDefLog, "-1", false);

            Assert.AreEqual(2, SkillUtils.GetGunneryModifier(pilotLow));
            Assert.AreEqual(1, SkillUtils.GetPilotingModifier(pilotLow));
            Assert.AreEqual(1, SkillUtils.GetGutsModifier(pilotLow));
            Assert.AreEqual(0, SkillUtils.GetTacticsModifier(pilotLow));
        }
        private static PilotDef GenerateCrew(StarSystem starSystem, string callsign, PilotDef pilotDef)
        {
            Mod.Log.Debug?.Write($"Generating support crew with callsign: {callsign}");

            // Generate the lifepath we'll use
            LifePath lifePath = LifePathHelper.GetRandomLifePath();

            int initialAge = ModState.SimGameState.Constants.Pilot.MinimumPilotAge +
                             ModState.SimGameState.NetworkRandom.Int(1, ModState.SimGameState.Constants.Pilot.StartingAgeRange + 1);
            int currentAge = Mod.Random.Next(initialAge, 70);

            Mod.Log.Debug?.Write($" - currentAge: {currentAge}");

            Gender newGender   = RandomGender();
            Gender voiceGender = newGender;

            if (voiceGender == Gender.NonBinary)
            {
                voiceGender = ((!(ModState.SimGameState.NetworkRandom.Float() < 0.5f)) ? Gender.Female : Gender.Male);
            }
            string voice        = RandomUnusedVoice(voiceGender);
            string newFirstName = ModState.CrewCreateState.NameGenerator.GetFirstName(newGender);
            string newLastName  = ModState.CrewCreateState.NameGenerator.GetLastName();

            Mod.Log.Debug?.Write($" - gender: {newGender}  voiceGender: {voiceGender}  firstName: {newFirstName}  lastName: {newLastName}");
            pilotDef.SetVoice(voice);

            StringBuilder lifepathDescParagraphs = new StringBuilder();
            string        backgroundTitle        = new Text(lifePath.Description.Title).ToString();
            string        backgroundDesc         = new Text(lifePath.Description.Description).ToString();
            // DETAILS string is EXTREMELY picky, see HumanDescriptionDef.GetLocalizedDetails. There format must be followed *exactly*
            string formattedBackground = $"{Environment.NewLine}<b>{backgroundTitle}:</b>  {backgroundDesc}";

            Mod.Log.Debug?.Write($" - Background: {formattedBackground}");
            lifepathDescParagraphs.Append(formattedBackground);

            // Add tags from the lifepath
            TagSet tagSet = new TagSet();

            tagSet.AddRange(lifePath.RequiredTags);

            foreach (string tag in lifePath.RandomTags)
            {
                double tagRoll = Mod.Random.NextDouble();
                if (tagRoll <= Mod.Config.HiringHall.LifePath.RandomTagChance)
                {
                    tagSet.Add(tag);
                }
            }
            Mod.Log.Debug?.Write($" - Tags: {String.Join(", ", tagSet)}");

            // Add tags to the background
            foreach (string tagId in tagSet)
            {
                Tag_MDD tagIfExists = MetadataDatabase.Instance.GetTagIfExists(tagId);
                if (tagIfExists != null)
                {
                    TagDataStruct tagStruct    = new TagDataStruct(tagId, tagIfExists.PlayerVisible, tagIfExists.Important, tagIfExists.Name, tagIfExists.FriendlyName, tagIfExists.Description);
                    string        formattedTag = $"<b><color=#ff8c00>{tagStruct.FriendlyName}:</b>  <color=#ffffff>{tagStruct.DescriptionTag}";
                    lifepathDescParagraphs.Append(formattedTag);
                }
            }

            string id = GenerateID();
            HumanDescriptionDef descriptionDef = new HumanDescriptionDef(id, callsign, newFirstName, newLastName, callsign, newGender,
                                                                         FactionEnumeration.GetNoFactionValue(), currentAge, lifepathDescParagraphs.ToString(), null);

            StatCollection statCollection = pilotDef.GetStats();
            int            spentXPPilot   = GetSpentXPPilot(statCollection);

            List <string> alreadyAssignedPortraits = new List <string>();

            if (ModState.SimGameState.Commander != null && ModState.SimGameState.Commander.pilotDef.PortraitSettings != null)
            {
                alreadyAssignedPortraits.Add(ModState.SimGameState.Commander.pilotDef.PortraitSettings.Description.Id);
            }
            foreach (Pilot activePilot in ModState.SimGameState.PilotRoster)
            {
                if (activePilot.pilotDef.PortraitSettings != null)
                {
                    alreadyAssignedPortraits.Add(activePilot.pilotDef.PortraitSettings.Description.Id);
                }
            }

            PilotDef pilotDef2 = new PilotDef(descriptionDef, pilotDef.BaseGunnery, pilotDef.BasePiloting, pilotDef.BaseGuts, pilotDef.BaseTactics, 0,
                                              ModState.SimGameState.CombatConstants.PilotingConstants.DefaultMaxInjuries, lethalInjury: false, 0, voice, pilotDef.abilityDefNames,
                                              AIPersonality.Undefined, 0, tagSet, spentXPPilot, 0)
            {
                DataManager      = ModState.SimGameState.DataManager,
                PortraitSettings = GetPortraitForGenderAndAge(voiceGender, currentAge, alreadyAssignedPortraits)
            };

            ModState.SimGameState.pilotGenCallsignDiscardPile.Add(pilotDef2.Description.Callsign);

            return(pilotDef2);
        }
        public void LegacyGetModifier_Abilities()
        {
            AbilityDef gutsDef8 = new AbilityDef();

            Traverse.Create(gutsDef8).Property("Description").SetValue(new BaseDescriptionDef("AbilityDefG8", "ABC", "DEF", "-1"));
            AbilityDef gutsDef5 = new AbilityDef();

            Traverse.Create(gutsDef5).Property("Description").SetValue(new BaseDescriptionDef("AbilityDefG5", "ABC", "DEF", "-1"));

            FactionValue factionValue = new FactionValue();

            factionValue.Name = "1";

            HumanDescriptionDef humanDescDef = new HumanDescriptionDef("-1", "Test", "FNAME", "LNAME", "CSIGN", Gender.Male, factionValue, 1, "foo", "");

            Traverse.Create(humanDescDef).Field("factionValue").SetValue(factionValue);
            Traverse.Create(humanDescDef).Field("factionID").SetValue("1");

            // gun, pilot, guts, tactics
            PilotDef pilotDefHigh = new PilotDef(humanDescDef, 10, 9, 8, 7, 0, 3, false, 0, "voice",
                                                 new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotHigh = new Pilot(pilotDefHigh, "-1", false);

            Traverse.Create(pilotHigh).Property("Abilities").SetValue(new List <Ability>());

            pilotHigh.Abilities.Add(new Ability(gutsDef8));
            pilotHigh.Abilities.Add(new Ability(gutsDef5));

            Assert.AreEqual(7, SkillUtils.GetGunneryModifier(pilotHigh));
            Assert.AreEqual(4, SkillUtils.GetPilotingModifier(pilotHigh));
            Assert.AreEqual(4, SkillUtils.GetGutsModifier(pilotHigh));
            Assert.AreEqual(3, SkillUtils.GetTacticsModifier(pilotHigh));

            PilotDef pilotDefMed = new PilotDef(humanDescDef, 7, 6, 5, 4, 0, 3, false, 0, "voice",
                                                new List <string>()
            {
                "AbilityDefG5"
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotMed = new Pilot(pilotDefMed, "-1", false);

            Traverse.Create(pilotMed).Property("Abilities").SetValue(new List <Ability>());

            pilotMed.Abilities.Add(new Ability(gutsDef5));

            Assert.AreEqual(4, SkillUtils.GetGunneryModifier(pilotMed));
            Assert.AreEqual(3, SkillUtils.GetPilotingModifier(pilotMed));
            Assert.AreEqual(2, SkillUtils.GetGutsModifier(pilotMed));
            Assert.AreEqual(2, SkillUtils.GetTacticsModifier(pilotMed));

            PilotDef pilotDefLog = new PilotDef(humanDescDef, 4, 3, 2, 1, 0, 3, false, 0, "voice",
                                                new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotLow = new Pilot(pilotDefLog, "-1", false);

            Assert.AreEqual(2, SkillUtils.GetGunneryModifier(pilotLow));
            Assert.AreEqual(1, SkillUtils.GetPilotingModifier(pilotLow));
            Assert.AreEqual(1, SkillUtils.GetGutsModifier(pilotLow));
            Assert.AreEqual(0, SkillUtils.GetTacticsModifier(pilotLow));
        }
        public void GetModifier_Abilities()
        {
            Dictionary <int, int> modifiersForSkill = new Dictionary <int, int>()
            {
                { 1, 5 }, { 2, 10 }, { 3, 15 }, { 4, 20 }, { 5, 25 }, { 6, 30 }, { 7, 35 }, { 8, 40 }, { 9, 45 }, { 10, 50 },
                { 11, 55 }, { 12, 60 }, { 13, 65 }, { 14, 70 }, { 15, 75 }, { 16, 80 }, { 17, 85 }, { 18, 90 }, { 19, 95 }, { 20, 100 },
            };
            float abilityMulti = 1.5f;

            AbilityDef gutsDef8 = new AbilityDef();

            Traverse.Create(gutsDef8).Property("Description").SetValue(new BaseDescriptionDef("AbilityDefG8", "ABC", "DEF", "-1"));
            AbilityDef gutsDef5 = new AbilityDef();

            Traverse.Create(gutsDef5).Property("Description").SetValue(new BaseDescriptionDef("AbilityDefG5", "ABC", "DEF", "-1"));

            FactionValue factionValue = new FactionValue();

            factionValue.Name = "1";

            HumanDescriptionDef humanDescDef = new HumanDescriptionDef("-1", "Test", "FNAME", "LNAME", "CSIGN", Gender.Male, factionValue, 1, "foo", "");

            Traverse.Create(humanDescDef).Field("factionValue").SetValue(factionValue);
            Traverse.Create(humanDescDef).Field("factionID").SetValue("1");

            // gun, pilot, guts, tactics
            PilotDef pilotDefHigh = new PilotDef(humanDescDef, 10, 9, 8, 7, 0, 3, false, 0, "voice",
                                                 new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotHigh = new Pilot(pilotDefHigh, "-1", false);

            Traverse.Create(pilotHigh).Property("Abilities").SetValue(new List <Ability>());

            pilotHigh.Abilities.Add(new Ability(gutsDef8));
            pilotHigh.Abilities.Add(new Ability(gutsDef5));

            Assert.AreEqual(53,
                            SkillUtils.GetModifier(pilotHigh, pilotHigh.Gunnery, modifiersForSkill, new List <string>()
            {
                "AbilityDefG5", "AbilityDefG8"
            }, abilityMulti)
                            );
            Assert.AreEqual(45,
                            SkillUtils.GetModifier(pilotHigh, pilotHigh.Piloting, modifiersForSkill, new List <string>()
            {
                "AbilityDefP5", "AbilityDefP8"
            }, abilityMulti)
                            );
            Assert.AreEqual(40,
                            SkillUtils.GetModifier(pilotHigh, pilotHigh.Guts, modifiersForSkill, new List <string>()
            {
                "AbilityDefGu5", "AbilityDefGu8"
            }, abilityMulti)
                            );
            Assert.AreEqual(35,
                            SkillUtils.GetModifier(pilotHigh, pilotHigh.Tactics, modifiersForSkill, new List <string>()
            {
                "AbilityDefT5A", "AbilityDefT8A"
            }, abilityMulti)
                            );

            PilotDef pilotDefMed = new PilotDef(humanDescDef, 7, 6, 5, 4, 0, 3, false, 0, "voice",
                                                new List <string>()
            {
                "AbilityDefG5"
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotMed = new Pilot(pilotDefMed, "-1", false);

            Traverse.Create(pilotMed).Property("Abilities").SetValue(new List <Ability>());

            pilotMed.Abilities.Add(new Ability(gutsDef5));

            Assert.AreEqual(37,
                            SkillUtils.GetModifier(pilotMed, pilotMed.Gunnery, modifiersForSkill, new List <string>()
            {
                "AbilityDefG5", "AbilityDefG8"
            }, abilityMulti)
                            );
            Assert.AreEqual(30,
                            SkillUtils.GetModifier(pilotMed, pilotMed.Piloting, modifiersForSkill, new List <string>()
            {
                "AbilityDefP5", "AbilityDefP8"
            }, abilityMulti)
                            );
            Assert.AreEqual(25,
                            SkillUtils.GetModifier(pilotMed, pilotMed.Guts, modifiersForSkill, new List <string>()
            {
                "AbilityDefGu5", "AbilityDefGu8"
            }, abilityMulti)
                            );
            Assert.AreEqual(20,
                            SkillUtils.GetModifier(pilotMed, pilotMed.Tactics, modifiersForSkill, new List <string>()
            {
                "AbilityDefT5A", "AbilityDefT8A"
            }, abilityMulti)
                            );

            PilotDef pilotDefLog = new PilotDef(humanDescDef, 4, 3, 2, 1, 0, 3, false, 0, "voice",
                                                new List <string>()
            {
            }, AIPersonality.Undefined, 0, 0, 0);
            Pilot pilotLow = new Pilot(pilotDefLog, "-1", false);

            Assert.AreEqual(20,
                            SkillUtils.GetModifier(pilotLow, pilotLow.Gunnery, modifiersForSkill, new List <string>()
            {
                "AbilityDefG5", "AbilityDefG8"
            }, abilityMulti)
                            );
            Assert.AreEqual(15,
                            SkillUtils.GetModifier(pilotLow, pilotLow.Piloting, modifiersForSkill, new List <string>()
            {
                "AbilityDefP5", "AbilityDefP8"
            }, abilityMulti)
                            );
            Assert.AreEqual(10,
                            SkillUtils.GetModifier(pilotLow, pilotLow.Guts, modifiersForSkill, new List <string>()
            {
                "AbilityDefGu5", "AbilityDefGu8"
            }, abilityMulti)
                            );
            Assert.AreEqual(5,
                            SkillUtils.GetModifier(pilotLow, pilotLow.Tactics, modifiersForSkill, new List <string>()
            {
                "AbilityDefT5A", "AbilityDefT8A"
            }, abilityMulti)
                            );
        }
            public static bool Prefix(HumanDescriptionDef __instance, ref Text __result)
            {
                var instance = __instance;

                if (instance.Details == null)
                {
                    __result = new Text();
                    return(false);
                }
                if (instance.GetLocalizedDetails() != null && (bool)AccessTools.Field(typeof(BaseDescriptionDef), "detailsParsed").GetValue(instance))
                {
                    __result = instance.GetLocalizedDetails();
                    return(false);
                }
                Text text = new Text();

                if (instance.isGenerated)
                {
                    string[] strArray = instance.Details.Split(new string[4]
                    {
                        Environment.NewLine,
                        "<b>",
                        ":</b>",
                        "\n\n"
                    }, StringSplitOptions.RemoveEmptyEntries);
                    // pad the array length to make it even
                    if (strArray.Length % 2 != 0)
                    {
                        Array.Resize(ref strArray, strArray.Length + 1);
                    }
                    int index = 0;
                    while (index < strArray.Length)
                    {
                        text.Append("<b>{0}:</b> {1}\n\n", (object[])new string[2]
                        {
                            strArray[index],
                            strArray[index + 1]
                        });
                        index += 2;
                    }
                }
                else if (instance.isCommander)
                {
                    string   details   = instance.Details;
                    string[] separator = new string[1]
                    {
                        Environment.NewLine
                    };
                    int num = 1;
                    foreach (object obj in details.Split(separator, (StringSplitOptions)num))
                    {
                        text.Append("{0} \n\n", obj);
                    }
                }
                else
                {
                    text.Append(instance.Details, new object[0]);
                }
                AccessTools.Field(typeof(BaseDescriptionDef), "detailsParsed").SetValue(instance, true);
                AccessTools.Field(typeof(BaseDescriptionDef), "detailsParsed").SetValue(instance, text);
                __result = text;
                return(false);
            }