static void addClassToActionList(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, ActionList action_list, BlueprintCharacterClass class_to_check)
 {
     foreach (var a in action_list.Actions)
     {
         if (a == null)
         {
             continue;
         }
         if (a is ContextActionApplyBuff)
         {
             addClassToBuff(class_to_add, archetypes_to_add, (a as ContextActionApplyBuff).Buff, class_to_check);
         }
         else if (a is ContextActionSpawnAreaEffect)
         {
             addClassToAreaEffect(class_to_add, archetypes_to_add, (a as ContextActionSpawnAreaEffect).AreaEffect, class_to_check);
         }
         else if (a is Conditional)
         {
             var a_conditional = (a as Conditional);
             addClassToActionList(class_to_add, archetypes_to_add, a_conditional.IfTrue, class_to_check);
             addClassToActionList(class_to_add, archetypes_to_add, a_conditional.IfFalse, class_to_check);
         }
         else if (a is ContextActionConditionalSaved)
         {
             var a_conditional = (a as ContextActionConditionalSaved);
             addClassToActionList(class_to_add, archetypes_to_add, a_conditional.Failed, class_to_check);
             addClassToActionList(class_to_add, archetypes_to_add, a_conditional.Succeed, class_to_check);
         }
     }
 }
        internal static void Load()
        {
            if (ArcanistClass.arcanist != null)
            {
                return;
            }
            var    sorcerer                  = Helpers.GetClass("b3a505fb61437dc4097f43c3f8f9a4cf");
            var    wizard                    = Helpers.GetClass("ba34257984f4c41408ce1dc2004e342e");
            string arcanistGuid              = "26416b7c382e32ccb5b615bc17ccc797";
            string ArcanistSpellbookGuid     = "550161ffb24541148f787f1d4561fd6c";
            string ArcanistProficienciesGuid = "6fa029dd97a344be84ac6ee53d921cb9";
            string ArcanistCantripsGuid      = "904f17a28c1d3fde8a3afb036c4a9b42";
            var    Arcanistguidlist          = new string[100];
            String baseguid                  = "a3a5ccc9c670e6c4ca4a686d23";
            int    x = 0;

            for (long i = 29999; i < 30099; i++)
            {
                Arcanistguidlist[x] = baseguid + i.ToString();
                x++;
            }

            var arcanist = ArcanistClass.arcanist = Helpers.Create <BlueprintCharacterClass>();

            arcanistArray = new BlueprintCharacterClass[] { ArcanistClass.arcanist };
            ArcanistClass.arcanist.name = "ArcanistClass";
            library.AddAsset(ArcanistClass.arcanist, arcanistGuid);
            ArcanistClass.arcanist.LocalizedName        = Helpers.CreateString("Arcanist.Name", "Arcanist(W.I.P)");
            ArcanistClass.arcanist.LocalizedDescription = Helpers.CreateString("Arcanist.Description", "Arcanists are scholars of all things magical.\n" +
                                                                               "They constantly seek out new forms of magic to discover how they work, and in many cases, to collect the energy of such magic for their own uses. Many arcanists are seen as reckless," +
                                                                               "\nmore concerned with the potency of magic than the ramifications of unleashing such power.");
            ArcanistClass.arcanist.m_Icon          = sorcerer.Icon;
            ArcanistClass.arcanist.SkillPoints     = 1;
            ArcanistClass.arcanist.HitDie          = DiceType.D6;
            ArcanistClass.arcanist.BaseAttackBonus = sorcerer.BaseAttackBonus;
            ArcanistClass.arcanist.FortitudeSave   = sorcerer.FortitudeSave;
            ArcanistClass.arcanist.ReflexSave      = wizard.ReflexSave;
            ArcanistClass.arcanist.WillSave        = wizard.WillSave;

            var spellbook = Helpers.Create <BlueprintSpellbook>();

            spellbook.name = "ArcanistSpellbook";
            library.AddAsset(spellbook, ArcanistSpellbookGuid);
            spellbook.Name = ArcanistClass.arcanist.LocalizedName;
            var magusSpellLevels = library.Get <BlueprintSpellsTable>("6326b540f7c6a604f9d6f82cc0e2293c");
            var wizardLevels     = library.Get <BlueprintSpellsTable>("78bb94ed2e75122428232950bb09e97b");

            spellbook.SpellsPerDay           = wizardLevels;
            spellbook.SpellList              = wizard.Spellbook.SpellList;
            spellbook.SpellsPerLevel         = 2;
            spellbook.Spontaneous            = false;
            spellbook.IsArcane               = true;
            spellbook.AllSpellsKnown         = false;
            spellbook.CanCopyScrolls         = true;
            spellbook.CastingAttribute       = StatType.Intelligence;
            spellbook.CharacterClass         = ArcanistClass.arcanist;
            spellbook.CantripsType           = CantripsType.Cantrips;
            ArcanistClass.arcanist.Spellbook = spellbook;

            // Consolidated skills make this a bit of a judgement call. Explanation below.
            ArcanistClass.arcanist.ClassSkills = new StatType[] {
                // Warpriests have Diplomacy, Intimidate and Sense Motive (which in PF:K is like Persuasion).
                StatType.SkillPersuasion,
                // Warpriests have Climb/Swim
                StatType.SkillAthletics,
                // Warpriests have Knowledge (religion) which is the main part of the consolidated skill.
                StatType.SkillLoreReligion,
                // Warpriests have Survial and Handle Animal
                StatType.SkillLoreNature
            };



            ArcanistClass.arcanist.IsDivineCaster = false;
            ArcanistClass.arcanist.IsArcaneCaster = true;

            var paladin = library.Get <BlueprintCharacterClass>("bfa11238e7ae3544bbeb4d0b92e897ec");

            //var ArcanePoolFeature = library.Get<BlueprintFeature>("3ce9bb90749c21249adc639031d5eed1");//magus
            ArcanistClass.arcanist.StartingGold   = paladin.StartingGold; // all classes start with 411.
            ArcanistClass.arcanist.PrimaryColor   = paladin.PrimaryColor;
            ArcanistClass.arcanist.SecondaryColor = paladin.SecondaryColor;

            ArcanistClass.arcanist.RecommendedAttributes    = new StatType[] { StatType.Intelligence, StatType.Dexterity };
            ArcanistClass.arcanist.NotRecommendedAttributes = new StatType[] { StatType.Strength };

            ArcanistClass.arcanist.EquipmentEntities       = wizard.EquipmentEntities;
            ArcanistClass.arcanist.MaleEquipmentEntities   = wizard.MaleEquipmentEntities;
            ArcanistClass.arcanist.FemaleEquipmentEntities = sorcerer.FemaleEquipmentEntities;

            // Both of the restrictions here are relevant (no atheism feature, no animal class).
            ArcanistClass.arcanist.ComponentsArray  = wizard.ComponentsArray;
            ArcanistClass.arcanist.HideIfRestricted = true;
            ArcanistClass.arcanist.AddComponent(ArcanistClass.arcanist.PrerequisiteClassLevel(1));

            ArcanistClass.arcanist.StartingItems = wizard.StartingItems;

            var progression = Helpers.CreateProgression("ArcanistProgression",
                                                        ArcanistClass.arcanist.Name,
                                                        ArcanistClass.arcanist.Description,
                                                        Arcanistguidlist[50],
                                                        ArcanistClass.arcanist.Icon,
                                                        FeatureGroup.None);

            progression.Classes = arcanistArray;
            var entries = new List <LevelEntry>();


            //cantrips.SetDescription("arcanists learn a number of cantrips, or 0-level spells. These spells are cast like any other spell, but they do not consume any slots and may be used again.");
            //


            var cantrips = Helpers.createCantrips("ArcanistCantripsFeature",
                                                  "Cantrips",
                                                  "Arcanists can cast a number of cantrips, or 0-level spells. These spells are cast like any other spell, but they are not expended when cast and may be used again.",
                                                  Helpers.NiceIcons(999), //replaceicon
                                                  ArcanistCantripsGuid,
                                                  arcanist,
                                                  StatType.Intelligence,
                                                  arcanist.Spellbook.SpellList.SpellsByLevel[0].Spells.ToArray());



            var proficiencies = library.CopyAndAdd <BlueprintFeature>(
                "a98d7cc4e30fe6c4bb3a2c2f69acc3fe", // wizard proficiencies
                "ArcanistProficiencies",
                ArcanistProficienciesGuid);

            proficiencies.SetName("arcanist Proficiencies");
            proficiencies.SetDescription("A arcanist is proficient with all simple weapons, as well as the favored weapon of their deity.");

            var detectMagic    = library.Get <BlueprintFeature>("ee0b69e90bac14446a4cf9a050f87f2e");
            var deitySelection = library.Get <BlueprintFeatureSelection>("59e7a76987fe3b547b9cce045f4db3e4");


            var MagusSpellRecallFeature = library.CopyAndAdd <BlueprintFeature>("61fc0521e9992624e9c518060bf89c0f", "ArcanistPool", Arcanistguidlist[1]);
            var MagusSpellRecall        = library.CopyAndAdd <BlueprintAbility>("1bd76e00b6e056d42a8ecc1031dd43b4", "ArcanistSpellrecall", Arcanistguidlist[2]);

            MagusSpellRecallFeature.SetDescription("Arcanist Reservoir use this reservoir to empower your spells through varius means.");
            createArcaneReservoir();
            var Yog = library.CopyAndAdd <BlueprintFeature>("a3a5ccc9c670e6f4ca4a686d23b89900", "Yog", Arcanistguidlist[98]);

            Yog.SetDescription("praise yog");

            /*
             * foreach (var componen in Yog.ComponentsArray)
             * {
             *  Log.Write(componen.name);
             * }/*
             * foreach (StatType stat in (StatType[])Enum.GetValues(typeof(StatType)))
             * {
             *  Log.Write(stat.ToString());
             * }
             */
            var ExploitSelection = CreateArcanistExploitSelection();

            entries.Add(Helpers.LevelEntry(1,
                                           proficiencies,
                                           deitySelection,
                                           cantrips,
                                           //ArcanePoolFeature,
                                           ExploitSelection,
                                           Arcanist_reservoir,
                                           detectMagic
                                           ));
            var WizardFeatSelection = library.Get <BlueprintFeatureSelection>("8c3102c2ff3b69444b139a98521a4899");
            var fighterFeat         = library.Get <BlueprintFeatureSelection>("41c8486641f7d6d4283ca9dae4147a9f");

            //entries.Add(Helpers.LevelEntry(2));
            entries.Add(Helpers.LevelEntry(3, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(4));
            entries.Add(Helpers.LevelEntry(5, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(6));
            entries.Add(Helpers.LevelEntry(7, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(8));
            entries.Add(Helpers.LevelEntry(9, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(10));
            entries.Add(Helpers.LevelEntry(11, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(12));
            entries.Add(Helpers.LevelEntry(13, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(14));
            entries.Add(Helpers.LevelEntry(15, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(16));
            entries.Add(Helpers.LevelEntry(17, ExploitSelection, WizardFeatSelection));
            //entries.Add(Helpers.LevelEntry(18));
            entries.Add(Helpers.LevelEntry(19, ExploitSelection, WizardFeatSelection));
            entries.Add(Helpers.LevelEntry(20, Yog));
            progression.UIDeterminatorsGroup = new BlueprintFeatureBase[] {
                // TODO: 1st level stuff
            };
            progression.UIGroups             = Helpers.CreateUIGroups(); // TODO
            progression.LevelEntries         = entries.ToArray();

            ArcanistClass.arcanist.Progression = progression;

            ArcanistClass.arcanist.Archetypes = Array.Empty <BlueprintArchetype>();

            ArcanistClass.arcanist.RegisterClass();
        }
        static void createMajorMagic()
        {
            var druid  = library.Get <BlueprintCharacterClass>("610d836f3a3a9ed42a4349b62f002e96");
            var spells = Helpers.wizardSpellList.SpellsByLevel[1].Spells;

            major_magic = Helpers.CreateFeatureSelection("MajorMagicRogueTalent",
                                                         "Major Magic",
                                                         "A rogue with this talent gains the ability to cast a 1st-level spell from the sorcerer/wizard spell list once per day as a spell-like ability for every 2 rogue levels she possesses. The rogue’s caster level for this ability is equal to her rogue level. The save DC for this spell is 11 + the rogue’s Intelligence modifier. A rogue must have the minor magic rogue talent and an Intelligence score of at least 11 to select this talent.",
                                                         "",
                                                         Helpers.GetIcon("4ac47ddb9fa1eaf43a1b6809980cfbd2"), //magic missile
                                                         FeatureGroup.RogueTalent,
                                                         Helpers.PrerequisiteStatValue(StatType.Intelligence, 11),
                                                         Helpers.PrerequisiteFeature(minor_magic)
                                                         );

            var classes = new BlueprintCharacterClass[] { library.Get <BlueprintCharacterClass>("299aa766dee3cbf4790da4efb8c72484"), //rogue
                                                          library.Get <BlueprintCharacterClass>("c75e0971973957d4dbad24bc7957e4fb"),
                                                          Investigator.investigator_class,
                                                          druid,
                                                          library.Get <BlueprintCharacterClass>("772c83a25e2268e448e841dcd548235f"),   //bard for archaelogist
                                                          library.Get <BlueprintCharacterClass>("f1a70d9e1b0b41e49874e1fa9052a1ce") }; //inquisitor for sanctified slayer


            foreach (var s in spells)
            {
                var resource = Helpers.CreateAbilityResource("MajorMagic" + s.name + "Resource", "", "", Helpers.MergeIds("27fea41a99cd46609f8ab2283d1afce0", s.AssetGuid), null);
                resource.SetIncreasedByLevelStartPlusDivStep(0, 2, 1, 2, 1, 0, 0.0f, classes);
                BlueprintFeature feature = null;
                if (!s.HasVariants)
                {
                    var spell_like = Common.convertToSpellLike(s, "MajorMagic", classes, StatType.Intelligence, resource, no_scaling: true,
                                                               guid: Helpers.MergeIds("0e6a36ac029049c98a682f688e419f45", s.AssetGuid));
                    feature = Common.AbilityToFeatureMaybeReuseGuid(spell_like, false, Helpers.MergeIds("fb026930ab7943da96f6e17b7c778f2b", s.AssetGuid));
                    spell_like.AddComponent(Helpers.Create <NewMechanics.BindAbilitiesToClassFixedLevel>(b =>
                    {
                        b.Abilites          = new BlueprintAbility[] { spell_like };
                        b.CharacterClass    = classes[0];
                        b.AdditionalClasses = classes.Skip(1).ToArray();
                        b.Cantrip           = false;
                        b.Stat        = StatType.Intelligence;
                        b.fixed_level = 1;
                        b.Archetypes  = new BlueprintArchetype[] { Archetypes.SanctifiedSlayer.archetype, Archetypes.NatureFang.archetype };
                    }
                                                                                                         )
                                            );
                }
                else
                {
                    List <BlueprintAbility> spell_likes = new List <BlueprintAbility>();
                    foreach (var v in s.Variants)
                    {
                        spell_likes.Add(Common.convertToSpellLike(v, "MajorMagic", classes, StatType.Intelligence, resource, no_scaling: true,
                                                                  guid: Helpers.MergeIds("0e6a36ac029049c98a682f688e419f45", v.AssetGuid)));
                    }
                    var wrapper = Common.createVariantWrapper("MajorMagic" + s.name, guid: Helpers.MergeIds("0e6a36ac029049c98a682f688e419f45", s.AssetGuid), spell_likes.ToArray());
                    wrapper.SetNameDescriptionIcon(s.Name, s.Description, s.Icon);
                    feature = Common.AbilityToFeatureMaybeReuseGuid(wrapper, false, Helpers.MergeIds("3704cc05c1b64ea990ae6a2b97d35311", s.AssetGuid));
                    feature.AddComponent(Helpers.Create <NewMechanics.BindAbilitiesToClassFixedLevel>(b =>
                    {
                        b.Abilites          = spell_likes.ToArray();
                        b.CharacterClass    = classes[0];
                        b.AdditionalClasses = classes.Skip(1).ToArray();
                        b.Cantrip           = false;
                        b.Stat        = StatType.Intelligence;
                        b.fixed_level = 1;
                        b.Archetypes  = new BlueprintArchetype[] { Archetypes.SanctifiedSlayer.archetype, Archetypes.NatureFang.archetype };
                    }
                                                                                                      )
                                         );
                }
                feature.SetName("Major Magic: " + feature.Name);
                feature.Groups = new FeatureGroup[] { FeatureGroup.RogueTalent };
                feature.AddComponent(resource.CreateAddAbilityResource());
                major_magic.AllFeatures = major_magic.AllFeatures.AddToArray(feature);
            }
            addToTalentSelection(major_magic);
        }
        public static void CreateAnimalAllyFeatLine()
        {
            Main.ApplyPatch(typeof(GetPortraitFolderPathPatch), "Test");

            BlueprintFeature skillFocusLoreNature = Main.library.Get <BlueprintFeature>("6507d2da389ed55448e0e1e5b871c013");

            BlueprintFeature natureSoul = Helpers.CreateFeature(
                "NatureSoul",
                "Nature Soul",
                "You are innately in tune with nature and venerate the power and mystery of the natural world. \n" +
                "Benefit: You get a + 2 bonus on all Knowledge(nature) checks and Survival checks.If you have 10 or more ranks in one of these skills, the bonus increases to + 4 for that skill.",
                Helpers.getGuid("NatureSoul"),
                skillFocusLoreNature.Icon,
                FeatureGroup.Feat,
                Helpers.Create <NatureSoulLogic>()
                );


            BlueprintFeature        animalDomainProgressionSecondary = Main.library.Get <BlueprintFeature>("f13eb6be93dd5234c8126e5384040009");
            BlueprintFeature        animalDomainProgression          = Main.library.Get <BlueprintFeature>("23d2f87aa54c89f418e68e790dba11e0");
            BlueprintArchetype      sacredHuntsmasterArchetype       = Main.library.Get <BlueprintArchetype>("46eb929c8b6d7164188eb4d9bcd0a012");
            BlueprintCharacterClass inquisitorClass = Main.library.Get <BlueprintCharacterClass>("f1a70d9e1b0b41e49874e1fa9052a1ce");


            BlueprintFeature AnimalCompanionEmptyCompanion     = Main.library.Get <BlueprintFeature>("472091361cf118049a2b4339c4ea836a");
            BlueprintFeature AnimalCompanionFeatureBear        = Main.library.Get <BlueprintFeature>("f6f1cdcc404f10c4493dc1e51208fd6f");
            BlueprintFeature AnimalCompanionFeatureBoar        = Main.library.Get <BlueprintFeature>("afb817d80b843cc4fa7b12289e6ebe3d");
            BlueprintFeature AnimalCompanionFeatureCentipede   = Main.library.Get <BlueprintFeature>("f9ef7717531f5914a9b6ecacfad63f46");
            BlueprintFeature AnimalCompanionFeatureDog         = Main.library.Get <BlueprintFeature>("f894e003d31461f48a02f5caec4e3359");
            BlueprintFeature AnimalCompanionFeatureEkun        = Main.library.Get <BlueprintFeature>("e992949eba096644784592dc7f51a5c7");
            BlueprintFeature AnimalCompanionFeatureElk         = Main.library.Get <BlueprintFeature>("aa92fea676be33d4dafd176d699d7996");
            BlueprintFeature AnimalCompanionFeatureLeopard     = Main.library.Get <BlueprintFeature>("2ee2ba60850dd064e8b98bf5c2c946ba");
            BlueprintFeature AnimalCompanionFeatureMammoth     = Main.library.Get <BlueprintFeature>("6adc3aab7cde56b40aa189a797254271");
            BlueprintFeature AnimalCompanionFeatureMonitor     = Main.library.Get <BlueprintFeature>("ece6bde3dfc76ba4791376428e70621a");
            BlueprintFeature AnimalCompanionFeatureSmilodon    = Main.library.Get <BlueprintFeature>("126712ef923ab204983d6f107629c895");
            BlueprintFeature AnimalCompanionFeatureWolf        = Main.library.Get <BlueprintFeature>("67a9dc42b15d0954ca4689b13e8dedea");
            BlueprintFeature AnimalCompanionFeatureGiantSpider = AddSpiderCompanion();

            BlueprintFeature[] features = new BlueprintFeature[]
            {
                AnimalCompanionEmptyCompanion,
                AnimalCompanionFeatureBear,
                AnimalCompanionFeatureBoar,
                AnimalCompanionFeatureCentipede,
                AnimalCompanionFeatureDog,
                AnimalCompanionFeatureEkun,
                AnimalCompanionFeatureElk,
                AnimalCompanionFeatureLeopard,
                AnimalCompanionFeatureMammoth,
                AnimalCompanionFeatureMonitor,
                AnimalCompanionFeatureSmilodon,
                AnimalCompanionFeatureWolf,
                AnimalCompanionFeatureGiantSpider
            };

            AddAnimalCompanionToAllSelections(AnimalCompanionFeatureGiantSpider);

            BlueprintProgression domainAnimalCompanionProgression = Main.library.Get <BlueprintProgression>("125af359f8bc9a145968b5d8fd8159b8");


            BlueprintProgression animalAllyProgression = Main.library.CopyAndAdd(domainAnimalCompanionProgression, "animalAllyProgression", Helpers.getGuid("animalAllyProgression"));

            animalAllyProgression.Classes = (BlueprintCharacterClass[])Array.Empty <BlueprintCharacterClass>();

            BlueprintFeatureSelection animalAlly = Helpers.CreateFeatureSelection(
                "AnimalAlly",
                "Animal Ally",
                "You gain an animal companion as if you were a druid of your character level –3 from the following list: badger, bird, camel, cat (small), dire rat, dog, horse, pony, snake (viper), or wolf. If you later gain an animal companion through another source (such as the Animal domain, divine bond, hunter’s bond, mount, or nature bond class features), the effective druid level granted by this feat stacks with that granted by other sources.",
                Helpers.getGuid("AnimalAlly"),
                skillFocusLoreNature.Icon,
                FeatureGroup.Feat,
                natureSoul.PrerequisiteFeature(),
                Helpers.PrerequisiteCharacterLevel(4),
                Helpers.Create <PrerequisiteNoArchetype>(x =>
            {
                x.Archetype      = sacredHuntsmasterArchetype;
                x.CharacterClass = inquisitorClass;
            }),
                animalDomainProgression.PrerequisiteNoFeature(),
                animalDomainProgressionSecondary.PrerequisiteNoFeature(),
                Helpers.Create <AddFeatureOnApply>(x => x.Feature = animalAllyProgression),
                Helpers.Create <AnimalAllyAdjustToLevelLogic>()
                );

            animalAlly.SetFeatures(features);

            Main.library.AddFeats(natureSoul, animalAlly);
        }
        // Creates the progression that offers a choice of HP, Skill Rank, or other choices each level up.
        private static void FillFavoredClassProgression(BlueprintProgression favored, BlueprintCharacterClass favoredClass, List <BlueprintFeature> extraChoices = null)
        {
            bool isPrestige = favoredClass.PrestigeClass;

            favored.Classes = new BlueprintCharacterClass[] { favoredClass };
            favored.ExclusiveProgression = favoredClass;

            FeatureGroup group = UpdateLevelUpDeterminatorText.Group;

            if (isPrestige)
            {
                group = FeatureGroup.Feat;
            }

            BlueprintFeatureSelection selection = Helpers.CreateFeatureSelection(
                favored.name + "BonusSelection",
                favored.Name,
                favored.Description,
                Helpers.MergeIds(favored.AssetGuid, "5b99b7d724e048c08b384dd890826"),
                favoredClass.Icon,
                group);

            List <BlueprintFeature> choices = new List <BlueprintFeature> {
                bonusHitPointFeat, bonusSkillRankFeat
            };

            if (extraChoices != null)
            {
                choices.AddRange(extraChoices);
            }
            selection.SetFeatures(choices);

            List <LevelEntry> entries = new List <LevelEntry>();
            int maxLevel = isPrestige ? 10 : 20;

            for (int level = 1; level <= maxLevel; level++)
            {
                entries.Add(Helpers.LevelEntry(level, selection));
            }

            if (isPrestige)
            {
                // Create the skill selection feature that offers +2 bonus to class skill
                // (+4 bonus with 10 ranks invested).
                BlueprintFeatureSelection paramSkill = Helpers.CreateFeatureSelection(
                    favored.name + "SkillBonus",
                    favored.Name,
                    favored.Description + "\nYou gain a +2 bonus on checks using the skill you chose from that prestige class’s class skills. If you have 10 or more ranks in one of these skills, the bonus increases to +4 for that skill. This bonus stacks with the bonus granted by Skill Focus, but does not stack with a bonus granted by any other feat (such as Magical Aptitude or Persuasive).",
                    Helpers.MergeIds(favoredClass.AssetGuid, "15faccea8a364cb39d091dd01b513c3a"),
                    Helpers.skillFocusFeat.Icon,
                    FeatureGroup.None,
                    Helpers.Create <AddParameterizedStatBonus>(a => a.Descriptor = ModifierDescriptor.Feat));
                List <BlueprintFeature> classSkillFeatures = new List <BlueprintFeature>();
                foreach (StatType favoredClassClassSkill in favoredClass.ClassSkills)
                {
                    classSkillFeatures.Add(StatBonusTenRanksByStatType.Get(favoredClassClassSkill));
                }


                paramSkill.SetFeatures(classSkillFeatures);
                entries[0].Features.Add(paramSkill);
            }

            favored.LevelEntries = entries.ToArray();
        }
Example #6
0
        // Adds the Crossblooded Sorcerer archetype.
        internal static void Load()
        {
            var progressionClasses = new BlueprintCharacterClass[] { sorcererClass, dragonDiscipleClass };

            var crossblooded = Helpers.Create <BlueprintArchetype>(a =>
            {
                a.name                 = "CrossbloodedSorcererArchetype";
                a.LocalizedName        = Helpers.CreateString("Crossblooded.Name", "Crossblooded Sorcerer");
                a.LocalizedDescription = Helpers.CreateString("Crossblooded.Description",
                                                              "A crossblooded sorcerer selects two different bloodlines. The sorcerer may gain access to the skills, feats, and some of the powers of both bloodlines they are descended from, but at the cost of reduced mental clarity and choice.");
            });

            library.AddAsset(crossblooded, crossbloodedId);
            crossblooded.SetIcon(sorcererClass.Icon);

            crossblooded.ReplaceSpellbook = CreateReplacementSpellbook();

            var bloodlineSelection = Helpers.bloodlineSelection;
            var bloodlines         = bloodlineSelection.AllFeatures.Cast <BlueprintProgression>().ToList();

            var sorcererFeatSelection = library.Get <BlueprintFeatureSelection>("3a60f0c0442acfb419b0c03b584e1394");

            var powers      = new SortedDictionary <int, SortedSet <BlueprintFeature> >();
            var spells      = new SortedDictionary <int, SortedSet <BlueprintFeature> >();
            var powerLevels = new int[] { 1, 3, 9, 15, 20 };
            var spellLevels = new int[] { 3, 5, 7, 9, 11, 13, 15, 17, 19 };

            foreach (var level in powerLevels)
            {
                powers.Add(level, new SortedSet <BlueprintFeature>(BlueprintCompare.instance));
            }
            foreach (var level in spellLevels)
            {
                spells.Add(level, new SortedSet <BlueprintFeature>(BlueprintCompare.instance));
            }

            var crossbloodlines = new List <BlueprintProgression>();

            foreach (var bloodline in bloodlines)
            {
                var levelLogic = CrossBloodlineLogic.TryCreate(bloodline);
                if (levelLogic == null)
                {
                    continue;
                }
                var crossbloodline = library.CopyAndAdd(bloodline, $"{bloodline.name}Cross", bloodline.AssetGuid, "933224357f8d48be837a3083e33a18a8");
                crossbloodline.SetName($"{bloodline.Name} (Crossblood)");
                crossbloodline.LevelEntries = new LevelEntry[] {
                    Helpers.LevelEntry(1, bloodline.GetLevelEntry(1).Features.Where(EldritchHeritage.IsArcanaOrClassSkill))
                };
                crossbloodline.Classes = progressionClasses;
                crossbloodline.Ranks   = 1;
                crossbloodline.AddComponent(levelLogic);
                crossbloodlines.Add(crossbloodline);
                crossbloodForBloodline.Add(bloodline, crossbloodline);

                // Collect spells and abilities so we can build the choices for the main crossblooded progression.
                // (Note: we need to clone these, so we can change the prerequisites).
                foreach (var level in powerLevels)
                {
                    var power = CreateBloodlinePower(bloodline, level, crossbloodline);
                    powers[level].Add(power);
                }
                foreach (var level in spellLevels)
                {
                    var spell = CreateBloodlineSpell(bloodline, level, crossbloodline);
                    spells[level].Add(spell);
                }
            }

            FixBloodlinePrerequisites(crossblooded);

            crossbloodProgression = Helpers.CreateProgression("CrossbloodedProgression",
                                                              crossblooded.Name, crossblooded.Description, "5f9f524c33ae4df780c54189ab9642b6",
                                                              crossblooded.Icon, FeatureGroup.None);

            crossbloodProgression.Classes = progressionClasses;

            var entries    = new List <LevelEntry>();
            var powerGroup = new List <BlueprintFeatureBase>();
            var spellGroup = new List <BlueprintFeatureBase>();

            var allPowerChoices = new List <BlueprintFeature>();
            var allSpellChoices = new List <BlueprintFeature>();

            foreach (var level in new SortedSet <int>(powerLevels.Concat(spellLevels)))
            {
                var entry = Helpers.LevelEntry(level);
                entries.Add(entry);

                SortedSet <BlueprintFeature> powerChoices;
                if (powers.TryGetValue(level, out powerChoices))
                {
                    var description    = "At 1st, 3rd, 9th, 15th, and 20th levels, a crossblooded sorcerer gains one of the two new bloodline powers available to their at that level. They may instead select a lower-level bloodline power they did not choose in place of one of these higher-level powers.";
                    var powerSelection = Helpers.CreateFeatureSelection($"BloodlinePowerSelection{level}",
                                                                        "Bloodline Power",
                                                                        DescribeChoices(description, powerChoices),
                                                                        Helpers.MergeIds(guidsByLevel[level], "15029e64baee4db6b09ca6a6ed2d70c0"),
                                                                        null,
                                                                        FeatureGroup.None);
                    //powerSelection.HideInUI = true;

                    allPowerChoices.AddRange(powerChoices);
                    powerSelection.SetFeatures(allPowerChoices);
                    powerGroup.Add(powerSelection);
                    entry.Features.Add(powerSelection);
                }
                SortedSet <BlueprintFeature> spellChoices;
                if (spells.TryGetValue(level, out spellChoices))
                {
                    var description    = "A crossblooded sorcerer may select their bonus spells from either of their bloodlines. The sorcerer also has the choice to learn a lower-level bonus spell they did not choose in place of the higher-level bonus spell they would normally gain. Lower-level bonus spells learned this way always use the spell level that they would be if the sorcerer had learned them with the appropriate bonus spell.";
                    var spellSelection = Helpers.CreateFeatureSelection($"BloodlineSpellSelection{level}",
                                                                        "Bloodline Spell",
                                                                        DescribeChoices(description, spellChoices),
                                                                        Helpers.MergeIds(guidsByLevel[level], "d333e2fb82ab4ab4af7d03d84aa5895c"),
                                                                        null,
                                                                        FeatureGroup.None);
                    //spellSelection.HideInUI = true;

                    allSpellChoices.AddRange(spellChoices);
                    spellSelection.SetFeatures(allSpellChoices);
                    spellGroup.Add(spellSelection);
                    entry.Features.Add(spellSelection);
                }
            }

            crossbloodProgression.LevelEntries = entries.ToArray();
            crossbloodProgression.UIGroups     = new UIGroup[] { Helpers.CreateUIGroup(spellGroup), Helpers.CreateUIGroup(powerGroup) };

            bloodlineChoice1 = Helpers.CreateFeatureSelection($"{bloodlineSelection.name}Cross1",
                                                              bloodlineSelection.Name, bloodlineSelection.Description,
                                                              "08cbfcda615f49218d3b118fc9322b81",
                                                              bloodlineSelection.Icon,
                                                              FeatureGroup.BloodLine);
            bloodlineChoice1.SetFeatures(crossbloodlines);

            bloodlineChoice2 = Helpers.CreateFeatureSelection($"{bloodlineSelection.name}Cross2",
                                                              bloodlineSelection.Name, bloodlineSelection.Description,
                                                              "ef595c20be9745b698e25e5a33b7d443",
                                                              bloodlineSelection.Icon,
                                                              FeatureGroup.BloodLine);
            bloodlineChoice2.SetFeatures(crossbloodlines);

            var level1 = Helpers.LevelEntry(1,
                                            crossbloodProgression,
                                            Helpers.CreateFeature("CrossbloodedConflictingUrges", "Crossblooded (conflicting urges)",
                                                                  "The conflicting urges created by the divergent nature of the crossblooded sorcerer’s dual heritage forces them to constantly take some mental effort just to remain focused on their current situation and needs. This leaves them with less mental resolve to deal with external threats. A crossblooded sorcerer always takes a –2 penalty on Will saves.",
                                                                  "ebefc29906f74c0d9a8b914095cc05d6",
                                                                  Helpers.GetIcon("983e8ad193160b44da80b38af4927e75"), // Diverse Training
                                                                  FeatureGroup.None,
                                                                  Helpers.CreateAddStatBonus(StatType.SaveWill, -2, ModifierDescriptor.Penalty)),
                                            bloodlineChoice1,
                                            bloodlineChoice2);

            crossblooded.RemoveFeatures = new LevelEntry[] { Helpers.LevelEntry(1, bloodlineSelection) };
            crossblooded.AddFeatures    = new LevelEntry[] { level1 };

            crossblooded.BaseAttackBonus = sorcererClass.BaseAttackBonus;
            crossblooded.FortitudeSave   = sorcererClass.FortitudeSave;
            crossblooded.ReflexSave      = sorcererClass.ReflexSave;
            crossblooded.WillSave        = sorcererClass.WillSave;

            Helpers.SetField(crossblooded, "m_ParentClass", sorcererClass);

            var archetypes = sorcererClass.Archetypes.ToList();

            archetypes.Insert(0, crossblooded);
            sorcererClass.Archetypes = archetypes.ToArray();

            // Fix prestige class spellbook selection
            // TODO: find these automatically, or it won't be compatible with new prestige classes.
            FixSpellbookSelection(crossblooded, "ae04b7cdeb88b024b9fd3882cc7d3d76", "9ff7ad30e5a074346a40f80efda277c8", FeatureGroup.ArcaneTricksterSpellbook);
            FixSpellbookSelection(crossblooded, "8c1ba14c0b6dcdb439c56341385ee474", "fa2a2469c9ba6d54b8fc2356f4fc0e9e", FeatureGroup.DragonDiscipleSpellbook);
            FixSpellbookSelection(crossblooded, "dc3ab8d0484467a4787979d93114ebc3", "89d2b9f096b54804c8350dd2a899f8a4", FeatureGroup.EldritchKnightSpellbook);
            FixSpellbookSelection(crossblooded, "97f510c6483523c49bc779e93e4c4568", "e8013bf2853590f4fba12b4b57366bcc", FeatureGroup.MysticTheurgeArcaneSpellbook);
        }
Example #7
0
        // Add the Prestigious Spellcaster feat.
        internal static void Load()
        {
            if (prestigiousSpellcasterClasses != null)
            {
                return;
            }

            dragonDiscipleClass = Helpers.GetClass(dragonDiscipleId);
            eldritchKnightClass = Helpers.GetClass(eldritchKnightId);
            // NOTE: this order must match the order used in the feats.
            ///126
            prestigiousSpellcasterDefault = new BlueprintCharacterClass[] { eldritchKnightClass, dragonDiscipleClass };
            ///127
            prestigiousSpellcasterExtra = Helpers.prestigeClassesSkipLevels.ToArray();

            //prestigiousSpellcasterClasses = prestigiousSpellcasterDefault.Concat(prestigiousSpellcasterExtra).ToArray();
            prestigiousSpellcasterClasses = Helpers.prestigeClassesSkipLevels.ToArray();

            FixEldritchKnightPrereq();

            // TODO: it would be nice to find the list of spellcasting prestige classes with skipped levels automatically.
            var spellSpecialization = library.Get <BlueprintFeatureSelection>("fe67bc3b04f1cd542b4df6e28b6e0ff5");
            var prestigiousSpell    = Helpers.CreateFeatureSelection("PrestigiousSpellcasterSelection", "Prestigious Spellcaster",
                                                                     "The transition into a spellcasting prestige class is less difficult for you, and because of this, you gain 1 additional effective spellcaster level from your prestige class levels.",
                                                                     "30e9a3fcdb0446aa87f45d0f50b3b3fc",
                                                                     Image2Sprite.Create("Mods/EldritchArcana/sprites/prestigious_spellcaster.png"),
                                                                     FeatureGroup.Feat);


            //126

            /*
             * prestigiousSpell.SetFeatures(
             *  CreatePrestigiousSpellcaster(eldritchKnightClass, "dc3ab8d0484467a4787979d93114ebc3"  ),//*EldritchKnightSpellbookSelection
             *  CreatePrestigiousSpellcaster(dragonDiscipleClass, "8c1ba14c0b6dcdb439c56341385ee474"  )
             *  );//*DragonDiscipleSpellbookSelection
             * //start*/

            foreach (BlueprintCharacterClass c in prestigiousSpellcasterClasses)
            {
                Log.Write("patching:" + c.ToString());
                try
                {
                    var spellbookguid = "";
                    for (int i = 1; i < 11; i++)
                    {
                        var entry = c.Progression.GetLevelEntry(i);

                        foreach (BlueprintFeatureBase f in entry.Features)
                        {
                            if (f.name.ToUpper().Contains("SPELLBOOK"))
                            {
                                spellbookguid = f.AssetGuid;
                                break;
                            }
                        }
                        if (spellbookguid != "" && spellbookguid != null)
                        {
                            break;
                        }
                    }
                    if (spellbookguid != "" && spellbookguid != null)
                    {
                        try
                        {
                            var feat = CreatePrestigiousSpellcaster(c, spellbookguid);
                            prestigiousSpell.Features.AddToArray(feat);
                        }
                        catch (System.Exception)
                        {
                            Log.Write("There was an issue with " + c.name + " unable to add to prestigious spellcaster");
                        }
                    }
                }
                catch (System.Exception)
                {
                    Log.Write("Patching:" + c.ToString() + " Failed");
                }
            }
            //end

            var components = new List <BlueprintComponent>(prestigiousSpellcasterClasses.Select(
                                                               c => Helpers.PrerequisiteClassLevel(c, 1, any: true)));

            components.Add(Helpers.PrerequisiteFeature(FavoredClassBonus.favoredPrestigeClass));
            components.Add(Helpers.Create <PrestigiousSpellcasterRecommendation>());
            prestigiousSpell.SetComponents(components);
            prestigiousSpell.AllFeatures = prestigiousSpell.Features;
            // Log.Write(prestigiousSpell, "", true);

            library.AddFeats(prestigiousSpell);

            ApplySpellbook_Apply_Patch.onApplySpellbook.Add((state, unit, previousCasterLevel) =>
            {
                if (ShouldGainCasterLevelOnLevelUp(state, unit))
                {
                    IncreaseCasterLevel(state, unit);
                }
            });

            // Set this last, so it won't be set if we failed to initialize.
            prestigiousSpellcaster = prestigiousSpell;
        }
        public static void addClassToProgression(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, DomainSpellsType spells_type, BlueprintProgression progression, BlueprintCharacterClass class_to_check)
        {
            if (progression.Classes.Contains(class_to_check))
            {
                progression.Classes = progression.Classes.AddToArray(class_to_add).Distinct().ToArray();


                progression.Archetypes = progression.Archetypes.AddToArray(archetypes_to_add).Distinct().ToArray();
            }

            foreach (var entry in progression.LevelEntries)
            {
                foreach (var feat in entry.Features)
                {
                    addClassToFact(class_to_add, archetypes_to_add, spells_type, feat, class_to_check);
                }
            }

            addClassToFeat(class_to_add, archetypes_to_add, spells_type, progression, class_to_check);
        }
 public static void AddClassLevel_NotCharacterLevel(this UnitProgressionData instance, BlueprintCharacterClass characterClass)
 {
     //instance.SureClassData(characterClass).Level++;
     GetMethodDel <UnitProgressionData, Func <UnitProgressionData, BlueprintCharacterClass, ClassData> >
         ("SureClassData")(instance, characterClass).Level++;
     //instance.CharacterLevel++;
     instance.Classes.Sort();
     instance.Features.AddFact(characterClass.Progression, null);
     instance.Owner.OnGainClassLevel(characterClass);
     //int[] bonuses = BlueprintRoot.Instance.Progression.XPTable.Bonuses;
     //int val = bonuses[Math.Min(bonuses.Length - 1, instance.CharacterLevel)];
     //instance.Experience = Math.Max(instance.Experience, val);
 }
        public static void addClassToResource(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, BlueprintAbilityResource rsc, BlueprintCharacterClass class_to_check)
        {
            //lueprintCharacterClass cleric_class = library.Get<BlueprintCharacterClass>("67819271767a9dd4fbfd4ae700befea0");
            var amount     = ExtensionMethods.getMaxAmount(rsc);
            var classes    = Helpers.GetField <BlueprintCharacterClass[]>(amount, "Class");
            var archetypes = Helpers.GetField <BlueprintArchetype[]>(amount, "Archetypes");

            if (classes != null && !classes.Empty() && classes.Contains(class_to_check))
            {
                classes    = classes.AddToArray(class_to_add).Distinct().ToArray();
                archetypes = archetypes.AddToArray(archetypes_to_add).Distinct().ToArray();
                Helpers.SetField(amount, "Class", classes);
                Helpers.SetField(amount, "Archetypes", archetypes);
                ExtensionMethods.setMaxAmount(rsc, amount);
            }

            var classes_div    = Helpers.GetField <BlueprintCharacterClass[]>(amount, "ClassDiv");
            var archetypes_div = Helpers.GetField <BlueprintArchetype[]>(amount, "ArchetypesDiv");

            if (classes_div != null && !classes_div.Empty() && classes_div.Contains(class_to_check))
            {
                classes_div    = classes_div.AddToArray(class_to_add).Distinct().ToArray();
                archetypes_div = archetypes_div.AddToArray(archetypes_to_add).Distinct().ToArray();
                Helpers.SetField(amount, "ClassDiv", classes_div);
                Helpers.SetField(amount, "ArchetypesDiv", archetypes_div);
                ExtensionMethods.setMaxAmount(rsc, amount);
            }
        }
        public static void addClassToDomains(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, DomainSpellsType spells_type, BlueprintFeatureSelection domain_selection, BlueprintCharacterClass class_to_check)
        {
            var domains = domain_selection.AllFeatures;

            foreach (var domain_feature in domains)
            {
                addClassToFact(class_to_add, archetypes_to_add, spells_type, domain_feature, class_to_check);
            }
        }
        public static void addClassToAreaEffect(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, BlueprintAbilityAreaEffect a, BlueprintCharacterClass class_to_check)
        {
            var components = a.ComponentsArray;

            foreach (var c in components)
            {
                if (c is ContextRankConfig)
                {
                    addClassToContextRankConfig(class_to_add, archetypes_to_add, c as ContextRankConfig, a.name, class_to_check);
                }
                else if (c is AbilityAreaEffectBuff)
                {
                    addClassToBuff(class_to_add, archetypes_to_add, (c as AbilityAreaEffectBuff).Buff, class_to_check);
                }
                else if (c is AbilityAreaEffectRunAction)
                {
                    var c_typed = c as AbilityAreaEffectRunAction;
                    if (c_typed.Round != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.Round, class_to_check);
                    }
                    if (c_typed.UnitEnter != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.UnitEnter, class_to_check);
                    }
                    if (c_typed.UnitEnter != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.UnitExit, class_to_check);
                    }
                    if (c_typed.UnitMove != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.UnitMove, class_to_check);
                    }
                }
            }
        }
        public static void addClassToBuff(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, BlueprintBuff b, BlueprintCharacterClass class_to_check)
        {
            var components = b.ComponentsArray;

            foreach (var c in components.ToArray())
            {
                if (c is ContextRankConfig)
                {
                    addClassToContextRankConfig(class_to_add, archetypes_to_add, c as ContextRankConfig, b.name, class_to_check);
                }
                else if (c is Kingmaker.UnitLogic.Buffs.Components.AddAreaEffect)
                {
                    addClassToAreaEffect(class_to_add, archetypes_to_add, (c as AddAreaEffect).AreaEffect, class_to_check);
                }
                else if (c is ContextCalculateAbilityParamsBasedOnClass)
                {
                    var c_typed = c as ContextCalculateAbilityParamsBasedOnClass;
                    b.ReplaceComponent(c, Common.createContextCalculateAbilityParamsBasedOnClassesWithArchetypes(new BlueprintCharacterClass[] { c_typed.CharacterClass, class_to_add }.Distinct().ToArray(), archetypes_to_add, c_typed.StatType));
                }
                else if (c is NewMechanics.ContextCalculateAbilityParamsBasedOnClasses)
                {
                    var c_typed = c as NewMechanics.ContextCalculateAbilityParamsBasedOnClasses;
                    b.ReplaceComponent(c, Common.createContextCalculateAbilityParamsBasedOnClassesWithArchetypes(c_typed.CharacterClasses.AddToArray(class_to_add).Distinct().ToArray(), c_typed.archetypes.AddToArray(archetypes_to_add).Distinct().ToArray(), c_typed.StatType));
                }
                else if (c is AddFactContextActions)
                {
                    var c_typed = c as AddFactContextActions;
                    if (c_typed.NewRound != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.NewRound, class_to_check);
                    }
                    if (c_typed.Activated != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.Activated, class_to_check);
                    }
                    if (c_typed.Deactivated != null)
                    {
                        addClassToActionList(class_to_add, archetypes_to_add, c_typed.Deactivated, class_to_check);
                    }
                }
                else if (c is AddFacts)
                {
                    var c_typed = c as AddFacts;
                    foreach (var f in c_typed.Facts)
                    {
                        addClassToFact(class_to_add, archetypes_to_add, DomainSpellsType.NoSpells, f, class_to_check);
                    }
                }
            }
        }
        public static void addClassToContextRankConfig(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, ContextRankConfig c, string archetypes_list_prefix, BlueprintCharacterClass class_to_check)
        {
            var classes = Helpers.GetField <BlueprintCharacterClass[]>(c, "m_Class");

            if (classes == null || classes.Empty() || !classes.Contains(class_to_check))
            {
                return;
            }

            classes = classes.AddToArray(class_to_add).Distinct().ToArray();

            Helpers.SetField(c, "m_Class", classes);


            if (!archetypes_to_add.Empty())
            {
                var base_value_type = Helpers.GetField <ContextRankBaseValueType>(c, "m_BaseValueType");
                var rank_type       = Helpers.GetField <AbilityRankType>(c, "m_Type");
                if (base_value_type == ContextRankBaseValueType.ClassLevel || base_value_type == ContextRankBaseValueType.SummClassLevelWithArchetype)
                {
                    var archetypes_list = Helpers.CreateFeature(archetypes_list_prefix + rank_type.ToString() + "ArchetypesListFeature",
                                                                "",
                                                                "",
                                                                "",
                                                                null,
                                                                FeatureGroup.None,
                                                                Helpers.Create <ContextRankConfigArchetypeList>(a => a.archetypes = archetypes_to_add)
                                                                );
                    Helpers.SetField(c, "m_BaseValueType", ContextRankBaseValueTypeExtender.SummClassLevelWithArchetypes.ToContextRankBaseValueType());
                    Helpers.SetField(c, "m_Feature", archetypes_list);
                }
                else if (base_value_type == ContextRankBaseValueType.MaxClassLevelWithArchetype)
                {
                    var archetypes_list = Helpers.CreateFeature(archetypes_list_prefix + rank_type.ToString() + "ArchetypesListFeature",
                                                                "",
                                                                "",
                                                                "",
                                                                null,
                                                                FeatureGroup.None,
                                                                Helpers.Create <ContextRankConfigArchetypeList>(a => a.archetypes = archetypes_to_add)
                                                                );
                    Helpers.SetField(c, "m_BaseValueType", ContextRankBaseValueTypeExtender.MaxClassLevelWithArchetypes.ToContextRankBaseValueType());
                    Helpers.SetField(c, "m_Feature", archetypes_list);
                }
                else if (base_value_type == ContextRankBaseValueTypeExtender.SummClassLevelWithArchetypes.ToContextRankBaseValueType() ||
                         base_value_type == ContextRankBaseValueTypeExtender.MaxClassLevelWithArchetypes.ToContextRankBaseValueType())
                {
                    var archetypes_list = Helpers.GetField <BlueprintFeature>(c, "m_Feature");
                    archetypes_list.ReplaceComponent <ContextRankConfigArchetypeList>(a => a.archetypes = a.archetypes.AddToArray(archetypes_to_add).Distinct().ToArray());
                }
            }
        }
        public static BlueprintScriptableObject[] Tooltip()
        {
            TooltipData contextTooltipData = Game.Instance.UI.TooltipsController.ContextTooltipData;

            if (contextTooltipData == null)
            {
                return((BlueprintScriptableObject[])null);
            }
            ItemEntity itemEntity = contextTooltipData.Item;

            if (itemEntity != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)itemEntity.Blueprint
                       }
            }
            ;
            BlueprintFeatureBase feature = contextTooltipData.Feature;

            if (feature != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)feature
                       }
            }
            ;
            Ability ability = contextTooltipData.Ability;

            if (ability != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)ability.Blueprint
                       }
            }
            ;
            BlueprintFeatureSelection featureSelection = contextTooltipData.FeatureSelection;

            if (featureSelection != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)featureSelection
                       }
            }
            ;
            AbilityData abilityData = contextTooltipData.AbilityData;

            if (abilityData != (AbilityData)null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)abilityData.Blueprint
                       }
            }
            ;
            ActivatableAbility activatableAbility = contextTooltipData.ActivatableAbility;

            if (activatableAbility != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)activatableAbility.Blueprint
                       }
            }
            ;
            Buff buff = contextTooltipData.Buff;

            if (buff != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)buff.Blueprint
                       }
            }
            ;
            BlueprintAbility blueprintAbility = contextTooltipData.BlueprintAbility;

            if (blueprintAbility != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)blueprintAbility
                       }
            }
            ;
            BlueprintCookingRecipe recipe = contextTooltipData.Recipe;

            if (recipe != (UnityEngine.Object)null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)recipe
                       }
            }
            ;
            KingdomBuff kingdomBuff = contextTooltipData.KingdomBuff;

            if (kingdomBuff != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)kingdomBuff.Blueprint
                       }
            }
            ;
            UnitEntityData unit = contextTooltipData.Unit;

            if (unit != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)unit.Blueprint
                       }
            }
            ;
            BlueprintCharacterClass blueprintCharacterClass = contextTooltipData.Class;

            if (blueprintCharacterClass != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)blueprintCharacterClass
                       }
            }
            ;
            BlueprintRace race = contextTooltipData.Race;

            if (race != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)race
                       }
            }
            ;
            BlueprintSettlementBuilding settlementBuildingBp = contextTooltipData.SettlementBuildingBp;

            if (settlementBuildingBp != null)
            {
                return new BlueprintScriptableObject[1]
                       {
                           (BlueprintScriptableObject)settlementBuildingBp
                       }
            }
            ;
            SettlementBuilding settlementBuilding = contextTooltipData.SettlementBuilding;

            if (settlementBuilding == null)
            {
                return((BlueprintScriptableObject[])contextTooltipData.TutorialPage ?? (BlueprintScriptableObject[])null);
            }
            return(new BlueprintScriptableObject[1]
            {
                (BlueprintScriptableObject)settlementBuilding.Blueprint
            });
        }
    }
}
        public static bool IsChildProgressionOf(this BlueprintProgression progression, UnitDescriptor unit, BlueprintCharacterClass characterClass)
        {
            ClassData classData = unit.Progression.GetClassData(characterClass);

            if (classData != null)
            {
                if (progression.Classes.Contains(characterClass) &&
                    !classData.Archetypes.Intersect(characterClass.Archetypes).Any())
                {
                    return(true);
                }
                if (classData.Archetypes.Intersect(unit.Progression.GetClassData(characterClass).Archetypes).Any())
                {
                    return(true);
                }
            }
            return(false);
        }
        // Adds the Crossblooded Sorcerer archetype.
        internal static void Load()
        {
            var progressionClasses = new BlueprintCharacterClass[] { sorcererClass, dragonDiscipleClass };

            var crossblooded = Helpers.Create <BlueprintArchetype>(a =>
            {
                a.name                 = "CrossbloodedSorcererArchetype";
                a.LocalizedName        = Helpers.CreateString("Crossblooded.Name", RES.CrossbloodedSorcererLocalizedName_info);
                a.LocalizedDescription = Helpers.CreateString("Crossblooded.Description",
                                                              RES.CrossbloodedSorcererLocalizedDescription_info);
            });

            library.AddAsset(crossblooded, crossbloodedId);
            crossblooded.SetIcon(sorcererClass.Icon);

            crossblooded.ReplaceSpellbook = CreateReplacementSpellbook();

            var bloodlineSelection = Helpers.bloodlineSelection;
            var bloodlines         = bloodlineSelection.AllFeatures.Cast <BlueprintProgression>().ToList();

            var sorcererFeatSelection = library.Get <BlueprintFeatureSelection>("3a60f0c0442acfb419b0c03b584e1394");

            var powers      = new SortedDictionary <int, SortedSet <BlueprintFeature> >();
            var spells      = new SortedDictionary <int, SortedSet <BlueprintFeature> >();
            var powerLevels = new int[] { 1, 3, 9, 15, 20 };
            var spellLevels = new int[] { 3, 5, 7, 9, 11, 13, 15, 17, 19 };

            foreach (var level in powerLevels)
            {
                powers.Add(level, new SortedSet <BlueprintFeature>(BlueprintCompare.instance));
            }
            foreach (var level in spellLevels)
            {
                spells.Add(level, new SortedSet <BlueprintFeature>(BlueprintCompare.instance));
            }

            var crossbloodlines = new List <BlueprintProgression>();


            foreach (var bloodline in bloodlines)
            {
                //Log.Write(bloodline);

                /*if(bloodline.AssetGuid=="a4cf06211879416ea82e10ca3062bb81")
                 * {
                 *  break;
                 * }*/
                var levelLogic = CrossBloodlineLogic.TryCreate(bloodline);
                if (levelLogic == null)
                {
                    continue;
                }
                var crossbloodline = library.CopyAndAdd(bloodline, $"{bloodline.name}Cross", bloodline.AssetGuid, "933224357f8d48be837a3083e33a18a8");
                crossbloodline.SetName($"{bloodline.Name} (Crossblood)");
                crossbloodline.LevelEntries = new LevelEntry[] {
                    Helpers.LevelEntry(1, bloodline.GetLevelEntry(1).Features.Where(EldritchHeritage.IsArcanaOrClassSkill))
                };
                crossbloodline.Classes = progressionClasses;
                crossbloodline.Ranks   = 1;
                crossbloodline.AddComponent(levelLogic);
                crossbloodlines.Add(crossbloodline);
                crossbloodForBloodline.Add(bloodline, crossbloodline);

                // Collect spells and abilities so we can build the choices for the main crossblooded progression.
                // (Note: we need to clone these, so we can change the prerequisites).
                foreach (var level in powerLevels)
                {
                    var power = CreateBloodlinePower(bloodline, level, crossbloodline);
                    powers[level].Add(power);
                }
                foreach (var level in spellLevels)
                {
                    var spell = CreateBloodlineSpell(bloodline, level, crossbloodline);
                    spells[level].Add(spell);
                }
                var Mutatepower = CreateMutateBloodlinePower(bloodline, 1, crossbloodline);
                powers[1].Add(Mutatepower);
            }
            //i commented beneath value to have it at least working
            FixBloodlinePrerequisites(crossblooded);

            crossbloodProgression = Helpers.CreateProgression("CrossbloodedProgression",
                                                              crossblooded.Name, crossblooded.Description, "5f9f524c33ae4df780c54189ab9642b6",
                                                              crossblooded.Icon, FeatureGroup.None);

            crossbloodProgression.Classes = progressionClasses;

            var entries    = new List <LevelEntry>();
            var powerGroup = new List <BlueprintFeatureBase>();
            var spellGroup = new List <BlueprintFeatureBase>();

            var allPowerChoices = new List <BlueprintFeature>();
            //var allMutatedPowerChoices = new List<BlueprintFeature>();
            var allSpellChoices = new List <BlueprintFeature>();

            foreach (var level in new SortedSet <int>(powerLevels.Concat(spellLevels)))
            {
                var entry = Helpers.LevelEntry(level);
                entries.Add(entry);

                SortedSet <BlueprintFeature> powerChoices;
                if (powers.TryGetValue(level, out powerChoices))
                {
                    var description = RES.BloodlinePowerFeatureDescription_info;

                    var powerSelection = Helpers.CreateFeatureSelection($"BloodlinePowerSelection{level}",
                                                                        RES.BloodlinePowerFeatureName_info,
                                                                        DescribeChoices(description, powerChoices),
                                                                        Helpers.MergeIds(guidsByLevel[level], "15029e64baee4db6b09ca6a6ed2d70c0"),
                                                                        null,
                                                                        FeatureGroup.None);



                    allPowerChoices.AddRange(powerChoices);
                    powerSelection.SetFeatures(allPowerChoices);
                    powerGroup.Add(powerSelection);
                    entry.Features.Add(powerSelection);
                }
                SortedSet <BlueprintFeature> spellChoices;
                if (spells.TryGetValue(level, out spellChoices))
                {
                    var description    = RES.BloodlineSpellFeatureDescription_info;
                    var spellSelection = Helpers.CreateFeatureSelection($"BloodlineSpellSelection{level}",
                                                                        RES.BloodlineSpellFeatureName_info,
                                                                        DescribeChoices(description, spellChoices),
                                                                        Helpers.MergeIds(guidsByLevel[level], "d333e2fb82ab4ab4af7d03d84aa5895c"),
                                                                        null,
                                                                        FeatureGroup.None);
                    //spellSelection.HideInUI = true;

                    allSpellChoices.AddRange(spellChoices);
                    spellSelection.SetFeatures(allSpellChoices);
                    spellGroup.Add(spellSelection);
                    entry.Features.Add(spellSelection);
                }
            }

            crossbloodProgression.LevelEntries = entries.ToArray();
            crossbloodProgression.UIGroups     = new UIGroup[] { Helpers.CreateUIGroup(spellGroup), Helpers.CreateUIGroup(powerGroup) };

            bloodlineChoice1 = Helpers.CreateFeatureSelection($"{bloodlineSelection.name}Cross1",
                                                              bloodlineSelection.Name, bloodlineSelection.Description,
                                                              "08cbfcda615f49218d3b118fc9322b81",
                                                              bloodlineSelection.Icon,
                                                              FeatureGroup.BloodLine);
            bloodlineChoice1.SetFeatures(crossbloodlines);

            bloodlineChoice2 = Helpers.CreateFeatureSelection($"{bloodlineSelection.name}Cross2",
                                                              bloodlineSelection.Name, bloodlineSelection.Description,
                                                              "ef595c20be9745b698e25e5a33b7d443",
                                                              bloodlineSelection.Icon,
                                                              FeatureGroup.BloodLine);
            bloodlineChoice2.SetFeatures(crossbloodlines);
            //
            var level1 = Helpers.LevelEntry(1,
                                            crossbloodProgression,
                                            Helpers.CreateFeature("CrossbloodedConflictingUrges", RES.CrossbloodedConflictingUrgesFeatureName_info,
                                                                  RES.CrossbloodedConflictingUrgesFeatureDescription_info,
                                                                  "ebefc29906f74c0d9a8b914095cc05d6",
                                                                  Helpers.GetIcon("983e8ad193160b44da80b38af4927e75"), // Diverse Training
                                                                  FeatureGroup.None,
                                                                  Helpers.CreateAddStatBonus(StatType.SaveWill, -2, ModifierDescriptor.Penalty)),
                                            bloodlineChoice1,
                                            bloodlineChoice2);

            crossblooded.RemoveFeatures = new LevelEntry[] { Helpers.LevelEntry(1, bloodlineSelection) };
            crossblooded.AddFeatures    = new LevelEntry[] { level1 };

            crossblooded.BaseAttackBonus = sorcererClass.BaseAttackBonus;
            crossblooded.FortitudeSave   = sorcererClass.FortitudeSave;
            crossblooded.ReflexSave      = sorcererClass.ReflexSave;
            crossblooded.WillSave        = sorcererClass.WillSave;

            Helpers.SetField(crossblooded, "m_ParentClass", sorcererClass);

            var archetypes = sorcererClass.Archetypes.ToList();

            archetypes.Insert(0, crossblooded);
            sorcererClass.Archetypes = archetypes.ToArray();
            //sorcererClass.Progression.LevelEntries;
            // Fix prestige class spellbook selection
            // TODO: find these automatically, or it won't be compatible with new prestige classes.
            FixSpellbookSelection(crossblooded, "ae04b7cdeb88b024b9fd3882cc7d3d76", "9ff7ad30e5a074346a40f80efda277c8", FeatureGroup.ArcaneTricksterSpellbook);
            FixSpellbookSelection(crossblooded, "8c1ba14c0b6dcdb439c56341385ee474", "fa2a2469c9ba6d54b8fc2356f4fc0e9e", FeatureGroup.DragonDiscipleSpellbook);
            FixSpellbookSelection(crossblooded, "dc3ab8d0484467a4787979d93114ebc3", "89d2b9f096b54804c8350dd2a899f8a4", FeatureGroup.EldritchKnightSpellbook);
            FixSpellbookSelection(crossblooded, "97f510c6483523c49bc779e93e4c4568", "e8013bf2853590f4fba12b4b57366bcc", FeatureGroup.MysticTheurgeArcaneSpellbook);
        }
