Beispiel #1
0
            public static bool Prefix(LevelUpState state, UnitDescriptor unit)
            {
                if (!settings.toggleMulticlass)
                {
                    return(false);
                }
                if ((UnityEngine.Object)state.SelectedClass == (UnityEngine.Object)null)
                {
                    return(true);
                }
                SkipLevelsForSpellProgression component1 = state.SelectedClass.GetComponent <SkipLevelsForSpellProgression>();

                if ((UnityEngine.Object)component1 != (UnityEngine.Object)null && ((IEnumerable <int>)component1.Levels).Contains <int>(state.NextClassLevel))
                {
                    return(true);
                }
                ClassData classData = unit.Progression.GetClassData(state.SelectedClass);

                if (classData == null || !((UnityEngine.Object)classData.Spellbook != (UnityEngine.Object)null))
                {
                    return(true);
                }
                Spellbook spellbook1 = unit.DemandSpellbook(classData.Spellbook);

                if ((bool)(UnityEngine.Object)state.SelectedClass.Spellbook && (UnityEngine.Object)state.SelectedClass.Spellbook != (UnityEngine.Object)classData.Spellbook)
                {
                    Spellbook spellbook2 = unit.Spellbooks.FirstOrDefault <Spellbook>((Func <Spellbook, bool>)(s => (UnityEngine.Object)s.Blueprint == (UnityEngine.Object)state.SelectedClass.Spellbook));
                    if (spellbook2 != null)
                    {
                        foreach (AbilityData allKnownSpell in spellbook2.GetAllKnownSpells())
                        {
                            spellbook1.AddKnown(allKnownSpell.SpellLevel, allKnownSpell.Blueprint);
                        }
                        unit.DeleteSpellbook(state.SelectedClass.Spellbook);
                    }
                }
                int casterLevelBefore = spellbook1.CasterLevel;

                spellbook1.AddLevelFromClass(classData.CharacterClass);
                int casterLevelAfter = spellbook1.CasterLevel;

                if (casterLevelBefore == casterLevelAfter)
                {
                    return(true);                                       // Mod line
                }
                SpellSelectionData spellSelectionData = state.DemandSpellSelection(spellbook1.Blueprint, spellbook1.Blueprint.SpellList);

                if ((UnityEngine.Object)spellbook1.Blueprint.SpellsKnown != (UnityEngine.Object)null)
                {
                    for (int index = 0; index <= 10; ++index)
                    {
                        BlueprintSpellsTable spellsKnown = spellbook1.Blueprint.SpellsKnown;
                        int?count = spellsKnown.GetCount(casterLevelBefore, index);
                        int num1  = count ?? 0;
                        count = spellsKnown.GetCount(casterLevelAfter, index);
                        int num2 = count ?? 0;
                        spellSelectionData.SetLevelSpells(index, Math.Max(0, num2 - num1));
                    }
                }
                int maxSpellLevel = spellbook1.MaxSpellLevel;

                if (spellbook1.Blueprint.SpellsPerLevel > 0)
                {
                    if (casterLevelBefore == 0)
                    {
                        spellSelectionData.SetExtraSpells(0, maxSpellLevel);
                        spellSelectionData.ExtraByStat = true;
                        spellSelectionData.UpdateMaxLevelSpells(unit);
                    }
                    else
                    {
                        spellSelectionData.SetExtraSpells(spellbook1.Blueprint.SpellsPerLevel, maxSpellLevel);
                    }
                }
                foreach (AddCustomSpells component2 in spellbook1.Blueprint.GetComponents <AddCustomSpells>())
                {
                    ApplySpellbook.TryApplyCustomSpells(spellbook1, component2, state, unit);
                }
                return(true);
            }
