Skip to content

Commit

Permalink
Merge pull request #542 from FFXIV-CombatReborn/BEEG
Browse files Browse the repository at this point in the history
Refactor and enhance rotation logic across classes
  • Loading branch information
LTS-FFXIV authored Jan 7, 2025
2 parents be96abf + 30e29a9 commit 32fee27
Show file tree
Hide file tree
Showing 18 changed files with 1,048 additions and 232 deletions.
2 changes: 0 additions & 2 deletions BasicRotations/Healer/AST_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,6 @@ protected override bool GeneralGCD(out IAction? act)
}
#endregion



#region Extra Methods
public override bool CanHealSingleSpell => base.CanHealSingleSpell && (GCDHeal || PartyMembers.GetJobCategory(JobRole.Healer).Count() < 2);
public override bool CanHealAreaSpell => base.CanHealAreaSpell && (GCDHeal || PartyMembers.GetJobCategory(JobRole.Healer).Count() < 2);
Expand Down
8 changes: 8 additions & 0 deletions BasicRotations/Magical/SMN_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public enum SummonOrderType : byte
[RotationConfig(CombatType.PvE, Name = "Use Swiftcast on Garuda")]
public bool AddSwiftcastOnGaruda { get; set; } = false;

[RotationConfig(CombatType.PvE, Name = "Use Swiftcast on Ruby Rite if you are not high enough level for Garuda")]
public bool AddSwiftcastOnRuby { get; set; } = false;

[RotationConfig(CombatType.PvE, Name = "Order")]
public SummonOrderType SummonOrder { get; set; } = SummonOrderType.TopazEmeraldRuby;

Expand Down Expand Up @@ -148,6 +151,11 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
if (SwiftcastPvE.CanUse(out act)) return true;
}

if (AddSwiftcastOnRuby && nextGCD == RubyRitePvE && Player.Level < 86)
{
if (SwiftcastPvE.CanUse(out act)) return true;
}

if ((RadiantOnCooldown && RadiantAegisPvE.Cooldown.CurrentCharges == 2 || RadiantAegisPvE.Cooldown.CurrentCharges == 1 && RadiantAegisPvE.Cooldown.WillHaveOneCharge(5)) && (anyBigInvocationIsCoolingDown && Player.Level <= 100) && RadiantAegisPvE.CanUse(out act)) return true;
if (RadiantOnCooldown && Player.Level < 88 && anyBigInvocationIsCoolingDown && RadiantAegisPvE.CanUse(out act)) return true;

Expand Down
76 changes: 53 additions & 23 deletions BasicRotations/Melee/NIN_Default.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Dalamud.Interface.Colors;

namespace DefaultRotations.Melee;

[Rotation("Default", CombatType.PvE, GameVersion = "7.15")]
Expand Down Expand Up @@ -82,9 +84,18 @@ private bool ChoiceNinjutsu(out IAction? act)
{
act = null;

if (!JinPvE.CanUse(out _) || !ChiPvE.CanUse(out _) || !TenPvE.CanUse(out _)) return false;
// If the last action performed matches any of a list of specific actions, it clears the Ninjutsu aim.
// This serves as a reset/cleanup mechanism to ensure the decision logic starts fresh for the next cycle.
if (IsLastAction(true, DotonPvE, SuitonPvE,
RabbitMediumPvE, FumaShurikenPvE, KatonPvE, RaitonPvE,
HyotonPvE, HutonPvE, DotonPvE, SuitonPvE, GokaMekkyakuPvE, HyoshoRanryuPvE))
{
ClearNinjutsu();
}

if ((!JinPvE.CanUse(out _) && JinPvE.EnoughLevel) || (!ChiPvE.CanUse(out _) && ChiPvE.EnoughLevel) || (!TenPvE.CanUse(out _) && TenPvE.EnoughLevel)) return false;
// Ensures that the action ID currently considered for Ninjutsu is actually valid for Ninjutsu execution.
if (AdjustId(ActionID.NinjutsuPvE) != ActionID.NinjutsuPvE) return false;
//if (AdjustId(ActionID.NinjutsuPvE) != ActionID.NinjutsuPvE) return false;
// If more than 4.5 seconds have passed since the last action, it clears any pending Ninjutsu to avoid stale actions.
if (TimeSinceLastAction.TotalSeconds > 4.5) ClearNinjutsu();

Expand All @@ -93,30 +104,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.CanUse(out _) && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
if (GokaMekkyakuPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
{
SetNinjutsu(GokaMekkyakuPvE);
return false;
}
if (HyoshoRanryuPvE.CanUse(out _) && TenPvE.CanUse(out _) && JinPvE.CanUse(out _))
if (HyoshoRanryuPvE.EnoughLevel && TenPvE.CanUse(out _) && JinPvE.CanUse(out _))
{
SetNinjutsu(HyoshoRanryuPvE);
return false;
}

if (HutonPvE.CanUse(out _) && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _))
if (HutonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _))
{
SetNinjutsu(HutonPvE);
return false;
}

