예제 #1
0
            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);
                                }
                            }
                        }
                    });
                }
            }
예제 #2
0
            private static void Postfix(LevelUpState state, UnitDescriptor unit)
            {
                if (!settings.toggleMulticlass)
                {
                    return;
                }
                if (!unit.IsPartyOrPet())
                {
                    return;
                }
                //if (Mod.IsCharGen()) Main.Log($"stack: {System.Environment.StackTrace}");
                if (IsAvailable())
                {
                    Main.multiclassMod.AppliedMulticlassSet.Clear();
                    Main.multiclassMod.UpdatedProgressions.Clear();
                    // Some companions have predefined levels so in some cases we get called iteratively for each level so we will make sure we only apply multiclass on the last level
                    if (unit.TryGetPartyMemberForLevelUpVersion(out var ch) &&
                        ch.TryGetClass(state.SelectedClass, out var cl) &&
                        unit != ch.Descriptor &&
                        state.NextClassLevel <= cl.Level
                        )
                    {
                        Mod.Debug($"SelectClass_Apply_Patch, unit: {unit.CharacterName.orange()} isCH: {unit == ch.Descriptor}) - skip - lvl:{state.NextClassLevel} vs {cl.Level} ".green());
                        return;
                    }
                    // get multi-class setting
                    var useDefaultMulticlassOptions = state.IsCharGen();
                    var options = MulticlassOptions.Get(useDefaultMulticlassOptions ? null : unit);
                    Mod.Trace($"SelectClass_Apply_Patch, unit: {unit.CharacterName.orange()} useDefaultMulticlassOptions: {useDefaultMulticlassOptions} isCharGen: {state.IsCharGen()} is1stLvl: {state.IsFirstCharacterLevel} isPHChar: {unit.CharacterName == "Player Character"} level: {state.NextClassLevel.ToString().yellow()}".cyan().bold());

                    if (options == null || options.Count == 0)
                    {
                        return;
                    }
                    Mod.Trace($"    selected options: {options}".orange());
                    //selectedMulticlassSet.ForEach(cl => Main.Log($"    {cl}"));

                    // applying classes
                    var           selectedClass = state.SelectedClass;
                    StateReplacer stateReplacer = new(state);
                    foreach (var characterClass in Main.multiclassMod.AllClasses)
                    {
                        if (characterClass.IsMythic != selectedClass.IsMythic)
                        {
                            continue;
                        }
                        if (Main.multiclassMod.AppliedMulticlassSet.Contains(characterClass))
                        {
                            Mod.Warn($"SelectClass_Apply_Patch - duplicate application of multiclass detected: {characterClass.name.yellow()}");
                            continue;
                        }
                        if (options.Contains(characterClass))
                        {
                            Mod.Trace($"   checking {characterClass.HashKey()} {characterClass.GetDisplayName()} ");
                        }
                        if (characterClass != stateReplacer.SelectedClass &&
                            characterClass.IsMythic == state.IsMythicClassSelected &&
                            options.Contains(characterClass)
                            )
                        {
                            stateReplacer.Replace(null, 0); // TODO - figure out and document what this is doing
                            Mod.Trace($"       {characterClass.Name} matches".cyan());
                            //stateReplacer.Replace(characterClass, unit.Progression.GetClassLevel(characterClass));

                            if (new SelectClass(characterClass).Check(state, unit))
                            {
                                Mod.Trace($"         - {nameof(SelectClass)}.{nameof(SelectClass.Apply)}*({characterClass}, {unit})".cyan());

                                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));

                                Main.multiclassMod.AppliedMulticlassSet.Add(characterClass);
                            }
                        }
                    }
                    stateReplacer.Restore();

                    Mod.Trace($"    checking archetypes for {unit.CharacterName}".cyan());
                    // applying archetypes
                    ForEachAppliedMulticlass(state, unit, () => {
                        Mod.Trace($"    {state.SelectedClass.HashKey()} SelectClass-ForEachApplied".cyan().bold());
                        var selectedClass    = state.SelectedClass;
                        var archetypeOptions = options.ArchetypeOptions(selectedClass);
                        foreach (var archetype in state.SelectedClass.Archetypes)
                        {
                            // here is where we need to start supporting multiple archetypes of the same class
                            if (archetypeOptions.Contains(archetype))
                            {
                                Mod.Trace($"    adding archetype: ${archetype.Name}".cyan().bold());
                                AddArchetype addArchetype = new(state.SelectedClass, archetype);
                                unit.SetClassIsGestalt(addArchetype.CharacterClass, true);
                                if (addArchetype.Check(state, unit))
                                {
                                    addArchetype.Apply(state, unit);
                                }
                            }
                        }