From aed9cb79f7e2a67dbff3aa91f30390f605106496 Mon Sep 17 00:00:00 2001 From: Karaha-Baruha Date: Fri, 20 Sep 2024 23:55:36 -0500 Subject: [PATCH 1/3] Beta MCH rework with queen and buff timing optimizations and CM/DC pooling --- BasicRotations/Ranged/zMCH_Beta.cs | 224 +++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 BasicRotations/Ranged/zMCH_Beta.cs diff --git a/BasicRotations/Ranged/zMCH_Beta.cs b/BasicRotations/Ranged/zMCH_Beta.cs new file mode 100644 index 0000000..776f192 --- /dev/null +++ b/BasicRotations/Ranged/zMCH_Beta.cs @@ -0,0 +1,224 @@ +namespace DefaultRotations.Ranged; + +[Rotation("zMCH Beta", CombatType.PvE, GameVersion = "7.05")] +[SourceCode(Path = "main/DefaultRotations/Ranged/zMCH_Beta.cs")] +[Api(4)] +public sealed class zMCH_Beta : MachinistRotation +{ + #region Config Options + [RotationConfig(CombatType.PvE, Name = "Use new beta Queen logic (attempt to align with burst and otherwise avoid overcap). \nUnchecking this will use the 'experimental' hardcoded timings from the default rotation.")] + private bool NewQueenLogic { get; set; } = true; + + [RotationConfig(CombatType.PvE, Name = "Prioritize Barrel Stabilizer use")] + private bool BSPrio { get; set; } = false; + + [RotationConfig(CombatType.PvE, Name = "Pool Drill to preserve 123 combo (this is probably a DPS loss but it will make xivanalysis happy)")] + private bool PoolDrillForCombo { 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) + { + // ReassemblePvE's duration is 5s, need to fire the first GCD before it ends + if (remainTime < 5 && ReassemblePvE.CanUse(out var act)) return act; + // tincture needs to be used on -2s exactly + if (remainTime <= 2 && UseBurstMedicine(out 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) && + (nextGCD.IsTheSameTo(true, [ChainSawPvE, ExcavatorPvE]) || nextGCD.IsTheSameTo(false, [AirAnchorPvE]) || + (!ChainSawPvE.EnoughLevel && nextGCD.IsTheSameTo(true, DrillPvE)) || + (!DrillPvE.EnoughLevel && nextGCD.IsTheSameTo(true, CleanShotPvE)) || + (!CleanShotPvE.EnoughLevel && nextGCD.IsTheSameTo(false, HotShotPvE))); + // Attempt to use Reassemble if it's ready + if (isReassembleUsable) + { + if (ReassemblePvE.CanUse(out act, skipComboCheck: true, 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) + { + // Keeps Ricochet and Gauss cannon Even + bool isRicochetMore = RicochetPvE.EnoughLevel && GaussRoundPvE.Cooldown.CurrentCharges <= RicochetPvE.Cooldown.CurrentCharges; + + // Start Ricochet/Gauss cooldowns rolling + if (!RicochetPvE.Cooldown.IsCoolingDown && RicochetPvE.CanUse(out act, skipAoeCheck: true)) return true; + if (!GaussRoundPvE.Cooldown.IsCoolingDown && GaussRoundPvE.CanUse(out act, skipAoeCheck: true)) return true; + + // 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) && HyperchargePvE.CanUse(out act)) return true; + + // Rook Autoturret/Queen Logic + if (CanUseQueenMeow(out act, nextGCD)) return true; + + if (BSPrio && BarrelStabilizerPvE.CanUse(out act)) return true; + + // Burst + if (IsBurst) + { + if ((IsLastAbility(false, HyperchargePvE) || Heat >= 50 || Player.HasStatus(true, StatusID.Hypercharged)) && ToolChargeSoon(out _) && !LowLevelHyperCheck && WildfirePvE.CanUse(out act)) return true; + } + // Use Hypercharge if if wildfire will not be up in 30 seconds or if you hit 100 heat + if (!LowLevelHyperCheck && !Player.HasStatus(true, StatusID.Reassembled) && (!WildfirePvE.Cooldown.WillHaveOneCharge(30) || (Heat == 100))) + { + if (ToolChargeSoon(out act)) return true; + } + + // Use Ricochet and Gauss if have pooled charges or is burst window + if (isRicochetMore) + { + if ((IsLastGCD(true, BlazingShotPvE, HeatBlastPvE) + || RicochetPvE.Cooldown.CurrentCharges >= RicochetPvE.Cooldown.MaxCharges - 1 + || !WildfirePvE.Cooldown.ElapsedAfter(20)) + && RicochetPvE.CanUse(out act, skipAoeCheck: true, usedUp: true)) + return true; + } + + if ((IsLastGCD(true, BlazingShotPvE, HeatBlastPvE) + || GaussRoundPvE.Cooldown.CurrentCharges >= GaussRoundPvE.Cooldown.MaxCharges - 1 + || !WildfirePvE.Cooldown.ElapsedAfter(20)) + && GaussRoundPvE.CanUse(out act, usedUp: true, skipAoeCheck: true)) + return true; + + if (IsBurst) + { + if (BarrelStabilizerPvE.CanUse(out act)) return true; + } + + return base.AttackAbility(nextGCD, out act); + } + #endregion + + #region GCD Logic + protected override bool GeneralGCD(out IAction? act) + { + // overheated aoe + if (AutoCrossbowPvE.CanUse(out act)) return true; + // overheated single + if (HeatBlastPvE.CanUse(out act)) return true; + + // drill's aoe version + if (BioblasterPvE.CanUse(out act, usedUp: true)) return true; + + // single target --- need to update this strange condition writing!!! + if (!SpreadShotPvE.CanUse(out _)) + { + // use AirAnchor if possible + if (HotShotMasteryTrait.EnoughLevel && AirAnchorPvE.CanUse(out act)) return true; + + // for opener: only use the first charge of Drill after AirAnchor when there are two + if (EnhancedMultiweaponTrait.EnoughLevel && DrillPvE.CanUse(out act, usedUp: false)) return true; + if (!EnhancedMultiweaponTrait.EnoughLevel && DrillPvE.CanUse(out act, usedUp: true)) return true; + + if (!AirAnchorPvE.EnoughLevel && HotShotPvE.CanUse(out act)) return true; + } + + // ChainSaw is always used after Drill + if (ChainSawPvE.CanUse(out act, skipAoeCheck: true)) return true; + // use combo finisher asap + if (ExcavatorPvE.CanUse(out act, skipAoeCheck: true)) return true; + // use FMF after ChainSaw combo in 'alternative opener' + if (FullMetalFieldPvE.CanUse(out act)) return true; + + // dont use the second charge of Drill if it's in opener, also save Drill for burst --- need to combine this with the logic above!!! + if (EnhancedMultiweaponTrait.EnoughLevel + && !CombatElapsedLessGCD(6) + && !ChainSawPvE.Cooldown.WillHaveOneCharge(6) + && (!PoolDrillForCombo || (!CleanShotPvE.CanUse(out _) && !SlugShotPvE.CanUse(out _))) + && DrillPvE.CanUse(out act, usedUp: true)) return true; + + // basic aoe + if (SpreadShotPvE.CanUse(out act)) return true; + + // single target 123 combo + 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 ToolChargeSoon(out IAction? act) + { + float REST_TIME = 8f; + 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.IsCoolingDown)) + || + // Chainsaw Charge Detection + (ChainSawPvE.EnoughLevel && ChainSawPvE.Cooldown.WillHaveOneCharge(REST_TIME)))) + { + act = null; + return false; + } + else + { + return HyperchargePvE.CanUse(out act); + } + } + + private bool CanUseQueenMeow(out IAction? act, IAction nextGCD) + { + // Define conditions under which the Rook Autoturret/Queen can be used. + bool QueenOne = Battery >= 60 && CombatElapsedLess(25f); + bool QueenTwo = Battery >= 90 && !CombatElapsedLess(58f) && CombatElapsedLess(78f); + bool QueenThree = Battery >= 100 && !CombatElapsedLess(111f) && CombatElapsedLess(131f); + bool QueenFour = Battery >= 50 && !CombatElapsedLess(148f) && CombatElapsedLess(168f); + bool QueenFive = Battery >= 60 && !CombatElapsedLess(178f) && CombatElapsedLess(198f); + bool QueenSix = Battery >= 100 && !CombatElapsedLess(230f) && CombatElapsedLess(250f); + bool QueenSeven = Battery >= 50 && !CombatElapsedLess(268f) && CombatElapsedLess(288f); + bool QueenEight = Battery >= 70 && !CombatElapsedLess(296f) && CombatElapsedLess(316f); + bool QueenNine = Battery >= 100 && !CombatElapsedLess(350f) && CombatElapsedLess(370f); + bool QueenTen = Battery >= 50 && !CombatElapsedLess(388f) && CombatElapsedLess(408f); + bool QueenEleven = Battery >= 80 && !CombatElapsedLess(416f) && CombatElapsedLess(436f); + bool QueenTwelve = Battery >= 100 && !CombatElapsedLess(470f) && CombatElapsedLess(490f); + bool QueenThirteen = Battery >= 50 && !CombatElapsedLess(505f) && CombatElapsedLess(525f); + bool QueenFourteen = Battery >= 60 && !CombatElapsedLess(538f) && CombatElapsedLess(558f); + bool QueenFifteen = Battery >= 100 && !CombatElapsedLess(590f) && CombatElapsedLess(610f); + + if ( + (NewQueenLogic && + (WildfirePvE.Cooldown.WillHaveOneChargeGCD(1) + || !WildfirePvE.Cooldown.ElapsedAfter(10) + || nextGCD.IsTheSameTo(true, CleanShotPvE) && Battery == 100) + || (nextGCD.IsTheSameTo(true, AirAnchorPvE, ChainSawPvE, ExcavatorPvE) && (Battery == 90 || Battery == 100))) + || !NewQueenLogic && (QueenOne || QueenTwo || QueenThree || QueenFour || QueenFive || QueenSix || QueenSeven || QueenEight || QueenNine || QueenTen || QueenEleven || QueenTwelve || QueenThirteen || QueenFourteen || QueenFifteen)) + { + if (RookAutoturretPvE.CanUse(out act)) return true; + } + act = null; + return false; + } + #endregion +} \ No newline at end of file From 91e3eaf88694d3f50df57a7f3addcb8c6952106c Mon Sep 17 00:00:00 2001 From: Karaha-Baruha Date: Sat, 21 Sep 2024 00:02:16 -0500 Subject: [PATCH 2/3] default Barrel Stabilizer priority to true --- BasicRotations/Ranged/zMCH_Beta.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BasicRotations/Ranged/zMCH_Beta.cs b/BasicRotations/Ranged/zMCH_Beta.cs index 776f192..1ccc5f0 100644 --- a/BasicRotations/Ranged/zMCH_Beta.cs +++ b/BasicRotations/Ranged/zMCH_Beta.cs @@ -10,7 +10,7 @@ public sealed class zMCH_Beta : MachinistRotation private bool NewQueenLogic { get; set; } = true; [RotationConfig(CombatType.PvE, Name = "Prioritize Barrel Stabilizer use")] - private bool BSPrio { get; set; } = false; + private bool BSPrio { get; set; } = true; [RotationConfig(CombatType.PvE, Name = "Pool Drill to preserve 123 combo (this is probably a DPS loss but it will make xivanalysis happy)")] private bool PoolDrillForCombo { get; set; } = true; From 1fe5ce71856d6a9ffe2dc277a28fa09045bf5f14 Mon Sep 17 00:00:00 2001 From: Karaha-Baruha Date: Sat, 21 Sep 2024 00:24:52 -0500 Subject: [PATCH 3/3] default drill pool to false --- BasicRotations/Ranged/zMCH_Beta.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BasicRotations/Ranged/zMCH_Beta.cs b/BasicRotations/Ranged/zMCH_Beta.cs index 1ccc5f0..35dce37 100644 --- a/BasicRotations/Ranged/zMCH_Beta.cs +++ b/BasicRotations/Ranged/zMCH_Beta.cs @@ -12,8 +12,8 @@ public sealed class zMCH_Beta : MachinistRotation [RotationConfig(CombatType.PvE, Name = "Prioritize Barrel Stabilizer use")] private bool BSPrio { get; set; } = true; - [RotationConfig(CombatType.PvE, Name = "Pool Drill to preserve 123 combo (this is probably a DPS loss but it will make xivanalysis happy)")] - private bool PoolDrillForCombo { get; set; } = true; + [RotationConfig(CombatType.PvE, Name = "Pool Drill to preserve 123 combo (this is probably a slight DPS loss but it will make xivanalysis happy)")] + private bool PoolDrillForCombo { get; set; } = false; #endregion #region Countdown logic