if (KatonPvE.CanUse(out _) && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
if (KatonPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
{
SetNinjutsu(KatonPvE);
return false;
}

if (RaitonPvE.CanUse(out _) && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _))
if (RaitonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _))
{
SetNinjutsu(RaitonPvE);
return false;
Expand All @@ -137,46 +148,36 @@ private bool ChoiceNinjutsu(out IAction? act)
// Also considers using Suiton for vulnerability debuff on the enemy if conditions are optimal.

//Aoe
if (KatonPvE.CanUse(out _) && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
if (NumberOfHostilesInRange > 1 && KatonPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
{
if (!Player.HasStatus(true, StatusID.Doton) && !IsMoving && !IsLastGCD(false, DotonPvE) && (!TenChiJinPvE.Cooldown.WillHaveOneCharge(6)) || !Player.HasStatus(true, StatusID.Doton) && !TenChiJinPvE.Cooldown.IsCoolingDown && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _))
SetNinjutsu(DotonPvE);
else SetNinjutsu(KatonPvE);
return false;
}

//Single
if (!ShadowWalkerNeeded && TenPvE.CanUse(out _, usedUp: InTrickAttack && !Player.HasStatus(false, StatusID.RaijuReady)))
{
if (RaitonPvE.CanUse(out _) && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _))
if (RaitonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _))
{
SetNinjutsu(RaitonPvE);
return false;
}

if (!ChiPvE.EnoughLevel && FumaShurikenPvE.CanUse(out _))
if (!ChiPvE.EnoughLevel && FumaShurikenPvE.EnoughLevel)
{
SetNinjutsu(FumaShurikenPvE);
return false;
}
}

//Vulnerable
if (ShadowWalkerNeeded && !Player.HasStatus(true, StatusID.TenChiJin) && SuitonPvE.CanUse(out _, skipStatusProvideCheck: false) && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _))
if (ShadowWalkerNeeded && (!MeisuiPvE.Cooldown.IsCoolingDown || !TrickAttackPvE.Cooldown.IsCoolingDown || KunaisBanePvE.Cooldown.IsCoolingDown) && !Player.HasStatus(true, StatusID.ShadowWalker) && !Player.HasStatus(true, StatusID.TenChiJin) && SuitonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _))
{
SetNinjutsu(SuitonPvE);
return false;
}
}

// If the last action performed matches any of a list of specific actions, it clears the Ninjutsu aim.
// This serves as a reset/cleanup mechanism to ensure the decision logic starts fresh for the next cycle.
if (IsLastAction(false, DotonPvE, SuitonPvE,
RabbitMediumPvE, FumaShurikenPvE, KatonPvE, RaitonPvE,
HyotonPvE, HutonPvE, DotonPvE, SuitonPvE, GokaMekkyakuPvE, HyoshoRanryuPvE))
{
ClearNinjutsu();
}
return false; // Indicates that no specific Ninjutsu action was chosen in this cycle.
}
#endregion
Expand All @@ -199,7 +200,7 @@ private bool DoNinjutsu(out IAction? act)
&& !IsLastAction(false, FumaShurikenPvE_18875, FumaShurikenPvE_18873))
{
//AOE
if (KatonPvE.CanUse(out _))
if (KatonPvE.EnoughLevel)
{
if (FumaShurikenPvE_18875.CanUse(out act)) return true;
}
Expand Down Expand Up @@ -322,6 +323,7 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)

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

if (TenriJindoPvE.CanUse(out act)) return true;

Expand Down Expand Up @@ -352,7 +354,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)

// If the player is within Trick Attack's effective window, and Ten Chi Jin hasn't recently been used,
// then Ten Chi Jin is set as the next action to perform.
if (InTrickAttack && !TenPvE.Cooldown.ElapsedAfter(30) && TenChiJinPvE.CanUse(out act)) return true;
if (InTrickAttack && !Player.HasStatus(true, StatusID.ShadowWalker) && !TenPvE.Cooldown.ElapsedAfter(30) && TenChiJinPvE.CanUse(out act)) return true;

// If more than 5 seconds have passed in combat, checks if Bunshin is available to use.
if (!CombatElapsedLess(5) && BunshinPvE.CanUse(out act)) return true;
Expand Down Expand Up @@ -402,6 +404,8 @@ protected override bool GeneralGCD(out IAction? act)

var hasRaijuReady = Player.HasStatus(true, StatusID.RaijuReady);

if (RabbitMediumPvE.CanUse(out act)) return true;

