diff --git a/BasicRotations/Magical/SMN_Default.cs b/BasicRotations/Magical/SMN_Default.cs index 56ddb88..3c50f49 100644 --- a/BasicRotations/Magical/SMN_Default.cs +++ b/BasicRotations/Magical/SMN_Default.cs @@ -31,6 +31,9 @@ public enum SummonOrderType : byte [RotationConfig(CombatType.PvE, Name = "Use Crimson Cyclone. Will use at any range, regardless of saftey use with caution.")] public bool AddCrimsonCyclone { get; set; } = true; + [RotationConfig(CombatType.PvE, Name = "Use Bahamut no matter what whenever it's up lol don't wait")] + public bool AlwaysBaha { get; set; } = false; + [RotationConfig(CombatType.PvE, Name = "Use Swiftcast")] public SwiftType AddSwiftcast { get; set; } = SwiftType.No; @@ -94,6 +97,8 @@ protected override bool GeneralGCD(out IAction? act) { if (SummonCarbunclePvE.CanUse(out act)) return true; + if ((Player.HasStatus(false, StatusID.SearingLight) || SearingLightPvE.Cooldown.IsCoolingDown) && AlwaysBaha && SummonBahamutPvE.CanUse(out act)) return true; + if (SlipstreamPvE.CanUse(out act, skipAoeCheck: true)) return true; if (CrimsonStrikePvE.CanUse(out act, skipAoeCheck: true)) return true; diff --git a/BasicRotations/Magical/SMN_zBeta.cs b/BasicRotations/Magical/SMN_zBeta.cs deleted file mode 100644 index a74745e..0000000 --- a/BasicRotations/Magical/SMN_zBeta.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System.ComponentModel; - -namespace DefaultRotations.Magical; - -[Rotation("Beta", CombatType.PvE, GameVersion = "6.58")] -[SourceCode(Path = "main/DefaultRotations/Magical/SMN_zBeta.cs")] -[Api(1)] -public sealed class SMN_zBeta : SummonerRotation -{ - #region Config Options - public enum SwiftType : byte - { - No, - Emerald, - Ruby, - All, - } - - public enum SummonOrderType : byte - { - [Description("Topaz-Emerald-Ruby")] - TopazEmeraldRuby, - - [Description("Topaz-Ruby-Emerald")] - TopazRubyEmerald, - - [Description("Emerald-Topaz-Ruby")] - EmeraldTopazRuby, - } - - [RotationConfig(CombatType.PvE, Name = "Use Crimson Cyclone. Will use at any range, regardless of saftey use with caution.")] - public bool AddCrimsonCyclone { get; set; } = true; - - [RotationConfig(CombatType.PvE, Name = "Use Bahamut no matter what whenever it's up lol don't wait")] - public bool AlwaysBaha { get; set; } = false; - - [RotationConfig(CombatType.PvE, Name = "Use Swiftcast")] - public SwiftType AddSwiftcast { get; set; } = SwiftType.No; - - [RotationConfig(CombatType.PvE, Name = "Order")] - public SummonOrderType SummonOrder { get; set; } = SummonOrderType.EmeraldTopazRuby; - #endregion - - #region Countdown Logic - protected override IAction? CountDownAction(float remainTime) - { - if (SummonCarbunclePvE.CanUse(out var act)) return act; - - if (remainTime <= RuinPvE.Info.CastTime + CountDownAhead - && RuinPvE.CanUse(out act)) return act; - return base.CountDownAction(remainTime); - } - #endregion - - #region Move Logic - [RotationDesc(ActionID.CrimsonCyclonePvE)] - protected override bool MoveForwardGCD(out IAction? act) - { - if (CrimsonCyclonePvE.CanUse(out act, skipAoeCheck: true)) return true; - return base.MoveForwardGCD(out act); - } - #endregion - - #region oGCD Logic - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - if (IsBurst && !Player.HasStatus(false, StatusID.SearingLight)) - { - if (SearingLightPvE.CanUse(out act, skipAoeCheck: true)) return true; - } - - var IsTargetBoss = HostileTarget?.IsBossFromTTK() ?? false; - var IsTargetDying = HostileTarget?.IsDying() ?? false; - - if ((InBahamut && SummonBahamutPvE.Cooldown.ElapsedOneChargeAfterGCD(3) || InPhoenix || - IsTargetBoss && IsTargetDying) && EnkindleBahamutPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if ((SummonBahamutPvE.Cooldown.ElapsedOneChargeAfterGCD(3) || IsTargetBoss && IsTargetDying) && DeathflarePvE.CanUse(out act, skipAoeCheck: true)) return true; - if (RekindlePvE.CanUse(out act, skipAoeCheck: true)) return true; - if (MountainBusterPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if ((Player.HasStatus(false, StatusID.SearingLight) && InBahamut && (SummonBahamutPvE.Cooldown.ElapsedOneChargeAfterGCD(3) || !EnergyDrainPvE.Cooldown.IsCoolingDown) || - !SearingLightPvE.EnoughLevel || IsTargetBoss && IsTargetDying) && PainflarePvE.CanUse(out act)) return true; - - if ((Player.HasStatus(false, StatusID.SearingLight) && InBahamut && (SummonBahamutPvE.Cooldown.ElapsedOneChargeAfterGCD(3) || !EnergyDrainPvE.Cooldown.IsCoolingDown) || - !SearingLightPvE.EnoughLevel || IsTargetBoss && IsTargetDying) && FesterPvE.CanUse(out act)) return true; - - if (EnergySiphonPvE.CanUse(out act)) return true; - if (EnergyDrainPvE.CanUse(out act)) return true; - - return base.AttackAbility(nextGCD, out act); - } - #endregion - - #region GCD Logic - protected override bool GeneralGCD(out IAction? act) - { - if (SummonCarbunclePvE.CanUse(out act)) return true; - - if ((Player.HasStatus(false, StatusID.SearingLight) || SearingLightPvE.Cooldown.IsCoolingDown) && AlwaysBaha && SummonBahamutPvE.CanUse(out act)) return true; - - if (SlipstreamPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (CrimsonStrikePvE.CanUse(out act, skipAoeCheck: true)) return true; - - //AOE - if (PreciousBrilliancePvE.CanUse(out act)) return true; - //Single - if (GemshinePvE.CanUse(out act)) return true; - - if (!IsMoving && AddCrimsonCyclone && CrimsonCyclonePvE.CanUse(out act, skipAoeCheck: true)) return true; - - if ((Player.HasStatus(false, StatusID.SearingLight) || SearingLightPvE.Cooldown.IsCoolingDown) && SummonBahamutPvE.CanUse(out act)) return true; - - if (!SummonBahamutPvE.EnoughLevel && HasHostilesInRange && AetherchargePvE.CanUse(out act)) return true; - - if (IsMoving && (Player.HasStatus(true, StatusID.GarudasFavor) || InIfrit) - && !Player.HasStatus(true, StatusID.Swiftcast) && !InBahamut && !InPhoenix - && RuinIvPvE.CanUse(out act, skipAoeCheck: true)) return true; - - switch (SummonOrder) - { - case SummonOrderType.TopazEmeraldRuby: - default: - if (SummonTopazPvE.CanUse(out act)) return true; - if (SummonEmeraldPvE.CanUse(out act)) return true; - if (SummonRubyPvE.CanUse(out act)) return true; - break; - - case SummonOrderType.TopazRubyEmerald: - if (SummonTopazPvE.CanUse(out act)) return true; - if (SummonRubyPvE.CanUse(out act)) return true; - if (SummonEmeraldPvE.CanUse(out act)) return true; - break; - - case SummonOrderType.EmeraldTopazRuby: - if (SummonEmeraldPvE.CanUse(out act)) return true; - if (SummonTopazPvE.CanUse(out act)) return true; - if (SummonRubyPvE.CanUse(out act)) return true; - break; - } - - if (SummonTimeEndAfterGCD() && AttunmentTimeEndAfterGCD() && - !Player.HasStatus(true, StatusID.Swiftcast) && !InBahamut && !InPhoenix && - RuinIvPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (OutburstPvE.CanUse(out act)) return true; - - if (RuinPvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - #endregion - - #region Extra Methods - public override bool CanHealSingleSpell => false; - - #endregion -} \ No newline at end of file diff --git a/BasicRotations/Melee/DRG_Default.cs b/BasicRotations/Melee/DRG_Default.cs index 0b97331..dd9d41e 100644 --- a/BasicRotations/Melee/DRG_Default.cs +++ b/BasicRotations/Melee/DRG_Default.cs @@ -8,6 +8,9 @@ public sealed class DRG_Default : DragoonRotation { #region Config Options [RotationDesc(ActionID.SpineshatterDivePvE, ActionID.DragonfireDivePvE)] + + [RotationConfig(CombatType.PvE, Name = "Break Single Target Combo to AOE when time to AOE")] + public bool DoomSpikeWhenever { get; set; } = true; #endregion #region Move Logic @@ -83,9 +86,11 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) #region GCD Logic protected override bool GeneralGCD(out IAction? act) { + var doomSpikeRightNow = DoomSpikeWhenever; + if (CoerthanTormentPvE.CanUse(out act)) return true; if (SonicThrustPvE.CanUse(out act)) return true; - if (DoomSpikePvE.CanUse(out act)) return true; + if (DoomSpikePvE.CanUse(out act, skipComboCheck: doomSpikeRightNow)) return true; if (WheelingThrustPvE.CanUse(out act)) return true; diff --git a/BasicRotations/Melee/DRG_zBeta.cs b/BasicRotations/Melee/DRG_zBeta.cs deleted file mode 100644 index 1224f22..0000000 --- a/BasicRotations/Melee/DRG_zBeta.cs +++ /dev/null @@ -1,115 +0,0 @@ -namespace DefaultRotations.Melee; - -[Rotation("Beta", CombatType.PvE, GameVersion = "6.58")] -[SourceCode(Path = "main/DefaultRotations/Melee/DRG_zBeta.cs")] -[Api(1)] - -public sealed class DRG_zBeta : DragoonRotation -{ - #region Config Options - [RotationDesc(ActionID.SpineshatterDivePvE, ActionID.DragonfireDivePvE)] - - [RotationConfig(CombatType.PvE, Name = "Break Single Target for AOE cause why the heck not let's test it")] - public bool DoomSpikeWhenever { get; set; } = true; - #endregion - - #region Move Logic - protected override bool MoveForwardAbility(IAction nextGCD, out IAction act) - { - if (SpineshatterDivePvE.CanUse(out act)) return true; - if (DragonfireDivePvE.CanUse(out act, skipAoeCheck: true)) return true; - - return false; - } - - #endregion - - #region oGCD Logic - protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) - { - if (nextGCD.IsTheSameTo(true, FullThrustPvE, CoerthanTormentPvE) - || Player.HasStatus(true, StatusID.LanceCharge) && nextGCD.IsTheSameTo(false, FangAndClawPvE)) - { - if (LifeSurgePvE.CanUse(out act, onLastAbility: true, usedUp: true)) return true; - } - - return base.EmergencyAbility(nextGCD, out act); - } - - - - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - if (IsBurst && InCombat) - { - if (LanceChargePvE.CanUse(out act, skipAoeCheck: true) && Player.HasStatus(true, StatusID.PowerSurge)) return true; - if (LanceChargePvE.CanUse(out act, skipAoeCheck: true, onLastAbility: true) && !Player.HasStatus(true, StatusID.PowerSurge)) return true; - - if (DragonSightPvE.CanUse(out act, skipAoeCheck: true)) return true; - if (BattleLitanyPvE.CanUse(out act, skipAoeCheck: true)) return true; - } - - if (NastrondPvE.CanUse(out act, skipAoeCheck: true)) return true; - if (StardiverPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (HighJumpPvE.EnoughLevel) - { - if (HighJumpPvE.CanUse(out act)) return true; - } - else - { - if (JumpPvE.CanUse(out act)) return true; - } - - if (GeirskogulPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (SpineshatterDivePvE.CanUse(out act, usedUp: true)) - { - if (Player.HasStatus(true, StatusID.LanceCharge) && LanceChargePvE.Cooldown.ElapsedOneChargeAfterGCD(3)) return true; - } - if (Player.HasStatus(true, StatusID.PowerSurge) && SpineshatterDivePvE.Cooldown.CurrentCharges != 1 && SpineshatterDivePvE.CanUse(out act)) return true; - - if (MirageDivePvE.CanUse(out act)) return true; - - if (DragonfireDivePvE.CanUse(out act, skipAoeCheck: true)) - { - if (Player.HasStatus(true, StatusID.LanceCharge) && LanceChargePvE.Cooldown.ElapsedOneChargeAfterGCD(3)) return true; - } - - if (WyrmwindThrustPvE.CanUse(out act, skipAoeCheck: true)) return true; - if (MergedStatus.HasFlag(AutoStatus.MoveForward) && MoveForwardAbility(nextGCD, out act)) return true; - - return base.AttackAbility(nextGCD, out act); - } - #endregion - - #region GCD Logic - protected override bool GeneralGCD(out IAction? act) - { - var doomSpikeRightMeow = DoomSpikeWhenever; - - if (CoerthanTormentPvE.CanUse(out act)) return true; - if (SonicThrustPvE.CanUse(out act)) return true; - if (DoomSpikePvE.CanUse(out act, skipComboCheck: doomSpikeRightMeow)) return true; - - - if (WheelingThrustPvE.CanUse(out act)) return true; - if (FangAndClawPvE.CanUse(out act)) return true; - - - if (FullThrustPvE.CanUse(out act)) return true; - if (ChaosThrustPvE.CanUse(out act)) return true; - - if (Player.WillStatusEndGCD(5, 0, true, StatusID.PowerSurge_2720)) - { - if (DisembowelPvE.CanUse(out act)) return true; - } - - if (VorpalThrustPvE.CanUse(out act)) return true; - if (TrueThrustPvE.CanUse(out act)) return true; - if (PiercingTalonPvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - #endregion -} diff --git a/BasicRotations/Melee/NIN_Default.cs b/BasicRotations/Melee/NIN_Default.cs index 75c45bf..7cb7d4d 100644 --- a/BasicRotations/Melee/NIN_Default.cs +++ b/BasicRotations/Melee/NIN_Default.cs @@ -5,33 +5,24 @@ namespace DefaultRotations.Melee; [Api(1)] public sealed class NIN_Default : NinjaRotation { - private IBaseAction? _ninActionAim = null; // Holds the next ninjutsu action to perform. - - // Determines if Trick Attack is in its effective period. - private bool InTrickAttack => TrickAttackPvE.Cooldown.IsCoolingDown && !TrickAttackPvE.Cooldown.ElapsedAfter(17); - - // Determines if Mug is in its effective period. - private bool InMug => MugPvE.Cooldown.IsCoolingDown && !MugPvE.Cooldown.ElapsedAfter(19); - - // Checks if no ninjutsu action is currently selected or if the Rabbit Medium has been invoked. - private static bool NoNinjutsu => AdjustId(ActionID.NinjutsuPvE) is ActionID.NinjutsuPvE or ActionID.RabbitMediumPvE; - + #region Config Options // Configuration properties for rotation behavior. [RotationConfig(CombatType.PvE, Name = "Use Hide")] public bool UseHide { get; set; } = true; [RotationConfig(CombatType.PvE, Name = "Use Unhide")] public bool AutoUnhide { get; set; } = true; + #endregion + #region CountDown Logic // Logic to determine the action to take during the countdown phase before combat starts. - #region CountDown protected override IAction? CountDownAction(float remainTime) { - + // Clears ninjutsu setup if countdown is more than 10 seconds or if Huton is the aim but shouldn't be. if (remainTime > 10) ClearNinjutsu(); var realInHuton = !HutonEndAfterGCD() || IsLastAction(false, HutonPvE); if (realInHuton && _ninActionAim == HutonPvE) ClearNinjutsu(); - + // Decision-making for ninjutsu actions based on remaining time until combat starts. if (DoNinjutsu(out var act)) { @@ -55,15 +46,15 @@ public sealed class NIN_Default : NinjaRotation return base.CountDownAction(remainTime); } #endregion - - #region Ninjutsu Management + + #region Ninjutsu Logic // Sets the target ninjutsu action to be performed next. // If the action is null, or currently set to Rabbit Medium (indicating a failed Ninjutsu attempt), it exits early. // If the current action aim is not null and the last action matches certain conditions, it exits early. // Finally, updates the current ninjutsu action aim if it's different from the incoming action. private void SetNinjutsu(IBaseAction act) { - + if (act == null || AdjustId(ActionID.NinjutsuPvE) == ActionID.RabbitMediumPvE) return; if (_ninActionAim != null && IsLastAction(false, TenPvE, JinPvE, ChiPvE, FumaShurikenPvE_18873, FumaShurikenPvE_18874, FumaShurikenPvE_18875)) return; @@ -73,7 +64,7 @@ private void SetNinjutsu(IBaseAction act) _ninActionAim = act; } } - + // Clears the ninjutsu action aim, effectively resetting any planned ninjutsu action. private void ClearNinjutsu() { @@ -82,7 +73,7 @@ private void ClearNinjutsu() _ninActionAim = null; } } - + // Logic for choosing which ninjutsu action to set up next, based on various game state conditions. private bool ChoiceNinjutsu(out IAction? act) { @@ -152,15 +143,14 @@ private bool ChoiceNinjutsu(out IAction? act) //Aoe if (KatonPvE.CanUse(out _)) { - if (!Player.HasStatus(true, StatusID.Doton) && !IsMoving - && (!TenChiJinPvE.Cooldown.WillHaveOneCharge(6)) || !TenChiJinPvE.Cooldown.IsCoolingDown) + if (!Player.HasStatus(true, StatusID.Doton) && !IsMoving && !IsLastGCD(false, DotonPvE) && (!TenChiJinPvE.Cooldown.WillHaveOneCharge(6)) || !TenChiJinPvE.Cooldown.IsCoolingDown) SetNinjutsu(DotonPvE); else SetNinjutsu(KatonPvE); return false; } //Vulnerable - if (IsBurst && TrickAttackPvE.Cooldown.WillHaveOneCharge(18) && SuitonPvE.CanUse(out _)) + if (IsBurst && TrickAttackPvE.Cooldown.WillHaveOneCharge(18) && SuitonPvE.CanUse(out _) && !Player.HasStatus(true, StatusID.Suiton)) { SetNinjutsu(SuitonPvE); return false; @@ -193,7 +183,9 @@ private bool ChoiceNinjutsu(out IAction? act) } return false; // Indicates that no specific Ninjutsu action was chosen in this cycle. } - + #endregion + + #region Ninjutsu Execution // Attempts to perform a ninjutsu action, based on the current game state and conditions. private bool DoNinjutsu(out IAction? act) { @@ -229,7 +221,7 @@ private bool DoNinjutsu(out IAction? act) { if (RaitonPvE_18877.CanUse(out act, skipAoeCheck: true)) return true; } - else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880)) + else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880) && !Player.HasStatus(true, StatusID.Doton)) { if (DotonPvE_18880.CanUse(out act, skipAoeCheck: true)) return true; } @@ -300,56 +292,8 @@ private bool DoNinjutsu(out IAction? act) } #endregion - - // Main method for determining the general action to take during the combat's global cooldown phase. - #region GeneralGCD - protected override bool GeneralGCD(out IAction? act) - { - var hasRaijuReady = Player.HasStatus(true, StatusID.RaijuReady); - - if ((InTrickAttack || InMug) && NoNinjutsu && !hasRaijuReady - && !Player.HasStatus(true, StatusID.TenChiJin) - && PhantomKamaitachiPvE.CanUse(out act)) return true; - - if (ChoiceNinjutsu(out act)) return true; - if ((!InCombat || !CombatElapsedLess(7)) && DoNinjutsu(out act)) return true; - - //No Ninjutsu - if (NoNinjutsu) - { - if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true; - if (hasRaijuReady) return false; - } - - if (HuraijinPvE.CanUse(out act)) return true; - - //AOE - if (HakkeMujinsatsuPvE.CanUse(out act)) return true; - if (DeathBlossomPvE.CanUse(out act)) return true; - - //Single - if (ArmorCrushPvE.CanUse(out act)) return true; - if (AeolianEdgePvE.CanUse(out act)) return true; - if (GustSlashPvE.CanUse(out act)) return true; - if (SpinningEdgePvE.CanUse(out act)) return true; - - //Range - - if (ThrowingDaggerPvE.CanUse(out act)) return true; - - if (AutoUnhide) - { - StatusHelper.StatusOff(StatusID.Hidden); - } - if (!InCombat && _ninActionAim == null && UseHide - && TenPvE.Cooldown.IsCoolingDown && HidePvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - #endregion - + #region Move Logic // Defines logic for actions to take when moving forward during combat. - #region MoveForwardGCD // This attribute associates the method with the Forked Raiju PvE action, // indicating it's a relevant ability when considering movement-based actions. [RotationDesc(ActionID.ForkedRaijuPvE)] @@ -357,67 +301,64 @@ protected override bool MoveForwardGCD(out IAction? act) { // Initializes the action to null, indicating no action has been chosen yet. act = null; - + // Checks if Forked Raiju, a movement-friendly ability, can be used. // If so, sets it as the action to perform, returning true to indicate an action has been selected. if (ForkedRaijuPvE.CanUse(out act)) return true; - + // If Forked Raiju is not available or not the best option, // falls back to the base class's logic for choosing a move-forward action. return base.MoveForwardGCD(out act); } #endregion - - #region EmergencyAbility + #region oGCD Logic // Determines the emergency abilities to use, overriding the base class implementation. protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) { // Initializes the action to null, indicating no action has been chosen yet. act = null; - + // If Ninjutsu is available or not in combat, defers to the base class's emergency ability logic. if (!NoNinjutsu || !InCombat) return base.EmergencyAbility(nextGCD, out act); - + // First priority is given to Kassatsu if it's available, allowing for an immediate powerful Ninjutsu. if (KassatsuPvE.CanUse(out act)) return true; - + // Next, checks if a burst medicine is available and appropriate to use. if (UseBurstMedicine(out act)) return true; - + // If in a burst phase and not just starting combat, checks if Mug is available to generate additional Ninki. if (IsBurst && !CombatElapsedLess(5) && MugPvE.CanUse(out act)) return true; - + // Prioritizes using Suiton and Trick Attack for maximizing damage, especially outside the initial combat phase. if (!CombatElapsedLess(6)) { // Attempts to use Trick Attack if it's available. if (TrickAttackPvE.CanUse(out act)) return true; - + // If Trick Attack is on cooldown but will not be ready soon, considers using Meisui to recover Ninki. if (TrickAttackPvE.Cooldown.IsCoolingDown && !TrickAttackPvE.Cooldown.WillHaveOneCharge(19) && MeisuiPvE.CanUse(out act)) return true; } - + // If none of the specific conditions are met, falls back to the base class's emergency ability logic. return base.EmergencyAbility(nextGCD, out act); } - #endregion - + // Defines attack abilities to use during combat, overriding the base class implementation. - #region AttackAbility protected override bool AttackAbility(IAction nextGCD, out IAction? act) { act = null; // If Ninjutsu is available or not in combat, it exits early, indicating no attack action to perform. if (!NoNinjutsu || !InCombat) return false; - + // If the player is not moving, 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 (!IsMoving && InTrickAttack && !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; - + // Special handling if within Trick Attack's effective window: if (InTrickAttack) { @@ -432,7 +373,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) if (DreamWithinADreamPvE.CanUse(out act)) return true; } } - + // Checks for the use of Hellfrog Medium or Bhavacakra under certain conditions: // - Not in the Mug's effective window or within Trick Attack's window // - Certain cooldown conditions are met, or specific statuses are active. @@ -448,13 +389,74 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) } #endregion + #region GCD Logic + // Main method for determining the general action to take during the combat's global cooldown phase. + protected override bool GeneralGCD(out IAction? act) + { + var hasRaijuReady = Player.HasStatus(true, StatusID.RaijuReady); + + if ((InTrickAttack || InMug) && NoNinjutsu && !hasRaijuReady + && !Player.HasStatus(true, StatusID.TenChiJin) + && PhantomKamaitachiPvE.CanUse(out act)) return true; + + if (ChoiceNinjutsu(out act)) return true; + if ((!InCombat || !CombatElapsedLess(7)) && DoNinjutsu(out act)) return true; + + //No Ninjutsu + if (NoNinjutsu) + { + if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true; + if (hasRaijuReady) return false; + } + + if (HuraijinPvE.CanUse(out act)) return true; + + //AOE + if (HakkeMujinsatsuPvE.CanUse(out act)) return true; + if (DeathBlossomPvE.CanUse(out act)) return true; + + //Single + if (ArmorCrushPvE.CanUse(out act)) return true; + if (AeolianEdgePvE.CanUse(out act)) return true; + if (GustSlashPvE.CanUse(out act)) return true; + if (SpinningEdgePvE.CanUse(out act)) return true; + + //Range + + if (ThrowingDaggerPvE.CanUse(out act)) return true; + + if (AutoUnhide) + { + StatusHelper.StatusOff(StatusID.Hidden); + } + if (!InCombat && _ninActionAim == null && UseHide + && TenPvE.Cooldown.IsCoolingDown && HidePvE.CanUse(out act)) return true; + + return base.GeneralGCD(out act); + } + #endregion + + #region Extra Methods + // Holds the next ninjutsu action to perform. + private IBaseAction? _ninActionAim = null; + + // Determines if Trick Attack is in its effective period. + private bool InTrickAttack => TrickAttackPvE.Cooldown.IsCoolingDown && !TrickAttackPvE.Cooldown.ElapsedAfter(17); + + // Determines if Mug is in its effective period. + private bool InMug => MugPvE.Cooldown.IsCoolingDown && !MugPvE.Cooldown.ElapsedAfter(19); + + // Checks if no ninjutsu action is currently selected or if the Rabbit Medium has been invoked. + private static bool NoNinjutsu => AdjustId(ActionID.NinjutsuPvE) is ActionID.NinjutsuPvE or ActionID.RabbitMediumPvE; + // Displays the current status of the rotation, including the aimed ninjutsu action, if any. public override void DisplayStatus() { - if(_ninActionAim != null) + if (_ninActionAim != null) { - ImGui.Text(_ninActionAim.ToString() + _ninActionAim.AdjustedID.ToString()); + ImGui.Text(_ninActionAim.ToString() + _ninActionAim.AdjustedID.ToString()); } base.DisplayStatus(); } -} + #endregion +} \ No newline at end of file diff --git a/BasicRotations/Melee/NIN_zBeta.cs b/BasicRotations/Melee/NIN_zBeta.cs deleted file mode 100644 index cc18acb..0000000 --- a/BasicRotations/Melee/NIN_zBeta.cs +++ /dev/null @@ -1,462 +0,0 @@ -namespace DefaultRotations.Melee; - -[Rotation("NIN Beta Rotation", CombatType.PvE, GameVersion = "6.58")] -[SourceCode(Path = "main/DefaultRotations/Melee/NIN_zBeta.cs")] -[Api(1)] -public sealed class NIN_zBeta : NinjaRotation -{ - #region Config Options - // Configuration properties for rotation behavior. - [RotationConfig(CombatType.PvE, Name = "Use Hide")] - public bool UseHide { get; set; } = true; - [RotationConfig(CombatType.PvE, Name = "Use Unhide")] - public bool AutoUnhide { get; set; } = true; - #endregion - - #region CountDown Logic - // Logic to determine the action to take during the countdown phase before combat starts. - protected override IAction? CountDownAction(float remainTime) - { - - // Clears ninjutsu setup if countdown is more than 10 seconds or if Huton is the aim but shouldn't be. - if (remainTime > 10) ClearNinjutsu(); - var realInHuton = !HutonEndAfterGCD() || IsLastAction(false, HutonPvE); - if (realInHuton && _ninActionAim == HutonPvE) ClearNinjutsu(); - - // Decision-making for ninjutsu actions based on remaining time until combat starts. - if (DoNinjutsu(out var act)) - { - if (act == SuitonPvE && remainTime > CountDownAhead) return null; - return act; - } - - else if (remainTime < 5) - { - SetNinjutsu(SuitonPvE); - } - else if (remainTime < 10) - { - // If within 10 seconds to start, consider using Hide or setting up Huton. - if (_ninActionAim == null && TenPvE.Cooldown.IsCoolingDown && HidePvE.CanUse(out act)) return act; - if (!realInHuton) - { - SetNinjutsu(HutonPvE); - } - } - return base.CountDownAction(remainTime); - } - #endregion - - #region Ninjutsu Logic - // Sets the target ninjutsu action to be performed next. - // If the action is null, or currently set to Rabbit Medium (indicating a failed Ninjutsu attempt), it exits early. - // If the current action aim is not null and the last action matches certain conditions, it exits early. - // Finally, updates the current ninjutsu action aim if it's different from the incoming action. - private void SetNinjutsu(IBaseAction act) - { - - if (act == null || AdjustId(ActionID.NinjutsuPvE) == ActionID.RabbitMediumPvE) return; - - if (_ninActionAim != null && IsLastAction(false, TenPvE, JinPvE, ChiPvE, FumaShurikenPvE_18873, FumaShurikenPvE_18874, FumaShurikenPvE_18875)) return; - - if (_ninActionAim != act) - { - _ninActionAim = act; - } - } - - // Clears the ninjutsu action aim, effectively resetting any planned ninjutsu action. - private void ClearNinjutsu() - { - if (_ninActionAim != null) - { - _ninActionAim = null; - } - } - - // Logic for choosing which ninjutsu action to set up next, based on various game state conditions. - private bool ChoiceNinjutsu(out IAction? act) - { - act = null; - // Ensures that the action ID currently considered for Ninjutsu is actually valid for Ninjutsu execution. - 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(); - // Prevents choosing a new Ninjutsu if the timing is too tight. - if (_ninActionAim != null && WeaponRemain < 0.1) return false; - - // Checks for Kassatsu status to prioritize high-impact Ninjutsu due to its buff. - if (Player.HasStatus(true, StatusID.Kassatsu)) - { - // 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 _)) - { - SetNinjutsu(GokaMekkyakuPvE); - return false; - } - if (HyoshoRanryuPvE.CanUse(out _)) - { - SetNinjutsu(HyoshoRanryuPvE); - return false; - } - - if (KatonPvE.CanUse(out _)) - { - SetNinjutsu(KatonPvE); - return false; - } - - if (RaitonPvE.CanUse(out _)) - { - SetNinjutsu(RaitonPvE); - return false; - } - } - else - { - // If Suiton is active but no specific Ninjutsu is currently aimed, it clears the Ninjutsu aim. - // This check is relevant for managing Suiton's effect, particularly for enabling Trick Attack. - if (Player.HasStatus(true, StatusID.Suiton) - && _ninActionAim == SuitonPvE && NoNinjutsu) - { - ClearNinjutsu(); - } - - // Chooses buffs or AoE actions based on combat conditions and cooldowns. - // For instance, setting Huton for speed buff or choosing AoE Ninjutsu like Katon or Doton based on enemy positioning. - // Also considers using Suiton for vulnerability debuff on the enemy if conditions are optimal. - if (HuraijinPvE.CanUse(out act)) return true; - if (!HutonEndAfterGCD() && _ninActionAim?.ID == HutonPvE.ID) - { - ClearNinjutsu(); - return false; - } - if (TenPvE.CanUse(out _, usedUp: true) - && (!InCombat || !HuraijinPvE.EnoughLevel) && HutonPvE.CanUse(out _) - && !IsLastAction(false, HutonPvE)) - { - SetNinjutsu(HutonPvE); - return false; - } - - //Aoe - if (KatonPvE.CanUse(out _)) - { - if (!Player.HasStatus(true, StatusID.Doton) && !IsMoving && !IsLastGCD(false, DotonPvE) && (!TenChiJinPvE.Cooldown.WillHaveOneCharge(6)) || !TenChiJinPvE.Cooldown.IsCoolingDown) - SetNinjutsu(DotonPvE); - else SetNinjutsu(KatonPvE); - return false; - } - - //Vulnerable - if (IsBurst && TrickAttackPvE.Cooldown.WillHaveOneCharge(18) && SuitonPvE.CanUse(out _) && !Player.HasStatus(true, StatusID.Suiton)) - { - SetNinjutsu(SuitonPvE); - return false; - } - - //Single - if (TenPvE.CanUse(out _, usedUp: InTrickAttack && !Player.HasStatus(false, StatusID.RaijuReady))) - { - if (RaitonPvE.CanUse(out _)) - { - SetNinjutsu(RaitonPvE); - return false; - } - - if (!ChiPvE.EnoughLevel && FumaShurikenPvE.CanUse(out _)) - { - SetNinjutsu(FumaShurikenPvE); - 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 - - #region Ninjutsu Execution - // Attempts to perform a ninjutsu action, based on the current game state and conditions. - private bool DoNinjutsu(out IAction? act) - { - act = null; - - //TenChiJin - if (Player.HasStatus(true, StatusID.TenChiJin)) - { - uint tenId = AdjustId(TenPvE.ID); - uint chiId = AdjustId(ChiPvE.ID); - uint jinId = AdjustId(JinPvE.ID); - - //First - if (tenId == FumaShurikenPvE_18873.ID - && !IsLastAction(false, FumaShurikenPvE_18875, FumaShurikenPvE_18873)) - { - //AOE - if (KatonPvE.CanUse(out _)) - { - if (FumaShurikenPvE_18875.CanUse(out act)) return true; - } - //Single - if (FumaShurikenPvE_18873.CanUse(out act)) return true; - } - - //Second - else if (tenId == KatonPvE_18876.ID && !IsLastAction(false, KatonPvE_18876)) - { - if (KatonPvE_18876.CanUse(out act, skipAoeCheck: true)) return true; - } - //Others - else if (chiId == RaitonPvE_18877.ID && !IsLastAction(false, RaitonPvE_18877)) - { - if (RaitonPvE_18877.CanUse(out act, skipAoeCheck: true)) return true; - } - else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880) && !Player.HasStatus(true, StatusID.Doton)) - { - if (DotonPvE_18880.CanUse(out act, skipAoeCheck: true)) return true; - } - else if (jinId == SuitonPvE_18881.ID && !IsLastAction(false, SuitonPvE_18881)) - { - if (SuitonPvE_18881.CanUse(out act, skipAoeCheck: true)) return true; - } - } - - //Keep Kassatsu in Burst. - if (!Player.WillStatusEnd(3, false, StatusID.Kassatsu) - && Player.HasStatus(false, StatusID.Kassatsu) && !InTrickAttack) return false; - if (_ninActionAim == null) return false; - - var id = AdjustId(ActionID.NinjutsuPvE); - - //Failed - if ((uint)id == RabbitMediumPvE.ID) - { - ClearNinjutsu(); - act = null; - return false; - } - //First - else if (id == ActionID.NinjutsuPvE) - { - //Can't use. - if (!Player.HasStatus(true, StatusID.Kassatsu, StatusID.TenChiJin) - && !TenPvE.CanUse(out _, usedUp: true) - && !IsLastAction(false, _ninActionAim.Setting.Ninjutsu![0])) - { - return false; - } - act = _ninActionAim.Setting.Ninjutsu![0]; - return true; - } - //Finished - else if ((uint)id == _ninActionAim.ID) - { - if (_ninActionAim.CanUse(out act, skipAoeCheck: true)) return true; - if (_ninActionAim.ID == DotonPvE.ID && !InCombat) - { - act = _ninActionAim; - return true; - } - } - //Second - else if ((uint)id == FumaShurikenPvE.ID) - { - if (_ninActionAim.Setting.Ninjutsu!.Length > 1 - && !IsLastAction(false, _ninActionAim.Setting.Ninjutsu![1])) - { - act = _ninActionAim.Setting.Ninjutsu![1]; - return true; - } - } - //Third - else if ((uint)id == KatonPvE.ID || (uint)id == RaitonPvE.ID || (uint)id == HyotonPvE.ID) - { - if (_ninActionAim.Setting.Ninjutsu!.Length > 2 - && !IsLastAction(false, _ninActionAim.Setting.Ninjutsu![2])) - { - act = _ninActionAim.Setting.Ninjutsu![2]; - return true; - } - } - return false; - } - #endregion - - #region Move Logic - // Defines logic for actions to take when moving forward during combat. - // This attribute associates the method with the Forked Raiju PvE action, - // indicating it's a relevant ability when considering movement-based actions. - [RotationDesc(ActionID.ForkedRaijuPvE)] - protected override bool MoveForwardGCD(out IAction? act) - { - // Initializes the action to null, indicating no action has been chosen yet. - act = null; - - // Checks if Forked Raiju, a movement-friendly ability, can be used. - // If so, sets it as the action to perform, returning true to indicate an action has been selected. - if (ForkedRaijuPvE.CanUse(out act)) return true; - - // If Forked Raiju is not available or not the best option, - // falls back to the base class's logic for choosing a move-forward action. - return base.MoveForwardGCD(out act); - } - #endregion - - #region oGCD Logic - // Determines the emergency abilities to use, overriding the base class implementation. - protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) - { - // Initializes the action to null, indicating no action has been chosen yet. - act = null; - - // If Ninjutsu is available or not in combat, defers to the base class's emergency ability logic. - if (!NoNinjutsu || !InCombat) return base.EmergencyAbility(nextGCD, out act); - - // First priority is given to Kassatsu if it's available, allowing for an immediate powerful Ninjutsu. - if (KassatsuPvE.CanUse(out act)) return true; - - // Next, checks if a burst medicine is available and appropriate to use. - if (UseBurstMedicine(out act)) return true; - - // If in a burst phase and not just starting combat, checks if Mug is available to generate additional Ninki. - if (IsBurst && !CombatElapsedLess(5) && MugPvE.CanUse(out act)) return true; - - // Prioritizes using Suiton and Trick Attack for maximizing damage, especially outside the initial combat phase. - if (!CombatElapsedLess(6)) - { - // Attempts to use Trick Attack if it's available. - if (TrickAttackPvE.CanUse(out act)) return true; - - // If Trick Attack is on cooldown but will not be ready soon, considers using Meisui to recover Ninki. - if (TrickAttackPvE.Cooldown.IsCoolingDown && !TrickAttackPvE.Cooldown.WillHaveOneCharge(19) && MeisuiPvE.CanUse(out act)) return true; - } - - // If none of the specific conditions are met, falls back to the base class's emergency ability logic. - return base.EmergencyAbility(nextGCD, out act); - } - - // Defines attack abilities to use during combat, overriding the base class implementation. - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - act = null; - // If Ninjutsu is available or not in combat, it exits early, indicating no attack action to perform. - if (!NoNinjutsu || !InCombat) return false; - - // If the player is not moving, 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 (!IsMoving && InTrickAttack && !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; - - // Special handling if within Trick Attack's effective window: - if (InTrickAttack) - { - // If Dream Within A Dream is not yet available, checks if Assassinate can be used. - if (!DreamWithinADreamPvE.EnoughLevel) - { - if (AssassinatePvE.CanUse(out act)) return true; - } - else - { - // If Dream Within A Dream is available, it's set as the next action. - if (DreamWithinADreamPvE.CanUse(out act)) return true; - } - } - - // Checks for the use of Hellfrog Medium or Bhavacakra under certain conditions: - // - Not in the Mug's effective window or within Trick Attack's window - // - Certain cooldown conditions are met, or specific statuses are active. - if ((!InMug || InTrickAttack) - && (!BunshinPvE.Cooldown.WillHaveOneCharge(10) || Player.HasStatus(false, StatusID.PhantomKamaitachiReady) || MugPvE.Cooldown.WillHaveOneCharge(2))) - { - if (HellfrogMediumPvE.CanUse(out act)) return true; - if (BhavacakraPvE.CanUse(out act)) return true; - } - if (MergedStatus.HasFlag(AutoStatus.MoveForward) && MoveForwardAbility(nextGCD, out act)) return true; - // If none of the conditions are met, it falls back to the base class's implementation for attack ability. - return base.AttackAbility(nextGCD, out act); - } - #endregion - - #region GCD Logic - // Main method for determining the general action to take during the combat's global cooldown phase. - protected override bool GeneralGCD(out IAction? act) - { - var hasRaijuReady = Player.HasStatus(true, StatusID.RaijuReady); - - if ((InTrickAttack || InMug) && NoNinjutsu && !hasRaijuReady - && !Player.HasStatus(true, StatusID.TenChiJin) - && PhantomKamaitachiPvE.CanUse(out act)) return true; - - if (ChoiceNinjutsu(out act)) return true; - if ((!InCombat || !CombatElapsedLess(7)) && DoNinjutsu(out act)) return true; - - //No Ninjutsu - if (NoNinjutsu) - { - if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true; - if (hasRaijuReady) return false; - } - - if (HuraijinPvE.CanUse(out act)) return true; - - //AOE - if (HakkeMujinsatsuPvE.CanUse(out act)) return true; - if (DeathBlossomPvE.CanUse(out act)) return true; - - //Single - if (ArmorCrushPvE.CanUse(out act)) return true; - if (AeolianEdgePvE.CanUse(out act)) return true; - if (GustSlashPvE.CanUse(out act)) return true; - if (SpinningEdgePvE.CanUse(out act)) return true; - - //Range - - if (ThrowingDaggerPvE.CanUse(out act)) return true; - - if (AutoUnhide) - { - StatusHelper.StatusOff(StatusID.Hidden); - } - if (!InCombat && _ninActionAim == null && UseHide - && TenPvE.Cooldown.IsCoolingDown && HidePvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - #endregion - - #region Extra Methods - // Holds the next ninjutsu action to perform. - private IBaseAction? _ninActionAim = null; - - // Determines if Trick Attack is in its effective period. - private bool InTrickAttack => TrickAttackPvE.Cooldown.IsCoolingDown && !TrickAttackPvE.Cooldown.ElapsedAfter(17); - - // Determines if Mug is in its effective period. - private bool InMug => MugPvE.Cooldown.IsCoolingDown && !MugPvE.Cooldown.ElapsedAfter(19); - - // Checks if no ninjutsu action is currently selected or if the Rabbit Medium has been invoked. - private static bool NoNinjutsu => AdjustId(ActionID.NinjutsuPvE) is ActionID.NinjutsuPvE or ActionID.RabbitMediumPvE; - - // Displays the current status of the rotation, including the aimed ninjutsu action, if any. - public override void DisplayStatus() - { - if (_ninActionAim != null) - { - ImGui.Text(_ninActionAim.ToString() + _ninActionAim.AdjustedID.ToString()); - } - base.DisplayStatus(); - } - #endregion -} \ No newline at end of file diff --git a/BasicRotations/Melee/SAM_Default.cs b/BasicRotations/Melee/SAM_Default.cs index 972211e..bd16c0b 100644 --- a/BasicRotations/Melee/SAM_Default.cs +++ b/BasicRotations/Melee/SAM_Default.cs @@ -33,7 +33,10 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) if (Kenki <= 50 && IkishotenPvE.CanUse(out act)) return true; - if ((HostileTarget?.HasStatus(true, StatusID.Higanbana) ?? false) && (HostileTarget?.WillStatusEnd(32, true, StatusID.Higanbana) ?? false) && !(HostileTarget?.WillStatusEnd(28, true, StatusID.Higanbana) ?? false) && SenCount == 1 && IsLastAction(true, YukikazePvE) && !HaveMeikyoShisui) + if ((HostileTarget?.HasStatus(true, StatusID.Higanbana) ?? false) && + (HostileTarget?.WillStatusEnd(32, true, StatusID.Higanbana) ?? false) && + !(HostileTarget?.WillStatusEnd(28, true, StatusID.Higanbana) ?? false) && + SenCount == 1 && IsLastAction(true, YukikazePvE) && !HaveMeikyoShisui) { if (HagakurePvE.CanUse(out act)) return true; } @@ -87,7 +90,7 @@ protected override bool GeneralGCD(out IAction? act) if (SenCount == 1 && IsTargetBoss && !IsTargetDying) { - if (HasMoon && HasFlower && HiganbanaPvE.CanUse(out act)) return true; + if (HasMoon && HasFlower && !FugaPvE.CanUse(out _) && HiganbanaPvE.CanUse(out act)) return true; } if (SenCount == 2) { @@ -98,8 +101,8 @@ protected override bool GeneralGCD(out IAction? act) if (MidareSetsugekkaPvE.CanUse(out act)) return true; } - if ((!HasMoon || IsMoonTimeLessThanFlower || !OkaPvE.EnoughLevel) && MangetsuPvE.CanUse(out act, skipAoeCheck: HaveMeikyoShisui && !HasGetsu)) return true; - if ((!HasFlower || !IsMoonTimeLessThanFlower) && OkaPvE.CanUse(out act, skipAoeCheck: HaveMeikyoShisui && !HasKa)) return true; + if ((!HasMoon || IsMoonTimeLessThanFlower || !OkaPvE.EnoughLevel) && MangetsuPvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && !HasGetsu)) return true; + if ((!HasFlower || !IsMoonTimeLessThanFlower) && OkaPvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && !HasKa)) return true; if (!HasSetsu && YukikazePvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && HasGetsu && HasKa)) return true; diff --git a/BasicRotations/Melee/SAM_zBeta.cs b/BasicRotations/Melee/SAM_zBeta.cs deleted file mode 100644 index c46ce7a..0000000 --- a/BasicRotations/Melee/SAM_zBeta.cs +++ /dev/null @@ -1,134 +0,0 @@ -namespace DefaultRotations.Melee; - -[Rotation("Beta", CombatType.PvE, GameVersion = "6.58")] -[SourceCode(Path = "main/DefaultRotations/Melee/SAM_zBeta.cs")] -[Api(1)] -public sealed class SAM_zBeta : SamuraiRotation -{ - #region Config Options - - [Range(0, 85, ConfigUnitType.None, 5)] - [RotationConfig(CombatType.PvE, Name = "Use Kenki above.")] - public int AddKenki { get; set; } = 50; - - #endregion - - #region Countdown Logic - - protected override IAction? CountDownAction(float remainTime) - { - if (remainTime <= 5 && MeikyoShisuiPvE.CanUse(out var act)) return act; - if (remainTime <= 2 && TrueNorthPvE.CanUse(out act)) return act; - return base.CountDownAction(remainTime); - } - - #endregion - - #region oGCD Logic - - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - var IsTargetBoss = HostileTarget?.IsBossFromTTK() ?? false; - var IsTargetDying = HostileTarget?.IsDying() ?? false; - - if (Kenki <= 50 && IkishotenPvE.CanUse(out act)) return true; - - if ((HostileTarget?.HasStatus(true, StatusID.Higanbana) ?? false) && - (HostileTarget?.WillStatusEnd(32, true, StatusID.Higanbana) ?? false) && - !(HostileTarget?.WillStatusEnd(28, true, StatusID.Higanbana) ?? false) && - SenCount == 1 && IsLastAction(true, YukikazePvE) && !HaveMeikyoShisui) - { - if (HagakurePvE.CanUse(out act)) return true; - } - - if (HasMoon && HasFlower) - { - if (HissatsuGurenPvE.CanUse(out act, skipAoeCheck: !HissatsuSeneiPvE.EnoughLevel)) return true; - if (HissatsuSeneiPvE.CanUse(out act)) return true; - } - - if (ShohaIiPvE.CanUse(out act)) return true; - if (ShohaPvE.CanUse(out act)) return true; - - if (Kenki >= 50 && IkishotenPvE.Cooldown.WillHaveOneCharge(10) || Kenki >= AddKenki || IsTargetBoss && IsTargetDying) - { - if (HissatsuKyutenPvE.CanUse(out act)) return true; - if (HissatsuShintenPvE.CanUse(out act)) return true; - } - - return base.AttackAbility(nextGCD, out act); - } - protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) - { - var IsTargetBoss = HostileTarget?.IsBossFromTTK() ?? false; - var IsTargetDying = HostileTarget?.IsDying() ?? false; - - if (HasHostilesInRange && IsLastGCD(true, YukikazePvE, MangetsuPvE, OkaPvE) && - (!IsTargetBoss || (HostileTarget?.HasStatus(true, StatusID.Higanbana) ?? false) && !(HostileTarget?.WillStatusEnd(40, true, StatusID.Higanbana) ?? false) || !HasMoon && !HasFlower || IsTargetBoss && IsTargetDying)) - { - if (MeikyoShisuiPvE.CanUse(out act, usedUp: true)) return true; - } - return base.EmergencyAbility(nextGCD, out act); - } - - #endregion - - #region GCD Logic - - protected override bool GeneralGCD(out IAction? act) - { - if (KaeshiNamikiriPvE.CanUse(out act, skipAoeCheck: true, usedUp: true)) return true; - - var IsTargetBoss = HostileTarget?.IsBossFromTTK() ?? false; - var IsTargetDying = HostileTarget?.IsDying() ?? false; - - if (KaeshiGokenPvE.CanUse(out act, skipAoeCheck: true, usedUp: true)) return true; - if (KaeshiSetsugekkaPvE.CanUse(out act, skipAoeCheck: true, usedUp: true)) return true; - - if ((!IsTargetBoss || (HostileTarget?.HasStatus(true, StatusID.Higanbana) ?? false)) && HasMoon && HasFlower - && OgiNamikiriPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (SenCount == 1 && IsTargetBoss && !IsTargetDying) - { - if (HasMoon && HasFlower && !FugaPvE.CanUse(out _) && HiganbanaPvE.CanUse(out act)) return true; - } - if (SenCount == 2) - { - if (TenkaGokenPvE.CanUse(out act, skipAoeCheck: !MidareSetsugekkaPvE.EnoughLevel)) return true; - } - if (SenCount == 3) - { - if (MidareSetsugekkaPvE.CanUse(out act)) return true; - } - - if ((!HasMoon || IsMoonTimeLessThanFlower || !OkaPvE.EnoughLevel) && MangetsuPvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && !HasGetsu)) return true; - if ((!HasFlower || !IsMoonTimeLessThanFlower) && OkaPvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && !HasKa)) return true; - - if (!HasSetsu && YukikazePvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && HasGetsu && HasKa)) return true; - - if (GekkoPvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && !HasGetsu)) return true; - if (KashaPvE.CanUse(out act, skipComboCheck: HaveMeikyoShisui && !HasKa)) return true; - - if ((!HasMoon || IsMoonTimeLessThanFlower || !ShifuPvE.EnoughLevel) && JinpuPvE.CanUse(out act)) return true; - if ((!HasFlower || !IsMoonTimeLessThanFlower) && ShifuPvE.CanUse(out act)) return true; - - if (FukoPvE.CanUse(out act, skipComboCheck: true)) return true; - if (!FukoPvE.EnoughLevel && FugaPvE.CanUse(out act, skipComboCheck: true)) return true; - - if (!HaveMeikyoShisui) - { - if (HakazePvE.CanUse(out act)) return true; - - if (EnpiPvE.CanUse(out act)) return true; - } - - return base.GeneralGCD(out act); - } - - #endregion - - #region Extra Methods - private static bool HaveMeikyoShisui => Player.HasStatus(true, StatusID.MeikyoShisui); - - #endregion -} \ No newline at end of file diff --git a/BasicRotations/Ranged/MCH_Default.cs b/BasicRotations/Ranged/MCH_Default.cs index f795372..512e2dc 100644 --- a/BasicRotations/Ranged/MCH_Default.cs +++ b/BasicRotations/Ranged/MCH_Default.cs @@ -45,24 +45,24 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) (!DrillPvE.EnoughLevel && CleanShotPvE.EnoughLevel && nextGCD.IsTheSameTo(true, CleanShotPvE)) || //HotShot Logic (!CleanShotPvE.EnoughLevel && nextGCD.IsTheSameTo(true, HotShotPvE))); - + // Keeps Ricochet and Gauss cannon Even bool isRicochetMore = RicochetPvE.EnoughLevel && GaussRoundPvE.Cooldown.CurrentCharges <= RicochetPvE.Cooldown.CurrentCharges; bool isGaussMore = !RicochetPvE.EnoughLevel || GaussRoundPvE.Cooldown.CurrentCharges > RicochetPvE.Cooldown.CurrentCharges; - + // Attempt to use Reassemble if it's ready if (isReassembleUsable) { if (ReassemblePvE.CanUse(out act, onLastAbility: true, skipClippingCheck: true, skipComboCheck: true, usedUp: true)) return true; } - + // Use Ricochet if (isRicochetMore && ((!IsLastAction(true, new[] { GaussRoundPvE, RicochetPvE }) && IsLastGCD(true, HeatBlastPvE)) || !IsLastGCD(true, HeatBlastPvE))) { if (RicochetPvE.CanUse(out act, skipAoeCheck: true, usedUp: true)) return true; } - + // Use Gauss if (isGaussMore && ((!IsLastAction(true, new[] { GaussRoundPvE, RicochetPvE }) && IsLastGCD(true, HeatBlastPvE)) || !IsLastGCD(true, HeatBlastPvE))) { @@ -82,11 +82,13 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) (nextGCD.IsTheSameTo(true, AirAnchorPvE) || nextGCD.IsTheSameTo(true, CleanShotPvE)) || nextGCD.IsTheSameTo(true, HeatedCleanShotPvE) || nextGCD.IsTheSameTo(true, ChainSawPvE); bool BatteryCheckQueen = Battery >= 90 && !WildfirePvE.Cooldown.ElapsedAfter(70f); bool LastGCDCheckQueen = Battery >= 80 && !WildfirePvE.Cooldown.ElapsedAfter(77.5f) && IsLastGCD(true, AirAnchorPvE); + // Check for not burning Hypercharge below level 52 on AOE + bool LowLevelHyperCheck = !AutoCrossbowPvE.EnoughLevel && SpreadShotPvE.CanUse(out _); // If Wildfire is active, use Hypercharge.....Period if (Player.HasStatus(true, StatusID.Wildfire_1946)) { - return HyperchargePvE.CanUse(out act, skipClippingCheck: true); + return HyperchargePvE.CanUse(out act, skipClippingCheck: true, skipComboCheck: true); } // Burst if (IsBurst) @@ -95,11 +97,11 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) { if ((IsLastAbility(false, HyperchargePvE) || Heat >= 50) && !CombatElapsedLess(10) && CanUseHyperchargePvE(out _) - && WildfirePvE.CanUse(out act, onLastAbility: true, skipComboCheck: true)) return true; + && !LowLevelHyperCheck && WildfirePvE.CanUse(out act, onLastAbility: true, skipComboCheck: true)) return true; } } // Use Hypercharge if at least 12 seconds of combat and (if wildfire will not be up in 30 seconds or if you hit 100 heat) - if (!CombatElapsedLess(12) && !Player.HasStatus(true, StatusID.Reassembled) && (!WildfirePvE.Cooldown.WillHaveOneCharge(30) || (Heat == 100))) + if (!LowLevelHyperCheck && !CombatElapsedLess(12) && !Player.HasStatus(true, StatusID.Reassembled) && (!WildfirePvE.Cooldown.WillHaveOneCharge(30) || (Heat == 100))) { if (CanUseHyperchargePvE(out act)) return true; } @@ -195,4 +197,4 @@ private bool CanUseHyperchargePvE(out IAction? act) } } #endregion -} +} \ No newline at end of file diff --git a/BasicRotations/Ranged/MCH_zBeta.cs b/BasicRotations/Ranged/MCH_zBeta.cs deleted file mode 100644 index 95a9619..0000000 --- a/BasicRotations/Ranged/MCH_zBeta.cs +++ /dev/null @@ -1,200 +0,0 @@ -namespace DefaultRotations.Ranged; - -[Rotation("Beta", CombatType.PvE, GameVersion = "6.58", Description = "Additonal contributions to this rotation thanks to Toshi!")] -[SourceCode(Path = "main/DefaultRotations/Ranged/MCH_zBeta.cs")] -[Api(1)] -public sealed class MCH_zBeta : MachinistRotation -{ - #region Config Options - [RotationConfig(CombatType.PvE, Name = "Uses Rook Autoturret/Automaton Queen immediately whenever you get 50 battery")] - public bool UseQueenWhenever { get; set; } = true; - #endregion - - #region Countdown logic - // Defines logic for actions to take during the countdown before combat starts. - protected override IAction? CountDownAction(float remainTime) - { - if (remainTime < 5) - { - if (ReassemblePvE.CanUse(out var act)) return act; - } - if (remainTime < 2) - { - if (UseBurstMedicine(out var act)) return act; - } - return base.CountDownAction(remainTime); - } - #endregion - - #region oGCD Logic - // Determines emergency actions to take based on the next planned GCD action. - protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) - { - // Reassemble Logic - // Check next GCD action and conditions for Reassemble. - bool isReassembleUsable = - //Reassemble current # of charges and double proc protection - ReassemblePvE.Cooldown.CurrentCharges > 0 && !Player.HasStatus(true, StatusID.Reassembled) && - //Chainsaw Level Check and NextGCD Check - ((ChainSawPvE.EnoughLevel && nextGCD.IsTheSameTo(true, ChainSawPvE)) || - //AirAnchor Logic - (AirAnchorPvE.EnoughLevel && nextGCD.IsTheSameTo(true, AirAnchorPvE)) || - //Drill Logic - (DrillPvE.EnoughLevel && !ChainSawPvE.EnoughLevel && nextGCD.IsTheSameTo(true, DrillPvE)) || - //Cleanshot Logic - (!DrillPvE.EnoughLevel && CleanShotPvE.EnoughLevel && nextGCD.IsTheSameTo(true, CleanShotPvE)) || - //HotShot Logic - (!CleanShotPvE.EnoughLevel && nextGCD.IsTheSameTo(true, HotShotPvE))); - - // Keeps Ricochet and Gauss cannon Even - bool isRicochetMore = RicochetPvE.EnoughLevel && GaussRoundPvE.Cooldown.CurrentCharges <= RicochetPvE.Cooldown.CurrentCharges; - bool isGaussMore = !RicochetPvE.EnoughLevel || GaussRoundPvE.Cooldown.CurrentCharges > RicochetPvE.Cooldown.CurrentCharges; - - // Attempt to use Reassemble if it's ready - if (isReassembleUsable) - { - if (ReassemblePvE.CanUse(out act, onLastAbility: true, skipClippingCheck: true, skipComboCheck: true, usedUp: true)) return true; - } - - // Use Ricochet - if (isRicochetMore && ((!IsLastAction(true, new[] { GaussRoundPvE, RicochetPvE }) && IsLastGCD(true, HeatBlastPvE)) || !IsLastGCD(true, HeatBlastPvE))) - { - if (RicochetPvE.CanUse(out act, skipAoeCheck: true, usedUp: true)) - return true; - } - - // Use Gauss - if (isGaussMore && ((!IsLastAction(true, new[] { GaussRoundPvE, RicochetPvE }) && IsLastGCD(true, HeatBlastPvE)) || !IsLastGCD(true, HeatBlastPvE))) - { - if (GaussRoundPvE.CanUse(out act, usedUp: true)) - return true; - } - return base.EmergencyAbility(nextGCD, out act); - } - - // Logic for using attack abilities outside of GCD, focusing on burst windows and cooldown management. - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - // Define conditions under which the Rook Autoturret/Queen can be used. - bool OpenerQueen = !CombatElapsedLess(20f) && CombatElapsedLess(25f); - bool CombatTimeQueen = CombatElapsedLess(60f) && !CombatElapsedLess(45f); - bool WildfireCooldownQueen = WildfirePvE.Cooldown.IsCoolingDown && WildfirePvE.Cooldown.ElapsedAfter(105f) && Battery == 100 && - (nextGCD.IsTheSameTo(true, AirAnchorPvE) || nextGCD.IsTheSameTo(true, CleanShotPvE)) || nextGCD.IsTheSameTo(true, HeatedCleanShotPvE) || nextGCD.IsTheSameTo(true, ChainSawPvE); - bool BatteryCheckQueen = Battery >= 90 && !WildfirePvE.Cooldown.ElapsedAfter(70f); - bool LastGCDCheckQueen = Battery >= 80 && !WildfirePvE.Cooldown.ElapsedAfter(77.5f) && IsLastGCD(true, AirAnchorPvE); - // Check for not burning Hypercharge below level 52 on AOE - bool LowLevelHyperCheck = !AutoCrossbowPvE.EnoughLevel && SpreadShotPvE.CanUse(out _); - - // If Wildfire is active, use Hypercharge.....Period - if (Player.HasStatus(true, StatusID.Wildfire_1946)) - { - return HyperchargePvE.CanUse(out act, skipClippingCheck: true, skipComboCheck: true); - } - // Burst - if (IsBurst) - { - if (UseBurstMedicine(out act)) return true; - - { - if ((IsLastAbility(false, HyperchargePvE) || Heat >= 50) && !CombatElapsedLess(10) && CanUseHyperchargePvE(out _) - && !LowLevelHyperCheck && WildfirePvE.CanUse(out act, onLastAbility: true, skipComboCheck: true)) return true; - } - } - // Use Hypercharge if at least 12 seconds of combat and (if wildfire will not be up in 30 seconds or if you hit 100 heat) - if (!LowLevelHyperCheck && !CombatElapsedLess(12) && !Player.HasStatus(true, StatusID.Reassembled) && (!WildfirePvE.Cooldown.WillHaveOneCharge(30) || (Heat == 100))) - { - if (CanUseHyperchargePvE(out act)) return true; - } - // Rook Autoturret/Queen Logic toggle on - if (UseQueenWhenever && (OpenerQueen || CombatTimeQueen || WildfireCooldownQueen || BatteryCheckQueen || LastGCDCheckQueen)) - { - return RookAutoturretPvE.CanUse(out act, skipComboCheck: true); - } - // Rook Autoturret/Queen Logic toggle off - if (!UseQueenWhenever) - { - return RookAutoturretPvE.CanUse(out act, skipComboCheck: true); - } - // Use Barrel Stabilizer on CD if won't cap - if (BarrelStabilizerPvE.CanUse(out act)) return true; - - return base.AttackAbility(nextGCD, out act); - } - #endregion - - #region GCD Logic - // Defines the general logic for determining which global cooldown (GCD) action to take. - protected override bool GeneralGCD(out IAction? act) - { - // Checks and executes AutoCrossbow or HeatBlast if conditions are met (overheated state). - if (AutoCrossbowPvE.CanUse(out act)) return true; - if (HeatBlastPvE.CanUse(out act)) return true; - - // Executes Bioblaster, and then checks for AirAnchor or HotShot, and Drill based on availability and conditions. - if (BioblasterPvE.CanUse(out act)) return true; - // Check if SpreadShot cannot be used - if (!SpreadShotPvE.CanUse(out _)) - { - // Check if AirAnchor can be used - if (AirAnchorPvE.CanUse(out act)) return true; - - // If not at the required level for AirAnchor and HotShot can be used - if (!AirAnchorPvE.EnoughLevel && HotShotPvE.CanUse(out act)) return true; - - // Check if Drill can be used - if (DrillPvE.CanUse(out act)) return true; - } - - // Special condition for using ChainSaw outside of AoE checks if no action is chosen within 4 GCDs. - if (!CombatElapsedLessGCD(4) && ChainSawPvE.CanUse(out act, skipAoeCheck: true)) return true; - - // AoE actions: ChainSaw and SpreadShot based on their usability. - if (SpreadShotPvE.CanUse(out _)) - { - if (ChainSawPvE.CanUse(out act)) return true; - } - if (SpreadShotPvE.CanUse(out act)) return true; - - // Single target actions: CleanShot, SlugShot, and SplitShot based on their usability. - if (CleanShotPvE.CanUse(out act)) return true; - if (SlugShotPvE.CanUse(out act)) return true; - if (SplitShotPvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - #endregion - - #region Extra Methods - // Extra private helper methods for determining the usability of specific abilities under certain conditions. - // These methods simplify the main logic by encapsulating specific checks related to abilities' cooldowns and prerequisites. - // Logic for Hypercharge - private bool CanUseHyperchargePvE(out IAction? act) - { - float REST_TIME = 6f; - if - //Cannot AOE - ((!SpreadShotPvE.CanUse(out _)) - && - // AirAnchor Enough Level % AirAnchor - ((AirAnchorPvE.EnoughLevel && AirAnchorPvE.Cooldown.WillHaveOneCharge(REST_TIME)) - || - // HotShot Charge Detection - (!AirAnchorPvE.EnoughLevel && HotShotPvE.EnoughLevel && HotShotPvE.Cooldown.WillHaveOneCharge(REST_TIME)) - || - // Drill Charge Detection - (DrillPvE.EnoughLevel && DrillPvE.Cooldown.WillHaveOneCharge(REST_TIME)) - || - // Chainsaw Charge Detection - (ChainSawPvE.EnoughLevel && ChainSawPvE.Cooldown.WillHaveOneCharge(REST_TIME)))) - { - act = null; - return false; - } - else - { - // Use Hypercharge - return HyperchargePvE.CanUse(out act); - } - } - #endregion -} diff --git a/BasicRotations/Tank/DRK_Default.cs b/BasicRotations/Tank/DRK_Default.cs index aae69c3..c256619 100644 --- a/BasicRotations/Tank/DRK_Default.cs +++ b/BasicRotations/Tank/DRK_Default.cs @@ -96,8 +96,12 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) { if (UseBurstMedicine(out act)) return true; if (InCombat && DeliriumPvE.CanUse(out act)) return true; - if (DeliriumPvE.Cooldown.ElapsedAfterGCD(1) && !DeliriumPvE.Cooldown.ElapsedAfterGCD(3) + if (DeliriumPvE.EnoughLevel && DeliriumPvE.Cooldown.ElapsedAfterGCD(1) && !DeliriumPvE.Cooldown.ElapsedAfterGCD(3) && BloodWeaponPvE.CanUse(out act)) return true; + if (!DeliriumPvE.EnoughLevel) + { + if (BloodWeaponPvE.CanUse(out act, skipClippingCheck: true)) return true; + } if (LivingShadowPvE.CanUse(out act, skipAoeCheck: true)) return true; if (BloodspillerPvE.CanUse(out act, skipClippingCheck: true, skipComboCheck: true)) return true; } diff --git a/BasicRotations/Tank/DRK_zBeta.cs b/BasicRotations/Tank/DRK_zBeta.cs deleted file mode 100644 index 62652f0..0000000 --- a/BasicRotations/Tank/DRK_zBeta.cs +++ /dev/null @@ -1,212 +0,0 @@ -namespace DefaultRotations.Tank; - -[Rotation("Beta", CombatType.PvE, GameVersion = "6.58")] -[SourceCode(Path = "main/DefaultRotations/Tank/DRK_zBeta.cs")] -[Api(1)] -public sealed class DRK_zBeta : DarkKnightRotation -{ - #region Config Options - [RotationConfig(CombatType.PvE, Name = "Keep at least 3000 MP")] - public bool TheBlackestNight { get; set; } = true; - #endregion - - #region Countdown Logic - // Countdown logic to prepare for combat. - // Includes logic for using Provoke, tank stances, and burst medicines. - protected override IAction? CountDownAction(float remainTime) - { - //Provoke when has Shield. - if (remainTime <= CountDownAhead) - { - if (HasTankStance) - { - if (ProvokePvE.CanUse(out _)) return ProvokePvE; - } - } - if (remainTime <= 2 && UseBurstMedicine(out var act)) return act; - if (remainTime <= 3 && TheBlackestNightPvE.CanUse(out act)) return act; - if (remainTime <= 4 && BloodWeaponPvE.CanUse(out act)) return act; - return base.CountDownAction(remainTime); - } - #endregion - - #region oGCD Logic - // Decision-making for emergency abilities, focusing on Blood Weapon usage. - protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) - { - if (base.EmergencyAbility(nextGCD, out act)) return true; - - if ((InCombat && CombatElapsedLess(2) || TimeSinceLastAction.TotalSeconds >= 10)) - { - if (BloodWeaponPvE.CanUse(out act, skipAoeCheck: true)) return true; - } - - return base.EmergencyAbility(nextGCD, out act); - } - - // Determines healing actions based on The Blackest Night ability. - [RotationDesc(ActionID.TheBlackestNightPvE)] - protected override bool HealSingleAbility(IAction nextGCD, out IAction? act) - { - if (TheBlackestNightPvE.CanUse(out act)) return true; - return base.HealSingleAbility(nextGCD, out act); - } - - [RotationDesc(ActionID.DarkMissionaryPvE, ActionID.ReprisalPvE)] - protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act) - { - if (!InTwoMIsBurst() && DarkMissionaryPvE.CanUse(out act)) return true; - if (!InTwoMIsBurst() && ReprisalPvE.CanUse(out act, skipAoeCheck: true)) return true; - - return base.DefenseAreaAbility(nextGCD, out act); - } - - [RotationDesc(ActionID.TheBlackestNightPvE, ActionID.OblationPvE, ActionID.ReprisalPvE, ActionID.ShadowWallPvE, ActionID.RampartPvE, ActionID.DarkMindPvE)] - protected override bool DefenseSingleAbility(IAction nextGCD, out IAction? act) - { - act = null; - - if (Player.HasStatus(true, StatusID.BlackestNight)) return false; - - //10 - if (OblationPvE.CanUse(out act, usedUp: true, onLastAbility: true)) return true; - - if (ReprisalPvE.CanUse(out act, skipAoeCheck: true, onLastAbility: true)) return true; - - if (TheBlackestNightPvE.CanUse(out act, onLastAbility: true)) return true; - //30 - if ((!RampartPvE.Cooldown.IsCoolingDown || RampartPvE.Cooldown.ElapsedAfter(60)) && ShadowWallPvE.CanUse(out act)) return true; - - //20 - if (ShadowWallPvE.Cooldown.IsCoolingDown && ShadowWallPvE.Cooldown.ElapsedAfter(60) && RampartPvE.CanUse(out act)) return true; - if (DarkMindPvE.CanUse(out act)) return true; - - return base.DefenseAreaAbility(nextGCD, out act); - } - - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - if (CheckDarkSide) - { - if (FloodOfDarknessPvE.CanUse(out act)) return true; - if (EdgeOfDarknessPvE.CanUse(out act)) return true; - } - - if (IsBurst) - { - if (UseBurstMedicine(out act)) return true; - if (InCombat && DeliriumPvE.CanUse(out act)) return true; - if (DeliriumPvE.EnoughLevel && DeliriumPvE.Cooldown.ElapsedAfterGCD(1) && !DeliriumPvE.Cooldown.ElapsedAfterGCD(3) - && BloodWeaponPvE.CanUse(out act)) return true; - if (!DeliriumPvE.EnoughLevel) - { - if (BloodWeaponPvE.CanUse(out act, skipClippingCheck: true)) return true; - } - if (LivingShadowPvE.CanUse(out act, skipAoeCheck: true)) return true; - if (BloodspillerPvE.CanUse(out act, skipClippingCheck: true, skipComboCheck: true)) return true; - } - - if (CombatLess) - { - act = null; - return false; - } - - if (!IsMoving && SaltedEarthPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (ShadowbringerPvE.CanUse(out act, skipAoeCheck: true)) return true; - - if (NumberOfHostilesInRange >= 3 && AbyssalDrainPvE.CanUse(out act)) return true; - if (CarveAndSpitPvE.CanUse(out act)) return true; - - if (InTwoMIsBurst()) - { - if (ShadowbringerPvE.CanUse(out act, usedUp: true, skipAoeCheck: true)) return true; - - } - - if (PlungePvE.CanUse(out act, skipAoeCheck: true) && !IsMoving) return true; - - if (SaltAndDarknessPvE.CanUse(out act)) return true; - - if (InTwoMIsBurst()) - { - if (PlungePvE.CanUse(out act, usedUp: true, skipAoeCheck: true) && !IsMoving) return true; - } - if (MergedStatus.HasFlag(AutoStatus.MoveForward) && MoveForwardAbility(nextGCD, out act)) return true; - return base.AttackAbility(nextGCD, out act); - } - #endregion - - #region GCD Logic - protected override bool GeneralGCD(out IAction? act) - { - //Use Blood - if (UseBlood) - { - if (QuietusPvE.CanUse(out act, skipClippingCheck: true, skipComboCheck: true)) return true; - if (BloodspillerPvE.CanUse(out act, skipClippingCheck: true, skipComboCheck: true)) return true; - } - - //AOE - if (StalwartSoulPvE.CanUse(out act)) return true; - if (UnleashPvE.CanUse(out act)) return true; - - //Single Target - if (SouleaterPvE.CanUse(out act)) return true; - if (SyphonStrikePvE.CanUse(out act)) return true; - if (HardSlashPvE.CanUse(out act)) return true; - - if (UnmendPvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - #endregion - - #region Extra Methods - // Indicates whether the Dark Knight can heal using a single ability. - public override bool CanHealSingleAbility => false; - - // Logic to determine when to use blood-based abilities. - private bool UseBlood - { - get - { - // Conditions based on player statuses and ability cooldowns. - if (!DeliriumPvE.EnoughLevel) return true; - if (Player.HasStatus(true, StatusID.Delirium_1972) && LivingShadowPvE.Cooldown.IsCoolingDown) return true; - if ((DeliriumPvE.Cooldown.WillHaveOneChargeGCD(1) && !LivingShadowPvE.Cooldown.WillHaveOneChargeGCD(3)) || Blood >= 90 && !LivingShadowPvE.Cooldown.WillHaveOneChargeGCD(1)) return true; - - return false; - } - } - // Determines if currently in a burst phase based on cooldowns of key abilities. - private bool InTwoMIsBurst() - { - if ((BloodWeaponPvE.Cooldown.IsCoolingDown && DeliriumPvE.Cooldown.IsCoolingDown && ((LivingShadowPvE.Cooldown.IsCoolingDown && !(LivingShadowPvE.Cooldown.ElapsedAfter(15))) || !LivingShadowPvE.EnoughLevel))) return true; - else return false; - } - - // Checks if combat time is less than 3 seconds. - private static bool CombatLess => CombatElapsedLess(3); - - // Manages DarkSide ability based on several conditions. - private bool CheckDarkSide - { - get - { - if (DarkSideEndAfterGCD(3)) return true; - - if (CombatLess) return false; - - if ((InTwoMIsBurst() && HasDarkArts) || (HasDarkArts && Player.HasStatus(true, StatusID.BlackestNight)) || (HasDarkArts && DarkSideEndAfterGCD(3))) return true; - - if ((InTwoMIsBurst() && BloodWeaponPvE.Cooldown.IsCoolingDown && LivingShadowPvE.Cooldown.IsCoolingDown && SaltedEarthPvE.Cooldown.IsCoolingDown && ShadowbringerPvE.Cooldown.CurrentCharges == 0 && CarveAndSpitPvE.Cooldown.IsCoolingDown)) return true; - - if (TheBlackestNight && CurrentMp < 6000) return false; - - return CurrentMp >= 8500; - } - } - #endregion -} \ No newline at end of file diff --git a/BasicRotations/Tank/WAR_Default.cs b/BasicRotations/Tank/WAR_Default.cs index ca0c0a9..d0b1eda 100644 --- a/BasicRotations/Tank/WAR_Default.cs +++ b/BasicRotations/Tank/WAR_Default.cs @@ -5,6 +5,10 @@ namespace DefaultRotations.Tank; [Api(1)] public sealed class WAR_Default : WarriorRotation { + #region Config Options + [RotationConfig(CombatType.PvE, Name = "Only use Nascent Flash if Tank Stance is off")] + public bool NeverscentFlash { get; set; } = false; + #endregion #region Countdown Logic protected override IAction? CountDownAction(float remainTime) @@ -41,7 +45,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) && !Player.WillStatusEndGCD(6, 0, true, StatusID.SurgingTempest) || !MythrilTempestPvE.EnoughLevel) { - if (BerserkPvE.CanUse(out act, onLastAbility: true)) return true; + if (BerserkPvE.CanUse(out act)) return true; } // If the player is in a burst status, use Infuriate. @@ -60,7 +64,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) if (UpheavalPvE.CanUse(out act)) return true; // If Onslaught can be used and the player is not moving, use it and return true. - if (OnslaughtPvE.CanUse(out act, usedUp: IsBurstStatus) && !IsMoving) return true; + if (OnslaughtPvE.CanUse(out act, usedUp: IsBurstStatus) && !IsMoving && !IsLastAction(true, OnslaughtPvE)) return true; // If the player's status includes moving forward and a move forward ability can be used, use it and return true. if (MergedStatus.HasFlag(AutoStatus.MoveForward) && MoveForwardAbility(nextGCD, out act)) return true; @@ -70,9 +74,6 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) protected override bool GeneralAbility(IAction nextGCD, out IAction? act) { - // Initialize the action to null. - act = null; - // If the player's health ratio is less than 0.6 (60%), consider using healing abilities. if (Player.GetHealthRatio() < 0.6f) { @@ -133,11 +134,16 @@ protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act) #region GCD Logic protected override bool GeneralGCD(out IAction? act) { + if (IsLastAction(false, InnerReleasePvE)) + { + if (FellCleavePvE.CanUse(out act, skipStatusProvideCheck: true)) return true; + } + // If the player's Surging Tempest status will not end in the next 3 GCDs, consider using certain abilities. if (!Player.WillStatusEndGCD(3, 0, true, StatusID.SurgingTempest)) { // If the player is not moving, is in a burst status, and Primal Rend can be used on a target within a distance of 1, use Primal Rend. - if (!IsMoving && IsBurstStatus && PrimalRendPvE.CanUse(out act, skipAoeCheck: true)) + if (!IsMoving && PrimalRendPvE.CanUse(out act, skipAoeCheck: true)) { if (PrimalRendPvE.Target.Target?.DistanceToPlayer() < 1) return true; } @@ -166,14 +172,14 @@ protected override bool GeneralGCD(out IAction? act) [RotationDesc(ActionID.NascentFlashPvE)] protected override bool HealSingleGCD(out IAction? act) { - // Initialize the action to null. - act = null; - // If Nascent Flash can be used and the player is in combat and the target's health ratio is less than 0.6, use Nascent Flash. // This means Nascent Flash is used when the player is in combat and the target is at 60% health or less. - if (NascentFlashPvE.CanUse(out act) + if (!NeverscentFlash && NascentFlashPvE.CanUse(out act) && (InCombat && NascentFlashPvE.Target.Target?.GetHealthRatio() < 0.6)) return true; + if (NeverscentFlash && NascentFlashPvE.CanUse(out act) + && (InCombat && !Player.HasStatus(true, StatusID.Defiance) && NascentFlashPvE.Target.Target?.GetHealthRatio() < 0.6)) return true; + return base.HealSingleGCD(out act); } #endregion @@ -181,4 +187,4 @@ protected override bool HealSingleGCD(out IAction? act) #region Extra Methods private static bool IsBurstStatus => !Player.WillStatusEndGCD(0, 0, false, StatusID.InnerStrength); #endregion -} +} \ No newline at end of file diff --git a/BasicRotations/Tank/WAR_zBeta.cs b/BasicRotations/Tank/WAR_zBeta.cs deleted file mode 100644 index 1e0d143..0000000 --- a/BasicRotations/Tank/WAR_zBeta.cs +++ /dev/null @@ -1,196 +0,0 @@ -namespace DefaultRotations.Tank; - -[Rotation("Beta", CombatType.PvE, GameVersion = "6.58")] -[SourceCode(Path = "main/DefaultRotations/Tank/WAR_zBeta.cs")] -[Api(1)] -public sealed class WAR_zBeta : WarriorRotation -{ - #region Config Options - [RotationConfig(CombatType.PvE, Name = "Only use Nascent Flash if Tank Stance is off")] - public bool NeverscentFlash { get; set; } = false; - #endregion - - #region Countdown Logic - protected override IAction? CountDownAction(float remainTime) - { - if (remainTime <= CountDownAhead) - { - if (HasTankStance) - { - if (ProvokePvE.CanUse(out var act)) return act; - } - else - { - if (TomahawkPvE.CanUse(out var act)) return act; - } - } - return base.CountDownAction(remainTime); - } - #endregion - - #region oGCD Logic - protected override bool AttackAbility(IAction nextGCD, out IAction? act) - { - // If Infuriate can be used, use it and return true. - if (InfuriatePvE.CanUse(out act, gcdCountForAbility: 3)) return true; - - // If less than one global cooldown (GCD) has passed in combat, don't use any abilities. - if (CombatElapsedLessGCD(1)) return false; - - // If a burst medicine can be used, use it and return true. - if (UseBurstMedicine(out act)) return true; - - // If the player has the Surging Tempest status and it will not end in the next 6 GCDs, or if the player does not have a high enough level for Mythril Tempest, use Berserk. - if (Player.HasStatus(false, StatusID.SurgingTempest) - && !Player.WillStatusEndGCD(6, 0, true, StatusID.SurgingTempest) - || !MythrilTempestPvE.EnoughLevel) - { - if (BerserkPvE.CanUse(out act)) return true; - } - - // If the player is in a burst status, use Infuriate. - if (IsBurstStatus) - { - if (InfuriatePvE.CanUse(out act, usedUp: true)) return true; - } - - // If less than four GCDs have passed in combat, don't use any abilities. - if (CombatElapsedLessGCD(4)) return false; - - // If Orogeny can be used, use it and return true. - if (OrogenyPvE.CanUse(out act)) return true; - - // If Upheaval can be used, use it and return true. - if (UpheavalPvE.CanUse(out act)) return true; - - // If Onslaught can be used and the player is not moving, use it and return true. - if (OnslaughtPvE.CanUse(out act, usedUp: IsBurstStatus) && !IsMoving && !IsLastAction(true, OnslaughtPvE)) return true; - - // If the player's status includes moving forward and a move forward ability can be used, use it and return true. - if (MergedStatus.HasFlag(AutoStatus.MoveForward) && MoveForwardAbility(nextGCD, out act)) return true; - return base.AttackAbility(nextGCD, out act); - } - - - protected override bool GeneralAbility(IAction nextGCD, out IAction? act) - { - // Initialize the action to null. - act = null; - - // If the player's health ratio is less than 0.6 (60%), consider using healing abilities. - if (Player.GetHealthRatio() < 0.6f) - { - // If Thrill of Battle can be used, use it and return true. - if (ThrillOfBattlePvE.CanUse(out act)) return true; - - // If Equilibrium can be used, use it and return true. - if (EquilibriumPvE.CanUse(out act)) return true; - } - return base.GeneralAbility(nextGCD, out act); - } - - [RotationDesc(ActionID.RawIntuitionPvE, ActionID.VengeancePvE, ActionID.RampartPvE, ActionID.RawIntuitionPvE, ActionID.ReprisalPvE)] - // This method is responsible for determining the defensive abilities to use in a single-target situation. - protected override bool DefenseSingleAbility(IAction nextGCD, out IAction? act) - { - act = null; - - // If the player currently has the Holmgang status and their health ratio is less than 0.3 (30%), don't use any defensive abilities. - if (Player.HasStatus(true, StatusID.Holmgang_409) && Player.GetHealthRatio() < 0.3f) return false; - - // If Raw Intuition can be used and there are more than 2 hostiles in range, use it. - if (RawIntuitionPvE.CanUse(out act, onLastAbility: true) && NumberOfHostilesInRange > 2) return true; - - // If the player's Bloodwhetting or Raw Intuition status will not end in the next GCD, don't use any defensive abilities. - if (!Player.WillStatusEndGCD(0, 0, true, StatusID.Bloodwhetting, StatusID.RawIntuition)) return false; - - // If Reprisal can be used, use it. - if (ReprisalPvE.CanUse(out act, skipAoeCheck: true, onLastAbility: true)) return true; - - // If Rampart is not cooling down or has been cooling down for more than 60 seconds, and Vengeance can be used, use Vengeance. - if ((!RampartPvE.Cooldown.IsCoolingDown || RampartPvE.Cooldown.ElapsedAfter(60)) && VengeancePvE.CanUse(out act)) return true; - - // If Vengeance is cooling down and has been cooling down for more than 60 seconds, or if Vengeance is not at a high enough level, and Rampart can be used, use Rampart. - if (((VengeancePvE.Cooldown.IsCoolingDown && VengeancePvE.Cooldown.ElapsedAfter(60)) || !VengeancePvE.EnoughLevel) && RampartPvE.CanUse(out act)) return true; - - - return base.DefenseAreaAbility(nextGCD, out act); - } - - [RotationDesc(ActionID.ShakeItOffPvE, ActionID.ReprisalPvE)] - protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act) - { - // Initialize the action to null. - act = null; - - // If Shake It Off is cooling down and won't have a charge in the next 60 seconds, or if Reprisal is cooling down and won't have a charge in the next 50 seconds, don't use any defensive abilities. - if (ShakeItOffPvE.Cooldown.IsCoolingDown && !ShakeItOffPvE.Cooldown.WillHaveOneCharge(60) - || ReprisalPvE.Cooldown.IsCoolingDown && !ReprisalPvE.Cooldown.WillHaveOneCharge(50)) return false; - - // If Shake It Off can be used, use it. - if (ShakeItOffPvE.CanUse(out act, skipAoeCheck: true)) return true; - - return base.DefenseAreaAbility(nextGCD, out act); - } - #endregion - - #region GCD Logic - protected override bool GeneralGCD(out IAction? act) - { - if (IsLastAction(false, InnerReleasePvE)) - { - if (FellCleavePvE.CanUse(out act, skipStatusProvideCheck: true)) return true; - } - - // If the player's Surging Tempest status will not end in the next 3 GCDs, consider using certain abilities. - if (!Player.WillStatusEndGCD(3, 0, true, StatusID.SurgingTempest)) - { - // If the player is not moving, is in a burst status, and Primal Rend can be used on a target within a distance of 1, use Primal Rend. - if (!IsMoving && PrimalRendPvE.CanUse(out act, skipAoeCheck: true)) - { - if (PrimalRendPvE.Target.Target?.DistanceToPlayer() < 1) return true; - } - // If the player is in a burst status, does not have the Nascent Chaos status, or has a Beast Gauge greater than 80, consider using Steel Cyclone or Inner Beast. - if (IsBurstStatus || !Player.HasStatus(false, StatusID.NascentChaos) || BeastGauge > 80) - { - if (SteelCyclonePvE.CanUse(out act)) return true; - if (InnerBeastPvE.CanUse(out act)) return true; - } - } - - // If any of the following abilities can be used, use them and return true. - if (MythrilTempestPvE.CanUse(out act)) return true; - if (OverpowerPvE.CanUse(out act)) return true; - if (StormsEyePvE.CanUse(out act)) return true; - if (StormsPathPvE.CanUse(out act)) return true; - if (MaimPvE.CanUse(out act)) return true; - if (HeavySwingPvE.CanUse(out act)) return true; - - // If Tomahawk can be used, use it and return true. - if (TomahawkPvE.CanUse(out act)) return true; - - return base.GeneralGCD(out act); - } - - [RotationDesc(ActionID.NascentFlashPvE)] - protected override bool HealSingleGCD(out IAction? act) - { - // Initialize the action to null. - act = null; - - // If Nascent Flash can be used and the player is in combat and the target's health ratio is less than 0.6, use Nascent Flash. - // This means Nascent Flash is used when the player is in combat and the target is at 60% health or less. - if (!NeverscentFlash && NascentFlashPvE.CanUse(out act) - && (InCombat && NascentFlashPvE.Target.Target?.GetHealthRatio() < 0.6)) return true; - - if (NeverscentFlash && NascentFlashPvE.CanUse(out act) - && (InCombat && !Player.HasStatus(true, StatusID.Defiance) && NascentFlashPvE.Target.Target?.GetHealthRatio() < 0.6)) return true; - - return base.HealSingleGCD(out act); - } - #endregion - - #region Extra Methods - private static bool IsBurstStatus => !Player.WillStatusEndGCD(0, 0, false, StatusID.InnerStrength); - #endregion -}