Beispiel #2
0
            public static bool Prefix(LevelUpState state, UnitDescriptor unit)
            {
                if (!settings.toggleMulticlass)
                {
                    return(true);
                }

                if (state.SelectedClass == null)
                {
                    return(false);
                }

                var component1 = state.SelectedClass.GetComponent <SkipLevelsForSpellProgression>();

                if (component1 != null && component1.Levels.Contains(state.NextClassLevel))
                {
                    return(false);
                }

                var classData = unit.Progression.GetClassData(state.SelectedClass);

                if (classData?.Spellbook == null)
                {
                    return(false);
                }

                var spellbook1 = unit.DemandSpellbook(classData.Spellbook);

                if (state.SelectedClass.Spellbook && state.SelectedClass.Spellbook != classData.Spellbook)
                {
                    var spellbook2 = unit.Spellbooks.FirstOrDefault(s => s.Blueprint == state.SelectedClass.Spellbook);
                    if (spellbook2 != null)
                    {
                        foreach (var allKnownSpell in spellbook2.GetAllKnownSpells())
                        {
                            spellbook1.AddKnown(allKnownSpell.SpellLevel, allKnownSpell.Blueprint);
                        }

                        unit.DeleteSpellbook(state.SelectedClass.Spellbook);
                    }
                }
                var casterLevelAfter = CasterHelpers.GetRealCasterLevel(unit, spellbook1.Blueprint);     // Calculates based on progression which includes class selected in level up screen

                spellbook1.AddLevelFromClass(classData.CharacterClass);                                  // This only adds one class at a time and will only ever increase by 1 or 2
                var casterLevelBefore  = casterLevelAfter - (classData.CharacterClass.IsMythic ? 2 : 1); // Technically only needed to see if this is our first level of a casting class
                var spellSelectionData = state.DemandSpellSelection(spellbook1.Blueprint, spellbook1.Blueprint.SpellList);

                if (spellbook1.Blueprint.SpellsKnown != null)
                {
                    for (var index = 0; index <= 10; ++index)
                    {
                        var spellsKnown   = spellbook1.Blueprint.SpellsKnown;
                        var expectedCount = spellsKnown.GetCount(casterLevelAfter, index);
                        var actual        = CasterHelpers.GetCachedSpellsKnown(unit, spellbook1, index);
#if DEBUG
                        //Mod.Trace($"Spellbook {spellbook1.Blueprint.Name}: Granting {expectedCount-actual} spells of spell level:{index} based on expected={expectedCount} and actual={actual}");
#endif
                        spellSelectionData.SetLevelSpells(index, Math.Max(0, expectedCount - actual));
                    }
                }
                var maxSpellLevel = spellbook1.MaxSpellLevel;
                if (spellbook1.Blueprint.SpellsPerLevel > 0)
                {
                    if (casterLevelBefore == 0)
                    {
                        spellSelectionData.SetExtraSpells(0, maxSpellLevel);
                        spellSelectionData.ExtraByStat = true;
                        spellSelectionData.UpdateMaxLevelSpells(unit);
                    }
                    else
                    {
                        spellSelectionData.SetExtraSpells(spellbook1.Blueprint.SpellsPerLevel, maxSpellLevel);
                    }
                }
                foreach (var component2 in spellbook1.Blueprint.GetComponents <AddCustomSpells>())
                {
                    ApplySpellbook.TryApplyCustomSpells(spellbook1, component2, state, unit);
                }

                return(false);
            }