Example #18
0
 public StateReplacer(LevelUpState state)
 {
     State          = state;
     SelectedClass  = state.SelectedClass;
     NextClassLevel = state.NextClassLevel;
 }
        //subordinate spell
        //dispelling pulse

        public PhrenicAmplificationsEngine(BlueprintAbilityResource pool_resource, BlueprintSpellbook linked_spellbook, BlueprintCharacterClass linked_class, string asset_prefix)
        {
            resource        = pool_resource;
            spellbook       = linked_spellbook;
            character_class = linked_class;
            name_prefix     = asset_prefix;
        }
Example #20
0
 public void Replace(BlueprintCharacterClass selectedClass)
 {
     State.SelectedClass = selectedClass;
 }
Example #21
0
 public void HandleUnitGainLevel(UnitDescriptor unit, BlueprintCharacterClass @class)
 {
     SetValue();
 }
Example #22
0
 public void Replace(BlueprintCharacterClass selectedClass, int nextClassLevel)
 {
     State.SelectedClass  = selectedClass;
     State.NextClassLevel = nextClassLevel;
 }
        static public void addClassToFeat(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, DomainSpellsType spells_type, BlueprintFeatureBase feat)
        {
            foreach (var c in feat.ComponentsArray.ToArray())
            {
                if (c is IncreaseSpellDamageByClassLevel)
                {
                    var c_typed = c as IncreaseSpellDamageByClassLevel;
                    c_typed.AdditionalClasses = c_typed.AdditionalClasses.AddToArray(class_to_add);
                    c_typed.Archetypes        = c_typed.Archetypes.AddToArray(archetypes_to_add);
                }
                if (c is AddFeatureOnApply)
                {
                    var c_typed = c as AddFeatureOnApply;
                    addClassToFact(class_to_add, archetypes_to_add, spells_type, c_typed.Feature);
                }
                else if (c is AddFeatureOnClassLevel)
                {
                    var c_typed = c as AddFeatureOnClassLevel;
                    c_typed.AdditionalClasses = c_typed.AdditionalClasses.AddToArray(class_to_add);
                    c_typed.Archetypes        = c_typed.Archetypes.AddToArray(archetypes_to_add);
                    addClassToFact(class_to_add, archetypes_to_add, spells_type, c_typed.Feature as BlueprintUnitFact);
                }
                else if (c is LevelUpMechanics.AddFeatureOnClassLevelRange)
                {
                    var c_typed = c as LevelUpMechanics.AddFeatureOnClassLevelRange;
                    c_typed.classes    = c_typed.classes.AddToArray(class_to_add);
                    c_typed.archetypes = c_typed.archetypes.AddToArray(archetypes_to_add);
                    if (!c_typed.class_bonuses.Empty())
                    {
                        c_typed.class_bonuses = c_typed.class_bonuses.AddToArray(c_typed.class_bonuses.Last());
                    }
                    addClassToFact(class_to_add, archetypes_to_add, spells_type, c_typed.Feature as BlueprintUnitFact);
                }
                else if (c is AddFeatureIfHasFact)
                {
                    var c_typed = c as AddFeatureIfHasFact;
                    addClassToFact(class_to_add, archetypes_to_add, spells_type, c_typed.Feature as BlueprintUnitFact);
                }
                else if (c is AddSpecialSpellList && spells_type == DomainSpellsType.SpecialList)
                {
                    var c_typed = c as AddSpecialSpellList;
                    if (c_typed.CharacterClass != class_to_add)
                    {
                        var c2 = Helpers.Create <Kingmaker.UnitLogic.FactLogic.AddSpecialSpellList>();
                        c2.CharacterClass = class_to_add;
                        c2.SpellList      = c_typed.SpellList;
                        feat.AddComponent(c2);
                    }
                }
                else if (c is AddOppositionSchool && spells_type == DomainSpellsType.SpecialList)
                {
                    var c_typed = c as AddOppositionSchool;
                    if (c_typed.CharacterClass != class_to_add)
                    {
                        var c2 = Helpers.Create <AddOppositionSchool>();
                        c2.CharacterClass = class_to_add;
                        c2.School         = c_typed.School;
                        feat.AddComponent(c2);
                    }
                }
                else if (c is Kingmaker.UnitLogic.FactLogic.AddFacts)
                {
                    var c_typed = (Kingmaker.UnitLogic.FactLogic.AddFacts)c;
                    foreach (var f in c_typed.Facts)
                    {
                        addClassToFact(class_to_add, archetypes_to_add, spells_type, f);
                    }
                }
                else if (c is AddAbilityResources)
                {
                    var c_typed = (Kingmaker.Designers.Mechanics.Facts.AddAbilityResources)c;
                    addClassToResource(class_to_add, archetypes_to_add, c_typed.Resource);
                }
                else if (c is FactSinglify)
                {
                    var c_typed = c as FactSinglify;
                    foreach (var f in c_typed.NewFacts)
                    {
                        addClassToFact(class_to_add, archetypes_to_add, spells_type, f);
                    }
                }
                else if (c is ReplaceCasterLevelOfAbility)
                {
                    var c_typed = c as ReplaceCasterLevelOfAbility;

                    c_typed.AdditionalClasses = c_typed.AdditionalClasses.AddToArray(class_to_add);
                    c_typed.Archetypes        = c_typed.Archetypes.AddToArray(archetypes_to_add);
                }
                else if (c is BindAbilitiesToClass)
                {
                    var c_typed = c as BindAbilitiesToClass;

                    c_typed.AdditionalClasses = c_typed.AdditionalClasses.AddToArray(class_to_add);
                    c_typed.Archetypes        = c_typed.Archetypes.AddToArray(archetypes_to_add);
                }
                else if (c is ContextRankConfig)
                {
                    addClassToContextRankConfig(class_to_add, archetypes_to_add, c as ContextRankConfig, feat.name);
                }
                else if (c is IntenseSpells)
                {
                    feat.AddComponent(Helpers.Create <NewMechanics.IntenseSpellsForClasses>(i => i.classes = new BlueprintCharacterClass[] { class_to_add, (c as IntenseSpells).Wizard }));
                    feat.RemoveComponent(c);
                }
                else if (c is NewMechanics.IntenseSpellsForClasses)
                {
                    var c_typed = c as NewMechanics.IntenseSpellsForClasses;
                    if (!c_typed.classes.Contains(class_to_add))
                    {
                        c_typed.classes = c_typed.classes.AddToArray(class_to_add);
                    }
                }
                else if (c is AddClassLevelToSummonDuration)
                {
                    feat.AddComponent(Helpers.Create <NewMechanics.AddClassesLevelToSummonDuration>(i => i.CharacterClasses = new BlueprintCharacterClass[] { class_to_add, (c as AddClassLevelToSummonDuration).CharacterClass }));
                    feat.RemoveComponent(c);
                }
                else if (c is NewMechanics.AddClassesLevelToSummonDuration)
                {
                    var c_typed = c as NewMechanics.AddClassesLevelToSummonDuration;
                    if (!c_typed.CharacterClasses.Contains(class_to_add))
                    {
                        c_typed.CharacterClasses = c_typed.CharacterClasses.AddToArray(class_to_add);
                    }
                }
                else if (c is LearnSpellList && spells_type == DomainSpellsType.NormalList)
                {
                    var spell_list = (c as LearnSpellList)?.SpellList;
                    if (spell_list == null)
                    {
                        continue;
                    }
                    if (archetypes_to_add.Empty())
                    {
                        var learn_spells_fact = Helpers.Create <Kingmaker.UnitLogic.FactLogic.LearnSpellList>();
                        learn_spells_fact.SpellList      = spell_list;
                        learn_spells_fact.CharacterClass = class_to_add;
                        feat.AddComponent(learn_spells_fact);
                    }
                    else
                    {
                        foreach (var ar_type in archetypes_to_add)
                        {
                            var learn_spells_fact = Helpers.Create <Kingmaker.UnitLogic.FactLogic.LearnSpellList>();
                            learn_spells_fact.SpellList      = spell_list;
                            learn_spells_fact.CharacterClass = class_to_add;
                            learn_spells_fact.Archetype      = ar_type;
                            feat.AddComponent(learn_spells_fact);
                        }
                    }
                }
                else if (c is AddKnownSpell && spells_type == DomainSpellsType.NormalList)
                {
                    if (archetypes_to_add.Empty())
                    {
                        var learn_spells_fact = Helpers.Create <AddKnownSpell>();
                        learn_spells_fact.Spell          = (c as AddKnownSpell).Spell;
                        learn_spells_fact.SpellLevel     = (c as AddKnownSpell).SpellLevel;
                        learn_spells_fact.CharacterClass = class_to_add;
                        feat.AddComponent(learn_spells_fact);
                    }
                    else
                    {
                        foreach (var ar_type in archetypes_to_add)
                        {
                            var learn_spells_fact = Helpers.Create <AddKnownSpell>();
                            learn_spells_fact.Spell          = (c as AddKnownSpell).Spell;
                            learn_spells_fact.SpellLevel     = (c as AddKnownSpell).SpellLevel;
                            learn_spells_fact.CharacterClass = class_to_add;
                            learn_spells_fact.Archetype      = ar_type;
                            feat.AddComponent(learn_spells_fact);
                        }
                    }
                }
            }
        }
        internal static Fact GetSpellcasterFact(UnitDescriptor unit, BlueprintCharacterClass selectedClass)
        {
            var blueprint = prestigiousSpellcaster.AllFeatures[Array.IndexOf(prestigiousSpellcasterClasses, selectedClass)];

            return(unit.Logic.GetFact(blueprint) ?? unit.Progression.Features.GetFact(blueprint));
        }
