From 30e29a9b67e0ab4619eda787239fb5d41264d7fc Mon Sep 17 00:00:00 2001
From: LTS-FFXIV <127939494+LTS-FFXIV@users.noreply.github.com>
Date: Tue, 7 Jan 2025 17:41:17 -0600
Subject: [PATCH] Refactor and enhance rotation logic across classes
Refactored rotation logic in multiple classes to improve readability, consistency, and performance. Key changes include:
- `AST_Default.cs`: Added healer count condition to healing methods.
- `SMN_Default.cs`: Added `AddSwiftcastOnRuby` config and logic for Swiftcast.
- `NIN_Default.cs`: Added `Dalamud.Interface.Colors` usage, new methods, and improved action handling.
- `GNB_Default.PVP.cs`: Added `HypervelocityPvP` check and removed `usedUp` parameter.
- `DRK_Default.cs`: Updated `GeneralGCD` to allow `DisesteemPvE` usage.
- Introduced `NoMercyLogic` and `InBurstStatus` in `GNB_Default`.
- Added new action checks and debug displays in various rotation classes.
- Refactored `GunbreakerRotation`, `MachinistRotation`, and `MonkRotation` classes with new properties and methods for PvE action readiness.
- Updated `NinjaRotation` with new readiness properties and debug information.
- Introduced new `GNB_Beta` class with specialized logic and attributes.
---
BasicRotations/Healer/AST_Default.cs | 2 -
BasicRotations/Magical/SMN_Default.cs | 8 +
BasicRotations/Melee/NIN_Default.cs | 76 +++--
.../PVPRotations/Tank/GNB_Default.PVP.cs | 11 +-
BasicRotations/Tank/DRK_Default.cs | 2 +-
BasicRotations/Tank/GNB_Beta.cs | 266 ++++++++++++++++
BasicRotations/Tank/GNB_Default.cs | 91 +++---
RotationSolver.Basic/Configuration/Configs.cs | 2 +-
.../Rotations/Basic/BardRotation.cs | 17 +-
.../Rotations/Basic/BlackMageRotation.cs | 14 +-
.../Rotations/Basic/DancerRotation.cs | 57 +++-
.../Rotations/Basic/DarkKnightRotation.cs | 50 +--
.../Rotations/Basic/DragoonRotation.cs | 45 ++-
.../Rotations/Basic/GunbreakerRotation.cs | 141 ++++++---
.../Rotations/Basic/MachinistRotation.cs | 27 +-
.../Rotations/Basic/MonkRotation.cs | 66 +++-
.../Rotations/Basic/NinjaRotation.cs | 118 ++++++-
.../Rotations/Basic/ReaperRotation.cs | 287 +++++++++++++-----
18 files changed, 1048 insertions(+), 232 deletions(-)
create mode 100644 BasicRotations/Tank/GNB_Beta.cs
diff --git a/BasicRotations/Healer/AST_Default.cs b/BasicRotations/Healer/AST_Default.cs
index 7c6c980e3..d856a9d1f 100644
--- a/BasicRotations/Healer/AST_Default.cs
+++ b/BasicRotations/Healer/AST_Default.cs
@@ -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);
diff --git a/BasicRotations/Magical/SMN_Default.cs b/BasicRotations/Magical/SMN_Default.cs
index a8abac873..4be3409f2 100644
--- a/BasicRotations/Magical/SMN_Default.cs
+++ b/BasicRotations/Magical/SMN_Default.cs
@@ -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;
@@ -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;
diff --git a/BasicRotations/Melee/NIN_Default.cs b/BasicRotations/Melee/NIN_Default.cs
index 6214c6f5a..16eaea9fe 100644
--- a/BasicRotations/Melee/NIN_Default.cs
+++ b/BasicRotations/Melee/NIN_Default.cs
@@ -1,3 +1,5 @@
+using Dalamud.Interface.Colors;
+
namespace DefaultRotations.Melee;
[Rotation("Default", CombatType.PvE, GameVersion = "7.15")]
@@ -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();
@@ -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;
@@ -137,24 +148,23 @@ 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;
@@ -162,21 +172,12 @@ private bool ChoiceNinjutsu(out IAction? act)
}
//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
@@ -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;
}
@@ -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;
@@ -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;
@@ -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;
@@ -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
}
diff --git a/BasicRotations/PVPRotations/Tank/GNB_Default.PVP.cs b/BasicRotations/PVPRotations/Tank/GNB_Default.PVP.cs
index 1a7d52cc6..e930f8b10 100644
--- a/BasicRotations/PVPRotations/Tank/GNB_Default.PVP.cs
+++ b/BasicRotations/PVPRotations/Tank/GNB_Default.PVP.cs
@@ -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;
@@ -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)
diff --git a/BasicRotations/Tank/DRK_Default.cs b/BasicRotations/Tank/DRK_Default.cs
index 1358e9a88..0ca8fd434 100644
--- a/BasicRotations/Tank/DRK_Default.cs
+++ b/BasicRotations/Tank/DRK_Default.cs
@@ -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;
diff --git a/BasicRotations/Tank/GNB_Beta.cs b/BasicRotations/Tank/GNB_Beta.cs
new file mode 100644
index 000000000..18da7a1d2
--- /dev/null
+++ b/BasicRotations/Tank/GNB_Beta.cs
@@ -0,0 +1,266 @@
+namespace DefaultRotations.Tank;
+
+[Rotation("Beta", CombatType.PvE, GameVersion = "7.15")]
+[SourceCode(Path = "main/BasicRotations/Tank/GNB_Beta.cs")]
+[Api(4)]
+public sealed class GNB_Beta : GunbreakerRotation
+{
+ #region Countdown Logic
+
+ protected override IAction? CountDownAction(float remainTime)
+ {
+ if (remainTime <= 0.7 && LightningShotPvE.CanUse(out var act)) return act;
+ if (remainTime <= 1.2 && UseBurstMedicine(out act)) return act;
+ return base.CountDownAction(remainTime);
+ }
+ #endregion
+
+ #region Additional oGCD Logic
+
+ [RotationDesc]
+ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
+ {
+ // Attempt to align Bloodfest with No Mercy during opener
+ if (InCombat && CombatElapsedLess(30))
+ {
+ if (!CombatElapsedLessGCD(2) && NoMercyPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (Player.HasStatus(true, StatusID.NoMercy) && BloodfestPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ }
+
+ return base.EmergencyAbility(nextGCD, out act);
+ }
+
+ [RotationDesc(ActionID.TrajectoryPvE)]
+ protected override bool MoveForwardAbility(IAction nextGCD, out IAction? act)
+ {
+ if (TrajectoryPvE.CanUse(out act)) return true;
+ return base.MoveForwardAbility(nextGCD, out act);
+ }
+
+ [RotationDesc(ActionID.HeartOfLightPvE, ActionID.ReprisalPvE)]
+ protected sealed override bool DefenseAreaAbility(IAction nextGCD, out IAction? act)
+ {
+ if (!Player.HasStatus(true, StatusID.NoMercy) && HeartOfLightPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (!Player.HasStatus(true, StatusID.NoMercy) && ReprisalPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ return base.DefenseAreaAbility(nextGCD, out act);
+ }
+
+ [RotationDesc(ActionID.HeartOfStonePvE, ActionID.NebulaPvE, ActionID.RampartPvE, ActionID.CamouflagePvE, ActionID.ReprisalPvE)]
+ protected override bool DefenseSingleAbility(IAction nextGCD, out IAction? act)
+ {
+ //10
+ if (CamouflagePvE.CanUse(out act)) return true;
+ //15
+ if (HeartOfStonePvE.CanUse(out act)) return true;
+
+ //30
+ if ((!RampartPvE.Cooldown.IsCoolingDown || RampartPvE.Cooldown.ElapsedAfter(60)) && NebulaPvE.CanUse(out act)) return true;
+ //20
+ if (NebulaPvE.Cooldown.IsCoolingDown && NebulaPvE.Cooldown.ElapsedAfter(60) && RampartPvE.CanUse(out act)) return true;
+
+ if (ReprisalPvE.CanUse(out act)) return true;
+
+ return base.DefenseSingleAbility(nextGCD, out act);
+ }
+
+ [RotationDesc(ActionID.AuroraPvE)]
+ protected override bool HealSingleAbility(IAction nextGCD, out IAction? act)
+ {
+ if (AuroraPvE.CanUse(out act, usedUp: true)) return true;
+ return base.HealSingleAbility(nextGCD, out act);
+ }
+ #endregion
+
+ #region oGCD Logic
+
+ protected override bool GeneralAbility(IAction nextGCD, out IAction? act)
+ {
+ if (!CombatElapsedLessGCD(5) && NoMercyPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ return base.GeneralAbility(nextGCD, out act);
+ }
+
+ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
+ {
+ //if (IsBurst && CanUseNoMercy(out act)) return true;
+
+ if (!CombatElapsedLessGCD(5) && NoMercyPvE.CanUse(out act, skipAoeCheck: true)) return true;
+
+ if (JugularRipPvE.CanUse(out act)) return true;
+
+ if (DangerZonePvE.CanUse(out act) && !DoubleDownPvE.EnoughLevel)
+ {
+
+ if (!IsFullParty && !(DangerZonePvE.Target.Target?.IsBossFromTTK() ?? false)) return true;
+
+ if (!GnashingFangPvE.EnoughLevel && (Player.HasStatus(true, StatusID.NoMercy) || !NoMercyPvE.Cooldown.WillHaveOneCharge(15))) return true;
+
+ if (Player.HasStatus(true, StatusID.NoMercy) && GnashingFangPvE.Cooldown.IsCoolingDown) return true;
+
+ if (!Player.HasStatus(true, StatusID.NoMercy) && !GnashingFangPvE.Cooldown.WillHaveOneCharge(20)) return true;
+ }
+
+ if (Player.HasStatus(true, StatusID.NoMercy) && CanUseBowShock(out act)) return true;
+
+ //if (TrajectoryPvE.CanUse(out act) && !IsMoving) return true;
+ if (GnashingFangPvE.Cooldown.IsCoolingDown && DoubleDownPvE.Cooldown.IsCoolingDown && Ammo == 0 && BloodfestPvE.CanUse(out act)) return true;
+
+ if (AbdomenTearPvE.CanUse(out act)) return true;
+ if (EyeGougePvE.CanUse(out act)) return true;
+ if (FatedBrandPvE.CanUse(out act)) return true;
+ if (HypervelocityPvE.CanUse(out act)) return true;
+ return base.AttackAbility(nextGCD, out act);
+ }
+ #endregion
+
+ #region GCD Logic
+
+ protected override bool GeneralGCD(out IAction? act)
+ {
+ bool areDDTargetsInRange = AllHostileTargets.Any(hostile => hostile.DistanceToPlayer() < 4.5f);
+
+ if (Player.HasStatus(true, StatusID.NoMercy) && BloodfestPvE.CanUse(out act)) return true;
+
+ if (IsLastGCD(false, NobleBloodPvE) && LionHeartPvE.CanUse(out act, skipComboCheck: true)) return true;
+ if (IsLastGCD(false, ReignOfBeastsPvE) && NobleBloodPvE.CanUse(out act, skipComboCheck: true)) return true;
+ if (ReignOfBeastsPvE.CanUse(out act, skipAoeCheck: true)) return true;
+
+ if (Player.HasStatus(true, StatusID.NoMercy) && SonicBreakPvE.CanUse(out act)) return true;
+
+ if (areDDTargetsInRange)
+ {
+ if (Player.HasStatus(true, StatusID.NoMercy) && CanUseDoubleDown(out act)) return true;
+ if (Player.HasStatus(true, StatusID.NoMercy) && IsLastGCD(ActionID.DoubleDownPvE) && BlastingZonePvE.CanUse(out act)) return true;
+ }
+
+ if (NoMercyPvE.Cooldown.IsCoolingDown && BloodfestPvE.Cooldown.IsCoolingDown && BlastingZonePvE.CanUse(out act)) return true;
+
+ if (CanUseGnashingFang(out act)) return true;
+
+ if (SavageClawPvE.CanUse(out act, skipComboCheck: true)) return true;
+ if (WickedTalonPvE.CanUse(out act, skipComboCheck: true)) return true;
+
+ if (CanUseBurstStrike(out act)) return true;
+
+ if (FatedCirclePvE.CanUse(out act)) return true;
+ if (DemonSlaughterPvE.CanUse(out act)) return true;
+ if (DemonSlicePvE.CanUse(out act)) return true;
+
+ if (Ammo == MaxAmmo && IsLastGCD(ActionID.BrutalShellPvE) && BurstStrikePvE.CanUse(out act)) return true;
+
+ if (SolidBarrelPvE.CanUse(out act)) return true;
+ if (BrutalShellPvE.CanUse(out act)) return true;
+ if (KeenEdgePvE.CanUse(out act)) return true;
+
+ if (LightningShotPvE.CanUse(out act)) return true;
+
+ return base.GeneralGCD(out act);
+ }
+
+ #endregion
+
+ #region Extra Methods
+ public override bool CanHealSingleSpell => false;
+
+ public override bool CanHealAreaSpell => false;
+
+ //private bool CanUseNoMercy(out IAction act)
+ //{
+ // if (!NoMercy.CanUse(out act, CanUseOption.OnLastAbility)) return false;
+
+ // if (!IsFullParty && !IsTargetBoss && !IsMoving && DemonSlice.CanUse(out _)) return true;
+
+ // if (!BurstStrike.EnoughLevel) return true;
+
+ // if (BurstStrike.EnoughLevel)
+ // {
+ // if (IsLastGCD((ActionID)KeenEdge.ID) && Ammo == 1 && !GnashingFang.IsCoolingDown && !BloodFest.IsCoolingDown) return true;
+ // else if (Ammo == (Level >= 88 ? 3 : 2)) return true;
+ // else if (Ammo == 2 && GnashingFang.IsCoolingDown) return true;
+ // }
+
+ // act = null;
+ // return false;
+ //}
+
+ private bool CanUseGnashingFang(out IAction? act)
+ {
+ if (GnashingFangPvE.CanUse(out act))
+ {
+ //AOE Check: Mobs = NO, Boss = YES
+ if (DemonSlicePvE.CanUse(out _)) return false;
+
+ if (Player.HasStatus(true, StatusID.NoMercy) || !NoMercyPvE.Cooldown.WillHaveOneCharge(55)) return true;
+
+ if (Ammo > 0 && !NoMercyPvE.Cooldown.WillHaveOneCharge(17) && NoMercyPvE.Cooldown.WillHaveOneCharge(35)) return true;
+
+ if (Ammo <= 3 && IsLastGCD((ActionID)BrutalShellPvE.ID) && NoMercyPvE.Cooldown.WillHaveOneCharge(3)) return true;
+
+ if (Ammo == 1 && !NoMercyPvE.Cooldown.WillHaveOneCharge(55) && BloodfestPvE.Cooldown.WillHaveOneCharge(5)) return true;
+
+ if (Ammo == 1 && !NoMercyPvE.Cooldown.WillHaveOneCharge(55) && (!BloodfestPvE.Cooldown.IsCoolingDown && BloodfestPvE.EnoughLevel || !BloodfestPvE.EnoughLevel)) return true;
+ }
+ return false;
+ }
+
+ /*private bool CanUseSonicBreak(out IAction act)
+ {
+ if (SonicBreakPvE.CanUse(out act))
+ {
+
+ if (!GnashingFangPvE.EnoughLevel && Player.HasStatus(true, StatusID.NoMercy)) return true;
+
+ if (!DoubleDownPvE.EnoughLevel && Player.HasStatus(true, StatusID.ReadyToRip)
+ && GnashingFangPvE.Cooldown.IsCoolingDown) return true;
+
+ }
+ return false;
+ }*/
+
+ private bool CanUseDoubleDown(out IAction? act)
+ {
+ if (DoubleDownPvE.CanUse(out act, skipAoeCheck: true))
+ {
+ if (SonicBreakPvE.Cooldown.IsCoolingDown && Player.HasStatus(true, StatusID.NoMercy)) return true;
+ if (Player.HasStatus(true, StatusID.NoMercy) && !NoMercyPvE.Cooldown.WillHaveOneCharge(55) && BloodfestPvE.Cooldown.WillHaveOneCharge(5)) return true;
+
+ }
+ return false;
+ }
+
+ private bool CanUseBurstStrike(out IAction act)
+ {
+ if (BurstStrikePvE.CanUse(out act))
+ {
+ if (DemonSlicePvE.CanUse(out _)) return false;
+
+ if (SonicBreakPvE.Cooldown.IsCoolingDown && SonicBreakPvE.Cooldown.WillHaveOneCharge(0.5f) && GnashingFangPvE.EnoughLevel) return false;
+
+ if (Player.HasStatus(true, StatusID.NoMercy) &&
+ AmmoComboStep == 0 &&
+ !GnashingFangPvE.Cooldown.WillHaveOneCharge(1)) return true;
+
+ if (!CartridgeChargeIiTrait.EnoughLevel && Ammo == 2) return true;
+
+ if (IsLastGCD((ActionID)BrutalShellPvE.ID) &&
+ (Ammo == MaxAmmo ||
+ BloodfestPvE.Cooldown.WillHaveOneCharge(6) && Ammo <= 2 && !NoMercyPvE.Cooldown.WillHaveOneCharge(10) && BloodfestPvE.EnoughLevel)) return true;
+
+ }
+ return false;
+ }
+
+ private bool CanUseBowShock(out IAction act)
+ {
+ if (BowShockPvE.CanUse(out act, skipAoeCheck: true))
+ {
+ //AOE CHECK
+ if (DemonSlicePvE.CanUse(out _) && !IsFullParty) return true;
+
+ if (!SonicBreakPvE.EnoughLevel && Player.HasStatus(true, StatusID.NoMercy)) return true;
+
+ if (Player.HasStatus(true, StatusID.NoMercy) && SonicBreakPvE.Cooldown.IsCoolingDown) return true;
+ }
+ return false;
+ }
+ #endregion
+}
diff --git a/BasicRotations/Tank/GNB_Default.cs b/BasicRotations/Tank/GNB_Default.cs
index ff131f879..10808a516 100644
--- a/BasicRotations/Tank/GNB_Default.cs
+++ b/BasicRotations/Tank/GNB_Default.cs
@@ -5,6 +5,13 @@ namespace DefaultRotations.Tank;
[Api(4)]
public sealed class GNB_Default : GunbreakerRotation
{
+ #region Config Options
+ [RotationConfig(CombatType.PvE, Name = "Use experimental No Mercy logic for burst")]
+ public bool NoMercyLogic { get; set; } = false;
+ #endregion
+
+ private static bool InBurstStatus => !Player.WillStatusEnd(0, true, StatusID.NoMercy);
+
#region Countdown Logic
protected override IAction? CountDownAction(float remainTime)
{
@@ -22,17 +29,22 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
if (InCombat && CombatElapsedLess(30))
{
if (!CombatElapsedLessGCD(2) && NoMercyPvE.CanUse(out act, skipAoeCheck: true)) return true;
- if (Player.HasStatus(true, StatusID.NoMercy) && BloodfestPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (InBurstStatus && BloodfestPvE.CanUse(out act, skipAoeCheck: true)) return true;
}
+ if (AbdomenTearPvE.CanUse(out act)) return true;
+ if (EyeGougePvE.CanUse(out act)) return true;
+ if (FatedBrandPvE.CanUse(out act)) return true;
+ if (HypervelocityPvE.CanUse(out act)) return true;
+
return base.EmergencyAbility(nextGCD, out act);
}
[RotationDesc(ActionID.HeartOfLightPvE, ActionID.ReprisalPvE)]
protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act)
{
- if (!Player.HasStatus(true, StatusID.NoMercy) && HeartOfLightPvE.CanUse(out act, skipAoeCheck: true)) return true;
- if (!Player.HasStatus(true, StatusID.NoMercy) && ReprisalPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (!InBurstStatus && HeartOfLightPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (!InBurstStatus && ReprisalPvE.CanUse(out act, skipAoeCheck: true)) return true;
return base.DefenseAreaAbility(nextGCD, out act);
}
@@ -62,9 +74,9 @@ protected override bool HealSingleAbility(IAction nextGCD, out IAction? act)
}
protected override bool AttackAbility(IAction nextGCD, out IAction? act)
{
- //if (IsBurst && CanUseNoMercy(out act)) return true;
+ if (NoMercyLogic && IsBurst && CanUseNoMercy(out act)) return true;
- if (!CombatElapsedLessGCD(5) && NoMercyPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (!NoMercyLogic && !CombatElapsedLessGCD(5) && NoMercyPvE.CanUse(out act, skipAoeCheck: true)) return true;
if (JugularRipPvE.CanUse(out act)) return true;
@@ -73,23 +85,25 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
if (!IsFullParty && !(DangerZonePvE.Target.Target?.IsBossFromTTK() ?? false)) return true;
- if (!GnashingFangPvE.EnoughLevel && (Player.HasStatus(true, StatusID.NoMercy) || !NoMercyPvE.Cooldown.WillHaveOneCharge(15))) return true;
+ if (!GnashingFangPvE.EnoughLevel && (InBurstStatus || !NoMercyPvE.Cooldown.WillHaveOneCharge(15))) return true;
- if (Player.HasStatus(true, StatusID.NoMercy) && GnashingFangPvE.Cooldown.IsCoolingDown) return true;
+ if (InBurstStatus && GnashingFangPvE.Cooldown.IsCoolingDown) return true;
- if (!Player.HasStatus(true, StatusID.NoMercy) && !GnashingFangPvE.Cooldown.WillHaveOneCharge(20)) return true;
+ if (!InBurstStatus && !GnashingFangPvE.Cooldown.WillHaveOneCharge(20)) return true;
}
- if (Player.HasStatus(true, StatusID.NoMercy) && CanUseBowShock(out act)) return true;
+ if (InBurstStatus && CanUseBowShock(out act)) return true;
//if (TrajectoryPvE.CanUse(out act) && !IsMoving) return true;
if (GnashingFangPvE.Cooldown.IsCoolingDown && DoubleDownPvE.Cooldown.IsCoolingDown && Ammo == 0 && BloodfestPvE.CanUse(out act)) return true;
- if (AbdomenTearPvE.CanUse(out act)) return true;
- if (EyeGougePvE.CanUse(out act)) return true;
- if (FatedBrandPvE.CanUse(out act)) return true;
- if (HypervelocityPvE.CanUse(out act)) return true;
- if (MergedStatus.HasFlag(AutoStatus.MoveForward) && MoveForwardAbility(nextGCD, out act)) return true;
+ bool areDDTargetsInRange = AllHostileTargets.Any(hostile => hostile.DistanceToPlayer() < 4.5f);
+
+ if (areDDTargetsInRange)
+ {
+ if (InBurstStatus && IsLastGCD(ActionID.DoubleDownPvE) && BlastingZonePvE.CanUse(out act)) return true;
+ }
+ if (NoMercyPvE.Cooldown.IsCoolingDown && BloodfestPvE.Cooldown.IsCoolingDown && BlastingZonePvE.CanUse(out act)) return true;
return base.AttackAbility(nextGCD, out act);
}
#endregion
@@ -99,22 +113,19 @@ protected override bool GeneralGCD(out IAction? act)
{
bool areDDTargetsInRange = AllHostileTargets.Any(hostile => hostile.DistanceToPlayer() < 4.5f);
- if (Player.HasStatus(true, StatusID.NoMercy) && BloodfestPvE.CanUse(out act)) return true;
+ if (InBurstStatus && BloodfestPvE.CanUse(out act)) return true;
if (IsLastGCD(false, NobleBloodPvE) && LionHeartPvE.CanUse(out act, skipComboCheck: true)) return true;
if (IsLastGCD(false, ReignOfBeastsPvE) && NobleBloodPvE.CanUse(out act, skipComboCheck: true)) return true;
- if (ReignOfBeastsPvE.CanUse(out act, skipAoeCheck: true)) return true;
+ if (!InGnashingFang && ReignOfBeastsPvE.CanUse(out act, skipAoeCheck: true)) return true;
- if (Player.HasStatus(true, StatusID.NoMercy) && SonicBreakPvE.CanUse(out act)) return true;
+ if (InBurstStatus && SonicBreakPvE.CanUse(out act)) return true;
if (areDDTargetsInRange)
{
- if (Player.HasStatus(true, StatusID.NoMercy) && CanUseDoubleDown(out act)) return true;
- if (Player.HasStatus(true, StatusID.NoMercy) && IsLastGCD(ActionID.DoubleDownPvE) && BlastingZonePvE.CanUse(out act)) return true;
+ if (InBurstStatus && CanUseDoubleDown(out act)) return true;
}
- if (NoMercyPvE.Cooldown.IsCoolingDown && BloodfestPvE.Cooldown.IsCoolingDown && BlastingZonePvE.CanUse(out act)) return true;
-
if (CanUseGnashingFang(out act)) return true;
if (SavageClawPvE.CanUse(out act, skipComboCheck: true)) return true;
@@ -128,9 +139,12 @@ protected override bool GeneralGCD(out IAction? act)
if (Ammo == MaxAmmo && IsLastGCD(ActionID.BrutalShellPvE) && BurstStrikePvE.CanUse(out act)) return true;
- if (SolidBarrelPvE.CanUse(out act)) return true;
- if (BrutalShellPvE.CanUse(out act)) return true;
- if (KeenEdgePvE.CanUse(out act)) return true;
+ if (!InGnashingFang)
+ {
+ if (SolidBarrelPvE.CanUse(out act)) return true;
+ if (BrutalShellPvE.CanUse(out act)) return true;
+ if (KeenEdgePvE.CanUse(out act)) return true;
+ }
if (LightningShotPvE.CanUse(out act)) return true;
@@ -143,24 +157,25 @@ protected override bool GeneralGCD(out IAction? act)
public override bool CanHealAreaSpell => false;
- //private bool CanUseNoMercy(out IAction act)
- //{
- // if (!NoMercy.CanUse(out act, CanUseOption.OnLastAbility)) return false;
+ private bool CanUseNoMercy(out IAction act)
+ {
+ var IsTargetBoss = HostileTarget?.IsBossFromIcon() ?? false;
- // if (!IsFullParty && !IsTargetBoss && !IsMoving && DemonSlice.CanUse(out _)) return true;
+ if (!NoMercyPvE.CanUse(out act)) return false;
- // if (!BurstStrike.EnoughLevel) return true;
+ if (!IsFullParty && !IsTargetBoss && !IsMoving && DemonSlicePvE.CanUse(out _)) return true;
- // if (BurstStrike.EnoughLevel)
- // {
- // if (IsLastGCD((ActionID)KeenEdge.ID) && Ammo == 1 && !GnashingFang.IsCoolingDown && !BloodFest.IsCoolingDown) return true;
- // else if (Ammo == (Level >= 88 ? 3 : 2)) return true;
- // else if (Ammo == 2 && GnashingFang.IsCoolingDown) return true;
- // }
+ if (!BurstStrikePvE.EnoughLevel) return true;
- // act = null;
- // return false;
- //}
+ if (BurstStrikePvE.EnoughLevel)
+ {
+ if (IsLastGCD(ActionID.KeenEdgePvE) && Ammo == 1 && !GnashingFangPvE.Cooldown.IsCoolingDown && !BloodfestPvE.Cooldown.IsCoolingDown) return true;
+ else if (Ammo == MaxAmmo) return true;
+ else if (Ammo == 2 && GnashingFangPvE.Cooldown.IsCoolingDown) return true;
+ }
+
+ return false;
+ }
private bool CanUseGnashingFang(out IAction? act)
{
diff --git a/RotationSolver.Basic/Configuration/Configs.cs b/RotationSolver.Basic/Configuration/Configs.cs
index f7eb14c18..5b4a2b6a7 100644
--- a/RotationSolver.Basic/Configuration/Configs.cs
+++ b/RotationSolver.Basic/Configuration/Configs.cs
@@ -482,7 +482,7 @@ public const string
Filter = HealingActionCondition, Section = 3)]
private static readonly bool _friendlyBattleNPCHeal = false;
- [ConditionBool, UI("Heal and raise Party NPCs. (Breaks some fights due to status weirdness)", Description = "Experimental, only enable as needed.",
+ [ConditionBool, UI("Heal and raise Party NPCs.", Description = "Experimental, only enable as needed.",
Filter = HealingActionCondition, Section = 3)]
private static readonly bool _friendlyPartyNPCHealRaise2 = false;
diff --git a/RotationSolver.Basic/Rotations/Basic/BardRotation.cs b/RotationSolver.Basic/Rotations/Basic/BardRotation.cs
index 09fe0dfcd..8b33c710c 100644
--- a/RotationSolver.Basic/Rotations/Basic/BardRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/BardRotation.cs
@@ -1,3 +1,5 @@
+using Dalamud.Interface.Colors;
+
namespace RotationSolver.Basic.Rotations.Basic;
partial class BardRotation
@@ -52,6 +54,17 @@ partial class BardRotation
///
protected static bool SongEndAfterGCD(uint gctCount = 0, float offset = 0)
=> SongEndAfter(GCDTime(gctCount, offset));
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool BlastArrowPvEReady => Service.GetAdjustedActionId(ActionID.ApexArrowPvE) == ActionID.BlastArrowPvE;
+ #endregion
+
+ #region Draw Debug
///
public override void DisplayStatus()
@@ -64,6 +77,8 @@ public override void DisplayStatus()
ImGui.Text("SongTime: " + SongTime.ToString());
ImGui.Text("BloodletterMax: " + BloodletterMax.ToString());
ImGui.Text("Bloodlettercharges: " + BloodletterPvE.Cooldown.CurrentCharges.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("BlastArrowPvEReady: " + BlastArrowPvEReady.ToString());
}
#endregion
@@ -310,7 +325,7 @@ static partial void ModifyLadonsbitePvE(ref ActionSetting setting)
static partial void ModifyBlastArrowPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.BlastArrowReady];
+ setting.ActionCheck = () => BlastArrowPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
diff --git a/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs b/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs
index 5d717b9d5..4bc3f66dd 100644
--- a/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs
@@ -1,4 +1,6 @@
-namespace RotationSolver.Basic.Rotations.Basic;
+using Dalamud.Interface.Colors;
+
+namespace RotationSolver.Basic.Rotations.Basic;
partial class BlackMageRotation
{
@@ -164,6 +166,13 @@ public static bool IsPolyglotStacksMaxed
protected static bool HasThunder => Player.HasStatus(true, StatusID.Thunderhead);
#endregion
+ #region PvE Actions Unassignable
+ ///
+ ///
+ ///
+ public static bool ParadoxPvEReady => Service.GetAdjustedActionId(ActionID.FirePvE) == ActionID.ParadoxPvE;
+ #endregion
+
#region Debug
///
public override void DisplayStatus()
@@ -183,6 +192,9 @@ public override void DisplayStatus()
ImGui.Text("IsEnochianActive: " + IsEnochianActive.ToString());
ImGui.Text("EnochianTimeRaw: " + EnochianTimeRaw.ToString());
ImGui.Text("EnochianTime: " + EnochianTime.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("ParadoxPvEReady: " + ParadoxPvEReady.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudOrange, "PvP Actions");
ImGui.Text("HasPvPAstralFire: " + HasPvPAstralFire.ToString());
ImGui.Text("HasPvPUmbralIce: " + HasPvPUmbralIce.ToString());
}
diff --git a/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs b/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs
index c005040c2..be71a7437 100644
--- a/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs
@@ -1,4 +1,6 @@
-namespace RotationSolver.Basic.Rotations.Basic;
+using Dalamud.Interface.Colors;
+
+namespace RotationSolver.Basic.Rotations.Basic;
partial class DancerRotation
{
@@ -7,6 +9,7 @@ partial class DancerRotation
///
public override MedicineType MedicineType => MedicineType.Dexterity;
+ #region Job Gauge
///
///
///
@@ -26,6 +29,42 @@ partial class DancerRotation
///
///
public static byte CompletedSteps => JobGauge.CompletedSteps;
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool StandardFinishPvEReady => Service.GetAdjustedActionId(ActionID.StandardStepPvE) == ActionID.StandardFinishPvE;
+
+ ///
+ ///
+ ///
+ public static bool TechnicalFinishPvEReady => Service.GetAdjustedActionId(ActionID.TechnicalStepPvE) == ActionID.TechnicalFinishPvE;
+
+ ///
+ ///
+ ///
+ public static bool ImprovisedFinishPvEReady => Service.GetAdjustedActionId(ActionID.ImprovisationPvE) == ActionID.ImprovisedFinishPvE;
+
+ ///
+ ///
+ ///
+ public static bool TillanaPvEReady => Service.GetAdjustedActionId(ActionID.TechnicalStepPvE) == ActionID.TillanaPvE;
+
+ ///
+ ///
+ ///
+ public static bool FinishingMovePvEReady => Service.GetAdjustedActionId(ActionID.StandardStepPvE) == ActionID.FinishingMovePvE;
+
+ ///
+ ///
+ ///
+ public static bool DanceOfTheDawnPvEReady => Service.GetAdjustedActionId(ActionID.SaberDancePvE) == ActionID.DanceOfTheDawnPvE;
+ #endregion
+
+ #region Debug Status
///
public override void DisplayStatus()
@@ -34,7 +73,15 @@ public override void DisplayStatus()
ImGui.Text("Esprit: " + Esprit.ToString());
ImGui.Text("Feathers: " + Feathers.ToString());
ImGui.Text("CompletedSteps: " + CompletedSteps.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("StandardFinishPvEReady: " + StandardFinishPvEReady.ToString());
+ ImGui.Text("TechnicalFinishPvE: " + TechnicalFinishPvE.ToString());
+ ImGui.Text("ImprovisedFinishPvEReady: " + ImprovisedFinishPvEReady.ToString());
+ ImGui.Text("TillanaPvEReady: " + TillanaPvEReady.ToString());
+ ImGui.Text("FinishingMovePvEReady: " + FinishingMovePvEReady.ToString());
+ ImGui.Text("DanceOfTheDawnPvEReady: " + DanceOfTheDawnPvEReady.ToString());
}
+ #endregion
static partial void ModifyCascadePvE(ref ActionSetting setting)
{
@@ -182,8 +229,7 @@ static partial void ModifyStarfallDancePvE(ref ActionSetting setting)
static partial void ModifyTillanaPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Esprit <= 50;
- setting.StatusNeed = [StatusID.FlourishingFinish];
+ setting.ActionCheck = () => Esprit <= 50 && TillanaPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
@@ -292,7 +338,7 @@ static partial void ModifyLastDancePvE(ref ActionSetting setting)
static partial void ModifyFinishingMovePvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.FinishingMoveReady];
+ setting.ActionCheck = () => FinishingMovePvEReady;
setting.StatusProvide = [StatusID.LastDanceReady];
setting.CreateConfig = () => new ActionConfig()
{
@@ -303,8 +349,7 @@ static partial void ModifyFinishingMovePvE(ref ActionSetting setting)
static partial void ModifyDanceOfTheDawnPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Esprit >= 50;
- setting.StatusNeed = [StatusID.DanceOfTheDawnReady];
+ setting.ActionCheck = () => Esprit >= 50 && DanceOfTheDawnPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
diff --git a/RotationSolver.Basic/Rotations/Basic/DarkKnightRotation.cs b/RotationSolver.Basic/Rotations/Basic/DarkKnightRotation.cs
index 29b4b788a..481c3bdf3 100644
--- a/RotationSolver.Basic/Rotations/Basic/DarkKnightRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/DarkKnightRotation.cs
@@ -23,26 +23,6 @@ partial class DarkKnightRotation
///
public static bool HasDelirium => !Player.WillStatusEnd(0, true, StatusID.Delirium_3836);
- ///
- ///
- ///
- public static bool ScarletDeliriumReady => Service.GetAdjustedActionId(ActionID.BloodspillerPvE) == ActionID.ScarletDeliriumPvE;
-
- ///
- ///
- ///
- public static bool ComeuppanceReady => Service.GetAdjustedActionId(ActionID.BloodspillerPvE) == ActionID.ComeuppancePvE;
-
- ///
- ///
- ///
- public static bool TorcleaverReady => Service.GetAdjustedActionId(ActionID.BloodspillerPvE) == ActionID.TorcleaverPvE;
-
- ///
- ///
- ///
- public static bool ImpalementReady => Service.GetAdjustedActionId(ActionID.QuietusPvE) == ActionID.ImpalementPvE;
-
static float DarkSideTimeRemainingRaw => JobGauge.DarksideTimeRemaining / 1000f;
///
@@ -88,7 +68,9 @@ protected static bool DarkSideEndAfterGCD(uint gctCount = 0, float offset = 0)
///
protected static bool ShadowTimeEndAfterGCD(uint gctCount = 0, float offset = 0)
=> ShadowTimeEndAfter(GCDTime(gctCount, offset));
+ #endregion
+ #region Status Tracking
///
/// Holds the remaining amount of BloodWeapon stacks
///
@@ -124,6 +106,32 @@ public static byte LowDeliriumStacks
return stacks == byte.MaxValue ? (byte)3 : stacks;
}
}
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool ScarletDeliriumReady => Service.GetAdjustedActionId(ActionID.BloodspillerPvE) == ActionID.ScarletDeliriumPvE;
+
+ ///
+ ///
+ ///
+ public static bool ComeuppanceReady => Service.GetAdjustedActionId(ActionID.BloodspillerPvE) == ActionID.ComeuppancePvE;
+
+ ///
+ ///
+ ///
+ public static bool TorcleaverReady => Service.GetAdjustedActionId(ActionID.BloodspillerPvE) == ActionID.TorcleaverPvE;
+
+ ///
+ ///
+ ///
+ public static bool ImpalementReady => Service.GetAdjustedActionId(ActionID.QuietusPvE) == ActionID.ImpalementPvE;
+ #endregion
+
+ #region Draw Debug
///
public override void DisplayStatus()
@@ -143,6 +151,7 @@ public override void DisplayStatus()
}
#endregion
+ #region PvE Actions
static partial void ModifyHardSlashPvE(ref ActionSetting setting)
{
@@ -399,6 +408,7 @@ static partial void ModifyDisesteemPvE(ref ActionSetting setting)
AoeCount = 1,
};
}
+ #endregion
///
protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
diff --git a/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs b/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs
index 684a5351b..797164747 100644
--- a/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs
@@ -1,10 +1,13 @@
-namespace RotationSolver.Basic.Rotations.Basic;
+using Dalamud.Interface.Colors;
+
+namespace RotationSolver.Basic.Rotations.Basic;
partial class DragoonRotation
{
///
public override MedicineType MedicineType => MedicineType.Strength;
+ #region Job Gauge
///
///
///
@@ -40,6 +43,32 @@ partial class DragoonRotation
///
protected static bool LOTDEndAfterGCD(uint gctCount = 0, float offset = 0)
=> LOTDEndAfter(GCDTime(gctCount, offset));
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool DrakesbanePvEFangReady => Service.GetAdjustedActionId(ActionID.FangAndClawPvE) == ActionID.DrakesbanePvE;
+
+ ///
+ ///
+ ///
+ public static bool DrakesbanePvEWheelingReady => Service.GetAdjustedActionId(ActionID.WheelingThrustPvE) == ActionID.DrakesbanePvE;
+
+ ///
+ ///
+ ///
+ public static bool RaidenThrustPvEReady => Service.GetAdjustedActionId(ActionID.TrueThrustPvE) == ActionID.RaidenThrustPvE;
+
+ ///
+ ///
+ ///
+ public static bool DraconianFuryPvEReady => Service.GetAdjustedActionId(ActionID.DoomSpikePvE) == ActionID.DraconianFuryPvE;
+ #endregion
+
+ #region Draw Debug
///
public override void DisplayStatus()
@@ -48,9 +77,15 @@ public override void DisplayStatus()
ImGui.Text("FocusCount: " + FocusCount.ToString());
ImGui.Text("LOTDTimeRaw: " + LOTDTimeRaw.ToString());
ImGui.Text("LOTDTime: " + LOTDTime.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("DrakesbanePvEFangReady: " + DrakesbanePvEFangReady.ToString());
+ ImGui.Text("DrakesbanePvEWheelingReady: " + DrakesbanePvEWheelingReady.ToString());
+ ImGui.Text("RaidenThrustPvEReady: " + RaidenThrustPvEReady.ToString());
+ ImGui.Text("DraconianFuryPvEReady: " + DraconianFuryPvEReady.ToString());
}
+ #endregion
- //Job
+ #region PvE Actions
static partial void ModifyTrueThrustPvE(ref ActionSetting setting)
{
@@ -194,6 +229,7 @@ static partial void ModifySonicThrustPvE(ref ActionSetting setting)
static partial void ModifyDrakesbanePvE(ref ActionSetting setting) //aka Kendrick Lamar
{
+ setting.ActionCheck = () => DrakesbanePvEFangReady || DrakesbanePvEWheelingReady;
setting.ComboIds = [ActionID.WheelingThrustPvE, ActionID.FangAndClawPvE];
setting.StatusProvide = [StatusID.DraconianFire];
setting.CreateConfig = () => new ActionConfig()
@@ -234,7 +270,7 @@ static partial void ModifyHighJumpPvE(ref ActionSetting setting)
static partial void ModifyRaidenThrustPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.DraconianFire];
+ setting.ActionCheck = () => RaidenThrustPvEReady;
}
static partial void ModifyStardiverPvE(ref ActionSetting setting)
@@ -249,7 +285,7 @@ static partial void ModifyStardiverPvE(ref ActionSetting setting)
static partial void ModifyDraconianFuryPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.DraconianFire];
+ setting.ActionCheck = () => DraconianFuryPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
@@ -313,6 +349,7 @@ static partial void ModifyStarcrossPvE(ref ActionSetting setting)
AoeCount = 1,
};
}
+ #endregion
// PvP
static partial void ModifyHighJumpPvP(ref ActionSetting setting)
diff --git a/RotationSolver.Basic/Rotations/Basic/GunbreakerRotation.cs b/RotationSolver.Basic/Rotations/Basic/GunbreakerRotation.cs
index 5e4dbefad..c3adfb55e 100644
--- a/RotationSolver.Basic/Rotations/Basic/GunbreakerRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/GunbreakerRotation.cs
@@ -6,8 +6,6 @@ partial class GunbreakerRotation
{
///
public override MedicineType MedicineType => MedicineType.Strength;
-
-
///
///
///
@@ -30,14 +28,84 @@ partial class GunbreakerRotation
public static byte AmmoComboStep => JobGauge.AmmoComboStep;
///
- ///
+ /// Gets the maximum amount of ammo available.
///
- public static byte MaxAmmo => CartridgeChargeIiTrait.EnoughLevel ? (byte)3 : (byte)2;
+ public static byte MaxAmmo
+ {
+ get
+ {
+ if (CartridgeChargeIiTrait.EnoughLevel)
+ {
+ return 3;
+ }
+ else if (CartridgeChargeTrait.EnoughLevel)
+ {
+ return 2;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
///
/// Gets the max combo time of the Gnashing Fang combo.
///
public static short MaxTimerDuration => JobGauge.MaxTimerDuration;
+
+ ///
+ ///
+ ///
+ public static bool InGnashingFang => AmmoComboStep > 0;
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool SavageClawPvEReady => Service.GetAdjustedActionId(ActionID.GnashingFangPvE) == ActionID.SavageClawPvE;
+
+ ///
+ ///
+ ///
+ public static bool WickedTalonPvEReady => Service.GetAdjustedActionId(ActionID.GnashingFangPvE) == ActionID.WickedTalonPvE;
+
+ ///
+ ///
+ ///
+ public static bool JugularRipPvEReady => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.JugularRipPvE;
+
+ ///
+ ///
+ ///
+ public static bool AbdomenTearPvEReady => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.AbdomenTearPvE;
+
+ ///
+ ///
+ ///
+ public static bool EyeGougePvEReady => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.EyeGougePvE;
+
+ ///
+ ///
+ ///
+ public static bool HypervelocityPvEReady => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.HypervelocityPvE;
+
+ ///
+ ///
+ ///
+ public static bool FatedBrandPvEReady => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.FatedBrandPvE;
+
+ ///
+ ///
+ ///
+ public static bool NobleBloodPvEReady => Service.GetAdjustedActionId(ActionID.ReignOfBeastsPvE) == ActionID.NobleBloodPvE;
+
+ ///
+ ///
+ ///
+ public static bool LionHeartPvEReady => Service.GetAdjustedActionId(ActionID.ReignOfBeastsPvE) == ActionID.LionHeartPvE;
#endregion
#region Debug Status
@@ -49,6 +117,19 @@ public override void DisplayStatus()
ImGui.Text("AmmoComboStep: " + AmmoComboStep.ToString());
ImGui.Text("MaxAmmo: " + MaxAmmo.ToString());
ImGui.Text("MaxTimerDuration: " + MaxTimerDuration.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("SavageClawPvEReady: " + SavageClawPvEReady.ToString());
+ ImGui.Text("WickedTalonPvEReady: " + WickedTalonPvEReady.ToString());
+ ImGui.Spacing();
+ ImGui.Text("JugularRipPvEReady: " + JugularRipPvEReady.ToString());
+ ImGui.Text("AbdomenTearPvEReady: " + AbdomenTearPvEReady.ToString());
+ ImGui.Text("EyeGougePvEReady: " + EyeGougePvEReady.ToString());
+ ImGui.Text("HypervelocityPvEReady: " + HypervelocityPvEReady.ToString());
+ ImGui.Spacing();
+ ImGui.Text("FatedBrandPvEReady: " + FatedBrandPvEReady.ToString());
+ ImGui.Spacing();
+ ImGui.Text("NobleBloodPvEReady: " + NobleBloodPvEReady.ToString());
+ ImGui.Text("LionHeartPvEReady: " + LionHeartPvEReady.ToString());
ImGui.TextColored(ImGuiColors.DalamudYellow, "PvP Actions");
ImGui.Text("SavageClawPvPReady: " + SavageClawPvPReady.ToString());
ImGui.Text("WickedTalonPvPReady: " + WickedTalonPvPReady.ToString());
@@ -75,18 +156,19 @@ static partial void ModifyNoMercyPvE(ref ActionSetting setting)
setting.StatusProvide = [StatusID.ReadyToBreak];
setting.CreateConfig = () => new ActionConfig()
{
- TimeToKill = 10,
+ TimeToKill = 5,
};
}
static partial void ModifyBrutalShellPvE(ref ActionSetting setting)
{
- setting.ComboIds = [ActionID.KeenEdgePvE];
+
}
static partial void ModifyCamouflagePvE(ref ActionSetting setting)
{
setting.TargetType = TargetType.Self;
+ setting.IsFriendly = true;
}
static partial void ModifyDemonSlicePvE(ref ActionSetting setting)
@@ -111,7 +193,7 @@ static partial void ModifyDangerZonePvE(ref ActionSetting setting)
static partial void ModifySolidBarrelPvE(ref ActionSetting setting)
{
- setting.ComboIds = [ActionID.BrutalShellPvE];
+
}
static partial void ModifyBurstStrikePvE(ref ActionSetting setting)
@@ -123,12 +205,12 @@ static partial void ModifyBurstStrikePvE(ref ActionSetting setting)
static partial void ModifyNebulaPvE(ref ActionSetting setting)
{
setting.StatusProvide = StatusHelper.RampartStatus;
- setting.ActionCheck = () => Player.IsTargetOnSelf();
+ setting.TargetType = TargetType.Self;
+ setting.IsFriendly = true;
}
static partial void ModifyDemonSlaughterPvE(ref ActionSetting setting)
{
- setting.ComboIds = [ActionID.DemonSlicePvE];
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 2,
@@ -166,15 +248,13 @@ static partial void ModifyGnashingFangPvE(ref ActionSetting setting)
static partial void ModifySavageClawPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Service.GetAdjustedActionId(ActionID.GnashingFangPvE) == ActionID.SavageClawPvE;
- setting.ComboIds = [ActionID.GnashingFangPvE];
+ setting.ActionCheck = () => SavageClawPvEReady;
setting.StatusProvide = [StatusID.ReadyToTear];
}
static partial void ModifyWickedTalonPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Service.GetAdjustedActionId(ActionID.GnashingFangPvE) == ActionID.WickedTalonPvE;
- setting.ComboIds = [ActionID.SavageClawPvE];
+ setting.ActionCheck = () => WickedTalonPvEReady;
setting.StatusProvide = [StatusID.ReadyToGouge];
}
@@ -195,7 +275,7 @@ static partial void ModifyHeartOfLightPvE(ref ActionSetting setting)
static partial void ModifyHeartOfStonePvE(ref ActionSetting setting)
{
setting.StatusProvide = [StatusID.HeartOfStone];
- setting.ActionCheck = () => Player.IsParty() || Player.IsTargetOnSelf();
+ setting.IsFriendly = true;
}
static partial void ModifyContinuationPvE(ref ActionSetting setting)
@@ -205,22 +285,19 @@ static partial void ModifyContinuationPvE(ref ActionSetting setting)
static partial void ModifyJugularRipPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.JugularRipPvE;
- setting.ComboIds = [ActionID.GnashingFangPvE];
+ setting.ActionCheck = () => JugularRipPvEReady;
setting.StatusNeed = [StatusID.ReadyToRip];
}
static partial void ModifyAbdomenTearPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.AbdomenTearPvE;
- setting.ComboIds = [ActionID.SavageClawPvE];
+ setting.ActionCheck = () => AbdomenTearPvEReady;
setting.StatusNeed = [StatusID.ReadyToTear];
}
static partial void ModifyEyeGougePvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.EyeGougePvE;
- setting.ComboIds = [ActionID.WickedTalonPvE];
+ setting.ActionCheck = () => EyeGougePvEReady;
setting.StatusNeed = [StatusID.ReadyToGouge];
}
@@ -253,8 +330,7 @@ static partial void ModifyHeartOfCorundumPvE(ref ActionSetting setting)
static partial void ModifyHypervelocityPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Service.GetAdjustedActionId(ActionID.ContinuationPvE) == ActionID.HypervelocityPvE;
- setting.ComboIds = [ActionID.BurstStrikePvE];
+ setting.ActionCheck = () => HypervelocityPvEReady;
setting.StatusNeed = [StatusID.ReadyToBlast];
}
@@ -270,13 +346,13 @@ static partial void ModifyDoubleDownPvE(ref ActionSetting setting)
static partial void ModifyGreatNebulaPvE(ref ActionSetting setting)
{
setting.StatusProvide = StatusHelper.RampartStatus;
- setting.ActionCheck = () => Player.IsTargetOnSelf();
+ setting.TargetType = TargetType.Self;
+ setting.IsFriendly = true;
}
static partial void ModifyFatedBrandPvE(ref ActionSetting setting)
{
- setting.ComboIds = [ActionID.FatedCirclePvE];
- setting.StatusNeed = [StatusID.ReadyToRaze];
+ setting.ActionCheck = () => FatedBrandPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 2,
@@ -294,6 +370,7 @@ static partial void ModifyReignOfBeastsPvE(ref ActionSetting setting)
static partial void ModifyNobleBloodPvE(ref ActionSetting setting)
{
+ setting.ActionCheck = () => NobleBloodPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1
@@ -304,6 +381,7 @@ static partial void ModifyNobleBloodPvE(ref ActionSetting setting)
static partial void ModifyLionHeartPvE(ref ActionSetting setting)
{
+ setting.ActionCheck = () => LionHeartPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1
@@ -432,6 +510,7 @@ static partial void ModifyEyeGougePvP(ref ActionSetting setting)
{
setting.ActionCheck = () => EyeGougePvPReady;
}
+ #endregion
///
protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
@@ -440,14 +519,4 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
&& Player.GetHealthRatio() <= Service.Config.HealthForDyingTanks) return true;
return base.EmergencyAbility(nextGCD, out act);
}
-
- ///
- [RotationDesc(ActionID.TrajectoryPvE)]
- protected sealed override bool MoveForwardAbility(IAction nextGCD, out IAction? act)
- {
- if (TrajectoryPvE.CanUse(out act)) return true;
- return false;
- }
-
- #endregion
-}
+}
\ No newline at end of file
diff --git a/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs b/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs
index b759a6760..f7a91dd85 100644
--- a/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs
@@ -1,3 +1,5 @@
+using Dalamud.Interface.Colors;
+
namespace RotationSolver.Basic.Rotations.Basic;
partial class MachinistRotation
@@ -72,7 +74,21 @@ public static byte OverheatedStacks
///
protected static bool OverheatedEndAfterGCD(uint gctCount = 0, float offset = 0)
=> OverheatedEndAfter(GCDTime(gctCount, offset));
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool DetonatorPvEReady => Service.GetAdjustedActionId(ActionID.WildfirePvE) == ActionID.DetonatorPvE;
+ ///
+ ///
+ ///
+ public static bool ExcavatorPvEReady => Service.GetAdjustedActionId(ActionID.ChainSawPvE) == ActionID.ExcavatorPvE;
+ #endregion
+ #region Debug Display
///
public override void DisplayStatus()
{
@@ -86,6 +102,10 @@ public override void DisplayStatus()
ImGui.Text("OverheatTimeRemainingRaw: " + OverheatTimeRemainingRaw.ToString());
ImGui.Text("OverheatTime: " + OverheatTime.ToString());
ImGui.Text("OverheatedStacks: " + OverheatedStacks.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("DetonatorPvEReady: " + DetonatorPvEReady.ToString());
+ ImGui.Text("ExcavatorPvEReady: " + ExcavatorPvEReady.ToString());
+ ImGui.Spacing();
}
#endregion
@@ -190,6 +210,11 @@ static partial void ModifyWildfirePvE(ref ActionSetting setting)
};
}
+ static partial void ModifyDetonatorPvE(ref ActionSetting setting)
+ {
+ setting.ActionCheck = () => DetonatorPvEReady;
+ }
+
static partial void ModifyRicochetPvE(ref ActionSetting setting)
{
setting.UnlockedByQuestID = 67240;
@@ -377,7 +402,7 @@ static partial void ModifyCheckmatePvE(ref ActionSetting setting)
static partial void ModifyExcavatorPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Player.HasStatus(true, StatusID.ExcavatorReady);
+ setting.ActionCheck = () => ExcavatorPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
diff --git a/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs b/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs
index 95608c92e..dacfaebc7 100644
--- a/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs
@@ -1,3 +1,5 @@
+using Dalamud.Interface.Colors;
+
namespace RotationSolver.Basic.Rotations.Basic;
partial class MonkRotation
{
@@ -49,6 +51,47 @@ partial class MonkRotation
/// Brotherhood
///
public static bool InBrotherhood => !Player.WillStatusEnd(0, true, StatusID.Brotherhood);
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool CelestialRevolutionPvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.CelestialRevolutionPvE;
+
+ ///
+ ///
+ ///
+ public static bool FlintStrikePvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.FlintStrikePvE;
+
+ ///
+ ///
+ ///
+ public static bool RisingPhoenixPvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.RisingPhoenixPvE;
+
+ ///
+ ///
+ ///
+ public static bool TornadoKickPvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.TornadoKickPvE;
+
+ ///
+ ///
+ ///
+ public static bool PhantomRushPvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.PhantomRushPvE;
+
+ ///
+ ///
+ ///
+ public static bool ElixirFieldPvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.ElixirFieldPvE;
+
+ ///
+ ///
+ ///
+ public static bool ElixirBurstPvEReady => Service.GetAdjustedActionId(ActionID.MasterfulBlitzPvE) == ActionID.ElixirBurstPvE;
+ #endregion
+
+ #region Draw Debug
///
public override void DisplayStatus()
@@ -61,9 +104,18 @@ public override void DisplayStatus()
ImGui.Text($"HasSolar: {HasSolar}");
ImGui.Text($"Chakra: {Chakra}");
ImGui.Text($"BeastChakras: {string.Join(", ", BeastChakras)}");
+ ImGui.TextColored(ImGuiColors.DalamudViolet, "PvE Actions");
+ ImGui.Text("CelestialRevolutionPvEReady: " + CelestialRevolutionPvEReady.ToString());
+ ImGui.Text("FlintStrikePvEReady: " + FlintStrikePvEReady.ToString());
+ ImGui.Text("RisingPhoenixPvEReady: " + RisingPhoenixPvEReady.ToString());
+ ImGui.Text("TornadoKickPvEReady: " + TornadoKickPvEReady.ToString());
+ ImGui.Text("PhantomRushPvEReady: " + PhantomRushPvEReady.ToString());
+ ImGui.Text("ElixirFieldPvEReady: " + ElixirFieldPvEReady.ToString());
+ ImGui.Text("ElixirBurstPvEReady: " + ElixirBurstPvEReady.ToString());
}
#endregion
+ #region PvE Actions
static partial void ModifyBootshinePvE(ref ActionSetting setting)
{
setting.StatusProvide = [StatusID.RaptorForm];
@@ -215,7 +267,7 @@ static partial void ModifyTornadoKickPvE(ref ActionSetting setting)
static partial void ModifyElixirFieldPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => BeastChakras.Distinct().Count() == 1 && BeastChakras.Any(chakra => chakra != BeastChakra.NONE);
+ setting.ActionCheck = () => ElixirFieldPvEReady;
setting.StatusProvide = [StatusID.FormlessFist];
setting.CreateConfig = () => new ActionConfig()
{
@@ -225,7 +277,7 @@ static partial void ModifyElixirFieldPvE(ref ActionSetting setting)
static partial void ModifyCelestialRevolutionPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => BeastChakras.Distinct().Count() == 2 && BeastChakras.Any(chakra => chakra != BeastChakra.NONE);
+ setting.ActionCheck = () => CelestialRevolutionPvEReady;
setting.StatusProvide = [StatusID.FormlessFist];
setting.CreateConfig = () => new ActionConfig()
{
@@ -235,7 +287,7 @@ static partial void ModifyCelestialRevolutionPvE(ref ActionSetting setting)
static partial void ModifyFlintStrikePvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => BeastChakras.Distinct().Count() == 3 && BeastChakras.Any(chakra => chakra != BeastChakra.NONE);
+ setting.ActionCheck = () => FlintStrikePvEReady;
setting.StatusProvide = [StatusID.FormlessFist];
setting.CreateConfig = () => new ActionConfig()
{
@@ -319,7 +371,7 @@ static partial void ModifyShadowOfTheDestroyerPvE(ref ActionSetting setting)
static partial void ModifyRisingPhoenixPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => BeastChakras.Distinct().Count() == 3 && BeastChakras.Any(chakra => chakra != BeastChakra.NONE);
+ setting.ActionCheck = () => RisingPhoenixPvEReady;
setting.StatusProvide = [StatusID.FormlessFist];
setting.CreateConfig = () => new ActionConfig()
{
@@ -329,7 +381,7 @@ static partial void ModifyRisingPhoenixPvE(ref ActionSetting setting)
static partial void ModifyPhantomRushPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => HasSolar && HasLunar && BeastChakras.Any(chakra => chakra != BeastChakra.NONE);
+ setting.ActionCheck = () => PhantomRushPvEReady;
setting.StatusProvide = [StatusID.FormlessFist];
setting.CreateConfig = () => new ActionConfig()
{
@@ -359,7 +411,7 @@ static partial void ModifyPouncingCoeurlPvE(ref ActionSetting setting)
static partial void ModifyElixirBurstPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => BeastChakras.Distinct().Count() == 1 && BeastChakras.Any(chakra => chakra != BeastChakra.NONE);
+ setting.ActionCheck = () => ElixirBurstPvEReady;
setting.StatusProvide = [StatusID.FormlessFist];
setting.CreateConfig = () => new ActionConfig()
{
@@ -385,7 +437,7 @@ static partial void ModifyFiresReplyPvE(ref ActionSetting setting)
AoeCount = 1,
};
}
-
+ #endregion
// PvP
static partial void ModifyThunderclapPvP(ref ActionSetting setting)
diff --git a/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs b/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
index 86ce1c1e8..6cad3b2a2 100644
--- a/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
@@ -1,4 +1,6 @@
-namespace RotationSolver.Basic.Rotations.Basic;
+using Dalamud.Interface.Colors;
+
+namespace RotationSolver.Basic.Rotations.Basic;
partial class NinjaRotation
{
@@ -24,7 +26,7 @@ partial class NinjaRotation
///
/// Do you need to prep or currently use shadowwalker
///
- public bool ShadowWalkerNeeded => TrickAttackPvE.Cooldown.WillHaveOneCharge(18) || KunaisBanePvE.Cooldown.WillHaveOneCharge(18) || MeisuiPvE.Cooldown.WillHaveOneCharge(18);
+ public bool ShadowWalkerNeeded => (TrickAttackPvE.EnoughLevel && TrickAttackPvE.Cooldown.WillHaveOneCharge(18)) || (KunaisBanePvE.EnoughLevel && KunaisBanePvE.Cooldown.WillHaveOneCharge(18)) || (MeisuiPvE.EnoughLevel && MeisuiPvE.Cooldown.WillHaveOneCharge(18));
///
/// Determines if Trick Attack is in its effective period.
@@ -52,7 +54,77 @@ public static byte RaijuStacks
return stacks == byte.MaxValue ? (byte)3 : stacks;
}
}
+ #endregion
+
+ #region PvE Actions Unassignable
+
+ ///
+ ///
+ ///
+ public static bool RabbitMediumPvEActive => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.RabbitMediumPvE;
+
+ ///
+ ///
+ ///
+ public static bool FumaShurikenPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.FumaShurikenPvE;
+
+ ///
+ ///
+ ///
+ public static bool KatonPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.KatonPvE;
+
+ ///
+ ///
+ ///
+ public static bool RaitonPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.RaitonPvE;
+
+ ///
+ ///
+ ///
+ public static bool HyotonPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.HyotonPvE;
+
+ ///
+ ///
+ ///
+ public static bool HutonPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.HutonPvE;
+
+ ///
+ ///
+ ///
+ public static bool DotonPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.DotonPvE;
+ ///
+ ///
+ ///
+ public static bool SuitonPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.SuitonPvE;
+
+ ///
+ ///
+ ///
+ public static bool GokaMekkyakuPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.GokaMekkyakuPvE;
+
+ ///
+ ///
+ ///
+ public static bool HyoshoRanryuPvEReady => Service.GetAdjustedActionId(ActionID.NinjutsuPvE) == ActionID.HyoshoRanryuPvE;
+
+ ///
+ ///
+ ///
+ public static bool DeathfrogMediumPvEReady => Service.GetAdjustedActionId(ActionID.HellfrogMediumPvE) == ActionID.DeathfrogMediumPvE;
+
+ ///
+ ///
+ ///
+ public static bool ZeshoMeppoPvEReady => Service.GetAdjustedActionId(ActionID.BhavacakraPvE) == ActionID.ZeshoMeppoPvE;
+
+ ///
+ ///
+ ///
+ public static bool TenriJindoPvEReady => Service.GetAdjustedActionId(ActionID.TenChiJinPvE) == ActionID.TenriJindoPvE;
+ #endregion
+
+ #region Draw Debug
///
public override void DisplayStatus()
{
@@ -64,9 +136,29 @@ public override void DisplayStatus()
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
+ #region PvE Actions
+
+ static partial void ModifyRabbitMediumPvE(ref ActionSetting setting)
+ {
+ setting.ActionCheck = () => RabbitMediumPvEActive;
+ }
+
static partial void ModifySpinningEdgePvE(ref ActionSetting setting)
{
@@ -275,8 +367,7 @@ static partial void ModifyKunaisBanePvE(ref ActionSetting setting)
static partial void ModifyDeathfrogMediumPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Ninki <= 50;
- setting.StatusNeed = [StatusID.Higi];
+ setting.ActionCheck = () => Ninki <= 50 && DeathfrogMediumPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
@@ -285,13 +376,12 @@ static partial void ModifyDeathfrogMediumPvE(ref ActionSetting setting)
static partial void ModifyZeshoMeppoPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => Ninki <= 50;
- setting.StatusNeed = [StatusID.Higi];
+ setting.ActionCheck = () => Ninki <= 50 && ZeshoMeppoPvEReady;
}
static partial void ModifyTenriJindoPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.TenriJindoReady];
+ setting.ActionCheck = () => TenriJindoPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
@@ -316,11 +406,12 @@ public NinjaRotation()
static partial void ModifyFumaShurikenPvE(ref ActionSetting setting)
{
-
+ setting.ActionCheck = () => FumaShurikenPvEReady;
}
static partial void ModifyKatonPvE(ref ActionSetting setting)
{
+ setting.ActionCheck = () => KatonPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
@@ -329,16 +420,18 @@ static partial void ModifyKatonPvE(ref ActionSetting setting)
static partial void ModifyRaitonPvE(ref ActionSetting setting)
{
- //setting.StatusProvide = [StatusID.RaijuReady];
+ setting.ActionCheck = () => RaitonPvEReady;
}
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.CreateConfig = () => new ActionConfig()
{
@@ -348,6 +441,7 @@ static partial void ModifyHutonPvE(ref ActionSetting setting)
static partial void ModifyDotonPvE(ref ActionSetting setting)
{
+ setting.ActionCheck = () => DotonPvEReady;
setting.StatusProvide = [StatusID.Doton];
setting.CreateConfig = () => new ActionConfig()
{
@@ -357,12 +451,13 @@ static partial void ModifyDotonPvE(ref ActionSetting setting)
static partial void ModifySuitonPvE(ref ActionSetting setting)
{
+ setting.ActionCheck = () => SuitonPvEReady;
setting.StatusProvide = [StatusID.ShadowWalker];
}
static partial void ModifyGokaMekkyakuPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Kassatsu];
+ setting.ActionCheck = () => GokaMekkyakuPvEReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
@@ -371,8 +466,9 @@ static partial void ModifyGokaMekkyakuPvE(ref ActionSetting setting)
static partial void ModifyHyoshoRanryuPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Kassatsu];
+ setting.ActionCheck = () => HyoshoRanryuPvEReady;
}
+ #endregion
// PvP
static partial void ModifyShukuchiPvP(ref ActionSetting setting)
diff --git a/RotationSolver.Basic/Rotations/Basic/ReaperRotation.cs b/RotationSolver.Basic/Rotations/Basic/ReaperRotation.cs
index 012842cbb..fb14e583c 100644
--- a/RotationSolver.Basic/Rotations/Basic/ReaperRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/ReaperRotation.cs
@@ -1,64 +1,160 @@
-namespace RotationSolver.Basic.Rotations.Basic;
+using Dalamud.Interface.Colors;
+
+namespace RotationSolver.Basic.Rotations.Basic;
partial class ReaperRotation
{
///
public override MedicineType MedicineType => MedicineType.Strength;
+ #region JobGauge
+ ///
+ ///
+ ///
+ public static byte Soul => JobGauge.Soul;
+
+ ///
+ ///
+ ///
+ public static byte Shroud => JobGauge.Shroud;
+
+ ///
+ ///
+ ///
+ public static float EnshroudedTiemRemaining => JobGauge.EnshroudedTimeRemaining;
+
+ ///
+ ///
+ ///
+ public static byte LemureShroud => JobGauge.LemureShroud;
+
+ ///
+ ///
+ ///
+ public static byte VoidShroud => JobGauge.VoidShroud;
+ #endregion
+
+ #region Status Tracking
+ ///
+ ///
+ ///
+ public static bool HasEnshrouded => !Player.WillStatusEnd(0, true, StatusID.Enshrouded);
+
///
///
///
- public static bool HasEnshrouded => Player.HasStatus(true, StatusID.Enshrouded);
+ public static bool HasSoulReaver => !Player.WillStatusEnd(0, true, StatusID.SoulReaver);
///
///
///
- public static bool HasSoulReaver => Player.HasStatus(true, StatusID.SoulReaver);
+ public static bool HasSoulsow => !Player.WillStatusEnd(0, true, StatusID.Soulsow);
///
///
///
- public static bool HasExecutioner => Player.HasStatus(true, StatusID.Executioner);
+ public static bool HasExecutioner => !Player.WillStatusEnd(0, true, StatusID.Executioner);
///
///
///
- public static bool HasIdealHost => Player.HasStatus(true, StatusID.IdealHost);
+ public static bool HasIdealHost => !Player.WillStatusEnd(0, true, StatusID.IdealHost);
///
///
///
- public static bool HasOblatio => Player.HasStatus(true, StatusID.Oblatio);
+ public static bool HasOblatio => !Player.WillStatusEnd(0, true, StatusID.Oblatio);
///
///
///
public static bool HasPerfectioParata => Player.HasStatus(true, StatusID.PerfectioParata);
+ #endregion
+
+ #region Actions Unassignable
- #region JobGauge
///
///
///
- public static byte Soul => JobGauge.Soul;
+ public static bool UnveiledGibbetPvEReady => Service.GetAdjustedActionId(ActionID.BloodStalkPvE) == ActionID.UnveiledGibbetPvE;
///
///
///
- public static byte Shroud => JobGauge.Shroud;
+ public static bool UnveiledGallowsPvEReady => Service.GetAdjustedActionId(ActionID.BloodStalkPvE) == ActionID.UnveiledGallowsPvE;
///
///
///
- public static byte LemureShroud => JobGauge.LemureShroud;
+ public static bool RegressPvEIngressReady => Service.GetAdjustedActionId(ActionID.HellsIngressPvE) == ActionID.RegressPvE;
///
///
///
- public static byte VoidShroud => JobGauge.VoidShroud;
+ public static bool RegressPvEEgressReady => Service.GetAdjustedActionId(ActionID.HellsEgressPvE) == ActionID.RegressPvE;
+
+ ///
+ ///
+ ///
+ public static bool VoidReapingPvEReady => Service.GetAdjustedActionId(ActionID.GibbetPvE) == ActionID.VoidReapingPvE;
+
+ ///
+ ///
+ ///
+ public static bool CrossReapingPvEReady => Service.GetAdjustedActionId(ActionID.GallowsPvE) == ActionID.CrossReapingPvE;
+
+ ///
+ ///
+ ///
+ public static bool GrimReapingPvEReady => Service.GetAdjustedActionId(ActionID.GuillotinePvE) == ActionID.GrimReapingPvE;
+
+ ///
+ ///
+ ///
+ public static bool HarvestMoonPvEReady => Service.GetAdjustedActionId(ActionID.SoulsowPvE) == ActionID.HarvestMoonPvE;
+
+ ///
+ ///
+ ///
+ public static bool LemuresSlicePvEReady => Service.GetAdjustedActionId(ActionID.BloodStalkPvE) == ActionID.LemuresSlicePvE;
+
+ ///
+ ///
+ ///
+ public static bool LemuresScythePvEReady => Service.GetAdjustedActionId(ActionID.GrimSwathePvE) == ActionID.LemuresScythePvE;
+
+ ///
+ ///
+ ///
+ public static bool SacrificiumPvEReady => Service.GetAdjustedActionId(ActionID.GluttonyPvE) == ActionID.SacrificiumPvE;
+
+ ///
+ ///
+ ///
+ public static bool ExecutionersGibbetPvEReady => Service.GetAdjustedActionId(ActionID.GibbetPvE) == ActionID.ExecutionersGibbetPvE;
+
+ ///
+ ///
+ ///
+ public static bool ExecutionersGallowsPvEReady => Service.GetAdjustedActionId(ActionID.GallowsPvE) == ActionID.ExecutionersGallowsPvE;
+
+ ///
+ ///
+ ///
+ public static bool ExecutionersGuillotinePvEReady => Service.GetAdjustedActionId(ActionID.GuillotinePvE) == ActionID.ExecutionersGuillotinePvE;
+
+ ///
+ ///
+ ///
+ public static bool PerfectioPvEReady => Service.GetAdjustedActionId(ActionID.CommunioPvE) == ActionID.PerfectioPvE;
+ #endregion
+
+ #region Debug
///
public override void DisplayStatus()
{
+ ImGui.Text("EnshroudedTiemRemaining: " + EnshroudedTiemRemaining.ToString());
ImGui.Text("HasEnshrouded: " + HasEnshrouded.ToString());
ImGui.Text("HasSoulReaver: " + HasSoulReaver.ToString());
ImGui.Text("HasExecutioner: " + HasExecutioner.ToString());
@@ -69,9 +165,26 @@ public override void DisplayStatus()
ImGui.Text("Shroud: " + Shroud.ToString());
ImGui.Text("LemureShroud: " + LemureShroud.ToString());
ImGui.Text("VoidShroud: " + VoidShroud.ToString());
+ ImGui.TextColored(ImGuiColors.DalamudOrange, "PvE Actions");
+ ImGui.Text("UnveiledGibbetPvEReady: " + UnveiledGibbetPvEReady.ToString());
+ ImGui.Text("UnveiledGallowsPvEReady: " + UnveiledGallowsPvEReady.ToString());
+ ImGui.Text("RegressPvEIngressReady: " + RegressPvEIngressReady.ToString());
+ ImGui.Text("RegressPvEEgressReady: " + RegressPvEEgressReady.ToString());
+ ImGui.Text("VoidReapingPvEReady: " + VoidReapingPvEReady.ToString());
+ ImGui.Text("CrossReapingPvEReady: " + CrossReapingPvEReady.ToString());
+ ImGui.Text("GrimReapingPvEReady: " + GrimReapingPvEReady.ToString());
+ ImGui.Text("HarvestMoonPvEReady: " + HarvestMoonPvEReady.ToString());
+ ImGui.Text("LemuresSlicePvEReady: " + LemuresSlicePvEReady.ToString());
+ ImGui.Text("LemuresScythePvEReady: " + LemuresScythePvEReady.ToString());
+ ImGui.Text("SacrificiumPvEReady: " + SacrificiumPvEReady.ToString());
+ ImGui.Text("ExecutionersGibbetPvEReady: " + ExecutionersGibbetPvEReady.ToString());
+ ImGui.Text("ExecutionersGallowsPvEReady: " + ExecutionersGallowsPvEReady.ToString());
+ ImGui.Text("ExecutionersGuillotinePvEReady: " + ExecutionersGuillotinePvEReady.ToString());
+ ImGui.Text("PerfectioPvEReady: " + PerfectioPvEReady.ToString());
}
#endregion
+ #region PvE Actions
static partial void ModifySlicePvE(ref ActionSetting setting)
{
setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver;
@@ -82,20 +195,25 @@ static partial void ModifyWaxingSlicePvE(ref ActionSetting setting)
setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver;
}
- static partial void ModifyInfernalSlicePvE(ref ActionSetting setting)
- {
- setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver;
- }
-
static partial void ModifyShadowOfDeathPvE(ref ActionSetting setting)
{
setting.TargetStatusProvide = [StatusID.DeathsDesign];
setting.ActionCheck = () => !HasSoulReaver;
}
- static partial void ModifySoulSlicePvE(ref ActionSetting setting)
+ static partial void ModifyHarpePvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul <= 50;
+ setting.SpecialType = SpecialActionType.MeleeRange;
+ }
+
+ static partial void ModifyHellsIngressPvE(ref ActionSetting setting)
+ {
+ setting.StatusProvide = [StatusID.EnhancedHarpe, StatusID.Bind];
+ }
+
+ static partial void ModifyHellsEgressPvE(ref ActionSetting setting)
+ {
+ setting.StatusProvide = [StatusID.EnhancedHarpe, StatusID.Bind];
}
static partial void ModifySpinningScythePvE(ref ActionSetting setting)
@@ -103,7 +221,7 @@ static partial void ModifySpinningScythePvE(ref ActionSetting setting)
setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver;
}
- static partial void ModifyNightmareScythePvE(ref ActionSetting setting)
+ static partial void ModifyInfernalSlicePvE(ref ActionSetting setting)
{
setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver;
}
@@ -118,57 +236,52 @@ static partial void ModifyWhorlOfDeathPvE(ref ActionSetting setting)
};
}
- static partial void ModifySoulScythePvE(ref ActionSetting setting)
- {
- setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul <= 50;
- }
-
- static partial void ModifyGibbetPvE(ref ActionSetting setting)
+ static partial void ModifyArcaneCrestPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.SoulReaver];
+ setting.StatusProvide = [StatusID.CrestOfTimeBorrowed];
+ setting.IsFriendly = true;
}
- static partial void ModifyExecutionersGibbetPvE(ref ActionSetting setting)
+ static partial void ModifyNightmareScythePvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Executioner];
+ setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver;
}
- static partial void ModifyGallowsPvE(ref ActionSetting setting)
+ static partial void ModifyBloodStalkPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.SoulReaver];
+ setting.StatusProvide = [StatusID.SoulReaver];
+ setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
}
- static partial void ModifyExecutionersGallowsPvE(ref ActionSetting setting)
+ static partial void ModifyGrimSwathePvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Executioner];
+ setting.StatusProvide = [StatusID.SoulReaver];
+ setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
}
- static partial void ModifyGuillotinePvE(ref ActionSetting setting)
+ static partial void ModifySoulSlicePvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.SoulReaver];
+ setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul <= 50;
}
- static partial void ModifyExecutionersGuillotinePvE(ref ActionSetting setting)
+ static partial void ModifySoulScythePvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Executioner];
+ setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul <= 50;
}
- static partial void ModifyBloodStalkPvE(ref ActionSetting setting)
+ static partial void ModifyGibbetPvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.SoulReaver];
- setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
+ setting.ActionCheck = () => HasSoulReaver;
}
- static partial void ModifyGrimSwathePvE(ref ActionSetting setting)
+ static partial void ModifyGallowsPvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.SoulReaver];
- setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
+ setting.ActionCheck = () => HasSoulReaver;
}
- static partial void ModifyGluttonyPvE(ref ActionSetting setting)
+ static partial void ModifyGuillotinePvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.SoulReaver, StatusID.Executioner];
- setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
+ setting.ActionCheck = () => HasSoulReaver;
}
static partial void ModifyArcaneCirclePvE(ref ActionSetting setting)
@@ -180,93 +293,117 @@ static partial void ModifyArcaneCirclePvE(ref ActionSetting setting)
};
}
- static partial void ModifyPlentifulHarvestPvE(ref ActionSetting setting)
+ static partial void ModifyGluttonyPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.ImmortalSacrifice];
- setting.ActionCheck = () => !Player.HasStatus(true, StatusID.BloodsownCircle_2972);
+ setting.StatusProvide = [StatusID.SoulReaver, StatusID.Executioner];
+ setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
}
static partial void ModifyEnshroudPvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.Enshrouded];
setting.ActionCheck = () => !HasEnshrouded && !HasSoulReaver && Soul >= 50;
setting.UnlockedByQuestID = 69614;
}
- static partial void ModifySacrificiumPvE(ref ActionSetting setting)
+ static partial void ModifySoulsowPvE(ref ActionSetting setting)
+ {
+ setting.StatusProvide = [StatusID.Soulsow];
+ setting.ActionCheck = () => !InCombat;
+ }
+
+ static partial void ModifyPlentifulHarvestPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => HasEnshrouded && HasOblatio;
+ setting.StatusNeed = [StatusID.ImmortalSacrifice];
+ setting.ActionCheck = () => !Player.HasStatus(true, StatusID.BloodsownCircle_2972);
}
static partial void ModifyCommunioPvE(ref ActionSetting setting)
{
setting.StatusProvide = [StatusID.PerfectioParata];
- setting.StatusNeed = [StatusID.Enshrouded];
- setting.ActionCheck = () => LemureShroud == 1;
+ setting.ActionCheck = () => LemureShroud == 1 && HasEnshrouded;
}
+ #endregion
- static partial void ModifyPerfectioPvE(ref ActionSetting setting)
+ #region PvE Actions Unassaignable
+
+ static partial void ModifyUnveiledGibbetPvE(ref ActionSetting setting)
{
- setting.ActionCheck = () => HasPerfectioParata;
+ setting.ActionCheck = () => UnveiledGibbetPvEReady && Soul >= 50;
}
- static partial void ModifyLemuresSlicePvE(ref ActionSetting setting)
+ static partial void ModifyUnveiledGallowsPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Enshrouded];
- setting.ActionCheck = () => VoidShroud >= 2;
+ setting.ActionCheck = () => UnveiledGallowsPvEReady && Soul >= 50;
}
- static partial void ModifyLemuresScythePvE(ref ActionSetting setting)
+ static partial void ModifyRegressPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Enshrouded];
- setting.ActionCheck = () => VoidShroud >= 2;
+ setting.ActionCheck = () => RegressPvEIngressReady || RegressPvEEgressReady;
}
static partial void ModifyVoidReapingPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Enshrouded];
+ setting.ActionCheck = () => VoidReapingPvEReady && LemureShroud >= 1;
}
static partial void ModifyCrossReapingPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Enshrouded];
+ setting.ActionCheck = () => CrossReapingPvEReady && LemureShroud >= 1;
}
static partial void ModifyGrimReapingPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Enshrouded];
+ setting.ActionCheck = () => GrimReapingPvEReady && LemureShroud >= 1;
}
- static partial void ModifyHarpePvE(ref ActionSetting setting)
+ static partial void ModifyHarvestMoonPvE(ref ActionSetting setting)
{
- setting.SpecialType = SpecialActionType.MeleeRange;
+ setting.ActionCheck = () => HarvestMoonPvEReady && HasSoulsow;
}
- static partial void ModifyHellsIngressPvE(ref ActionSetting setting)
+ static partial void ModifyLemuresSlicePvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.EnhancedHarpe, StatusID.Bind];
+ setting.ActionCheck = () => LemuresSlicePvEReady && VoidShroud >= 2;
}
- static partial void ModifyHellsEgressPvE(ref ActionSetting setting)
+ static partial void ModifyLemuresScythePvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.EnhancedHarpe, StatusID.Bind];
+ setting.ActionCheck = () => LemuresScythePvEReady && VoidShroud >= 2;
}
- static partial void ModifySoulsowPvE(ref ActionSetting setting)
+ static partial void ModifySacrificiumPvE(ref ActionSetting setting)
{
- setting.StatusProvide = [StatusID.Soulsow];
- setting.ActionCheck = () => !InCombat;
+ setting.ActionCheck = () => SacrificiumPvEReady && HasEnshrouded && HasOblatio;
}
- static partial void ModifyHarvestMoonPvE(ref ActionSetting setting)
+ static partial void ModifyExecutionersGibbetPvE(ref ActionSetting setting)
+ {
+ setting.ActionCheck = () => ExecutionersGibbetPvEReady && HasExecutioner;
+ }
+
+ static partial void ModifyExecutionersGallowsPvE(ref ActionSetting setting)
{
- setting.StatusNeed = [StatusID.Soulsow];
+ setting.ActionCheck = () => ExecutionersGallowsPvEReady && HasExecutioner;
}
+ static partial void ModifyExecutionersGuillotinePvE(ref ActionSetting setting)
+ {
+ setting.ActionCheck = () => ExecutionersGuillotinePvEReady && HasExecutioner;
+ }
+
+ static partial void ModifyPerfectioPvE(ref ActionSetting setting)
+ {
+ setting.ActionCheck = () => PerfectioPvEReady && HasPerfectioParata;
+ }
+
+ #endregion
+
+ #region PvP Actions
static partial void ModifyHellsIngressPvP(ref ActionSetting setting)
{
setting.SpecialType = SpecialActionType.MovingForward;
}
+ #endregion
///
[RotationDesc(ActionID.HellsIngressPvE)]