From 5dbb5d84582caf464e8ade7b3fc27ff53f486478 Mon Sep 17 00:00:00 2001 From: LTS-FFXIV <127939494+LTS-FFXIV@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:51:26 -0600 Subject: [PATCH] Ninja fixes --- BasicRotations/Melee/NIN_Default.cs | 41 +++------- RotationSolver.Basic/Helpers/ObjectHelper.cs | 2 +- .../Rotations/Basic/NinjaRotation.cs | 80 ++++++++++++++----- 3 files changed, 72 insertions(+), 51 deletions(-) diff --git a/BasicRotations/Melee/NIN_Default.cs b/BasicRotations/Melee/NIN_Default.cs index 16eaea9fe..32b4d118f 100644 --- a/BasicRotations/Melee/NIN_Default.cs +++ b/BasicRotations/Melee/NIN_Default.cs @@ -16,11 +16,6 @@ public sealed class NIN_Default : NinjaRotation [RotationConfig(CombatType.PvE, Name = "Use Unhide")] public bool AutoUnhide { get; set; } = true; - - [RotationConfig(CombatType.PvE, Name = "Attempt to lock out all GCDs except mudra during mudra to prevent ghosting")] - public bool MudraProtection { get; set; } = false; - - public bool IsShadowWalking = Player.HasStatus(true, StatusID.ShadowWalker); #endregion #region CountDown Logic @@ -104,34 +99,30 @@ private bool ChoiceNinjutsu(out IAction? act) { // Attempts to set high-damage AoE Ninjutsu if available under Kassatsu's effect. // These are prioritized due to Kassatsu's enhancement of Ninjutsu abilities. - if (GokaMekkyakuPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _)) + if (NumberOfHostilesInRange > 2 && GokaMekkyakuPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _)) { SetNinjutsu(GokaMekkyakuPvE); - return false; } - if (HyoshoRanryuPvE.EnoughLevel && TenPvE.CanUse(out _) && JinPvE.CanUse(out _)) + if (NumberOfHostilesInRange == 1 && HyoshoRanryuPvE.EnoughLevel && TenPvE.CanUse(out _) && JinPvE.CanUse(out _)) { SetNinjutsu(HyoshoRanryuPvE); - return false; } if (HutonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _)) { SetNinjutsu(HutonPvE); - return false; } if (KatonPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _)) { SetNinjutsu(KatonPvE); - return false; } if (RaitonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _)) { SetNinjutsu(RaitonPvE); - return false; } + else return false; } else { @@ -218,7 +209,7 @@ private bool DoNinjutsu(out IAction? act) { if (RaitonPvE_18877.CanUse(out act, skipAoeCheck: true)) return true; } - else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880) && !Player.HasStatus(true, StatusID.Doton)) + else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880) && !HasDoton) { if (DotonPvE_18880.CanUse(out act, skipAoeCheck: true)) return true; } @@ -230,7 +221,7 @@ private bool DoNinjutsu(out IAction? act) //Keep Kassatsu in Burst. if (!Player.WillStatusEnd(3, false, StatusID.Kassatsu) - && Player.HasStatus(false, StatusID.Kassatsu) && !InTrickAttack) return false; + && HasKassatsu && !InTrickAttack) return false; if (_ninActionAim == null) return false; var id = AdjustId(ActionID.NinjutsuPvE); @@ -316,11 +307,6 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) // If Ninjutsu is available or not in combat, defers to the base class's emergency ability logic. if (!NoNinjutsu || !InCombat) return base.EmergencyAbility(nextGCD, out act); - if (NoNinjutsu) - { - if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true; - } - // First priority is given to Kassatsu if it's available, allowing for an immediate powerful Ninjutsu. if (NoNinjutsu && KassatsuPvE.CanUse(out act)) return true; if (!TenChiJinPvE.Cooldown.IsCoolingDown && MeisuiPvE.CanUse(out act)) return true; @@ -378,7 +364,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) // - Not in the Mug's effective window or within Trick Attack's window // - Certain cooldown conditions are met, or specific statuses are active. if ((!InMug || InTrickAttack) - && (!BunshinPvE.Cooldown.WillHaveOneCharge(10) || Player.HasStatus(false, StatusID.PhantomKamaitachiReady) || MugPvE.Cooldown.WillHaveOneCharge(2))) + && (!BunshinPvE.Cooldown.WillHaveOneCharge(10) || HasPhantomKamaitachi || MugPvE.Cooldown.WillHaveOneCharge(2))) { if (HellfrogMediumPvE.CanUse(out act, skipAoeCheck: !BhavacakraPvE.EnoughLevel)) return true; if (BhavacakraPvE.CanUse(out act)) return true; @@ -402,14 +388,14 @@ protected override bool GeneralGCD(out IAction? act) { act = null; - var hasRaijuReady = Player.HasStatus(true, StatusID.RaijuReady); - if (RabbitMediumPvE.CanUse(out act)) return true; - if ((InTrickAttack || InMug) && NoNinjutsu && !hasRaijuReady + if ((InTrickAttack || InMug) && NoNinjutsu && !HasRaijuReady && !Player.HasStatus(true, StatusID.TenChiJin) && PhantomKamaitachiPvE.CanUse(out act)) return true; + if (FleetingRaijuPvE.CanUse(out act)) return true; + if (ChoiceNinjutsu(out act)) return true; if ((!InCombat || !CombatElapsedLess(7)) && DoNinjutsu(out act)) return true; @@ -417,12 +403,7 @@ protected override bool GeneralGCD(out IAction? act) if (NoNinjutsu) { if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true; - if (hasRaijuReady) return false; - } - - if (IsLastAbility(true, TenPvE, ChiPvE, JinPvE) && MudraProtection) - { - return base.GeneralGCD(out act); + if (HasRaijuReady) return false; } //AOE @@ -436,7 +417,7 @@ protected override bool GeneralGCD(out IAction? act) if (SpinningEdgePvE.CanUse(out act)) return true; //Range - if (!Player.HasStatus(true, StatusID.Mudra)) + if (!IsExecutingMudra) { if (ThrowingDaggerPvE.CanUse(out act)) return true; } diff --git a/RotationSolver.Basic/Helpers/ObjectHelper.cs b/RotationSolver.Basic/Helpers/ObjectHelper.cs index 3c584776a..d63e5bb37 100644 --- a/RotationSolver.Basic/Helpers/ObjectHelper.cs +++ b/RotationSolver.Basic/Helpers/ObjectHelper.cs @@ -47,7 +47,7 @@ internal static bool CanProvoke(this IGameObject target) { foreach (var n in ns1) { - if (!string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name?.ExtractText() ?? string.Empty).Success) + if (!string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name?.GetText() ?? string.Empty).Success) { return false; } diff --git a/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs b/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs index 6cad3b2a2..a33a3e81a 100644 --- a/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs @@ -41,7 +41,7 @@ partial class NinjaRotation /// /// Checks if no ninjutsu action is currently selected or if the Rabbit Medium has been invoked. /// - public static bool NoNinjutsu => AdjustId(ActionID.NinjutsuPvE) is ActionID.NinjutsuPvE or ActionID.RabbitMediumPvE; + public static bool NoNinjutsu => !IsExecutingMudra || RabbitMediumPvEActive; /// /// Holds the remaining amount of Delirium stacks @@ -121,9 +121,49 @@ public static byte RaijuStacks /// /// /// - public static bool TenriJindoPvEReady => Service.GetAdjustedActionId(ActionID.TenChiJinPvE) == ActionID.TenriJindoPvE; + public static bool TenriJindoPvEReady => Service.GetAdjustedActionId(ActionID.TenChiJinPvE) == ActionID.TenriJindoPvE && !HasTenChiJin; #endregion + /// + /// + /// + public static bool HasKassatsu => !Player.WillStatusEnd(0, true, StatusID.Kassatsu); + + /// + /// + /// + public static bool HasRaijuReady => !Player.WillStatusEnd(0, true, StatusID.RaijuReady); + + /// + /// + /// + public static bool IsExecutingMudra => !Player.WillStatusEnd(0, true, StatusID.Mudra); + + /// + /// + /// + public static bool HasDoton => !Player.WillStatusEnd(0, true, StatusID.Doton); + + /// + /// + /// + public static bool IsShadowWalking => !Player.WillStatusEnd(0, true, StatusID.ShadowWalker); + + /// + /// + /// + public static bool HasPhantomKamaitachi => !Player.WillStatusEnd(0, true, StatusID.PhantomKamaitachiReady); + + /// + /// + /// + public static bool HasTenChiJin => !Player.WillStatusEnd(0, true, StatusID.TenChiJin); + + /// + /// + /// + public static bool IsHidden => !Player.WillStatusEnd(0, true, StatusID.Hidden); + #region Draw Debug /// public override void DisplayStatus() @@ -277,11 +317,12 @@ static partial void ModifyArmorCrushPvE(ref ActionSetting setting) static partial void ModifyDreamWithinADreamPvE(ref ActionSetting setting) { setting.UnlockedByQuestID = 67222; + setting.ActionCheck = () => !HasTenChiJin; } static partial void ModifyHellfrogMediumPvE(ref ActionSetting setting) { - setting.ActionCheck = () => Ninki >= 50; + setting.ActionCheck = () => Ninki >= 50 && !HasTenChiJin; setting.CreateConfig = () => new ActionConfig() { AoeCount = 3, @@ -292,7 +333,7 @@ static partial void ModifyDokumoriPvE(ref ActionSetting setting) { setting.StatusProvide = [StatusID.Higi]; setting.TargetStatusProvide = [StatusID.Dokumori]; - setting.ActionCheck = () => Ninki <= 60 && IsLongerThan(10); + setting.ActionCheck = () => Ninki <= 60 && IsLongerThan(10) && !HasTenChiJin; setting.CreateConfig = () => new ActionConfig() { TimeToKill = 10, @@ -305,31 +346,32 @@ static partial void ModifyDokumoriPvE(ref ActionSetting setting) static partial void ModifyBhavacakraPvE(ref ActionSetting setting) { - setting.ActionCheck = () => Ninki >= 50; + setting.ActionCheck = () => Ninki >= 50 && !HasTenChiJin; } static partial void ModifyTenChiJinPvE(ref ActionSetting setting) { + setting.ActionCheck = () => !HasKassatsu; setting.StatusProvide = [StatusID.TenChiJin, StatusID.TenriJindoReady]; setting.UnlockedByQuestID = 68488; } - + static partial void ModifyMeisuiPvE(ref ActionSetting setting) { setting.StatusNeed = [StatusID.ShadowWalker]; setting.StatusProvide = [StatusID.Meisui]; - setting.ActionCheck = () => !Player.HasStatus(true, StatusID.Kassatsu) && InCombat; + setting.ActionCheck = () => !HasKassatsu && InCombat && !HasTenChiJin; } static partial void ModifyBunshinPvE(ref ActionSetting setting) { - setting.ActionCheck = () => Ninki >= 50; + setting.ActionCheck = () => Ninki >= 50 && !HasTenChiJin; setting.StatusProvide = [StatusID.Bunshin, StatusID.PhantomKamaitachiReady]; } static partial void ModifyPhantomKamaitachiPvE(ref ActionSetting setting) { - setting.StatusNeed = [StatusID.PhantomKamaitachiReady]; + setting.ActionCheck = () => HasPhantomKamaitachi; setting.CreateConfig = () => new ActionConfig() { AoeCount = 1, @@ -338,7 +380,7 @@ static partial void ModifyPhantomKamaitachiPvE(ref ActionSetting setting) static partial void ModifyHollowNozuchiPvE(ref ActionSetting setting) { - setting.StatusNeed = [StatusID.Doton]; + setting.ActionCheck = () => HasDoton; setting.CreateConfig = () => new ActionConfig() { AoeCount = 1, @@ -347,17 +389,17 @@ static partial void ModifyHollowNozuchiPvE(ref ActionSetting setting) static partial void ModifyForkedRaijuPvE(ref ActionSetting setting) { - setting.StatusNeed = [StatusID.RaijuReady]; + setting.ActionCheck = () => HasRaijuReady; } static partial void ModifyFleetingRaijuPvE(ref ActionSetting setting) { - setting.StatusNeed = [StatusID.RaijuReady]; + setting.ActionCheck = () => HasRaijuReady; } static partial void ModifyKunaisBanePvE(ref ActionSetting setting) { - setting.ActionCheck = () => Player.HasStatus(true, StatusID.Hidden) || Player.HasStatus(true, StatusID.ShadowWalker); + setting.ActionCheck = () => (IsHidden || IsShadowWalking) && !HasTenChiJin; setting.TargetStatusProvide = [StatusID.KunaisBane]; setting.CreateConfig = () => new ActionConfig() { @@ -367,7 +409,7 @@ static partial void ModifyKunaisBanePvE(ref ActionSetting setting) static partial void ModifyDeathfrogMediumPvE(ref ActionSetting setting) { - setting.ActionCheck = () => Ninki <= 50 && DeathfrogMediumPvEReady; + setting.ActionCheck = () => Ninki <= 50 && DeathfrogMediumPvEReady && !HasTenChiJin; setting.CreateConfig = () => new ActionConfig() { AoeCount = 3, @@ -376,7 +418,7 @@ static partial void ModifyDeathfrogMediumPvE(ref ActionSetting setting) static partial void ModifyZeshoMeppoPvE(ref ActionSetting setting) { - setting.ActionCheck = () => Ninki <= 50 && ZeshoMeppoPvEReady; + setting.ActionCheck = () => Ninki <= 50 && ZeshoMeppoPvEReady && !HasTenChiJin; } static partial void ModifyTenriJindoPvE(ref ActionSetting setting) @@ -426,13 +468,11 @@ static partial void ModifyRaitonPvE(ref ActionSetting setting) static partial void ModifyHyotonPvE(ref ActionSetting setting) { setting.ActionCheck = () => HyotonPvEReady; - setting.TargetStatusProvide = [StatusID.Blind]; } static partial void ModifyHutonPvE(ref ActionSetting setting) { - setting.ActionCheck = () => HutonPvEReady; - setting.StatusProvide = [StatusID.ShadowWalker]; + setting.ActionCheck = () => HutonPvEReady && !IsShadowWalking; setting.CreateConfig = () => new ActionConfig() { AoeCount = 3, @@ -457,7 +497,7 @@ static partial void ModifySuitonPvE(ref ActionSetting setting) static partial void ModifyGokaMekkyakuPvE(ref ActionSetting setting) { - setting.ActionCheck = () => GokaMekkyakuPvEReady; + setting.ActionCheck = () => HasKassatsu; setting.CreateConfig = () => new ActionConfig() { AoeCount = 3, @@ -466,7 +506,7 @@ static partial void ModifyGokaMekkyakuPvE(ref ActionSetting setting) static partial void ModifyHyoshoRanryuPvE(ref ActionSetting setting) { - setting.ActionCheck = () => HyoshoRanryuPvEReady; + setting.ActionCheck = () => HasKassatsu; } #endregion