Example #1
0
        static void createOppositionResearch()
        {
            var opposition_schools = library.Get <BlueprintFeatureSelection>("6c29030e9fea36949877c43a6f94ff31").AllFeatures;
            var icon = Helpers.GetIcon("68a23a419b330de45b4c3789649b5b41");

            opposition_research = Helpers.CreateFeatureSelection("OppositionResearchWizardDiscoveryFeature",
                                                                 "Opposition Research",
                                                                 "Select one Wizard opposition school; preparing spells of this school now only requires one spell slot of the appropriate level instead of two.",
                                                                 "",
                                                                 icon,
                                                                 FeatureGroup.Feat,
                                                                 Helpers.PrerequisiteFeaturesFromList(opposition_schools),
                                                                 Helpers.PrerequisiteClassLevel(wizard, 9)
                                                                 );
            opposition_research.AddComponent(Helpers.PrerequisiteNoFeature(opposition_research));

            foreach (BlueprintFeature opposition_school in opposition_schools)
            {
                SpellSchool school  = opposition_school.GetComponent <AddOppositionSchool>().School;
                var         feature = Helpers.CreateFeature(school.ToString() + "OppositionResearchWizardDiscoveryFeature",
                                                            "Opposition Research: " + school.ToString(),
                                                            opposition_research.Description,
                                                            "",
                                                            opposition_school.Icon,
                                                            FeatureGroup.WizardFeat,
                                                            Helpers.Create <RemoveFeatureOnApply>(f => f.Feature  = opposition_school),
                                                            Helpers.Create <RemoveOppositionSchool>(s => s.school = school),
                                                            Helpers.PrerequisiteFeature(opposition_school),
                                                            Helpers.PrerequisiteClassLevel(wizard, 9)
                                                            );
                opposition_research.AllFeatures = opposition_research.AllFeatures.AddToArray(feature);
            }

            addWizardDiscovery(opposition_research);
        }
Example #2
0
        static void createSecretsOfTheGrave()
        {
            var bloodline_undead_arcana = library.Get <BlueprintFeature>("1a5e7191279e7cd479b17a6ca438498c");

            var wizard     = library.Get <BlueprintCharacterClass>("ba34257984f4c41408ce1dc2004e342e");
            var bard       = archetype.GetParentClass();
            var spell_list = Common.combineSpellLists("DirgeBardBonusNecromancySpellsList", bard.Spellbook.SpellList, Witch.witch_class.Spellbook.SpellList, wizard.Spellbook.SpellList);

            Common.filterSpellList(spell_list, s => s.School == SpellSchool.Necromancy);

            var spell_selection = library.CopyAndAdd <BlueprintParametrizedFeature>("4a2e8388c2f0dd3478811d9c947bebfb", "DirgeBardExtraNecromancySpell", "");

            spell_selection.SetNameDescriptionIcon("Secrets of the Grave",
                                                   "At 2nd level, a dirge bard gains a bonus equal to half his bard level on Knowledge (religion) checks made to identify undead creatures and their abilities. A dirge bard may use mind-affecting spells to affect undead as if they were living creatures, even if they are mindless. In addition, he may add one necromancy spell from the spell list of any arcane spellcasting class to his list of spells known at 2nd level and every four levels thereafter.",
                                                   Helpers.GetIcon("a9bb3dcb2e8d44a49ac36c393c114bd9")
                                                   );

            spell_selection.ComponentsArray            = new BlueprintComponent[] { Helpers.CreateLearnSpell(spell_list, archetype.GetParentClass()) };
            spell_selection.BlueprintParameterVariants = Common.getSpellsFromSpellList(spell_list);
            spell_selection.SpellList        = spell_list;
            spell_selection.SpellcasterClass = archetype.GetParentClass();

            secrets_of_the_grave = Common.featureToSelection(spell_selection);
            secrets_of_the_grave.AddComponent(Helpers.CreateAddFact(bloodline_undead_arcana));
        }
        private static BlueprintFeatureSelection getSlayerTalentSelection()
        {
            BlueprintFeatureSelection rogueTalents = library.Get <BlueprintFeatureSelection>("c074a5d615200494b8f2a9c845799d93");



            BlueprintFeatureSelection slayerTalents = Helpers.CreateFeatureSelection(
                "rogueTalents",
                "Slayer Talents (MOD)",
                "As a slayer gains experience, he learns a number of talents that aid him and confound his foes. Starting at 2nd level and every 2 levels thereafter, a slayer gains one slayer talent. Unless otherwise noted, a slayer cannot select an individual talent more than once.",
                Helpers.getGuid("rogueTalents"),
                rogueTalents.Icon,
                FeatureGroup.RogueTalent,
                Helpers.PrerequisiteClassLevel(slayer, 1));

            List <BlueprintFeature> features = new List <BlueprintFeature>(rogueTalents.AllFeatures);
            var goBackFeature = library.Get <BlueprintFeature>(Helpers.getGuid("0GoBack"));

            BlueprintFeatureSelection slayerStyleLevelTwo = library.CopyAndAdd <BlueprintFeatureSelection>("c6d0da9124735a44f93ac31df803b9a9", "Ranger Style", Helpers.getGuid("SlayerStyleLevelTwo"));

            slayerStyleLevelTwo.AddComponent(Helpers.PrerequisiteClassLevel(slayer, 2));
            slayerStyleLevelTwo.AddComponent(slayerStyleLevelTwo.PrerequisiteNoFeature());
            slayerStyleLevelTwo.SetFeatures(slayerStyleLevelTwo.AllFeatures.AddToArray(goBackFeature));
            features.Add(slayerStyleLevelTwo);


            BlueprintFeatureSelection slayerStyleLevelSix = library.CopyAndAdd <BlueprintFeatureSelection>("61f82ba786fe05643beb3cd3910233a8", "Ranger Style", Helpers.getGuid("SlayerStyleLevelSix"));

            slayerStyleLevelSix.AddComponent(Helpers.PrerequisiteClassLevel(slayer, 6));
            slayerStyleLevelSix.AddComponent(slayerStyleLevelSix.PrerequisiteNoFeature());
            slayerStyleLevelSix.SetFeatures(slayerStyleLevelSix.AllFeatures.AddToArray(goBackFeature));
            features.Add(slayerStyleLevelSix);

            BlueprintFeatureSelection slayerStyleLevelTen = library.CopyAndAdd <BlueprintFeatureSelection>("78177315fc63b474ea3cbb8df38fafcd", "Ranger Style", Helpers.getGuid("SlayerStyleLevelTen"));

            slayerStyleLevelTen.AddComponent(Helpers.PrerequisiteClassLevel(slayer, 10));
            slayerStyleLevelTen.AddComponent(slayerStyleLevelTen.PrerequisiteNoFeature());
            slayerStyleLevelTen.SetFeatures(slayerStyleLevelTen.AllFeatures.AddToArray(goBackFeature));
            features.Add(slayerStyleLevelTen);


            slayerTalents.SetFeatures(features);

            return(slayerTalents);
        }
Example #4
0
        internal static void create()
        {
            var kineticist_class = ResourcesLibrary.TryGetBlueprint <BlueprintCharacterClass>("42a455d9ec1ad924d889272429eb8391");

            archetype = Helpers.Create <BlueprintArchetype>(a =>
            {
                a.name                 = "KineticChirurgeonArchetype";
                a.LocalizedName        = Helpers.CreateString($"{a.name}.Name", "Kinetic Chirurgeon");
                a.LocalizedDescription = Helpers.CreateString($"{a.name}.Description", "While any hydrokineticist can learn the rudiments of healing, some kineticists are virtuosos of the curative arts.");
            });
            Helpers.SetField(archetype, "m_ParentClass", kineticist_class);
            library.AddAsset(archetype, "");

            var element_selection     = library.Get <BlueprintFeatureSelection>("1f3a15a3ae8a5524ab8b97f469bf4e3d");
            var infusion_selection    = library.Get <BlueprintFeatureSelection>("58d6f8e9eea63f6418b107ce64f315ea");
            var wild_talent_selection = library.Get <BlueprintFeatureSelection>("5c883ae0cd6d7d5448b7a420f51f8459");

            archetype.RemoveFeatures = new LevelEntry[] { Helpers.LevelEntry(1, infusion_selection),
                                                          Helpers.LevelEntry(2, wild_talent_selection),
                                                          Helpers.LevelEntry(4, wild_talent_selection),
                                                          Helpers.LevelEntry(6, wild_talent_selection, KineticistFix.internal_buffer),
                                                          Helpers.LevelEntry(8, wild_talent_selection),
                                                          Helpers.LevelEntry(10, wild_talent_selection),
                                                          Helpers.LevelEntry(12, wild_talent_selection),
                                                          Helpers.LevelEntry(14, wild_talent_selection),
                                                          Helpers.LevelEntry(16, wild_talent_selection),
                                                          Helpers.LevelEntry(18, wild_talent_selection),
                                                          Helpers.LevelEntry(20, wild_talent_selection) };
            createKineticChirurgery();
            createMetahealerTalent();
            createHealingBuffer();

            archetype.AddFeatures = new LevelEntry[] { Helpers.LevelEntry(1, kinetic_chirurgery),
                                                       Helpers.LevelEntry(2, metahealer_wild_talent),
                                                       Helpers.LevelEntry(4, metahealer_wild_talent),
                                                       Helpers.LevelEntry(6, healing_buffer, metahealer_wild_talent),
                                                       Helpers.LevelEntry(8, metahealer_wild_talent),
                                                       Helpers.LevelEntry(10, metahealer_wild_talent),
                                                       Helpers.LevelEntry(12, metahealer_wild_talent),
                                                       Helpers.LevelEntry(14, metahealer_wild_talent),
                                                       Helpers.LevelEntry(16, metahealer_wild_talent),
                                                       Helpers.LevelEntry(18, metahealer_wild_talent),
                                                       Helpers.LevelEntry(20, metahealer_wild_talent) };

            archetype.OverrideAttributeRecommendations        = true;
            kineticist_class.Progression.UIDeterminatorsGroup = kineticist_class.Progression.UIDeterminatorsGroup.AddToArray(kinetic_chirurgery);
            kineticist_class.Archetypes = kineticist_class.Archetypes.AddToArray(archetype);

            //fix expanded element bonus
            wild_talent_selection.AddComponent(Common.prerequisiteNoArchetype(archetype));
            metahealer_wild_talent.AddComponent(Common.createPrerequisiteArchetypeLevel(archetype, 1));


            KineticistFix.expanded_element_bonus_talent_selection.AllFeatures = KineticistFix.expanded_element_bonus_talent_selection.AllFeatures.AddToArray(metahealer_wild_talent);
        }
