diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index e62ce9830..1e94d520a 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -1,386 +1,431 @@ -using Dalamud.Game.ClientState.JobGauge.Enums; +using System.Linq; +using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.MNK; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.JobHelpers; -internal abstract class MNKHelper : MNK +internal class MNK { - public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) - { - if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) - return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) - ? DragonKick - : OriginalHook(Bootshine); + // MNK Gauge & Extensions + public static float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; + public static MNKOpenerLogic MNKOpener = new(); + public static MNKGauge Gauge = GetJobGauge(); + + public static bool bothNadisOpen => Gauge.Nadi.ToString() == "LUNAR, SOLAR"; + + public static bool solarNadi => Gauge.Nadi == Nadi.SOLAR; + + public static bool lunarNadi => Gauge.Nadi == Nadi.LUNAR; + + public static int opoOpoChakra => Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); - if (HasEffect(Buffs.RaptorForm)) - return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) - ? TwinSnakes - : OriginalHook(TrueStrike); + public static int raptorChakra => Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); - if (HasEffect(Buffs.CoeurlForm)) + public static int coeurlChakra => Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + + internal class MNKHelper + { + public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) { - if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) + if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) + return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) + ? DragonKick + : OriginalHook(Bootshine); + + if (HasEffect(Buffs.RaptorForm)) + return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) + ? TwinSnakes + : OriginalHook(TrueStrike); + + if (HasEffect(Buffs.CoeurlForm)) { - if (!OnTargetsRear() && - TargetNeedsPositionals() && - !HasEffect(Buffs.TrueNorth) && - ActionReady(TrueNorth) && - useTrueNorthIfEnabled) - return TrueNorth; - - return Demolish; + if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) + { + if (!OnTargetsRear() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; + + return Demolish; + } + + if (LevelChecked(SnapPunch)) + { + if (!OnTargetsFlank() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; + + return OriginalHook(SnapPunch); + } } - if (LevelChecked(SnapPunch)) + return actionId; + } + + public static bool UsePerfectBalance() + { + if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance) && !HasEffect(Buffs.FormlessFist)) { - if (!OnTargetsFlank() && - TargetNeedsPositionals() && - !HasEffect(Buffs.TrueNorth) && - ActionReady(TrueNorth) && - useTrueNorthIfEnabled) - return TrueNorth; - - return OriginalHook(SnapPunch); + // Odd window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + !JustUsed(PerfectBalance, 20) && + HasEffect(Buffs.RiddleOfFire) && !HasEffect(Buffs.Brotherhood)) + return true; + + // Even window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && + (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) + return true; + + // Low level + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || + !LevelChecked(RiddleOfFire))) + return true; } - } - return actionId; + return false; + } } -} -internal class MNKOpenerLogic : MNK -{ - private OpenerState currentState = OpenerState.PrePull; + internal class MNKOpenerLogic + { + private OpenerState currentState = OpenerState.PrePull; - public uint OpenerStep; + public uint OpenerStep; - public uint PrePullStep; + public uint PrePullStep; - private static uint OpenerLevel => 100; + private static uint OpenerLevel => 100; - public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; - private static bool CanOpener => HasCooldowns() && LevelChecked; + private static bool CanOpener => HasCooldowns() && LevelChecked; - public OpenerState CurrentState - { - get => currentState; - set + public OpenerState CurrentState { - if (value != currentState) + get => currentState; + set { - if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); - if (value == OpenerState.InOpener) OpenerStep = 1; - - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + if (value != currentState) { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - currentState = value; + currentState = value; + } } } - } - private static bool HasCooldowns() - { - if (GetRemainingCharges(PerfectBalance) < 2) - return false; - - if (!ActionReady(Brotherhood)) - return false; + private static bool HasCooldowns() + { + if (GetRemainingCharges(PerfectBalance) < 2) + return false; - if (!ActionReady(RiddleOfFire)) - return false; + if (!ActionReady(Brotherhood)) + return false; - if (!ActionReady(RiddleOfWind)) - return false; + if (!ActionReady(RiddleOfFire)) + return false; - if (!ActionReady(Meditation) && Gauge.Chakra < 5) - return false; + if (!ActionReady(RiddleOfWind)) + return false; - if (Gauge.Nadi != Nadi.NONE) - return false; + if (Gauge.Nadi != Nadi.NONE) + return false; - if (Gauge.RaptorFury != 0) - return false; + if (Gauge.RaptorFury != 0) + return false; - if (Gauge.CoeurlFury != 0) - return false; + if (Gauge.CoeurlFury != 0) + return false; - return true; - } + return true; + } - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) return false; + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) PrePullStep = 1; + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns()) PrePullStep = 0; + if (!HasCooldowns()) PrePullStep = 0; - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (Gauge.Chakra < 5 && PrePullStep == 1) + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - actionID = ForbiddenMeditation; + if (Gauge.Chakra < 5 && PrePullStep == 1) + { + actionID = ForbiddenMeditation; - return true; - } + return true; + } - if (!HasEffect(Buffs.FormlessFist) && - !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) - { - actionID = FormShift; + if (!HasEffect(Buffs.FormlessFist) && + !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) + { + actionID = FormShift; - return true; - } + return true; + } - if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = DragonKick; - - if (ActionWatching.CombatActions.Count > 2 && InCombat()) - CurrentState = OpenerState.FailedOpener; + if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = DragonKick; - return true; - } - PrePullStep = 0; + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; - return false; - } + return true; + } + PrePullStep = 0; - private bool DoSlOpener(ref uint actionID) - { - if (!LevelChecked) return false; + } - if (currentState == OpenerState.InOpener) + private bool DoSlOpener(ref uint actionID) { - if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && - CanWeave(ActionWatching.LastWeaponskill) && - Gauge.Chakra >= 5 && - OpenerStep > 9) - { - actionID = TheForbiddenChakra; + if (!LevelChecked) + return false; - return true; - } + if (currentState == OpenerState.InOpener) + { + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + CanWeave(ActionWatching.LastWeaponskill) && + Gauge.Chakra >= 5 && + OpenerStep > 9) + { + actionID = TheForbiddenChakra; - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) - OpenerStep++; - else if (OpenerStep == 1) actionID = PerfectBalance; + return true; + } - if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = TwinSnakes; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) + OpenerStep++; + else if (OpenerStep == 1) actionID = PerfectBalance; - if (WasLastWeaponskill(Demolish) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Demolish; + if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = TwinSnakes; - if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Brotherhood; + if (WasLastWeaponskill(Demolish) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = Demolish; - if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; + if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Brotherhood; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = LeapingOpo; + if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; - if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = TheForbiddenChakra; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = LeapingOpo; - if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = TheForbiddenChakra; - if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = RisingPhoenix; + if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonKick; + if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = RisingPhoenix; - if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = WindsReply; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonKick; - if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = FiresReply; + if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = WindsReply; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = LeapingOpo; + if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FiresReply; - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) - OpenerStep++; - else if (OpenerStep == 14) actionID = PerfectBalance; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = LeapingOpo; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = DragonKick; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) + OpenerStep++; + else if (OpenerStep == 14) actionID = PerfectBalance; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LeapingOpo; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = DragonKick; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = DragonKick; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LeapingOpo; - if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = ElixirBurst; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = DragonKick; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 19) actionID = LeapingOpo; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = ElixirBurst; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 19) actionID = LeapingOpo; - if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || - (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || - (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || - (actionID is Brotherhood && IsOnCooldown(Brotherhood))) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - Svc.Log.Debug($"Failed at {actionID}"); - CurrentState = OpenerState.FailedOpener; + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; - return false; - } + if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || + (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || + (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || + (actionID is Brotherhood && IsOnCooldown(Brotherhood))) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + Svc.Log.Debug($"Failed at {actionID}"); + CurrentState = OpenerState.FailedOpener; - return true; - } + return false; + } - return false; - } + return true; + } - private bool DoLlOpener(ref uint actionID) - { - if (!LevelChecked) return false; + } - if (currentState == OpenerState.InOpener) + private bool DoLlOpener(ref uint actionID) { - if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && - CanWeave(ActionWatching.LastWeaponskill) && - Gauge.Chakra >= 5 && - OpenerStep > 9) + if (!LevelChecked) + return false; + + if (currentState == OpenerState.InOpener) { - actionID = TheForbiddenChakra; + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + CanWeave(ActionWatching.LastWeaponskill) && + Gauge.Chakra >= 5 && + OpenerStep > 9) + { + actionID = TheForbiddenChakra; - return true; - } + return true; + } - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) - OpenerStep++; - else if (OpenerStep == 1) actionID = PerfectBalance; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) + OpenerStep++; + else if (OpenerStep == 1) actionID = PerfectBalance; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = LeapingOpo; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = LeapingOpo; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = DragonKick; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = DragonKick; - if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Brotherhood; + if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Brotherhood; - if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; + if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = LeapingOpo; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = LeapingOpo; - if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = TheForbiddenChakra; + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = TheForbiddenChakra; - if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; + if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; - if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = ElixirBurst; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = ElixirBurst; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonKick; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonKick; - if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = WindsReply; + if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = WindsReply; - if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = FiresReply; + if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FiresReply; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = LeapingOpo; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = LeapingOpo; - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) - OpenerStep++; - else if (OpenerStep == 14) actionID = PerfectBalance; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) + OpenerStep++; + else if (OpenerStep == 14) actionID = PerfectBalance; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = DragonKick; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = DragonKick; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LeapingOpo; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LeapingOpo; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = DragonKick; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = DragonKick; - if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = ElixirBurst; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = ElixirBurst; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 19) actionID = LeapingOpo; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 19) actionID = LeapingOpo; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; - if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || - (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || - (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || - (actionID is Brotherhood && IsOnCooldown(Brotherhood))) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - Svc.Log.Debug($"Failed at {actionID}"); - CurrentState = OpenerState.FailedOpener; + if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || + (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || + (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || + (actionID is Brotherhood && IsOnCooldown(Brotherhood))) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + Svc.Log.Debug($"Failed at {actionID}"); + CurrentState = OpenerState.FailedOpener; - return false; + return false; + } + + return true; } - return true; + return false; } - return false; - } + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } + public bool DoFullOpener(ref uint actionID, int selectedOpener) + { + if (!LevelChecked) + return false; - public bool DoFullOpener(ref uint actionID, int selectedOpener) - { - if (!LevelChecked) - return false; + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; + if (CurrentState == OpenerState.InOpener) + switch (selectedOpener) + { + case 0 when DoLlOpener(ref actionID): - if (CurrentState == OpenerState.InOpener) - switch (selectedOpener) - { - case 0 when DoLlOpener(ref actionID): + case 1 when DoSlOpener(ref actionID): + return true; + } - case 1 when DoSlOpener(ref actionID): - return true; + if (!InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; } - if (!InCombat()) - { - ResetOpener(); - CurrentState = OpenerState.PrePull; + return false; } - - return false; } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index dfff50113..a26938709 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -1,78 +1,13 @@ -using System.Linq; -using Dalamud.Game.ClientState.JobGauge.Enums; -using Dalamud.Game.ClientState.JobGauge.Types; -using Dalamud.Game.ClientState.Statuses; -using XIVSlothCombo.Combos.JobHelpers; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; -using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; +using static XIVSlothCombo.Combos.JobHelpers.MNK; namespace XIVSlothCombo.Combos.PvE; internal class MNK { - public const byte ClassID = 2; - public const byte JobID = 20; - - public const uint - Bootshine = 53, - TrueStrike = 54, - SnapPunch = 56, - Meditation = 36940, - SteelPeak = 25761, - TwinSnakes = 61, - ArmOfTheDestroyer = 62, - Demolish = 66, - Mantra = 65, - DragonKick = 74, - Rockbreaker = 70, - Thunderclap = 25762, - HowlingFist = 25763, - FourPointFury = 16473, - PerfectBalance = 69, - FormShift = 4262, - TheForbiddenChakra = 3547, - MasterfulBlitz = 25764, - RiddleOfEarth = 7394, - EarthsReply = 36944, - RiddleOfFire = 7395, - Brotherhood = 7396, - RiddleOfWind = 25766, - EnlightenedMeditation = 36943, - Enlightenment = 16474, - SixSidedStar = 16476, - ShadowOfTheDestroyer = 25767, - RisingPhoenix = 25768, - WindsReply = 36949, - ForbiddenMeditation = 36942, - LeapingOpo = 36945, - RisingRaptor = 36946, - PouncingCoeurl = 36947, - TrueNorth = 7546, - ElixirBurst = 36948, - FiresReply = 36950; - - protected static MNKGauge Gauge => GetJobGauge(); - - protected static class Buffs - { - public const ushort - TwinSnakes = 101, - OpoOpoForm = 107, - RaptorForm = 108, - CoeurlForm = 109, - PerfectBalance = 110, - RiddleOfFire = 1181, - RiddleOfWind = 2687, - FormlessFist = 2513, - TrueNorth = 1250, - WindsRumination = 3842, - FiresRumination = 3843, - Brotherhood = 1185; - } - public static class Config { public static UserInt @@ -86,20 +21,10 @@ public static UserInt internal class MNK_ST_SimpleMode : CustomCombo { - internal static MNKOpenerLogic MNKOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); - int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); - int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); - float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; - if (actionID is Bootshine or LeapingOpo) { if (MNKOpener.DoFullOpener(ref actionID, 0)) @@ -141,29 +66,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb return RiddleOfWind; //Perfect Balance - if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist)) - { - // Odd window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - !JustUsed(PerfectBalance, 20) && - HasEffect(Buffs.RiddleOfFire) && - !HasEffect(Buffs.Brotherhood)) - return PerfectBalance; - - // Even window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && - (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) - return PerfectBalance; - - // Low level - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || - !LevelChecked(RiddleOfFire))) - return PerfectBalance; - } + if (MNKHelper.UsePerfectBalance()) + return PerfectBalance; if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) @@ -249,20 +153,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb internal class MNK_ST_AdvancedMode : CustomCombo { - internal static MNKOpenerLogic MNKOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_AdvancedMode; protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); - int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); - int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); - float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; - if (actionID is Bootshine or LeapingOpo) { if (IsEnabled(CustomComboPreset.MNK_STUseOpener)) @@ -315,29 +209,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Perfect Balance if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && - ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist)) - { - // Odd window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - !JustUsed(PerfectBalance, 20) && - HasEffect(Buffs.RiddleOfFire) && - !HasEffect(Buffs.Brotherhood)) - return PerfectBalance; - - // Even window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && - (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) - return PerfectBalance; - - // Low level - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || - !LevelChecked(RiddleOfFire))) - return PerfectBalance; - } + MNKHelper.UsePerfectBalance()) + return PerfectBalance; if (IsEnabled(CustomComboPreset.MNK_ST_ComboHeals)) { @@ -362,48 +235,45 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb ? DragonKick : OriginalHook(Bootshine); - if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) + // Masterful Blitz + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && + !IsOriginal(MasterfulBlitz)) + return OriginalHook(MasterfulBlitz); + + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) { - // Masterful Blitz - if (LevelChecked(MasterfulBlitz) && - !HasEffect(Buffs.PerfectBalance) && - !IsOriginal(MasterfulBlitz)) - return OriginalHook(MasterfulBlitz); + #region Open Solar - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) + if (!solarNadi && !bothNadisOpen) { - #region Open Solar - - if (!solarNadi && !bothNadisOpen) - { - if (coeurlChakra == 0) - return Gauge.CoeurlFury == 0 - ? Demolish - : OriginalHook(SnapPunch); - - if (raptorChakra == 0) - return Gauge.RaptorFury == 0 - ? TwinSnakes - : OriginalHook(TrueStrike); - - if (opoOpoChakra == 0) - return Gauge.OpoOpoFury == 0 - ? DragonKick - : OriginalHook(Bootshine); - } - - #endregion + if (coeurlChakra == 0) + return Gauge.CoeurlFury == 0 + ? Demolish + : OriginalHook(SnapPunch); - #region Open Lunar + if (raptorChakra == 0) + return Gauge.RaptorFury == 0 + ? TwinSnakes + : OriginalHook(TrueStrike); - if (solarNadi || lunarNadi || bothNadisOpen) + if (opoOpoChakra == 0) return Gauge.OpoOpoFury == 0 ? DragonKick : OriginalHook(Bootshine); - - #endregion } + + #endregion + + #region Open Lunar + + if (solarNadi || lunarNadi || bothNadisOpen) + return Gauge.OpoOpoFury == 0 + ? DragonKick + : OriginalHook(Bootshine); + + #endregion } if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) @@ -441,10 +311,6 @@ internal class MNK_AOE_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - bool nadiNone = Gauge.Nadi == Nadi.NONE; - if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) { if (!InCombat() && Gauge.Chakra < 5 && LevelChecked(Meditation)) @@ -476,14 +342,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return RiddleOfWind; if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) - - if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || - GetCooldownRemainingTime(PerfectBalance) <= 4 || - HasEffect(Buffs.Brotherhood) || - (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || - (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) - return PerfectBalance; + !HasEffect(Buffs.PerfectBalance) && + (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || + GetCooldownRemainingTime(PerfectBalance) <= 4 || + HasEffect(Buffs.Brotherhood) || + (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || + (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8))) + return PerfectBalance; if (Gauge.Chakra >= 5 && LevelChecked(HowlingFist) && @@ -497,12 +362,18 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return All.Bloodbath; } - if (HasEffect(Buffs.WindsRumination)) - return WindsReply; - - if (HasEffect(Buffs.FiresRumination)) + if (LevelChecked(FiresReply) && + HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) return FiresReply; + if (HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) + return WindsReply; + // Masterful Blitz if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) @@ -511,14 +382,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Perfect Balance if (HasEffect(Buffs.PerfectBalance)) { - if (nadiNone || !lunarNadi) - if (pbStacks?.StackCount > 0) - return LevelChecked(ShadowOfTheDestroyer) - ? ShadowOfTheDestroyer - : Rockbreaker; - - if (lunarNadi) - switch (pbStacks?.StackCount) + #region Open Solar + + if (!solarNadi && !bothNadisOpen) + switch (GetBuffStacks(Buffs.PerfectBalance)) { case 3: return OriginalHook(ArmOfTheDestroyer); @@ -529,6 +396,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim case 1: return Rockbreaker; } + + #endregion + + #region Open Lunar + + if (solarNadi || lunarNadi || bothNadisOpen) + return LevelChecked(ShadowOfTheDestroyer) + ? ShadowOfTheDestroyer + : Rockbreaker; + + #endregion } // Monk Rotation @@ -558,10 +436,6 @@ internal class MNK_AOE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - bool nadiNone = Gauge.Nadi == Nadi.NONE; - if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) { if (IsEnabled(CustomComboPreset.MNK_AoEUseMeditation) && @@ -602,20 +476,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance) && ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) - - // Use Perfect Balance if: - // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE - // 2. At max stacks / before overcap. - // 3. During Brotherhood. - // 4. During Riddle of Fire. - // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || - GetCooldownRemainingTime(PerfectBalance) <= 4 || - HasEffect(Buffs.Brotherhood) || - (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || - (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) - return PerfectBalance; + !HasEffect(Buffs.PerfectBalance) && + (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || + GetCooldownRemainingTime(PerfectBalance) <= 4 || + HasEffect(Buffs.Brotherhood) || + (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || + (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8))) + return PerfectBalance; if (IsEnabled(CustomComboPreset.MNK_AoEUseHowlingFist) && Gauge.Chakra >= 5 && @@ -639,45 +506,55 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (IsEnabled(CustomComboPreset.MNK_AoEUseROF) && IsEnabled(CustomComboPreset.MNK_AoEUseFiresReply) && - HasEffect(Buffs.FiresRumination)) + LevelChecked(FiresReply) && + HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) return FiresReply; if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && IsEnabled(CustomComboPreset.MNK_AoEUseWindsReply) && - HasEffect(Buffs.WindsRumination)) + HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) return WindsReply; } // Masterful Blitz - if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance)) + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && + OriginalHook(MasterfulBlitz) != MasterfulBlitz) + return OriginalHook(MasterfulBlitz); + + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) { - if (LevelChecked(MasterfulBlitz) && - !HasEffect(Buffs.PerfectBalance) && - OriginalHook(MasterfulBlitz) != MasterfulBlitz) - return OriginalHook(MasterfulBlitz); + #region Open Solar - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) - { - if (nadiNone || !lunarNadi) - if (pbStacks?.StackCount > 0) - return LevelChecked(ShadowOfTheDestroyer) - ? ShadowOfTheDestroyer - : Rockbreaker; - - if (lunarNadi) - switch (pbStacks?.StackCount) - { - case 3: - return OriginalHook(ArmOfTheDestroyer); - - case 2: - return FourPointFury; - - case 1: - return Rockbreaker; - } - } + if (!solarNadi && !bothNadisOpen) + switch (GetBuffStacks(Buffs.PerfectBalance)) + { + case 3: + return OriginalHook(ArmOfTheDestroyer); + + case 2: + return FourPointFury; + + case 1: + return Rockbreaker; + } + + #endregion + + #region Open Lunar + + if (solarNadi || lunarNadi || bothNadisOpen) + return LevelChecked(ShadowOfTheDestroyer) + ? ShadowOfTheDestroyer + : Rockbreaker; + + #endregion } // Monk Rotation @@ -707,11 +584,10 @@ internal class MNK_PerfectBalance : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - if (actionID is PerfectBalance && - OriginalHook(MasterfulBlitz) != MasterfulBlitz && LevelChecked(MasterfulBlitz)) - return OriginalHook(MasterfulBlitz); - - return actionID; + return actionID is PerfectBalance && OriginalHook(MasterfulBlitz) != MasterfulBlitz && + LevelChecked(MasterfulBlitz) + ? OriginalHook(MasterfulBlitz) + : actionID; } } @@ -727,6 +603,68 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } + #region ID's + + public const byte ClassID = 2; + public const byte JobID = 20; + + public const uint + Bootshine = 53, + TrueStrike = 54, + SnapPunch = 56, + Meditation = 36940, + SteelPeak = 25761, + TwinSnakes = 61, + ArmOfTheDestroyer = 62, + Demolish = 66, + Mantra = 65, + DragonKick = 74, + Rockbreaker = 70, + Thunderclap = 25762, + HowlingFist = 25763, + FourPointFury = 16473, + PerfectBalance = 69, + FormShift = 4262, + TheForbiddenChakra = 3547, + MasterfulBlitz = 25764, + RiddleOfEarth = 7394, + EarthsReply = 36944, + RiddleOfFire = 7395, + Brotherhood = 7396, + RiddleOfWind = 25766, + EnlightenedMeditation = 36943, + Enlightenment = 16474, + SixSidedStar = 16476, + ShadowOfTheDestroyer = 25767, + RisingPhoenix = 25768, + WindsReply = 36949, + ForbiddenMeditation = 36942, + LeapingOpo = 36945, + RisingRaptor = 36946, + PouncingCoeurl = 36947, + TrueNorth = 7546, + ElixirBurst = 36948, + FiresReply = 36950; + + public static class Buffs + { + public const ushort + TwinSnakes = 101, + OpoOpoForm = 107, + RaptorForm = 108, + CoeurlForm = 109, + PerfectBalance = 110, + RiddleOfFire = 1181, + RiddleOfWind = 2687, + FormlessFist = 2513, + TrueNorth = 1250, + WindsRumination = 3842, + FiresRumination = 3843, + Brotherhood = 1185; + } + + #endregion + #region Beast Chakras internal class MNK_BeastChakra_OpoOpo : CustomCombo