/*
         * Uses the CharacterBuildController to edit level plans
         * Refer MainMenu.StartChargen which sets up the state and then calls CharacterBuildController.HandleLevelUpStart
         *
         */
        public static void EditLevelPlan(LevelPlanHolder levelPlanHolder, int level)
        {
            var unit = levelPlanHolder.CreateUnit(level);

            if (Main.settings.ShowDollRoom)
            {
                ShowDollRoom(unit);
            }
            CharacterBuildController characterBuildController = Game.Instance.UI.CharacterBuildController;
            var mode = level == 1 ? LevelUpState.CharBuildMode.CharGen : LevelUpState.CharBuildMode.LevelUp;

            CurrentLevelUpController = LevelUpController.Start(
                unit: unit.Descriptor,
                instantCommit: false,
                unitJson: null,
                onSuccess: null,
                mode: mode);
            CurrentLevelUpController.SelectPortrait(Game.Instance.BlueprintRoot.CharGen.Portraits[0]);
            CurrentLevelUpController.SelectGender(Gender.Male);
            CurrentLevelUpController.SelectRace(Game.Instance.BlueprintRoot.Progression.CharacterRaces[0]);
            CurrentLevelUpController.SelectAlignment(Kingmaker.Enums.Alignment.TrueNeutral);
            CurrentLevelUpController.SelectVoice(Game.Instance.BlueprintRoot.CharGen.MaleVoices[0]);
            CurrentLevelUpController.SelectName("LevelPlan");
            Traverse.Create(characterBuildController).Property <LevelUpController>("LevelUpController").Value = CurrentLevelUpController;
            Traverse.Create(characterBuildController).Field("Mode").SetValue(CurrentLevelUpController.State.Mode);
            Traverse.Create(characterBuildController).Field("Unit").SetValue(unit.Descriptor);
            characterBuildController.Show(true);
        }
Ejemplo n.º 2
0
        /*
         * Refer MainMenu.StartChargen which also calls CharacterBuildController.HandleLevelUpStart
         *
         */
        internal static void TestLevelup()
        {
            var unit           = CreateUnit();
            var descriptorJson = UnitSerialization.Serialize(unit.Descriptor);;

            if (Main.settings.ShowDollRoom)
            {
                ShowDollRoom(unit);
            }
            CharacterBuildController characterBuildController = Game.Instance.UI.CharacterBuildController;

            LevelPlanManager.CurrentLevelUpController = LevelUpController.Start(
                unit: unit.Descriptor,
                instantCommit: false,
                unitJson: descriptorJson,
                onSuccess: null,
                mode: LevelUpState.CharBuildMode.CharGen);

            /*CurrentLevelUpController.SelectPortrait(Game.Instance.BlueprintRoot.CharGen.Portraits[0]);
             * CurrentLevelUpController.SelectGender(Gender.Male);
             * CurrentLevelUpController.SelectRace(Game.Instance.BlueprintRoot.Progression.CharacterRaces[0]);
             * CurrentLevelUpController.SelectAlignment(Kingmaker.Enums.Alignment.TrueNeutral);
             * CurrentLevelUpController.SelectVoice(Game.Instance.BlueprintRoot.CharGen.MaleVoices[0]);
             * CurrentLevelUpController.SelectName("LevelPlan");*/
            Traverse.Create(characterBuildController).Property <LevelUpController>("LevelUpController").Value = LevelPlanManager.CurrentLevelUpController;
            characterBuildController.Unit = unit.Descriptor;
            characterBuildController.Show(true);
        }