Example #5
0
            void createBattleMasterHex()
            {
                battle_master_hex = Helpers.CreateFeatureSelection(prefix + "BattleMasterHex",
                                                                   "Battle Master",
                                                                   "The shaman makes an extra attack of opportunity each round. This ability stacks with the attacks of opportunity granted by the Combat Reflexes feat. At 8th level, the shaman gains the Weapon Specialization feat in a weapon of her choice as a bonus feat. At 16th level, the shaman gains the Greater Weapon Focus feat as a bonus feat, for the same weapon chosen for Weapon Specialization. The shaman doesn’t need to meet the prerequisites of these feats.",
                                                                   "",
                                                                   library.Get <BlueprintParametrizedFeature>("31470b17e8446ae4ea0dacd6c5817d86").Icon,
                                                                   FeatureGroup.None
                                                                   );



                foreach (var category in Enum.GetValues(typeof(WeaponCategory)).Cast <WeaponCategory>())
                {
                    var ws_feature = Helpers.CreateFeature(prefix + "BattleMasterHex" + category.ToString() + "WeaponSpecializationFeature",
                                                           "",
                                                           "",
                                                           "",
                                                           null,
                                                           FeatureGroup.None,
                                                           Common.createAddParametrizedFeatures(library.Get <BlueprintParametrizedFeature>("31470b17e8446ae4ea0dacd6c5817d86"), category)
                                                           );
                    ws_feature.HideInCharacterSheetAndLevelUp = true;
                    var gws_feature = Helpers.CreateFeature(prefix + "BattleMasterHex" + category.ToString() + "GreaterWeaponFocusFeature",
                                                            "",
                                                            "",
                                                            "",
                                                            null,
                                                            FeatureGroup.None,
                                                            Common.createAddParametrizedFeatures(library.Get <BlueprintParametrizedFeature>("09c9e82965fb4334b984a1e9df3bd088"), category)
                                                            );
                    gws_feature.HideInCharacterSheetAndLevelUp = true;
                    var feature = Helpers.CreateFeature(prefix + "BattleMasterHex" + category.ToString() + "Feature",
                                                        battle_master_hex.Name + $" ({LocalizedTexts.Instance.Stats.GetText(category)})",
                                                        battle_master_hex.Description,
                                                        "",
                                                        battle_master_hex.Icon,
                                                        FeatureGroup.None,
                                                        Helpers.CreateAddStatBonus(StatType.AttackOfOpportunityCount, 1, ModifierDescriptor.UntypedStackable),
                                                        Helpers.CreateAddFeatureOnClassLevel(ws_feature, 8, hex_engine.hex_classes),
                                                        Helpers.CreateAddFeatureOnClassLevel(gws_feature, 16, hex_engine.hex_classes),
                                                        Helpers.Create <PrerequisiteProficiency>(p =>
                    {
                        p.WeaponProficiencies = new WeaponCategory[] { category };
                        p.ArmorProficiencies  = new Kingmaker.Blueprints.Items.Armors.ArmorProficiencyGroup[0];
                    }));
                    battle_master_hex.AllFeatures = battle_master_hex.AllFeatures.AddToArray(feature);
                }
                battle_master_hex.AddComponent(Helpers.PrerequisiteNoFeature(battle_master_hex));
            }
        static internal void load()
        {
            var improved_unarmed_strike = library.Get <BlueprintFeature>("7812ad3672a4b9a4fb894ea402095167");
            var weapon_focus            = library.Get <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e");

            feral_combat_training = Helpers.CreateFeatureSelection("FeralCombatTrainingSelection",
                                                                   "Feral Combat Training",
                                                                   "Choose one of your natural weapons. While using the selected natural weapon, you can apply the effects of feats that have Improved Unarmed Strike as a prerequisite.\n"
                                                                   + "Special: If you are a monk, you can use the selected natural weapon with your flurry of blows class feature.",
                                                                   "",
                                                                   LoadIcons.Image2Sprite.Create(@"FeatIcons/Icon_Feral_Combat.png"),
                                                                   FeatureGroup.CombatFeat,
                                                                   Helpers.PrerequisiteFeature(improved_unarmed_strike)
                                                                   );
            feral_combat_training.HideInCharacterSheetAndLevelUp = true;

            foreach (var natural_weapon_entry in natural_weapon_entries)
            {
                feral_combat_training.AddComponent(Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true));
                var feral_combat_entry = Helpers.CreateFeature("FeralCombat" + natural_weapon_entry.category.ToString() + "Feature",
                                                               feral_combat_training.Name + $" ({natural_weapon_entry.name})",
                                                               feral_combat_training.Description,
                                                               "",
                                                               feral_combat_training.Icon,
                                                               FeatureGroup.CombatFeat,
                                                               Helpers.PrerequisiteFeature(improved_unarmed_strike),
                                                               Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true)
                                                               );
                natural_weapon_type_fact_map.Add(natural_weapon_entry.category, feral_combat_entry);
                feral_combat_training.AllFeatures = feral_combat_training.AllFeatures.AddToArray(feral_combat_entry);
                feral_combat_entry.Groups         = feral_combat_entry.Groups.AddToArray(FeatureGroup.Feat);
            }

            library.AddCombatFeats(feral_combat_training);

            ki_focus_weapon = library.CopyAndAdd <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e", "KiWeaponFeature", "");
            ki_focus_weapon.SetNameDescriptionIcon("Ki Weapon", "You can use ki attacks through the specified weapon as if they were unarmed attacks. These attacks include the monk’s ki strike, quivering palm, and the Stunning Fist feat", null);
            ki_focus_weapon.Groups          = new FeatureGroup[0];
            ki_focus_weapon.ComponentsArray = new BlueprintComponent[0];
            fixAbilities();
        }
        static internal void load()
        {
            var improved_unarmed_strike = library.Get <BlueprintFeature>("7812ad3672a4b9a4fb894ea402095167");
            var weapon_focus            = library.Get <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e");

            feral_combat_training = Helpers.CreateFeatureSelection("FeralCombatTrainingSelection",
                                                                   "Feral Combat Training",
                                                                   "Choose one of your natural weapons. While using the selected natural weapon, you can apply the effects of feats that have Improved Unarmed Strike as a prerequisite.\n"
                                                                   + "Special: If you are a monk, you can use the selected natural weapon with your flurry of blows class feature.",
                                                                   "",
                                                                   null,
                                                                   FeatureGroup.CombatFeat,
                                                                   Helpers.PrerequisiteFeature(improved_unarmed_strike)
                                                                   );
            feral_combat_training.HideInCharacterSheetAndLevelUp = true;

            foreach (var natural_weapon_entry in natural_weapon_entries)
            {
                feral_combat_training.AddComponent(Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true));
                var feral_combat_entry = Helpers.CreateFeature("FeralCombat" + natural_weapon_entry.category.ToString() + "Feature",
                                                               feral_combat_training.Name + $" ({natural_weapon_entry.name})",
                                                               feral_combat_training.Description,
                                                               "",
                                                               null,
                                                               FeatureGroup.CombatFeat,
                                                               Helpers.PrerequisiteFeature(improved_unarmed_strike),
                                                               Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true)
                                                               );
                natural_weapon_type_fact_map.Add(natural_weapon_entry.category, feral_combat_entry);
                feral_combat_training.AllFeatures = feral_combat_training.AllFeatures.AddToArray(feral_combat_entry);
                feral_combat_entry.Groups         = feral_combat_entry.Groups.AddToArray(FeatureGroup.Feat);
            }

            library.AddCombatFeats(feral_combat_training);
            fixAbilities();
        }
        static internal void load()
        {
            var improved_unarmed_strike = library.Get <BlueprintFeature>("7812ad3672a4b9a4fb894ea402095167");
            var weapon_focus            = library.Get <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e");

            feral_combat_training = Helpers.CreateFeatureSelection("FeralCombatTrainingSelection",
                                                                   "Feral Combat Training",
                                                                   "Choose one of your natural weapons. While using the selected natural weapon, you can apply the effects of feats that have Improved Unarmed Strike as a prerequisite.\n"
                                                                   + "Special: If you are a monk, you can use the selected natural weapon with your flurry of blows class feature.",
                                                                   "",
                                                                   LoadIcons.Image2Sprite.Create(@"FeatIcons/Icon_Feral_Combat.png"),
                                                                   FeatureGroup.CombatFeat,
                                                                   Helpers.PrerequisiteFeature(improved_unarmed_strike)
                                                                   );
            feral_combat_training.HideInCharacterSheetAndLevelUp = true;

            foreach (var natural_weapon_entry in natural_weapon_entries)
            {
                feral_combat_training.AddComponent(Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true));
                var feral_combat_entry = Helpers.CreateFeature("FeralCombat" + natural_weapon_entry.category.ToString() + "Feature",
                                                               feral_combat_training.Name + $" ({natural_weapon_entry.name})",
                                                               feral_combat_training.Description,
                                                               "",
                                                               feral_combat_training.Icon,
                                                               FeatureGroup.CombatFeat,
                                                               Helpers.PrerequisiteFeature(improved_unarmed_strike),
                                                               Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true)
                                                               );
                natural_weapon_type_fact_map.Add(natural_weapon_entry.category, feral_combat_entry);
                feral_combat_training.AllFeatures = feral_combat_training.AllFeatures.AddToArray(feral_combat_entry);
                feral_combat_entry.Groups         = feral_combat_entry.Groups.AddToArray(FeatureGroup.Feat);
            }

            library.AddCombatFeats(feral_combat_training);

            ki_focus_weapon = library.CopyAndAdd <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e", "KiWeaponFeature", "");
            ki_focus_weapon.SetNameDescriptionIcon("Ki Weapon", "You can use ki attacks through the specified weapon as if they were unarmed attacks. These attacks include the monk’s ki strike, quivering palm, and the Stunning Fist feat", null);
            ki_focus_weapon.Groups          = new FeatureGroup[0];
            ki_focus_weapon.ComponentsArray = new BlueprintComponent[0];

            var ki_strike_magic      = library.Get <BlueprintFeature>("1188005ee3160f84f8bed8b19a7d46cf");
            var ki_strike_cold_iron  = library.Get <BlueprintFeature>("7b657938fde78b14cae10fc0d3dcb991");
            var ki_strike_adamantine = library.Get <BlueprintFeature>("ddc10a3463bd4d54dbcbe993655cf64e");
            var ki_strike_lawful     = library.Get <BlueprintFeature>("1188005ee3160f84f8bed8b19a7d46cf");

            ki_strike_magic.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageMaterialIfParametrizedFeature>(a =>
            {
                a.add_magic = true;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                         );
            ki_strike_cold_iron.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageMaterialIfParametrizedFeature>(a =>
            {
                a.material = PhysicalDamageMaterial.ColdIron;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                             );
            ki_strike_adamantine.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageMaterialIfParametrizedFeature>(a =>
            {
                a.material = PhysicalDamageMaterial.Adamantite;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                              );
            ki_strike_lawful.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageAlignmentIfParametrizedFeature>(a =>
            {
                a.damage_alignment = DamageAlignment.Lawful;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                          );

            fixAbilities();
        }
Example #9
0
 static void createStyleMaster()
 {
     style_master = library.CopyAndAdd(Warpriest.sacred_fist_syle_feat_selection, "NinjaStyleMasterFeatureSelection", "");
     style_master.SetNameDescription("Style Master", "A ninja who selects this ninja trick gains a style feat that she qualifies for as a bonus feat.");
     style_master.AddComponent(Helpers.PrerequisiteNoFeature(style_master));
 }
        private static void CreateAdvancedWeaponTraining()
        {
            var fighter = Helpers.fighterClass;

            BlueprintFeature twoHandedWeaponFeature = library.Get <BlueprintFeature>("88da2a5dfc505054f933bb81014e864f");

            twoHandedWeaponFeature.AddComponent(twoHandedWeaponFeature.PrerequisiteFeature());


            BlueprintFeatureSelection advancedWeaponTraining = Helpers.CreateFeatureSelection("AdvancedWeaponTraining",
                                                                                              "Advanced Weapon Training",
                                                                                              "Beginning at 9th level, instead of selecting an additional fighter weapon group, a fighter can choose an advanced weapon training option for one fighter weapon group that he previously selected with the weapon training class feature.",
                                                                                              "e10b3aca8e8c4075b96ac6b5f27dae27",
                                                                                              WeaponTraining.Icon,
                                                                                              FeatureGroup.CombatFeat,
                                                                                              WeaponTraining.PrerequisiteFeature(true),
                                                                                              twoHandedWeaponFeature.PrerequisiteFeature(true),
                                                                                              fighter.PrerequisiteClassLevel(5)
                                                                                              );

            var features = getAdvancedWeaponTraining(fighter);

            var goBackFeature = Helpers.CreateFeature("0GoBack", "(Go Back)", "Helps to navigate in deep selection trees. Has no other use.", Helpers.getGuid("0GoBack"), null, FeatureGroup.None, Helpers.Create <UndoSelectionLogic>());
            var prerequisite  = Helpers.Create <PrerequisiteMeetsPrerequisiteForAny>();

            prerequisite.Features = features.ToArray();
            goBackFeature.AddComponent(prerequisite);

            advancedWeaponTraining.AddComponent(prerequisite);
            features.Add(goBackFeature);
            advancedWeaponTraining.SetFeatures(features);

            library.AddCombatFeats(advancedWeaponTraining);

            BlueprintFeatureSelection advancedWeaponTrainingForSelection = Helpers.CreateFeatureSelection("AdvancedWeaponTrainingLVL9",
                                                                                                          "Advanced Weapon Training",
                                                                                                          "Beginning at 9th level, instead of selecting an additional fighter weapon group, a fighter can choose an advanced weapon training option for one fighter weapon group that he previously selected with the weapon training class feature.",
                                                                                                          "914b143cd76b40dc91feb87d7c404b23",
                                                                                                          WeaponTraining.Icon,
                                                                                                          FeatureGroup.CombatFeat,
                                                                                                          Helpers.PrerequisiteFeature(WeaponTraining),
                                                                                                          fighter.PrerequisiteClassLevel(9)
                                                                                                          );

            BlueprintFeatureSelection advancedWeaponTrainingForSelectionLVL13 = Helpers.CreateFeatureSelection("AdvancedWeaponTrainingLVL13",
                                                                                                               "Advanced Weapon Training",
                                                                                                               "Beginning at 9th level, instead of selecting an additional fighter weapon group, a fighter can choose an advanced weapon training option for one fighter weapon group that he previously selected with the weapon training class feature.",
                                                                                                               Helpers.getGuid("AdvancedWeaponTrainingLVL13"),
                                                                                                               WeaponTraining.Icon,
                                                                                                               FeatureGroup.CombatFeat,
                                                                                                               WeaponTraining.PrerequisiteFeature(),
                                                                                                               fighter.PrerequisiteClassLevel(13)
                                                                                                               );

            BlueprintFeatureSelection advancedWeaponTrainingForSelectionLVL17 = Helpers.CreateFeatureSelection("AdvancedWeaponTrainingLVL17",
                                                                                                               "Advanced Weapon Training",
                                                                                                               "Beginning at 9th level, instead of selecting an additional fighter weapon group, a fighter can choose an advanced weapon training option for one fighter weapon group that he previously selected with the weapon training class feature.",
                                                                                                               Helpers.getGuid("AdvancedWeaponTrainingLVL17"),
                                                                                                               WeaponTraining.Icon,
                                                                                                               FeatureGroup.CombatFeat,
                                                                                                               Helpers.PrerequisiteFeature(WeaponTraining),
                                                                                                               fighter.PrerequisiteClassLevel(17)
                                                                                                               );

            advancedWeaponTrainingForSelection.SetFeatures(features);
            advancedWeaponTrainingForSelection.AddComponent(prerequisite);
            advancedWeaponTrainingForSelectionLVL13.SetFeatures(features);
            advancedWeaponTrainingForSelectionLVL13.AddComponent(prerequisite);
            advancedWeaponTrainingForSelectionLVL17.SetFeatures(features);
            advancedWeaponTrainingForSelectionLVL17.AddComponent(prerequisite);


            WeaponTraining.SetFeatures(WeaponTraining.AllFeatures.AddToArray(advancedWeaponTrainingForSelection, advancedWeaponTrainingForSelectionLVL13, advancedWeaponTrainingForSelectionLVL17));
        }
        private static List <BlueprintFeature> getAdvancedWeaponTraining(BlueprintCharacterClass fighter)
        {
            var weaponFocus   = library.Get <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e");
            var weaponFinesse = library.Get <BlueprintFeature>("90e54424d682d104ab36436bd527af09");
            var features      = new List <BlueprintFeature>();

            FillWeaponFocusAndWeaponTrainingDictionaries();
            CreateAbilityMoveActions();


            foreach (var weaponTraining in _weaponTrainingBluePrints)
            {
                string weaponTrainingName        = getWeaponTrainingName(weaponTraining, true);
                string weaponTrainingDisplayName = getWeaponTrainingName(weaponTraining);


                string newAssetID = Helpers.getGuid("FocusedWeapon" + weaponTrainingName);

                var focusedWeaponSpecific = Helpers.Create <BlueprintParametrizedFeatureWeaponTraining>(x => x.WeaponTraining = weaponTraining);
                Helpers.SetFeatureInfo(focusedWeaponSpecific, "FocusedWeapon" + weaponTrainingName,
                                       "Focused Weapon (" + weaponTrainingDisplayName + ")", "The fighter selects one weapon for which he has Weapon Focus and that belongs to the associated fighter weapon group. The fighter can deal damage with this weapon based on the damage of the warpriest’s sacred weapon class feature, treating his fighter level as his warpriest level. The fighter must have Weapon Focus with the selected weapon in order to choose this option.",
                                       newAssetID,
                                       WeaponTraining.Icon,
                                       FeatureGroup.Feat,
                                       weaponFocus.PrerequisiteFeature(),
                                       weaponTraining.PrerequisiteFeature(),
                                       Helpers.Create <FocusedWeaponLogic>());
                focusedWeaponSpecific.ParameterType = FeatureParameterType.WeaponCategory;
                focusedWeaponSpecific.Prerequisite  = weaponFocus;
                focusedWeaponSpecific.Ranks         = 1;

                features.Add(focusedWeaponSpecific);


                features.Add(Helpers.CreateFeature(
                                 "ArmedBravery" + weaponTrainingName,
                                 "Armed Bravery (" + weaponTrainingDisplayName + ")",
                                 "The fighter applies his bonus from bravery to Will saving throws. In addition, the DC of Intimidate checks to demoralize him increases by an amount equal to twice his bonus from bravery. The fighter must have the bravery class feature in order to select this option.",
                                 Helpers.getGuid("ArmedBravery" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 BraveryFeature.PrerequisiteFeature(),
                                 Helpers.Create <ArmedBraveryLogic>(x => x.WeaponTraining = weaponTraining)
                                 ));

                features.Add(Helpers.CreateFeature(
                                 "CombatManeuverDefense" + weaponTrainingName,
                                 "Combat Maneuver Defense (" + weaponTrainingDisplayName + ")",
                                 "When the fighter is wielding weapons from the associated weapon group, his weapon training bonus applies to his CMD against all combat maneuvers attempted against him, instead of just against disarm and sunder combat maneuvers.",
                                 Helpers.getGuid("CombatManeuverDefense" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 Helpers.Create <CombatManeuverDefenseLogic>(x => x.WeaponTraining = weaponTraining)
                                 ));

                features.Add(Helpers.CreateFeature(
                                 "DazzlingIntimidation" + weaponTrainingName,
                                 "Dazzling Intimidation (" + weaponTrainingDisplayName + ")",
                                 "The fighter applies his weapon training bonus to Intimidate checks and can attempt an Intimidate check to demoralize an opponent as a move action instead of a standard action. If he has the Dazzling Display feat, he can use it as a standard action instead of a full-round action.",
                                 Helpers.getGuid("DazzlingIntimidation" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 Helpers.Create <DazzlingIntimidationLogic>(x => x.WeaponTraining = weaponTraining)
                                 ));

                features.Add(Helpers.CreateFeature(
                                 "DefensiveWeaponTraining" + weaponTrainingName,
                                 "Defensive Weapon Training (" + weaponTrainingDisplayName + ")",
                                 "The fighter gains a +1 shield bonus to his Armor Class. The fighter adds half his weapon’s enhancement bonus (if any) to this shield bonus. When his weapon training bonus for weapons from the associated fighter weapon group reaches +4, this shield bonus increases to +2. This shield bonus is lost if the fighter is immobilized or helpless.",
                                 Helpers.getGuid("DefensiveWeaponTraining" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 Helpers.Create <DefensiveWeaponTrainingLogic>(x => x.WeaponTraining = weaponTraining)
                                 ));

                features.Add(Helpers.CreateFeature(
                                 "EffortlessDualWielding" + weaponTrainingName,
                                 "Effortless Dual-Wielding (" + weaponTrainingDisplayName + ")",
                                 "The fighter treats all one-handed weapons that belong to the associated weapon group as though they were light weapons when determining his penalties on attack rolls for fighting with two weapons.",
                                 Helpers.getGuid("EffortlessDualWielding" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 Helpers.Create <EffortlessDualWieldingLogic>(x => x.WeaponTraining = weaponTraining)
                                 ));

                BlueprintFeatureSelection versatileTraining = Helpers.CreateFeatureSelection(
                    "VersatileTraining" + weaponTrainingName,
                    "Versatile Training (" + weaponTrainingDisplayName + ")",
                    "The fighter can use his base attack bonus in place of his ranks in two skills of his choice that are associated with the fighter weapon group he has chosen with this option (see below). The fighter need not be wielding an associated weapon to use this option. When using versatile training, the fighter substitutes his total base attack bonus (including his base attack bonus gained through levels in other classes) for his ranks in these skills, but adds the skill’s usual ability score modifier and any other bonuses or penalties that would modify those skills. Once the skills have been selected, they cannot be changed and the fighter can immediately retrain all of his skill ranks in the selected skills at no additional cost in money or time. In addition, the fighter adds all skills chosen with this option to his list of class skills. A fighter can choose this option up to two times. The Bluff and Intimidate skills are associated with all fighter weapon groups. The various fighter weapon groups also have the following associated skills: axes (Climb, Survival), bows (Knowledge [engineering], Perception), close (Sense Motive, Stealth), crossbows (Perception, Stealth), double (Acrobatics, Sense Motive), firearms (Perception, Sleight of Hand), flails (Acrobatics, Sleight of Hand), hammers (Diplomacy, Ride), heavy blades (Diplomacy, Ride), light blades (Diplomacy, Sleight of Hand), monk (Acrobatics, Escape Artist), natural (Climb, Fly, Swim), polearms (Diplomacy, Sense Motive), siege engines (Disable Device, Profession [driver]), spears (Handle Animal, Ride), and thrown (Acrobatics, Perception)",
                    Helpers.getGuid("VersatileTraining" + weaponTrainingName),
                    WeaponTraining.Icon,
                    FeatureGroup.CombatFeat,
                    weaponTraining.PrerequisiteFeature());

                List <BlueprintFeature> versatileTrainingFeatures = new List <BlueprintFeature>();
                WeaponGroupAttackBonus  weaponGroupAttackBonus    = weaponTraining.GetComponent <WeaponGroupAttackBonus>();
                if (weaponGroupAttackBonus != null)
                {
                    foreach (var statType in _weaponTrainingToStatType[weaponGroupAttackBonus.WeaponGroup])
                    {
                        versatileTrainingFeatures.Add(Helpers.CreateFeature(
                                                          "VersatileTraining" + weaponTrainingName + statType,
                                                          "Versatile Training (" + statType + ")",
                                                          "The fighter treats all one-handed weapons that belong to the associated weapon group as though they were light weapons when determining his penalties on attack rolls for fighting with two weapons.",
                                                          Helpers.getGuid("VersatileTraining" + weaponTrainingDisplayName + statType),
                                                          WeaponTraining.Icon,
                                                          FeatureGroup.CombatFeat,
                                                          weaponTraining.PrerequisiteFeature(),
                                                          Helpers.Create <SetSkillRankToBabLogic>(x => x.type = statType)));
                    }
                }

                versatileTraining.AddComponent(Helpers.Create <PrerequisiteMeetsPrerequisiteForAny>(x => x.Features = versatileTrainingFeatures.ToArray()));
                versatileTraining.SetFeatures(versatileTrainingFeatures);
                features.Add(versatileTraining);

                var fightersFinesse = Helpers.CreateFeature(
                    "FightersFinesse" + weaponTrainingName,
                    "Fighter’s Finesse (" + weaponTrainingDisplayName + ")",
                    "The fighter gains the benefits of the Weapon Finesse feat with all melee weapons that belong to the associated fighter weapon group (even if they cannot normally be used with Weapon Finesse). The fighter must have the Weapon Finesse feat before choosing this option.",
                    Helpers.getGuid("FightersFinesse" + weaponTrainingName),
                    WeaponTraining.Icon,
                    FeatureGroup.CombatFeat,
                    weaponTraining.PrerequisiteFeature(),
                    weaponFinesse.PrerequisiteFeature(),
                    Helpers.Create <FightersFinesseLogic>(x => x.WeaponTraining = weaponTraining));
                features.Add(fightersFinesse);

                features.Add(Helpers.CreateFeature(
                                 "TrainedGrace" + weaponTrainingName,
                                 "Trained Grace (" + weaponTrainingDisplayName + ")",
                                 "When the fighter uses Weapon Finesse to make a melee attack with a weapon, using his Dexterity modifier on attack rolls and his Strength modifier on damage rolls, he doubles his weapon training bonus on damage rolls. The fighter must have Weapon Finesse in order to choose this option.",
                                 Helpers.getGuid("TrainedGrace" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 weaponFinesse.PrerequisiteFeature(),
                                 Helpers.Create <TrainedGraceLogic>(x =>
                {
                    x.WeaponFighterGroupFeature = weaponTraining;
                    x.FightersFinesseFeature    = fightersFinesse;
                })));

                features.Add(Helpers.CreateFeature(
                                 "FightersReflexes" + weaponTrainingName,
                                 "Fighter’s Reflexes (" + weaponTrainingDisplayName + ")",
                                 "The fighter applies his weapon training bonus to Reflex saving throws. He loses this bonus when he is flat-footed or denied his Dexterity bonus to AC.",
                                 Helpers.getGuid("FightersReflexes" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 Helpers.Create <FightersReflexesLogic>(x => x.WeaponTraining = weaponTraining)));

                features.Add(Helpers.CreateFeature(
                                 "FightersTactics" + weaponTrainingName,
                                 "Fighter’s Tactics (" + weaponTrainingDisplayName + ")",
                                 "All of the fighter’s allies are treated as if they had the same teamwork feats as the fighter for the purpose of determining whether the fighter receives a bonus from his teamwork feats. His allies do not receive any bonuses from these feats unless they actually have the feats themselves. The allies’ positioning and actions must still meet the prerequisites listed in the teamwork feat for the fighter to receive the listed bonus.",
                                 Helpers.getGuid("FightersTactics" + weaponTrainingName),
                                 WeaponTraining.Icon,
                                 FeatureGroup.CombatFeat,
                                 weaponTraining.PrerequisiteFeature(),
                                 Helpers.Create <FightersTacticsLogic>(x => x.WeaponTraining = weaponTraining)));
            }

            features.AddRange(AddWarriorSpirit());

            return(features);
        }
Example #12
0
        private static List <BlueprintFeature> getAdvancedArmorTrainings(BlueprintFeature armorTraining, BlueprintCharacterClass fighter)
        {
            List <BlueprintFeature> list = new List <BlueprintFeature>();

            list.Add(Helpers.CreateFeature("ArmoredConfidence", "Armored Confidence",
                                           "While wearing armor, the fighter gains a bonus on Intimidate checks based upon the type of armor he is wearing: +1 for light armor, +2 for medium armor, or +3 for heavy armor. This bonus increases by 1 at 7th level and every 4 fighter levels thereafter, to a maximum of +4 at 19th level. In addition, the fighter adds half his armored confidence bonus to the DC of Intimidate checks to demoralize him.",
                                           "0d9cafb651a6427b950fb4a049126561",
                                           armorTraining.Icon,
                                           FeatureGroup.CombatFeat,
                                           Helpers.PrerequisiteFeature(armorTraining),
                                           Helpers.PrerequisiteClassLevel(fighter, 3),
                                           Helpers.Create <ArmoredConfidenceLogic>()));
            list.Add(Helpers.CreateFeature("ArmoredJuggernaut", "Armored Juggernaut",
                                           "When wearing heavy armor, the fighter gains DR 1/—. At 7th level, the fighter gains DR 1/— when wearing medium armor, and DR 2/— when wearing heavy armor. At 11th level, the fighter gains DR 1/— when wearing light armor, DR 2/— when wearing medium armor, and DR 3/— when wearing heavy armor. If the fighter is 19th level and has the armor mastery class feature, these DR values increase by 5. The DR from this ability stacks with that provided by adamantine armor, but not with other forms of damage reduction. This damage reduction does not apply if the fighter is helpless, stunned, or unconscious.",
                                           "74485919028943a5affacab602164ef7",
                                           armorTraining.Icon,
                                           FeatureGroup.CombatFeat,
                                           Helpers.PrerequisiteFeature(armorTraining),
                                           Helpers.PrerequisiteClassLevel(fighter, 3), Helpers.Create <ArmoredJuggernautLogic>()));

            BlueprintFeatureSelection adaptableTraining = Helpers.CreateFeatureSelection("AdaptableTraining", "Adaptable Training",
                                                                                         "The fighter can use his base attack bonus in place of his ranks in one skill of his choice from the following list: Mobility or Athletics. The fighter need not be wearing armor or using a shield to use this option. When using adaptable training, the fighter substitutes his total base attack bonus (including his base attack bonus gained through levels in other classes) for his ranks in this skill, but adds the skill’s usual ability score modifier and any other bonuses or penalties that would modify that skill. Once a skill has been selected, it cannot be changed and the fighter can immediately retrain all of his ranks in the selected skill at no additional cost in money or time. In addition, the fighter adds all skills chosen with this option to his list of class skills. A fighter can choose this option once.",
                                                                                         "94db2d5bc745417db94c68c463ab490d",
                                                                                         armorTraining.Icon,
                                                                                         FeatureGroup.CombatFeat,
                                                                                         Helpers.PrerequisiteFeature(armorTraining),
                                                                                         Helpers.PrerequisiteClassLevel(fighter, 3));

            BlueprintFeature adaptableTrainingMobility = Helpers.CreateFeature("AdaptableTrainingMobility", "Adaptable Training (Mobility)",
                                                                               "The fighter uses his base attack bonus in place of his ranks in Mobility. The fighter need not be wearing armor or using a shield to use this option. When using adaptable training, the fighter substitutes his total base attack bonus (including his base attack bonus gained through levels in other classes) for his ranks in this skill, but adds the skill’s usual ability score modifier and any other bonuses or penalties that would modify that skill. Once a skill has been selected, it cannot be changed and the fighter can immediately retrain all of his ranks in the selected skill at no additional cost in money or time. In addition, the fighter adds all skills chosen with this option to his list of class skills. A fighter can choose this option once.",
                                                                               "0f7a885d28024b03b992e15ff453db00",
                                                                               armorTraining.Icon,
                                                                               FeatureGroup.CombatFeat,
                                                                               Helpers.PrerequisiteFeature(armorTraining),
                                                                               Helpers.PrerequisiteClassLevel(fighter, 3),
                                                                               Helpers.Create <SetSkillRankToBabLogic>(b => b.type = Kingmaker.EntitySystem.Stats.StatType.SkillMobility));
            BlueprintFeature adaptableTrainingAthletics = Helpers.CreateFeature("AdaptableTrainingAthletics", "Adaptable Training (Athletics)",
                                                                                "The fighter uses his base attack bonus in place of his ranks in Athletics. The fighter need not be wearing armor or using a shield to use this option. When using adaptable training, the fighter substitutes his total base attack bonus (including his base attack bonus gained through levels in other classes) for his ranks in this skill, but adds the skill’s usual ability score modifier and any other bonuses or penalties that would modify that skill. Once a skill has been selected, it cannot be changed and the fighter can immediately retrain all of his ranks in the selected skill at no additional cost in money or time. In addition, the fighter adds all skills chosen with this option to his list of class skills. A fighter can choose this option once.",
                                                                                "91b76275af7441afb0c88811f25f7131",
                                                                                armorTraining.Icon,
                                                                                FeatureGroup.CombatFeat,
                                                                                Helpers.PrerequisiteFeature(armorTraining),
                                                                                Helpers.PrerequisiteClassLevel(fighter, 3),
                                                                                Helpers.Create <SetSkillRankToBabLogic>(b => b.type = Kingmaker.EntitySystem.Stats.StatType.SkillAthletics));

            adaptableTraining.AddComponent(adaptableTraining.PrerequisiteNoFeature());
            adaptableTraining.SetFeatures(adaptableTrainingMobility, adaptableTrainingAthletics);
            list.Add(adaptableTraining);

            BlueprintFeatureSelection armorSpecialization = Helpers.CreateFeatureSelection("ArmorSpecialization", "Armor Specialization",
                                                                                           "The fighter selects one specific type of armor with which he is proficient, such as chain shirts or scale mail. While wearing the selected type of armor, the fighter adds one-quarter of his fighter level to the armor’s armor bonus, up to a maximum bonus of +3 for light armor, +4 for medium armor, or +5 for heavy armor. This increase to the armor bonus doesn’t increase the benefit that the fighter gains from feats, class abilities, or other effects that are determined by his armor’s base armor bonus, including other advanced armor training options. A fighter can choose this option multiple times. Each time he chooses it, he applies its benefit to a different type of armor.",
                                                                                           "59d7a65500f34c4997bfb27ec93c15ec",
                                                                                           armorTraining.Icon,
                                                                                           FeatureGroup.CombatFeat,
                                                                                           Helpers.PrerequisiteFeature(armorTraining),
                                                                                           Helpers.PrerequisiteClassLevel(fighter, 3));

            Dictionary <string, BlueprintFeature> armorSpecializationFeatureList = new Dictionary <string, BlueprintFeature>();

            foreach (BlueprintArmorType armorType in Resources.FindObjectsOfTypeAll <BlueprintArmorType>())
            {
                string guidString = Helpers.getGuid("ArmorSpecialization" + armorType.DefaultName);
                if ((armorType.ProficiencyGroup == ArmorProficiencyGroup.Heavy ||
                     armorType.ProficiencyGroup == ArmorProficiencyGroup.Medium ||
                     armorType.ProficiencyGroup == ArmorProficiencyGroup.Light) &&
                    !armorSpecializationFeatureList.ContainsKey(guidString))
                {
                    BlueprintFeature armorSpecializationForType = Helpers.CreateFeature("ArmorSpecialization" + armorType.DefaultName, "Armor Specialization (" + armorType.DefaultName + ")",
                                                                                        "Armor Specialization in " + armorType.DefaultName,
                                                                                        guidString,
                                                                                        armorTraining.Icon,
                                                                                        FeatureGroup.CombatFeat,
                                                                                        Helpers.PrerequisiteFeature(armorTraining),
                                                                                        Helpers.PrerequisiteClassLevel(fighter, 3),
                                                                                        Helpers.Create <ArmorSpecializationLogic>(b => b.BlueprintArmorType = armorType));
                    armorSpecializationFeatureList.Add(guidString, armorSpecializationForType);
                }
            }
            armorSpecialization.SetFeatures(armorSpecializationFeatureList.Values);

            list.Add(armorSpecialization);

            list.Add(Helpers.CreateFeature("SteelHeadbutt", "Steel Headbutt",
                                           "While wearing medium or heavy armor, a fighter can deliver a headbutt with his helm as part of a full attack action. This headbutt is in addition to his normal attacks, and is made using the fighter’s base attack bonus – 5. A helmet headbutt deals 1d3 points of damage if the fighter is wearing medium armor, or 1d4 points of damage if he is wearing heavy armor (1d2 and 1d3, respectively, for Small creatures), plus an amount of damage equal to 1/2 the fighter’s Strength modifier. Treat this attack as a weapon attack made using the same special material (if any) as the armor. The armor’s enhancement bonus does modify the headbutt attack.",
                                           "07cf0a9960f14e8e8e93a449d3a750aa",
                                           armorTraining.Icon,
                                           FeatureGroup.CombatFeat,
                                           Helpers.PrerequisiteFeature(armorTraining),
                                           Helpers.PrerequisiteClassLevel(fighter, 3),
                                           Helpers.Create <SteelHeadbuttLogic>()));

            return(list);
        }
Example #13
0
        public static BlueprintFeatureSelection CreateRaceTraits(BlueprintFeatureSelection adopted)
        {
            var noFeature  = Helpers.PrerequisiteNoFeature(null);
            var raceTraits = Helpers.CreateFeatureSelection("RaceTrait", RES.RaceTraitName_info,
                                                            RES.RaceTraitDescription_info,
                                                            "6264aa9515be40cda55892da93685764", null, FeatureGroup.None,
                                                            Helpers.PrerequisiteNoFeature(adopted), noFeature);

            noFeature.Feature = raceTraits;

            var humanReq = Helpers.PrerequisiteFeaturesFromList(Helpers.human, Helpers.halfElf, Helpers.halfOrc,
                                                                // Note: Aasimar/Tiefling included under the assumption they have "Scion of Humanity"/"Pass for Human"
                                                                Helpers.aasimar, Helpers.tiefling);

            var halfElfReq  = Helpers.PrerequisiteFeature(Helpers.halfElf);
            var halfOrcReq  = Helpers.PrerequisiteFeature(Helpers.halfOrc);
            var elfReq      = Helpers.PrerequisiteFeaturesFromList(Helpers.elf, Helpers.halfElf);
            var dwarfReq    = Helpers.PrerequisiteFeature(Helpers.dwarf);
            var halflingReq = Helpers.PrerequisiteFeature(Helpers.halfling);
            var gnomeReq    = Helpers.PrerequisiteFeature(Helpers.gnome);
            var aasimarReq  = Helpers.PrerequisiteFeature(Helpers.aasimar);
            var tieflingReq = Helpers.PrerequisiteFeature(Helpers.tiefling);

            // TODO: how do we code prerequisites so they aren't ignored by "Adopted"?
            // (only race prereq should be ignored, not others)
            //
            // Note: half-elf, half-orc can take traits from either race.
            // Also Aasimar/Tiefling are treated as having Scion of Humanity/Pass for Human in the game.
            var choices = new List <BlueprintFeature>();

            // Human:
            // - Carefully Hidden (+1 will save, +2 vs divination)
            // - Fanatic (Arcana)
            // - Historian (World and +1 bardic knowledge if Bard)
            // - Shield Bearer (+1 dmg shield bash)
            // - Superstitious (+1 save arcane spells)
            // - World Traveler (choose: persuasion, perception, or world)

            var components = new List <BlueprintComponent> {
                humanReq
            };

            components.Add(Helpers.CreateAddStatBonus(StatType.SaveWill, 1, ModifierDescriptor.Trait));
            components.Add(Helpers.Create <SavingThrowBonusAgainstSchool>(a =>
            {
                a.School             = SpellSchool.Divination;
                a.Value              = 2;
                a.ModifierDescriptor = ModifierDescriptor.Trait;
            }));
            choices.Add(Helpers.CreateFeature("CarefullyHiddenTrait", RES.RaceCarefullyHiddenTraitName_info,
                                              RES.RaceCarefullyHiddenTraitDescription_info,
                                              "38b92d2ebb4c4cdb8e946e29f5b2f178",
                                              Helpers.GetIcon("175d1577bb6c9a04baf88eec99c66334"), // Iron Will
                                              FeatureGroup.None,
                                              components.ToArray()));

            choices.Add(Traits.CreateAddStatBonus("FanaticTrait", RES.RaceFanaticTraitName_info,
                                                  RES.RaceFanaticTraitDescription_info,
                                                  "6427e81ba399406c93b463c284a42055",
                                                  StatType.SkillKnowledgeArcana,
                                                  humanReq));

            var bardicKnowledge = Traits.library.Get <BlueprintFeature>("65cff8410a336654486c98fd3bacd8c5");

            components.Clear();
            components.Add(humanReq);
            components.AddRange((new StatType[] {
                StatType.SkillKnowledgeArcana,
                StatType.SkillKnowledgeWorld,
                StatType.SkillLoreNature,
                StatType.SkillLoreReligion,
            }).Select((skill) => Helpers.Create <AddStatBonusIfHasFact>(a =>
            {
                a.Stat        = skill;
                a.Value       = 1;
                a.CheckedFact = bardicKnowledge;
                a.Descriptor  = ModifierDescriptor.UntypedStackable;
            })));

            var historian = Traits.CreateAddStatBonus("HistorianTrait", RES.RaceHistorianTraitName_info,
                                                      RES.RaceHistorianTraitDescription_info,
                                                      "4af3871899e4440bae03d4c33d4b52fd",
                                                      StatType.SkillKnowledgeWorld,
                                                      components.ToArray());

            choices.Add(historian);

            components.Clear();
            components.Add(humanReq);
            components.AddRange(new String[] {
                "98a0dc03586a6d04791901c41700e516", // SpikedLightShield
                "1fd965e522502fe479fdd423cca07684", // WeaponLightShield
                "a1b85d048fb5003438f34356df938a9f", // SpikedHeavyShield
                "be9b6408e6101cb4997a8996484baf19"  // WeaponHeavyShield
            }.Select(id => Helpers.Create <WeaponTypeDamageBonus>(w => { w.DamageBonus = 1; w.WeaponType = Traits.library.Get <BlueprintWeaponType>(id); })));

            choices.Add(Helpers.CreateFeature("ShieldBearerTrait", RES.RaceShieldBearerTraitName_info,
                                              RES.RaceShieldBearerTraitDescription_info,
                                              "044ebbbadfba4d58afa11bfbf38df199",
                                              Helpers.GetIcon("121811173a614534e8720d7550aae253"), // Shield Bash
                                              FeatureGroup.None,
                                              components.ToArray()));

            choices.Add(Helpers.CreateFeature("SuperstitiousTrait", RES.RaceSuperstitiousTraitName_info,
                                              RES.RaceSuperstitiousTraitDescription_info,
                                              "f5d79e5fbb87473ca0b13ed15b742079",
                                              Helpers.GetIcon("2483a523984f44944a7cf157b21bf79c"), // Elven Immunities
                                              FeatureGroup.None,
                                              humanReq,
                                              Helpers.Create <SavingThrowBonusAgainstSpellSource>()));

            //var travelerDescription = "Your family has taken the love of travel to an extreme, roaming the world extensively. You've seen dozens of cultures and have learned to appreciate the diversity of what the world has to offer.";
            var worldTraveler = Helpers.CreateFeatureSelection("WorldTravelerTrait", RES.RaceWorldTravelerTraitName_info,
                                                               RES.RaceWorldTravelerTraitDescription_info + RES.RaceWorldTravelerTraitBenefit_info,
                                                               "ecacfcbeddfe453cafc8d60fc1db7d34",
                                                               Helpers.GetIcon("3adf9274a210b164cb68f472dc1e4544"), // Human Skilled
                                                               FeatureGroup.None,
                                                               humanReq);

            var travelerFeats = new StatType[] {
                StatType.SkillPersuasion,
                StatType.SkillKnowledgeWorld,
                StatType.SkillPerception
            }.Select(skill => Traits.CreateAddStatBonus(
                         $"WorldTraveler{skill}Trait",
                         String.Format(RES.TypeHyphenSubtype_info,
                                       RES.RaceWorldTravelerTraitName_info.Substring(0, RES.RaceWorldTravelerTraitName_info.IndexOf("(") >= 0 ?
                                                                                     RES.RaceWorldTravelerTraitName_info.IndexOf("(") : RES.RaceWorldTravelerTraitName_info.IndexOf("(")),
                                       UIUtility.GetStatText(skill)),
                         RES.RaceWorldTravelerTraitDescription_info,
                         Helpers.MergeIds(Helpers.GetSkillFocus(skill).AssetGuid, "9b03b7ff17394007a3fbec18aa42604b"),
                         skill)).ToArray();

            worldTraveler.SetFeatures(travelerFeats);
            choices.Add(worldTraveler);

            // Elf:
            // - Dilettante Artist (persuasion)
            // - Forlorn (+1 fort save)
            // - Warrior of the Old (+2 init)
            // - Youthful Mischief (+1 ref)
            choices.Add(Traits.CreateAddStatBonus("DilettanteArtistTrait", RES.DilettanteArtistTraitName_info,
                                                  RES.DilettanteArtistTraitDescription_info,
                                                  "ac5a16e72ef74b4884c674dcbb61692c",
                                                  StatType.SkillPersuasion, elfReq));

            choices.Add(Helpers.CreateFeature("ForlornTrait", RES.ForlornTraitName_info,
                                              RES.ForlornTraitDescription_info,
                                              "1511289c92ea4233b14c4f51072ea10f",
                                              Helpers.GetIcon("79042cb55f030614ea29956177977c52"), // Great Fortitude
                                              FeatureGroup.None,
                                              elfReq,
                                              Helpers.CreateAddStatBonus(StatType.SaveFortitude, 1, ModifierDescriptor.Trait)
                                              ));

            choices.Add(Helpers.CreateFeature("WarriorOfOldTrait", RES.WarriorOfOldTraitName_info,
                                              RES.WarriorOfOldTraitDescription_info,
                                              "dc36a2c52abb4e6dbff549ac65a5a171",
                                              Helpers.GetIcon("797f25d709f559546b29e7bcb181cc74"), // Improved Initiative
                                              FeatureGroup.None,
                                              elfReq,
                                              Helpers.CreateAddStatBonus(StatType.Initiative, 2, ModifierDescriptor.Trait)));

            choices.Add(Helpers.CreateFeature("YouthfulMischiefTrait", RES.YouthfulMischiefTraitName_info,
                                              RES.YouthfulMischiefTraitDescription_info,
                                              "bfcc574d1f214455ac369fa46e07200e",
                                              Helpers.GetIcon("15e7da6645a7f3d41bdad7c8c4b9de1e"), // Lightning Reflexes
                                              FeatureGroup.None,
                                              elfReq,
                                              Helpers.CreateAddStatBonus(StatType.SaveReflex, 1, ModifierDescriptor.Trait)));

            // Half-orc:
            // - Brute (persuasion)
            // - Legacy of Sand (+1 will save)
            var brute = Traits.CreateAddStatBonus("BruteTrait", RES.BruteTraitName_info,
                                                  RES.BruteTraitDescription_info,
                                                  "1ee0ce55ace74ccbb798e2fdc13181f6", StatType.SkillPersuasion, halfOrcReq);

            brute.SetIcon(Helpers.GetIcon("885f478dff2e39442a0f64ceea6339c9")); // Intimidating
            choices.Add(brute);

            BlueprintItemWeapon bite = Traits.library.CopyAndAdd <BlueprintItemWeapon>("35dfad6517f401145af54111be04d6cf", "Tusked",
                                                                                       "44dfad6517f401145af54111be04d644");

            choices.Add(Helpers.CreateFeature("TuskedTrait", RES.TuskedTraitName_info,
                                              RES.TuskedTraitDescription_info,
                                              "1511289c92ea4233b14c4f51072ea09g",
                                              Image2Sprite.Create("Mods/EldritchArcana/sprites/halforc_tusked.png"), // Great Fortitude
                                              FeatureGroup.None,
                                              halfOrcReq,
                                              Helpers.Create <AddAdditionalLimb>(x => x.Weapon = bite)
                                              ));

            choices.Add(Helpers.CreateFeature("LegacyOfSandTrait", RES.LegacyOfSandTraitName_info,
                                              RES.LegacyOfSandTraitDescription_info,
                                              "e5fb1675eb6e4ef9accef7eb3a10862a",
                                              Image2Sprite.Create("Mods/EldritchArcana/sprites/halforc_legacy_of_sand.png"),
                                              FeatureGroup.None,
                                              halfOrcReq,
                                              Helpers.CreateAddStatBonus(StatType.SaveWill, 1, ModifierDescriptor.Trait)));

            // Half-elf:
            // - Elven Relexes (+2 initiative)
            // - Failed Apprentice (+1 save arcane spells)
            choices.Add(Helpers.CreateFeature("ElvenReflexsTrait", RES.ElvenReflexsTraitName_info,
                                              RES.ElvenReflexsTraitDescription_info,
                                              "9975678ce2fc420da9cd6ec4fe8c8b9b",
                                              Helpers.GetIcon("797f25d709f559546b29e7bcb181cc74"), // Improved Initiative
                                              FeatureGroup.None,
                                              halfElfReq,
                                              Helpers.CreateAddStatBonus(StatType.Initiative, 2, ModifierDescriptor.Trait)));

            choices.Add(Helpers.CreateFeature("FailedAprenticeTrait", RES.FailedAprenticeTraitName_info,
                                              RES.FailedAprenticeTraitDescription_info,
                                              "8ed66066751f43c2920055dd6358adc8",
                                              Helpers.GetIcon("2483a523984f44944a7cf157b21bf79c"), // Elven Immunities
                                              FeatureGroup.None,
                                              halfElfReq,
                                              Helpers.Create <SavingThrowBonusAgainstSpellSource>()));

            // Halfling:
            // - Freed Slave (world)
            // - Freedom Fighter (mobility)
            // - Well-Informed (persuasion)
            choices.Add(Traits.CreateAddStatBonus("FreedSlaveTrait", RES.FreedSlaveTraitName_info,
                                                  RES.FreedSlaveTraitDescription_info,
                                                  "d2fc5fe0c64142a79e0ebee18f14b0be", StatType.SkillKnowledgeWorld, halflingReq));
            choices.Add(Traits.CreateAddStatBonus("FreedomFighterTrait", RES.FreedomFighterTraitName_info,
                                                  RES.FreedomFighterTraitDescription_info,
                                                  "3a4d2cd14dc446319085c865570ccc3d", StatType.SkillMobility, halflingReq));
            choices.Add(Traits.CreateAddStatBonus("WellInformedTrait", RES.WellInformedTraitName_info,
                                                  RES.WellInformedTraitDescription_info,
                                                  "940ced5d41594b9aa22ee22217fbd46f", StatType.SkillPersuasion, halflingReq));

            // Dwarf:
            // - Grounded (+2 mobility, +1 reflex)
            // - Militant Merchant (perception)Owner.HPLeft
            // - Ruthless (+1 confirm crits)
            // - Zest for Battle (+1 trait dmg if has morale attack bonus)

            var GloryOfOld = Helpers.CreateFeature("GloryOfOldTrait", RES.GloryOfOldTraitName_info,
                                                   RES.GloryOfOldTraitDescription_info,
                                                   "4283a523984f44944a7cf157b21bf7c9",
                                                   Image2Sprite.Create("Mods/EldritchArcana/sprites/spell_perfection.png"),
                                                   FeatureGroup.None,
                                                   dwarfReq,
                                                   Helpers.Create <SavingThrowBonusAgainstDescriptor>(s => { s.SpellDescriptor = SpellDescriptor.Poison; s.Value = 1; s.ModifierDescriptor = ModifierDescriptor.Racial; }),
                                                   Helpers.Create <SavingThrowBonusAgainstDescriptor>(s => { s.SpellDescriptor = SpellDescriptor.BreathWeapon; s.Value = 1; s.ModifierDescriptor = ModifierDescriptor.Trait; }));

            components.Clear();
            components.AddRange((new SpellSchool[]
            {
                SpellSchool.Abjuration,
                SpellSchool.Conjuration,
                SpellSchool.Divination,
                SpellSchool.Enchantment,
                SpellSchool.Evocation,
                SpellSchool.Illusion,
                SpellSchool.Necromancy,
                SpellSchool.Transmutation,
                SpellSchool.Universalist
            }).Select((school) => Helpers.Create <SavingThrowBonusAgainstSchool>(a =>
            {
                a.School             = school;
                a.Value              = 1;
                a.ModifierDescriptor = ModifierDescriptor.Racial;
            })));

            GloryOfOld.AddComponents(components);

            choices.Add(GloryOfOld);

            choices.Add(Helpers.CreateFeature("GroundedTrait", RES.GroundedTraitName_info,
                                              RES.GroundedTraitDescription_info,
                                              "9b13923527a64c3bbf8de904c5a9ef8b",
                                              Helpers.GetIcon("3a8d34905eae4a74892aae37df3352b9"), // Skill Focus Stealth (mobility)
                                              FeatureGroup.None,
                                              dwarfReq,
                                              Helpers.CreateAddStatBonus(StatType.SkillMobility, 2, ModifierDescriptor.Racial),
                                              Helpers.CreateAddStatBonus(StatType.SaveReflex, 1, ModifierDescriptor.Racial)));

            choices.Add(Traits.CreateAddStatBonus("MilitantMerchantTrait", RES.MilitantMerchantTraitName_info,
                                                  RES.MilitantMerchantTraitDescription_info,
                                                  "38226f4ad9ed4211878ef95497d01857", StatType.SkillPerception, dwarfReq));

            choices.Add(Helpers.CreateFeature("RuthlessTrait", RES.RuthlessTraitName_info,
                                              RES.RuthlessTraitDescription_info,
                                              "58d18289cb7f4ad4a690d9502d397a3a",
                                              Helpers.GetIcon("f4201c85a991369408740c6888362e20"), // Improved Critical
                                              FeatureGroup.None,
                                              dwarfReq,
                                              Helpers.Create <CriticalConfirmationBonus>(a => { a.Bonus = 1; a.Value = 0; })));


            var Frostborn = Helpers.CreateFeature("FrostbornTrait", RES.FrostbornTraitName_info,
                                                  RES.FrostbornTraitDescription_info,
                                                  "f987f5e69db44cdd99983985e37a6c3c",
                                                  Helpers.GetIcon("121811173a614534e8720d7550aae253"), // Weapon Specialization
                                                  FeatureGroup.None,
                                                  dwarfReq);

            Frostborn.AddComponent(Helpers.Create <AddDamageResistanceEnergy>(r => { r.Type = Kingmaker.Enums.Damage.DamageEnergyType.Cold; r.Value = 4; }));
            Frostborn.AddComponent(Helpers.Create <SavingThrowBonusAgainstDescriptor>(s => { s.SpellDescriptor = SpellDescriptor.Cold; s.ModifierDescriptor = ModifierDescriptor.Racial; s.Bonus = 1; }));
            choices.Add(Frostborn);

            choices.Add(Helpers.CreateFeature("ZestForBattleTrait", RES.ZestForBattleTraitName_info,
                                              RES.ZestForBattleTraitDescription_info,
                                              "a987f5e69db44cdd98983985e37a6c2a",
                                              Helpers.GetIcon("31470b17e8446ae4ea0dacd6c5817d86"), // Weapon Specialization
                                              FeatureGroup.None,
                                              dwarfReq,
                                              Helpers.Create <DamageBonusIfMoraleBonus>()));

            // Gnome:
            // - Animal Friend (+1 will save and lore nature class skill, must have familar or animal companion)
            // - Rapscallion (+1 init, +1 thievery)
            components.Clear();
            components.Add(gnomeReq);
            components.Add(Helpers.Create <AddClassSkill>(a => a.Skill = StatType.SkillLoreNature));
            // TODO: is there a cleaner way to implement this rather than a hard coded list?
            // (Ideally: it should work if a party NPC has a familiar/animal companion too.)
            // See also: PrerequisitePet.
            components.AddRange((new String[] {
                // Animal companions
                "f6f1cdcc404f10c4493dc1e51208fd6f",
                "afb817d80b843cc4fa7b12289e6ebe3d",
                "f9ef7717531f5914a9b6ecacfad63f46",
                "f894e003d31461f48a02f5caec4e3359",
                "e992949eba096644784592dc7f51a5c7",
                "aa92fea676be33d4dafd176d699d7996",
                "2ee2ba60850dd064e8b98bf5c2c946ba",
                "6adc3aab7cde56b40aa189a797254271",
                "ece6bde3dfc76ba4791376428e70621a",
                "126712ef923ab204983d6f107629c895",
                "67a9dc42b15d0954ca4689b13e8dedea",
                // Familiars
                "1cb0b559ca2e31e4d9dc65de012fa82f",
                "791d888c3f87da042a0a4d0f5c43641c",
                "1bbca102706408b4cb97281c984be5d5",
                "f111037444d5b6243bbbeb7fc9056ed3",
                "7ba93e2b888a3bd4ba5795ae001049f8",
                "97dff21a036e80948b07097ad3df2b30",
                "952f342f26e2a27468a7826da426f3e7",
                "61aeb92c176193e48b0c9c50294ab290",
                "5551dd90b1480e84a9caf4c5fd5adf65",
                "adf124729a6e01f4aaf746abbed9901d",
                "4d48365690ea9a746a74d19c31562788",
                "689b16790354c4c4c9b0f671f68d85fc",
                "3c0b706c526e0654b8af90ded235a089",
            }).Select(id => Helpers.Create <AddStatBonusIfHasFact>(a =>
            {
                a.Stat        = StatType.SaveWill;
                a.Value       = 1;
                a.Descriptor  = ModifierDescriptor.Trait;
                a.CheckedFact = Traits.library.Get <BlueprintFeature>(id);
            })));

            choices.Add(Helpers.CreateFeature("AnimalFriendTrait", RES.AnimalFriendTraitName_info,
                                              RES.AnimalFriendTraitDescription_info,
                                              "91c612b225d54adaa4ce4c633501b58e",
                                              Image2Sprite.Create("Mods/EldritchArcana/sprites/gnome_animal_friend.png"),//Helpers.GetIcon("1670990255e4fe948a863bafd5dbda5d"), // Boon Companion
                                              FeatureGroup.None,
                                              components.ToArray()));

            choices.Add(Helpers.CreateFeature("RapscallionTrait", RES.RapscallionTraitName_info,
                                              RES.RapscallionTraitDescription_info,
                                              "4f95abdcc70e4bda818be5b8860585c5",
                                              Helpers.GetSkillFocus(StatType.SkillMobility).Icon,
                                              FeatureGroup.None,
                                              gnomeReq,
                                              Helpers.CreateAddStatBonus(StatType.SkillMobility, 1, ModifierDescriptor.Trait),
                                              Helpers.CreateAddStatBonus(StatType.Initiative, 1, ModifierDescriptor.Trait)));

            // Aasimar:
            // - Martyr's Blood (+1 attack if HP below half).
            // - Toxophilite (+2 crit confirm with bows)
            // - Wary (+1 perception/persuasion)

            // TODO: Enlightened Warrior

            choices.Add(Helpers.CreateFeature("MartyrsBloodTrait", RES.MartyrsBloodTraitName_info,
                                              RES.MartyrsBloodTraitDescription_info,
                                              "729d27ad020d485f843264844f0f2155",
                                              Helpers.GetIcon("3ea2215150a1c8a4a9bfed9d9023903e"), // Iron Will Improved
                                              FeatureGroup.None,
                                              aasimarReq,
                                              Helpers.Create <AttackBonusIfAlignmentAndHealth>(a =>
            {
                a.TargetAlignment = AlignmentComponent.Evil;
                a.Descriptor      = ModifierDescriptor.Trait;
                a.Value           = 1;
                a.HitPointPercent = 0.5f;
            })));

            choices.Add(Helpers.CreateFeature("ToxophiliteTrait", RES.ToxophiliteTraitName_info,
                                              RES.ToxophiliteTraitDescription_info,
                                              "6c434f07c8984971b1d842cecdf144c6",
                                              Helpers.GetIcon("f4201c85a991369408740c6888362e20"), // Improved Critical
                                              FeatureGroup.None,
                                              aasimarReq,
                                              Helpers.Create <CriticalConfirmationBonus>(a =>
            {
                a.Bonus = 2;
                a.Value = 0;
                a.CheckWeaponRangeType = true;
                a.Type = AttackTypeAttackBonus.WeaponRangeType.RangedNormal;
            })));

            choices.Add(Helpers.CreateFeature("WaryTrait", RES.WaryTraitName_info,
                                              RES.WaryTraitDescription_info,
                                              "7a72a0e956784cc38ea049e503189810",
                                              Helpers.GetIcon("86d93a5891d299d4983bdc6ef3987afd"), // Persuasive
                                              FeatureGroup.None,
                                              aasimarReq,
                                              Helpers.CreateAddStatBonus(StatType.SkillPerception, 1, ModifierDescriptor.Trait),
                                              Helpers.CreateAddStatBonus(StatType.SkillPerception, 1, ModifierDescriptor.Trait)));

            // Tiefling:
            // - Ever Wary (retain half dex bonus AC during surpise round)
            // - Prolong Magic (racial spell-like abilities get free extend spell)
            // - God Scorn (Demodand heritage; +1 saves vs divine spells)
            // - Shadow Stabber (+2 damage if opponent can't see you)

            choices.Add(Helpers.CreateFeature("EverWaryTrait", RES.EverWaryTraitName_info,
                                              RES.EverWaryTraitDescripton_info,
                                              "0400c9c99e704a1f81a769aa88044a03",
                                              Helpers.GetIcon("3c08d842e802c3e4eb19d15496145709"), // uncanny dodge
                                              FeatureGroup.None,
                                              tieflingReq,
                                              Helpers.Create <ACBonusDuringSurpriseRound>()));

            var tieflingHeritageDemodand = Traits.library.Get <BlueprintFeature>("a53d760a364cd90429e16aa1e7048d0a");

            choices.Add(Helpers.CreateFeature("GodScornTrait", RES.GodScornTraitName_info,
                                              RES.GodScornTraitDescription_info,
                                              "db41263f6fd3450ea0a3bc45c98330f7",
                                              Helpers.GetIcon("2483a523984f44944a7cf157b21bf79c"), // Elven Immunities
                                              FeatureGroup.None,
                                              Helpers.PrerequisiteFeature(tieflingHeritageDemodand),
                                              Helpers.Create <SavingThrowBonusAgainstSpellSource>(s => s.Source = SpellSource.Divine)));

            var tieflingHeritageSelection = Traits.library.Get <BlueprintFeatureSelection>("c862fd0e4046d2d4d9702dd60474a181");

            choices.Add(Helpers.CreateFeature("ProlongMagicTrait", RES.ProlongMagicTraitName_info,
                                              RES.ProlongMagicTraitDescription_info,
                                              "820f697f59114993a55c46044c98bf9c",
                                              tieflingHeritageSelection.Icon,
                                              FeatureGroup.None,
                                              tieflingReq,
                                              // TODO: double check that this actually works for SLAs.
                                              Helpers.Create <AutoMetamagic>(a => { a.Metamagic = Metamagic.Extend; a.Abilities = Traits.CollectTieflingAbilities(tieflingHeritageSelection); })));

            choices.Add(Helpers.CreateFeature("ShadowStabberTrait", RES.ShadowStabberTraitName_info,
                                              RES.ShadowStabberTraitDescription_info,
                                              "b67d04e21a9147e3b8f9bd81ba36f409",
                                              Helpers.GetIcon("9f0187869dc23744292c0e5bb364464e"), // accomplished sneak attacker
                                              FeatureGroup.None,
                                              tieflingReq,
                                              Helpers.Create <DamageBonusIfInvisibleToTarget>(d => d.Bonus = 2)));

            choices.Add(UndoSelection.Feature.Value);
            raceTraits.SetFeatures(choices);
            adopted.SetFeatures(raceTraits.Features);
            adopted.AddComponent(Helpers.PrerequisiteNoFeature(raceTraits));

            return(raceTraits);
        }
Example #14
0
        public static BlueprintFeatureSelection CreateRaceTraits(BlueprintFeatureSelection adopted)
        {
            var noFeature  = Helpers.PrerequisiteNoFeature(null);
            var raceTraits = Helpers.CreateFeatureSelection("RaceTrait", "Race Trait",
                                                            "Race traits are keyed to specific races or ethnicities, which your character must belong to in order to select the trait.",
                                                            "6264aa9515be40cda55892da93685764", null, FeatureGroup.None,
                                                            Helpers.PrerequisiteNoFeature(adopted), noFeature);

            noFeature.Feature = raceTraits;

            var humanReq = Helpers.PrerequisiteFeaturesFromList(Helpers.human, Helpers.halfElf, Helpers.halfOrc,
                                                                // Note: Aasimar/Tiefling included under the assumption they have "Scion of Humanity"/"Pass for Human"
                                                                Helpers.aasimar, Helpers.tiefling);

            var halfElfReq  = Helpers.PrerequisiteFeature(Helpers.halfElf);
            var halfOrcReq  = Helpers.PrerequisiteFeature(Helpers.halfOrc);
            var elfReq      = Helpers.PrerequisiteFeaturesFromList(Helpers.elf, Helpers.halfElf);
            var dwarfReq    = Helpers.PrerequisiteFeature(Helpers.dwarf);
            var halflingReq = Helpers.PrerequisiteFeature(Helpers.halfling);
            var gnomeReq    = Helpers.PrerequisiteFeature(Helpers.gnome);
            var aasimarReq  = Helpers.PrerequisiteFeature(Helpers.aasimar);
            var tieflingReq = Helpers.PrerequisiteFeature(Helpers.tiefling);

            // TODO: how do we code prerequisites so they aren't ignored by "Adopted"?
            // (only race prereq should be ignored, not others)
            //
            // Note: half-elf, half-orc can take traits from either race.
            // Also Aasimar/Tiefling are treated as having Scion of Humanity/Pass for Human in the game.
            var choices = new List <BlueprintFeature>();

            // Human:
            // - Carefully Hidden (+1 will save, +2 vs divination)
            // - Fanatic (Arcana)
            // - Historian (World and +1 bardic knowledge if Bard)
            // - Shield Bearer (+1 dmg shield bash)
            // - Superstitious (+1 save arcane spells)
            // - World Traveler (choose: persuasion, perception, or world)
            //e62f392949c24eb4b8fb2bc9db4345e3 // cleric orisons
            // IllusionMirrorImageAbility.62a04a20dcd3067468565f89e3d7c687/
            //TrickeryDomainBaseFeature.cd1f4a784e0820647a34fe9bd5ffa770  /// copycat
            //TrickeryDomainBaseResource.148c9ad7e47f4284b9c3686bb440c08c
            //ring of radiant arrows 3 arcane missles
            //blessed signet ring 3 times bless
            //MesmerizingNecklaceFeature.6fbea605b47e3354481683233511051b 3 times color spray
            //var copycatresource = Traits.library.Get<BlueprintAbilityResource>("148c9ad7e47f4284b9c3686bb440c08c");

            //var triflerDescription = "A childhood spent at your mystically gifted grandmother’s side has taught you the basics of real magic.";
            //var trifler = Helpers.CreateFeatureSelection("TriflerTrait", "Trifler (grandma)",
            //    triflerDescription + "\nBenefits: You may choose one of the level 1 spells and that spell you can cast 3 times per day as a spell-like ability.",
            //    "ecacfccfddfe456cafc8d60fc1db7d34",
            //    Helpers.GetIcon("3adf9274a210b164cb68f472dc1e4544"), // Human Skilled
            //    FeatureGroup.None);

            //var colorspray = Traits.library.CopyAndAdd<BlueprintFeature>(
            //    "6fbea605b47e3354481683233511051b",
            //    "TriflerTraitColorspray",
            //    "cd1f4a784e0b20647a34fe9bd5ffa7a0");
            //colorspray.SetDescription(triflerDescription + "\n Benefit: You may cast color spray 3 times per day as a spell-like ability.");
            //colorspray.SetName("Trifler color spray");

            //var colorspray = Traits.library.CopyAndAdd<BlueprintFeature>(
            //    "cd1f4a784e0820647a34fe9bd5ffa770",
            //    "TriflerTraitColorspray",
            //    "6fbea605b47e3354481683233511051b");
            //colorspray.SetDescription(triflerDescription + "\n Benefit: You may cast color spray 3 times per day as a spell-like ability.");
            //colorspray.SetName("Trifler color spray");

            //var TriflerFeatures = new List<BlueprintFeature>()
            //{
            //    colorspray
            //};

            //choices.Add(trifler);
            //choices.Add(colorspray);


            var components = new List <BlueprintComponent> {
                humanReq
            };

            components.Add(Helpers.CreateAddStatBonus(StatType.SaveWill, 1, ModifierDescriptor.Trait));
            components.Add(Helpers.Create <SavingThrowBonusAgainstSchool>(a =>
            {
                a.School             = SpellSchool.Divination;
                a.Value              = 2;
                a.ModifierDescriptor = ModifierDescriptor.Trait;
            }));
            choices.Add(Helpers.CreateFeature("CarefullyHiddenTrait", "Carefully Hidden (Human)",
                                              "Your life as a member of an unpopular ethnic group has given you an uncanny knack for avoiding detection.\nBenefit: You gain a +1 trait bonus to Will saves and a +2 trait bonus to saving throws versus divination effects.",
                                              "38b92d2ebb4c4cdb8e946e29f5b2f178",
                                              Helpers.GetIcon("175d1577bb6c9a04baf88eec99c66334"), // Iron Will
                                              FeatureGroup.None,
                                              components.ToArray()));
            choices.Add(Traits.CreateAddStatBonus("FanaticTrait", "Fanatic (Human)",
                                                  "Your years spent in libraries reading every musty tome you could find about ancient lost civilizations has given you insight into the subjects of history and the arcane.",
                                                  "6427e81ba399406c93b463c284a42055",
                                                  StatType.SkillKnowledgeArcana,
                                                  humanReq));

            var bardicKnowledge = Traits.library.Get <BlueprintFeature>("65cff8410a336654486c98fd3bacd8c5");

            components.Clear();
            components.Add(humanReq);
            components.AddRange((new StatType[] {
                StatType.SkillKnowledgeArcana,
                StatType.SkillKnowledgeWorld,
                StatType.SkillLoreNature,
                StatType.SkillLoreReligion,
            }).Select((skill) => Helpers.Create <AddStatBonusIfHasFact>(a =>
            {
                a.Stat        = skill;
                a.Value       = 1;
                a.CheckedFact = bardicKnowledge;
                a.Descriptor  = ModifierDescriptor.UntypedStackable;
            })));

            var historian = Traits.CreateAddStatBonus("HistorianTrait", "Historian (Human)",
                                                      "Your parents were scholars of history, whether genealogists of your own family tree, sages on the subject of ancient empires, or simply hobbyists with a deep and abiding love for the past.\nBenefits: You gain a +1 trait bonus on Knowledge (history) checks and bardic knowledge checks, and Knowledge (history) is always a class skill for you.",
                                                      "4af3871899e4440bae03d4c33d4b52fd",
                                                      StatType.SkillKnowledgeWorld,
                                                      components.ToArray());

            choices.Add(historian);

            components.Clear();
            components.Add(humanReq);
            components.AddRange(new String[] {
                "98a0dc03586a6d04791901c41700e516", // SpikedLightShield
                "1fd965e522502fe479fdd423cca07684", // WeaponLightShield
                "a1b85d048fb5003438f34356df938a9f", // SpikedHeavyShield
                "be9b6408e6101cb4997a8996484baf19"  // WeaponHeavyShield
            }.Select(id => Helpers.Create <WeaponTypeDamageBonus>(w => { w.DamageBonus = 1; w.WeaponType = Traits.library.Get <BlueprintWeaponType>(id); })));

            choices.Add(Helpers.CreateFeature("ShieldBearerTrait", "Shield Bearer (Human)",
                                              "You have survived many battles thanks to your skill with your shield.\nBenefit: When performing a shield bash, you deal 1 additional point of damage.",
                                              "044ebbbadfba4d58afa11bfbf38df199",
                                              Helpers.GetIcon("121811173a614534e8720d7550aae253"), // Shield Bash
                                              FeatureGroup.None,
                                              components.ToArray()));

            choices.Add(Helpers.CreateFeature("SuperstitiousTrait", "Superstitious (Human)",
                                              "You have a healthy fear of sorcerers’ speech and wizards’ words that has helped you to survive their charms.\nBenefit: You gain a +1 trait bonus on saving throws against arcane spells.",
                                              "f5d79e5fbb87473ca0b13ed15b742079",
                                              Helpers.GetIcon("2483a523984f44944a7cf157b21bf79c"), // Elven Immunities
                                              FeatureGroup.None,
                                              humanReq,
                                              Helpers.Create <SavingThrowBonusAgainstSpellSource>()));

            var travelerDescription = "Your family has taken the love of travel to an extreme, roaming the world extensively. You’ve seen dozens of cultures and have learned to appreciate the diversity of what the world has to offer.";
            var worldTraveler       = Helpers.CreateFeatureSelection("WorldTravelerTrait", "World Traveler (Human)",
                                                                     travelerDescription + "\nBenefits: Select one of the following skills: Persuasion, Knowledge (world), or Perception. You gain a +1 trait bonus on checks with that skill, and it is always a class skill for you.",
                                                                     "ecacfcbeddfe453cafc8d60fc1db7d34",
                                                                     Helpers.GetIcon("3adf9274a210b164cb68f472dc1e4544"), // Human Skilled
                                                                     FeatureGroup.None,
                                                                     humanReq);

            var travelerFeats = new StatType[] {
                StatType.SkillPersuasion,
                StatType.SkillKnowledgeWorld,
                StatType.SkillPerception
            }.Select(skill => Traits.CreateAddStatBonus(
                         $"WorldTraveler{skill}Trait",
                         $"World Traveler — {UIUtility.GetStatText(skill)}",
                         travelerDescription,
                         Helpers.MergeIds(Helpers.GetSkillFocus(skill).AssetGuid, "9b03b7ff17394007a3fbec18aa42604b"),
                         skill)).ToArray();

            worldTraveler.SetFeatures(travelerFeats);
            choices.Add(worldTraveler);

            // Elf:
            // - Dilettante Artist (persuasion)
            // - Forlorn (+1 fort save)
            // - Warrior of the Old (+2 init)
            // - Youthful Mischief (+1 ref)
            choices.Add(Traits.CreateAddStatBonus("DilettanteArtistTrait", "Dilettante Artist (Elf)",
                                                  "Art for you is a social gateway and you use it to influence and penetrate high society.",
                                                  "ac5a16e72ef74b4884c674dcbb61692c", StatType.SkillPersuasion, elfReq));

            BlueprintItemWeapon bite = Traits.library.CopyAndAdd <BlueprintItemWeapon>("35dfad6517f401145af54111be04d6cf", "Tusked",
                                                                                       "44dfad6517f401145af54111be04d644");



            choices.Add(Helpers.CreateFeature("ForlornTrait", "Forlorn (Elf)",
                                              "Having lived outside of traditional elf society for much or all of your life, you know the world can be cruel, dangerous, and unforgiving of the weak.\nBenefit: You gain a +1 trait bonus on Fortitude saving throws.",
                                              "1511289c92ea4233b14c4f51072ea10f",
                                              Helpers.GetIcon("79042cb55f030614ea29956177977c52"), // Great Fortitude
                                              FeatureGroup.None,
                                              elfReq,
                                              Helpers.CreateAddStatBonus(StatType.SaveFortitude, 1, ModifierDescriptor.Trait)
                                              ));

            choices.Add(Helpers.CreateFeature("TuskedTrait", "Tusked (Half-orc)",
                                              "Benefit: Huge, sharp tusks bulge from your mouth, and you receive a bite attack (1d4 damage for Medium characters). If used as part of a full attack action, the bite attack is made at your full base attack bonus –5.",
                                              "1511289c92ea4233b14c4f51072ea09g",
                                              Image2Sprite.Create("Mods/EldritchArcana/sprites/halforc_tusked.png"), // Great Fortitude
                                              FeatureGroup.None,
                                              halfOrcReq,
                                              Helpers.Create <AddAdditionalLimb>(x => x.Weapon = bite)
                                              ));

            choices.Add(Helpers.CreateFeature("WarriorOfOldTrait", "Warrior of Old (Elf)",
                                              "As a child, you put in long hours on combat drills, and though time has made this training a dim memory, you still have a knack for quickly responding to trouble.\nBenefit: You gain a +2 trait bonus on initiative checks.",
                                              "dc36a2c52abb4e6dbff549ac65a5a171",
                                              Helpers.GetIcon("797f25d709f559546b29e7bcb181cc74"), // Improved Initiative
                                              FeatureGroup.None,
                                              elfReq,
                                              Helpers.CreateAddStatBonus(StatType.Initiative, 2, ModifierDescriptor.Trait)));

            choices.Add(Helpers.CreateFeature("YouthfulMischiefTrait", "Youthful Mischeif (Elf)",
                                              "Though you gave up the life of a padfoot, scout, or minstrel decades before, you still know how to roll with the punches when things turn sour.\nBenefit: You gain a +1 trait bonus on Reflex saves.",
                                              "bfcc574d1f214455ac369fa46e07200e",
                                              Helpers.GetIcon("15e7da6645a7f3d41bdad7c8c4b9de1e"), // Lightning Reflexes
                                              FeatureGroup.None,
                                              elfReq,
                                              Helpers.CreateAddStatBonus(StatType.SaveReflex, 1, ModifierDescriptor.Trait)));

            // Half-orc:
            // - Brute (persuasion)
            // - Legacy of Sand (+1 will save)
            var brute = Traits.CreateAddStatBonus("BruteTrait", "Brute (Half-Orc)",
                                                  "You have worked for a crime lord, either as a low-level enforcer or as a guard, and are adept at frightening away people.",
                                                  "1ee0ce55ace74ccbb798e2fdc13181f6", StatType.SkillPersuasion, halfOrcReq);

            brute.SetIcon(Helpers.GetIcon("885f478dff2e39442a0f64ceea6339c9")); // Intimidating
            choices.Add(brute);

            var GloryOfOld = Helpers.CreateFeature("GloryOfOldTrait", "Glory of old",
                                                   "You are part of the old Guard" +
                                                   "\nYou belong to the elite veteran regiments of The old king and his army and are intensely loyal to him. It was you who made the last charge at the dwarven kingdom." +
                                                   "Benefit: You receive a +1 trait bonus on saving throws against spells, spell-like abilities, and poison",
                                                   "4283a523984f44944a7cf157b21bf7c9",
                                                   Image2Sprite.Create("Mods/EldritchArcana/sprites/spell_perfection.png"),
                                                   FeatureGroup.None,
                                                   dwarfReq,
                                                   Helpers.Create <SavingThrowBonusAgainstDescriptor>(s => { s.SpellDescriptor = SpellDescriptor.Poison; s.Value = 1; s.ModifierDescriptor = ModifierDescriptor.Racial; }),
                                                   Helpers.Create <SavingThrowBonusAgainstDescriptor>(s => { s.SpellDescriptor = SpellDescriptor.BreathWeapon; s.Value = 1; s.ModifierDescriptor = ModifierDescriptor.Trait; }));

            components.Clear();
            components.AddRange((new SpellSchool[]
            {
                SpellSchool.Abjuration,
                SpellSchool.Conjuration,
                SpellSchool.Divination,
                SpellSchool.Enchantment,
                SpellSchool.Evocation,
                SpellSchool.Illusion,
                SpellSchool.Necromancy,
                SpellSchool.Transmutation,
                SpellSchool.Universalist
            }).Select((school) => Helpers.Create <SavingThrowBonusAgainstSchool>(a =>
            {
                a.School             = school;
                a.Value              = 1;
                a.ModifierDescriptor = ModifierDescriptor.Racial;
            })));

            GloryOfOld.AddComponents(components);

            choices.Add(GloryOfOld);



            choices.Add(Helpers.CreateFeature("LegacyOfSandTrait", "Legacy of Sand (Half-Orc)",
                                              "A large tribe of orcs adapted to life in the desert once dwelt in southeastern Katapesh. Although this tribe is long extinct, some half-orcs of Katapesh carry the traits of this tribe in their particularly large jaws, broad shoulders, and shockingly pale eyes. You often have dreams of hunts and strange ceremonies held under moonlight in the desert sands. Some ascribe these dreams to racial memory, others to visions or prophecies. These dreams have instilled in you a fierce sense of tradition.\nBenefit: You gain a +1 trait bonus on all Will saving throws.",
                                              "e5fb1675eb6e4ef9accef7eb3a10862a",
                                              Image2Sprite.Create("Mods/EldritchArcana/sprites/halforc_legacy_of_sand.png"),
                                              FeatureGroup.None,
                                              halfOrcReq,
                                              Helpers.CreateAddStatBonus(StatType.SaveWill, 1, ModifierDescriptor.Trait)));

            // Half-elf:
            // - Elven Relexes (+2 initiative)
            // - Failed Apprentice (+1 save arcane spells)
            choices.Add(Helpers.CreateFeature("ElvenReflexsTrait", "Elven Reflexes (Half-Elf)",
                                              "One of your parents was a member of a wild elven tribe, and you’ve inherited a portion of your elven parent’s quick reflexes.\nBenefit: You gain a +2 trait bonus on initiative checks.",
                                              "9975678ce2fc420da9cd6ec4fe8c8b9b",
                                              Helpers.GetIcon("797f25d709f559546b29e7bcb181cc74"), // Improved Initiative
                                              FeatureGroup.None,
                                              halfElfReq,
                                              Helpers.CreateAddStatBonus(StatType.Initiative, 2, ModifierDescriptor.Trait)));

            choices.Add(Helpers.CreateFeature("FailedAprenticeTrait", "Failed Apprentice (Half-Elf)",
                                              "You have a healthy fear of sorcerers’ speech and wizards’ words that has helped you to survivAs a child, your parents sent you to a distant wizard’s tower as an apprentice so that you could learn the arcane arts. Unfortunately, you had no arcane talent whatsoever, though you did learn a great deal about the workings of spells and how to resist them.\nBenefit: You gain a +1 trait bonus on saves against arcane spells.",
                                              "8ed66066751f43c2920055dd6358adc8",
                                              Helpers.GetIcon("2483a523984f44944a7cf157b21bf79c"), // Elven Immunities
                                              FeatureGroup.None,
                                              halfElfReq,
                                              Helpers.Create <SavingThrowBonusAgainstSpellSource>()));

            // Halfling:
            // - Freed Slave (world)
            // - Freedom Fighter (mobility)
            // - Well-Informed (persuasion)
            choices.Add(Traits.CreateAddStatBonus("FreedSlaveTrait", "Freed Slave (Halfling)",
                                                  "You grew up as a slave and know the ins and outs of nobility better than most.",
                                                  "d2fc5fe0c64142a79e0ebee18f14b0be", StatType.SkillKnowledgeWorld, halflingReq));
            choices.Add(Traits.CreateAddStatBonus("FreedomFighterTrait", "Freedom Fighter (Halfling)",
                                                  "Your parents allowed escaping slaves to hide in your home, and the stories you’ve heard from them instilled into you a deep loathing of slavery, and a desire to help slaves evade capture and escape.",
                                                  "3a4d2cd14dc446319085c865570ccc3d", StatType.SkillMobility, halflingReq));
            choices.Add(Traits.CreateAddStatBonus("WellInformedTrait", "Well-Informed (Halfling)",
                                                  "You make it a point to know everyone and to be connected to everything around you. You frequent the best taverns, attend all of the right events, and graciously help anyone who needs it.",
                                                  "940ced5d41594b9aa22ee22217fbd46f", StatType.SkillPersuasion, halflingReq));

            // Dwarf:
            // - Grounded (+2 mobility, +1 reflex)
            // - Militant Merchant (perception)Owner.HPLeft
            // - Ruthless (+1 confirm crits)
            // - Zest for Battle (+1 trait dmg if has morale attack bonus)
            choices.Add(Helpers.CreateFeature("GroundedTrait", "Grounded (Dwarf)",
                                              "You are well balanced, both physically and mentally.\nBenefit: You gain a +2 trait bonus on Mobility checks, and a +1 trait bonus on Reflex saves.",
                                              "9b13923527a64c3bbf8de904c5a9ef8b",
                                              Helpers.GetIcon("3a8d34905eae4a74892aae37df3352b9"), // Skill Focus Stealth (mobility)
                                              FeatureGroup.None,
                                              dwarfReq,
                                              Helpers.CreateAddStatBonus(StatType.SkillMobility, 2, ModifierDescriptor.Racial),
                                              Helpers.CreateAddStatBonus(StatType.SaveReflex, 1, ModifierDescriptor.Racial)));

            choices.Add(Traits.CreateAddStatBonus("MilitantMerchantTrait", "Militant Merchant (Dwarf)",
                                                  "You know what it takes to get your goods to market and will stop at nothing to protect your products. Years of fending off thieves, cutthroats, and brigands have given you a sixth sense when it comes to danger.",
                                                  "38226f4ad9ed4211878ef95497d01857", StatType.SkillPerception, dwarfReq));

            choices.Add(Helpers.CreateFeature("RuthlessTrait", "Ruthless (Dwarf)",
                                              "You never hesitate to strike a killing blow.\nBenefit: You gain a +1 trait bonus on attack rolls to confirm critical hits.",
                                              "58d18289cb7f4ad4a690d9502d397a3a",
                                              Helpers.GetIcon("f4201c85a991369408740c6888362e20"), // Improved Critical
                                              FeatureGroup.None,
                                              dwarfReq,
                                              Helpers.Create <CriticalConfirmationBonus>(a => { a.Bonus = 1; a.Value = 0; })));


            var Frostborn = Helpers.CreateFeature("FrostbornTrait", "Frostborn (Dwarf)",
                                                  "You were raised in the icy tundra\nBenefit:Benefit: You gain a +4 trait bonus to resist the effects of cold environments, as well as a +1 trait bonus on all saving throws against cold effects.",
                                                  "f987f5e69db44cdd99983985e37a6c3c",
                                                  Helpers.GetIcon("121811173a614534e8720d7550aae253"), // Weapon Specialization
                                                  FeatureGroup.None,
                                                  dwarfReq);

            Frostborn.AddComponent(Helpers.Create <AddDamageResistanceEnergy>(r => { r.Type = Kingmaker.Enums.Damage.DamageEnergyType.Cold; r.Value = 4; }));
            Frostborn.AddComponent(Helpers.Create <SavingThrowBonusAgainstDescriptor>(s => { s.SpellDescriptor = SpellDescriptor.Cold; s.ModifierDescriptor = ModifierDescriptor.Racial; s.Bonus = 1; }));
            choices.Add(Frostborn);

            choices.Add(Helpers.CreateFeature("ZestForBattleTrait", "Zest for Battle (Dwarf)",
                                              "Your greatest joy is being in the thick of battle, and smiting your enemies for a righteous or even dastardly cause.\nBenefit: Whenever you have a morale bonus to weapon attack rolls, you also receive a +1 trait bonus on weapon damage rolls.",
                                              "a987f5e69db44cdd98983985e37a6c2a",
                                              Helpers.GetIcon("31470b17e8446ae4ea0dacd6c5817d86"), // Weapon Specialization
                                              FeatureGroup.None,
                                              dwarfReq,
                                              Helpers.Create <DamageBonusIfMoraleBonus>()));

            // Gnome:
            // - Animal Friend (+1 will save and lore nature class skill, must have familar or animal companion)
            // - Rapscallion (+1 init, +1 thievery)
            components.Clear();
            components.Add(gnomeReq);
            components.Add(Helpers.Create <AddClassSkill>(a => a.Skill = StatType.SkillLoreNature));
            // TODO: is there a cleaner way to implement this rather than a hard coded list?
            // (Ideally: it should work if a party NPC has a familiar/animal companion too.)
            // See also: PrerequisitePet.
            components.AddRange((new String[] {
                // Animal companions
                "f6f1cdcc404f10c4493dc1e51208fd6f",
                "afb817d80b843cc4fa7b12289e6ebe3d",
                "f9ef7717531f5914a9b6ecacfad63f46",
                "f894e003d31461f48a02f5caec4e3359",
                "e992949eba096644784592dc7f51a5c7",
                "aa92fea676be33d4dafd176d699d7996",
                "2ee2ba60850dd064e8b98bf5c2c946ba",
                "6adc3aab7cde56b40aa189a797254271",
                "ece6bde3dfc76ba4791376428e70621a",
                "126712ef923ab204983d6f107629c895",
                "67a9dc42b15d0954ca4689b13e8dedea",
                // Familiars
                "1cb0b559ca2e31e4d9dc65de012fa82f",
                "791d888c3f87da042a0a4d0f5c43641c",
                "1bbca102706408b4cb97281c984be5d5",
                "f111037444d5b6243bbbeb7fc9056ed3",
                "7ba93e2b888a3bd4ba5795ae001049f8",
                "97dff21a036e80948b07097ad3df2b30",
                "952f342f26e2a27468a7826da426f3e7",
                "61aeb92c176193e48b0c9c50294ab290",
                "5551dd90b1480e84a9caf4c5fd5adf65",
                "adf124729a6e01f4aaf746abbed9901d",
                "4d48365690ea9a746a74d19c31562788",
                "689b16790354c4c4c9b0f671f68d85fc",
                "3c0b706c526e0654b8af90ded235a089",
            }).Select(id => Helpers.Create <AddStatBonusIfHasFact>(a =>
            {
                a.Stat        = StatType.SaveWill;
                a.Value       = 1;
                a.Descriptor  = ModifierDescriptor.Trait;
                a.CheckedFact = Traits.library.Get <BlueprintFeature>(id);
            })));

            choices.Add(Helpers.CreateFeature("AnimalFriendTrait", "Animal Friend (Gnome)",
                                              "You’ve long been a friend to animals, and feel safer when animals are nearby.\nBenefits: You gain a +1 trait bonus on Will saving throws as long as you have an animal companion or familiar, and Lore (Nature) is always a class skill for you.",
                                              "91c612b225d54adaa4ce4c633501b58e",
                                              Image2Sprite.Create("Mods/EldritchArcana/sprites/gnome_animal_friend.png"),//Helpers.GetIcon("1670990255e4fe948a863bafd5dbda5d"), // Boon Companion
                                              FeatureGroup.None,
                                              components.ToArray()));

            choices.Add(Helpers.CreateFeature("Rapscallion", "Rapscallion (Gnome)",
                                              "You’ve spent your entire life thumbing your nose at the establishment and take pride in your run-ins with the law. Somehow, despite all your mischievous behavior, you’ve never been caught.\nBenefits: You gain a +1 trait bonus on Mobility checks and a +1 trait bonus on initiative checks.",
                                              "4f95abdcc70e4bda818be5b8860585c5",
                                              Helpers.GetSkillFocus(StatType.SkillMobility).Icon,
                                              FeatureGroup.None,
                                              gnomeReq,
                                              Helpers.CreateAddStatBonus(StatType.SkillMobility, 1, ModifierDescriptor.Trait),
                                              Helpers.CreateAddStatBonus(StatType.Initiative, 1, ModifierDescriptor.Trait)));

            // Aasimar:
            // - Martyr’s Blood (+1 attack if HP below half).
            // - Toxophilite (+2 crit confirm with bows)
            // - Wary (+1 perception/persuasion)

            // TODO: Enlightened Warrior

            choices.Add(Helpers.CreateFeature("MartyrsBloodTrait", "Martyr’s Blood (Aasimar)",
                                              "You carry the blood of a self-sacrificing celestial, and strive to live up to your potential for heroism.\nBenefit(s): As long as your current hit point total is less than half of your maximum hit points possible, you gain a +1 trait bonus on attack rolls against evil foes.",
                                              "729d27ad020d485f843264844f0f2155",
                                              Helpers.GetIcon("3ea2215150a1c8a4a9bfed9d9023903e"), // Iron Will Improved
                                              FeatureGroup.None,
                                              aasimarReq,
                                              Helpers.Create <AttackBonusIfAlignmentAndHealth>(a =>
            {
                a.TargetAlignment = AlignmentComponent.Evil;
                a.Descriptor      = ModifierDescriptor.Trait;
                a.Value           = 1;
                a.HitPointPercent = 0.5f;
            })));

            choices.Add(Helpers.CreateFeature("ToxophiliteTrait", "Toxophilite (Aasimar)",
                                              "You’ve inherited some of your celestial ancestor’s prowess with the bow.\nBenefit: You gain a +2 trait bonus on attack rolls made to confirm critical hits with bows.",
                                              "6c434f07c8984971b1d842cecdf144c6",
                                              Helpers.GetIcon("f4201c85a991369408740c6888362e20"), // Improved Critical
                                              FeatureGroup.None,
                                              aasimarReq,
                                              Helpers.Create <CriticalConfirmationBonus>(a =>
            {
                a.Bonus = 2;
                a.Value = 0;
                a.CheckWeaponRangeType = true;
                a.Type = AttackTypeAttackBonus.WeaponRangeType.RangedNormal;
            })));

            choices.Add(Helpers.CreateFeature("WaryTrait", "Wary (Aasimar)",
                                              "You grew up around people who were jealous of and hostile toward you. Perhaps your parents were not pleased to have a child touched by the divine—they may have berated or beaten you, or even sold you into slavery for an exorbitant price. You grew up mistrustful of others and believing your unique appearance to be a curse.\nBenefit: You gain a +1 trait bonus on Persuasion and Perception checks.",
                                              "7a72a0e956784cc38ea049e503189810",
                                              Helpers.GetIcon("86d93a5891d299d4983bdc6ef3987afd"), // Persuasive
                                              FeatureGroup.None,
                                              aasimarReq,
                                              Helpers.CreateAddStatBonus(StatType.SkillPersuasion, 1, ModifierDescriptor.Trait),
                                              Helpers.CreateAddStatBonus(StatType.SkillPerception, 1, ModifierDescriptor.Trait)));

            // Tiefling:
            // - Ever Wary (retain half dex bonus AC during surpise round)
            // - Prolong Magic (racial spell-like abilities get free extend spell)
            // - God Scorn (Demodand heritage; +1 saves vs divine spells)
            // - Shadow Stabber (+2 damage if opponent can't see you)

            choices.Add(Helpers.CreateFeature("EverWaryTrait", "Ever wary (Tiefling)",
                                              "Constant fear that your fiendish nature might provoke a sudden attack ensures that you never completely let down your guard.\nBenefit During the surprise round and before your first action in combat, you can apply half your Dexterity bonus (if any) to your AC. You still count as flat-footed for the purposes of attacks and effects.",
                                              "0400c9c99e704a1f81a769aa88044a03",
                                              Helpers.GetIcon("3c08d842e802c3e4eb19d15496145709"), // uncanny dodge
                                              FeatureGroup.None,
                                              tieflingReq,
                                              Helpers.Create <ACBonusDuringSurpriseRound>()));

            var tieflingHeritageDemodand = Traits.library.Get <BlueprintFeature>("a53d760a364cd90429e16aa1e7048d0a");

            choices.Add(Helpers.CreateFeature("GodScornTrait", "God Scorn (Demodand Tiefling)",
                                              "Your contempt for the gods and their sad little priests makes it easier to shake off the effects of their prayers.\nBenefit You gain a +1 trait bonus on saving throws against divine spells.",
                                              "db41263f6fd3450ea0a3bc45c98330f7",
                                              Helpers.GetIcon("2483a523984f44944a7cf157b21bf79c"), // Elven Immunities
                                              FeatureGroup.None,
                                              Helpers.PrerequisiteFeature(tieflingHeritageDemodand),
                                              Helpers.Create <SavingThrowBonusAgainstSpellSource>(s => s.Source = SpellSource.Divine)));

            var tieflingHeritageSelection = Traits.library.Get <BlueprintFeatureSelection>("c862fd0e4046d2d4d9702dd60474a181");

            choices.Add(Helpers.CreateFeature("ProlongMagicTrait", "Prolong Magic (Tiefling)",
                                              "Constant drills and preparation allow you to get more out of your innate magic.\nBenefit Whenever you use a spell - like ability gained through your tiefling heritage, it automatically acts as if affected by the Extend Spell metamagic feat.",
                                              "820f697f59114993a55c46044c98bf9c",
                                              tieflingHeritageSelection.Icon,
                                              FeatureGroup.None,
                                              tieflingReq,
                                              // TODO: double check that this actually works for SLAs.
                                              Helpers.Create <AutoMetamagic>(a => { a.Metamagic = Metamagic.Extend; a.Abilities = Traits.CollectTieflingAbilities(tieflingHeritageSelection); })));

            choices.Add(Helpers.CreateFeature("ShadowStabberTrait", "Shadow Stabber (Tiefling)",
                                              "An instinct for dishonorable conduct serves you well when fighting opponents who are blind, oblivious, or blundering around in the dark.\nBenefit You gain a +2 trait bonus on melee weapon damage rolls made against foes that cannot see you.",
                                              "b67d04e21a9147e3b8f9bd81ba36f409",
                                              Helpers.GetIcon("9f0187869dc23744292c0e5bb364464e"), // accomplished sneak attacker
                                              FeatureGroup.None,
                                              tieflingReq,
                                              Helpers.Create <DamageBonusIfInvisibleToTarget>(d => d.Bonus = 2)));

            choices.Add(UndoSelection.Feature.Value);
            raceTraits.SetFeatures(choices);
            adopted.SetFeatures(raceTraits.Features);
            adopted.AddComponent(Helpers.PrerequisiteNoFeature(raceTraits));

            return(raceTraits);
        }
        static internal void load()
        {
            var improved_unarmed_strike = library.Get <BlueprintFeature>("7812ad3672a4b9a4fb894ea402095167");
            var weapon_focus            = library.Get <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e");

            feral_combat_training = Helpers.CreateFeatureSelection("FeralCombatTrainingSelection",
                                                                   "Feral Combat Training",
                                                                   "Choose one of your natural weapons. While using the selected natural weapon, you can apply the effects of feats that have Improved Unarmed Strike as a prerequisite.\n"
                                                                   + "Special: If you are a monk, you can use the selected natural weapon with your flurry of blows class feature.",
                                                                   "",
                                                                   LoadIcons.Image2Sprite.Create(@"FeatIcons/Icon_Feral_Combat.png"),
                                                                   FeatureGroup.CombatFeat,
                                                                   Helpers.PrerequisiteFeature(improved_unarmed_strike)
                                                                   );
            feral_combat_training.HideInCharacterSheetAndLevelUp = true;

            foreach (var natural_weapon_entry in natural_weapon_entries)
            {
                feral_combat_training.AddComponent(Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true));
                var feral_combat_entry = Helpers.CreateFeature("FeralCombat" + natural_weapon_entry.category.ToString() + "Feature",
                                                               feral_combat_training.Name + $" ({natural_weapon_entry.name})",
                                                               feral_combat_training.Description,
                                                               "",
                                                               feral_combat_training.Icon,
                                                               FeatureGroup.CombatFeat,
                                                               Helpers.PrerequisiteFeature(improved_unarmed_strike),
                                                               Common.createPrerequisiteParametrizedFeatureWeapon(weapon_focus, natural_weapon_entry.category, any: true)
                                                               );
                natural_weapon_type_fact_map.Add(natural_weapon_entry.category, feral_combat_entry);
                feral_combat_training.AllFeatures = feral_combat_training.AllFeatures.AddToArray(feral_combat_entry);
                feral_combat_entry.Groups         = feral_combat_entry.Groups.AddToArray(FeatureGroup.Feat);
            }

            library.AddCombatFeats(feral_combat_training);

            ki_focus_weapon = library.CopyAndAdd <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e", "KiWeaponFeature", "");
            ki_focus_weapon.SetNameDescriptionIcon("Ki Weapon", "You can use ki attacks through the specified weapon as if they were unarmed attacks. These attacks include the monk’s ki strike, quivering palm, and the Stunning Fist feat.", null);
            ki_focus_weapon.Groups          = new FeatureGroup[0];
            ki_focus_weapon.ComponentsArray = new BlueprintComponent[0];


            crusaders_flurry = library.CopyAndAdd <BlueprintParametrizedFeature>("1e1f627d26ad36f43bbd26cc2bf8ac7e", "CrusadersFlurry", "8ff12016059f45b28eb616b2323efc2e");
            crusaders_flurry.SetNameDescriptionIcon("Crusader's Flurry", "You can use your deity’s favored weapon as if it were a monk weapon.",
                                                    LoadIcons.Image2Sprite.Create(@"FeatIcons/CrusadersFlurry.png"));
            crusaders_flurry.Groups            = new FeatureGroup[] { FeatureGroup.Feat };
            crusaders_flurry.Prerequisite      = NewFeats.deity_favored_weapon;
            crusaders_flurry.WeaponSubCategory = WeaponSubCategory.Melee;
            crusaders_flurry.ComponentsArray   = new BlueprintComponent[]
            {
                Helpers.Create <PrerequisiteMechanics.PrerequisiteMatchingParametrizedFeatures>(p => { p.base_feature = weapon_focus; p.dependent_feature = NewFeats.deity_favored_weapon; }),
                Helpers.Create <PrerequisiteParametrizedWeaponSubcategory>(p => { p.Feature = NewFeats.deity_favored_weapon; p.SubCategory = WeaponSubCategory.Melee; }),
                ChannelEnergyEngine.improved_channel.GetComponent <PrerequisiteFeaturesFromList>(),    //channel energy prereq
                Helpers.PrerequisiteFeature(library.Get <BlueprintFeature>("fd99770e6bd240a4aab70f7af103e56a"), any: true),
                Helpers.PrerequisiteFeature(Warpriest.flurry2_unlock, any: true),
                Helpers.PrerequisiteFeature(Brawler.brawlers_flurry, any: true)
            };
            library.AddFeats(crusaders_flurry);

            var ki_strike_magic      = library.Get <BlueprintFeature>("1188005ee3160f84f8bed8b19a7d46cf");
            var ki_strike_cold_iron  = library.Get <BlueprintFeature>("7b657938fde78b14cae10fc0d3dcb991");
            var ki_strike_adamantine = library.Get <BlueprintFeature>("ddc10a3463bd4d54dbcbe993655cf64e");
            var ki_strike_lawful     = library.Get <BlueprintFeature>("1188005ee3160f84f8bed8b19a7d46cf");

            ki_strike_magic.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageMaterialIfParametrizedFeature>(a =>
            {
                a.add_magic = true;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                         );
            ki_strike_cold_iron.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageMaterialIfParametrizedFeature>(a =>
            {
                a.material = PhysicalDamageMaterial.ColdIron;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                             );
            ki_strike_adamantine.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageMaterialIfParametrizedFeature>(a =>
            {
                a.material = PhysicalDamageMaterial.Adamantite;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                              );
            ki_strike_lawful.AddComponent(Helpers.Create <NewMechanics.AddOutgoingPhysicalDamageAlignmentIfParametrizedFeature>(a =>
            {
                a.damage_alignment = DamageAlignment.Lawful;
                a.required_parametrized_feature = FeralCombatTraining.ki_focus_weapon;
            })
                                          );

            fixAbilities();
        }