Example #25
0
 public abstract int getFakeClassLevel(BlueprintCharacterClass character_class);
        public static void Load()
        {
            if (slayer != null)
            {
                return;
            }
            BlueprintCharacterClass rogue  = library.Get <BlueprintCharacterClass>("299aa766dee3cbf4790da4efb8c72484");
            BlueprintCharacterClass ranger = library.Get <BlueprintCharacterClass>("cda0615668a6df14eb36ba19ee881af6");

            slayer      = Helpers.Create <BlueprintCharacterClass>();
            slayerArray = new BlueprintCharacterClass[] { slayer };
            slayer.name = "SlayerClass";
            library.AddAsset(slayer, Helpers.getGuid("SlayerClass"));

            slayer.LocalizedName        = Helpers.CreateString("Slayer.Name", "Slayer (MOD)");
            slayer.LocalizedDescription = Helpers.CreateString("Slayer.Description", "Dev note: This is the mod version of the slayer. It stays in the mod to keep savegame compatibility. It is suggested to switch to the official slayer class through respecing. \n Skilled at tracking down targets, slayers are consummate hunters, living for the chase and the deadly stroke that brings it to a close. Slayers spend most of their time honing their weapon skills, studying the habits and anatomy of foes, and practicing combat maneuvers.");
            slayer.m_Icon          = ranger.Icon;
            slayer.SkillPoints     = 4;
            slayer.HitDie          = DiceType.D10;
            slayer.BaseAttackBonus = ranger.BaseAttackBonus;
            slayer.FortitudeSave   = ranger.FortitudeSave;
            slayer.ReflexSave      = ranger.ReflexSave;
            slayer.WillSave        = ranger.WillSave;
            slayer.ClassSkills     = new StatType[]
            {
                StatType.SkillMobility,
                StatType.SkillAthletics,
                StatType.SkillPersuasion,
                StatType.SkillKnowledgeWorld,
                StatType.SkillPerception,
                StatType.SkillStealth
            };

            slayer.StartingGold   = ranger.StartingGold; // all classes start with 411.
            slayer.PrimaryColor   = ranger.PrimaryColor;
            slayer.SecondaryColor = ranger.SecondaryColor;

            slayer.RecommendedAttributes    = new StatType[] { StatType.Strength, StatType.Dexterity };
            slayer.NotRecommendedAttributes = new StatType[] { StatType.Charisma };

            slayer.StartingItems           = ranger.StartingItems;
            slayer.EquipmentEntities       = ranger.EquipmentEntities;
            slayer.MaleEquipmentEntities   = ranger.MaleEquipmentEntities;
            slayer.FemaleEquipmentEntities = ranger.FemaleEquipmentEntities;
            slayer.AddComponent(slayer.PrerequisiteClassLevel(1));

            var progression = Helpers.CreateProgression("SlayerProgression",
                                                        slayer.Name,
                                                        slayer.Description,
                                                        Helpers.getGuid("SlayerProgression"),
                                                        slayer.Icon,
                                                        FeatureGroup.None);

            progression.Classes = slayerArray;
            var entries = new List <LevelEntry>();


            var proficiencies = library.CopyAndAdd <BlueprintFeature>(
                "c5e479367d07d62428f2fe92f39c0341", // RangerProficiencies
                "SlayerProficiencies",
                Helpers.getGuid("SlayerProficiencies"));

            proficiencies.SetName("Slayer Proficiencies");
            proficiencies.SetDescription("A slayer is proficient with all simple and martial weapons, as well as with light armor, medium armor, and shields (except tower shields).");

            CreateStudiedTarget();
            BlueprintFeatureSelection slayerTalents = getSlayerTalentSelection();
            BlueprintFeature          sneakAttack   = library.Get <BlueprintFeature>("9b9eac6709e1c084cb18c3a366e0ec87");


            BlueprintFeature studiedTargetImprovement = library.Get <BlueprintFeature>(Helpers.getGuid("StudiedTargetProgression"));

            entries.Add(Helpers.LevelEntry(1,
                                           proficiencies,
                                           library.Get <BlueprintFeature>(Helpers.getGuid("StudiedTargetMove")),
                                           studiedTargetImprovement,
                                           library.Get <BlueprintFeature>("d3e6275cfa6e7a04b9213b7b292a011c"), // ray calculate feature
                                           library.Get <BlueprintFeature>("62ef1cdb90f1d654d996556669caf7fa")  // touch calculate feature
                                           ));
            entries.Add(Helpers.LevelEntry(2, slayerTalents));
            entries.Add(Helpers.LevelEntry(3, sneakAttack, library.Get <BlueprintFeature>(Helpers.getGuid("setStudiedTargetOnSneakAttack"))));
            entries.Add(Helpers.LevelEntry(4, slayerTalents));

            entries.Add(Helpers.LevelEntry(5, studiedTargetImprovement));
            entries.Add(Helpers.LevelEntry(6, slayerTalents, sneakAttack));
            entries.Add(Helpers.LevelEntry(7, library.Get <BlueprintFeature>(Helpers.getGuid("StudiedTargetSwift"))));
            entries.Add(Helpers.LevelEntry(8, slayerTalents));
            entries.Add(Helpers.LevelEntry(9, sneakAttack));
            entries.Add(Helpers.LevelEntry(10,
                                           studiedTargetImprovement,
                                           slayerTalents,
                                           library.Get <BlueprintFeature>("a33b99f95322d6741af83e9381b2391c")));                    // Advanced Talents
            entries.Add(Helpers.LevelEntry(12, slayerTalents, sneakAttack));
            entries.Add(Helpers.LevelEntry(14, slayerTalents, library.Get <BlueprintFeature>("385260ca07d5f1b4e907ba22a02944fc"))); // Quarry
            entries.Add(Helpers.LevelEntry(15, studiedTargetImprovement, sneakAttack));
            entries.Add(Helpers.LevelEntry(16, slayerTalents));
            entries.Add(Helpers.LevelEntry(18, slayerTalents, sneakAttack));
            entries.Add(Helpers.LevelEntry(19, library.Get <BlueprintFeature>("25e009b7e53f86141adee3a1213af5af"))); // ImprovedQuarry
            entries.Add(Helpers.LevelEntry(20, studiedTargetImprovement, slayerTalents));

            progression.LevelEntries = entries.ToArray();
            slayer.Progression       = progression;
            slayer.RegisterClass();
            addFavoredClassBonus(slayer);
        }
        static void createMinorMagic()
        {
            var druid  = library.Get <BlueprintCharacterClass>("610d836f3a3a9ed42a4349b62f002e96");
            var spells = Helpers.wizardSpellList.SpellsByLevel[0].Spells;

            minor_magic = Helpers.CreateFeatureSelection("MinorMagicRogueTalent",
                                                         "Minor Magic",
                                                         "A rogue with this talent gains the ability to cast a 0-level spell from the sorcerer/wizard spell list. This spell can be cast three times a day as a spell-like ability. The caster level for this ability is equal to the rogue’s level. The save DC for this spell is 10 + the rogue’s Intelligence modifier.",
                                                         "",
                                                         Helpers.GetIcon("16e23c7a8ae53cc42a93066d19766404"), //jolt
                                                         FeatureGroup.RogueTalent,
                                                         Helpers.PrerequisiteStatValue(StatType.Intelligence, 10)
                                                         );

            var classes = new BlueprintCharacterClass[] { library.Get <BlueprintCharacterClass>("299aa766dee3cbf4790da4efb8c72484"), //rogue
                                                          library.Get <BlueprintCharacterClass>("c75e0971973957d4dbad24bc7957e4fb"), //slayer
                                                          Investigator.investigator_class,
                                                          druid,
                                                          library.Get <BlueprintCharacterClass>("772c83a25e2268e448e841dcd548235f"),   //bard for archaelogist
                                                          library.Get <BlueprintCharacterClass>("f1a70d9e1b0b41e49874e1fa9052a1ce") }; //inquisitor for sanctified slayer


            foreach (var s in spells)
            {
                BlueprintFeature feature = null;
                if (!s.HasVariants)
                {
                    var spell_like = Common.convertToSpellLike(s, "MinorMagic", classes, StatType.Intelligence, no_resource: true, no_scaling: true,
                                                               guid: Helpers.MergeIds("0e6a36ac029049c98a682f688e419f45", s.AssetGuid));
                    feature = Common.AbilityToFeatureMaybeReuseGuid(spell_like, false, Helpers.MergeIds("fb026930ab7943da96f6e17b7c778f2b", s.AssetGuid));
                    feature.AddComponent(Helpers.Create <BindAbilitiesToClass>(b =>
                    {
                        b.Abilites          = new BlueprintAbility[] { spell_like };
                        b.CharacterClass    = classes[0];
                        b.AdditionalClasses = classes.Skip(1).ToArray();
                        b.Cantrip           = true;
                        b.Stat       = StatType.Intelligence;
                        b.Archetypes = new BlueprintArchetype[] { Archetypes.SanctifiedSlayer.archetype, Archetypes.NatureFang.archetype };
                    }
                                                                               )
                                         );
                }
                else
                {
                    List <BlueprintAbility> spell_likes = new List <BlueprintAbility>();
                    foreach (var v in s.Variants)
                    {
                        spell_likes.Add(Common.convertToSpellLike(v, "MinorMagic", classes, StatType.Intelligence, no_resource: true, no_scaling: true,
                                                                  guid: Helpers.MergeIds("0e6a36ac029049c98a682f688e419f45", v.AssetGuid)));
                    }
                    var wrapper = Common.createVariantWrapper("MinorMagic" + s.name, Helpers.MergeIds("0e6a36ac029049c98a682f688e419f45", s.AssetGuid), spell_likes.ToArray());
                    wrapper.SetNameDescriptionIcon(s.Name, s.Description, s.Icon);
                    feature = Common.AbilityToFeatureMaybeReuseGuid(wrapper, false, Helpers.MergeIds("fb026930ab7943da96f6e17b7c778f2b", s.AssetGuid));
                    feature.AddComponent(Helpers.Create <BindAbilitiesToClass>(b =>
                    {
                        b.Abilites          = spell_likes.ToArray();
                        b.CharacterClass    = classes[0];
                        b.AdditionalClasses = classes.Skip(1).ToArray();
                        b.Cantrip           = true;
                        b.Stat       = StatType.Intelligence;
                        b.Archetypes = new BlueprintArchetype[] { Archetypes.SanctifiedSlayer.archetype, Archetypes.NatureFang.archetype };
                    }
                                                                               )
                                         );
                }
                feature.SetName("Minor Magic: " + feature.Name);
                feature.Groups          = new FeatureGroup[] { FeatureGroup.RogueTalent };
                minor_magic.AllFeatures = minor_magic.AllFeatures.AddToArray(feature);
            }
            addToTalentSelection(minor_magic);
        }
        internal static void Load()
        {
            if (OracleClass.oracle != null)
            {
                return;
            }

            var sorcerer = Helpers.GetClass("b3a505fb61437dc4097f43c3f8f9a4cf");
            var cleric   = Helpers.GetClass("67819271767a9dd4fbfd4ae700befea0");

            var oracle = OracleClass.oracle = Helpers.Create <BlueprintCharacterClass>();

            oracleArray = new BlueprintCharacterClass[] { oracle };
            oracle.name = "OracleClass";
            library.AddAsset(oracle, "ec73f4790c1d4554871b81cde0b9399b");
            oracle.LocalizedName        = Helpers.CreateString("Oracle.Name", RES.OracleLocalizedName_info);
            oracle.LocalizedDescription = Helpers.CreateString("Oracle.Description", RES.OracleLocalizedDescription_info);
            oracle.m_Icon          = cleric.Icon;
            oracle.SkillPoints     = Main.settings?.OracleHas3SkillPoints == true ? 3 : 4;
            oracle.HitDie          = DiceType.D8;
            oracle.BaseAttackBonus = cleric.BaseAttackBonus;
            oracle.FortitudeSave   = sorcerer.FortitudeSave;
            oracle.ReflexSave      = sorcerer.ReflexSave;
            oracle.WillSave        = sorcerer.WillSave;

            // TODO: Oracle will not work properly with Mystic Theurge.
            // Not sure it's worth fixing, but if desired the fix would be:
            // - patch spellbook selection feats, similar to what Crossblooded does.
            // - use a similar apporach as Theurge does for Inquisitor, to select new spells via the feat UI.
            var spellbook = Helpers.Create <BlueprintSpellbook>();

            spellbook.name = "OracleSpellbook";
            library.AddAsset(spellbook, "c26cdf7ee670428c96aad20225f3fdca");
            spellbook.Name             = oracle.LocalizedName;
            spellbook.SpellsPerDay     = sorcerer.Spellbook.SpellsPerDay;
            spellbook.SpellsKnown      = sorcerer.Spellbook.SpellsKnown;
            spellbook.SpellList        = cleric.Spellbook.SpellList;
            spellbook.Spontaneous      = true;
            spellbook.IsArcane         = false;
            spellbook.AllSpellsKnown   = false;
            spellbook.CanCopyScrolls   = false;
            spellbook.CastingAttribute = StatType.Charisma;
            spellbook.CharacterClass   = oracle;
            spellbook.CantripsType     = CantripsType.Orisions;
            oracle.Spellbook           = spellbook;

            // Consolidated skills make this a bit of a judgement call. Explanation below.
            // Note that Mysteries add 2 more skills typically.
            oracle.ClassSkills = new StatType[] {
                // Oracles have Diplomacy and Sense Motive. Diplomacy is the main component of
                // Persuasion in PF:K. (Also: while Sense Motives should map to Perception with
                // consolidated skills, in PF:K it seems to be more in line with Persuasion).
                StatType.SkillPersuasion,
                // Oracles have Knowledge (history), which is a main component of (world).
                StatType.SkillKnowledgeWorld,
                // Oracles have Knowledge (planes) and Knowledge (religion) so this is an easy call,
                // because those skills are 100% of consolidated Religion skill.
                StatType.SkillLoreReligion,
            };

            oracle.IsDivineCaster = true;
            oracle.IsArcaneCaster = false;

            oracle.StartingGold   = cleric.StartingGold; // all classes start with 411.
            oracle.PrimaryColor   = cleric.PrimaryColor;
            oracle.SecondaryColor = cleric.SecondaryColor;

            oracle.RecommendedAttributes    = new StatType[] { StatType.Charisma };
            oracle.NotRecommendedAttributes = new StatType[] { StatType.Intelligence };

            oracle.EquipmentEntities       = cleric.EquipmentEntities;
            oracle.MaleEquipmentEntities   = cleric.MaleEquipmentEntities;
            oracle.FemaleEquipmentEntities = cleric.FemaleEquipmentEntities;

            // Both of the restrictions here are relevant (no atheism feature, no animal class).
            oracle.ComponentsArray = sorcerer.ComponentsArray;
            oracle.StartingItems   = cleric.StartingItems;

            var progression = Helpers.CreateProgression("OracleProgression",
                                                        oracle.Name,
                                                        oracle.Description,
                                                        "317a0f107135425faa7def96cb8ef690",
                                                        oracle.Icon,
                                                        FeatureGroup.None);

            progression.Classes = oracleArray;
            var entries = new List <LevelEntry>();

            var orisons = library.CopyAndAdd <BlueprintFeature>(
                "e62f392949c24eb4b8fb2bc9db4345e3", // cleric orisions
                "OracleOrisonsFeature",
                "926891a8e8a74d9eac63a1e296b1a4f3");

            orisons.SetDescription(RES.OracleOrisonsFeatureDescription_info);
            orisons.SetComponents(orisons.ComponentsArray.Select(c =>
            {
                var bind = c as BindAbilitiesToClass;
                if (bind == null)
                {
                    return(c);
                }
                bind = UnityEngine.Object.Instantiate(bind);
                bind.CharacterClass = oracle;
                bind.Stat           = StatType.Charisma;
                return(bind);
            }));
            var proficiencies = library.CopyAndAdd <BlueprintFeature>(
                "8c971173613282844888dc20d572cfc9", // cleric proficiencies
                "OracleProficiencies",
                "baee2212dee249cb8136bda72a872ba4");

            proficiencies.SetName(RES.OracleProficienciesFeatureName_info);
            proficiencies.SetDescription(RES.OracleProficienciesFeatureDescription_info);

            // Note: curses need to be created first, because some revelations use them (e.g. Cinder Dance).
            var curse = OracleCurses.CreateSelection();

            (var mystery, var revelation, var mysteryClassSkills) = CreateMysteryAndRevelationSelection();

            var cureOrInflictSpell = CreateCureOrInflictSpellSelection();

            var detectMagic = library.Get <BlueprintFeature>("ee0b69e90bac14446a4cf9a050f87f2e");

            entries.Add(Helpers.LevelEntry(1,
                                           proficiencies,
                                           mystery,
                                           curse,
                                           cureOrInflictSpell,
                                           revelation,
                                           orisons,
                                           mysteryClassSkills,
                                           library.Get <BlueprintFeature>("d3e6275cfa6e7a04b9213b7b292a011c"), // ray calculate feature
                                           library.Get <BlueprintFeature>("62ef1cdb90f1d654d996556669caf7fa"), // touch calculate feature
                                           library.Get <BlueprintFeature>("9fc9813f569e2e5448ddc435abf774b3"), // full caster
                                           detectMagic
                                           ));
            entries.Add(Helpers.LevelEntry(3, revelation));
            entries.Add(Helpers.LevelEntry(7, revelation));
            entries.Add(Helpers.LevelEntry(11, revelation));
            entries.Add(Helpers.LevelEntry(15, revelation));
            entries.Add(Helpers.LevelEntry(19, revelation));
            progression.UIDeterminatorsGroup = new BlueprintFeatureBase[] {
                mystery, curse, cureOrInflictSpell, proficiencies, orisons, mysteryClassSkills, detectMagic,
            };
            progression.UIGroups = Helpers.CreateUIGroups(
                revelation, revelation, revelation, revelation, revelation, revelation);
            progression.LevelEntries = entries.ToArray();

            oracle.Progression = progression;

            oracle.Archetypes = OracleArchetypes.Create(mystery, revelation, mysteryClassSkills).ToArray();

            oracle.RegisterClass();

            var extraRevelation = Helpers.CreateFeatureSelection("ExtraRevelation",
                                                                 RES.ExtraRevelationFeatureName_info, RES.ExtraRevelationFeatureDescription_info,
                                                                 "e91bd89bb5534ae2b61a3222a9b7325e",
                                                                 Image2Sprite.Create("Mods/EldritchArcana/sprites/revelations_extra.png"),
                                                                 FeatureGroup.Feat,
                                                                 Helpers.PrerequisiteClassLevel(oracle, 1));
            var extras = revelation.Features.Select(
                // The level-up UI sometimes loses track of two selections at the same level
                // (e.g. taking Extra Revelations at 1st level),  so clone the feature selections.
                f => library.CopyAndAdd(f, $"{f.name}Extra", f.AssetGuid, "afc8ceb5eb2849d5976e07f5f02ab200")).ToList();

            extras.Add(UndoSelection.Feature.Value);
            extraRevelation.SetFeatures(extras);
            var abundantRevelations = Helpers.CreateFeatureSelection("AbundantRevelations",
                                                                     RES.AbundantRevelationsFeatureName_info,
                                                                     RES.AbundantRevelationsFeatureDescription_info,
                                                                     "1614c7b40565481fa3728fd7375ddca0",
                                                                     Image2Sprite.Create("Mods/EldritchArcana/sprites/revelations_abundant.png"),
                                                                     FeatureGroup.Feat);
            var resourceChoices   = new List <BlueprintFeature>();
            var prereqRevelations = new List <Prerequisite> {
                Helpers.PrerequisiteClassLevel(oracle, 1)
            };

            CreateAbundantRevelations(revelation, abundantRevelations, resourceChoices, prereqRevelations, new HashSet <BlueprintFeature>());
            abundantRevelations.SetFeatures(resourceChoices);
            abundantRevelations.SetComponents(prereqRevelations);

            library.AddFeats(extraRevelation, abundantRevelations);
        }
 public void HandleUnitGainLevel(UnitDescriptor unit, BlueprintCharacterClass @class)
 {
     this.Apply();
 }
        static public void addClassToAbility(BlueprintCharacterClass class_to_add, BlueprintArchetype[] archetypes_to_add, BlueprintAbility a, BlueprintCharacterClass class_to_check)
        {
            var components = a.ComponentsArray.ToArray();

            foreach (var c in components.ToArray())
            {
                if (c is AbilityVariants)
                {
                    foreach (var v in (c as AbilityVariants).Variants)
                    {
                        addClassToAbility(class_to_add, archetypes_to_add, v, class_to_check);
                    }
                }
                else if (c is ContextRankConfig)
                {
                    addClassToContextRankConfig(class_to_add, archetypes_to_add, c as ContextRankConfig, a.name, class_to_check);
                }
                else if (c is AbilityEffectRunAction)
                {
                    addClassToActionList(class_to_add, archetypes_to_add, (c as AbilityEffectRunAction).Actions, class_to_check);
                }
                else if (c is ContextCalculateAbilityParamsBasedOnClass)
                {
                    var c_typed = c as ContextCalculateAbilityParamsBasedOnClass;
                    if (c_typed.CharacterClass == class_to_check)
                    {
                        a.ReplaceComponent(c, Common.createContextCalculateAbilityParamsBasedOnClassesWithArchetypes(new BlueprintCharacterClass[] { c_typed.CharacterClass, class_to_add }.Distinct().ToArray(), archetypes_to_add, c_typed.StatType));
                    }
                }
                else if (c is NewMechanics.ContextCalculateAbilityParamsBasedOnClasses)
                {
                    var c_typed = c as NewMechanics.ContextCalculateAbilityParamsBasedOnClasses;
                    if (c_typed.CharacterClasses.Contains(class_to_check))
                    {
                        a.ReplaceComponent(c, Common.createContextCalculateAbilityParamsBasedOnClassesWithArchetypes(c_typed.CharacterClasses.AddToArray(class_to_add).Distinct().ToArray(), c_typed.archetypes.AddToArray(archetypes_to_add).Distinct().ToArray(), c_typed.StatType));
                    }
                }
                else if (c is AbilityEffectStickyTouch)
                {
                    addClassToAbility(class_to_add, archetypes_to_add, (c as AbilityEffectStickyTouch).TouchDeliveryAbility, class_to_check);
                }
            }
        }