Beispiel #3
0
        // TODO: this unfortunately duplicates a lot of ApplySpellbook.Apply, but it's needed because:
        // - Apply checks the skip spell levels internally, so we can't prevent the skip without mutating data structures.
        // - Apply only knows how to add one level, but sometimes we need to gain 2 (if Prestigious Spellcaster fills in
        //   a previous missing level, and another one is gained normally).
        internal static void IncreaseCasterLevel(LevelUpState state, UnitDescriptor unit)
        {
            var blueprintSpellbook = unit.Progression.GetClassData(state.SelectedClass)?.Spellbook;

            Log.Append($"IncreaseCasterLevel {unit.CharacterName}, class {state.SelectedClass}, blueprintSpellbook {blueprintSpellbook}");
            if (blueprintSpellbook == null)
            {
                return;
            }

            var spellbook = unit.DemandSpellbook(blueprintSpellbook);
            var selectedClassSpellbook = state.SelectedClass.Spellbook;

            if (selectedClassSpellbook != null && selectedClassSpellbook != blueprintSpellbook)
            {
                var oldSpellbook = unit.Spellbooks.FirstOrDefault((s) => s.Blueprint == selectedClassSpellbook);
                if (oldSpellbook != null)
                {
                    foreach (var known in oldSpellbook.GetAllKnownSpells())
                    {
                        spellbook.AddKnown(known.SpellLevel, known.Blueprint);
                    }
                    unit.DeleteSpellbook(selectedClassSpellbook);
                }
            }
            int oldCasterLevel = spellbook.CasterLevel;

            spellbook.AddCasterLevel();
            int newCasterLevel = spellbook.CasterLevel;

            Log.Write($"Level up from {oldCasterLevel} to {newCasterLevel}");
            var spellSelection = state.DemandSpellSelection(spellbook.Blueprint, spellbook.Blueprint.SpellList);
            var spellsKnown    = spellbook.Blueprint.SpellsKnown;

            if (spellsKnown != null)
            {
                for (int i = 0; i <= 9; i++)
                {
                    int?oldSpellsKnown = spellsKnown.GetCount(oldCasterLevel, i);
                    int?newSpellsKnown = spellsKnown.GetCount(newCasterLevel, i);
                    var newSpells      = newSpellsKnown.GetValueOrDefault() - oldSpellsKnown.GetValueOrDefault();
                    // Log.Write($"  gain spells {newSpells} at level {i}");
                    int existingNewSpells = spellSelection.LevelCount[i]?.SpellSelections.Length ?? 0;
                    spellSelection.SetLevelSpells(i, newSpells + existingNewSpells);
                }
            }
            int maxSpellLevel  = spellbook.MaxSpellLevel;
            int spellsPerLevel = spellbook.Blueprint.SpellsPerLevel;

            if (spellsPerLevel > 0)
            {
                if (oldCasterLevel == 0)
                {
                    spellSelection.SetExtraSpells(0, maxSpellLevel);
                    spellSelection.ExtraByStat = true;
                    spellSelection.UpdateMaxLevelSpells(unit);
                }
                else
                {
                    spellSelection.ExtraMaxLevel = maxSpellLevel;
                    var existingExtra = spellSelection.ExtraSelected?.Length ?? 0;
                    spellSelection.ExtraSelected = new BlueprintAbility[spellsPerLevel + existingExtra];
                }
            }
            foreach (var customSpells in spellbook.Blueprint.GetComponents <AddCustomSpells>())
            {
                if (customSpells.CasterLevel == newCasterLevel)
                {
                    var customSelection = state.DemandSpellSelection(spellbook.Blueprint, customSpells.SpellList);
                    customSelection.SetExtraSpells(customSpells.Count, customSpells.MaxSpellLevel);
                }
            }
            ReplaceSpells.HandleUpdateCasterLevel(unit, state, spellbook);
        }
        static public bool Prefix(ApplySpellbook __instance, LevelUpState state, UnitDescriptor unit)
        {
            if (state.SelectedClass != ArcanistClass.arcanist)
            {
                return(true);
            }

            if (state.SelectedClass == null)
            {
                return(false);
            }
            SkipLevelsForSpellProgression component = state.SelectedClass.GetComponent <SkipLevelsForSpellProgression>();

            if (component != null && component.Levels.Contains(state.NextClassLevel))
            {
                return(false);
            }
            ClassData classData = unit.Progression.GetClassData(state.SelectedClass);

            if (classData == null)
            {
                return(false);
            }
            if (classData.Spellbook != null)
            {
                Spellbook spellbook = unit.DemandSpellbook(classData.Spellbook);
                if (state.SelectedClass.Spellbook && state.SelectedClass.Spellbook != classData.Spellbook)
                {
                    Spellbook spellbook2 = unit.Spellbooks.FirstOrDefault((Spellbook s) => s.Blueprint == state.SelectedClass.Spellbook);
                    if (spellbook2 != null)
                    {
                        foreach (AbilityData abilityData in spellbook2.GetAllKnownSpells())
                        {
                            spellbook.AddKnown(abilityData.SpellLevel, abilityData.Blueprint, false);
                        }
                        unit.DeleteSpellbook(state.SelectedClass.Spellbook);
                    }
                }
                int casterLevel = spellbook.CasterLevel;
                spellbook.AddCasterLevel();
                int casterLevel2 = spellbook.CasterLevel;
                SpellSelectionData spellSelectionData = state.DemandSpellSelection(spellbook.Blueprint, spellbook.Blueprint.SpellList);
                if (spellbook.Blueprint.SpellsKnown != null && 1 == 0)
                {
                    // SelectedClass must be arcanist, arcanist requires wizard-like spell selection,
                    // while its SpellsKnown is not null
                    for (int i = 0; i <= 9; i++)
                    {
                        int?count  = spellbook.Blueprint.SpellsKnown.GetCount(casterLevel, i);
                        int num    = (count == null) ? 0 : count.Value;
                        int?count2 = spellbook.Blueprint.SpellsKnown.GetCount(casterLevel2, i);
                        int num2   = (count2 == null) ? 0 : count2.Value;
                        spellSelectionData.SetLevelSpells(i, num2 - num);
                    }
                }
                int maxSpellLevel = spellbook.MaxSpellLevel;
                if (spellbook.Blueprint.SpellsPerLevel > 0)
                {
                    if (casterLevel == 0)
                    {
                        spellSelectionData.SetExtraSpells(0, maxSpellLevel);
                        spellSelectionData.ExtraByStat = true;
                        spellSelectionData.UpdateMaxLevelSpells(unit);
                    }
                    else
                    {
                        spellSelectionData.SetExtraSpells(spellbook.Blueprint.SpellsPerLevel, maxSpellLevel);
                    }
                }
                foreach (AddCustomSpells customSpells in spellbook.Blueprint.GetComponents <AddCustomSpells>())
                {
                    ApplySpellbook_TryApplyCustomSpells(__instance, spellbook, customSpells, state, unit);
                }
            }
            return(false);
        }