From 57e0c262659f1ba0168248e3291be9bb98a43a21 Mon Sep 17 00:00:00 2001 From: Akechi-kun <167795370+Akechi-kun@users.noreply.github.com> Date: Tue, 24 Dec 2024 19:12:45 -0800 Subject: [PATCH] NIN Shukuchi addition --- .../Autorotation/Utility/ClassDRGUtility.cs | 9 +- .../Autorotation/Utility/ClassNINUtility.cs | 83 ++++++++++++++++++- 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/BossMod/Autorotation/Utility/ClassDRGUtility.cs b/BossMod/Autorotation/Utility/ClassDRGUtility.cs index 343e0c047..0d0f2bb20 100644 --- a/BossMod/Autorotation/Utility/ClassDRGUtility.cs +++ b/BossMod/Autorotation/Utility/ClassDRGUtility.cs @@ -3,8 +3,7 @@ public sealed class ClassDRGUtility(RotationModuleManager manager, Actor player) : RoleMeleeUtility(manager, player) { public enum Track { WingedGlide = SharedTrack.Count } - public enum DashStrategy { None, GapClose } - public bool InMeleeRange(Actor? target) => Player.DistanceToHitbox(target) <= 3; //Checks if we're inside melee range + public enum DashStrategy { None, GapClose, GapCloseHold1 } public static readonly ActionID IDLimitBreak3 = ActionID.MakeSpell(DRG.AID.DragonsongDive); @@ -15,7 +14,8 @@ public static RotationModuleDefinition Definition() res.Define(Track.WingedGlide).As("Winged Glide", "Dash", 20) .AddOption(DashStrategy.None, "Automatic", "No use.") - .AddOption(DashStrategy.GapClose, "GapClose", "Use as gapcloser if outside melee range", 60, 0, ActionTargets.Hostile, 45) + .AddOption(DashStrategy.GapClose, "GapClose", "Use Winged Glide as gapcloser if outside melee range", 60, 0, ActionTargets.Hostile, 45) + .AddOption(DashStrategy.GapCloseHold1, "GapCloseHold1", "Use Winged Glide as gapcloser if outside melee range; conserves 1 charge for manual usage", 60, 0, ActionTargets.Hostile, 84) .AddAssociatedActions(DRG.AID.WingedGlide); return res; @@ -34,7 +34,8 @@ public override void Execute(StrategyValues strategy, Actor? primaryTarget, floa private bool ShouldUseDash(DashStrategy strategy, Actor? primaryTarget) => strategy switch { DashStrategy.None => false, - DashStrategy.GapClose => !InMeleeRange(primaryTarget), + DashStrategy.GapClose => Player.DistanceToHitbox(primaryTarget) is > 3 and <= 20, + DashStrategy.GapCloseHold1 => Player.DistanceToHitbox(primaryTarget) is > 3 and <= 20 && World.Client.Cooldowns[ActionDefinitions.Instance.Spell(DRG.AID.WingedGlide)!.MainCooldownGroup].Remaining <= 59.9f, _ => false, }; } diff --git a/BossMod/Autorotation/Utility/ClassNINUtility.cs b/BossMod/Autorotation/Utility/ClassNINUtility.cs index b3cea3fae..7369dc67f 100644 --- a/BossMod/Autorotation/Utility/ClassNINUtility.cs +++ b/BossMod/Autorotation/Utility/ClassNINUtility.cs @@ -2,7 +2,8 @@ public sealed class ClassNINUtility(RotationModuleManager manager, Actor player) : RoleMeleeUtility(manager, player) { - public enum Track { ShadeShift = SharedTrack.Count } + public enum Track { ShadeShift = SharedTrack.Count, Shukuchi } + public enum DashStrategy { None, GapClose, GapCloseHold1 } public static readonly ActionID IDLimitBreak3 = ActionID.MakeSpell(NIN.AID.Chimatsuri); @@ -13,6 +14,12 @@ public static RotationModuleDefinition Definition() DefineSimpleConfig(res, Track.ShadeShift, "Shade", "", 400, NIN.AID.ShadeShift, 20); + res.Define(Track.Shukuchi).As("Shukuchi", "Dash", 20) + .AddOption(DashStrategy.None, "Automatic", "No use.") + .AddOption(DashStrategy.GapClose, "GapClose", "Use Shukuchi as gapcloser if outside melee range of any target; will dash to target selected via CDPlanner. If none selected, will dash to current target or not at all if no target", 60, 0, ActionTargets.All, 40) + .AddOption(DashStrategy.GapCloseHold1, "GapCloseHold1", "Use Shukuchi as gapcloser if outside melee range; conserves 1 charge for manual usage", 60, 0, ActionTargets.All, 76) + .AddAssociatedActions(NIN.AID.Shukuchi); + return res; } @@ -20,5 +27,79 @@ public override void Execute(StrategyValues strategy, Actor? primaryTarget, floa { ExecuteShared(strategy, IDLimitBreak3, primaryTarget); ExecuteSimple(strategy.Option(Track.ShadeShift), NIN.AID.ShadeShift, Player); + + var dash = strategy.Option(Track.Shukuchi); + var dashTarget = ResolveTargetOverride(dash.Value) ?? primaryTarget; + var dashStrategy = strategy.Option(Track.Shukuchi).As(); + if (ShouldUseDash(dashStrategy, primaryTarget)) + QueueOGCD(NIN.AID.Shukuchi, dashTarget); + } + private bool ShouldUseDash(DashStrategy strategy, Actor? primaryTarget) => strategy switch + { + DashStrategy.None => false, + DashStrategy.GapClose => Player.DistanceToHitbox(primaryTarget) is > 3 and <= 20, + DashStrategy.GapCloseHold1 => Player.DistanceToHitbox(primaryTarget) is > 3 and <= 20 && World.Client.Cooldowns[ActionDefinitions.Instance.Spell(DRG.AID.WingedGlide)!.MainCooldownGroup].Remaining <= 59.9f, + _ => false, + }; + + #region Core Execution Helpers + + public NIN.AID NextGCD; //Next global cooldown action to be used + public void QueueGCD

(NIN.AID aid, Actor? target, P priority, float delay = 0) where P : Enum + => QueueGCD(aid, target, (int)(object)priority, delay); + + public void QueueGCD(NIN.AID aid, Actor? target, int priority = 8, float delay = 0) + { + var NextGCDPrio = 0; + + if (priority == 0) + return; + + if (QueueAction(aid, target, ActionQueue.Priority.High, delay) && priority > NextGCDPrio) + { + NextGCD = aid; + } + } + + public void QueueOGCD

(NIN.AID aid, Actor? target, P priority, float delay = 0) where P : Enum + => QueueOGCD(aid, target, (int)(object)priority, delay); + + public void QueueOGCD(NIN.AID aid, Actor? target, int priority = 4, float delay = 0) + { + if (priority == 0) + return; + + QueueAction(aid, target, ActionQueue.Priority.Medium + priority, delay); + } + + public bool QueueAction(NIN.AID aid, Actor? target, float priority, float delay) + { + if ((uint)(object)aid == 0) + return false; + + var def = ActionDefinitions.Instance.Spell(aid); + if (def == null) + return false; + + if (def.Range != 0 && target == null) + { + return false; + } + + Vector3 targetPos = default; + + if (def.AllowedTargets.HasFlag(ActionTargets.Area)) + { + if (def.Range == 0) + targetPos = Player.PosRot.XYZ(); + else if (target != null) + targetPos = target.PosRot.XYZ(); + } + + Hints.ActionsToExecute.Push(ActionID.MakeSpell(aid), target, priority, delay: delay, targetPos: targetPos); + return true; + } + #endregion + }