Exemplo n.º 1
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);
                                }
                            }
                        }
Exemplo n.º 2
0
            public static void Postfix(bool __state, ItemEntity __instance, ref bool __result, UnitDescriptor user)
            {
                if (__state)
                {
                    var blueprintItemEquipment = __instance.Blueprint as BlueprintItemEquipment;
                    if (!blueprintItemEquipment || !blueprintItemEquipment.GainAbility)
                    {
                        __result = false;
                        return;
                    }
                    if (!__instance.IsSpendCharges)
                    {
                        __result = true;
                        return;
                    }
                    var hasNoCharges = false;
                    if (__instance.Charges > 0)
                    {
                        ItemEntityUsable itemEntityUsable = new((BlueprintItemEquipmentUsable)__instance.Blueprint);
                        if (user.State.Features.HandOfMagusDan && itemEntityUsable.Blueprint.Type == UsableItemType.Scroll)
                        {
                            RuleRollDice ruleRollDice = new(user.Unit, new DiceFormula(1, DiceType.D100));
                            Rulebook.Trigger(ruleRollDice);
                            if (ruleRollDice.Result <= 25)
                            {
                                __result = true;
                                return;
                            }
                        }

                        if (user.IsPartyOrPet())
                        {
                            __result = true;
                            return;
                        }

                        --__instance.Charges;
                    }
                    else
                    {
                        hasNoCharges = true;
                    }

                    if (__instance.Charges >= 1 || blueprintItemEquipment.RestoreChargesOnRest)
                    {
                        __result = !hasNoCharges;
                        return;
                    }

                    if (__instance.Count > 1)
                    {
                        __instance.DecrementCount(1);
                        __instance.Charges = 1;
                    }
                    else
                    {
                        var collection = __instance.Collection;
                        collection?.Remove(__instance);
                    }

                    __result = !hasNoCharges;
                }
            }