if ((InTrickAttack || InMug) && NoNinjutsu && !hasRaijuReady
&& !Player.HasStatus(true, StatusID.TenChiJin)
&& PhantomKamaitachiPvE.CanUse(out act)) return true;
Expand Down Expand Up @@ -451,5 +455,31 @@ protected override bool GeneralGCD(out IAction? act)
#region Extra Methods
// Holds the next ninjutsu action to perform.
private IBaseAction? _ninActionAim = null;

public override void DisplayStatus()
{
ImGui.Text($"Ninjutsu Action: {_ninActionAim}");
ImGui.Text($"Ninki: {Ninki}");
ImGui.Text($"Kazematoi: {Kazematoi}");
ImGui.Text($"HasJin: {HasJin}");
ImGui.Text($"InTrickAttack: {InTrickAttack}");
ImGui.Text($"InMug: {InMug}");
ImGui.Text($"NoNinjutsu: {NoNinjutsu}");
ImGui.Text($"RaijuStacks: {RaijuStacks}");
ImGui.Text($"ShadowWalkerNeeded: {ShadowWalkerNeeded}");
ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
ImGui.Text("FumaShurikenPvEReady: " + FumaShurikenPvEReady.ToString());
ImGui.Text("KatonPvEReady: " + KatonPvEReady.ToString());
ImGui.Text("RaitonPvEReady: " + RaitonPvEReady.ToString());
ImGui.Text("HyotonPvEReady: " + HyotonPvEReady.ToString());
ImGui.Text("HutonPvEReady: " + HutonPvEReady.ToString());
ImGui.Text("DotonPvEReady: " + DotonPvEReady.ToString());
ImGui.Text("SuitonPvEReady: " + SuitonPvEReady.ToString());
ImGui.Text("GokaMekkyakuPvEReady: " + GokaMekkyakuPvEReady.ToString());
ImGui.Text("HyoshoRanryuPvEReady: " + HyoshoRanryuPvEReady.ToString());
ImGui.Text("DeathfrogMediumPvEReady: " + DeathfrogMediumPvEReady.ToString());
ImGui.Text("ZeshoMeppoPvEReady: " + ZeshoMeppoPvEReady.ToString());
ImGui.Text("TenriJindoPvEReady: " + TenriJindoPvEReady.ToString());
}
#endregion
}
11 changes: 6 additions & 5 deletions BasicRotations/PVPRotations/Tank/GNB_Default.PVP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
act = null;
if (GuardCancel && Player.HasStatus(true, StatusID.Guard)) return false;

if (HypervelocityPvP.CanUse(out act)) return true;
if (JugularRipPvP.CanUse(out act)) return true;
if (AbdomenTearPvE.CanUse(out act, usedUp: true)) return true;
if (AbdomenTearPvP.CanUse(out act)) return true;
if (EyeGougePvP.CanUse(out act)) return true;
if (FatedBrandPvP.CanUse(out act, usedUp: true)) return true;
if (FatedBrandPvP.CanUse(out act)) return true;

if (BlastingZonePvP.CanUse(out act)) return true;
if (RoughDividePvP.CanUse(out act, usedUp: true)) return true;
Expand All @@ -120,11 +121,11 @@ protected override bool GeneralGCD(out IAction? act)
if (GuardCancel && Player.HasStatus(true, StatusID.Guard)) return false;
if (!Player.HasStatus(true, StatusID.Guard) && UseSprintPvP && !Player.HasStatus(true, StatusID.Sprint) && !InCombat && SprintPvP.CanUse(out act)) return true;

if (!JugularRipPvPReady && !AbdomenTearPvPReady && !EyeGougePvPReady && !FatedBrandPvPReady
if (!JugularRipPvPReady && !AbdomenTearPvPReady && !EyeGougePvPReady && !FatedBrandPvPReady && !HypervelocityPvPReady
&& FatedCirclePvP.CanUse(out act)) return true;

if (WickedTalonPvE.CanUse(out act, usedUp: true)) return true;
if (SavageClawPvP.CanUse(out act, usedUp: true)) return true;
if (WickedTalonPvP.CanUse(out act)) return true;
if (SavageClawPvP.CanUse(out act)) return true;
if (GnashingFangPvP.CanUse(out act, usedUp: true)) return true;

if (!SavageClawPvPReady && !WickedTalonPvPReady)
Expand Down
2 changes: 1 addition & 1 deletion BasicRotations/Tank/DRK_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
#region GCD Logic
protected override bool GeneralGCD(out IAction? act)
{
if (DisesteemPvE.CanUse(out act)) return true;
if (DisesteemPvE.CanUse(out act, skipComboCheck: true, skipAoeCheck: true)) return true;

//AOE Delirium
if (ImpalementPvE.CanUse(out act)) return true;
Expand Down
Loading

0 comments on commit 32fee27

Please sign in to comment.