static void Postfix(SelectFeature __instance, ref StateReplacer __state) { if (__state != null) { __state.Restore(); } }
static void Postfix(LevelUpState state, UnitDescriptor unit) { if (IsAvailable()) { Core.Mod.AppliedMulticlassSet.Clear(); Core.Mod.UpdatedProgressions.Clear(); // get multiclass setting HashSet <string> selectedMulticlassSet = Core.Mod.LevelUpController.Unit.IsMainCharacter ? MainCharSet : (state.IsCharGen() && unit.IsCustomCompanion()) ? CharGenSet : CompanionSets.ContainsKey(unit.CharacterName) ? CompanionSets[unit.CharacterName] : null; if (selectedMulticlassSet == null || selectedMulticlassSet.Count == 0) { return; } // applying classes StateReplacer stateReplacer = new StateReplacer(state); foreach (BlueprintCharacterClass characterClass in Core.Mod.CharacterClasses) { if (characterClass != stateReplacer.SelectedClass && selectedMulticlassSet.Contains(characterClass.AssetGuid)) { stateReplacer.Replace(null, 0); if (new SelectClass(characterClass).Check(state, unit)) { Core.Debug($" - {nameof(SelectClass)}.{nameof(SelectClass.Apply)}*({characterClass}, {unit})"); unit.Progression.AddClassLevel_NotCharacterLevel(characterClass); //state.NextClassLevel = unit.Progression.GetClassLevel(characterClass); //state.SelectedClass = characterClass; characterClass.RestrictPrerequisites(unit, state); //EventBus.RaiseEvent<ILevelUpSelectClassHandler>(h => h.HandleSelectClass(unit, state)); Core.Mod.AppliedMulticlassSet.Add(characterClass); } } } stateReplacer.Restore(); // applying archetypes ForEachAppliedMulticlass(state, unit, () => { foreach (BlueprintArchetype archetype in state.SelectedClass.Archetypes) { if (selectedMulticlassSet.Contains(archetype.AssetGuid)) { AddArchetype addArchetype = new AddArchetype(state.SelectedClass, archetype); if (addArchetype.Check(state, unit)) { addArchetype.Apply(state, unit); } } } }); } }
static void Postfix(SelectFeature __instance, ref StateReplacer __state) { if (!settings.toggleMulticlass) { return; } if (__state != null) { __state.Restore(); } }
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); } }