static void Prefix(ApplySpellbook __instance, LevelUpState state, UnitDescriptor unit)
 {
     if (IsAvailable())
     {
         Core.Debug($" - {nameof(ApplySpellbook)}.{nameof(ApplySpellbook.Apply)}({state.SelectedClass}[{state.NextClassLevel}], {unit})");
     }
 }
Example #2
0
 static void Postfix(ApplySpellbook __instance, ref bool __state)
 {
     if (__state)
     {
         Enabled = true;
     }
 }
Example #3
0
 static void Prefix(ApplySpellbook __instance, ref bool __state)
 {
     if (IsAvailable())
     {
         __state = true;
         Enabled = false;
     }
 }
Example #4
0
 static void Postfix(MethodBase __originalMethod, ApplySpellbook __instance, LevelUpState state, UnitDescriptor unit)
 {
     if (IsAvailable() && !Main.multiclassMod.LockedPatchedMethods.Contains(__originalMethod))
     {
         Main.multiclassMod.LockedPatchedMethods.Add(__originalMethod);
         ForEachAppliedMulticlass(state, unit, () => {
             __instance.Apply(state, unit);
         });
         Main.multiclassMod.LockedPatchedMethods.Remove(__originalMethod);
     }
 }
Example #5
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);
            }
Example #6
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);
            }
Example #7
0
            static void Postfix(MethodBase __originalMethod, ApplySpellbook __instance, LevelUpState state, UnitDescriptor unit)
            {
                if (!IsAvailable())
                {
                    return;
                }

                if (!Core.Mod.LockedPatchedMethods.Contains(__originalMethod))
                {
                    Core.Mod.LockedPatchedMethods.Add(__originalMethod);

                    Dictionary <Spellbook, int> spellbookCasterLevels = new Dictionary <Spellbook, int>();

                    // simulate the internal caster level
                    foreach (ClassData classData in unit.Progression.Classes)
                    {
                        if (classData != null && classData.Spellbook != null)
                        {
                            int[] skipLevelList = classData.CharacterClass.GetComponent <SkipLevelsForSpellProgression>()?.Levels;
                            int   skipLevels    = 0;
                            // Eldritch Knight || Dragon Disciple
                            if (classData.CharacterClass.AssetGuid == "de52b73972f0ed74c87f8f6a8e20b542" ||
                                classData.CharacterClass.AssetGuid == "72051275b1dbb2d42ba9118237794f7c")
                            {
                                skipLevels = 1;
                            }

                            Spellbook spellbook = unit.DemandSpellbook(classData.Spellbook);
                            if (!spellbookCasterLevels.TryGetValue(spellbook, out int casterLevel))
                            {
                                casterLevel = 0;
                            }
                            for (int i = 1 + skipLevels; i <= classData.Level; i++)
                            {
                                if (skipLevelList == null || !skipLevelList.Contains(i))
                                {
                                    casterLevel++;
                                }
                            }
                            spellbookCasterLevels[spellbook] = casterLevel;
                        }
                    }

                    // f*****g Mystic
                    foreach (Feature feature in unit.Progression.Features.Enumerable
                             .Where(feature => feature.Components.Any(item => item is AddSpellbookLevel)))
                    {
                        foreach (AddSpellbookLevel fact in feature.Components
                                 .Where(item => item is AddSpellbookLevel))
                        {
                            ClassData classData     = unit.Progression.GetClassData(feature.GetSourceClass());
                            int[]     skipLevelList = classData.CharacterClass.GetComponent <SkipLevelsForSpellProgression>()?.Levels;

                            Spellbook spellbook = fact.Owner.DemandSpellbook(fact.Spellbook);
                            if (!spellbookCasterLevels.TryGetValue(spellbook, out int casterLevel))
                            {
                                casterLevel = 0;
                            }
                            for (int i = 1; i <= classData.Level; i++)
                            {
                                if (skipLevelList == null || !skipLevelList.Contains(i))
                                {
                                    casterLevel++;
                                }
                            }
                            spellbookCasterLevels[spellbook] = casterLevel;
                        }
                    }

                    // simulate the caster level
                    foreach (Spellbook spellbook in new List <Spellbook>(spellbookCasterLevels.Keys))
                    {
                        int casterLevel = spellbookCasterLevels[spellbook];
                        int maxLevel    = spellbook.Blueprint.SpellsPerDay.Levels.Length - 1;
                        if (RestrictCasterLevelToCharacterLevel.IsAvailable())
                        {
                            casterLevel = Math.Min(casterLevel, unit.Progression.CharacterLevel);
                        }
                        casterLevel = Math.Max(0, Math.Min(maxLevel, casterLevel + spellbook.Blueprint.CasterLevelModifier));
                        spellbookCasterLevels[spellbook] = casterLevel;
                        Core.Debug($"   - Recalculated spellbook: {spellbook.Blueprint.Name}, target level: {casterLevel}, current level: {spellbook.CasterLevel}");
                    }

                    // check and increase the caster level of the spellbooks
                    StateReplacer stateReplacer = new StateReplacer(state);
                    foreach (Spellbook spellbook in spellbookCasterLevels.Keys)
                    {
                        BlueprintCharacterClass characterClass = spellbook.Blueprint.GetOwnerClass(unit);
                        stateReplacer.Replace(characterClass, unit.Progression.GetClassLevel(characterClass));

                        // We need __instance.Apply(state, unit) to always lead to an increase in the caster level
                        SkipLevelsForSpellProgression skipLevels = characterClass.GetComponent <SkipLevelsForSpellProgression>();
                        int[] backup = skipLevels?.Levels;
                        if (skipLevels != null)
                        {
                            skipLevels.Levels = new int[0];
                        }

                        int casterLevel = spellbookCasterLevels[spellbook];
                        while (spellbook.CasterLevel < casterLevel)
                        {
                            Core.Debug($"   - Applying caster level: {spellbook.CasterLevel} => {casterLevel}");
                            __instance.Apply(state, unit);
                        }

                        if (skipLevels != null)
                        {
                            skipLevels.Levels = backup;
                        }
                    }
                    stateReplacer.Restore();

                    Core.Mod.LockedPatchedMethods.Remove(__originalMethod);
                }
            }
        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);
        }