From 881b596c8e1050a6d167c1ac880fe0a98d018370 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Fri, 29 Dec 2023 11:25:59 +0100 Subject: [PATCH 01/16] Gnashing fang fix --- BossMod/Autorotation/GNB/GNBActions.cs | 1 + BossMod/Autorotation/GNB/GNBRotation.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/BossMod/Autorotation/GNB/GNBActions.cs b/BossMod/Autorotation/GNB/GNBActions.cs index 2b0a31d16a..a9935c60c3 100644 --- a/BossMod/Autorotation/GNB/GNBActions.cs +++ b/BossMod/Autorotation/GNB/GNBActions.cs @@ -27,6 +27,7 @@ public Actions(Autorotation autorot, Actor player) SupportedSpell(AID.DangerZone).TransformAction = SupportedSpell(AID.BlastingZone).TransformAction = () => ActionID.MakeSpell(_state.BestZone); SupportedSpell(AID.HeartOfStone).TransformAction = SupportedSpell(AID.HeartOfCorundum).TransformAction = () => ActionID.MakeSpell(_state.BestHeart); SupportedSpell(AID.Continuation).TransformAction = SupportedSpell(AID.JugularRip).TransformAction = SupportedSpell(AID.AbdomenTear).TransformAction = SupportedSpell(AID.EyeGouge).TransformAction = SupportedSpell(AID.Hypervelocity).TransformAction = () => ActionID.MakeSpell(_state.BestContinuation); + SupportedSpell(AID.GnashingFang).TransformAction = SupportedSpell(AID.SavageClaw).TransformAction = SupportedSpell(AID.WickedTalon).TransformAction = () => ActionID.MakeSpell(_state.BestGnash); SupportedSpell(AID.Aurora).Condition = _ => Player.HP.Cur < Player.HP.Max; SupportedSpell(AID.Reprisal).Condition = _ => Autorot.Hints.PotentialTargets.Any(e => e.Actor.Position.InCircle(Player.Position, 5 + e.Actor.HitboxRadius)); // TODO: consider checking only target?.. diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index 2051c7bf90..71f00f5ac1 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -1,5 +1,6 @@  using Dalamud.Game.ClientState.Objects.SubKinds; +using FFXIVClientStructs.FFXIV.Client.Game.Gauge; using System.Runtime.CompilerServices; namespace BossMod.GNB @@ -24,6 +25,7 @@ public class State : CommonRotation.PlayerState public AID BestZone => Unlocked(AID.BlastingZone) ? AID.BlastingZone : AID.DangerZone; public AID BestHeart => Unlocked(AID.HeartOfCorundum) ? AID.HeartOfCorundum : AID.HeartOfStone; public AID BestContinuation => ReadyToRip ? AID.JugularRip : ReadyToTear ? AID.AbdomenTear : ReadyToGouge ? AID.EyeGouge : ReadyToBlast ? AID.Hypervelocity : AID.Continuation; + public AID BestGnash => GunComboStep == 1 ? AID.SavageClaw : GunComboStep == 2 ? AID.WickedTalon : AID.GnashingFang; public AID ComboLastMove => (AID)ComboLastAction; public State(float[] cooldowns) : base(cooldowns) { } From 74679c467b6daf8de55c8cba168ef79a3989306b Mon Sep 17 00:00:00 2001 From: lazylemo Date: Fri, 29 Dec 2023 11:30:04 +0100 Subject: [PATCH 02/16] Cleanup --- BossMod/Autorotation/GNB/GNBActions.cs | 3 +-- BossMod/Autorotation/GNB/GNBRotation.cs | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/BossMod/Autorotation/GNB/GNBActions.cs b/BossMod/Autorotation/GNB/GNBActions.cs index a9935c60c3..38d687bfc2 100644 --- a/BossMod/Autorotation/GNB/GNBActions.cs +++ b/BossMod/Autorotation/GNB/GNBActions.cs @@ -1,5 +1,4 @@ -using Dalamud.Game.ClientState.Conditions; -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.JobGauge.Types; using System; using System.Linq; diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index 71f00f5ac1..a921d77591 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -1,7 +1,4 @@  -using Dalamud.Game.ClientState.Objects.SubKinds; -using FFXIVClientStructs.FFXIV.Client.Game.Gauge; -using System.Runtime.CompilerServices; namespace BossMod.GNB { From cef98ffb0fa54a0d51d1e49bfb16ee1eb41bc1d4 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Fri, 29 Dec 2023 11:51:15 +0100 Subject: [PATCH 03/16] Forgot to add this in ST combo --- BossMod/Autorotation/GNB/GNBActions.cs | 3 ++- BossMod/Autorotation/GNB/GNBRotation.cs | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/BossMod/Autorotation/GNB/GNBActions.cs b/BossMod/Autorotation/GNB/GNBActions.cs index 38d687bfc2..7ab7360e4d 100644 --- a/BossMod/Autorotation/GNB/GNBActions.cs +++ b/BossMod/Autorotation/GNB/GNBActions.cs @@ -127,7 +127,8 @@ private void OnConfigModified(object? sender, EventArgs args) SupportedSpell(AID.DemonSlice).PlaceholderForAuto = _config.FullRotation ? AutoActionAOE : AutoActionNone; // combo replacement - SupportedSpell(AID.BrutalShell).TransformAction = _config.STCombos ? () => ActionID.MakeSpell(Rotation.GetNextBurtalShellComboAction(ComboLastMove)) : null; + SupportedSpell(AID.BrutalShell).TransformAction = _config.STCombos ? () => ActionID.MakeSpell(Rotation.GetNextBrutalShellComboAction(ComboLastMove)) : null; + SupportedSpell(AID.SolidBarrel).TransformAction = _config.STCombos ? () => ActionID.MakeSpell(Rotation.GetNextSTComboAction(ComboLastMove, AID.SolidBarrel)) : null; SupportedSpell(AID.DemonSlaughter).TransformAction = _config.AOECombos ? () => ActionID.MakeSpell(Rotation.GetNextAOEComboAction(ComboLastMove)) : null; // smart targets diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index a921d77591..5acb52bc05 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -162,7 +162,13 @@ public void ApplyStrategyOverrides(uint[] overrides) public static int GetAOEComboLength(AID comboLastMove) => comboLastMove == AID.DemonSlice ? 1 : 2; - public static AID GetNextBurtalShellComboAction(AID comboLastMove) => comboLastMove == AID.KeenEdge ? AID.BrutalShell : AID.KeenEdge; + public static AID GetNextBrutalShellComboAction(AID comboLastMove) => comboLastMove == AID.KeenEdge ? AID.BrutalShell : AID.KeenEdge; + public static AID GetNextSTComboAction(AID comboLastMove, AID finisher) => comboLastMove switch + { + AID.BrutalShell => finisher, + AID.KeenEdge => AID.BrutalShell, + _ => AID.KeenEdge + }; public static AID GetNextAOEComboAction(AID comboLastMove) => comboLastMove == AID.DemonSlice ? AID.DemonSlaughter : AID.DemonSlice; From 3da0f99fd3849fe1b57d7c966bca3041f8760f86 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sat, 30 Dec 2023 02:37:54 +0100 Subject: [PATCH 04/16] GNB level checks --- BossMod/Autorotation/GNB/GNBActions.cs | 8 +- BossMod/Autorotation/GNB/GNBRotation.cs | 267 +++++++++++++++++---- BossMod/CooldownPlanner/PlanDefinitions.cs | 1 + 3 files changed, 225 insertions(+), 51 deletions(-) diff --git a/BossMod/Autorotation/GNB/GNBActions.cs b/BossMod/Autorotation/GNB/GNBActions.cs index 7ab7360e4d..a1601ca9da 100644 --- a/BossMod/Autorotation/GNB/GNBActions.cs +++ b/BossMod/Autorotation/GNB/GNBActions.cs @@ -1,4 +1,5 @@ -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.JobGauge.Types; using System; using System.Linq; @@ -106,10 +107,12 @@ private void UpdatePlayerState() { FillCommonPlayerState(_state); _state.HaveTankStance = Player.FindStatus(SID.RoyalGuard) != null; + if (_state.ComboLastMove == AID.SolidBarrel) + _state.ComboTimeLeft = 0; _state.Ammo = Service.JobGauges.Get().Ammo; _state.GunComboStep = Service.JobGauges.Get().AmmoComboStep; - _state.MaxCartridges = _state.Level >= 88 ? 3 : 2; + _state.MaxCartridges = _state.Unlocked(TraitID.CartridgeChargeII) ? 3 : 2; _state.NoMercyLeft = StatusDetails(Player, SID.NoMercy, Player.InstanceID).Left; _state.ReadyToRip = Player.FindStatus(SID.ReadyToRip) != null; @@ -132,7 +135,6 @@ private void OnConfigModified(object? sender, EventArgs args) SupportedSpell(AID.DemonSlaughter).TransformAction = _config.AOECombos ? () => ActionID.MakeSpell(Rotation.GetNextAOEComboAction(ComboLastMove)) : null; // smart targets - SupportedSpell(AID.HeartOfCorundum).TransformTarget = _config.SmartHeartofCorundumShirkTarget ? SmartTargetCoTank : null; SupportedSpell(AID.Shirk).TransformTarget = _config.SmartHeartofCorundumShirkTarget ? SmartTargetCoTank : null; SupportedSpell(AID.Provoke).TransformTarget = _config.ProvokeMouseover ? SmartTargetHostile : null; // TODO: also interject/low-blow } diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index 5acb52bc05..fca3ef954e 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -1,4 +1,7 @@  +using BossMod.Components; +using Dalamud.Game.ClientState.Objects.SubKinds; +using System.Runtime.CompilerServices; namespace BossMod.GNB { @@ -32,7 +35,7 @@ public State(float[] cooldowns) : base(cooldowns) { } public override string ToString() { - return $"ammo={Ammo}, ReadytoBlast={ReadyToBlast}, ReadytoGouge={ReadyToGouge}, ReadytoRip={ReadyToRip}, ReadytoTear={ReadyToTear}, roughdivide={CD(CDGroup.RoughDivide):f1}, RB={RaidBuffsLeft:f1}, PotCD={PotionCD:f1}, GCD={GCD:f3}, ALock={AnimationLock:f3}+{AnimationLockDelay:f3}, lvl={Level}/{UnlockProgress}"; + return $"ammo={Ammo}, ReadytoBlast={ReadyToBlast}, ReadytoGouge={ReadyToGouge}, ReadytoRip={ReadyToRip}, ReadytoTear={ReadyToTear}, roughdivide={CD(CDGroup.RoughDivide):f1}, CBT={ComboTimeLeft:f1}, RB={RaidBuffsLeft:f1}, PotCD={PotionCD:f1}, GCD={GCD:f3}, ALock={AnimationLock:f3}+{AnimationLockDelay:f3}, lvl={Level}/{UnlockProgress}"; } } @@ -52,8 +55,11 @@ public enum GaugeUse : uint [PropertyDisplay("Use ST combo if still in ST combo, else use AOE combo", 0x80c0c000)] ComboFitBeforeDowntime = 3, // useful on late phases before downtime + [PropertyDisplay("Use appropriate rotation to reach max gauge before downtime (NEEDS TESTING)", 0x80c0c000)] + MaxGaugeBeforeDowntime = 4, // useful on late phases before downtime + [PropertyDisplay("Use combo until second-last step, then spend gauge", 0x80400080)] - PenultimateComboThenSpend = 4, // useful for ensuring ST extension is used right before long downtime + PenultimateComboThenSpend = 5, // useful for ensuring ST extension is used right before long downtime } public enum PotionUse : uint @@ -113,6 +119,7 @@ public enum SpecialAction : uint public GaugeUse GaugeStrategy; // how are we supposed to handle gauge public PotionUse PotionStrategy; // how are we supposed to use potions public OffensiveAbilityUse NoMercyUse; // how are we supposed to use IR + public OffensiveAbilityUse BloodFestUse; public OffensiveAbilityUse GnashUse; // how are we supposed to use upheaval public OffensiveAbilityUse ZoneUse; // how are we supposed to use upheaval public OffensiveAbilityUse BowUse; // how are we supposed to use PR @@ -128,22 +135,24 @@ public override string ToString() // TODO: these bindings should be done by the framework... public void ApplyStrategyOverrides(uint[] overrides) { - if (overrides.Length >= 8) + if (overrides.Length >= 9) { GaugeStrategy = (GaugeUse)overrides[0]; PotionStrategy = (PotionUse)overrides[1]; NoMercyUse = (OffensiveAbilityUse)overrides[2]; - GnashUse = (OffensiveAbilityUse)overrides[3]; - ZoneUse = (OffensiveAbilityUse)overrides[4]; - BowUse = (OffensiveAbilityUse)overrides[5]; - RoughDivideStrategy = (RoughDivideUse)overrides[6]; - SpecialActionUse = (SpecialAction)overrides[7]; + BloodFestUse = (OffensiveAbilityUse)overrides[3]; + GnashUse = (OffensiveAbilityUse)overrides[4]; + ZoneUse = (OffensiveAbilityUse)overrides[5]; + BowUse = (OffensiveAbilityUse)overrides[6]; + RoughDivideStrategy = (RoughDivideUse)overrides[7]; + SpecialActionUse = (SpecialAction)overrides[8]; } else { GaugeStrategy = GaugeUse.Automatic; PotionStrategy = PotionUse.Manual; NoMercyUse = OffensiveAbilityUse.Automatic; + BloodFestUse = OffensiveAbilityUse.Automatic; GnashUse = OffensiveAbilityUse.Automatic; ZoneUse = OffensiveAbilityUse.Automatic; BowUse = OffensiveAbilityUse.Automatic; @@ -153,6 +162,13 @@ public void ApplyStrategyOverrides(uint[] overrides) } } + public static int GaugeGainedFromAction(State state, AID action) => action switch + { + AID.SolidBarrel or AID.DemonSlaughter => 1, + AID.Bloodfest => state.Unlocked(TraitID.CartridgeChargeII) ? 3 : 2, + _ => 0 + }; + public static int GetSTComboLength(AID comboLastMove) => comboLastMove switch { AID.BrutalShell => 1, @@ -161,8 +177,6 @@ public void ApplyStrategyOverrides(uint[] overrides) }; public static int GetAOEComboLength(AID comboLastMove) => comboLastMove == AID.DemonSlice ? 1 : 2; - - public static AID GetNextBrutalShellComboAction(AID comboLastMove) => comboLastMove == AID.KeenEdge ? AID.BrutalShell : AID.KeenEdge; public static AID GetNextSTComboAction(AID comboLastMove, AID finisher) => comboLastMove switch { AID.BrutalShell => finisher, @@ -170,22 +184,56 @@ public void ApplyStrategyOverrides(uint[] overrides) _ => AID.KeenEdge }; - public static AID GetNextAOEComboAction(AID comboLastMove) => comboLastMove == AID.DemonSlice ? AID.DemonSlaughter : AID.DemonSlice; + public static AID GetNextBrutalShellComboAction(AID comboLastMove) + { + if (comboLastMove == AID.DemonSlice) + { + return AID.DemonSlaughter; + } + else if (comboLastMove == AID.BrutalShell) + { + return AID.SolidBarrel; + } + else if (comboLastMove == AID.KeenEdge) + { + return AID.BrutalShell; + } + + return AID.KeenEdge; + } + + public static AID GetNextAOEComboAction(AID comboLastMove) + { + if (comboLastMove == AID.DemonSlice) + { + return AID.DemonSlaughter; + } + else if (comboLastMove == AID.BrutalShell) + { + return AID.SolidBarrel; + } + else if (comboLastMove == AID.KeenEdge) + { + return AID.BrutalShell; + } + + return AID.DemonSlice; + } public static AID GetNextUnlockedComboAction(State state, Strategy strategy, bool aoe) { - if (strategy.GaugeStrategy == Strategy.GaugeUse.ComboFitBeforeDowntime && (strategy.FightEndIn <= state.GCD + 2.5f * GetSTComboLength(AID.KeenEdge)) && state.ComboTimeLeft == 0) + if (strategy.GaugeStrategy == Strategy.GaugeUse.ComboFitBeforeDowntime && (strategy.FightEndIn <= state.GCD + 2.5f * GetSTComboLength(state.ComboLastMove)) && state.ComboTimeLeft == 0) return AID.DemonSlice; if (aoe) { return state.ComboLastMove switch - { + { AID.DemonSlice => state.Unlocked(AID.DemonSlaughter) ? AID.DemonSlaughter : AID.DemonSlice, AID.BrutalShell => state.Unlocked(AID.SolidBarrel) ? AID.SolidBarrel : AID.KeenEdge, AID.KeenEdge => state.Unlocked(AID.BrutalShell) ? AID.BrutalShell : AID.KeenEdge, _ => AID.DemonSlice - }; + }; } else { @@ -201,13 +249,22 @@ public static AID GetNextUnlockedComboAction(State state, Strategy strategy, boo public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) { + if (strategy.GaugeStrategy == Strategy.GaugeUse.Spend) + { + if (state.CD(CDGroup.GnashingFang) > 9 && state.Ammo >= 1) + return AID.BurstStrike; + if (strategy.FightEndIn < 9 && state.Ammo > 0) + return AID.BurstStrike; + } + if (Service.Config.Get().Skscheck && state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5) return AID.SolidBarrel; if (!Service.Config.Get().Skscheck && state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5 && state.CD(CDGroup.Bloodfest) > 20) return AID.SolidBarrel; + if (state.CD(CDGroup.NoMercy) > 17) { - if (state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 0.6 && state.Ammo >= 1 && ShouldUseGnash(state, strategy) && state.NumTargetsHitByAOE <= 3) + if (state.GunComboStep == 0 && state.Unlocked(AID.GnashingFang) && state.CD(CDGroup.GnashingFang) < 0.6 && state.Ammo >= 1 && ShouldUseGnash(state, strategy) && state.NumTargetsHitByAOE <= 3) return AID.GnashingFang; } @@ -233,9 +290,9 @@ public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) return AID.FatedCircle; if (aoe && state.Ammo >= 1 && state.CD(CDGroup.GnashingFang) > state.GCD && state.CD(CDGroup.SonicBreak) > state.GCD && !state.Unlocked(AID.DoubleDown) && state.GunComboStep == 0) return AID.FatedCircle; - if (aoe && state.Ammo >= 1 && state.CD(CDGroup.GnashingFang) > state.GCD && !state.Unlocked(AID.DoubleDown) && !state.Unlocked(AID.SonicBreak) && state.GunComboStep == 0) + if (aoe && state.Ammo >= 1 && state.CD(CDGroup.GnashingFang) > state.GCD && state.Unlocked(AID.FatedCircle) && !state.Unlocked(AID.DoubleDown) && !state.Unlocked(AID.SonicBreak) && state.GunComboStep == 0) return AID.FatedCircle; - if (aoe && state.Ammo >= 1 && !state.Unlocked(AID.DoubleDown) && !state.Unlocked(AID.SonicBreak) && !state.Unlocked(AID.GnashingFang)) + if (aoe && state.Ammo >= 1 && state.Unlocked(AID.FatedCircle) && !state.Unlocked(AID.DoubleDown) && !state.Unlocked(AID.SonicBreak) && !state.Unlocked(AID.GnashingFang)) return AID.FatedCircle; } @@ -247,12 +304,12 @@ public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) return AID.SavageClaw; } - if (state.ComboLastMove == AID.BrutalShell && state.Ammo == state.MaxCartridges) + if (state.ComboLastMove == AID.BrutalShell && state.Ammo == state.MaxCartridges && state.Unlocked(AID.BurstStrike)) { return AID.BurstStrike; } - if (aoe && state.ComboLastMove == AID.DemonSlice && state.Ammo == state.MaxCartridges) + if (aoe && state.ComboLastMove == AID.DemonSlice && state.Ammo == state.MaxCartridges && state.Unlocked(AID.FatedCircle)) { return AID.FatedCircle; } @@ -286,33 +343,87 @@ public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) _ => false }; - public static bool ShouldUseNoMercy(State state, Strategy strategy) => strategy.NoMercyUse switch + public static bool ShouldUseNoMercy(State state, Strategy strategy) { - Strategy.OffensiveAbilityUse.Delay => false, - Strategy.OffensiveAbilityUse.Force => true, - _ => (!Service.Config.Get().Skscheck && strategy.CombatTimer >= 0 && (state.CD(CDGroup.GnashingFang) < state.GCD) && ((state.TargetingEnemy && ((!Service.Config.Get().EarlyNoMercy && state.ComboLastMove == AID.BrutalShell) || (Service.Config.Get().EarlyNoMercy && state.ComboLastMove == AID.KeenEdge)) && state.Ammo == 0 && state.CD(CDGroup.Bloodfest) < 4) || state.Ammo == state.MaxCartridges || state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1 || (state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20))) || - (Service.Config.Get().Skscheck && state.GCD < 0.8 && (state.CD(CDGroup.GnashingFang) < state.GCD) && (state.Ammo == state.MaxCartridges || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1) || (state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell))) - }; + if (strategy.NoMercyUse == Strategy.OffensiveAbilityUse.Delay) + { + return false; + } + else if (strategy.NoMercyUse == Strategy.OffensiveAbilityUse.Force) + { + return true; + } + else + { + GNBConfig gnbConfig = Service.Config.Get(); + bool isEarlyNoMercy = gnbConfig.EarlyNoMercy; + + bool isGnashingFangReady = state.CD(CDGroup.GnashingFang) < 2.5 && state.Unlocked(AID.GnashingFang); + bool isSonicBreakReady = state.CD(CDGroup.SonicBreak) < 2.5 && state.Unlocked(AID.SonicBreak); + bool isDoubleDownReady = state.CD(CDGroup.DoubleDown) < 2.5 && state.Unlocked(AID.DoubleDown); + bool justusewhenever = !state.Unlocked(AID.BurstStrike) && state.TargetingEnemy && state.RangeToTarget < 5; + + bool shouldUseEarlyNoMercy = state.TargetingEnemy && ((!isEarlyNoMercy && state.ComboLastMove == AID.BrutalShell) || (isEarlyNoMercy && state.ComboLastMove == AID.KeenEdge)) && strategy.CombatTimer < 10 && (state.Ammo == 0 || state.Ammo == state.MaxCartridges) && ((state.GCD < 0.8 && gnbConfig.Skscheck) || (!gnbConfig.Skscheck)); + + bool shouldUseRegularNoMercy = (!gnbConfig.Skscheck + && (isGnashingFangReady || isSonicBreakReady || isDoubleDownReady) + && state.TargetingEnemy + && ((state.Ammo == state.MaxCartridges) + || (state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20) + || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1))) || shouldUseEarlyNoMercy; + + bool shouldUseSksCheck = (gnbConfig.Skscheck && state.GCD < 0.8 + && (isGnashingFangReady || isSonicBreakReady || isDoubleDownReady) + && state.TargetingEnemy + && (state.Ammo == state.MaxCartridges + || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1) + || (state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20))) || shouldUseEarlyNoMercy; + + return shouldUseRegularNoMercy || shouldUseSksCheck || justusewhenever; + } + } + public static bool ShouldUseGnash(State state, Strategy strategy) => strategy.GnashUse switch { Strategy.OffensiveAbilityUse.Delay => false, Strategy.OffensiveAbilityUse.Force => true, - _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.CD(CDGroup.GnashingFang) < 0.6 && state.Ammo >= 1 + _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.Unlocked(AID.GnashingFang) && state.CD(CDGroup.GnashingFang) < 0.6 && state.Ammo >= 1 }; public static bool ShouldUseZone(State state, Strategy strategy) => strategy.ZoneUse switch { Strategy.OffensiveAbilityUse.Delay => false, Strategy.OffensiveAbilityUse.Force => true, - _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.CD(CDGroup.GnashingFang) > state.AnimationLock && state.CD(CDGroup.NoMercy) > 17 + _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.Unlocked(AID.SonicBreak) && state.CD(CDGroup.SonicBreak) > state.AnimationLock && state.CD(CDGroup.NoMercy) > 17 }; + public static bool ShouldUseFest(State state, Strategy strategy) + { + if (strategy.BloodFestUse == Strategy.OffensiveAbilityUse.Delay) + { + return false; + } + else if (strategy.BloodFestUse == Strategy.OffensiveAbilityUse.Force) + { + return true; + } + else + { + GNBConfig gnbConfig = Service.Config.Get(); + bool isEarlyNoMercy = gnbConfig.EarlyNoMercy; + + bool shouldUseEarlyNoMercy = state.TargetingEnemy && state.CD(CDGroup.NoMercy) < state.AnimationLock && ((!isEarlyNoMercy && state.ComboLastMove == AID.BrutalShell) || (isEarlyNoMercy && state.ComboLastMove == AID.KeenEdge)) && strategy.CombatTimer < 10 && state.Ammo == 0 && state.Unlocked(AID.Bloodfest); + bool inNoMercy = state.NoMercyLeft > state.AnimationLock && state.Unlocked(AID.Bloodfest); + return inNoMercy && state.Ammo == 0; + } + } + public static bool ShouldUseBow(State state, Strategy strategy) => strategy.BowUse switch { Strategy.OffensiveAbilityUse.Delay => false, Strategy.OffensiveAbilityUse.Force => true, - _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.CD(CDGroup.GnashingFang) > state.AnimationLock && state.CD(CDGroup.NoMercy) > 40 + _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.Unlocked(AID.BowShock) && state.CD(CDGroup.SonicBreak) > state.AnimationLock && state.CD(CDGroup.NoMercy) > 40 }; public static bool ShouldUseRoughDivide(State state, Strategy strategy) @@ -352,13 +463,60 @@ public static bool ShouldUseRoughDivide(State state, Strategy strategy) } } + public static AID ChooseRotationBasedOnGauge(State state, Strategy strategy, bool aoe) + { + int maxGauge = state.MaxCartridges; + + // Calculate remaining gauge needed + int remainingGauge = maxGauge - state.Ammo; + + // Calculate the time needed to complete each rotation + float timeForSTRotation; + float timeForAOERotation; + float timeForSTRotationForOneCart; + float timeForAOERotationForOneCart; + + // Calculate the time needed to gain the remaining gauge for each rotation + timeForSTRotation = state.GCD + remainingGauge * (2.5f * GetSTComboLength(state.ComboLastMove) - 1); // Assuming SolidBarrel adds 1 gauge + timeForAOERotation = state.GCD + remainingGauge * (2.5f * GetAOEComboLength(state.ComboLastMove) - 1); // Assuming DemonSlice adds 1 gauge + + timeForSTRotationForOneCart = state.GCD + (2.5f * GetSTComboLength(state.ComboLastMove) - 1); // Assuming SolidBarrel adds 1 gauge + timeForAOERotationForOneCart = state.GCD + (2.5f * GetAOEComboLength(state.ComboLastMove) - 1); // Assuming DemonSlice adds 1 gauge + + // Choose the rotation with the shorter duration + if (strategy.FightEndIn <= timeForSTRotation) + { + // Return the next ST GCD action + return GetNextBrutalShellComboAction(state.ComboLastMove); + } + if (strategy.FightEndIn <= timeForAOERotation) + { + // Return the next AOE GCD action + return GetNextAOEComboAction(state.ComboLastMove); + } + // Choose the rotation with the shorter duration + if (strategy.FightEndIn <= timeForSTRotationForOneCart) + { + // Return the next ST GCD action + return GetNextBrutalShellComboAction(state.ComboLastMove); + } + if (strategy.FightEndIn <= timeForAOERotationForOneCart) + { + // Return the next AOE GCD action + return GetNextAOEComboAction(state.ComboLastMove); + } + + // Default action + return GetNextUnlockedComboAction(state, strategy, aoe); + } + public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) { // prepull if (strategy.CombatTimer > -100 && strategy.CombatTimer < -0.7f) return AID.None; - if (strategy.GaugeStrategy == Strategy.GaugeUse.ComboFitBeforeDowntime && GetSTComboLength(state.ComboLastMove) <= strategy.FightEndIn) + if (strategy.GaugeStrategy == Strategy.GaugeUse.ComboFitBeforeDowntime && (state.GCD + 2.5f * GetSTComboLength(state.ComboLastMove) <= strategy.FightEndIn) && state.NoMercyLeft < state.AnimationLock) return GetNextAOEComboAction(state.ComboLastMove); if (strategy.GaugeStrategy == Strategy.GaugeUse.LightningShotIfNotInMelee && state.RangeToTarget > 3) @@ -396,36 +554,28 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.SavageClaw; } - if (strategy.GaugeStrategy == Strategy.GaugeUse.Spend && state.Ammo >= 1 && state.CD(CDGroup.GnashingFang) >= state.AnimationLock && state.CD(CDGroup.SonicBreak) >= state.AnimationLock && state.CD(CDGroup.DoubleDown) >= state.AnimationLock && state.GunComboStep == 0) - return AID.BurstStrike; + if (strategy.GaugeStrategy == Strategy.GaugeUse.Spend) + return GetNextAmmoAction(state, strategy, aoe); + + if (strategy.GaugeStrategy == Strategy.GaugeUse.MaxGaugeBeforeDowntime && state.NoMercyLeft < state.AnimationLock) + return ChooseRotationBasedOnGauge(state, strategy, aoe); return GetNextUnlockedComboAction(state, strategy, aoe); } public static ActionID GetNextBestOGCD(State state, Strategy strategy, float deadline, bool aoe) { - if (strategy.CombatTimer > -100 && strategy.CombatTimer < -0.7f) - return ActionID.MakeSpell(AID.None); bool hasContinuation = state.ReadyToBlast || state.ReadyToGouge || state.ReadyToRip || state.ReadyToTear; if (strategy.SpecialActionUse == Strategy.SpecialAction.LB3) return ActionID.MakeSpell(AID.GunmetalSoul); - bool wantOnslaught = state.Unlocked(AID.RoughDivide) && state.TargetingEnemy && ShouldUseRoughDivide(state, strategy); - if (wantOnslaught && state.RangeToTarget > 3) + bool wantRoughDivide = state.Unlocked(AID.RoughDivide) && state.TargetingEnemy && ShouldUseRoughDivide(state, strategy); + if (wantRoughDivide && state.RangeToTarget > 3) return ActionID.MakeSpell(AID.RoughDivide); if (ShouldUsePotion(state, strategy) && state.CanWeave(state.PotionCD, 1.1f, deadline)) return CommonDefinitions.IDPotionStr; - if (state.ReadyToBlast) - return ActionID.MakeSpell(AID.Hypervelocity); - if (state.ReadyToGouge) - return ActionID.MakeSpell(AID.EyeGouge); - if (state.ReadyToTear) - return ActionID.MakeSpell(AID.AbdomenTear); - if (state.ReadyToRip) - return ActionID.MakeSpell(AID.JugularRip); - if (state.Unlocked(AID.NoMercy)) { if (ShouldUseNoMercy(state, strategy) && state.CanWeave(CDGroup.NoMercy, 0.6f, deadline)) @@ -438,13 +588,25 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea if (state.Unlocked(AID.BowShock) && ShouldUseBow(state, strategy) && state.CanWeave(CDGroup.BowShock, 0.6f, deadline)) return ActionID.MakeSpell(AID.BowShock); - if (state.Unlocked(AID.Bloodfest) && state.CanWeave(CDGroup.Bloodfest, 0.6f, deadline) && state.Ammo == 0 && state.NoMercyLeft > state.AnimationLock) + if (state.ReadyToBlast && state.Unlocked(AID.Continuation)) + return ActionID.MakeSpell(AID.Hypervelocity); + if (state.ReadyToGouge && state.Unlocked(AID.Continuation)) + return ActionID.MakeSpell(AID.EyeGouge); + if (state.ReadyToTear && state.Unlocked(AID.Continuation)) + return ActionID.MakeSpell(AID.AbdomenTear); + if (state.ReadyToRip && state.Unlocked(AID.Continuation)) + return ActionID.MakeSpell(AID.JugularRip); + + if (state.Unlocked(AID.Bloodfest) && state.CanWeave(CDGroup.Bloodfest, 0.6f, deadline) && ShouldUseFest(state, strategy)) return ActionID.MakeSpell(AID.Bloodfest); - if (wantOnslaught && Service.Config.Get().NoMercyRoughDivide && state.CanWeave(state.CD(CDGroup.RoughDivide) - 28.5f, 0.6f, deadline) && state.NoMercyLeft > state.AnimationLock && state.CD(CDGroup.GnashingFang) > 2.5) + if (wantRoughDivide && Service.Config.Get().NoMercyRoughDivide && state.CanWeave(state.CD(CDGroup.RoughDivide) - 28.5f, 0.6f, deadline) && state.NoMercyLeft > state.AnimationLock && state.CD(CDGroup.SonicBreak) > 5.5 && state.Unlocked(AID.BurstStrike)) + return ActionID.MakeSpell(AID.RoughDivide); + + if (wantRoughDivide && state.CanWeave(state.CD(CDGroup.RoughDivide), 0.6f, deadline) && state.Unlocked(AID.SonicBreak) && state.CD(CDGroup.SonicBreak) > 5.5) return ActionID.MakeSpell(AID.RoughDivide); - if (wantOnslaught && state.CanWeave(state.CD(CDGroup.RoughDivide), 0.6f, deadline) && state.CD(CDGroup.GnashingFang) > 2.5) + if (wantRoughDivide && state.CanWeave(state.CD(CDGroup.RoughDivide), 0.6f, deadline) && !state.Unlocked(AID.SonicBreak)) return ActionID.MakeSpell(AID.RoughDivide); if (strategy.SpecialActionUse == Strategy.SpecialAction.StanceOn && state.CanWeave(state.CD(CDGroup.RoyalGuard), 0.6f, deadline) && state.GunComboStep == 0 && !state.HaveTankStance) @@ -453,7 +615,16 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea if (strategy.SpecialActionUse == Strategy.SpecialAction.StanceOff && state.CanWeave(state.CD(CDGroup.ReleaseRoyalGuard), 0.6f, deadline) && state.GunComboStep == 0 && state.HaveTankStance) return ActionID.MakeSpell(AID.ReleaseRoyalGuard); - if (state.CanWeave(state.CD(CDGroup.Aurora) - 60, 0.6f, deadline) && state.AuroraLeft < state.GCD && state.CD(CDGroup.NoMercy) > 1 && state.CD(CDGroup.GnashingFang) > 1 && state.CD(CDGroup.SonicBreak) > 1 && state.CD(CDGroup.DoubleDown) > 1) + if (state.CanWeave(state.CD(CDGroup.Aurora) - 60, 0.6f, deadline) && state.Unlocked(AID.Aurora) && state.AuroraLeft < state.GCD && state.CD(CDGroup.NoMercy) > 1 && state.CD(CDGroup.GnashingFang) > 1 && state.CD(CDGroup.SonicBreak) > 1 && state.CD(CDGroup.DoubleDown) > 1) + return ActionID.MakeSpell(AID.Aurora); + + if (state.CanWeave(state.CD(CDGroup.Aurora) - 60, 0.6f, deadline) && state.Unlocked(AID.Aurora) && !state.Unlocked(AID.DoubleDown) && state.AuroraLeft < state.GCD && state.CD(CDGroup.NoMercy) > 1 && state.CD(CDGroup.GnashingFang) > 1 && state.CD(CDGroup.SonicBreak) > 1) + return ActionID.MakeSpell(AID.Aurora); + + if (state.CanWeave(state.CD(CDGroup.Aurora) - 60, 0.6f, deadline) && state.Unlocked(AID.Aurora) && !state.Unlocked(AID.DoubleDown) && !state.Unlocked(AID.SonicBreak) && state.AuroraLeft < state.GCD && state.CD(CDGroup.NoMercy) > 1 && state.CD(CDGroup.GnashingFang) > 1) + return ActionID.MakeSpell(AID.Aurora); + + if (state.CanWeave(state.CD(CDGroup.Aurora) - 60, 0.6f, deadline) && state.Unlocked(AID.Aurora) && !state.Unlocked(AID.DoubleDown) && !state.Unlocked(AID.SonicBreak) && !state.Unlocked(AID.GnashingFang) && state.AuroraLeft < state.GCD && state.CD(CDGroup.NoMercy) > 1) return ActionID.MakeSpell(AID.Aurora); return new(); diff --git a/BossMod/CooldownPlanner/PlanDefinitions.cs b/BossMod/CooldownPlanner/PlanDefinitions.cs index 89777dc98c..6fd3b95e9e 100644 --- a/BossMod/CooldownPlanner/PlanDefinitions.cs +++ b/BossMod/CooldownPlanner/PlanDefinitions.cs @@ -193,6 +193,7 @@ private static ClassData DefineGNB() c.StrategyTracks.Add(new("Gauge", typeof(GNB.Rotation.Strategy.GaugeUse))); c.StrategyTracks.Add(new("Potion", typeof(GNB.Rotation.Strategy.PotionUse), 270)); c.StrategyTracks.Add(new("NoM", typeof(GNB.Rotation.Strategy.OffensiveAbilityUse))); + c.StrategyTracks.Add(new("Fest", typeof(GNB.Rotation.Strategy.OffensiveAbilityUse))); c.StrategyTracks.Add(new("Gnash", typeof(GNB.Rotation.Strategy.OffensiveAbilityUse))); c.StrategyTracks.Add(new("Zone", typeof(GNB.Rotation.Strategy.OffensiveAbilityUse))); c.StrategyTracks.Add(new("BowS", typeof(GNB.Rotation.Strategy.OffensiveAbilityUse))); From e29a52c34a7fb29dbaf9b5f40fce56e09cd342df Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sat, 30 Dec 2023 02:55:39 +0100 Subject: [PATCH 05/16] Clean up --- BossMod/Autorotation/GNB/GNBRotation.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index fca3ef954e..1ae3919f2a 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -1,8 +1,4 @@  -using BossMod.Components; -using Dalamud.Game.ClientState.Objects.SubKinds; -using System.Runtime.CompilerServices; - namespace BossMod.GNB { public static class Rotation From 90b3393d6c5b43352ae80dc2a9da0e2d59920091 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sat, 30 Dec 2023 21:41:47 +0100 Subject: [PATCH 06/16] More GNB and RPR fixes/optimizations --- BossMod/Autorotation/GNB/GNBRotation.cs | 18 +++++++++--------- BossMod/Autorotation/RPR/RPRActions.cs | 2 ++ BossMod/Autorotation/RPR/RPRRotation.cs | 25 ++++++++++++++----------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index 1ae3919f2a..0e21b423fb 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -152,7 +152,7 @@ public void ApplyStrategyOverrides(uint[] overrides) GnashUse = OffensiveAbilityUse.Automatic; ZoneUse = OffensiveAbilityUse.Automatic; BowUse = OffensiveAbilityUse.Automatic; - RoughDivideStrategy = RoughDivideUse.NoReserve; + RoughDivideStrategy = RoughDivideUse.Automatic; SpecialActionUse = SpecialAction.None; } } @@ -253,9 +253,9 @@ public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) return AID.BurstStrike; } - if (Service.Config.Get().Skscheck && state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5) + if (Service.Config.Get().Skscheck && state.Ammo == state.MaxCartridges - 1 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5) return AID.SolidBarrel; - if (!Service.Config.Get().Skscheck && state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5 && state.CD(CDGroup.Bloodfest) > 20) + if (!Service.Config.Get().Skscheck && state.Ammo == state.MaxCartridges - 1 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5 && (state.CD(CDGroup.Bloodfest) > 20 && state.Unlocked(AID.Bloodfest))) return AID.SolidBarrel; if (state.CD(CDGroup.NoMercy) > 17) @@ -359,21 +359,21 @@ public static bool ShouldUseNoMercy(State state, Strategy strategy) bool isDoubleDownReady = state.CD(CDGroup.DoubleDown) < 2.5 && state.Unlocked(AID.DoubleDown); bool justusewhenever = !state.Unlocked(AID.BurstStrike) && state.TargetingEnemy && state.RangeToTarget < 5; - bool shouldUseEarlyNoMercy = state.TargetingEnemy && ((!isEarlyNoMercy && state.ComboLastMove == AID.BrutalShell) || (isEarlyNoMercy && state.ComboLastMove == AID.KeenEdge)) && strategy.CombatTimer < 10 && (state.Ammo == 0 || state.Ammo == state.MaxCartridges) && ((state.GCD < 0.8 && gnbConfig.Skscheck) || (!gnbConfig.Skscheck)); + bool shouldUseEarlyNoMercy = state.TargetingEnemy && ((!isEarlyNoMercy && state.ComboLastMove == AID.BrutalShell) || (isEarlyNoMercy && state.ComboLastMove == AID.KeenEdge)) && state.Unlocked(AID.Bloodfest) && strategy.CombatTimer < 10 && (state.Ammo == 0 || state.Ammo == state.MaxCartridges) && ((state.GCD < 0.8 && gnbConfig.Skscheck) || (!gnbConfig.Skscheck)); bool shouldUseRegularNoMercy = (!gnbConfig.Skscheck && (isGnashingFangReady || isSonicBreakReady || isDoubleDownReady) && state.TargetingEnemy && ((state.Ammo == state.MaxCartridges) - || (state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20) - || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1))) || shouldUseEarlyNoMercy; + || (state.Ammo == state.MaxCartridges - 1 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20) + || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1 && state.Unlocked(AID.Bloodfest)))) || shouldUseEarlyNoMercy; bool shouldUseSksCheck = (gnbConfig.Skscheck && state.GCD < 0.8 && (isGnashingFangReady || isSonicBreakReady || isDoubleDownReady) && state.TargetingEnemy && (state.Ammo == state.MaxCartridges - || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1) - || (state.Ammo == 2 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20))) || shouldUseEarlyNoMercy; + || (state.CD(CDGroup.Bloodfest) < 15 && state.Ammo == 1 && state.Unlocked(AID.Bloodfest)) + || (state.Ammo == state.MaxCartridges - 1 && state.ComboLastMove == AID.BrutalShell && state.CD(CDGroup.Bloodfest) > 20 && state.Unlocked(AID.Bloodfest)))) || shouldUseEarlyNoMercy; return shouldUseRegularNoMercy || shouldUseSksCheck || justusewhenever; } @@ -584,7 +584,7 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea if (state.Unlocked(AID.BowShock) && ShouldUseBow(state, strategy) && state.CanWeave(CDGroup.BowShock, 0.6f, deadline)) return ActionID.MakeSpell(AID.BowShock); - if (state.ReadyToBlast && state.Unlocked(AID.Continuation)) + if (state.ReadyToBlast && state.Unlocked(AID.Hypervelocity)) return ActionID.MakeSpell(AID.Hypervelocity); if (state.ReadyToGouge && state.Unlocked(AID.Continuation)) return ActionID.MakeSpell(AID.EyeGouge); diff --git a/BossMod/Autorotation/RPR/RPRActions.cs b/BossMod/Autorotation/RPR/RPRActions.cs index 65956c61f5..fc48f639d3 100644 --- a/BossMod/Autorotation/RPR/RPRActions.cs +++ b/BossMod/Autorotation/RPR/RPRActions.cs @@ -135,6 +135,8 @@ private void UpdatePlayerState() _state.VoidShroudCount = gauge.VoidShroud; _state.ShroudGauge = gauge.Shroud; _state.SoulGauge = gauge.Soul; + if (_state.ComboLastMove == AID.InfernalSlice) + _state.ComboTimeLeft = 0; _state.SoulReaverLeft = StatusDetails(Player, SID.SoulReaver, Player.InstanceID).Left; diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index bfdb9a52fa..e975e53355 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -242,17 +242,20 @@ public static AID GetNextUnlockedComboAction(State state, bool aoe) public static AID GetNextBSAction(State state, bool aoe) { - if (state.EnhancedGibbetLeft > state.GCD) - return !aoe ? AID.Gibbet : AID.Gibbet; + if (!aoe) + { + if (state.EnhancedGibbetLeft > state.GCD) + return AID.Gibbet; - if (state.EnhancedGallowsLeft > state.GCD) - return !aoe ? AID.Gallows : AID.Gallows; + if (state.EnhancedGallowsLeft > state.GCD) + return AID.Gallows; + } if (aoe) return AID.Guillotine; - return !aoe ? AID.Gallows : AID.Gallows; + return AID.Gallows; } public static bool RefreshDOT(State state, float timeLeft) => timeLeft < state.GCD; @@ -286,7 +289,7 @@ public static bool ShouldUseBloodstalk(State state, Strategy strategy, bool aoe) if (state.SoulGauge >= 50 && state.CD(CDGroup.Gluttony) > 28 && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ShroudGauge <= 90 && state.CD(CDGroup.ArcaneCircle) > 9) return true; - if (state.SoulGauge == 100 && state.CD(CDGroup.Gluttony) > state.AnimationLock && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ShroudGauge <= 90) + if (state.SoulGauge == 100 && state.CD(CDGroup.Gluttony) > state.AnimationLock && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ShroudGauge <= 90 && state.ImmortalSacrificeLeft < state.AnimationLock) return true; return false; @@ -382,7 +385,7 @@ public static bool ShouldUseEnshroud(State state, Strategy strategy) return false; if (state.ArcaneCircleLeft > state.AnimationLock && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) return true; - if ((state.CD(CDGroup.ArcaneCircle) < 6.5 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) + if ((state.CD(CDGroup.ArcaneCircle) < 6 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) return true; return false; @@ -399,7 +402,7 @@ public static bool ShouldUseArcaneCircle(State state, Strategy strategy) if (soulReaver) return false; - if (state.EnshroudedLeft < 25 && state.TargetDeathDesignLeft > 30 && state.GCD < 0.8) + if (enshrouded && state.CD(CDGroup.Enshroud) < 11f && state.TargetDeathDesignLeft > 30) return true; if (state.ShroudGauge < 50 && !enshrouded && strategy.CombatTimer > 0) return true; @@ -496,6 +499,8 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) } + if (plentifulReady && state.BloodsownCircleLeft < 1 && !soulReaver && !enshrouded && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0)) + return AID.PlentifulHarvest; if ((state.CD(CDGroup.Gluttony) < 7.5 && state.Unlocked(AID.Gluttony) && !enshrouded && !soulReaver && state.TargetDeathDesignLeft < 10) || (state.CD(CDGroup.Gluttony) > 25 && state.Unlocked(AID.Gluttony) && state.SoulGauge >= 50 && !soulReaver && !enshrouded && state.TargetDeathDesignLeft < 7.5)) return AID.ShadowofDeath; @@ -522,11 +527,9 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) return AID.Communio; - return AID.CrossReaping; + return AID.GrimReaping; } - if (plentifulReady && state.BloodsownCircleLeft < 1 && !soulReaver && !enshrouded && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0)) - return AID.PlentifulHarvest; if (state.SoulReaverLeft > state.GCD) return GetNextBSAction(state, aoe); From 834e2b4fc70c6690d7614d1327ff98c34212044c Mon Sep 17 00:00:00 2001 From: lazylemo Date: Tue, 2 Jan 2024 14:00:55 +0100 Subject: [PATCH 07/16] DRG (attempt to fix Life Cycle if it gets out of sync and auto true north) RPR more optimizations GNB more level tings and Blood Fest added to CD planner --- BossMod/Autorotation/DRG/DRGActions.cs | 3 +- BossMod/Autorotation/DRG/DRGRotation.cs | 87 ++++++++++++++++++++-- BossMod/Autorotation/GNB/GNBActions.cs | 4 + BossMod/Autorotation/GNB/GNBRotation.cs | 20 ++--- BossMod/Autorotation/RPR/RPRActions.cs | 1 + BossMod/Autorotation/RPR/RPRDefinitions.cs | 5 +- BossMod/Autorotation/RPR/RPRRotation.cs | 60 +++++++++------ BossMod/CooldownPlanner/PlanDefinitions.cs | 4 +- 8 files changed, 140 insertions(+), 44 deletions(-) diff --git a/BossMod/Autorotation/DRG/DRGActions.cs b/BossMod/Autorotation/DRG/DRGActions.cs index d557610ac6..b590c88203 100644 --- a/BossMod/Autorotation/DRG/DRGActions.cs +++ b/BossMod/Autorotation/DRG/DRGActions.cs @@ -12,6 +12,7 @@ class Actions : CommonActions private DRGConfig _config; private Rotation.State _state; private Rotation.Strategy _strategy; + private bool _aoe; public Actions(Autorotation autorot, Actor player) : base(autorot, player, Definitions.UnlockQuests, Definitions.SupportedActions) @@ -115,7 +116,7 @@ protected override NextAction CalculateAutomaticOGCD(float deadline) //if (_state.CanWeave(deadline - _state.OGCDSlotLength)) // first ogcd slot //res = Rotation.GetNextBestOGCD(_state, _strategy, deadline - _state.OGCDSlotLength); if (!res && _state.CanWeave(deadline)) // second/only ogcd slot - res = Rotation.GetNextBestOGCD(_state, _strategy, deadline); + res = Rotation.GetNextBestOGCD(_state, _strategy, deadline, _aoe); var target = res == ActionID.MakeSpell(AID.DragonSight) ? FindBestDragonSightTarget() : Autorot.PrimaryTarget; return MakeResult(res, target); diff --git a/BossMod/Autorotation/DRG/DRGRotation.cs b/BossMod/Autorotation/DRG/DRGRotation.cs index 3b0e9f67b7..9d6728ecaf 100644 --- a/BossMod/Autorotation/DRG/DRGRotation.cs +++ b/BossMod/Autorotation/DRG/DRGRotation.cs @@ -1,5 +1,4 @@  - namespace BossMod.DRG { public static class Rotation @@ -49,6 +48,15 @@ public override string ToString() // strategy configuration public class Strategy : CommonRotation.Strategy { + public enum TrueNorthUse : uint + { + Automatic = 0, + + [PropertyDisplay("Delay", 0x800000ff)] + Delay = 1, + [PropertyDisplay("Force", 0x8000ff00)] + Force = 2, + } public enum SpineShatteruse : uint { Automatic = 0, // always keep one charge reserved, use other charges under raidbuffs or prevent overcapping @@ -66,6 +74,7 @@ public enum SpineShatteruse : uint UseOutsideMelee = 4, // use immediately if outside melee range } + public TrueNorthUse TrueNorthStrategy; public SpineShatteruse SpineShatterStrategy; // how are we supposed to use spineshatter dive public int NumAOEGCDTargets; // range 10 width 4 rect public bool UseAOERotation; @@ -79,10 +88,13 @@ public void ApplyStrategyOverrides(uint[] overrides) { if (overrides.Length >= 8) { - SpineShatterStrategy = (SpineShatteruse)overrides[0]; + TrueNorthStrategy = (TrueNorthUse)overrides[0]; + SpineShatterStrategy = (SpineShatteruse)overrides[1]; + } else { + TrueNorthStrategy = TrueNorthUse.Automatic; SpineShatterStrategy = SpineShatteruse.Automatic; } } @@ -253,6 +265,60 @@ public static (Positional, bool) GetNextPositional(State state, Strategy strateg } } + public static bool ShouldUseTrueNorth(State state, Strategy strategy) + { + switch (strategy.TrueNorthStrategy) + { + case Strategy.TrueNorthUse.Delay: + return false; + + default: + if (!state.TargetingEnemy) + return false; + if (state.TrueNorthLeft > state.AnimationLock || state.RightEyeLeft > state.AnimationLock) + return false; + if (GetNextPositional(state, strategy).Item2 && strategy.NextPositionalCorrect) + return false; + if (GetNextPositional(state, strategy).Item2 && !strategy.NextPositionalCorrect) + return true; + return false; + } + } + + public static bool ShouldUseGeirskogul(State state, Strategy strategy) + { + if (state.EyeCount == 2 && state.CD(CDGroup.LanceCharge) < 40) + return false; + if (state.EyeCount == 2 && state.LanceChargeLeft > state.AnimationLock) + return true; + if (state.EyeCount == 1 && state.LanceChargeLeft > state.AnimationLock) + { + if (state.DiveReadyLeft > state.AnimationLock && state.CD(CDGroup.HighJump) > 10) + return false; + } + if (state.EyeCount != 2 && state.CD(CDGroup.LanceCharge) < 40) + { + return true; + } + if (state.EyeCount == 0) + { + return true; + } + return true; + } + + public static bool ShouldUseWyrmWindThrust(State state, Strategy strategy) + { + bool nextGCDisRaiden = state.DraconianFireLeft > state.AnimationLock && (state.ComboLastMove == AID.WheelingThrust || state.ComboLastMove == AID.FangAndClaw) && state.WheelInMotionLeft < state.AnimationLock && state.FangAndClawBaredLeft < state.AnimationLock; + if (state.FirstmindFocusCount >= 2 && state.CD(CDGroup.LanceCharge) > 10) + return true; + if (state.FirstmindFocusCount >= 2 && state.LanceChargeLeft > state.AnimationLock) + return true; + if (state.FirstmindFocusCount >= 2 && state.CD(CDGroup.LanceCharge) < 10 && !nextGCDisRaiden) + return false; + return false; + } + public static AID GetNextBestGCD(State state, Strategy strategy) { // prepull @@ -284,14 +350,15 @@ public static AID GetNextBestGCD(State state, Strategy strategy) } } - public static ActionID GetNextBestOGCD(State state, Strategy strategy, float deadline) + public static ActionID GetNextBestOGCD(State state, Strategy strategy, float deadline, bool aoe) { bool canJump = strategy.PositionLockIn > state.AnimationLock; bool wantSpineShatter = state.Unlocked(AID.SpineshatterDive) && state.TargetingEnemy && UseSpineShatterDive(state, strategy); + if (state.PowerSurgeLeft > state.GCD) { - if (state.Unlocked(AID.LanceCharge) && state.CanWeave(CDGroup.LanceCharge, 0.6f, deadline) && ((state.CD(CDGroup.DragonSight) < state.GCD) || (state.CD(CDGroup.DragonSight) < 65) && (state.CD(CDGroup.DragonSight) > 55))) + if (state.Unlocked(AID.LanceCharge) && state.CanWeave(CDGroup.LanceCharge, 0.6f, deadline - state.OGCDSlotLength) && ((state.CD(CDGroup.DragonSight) < state.GCD) || (state.CD(CDGroup.DragonSight) < 65) && (state.CD(CDGroup.DragonSight) > 55))) return ActionID.MakeSpell(AID.LanceCharge); if (state.Unlocked(AID.DragonSight) && state.CanWeave(CDGroup.DragonSight, 0.6f, deadline) && state.CD(CDGroup.BattleLitany) < state.GCD + 2.5) return ActionID.MakeSpell(AID.DragonSight); @@ -307,17 +374,21 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea if (state.CD(CDGroup.LanceCharge) > 5 && state.CD(CDGroup.DragonSight) > 5 && state.CD(CDGroup.BattleLitany) > 5) { - if (state.Unlocked(AID.Geirskogul) && state.CanWeave(CDGroup.Geirskogul, 0.6f, deadline)) + if (state.CanWeave(CDGroup.WyrmwindThrust, 0.6f, deadline) && ShouldUseWyrmWindThrust(state, strategy) && (GetNextBestGCD(state, strategy) == AID.DraconianFury || GetNextBestGCD(state, strategy) == AID.RaidenThrust)) + return ActionID.MakeSpell(AID.WyrmwindThrust); + if (state.Unlocked(AID.Geirskogul) && state.CanWeave(CDGroup.Geirskogul, 0.6f, deadline) && ShouldUseGeirskogul(state, strategy)) return ActionID.MakeSpell(AID.Geirskogul); if (canJump && state.Unlocked(AID.Jump) && state.CanWeave(state.Unlocked(AID.HighJump) ? CDGroup.HighJump : CDGroup.Jump, 0.8f, deadline)) return ActionID.MakeSpell(state.BestJump); + if (state.DiveReadyLeft > state.AnimationLock && state.CanWeave(CDGroup.MirageDive, 0.6f, deadline) && state.EyeCount == 1 && state.CD(CDGroup.Geirskogul) < state.AnimationLock && state.LanceChargeLeft > state.AnimationLock) + return ActionID.MakeSpell(AID.MirageDive); if (canJump && state.Unlocked(AID.DragonfireDive) && state.CanWeave(CDGroup.DragonfireDive, 0.8f, deadline)) return ActionID.MakeSpell(AID.DragonfireDive); if (wantSpineShatter && state.CanWeave(state.CD(CDGroup.SpineshatterDive), 0.8f, deadline)) return ActionID.MakeSpell(AID.SpineshatterDive); if (canJump && state.Unlocked(AID.Stardiver) && state.LifeOfTheDragonLeft > state.AnimationLock && state.CanWeave(CDGroup.Stardiver, 1.5f, deadline)) return ActionID.MakeSpell(AID.Stardiver); - if (state.FirstmindFocusCount >= 2 && state.CanWeave(CDGroup.WyrmwindThrust, 0.6f, deadline)) + if (state.CanWeave(CDGroup.WyrmwindThrust, 0.6f, deadline) && ShouldUseWyrmWindThrust(state, strategy)) return ActionID.MakeSpell(AID.WyrmwindThrust); if (wantSpineShatter && state.RangeToTarget > 3) return ActionID.MakeSpell(AID.SpineshatterDive); @@ -331,11 +402,13 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea // return ActionID.MakeSpell(AID.MirageDive); //if (state.DiveReadyLeft > state.AnimationLock && state.CanWeave(CDGroup.MirageDive, 0.6f, deadline) && state.EyeCount != 2 && state.LifeOfTheDragonLeft < state.AnimationLock) // return ActionID.MakeSpell(AID.MirageDive); - if (state.DiveReadyLeft > state.AnimationLock && state.CanWeave(CDGroup.MirageDive, 0.6f, deadline) && state.EyeCount != 2) + if (state.DiveReadyLeft > state.AnimationLock && state.CanWeave(CDGroup.MirageDive, 0.6f, deadline) && (state.EyeCount != 2 || state.DiveReadyLeft < state.GCD)) return ActionID.MakeSpell(AID.MirageDive); } } + if (ShouldUseTrueNorth(state, strategy) && state.CanWeave(CDGroup.TrueNorth - 45, 0.6f, deadline) && !aoe && state.GCD < 0.8) + return ActionID.MakeSpell(AID.TrueNorth); // no suitable oGCDs... return new(); diff --git a/BossMod/Autorotation/GNB/GNBActions.cs b/BossMod/Autorotation/GNB/GNBActions.cs index a1601ca9da..22e883b9cf 100644 --- a/BossMod/Autorotation/GNB/GNBActions.cs +++ b/BossMod/Autorotation/GNB/GNBActions.cs @@ -28,6 +28,10 @@ public Actions(Autorotation autorot, Actor player) SupportedSpell(AID.HeartOfStone).TransformAction = SupportedSpell(AID.HeartOfCorundum).TransformAction = () => ActionID.MakeSpell(_state.BestHeart); SupportedSpell(AID.Continuation).TransformAction = SupportedSpell(AID.JugularRip).TransformAction = SupportedSpell(AID.AbdomenTear).TransformAction = SupportedSpell(AID.EyeGouge).TransformAction = SupportedSpell(AID.Hypervelocity).TransformAction = () => ActionID.MakeSpell(_state.BestContinuation); SupportedSpell(AID.GnashingFang).TransformAction = SupportedSpell(AID.SavageClaw).TransformAction = SupportedSpell(AID.WickedTalon).TransformAction = () => ActionID.MakeSpell(_state.BestGnash); + SupportedSpell(AID.Continuation).Condition = _ => _state.ReadyToRip ? ActionID.MakeSpell(AID.JugularRip) : ActionID.MakeSpell(AID.None); + SupportedSpell(AID.Continuation).Condition = _ => _state.ReadyToTear ? ActionID.MakeSpell(AID.AbdomenTear) : ActionID.MakeSpell(AID.None); + SupportedSpell(AID.Continuation).Condition = _ => _state.ReadyToGouge ? ActionID.MakeSpell(AID.EyeGouge) : ActionID.MakeSpell(AID.None); + SupportedSpell(AID.Continuation).Condition = _ => _state.ReadyToBlast ? ActionID.MakeSpell(AID.Hypervelocity) : ActionID.MakeSpell(AID.None); SupportedSpell(AID.Aurora).Condition = _ => Player.HP.Cur < Player.HP.Max; SupportedSpell(AID.Reprisal).Condition = _ => Autorot.Hints.PotentialTargets.Any(e => e.Actor.Position.InCircle(Player.Position, 5 + e.Actor.HitboxRadius)); // TODO: consider checking only target?.. diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index 0e21b423fb..b101c4a3bc 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -1,4 +1,6 @@  +using FFXIVClientStructs.FFXIV.Client.Game.UI; + namespace BossMod.GNB { public static class Rotation @@ -71,7 +73,7 @@ public enum PotionUse : uint [PropertyDisplay("2min / 8min Potion use", 0x800000ff)] Special = 3, - [PropertyDisplay("Use ASAP, even if without ST", 0x800000ff)] + [PropertyDisplay("Use ASAP", 0x800000ff)] Force = 4, } @@ -519,13 +521,13 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.LightningShot; if (state.ReadyToBlast) - return AID.Hypervelocity; + return state.BestContinuation; if (state.ReadyToGouge) - return AID.EyeGouge; + return state.BestContinuation; if (state.ReadyToTear) - return AID.AbdomenTear; + return state.BestContinuation; if (state.ReadyToRip) - return AID.JugularRip; + return state.BestContinuation; if (strategy.GaugeStrategy == Strategy.GaugeUse.PenultimateComboThenSpend && state.ComboLastMove != AID.BrutalShell && state.ComboLastMove != AID.DemonSlice && (state.ComboLastMove != AID.BrutalShell || state.Ammo == state.MaxCartridges) && state.GunComboStep == 0) return aoe ? AID.DemonSlice : state.ComboLastMove == AID.KeenEdge ? AID.BrutalShell : AID.KeenEdge; @@ -585,13 +587,13 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea return ActionID.MakeSpell(AID.BowShock); if (state.ReadyToBlast && state.Unlocked(AID.Hypervelocity)) - return ActionID.MakeSpell(AID.Hypervelocity); + return ActionID.MakeSpell(state.BestContinuation); if (state.ReadyToGouge && state.Unlocked(AID.Continuation)) - return ActionID.MakeSpell(AID.EyeGouge); + return ActionID.MakeSpell(state.BestContinuation); if (state.ReadyToTear && state.Unlocked(AID.Continuation)) - return ActionID.MakeSpell(AID.AbdomenTear); + return ActionID.MakeSpell(state.BestContinuation); if (state.ReadyToRip && state.Unlocked(AID.Continuation)) - return ActionID.MakeSpell(AID.JugularRip); + return ActionID.MakeSpell(state.BestContinuation); if (state.Unlocked(AID.Bloodfest) && state.CanWeave(CDGroup.Bloodfest, 0.6f, deadline) && ShouldUseFest(state, strategy)) return ActionID.MakeSpell(AID.Bloodfest); diff --git a/BossMod/Autorotation/RPR/RPRActions.cs b/BossMod/Autorotation/RPR/RPRActions.cs index fc48f639d3..97f0f7563d 100644 --- a/BossMod/Autorotation/RPR/RPRActions.cs +++ b/BossMod/Autorotation/RPR/RPRActions.cs @@ -25,6 +25,7 @@ public Actions(Autorotation autorot, Actor player) SupportedSpell(AID.BloodStalk).TransformAction = SupportedSpell(AID.UnveiledGallows).TransformAction = SupportedSpell(AID.UnveiledGibbet).TransformAction = () => ActionID.MakeSpell(_state.Beststalk); SupportedSpell(AID.Gibbet).TransformAction = SupportedSpell(AID.VoidReaping).TransformAction = () => ActionID.MakeSpell(_state.BestGibbet); SupportedSpell(AID.Gallows).TransformAction = SupportedSpell(AID.CrossReaping).TransformAction = () => ActionID.MakeSpell(_state.BestGallow); + SupportedSpell(AID.SoulSow).TransformAction = SupportedSpell(AID.HarvestMoon).TransformAction = () => ActionID.MakeSpell(_state.BestSow); SupportedSpell(AID.Harpe).Condition = _ => !_config.ForbidEarlyHarpe || _strategy.CombatTimer == float.MinValue || _strategy.CombatTimer >= -1.7f; SupportedSpell(AID.LegSweep).Condition = target => target?.CastInfo?.Interruptible ?? false; diff --git a/BossMod/Autorotation/RPR/RPRDefinitions.cs b/BossMod/Autorotation/RPR/RPRDefinitions.cs index 3f737b1027..e985f81d91 100644 --- a/BossMod/Autorotation/RPR/RPRDefinitions.cs +++ b/BossMod/Autorotation/RPR/RPRDefinitions.cs @@ -56,7 +56,6 @@ public enum AID : uint LegSweep = 7863, //LB3 - TheEnd = 24858, } public enum TraitID : uint @@ -94,7 +93,6 @@ public enum CDGroup : int Feint = 47, ArmsLength = 48, SecondWind = 49, - LimitBreak = 71, } public enum SID : uint @@ -198,8 +196,10 @@ static Definitions() SupportedActions.GCD(AID.ShadowofDeath, 3); SupportedActions.GCD(AID.VoidReaping, 3); SupportedActions.GCD(AID.CrossReaping, 3); + SupportedActions.GCD(AID.GrimReaping, 8); SupportedActions.GCD(AID.WhorlofDeath, 5); SupportedActions.GCD(AID.Harpe, 25); + SupportedActions.GCD(AID.SoulSow, 0); SupportedActions.GCDWithCharges(AID.SoulSlice, 3, CDGroup.SoulSlice, 30.0f, 2); SupportedActions.GCDWithCharges(AID.SoulScythe, 5, CDGroup.SoulScythe, 30.0f, 2); SupportedActions.GCD(AID.Gibbet, 3); @@ -224,7 +224,6 @@ static Definitions() SupportedActions.OGCD(AID.ArmsLength, 0, CDGroup.ArmsLength, 120.0f).EffectDuration = 6; SupportedActions.OGCDWithCharges(AID.TrueNorth, 0, CDGroup.TrueNorth, 45.0f, 2).EffectDuration = 10; SupportedActions.OGCD(AID.LegSweep, 3, CDGroup.LegSweep, 40.0f); - SupportedActions.OGCD(AID.TheEnd, 0, CDGroup.LimitBreak, 0, 3.86f); } } } diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index e975e53355..a9cde76808 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -30,6 +30,7 @@ public class State : CommonRotation.PlayerState : AID.BloodStalk; public AID BestGallow => EnshroudedLeft > AnimationLock ? AID.CrossReaping : AID.Gallows; public AID BestGibbet => EnshroudedLeft > AnimationLock ? AID.VoidReaping : AID.Gibbet; + public AID BestSow => HasSoulsow ? AID.HarvestMoon : AID.SoulSow; public SID ExpectedShadowofDeath => SID.DeathsDesign; public AID ComboLastMove => (AID)ComboLastAction; public State(float[] cooldowns) : base(cooldowns) { } @@ -39,7 +40,7 @@ public State(float[] cooldowns) : base(cooldowns) { } public override string ToString() { - return $"shg={ShroudGauge}, Bloodsown={BloodsownCircleLeft} sog={SoulGauge}, RB={RaidBuffsLeft:f1}, DD={TargetDeathDesignLeft:f1}, EGI={EnhancedGibbetLeft:f1}, EGA={EnhancedGallowsLeft:f1}, CircleofSac={CircleofSacrificeLeft} SoulSlice={CD(CDGroup.SoulSlice)} AC={ArcaneCircleLeft:f1}, ACCD={CD(CDGroup.ArcaneCircle):f1}, PotCD={PotionCD:f1}, GCD={GCD:f3}, ALock={AnimationLock:f3}+{AnimationLockDelay:f3}, lvl={Level}/{UnlockProgress}"; + return $"shg={ShroudGauge}, Bloodsown={BloodsownCircleLeft} sog={SoulGauge}, RB={RaidBuffsLeft:f1}, DD={TargetDeathDesignLeft:f1}, EGI={EnhancedGibbetLeft:f1}, EGA={EnhancedGallowsLeft:f1}, CircleofSac={CircleofSacrificeLeft} SoulSlice={CD(CDGroup.SoulSlice)}, Enshroud={CD(CDGroup.Enshroud)}, AC={ArcaneCircleLeft}, ACCD={CD(CDGroup.ArcaneCircle):f1}, PotCD={PotionCD:f1}, GCD={GCD:f3}, ALock={AnimationLock:f3}+{AnimationLockDelay:f3}, lvl={Level}/{UnlockProgress}"; } } @@ -146,14 +147,12 @@ public enum PotionUse : uint public enum SpecialAction : uint { None = 0, // don't use any special actions - - [PropertyDisplay("LB3", 0x8000ff00)] - LB3, // use LB3 if available } public GaugeUse GaugeStrategy; // how are we supposed to handle gauge public BloodstalkUse BloodstalkStrategy; // how are we supposed to use bloodstalk public EnshroudUse EnshroudStrategy; // how are we supposed to use enshroud + public OffensiveAbilityUse ArcaneCircleStrategy; public GluttonyUse GluttonyStrategy; public PotionUse PotionStrategy; // how are we supposed to use potions //public OffensiveAbilityUse CommunioUse; @@ -163,15 +162,16 @@ public enum SpecialAction : uint public void ApplyStrategyOverrides(uint[] overrides) { - if (overrides.Length >= 7) + if (overrides.Length >= 8) { GaugeStrategy = (GaugeUse)overrides[0]; BloodstalkStrategy = (BloodstalkUse)overrides[1]; TrueNorthStrategy = (TrueNorthUse)overrides[2]; EnshroudStrategy = (EnshroudUse)overrides[3]; - GluttonyStrategy = (GluttonyUse)overrides[4]; - PotionStrategy = (PotionUse)overrides[5]; - SpecialActionUse = (SpecialAction)overrides[6]; + ArcaneCircleStrategy = (OffensiveAbilityUse)overrides[4]; + GluttonyStrategy = (GluttonyUse)overrides[5]; + PotionStrategy = (PotionUse)overrides[6]; + SpecialActionUse = (SpecialAction)overrides[7]; } else { @@ -179,6 +179,7 @@ public void ApplyStrategyOverrides(uint[] overrides) BloodstalkStrategy = BloodstalkUse.Automatic; TrueNorthStrategy = TrueNorthUse.Automatic; EnshroudStrategy = EnshroudUse.Automatic; + ArcaneCircleStrategy = OffensiveAbilityUse.Automatic; GluttonyStrategy = GluttonyUse.Automatic; PotionStrategy = PotionUse.Manual; SpecialActionUse = SpecialAction.None; @@ -283,7 +284,7 @@ public static bool ShouldUseBloodstalk(State state, Strategy strategy, bool aoe) if (enshrouded) return false; - if (ShouldUseEnshroud(state, strategy)) + if (ShouldUseEnshroud(state, strategy) && state.CD(CDGroup.Enshroud) < state.GCD) return false; if (state.SoulGauge >= 50 && state.CD(CDGroup.Gluttony) > 28 && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ShroudGauge <= 90 && state.CD(CDGroup.ArcaneCircle) > 9) @@ -292,6 +293,11 @@ public static bool ShouldUseBloodstalk(State state, Strategy strategy, bool aoe) if (state.SoulGauge == 100 && state.CD(CDGroup.Gluttony) > state.AnimationLock && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ShroudGauge <= 90 && state.ImmortalSacrificeLeft < state.AnimationLock) return true; + if (state.SoulGauge >= 50 && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ImmortalSacrificeLeft > state.AnimationLock && state.BloodsownCircleLeft > 4.8f && (state.CD(CDGroup.SoulSlice) > 30 || state.CD(CDGroup.SoulSlice) < 60) && state.ShroudGauge <= 40) + return true; + + if ((state.CD(CDGroup.ArcaneCircle) < 6 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) + return false; return false; } } @@ -354,7 +360,7 @@ public static bool ShouldUseGluttony(State state, Strategy strategy) if (ShouldUseEnshroud(state, strategy)) return false; - if (!plentifulReady && (state.ComboTimeLeft > 5 || state.ComboTimeLeft == 0) && state.SoulGauge >= 50 && state.ShroudGauge <= 80) + if ((!plentifulReady || (plentifulReady && state.BloodsownCircleLeft > 4.8f)) && (state.ComboTimeLeft > 5 || state.ComboTimeLeft == 0) && state.SoulGauge >= 50 && state.ShroudGauge <= 80 && state.TargetDeathDesignLeft > 0) return true; return false; @@ -383,9 +389,9 @@ public static bool ShouldUseEnshroud(State state, Strategy strategy) if (enshrouded) return false; - if (state.ArcaneCircleLeft > state.AnimationLock && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) + if (state.ArcaneCircleLeft > state.AnimationLock && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0) && state.CD(CDGroup.Enshroud) < state.GCD) return true; - if ((state.CD(CDGroup.ArcaneCircle) < 6 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) + if ((state.CD(CDGroup.ArcaneCircle) < 5 + state.GCD || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0) && state.CD(CDGroup.Enshroud) < state.GCD) return true; return false; @@ -397,17 +403,25 @@ public static bool ShouldUseArcaneCircle(State state, Strategy strategy) bool soulReaver = state.Unlocked(AID.BloodStalk) && state.SoulReaverLeft > state.AnimationLock; bool enshrouded = state.Unlocked(AID.Enshroud) && state.EnshroudedLeft > state.AnimationLock; - if (!state.TargetingEnemy) - return false; - if (soulReaver) + if (strategy.ArcaneCircleStrategy == Strategy.OffensiveAbilityUse.Delay) return false; - if (enshrouded && state.CD(CDGroup.Enshroud) < 11f && state.TargetDeathDesignLeft > 30) - return true; - if (state.ShroudGauge < 50 && !enshrouded && strategy.CombatTimer > 0) + else if (strategy.ArcaneCircleStrategy == Strategy.OffensiveAbilityUse.Force) return true; - return false; + else + { + if (!state.TargetingEnemy) + return false; + if (soulReaver) + return false; + + if (enshrouded && state.CD(CDGroup.Enshroud) < 10.5f && state.TargetDeathDesignLeft > 30) + return true; + if (state.ShroudGauge < 50 && !enshrouded && state.TargetDeathDesignLeft > 0) + return true; + return false; + } } public static bool ShouldUsePotion(State state, Strategy strategy) => strategy.PotionStrategy switch @@ -469,8 +483,10 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) // prepull if (strategy.CombatTimer > -100 && strategy.CombatTimer < -4.2f && !state.HasSoulsow) return AID.SoulSow; - if (strategy.CombatTimer > -100 && strategy.CombatTimer < -1.7f) + if (strategy.CombatTimer > -100 && strategy.CombatTimer < -1.6f) return AID.None; + if (strategy.CombatTimer > -1.6f && strategy.CombatTimer < 0f) + return AID.Harpe; if (strategy.GaugeStrategy == Strategy.GaugeUse.HarvestMoonIfNotInMelee && state.HasSoulsow && state.RangeToTarget > 3 && strategy.CombatTimer > 0) return AID.HarvestMoon; @@ -522,7 +538,7 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) } if (enshrouded && aoe) { - if (state.CD(CDGroup.ArcaneCircle) < state.GCD + 10) + if (state.CD(CDGroup.ArcaneCircle) < 6) return AID.WhorlofDeath; if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) return AID.Communio; @@ -549,8 +565,6 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea bool soulReaver = state.Unlocked(AID.BloodStalk) && state.SoulReaverLeft > state.AnimationLock; bool enshrouded = state.Unlocked(AID.Enshroud) && state.EnshroudedLeft > state.AnimationLock; var (positional, shouldUsePositional) = GetNextPositional(state, strategy); - if (strategy.SpecialActionUse == Strategy.SpecialAction.LB3) - return ActionID.MakeSpell(AID.TheEnd); //if (strategy.ArcaneCircleStrategy == Strategy.ArcaneCircleUse.Delay) // return ActionID.MakeSpell(AID.Enshroud); if (ShouldUsePotion(state, strategy) && state.CanWeave(state.PotionCD, 1.1f, deadline)) diff --git a/BossMod/CooldownPlanner/PlanDefinitions.cs b/BossMod/CooldownPlanner/PlanDefinitions.cs index 6fd3b95e9e..4030b4ed40 100644 --- a/BossMod/CooldownPlanner/PlanDefinitions.cs +++ b/BossMod/CooldownPlanner/PlanDefinitions.cs @@ -121,9 +121,10 @@ private static ClassData DefineSCH() private static ClassData DefineDRG() { var c = new ClassData(typeof(DRG.AID), DRG.Definitions.SupportedActions); - c.StrategyTracks.Add(new("SpineShatter", typeof(DRG.Rotation.Strategy.SpineShatteruse))); c.CooldownTracks.Add(new("Feint", ActionID.MakeSpell(DRG.AID.Feint), 22)); c.CooldownTracks.Add(new("ArmsL", ActionID.MakeSpell(DRG.AID.ArmsLength), 32)); + c.StrategyTracks.Add(new("TrueN", typeof(DRG.Rotation.Strategy.TrueNorthUse))); + c.StrategyTracks.Add(new("SpineShatter", typeof(DRG.Rotation.Strategy.SpineShatteruse))); return c; } @@ -170,6 +171,7 @@ private static ClassData DefineRPR() c.StrategyTracks.Add(new("SOUL", typeof(RPR.Rotation.Strategy.BloodstalkUse))); c.StrategyTracks.Add(new("TrN", typeof(RPR.Rotation.Strategy.TrueNorthUse))); c.StrategyTracks.Add(new("ENSH", typeof(RPR.Rotation.Strategy.EnshroudUse))); + c.StrategyTracks.Add(new("ARC", typeof(RPR.Rotation.Strategy.ArcaneCircleUse))); c.StrategyTracks.Add(new("Glut", typeof(RPR.Rotation.Strategy.GluttonyUse), 60)); c.StrategyTracks.Add(new("Potion", typeof(RPR.Rotation.Strategy.PotionUse), 270)); c.StrategyTracks.Add(new("spec", typeof(RPR.Rotation.Strategy.SpecialAction))); From 23af0be754a1ccd8b37ab55bdf85b9e0a04ef01f Mon Sep 17 00:00:00 2001 From: lazylemo Date: Wed, 3 Jan 2024 02:28:55 +0100 Subject: [PATCH 08/16] Small reaper optimization --- BossMod/Autorotation/RPR/RPRRotation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index a9cde76808..41fb31057e 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -550,10 +550,10 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (state.SoulReaverLeft > state.GCD) return GetNextBSAction(state, aoe); - if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && state.Unlocked(AID.SoulScythe) && !enshrouded && !soulReaver && aoe && (state.ComboTimeLeft > 2.5 + 2.5 || state.ComboTimeLeft == 0)) + if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && state.Unlocked(AID.SoulScythe) && !enshrouded && !soulReaver && aoe && (state.ComboTimeLeft > 2.5 + 2.5 || state.ComboTimeLeft == 0) && state.CD(CDGroup.ArcaneCircle) > 8) return AID.SoulScythe; - if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && state.Unlocked(AID.SoulSlice) && !enshrouded && !soulReaver && !aoe && (state.ComboTimeLeft > 2.5 + 2.5 || state.ComboTimeLeft == 0)) + if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && state.Unlocked(AID.SoulSlice) && !enshrouded && !soulReaver && !aoe && (state.ComboTimeLeft > 2.5 + 2.5 || state.ComboTimeLeft == 0) && state.CD(CDGroup.ArcaneCircle) > 8) return AID.SoulSlice; From 5039aceb927530d97f98abd74e4a080247d4f749 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Wed, 3 Jan 2024 02:57:48 +0100 Subject: [PATCH 09/16] RPR lvl check --- BossMod/Autorotation/RPR/RPRRotation.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index 41fb31057e..b6b36a0836 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -386,6 +386,8 @@ public static bool ShouldUseEnshroud(State state, Strategy strategy) return false; if (soulReaver) return false; + if (!state.Unlocked(AID.Enshroud)) + return false; if (enshrouded) return false; From 29cbd3b16d891a5811b6af83a678a0b816116263 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 15:57:57 +0100 Subject: [PATCH 10/16] RPR more optimizing and added harvest moon double enshroud potion GNB added early Sonic Break option --- BossMod/Autorotation/GNB/GNBConfig.cs | 3 + BossMod/Autorotation/GNB/GNBRotation.cs | 15 ++- BossMod/Autorotation/RPR/RPRActions.cs | 6 + BossMod/Autorotation/RPR/RPRRotation.cs | 146 +++++++++++++++++---- BossMod/CooldownPlanner/PlanDefinitions.cs | 1 + 5 files changed, 140 insertions(+), 31 deletions(-) diff --git a/BossMod/Autorotation/GNB/GNBConfig.cs b/BossMod/Autorotation/GNB/GNBConfig.cs index b3d81b1d01..c409560143 100644 --- a/BossMod/Autorotation/GNB/GNBConfig.cs +++ b/BossMod/Autorotation/GNB/GNBConfig.cs @@ -29,5 +29,8 @@ class GNBConfig : ConfigNode [PropertyDisplay("Early No Mercy in Opener")] public bool EarlyNoMercy = true; + + [PropertyDisplay("Early Sonic Break in Opener")] + public bool EarlySonicBreak = true; } } diff --git a/BossMod/Autorotation/GNB/GNBRotation.cs b/BossMod/Autorotation/GNB/GNBRotation.cs index b101c4a3bc..3cfd8acce7 100644 --- a/BossMod/Autorotation/GNB/GNBRotation.cs +++ b/BossMod/Autorotation/GNB/GNBRotation.cs @@ -260,17 +260,20 @@ public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) if (!Service.Config.Get().Skscheck && state.Ammo == state.MaxCartridges - 1 && state.ComboLastMove == AID.BrutalShell && state.GunComboStep == 0 && state.CD(CDGroup.GnashingFang) < 2.5 && (state.CD(CDGroup.Bloodfest) > 20 && state.Unlocked(AID.Bloodfest))) return AID.SolidBarrel; + if (Service.Config.Get().EarlySonicBreak && state.CD(CDGroup.NoMercy) > 40 && state.CD(CDGroup.SonicBreak) < 0.6f) + return AID.SonicBreak; + if (state.CD(CDGroup.NoMercy) > 17) { - if (state.GunComboStep == 0 && state.Unlocked(AID.GnashingFang) && state.CD(CDGroup.GnashingFang) < 0.6 && state.Ammo >= 1 && ShouldUseGnash(state, strategy) && state.NumTargetsHitByAOE <= 3) + if (state.GunComboStep == 0 && state.Unlocked(AID.GnashingFang) && state.CD(CDGroup.GnashingFang) < 0.6f && state.Ammo >= 1 && ShouldUseGnash(state, strategy) && state.NumTargetsHitByAOE <= 3) return AID.GnashingFang; } if (state.NoMercyLeft > state.AnimationLock) { - if (state.CD(CDGroup.SonicBreak) < 0.6 && state.Unlocked(AID.SonicBreak)) + if (state.CD(CDGroup.SonicBreak) < 0.6f && state.Unlocked(AID.SonicBreak)) return AID.SonicBreak; - if (state.CD(CDGroup.DoubleDown) < 0.6 && state.Unlocked(AID.DoubleDown) && state.Ammo >= 2 && state.RangeToTarget <= 5) + if (state.CD(CDGroup.DoubleDown) < 0.6f && state.Unlocked(AID.DoubleDown) && state.Ammo >= 2 && state.RangeToTarget <= 5) return AID.DoubleDown; if (!aoe && state.CD(CDGroup.DoubleDown) < state.GCD && state.CD(CDGroup.GnashingFang) > state.GCD && state.Unlocked(AID.DoubleDown) && state.Ammo == 1 && state.CD(CDGroup.Bloodfest) < 1.9) return AID.BurstStrike; @@ -314,7 +317,7 @@ public static AID GetNextAmmoAction(State state, Strategy strategy, bool aoe) if (strategy.GaugeStrategy == Strategy.GaugeUse.Spend && state.Ammo >= 0) { - if (state.CD(CDGroup.GnashingFang) < 0.6) + if (state.CD(CDGroup.GnashingFang) < 0.6f) return AID.GnashingFang; return AID.BurstStrike; } @@ -386,7 +389,7 @@ public static bool ShouldUseNoMercy(State state, Strategy strategy) { Strategy.OffensiveAbilityUse.Delay => false, Strategy.OffensiveAbilityUse.Force => true, - _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.Unlocked(AID.GnashingFang) && state.CD(CDGroup.GnashingFang) < 0.6 && state.Ammo >= 1 + _ => strategy.CombatTimer >= 0 && state.TargetingEnemy && state.Unlocked(AID.GnashingFang) && state.CD(CDGroup.GnashingFang) < 0.6f && state.Ammo >= 1 }; public static bool ShouldUseZone(State state, Strategy strategy) => strategy.ZoneUse switch @@ -541,7 +544,7 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (state.NoMercyLeft > state.AnimationLock) return GetNextAmmoAction(state, strategy, aoe); - if (state.CD(CDGroup.GnashingFang) < 0.6) + if (state.CD(CDGroup.GnashingFang) < 0.6f) return GetNextAmmoAction(state, strategy, aoe); if (state.GunComboStep > 0) diff --git a/BossMod/Autorotation/RPR/RPRActions.cs b/BossMod/Autorotation/RPR/RPRActions.cs index 97f0f7563d..6816655ddd 100644 --- a/BossMod/Autorotation/RPR/RPRActions.cs +++ b/BossMod/Autorotation/RPR/RPRActions.cs @@ -13,6 +13,7 @@ class Actions : CommonActions private bool _aoe; private Rotation.State _state; private Rotation.Strategy _strategy; + private bool lastActionisSoD; public Actions(Autorotation autorot, Actor player) : base(autorot, player, Definitions.UnlockQuests, Definitions.SupportedActions) @@ -156,6 +157,11 @@ private void UpdatePlayerState() _state.TargetDeathDesignLeft = StatusDetails(Autorot.PrimaryTarget, _state.ExpectedShadowofDeath, Player.InstanceID).Left; } + protected override void OnActionSucceeded(ActorCastEvent ev) + { + _state.lastActionisSoD = ev.Action.Type == ActionType.Spell && (AID)ev.Action.ID is AID.ShadowofDeath or AID.WhorlofDeath; + } + private void OnConfigModified(object? sender, EventArgs args) { // placeholders diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index b6b36a0836..152c00fcb4 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -23,6 +23,7 @@ public class State : CommonRotation.PlayerState public bool HasSoulsow; public float TargetDeathDesignLeft; public float CircleofSacrificeLeft; + public bool lastActionisSoD; public AID Beststalk => EnhancedGallowsLeft > AnimationLock ? AID.UnveiledGallows : EnhancedGibbetLeft > AnimationLock ? AID.UnveiledGibbet @@ -73,9 +74,6 @@ public enum GaugeUse : uint [PropertyDisplay("Use combo, unless it can't be finished before downtime", 0x80c0c000)] ComboFitBeforeDowntime = 5, - - [PropertyDisplay("Use combo until second-last step", 0x80400080)] - PenultimateComboThenSpend = 6, } public enum BloodstalkUse : uint @@ -142,6 +140,9 @@ public enum PotionUse : uint [PropertyDisplay("Force", 0x800000ff)] Force = 3, + + [PropertyDisplay("Special (Needs testing)", 0x80400080)] + Special = 4, } public enum SpecialAction : uint @@ -151,6 +152,7 @@ public enum SpecialAction : uint public GaugeUse GaugeStrategy; // how are we supposed to handle gauge public BloodstalkUse BloodstalkStrategy; // how are we supposed to use bloodstalk + public OffensiveAbilityUse SoulSliceStrategy; public EnshroudUse EnshroudStrategy; // how are we supposed to use enshroud public OffensiveAbilityUse ArcaneCircleStrategy; public GluttonyUse GluttonyStrategy; @@ -162,21 +164,23 @@ public enum SpecialAction : uint public void ApplyStrategyOverrides(uint[] overrides) { - if (overrides.Length >= 8) + if (overrides.Length >= 9) { GaugeStrategy = (GaugeUse)overrides[0]; BloodstalkStrategy = (BloodstalkUse)overrides[1]; - TrueNorthStrategy = (TrueNorthUse)overrides[2]; - EnshroudStrategy = (EnshroudUse)overrides[3]; - ArcaneCircleStrategy = (OffensiveAbilityUse)overrides[4]; - GluttonyStrategy = (GluttonyUse)overrides[5]; - PotionStrategy = (PotionUse)overrides[6]; - SpecialActionUse = (SpecialAction)overrides[7]; + SoulSliceStrategy = (OffensiveAbilityUse)overrides[2]; + TrueNorthStrategy = (TrueNorthUse)overrides[3]; + EnshroudStrategy = (EnshroudUse)overrides[4]; + ArcaneCircleStrategy = (OffensiveAbilityUse)overrides[5]; + GluttonyStrategy = (GluttonyUse)overrides[6]; + PotionStrategy = (PotionUse)overrides[7]; + SpecialActionUse = (SpecialAction)overrides[8]; } else { GaugeStrategy = GaugeUse.Automatic; BloodstalkStrategy = BloodstalkUse.Automatic; + SoulSliceStrategy = OffensiveAbilityUse.Automatic; TrueNorthStrategy = TrueNorthUse.Automatic; EnshroudStrategy = EnshroudUse.Automatic; ArcaneCircleStrategy = OffensiveAbilityUse.Automatic; @@ -357,6 +361,9 @@ public static bool ShouldUseGluttony(State state, Strategy strategy) if (enshrouded) return false; + if (!state.Unlocked(AID.Gluttony)) + return false; + if (ShouldUseEnshroud(state, strategy)) return false; @@ -393,7 +400,7 @@ public static bool ShouldUseEnshroud(State state, Strategy strategy) return false; if (state.ArcaneCircleLeft > state.AnimationLock && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0) && state.CD(CDGroup.Enshroud) < state.GCD) return true; - if ((state.CD(CDGroup.ArcaneCircle) < 5 + state.GCD || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0) && state.CD(CDGroup.Enshroud) < state.GCD) + if ((state.CD(CDGroup.ArcaneCircle) < 9 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0) && state.CD(CDGroup.Enshroud) < state.GCD) return true; return false; @@ -418,7 +425,7 @@ public static bool ShouldUseArcaneCircle(State state, Strategy strategy) if (soulReaver) return false; - if (enshrouded && state.CD(CDGroup.Enshroud) < 10.5f && state.TargetDeathDesignLeft > 30) + if (enshrouded && state.TargetDeathDesignLeft > 30) return true; if (state.ShroudGauge < 50 && !enshrouded && state.TargetDeathDesignLeft > 0) return true; @@ -430,7 +437,7 @@ public static bool ShouldUseArcaneCircle(State state, Strategy strategy) { Strategy.PotionUse.Manual => false, Strategy.PotionUse.Opener => state.CD(CDGroup.ArcaneCircle) > state.GCD && state.CD(CDGroup.SoulSlice) > 0, - Strategy.PotionUse.Burst => state.CD(CDGroup.ArcaneCircle) < 6 && state.EnshroudedLeft > 25 && state.EnshroudedLeft < 29 && state.TargetDeathDesignLeft > 28, + Strategy.PotionUse.Burst => state.CD(CDGroup.ArcaneCircle) < 9 && state.lastActionisSoD && state.TargetDeathDesignLeft > 28, Strategy.PotionUse.Force => true, _ => false }; @@ -477,6 +484,34 @@ public static bool ShouldUseTrueNorth(State state, Strategy strategy) } } + public static bool ShouldUseSoulSlice(State state, Strategy strategy, bool aoe) + { + bool plentifulReady = state.Unlocked(AID.PlentifulHarvest) && state.ImmortalSacrificeLeft > state.AnimationLock && state.CircleofSacrificeLeft < state.GCD; + bool soulReaver = state.Unlocked(AID.BloodStalk) && state.SoulReaverLeft > state.AnimationLock; + bool enshrouded = state.Unlocked(AID.Enshroud) && state.EnshroudedLeft > state.AnimationLock; + switch (strategy.SoulSliceStrategy) + { + case Strategy.OffensiveAbilityUse.Delay: + return false; + + case Strategy.OffensiveAbilityUse.Force: + return true; + + default: + if (!state.TargetingEnemy) + return false; + if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && (state.ComboTimeLeft > 5 || state.ComboTimeLeft == 0) && state.CD(CDGroup.ArcaneCircle) > 11.5f) + return true; + if (enshrouded) + return false; + if (soulReaver) + return false; + if (state.ArcaneCircleLeft > state.AnimationLock && state.ComboTimeLeft < 11) + return false; + return false; + } + } + public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) { bool plentifulReady = state.Unlocked(AID.PlentifulHarvest) && state.ImmortalSacrificeLeft > state.AnimationLock && state.CircleofSacrificeLeft < state.GCD; @@ -502,8 +537,40 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.Harpe; if (strategy.GaugeStrategy == Strategy.GaugeUse.ForceExtendDD && state.Unlocked(AID.ShadowofDeath) && !soulReaver) return aoe ? AID.WhorlofDeath : AID.ShadowofDeath; - if (strategy.GaugeStrategy == Strategy.GaugeUse.PenultimateComboThenSpend && state.ComboLastMove != AID.WaxingSlice && state.ComboLastMove != AID.NightmareScythe && (state.ComboLastMove != AID.Slice || state.SoulGauge <= 90) && !soulReaver) - return aoe ? AID.NightmareScythe : state.ComboLastMove == AID.Slice ? AID.WaxingSlice : AID.Slice; + + if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.ShroudGauge >= 50) + { + if (state.HasSoulsow) + { + if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < state.GCD + 2.5) + return AID.ShadowofDeath; + if (state.CD(CDGroup.ArcaneCircle) < 7.5f) + return AID.Enshroud; + if (state.LemureShroudCount is 4 && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 8) + return AID.ShadowofDeath; + if (state.LemureShroudCount is 1) + return AID.HarvestMoon; + } + if (!state.HasSoulsow) + { + if (plentifulReady && state.BloodsownCircleLeft < 1 && !soulReaver && !enshrouded && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0)) + return AID.PlentifulHarvest; + if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) + return AID.Communio; + if (state.Unlocked(AID.LemuresSlice) && state.VoidShroudCount >= 2 && state.CD(CDGroup.ArcaneCircle) > 10) + return AID.LemuresSlice; + if (state.EnhancedVoidReapingLeft > state.AnimationLock) + return AID.VoidReaping; + if (state.EnhancedCrossReapingLeft > state.AnimationLock) + return AID.CrossReaping; + return AID.CrossReaping; + } + if (ShouldUseSoulSlice(state, strategy, aoe)) + return aoe ? AID.SoulScythe : AID.SoulSlice; + if (state.SoulReaverLeft > state.GCD) + return GetNextBSAction(state, aoe); + return GetNextUnlockedComboAction(state, aoe); + } if (!aoe) { @@ -516,7 +583,6 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.WhorlofDeath; } - if (plentifulReady && state.BloodsownCircleLeft < 1 && !soulReaver && !enshrouded && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0)) return AID.PlentifulHarvest; @@ -525,11 +591,11 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (enshrouded && !aoe) { - if (state.CD(CDGroup.ArcaneCircle) < 6.5) + if ((state.LemureShroudCount == 4 || state.LemureShroudCount == 3) && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 9) return AID.ShadowofDeath; if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) return AID.Communio; - if (state.Unlocked(AID.LemuresSlice) && state.VoidShroudCount >= 2) + if (state.Unlocked(AID.LemuresSlice) && state.VoidShroudCount >= 2 && state.CD(CDGroup.ArcaneCircle) > 10) return AID.LemuresSlice; if (state.EnhancedVoidReapingLeft > state.AnimationLock) return AID.VoidReaping; @@ -538,6 +604,7 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.CrossReaping; } + if (enshrouded && aoe) { if (state.CD(CDGroup.ArcaneCircle) < 6) @@ -548,17 +615,15 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.GrimReaping; } - if (state.SoulReaverLeft > state.GCD) return GetNextBSAction(state, aoe); - if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && state.Unlocked(AID.SoulScythe) && !enshrouded && !soulReaver && aoe && (state.ComboTimeLeft > 2.5 + 2.5 || state.ComboTimeLeft == 0) && state.CD(CDGroup.ArcaneCircle) > 8) + if (ShouldUseSoulSlice(state, strategy, aoe) && aoe) return AID.SoulScythe; - if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && state.Unlocked(AID.SoulSlice) && !enshrouded && !soulReaver && !aoe && (state.ComboTimeLeft > 2.5 + 2.5 || state.ComboTimeLeft == 0) && state.CD(CDGroup.ArcaneCircle) > 8) + if (ShouldUseSoulSlice(state, strategy, aoe) && !aoe) return AID.SoulSlice; - return GetNextUnlockedComboAction(state, aoe); } @@ -569,6 +634,38 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea var (positional, shouldUsePositional) = GetNextPositional(state, strategy); //if (strategy.ArcaneCircleStrategy == Strategy.ArcaneCircleUse.Delay) // return ActionID.MakeSpell(AID.Enshroud); + if (strategy.PotionStrategy == Strategy.PotionUse.Special) + { + if (state.HasSoulsow) + { + if (state.LemureShroudCount is 4 && state.CanWeave(state.PotionCD, 1.1f, deadline) && state.lastActionisSoD) + return CommonDefinitions.IDPotionStr; + if (state.LemureShroudCount is 3 && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) + return ActionID.MakeSpell(AID.ArcaneCircle); + if (state.CD(CDGroup.ArcaneCircle) > 11 && state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline)) + return ActionID.MakeSpell(AID.LemuresSlice); + } + if (!state.HasSoulsow) + { + if (ShouldUseTrueNorth(state, strategy) && state.CanWeave(CDGroup.TrueNorth - 45, 0.6f, deadline) && !aoe && state.GCD < 0.8) + return ActionID.MakeSpell(AID.TrueNorth); + if (ShouldUseEnshroud(state, strategy) && state.Unlocked(AID.Enshroud) && state.CanWeave(CDGroup.Enshroud, 0.6f, deadline)) + return ActionID.MakeSpell(AID.Enshroud); + if (ShouldUseArcaneCircle(state, strategy) && state.Unlocked(AID.ArcaneCircle) && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) + return ActionID.MakeSpell(AID.ArcaneCircle); + if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && !aoe && state.CD(CDGroup.ArcaneCircle) > 10) + return ActionID.MakeSpell(AID.LemuresSlice); + if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && aoe && state.CD(CDGroup.ArcaneCircle) > 10) + return ActionID.MakeSpell(AID.LemuresScythe); + if (ShouldUseGluttony(state, strategy) && state.CanWeave(CDGroup.Gluttony, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 5) + return ActionID.MakeSpell(AID.Gluttony); + if (ShouldUseBloodstalk(state, strategy, aoe) && state.Unlocked(AID.BloodStalk) && state.CanWeave(CDGroup.BloodStalk, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 2.5) + return ActionID.MakeSpell(state.Beststalk); + if (ShouldUseGrimSwathe(state, strategy, aoe) && state.Unlocked(AID.GrimSwathe) && state.CanWeave(CDGroup.BloodStalk, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 2.5) + return ActionID.MakeSpell(AID.GrimSwathe); + } + } + if (ShouldUsePotion(state, strategy) && state.CanWeave(state.PotionCD, 1.1f, deadline)) return CommonDefinitions.IDPotionStr; if (ShouldUseTrueNorth(state, strategy) && state.CanWeave(CDGroup.TrueNorth - 45, 0.6f, deadline) && !aoe && state.GCD < 0.8) @@ -577,9 +674,9 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea return ActionID.MakeSpell(AID.Enshroud); if (ShouldUseArcaneCircle(state, strategy) && state.Unlocked(AID.ArcaneCircle) && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) return ActionID.MakeSpell(AID.ArcaneCircle); - if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && !aoe) + if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && !aoe && state.CD(CDGroup.ArcaneCircle) > 10) return ActionID.MakeSpell(AID.LemuresSlice); - if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && aoe) + if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && aoe && state.CD(CDGroup.ArcaneCircle) > 10) return ActionID.MakeSpell(AID.LemuresScythe); if (ShouldUseGluttony(state, strategy) && state.Unlocked(AID.Gluttony) && state.CanWeave(CDGroup.Gluttony, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 5) return ActionID.MakeSpell(AID.Gluttony); @@ -588,7 +685,6 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea if (ShouldUseGrimSwathe(state, strategy, aoe) && state.Unlocked(AID.GrimSwathe) && state.CanWeave(CDGroup.BloodStalk, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 2.5) return ActionID.MakeSpell(AID.GrimSwathe); - return new(); } } diff --git a/BossMod/CooldownPlanner/PlanDefinitions.cs b/BossMod/CooldownPlanner/PlanDefinitions.cs index 4030b4ed40..aecfcb3db9 100644 --- a/BossMod/CooldownPlanner/PlanDefinitions.cs +++ b/BossMod/CooldownPlanner/PlanDefinitions.cs @@ -169,6 +169,7 @@ private static ClassData DefineRPR() c.CooldownTracks.Add(new("Sprint", CommonDefinitions.IDSprint, 1)); c.StrategyTracks.Add(new("Gauge", typeof(RPR.Rotation.Strategy.GaugeUse))); c.StrategyTracks.Add(new("SOUL", typeof(RPR.Rotation.Strategy.BloodstalkUse))); + c.StrategyTracks.Add(new("SS", typeof(RPR.Rotation.Strategy.OffensiveAbilityUse))); c.StrategyTracks.Add(new("TrN", typeof(RPR.Rotation.Strategy.TrueNorthUse))); c.StrategyTracks.Add(new("ENSH", typeof(RPR.Rotation.Strategy.EnshroudUse))); c.StrategyTracks.Add(new("ARC", typeof(RPR.Rotation.Strategy.ArcaneCircleUse))); From d3d58799a286050eacbb0b7a1929284be218c599 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 16:02:21 +0100 Subject: [PATCH 11/16] small fix --- BossMod/Autorotation/RPR/RPRRotation.cs | 76 ++++++------------------- 1 file changed, 16 insertions(+), 60 deletions(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index 152c00fcb4..e0c651a7ae 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -538,38 +538,16 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (strategy.GaugeStrategy == Strategy.GaugeUse.ForceExtendDD && state.Unlocked(AID.ShadowofDeath) && !soulReaver) return aoe ? AID.WhorlofDeath : AID.ShadowofDeath; - if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.ShroudGauge >= 50) + if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow) { - if (state.HasSoulsow) - { - if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < state.GCD + 2.5) - return AID.ShadowofDeath; - if (state.CD(CDGroup.ArcaneCircle) < 7.5f) - return AID.Enshroud; - if (state.LemureShroudCount is 4 && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 8) - return AID.ShadowofDeath; - if (state.LemureShroudCount is 1) - return AID.HarvestMoon; - } - if (!state.HasSoulsow) - { - if (plentifulReady && state.BloodsownCircleLeft < 1 && !soulReaver && !enshrouded && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0)) - return AID.PlentifulHarvest; - if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) - return AID.Communio; - if (state.Unlocked(AID.LemuresSlice) && state.VoidShroudCount >= 2 && state.CD(CDGroup.ArcaneCircle) > 10) - return AID.LemuresSlice; - if (state.EnhancedVoidReapingLeft > state.AnimationLock) - return AID.VoidReaping; - if (state.EnhancedCrossReapingLeft > state.AnimationLock) - return AID.CrossReaping; - return AID.CrossReaping; - } - if (ShouldUseSoulSlice(state, strategy, aoe)) - return aoe ? AID.SoulScythe : AID.SoulSlice; - if (state.SoulReaverLeft > state.GCD) - return GetNextBSAction(state, aoe); - return GetNextUnlockedComboAction(state, aoe); + if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < state.GCD + 2.5) + return AID.ShadowofDeath; + if (state.CD(CDGroup.ArcaneCircle) < 7.5f) + return AID.Enshroud; + if (state.LemureShroudCount is 4 && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 8) + return AID.ShadowofDeath; + if (state.LemureShroudCount is 1) + return AID.HarvestMoon; } if (!aoe) @@ -634,36 +612,14 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea var (positional, shouldUsePositional) = GetNextPositional(state, strategy); //if (strategy.ArcaneCircleStrategy == Strategy.ArcaneCircleUse.Delay) // return ActionID.MakeSpell(AID.Enshroud); - if (strategy.PotionStrategy == Strategy.PotionUse.Special) + if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow) { - if (state.HasSoulsow) - { - if (state.LemureShroudCount is 4 && state.CanWeave(state.PotionCD, 1.1f, deadline) && state.lastActionisSoD) - return CommonDefinitions.IDPotionStr; - if (state.LemureShroudCount is 3 && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) - return ActionID.MakeSpell(AID.ArcaneCircle); - if (state.CD(CDGroup.ArcaneCircle) > 11 && state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline)) - return ActionID.MakeSpell(AID.LemuresSlice); - } - if (!state.HasSoulsow) - { - if (ShouldUseTrueNorth(state, strategy) && state.CanWeave(CDGroup.TrueNorth - 45, 0.6f, deadline) && !aoe && state.GCD < 0.8) - return ActionID.MakeSpell(AID.TrueNorth); - if (ShouldUseEnshroud(state, strategy) && state.Unlocked(AID.Enshroud) && state.CanWeave(CDGroup.Enshroud, 0.6f, deadline)) - return ActionID.MakeSpell(AID.Enshroud); - if (ShouldUseArcaneCircle(state, strategy) && state.Unlocked(AID.ArcaneCircle) && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) - return ActionID.MakeSpell(AID.ArcaneCircle); - if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && !aoe && state.CD(CDGroup.ArcaneCircle) > 10) - return ActionID.MakeSpell(AID.LemuresSlice); - if (state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline) && aoe && state.CD(CDGroup.ArcaneCircle) > 10) - return ActionID.MakeSpell(AID.LemuresScythe); - if (ShouldUseGluttony(state, strategy) && state.CanWeave(CDGroup.Gluttony, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 5) - return ActionID.MakeSpell(AID.Gluttony); - if (ShouldUseBloodstalk(state, strategy, aoe) && state.Unlocked(AID.BloodStalk) && state.CanWeave(CDGroup.BloodStalk, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 2.5) - return ActionID.MakeSpell(state.Beststalk); - if (ShouldUseGrimSwathe(state, strategy, aoe) && state.Unlocked(AID.GrimSwathe) && state.CanWeave(CDGroup.BloodStalk, 0.6f, deadline) && !enshrouded && state.TargetDeathDesignLeft > 2.5) - return ActionID.MakeSpell(AID.GrimSwathe); - } + if (state.LemureShroudCount is 4 && state.CanWeave(state.PotionCD, 1.1f, deadline) && state.lastActionisSoD) + return CommonDefinitions.IDPotionStr; + if (state.LemureShroudCount is 3 && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) + return ActionID.MakeSpell(AID.ArcaneCircle); + if (state.CD(CDGroup.ArcaneCircle) > 11 && state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline)) + return ActionID.MakeSpell(AID.LemuresSlice); } if (ShouldUsePotion(state, strategy) && state.CanWeave(state.PotionCD, 1.1f, deadline)) From 22315d43794ce5167523d65f0bf2a1eb9b8b63d6 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 16:56:04 +0100 Subject: [PATCH 12/16] more RPR optimizations --- BossMod/Autorotation/RPR/RPRRotation.cs | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index e0c651a7ae..7b7897bbe8 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -540,7 +540,7 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow) { - if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < state.GCD + 2.5) + if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < 30) return AID.ShadowofDeath; if (state.CD(CDGroup.ArcaneCircle) < 7.5f) return AID.Enshroud; @@ -548,6 +548,29 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.ShadowofDeath; if (state.LemureShroudCount is 1) return AID.HarvestMoon; + if (enshrouded && !aoe) + { + if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) + return AID.Communio; + if (state.EnhancedVoidReapingLeft > state.AnimationLock) + return AID.VoidReaping; + if (state.EnhancedCrossReapingLeft > state.AnimationLock) + return AID.CrossReaping; + + return AID.CrossReaping; + } + if (state.SoulReaverLeft > state.GCD) + return GetNextBSAction(state, aoe); + + if (state.SoulReaverLeft > state.GCD) + return GetNextBSAction(state, aoe); + + if (ShouldUseSoulSlice(state, strategy, aoe) && aoe) + return AID.SoulScythe; + + if (ShouldUseSoulSlice(state, strategy, aoe) && !aoe) + return AID.SoulSlice; + return GetNextUnlockedComboAction(state, aoe); } if (!aoe) @@ -614,6 +637,8 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea // return ActionID.MakeSpell(AID.Enshroud); if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow) { + if (state.CD(CDGroup.ArcaneCircle) < 7.5f && state.ShroudGauge >= 50 && state.CanWeave(CDGroup.Enshroud, 0.6f, deadline)) + return ActionID.MakeSpell(AID.Enshroud); if (state.LemureShroudCount is 4 && state.CanWeave(state.PotionCD, 1.1f, deadline) && state.lastActionisSoD) return CommonDefinitions.IDPotionStr; if (state.LemureShroudCount is 3 && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) From bf80d6e2dd628391a64c5b0efe8bce38634f4fbf Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 16:56:35 +0100 Subject: [PATCH 13/16] kek --- BossMod/Autorotation/RPR/RPRRotation.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index 7b7897bbe8..03bbcc1bd3 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -542,8 +542,6 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) { if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < 30) return AID.ShadowofDeath; - if (state.CD(CDGroup.ArcaneCircle) < 7.5f) - return AID.Enshroud; if (state.LemureShroudCount is 4 && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 8) return AID.ShadowofDeath; if (state.LemureShroudCount is 1) From 78f8a34f7ddde657edd4a6100ff32f87d62a5856 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 18:39:43 +0100 Subject: [PATCH 14/16] RPR harvest moon pot fix --- BossMod/Autorotation/RPR/RPRRotation.cs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index 03bbcc1bd3..266642ec2c 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -500,7 +500,7 @@ public static bool ShouldUseSoulSlice(State state, Strategy strategy, bool aoe) default: if (!state.TargetingEnemy) return false; - if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && (state.ComboTimeLeft > 5 || state.ComboTimeLeft == 0) && state.CD(CDGroup.ArcaneCircle) > 11.5f) + if (state.SoulGauge <= 50 && state.CD(CDGroup.SoulSlice) - 30 < state.GCD && (state.ComboTimeLeft > 5 || state.ComboTimeLeft == 0 || (state.ArcaneCircleLeft > state.AnimationLock && state.ComboTimeLeft > 11)) && state.CD(CDGroup.ArcaneCircle) > 11.5f) return true; if (enshrouded) return false; @@ -538,11 +538,13 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (strategy.GaugeStrategy == Strategy.GaugeUse.ForceExtendDD && state.Unlocked(AID.ShadowofDeath) && !soulReaver) return aoe ? AID.WhorlofDeath : AID.ShadowofDeath; - if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow) + if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow && state.CD(CDGroup.ArcaneCircle) < 11.5) { if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < 30) return AID.ShadowofDeath; - if (state.LemureShroudCount is 4 && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 8) + if (state.ComboTimeLeft != 0 || state.ComboTimeLeft == 0) + return GetNextUnlockedComboAction(state, aoe); + if (state.LemureShroudCount is 3 && !state.lastActionisSoD && state.PotionCD < 1) return AID.ShadowofDeath; if (state.LemureShroudCount is 1) return AID.HarvestMoon; @@ -557,17 +559,7 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) return AID.CrossReaping; } - if (state.SoulReaverLeft > state.GCD) - return GetNextBSAction(state, aoe); - - if (state.SoulReaverLeft > state.GCD) - return GetNextBSAction(state, aoe); - - if (ShouldUseSoulSlice(state, strategy, aoe) && aoe) - return AID.SoulScythe; - if (ShouldUseSoulSlice(state, strategy, aoe) && !aoe) - return AID.SoulSlice; return GetNextUnlockedComboAction(state, aoe); } @@ -590,7 +582,7 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (enshrouded && !aoe) { - if ((state.LemureShroudCount == 4 || state.LemureShroudCount == 3) && !state.lastActionisSoD && state.CD(CDGroup.ArcaneCircle) < 9) + if ((state.LemureShroudCount == 4 || state.LemureShroudCount == 3) && (!state.lastActionisSoD || strategy.PotionStrategy == Strategy.PotionUse.Burst && !state.lastActionisSoD && state.PotionCD < 1) && state.CD(CDGroup.ArcaneCircle) < 9) return AID.ShadowofDeath; if (state.Unlocked(AID.Communio) && state.LemureShroudCount is 1 && state.VoidShroudCount is 0) return AID.Communio; @@ -637,9 +629,9 @@ public static ActionID GetNextBestOGCD(State state, Strategy strategy, float dea { if (state.CD(CDGroup.ArcaneCircle) < 7.5f && state.ShroudGauge >= 50 && state.CanWeave(CDGroup.Enshroud, 0.6f, deadline)) return ActionID.MakeSpell(AID.Enshroud); - if (state.LemureShroudCount is 4 && state.CanWeave(state.PotionCD, 1.1f, deadline) && state.lastActionisSoD) + if (state.LemureShroudCount is 3 && state.CanWeave(state.PotionCD, 1.1f, deadline) && state.lastActionisSoD) return CommonDefinitions.IDPotionStr; - if (state.LemureShroudCount is 3 && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) + if (state.LemureShroudCount is 2 && state.CanWeave(CDGroup.ArcaneCircle, 0.6f, deadline)) return ActionID.MakeSpell(AID.ArcaneCircle); if (state.CD(CDGroup.ArcaneCircle) > 11 && state.VoidShroudCount >= 2 && state.CanWeave(CDGroup.LemuresSlice, 0.6f, deadline)) return ActionID.MakeSpell(AID.LemuresSlice); From dc90484f3aa2c83875ca49cff563ccde09f7888d Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 19:13:47 +0100 Subject: [PATCH 15/16] RPR fix --- BossMod/Autorotation/RPR/RPRRotation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index 266642ec2c..1c8c398710 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -538,11 +538,11 @@ public static AID GetNextBestGCD(State state, Strategy strategy, bool aoe) if (strategy.GaugeStrategy == Strategy.GaugeUse.ForceExtendDD && state.Unlocked(AID.ShadowofDeath) && !soulReaver) return aoe ? AID.WhorlofDeath : AID.ShadowofDeath; - if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow && state.CD(CDGroup.ArcaneCircle) < 11.5) + if (strategy.PotionStrategy == Strategy.PotionUse.Special && state.HasSoulsow && (state.CD(CDGroup.ArcaneCircle) < 11.5 || state.CD(CDGroup.ArcaneCircle) > 115)) { if (state.CD(CDGroup.ArcaneCircle) < 11.5f && state.TargetDeathDesignLeft < 30) return AID.ShadowofDeath; - if (state.ComboTimeLeft != 0 || state.ComboTimeLeft == 0) + if (state.ComboTimeLeft != 0 || state.ComboTimeLeft == 0 && !enshrouded && !soulReaver) return GetNextUnlockedComboAction(state, aoe); if (state.LemureShroudCount is 3 && !state.lastActionisSoD && state.PotionCD < 1) return AID.ShadowofDeath; From fb4f26be4742ee59e6950ee01a908e79da303856 Mon Sep 17 00:00:00 2001 From: lazylemo Date: Sun, 7 Jan 2024 23:08:01 +0100 Subject: [PATCH 16/16] small fixes --- BossMod/Autorotation/RPR/RPRRotation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BossMod/Autorotation/RPR/RPRRotation.cs b/BossMod/Autorotation/RPR/RPRRotation.cs index 1c8c398710..52aec77034 100644 --- a/BossMod/Autorotation/RPR/RPRRotation.cs +++ b/BossMod/Autorotation/RPR/RPRRotation.cs @@ -300,7 +300,7 @@ public static bool ShouldUseBloodstalk(State state, Strategy strategy, bool aoe) if (state.SoulGauge >= 50 && !aoe && (state.ComboTimeLeft > 2.5 || state.ComboTimeLeft == 0) && state.ImmortalSacrificeLeft > state.AnimationLock && state.BloodsownCircleLeft > 4.8f && (state.CD(CDGroup.SoulSlice) > 30 || state.CD(CDGroup.SoulSlice) < 60) && state.ShroudGauge <= 40) return true; - if ((state.CD(CDGroup.ArcaneCircle) < 6 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) + if ((state.CD(CDGroup.ArcaneCircle) < 9 || state.CD(CDGroup.ArcaneCircle) > 60) && state.ShroudGauge >= 50 && (state.ComboTimeLeft > 11 || state.ComboTimeLeft == 0)) return false; return false; } @@ -425,7 +425,7 @@ public static bool ShouldUseArcaneCircle(State state, Strategy strategy) if (soulReaver) return false; - if (enshrouded && state.TargetDeathDesignLeft > 30) + if (enshrouded && state.LemureShroudCount is 3 && state.TargetDeathDesignLeft > 30) return true; if (state.ShroudGauge < 50 && !enshrouded && state.TargetDeathDesignLeft > 0) return true;