Example #1
0
        private static void LoadVehicleDefs()
        {
            try {
                if (planeDefs != null)
                {
                    return;
                }
                planeDefs = new Dictionary <GeoVehicleDef, VehicleItemDef>(3);
                tankDefs  = new Dictionary <TacUnitClassDef, GroundVehicleItemDef>(3);

                Verbo("Loading vehicles for scrap screen");
                DefRepository defRepo = GameUtl.GameComponent <DefRepository>();
                foreach (BaseDef def in defRepo.GetAllDefs <ItemDef>())
                {
                    if (def is GroundVehicleItemDef tankDef)
                    {
                        TacUnitClassDef chrDef = tankDef.VehicleClassDef;
                        if (chrDef != null && (chrDef.IsVehicle || chrDef.IsMutog))
                        {
                            tankDefs[chrDef] = tankDef;
                        }
                    }
                    else if (def is VehicleItemDef planeDef)
                    {
                        GeoVehicleDef vDef = planeDef.ComponentSetDef?.GetComponentDef <GeoVehicleDef>();
                        if (vDef != null)
                        {
                            planeDefs[vDef] = planeDef;
                        }
                    }
                }
                Verbo("Mapped {0} types of airplanes, {1} types of tanks", planeDefs.Count, tankDefs.Count);
            } catch (Exception ex) { Error(ex); }
        }
Example #2
0
 private static TacticalItemDef FindTacItem(string key)
 {
     if (Repo == null)
     {
         Repo = GameUtl.GameComponent <DefRepository>();
     }
     return(Repo.GetDef(key) as TacticalItemDef ?? Repo.GetAllDefs <TacticalItemDef>().FirstOrDefault(e => e.name == key));
 }
        /// <summary>
        /// Called very early, just after main assemblies are loaded, before logos. Saves have not been scanned and most game data are unavailable.
        /// Full info at https://github.com/Sheep-y/Modnix/wiki/DLL-Specs#SplashMod
        /// </summary>
        /// <param name="api">First param (string) is the query/action. Second param (object) and result (object) varies by action.</param>
        public void SplashMod(ModnixCallback api = null)
        {
            // Technically, SplashMod isn't the right place to init this mod. However, it ensures a VERY
            // early load, and it doesn't cause any issues. This means PPDefModifier can modify it.
            harmInst = HarmonyInstance.Create(typeof(MyMod).FullName);
            harmInst.PatchAll();
            FileLog.logPath = "./Mods/PPWB_Harmony.log";
            FileLog.Log("PPWB...");
            BasicUtil.EnsureAPI(ref api);
            BasicUtil.GetConfig(ref Config, api);
            storedAPI = api;

            DefRepository definitions_repo = GameUtl.GameComponent<DefRepository>();
            List<WeaponDef> WeaponList = definitions_repo.GetAllDefs<WeaponDef>().ToList();
            List<DamageKeywordDef> damageKeywords = definitions_repo.GetAllDefs<DamageKeywordDef>().ToList();

            BasicUtil.Log($"Found {WeaponList.Count} weapons loaded into the game.", api);
            BasicUtil.Log($"Found {damageKeywords.Count} damage types loaded into the game.", api);

            #region DamageTypeSetup
            List<DamageKeywordPair> damageKeywordPairsToAdd = new List<DamageKeywordPair>();
            if (Config.add_bleed) {
                damageKeywordPairsToAdd.Add(new DamageKeywordPair() {
                    Value = 0,
                    DamageKeywordDef = damageKeywords.Find(x => x.name.Contains("Bleed"))
                });
            }
            if (Config.add_pierce) {
                damageKeywordPairsToAdd.Add(new DamageKeywordPair() {
                    Value = 0,
                    DamageKeywordDef = damageKeywords.Find(x => x.name.Contains("Pierc")) // Because it's truncated "Piercing"
                });
            }
            if (Config.add_shred) {
                damageKeywordPairsToAdd.Add(new DamageKeywordPair() {
                    Value = 0,
                    DamageKeywordDef = damageKeywords.Find(x => x.name.Contains("Shred"))
                });
            };
            #endregion

            BasicUtil.Log("Adding damage types to all weapons.", api);
            foreach (WeaponDef weapon in WeaponList) {
                foreach (DamageKeywordPair dkp in damageKeywordPairsToAdd) {
                    if (!weapon.DamagePayload.DamageKeywords.Exists(x => x.DamageKeywordDef == dkp.DamageKeywordDef)) {
                        weapon.DamagePayload.DamageKeywords.Add(dkp.Clone());
#if DEBUG
                        BasicUtil.Log($"Had to add damage type {dkp.DamageKeywordDef.Visuals.DisplayName1.Localize()} to {weapon.GetDisplayName().Localize()}", api);
#endif
                    }
                }
                weapon.DamagePayload.DamageKeywords.Sort( (x, y) => x.CompareTo(y));
            }

            BasicUtil.Log("Done adding damage types.", api);
        }