Ejemplo n.º 3
0
        private LevelUpController AddLevel(UnitDescriptor unit, Dictionary <SelectionEntry, HashSet <int> > selectionsHistory, HashSet <int> spellHistory)
        {
            LevelUpController levelUpController = LevelUpController.Start(unit, true, null, null, LevelUpState.CharBuildMode.LevelUp);

            if (levelUpController.State.CanSelectRace)
            {
                BlueprintRace    race = unit.Progression.Race;
                DefaultBuildData data = ElementsContext.GetData <DefaultBuildData>();
                if (data != null)
                {
                    race = data.Race;
                }
                if (race != null)
                {
                    levelUpController.SelectRace(race);
                }
            }
            if (levelUpController.State.CanSelectRaceStat)
            {
                levelUpController.SelectRaceStat(instance.RaceStat);
            }
            this.ApplyStatsDistributionPreset(levelUpController);
            if (unit.Progression.GetClassLevel(instance.CharacterClass) <= 0)
            {
                foreach (BlueprintArchetype archetype in instance.Archetypes)
                {
                    levelUpController.AddArchetype(instance.CharacterClass, archetype);
                }
            }
            levelUpController.SelectClass(instance.CharacterClass, false);
            levelUpController.ApplyClassMechanics();
            this.PerformSelections(levelUpController, selectionsHistory, new LevelUpActionPriority?(LevelUpActionPriority.ReplaceSpellbook));
            levelUpController.ApplySpellbook();
            while (levelUpController.State.AttributePoints > 0 && instance.LevelsStat.IsAttribute())
            {
                levelUpController.SpendAttributePoint(instance.LevelsStat);
            }
            this.PerformSelections(levelUpController, selectionsHistory, new LevelUpActionPriority?(LevelUpActionPriority.ApplySkillPoints));
            levelUpController.ApplySkillPoints();
            while (levelUpController.State.SkillPointsRemaining > 0)
            {
                int skillPointsRemaining = levelUpController.State.SkillPointsRemaining;
                foreach (StatType skill in instance.Skills)
                {
                    if (levelUpController.State.SkillPointsRemaining <= 0)
                    {
                        break;
                    }
                    levelUpController.SpendSkillPoint(skill);
                }
                if (skillPointsRemaining == levelUpController.State.SkillPointsRemaining)
                {
                    break;
                }
            }
            this.PerformSelections(levelUpController, selectionsHistory, null);
            this.PerformSpellSelections(levelUpController, spellHistory);
            return(levelUpController);
        }
        /*
         * Refer AddClassLevels.LevelUp and Player.CreateCustomCompanion
         */
        public UnitEntityData CreateUnit(int level)
        {
            //var playerUnit = ResourcesLibrary.TryGetBlueprint<BlueprintUnit>("4391e8b9afbb0cf43aeba700c089f56d");
            //var unit = new UnitDescriptor(playerUnit, null);
            var unit = Main.settings.DefaultPointBuy25 ?
                       Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.DefaultPlayerCharacter) :
                       Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.CustomCompanion);

            ApplyLevelPlan(unit.Descriptor);
            for (int i = 0; i < level; i++)
            {
                var levelUpController = LevelUpController.Start(unit.Descriptor, true);
            }
            return(unit);
        }
        static void CreateLevelPlan()
        {
            var unit     = Game.Instance.Player.MainCharacter.Value.Descriptor;
            var unitJson = UnitSerialization.Serialize(unit);
            CharacterBuildController characterBuildController = Game.Instance.UI.CharacterBuildController;

            CurrentLevelUpController = LevelUpController.Start(
                unit: unit,
                instantCommit: false,
                unitJson: unitJson,
                onSuccess: null,
                mode: LevelUpState.CharBuildMode.PreGen);
            Traverse.Create(characterBuildController).Property <LevelUpController>("LevelUpController").Value = CurrentLevelUpController;
            Traverse.Create(characterBuildController).Field("Mode").SetValue(CurrentLevelUpController.State.Mode);
            Traverse.Create(characterBuildController).Field("Unit").SetValue(unit);
            characterBuildController.Show(true);
        }
        /*
         * Create a level plan from BlueprintCharacterClass' defaultBuild
         * Refer AddClassLevels.LevelUp and LevelController.ApplyStatsDistributionPreset
         * LevelUpController.SelectDefaultClassBuild and CharacterBuildController.LoadDefaultProgression
         *
         * AddClassLevels and StatsDistributionPreset are both components of
         * BlueprintCharacterClass.DefaultBuild
         */
        public LevelPlanHolder(BlueprintCharacterClass defaultClass)
        {
            bool IsDefaultBuildPriority(LevelUpActionPriority priority)
            {
                return(priority != LevelUpActionPriority.Visual && priority != LevelUpActionPriority.Race && priority != LevelUpActionPriority.Class &&
                       priority != LevelUpActionPriority.ApplyClass && priority != LevelUpActionPriority.ApplySpellbook && priority != LevelUpActionPriority.ApplySkillPoints &&
                       priority != LevelUpActionPriority.Alignment);
            }

            using (new CodeTimer("Create default build"))
            {
                var defaultBuild   = defaultClass.DefaultBuild;
                var addClassLevels = defaultBuild.GetComponent <AddClassLevels>();
                var targetPoints   = Main.settings.DefaultPointBuy25 ? 25 : 20;
                var stats          = defaultBuild.GetComponents <StatsDistributionPreset>().FirstOrDefault(sd => sd.TargetPoints == targetPoints);
                //var race = Game.Instance.BlueprintRoot.Progression.CharacterRaces[0];
                var            race = ResourcesLibrary.TryGetBlueprint <BlueprintRace>("5c4e42124dc2b4647af6e36cf2590500");
                UnitEntityData unit = Main.settings.DefaultPointBuy25 ?
                                      Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.DefaultPlayerCharacter) :
                                      Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.CustomCompanion);
                var levelUpController = LevelUpController.Start(unit.Descriptor,
                                                                instantCommit: true,
                                                                mode: LevelUpState.CharBuildMode.CharGen);
                if (!levelUpController.SelectPortrait(Game.Instance.BlueprintRoot.CharGen.Portraits[0]))
                {
                    throw new Exception("Error selecting portrait");
                }
                if (!levelUpController.SelectGender(Gender.Male))
                {
                    throw new Exception("Error selecting gender");
                }
                if (!levelUpController.SelectRace(race))
                {
                    throw new Exception("Error selecting race");
                }
                //Default build must be aquired after selecting race but before selecting class
                levelUpController.Unit.Ensure <LevelUpPlanUnitHolder>();
                levelUpController.Unit.Progression.DropLevelPlans();
                levelUpController.Unit.AddFact(defaultBuild, null, null);
                LevelPlanData levelPlan = levelUpController.Unit.Progression.GetLevelPlan(levelUpController.State.NextLevel);
                if (!levelUpController.SelectClass(defaultClass))
                {
                    throw new Exception("Error selecting class");
                }
                levelUpController.LevelUpActions.RemoveAll((ILevelUpAction a) => IsDefaultBuildPriority(a.Priority));
                levelUpController.LevelUpActions.AddRange(from a in levelPlan.Actions
                                                          where IsDefaultBuildPriority(a.Priority)
                                                          select a);
                levelUpController.LevelUpActions = (from a in levelUpController.LevelUpActions
                                                    orderby a.Priority
                                                    select a).ToList();
                if (!levelUpController.SelectAlignment(Kingmaker.Enums.Alignment.TrueNeutral))
                {
                    throw new Exception("Error selecting alignment");
                }
                if (!levelUpController.SelectName($"Default {defaultClass.Name} Build"))
                {
                    throw new Exception("Error selecting name");
                }
                for (int i = 0; i < 20; i++)
                {
                    var plan = unit.Descriptor.Progression.GetLevelPlan(i + 1);
                    LevelPlanData[i] = plan;
                }
                LevelPlanData[0] = new LevelPlanData(1, levelUpController.LevelUpActions.ToArray());
            }
            using (new CodeTimer("Verify default build"))
            {
                VerifyLevelPlan();
            }
        }
        /*
         * Verify that a level plan is valid. We do this by creating a test unit and try to level it up with the leveling plan
         * Refer LevelUpController, LevelUpState.IsComplete CharacterBuildController.Next
         * CharBPhase.IsUnlocked
         */
        void VerifyLevelPlan()
        {
            var unitEntityData = Main.settings.DefaultPointBuy25 ?
                                 Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.DefaultPlayerCharacter) :
                                 Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.CustomCompanion);

            for (int i = 0; i < 20; i++)
            {
                if (i > 0)
                {
                    ValidLevels[i] = false;
                    Message[i]     = "TODO";
                    continue;
                }
                var levelUpLog        = new List <string>();
                var mode              = i == 0 ? LevelUpState.CharBuildMode.CharGen : LevelUpState.CharBuildMode.LevelUp;
                var levelUpController = LevelUpController.Start(unitEntityData.Descriptor, instantCommit: false, mode: mode);
                if (LevelPlanData[i] == null)
                {
                    throw new Exception($"Level plan is null for index {i}");
                }
                if (LevelPlanData[i].Actions == null)
                {
                    throw new Exception($"Actions not set for level plan {i}, level {LevelPlanData[i].Level}");
                }

                foreach (var action in LevelPlanData[i].Actions)
                {
                    if (!action.Check(levelUpController.State, unitEntityData.Descriptor))
                    {
                        levelUpLog.Add($"Invalid action: {Util.MakeActionReadable(action)}");
                    }
                    else
                    {
                        levelUpController.LevelUpActions.Add(action);
                        action.Apply(levelUpController.State, unitEntityData.Descriptor);
                        levelUpController.State.OnApplyAction();
                    }
                }
                unitEntityData.Descriptor.Progression.ReapplyFeaturesOnLevelUp();
                ValidLevels[i] = levelUpController.State.IsComplete() && levelUpLog.Count == 0;
                if (!levelUpController.State.IsComplete())
                {
                    if (!levelUpController.State.StatsDistribution.IsComplete())
                    {
                        levelUpLog.Add("Stat Distribution is incomplete");
                    }
                    if (levelUpController.State.CanSelectAlignment)
                    {
                        levelUpLog.Add("Alignment not selected");
                    }
                    if (levelUpController.State.CanSelectRace)
                    {
                        levelUpLog.Add("Race not selected");
                    }
                    if (levelUpController.State.CanSelectRaceStat)
                    {
                        levelUpLog.Add("CanSelectRaceStat");
                    }
                    if (levelUpController.State.CanSelectName)
                    {
                        levelUpLog.Add("CanSelectName");
                    }
                    if (levelUpController.State.CanSelectPortrait)
                    {
                        levelUpLog.Add("CanSelectPortrait");
                    }
                    if (levelUpController.State.CanSelectGender)
                    {
                        levelUpLog.Add("CanSelectGender");
                    }
                    if (!levelUpController.State.CanSelectVoice)
                    {
                        levelUpLog.Add("CanSelectVoice");
                    }
                    if (levelUpController.State.AttributePoints > 0)
                    {
                        levelUpLog.Add("Unassigned Attribute Points");
                    }
                    if (levelUpController.State.SelectedClass == null)
                    {
                        levelUpLog.Add("Class is null");
                    }
                    if (!levelUpController.State.IsSkillPointsComplete())
                    {
                        levelUpLog.Add("Unassigned Skill Points");
                    }
                    if (levelUpController.State.Selections.Any((FeatureSelectionState s) => !s.Selected && s.CanSelectAnything(levelUpController.State, unitEntityData.Descriptor)))
                    {
                        levelUpLog.Add("Unassinged Features");
                    }
                    if (levelUpController.State.SpellSelections.Any((SpellSelectionData data) => data.CanSelectAnything(unitEntityData.Descriptor)))
                    {
                        levelUpLog.Add("Unassigned Spells");
                    }
                }
                if (ValidLevels[i])
                {
                    Message[i] = "Valid level plan";
                }
                else
                {
                    Message[i] = $"Invalid level plan:\n{string.Join("\n", levelUpLog)}";
                }
            }
        }