Example #4
0
 private static bool CreateCache()
 {
     lock ( ByType ) {
         if (Repo != null)
         {
             return(false);
         }
         Verbo("Building BaseDef cache");
         Repo = GameUtl.GameComponent <DefRepository>();
         ByType[typeof(BaseDef)] = new List <BaseDef>(AllDefs);
         ByName = new SimpleCache();
         ByPath = new SimpleCache();
         foreach (var def in AllDefs)
         {
             AddToCache(def);
         }
         Info("Built cache from {0} BaseDef", ByType[typeof(BaseDef)].Count);
         return(true);
     }
 }
Example #5
0
        //make list of skills to choose from
        internal static (List <TacticalAbilityDef>, int) SelectSkills(string soldierSpec, DefRepository defRep)
        {
            List <TacticalAbilityDef> skillList = new List <TacticalAbilityDef>();
            int classStat = 0;

            try
            {
                IDictionary <string, int> skills         = GetClassDictionary(soldierSpec);
                List <TacticalAbilityDef> viewEAbilities = (from p in defRep.GetAllDefs <TacticalAbilityDef>()
                                                            where p.ViewElementDef != null && p.CharacterProgressionData != null
                                                            select p).ToList();

                var skillsV = from p in skills
                              orderby p.Value ascending
                              select p;

                foreach (var sk in skillsV)
                {
                    if (sk.Value > 0 && sk.Key != "ClassAllowed" && sk.Key != "ClassStatic")
                    {
                        bool found = false;
                        foreach (var vEA in viewEAbilities)
                        {
                            if ((string.Equals(vEA.name, sk.Key, StringComparison.OrdinalIgnoreCase) || string.Equals(vEA.ViewElementDef.DisplayName1.LocalizeEnglish(), sk.Key, StringComparison.OrdinalIgnoreCase)) && !found)
                            {
                                skillList.Add(vEA);
                                found = true;
                            }
                        }
                        if (!found)
                        {
                            Logger.Debug($"Ability: {sk.Key}  was not found in AbilityDef and was not added to list!");
                        }
                    }
                    else if (sk.Key == "ClassStatic")
                    {
                        classStat = sk.Value;
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e);
            }
            return(skillList, classStat);
        }
        internal static Dictionary <int, TacticalAbilityDef> GeneratePersonalTraits(int abilitiesCount, LevelProgressionDef levelDef, SpecializationDef soldierSpec, DefRepository defRepo, List <TacticalAbilityDef> personalAbilityPool)
        {
            try
            {
                Logger.Info($"Specialization for soldier is: {soldierSpec.ViewElementDef.DisplayName1.LocalizeEnglish()}");

                Dictionary <int, TacticalAbilityDef> dictionary = new Dictionary <int, TacticalAbilityDef>(); //dictionary to return
                List <TacticalAbilityDef>            tmpList    = new List <TacticalAbilityDef>();
                List <int> availableSlots = new List <int>();                                                 //slots to fill with skills

                for (int i = 0; i < levelDef.MaxLevel; i++)
                {
                    availableSlots.Add(i);
                }

                (List <TacticalAbilityDef> skills, int classStat) = Support.SelectSkills(soldierSpec.name, defRepo);

                if (skills.IsEmpty())
                {
                    skills = personalAbilityPool;
                    Logger.Info($"SelectSkills returned no skills!");
                }

                if (skills.Count < abilitiesCount && personalAbilityPool.Count > 0 && !SelectClassTraits.Settings.LeaveEmpty) //if not enough skills and LeavyEmpty is not true, fill up from personalanilitypool
                {
                    List <TacticalAbilityDef> tmpList2 = new List <TacticalAbilityDef>();

                    foreach (var skl in skills) //check if some skills in personalabilitypool already are in skills and remove them
                    {
                        if (personalAbilityPool.Contains(skl))
                        {
                            tmpList2.Add(skl);
                            personalAbilityPool.Remove(skl);
                        }
                    }

                    while (skills.Count < abilitiesCount && personalAbilityPool.Count > 0) //fill up with random skills
                    {
                        TacticalAbilityDef rando = personalAbilityPool.GetRandomElement();
                        tmpList2.Add(rando);
                        skills.Add(rando);
                        personalAbilityPool.Remove(rando);
                    }

                    personalAbilityPool.AddRange(tmpList2);
                }

                if (classStat != 1) //if class is not static generate skills randomly
                {
                    int num = 0;
                    while (num < abilitiesCount && skills.Count > 0)
                    {
                        TacticalAbilityDef randomElement = skills.GetRandomElement();
                        if (randomElement != null)
                        {
                            skills.Remove(randomElement);
                            tmpList.Add(randomElement);
                            int slot = availableSlots.GetRandomElement();

                            Logger.Info($"GeneratePersonalAbilities slot: {slot}   ability: {randomElement.ViewElementDef.DisplayName1.Localize()}");

                            availableSlots.Remove(slot);

                            dictionary.Add(slot, randomElement);
                            num++;
                        }
                        else
                        {
                            throw new NullReferenceException("skills list returned no TacticalAbilityDef");
                        }
                    }
                }
                else //if static just copy
                {
                    Logger.Info("Class is static:");
                    for (int i = 0; i < skills.Count && i < abilitiesCount; i++)
                    {
                        dictionary.Add(availableSlots[i], skills[i]);
                        Logger.Info($"i: {i}   slot: {availableSlots[i]}   skill: {skills[i].ViewElementDef.DisplayName1.LocalizeEnglish()}");
                    }
                }

                return(dictionary);
            }
            catch (Exception e)
            {
                Logger.Error(e);
                return(null);
            }
        }
Example #7
0
            public static bool Prefix(ref GeoUnitDescriptor __result, GeoFaction faction, TacCharacterDef template, BaseStatSheetDef ___BaseStatsSheet, DefRepository ____defRepo, List <TacticalAbilityDef> ____personalAbilityPool)
            {
                try
                {
                    if (template == null)
                    {
                        throw new Exception("Missing template for character");
                    }

                    GeoUnitDescriptor geoUnitDescriptor = new GeoUnitDescriptor(faction, new GeoUnitDescriptor.UnitTypeDescriptor(template));
                    GeoUnitDescriptor.ProgressionDescriptor progressionDescriptor = null;

                    foreach (ClassTagDef classTag in template.ClassTags)
                    {
                        SpecializationDef specializationByClassTag = Support.GetSpecializationByClassTag(classTag, ____defRepo.GetAllDefs <SpecializationDef>().ToList());

                        if (specializationByClassTag != null)
                        {
                            if (progressionDescriptor == null)
                            {
                                Dictionary <int, TacticalAbilityDef> personalAbilitiesByLevel = AbilityGen.GeneratePersonalTraits(___BaseStatsSheet.PersonalAbilitiesCount, template.Data.LevelProgression.Def, specializationByClassTag, ____defRepo, ____personalAbilityPool);
                                progressionDescriptor = new GeoUnitDescriptor.ProgressionDescriptor(specializationByClassTag, personalAbilitiesByLevel);
                            }
                            else
                            {
                                progressionDescriptor.SecondarySpecDef = specializationByClassTag;
                            }
                        }
                    }
                    if (progressionDescriptor != null && template.Data.LevelProgression.IsValid)
                    {
                        progressionDescriptor.Level = template.Data.LevelProgression.Level;
                        progressionDescriptor.ExtraAbilities.AddRange(template.Data.Abilites);
                    }
                    if (progressionDescriptor != null)
                    {
                        geoUnitDescriptor.Progression = progressionDescriptor;
                    }
                    geoUnitDescriptor.BonusStats = template.Data.BonusStats;
                    geoUnitDescriptor.ArmorItems.AddRange(template.Data.BodypartItems.OfType <TacticalItemDef>());
                    geoUnitDescriptor.Equipment.AddRange(template.Data.EquipmentItems.OfType <TacticalItemDef>());
                    geoUnitDescriptor.Inventory.AddRange(template.Data.InventoryItems.OfType <TacticalItemDef>());
                    __result = geoUnitDescriptor;

                    return(false);
                }
                catch (Exception e)
                {
                    Logger.Error(e);
                    return(true);
                }
            }
Example #8
0
 public PPDefRepository(DefRepository repo)
 {
     this.repo = repo;
 }
Example #9
0
        /// <summary>
        /// Called after basic assets are loaded, before the hottest year cinematic. Virtually the same time as PPML.
        /// Full info at https://github.com/Sheep-y/Modnix/wiki/DLL-Specs#MainMod
        /// </summary>
        /// <param name="api">First param (string) is the query/action. Second param (object) and result (object) varies by action.</param>
        public static void MainMod(ModnixCallback api = null)
        {
            BasicUtil.EnsureAPI(ref api);
            BasicUtil.GetConfig(ref Config, api);

            api("log info", "New MainMod initialized");
            DefRepository gameRootDef = GameUtl.GameComponent <DefRepository>();

            List <TacticalItemDef> tacticalItems = gameRootDef.GetAllDefs <TacticalItemDef>().ToList().FindAll(
                new Predicate <TacticalItemDef>(FilterDefList)
                );

            BasicUtil.Log($"Readied {tacticalItems.Count} Independent tactical items.", api);

            string guid = "";

            I2.Loc.LanguageSourceData langDB = I2.Loc.LocalizationManager.Sources[0];
            int englishKey = langDB.GetLanguageIndex("English");

            foreach (ItemDef item in tacticalItems)
            {
                bool isWeapon = item.GetType() == typeof(WeaponDef);
#if DEBUG
                BasicUtil.Log($"Making Reverse Engineer for: {item.GetDisplayName().Localize()} - {item}", api);
#endif
                ResearchTagDef optional              = (ResearchTagDef)gameRootDef.GetDef("08191866-ff38-9e74-abd7-cb484188911a");
                GeoFactionDef  PhoenixPointFaction   = (GeoFactionDef)gameRootDef.GetDef("8be7e872-0ad2-a2a4-7bee-c980ed304a8a");
                GeoFactionDef  DisciplesOfAnuFaction = (GeoFactionDef)gameRootDef.GetDef("edc6783a-be00-1a84-2b97-2fe1e0fc5448");
                GeoFactionDef  NewJerichoFaction     = (GeoFactionDef)gameRootDef.GetDef("d31c78b9-ff0e-8b94-ab96-9672da73da54");
                GeoFactionDef  SynedrionFaction      = (GeoFactionDef)gameRootDef.GetDef("0e6dc218-e157-5954-c9ab-1a0606e0d914");

                // 1 + length of compatible ammo list
                int       researchUnlockLength = 1 + ((isWeapon) ? ((WeaponDef)item).CompatibleAmmunition.Length : 0);
                ItemDef[] researchUnocks       = new ItemDef[researchUnlockLength];
                researchUnocks[0] = item;
                for (int i = 1; i < researchUnlockLength; i++)
                {
                    researchUnocks[i] = ((WeaponDef)item).CompatibleAmmunition[i - 1];
                }

                string[] guidparts = item.Guid.Split('-');
                string   guidBase  = string.Join("-", guidparts.Take(3));
                string   guidTail  = "deadbeefbabe";
                int      typeInt;

                #region Generate reverse engineering def
                typeInt = (int)ResearchGUIDSegments.ReceiveItemResearchRequirement;
                ReceiveItemResearchRequirementDef rirrDef = ScriptableObject.CreateInstance <ReceiveItemResearchRequirementDef>();
                rirrDef.name    = item.name + "_ReceiveItemResearchRequirementDef";
                rirrDef.Guid    = $"{guidBase}-{typeInt:x4}-{guidTail}";
                rirrDef.ItemDef = item;

                typeInt = (int)ResearchGUIDSegments.ItemResearchCost;
                string I2Key = $"REVERSE_ENGINEER_COSTDEF_{item.name}";
                ItemResearchCostDef ircDef = ScriptableObject.CreateInstance <ItemResearchCostDef>();
                ircDef.name             = item.name + "_ItemResearchCostDef";
                ircDef.Guid             = $"{guidBase}-{typeInt:x4}-{guidTail}";
                ircDef.ItemDef          = item;
                ircDef.Amount           = 1;
                ircDef.LocalizationText = new Base.UI.LocalizedTextBind()
                {
                    LocalizationKey = I2Key
                };
                langDB.AddTerm($"REVERSE_ENGINEER_COSTDEF_{item.name}", I2.Loc.eTermType.Text);
                langDB.GetTermData(I2Key).Languages[englishKey] = "Needed items {0}/{1}";

                typeInt = (int)ResearchGUIDSegments.ManufactureResearchReward;
                ManufactureResearchRewardDef mrdDef = ScriptableObject.CreateInstance <ManufactureResearchRewardDef>();
                mrdDef.name  = item.name + "_ManufactureResearchRewardDef";
                mrdDef.Guid  = $"{guidBase}-{typeInt:x4}-{guidTail}";
                mrdDef.Items = researchUnocks;

                typeInt = (int)ResearchGUIDSegments.Research;
                string      rName = item.name + "_ResearchDef";
                ResearchDef reverseEngineerDef = ScriptableObject.CreateInstance <ResearchDef>();
                reverseEngineerDef.name             = rName;
                reverseEngineerDef.Guid             = $"{guidBase}-{typeInt:X4}-{guidTail}";
                reverseEngineerDef.Id               = rName;
                reverseEngineerDef.Faction          = PhoenixPointFaction;
                reverseEngineerDef.Costs            = new ResearchCostDef[] { ircDef };
                reverseEngineerDef.ResearchCost     = 100;
                reverseEngineerDef.Tags             = new ResearchTagDef[] { optional };
                reverseEngineerDef.ValidForFactions = new List <GeoFactionDef> {
                    PhoenixPointFaction
                };
                reverseEngineerDef.Unlocks       = new ResearchRewardDef[] { mrdDef };
                reverseEngineerDef.InitialStates = new ResearchDef.InitialResearchState[] {
                    new ResearchDef.InitialResearchState {
                        Faction = PhoenixPointFaction,
                        State   = ResearchState.Hidden
                    },
                    new ResearchDef.InitialResearchState {
                        Faction = DisciplesOfAnuFaction,
                        State   = ResearchState.Hidden
                    },
                    new ResearchDef.InitialResearchState {
                        Faction = NewJerichoFaction,
                        State   = ResearchState.Hidden
                    },
                    new ResearchDef.InitialResearchState {
                        Faction = SynedrionFaction,
                        State   = ResearchState.Hidden
                    }
                };
                reverseEngineerDef.RevealRequirements.Container = new ReseachRequirementDefOpContainer[] {
                    new ReseachRequirementDefOpContainer()
                    {
                        Operation    = ResearchContainerOperation.ALL,
                        Requirements = new ResearchRequirementDef[] {
                            rirrDef
                        }
                    }
                };
#if DEBUG
                BasicUtil.Log($"{researchUnocks.Length} items prepared for the rDef.", api);
                BasicUtil.Log(ircDef.LocalizationText.Localize(), api);
#if NOISY
                BasicUtil.Log(reverseEngineerDef.Repr(), api);
#endif
#endif
                #endregion
                gameRootDef.CreateRuntimeDef(rirrDef, rirrDef.GetType(), rirrDef.Guid);
                gameRootDef.CreateRuntimeDef(ircDef, ircDef.GetType(), ircDef.Guid);
                gameRootDef.CreateRuntimeDef(mrdDef, mrdDef.GetType(), mrdDef.Guid);
                gameRootDef.CreateRuntimeDef(reverseEngineerDef, guid: reverseEngineerDef.Guid);
                guid = reverseEngineerDef.Guid;
            }
#if DEBUG
            foreach (GeoFactionDef fact in gameRootDef.GetAllDefs <GeoFactionDef>().ToList())
            {
                BasicUtil.Log(fact.Render(), api);
            }
            BasicUtil.Log($"Looking for GUID: {guid}", api);
            DefRepository temp = GameUtl.GameComponent <DefRepository>();
            ResearchDef   rDef = (ResearchDef)temp.GetDef(guid);
            BasicUtil.Log(rDef.name, api);
            BasicUtil.Log(rDef.Guid, api);
            BasicUtil.Log(rDef.Costs[0].Guid, api);
            BasicUtil.Log(rDef.Unlocks[0].Guid, api);
            BasicUtil.Log(rDef.RevealRequirements.Container[0].Requirements[0].Guid, api);

            BasicUtil.Log(
                rDef.Repr(),
                api);
            BasicUtil.Log(
                // Reverse Engineering example
                ((ResearchDef)temp.GetDef("15d2170b-469b-0341-22d4-a8b4d90eefb8")).Repr(),
                api);
#if COMPAREMANY
            BasicUtil.Log(
                // Capture research
                ((ResearchDef)temp.GetDef("c7b3f8ab-8c90-0343-823b-c966d2c4edb8")).Repr(),
                api);
            BasicUtil.Log(
                // Research that rewards multiple resources
                temp.GetAllDefs <ResearchDef>().ToList().Find(x => x.Resources.Count > 1).Repr(),
                api);
#endif
#endif
        }