From a4025a23c7f8da5710a51dcc449f25937062ee2a Mon Sep 17 00:00:00 2001 From: ace Date: Fri, 23 Aug 2024 05:21:29 -0700 Subject: [PATCH 001/208] BH&ROF fix --- XIVSlothCombo/Combos/PvE/MNK.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index cba7252be..dc20866ab 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -294,13 +294,15 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) { - if (Brotherhood.LevelChecked() + if (IsEnabled(CustomComboPreset.MNK_STUseBrotherhood) + && Brotherhood.LevelChecked() && !IsOnCooldown(Brotherhood)) { return Brotherhood; } - if (RiddleOfFire.LevelChecked() + if (IsEnabled(CustomComboPreset.MNK_STUseROF) + && RiddleOfFire.LevelChecked() && !IsOnCooldown(RiddleOfFire)) { return RiddleOfFire; From a51ef5076be1d3c12b0cf3ab8569fc1b609591c3 Mon Sep 17 00:00:00 2001 From: ace Date: Fri, 23 Aug 2024 07:40:46 -0700 Subject: [PATCH 002/208] whoops --- XIVSlothCombo/Combos/PvE/VPR.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 4e2765be9..19f984de5 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -432,7 +432,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Reawakend Usage - if (UseReawaken(gauge)) + if (IsEnabled(CustomComboPreset.VPR_ST_Reawaken) && UseReawaken(gauge)) return Reawaken; //Overcap protection From ebed0b27aa26564bb0628399190c8b1d3c15a4c5 Mon Sep 17 00:00:00 2001 From: edewen Date: Fri, 23 Aug 2024 12:21:38 -0400 Subject: [PATCH 003/208] Simple Mode Copied the ST advanced mode and removed configuration requirements for an optimized ST Simple mode --- XIVSlothCombo/Combos/PvE/PCT.cs | 255 +++++++++++++++++++++++++------- 1 file changed, 204 insertions(+), 51 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index df12da91e..a6eec89e8 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -87,96 +87,249 @@ public static UserBool internal class PCT_ST_SimpleMode : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.PCT_ST_SimpleMode; + internal static PCTOpenerLogicLvl100 PCTOpenerLvl100 = new(); + internal static PCTOpenerLogicLvl92 PCTOpenerLvl92 = new(); + internal static PCTOpenerLogicLvl90 PCTOpenerLvl90 = new(); + internal static PCTOpenerLogicLvl80 PCTOpenerLvl80 = new(); + internal static PCTOpenerLogicLvl70 PCTOpenerLvl70 = new(); protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { if (actionID is FireInRed) { var gauge = GetJobGauge(); - bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + bool canWeave = CanSpellWeave(ActionWatching.LastSpell) || CanSpellWeave(actionID); - if (HasEffect(Buffs.Starstruck)) - return OriginalHook(StarPrism); + // Prepull logic + + if (!InCombat() || InCombat() && CurrentTarget == null) + { + if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn) + return OriginalHook(CreatureMotif); + if (WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime)) + return OriginalHook(WeaponMotif); + if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(LandscapeMotif); + } + + // Lvl 100 Opener + if (StarPrism.LevelChecked()) + { + if (PCTOpenerLvl100.DoFullOpener(ref actionID)) + return actionID; + } + // Lvl 92 Opener + else if (!StarPrism.LevelChecked() && RainbowDrip.LevelChecked()) + { + if (PCTOpenerLvl92.DoFullOpener(ref actionID)) + return actionID; + } + // Lvl 90 Opener + else if (!StarPrism.LevelChecked() && !RainbowDrip.LevelChecked() && CometinBlack.LevelChecked()) + { + if (PCTOpenerLvl90.DoFullOpener(ref actionID)) + return actionID; + } + // Lvl 80 Opener + else if (!StarPrism.LevelChecked() && !CometinBlack.LevelChecked() && HolyInWhite.LevelChecked()) + { + if (PCTOpenerLvl80.DoFullOpener(ref actionID)) + return actionID; + } + // Lvl 70 Opener + else if (!StarPrism.LevelChecked() && !CometinBlack.LevelChecked() && !HolyInWhite.LevelChecked() && StarryMuse.LevelChecked()) + { + if (PCTOpenerLvl70.DoFullOpener(ref actionID)) + return actionID; + } + + // General Weaves + if (InCombat() && canWeave) + { + // ScenicMuse + + if (ScenicMuse.LevelChecked() && + gauge.LandscapeMotifDrawn && + gauge.WeaponMotifDrawn && + IsOffCooldown(ScenicMuse)) + { + return OriginalHook(ScenicMuse); + } + + // LivingMuse + + if (LivingMuse.LevelChecked() && + gauge.CreatureMotifDrawn && + (!(gauge.MooglePortraitReady || gauge.MadeenPortraitReady) || + GetRemainingCharges(LivingMuse) == GetMaxCharges(LivingMuse))) + { + if (HasCharges(OriginalHook(LivingMuse))) + { + if (!ScenicMuse.LevelChecked() || + GetCooldown(ScenicMuse).CooldownRemaining > GetCooldownChargeRemainingTime(LivingMuse)) + { + return OriginalHook(LivingMuse); + } + } + } + + // SteelMuse + + if (SteelMuse.LevelChecked() && + !HasEffect(Buffs.HammerTime) && + gauge.WeaponMotifDrawn && + HasCharges(OriginalHook(SteelMuse)) && + (GetCooldown(SteelMuse).CooldownRemaining < GetCooldown(ScenicMuse).CooldownRemaining || + GetRemainingCharges(SteelMuse) == GetMaxCharges(SteelMuse) || + !ScenicMuse.LevelChecked())) + { + return OriginalHook(SteelMuse); + } + + // MogoftheAges + + if (MogoftheAges.LevelChecked() && + (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && + IsOffCooldown(OriginalHook(MogoftheAges)) && + (GetCooldownRemainingTime(StarryMuse) >= 60 || !ScenicMuse.LevelChecked())) + { + return OriginalHook(MogoftheAges); + } + + // Swiftcast + + if (IsMoving && + IsOffCooldown(All.Swiftcast) && + All.Swiftcast.LevelChecked() && + !HasEffect(Buffs.HammerTime) && + gauge.Paint < 1 && + (!gauge.CreatureMotifDrawn || !gauge.WeaponMotifDrawn || !gauge.LandscapeMotifDrawn)) + { + return All.Swiftcast; + } + + // SubtractivePalette + + if (SubtractivePalette.LevelChecked() && + !HasEffect(Buffs.SubtractivePalette) && + !HasEffect(Buffs.MonochromeTones)) + { + if (HasEffect(Buffs.SubtractiveSpectrum) || gauge.PalleteGauge >= 50) + { + return SubtractivePalette; + } + } + } - if (HasEffect(Buffs.RainbowBright)) - return OriginalHook(RainbowDrip); + // Swiftcast Motifs + if (HasEffect(All.Buffs.Swiftcast)) + { + if (!gauge.CreatureMotifDrawn && CreatureMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(CreatureMotif); + if (!gauge.WeaponMotifDrawn && HammerMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(HammerMotif); + if (!gauge.LandscapeMotifDrawn && LandscapeMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(LandscapeMotif); + } - if (IsMoving) + // IsMoving logic + if (IsMoving && InCombat()) { - if (gauge.Paint > 0) - { - if (HasEffect(Buffs.MonochromeTones)) - return OriginalHook(CometinBlack); + if (HammerStamp.LevelChecked() && HasEffect(Buffs.HammerTime)) + return OriginalHook(HammerStamp); + + if (CometinBlack.LevelChecked() && gauge.Paint >= 1 && HasEffect(Buffs.MonochromeTones)) + return OriginalHook(CometinBlack); + if (HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); - } } - - if (HasEffect(Buffs.StarryMuse)) + //Prepare for Burst + if (GetCooldownRemainingTime(ScenicMuse) <= 20) { - if (HasEffect(Buffs.SubtractiveSpectrum) && !HasEffect(Buffs.SubtractivePalette) && canWeave) - return OriginalHook(SubtractivePalette); + if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn) + return OriginalHook(LandscapeMotif); - if (MogoftheAges.LevelChecked() && (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && IsOffCooldown(OriginalHook(MogoftheAges))) - return OriginalHook(MogoftheAges); + if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn) + return OriginalHook(CreatureMotif); - if (!HasEffect(Buffs.HammerTime) && gauge.WeaponMotifDrawn && HasCharges(OriginalHook(SteelMuse)) && GetBuffRemainingTime(Buffs.StarryMuse) >= 15f) - return OriginalHook(SteelMuse); + if (WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime)) + return OriginalHook(WeaponMotif); + } - if (gauge.CreatureMotifDrawn && HasCharges(OriginalHook(LivingMuse)) && canWeave) - return OriginalHook(LivingMuse); + // Burst + if (HasEffect(Buffs.StarryMuse)) + { - if (HasEffect(Buffs.HammerTime)) + if (CometinBlack.LevelChecked() && HasEffect(Buffs.MonochromeTones) && gauge.Paint > 0) + return CometinBlack; + + if (HammerStamp.LevelChecked() && HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.Starstruck)) return OriginalHook(HammerStamp); - if (HasEffect(Buffs.SubtractivePalette)) - return OriginalHook(BlizzardinCyan); + if (HasEffect(Buffs.Starstruck) || HasEffect(Buffs.Starstruck) && GetBuffRemainingTime(Buffs.Starstruck) <= 3f) + return StarPrism; + + if (HasEffect(Buffs.RainbowBright) || HasEffect(Buffs.RainbowBright) && GetBuffRemainingTime(Buffs.StarryMuse) <= 3f) + return RainbowDrip; + - return actionID; } - if (gauge.PalleteGauge >= 50 && !HasEffect(Buffs.SubtractivePalette) && canWeave) - return OriginalHook(SubtractivePalette); + if (HasEffect(Buffs.RainbowBright) && !HasEffect(Buffs.StarryMuse)) + return RainbowDrip; - if (HasEffect(Buffs.HammerTime) && !canWeave) + if (CometinBlack.LevelChecked() && HasEffect(Buffs.MonochromeTones) && gauge.Paint > 0 && GetCooldownRemainingTime(StarryMuse) > 30f) + return OriginalHook(CometinBlack); + + if (HammerStamp.LevelChecked() && HasEffect(Buffs.HammerTime)) return OriginalHook(HammerStamp); - if (InCombat()) + if (!HasEffect(Buffs.StarryMuse)) { - if (gauge.LandscapeMotifDrawn && gauge.WeaponMotifDrawn && (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && IsOffCooldown(MogoftheAges) && IsOffCooldown(ScenicMuse) && canWeave) - return OriginalHook(ScenicMuse); - - if (MogoftheAges.LevelChecked() && (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && IsOffCooldown(OriginalHook(MogoftheAges)) && (GetCooldown(LivingMuse).CooldownRemaining < GetCooldown(ScenicMuse).CooldownRemaining || !ScenicMuse.LevelChecked()) && canWeave) - return OriginalHook(MogoftheAges); - - if (!HasEffect(Buffs.HammerTime) && gauge.WeaponMotifDrawn && HasCharges(OriginalHook(SteelMuse)) && (GetCooldown(SteelMuse).CooldownRemaining < GetCooldown(ScenicMuse).CooldownRemaining || GetRemainingCharges(SteelMuse) == GetMaxCharges(SteelMuse) || !ScenicMuse.LevelChecked()) && canWeave) - return OriginalHook(SteelMuse); - - if (gauge.CreatureMotifDrawn && (!(gauge.MooglePortraitReady || gauge.MadeenPortraitReady) || GetCooldown(LivingMuse).CooldownRemaining > GetCooldown(ScenicMuse).CooldownRemaining || GetRemainingCharges(LivingMuse) == GetMaxCharges(LivingMuse) || !ScenicMuse.LevelChecked()) && HasCharges(OriginalHook(LivingMuse)) && canWeave) - return OriginalHook(LivingMuse); - - if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && GetCooldownRemainingTime(ScenicMuse) <= GetActionCastTime(OriginalHook(LandscapeMotif))) + // LandscapeMotif + + if (LandscapeMotif.LevelChecked() && + !gauge.LandscapeMotifDrawn && + GetCooldownRemainingTime(ScenicMuse) <= 20) + { return OriginalHook(LandscapeMotif); - - if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && (HasCharges(LivingMuse) || GetCooldownChargeRemainingTime(LivingMuse) <= GetActionCastTime(OriginalHook(CreatureMotif)))) + } + + // CreatureMotif + + if (CreatureMotif.LevelChecked() && + !gauge.CreatureMotifDrawn && + (HasCharges(LivingMuse) || GetCooldownChargeRemainingTime(LivingMuse) <= 8)) + { return OriginalHook(CreatureMotif); - - if (WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !gauge.WeaponMotifDrawn && (HasCharges(SteelMuse) || GetCooldownChargeRemainingTime(SteelMuse) <= GetActionCastTime(OriginalHook(WeaponMotif)))) + } + + // WeaponMotif + + if (WeaponMotif.LevelChecked() && + !HasEffect(Buffs.HammerTime) && + !gauge.WeaponMotifDrawn && + (HasCharges(SteelMuse) || GetCooldownChargeRemainingTime(SteelMuse) <= 8)) + { return OriginalHook(WeaponMotif); - + } } - if (gauge.Paint > 0 && HasEffect(Buffs.MonochromeTones)) - return OriginalHook(CometinBlack); - if (HasEffect(Buffs.SubtractivePalette)) - return OriginalHook(BlizzardinCyan); + if (All.LucidDreaming.LevelChecked() && ActionReady(All.LucidDreaming) && CanSpellWeave(actionID) && LocalPlayer.CurrentMp <= 6500) + return All.LucidDreaming; + + if (BlizzardIIinCyan.LevelChecked() && HasEffect(Buffs.SubtractivePalette)) + return OriginalHook(BlizzardinCyan); } + return actionID; } } + internal class PCT_ST_AdvancedMode : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.PCT_ST_AdvancedMode; From 80d3cbff15a1588a2c28f1dee5d6e80e894174a3 Mon Sep 17 00:00:00 2001 From: edewen Date: Fri, 23 Aug 2024 12:46:47 -0400 Subject: [PATCH 004/208] Aoe Simple mode Copied advanced aoe into simple and removed the configs for an optimized simple one button. --- XIVSlothCombo/Combos/PvE/PCT.cs | 195 +++++++++++++++++++++++--------- 1 file changed, 142 insertions(+), 53 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index a6eec89e8..c2d196b69 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -616,85 +616,174 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell); - if (HasEffect(Buffs.Starstruck)) - return OriginalHook(StarPrism); - - if (HasEffect(Buffs.RainbowBright)) - return OriginalHook(RainbowDrip); + // Prepull logic + + + if (!InCombat() || InCombat() && CurrentTarget == null) + { + if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn) + return OriginalHook(CreatureMotif); + if (WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime)) + return OriginalHook(WeaponMotif); + if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(LandscapeMotif); + } + - if (IsMoving) + // General Weaves + if (InCombat() && canWeave) { - if (gauge.Paint > 0) + // LivingMuse + + if (LivingMuse.LevelChecked() && + gauge.CreatureMotifDrawn && + (!(gauge.MooglePortraitReady || gauge.MadeenPortraitReady) || + GetRemainingCharges(LivingMuse) == GetMaxCharges(LivingMuse))) { - if (HasEffect(Buffs.MonochromeTones)) - return OriginalHook(CometinBlack); - - return OriginalHook(HolyInWhite); + if (HasCharges(OriginalHook(LivingMuse))) + { + if (!ScenicMuse.LevelChecked() || + GetCooldown(ScenicMuse).CooldownRemaining > GetCooldownChargeRemainingTime(LivingMuse)) + { + return OriginalHook(LivingMuse); + } + } + } + + // ScenicMuse + + if (ScenicMuse.LevelChecked() && + gauge.LandscapeMotifDrawn && + gauge.WeaponMotifDrawn && + IsOffCooldown(ScenicMuse)) + { + return OriginalHook(ScenicMuse); + } + + // SteelMuse + + if (SteelMuse.LevelChecked() && + !HasEffect(Buffs.HammerTime) && + gauge.WeaponMotifDrawn && + HasCharges(OriginalHook(SteelMuse)) && + (GetCooldown(SteelMuse).CooldownRemaining < GetCooldown(ScenicMuse).CooldownRemaining || + GetRemainingCharges(SteelMuse) == GetMaxCharges(SteelMuse) || + !ScenicMuse.LevelChecked())) + { + return OriginalHook(SteelMuse); + } + + // MogoftheAges + + if (MogoftheAges.LevelChecked() && + (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && + (IsOffCooldown(OriginalHook(MogoftheAges)) || !ScenicMuse.LevelChecked())) + { + return OriginalHook(MogoftheAges); + } + + if (IsMoving && + IsOffCooldown(All.Swiftcast) && + All.Swiftcast.LevelChecked() && + !HasEffect(Buffs.HammerTime) && + gauge.Paint < 1 && + (!gauge.CreatureMotifDrawn || !gauge.WeaponMotifDrawn || !gauge.LandscapeMotifDrawn)) + { + return All.Swiftcast; + } + + // Subtractive Palette + if (SubtractivePalette.LevelChecked() && + !HasEffect(Buffs.SubtractivePalette) && + !HasEffect(Buffs.MonochromeTones)) + { + if (HasEffect(Buffs.SubtractiveSpectrum) || gauge.PalleteGauge >= 50) + return SubtractivePalette; } } - if (HasEffect(Buffs.StarryMuse)) + if (HasEffect(All.Buffs.Swiftcast)) { - if (HasEffect(Buffs.SubtractiveSpectrum) && !HasEffect(Buffs.SubtractivePalette) && canWeave) - return OriginalHook(SubtractivePalette); - - if (MogoftheAges.LevelChecked() && (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && IsOffCooldown(OriginalHook(MogoftheAges))) - return OriginalHook(MogoftheAges); - - if (!HasEffect(Buffs.HammerTime) && gauge.WeaponMotifDrawn && HasCharges(OriginalHook(SteelMuse)) && GetBuffRemainingTime(Buffs.StarryMuse) >= 15f) - return OriginalHook(SteelMuse); - - if (gauge.CreatureMotifDrawn && HasCharges(OriginalHook(LivingMuse)) && canWeave) - return OriginalHook(LivingMuse); + if (!gauge.CreatureMotifDrawn && CreatureMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(CreatureMotif); + if (!gauge.WeaponMotifDrawn && HammerMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(HammerMotif); + if (!gauge.LandscapeMotifDrawn && LandscapeMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + return OriginalHook(LandscapeMotif); + } - if (HasEffect(Buffs.HammerTime)) + if (IsMoving && InCombat()) + { + if (HammerStamp.LevelChecked() && HasEffect(Buffs.HammerTime)) return OriginalHook(HammerStamp); - if (HasEffect(Buffs.SubtractivePalette)) - return OriginalHook(BlizzardIIinCyan); + if (CometinBlack.LevelChecked() && gauge.Paint >= 1 && HasEffect(Buffs.MonochromeTones)) + return OriginalHook(CometinBlack); + + if (HolyInWhite.LevelChecked() && gauge.Paint >= 1) + return OriginalHook(HolyInWhite); - return actionID; } - if (gauge.PalleteGauge >= 50 && !HasEffect(Buffs.SubtractivePalette) && canWeave) - return OriginalHook(SubtractivePalette); + //Prepare for Burst + if (GetCooldownRemainingTime(ScenicMuse) <= 20) + { + if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn) + return OriginalHook(LandscapeMotif); - if (HasEffect(Buffs.HammerTime) && !canWeave) - return OriginalHook(HammerStamp); + if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn) + return OriginalHook(CreatureMotif); - if (InCombat()) + if (WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime)) + return OriginalHook(WeaponMotif); + } + + // Burst + if (HasEffect(Buffs.StarryMuse)) { - if (gauge.LandscapeMotifDrawn && gauge.WeaponMotifDrawn && (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && IsOffCooldown(MogoftheAges) && IsOffCooldown(ScenicMuse) && canWeave) - return OriginalHook(ScenicMuse); + // Check for CometInBlack + if (CometinBlack.LevelChecked() && HasEffect(Buffs.MonochromeTones) && gauge.Paint > 0) + return CometinBlack; - if (MogoftheAges.LevelChecked() && (gauge.MooglePortraitReady || gauge.MadeenPortraitReady) && IsOffCooldown(OriginalHook(MogoftheAges)) && (GetCooldown(MogoftheAges).CooldownRemaining < GetCooldown(ScenicMuse).CooldownRemaining || !ScenicMuse.LevelChecked()) && canWeave) - return OriginalHook(MogoftheAges); + // Check for HammerTime + if (HammerStamp.LevelChecked() && HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.Starstruck)) + return OriginalHook(HammerStamp); - if (!HasEffect(Buffs.HammerTime) && gauge.WeaponMotifDrawn && HasCharges(OriginalHook(SteelMuse)) && (GetCooldown(SteelMuse).CooldownRemaining < GetCooldown(ScenicMuse).CooldownRemaining || GetRemainingCharges(SteelMuse) == GetMaxCharges(SteelMuse) || !ScenicMuse.LevelChecked()) && canWeave) - return OriginalHook(SteelMuse); + // Check for Starstruck + if (HasEffect(Buffs.Starstruck) || (HasEffect(Buffs.Starstruck) && GetBuffRemainingTime(Buffs.Starstruck) < 3)) + return StarPrism; + + // Check for RainbowBright + if (HasEffect(Buffs.RainbowBright) || (HasEffect(Buffs.RainbowBright) && GetBuffRemainingTime(Buffs.StarryMuse) < 3)) + return RainbowDrip; + } - if (gauge.CreatureMotifDrawn && (!(gauge.MooglePortraitReady || gauge.MadeenPortraitReady) || GetCooldown(LivingMuse).CooldownRemaining > GetCooldown(ScenicMuse).CooldownRemaining || GetRemainingCharges(LivingMuse) == GetMaxCharges(LivingMuse) || !ScenicMuse.LevelChecked()) && HasCharges(OriginalHook(LivingMuse)) && canWeave) - return OriginalHook(LivingMuse); + if (HasEffect(Buffs.RainbowBright) && !HasEffect(Buffs.StarryMuse)) + return RainbowDrip; - if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && GetCooldownRemainingTime(ScenicMuse) <= GetActionCastTime(OriginalHook(LandscapeMotif))) - return OriginalHook(LandscapeMotif); + if (CometinBlack.LevelChecked() && HasEffect(Buffs.MonochromeTones) && gauge.Paint > 0 && GetCooldownRemainingTime(StarryMuse) > 60) + return OriginalHook(CometinBlack); - if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && (HasCharges(LivingMuse) || GetCooldownChargeRemainingTime(LivingMuse) <= GetActionCastTime(OriginalHook(CreatureMotif)))) - return OriginalHook(CreatureMotif); + if (HammerStamp.LevelChecked() && HasEffect(Buffs.HammerTime)) + return OriginalHook(HammerStamp); - if (WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !gauge.WeaponMotifDrawn && (HasCharges(SteelMuse) || GetCooldownChargeRemainingTime(SteelMuse) <= GetActionCastTime(OriginalHook(WeaponMotif)))) - return OriginalHook(WeaponMotif); + if (!HasEffect(Buffs.StarryMuse)) + { + if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && GetCooldownRemainingTime(ScenicMuse) <= 20) + return OriginalHook(LandscapeMotif); + + if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && (HasCharges(LivingMuse) || GetCooldownChargeRemainingTime(LivingMuse) <= 8)) + return OriginalHook(CreatureMotif); + + if (WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !gauge.WeaponMotifDrawn && (HasCharges(SteelMuse) || GetCooldownChargeRemainingTime(SteelMuse) <= 8)) + return OriginalHook(WeaponMotif); } - if (gauge.Paint > 0 && HasEffect(Buffs.MonochromeTones)) - return OriginalHook(CometinBlack); - - if (gauge.Paint > 0) - return OriginalHook(HolyInWhite); + if (All.LucidDreaming.LevelChecked() && ActionReady(All.LucidDreaming) && CanSpellWeave(actionID) && LocalPlayer.CurrentMp <= 6500) + return All.LucidDreaming; - if (HasEffect(Buffs.SubtractivePalette)) + if (BlizzardIIinCyan.LevelChecked() && HasEffect(Buffs.SubtractivePalette)) return OriginalHook(BlizzardIIinCyan); - } return actionID; } From 1727459afe01725fe4124ec16d3189cc7204417e Mon Sep 17 00:00:00 2001 From: Kage Date: Fri, 23 Aug 2024 21:24:17 +0200 Subject: [PATCH 005/208] fix below lvl 50 loop --- XIVSlothCombo/Combos/PvE/DRG.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG.cs index bad4ef110..ea011ea0e 100644 --- a/XIVSlothCombo/Combos/PvE/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG.cs @@ -214,9 +214,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (lastComboMove is TrueThrust or RaidenThrust && LevelChecked(VorpalThrust)) { return (LevelChecked(Disembowel) && - ((ChaosDoTDebuff is null) || GetBuffRemainingTime(Buffs.PowerSurge) < 15)) - ? OriginalHook(Disembowel) - : OriginalHook(VorpalThrust); + (((ChaosDoTDebuff is null) && LevelChecked(ChaosThrust)) || + GetBuffRemainingTime(Buffs.PowerSurge) < 15)) + ? OriginalHook(Disembowel) + : OriginalHook(VorpalThrust); } if (lastComboMove == OriginalHook(Disembowel) && LevelChecked(ChaosThrust)) @@ -415,7 +416,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (lastComboMove is TrueThrust or RaidenThrust && LevelChecked(VorpalThrust)) { return (LevelChecked(Disembowel) && - ((ChaosDoTDebuff is null) || GetBuffRemainingTime(Buffs.PowerSurge) < 15)) + (((ChaosDoTDebuff is null) && LevelChecked(ChaosThrust)) || + GetBuffRemainingTime(Buffs.PowerSurge) < 15)) ? OriginalHook(Disembowel) : OriginalHook(VorpalThrust); } From 507c63f0c78cdaeceb3b0740d10d39d34212afbf Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:13:47 -0500 Subject: [PATCH 006/208] Revert of RDM Prefulgence tweaks. Handled now by oGCD Options --- XIVSlothCombo/Combos/JobHelpers/RDM.cs | 16 +++++++--------- XIVSlothCombo/Combos/PvE/RDM.cs | 2 ++ XIVSlothCombo/Window/Functions/UserConfig.cs | 2 ++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/RDM.cs b/XIVSlothCombo/Combos/JobHelpers/RDM.cs index 81a1a219e..992b4d988 100644 --- a/XIVSlothCombo/Combos/JobHelpers/RDM.cs +++ b/XIVSlothCombo/Combos/JobHelpers/RDM.cs @@ -152,15 +152,6 @@ internal static bool CanUse(in uint lastComboMove, out uint actionID) return true; } - if (lastComboMove is Resolution - && TraitLevelChecked(Traits.EnhancedManaficationIII) - && HasEffect(Buffs.PrefulugenceReady)) - { - actionID = Prefulgence; - return true; - } - - actionID = 0; return false; } @@ -178,6 +169,7 @@ internal static bool CanUse(in uint actionID, in bool SingleTarget, out uint new bool contra = SingleTarget ? Config.RDM_ST_oGCD_ContraSixte : Config.RDM_AoE_oGCD_ContraSixte; bool engagement = SingleTarget ? Config.RDM_ST_oGCD_Engagement : Config.RDM_AoE_oGCD_Engagement; bool vice = SingleTarget ? Config.RDM_ST_oGCD_ViceOfThorns : Config.RDM_AoE_oGCD_ViceOfThorns; + bool prefulg = SingleTarget ? Config.RDM_ST_oGCD_Prefulgence : Config.RDM_AoE_oGCD_Prefulgence; int engagementPool = (SingleTarget && Config.RDM_ST_oGCD_Engagement_Pooling) || (!SingleTarget && Config.RDM_AoE_oGCD_Engagement_Pooling) ? 1 : 0; bool corpacorps = SingleTarget ? Config.RDM_ST_oGCD_CorpACorps : Config.RDM_AoE_oGCD_CorpACorps; @@ -220,6 +212,12 @@ internal static bool CanUse(in uint actionID, in bool SingleTarget, out uint new && HasEffect(Buffs.ThornedFlourish)) placeOGCD = ViceOfThorns; + if (placeOGCD == 0 + && prefulg + && TraitLevelChecked(Traits.EnhancedManaficationIII) + && HasEffect(Buffs.PrefulugenceReady)) + placeOGCD = Prefulgence; + if (CanSpellWeave(actionID) && placeOGCD != 0) { newActionID = placeOGCD; diff --git a/XIVSlothCombo/Combos/PvE/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM.cs index e47da42ae..299114148 100644 --- a/XIVSlothCombo/Combos/PvE/RDM.cs +++ b/XIVSlothCombo/Combos/PvE/RDM.cs @@ -108,6 +108,7 @@ public static UserBool RDM_ST_oGCD_CorpACorps_Melee = new("RDM_ST_oGCD_CorpACorps_Melee"), RDM_ST_oGCD_CorpACorps_Pooling = new("RDM_ST_oGCD_CorpACorps_Pooling"), RDM_ST_oGCD_ViceOfThorns = new("RDM_ST_oGCD_ViceOfThorns"), + RDM_ST_oGCD_Prefulgence = new("RDM_ST_oGCD_Prefulgence"), RDM_ST_MeleeCombo_Adv = new("RDM_ST_MeleeCombo_Adv"), RDM_ST_MeleeFinisher_Adv = new("RDM_ST_MeleeFinisher_Adv"), RDM_ST_MeleeEnforced = new("RDM_ST_MeleeEnforced"), @@ -121,6 +122,7 @@ public static UserBool RDM_AoE_oGCD_CorpACorps_Melee = new("RDM_AoE_oGCD_CorpACorps_Melee"), RDM_AoE_oGCD_CorpACorps_Pooling = new("RDM_AoE_oGCD_CorpACorps_Pooling"), RDM_AoE_oGCD_ViceOfThorns = new("RDM_AoE_oGCD_ViceOfThorns"), + RDM_AoE_oGCD_Prefulgence = new("RDM_AoE_oGCD_Prefulgence"), RDM_AoE_MeleeCombo_Adv = new("RDM_AoE_MeleeCombo_Adv"), RDM_AoE_MeleeFinisher_Adv = new("RDM_AoE_MeleeFinisher_Adv"); public static UserBoolArray diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index bba1a908d..ed3217a61 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1848,6 +1848,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) ImGui.Unindent(); } UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_ViceOfThorns, "Vice of Thorns", ""); + UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_Prefulgence, "Prefulgence", ""); } if (preset is CustomComboPreset.RDM_ST_MeleeCombo) @@ -1899,6 +1900,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) ImGui.Unindent(); } UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_ViceOfThorns, "Vice of Thorns", ""); + UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_Prefulgence, "Prefulgence", ""); } if (preset is CustomComboPreset.RDM_AoE_MeleeCombo) From 026ac96bb187d68f2ddee09cd77610b57339e3da Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:44:14 -0500 Subject: [PATCH 007/208] [SCH] Removed duplicate AoE Lucid Slider --- XIVSlothCombo/Window/Functions/UserConfig.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index bba1a908d..e4bbeeb5f 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2208,9 +2208,6 @@ internal static void Draw(CustomComboPreset preset, bool enabled) } } - if (preset is CustomComboPreset.SCH_AoE_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_AoE_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); - if (preset is CustomComboPreset.SCH_ST_Heal) { UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); @@ -2237,7 +2234,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) if (preset is CustomComboPreset.SCH_ST_Heal_Esuna) UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); - if (preset is CustomComboPreset.SCH_AoE_Heal) + if (preset is CustomComboPreset.SCH_AoE_Lucid) UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_AoE_Heal_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); if (preset is CustomComboPreset.SCH_DeploymentTactics) From a9b037fe10879ee3838784196606b7e7b3b65510 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:55:49 -0500 Subject: [PATCH 008/208] Lucid Dreaming Weave Fix --- XIVSlothCombo/Combos/PvE/ALL.cs | 2 +- XIVSlothCombo/Combos/PvE/SCH.cs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/ALL.cs b/XIVSlothCombo/Combos/PvE/ALL.cs index 05c3e5099..f6d049e16 100644 --- a/XIVSlothCombo/Combos/PvE/ALL.cs +++ b/XIVSlothCombo/Combos/PvE/ALL.cs @@ -76,7 +76,7 @@ public const ushort public static bool CanUseLucid(uint actionID, int MPThreshold, bool weave = true) => CustomComboFunctions.ActionReady(LucidDreaming) && CustomComboFunctions.LocalPlayer.CurrentMp <= MPThreshold - && (weave && CustomComboFunctions.CanSpellWeave(actionID)); + && (!weave || CustomComboFunctions.CanSpellWeave(actionID)); internal class ALL_IslandSanctuary_Sprint : CustomCombo { diff --git a/XIVSlothCombo/Combos/PvE/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH.cs index 2e5bec2d1..a47823d56 100644 --- a/XIVSlothCombo/Combos/PvE/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH.cs @@ -495,9 +495,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Aetherflow; // Lucid Dreaming - if (IsEnabled(CustomComboPreset.SCH_AoE_Heal_Lucid) && - ActionReady(All.LucidDreaming) && - LocalPlayer.CurrentMp < Config.SCH_AoE_Heal_LucidOption) + if (IsEnabled(CustomComboPreset.SCH_AoE_Heal_Lucid) + && All.CanUseLucid(actionID, Config.SCH_AoE_Heal_LucidOption, true)) return All.LucidDreaming; // Indomitability From a6bec6e108947f4ebb02aba8babe2407ecef0c56 Mon Sep 17 00:00:00 2001 From: ace Date: Sat, 24 Aug 2024 02:51:36 -0700 Subject: [PATCH 009/208] GNB AOE Reign --- XIVSlothCombo/Combos/PvE/GNB.cs | 47 +++++++++++---------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index dcffeaecd..614866438 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -334,7 +334,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Variant.VariantCure; //Ranged Uptime - if (IsEnabled(CustomComboPreset.GNB_ST_RangedUptime) && + if (IsEnabled(CustomComboPreset.GNB_ST_RangedUptime) && !InMeleeRange() && LevelChecked(LightningShot) && HasBattleTarget()) return LightningShot; @@ -378,7 +378,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { //Bloodfest if (IsEnabled(CustomComboPreset.GNB_ST_Bloodfest) && ActionReady(Bloodfest) && Ammo is 0 && (JustUsed(NoMercy, 20f))) - return Bloodfest; + return Bloodfest; //Zone if (IsEnabled(CustomComboPreset.GNB_ST_BlastingZone) && ActionReady(DangerZone) && !JustUsed(NoMercy)) @@ -441,7 +441,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Lv90-Lv99 if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown)) { - if (JustUsed(NoMercy, 3f) && + if (JustUsed(NoMercy, 3f) && ((!HasEffect(Buffs.ReadyToBlast) && Ammo == 3 && bfCD < GCD * 12 || ActionReady(Bloodfest)) //2min || (bfCD is < 90 and > 15 && Ammo == 3) //1min 3 carts || (JustUsed(Bloodfest, 2f) && JustUsed(BrutalShell)))) //opener @@ -833,24 +833,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //DoubleDown if (Ammo >= 2 && ActionReady(DoubleDown) && HasEffect(Buffs.NoMercy)) //use on CD under NM return DoubleDown; - //FatedCircle - if (Ammo > 0 && LevelChecked(FatedCircle) && (HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF - (bfCD < 6)) // Bloodfest prep - return FatedCircle; //Reign if (LevelChecked(ReignOfBeasts)) //because leaving this out anywhere is a waste { - if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) - { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) - return OriginalHook(ReignOfBeasts); - } - - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) - { + if ((GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) || + (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood))) return OriginalHook(ReignOfBeasts); - } } + //FatedCircle + if (Ammo > 0 && LevelChecked(FatedCircle) && (HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF + (bfCD < 6)) // Bloodfest prep + return FatedCircle; } //1-2 @@ -893,7 +886,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IsEnabled(Variant.VariantSpiritDart) && (sustainedDamage is null || sustainedDamage?.RemainingTime <= 3)) return Variant.VariantSpiritDart; - + //Variant Ultimatum if (IsEnabled(CustomComboPreset.GNB_Variant_Ultimatum) && IsEnabled(Variant.VariantUltimatum) && ActionReady(Variant.VariantUltimatum)) return Variant.VariantUltimatum; @@ -921,24 +914,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //DoubleDown if (IsEnabled(CustomComboPreset.GNB_AoE_DoubleDown) && Ammo >= 2 && ActionReady(DoubleDown) && HasEffect(Buffs.NoMercy)) //use on CD under NM return DoubleDown; - //FatedCircle - if (Ammo > 0 && LevelChecked(FatedCircle) && ((IsEnabled(CustomComboPreset.GNB_AoE_FatedCircle) && HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF - (IsEnabled(CustomComboPreset.GNB_AoE_Bloodfest) && bfCD < 6))) // Bloodfest prep - return FatedCircle; //Reign if (IsEnabled(CustomComboPreset.GNB_AoE_Reign) && LevelChecked(ReignOfBeasts)) //because leaving this out anywhere is a waste { - if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) - { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) - return OriginalHook(ReignOfBeasts); - } - - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) - { + if ((GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) || + (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood))) return OriginalHook(ReignOfBeasts); - } } + //FatedCircle + if (Ammo > 0 && LevelChecked(FatedCircle) && ((IsEnabled(CustomComboPreset.GNB_AoE_FatedCircle) && HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF + (IsEnabled(CustomComboPreset.GNB_AoE_Bloodfest) && bfCD < 6))) // Bloodfest prep + return FatedCircle; } //1-2 @@ -1045,7 +1031,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(GnashingFang) && !ActionReady(DoubleDown) && GunStep == 0) { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) return OriginalHook(ReignOfBeasts); } From 392c8c3eb0d90a5dbe1b2c11c6a44b5776abf074 Mon Sep 17 00:00:00 2001 From: ace Date: Sat, 24 Aug 2024 11:12:24 -0700 Subject: [PATCH 010/208] BurstStrike in AoE check --- XIVSlothCombo/Combos/PvE/GNB.cs | 50 +++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index 614866438..c207360bb 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -840,16 +840,33 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood))) return OriginalHook(ReignOfBeasts); } - //FatedCircle - if (Ammo > 0 && LevelChecked(FatedCircle) && (HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF + //FatedCircle - if not unlocked, use BurstStrike + if (Ammo > 0 && LevelChecked(FatedCircle) && + (HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF (bfCD < 6)) // Bloodfest prep return FatedCircle; + if (Ammo > 0 && !LevelChecked(FatedCircle) && LevelChecked(BurstStrike) && + (HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0)) //use when under NM after DD & ignores GF + return BurstStrike; } //1-2 - if (comboTime > 0 && lastComboMove == DemonSlice && LevelChecked(DemonSlaughter)) + if (comboTime > 0) { - return (LevelChecked(FatedCircle) && Ammo == MaxCartridges(level)) ? FatedCircle : DemonSlaughter; + if (lastComboMove == DemonSlice && LevelChecked(DemonSlaughter)) + { + if (Ammo == MaxCartridges(level)) + { + if (LevelChecked(FatedCircle)) + return FatedCircle; + if (!LevelChecked(FatedCircle)) + return BurstStrike; + } + if (Ammo != MaxCartridges(level)) + { + return DemonSlaughter; + } + } } return DemonSlice; @@ -921,16 +938,33 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood))) return OriginalHook(ReignOfBeasts); } - //FatedCircle - if (Ammo > 0 && LevelChecked(FatedCircle) && ((IsEnabled(CustomComboPreset.GNB_AoE_FatedCircle) && HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF + //FatedCircle - if not unlocked, use BurstStrike + if (Ammo > 0 && LevelChecked(FatedCircle) && + ((IsEnabled(CustomComboPreset.GNB_AoE_FatedCircle) && HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF (IsEnabled(CustomComboPreset.GNB_AoE_Bloodfest) && bfCD < 6))) // Bloodfest prep return FatedCircle; + if (Ammo > 0 && !LevelChecked(FatedCircle) && LevelChecked(BurstStrike) && + (HasEffect(Buffs.NoMercy) && GunStep == 0)) // Bloodfest prep + return BurstStrike; } //1-2 - if (comboTime > 0 && lastComboMove == DemonSlice && LevelChecked(DemonSlaughter)) + if (comboTime > 0) { - return (IsEnabled(CustomComboPreset.GNB_AoE_Overcap) && LevelChecked(FatedCircle) && Ammo == MaxCartridges(level)) ? FatedCircle : DemonSlaughter; + if (lastComboMove == DemonSlice && LevelChecked(DemonSlaughter)) + { + if (Ammo == MaxCartridges(level)) + { + if (LevelChecked(FatedCircle)) + return FatedCircle; + if (!LevelChecked(FatedCircle)) + return BurstStrike; + } + if (Ammo != MaxCartridges(level)) + { + return DemonSlaughter; + } + } } return DemonSlice; From 5a3de8882b34153fb2b9ee3f32ef2284c4d76496 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 24 Aug 2024 20:48:41 +0100 Subject: [PATCH 011/208] Fix AST AoE hot check --- XIVSlothCombo/Combos/PvE/AST.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 2d8562149..370187a5a 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -514,8 +514,8 @@ Gauge.DrawnCrownCard is CardType.LADY } // Only check for our own HoTs - var aspectedHeliosHoT = FindEffect(Buffs.AspectedBenefic, LocalPlayer, LocalPlayer?.GameObjectId); - var heliosConjunctionHoT = FindEffect(Buffs.AspectedBenefic, LocalPlayer, LocalPlayer?.GameObjectId); + var aspectedHeliosHoT = FindEffect(Buffs.AspectedHelios, LocalPlayer, LocalPlayer?.GameObjectId); + var heliosConjunctionHoT = FindEffect(Buffs.HeliosConjunction, LocalPlayer, LocalPlayer?.GameObjectId); if ((IsEnabled(CustomComboPreset.AST_AoE_SimpleHeals_Aspected) && NonaspectedMode) || // Helios mode: option must be on !NonaspectedMode) // Aspected mode: option is not required From 30239ae2d1cf93c5b7e06cad99a073427a241076 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 24 Aug 2024 20:53:41 +0100 Subject: [PATCH 012/208] Remove aspected horoscope check --- XIVSlothCombo/Combos/PvE/AST.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 370187a5a..3290f2514 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -523,7 +523,6 @@ Gauge.DrawnCrownCard is CardType.LADY if ((ActionReady(AspectedHelios) && aspectedHeliosHoT is null && heliosConjunctionHoT is null) - || HasEffect(Buffs.Horoscope) || (HasEffect(Buffs.NeutralSect) && !HasEffect(Buffs.NeutralSectShield))) return OriginalHook(AspectedHelios); } From 32e9b7166c6042af6df2d69f2aa78bb0347bdd73 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 24 Aug 2024 21:02:09 +0100 Subject: [PATCH 013/208] Simplify AST hot check --- XIVSlothCombo/Combos/PvE/AST.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 3290f2514..df53bd0ef 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -514,21 +514,18 @@ Gauge.DrawnCrownCard is CardType.LADY } // Only check for our own HoTs - var aspectedHeliosHoT = FindEffect(Buffs.AspectedHelios, LocalPlayer, LocalPlayer?.GameObjectId); - var heliosConjunctionHoT = FindEffect(Buffs.HeliosConjunction, LocalPlayer, LocalPlayer?.GameObjectId); + var hotCheck = HeliosConjuction.LevelChecked() ? FindEffect(Buffs.HeliosConjunction, LocalPlayer, LocalPlayer?.GameObjectId) : FindEffect(Buffs.AspectedHelios, LocalPlayer, LocalPlayer?.GameObjectId); if ((IsEnabled(CustomComboPreset.AST_AoE_SimpleHeals_Aspected) && NonaspectedMode) || // Helios mode: option must be on !NonaspectedMode) // Aspected mode: option is not required { if ((ActionReady(AspectedHelios) - && aspectedHeliosHoT is null - && heliosConjunctionHoT is null) + && hotCheck is null) || (HasEffect(Buffs.NeutralSect) && !HasEffect(Buffs.NeutralSectShield))) return OriginalHook(AspectedHelios); } - if ((aspectedHeliosHoT is not null || heliosConjunctionHoT is not null) - && (aspectedHeliosHoT?.RemainingTime > 2 || heliosConjunctionHoT?.RemainingTime > 2)) + if (hotCheck is not null && hotCheck.RemainingTime > GetActionCastTime(OriginalHook(AspectedHelios)) + 1f) return Helios; } From b854f382527b758f549f3c58847043c5d2b06809 Mon Sep 17 00:00:00 2001 From: edewen Date: Sat, 24 Aug 2024 22:41:42 -0400 Subject: [PATCH 014/208] Shifting Earthly star Added earthly star to the prepull noncombat line with the card draw. Shifted earthly star a bit higher above the ogcds that cant drift. oracle/arcana --- XIVSlothCombo/Combos/PvE/AST.cs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 3290f2514..b8a676e49 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -215,11 +215,15 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (((!AlternateMode && MaleficList.Contains(actionID)) || (AlternateMode && CombustList.ContainsKey(actionID)) && !InCombat())) - + { if (IsEnabled(CustomComboPreset.AST_DPS_AutoDraw) && ActionReady(OriginalHook(AstralDraw)) && (Gauge.DrawnCards.All(x => x is CardType.NONE) || (DrawnCard == CardType.NONE && Config.AST_ST_DPS_OverwriteCards))) return OriginalHook(AstralDraw); + if (IsEnabled(CustomComboPreset.AST_ST_DPS_EarthlyStar) && + ActionReady(EarthlyStar)) + return EarthlyStar; + } //In combat if (((!AlternateMode && MaleficList.Contains(actionID)) || (AlternateMode && CombustList.ContainsKey(actionID))) && @@ -335,6 +339,12 @@ Gauge.DrawnCards[0] is not CardType.NONE && ActionWatching.NumberOfGcdsUsed >= 3) return Divination; + //Earthly Star + if (IsEnabled(CustomComboPreset.AST_ST_DPS_EarthlyStar) && + ActionReady(EarthlyStar) && + CanSpellWeave(actionID)) + return EarthlyStar; + if (IsEnabled(CustomComboPreset.AST_DPS_Oracle) && HasEffect(Buffs.Divining) && CanSpellWeave(actionID)) @@ -345,13 +355,7 @@ Gauge.DrawnCards[0] is not CardType.NONE && IsEnabled(CustomComboPreset.AST_DPS_LazyLord) && Gauge.DrawnCrownCard is CardType.LORD && HasBattleTarget() && CanDelayedWeave(actionID)) - return OriginalHook(MinorArcana); - - //Earthly Star - if (IsEnabled(CustomComboPreset.AST_ST_DPS_EarthlyStar) && - ActionReady(EarthlyStar) && - CanSpellWeave(actionID)) - return EarthlyStar; + return OriginalHook(MinorArcana); if (HasBattleTarget()) { @@ -451,6 +455,11 @@ Gauge.DrawnCards[0] is not CardType.NONE && CanDelayedWeave(actionID) && ActionWatching.NumberOfGcdsUsed >= 3) return Divination; + //Earthly Star + if (IsEnabled(CustomComboPreset.AST_AOE_DPS_EarthlyStar) && + ActionReady(EarthlyStar) && + CanSpellWeave(actionID)) + return EarthlyStar; if (IsEnabled(CustomComboPreset.AST_AOE_Oracle) && HasEffect(Buffs.Divining) && @@ -463,13 +472,6 @@ Gauge.DrawnCards[0] is not CardType.NONE && HasBattleTarget() && CanDelayedWeave(actionID)) return OriginalHook(MinorArcana); - - //Earthly Star - if (IsEnabled(CustomComboPreset.AST_AOE_DPS_EarthlyStar) && - ActionReady(EarthlyStar) && - CanSpellWeave(actionID)) - return EarthlyStar; - } return actionID; } From c0d7b04299e44bf6370604ade6fe1d8c1ad58e2a Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 25 Aug 2024 11:39:53 +0100 Subject: [PATCH 015/208] Optimize attribute fetching --- .../Attributes/AutoActionAttribute.cs | 20 ++ .../Attributes/CustomComboInfoAttribute.cs | 142 +--------- XIVSlothCombo/Combos/CustomComboPreset.cs | 268 +++++++++--------- XIVSlothCombo/Core/PluginConfiguration.cs | 2 +- XIVSlothCombo/CustomCombo/Functions/Misc.cs | 68 ++++- XIVSlothCombo/Window/Functions/Presets.cs | 171 ++++++----- XIVSlothCombo/Window/Messages/Messages.cs | 3 +- XIVSlothCombo/Window/Tabs/PvEFeatures.cs | 5 +- XIVSlothCombo/Window/Tabs/Settings.cs | 199 ++++++------- 9 files changed, 430 insertions(+), 448 deletions(-) create mode 100644 XIVSlothCombo/Attributes/AutoActionAttribute.cs diff --git a/XIVSlothCombo/Attributes/AutoActionAttribute.cs b/XIVSlothCombo/Attributes/AutoActionAttribute.cs new file mode 100644 index 000000000..70e893a0e --- /dev/null +++ b/XIVSlothCombo/Attributes/AutoActionAttribute.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace XIVSlothCombo.Attributes +{ + [AttributeUsage(AttributeTargets.Field)] + internal class AutoActionAttribute : Attribute + { + public bool IsAoE; + public bool IsHeal; + internal AutoActionAttribute(bool isAoE, bool isHeal) + { + IsAoE = isAoE; + IsHeal = isHeal; + } + } +} diff --git a/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs b/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs index 8ab5928a3..09ff5fafd 100644 --- a/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs +++ b/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Runtime.CompilerServices; using XIVSlothCombo.Combos.PvE; +using XIVSlothCombo.CustomComboNS.Functions; namespace XIVSlothCombo.Attributes { @@ -14,165 +15,40 @@ namespace XIVSlothCombo.Attributes internal class CustomComboInfoAttribute : Attribute { /// Initializes a new instance of the class. - /// Display name. + /// Display name. /// Combo description. /// Associated job ID. /// Display order. /// Display meme name /// Meme description. - internal CustomComboInfoAttribute(string fancyName, string description, byte jobID, [CallerLineNumber] int order = 0, string memeName = "", string memeDescription = "") + internal CustomComboInfoAttribute(string name, string description, byte jobID, [CallerLineNumber] int order = 0) { - FancyName = fancyName; + Name = name; Description = description; JobID = jobID; Order = order; - MemeName = memeName; - MemeDescription = memeDescription; } /// Gets the display name. - public string FancyName { get; } - - /// Gets the meme name. - public string MemeName { get; } + public string Name { get; } /// Gets the description. public string Description { get; } - /// Gets the meme description. - public string MemeDescription { get; } - /// Gets the job ID. public byte JobID { get; } /// Gets the job role. - public int Role => JobIDToRole(JobID); - - public uint ClassJobCategory => JobIDToClassJobCategory(JobID); - - private static int JobIDToRole(byte jobID) - { - if (Svc.Data.GetExcelSheet().HasRow(jobID)) - return Svc.Data.GetExcelSheet().GetRow(jobID).Role; - - return 0; - } - - private static uint JobIDToClassJobCategory(byte jobID) - { - if (Svc.Data.GetExcelSheet().HasRow(jobID)) - return Svc.Data.GetExcelSheet().GetRow(jobID).ClassJobCategory.Row; + public int Role => CustomComboFunctions.JobIDs.JobIDToRole(JobID); - return 0; - } + public uint ClassJobCategory => CustomComboFunctions.JobIDs.JobIDToClassJobCategory(JobID); /// Gets the display order. public int Order { get; } /// Gets the job name. - public string JobName => JobIDToName(JobID); - - public string JobShorthand => JobIDToShorthand(JobID); - - private static string JobIDToShorthand(byte key) - { - if (key == 41) - return "VPR"; - - if (key == 0) - return ""; - - if (ClassJobs.TryGetValue(key, out var job)) - { - return job.Abbreviation.RawString; - } - else - { - return ""; - } - } - - private static readonly Dictionary ClassJobs = Svc.Data.GetExcelSheet()!.ToDictionary(i => i.RowId, i => i); - - public static string JobIDToName(byte key) - { - if (key == 0) - return "General/Multiple Jobs"; - - //Override DOH/DOL - if (key is DOH.JobID) key = 08; //Set to Carpenter - if (key is DOL.JobID) key = 16; //Set to Miner - if (ClassJobs.TryGetValue(key, out ClassJob? job)) - { - //Grab Category name for DOH/DOL, else the normal Name for the rest - string jobname = key is 08 or 16 ? job.ClassJobCategory.Value.Name : job.Name; - //Job names are all lowercase by default. This capitalizes based on regional rules - string cultureID = Svc.ClientState.ClientLanguage switch - { - Dalamud.Game.ClientLanguage.French => "fr-FR", - Dalamud.Game.ClientLanguage.Japanese => "ja-JP", - Dalamud.Game.ClientLanguage.German => "de-DE", - _ => "en-us", - }; - TextInfo textInfo = new CultureInfo(cultureID, false).TextInfo; - jobname = textInfo.ToTitleCase(jobname); - //if (key is 0) jobname = " " + jobname; //Adding space to the front of Global moves it to the top. Shit hack but works - return jobname; - - } //Misc or unknown - else return key == 99 ? "Global" : "Unknown"; - } - - /// Gets the meme job name. - public string MemeJobName => MemeJobIDToName(JobID); + public string JobName => CustomComboFunctions.JobIDs.JobIDToName(JobID); - private static string MemeJobIDToName(byte key) => key switch - { - 0 => "Adventurer", - 1 => "Gladiator", - 2 => "Pugilist", - 3 => "Marauder", - 4 => "Lancer", - 5 => "Archer", - 6 => "Conjurer", - 7 => "Thaumaturge", - 8 => "Carpenter", - 9 => "Blacksmith", - 10 => "Armorer", - 11 => "Goldsmith", - 12 => "Leatherworker", - 13 => "Weaver", - 14 => "Alchemist", - 15 => "Culinarian", - 16 => "Miner", - 17 => "Botanist", - 18 => "Fisher", - 19 => "Paladin", - 20 => "Monk", - 21 => "Warrior", - 22 => "Dragoon", - 23 => "Bard", - 24 => "White Mage", - 25 => "Black Mage", - 26 => "Arcanist", - 27 => "Summoner", - 28 => "Scholar", - 29 => "Rogue", - 30 => "Ninja", - 31 => "Machinist", - 32 => "Dark Knight", - 33 => "Astrologian", - 34 => "Samurai", - 35 => "Red Mage", - 36 => "Blue Mage", - 37 => "Gunbreaker", - 38 => "Dancer", - 39 => "Reaper", - 40 => "Sage", - 99 => "Global", - DOH.JobID => "Disciples of the Hand", - DOL.JobID => "Disciples of the Land", - _ => "Unknown", - }; + public string JobShorthand => CustomComboFunctions.JobIDs.JobIDToShorthand(JobID); } } diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..7261fbbd6 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -186,19 +186,19 @@ public enum CustomComboPreset AST_ST_DPS_CombustUptime = 1018, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Lightspeed Weave Option", "Adds Lightspeed when moving", AST.JobID, 2, "", "")] + [CustomComboInfo("Lightspeed Weave Option", "Adds Lightspeed when moving", AST.JobID, 2)] AST_DPS_LightSpeed = 1020, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Lucid Dreaming Weave Option", "Adds Lucid Dreaming when MP drops below slider value", AST.JobID, 3, "", "")] + [CustomComboInfo("Lucid Dreaming Weave Option", "Adds Lucid Dreaming when MP drops below slider value", AST.JobID, 3)] AST_DPS_Lucid = 1008, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Divination Weave Option", "Adds Divination", AST.JobID, 4, "", "")] + [CustomComboInfo("Divination Weave Option", "Adds Divination", AST.JobID, 4)] AST_DPS_Divination = 1016, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Card Draw Weave Option", "Draws your cards", AST.JobID, 5, "", "")] + [CustomComboInfo("Card Draw Weave Option", "Draws your cards", AST.JobID, 5)] AST_DPS_AutoDraw = 1011, [ParentCombo(AST_ST_DPS)] @@ -206,7 +206,7 @@ public enum CustomComboPreset AST_DPS_AutoPlay = 1037, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Lord of Crowns Weave Option", "Adds Lord Of Crowns", AST.JobID, 10, "", "")] + [CustomComboInfo("Lord of Crowns Weave Option", "Adds Lord Of Crowns", AST.JobID, 10)] AST_DPS_LazyLord = 1014, [ParentCombo(AST_ST_DPS)] @@ -230,19 +230,19 @@ public enum CustomComboPreset AST_AOE_DPS = 1041, [ParentCombo(AST_AOE_DPS)] - [CustomComboInfo("Lightspeed Weave Option", "Adds Lightspeed when moving", AST.JobID, 2, "", "")] + [CustomComboInfo("Lightspeed Weave Option", "Adds Lightspeed when moving", AST.JobID, 2)] AST_AOE_LightSpeed = 1048, [ParentCombo(AST_AOE_DPS)] - [CustomComboInfo("Lucid Dreaming Weave Option", "Adds Lucid Dreaming when MP drops below slider value", AST.JobID, 3, "", "")] + [CustomComboInfo("Lucid Dreaming Weave Option", "Adds Lucid Dreaming when MP drops below slider value", AST.JobID, 3)] AST_AOE_Lucid = 1042, [ParentCombo(AST_AOE_DPS)] - [CustomComboInfo("Divination Weave Option", "Adds Divination", AST.JobID, 4, "", "")] + [CustomComboInfo("Divination Weave Option", "Adds Divination", AST.JobID, 4)] AST_AOE_Divination = 1043, [ParentCombo(AST_AOE_DPS)] - [CustomComboInfo("Card Draw Weave Option", "Draws your cards", AST.JobID, 5, "", "")] + [CustomComboInfo("Card Draw Weave Option", "Draws your cards", AST.JobID, 5)] AST_AOE_AutoDraw = 1044, [ParentCombo(AST_AOE_DPS)] @@ -250,7 +250,7 @@ public enum CustomComboPreset AST_AOE_AutoPlay = 1045, [ParentCombo(AST_AOE_DPS)] - [CustomComboInfo("Lord of Crowns Weave Option", "Adds Lord Of Crowns", AST.JobID, 7, "", "")] + [CustomComboInfo("Lord of Crowns Weave Option", "Adds Lord Of Crowns", AST.JobID, 7)] AST_AOE_LazyLord = 1046, [ParentCombo(AST_AOE_DPS)] @@ -366,11 +366,11 @@ public enum CustomComboPreset #region BLACK MAGE [ReplaceSkill(BLM.Fire)] - [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -10, "", "")] + [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -10)] BLM_ST_SimpleMode = 2012, [ReplaceSkill(BLM.Blizzard2, BLM.HighBlizzard2)] - [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -8, "", "")] + [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -8)] BLM_AoE_SimpleMode = 2008, #region Variant @@ -1254,7 +1254,7 @@ public enum CustomComboPreset #region Buffs ST [ParentCombo(DRG_ST_AdvancedMode)] - [CustomComboInfo("Buffs Option", "Adds various buffs to the rotation.", DRG.JobID, 2, "", "")] + [CustomComboInfo("Buffs Option", "Adds various buffs to the rotation.", DRG.JobID, 2)] DRG_ST_Buffs = 6102, [ParentCombo(DRG_ST_Buffs)] @@ -1705,7 +1705,7 @@ public enum CustomComboPreset #endregion #region Aurora - [CustomComboInfo("Aurora Protection Feature", "Locks out Aurora if Aurora's effect is on the target.", GNB.JobID, 0, "", "")] + [CustomComboInfo("Aurora Protection Feature", "Locks out Aurora if Aurora's effect is on the target.", GNB.JobID, 0)] GNB_AuroraProtection = 7700, #endregion @@ -3232,215 +3232,215 @@ The three digets after RDM.JobID can be used to reorder items in the list SGE_ST_DPS_Opener = 14055, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Lucid Dreaming Option", "Weaves Lucid Dreaming when your MP drops below the specified value.", SGE.JobID, 120, "", "")] + [CustomComboInfo("Lucid Dreaming Option", "Weaves Lucid Dreaming when your MP drops below the specified value.", SGE.JobID, 120)] SGE_ST_DPS_Lucid = 14002, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Eukrasian Dosis Option", "Automatic DoT Uptime.", SGE.JobID, 110, "", "")] + [CustomComboInfo("Eukrasian Dosis Option", "Automatic DoT Uptime.", SGE.JobID, 110)] SGE_ST_DPS_EDosis = 14003, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Movement Options", "Use selected instant cast actions while moving.", SGE.JobID, 113, "", "")] + [CustomComboInfo("Movement Options", "Use selected instant cast actions while moving.", SGE.JobID, 113)] SGE_ST_DPS_Movement = 14004, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Phlegma Option", "Use Phlegma if available and within range.", SGE.JobID, 111, "", "")] + [CustomComboInfo("Phlegma Option", "Use Phlegma if available and within range.", SGE.JobID, 111)] SGE_ST_DPS_Phlegma = 14005, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Kardia Reminder Option", "Adds Kardia when not under the effect.", SGE.JobID, 122, "", "")] + [CustomComboInfo("Kardia Reminder Option", "Adds Kardia when not under the effect.", SGE.JobID, 122)] SGE_ST_DPS_Kardia = 14006, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Rhizomata Option", "Weaves Rhizomata when Addersgall gauge falls below the specified value.", SGE.JobID, 121, "", "")] + [CustomComboInfo("Rhizomata Option", "Weaves Rhizomata when Addersgall gauge falls below the specified value.", SGE.JobID, 121)] SGE_ST_DPS_Rhizo = 14007, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Psych Option", "Weaves Psych when available.", SGE.JobID, 112, "", "")] + [CustomComboInfo("Psych Option", "Weaves Psych when available.", SGE.JobID, 112)] SGE_ST_DPS_Psyche = 14008, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Addersgall Overflow Protection", "Weaves Druochole when Addersgall gauge is greater than or equal to the specified value.", SGE.JobID, 123, "", "")] + [CustomComboInfo("Addersgall Overflow Protection", "Weaves Druochole when Addersgall gauge is greater than or equal to the specified value.", SGE.JobID, 123)] SGE_ST_DPS_AddersgallProtect = 14054, #endregion #region AoE DPS Feature [ReplaceSkill(SGE.Dyskrasia, SGE.Dyskrasia2)] - [CustomComboInfo("AoE DPS Feature", "Adds various options to Dyskrasia I & II. Requires a target.", SGE.JobID, 200, "", "")] + [CustomComboInfo("AoE DPS Feature", "Adds various options to Dyskrasia I & II. Requires a target.", SGE.JobID, 200)] SGE_AoE_DPS = 14009, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Phlegma Option", "Uses Phlegma if available.", SGE.JobID, 3, "", "")] + [CustomComboInfo("Phlegma Option", "Uses Phlegma if available.", SGE.JobID, 3)] SGE_AoE_DPS_Phlegma = 14010, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Toxikon Option", "Use Toxikon if available.", SGE.JobID, 4, "", "")] + [CustomComboInfo("Toxikon Option", "Use Toxikon if available.", SGE.JobID, 4)] SGE_AoE_DPS_Toxikon = 14011, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Psyche Option", "Weaves Psyche if available.", SGE.JobID, 2, "", "")] + [CustomComboInfo("Psyche Option", "Weaves Psyche if available.", SGE.JobID, 2)] SGE_AoE_DPS_Psyche = 14051, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Eukrasia Option", "Uses Eukrasia for Eukrasia Dyskrasia.", SGE.JobID, 1, "", "")] + [CustomComboInfo("Eukrasia Option", "Uses Eukrasia for Eukrasia Dyskrasia.", SGE.JobID, 1)] SGE_AoE_DPS_EDyskrasia = 14052, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Lucid Dreaming Option", "Weaves Lucid Dreaming when your MP falls below the specified value.", SGE.JobID, 4, "", "")] + [CustomComboInfo("Lucid Dreaming Option", "Weaves Lucid Dreaming when your MP falls below the specified value.", SGE.JobID, 4)] SGE_AoE_DPS_Lucid = 14012, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Rhizomata Option", "Weaves Rhizomata when Addersgall gauge falls below the specified value.", SGE.JobID, 5, "", "")] + [CustomComboInfo("Rhizomata Option", "Weaves Rhizomata when Addersgall gauge falls below the specified value.", SGE.JobID, 5)] SGE_AoE_DPS_Rhizo = 14013, [ParentCombo(SGE_AoE_DPS)] - [CustomComboInfo("Addersgall Overflow Protection", "Weaves Druochole when Addersgall gauge is greater than or equal to the specified value.", SGE.JobID, 6, "", "")] + [CustomComboInfo("Addersgall Overflow Protection", "Weaves Druochole when Addersgall gauge is greater than or equal to the specified value.", SGE.JobID, 6)] SGE_AoE_DPS_AddersgallProtect = 14053, #endregion #region Diagnosis Simple Single Target Heal [ReplaceSkill(SGE.Diagnosis)] - [CustomComboInfo("Single Target Heal Feature", "Supports soft-targeting.\nOptions below are in priority order.", SGE.JobID, 300, "", "")] + [CustomComboInfo("Single Target Heal Feature", "Supports soft-targeting.\nOptions below are in priority order.", SGE.JobID, 300)] SGE_ST_Heal = 14014, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Esuna Option", "Applies Esuna to your target if there is a cleansable debuff.", SGE.JobID, 11, "", "")] + [CustomComboInfo("Esuna Option", "Applies Esuna to your target if there is a cleansable debuff.", SGE.JobID, 11)] SGE_ST_Heal_Esuna = 14015, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Apply Kardia Option", "Applies Kardia to your target if it's not applied to anyone else.", SGE.JobID, 1, "", "")] + [CustomComboInfo("Apply Kardia Option", "Applies Kardia to your target if it's not applied to anyone else.", SGE.JobID, 1)] SGE_ST_Heal_Kardia = 14016, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Eukrasian Diagnosis Option", "Diagnosis becomes Eukrasian Diagnosis if the shield is not applied to the target.", SGE.JobID, 2, "", "")] + [CustomComboInfo("Eukrasian Diagnosis Option", "Diagnosis becomes Eukrasian Diagnosis if the shield is not applied to the target.", SGE.JobID, 2)] SGE_ST_Heal_EDiagnosis = 14017, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Soteria Option", "Applies Soteria.", SGE.JobID, 3, "", "")] + [CustomComboInfo("Soteria Option", "Applies Soteria.", SGE.JobID, 3)] SGE_ST_Heal_Soteria = 14018, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Zoe Option", "Applies Zoe.", SGE.JobID, 4, "", "")] + [CustomComboInfo("Zoe Option", "Applies Zoe.", SGE.JobID, 4)] SGE_ST_Heal_Zoe = 14019, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Pepsis Option", "Triggers Pepsis if a shield is present.", SGE.JobID, 5, "", "")] + [CustomComboInfo("Pepsis Option", "Triggers Pepsis if a shield is present.", SGE.JobID, 5)] SGE_ST_Heal_Pepsis = 14020, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Taurochole Option", "Adds Taurochole.", SGE.JobID, 6, "", "")] + [CustomComboInfo("Taurochole Option", "Adds Taurochole.", SGE.JobID, 6)] SGE_ST_Heal_Taurochole = 14021, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Haima Option", "Applies Haima.", SGE.JobID, 7, "", "")] + [CustomComboInfo("Haima Option", "Applies Haima.", SGE.JobID, 7)] SGE_ST_Heal_Haima = 14022, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Rhizomata Option", "Adds Rhizomata when Addersgall is 0.", SGE.JobID, 10, "", "")] + [CustomComboInfo("Rhizomata Option", "Adds Rhizomata when Addersgall is 0.", SGE.JobID, 10)] SGE_ST_Heal_Rhizomata = 14023, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Krasis Option", "Applies Krasis.", SGE.JobID, 8, "", "")] + [CustomComboInfo("Krasis Option", "Applies Krasis.", SGE.JobID, 8)] SGE_ST_Heal_Krasis = 14024, [ParentCombo(SGE_ST_Heal)] - [CustomComboInfo("Druochole Option", "Applies Druochole.", SGE.JobID, 9, "", "")] + [CustomComboInfo("Druochole Option", "Applies Druochole.", SGE.JobID, 9)] SGE_ST_Heal_Druochole = 14025, #endregion #region Sage Simple AoE Heal [ReplaceSkill(SGE.Prognosis)] - [CustomComboInfo("AoE Heal Feature", "Customize your AoE healing to your liking.", SGE.JobID, 500, "", "")] + [CustomComboInfo("AoE Heal Feature", "Customize your AoE healing to your liking.", SGE.JobID, 500)] SGE_AoE_Heal = 14026, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Physis Option", "Adds Physis.", SGE.JobID, 504, "", "")] + [CustomComboInfo("Physis Option", "Adds Physis.", SGE.JobID, 504)] SGE_AoE_Heal_Physis = 14027, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Philosophia Option", "Adds Philosophia.", SGE.JobID, 505, "", "")] + [CustomComboInfo("Philosophia Option", "Adds Philosophia.", SGE.JobID, 505)] SGE_AoE_Heal_Philosophia = 14050, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Eukrasian Prognosis Option", "Prognosis becomes Eukrasian Prognosis if the shield is not applied.", SGE.JobID, 520, "", "")] + [CustomComboInfo("Eukrasian Prognosis Option", "Prognosis becomes Eukrasian Prognosis if the shield is not applied.", SGE.JobID, 520)] SGE_AoE_Heal_EPrognosis = 14028, [ParentCombo(SGE_AoE_Heal_EPrognosis)] - [CustomComboInfo("Ignore Shield Check", "Warning, will force the use of Eukrasia Prognosis, and normal Prognosis will be unavailable.", SGE.JobID, 520, "", "")] + [CustomComboInfo("Ignore Shield Check", "Warning, will force the use of Eukrasia Prognosis, and normal Prognosis will be unavailable.", SGE.JobID, 520)] SGE_AoE_Heal_EPrognosis_IgnoreShield = 14029, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Holos Option", "Adds Holos.", SGE.JobID, 505, "", "")] + [CustomComboInfo("Holos Option", "Adds Holos.", SGE.JobID, 505)] SGE_AoE_Heal_Holos = 14030, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Panhaima Option", "Adds Panhaima.", SGE.JobID, 506, "", "")] + [CustomComboInfo("Panhaima Option", "Adds Panhaima.", SGE.JobID, 506)] SGE_AoE_Heal_Panhaima = 14031, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Pepsis Option", "Triggers Pepsis if a shield is present.", SGE.JobID, 507, "", "")] + [CustomComboInfo("Pepsis Option", "Triggers Pepsis if a shield is present.", SGE.JobID, 507)] SGE_AoE_Heal_Pepsis = 14032, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Ixochole Option", "Adds Ixochole.", SGE.JobID, 503, "", "")] + [CustomComboInfo("Ixochole Option", "Adds Ixochole.", SGE.JobID, 503)] SGE_AoE_Heal_Ixochole = 14033, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Kerachole Option", "Adds Kerachole.", SGE.JobID, 502, "", "")] + [CustomComboInfo("Kerachole Option", "Adds Kerachole.", SGE.JobID, 502)] SGE_AoE_Heal_Kerachole = 14035, [ParentCombo(SGE_AoE_Heal)] - [CustomComboInfo("Rhizomata Option", "Adds Rhizomata when Addersgall is 0.", SGE.JobID, 501, "", "")] + [CustomComboInfo("Rhizomata Option", "Adds Rhizomata when Addersgall is 0.", SGE.JobID, 501)] SGE_AoE_Heal_Rhizomata = 14036, #endregion #region Misc Healing [ReplaceSkill(SGE.Taurochole, SGE.Druochole, SGE.Ixochole, SGE.Kerachole)] - [CustomComboInfo("Rhizomata Feature", "Replaces Addersgall skills with Rhizomata when empty.", SGE.JobID, 600, "", "")] + [CustomComboInfo("Rhizomata Feature", "Replaces Addersgall skills with Rhizomata when empty.", SGE.JobID, 600)] SGE_Rhizo = 14037, [ReplaceSkill(SGE.Taurochole)] - [CustomComboInfo("Taurochole to Druochole Feature", "Turns Taurochole to Druochole when Taurochole is on cooldown.", SGE.JobID, 700, "", "")] + [CustomComboInfo("Taurochole to Druochole Feature", "Turns Taurochole to Druochole when Taurochole is on cooldown.", SGE.JobID, 700)] SGE_TauroDruo = 14038, [ReplaceSkill(SGE.Pneuma)] - [CustomComboInfo("Zoe Pneuma Feature", "Places Zoe on top of Pneuma when both actions are on cooldown.", SGE.JobID, 701, "", "")] //Temporary to keep the order + [CustomComboInfo("Zoe Pneuma Feature", "Places Zoe on top of Pneuma when both actions are on cooldown.", SGE.JobID, 701)] //Temporary to keep the order SGE_ZoePneuma = 14039, #endregion #region Utility [ReplaceSkill(All.Swiftcast)] [ConflictingCombos(ALL_Healer_Raise)] - [CustomComboInfo("Swiftcast Raise Feature", "Changes Swiftcast to Egeiro while Swiftcast is on cooldown.", SGE.JobID, 800, "", "")] + [CustomComboInfo("Swiftcast Raise Feature", "Changes Swiftcast to Egeiro while Swiftcast is on cooldown.", SGE.JobID, 800)] SGE_Raise = 14040, [ReplaceSkill(SGE.Soteria)] - [CustomComboInfo("Soteria to Kardia Feature", "Soteria turns into Kardia when not active or Soteria is on-cooldown.", SGE.JobID, 900, "", "")] + [CustomComboInfo("Soteria to Kardia Feature", "Soteria turns into Kardia when not active or Soteria is on-cooldown.", SGE.JobID, 900)] SGE_Kardia = 14041, [ReplaceSkill(SGE.Eukrasia)] - [CustomComboInfo("Eukrasia Feature", "Eukrasia turns into the selected Eukrasian-type action when active.", SGE.JobID, 1000, "", "")] + [CustomComboInfo("Eukrasia Feature", "Eukrasia turns into the selected Eukrasian-type action when active.", SGE.JobID, 1000)] SGE_Eukrasia = 14042, [ReplaceSkill(SGE.Kerachole)] - [CustomComboInfo("Spell Overlap Protection", "Prevents you from wasting actions if under the effect of someone else's actions", SGE.JobID, 1000, "", "")] + [CustomComboInfo("Spell Overlap Protection", "Prevents you from wasting actions if under the effect of someone else's actions", SGE.JobID, 1000)] SGE_OverProtect = 14043, [ParentCombo(SGE_OverProtect)] - [CustomComboInfo("Under Kerachole", "Don't use Kerachole when under the effect of someone's Kerachole", SGE.JobID, 1000, "", "")] + [CustomComboInfo("Under Kerachole", "Don't use Kerachole when under the effect of someone's Kerachole", SGE.JobID, 1000)] SGE_OverProtect_Kerachole = 14044, [ParentCombo(SGE_OverProtect_Kerachole)] - [CustomComboInfo("Under Sacred Soil", "Don't use Kerachole when under the effect of someone's Sacred Soil", SGE.JobID, 1000, "", "")] + [CustomComboInfo("Under Sacred Soil", "Don't use Kerachole when under the effect of someone's Sacred Soil", SGE.JobID, 1000)] SGE_OverProtect_SacredSoil = 14045, [ParentCombo(SGE_OverProtect)] - [CustomComboInfo("Under Panhaima", "Don't use Panhaima when under the effect of someone's Panhaima", SGE.JobID, 1000, "", "")] + [CustomComboInfo("Under Panhaima", "Don't use Panhaima when under the effect of someone's Panhaima", SGE.JobID, 1000)] SGE_OverProtect_Panhaima = 14046, [ParentCombo(SGE_OverProtect)] - [CustomComboInfo("Under Philosophia", "Don't use Philosophia when under the effect of someone's Philosophia", SGE.JobID, 1000, "", "")] + [CustomComboInfo("Under Philosophia", "Don't use Philosophia when under the effect of someone's Philosophia", SGE.JobID, 1000)] SGE_OverProtect_Philosophia = 14047, [Variant] @@ -3903,23 +3903,23 @@ The three digets after RDM.JobID can be used to reorder items in the list SMN_Advanced_Combo = 17000, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Demi Attacks Combo Option", "Adds Demi Summon oGCDs to the single target and AoE combos.", SMN.JobID, 11, "", "")] + [CustomComboInfo("Demi Attacks Combo Option", "Adds Demi Summon oGCDs to the single target and AoE combos.", SMN.JobID, 11)] SMN_Advanced_Combo_DemiSummons_Attacks = 17002, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Egi Attacks Combo Option", "Adds Gemshine and Precious Brilliance to the single target and AoE combos, respectively.", SMN.JobID, 4, "", "")] + [CustomComboInfo("Egi Attacks Combo Option", "Adds Gemshine and Precious Brilliance to the single target and AoE combos, respectively.", SMN.JobID, 4)] SMN_Advanced_Combo_EgiSummons_Attacks = 17004, [ReplaceSkill(SMN.Fester)] - [CustomComboInfo("Energy Drain to Fester Feature", "Change Fester into Energy Drain when out of Aetherflow stacks.", SMN.JobID, 6, "", "")] + [CustomComboInfo("Energy Drain to Fester Feature", "Change Fester into Energy Drain when out of Aetherflow stacks.", SMN.JobID, 6)] SMN_EDFester = 17008, [ReplaceSkill(SMN.Painflare)] - [CustomComboInfo("Energy Siphon to Painflare Feature", "Change Painflare into Energy Siphon when out of Aetherflow stacks.", SMN.JobID, 7, "", "")] + [CustomComboInfo("Energy Siphon to Painflare Feature", "Change Painflare into Energy Siphon when out of Aetherflow stacks.", SMN.JobID, 7)] SMN_ESPainflare = 17009, // BONUS TWEAKS - [CustomComboInfo("Carbuncle Reminder Feature", "Replaces most offensive actions with Summon Carbuncle when it is not summoned.", SMN.JobID, 8, "", "")] + [CustomComboInfo("Carbuncle Reminder Feature", "Replaces most offensive actions with Summon Carbuncle when it is not summoned.", SMN.JobID, 8)] SMN_CarbuncleReminder = 17010, [ParentCombo(SMN_Advanced_Combo)] @@ -3931,73 +3931,73 @@ The three digets after RDM.JobID can be used to reorder items in the list SMN_EDFester_Ruin4 = 17013, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Energy Attacks Combo Option", "Adds Energy Drain and Fester to the single target combo.\nAdds Energy Siphon and Painflare to the AoE combo.\nWill be used on cooldown.", SMN.JobID, 1, "", "")] + [CustomComboInfo("Energy Attacks Combo Option", "Adds Energy Drain and Fester to the single target combo.\nAdds Energy Siphon and Painflare to the AoE combo.\nWill be used on cooldown.", SMN.JobID, 1)] SMN_Advanced_Combo_EDFester = 17014, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Egi Summons Combo Option", "Adds Egi summons to the single target and AoE combos.\nWill prioritise the Egi selected below.\nIf no option is selected, the feature will default to summoning Titan first.", SMN.JobID, 3, "", "")] + [CustomComboInfo("Egi Summons Combo Option", "Adds Egi summons to the single target and AoE combos.\nWill prioritise the Egi selected below.\nIf no option is selected, the feature will default to summoning Titan first.", SMN.JobID, 3)] SMN_DemiEgiMenu_EgiOrder = 17016, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Searing Light Combo Option", "Adds Searing Light to the single target and AoE combos.\nWill be used on cooldown.", SMN.JobID, 9, "", "")] + [CustomComboInfo("Searing Light Combo Option", "Adds Searing Light to the single target and AoE combos.\nWill be used on cooldown.", SMN.JobID, 9)] SMN_SearingLight = 17017, [ParentCombo(SMN_SearingLight)] - [CustomComboInfo("Searing Light Burst Option", "Casts Searing Light only during Demi phases.\nReflects Demi choice selected under 'Pooled oGCDs Option'.\nNot recommended for SpS Builds.", SMN.JobID, 0, "")] + [CustomComboInfo("Searing Light Burst Option", "Casts Searing Light only during Demi phases.\nReflects Demi choice selected under 'Pooled oGCDs Option'.\nNot recommended for SpS Builds.", SMN.JobID, 0)] SMN_SearingLight_Burst = 17018, [ParentCombo(SMN_SearingLight)] - [CustomComboInfo("Searing Flash Combo Option", "Adds Searing Flash to the single target and AoE combos.", SMN.JobID, 1, "", "")] + [CustomComboInfo("Searing Flash Combo Option", "Adds Searing Flash to the single target and AoE combos.", SMN.JobID, 1)] SMN_SearingFlash = 17019, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Demi Summons Combo Option", "Adds Demi summons to the single target and AoE combos.", SMN.JobID, 10, "", "")] + [CustomComboInfo("Demi Summons Combo Option", "Adds Demi summons to the single target and AoE combos.", SMN.JobID, 10)] SMN_Advanced_Combo_DemiSummons = 17020, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Swiftcast Egi Ability Option", "Uses Swiftcast during the selected Egi summon.", SMN.JobID, 8, "", "")] + [CustomComboInfo("Swiftcast Egi Ability Option", "Uses Swiftcast during the selected Egi summon.", SMN.JobID, 8)] SMN_DemiEgiMenu_SwiftcastEgi = 17023, - [CustomComboInfo("Astral Flow/Enkindle on Demis Feature", "Adds Enkindle Bahamut, Enkindle Phoenix and Astral Flow to their relevant summons.", SMN.JobID, 11, "", "")] + [CustomComboInfo("Astral Flow/Enkindle on Demis Feature", "Adds Enkindle Bahamut, Enkindle Phoenix and Astral Flow to their relevant summons.", SMN.JobID, 11)] SMN_DemiAbilities = 17024, [ParentCombo(SMN_Advanced_Combo_EDFester)] - [CustomComboInfo("Pooled oGCDs Option", "Pools damage oGCDs for use inside the selected Demi phase while under the Searing Light buff.\nBahamut Burst becomes Solar Bahamut Burst at Lv100.", SMN.JobID, 1, "", "")] + [CustomComboInfo("Pooled oGCDs Option", "Pools damage oGCDs for use inside the selected Demi phase while under the Searing Light buff.\nBahamut Burst becomes Solar Bahamut Burst at Lv100.", SMN.JobID, 1)] SMN_DemiEgiMenu_oGCDPooling = 17025, [ConflictingCombos(ALL_Caster_Raise)] - [CustomComboInfo("Alternative Raise Feature", "Changes Swiftcast to Raise when on cooldown.", SMN.JobID, 8, "", "")] + [CustomComboInfo("Alternative Raise Feature", "Changes Swiftcast to Raise when on cooldown.", SMN.JobID, 8)] SMN_Raise = 17027, [ParentCombo(SMN_Advanced_Combo_DemiSummons_Attacks)] - [CustomComboInfo("Rekindle Combo Option", "Adds Rekindle to the single target and AoE combos.", SMN.JobID, 13, "", "")] + [CustomComboInfo("Rekindle Combo Option", "Adds Rekindle to the single target and AoE combos.", SMN.JobID, 13)] SMN_Advanced_Combo_DemiSummons_Rekindle = 17028, [ParentCombo(SMN_Advanced_Combo_DemiSummons_Attacks)] - [CustomComboInfo("Lux Solaris Combo Option", "Adds Lux Solaris to the single target and AoE combos.", SMN.JobID, 14, "", "")] + [CustomComboInfo("Lux Solaris Combo Option", "Adds Lux Solaris to the single target and AoE combos.", SMN.JobID, 14)] SMN_Advanced_Combo_DemiSummons_LuxSolaris = 17029, [ReplaceSkill(SMN.Ruin4)] - [CustomComboInfo("Ruin III Mobility Feature", "Puts Ruin III on Ruin IV when you don't have Further Ruin.", SMN.JobID, 9, "", "")] + [CustomComboInfo("Ruin III Mobility Feature", "Puts Ruin III on Ruin IV when you don't have Further Ruin.", SMN.JobID, 9)] SMN_RuinMobility = 17030, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming to the single target combo when MP falls below the set value.", SMN.JobID, 2, "", "")] + [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming to the single target combo when MP falls below the set value.", SMN.JobID, 2)] SMN_Lucid = 17031, - [CustomComboInfo("Egi Abilities on Summons Feature", "Adds Egi Abilities (Astral Flow) to Egi summons when ready.\nEgi abilities will appear on their respective Egi summon ability, as well as Titan.", SMN.JobID, 12, "", "")] + [CustomComboInfo("Egi Abilities on Summons Feature", "Adds Egi Abilities (Astral Flow) to Egi summons when ready.\nEgi abilities will appear on their respective Egi summon ability, as well as Titan.", SMN.JobID, 12)] SMN_Egi_AstralFlow = 17034, [ParentCombo(SMN_SearingLight)] - [CustomComboInfo("Use only on Single Target combo", "Prevent this feature from applying to the AoE combo.", SMN.JobID, 2, "", "")] + [CustomComboInfo("Use only on Single Target combo", "Prevent this feature from applying to the AoE combo.", SMN.JobID, 2)] SMN_SearingLight_STOnly = 17036, [ParentCombo(SMN_DemiEgiMenu_oGCDPooling)] - [CustomComboInfo("Use only on Single Target combo", "Prevent this feature from applying to the AoE combo.", SMN.JobID, 3, "", "")] + [CustomComboInfo("Use only on Single Target combo", "Prevent this feature from applying to the AoE combo.", SMN.JobID, 3)] SMN_DemiEgiMenu_oGCDPooling_Only = 17037, [ParentCombo(SMN_DemiEgiMenu_SwiftcastEgi)] - [CustomComboInfo("Use only on Single Target combo", "Prevent this feature from applying to the AoE combo.", SMN.JobID, 2, "", "")] + [CustomComboInfo("Use only on Single Target combo", "Prevent this feature from applying to the AoE combo.", SMN.JobID, 2)] SMN_DemiEgiMenu_SwiftcastEgi_Only = 17038, [ParentCombo(SMN_ESPainflare)] @@ -4005,20 +4005,20 @@ The three digets after RDM.JobID can be used to reorder items in the list SMN_ESPainflare_Ruin4 = 17039, [ParentCombo(SMN_Advanced_Combo)] - [CustomComboInfo("Add Egi Astralflow", "Choose which Egi Astralflows to add to the rotation.", SMN.JobID, 0, "", "")] + [CustomComboInfo("Add Egi Astralflow", "Choose which Egi Astralflows to add to the rotation.", SMN.JobID, 0)] SMN_ST_Egi_AstralFlow = 17048, [ConflictingCombos(SMN_Advanced_Combo)] [ReplaceSkill(SMN.Ruin, SMN.Ruin2, SMN.Outburst, SMN.Tridisaster)] - [CustomComboInfo("Simple Summoner Feature", "General purpose one-button combo.\nBursts on Bahamut phase.\nSummons Titan, Garuda, then Ifrit.\nSwiftcasts on Slipstream unless drifted.", SMN.JobID, -1, "", "")] + [CustomComboInfo("Simple Summoner Feature", "General purpose one-button combo.\nBursts on Bahamut phase.\nSummons Titan, Garuda, then Ifrit.\nSwiftcasts on Slipstream unless drifted.", SMN.JobID, -1)] SMN_Simple_Combo = 17041, [ParentCombo(SMN_DemiEgiMenu_oGCDPooling)] - [CustomComboInfo("Burst Delay Option", "Only follows Burst Delay settings for the opener burst.\nThis Option is for high SPS builds.", SMN.JobID, 2, "", "")] + [CustomComboInfo("Burst Delay Option", "Only follows Burst Delay settings for the opener burst.\nThis Option is for high SPS builds.", SMN.JobID, 2)] SMN_Advanced_Burst_Delay_Option = 17043, [ParentCombo(SMN_DemiEgiMenu_oGCDPooling)] - [CustomComboInfo("Any Searing Burst Option", "Checks for any Searing light for bursting rather than just your own.\nUse this option if partied with multiple SMN and are worried about your Searing being overwritten.", SMN.JobID, 1, "", "")] + [CustomComboInfo("Any Searing Burst Option", "Checks for any Searing light for bursting rather than just your own.\nUse this option if partied with multiple SMN and are worried about your Searing being overwritten.", SMN.JobID, 1)] SMN_Advanced_Burst_Any_Option = 17044, [Variant] @@ -4247,43 +4247,43 @@ The three digets after RDM.JobID can be used to reorder items in the list WAR_ST_Advanced_InnerRelease = 18003, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Tomahawk Uptime Option", "Adds Tomahawk to Advanced Mode when you are out of range.", WAR.JobID, 1, "", "")] + [CustomComboInfo("Tomahawk Uptime Option", "Adds Tomahawk to Advanced Mode when you are out of range.", WAR.JobID, 1)] WAR_ST_Advanced_RangedUptime = 18004, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Storm's Eye Option", "Adds Storms Eye to Advanced Mode.", WAR.JobID, 2, "", "")] + [CustomComboInfo("Storm's Eye Option", "Adds Storms Eye to Advanced Mode.", WAR.JobID, 2)] WAR_ST_Advanced_StormsEye = 18005, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Inner Beast / Fell Cleave Option", "Adds Inner Beast / Fell Cleave to Advanced Mode. Will use when you have the set minimum gauge, or under the effect of Inner Release. Will also use Nascent Chaos.", WAR.JobID, 2, "", "")] + [CustomComboInfo("Inner Beast / Fell Cleave Option", "Adds Inner Beast / Fell Cleave to Advanced Mode. Will use when you have the set minimum gauge, or under the effect of Inner Release. Will also use Nascent Chaos.", WAR.JobID, 2)] WAR_ST_Advanced_FellCleave = 18006, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Infuriate Option", "Adds Infuriate to Advanced Mode.", WAR.JobID, 3, "", "")] + [CustomComboInfo("Infuriate Option", "Adds Infuriate to Advanced Mode.", WAR.JobID, 3)] WAR_ST_Advanced_Infuriate = 18007, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Onslaught Option", "Adds Onslaught to Advanced Mode if you are under Surging Tempest Buff.", WAR.JobID, 4, "", "")] + [CustomComboInfo("Onslaught Option", "Adds Onslaught to Advanced Mode if you are under Surging Tempest Buff.", WAR.JobID, 4)] WAR_ST_Advanced_Onslaught = 18008, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Upheaval Option", "Adds Upheaval to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Upheaval Option", "Adds Upheaval to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5)] WAR_ST_Advanced_Upheaval = 18009, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Primal Wrath Option", "Adds Primal Wrath to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Primal Wrath Option", "Adds Primal Wrath to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5)] WAR_ST_Advanced_PrimalWrath = 18010, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Primal Ruination Option", "Adds Primal Ruination to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Primal Ruination Option", "Adds Primal Ruination to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5)] WAR_ST_Advanced_PrimalRuination = 18011, [ParentCombo(WAR_AoE_Advanced)] - [CustomComboInfo("Orogeny Option", "Adds Orogeny to Advanced Mode when you are buffed with Surging Tempest.", WAR.JobID, 6, "", "")] + [CustomComboInfo("Orogeny Option", "Adds Orogeny to Advanced Mode when you are buffed with Surging Tempest.", WAR.JobID, 6)] WAR_AoE_Advanced_Orogeny = 18012, [ParentCombo(WAR_ST_Advanced)] - [CustomComboInfo("Primal Rend Option", "Adds Primal Rend to Advanced Mode. Only uses when in the Target's target ring (1 yalm) & when not moving. Otherwise, will use when buff time is equal to 1 GCD.", WAR.JobID, 7, "", "")] + [CustomComboInfo("Primal Rend Option", "Adds Primal Rend to Advanced Mode. Only uses when in the Target's target ring (1 yalm) & when not moving. Otherwise, will use when buff time is equal to 1 GCD.", WAR.JobID, 7)] WAR_ST_Advanced_PrimalRend = 18013, [ParentCombo(WAR_ST_Advanced_PrimalRend)] @@ -4298,11 +4298,11 @@ The three digets after RDM.JobID can be used to reorder items in the list #region Advanced AoE [ConflictingCombos(WAR_AoE_Simple)] [ReplaceSkill(WAR.Overpower)] - [CustomComboInfo("Advanced Mode - AoE", "Replaces Overpower with a one-button full AoE rotation.\nThis is the ideal selection for users experienced with the job.", WAR.JobID, 2, "", "")] + [CustomComboInfo("Advanced Mode - AoE", "Replaces Overpower with a one-button full AoE rotation.\nThis is the ideal selection for users experienced with the job.", WAR.JobID, 2)] WAR_AoE_Advanced = 18016, [ReplaceSkill(WAR.NascentFlash)] - [CustomComboInfo("Nascent Flash Feature", "Replace Nascent Flash with Raw intuition when level synced below 76.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Nascent Flash Feature", "Replace Nascent Flash with Raw intuition when level synced below 76.", WAR.JobID, 5)] WAR_NascentFlash = 18017, [ParentCombo(WAR_AoE_Advanced)] @@ -4314,15 +4314,15 @@ The three digets after RDM.JobID can be used to reorder items in the list WAR_AoE_Advanced_InnerRelease = 18019, [ParentCombo(WAR_AoE_Advanced)] - [CustomComboInfo("Primal Wrath Option", "Adds Primal Wrath to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Primal Wrath Option", "Adds Primal Wrath to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5)] WAR_AoE_Advanced_PrimalWrath = 18020, [ParentCombo(WAR_AoE_Advanced)] - [CustomComboInfo("Primal Rend Option", "Adds Primal Rend to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Primal Rend Option", "Adds Primal Rend to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5)] WAR_AoE_Advanced_PrimalRend = 18021, [ParentCombo(WAR_AoE_Advanced)] - [CustomComboInfo("Primal Ruination Option", "Adds Primal Ruination to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5, "", "")] + [CustomComboInfo("Primal Ruination Option", "Adds Primal Ruination to Advanced Mode if you have Surging Tempest.", WAR.JobID, 5)] WAR_AoE_Advanced_PrimalRuination = 18022, [ParentCombo(WAR_AoE_Advanced)] @@ -4332,15 +4332,15 @@ The three digets after RDM.JobID can be used to reorder items in the list #region Misc [ReplaceSkill(WAR.FellCleave, WAR.Decimate)] - [CustomComboInfo("Infuriate on Fell Cleave / Decimate Feature", "Turns Fell Cleave and Decimate into Infuriate if at or under set rage value.", WAR.JobID, 4, "", "")] + [CustomComboInfo("Infuriate on Fell Cleave / Decimate Feature", "Turns Fell Cleave and Decimate into Infuriate if at or under set rage value.", WAR.JobID, 4)] WAR_InfuriateFellCleave = 18024, [ReplaceSkill(WAR.StormsEye)] - [CustomComboInfo("Storm's Eye Combo Feature", "Replace Storm's Eye with its combo chain.", WAR.JobID, 3, "", "")] + [CustomComboInfo("Storm's Eye Combo Feature", "Replace Storm's Eye with its combo chain.", WAR.JobID, 3)] War_ST_StormsEye = 18025, [ReplaceSkill(WAR.InnerRelease)] - [CustomComboInfo("Primal Combo Feature", "Turns Inner Release into the Primal combo on use.", WAR.JobID, 3, "", "")] + [CustomComboInfo("Primal Combo Feature", "Turns Inner Release into the Primal combo on use.", WAR.JobID, 3)] WAR_PrimalCombo_InnerRelease = 18026, [ParentCombo(WAR_InfuriateFellCleave)] @@ -4372,39 +4372,39 @@ The three digets after RDM.JobID can be used to reorder items in the list #region Single Target DPS Feature [ReplaceSkill(WHM.Stone1, WHM.Stone2, WHM.Stone3, WHM.Stone4, WHM.Glare1, WHM.Glare3)] - [CustomComboInfo("Single Target DPS Feature", "Collection of cooldowns and spell features on Glare/Stone.", WHM.JobID, 1, "", "")] + [CustomComboInfo("Single Target DPS Feature", "Collection of cooldowns and spell features on Glare/Stone.", WHM.JobID, 1)] WHM_ST_MainCombo = 19099, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Opener Option", "Use the Balance opener from level 56+.", WHM.JobID, 11, "", "")] + [CustomComboInfo("Opener Option", "Use the Balance opener from level 56+.", WHM.JobID, 11)] WHM_ST_MainCombo_Opener = 19023, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Aero/Dia Uptime Option", "Adds Aero/Dia to the single target combo if the debuff is not present on current target, or is about to expire.", WHM.JobID, 12, "", "")] + [CustomComboInfo("Aero/Dia Uptime Option", "Adds Aero/Dia to the single target combo if the debuff is not present on current target, or is about to expire.", WHM.JobID, 12)] WHM_ST_MainCombo_DoT = 19013, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Assize Option", "Adds Assize to the single target combo.", WHM.JobID, 13, "", "")] + [CustomComboInfo("Assize Option", "Adds Assize to the single target combo.", WHM.JobID, 13)] WHM_ST_MainCombo_Assize = 19009, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Glare IV Option", "Adds Glare IV to the single target combo when under Sacred Sight", WHM.JobID, 14, "", "")] + [CustomComboInfo("Glare IV Option", "Adds Glare IV to the single target combo when under Sacred Sight", WHM.JobID, 14)] WHM_ST_MainCombo_GlareIV = 19015, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Afflatus Misery Option", "Adds Afflatus Misery to the single target combo when it is ready to be used.", WHM.JobID, 15, "", "")] + [CustomComboInfo("Afflatus Misery Option", "Adds Afflatus Misery to the single target combo when it is ready to be used.", WHM.JobID, 15)] WHM_ST_MainCombo_Misery_oGCD = 19017, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Lily Overcap Protection Option", "Adds Afflatus Rapture to the single target combo when at three Lilies.", WHM.JobID, 16, "", "")] + [CustomComboInfo("Lily Overcap Protection Option", "Adds Afflatus Rapture to the single target combo when at three Lilies.", WHM.JobID, 16)] WHM_ST_MainCombo_LilyOvercap = 19016, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Presence of Mind Option", "Adds Presence of Mind to the single target combo.", WHM.JobID, 17, "", "")] + [CustomComboInfo("Presence of Mind Option", "Adds Presence of Mind to the single target combo.", WHM.JobID, 17)] WHM_ST_MainCombo_PresenceOfMind = 19008, [ParentCombo(WHM_ST_MainCombo)] - [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming to the single target combo when below set MP value.", WHM.JobID, 18, "", "")] + [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming to the single target combo when below set MP value.", WHM.JobID, 18)] WHM_ST_MainCombo_Lucid = 19006, #endregion @@ -4412,59 +4412,59 @@ The three digets after RDM.JobID can be used to reorder items in the list #region AoE DPS Feature [ReplaceSkill(WHM.Holy, WHM.Holy3)] - [CustomComboInfo("AoE DPS Feature", "Collection of cooldowns and spell features on Holy/Holy III.", WHM.JobID, 2, "", "")] + [CustomComboInfo("AoE DPS Feature", "Collection of cooldowns and spell features on Holy/Holy III.", WHM.JobID, 2)] WHM_AoE_DPS = 19190, [ParentCombo(WHM_AoE_DPS)] - [CustomComboInfo("Assize Option", "Adds Assize to the AoE combo.", WHM.JobID, 21, "", "")] + [CustomComboInfo("Assize Option", "Adds Assize to the AoE combo.", WHM.JobID, 21)] WHM_AoE_DPS_Assize = 19192, [ParentCombo(WHM_AoE_DPS)] - [CustomComboInfo("Glare IV Option", "Adds Glare IV to the AoE combo when under Sacred Sight", WHM.JobID, 22, "", "")] + [CustomComboInfo("Glare IV Option", "Adds Glare IV to the AoE combo when under Sacred Sight", WHM.JobID, 22)] WHM_AoE_DPS_GlareIV = 19196, [ParentCombo(WHM_AoE_DPS)] - [CustomComboInfo("Afflatus Misery Option", "Adds Afflatus Misery to the AoE combo when it is ready to be used.", WHM.JobID, 23, "", "")] + [CustomComboInfo("Afflatus Misery Option", "Adds Afflatus Misery to the AoE combo when it is ready to be used.", WHM.JobID, 23)] WHM_AoE_DPS_Misery = 19194, [ParentCombo(WHM_AoE_DPS)] - [CustomComboInfo("Lily Overcap Protection Option", "Adds Afflatus Rapture to the AoE combo when at three Lilies.", WHM.JobID, 24, "", "")] + [CustomComboInfo("Lily Overcap Protection Option", "Adds Afflatus Rapture to the AoE combo when at three Lilies.", WHM.JobID, 24)] WHM_AoE_DPS_LilyOvercap = 19193, [ParentCombo(WHM_AoE_DPS)] - [CustomComboInfo("Presence of Mind Option", "Adds Presence of Mind to the AoE combo, this will delay your GCD by default.", WHM.JobID, 25, "", "")] + [CustomComboInfo("Presence of Mind Option", "Adds Presence of Mind to the AoE combo, this will delay your GCD by default.", WHM.JobID, 25)] WHM_AoE_DPS_PresenceOfMind = 19195, [ParentCombo(WHM_AoE_DPS)] - [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming to the AoE combo when below the set MP value if you are moving or it can be weaved without GCD delay.", WHM.JobID, 26, "", "")] + [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming to the AoE combo when below the set MP value if you are moving or it can be weaved without GCD delay.", WHM.JobID, 26)] WHM_AoE_DPS_Lucid = 19191, #endregion [ReplaceSkill(WHM.AfflatusSolace)] - [CustomComboInfo("Solace into Misery Feature", "Replaces Afflatus Solace with Afflatus Misery when it is ready to be used.", WHM.JobID, 30, "", "")] + [CustomComboInfo("Solace into Misery Feature", "Replaces Afflatus Solace with Afflatus Misery when it is ready to be used.", WHM.JobID, 30)] WHM_SolaceMisery = 19000, [ReplaceSkill(WHM.AfflatusRapture)] - [CustomComboInfo("Rapture into Misery Feature", "Replaces Afflatus Rapture with Afflatus Misery when it is ready to be used.", WHM.JobID, 40, "", "")] + [CustomComboInfo("Rapture into Misery Feature", "Replaces Afflatus Rapture with Afflatus Misery when it is ready to be used.", WHM.JobID, 40)] WHM_RaptureMisery = 19001, #region AoE Heals Feature [ReplaceSkill(WHM.Medica1)] - [CustomComboInfo("Simple Heals (AoE)", "Replaces Medica with a one button AoE healing setup.", WHM.JobID, 4, "", "")] + [CustomComboInfo("Simple Heals (AoE)", "Replaces Medica with a one button AoE healing setup.", WHM.JobID, 4)] WHM_AoEHeals = 19007, [ParentCombo(WHM_AoEHeals)] - [CustomComboInfo("Afflatus Rapture Option", "Uses Afflatus Rapture when available.", WHM.JobID, 2, "", "")] + [CustomComboInfo("Afflatus Rapture Option", "Uses Afflatus Rapture when available.", WHM.JobID, 2)] WHM_AoEHeals_Rapture = 19011, [ParentCombo(WHM_AoEHeals)] - [CustomComboInfo("Afflatus Misery Option", "Uses Afflatus Misery when available.", WHM.JobID, 3, "", "")] + [CustomComboInfo("Afflatus Misery Option", "Uses Afflatus Misery when available.", WHM.JobID, 3)] WHM_AoEHeals_Misery = 19010, [ParentCombo(WHM_AoEHeals)] - [CustomComboInfo("Thin Air Option", "Uses Thin Air when available.", WHM.JobID, 4, "", "")] + [CustomComboInfo("Thin Air Option", "Uses Thin Air when available.", WHM.JobID, 4)] WHM_AoEHeals_ThinAir = 19200, [ParentCombo(WHM_AoEHeals)] @@ -4542,16 +4542,16 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion [ReplaceSkill(WHM.Cure2)] - [CustomComboInfo("Cure II Sync Feature", "Changes Cure II to Cure when synced below Lv.30.", WHM.JobID, 70, "", "")] + [CustomComboInfo("Cure II Sync Feature", "Changes Cure II to Cure when synced below Lv.30.", WHM.JobID, 70)] WHM_CureSync = 19002, [ReplaceSkill(All.Swiftcast)] [ConflictingCombos(ALL_Healer_Raise)] - [CustomComboInfo("Alternative Raise Feature", "Changes Swiftcast to Raise.", WHM.JobID, 80, "", "")] + [CustomComboInfo("Alternative Raise Feature", "Changes Swiftcast to Raise.", WHM.JobID, 80)] WHM_Raise = 19004, [ReplaceSkill(WHM.Raise)] - [CustomComboInfo("Thin Air Raise Feature", "Adds Thin Air to the Global Raise Feature/Alternative Raise Feature.", WHM.JobID, 90, "", "")] + [CustomComboInfo("Thin Air Raise Feature", "Adds Thin Air to the Global Raise Feature/Alternative Raise Feature.", WHM.JobID, 90)] WHM_ThinAirRaise = 19014, [Variant] diff --git a/XIVSlothCombo/Core/PluginConfiguration.cs b/XIVSlothCombo/Core/PluginConfiguration.cs index 0f717f004..b627a652b 100644 --- a/XIVSlothCombo/Core/PluginConfiguration.cs +++ b/XIVSlothCombo/Core/PluginConfiguration.cs @@ -217,7 +217,7 @@ public void ResetFeatures(string config, int[] values) } var info = preset.GetComboAttribute(); - Svc.Chat.PrintError($"[XIVSlothCombo] - {info.JobName}: {info.FancyName}"); + Svc.Chat.PrintError($"[XIVSlothCombo] - {info.JobName}: {info.Name}"); EnabledActions.Remove(preset); } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Misc.cs b/XIVSlothCombo/CustomCombo/Functions/Misc.cs index 1e40be113..b749238ba 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Misc.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Misc.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +using ECommons.DalamudServices; +using Lumina.Excel.GeneratedSheets; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Core; @@ -19,6 +23,68 @@ internal abstract partial class CustomComboFunctions public class JobIDs { + public static int JobIDToRole(byte jobID) + { + if (Svc.Data.GetExcelSheet().HasRow(jobID)) + return Svc.Data.GetExcelSheet().GetRow(jobID).Role; + + return 0; + } + + public static string JobIDToShorthand(byte key) + { + if (key == 0) + return ""; + + if (ClassJobs.TryGetValue(key, out var job)) + { + return job.Abbreviation.RawString; + } + else + { + return ""; + } + } + + private static readonly Dictionary ClassJobs = Svc.Data.GetExcelSheet()!.ToDictionary(i => i.RowId, i => i); + + public static string JobIDToName(byte key) + { + if (key == 0) + return "General/Multiple Jobs"; + + //Override DOH/DOL + if (key is DOH.JobID) key = 08; //Set to Carpenter + if (key is DOL.JobID) key = 16; //Set to Miner + if (ClassJobs.TryGetValue(key, out ClassJob? job)) + { + //Grab Category name for DOH/DOL, else the normal Name for the rest + string jobname = key is 08 or 16 ? job.ClassJobCategory.Value.Name : job.Name; + //Job names are all lowercase by default. This capitalizes based on regional rules + string cultureID = Svc.ClientState.ClientLanguage switch + { + Dalamud.Game.ClientLanguage.French => "fr-FR", + Dalamud.Game.ClientLanguage.Japanese => "ja-JP", + Dalamud.Game.ClientLanguage.German => "de-DE", + _ => "en-us", + }; + TextInfo textInfo = new CultureInfo(cultureID, false).TextInfo; + jobname = textInfo.ToTitleCase(jobname); + //if (key is 0) jobname = " " + jobname; //Adding space to the front of Global moves it to the top. Shit hack but works + return jobname; + + } //Misc or unknown + else return key == 99 ? "Global" : "Unknown"; + } + + public static uint JobIDToClassJobCategory(byte jobID) + { + if (Svc.Data.GetExcelSheet().HasRow(jobID)) + return Svc.Data.GetExcelSheet().GetRow(jobID).ClassJobCategory.Row; + + return 0; + } + // Job IDs ClassIDs (no jobstone) (Lancer, Pugilist, etc) public static readonly List Melee = [ diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 2c00ddf18..038e82e07 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -1,9 +1,12 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; +using ECommons; using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; +using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text; @@ -13,26 +16,63 @@ using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; +using XIVSlothCombo.Window.Tabs; namespace XIVSlothCombo.Window.Functions { internal class Presets : ConfigWindow { + internal static Dictionary Attributes = new(); + internal class PresetAttributes + { + public bool IsPvP; + public CustomComboPreset[] Conflicts; + public CustomComboPreset? Parent; + public BlueInactiveAttribute? BlueInactive; + public VariantParentAttribute? VariantParent; + public BozjaParentAttribute? BozjaParent; + public EurekaParentAttribute? EurekaParent; + public HoverInfoAttribute? HoverInfo; + public ReplaceSkillAttribute? ReplaceSkill; + public CustomComboInfoAttribute? CustomComboInfo; + + public PresetAttributes(CustomComboPreset preset) + { + IsPvP = PresetStorage.IsPvP(preset); + Conflicts = PresetStorage.GetConflicts(preset); + Parent = PresetStorage.GetParent(preset); + BlueInactive = preset.GetAttribute(); + VariantParent = preset.GetAttribute(); + BozjaParent = preset.GetAttribute(); + EurekaParent = preset.GetAttribute(); + HoverInfo = preset.GetAttribute(); + ReplaceSkill = preset.GetAttribute(); + CustomComboInfo = preset.GetAttribute(); + } + } + internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfoAttribute info, ref int i) { + if (!Attributes.ContainsKey(preset)) + { + PresetAttributes attributes = new(preset); + Attributes[preset] = attributes; + } var enabled = PresetStorage.IsEnabled(preset); - var secret = PresetStorage.IsPvP(preset); - var conflicts = PresetStorage.GetConflicts(preset); - var parent = PresetStorage.GetParent(preset); - var blueAttr = preset.GetAttribute(); + var secret = Attributes[preset].IsPvP; + var conflicts = Attributes[preset].Conflicts; + var parent = Attributes[preset].Parent; + var blueAttr = Attributes[preset].BlueInactive; + var variantParents = Attributes[preset].VariantParent; + var bozjaParents = Attributes[preset].BozjaParent; + var eurekaParents = Attributes[preset].EurekaParent; ImGui.Spacing(); - if (ImGui.Checkbox($"{info.FancyName}###{info.FancyName}{i}", ref enabled)) + if (ImGui.Checkbox($"{info.Name}###{i}", ref enabled)) { if (enabled) { - EnableParentPresets(preset); Service.Configuration.EnabledActions.Add(preset); foreach (var conflict in conflicts) @@ -40,7 +80,6 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo Service.Configuration.EnabledActions.Remove(conflict); } } - else { Service.Configuration.EnabledActions.Remove(preset); @@ -48,35 +87,31 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo Service.Configuration.Save(); } - - ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey); - - DrawReplaceAttribute(preset); - Vector2 length = new(); - - if (i != -1) + using (var styleCol = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey)) { - ImGui.Text($"#{i}: "); - length = ImGui.CalcTextSize($"#{i}: "); - ImGui.SameLine(); - ImGui.PushItemWidth(length.Length()); - } - - ImGui.TextWrapped($"{info.Description}"); + DrawReplaceAttribute(preset); - if (preset.GetHoverAttribute() != null) - { - if (ImGui.IsItemHovered()) + if (i != -1) { - ImGui.BeginTooltip(); - ImGui.TextUnformatted(preset.GetHoverAttribute().HoverText); - ImGui.EndTooltip(); + ImGui.Text($"#{i}: "); + length = ImGui.CalcTextSize($"#{i}: "); + ImGui.SameLine(); + ImGui.PushItemWidth(length.Length()); } - } + ImGui.TextWrapped($"{info.Description}"); - ImGui.PopStyleColor(); + if (Attributes[preset].HoverInfo != null) + { + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted(Attributes[preset].HoverInfo.HoverText); + ImGui.EndTooltip(); + } + } + } ImGui.Spacing(); if (conflicts.Length > 0) @@ -86,15 +121,17 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.Indent(); foreach (var conflict in conflicts) { - var comboInfo = conflict.GetAttribute(); - conflictBuilder.Insert(0, $"{comboInfo.FancyName}"); + var comboInfo = Attributes.ContainsKey(conflict) ? Attributes[conflict].CustomComboInfo : conflict.GetAttribute(); + conflictBuilder.Insert(0, $"{comboInfo.Name}"); var par2 = conflict; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - conflictBuilder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) { + conflictBuilder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo : subpar?.GetAttribute().Name)} -> "); + par2 = subpar!.Value; + } } @@ -125,21 +162,23 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo } } - VariantParentAttribute? varientparents = preset.GetAttribute(); - if (varientparents is not null) + if (variantParents is not null) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen); - ImGui.TextWrapped($"Part of normal combo{(varientparents.ParentPresets.Length > 1 ? "s" : "")}:"); + ImGui.TextWrapped($"Part of normal combo{(variantParents.ParentPresets.Length > 1 ? "s" : "")}:"); StringBuilder builder = new(); - foreach (var par in varientparents.ParentPresets) + foreach (var par in variantParents.ParentPresets) { - builder.Insert(0, $"{par.GetAttribute().FancyName}"); + builder.Insert(0, $"{(Attributes.ContainsKey(par) ? Attributes[par].CustomComboInfo.Name : par.GetAttribute().Name)}"); var par2 = par; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - builder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + builder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.Name : subpar?.GetAttribute().Name)} -> "); + par2 = subpar!.Value; + } } @@ -149,21 +188,23 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.PopStyleColor(); } - BozjaParentAttribute? bozjaparents = preset.GetAttribute(); - if (bozjaparents is not null) + if (bozjaParents is not null) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen); - ImGui.TextWrapped($"Part of normal combo{(varientparents.ParentPresets.Length > 1 ? "s" : "")}:"); + ImGui.TextWrapped($"Part of normal combo{(variantParents.ParentPresets.Length > 1 ? "s" : "")}:"); StringBuilder builder = new(); - foreach (var par in bozjaparents.ParentPresets) + foreach (var par in bozjaParents.ParentPresets) { - builder.Insert(0, $"{par.GetAttribute().FancyName}"); + builder.Insert(0, $"{(Attributes.ContainsKey(par) ? Attributes[par].CustomComboInfo.Name : par.GetAttribute().Name)}"); var par2 = par; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - builder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + builder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.Name : subpar?.GetAttribute().Name)} -> "); + par2 = subpar!.Value; + } } @@ -173,21 +214,23 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.PopStyleColor(); } - EurekaParentAttribute? eurekaparents = preset.GetAttribute(); - if (eurekaparents is not null) + if (eurekaParents is not null) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen); - ImGui.TextWrapped($"Part of normal combo{(varientparents.ParentPresets.Length > 1 ? "s" : "")}:"); + ImGui.TextWrapped($"Part of normal combo{(variantParents.ParentPresets.Length > 1 ? "s" : "")}:"); StringBuilder builder = new(); - foreach (var par in eurekaparents.ParentPresets) + foreach (var par in eurekaParents.ParentPresets) { - builder.Insert(0, $"{par.GetAttribute().FancyName}"); + builder.Insert(0, $"{(Attributes.ContainsKey(par) ? Attributes[par].CustomComboInfo.Name : par.GetAttribute().Name)}"); var par2 = par; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - builder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + builder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.Name : subpar?.GetAttribute().Name)} -> "); + par2 = subpar!.Value; + } } @@ -199,23 +242,13 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo UserConfigItems.Draw(preset, enabled); - if (preset == CustomComboPreset.NIN_ST_SimpleMode_BalanceOpener || preset == CustomComboPreset.NIN_ST_AdvancedMode_BalanceOpener) - { - ImGui.SetCursorPosX(ImGui.GetCursorPosX() + length.Length()); - if (ImGui.Button($"Image of rotation###ninrtn{i}")) - { - Util.OpenLink("https://i.imgur.com/IeP27KF.png"); - } - } - i++; - var hideChildren = Service.Configuration.HideChildren; - var children = presetChildren[preset]; + var children = presetChildren.ContainsKey(preset) ? presetChildren[preset] : null; - if (children.Length > 0) + if (children != null) { - if (enabled || !hideChildren) + if (enabled || !Service.Configuration.HideChildren) { ImGui.Indent(); @@ -244,10 +277,10 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo continue; } } - else { DrawPreset(childPreset, childInfo, ref i); + continue; } } @@ -263,7 +296,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo private static void DrawReplaceAttribute(CustomComboPreset preset) { - var att = preset.GetReplaceAttribute(); + var att = Attributes[preset].ReplaceSkill; if (att != null) { string skills = string.Join(", ", att.ActionNames); diff --git a/XIVSlothCombo/Window/Messages/Messages.cs b/XIVSlothCombo/Window/Messages/Messages.cs index 7e2535d59..86503e354 100644 --- a/XIVSlothCombo/Window/Messages/Messages.cs +++ b/XIVSlothCombo/Window/Messages/Messages.cs @@ -1,5 +1,6 @@ using Dalamud.Interface.Colors; using ImGuiNET; +using XIVSlothCombo.CustomComboNS.Functions; namespace XIVSlothCombo.Window.MessagesNS { @@ -7,7 +8,7 @@ internal static class Messages { internal static bool PrintBLUMessage(string jobName) { - if (jobName == Attributes.CustomComboInfoAttribute.JobIDToName(36)) //Blue Mage ID + if (jobName == CustomComboFunctions.JobIDs.JobIDToName(36)) //Blue Mage ID { ImGui.TextColored(ImGuiColors.ParsedPink, $"Please note that even if you do not have all the required spells active, you may still use these features.\nAny spells you do not have active will be skipped over so if a feature is not working as intended then\nplease try and enable more required spells."); } diff --git a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs index 2f4cecc1c..8094e74b4 100644 --- a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs +++ b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs @@ -1,10 +1,13 @@ using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; +using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; +using System.Diagnostics; using System.Linq; using System.Numerics; +using System.Threading; using XIVSlothCombo.Core; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; @@ -18,7 +21,6 @@ internal class PvEFeatures : ConfigWindow internal static bool HasToOpenJob = true; internal static string OpenJob = string.Empty; - internal static new void Draw() { //#if !DEBUG @@ -182,7 +184,6 @@ internal static void DrawHeadingContents(string jobName, int i) else { presetBox.Draw(); - continue; } } diff --git a/XIVSlothCombo/Window/Tabs/Settings.cs b/XIVSlothCombo/Window/Tabs/Settings.cs index 71ae59937..bf3f92067 100644 --- a/XIVSlothCombo/Window/Tabs/Settings.cs +++ b/XIVSlothCombo/Window/Tabs/Settings.cs @@ -1,7 +1,9 @@ -using ImGuiNET; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; using System; using System.Numerics; using XIVSlothCombo.Attributes; +using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; namespace XIVSlothCombo.Window.Tabs @@ -11,143 +13,126 @@ internal class Settings : ConfigWindow internal static new void Draw() { PvEFeatures.HasToOpenJob = true; - ImGui.BeginChild("main", new Vector2(0, 0), true); - ImGui.Text("This tab allows you to customise your options when enabling features."); - - #region SubCombos - - bool hideChildren = Service.Configuration.HideChildren; - - if (ImGui.Checkbox("Hide SubCombo Options", ref hideChildren)) + using (var child = ImRaii.Child("main", new Vector2(0, 0), true)) { - Service.Configuration.HideChildren = hideChildren; - Service.Configuration.Save(); - } + ImGui.Text("This tab allows you to customise your options when enabling features."); - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.TextUnformatted("Hides the sub-options of disabled features."); - ImGui.EndTooltip(); - } - ImGui.NextColumn(); + #region SubCombos - #endregion + bool hideChildren = Service.Configuration.HideChildren; - #region Conflicting + if (ImGui.Checkbox("Hide SubCombo Options", ref hideChildren)) + { + Service.Configuration.HideChildren = hideChildren; + Service.Configuration.Save(); + } - bool hideConflicting = Service.Configuration.HideConflictedCombos; - if (ImGui.Checkbox("Hide Conflicted Combos", ref hideConflicting)) - { - Service.Configuration.HideConflictedCombos = hideConflicting; - Service.Configuration.Save(); - } + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted("Hides the sub-options of disabled features."); + ImGui.EndTooltip(); + } + ImGui.NextColumn(); - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.TextUnformatted("Hides any combos that conflict with others you have selected."); - ImGui.EndTooltip(); - } + #endregion - #endregion + #region Conflicting - #region Combat Log + bool hideConflicting = Service.Configuration.HideConflictedCombos; + if (ImGui.Checkbox("Hide Conflicted Combos", ref hideConflicting)) + { + Service.Configuration.HideConflictedCombos = hideConflicting; + Service.Configuration.Save(); + } - bool showCombatLog = Service.Configuration.EnabledOutputLog; + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted("Hides any combos that conflict with others you have selected."); + ImGui.EndTooltip(); + } - if (ImGui.Checkbox("Output Log to Chat", ref showCombatLog)) - { - Service.Configuration.EnabledOutputLog = showCombatLog; - Service.Configuration.Save(); - } + #endregion - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.TextUnformatted("Every time you use an action, the plugin will print it to the chat."); - ImGui.EndTooltip(); - } - #endregion + #region Combat Log - #region SpecialEvent + bool showCombatLog = Service.Configuration.EnabledOutputLog; - bool isSpecialEvent = DateTime.Now.Day == 1 && DateTime.Now.Month == 4; - bool slothIrl = isSpecialEvent && Service.Configuration.SpecialEvent; + if (ImGui.Checkbox("Output Log to Chat", ref showCombatLog)) + { + Service.Configuration.EnabledOutputLog = showCombatLog; + Service.Configuration.Save(); + } - if (isSpecialEvent) + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted("Every time you use an action, the plugin will print it to the chat."); + ImGui.EndTooltip(); + } + #endregion - { + #region Melee Offset + float offset = (float)Service.Configuration.MeleeOffset; + ImGui.PushItemWidth(75); - if (ImGui.Checkbox("Sloth Mode!?", ref slothIrl)) + bool inputChangedeth = false; + inputChangedeth |= ImGui.InputFloat("Melee Distance Offset", ref offset); + + if (inputChangedeth) { - Service.Configuration.SpecialEvent = slothIrl; + Service.Configuration.MeleeOffset = (double)offset; Service.Configuration.Save(); } - } - else - { - Service.Configuration.SpecialEvent = false; - Service.Configuration.Save(); - } + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted("Offset of melee check distance for features that use it.\r\nFor those who don't want to immediately use their ranged attack if the boss walks slightly out of range."); + ImGui.EndTooltip(); + } + #endregion - float offset = (float)Service.Configuration.MeleeOffset; - ImGui.PushItemWidth(75); + #region Message of the Day - bool inputChangedeth = false; - inputChangedeth |= ImGui.InputFloat("Melee Distance Offset", ref offset); + bool motd = Service.Configuration.HideMessageOfTheDay; - if (inputChangedeth) - { - Service.Configuration.MeleeOffset = (double)offset; - Service.Configuration.Save(); - } - - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.TextUnformatted("Offset of melee check distance for features that use it.\r\nFor those who don't want to immediately use their ranged attack if the boss walks slightly out of range."); - ImGui.EndTooltip(); - } - - #endregion + if (ImGui.Checkbox("Hide Message of the Day", ref motd)) + { + Service.Configuration.HideMessageOfTheDay = motd; + Service.Configuration.Save(); + } - #region Message of the Day + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted("Disables the Message of the Day message in your chat when you login."); + ImGui.EndTooltip(); + } + ImGui.NextColumn(); - bool motd = Service.Configuration.HideMessageOfTheDay; + #endregion - if (ImGui.Checkbox("Hide Message of the Day", ref motd)) - { - Service.Configuration.HideMessageOfTheDay = motd; - Service.Configuration.Save(); - } + #region TargetHelper - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.TextUnformatted("Disables the Message of the Day message in your chat when you login."); - ImGui.EndTooltip(); - } - ImGui.NextColumn(); + Vector4 colour = Service.Configuration.TargetHighlightColor; + if (ImGui.ColorEdit4("Target Highlight Colour", ref colour, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.AlphaPreview | ImGuiColorEditFlags.AlphaBar)) + { + Service.Configuration.TargetHighlightColor = colour; + Service.Configuration.Save(); + } - #endregion + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted($"Used for {CustomComboFunctions.JobIDs.JobIDToName(33)} card targeting features.\r\nSet Alpha to 0 to hide the box."); + ImGui.EndTooltip(); + } - Vector4 colour = Service.Configuration.TargetHighlightColor; - if (ImGui.ColorEdit4("Target Highlight Colour", ref colour, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.AlphaPreview | ImGuiColorEditFlags.AlphaBar)) - { - Service.Configuration.TargetHighlightColor = colour; - Service.Configuration.Save(); - } + #endregion - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.TextUnformatted($"Used for {CustomComboInfoAttribute.JobIDToName(33)} card targeting features.\r\nSet Alpha to 0 to hide the box."); - ImGui.EndTooltip(); } - - ImGui.EndChild(); } } } From b6253a979a5a2c6db0ffe3f4579bfe5d3d4ba2b5 Mon Sep 17 00:00:00 2001 From: Kage Date: Sun, 25 Aug 2024 14:31:00 +0200 Subject: [PATCH 016/208] fix originalhooks --- XIVSlothCombo/Combos/PvE/DRG.cs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG.cs index ea011ea0e..8eee8bcb7 100644 --- a/XIVSlothCombo/Combos/PvE/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG.cs @@ -186,26 +186,26 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Starcross) && AnimationLock.CanDRGWeave(Starcross) && HasEffect(Buffs.StarcrossReady)) - return OriginalHook(Stardiver); + return Starcross; //Rise of the Dragon Feature if (LevelChecked(RiseOfTheDragon) && AnimationLock.CanDRGWeave(RiseOfTheDragon) && HasEffect(Buffs.DragonsFlight)) - return OriginalHook(DragonfireDive); - - //Mirage Feature - if (LevelChecked(MirageDive) && - AnimationLock.CanDRGWeave(MirageDive) && - HasEffect(Buffs.DiveReady)) - return OriginalHook(HighJump); + return RiseOfTheDragon; //Nastrond Feature if (LevelChecked(Nastrond) && AnimationLock.CanDRGWeave(Nastrond) && HasEffect(Buffs.NastrondReady) && gauge.IsLOTDActive) - return OriginalHook(Geirskogul); + return Nastrond; + + //Mirage Feature + if (LevelChecked(MirageDive) && + AnimationLock.CanDRGWeave(MirageDive) && + HasEffect(Buffs.DiveReady)) + return MirageDive; } //1-2-3 Combo @@ -375,13 +375,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim LevelChecked(Starcross) && AnimationLock.CanDRGWeave(Starcross) && HasEffect(Buffs.StarcrossReady)) - return OriginalHook(Stardiver); + return Starcross; //Rise of the Dragon Feature if (IsEnabled(CustomComboPreset.DRG_ST_Dives_RiseOfTheDragon) && AnimationLock.CanDRGWeave(RiseOfTheDragon) && HasEffect(Buffs.DragonsFlight)) - return OriginalHook(DragonfireDive); + return RiseOfTheDragon; //Nastrond Feature if (IsEnabled(CustomComboPreset.DRG_ST_Nastrond) && @@ -389,14 +389,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim AnimationLock.CanDRGWeave(Nastrond) && HasEffect(Buffs.NastrondReady) && gauge.IsLOTDActive) - return OriginalHook(Geirskogul); + return Nastrond; //Mirage Feature if (IsEnabled(CustomComboPreset.DRG_ST_Mirage) && LevelChecked(MirageDive) && AnimationLock.CanDRGWeave(MirageDive) && HasEffect(Buffs.DiveReady)) - return OriginalHook(HighJump); + return MirageDive; } } From e98ef0ce57b60edefd5fa039fc89059320f3c718 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 25 Aug 2024 18:15:02 +0100 Subject: [PATCH 017/208] Fix low level MNK combo issues --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 7 +- XIVSlothCombo/Combos/PvE/MNK.cs | 117 ++++++++++++------------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index 93bbe544d..564013dd3 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -5,6 +5,7 @@ using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; +using XIVSlothCombo.Extensions; namespace XIVSlothCombo.Combos.JobHelpers { @@ -15,7 +16,7 @@ public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnable { if (CustomComboFunctions.HasEffect(Buffs.OpoOpoForm) || CustomComboFunctions.HasEffect(Buffs.FormlessFist)) { - if (Gauge.OpoOpoFury == 0) + if (Gauge.OpoOpoFury == 0 && DragonKick.LevelChecked()) { if (CustomComboFunctions.LevelChecked(DragonKick)) return DragonKick; @@ -28,7 +29,7 @@ public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnable if (CustomComboFunctions.HasEffect(Buffs.RaptorForm)) { - if (Gauge.RaptorFury == 0) + if (Gauge.RaptorFury == 0 && TwinSnakes.LevelChecked()) { if (CustomComboFunctions.LevelChecked(TwinSnakes)) return TwinSnakes; @@ -42,7 +43,7 @@ public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnable if (CustomComboFunctions.HasEffect(Buffs.CoeurlForm)) { - if (Gauge.CoeurlFury == 0) + if (Gauge.CoeurlFury == 0 && Demolish.LevelChecked()) { if (!CustomComboFunctions.OnTargetsRear() && CustomComboFunctions.TargetNeedsPositionals() diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index cba7252be..97fe1fcc3 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -111,7 +111,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // OGCDs - if (inCombat && canWeave) + if (canWeave) { if (IsEnabled(Variant.VariantRampart) && IsOffCooldown(Variant.VariantRampart)) @@ -157,80 +157,79 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // GCDs - if (inCombat) + + // Ensure usage if buff is almost depleted. + if (HasEffect(Buffs.FiresRumination) && GetBuffRemainingTime(Buffs.FiresRumination) < 4) { - // Ensure usage if buff is almost depleted. - if (HasEffect(Buffs.FiresRumination) && GetBuffRemainingTime(Buffs.FiresRumination) < 4) - { - return FiresReply; - } + return FiresReply; + } - if (HasEffect(Buffs.WindsRumination) && GetBuffRemainingTime(Buffs.WindsRumination) < 4) - { - return WindsReply; - } + if (HasEffect(Buffs.WindsRumination) && GetBuffRemainingTime(Buffs.WindsRumination) < 4) + { + return WindsReply; + } - if (HasEffect(Buffs.FormlessFist)) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + if (HasEffect(Buffs.FormlessFist)) + { + return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); + } - // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) - { - return OriginalHook(MasterfulBlitz); - } + // Masterful Blitz + if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) + { + return OriginalHook(MasterfulBlitz); + } - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) - { - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); - int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); - int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) + { + bool solarNadi = Gauge.Nadi == Nadi.SOLAR; + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); + int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); + int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); - #region Open Solar - if (!solarNadi && !bothNadisOpen) + #region Open Solar + if (!solarNadi && !bothNadisOpen) + { + if (coeurlChakra == 0) { - if (coeurlChakra == 0) - { - return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); - } - else if (raptorChakra == 0) - { - return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); - } - else if (opoOpoChakra == 0) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); } - #endregion - #region Open Lunar - if (solarNadi || lunarNadi || bothNadisOpen) + else if (raptorChakra == 0) + { + return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); + } + else if (opoOpoChakra == 0) { return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); } - #endregion } - - if (HasEffect(Buffs.WindsRumination)) + #endregion + #region Open Lunar + if (solarNadi || lunarNadi || bothNadisOpen) { - return WindsReply; + return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); } + #endregion + } - if (HasEffect(Buffs.FiresRumination) - && !HasEffect(Buffs.PerfectBalance) - && !HasEffect(Buffs.FormlessFist) - && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick))) - { - return FiresReply; - } + if (HasEffect(Buffs.WindsRumination)) + { + return WindsReply; + } - // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID); + if (HasEffect(Buffs.FiresRumination) + && !HasEffect(Buffs.PerfectBalance) + && !HasEffect(Buffs.FormlessFist) + && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick))) + { + return FiresReply; } + + // Standard Beast Chakras + return MNKHelper.DetermineCoreAbility(actionID); + } return actionID; @@ -468,7 +467,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // 3. During Brotherhood. // 4. During Riddle of Fire. // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if (HasCharges(PerfectBalance) && + if (HasCharges(PerfectBalance) && (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || (GetCooldownRemainingTime(PerfectBalance) <= 4) || (HasEffect(Buffs.Brotherhood)) || From 22aaaf742140a5313670441f77910ceeddffe0aa Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 25 Aug 2024 18:29:57 +0100 Subject: [PATCH 018/208] Menu peformance improvements --- XIVSlothCombo/Window/Functions/Presets.cs | 164 +++++++++++++--------- 1 file changed, 100 insertions(+), 64 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 2c00ddf18..4234e5e58 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -1,38 +1,77 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; +using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Reflection.Emit; using System.Text; using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos; using XIVSlothCombo.Core; using XIVSlothCombo.Data; -using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; namespace XIVSlothCombo.Window.Functions { internal class Presets : ConfigWindow { + internal static Dictionary Attributes = new(); + internal class PresetAttributes + { + public bool IsPvP; + public CustomComboPreset[] Conflicts; + public CustomComboPreset? Parent; + public BlueInactiveAttribute? BlueInactive; + public VariantParentAttribute? VariantParent; + public BozjaParentAttribute? BozjaParent; + public EurekaParentAttribute? EurekaParent; + public HoverInfoAttribute? HoverInfo; + public ReplaceSkillAttribute? ReplaceSkill; + public CustomComboInfoAttribute? CustomComboInfo; + + public PresetAttributes(CustomComboPreset preset) + { + IsPvP = PresetStorage.IsPvP(preset); + Conflicts = PresetStorage.GetConflicts(preset); + Parent = PresetStorage.GetParent(preset); + BlueInactive = preset.GetAttribute(); + VariantParent = preset.GetAttribute(); + BozjaParent = preset.GetAttribute(); + EurekaParent = preset.GetAttribute(); + HoverInfo = preset.GetAttribute(); + ReplaceSkill = preset.GetAttribute(); + CustomComboInfo = preset.GetAttribute(); + } + } + internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfoAttribute info, ref int i) { + if (!Attributes.ContainsKey(preset)) + { + PresetAttributes attributes = new(preset); + Attributes[preset] = attributes; + } var enabled = PresetStorage.IsEnabled(preset); - var secret = PresetStorage.IsPvP(preset); - var conflicts = PresetStorage.GetConflicts(preset); - var parent = PresetStorage.GetParent(preset); - var blueAttr = preset.GetAttribute(); + var secret = Attributes[preset].IsPvP; + var conflicts = Attributes[preset].Conflicts; + var parent = Attributes[preset].Parent; + var blueAttr = Attributes[preset].BlueInactive; + var variantParents = Attributes[preset].VariantParent; + var bozjaParents = Attributes[preset].BozjaParent; + var eurekaParents = Attributes[preset].EurekaParent; ImGui.Spacing(); - if (ImGui.Checkbox($"{info.FancyName}###{info.FancyName}{i}", ref enabled)) + if (ImGui.Checkbox($"{info.FancyName}###{i}", ref enabled)) { if (enabled) { - EnableParentPresets(preset); Service.Configuration.EnabledActions.Add(preset); foreach (var conflict in conflicts) @@ -40,7 +79,6 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo Service.Configuration.EnabledActions.Remove(conflict); } } - else { Service.Configuration.EnabledActions.Remove(preset); @@ -49,34 +87,33 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo Service.Configuration.Save(); } - ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey); - DrawReplaceAttribute(preset); Vector2 length = new(); - - if (i != -1) + using (var styleCol = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey)) { - ImGui.Text($"#{i}: "); - length = ImGui.CalcTextSize($"#{i}: "); - ImGui.SameLine(); - ImGui.PushItemWidth(length.Length()); - } + if (i != -1) + { + ImGui.Text($"#{i}: "); + length = ImGui.CalcTextSize($"#{i}: "); + ImGui.SameLine(); + ImGui.PushItemWidth(length.Length()); + } - ImGui.TextWrapped($"{info.Description}"); + ImGui.TextWrapped($"{info.Description}"); - if (preset.GetHoverAttribute() != null) - { - if (ImGui.IsItemHovered()) + if (Attributes[preset].HoverInfo != null) { - ImGui.BeginTooltip(); - ImGui.TextUnformatted(preset.GetHoverAttribute().HoverText); - ImGui.EndTooltip(); + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + ImGui.TextUnformatted(Attributes[preset].HoverInfo.HoverText); + ImGui.EndTooltip(); + } } } - ImGui.PopStyleColor(); ImGui.Spacing(); if (conflicts.Length > 0) @@ -86,15 +123,18 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.Indent(); foreach (var conflict in conflicts) { - var comboInfo = conflict.GetAttribute(); + var comboInfo = Attributes.ContainsKey(conflict) ? Attributes[conflict].CustomComboInfo : conflict.GetAttribute(); conflictBuilder.Insert(0, $"{comboInfo.FancyName}"); var par2 = conflict; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - conflictBuilder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + conflictBuilder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo : subpar?.GetAttribute().FancyName)} -> "); + par2 = subpar!.Value; + } } @@ -125,21 +165,23 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo } } - VariantParentAttribute? varientparents = preset.GetAttribute(); - if (varientparents is not null) + if (variantParents is not null) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen); - ImGui.TextWrapped($"Part of normal combo{(varientparents.ParentPresets.Length > 1 ? "s" : "")}:"); + ImGui.TextWrapped($"Part of normal combo{(variantParents.ParentPresets.Length > 1 ? "s" : "")}:"); StringBuilder builder = new(); - foreach (var par in varientparents.ParentPresets) + foreach (var par in variantParents.ParentPresets) { - builder.Insert(0, $"{par.GetAttribute().FancyName}"); + builder.Insert(0, $"{(Attributes.ContainsKey(par) ? Attributes[par].CustomComboInfo.FancyName : par.GetAttribute().FancyName)}"); var par2 = par; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - builder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + builder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.FancyName : subpar?.GetAttribute().FancyName)} -> "); + par2 = subpar!.Value; + } } @@ -149,21 +191,23 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.PopStyleColor(); } - BozjaParentAttribute? bozjaparents = preset.GetAttribute(); - if (bozjaparents is not null) + if (bozjaParents is not null) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen); - ImGui.TextWrapped($"Part of normal combo{(varientparents.ParentPresets.Length > 1 ? "s" : "")}:"); + ImGui.TextWrapped($"Part of normal combo{(variantParents.ParentPresets.Length > 1 ? "s" : "")}:"); StringBuilder builder = new(); - foreach (var par in bozjaparents.ParentPresets) + foreach (var par in bozjaParents.ParentPresets) { - builder.Insert(0, $"{par.GetAttribute().FancyName}"); + builder.Insert(0, $"{(Attributes.ContainsKey(par) ? Attributes[par].CustomComboInfo.FancyName : par.GetAttribute().FancyName)}"); var par2 = par; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - builder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + builder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.FancyName : subpar?.GetAttribute().FancyName)} -> "); + par2 = subpar!.Value; + } } @@ -173,21 +217,23 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.PopStyleColor(); } - EurekaParentAttribute? eurekaparents = preset.GetAttribute(); - if (eurekaparents is not null) + if (eurekaParents is not null) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen); - ImGui.TextWrapped($"Part of normal combo{(varientparents.ParentPresets.Length > 1 ? "s" : "")}:"); + ImGui.TextWrapped($"Part of normal combo{(variantParents.ParentPresets.Length > 1 ? "s" : "")}:"); StringBuilder builder = new(); - foreach (var par in eurekaparents.ParentPresets) + foreach (var par in eurekaParents.ParentPresets) { - builder.Insert(0, $"{par.GetAttribute().FancyName}"); + builder.Insert(0, $"{(Attributes.ContainsKey(par) ? Attributes[par].CustomComboInfo.FancyName : par.GetAttribute().FancyName)}"); var par2 = par; while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - builder.Insert(0, $"{subpar?.GetAttribute().FancyName} -> "); - par2 = subpar!.Value; + if (subpar != null) + { + builder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.FancyName : subpar?.GetAttribute().FancyName)} -> "); + par2 = subpar!.Value; + } } @@ -199,23 +245,13 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo UserConfigItems.Draw(preset, enabled); - if (preset == CustomComboPreset.NIN_ST_SimpleMode_BalanceOpener || preset == CustomComboPreset.NIN_ST_AdvancedMode_BalanceOpener) - { - ImGui.SetCursorPosX(ImGui.GetCursorPosX() + length.Length()); - if (ImGui.Button($"Image of rotation###ninrtn{i}")) - { - Util.OpenLink("https://i.imgur.com/IeP27KF.png"); - } - } - i++; - var hideChildren = Service.Configuration.HideChildren; - var children = presetChildren[preset]; + var children = presetChildren.ContainsKey(preset) ? presetChildren[preset] : null; - if (children.Length > 0) + if (children != null) { - if (enabled || !hideChildren) + if (enabled || !Service.Configuration.HideChildren) { ImGui.Indent(); @@ -244,10 +280,10 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo continue; } } - else { DrawPreset(childPreset, childInfo, ref i); + continue; } } @@ -263,7 +299,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo private static void DrawReplaceAttribute(CustomComboPreset preset) { - var att = preset.GetReplaceAttribute(); + var att = Attributes[preset].ReplaceSkill; if (att != null) { string skills = string.Join(", ", att.ActionNames); From 480a72efda6a7db8af5938a3956213c04a1e734c Mon Sep 17 00:00:00 2001 From: Katie Date: Sun, 25 Aug 2024 13:37:32 -0400 Subject: [PATCH 019/208] Add AoE Holy in White feature --- XIVSlothCombo/Combos/CustomComboPreset.cs | 28 +++++++++++--------- XIVSlothCombo/Combos/PvE/PCT.cs | 10 +++++++ XIVSlothCombo/Window/Functions/UserConfig.cs | 6 +++++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..53e086d6f 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2486,7 +2486,7 @@ public enum CustomComboPreset PCT_AoE_AdvancedMode = 20040, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Prepull Motifs Feature", "Adds missing Motifs to the combo while out of combat.", PCT.JobID)] + [CustomComboInfo("Prepull Motifs Feature", "Adds missing Motifs to the combo while out of combat.", PCT.JobID, 1)] PCT_AoE_AdvancedMode_PrePullMotifs = 20041, [ParentCombo(PCT_AoE_AdvancedMode_PrePullMotifs)] @@ -2494,7 +2494,7 @@ public enum CustomComboPreset PCT_AoE_AdvancedMode_NoTargetMotifs = 20042, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Starry Muse Burst Feature", $"Adds selected spells below to the burst phase.", PCT.JobID)] + [CustomComboInfo("Starry Muse Burst Feature", $"Adds selected spells below to the burst phase.", PCT.JobID, 2)] PCT_AoE_AdvancedMode_Burst_Phase = 20043, [ParentCombo(PCT_AoE_AdvancedMode_Burst_Phase)] @@ -2518,7 +2518,7 @@ public enum CustomComboPreset PCT_AoE_AdvancedMode_Burst_BlizzardInCyan = 20048, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Motif Selection Feature", $"Add Selected Motifs to the combo.", PCT.JobID)] + [CustomComboInfo("Motif Selection Feature", $"Add Selected Motifs to the combo.", PCT.JobID, 3)] PCT_AoE_AdvancedMode_MotifFeature = 20049, [ParentCombo(PCT_AoE_AdvancedMode_MotifFeature)] @@ -2534,7 +2534,7 @@ public enum CustomComboPreset PCT_AoE_AdvancedMode_WeaponMotif = 20052, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Muse Selection Feature", $"Adds Selected Muses to the combo.", PCT.JobID)] + [CustomComboInfo("Muse Selection Feature", $"Adds Selected Muses to the combo.", PCT.JobID, 4)] PCT_AoE_AdvancedMode_MuseFeature = 20053, [ParentCombo(PCT_AoE_AdvancedMode_MuseFeature)] @@ -2550,23 +2550,27 @@ public enum CustomComboPreset PCT_AoE_AdvancedMode_SteelMuse = 20056, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Mog/Madeen Feature", $"Adds Mog/Madeen to the combo.", PCT.JobID)] + [CustomComboInfo("Mog/Madeen Feature", $"Adds Mog/Madeen to the combo.", PCT.JobID, 5)] PCT_AoE_AdvancedMode_MogOfTheAges = 20057, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Subtractive Palette Feature", $"Adds Subtractive Palette to the combo.", PCT.JobID)] + [CustomComboInfo("Subtractive Palette Feature", $"Adds Subtractive Palette to the combo.", PCT.JobID, 6)] PCT_AoE_AdvancedMode_SubtractivePalette = 20058, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Comet in Black Option", $"Adds Comet in Black to the combo.", PCT.JobID)] + [CustomComboInfo("Comet in Black Option", $"Adds Comet in Black to the combo.", PCT.JobID, 7)] PCT_AoE_AdvancedMode_CometinBlack = 20059, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Hammer Stamp Combo Option", $"Adds Hammer Stamp combo.", PCT.JobID)] + [CustomComboInfo("Hammer Stamp Combo Option", $"Adds Hammer Stamp combo.", PCT.JobID, 8)] PCT_AoE_AdvancedMode_HammerStampCombo = 20060, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Movement Features", $"Adds selected features to the combo while moving.", PCT.JobID)] + [CustomComboInfo("Holy in White Option", $"Adds Holy in White to the combo.", PCT.JobID, 9)] + PCT_AoE_AdvancedMode_HolyinWhite = 20068, + + [ParentCombo(PCT_AoE_AdvancedMode)] + [CustomComboInfo("Movement Features", $"Adds selected features to the combo while moving.", PCT.JobID, 10)] PCT_AoE_AdvancedMode_MovementFeature = 20061, [ParentCombo(PCT_AoE_AdvancedMode_MovementFeature)] @@ -2586,11 +2590,11 @@ public enum CustomComboPreset PCT_AoE_AdvancedMode_SwitfcastOption = 20065, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Blizzard in Cyan Option", $"Adds Blizzard in Cyan to the combo.", PCT.JobID)] + [CustomComboInfo("Blizzard in Cyan Option", $"Adds Blizzard in Cyan to the combo.", PCT.JobID, 11)] PCT_AoE_AdvancedMode_BlizzardInCyan = 20066, [ParentCombo(PCT_AoE_AdvancedMode)] - [CustomComboInfo("Lucid Dreaming Option", $"Adds Lucid Dreaming to the combo.", PCT.JobID)] + [CustomComboInfo("Lucid Dreaming Option", $"Adds Lucid Dreaming to the combo.", PCT.JobID, 12)] PCT_AoE_AdvancedMode_LucidDreaming = 20067, [ReplaceSkill(PCT.FireInRed, PCT.FireIIinRed)] @@ -2607,7 +2611,7 @@ public enum CustomComboPreset CombinedPaint = 20004, - // Last value for AoE = 20067 + // Last value for AoE = 20068 #endregion #endregion diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index df12da91e..26385815e 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -23,6 +23,7 @@ public const uint AeroInGreen = 34651, WaterInBlue = 34652, FireIIinRed = 34656, + AeroIIinGreen = 34657, HammerMotif = 34668, WingedMuse = 34671, StrikingMuse = 34674, @@ -45,6 +46,7 @@ public const uint StarPrism = 34681, SteelMuse = 35348, SubtractivePalette = 34683, + StoneIIinYellow = 34660, ThunderIIinMagenta = 34661, ThunderinMagenta = 34655, WaterinBlue = 34652, @@ -75,6 +77,7 @@ public static class Config public static UserInt CombinedAetherhueChoices = new("CombinedAetherhueChoices"), PCT_ST_AdvancedMode_LucidOption = new("PCT_ST_AdvancedMode_LucidOption", 6500), + PCT_AoE_AdvancedMode_HolyinWhiteOption = new("PCT_AoE_AdvancedMode_HolyinWhiteOption", 0), PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500); public static UserBool @@ -721,6 +724,13 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } } + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_HolyinWhite) && !HasEffect(Buffs.StarryMuse) && !HasEffect(Buffs.MonochromeTones)) + { + if (gauge.Paint > Config.PCT_AoE_AdvancedMode_HolyinWhiteOption || + (Config.PCT_AoE_AdvancedMode_HolyinWhiteOption == 5 && gauge.Paint == 5 && !HasEffect(Buffs.HammerTime) && + (HasEffect(Buffs.RainbowBright) || WasLastSpell(AeroIIinGreen) || WasLastSpell(StoneIIinYellow)))) + return OriginalHook(HolyInWhite); + } if (HasEffect(Buffs.RainbowBright) && !HasEffect(Buffs.StarryMuse)) return RainbowDrip; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index bba1a908d..6bf69eddb 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1676,6 +1676,12 @@ internal static void Draw(CustomComboPreset preset, bool enabled) { UserConfig.DrawSliderInt(0, 10000, PCT.Config.PCT_ST_AdvancedMode_LucidOption, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); } + + if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_HolyinWhite) + { + UserConfig.DrawSliderInt(0, 5, PCT.Config.PCT_AoE_AdvancedMode_HolyinWhiteOption, "How many charges to keep ready? (0 = Use all)"); + } + if(preset == CustomComboPreset.PCT_AoE_AdvancedMode_LucidDreaming) { UserConfig.DrawSliderInt(0, 10000, PCT.Config.PCT_AoE_AdvancedMode_LucidOption, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); From 1f9fedd3d65a1050f352da2d58b7d6514109bfb9 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 25 Aug 2024 18:52:10 +0100 Subject: [PATCH 020/208] Fix SCH lucid sliders --- XIVSlothCombo/Window/Functions/UserConfig.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index d88cb9421..956d6bd4e 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2237,6 +2237,9 @@ internal static void Draw(CustomComboPreset preset, bool enabled) UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); if (preset is CustomComboPreset.SCH_AoE_Lucid) + UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_AoE_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); + + if (preset is CustomComboPreset.SCH_AoE_Heal_Lucid) UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_AoE_Heal_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); if (preset is CustomComboPreset.SCH_DeploymentTactics) From f2c40f5d57b907b3633da246febf9737935893f3 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 25 Aug 2024 18:55:54 +0100 Subject: [PATCH 021/208] [PUSH] v3.2.0.8 --- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index dcdd84427..b567653b4 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Sloth - - 3.2.0.7 + 3.2.0.8 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From bf9280824a2388ebf4d6b20c3c2d912caf5ebc81 Mon Sep 17 00:00:00 2001 From: Katie Date: Sun, 25 Aug 2024 14:20:39 -0400 Subject: [PATCH 022/208] Remove action range checks from Reawaken and Vicepit sequence in AoE combo --- XIVSlothCombo/Combos/PvE/VPR.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 19f984de5..c1c6bfe94 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -624,10 +624,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!HasEffect(Buffs.Reawakened)) { //Vicepit weaves - if (HasEffect(Buffs.FellhuntersVenom) && InMeleeRange()) + if (HasEffect(Buffs.FellhuntersVenom)) return OriginalHook(Twinfang); - if (HasEffect(Buffs.FellskinsVenom) && InMeleeRange()) + if (HasEffect(Buffs.FellskinsVenom)) return OriginalHook(Twinblood); //Serpents Ire usage @@ -637,7 +637,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Vicepit combo - if (!HasEffect(Buffs.Reawakened) && InMeleeRange()) + if (!HasEffect(Buffs.Reawakened)) { if (SwiftskinsDenReady) return HuntersDen; @@ -649,7 +649,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Reawakend Usage if ((HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && + !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) return Reawaken; @@ -661,7 +661,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit Usage if (ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && InMeleeRange()) + ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre))) return Vicepit; // Uncoiled Fury usage @@ -802,8 +802,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Reawakened)) { //Vicepit weaves - if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - InMeleeRange()) + if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo)) { if (HasEffect(Buffs.FellhuntersVenom)) return OriginalHook(Twinfang); @@ -822,7 +821,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit combo if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - !HasEffect(Buffs.Reawakened) && InMeleeRange()) + !HasEffect(Buffs.Reawakened)) { if (SwiftskinsDenReady) return HuntersDen; @@ -835,7 +834,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.VPR_AoE_Reawaken) && (HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && + !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) return Reawaken; @@ -849,7 +848,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit Usage if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && IsEnabled(CustomComboPreset.VPR_AoE_Vicepit) && - ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && + ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre))) return Vicepit; From acfb09b471ed583ed3079f5db4c35cc355ec2284 Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 26 Aug 2024 00:49:39 +0200 Subject: [PATCH 023/208] update weave windows update originalhooks update queen usage --- XIVSlothCombo/Combos/JobHelpers/MCH.cs | 58 +++-- XIVSlothCombo/Combos/PvE/MCH.cs | 310 +++++++++++++------------ 2 files changed, 200 insertions(+), 168 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MCH.cs b/XIVSlothCombo/Combos/JobHelpers/MCH.cs index 9304ba7a3..a8edc857b 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MCH.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MCH.cs @@ -277,28 +277,46 @@ public static bool UseQueen(MCHGauge gauge) { int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - if (!ActionWatching.HasDoubleWeaved() && CanWeave(OriginalHook(SplitShot)) && - !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && !JustUsed(OriginalHook(Heatblast)) && - LevelChecked(OriginalHook(RookAutoturret)) && !gauge.IsRobotActive && gauge.Battery >= 50 && - ((LevelChecked(FullMetalField) && !JustUsed(FullMetalField)) || !LevelChecked(FullMetalField))) + if (!ActionWatching.HasDoubleWeaved() && !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && + !JustUsed(OriginalHook(Heatblast)) && LevelChecked(OriginalHook(RookAutoturret)) && + !gauge.IsRobotActive && gauge.Battery >= 50) { - //1min - if (BSUsed == 1 & gauge.Battery >= 90) - return true; - - //even mins - if (BSUsed >= 2 && gauge.Battery >= 100) - return true; - - //odd mins 1st queen - if (BSUsed >= 2 && gauge.Battery >= 50 && - GetCooldownRemainingTime(BarrelStabilizer) is >= 30 and <= 65) - return true; + if (LevelChecked(FullMetalField)) + { + //1min + if (BSUsed == 1 & gauge.Battery >= 90) + return true; + + //even mins + if (BSUsed >= 2 && gauge.Battery == 100 && JustUsed(AirAnchor)) + return true; + + //odd mins 1st queen + if (BSUsed >= 2 && gauge.Battery == 50 && + gauge.LastSummonBatteryPower == 100) + return true; + + //odd mins 2nd queen + if ((BSUsed is 2 or 5 or 8) && gauge.Battery >= 60 && + gauge.LastSummonBatteryPower == 50) + return true; + + //odd mins 2nd queen + if ((BSUsed is 3 or 6 or 9) && gauge.Battery >= 70 && + gauge.LastSummonBatteryPower == 50) + return true; + + //odd mins 2nd queen + if ((BSUsed is 4 or 7 or 10) && gauge.Battery >= 80 && + gauge.LastSummonBatteryPower == 50) + return true; + } - //odd mins 2nd queen - if (BSUsed >= 2 && gauge.Battery >= 60 && - GetCooldownRemainingTime(BarrelStabilizer) is >= 10 and <= 30) - return true; + if (!LevelChecked(FullMetalField)) + { + if (gauge.Battery == 100) + return true; + } if (!LevelChecked(BarrelStabilizer)) return true; diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index cc29a8ddd..810e798c4 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; +using System.Linq; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; @@ -108,12 +109,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool anchorCD = !LevelChecked(AirAnchor) || (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); bool sawCD = !LevelChecked(Chainsaw) || (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; + int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); if (actionID is SplitShot or HeatedSplitShot) { if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MCH_VariantCure) + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MCH_VariantCure) return Variant.VariantCure; if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && @@ -130,26 +132,65 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (interruptReady) return All.HeadGraze; - // Wildfire - if (JustUsed(Hypercharge) && CanWeave(actionID) && ActionReady(Wildfire)) - return Wildfire; - - // BarrelStabilizer - if (!gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; - - if (CanWeave(actionID) && (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && - LevelChecked(Hypercharge) && !gauge.IsOverheated && !MCHExtensions.IsComboExpiring(6)) + //All weaves + if (CanWeave(ActionWatching.LastWeaponskill) && + !ActionWatching.HasDoubleWeaved()) { - //Protection & ensures Hyper charged is double weaved with WF during reopener - if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || - ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || - !LevelChecked(Wildfire)) - return Hypercharge; - - if (drillCD && anchorCD && sawCD && - ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) - return Hypercharge; + // Wildfire + if (JustUsed(Hypercharge) && ActionReady(Wildfire)) + return Wildfire; + + // BarrelStabilizer + if (!gauge.IsOverheated && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; + + if ((gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + LevelChecked(Hypercharge) && !gauge.IsOverheated) + { + //Protection & ensures Hyper charged is double weaved with WF during reopener + if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || + ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || + !LevelChecked(Wildfire)) + return Hypercharge; + + if (drillCD && anchorCD && sawCD && + ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) + return Hypercharge; + } + + //Queen + if (MCHExtensions.UseQueen(gauge) && + GetCooldownRemainingTime(Wildfire) > GCD) + return OriginalHook(RookAutoturret); + + //Heatblast, Gauss, Rico + if (JustUsed(OriginalHook(Heatblast)) && + (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } + + //gauss and ricochet outside HC + if (!gauge.IsOverheated && + (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || + JustUsed(Drill) || JustUsed(Excavator))) + { + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); + } + + // healing + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + return All.SecondWind; } //Full Metal Field @@ -157,48 +198,22 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && LevelChecked(FullMetalField)) - return OriginalHook(BarrelStabilizer); - - //Heatblast, Gauss, Rico - if (CanWeave(actionID) && JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } + return FullMetalField; if (gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); - //Queen - if (MCHExtensions.UseQueen(gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) - return OriginalHook(RookAutoturret); - - //gauss and ricochet outside HC - if (CanWeave(actionID) && !gauge.IsOverheated && - (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || - JustUsed(Drill) || JustUsed(Excavator)) && - !ActionWatching.HasDoubleWeaved()) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } - if (ReassembledTools(ref actionID, gauge) && !gauge.IsOverheated) return actionID; - // healing - if (CanWeave(actionID) && PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) - return All.SecondWind; + if (LevelChecked(Excavator) && + HasEffect(Buffs.ExcavatorReady) && + ((BSUsed is 1) || + ((BSUsed is 2 or 5 or 8) && gauge.Battery <= 40) || + ((BSUsed is 3 or 6 or 9) && gauge.Battery <= 50) || + ((BSUsed is 4 or 7 or 10) && gauge.Battery <= 60) || + (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) + return OriginalHook(Chainsaw); //1-2-3 Combo if (comboTime > 0) @@ -225,7 +240,7 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) // TOOLS!! Chainsaw Drill Air Anchor Excavator if (!gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(actionID) || !InCombat()) & - ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery) || + ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive) || (LevelChecked(Chainsaw) && !LevelChecked(Excavator) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || (LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || (LevelChecked(Drill) && !LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) @@ -234,14 +249,6 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) return true; } - if (LevelChecked(OriginalHook(Chainsaw)) && - !battery && - HasEffect(Buffs.ExcavatorReady)) - { - actionID = OriginalHook(Chainsaw); - return true; - } - if (LevelChecked(Chainsaw) && !battery && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw))) @@ -284,6 +291,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool anchorCD = !LevelChecked(AirAnchor) || (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); bool sawCD = !LevelChecked(Chainsaw) || (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; + bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[0] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); + int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); if (actionID is SplitShot or HeatedSplitShot) { @@ -309,35 +318,78 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Interrupt) && interruptReady) return All.HeadGraze; - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_QueenOverdrive) && - gauge.IsRobotActive && GetTargetHPPercent() <= Config.MCH_ST_QueenOverDrive && - CanWeave(actionID) && ActionReady(OriginalHook(RookOverdrive))) - return OriginalHook(RookOverdrive); - - // Wildfire - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_WildFire) && - JustUsed(Hypercharge) && CanWeave(actionID) && ActionReady(Wildfire) && - GetTargetHPPercent() >= Config.MCH_ST_WildfireHP) - return Wildfire; - - // BarrelStabilizer - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer) && - !gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; - - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && - CanWeave(actionID) && (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && - LevelChecked(Hypercharge) && !gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) + //All weaves + if (CanWeave(ActionWatching.LastWeaponskill) && + !ActionWatching.HasDoubleWeaved()) { - //Protection & ensures Hyper charged is double weaved with WF during reopener - if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || - ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || - !LevelChecked(Wildfire)) - return Hypercharge; - - if (drillCD && anchorCD && sawCD && - ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) - return Hypercharge; + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_QueenOverdrive) && + gauge.IsRobotActive && GetTargetHPPercent() <= Config.MCH_ST_QueenOverDrive && + ActionReady(OriginalHook(RookOverdrive))) + return OriginalHook(RookOverdrive); + + // Wildfire + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_WildFire) && + JustUsed(Hypercharge) && ActionReady(Wildfire) && + GetTargetHPPercent() >= Config.MCH_ST_WildfireHP) + return Wildfire; + + // BarrelStabilizer + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer) && + !gauge.IsOverheated && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; + + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && + (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + LevelChecked(Hypercharge) && !gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) + { + //Protection & ensures Hyper charged is double weaved with WF during reopener + if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || + ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || + !LevelChecked(Wildfire)) + return Hypercharge; + + if (drillCD && anchorCD && sawCD && + ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) + return Hypercharge; + } + + //Queen + if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && + MCHExtensions.UseQueen(gauge) && + GetCooldownRemainingTime(Wildfire) > GCD) + return OriginalHook(RookAutoturret); + + //Heatblast, Gauss, Rico + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && + JustUsed(OriginalHook(Heatblast)) && + (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } + + //gauss and ricochet outside HC + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && + !gauge.IsOverheated && + (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || + JustUsed(Drill) || JustUsed(Excavator))) + { + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); + } + + // healing + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && + PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind)) + return All.SecondWind; } //Full Metal Field @@ -346,53 +398,25 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && LevelChecked(FullMetalField)) - return OriginalHook(BarrelStabilizer); - - //Heatblast, Gauss, Rico - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && - CanWeave(actionID) && JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } + return FullMetalField; if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Heatblast) && gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); - //Queen - if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && - MCHExtensions.UseQueen(gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) - return OriginalHook(RookAutoturret); - - //gauss and ricochet outside HC - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && - CanWeave(actionID) && !gauge.IsOverheated && - (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || - JustUsed(Drill) || JustUsed(Excavator)) && - !ActionWatching.HasDoubleWeaved()) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } - if (ReassembledTools(ref actionID, gauge) && !gauge.IsOverheated) return actionID; - // healing - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && - CanWeave(actionID) && PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind)) - return All.SecondWind; + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && + reassembledExcavator && + LevelChecked(Excavator) && + HasEffect(Buffs.ExcavatorReady) && + ((BSUsed is 1) || + ((BSUsed is 2 or 5 or 8) && gauge.Battery <= 40) || + ((BSUsed is 3 or 6 or 9) && gauge.Battery <= 50) || + ((BSUsed is 4 or 7 or 10) && gauge.Battery <= 60) || + (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) + return OriginalHook(Chainsaw); //1-2-3 Combo if (comboTime > 0) @@ -415,7 +439,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) { bool battery = Svc.Gauges.Get().Battery >= 100; - bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[0] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledChainsaw = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[1] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[1] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledAnchor = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[2] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[2] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledDrill = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[3] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[3] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); @@ -423,9 +446,9 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) // TOOLS!! Chainsaw Drill Air Anchor Excavator if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && - !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(actionID) || !InCombat()) && + !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) && GetRemainingCharges(Reassemble) > Config.MCH_ST_ReassemblePool && - ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery) || + ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive) || (Config.MCH_ST_Reassembled[1] && LevelChecked(Chainsaw) && (!LevelChecked(Excavator) || !Config.MCH_ST_Reassembled[0]) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || (Config.MCH_ST_Reassembled[2] && LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || (Config.MCH_ST_Reassembled[3] && LevelChecked(Drill) && (!LevelChecked(AirAnchor) || !Config.MCH_ST_Reassembled[2]) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) @@ -434,16 +457,6 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) return true; } - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && - reassembledExcavator && - LevelChecked(OriginalHook(Chainsaw)) && - !battery && - HasEffect(Buffs.ExcavatorReady)) - { - actionID = OriginalHook(Chainsaw); - return true; - } - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Chainsaw) && reassembledChainsaw && LevelChecked(Chainsaw) && @@ -467,7 +480,8 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Drill) && reassembledDrill && LevelChecked(Drill) && - !JustUsed(Drill) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill)) && + !JustUsed(Drill) && + ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill)) && GetCooldownRemainingTime(Wildfire) is >= 20 or <= 10) { actionID = Drill; @@ -505,7 +519,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Full Metal Field if (HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) - return OriginalHook(BarrelStabilizer); + return FullMetalField; // BarrelStabilizer if (!gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) @@ -595,7 +609,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Full Metal Field if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer_FullMetalField) && HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) - return OriginalHook(BarrelStabilizer); + return FullMetalField; // BarrelStabilizer if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer) && From 507333a7fa0ebbfc12a73bda69e73f4fb91c521e Mon Sep 17 00:00:00 2001 From: edewen Date: Mon, 26 Aug 2024 07:42:01 -0400 Subject: [PATCH 024/208] Added Holy in white to simple aoe per balance. Will retain one charge --- XIVSlothCombo/Combos/PvE/PCT.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index c2d196b69..ed3d6485b 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -778,6 +778,9 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !gauge.WeaponMotifDrawn && (HasCharges(SteelMuse) || GetCooldownChargeRemainingTime(SteelMuse) <= 8)) return OriginalHook(WeaponMotif); } + //Saves one Charge of White paint for movement/Black paint. + if (HolyInWhite.LevelChecked() && gauge.Paint >= 2) + return OriginalHook(HolyInWhite); if (All.LucidDreaming.LevelChecked() && ActionReady(All.LucidDreaming) && CanSpellWeave(actionID) && LocalPlayer.CurrentMp <= 6500) return All.LucidDreaming; From 4d3cb7333197dff8cd8e46a536324ec897c0f71b Mon Sep 17 00:00:00 2001 From: Katie Date: Mon, 26 Aug 2024 17:25:55 -0400 Subject: [PATCH 025/208] Revert "Remove action range checks from Reawaken and Vicepit sequence in AoE combo" This reverts commit bf9280824a2388ebf4d6b20c3c2d912caf5ebc81. --- XIVSlothCombo/Combos/PvE/VPR.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index c1c6bfe94..19f984de5 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -624,10 +624,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!HasEffect(Buffs.Reawakened)) { //Vicepit weaves - if (HasEffect(Buffs.FellhuntersVenom)) + if (HasEffect(Buffs.FellhuntersVenom) && InMeleeRange()) return OriginalHook(Twinfang); - if (HasEffect(Buffs.FellskinsVenom)) + if (HasEffect(Buffs.FellskinsVenom) && InMeleeRange()) return OriginalHook(Twinblood); //Serpents Ire usage @@ -637,7 +637,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Vicepit combo - if (!HasEffect(Buffs.Reawakened)) + if (!HasEffect(Buffs.Reawakened) && InMeleeRange()) { if (SwiftskinsDenReady) return HuntersDen; @@ -649,7 +649,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Reawakend Usage if ((HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && + !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) return Reawaken; @@ -661,7 +661,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit Usage if (ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre))) + ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && InMeleeRange()) return Vicepit; // Uncoiled Fury usage @@ -802,7 +802,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Reawakened)) { //Vicepit weaves - if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo)) + if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && + InMeleeRange()) { if (HasEffect(Buffs.FellhuntersVenom)) return OriginalHook(Twinfang); @@ -821,7 +822,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit combo if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - !HasEffect(Buffs.Reawakened)) + !HasEffect(Buffs.Reawakened) && InMeleeRange()) { if (SwiftskinsDenReady) return HuntersDen; @@ -834,7 +835,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.VPR_AoE_Reawaken) && (HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && + !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) return Reawaken; @@ -848,7 +849,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit Usage if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && IsEnabled(CustomComboPreset.VPR_AoE_Vicepit) && - ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && + ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre))) return Vicepit; From 6d3fc781076eda2c5c94e88a49cdf9c72681e875 Mon Sep 17 00:00:00 2001 From: Katie Date: Mon, 26 Aug 2024 18:05:50 -0400 Subject: [PATCH 026/208] Add option to disable range checks for Vicepit + combo and Reawaken in AoE --- XIVSlothCombo/Combos/CustomComboPreset.cs | 12 ++++++++++++ XIVSlothCombo/Combos/PvE/VPR.cs | 23 ++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..a8462a949 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4147,10 +4147,18 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Vicepit", "Adds Vicepit to the rotation.", VPR.JobID)] VPR_AoE_Vicepit = 30105, + [ParentCombo(VPR_AoE_Vicepit)] + [CustomComboInfo("Disable Range Check", "Disables the range check for Vicepit.", VPR.JobID)] + VPR_AoE_Vicepit_DisableRange = 30111, + [ParentCombo(VPR_AoE_CDs)] [CustomComboInfo("Vicepit Combo", "Adds Swiftskin's Den and Hunter's Den to the rotation.", VPR.JobID)] VPR_AoE_VicepitCombo = 30106, + [ParentCombo(VPR_AoE_VicepitCombo)] + [CustomComboInfo("Disable Range Check", "Disables the range check for Swiftskin's Den and Hunter's Den.", VPR.JobID)] + VPR_AoE_VicepitCombo_DisableRange = 30113, + #endregion [ParentCombo(VPR_AoE_AdvancedMode)] @@ -4170,6 +4178,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Reawaken", "Adds Reawaken to the rotation.", VPR.JobID)] VPR_AoE_Reawaken = 30110, + [ParentCombo(VPR_AoE_Reawaken)] + [CustomComboInfo("Disable Range Check", "Disables the range check for Reawaken.", VPR.JobID)] + VPR_AoE_Reawaken_DisableRange = 30114, + [ParentCombo(VPR_AoE_AdvancedMode)] [ConflictingCombos(VPR_ReawakenLegacy)] [CustomComboInfo("Reawaken Combo", "Adds Generation and Legacy to the rotation.", VPR.JobID)] diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 19f984de5..826afcc20 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -598,6 +598,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; + bool in5y = GetTargetDistance() <= 5; bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; @@ -624,10 +625,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!HasEffect(Buffs.Reawakened)) { //Vicepit weaves - if (HasEffect(Buffs.FellhuntersVenom) && InMeleeRange()) + if (HasEffect(Buffs.FellhuntersVenom) && in5y) return OriginalHook(Twinfang); - if (HasEffect(Buffs.FellskinsVenom) && InMeleeRange()) + if (HasEffect(Buffs.FellskinsVenom) && in5y) return OriginalHook(Twinblood); //Serpents Ire usage @@ -637,7 +638,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Vicepit combo - if (!HasEffect(Buffs.Reawakened) && InMeleeRange()) + if (!HasEffect(Buffs.Reawakened) && in5y) { if (SwiftskinsDenReady) return HuntersDen; @@ -649,7 +650,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Reawakend Usage if ((HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && + !HasEffect(Buffs.Reawakened) && in5y && !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) return Reawaken; @@ -661,7 +662,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit Usage if (ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && InMeleeRange()) + ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && in5y) return Vicepit; // Uncoiled Fury usage @@ -770,6 +771,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; + bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; @@ -803,7 +805,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { //Vicepit weaves if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - InMeleeRange()) + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) { if (HasEffect(Buffs.FellhuntersVenom)) return OriginalHook(Twinfang); @@ -822,7 +824,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit combo if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - !HasEffect(Buffs.Reawakened) && InMeleeRange()) + !HasEffect(Buffs.Reawakened) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) { if (SwiftskinsDenReady) return HuntersDen; @@ -835,7 +838,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.VPR_AoE_Reawaken) && (HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && + !HasEffect(Buffs.Reawakened) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_Reawaken_DisableRange)) && !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) return Reawaken; @@ -849,7 +853,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicepit Usage if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && IsEnabled(CustomComboPreset.VPR_AoE_Vicepit) && - ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && + ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_Vicepit_DisableRange)) && ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre))) return Vicepit; From 2ca6b1cffe3baeb8b9181aa0279bf0c87b92d67f Mon Sep 17 00:00:00 2001 From: edewen Date: Mon, 26 Aug 2024 20:24:33 -0400 Subject: [PATCH 027/208] True North Ninja Update --- XIVSlothCombo/Combos/CustomComboPreset.cs | 6 +- XIVSlothCombo/Combos/PvE/NIN.cs | 113 +++++++++++++++++----- 2 files changed, 92 insertions(+), 27 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..3669dbb42 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2321,9 +2321,9 @@ public enum CustomComboPreset [CustomComboInfo("Suiton Uptime Option", "Adds Suiton as an uptime feature.", NIN.JobID)] NIN_ST_AdvancedMode_Suiton_Uptime = 10067, - [ParentCombo(NIN_ST_AdvancedMode_TrueNorth_ArmorCrush)] - [CustomComboInfo("Dynamic True North Option", "Adds True North before Armor Crush when you are not in the correct position for the enhanced potency bonus.", NIN.JobID)] - NIN_ST_AdvancedMode_TrueNorth_ArmorCrush_Dynamic = 10068, + //[ParentCombo(NIN_ST_AdvancedMode_TrueNorth_ArmorCrush)] Removed because true north is going to be dynamic inherently. Armor crush happens far more often now. Can just elimite all AC with TN. + //[CustomComboInfo("Dynamic True North Option", "Adds True North before Armor Crush when you are not in the correct position for the enhanced potency bonus.", NIN.JobID)] + //NIN_ST_AdvancedMode_TrueNorth_ArmorCrush_Dynamic = 10068, [Variant] [VariantParent(NIN_ST_SimpleMode, NIN_ST_AdvancedMode, NIN_AoE_SimpleMode, NIN_AoE_AdvancedMode)] diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN.cs index 4efb22ef1..b32850794 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN.cs @@ -169,6 +169,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim double playerHP = PlayerHealthPercentageHp(); bool phantomUptime = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Phantom_Uptime); var comboLength = GetCooldown(GustSlash).CooldownTotal * 3; + bool trueNorthArmor = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth) && TargetNeedsPositionals() && !OnTargetsFlank() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canDelayedWeave; + bool trueNorthEdge = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth) && TargetNeedsPositionals() && IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth_ArmorCrush) && !OnTargetsRear() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canDelayedWeave; + if (IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus) || (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5 && !InCombat())) mudraState.CurrentMudra = MudraCasting.MudraState.None; @@ -376,26 +379,51 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (lastComboMove == SpinningEdge && GustSlash.LevelChecked()) return OriginalHook(GustSlash); - if (IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth) && TargetNeedsPositionals() && - IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth_ArmorCrush) && - lastComboMove == GustSlash && GetRemainingCharges(All.TrueNorth) > 0 && - All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && - canWeave) - return OriginalHook(All.TrueNorth); - if (lastComboMove == GustSlash && ArmorCrush.LevelChecked()) { - if ((!NINHelper.MugDebuff) || (NINHelper.MugDebuff && gauge.Kazematoi == 0)) + if (!NINHelper.MugDebuff) { if (gauge.Kazematoi < 4) - return OriginalHook(ArmorCrush); + { + if (trueNorthArmor) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(ArmorCrush); + } + else + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } + } + if (NINHelper.MugDebuff) + { + if (gauge.Kazematoi == 0) + { + if (trueNorthArmor) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(ArmorCrush); + } + else + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } } + } + if (lastComboMove == GustSlash && !ArmorCrush.LevelChecked() && AeolianEdge.LevelChecked()) + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); } - - if (lastComboMove == GustSlash && AeolianEdge.LevelChecked() && (gauge.Kazematoi > 0 || !ArmorCrush.LevelChecked())) - return OriginalHook(AeolianEdge); } - return OriginalHook(SpinningEdge); } return actionID; @@ -592,6 +620,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool canWeave = CanWeave(SpinningEdge); bool inTrickBurstSaveWindow = GetCooldownRemainingTime(TrickAttack) <= 15 && Suiton.LevelChecked(); bool useBhakaBeforeTrickWindow = GetCooldownRemainingTime(TrickAttack) >= 3; + var canDelayedWeave = CanDelayedWeave(SpinningEdge); + bool trueNorthArmor = TargetNeedsPositionals() && !OnTargetsFlank() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canDelayedWeave; + bool trueNorthEdge = TargetNeedsPositionals() && !OnTargetsRear() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canDelayedWeave; + if (OriginalHook(Ninjutsu) is Rabbit) return OriginalHook(Ninjutsu); @@ -685,18 +717,51 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (lastComboMove == SpinningEdge && GustSlash.LevelChecked()) return OriginalHook(GustSlash); - if (lastComboMove == GustSlash && TargetNeedsPositionals() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canWeave) - return OriginalHook(All.TrueNorth); - - if (lastComboMove == GustSlash && AeolianEdge.LevelChecked() && (gauge.Kazematoi > 0 || !ArmorCrush.LevelChecked())) - return OriginalHook(AeolianEdge); - - if (lastComboMove == GustSlash && ArmorCrush.LevelChecked() && gauge.Kazematoi < 5) - return OriginalHook(ArmorCrush); - - + if (lastComboMove == GustSlash && ArmorCrush.LevelChecked()) + { + if (!NINHelper.MugDebuff) + { + if (gauge.Kazematoi < 4) + { + if (trueNorthArmor) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(ArmorCrush); + } + else + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } + } + if (NINHelper.MugDebuff) + { + if (gauge.Kazematoi == 0) + { + if (trueNorthArmor) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(ArmorCrush); + } + else + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } + } + } + if (lastComboMove == GustSlash && !ArmorCrush.LevelChecked() && AeolianEdge.LevelChecked()) + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } } - return OriginalHook(SpinningEdge); } return actionID; From 1be55c4532573f09fca9ebc9ba7f273ffb008380 Mon Sep 17 00:00:00 2001 From: edewen Date: Mon, 26 Aug 2024 21:49:45 -0400 Subject: [PATCH 028/208] Burn Kazematoi Slider --- XIVSlothCombo/Combos/PvE/NIN.cs | 6 ++++-- XIVSlothCombo/Window/Functions/UserConfig.cs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN.cs index b32850794..73577322e 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN.cs @@ -127,6 +127,7 @@ public const string Advanced_Trick_Cooldown = "Advanced_Trick_Cooldown", Advanced_DotonTimer = "Advanced_DotonTimer", Advanced_DotonHP = "Advanced_DotonHP", + BurnKazematoi = "BurnKazematoi", Advanced_TCJEnderAoE = "Advanced_TCJEnderAoe", Advanced_ChargePool = "Advanced_ChargePool", SecondWindThresholdST = "SecondWindThresholdST", @@ -163,6 +164,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool suitonUptime = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Suiton_Uptime); int bhavaPool = GetOptionValue(Config.Ninki_BhavaPooling); int bunshinPool = GetOptionValue(Config.Ninki_BunshinPoolingST); + int burnKazematoi = GetOptionValue(NIN.Config.BurnKazematoi); int SecondWindThreshold = PluginConfiguration.GetCustomIntValue(Config.SecondWindThresholdST); int ShadeShiftThreshold = PluginConfiguration.GetCustomIntValue(Config.ShadeShiftThresholdST); int BloodbathThreshold = PluginConfiguration.GetCustomIntValue(Config.BloodbathThresholdST); @@ -381,7 +383,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (lastComboMove == GustSlash && ArmorCrush.LevelChecked()) { - if (!NINHelper.MugDebuff) + if (!NINHelper.MugDebuff && GetTargetHPPercent() > burnKazematoi) { if (gauge.Kazematoi < 4) { @@ -398,7 +400,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(AeolianEdge); } } - if (NINHelper.MugDebuff) + if (NINHelper.MugDebuff || GetTargetHPPercent() <= burnKazematoi) { if (gauge.Kazematoi == 0) { diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..dc06e8fbd 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1598,6 +1598,8 @@ internal static void Draw(CustomComboPreset preset, bool enabled) UserConfig.DrawRadioButton(NIN.Config.NIN_SimpleMudra_Choice, "Mudra Path Set 1", $"1. Ten Mudras -> Fuma Shuriken, Raiton/Hyosho Ranryu, Suiton (Doton under Kassatsu).\nChi Mudras -> Fuma Shuriken, Hyoton, Huton.\nJin Mudras -> Fuma Shuriken, Katon/Goka Mekkyaku, Doton", 1); UserConfig.DrawRadioButton(NIN.Config.NIN_SimpleMudra_Choice, "Mudra Path Set 2", $"2. Ten Mudras -> Fuma Shuriken, Hyoton/Hyosho Ranryu, Doton.\nChi Mudras -> Fuma Shuriken, Katon, Suiton.\nJin Mudras -> Fuma Shuriken, Raiton/Goka Mekkyaku, Huton (Doton under Kassatsu).", 2); } + if (preset == CustomComboPreset.NIN_ST_AdvancedMode) + UserConfig.DrawSliderInt(0, 10, NIN.Config.BurnKazematoi, "Target HP% to dump all pooled Kazematoi below"); if (preset == CustomComboPreset.NIN_ST_AdvancedMode_Bhavacakra) UserConfig.DrawSliderInt(50, 100, NIN.Config.Ninki_BhavaPooling, "Set the minimal amount of Ninki required to have before spending on Bhavacakra."); From 4855bbdec33aa27058a199e1d8e97088d8473861 Mon Sep 17 00:00:00 2001 From: edewen Date: Tue, 27 Aug 2024 20:50:17 -0400 Subject: [PATCH 029/208] Added % slider to stop drawing motifs I added a separate % slider for each motif because it just makes sense, they do such different thing. --- XIVSlothCombo/Combos/PvE/PCT.cs | 53 +++++++++++++------- XIVSlothCombo/Window/Functions/UserConfig.cs | 12 +++++ 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index ed3d6485b..1c2a04cc9 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using XIVSlothCombo.Combos.JobHelpers; +using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; @@ -75,7 +76,14 @@ public static class Config public static UserInt CombinedAetherhueChoices = new("CombinedAetherhueChoices"), PCT_ST_AdvancedMode_LucidOption = new("PCT_ST_AdvancedMode_LucidOption", 6500), + PCT_ST_CreatureStop = new("PCT_ST_CreatureStop"), + PCT_AoE_CreatureStop = new("PCT_AoE_CreatureStop"), + PCT_ST_WeaponStop = new("PCT_ST_WeaponStop"), + PCT_AoE_WeaponStop = new("PCT_AoE_WeaponStop"), + PCT_ST_LandscapeStop = new("PCT_ST_LandscapeStop"), + PCT_AoE_LandscapeStop = new("PCT_AoE_LandscapeStop"), PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500); + public static UserBool CombinedMotifsMog = new("CombinedMotifsMog"), @@ -345,6 +353,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb { var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell) || CanSpellWeave(actionID); + int creatureStop = PluginConfiguration.GetCustomIntValue(Config.PCT_ST_CreatureStop); + int landscapeStop = PluginConfiguration.GetCustomIntValue(Config.PCT_ST_LandscapeStop); + int weaponStop = PluginConfiguration.GetCustomIntValue(Config.PCT_ST_WeaponStop); + // Prepull logic if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_PrePullMotifs)) @@ -488,11 +500,11 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Swiftcast Motifs if (HasEffect(All.Buffs.Swiftcast)) { - if (!gauge.CreatureMotifDrawn && CreatureMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + if (!gauge.CreatureMotifDrawn && CreatureMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse) && GetTargetHPPercent() > creatureStop) return OriginalHook(CreatureMotif); - if (!gauge.WeaponMotifDrawn && HammerMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.StarryMuse)) - return OriginalHook(HammerMotif); - if (!gauge.LandscapeMotifDrawn && LandscapeMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + if (!gauge.WeaponMotifDrawn && WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.StarryMuse) && GetTargetHPPercent() > weaponStop) + return OriginalHook(WeaponMotif); + if (!gauge.LandscapeMotifDrawn && LandscapeMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse) && GetTargetHPPercent() > landscapeStop) return OriginalHook(LandscapeMotif); } @@ -513,13 +525,13 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Prepare for Burst if (GetCooldownRemainingTime(ScenicMuse) <= 20) { - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif) && LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn) + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif) && LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && GetTargetHPPercent() > landscapeStop) return OriginalHook(LandscapeMotif); - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif) && CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn) + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif) && CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && GetTargetHPPercent() > creatureStop) return OriginalHook(CreatureMotif); - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif) && WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime)) + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif) && WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime) && GetTargetHPPercent() > weaponStop) return OriginalHook(WeaponMotif); } @@ -559,7 +571,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (!HasEffect(Buffs.StarryMuse)) { // LandscapeMotif - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif)) + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif) && GetTargetHPPercent() > landscapeStop) { if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && @@ -570,7 +582,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // CreatureMotif - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif)) + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif) && GetTargetHPPercent() > creatureStop) { if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && @@ -581,7 +593,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // WeaponMotif - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif)) + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif) && GetTargetHPPercent() > weaponStop) { if (WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && @@ -802,6 +814,9 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb { var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + int creatureStop = PluginConfiguration.GetCustomIntValue(Config.PCT_AoE_CreatureStop); + int landscapeStop = PluginConfiguration.GetCustomIntValue(Config.PCT_AoE_LandscapeStop); + int weaponStop = PluginConfiguration.GetCustomIntValue(Config.PCT_AoE_WeaponStop); // Prepull logic if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_PrePullMotifs)) @@ -906,11 +921,11 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (HasEffect(All.Buffs.Swiftcast)) { - if (!gauge.CreatureMotifDrawn && CreatureMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + if (!gauge.CreatureMotifDrawn && CreatureMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse) && GetTargetHPPercent() > creatureStop) return OriginalHook(CreatureMotif); - if (!gauge.WeaponMotifDrawn && HammerMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.StarryMuse)) + if (!gauge.WeaponMotifDrawn && HammerMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !HasEffect(Buffs.StarryMuse) && GetTargetHPPercent() >weaponStop) return OriginalHook(HammerMotif); - if (!gauge.LandscapeMotifDrawn && LandscapeMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse)) + if (!gauge.LandscapeMotifDrawn && LandscapeMotif.LevelChecked() && !HasEffect(Buffs.StarryMuse) && GetTargetHPPercent() > landscapeStop) return OriginalHook(LandscapeMotif); } @@ -930,13 +945,13 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Prepare for Burst if (GetCooldownRemainingTime(ScenicMuse) <= 20) { - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif) && LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn) + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif) && LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && GetTargetHPPercent() > landscapeStop) return OriginalHook(LandscapeMotif); - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif) && CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn) + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif) && CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && GetTargetHPPercent() > creatureStop) return OriginalHook(CreatureMotif); - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif) && WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime)) + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif) && WeaponMotif.LevelChecked() && !gauge.WeaponMotifDrawn && !HasEffect(Buffs.HammerTime) && GetTargetHPPercent() > weaponStop) return OriginalHook(WeaponMotif); } @@ -979,19 +994,19 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (!HasEffect(Buffs.StarryMuse)) { - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif)) + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif) && GetTargetHPPercent() > landscapeStop) { if (LandscapeMotif.LevelChecked() && !gauge.LandscapeMotifDrawn && GetCooldownRemainingTime(ScenicMuse) <= 20) return OriginalHook(LandscapeMotif); } - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif)) + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif) && GetTargetHPPercent() > creatureStop) { if (CreatureMotif.LevelChecked() && !gauge.CreatureMotifDrawn && (HasCharges(LivingMuse) || GetCooldownChargeRemainingTime(LivingMuse) <= 8)) return OriginalHook(CreatureMotif); } - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif)) + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif) && GetTargetHPPercent() > weaponStop) { if (WeaponMotif.LevelChecked() && !HasEffect(Buffs.HammerTime) && !gauge.WeaponMotifDrawn && (HasCharges(SteelMuse) || GetCooldownChargeRemainingTime(SteelMuse) <= 8)) return OriginalHook(WeaponMotif); diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..aacdaf1f6 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1680,6 +1680,18 @@ internal static void Draw(CustomComboPreset preset, bool enabled) { UserConfig.DrawSliderInt(0, 10000, PCT.Config.PCT_AoE_AdvancedMode_LucidOption, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); } + if (preset == CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif) + UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_ST_LandscapeStop, "Health % to stop Drawing Motif"); + if (preset == CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif) + UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_ST_CreatureStop, "Health % to stop Drawing Motif"); + if (preset == CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif) + UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_ST_WeaponStop, "Health % to stop Drawing Motif"); + if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif) + UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_AoE_LandscapeStop, "Health % to stop Drawing Motif"); + if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif) + UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_AoE_CreatureStop, "Health % to stop Drawing Motif"); + if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif) + UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_AoE_WeaponStop, "Health % to stop Drawing Motif"); // PvP if (preset == CustomComboPreset.PCTPvP_BurstControl) From 83c863a6540c5bd699f3fd9e8748e9682ef2f18f Mon Sep 17 00:00:00 2001 From: Katie Date: Tue, 27 Aug 2024 22:42:18 -0400 Subject: [PATCH 030/208] Add battle target check to AoE Simple Mode --- XIVSlothCombo/Combos/PvE/VPR.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 826afcc20..9f84d8b4e 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -598,7 +598,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; - bool in5y = GetTargetDistance() <= 5; + bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; From d605fd96c285770eb87dc9191ca5db366cd0809f Mon Sep 17 00:00:00 2001 From: ace Date: Tue, 27 Aug 2024 22:29:28 -0700 Subject: [PATCH 031/208] combotimer fixes --- XIVSlothCombo/Combos/PvE/VPR.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 19f984de5..0a5964970 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -419,7 +419,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicewinder Combo if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && - IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && + IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && !HasEffect(Buffs.Reawakened) && LevelChecked(Vicewinder) && InMeleeRange()) { // Swiftskin's Coil @@ -443,20 +443,20 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicewinder Usage if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && - IsEnabled(CustomComboPreset.VPR_ST_Vicewinder) && HasEffect(Buffs.Swiftscaled) && + IsEnabled(CustomComboPreset.VPR_ST_Vicewinder) && HasEffect(Buffs.Swiftscaled) && !VPRCheckTimers.IsComboExpiring(3) && ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) return Vicewinder; // Uncoiled Fury usage - if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && + if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && !VPRCheckTimers.IsComboExpiring(2) && LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && ((RattlingCoils > Config.VPR_ST_UncoiledFury_HoldCharges) || (enemyHP < uncoiledThreshold && VPRCheckRattlingCoils.HasRattlingCoilStack(gauge))) && !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && !WasLastWeaponskill(Ouroboros) && - !VPRCheckTimers.IsEmpowermentExpiring(6) && !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) + !VPRCheckTimers.IsEmpowermentExpiring(3)) return UncoiledFury; //Reawaken combo From fa5e278d1f4ea15e573cf83666f24ff25bb11ddf Mon Sep 17 00:00:00 2001 From: ace Date: Tue, 27 Aug 2024 23:55:18 -0700 Subject: [PATCH 032/208] WIP --- XIVSlothCombo/Combos/JobHelpers/SAM.cs | 102 +++++++------------ XIVSlothCombo/Combos/PvE/SAM.cs | 132 +++++++++++++++++++------ 2 files changed, 137 insertions(+), 97 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/SAM.cs b/XIVSlothCombo/Combos/JobHelpers/SAM.cs index ec2a655e5..3b863a0c2 100644 --- a/XIVSlothCombo/Combos/JobHelpers/SAM.cs +++ b/XIVSlothCombo/Combos/JobHelpers/SAM.cs @@ -1,4 +1,5 @@ -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using System.Linq; @@ -22,7 +23,7 @@ private static int GetSenCount() return senCount; } - internal static bool ComboStarted => GetComboStarted(); + internal static bool ComboStarted => GetComboStarted(); private unsafe static bool GetComboStarted() { var comboAction = ActionManager.Instance()->Combo.Action; @@ -30,40 +31,6 @@ private unsafe static bool GetComboStarted() return true; return false; } - - internal static bool UseTsubame => GetUseTsubame(); - - private static bool GetUseTsubame() - { - int MeikyoUsed = ActionWatching.CombatActions.Count(x => x == MeikyoShisui); - - if (CustomComboFunctions.ActionReady(TsubameGaeshi)) - { - //Tendo - if (CustomComboFunctions.HasEffect(Buffs.TendoKaeshiSetsugekkaReady)) - return true; - - if (CustomComboFunctions.HasEffect(Buffs.TsubameReady)) - { - var meikyoModulo = MeikyoUsed % 15; - //1 and 2 min - if ((meikyoModulo is 0 or 1 or 2 or 3 or 4 or 9 or 10)) - return true; - - // 3 and 4 min - if ((meikyoModulo is 5 or 6 or 11 or 12) && - CustomComboFunctions.GetBuffStacks(Buffs.MeikyoShisui) is 2) - return true; - - // 5 and 6 min - if ((meikyoModulo is 7 or 8 or 13 or 14) && - CustomComboFunctions.GetBuffStacks(Buffs.MeikyoShisui) is 1) - return true; - } - } - return false; - } - } @@ -195,50 +162,53 @@ private bool DoOpener(ref uint actionID) if (CustomComboFunctions.WasLastAction(MeikyoShisui) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = MeikyoShisui; - if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Gekko; + if (CustomComboFunctions.WasLastAction(All.TrueNorth) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = All.TrueNorth; + + if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = Gekko; - if (CustomComboFunctions.WasLastAction(Zanshin) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = Zanshin; + if (CustomComboFunctions.WasLastAction(Zanshin) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = Zanshin; - if (CustomComboFunctions.WasLastAction(Higanbana) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Higanbana; + if (CustomComboFunctions.WasLastAction(Higanbana) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = Higanbana; - if (CustomComboFunctions.WasLastAction(OgiNamikiri) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = OgiNamikiri; + if (CustomComboFunctions.WasLastAction(OgiNamikiri) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = OgiNamikiri; - if (CustomComboFunctions.WasLastAction(Shoha) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Shoha; + if (CustomComboFunctions.WasLastAction(Shoha) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = Shoha; - if (CustomComboFunctions.WasLastAction(KaeshiNamikiri) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = KaeshiNamikiri; + if (CustomComboFunctions.WasLastAction(KaeshiNamikiri) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = KaeshiNamikiri; - if (CustomComboFunctions.WasLastAction(Kasha) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Kasha; + if (CustomComboFunctions.WasLastAction(Kasha) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = Kasha; - if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = Shinten; + if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = Shinten; - if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = Gekko; + if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = Gekko; - if (CustomComboFunctions.WasLastAction(Gyoten) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Gyoten; + if (CustomComboFunctions.WasLastAction(Gyoten) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = Gyoten; - if (CustomComboFunctions.WasLastAction(Gyofu) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Gyofu; + if (CustomComboFunctions.WasLastAction(Gyofu) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = Gyofu; - if (CustomComboFunctions.WasLastAction(Yukikaze) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = Yukikaze; + if (CustomComboFunctions.WasLastAction(Yukikaze) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = Yukikaze; - if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = Shinten; + if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = Shinten; - if (CustomComboFunctions.WasLastAction(TendoSetsugekka) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = TendoSetsugekka; + if (CustomComboFunctions.WasLastAction(TendoSetsugekka) && OpenerStep == 23) OpenerStep++; + else if (OpenerStep == 23) actionID = TendoSetsugekka; - if (CustomComboFunctions.WasLastAction(TendoKaeshiSetsugekka) && OpenerStep == 23) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 23) actionID = TendoKaeshiSetsugekka; + if (CustomComboFunctions.WasLastAction(TendoKaeshiSetsugekka) && OpenerStep == 24) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 24) actionID = TendoKaeshiSetsugekka; if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index cf5cbf4ca..a7b5d2e8b 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -2,6 +2,7 @@ using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Component.GUI; +using Lumina.Excel.GeneratedSheets2; using System; using System.Linq; using XIVSlothCombo.Combos.JobHelpers; @@ -215,13 +216,13 @@ internal class SAM_ST_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { SAMGauge? gauge = GetJobGauge(); - bool oneSeal = OriginalHook(Iaijutsu) is Higanbana; - bool twoSeal = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; - bool threeSeal = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; + bool oneSen = OriginalHook(Iaijutsu) is Higanbana; + bool twoSen = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; + bool threeSen = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; float enemyHP = GetTargetHPPercent(); bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); float meikyostacks = GetBuffStacks(Buffs.MeikyoShisui); - + if (actionID is Hakaze or Gyofu) { if (IsEnabled(CustomComboPreset.SAM_Variant_Cure) && @@ -273,9 +274,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Zanshin Usage if (LevelChecked(Zanshin) && gauge.Kenki >= 50 && CanWeave(actionID) && HasEffect(Buffs.ZanshinReady) && - ((meikyostacks is 2 && WasLastWeaponskill(Gekko)) || + (JustUsed(OgiNamikiri, 5f) || GetBuffRemainingTime(Buffs.ZanshinReady) <= 6)) - return OriginalHook(Ikishoten); + return Zanshin; if (LevelChecked(Shoha) && gauge.MeditationStacks is 3) return Shoha; @@ -300,14 +301,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Iaijutsu Features if (LevelChecked(Iaijutsu)) { - if (SAMHelper.UseTsubame) - return OriginalHook(TsubameGaeshi); - if (!IsMoving && - ((oneSeal && GetDebuffRemainingTime(Debuffs.Higanbana) <= 10) || - (twoSeal && !LevelChecked(MidareSetsugekka)) || - (threeSeal && LevelChecked(MidareSetsugekka)) || - (threeSeal && LevelChecked(TendoSetsugekka) && !HasEffect(Buffs.TsubameReady)))) + ((oneSen && GetDebuffRemainingTime(Debuffs.Higanbana) <= 10) || + (twoSen && !LevelChecked(MidareSetsugekka)) || + (threeSen && LevelChecked(MidareSetsugekka)) || + (threeSen && LevelChecked(TendoSetsugekka) && !HasEffect(Buffs.TsubameReady)))) return OriginalHook(Iaijutsu); } } @@ -344,11 +342,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Yukikaze; if ((!LevelChecked(Kasha) && ((GetBuffRemainingTime(Buffs.Fugetsu) < GetBuffRemainingTime(Buffs.Fuka)) || !HasEffect(Buffs.Fugetsu))) || - (LevelChecked(Kasha) && (!HasEffect(Buffs.Fugetsu) || (HasEffect(Buffs.Fuka) && !gauge.Sen.HasFlag(Sen.GETSU)) || (threeSeal && (GetBuffRemainingTime(Buffs.Fugetsu) < GetBuffRemainingTime(Buffs.Fuka)))))) + (LevelChecked(Kasha) && (!HasEffect(Buffs.Fugetsu) || (HasEffect(Buffs.Fuka) && !gauge.Sen.HasFlag(Sen.GETSU)) || (threeSen && (GetBuffRemainingTime(Buffs.Fugetsu) < GetBuffRemainingTime(Buffs.Fuka)))))) return Jinpu; if (LevelChecked(Shifu) && ((!LevelChecked(Kasha) && ((GetBuffRemainingTime(Buffs.Fuka) < GetBuffRemainingTime(Buffs.Fugetsu)) || !HasEffect(Buffs.Fuka))) || - (LevelChecked(Kasha) && (!HasEffect(Buffs.Fuka) || (HasEffect(Buffs.Fugetsu) && !gauge.Sen.HasFlag(Sen.KA)) || (threeSeal && (GetBuffRemainingTime(Buffs.Fuka) < GetBuffRemainingTime(Buffs.Fugetsu))))))) + (LevelChecked(Kasha) && (!HasEffect(Buffs.Fuka) || (HasEffect(Buffs.Fugetsu) && !gauge.Sen.HasFlag(Sen.KA)) || (threeSen && (GetBuffRemainingTime(Buffs.Fuka) < GetBuffRemainingTime(Buffs.Fugetsu))))))) return Shifu; } @@ -362,6 +360,35 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } return actionID; } + + public static bool GetUseMeikyo() + { + int MeikyoUsed = ActionWatching.CombatActions.Count(x => x == MeikyoShisui); + var gauge = CustomComboFunctions.GetJobGauge(); + bool oneSen = OriginalHook(Iaijutsu) is Higanbana; + bool twoSen = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; + bool threeSen = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; + + if (CustomComboFunctions.ActionReady(MeikyoShisui)) + { + var usedMeikyo = MeikyoUsed % 20; + //1 and 2 min are #3 and #4, reset at 9 & 15 + if ((usedMeikyo is 3 or 4 or 9 or 10 or 15 or 16) && + threeSen) + return true; + + // 3 and 4 min are #5 and #6, reset at 11 & 17 + if ((usedMeikyo is 5 or 6 or 11 or 12 or 17 or 18) && + twoSen) + return true; + + // 5 and 6 min are #7 and #8, reset at 13 & 19 + if ((usedMeikyo is 7 or 8 or 13 or 14 or 19 or 20) && + oneSen) + return true; + } + return false; + } } internal class SAM_ST_AdvancedMode : CustomCombo @@ -372,15 +399,16 @@ internal class SAM_ST_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { SAMGauge? gauge = GetJobGauge(); - bool oneSeal = OriginalHook(Iaijutsu) is Higanbana; - bool twoSeal = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; - bool threeSeal = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; + bool oneSen = OriginalHook(Iaijutsu) is Higanbana; + bool twoSen = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; + bool threeSen = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; float enemyHP = GetTargetHPPercent(); bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); int kenkiOvercap = Config.SAM_ST_KenkiOvercapAmount; float shintenTreshhold = Config.SAM_ST_ExecuteThreshold; float HiganbanaThreshold = Config.SAM_ST_Higanbana_Threshold; float meikyostacks = GetBuffStacks(Buffs.MeikyoShisui); + float GCD = GetCooldown(Hakaze).CooldownTotal; if (actionID is Hakaze or Gyofu) { @@ -414,14 +442,21 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.SAM_ST_CDs)) { //Meikyo Features - if (IsEnabled(CustomComboPreset.SAM_ST_CDs_MeikyoShisui) && + /* if (IsEnabled(CustomComboPreset.SAM_ST_CDs_MeikyoShisui) && !HasEffect(Buffs.MeikyoShisui) && ActionReady(MeikyoShisui) && - GetCooldownRemainingTime(MeikyoShisui) <= 10 && - SAMHelper.SenCount < 3 && + SAMHelper.SenCount > 0 && !SAMHelper.ComboStarted) return MeikyoShisui; + if (GetUseMeikyo()) + return MeikyoShisui; */ + + if (ActionReady(MeikyoShisui) && meikyostacks is 0 && (oneSen || twoSen || threeSen) && + (JustUsed(KaeshiSetsugekka, 5f) && GetCooldownRemainingTime(Ikishoten) is >= 45 and <= 75) || //1min + (JustUsed(KaeshiSetsugekka, 5f) && GetCooldownRemainingTime(Ikishoten) is >= 105)) //2min + return MeikyoShisui; + //Ikishoten Features if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Ikishoten) && LevelChecked(Ikishoten)) { @@ -443,9 +478,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Zanshin) && LevelChecked(Zanshin) && gauge.Kenki >= 50 && CanWeave(actionID) && HasEffect(Buffs.ZanshinReady) && - ((meikyostacks is 2 && WasLastWeaponskill(Gekko)) || + (JustUsed(Higanbana, 7f) || GetBuffRemainingTime(Buffs.ZanshinReady) <= 6)) - return OriginalHook(Ikishoten); + return Zanshin; if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Shoha) && LevelChecked(Shoha) && gauge.MeditationStacks is 3) @@ -471,21 +506,24 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.SAM_ST_CDs_OgiNamikiri) && (!IsEnabled(CustomComboPreset.SAM_ST_CDs_OgiNamikiri_Movement) || (IsEnabled(CustomComboPreset.SAM_ST_CDs_OgiNamikiri_Movement) && !IsMoving)) && - ActionReady(OgiNamikiri) && + ActionReady(OgiNamikiri) && (JustUsed(Higanbana, 5f) || GetBuffRemainingTime(Buffs.OgiNamikiriReady) <= GCD) && (gauge.Kaeshi == Kaeshi.NAMIKIRI || HasEffect(Buffs.OgiNamikiriReady))) return OriginalHook(OgiNamikiri); // Iaijutsu Features if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu) && LevelChecked(Iaijutsu)) { - if (SAMHelper.UseTsubame) + if (LevelChecked(TsubameGaeshi) && HasEffect(Buffs.TsubameReady) && + (threeSen || GetDebuffRemainingTime(Debuffs.Higanbana) > 40)) + return OriginalHook(TsubameGaeshi); + if (HasEffect(Buffs.TendoKaeshiSetsugekkaReady)) return OriginalHook(TsubameGaeshi); if ((!IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu_Movement) || (IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu_Movement) && !IsMoving)) && - ((oneSeal && enemyHP > HiganbanaThreshold && GetDebuffRemainingTime(Debuffs.Higanbana) <= 10) || - (twoSeal && !LevelChecked(MidareSetsugekka)) || - (threeSeal && + ((oneSen && enemyHP > HiganbanaThreshold && GetDebuffRemainingTime(Debuffs.Higanbana) <= 19 && JustUsed(Gekko, 3f) && JustUsed(MeikyoShisui, 15f)) || + (twoSen && !LevelChecked(MidareSetsugekka)) || + (threeSen && (LevelChecked(MidareSetsugekka) && !HasEffect(Buffs.TsubameReady))))) return OriginalHook(Iaijutsu); } @@ -528,12 +566,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Yukikaze; if ((!LevelChecked(Kasha) && ((GetBuffRemainingTime(Buffs.Fugetsu) < GetBuffRemainingTime(Buffs.Fuka)) || !HasEffect(Buffs.Fugetsu))) || - (LevelChecked(Kasha) && (!HasEffect(Buffs.Fugetsu) || (HasEffect(Buffs.Fuka) && !gauge.Sen.HasFlag(Sen.GETSU)) || (threeSeal && (GetBuffRemainingTime(Buffs.Fugetsu) < GetBuffRemainingTime(Buffs.Fuka)))))) + (LevelChecked(Kasha) && (!HasEffect(Buffs.Fugetsu) || (HasEffect(Buffs.Fuka) && !gauge.Sen.HasFlag(Sen.GETSU)) || (threeSen && (GetBuffRemainingTime(Buffs.Fugetsu) < GetBuffRemainingTime(Buffs.Fuka)))))) return Jinpu; if (IsEnabled(CustomComboPreset.SAM_ST_Kasha) && LevelChecked(Shifu) && ((!LevelChecked(Kasha) && ((GetBuffRemainingTime(Buffs.Fuka) < GetBuffRemainingTime(Buffs.Fugetsu)) || !HasEffect(Buffs.Fuka))) || - (LevelChecked(Kasha) && (!HasEffect(Buffs.Fuka) || (HasEffect(Buffs.Fugetsu) && !gauge.Sen.HasFlag(Sen.KA)) || (threeSeal && (GetBuffRemainingTime(Buffs.Fuka) < GetBuffRemainingTime(Buffs.Fugetsu))))))) + (LevelChecked(Kasha) && (!HasEffect(Buffs.Fuka) || (HasEffect(Buffs.Fugetsu) && !gauge.Sen.HasFlag(Sen.KA)) || (threeSen && (GetBuffRemainingTime(Buffs.Fuka) < GetBuffRemainingTime(Buffs.Fugetsu))))))) return Shifu; } @@ -548,6 +586,38 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } return actionID; } + + public static bool GetUseMeikyo() + { + int MeikyoUsed = ActionWatching.CombatActions.Count(x => x == MeikyoShisui); + bool oneSen = OriginalHook(Iaijutsu) is Higanbana; + bool twoSen = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; + bool threeSen = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; + + if (ActionReady(MeikyoShisui)) + { + var usedMeikyo = MeikyoUsed % 15; + //1 and 2 min are #3 and #4, reset at 9 & 15 + if ((usedMeikyo is 1 or 2 or 7 or 8) && (GetCooldownRemainingTime(Ikishoten) > 45) && + threeSen) + return true; + + // 3 and 4 min are #5 and #6, reset at 11 & 17 + if ((usedMeikyo is 3 or 4 or 9 or 10) && (GetCooldownRemainingTime(Ikishoten) > 45) && + twoSen) + return true; + + // 5 and 6 min are #7 and #8, reset at 13 & 19 + if ((usedMeikyo is 5 or 11) && (GetCooldownRemainingTime(Ikishoten) > 45) && + oneSen) + return true; + if ((usedMeikyo is 6 or 12) && + oneSen) + return true; + } + return false; + } + } internal class SAM_AoE_OkaCombo : CustomCombo @@ -958,4 +1028,4 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } } -} +} \ No newline at end of file From 1a8a12e3ef3e80c6a3f2ec14f9254080ac2872d4 Mon Sep 17 00:00:00 2001 From: Kage Date: Wed, 28 Aug 2024 13:20:11 +0200 Subject: [PATCH 033/208] RPR - fix lower lvl bloodstalk use --- XIVSlothCombo/Combos/PvE/RPR.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/RPR.cs b/XIVSlothCombo/Combos/PvE/RPR.cs index bbdf8dc4e..06ca0122d 100644 --- a/XIVSlothCombo/Combos/PvE/RPR.cs +++ b/XIVSlothCombo/Combos/PvE/RPR.cs @@ -155,7 +155,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && - !RPRHelpers.IsComboExpiring(3) && GetCooldownRemainingTime(ArcaneCircle) > GCD * 3) + ((GetCooldownRemainingTime(ArcaneCircle) > GCD * 3) || !LevelChecked(ArcaneCircle)) && + !RPRHelpers.IsComboExpiring(3)) { //Gluttony if (!JustUsed(Perfectio) && ActionReady(Gluttony)) @@ -355,7 +356,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && - !RPRHelpers.IsComboExpiring(3) && GetCooldownRemainingTime(ArcaneCircle) > GCD * 3) + ((GetCooldownRemainingTime(ArcaneCircle) > GCD * 3) || !LevelChecked(ArcaneCircle)) && + !RPRHelpers.IsComboExpiring(3)) { //Gluttony if (IsEnabled(CustomComboPreset.RPR_ST_Gluttony) && From edb41be943d33e56a35aeaa18b75cc1e04c277e7 Mon Sep 17 00:00:00 2001 From: Kage Date: Wed, 28 Aug 2024 13:26:23 +0200 Subject: [PATCH 034/208] DRG - fix priority for hard cooldowns --- XIVSlothCombo/Combos/PvE/DRG.cs | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG.cs index 8eee8bcb7..0bc7670e7 100644 --- a/XIVSlothCombo/Combos/PvE/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG.cs @@ -153,28 +153,28 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) return LifeSurge; - //Wyrmwind Thrust Feature - if (LevelChecked(WyrmwindThrust) && - AnimationLock.CanDRGWeave(WyrmwindThrust) && - gauge.FirstmindsFocusCount is 2) - return WyrmwindThrust; - //Geirskogul Feature if (ActionReady(Geirskogul) && AnimationLock.CanDRGWeave(Geirskogul)) return Geirskogul; + //Dragonfire Dive Feature + if (ActionReady(DragonfireDive) && + AnimationLock.CanDRGWeave(DragonfireDive) && + !IsMoving) + return DragonfireDive; + //(High) Jump Feature if (ActionReady(OriginalHook(Jump)) && AnimationLock.CanDRGWeave(OriginalHook(Jump)) && !IsMoving) return OriginalHook(Jump); - //Dragonfire Dive Feature - if (ActionReady(DragonfireDive) && - AnimationLock.CanDRGWeave(DragonfireDive) && - !IsMoving) - return DragonfireDive; + //Wyrmwind Thrust Feature + if (LevelChecked(WyrmwindThrust) && + AnimationLock.CanDRGWeave(WyrmwindThrust) && + gauge.FirstmindsFocusCount is 2) + return WyrmwindThrust; //StarDiver Feature if (ActionReady(Stardiver) && @@ -332,6 +332,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) return LifeSurge; + //Geirskogul Feature + if (IsEnabled(CustomComboPreset.DRG_ST_Geirskogul) && + ActionReady(Geirskogul) && + AnimationLock.CanDRGWeave(Geirskogul)) + return Geirskogul; + //Dragonfire Dive Feature if (IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive) && ActionReady(DragonfireDive) && @@ -340,15 +346,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive_Movement) && !IsMoving))) return DragonfireDive; - //StarDiver Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Stardiver) && - ActionReady(Stardiver) && - AnimationLock.CanDRGWeave(Stardiver) && - gauge.IsLOTDActive && - (!IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) || - (IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) && !IsMoving))) - return Stardiver; - //(High) Jump Feature if (IsEnabled(CustomComboPreset.DRG_ST_HighJump) && ActionReady(OriginalHook(Jump)) && @@ -364,11 +361,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim gauge.FirstmindsFocusCount is 2) return WyrmwindThrust; - //Geirskogul Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Geirskogul) && - ActionReady(Geirskogul) && - AnimationLock.CanDRGWeave(Geirskogul)) - return Geirskogul; + //StarDiver Feature + if (IsEnabled(CustomComboPreset.DRG_ST_Stardiver) && + ActionReady(Stardiver) && + AnimationLock.CanDRGWeave(Stardiver) && + gauge.IsLOTDActive && + (!IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) || + (IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) && !IsMoving))) + return Stardiver; //Starcross Feature if (IsEnabled(CustomComboPreset.DRG_ST_Starcross) && From 3d0938627146a3d54267038cbceb06c0b8d3225b Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 28 Aug 2024 08:10:02 -0400 Subject: [PATCH 035/208] Adding rainbow bright to movement per Akechi --- XIVSlothCombo/Combos/PvE/PCT.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index 1c2a04cc9..2fcb7ae41 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -249,6 +249,9 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (CometinBlack.LevelChecked() && gauge.Paint >= 1 && HasEffect(Buffs.MonochromeTones)) return OriginalHook(CometinBlack); + if (HasEffect(Buffs.RainbowBright) || HasEffect(Buffs.RainbowBright) && GetBuffRemainingTime(Buffs.StarryMuse) <= 3f) + return RainbowDrip; + if (HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); } @@ -518,6 +521,12 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_MovementOption_CometinBlack) && CometinBlack.LevelChecked() && gauge.Paint >= 1 && HasEffect(Buffs.MonochromeTones)) return OriginalHook(CometinBlack); + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_Burst_RainbowDrip)) + { + if (HasEffect(Buffs.RainbowBright) || HasEffect(Buffs.RainbowBright) && GetBuffRemainingTime(Buffs.StarryMuse) <= 3f) + return RainbowDrip; + } + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_MovementOption_HolyInWhite) && HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); } @@ -732,6 +741,9 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (CometinBlack.LevelChecked() && gauge.Paint >= 1 && HasEffect(Buffs.MonochromeTones)) return OriginalHook(CometinBlack); + if (HasEffect(Buffs.RainbowBright) || (HasEffect(Buffs.RainbowBright) && GetBuffRemainingTime(Buffs.StarryMuse) < 3)) + return RainbowDrip; + if (HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); @@ -937,6 +949,12 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_MovementOption_CometinBlack) && CometinBlack.LevelChecked() && gauge.Paint >= 1 && HasEffect(Buffs.MonochromeTones)) return OriginalHook(CometinBlack); + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_Burst_RainbowDrip)) + { + if (HasEffect(Buffs.RainbowBright) || (HasEffect(Buffs.RainbowBright) && GetBuffRemainingTime(Buffs.StarryMuse) < 3)) + return RainbowDrip; + } + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_MovementOption_HolyInWhite) && HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); From 6b2213c3e873e4cd05f7895b8528abeb98354188 Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 28 Aug 2024 08:21:43 -0400 Subject: [PATCH 036/208] Fix lvl 52-53 pitch perfect Added lvl check to empycd check in Pitch perfect line to prevent it from popping at 2 in dusk vigil. --- XIVSlothCombo/Combos/PvE/BRD.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index fa762902d..76b202665 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -429,7 +429,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return EmpyrealArrow; if (LevelChecked(PitchPerfect) && songWanderer && - (gauge.Repertoire == 3 || (gauge.Repertoire == 2 && empyrealCD < 2))) + (gauge.Repertoire == 3 || (LevelChecked(EmpyrealArrow) && gauge.Repertoire == 2 && empyrealCD < 2))) return OriginalHook(PitchPerfect); if (ActionReady(Sidewinder)) @@ -730,7 +730,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return EmpyrealArrow; if (LevelChecked(PitchPerfect) && songWanderer && - (gauge.Repertoire == 3 || (gauge.Repertoire == 2 && empyrealCD < 2))) + (gauge.Repertoire == 3 || (LevelChecked(EmpyrealArrow) && gauge.Repertoire == 2 && empyrealCD < 2))) return OriginalHook(PitchPerfect); if (ActionReady(Sidewinder)) @@ -1055,7 +1055,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return EmpyrealArrow; if (LevelChecked(PitchPerfect) && songWanderer && - (gauge.Repertoire == 3 || (gauge.Repertoire == 2 && empyrealCD < 2))) + (gauge.Repertoire == 3 || (LevelChecked(EmpyrealArrow) && gauge.Repertoire == 2 && empyrealCD < 2))) return OriginalHook(PitchPerfect); if (ActionReady(Sidewinder)) @@ -1284,7 +1284,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return EmpyrealArrow; if (LevelChecked(PitchPerfect) && songWanderer && - (gauge.Repertoire == 3 || (gauge.Repertoire == 2 && empyrealCD < 2))) + (gauge.Repertoire == 3 || (LevelChecked(EmpyrealArrow) && gauge.Repertoire == 2 && empyrealCD < 2))) return OriginalHook(PitchPerfect); if (ActionReady(Sidewinder)) From bf18c179203638a392bf5e505922992b0326ec0f Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 28 Aug 2024 08:58:42 -0400 Subject: [PATCH 037/208] Increase raging jaws slider Increased slider to allow up to 10 seconds. Adjusted recast on dots to prevent it from double raging jaws on higher settings. --- XIVSlothCombo/Combos/PvE/BRD.cs | 2 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 76b202665..5ab3813a0 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -817,7 +817,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.BRD_Adv_DoT)) { if (ActionReady(IronJaws) && IsEnabled(CustomComboPreset.BRD_Adv_RagingJaws) && HasEffect(Buffs.RagingStrikes) && - !WasLastAction(IronJaws) && ragingStrikesDuration < ragingJawsRenewTime && poisonRecast(40) && windRecast(40)) + !WasLastAction(IronJaws) && ragingStrikesDuration < ragingJawsRenewTime && poisonRecast(35) && windRecast(35)) { openerFinished = true; return IronJaws; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..93d8819f3 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1347,7 +1347,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #region BARD if (preset == CustomComboPreset.BRD_Adv_RagingJaws) - UserConfig.DrawSliderInt(3, 5, BRD.Config.BRD_RagingJawsRenewTime, "Remaining time (In seconds)"); + UserConfig.DrawSliderInt(3, 10, BRD.Config.BRD_RagingJawsRenewTime, "Remaining time (In seconds). Recommended 5, increase little by little if refresh is outside of radiant window"); if (preset == CustomComboPreset.BRD_Adv_NoWaste) UserConfig.DrawSliderInt(1, 10, BRD.Config.BRD_NoWasteHPPercentage, "Remaining target HP percentage"); From 796741b4ef36510cdd2684c204004377a59471e1 Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 28 Aug 2024 12:06:49 -0400 Subject: [PATCH 038/208] Tighten ragingjaws dot recast to keep it from doubling on higher skill speeds. --- XIVSlothCombo/Combos/PvE/BRD.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 5ab3813a0..170635e79 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -1365,7 +1365,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim }; if (ActionReady(IronJaws) && HasEffect(Buffs.RagingStrikes) && - !WasLastAction(IronJaws) && ragingStrikesDuration < ragingJawsRenewTime && poisonRecast(40) && windRecast(40)) + !WasLastAction(IronJaws) && ragingStrikesDuration < ragingJawsRenewTime && poisonRecast(35) && windRecast(35)) { openerFinished = true; return IronJaws; From ef44d0077161af2e62f02dd4030dfebcd7d0ef7b Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 28 Aug 2024 15:59:48 -0400 Subject: [PATCH 039/208] For for 54-84 pooling of bloodletter/rain charges Added trait check for enhanced bloodletter for pooling 3 charges. Added option for actually pooling aoe charges as it was forced before. --- XIVSlothCombo/Combos/CustomComboPreset.cs | 8 ++++++-- XIVSlothCombo/Combos/PvE/BRD.cs | 14 +++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..586f34076 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -677,9 +677,13 @@ public enum CustomComboPreset //BardSimpleOpener = 3022, [ParentCombo(BRD_ST_AdvMode)] - [CustomComboInfo("Pooling Option", "Pools Bloodletter charges to allow for optimum burst phases, will also keep sidewinder in the buff window during wanderers.", BRD.JobID)] + [CustomComboInfo("Pooling Option", "84+ Pools Bloodletter charges to allow for optimum burst phases.", BRD.JobID)] BRD_Adv_Pooling = 3023, + [ParentCombo(BRD_AoE_AdvMode)] + [CustomComboInfo("Pooling Option", "84+ Pools Rain of death charges to allow for optimum burst phases.", BRD.JobID)] + BRD_AoE_Pooling = 3040, + [ParentCombo(BRD_IronJaws)] [CustomComboInfo("Iron Jaws Apex Option", "Adds Apex and Blast Arrow to Iron Jaws when available.", BRD.JobID)] BRD_IronJawsApex = 3024, @@ -717,7 +721,7 @@ public enum CustomComboPreset [ParentCombo(BRD_AoE_AdvMode)] [CustomComboInfo("AoE No Waste Option", "Adds enemy health checking on targetted mob for songs.\nThey will not be reapplied if less than specified.", BRD.JobID)] BRD_AoE_Adv_NoWaste = 3033, - // Last value = 3038 + // Last value = 3040 #endregion diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 170635e79..e77fd014c 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -84,7 +84,11 @@ public const string BRD_AoESecondWindThreshold = "BRD_AoESecondWindThreshold", BRD_VariantCure = "BRD_VariantCure"; } - + internal static class Traits + { + internal const ushort + EnhancedBloodletter = 445; + } #region Song status internal static bool SongIsNotNone(Song value) => value != Song.NONE; internal static bool SongIsNone(Song value) => value == Song.NONE; @@ -451,7 +455,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { uint rainOfDeathCharges = LevelChecked(RainOfDeath) ? GetRemainingCharges(RainOfDeath) : 0; - if (LevelChecked(WanderersMinuet)) + if (IsEnabled(CustomComboPreset.BRD_AoE_Pooling) && LevelChecked(WanderersMinuet) && TraitLevelChecked(Traits.EnhancedBloodletter)) { if (songWanderer) { @@ -755,7 +759,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { uint bloodletterCharges = GetRemainingCharges(Bloodletter); - if (IsEnabled(CustomComboPreset.BRD_Adv_Pooling) && LevelChecked(WanderersMinuet)) + if (IsEnabled(CustomComboPreset.BRD_Adv_Pooling) && LevelChecked(WanderersMinuet) && TraitLevelChecked(Traits.EnhancedBloodletter)) { if (songWanderer) { @@ -1076,7 +1080,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { uint rainOfDeathCharges = LevelChecked(RainOfDeath) ? GetRemainingCharges(RainOfDeath) : 0; - if (LevelChecked(WanderersMinuet)) + if (LevelChecked(WanderersMinuet) && TraitLevelChecked(Traits.EnhancedBloodletter)) { if (songWanderer) { @@ -1305,7 +1309,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { uint bloodletterCharges = GetRemainingCharges(Bloodletter); - if (LevelChecked(WanderersMinuet)) + if (LevelChecked(WanderersMinuet) && TraitLevelChecked(Traits.EnhancedBloodletter)) { if (songWanderer) { From a8d8a488944f4494e7447026186a7aeb8f22a433 Mon Sep 17 00:00:00 2001 From: ace Date: Wed, 28 Aug 2024 21:35:45 -0700 Subject: [PATCH 040/208] No Mercy HP% slider --- XIVSlothCombo/Combos/CustomComboPreset.cs | 4 ++-- XIVSlothCombo/Combos/PvE/GNB.cs | 12 ++++++++++-- XIVSlothCombo/Window/Functions/UserConfig.cs | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..b928e1094 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1594,7 +1594,7 @@ public enum CustomComboPreset [CustomComboInfo("Continuation Option", "Adds Continuation to Gnashing Fang when available.", GNB.JobID)] GNB_GF_Continuation = 7301, - [ConflictingCombos(GNB_ST_NoMercy)] + [ConflictingCombos(GNB_NM_Features)] [ParentCombo(GNB_GF_Features)] [CustomComboInfo("No Mercy Option", "Adds No Mercy to Gnashing Fang when available.", GNB.JobID)] GNB_GF_NoMercy = 7302, @@ -1652,7 +1652,7 @@ public enum CustomComboPreset #endregion #region No Mercy - [ConflictingCombos(GNB_ST_Simple, GNB_AoE_Simple, GNB_ST_NoMercy, GNB_AoE_NoMercy, GNB_GF_NoMercy)] + [ConflictingCombos(GNB_ST_Simple, GNB_AoE_Simple, GNB_GF_Features)] [ReplaceSkill(GNB.NoMercy)] [CustomComboInfo("No Mercy Features", "Collection of No Mercy related features.", GNB.JobID)] GNB_NM_Features = 7500, diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index c207360bb..50149e0e0 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -1,7 +1,9 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.PvE.Content; +using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; namespace XIVSlothCombo.Combos.PvE @@ -68,7 +70,11 @@ public static class Config { public const string GNB_VariantCure = "GNB_VariantCure"; + public static UserInt + GNB_ST_NoMercyStop = new("GNB_ST_NoMercy"), + GNB_AoE_NoMercyStop = new ("GNB_AoE_NoMercy"); } + internal class GNB_ST_SimpleMode : CustomCombo { @@ -327,6 +333,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var nmCD = GetCooldownRemainingTime(NoMercy); //NoMercy's cooldown; 60s total var bfCD = GetCooldownRemainingTime(Bloodfest); // Bloodfest's cooldown; 120s total float GCD = GetCooldown(KeenEdge).CooldownTotal; //2.5 is base SkS, but can work with 2.4x + int nmStop = PluginConfiguration.GetCustomIntValue(Config.GNB_ST_NoMercyStop); //Variant Cure if (IsEnabled(CustomComboPreset.GNB_Variant_Cure) && IsEnabled(Variant.VariantCure) @@ -341,7 +348,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //NoMercy if (IsEnabled(CustomComboPreset.GNB_ST_Advanced_CooldownsGroup) && IsEnabled(CustomComboPreset.GNB_ST_NoMercy)) { - if (ActionReady(NoMercy)) + if (ActionReady(NoMercy) && GetTargetHPPercent() >= nmStop) { if (CanWeave(actionID)) { @@ -888,6 +895,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var GunStep = GetJobGauge().AmmoComboStep; // For GnashingFang & (possibly) ReignCombo purposes var bfCD = GetCooldownRemainingTime(Bloodfest); // Bloodfest's cooldown; 120s total float GCD = GetCooldown(KeenEdge).CooldownTotal; //2.5 is base SkS, but can work with 2.4x + int nmStop = PluginConfiguration.GetCustomIntValue(Config.GNB_AoE_NoMercyStop); //Variant Cure if (IsEnabled(CustomComboPreset.GNB_Variant_Cure) && IsEnabled(Variant.VariantCure) && PlayerHealthPercentageHp() <= GetOptionValue(Config.GNB_VariantCure)) @@ -909,7 +917,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Variant.VariantUltimatum; //NoMercy - if (IsEnabled(CustomComboPreset.GNB_AoE_NoMercy) && ActionReady(NoMercy)) //use on CD + if (IsEnabled(CustomComboPreset.GNB_AoE_NoMercy) && ActionReady(NoMercy) && GetTargetHPPercent() > nmStop) //use on CD return NoMercy; //BowShock if (IsEnabled(CustomComboPreset.GNB_AoE_BowShock) && ActionReady(BowShock) && LevelChecked(BowShock) && HasEffect(Buffs.NoMercy)) //use on CD under NM diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..9895bba33 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1518,6 +1518,10 @@ internal static void Draw(CustomComboPreset preset, bool enabled) if (preset == CustomComboPreset.GNB_Variant_Cure) UserConfig.DrawSliderInt(1, 100, GNB.Config.GNB_VariantCure, "HP% to be at or under", 200); + if (preset == CustomComboPreset.GNB_ST_NoMercy) + UserConfig.DrawSliderInt(0, 10, GNB.Config.GNB_ST_NoMercyStop, "Disable Usage if Target HP% is below set value.\nTo Disable this, set to 0."); + if (preset == CustomComboPreset.GNB_AoE_NoMercy) + UserConfig.DrawSliderInt(0, 10, GNB.Config.GNB_AoE_NoMercyStop, "Disable Usage if Target HP% is below set value.\nTo Disable this, set to 0."); #endregion // ==================================================================================== From d0850180116fa3fc13bf7a4d08ada653b450560b Mon Sep 17 00:00:00 2001 From: ace Date: Thu, 29 Aug 2024 01:36:07 -0700 Subject: [PATCH 041/208] cleanup --- XIVSlothCombo/Combos/CustomComboPreset.cs | 44 +++++++++++------------ XIVSlothCombo/Combos/PvE/GNB.cs | 5 +-- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index b928e1094..4926c6caf 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1481,7 +1481,7 @@ public enum CustomComboPreset #region Advanced ST [ConflictingCombos(GNB_ST_Simple)] [ReplaceSkill(GNB.KeenEdge)] - [CustomComboInfo("Advanced Mode - Single Target", "Replace Keen Edge with its combo chain.\n Uses Burst Strike when you have 3 cartridges & your last combo action was Brutal Shell.", GNB.JobID)] + [CustomComboInfo("Advanced Mode - Single Target", "Replace Keen Edge with its combo chain.\nThis is the ideal selection for experienced users of the job.", GNB.JobID)] GNB_ST_Advanced = 7003, #region Lightning Shot @@ -1492,50 +1492,50 @@ public enum CustomComboPreset #region Gnashing Fang [ParentCombo(GNB_ST_Advanced)] - [CustomComboInfo("Continuation Option", "Adds Continuation to the main combo.\n 'Gnashing Fang Starter' option must be enabled or started manually.", GNB.JobID)] + [CustomComboInfo("Continuation Option", "Adds Continuation & Hypervelocity into the rotation.\n'Gnashing Fang' option must be enabled or started manually.", GNB.JobID)] GNB_ST_Continuation = 7005, [ParentCombo(GNB_ST_Continuation)] - [CustomComboInfo("Gnashing Fang Starter Option", "Begins Gnashing Fang for you on the main combo.", GNB.JobID)] + [CustomComboInfo("Gnashing Fang Option", "Adds Gnashing Fang combo into the rotation.", GNB.JobID)] GNB_ST_GnashingStarter = 7006, #endregion #region Cooldowns [ParentCombo(GNB_ST_Advanced)] - [CustomComboInfo("Cooldowns Option", "Adds various cooldowns to the main combo.", GNB.JobID)] + [CustomComboInfo("Cooldowns Option", "Adds various cooldowns into the rotation.", GNB.JobID)] GNB_ST_Advanced_CooldownsGroup = 7007, [ConflictingCombos(GNB_NM_Features)] [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("No Mercy Option", "Adds No Mercy to the main combo when at full ammo.", GNB.JobID)] + [CustomComboInfo("No Mercy Option", "Adds No Mercy into the rotation when appropriate.", GNB.JobID)] GNB_ST_NoMercy = 7008, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Danger/Blasting Zone Option", "Adds Danger/Blasting Zone to the main combo.", GNB.JobID)] + [CustomComboInfo("Danger/Blasting Zone Option", "Adds Danger/Blasting Zone into the rotation when available.", GNB.JobID)] GNB_ST_BlastingZone = 7009, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Bow Shock Option", "Adds Bow Shock to the main combo.", GNB.JobID)] + [CustomComboInfo("Bow Shock Option", "Adds Bow Shock into the rotation when appropriate.", GNB.JobID)] GNB_ST_BowShock = 7010, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Bloodfest Option", "Adds Bloodfest to the main combo when ammo is 0.", GNB.JobID)] + [CustomComboInfo("Bloodfest Option", "Adds Bloodfest into the rotation when appropriate.", GNB.JobID)] GNB_ST_Bloodfest = 7011, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Sonic Break Option", "Adds Sonic Break to the main combo.", GNB.JobID)] + [CustomComboInfo("Sonic Break Option", "Adds Sonic Break into the rotation when appropriate.", GNB.JobID)] GNB_ST_SonicBreak = 7012, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Double Down Option", "Adds Double Down to the main combo when under No Mercy buff.", GNB.JobID)] + [CustomComboInfo("Double Down Option", "Adds Double Down into the rotation when appropriate.", GNB.JobID)] GNB_ST_DoubleDown = 7013, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Reign combo Option", "Adds Reign/Noble/Lionheart to the main combo.", GNB.JobID)] + [CustomComboInfo("Reign combo Option", "Adds Reign/Noble/Lionheart into the rotation when appropriate.", GNB.JobID)] GNB_ST_Reign = 7014, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Burst Strike Option", "Adds Burst Strike and Hypervelocity (when available) to the main combo when under No Mercy and Gnashing Fang is over.", GNB.JobID)] + [CustomComboInfo("Burst Strike Option", "Adds Burst Strike into the rotation when appropriate.", GNB.JobID)] GNB_ST_BurstStrike = 7015, #endregion @@ -1544,44 +1544,44 @@ public enum CustomComboPreset #region Advanced AoE [ConflictingCombos(GNB_AoE_Simple)] [ReplaceSkill(GNB.DemonSlice)] - [CustomComboInfo("Advanced Mode - AoE", "Replace Demon Slice with its combo chain.", GNB.JobID)] + [CustomComboInfo("Advanced Mode - AoE", "Replace Demon Slice with its combo chain.\nThis is the ideal selection for experienced users of the job.", GNB.JobID)] GNB_AoE_Advanced = 7200, [ConflictingCombos(GNB_NM_Features)] [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("No Mercy Option", "Adds No Mercy to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("No Mercy Option", "Adds No Mercy into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_NoMercy = 7201, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Danger/Blasting Zone Option", "Adds Danger/Blasting Zone to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Danger/Blasting Zone Option", "Adds Danger/Blasting Zone into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_DangerZone = 7202, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Bow Shock Option", "Adds Bow Shock onto the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Bow Shock Option", "Adds Bow Shock oninto the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_BowShock = 7203, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Bloodfest Option", "Adds Bloodfest to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Bloodfest Option", "Adds Bloodfest into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_Bloodfest = 7204, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Sonic Break Option", "Adds Sonic Break to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Sonic Break Option", "Adds Sonic Break into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_SonicBreak = 7205, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Double Down Option", "Adds Double Down to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Double Down Option", "Adds Double Down into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_DoubleDown = 7206, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Reign Combo Option", "Adds Reign/Noble/LionHeart to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Reign Combo Option", "Adds Reign/Noble/LionHeart into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_Reign = 7207, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Fated Circle Option", "Adds Fated Circle to the AoE combo when appropriate.", GNB.JobID)] + [CustomComboInfo("Fated Circle Option", "Adds Fated Circle into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_FatedCircle = 7208, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Ammo Overcap Option", "Adds Fated Circle to the AoE combo when about to overcap.", GNB.JobID)] + [CustomComboInfo("Ammo Overcap Option", "Adds Fated Circle into the AoE rotation if you have max cartridges & your last action was Demon Slice.", GNB.JobID)] GNB_AoE_Overcap = 7209, #endregion diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index 50149e0e0..053a7c303 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -70,9 +70,10 @@ public static class Config { public const string GNB_VariantCure = "GNB_VariantCure"; + public static UserInt - GNB_ST_NoMercyStop = new("GNB_ST_NoMercy"), - GNB_AoE_NoMercyStop = new ("GNB_AoE_NoMercy"); + GNB_ST_NoMercyStop = new("GNB_ST_NoMercyStop"), + GNB_AoE_NoMercyStop = new ("GNB_AoE_NoMercyStop"); } From f6ccf81d53de64093fc09f8ee2564296fdf0c6c8 Mon Sep 17 00:00:00 2001 From: Kage Date: Thu, 29 Aug 2024 11:27:12 +0200 Subject: [PATCH 042/208] fix second weaving during hypercharge optimize reassemble --- XIVSlothCombo/Combos/PvE/MCH.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index 810e798c4..11ac35a5c 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -189,7 +189,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } // healing - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind) && !gauge.IsOverheated) return All.SecondWind; } @@ -203,7 +203,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); - if (ReassembledTools(ref actionID, gauge) && !gauge.IsOverheated) + if (ReassembledTools(ref actionID, gauge)) return actionID; if (LevelChecked(Excavator) && @@ -239,8 +239,8 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) // TOOLS!! Chainsaw Drill Air Anchor Excavator if (!gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && - !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(actionID) || !InCombat()) & - ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive) || + !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) & + ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || (LevelChecked(Chainsaw) && !LevelChecked(Excavator) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || (LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || (LevelChecked(Drill) && !LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) @@ -388,7 +388,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // healing if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && - PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind)) + PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind) && !gauge.IsOverheated) return All.SecondWind; } @@ -404,7 +404,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); - if (ReassembledTools(ref actionID, gauge) && !gauge.IsOverheated) + if (ReassembledTools(ref actionID, gauge)) return actionID; if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && @@ -448,7 +448,7 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) !gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) && GetRemainingCharges(Reassemble) > Config.MCH_ST_ReassemblePool && - ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive) || + ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || (Config.MCH_ST_Reassembled[1] && LevelChecked(Chainsaw) && (!LevelChecked(Excavator) || !Config.MCH_ST_Reassembled[0]) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || (Config.MCH_ST_Reassembled[2] && LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || (Config.MCH_ST_Reassembled[3] && LevelChecked(Drill) && (!LevelChecked(AirAnchor) || !Config.MCH_ST_Reassembled[2]) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) From 0acece2d49b9486f13819c613b036a4d45da413b Mon Sep 17 00:00:00 2001 From: edewen Date: Thu, 29 Aug 2024 17:57:18 -0400 Subject: [PATCH 043/208] Removed uncoded option Songs on ogcd. Was never actually coded in there, just a checkbox that doesnt work. --- XIVSlothCombo/Combos/CustomComboPreset.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 586f34076..ca4f55659 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -621,11 +621,7 @@ public enum CustomComboPreset [ParentCombo(BRD_ST_AdvMode)] [CustomComboInfo("Bard Songs Option", "This option adds the Bard's Songs to the Advanced Bard Feature.", BRD.JobID)] - BRD_Adv_Song = 3011, - - [ParentCombo(BRD_AoE_oGCD)] - [CustomComboInfo("Songs Option", "Adds Songs onto AoE oGCD Feature.", BRD.JobID)] - BRD_oGCDSongs = 3012, + BRD_Adv_Song = 3011, [ReplaceSkill(BRD.Barrage)] [CustomComboInfo("Bard Buffs Feature", "Adds Raging Strikes and Battle Voice onto Barrage.", BRD.JobID)] From 4dd00692963dfe703e2bd2411c8f8409a0ce2990 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:10:40 -0500 Subject: [PATCH 044/208] [SCH] Single Target Heal Priority Added priority system from Sage with Excogitation and Protraction Cleaned up SGEHelper while referencing it. --- XIVSlothCombo/Combos/CustomComboPreset.cs | 40 ++++++----- XIVSlothCombo/Combos/JobHelpers/SCH.cs | 72 ++++++++++++++++++++ XIVSlothCombo/Combos/JobHelpers/SGE.cs | 62 ++++++++--------- XIVSlothCombo/Combos/PvE/SCH.cs | 32 ++++++--- XIVSlothCombo/Combos/PvE/SGE.cs | 6 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 15 ++++ 6 files changed, 167 insertions(+), 60 deletions(-) create mode 100644 XIVSlothCombo/Combos/JobHelpers/SCH.cs diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..65d5a324a 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3826,25 +3826,33 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Single Target Heal Feature", "Change Physick into Adloquium, Lustrate, then Physick with below options:", SCH.JobID, 4)] SCH_ST_Heal = 16023, - [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Lucid Dreaming Weave Option", "Adds Lucid Dreaming when MP drops below slider value:", SCH.JobID, 1)] - SCH_ST_Heal_Lucid = 16024, + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Lucid Dreaming Weave Option", "Adds Lucid Dreaming when MP drops below slider value:", SCH.JobID, 1)] + SCH_ST_Heal_Lucid = 16024, - [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Aetherflow Weave Option", "Use Aetherflow when out of Aetherflow stacks.", SCH.JobID, 2)] - SCH_ST_Heal_Aetherflow = 16025, + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Aetherflow Weave Option", "Use Aetherflow when out of Aetherflow stacks.", SCH.JobID, 2)] + SCH_ST_Heal_Aetherflow = 16025, - [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Esuna Option", "Applies Esuna to your target if there is a cleansable debuff.", SGE.JobID, 3)] - SCH_ST_Heal_Esuna = 16026, + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Esuna Option", "Applies Esuna to your target if there is a cleansable debuff.", SGE.JobID, 3)] + SCH_ST_Heal_Esuna = 16026, - [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Adloquium Option", "Use Adloquium when missing Galvanize or target HP%% below:", SCH.JobID, 4)] - SCH_ST_Heal_Adloquium = 16027, + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Adloquium Option", "Use Adloquium when missing Galvanize or target HP%% below:", SCH.JobID, 4)] + SCH_ST_Heal_Adloquium = 16027, - [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Lustrate Option", "Use Lustrate when target HP%% below:", SCH.JobID, 5)] - SCH_ST_Heal_Lustrate = 16028, + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Lustrate Option", "Use Lustrate when target HP%% below:", SCH.JobID, 5)] + SCH_ST_Heal_Lustrate = 16028, + + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Excogitation Option", "Use Excogitation when target HP%% below:", SCH.JobID, 6)] + SCH_ST_Heal_Excogitation = 16038, + + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Protraction Option", "Use Protraction when target HP%% below:", SCH.JobID, 7)] + SCH_ST_Heal_Protraction = 16039, #endregion @@ -3891,7 +3899,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion - // Last value = 16037 + // Last value = 16039 #endregion diff --git a/XIVSlothCombo/Combos/JobHelpers/SCH.cs b/XIVSlothCombo/Combos/JobHelpers/SCH.cs new file mode 100644 index 000000000..ae33b7262 --- /dev/null +++ b/XIVSlothCombo/Combos/JobHelpers/SCH.cs @@ -0,0 +1,72 @@ +using static XIVSlothCombo.Combos.PvE.SCH; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.JobHelpers +{ + internal class SCHHelper + { + public static int GetMatchingConfigST(int i, out uint action, out bool enabled) + { + var healTarget = GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); + + switch (i) + { + case 0: + action = Lustrate; + enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Lustrate) && Gauge.HasAetherflow(); + return Config.SCH_ST_Heal_LustrateOption; + case 1: + action = Excogitation; + enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Excogitation) && (Gauge.HasAetherflow() || HasEffect(Buffs.Recitation)); + return Config.SCH_ST_Heal_ExcogitationOption; + case 2: + action = Protraction; + enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Protraction); + return Config.SCH_ST_Heal_ProtractionOption; + } + + enabled = false; + action = 0; + return 0; + } + + //public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) + //{ + // switch (i) + // { + // case 0: + // action = PvE.SGE.Kerachole; + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Kerachole) && (!PvE.SGE.Config.SGE_AoE_Heal_KeracholeTrait || (PvE.SGE.Config.SGE_AoE_Heal_KeracholeTrait && TraitLevelChecked(PvE.SGE.Traits.EnhancedKerachole))) && PvE.SGE.Gauge.HasAddersgall(); + // return 0; + // case 1: + // action = PvE.SGE.Ixochole; + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Ixochole) && PvE.SGE.Gauge.HasAddersgall(); + // return 0; + // case 2: + // action = OriginalHook(PvE.SGE.Physis); + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Physis); + // return 0; + // case 3: + // action = PvE.SGE.Holos; + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Holos); + // return 0; + // case 4: + // action = PvE.SGE.Panhaima; + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Panhaima); + // return 0; + // case 5: + // action = PvE.SGE.Pepsis; + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Pepsis) && FindEffect(PvE.SGE.Buffs.EukrasianPrognosis) is not null; + // return 0; + // case 6: + // action = PvE.SGE.Philosophia; + // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Philosophia); + // return 0; + // } + + // enabled = false; + // action = 0; + // return 0; + //} + } +} diff --git a/XIVSlothCombo/Combos/JobHelpers/SGE.cs b/XIVSlothCombo/Combos/JobHelpers/SGE.cs index 84425e8f3..8262df758 100644 --- a/XIVSlothCombo/Combos/JobHelpers/SGE.cs +++ b/XIVSlothCombo/Combos/JobHelpers/SGE.cs @@ -1,44 +1,44 @@ -using XIVSlothCombo.Combos.PvE; -using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Combos.PvE.SGE; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.JobHelpers { - internal class SGE : CustomComboFunctions + internal class SGEHelper { public static int GetMatchingConfigST(int i, out uint action, out bool enabled) { - var healTarget = GetHealTarget(PvE.SGE.Config.SGE_ST_Heal_Adv && PvE.SGE.Config.SGE_ST_Heal_UIMouseOver); + var healTarget = GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); switch (i) { case 0: - action = PvE.SGE.Soteria; + action = Soteria; enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Soteria); - return PvE.SGE.Config.SGE_ST_Heal_Soteria; + return Config.SGE_ST_Heal_Soteria; case 1: - action = PvE.SGE.Zoe; + action = Zoe; enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Zoe); - return PvE.SGE.Config.SGE_ST_Heal_Zoe; + return Config.SGE_ST_Heal_Zoe; case 2: - action = PvE.SGE.Pepsis; - enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Pepsis) && FindEffect(PvE.SGE.Buffs.EukrasianDiagnosis, healTarget, LocalPlayer?.GameObjectId) is not null; - return PvE.SGE.Config.SGE_ST_Heal_Pepsis; + action = Pepsis; + enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Pepsis) && FindEffect(Buffs.EukrasianDiagnosis, healTarget, LocalPlayer?.GameObjectId) is not null; + return Config.SGE_ST_Heal_Pepsis; case 3: - action = PvE.SGE.Taurochole; - enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Taurochole) && PvE.SGE.Gauge.HasAddersgall(); - return PvE.SGE.Config.SGE_ST_Heal_Taurochole; + action = Taurochole; + enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Taurochole) && Gauge.HasAddersgall(); + return Config.SGE_ST_Heal_Taurochole; case 4: - action = PvE.SGE.Haima; + action = Haima; enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Haima); - return PvE.SGE.Config.SGE_ST_Heal_Haima; + return Config.SGE_ST_Heal_Haima; case 5: - action = PvE.SGE.Krasis; + action = Krasis; enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Krasis); - return PvE.SGE.Config.SGE_ST_Heal_Krasis; + return Config.SGE_ST_Heal_Krasis; case 6: - action = PvE.SGE.Druochole; - enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Druochole) && PvE.SGE.Gauge.HasAddersgall(); - return PvE.SGE.Config.SGE_ST_Heal_Druochole; + action = Druochole; + enabled = IsEnabled(CustomComboPreset.SGE_ST_Heal_Druochole) && Gauge.HasAddersgall(); + return Config.SGE_ST_Heal_Druochole; } enabled = false; @@ -51,31 +51,31 @@ public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) switch (i) { case 0: - action = PvE.SGE.Kerachole; - enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Kerachole) && (!PvE.SGE.Config.SGE_AoE_Heal_KeracholeTrait || (PvE.SGE.Config.SGE_AoE_Heal_KeracholeTrait && TraitLevelChecked(PvE.SGE.Traits.EnhancedKerachole))) && PvE.SGE.Gauge.HasAddersgall(); + action = Kerachole; + enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Kerachole) && (!Config.SGE_AoE_Heal_KeracholeTrait || (Config.SGE_AoE_Heal_KeracholeTrait && TraitLevelChecked(Traits.EnhancedKerachole))) && Gauge.HasAddersgall(); return 0; case 1: - action = PvE.SGE.Ixochole; - enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Ixochole) && PvE.SGE.Gauge.HasAddersgall(); + action = Ixochole; + enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Ixochole) && Gauge.HasAddersgall(); return 0; case 2: - action = OriginalHook(PvE.SGE.Physis); + action = OriginalHook(Physis); enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Physis); return 0; case 3: - action = PvE.SGE.Holos; + action = Holos; enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Holos); return 0; case 4: - action = PvE.SGE.Panhaima; + action = Panhaima; enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Panhaima); return 0; case 5: - action = PvE.SGE.Pepsis; - enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Pepsis) && FindEffect(PvE.SGE.Buffs.EukrasianPrognosis) is not null; + action = Pepsis; + enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Pepsis) && FindEffect(Buffs.EukrasianPrognosis) is not null; return 0; case 6: - action = PvE.SGE.Philosophia; + action = Philosophia; enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Philosophia); return 0; } diff --git a/XIVSlothCombo/Combos/PvE/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH.cs index a47823d56..1d21ce35c 100644 --- a/XIVSlothCombo/Combos/PvE/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH.cs @@ -3,6 +3,7 @@ using Dalamud.Game.ClientState.Statuses; using System.Collections.Generic; using XIVSlothCombo.Combos.PvE.Content; +using static XIVSlothCombo.Combos.JobHelpers.SCHHelper; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; @@ -28,6 +29,7 @@ internal const uint Excogitation = 7434, Consolation = 16546, Resurrection = 173, + Protraction = 25867, // Offense Bio = 17864, @@ -93,9 +95,9 @@ internal static readonly Dictionary // Class Gauge - private static SCHGauge Gauge => CustomComboFunctions.GetJobGauge(); + internal static SCHGauge Gauge => CustomComboFunctions.GetJobGauge(); - private static bool HasAetherflow(this SCHGauge gauge) => (gauge.Aetherflow > 0); + internal static bool HasAetherflow(this SCHGauge gauge) => (gauge.Aetherflow > 0); internal enum OpenerState { @@ -130,7 +132,11 @@ public static UserInt SCH_ST_Heal_LucidOption = new("SCH_ST_Heal_LucidOption", 6500), SCH_ST_Heal_AdloquiumOption = new("SCH_ST_Heal_AdloquiumOption"), SCH_ST_Heal_LustrateOption = new("SCH_ST_Heal_LustrateOption"), + SCH_ST_Heal_ExcogitationOption = new("SCH_ST_Heal_ExcogitationOption"), + SCH_ST_Heal_ProtractionOption = new("SCH_ST_Heal_ProtractionOption"), SCH_ST_Heal_EsunaOption = new("SCH_ST_Heal_EsunaOption"); + public static UserIntArray + SCH_ST_Heals_Priority = new("SCH_ST_Heals_Priority"); public static UserBool SCH_ST_Heal_Adv = new("SCH_ST_Heal_Adv"), SCH_ST_Heal_UIMouseOver = new("SCH_ST_Heal_UIMouseOver"), @@ -572,6 +578,19 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim HasCleansableDebuff(healTarget)) return All.Esuna; + foreach (var prio in Config.SCH_ST_Heals_Priority.Items.OrderBy(x => x)) + { + var index = Config.SCH_ST_Heals_Priority.IndexOf(prio); + var config = GetMatchingConfigST(index, out var spell, out bool enabled); + + if (enabled) + { + if (GetTargetHPPercent(healTarget) <= config && + ActionReady(spell)) + return spell; + } + } + //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && @@ -579,15 +598,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { return OriginalHook(Adloquium); } - - //Cast Lustrate if you have Aetherflow and Target HP is below % - if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Lustrate) && - ActionReady(Lustrate) && - Gauge.HasAetherflow() && - GetTargetHPPercent(healTarget) <= Config.SCH_ST_Heal_LustrateOption) - { - return Lustrate; - } } return actionID; } diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE.cs index 8411987c0..940e03f67 100644 --- a/XIVSlothCombo/Combos/PvE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE.cs @@ -7,7 +7,9 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Combos.JobHelpers.SGEHelper; using XIVSlothCombo.Data; +using XIVSlothCombo.Combos.JobHelpers; namespace XIVSlothCombo.Combos.PvE { @@ -517,7 +519,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim foreach (var prio in Config.SGE_ST_Heals_Priority.Items.OrderBy(x => x)) { var index = Config.SGE_ST_Heals_Priority.IndexOf(prio); - var config = JobHelpers.SGE.GetMatchingConfigST(index, out var spell, out bool enabled); + var config = GetMatchingConfigST(index, out var spell, out bool enabled); if (enabled) { @@ -561,7 +563,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim foreach (var prio in Config.SGE_AoE_Heals_Priority.Items.OrderBy(x => x)) { var index = Config.SGE_AoE_Heals_Priority.IndexOf(prio); - var config = JobHelpers.SGE.GetMatchingConfigAoE(index, out var spell, out bool enabled); + var config = GetMatchingConfigAoE(index, out var spell, out bool enabled); if (enabled) { diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..c6430a2b2 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2231,7 +2231,22 @@ internal static void Draw(CustomComboPreset preset, bool enabled) UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_AdloquiumOption, "Use Adloquium on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); if (preset is CustomComboPreset.SCH_ST_Heal_Lustrate) + { UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_LustrateOption, "Start using when below HP %. Set to 100 to disable this check"); + UserConfig.DrawPriorityInput(SCH.Config.SCH_ST_Heals_Priority, 3, 0, $"{SCH.Lustrate.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SCH_ST_Heal_Excogitation) + { + UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_ExcogitationOption, "Start using when below HP %. Set to 100 to disable this check"); + UserConfig.DrawPriorityInput(SCH.Config.SCH_ST_Heals_Priority, 3, 1, $"{SCH.Excogitation.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SCH_ST_Heal_Protraction) + { + UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_ProtractionOption, "Start using when below HP %. Set to 100 to disable this check"); + UserConfig.DrawPriorityInput(SCH.Config.SCH_ST_Heals_Priority, 3, 2, $"{SCH.Protraction.ActionName()} Priority: "); + } if (preset is CustomComboPreset.SCH_ST_Heal_Esuna) UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); From c7269987b2a7b511a2f1b033b53b0ab22498365a Mon Sep 17 00:00:00 2001 From: Kage Date: Sat, 31 Aug 2024 10:57:15 +0200 Subject: [PATCH 045/208] make compatible for < 2.5 sks --- XIVSlothCombo/Combos/JobHelpers/MCH.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MCH.cs b/XIVSlothCombo/Combos/JobHelpers/MCH.cs index a8edc857b..8d5528569 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MCH.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MCH.cs @@ -288,7 +288,7 @@ public static bool UseQueen(MCHGauge gauge) return true; //even mins - if (BSUsed >= 2 && gauge.Battery == 100 && JustUsed(AirAnchor)) + if (BSUsed >= 2 && gauge.Battery == 100) return true; //odd mins 1st queen From 233737981f63a94658a1ff37ca1b9d1eaf0bebed Mon Sep 17 00:00:00 2001 From: ace Date: Sun, 1 Sep 2024 06:51:40 -0700 Subject: [PATCH 046/208] 2.14 Optimal Rotation --- XIVSlothCombo/Combos/PvE/SAM.cs | 191 +++++++++++++++++--------------- 1 file changed, 102 insertions(+), 89 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index a7b5d2e8b..97a07c2dc 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -221,21 +221,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool threeSen = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; float enemyHP = GetTargetHPPercent(); bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - float meikyostacks = GetBuffStacks(Buffs.MeikyoShisui); + float GCD = GetCooldown(Hakaze).CooldownTotal; if (actionID is Hakaze or Gyofu) { - if (IsEnabled(CustomComboPreset.SAM_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.SAM_VariantCure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.SAM_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanSpellWeave(actionID)) - return Variant.VariantRampart; - // Opener for SAM if (SAMOpener.DoFullOpener(ref actionID)) return actionID; @@ -245,15 +234,16 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return MeikyoShisui; //oGCDs - if (CanWeave(actionID)) + if (CanWeave(ActionWatching.LastWeaponskill)) { //Meikyo Features - if (!HasEffect(Buffs.MeikyoShisui) && - ActionReady(MeikyoShisui) && - GetCooldownRemainingTime(MeikyoShisui) <= 10 && - SAMHelper.SenCount < 3 && - !SAMHelper.ComboStarted) - return MeikyoShisui; + if (ActionReady(MeikyoShisui)) + { + if (OptimalMeikyo()) + return MeikyoShisui; + if (GetCooldownRemainingTime(MeikyoShisui) <= GCD * 3 && ComboTimer is 0) //Overcap protection for scuffed runs + return MeikyoShisui; + } //Ikishoten Features if (LevelChecked(Ikishoten)) @@ -274,38 +264,47 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Zanshin Usage if (LevelChecked(Zanshin) && gauge.Kenki >= 50 && CanWeave(actionID) && HasEffect(Buffs.ZanshinReady) && - (JustUsed(OgiNamikiri, 5f) || + (JustUsed(Higanbana, 7f) || GetBuffRemainingTime(Buffs.ZanshinReady) <= 6)) return Zanshin; if (LevelChecked(Shoha) && gauge.MeditationStacks is 3) return Shoha; - - if (LevelChecked(Shinten) && gauge.Kenki > 50 && - !HasEffect(Buffs.ZanshinReady) && - ((gauge.Kenki >= 50) || - (enemyHP <= 1))) - return Shinten; } + if (LevelChecked(Shinten) && gauge.Kenki > 50 && + !HasEffect(Buffs.ZanshinReady) && + gauge.Kenki >= 80) + return Shinten; + if (LevelChecked(Enpi) && !InMeleeRange() && HasBattleTarget()) return Enpi; - if (HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) + if (IsEnabled(CustomComboPreset.SAM_ST_CDs) && + HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) { //Ogi Namikiri Features - if (ActionReady(OgiNamikiri) && + if (!IsMoving && ActionReady(OgiNamikiri) && (JustUsed(Higanbana, 5f) || GetBuffRemainingTime(Buffs.OgiNamikiriReady) <= GCD) && (gauge.Kaeshi == Kaeshi.NAMIKIRI || HasEffect(Buffs.OgiNamikiriReady))) return OriginalHook(OgiNamikiri); // Iaijutsu Features if (LevelChecked(Iaijutsu)) { + if (HasEffect(Buffs.TendoKaeshiSetsugekkaReady)) + return OriginalHook(TsubameGaeshi); + if (LevelChecked(TsubameGaeshi) && HasEffect(Buffs.TsubameReady)) + { + if (GetCooldownRemainingTime(Senei) > 33 || + threeSen) + return OriginalHook(TsubameGaeshi); + } + if (!IsMoving && - ((oneSen && GetDebuffRemainingTime(Debuffs.Higanbana) <= 10) || + ((oneSen && enemyHP >= 1 && GetDebuffRemainingTime(Debuffs.Higanbana) <= 19 && JustUsed(Gekko, 3f) && JustUsed(MeikyoShisui, 15f)) || (twoSen && !LevelChecked(MidareSetsugekka)) || - (threeSen && LevelChecked(MidareSetsugekka)) || - (threeSen && LevelChecked(TendoSetsugekka) && !HasEffect(Buffs.TsubameReady)))) + (threeSen && + (LevelChecked(MidareSetsugekka) && !HasEffect(Buffs.TsubameReady))))) return OriginalHook(Iaijutsu); } } @@ -325,15 +324,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Yukikaze; } - // healing - - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) - return All.SecondWind; - - if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) - return All.Bloodbath; - - if (comboTime > 0) { if (lastComboMove is Hakaze or Gyofu && LevelChecked(Jinpu)) @@ -361,30 +351,45 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return actionID; } - public static bool GetUseMeikyo() + public static bool OptimalMeikyo() { int MeikyoUsed = ActionWatching.CombatActions.Count(x => x == MeikyoShisui); - var gauge = CustomComboFunctions.GetJobGauge(); bool oneSen = OriginalHook(Iaijutsu) is Higanbana; bool twoSen = OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken; bool threeSen = OriginalHook(Iaijutsu) is MidareSetsugekka or TendoSetsugekka; - if (CustomComboFunctions.ActionReady(MeikyoShisui)) + if (ActionReady(MeikyoShisui)) { - var usedMeikyo = MeikyoUsed % 20; - //1 and 2 min are #3 and #4, reset at 9 & 15 - if ((usedMeikyo is 3 or 4 or 9 or 10 or 15 or 16) && - threeSen) - return true; + var usedMeikyo = MeikyoUsed % 15; + //NOTE: Opener Meikyos don't count here for some reason per testing. On 6min, Meikyos 6 & 7 are used, so loop resets at 8. - // 3 and 4 min are #5 and #6, reset at 11 & 17 - if ((usedMeikyo is 5 or 6 or 11 or 12 or 17 or 18) && - twoSen) - return true; + if (GetCooldownRemainingTime(Ikishoten) is > 49 and < 71) //1min windows + { + if (usedMeikyo is 1 or 8 && + threeSen) + return true; + if (usedMeikyo is 3 or 10 && + twoSen) + return true; + if (usedMeikyo is 5 or 12 && + oneSen) + return true; + } + + if (GetCooldownRemainingTime(Ikishoten) > 80) //2min windows + { + if (usedMeikyo is 2 or 9 && + threeSen) + return true; + if (usedMeikyo is 4 or 11 && + twoSen) + return true; + if (usedMeikyo is 6 or 13 && + oneSen) + return true; + } - // 5 and 6 min are #7 and #8, reset at 13 & 19 - if ((usedMeikyo is 7 or 8 or 13 or 14 or 19 or 20) && - oneSen) + if (usedMeikyo is 7 or 14 && !HasEffect(Buffs.MeikyoShisui)) return true; } return false; @@ -407,7 +412,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim int kenkiOvercap = Config.SAM_ST_KenkiOvercapAmount; float shintenTreshhold = Config.SAM_ST_ExecuteThreshold; float HiganbanaThreshold = Config.SAM_ST_Higanbana_Threshold; - float meikyostacks = GetBuffStacks(Buffs.MeikyoShisui); float GCD = GetCooldown(Hakaze).CooldownTotal; if (actionID is Hakaze or Gyofu) @@ -442,20 +446,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.SAM_ST_CDs)) { //Meikyo Features - /* if (IsEnabled(CustomComboPreset.SAM_ST_CDs_MeikyoShisui) && - !HasEffect(Buffs.MeikyoShisui) && - ActionReady(MeikyoShisui) && - SAMHelper.SenCount > 0 && - !SAMHelper.ComboStarted) - return MeikyoShisui; - - if (GetUseMeikyo()) - return MeikyoShisui; */ - - if (ActionReady(MeikyoShisui) && meikyostacks is 0 && (oneSen || twoSen || threeSen) && - (JustUsed(KaeshiSetsugekka, 5f) && GetCooldownRemainingTime(Ikishoten) is >= 45 and <= 75) || //1min - (JustUsed(KaeshiSetsugekka, 5f) && GetCooldownRemainingTime(Ikishoten) is >= 105)) //2min - return MeikyoShisui; + if (IsEnabled(CustomComboPreset.SAM_ST_CDs_MeikyoShisui) && ActionReady(MeikyoShisui)) + { + if (OptimalMeikyo()) + return MeikyoShisui; + if (GetCooldownRemainingTime(MeikyoShisui) <= GCD * 3 && ComboTimer is 0) //Overcap protection for scuffed runs + return MeikyoShisui; + } //Ikishoten Features if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Ikishoten) && LevelChecked(Ikishoten)) @@ -513,11 +510,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Iaijutsu Features if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu) && LevelChecked(Iaijutsu)) { - if (LevelChecked(TsubameGaeshi) && HasEffect(Buffs.TsubameReady) && - (threeSen || GetDebuffRemainingTime(Debuffs.Higanbana) > 40)) - return OriginalHook(TsubameGaeshi); if (HasEffect(Buffs.TendoKaeshiSetsugekkaReady)) return OriginalHook(TsubameGaeshi); + if (LevelChecked(TsubameGaeshi) && HasEffect(Buffs.TsubameReady)) + { + if (GetCooldownRemainingTime(Senei) > 33 || + threeSen) + return OriginalHook(TsubameGaeshi); + } if ((!IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu_Movement) || (IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu_Movement) && !IsMoving)) && @@ -587,7 +587,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return actionID; } - public static bool GetUseMeikyo() + public static bool OptimalMeikyo() { int MeikyoUsed = ActionWatching.CombatActions.Count(x => x == MeikyoShisui); bool oneSen = OriginalHook(Iaijutsu) is Higanbana; @@ -597,27 +597,40 @@ public static bool GetUseMeikyo() if (ActionReady(MeikyoShisui)) { var usedMeikyo = MeikyoUsed % 15; - //1 and 2 min are #3 and #4, reset at 9 & 15 - if ((usedMeikyo is 1 or 2 or 7 or 8) && (GetCooldownRemainingTime(Ikishoten) > 45) && - threeSen) - return true; + //NOTE: Opener Meikyos don't count here for some reason per testing. On 6min, Meikyos 6 & 7 are used, so loop resets at 8. - // 3 and 4 min are #5 and #6, reset at 11 & 17 - if ((usedMeikyo is 3 or 4 or 9 or 10) && (GetCooldownRemainingTime(Ikishoten) > 45) && - twoSen) - return true; + if (GetCooldownRemainingTime(Ikishoten) is > 49 and < 71) //1min windows + { + if (usedMeikyo is 1 or 8 && + threeSen) + return true; + if (usedMeikyo is 3 or 10 && + twoSen) + return true; + if (usedMeikyo is 5 or 12 && + oneSen) + return true; + } - // 5 and 6 min are #7 and #8, reset at 13 & 19 - if ((usedMeikyo is 5 or 11) && (GetCooldownRemainingTime(Ikishoten) > 45) && - oneSen) - return true; - if ((usedMeikyo is 6 or 12) && - oneSen) + if (GetCooldownRemainingTime(Ikishoten) > 80) //2min windows + { + if (usedMeikyo is 2 or 9 && + threeSen) + return true; + if (usedMeikyo is 4 or 11 && + twoSen) + return true; + if (usedMeikyo is 6 or 13 && + oneSen) + return true; + } + + if (usedMeikyo is 7 or 14 && !HasEffect(Buffs.MeikyoShisui)) return true; + } return false; } - } internal class SAM_AoE_OkaCombo : CustomCombo From 6c7b7d9e3f98c968ab9c65d1dc53d6533eece3cd Mon Sep 17 00:00:00 2001 From: ace Date: Sun, 1 Sep 2024 07:01:33 -0700 Subject: [PATCH 047/208] . --- XIVSlothCombo/Combos/PvE/SAM.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index 97a07c2dc..b1270286f 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -241,7 +241,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (OptimalMeikyo()) return MeikyoShisui; - if (GetCooldownRemainingTime(MeikyoShisui) <= GCD * 3 && ComboTimer is 0) //Overcap protection for scuffed runs + if (GetCooldownRemainingTime(MeikyoShisui) <= GCD * 3 && ComboTimer is 0 && !HasEffect(Buffs.MeikyoShisui)) //Overcap protection for scuffed runs return MeikyoShisui; } @@ -450,7 +450,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (OptimalMeikyo()) return MeikyoShisui; - if (GetCooldownRemainingTime(MeikyoShisui) <= GCD * 3 && ComboTimer is 0) //Overcap protection for scuffed runs + if (GetCooldownRemainingTime(MeikyoShisui) <= GCD * 3 && ComboTimer is 0 && !HasEffect(Buffs.MeikyoShisui)) //Overcap protection for scuffed runs return MeikyoShisui; } From 9baeb57d82201c69755bfd2bf9a1553ab0677b1c Mon Sep 17 00:00:00 2001 From: ace Date: Sun, 1 Sep 2024 07:20:24 -0700 Subject: [PATCH 048/208] fixes --- XIVSlothCombo/Combos/CustomComboPreset.cs | 10 +++++++++- XIVSlothCombo/Combos/PvE/GNB.cs | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 4926c6caf..55b51da16 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1580,9 +1580,17 @@ public enum CustomComboPreset [CustomComboInfo("Fated Circle Option", "Adds Fated Circle into the AoE rotation when appropriate.", GNB.JobID)] GNB_AoE_FatedCircle = 7208, + [ParentCombo(GNB_AoE_FatedCircle)] + [CustomComboInfo("Burst Strike Option", "Adds Burst Strike into the AoE rotation if you do not have Fated Circle unlocked yet.", GNB.JobID)] + GNB_AoE_noFatedCircle = 7209, + [ParentCombo(GNB_AoE_Advanced)] [CustomComboInfo("Ammo Overcap Option", "Adds Fated Circle into the AoE rotation if you have max cartridges & your last action was Demon Slice.", GNB.JobID)] - GNB_AoE_Overcap = 7209, + GNB_AoE_Overcap = 7210, + + [ParentCombo(GNB_AoE_Overcap)] + [CustomComboInfo("Ammo Overcap Burst Strike Option", "Adds Burst Strike into the AoE rotation if you have max cartridges, your last action was Demon Slice, & you do not have Fated Circle unlocked yet.", GNB.JobID)] + GNB_AoE_BSOvercap = 7211, #endregion #region Gnashing Fang diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index 053a7c303..6f7e6ed43 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -952,7 +952,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ((IsEnabled(CustomComboPreset.GNB_AoE_FatedCircle) && HasEffect(Buffs.NoMercy) && !ActionReady(DoubleDown) && GunStep == 0) || //use when under NM after DD & ignores GF (IsEnabled(CustomComboPreset.GNB_AoE_Bloodfest) && bfCD < 6))) // Bloodfest prep return FatedCircle; - if (Ammo > 0 && !LevelChecked(FatedCircle) && LevelChecked(BurstStrike) && + if (IsEnabled(CustomComboPreset.GNB_AoE_noFatedCircle) && Ammo > 0 && !LevelChecked(FatedCircle) && LevelChecked(BurstStrike) && (HasEffect(Buffs.NoMercy) && GunStep == 0)) // Bloodfest prep return BurstStrike; } @@ -964,9 +964,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (Ammo == MaxCartridges(level)) { - if (LevelChecked(FatedCircle)) + if (IsEnabled(CustomComboPreset.GNB_AoE_Overcap) && LevelChecked(FatedCircle)) return FatedCircle; - if (!LevelChecked(FatedCircle)) + if (IsEnabled(CustomComboPreset.GNB_AoE_BSOvercap) && !LevelChecked(FatedCircle)) return BurstStrike; } if (Ammo != MaxCartridges(level)) From 14c70d58f4e1bb726de14a2f84120cbb2b137ab9 Mon Sep 17 00:00:00 2001 From: ace Date: Sun, 1 Sep 2024 07:51:33 -0700 Subject: [PATCH 049/208] Iajutsu fixes --- XIVSlothCombo/Combos/PvE/SAM.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index b1270286f..82a7fa0e4 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -945,12 +945,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ActionReady(Shoha) && gauge.MeditationStacks is 3 && CanWeave(actionID)) return Shoha; - if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_OgiNamikiri) && - ActionReady(OgiNamikiri) && (gauge.Kaeshi is Kaeshi.NAMIKIRI || HasEffect(Buffs.OgiNamikiriReady))) + if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_OgiNamikiri) && + LevelChecked(OgiNamikiri) && HasEffect(Buffs.OgiNamikiriReady)) return OriginalHook(OgiNamikiri); - if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_TsubameGaeshi) && - ActionReady(TsubameGaeshi) && (gauge.Kaeshi != Kaeshi.NONE || WasLastWeaponskill(TendoSetsugekka))) + if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_TsubameGaeshi) && + ((LevelChecked(TsubameGaeshi) && HasEffect(Buffs.TsubameReady)) || (LevelChecked(TendoKaeshiSetsugekka) && HasEffect(Buffs.TendoKaeshiSetsugekkaReady)))) return OriginalHook(TsubameGaeshi); } return actionID; From fc9f594d973fedcb4f5ede02f337307fa0641101 Mon Sep 17 00:00:00 2001 From: ace Date: Sun, 1 Sep 2024 08:15:40 -0700 Subject: [PATCH 050/208] . --- XIVSlothCombo/Combos/CustomComboPreset.cs | 1 - XIVSlothCombo/Combos/JobHelpers/SAM.cs | 67 +++++++++++------------ XIVSlothCombo/Combos/PvE/SAM.cs | 3 - 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..9e6fe74ed 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1,7 +1,6 @@ using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Combos.PvP; -using static XIVSlothCombo.Combos.PvE.BRD; namespace XIVSlothCombo.Combos { diff --git a/XIVSlothCombo/Combos/JobHelpers/SAM.cs b/XIVSlothCombo/Combos/JobHelpers/SAM.cs index 3b863a0c2..4ebe67090 100644 --- a/XIVSlothCombo/Combos/JobHelpers/SAM.cs +++ b/XIVSlothCombo/Combos/JobHelpers/SAM.cs @@ -1,8 +1,6 @@ -using Dalamud.Game.ClientState.JobGauge.Enums; -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; -using System.Linq; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; @@ -162,53 +160,50 @@ private bool DoOpener(ref uint actionID) if (CustomComboFunctions.WasLastAction(MeikyoShisui) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = MeikyoShisui; - if (CustomComboFunctions.WasLastAction(All.TrueNorth) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = All.TrueNorth; + if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = Gekko; - if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = Gekko; + if (CustomComboFunctions.WasLastAction(Zanshin) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = Zanshin; - if (CustomComboFunctions.WasLastAction(Zanshin) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Zanshin; + if (CustomComboFunctions.WasLastAction(Higanbana) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = Higanbana; - if (CustomComboFunctions.WasLastAction(Higanbana) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = Higanbana; + if (CustomComboFunctions.WasLastAction(OgiNamikiri) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = OgiNamikiri; - if (CustomComboFunctions.WasLastAction(OgiNamikiri) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = OgiNamikiri; + if (CustomComboFunctions.WasLastAction(Shoha) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = Shoha; - if (CustomComboFunctions.WasLastAction(Shoha) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = Shoha; + if (CustomComboFunctions.WasLastAction(KaeshiNamikiri) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = KaeshiNamikiri; - if (CustomComboFunctions.WasLastAction(KaeshiNamikiri) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = KaeshiNamikiri; + if (CustomComboFunctions.WasLastAction(Kasha) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = Kasha; - if (CustomComboFunctions.WasLastAction(Kasha) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = Kasha; + if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = Shinten; - if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = Shinten; + if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = Gekko; - if (CustomComboFunctions.WasLastAction(Gekko) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Gekko; + if (CustomComboFunctions.WasLastAction(Gyoten) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = Gyoten; - if (CustomComboFunctions.WasLastAction(Gyoten) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Gyoten; + if (CustomComboFunctions.WasLastAction(Gyofu) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = Gyofu; - if (CustomComboFunctions.WasLastAction(Gyofu) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = Gyofu; + if (CustomComboFunctions.WasLastAction(Yukikaze) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = Yukikaze; - if (CustomComboFunctions.WasLastAction(Yukikaze) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = Yukikaze; + if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = Shinten; - if (CustomComboFunctions.WasLastAction(Shinten) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = Shinten; + if (CustomComboFunctions.WasLastAction(TendoSetsugekka) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = TendoSetsugekka; - if (CustomComboFunctions.WasLastAction(TendoSetsugekka) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = TendoSetsugekka; - - if (CustomComboFunctions.WasLastAction(TendoKaeshiSetsugekka) && OpenerStep == 24) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 24) actionID = TendoKaeshiSetsugekka; + if (CustomComboFunctions.WasLastAction(TendoKaeshiSetsugekka) && OpenerStep == 23) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 23) actionID = TendoKaeshiSetsugekka; if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index 82a7fa0e4..6af8b7c8a 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -1,8 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.JobGauge.Types; -using ECommons.DalamudServices; -using FFXIVClientStructs.FFXIV.Component.GUI; -using Lumina.Excel.GeneratedSheets2; using System; using System.Linq; using XIVSlothCombo.Combos.JobHelpers; From be446ef647b3c563af56df74b1e1d6b855c2e65d Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 1 Sep 2024 20:42:16 +0100 Subject: [PATCH 051/208] AutoRot WIP --- .../Attributes/ReplaceSkillAttribute.cs | 2 + .../AutoRotation/AutoRotationConfig.cs | 27 ++ .../AutoRotation/AutoRotationController.cs | 227 ++++++++++++++++ XIVSlothCombo/AutoRotation/RotationMode.cs | 38 +++ XIVSlothCombo/Combos/CustomComboPreset.cs | 4 + XIVSlothCombo/Combos/JobHelpers/MNK.cs | 7 +- XIVSlothCombo/Combos/JobHelpers/PCT.cs | 2 +- XIVSlothCombo/Combos/PvE/AST.cs | 2 +- XIVSlothCombo/Combos/PvE/BLU.cs | 2 +- XIVSlothCombo/Combos/PvE/MNK.cs | 249 +++++++++--------- XIVSlothCombo/Core/IconReplacer.cs | 15 +- XIVSlothCombo/Core/PluginConfiguration.cs | 14 +- XIVSlothCombo/CustomCombo/CustomCombo.cs | 9 +- XIVSlothCombo/CustomCombo/Functions/Action.cs | 9 +- XIVSlothCombo/CustomCombo/Functions/Misc.cs | 2 +- XIVSlothCombo/CustomCombo/Functions/Party.cs | 14 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 8 +- XIVSlothCombo/Data/ActionWatching.cs | 2 +- XIVSlothCombo/Window/ConfigWindow.cs | 13 +- XIVSlothCombo/Window/Functions/Presets.cs | 39 ++- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 66 +++++ XIVSlothCombo/Window/Tabs/Debug.cs | 7 + XIVSlothCombo/Window/Tabs/Settings.cs | 3 + XIVSlothCombo/XIVSlothCombo.cs | 13 + 24 files changed, 612 insertions(+), 162 deletions(-) create mode 100644 XIVSlothCombo/AutoRotation/AutoRotationConfig.cs create mode 100644 XIVSlothCombo/AutoRotation/AutoRotationController.cs create mode 100644 XIVSlothCombo/AutoRotation/RotationMode.cs create mode 100644 XIVSlothCombo/Window/Tabs/AutoRotationTab.cs diff --git a/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs b/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs index d81d2b3cc..44fff0b36 100644 --- a/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs +++ b/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs @@ -16,12 +16,14 @@ internal ReplaceSkillAttribute(params uint[] actionIDs) { if (ActionWatching.ActionSheet.TryGetValue(id, out var action) && action != null) { + ActionIDs.Add(id); ActionNames.Add($"{action.Name}"); ActionIcons.Add(action.Icon); } } } + internal List ActionIDs { get; set; } = []; internal List ActionNames { get; set; } = []; internal List ActionIcons { get; set; } = []; diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs new file mode 100644 index 000000000..645c38574 --- /dev/null +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace XIVSlothCombo.AutoRotation +{ + public class AutoRotationConfig + { + public bool Enabled; + public bool InCombatOnly = false; + public DPSRotationMode DPSRotationMode; + public HealerRotationMode HealerRotationMode; + public TankRotationMode TankRotationMode; + public int DPSAoETargets = 2; + public int HealerAoETargets = 2; + public int TankAoETargets = 2; + public HealerSettings HealerSettings = new(); + } + + public class HealerSettings + { + public int SingleTargetHPP = 70; + public int AoETargetHPP = 60; + } +} diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs new file mode 100644 index 000000000..f6bf2c8c5 --- /dev/null +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -0,0 +1,227 @@ +using Dalamud.Game.ClientState.Objects.Types; +using ECommons.DalamudServices; +using ECommons.GameFunctions; +using ECommons.GameHelpers; +using ECommons.Throttlers; +using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.Game.Object; +using ImGuizmoNET; +using System; +using System.Linq; +using XIVSlothCombo.Combos; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Services; +using XIVSlothCombo.Window.Functions; +using static FFXIVClientStructs.FFXIV.Client.UI.RaptureAtkHistory.Delegates; +using Action = Lumina.Excel.GeneratedSheets.Action; + +namespace XIVSlothCombo.AutoRotation +{ + internal unsafe static class AutoRotationController + { + internal static void Run() + { + if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) + return; + + if (!EzThrottler.Throttle("AutoRotController", 50)) + return; + + foreach (var preset in Service.Configuration.AutoActions.OrderBy(x => Presets.Attributes[x.Key].AutoAction.IsHeal)) + { + if (!CustomComboFunctions.IsEnabled(preset.Key) || !preset.Value) continue; + + var attributes = Presets.Attributes[preset.Key]; + var action = attributes.AutoAction; + var gameAct = attributes.ReplaceSkill.ActionIDs.First(); + var sheetAct = Svc.Data.GetExcelSheet().GetRow(gameAct); + var classId = CustomComboFunctions.JobIDs.JobToClass((uint)Player.Job); + if ((byte)Player.Job != attributes.CustomComboInfo.JobID && (byte)Player.Job != classId) + continue; + + var healTarget = AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode); + + if (action.IsHeal && healTarget is not null) + { + AutomateHealing(preset.Key, attributes, gameAct); + return; + } + + //if (Player.Object.GetRole() is CombatRole.Tank) + //{ + // AutomateTanking(preset.Key, attributes, gameAct); + // continue; + //} + + if (healTarget == null) + AutomateDPS(preset.Key, attributes, gameAct); + } + + + } + + private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + { + if (attributes.AutoAction.IsAoE) + { + + } + else + { + var mode = Service.Configuration.RotationConfig.DPSRotationMode; + return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); + } + return false; + } + + private static void AutomateTanking(CustomComboPreset key, Presets.PresetAttributes attributes, uint gameAct) + { + if (attributes.AutoAction.IsAoE) + { + + } + else + { + + } + } + + private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + { + if (attributes.AutoAction.IsAoE) + { + + } + else + { + var mode = Service.Configuration.RotationConfig.HealerRotationMode; + return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); + } + return false; + } + + public static class AutoRotationHelper + { + public static IGameObject? GetSingleTarget(System.Enum rotationMode) + { + if (rotationMode is DPSRotationMode dpsmode) + { + IGameObject? target = dpsmode switch + { + DPSRotationMode.Manual => Svc.Targets.Target, + DPSRotationMode.Highest_Max => DPSTargeting.GetHighestMaxTarget(), + DPSRotationMode.Lowest_Max => DPSTargeting.GetLowestMaxTarget(), + DPSRotationMode.Highest_Current => DPSTargeting.GetHighestCurrentTarget(), + DPSRotationMode.Lowest_Current => DPSTargeting.GetLowestCurrentTarget(), + DPSRotationMode.Tank_Target => DPSTargeting.GetTankTarget(), + }; + return target; + } + if (rotationMode is HealerRotationMode healermode) + { + if (Player.Object.GetRole() != CombatRole.Healer) return null; + IGameObject? target = healermode switch + { + HealerRotationMode.Manual => Svc.Targets.Target, + HealerRotationMode.Highest_Current => HealerTargeting.GetHighestCurrent(), + HealerRotationMode.Lowest_Current => HealerTargeting.GetLowestCurrent(), + }; + + return target; + } + if (rotationMode is TankRotationMode tankmode) + { + + } + + return null; + } + + public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + { + + return false; + } + + public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + { + var target = AutoRotationHelper.GetSingleTarget(mode); + if (target is null) + return false; + + var outAct = attributes.ReplaceSkill.ActionIDs.First(); + foreach (var actToCheck in attributes.ReplaceSkill.ActionIDs) + { + var customCombo = Service.IconReplacer.CustomCombos.First(x => x.Preset == preset); + if (customCombo.TryInvoke(actToCheck, (byte)Player.Level, ActionManager.Instance()->Combo.Action, ActionManager.Instance()->Combo.Timer, out var changedAct, target)) + { + outAct = changedAct; + break; + } + } + + var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); + if (CustomComboFunctions.IsMoving && castTime > 0) + return false; + + var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, (GameObject*)target.Address) != 562; + if (inRange) + { + ActionManager.Instance()->UseAction(ActionType.Action, outAct, target.GameObjectId); + return true; + } + + return false; + } + } + + public static class DPSTargeting + { + public static IGameObject? GetTankTarget() + { + var tank = Svc.Party.Where(x => x is IBattleChara chara && chara.GetRole() == CombatRole.Tank).FirstOrDefault(); + if (tank == null) + return null; + + return tank.GameObject.TargetObject; + } + + public static IGameObject? GetLowestCurrentTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderBy(x => (x as IBattleChara).CurrentHp).FirstOrDefault(); + } + + public static IGameObject? GetHighestCurrentTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => (x as IBattleChara).CurrentHp).FirstOrDefault(); + } + + public static IGameObject? GetLowestMaxTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderBy(x => (x as IBattleChara).MaxHp).FirstOrDefault(); + } + + public static IGameObject? GetHighestMaxTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => (x as IBattleChara).MaxHp).FirstOrDefault(); + } + } + + public static class HealerTargeting + { + internal static IGameObject? GetHighestCurrent() + { + if (CustomComboFunctions.GetPartyMembers().Count == 0) return Player.Object; + var target = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP).OrderByDescending(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + return target; + } + + internal static IGameObject? GetLowestCurrent() + { + if (CustomComboFunctions.GetPartyMembers().Count == 0) return Player.Object; + var target = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP).OrderBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + return target; + } + } + } +} diff --git a/XIVSlothCombo/AutoRotation/RotationMode.cs b/XIVSlothCombo/AutoRotation/RotationMode.cs new file mode 100644 index 000000000..a3a6ef35c --- /dev/null +++ b/XIVSlothCombo/AutoRotation/RotationMode.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace XIVSlothCombo.AutoRotation +{ + public enum DPSRotationMode + { + Manual, + Highest_Max, + Lowest_Max, + Highest_Current, + Lowest_Current, + Tank_Target, + } + + public enum HealerRotationMode + { + Manual, + Highest_Current, + Lowest_Current, + //Self_Priority, + //Tank_Priority, + //Healer_Priority, + //DPS_Priority, + } + + public enum TankRotationMode + { + Manual, + Highest_Max, + Lowest_Max, + Highest_Current, + Lowest_Current, + } +} diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 7261fbbd6..d9f1b9272 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -177,6 +177,7 @@ public enum CustomComboPreset #region ASTROLOGIAN #region ST DPS + [AutoAction(false, false)] [ReplaceSkill(AST.Malefic, AST.Malefic2, AST.Malefic3, AST.Malefic4, AST.FallMalefic, AST.Combust, AST.Combust2, AST.Combust3)] [CustomComboInfo("Single Target DPS Feature", "Replaces Malefic or Combust with options below", AST.JobID, 1)] AST_ST_DPS = 1004, @@ -225,6 +226,7 @@ public enum CustomComboPreset #endregion #region AOE DPS + [AutoAction(true, false)] [ReplaceSkill(AST.Gravity, AST.Gravity2)] [CustomComboInfo("AoE DPS Feature", "Replaces Gravity with options below", AST.JobID, 2)] AST_AOE_DPS = 1041, @@ -265,6 +267,7 @@ public enum CustomComboPreset #endregion #region Healing + [AutoAction(false, true)] [ReplaceSkill(AST.Benefic2)] [CustomComboInfo("Simple Heals (Single Target)", "Replaces Benefic II with a one button healing replacement.", AST.JobID, 3)] AST_ST_SimpleHeals = 1023, @@ -305,6 +308,7 @@ public enum CustomComboPreset [CustomComboInfo("The Bole Option", "Adds The Bole (Reduced Damage) when the card has been drawn", AST.JobID)] AST_ST_SimpleHeals_Bole = 1050, + [AutoAction(true,true)] [ReplaceSkill(AST.Helios, AST.AspectedHelios, AST.HeliosConjuction)] [CustomComboInfo("Simple Heals (AoE)", "Replaces Aspected Helios or Helios with a one button healing replacement.", AST.JobID, 4)] AST_AoE_SimpleHeals_AspectedHelios = 1010, diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index 93bbe544d..564013dd3 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -5,6 +5,7 @@ using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; +using XIVSlothCombo.Extensions; namespace XIVSlothCombo.Combos.JobHelpers { @@ -15,7 +16,7 @@ public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnable { if (CustomComboFunctions.HasEffect(Buffs.OpoOpoForm) || CustomComboFunctions.HasEffect(Buffs.FormlessFist)) { - if (Gauge.OpoOpoFury == 0) + if (Gauge.OpoOpoFury == 0 && DragonKick.LevelChecked()) { if (CustomComboFunctions.LevelChecked(DragonKick)) return DragonKick; @@ -28,7 +29,7 @@ public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnable if (CustomComboFunctions.HasEffect(Buffs.RaptorForm)) { - if (Gauge.RaptorFury == 0) + if (Gauge.RaptorFury == 0 && TwinSnakes.LevelChecked()) { if (CustomComboFunctions.LevelChecked(TwinSnakes)) return TwinSnakes; @@ -42,7 +43,7 @@ public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnable if (CustomComboFunctions.HasEffect(Buffs.CoeurlForm)) { - if (Gauge.CoeurlFury == 0) + if (Gauge.CoeurlFury == 0 && Demolish.LevelChecked()) { if (!CustomComboFunctions.OnTargetsRear() && CustomComboFunctions.TargetNeedsPositionals() diff --git a/XIVSlothCombo/Combos/JobHelpers/PCT.cs b/XIVSlothCombo/Combos/JobHelpers/PCT.cs index e7761ca6f..babcde23a 100644 --- a/XIVSlothCombo/Combos/JobHelpers/PCT.cs +++ b/XIVSlothCombo/Combos/JobHelpers/PCT.cs @@ -214,7 +214,7 @@ private bool DoOpener(ref uint actionID) if (CustomComboFunctions.WasLastAction(RainbowDrip) && OpenerStep == adjustedStep) OpenerStep++; else if (OpenerStep == adjustedStep) actionID = RainbowDrip; - Svc.Log.Debug($"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); + //Svc.Log.Debug($"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); if (ActionWatching.TimeSinceLastAction.TotalSeconds > 4) { diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 2d8562149..98b4932f5 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -554,7 +554,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var canArrow = (Config.AST_ST_SimpleHeals_WeaveArrow && CanSpellWeave(actionID)) || !Config.AST_ST_SimpleHeals_WeaveArrow; //Grab our target (Soft->Hard->Self) - IGameObject? healTarget = GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget != null ? this.OptionalTarget : GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Esuna) && ActionReady(All.Esuna) && GetTargetHPPercent(healTarget) >= Config.AST_ST_SimpleHeals_Esuna && diff --git a/XIVSlothCombo/Combos/PvE/BLU.cs b/XIVSlothCombo/Combos/PvE/BLU.cs index 1b049cfc0..a439cd633 100644 --- a/XIVSlothCombo/Combos/PvE/BLU.cs +++ b/XIVSlothCombo/Combos/PvE/BLU.cs @@ -171,7 +171,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (actionID is FinalSting) { - if (IsEnabled(CustomComboPreset.BLU_SoloMode) && HasCondition(ConditionFlag.BoundByDuty) && !HasEffect(Buffs.BasicInstinct) && GetPartyMembers().Length == 0 && IsSpellActive(BasicInstinct)) + if (IsEnabled(CustomComboPreset.BLU_SoloMode) && HasCondition(ConditionFlag.BoundByDuty) && !HasEffect(Buffs.BasicInstinct) && GetPartyMembers().Count == 0 && IsSpellActive(BasicInstinct)) return BasicInstinct; if (!HasEffect(Buffs.Whistle) && IsSpellActive(Whistle) && !WasLastAction(Whistle)) return Whistle; diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index cba7252be..4959a1934 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -111,7 +111,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // OGCDs - if (inCombat && canWeave) + if (canWeave) { if (IsEnabled(Variant.VariantRampart) && IsOffCooldown(Variant.VariantRampart)) @@ -157,80 +157,79 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // GCDs - if (inCombat) + + // Ensure usage if buff is almost depleted. + if (HasEffect(Buffs.FiresRumination) && GetBuffRemainingTime(Buffs.FiresRumination) < 4) { - // Ensure usage if buff is almost depleted. - if (HasEffect(Buffs.FiresRumination) && GetBuffRemainingTime(Buffs.FiresRumination) < 4) - { - return FiresReply; - } + return FiresReply; + } - if (HasEffect(Buffs.WindsRumination) && GetBuffRemainingTime(Buffs.WindsRumination) < 4) - { - return WindsReply; - } + if (HasEffect(Buffs.WindsRumination) && GetBuffRemainingTime(Buffs.WindsRumination) < 4) + { + return WindsReply; + } - if (HasEffect(Buffs.FormlessFist)) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + if (HasEffect(Buffs.FormlessFist)) + { + return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); + } - // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) - { - return OriginalHook(MasterfulBlitz); - } + // Masterful Blitz + if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) + { + return OriginalHook(MasterfulBlitz); + } - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) - { - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); - int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); - int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) + { + bool solarNadi = Gauge.Nadi == Nadi.SOLAR; + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); + int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); + int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); - #region Open Solar - if (!solarNadi && !bothNadisOpen) + #region Open Solar + if (!solarNadi && !bothNadisOpen) + { + if (coeurlChakra == 0) { - if (coeurlChakra == 0) - { - return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); - } - else if (raptorChakra == 0) - { - return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); - } - else if (opoOpoChakra == 0) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); } - #endregion - #region Open Lunar - if (solarNadi || lunarNadi || bothNadisOpen) + else if (raptorChakra == 0) + { + return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); + } + else if (opoOpoChakra == 0) { return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); } - #endregion } - - if (HasEffect(Buffs.WindsRumination)) + #endregion + #region Open Lunar + if (solarNadi || lunarNadi || bothNadisOpen) { - return WindsReply; + return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); } + #endregion + } - if (HasEffect(Buffs.FiresRumination) - && !HasEffect(Buffs.PerfectBalance) - && !HasEffect(Buffs.FormlessFist) - && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick))) - { - return FiresReply; - } + if (HasEffect(Buffs.WindsRumination)) + { + return WindsReply; + } - // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID); + if (HasEffect(Buffs.FiresRumination) + && !HasEffect(Buffs.PerfectBalance) + && !HasEffect(Buffs.FormlessFist) + && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick))) + { + return FiresReply; } + + // Standard Beast Chakras + return MNKHelper.DetermineCoreAbility(actionID); + } return actionID; @@ -268,7 +267,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb return Variant.VariantCure; // OGCDs - if (inCombat && canWeave) + if (canWeave) { if (IsEnabled(CustomComboPreset.MNK_Variant_Rampart) && IsEnabled(Variant.VariantRampart) && @@ -328,91 +327,89 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // GCDs - if (inCombat) + // Ensure usage if buff is almost depleted. + if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) + && HasEffect(Buffs.FiresRumination) + && GetBuffRemainingTime(Buffs.FiresRumination) < 4) { - // Ensure usage if buff is almost depleted. - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) - && HasEffect(Buffs.FiresRumination) - && GetBuffRemainingTime(Buffs.FiresRumination) < 4) - { - return FiresReply; - } + return FiresReply; + } - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) - && HasEffect(Buffs.WindsRumination) - && GetBuffRemainingTime(Buffs.WindsRumination) < 4) - { - return WindsReply; - } + if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) + && HasEffect(Buffs.WindsRumination) + && GetBuffRemainingTime(Buffs.WindsRumination) < 4) + { + return WindsReply; + } - if (HasEffect(Buffs.FormlessFist)) + if (HasEffect(Buffs.FormlessFist)) + { + return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); + } + + if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) + { + // Masterful Blitz + if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); + return OriginalHook(MasterfulBlitz); } - if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) { - // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) - { - return OriginalHook(MasterfulBlitz); - } + bool solarNadi = Gauge.Nadi == Nadi.SOLAR; + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); + int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); + int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) + #region Open Solar + if (!solarNadi && !bothNadisOpen) { - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); - int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); - int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); - - #region Open Solar - if (!solarNadi && !bothNadisOpen) + if (coeurlChakra == 0) { - if (coeurlChakra == 0) - { - return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); - } - else if (raptorChakra == 0) - { - return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); - } - else if (opoOpoChakra == 0) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); } - #endregion - #region Open Lunar - if (solarNadi || lunarNadi || bothNadisOpen) + else if (raptorChakra == 0) + { + return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); + } + else if (opoOpoChakra == 0) { return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); } - #endregion } + #endregion + #region Open Lunar + if (solarNadi || lunarNadi || bothNadisOpen) + { + return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); + } + #endregion } + } - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) - && HasEffect(Buffs.WindsRumination) - && WindsReply.LevelChecked()) - { - return WindsReply; - } - - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) - && HasEffect(Buffs.FiresRumination) - && !HasEffect(Buffs.PerfectBalance) - && !HasEffect(Buffs.FormlessFist) - && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick)) - && FiresReply.LevelChecked()) - { - return FiresReply; - } + if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) + && HasEffect(Buffs.WindsRumination) + && WindsReply.LevelChecked()) + { + return WindsReply; + } - // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); + if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) + && HasEffect(Buffs.FiresRumination) + && !HasEffect(Buffs.PerfectBalance) + && !HasEffect(Buffs.FormlessFist) + && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick)) + && FiresReply.LevelChecked()) + { + return FiresReply; } + + // Standard Beast Chakras + return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); + } return actionID; @@ -468,7 +465,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // 3. During Brotherhood. // 4. During Riddle of Fire. // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if (HasCharges(PerfectBalance) && + if (HasCharges(PerfectBalance) && (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || (GetCooldownRemainingTime(PerfectBalance) <= 4) || (HasEffect(Buffs.Brotherhood)) || diff --git a/XIVSlothCombo/Core/IconReplacer.cs b/XIVSlothCombo/Core/IconReplacer.cs index 8f0c46496..dec279301 100644 --- a/XIVSlothCombo/Core/IconReplacer.cs +++ b/XIVSlothCombo/Core/IconReplacer.cs @@ -2,19 +2,22 @@ using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.UI; +using Lumina.Excel.GeneratedSheets; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; +using Action = Lumina.Excel.GeneratedSheets.Action; namespace XIVSlothCombo.Core { /// This class facilitates icon replacement. internal sealed partial class IconReplacer : IDisposable { - private readonly List customCombos; + public readonly List CustomCombos; private readonly Hook isIconReplaceableHook; private readonly Hook getIconHook; @@ -24,7 +27,7 @@ internal sealed partial class IconReplacer : IDisposable /// Initializes a new instance of the class. public IconReplacer() { - customCombos = Assembly.GetAssembly(typeof(CustomCombo))!.GetTypes() + CustomCombos = Assembly.GetAssembly(typeof(CustomCombo))!.GetTypes() .Where(t => !t.IsAbstract && t.BaseType == typeof(CustomCombo)) .Select(t => Activator.CreateInstance(t)) .Cast() @@ -72,10 +75,16 @@ private unsafe uint GetIconDetour(IntPtr actionManager, uint actionID) float comboTime = ActionManager.Instance()->Combo.Action != 0 ? ActionManager.Instance()->Combo.Timer : 0; byte level = Svc.ClientState.LocalPlayer?.Level ?? 0; - foreach (CustomCombo? combo in customCombos) + foreach (CustomCombo? combo in CustomCombos) { if (combo.TryInvoke(actionID, level, lastComboMove, comboTime, out uint newActionID)) + { + if (Service.Configuration.BlockSpellOnMove && ActionManager.GetAdjustedCastTime(ActionType.Action, newActionID) > 0 && CustomComboFunctions.IsMoving) + { + return OriginalHook(11); + } return newActionID; + } } return OriginalHook(actionID); diff --git a/XIVSlothCombo/Core/PluginConfiguration.cs b/XIVSlothCombo/Core/PluginConfiguration.cs index b627a652b..550caf630 100644 --- a/XIVSlothCombo/Core/PluginConfiguration.cs +++ b/XIVSlothCombo/Core/PluginConfiguration.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using XIVSlothCombo.AutoRotation; using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Extensions; @@ -44,10 +45,18 @@ public class PluginConfiguration : IPluginConfiguration /// Gets or sets the offset of the melee range check. Default is 0. public double MeleeOffset { get; set; } = 0; + public bool BlockSpellOnMove = false; public Vector4 TargetHighlightColor { get; set; } = new() { W = 1, X = 0.5f, Y = 0.5f, Z = 0.5f }; #endregion + #region AutoAction Settings + public Dictionary AutoActions { get; set; } = []; + + public AutoRotationConfig RotationConfig { get; set; } = new(); + + #endregion + #region Custom Float Values [JsonProperty("CustomFloatValuesV6")] @@ -233,14 +242,9 @@ public void ResetFeatures(string config, int[] values) #region Other (SpecialEvent, MotD, Save) - /// Handles 'special event' feature naming. - public bool SpecialEvent { get; set; } = false; - /// Hides the message of the day. public bool HideMessageOfTheDay { get; set; } = false; - public bool RecommendedSettingsViewed { get; set; } = false; - /// Save the configuration to disk. public void Save() => Svc.PluginInterface.SavePluginConfig(this); diff --git a/XIVSlothCombo/CustomCombo/CustomCombo.cs b/XIVSlothCombo/CustomCombo/CustomCombo.cs index 9767aae47..070e3625a 100644 --- a/XIVSlothCombo/CustomCombo/CustomCombo.cs +++ b/XIVSlothCombo/CustomCombo/CustomCombo.cs @@ -1,11 +1,11 @@ -using Dalamud.Utility; +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Utility; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Extensions; namespace XIVSlothCombo.CustomComboNS { @@ -22,6 +22,8 @@ protected CustomCombo() StartTimer(); } + protected IGameObject? OptionalTarget; + /// Gets the preset associated with this combo. protected internal abstract CustomComboPreset Preset { get; } @@ -39,7 +41,7 @@ protected CustomCombo() /// Replacement action ID. /// True if the action has changed, otherwise false. - public unsafe bool TryInvoke(uint actionID, byte level, uint lastComboMove, float comboTime, out uint newActionID) + public unsafe bool TryInvoke(uint actionID, byte level, uint lastComboMove, float comboTime, out uint newActionID, IGameObject targetOverride = null) { newActionID = 0; @@ -61,6 +63,7 @@ public unsafe bool TryInvoke(uint actionID, byte level, uint lastComboMove, floa JobID != classJobID && ClassID != classJobID) return false; + OptionalTarget = targetOverride; uint resultingActionID = Invoke(actionID, lastComboMove, comboTime, level); //Dalamud.Logging.PluginLog.Debug(resultingActionID.ToString()); diff --git a/XIVSlothCombo/CustomCombo/Functions/Action.cs b/XIVSlothCombo/CustomCombo/Functions/Action.cs index 7a79b10ac..4e8422eba 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Action.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Action.cs @@ -1,4 +1,5 @@ -using FFXIVClientStructs.FFXIV.Client.Game; +using Dalamud.Game.ClientState.Objects.Types; +using FFXIVClientStructs.FFXIV.Client.Game; using System.Linq; using XIVSlothCombo.Data; using XIVSlothCombo.Services; @@ -45,7 +46,7 @@ internal abstract partial class CustomComboFunctions /// Checks if the player is in range to use an action. Best used with actions with irregular ranges. /// ID of the action. /// - public static bool InActionRange(uint id) + public static bool InActionRange(uint id, IGameObject? optionalTarget = null) { int range = ActionWatching.GetActionRange(id); switch (range) @@ -66,12 +67,12 @@ public static bool InActionRange(uint id) //But attacks from player must include personal space (0.5y). if (radius > 0) { //Do not nest with above - if (HasTarget()) return GetTargetDistance() <= (radius - 0.5f); else return false; + if (HasTarget()) return GetTargetDistance(optionalTarget) <= (radius - 0.5f); else return false; } else return true; //Self use targets (Second Wind) have no radius } default: - return GetTargetDistance() <= range; + return GetTargetDistance(optionalTarget) <= range; } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Misc.cs b/XIVSlothCombo/CustomCombo/Functions/Misc.cs index b749238ba..eaf4881c7 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Misc.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Misc.cs @@ -139,7 +139,7 @@ public static byte JobToClass(uint jobID) SMN.JobID => SMN.ClassID, WAR.JobID => WAR.ClassID, WHM.JobID => WHM.ClassID, - _ => 0xFF, + _ => (byte)jobID, }; } diff --git a/XIVSlothCombo/CustomCombo/Functions/Party.cs b/XIVSlothCombo/CustomCombo/Functions/Party.cs index e1fa0df6a..8efa4f73b 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Party.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Party.cs @@ -1,6 +1,8 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using ECommons.DalamudServices; +using FFXIVClientStructs.FFXIV.Client.Game.Object; +using System.Collections.Generic; using System.Linq; using XIVSlothCombo.Services; @@ -13,7 +15,17 @@ internal abstract partial class CustomComboFunctions /// Gets the party list /// Current party list. - public static IPartyList GetPartyMembers() => Svc.Party; + public static List GetPartyMembers() + { + var output = new List(); + for (int i = 1; i <= 8; i++) + { + var member = GetPartySlot(i); + if (member != null) + output.Add(member as IBattleChara); + } + return output; + } public unsafe static IGameObject? GetPartySlot(int slot) { diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index d9869f6b1..077c30dce 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -23,13 +23,13 @@ internal abstract partial class CustomComboFunctions /// Gets the distance from the target. /// Double representing the distance from the target. - public static float GetTargetDistance() + public static float GetTargetDistance(IGameObject? optionalTarget = null) { - if (CurrentTarget is null || LocalPlayer is null) + if (LocalPlayer is null) return 0; - if (CurrentTarget is not IBattleChara chara) - return 0; + IBattleChara chara = optionalTarget is null ? CurrentTarget as IBattleChara : optionalTarget as IBattleChara; + if (chara is null) return 0; if (CurrentTarget.GameObjectId == LocalPlayer.GameObjectId) return 0; diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index 5830bddba..db25c8208 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -101,7 +101,7 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp TimeLastActionUsed = DateTime.Now; ActionType = actionType; - //Dalamud.Logging.PluginLog.Debug($"{actionId} {sequence} {a5} {a6} {a7} {a8} {a9}"); + Svc.Log.Debug($"{actionId} {sequence} {a5} {a6} {a7} {a8} {a9}"); } catch (Exception ex) { diff --git a/XIVSlothCombo/Window/ConfigWindow.cs b/XIVSlothCombo/Window/ConfigWindow.cs index 26d2badac..c8570e06b 100644 --- a/XIVSlothCombo/Window/ConfigWindow.cs +++ b/XIVSlothCombo/Window/ConfigWindow.cs @@ -136,6 +136,11 @@ public override void Draw() OpenWindow = OpenWindow.Settings; } ImGui.Spacing(); + if (ImGui.Selectable("Auto-Rotation", OpenWindow == OpenWindow.AutoRotation)) + { + OpenWindow = OpenWindow.AutoRotation; + } + ImGui.Spacing(); if (ImGui.Selectable("About", OpenWindow == OpenWindow.About)) { OpenWindow = OpenWindow.About; @@ -172,6 +177,9 @@ public override void Draw() case OpenWindow.Debug: Debug.Draw(); break; + case OpenWindow.AutoRotation: + AutoRotationTab.Draw(); + break; default: break; }; @@ -191,7 +199,8 @@ public enum OpenWindow PvE = 1, PvP = 2, Settings = 3, - About = 4, - Debug = 5, + AutoRotation = 4, + About = 5, + Debug = 6, } } diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 038e82e07..d24eb31a6 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -1,22 +1,21 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; -using ECommons; using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Reflection.Emit; using System.Text; using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos; using XIVSlothCombo.Core; using XIVSlothCombo.Data; -using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; -using XIVSlothCombo.Window.Tabs; namespace XIVSlothCombo.Window.Functions { @@ -35,6 +34,7 @@ internal class PresetAttributes public HoverInfoAttribute? HoverInfo; public ReplaceSkillAttribute? ReplaceSkill; public CustomComboInfoAttribute? CustomComboInfo; + public AutoActionAttribute? AutoAction; public PresetAttributes(CustomComboPreset preset) { @@ -48,6 +48,7 @@ public PresetAttributes(CustomComboPreset preset) HoverInfo = preset.GetAttribute(); ReplaceSkill = preset.GetAttribute(); CustomComboInfo = preset.GetAttribute(); + AutoAction = preset.GetAttribute(); } } @@ -66,9 +67,31 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo var variantParents = Attributes[preset].VariantParent; var bozjaParents = Attributes[preset].BozjaParent; var eurekaParents = Attributes[preset].EurekaParent; + var auto = Attributes[preset].AutoAction; ImGui.Spacing(); + if (auto != null) + { + if (!Service.Configuration.AutoActions.ContainsKey(preset)) + Service.Configuration.AutoActions[preset] = false; + + var label = "Auto-Mode"; + var labelSize = ImGui.CalcTextSize(label); + ImGui.SetCursorPosX(ImGui.GetContentRegionAvail().X - labelSize.X.Scale() - 64f.Scale()); + bool autoOn = Service.Configuration.AutoActions[preset]; + if (ImGui.Checkbox($"###AutoAction{i}", ref autoOn)) + { + Service.Configuration.AutoActions[preset] = autoOn; + Service.Configuration.Save(); + } + ImGui.SameLine(); + ImGuiEx.Text(label); + ImGuiComponents.HelpMarker($"Add this feature to Auto-Rotation.\n" + + $"Auto-Rotation will automatically use the actions selected within the feature, allowing you to focus on movement. Configure the settings in the 'Auto-Rotation' section."); + ImGui.Separator(); + } + if (ImGui.Checkbox($"{info.Name}###{i}", ref enabled)) { if (enabled) @@ -87,11 +110,12 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo Service.Configuration.Save(); } + + DrawReplaceAttribute(preset); + Vector2 length = new(); using (var styleCol = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey)) { - DrawReplaceAttribute(preset); - if (i != -1) { ImGui.Text($"#{i}: "); @@ -112,6 +136,8 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo } } } + + ImGui.Spacing(); if (conflicts.Length > 0) @@ -128,7 +154,8 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo while (PresetStorage.GetParent(par2) != null) { var subpar = PresetStorage.GetParent(par2); - if (subpar != null) { + if (subpar != null) + { conflictBuilder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo : subpar?.GetAttribute().Name)} -> "); par2 = subpar!.Value; } diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs new file mode 100644 index 000000000..28ed8001f --- /dev/null +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -0,0 +1,66 @@ +using Dalamud.Interface.Components; +using ECommons.ImGuiMethods; +using ImGuiNET; +using XIVSlothCombo.Services; + +namespace XIVSlothCombo.Window.Tabs +{ + internal class AutoRotationTab : ConfigWindow + { + internal static new void Draw() + { + ImGui.TextWrapped($"This is where you can configure the parameters in which Auto-Rotation will operate. " + + $"Features marked with an 'Auto-Mode' checkbox are able to be used with Auto-Rotation."); + ImGui.Separator(); + + var cfg = Service.Configuration.RotationConfig; + bool changed = false; + + changed |= ImGui.Checkbox($"Enable Auto-Rotation", ref cfg.Enabled); + if (cfg.Enabled) + { + changed |= ImGui.Checkbox("Only in Combat", ref cfg.InCombatOnly); + } + + if (ImGui.CollapsingHeader("DPS Settings")) + { + ImGui.Text($"Targeting Mode"); + changed |= ImGuiEx.EnumCombo("###DPSTargetingMode", ref cfg.DPSRotationMode); + ImGuiComponents.HelpMarker("Manual - Leaves all targeting decisions to you.\n" + + "Highest Max - Prioritises enemies with the highest max HP.\n" + + "Lowest Max - Prioritises enemies with the lowest max HP.\n" + + "Highest Current - Prioritises the enemy with the highest current HP.\n" + + "Lowest Current - Prioritises the enemy with the lowest current HP.\n" + + "Tank Target - Prioritises the same target as the first tank in your group."); + } + ImGui.Spacing(); + if (ImGui.CollapsingHeader("Healing Settings")) + { + ImGui.Text($"Targeting Mode"); + changed |= ImGuiEx.EnumCombo("###HealerTargetingMode", ref cfg.HealerRotationMode); + ImGuiComponents.HelpMarker("Manual - Leaves all targeting decisions to you.\n" + + "Highest Current - Prioritises the party member with the highest current HP.\n" + + "Lowest Current - Prioritises the party member with the lowest current HP.\n" + + "Self Priority - Heal yourself before others.\n" + + "Tank Priority - Heal the tank(s) before others.\n" + + "Healer Priority - Heal the healer(s) before others.\n" + + "DPS Priority - Heal the DPS before others."); + + ImGui.SetNextItemWidth(200f.Scale()); + changed |= ImGuiEx.SliderInt("Single Target HP% Threshold", ref cfg.HealerSettings.SingleTargetHPP, 1, 99, "%d%%"); + ImGui.SetNextItemWidth(200f.Scale()); + changed |= ImGuiEx.SliderInt("AoE Group Average HP% Threshold", ref cfg.HealerSettings.AoETargetHPP, 1, 99, "%d%%"); + } + ImGui.Spacing(); + if (ImGui.CollapsingHeader("Tank Settings")) + { + ImGui.Text($"Targeting Mode"); + changed |= ImGuiEx.EnumCombo("###TankTargetingMode", ref cfg.TankRotationMode); + } + + if (changed) + Service.Configuration.Save(); + + } + } +} diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 06df7e63b..ebfeaf53a 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -5,6 +5,7 @@ using ECommons.DalamudServices; using ECommons.ImGuiMethods; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.UI; using ImGuiNET; using Lumina.Excel.GeneratedSheets; @@ -169,6 +170,12 @@ static void CustomStyleText(string label, object? value) CustomStyleText($"Max Charges:", $"{debugSpell.MaxCharges}"); if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.RowId)) CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.RowId])/1000f:F2}"); + + if (Svc.Targets.Target != null) + { + var inRange = ActionManager.GetActionInRangeOrLoS(debugSpell.RowId, (GameObject*)LocalPlayer.Address, (GameObject*)Svc.Targets.Target.Address); + CustomStyleText("InRange or LoS:", inRange == 0 ? "In range and in line of sight" : $"{inRange}: {Svc.Data.GetExcelSheet().GetRow(inRange).Text}"); + } } } diff --git a/XIVSlothCombo/Window/Tabs/Settings.cs b/XIVSlothCombo/Window/Tabs/Settings.cs index bf3f92067..42d8d1fea 100644 --- a/XIVSlothCombo/Window/Tabs/Settings.cs +++ b/XIVSlothCombo/Window/Tabs/Settings.cs @@ -132,6 +132,9 @@ internal class Settings : ConfigWindow #endregion + if (ImGui.Checkbox($"Block spells if moving", ref Service.Configuration.BlockSpellOnMove)) + Service.Configuration.Save(); + } } } diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 1e75ea445..5570b1540 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -17,6 +17,7 @@ using System.Reflection; using System.Threading.Tasks; using XIVSlothCombo.Attributes; +using XIVSlothCombo.AutoRotation; using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Combos.PvP; @@ -24,6 +25,7 @@ using XIVSlothCombo.Data; using XIVSlothCombo.Services; using XIVSlothCombo.Window; +using XIVSlothCombo.Window.Functions; using XIVSlothCombo.Window.Tabs; namespace XIVSlothCombo @@ -125,6 +127,7 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) Svc.ClientState.Login += PrintLoginMessage; if (Svc.ClientState.IsLoggedIn) ResetFeatures(); + CachePresets(); Svc.Framework.Update += OnFrameworkUpdate; KillRedundantIDs(); @@ -135,6 +138,15 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) #endif } + private void CachePresets() + { + foreach (var preset in Enum.GetValues()) + { + Presets.Attributes.Add(preset, new Presets.PresetAttributes(preset)); + } + Svc.Log.Information($"Cached {Presets.Attributes.Count} preset attributes."); + } + private static void HandleConflictedCombos() { var enabledCopy = Service.Configuration.EnabledActions.ToHashSet(); //Prevents issues later removing during enumeration @@ -164,6 +176,7 @@ private void OnFrameworkUpdate(IFramework framework) BlueMageService.PopulateBLUSpells(); TargetHelper.Draw(); + AutoRotationController.Run(); } private static void KillRedundantIDs() From 8a37c2255a72507bdbde8bbcdc8d878e8ecb7587 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 1 Sep 2024 21:22:56 +0100 Subject: [PATCH 052/208] More autorot --- .../AutoRotation/AutoRotationController.cs | 70 ++++++++++++++----- XIVSlothCombo/CustomCombo/Functions/Action.cs | 3 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 5 +- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 3 +- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index f6bf2c8c5..5ad9784ef 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -5,14 +5,12 @@ using ECommons.Throttlers; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; -using ImGuizmoNET; using System; using System.Linq; using XIVSlothCombo.Combos; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; -using static FFXIVClientStructs.FFXIV.Client.UI.RaptureAtkHistory.Delegates; using Action = Lumina.Excel.GeneratedSheets.Action; namespace XIVSlothCombo.AutoRotation @@ -27,7 +25,7 @@ internal static void Run() if (!EzThrottler.Throttle("AutoRotController", 50)) return; - foreach (var preset in Service.Configuration.AutoActions.OrderBy(x => Presets.Attributes[x.Key].AutoAction.IsHeal)) + foreach (var preset in Service.Configuration.AutoActions.OrderBy(x => Presets.Attributes[x.Key].AutoAction.IsAoE && Presets.Attributes[x.Key].AutoAction.IsHeal)) { if (!CustomComboFunctions.IsEnabled(preset.Key) || !preset.Value) continue; @@ -39,12 +37,14 @@ internal static void Run() if ((byte)Player.Job != attributes.CustomComboInfo.JobID && (byte)Player.Job != classId) continue; + var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); var healTarget = AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode); + var aoeHeal = HealerTargeting.GetPartyAverage(outAct) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP; - if (action.IsHeal && healTarget is not null) + if (action.IsHeal) { AutomateHealing(preset.Key, attributes, gameAct); - return; + continue; } //if (Player.Object.GetRole() is CombatRole.Tank) @@ -53,8 +53,8 @@ internal static void Run() // continue; //} - if (healTarget == null) - AutomateDPS(preset.Key, attributes, gameAct); + if (healTarget == null && !aoeHeal) + AutomateDPS(preset.Key, attributes, gameAct); } @@ -90,7 +90,7 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr { if (attributes.AutoAction.IsAoE) { - + return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); } else { @@ -139,27 +139,54 @@ public static class AutoRotationHelper public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { - + if (attributes.AutoAction.IsHeal) + { + uint outAct = InvokeCombo(preset, attributes, Player.Object); + + if (HealerTargeting.GetPartyAverage(outAct) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP) + { + var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); + if (CustomComboFunctions.IsMoving && castTime > 0) + return false; + + ActionManager.Instance()->UseAction(ActionType.Action, outAct); + return true; + } + } + else + { + + } return false; } - public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttributes attributes, IGameObject? optionalTarget = null) { - var target = AutoRotationHelper.GetSingleTarget(mode); - if (target is null) - return false; - - var outAct = attributes.ReplaceSkill.ActionIDs.First(); + var outAct = attributes.ReplaceSkill.ActionIDs.FirstOrDefault(); foreach (var actToCheck in attributes.ReplaceSkill.ActionIDs) { - var customCombo = Service.IconReplacer.CustomCombos.First(x => x.Preset == preset); - if (customCombo.TryInvoke(actToCheck, (byte)Player.Level, ActionManager.Instance()->Combo.Action, ActionManager.Instance()->Combo.Timer, out var changedAct, target)) + var customCombo = Service.IconReplacer.CustomCombos.FirstOrDefault(x => x.Preset == preset); + if (customCombo != null) { - outAct = changedAct; - break; + if (customCombo.TryInvoke(actToCheck, (byte)Player.Level, ActionManager.Instance()->Combo.Action, ActionManager.Instance()->Combo.Timer, out var changedAct, optionalTarget)) + { + outAct = changedAct; + break; + } } } + return outAct; + } + + public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + { + var target = AutoRotationHelper.GetSingleTarget(mode); + if (target is null) + return false; + + var outAct = InvokeCombo(preset, attributes); + var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) return false; @@ -222,6 +249,11 @@ public static class HealerTargeting var target = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP).OrderBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); return target; } + + internal static float GetPartyAverage(uint outAct) + { + return CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.InActionRange(outAct, x)).Average(x => CustomComboFunctions.GetTargetHPPercent(x)); + } } } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Action.cs b/XIVSlothCombo/CustomCombo/Functions/Action.cs index 4e8422eba..c35beb579 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Action.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Action.cs @@ -1,4 +1,5 @@ using Dalamud.Game.ClientState.Objects.Types; +using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using System.Linq; using XIVSlothCombo.Data; @@ -67,7 +68,7 @@ public static bool InActionRange(uint id, IGameObject? optionalTarget = null) //But attacks from player must include personal space (0.5y). if (radius > 0) { //Do not nest with above - if (HasTarget()) return GetTargetDistance(optionalTarget) <= (radius - 0.5f); else return false; + if (HasTarget() || optionalTarget != null) return GetTargetDistance(optionalTarget) <= (radius - 0.5f); else return false; } else return true; //Self use targets (Second Wind) have no radius } diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 077c30dce..58c421c80 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -28,15 +28,14 @@ public static float GetTargetDistance(IGameObject? optionalTarget = null) if (LocalPlayer is null) return 0; - IBattleChara chara = optionalTarget is null ? CurrentTarget as IBattleChara : optionalTarget as IBattleChara; + IBattleChara chara = optionalTarget != null ? optionalTarget as IBattleChara : CurrentTarget != null ? CurrentTarget as IBattleChara : null; if (chara is null) return 0; - if (CurrentTarget.GameObjectId == LocalPlayer.GameObjectId) + if (chara.GameObjectId == LocalPlayer.GameObjectId) return 0; Vector2 position = new(chara.Position.X, chara.Position.Z); Vector2 selfPosition = new(LocalPlayer.Position.X, LocalPlayer.Position.Z); - return Math.Max(0, Vector2.Distance(position, selfPosition) - chara.HitboxRadius - LocalPlayer.HitboxRadius); } diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 28ed8001f..99782dacb 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -49,7 +49,8 @@ internal class AutoRotationTab : ConfigWindow ImGui.SetNextItemWidth(200f.Scale()); changed |= ImGuiEx.SliderInt("Single Target HP% Threshold", ref cfg.HealerSettings.SingleTargetHPP, 1, 99, "%d%%"); ImGui.SetNextItemWidth(200f.Scale()); - changed |= ImGuiEx.SliderInt("AoE Group Average HP% Threshold", ref cfg.HealerSettings.AoETargetHPP, 1, 99, "%d%%"); + changed |= ImGuiEx.SliderInt("AoE HP% Threshold", ref cfg.HealerSettings.AoETargetHPP, 1, 99, "%d%%"); + ImGuiComponents.HelpMarker(""); } ImGui.Spacing(); if (ImGui.CollapsingHeader("Tank Settings")) From 50d26b6160b4a8f4fbae632c62db3f54ca304af7 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 1 Sep 2024 21:09:27 -0500 Subject: [PATCH 053/208] Icons Icons for All classes and DoL added --- XIVSlothCombo/Window/Icons.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Window/Icons.cs b/XIVSlothCombo/Window/Icons.cs index f37fa589d..0eed31e97 100644 --- a/XIVSlothCombo/Window/Icons.cs +++ b/XIVSlothCombo/Window/Icons.cs @@ -4,6 +4,7 @@ using ECommons.DalamudServices; using Lumina.Data.Files; using System.Collections.Generic; +using XIVSlothCombo.Combos.PvE; namespace XIVSlothCombo.Window { @@ -12,17 +13,21 @@ internal static class Icons public static Dictionary CachedModdedIcons = new(); public static IDalamudTextureWrap? GetJobIcon(uint jobId) { - if (jobId == 0 || jobId > 42) return null; - var icon = GetTextureFromIconId(62100 + jobId); - - return icon; + switch (jobId) + { + case All.JobID: jobId = 62146; break; //Adventurer / General + case > All.JobID and <= 42: jobId += 62100; break; //Classes + case DOL.JobID: jobId = 82096; break; + default: return null; //Unknown, return null + } + return GetTextureFromIconId(jobId); } private static string ResolvePath(string path) => Svc.TextureSubstitution.GetSubstitutedPath(path); public static IDalamudTextureWrap? GetTextureFromIconId(uint iconId, uint stackCount = 0, bool hdIcon = true) { - GameIconLookup lookup = new GameIconLookup(iconId + stackCount, false, hdIcon); + GameIconLookup lookup = new(iconId + stackCount, false, hdIcon); string path = Svc.Texture.GetIconPath(lookup); string resolvePath = ResolvePath(path); @@ -32,7 +37,7 @@ internal static class Icons try { - if (CachedModdedIcons.ContainsKey(iconId)) return CachedModdedIcons[iconId]; + if (CachedModdedIcons.TryGetValue(iconId, out IDalamudTextureWrap? cachedIcon)) return cachedIcon; var tex = Svc.Data.GameData.GetFileFromDisk(resolvePath); var output = Svc.Texture.CreateFromRaw(RawImageSpecification.Rgba32(tex.Header.Width, tex.Header.Width), tex.GetRgbaImageData()); if (output != null) From aee6521497a50f32c571324b648df7b85f4bc742 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Mon, 2 Sep 2024 08:03:38 +0100 Subject: [PATCH 054/208] AutoRot AoE DPS --- .../AutoRotation/AutoRotationController.cs | 73 +++++++++------ XIVSlothCombo/CustomCombo/Functions/Target.cs | 92 ++++++++++++++++++- XIVSlothCombo/Extensions/ListExtensions.cs | 42 +++++++++ 3 files changed, 175 insertions(+), 32 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 19391fc84..f2b14b825 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -6,6 +6,7 @@ using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; using System; +using System.Diagnostics; using System.Linq; using XIVSlothCombo.Combos; using XIVSlothCombo.CustomComboNS.Functions; @@ -22,10 +23,11 @@ internal static void Run() if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) return; - if (!EzThrottler.Throttle("AutoRotController", 50)) + if (!EzThrottler.Throttle("AutoRotController", 750)) return; - foreach (var preset in Service.Configuration.AutoActions.OrderBy(x => Presets.Attributes[x.Key].AutoAction.IsAoE && Presets.Attributes[x.Key].AutoAction.IsHeal)) + foreach (var preset in Service.Configuration.AutoActions.OrderBy(x => Presets.Attributes[x.Key].AutoAction.IsHeal) + .ThenBy(x => Presets.Attributes[x.Key].AutoAction.IsAoE)) { if (!CustomComboFunctions.IsEnabled(preset.Key) || !preset.Value) continue; @@ -39,7 +41,7 @@ internal static void Run() var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); var healTarget = AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode); - var aoeHeal = HealerTargeting.GetPartyMax(outAct) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP; + var aoeHeal = HealerTargeting.GetPartyMax(outAct, out int count) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP && count >= 2; if (action.IsHeal) { @@ -64,9 +66,9 @@ private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttribut { if (attributes.AutoAction.IsAoE) { - + return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); } - else + else if (CustomComboFunctions.NumberOfEnemiesInCombat(gameAct) < Service.Configuration.RotationConfig.DPSAoETargets) { var mode = Service.Configuration.RotationConfig.DPSRotationMode; return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); @@ -143,7 +145,7 @@ public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes { uint outAct = InvokeCombo(preset, attributes, Player.Object); - if (HealerTargeting.GetPartyMax(outAct) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP) + if (HealerTargeting.GetPartyMax(outAct, out int count) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP && count >= 2) { var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) @@ -155,28 +157,20 @@ public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes } else { - - } - return false; - } - - public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttributes attributes, IGameObject? optionalTarget = null) - { - var outAct = attributes.ReplaceSkill.ActionIDs.FirstOrDefault(); - foreach (var actToCheck in attributes.ReplaceSkill.ActionIDs) - { - var customCombo = Service.IconReplacer.CustomCombos.FirstOrDefault(x => x.Preset == preset); - if (customCombo != null) + uint outAct = InvokeCombo(preset, attributes, Player.Object); + var target = GetSingleTarget(Service.Configuration.RotationConfig.DPSRotationMode); + Svc.Targets.Target = target; + if (CustomComboFunctions.NumberOfEnemiesInCombat(outAct) >= Service.Configuration.RotationConfig.DPSAoETargets) { - if (customCombo.TryInvoke(actToCheck, (byte)Player.Level, ActionManager.Instance()->Combo.Action, ActionManager.Instance()->Combo.Timer, out var changedAct, optionalTarget)) - { - outAct = changedAct; - break; - } + var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); + if (CustomComboFunctions.IsMoving && castTime > 0) + return false; + + ActionManager.Instance()->UseAction(ActionType.Action, outAct); + return true; } } - - return outAct; + return false; } public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) @@ -185,7 +179,7 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset if (target is null) return false; - var outAct = InvokeCombo(preset, attributes); + var outAct = InvokeCombo(preset, attributes, target); var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) @@ -194,12 +188,32 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, (GameObject*)target.Address) != 562; if (inRange) { + Svc.Targets.Target = target; ActionManager.Instance()->UseAction(ActionType.Action, outAct, target.GameObjectId); return true; } return false; } + + public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttributes attributes, IGameObject? optionalTarget = null) + { + var outAct = attributes.ReplaceSkill.ActionIDs.FirstOrDefault(); + foreach (var actToCheck in attributes.ReplaceSkill.ActionIDs) + { + var customCombo = Service.IconReplacer.CustomCombos.FirstOrDefault(x => x.Preset == preset); + if (customCombo != null) + { + if (customCombo.TryInvoke(actToCheck, (byte)Player.Level, ActionManager.Instance()->Combo.Action, ActionManager.Instance()->Combo.Timer, out var changedAct, optionalTarget)) + { + outAct = changedAct; + break; + } + } + } + + return outAct; + } } public static class DPSTargeting @@ -250,9 +264,12 @@ public static class HealerTargeting return target; } - internal static float GetPartyMax(uint outAct) + internal static float GetPartyMax(uint outAct, out int count) { - return CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.InActionRange(outAct, x)).Max(x => CustomComboFunctions.GetTargetHPPercent(x)); + var members = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.InActionRange(outAct, x)); + var avg = members.Average(x => CustomComboFunctions.GetTargetHPPercent(x)); + count = members.Count(); + return avg; } } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 58c421c80..6a5c46927 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -1,7 +1,10 @@ using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.Types; +using ECommons; using ECommons.DalamudServices; +using FFXIVClientStructs.FFXIV.Client.Game.Character; +using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.System.Framework; using System; using System.Linq; @@ -9,6 +12,8 @@ using XIVSlothCombo.Data; using XIVSlothCombo.Services; using StructsObject = FFXIVClientStructs.FFXIV.Client.Game.Object; +using ECommons.GameFunctions; +using XIVSlothCombo.Extensions; namespace XIVSlothCombo.CustomComboNS.Functions { @@ -23,7 +28,7 @@ internal abstract partial class CustomComboFunctions /// Gets the distance from the target. /// Double representing the distance from the target. - public static float GetTargetDistance(IGameObject? optionalTarget = null) + public static float GetTargetDistance(IGameObject? optionalTarget = null, IGameObject? source = null) { if (LocalPlayer is null) return 0; @@ -31,12 +36,14 @@ public static float GetTargetDistance(IGameObject? optionalTarget = null) IBattleChara chara = optionalTarget != null ? optionalTarget as IBattleChara : CurrentTarget != null ? CurrentTarget as IBattleChara : null; if (chara is null) return 0; - if (chara.GameObjectId == LocalPlayer.GameObjectId) + IBattleChara sourceChara = source != null ? source as IBattleChara : LocalPlayer; + + if (chara.GameObjectId == sourceChara.GameObjectId) return 0; Vector2 position = new(chara.Position.X, chara.Position.Z); - Vector2 selfPosition = new(LocalPlayer.Position.X, LocalPlayer.Position.Z); - return Math.Max(0, Vector2.Distance(position, selfPosition) - chara.HitboxRadius - LocalPlayer.HitboxRadius); + Vector2 selfPosition = new(sourceChara.Position.X, sourceChara.Position.Z); + return Math.Max(0, Vector2.Distance(position, selfPosition) - chara.HitboxRadius - sourceChara.HitboxRadius); } /// Gets a value indicating whether you are in melee range from the current target. @@ -390,5 +397,82 @@ static internal float AngleXZ(Vector3 a, Vector3 b) internal unsafe static bool OutOfRange(uint actionID, IGameObject target) => ActionWatching.OutOfRange(actionID, Svc.ClientState.LocalPlayer!, target); + public unsafe static bool EnemiesInRange(uint spellCheck) + { + var enemies = Svc.Objects.Where(x => x.ObjectKind == ObjectKind.BattleNpc).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); + foreach (var enemy in enemies) + { + var enemyChara = CharacterManager.Instance()->LookupBattleCharaByEntityId(enemy.EntityId); + if (enemyChara->Character.InCombat) + { + if (!ActionManager.CanUseActionOnTarget(7, enemy.GameObject())) continue; + if (!enemyChara->Character.GameObject.GetIsTargetable()) continue; + + if (!OutOfRange(spellCheck, enemy)) + return true; + } + + } + + return false; + } + + public unsafe static int NumberOfEnemiesInCombat(uint aoeSpell) + { + ActionWatching.ActionSheet.Values.TryGetFirst(x => x.RowId == aoeSpell, out var sheetSpell); + bool needsTarget = sheetSpell.CanTargetHostile; + + int count = 0; + var enemies = Svc.Objects.Where(x => x.ObjectKind == ObjectKind.BattleNpc && x.IsTargetable && !x.IsDead).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); + + for (int i = 0; i < enemies.Count(); i++) + { + var enemyObjectId = enemies[i].EntityId; + + var enemyChara = CharacterManager.Instance()->LookupBattleCharaByEntityId(enemyObjectId); + + if (enemyChara is null || !enemyChara->Character.InCombat || enemyChara->Character.IsFriend) continue; + + if (ActionManager.CanUseActionOnTarget(7, &enemyChara->Character.GameObject)) + { + if (!needsTarget) + { + if (GetTargetDistance(Svc.Objects.First(x => x.EntityId == enemyObjectId)) <= sheetSpell.EffectRange) + count++; + } + else + { + if (Svc.Targets.Target != null) + { + for (int t = 0; t < enemies.Count(); t++) + { + var nearbyEnemy = enemies[t].EntityId; + var nearbyChara = CharacterManager.Instance()->LookupBattleCharaByEntityId(nearbyEnemy); + if (nearbyChara is null) continue; + if (Svc.Objects.FindFirst(x => x.EntityId == enemyObjectId, out var tar)) + { + if (tar.IsDead) continue; + + if (GetTargetDistance(tar, Svc.Targets.Target) <= sheetSpell.EffectRange) + { + count++; + } + } + } + + Svc.Log.Debug($"{count}"); + return count; + } + } + } + + + } + + return count; + + return 0; + } + } } diff --git a/XIVSlothCombo/Extensions/ListExtensions.cs b/XIVSlothCombo/Extensions/ListExtensions.cs index c979c4e55..0f05b2e18 100644 --- a/XIVSlothCombo/Extensions/ListExtensions.cs +++ b/XIVSlothCombo/Extensions/ListExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace XIVSlothCombo.Extensions { @@ -17,5 +18,46 @@ public static void Shuffle(this IList list) (list[n], list[k]) = (list[k], list[n]); } } + + public static void SwapValues(this T[] source, long index1, long index2) + { + T temp = source[index1]; + source[index1] = source[index2]; + source[index2] = temp; + } + + // Find the first object fulfilling predicate's criteria in the given list, if one exists. + // Returns true if an object is found, false otherwise. + public static bool FindFirst(this IEnumerable array, Predicate predicate, [NotNullWhen(true)] out T? result) + { + foreach (var obj in array) + { + if (predicate(obj)) + { + result = obj!; + return true; + } + } + + result = default; + return false; + } + + // Find the first occurrence of needle in the given list and return the value contained in the list in result. + // Returns true if an object is found, false otherwise. + public static bool FindFirst(this IEnumerable array, T needle, [NotNullWhen(true)] out T? result) where T : notnull + { + foreach (var obj in array) + { + if (obj.Equals(needle)) + { + result = obj; + return true; + } + } + + result = default; + return false; + } } } From fc2ed7b8f8e9cd5afb5f262c6ee5c3f42bb0fc02 Mon Sep 17 00:00:00 2001 From: edewen Date: Tue, 3 Sep 2024 08:23:14 -0400 Subject: [PATCH 055/208] Move resonant and encore to thier own options --- XIVSlothCombo/Combos/CustomComboPreset.cs | 14 +++++++++++--- XIVSlothCombo/Combos/PvE/BRD.cs | 4 ++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index ca4f55659..60d4f6d87 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -647,10 +647,18 @@ public enum CustomComboPreset [CustomComboInfo("Buffs Option", "Adds buffs onto the Advanced Bard feature.", BRD.JobID)] BRD_Adv_Buffs = 3017, - [ParentCombo(BRD_Adv_Buffs)] - [CustomComboInfo("Buffs - Radiant Option", "Adds Radiant Finale to theBuffs feature.", BRD.JobID)] + [ParentCombo(BRD_ST_AdvMode)] + [CustomComboInfo("Resonant Option", "Adds Resonant Arrow to the Rotation after Barrage.", BRD.JobID)] + BRD_Adv_BuffsResonant = 3041, + + [ParentCombo(BRD_ST_AdvMode)] + [CustomComboInfo("Buffs - Radiant Option", "Adds Radiant Finale to the Advanced Bard feature.", BRD.JobID)] BRD_Adv_BuffsRadiant = 3018, + [ParentCombo(BRD_ST_AdvMode)] + [CustomComboInfo("Encore Option", "Adds Radiant Encore to the Rotation after Finale.", BRD.JobID)] + BRD_Adv_BuffsEncore = 3042, + [ParentCombo(BRD_ST_AdvMode)] [CustomComboInfo("No Waste Option", "Adds enemy health checking on mobs for buffs, DoTs and Songs.\nThey will not be reapplied if less than specified.", BRD.JobID)] BRD_Adv_NoWaste = 3019, @@ -717,7 +725,7 @@ public enum CustomComboPreset [ParentCombo(BRD_AoE_AdvMode)] [CustomComboInfo("AoE No Waste Option", "Adds enemy health checking on targetted mob for songs.\nThey will not be reapplied if less than specified.", BRD.JobID)] BRD_AoE_Adv_NoWaste = 3033, - // Last value = 3040 + // Last value = 3042 #endregion diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index e77fd014c..39f1df502 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -791,7 +791,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } //Moved below weaves bc roobert says it is blocking his weaves from happening - if (HasEffect(Buffs.RadiantEncoreReady) && !JustUsed(RadiantFinale) && GetCooldownElapsed(BattleVoice) >= 4.2f && IsEnabled(CustomComboPreset.BRD_Adv_BuffsRadiant)) + if (HasEffect(Buffs.RadiantEncoreReady) && !JustUsed(RadiantFinale) && GetCooldownElapsed(RadiantFinale) >= 4.2f && IsEnabled(CustomComboPreset.BRD_Adv_BuffsEncore)) return OriginalHook(RadiantEncore); if (isEnemyHealthHigh) @@ -881,7 +881,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (HasEffect(Buffs.HawksEye) || HasEffect(Buffs.Barrage)) return OriginalHook(StraightShot); - if (HasEffect(Buffs.ResonantArrowReady) && IsEnabled(CustomComboPreset.BRD_Adv_Buffs)) + if (HasEffect(Buffs.ResonantArrowReady) && IsEnabled(CustomComboPreset.BRD_Adv_BuffsResonant)) return ResonantArrow; } From 9e81ed4d6a3b964e40f5048cb623738a8866f80e Mon Sep 17 00:00:00 2001 From: Kage Date: Tue, 3 Sep 2024 17:16:44 +0200 Subject: [PATCH 056/208] added comments --- XIVSlothCombo/Combos/PvE/MCH.cs | 46 +++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index 11ac35a5c..ed69436e7 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -124,7 +124,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim CanWeave(actionID)) return Variant.VariantRampart; - // Opener for MCH + // Opener if (MCHOpener.DoFullOpener(ref actionID)) return actionID; @@ -132,7 +132,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (interruptReady) return All.HeadGraze; - //All weaves + // All weaves if (CanWeave(ActionWatching.LastWeaponskill) && !ActionWatching.HasDoubleWeaved()) { @@ -144,15 +144,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!gauge.IsOverheated && ActionReady(BarrelStabilizer)) return BarrelStabilizer; + // Hypercharge if ((gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && LevelChecked(Hypercharge) && !gauge.IsOverheated) { - //Protection & ensures Hyper charged is double weaved with WF during reopener + // Ensures Hypercharge is double weaved with WF if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || !LevelChecked(Wildfire)) return Hypercharge; + // Only Hypercharge when tools are on cooldown if (drillCD && anchorCD && sawCD && ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) return Hypercharge; @@ -163,7 +165,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim GetCooldownRemainingTime(Wildfire) > GCD) return OriginalHook(RookAutoturret); - //Heatblast, Gauss, Rico + // Gauss Round and Ricochet during HC if (JustUsed(OriginalHook(Heatblast)) && (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) { @@ -176,7 +178,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(Ricochet); } - //gauss and ricochet outside HC + // Gauss Round and Ricochet outside HC if (!gauge.IsOverheated && (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || JustUsed(Drill) || JustUsed(Excavator))) @@ -188,24 +190,27 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(Ricochet); } - // healing + // Healing if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind) && !gauge.IsOverheated) return All.SecondWind; } - //Full Metal Field + // Full Metal Field if (HasEffect(Buffs.FullMetalMachinist) && (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && LevelChecked(FullMetalField)) return FullMetalField; + // Heatblast if (gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); + // Reassemble and Tools if (ReassembledTools(ref actionID, gauge)) return actionID; + // Excavator if (LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && ((BSUsed is 1) || @@ -215,7 +220,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) return OriginalHook(Chainsaw); - //1-2-3 Combo + // 1-2-3 Combo if (comboTime > 0) { if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) @@ -237,7 +242,6 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) { bool battery = Svc.Gauges.Get().Battery >= 100; - // TOOLS!! Chainsaw Drill Air Anchor Excavator if (!gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) & ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || @@ -307,7 +311,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim CanWeave(actionID)) return Variant.VariantRampart; - // Opener for MCH + // Opener if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Opener)) { if (MCHOpener.DoFullOpener(ref actionID)) @@ -318,7 +322,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Interrupt) && interruptReady) return All.HeadGraze; - //All weaves + // All weaves if (CanWeave(ActionWatching.LastWeaponskill) && !ActionWatching.HasDoubleWeaved()) { @@ -338,28 +342,30 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !gauge.IsOverheated && ActionReady(BarrelStabilizer)) return BarrelStabilizer; + // Hypercharge if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && LevelChecked(Hypercharge) && !gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) { - //Protection & ensures Hyper charged is double weaved with WF during reopener + // Ensures Hypercharge is double weaved with WF if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || !LevelChecked(Wildfire)) return Hypercharge; + // Only Hypercharge when tools are on cooldown if (drillCD && anchorCD && sawCD && ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) return Hypercharge; } - //Queen + // Queen if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && MCHExtensions.UseQueen(gauge) && GetCooldownRemainingTime(Wildfire) > GCD) return OriginalHook(RookAutoturret); - //Heatblast, Gauss, Rico + // Gauss Round and Ricochet during HC if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && JustUsed(OriginalHook(Heatblast)) && (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) @@ -373,7 +379,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(Ricochet); } - //gauss and ricochet outside HC + // Gauss Round and Ricochet outside HC if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && !gauge.IsOverheated && (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || @@ -386,13 +392,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(Ricochet); } - // healing + // Healing if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind) && !gauge.IsOverheated) return All.SecondWind; } - //Full Metal Field + // Full Metal Field if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer_FullMetalField) && HasEffect(Buffs.FullMetalMachinist) && (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || @@ -400,13 +406,16 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim LevelChecked(FullMetalField)) return FullMetalField; + // Heatblast if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Heatblast) && gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); + // Reassemble and Tools if (ReassembledTools(ref actionID, gauge)) return actionID; + // Excavator if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && reassembledExcavator && LevelChecked(Excavator) && @@ -418,7 +427,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) return OriginalHook(Chainsaw); - //1-2-3 Combo + // 1-2-3 Combo if (comboTime > 0) { if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) @@ -443,7 +452,6 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) bool reassembledAnchor = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[2] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[2] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledDrill = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[3] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[3] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); - // TOOLS!! Chainsaw Drill Air Anchor Excavator if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) && From 8c0a7f03717fd4b83aaac8d7d2ba7073259e3844 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Tue, 3 Sep 2024 18:30:29 +0100 Subject: [PATCH 057/208] PCT Autorot & Fix aoe check --- .../AutoRotation/AutoRotationController.cs | 32 +++++++++-------- XIVSlothCombo/Combos/CustomComboPreset.cs | 3 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 35 ++++++++----------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index f2b14b825..5f8282427 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -6,10 +6,10 @@ using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; using System; -using System.Diagnostics; using System.Linq; using XIVSlothCombo.Combos; using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; using Action = Lumina.Excel.GeneratedSheets.Action; @@ -26,8 +26,9 @@ internal static void Run() if (!EzThrottler.Throttle("AutoRotController", 750)) return; - foreach (var preset in Service.Configuration.AutoActions.OrderBy(x => Presets.Attributes[x.Key].AutoAction.IsHeal) - .ThenBy(x => Presets.Attributes[x.Key].AutoAction.IsAoE)) + var c = 0; + foreach (var preset in Service.Configuration.AutoActions.OrderByDescending(x => Presets.Attributes[x.Key].AutoAction.IsHeal) + .ThenByDescending(x => Presets.Attributes[x.Key].AutoAction.IsAoE)) { if (!CustomComboFunctions.IsEnabled(preset.Key) || !preset.Value) continue; @@ -36,7 +37,7 @@ internal static void Run() var gameAct = attributes.ReplaceSkill.ActionIDs.First(); var sheetAct = Svc.Data.GetExcelSheet().GetRow(gameAct); var classId = CustomComboFunctions.JobIDs.JobToClass((uint)Player.Job); - if ((byte)Player.Job != attributes.CustomComboInfo.JobID && (byte)Player.Job != classId) + if ((byte)Player.Job != attributes.CustomComboInfo.JobID) continue; var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); @@ -56,7 +57,8 @@ internal static void Run() //} if (healTarget == null && !aoeHeal) - AutomateDPS(preset.Key, attributes, gameAct); + if (AutomateDPS(preset.Key, attributes, gameAct)) + return; } @@ -64,16 +66,15 @@ internal static void Run() private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { + var mode = Service.Configuration.RotationConfig.DPSRotationMode; if (attributes.AutoAction.IsAoE) { return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); } - else if (CustomComboFunctions.NumberOfEnemiesInCombat(gameAct) < Service.Configuration.RotationConfig.DPSAoETargets) + else { - var mode = Service.Configuration.RotationConfig.DPSRotationMode; return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); } - return false; } private static void AutomateTanking(CustomComboPreset key, Presets.PresetAttributes attributes, uint gameAct) @@ -99,7 +100,6 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr var mode = Service.Configuration.RotationConfig.HealerRotationMode; return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); } - return false; } public static class AutoRotationHelper @@ -159,13 +159,17 @@ public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes { uint outAct = InvokeCombo(preset, attributes, Player.Object); var target = GetSingleTarget(Service.Configuration.RotationConfig.DPSRotationMode); - Svc.Targets.Target = target; - if (CustomComboFunctions.NumberOfEnemiesInCombat(outAct) >= Service.Configuration.RotationConfig.DPSAoETargets) + var mustTarget = Svc.Data.GetExcelSheet().GetRow(outAct).CanTargetHostile; + + if (CustomComboFunctions.NumberOfEnemiesInRange(outAct, target) >= Service.Configuration.RotationConfig.DPSAoETargets) { var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) return false; + if (mustTarget) + Svc.Targets.Target = target; + ActionManager.Instance()->UseAction(ActionType.Action, outAct); return true; } @@ -175,7 +179,7 @@ public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { - var target = AutoRotationHelper.GetSingleTarget(mode); + var target = GetSingleTarget(mode); if (target is null) return false; @@ -239,12 +243,12 @@ public static class DPSTargeting public static IGameObject? GetLowestMaxTarget() { - return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderBy(x => (x as IBattleChara).MaxHp).FirstOrDefault(); + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderBy(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } public static IGameObject? GetHighestMaxTarget() { - return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => (x as IBattleChara).MaxHp).FirstOrDefault(); + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } } diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index d9f1b9272..00198c276 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2357,7 +2357,7 @@ public enum CustomComboPreset #region ST - + [AutoAction(false, false)] [ReplaceSkill(PCT.FireInRed)] [ConflictingCombos(CombinedAetherhues, PCT_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", $"Replaces Fire in Red with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", PCT.JobID)] @@ -2484,6 +2484,7 @@ public enum CustomComboPreset #region AoE + [AutoAction(true, false)] [ReplaceSkill(PCT.FireIIinRed)] [ConflictingCombos(CombinedAetherhues, PCT_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", $"Replaces Fire II in Red with a one-button full AoE rotation.\nThese features are ideal if you want to customize the rotation.", PCT.JobID)] diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 6a5c46927..44ba82252 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -3,6 +3,7 @@ using Dalamud.Game.ClientState.Objects.Types; using ECommons; using ECommons.DalamudServices; +using ECommons.GameHelpers; using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.System.Framework; @@ -417,7 +418,7 @@ public unsafe static bool EnemiesInRange(uint spellCheck) return false; } - public unsafe static int NumberOfEnemiesInCombat(uint aoeSpell) + public unsafe static int NumberOfEnemiesInRange(uint aoeSpell, IGameObject? target) { ActionWatching.ActionSheet.Values.TryGetFirst(x => x.RowId == aoeSpell, out var sheetSpell); bool needsTarget = sheetSpell.CanTargetHostile; @@ -425,42 +426,36 @@ public unsafe static int NumberOfEnemiesInCombat(uint aoeSpell) int count = 0; var enemies = Svc.Objects.Where(x => x.ObjectKind == ObjectKind.BattleNpc && x.IsTargetable && !x.IsDead).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); + if (!ActionManager.CanUseActionOnTarget(7, target.Struct())) + return 0; + + for (int i = 0; i < enemies.Count(); i++) { - var enemyObjectId = enemies[i].EntityId; + var enemyChara = enemies[i]; - var enemyChara = CharacterManager.Instance()->LookupBattleCharaByEntityId(enemyObjectId); + if (enemyChara is null || !enemyChara.Character()->InCombat || enemyChara.Character()->IsFriend) continue; - if (enemyChara is null || !enemyChara->Character.InCombat || enemyChara->Character.IsFriend) continue; - - if (ActionManager.CanUseActionOnTarget(7, &enemyChara->Character.GameObject)) + if (ActionManager.CanUseActionOnTarget(7, enemyChara.GameObject())) { if (!needsTarget) { - if (GetTargetDistance(Svc.Objects.First(x => x.EntityId == enemyObjectId)) <= sheetSpell.EffectRange) + if (GetTargetDistance(enemyChara) - enemyChara.HitboxRadius <= sheetSpell.EffectRange) count++; } else { - if (Svc.Targets.Target != null) + if (target != null) { for (int t = 0; t < enemies.Count(); t++) { - var nearbyEnemy = enemies[t].EntityId; - var nearbyChara = CharacterManager.Instance()->LookupBattleCharaByEntityId(nearbyEnemy); - if (nearbyChara is null) continue; - if (Svc.Objects.FindFirst(x => x.EntityId == enemyObjectId, out var tar)) + var nearEnemy = enemies[t]; + if (GetTargetDistance(nearEnemy, target) - nearEnemy.HitboxRadius <= sheetSpell.EffectRange) { - if (tar.IsDead) continue; - - if (GetTargetDistance(tar, Svc.Targets.Target) <= sheetSpell.EffectRange) - { - count++; - } + count++; } + } - - Svc.Log.Debug($"{count}"); return count; } } From 3a2cb30e2868e2995fff70a046433233d34fd4c2 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:23:55 -0500 Subject: [PATCH 058/208] Added VPR and PCT to /scombo debug --- XIVSlothCombo/XIVSlothCombo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 1e75ea445..8e21ca3a3 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -527,6 +527,8 @@ private void OnCommand(string command, string arguments) 38 => typeof(DNC.Config), 39 => typeof(RPR.Config), 40 => typeof(SGE.Config), + 41 => typeof(VPR.Config), + 42 => typeof(PCT.Config), _ => throw new NotImplementedException(), }; From e8c83f948658ed0fef2f258424920babe74cd608 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Tue, 3 Sep 2024 20:46:57 -0600 Subject: [PATCH 059/208] Increase the maximum wait time for Tech --- XIVSlothCombo/Combos/PvE/DNC.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index 60e102f75..b7c4bce80 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -271,7 +271,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var needToTech = IsEnabled(CustomComboPreset.DNC_ST_Adv_TS) && // Enabled - GetCooldownRemainingTime(TechnicalStep) < 0.05f && // Up or about to be (some anti-drift) + GetCooldownRemainingTime(TechnicalStep) < 0.3f && // Up or about to be (some anti-drift) !HasEffect(Buffs.StandardStep) && // After Standard IsOnCooldown(StandardStep) && GetTargetHPPercent() > targetHpThresholdTechnical &&// HP% check From 2b655d6079bbac198a05e7f78af4f41cb1b5c6bb Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Tue, 3 Sep 2024 21:32:58 -0600 Subject: [PATCH 060/208] Further Increase the maximum wait time for Tech, And make it easier to manage --- XIVSlothCombo/Combos/PvE/DNC.cs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index b7c4bce80..70cc7532f 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -269,14 +269,30 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var targetHpThresholdTechnical = Config.DNC_ST_Adv_TSBurstPercent; var gcd = GetCooldown(Fountain).CooldownTotal; + // Thresholds to wait for TS/SS to come off CD + var longAlignmentThreshold = 0.6f; + var shortAlignmentThreshold = 0.3f; + if (IsEnabled(CustomComboPreset.DNC_ST_Adv_Flourish_ForcedTripleWeave)) + { + longAlignmentThreshold = 0.3f; + shortAlignmentThreshold = 0.1f; + } + var needToTech = IsEnabled(CustomComboPreset.DNC_ST_Adv_TS) && // Enabled - GetCooldownRemainingTime(TechnicalStep) < 0.3f && // Up or about to be (some anti-drift) + GetCooldownRemainingTime(TechnicalStep) < longAlignmentThreshold && // Up or about to be (some anti-drift) !HasEffect(Buffs.StandardStep) && // After Standard IsOnCooldown(StandardStep) && GetTargetHPPercent() > targetHpThresholdTechnical &&// HP% check LevelChecked(TechnicalStep); + // More Threshold, but only for SS + if (IsEnabled(CustomComboPreset.DNC_ST_Adv_SS_Hold)) + { + longAlignmentThreshold = gcd; + shortAlignmentThreshold = gcd; + } + var needToStandardOrFinish = IsEnabled(CustomComboPreset.DNC_ST_Adv_SS) && // Enabled GetTargetHPPercent() > targetHpThresholdStandard && // HP% check @@ -287,17 +303,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var needToFinish = HasEffect(Buffs.FinishingMoveReady) && !HasEffect(Buffs.LastDanceReady) && - ((GetCooldownRemainingTime(StandardStep) < 0.3f && // About to be up - some more aggressive anti-drift + ((GetCooldownRemainingTime(StandardStep) < longAlignmentThreshold && // About to be up - some more aggressive anti-drift HasEffect(Buffs.TechnicalFinish)) || (!HasEffect(Buffs.TechnicalFinish) && // Anti-Drift outside of Tech - GetCooldownRemainingTime(StandardStep) < 0.05f)); + GetCooldownRemainingTime(StandardStep) < shortAlignmentThreshold)); var needToStandard = - ((!IsEnabled(CustomComboPreset.DNC_ST_Adv_SS_Hold) && - GetCooldownRemainingTime(StandardStep) < 0.1f) || // Up or about to be (some anti-drift) - IsEnabled(CustomComboPreset.DNC_ST_Adv_SS_Hold) && - GetCooldownRemainingTime(StandardStep) < gcd) // About to be up next GCD - && + GetCooldownRemainingTime(StandardStep) < longAlignmentThreshold && // Up or about to be (some anti-drift) !HasEffect(Buffs.FinishingMoveReady) && (IsOffCooldown(Flourish) || GetCooldownRemainingTime(Flourish) > 5) && From 57106b870cf4d2d12d3aee5d530fc6f082d7c482 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Tue, 3 Sep 2024 22:37:15 -0600 Subject: [PATCH 061/208] Move the Hold Option to only apply to SS, not FM --- XIVSlothCombo/Combos/PvE/DNC.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index 70cc7532f..f29d0c724 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -286,13 +286,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim GetTargetHPPercent() > targetHpThresholdTechnical &&// HP% check LevelChecked(TechnicalStep); - // More Threshold, but only for SS - if (IsEnabled(CustomComboPreset.DNC_ST_Adv_SS_Hold)) - { - longAlignmentThreshold = gcd; - shortAlignmentThreshold = gcd; - } - var needToStandardOrFinish = IsEnabled(CustomComboPreset.DNC_ST_Adv_SS) && // Enabled GetTargetHPPercent() > targetHpThresholdStandard && // HP% check @@ -300,6 +293,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim GetCooldownRemainingTime(TechnicalStep) > 5) && // Don't mangle LevelChecked(StandardStep); + // More Threshold, but only for SS + if (IsEnabled(CustomComboPreset.DNC_ST_Adv_SS_Hold)) + { + longAlignmentThreshold = gcd; + shortAlignmentThreshold = gcd; + } + var needToFinish = HasEffect(Buffs.FinishingMoveReady) && !HasEffect(Buffs.LastDanceReady) && From 6cc5e43f583444f278c5db3291eb322ecdb1bb98 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Tue, 3 Sep 2024 23:41:46 -0600 Subject: [PATCH 062/208] Clarify DNC's Anti-Drift Options --- XIVSlothCombo/Combos/CustomComboPreset.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..c9e19e606 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -854,18 +854,19 @@ public enum CustomComboPreset [ParentCombo(DNC_ST_AdvancedMode)] [ConflictingCombos(DNC_ST_Adv_StandardFill)] - [CustomComboInfo("Standard Dance Option", "Includes Standard Step (and all steps) in the rotation.", DNC.JobID, 1)] + [CustomComboInfo("Standard Dance Option", "Includes Standard Step, all dance steps, and Finish in the rotation." + + "\nIt is recommended to use one of the two Anti-Drift options along with this.", DNC.JobID, 1)] DNC_ST_Adv_SS = 4052, [ParentCombo(DNC_ST_Adv_SS)] - [ConflictingCombos(DNC_ST_Adv_StandardFill)] [CustomComboInfo("Standard Dance Opener Option", "Starts Standard Step (and steps) before combat.", DNC.JobID)] DNC_ST_Adv_SS_Prepull = 4090, [ParentCombo(DNC_ST_Adv_SS)] [ConflictingCombos(DNC_ST_Adv_Flourish_ForcedTripleWeave)] - [CustomComboInfo("Hold Standard Dance Option", "Will hold GCDs for Standard Step if it is going to come off cooldown before your next GCD. This WILL give you down-time." + - "\nThis is recommended by The Balance if you have any extra skill speed, but this can also just be a good anti-drift option.", DNC.JobID)] + [CustomComboInfo("Hold for Standard Option (Anti-Drift)", "Will hold GCDs for Standard Step if it is going to come off cooldown before your next GCD." + + "\nThis WILL give you down-time." + + "\nONLY recommended if you have extra skill speed, but can be used as an anti-drift option.", DNC.JobID)] DNC_ST_Adv_SS_Hold = 4091, [ParentCombo(DNC_ST_AdvancedMode)] @@ -881,7 +882,8 @@ public enum CustomComboPreset [ParentCombo(DNC_ST_AdvancedMode)] [ConflictingCombos(DNC_ST_Adv_TechFill)] - [CustomComboInfo("Technical Dance Option", "Includes Technical Step, all dance steps and Technical Finish in the rotation.", DNC.JobID, 4)] + [CustomComboInfo("Technical Dance Option", "Includes Technical Step, all dance steps, and Finish in the rotation." + + "\nIt is recommended to use one of the two Anti-Drift options along with this.", DNC.JobID, 4)] DNC_ST_Adv_TS = 4053, [ParentCombo(DNC_ST_AdvancedMode)] @@ -902,8 +904,9 @@ public enum CustomComboPreset [ParentCombo(DNC_ST_Adv_Flourish)] [ConflictingCombos(DNC_ST_Adv_SS_Hold)] - [CustomComboInfo("Force Triple Weave for alignment", "Forces a triple weave of Flourish and Fan Dance 3 + 4 during non-opener burst windows." + - "\nFixes SS/FM drift where you use a gcd when SS/FM is on a 0.5sec CD.", DNC.JobID, 1)] + [CustomComboInfo("Force Triple Weave Option (Anti-Drift)", "Forces a triple weave of Flourish and Fan Dance 3 + 4 during non-opener burst windows." + + "\nFixes SS/FM drift where you use a gcd when SS/FM is on a 0.5sec CD." + + "\nRecommended to help prevent drift.", DNC.JobID, 1)] DNC_ST_Adv_Flourish_ForcedTripleWeave = 4088, [ParentCombo(DNC_ST_AdvancedMode)] From ab85edb9e4ca8399369375ea1f2bf52f060c11f9 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 4 Sep 2024 09:35:53 +0100 Subject: [PATCH 063/208] Autorot fixes --- .../AutoRotation/AutoRotationController.cs | 24 ++++++++++--------- XIVSlothCombo/Combos/CustomComboPreset.cs | 2 ++ XIVSlothCombo/Combos/PvE/MCH.cs | 6 ++--- XIVSlothCombo/Window/Functions/Presets.cs | 4 ++-- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 5f8282427..48066bb3b 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -1,4 +1,5 @@ using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Plugin.Internal.Types.Manifest; using ECommons.DalamudServices; using ECommons.GameFunctions; using ECommons.GameHelpers; @@ -36,14 +37,12 @@ internal static void Run() var action = attributes.AutoAction; var gameAct = attributes.ReplaceSkill.ActionIDs.First(); var sheetAct = Svc.Data.GetExcelSheet().GetRow(gameAct); - var classId = CustomComboFunctions.JobIDs.JobToClass((uint)Player.Job); if ((byte)Player.Job != attributes.CustomComboInfo.JobID) continue; - + var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); var healTarget = AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode); var aoeHeal = HealerTargeting.GetPartyMax(outAct, out int count) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP && count >= 2; - if (action.IsHeal) { AutomateHealing(preset.Key, attributes, gameAct); @@ -57,8 +56,7 @@ internal static void Run() //} if (healTarget == null && !aoeHeal) - if (AutomateDPS(preset.Key, attributes, gameAct)) - return; + AutomateDPS(preset.Key, attributes, gameAct); } @@ -189,11 +187,14 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset if (CustomComboFunctions.IsMoving && castTime > 0) return false; - var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, (GameObject*)target.Address) != 562; - if (inRange) + var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, target.Struct()) != 562; + var canUseTarget = ActionManager.CanUseActionOnTarget(outAct, target.Struct()); + var canUseSelf = ActionManager.CanUseActionOnTarget(outAct, Player.GameObject); + var canUse = canUseSelf || canUseTarget; + if (canUse) { Svc.Targets.Target = target; - ActionManager.Instance()->UseAction(ActionType.Action, outAct, target.GameObjectId); + ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); return true; } @@ -224,11 +225,11 @@ public static class DPSTargeting { public static IGameObject? GetTankTarget() { - var tank = Svc.Party.Where(x => x is IBattleChara chara && chara.GetRole() == CombatRole.Tank).FirstOrDefault(); + var tank = CustomComboFunctions.GetPartyMembers().Where(x => x.GetRole() == CombatRole.Tank).FirstOrDefault(); if (tank == null) return null; - return tank.GameObject.TargetObject; + return tank.TargetObject; } public static IGameObject? GetLowestCurrentTarget() @@ -271,8 +272,9 @@ public static class HealerTargeting internal static float GetPartyMax(uint outAct, out int count) { var members = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.InActionRange(outAct, x)); - var avg = members.Average(x => CustomComboFunctions.GetTargetHPPercent(x)); count = members.Count(); + if (count == 0) return 0; + var avg = members.Average(x => CustomComboFunctions.GetTargetHPPercent(x)); return avg; } } diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 00198c276..ea155c650 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1736,6 +1736,7 @@ public enum CustomComboPreset #region Simple ST + [AutoAction(false,false)] [ReplaceSkill(MCH.SplitShot, MCH.HeatedSplitShot)] [ConflictingCombos(MCH_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Split Shot with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", MCH.JobID)] @@ -1820,6 +1821,7 @@ public enum CustomComboPreset #region Simple AoE + [AutoAction(true,false)] [ReplaceSkill(MCH.SpreadShot)] [ConflictingCombos(MCH_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Spread Shot with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", MCH.JobID)] diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index cc29a8ddd..7efd0ec0f 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -122,9 +122,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim CanWeave(actionID)) return Variant.VariantRampart; - // Opener for MCH - if (MCHOpener.DoFullOpener(ref actionID)) - return actionID; + //// Opener for MCH + //if (MCHOpener.DoFullOpener(ref actionID)) + // return actionID; // Interrupt if (interruptReady) diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index d24eb31a6..8a37b4fe2 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -147,7 +147,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.Indent(); foreach (var conflict in conflicts) { - var comboInfo = Attributes.ContainsKey(conflict) ? Attributes[conflict].CustomComboInfo : conflict.GetAttribute(); + var comboInfo = Attributes[conflict].CustomComboInfo; conflictBuilder.Insert(0, $"{comboInfo.Name}"); var par2 = conflict; @@ -156,7 +156,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo var subpar = PresetStorage.GetParent(par2); if (subpar != null) { - conflictBuilder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo : subpar?.GetAttribute().Name)} -> "); + conflictBuilder.Insert(0, $"{Attributes[subpar.Value].CustomComboInfo.Name} -> "); par2 = subpar!.Value; } From bdcc1e5cce08b974b32aabae0c737eb0e461d9db Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 4 Sep 2024 07:18:08 -0400 Subject: [PATCH 064/208] Wide volley fixed to account for barrage buff --- XIVSlothCombo/Combos/PvE/BRD.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 39f1df502..dcde8ae08 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -490,7 +490,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } - bool wideVolleyReady = LevelChecked(WideVolley) && HasEffect(Buffs.HawksEye); + bool wideVolleyReady = LevelChecked(WideVolley) && (HasEffect(Buffs.HawksEye) || HasEffect(Buffs.Barrage)); bool blastArrowReady = LevelChecked(BlastArrow) && HasEffect(Buffs.BlastArrowReady); bool resonantArrowReady = LevelChecked(ResonantArrow) && HasEffect(Buffs.ResonantArrowReady); @@ -1114,7 +1114,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } - bool wideVolleyReady = LevelChecked(WideVolley) && HasEffect(Buffs.HawksEye); + bool wideVolleyReady = LevelChecked(WideVolley) && (HasEffect(Buffs.HawksEye) || HasEffect(Buffs.Barrage)); bool blastArrowReady = LevelChecked(BlastArrow) && HasEffect(Buffs.BlastArrowReady); bool resonantArrowReady = LevelChecked(ResonantArrow) && HasEffect(Buffs.ResonantArrowReady); From 2b7a3dcebcc3301f9777ccb279730347b0e7e6d8 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 4 Sep 2024 13:45:47 +0100 Subject: [PATCH 065/208] Autorots wired up, tank logic started --- .../AutoRotation/AutoRotationController.cs | 67 +++++++++++--- XIVSlothCombo/Combos/CustomComboPreset.cs | 92 +++++++++++++------ XIVSlothCombo/Combos/PvE/MCH.cs | 6 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 5 +- 4 files changed, 128 insertions(+), 42 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 48066bb3b..3de6693b2 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -24,7 +24,7 @@ internal static void Run() if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) return; - if (!EzThrottler.Throttle("AutoRotController", 750)) + if (!EzThrottler.Throttle("AutoRotController", 100)) return; var c = 0; @@ -49,11 +49,11 @@ internal static void Run() continue; } - //if (Player.Object.GetRole() is CombatRole.Tank) - //{ - // AutomateTanking(preset.Key, attributes, gameAct); - // continue; - //} + if (Player.Object.GetRole() is CombatRole.Tank) + { + AutomateTanking(preset.Key, attributes, gameAct); + continue; + } if (healTarget == null && !aoeHeal) AutomateDPS(preset.Key, attributes, gameAct); @@ -75,27 +75,28 @@ private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttribut } } - private static void AutomateTanking(CustomComboPreset key, Presets.PresetAttributes attributes, uint gameAct) + private static bool AutomateTanking(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { + var mode = Service.Configuration.RotationConfig.TankRotationMode; if (attributes.AutoAction.IsAoE) { - + return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); } else { - + return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); } } private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { + var mode = Service.Configuration.RotationConfig.HealerRotationMode; if (attributes.AutoAction.IsAoE) { return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); } else { - var mode = Service.Configuration.RotationConfig.HealerRotationMode; return AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); } } @@ -131,7 +132,16 @@ public static class AutoRotationHelper } if (rotationMode is TankRotationMode tankmode) { - + if (Player.Object.GetRole() != CombatRole.Tank) return null; + IGameObject? target = tankmode switch + { + TankRotationMode.Manual => Svc.Targets.Target, + TankRotationMode.Highest_Max => TankTargeting.GetHighestMaxTarget(), + TankRotationMode.Lowest_Max => TankTargeting.GetLowestMaxTarget(), + TankRotationMode.Highest_Current => TankTargeting.GetHighestCurrentTarget(), + TankRotationMode.Lowest_Current => TankTargeting.GetLowestCurrentTarget(), + }; + return target; } return null; @@ -278,5 +288,40 @@ internal static float GetPartyMax(uint outAct, out int count) return avg; } } + + public static class TankTargeting + { + public static IGameObject? GetLowestCurrentTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) + .OrderByDescending(x => x.TargetObject != Player.Object) + .ThenBy(x => (x as IBattleChara).CurrentHp) + .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + } + + public static IGameObject? GetHighestCurrentTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) + .OrderByDescending(x => x.TargetObject != Player.Object) + .ThenByDescending(x => (x as IBattleChara).CurrentHp) + .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + } + + public static IGameObject? GetLowestMaxTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) + .OrderByDescending(x => x.TargetObject != Player.Object) + .ThenBy(x => (x as IBattleChara).MaxHp) + .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + } + + public static IGameObject? GetHighestMaxTarget() + { + return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) + .OrderByDescending(x => x.TargetObject != Player.Object) + .ThenByDescending(x => (x as IBattleChara).MaxHp) + .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + } + } } } diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index ea155c650..d95e70d0b 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -369,10 +369,12 @@ public enum CustomComboPreset #region BLACK MAGE + [AutoAction(false, false)] [ReplaceSkill(BLM.Fire)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -10)] BLM_ST_SimpleMode = 2012, + [AutoAction(true, false)] [ReplaceSkill(BLM.Blizzard2, BLM.HighBlizzard2)] [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -8)] BLM_AoE_SimpleMode = 2008, @@ -559,21 +561,25 @@ public enum CustomComboPreset #region BARD + [AutoAction(false, false)] [ReplaceSkill(BRD.HeavyShot, BRD.BurstShot)] [ConflictingCombos(BRD_ST_AdvMode)] [CustomComboInfo("Simple Mode - Single Target", "Adds every single target ability to one button,\nIf there are DoTs on target, will try to maintain their uptime.", BRD.JobID)] BRD_ST_SimpleMode = 3036, + [AutoAction(true, false)] [ConflictingCombos(BRD_AoE_Combo, BRD_AoE_AdvMode)] [ReplaceSkill(BRD.QuickNock, BRD.Ladonsbite)] [CustomComboInfo("Simple Mode - AoE", "Weaves oGCDs onto Quick Nock/Ladonsbite.", BRD.JobID)] BRD_AoE_SimpleMode = 3035, + [AutoAction(false, false)] [ReplaceSkill(BRD.HeavyShot, BRD.BurstShot)] [ConflictingCombos(BRD_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Adds every single target ability to one button,\nIf there are DoTs on target, will try to maintain their uptime.", BRD.JobID)] BRD_ST_AdvMode = 3009, + [AutoAction(true, false)] [ConflictingCombos(BRD_AoE_Combo, BRD_AoE_SimpleMode)] [ReplaceSkill(BRD.QuickNock, BRD.Ladonsbite)] [CustomComboInfo("Advanced Mode - AoE", "Weaves oGCDs onto Quick Nock/Ladonsbite.", BRD.JobID)] @@ -728,6 +734,7 @@ public enum CustomComboPreset #region DANCER #region Single Target Multibutton + [AutoAction(false, false)] [ReplaceSkill(DNC.Cascade)] [ConflictingCombos(DNC_ST_AdvancedMode, DNC_AoE_AdvancedMode)] [CustomComboInfo("Single Target Multibutton Feature", "Single target combo with Fan Dances and Esprit use.", DNC.JobID)] @@ -747,6 +754,7 @@ public enum CustomComboPreset #endregion #region AoE Multibutton + [AutoAction(true, false)] [ReplaceSkill(DNC.Windmill)] [ConflictingCombos(DNC_ST_AdvancedMode, DNC_AoE_AdvancedMode)] [CustomComboInfo("AoE Multibutton Feature", "AoE combo with Fan Dances and Esprit use.", DNC.JobID)] @@ -847,6 +855,7 @@ public enum CustomComboPreset DNC_TechnicalStep_Devilment = 4087, #region Advanced Dancer (Single Target) + [AutoAction(false, false)] [ReplaceSkill(DNC.Cascade)] [ConflictingCombos(DNC_ST_MultiButton, DNC_AoE_MultiButton, DNC_DanceComboReplacer, DNC_FlourishingFeatures_Menu, DNC_Starfall_Devilment)] [CustomComboInfo("Advanced Dancer (Single Target) Feature", "Single button, single target. Can include songs, flourishes, overcap protections, and more.", DNC.JobID, 0)] @@ -951,6 +960,7 @@ public enum CustomComboPreset #endregion #region Advanced Dancer (AoE) + [AutoAction(true, false)] [ReplaceSkill(DNC.Windmill)] [ConflictingCombos(DNC_ST_MultiButton, DNC_AoE_MultiButton, DNC_DanceComboReplacer, DNC_FlourishingFeatures_Menu, DNC_Starfall_Devilment)] [CustomComboInfo("Advanced Dancer (AoE) Feature", "Single button, AoE. Includes songs, flourishes, overcap protections, and more." + @@ -1047,7 +1057,7 @@ public enum CustomComboPreset #region DARK KNIGHT #region Advanced Single Target Combo - + [AutoAction(false, false)] [ReplaceSkill(DRK.HardSlash)] [CustomComboInfo("Advanced Mode - Single Target", "Replace Hard Slash with a customizable all-in-one button rotation.\nFeatures can be toggled on or off to suit your playstyle.", DRK.JobID)] DRK_ST_Combo = 5001, @@ -1138,7 +1148,7 @@ public enum CustomComboPreset // Last value = 5015 #region Advanced Multi Target Combo - + [AutoAction(true, false)] [ReplaceSkill(DRK.Unleash)] [CustomComboInfo("Advanced Mode - AoE", "Replace Unleash with a customizable all-in-one button rotation.\nFeatures can be toggled on or off to suit your playstyle.", DRK.JobID)] DRK_AoE_Combo = 5016, @@ -1238,14 +1248,14 @@ public enum CustomComboPreset #endregion #region DRAGOON - + [AutoAction(false, false)] [ReplaceSkill(DRG.TrueThrust)] [ConflictingCombos(DRG_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces True Thrust with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", DRG.JobID)] DRG_ST_SimpleMode = 6001, #region Advanced ST Dragoon - + [AutoAction(false, false)] [ReplaceSkill(DRG.TrueThrust)] [ConflictingCombos(DRG_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces True Thrust with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", DRG.JobID)] @@ -1344,14 +1354,14 @@ public enum CustomComboPreset DRG_TrueNorthDynamic = 6199, #endregion - + [AutoAction(true, false)] [ReplaceSkill(DRG.DoomSpike)] [ConflictingCombos(DRG_AOE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Doom Spike with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", DRG.JobID)] DRG_AOE_SimpleMode = 6200, #region Advanced AoE Dragoon - + [AutoAction(true, false)] [ReplaceSkill(DRG.DoomSpike)] [ConflictingCombos(DRG_AOE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Doom Spike with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", DRG.JobID)] @@ -1469,6 +1479,7 @@ public enum CustomComboPreset #region GUNBREAKER #region Simple ST + [AutoAction(false, false)] [ConflictingCombos(GNB_ST_Advanced, GNB_NM_Features)] [ReplaceSkill(GNB.KeenEdge)] [CustomComboInfo("Simple Mode - Single Target", "Replace Keen Edge with its combo chain.\n This is the ideal selection for newcomers to the job.", GNB.JobID)] @@ -1476,6 +1487,7 @@ public enum CustomComboPreset #endregion #region Simple AOE + [AutoAction(true, false)] [ConflictingCombos(GNB_AoE_Advanced, GNB_NM_Features)] [ReplaceSkill(GNB.DemonSlice)] [CustomComboInfo("Simple Mode - AoE", "Replace Demon Slice with its combo chain.\n This is the ideal selection for newcomers to the job.", GNB.JobID)] @@ -1483,6 +1495,7 @@ public enum CustomComboPreset #endregion #region Advanced ST + [AutoAction(false, false)] [ConflictingCombos(GNB_ST_Simple)] [ReplaceSkill(GNB.KeenEdge)] [CustomComboInfo("Advanced Mode - Single Target", "Replace Keen Edge with its combo chain.\n Uses Burst Strike when you have 3 cartridges & your last combo action was Brutal Shell.", GNB.JobID)] @@ -1546,6 +1559,7 @@ public enum CustomComboPreset #endregion #region Advanced AoE + [AutoAction(true, false)] [ConflictingCombos(GNB_AoE_Simple)] [ReplaceSkill(GNB.DemonSlice)] [CustomComboInfo("Advanced Mode - AoE", "Replace Demon Slice with its combo chain.", GNB.JobID)] @@ -1745,7 +1759,7 @@ public enum CustomComboPreset #endregion #region Advanced ST - + [AutoAction(false, false)] [ReplaceSkill(MCH.SplitShot, MCH.HeatedSplitShot)] [ConflictingCombos(MCH_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Split Shot with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", MCH.JobID)] @@ -1830,7 +1844,7 @@ public enum CustomComboPreset #endregion #region Advanced AoE - + [AutoAction(true, false)] [ReplaceSkill(MCH.SpreadShot, MCH.Scattergun)] [ConflictingCombos(MCH_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Spread Shot with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", MCH.JobID)] @@ -1953,11 +1967,13 @@ public enum CustomComboPreset #region MONK + [AutoAction(false, false)] [ReplaceSkill([MNK.Bootshine])] [CustomComboInfo("Simple Mode - Single Target", "Replaces Bootshine with a one - button full single target rotation.\nThis is ideal for newcomers to the job.", MNK.JobID)] [ConflictingCombos(MNK_ST_BeastChakras, MNK_ST_AdvancedMode)] MNK_ST_SimpleMode = 9004, + [AutoAction(true, false)] [ReplaceSkill([MNK.ArmOfTheDestroyer])] [CustomComboInfo("Simple Mode - AoE", "Replaces Arm of the Destroyer with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", MNK.JobID)] MNK_AOE_SimpleMode = 9003, @@ -2072,6 +2088,7 @@ public enum CustomComboPreset #region NINJA + [AutoAction(false, false)] [ReplaceSkill(NIN.SpinningEdge)] [ConflictingCombos(NIN_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Spinning Edge with a one-button full single target rotation.\nThis is the ideal option for newcomers to the job.", NIN.JobID)] @@ -2081,11 +2098,13 @@ public enum CustomComboPreset [CustomComboInfo("Balance Opener Option", "Starts with the Balance opener.\nRequires level 100, with the following requirements:\n- 2 mudra charges ready\n- Dokumori off cooldown.\n- Kunai's Bane off cooldown.\n- TenChiJin off cooldown.\n- Phantom Kamaitachi off cooldown.\n- Bunshin off cooldown.\n- Dream Within a Dream off cooldown.\n- Kassatsu off cooldown.", NIN.JobID)] NIN_ST_SimpleMode_BalanceOpener = 10001, + [AutoAction(true, false)] [ReplaceSkill(NIN.DeathBlossom)] [ConflictingCombos(NIN_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Turns Death Blossom into a one-button full AoE rotation.", NIN.JobID)] NIN_AoE_SimpleMode = 10002, + [AutoAction(false, false)] [ReplaceSkill(NIN.SpinningEdge)] [ConflictingCombos(NIN_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replace Spinning Edge with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", NIN.JobID)] @@ -2209,6 +2228,7 @@ public enum CustomComboPreset [CustomComboInfo("Bloodbath Option", "Adds Bloodbath to Advanced Mode.", NIN.JobID)] NIN_ST_AdvancedMode_Bloodbath = 10034, + [AutoAction(true, false)] [ReplaceSkill(NIN.DeathBlossom)] [ConflictingCombos(NIN_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replace Death Blossom with a one-button full AoE rotation.\nThese features are ideal if you want to customize the rotation.", NIN.JobID)] @@ -2347,11 +2367,13 @@ public enum CustomComboPreset #region PICTOMANCER + [AutoAction(false, false)] [ReplaceSkill(PCT.FireInRed)] [ConflictingCombos(CombinedAetherhues, PCT_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Consolidates the single target rotation into one button, ideal for newcomers.", PCT.JobID)] PCT_ST_SimpleMode = 20000, + [AutoAction(true, false)] [ReplaceSkill(PCT.FireIIinRed)] [ConflictingCombos(CombinedAetherhues, PCT_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Consolidates the AoE rotation into one button, ideal for newcomers.", PCT.JobID)] @@ -2622,12 +2644,13 @@ public enum CustomComboPreset #region PALADIN // Simple Modes - + [AutoAction(false, false)] [ConflictingCombos(PLD_ST_AdvancedMode)] [ReplaceSkill(PLD.FastBlade)] [CustomComboInfo("Simple Mode - Single Target", $"Replaces Fast Blade with an all-in-one button rotation.\nThis is the ideal option for newcomers to the job.", PLD.JobID, 0)] PLD_ST_SimpleMode = 11000, + [AutoAction(true, false)] [ConflictingCombos(PLD_AoE_AdvancedMode)] [ReplaceSkill(PLD.TotalEclipse)] [CustomComboInfo("Simple Mode - AoE", $"Replaces Total Eclipse with an all-in-one button rotation.\nThis is the ideal option for newcomers to the job.", PLD.JobID, 1)] @@ -2635,6 +2658,7 @@ public enum CustomComboPreset // ST Advanced Mode + [AutoAction(false, false)] [ConflictingCombos(PLD_ST_SimpleMode)] [ReplaceSkill(PLD.FastBlade)] [CustomComboInfo("Advanced Mode - Single Target", $"Replaces Fast Blade with a customizable all-in-one button rotation.\nFeatures can be toggled on or off to suit your playstyle.", PLD.JobID, 2)] @@ -2698,6 +2722,7 @@ public enum CustomComboPreset // AoE Advanced Mode + [AutoAction(true, false)] [ConflictingCombos(PLD_AoE_SimpleMode)] [ReplaceSkill(PLD.TotalEclipse)] [CustomComboInfo("Advanced Mode - AoE", $"Replaces Total Eclipse with a customizable all-in-one button rotation.\nFeatures can be toggled on or off to suit your playstyle.", PLD.JobID, 3)] @@ -2791,7 +2816,7 @@ public enum CustomComboPreset #region REAPER #region Simple ST - + [AutoAction(false, false)] [ReplaceSkill(RPR.Slice)] [ConflictingCombos(RPR_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Slice with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", RPR.JobID)] @@ -2800,7 +2825,7 @@ public enum CustomComboPreset #endregion #region Advanced ST - + [AutoAction(false, false)] [ReplaceSkill(RPR.Slice)] [ConflictingCombos(RPR_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Slice with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", RPR.JobID)] @@ -2894,7 +2919,7 @@ public enum CustomComboPreset #endregion #region Simple AoE - + [AutoAction(true, false)] [ReplaceSkill(RPR.SpinningScythe)] [ConflictingCombos(RPR_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Spinning Scythe with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", RPR.JobID)] @@ -2903,7 +2928,7 @@ public enum CustomComboPreset #endregion #region Advanced AoE - + [AutoAction(true, false)] [ReplaceSkill(RPR.SpinningScythe)] [ConflictingCombos(RPR_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Spinning Scythe with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", RPR.JobID)] @@ -3069,6 +3094,7 @@ New features should be added to the appropriate sections. The three digets after RDM.JobID can be used to reorder items in the list */ #region Single Target DPS + [AutoAction(false, false)] [ReplaceSkill(RDM.Jolt, RDM.Jolt2)] [CustomComboInfo("Single Target DPS Features", "Enables various Single Target options below.", RDM.JobID, 1)] RDM_ST_DPS = 13000, @@ -3127,6 +3153,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region AoE DPS + [AutoAction(true, false)] [ReplaceSkill(RDM.Scatter, RDM.Impact)] [CustomComboInfo("AoE DPS Feature", "Enables various AoE Target options below.", RDM.JobID, 310)] RDM_AoE_DPS = 13310, @@ -3230,6 +3257,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #region SAGE #region Single Target DPS Feature + [AutoAction(false, false)] [ReplaceSkill(SGE.Dosis, SGE.Dosis2, SGE.Dosis3)] [CustomComboInfo("Single Target DPS Feature", "Adds various options to Dosis I/II/III.", SGE.JobID, 100)] SGE_ST_DPS = 14001, @@ -3273,6 +3301,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region AoE DPS Feature + [AutoAction(false, false)] [ReplaceSkill(SGE.Dyskrasia, SGE.Dyskrasia2)] [CustomComboInfo("AoE DPS Feature", "Adds various options to Dyskrasia I & II. Requires a target.", SGE.JobID, 200)] SGE_AoE_DPS = 14009, @@ -3307,6 +3336,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Diagnosis Simple Single Target Heal + [AutoAction(false, true)] [ReplaceSkill(SGE.Diagnosis)] [CustomComboInfo("Single Target Heal Feature", "Supports soft-targeting.\nOptions below are in priority order.", SGE.JobID, 300)] SGE_ST_Heal = 14014, @@ -3357,6 +3387,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Sage Simple AoE Heal + [AutoAction(true, true)] [ReplaceSkill(SGE.Prognosis)] [CustomComboInfo("AoE Heal Feature", "Customize your AoE healing to your liking.", SGE.JobID, 500)] SGE_AoE_Heal = 14026, @@ -3468,7 +3499,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #region SAMURAI #region Simple ST - + [AutoAction(false, false)] [ReplaceSkill(SAM.Hakaze, SAM.Gyofu)] [ConflictingCombos(SAM_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Hakaze/Gyofu with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", SAM.JobID)] @@ -3477,7 +3508,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Advanced ST - + [AutoAction(false, false)] [ReplaceSkill(SAM.Hakaze, SAM.Gyofu)] [ConflictingCombos(SAM_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Hakaze/Gyofu with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", SAM.JobID)] @@ -3559,7 +3590,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Simple AoE - + [AutoAction(true, false)] [ReplaceSkill(SAM.Fuga, SAM.Fuko)] [ConflictingCombos(SAM_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Fuga/Fuko with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", SAM.JobID)] @@ -3568,7 +3599,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region AoE Combos - + [AutoAction(true, false)] [ReplaceSkill(SAM.Fuga, SAM.Fuko)] [ConflictingCombos(SAM_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Fuga/Fuko with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", SAM.JobID)] @@ -3737,6 +3768,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #region SCHOLAR #region DPS + [AutoAction(false, false)] [ReplaceSkill(SCH.Ruin, SCH.Broil, SCH.Broil2, SCH.Broil3, SCH.Broil4, SCH.Bio, SCH.Bio2, SCH.Biolysis)] [CustomComboInfo("Single Target DPS Feature", "Replaces Ruin I / Broils with options below", SCH.JobID, 1)] SCH_DPS = 16001, @@ -3773,7 +3805,7 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Dissipation Opener Option", "Use Dissipation at the start of the battle.", SCH.JobID, 170)] SCH_DPS_Dissipation_Opener = 16009, - + [AutoAction(true, false)] [ReplaceSkill(SCH.ArtOfWar, SCH.ArtOfWarII)] [CustomComboInfo("AoE DPS Feature", "Replaces Art of War with options below.", SCH.JobID, 3)] SCH_AoE = 16010, @@ -3809,6 +3841,7 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Consolation During Seraph Option", "Adds Consolation during Seraph.", SCH.JobID)] SCH_Fairy_Combo_Consolation = 16017, + [AutoAction(true, true)] [ReplaceSkill(SCH.Succor)] [CustomComboInfo("AoE Heal Feature", "Replaces Succor with options below:", SCH.JobID, 5)] SCH_AoE_Heal = 16018, @@ -3829,6 +3862,7 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Indomitability Option", "Use Indomitability before using Succor.", SCH.JobID)] SCH_AoE_Heal_Indomitability = 16022, + [AutoAction(false, true)] [ReplaceSkill(SCH.Physick)] [CustomComboInfo("Single Target Heal Feature", "Change Physick into Adloquium, Lustrate, then Physick with below options:", SCH.JobID, 4)] SCH_ST_Heal = 16023, @@ -3903,7 +3937,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region SUMMONER - + [AutoAction(false, false)] [ReplaceSkill(SMN.Ruin, SMN.Ruin2, SMN.Outburst, SMN.Tridisaster)] [ConflictingCombos(SMN_Simple_Combo)] [CustomComboInfo("Advanced Summoner Feature", "Advanced combo features for a greater degree of customisation.\nAccommodates SpS builds.\nRuin III is left unchanged for mobility purposes.", SMN.JobID)] @@ -4015,6 +4049,7 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Add Egi Astralflow", "Choose which Egi Astralflows to add to the rotation.", SMN.JobID, 0)] SMN_ST_Egi_AstralFlow = 17048, + [AutoAction(false, false)] [ConflictingCombos(SMN_Advanced_Combo)] [ReplaceSkill(SMN.Ruin, SMN.Ruin2, SMN.Outburst, SMN.Tridisaster)] [CustomComboInfo("Simple Summoner Feature", "General purpose one-button combo.\nBursts on Bahamut phase.\nSummons Titan, Garuda, then Ifrit.\nSwiftcasts on Slipstream unless drifted.", SMN.JobID, -1)] @@ -4050,14 +4085,14 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region VIPER - + [AutoAction(false, false)] [ReplaceSkill(VPR.SteelFangs)] [ConflictingCombos(VPR_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Steel Fangs with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", VPR.JobID, -2)] VPR_ST_SimpleMode = 30000, #region Advanced ST Viper - + [AutoAction(false, false)] [ReplaceSkill(VPR.SteelFangs)] [ConflictingCombos(VPR_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Steel Fangs with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", VPR.JobID)] @@ -4128,13 +4163,14 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion + [AutoAction(true, false)] [ReplaceSkill(VPR.SteelMaw)] [ConflictingCombos(VPR_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Steel Maw with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", VPR.JobID, -1)] VPR_AoE_SimpleMode = 30100, #region Advanced AoE Viper - + [AutoAction(true, false)] [ReplaceSkill(VPR.SteelMaw)] [ConflictingCombos(VPR_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Steel Maw with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", VPR.JobID)] @@ -4230,6 +4266,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #region WARRIOR #region Simple ST + [AutoAction(false, false)] [ConflictingCombos(WAR_ST_Advanced)] [ReplaceSkill(WAR.StormsPath)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Storm's Path with a one-button full single target rotation.\nThis is the ideal selection for newcomers to the job.", WAR.JobID, 1)] @@ -4237,6 +4274,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Simple AoE + [AutoAction(true, false)] [ConflictingCombos(WAR_AoE_Advanced)] [ReplaceSkill(WAR.Overpower)] [CustomComboInfo("Simple Mode - AoE", "Replaces Overpower with a one-button full AoE rotation.\nThis is the ideal selection for newcomers to the job.", WAR.JobID, 1)] @@ -4244,6 +4282,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Advanced ST + [AutoAction(false, false)] [ConflictingCombos(WAR_ST_Simple)] [ReplaceSkill(WAR.StormsPath)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Storm's Path with a one-button full single target rotation.\nThis is the ideal selection for users experienced with the job.", WAR.JobID, 2)] @@ -4303,6 +4342,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Advanced AoE + [AutoAction(true, false)] [ConflictingCombos(WAR_AoE_Simple)] [ReplaceSkill(WAR.Overpower)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Overpower with a one-button full AoE rotation.\nThis is the ideal selection for users experienced with the job.", WAR.JobID, 2)] @@ -4377,7 +4417,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #region WHITE MAGE #region Single Target DPS Feature - + [AutoAction(false, false)] [ReplaceSkill(WHM.Stone1, WHM.Stone2, WHM.Stone3, WHM.Stone4, WHM.Glare1, WHM.Glare3)] [CustomComboInfo("Single Target DPS Feature", "Collection of cooldowns and spell features on Glare/Stone.", WHM.JobID, 1)] WHM_ST_MainCombo = 19099, @@ -4417,7 +4457,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region AoE DPS Feature - + [AutoAction(true, false)] [ReplaceSkill(WHM.Holy, WHM.Holy3)] [CustomComboInfo("AoE DPS Feature", "Collection of cooldowns and spell features on Holy/Holy III.", WHM.JobID, 2)] WHM_AoE_DPS = 19190, @@ -4457,7 +4497,7 @@ The three digets after RDM.JobID can be used to reorder items in the list WHM_RaptureMisery = 19001, #region AoE Heals Feature - + [AutoAction(true, true)] [ReplaceSkill(WHM.Medica1)] [CustomComboInfo("Simple Heals (AoE)", "Replaces Medica with a one button AoE healing setup.", WHM.JobID, 4)] WHM_AoEHeals = 19007, @@ -4505,7 +4545,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Single Target Heals - + [AutoAction(false, true)] [ReplaceSkill(WHM.Cure)] [CustomComboInfo("Simple Heals (Single Target)", "Replaces Cure with a one button single target healing setup.", WHM.JobID, 3)] WHM_STHeals = 19300, diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index 7efd0ec0f..cc29a8ddd 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -122,9 +122,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim CanWeave(actionID)) return Variant.VariantRampart; - //// Opener for MCH - //if (MCHOpener.DoFullOpener(ref actionID)) - // return actionID; + // Opener for MCH + if (MCHOpener.DoFullOpener(ref actionID)) + return actionID; // Interrupt if (interruptReady) diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 44ba82252..88939f3ae 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -420,16 +420,17 @@ public unsafe static bool EnemiesInRange(uint spellCheck) public unsafe static int NumberOfEnemiesInRange(uint aoeSpell, IGameObject? target) { + if (target is null) return 0; + ActionWatching.ActionSheet.Values.TryGetFirst(x => x.RowId == aoeSpell, out var sheetSpell); bool needsTarget = sheetSpell.CanTargetHostile; int count = 0; - var enemies = Svc.Objects.Where(x => x.ObjectKind == ObjectKind.BattleNpc && x.IsTargetable && !x.IsDead).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); + var enemies = Svc.Objects.Where(x => x != null && x.ObjectKind == ObjectKind.BattleNpc && x.IsTargetable && !x.IsDead).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); if (!ActionManager.CanUseActionOnTarget(7, target.Struct())) return 0; - for (int i = 0; i < enemies.Count(); i++) { var enemyChara = enemies[i]; From 9e2a8297e3c69e302b184b4091051516591c6dc6 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Wed, 4 Sep 2024 07:39:56 -0600 Subject: [PATCH 066/208] Check for older Delirium buff IDs Closes #1764 --- XIVSlothCombo/Combos/PvE/DRK.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK.cs index 6aeb752c1..7a8096509 100644 --- a/XIVSlothCombo/Combos/PvE/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK.cs @@ -59,6 +59,7 @@ public static class Buffs public const ushort // Main Buffs BloodWeapon = 742, + OlderDelirium = 1972, Delirium = 3836, // Periodic Buffs @@ -70,10 +71,10 @@ public const ushort Scorn = 3837; } - public static class Debuffs + public static class Traits { - public const ushort - Placeholder = 1; + public const uint + EnhancedDelirium = 572; } public static class Config @@ -245,7 +246,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim && IsEnabled(CustomComboPreset.DRK_ST_Bloodspiller)) { //Regular Bloodspiller - if (GetBuffStacks(Buffs.Delirium) > 0) + if (GetBuffStacks(Buffs.Delirium) > 0 + || (TraitLevelChecked(Traits.EnhancedDelirium) + && GetBuffStacks(Buffs.OlderDelirium) > 0)) return Bloodspiller; //Blood management before Delirium From a2ba562df28b17af49d20a78903ccebf462b52f6 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Wed, 4 Sep 2024 07:40:20 -0600 Subject: [PATCH 067/208] Clarify Delirium documentation --- XIVSlothCombo/Combos/PvE/DRK.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK.cs index 7a8096509..bb1521c40 100644 --- a/XIVSlothCombo/Combos/PvE/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK.cs @@ -245,18 +245,16 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Delirium) && IsEnabled(CustomComboPreset.DRK_ST_Bloodspiller)) { - //Regular Bloodspiller + //Bloodspiller under Delirium if (GetBuffStacks(Buffs.Delirium) > 0 || (TraitLevelChecked(Traits.EnhancedDelirium) && GetBuffStacks(Buffs.OlderDelirium) > 0)) return Bloodspiller; - //Blood management before Delirium + //Blood management outside of Delirium if (IsEnabled(CustomComboPreset.DRK_ST_Delirium) - && ( - (gauge.Blood >= 60 && GetCooldownRemainingTime(Delirium) is > 0 and < 3) - || (gauge.Blood >= 50 && GetCooldownRemainingTime(Delirium) > 37) - )) + && ((gauge.Blood >= 60 && GetCooldownRemainingTime(Delirium) is > 0 and < 3) // Prep for Delirium + || (gauge.Blood >= 50 && GetCooldownRemainingTime(Delirium) > 37))) // Regular Bloodspiller return Bloodspiller; } From af186e71e7ad2adf0f3aca86a7721addbda42b0c Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 4 Sep 2024 11:37:07 -0400 Subject: [PATCH 068/208] Made prepull its own option with specific wording. --- XIVSlothCombo/Combos/CustomComboPreset.cs | 6 +++++- XIVSlothCombo/Combos/PvE/AST.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..965de4250 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -222,6 +222,10 @@ public enum CustomComboPreset "\nTo be used in conjunction with Redirect/Reaction/etc", AST.JobID, 11)] AST_ST_DPS_EarthlyStar = 1051, + [ParentCombo(AST_ST_DPS)] + [CustomComboInfo("Earthly Star Prepull Option", "Adds Earthly Star Prepull." + + "\nIf using redirect stack, suggest target > melee > self", AST.JobID, 12)] + AST_ST_DPS_EarthlyStarPrepull = 1054, #endregion #region AOE DPS @@ -359,7 +363,7 @@ public enum CustomComboPreset AST_Cards_QuickTargetCards_TargetExtra = 1031, #endregion - // Last value = 1053 + // Last value = 1054 #endregion diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index be0728b4e..a9173be4e 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -220,7 +220,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ActionReady(OriginalHook(AstralDraw)) && (Gauge.DrawnCards.All(x => x is CardType.NONE) || (DrawnCard == CardType.NONE && Config.AST_ST_DPS_OverwriteCards))) return OriginalHook(AstralDraw); - if (IsEnabled(CustomComboPreset.AST_ST_DPS_EarthlyStar) && + if (IsEnabled(CustomComboPreset.AST_ST_DPS_EarthlyStarPrepull) && ActionReady(EarthlyStar)) return EarthlyStar; } From bd72ef15624bba8beeb0d70a605bae50c51d2e65 Mon Sep 17 00:00:00 2001 From: edewen Date: Wed, 4 Sep 2024 11:43:01 -0400 Subject: [PATCH 069/208] Reverted/removed prepull star --- XIVSlothCombo/Combos/CustomComboPreset.cs | 6 +----- XIVSlothCombo/Combos/PvE/AST.cs | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 965de4250..c50e1b62d 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -221,11 +221,7 @@ public enum CustomComboPreset [CustomComboInfo("Earthly Star Option", "Adds Earthly Star." + "\nTo be used in conjunction with Redirect/Reaction/etc", AST.JobID, 11)] AST_ST_DPS_EarthlyStar = 1051, - - [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Earthly Star Prepull Option", "Adds Earthly Star Prepull." + - "\nIf using redirect stack, suggest target > melee > self", AST.JobID, 12)] - AST_ST_DPS_EarthlyStarPrepull = 1054, + #endregion #region AOE DPS diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index a9173be4e..2ec8d483b 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -219,10 +219,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.AST_DPS_AutoDraw) && ActionReady(OriginalHook(AstralDraw)) && (Gauge.DrawnCards.All(x => x is CardType.NONE) || (DrawnCard == CardType.NONE && Config.AST_ST_DPS_OverwriteCards))) return OriginalHook(AstralDraw); - - if (IsEnabled(CustomComboPreset.AST_ST_DPS_EarthlyStarPrepull) && - ActionReady(EarthlyStar)) - return EarthlyStar; } //In combat if (((!AlternateMode && MaleficList.Contains(actionID)) || From 987b9c91b3c1ef22f3ce323d5edf9cc09c9ba3cd Mon Sep 17 00:00:00 2001 From: ace Date: Thu, 5 Sep 2024 02:18:08 -0700 Subject: [PATCH 070/208] big cleanup --- XIVSlothCombo/Combos/CustomComboPreset.cs | 60 ++++++++++---------- XIVSlothCombo/Combos/PvE/GNB.cs | 54 +++++++++--------- XIVSlothCombo/Window/Functions/UserConfig.cs | 4 +- 3 files changed, 60 insertions(+), 58 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 55b51da16..762ca54f4 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1484,59 +1484,61 @@ public enum CustomComboPreset [CustomComboInfo("Advanced Mode - Single Target", "Replace Keen Edge with its combo chain.\nThis is the ideal selection for experienced users of the job.", GNB.JobID)] GNB_ST_Advanced = 7003, - #region Lightning Shot - [ParentCombo(GNB_ST_Advanced)] - [CustomComboInfo("Lightning Shot Uptime Option", "Adds Lightning Shot to the main combo when you are out of range.", GNB.JobID)] - GNB_ST_RangedUptime = 7004, - #endregion - - #region Gnashing Fang - [ParentCombo(GNB_ST_Advanced)] - [CustomComboInfo("Continuation Option", "Adds Continuation & Hypervelocity into the rotation.\n'Gnashing Fang' option must be enabled or started manually.", GNB.JobID)] - GNB_ST_Continuation = 7005, - - [ParentCombo(GNB_ST_Continuation)] - [CustomComboInfo("Gnashing Fang Option", "Adds Gnashing Fang combo into the rotation.", GNB.JobID)] - GNB_ST_GnashingStarter = 7006, - #endregion - #region Cooldowns [ParentCombo(GNB_ST_Advanced)] [CustomComboInfo("Cooldowns Option", "Adds various cooldowns into the rotation.", GNB.JobID)] - GNB_ST_Advanced_CooldownsGroup = 7007, + GNB_ST_Advanced_CooldownsGroup = 7004, [ConflictingCombos(GNB_NM_Features)] [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("No Mercy Option", "Adds No Mercy into the rotation when appropriate.", GNB.JobID)] - GNB_ST_NoMercy = 7008, + GNB_ST_NoMercy = 7005, + + [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] + [CustomComboInfo("Sonic Break Option", "Adds Sonic Break into the rotation when appropriate.", GNB.JobID)] + GNB_ST_SonicBreak = 7006, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Danger/Blasting Zone Option", "Adds Danger/Blasting Zone into the rotation when available.", GNB.JobID)] - GNB_ST_BlastingZone = 7009, + GNB_ST_BlastingZone = 7007, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Bow Shock Option", "Adds Bow Shock into the rotation when appropriate.", GNB.JobID)] - GNB_ST_BowShock = 7010, + GNB_ST_BowShock = 7008, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Bloodfest Option", "Adds Bloodfest into the rotation when appropriate.", GNB.JobID)] - GNB_ST_Bloodfest = 7011, + GNB_ST_Bloodfest = 7009, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Sonic Break Option", "Adds Sonic Break into the rotation when appropriate.", GNB.JobID)] - GNB_ST_SonicBreak = 7012, + [CustomComboInfo("Gnashing Fang Option", "Adds Gnashing Fang combo into the rotation.", GNB.JobID)] + GNB_ST_Gnashing = 7010, + + [ParentCombo(GNB_ST_Gnashing)] + [CustomComboInfo("Continuation Option", "Adds Continuation & Hypervelocity into the rotation.\n'Gnashing Fang' option must be enabled or started manually.", GNB.JobID)] + GNB_ST_Continuation = 7011, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Double Down Option", "Adds Double Down into the rotation when appropriate.", GNB.JobID)] - GNB_ST_DoubleDown = 7013, + GNB_ST_DoubleDown = 7012, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] - [CustomComboInfo("Reign combo Option", "Adds Reign/Noble/Lionheart into the rotation when appropriate.", GNB.JobID)] - GNB_ST_Reign = 7014, + [CustomComboInfo("Reign Combo Option", "Adds Reign/Noble/Lionheart into the rotation when appropriate.", GNB.JobID)] + GNB_ST_Reign = 7013, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Burst Strike Option", "Adds Burst Strike into the rotation when appropriate.", GNB.JobID)] - GNB_ST_BurstStrike = 7015, + GNB_ST_BurstStrike = 7014, + + [ParentCombo(GNB_ST_Advanced)] + [CustomComboInfo("Ammo Overcap Option", "Adds Burst Strike into the AoE rotation if you have max cartridges & your last combo action was Brutal Shell.", GNB.JobID)] + GNB_ST_Overcap = 7015, + #endregion + + #region Lightning Shot + [ParentCombo(GNB_ST_Advanced)] + [CustomComboInfo("Lightning Shot Uptime Option", "Adds Lightning Shot to the main combo when you are out of range.", GNB.JobID)] + GNB_ST_RangedUptime = 7016, #endregion #endregion @@ -1585,11 +1587,11 @@ public enum CustomComboPreset GNB_AoE_noFatedCircle = 7209, [ParentCombo(GNB_AoE_Advanced)] - [CustomComboInfo("Ammo Overcap Option", "Adds Fated Circle into the AoE rotation if you have max cartridges & your last action was Demon Slice.", GNB.JobID)] + [CustomComboInfo("Ammo Overcap Option", "Adds Fated Circle into the AoE rotation if you have max cartridges & your last combo action was Demon Slice.", GNB.JobID)] GNB_AoE_Overcap = 7210, [ParentCombo(GNB_AoE_Overcap)] - [CustomComboInfo("Ammo Overcap Burst Strike Option", "Adds Burst Strike into the AoE rotation if you have max cartridges, your last action was Demon Slice, & you do not have Fated Circle unlocked yet.", GNB.JobID)] + [CustomComboInfo("Ammo Overcap Burst Strike Option", "Adds Burst Strike into the AoE rotation if you have max cartridges, your last combo action was Demon Slice, & you do not have Fated Circle unlocked yet.", GNB.JobID)] GNB_AoE_BSOvercap = 7211, #endregion diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index 6f7e6ed43..e86e7b607 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -102,7 +102,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return LightningShot; //NoMercy - if (ActionReady(NoMercy)) + if (ActionReady(NoMercy) && GetCooldownRemainingTime(DoubleDown) < GCD * 2 && GetCooldownRemainingTime(GnashingFang) < GCD * 3) { if (CanWeave(actionID)) { @@ -119,6 +119,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } + //Bloodfest + if (ActionReady(Bloodfest) && Ammo is 0 && (JustUsed(NoMercy, 20f))) + return Bloodfest; + //oGCDs if (CanWeave(actionID)) { @@ -133,10 +137,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.GNB_Variant_Ultimatum) && IsEnabled(Variant.VariantUltimatum) && ActionReady(Variant.VariantUltimatum)) return Variant.VariantUltimatum; - //Bloodfest - if (ActionReady(Bloodfest) && Ammo is 0 && (JustUsed(NoMercy, 20f))) - return Bloodfest; - //Zone if (ActionReady(DangerZone) && !JustUsed(NoMercy)) { @@ -225,7 +225,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Lv90-Lv99 - if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown) && GetCooldownRemainingTime(DoubleDown) <= 0.6f) + if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown) && GetCooldownRemainingTime(DoubleDown) <= 0.3f) { if ((Ammo >= 2 && !HasEffect(Buffs.ReadyToBreak) && JustUsed(SonicBreak, 3f) && (bfCD < GCD * 6 || ActionReady(Bloodfest))) //2min NM 3 carts || (!HasEffect(Buffs.ReadyToBreak) && Ammo == 3 && JustUsed(SonicBreak, 3f) && bfCD is < 90 and > 15) //1min NM 3 carts @@ -301,7 +301,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return BrutalShell; if (lastComboMove == BrutalShell && LevelChecked(SolidBarrel)) { - if (LevelChecked(Hypervelocity) && HasEffect(Buffs.ReadyToBlast) && nmCD > 1) //Lv100 Hypervelocity fit into NM check + if (LevelChecked(Hypervelocity) && HasEffect(Buffs.ReadyToBlast) && (nmCD is > 1 or <= 0.1f)) //Lv100 Hypervelocity fit into NM check return Hypervelocity; if (LevelChecked(BurstStrike) && Ammo == MaxCartridges(level)) return BurstStrike; @@ -349,7 +349,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //NoMercy if (IsEnabled(CustomComboPreset.GNB_ST_Advanced_CooldownsGroup) && IsEnabled(CustomComboPreset.GNB_ST_NoMercy)) { - if (ActionReady(NoMercy) && GetTargetHPPercent() >= nmStop) + if (ActionReady(NoMercy) && GetTargetHPPercent() >= nmStop && GetCooldownRemainingTime(DoubleDown) < GCD * 2 && GetCooldownRemainingTime(GnashingFang) < GCD * 3) { if (CanWeave(actionID)) { @@ -367,6 +367,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } + //Bloodfest - Forced to prevent combo from spazzing out due to next action possibly requiring Ammo + if (IsEnabled(CustomComboPreset.GNB_ST_Bloodfest) && ActionReady(Bloodfest) && Ammo is 0 && (JustUsed(NoMercy, 20f))) + return Bloodfest; + //oGCDs if (CanWeave(actionID)) { @@ -384,10 +388,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //CDs if (IsEnabled(CustomComboPreset.GNB_ST_Advanced_CooldownsGroup)) { - //Bloodfest - if (IsEnabled(CustomComboPreset.GNB_ST_Bloodfest) && ActionReady(Bloodfest) && Ammo is 0 && (JustUsed(NoMercy, 20f))) - return Bloodfest; - //Zone if (IsEnabled(CustomComboPreset.GNB_ST_BlastingZone) && ActionReady(DangerZone) && !JustUsed(NoMercy)) { @@ -396,7 +396,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !LevelChecked(GnashingFang))) // 17)) + if (LevelChecked(ReignOfBeasts) && (JustUsed(DoubleDown, 5f) || nmCD > 17)) return OriginalHook(DangerZone); } @@ -426,7 +426,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Hypervelocity - if (IsEnabled(CustomComboPreset.GNB_ST_Continuation) && JustUsed(BurstStrike) && LevelChecked(Hypervelocity) && HasEffect(Buffs.ReadyToBlast) && nmCD > 1) + if (IsEnabled(CustomComboPreset.GNB_ST_Continuation) && JustUsed(BurstStrike, 5f) && LevelChecked(Hypervelocity) && HasEffect(Buffs.ReadyToBlast) && nmCD > 1) return Hypervelocity; //GF combo @@ -442,7 +442,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if ((Ammo == 2 && JustUsed(NoMercy, 3f) && !HasEffect(Buffs.ReadyToBlast) && (bfCD < GCD * 12 || ActionReady(Bloodfest))) //2min || (JustUsed(GnashingFang, 3f) && bfCD is < 90 and > 15 && !ActionReady(DoubleDown) && Ammo == 0 && !HasEffect(Buffs.ReadyToRip) && HasEffect(Buffs.ReadyToBreak)) //1min 2cart || (Ammo == 3 && (bfCD is < 90 and > 15 && JustUsed(NoMercy, 3f)) //1min 3cart - || (JustUsed(Bloodfest, 2f) && JustUsed(BrutalShell)))) //opener + || (JustUsed(Bloodfest, 3f) && JustUsed(BrutalShell, 3f)))) //opener return SonicBreak; } @@ -452,7 +452,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (JustUsed(NoMercy, 3f) && ((!HasEffect(Buffs.ReadyToBlast) && Ammo == 3 && bfCD < GCD * 12 || ActionReady(Bloodfest)) //2min || (bfCD is < 90 and > 15 && Ammo == 3) //1min 3 carts - || (JustUsed(Bloodfest, 2f) && JustUsed(BrutalShell)))) //opener + || (JustUsed(Bloodfest, 3f) && JustUsed(BrutalShell)))) //opener return SonicBreak; } @@ -471,14 +471,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Lv100 if (LevelChecked(ReignOfBeasts) && GetCooldownRemainingTime(DoubleDown) < 0.7f) { - if ((JustUsed(SonicBreak, 3f) && !HasEffect(Buffs.ReadyToBreak) && bfCD < GCD * 6 || ActionReady(Bloodfest)) //2min - || (JustUsed(SonicBreak, 3f) && Ammo == 3) //1min NM 3 carts + if ((JustUsed(SonicBreak, 10f) && !HasEffect(Buffs.ReadyToBreak) && bfCD < GCD * 6 || ActionReady(Bloodfest)) //2min + || (JustUsed(SonicBreak, 10f) && Ammo == 3) //1min NM 3 carts || (JustUsed(SolidBarrel, 3f) && Ammo == 3 && HasEffect(Buffs.ReadyToBreak) && HasEffect(Buffs.NoMercy))) //1min NM 2 carts return DoubleDown; } //Lv90-Lv99 - if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown) && GetCooldownRemainingTime(DoubleDown) <= 0.6f) + if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown) && GetCooldownRemainingTime(DoubleDown) <= 0.3f) { if ((Ammo >= 2 && !HasEffect(Buffs.ReadyToBreak) && JustUsed(SonicBreak, 3f) && (bfCD < GCD * 6 || ActionReady(Bloodfest))) //2min NM 3 carts || (!HasEffect(Buffs.ReadyToBreak) && Ammo == 3 && JustUsed(SonicBreak, 3f) && bfCD is < 90 and > 15) //1min NM 3 carts @@ -498,7 +498,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //GnashingFang - if (IsEnabled(CustomComboPreset.GNB_ST_GnashingStarter) && LevelChecked(GnashingFang) && GetCooldownRemainingTime(GnashingFang) < 0.7f && Ammo > 0) + if (IsEnabled(CustomComboPreset.GNB_ST_Gnashing) && LevelChecked(GnashingFang) && GetCooldownRemainingTime(GnashingFang) < 0.7f && Ammo > 0) { if (!HasEffect(Buffs.ReadyToBlast) && GunStep == 0 && ActionReady(GnashingFang) && (LevelChecked(ReignOfBeasts) && HasEffect(Buffs.NoMercy) && JustUsed(DoubleDown, 3f)) //Lv100 odd/even minute use @@ -540,12 +540,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Lv100 2cart 2min starter - if (IsEnabled(CustomComboPreset.GNB_ST_Advanced_CooldownsGroup) && IsEnabled(CustomComboPreset.GNB_ST_BurstStrike) && + if (IsEnabled(CustomComboPreset.GNB_ST_Advanced_CooldownsGroup) && IsEnabled(CustomComboPreset.GNB_ST_BurstStrike) && GetTargetHPPercent() > nmStop && LevelChecked(ReignOfBeasts) && ((nmCD <= GCD || ActionReady(NoMercy)) && Ammo is 3 && (bfCD < GCD * 12 || ActionReady(Bloodfest)))) return BurstStrike; //GnashingFang combo safety net - if (IsEnabled(CustomComboPreset.GNB_ST_Continuation) && GunStep is 1 or 2) + if (IsEnabled(CustomComboPreset.GNB_ST_Gnashing) && GunStep is 1 or 2) return OriginalHook(GnashingFang); //123 (overcap included) @@ -555,9 +555,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return BrutalShell; if (lastComboMove == BrutalShell && LevelChecked(SolidBarrel)) { - if (LevelChecked(Hypervelocity) && HasEffect(Buffs.ReadyToBlast) && nmCD > 1) //Lv100 Hypervelocity fit into NM check + if (IsEnabled(CustomComboPreset.GNB_ST_Continuation) && LevelChecked(Hypervelocity) && HasEffect(Buffs.ReadyToBlast) && (nmCD is > 1 or <= 0.1f || GetTargetHPPercent() < nmStop)) //Lv100 Hypervelocity fit into NM check return Hypervelocity; - if (LevelChecked(BurstStrike) && Ammo == MaxCartridges(level)) + if (IsEnabled(CustomComboPreset.GNB_ST_Overcap) && LevelChecked(BurstStrike) && Ammo == MaxCartridges(level)) return BurstStrike; return SolidBarrel; } @@ -710,7 +710,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Lv90 - if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown) && GetCooldownRemainingTime(DoubleDown) <= 0.6f) + if (!LevelChecked(ReignOfBeasts) && LevelChecked(DoubleDown) && GetCooldownRemainingTime(DoubleDown) <= 0.3f) { if ((Ammo >= 2 && !HasEffect(Buffs.ReadyToBreak) && JustUsed(SonicBreak, 3f) && (bfCD < GCD * 6 || ActionReady(Bloodfest))) //2min NM 3 carts || (!HasEffect(Buffs.ReadyToBreak) && Ammo == 3 && JustUsed(SonicBreak, 3f) && bfCD is < 90 and > 15) //1min NM 3 carts @@ -997,7 +997,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.GNB_BS_Continuation) && HasEffect(Buffs.ReadyToBlast) && LevelChecked(Hypervelocity)) return Hypervelocity; - if (IsEnabled(CustomComboPreset.GNB_BS_Bloodfest) && Ammo is 0 && LevelChecked(Bloodfest) && !HasEffect(Buffs.ReadyToBlast) && bfCD < 0.6f) + if (IsEnabled(CustomComboPreset.GNB_BS_Bloodfest) && Ammo is 0 && LevelChecked(Bloodfest) && !HasEffect(Buffs.ReadyToBlast) && bfCD < 0.3f) return Bloodfest; if (IsEnabled(CustomComboPreset.GNB_BS_DoubleDown) && HasEffect(Buffs.NoMercy) && GetCooldownRemainingTime(DoubleDown) < 2 && Ammo >= 2 && LevelChecked(DoubleDown)) return DoubleDown; @@ -1009,7 +1009,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(ReignOfBeasts); } - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) + if (JustUsed(ReignOfBeasts, 10f) || JustUsed(NobleBlood, 10f)) { return OriginalHook(ReignOfBeasts); } diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 9895bba33..2f4622d16 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1519,9 +1519,9 @@ internal static void Draw(CustomComboPreset preset, bool enabled) if (preset == CustomComboPreset.GNB_Variant_Cure) UserConfig.DrawSliderInt(1, 100, GNB.Config.GNB_VariantCure, "HP% to be at or under", 200); if (preset == CustomComboPreset.GNB_ST_NoMercy) - UserConfig.DrawSliderInt(0, 10, GNB.Config.GNB_ST_NoMercyStop, "Disable Usage if Target HP% is below set value.\nTo Disable this, set to 0."); + UserConfig.DrawSliderInt(0, 25, GNB.Config.GNB_ST_NoMercyStop, "Stop Usage if Target HP% is below set value.\nTo Disable this option, set to 0."); if (preset == CustomComboPreset.GNB_AoE_NoMercy) - UserConfig.DrawSliderInt(0, 10, GNB.Config.GNB_AoE_NoMercyStop, "Disable Usage if Target HP% is below set value.\nTo Disable this, set to 0."); + UserConfig.DrawSliderInt(0, 25, GNB.Config.GNB_AoE_NoMercyStop, "Stop Usage if Target HP% is below set value.\nTo Disable this option, set to 0."); #endregion // ==================================================================================== From 8e985432639d8f4f02308257ad242643e627c97d Mon Sep 17 00:00:00 2001 From: ace Date: Thu, 5 Sep 2024 02:25:54 -0700 Subject: [PATCH 071/208] . --- XIVSlothCombo/Combos/CustomComboPreset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 762ca54f4..e07413ed4 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1531,7 +1531,7 @@ public enum CustomComboPreset GNB_ST_BurstStrike = 7014, [ParentCombo(GNB_ST_Advanced)] - [CustomComboInfo("Ammo Overcap Option", "Adds Burst Strike into the AoE rotation if you have max cartridges & your last combo action was Brutal Shell.", GNB.JobID)] + [CustomComboInfo("Ammo Overcap Option", "Adds Burst Strike into the rotation if you have max cartridges & your last combo action was Brutal Shell.", GNB.JobID)] GNB_ST_Overcap = 7015, #endregion From 04026bbe9201476ccb2b2c51ce4764fe4e4560cf Mon Sep 17 00:00:00 2001 From: ace Date: Thu, 5 Sep 2024 05:50:51 -0700 Subject: [PATCH 072/208] Reign fixes --- XIVSlothCombo/Combos/PvE/GNB.cs | 48 +++++++++------------------------ 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index e86e7b607..91afa4119 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -264,14 +264,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(GnashingFang) && !ActionReady(DoubleDown) && GunStep == 0) { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) + if (JustUsed(WickedTalon, 6f) || (JustUsed(EyeGouge, 5f))) return OriginalHook(ReignOfBeasts); } - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) - { + if (GunStep is 3 or 4) return OriginalHook(ReignOfBeasts); - } } //BurstStrike @@ -517,14 +515,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(GnashingFang) && !ActionReady(DoubleDown) && GunStep == 0) { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) + if (JustUsed(WickedTalon, 6f) || (JustUsed(EyeGouge, 5f))) return OriginalHook(ReignOfBeasts); } - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) - { + if (GunStep is 3 or 4) return OriginalHook(ReignOfBeasts); - } } //BurstStrike @@ -748,15 +744,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.GNB_GF_Features) && IsEnabled(CustomComboPreset.GNB_GF_Reign) && (LevelChecked(ReignOfBeasts))) { if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(GnashingFang) && !ActionReady(DoubleDown) && GunStep == 0) - { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) - return OriginalHook(ReignOfBeasts); - } + return OriginalHook(ReignOfBeasts); - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) - { + if (GunStep is 3 or 4) return OriginalHook(ReignOfBeasts); - } } //Burst Strike @@ -845,7 +836,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(ReignOfBeasts)) //because leaving this out anywhere is a waste { if ((GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) || - (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood))) + (GunStep is 3 or 4)) return OriginalHook(ReignOfBeasts); } //FatedCircle - if not unlocked, use BurstStrike @@ -944,7 +935,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.GNB_AoE_Reign) && LevelChecked(ReignOfBeasts)) //because leaving this out anywhere is a waste { if ((GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) || - (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood))) + (GunStep is 3 or 4)) return OriginalHook(ReignOfBeasts); } //FatedCircle - if not unlocked, use BurstStrike @@ -1003,16 +994,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return DoubleDown; if (IsEnabled(CustomComboPreset.GNB_BS_Reign) && (LevelChecked(ReignOfBeasts))) { - if (HasEffect(Buffs.ReadyToReign) && GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) - { - if (JustUsed(WickedTalon) || (JustUsed(EyeGouge))) - return OriginalHook(ReignOfBeasts); - } - - if (JustUsed(ReignOfBeasts, 10f) || JustUsed(NobleBlood, 10f)) - { + if ((HasEffect(Buffs.ReadyToReign) && GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) || + (GunStep is 3 or 4)) return OriginalHook(ReignOfBeasts); - } } } @@ -1070,17 +1054,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return SonicBreak; if (IsEnabled(CustomComboPreset.GNB_NM_DD) && LevelChecked(DoubleDown) && ActionReady(DoubleDown) && Ammo >= 2 && LevelChecked(DoubleDown)) return DoubleDown; - if (IsEnabled(CustomComboPreset.GNB_NM_Reign) && LevelChecked(ReignOfBeasts)) + if (IsEnabled(CustomComboPreset.GNB_NM_Reign) && (LevelChecked(ReignOfBeasts))) { - if (GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(GnashingFang) && !ActionReady(DoubleDown) && GunStep == 0) - { - return OriginalHook(ReignOfBeasts); - } - - if (JustUsed(ReignOfBeasts) || JustUsed(NobleBlood)) - { + if ((HasEffect(Buffs.ReadyToReign) && GetBuffRemainingTime(Buffs.ReadyToReign) > 0 && !ActionReady(DoubleDown) && GunStep == 0) || + (GunStep is 3 or 4)) return OriginalHook(ReignOfBeasts); - } } } } From 1f0904c5b76c2ee152b45d93767e5b6e704576d7 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Thu, 5 Sep 2024 14:49:26 -0600 Subject: [PATCH 073/208] Hide away the Multi-Button Combo settings --- XIVSlothCombo/Window/Functions/UserConfig.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..f1aa268de 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1391,14 +1391,18 @@ internal static void Draw(CustomComboPreset preset, bool enabled) ImGui.Spacing(); } + if (preset == CustomComboPreset.DNC_Variant_Cure) + UserConfig.DrawSliderInt(1, 100, DNC.Config.DNCVariantCurePercent, "HP% to be at or under", 200); + + #region Multi-Button Sliders + if (preset == CustomComboPreset.DNC_ST_EspritOvercap) UserConfig.DrawSliderInt(50, 100, DNC.Config.DNCEspritThreshold_ST, "Esprit", 150, SliderIncrements.Fives); if (preset == CustomComboPreset.DNC_AoE_EspritOvercap) UserConfig.DrawSliderInt(50, 100, DNC.Config.DNCEspritThreshold_AoE, "Esprit", 150, SliderIncrements.Fives); - if (preset == CustomComboPreset.DNC_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, DNC.Config.DNCVariantCurePercent, "HP% to be at or under", 200); + #endregion #region Advanced ST Sliders From 60fc435ded086eb0ee0861f684407914bf2307be Mon Sep 17 00:00:00 2001 From: Katie Date: Thu, 5 Sep 2024 18:15:00 -0400 Subject: [PATCH 074/208] Add more detail to range check option descriptions --- XIVSlothCombo/Combos/CustomComboPreset.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index a8462a949..aaf22e65a 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4148,7 +4148,7 @@ The three digets after RDM.JobID can be used to reorder items in the list VPR_AoE_Vicepit = 30105, [ParentCombo(VPR_AoE_Vicepit)] - [CustomComboInfo("Disable Range Check", "Disables the range check for Vicepit.", VPR.JobID)] + [CustomComboInfo("Disable Range Check", "Disables the range check for Vicepit, so it will be used even without a target selected.", VPR.JobID)] VPR_AoE_Vicepit_DisableRange = 30111, [ParentCombo(VPR_AoE_CDs)] @@ -4156,7 +4156,7 @@ The three digets after RDM.JobID can be used to reorder items in the list VPR_AoE_VicepitCombo = 30106, [ParentCombo(VPR_AoE_VicepitCombo)] - [CustomComboInfo("Disable Range Check", "Disables the range check for Swiftskin's Den and Hunter's Den.", VPR.JobID)] + [CustomComboInfo("Disable Range Check", "Disables the range check for Swiftskin's Den and Hunter's Den, so they will be used even without a target selected.", VPR.JobID)] VPR_AoE_VicepitCombo_DisableRange = 30113, #endregion @@ -4179,7 +4179,7 @@ The three digets after RDM.JobID can be used to reorder items in the list VPR_AoE_Reawaken = 30110, [ParentCombo(VPR_AoE_Reawaken)] - [CustomComboInfo("Disable Range Check", "Disables the range check for Reawaken.", VPR.JobID)] + [CustomComboInfo("Disable Range Check", "Disables the range check for Reawaken, so it will be used even without a target selected.", VPR.JobID)] VPR_AoE_Reawaken_DisableRange = 30114, [ParentCombo(VPR_AoE_AdvancedMode)] From c576a869436d82e7d446d727f531c9bd2e98ba0c Mon Sep 17 00:00:00 2001 From: ace Date: Thu, 5 Sep 2024 20:26:54 -0700 Subject: [PATCH 075/208] add SimpleMode Variants back into ST --- XIVSlothCombo/Combos/PvE/SAM.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index 6af8b7c8a..af62aa85b 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -222,6 +222,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Hakaze or Gyofu) { + if (IsEnabled(CustomComboPreset.SAM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.SAM_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.SAM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanSpellWeave(actionID)) + return Variant.VariantRampart; + // Opener for SAM if (SAMOpener.DoFullOpener(ref actionID)) return actionID; From b2b867a96a4159c0b762f82f949bb1be59b86ec9 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Thu, 5 Sep 2024 23:41:10 -0600 Subject: [PATCH 076/208] Clarify Delirium Buff names, simplify logic for Bloodspiller --- XIVSlothCombo/Combos/PvE/DRK.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK.cs index bb1521c40..79cbb9af1 100644 --- a/XIVSlothCombo/Combos/PvE/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK.cs @@ -59,8 +59,8 @@ public static class Buffs public const ushort // Main Buffs BloodWeapon = 742, - OlderDelirium = 1972, - Delirium = 3836, + Delirium = 1972, + EnhancedDelirium = 3836, // Periodic Buffs Darkside = 741, @@ -237,7 +237,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Delirium) && LevelChecked(ScarletDelirium) && IsEnabled(CustomComboPreset.DRK_ST_Delirium_Chain) - && HasEffect(Buffs.Delirium) + && HasEffect(Buffs.EnhancedDelirium) && gauge.DarksideTimeRemaining > 0) return OriginalHook(Bloodspiller); @@ -246,9 +246,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim && IsEnabled(CustomComboPreset.DRK_ST_Bloodspiller)) { //Bloodspiller under Delirium - if (GetBuffStacks(Buffs.Delirium) > 0 - || (TraitLevelChecked(Traits.EnhancedDelirium) - && GetBuffStacks(Buffs.OlderDelirium) > 0)) + var deliriumBuff = TraitLevelChecked(Traits.EnhancedDelirium) + ? Buffs.Delirium + : Buffs.EnhancedDelirium; + if (GetBuffStacks(deliriumBuff) > 0) return Bloodspiller; //Blood management outside of Delirium @@ -382,7 +383,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Delirium) && LevelChecked(Impalement) && IsEnabled(CustomComboPreset.DRK_AoE_Delirium_Chain) - && HasEffect(Buffs.Delirium) + && HasEffect(Buffs.EnhancedDelirium) && gauge.DarksideTimeRemaining > 1) return OriginalHook(Quietus); From b8f3b5f54bac07b1395ba06ebf16a1757edc8679 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Thu, 5 Sep 2024 23:43:36 -0600 Subject: [PATCH 077/208] Correct the Delirium Buff logic for Bloodspiller usage --- XIVSlothCombo/Combos/PvE/DRK.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK.cs index 79cbb9af1..d3d2e29ea 100644 --- a/XIVSlothCombo/Combos/PvE/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK.cs @@ -247,8 +247,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { //Bloodspiller under Delirium var deliriumBuff = TraitLevelChecked(Traits.EnhancedDelirium) - ? Buffs.Delirium - : Buffs.EnhancedDelirium; + ? Buffs.EnhancedDelirium + : Buffs.Delirium; if (GetBuffStacks(deliriumBuff) > 0) return Bloodspiller; From d3c11bbb43ae679b04b625252c36ce8d61de3bad Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Fri, 6 Sep 2024 02:32:28 -0600 Subject: [PATCH 078/208] Remove unnecessary Medica III option --- XIVSlothCombo/Combos/CustomComboPreset.cs | 7 ++----- XIVSlothCombo/Combos/PvE/WHM.cs | 9 +++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..caff65d02 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4484,13 +4484,10 @@ The three digets after RDM.JobID can be used to reorder items in the list WHM_AoEHeals_Lucid = 19204, [ParentCombo(WHM_AoEHeals)] - [CustomComboInfo("Medica II Option", "Uses Medica II when current target doesn't have Medica II buff.", WHM.JobID, 1)] + [CustomComboInfo("Medica II Option", "Uses Medica II when current target doesn't have Medica II buff." + + "\nUpgrades to Medica III when level allows.", WHM.JobID, 1)] WHM_AoEHeals_Medica2 = 19205, - [ParentCombo(WHM_AoEHeals_Medica2)] - [CustomComboInfo("Medica III Option", "Upgrades to Medica III when level allows.", WHM.JobID)] - WHM_AoEHeals_Medica3 = 19206, - [ParentCombo(WHM_AoEHeals)] [CustomComboInfo("Divine Caress", "Uses Divine Caress when Divine Grace from Temperance is active.", WHM.JobID, 8)] WHM_AoEHeals_DivineCaress = 19207, diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 6c2f1a46d..d6f20c67e 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -350,12 +350,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim || hasMedica3 != null && hasMedica3.RemainingTime <= Config.WHM_AoEHeals_MedicaTime) // ^ && (ActionReady(Medica2) || ActionReady(Medica3))) { - // Medica 3 upgrade - if (IsEnabled(CustomComboPreset.WHM_AoEHeals_Medica3) - && LevelChecked(Medica3)) - return Medica3; - - return Medica2; + return LevelChecked(Medica3) + ? Medica3 + : Medica2; } if (IsEnabled(CustomComboPreset.WHM_AoEHeals_Cure3) From 87cf6677a04da3d19c116da46c39acbe0e89409e Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 6 Sep 2024 11:56:19 +0100 Subject: [PATCH 079/208] Add punish lib, more autorot shit --- .gitmodules | 3 + PunishLib | 1 + XIVSlothCombo.sln | 8 +++ .../AutoRotation/AutoRotationConfig.cs | 5 +- .../AutoRotation/AutoRotationController.cs | 56 ++++++++++++++----- XIVSlothCombo/Combos/PvE/WAR.cs | 4 ++ XIVSlothCombo/CustomCombo/Functions/Target.cs | 7 ++- XIVSlothCombo/Window/ConfigWindow.cs | 6 +- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 26 ++++++--- XIVSlothCombo/Window/Tabs/Debug.cs | 33 ++++++++++- .../{XIVSlothCombo.json => WrathCombo.json} | 9 ++- XIVSlothCombo/XIVSlothCombo.cs | 4 +- XIVSlothCombo/XIVSlothCombo.csproj | 13 ++++- 13 files changed, 134 insertions(+), 41 deletions(-) create mode 160000 PunishLib rename XIVSlothCombo/{XIVSlothCombo.json => WrathCombo.json} (55%) diff --git a/.gitmodules b/.gitmodules index 208167663..481c675c6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,3 +8,6 @@ [submodule "ECommons"] path = ECommons url = https://github.com/NightmareXIV/ECommons.git +[submodule "PunishLib"] + path = PunishLib + url = https://github.com/PunishXIV/PunishLib.git diff --git a/PunishLib b/PunishLib new file mode 160000 index 000000000..fd8fd4418 --- /dev/null +++ b/PunishLib @@ -0,0 +1 @@ +Subproject commit fd8fd4418f6a3a8cd97a8c2179a54f1abdd9513b diff --git a/XIVSlothCombo.sln b/XIVSlothCombo.sln index 99cae0a86..47d7ebc27 100644 --- a/XIVSlothCombo.sln +++ b/XIVSlothCombo.sln @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Github Actions", "Github Ac EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ECommons", "ECommons\ECommons\ECommons.csproj", "{3E8E720E-9990-4202-9035-12F54C78CF47}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PunishLib", "PunishLib\PunishLib\PunishLib.csproj", "{768A2A82-B5F0-4C7B-9430-378DC290111B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -38,6 +40,12 @@ Global {3E8E720E-9990-4202-9035-12F54C78CF47}.GitBuild|x64.Build.0 = Debug|x64 {3E8E720E-9990-4202-9035-12F54C78CF47}.Release|x64.ActiveCfg = Release|x64 {3E8E720E-9990-4202-9035-12F54C78CF47}.Release|x64.Build.0 = Release|x64 + {768A2A82-B5F0-4C7B-9430-378DC290111B}.Debug|x64.ActiveCfg = Debug|x64 + {768A2A82-B5F0-4C7B-9430-378DC290111B}.Debug|x64.Build.0 = Debug|x64 + {768A2A82-B5F0-4C7B-9430-378DC290111B}.GitBuild|x64.ActiveCfg = Debug|x64 + {768A2A82-B5F0-4C7B-9430-378DC290111B}.GitBuild|x64.Build.0 = Debug|x64 + {768A2A82-B5F0-4C7B-9430-378DC290111B}.Release|x64.ActiveCfg = Release|x64 + {768A2A82-B5F0-4C7B-9430-378DC290111B}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs index 645c38574..5e2a1b949 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -13,9 +13,7 @@ public class AutoRotationConfig public DPSRotationMode DPSRotationMode; public HealerRotationMode HealerRotationMode; public TankRotationMode TankRotationMode; - public int DPSAoETargets = 2; - public int HealerAoETargets = 2; - public int TankAoETargets = 2; + public int? DPSAoETargets = 2; public HealerSettings HealerSettings = new(); } @@ -23,5 +21,6 @@ public class HealerSettings { public int SingleTargetHPP = 70; public int AoETargetHPP = 60; + public int SingleTargetRegenHPP = 80; } } diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 3de6693b2..eac20fd91 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -1,16 +1,14 @@ using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Plugin.Internal.Types.Manifest; using ECommons.DalamudServices; using ECommons.GameFunctions; using ECommons.GameHelpers; using ECommons.Throttlers; using FFXIVClientStructs.FFXIV.Client.Game; -using FFXIVClientStructs.FFXIV.Client.Game.Object; using System; using System.Linq; using XIVSlothCombo.Combos; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; using Action = Lumina.Excel.GeneratedSheets.Action; @@ -24,7 +22,7 @@ internal static void Run() if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) return; - if (!EzThrottler.Throttle("AutoRotController", 100)) + if (!EzThrottler.Throttle("AutoRotController", 150)) return; var c = 0; @@ -39,7 +37,7 @@ internal static void Run() var sheetAct = Svc.Data.GetExcelSheet().GetRow(gameAct); if ((byte)Player.Job != attributes.CustomComboInfo.JobID) continue; - + var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); var healTarget = AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode); var aoeHeal = HealerTargeting.GetPartyMax(outAct, out int count) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP && count >= 2; @@ -123,7 +121,7 @@ public static class AutoRotationHelper if (Player.Object.GetRole() != CombatRole.Healer) return null; IGameObject? target = healermode switch { - HealerRotationMode.Manual => Svc.Targets.Target, + HealerRotationMode.Manual => HealerTargeting.ManualTarget(), HealerRotationMode.Highest_Current => HealerTargeting.GetHighestCurrent(), HealerRotationMode.Lowest_Current => HealerTargeting.GetLowestCurrent(), }; @@ -178,7 +176,7 @@ public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes if (mustTarget) Svc.Targets.Target = target; - ActionManager.Instance()->UseAction(ActionType.Action, outAct); + ActionManager.Instance()->UseAction(ActionType.Action, outAct, mustTarget && target != null ? target.GameObjectId : Player.Object.GameObjectId); return true; } } @@ -200,8 +198,9 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, target.Struct()) != 562; var canUseTarget = ActionManager.CanUseActionOnTarget(outAct, target.Struct()); var canUseSelf = ActionManager.CanUseActionOnTarget(outAct, Player.GameObject); + var canUse = canUseSelf || canUseTarget; - if (canUse) + if (canUse && inRange) { Svc.Targets.Target = target; ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); @@ -265,17 +264,32 @@ public static class DPSTargeting public static class HealerTargeting { + internal static IGameObject? ManualTarget() + { + if (Svc.Targets.Target == null) return null; + var t = Svc.Targets.Target; + bool goodToHeal = CustomComboFunctions.GetTargetHPPercent(t) <= (TargetHasRegen(t) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP); + if (goodToHeal) + { + return t; + } + return null; + } internal static IGameObject? GetHighestCurrent() { if (CustomComboFunctions.GetPartyMembers().Count == 0) return Player.Object; - var target = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP).OrderByDescending(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + var target = CustomComboFunctions.GetPartyMembers() + .Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= (TargetHasRegen(x) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP)) + .OrderByDescending(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); return target; } internal static IGameObject? GetLowestCurrent() { if (CustomComboFunctions.GetPartyMembers().Count == 0) return Player.Object; - var target = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP).OrderBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + var target = CustomComboFunctions.GetPartyMembers() + .Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= (TargetHasRegen(x) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP)) + .OrderBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); return target; } @@ -287,6 +301,18 @@ internal static float GetPartyMax(uint outAct, out int count) var avg = members.Average(x => CustomComboFunctions.GetTargetHPPercent(x)); return avg; } + + private static bool TargetHasRegen(IGameObject target) + { + ushort regenBuff = JobID switch + { + AST.JobID => AST.Buffs.AspectedBenefic, + WHM.JobID => WHM.Buffs.Regen, + _ => 0 + }; + + return CustomComboFunctions.FindEffect(regenBuff) != null; + } } public static class TankTargeting @@ -294,7 +320,7 @@ public static class TankTargeting public static IGameObject? GetLowestCurrentTarget() { return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) - .OrderByDescending(x => x.TargetObject != Player.Object) + .OrderByDescending(x => x.TargetObject?.GameObjectId != Player.Object?.GameObjectId) .ThenBy(x => (x as IBattleChara).CurrentHp) .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } @@ -302,7 +328,7 @@ public static class TankTargeting public static IGameObject? GetHighestCurrentTarget() { return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) - .OrderByDescending(x => x.TargetObject != Player.Object) + .OrderByDescending(x => x.TargetObject?.GameObjectId != Player.Object?.GameObjectId) .ThenByDescending(x => (x as IBattleChara).CurrentHp) .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } @@ -310,15 +336,15 @@ public static class TankTargeting public static IGameObject? GetLowestMaxTarget() { return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) - .OrderByDescending(x => x.TargetObject != Player.Object) - .ThenBy(x => (x as IBattleChara).MaxHp) + .OrderByDescending(x => x.TargetObject?.GameObjectId != Player.Object?.GameObjectId) + .OrderBy(x => (x as IBattleChara).MaxHp) .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } public static IGameObject? GetHighestMaxTarget() { return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable) - .OrderByDescending(x => x.TargetObject != Player.Object) + .OrderByDescending(x => x.TargetObject?.GameObjectId != Player.Object?.GameObjectId) .ThenByDescending(x => (x as IBattleChara).MaxHp) .ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } diff --git a/XIVSlothCombo/Combos/PvE/WAR.cs b/XIVSlothCombo/Combos/PvE/WAR.cs index d1eebaf01..13e29073c 100644 --- a/XIVSlothCombo/Combos/PvE/WAR.cs +++ b/XIVSlothCombo/Combos/PvE/WAR.cs @@ -96,6 +96,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (CanWeave(actionID)) { + if (ActionReady(OriginalHook(RawIntuition)) && PlayerHealthPercentageHp() <= 80) + return OriginalHook(RawIntuition); if (ActionReady(OriginalHook(Berserk)) && LevelChecked(Berserk)) return OriginalHook(Berserk); if (ActionReady(Upheaval) && LevelChecked(Upheaval)) @@ -284,6 +286,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (CanWeave(actionID)) { + if (ActionReady(OriginalHook(RawIntuition)) && PlayerHealthPercentageHp() <= 80) + return OriginalHook(RawIntuition); if (CanWeave(actionID) && ActionReady(OriginalHook(Berserk)) && LevelChecked(Berserk)) return OriginalHook(Berserk); if (ActionReady(Orogeny) && LevelChecked(Orogeny) && HasEffect(Buffs.SurgingTempest)) diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 88939f3ae..498b977e9 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -44,7 +44,7 @@ public static float GetTargetDistance(IGameObject? optionalTarget = null, IGameO Vector2 position = new(chara.Position.X, chara.Position.Z); Vector2 selfPosition = new(sourceChara.Position.X, sourceChara.Position.Z); - return Math.Max(0, Vector2.Distance(position, selfPosition) - chara.HitboxRadius - sourceChara.HitboxRadius); + return Math.Max(0, Vector2.Distance(position, selfPosition) - chara.HitboxRadius); } /// Gets a value indicating whether you are in melee range from the current target. @@ -441,7 +441,7 @@ public unsafe static int NumberOfEnemiesInRange(uint aoeSpell, IGameObject? targ { if (!needsTarget) { - if (GetTargetDistance(enemyChara) - enemyChara.HitboxRadius <= sheetSpell.EffectRange) + if (GetTargetDistance(enemyChara) <= sheetSpell.EffectRange) count++; } else @@ -451,7 +451,8 @@ public unsafe static int NumberOfEnemiesInRange(uint aoeSpell, IGameObject? targ for (int t = 0; t < enemies.Count(); t++) { var nearEnemy = enemies[t]; - if (GetTargetDistance(nearEnemy, target) - nearEnemy.HitboxRadius <= sheetSpell.EffectRange) + var dist = GetTargetDistance(nearEnemy, target); + if (dist <= sheetSpell.EffectRange) { count++; } diff --git a/XIVSlothCombo/Window/ConfigWindow.cs b/XIVSlothCombo/Window/ConfigWindow.cs index c8570e06b..9a708264a 100644 --- a/XIVSlothCombo/Window/ConfigWindow.cs +++ b/XIVSlothCombo/Window/ConfigWindow.cs @@ -4,6 +4,8 @@ using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; +using PunishLib; +using PunishLib.ImGuiMethods; using System; using System.Collections.Generic; using System.Linq; @@ -110,7 +112,7 @@ public override void Draw() using (var leftChild = ImRaii.Child($"###SlothLeftSide", regionSize with { Y = topLeftSideHeight }, false, ImGuiWindowFlags.NoDecoration)) { - if (ThreadLoadImageHandler.TryGetTextureWrap(@"https://github.com/Taurenkey/XIVSlothCombo/blob/main/res/plugin/xivslothcombo.png?raw=true", out var logo)) + if (ThreadLoadImageHandler.TryGetTextureWrap(PunishLibMain.PluginManifest.IconUrl, out var logo)) //todo update { ImGuiEx.LineCentered("###SlothLogo", () => { @@ -172,7 +174,7 @@ public override void Draw() Settings.Draw(); break; case OpenWindow.About: - P.AboutUs.Draw(); + AboutTab.Draw(P.Name); break; case OpenWindow.Debug: Debug.Draw(); diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index bf3c52abc..7774724a4 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -24,7 +24,8 @@ internal class AutoRotationTab : ConfigWindow if (ImGui.CollapsingHeader("DPS Settings")) { - ImGui.Text($"Targeting Mode"); + ImGui.Text($"These settings will apply to DPS jobs and for Healers DPS actions."); + ImGuiEx.TextUnderlined($"Targeting Mode"); changed |= ImGuiEx.EnumCombo("###DPSTargetingMode", ref cfg.DPSRotationMode); ImGuiComponents.HelpMarker("Manual - Leaves all targeting decisions to you.\n" + "Highest Max - Prioritises enemies with the highest max HP.\n" + @@ -32,25 +33,34 @@ internal class AutoRotationTab : ConfigWindow "Highest Current - Prioritises the enemy with the highest current HP.\n" + "Lowest Current - Prioritises the enemy with the lowest current HP.\n" + "Tank Target - Prioritises the same target as the first tank in your group."); + ImGui.Spacing(); + var input = ImGuiEx.InputInt(100f.Scale(), "Targets Required for AoE Features", ref cfg.DPSAoETargets); + if (input) + { + changed |= input; + if (cfg.DPSAoETargets < 0) + cfg.DPSAoETargets = 0; + } + ImGuiComponents.HelpMarker("Disabling this will turn off AoE DPS features. Otherwise will require the amount of targets required to be in range of an AoE feature's attack to use."); + } ImGui.Spacing(); if (ImGui.CollapsingHeader("Healing Settings")) { ImGui.Text($"Targeting Mode"); changed |= ImGuiEx.EnumCombo("###HealerTargetingMode", ref cfg.HealerRotationMode); - ImGuiComponents.HelpMarker("Manual - Leaves all targeting decisions to you.\n" + + ImGuiComponents.HelpMarker("Manual - Will only heal a target if you select them manually. If the target does not meet the healing threshold settings criteria below it will skip healing in favour of DPSing (if also enabled).\n" + "Highest Current - Prioritises the party member with the highest current HP.\n" + - "Lowest Current - Prioritises the party member with the lowest current HP.\n" + - "Self Priority - Heal yourself before others.\n" + - "Tank Priority - Heal the tank(s) before others.\n" + - "Healer Priority - Heal the healer(s) before others.\n" + - "DPS Priority - Heal the DPS before others."); + "Lowest Current - Prioritises the party member with the lowest current HP."); ImGui.SetNextItemWidth(200f.Scale()); changed |= ImGuiEx.SliderInt("Single Target HP% Threshold", ref cfg.HealerSettings.SingleTargetHPP, 1, 99, "%d%%"); ImGui.SetNextItemWidth(200f.Scale()); + changed |= ImGuiEx.SliderInt("Single Target HP% Threshold (target has Regen/Aspected Benefic)", ref cfg.HealerSettings.SingleTargetRegenHPP, 1, 99, "%d%%"); + ImGuiComponents.HelpMarker("You typically want to set this lower than the above setting."); + ImGui.SetNextItemWidth(200f.Scale()); changed |= ImGuiEx.SliderInt("AoE HP% Threshold", ref cfg.HealerSettings.AoETargetHPP, 1, 99, "%d%%"); - ImGuiComponents.HelpMarker("If all party members within AoE healing ranges health falls below this value it will use an AoE heal instead of single target heals."); + ImGuiComponents.HelpMarker("If all party members within AoE healing ranges average HP% falls below this value it will use an AoE heal instead of single target heals."); } ImGui.Spacing(); if (ImGui.CollapsingHeader("Tank Settings")) diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index ebfeaf53a..05a05fe1a 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -1,8 +1,11 @@ -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Game.ClientState.Objects.Enums; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface.Colors; using Dalamud.Interface.Utility.Raii; using ECommons.DalamudServices; +using ECommons.GameFunctions; +using ECommons.GameHelpers; using ECommons.ImGuiMethods; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; @@ -18,6 +21,7 @@ using XIVSlothCombo.Services; using static XIVSlothCombo.Combos.JobHelpers.NIN; using Action = Lumina.Excel.GeneratedSheets.Action; +using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using Status = Dalamud.Game.ClientState.Statuses.Status; namespace XIVSlothCombo.Window.Tabs @@ -168,6 +172,14 @@ static void CustomStyleText(string label, object? value) CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.UnlockLink).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.UnlockLink) ? "Completed" : "Not Completed")})"); CustomStyleText($"Base Recast:", $"{debugSpell.Recast100ms / 10f}s"); CustomStyleText($"Max Charges:", $"{debugSpell.MaxCharges}"); + CustomStyleText($"Range:", $"{debugSpell.Range}"); + CustomStyleText($"Effect Range:", $"{debugSpell.EffectRange}"); + CustomStyleText($"Can Target Hostile:", $"{debugSpell.CanTargetHostile}"); + CustomStyleText($"Can Target Self:", $"{debugSpell.CanTargetSelf}"); + CustomStyleText($"Can Target Friendly:", $"{debugSpell.CanTargetFriendly}"); + CustomStyleText($"Can Target Party:", $"{debugSpell.CanTargetParty}"); + CustomStyleText($"Can Target Area:", $"{debugSpell.TargetArea}"); + if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.RowId)) CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.RowId])/1000f:F2}"); @@ -175,7 +187,11 @@ static void CustomStyleText(string label, object? value) { var inRange = ActionManager.GetActionInRangeOrLoS(debugSpell.RowId, (GameObject*)LocalPlayer.Address, (GameObject*)Svc.Targets.Target.Address); CustomStyleText("InRange or LoS:", inRange == 0 ? "In range and in line of sight" : $"{inRange}: {Svc.Data.GetExcelSheet().GetRow(inRange).Text}"); + var canUseOnTarget = ActionManager.CanUseActionOnTarget(debugSpell.RowId, Svc.Targets.Target.Struct()); + CustomStyleText($"Can Use on Target:", canUseOnTarget); } + var canUseOnSelf = ActionManager.CanUseActionOnTarget(debugSpell.RowId, Player.GameObject); + CustomStyleText($"Can Use on Self:", canUseOnSelf); } } @@ -203,6 +219,20 @@ static void CustomStyleText(string label, object? value) CustomStyleText("In Melee Range:", CustomComboFunctions.InMeleeRange()); CustomStyleText("Relative Position:", CustomComboFunctions.AngleToTarget() is 2 ? "Rear" : (CustomComboFunctions.AngleToTarget() is 1 or 3) ? "Flank" : CustomComboFunctions.AngleToTarget() is 4 ? "Front" : ""); CustomStyleText("Health:", $"{CustomComboFunctions.EnemyHealthCurrentHp().ToString("N0")} / {CustomComboFunctions.EnemyHealthMaxHp().ToString("N0")} ({Math.Round(CustomComboFunctions.GetTargetHPPercent(), 2)}%)"); + ImGui.Indent(); + if (ImGui.CollapsingHeader("Relative Target Distances")) + { + ImGuiEx.TextUnderlined("Enemies"); + var enemies = Svc.Objects.Where(x => x != null && x.ObjectKind == ObjectKind.BattleNpc && x.IsTargetable && !x.IsDead).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); + foreach (var enemy in enemies) + { + if (enemy.GameObjectId == Svc.Targets.Target?.GameObjectId) continue; + if (!enemy.Character()->InCombat) continue; + var dist = CustomComboFunctions.GetTargetDistance(enemy, Svc.Targets.Target); + CustomStyleText($"{enemy.Name} ({enemy.GameObjectId}):", $"{dist:F1}"); + } + } + ImGui.Unindent(); ImGui.Spacing(); // Action Info @@ -219,6 +249,7 @@ static void CustomStyleText(string label, object? value) CustomStyleText("Combo Action:", CustomComboFunctions.ComboAction == 0 ? string.Empty : $"{(string.IsNullOrEmpty(ActionWatching.GetActionName(CustomComboFunctions.ComboAction)) ? "Unknown" : ActionWatching.GetActionName(CustomComboFunctions.ComboAction))} (ID: {CustomComboFunctions.ComboAction})"); CustomStyleText("Cast Time:", $"{LocalPlayer.CurrentCastTime:F2} / {LocalPlayer.TotalCastTime:F2}"); CustomStyleText("Cast Action:", LocalPlayer.CastActionId == 0 ? string.Empty : $"{(string.IsNullOrEmpty(ActionWatching.GetActionName(LocalPlayer.CastActionId)) ? "Unknown" : ActionWatching.GetActionName(LocalPlayer.CastActionId))} (ID: {LocalPlayer.CastActionId})"); + CustomStyleText("Animation Lock:", $"{ActionManager.Instance()->AnimationLock:F1}"); ImGui.Spacing(); // Party Info diff --git a/XIVSlothCombo/XIVSlothCombo.json b/XIVSlothCombo/WrathCombo.json similarity index 55% rename from XIVSlothCombo/XIVSlothCombo.json rename to XIVSlothCombo/WrathCombo.json index 42654f4ca..a40d5e940 100644 --- a/XIVSlothCombo/XIVSlothCombo.json +++ b/XIVSlothCombo/WrathCombo.json @@ -1,11 +1,10 @@ { - "Author": "Team Sloth", - "Name": "XIVSlothCombo", - "InternalName": "XIVSlothCombo", + "Author": "Team Wrath", + "Name": "Wrath Combo", + "InternalName": "WrathCombo", "DalamudApiLevel": 10, "Punchline": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "Description": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", - "RepoUrl": "https://github.com/Nik-Potokar/XIVSlothCombo", - "IconUrl": "https://raw.githubusercontent.com/Nik-Potokar/XIVSlothCombo/main/res/plugin/xivslothcombo.png", + "RepoUrl": "https://github.com/PunishXIV/WrathCombo", "Changelog": "Please check the project's GitHub or Discord for a full changelog." } diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 5570b1540..695462acf 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -9,6 +9,7 @@ using Dalamud.Utility; using ECommons; using ECommons.DalamudServices; +using PunishLib; using System; using System.Collections.Generic; using System.IO; @@ -97,6 +98,7 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) P = this; pluginInterface.Create(); ECommonsMain.Init(pluginInterface, this); + PunishLibMain.Init(pluginInterface, "Wrath Combo"); Service.Configuration = pluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration(); Service.Address = new PluginAddressResolver(); @@ -245,7 +247,7 @@ private void PrintMotD() /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Used for non-static only window initialization")] - public string Name => "XIVSlothCombo"; + public string Name => "Wrath Combo"; /// public void Dispose() diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index b567653b4..8dfd1fd78 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -2,9 +2,9 @@ - Team Sloth + Team Wrath - - 3.2.0.8 + 0.0.0.1 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU @@ -17,7 +17,7 @@ $(appdata)\XIVLauncher\addon\Hooks\dev\ $(appdata)\XIVLauncher\installedPlugins\XIVSlothCombo\$(version) $(appdata)\XIVLauncher\devPlugins\XIVSlothCombo\ - XIVSlothCombo + WrathCombo XIVSlothCombo XIVSlothCombo XIVSlothCombo @@ -72,6 +72,7 @@ + @@ -118,4 +119,10 @@ + + + PreserveNewest + + + From 9ed71a81e8876ed40bc5053609032d300d75e949 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 6 Sep 2024 15:56:53 +0100 Subject: [PATCH 080/208] Autorot toggles --- .../AutoRotation/AutoRotationController.cs | 13 +-- XIVSlothCombo/Window/ConfigWindow.cs | 2 +- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 11 ++- XIVSlothCombo/WrathCombo.json | 1 + XIVSlothCombo/XIVSlothCombo.cs | 97 ++++++++----------- 5 files changed, 58 insertions(+), 66 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index eac20fd91..3e3ef5564 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -65,7 +65,7 @@ private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttribut var mode = Service.Configuration.RotationConfig.DPSRotationMode; if (attributes.AutoAction.IsAoE) { - return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); + return AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); } else { @@ -78,7 +78,7 @@ private static bool AutomateTanking(CustomComboPreset preset, Presets.PresetAttr var mode = Service.Configuration.RotationConfig.TankRotationMode; if (attributes.AutoAction.IsAoE) { - return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); + return AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); } else { @@ -91,7 +91,7 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr var mode = Service.Configuration.RotationConfig.HealerRotationMode; if (attributes.AutoAction.IsAoE) { - return AutoRotationHelper.ExecuteAoE(preset, attributes, gameAct); + return AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); } else { @@ -145,7 +145,7 @@ public static class AutoRotationHelper return null; } - public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) + public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { if (attributes.AutoAction.IsHeal) { @@ -164,7 +164,7 @@ public static bool ExecuteAoE(CustomComboPreset preset, Presets.PresetAttributes else { uint outAct = InvokeCombo(preset, attributes, Player.Object); - var target = GetSingleTarget(Service.Configuration.RotationConfig.DPSRotationMode); + var target = GetSingleTarget(mode); var mustTarget = Svc.Data.GetExcelSheet().GetRow(outAct).CanTargetHostile; if (CustomComboFunctions.NumberOfEnemiesInRange(outAct, target) >= Service.Configuration.RotationConfig.DPSAoETargets) @@ -195,11 +195,12 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset if (CustomComboFunctions.IsMoving && castTime > 0) return false; + var areaTargeted = Svc.Data.GetExcelSheet().GetRow(outAct).TargetArea; var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, target.Struct()) != 562; var canUseTarget = ActionManager.CanUseActionOnTarget(outAct, target.Struct()); var canUseSelf = ActionManager.CanUseActionOnTarget(outAct, Player.GameObject); - var canUse = canUseSelf || canUseTarget; + var canUse = canUseSelf || canUseTarget || areaTargeted; if (canUse && inRange) { Svc.Targets.Target = target; diff --git a/XIVSlothCombo/Window/ConfigWindow.cs b/XIVSlothCombo/Window/ConfigWindow.cs index 9a708264a..1226950e8 100644 --- a/XIVSlothCombo/Window/ConfigWindow.cs +++ b/XIVSlothCombo/Window/ConfigWindow.cs @@ -112,7 +112,7 @@ public override void Draw() using (var leftChild = ImRaii.Child($"###SlothLeftSide", regionSize with { Y = topLeftSideHeight }, false, ImGuiWindowFlags.NoDecoration)) { - if (ThreadLoadImageHandler.TryGetTextureWrap(PunishLibMain.PluginManifest.IconUrl, out var logo)) //todo update + if (ThreadLoadImageHandler.TryGetTextureWrap(PunishLibMain.PluginManifest.IconUrl ?? "", out var logo)) //todo update { ImGuiEx.LineCentered("###SlothLogo", () => { diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 7774724a4..15eddadf9 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -24,7 +24,8 @@ internal class AutoRotationTab : ConfigWindow if (ImGui.CollapsingHeader("DPS Settings")) { - ImGui.Text($"These settings will apply to DPS jobs and for Healers DPS actions."); + ImGuiEx.LineCentered("###DPSAutoRot", () => ImGui.Text($"These settings will apply to DPS jobs and for Healers DPS actions.")); + ImGui.Spacing(); ImGuiEx.TextUnderlined($"Targeting Mode"); changed |= ImGuiEx.EnumCombo("###DPSTargetingMode", ref cfg.DPSRotationMode); ImGuiComponents.HelpMarker("Manual - Leaves all targeting decisions to you.\n" + @@ -47,11 +48,11 @@ internal class AutoRotationTab : ConfigWindow ImGui.Spacing(); if (ImGui.CollapsingHeader("Healing Settings")) { - ImGui.Text($"Targeting Mode"); + ImGuiEx.TextUnderlined($"Healing Targeting Mode"); changed |= ImGuiEx.EnumCombo("###HealerTargetingMode", ref cfg.HealerRotationMode); ImGuiComponents.HelpMarker("Manual - Will only heal a target if you select them manually. If the target does not meet the healing threshold settings criteria below it will skip healing in favour of DPSing (if also enabled).\n" + - "Highest Current - Prioritises the party member with the highest current HP.\n" + - "Lowest Current - Prioritises the party member with the lowest current HP."); + "Highest Current - Prioritises the party member with the highest current HP%.\n" + + "Lowest Current - Prioritises the party member with the lowest current HP%."); ImGui.SetNextItemWidth(200f.Scale()); changed |= ImGuiEx.SliderInt("Single Target HP% Threshold", ref cfg.HealerSettings.SingleTargetHPP, 1, 99, "%d%%"); @@ -65,7 +66,7 @@ internal class AutoRotationTab : ConfigWindow ImGui.Spacing(); if (ImGui.CollapsingHeader("Tank Settings")) { - ImGui.Text($"Targeting Mode"); + ImGuiEx.TextUnderlined($"Targeting Mode"); changed |= ImGuiEx.EnumCombo("###TankTargetingMode", ref cfg.TankRotationMode); } diff --git a/XIVSlothCombo/WrathCombo.json b/XIVSlothCombo/WrathCombo.json index a40d5e940..853e1fe50 100644 --- a/XIVSlothCombo/WrathCombo.json +++ b/XIVSlothCombo/WrathCombo.json @@ -6,5 +6,6 @@ "Punchline": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "Description": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "RepoUrl": "https://github.com/PunishXIV/WrathCombo", + "IconUrl": "https://s3.puni.sh/media/plugin/60/icon-2bwhkn3zf1f.png", "Changelog": "Please check the project's GitHub or Discord for a full changelog." } diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 695462acf..cd38ecac6 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.Statuses; using Dalamud.Game.Command; +using Dalamud.Game.Gui.Dtr; using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; @@ -42,6 +43,7 @@ public sealed partial class XIVSlothCombo : IDalamudPlugin internal static XIVSlothCombo? P = null!; internal WindowSystem ws; private readonly HttpClient httpClient = new(); + private IDtrBarEntry DtrBarEntry; private readonly TextPayload starterMotd = new("[Sloth Message of the Day] "); private static uint? jobID; @@ -126,6 +128,8 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) ShowInHelp = true, }); + DtrBarEntry ??= Svc.DtrBar.Get("Wrath Combo"); + DtrBarEntry.OnClick = () => { Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; }; Svc.ClientState.Login += PrintLoginMessage; if (Svc.ClientState.IsLoggedIn) ResetFeatures(); @@ -179,6 +183,11 @@ private void OnFrameworkUpdate(IFramework framework) BlueMageService.PopulateBLUSpells(); TargetHelper.Draw(); AutoRotationController.Run(); + var autoOn = Service.Configuration.RotationConfig.Enabled; + DtrBarEntry.Text = new SeString( + new IconPayload(autoOn ? BitmapFontIcon.SwordUnsheathed : BitmapFontIcon.SwordSheathed), + new TextPayload($"{(Service.Configuration.RotationConfig.Enabled ? ": On" : ": Off")}") + ); } private static void KillRedundantIDs() @@ -255,6 +264,7 @@ public void Dispose() ConfigWindow?.Dispose(); ws.RemoveAllWindows(); + Svc.DtrBar.Remove("Wrath Combo"); Svc.Commands.RemoveHandler(Command); Svc.Framework.Update -= OnFrameworkUpdate; Svc.PluginInterface.UiBuilder.OpenConfigUi -= OnOpenConfigUi; @@ -298,83 +308,56 @@ private void OnCommand(string command, string arguments) case "set": // set a feature { - if (!Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.InCombat]) + string? targetPreset = argumentsParts[1].ToLowerInvariant(); + foreach (CustomComboPreset preset in Enum.GetValues()) { - string? targetPreset = argumentsParts[1].ToLowerInvariant(); - foreach (CustomComboPreset preset in Enum.GetValues()) - { - if (!preset.ToString().Equals(targetPreset, StringComparison.InvariantCultureIgnoreCase)) - continue; - - Service.Configuration.EnabledActions.Add(preset); - Svc.Chat.Print($"{preset} SET"); - } + if (!preset.ToString().Equals(targetPreset, StringComparison.InvariantCultureIgnoreCase)) + continue; - Service.Configuration.Save(); - } - - else - { - Svc.Chat.PrintError("Features cannot be set in combat."); + Service.Configuration.EnabledActions.Add(preset); + Svc.Chat.Print($"{preset} SET"); } + Service.Configuration.Save(); break; } case "toggle": // toggle a feature { - if (!Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.InCombat]) + string? targetPreset = argumentsParts[1].ToLowerInvariant(); + foreach (CustomComboPreset preset in Enum.GetValues()) { - string? targetPreset = argumentsParts[1].ToLowerInvariant(); - foreach (CustomComboPreset preset in Enum.GetValues()) - { - if (!preset.ToString().Equals(targetPreset, StringComparison.InvariantCultureIgnoreCase)) - continue; + if (!preset.ToString().Equals(targetPreset, StringComparison.InvariantCultureIgnoreCase)) + continue; - if (!Service.Configuration.EnabledActions.Remove(preset)) - { - Service.Configuration.EnabledActions.Add(preset); - Svc.Chat.Print($"{preset} SET"); - } - else - { - Svc.Chat.Print($"{preset} UNSET"); - } + if (!Service.Configuration.EnabledActions.Remove(preset)) + { + Service.Configuration.EnabledActions.Add(preset); + Svc.Chat.Print($"{preset} SET"); + } + else + { + Svc.Chat.Print($"{preset} UNSET"); } - - Service.Configuration.Save(); - } - - else - { - Svc.Chat.PrintError("Features cannot be toggled in combat."); } + Service.Configuration.Save(); break; } case "unset": // unset a feature { - if (!Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.InCombat]) + string? targetPreset = argumentsParts[1].ToLowerInvariant(); + foreach (CustomComboPreset preset in Enum.GetValues()) { - string? targetPreset = argumentsParts[1].ToLowerInvariant(); - foreach (CustomComboPreset preset in Enum.GetValues()) - { - if (!preset.ToString().Equals(targetPreset, StringComparison.InvariantCultureIgnoreCase)) - continue; + if (!preset.ToString().Equals(targetPreset, StringComparison.InvariantCultureIgnoreCase)) + continue; - Service.Configuration.EnabledActions.Remove(preset); - Svc.Chat.Print($"{preset} UNSET"); - } - - Service.Configuration.Save(); - } - - else - { - Svc.Chat.PrintError("Features cannot be unset in combat."); + Service.Configuration.EnabledActions.Remove(preset); + Svc.Chat.Print($"{preset} UNSET"); } + Service.Configuration.Save(); break; } @@ -613,6 +596,12 @@ private void OnCommand(string command, string arguments) break; } } + case "auto": + { + Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; + Service.Configuration.Save(); + break; + } default: ConfigWindow.IsOpen = !ConfigWindow.IsOpen; PvEFeatures.HasToOpenJob = true; From 3d065505cf8062cc8074458ab830c271f1a81c4c Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Fri, 6 Sep 2024 10:33:00 -0600 Subject: [PATCH 081/208] Revert ID changes --- XIVSlothCombo/Combos/CustomComboPreset.cs | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e07413ed4..ad1dfe01f 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1487,58 +1487,58 @@ public enum CustomComboPreset #region Cooldowns [ParentCombo(GNB_ST_Advanced)] [CustomComboInfo("Cooldowns Option", "Adds various cooldowns into the rotation.", GNB.JobID)] - GNB_ST_Advanced_CooldownsGroup = 7004, + GNB_ST_Advanced_CooldownsGroup = 7007, [ConflictingCombos(GNB_NM_Features)] [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("No Mercy Option", "Adds No Mercy into the rotation when appropriate.", GNB.JobID)] - GNB_ST_NoMercy = 7005, + GNB_ST_NoMercy = 7008, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Sonic Break Option", "Adds Sonic Break into the rotation when appropriate.", GNB.JobID)] - GNB_ST_SonicBreak = 7006, + GNB_ST_SonicBreak = 7012, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Danger/Blasting Zone Option", "Adds Danger/Blasting Zone into the rotation when available.", GNB.JobID)] - GNB_ST_BlastingZone = 7007, + GNB_ST_BlastingZone = 7009, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Bow Shock Option", "Adds Bow Shock into the rotation when appropriate.", GNB.JobID)] - GNB_ST_BowShock = 7008, + GNB_ST_BowShock = 7010, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Bloodfest Option", "Adds Bloodfest into the rotation when appropriate.", GNB.JobID)] - GNB_ST_Bloodfest = 7009, + GNB_ST_Bloodfest = 7011, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Gnashing Fang Option", "Adds Gnashing Fang combo into the rotation.", GNB.JobID)] - GNB_ST_Gnashing = 7010, + GNB_ST_Gnashing = 7016, [ParentCombo(GNB_ST_Gnashing)] [CustomComboInfo("Continuation Option", "Adds Continuation & Hypervelocity into the rotation.\n'Gnashing Fang' option must be enabled or started manually.", GNB.JobID)] - GNB_ST_Continuation = 7011, + GNB_ST_Continuation = 7005, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Double Down Option", "Adds Double Down into the rotation when appropriate.", GNB.JobID)] - GNB_ST_DoubleDown = 7012, + GNB_ST_DoubleDown = 7017, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Reign Combo Option", "Adds Reign/Noble/Lionheart into the rotation when appropriate.", GNB.JobID)] - GNB_ST_Reign = 7013, + GNB_ST_Reign = 7014, [ParentCombo(GNB_ST_Advanced_CooldownsGroup)] [CustomComboInfo("Burst Strike Option", "Adds Burst Strike into the rotation when appropriate.", GNB.JobID)] - GNB_ST_BurstStrike = 7014, + GNB_ST_BurstStrike = 7015, [ParentCombo(GNB_ST_Advanced)] [CustomComboInfo("Ammo Overcap Option", "Adds Burst Strike into the rotation if you have max cartridges & your last combo action was Brutal Shell.", GNB.JobID)] - GNB_ST_Overcap = 7015, + GNB_ST_Overcap = 7018, #endregion #region Lightning Shot [ParentCombo(GNB_ST_Advanced)] [CustomComboInfo("Lightning Shot Uptime Option", "Adds Lightning Shot to the main combo when you are out of range.", GNB.JobID)] - GNB_ST_RangedUptime = 7016, + GNB_ST_RangedUptime = 7004, #endregion #endregion @@ -1584,11 +1584,11 @@ public enum CustomComboPreset [ParentCombo(GNB_AoE_FatedCircle)] [CustomComboInfo("Burst Strike Option", "Adds Burst Strike into the AoE rotation if you do not have Fated Circle unlocked yet.", GNB.JobID)] - GNB_AoE_noFatedCircle = 7209, + GNB_AoE_noFatedCircle = 7212, [ParentCombo(GNB_AoE_Advanced)] [CustomComboInfo("Ammo Overcap Option", "Adds Fated Circle into the AoE rotation if you have max cartridges & your last combo action was Demon Slice.", GNB.JobID)] - GNB_AoE_Overcap = 7210, + GNB_AoE_Overcap = 7209, [ParentCombo(GNB_AoE_Overcap)] [CustomComboInfo("Ammo Overcap Burst Strike Option", "Adds Burst Strike into the AoE rotation if you have max cartridges, your last combo action was Demon Slice, & you do not have Fated Circle unlocked yet.", GNB.JobID)] From 15ee9d99d090a587832a374f5f3aa1a368a3247f Mon Sep 17 00:00:00 2001 From: Katie Date: Sat, 7 Sep 2024 13:28:25 -0400 Subject: [PATCH 082/208] Move Swiftcast logic to IsMoving and add motif level checks --- XIVSlothCombo/Combos/PvE/PCT.cs | 39 ++++++++++----------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index df12da91e..09edacd88 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -303,20 +303,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } } - // Swiftcast - if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_SwitfcastOption)) - { - if (IsMoving && - IsOffCooldown(All.Swiftcast) && - All.Swiftcast.LevelChecked() && - !HasEffect(Buffs.HammerTime) && - gauge.Paint < 1 && - (!gauge.CreatureMotifDrawn || !gauge.WeaponMotifDrawn || !gauge.LandscapeMotifDrawn)) - { - return All.Swiftcast; - } - } - // SubtractivePalette if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_SubtractivePalette)) { @@ -355,6 +341,12 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_MovementOption_HolyInWhite) && HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); + + if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_SwitfcastOption) && ActionReady(All.Swiftcast) && + ((LevelChecked(CreatureMotif) && !gauge.CreatureMotifDrawn) || + (LevelChecked(WeaponMotif) && !gauge.WeaponMotifDrawn) || + (LevelChecked(LandscapeMotif) && !gauge.LandscapeMotifDrawn))) + return All.Swiftcast; } //Prepare for Burst @@ -633,20 +625,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } - if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_SwitfcastOption)) - { - if (IsMoving && - IsOffCooldown(All.Swiftcast) && - All.Swiftcast.LevelChecked() && - !HasEffect(Buffs.HammerTime) && - gauge.Paint < 1 && - (!gauge.CreatureMotifDrawn || !gauge.WeaponMotifDrawn || !gauge.LandscapeMotifDrawn)) - { - return All.Swiftcast; - } - } - - // Subtractive Palette if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_SubtractivePalette) && SubtractivePalette.LevelChecked() && @@ -680,6 +658,11 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_MovementOption_HolyInWhite) && HolyInWhite.LevelChecked() && gauge.Paint >= 1) return OriginalHook(HolyInWhite); + if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_SwitfcastOption) && ActionReady(All.Swiftcast) && + ((LevelChecked(CreatureMotif) && !gauge.CreatureMotifDrawn) || + (LevelChecked(WeaponMotif) && !gauge.WeaponMotifDrawn) || + (LevelChecked(LandscapeMotif) && !gauge.LandscapeMotifDrawn))) + return All.Swiftcast; } //Prepare for Burst From 04ceffb3996f0d544369e6999461eb3fffc6dd38 Mon Sep 17 00:00:00 2001 From: ace Date: Sat, 7 Sep 2024 10:51:07 -0700 Subject: [PATCH 083/208] . --- XIVSlothCombo/Combos/PvE/VPR.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 0a5964970..6c92f1eb1 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -202,14 +202,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return UncoiledFury; //Vicewinder Usage - if (HasEffect(Buffs.Swiftscaled) && + if (HasEffect(Buffs.Swiftscaled) && !VPRCheckTimers.IsComboExpiring(3) && ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) return Vicewinder; // Uncoiled Fury usage - if (LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + if (LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && !VPRCheckTimers.IsComboExpiring(2) && RattlingCoils > 1 && !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && !WasLastWeaponskill(Ouroboros) && From e42ba2ca50b78f68107526e2db3dee76258e5264 Mon Sep 17 00:00:00 2001 From: edewen Date: Sat, 7 Sep 2024 14:39:10 -0400 Subject: [PATCH 084/208] Added not moving tag to earthly star aoe. --- XIVSlothCombo/Combos/PvE/AST.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 2ec8d483b..6298a0e37 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -452,7 +452,7 @@ Gauge.DrawnCards[0] is not CardType.NONE && ActionWatching.NumberOfGcdsUsed >= 3) return Divination; //Earthly Star - if (IsEnabled(CustomComboPreset.AST_AOE_DPS_EarthlyStar) && + if (IsEnabled(CustomComboPreset.AST_AOE_DPS_EarthlyStar) && !IsMoving && ActionReady(EarthlyStar) && CanSpellWeave(actionID)) return EarthlyStar; From 7ab33b994deb6530001815a8a6ec7baa1b2223bf Mon Sep 17 00:00:00 2001 From: Katie Date: Sat, 7 Sep 2024 15:34:05 -0400 Subject: [PATCH 085/208] Add variant action options --- XIVSlothCombo/Combos/CustomComboPreset.cs | 10 +++++++ XIVSlothCombo/Combos/PvE/VPR.cs | 30 +++++++++++++++++++- XIVSlothCombo/Window/Functions/UserConfig.cs | 3 ++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..6596327fc 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4218,6 +4218,16 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Include Twin Combo Actions", "Adds Twinfang and Twinblood to the button.", VPR.JobID)] VPR_VicepitDens_oGCDs = 30207, + [Variant] + [VariantParent(VPR_ST_AdvancedMode, VPR_AoE_AdvancedMode)] + [CustomComboInfo("Cure Option", "Use Variant Cure when HP is below set threshold.", VPR.JobID)] + VPR_Variant_Cure = 30300, + + [Variant] + [VariantParent(VPR_ST_AdvancedMode, VPR_AoE_AdvancedMode)] + [CustomComboInfo("Rampart Option", "Use Variant Rampart on cooldown.", VPR.JobID)] + VPR_Variant_Rampart = 30301, + #endregion #region WARRIOR diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index 19f984de5..e10d0c009 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.JobGauge.Types; +using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; @@ -104,7 +105,8 @@ public static UserInt VPR_AoE_UncoiledFury_HoldCharges = new("VPR_AoE_UncoiledFury_HoldCharges", 0), VPR_ST_UncoiledFury_Threshold = new("VPR_ST_UncoiledFury_Threshold", 1), VPR_AoE_UncoiledFury_Threshold = new("VPR_AoE_UncoiledFury_Threshold", 1), - VPR_ReawakenLegacyButton = new("VPR_ReawakenLegacyButton"); + VPR_ReawakenLegacyButton = new("VPR_ReawakenLegacyButton"), + VPR_VariantCure = new("VPR_VariantCure"); public static UserFloat VPR_ST_Reawaken_Usage = new("VPR_ST_Reawaken_Usage", 2), @@ -351,6 +353,19 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is SteelFangs) { + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + // Opener for VPR if (IsEnabled(CustomComboPreset.VPR_ST_Opener)) { @@ -775,6 +790,19 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is SteelMaw) { + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + if (CanWeave(ActionWatching.LastWeaponskill)) { // Death Rattle diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..82377b46e 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2401,6 +2401,9 @@ internal static void Draw(CustomComboPreset preset, bool enabled) UserConfig.DrawRadioButton(VPR.Config.VPR_ReawakenLegacyButton, "Replaces Steel Fangs", "Replaces Steel Fangs with Full Generation - Legacy combo.", 1); } + if (preset == CustomComboPreset.VPR_Variant_Cure) + UserConfig.DrawSliderInt(1, 100, VPR.Config.VPR_VariantCure, "HP% to be at or under", 200); + #endregion // ==================================================================================== #region WARRIOR From dbebab66006a61b3a115c7ef4290ba12fbd76a5a Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 7 Sep 2024 13:39:15 -0600 Subject: [PATCH 086/208] Prevent most of combo code when out of combat, Fixes issue with Improvisation flashing pre-pull --- XIVSlothCombo/Combos/PvE/DNC.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index f29d0c724..1bdf130b0 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -364,6 +364,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim : TechnicalFinish4; #endregion + // Bail if not in combat + if (!InCombat()) return Cascade; + #region Weaves // ST Devilment if (IsEnabled(CustomComboPreset.DNC_ST_Adv_Devilment) && @@ -688,6 +691,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim : TechnicalFinish4; #endregion + // Bail if not in combat + if (!InCombat()) return Windmill; + #region Weaves // AoE Devilment if (IsEnabled(CustomComboPreset.DNC_AoE_Adv_Devilment) && From d390f965bc5b05268806e3ed6e6d99a6536bbb7a Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 7 Sep 2024 13:54:18 -0600 Subject: [PATCH 087/208] Moved combat check --- XIVSlothCombo/Combos/PvE/DNC.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index 1bdf130b0..b0f3ec3da 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -364,9 +364,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim : TechnicalFinish4; #endregion - // Bail if not in combat - if (!InCombat()) return Cascade; - #region Weaves // ST Devilment if (IsEnabled(CustomComboPreset.DNC_ST_Adv_Devilment) && @@ -481,7 +478,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // ST Improvisation if (IsEnabled(CustomComboPreset.DNC_ST_Adv_Improvisation) && ActionReady(Improvisation) && - !HasEffect(Buffs.TechnicalFinish)) + !HasEffect(Buffs.TechnicalFinish) && + InCombat()) return Improvisation; } #endregion @@ -691,9 +689,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim : TechnicalFinish4; #endregion - // Bail if not in combat - if (!InCombat()) return Windmill; - #region Weaves // AoE Devilment if (IsEnabled(CustomComboPreset.DNC_AoE_Adv_Devilment) && @@ -794,7 +789,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // AoE Improvisation if (IsEnabled(CustomComboPreset.DNC_AoE_Adv_Improvisation) && ActionReady(Improvisation) && - !HasEffect(Buffs.TechnicalStep)) + !HasEffect(Buffs.TechnicalStep) && + InCombat()) return Improvisation; } #endregion From 92e63524473fcf02289054f9c9ad88389c15d4f4 Mon Sep 17 00:00:00 2001 From: Katie Date: Sat, 7 Sep 2024 16:23:01 -0400 Subject: [PATCH 088/208] Add variant action options --- XIVSlothCombo/Combos/CustomComboPreset.cs | 9 ++++++ XIVSlothCombo/Combos/PvE/PCT.cs | 30 +++++++++++++++++++- XIVSlothCombo/Window/Functions/UserConfig.cs | 3 ++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..930761fc5 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2606,6 +2606,15 @@ public enum CustomComboPreset [CustomComboInfo("One Button Paint", "Consolidates paint-consuming actions into one button.", PCT.JobID)] CombinedPaint = 20004, + [Variant] + [VariantParent(PCT_ST_AdvancedMode, PCT_AoE_AdvancedMode)] + [CustomComboInfo("Cure Option", "Use Variant Cure when HP is below set threshold.", PCT.JobID)] + PCT_Variant_Cure = 20100, + + [Variant] + [VariantParent(PCT_ST_AdvancedMode, PCT_AoE_AdvancedMode)] + [CustomComboInfo("Rampart Option", "Use Variant Rampart on cooldown.", PCT.JobID)] + PCT_Variant_Rampart = 20101, // Last value for AoE = 20067 #endregion diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index df12da91e..2ab1524d0 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using XIVSlothCombo.Combos.JobHelpers; +using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; @@ -75,7 +76,8 @@ public static class Config public static UserInt CombinedAetherhueChoices = new("CombinedAetherhueChoices"), PCT_ST_AdvancedMode_LucidOption = new("PCT_ST_AdvancedMode_LucidOption", 6500), - PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500); + PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500), + PCT_VariantCure = new("PCT_VariantCure"); public static UserBool CombinedMotifsMog = new("CombinedMotifsMog"), @@ -193,6 +195,19 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell) || CanSpellWeave(actionID); + // Variant Cure + if (IsEnabled(CustomComboPreset.PCT_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.PCT_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.PCT_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + canWeave) + return Variant.VariantRampart; + // Prepull logic if (IsEnabled(CustomComboPreset.PCT_ST_AdvancedMode_PrePullMotifs)) { @@ -558,6 +573,19 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + // Variant Cure + if (IsEnabled(CustomComboPreset.PCT_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.PCT_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.PCT_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + canWeave) + return Variant.VariantRampart; + // Prepull logic if (IsEnabled(CustomComboPreset.PCT_AoE_AdvancedMode_PrePullMotifs)) { diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..c50ee1c79 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1681,6 +1681,9 @@ internal static void Draw(CustomComboPreset preset, bool enabled) UserConfig.DrawSliderInt(0, 10000, PCT.Config.PCT_AoE_AdvancedMode_LucidOption, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); } + if (preset == CustomComboPreset.PCT_Variant_Cure) + UserConfig.DrawSliderInt(1, 100, PCT.Config.PCT_VariantCure, "HP% to be at or under", 200); + // PvP if (preset == CustomComboPreset.PCTPvP_BurstControl) UserConfig.DrawSliderInt(1, 100, PCTPvP.Config.PCTPvP_BurstHP, "Target HP%", 200); From 4fb1f7b24101e9901f013803b73f4a03ca911ef9 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sun, 8 Sep 2024 02:26:11 -0600 Subject: [PATCH 089/208] Fix issue with colliding Variant Option IDs --- XIVSlothCombo/Window/Tabs/PvEFeatures.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs index 2f4cecc1c..005cc8d50 100644 --- a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs +++ b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs @@ -141,9 +141,9 @@ internal class PvEFeatures : ConfigWindow private static void DrawVariantContents(string jobName) { + int i = 0; foreach (var (preset, info) in groupedPresets[jobName].Where(x => PresetStorage.IsVariant(x.Preset))) { - int i = -1; InfoBox presetBox = new() { Color = Colors.Grey, BorderThickness = 1f, CurveRadius = 8f, ContentsAction = () => { Presets.DrawPreset(preset, info, ref i); } }; presetBox.Draw(); ImGuiHelpers.ScaledDummy(12.0f); From 94b49dca49f0e42911b1a750d5e6345a5e93bab2 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sun, 8 Sep 2024 02:34:28 -0600 Subject: [PATCH 090/208] Prevent Variant Option #s --- XIVSlothCombo/Window/Functions/Presets.cs | 2 +- XIVSlothCombo/Window/Tabs/PvEFeatures.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 4234e5e58..37e552b93 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -68,7 +68,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.Spacing(); - if (ImGui.Checkbox($"{info.FancyName}###{i}", ref enabled)) + if (ImGui.Checkbox($"{info.FancyName}###{preset}{i}", ref enabled)) { if (enabled) { diff --git a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs index 005cc8d50..2f4cecc1c 100644 --- a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs +++ b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs @@ -141,9 +141,9 @@ internal class PvEFeatures : ConfigWindow private static void DrawVariantContents(string jobName) { - int i = 0; foreach (var (preset, info) in groupedPresets[jobName].Where(x => PresetStorage.IsVariant(x.Preset))) { + int i = -1; InfoBox presetBox = new() { Color = Colors.Grey, BorderThickness = 1f, CurveRadius = 8f, ContentsAction = () => { Presets.DrawPreset(preset, info, ref i); } }; presetBox.Draw(); ImGuiHelpers.ScaledDummy(12.0f); From 04a420e57fbb1c020486e036b0f4bf57666a40b8 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sun, 8 Sep 2024 05:05:07 -0600 Subject: [PATCH 091/208] Add WHM AoE 'opener' option --- XIVSlothCombo/Combos/CustomComboPreset.cs | 5 +++++ XIVSlothCombo/Combos/PvE/WHM.cs | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..323b93a8c 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4415,6 +4415,11 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("AoE DPS Feature", "Collection of cooldowns and spell features on Holy/Holy III.", WHM.JobID, 2, "", "")] WHM_AoE_DPS = 19190, + [ParentCombo(WHM_AoE_DPS)] + [CustomComboInfo("Swift Holy Pull 'Opener' Option", "Adds a Swiftcast->Holy at the beginning of your AoE rotation." + + "\nRequires you to already be in combat, to have stopped moving, and to not have used Assize yet.", WHM.JobID, 20, "", "")] + WHM_AoE_DPS_SwiftHoly = 19197, + [ParentCombo(WHM_AoE_DPS)] [CustomComboInfo("Assize Option", "Adds Assize to the AoE combo.", WHM.JobID, 21, "", "")] WHM_AoE_DPS_Assize = 19192, diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 6c2f1a46d..dc99e2d2c 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -429,6 +429,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim internal class WHM_AoE_DPS : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.WHM_AoE_DPS; + internal static int AssizeCount => ActionWatching.CombatActions.Count(x => x == Assize); protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { @@ -440,6 +441,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool liliesNearlyFull = gauge.Lily == 2 && gauge.LilyTimer >= 17000; bool PresenceOfMindReady = ActionReady(PresenceOfMind) && (!Config.WHM_AoEDPS_PresenceOfMindWeave); + if (IsEnabled(CustomComboPreset.WHM_AoE_DPS_SwiftHoly) && + ActionReady(All.Swiftcast) && + AssizeCount == 0 && !IsMoving && InCombat()) + return All.Swiftcast; + if (IsEnabled(CustomComboPreset.WHM_AoE_DPS_SwiftHoly) && + WasLastAction(All.Swiftcast)) + return actionID; + if (IsEnabled(CustomComboPreset.WHM_AoE_DPS_Assize) && ActionReady(Assize)) return Assize; From 07d41e49909e80962e52253c5a750bd7bc7f517c Mon Sep 17 00:00:00 2001 From: Kage Date: Sun, 8 Sep 2024 19:01:17 +0200 Subject: [PATCH 092/208] add Advanced AoE refactor code --- XIVSlothCombo/Combos/CustomComboPreset.cs | 63 +- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 596 +++++---- XIVSlothCombo/Combos/PvE/MNK.cs | 1168 +++++++++--------- XIVSlothCombo/Window/Functions/UserConfig.cs | 9 + 4 files changed, 973 insertions(+), 863 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index e0539e3e7..936d7cd6d 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1947,19 +1947,21 @@ public enum CustomComboPreset #region MONK - [ReplaceSkill([MNK.Bootshine])] - [CustomComboInfo("Simple Mode - Single Target", "Replaces Bootshine with a one - button full single target rotation.\nThis is ideal for newcomers to the job.", MNK.JobID)] + [ReplaceSkill([MNK.Bootshine, MNK.LeapingOpo])] [ConflictingCombos(MNK_ST_BeastChakras, MNK_ST_AdvancedMode)] + [CustomComboInfo("Simple Mode - Single Target", "Replaces Bootshine with a one - button full single target rotation.\nThis is ideal for newcomers to the job.", MNK.JobID)] MNK_ST_SimpleMode = 9004, - [ReplaceSkill([MNK.ArmOfTheDestroyer])] + [ReplaceSkill([MNK.ArmOfTheDestroyer,MNK.ShadowOfTheDestroyer])] + [ConflictingCombos(MNK_AOE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Arm of the Destroyer with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", MNK.JobID)] MNK_AOE_SimpleMode = 9003, #region Monk Advanced ST + [ReplaceSkill([MNK.Bootshine])] - [CustomComboInfo("Advanced Mode - Single Target", "Replaces Bootshine with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", MNK.JobID)] [ConflictingCombos(MNK_ST_BeastChakras, MNK_ST_SimpleMode)] + [CustomComboInfo("Advanced Mode - Single Target", "Replaces Bootshine with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", MNK.JobID)] MNK_ST_AdvancedMode = 9005, [ParentCombo(MNK_ST_AdvancedMode)] @@ -2016,6 +2018,55 @@ public enum CustomComboPreset #endregion + #region Monk Advanced AOE + + [ReplaceSkill([MNK.ArmOfTheDestroyer, MNK.ShadowOfTheDestroyer])] + [ConflictingCombos(MNK_AOE_SimpleMode)] + [CustomComboInfo("Advanced Mode - AoE", "Replaces Arm of the Destroyer with a one-button full single target rotation.\nThese features are ideal if you want to customize the rotation.", MNK.JobID)] + MNK_AOE_AdvancedMode = 9027, + + [ParentCombo(MNK_AOE_AdvancedMode)] + [CustomComboInfo("Meditation Option", "Adds Meditation to the rotation", MNK.JobID)] + MNK_AoEUseMeditation = 9028, + + [ParentCombo(MNK_AOE_AdvancedMode)] + [CustomComboInfo("Buffs Option", "Adds selected buffs to the rotation", MNK.JobID)] + MNK_AoEUseBuffs = 9029, + + [ParentCombo(MNK_AoEUseBuffs)] + [CustomComboInfo("Brotherhood Option", "Adds Brotherhood to the rotation", MNK.JobID)] + MNK_AoEUseBrotherhood = 9030, + + [ParentCombo(MNK_AoEUseBuffs)] + [CustomComboInfo("Riddle of Wind Option", "Adds Riddle of Wind to the rotation", MNK.JobID)] + MNK_AoEUseROW = 9031, + + [ParentCombo(MNK_AoEUseBuffs)] + [CustomComboInfo("Riddle of Fire Option", "Adds Riddle of Fire to the rotation", MNK.JobID)] + MNK_AoEUseROF = 9032, + + [ParentCombo(MNK_AOE_AdvancedMode)] + [CustomComboInfo("Howling Fist Option", "Adds Howling Fist to the rotation", MNK.JobID)] + MNK_AoEUseHowlingFist = 9033, + + [ParentCombo(MNK_AOE_AdvancedMode)] + [CustomComboInfo("Perfect Balance Option", "Adds Perfect Balance and Masterful Blitz to the rotation", MNK.JobID)] + MNK_AoEUsePerfectBalance = 9034, + + [ParentCombo(MNK_AoEUseROW)] + [CustomComboInfo("Wind's Reply Option", "Adds Wind's Reply to the rotation", MNK.JobID)] + MNK_AoEUseWindsReply = 9035, + + [ParentCombo(MNK_AoEUseROF)] + [CustomComboInfo("Fire's Reply Option", "Adds Fire's Reply to the rotation", MNK.JobID)] + MNK_AoEUseFiresReply = 9036, + + [ParentCombo(MNK_AOE_AdvancedMode)] + [CustomComboInfo("Combo Heals Option", "Adds Bloodbath and Second Wind to the rotation.", MNK.JobID)] + MNK_AoE_ComboHeals = 9037, + + #endregion + #region Monk Beast Chakras [ConflictingCombos(MNK_ST_AdvancedMode, MNK_ST_SimpleMode)] @@ -2060,8 +2111,10 @@ public enum CustomComboPreset MNK_Variant_Cure = 9026, #endregion - + + // last value = 9037 // End Monk + #endregion #region NINJA diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index 564013dd3..a74cf5810 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -1,415 +1,405 @@ -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.JobGauge.Enums; using ECommons.DalamudServices; -using System.Linq; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Combos.PvE; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; -using XIVSlothCombo.Extensions; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers -{ +namespace XIVSlothCombo.Combos.JobHelpers; - internal class MNKHelper : MNK +internal abstract class MNKHelper : MNK +{ + public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled = true) { - public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled = true) + if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) + return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) + ? DragonKick + : OriginalHook(Bootshine); + + if (HasEffect(Buffs.RaptorForm)) + return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) + ? TwinSnakes + : OriginalHook(TrueStrike); + + if (HasEffect(Buffs.CoeurlForm)) { - if (CustomComboFunctions.HasEffect(Buffs.OpoOpoForm) || CustomComboFunctions.HasEffect(Buffs.FormlessFist)) + if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) { - if (Gauge.OpoOpoFury == 0 && DragonKick.LevelChecked()) - { - if (CustomComboFunctions.LevelChecked(DragonKick)) - return DragonKick; - } - else - { - return CustomComboFunctions.OriginalHook(Bootshine); - } - } + if (!OnTargetsRear() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; - if (CustomComboFunctions.HasEffect(Buffs.RaptorForm)) - { - if (Gauge.RaptorFury == 0 && TwinSnakes.LevelChecked()) - { - if (CustomComboFunctions.LevelChecked(TwinSnakes)) - return TwinSnakes; - } - else - { - if (CustomComboFunctions.LevelChecked(TrueStrike)) - return CustomComboFunctions.OriginalHook(TrueStrike); - } + return Demolish; } - if (CustomComboFunctions.HasEffect(Buffs.CoeurlForm)) + if (LevelChecked(SnapPunch)) { - if (Gauge.CoeurlFury == 0 && Demolish.LevelChecked()) - { - if (!CustomComboFunctions.OnTargetsRear() - && CustomComboFunctions.TargetNeedsPositionals() - && !CustomComboFunctions.HasEffect(Buffs.TrueNorth) - && CustomComboFunctions.LevelChecked(TrueNorth) - && CustomComboFunctions.HasCharges(TrueNorth) - && useTrueNorthIfEnabled) - { - return TrueNorth; - } - else - { - if (CustomComboFunctions.LevelChecked(Demolish)) - return Demolish; - } - } - - if (!CustomComboFunctions.OnTargetsFlank() - && CustomComboFunctions.TargetNeedsPositionals() - && !CustomComboFunctions.HasEffect(Buffs.TrueNorth) - && CustomComboFunctions.LevelChecked(TrueNorth) - && CustomComboFunctions.HasCharges(TrueNorth) - && useTrueNorthIfEnabled) - { + if (!OnTargetsFlank() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) return TrueNorth; - } - else - { - if (CustomComboFunctions.LevelChecked(SnapPunch)) - return CustomComboFunctions.OriginalHook(SnapPunch); - } - } - return actionId; + return OriginalHook(SnapPunch); + } } + + return actionId; } +} + +internal class MNKOpenerLogic : MNK +{ + private OpenerState currentState = OpenerState.PrePull; + + public uint OpenerStep; + + public uint PrePullStep; - internal class MNKOpenerLogic : MNK + private static uint OpenerLevel => 100; + + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState { - private static bool HasCooldowns() + get => currentState; + set { - if (CustomComboFunctions.GetRemainingCharges(PerfectBalance) < 2) - return false; + if (value != currentState) + { + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; - if (!CustomComboFunctions.ActionReady(Brotherhood)) - return false; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - if (!CustomComboFunctions.ActionReady(RiddleOfFire)) - return false; + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - if (!CustomComboFunctions.ActionReady(RiddleOfWind)) - return false; + currentState = value; + } + } + } - if (!CustomComboFunctions.ActionReady(Meditation) && Gauge.Chakra < 5) - return false; + private static bool HasCooldowns() + { + if (GetRemainingCharges(PerfectBalance) < 2) + return false; - if (Gauge.Nadi != Dalamud.Game.ClientState.JobGauge.Enums.Nadi.NONE) - return false; + if (!ActionReady(Brotherhood)) + return false; - if (Gauge.RaptorFury != 0) return false; - if (Gauge.CoeurlFury != 0) return false; + if (!ActionReady(RiddleOfFire)) + return false; - return true; - } + if (!ActionReady(RiddleOfWind)) + return false; - private static uint OpenerLevel => 100; + if (!ActionReady(Meditation) && Gauge.Chakra < 5) + return false; - public uint PrePullStep = 0; + if (Gauge.Nadi != Nadi.NONE) + return false; - public uint OpenerStep = 0; + if (Gauge.RaptorFury != 0 || Gauge.CoeurlFury != 0) + return false; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; + return true; + } - private static bool CanOpener => HasCooldowns() && LevelChecked; + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) + return false; - private OpenerState currentState = OpenerState.PrePull; + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - public OpenerState CurrentState - { - get - { - return currentState; - } - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; - } - } - } + if (!HasCooldowns()) PrePullStep = 0; - private bool DoPrePullSteps(ref uint actionID) + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (!LevelChecked) - return false; - - if (CanOpener && PrePullStep == 0) + if (Gauge.Chakra < 5 && PrePullStep == 1) { - PrePullStep = 1; + actionID = ForbiddenMeditation; + + return true; } - if (!HasCooldowns()) + if (!HasEffect(Buffs.FormlessFist) && + !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) { - PrePullStep = 0; + actionID = FormShift; + + return true; } - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (Gauge.Chakra < 5 && PrePullStep == 1) - { - actionID = ForbiddenMeditation; - return true; - } + if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = DragonKick; - if (!CustomComboFunctions.HasEffect(Buffs.FormlessFist) && !CustomComboFunctions.HasEffect(Buffs.RaptorForm) && PrePullStep == 1) - { - actionID = FormShift; - return true; - } + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; - if (CustomComboFunctions.WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = DragonKick; + return true; + } + PrePullStep = 0; - if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) - CurrentState = OpenerState.FailedOpener; + return false; + } - return true; - } - PrePullStep = 0; + private bool DoSlOpener(ref uint actionID) + { + if (!LevelChecked) return false; - } - private bool DoSLOpener(ref uint actionID) + if (currentState == OpenerState.InOpener) { - if (!LevelChecked) - return false; - - if (currentState == OpenerState.InOpener) + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + Gauge.Chakra >= 5 && + OpenerStep > 2) { - if (CustomComboFunctions.IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) - && Gauge.Chakra >= 5 - && OpenerStep > 2) - { - actionID = TheForbiddenChakra; - return true; - } + actionID = TheForbiddenChakra; - if ((CustomComboFunctions.WasLastAction(PerfectBalance) || CustomComboFunctions.HasEffect(Buffs.PerfectBalance)) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = PerfectBalance; + return true; + } - if (CustomComboFunctions.WasLastAction(TheForbiddenChakra) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = TheForbiddenChakra; + if ((WasLastAction(PerfectBalance) || + HasEffect(Buffs.PerfectBalance)) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = PerfectBalance; - if (CustomComboFunctions.WasLastWeaponskill(TwinSnakes) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = TwinSnakes; + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = TheForbiddenChakra; - if (CustomComboFunctions.WasLastWeaponskill(Demolish) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Demolish; + if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = TwinSnakes; - if (CustomComboFunctions.WasLastAbility(Brotherhood) && CustomComboFunctions.HasEffect(Buffs.Brotherhood) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Brotherhood; + if (WasLastWeaponskill(Demolish) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Demolish; - if (CustomComboFunctions.WasLastAction(RiddleOfFire) && CustomComboFunctions.HasEffect(Buffs.RiddleOfFire) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = RiddleOfFire; + if (WasLastAbility(Brotherhood) && HasEffect(Buffs.Brotherhood) && + OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = Brotherhood; - // Pot + if (WasLastAction(RiddleOfFire) && + HasEffect(Buffs.RiddleOfFire) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = RiddleOfFire; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = LeapingOpo; + // Pot - if (CustomComboFunctions.WasLastAction(RiddleOfWind) && CustomComboFunctions.HasEffect(Buffs.RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = RiddleOfWind; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = RisingPhoenix; + if (WasLastAction(RiddleOfWind) && + HasEffect(Buffs.RiddleOfWind) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = RiddleOfWind; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonKick; + if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = RisingPhoenix; - if ((CustomComboFunctions.WasLastWeaponskill(FiresReply) || !CustomComboFunctions.HasEffect(Buffs.FiresRumination)) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = FiresReply; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonKick; - if ((CustomComboFunctions.WasLastWeaponskill(WindsReply) || !CustomComboFunctions.HasEffect(Buffs.WindsRumination)) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = WindsReply; + if ((WasLastWeaponskill(FiresReply) || + !HasEffect(Buffs.FiresRumination)) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = FiresReply; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = LeapingOpo; + if ((WasLastWeaponskill(WindsReply) || + !HasEffect(Buffs.WindsRumination)) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = WindsReply; - if ((CustomComboFunctions.WasLastAction(PerfectBalance) || CustomComboFunctions.HasEffect(Buffs.PerfectBalance)) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = PerfectBalance; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = DragonKick; + if ((WasLastAction(PerfectBalance) || + HasEffect(Buffs.PerfectBalance)) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = PerfectBalance; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LeapingOpo; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = DragonKick; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = DragonKick; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = ElixirBurst; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = DragonKick; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 19) actionID = LeapingOpo; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = ElixirBurst; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) + CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 19) actionID = LeapingOpo; - if (((actionID == PerfectBalance && CustomComboFunctions.GetRemainingCharges(PerfectBalance) == 0) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) || - (OpenerStep is 6 && CustomComboFunctions.HasEffect(Buffs.RiddleOfFire)) || - (OpenerStep is 8 && CustomComboFunctions.HasEffect(Buffs.RiddleOfWind)) || - (OpenerStep is 5 && CustomComboFunctions.HasEffect(Buffs.Brotherhood)) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - Svc.Log.Debug($"Failed at {actionID}"); - CurrentState = OpenerState.FailedOpener; - return false; - } - return true; + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if ((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0 && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) || + (OpenerStep is 6 && HasEffect(Buffs.RiddleOfFire)) || + (OpenerStep is 8 && HasEffect(Buffs.RiddleOfWind)) || + (OpenerStep is 5 && HasEffect(Buffs.Brotherhood) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3)) + { + Svc.Log.Debug($"Failed at {actionID}"); + CurrentState = OpenerState.FailedOpener; + + return false; } - return false; + + return true; } - private bool DoLLOpener(ref uint actionID) - { - if (!LevelChecked) - return false; + return false; + } + + private bool DoLlOpener(ref uint actionID) + { + if (!LevelChecked) + return false; - if (currentState == OpenerState.InOpener) + if (currentState == OpenerState.InOpener) + { + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) + && Gauge.Chakra >= 5 + && OpenerStep > 2) { - if (CustomComboFunctions.IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) - && Gauge.Chakra >= 5 - && OpenerStep > 2) - { - actionID = TheForbiddenChakra; - return true; - } + actionID = TheForbiddenChakra; - if ((CustomComboFunctions.WasLastAction(PerfectBalance) || CustomComboFunctions.HasEffect(Buffs.PerfectBalance)) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = PerfectBalance; + return true; + } - if (CustomComboFunctions.WasLastAction(TheForbiddenChakra) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = TheForbiddenChakra; + if ((WasLastAction(PerfectBalance) || + HasEffect(Buffs.PerfectBalance)) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = PerfectBalance; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = LeapingOpo; + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = TheForbiddenChakra; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = DragonKick; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastAbility(Brotherhood) && CustomComboFunctions.HasEffect(Buffs.Brotherhood) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Brotherhood; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = DragonKick; - if (CustomComboFunctions.WasLastAction(RiddleOfFire) && CustomComboFunctions.HasEffect(Buffs.RiddleOfFire) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = RiddleOfFire; + if (WasLastAbility(Brotherhood) && HasEffect(Buffs.Brotherhood) && + OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = Brotherhood; - // Pot + if (WasLastAction(RiddleOfFire) && + HasEffect(Buffs.RiddleOfFire) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = RiddleOfFire; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = LeapingOpo; + // Pot - if (CustomComboFunctions.WasLastAction(RiddleOfWind) && CustomComboFunctions.HasEffect(Buffs.RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = RiddleOfWind; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = ElixirBurst; + if (WasLastAction(RiddleOfWind) && + HasEffect(Buffs.RiddleOfWind) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = RiddleOfWind; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonKick; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = ElixirBurst; - if ((CustomComboFunctions.WasLastWeaponskill(FiresReply) || !CustomComboFunctions.HasEffect(Buffs.FiresRumination)) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = FiresReply; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonKick; - if ((CustomComboFunctions.WasLastWeaponskill(WindsReply) || !CustomComboFunctions.HasEffect(Buffs.WindsRumination)) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = WindsReply; + if ((WasLastWeaponskill(FiresReply) || + !HasEffect(Buffs.FiresRumination)) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = FiresReply; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = LeapingOpo; + if ((WasLastWeaponskill(WindsReply) || + !HasEffect(Buffs.WindsRumination)) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = WindsReply; - if ((CustomComboFunctions.WasLastAction(PerfectBalance) || CustomComboFunctions.HasEffect(Buffs.PerfectBalance)) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = PerfectBalance; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = DragonKick; + if ((WasLastAction(PerfectBalance) || + HasEffect(Buffs.PerfectBalance)) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = PerfectBalance; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LeapingOpo; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = DragonKick; - if (CustomComboFunctions.WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = DragonKick; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LeapingOpo; - if (CustomComboFunctions.WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = ElixirBurst; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = DragonKick; - if (CustomComboFunctions.WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 19) actionID = LeapingOpo; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = ElixirBurst; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) + CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 19) actionID = LeapingOpo; - if (((actionID == PerfectBalance && CustomComboFunctions.GetRemainingCharges(PerfectBalance) == 0) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) || - (OpenerStep is 6 && CustomComboFunctions.HasEffect(Buffs.RiddleOfFire)) || - (OpenerStep is 8 && CustomComboFunctions.HasEffect(Buffs.RiddleOfWind)) || - (OpenerStep is 5 && CustomComboFunctions.HasEffect(Buffs.Brotherhood)) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - Svc.Log.Debug($"Failed at {actionID}"); - CurrentState = OpenerState.FailedOpener; - return false; - } - return true; + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if ((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0 && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) || + (OpenerStep is 6 && HasEffect(Buffs.RiddleOfFire)) || + (OpenerStep is 8 && HasEffect(Buffs.RiddleOfWind)) || + (OpenerStep is 5 && HasEffect(Buffs.Brotherhood) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3)) + { + Svc.Log.Debug($"Failed at {actionID}"); + CurrentState = OpenerState.FailedOpener; + + return false; } - return false; - } - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; + return true; } - public bool DoFullOpener(ref uint actionID, int selectedOpener) - { - if (!LevelChecked) - return false; + return false; + } - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } - if (CurrentState == OpenerState.InOpener) + public bool DoFullOpener(ref uint actionID, int selectedOpener) + { + if (!LevelChecked) + return false; + + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; + + if (CurrentState == OpenerState.InOpener) + { + if (selectedOpener == 1) { - if (selectedOpener == 1) - { - if (DoLLOpener(ref actionID)) - return true; - } - else if (selectedOpener == 2) - { - if (DoSLOpener(ref actionID)) - return true; - } + if (DoLlOpener(ref actionID)) + return true; } - - if (!CustomComboFunctions.InCombat()) + else if (selectedOpener == 2) { - ResetOpener(); - CurrentState = OpenerState.PrePull; + if (DoSlOpener(ref actionID)) + return true; } - return false; } + + if (!InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; + } + + return false; } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 69ef36c6a..04e9242d4 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -1,690 +1,748 @@ +using System.Linq; using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.JobGauge.Types; -using System; -using System.Linq; +using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.JobHelpers; using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE; -namespace XIVSlothCombo.Combos.PvE +internal class MNK { - internal class MNK + public const byte ClassID = 2; + public const byte JobID = 20; + + public const uint + Bootshine = 53, + TrueStrike = 54, + SnapPunch = 56, + Meditation = 36940, + SteelPeak = 25761, + TwinSnakes = 61, + ArmOfTheDestroyer = 62, + Demolish = 66, + Mantra = 65, + DragonKick = 74, + Rockbreaker = 70, + Thunderclap = 25762, + HowlingFist = 25763, + FourPointFury = 16473, + PerfectBalance = 69, + FormShift = 4262, + TheForbiddenChakra = 3547, + MasterfulBlitz = 25764, + RiddleOfEarth = 7394, + EarthsReply = 36944, + RiddleOfFire = 7395, + Brotherhood = 7396, + RiddleOfWind = 25766, + EnlightenedMeditation = 36943, + Enlightenment = 16474, + SixSidedStar = 16476, + ShadowOfTheDestroyer = 25767, + RisingPhoenix = 25768, + WindsReply = 36949, + ForbiddenMeditation = 36942, + LeapingOpo = 36945, + RisingRaptor = 36946, + PouncingCoeurl = 36947, + TrueNorth = 7546, + ElixirBurst = 36948, + FiresReply = 36950; + + protected static MNKGauge Gauge => GetJobGauge(); + + protected static class Buffs { - public const byte ClassID = 2; - public const byte JobID = 20; - - public const uint - Bootshine = 53, - TrueStrike = 54, - SnapPunch = 56, - Meditation = 36940, - SteelPeak = 25761, - TwinSnakes = 61, - ArmOfTheDestroyer = 62, - Demolish = 66, - Mantra = 65, - DragonKick = 74, - Rockbreaker = 70, - Thunderclap = 25762, - HowlingFist = 25763, - FourPointFury = 16473, - PerfectBalance = 69, - FormShift = 4262, - TheForbiddenChakra = 3547, - MasterfulBlitz = 25764, - RiddleOfEarth = 7394, - EarthsReply = 36944, - RiddleOfFire = 7395, - Brotherhood = 7396, - RiddleOfWind = 25766, - EnlightenedMeditation = 36943, - Enlightenment = 16474, - SixSidedStar = 16476, - ShadowOfTheDestroyer = 25767, - RisingPhoenix = 25768, - WindsReply = 36949, - ForbiddenMeditation = 36942, - LeapingOpo = 36945, - RisingRaptor = 36946, - PouncingCoeurl = 36947, - TrueNorth = 7546, - ElixirBurst = 36948, - FiresReply = 36950; - - public static class Buffs - { - public const ushort - TwinSnakes = 101, - OpoOpoForm = 107, - RaptorForm = 108, - CoeurlForm = 109, - PerfectBalance = 110, - RiddleOfFire = 1181, - RiddleOfWind = 2687, - FormlessFist = 2513, - TrueNorth = 1250, - WindsRumination = 3842, - FiresRumination = 3843, - Brotherhood = 1185; - } + public const ushort + TwinSnakes = 101, + OpoOpoForm = 107, + RaptorForm = 108, + CoeurlForm = 109, + PerfectBalance = 110, + RiddleOfFire = 1181, + RiddleOfWind = 2687, + FormlessFist = 2513, + TrueNorth = 1250, + WindsRumination = 3842, + FiresRumination = 3843, + Brotherhood = 1185; + } - public static MNKGauge Gauge => CustomComboFunctions.GetJobGauge(); + public static class Config + { + public static UserInt + MNK_ST_SecondWind_Threshold = new("MNK_ST_SecondWindThreshold", 25), + MNK_ST_Bloodbath_Threshold = new("MNK_ST_BloodbathThreshold", 40), + MNK_AoE_SecondWind_Threshold = new("MNK_AoE_SecondWindThreshold", 25), + MNK_AoE_Bloodbath_Threshold = new("MNK_AoE_BloodbathThreshold", 40), + MNK_SelectedOpener = new("MNK_SelectedOpener"), + MNK_VariantCure = new("MNK_Variant_Cure"); + } - public static class Config - { - public static UserInt - MNK_ST_SecondWind_Threshold = new("MNK_ST_SecondWindThreshold", 25), - MNK_ST_Bloodbath_Threshold = new("MNK_ST_BloodbathThreshold", 40), - MNK_SelectedOpener = new("MNK_SelectedOpener"), - MNK_VariantCure = new("MNK_Variant_Cure"); - } + internal class MNK_ST_SimpleMode : CustomCombo + { + internal static MNKOpenerLogic MNKOpener = new(); - internal class MNK_ST_SimpleMode : CustomCombo + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_SimpleMode; - internal static MNKOpenerLogic MNKOpener = new(); - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; + bool solarNadi = Gauge.Nadi == Nadi.SOLAR; + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); + int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); + int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + + if (actionID is Bootshine or LeapingOpo) { - bool canWeave = CanWeave(actionID, 0.5); - bool inCombat = HasCondition(Dalamud.Game.ClientState.Conditions.ConditionFlag.InCombat); - bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; - - if (actionID is Bootshine or LeapingOpo) + if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) + return actionID; + + //Variant Cure + if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MNK_VariantCure) + return Variant.VariantCure; + + if ((!InCombat() || !InMeleeRange()) && + Gauge.Chakra < 5 && + HasEffect(Buffs.RiddleOfFire) && + LevelChecked(Meditation)) + return OriginalHook(Meditation); + + // OGCDs + if (CanWeave(ActionWatching.LastWeaponskill)) { - if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) - return actionID; + //Variant Rampart + if (IsEnabled(CustomComboPreset.MNK_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart)) + return Variant.VariantRampart; + + if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance) && + (((JustUsed(LeapingOpo) || JustUsed(DragonKick)) && + GetCooldownRemainingTime(RiddleOfFire) < 8 && + GetCooldownRemainingTime(Brotherhood) < 7) || + (GetBuffRemainingTime(Buffs.RiddleOfFire) >= 8 && + !HasEffect(Buffs.FiresRumination)))) + return PerfectBalance; + + if (ActionReady(Brotherhood)) + return Brotherhood; + + if (ActionReady(RiddleOfFire)) + return RiddleOfFire; + + if (ActionReady(RiddleOfWind)) + return RiddleOfWind; + + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) + return All.Bloodbath; + + if (Gauge.Chakra >= 5 && + SteelPeak.LevelChecked()) + return OriginalHook(SteelPeak); + } + + // GCDs + // Ensure usage if buff is almost depleted. + if (HasEffect(Buffs.FiresRumination) && + GetBuffRemainingTime(Buffs.FiresRumination) < 4) + return FiresReply; + if (HasEffect(Buffs.WindsRumination) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) + return WindsReply; - if (IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MNK_VariantCure) - return Variant.VariantCure; + if (HasEffect(Buffs.FormlessFist)) + return Gauge.OpoOpoFury == 0 + ? OriginalHook(DragonKick) + : OriginalHook(Bootshine); - if ((!inCombat || !InMeleeRange()) - && Gauge.Chakra < 5 - && !HasEffect(Buffs.RiddleOfFire) - && LevelChecked(Meditation)) + // Masterful Blitz + if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && + HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) + return OriginalHook(MasterfulBlitz); + + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) + { + #region Open Solar + + if (!solarNadi && !bothNadisOpen) { - return OriginalHook(Meditation); + if (coeurlChakra == 0) + return Gauge.CoeurlFury == 0 + ? OriginalHook(Demolish) + : OriginalHook(SnapPunch); + + if (raptorChakra == 0) + return Gauge.RaptorFury == 0 + ? OriginalHook(TwinSnakes) + : OriginalHook(TrueStrike); + + if (opoOpoChakra == 0) + return Gauge.OpoOpoFury == 0 + ? OriginalHook(DragonKick) + : OriginalHook(Bootshine); } - // OGCDs - if (canWeave) - { - if (IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart)) - return Variant.VariantRampart; + #endregion - if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance)) - { - if ((WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick)) - && (GetCooldownRemainingTime(RiddleOfFire) < 8 - && GetCooldownRemainingTime(Brotherhood) < 7) || - (GetBuffRemainingTime(Buffs.RiddleOfFire) >= 8 - && !HasEffect(Buffs.FiresRumination))) - { - return PerfectBalance; - } - } + #region Open Lunar - if (ActionReady(Brotherhood)) - { - return Brotherhood; - } + if (solarNadi || lunarNadi || bothNadisOpen) + return Gauge.OpoOpoFury == 0 + ? OriginalHook(DragonKick) + : OriginalHook(Bootshine); - if (ActionReady(RiddleOfFire)) - { - return RiddleOfFire; - } + #endregion + } - if (ActionReady(RiddleOfWind)) - { - return RiddleOfWind; - } + if (HasEffect(Buffs.WindsRumination)) + return WindsReply; - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) - return All.SecondWind; - if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) - return All.Bloodbath; + if (HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist) && + (JustUsed(LeapingOpo) || JustUsed(DragonKick))) + return FiresReply; - if (Gauge.Chakra >= 5 - && SteelPeak.LevelChecked()) - { - return OriginalHook(SteelPeak); - } - } + // Standard Beast Chakras + return MNKHelper.DetermineCoreAbility(actionID); + } - // GCDs + return actionID; + } + } + + internal class MNK_ST_AdvancedMode : CustomCombo + { + internal static MNKOpenerLogic MNKOpener = new(); + + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + { + bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; + bool solarNadi = Gauge.Nadi == Nadi.SOLAR; + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); + int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); + int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + + if (actionID is Bootshine or LeapingOpo) + { + if (IsEnabled(CustomComboPreset.MNK_STUseOpener)) + if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) + return actionID; - // Ensure usage if buff is almost depleted. - if (HasEffect(Buffs.FiresRumination) && GetBuffRemainingTime(Buffs.FiresRumination) < 4) + if (IsEnabled(CustomComboPreset.MNK_STUseMeditation) && + (!InCombat() || !InMeleeRange()) && + Gauge.Chakra < 5 && + !HasEffect(Buffs.RiddleOfFire) && + LevelChecked(Meditation)) + return OriginalHook(Meditation); + + //Variant Cure + if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MNK_VariantCure) + return Variant.VariantCure; + + // OGCDs + if (CanWeave(ActionWatching.LastWeaponskill)) + { + //Variant Rampart + if (IsEnabled(CustomComboPreset.MNK_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart)) + return Variant.VariantRampart; + + if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && + ActionReady(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance)) { - return FiresReply; + if ((JustUsed(LeapingOpo) || JustUsed(DragonKick)) && + GetCooldownRemainingTime(RiddleOfFire) < 7 && + GetCooldownRemainingTime(Brotherhood) < 7) + return PerfectBalance; + + if ((JustUsed(LeapingOpo) || JustUsed(DragonKick)) && + HasEffect(Buffs.RiddleOfFire) && + GetBuffRemainingTime(Buffs.RiddleOfFire) > 8 && + !HasEffect(Buffs.FiresRumination)) + return PerfectBalance; } - if (HasEffect(Buffs.WindsRumination) && GetBuffRemainingTime(Buffs.WindsRumination) < 4) + if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) { - return WindsReply; + if (IsEnabled(CustomComboPreset.MNK_STUseBrotherhood) && + ActionReady(Brotherhood)) + return Brotherhood; + + if (IsEnabled(CustomComboPreset.MNK_STUseROF) && + ActionReady(RiddleOfFire)) + return RiddleOfFire; + + if (IsEnabled(CustomComboPreset.MNK_STUseROW) && + ActionReady(RiddleOfWind)) + return RiddleOfWind; } - if (HasEffect(Buffs.FormlessFist)) + if (IsEnabled(CustomComboPreset.MNK_ST_ComboHeals)) { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); + if (PlayerHealthPercentageHp() <= Config.MNK_ST_SecondWind_Threshold && + ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= Config.MNK_ST_Bloodbath_Threshold && + ActionReady(All.Bloodbath)) + return All.Bloodbath; } + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + Gauge.Chakra >= 5 && + LevelChecked(SteelPeak)) + return OriginalHook(Meditation); + } + + // GCDs + // Ensure usage if buff is almost depleted. + if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) && + HasEffect(Buffs.FiresRumination) && + GetBuffRemainingTime(Buffs.FiresRumination) < 4) + return FiresReply; + + if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && + HasEffect(Buffs.WindsRumination) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) + return WindsReply; + + if (HasEffect(Buffs.FormlessFist)) + return Gauge.OpoOpoFury == 0 + ? OriginalHook(DragonKick) + : OriginalHook(Bootshine); + + if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) + { // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) - { + if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && + HasEffect(Buffs.RiddleOfFire) && + OriginalHook(MasterfulBlitz) != MasterfulBlitz) return OriginalHook(MasterfulBlitz); - } // Perfect Balance if (HasEffect(Buffs.PerfectBalance)) { - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); - int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); - int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); - #region Open Solar + if (!solarNadi && !bothNadisOpen) { if (coeurlChakra == 0) - { - return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); - } - else if (raptorChakra == 0) - { - return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); - } - else if (opoOpoChakra == 0) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + return Gauge.CoeurlFury == 0 + ? OriginalHook(Demolish) + : OriginalHook(SnapPunch); + + if (raptorChakra == 0) + return Gauge.RaptorFury == 0 + ? OriginalHook(TwinSnakes) + : OriginalHook(TrueStrike); + + if (opoOpoChakra == 0) + return Gauge.OpoOpoFury == 0 + ? OriginalHook(DragonKick) + : OriginalHook(Bootshine); } + #endregion + #region Open Lunar - if (solarNadi || lunarNadi || bothNadisOpen) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } - #endregion - } - if (HasEffect(Buffs.WindsRumination)) - { - return WindsReply; - } + if (solarNadi || lunarNadi || bothNadisOpen) + return Gauge.OpoOpoFury == 0 + ? OriginalHook(DragonKick) + : OriginalHook(Bootshine); - if (HasEffect(Buffs.FiresRumination) - && !HasEffect(Buffs.PerfectBalance) - && !HasEffect(Buffs.FormlessFist) - && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick))) - { - return FiresReply; + #endregion } - - // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID); - } - return actionID; + if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && + HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply)) + return WindsReply; + + if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) && + HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist) && + (JustUsed(LeapingOpo) || JustUsed(DragonKick)) && + LevelChecked(FiresReply)) + return FiresReply; + + // Standard Beast Chakras + return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); } + + return actionID; } + } + + internal class MNK_AOE_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_AOE_SimpleMode; - internal class MNK_ST_AdvancedMode : CustomCombo + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_AdvancedMode; - internal static MNKOpenerLogic MNKOpener = new(); - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + bool nadiNone = Gauge.Nadi == Nadi.NONE; + + if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) { - bool canWeave = CanWeave(actionID, 0.5); - bool inCombat = HasCondition(Dalamud.Game.ClientState.Conditions.ConditionFlag.InCombat); - bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; + if (!InCombat() && Gauge.Chakra < 5 && LevelChecked(Meditation)) + return OriginalHook(Meditation); - if (actionID is Bootshine or LeapingOpo) - { - if (IsEnabled(CustomComboPreset.MNK_STUseOpener)) - { - if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) - return actionID; - } + //Variant Cure + if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MNK_VariantCure) + return Variant.VariantCure; - if (IsEnabled(CustomComboPreset.MNK_STUseMeditation) - && (!inCombat || !InMeleeRange()) - && Gauge.Chakra < 5 - && !HasEffect(Buffs.RiddleOfFire) - && LevelChecked(Meditation)) + // Buffs + if (CanWeave(ActionWatching.LastWeaponskill)) + { + //Variant Rampart + if (IsEnabled(CustomComboPreset.MNK_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart)) + return Variant.VariantRampart; + + if (ActionReady(RiddleOfFire)) + return RiddleOfFire; + + if (LevelChecked(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance) && + IsOriginal(MasterfulBlitz)) { - return OriginalHook(Meditation); + // Use Perfect Balance if: + // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE + // 2. At max stacks / before overcap. + // 3. During Brotherhood. + // 4. During Riddle of Fire. + // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. + if ((HasCharges(PerfectBalance) && + GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || + GetCooldownRemainingTime(PerfectBalance) <= 4 || + HasEffect(Buffs.Brotherhood) || + (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || + (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) + return PerfectBalance; } - if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && IsEnabled(Variant.VariantCure) && PlayerHealthPercentageHp() <= GetOptionValue(Config.MNK_VariantCure)) - return Variant.VariantCure; + if (ActionReady(Brotherhood)) + return Brotherhood; - // OGCDs - if (inCombat && canWeave) - { - if (IsEnabled(CustomComboPreset.MNK_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart)) - return Variant.VariantRampart; + if (ActionReady(RiddleOfWind)) + return RiddleOfWind; - if (PerfectBalance.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasCharges(PerfectBalance) && IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) - { - if ((WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick)) - && GetCooldownRemainingTime(RiddleOfFire) < 7 - && GetCooldownRemainingTime(Brotherhood) < 7) - { - return PerfectBalance; - } - else if ((WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick)) - && HasEffect(Buffs.RiddleOfFire) - && GetBuffRemainingTime(Buffs.RiddleOfFire) > 8 - && !HasEffect(Buffs.FiresRumination)) - { - return PerfectBalance; - } - } + if (Gauge.Chakra >= 5 && + LevelChecked(HowlingFist) && + HasBattleTarget()) + return OriginalHook(HowlingFist); - if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) - { - if (IsEnabled(CustomComboPreset.MNK_STUseBrotherhood) - && Brotherhood.LevelChecked() - && !IsOnCooldown(Brotherhood)) - { - return Brotherhood; - } - - if (IsEnabled(CustomComboPreset.MNK_STUseROF) - && RiddleOfFire.LevelChecked() - && !IsOnCooldown(RiddleOfFire)) - { - return RiddleOfFire; - } + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + return All.SecondWind; - if (IsEnabled(CustomComboPreset.MNK_STUseROW) - && RiddleOfWind.LevelChecked() - && !IsOnCooldown(RiddleOfWind)) - { - return RiddleOfWind; - } - } + if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) + return All.Bloodbath; + } - if (PlayerHealthPercentageHp() <= PluginConfiguration.GetCustomIntValue(Config.MNK_ST_SecondWind_Threshold) && IsEnabled(CustomComboPreset.MNK_ST_ComboHeals) && LevelChecked(All.SecondWind) && IsOffCooldown(All.SecondWind)) - return All.SecondWind; - if (PlayerHealthPercentageHp() <= PluginConfiguration.GetCustomIntValue(Config.MNK_ST_Bloodbath_Threshold) && IsEnabled(CustomComboPreset.MNK_ST_ComboHeals) && LevelChecked(All.Bloodbath) && IsOffCooldown(All.Bloodbath)) - return All.Bloodbath; + if (HasEffect(Buffs.WindsRumination)) + return WindsReply; - if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) - && Gauge.Chakra >= 5 - && SteelPeak.LevelChecked()) - { - return OriginalHook(Meditation); - } - } + if (HasEffect(Buffs.FiresRumination)) + return FiresReply; - // GCDs - if (inCombat) - { - // Ensure usage if buff is almost depleted. - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) - && HasEffect(Buffs.FiresRumination) - && GetBuffRemainingTime(Buffs.FiresRumination) < 4) - { - return FiresReply; - } + // Masterful Blitz + if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && + OriginalHook(MasterfulBlitz) != MasterfulBlitz) + return OriginalHook(MasterfulBlitz); - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) - && HasEffect(Buffs.WindsRumination) - && GetBuffRemainingTime(Buffs.WindsRumination) < 4) - { - return WindsReply; - } + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) + { + if (nadiNone || !lunarNadi) + if (pbStacks?.StackCount > 0) + return ShadowOfTheDestroyer.LevelChecked() + ? ShadowOfTheDestroyer + : Rockbreaker; - if (HasEffect(Buffs.FormlessFist)) + if (lunarNadi) + switch (pbStacks?.StackCount) { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } + case 3: + return OriginalHook(ArmOfTheDestroyer); - if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) - { - // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && HasEffect(Buffs.RiddleOfFire) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) - { - return OriginalHook(MasterfulBlitz); - } + case 2: + return FourPointFury; - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) - { - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.OPOOPO).Count(); - int raptorChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.RAPTOR).Count(); - int coeurlChakra = Gauge.BeastChakra.Where(x => x == BeastChakra.COEURL).Count(); - - #region Open Solar - if (!solarNadi && !bothNadisOpen) - { - if (coeurlChakra == 0) - { - return Gauge.CoeurlFury == 0 ? OriginalHook(Demolish) : OriginalHook(SnapPunch); - } - else if (raptorChakra == 0) - { - return Gauge.RaptorFury == 0 ? OriginalHook(TwinSnakes) : OriginalHook(TrueStrike); - } - else if (opoOpoChakra == 0) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } - } - #endregion - #region Open Lunar - if (solarNadi || lunarNadi || bothNadisOpen) - { - return Gauge.OpoOpoFury == 0 ? OriginalHook(DragonKick) : OriginalHook(Bootshine); - } - #endregion - } + case 1: + return Rockbreaker; } + } - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) - && HasEffect(Buffs.WindsRumination) - && WindsReply.LevelChecked()) - { - return WindsReply; - } + // Monk Rotation + if (HasEffect(Buffs.OpoOpoForm)) + return OriginalHook(ArmOfTheDestroyer); - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) - && HasEffect(Buffs.FiresRumination) - && !HasEffect(Buffs.PerfectBalance) - && !HasEffect(Buffs.FormlessFist) - && (WasLastWeaponskill(LeapingOpo) || WasLastWeaponskill(DragonKick)) - && FiresReply.LevelChecked()) - { - return FiresReply; - } + if (HasEffect(Buffs.RaptorForm)) + { + if (LevelChecked(FourPointFury)) + return FourPointFury; - // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); - } + if (LevelChecked(TwinSnakes)) + return TwinSnakes; } - return actionID; + if (HasEffect(Buffs.CoeurlForm) && LevelChecked(Rockbreaker)) + return Rockbreaker; } + + return actionID; } + } - internal class MNK_AoE_SimpleMode : CustomCombo + internal class MNK_AOE_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_AOE_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_AOE_SimpleMode; + Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); + bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; + bool nadiNone = Gauge.Nadi == Nadi.NONE; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) { - if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) + if (IsEnabled(CustomComboPreset.MNK_AoEUseMeditation) && + !InCombat() && Gauge.Chakra < 5 && LevelChecked(Meditation)) + return OriginalHook(Meditation); + + //Variant Cure + if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MNK_VariantCure) + return Variant.VariantCure; + + // Buffs + if (CanWeave(ActionWatching.LastWeaponskill)) { - bool inCombat = HasCondition(Dalamud.Game.ClientState.Conditions.ConditionFlag.InCombat); - MNKGauge gauge = GetJobGauge(); - bool canWeave = CanWeave(actionID, 0.5); - _ = CanWeave(actionID); - Dalamud.Game.ClientState.Statuses.Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); - bool lunarNadi = gauge.Nadi == Nadi.LUNAR; - bool nadiNONE = gauge.Nadi == Nadi.NONE; - - if (!inCombat) + //Variant Rampart + if (IsEnabled(CustomComboPreset.MNK_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart)) + return Variant.VariantRampart; + + if (IsEnabled(CustomComboPreset.MNK_AoEUseROF) && + ActionReady(RiddleOfFire)) + return RiddleOfFire; + + if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance) && + LevelChecked(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance) && + IsOriginal(MasterfulBlitz)) { - if (gauge.Chakra < 5 && Meditation.LevelChecked()) - { - return OriginalHook(Meditation); ; - } + // Use Perfect Balance if: + // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE + // 2. At max stacks / before overcap. + // 3. During Brotherhood. + // 4. During Riddle of Fire. + // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. + if ((HasCharges(PerfectBalance) && + GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || + GetCooldownRemainingTime(PerfectBalance) <= 4 || + HasEffect(Buffs.Brotherhood) || + (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || + (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) + return PerfectBalance; } + if (IsEnabled(CustomComboPreset.MNK_AoEUseBrotherhood) && + ActionReady(Brotherhood)) + return Brotherhood; - if (IsEnabled(Variant.VariantCure) && PlayerHealthPercentageHp() <= GetOptionValue(Config.MNK_VariantCure)) - return Variant.VariantCure; + if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && + ActionReady(RiddleOfWind)) + return RiddleOfWind; - // Buffs - if (inCombat && canWeave) - { - - if (IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart)) - return Variant.VariantRampart; + if (IsEnabled(CustomComboPreset.MNK_AoEUseHowlingFist) && + Gauge.Chakra >= 5 && + LevelChecked(HowlingFist) && + HasBattleTarget()) + return OriginalHook(HowlingFist); - if (ActionReady(RiddleOfFire)) - { - return RiddleOfFire; - } - - if (PerfectBalance.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && IsOriginal(MasterfulBlitz)) - { - // Use Perfect Balance if: - // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE - // 2. At max stacks / before overcap. - // 3. During Brotherhood. - // 4. During Riddle of Fire. - // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if (HasCharges(PerfectBalance) && - (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || - (GetCooldownRemainingTime(PerfectBalance) <= 4) || - (HasEffect(Buffs.Brotherhood)) || - (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || - (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) - { - return PerfectBalance; - } - } - - if (ActionReady(Brotherhood)) - { - return Brotherhood; - } - - if (ActionReady(RiddleOfWind)) - { - return RiddleOfWind; - } - - if (Gauge.Chakra >= 5 - && HowlingFist.LevelChecked() - && HasBattleTarget()) - { - return OriginalHook(HowlingFist); - } - - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + if (IsEnabled(CustomComboPreset.MNK_AoE_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.MNK_AoE_SecondWind_Threshold && + ActionReady(All.SecondWind)) return All.SecondWind; - if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) + + if (PlayerHealthPercentageHp() <= Config.MNK_AoE_Bloodbath_Threshold && + ActionReady(All.Bloodbath)) return All.Bloodbath; } + } - if (inCombat) - { - if (HasEffect(Buffs.WindsRumination)) - { - return WindsReply; - } + if (IsEnabled(CustomComboPreset.MNK_AoEUseWindsReply) && + HasEffect(Buffs.WindsRumination)) + return WindsReply; - if (HasEffect(Buffs.FiresRumination)) - { - return FiresReply; - } + if (IsEnabled(CustomComboPreset.MNK_AoEUseFiresReply) && + HasEffect(Buffs.FiresRumination)) + return FiresReply; - // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) - { - return OriginalHook(MasterfulBlitz); - } + // Masterful Blitz + if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance)) + { + if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && + OriginalHook(MasterfulBlitz) != MasterfulBlitz) + return OriginalHook(MasterfulBlitz); - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) - { - if (nadiNONE || !lunarNadi) - { - if (pbStacks?.StackCount > 0) - { - return ShadowOfTheDestroyer.LevelChecked() ? ShadowOfTheDestroyer : Rockbreaker; - } - } - if (lunarNadi) + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) + { + if (nadiNone || !lunarNadi) + if (pbStacks?.StackCount > 0) + return ShadowOfTheDestroyer.LevelChecked() + ? ShadowOfTheDestroyer + : Rockbreaker; + + if (lunarNadi) + switch (pbStacks?.StackCount) { - switch (pbStacks?.StackCount) - { - case 3: - return OriginalHook(ArmOfTheDestroyer); - case 2: - return FourPointFury; - case 1: - return Rockbreaker; - } - } - } + case 3: + return OriginalHook(ArmOfTheDestroyer); - // Monk Rotation - if (HasEffect(Buffs.OpoOpoForm)) - { - return OriginalHook(ArmOfTheDestroyer); - } - - if (HasEffect(Buffs.RaptorForm)) - { - if (FourPointFury.LevelChecked()) - return FourPointFury; - - if (TwinSnakes.LevelChecked()) - return TwinSnakes; - } + case 2: + return FourPointFury; - if (HasEffect(Buffs.CoeurlForm) && Rockbreaker.LevelChecked()) - { - return Rockbreaker; - } + case 1: + return Rockbreaker; + } } } - return actionID; - } - } - #region Beast Chakras - internal class MNK_BeastChakra_OpoOpo : CustomCombo - { - protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_ST_BeastChakras; + // Monk Rotation + if (HasEffect(Buffs.OpoOpoForm)) + return OriginalHook(ArmOfTheDestroyer); - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) - { - if (IsEnabled(CustomComboPreset.MNK_BC_OPOOPO)) + if (HasEffect(Buffs.RaptorForm)) { - if (actionID is Bootshine or LeapingOpo) - { - if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance)) - { - if (Gauge.OpoOpoFury == 0) - { - if (LevelChecked(DragonKick)) - return DragonKick; - } - else - { - return OriginalHook(Bootshine); - } - } - } + if (LevelChecked(FourPointFury)) + return FourPointFury; + + if (LevelChecked(TwinSnakes)) + return TwinSnakes; } - return actionID; + if (HasEffect(Buffs.CoeurlForm) && LevelChecked(Rockbreaker)) + return Rockbreaker; } + + return actionID; } + } - internal class MNK_BeastChakra_Raptor : CustomCombo - { - protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_ST_BeastChakras; + internal class MNK_PerfectBalance : CustomCombo + { + protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_PerfectBalance; - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) - { - if (IsEnabled(CustomComboPreset.MNK_BC_RAPTOR)) - { - if (actionID is TrueStrike or RisingRaptor) - { - if (HasEffect(Buffs.RaptorForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance)) - { - if (Gauge.RaptorFury == 0) - { - if (LevelChecked(TwinSnakes)) - return TwinSnakes; - } - else - { - return OriginalHook(TrueStrike); - } - } - } - } + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + { + if (actionID == PerfectBalance) + if (OriginalHook(MasterfulBlitz) != MasterfulBlitz && MasterfulBlitz.LevelChecked()) + return OriginalHook(MasterfulBlitz); - return actionID; - } + return actionID; } + } - internal class MNK_BeastChakra_Coeurl : CustomCombo + internal class MNK_Riddle_Brotherhood : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_Riddle_Brotherhood; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_ST_BeastChakras; + return actionID is RiddleOfFire && ActionReady(Brotherhood) && IsOnCooldown(RiddleOfFire) + ? Brotherhood + : actionID; + } + } - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) - { - if (IsEnabled(CustomComboPreset.MNK_BC_COEURL)) - { - if (actionID is SnapPunch or PouncingCoeurl) - { - if (HasEffect(Buffs.CoeurlForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance)) - { - if (Gauge.CoeurlFury == 0) - { - if (LevelChecked(Demolish)) - return Demolish; - } - else - { - return OriginalHook(SnapPunch); - } - } - } - } + #region Beast Chakras - return actionID; - } - } - #endregion + internal class MNK_BeastChakra_OpoOpo : CustomCombo + { + protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_ST_BeastChakras; - internal class MNK_PerfectBalance : CustomCombo + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_PerfectBalance; + if (IsEnabled(CustomComboPreset.MNK_BC_OPOOPO) && + actionID is Bootshine or LeapingOpo && + (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance))) + return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) + ? DragonKick + : OriginalHook(Bootshine); + + return actionID; + } + } - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) - { - if (actionID == PerfectBalance) - { - if (OriginalHook(MasterfulBlitz) != MasterfulBlitz && MasterfulBlitz.LevelChecked()) - return OriginalHook(MasterfulBlitz); - } + internal class MNK_BeastChakra_Raptor : CustomCombo + { + protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_ST_BeastChakras; - return actionID; - } + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + { + if (IsEnabled(CustomComboPreset.MNK_BC_RAPTOR) && + actionID is TrueStrike or RisingRaptor && + (HasEffect(Buffs.RaptorForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance))) + return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) + ? TwinSnakes + : OriginalHook(TrueStrike); + + return actionID; } + } - internal class MNK_Riddle_Brotherhood : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_Riddle_Brotherhood; + internal class MNK_BeastChakra_Coeurl : CustomCombo + { + protected internal override CustomComboPreset Preset => CustomComboPreset.MNK_ST_BeastChakras; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - return actionID is RiddleOfFire && Brotherhood.LevelChecked() && IsOnCooldown(RiddleOfFire) && IsOffCooldown(Brotherhood) - ? Brotherhood - : actionID; - } + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + { + if (IsEnabled(CustomComboPreset.MNK_BC_COEURL) && + actionID is SnapPunch or PouncingCoeurl && + (HasEffect(Buffs.CoeurlForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance))) + return Gauge.CoeurlFury == 0 && LevelChecked(Demolish) + ? Demolish + : OriginalHook(SnapPunch); + + return actionID; } } + + #endregion } \ No newline at end of file diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 956d6bd4e..43affc224 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1580,6 +1580,15 @@ internal static void Draw(CustomComboPreset preset, bool enabled) UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_Bloodbath_Threshold, "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); } + if (preset == CustomComboPreset.MNK_AoE_ComboHeals) + { + UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_AoE_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); + + UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_AoE_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); + } + if (preset == CustomComboPreset.MNK_STUseOpener && enabled) { UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Double Lunar", "Uses Lunar/Lunar opener", 1); From 74ea6f6b50ff8df7d380160d3e9e03921ec869a5 Mon Sep 17 00:00:00 2001 From: Kage Date: Sun, 8 Sep 2024 19:02:27 +0200 Subject: [PATCH 093/208] revert MCH changes - different PR --- XIVSlothCombo/Combos/JobHelpers/MCH.cs | 58 ++--- XIVSlothCombo/Combos/PvE/MCH.cs | 340 ++++++++++++------------- 2 files changed, 179 insertions(+), 219 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MCH.cs b/XIVSlothCombo/Combos/JobHelpers/MCH.cs index 8d5528569..9304ba7a3 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MCH.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MCH.cs @@ -277,46 +277,28 @@ public static bool UseQueen(MCHGauge gauge) { int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - if (!ActionWatching.HasDoubleWeaved() && !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && - !JustUsed(OriginalHook(Heatblast)) && LevelChecked(OriginalHook(RookAutoturret)) && - !gauge.IsRobotActive && gauge.Battery >= 50) + if (!ActionWatching.HasDoubleWeaved() && CanWeave(OriginalHook(SplitShot)) && + !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && !JustUsed(OriginalHook(Heatblast)) && + LevelChecked(OriginalHook(RookAutoturret)) && !gauge.IsRobotActive && gauge.Battery >= 50 && + ((LevelChecked(FullMetalField) && !JustUsed(FullMetalField)) || !LevelChecked(FullMetalField))) { - if (LevelChecked(FullMetalField)) - { - //1min - if (BSUsed == 1 & gauge.Battery >= 90) - return true; - - //even mins - if (BSUsed >= 2 && gauge.Battery == 100) - return true; - - //odd mins 1st queen - if (BSUsed >= 2 && gauge.Battery == 50 && - gauge.LastSummonBatteryPower == 100) - return true; - - //odd mins 2nd queen - if ((BSUsed is 2 or 5 or 8) && gauge.Battery >= 60 && - gauge.LastSummonBatteryPower == 50) - return true; - - //odd mins 2nd queen - if ((BSUsed is 3 or 6 or 9) && gauge.Battery >= 70 && - gauge.LastSummonBatteryPower == 50) - return true; - - //odd mins 2nd queen - if ((BSUsed is 4 or 7 or 10) && gauge.Battery >= 80 && - gauge.LastSummonBatteryPower == 50) - return true; - } + //1min + if (BSUsed == 1 & gauge.Battery >= 90) + return true; - if (!LevelChecked(FullMetalField)) - { - if (gauge.Battery == 100) - return true; - } + //even mins + if (BSUsed >= 2 && gauge.Battery >= 100) + return true; + + //odd mins 1st queen + if (BSUsed >= 2 && gauge.Battery >= 50 && + GetCooldownRemainingTime(BarrelStabilizer) is >= 30 and <= 65) + return true; + + //odd mins 2nd queen + if (BSUsed >= 2 && gauge.Battery >= 60 && + GetCooldownRemainingTime(BarrelStabilizer) is >= 10 and <= 30) + return true; if (!LevelChecked(BarrelStabilizer)) return true; diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index ed69436e7..cc29a8ddd 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -1,6 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; -using System.Linq; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; @@ -109,13 +108,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool anchorCD = !LevelChecked(AirAnchor) || (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); bool sawCD = !LevelChecked(Chainsaw) || (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); if (actionID is SplitShot or HeatedSplitShot) { if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MCH_VariantCure) + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MCH_VariantCure) return Variant.VariantCure; if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && @@ -124,7 +122,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim CanWeave(actionID)) return Variant.VariantRampart; - // Opener + // Opener for MCH if (MCHOpener.DoFullOpener(ref actionID)) return actionID; @@ -132,95 +130,77 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (interruptReady) return All.HeadGraze; - // All weaves - if (CanWeave(ActionWatching.LastWeaponskill) && - !ActionWatching.HasDoubleWeaved()) - { - // Wildfire - if (JustUsed(Hypercharge) && ActionReady(Wildfire)) - return Wildfire; - - // BarrelStabilizer - if (!gauge.IsOverheated && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; - - // Hypercharge - if ((gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && - LevelChecked(Hypercharge) && !gauge.IsOverheated) - { - // Ensures Hypercharge is double weaved with WF - if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || - ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || - !LevelChecked(Wildfire)) - return Hypercharge; - - // Only Hypercharge when tools are on cooldown - if (drillCD && anchorCD && sawCD && - ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) - return Hypercharge; - } - - //Queen - if (MCHExtensions.UseQueen(gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) - return OriginalHook(RookAutoturret); + // Wildfire + if (JustUsed(Hypercharge) && CanWeave(actionID) && ActionReady(Wildfire)) + return Wildfire; - // Gauss Round and Ricochet during HC - if (JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } - - // Gauss Round and Ricochet outside HC - if (!gauge.IsOverheated && - (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || - JustUsed(Drill) || JustUsed(Excavator))) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } - - // Healing - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind) && !gauge.IsOverheated) - return All.SecondWind; + // BarrelStabilizer + if (!gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; + + if (CanWeave(actionID) && (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && + LevelChecked(Hypercharge) && !gauge.IsOverheated && !MCHExtensions.IsComboExpiring(6)) + { + //Protection & ensures Hyper charged is double weaved with WF during reopener + if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || + ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || + !LevelChecked(Wildfire)) + return Hypercharge; + + if (drillCD && anchorCD && sawCD && + ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) + return Hypercharge; } - // Full Metal Field + //Full Metal Field if (HasEffect(Buffs.FullMetalMachinist) && (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && LevelChecked(FullMetalField)) - return FullMetalField; + return OriginalHook(BarrelStabilizer); + + //Heatblast, Gauss, Rico + if (CanWeave(actionID) && JustUsed(OriginalHook(Heatblast)) && + (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - // Heatblast if (gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); - // Reassemble and Tools - if (ReassembledTools(ref actionID, gauge)) + //Queen + if (MCHExtensions.UseQueen(gauge) && + GetCooldownRemainingTime(Wildfire) > GCD) + return OriginalHook(RookAutoturret); + + //gauss and ricochet outside HC + if (CanWeave(actionID) && !gauge.IsOverheated && + (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || + JustUsed(Drill) || JustUsed(Excavator)) && + !ActionWatching.HasDoubleWeaved()) + { + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); + } + + if (ReassembledTools(ref actionID, gauge) && !gauge.IsOverheated) return actionID; - // Excavator - if (LevelChecked(Excavator) && - HasEffect(Buffs.ExcavatorReady) && - ((BSUsed is 1) || - ((BSUsed is 2 or 5 or 8) && gauge.Battery <= 40) || - ((BSUsed is 3 or 6 or 9) && gauge.Battery <= 50) || - ((BSUsed is 4 or 7 or 10) && gauge.Battery <= 60) || - (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) - return OriginalHook(Chainsaw); + // healing + if (CanWeave(actionID) && PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + return All.SecondWind; - // 1-2-3 Combo + //1-2-3 Combo if (comboTime > 0) { if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) @@ -242,9 +222,10 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) { bool battery = Svc.Gauges.Get().Battery >= 100; + // TOOLS!! Chainsaw Drill Air Anchor Excavator if (!gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && - !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) & - ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || + !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(actionID) || !InCombat()) & + ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery) || (LevelChecked(Chainsaw) && !LevelChecked(Excavator) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || (LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || (LevelChecked(Drill) && !LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) @@ -253,6 +234,14 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) return true; } + if (LevelChecked(OriginalHook(Chainsaw)) && + !battery && + HasEffect(Buffs.ExcavatorReady)) + { + actionID = OriginalHook(Chainsaw); + return true; + } + if (LevelChecked(Chainsaw) && !battery && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw))) @@ -295,8 +284,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool anchorCD = !LevelChecked(AirAnchor) || (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); bool sawCD = !LevelChecked(Chainsaw) || (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; - bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[0] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); if (actionID is SplitShot or HeatedSplitShot) { @@ -311,7 +298,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim CanWeave(actionID)) return Variant.VariantRampart; - // Opener + // Opener for MCH if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Opener)) { if (MCHOpener.DoFullOpener(ref actionID)) @@ -322,112 +309,92 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Interrupt) && interruptReady) return All.HeadGraze; - // All weaves - if (CanWeave(ActionWatching.LastWeaponskill) && - !ActionWatching.HasDoubleWeaved()) - { - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_QueenOverdrive) && - gauge.IsRobotActive && GetTargetHPPercent() <= Config.MCH_ST_QueenOverDrive && - ActionReady(OriginalHook(RookOverdrive))) - return OriginalHook(RookOverdrive); - - // Wildfire - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_WildFire) && - JustUsed(Hypercharge) && ActionReady(Wildfire) && - GetTargetHPPercent() >= Config.MCH_ST_WildfireHP) - return Wildfire; - - // BarrelStabilizer - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer) && - !gauge.IsOverheated && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; - - // Hypercharge - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && - (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && - LevelChecked(Hypercharge) && !gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) - { - // Ensures Hypercharge is double weaved with WF - if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || - ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || - !LevelChecked(Wildfire)) - return Hypercharge; - - // Only Hypercharge when tools are on cooldown - if (drillCD && anchorCD && sawCD && - ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) - return Hypercharge; - } - - // Queen - if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && - MCHExtensions.UseQueen(gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) - return OriginalHook(RookAutoturret); + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_QueenOverdrive) && + gauge.IsRobotActive && GetTargetHPPercent() <= Config.MCH_ST_QueenOverDrive && + CanWeave(actionID) && ActionReady(OriginalHook(RookOverdrive))) + return OriginalHook(RookOverdrive); - // Gauss Round and Ricochet during HC - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && - JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } - - // Gauss Round and Ricochet outside HC - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && - !gauge.IsOverheated && - (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || - JustUsed(Drill) || JustUsed(Excavator))) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } - - // Healing - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && - PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind) && !gauge.IsOverheated) - return All.SecondWind; + // Wildfire + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_WildFire) && + JustUsed(Hypercharge) && CanWeave(actionID) && ActionReady(Wildfire) && + GetTargetHPPercent() >= Config.MCH_ST_WildfireHP) + return Wildfire; + + // BarrelStabilizer + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer) && + !gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; + + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && + CanWeave(actionID) && (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + LevelChecked(Hypercharge) && !gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) + { + //Protection & ensures Hyper charged is double weaved with WF during reopener + if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || + ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || + !LevelChecked(Wildfire)) + return Hypercharge; + + if (drillCD && anchorCD && sawCD && + ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) + return Hypercharge; } - // Full Metal Field + //Full Metal Field if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer_FullMetalField) && HasEffect(Buffs.FullMetalMachinist) && (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && LevelChecked(FullMetalField)) - return FullMetalField; + return OriginalHook(BarrelStabilizer); + + //Heatblast, Gauss, Rico + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && + CanWeave(actionID) && JustUsed(OriginalHook(Heatblast)) && + (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - // Heatblast if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Heatblast) && gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) return OriginalHook(Heatblast); - // Reassemble and Tools - if (ReassembledTools(ref actionID, gauge)) + //Queen + if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && + MCHExtensions.UseQueen(gauge) && + GetCooldownRemainingTime(Wildfire) > GCD) + return OriginalHook(RookAutoturret); + + //gauss and ricochet outside HC + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && + CanWeave(actionID) && !gauge.IsOverheated && + (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || + JustUsed(Drill) || JustUsed(Excavator)) && + !ActionWatching.HasDoubleWeaved()) + { + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); + + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); + } + + if (ReassembledTools(ref actionID, gauge) && !gauge.IsOverheated) return actionID; - // Excavator - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && - reassembledExcavator && - LevelChecked(Excavator) && - HasEffect(Buffs.ExcavatorReady) && - ((BSUsed is 1) || - ((BSUsed is 2 or 5 or 8) && gauge.Battery <= 40) || - ((BSUsed is 3 or 6 or 9) && gauge.Battery <= 50) || - ((BSUsed is 4 or 7 or 10) && gauge.Battery <= 60) || - (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) - return OriginalHook(Chainsaw); + // healing + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && + CanWeave(actionID) && PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind)) + return All.SecondWind; - // 1-2-3 Combo + //1-2-3 Combo if (comboTime > 0) { if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) @@ -448,15 +415,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) { bool battery = Svc.Gauges.Get().Battery >= 100; + bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[0] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledChainsaw = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[1] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[1] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledAnchor = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[2] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[2] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); bool reassembledDrill = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[3] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[3] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); + // TOOLS!! Chainsaw Drill Air Anchor Excavator if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && - !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) && + !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(actionID) || !InCombat()) && GetRemainingCharges(Reassemble) > Config.MCH_ST_ReassemblePool && - ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || + ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery) || (Config.MCH_ST_Reassembled[1] && LevelChecked(Chainsaw) && (!LevelChecked(Excavator) || !Config.MCH_ST_Reassembled[0]) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || (Config.MCH_ST_Reassembled[2] && LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || (Config.MCH_ST_Reassembled[3] && LevelChecked(Drill) && (!LevelChecked(AirAnchor) || !Config.MCH_ST_Reassembled[2]) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) @@ -465,6 +434,16 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) return true; } + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && + reassembledExcavator && + LevelChecked(OriginalHook(Chainsaw)) && + !battery && + HasEffect(Buffs.ExcavatorReady)) + { + actionID = OriginalHook(Chainsaw); + return true; + } + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Chainsaw) && reassembledChainsaw && LevelChecked(Chainsaw) && @@ -488,8 +467,7 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Drill) && reassembledDrill && LevelChecked(Drill) && - !JustUsed(Drill) && - ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill)) && + !JustUsed(Drill) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill)) && GetCooldownRemainingTime(Wildfire) is >= 20 or <= 10) { actionID = Drill; @@ -527,7 +505,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Full Metal Field if (HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) - return FullMetalField; + return OriginalHook(BarrelStabilizer); // BarrelStabilizer if (!gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) @@ -617,7 +595,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Full Metal Field if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer_FullMetalField) && HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) - return FullMetalField; + return OriginalHook(BarrelStabilizer); // BarrelStabilizer if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer) && From 0deb0996368ed60aecf317db35634af8b64aabca Mon Sep 17 00:00:00 2001 From: Kage Date: Sun, 8 Sep 2024 19:11:41 +0200 Subject: [PATCH 094/208] auto refactor add static gauge --- XIVSlothCombo/Combos/JobHelpers/MCH.cs | 458 ++++--- XIVSlothCombo/Combos/PvE/MCH.cs | 1575 +++++++++++++----------- 2 files changed, 1066 insertions(+), 967 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MCH.cs b/XIVSlothCombo/Combos/JobHelpers/MCH.cs index 8d5528569..1fd7cea3d 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MCH.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MCH.cs @@ -1,329 +1,315 @@ -using Dalamud.Game.ClientState.JobGauge.Types; +using System.Linq; +using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; -using System.Linq; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Data; using static XIVSlothCombo.Combos.PvE.MCH; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.JobHelpers; + +internal abstract class MCHHelpers { - internal class MCHHelpers + internal class MCHOpenerLogic { - internal class MCHOpenerLogic + private OpenerState currentState = OpenerState.PrePull; + + public uint OpenerStep; + + public uint PrePullStep; + + private static uint OpenerLevel => 100; + + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState { - private static bool HasCooldowns() + get => currentState; + set { - if (GetRemainingCharges(CheckMate) < 3) - return false; + if (value != currentState) + { + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; - if (GetRemainingCharges(DoubleCheck) < 3) - return false; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - if (!ActionReady(Chainsaw)) - return false; + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - if (!ActionReady(Wildfire)) - return false; + currentState = value; + } + } + } - if (!ActionReady(BarrelStabilizer)) - return false; + private static bool HasCooldowns() + { + if (GetRemainingCharges(CheckMate) < 3) + return false; - if (!ActionReady(Excavator)) - return false; + if (GetRemainingCharges(DoubleCheck) < 3) + return false; - if (!ActionReady(FullMetalField)) - return false; + if (!ActionReady(Chainsaw)) + return false; - return true; - } + if (!ActionReady(Wildfire)) + return false; - private static uint OpenerLevel => 100; + if (!ActionReady(BarrelStabilizer)) + return false; - public uint PrePullStep = 0; + if (!ActionReady(Excavator)) + return false; - public uint OpenerStep = 0; + if (!ActionReady(FullMetalField)) + return false; - public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + return true; + } - private static bool CanOpener => HasCooldowns() && LevelChecked; + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) + return false; - private OpenerState currentState = OpenerState.PrePull; + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - public OpenerState CurrentState - { - get - { - return currentState; - } - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; - } - } - } + if (!HasCooldowns()) PrePullStep = 0; - private bool DoPrePullSteps(ref uint actionID) + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (!LevelChecked) - return false; - - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (HasEffect(Buffs.Reassembled) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = Reassemble; - if (!HasCooldowns()) - { - PrePullStep = 0; - } + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (HasEffect(Buffs.Reassembled) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = Reassemble; + return true; + } + PrePullStep = 0; - if (ActionWatching.CombatActions.Count > 2 && InCombat()) - CurrentState = OpenerState.FailedOpener; + return false; + } - return true; - } - PrePullStep = 0; + private bool DoOpener(ref uint actionID) + { + if (!LevelChecked) return false; - } - private bool DoOpener(ref uint actionID) + if (currentState == OpenerState.InOpener) { - if (!LevelChecked) - return false; + if (WasLastAction(AirAnchor) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = AirAnchor; - if (currentState == OpenerState.InOpener) - { - if (WasLastAction(AirAnchor) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = AirAnchor; + if (WasLastAction(CheckMate) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = CheckMate; - if (WasLastAction(CheckMate) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = CheckMate; + if (WasLastAction(DoubleCheck) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = DoubleCheck; - if (WasLastAction(DoubleCheck) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = DoubleCheck; + if (WasLastAction(Drill) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Drill; - if (WasLastAction(Drill) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Drill; + if (WasLastAction(BarrelStabilizer) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = BarrelStabilizer; - if (WasLastAction(BarrelStabilizer) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = BarrelStabilizer; + if (WasLastAction(Chainsaw) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = Chainsaw; - if (WasLastAction(Chainsaw) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = Chainsaw; + if (WasLastAction(Excavator) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = Excavator; - if (WasLastAction(Excavator) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = Excavator; + if (WasLastAction(AutomatonQueen) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = AutomatonQueen; - if (WasLastAction(AutomatonQueen) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = AutomatonQueen; + if (WasLastAction(Reassemble) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = Reassemble; - if (WasLastAction(Reassemble) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Reassemble; + if (WasLastAction(Drill) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = Drill; - if (WasLastAction(Drill) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = Drill; + if (WasLastAction(CheckMate) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = CheckMate; - if (WasLastAction(CheckMate) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = CheckMate; + if (WasLastAction(Wildfire) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = Wildfire; - if (WasLastAction(Wildfire) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = Wildfire; + if (WasLastAction(FullMetalField) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = FullMetalField; - if (WasLastAction(FullMetalField) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = FullMetalField; + if (WasLastAction(DoubleCheck) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = DoubleCheck; - if (WasLastAction(DoubleCheck) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = DoubleCheck; + if (WasLastAction(Hypercharge) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = Hypercharge; - if (WasLastAction(Hypercharge) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Hypercharge; + if (WasLastAction(BlazingShot) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = BlazingShot; - if (WasLastAction(BlazingShot) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = BlazingShot; + if (WasLastAction(CheckMate) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = CheckMate; - if (WasLastAction(CheckMate) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = CheckMate; + if (WasLastAction(BlazingShot) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = BlazingShot; - if (WasLastAction(BlazingShot) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = BlazingShot; + if (WasLastAction(DoubleCheck) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = DoubleCheck; - if (WasLastAction(DoubleCheck) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = DoubleCheck; + if (WasLastAction(BlazingShot) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = BlazingShot; - if (WasLastAction(BlazingShot) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = BlazingShot; + if (WasLastAction(CheckMate) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = CheckMate; - if (WasLastAction(CheckMate) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = CheckMate; + if (WasLastAction(BlazingShot) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = BlazingShot; - if (WasLastAction(BlazingShot) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = BlazingShot; + if (WasLastAction(DoubleCheck) && OpenerStep == 23) OpenerStep++; + else if (OpenerStep == 23) actionID = DoubleCheck; - if (WasLastAction(DoubleCheck) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = DoubleCheck; + if (WasLastAction(BlazingShot) && OpenerStep == 24) OpenerStep++; + else if (OpenerStep == 24) actionID = BlazingShot; - if (WasLastAction(BlazingShot) && OpenerStep == 24) OpenerStep++; - else if (OpenerStep == 24) actionID = BlazingShot; + if (WasLastAction(CheckMate) && OpenerStep == 25) OpenerStep++; + else if (OpenerStep == 25) actionID = CheckMate; - if (WasLastAction(CheckMate) && OpenerStep == 25) OpenerStep++; - else if (OpenerStep == 25) actionID = CheckMate; + if (WasLastAction(Drill) && OpenerStep == 26) OpenerStep++; + else if (OpenerStep == 26) actionID = Drill; - if (WasLastAction(Drill) && OpenerStep == 26) OpenerStep++; - else if (OpenerStep == 26) actionID = Drill; + if (WasLastAction(DoubleCheck) && OpenerStep == 27) OpenerStep++; + else if (OpenerStep == 27) actionID = DoubleCheck; - if (WasLastAction(DoubleCheck) && OpenerStep == 27) OpenerStep++; - else if (OpenerStep == 27) actionID = DoubleCheck; + if (WasLastAction(CheckMate) && OpenerStep == 28) OpenerStep++; + else if (OpenerStep == 28) actionID = CheckMate; - if (WasLastAction(CheckMate) && OpenerStep == 28) OpenerStep++; - else if (OpenerStep == 28) actionID = CheckMate; + if (WasLastAction(HeatedSplitShot) && OpenerStep == 29) OpenerStep++; + else if (OpenerStep == 29) actionID = HeatedSplitShot; - if (WasLastAction(HeatedSplitShot) && OpenerStep == 29) OpenerStep++; - else if (OpenerStep == 29) actionID = HeatedSplitShot; + if (WasLastAction(DoubleCheck) && OpenerStep == 30) OpenerStep++; + else if (OpenerStep == 30) actionID = DoubleCheck; - if (WasLastAction(DoubleCheck) && OpenerStep == 30) OpenerStep++; - else if (OpenerStep == 30) actionID = DoubleCheck; + if (WasLastAction(HeatedSlugShot) && OpenerStep == 31) OpenerStep++; + else if (OpenerStep == 31) actionID = HeatedSlugShot; - if (WasLastAction(HeatedSlugShot) && OpenerStep == 31) OpenerStep++; - else if (OpenerStep == 31) actionID = HeatedSlugShot; + if (WasLastAction(HeatedCleanShot) && OpenerStep == 32) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 32) actionID = HeatedCleanShot; - if (WasLastAction(HeatedCleanShot) && OpenerStep == 32) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 32) actionID = HeatedCleanShot; + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (((actionID == CheckMate && GetRemainingCharges(CheckMate) < 3) || + (actionID == Chainsaw && IsOnCooldown(Chainsaw)) || + (actionID == Wildfire && IsOnCooldown(Wildfire)) || + (actionID == BarrelStabilizer && IsOnCooldown(BarrelStabilizer)) || + (actionID == BarrelStabilizer && IsOnCooldown(Excavator)) || + (actionID == BarrelStabilizer && IsOnCooldown(FullMetalField)) || + (actionID == DoubleCheck && GetRemainingCharges(DoubleCheck) < 3)) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + CurrentState = OpenerState.FailedOpener; - if (((actionID == CheckMate && GetRemainingCharges(CheckMate) < 3) || - (actionID == Chainsaw && IsOnCooldown(Chainsaw)) || - (actionID == Wildfire && IsOnCooldown(Wildfire)) || - (actionID == BarrelStabilizer && IsOnCooldown(BarrelStabilizer)) || - (actionID == BarrelStabilizer && IsOnCooldown(Excavator)) || - (actionID == BarrelStabilizer && IsOnCooldown(FullMetalField)) || - (actionID == DoubleCheck && GetRemainingCharges(DoubleCheck) < 3)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - return true; + return false; } - return false; - } - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; + return true; } - public bool DoFullOpener(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; + return false; + } - if (CurrentState == OpenerState.InOpener) - { - if (DoOpener(ref actionID)) - return true; - } + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } - if (!InCombat()) - { - ResetOpener(); - CurrentState = OpenerState.PrePull; - } + public bool DoFullOpener(ref uint actionID) + { + if (!LevelChecked) return false; + + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; + + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID)) + return true; + + if (!InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; } + + return false; } + } - internal static class MCHExtensions + internal static class MCHExtensions + { + public static unsafe bool IsComboExpiring(float Times) { - public unsafe static bool IsComboExpiring(float Times) - { - float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal * Times; + float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal * Times; - if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) - return true; + if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) + return true; - else return false; - } + return false; + } - public static bool UseQueen(MCHGauge gauge) - { - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); + public static bool UseQueen(MCHGauge gauge) + { + int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - if (!ActionWatching.HasDoubleWeaved() && !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && - !JustUsed(OriginalHook(Heatblast)) && LevelChecked(OriginalHook(RookAutoturret)) && - !gauge.IsRobotActive && gauge.Battery >= 50) + if (!ActionWatching.HasDoubleWeaved() && !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && + !JustUsed(OriginalHook(Heatblast)) && LevelChecked(OriginalHook(RookAutoturret)) && + !gauge.IsRobotActive && gauge.Battery >= 50) + { + if (LevelChecked(FullMetalField)) { - if (LevelChecked(FullMetalField)) - { - //1min - if (BSUsed == 1 & gauge.Battery >= 90) - return true; - - //even mins - if (BSUsed >= 2 && gauge.Battery == 100) - return true; - - //odd mins 1st queen - if (BSUsed >= 2 && gauge.Battery == 50 && - gauge.LastSummonBatteryPower == 100) - return true; - - //odd mins 2nd queen - if ((BSUsed is 2 or 5 or 8) && gauge.Battery >= 60 && - gauge.LastSummonBatteryPower == 50) - return true; - - //odd mins 2nd queen - if ((BSUsed is 3 or 6 or 9) && gauge.Battery >= 70 && - gauge.LastSummonBatteryPower == 50) - return true; - - //odd mins 2nd queen - if ((BSUsed is 4 or 7 or 10) && gauge.Battery >= 80 && - gauge.LastSummonBatteryPower == 50) - return true; - } + //1min + if ((BSUsed == 1) & (gauge.Battery >= 90)) + return true; - if (!LevelChecked(FullMetalField)) - { - if (gauge.Battery == 100) - return true; - } + //even mins + if (BSUsed >= 2 && gauge.Battery == 100) + return true; + + //odd mins 1st queen + if (BSUsed >= 2 && gauge is { Battery: 50, LastSummonBatteryPower: 100 }) + return true; + + //odd mins 2nd queen + if (BSUsed is 2 or 5 or 8 && gauge is { Battery: >= 60, LastSummonBatteryPower: 50 }) + return true; - if (!LevelChecked(BarrelStabilizer)) + //odd mins 2nd queen + if (BSUsed is 3 or 6 or 9 && gauge is { Battery: >= 70, LastSummonBatteryPower: 50 }) + return true; + + //odd mins 2nd queen + if (BSUsed is 4 or 7 or 10 && gauge is { Battery: >= 80, LastSummonBatteryPower: 50 }) return true; } - return false; + if (!LevelChecked(FullMetalField)) + if (gauge.Battery == 100) + return true; + + if (!LevelChecked(BarrelStabilizer)) + return true; } + + return false; } } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index ed69436e7..6582ab9e7 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -1,559 +1,431 @@ +using System.Linq; using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; -using System.Linq; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; using static XIVSlothCombo.Combos.JobHelpers.MCHHelpers; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE +namespace XIVSlothCombo.Combos.PvE; + +internal class MCH { - internal class MCH + public const byte JobID = 31; + + public const uint + CleanShot = 2873, + HeatedCleanShot = 7413, + SplitShot = 2866, + HeatedSplitShot = 7411, + SlugShot = 2868, + HeatedSlugShot = 7412, + GaussRound = 2874, + Ricochet = 2890, + Reassemble = 2876, + Drill = 16498, + HotShot = 2872, + AirAnchor = 16500, + Hypercharge = 17209, + Heatblast = 7410, + SpreadShot = 2870, + Scattergun = 25786, + AutoCrossbow = 16497, + RookAutoturret = 2864, + RookOverdrive = 7415, + AutomatonQueen = 16501, + QueenOverdrive = 16502, + Tactician = 16889, + Chainsaw = 25788, + BioBlaster = 16499, + BarrelStabilizer = 7414, + Wildfire = 2878, + Dismantle = 2887, + Flamethrower = 7418, + BlazingShot = 36978, + DoubleCheck = 36979, + CheckMate = 36980, + Excavator = 36981, + FullMetalField = 36982; + + protected static MCHGauge? Gauge = GetJobGauge(); + + public static class Buffs { - public const byte JobID = 31; - - public const uint - CleanShot = 2873, - HeatedCleanShot = 7413, - SplitShot = 2866, - HeatedSplitShot = 7411, - SlugShot = 2868, - HeatedSlugShot = 7412, - GaussRound = 2874, - Ricochet = 2890, - Reassemble = 2876, - Drill = 16498, - HotShot = 2872, - AirAnchor = 16500, - Hypercharge = 17209, - Heatblast = 7410, - SpreadShot = 2870, - Scattergun = 25786, - AutoCrossbow = 16497, - RookAutoturret = 2864, - RookOverdrive = 7415, - AutomatonQueen = 16501, - QueenOverdrive = 16502, - Tactician = 16889, - Chainsaw = 25788, - BioBlaster = 16499, - BarrelStabilizer = 7414, - Wildfire = 2878, - Dismantle = 2887, - Flamethrower = 7418, - BlazingShot = 36978, - DoubleCheck = 36979, - CheckMate = 36980, - Excavator = 36981, - FullMetalField = 36982; - - public static class Buffs - { - public const ushort - Reassembled = 851, - Tactician = 1951, - Wildfire = 1946, - Overheated = 2688, - Flamethrower = 1205, - Hypercharged = 3864, - ExcavatorReady = 3865, - FullMetalMachinist = 3866; - } + public const ushort + Reassembled = 851, + Tactician = 1951, + Wildfire = 1946, + Overheated = 2688, + Flamethrower = 1205, + Hypercharged = 3864, + ExcavatorReady = 3865, + FullMetalMachinist = 3866; + } - public static class Debuffs - { - public const ushort - Dismantled = 2887, - Bioblaster = 1866; - } + public static class Debuffs + { + public const ushort + Dismantled = 2887, + Bioblaster = 1866; + } - public static class Traits - { - public const ushort - EnhancedMultiWeapon = 605; - } + public static class Traits + { + public const ushort + EnhancedMultiWeapon = 605; + } - public static class Config - { - public static UserInt - MCH_ST_SecondWindThreshold = new("MCH_ST_SecondWindThreshold", 25), - MCH_AoE_SecondWindThreshold = new("MCH_AoE_SecondWindThreshold", 25), - MCH_VariantCure = new("MCH_VariantCure"), - MCH_AoE_TurretUsage = new("MCH_AoE_TurretUsage"), - MCH_ST_ReassemblePool = new("MCH_ST_ReassemblePool", 0), - MCH_AoE_ReassemblePool = new("MCH_AoE_ReassemblePool", 0), - MCH_ST_WildfireHP = new("MCH_ST_WildfireHP", 1), - MCH_ST_HyperchargeHP = new("MCH_ST_HyperchargeHP", 1), - MCH_ST_QueenOverDrive = new("MCH_ST_QueenOverDrive"); - public static UserBoolArray - MCH_ST_Reassembled = new("MCH_ST_Reassembled"), - MCH_AoE_Reassembled = new("MCH_AoE_Reassembled"); - public static UserBool - MCH_AoE_Hypercharge = new("MCH_AoE_Hypercharge"); - } + public static class Config + { + public static UserInt + MCH_ST_SecondWindThreshold = new("MCH_ST_SecondWindThreshold", 25), + MCH_AoE_SecondWindThreshold = new("MCH_AoE_SecondWindThreshold", 25), + MCH_VariantCure = new("MCH_VariantCure"), + MCH_AoE_TurretUsage = new("MCH_AoE_TurretUsage"), + MCH_ST_ReassemblePool = new("MCH_ST_ReassemblePool", 0), + MCH_AoE_ReassemblePool = new("MCH_AoE_ReassemblePool", 0), + MCH_ST_WildfireHP = new("MCH_ST_WildfireHP", 1), + MCH_ST_HyperchargeHP = new("MCH_ST_HyperchargeHP", 1), + MCH_ST_QueenOverDrive = new("MCH_ST_QueenOverDrive"); + + public static UserBoolArray + MCH_ST_Reassembled = new("MCH_ST_Reassembled"), + MCH_AoE_Reassembled = new("MCH_AoE_Reassembled"); + + public static UserBool + MCH_AoE_Hypercharge = new("MCH_AoE_Hypercharge"); + } + + internal class MCH_ST_SimpleMode : CustomCombo + { + internal static MCHOpenerLogic MCHOpener = new(); - internal class MCH_ST_SimpleMode : CustomCombo + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_ST_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_ST_SimpleMode; - internal static MCHOpenerLogic MCHOpener = new(); + bool interruptReady = ActionReady(All.HeadGraze) && CanInterruptEnemy() && CanDelayedWeave(actionID); + float heatblastRC = GetCooldown(Heatblast).CooldownTotal; + + bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && + GetCooldownRemainingTime(Drill) > heatblastRC * 6) || + (TraitLevelChecked(Traits.EnhancedMultiWeapon) && + GetRemainingCharges(Drill) < GetMaxCharges(Drill) && + GetCooldownRemainingTime(Drill) > heatblastRC * 6); + + bool anchorCD = !LevelChecked(AirAnchor) || + (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); + + bool sawCD = !LevelChecked(Chainsaw) || + (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); + float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; + int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is SplitShot or HeatedSplitShot) { - MCHGauge? gauge = GetJobGauge(); - bool interruptReady = ActionReady(All.HeadGraze) && CanInterruptEnemy() && CanDelayedWeave(actionID); - float heatblastRC = GetCooldown(Heatblast).CooldownTotal; - bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && GetCooldownRemainingTime(Drill) > heatblastRC * 6) || - (TraitLevelChecked(Traits.EnhancedMultiWeapon) && GetRemainingCharges(Drill) < GetMaxCharges(Drill) && GetCooldownRemainingTime(Drill) > heatblastRC * 6); - bool anchorCD = !LevelChecked(AirAnchor) || (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); - bool sawCD = !LevelChecked(Chainsaw) || (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); - float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - - if (actionID is SplitShot or HeatedSplitShot) + if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MCH_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + // Opener + if (MCHOpener.DoFullOpener(ref actionID)) + return actionID; + + // Interrupt + if (interruptReady) + return All.HeadGraze; + + // All weaves + if (CanWeave(ActionWatching.LastWeaponskill) && + !ActionWatching.HasDoubleWeaved()) { - if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MCH_VariantCure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; - - // Opener - if (MCHOpener.DoFullOpener(ref actionID)) - return actionID; + // Wildfire + if (JustUsed(Hypercharge) && ActionReady(Wildfire)) + return Wildfire; - // Interrupt - if (interruptReady) - return All.HeadGraze; + // BarrelStabilizer + if (!Gauge.IsOverheated && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; - // All weaves - if (CanWeave(ActionWatching.LastWeaponskill) && - !ActionWatching.HasDoubleWeaved()) + // Hypercharge + if ((Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + LevelChecked(Hypercharge) && !Gauge.IsOverheated) { - // Wildfire - if (JustUsed(Hypercharge) && ActionReady(Wildfire)) - return Wildfire; - - // BarrelStabilizer - if (!gauge.IsOverheated && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; - - // Hypercharge - if ((gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && - LevelChecked(Hypercharge) && !gauge.IsOverheated) - { - // Ensures Hypercharge is double weaved with WF - if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || - ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || - !LevelChecked(Wildfire)) - return Hypercharge; - - // Only Hypercharge when tools are on cooldown - if (drillCD && anchorCD && sawCD && - ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) - return Hypercharge; - } - - //Queen - if (MCHExtensions.UseQueen(gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) - return OriginalHook(RookAutoturret); - - // Gauss Round and Ricochet during HC - if (JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } - - // Gauss Round and Ricochet outside HC - if (!gauge.IsOverheated && - (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || - JustUsed(Drill) || JustUsed(Excavator))) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } - - // Healing - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind) && !gauge.IsOverheated) - return All.SecondWind; + // Ensures Hypercharge is double weaved with WF + if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && + (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || + (!LevelChecked(FullMetalField) && ActionReady(Wildfire)) || + !LevelChecked(Wildfire)) + return Hypercharge; + + // Only Hypercharge when tools are on cooldown + if (drillCD && anchorCD && sawCD && + ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || + !LevelChecked(Wildfire))) + return Hypercharge; } - // Full Metal Field - if (HasEffect(Buffs.FullMetalMachinist) && - (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || - GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && - LevelChecked(FullMetalField)) - return FullMetalField; + //Queen + if (MCHExtensions.UseQueen(Gauge) && + GetCooldownRemainingTime(Wildfire) > GCD) + return OriginalHook(RookAutoturret); - // Heatblast - if (gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) - return OriginalHook(Heatblast); + // Gauss Round and Ricochet during HC + if (JustUsed(OriginalHook(Heatblast)) && + ActionWatching.GetAttackType(ActionWatching.LastAction) != + ActionWatching.ActionAttackType.Ability) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= + GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); - // Reassemble and Tools - if (ReassembledTools(ref actionID, gauge)) - return actionID; + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - // Excavator - if (LevelChecked(Excavator) && - HasEffect(Buffs.ExcavatorReady) && - ((BSUsed is 1) || - ((BSUsed is 2 or 5 or 8) && gauge.Battery <= 40) || - ((BSUsed is 3 or 6 or 9) && gauge.Battery <= 50) || - ((BSUsed is 4 or 7 or 10) && gauge.Battery <= 60) || - (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) - return OriginalHook(Chainsaw); - - // 1-2-3 Combo - if (comboTime > 0) + // Gauss Round and Ricochet outside HC + if (!Gauge.IsOverheated && + (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || + JustUsed(Drill) || JustUsed(Excavator))) { - if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) - return OriginalHook(SlugShot); - - if (lastComboMove == OriginalHook(SlugShot) && - !LevelChecked(Drill) && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble)) - return Reassemble; + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); - if (lastComboMove is SlugShot && LevelChecked(OriginalHook(CleanShot))) - return OriginalHook(CleanShot); + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); } - return OriginalHook(SplitShot); - } - return actionID; - } - private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) - { - bool battery = Svc.Gauges.Get().Battery >= 100; - - if (!gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && - !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) & - ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || - (LevelChecked(Chainsaw) && !LevelChecked(Excavator) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || - (LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || - (LevelChecked(Drill) && !LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) - { - actionID = Reassemble; - return true; + // Healing + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind) && !Gauge.IsOverheated) + return All.SecondWind; } - if (LevelChecked(Chainsaw) && - !battery && - ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw))) + // Full Metal Field + if (HasEffect(Buffs.FullMetalMachinist) && + (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || + GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && + LevelChecked(FullMetalField)) + return FullMetalField; + + // Heatblast + if (Gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) + return OriginalHook(Heatblast); + + // Reassemble and Tools + if (ReassembledTools(ref actionID, Gauge)) + return actionID; + + // Excavator + if (LevelChecked(Excavator) && + HasEffect(Buffs.ExcavatorReady) && + (BSUsed is 1 || + (BSUsed is 2 or 5 or 8 && Gauge.Battery <= 40) || + (BSUsed is 3 or 6 or 9 && Gauge.Battery <= 50) || + (BSUsed is 4 or 7 or 10 && Gauge.Battery <= 60) || + GetBuffRemainingTime(Buffs.ExcavatorReady) < 6)) + return OriginalHook(Chainsaw); + + // 1-2-3 Combo + if (comboTime > 0) { - actionID = Chainsaw; - return true; - } + if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) + return OriginalHook(SlugShot); - if (LevelChecked(OriginalHook(AirAnchor)) && - !battery && - ((GetCooldownRemainingTime(OriginalHook(AirAnchor)) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(OriginalHook(AirAnchor)))) - { - actionID = OriginalHook(AirAnchor); - return true; - } + if (lastComboMove == OriginalHook(SlugShot) && + !LevelChecked(Drill) && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble)) + return Reassemble; - if (LevelChecked(Drill) && - !JustUsed(Drill) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill)) && - GetCooldownRemainingTime(Wildfire) is >= 20 or <= 10) - { - actionID = Drill; - return true; + if (lastComboMove is SlugShot && LevelChecked(OriginalHook(CleanShot))) + return OriginalHook(CleanShot); } - return false; + + return OriginalHook(SplitShot); } + + return actionID; } - internal class MCH_ST_AdvancedMode : CustomCombo + private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_ST_AdvancedMode; - internal static MCHOpenerLogic MCHOpener = new(); - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + bool battery = Svc.Gauges.Get().Battery >= 100; + + if (!gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && + !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && + (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) & + ((LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && + GetCooldownRemainingTime(Wildfire) > 3) || + (LevelChecked(Chainsaw) && !LevelChecked(Excavator) && + (GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Chainsaw)) && !battery) || + (LevelChecked(AirAnchor) && + (GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(AirAnchor)) && !battery) || + (LevelChecked(Drill) && !LevelChecked(AirAnchor) && + (GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Drill))))) { - MCHGauge? gauge = GetJobGauge(); - bool interruptReady = ActionReady(All.HeadGraze) && CanInterruptEnemy() && CanDelayedWeave(actionID); - float heatblastRC = GetCooldown(Heatblast).CooldownTotal; - bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && GetCooldownRemainingTime(Drill) > heatblastRC * 6) || - (TraitLevelChecked(Traits.EnhancedMultiWeapon) && GetRemainingCharges(Drill) < GetMaxCharges(Drill) && GetCooldownRemainingTime(Drill) > heatblastRC * 6); - bool anchorCD = !LevelChecked(AirAnchor) || (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); - bool sawCD = !LevelChecked(Chainsaw) || (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); - float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; - bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[0] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - - if (actionID is SplitShot or HeatedSplitShot) - { - if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MCH_VariantCure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; - - // Opener - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Opener)) - { - if (MCHOpener.DoFullOpener(ref actionID)) - return actionID; - } - - // Interrupt - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Interrupt) && interruptReady) - return All.HeadGraze; - - // All weaves - if (CanWeave(ActionWatching.LastWeaponskill) && - !ActionWatching.HasDoubleWeaved()) - { - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_QueenOverdrive) && - gauge.IsRobotActive && GetTargetHPPercent() <= Config.MCH_ST_QueenOverDrive && - ActionReady(OriginalHook(RookOverdrive))) - return OriginalHook(RookOverdrive); - - // Wildfire - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_WildFire) && - JustUsed(Hypercharge) && ActionReady(Wildfire) && - GetTargetHPPercent() >= Config.MCH_ST_WildfireHP) - return Wildfire; - - // BarrelStabilizer - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer) && - !gauge.IsOverheated && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; - - // Hypercharge - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && - (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && - LevelChecked(Hypercharge) && !gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) - { - // Ensures Hypercharge is double weaved with WF - if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || - ((!LevelChecked(FullMetalField)) && ActionReady(Wildfire)) || - !LevelChecked(Wildfire)) - return Hypercharge; - - // Only Hypercharge when tools are on cooldown - if (drillCD && anchorCD && sawCD && - ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || !LevelChecked(Wildfire))) - return Hypercharge; - } - - // Queen - if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && - MCHExtensions.UseQueen(gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) - return OriginalHook(RookAutoturret); - - // Gauss Round and Ricochet during HC - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && - JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } - - // Gauss Round and Ricochet outside HC - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && - !gauge.IsOverheated && - (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || - JustUsed(Drill) || JustUsed(Excavator))) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); - - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } - - // Healing - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && - PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && ActionReady(All.SecondWind) && !gauge.IsOverheated) - return All.SecondWind; - } - - // Full Metal Field - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer_FullMetalField) && - HasEffect(Buffs.FullMetalMachinist) && - (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || - GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && - LevelChecked(FullMetalField)) - return FullMetalField; - - // Heatblast - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Heatblast) && - gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) - return OriginalHook(Heatblast); - - // Reassemble and Tools - if (ReassembledTools(ref actionID, gauge)) - return actionID; + actionID = Reassemble; - // Excavator - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && - reassembledExcavator && - LevelChecked(Excavator) && - HasEffect(Buffs.ExcavatorReady) && - ((BSUsed is 1) || - ((BSUsed is 2 or 5 or 8) && gauge.Battery <= 40) || - ((BSUsed is 3 or 6 or 9) && gauge.Battery <= 50) || - ((BSUsed is 4 or 7 or 10) && gauge.Battery <= 60) || - (GetBuffRemainingTime(Buffs.ExcavatorReady) < 6))) - return OriginalHook(Chainsaw); - - // 1-2-3 Combo - if (comboTime > 0) - { - if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) - return OriginalHook(SlugShot); + return true; + } - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[4] && lastComboMove == OriginalHook(SlugShot) && - !LevelChecked(Drill) && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble)) - return Reassemble; + if (LevelChecked(Chainsaw) && + !battery && + (GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Chainsaw))) + { + actionID = Chainsaw; - if (lastComboMove is SlugShot && LevelChecked(OriginalHook(CleanShot))) - return OriginalHook(CleanShot); - } - return OriginalHook(SplitShot); - } - return actionID; + return true; } - private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) + if (LevelChecked(OriginalHook(AirAnchor)) && + !battery && + (GetCooldownRemainingTime(OriginalHook(AirAnchor)) <= + GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || ActionReady(OriginalHook(AirAnchor)))) { - bool battery = Svc.Gauges.Get().Battery >= 100; - bool reassembledChainsaw = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[1] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[1] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); - bool reassembledAnchor = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[2] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[2] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); - bool reassembledDrill = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[3] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[3] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble)); - - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && - !gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && - !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) && - GetRemainingCharges(Reassemble) > Config.MCH_ST_ReassemblePool && - ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || - (Config.MCH_ST_Reassembled[1] && LevelChecked(Chainsaw) && (!LevelChecked(Excavator) || !Config.MCH_ST_Reassembled[0]) && ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw)) && !battery) || - (Config.MCH_ST_Reassembled[2] && LevelChecked(AirAnchor) && ((GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(AirAnchor)) && !battery) || - (Config.MCH_ST_Reassembled[3] && LevelChecked(Drill) && (!LevelChecked(AirAnchor) || !Config.MCH_ST_Reassembled[2]) && ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill))))) - { - actionID = Reassemble; - return true; - } + actionID = OriginalHook(AirAnchor); - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Chainsaw) && - reassembledChainsaw && - LevelChecked(Chainsaw) && - !battery && - ((GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Chainsaw))) - { - actionID = Chainsaw; - return true; - } + return true; + } - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_AirAnchor) && - reassembledAnchor && - LevelChecked(OriginalHook(AirAnchor)) && - !battery && - ((GetCooldownRemainingTime(OriginalHook(AirAnchor)) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(OriginalHook(AirAnchor)))) - { - actionID = OriginalHook(AirAnchor); - return true; - } + if (LevelChecked(Drill) && + !JustUsed(Drill) && + (GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Drill)) && + GetCooldownRemainingTime(Wildfire) is >= 20 or <= 10) + { + actionID = Drill; - if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Drill) && - reassembledDrill && - LevelChecked(Drill) && - !JustUsed(Drill) && - ((GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25) || ActionReady(Drill)) && - GetCooldownRemainingTime(Wildfire) is >= 20 or <= 10) - { - actionID = Drill; - return true; - } - return false; + return true; } - } - - internal class MCH_AoE_SimpleMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_AoE_SimpleMode; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - MCHGauge? gauge = GetJobGauge(); - float GCD = GetCooldown(OriginalHook(SpreadShot)).CooldownTotal; + return false; + } + } - if (actionID is SpreadShot or Scattergun) - { - if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MCH_VariantCure) - return Variant.VariantCure; + internal class MCH_ST_AdvancedMode : CustomCombo + { + internal static MCHOpenerLogic MCHOpener = new(); - if (HasEffect(Buffs.Flamethrower) || JustUsed(Flamethrower)) - return OriginalHook(11); + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_ST_AdvancedMode; - if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + bool interruptReady = ActionReady(All.HeadGraze) && CanInterruptEnemy() && CanDelayedWeave(actionID); + float heatblastRC = GetCooldown(Heatblast).CooldownTotal; + + bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && + GetCooldownRemainingTime(Drill) > heatblastRC * 6) || + (TraitLevelChecked(Traits.EnhancedMultiWeapon) && + GetRemainingCharges(Drill) < GetMaxCharges(Drill) && + GetCooldownRemainingTime(Drill) > heatblastRC * 6); + + bool anchorCD = !LevelChecked(AirAnchor) || + (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); + + bool sawCD = !LevelChecked(Chainsaw) || + (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); + float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; + + bool reassembledExcavator = + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && + (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[0] && + !HasEffect(Buffs.Reassembled)) || + (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || + !IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble); + int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); + + if (actionID is SplitShot or HeatedSplitShot) + { + if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MCH_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + // Opener + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Opener)) + if (MCHOpener.DoFullOpener(ref actionID)) + return actionID; + // Interrupt + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Interrupt) && interruptReady) + return All.HeadGraze; - //Full Metal Field - if (HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) - return FullMetalField; + // All weaves + if (CanWeave(ActionWatching.LastWeaponskill) && + !ActionWatching.HasDoubleWeaved()) + { + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_QueenOverdrive) && + Gauge.IsRobotActive && GetTargetHPPercent() <= Config.MCH_ST_QueenOverDrive && + ActionReady(OriginalHook(RookOverdrive))) + return OriginalHook(RookOverdrive); + + // Wildfire + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_WildFire) && + JustUsed(Hypercharge) && ActionReady(Wildfire) && + GetTargetHPPercent() >= Config.MCH_ST_WildfireHP) + return Wildfire; - // BarrelStabilizer - if (!gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) + // BarrelStabilizer + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer) && + !Gauge.IsOverheated && ActionReady(BarrelStabilizer)) return BarrelStabilizer; - if (ActionReady(BioBlaster) && !TargetHasEffect(Debuffs.Bioblaster)) - return OriginalHook(BioBlaster); - - if (ActionReady(Flamethrower) && !IsMoving) - return OriginalHook(Flamethrower); + // Hypercharge + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && + (Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + LevelChecked(Hypercharge) && !Gauge.IsOverheated && + GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) + { + // Ensures Hypercharge is double weaved with WF + if ((LevelChecked(FullMetalField) && JustUsed(FullMetalField) && + (GetCooldownRemainingTime(Wildfire) < GCD || ActionReady(Wildfire))) || + (!LevelChecked(FullMetalField) && ActionReady(Wildfire)) || + !LevelChecked(Wildfire)) + return Hypercharge; + + // Only Hypercharge when tools are on cooldown + if (drillCD && anchorCD && sawCD && + ((GetCooldownRemainingTime(Wildfire) > 40 && LevelChecked(Wildfire)) || + !LevelChecked(Wildfire))) + return Hypercharge; + } - if (!gauge.IsOverheated && gauge.Battery == 100) + // Queen + if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && + MCHExtensions.UseQueen(Gauge) && + GetCooldownRemainingTime(Wildfire) > GCD) return OriginalHook(RookAutoturret); - // Hypercharge - if ((gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && LevelChecked(Hypercharge) && LevelChecked(AutoCrossbow) && !gauge.IsOverheated && - ((BioBlaster.LevelChecked() && GetCooldownRemainingTime(BioBlaster) > 10) || !BioBlaster.LevelChecked()) && - ((Flamethrower.LevelChecked() && GetCooldownRemainingTime(Flamethrower) > 10) || !Flamethrower.LevelChecked())) - return Hypercharge; - - //AutoCrossbow, Gauss, Rico - if (CanWeave(actionID) && JustUsed(OriginalHook(AutoCrossbow)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) + // Gauss Round and Ricochet during HC + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && + JustUsed(OriginalHook(Heatblast)) && + ActionWatching.GetAttackType(ActionWatching.LastAction) != + ActionWatching.ActionAttackType.Ability) { if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + GetRemainingCharges(OriginalHook(GaussRound)) >= + GetRemainingCharges(OriginalHook(Ricochet))) return OriginalHook(GaussRound); if (ActionReady(OriginalHook(Ricochet)) && @@ -561,327 +433,568 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(Ricochet); } - if (gauge.IsOverheated && AutoCrossbow.LevelChecked()) - return OriginalHook(AutoCrossbow); + // Gauss Round and Ricochet outside HC + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_GaussRicochet) && + !Gauge.IsOverheated && + (JustUsed(OriginalHook(AirAnchor)) || JustUsed(Chainsaw) || + JustUsed(Drill) || JustUsed(Excavator))) + { + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); - if (!HasEffect(Buffs.Wildfire) && - !HasEffect(Buffs.Reassembled) && HasCharges(Reassemble) && - (Scattergun.LevelChecked() || - (gauge.IsOverheated && AutoCrossbow.LevelChecked()) || - (GetCooldownRemainingTime(Chainsaw) < 1 && Chainsaw.LevelChecked()) || - (GetCooldownRemainingTime(OriginalHook(Chainsaw)) < 1 && Excavator.LevelChecked()))) - return Reassemble; + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); + } - if (LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady)) - return OriginalHook(Chainsaw); + // Healing + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_SecondWind) && + PlayerHealthPercentageHp() <= Config.MCH_ST_SecondWindThreshold && + ActionReady(All.SecondWind) && !Gauge.IsOverheated) + return All.SecondWind; + } + + // Full Metal Field + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer_FullMetalField) && + HasEffect(Buffs.FullMetalMachinist) && + (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || + GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && + LevelChecked(FullMetalField)) + return FullMetalField; + + // Heatblast + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Heatblast) && + Gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) + return OriginalHook(Heatblast); + + // Reassemble and Tools + if (ReassembledTools(ref actionID, Gauge)) + return actionID; + + // Excavator + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Excavator) && + reassembledExcavator && + LevelChecked(Excavator) && + HasEffect(Buffs.ExcavatorReady) && + (BSUsed is 1 || + (BSUsed is 2 or 5 or 8 && Gauge.Battery <= 40) || + (BSUsed is 3 or 6 or 9 && Gauge.Battery <= 50) || + (BSUsed is 4 or 7 or 10 && Gauge.Battery <= 60) || + GetBuffRemainingTime(Buffs.ExcavatorReady) < 6)) + return OriginalHook(Chainsaw); + + // 1-2-3 Combo + if (comboTime > 0) + { + if (lastComboMove is SplitShot && LevelChecked(OriginalHook(SlugShot))) + return OriginalHook(SlugShot); - if ((LevelChecked(Chainsaw) && (GetCooldownRemainingTime(Chainsaw) <= GCD + 0.25)) || ActionReady(Chainsaw)) - return Chainsaw; + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[4] && + lastComboMove == OriginalHook(SlugShot) && + !LevelChecked(Drill) && !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble)) + return Reassemble; - if (LevelChecked(AutoCrossbow) && gauge.IsOverheated) - return AutoCrossbow; + if (lastComboMove is SlugShot && LevelChecked(OriginalHook(CleanShot))) + return OriginalHook(CleanShot); } - return actionID; + + return OriginalHook(SplitShot); } + + return actionID; } - internal class MCH_AoE_AdvancedMode : CustomCombo + private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_AoE_AdvancedMode; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + bool battery = Svc.Gauges.Get().Battery >= 100; + + bool reassembledChainsaw = + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[1] && + (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[1] && + !HasEffect(Buffs.Reassembled)) || + (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || + !IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble); + + bool reassembledAnchor = + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[2] && + (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[2] && + !HasEffect(Buffs.Reassembled)) || + (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || + !IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble); + + bool reassembledDrill = + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[3] && + (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || + (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && !Config.MCH_ST_Reassembled[3] && + !HasEffect(Buffs.Reassembled)) || + (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || + !IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble); + + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && + !gauge.IsOverheated && !JustUsed(OriginalHook(Heatblast)) && !ActionWatching.HasDoubleWeaved() && + !HasEffect(Buffs.Reassembled) && ActionReady(Reassemble) && + (CanWeave(ActionWatching.LastWeaponskill) || !InCombat()) && + GetRemainingCharges(Reassemble) > Config.MCH_ST_ReassemblePool && + ((Config.MCH_ST_Reassembled[0] && LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && + !battery && gauge.IsRobotActive && GetCooldownRemainingTime(Wildfire) > 3) || + (Config.MCH_ST_Reassembled[1] && LevelChecked(Chainsaw) && + (!LevelChecked(Excavator) || !Config.MCH_ST_Reassembled[0]) && + (GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Chainsaw)) && !battery) || + (Config.MCH_ST_Reassembled[2] && LevelChecked(AirAnchor) && + (GetCooldownRemainingTime(AirAnchor) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(AirAnchor)) && !battery) || + (Config.MCH_ST_Reassembled[3] && LevelChecked(Drill) && + (!LevelChecked(AirAnchor) || !Config.MCH_ST_Reassembled[2]) && + (GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Drill))))) { - MCHGauge? gauge = GetJobGauge(); - float GCD = GetCooldown(OriginalHook(SpreadShot)).CooldownTotal; - bool reassembledScattergun = IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[0] && HasEffect(Buffs.Reassembled); - bool reassembledCrossbow = (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[1] && HasEffect(Buffs.Reassembled)) || (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !Config.MCH_AoE_Reassembled[1] && !HasEffect(Buffs.Reassembled)) || (!IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble)); - bool reassembledChainsaw = (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[2] && HasEffect(Buffs.Reassembled)) || (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !Config.MCH_AoE_Reassembled[2] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_AoE_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble)); - bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[3] && HasEffect(Buffs.Reassembled)) || (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !Config.MCH_AoE_Reassembled[3] && !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_AoE_ReassemblePool) || (!IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble)); - - if (actionID is SpreadShot or Scattergun) - { - if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.MCH_VariantCure) - return Variant.VariantCure; + actionID = Reassemble; - if (HasEffect(Buffs.Flamethrower) || JustUsed(Flamethrower)) - return OriginalHook(11); + return true; + } - if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Chainsaw) && + reassembledChainsaw && + LevelChecked(Chainsaw) && + !battery && + (GetCooldownRemainingTime(Chainsaw) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Chainsaw))) + { + actionID = Chainsaw; - //Full Metal Field - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer_FullMetalField) && - HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) - return FullMetalField; + return true; + } - // BarrelStabilizer - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer) && - !gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) - return BarrelStabilizer; + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_AirAnchor) && + reassembledAnchor && + LevelChecked(OriginalHook(AirAnchor)) && + !battery && + (GetCooldownRemainingTime(OriginalHook(AirAnchor)) <= + GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || ActionReady(OriginalHook(AirAnchor)))) + { + actionID = OriginalHook(AirAnchor); - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Bioblaster) && - ActionReady(BioBlaster) && !TargetHasEffect(Debuffs.Bioblaster)) - return OriginalHook(BioBlaster); + return true; + } - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_FlameThrower) && - ActionReady(Flamethrower) && !IsMoving) - return OriginalHook(Flamethrower); + if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Drill) && + reassembledDrill && + LevelChecked(Drill) && + !JustUsed(Drill) && + (GetCooldownRemainingTime(Drill) <= GetCooldownRemainingTime(OriginalHook(SplitShot)) + 0.25 || + ActionReady(Drill)) && + GetCooldownRemainingTime(Wildfire) is >= 20 or <= 10) + { + actionID = Drill; - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Queen) && !gauge.IsOverheated) - { - if (gauge.Battery >= Config.MCH_AoE_TurretUsage) - return OriginalHook(RookAutoturret); - } + return true; + } - // Hypercharge - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Hypercharge) && - (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && LevelChecked(Hypercharge) && LevelChecked(AutoCrossbow) && !gauge.IsOverheated && - ((BioBlaster.LevelChecked() && GetCooldownRemainingTime(BioBlaster) > 10) || !BioBlaster.LevelChecked() || IsNotEnabled(CustomComboPreset.MCH_AoE_Adv_Bioblaster)) && - ((Flamethrower.LevelChecked() && GetCooldownRemainingTime(Flamethrower) > 10) || !Flamethrower.LevelChecked() || IsNotEnabled(CustomComboPreset.MCH_AoE_Adv_FlameThrower))) - return Hypercharge; - - //AutoCrossbow, Gauss, Rico - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_GaussRicochet) && !Config.MCH_AoE_Hypercharge && - CanWeave(actionID) && JustUsed(OriginalHook(AutoCrossbow)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); + return false; + } + } - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } + internal class MCH_AoE_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_AoE_SimpleMode; - if (gauge.IsOverheated && AutoCrossbow.LevelChecked()) - return OriginalHook(AutoCrossbow); + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + float GCD = GetCooldown(OriginalHook(SpreadShot)).CooldownTotal; - //gauss and ricochet outside HC - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_GaussRicochet) && Config.MCH_AoE_Hypercharge && - CanWeave(actionID) && !gauge.IsOverheated) - { - if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) - return OriginalHook(GaussRound); + if (actionID is SpreadShot or Scattergun) + { + if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MCH_VariantCure) + return Variant.VariantCure; - if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) - return OriginalHook(Ricochet); - } + if (HasEffect(Buffs.Flamethrower) || JustUsed(Flamethrower)) + return OriginalHook(11); - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !HasEffect(Buffs.Wildfire) && - !HasEffect(Buffs.Reassembled) && HasCharges(Reassemble) && - GetRemainingCharges(Reassemble) > Config.MCH_AoE_ReassemblePool && - ((Config.MCH_AoE_Reassembled[0] && Scattergun.LevelChecked()) || - (gauge.IsOverheated && Config.MCH_AoE_Reassembled[1] && AutoCrossbow.LevelChecked()) || - (GetCooldownRemainingTime(Chainsaw) < 1 && Config.MCH_AoE_Reassembled[2] && Chainsaw.LevelChecked()) || - (GetCooldownRemainingTime(OriginalHook(Chainsaw)) < 1 && Config.MCH_AoE_Reassembled[3] && Excavator.LevelChecked()))) - return Reassemble; + if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + //Full Metal Field + if (HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) + return FullMetalField; + + // BarrelStabilizer + if (!Gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; + + if (ActionReady(BioBlaster) && !TargetHasEffect(Debuffs.Bioblaster)) + return OriginalHook(BioBlaster); + + if (ActionReady(Flamethrower) && !IsMoving) + return OriginalHook(Flamethrower); + + if (!Gauge.IsOverheated && Gauge.Battery == 100) + return OriginalHook(RookAutoturret); + + // Hypercharge + if ((Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && LevelChecked(Hypercharge) && + LevelChecked(AutoCrossbow) && !Gauge.IsOverheated && + ((BioBlaster.LevelChecked() && GetCooldownRemainingTime(BioBlaster) > 10) || + !BioBlaster.LevelChecked()) && + ((Flamethrower.LevelChecked() && GetCooldownRemainingTime(Flamethrower) > 10) || + !Flamethrower.LevelChecked())) + return Hypercharge; + + //AutoCrossbow, Gauss, Rico + if (CanWeave(actionID) && JustUsed(OriginalHook(AutoCrossbow)) && + ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Excavator) && - reassembledExcavator && - LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady)) - return OriginalHook(Chainsaw); + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Chainsaw) && - reassembledChainsaw && - LevelChecked(Chainsaw) && ((GetCooldownRemainingTime(Chainsaw) <= GCD + 0.25) || ActionReady(Chainsaw))) - return Chainsaw; + if (Gauge.IsOverheated && AutoCrossbow.LevelChecked()) + return OriginalHook(AutoCrossbow); - if (reassembledScattergun) - return OriginalHook(Scattergun); + if (!HasEffect(Buffs.Wildfire) && + !HasEffect(Buffs.Reassembled) && HasCharges(Reassemble) && + (Scattergun.LevelChecked() || + (Gauge.IsOverheated && AutoCrossbow.LevelChecked()) || + (GetCooldownRemainingTime(Chainsaw) < 1 && Chainsaw.LevelChecked()) || + (GetCooldownRemainingTime(OriginalHook(Chainsaw)) < 1 && Excavator.LevelChecked()))) + return Reassemble; - if (reassembledCrossbow && - LevelChecked(AutoCrossbow) && gauge.IsOverheated) - return AutoCrossbow; + if (LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady)) + return OriginalHook(Chainsaw); - if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_SecondWind)) - { - if (PlayerHealthPercentageHp() <= Config.MCH_AoE_SecondWindThreshold && ActionReady(All.SecondWind)) - return All.SecondWind; - } - } - return actionID; + if ((LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) <= GCD + 0.25) || + ActionReady(Chainsaw)) + return Chainsaw; + + if (LevelChecked(AutoCrossbow) && Gauge.IsOverheated) + return AutoCrossbow; } + + return actionID; } + } - internal class MCH_HeatblastGaussRicochet : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_Heatblast; + internal class MCH_AoE_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_AoE_AdvancedMode; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + float GCD = GetCooldown(OriginalHook(SpreadShot)).CooldownTotal; + + bool reassembledScattergun = IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && + Config.MCH_AoE_Reassembled[0] && HasEffect(Buffs.Reassembled); + + bool reassembledCrossbow = + (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[1] && + HasEffect(Buffs.Reassembled)) || + (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !Config.MCH_AoE_Reassembled[1] && + !HasEffect(Buffs.Reassembled)) || !IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble); + + bool reassembledChainsaw = + (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[2] && + HasEffect(Buffs.Reassembled)) || + (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !Config.MCH_AoE_Reassembled[2] && + !HasEffect(Buffs.Reassembled)) || + (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_AoE_ReassemblePool) || + !IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble); + + bool reassembledExcavator = + (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[3] && + HasEffect(Buffs.Reassembled)) || + (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !Config.MCH_AoE_Reassembled[3] && + !HasEffect(Buffs.Reassembled)) || + (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_AoE_ReassemblePool) || + !IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble); + + if (actionID is SpreadShot or Scattergun) { - MCHGauge? gauge = GetJobGauge(); + if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.MCH_VariantCure) + return Variant.VariantCure; - if (actionID is Heatblast or BlazingShot) - { - if (IsEnabled(CustomComboPreset.MCH_Heatblast_AutoBarrel) && - ActionReady(BarrelStabilizer) && !gauge.IsOverheated) - return BarrelStabilizer; - - if (IsEnabled(CustomComboPreset.MCH_Heatblast_Wildfire) && - ActionReady(Wildfire) && - JustUsed(Hypercharge)) - return Wildfire; + if (HasEffect(Buffs.Flamethrower) || JustUsed(Flamethrower)) + return OriginalHook(11); - if (!gauge.IsOverheated && LevelChecked(Hypercharge) && - (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged))) - return Hypercharge; + if (IsEnabled(CustomComboPreset.MCH_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; - //Heatblast, Gauss, Rico - if (IsEnabled(CustomComboPreset.MCH_Heatblast_GaussRound) && - CanWeave(actionID) && JustUsed(OriginalHook(Heatblast)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); + //Full Metal Field + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer_FullMetalField) && + HasEffect(Buffs.FullMetalMachinist) && LevelChecked(FullMetalField)) + return FullMetalField; - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } + // BarrelStabilizer + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Stabilizer) && + !Gauge.IsOverheated && CanWeave(actionID) && ActionReady(BarrelStabilizer)) + return BarrelStabilizer; - if (gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) - return OriginalHook(Heatblast); - } - return actionID; - } - } + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Bioblaster) && + ActionReady(BioBlaster) && !TargetHasEffect(Debuffs.Bioblaster)) + return OriginalHook(BioBlaster); - internal class MCH_AutoCrossbowGaussRicochet : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_AutoCrossbow; + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_FlameThrower) && + ActionReady(Flamethrower) && !IsMoving) + return OriginalHook(Flamethrower); - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - MCHGauge? gauge = GetJobGauge(); + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Queen) && !Gauge.IsOverheated) + if (Gauge.Battery >= Config.MCH_AoE_TurretUsage) + return OriginalHook(RookAutoturret); - if (actionID is AutoCrossbow) + // Hypercharge + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Hypercharge) && + (Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && LevelChecked(Hypercharge) && + LevelChecked(AutoCrossbow) && !Gauge.IsOverheated && + ((BioBlaster.LevelChecked() && GetCooldownRemainingTime(BioBlaster) > 10) || + !BioBlaster.LevelChecked() || IsNotEnabled(CustomComboPreset.MCH_AoE_Adv_Bioblaster)) && + ((Flamethrower.LevelChecked() && GetCooldownRemainingTime(Flamethrower) > 10) || + !Flamethrower.LevelChecked() || IsNotEnabled(CustomComboPreset.MCH_AoE_Adv_FlameThrower))) + return Hypercharge; + + //AutoCrossbow, Gauss, Rico + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_GaussRicochet) && !Config.MCH_AoE_Hypercharge && + CanWeave(actionID) && JustUsed(OriginalHook(AutoCrossbow)) && + ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability) { - if (IsEnabled(CustomComboPreset.MCH_AutoCrossbow_AutoBarrel) && - ActionReady(BarrelStabilizer) && !gauge.IsOverheated) - return BarrelStabilizer; + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); - if (!gauge.IsOverheated && LevelChecked(Hypercharge) && - (gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged))) - return Hypercharge; + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - //Autocrossbow, Gauss, Rico - if (IsEnabled(CustomComboPreset.MCH_AutoCrossbow_GaussRound) && CanWeave(actionID) && JustUsed(OriginalHook(AutoCrossbow)) && - (ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability)) - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); + if (Gauge.IsOverheated && AutoCrossbow.LevelChecked()) + return OriginalHook(AutoCrossbow); - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } + //gauss and ricochet outside HC + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_GaussRicochet) && Config.MCH_AoE_Hypercharge && + CanWeave(actionID) && !Gauge.IsOverheated) + { + if (ActionReady(OriginalHook(GaussRound)) && !JustUsed(OriginalHook(GaussRound))) + return OriginalHook(GaussRound); - if (gauge.IsOverheated && LevelChecked(OriginalHook(AutoCrossbow))) - return OriginalHook(AutoCrossbow); + if (ActionReady(OriginalHook(Ricochet)) && !JustUsed(OriginalHook(Ricochet))) + return OriginalHook(Ricochet); } - return actionID; + + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && !HasEffect(Buffs.Wildfire) && + !HasEffect(Buffs.Reassembled) && HasCharges(Reassemble) && + GetRemainingCharges(Reassemble) > Config.MCH_AoE_ReassemblePool && + ((Config.MCH_AoE_Reassembled[0] && Scattergun.LevelChecked()) || + (Gauge.IsOverheated && Config.MCH_AoE_Reassembled[1] && AutoCrossbow.LevelChecked()) || + (GetCooldownRemainingTime(Chainsaw) < 1 && Config.MCH_AoE_Reassembled[2] && + Chainsaw.LevelChecked()) || + (GetCooldownRemainingTime(OriginalHook(Chainsaw)) < 1 && Config.MCH_AoE_Reassembled[3] && + Excavator.LevelChecked()))) + return Reassemble; + + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Excavator) && + reassembledExcavator && + LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady)) + return OriginalHook(Chainsaw); + + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Chainsaw) && + reassembledChainsaw && + LevelChecked(Chainsaw) && + (GetCooldownRemainingTime(Chainsaw) <= GCD + 0.25 || ActionReady(Chainsaw))) + return Chainsaw; + + if (reassembledScattergun) + return OriginalHook(Scattergun); + + if (reassembledCrossbow && + LevelChecked(AutoCrossbow) && Gauge.IsOverheated) + return AutoCrossbow; + + if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_SecondWind)) + if (PlayerHealthPercentageHp() <= Config.MCH_AoE_SecondWindThreshold && ActionReady(All.SecondWind)) + return All.SecondWind; } + + return actionID; } + } - internal class MCH_GaussRoundRicochet : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_GaussRoundRicochet; + internal class MCH_HeatblastGaussRicochet : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_Heatblast; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Heatblast or BlazingShot) { - - if (actionID is GaussRound or Ricochet or CheckMate or DoubleCheck) + if (IsEnabled(CustomComboPreset.MCH_Heatblast_AutoBarrel) && + ActionReady(BarrelStabilizer) && !Gauge.IsOverheated) + return BarrelStabilizer; + + if (IsEnabled(CustomComboPreset.MCH_Heatblast_Wildfire) && + ActionReady(Wildfire) && + JustUsed(Hypercharge)) + return Wildfire; + + if (!Gauge.IsOverheated && LevelChecked(Hypercharge) && + (Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged))) + return Hypercharge; + + //Heatblast, Gauss, Rico + if (IsEnabled(CustomComboPreset.MCH_Heatblast_GaussRound) && + CanWeave(actionID) && JustUsed(OriginalHook(Heatblast)) && + ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability) { - { - if (ActionReady(OriginalHook(GaussRound)) && - GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) - return OriginalHook(GaussRound); + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); - if (ActionReady(OriginalHook(Ricochet)) && - GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) - return OriginalHook(Ricochet); - } + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); } - return actionID; + if (Gauge.IsOverheated && LevelChecked(OriginalHook(Heatblast))) + return OriginalHook(Heatblast); } + + return actionID; } + } - internal class MCH_Overdrive : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_Overdrive; + internal class MCH_AutoCrossbowGaussRicochet : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_AutoCrossbow; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is AutoCrossbow) { - MCHGauge? gauge = GetJobGauge(); + if (IsEnabled(CustomComboPreset.MCH_AutoCrossbow_AutoBarrel) && + ActionReady(BarrelStabilizer) && !Gauge.IsOverheated) + return BarrelStabilizer; + + if (!Gauge.IsOverheated && LevelChecked(Hypercharge) && + (Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged))) + return Hypercharge; + + //Autocrossbow, Gauss, Rico + if (IsEnabled(CustomComboPreset.MCH_AutoCrossbow_GaussRound) && CanWeave(actionID) && + JustUsed(OriginalHook(AutoCrossbow)) && + ActionWatching.GetAttackType(ActionWatching.LastAction) != ActionWatching.ActionAttackType.Ability) + { + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); - if (actionID is RookAutoturret or AutomatonQueen && gauge.IsRobotActive) - return OriginalHook(QueenOverdrive); + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - return actionID; + if (Gauge.IsOverheated && LevelChecked(OriginalHook(AutoCrossbow))) + return OriginalHook(AutoCrossbow); } + + return actionID; } + } - internal class MCH_HotShotDrillChainsawExcavator : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_HotShotDrillChainsawExcavator; + internal class MCH_GaussRoundRicochet : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_GaussRoundRicochet; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is GaussRound or Ricochet or CheckMate or DoubleCheck) { - if (actionID is Drill or HotShot or AirAnchor or Chainsaw) - { - if (LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady)) - return CalcBestAction(actionID, Excavator, Chainsaw, AirAnchor, Drill); + if (ActionReady(OriginalHook(GaussRound)) && + GetRemainingCharges(OriginalHook(GaussRound)) >= GetRemainingCharges(OriginalHook(Ricochet))) + return OriginalHook(GaussRound); - if (LevelChecked(Chainsaw)) - return CalcBestAction(actionID, Chainsaw, AirAnchor, Drill); + if (ActionReady(OriginalHook(Ricochet)) && + GetRemainingCharges(OriginalHook(Ricochet)) > GetRemainingCharges(OriginalHook(GaussRound))) + return OriginalHook(Ricochet); + } - if (LevelChecked(AirAnchor)) - return CalcBestAction(actionID, AirAnchor, Drill); + return actionID; + } + } - if (LevelChecked(Drill)) - return CalcBestAction(actionID, Drill, HotShot); + internal class MCH_Overdrive : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_Overdrive; - return HotShot; - } - return actionID; - } + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is RookAutoturret or AutomatonQueen && Gauge.IsRobotActive) + return OriginalHook(QueenOverdrive); + + return actionID; } + } - internal class MCH_DismantleTactician : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_DismantleTactician; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Dismantle - && (IsOnCooldown(Dismantle) || !LevelChecked(Dismantle)) - && ActionReady(Tactician) - && !HasEffect(Buffs.Tactician)) - return Tactician; + internal class MCH_HotShotDrillChainsawExcavator : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = + CustomComboPreset.MCH_HotShotDrillChainsawExcavator; - return actionID; - } + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Drill or HotShot or AirAnchor or Chainsaw) + return LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) + ? CalcBestAction(actionID, Excavator, Chainsaw, AirAnchor, Drill) + : LevelChecked(Chainsaw) + ? CalcBestAction(actionID, Chainsaw, AirAnchor, Drill) + : LevelChecked(AirAnchor) + ? CalcBestAction(actionID, AirAnchor, Drill) + : LevelChecked(Drill) + ? CalcBestAction(actionID, Drill, HotShot) + : HotShot; + + return actionID; } + } - internal class All_PRanged_Dismantle : CustomCombo + internal class MCH_DismantleTactician : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_DismantleTactician; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.All_PRanged_Dismantle; + if (actionID is Dismantle + && (IsOnCooldown(Dismantle) || !LevelChecked(Dismantle)) + && ActionReady(Tactician) + && !HasEffect(Buffs.Tactician)) + return Tactician; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Dismantle && TargetHasEffectAny(Debuffs.Dismantled) && IsOffCooldown(Dismantle)) - return OriginalHook(11); + return actionID; + } + } - return actionID; - } + internal class All_PRanged_Dismantle : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.All_PRanged_Dismantle; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Dismantle && TargetHasEffectAny(Debuffs.Dismantled) && IsOffCooldown(Dismantle)) + return OriginalHook(11); + + return actionID; } } } \ No newline at end of file From a04b67f05adeb6358f35c99fa23c630ce113914d Mon Sep 17 00:00:00 2001 From: Kage Date: Sun, 8 Sep 2024 19:26:41 +0200 Subject: [PATCH 095/208] Auto Refactor Add static gauge --- XIVSlothCombo/Combos/JobHelpers/DRG.cs | 393 +++--- XIVSlothCombo/Combos/JobHelpers/RPR.cs | 446 ++++--- XIVSlothCombo/Combos/PvE/DRG.cs | 1195 +++++++++--------- XIVSlothCombo/Combos/PvE/RPR.cs | 1539 ++++++++++++------------ 4 files changed, 1803 insertions(+), 1770 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/DRG.cs b/XIVSlothCombo/Combos/JobHelpers/DRG.cs index 1f298d86c..178b642c3 100644 --- a/XIVSlothCombo/Combos/JobHelpers/DRG.cs +++ b/XIVSlothCombo/Combos/JobHelpers/DRG.cs @@ -1,275 +1,270 @@ -using ECommons.DalamudServices; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Combos.PvE; +using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; -namespace XIVSlothCombo.Combos.JobHelpers -{ - internal class DRGOpenerLogic : DRG - { - private static bool HasCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2) - return false; - - if (!CustomComboFunctions.ActionReady(BattleLitany)) - return false; - - if (!CustomComboFunctions.ActionReady(DragonfireDive)) - return false; - - if (!CustomComboFunctions.ActionReady(LanceCharge)) - return false; - - return true; - } +namespace XIVSlothCombo.Combos.JobHelpers; - private static uint OpenerLevel => 100; +internal class DRGOpenerLogic : DRG +{ + private OpenerState currentState = OpenerState.PrePull; - public uint PrePullStep = 0; + public uint OpenerStep = 1; - public uint OpenerStep = 1; + public uint PrePullStep; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; + private static uint OpenerLevel => 100; - private static bool CanOpener => HasCooldowns() && LevelChecked; + public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; - private OpenerState currentState = OpenerState.PrePull; + private static bool CanOpener => HasCooldowns() && LevelChecked; - public OpenerState CurrentState + public OpenerState CurrentState + { + get => currentState; + set { - get - { - return currentState; - } - set + if (value != currentState) { - if (value != currentState) + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + + currentState = value; } } + } - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) return false; + private static bool HasCooldowns() + { + if (CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2) + return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (!CustomComboFunctions.ActionReady(BattleLitany)) + return false; - if (!HasCooldowns()) - { - PrePullStep = 0; - } + if (!CustomComboFunctions.ActionReady(DragonfireDive)) + return false; - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (CustomComboFunctions.WasLastAction(TrueThrust) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = TrueThrust; + if (!CustomComboFunctions.ActionReady(LanceCharge)) + return false; - if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) - CurrentState = OpenerState.FailedOpener; + return true; + } - return true; - } + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) return false; - PrePullStep = 0; - return false; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - private bool DoOpener(ref uint actionID) + if (!HasCooldowns()) PrePullStep = 0; + + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (!LevelChecked) return false; + if (CustomComboFunctions.WasLastAction(TrueThrust) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = TrueThrust; - if (currentState == OpenerState.InOpener) - { - if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = SpiralBlow; + if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) + CurrentState = OpenerState.FailedOpener; - if (CustomComboFunctions.WasLastAction(LanceCharge) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = LanceCharge; + return true; + } - if (CustomComboFunctions.WasLastAction(ChaoticSpring) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = ChaoticSpring; + PrePullStep = 0; - if (CustomComboFunctions.WasLastAction(BattleLitany) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = BattleLitany; + return false; + } - if (CustomComboFunctions.WasLastAction(Geirskogul) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Geirskogul; + private bool DoOpener(ref uint actionID) + { + if (!LevelChecked) return false; - if (CustomComboFunctions.WasLastAction(WheelingThrust) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = WheelingThrust; + if (currentState == OpenerState.InOpener) + { + if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = SpiralBlow; - if (CustomComboFunctions.WasLastAction(HighJump) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = HighJump; + if (CustomComboFunctions.WasLastAction(LanceCharge) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = LanceCharge; - if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = LifeSurge; + if (CustomComboFunctions.WasLastAction(ChaoticSpring) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = ChaoticSpring; - if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Drakesbane; + if (CustomComboFunctions.WasLastAction(BattleLitany) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = BattleLitany; - if (CustomComboFunctions.WasLastAction(DragonfireDive) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonfireDive; + if (CustomComboFunctions.WasLastAction(Geirskogul) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = Geirskogul; - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Nastrond; + if (CustomComboFunctions.WasLastAction(WheelingThrust) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = WheelingThrust; - if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = RaidenThrust; + if (CustomComboFunctions.WasLastAction(HighJump) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = HighJump; - if (CustomComboFunctions.WasLastAction(Stardiver) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Stardiver; + if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = LifeSurge; - if (CustomComboFunctions.WasLastAction(LanceBarrage) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = LanceBarrage; + if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = Drakesbane; - if (CustomComboFunctions.WasLastAction(Starcross) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Starcross; + if (CustomComboFunctions.WasLastAction(DragonfireDive) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonfireDive; - if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LifeSurge; + if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = Nastrond; - if (CustomComboFunctions.WasLastAction(HeavensThrust) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = HeavensThrust; + if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = RaidenThrust; - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Nastrond; + if (CustomComboFunctions.WasLastAction(Stardiver) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = Stardiver; - if (CustomComboFunctions.WasLastAction(RiseOfTheDragon) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = RiseOfTheDragon; + if (CustomComboFunctions.WasLastAction(LanceBarrage) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = LanceBarrage; - if (CustomComboFunctions.WasLastAction(FangAndClaw) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = FangAndClaw; + if (CustomComboFunctions.WasLastAction(Starcross) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = Starcross; - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = Nastrond; + if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LifeSurge; - if (CustomComboFunctions.WasLastAction(MirageDive) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = MirageDive; + if (CustomComboFunctions.WasLastAction(HeavensThrust) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = HeavensThrust; - if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = Drakesbane; + if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = Nastrond; - if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 24) OpenerStep++; - else if (OpenerStep == 24) actionID = RaidenThrust; + if (CustomComboFunctions.WasLastAction(RiseOfTheDragon) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = RiseOfTheDragon; - if (CustomComboFunctions.WasLastAction(WyrmwindThrust) && OpenerStep == 25) OpenerStep++; - else if (OpenerStep == 25) actionID = WyrmwindThrust; + if (CustomComboFunctions.WasLastAction(FangAndClaw) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = FangAndClaw; - if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 26) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 26) actionID = SpiralBlow; + if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = Nastrond; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (CustomComboFunctions.WasLastAction(MirageDive) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = MirageDive; - if (((actionID == DragonfireDive && CustomComboFunctions.IsOnCooldown(DragonfireDive)) || - (actionID == BattleLitany && CustomComboFunctions.IsOnCooldown(BattleLitany)) || - (actionID == LanceCharge && CustomComboFunctions.IsOnCooldown(LanceCharge)) || - (actionID == LifeSurge && CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - return true; - } - return false; - } + if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 23) OpenerStep++; + else if (OpenerStep == 23) actionID = Drakesbane; - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } + if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 24) OpenerStep++; + else if (OpenerStep == 24) actionID = RaidenThrust; - public bool DoFullOpener(ref uint actionID) - { - if (!LevelChecked) - return false; + if (CustomComboFunctions.WasLastAction(WyrmwindThrust) && OpenerStep == 25) OpenerStep++; + else if (OpenerStep == 25) actionID = WyrmwindThrust; - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; + if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 26) + CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 26) actionID = SpiralBlow; - if (CurrentState == OpenerState.InOpener) - { - if (DoOpener(ref actionID)) - return true; - } + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; - if (!CustomComboFunctions.InCombat()) + if (((actionID == DragonfireDive && CustomComboFunctions.IsOnCooldown(DragonfireDive)) || + (actionID == BattleLitany && CustomComboFunctions.IsOnCooldown(BattleLitany)) || + (actionID == LanceCharge && CustomComboFunctions.IsOnCooldown(LanceCharge)) || + (actionID == LifeSurge && CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2)) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { - ResetOpener(); - CurrentState = OpenerState.PrePull; + CurrentState = OpenerState.FailedOpener; + + return false; } - return false; + + return true; } + + return false; } - internal class AnimationLock + + private void ResetOpener() { - internal static readonly List FastLocks = - [ - DRG.BattleLitany, - DRG.LanceCharge, - DRG.LifeSurge, - DRG.Geirskogul, - DRG.Nastrond, - DRG.MirageDive, - DRG.WyrmwindThrust, - DRG.RiseOfTheDragon, - DRG.Starcross, - PvE.Content.Variant.VariantRampart, - PvE.All.TrueNorth - ]; - - internal static readonly List MidLocks = - [ - DRG.Jump, - DRG.HighJump, - DRG.DragonfireDive, - ]; - - internal static uint SlowLock => DRG.Stardiver; - - internal static bool CanDRGWeave(uint oGCD) - { - //GCD Ready - No Weave - if (CustomComboFunctions.IsOffCooldown(DRG.TrueThrust)) - return false; + PrePullStep = 0; + OpenerStep = 0; + } - var gcdTimer = CustomComboFunctions.GetCooldownRemainingTime(DRG.TrueThrust); + public bool DoFullOpener(ref uint actionID) + { + if (!LevelChecked) + return false; - if (FastLocks.Any(x => x == oGCD) && gcdTimer >= 0.6f) + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) return true; - if (MidLocks.Any(x => x == oGCD) && gcdTimer >= 0.8f) + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID)) return true; - if (SlowLock == oGCD && gcdTimer >= 1.5f) - return true; + if (!CustomComboFunctions.InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; + } + return false; + } +} + +internal class AnimationLock +{ + internal static readonly List FastLocks = + [ + DRG.BattleLitany, + DRG.LanceCharge, + DRG.LifeSurge, + DRG.Geirskogul, + DRG.Nastrond, + DRG.MirageDive, + DRG.WyrmwindThrust, + DRG.RiseOfTheDragon, + DRG.Starcross, + Variant.VariantRampart, + All.TrueNorth + ]; + + internal static readonly List MidLocks = + [ + DRG.Jump, + DRG.HighJump, + DRG.DragonfireDive + ]; + + internal static uint SlowLock => DRG.Stardiver; + + internal static bool CanDRGWeave(uint oGCD) + { + //GCD Ready - No Weave + if (CustomComboFunctions.IsOffCooldown(DRG.TrueThrust)) return false; - } + + float gcdTimer = CustomComboFunctions.GetCooldownRemainingTime(DRG.TrueThrust); + + if (FastLocks.Any(x => x == oGCD) && gcdTimer >= 0.6f) + return true; + + if (MidLocks.Any(x => x == oGCD) && gcdTimer >= 0.8f) + return true; + + if (SlowLock == oGCD && gcdTimer >= 1.5f) + return true; + + return false; } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/JobHelpers/RPR.cs b/XIVSlothCombo/Combos/JobHelpers/RPR.cs index 8719f2ad7..578e93a76 100644 --- a/XIVSlothCombo/Combos/JobHelpers/RPR.cs +++ b/XIVSlothCombo/Combos/JobHelpers/RPR.cs @@ -2,313 +2,309 @@ using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using static XIVSlothCombo.Combos.PvE.RPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.JobHelpers; + +internal abstract class RPR { - internal class RPR + internal class RPROpenerLogic { - internal class RPROpenerLogic - { - private static bool HasCooldowns() - { - if (GetRemainingCharges(SoulSlice) < 2) - return false; + private OpenerState currentState = OpenerState.PrePull; - if (!ActionReady(ArcaneCircle)) - return false; + public uint OpenerStep = 1; - if (!ActionReady(Gluttony)) - return false; + public uint PrePullStep; - return true; - } + private static uint OpenerLevel => 100; - private static uint OpenerLevel => 100; + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; - public uint PrePullStep = 0; + private static bool CanOpener => HasCooldowns() && LevelChecked; - public uint OpenerStep = 1; - - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; - - private static bool CanOpener => HasCooldowns() && LevelChecked; - - private OpenerState currentState = OpenerState.PrePull; - - public OpenerState CurrentState + public OpenerState CurrentState + { + get => currentState; + set { - get - { - return currentState; - } - set + if (value != currentState) { - if (value != currentState) + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + + currentState = value; } } + } - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) return false; + private static bool HasCooldowns() + { + if (GetRemainingCharges(SoulSlice) < 2) + return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (!ActionReady(ArcaneCircle)) + return false; - if (!HasCooldowns()) - { - PrePullStep = 0; - } + if (!ActionReady(Gluttony)) + return false; - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (WasLastAction(ShadowOfDeath) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = ShadowOfDeath; + return true; + } - if (ActionWatching.CombatActions.Count > 2 && InCombat()) - CurrentState = OpenerState.FailedOpener; + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) return false; - return true; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - PrePullStep = 0; - return false; - } + if (!HasCooldowns()) PrePullStep = 0; - private bool DoOpener(ref uint actionID) + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (!LevelChecked) return false; + if (WasLastAction(ShadowOfDeath) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = ShadowOfDeath; - if (currentState == OpenerState.InOpener) - { - if (WasLastAction(SoulSlice) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = SoulSlice; + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; - if (WasLastAction(ArcaneCircle) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = ArcaneCircle; + return true; + } - if (WasLastAction(Gluttony) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Gluttony; + PrePullStep = 0; - if (WasLastAction(ExecutionersGibbet) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = ExecutionersGibbet; + return false; + } - if (WasLastAction(ExecutionersGallows) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = ExecutionersGallows; + private bool DoOpener(ref uint actionID) + { + if (!LevelChecked) return false; - if (WasLastAction(PlentifulHarvest) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = PlentifulHarvest; + if (currentState == OpenerState.InOpener) + { + if (WasLastAction(SoulSlice) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = SoulSlice; - if (WasLastAction(Enshroud) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = Enshroud; + if (WasLastAction(ArcaneCircle) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = ArcaneCircle; - if (WasLastAction(VoidReaping) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = VoidReaping; + if (WasLastAction(Gluttony) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = Gluttony; - if (WasLastAction(Sacrificium) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Sacrificium; + if (WasLastAction(ExecutionersGibbet) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = ExecutionersGibbet; - if (WasLastAction(CrossReaping) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = CrossReaping; + if (WasLastAction(ExecutionersGallows) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = ExecutionersGallows; - if (WasLastAction(LemuresSlice) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = LemuresSlice; + if (WasLastAction(PlentifulHarvest) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = PlentifulHarvest; - if (WasLastAction(VoidReaping) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = VoidReaping; + if (WasLastAction(Enshroud) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = Enshroud; - if (WasLastAction(CrossReaping) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = CrossReaping; + if (WasLastAction(VoidReaping) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = VoidReaping; - if (WasLastAction(LemuresSlice) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = LemuresSlice; + if (WasLastAction(Sacrificium) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = Sacrificium; - if (WasLastAction(Communio) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Communio; + if (WasLastAction(CrossReaping) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = CrossReaping; - if (WasLastAction(Perfectio) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = Perfectio; + if (WasLastAction(LemuresSlice) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = LemuresSlice; - if (WasLastAction(SoulSlice) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = SoulSlice; + if (WasLastAction(VoidReaping) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = VoidReaping; - if (WasLastAction(UnveiledGibbet) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = UnveiledGibbet; + if (WasLastAction(CrossReaping) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = CrossReaping; - if (WasLastAction(Gibbet) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Gibbet; + if (WasLastAction(LemuresSlice) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = LemuresSlice; - if (WasLastAction(ShadowOfDeath) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = ShadowOfDeath; + if (WasLastAction(Communio) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = Communio; - if (WasLastAction(Slice) && OpenerStep == 21) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 21) actionID = Slice; + if (WasLastAction(Perfectio) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = Perfectio; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; + if (WasLastAction(SoulSlice) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = SoulSlice; - if (((actionID == SoulSlice && GetRemainingCharges(SoulSlice) == 0) || - (actionID == ArcaneCircle && IsOnCooldown(ArcaneCircle)) || - (actionID == Gluttony && IsOnCooldown(Gluttony))) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - return true; - } - return false; - } + if (WasLastAction(UnveiledGibbet) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = UnveiledGibbet; - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } + if (WasLastAction(Gibbet) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = Gibbet; - public bool DoFullOpener(ref uint actionID) - { - if (!LevelChecked) - return false; + if (WasLastAction(ShadowOfDeath) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = ShadowOfDeath; - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; + if (WasLastAction(Slice) && OpenerStep == 21) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 21) actionID = Slice; - if (CurrentState == OpenerState.InOpener) - { - if (DoOpener(ref actionID)) - return true; - } + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; - if (!InCombat()) + if (((actionID == SoulSlice && GetRemainingCharges(SoulSlice) == 0) || + (actionID == ArcaneCircle && IsOnCooldown(ArcaneCircle)) || + (actionID == Gluttony && IsOnCooldown(Gluttony))) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { - ResetOpener(); - CurrentState = OpenerState.PrePull; + CurrentState = OpenerState.FailedOpener; + + return false; } - return false; + + return true; } + + return false; } - internal class RPRHelpers + private void ResetOpener() { - public unsafe static bool IsComboExpiring(float Times) - { - float GCD = GetCooldown(Slice).CooldownTotal * Times; + PrePullStep = 0; + OpenerStep = 0; + } + + public bool DoFullOpener(ref uint actionID) + { + if (!LevelChecked) + return false; - if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) return true; - else return false; - } + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID)) + return true; - public static bool IsBuffExpiring(float Times) + if (!InCombat()) { - float GCD = GetCooldown(Slice).CooldownTotal * Times; + ResetOpener(); + CurrentState = OpenerState.PrePull; + } - if ((HasEffect(Buffs.EnhancedGallows) && GetBuffRemainingTime(Buffs.EnhancedGallows) < GCD) || - (HasEffect(Buffs.EnhancedGibbet) && GetBuffRemainingTime(Buffs.EnhancedGibbet) < GCD)) - return true; + return false; + } + } - else return false; - } + internal class RPRHelpers + { + public static unsafe bool IsComboExpiring(float Times) + { + float GCD = GetCooldown(Slice).CooldownTotal * Times; + + if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) + return true; + + return false; + } + + public static bool IsBuffExpiring(float Times) + { + float GCD = GetCooldown(Slice).CooldownTotal * Times; + + if ((HasEffect(Buffs.EnhancedGallows) && GetBuffRemainingTime(Buffs.EnhancedGallows) < GCD) || + (HasEffect(Buffs.EnhancedGibbet) && GetBuffRemainingTime(Buffs.EnhancedGibbet) < GCD)) + return true; + + return false; + } + + public static bool IsDebuffExpiring(float Times) + { + float GCD = GetCooldown(Slice).CooldownTotal * Times; - public static bool IsDebuffExpiring(float Times) + if (TargetHasEffect(Debuffs.DeathsDesign) && GetDebuffRemainingTime(Debuffs.DeathsDesign) < GCD) + return true; + + return false; + } + + public static bool UseEnshroud(RPRGauge gauge) + { + float GCD = GetCooldown(Slice).CooldownTotal; + + if (LevelChecked(Enshroud) && (gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && + !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.Enshrouded)) { - float GCD = GetCooldown(Slice).CooldownTotal * Times; + // Before Plentiful Harvest + if (!LevelChecked(PlentifulHarvest)) + return true; - if (TargetHasEffect(Debuffs.DeathsDesign) && GetDebuffRemainingTime(Debuffs.DeathsDesign) < GCD) + // Shroud in Arcane Circle + if (HasEffect(Buffs.ArcaneCircle)) return true; - else return false; - } + // Prep for double Enshroud + if (LevelChecked(PlentifulHarvest) && + GetCooldownRemainingTime(ArcaneCircle) <= GCD * 2 + 1.5) + return true; - public static bool UseEnshroud(RPRGauge gauge) - { - float GCD = GetCooldown(Slice).CooldownTotal; + //2nd part of Double Enshroud + if (LevelChecked(PlentifulHarvest) && + WasLastWeaponskill(PlentifulHarvest)) + return true; - if (LevelChecked(Enshroud) && (gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && - !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.Enshrouded)) - { - // Before Plentiful Harvest - if (!LevelChecked(PlentifulHarvest)) - return true; - - // Shroud in Arcane Circle - if (HasEffect(Buffs.ArcaneCircle)) - return true; - - // Prep for double Enshroud - if (LevelChecked(PlentifulHarvest) && - GetCooldownRemainingTime(ArcaneCircle) <= (GCD * 2) + 1.5) - return true; - - //2nd part of Double Enshroud - if (LevelChecked(PlentifulHarvest) && - WasLastWeaponskill(PlentifulHarvest)) - return true; - - //Natural Odd Minute Shrouds - if (!HasEffect(Buffs.ArcaneCircle) && !IsDebuffExpiring(5) && - GetCooldownRemainingTime(ArcaneCircle) is >= 50 and <= 65) - return true; - - // Correction for 2 min windows - if (!HasEffect(Buffs.ArcaneCircle) && !IsDebuffExpiring(5) && - gauge.Soul >= 90) - return true; - } - return false; + //Natural Odd Minute Shrouds + if (!HasEffect(Buffs.ArcaneCircle) && !IsDebuffExpiring(5) && + GetCooldownRemainingTime(ArcaneCircle) is >= 50 and <= 65) + return true; + + // Correction for 2 min windows + if (!HasEffect(Buffs.ArcaneCircle) && !IsDebuffExpiring(5) && + gauge.Soul >= 90) + return true; } - public static bool UseShadowOfDeath() - { - float GCD = GetCooldown(Slice).CooldownTotal; + return false; + } - if (LevelChecked(ShadowOfDeath) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && - !HasEffect(Buffs.ImmortalSacrifice) && !IsComboExpiring(1) && !JustUsed(Perfectio) && !JustUsed(ShadowOfDeath)) - { - if (LevelChecked(PlentifulHarvest) && HasEffect(Buffs.Enshrouded) && - GetCooldownRemainingTime(ArcaneCircle) <= (GCD * 2) + 1.5 && JustUsed(Enshroud)) - return true; + public static bool UseShadowOfDeath() + { + float GCD = GetCooldown(Slice).CooldownTotal; - if (LevelChecked(PlentifulHarvest) && HasEffect(Buffs.Enshrouded) && - ((GetCooldownRemainingTime(ArcaneCircle) <= GCD) || IsOffCooldown(ArcaneCircle)) && - (JustUsed(VoidReaping) || JustUsed(CrossReaping))) - return true; + if (LevelChecked(ShadowOfDeath) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && + !HasEffect(Buffs.ImmortalSacrifice) && !IsComboExpiring(1) && !JustUsed(Perfectio) && + !JustUsed(ShadowOfDeath)) + { + if (LevelChecked(PlentifulHarvest) && HasEffect(Buffs.Enshrouded) && + GetCooldownRemainingTime(ArcaneCircle) <= GCD * 2 + 1.5 && JustUsed(Enshroud)) + return true; - if (!HasEffect(Buffs.Enshrouded) && - ((IsEnabled(CustomComboPreset.RPR_ST_SimpleMode) && GetDebuffRemainingTime(Debuffs.DeathsDesign) <= 8) || - (IsEnabled(CustomComboPreset.RPR_ST_AdvancedMode) && GetDebuffRemainingTime(Debuffs.DeathsDesign) <= Config.RPR_SoDRefreshRange)) && - ((GetCooldownRemainingTime(ArcaneCircle) > GCD * 8) || IsOffCooldown(ArcaneCircle) || !LevelChecked(ArcaneCircle))) - return true; + if (LevelChecked(PlentifulHarvest) && HasEffect(Buffs.Enshrouded) && + (GetCooldownRemainingTime(ArcaneCircle) <= GCD || IsOffCooldown(ArcaneCircle)) && + (JustUsed(VoidReaping) || JustUsed(CrossReaping))) + return true; - } - return false; + if (!HasEffect(Buffs.Enshrouded) && + ((IsEnabled(CustomComboPreset.RPR_ST_SimpleMode) && + GetDebuffRemainingTime(Debuffs.DeathsDesign) <= 8) || + (IsEnabled(CustomComboPreset.RPR_ST_AdvancedMode) && + GetDebuffRemainingTime(Debuffs.DeathsDesign) <= Config.RPR_SoDRefreshRange)) && + (GetCooldownRemainingTime(ArcaneCircle) > GCD * 8 || IsOffCooldown(ArcaneCircle) || + !LevelChecked(ArcaneCircle))) + return true; } + + return false; } } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG.cs index 0bc7670e7..503e4e005 100644 --- a/XIVSlothCombo/Combos/PvE/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG.cs @@ -5,773 +5,776 @@ using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Extensions; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE +namespace XIVSlothCombo.Combos.PvE; + +internal class DRG { - internal class DRG + public const byte ClassID = 4; + public const byte JobID = 22; + + public const uint + PiercingTalon = 90, + ElusiveJump = 94, + LanceCharge = 85, + BattleLitany = 3557, + Jump = 92, + LifeSurge = 83, + HighJump = 16478, + MirageDive = 7399, + BloodOfTheDragon = 3553, + Stardiver = 16480, + CoerthanTorment = 16477, + DoomSpike = 86, + SonicThrust = 7397, + ChaosThrust = 88, + RaidenThrust = 16479, + TrueThrust = 75, + Disembowel = 87, + FangAndClaw = 3554, + WheelingThrust = 3556, + FullThrust = 84, + VorpalThrust = 78, + WyrmwindThrust = 25773, + DraconianFury = 25770, + ChaoticSpring = 25772, + DragonfireDive = 96, + Geirskogul = 3555, + Nastrond = 7400, + HeavensThrust = 25771, + Drakesbane = 36952, + RiseOfTheDragon = 36953, + LanceBarrage = 36954, + SpiralBlow = 36955, + Starcross = 36956; + + protected static DRGGauge? Gauge = GetJobGauge(); + + public static class Buffs + { + public const ushort + LanceCharge = 1864, + BattleLitany = 786, + DiveReady = 1243, + RaidenThrustReady = 1863, + PowerSurge = 2720, + LifeSurge = 116, + DraconianFire = 1863, + NastrondReady = 3844, + StarcrossReady = 3846, + DragonsFlight = 3845; + } + + public static class Debuffs { - public const byte ClassID = 4; - public const byte JobID = 22; + public const ushort + ChaosThrust = 118, + ChaoticSpring = 2719; + } + public static class Traits + { public const uint - PiercingTalon = 90, - ElusiveJump = 94, - LanceCharge = 85, - BattleLitany = 3557, - Jump = 92, - LifeSurge = 83, - HighJump = 16478, - MirageDive = 7399, - BloodOfTheDragon = 3553, - Stardiver = 16480, - CoerthanTorment = 16477, - DoomSpike = 86, - SonicThrust = 7397, - ChaosThrust = 88, - RaidenThrust = 16479, - TrueThrust = 75, - Disembowel = 87, - FangAndClaw = 3554, - WheelingThrust = 3556, - FullThrust = 84, - VorpalThrust = 78, - WyrmwindThrust = 25773, - DraconianFury = 25770, - ChaoticSpring = 25772, - DragonfireDive = 96, - Geirskogul = 3555, - Nastrond = 7400, - HeavensThrust = 25771, - Drakesbane = 36952, - RiseOfTheDragon = 36953, - LanceBarrage = 36954, - SpiralBlow = 36955, - Starcross = 36956; - - public static class Buffs - { - public const ushort - LanceCharge = 1864, - BattleLitany = 786, - DiveReady = 1243, - RaidenThrustReady = 1863, - PowerSurge = 2720, - LifeSurge = 116, - DraconianFire = 1863, - NastrondReady = 3844, - StarcrossReady = 3846, - DragonsFlight = 3845; - } + EnhancedLifeSurge = 438; + } - public static class Debuffs - { - public const ushort - ChaosThrust = 118, - ChaoticSpring = 2719; - } + public static class Config + { + public static UserInt + DRG_Variant_Cure = new("DRG_VariantCure"), + DRG_ST_LitanyHP = new("DRG_ST_LitanyHP", 2), + DRG_ST_SightHP = new("DRG_ST_SightHP", 2), + DRG_ST_LanceChargeHP = new("DRG_ST_LanceChargeHP", 2), + DRG_ST_SecondWind_Threshold = new("DRG_STSecondWindThreshold", 25), + DRG_ST_Bloodbath_Threshold = new("DRG_STBloodbathThreshold", 40), + DRG_AoE_LitanyHP = new("DRG_AoE_LitanyHP", 5), + DRG_AoE_SightHP = new("DRG_AoE_SightHP", 5), + DRG_AoE_LanceChargeHP = new("DRG_AoE_LanceChargeHP", 5), + DRG_AoE_SecondWind_Threshold = new("DRG_AoE_SecondWindThreshold", 25), + DRG_AoE_Bloodbath_Threshold = new("DRG_AoE_BloodbathThreshold", 40); + } - public static class Traits - { - public const uint - EnhancedLifeSurge = 438; - } + internal class DRG_ST_SimpleMode : CustomCombo + { + internal static DRGOpenerLogic DRGOpener = new(); - public static class Config - { - public static UserInt - DRG_Variant_Cure = new("DRG_VariantCure"), - DRG_ST_LitanyHP = new("DRG_ST_LitanyHP", 2), - DRG_ST_SightHP = new("DRG_ST_SightHP", 2), - DRG_ST_LanceChargeHP = new("DRG_ST_LanceChargeHP", 2), - DRG_ST_SecondWind_Threshold = new("DRG_STSecondWindThreshold", 25), - DRG_ST_Bloodbath_Threshold = new("DRG_STBloodbathThreshold", 40), - DRG_AoE_LitanyHP = new("DRG_AoE_LitanyHP", 5), - DRG_AoE_SightHP = new("DRG_AoE_SightHP", 5), - DRG_AoE_LanceChargeHP = new("DRG_AoE_LanceChargeHP", 5), - DRG_AoE_SecondWind_Threshold = new("DRG_AoE_SecondWindThreshold", 25), - DRG_AoE_Bloodbath_Threshold = new("DRG_AoE_BloodbathThreshold", 40); - } + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_ST_SimpleMode; - internal class DRG_ST_SimpleMode : CustomCombo + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_ST_SimpleMode; - internal static DRGOpenerLogic DRGOpener = new(); + Status? ChaosDoTDebuff; + + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); + + if (LevelChecked(ChaoticSpring)) + ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaoticSpring); + else ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaosThrust); - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is TrueThrust) { - DRGGauge? gauge = GetJobGauge(); - Status? ChaosDoTDebuff; - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth); + if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + AnimationLock.CanDRGWeave(Variant.VariantRampart)) + return Variant.VariantRampart; + + // Opener for DRG + if (DRGOpener.DoFullOpener(ref actionID)) + return actionID; + + // Piercing Talon Uptime Option + if (LevelChecked(PiercingTalon) && + !InMeleeRange() && + HasBattleTarget()) + return PiercingTalon; + + if (HasEffect(Buffs.PowerSurge)) + { + //Lance Charge Feature + if (ActionReady(LanceCharge) && + AnimationLock.CanDRGWeave(LanceCharge)) + return LanceCharge; + + //Battle Litany Feature + if (ActionReady(BattleLitany) && + AnimationLock.CanDRGWeave(BattleLitany)) + return BattleLitany; - if (LevelChecked(ChaoticSpring)) - ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaoticSpring); - else ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaosThrust); + //Life Surge Feature + if (ActionReady(LifeSurge) && + (GetCooldownRemainingTime(LifeSurge) < 40 || GetCooldownRemainingTime(BattleLitany) > 50) && + AnimationLock.CanDRGWeave(LifeSurge) && + HasEffect(Buffs.LanceCharge) && + !HasEffect(Buffs.LifeSurge) && + ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || + (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || + (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) + return LifeSurge; + + //Geirskogul Feature + if (ActionReady(Geirskogul) && + AnimationLock.CanDRGWeave(Geirskogul)) + return Geirskogul; + + //Dragonfire Dive Feature + if (ActionReady(DragonfireDive) && + AnimationLock.CanDRGWeave(DragonfireDive) && + !IsMoving) + return DragonfireDive; + + //(High) Jump Feature + if (ActionReady(OriginalHook(Jump)) && + AnimationLock.CanDRGWeave(OriginalHook(Jump)) && + !IsMoving) + return OriginalHook(Jump); + + //Wyrmwind Thrust Feature + if (LevelChecked(WyrmwindThrust) && + AnimationLock.CanDRGWeave(WyrmwindThrust) && + Gauge.FirstmindsFocusCount is 2) + return WyrmwindThrust; + + //StarDiver Feature + if (ActionReady(Stardiver) && + AnimationLock.CanDRGWeave(Stardiver) && + Gauge.IsLOTDActive && !IsMoving) + return Stardiver; + + //Starcross Feature + if (LevelChecked(Starcross) && + AnimationLock.CanDRGWeave(Starcross) && + HasEffect(Buffs.StarcrossReady)) + return Starcross; + + //Rise of the Dragon Feature + if (LevelChecked(RiseOfTheDragon) && + AnimationLock.CanDRGWeave(RiseOfTheDragon) && + HasEffect(Buffs.DragonsFlight)) + return RiseOfTheDragon; + + //Nastrond Feature + if (LevelChecked(Nastrond) && + AnimationLock.CanDRGWeave(Nastrond) && + HasEffect(Buffs.NastrondReady) && + Gauge.IsLOTDActive) + return Nastrond; + + //Mirage Feature + if (LevelChecked(MirageDive) && + AnimationLock.CanDRGWeave(MirageDive) && + HasEffect(Buffs.DiveReady)) + return MirageDive; + } - if (actionID is TrueThrust) + //1-2-3 Combo + if (comboTime > 0) { - if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - AnimationLock.CanDRGWeave(Variant.VariantRampart)) - return Variant.VariantRampart; - - // Opener for DRG + if (lastComboMove is TrueThrust or RaidenThrust && LevelChecked(VorpalThrust)) + return LevelChecked(Disembowel) && + ((ChaosDoTDebuff is null && LevelChecked(ChaosThrust)) || + GetBuffRemainingTime(Buffs.PowerSurge) < 15) + ? OriginalHook(Disembowel) + : OriginalHook(VorpalThrust); + + if (lastComboMove == OriginalHook(Disembowel) && LevelChecked(ChaosThrust)) + { + if (trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && + !OnTargetsRear()) + return All.TrueNorth; + + return OriginalHook(ChaosThrust); + } + + if (lastComboMove == OriginalHook(ChaosThrust) && LevelChecked(WheelingThrust)) + { + if (trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && + !OnTargetsRear()) + return All.TrueNorth; + + return WheelingThrust; + } + + if (lastComboMove == OriginalHook(VorpalThrust) && LevelChecked(FullThrust)) + return OriginalHook(FullThrust); + + if (lastComboMove == OriginalHook(FullThrust) && LevelChecked(FangAndClaw)) + { + if (trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && + !OnTargetsFlank()) + return All.TrueNorth; + + return FangAndClaw; + } + + if (lastComboMove is WheelingThrust or FangAndClaw && LevelChecked(Drakesbane)) + return Drakesbane; + } + + return OriginalHook(TrueThrust); + } + + return actionID; + } + } + + internal class DRG_ST_AdvancedMode : CustomCombo + { + internal static DRGOpenerLogic DRGOpener = new(); + + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_ST_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + Status? ChaosDoTDebuff; + + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); + + if (LevelChecked(ChaoticSpring)) + ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaoticSpring); + else ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaosThrust); + + if (actionID is TrueThrust) + { + if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + AnimationLock.CanDRGWeave(Variant.VariantRampart)) + return Variant.VariantRampart; + + // Opener for DRG + if (IsEnabled(CustomComboPreset.DRG_ST_Opener)) if (DRGOpener.DoFullOpener(ref actionID)) return actionID; - // Piercing Talon Uptime Option - if (LevelChecked(PiercingTalon) && - !InMeleeRange() && - HasBattleTarget()) - return PiercingTalon; + // Piercing Talon Uptime Option + if (IsEnabled(CustomComboPreset.DRG_ST_RangedUptime) && + LevelChecked(PiercingTalon) && !InMeleeRange() && HasBattleTarget()) + return PiercingTalon; - if (HasEffect(Buffs.PowerSurge)) + if (HasEffect(Buffs.PowerSurge)) + { + if (IsEnabled(CustomComboPreset.DRG_ST_Buffs)) { //Lance Charge Feature - if (ActionReady(LanceCharge) && - AnimationLock.CanDRGWeave(LanceCharge)) + if (IsEnabled(CustomComboPreset.DRG_ST_Lance) && + ActionReady(LanceCharge) && + AnimationLock.CanDRGWeave(LanceCharge) && + GetTargetHPPercent() >= Config.DRG_ST_LanceChargeHP) return LanceCharge; //Battle Litany Feature - if (ActionReady(BattleLitany) && - AnimationLock.CanDRGWeave(BattleLitany)) + if (IsEnabled(CustomComboPreset.DRG_ST_Litany) && + ActionReady(BattleLitany) && + AnimationLock.CanDRGWeave(BattleLitany) && + GetTargetHPPercent() >= Config.DRG_ST_LitanyHP) return BattleLitany; + } + if (IsEnabled(CustomComboPreset.DRG_ST_CDs)) + { //Life Surge Feature - if (ActionReady(LifeSurge) && - ((GetCooldownRemainingTime(LifeSurge) < 40) || (GetCooldownRemainingTime(BattleLitany) > 50)) && + if (IsEnabled(CustomComboPreset.DRG_ST_LifeSurge) && + ActionReady(LifeSurge) && + (GetCooldownRemainingTime(LifeSurge) < 40 || GetCooldownRemainingTime(BattleLitany) > 50) && AnimationLock.CanDRGWeave(LifeSurge) && HasEffect(Buffs.LanceCharge) && !HasEffect(Buffs.LifeSurge) && ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || - (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || - (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) + (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || + (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) return LifeSurge; //Geirskogul Feature - if (ActionReady(Geirskogul) && + if (IsEnabled(CustomComboPreset.DRG_ST_Geirskogul) && + ActionReady(Geirskogul) && AnimationLock.CanDRGWeave(Geirskogul)) return Geirskogul; //Dragonfire Dive Feature - if (ActionReady(DragonfireDive) && + if (IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive) && + ActionReady(DragonfireDive) && AnimationLock.CanDRGWeave(DragonfireDive) && - !IsMoving) + (!IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive_Movement) || + (IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive_Movement) && !IsMoving))) return DragonfireDive; //(High) Jump Feature - if (ActionReady(OriginalHook(Jump)) && + if (IsEnabled(CustomComboPreset.DRG_ST_HighJump) && + ActionReady(OriginalHook(Jump)) && AnimationLock.CanDRGWeave(OriginalHook(Jump)) && - !IsMoving) + (!IsEnabled(CustomComboPreset.DRG_ST_HighJump_Movement) || + (IsEnabled(CustomComboPreset.DRG_ST_HighJump_Movement) && !IsMoving))) return OriginalHook(Jump); //Wyrmwind Thrust Feature - if (LevelChecked(WyrmwindThrust) && + if (IsEnabled(CustomComboPreset.DRG_ST_Wyrmwind) && + LevelChecked(WyrmwindThrust) && AnimationLock.CanDRGWeave(WyrmwindThrust) && - gauge.FirstmindsFocusCount is 2) + Gauge.FirstmindsFocusCount is 2) return WyrmwindThrust; //StarDiver Feature - if (ActionReady(Stardiver) && + if (IsEnabled(CustomComboPreset.DRG_ST_Stardiver) && + ActionReady(Stardiver) && AnimationLock.CanDRGWeave(Stardiver) && - gauge.IsLOTDActive && !IsMoving) + Gauge.IsLOTDActive && + (!IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) || + (IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) && !IsMoving))) return Stardiver; //Starcross Feature - if (LevelChecked(Starcross) && + if (IsEnabled(CustomComboPreset.DRG_ST_Starcross) && + LevelChecked(Starcross) && AnimationLock.CanDRGWeave(Starcross) && HasEffect(Buffs.StarcrossReady)) return Starcross; //Rise of the Dragon Feature - if (LevelChecked(RiseOfTheDragon) && + if (IsEnabled(CustomComboPreset.DRG_ST_Dives_RiseOfTheDragon) && AnimationLock.CanDRGWeave(RiseOfTheDragon) && HasEffect(Buffs.DragonsFlight)) return RiseOfTheDragon; //Nastrond Feature - if (LevelChecked(Nastrond) && + if (IsEnabled(CustomComboPreset.DRG_ST_Nastrond) && + LevelChecked(Nastrond) && AnimationLock.CanDRGWeave(Nastrond) && HasEffect(Buffs.NastrondReady) && - gauge.IsLOTDActive) + Gauge.IsLOTDActive) return Nastrond; //Mirage Feature - if (LevelChecked(MirageDive) && + if (IsEnabled(CustomComboPreset.DRG_ST_Mirage) && + LevelChecked(MirageDive) && AnimationLock.CanDRGWeave(MirageDive) && HasEffect(Buffs.DiveReady)) return MirageDive; } + } - //1-2-3 Combo - if (comboTime > 0) - { - if (lastComboMove is TrueThrust or RaidenThrust && LevelChecked(VorpalThrust)) - { - return (LevelChecked(Disembowel) && - (((ChaosDoTDebuff is null) && LevelChecked(ChaosThrust)) || - GetBuffRemainingTime(Buffs.PowerSurge) < 15)) - ? OriginalHook(Disembowel) - : OriginalHook(VorpalThrust); - } - - if (lastComboMove == OriginalHook(Disembowel) && LevelChecked(ChaosThrust)) - { - if (trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && - !OnTargetsRear()) - return All.TrueNorth; + // healing + if (IsEnabled(CustomComboPreset.DRG_ST_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.DRG_ST_SecondWind_Threshold && ActionReady(All.SecondWind)) + return All.SecondWind; - return OriginalHook(ChaosThrust); - } + if (PlayerHealthPercentageHp() <= Config.DRG_ST_Bloodbath_Threshold && ActionReady(All.Bloodbath)) + return All.Bloodbath; + } + + //1-2-3 Combo + if (comboTime > 0) + { + if (lastComboMove is TrueThrust or RaidenThrust && LevelChecked(VorpalThrust)) + return LevelChecked(Disembowel) && + ((ChaosDoTDebuff is null && LevelChecked(ChaosThrust)) || + GetBuffRemainingTime(Buffs.PowerSurge) < 15) + ? OriginalHook(Disembowel) + : OriginalHook(VorpalThrust); + + if (lastComboMove == OriginalHook(Disembowel) && LevelChecked(ChaosThrust)) + { + if (IsEnabled(CustomComboPreset.DRG_TrueNorthDynamic) && + trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && + !OnTargetsRear()) + return All.TrueNorth; - if (lastComboMove == OriginalHook(ChaosThrust) && LevelChecked(WheelingThrust)) - { - if (trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && - !OnTargetsRear()) - return All.TrueNorth; + return OriginalHook(ChaosThrust); + } - return WheelingThrust; - } + if (lastComboMove == OriginalHook(ChaosThrust) && LevelChecked(WheelingThrust)) + { + if (IsEnabled(CustomComboPreset.DRG_TrueNorthDynamic) && + trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && + !OnTargetsRear()) + return All.TrueNorth; - if (lastComboMove == OriginalHook(VorpalThrust) && LevelChecked(FullThrust)) - return OriginalHook(FullThrust); + return WheelingThrust; + } - if (lastComboMove == OriginalHook(FullThrust) && LevelChecked(FangAndClaw)) - { - if (trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && - !OnTargetsFlank()) - return All.TrueNorth; + if (lastComboMove == OriginalHook(VorpalThrust) && LevelChecked(FullThrust)) + return OriginalHook(FullThrust); - return FangAndClaw; - } + if (lastComboMove == OriginalHook(FullThrust) && LevelChecked(FangAndClaw)) + { + if (IsEnabled(CustomComboPreset.DRG_TrueNorthDynamic) && + trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && + !OnTargetsFlank()) + return All.TrueNorth; - if (lastComboMove is WheelingThrust or FangAndClaw && LevelChecked(Drakesbane)) - return Drakesbane; + return FangAndClaw; } - return OriginalHook(TrueThrust); + + if (lastComboMove is WheelingThrust or FangAndClaw && LevelChecked(Drakesbane)) + return Drakesbane; } - return actionID; + + return OriginalHook(TrueThrust); } + + return actionID; } + } - internal class DRG_ST_AdvancedMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_ST_AdvancedMode; - internal static DRGOpenerLogic DRGOpener = new(); + internal class DRG_AOE_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_AOE_SimpleMode; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is DoomSpike) { - DRGGauge? gauge = GetJobGauge(); - Status? ChaosDoTDebuff; - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth); - - if (LevelChecked(ChaoticSpring)) - ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaoticSpring); - else ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaosThrust); - - if (actionID is TrueThrust) + if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + AnimationLock.CanDRGWeave(Variant.VariantRampart)) + return Variant.VariantRampart; + + // Piercing Talon Uptime Option + if (LevelChecked(PiercingTalon) && !InMeleeRange() && HasBattleTarget()) + return PiercingTalon; + + if (HasEffect(Buffs.PowerSurge)) { - if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - AnimationLock.CanDRGWeave(Variant.VariantRampart)) - return Variant.VariantRampart; - - // Opener for DRG - if (IsEnabled(CustomComboPreset.DRG_ST_Opener)) - { - if (DRGOpener.DoFullOpener(ref actionID)) - return actionID; - } - - // Piercing Talon Uptime Option - if (IsEnabled(CustomComboPreset.DRG_ST_RangedUptime) && - LevelChecked(PiercingTalon) && !InMeleeRange() && HasBattleTarget()) - return PiercingTalon; + //Lance Charge Feature + if (ActionReady(LanceCharge) && + AnimationLock.CanDRGWeave(LanceCharge)) + return LanceCharge; + + //Battle Litany Feature + if (ActionReady(BattleLitany) && + AnimationLock.CanDRGWeave(BattleLitany)) + return BattleLitany; - if (HasEffect(Buffs.PowerSurge)) - { - if (IsEnabled(CustomComboPreset.DRG_ST_Buffs)) - { - //Lance Charge Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Lance) && - ActionReady(LanceCharge) && - AnimationLock.CanDRGWeave(LanceCharge) && - GetTargetHPPercent() >= Config.DRG_ST_LanceChargeHP) - return LanceCharge; - - //Battle Litany Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Litany) && - ActionReady(BattleLitany) && - AnimationLock.CanDRGWeave(BattleLitany) && - GetTargetHPPercent() >= Config.DRG_ST_LitanyHP) - return BattleLitany; - } - - if (IsEnabled(CustomComboPreset.DRG_ST_CDs)) - { - //Life Surge Feature - if (IsEnabled(CustomComboPreset.DRG_ST_LifeSurge) && - ActionReady(LifeSurge) && - ((GetCooldownRemainingTime(LifeSurge) < 40) || (GetCooldownRemainingTime(BattleLitany) > 50)) && - AnimationLock.CanDRGWeave(LifeSurge) && - HasEffect(Buffs.LanceCharge) && - !HasEffect(Buffs.LifeSurge) && - ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || - (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || - (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) - return LifeSurge; - - //Geirskogul Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Geirskogul) && - ActionReady(Geirskogul) && - AnimationLock.CanDRGWeave(Geirskogul)) - return Geirskogul; - - //Dragonfire Dive Feature - if (IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive) && - ActionReady(DragonfireDive) && - AnimationLock.CanDRGWeave(DragonfireDive) && - (!IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive_Movement) || - (IsEnabled(CustomComboPreset.DRG_ST_DragonfireDive_Movement) && !IsMoving))) - return DragonfireDive; - - //(High) Jump Feature - if (IsEnabled(CustomComboPreset.DRG_ST_HighJump) && - ActionReady(OriginalHook(Jump)) && - AnimationLock.CanDRGWeave(OriginalHook(Jump)) && - (!IsEnabled(CustomComboPreset.DRG_ST_HighJump_Movement) || - (IsEnabled(CustomComboPreset.DRG_ST_HighJump_Movement) && !IsMoving))) - return OriginalHook(Jump); - - //Wyrmwind Thrust Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Wyrmwind) && - LevelChecked(WyrmwindThrust) && - AnimationLock.CanDRGWeave(WyrmwindThrust) && - gauge.FirstmindsFocusCount is 2) - return WyrmwindThrust; - - //StarDiver Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Stardiver) && - ActionReady(Stardiver) && - AnimationLock.CanDRGWeave(Stardiver) && - gauge.IsLOTDActive && - (!IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) || - (IsEnabled(CustomComboPreset.DRG_ST_Stardiver_Movement) && !IsMoving))) - return Stardiver; - - //Starcross Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Starcross) && - LevelChecked(Starcross) && - AnimationLock.CanDRGWeave(Starcross) && - HasEffect(Buffs.StarcrossReady)) - return Starcross; - - //Rise of the Dragon Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Dives_RiseOfTheDragon) && - AnimationLock.CanDRGWeave(RiseOfTheDragon) && - HasEffect(Buffs.DragonsFlight)) - return RiseOfTheDragon; - - //Nastrond Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Nastrond) && - LevelChecked(Nastrond) && - AnimationLock.CanDRGWeave(Nastrond) && - HasEffect(Buffs.NastrondReady) && - gauge.IsLOTDActive) - return Nastrond; - - //Mirage Feature - if (IsEnabled(CustomComboPreset.DRG_ST_Mirage) && - LevelChecked(MirageDive) && - AnimationLock.CanDRGWeave(MirageDive) && - HasEffect(Buffs.DiveReady)) - return MirageDive; - } - } + //Life Surge Feature + if (ActionReady(LifeSurge) && + AnimationLock.CanDRGWeave(LifeSurge) && + !HasEffect(Buffs.LifeSurge) && + ((JustUsed(SonicThrust) && LevelChecked(CoerthanTorment)) || + (JustUsed(DoomSpike) && LevelChecked(SonicThrust)) || + (JustUsed(DoomSpike) && !LevelChecked(SonicThrust)))) + return LifeSurge; + + //Wyrmwind Thrust Feature + if (LevelChecked(WyrmwindThrust) && + AnimationLock.CanDRGWeave(WyrmwindThrust) && + Gauge.FirstmindsFocusCount is 2) + return WyrmwindThrust; + + //Geirskogul Feature + if (ActionReady(Geirskogul) && + AnimationLock.CanDRGWeave(Geirskogul)) + return Geirskogul; + + //(High) Jump Feature + if (ActionReady(OriginalHook(Jump)) && + AnimationLock.CanDRGWeave(OriginalHook(Jump)) && + !IsMoving) + return OriginalHook(Jump); + + //Dragonfire Dive Feature + if (ActionReady(DragonfireDive) && + AnimationLock.CanDRGWeave(DragonfireDive) && + !IsMoving) + return DragonfireDive; + + //StarDiver Feature + if (ActionReady(Stardiver) && + AnimationLock.CanDRGWeave(Stardiver) && + Gauge.IsLOTDActive && !IsMoving) + return Stardiver; + + //Starcross Feature + if (LevelChecked(Starcross) && + AnimationLock.CanDRGWeave(Starcross) && + HasEffect(Buffs.StarcrossReady)) + return OriginalHook(Stardiver); + + //Rise of the Dragon Feature + if (LevelChecked(RiseOfTheDragon) && + AnimationLock.CanDRGWeave(RiseOfTheDragon) && + HasEffect(Buffs.DragonsFlight)) + return OriginalHook(DragonfireDive); + + //Mirage Feature + if (LevelChecked(MirageDive) && + AnimationLock.CanDRGWeave(MirageDive) && + HasEffect(Buffs.DiveReady)) + return OriginalHook(HighJump); + + //Nastrond Feature + if (LevelChecked(Nastrond) && + AnimationLock.CanDRGWeave(Nastrond) && + HasEffect(Buffs.NastrondReady) && + Gauge.IsLOTDActive) + return OriginalHook(Geirskogul); + } - // healing - if (IsEnabled(CustomComboPreset.DRG_ST_ComboHeals)) + if (comboTime > 0) + { + if (!SonicThrust.LevelChecked()) { - if (PlayerHealthPercentageHp() <= Config.DRG_ST_SecondWind_Threshold && ActionReady(All.SecondWind)) - return All.SecondWind; + if (lastComboMove == TrueThrust && LevelChecked(Disembowel)) + return Disembowel; - if (PlayerHealthPercentageHp() <= Config.DRG_ST_Bloodbath_Threshold && ActionReady(All.Bloodbath)) - return All.Bloodbath; + if (lastComboMove == Disembowel && LevelChecked(ChaosThrust)) + return OriginalHook(ChaosThrust); } - //1-2-3 Combo - if (comboTime > 0) + else { - if (lastComboMove is TrueThrust or RaidenThrust && LevelChecked(VorpalThrust)) - { - return (LevelChecked(Disembowel) && - (((ChaosDoTDebuff is null) && LevelChecked(ChaosThrust)) || - GetBuffRemainingTime(Buffs.PowerSurge) < 15)) - ? OriginalHook(Disembowel) - : OriginalHook(VorpalThrust); - } - - if (lastComboMove == OriginalHook(Disembowel) && LevelChecked(ChaosThrust)) - { - if (IsEnabled(CustomComboPreset.DRG_TrueNorthDynamic) && - trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && - !OnTargetsRear()) - return All.TrueNorth; - - return OriginalHook(ChaosThrust); - } - - if (lastComboMove == OriginalHook(ChaosThrust) && LevelChecked(WheelingThrust)) - { - if (IsEnabled(CustomComboPreset.DRG_TrueNorthDynamic) && - trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && - !OnTargetsRear()) - return All.TrueNorth; - - return WheelingThrust; - } + if (lastComboMove is DoomSpike or DraconianFury && LevelChecked(SonicThrust)) + return SonicThrust; - if (lastComboMove == OriginalHook(VorpalThrust) && LevelChecked(FullThrust)) - return OriginalHook(FullThrust); - - if (lastComboMove == OriginalHook(FullThrust) && LevelChecked(FangAndClaw)) - { - if (IsEnabled(CustomComboPreset.DRG_TrueNorthDynamic) && - trueNorthReady && AnimationLock.CanDRGWeave(All.TrueNorth) && - !OnTargetsFlank()) - return All.TrueNorth; - - return FangAndClaw; - } - - if (lastComboMove is WheelingThrust or FangAndClaw && LevelChecked(Drakesbane)) - return Drakesbane; + if (lastComboMove == SonicThrust && LevelChecked(CoerthanTorment)) + return CoerthanTorment; } - return OriginalHook(TrueThrust); } - return actionID; + + return !HasEffect(Buffs.PowerSurge) && !LevelChecked(SonicThrust) + ? OriginalHook(TrueThrust) + : OriginalHook(DoomSpike); } + + return actionID; } + } - internal class DRG_AOE_SimpleMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_AOE_SimpleMode; + internal class DRG_AOE_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_AOE_AdvancedMode; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is DoomSpike) { - DRGGauge? gauge = GetJobGauge(); - - if (actionID is DoomSpike) + if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + AnimationLock.CanDRGWeave(Variant.VariantRampart)) + return Variant.VariantRampart; + + // Piercing Talon Uptime Option + if (IsEnabled(CustomComboPreset.DRG_AoE_RangedUptime) && + LevelChecked(PiercingTalon) && !InMeleeRange() && HasBattleTarget()) + return PiercingTalon; + + if (HasEffect(Buffs.PowerSurge)) { - if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - AnimationLock.CanDRGWeave(Variant.VariantRampart)) - return Variant.VariantRampart; - - // Piercing Talon Uptime Option - if (LevelChecked(PiercingTalon) && !InMeleeRange() && HasBattleTarget()) - return PiercingTalon; - - if (HasEffect(Buffs.PowerSurge)) + if (IsEnabled(CustomComboPreset.DRG_AoE_Buffs)) { //Lance Charge Feature - if (ActionReady(LanceCharge) && - AnimationLock.CanDRGWeave(LanceCharge)) + if (IsEnabled(CustomComboPreset.DRG_AoE_Lance) && + ActionReady(LanceCharge) && + AnimationLock.CanDRGWeave(LanceCharge) && + GetTargetHPPercent() >= Config.DRG_AoE_LanceChargeHP) return LanceCharge; //Battle Litany Feature - if (ActionReady(BattleLitany) && - AnimationLock.CanDRGWeave(BattleLitany)) + if (IsEnabled(CustomComboPreset.DRG_AoE_Litany) && + ActionReady(BattleLitany) && + AnimationLock.CanDRGWeave(BattleLitany) && + GetTargetHPPercent() >= Config.DRG_AoE_LitanyHP) return BattleLitany; + } + if (IsEnabled(CustomComboPreset.DRG_AoE_CDs)) + { //Life Surge Feature - if (ActionReady(LifeSurge) && - AnimationLock.CanDRGWeave(LifeSurge) && - !HasEffect(Buffs.LifeSurge) && + if (IsEnabled(CustomComboPreset.DRG_AoE_LifeSurge) && + ActionReady(LifeSurge) && + AnimationLock.CanDRGWeave(LifeSurge) && !HasEffect(Buffs.LifeSurge) && ((JustUsed(SonicThrust) && LevelChecked(CoerthanTorment)) || - (JustUsed(DoomSpike) && LevelChecked(SonicThrust)) || - (JustUsed(DoomSpike) && !LevelChecked(SonicThrust)))) + (JustUsed(DoomSpike) && LevelChecked(SonicThrust)) || + (JustUsed(DoomSpike) && !LevelChecked(SonicThrust)))) return LifeSurge; //Wyrmwind Thrust Feature - if (LevelChecked(WyrmwindThrust) && + if (IsEnabled(CustomComboPreset.DRG_AoE_Wyrmwind) && + LevelChecked(WyrmwindThrust) && AnimationLock.CanDRGWeave(WyrmwindThrust) && - gauge.FirstmindsFocusCount is 2) + Gauge.FirstmindsFocusCount is 2) return WyrmwindThrust; //Geirskogul Feature - if (ActionReady(Geirskogul) && + if (IsEnabled(CustomComboPreset.DRG_AoE_Geirskogul) && + ActionReady(Geirskogul) && AnimationLock.CanDRGWeave(Geirskogul)) return Geirskogul; //(High) Jump Feature - if (ActionReady(OriginalHook(Jump)) && + if (IsEnabled(CustomComboPreset.DRG_AoE_HighJump) && + ActionReady(OriginalHook(Jump)) && AnimationLock.CanDRGWeave(OriginalHook(Jump)) && - !IsMoving) + (!IsEnabled(CustomComboPreset.DRG_AoE_HighJump_Movement) || + (IsEnabled(CustomComboPreset.DRG_AoE_HighJump_Movement) && !IsMoving))) return OriginalHook(Jump); //Dragonfire Dive Feature - if (ActionReady(DragonfireDive) && + if (IsEnabled(CustomComboPreset.DRG_AoE_DragonfireDive) && + ActionReady(DragonfireDive) && AnimationLock.CanDRGWeave(DragonfireDive) && - !IsMoving) + (!IsEnabled(CustomComboPreset.DRG_AoE_DragonfireDive_Movement) || + (IsEnabled(CustomComboPreset.DRG_AoE_DragonfireDive_Movement) && !IsMoving))) return DragonfireDive; //StarDiver Feature - if (ActionReady(Stardiver) && + if (IsEnabled(CustomComboPreset.DRG_AoE_Stardiver) && + ActionReady(Stardiver) && AnimationLock.CanDRGWeave(Stardiver) && - gauge.IsLOTDActive && !IsMoving) + Gauge.IsLOTDActive && + (!IsEnabled(CustomComboPreset.DRG_AoE_Stardiver_Movement) || + (IsEnabled(CustomComboPreset.DRG_AoE_Stardiver_Movement) && !IsMoving))) return Stardiver; //Starcross Feature - if (LevelChecked(Starcross) && + if (IsEnabled(CustomComboPreset.DRG_AoE_Starcross) && + LevelChecked(Starcross) && AnimationLock.CanDRGWeave(Starcross) && HasEffect(Buffs.StarcrossReady)) return OriginalHook(Stardiver); //Rise of the Dragon Feature - if (LevelChecked(RiseOfTheDragon) && + if (IsEnabled(CustomComboPreset.DRG_AoE_RiseOfTheDragon) && + LevelChecked(RiseOfTheDragon) && AnimationLock.CanDRGWeave(RiseOfTheDragon) && - HasEffect(Buffs.DragonsFlight)) + HasEffect(Buffs.DragonsFlight)) return OriginalHook(DragonfireDive); //Mirage Feature - if (LevelChecked(MirageDive) && + if (IsEnabled(CustomComboPreset.DRG_AoE_Mirage) && + LevelChecked(MirageDive) && AnimationLock.CanDRGWeave(MirageDive) && HasEffect(Buffs.DiveReady)) return OriginalHook(HighJump); //Nastrond Feature - if (LevelChecked(Nastrond) && + if (IsEnabled(CustomComboPreset.DRG_AoE_Nastrond) && + LevelChecked(Nastrond) && AnimationLock.CanDRGWeave(Nastrond) && HasEffect(Buffs.NastrondReady) && - gauge.IsLOTDActive) + Gauge.IsLOTDActive) return OriginalHook(Geirskogul); } - - if (comboTime > 0) - { - if (!SonicThrust.LevelChecked()) - { - if (lastComboMove == TrueThrust && LevelChecked(Disembowel)) - return Disembowel; - - if (lastComboMove == Disembowel && LevelChecked(ChaosThrust)) - return OriginalHook(ChaosThrust); - } - - else - { - if (lastComboMove is DoomSpike or DraconianFury && LevelChecked(SonicThrust)) - return SonicThrust; - - if (lastComboMove == SonicThrust && LevelChecked(CoerthanTorment)) - return CoerthanTorment; - } - } - return !HasEffect(Buffs.PowerSurge) && !LevelChecked(SonicThrust) - ? OriginalHook(TrueThrust) - : OriginalHook(DoomSpike); } - return actionID; - } - } - internal class DRG_AOE_AdvancedMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_AOE_AdvancedMode; + // healing + if (IsEnabled(CustomComboPreset.DRG_AoE_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.DRG_AoE_SecondWind_Threshold && + ActionReady(All.SecondWind)) + return All.SecondWind; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - DRGGauge? gauge = GetJobGauge(); + if (PlayerHealthPercentageHp() <= Config.DRG_AoE_Bloodbath_Threshold && ActionReady(All.Bloodbath)) + return All.Bloodbath; + } - if (actionID is DoomSpike) + if (comboTime > 0) { - if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.DRG_Variant_Cure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.DRG_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - AnimationLock.CanDRGWeave(Variant.VariantRampart)) - return Variant.VariantRampart; - - // Piercing Talon Uptime Option - if (IsEnabled(CustomComboPreset.DRG_AoE_RangedUptime) && - LevelChecked(PiercingTalon) && !InMeleeRange() && HasBattleTarget()) - return PiercingTalon; - - if (HasEffect(Buffs.PowerSurge)) + if (IsEnabled(CustomComboPreset.DRG_AoE_Disembowel) && + !SonicThrust.LevelChecked()) { - if (IsEnabled(CustomComboPreset.DRG_AoE_Buffs)) - { - //Lance Charge Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Lance) && - ActionReady(LanceCharge) && - AnimationLock.CanDRGWeave(LanceCharge) && - GetTargetHPPercent() >= Config.DRG_AoE_LanceChargeHP) - return LanceCharge; - - //Battle Litany Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Litany) && - ActionReady(BattleLitany) && - AnimationLock.CanDRGWeave(BattleLitany) && - GetTargetHPPercent() >= Config.DRG_AoE_LitanyHP) - return BattleLitany; - } - - if (IsEnabled(CustomComboPreset.DRG_AoE_CDs)) - { - //Life Surge Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_LifeSurge) && - ActionReady(LifeSurge) && - AnimationLock.CanDRGWeave(LifeSurge) && !HasEffect(Buffs.LifeSurge) && - ((JustUsed(SonicThrust) && LevelChecked(CoerthanTorment)) || - (JustUsed(DoomSpike) && LevelChecked(SonicThrust)) || - (JustUsed(DoomSpike) && !LevelChecked(SonicThrust)))) - return LifeSurge; - - //Wyrmwind Thrust Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Wyrmwind) && - LevelChecked(WyrmwindThrust) && - AnimationLock.CanDRGWeave(WyrmwindThrust) && - gauge.FirstmindsFocusCount is 2) - return WyrmwindThrust; - - //Geirskogul Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Geirskogul) && - ActionReady(Geirskogul) && - AnimationLock.CanDRGWeave(Geirskogul)) - return Geirskogul; - - //(High) Jump Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_HighJump) && - ActionReady(OriginalHook(Jump)) && - AnimationLock.CanDRGWeave(OriginalHook(Jump)) && - (!IsEnabled(CustomComboPreset.DRG_AoE_HighJump_Movement) || - (IsEnabled(CustomComboPreset.DRG_AoE_HighJump_Movement) && !IsMoving))) - return OriginalHook(Jump); - - //Dragonfire Dive Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_DragonfireDive) && - ActionReady(DragonfireDive) && - AnimationLock.CanDRGWeave(DragonfireDive) && - (!IsEnabled(CustomComboPreset.DRG_AoE_DragonfireDive_Movement) || - (IsEnabled(CustomComboPreset.DRG_AoE_DragonfireDive_Movement) && !IsMoving))) - return DragonfireDive; - - //StarDiver Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Stardiver) && - ActionReady(Stardiver) && - AnimationLock.CanDRGWeave(Stardiver) && - gauge.IsLOTDActive && - (!IsEnabled(CustomComboPreset.DRG_AoE_Stardiver_Movement) || - (IsEnabled(CustomComboPreset.DRG_AoE_Stardiver_Movement) && !IsMoving))) - return Stardiver; - - //Starcross Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Starcross) && - LevelChecked(Starcross) && - AnimationLock.CanDRGWeave(Starcross) && - HasEffect(Buffs.StarcrossReady)) - return OriginalHook(Stardiver); - - //Rise of the Dragon Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_RiseOfTheDragon) && - LevelChecked(RiseOfTheDragon) && - AnimationLock.CanDRGWeave(RiseOfTheDragon) && - HasEffect(Buffs.DragonsFlight)) - return OriginalHook(DragonfireDive); - - //Mirage Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Mirage) && - LevelChecked(MirageDive) && - AnimationLock.CanDRGWeave(MirageDive) && - HasEffect(Buffs.DiveReady)) - return OriginalHook(HighJump); - - //Nastrond Feature - if (IsEnabled(CustomComboPreset.DRG_AoE_Nastrond) && - LevelChecked(Nastrond) && - AnimationLock.CanDRGWeave(Nastrond) && - HasEffect(Buffs.NastrondReady) && - gauge.IsLOTDActive) - return OriginalHook(Geirskogul); - } - } - - // healing - if (IsEnabled(CustomComboPreset.DRG_AoE_ComboHeals)) - { - if (PlayerHealthPercentageHp() <= Config.DRG_AoE_SecondWind_Threshold && ActionReady(All.SecondWind)) - return All.SecondWind; + if (lastComboMove == TrueThrust && LevelChecked(Disembowel)) + return Disembowel; - if (PlayerHealthPercentageHp() <= Config.DRG_AoE_Bloodbath_Threshold && ActionReady(All.Bloodbath)) - return All.Bloodbath; + if (lastComboMove == Disembowel && LevelChecked(ChaosThrust)) + return OriginalHook(ChaosThrust); } - if (comboTime > 0) + else { - if (IsEnabled(CustomComboPreset.DRG_AoE_Disembowel) && - !SonicThrust.LevelChecked()) - { - if (lastComboMove == TrueThrust && LevelChecked(Disembowel)) - return Disembowel; - - if (lastComboMove == Disembowel && LevelChecked(ChaosThrust)) - return OriginalHook(ChaosThrust); - } - - else - { - if (lastComboMove is DoomSpike or DraconianFury && LevelChecked(SonicThrust)) - return SonicThrust; - - if (lastComboMove == SonicThrust && LevelChecked(CoerthanTorment)) - return CoerthanTorment; - } + if (lastComboMove is DoomSpike or DraconianFury && LevelChecked(SonicThrust)) + return SonicThrust; + + if (lastComboMove == SonicThrust && LevelChecked(CoerthanTorment)) + return CoerthanTorment; } - return IsEnabled(CustomComboPreset.DRG_AoE_Disembowel) && - !HasEffect(Buffs.PowerSurge) && !LevelChecked(SonicThrust) - ? OriginalHook(TrueThrust) - : OriginalHook(DoomSpike); } - return actionID; + + return IsEnabled(CustomComboPreset.DRG_AoE_Disembowel) && + !HasEffect(Buffs.PowerSurge) && !LevelChecked(SonicThrust) + ? OriginalHook(TrueThrust) + : OriginalHook(DoomSpike); } + + return actionID; } + } - internal class DRG_BurstCDFeature : CustomCombo + internal class DRG_BurstCDFeature : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_BurstCDFeature; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_BurstCDFeature; + if (actionID is LanceCharge) + if (IsOnCooldown(LanceCharge) && ActionReady(BattleLitany)) + return BattleLitany; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is LanceCharge) - { - if (IsOnCooldown(LanceCharge) && ActionReady(BattleLitany)) - return BattleLitany; - } - return actionID; - } + return actionID; } } -} - +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/RPR.cs b/XIVSlothCombo/Combos/PvE/RPR.cs index 06ca0122d..398995a5a 100644 --- a/XIVSlothCombo/Combos/PvE/RPR.cs +++ b/XIVSlothCombo/Combos/PvE/RPR.cs @@ -5,931 +5,970 @@ using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using static XIVSlothCombo.Combos.JobHelpers.RPR; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE +namespace XIVSlothCombo.Combos.PvE; + +internal class RPR { - internal class RPR + public const byte JobID = 39; + + public const uint + + // Single Target + Slice = 24373, + WaxingSlice = 24374, + InfernalSlice = 24375, + ShadowOfDeath = 24378, + SoulSlice = 24380, + + // AoE + SpinningScythe = 24376, + NightmareScythe = 24377, + WhorlOfDeath = 24379, + SoulScythe = 24381, + + // Unveiled + Gibbet = 24382, + Gallows = 24383, + Guillotine = 24384, + UnveiledGibbet = 24390, + UnveiledGallows = 24391, + ExecutionersGibbet = 36970, + ExecutionersGallows = 36971, + ExecutionersGuillotine = 36972, + + // Reaver + BloodStalk = 24389, + GrimSwathe = 24392, + Gluttony = 24393, + + // Sacrifice + ArcaneCircle = 24405, + PlentifulHarvest = 24385, + + // Enshroud + Enshroud = 24394, + Communio = 24398, + LemuresSlice = 24399, + LemuresScythe = 24400, + VoidReaping = 24395, + CrossReaping = 24396, + GrimReaping = 24397, + Sacrificium = 36969, + Perfectio = 36973, + + // Miscellaneous + HellsIngress = 24401, + HellsEgress = 24402, + Regress = 24403, + Harpe = 24386, + Soulsow = 24387, + HarvestMoon = 24388; + + protected static RPRGauge? Gauge = GetJobGauge(); + + public static class Buffs { - public const byte JobID = 39; - - public const uint - // Single Target - Slice = 24373, - WaxingSlice = 24374, - InfernalSlice = 24375, - ShadowOfDeath = 24378, - SoulSlice = 24380, - // AoE - SpinningScythe = 24376, - NightmareScythe = 24377, - WhorlOfDeath = 24379, - SoulScythe = 24381, - // Unveiled - Gibbet = 24382, - Gallows = 24383, - Guillotine = 24384, - UnveiledGibbet = 24390, - UnveiledGallows = 24391, - ExecutionersGibbet = 36970, - ExecutionersGallows = 36971, - ExecutionersGuillotine = 36972, - - // Reaver - BloodStalk = 24389, - GrimSwathe = 24392, - Gluttony = 24393, - // Sacrifice - ArcaneCircle = 24405, - PlentifulHarvest = 24385, - // Enshroud - Enshroud = 24394, - Communio = 24398, - LemuresSlice = 24399, - LemuresScythe = 24400, - VoidReaping = 24395, - CrossReaping = 24396, - GrimReaping = 24397, - Sacrificium = 36969, - Perfectio = 36973, - // Miscellaneous - HellsIngress = 24401, - HellsEgress = 24402, - Regress = 24403, - Harpe = 24386, - Soulsow = 24387, - HarvestMoon = 24388; - - public static class Buffs - { - public const ushort - SoulReaver = 2587, - ImmortalSacrifice = 2592, - ArcaneCircle = 2599, - EnhancedGibbet = 2588, - EnhancedGallows = 2589, - EnhancedVoidReaping = 2590, - EnhancedCrossReaping = 2591, - EnhancedHarpe = 2845, - Enshrouded = 2593, - Soulsow = 2594, - Threshold = 2595, - BloodsownCircle = 2972, - IdealHost = 3905, - Oblatio = 3857, - Executioner = 3858, - PerfectioParata = 3860; - } + public const ushort + SoulReaver = 2587, + ImmortalSacrifice = 2592, + ArcaneCircle = 2599, + EnhancedGibbet = 2588, + EnhancedGallows = 2589, + EnhancedVoidReaping = 2590, + EnhancedCrossReaping = 2591, + EnhancedHarpe = 2845, + Enshrouded = 2593, + Soulsow = 2594, + Threshold = 2595, + BloodsownCircle = 2972, + IdealHost = 3905, + Oblatio = 3857, + Executioner = 3858, + PerfectioParata = 3860; + } - public static class Debuffs - { - public const ushort - DeathsDesign = 2586; - } + public static class Debuffs + { + public const ushort + DeathsDesign = 2586; + } - public static class Config - { - public static UserInt - RPR_SoDThreshold = new("RPRSoDThreshold", 0), - RPR_WoDThreshold = new("RPRWoDThreshold", 1), - RPR_SoDRefreshRange = new("RPRSoDRefreshRange", 6), - RPR_Positional = new("RPR_Positional", 0), - RPR_VariantCure = new("RPRVariantCure"), - RPR_STSecondWindThreshold = new("RPR_STSecondWindThreshold", 25), - RPR_STBloodbathThreshold = new("RPR_STBloodbathThreshold", 40), - RPR_AoESecondWindThreshold = new("RPR_AoESecondWindThreshold", 25), - RPR_AoEBloodbathThreshold = new("RPR_AoEBloodbathThreshold", 40); - public static UserBoolArray - RPR_SoulsowOptions = new("RPR_SoulsowOptions"); - public static UserBool - RPR_ST_TrueNorth_Moving = new("RPR_ST_TrueNorth_Moving"); + public static class Config + { + public static UserInt + RPR_SoDThreshold = new("RPRSoDThreshold", 0), + RPR_WoDThreshold = new("RPRWoDThreshold", 1), + RPR_SoDRefreshRange = new("RPRSoDRefreshRange", 6), + RPR_Positional = new("RPR_Positional", 0), + RPR_VariantCure = new("RPRVariantCure"), + RPR_STSecondWindThreshold = new("RPR_STSecondWindThreshold", 25), + RPR_STBloodbathThreshold = new("RPR_STBloodbathThreshold", 40), + RPR_AoESecondWindThreshold = new("RPR_AoESecondWindThreshold", 25), + RPR_AoEBloodbathThreshold = new("RPR_AoEBloodbathThreshold", 40); + + public static UserBoolArray + RPR_SoulsowOptions = new("RPR_SoulsowOptions"); + + public static UserBool + RPR_ST_TrueNorth_Moving = new("RPR_ST_TrueNorth_Moving"); + } - } + internal class RPR_ST_SimpleMode : CustomCombo + { + internal static RPROpenerLogic RPROpener = new(); + + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ST_SimpleMode; - internal class RPR_ST_SimpleMode : CustomCombo + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ST_SimpleMode; - internal static RPROpenerLogic RPROpener = new(); + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); + bool trueNorthDynReady = trueNorthReady; + float GCD = GetCooldown(Slice).CooldownTotal; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is Slice) { - RPRGauge? gauge = GetJobGauge(); - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool trueNorthDynReady = trueNorthReady; - float GCD = GetCooldown(Slice).CooldownTotal; - - if (actionID is Slice) + //Variant Cure + if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) + return Variant.VariantCure; + + //Variant Rampart + if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + //RPR Opener + if (RPROpener.DoFullOpener(ref actionID)) + return actionID; + + //Arcane Circle + if (CanDelayedWeave(ActionWatching.LastWeaponskill) && + LevelChecked(ArcaneCircle) && + ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || + (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) + return ArcaneCircle; + + //All Weaves + if (CanWeave(ActionWatching.LastWeaponskill)) { - //Variant Cure - if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) - return Variant.VariantCure; - - //Variant Rampart - if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; - - //RPR Opener - if (RPROpener.DoFullOpener(ref actionID)) - return actionID; - - //Arcane Circle - if (CanDelayedWeave(ActionWatching.LastWeaponskill) && - LevelChecked(ArcaneCircle) && - ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || - (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) - return ArcaneCircle; - - //All Weaves - if (CanWeave(ActionWatching.LastWeaponskill)) + //Enshroud + if (RPRHelpers.UseEnshroud(Gauge)) + return Enshroud; + + //Gluttony/Bloodstalk + if (Gauge.Soul >= 50 && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && + !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && + (GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 || !LevelChecked(ArcaneCircle)) && + !RPRHelpers.IsComboExpiring(3)) { - //Enshroud - if (RPRHelpers.UseEnshroud(gauge)) - return Enshroud; - - //Gluttony/Bloodstalk - if (gauge.Soul >= 50 && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && - !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && - ((GetCooldownRemainingTime(ArcaneCircle) > GCD * 3) || !LevelChecked(ArcaneCircle)) && - !RPRHelpers.IsComboExpiring(3)) + //Gluttony + if (!JustUsed(Perfectio) && ActionReady(Gluttony)) { - //Gluttony - if (!JustUsed(Perfectio) && ActionReady(Gluttony)) - { - if (trueNorthReady) - return All.TrueNorth; - - return Gluttony; - } + if (trueNorthReady) + return All.TrueNorth; - //Bloodstalk - if (LevelChecked(BloodStalk) && - (!LevelChecked(Gluttony) || - (LevelChecked(Gluttony) && IsOnCooldown(Gluttony) && - (gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > GCD * 4)))) - return OriginalHook(BloodStalk); + return Gluttony; } - //Enshroud Weaves - if (HasEffect(Buffs.Enshrouded)) - { - //Sacrificium - if (gauge.LemureShroud is 2 && gauge.VoidShroud is 1 && - HasEffect(Buffs.Oblatio) && LevelChecked(Sacrificium)) - return OriginalHook(Gluttony); - - //Lemure's Slice - if (gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) - return OriginalHook(BloodStalk); - } + //Bloodstalk + if (LevelChecked(BloodStalk) && + (!LevelChecked(Gluttony) || + (LevelChecked(Gluttony) && IsOnCooldown(Gluttony) && + (Gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > GCD * 4)))) + return OriginalHook(BloodStalk); } - //Ranged Attacks - if (!InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget()) + //Enshroud Weaves + if (HasEffect(Buffs.Enshrouded)) { - //Communio - if (HasEffect(Buffs.Enshrouded) && gauge.LemureShroud is 1 && gauge.VoidShroud is 0 && LevelChecked(Communio)) - return Communio; - - return (HasEffect(Buffs.Soulsow) && LevelChecked(HarvestMoon)) - ? HarvestMoon - : Harpe; + //Sacrificium + if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && + HasEffect(Buffs.Oblatio) && LevelChecked(Sacrificium)) + return OriginalHook(Gluttony); + + //Lemure's Slice + if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) + return OriginalHook(BloodStalk); } + } - //Shadow Of Death - if (RPRHelpers.UseShadowOfDeath()) - return ShadowOfDeath; + //Ranged Attacks + if (!InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget()) + { + //Communio + if (HasEffect(Buffs.Enshrouded) && Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && + LevelChecked(Communio)) + return Communio; - if (TargetHasEffect(Debuffs.DeathsDesign)) - { - //Perfectio - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelpers.IsComboExpiring(1)) - return OriginalHook(Communio); + return HasEffect(Buffs.Soulsow) && LevelChecked(HarvestMoon) + ? HarvestMoon + : Harpe; + } - //Gibbet/Gallows - if (LevelChecked(Gibbet) && !HasEffect(Buffs.Enshrouded) && - (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner))) - { - //Gibbet - if (HasEffect(Buffs.EnhancedGibbet)) - { - if (trueNorthDynReady && !OnTargetsFlank()) - return All.TrueNorth; + //Shadow Of Death + if (RPRHelpers.UseShadowOfDeath()) + return ShadowOfDeath; - return OriginalHook(Gibbet); - } + if (TargetHasEffect(Debuffs.DeathsDesign)) + { + //Perfectio + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelpers.IsComboExpiring(1)) + return OriginalHook(Communio); - //Gallows - if (HasEffect(Buffs.EnhancedGallows) || - (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - { - if (trueNorthDynReady && !OnTargetsRear()) - return All.TrueNorth; + //Gibbet/Gallows + if (LevelChecked(Gibbet) && !HasEffect(Buffs.Enshrouded) && + (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner))) + { + //Gibbet + if (HasEffect(Buffs.EnhancedGibbet)) + { + if (trueNorthDynReady && !OnTargetsFlank()) + return All.TrueNorth; - return OriginalHook(Gallows); - } + return OriginalHook(Gibbet); } - //Plentiful Harvest - if (LevelChecked(PlentifulHarvest) && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.Executioner) && HasEffect(Buffs.ImmortalSacrifice) && - (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) - return PlentifulHarvest; - - //Enshroud Combo - if (HasEffect(Buffs.Enshrouded)) + //Gallows + if (HasEffect(Buffs.EnhancedGallows) || + (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) { - //Communio - if (gauge.LemureShroud is 1 && gauge.VoidShroud is 0 && LevelChecked(Communio)) - return Communio; - - //Void Reaping - if (HasEffect(Buffs.EnhancedVoidReaping)) - return OriginalHook(Gibbet); - - //Cross Reaping - if (HasEffect(Buffs.EnhancedCrossReaping) || - (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping))) - return OriginalHook(Gallows); - } + if (trueNorthDynReady && !OnTargetsRear()) + return All.TrueNorth; - //Soul Slice - if (gauge.Soul <= 50 && ActionReady(SoulSlice) && - !RPRHelpers.IsComboExpiring(3) && !JustUsed(Perfectio) && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.Executioner) && - !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.ImmortalSacrifice)) - return SoulSlice; + return OriginalHook(Gallows); + } } - //Healing - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) - return All.SecondWind; - - if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) - return All.Bloodbath; + //Plentiful Harvest + if (LevelChecked(PlentifulHarvest) && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.Executioner) && HasEffect(Buffs.ImmortalSacrifice) && + (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) + return PlentifulHarvest; - //1-2-3 Combo - if (comboTime > 0) + //Enshroud Combo + if (HasEffect(Buffs.Enshrouded)) { - if (lastComboMove == OriginalHook(Slice) && LevelChecked(WaxingSlice)) - return OriginalHook(WaxingSlice); + //Communio + if (Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && LevelChecked(Communio)) + return Communio; + + //Void Reaping + if (HasEffect(Buffs.EnhancedVoidReaping)) + return OriginalHook(Gibbet); - if (lastComboMove == OriginalHook(WaxingSlice) && LevelChecked(InfernalSlice)) - return OriginalHook(InfernalSlice); + //Cross Reaping + if (HasEffect(Buffs.EnhancedCrossReaping) || + (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping))) + return OriginalHook(Gallows); } - return OriginalHook(Slice); + + //Soul Slice + if (Gauge.Soul <= 50 && ActionReady(SoulSlice) && + !RPRHelpers.IsComboExpiring(3) && !JustUsed(Perfectio) && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.Executioner) && + !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.ImmortalSacrifice)) + return SoulSlice; } - return actionID; + + //Healing + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) + return All.Bloodbath; + + //1-2-3 Combo + if (comboTime > 0) + { + if (lastComboMove == OriginalHook(Slice) && LevelChecked(WaxingSlice)) + return OriginalHook(WaxingSlice); + + if (lastComboMove == OriginalHook(WaxingSlice) && LevelChecked(InfernalSlice)) + return OriginalHook(InfernalSlice); + } + + return OriginalHook(Slice); } + + return actionID; } + } - internal class RPR_ST_AdvancedMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ST_AdvancedMode; - internal static RPROpenerLogic RPROpener = new(); + internal class RPR_ST_AdvancedMode : CustomCombo + { + internal static RPROpenerLogic RPROpener = new(); + + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ST_AdvancedMode; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + double enemyHP = GetTargetHPPercent(); + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); + bool trueNorthDynReady = trueNorthReady; + int PositionalChoice = Config.RPR_Positional; + float GCD = GetCooldown(Slice).CooldownTotal; + + // Prevent the dynamic true north option from using the last charge + if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && + IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic_HoldCharge) && + GetRemainingCharges(All.TrueNorth) < 2 && trueNorthReady) + trueNorthDynReady = false; + + if (actionID is Slice) { - RPRGauge? gauge = GetJobGauge(); - double enemyHP = GetTargetHPPercent(); - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool trueNorthDynReady = trueNorthReady; - int PositionalChoice = Config.RPR_Positional; - float GCD = GetCooldown(Slice).CooldownTotal; - - // Prevent the dynamic true north option from using the last charge - if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && - IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic_HoldCharge) && - GetRemainingCharges(All.TrueNorth) < 2 && trueNorthReady) - trueNorthDynReady = false; - - if (actionID is Slice) + //Variant Cure + if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) + return Variant.VariantCure; + + //Variant Rampart + if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + //RPR Opener + if (IsEnabled(CustomComboPreset.RPR_ST_Opener)) + if (RPROpener.DoFullOpener(ref actionID)) + return actionID; + + //Arcane Circle + if (IsEnabled(CustomComboPreset.RPR_ST_CDs) && + IsEnabled(CustomComboPreset.RPR_ST_ArcaneCircle) && + CanDelayedWeave(ActionWatching.LastWeaponskill) && + LevelChecked(ArcaneCircle) && + ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || + (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) + return ArcaneCircle; + + //All Weaves + if (CanWeave(ActionWatching.LastWeaponskill)) { - //Variant Cure - if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) - return Variant.VariantCure; - - //Variant Rampart - if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; - - //RPR Opener - if (IsEnabled(CustomComboPreset.RPR_ST_Opener)) + if (IsEnabled(CustomComboPreset.RPR_ST_CDs)) { - if (RPROpener.DoFullOpener(ref actionID)) - return actionID; - } + //Enshroud + if (IsEnabled(CustomComboPreset.RPR_ST_Enshroud) && + RPRHelpers.UseEnshroud(Gauge)) + return Enshroud; - //Arcane Circle - if (IsEnabled(CustomComboPreset.RPR_ST_CDs) && - IsEnabled(CustomComboPreset.RPR_ST_ArcaneCircle) && - CanDelayedWeave(ActionWatching.LastWeaponskill) && - LevelChecked(ArcaneCircle) && - ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || - (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) - return ArcaneCircle; - - //All Weaves - if (CanWeave(ActionWatching.LastWeaponskill)) - { - if (IsEnabled(CustomComboPreset.RPR_ST_CDs)) + //Gluttony/Bloodstalk + if (Gauge.Soul >= 50 && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && + !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && + (GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 || !LevelChecked(ArcaneCircle)) && + !RPRHelpers.IsComboExpiring(3)) { - //Enshroud - if (IsEnabled(CustomComboPreset.RPR_ST_Enshroud) && - RPRHelpers.UseEnshroud(gauge)) - return Enshroud; - - //Gluttony/Bloodstalk - if (gauge.Soul >= 50 && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && - !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && - ((GetCooldownRemainingTime(ArcaneCircle) > GCD * 3) || !LevelChecked(ArcaneCircle)) && - !RPRHelpers.IsComboExpiring(3)) + //Gluttony + if (IsEnabled(CustomComboPreset.RPR_ST_Gluttony) && + !JustUsed(Perfectio) && ActionReady(Gluttony)) { - //Gluttony - if (IsEnabled(CustomComboPreset.RPR_ST_Gluttony) && - !JustUsed(Perfectio) && ActionReady(Gluttony)) - { - if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && - trueNorthReady) - return All.TrueNorth; - - return Gluttony; - } - - //Bloodstalk - if (IsEnabled(CustomComboPreset.RPR_ST_Bloodstalk) && - LevelChecked(BloodStalk) && - (!LevelChecked(Gluttony) || - (LevelChecked(Gluttony) && IsOnCooldown(Gluttony) && - (gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > GCD * 4)))) - return OriginalHook(BloodStalk); + if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && + trueNorthReady) + return All.TrueNorth; + + return Gluttony; } - } - //Enshroud Weaves - if (HasEffect(Buffs.Enshrouded)) - { - //Sacrificium - if (IsEnabled(CustomComboPreset.RPR_ST_Sacrificium) && - gauge.LemureShroud is 2 && gauge.VoidShroud is 1 && - HasEffect(Buffs.Oblatio) && LevelChecked(Sacrificium)) - return OriginalHook(Gluttony); - - //Lemure's Slice - if (IsEnabled(CustomComboPreset.RPR_ST_Lemure) && - gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) + //Bloodstalk + if (IsEnabled(CustomComboPreset.RPR_ST_Bloodstalk) && + LevelChecked(BloodStalk) && + (!LevelChecked(Gluttony) || + (LevelChecked(Gluttony) && IsOnCooldown(Gluttony) && + (Gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > GCD * 4)))) return OriginalHook(BloodStalk); } } - //Ranged Attacks - if (IsEnabled(CustomComboPreset.RPR_ST_RangedFiller) && - !InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget()) + //Enshroud Weaves + if (HasEffect(Buffs.Enshrouded)) { - //Communio - if (HasEffect(Buffs.Enshrouded) && gauge.LemureShroud is 1 && gauge.VoidShroud is 0 && LevelChecked(Communio)) - return Communio; - - return (IsEnabled(CustomComboPreset.RPR_ST_RangedFillerHarvestMoon) && - HasEffect(Buffs.Soulsow) && LevelChecked(HarvestMoon)) - ? HarvestMoon - : Harpe; + //Sacrificium + if (IsEnabled(CustomComboPreset.RPR_ST_Sacrificium) && + Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && + HasEffect(Buffs.Oblatio) && LevelChecked(Sacrificium)) + return OriginalHook(Gluttony); + + //Lemure's Slice + if (IsEnabled(CustomComboPreset.RPR_ST_Lemure) && + Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) + return OriginalHook(BloodStalk); } + } - //Shadow Of Death - if (IsEnabled(CustomComboPreset.RPR_ST_SoD) && - RPRHelpers.UseShadowOfDeath() && enemyHP > Config.RPR_SoDThreshold) - return ShadowOfDeath; + //Ranged Attacks + if (IsEnabled(CustomComboPreset.RPR_ST_RangedFiller) && + !InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget()) + { + //Communio + if (HasEffect(Buffs.Enshrouded) && Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && + LevelChecked(Communio)) + return Communio; - if (TargetHasEffect(Debuffs.DeathsDesign)) - { - //Perfectio - if (IsEnabled(CustomComboPreset.RPR_ST_Perfectio) && - HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelpers.IsComboExpiring(1)) - return OriginalHook(Communio); - - //Gibbet/Gallows - if (IsEnabled(CustomComboPreset.RPR_ST_GibbetGallows) && - LevelChecked(Gibbet) && !HasEffect(Buffs.Enshrouded) && - (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner))) - { - //Gibbet - if (HasEffect(Buffs.EnhancedGibbet) || - (PositionalChoice is 1 && !HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - { - if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && - trueNorthDynReady && !OnTargetsFlank()) - return All.TrueNorth; + return IsEnabled(CustomComboPreset.RPR_ST_RangedFillerHarvestMoon) && + HasEffect(Buffs.Soulsow) && LevelChecked(HarvestMoon) + ? HarvestMoon + : Harpe; + } - return OriginalHook(Gibbet); - } + //Shadow Of Death + if (IsEnabled(CustomComboPreset.RPR_ST_SoD) && + RPRHelpers.UseShadowOfDeath() && enemyHP > Config.RPR_SoDThreshold) + return ShadowOfDeath; - //Gallows - if (HasEffect(Buffs.EnhancedGallows) || - (PositionalChoice is 0 && !HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - { - if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && - trueNorthDynReady && !OnTargetsRear()) - return All.TrueNorth; + if (TargetHasEffect(Debuffs.DeathsDesign)) + { + //Perfectio + if (IsEnabled(CustomComboPreset.RPR_ST_Perfectio) && + HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelpers.IsComboExpiring(1)) + return OriginalHook(Communio); - return OriginalHook(Gallows); - } - } + //Gibbet/Gallows + if (IsEnabled(CustomComboPreset.RPR_ST_GibbetGallows) && + LevelChecked(Gibbet) && !HasEffect(Buffs.Enshrouded) && + (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner))) + { + //Gibbet + if (HasEffect(Buffs.EnhancedGibbet) || + (PositionalChoice is 1 && !HasEffect(Buffs.EnhancedGibbet) && + !HasEffect(Buffs.EnhancedGallows))) + { + if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && + trueNorthDynReady && !OnTargetsFlank()) + return All.TrueNorth; - //Plentiful Harvest - if (IsEnabled(CustomComboPreset.RPR_ST_CDs) && - IsEnabled(CustomComboPreset.RPR_ST_PlentifulHarvest) && - LevelChecked(PlentifulHarvest) && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.Executioner) && HasEffect(Buffs.ImmortalSacrifice) && - (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) - return PlentifulHarvest; + return OriginalHook(Gibbet); + } - //Enshroud Combo - if (HasEffect(Buffs.Enshrouded)) + //Gallows + if (HasEffect(Buffs.EnhancedGallows) || + (PositionalChoice is 0 && !HasEffect(Buffs.EnhancedGibbet) && + !HasEffect(Buffs.EnhancedGallows))) { - //Communio - if (IsEnabled(CustomComboPreset.RPR_ST_Communio) && - gauge.LemureShroud is 1 && gauge.VoidShroud is 0 && LevelChecked(Communio)) - return Communio; - - //Void Reaping - if (IsEnabled(CustomComboPreset.RPR_ST_Reaping) && - HasEffect(Buffs.EnhancedVoidReaping)) - return OriginalHook(Gibbet); - - //Cross Reaping - if (IsEnabled(CustomComboPreset.RPR_ST_Reaping) && - (HasEffect(Buffs.EnhancedCrossReaping) || - (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping)))) - return OriginalHook(Gallows); - } + if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && + trueNorthDynReady && !OnTargetsRear()) + return All.TrueNorth; - //Soul Slice - if (IsEnabled(CustomComboPreset.RPR_ST_SoulSlice) && - gauge.Soul <= 50 && ActionReady(SoulSlice) && - !RPRHelpers.IsComboExpiring(3) && !JustUsed(Perfectio) && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && - !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.Executioner) && - !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.ImmortalSacrifice)) - return SoulSlice; + return OriginalHook(Gallows); + } } - //Healing - if (IsEnabled(CustomComboPreset.RPR_ST_ComboHeals)) + //Plentiful Harvest + if (IsEnabled(CustomComboPreset.RPR_ST_CDs) && + IsEnabled(CustomComboPreset.RPR_ST_PlentifulHarvest) && + LevelChecked(PlentifulHarvest) && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.Executioner) && HasEffect(Buffs.ImmortalSacrifice) && + (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) + return PlentifulHarvest; + + //Enshroud Combo + if (HasEffect(Buffs.Enshrouded)) { - if (PlayerHealthPercentageHp() <= Config.RPR_STSecondWindThreshold && ActionReady(All.SecondWind)) - return All.SecondWind; + //Communio + if (IsEnabled(CustomComboPreset.RPR_ST_Communio) && + Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && LevelChecked(Communio)) + return Communio; + + //Void Reaping + if (IsEnabled(CustomComboPreset.RPR_ST_Reaping) && + HasEffect(Buffs.EnhancedVoidReaping)) + return OriginalHook(Gibbet); - if (PlayerHealthPercentageHp() <= Config.RPR_STBloodbathThreshold && ActionReady(All.Bloodbath)) - return All.Bloodbath; + //Cross Reaping + if (IsEnabled(CustomComboPreset.RPR_ST_Reaping) && + (HasEffect(Buffs.EnhancedCrossReaping) || + (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping)))) + return OriginalHook(Gallows); } - //1-2-3 Combo - if (comboTime > 0) - { - if (lastComboMove == OriginalHook(Slice) && LevelChecked(WaxingSlice)) - return OriginalHook(WaxingSlice); + //Soul Slice + if (IsEnabled(CustomComboPreset.RPR_ST_SoulSlice) && + Gauge.Soul <= 50 && ActionReady(SoulSlice) && + !RPRHelpers.IsComboExpiring(3) && !JustUsed(Perfectio) && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.Executioner) && + !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.ImmortalSacrifice)) + return SoulSlice; + } - if (lastComboMove == OriginalHook(WaxingSlice) && LevelChecked(InfernalSlice)) - return OriginalHook(InfernalSlice); - } - return OriginalHook(Slice); + //Healing + if (IsEnabled(CustomComboPreset.RPR_ST_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.RPR_STSecondWindThreshold && ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= Config.RPR_STBloodbathThreshold && ActionReady(All.Bloodbath)) + return All.Bloodbath; } - return actionID; + + //1-2-3 Combo + if (comboTime > 0) + { + if (lastComboMove == OriginalHook(Slice) && LevelChecked(WaxingSlice)) + return OriginalHook(WaxingSlice); + + if (lastComboMove == OriginalHook(WaxingSlice) && LevelChecked(InfernalSlice)) + return OriginalHook(InfernalSlice); + } + + return OriginalHook(Slice); } + + return actionID; } + } - internal class RPR_AoE_SimpleMode : CustomCombo + internal class RPR_AoE_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_AoE_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_AoE_SimpleMode; + float GCD = GetCooldown(SpinningScythe).CooldownTotal; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is SpinningScythe) { - RPRGauge? gauge = GetJobGauge(); - float GCD = GetCooldown(SpinningScythe).CooldownTotal; - - if (actionID is SpinningScythe) + if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + if (LevelChecked(WhorlOfDeath) && + GetDebuffRemainingTime(Debuffs.DeathsDesign) < 6 && !HasEffect(Buffs.SoulReaver) && + !HasEffect(Buffs.Executioner)) + return WhorlOfDeath; + + if (TargetHasEffect(Debuffs.DeathsDesign)) { - if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; - - if (LevelChecked(WhorlOfDeath) && - GetDebuffRemainingTime(Debuffs.DeathsDesign) < 6 && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner)) - return WhorlOfDeath; - - if (TargetHasEffect(Debuffs.DeathsDesign)) - { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); - - if (HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.Executioner) && - (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) - return PlentifulHarvest; - - if (CanWeave(actionID)) - { - if (LevelChecked(ArcaneCircle) && - ((GetCooldownRemainingTime(ArcaneCircle) <= GCD + 0.25) || ActionReady(ArcaneCircle))) - return ArcaneCircle; + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); - if (!HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.Executioner) && - ActionReady(Enshroud) && (gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && !RPRHelpers.IsComboExpiring(6)) - return Enshroud; + if (HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.Executioner) && + (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) + return PlentifulHarvest; - if (LevelChecked(Gluttony) && gauge.Soul >= 50 && !HasEffect(Buffs.Enshrouded) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && - ((GetCooldownRemainingTime(Gluttony) <= GetCooldownRemainingTime(Slice) + 0.25) || ActionReady(Gluttony))) - return Gluttony; + if (CanWeave(actionID)) + { + if (LevelChecked(ArcaneCircle) && + (GetCooldownRemainingTime(ArcaneCircle) <= GCD + 0.25 || ActionReady(ArcaneCircle))) + return ArcaneCircle; + + if (!HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && + !HasEffect(Buffs.Executioner) && + ActionReady(Enshroud) && (Gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && + !RPRHelpers.IsComboExpiring(6)) + return Enshroud; - if (LevelChecked(GrimSwathe) && !HasEffect(Buffs.Enshrouded) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && !HasEffect(Buffs.Executioner) && - gauge.Soul >= 50 && (!LevelChecked(Gluttony) || (LevelChecked(Gluttony) && - (gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > GCD * 5)))) - return GrimSwathe; - } + if (LevelChecked(Gluttony) && Gauge.Soul >= 50 && !HasEffect(Buffs.Enshrouded) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && + (GetCooldownRemainingTime(Gluttony) <= GetCooldownRemainingTime(Slice) + 0.25 || + ActionReady(Gluttony))) + return Gluttony; + + if (LevelChecked(GrimSwathe) && !HasEffect(Buffs.Enshrouded) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && + !HasEffect(Buffs.Executioner) && + Gauge.Soul >= 50 && (!LevelChecked(Gluttony) || (LevelChecked(Gluttony) && + (Gauge.Soul is 100 || + GetCooldownRemainingTime(Gluttony) > + GCD * 5)))) + return GrimSwathe; + } - if (!HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && - ActionReady(SoulScythe) && gauge.Soul <= 50) - return SoulScythe; + if (!HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && + !HasEffect(Buffs.PerfectioParata) && + ActionReady(SoulScythe) && Gauge.Soul <= 50) + return SoulScythe; - if (HasEffect(Buffs.Enshrouded)) - { - if (gauge.LemureShroud is 1 && gauge.VoidShroud is 0 && ActionReady(Communio)) - return Communio; + if (HasEffect(Buffs.Enshrouded)) + { + if (Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && ActionReady(Communio)) + return Communio; - if (gauge.LemureShroud is 2 && gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) - return OriginalHook(Gluttony); + if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) + return OriginalHook(Gluttony); - if (gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) - return OriginalHook(GrimSwathe); + if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) + return OriginalHook(GrimSwathe); - if (gauge.LemureShroud > 0) - return OriginalHook(Guillotine); - } + if (Gauge.LemureShroud > 0) + return OriginalHook(Guillotine); } + } - if (HasEffect(Buffs.SoulReaver) || (HasEffect(Buffs.Executioner) - && !HasEffect(Buffs.Enshrouded) && LevelChecked(Guillotine))) - return OriginalHook(Guillotine); + if (HasEffect(Buffs.SoulReaver) || (HasEffect(Buffs.Executioner) + && !HasEffect(Buffs.Enshrouded) && LevelChecked(Guillotine))) + return OriginalHook(Guillotine); - return lastComboMove == OriginalHook(SpinningScythe) && LevelChecked(NightmareScythe) - ? OriginalHook(NightmareScythe) - : OriginalHook(SpinningScythe); - } - return actionID; + return lastComboMove == OriginalHook(SpinningScythe) && LevelChecked(NightmareScythe) + ? OriginalHook(NightmareScythe) + : OriginalHook(SpinningScythe); } + + return actionID; } + } - internal class RPR_AoE_AdvancedMode : CustomCombo + internal class RPR_AoE_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_AoE_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_AoE_AdvancedMode; + double enemyHP = GetTargetHPPercent(); + float GCD = GetCooldown(SpinningScythe).CooldownTotal; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is SpinningScythe) { - RPRGauge? gauge = GetJobGauge(); - double enemyHP = GetTargetHPPercent(); - float GCD = GetCooldown(SpinningScythe).CooldownTotal; - - if (actionID is SpinningScythe) + if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(actionID)) + return Variant.VariantRampart; + + if (IsEnabled(CustomComboPreset.RPR_AoE_WoD) && + LevelChecked(WhorlOfDeath) && + GetDebuffRemainingTime(Debuffs.DeathsDesign) < 6 && !HasEffect(Buffs.SoulReaver) && + enemyHP > Config.RPR_WoDThreshold) + return WhorlOfDeath; + + if (TargetHasEffect(Debuffs.DeathsDesign)) { - if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.RPR_VariantCure)) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.RPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(actionID)) - return Variant.VariantRampart; - - if (IsEnabled(CustomComboPreset.RPR_AoE_WoD) && - LevelChecked(WhorlOfDeath) && - GetDebuffRemainingTime(Debuffs.DeathsDesign) < 6 && !HasEffect(Buffs.SoulReaver) && - enemyHP > Config.RPR_WoDThreshold) - return WhorlOfDeath; - - if (TargetHasEffect(Debuffs.DeathsDesign)) + if (IsEnabled(CustomComboPreset.RPR_AoE_Perfectio) && + HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); + + if (IsEnabled(CustomComboPreset.RPR_AoE_CDs)) { - if (IsEnabled(CustomComboPreset.RPR_AoE_Perfectio) && - HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); + if (IsEnabled(CustomComboPreset.RPR_AoE_PlentifulHarvest) && + HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && + (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) + return PlentifulHarvest; - if (IsEnabled(CustomComboPreset.RPR_AoE_CDs)) + if (CanWeave(actionID)) { - if (IsEnabled(CustomComboPreset.RPR_AoE_PlentifulHarvest) && - HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest) && + if (IsEnabled(CustomComboPreset.RPR_AoE_ArcaneCircle) && + LevelChecked(ArcaneCircle) && + (GetCooldownRemainingTime(ArcaneCircle) <= GCD + 0.25 || ActionReady(ArcaneCircle))) + return ArcaneCircle; + + if (IsEnabled(CustomComboPreset.RPR_AoE_Enshroud) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && - (GetBuffRemainingTime(Buffs.BloodsownCircle) <= 1 || JustUsed(Communio))) - return PlentifulHarvest; + ActionReady(Enshroud) && (Gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && + !RPRHelpers.IsComboExpiring(6)) + return Enshroud; - if (CanWeave(actionID)) - { - if (IsEnabled(CustomComboPreset.RPR_AoE_ArcaneCircle) && - LevelChecked(ArcaneCircle) && - ((GetCooldownRemainingTime(ArcaneCircle) <= GCD + 0.25) || ActionReady(ArcaneCircle))) - return ArcaneCircle; - - if (IsEnabled(CustomComboPreset.RPR_AoE_Enshroud) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && - ActionReady(Enshroud) && (gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && !RPRHelpers.IsComboExpiring(6)) - return Enshroud; - - if (IsEnabled(CustomComboPreset.RPR_AoE_Gluttony) && - LevelChecked(Gluttony) && gauge.Soul >= 50 && !HasEffect(Buffs.Enshrouded) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && - ((GetCooldownRemainingTime(Gluttony) <= GetCooldownRemainingTime(Slice) + 0.25) || ActionReady(Gluttony))) - return Gluttony; - - if (IsEnabled(CustomComboPreset.RPR_AoE_GrimSwathe) && - LevelChecked(GrimSwathe) && !HasEffect(Buffs.Enshrouded) && - !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && gauge.Soul >= 50 && - (!LevelChecked(Gluttony) || (LevelChecked(Gluttony) && - (gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > GCD * 5)))) - return GrimSwathe; - } + if (IsEnabled(CustomComboPreset.RPR_AoE_Gluttony) && + LevelChecked(Gluttony) && Gauge.Soul >= 50 && !HasEffect(Buffs.Enshrouded) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && + (GetCooldownRemainingTime(Gluttony) <= GetCooldownRemainingTime(Slice) + 0.25 || + ActionReady(Gluttony))) + return Gluttony; + + if (IsEnabled(CustomComboPreset.RPR_AoE_GrimSwathe) && + LevelChecked(GrimSwathe) && !HasEffect(Buffs.Enshrouded) && + !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.ImmortalSacrifice) && + Gauge.Soul >= 50 && + (!LevelChecked(Gluttony) || (LevelChecked(Gluttony) && + (Gauge.Soul is 100 || GetCooldownRemainingTime(Gluttony) > + GCD * 5)))) + return GrimSwathe; } + } - if (IsEnabled(CustomComboPreset.RPR_AoE_SoulScythe) && - !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && - ActionReady(SoulScythe) && gauge.Soul <= 50) - return SoulScythe; + if (IsEnabled(CustomComboPreset.RPR_AoE_SoulScythe) && + !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && + !HasEffect(Buffs.PerfectioParata) && + ActionReady(SoulScythe) && Gauge.Soul <= 50) + return SoulScythe; - if (HasEffect(Buffs.Enshrouded)) - { - if (IsEnabled(CustomComboPreset.RPR_AoE_Communio) && - gauge.LemureShroud is 1 && gauge.VoidShroud is 0 && ActionReady(Communio)) - return Communio; + if (HasEffect(Buffs.Enshrouded)) + { + if (IsEnabled(CustomComboPreset.RPR_AoE_Communio) && + Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && ActionReady(Communio)) + return Communio; - if (IsEnabled(CustomComboPreset.RPR_AoE_Sacrificium) && - gauge.LemureShroud is 2 && gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio) && CanWeave(actionID)) - return OriginalHook(Gluttony); + if (IsEnabled(CustomComboPreset.RPR_AoE_Sacrificium) && + Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio) && + CanWeave(actionID)) + return OriginalHook(Gluttony); - if (IsEnabled(CustomComboPreset.RPR_AoE_Lemure) && - gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) - return OriginalHook(GrimSwathe); + if (IsEnabled(CustomComboPreset.RPR_AoE_Lemure) && + Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) + return OriginalHook(GrimSwathe); - if (IsEnabled(CustomComboPreset.RPR_AoE_Reaping) && - gauge.LemureShroud > 0) - return OriginalHook(Guillotine); - } + if (IsEnabled(CustomComboPreset.RPR_AoE_Reaping) && + Gauge.LemureShroud > 0) + return OriginalHook(Guillotine); } + } - if (IsEnabled(CustomComboPreset.RPR_AoE_ComboHeals)) - { - if (PlayerHealthPercentageHp() <= Config.RPR_AoESecondWindThreshold && ActionReady(All.SecondWind)) - return All.SecondWind; + if (IsEnabled(CustomComboPreset.RPR_AoE_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.RPR_AoESecondWindThreshold && ActionReady(All.SecondWind)) + return All.SecondWind; - if (PlayerHealthPercentageHp() <= Config.RPR_AoEBloodbathThreshold && ActionReady(All.Bloodbath)) - return All.Bloodbath; - } + if (PlayerHealthPercentageHp() <= Config.RPR_AoEBloodbathThreshold && ActionReady(All.Bloodbath)) + return All.Bloodbath; + } - if (IsEnabled(CustomComboPreset.RPR_AoE_Guillotine) && - (HasEffect(Buffs.SoulReaver) || (HasEffect(Buffs.Executioner) - && !HasEffect(Buffs.Enshrouded) && LevelChecked(Guillotine)))) - return OriginalHook(Guillotine); + if (IsEnabled(CustomComboPreset.RPR_AoE_Guillotine) && + (HasEffect(Buffs.SoulReaver) || (HasEffect(Buffs.Executioner) + && !HasEffect(Buffs.Enshrouded) && LevelChecked(Guillotine)))) + return OriginalHook(Guillotine); - return lastComboMove == OriginalHook(SpinningScythe) && LevelChecked(NightmareScythe) - ? OriginalHook(NightmareScythe) - : OriginalHook(SpinningScythe); - } - return actionID; + return lastComboMove == OriginalHook(SpinningScythe) && LevelChecked(NightmareScythe) + ? OriginalHook(NightmareScythe) + : OriginalHook(SpinningScythe); } + + return actionID; } + } - internal class RPR_GluttonyBloodSwathe : CustomCombo + internal class RPR_GluttonyBloodSwathe : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_GluttonyBloodSwathe; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_GluttonyBloodSwathe; + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is GrimSwathe) { - RPRGauge? gauge = GetJobGauge(); - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth); - - if (actionID is GrimSwathe) + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) { - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) - { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); - if (HasEffect(Buffs.Enshrouded)) - { - if (gauge.LemureShroud == 1 && gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + if (HasEffect(Buffs.Enshrouded)) + { + if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) + return Communio; - if (gauge.LemureShroud is 2 && gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) - return OriginalHook(Gluttony); + if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) + return OriginalHook(Gluttony); - if (gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe)) - return OriginalHook(GrimSwathe); + if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe)) + return OriginalHook(GrimSwathe); - if (gauge.LemureShroud > 1) - return OriginalHook(Guillotine); - } + if (Gauge.LemureShroud > 1) + return OriginalHook(Guillotine); } + } - if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) - return Gluttony; + if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) + return Gluttony; - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && - (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Guillotine)) - return Guillotine; - } + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && + (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Guillotine)) + return Guillotine; + } + + if (actionID is BloodStalk) + { + if (IsEnabled(CustomComboPreset.RPR_TrueNorthGluttony) && + trueNorthReady && CanWeave(actionID)) + return All.TrueNorth; - if (actionID is BloodStalk) + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) { - if (IsEnabled(CustomComboPreset.RPR_TrueNorthGluttony) && - trueNorthReady && CanWeave(actionID)) - return All.TrueNorth; + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) + if (HasEffect(Buffs.Enshrouded)) { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); - - if (HasEffect(Buffs.Enshrouded)) - { - if (gauge.LemureShroud == 1 && gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) + return Communio; - if (gauge.LemureShroud is 2 && gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) - return OriginalHook(Gluttony); + if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) + return OriginalHook(Gluttony); - if (gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) - return OriginalHook(BloodStalk); + if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) + return OriginalHook(BloodStalk); - if (HasEffect(Buffs.EnhancedVoidReaping)) - return OriginalHook(Gibbet); + if (HasEffect(Buffs.EnhancedVoidReaping)) + return OriginalHook(Gibbet); - if (HasEffect(Buffs.EnhancedCrossReaping)) - return OriginalHook(Gallows); + if (HasEffect(Buffs.EnhancedCrossReaping)) + return OriginalHook(Gallows); - if (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping)) - return OriginalHook(Gallows); - } + if (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping)) + return OriginalHook(Gallows); } + } - if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) - return Gluttony; + if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) + return Gluttony; - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && - (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Gibbet)) - { - if (HasEffect(Buffs.EnhancedGibbet)) - return OriginalHook(Gibbet); + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && + (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Gibbet)) + { + if (HasEffect(Buffs.EnhancedGibbet)) + return OriginalHook(Gibbet); - if (HasEffect(Buffs.EnhancedGallows) || - (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - return OriginalHook(Gallows); - } + if (HasEffect(Buffs.EnhancedGallows) || + (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) + return OriginalHook(Gallows); } - return actionID; } + + return actionID; } + } + + internal class RPR_ArcaneCirclePlentifulHarvest : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = + CustomComboPreset.RPR_ArcaneCirclePlentifulHarvest; - internal class RPR_ArcaneCirclePlentifulHarvest : CustomCombo + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ArcaneCirclePlentifulHarvest; + if (actionID is ArcaneCircle) + if (HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest)) + return PlentifulHarvest; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is ArcaneCircle) - { - if (HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest)) - return PlentifulHarvest; - } - return actionID; - } + return actionID; } + } - internal class RPR_Regress : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_Regress; + internal class RPR_Regress : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_Regress; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - return (actionID is HellsEgress or HellsIngress) && FindEffect(Buffs.Threshold)?.RemainingTime <= 9 - ? Regress - : actionID; - } + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is HellsEgress or HellsIngress && FindEffect(Buffs.Threshold)?.RemainingTime <= 9 + ? Regress + : actionID; } + } - internal class RPR_Soulsow : CustomCombo + internal class RPR_Soulsow : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_Soulsow; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_Soulsow; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - var soulSowOptions = PluginConfiguration.GetCustomBoolArrayValue(Config.RPR_SoulsowOptions); - bool soulsowReady = LevelChecked(Soulsow) && !HasEffect(Buffs.Soulsow); - - return (((soulSowOptions.Length > 0) && ((actionID is Harpe && soulSowOptions[0]) || - (actionID is Slice && soulSowOptions[1]) || - (actionID is SpinningScythe && soulSowOptions[2]) || - (actionID is ShadowOfDeath && soulSowOptions[3]) || - (actionID is BloodStalk && soulSowOptions[4])) && soulsowReady && !InCombat()) || - (IsEnabled(CustomComboPreset.RPR_Soulsow_Combat) && actionID is Harpe && !HasBattleTarget())) ? - Soulsow : actionID; - } + bool[] soulSowOptions = PluginConfiguration.GetCustomBoolArrayValue(Config.RPR_SoulsowOptions); + bool soulsowReady = LevelChecked(Soulsow) && !HasEffect(Buffs.Soulsow); + + return (soulSowOptions.Length > 0 && ((actionID is Harpe && soulSowOptions[0]) || + (actionID is Slice && soulSowOptions[1]) || + (actionID is SpinningScythe && soulSowOptions[2]) || + (actionID is ShadowOfDeath && soulSowOptions[3]) || + (actionID is BloodStalk && soulSowOptions[4])) && soulsowReady && + !InCombat()) || + (IsEnabled(CustomComboPreset.RPR_Soulsow_Combat) && actionID is Harpe && !HasBattleTarget()) + ? Soulsow + : actionID; } + } - internal class RPR_EnshroudProtection : CustomCombo + internal class RPR_EnshroudProtection : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_EnshroudProtection; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_EnshroudProtection; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); + + if (actionID is Enshroud) { - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth); + if (IsEnabled(CustomComboPreset.RPR_TrueNorthEnshroud) && + GetBuffStacks(Buffs.SoulReaver) is 2 && trueNorthReady && CanDelayedWeave(Slice)) + return All.TrueNorth; - if (actionID is Enshroud) + if (HasEffect(Buffs.SoulReaver)) { - if (IsEnabled(CustomComboPreset.RPR_TrueNorthEnshroud) && - GetBuffStacks(Buffs.SoulReaver) is 2 && trueNorthReady && CanDelayedWeave(Slice)) - return All.TrueNorth; - - if (HasEffect(Buffs.SoulReaver)) - { - if (HasEffect(Buffs.EnhancedGibbet)) - return OriginalHook(Gibbet); + if (HasEffect(Buffs.EnhancedGibbet)) + return OriginalHook(Gibbet); - if (HasEffect(Buffs.EnhancedGallows) || - (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - return OriginalHook(Gallows); - } + if (HasEffect(Buffs.EnhancedGallows) || + (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) + return OriginalHook(Gallows); } - return actionID; } + + return actionID; } + } + + internal class RPR_CommunioOnGGG : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_CommunioOnGGG; - internal class RPR_CommunioOnGGG : CustomCombo + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_CommunioOnGGG; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is Gibbet or Gallows && HasEffect(Buffs.Enshrouded)) { - RPRGauge? gauge = GetJobGauge(); + if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) + return Communio; - if (actionID is Gibbet or Gallows && HasEffect(Buffs.Enshrouded)) - { - if (gauge.LemureShroud == 1 && gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; - - if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && - gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice) && CanWeave(actionID)) - return OriginalHook(BloodStalk); - } - - if (actionID is Guillotine && HasEffect(Buffs.Enshrouded)) - { - if (gauge.LemureShroud == 1 && gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && + Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice) && CanWeave(actionID)) + return OriginalHook(BloodStalk); + } - if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && - gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) - return OriginalHook(GrimSwathe); - } + if (actionID is Guillotine && HasEffect(Buffs.Enshrouded)) + { + if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) + return Communio; - return actionID; + if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && + Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) + return OriginalHook(GrimSwathe); } + + return actionID; } + } - internal class RPR_EnshroudCommunio : CustomCombo + internal class RPR_EnshroudCommunio : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_EnshroudCommunio; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_EnshroudCommunio; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + if (actionID is Enshroud) { - if (actionID is Enshroud) - { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); - if (HasEffect(Buffs.Enshrouded) && LevelChecked(Communio)) - return Communio; - } - return actionID; + if (HasEffect(Buffs.Enshrouded) && LevelChecked(Communio)) + return Communio; } + + return actionID; } } } \ No newline at end of file From 3380025171196629165791ca78cec7747b7d8d26 Mon Sep 17 00:00:00 2001 From: Kage Date: Sun, 8 Sep 2024 19:33:28 +0200 Subject: [PATCH 096/208] Masterfull blitz fix from @Akechi --- XIVSlothCombo/Combos/PvE/MNK.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 04e9242d4..8f3d5fb08 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -170,8 +170,9 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb : OriginalHook(Bootshine); // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && - HasEffect(Buffs.RiddleOfFire) && !IsOriginal(MasterfulBlitz)) + if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && + (HasEffect(Buffs.RiddleOfFire) || GetCooldownRemainingTime(RiddleOfFire) > 35) && + !IsOriginal(MasterfulBlitz)) return OriginalHook(MasterfulBlitz); // Perfect Balance @@ -338,8 +339,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb { // Masterful Blitz if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && - HasEffect(Buffs.RiddleOfFire) && - OriginalHook(MasterfulBlitz) != MasterfulBlitz) + (HasEffect(Buffs.RiddleOfFire) || GetCooldownRemainingTime(RiddleOfFire) > 35) && + !IsOriginal(MasterfulBlitz)) return OriginalHook(MasterfulBlitz); // Perfect Balance From f01ce391f3fd84c40c606224466d9f1a22fde713 Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 9 Sep 2024 12:53:28 +0200 Subject: [PATCH 097/208] rework ST for lower lvls PB optimizations Masterful Blitz optimization remove obselete code --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 15 +- XIVSlothCombo/Combos/PvE/MNK.cs | 207 +++++++++++-------- XIVSlothCombo/Window/Functions/UserConfig.cs | 15 +- 3 files changed, 132 insertions(+), 105 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index a74cf5810..3e3b45ea7 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -9,7 +9,7 @@ namespace XIVSlothCombo.Combos.JobHelpers; internal abstract class MNKHelper : MNK { - public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled = true) + public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) { if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) @@ -381,18 +381,13 @@ public bool DoFullOpener(ref uint actionID, int selectedOpener) return true; if (CurrentState == OpenerState.InOpener) - { - if (selectedOpener == 1) - { - if (DoLlOpener(ref actionID)) - return true; - } - else if (selectedOpener == 2) + switch (selectedOpener) { - if (DoSlOpener(ref actionID)) + case 0 when DoLlOpener(ref actionID): + + case 1 when DoSlOpener(ref actionID): return true; } - } if (!InCombat()) { diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 8f3d5fb08..a2e63d392 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -102,21 +102,24 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (actionID is Bootshine or LeapingOpo) { - if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) + if (MNKOpener.DoFullOpener(ref actionID, 0)) return actionID; + if ((!InCombat() || !InMeleeRange()) && + Gauge.Chakra < 5 && + !HasEffect(Buffs.RiddleOfFire) && + LevelChecked(Meditation)) + return OriginalHook(Meditation); + + if (!InCombat() && !HasEffect(Buffs.FormlessFist)) + return FormShift; + //Variant Cure if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && IsEnabled(Variant.VariantCure) && PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; - if ((!InCombat() || !InMeleeRange()) && - Gauge.Chakra < 5 && - HasEffect(Buffs.RiddleOfFire) && - LevelChecked(Meditation)) - return OriginalHook(Meditation); - // OGCDs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -126,52 +129,64 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; - if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance) && - (((JustUsed(LeapingOpo) || JustUsed(DragonKick)) && - GetCooldownRemainingTime(RiddleOfFire) < 8 && - GetCooldownRemainingTime(Brotherhood) < 7) || - (GetBuffRemainingTime(Buffs.RiddleOfFire) >= 8 && - !HasEffect(Buffs.FiresRumination)))) - return PerfectBalance; - - if (ActionReady(Brotherhood)) + if (IsEnabled(CustomComboPreset.MNK_STUseBrotherhood) && + ActionReady(Brotherhood)) return Brotherhood; - if (ActionReady(RiddleOfFire)) + if (IsEnabled(CustomComboPreset.MNK_STUseROF) && + ActionReady(RiddleOfFire)) return RiddleOfFire; - if (ActionReady(RiddleOfWind)) + if (IsEnabled(CustomComboPreset.MNK_STUseROW) && + ActionReady(RiddleOfWind)) return RiddleOfWind; - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + //Perfect Balance + if (ActionReady(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance)) + { + // Odd window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + !JustUsed(PerfectBalance, 20) && + HasEffect(Buffs.RiddleOfFire) && + !HasEffect(Buffs.Brotherhood)) + return PerfectBalance; + + // Even window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + HasEffect(Buffs.Brotherhood) && + HasEffect(Buffs.RiddleOfFire)) + return PerfectBalance; + + // Low level + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || + !LevelChecked(RiddleOfFire))) + return PerfectBalance; + } + + if (PlayerHealthPercentageHp() <= 25 && + ActionReady(All.SecondWind)) return All.SecondWind; - if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) + if (PlayerHealthPercentageHp() <= 40 && + ActionReady(All.Bloodbath)) return All.Bloodbath; if (Gauge.Chakra >= 5 && - SteelPeak.LevelChecked()) - return OriginalHook(SteelPeak); + LevelChecked(SteelPeak)) + return OriginalHook(Meditation); } // GCDs - // Ensure usage if buff is almost depleted. - if (HasEffect(Buffs.FiresRumination) && - GetBuffRemainingTime(Buffs.FiresRumination) < 4) - return FiresReply; - - if (HasEffect(Buffs.WindsRumination) && - GetBuffRemainingTime(Buffs.WindsRumination) < 4) - return WindsReply; - if (HasEffect(Buffs.FormlessFist)) return Gauge.OpoOpoFury == 0 - ? OriginalHook(DragonKick) + ? DragonKick : OriginalHook(Bootshine); // Masterful Blitz - if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && - (HasEffect(Buffs.RiddleOfFire) || GetCooldownRemainingTime(RiddleOfFire) > 35) && + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && !IsOriginal(MasterfulBlitz)) return OriginalHook(MasterfulBlitz); @@ -184,17 +199,17 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb { if (coeurlChakra == 0) return Gauge.CoeurlFury == 0 - ? OriginalHook(Demolish) + ? Demolish : OriginalHook(SnapPunch); if (raptorChakra == 0) return Gauge.RaptorFury == 0 - ? OriginalHook(TwinSnakes) + ? TwinSnakes : OriginalHook(TrueStrike); if (opoOpoChakra == 0) return Gauge.OpoOpoFury == 0 - ? OriginalHook(DragonKick) + ? DragonKick : OriginalHook(Bootshine); } @@ -204,23 +219,28 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (solarNadi || lunarNadi || bothNadisOpen) return Gauge.OpoOpoFury == 0 - ? OriginalHook(DragonKick) + ? DragonKick : OriginalHook(Bootshine); #endregion } - if (HasEffect(Buffs.WindsRumination)) - return WindsReply; - if (HasEffect(Buffs.FiresRumination) && !HasEffect(Buffs.PerfectBalance) && !HasEffect(Buffs.FormlessFist) && - (JustUsed(LeapingOpo) || JustUsed(DragonKick))) + (JustUsed(OriginalHook(Bootshine)) || + JustUsed(DragonKick) || + GetBuffRemainingTime(Buffs.FiresRumination) < 4)) return FiresReply; + if (HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + (HasEffect(Buffs.RiddleOfFire) || + GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + return WindsReply; + // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID); + return MNKHelper.DetermineCoreAbility(actionID, true); } return actionID; @@ -245,8 +265,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (actionID is Bootshine or LeapingOpo) { if (IsEnabled(CustomComboPreset.MNK_STUseOpener)) + { if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) return actionID; + } if (IsEnabled(CustomComboPreset.MNK_STUseMeditation) && (!InCombat() || !InMeleeRange()) && @@ -255,6 +277,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb LevelChecked(Meditation)) return OriginalHook(Meditation); + if (IsEnabled(CustomComboPreset.MNK_STUseFormShift) && + !InCombat() && !HasEffect(Buffs.FormlessFist)) + return FormShift; + //Variant Cure if (IsEnabled(CustomComboPreset.MNK_Variant_Cure) && IsEnabled(Variant.VariantCure) && @@ -270,22 +296,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; - if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && - ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) - { - if ((JustUsed(LeapingOpo) || JustUsed(DragonKick)) && - GetCooldownRemainingTime(RiddleOfFire) < 7 && - GetCooldownRemainingTime(Brotherhood) < 7) - return PerfectBalance; - - if ((JustUsed(LeapingOpo) || JustUsed(DragonKick)) && - HasEffect(Buffs.RiddleOfFire) && - GetBuffRemainingTime(Buffs.RiddleOfFire) > 8 && - !HasEffect(Buffs.FiresRumination)) - return PerfectBalance; - } - if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) { if (IsEnabled(CustomComboPreset.MNK_STUseBrotherhood) && @@ -301,6 +311,31 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb return RiddleOfWind; } + //Perfect Balance + if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && + ActionReady(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance)) + { + // Odd window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + !JustUsed(PerfectBalance, 20) && + HasEffect(Buffs.RiddleOfFire) && + !HasEffect(Buffs.Brotherhood)) + return PerfectBalance; + + // Even window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + HasEffect(Buffs.Brotherhood) && + HasEffect(Buffs.RiddleOfFire)) + return PerfectBalance; + + // Low level + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || + !LevelChecked(RiddleOfFire))) + return PerfectBalance; + } + if (IsEnabled(CustomComboPreset.MNK_ST_ComboHeals)) { if (PlayerHealthPercentageHp() <= Config.MNK_ST_SecondWind_Threshold && @@ -319,27 +354,16 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // GCDs - // Ensure usage if buff is almost depleted. - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) && - HasEffect(Buffs.FiresRumination) && - GetBuffRemainingTime(Buffs.FiresRumination) < 4) - return FiresReply; - - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && - HasEffect(Buffs.WindsRumination) && - GetBuffRemainingTime(Buffs.WindsRumination) < 4) - return WindsReply; - if (HasEffect(Buffs.FormlessFist)) return Gauge.OpoOpoFury == 0 - ? OriginalHook(DragonKick) + ? DragonKick : OriginalHook(Bootshine); if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) { // Masterful Blitz - if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && - (HasEffect(Buffs.RiddleOfFire) || GetCooldownRemainingTime(RiddleOfFire) > 35) && + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && !IsOriginal(MasterfulBlitz)) return OriginalHook(MasterfulBlitz); @@ -352,17 +376,17 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb { if (coeurlChakra == 0) return Gauge.CoeurlFury == 0 - ? OriginalHook(Demolish) + ? Demolish : OriginalHook(SnapPunch); if (raptorChakra == 0) return Gauge.RaptorFury == 0 - ? OriginalHook(TwinSnakes) + ? TwinSnakes : OriginalHook(TrueStrike); if (opoOpoChakra == 0) return Gauge.OpoOpoFury == 0 - ? OriginalHook(DragonKick) + ? DragonKick : OriginalHook(Bootshine); } @@ -372,26 +396,29 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (solarNadi || lunarNadi || bothNadisOpen) return Gauge.OpoOpoFury == 0 - ? OriginalHook(DragonKick) + ? DragonKick : OriginalHook(Bootshine); #endregion } } - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && - HasEffect(Buffs.WindsRumination) && - LevelChecked(WindsReply)) - return WindsReply; - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) && HasEffect(Buffs.FiresRumination) && !HasEffect(Buffs.PerfectBalance) && !HasEffect(Buffs.FormlessFist) && - (JustUsed(LeapingOpo) || JustUsed(DragonKick)) && - LevelChecked(FiresReply)) + (JustUsed(OriginalHook(Bootshine)) || + JustUsed(DragonKick) || + GetBuffRemainingTime(Buffs.FiresRumination) < 4)) return FiresReply; + if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && + HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + (HasEffect(Buffs.RiddleOfFire) || + GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + return WindsReply; + // Standard Beast Chakras return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); } @@ -436,7 +463,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(PerfectBalance) && !HasEffect(Buffs.PerfectBalance) && IsOriginal(MasterfulBlitz)) - { + // Use Perfect Balance if: // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE // 2. At max stacks / before overcap. @@ -450,7 +477,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - } if (ActionReady(Brotherhood)) return Brotherhood; @@ -564,7 +590,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim LevelChecked(PerfectBalance) && !HasEffect(Buffs.PerfectBalance) && IsOriginal(MasterfulBlitz)) - { + // Use Perfect Balance if: // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE // 2. At max stacks / before overcap. @@ -578,7 +604,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - } if (IsEnabled(CustomComboPreset.MNK_AoEUseBrotherhood) && ActionReady(Brotherhood)) @@ -701,7 +726,7 @@ internal class MNK_BeastChakra_OpoOpo : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { if (IsEnabled(CustomComboPreset.MNK_BC_OPOOPO) && - actionID is Bootshine or LeapingOpo && + actionID is Bootshine or LeapingOpo && (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance))) return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) ? DragonKick @@ -718,7 +743,7 @@ internal class MNK_BeastChakra_Raptor : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { if (IsEnabled(CustomComboPreset.MNK_BC_RAPTOR) && - actionID is TrueStrike or RisingRaptor && + actionID is TrueStrike or RisingRaptor && (HasEffect(Buffs.RaptorForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance))) return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) ? TwinSnakes @@ -735,7 +760,7 @@ internal class MNK_BeastChakra_Coeurl : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { if (IsEnabled(CustomComboPreset.MNK_BC_COEURL) && - actionID is SnapPunch or PouncingCoeurl && + actionID is SnapPunch or PouncingCoeurl && (HasEffect(Buffs.CoeurlForm) || HasEffect(Buffs.FormlessFist) || HasEffect(Buffs.PerfectBalance))) return Gauge.CoeurlFury == 0 && LevelChecked(Demolish) ? Demolish diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 43affc224..1d9f01d9c 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1572,12 +1572,16 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== + #region MONK if (preset == CustomComboPreset.MNK_ST_ComboHeals) { - UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_SecondWind_Threshold, "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_Bloodbath_Threshold, "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); + UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); + + UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); } if (preset == CustomComboPreset.MNK_AoE_ComboHeals) @@ -1591,8 +1595,11 @@ internal static void Draw(CustomComboPreset preset, bool enabled) if (preset == CustomComboPreset.MNK_STUseOpener && enabled) { - UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Double Lunar", "Uses Lunar/Lunar opener", 1); - UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Solar Lunar", "Uses Solar/Lunar opener", 2); + UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Double Lunar", + "Uses Lunar/Lunar opener", 0); + + UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Solar Lunar", + "Uses Solar/Lunar opener", 1); } if (preset == CustomComboPreset.MNK_Variant_Cure) From f7262c3f41309b569de77dbd3ca3951753b450c6 Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 9 Sep 2024 13:07:30 +0200 Subject: [PATCH 098/208] update AoE --- XIVSlothCombo/Combos/PvE/MNK.cs | 59 ++++++++++++++------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index a2e63d392..97c886525 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -456,31 +456,23 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IsEnabled(Variant.VariantRampart) && IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; - + + if (ActionReady(Brotherhood)) + return Brotherhood; + if (ActionReady(RiddleOfFire)) return RiddleOfFire; - if (LevelChecked(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - IsOriginal(MasterfulBlitz)) - - // Use Perfect Balance if: - // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE - // 2. At max stacks / before overcap. - // 3. During Brotherhood. - // 4. During Riddle of Fire. - // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if ((HasCharges(PerfectBalance) && - GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || + if (ActionReady(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance)) + + if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || GetCooldownRemainingTime(PerfectBalance) <= 4 || HasEffect(Buffs.Brotherhood) || (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - - if (ActionReady(Brotherhood)) - return Brotherhood; - + if (ActionReady(RiddleOfWind)) return RiddleOfWind; @@ -503,7 +495,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return FiresReply; // Masterful Blitz - if (MasterfulBlitz.LevelChecked() && !HasEffect(Buffs.PerfectBalance) && + if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) return OriginalHook(MasterfulBlitz); @@ -512,7 +504,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (nadiNone || !lunarNadi) if (pbStacks?.StackCount > 0) - return ShadowOfTheDestroyer.LevelChecked() + return LevelChecked(ShadowOfTheDestroyer) ? ShadowOfTheDestroyer : Rockbreaker; @@ -582,14 +574,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; + if (IsEnabled(CustomComboPreset.MNK_AoEUseBrotherhood) && + ActionReady(Brotherhood)) + return Brotherhood; + if (IsEnabled(CustomComboPreset.MNK_AoEUseROF) && ActionReady(RiddleOfFire)) return RiddleOfFire; if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance) && - LevelChecked(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - IsOriginal(MasterfulBlitz)) + ActionReady(PerfectBalance) && + !HasEffect(Buffs.PerfectBalance)) // Use Perfect Balance if: // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE @@ -597,18 +592,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // 3. During Brotherhood. // 4. During Riddle of Fire. // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if ((HasCharges(PerfectBalance) && - GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)) || + if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)|| GetCooldownRemainingTime(PerfectBalance) <= 4 || HasEffect(Buffs.Brotherhood) || (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - - if (IsEnabled(CustomComboPreset.MNK_AoEUseBrotherhood) && - ActionReady(Brotherhood)) - return Brotherhood; - + if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && ActionReady(RiddleOfWind)) return RiddleOfWind; @@ -642,7 +632,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Masterful Blitz if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance)) { - if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) return OriginalHook(MasterfulBlitz); @@ -651,7 +642,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (nadiNone || !lunarNadi) if (pbStacks?.StackCount > 0) - return ShadowOfTheDestroyer.LevelChecked() + return LevelChecked(ShadowOfTheDestroyer) ? ShadowOfTheDestroyer : Rockbreaker; @@ -697,9 +688,9 @@ internal class MNK_PerfectBalance : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - if (actionID == PerfectBalance) - if (OriginalHook(MasterfulBlitz) != MasterfulBlitz && MasterfulBlitz.LevelChecked()) - return OriginalHook(MasterfulBlitz); + if (actionID is PerfectBalance && + OriginalHook(MasterfulBlitz) != MasterfulBlitz && LevelChecked(MasterfulBlitz)) + return OriginalHook(MasterfulBlitz); return actionID; } From 063111f687cd5331c01e37e495356008f48d76c7 Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 9 Sep 2024 13:08:29 +0200 Subject: [PATCH 099/208] remove unused code --- XIVSlothCombo/Combos/PvE/MNK.cs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 97c886525..c44eda054 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -7,7 +7,6 @@ using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; -using XIVSlothCombo.Extensions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; @@ -265,10 +264,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (actionID is Bootshine or LeapingOpo) { if (IsEnabled(CustomComboPreset.MNK_STUseOpener)) - { if (MNKOpener.DoFullOpener(ref actionID, Config.MNK_SelectedOpener)) return actionID; - } if (IsEnabled(CustomComboPreset.MNK_STUseMeditation) && (!InCombat() || !InMeleeRange()) && @@ -456,23 +453,23 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IsEnabled(Variant.VariantRampart) && IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; - - if (ActionReady(Brotherhood)) + + if (ActionReady(Brotherhood)) return Brotherhood; - + if (ActionReady(RiddleOfFire)) return RiddleOfFire; if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance)) - + if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || GetCooldownRemainingTime(PerfectBalance) <= 4 || HasEffect(Buffs.Brotherhood) || (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - + if (ActionReady(RiddleOfWind)) return RiddleOfWind; @@ -592,13 +589,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // 3. During Brotherhood. // 4. During Riddle of Fire. // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance)|| + if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || GetCooldownRemainingTime(PerfectBalance) <= 4 || HasEffect(Buffs.Brotherhood) || (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - + if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && ActionReady(RiddleOfWind)) return RiddleOfWind; @@ -632,7 +629,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Masterful Blitz if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance)) { - if (LevelChecked(MasterfulBlitz) && + if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) return OriginalHook(MasterfulBlitz); From 2ca46121a8678fada9f9e30e72f9af8114ab843c Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 9 Sep 2024 13:52:48 +0200 Subject: [PATCH 100/208] link everything to correct options --- XIVSlothCombo/Combos/PvE/MNK.cs | 110 ++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index c44eda054..357698116 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -128,16 +128,14 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; - if (IsEnabled(CustomComboPreset.MNK_STUseBrotherhood) && - ActionReady(Brotherhood)) + if (ActionReady(Brotherhood)) return Brotherhood; - if (IsEnabled(CustomComboPreset.MNK_STUseROF) && - ActionReady(RiddleOfFire)) + if (ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return RiddleOfFire; - if (IsEnabled(CustomComboPreset.MNK_STUseROW) && - ActionReady(RiddleOfWind)) + if (ActionReady(RiddleOfWind)) return RiddleOfWind; //Perfect Balance @@ -284,6 +282,12 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; + if (IsEnabled(CustomComboPreset.MNK_STUseBuffs) && + IsEnabled(CustomComboPreset.MNK_STUseROF) && + ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) + return RiddleOfFire; + // OGCDs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -299,10 +303,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb ActionReady(Brotherhood)) return Brotherhood; - if (IsEnabled(CustomComboPreset.MNK_STUseROF) && - ActionReady(RiddleOfFire)) - return RiddleOfFire; - if (IsEnabled(CustomComboPreset.MNK_STUseROW) && ActionReady(RiddleOfWind)) return RiddleOfWind; @@ -400,21 +400,26 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } } - if (IsEnabled(CustomComboPreset.MNK_STUseFiresReply) && - HasEffect(Buffs.FiresRumination) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist) && - (JustUsed(OriginalHook(Bootshine)) || - JustUsed(DragonKick) || - GetBuffRemainingTime(Buffs.FiresRumination) < 4)) - return FiresReply; - - if (IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && - HasEffect(Buffs.WindsRumination) && - LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfFire) || - GetBuffRemainingTime(Buffs.WindsRumination) < 4)) - return WindsReply; + if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) + { + if (IsEnabled(CustomComboPreset.MNK_STUseROF) && + IsEnabled(CustomComboPreset.MNK_STUseFiresReply) && + HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist) && + (JustUsed(OriginalHook(Bootshine)) || + JustUsed(DragonKick) || + GetBuffRemainingTime(Buffs.FiresRumination) < 4)) + return FiresReply; + + if (IsEnabled(CustomComboPreset.MNK_STUseROW) && + IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && + HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + (HasEffect(Buffs.RiddleOfFire) || + GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + return WindsReply; + } // Standard Beast Chakras return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); @@ -445,6 +450,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; + if (ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) + return RiddleOfFire; + // Buffs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -456,9 +465,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionReady(Brotherhood)) return Brotherhood; - - if (ActionReady(RiddleOfFire)) - return RiddleOfFire; + + if (ActionReady(RiddleOfWind)) + return RiddleOfWind; if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance)) @@ -470,9 +479,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - if (ActionReady(RiddleOfWind)) - return RiddleOfWind; - if (Gauge.Chakra >= 5 && LevelChecked(HowlingFist) && HasBattleTarget()) @@ -562,6 +568,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; + if (IsEnabled(CustomComboPreset.MNK_AoEUseBuffs) && + IsEnabled(CustomComboPreset.MNK_AoEUseROF) && + ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) + return RiddleOfFire; + // Buffs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -571,13 +583,16 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IsOffCooldown(Variant.VariantRampart)) return Variant.VariantRampart; - if (IsEnabled(CustomComboPreset.MNK_AoEUseBrotherhood) && - ActionReady(Brotherhood)) - return Brotherhood; + if (IsEnabled(CustomComboPreset.MNK_AoEUseBuffs)) + { + if (IsEnabled(CustomComboPreset.MNK_AoEUseBrotherhood) && + ActionReady(Brotherhood)) + return Brotherhood; - if (IsEnabled(CustomComboPreset.MNK_AoEUseROF) && - ActionReady(RiddleOfFire)) - return RiddleOfFire; + if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && + ActionReady(RiddleOfWind)) + return RiddleOfWind; + } if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance) && ActionReady(PerfectBalance) && @@ -596,10 +611,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) return PerfectBalance; - if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && - ActionReady(RiddleOfWind)) - return RiddleOfWind; - if (IsEnabled(CustomComboPreset.MNK_AoEUseHowlingFist) && Gauge.Chakra >= 5 && LevelChecked(HowlingFist) && @@ -618,13 +629,18 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } - if (IsEnabled(CustomComboPreset.MNK_AoEUseWindsReply) && - HasEffect(Buffs.WindsRumination)) - return WindsReply; + if (IsEnabled(CustomComboPreset.MNK_AoEUseBuffs)) + { + if (IsEnabled(CustomComboPreset.MNK_AoEUseROF) && + IsEnabled(CustomComboPreset.MNK_AoEUseFiresReply) && + HasEffect(Buffs.FiresRumination)) + return FiresReply; - if (IsEnabled(CustomComboPreset.MNK_AoEUseFiresReply) && - HasEffect(Buffs.FiresRumination)) - return FiresReply; + if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && + IsEnabled(CustomComboPreset.MNK_AoEUseWindsReply) && + HasEffect(Buffs.WindsRumination)) + return WindsReply; + } // Masterful Blitz if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance)) From 395cbebf374cc600f6e931c7d86baad89f289dda Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 9 Sep 2024 15:36:38 +0200 Subject: [PATCH 101/208] add lvlcheck formshift --- XIVSlothCombo/Combos/PvE/MNK.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 357698116..229539948 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -110,7 +110,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb LevelChecked(Meditation)) return OriginalHook(Meditation); - if (!InCombat() && !HasEffect(Buffs.FormlessFist)) + if (!InCombat() && LevelChecked(FormShift) && + !HasEffect(Buffs.FormlessFist)) return FormShift; //Variant Cure @@ -273,7 +274,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb return OriginalHook(Meditation); if (IsEnabled(CustomComboPreset.MNK_STUseFormShift) && - !InCombat() && !HasEffect(Buffs.FormlessFist)) + !InCombat() && LevelChecked(FormShift) && + !HasEffect(Buffs.FormlessFist)) return FormShift; //Variant Cure From c5528454e8441206b12587df50c4c39a05d326e7 Mon Sep 17 00:00:00 2001 From: edewen Date: Mon, 9 Sep 2024 20:16:14 -0400 Subject: [PATCH 102/208] Dynamic Ninja TN Reworked Dynamic true north ninja option. Will dynamically choose finisher based on position and charges. Prevents overcap and waste and uses true north as needed. --- XIVSlothCombo/Combos/CustomComboPreset.cs | 8 ++- XIVSlothCombo/Combos/PvE/NIN.cs | 67 +++++++++++++++++------ 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 3669dbb42..708859a9a 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2188,6 +2188,7 @@ public enum CustomComboPreset NIN_ST_AdvancedMode_TrueNorth = 10030, [ParentCombo(NIN_ST_AdvancedMode_TrueNorth)] + [ConflictingCombos(NIN_ST_AdvancedMode_Dynamic)] [CustomComboInfo("Use Before Armor Crush Only Option", "Only triggers the use of True North before Armor Crush.", NIN.JobID)] NIN_ST_AdvancedMode_TrueNorth_ArmorCrush = 10031, @@ -2321,9 +2322,10 @@ public enum CustomComboPreset [CustomComboInfo("Suiton Uptime Option", "Adds Suiton as an uptime feature.", NIN.JobID)] NIN_ST_AdvancedMode_Suiton_Uptime = 10067, - //[ParentCombo(NIN_ST_AdvancedMode_TrueNorth_ArmorCrush)] Removed because true north is going to be dynamic inherently. Armor crush happens far more often now. Can just elimite all AC with TN. - //[CustomComboInfo("Dynamic True North Option", "Adds True North before Armor Crush when you are not in the correct position for the enhanced potency bonus.", NIN.JobID)] - //NIN_ST_AdvancedMode_TrueNorth_ArmorCrush_Dynamic = 10068, + [ParentCombo(NIN_ST_AdvancedMode_TrueNorth)] + [ConflictingCombos(NIN_ST_AdvancedMode_TrueNorth_ArmorCrush)] + [CustomComboInfo("Dynamic Ninja Positional Option", "Dynamic choice of Armor crush/Aeolian Edge based on position and available charges.\nGo to Flank to build charges, Rear to spend them. \nPrevents overcap or waste and will use true north as needed." , NIN.JobID)] + NIN_ST_AdvancedMode_Dynamic = 10068, [Variant] [VariantParent(NIN_ST_SimpleMode, NIN_ST_AdvancedMode, NIN_AoE_SimpleMode, NIN_AoE_AdvancedMode)] diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN.cs index 73577322e..6e08fc413 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN.cs @@ -173,7 +173,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var comboLength = GetCooldown(GustSlash).CooldownTotal * 3; bool trueNorthArmor = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth) && TargetNeedsPositionals() && !OnTargetsFlank() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canDelayedWeave; bool trueNorthEdge = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth) && TargetNeedsPositionals() && IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrueNorth_ArmorCrush) && !OnTargetsRear() && GetRemainingCharges(All.TrueNorth) > 0 && All.TrueNorth.LevelChecked() && !HasEffect(All.Buffs.TrueNorth) && canDelayedWeave; - + bool dynamic = IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Dynamic); + if (IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus) || (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5 && !InCombat())) mudraState.CurrentMudra = MudraCasting.MudraState.None; @@ -380,44 +381,74 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (lastComboMove == SpinningEdge && GustSlash.LevelChecked()) return OriginalHook(GustSlash); - + if (lastComboMove == GustSlash && ArmorCrush.LevelChecked()) { - if (!NINHelper.MugDebuff && GetTargetHPPercent() > burnKazematoi) - { - if (gauge.Kazematoi < 4) + if (dynamic) + { + if (gauge.Kazematoi > 3) + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } + + if (gauge.Kazematoi == 0) { if (trueNorthArmor) return OriginalHook(All.TrueNorth); else return OriginalHook(ArmorCrush); } - else + if ((gauge.Kazematoi > 0) && (gauge.Kazematoi < 4)) { - if (trueNorthEdge) - return OriginalHook(All.TrueNorth); + if (OnTargetsFlank()) + return OriginalHook(ArmorCrush); else return OriginalHook(AeolianEdge); } + + } - if (NINHelper.MugDebuff || GetTargetHPPercent() <= burnKazematoi) + if (!dynamic) { - if (gauge.Kazematoi == 0) + if (!NINHelper.MugDebuff && GetTargetHPPercent() > burnKazematoi) { - if (trueNorthArmor) - return OriginalHook(All.TrueNorth); + if (gauge.Kazematoi < 4) + { + if (trueNorthArmor) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(ArmorCrush); + } else - return OriginalHook(ArmorCrush); + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } } - else + if (NINHelper.MugDebuff || GetTargetHPPercent() <= burnKazematoi) { - if (trueNorthEdge) - return OriginalHook(All.TrueNorth); + if (gauge.Kazematoi == 0) + { + if (trueNorthArmor) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(ArmorCrush); + } else - return OriginalHook(AeolianEdge); + { + if (trueNorthEdge) + return OriginalHook(All.TrueNorth); + else + return OriginalHook(AeolianEdge); + } } } - } + } if (lastComboMove == GustSlash && !ArmorCrush.LevelChecked() && AeolianEdge.LevelChecked()) { if (trueNorthEdge) From c6fb3d185cfd2cbae98b34754b17bfb833c7e321 Mon Sep 17 00:00:00 2001 From: edewen Date: Tue, 10 Sep 2024 14:58:21 -0400 Subject: [PATCH 103/208] ow level fix for 30-45 Added low level section before suiton to raiton and fuma correctly --- XIVSlothCombo/Combos/PvE/NIN.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN.cs index 6e08fc413..ec2c6da4a 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN.cs @@ -178,12 +178,23 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus) || (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5 && !InCombat())) mudraState.CurrentMudra = MudraCasting.MudraState.None; - + if (IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_Suiton) && IsOnCooldown(TrickAttack) && mudraState.CurrentMudra == MudraCasting.MudraState.CastingSuiton && !setupSuitonWindow) mudraState.CurrentMudra = MudraCasting.MudraState.None; if (IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_Suiton) && IsOnCooldown(TrickAttack) && mudraState.CurrentMudra != MudraCasting.MudraState.CastingSuiton && setupSuitonWindow) mudraState.CurrentMudra = MudraCasting.MudraState.CastingSuiton; + + if (!Suiton.LevelChecked()) //For low level + { + if (Raiton.LevelChecked() && IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_Raiton)) //under 45 will only use Raiton + { + if (mudraState.CastRaiton(ref actionID)) + return actionID; + } + else if (!Raiton.LevelChecked() && mudraState.CastFumaShuriken(ref actionID) && IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_FumaShuriken)) // 30-35 will use only fuma + return actionID; + } if (OriginalHook(Ninjutsu) is Rabbit) return OriginalHook(Ninjutsu); From a0f9cdaf28e8a57dc2e04b1bb0cdb5a29af1bcf9 Mon Sep 17 00:00:00 2001 From: edewen Date: Tue, 10 Sep 2024 23:24:53 -0400 Subject: [PATCH 104/208] Fixed super rare occurance of lightspeed happening twice in opener. Added tag to check for already having buff. --- XIVSlothCombo/Combos/PvE/AST.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 6298a0e37..387e5e0eb 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -248,7 +248,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (MaleficCount == 1 && CombustCount == 0) return OriginalHook(Combust); - if (MaleficCount == 1 && (CombustCount == 1) && ActionReady(Lightspeed) && CanDelayedWeave(actionID)) + if (MaleficCount == 1 && (CombustCount == 1) && ActionReady(Lightspeed) && CanDelayedWeave(actionID) && !HasEffect(Buffs.Lightspeed)) return OriginalHook(Lightspeed); if (MaleficCount == 3 && CanWeave(actionID)) From ca19adadacff2a8a85d93500e6a33688721690e4 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 11 Sep 2024 17:36:18 +0100 Subject: [PATCH 105/208] More autorot --- .../AutoRotation/AutoRotationConfig.cs | 10 +- .../AutoRotation/AutoRotationController.cs | 71 ++++++---- XIVSlothCombo/AutoRotation/RotationMode.cs | 11 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 127 +++++++++++++----- XIVSlothCombo/Window/Functions/Presets.cs | 2 +- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 26 ++-- XIVSlothCombo/Window/Tabs/Debug.cs | 2 + XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 8 files changed, 163 insertions(+), 88 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs index 5e2a1b949..884410fe5 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -12,9 +12,15 @@ public class AutoRotationConfig public bool InCombatOnly = false; public DPSRotationMode DPSRotationMode; public HealerRotationMode HealerRotationMode; - public TankRotationMode TankRotationMode; - public int? DPSAoETargets = 2; public HealerSettings HealerSettings = new(); + public DPSSettings DPSSettings = new(); + } + + public class DPSSettings + { + public bool FATEPriority = false; + public bool QuestPriority = false; + public int? DPSAoETargets = 2; } public class HealerSettings diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 3e3ef5564..c99d1bfa2 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -1,14 +1,18 @@ -using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.Objects.Types; using ECommons.DalamudServices; using ECommons.GameFunctions; using ECommons.GameHelpers; using ECommons.Throttlers; using FFXIVClientStructs.FFXIV.Client.Game; using System; +using System.Collections; using System.Linq; +using System.Reflection.Metadata.Ecma335; using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; using Action = Lumina.Excel.GeneratedSheets.Action; @@ -19,7 +23,7 @@ internal unsafe static class AutoRotationController { internal static void Run() { - if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) + if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted] || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) return; if (!EzThrottler.Throttle("AutoRotController", 150)) @@ -75,7 +79,7 @@ private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttribut private static bool AutomateTanking(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { - var mode = Service.Configuration.RotationConfig.TankRotationMode; + var mode = Service.Configuration.RotationConfig.DPSRotationMode; if (attributes.AutoAction.IsAoE) { return AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); @@ -113,6 +117,8 @@ public static class AutoRotationHelper DPSRotationMode.Highest_Current => DPSTargeting.GetHighestCurrentTarget(), DPSRotationMode.Lowest_Current => DPSTargeting.GetLowestCurrentTarget(), DPSRotationMode.Tank_Target => DPSTargeting.GetTankTarget(), + DPSRotationMode.Nearest => DPSTargeting.GetNearestTarget(), + DPSRotationMode.Furthest => DPSTargeting.GetFurthestTarget(), }; return target; } @@ -128,19 +134,6 @@ public static class AutoRotationHelper return target; } - if (rotationMode is TankRotationMode tankmode) - { - if (Player.Object.GetRole() != CombatRole.Tank) return null; - IGameObject? target = tankmode switch - { - TankRotationMode.Manual => Svc.Targets.Target, - TankRotationMode.Highest_Max => TankTargeting.GetHighestMaxTarget(), - TankRotationMode.Lowest_Max => TankTargeting.GetLowestMaxTarget(), - TankRotationMode.Highest_Current => TankTargeting.GetHighestCurrentTarget(), - TankRotationMode.Lowest_Current => TankTargeting.GetLowestCurrentTarget(), - }; - return target; - } return null; } @@ -165,9 +158,12 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese { uint outAct = InvokeCombo(preset, attributes, Player.Object); var target = GetSingleTarget(mode); - var mustTarget = Svc.Data.GetExcelSheet().GetRow(outAct).CanTargetHostile; - - if (CustomComboFunctions.NumberOfEnemiesInRange(outAct, target) >= Service.Configuration.RotationConfig.DPSAoETargets) + var sheet = Svc.Data.GetExcelSheet().GetRow(outAct); + var mustTarget = sheet.CanTargetHostile; + var numEnemies = CustomComboFunctions.NumberOfEnemiesInRange(outAct); + Svc.Log.Debug($"{outAct.ActionName()} {numEnemies}"); + if (numEnemies >= Service.Configuration.RotationConfig.DPSSettings.DPSAoETargets || + (sheet.EffectRange == 0 && sheet.CanTargetSelf && !mustTarget)) { var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) @@ -231,8 +227,21 @@ public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttribute } } - public static class DPSTargeting + public class DPSTargeting { + public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => IsPriority(x)); + + private static bool IsPriority(IGameObject x) + { + bool isFate = Service.Configuration.RotationConfig.DPSSettings.FATEPriority && x.Struct()->FateId != 0; + var namePlateIcon = x.Struct()->NamePlateIconId; + bool isQuest = Service.Configuration.RotationConfig.DPSSettings.QuestPriority && namePlateIcon is 71204 or 71144 or 71224 or 71344; + if (Player.Object.GetRole() is CombatRole.Tank && x.TargetObjectId != Player.Object.GameObjectId) + return true; + + return isFate || isQuest; + } + public static IGameObject? GetTankTarget() { var tank = CustomComboFunctions.GetPartyMembers().Where(x => x.GetRole() == CombatRole.Tank).FirstOrDefault(); @@ -242,24 +251,34 @@ public static class DPSTargeting return tank.TargetObject; } + public static IGameObject? GetNearestTarget() + { + return BaseSelection.OrderBy(x => CustomComboFunctions.GetTargetDistance(x)).FirstOrDefault(); + } + + public static IGameObject? GetFurthestTarget() + { + return BaseSelection.OrderByDescending(x => CustomComboFunctions.GetTargetDistance(x)).FirstOrDefault(); + } + public static IGameObject? GetLowestCurrentTarget() { - return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderBy(x => (x as IBattleChara).CurrentHp).FirstOrDefault(); + return BaseSelection.OrderBy(x => (x as IBattleChara).CurrentHp).FirstOrDefault(); } public static IGameObject? GetHighestCurrentTarget() { - return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => (x as IBattleChara).CurrentHp).FirstOrDefault(); + return BaseSelection.OrderByDescending(x => (x as IBattleChara).CurrentHp).FirstOrDefault(); } public static IGameObject? GetLowestMaxTarget() { - return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderBy(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + return BaseSelection.OrderBy(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).ThenBy(x => CustomComboFunctions.GetTargetDistance(x)).FirstOrDefault(); } public static IGameObject? GetHighestMaxTarget() { - return Svc.Objects.Where(x => x is IBattleChara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); + return BaseSelection.OrderByDescending(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); } } @@ -280,7 +299,7 @@ public static class HealerTargeting { if (CustomComboFunctions.GetPartyMembers().Count == 0) return Player.Object; var target = CustomComboFunctions.GetPartyMembers() - .Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= (TargetHasRegen(x) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP)) + .Where(x => !x.IsDead && x.IsTargetable && CustomComboFunctions.GetTargetHPPercent(x) <= (TargetHasRegen(x) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP)) .OrderByDescending(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); return target; } @@ -289,7 +308,7 @@ public static class HealerTargeting { if (CustomComboFunctions.GetPartyMembers().Count == 0) return Player.Object; var target = CustomComboFunctions.GetPartyMembers() - .Where(x => CustomComboFunctions.GetTargetHPPercent(x) <= (TargetHasRegen(x) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP)) + .Where(x => !x.IsDead && x.IsTargetable && CustomComboFunctions.GetTargetHPPercent(x) <= (TargetHasRegen(x) ? Service.Configuration.RotationConfig.HealerSettings.SingleTargetRegenHPP : Service.Configuration.RotationConfig.HealerSettings.SingleTargetHPP)) .OrderBy(x => CustomComboFunctions.GetTargetHPPercent(x)).FirstOrDefault(); return target; } diff --git a/XIVSlothCombo/AutoRotation/RotationMode.cs b/XIVSlothCombo/AutoRotation/RotationMode.cs index a3a6ef35c..3091abdbe 100644 --- a/XIVSlothCombo/AutoRotation/RotationMode.cs +++ b/XIVSlothCombo/AutoRotation/RotationMode.cs @@ -14,6 +14,8 @@ public enum DPSRotationMode Highest_Current, Lowest_Current, Tank_Target, + Nearest, + Furthest, } public enum HealerRotationMode @@ -26,13 +28,4 @@ public enum HealerRotationMode //Healer_Priority, //DPS_Priority, } - - public enum TankRotationMode - { - Manual, - Highest_Max, - Lowest_Max, - Highest_Current, - Lowest_Current, - } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 498b977e9..8d5040cbb 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -3,18 +3,17 @@ using Dalamud.Game.ClientState.Objects.Types; using ECommons; using ECommons.DalamudServices; -using ECommons.GameHelpers; -using FFXIVClientStructs.FFXIV.Client.Game.Character; +using ECommons.GameFunctions; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.System.Framework; using System; using System.Linq; using System.Numerics; using XIVSlothCombo.Data; using XIVSlothCombo.Services; +using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using StructsObject = FFXIVClientStructs.FFXIV.Client.Game.Object; -using ECommons.GameFunctions; -using XIVSlothCombo.Extensions; namespace XIVSlothCombo.CustomComboNS.Functions { @@ -177,7 +176,7 @@ public static bool CanInterruptEnemy() /// The target object to check public static bool IsInRange(IGameObject? target) { - if (target == null || target.YalmDistanceX >= 30) + if (target == null || GetTargetDistance(target, LocalPlayer) >= 30) return false; return true; @@ -418,58 +417,116 @@ public unsafe static bool EnemiesInRange(uint spellCheck) return false; } - public unsafe static int NumberOfEnemiesInRange(uint aoeSpell, IGameObject? target) + public unsafe static int NumberOfEnemiesInRange(uint aoeSpell) { - if (target is null) return 0; - ActionWatching.ActionSheet.Values.TryGetFirst(x => x.RowId == aoeSpell, out var sheetSpell); bool needsTarget = sheetSpell.CanTargetHostile; int count = 0; var enemies = Svc.Objects.Where(x => x != null && x.ObjectKind == ObjectKind.BattleNpc && x.IsTargetable && !x.IsDead).Cast().Where(x => x.BattleNpcKind is BattleNpcSubKind.Enemy or BattleNpcSubKind.BattleNpcPart).ToList(); - if (!ActionManager.CanUseActionOnTarget(7, target.Struct())) - return 0; - for (int i = 0; i < enemies.Count(); i++) { var enemyChara = enemies[i]; - if (enemyChara is null || !enemyChara.Character()->InCombat || enemyChara.Character()->IsFriend) continue; - if (ActionManager.CanUseActionOnTarget(7, enemyChara.GameObject())) { - if (!needsTarget) + return sheetSpell.CastType switch { - if (GetTargetDistance(enemyChara) <= sheetSpell.EffectRange) - count++; - } - else - { - if (target != null) - { - for (int t = 0; t < enemies.Count(); t++) - { - var nearEnemy = enemies[t]; - var dist = GetTargetDistance(nearEnemy, target); - if (dist <= sheetSpell.EffectRange) - { - count++; - } - - } - return count; - } - } + 1 => 1, + 2 => sheetSpell.CanTargetSelf ? CanCircleAoe(sheetSpell.EffectRange) : CanRangedCircleAoe(sheetSpell.EffectRange, enemyChara), + 3 => CanConeAoe(sheetSpell.EffectRange), + 4 => CanLineAoe(sheetSpell.EffectRange), + _ => 0 + }; } } return count; + } - return 0; + #region Position + public static Vector3 DirectionToVec3(float direction) + { + return new(MathF.Sin(direction), 0, MathF.Cos(direction)); } + #region Point in Circle + public static bool PointInCircle(Vector3 offsetFromOrigin, float radius) + { + return offsetFromOrigin.LengthSquared() <= radius * radius; + } + #endregion + #region Point in Cone + public static bool PointInCone(Vector3 offsetFromOrigin, Vector3 direction, float halfAngle) + { + return Vector3.Dot(Vector3.Normalize(offsetFromOrigin), direction) >= MathF.Cos(halfAngle); + } + public static bool PointInCone(Vector3 offsetFromOrigin, float direction, float halfAngle) + { + return PointInCone(offsetFromOrigin, DirectionToVec3(direction), halfAngle); + } + #endregion + #region Point in Rect + public static bool PointInRect(Vector3 offsetFromOrigin, Vector3 direction, float lenFront, float lenBack, float halfWidth) + { + var normal = new Vector3(-direction.Z, 0, direction.X); + var dotDir = Vector3.Dot(offsetFromOrigin, direction); + var dotNormal = Vector3.Dot(offsetFromOrigin, normal); + return dotDir >= -lenBack && dotDir <= lenFront && MathF.Abs(dotNormal) <= halfWidth; + } + + public static bool PointInRect(Vector3 offsetFromOrigin, float direction, float lenFront, float lenBack, float halfWidth) + { + return PointInRect(offsetFromOrigin, DirectionToVec3(direction), lenFront, lenBack, halfWidth); + } + + public static bool PointInRect(Vector3 offsetFromOrigin, Vector3 startToEnd, float halfWidth) + { + var len = startToEnd.Length(); + return PointInRect(offsetFromOrigin, startToEnd / len, len, 0, halfWidth); + } + #endregion + + #endregion + + // Circle Aoe + public static int CanCircleAoe(float effectRange) + { + return Svc.Objects.Count(o => o.ObjectKind == ObjectKind.BattleNpc && + o.IsHostile() && + o.IsTargetable && + PointInCircle(o.Position - LocalPlayer.Position, effectRange + o.HitboxRadius)); + } + + // Ranged Circle Aoe + public static int CanRangedCircleAoe(float effectRange, IGameObject target) + { + return Svc.Objects.Count(o => o.ObjectKind == ObjectKind.BattleNpc && + o.IsHostile() && + o.IsTargetable && + PointInCircle(o.Position - target.Position, effectRange)); + } + + // Cone Aoe + public static int CanConeAoe(float effectRange) + { + return Svc.Objects.Count(o => o.ObjectKind == ObjectKind.BattleNpc && + o.IsHostile() && + o.IsTargetable && + PointInCone(o.Position - LocalPlayer.Position, LocalPlayer.Rotation, 0 + o.HitboxRadius / 2f) && + PointInCircle(o.Position - LocalPlayer.Position, effectRange + o.HitboxRadius)); + } + + // Line Aoe + public static int CanLineAoe(float effectRange) + { + return Svc.Objects.Count(o => o.ObjectKind == ObjectKind.BattleNpc && + o.IsHostile() && + o.IsTargetable && + PointInRect(o.Position - LocalPlayer.Position, LocalPlayer.Rotation, effectRange, 1, 2)); + } } } diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 8a37b4fe2..ad52c6eef 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -92,7 +92,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo ImGui.Separator(); } - if (ImGui.Checkbox($"{info.Name}###{i}", ref enabled)) + if (ImGui.Checkbox($"{info.Name}###{preset}{i}", ref enabled)) { if (enabled) { diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 15eddadf9..7e3aa7cf2 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -1,6 +1,7 @@ using Dalamud.Interface.Components; using ECommons.ImGuiMethods; using ImGuiNET; +using XIVSlothCombo.AutoRotation; using XIVSlothCombo.Services; namespace XIVSlothCombo.Window.Tabs @@ -22,10 +23,8 @@ internal class AutoRotationTab : ConfigWindow changed |= ImGui.Checkbox("Only in Combat", ref cfg.InCombatOnly); } - if (ImGui.CollapsingHeader("DPS Settings")) + if (ImGui.CollapsingHeader("Damage Settings")) { - ImGuiEx.LineCentered("###DPSAutoRot", () => ImGui.Text($"These settings will apply to DPS jobs and for Healers DPS actions.")); - ImGui.Spacing(); ImGuiEx.TextUnderlined($"Targeting Mode"); changed |= ImGuiEx.EnumCombo("###DPSTargetingMode", ref cfg.DPSRotationMode); ImGuiComponents.HelpMarker("Manual - Leaves all targeting decisions to you.\n" + @@ -33,16 +32,21 @@ internal class AutoRotationTab : ConfigWindow "Lowest Max - Prioritises enemies with the lowest max HP.\n" + "Highest Current - Prioritises the enemy with the highest current HP.\n" + "Lowest Current - Prioritises the enemy with the lowest current HP.\n" + - "Tank Target - Prioritises the same target as the first tank in your group."); + "Tank Target - Prioritises the same target as the first tank in your group.\n" + + "Nearest - Prioritises the closest target to you.\n" + + "Furthest - Prioritises the furthest target from you."); ImGui.Spacing(); - var input = ImGuiEx.InputInt(100f.Scale(), "Targets Required for AoE Features", ref cfg.DPSAoETargets); + var input = ImGuiEx.InputInt(100f.Scale(), "Targets Required for AoE Damage Features", ref cfg.DPSSettings.DPSAoETargets); if (input) { changed |= input; - if (cfg.DPSAoETargets < 0) - cfg.DPSAoETargets = 0; + if (cfg.DPSSettings.DPSAoETargets < 0) + cfg.DPSSettings.DPSAoETargets = 0; } - ImGuiComponents.HelpMarker("Disabling this will turn off AoE DPS features. Otherwise will require the amount of targets required to be in range of an AoE feature's attack to use."); + ImGuiComponents.HelpMarker($"Disabling this will turn off AoE DPS features. Otherwise will require the amount of targets required to be in range of an AoE feature's attack to use. This applies to all 3 roles, and for any features that deal AoE damage."); + + changed |= ImGui.Checkbox($"Prioritise FATE Targets", ref cfg.DPSSettings.FATEPriority); + changed |= ImGui.Checkbox($"Prioritise Quest Targets", ref cfg.DPSSettings.QuestPriority); } ImGui.Spacing(); @@ -63,12 +67,6 @@ internal class AutoRotationTab : ConfigWindow changed |= ImGuiEx.SliderInt("AoE HP% Threshold", ref cfg.HealerSettings.AoETargetHPP, 1, 99, "%d%%"); ImGuiComponents.HelpMarker("If all party members within AoE healing ranges average HP% falls below this value it will use an AoE heal instead of single target heals."); } - ImGui.Spacing(); - if (ImGui.CollapsingHeader("Tank Settings")) - { - ImGuiEx.TextUnderlined($"Targeting Mode"); - changed |= ImGuiEx.EnumCombo("###TankTargetingMode", ref cfg.TankRotationMode); - } if (changed) Service.Configuration.Save(); diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 05a05fe1a..2e2ffaa8a 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -179,6 +179,8 @@ static void CustomStyleText(string label, object? value) CustomStyleText($"Can Target Friendly:", $"{debugSpell.CanTargetFriendly}"); CustomStyleText($"Can Target Party:", $"{debugSpell.CanTargetParty}"); CustomStyleText($"Can Target Area:", $"{debugSpell.TargetArea}"); + CustomStyleText($"Cast Type:", $"{debugSpell.CastType}"); + CustomStyleText($"Targets Hit:", $"{CustomComboFunctions.NumberOfEnemiesInRange(debugSpell.RowId)}"); if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.RowId)) CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.RowId])/1000f:F2}"); diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 8dfd1fd78..8a30366d8 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.1 + 0.0.0.2 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From 307d726dbbdd6ac0cbb8bcfbd1ccd54893d934ae Mon Sep 17 00:00:00 2001 From: Kage Date: Wed, 11 Sep 2024 18:39:05 +0200 Subject: [PATCH 106/208] update opener --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 157 +++++++++++-------------- 1 file changed, 66 insertions(+), 91 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index 3e3b45ea7..e830d05da 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -127,23 +127,14 @@ private bool DoPrePullSteps(ref uint actionID) if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (Gauge.Chakra < 5 && PrePullStep == 1) - { - actionID = ForbiddenMeditation; - - return true; - } - - if (!HasEffect(Buffs.FormlessFist) && - !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) - { - actionID = FormShift; + if (Gauge.Chakra < 5 && PrePullStep == 1) PrePullStep++; + else if (PrePullStep == 1) actionID = Meditation; - return true; - } + if (!HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 2) PrePullStep++; + else if (PrePullStep == 2) actionID = FormShift; - if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = DragonKick; + if (WasLastAction(DragonKick) && PrePullStep == 3) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 3) actionID = DragonKick; if (ActionWatching.CombatActions.Count > 2 && InCombat()) CurrentState = OpenerState.FailedOpener; @@ -163,42 +154,38 @@ private bool DoSlOpener(ref uint actionID) if (currentState == OpenerState.InOpener) { if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + CanWeave(ActionWatching.LastWeaponskill) && Gauge.Chakra >= 5 && - OpenerStep > 2) + OpenerStep > 9) { actionID = TheForbiddenChakra; return true; } - if ((WasLastAction(PerfectBalance) || - HasEffect(Buffs.PerfectBalance)) && OpenerStep == 1) OpenerStep++; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) + OpenerStep++; else if (OpenerStep == 1) actionID = PerfectBalance; - if (WasLastAction(TheForbiddenChakra) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = TheForbiddenChakra; - - if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = TwinSnakes; + if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = TwinSnakes; - if (WasLastWeaponskill(Demolish) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Demolish; + if (WasLastWeaponskill(Demolish) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = Demolish; - if (WasLastAbility(Brotherhood) && HasEffect(Buffs.Brotherhood) && - OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Brotherhood; + if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Brotherhood; - if (WasLastAction(RiddleOfFire) && - HasEffect(Buffs.RiddleOfFire) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = RiddleOfFire; + if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = RiddleOfFire; - // Pot + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = LeapingOpo; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = LeapingOpo; + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = TheForbiddenChakra; - if (WasLastAction(RiddleOfWind) && - HasEffect(Buffs.RiddleOfWind) && OpenerStep == 8) OpenerStep++; + if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = RiddleOfWind; if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; @@ -207,19 +194,17 @@ private bool DoSlOpener(ref uint actionID) if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; else if (OpenerStep == 10) actionID = DragonKick; - if ((WasLastWeaponskill(FiresReply) || - !HasEffect(Buffs.FiresRumination)) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = FiresReply; + if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = WindsReply; - if ((WasLastWeaponskill(WindsReply) || - !HasEffect(Buffs.WindsRumination)) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = WindsReply; + if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FiresReply; if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; else if (OpenerStep == 13) actionID = LeapingOpo; - if ((WasLastAction(PerfectBalance) || - HasEffect(Buffs.PerfectBalance)) && OpenerStep == 14) OpenerStep++; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) + OpenerStep++; else if (OpenerStep == 14) actionID = PerfectBalance; if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; @@ -234,19 +219,17 @@ private bool DoSlOpener(ref uint actionID) if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; else if (OpenerStep == 18) actionID = ElixirBurst; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) - CurrentState = OpenerState.OpenerFinished; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == 19) actionID = LeapingOpo; if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) CurrentState = OpenerState.FailedOpener; - if ((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0 && - ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) || - (OpenerStep is 6 && HasEffect(Buffs.RiddleOfFire)) || - (OpenerStep is 8 && HasEffect(Buffs.RiddleOfWind)) || - (OpenerStep is 5 && HasEffect(Buffs.Brotherhood) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3)) + if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || + (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || + (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || + (actionID is Brotherhood && IsOnCooldown(Brotherhood))) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { Svc.Log.Debug($"Failed at {actionID}"); CurrentState = OpenerState.FailedOpener; @@ -267,43 +250,39 @@ private bool DoLlOpener(ref uint actionID) if (currentState == OpenerState.InOpener) { - if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) - && Gauge.Chakra >= 5 - && OpenerStep > 2) + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + CanWeave(ActionWatching.LastWeaponskill) && + Gauge.Chakra >= 5 && + OpenerStep > 9) { actionID = TheForbiddenChakra; return true; } - if ((WasLastAction(PerfectBalance) || - HasEffect(Buffs.PerfectBalance)) && OpenerStep == 1) OpenerStep++; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) + OpenerStep++; else if (OpenerStep == 1) actionID = PerfectBalance; - if (WasLastAction(TheForbiddenChakra) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = TheForbiddenChakra; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = LeapingOpo; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = LeapingOpo; - if (WasLastWeaponskill(DragonKick) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = DragonKick; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = DragonKick; - if (WasLastAbility(Brotherhood) && HasEffect(Buffs.Brotherhood) && - OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Brotherhood; + if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Brotherhood; - if (WasLastAction(RiddleOfFire) && - HasEffect(Buffs.RiddleOfFire) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = RiddleOfFire; + if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = RiddleOfFire; - // Pot + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = LeapingOpo; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = LeapingOpo; + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = TheForbiddenChakra; - if (WasLastAction(RiddleOfWind) && - HasEffect(Buffs.RiddleOfWind) && OpenerStep == 8) OpenerStep++; + if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = RiddleOfWind; if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; @@ -312,19 +291,17 @@ private bool DoLlOpener(ref uint actionID) if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; else if (OpenerStep == 10) actionID = DragonKick; - if ((WasLastWeaponskill(FiresReply) || - !HasEffect(Buffs.FiresRumination)) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = FiresReply; + if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = WindsReply; - if ((WasLastWeaponskill(WindsReply) || - !HasEffect(Buffs.WindsRumination)) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = WindsReply; + if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FiresReply; if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; else if (OpenerStep == 13) actionID = LeapingOpo; - if ((WasLastAction(PerfectBalance) || - HasEffect(Buffs.PerfectBalance)) && OpenerStep == 14) OpenerStep++; + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) + OpenerStep++; else if (OpenerStep == 14) actionID = PerfectBalance; if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; @@ -339,19 +316,17 @@ private bool DoLlOpener(ref uint actionID) if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; else if (OpenerStep == 18) actionID = ElixirBurst; - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) - CurrentState = OpenerState.OpenerFinished; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == 19) actionID = LeapingOpo; if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) CurrentState = OpenerState.FailedOpener; - if ((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0 && - ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) || - (OpenerStep is 6 && HasEffect(Buffs.RiddleOfFire)) || - (OpenerStep is 8 && HasEffect(Buffs.RiddleOfWind)) || - (OpenerStep is 5 && HasEffect(Buffs.Brotherhood) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3)) + if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || + (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || + (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || + (actionID is Brotherhood && IsOnCooldown(Brotherhood))) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { Svc.Log.Debug($"Failed at {actionID}"); CurrentState = OpenerState.FailedOpener; From 8d1c1c0dde6529c294a956b79f2426ddb5202ecc Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 11 Sep 2024 18:28:19 +0100 Subject: [PATCH 107/208] Guess what? Autorot --- .../AutoRotation/AutoRotationController.cs | 10 +++++++++- XIVSlothCombo/CustomCombo/Functions/Misc.cs | 18 ++++++++++++++++++ XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index c99d1bfa2..9adbf7992 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -39,7 +39,8 @@ internal static void Run() var action = attributes.AutoAction; var gameAct = attributes.ReplaceSkill.ActionIDs.First(); var sheetAct = Svc.Data.GetExcelSheet().GetRow(gameAct); - if ((byte)Player.Job != attributes.CustomComboInfo.JobID) + var classToJob = CustomComboFunctions.JobIDs.ClassToJob((byte)Player.Job); + if ((byte)Player.Job != attributes.CustomComboInfo.JobID && classToJob != attributes.CustomComboInfo.JobID) continue; var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); @@ -143,6 +144,8 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese if (attributes.AutoAction.IsHeal) { uint outAct = InvokeCombo(preset, attributes, Player.Object); + if (ActionManager.Instance()->GetActionStatus(ActionType.Action, outAct) != 0) + return false; if (HealerTargeting.GetPartyMax(outAct, out int count) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP && count >= 2) { @@ -157,6 +160,9 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese else { uint outAct = InvokeCombo(preset, attributes, Player.Object); + if (ActionManager.Instance()->GetActionStatus(ActionType.Action, outAct) != 0) + return false; + var target = GetSingleTarget(mode); var sheet = Svc.Data.GetExcelSheet().GetRow(outAct); var mustTarget = sheet.CanTargetHostile; @@ -186,6 +192,8 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset return false; var outAct = InvokeCombo(preset, attributes, target); + if (ActionManager.Instance()->GetActionStatus(ActionType.Action, outAct) != 0) + return false; var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) diff --git a/XIVSlothCombo/CustomCombo/Functions/Misc.cs b/XIVSlothCombo/CustomCombo/Functions/Misc.cs index eaf4881c7..23223e93d 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Misc.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Misc.cs @@ -143,6 +143,24 @@ public static byte JobToClass(uint jobID) }; } + public static byte ClassToJob(uint classId) + { + return classId switch + { + ADV.ClassID => ADV.JobID, + BLM.ClassID => BLM.JobID, + BRD.ClassID => BRD.JobID, + DRG.ClassID => DRG.JobID, + MNK.ClassID => MNK.JobID, + NIN.ClassID => NIN.JobID, + PLD.ClassID => PLD.JobID, + SMN.ClassID => SMN.JobID, + WAR.ClassID => WAR.JobID, + WHM.ClassID => WHM.JobID, + _ => (byte)classId, + }; + } + } } } diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 8a30366d8..6ef46ae6c 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.2 + 0.0.0.3 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From b668f1bfd0ecec1f07e3acdb0ff3f04919d5836a Mon Sep 17 00:00:00 2001 From: Kage Date: Wed, 11 Sep 2024 19:32:44 +0200 Subject: [PATCH 108/208] fix prepull --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index e830d05da..506a1afc1 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -127,15 +127,18 @@ private bool DoPrePullSteps(ref uint actionID) if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (Gauge.Chakra < 5 && PrePullStep == 1) PrePullStep++; - else if (PrePullStep == 1) actionID = Meditation; + if (Gauge.Chakra == 5 && PrePullStep == 1) PrePullStep++; + else if (PrePullStep == 1) actionID = OriginalHook(Meditation); - if (!HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 2) PrePullStep++; + if (HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 2) PrePullStep++; else if (PrePullStep == 2) actionID = FormShift; if (WasLastAction(DragonKick) && PrePullStep == 3) CurrentState = OpenerState.InOpener; else if (PrePullStep == 3) actionID = DragonKick; + if (!HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 3) + currentState = OpenerState.FailedOpener; + if (ActionWatching.CombatActions.Count > 2 && InCombat()) CurrentState = OpenerState.FailedOpener; From b5494c4303bbec07b101d59a81c60414d038018c Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Thu, 12 Sep 2024 01:16:16 -0600 Subject: [PATCH 109/208] Fix issue with long delay to standard+tech when other delays occur --- XIVSlothCombo/Combos/PvE/DNC.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index b0f3ec3da..e1b513b2a 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -289,8 +289,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var needToStandardOrFinish = IsEnabled(CustomComboPreset.DNC_ST_Adv_SS) && // Enabled GetTargetHPPercent() > targetHpThresholdStandard && // HP% check - (IsOffCooldown(TechnicalStep) || // Checking burst is ready for standard - GetCooldownRemainingTime(TechnicalStep) > 5) && // Don't mangle LevelChecked(StandardStep); // More Threshold, but only for SS From 4bd33050ed94fc19179c61806eb406c94ad92d30 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Thu, 12 Sep 2024 03:31:38 -0600 Subject: [PATCH 110/208] Update heal targeting for all healers to support soft->hard->mouseOver --- XIVSlothCombo/Combos/PvE/AST.cs | 2 +- XIVSlothCombo/Combos/PvE/SCH.cs | 2 +- XIVSlothCombo/Combos/PvE/SGE.cs | 2 +- XIVSlothCombo/Combos/PvE/WHM.cs | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 0fcfac841..80be43d58 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -550,7 +550,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var canArrow = (Config.AST_ST_SimpleHeals_WeaveArrow && CanSpellWeave(actionID)) || !Config.AST_ST_SimpleHeals_WeaveArrow; //Grab our target (Soft->Hard->Self) - IGameObject? healTarget = this.OptionalTarget != null ? this.OptionalTarget : GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Esuna) && ActionReady(All.Esuna) && GetTargetHPPercent(healTarget) >= Config.AST_ST_SimpleHeals_Esuna && diff --git a/XIVSlothCombo/Combos/PvE/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH.cs index a47823d56..b82cd5c05 100644 --- a/XIVSlothCombo/Combos/PvE/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH.cs @@ -565,7 +565,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return All.LucidDreaming; //Grab our target (Soft->Hard->Self) - IGameObject? healTarget = GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Esuna) && ActionReady(All.Esuna) && GetTargetHPPercent(healTarget) >= Config.SCH_ST_Heal_EsunaOption && diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE.cs index 8411987c0..0ec2d6a30 100644 --- a/XIVSlothCombo/Combos/PvE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE.cs @@ -497,7 +497,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (HasEffect(Buffs.Eukrasia)) return EukrasianDiagnosis; - IGameObject? healTarget = GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); if (IsEnabled(CustomComboPreset.SGE_ST_Heal_Esuna) && ActionReady(All.Esuna) && GetTargetHPPercent(healTarget) >= Config.SGE_ST_Heal_Esuna && diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 6c2f1a46d..9daacb0d4 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -319,7 +319,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool plenaryReady = ActionReady(PlenaryIndulgence) && (!Config.WHM_AoEHeals_PlenaryWeave || (Config.WHM_AoEHeals_PlenaryWeave && canWeave)); bool divineCaressReady = ActionReady(DivineCaress) && HasEffect(Buffs.DivineGrace); bool assizeReady = ActionReady(Assize) && (!Config.WHM_AoEHeals_AssizeWeave || (Config.WHM_AoEHeals_AssizeWeave && canWeave)); - var healTarget = GetHealTarget(Config.WHM_AoEHeals_MedicaMO); + var healTarget = Config.WHM_AoEHeals_MedicaMO ? GetHealTarget(Config.WHM_AoEHeals_MedicaMO) : LocalPlayer; var hasMedica2 = FindEffect(Buffs.Medica2, healTarget, LocalPlayer?.GameObjectId); var hasMedica3 = FindEffect(Buffs.Medica3, healTarget, LocalPlayer?.GameObjectId); @@ -378,7 +378,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Cure) { WHMGauge? gauge = GetJobGauge(); - IGameObject? healTarget = GetHealTarget(Config.WHM_STHeals_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.WHM_STHeals_UIMouseOver); + bool canWeave = CanSpellWeave(actionID, 0.3); bool thinAirReady = LevelChecked(ThinAir) && !HasEffect(Buffs.ThinAir) && GetRemainingCharges(ThinAir) > Config.WHM_STHeals_ThinAir; bool lucidReady = ActionReady(All.LucidDreaming) && LocalPlayer.CurrentMp <= Config.WHM_STHeals_Lucid; From 104e31d00dfc7e796672ef34942be7886b76fa8c Mon Sep 17 00:00:00 2001 From: Kage Date: Thu, 12 Sep 2024 15:37:26 +0200 Subject: [PATCH 111/208] add variant options on simple mode --- XIVSlothCombo/Combos/CustomComboPreset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 936d7cd6d..b5dae288f 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2101,12 +2101,12 @@ public enum CustomComboPreset #region Variant [Variant] - [VariantParent(MNK_ST_AdvancedMode, MNK_AOE_SimpleMode)] + [VariantParent(MNK_ST_SimpleMode,MNK_ST_AdvancedMode, MNK_AOE_SimpleMode,MNK_AOE_AdvancedMode)] [CustomComboInfo("Rampart Option", "Use Variant Rampart on cooldown.", MNK.JobID)] MNK_Variant_Rampart = 9025, [Variant] - [VariantParent(MNK_ST_AdvancedMode, MNK_AOE_SimpleMode)] + [VariantParent(MNK_ST_SimpleMode, MNK_ST_AdvancedMode, MNK_AOE_SimpleMode, MNK_AOE_AdvancedMode)] [CustomComboInfo("Cure Option", "Use Variant Cure when HP is below set threshold.", MNK.JobID)] MNK_Variant_Cure = 9026, From 800fed98ece20b9a59cf8894eafa35a70bf92366 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Thu, 12 Sep 2024 14:55:02 +0100 Subject: [PATCH 112/208] Autorot AoE fixes --- XIVSlothCombo/AutoRotation/AutoRotationController.cs | 5 +---- XIVSlothCombo/Combos/JobHelpers/SGE.cs | 7 ++++--- XIVSlothCombo/Combos/PvE/SGE.cs | 2 +- XIVSlothCombo/Combos/PvE/WHM.cs | 2 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 9 +++++---- XIVSlothCombo/Data/ActionWatching.cs | 2 +- XIVSlothCombo/Window/Tabs/Debug.cs | 7 +++++-- XIVSlothCombo/XIVSlothCombo.cs | 4 +--- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 9adbf7992..7a8ee6e06 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -160,14 +160,13 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese else { uint outAct = InvokeCombo(preset, attributes, Player.Object); - if (ActionManager.Instance()->GetActionStatus(ActionType.Action, outAct) != 0) + if (!CustomComboFunctions.ActionReady(outAct)) return false; var target = GetSingleTarget(mode); var sheet = Svc.Data.GetExcelSheet().GetRow(outAct); var mustTarget = sheet.CanTargetHostile; var numEnemies = CustomComboFunctions.NumberOfEnemiesInRange(outAct); - Svc.Log.Debug($"{outAct.ActionName()} {numEnemies}"); if (numEnemies >= Service.Configuration.RotationConfig.DPSSettings.DPSAoETargets || (sheet.EffectRange == 0 && sheet.CanTargetSelf && !mustTarget)) { @@ -192,8 +191,6 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset return false; var outAct = InvokeCombo(preset, attributes, target); - if (ActionManager.Instance()->GetActionStatus(ActionType.Action, outAct) != 0) - return false; var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) diff --git a/XIVSlothCombo/Combos/JobHelpers/SGE.cs b/XIVSlothCombo/Combos/JobHelpers/SGE.cs index 84425e8f3..51e1eb728 100644 --- a/XIVSlothCombo/Combos/JobHelpers/SGE.cs +++ b/XIVSlothCombo/Combos/JobHelpers/SGE.cs @@ -1,13 +1,14 @@ -using XIVSlothCombo.Combos.PvE; +using Dalamud.Game.ClientState.Objects.Types; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; namespace XIVSlothCombo.Combos.JobHelpers { internal class SGE : CustomComboFunctions { - public static int GetMatchingConfigST(int i, out uint action, out bool enabled) + public static int GetMatchingConfigST(int i, IGameObject? optionalTarget, out uint action, out bool enabled) { - var healTarget = GetHealTarget(PvE.SGE.Config.SGE_ST_Heal_Adv && PvE.SGE.Config.SGE_ST_Heal_UIMouseOver); + var healTarget = optionalTarget != null ? optionalTarget : GetHealTarget(PvE.SGE.Config.SGE_ST_Heal_Adv && PvE.SGE.Config.SGE_ST_Heal_UIMouseOver); switch (i) { diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE.cs index 8411987c0..f5b2a3f01 100644 --- a/XIVSlothCombo/Combos/PvE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE.cs @@ -517,7 +517,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim foreach (var prio in Config.SGE_ST_Heals_Priority.Items.OrderBy(x => x)) { var index = Config.SGE_ST_Heals_Priority.IndexOf(prio); - var config = JobHelpers.SGE.GetMatchingConfigST(index, out var spell, out bool enabled); + var config = JobHelpers.SGE.GetMatchingConfigST(index, this.OptionalTarget, out var spell, out bool enabled); if (enabled) { diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 6c2f1a46d..e937772b3 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -319,7 +319,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool plenaryReady = ActionReady(PlenaryIndulgence) && (!Config.WHM_AoEHeals_PlenaryWeave || (Config.WHM_AoEHeals_PlenaryWeave && canWeave)); bool divineCaressReady = ActionReady(DivineCaress) && HasEffect(Buffs.DivineGrace); bool assizeReady = ActionReady(Assize) && (!Config.WHM_AoEHeals_AssizeWeave || (Config.WHM_AoEHeals_AssizeWeave && canWeave)); - var healTarget = GetHealTarget(Config.WHM_AoEHeals_MedicaMO); + var healTarget = this.OptionalTarget != null ? this.OptionalTarget : GetHealTarget(Config.WHM_AoEHeals_MedicaMO); var hasMedica2 = FindEffect(Buffs.Medica2, healTarget, LocalPlayer?.GameObjectId); var hasMedica3 = FindEffect(Buffs.Medica3, healTarget, LocalPlayer?.GameObjectId); diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 8d5040cbb..92afbd96f 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -431,7 +431,7 @@ public unsafe static int NumberOfEnemiesInRange(uint aoeSpell) if (ActionManager.CanUseActionOnTarget(7, enemyChara.GameObject())) { - return sheetSpell.CastType switch + var numHit = sheetSpell.CastType switch { 1 => 1, 2 => sheetSpell.CanTargetSelf ? CanCircleAoe(sheetSpell.EffectRange) : CanRangedCircleAoe(sheetSpell.EffectRange, enemyChara), @@ -439,11 +439,12 @@ public unsafe static int NumberOfEnemiesInRange(uint aoeSpell) 4 => CanLineAoe(sheetSpell.EffectRange), _ => 0 }; + if (numHit > count) + count = numHit; } - - } + return count; } @@ -507,7 +508,7 @@ public static int CanRangedCircleAoe(float effectRange, IGameObject target) return Svc.Objects.Count(o => o.ObjectKind == ObjectKind.BattleNpc && o.IsHostile() && o.IsTargetable && - PointInCircle(o.Position - target.Position, effectRange)); + CustomComboFunctions.GetTargetDistance(target, o) <= effectRange); } // Cone Aoe diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index db25c8208..cc3d26cc7 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -101,7 +101,7 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp TimeLastActionUsed = DateTime.Now; ActionType = actionType; - Svc.Log.Debug($"{actionId} {sequence} {a5} {a6} {a7} {a8} {a9}"); + Svc.Log.Verbose($"{actionId} {sequence} {a5} {a6} {a7} {a8} {a9}"); } catch (Exception ex) { diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 2e2ffaa8a..f5d86f64c 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -148,8 +148,11 @@ static void CustomStyleText(string label, object? value) debugSpell = null; } - var classId = CustomComboFunctions.JobIDs.JobToClass(JobID.Value); - foreach (var act in Svc.Data.GetExcelSheet().Where(x => x.IsPlayerAction && x.ClassJob.Row == classId || x.ClassJob.Row == JobID.Value).OrderBy(x => x.ClassJobLevel)) + var classId = CustomComboFunctions.JobIDs.JobToClass(JobID!.Value); + var cjc = Svc.Data.Excel.GetSheetRaw("ClassJobCategory"); + var cjcColumIdx = cjc.Columns[JobID.Value]; + + foreach (var act in Svc.Data.GetExcelSheet()!.Where(x => x.IsPlayerAction && (x.ClassJob.Row == classId || x.ClassJob.Row == JobID.Value)).OrderBy(x => x.ClassJobLevel)) { if (ImGui.Selectable($"({act.RowId}) Lv.{act.ClassJobLevel}. {act.Name} - {(act.IsPvP ? "PvP" : "Normal")}", debugSpell?.RowId == act.RowId)) { diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index cd38ecac6..39d729093 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -86,7 +86,6 @@ public static uint? JobID if (jobID != value && value != null) { Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember = null; - Svc.Log.Debug($"Switched to job {value}"); PvEFeatures.HasToOpenJob = true; } jobID = value; @@ -129,7 +128,7 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) }); DtrBarEntry ??= Svc.DtrBar.Get("Wrath Combo"); - DtrBarEntry.OnClick = () => { Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; }; + DtrBarEntry.OnClick = () => { Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; Service.Configuration.Save(); }; Svc.ClientState.Login += PrintLoginMessage; if (Svc.ClientState.IsLoggedIn) ResetFeatures(); @@ -609,7 +608,6 @@ private void OnCommand(string command, string arguments) { var jobname = ConfigWindow.groupedPresets.Where(x => x.Value.Any(y => y.Info.JobShorthand.Equals(argumentsParts[0].ToLower(), StringComparison.CurrentCultureIgnoreCase))).FirstOrDefault().Key; var header = $"{jobname} - {argumentsParts[0].ToUpper()}"; - Svc.Log.Debug($"{jobname}"); PvEFeatures.HeaderToOpen = header; } break; From bcc20d9b9cf176dacdc173445d310bd2517a4eee Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 12 Sep 2024 08:58:11 -0500 Subject: [PATCH 113/208] PCT Variant on Simple Mode --- XIVSlothCombo/Combos/CustomComboPreset.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 930761fc5..8c0319314 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2606,17 +2606,21 @@ public enum CustomComboPreset [CustomComboInfo("One Button Paint", "Consolidates paint-consuming actions into one button.", PCT.JobID)] CombinedPaint = 20004, + // Last value for AoE = 20067 + #endregion + + #region Variant + [Variant] - [VariantParent(PCT_ST_AdvancedMode, PCT_AoE_AdvancedMode)] + [VariantParent(PCT_ST_SimpleMode, PCT_AoE_SimpleMode, PCT_ST_AdvancedMode, PCT_AoE_AdvancedMode)] [CustomComboInfo("Cure Option", "Use Variant Cure when HP is below set threshold.", PCT.JobID)] PCT_Variant_Cure = 20100, [Variant] - [VariantParent(PCT_ST_AdvancedMode, PCT_AoE_AdvancedMode)] + [VariantParent(PCT_ST_SimpleMode, PCT_AoE_SimpleMode, PCT_ST_AdvancedMode, PCT_AoE_AdvancedMode)] [CustomComboInfo("Rampart Option", "Use Variant Rampart on cooldown.", PCT.JobID)] PCT_Variant_Rampart = 20101, - // Last value for AoE = 20067 #endregion #endregion From a9512b0997d54e0def4b546b431c2ebc4c22dc52 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:00:02 -0500 Subject: [PATCH 114/208] PCT Variant on Simple Modes pt 2 --- XIVSlothCombo/Combos/PvE/PCT.cs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index 2ab1524d0..28ef227ab 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -97,6 +97,19 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + // Variant Cure + if (IsEnabled(CustomComboPreset.PCT_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.PCT_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.PCT_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + canWeave) + return Variant.VariantRampart; + if (HasEffect(Buffs.Starstruck)) return OriginalHook(StarPrism); @@ -478,6 +491,19 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb var gauge = GetJobGauge(); bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + // Variant Cure + if (IsEnabled(CustomComboPreset.PCT_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.PCT_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.PCT_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + canWeave) + return Variant.VariantRampart; + if (HasEffect(Buffs.Starstruck)) return OriginalHook(StarPrism); @@ -868,4 +894,4 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } } } -} \ No newline at end of file +} From 4f55e8de7d0efd7e82933e5b0f363bb2ce748ede Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:11:34 -0500 Subject: [PATCH 115/208] VPR Variant in Simple pt 1 --- XIVSlothCombo/Combos/CustomComboPreset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 6596327fc..c5d14a592 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4219,12 +4219,12 @@ The three digets after RDM.JobID can be used to reorder items in the list VPR_VicepitDens_oGCDs = 30207, [Variant] - [VariantParent(VPR_ST_AdvancedMode, VPR_AoE_AdvancedMode)] + [VariantParent(VPR_ST_SimpleMode, VPR_AoE_SimpleMode, VPR_ST_AdvancedMode, VPR_AoE_AdvancedMode)] [CustomComboInfo("Cure Option", "Use Variant Cure when HP is below set threshold.", VPR.JobID)] VPR_Variant_Cure = 30300, [Variant] - [VariantParent(VPR_ST_AdvancedMode, VPR_AoE_AdvancedMode)] + [VariantParent(VPR_ST_SimpleMode, VPR_AoE_SimpleMode, VPR_ST_AdvancedMode, VPR_AoE_AdvancedMode)] [CustomComboInfo("Rampart Option", "Use Variant Rampart on cooldown.", VPR.JobID)] VPR_Variant_Rampart = 30301, From 430db18d5bb2c15c59a936b5ec2870347e8b62bf Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:14:02 -0500 Subject: [PATCH 116/208] VPR Variant in Simple pt 2 --- XIVSlothCombo/Combos/PvE/VPR.cs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs index e10d0c009..c00e43775 100644 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR.cs @@ -137,6 +137,19 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (VPROpener.DoFullOpener(ref actionID)) return actionID; + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + //Serpents Ire - ForceWeave if (InCombat() && CanWeave(UncoiledFury) && !CappedOnCoils && ActionReady(SerpentsIre)) return SerpentsIre; @@ -620,6 +633,19 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (CanWeave(ActionWatching.LastWeaponskill)) { + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + // Death Rattle if (LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is LastLash) return OriginalHook(SerpentsTail); @@ -1159,4 +1185,4 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } } -} \ No newline at end of file +} From a2954040085728b772b683cb0301ca4633253f12 Mon Sep 17 00:00:00 2001 From: Kage Date: Fri, 13 Sep 2024 18:22:25 +0200 Subject: [PATCH 117/208] add delayed weave to RoF and RoW in opener --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index 506a1afc1..08cac0aef 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -180,7 +180,7 @@ private bool DoSlOpener(ref uint actionID) else if (OpenerStep == 4) actionID = Brotherhood; if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = RiddleOfFire; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; else if (OpenerStep == 6) actionID = LeapingOpo; @@ -189,7 +189,7 @@ private bool DoSlOpener(ref uint actionID) else if (OpenerStep == 7) actionID = TheForbiddenChakra; if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = RiddleOfWind; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; else if (OpenerStep == 9) actionID = RisingPhoenix; @@ -277,7 +277,7 @@ private bool DoLlOpener(ref uint actionID) else if (OpenerStep == 4) actionID = Brotherhood; if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = RiddleOfFire; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; else if (OpenerStep == 6) actionID = LeapingOpo; @@ -286,7 +286,7 @@ private bool DoLlOpener(ref uint actionID) else if (OpenerStep == 7) actionID = TheForbiddenChakra; if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = RiddleOfWind; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; else if (OpenerStep == 9) actionID = ElixirBurst; From 382925d7b983702aa1c197fad29553ccb8a772f4 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 14 Sep 2024 08:55:29 +0100 Subject: [PATCH 118/208] Typo fix --- XIVSlothCombo/Combos/CustomComboPreset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index c7f4e5070..5f727fc49 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3258,7 +3258,7 @@ The three digets after RDM.JobID can be used to reorder items in the list SGE_ST_DPS_Rhizo = 14007, [ParentCombo(SGE_ST_DPS)] - [CustomComboInfo("Psych Option", "Weaves Psych when available.", SGE.JobID, 112, "", "")] + [CustomComboInfo("Psyche Option", "Weaves Psyche when available.", SGE.JobID, 112, "", "")] SGE_ST_DPS_Psyche = 14008, [ParentCombo(SGE_ST_DPS)] From 7cea9812af5682cd2f65821cac5f24eebb5bd35b Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 14 Sep 2024 04:54:45 -0600 Subject: [PATCH 119/208] Correctly support soft->hard->mouseOver --- XIVSlothCombo/Combos/PvE/WHM.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 9daacb0d4..44a3a6e63 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -319,7 +319,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool plenaryReady = ActionReady(PlenaryIndulgence) && (!Config.WHM_AoEHeals_PlenaryWeave || (Config.WHM_AoEHeals_PlenaryWeave && canWeave)); bool divineCaressReady = ActionReady(DivineCaress) && HasEffect(Buffs.DivineGrace); bool assizeReady = ActionReady(Assize) && (!Config.WHM_AoEHeals_AssizeWeave || (Config.WHM_AoEHeals_AssizeWeave && canWeave)); - var healTarget = Config.WHM_AoEHeals_MedicaMO ? GetHealTarget(Config.WHM_AoEHeals_MedicaMO) : LocalPlayer; + var healTarget = this.OptionalTarget ?? + (Config.WHM_AoEHeals_MedicaMO + ? GetHealTarget(Config.WHM_AoEHeals_MedicaMO) + : LocalPlayer); var hasMedica2 = FindEffect(Buffs.Medica2, healTarget, LocalPlayer?.GameObjectId); var hasMedica3 = FindEffect(Buffs.Medica3, healTarget, LocalPlayer?.GameObjectId); From 44ea5b5ea8e3258d5f89fe7c238be76a567b41e2 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 14 Sep 2024 05:05:03 -0600 Subject: [PATCH 120/208] Keep previously PR'd changes, Undoes merge --- XIVSlothCombo/Combos/PvE/WHM.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 86b8deb6d..a4e5cd946 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -319,7 +319,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool plenaryReady = ActionReady(PlenaryIndulgence) && (!Config.WHM_AoEHeals_PlenaryWeave || (Config.WHM_AoEHeals_PlenaryWeave && canWeave)); bool divineCaressReady = ActionReady(DivineCaress) && HasEffect(Buffs.DivineGrace); bool assizeReady = ActionReady(Assize) && (!Config.WHM_AoEHeals_AssizeWeave || (Config.WHM_AoEHeals_AssizeWeave && canWeave)); - var healTarget = this.OptionalTarget != null ? this.OptionalTarget : GetHealTarget(Config.WHM_AoEHeals_MedicaMO); + var healTarget = this.OptionalTarget ?? + (Config.WHM_AoEHeals_MedicaMO + ? GetHealTarget(Config.WHM_AoEHeals_MedicaMO) + : LocalPlayer); var hasMedica2 = FindEffect(Buffs.Medica2, healTarget, LocalPlayer?.GameObjectId); var hasMedica3 = FindEffect(Buffs.Medica3, healTarget, LocalPlayer?.GameObjectId); From 6afb632171e16d0efb24762a65666fc6101378c0 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 14 Sep 2024 05:07:59 -0600 Subject: [PATCH 121/208] Manually restore previously PR'd changes --- XIVSlothCombo/Combos/PvE/WHM.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 44a3a6e63..7fed4c9b5 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -352,14 +352,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim || hasMedica2 != null && hasMedica2.RemainingTime <= Config.WHM_AoEHeals_MedicaTime // Medica buff, but falling off soon || hasMedica3 != null && hasMedica3.RemainingTime <= Config.WHM_AoEHeals_MedicaTime) // ^ && (ActionReady(Medica2) || ActionReady(Medica3))) - { - // Medica 3 upgrade - if (IsEnabled(CustomComboPreset.WHM_AoEHeals_Medica3) - && LevelChecked(Medica3)) - return Medica3; - - return Medica2; - } + return LevelChecked(Medica3) ? Medica3 : Medica2; if (IsEnabled(CustomComboPreset.WHM_AoEHeals_Cure3) && ActionReady(Cure3) @@ -433,6 +426,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim internal class WHM_AoE_DPS : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.WHM_AoE_DPS; + internal static int AssizeCount => ActionWatching.CombatActions.Count(x => x == Assize); protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { @@ -444,6 +438,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool liliesNearlyFull = gauge.Lily == 2 && gauge.LilyTimer >= 17000; bool PresenceOfMindReady = ActionReady(PresenceOfMind) && (!Config.WHM_AoEDPS_PresenceOfMindWeave); + if (IsEnabled(CustomComboPreset.WHM_AoE_DPS_SwiftHoly) && + ActionReady(All.Swiftcast) && + AssizeCount == 0 && !IsMoving && InCombat()) + return All.Swiftcast; + if (IsEnabled(CustomComboPreset.WHM_AoE_DPS_SwiftHoly) && + WasLastAction(All.Swiftcast)) + return actionID; + if (IsEnabled(CustomComboPreset.WHM_AoE_DPS_Assize) && ActionReady(Assize)) return Assize; From 12789df7647edc6d6ed218e9e6c9c2370331efcb Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 15 Sep 2024 09:44:10 -0500 Subject: [PATCH 122/208] Fixed Merge Compile Breaker --- XIVSlothCombo/Combos/PvE/PCT.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT.cs index af9d707cd..2b3579f4d 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT.cs @@ -81,15 +81,13 @@ public static UserInt PCT_ST_AdvancedMode_LucidOption = new("PCT_ST_AdvancedMode_LucidOption", 6500), PCT_AoE_AdvancedMode_HolyinWhiteOption = new("PCT_AoE_AdvancedMode_HolyinWhiteOption", 0), PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500), - PCT_VariantCure = new("PCT_VariantCure"); + PCT_VariantCure = new("PCT_VariantCure"), PCT_ST_CreatureStop = new("PCT_ST_CreatureStop"), PCT_AoE_CreatureStop = new("PCT_AoE_CreatureStop"), PCT_ST_WeaponStop = new("PCT_ST_WeaponStop"), PCT_AoE_WeaponStop = new("PCT_AoE_WeaponStop"), PCT_ST_LandscapeStop = new("PCT_ST_LandscapeStop"), - PCT_AoE_LandscapeStop = new("PCT_AoE_LandscapeStop"), - PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500); - + PCT_AoE_LandscapeStop = new("PCT_AoE_LandscapeStop"); public static UserBool CombinedMotifsMog = new("CombinedMotifsMog"), From e56f512e4ab0d6eabe3dcf548c7e6d37a85201e8 Mon Sep 17 00:00:00 2001 From: edewen Date: Sun, 15 Sep 2024 11:27:37 -0400 Subject: [PATCH 123/208] Bard Fixes Added Actionwatch and dots to rediant to help prevent tripleweaving by people who are cheating too hard --- XIVSlothCombo/Combos/PvE/BRD.cs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index dcde8ae08..90dc03f51 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -6,6 +6,7 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.Data; namespace XIVSlothCombo.Combos.PvE { @@ -316,9 +317,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Ladonsbite or QuickNock) { BRDGauge? gauge = GetJobGauge(); - bool canWeave = CanWeave(actionID); - bool canWeaveBuffs = CanWeave(actionID, 0.6); - bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9); + bool canWeave = CanWeave(actionID) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveBuffs = CanWeave(actionID, 0.6) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9) && !ActionWatching.HasDoubleWeaved(); int songTimerInSeconds = gauge.SongTimer / 1000; bool songNone = gauge.Song == Song.NONE; bool songWanderer = gauge.Song == Song.WANDERER; @@ -594,9 +595,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is HeavyShot or BurstShot) { BRDGauge? gauge = GetJobGauge(); - bool canWeave = CanWeave(actionID); - bool canWeaveBuffs = CanWeave(actionID, 0.6); - bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9); + bool canWeave = CanWeave(actionID) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveBuffs = CanWeave(actionID, 0.6) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9) && !ActionWatching.HasDoubleWeaved(); bool songNone = gauge.Song == Song.NONE; bool songWanderer = gauge.Song == Song.WANDERER; bool songMage = gauge.Song == Song.MAGE; @@ -693,7 +694,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.BRD_Adv_Buffs) && (!songNone || !LevelChecked(MagesBallad)) && isEnemyHealthHigh) { - bool radiantReady = LevelChecked(RadiantFinale) && IsOffCooldown(RadiantFinale); + bool radiantReady = LevelChecked(RadiantFinale) && IsOffCooldown(RadiantFinale) && TargetHasEffect(Debuffs.CausticBite) && TargetHasEffect(Debuffs.Stormbite); bool ragingReady = LevelChecked(RagingStrikes) && IsOffCooldown(RagingStrikes); bool battleVoiceReady = LevelChecked(BattleVoice) && IsOffCooldown(BattleVoice); bool barrageReady = LevelChecked(Barrage) && IsOffCooldown(Barrage); @@ -944,9 +945,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Ladonsbite or QuickNock) { BRDGauge? gauge = GetJobGauge(); - bool canWeave = CanWeave(actionID); - bool canWeaveBuffs = CanWeave(actionID, 0.6); - bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9); + bool canWeave = CanWeave(actionID) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveBuffs = CanWeave(actionID, 0.6) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9) && !ActionWatching.HasDoubleWeaved(); int songTimerInSeconds = gauge.SongTimer / 1000; bool songNone = gauge.Song == Song.NONE; bool songWanderer = gauge.Song == Song.WANDERER; @@ -1150,9 +1151,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is HeavyShot or BurstShot) { BRDGauge? gauge = GetJobGauge(); - bool canWeave = CanWeave(actionID); - bool canWeaveBuffs = CanWeave(actionID, 0.6); - bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9); + bool canWeave = CanWeave(actionID) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveBuffs = CanWeave(actionID, 0.6) && !ActionWatching.HasDoubleWeaved(); + bool canWeaveDelayed = CanDelayedWeave(actionID, 0.9) && !ActionWatching.HasDoubleWeaved(); bool songNone = gauge.Song == Song.NONE; bool songWanderer = gauge.Song == Song.WANDERER; bool songMage = gauge.Song == Song.MAGE; @@ -1247,7 +1248,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if ((!songNone || !LevelChecked(MagesBallad)) && isEnemyHealthHigh) { - bool radiantReady = LevelChecked(RadiantFinale) && IsOffCooldown(RadiantFinale); + bool radiantReady = LevelChecked(RadiantFinale) && IsOffCooldown(RadiantFinale) && TargetHasEffect(Debuffs.CausticBite) && TargetHasEffect(Debuffs.Stormbite); bool ragingReady = LevelChecked(RagingStrikes) && IsOffCooldown(RagingStrikes); bool battleVoiceReady = LevelChecked(BattleVoice) && IsOffCooldown(BattleVoice); bool barrageReady = LevelChecked(Barrage) && IsOffCooldown(Barrage); From f7cde70142b339c125b017b93ab62abd96e0cc9b Mon Sep 17 00:00:00 2001 From: edewen Date: Sun, 15 Sep 2024 16:00:39 -0400 Subject: [PATCH 124/208] Added line due to bad server tick causing double weave for some --- XIVSlothCombo/Combos/PvE/SCH.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH.cs index 1d21ce35c..f91ba7f1b 100644 --- a/XIVSlothCombo/Combos/PvE/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH.cs @@ -365,7 +365,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Dissipation; // Aetherflow - if (IsEnabled(CustomComboPreset.SCH_DPS_Aetherflow) && + if (IsEnabled(CustomComboPreset.SCH_DPS_Aetherflow) && !WasLastAction(Dissipation) && ActionReady(Aetherflow) && !Gauge.HasAetherflow() && InCombat() && CanSpellWeave(actionID)) return Aetherflow; From 6f2e2d96d365c12a331a226d719cdbfc60347494 Mon Sep 17 00:00:00 2001 From: Kage Date: Mon, 16 Sep 2024 00:12:33 +0200 Subject: [PATCH 125/208] fix pre opener optimize PB --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 30 ++++++++++++++++--------- XIVSlothCombo/Combos/PvE/MNK.cs | 31 ++++++++++++++------------ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index 08cac0aef..e62ce9830 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -110,7 +110,10 @@ private static bool HasCooldowns() if (Gauge.Nadi != Nadi.NONE) return false; - if (Gauge.RaptorFury != 0 || Gauge.CoeurlFury != 0) + if (Gauge.RaptorFury != 0) + return false; + + if (Gauge.CoeurlFury != 0) return false; return true; @@ -118,8 +121,7 @@ private static bool HasCooldowns() private bool DoPrePullSteps(ref uint actionID) { - if (!LevelChecked) - return false; + if (!LevelChecked) return false; if (CanOpener && PrePullStep == 0) PrePullStep = 1; @@ -127,18 +129,24 @@ private bool DoPrePullSteps(ref uint actionID) if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (Gauge.Chakra == 5 && PrePullStep == 1) PrePullStep++; - else if (PrePullStep == 1) actionID = OriginalHook(Meditation); + if (Gauge.Chakra < 5 && PrePullStep == 1) + { + actionID = ForbiddenMeditation; - if (HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 2) PrePullStep++; - else if (PrePullStep == 2) actionID = FormShift; + return true; + } - if (WasLastAction(DragonKick) && PrePullStep == 3) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 3) actionID = DragonKick; + if (!HasEffect(Buffs.FormlessFist) && + !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) + { + actionID = FormShift; - if (!HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 3) - currentState = OpenerState.FailedOpener; + return true; + } + if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = DragonKick; + if (ActionWatching.CombatActions.Count > 2 && InCombat()) CurrentState = OpenerState.FailedOpener; diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 229539948..945ddf97e 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -98,6 +98,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; if (actionID is Bootshine or LeapingOpo) { @@ -120,6 +121,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; + if (ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) + return RiddleOfFire; + // OGCDs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -131,17 +136,14 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (ActionReady(Brotherhood)) return Brotherhood; - - if (ActionReady(RiddleOfFire) && - CanDelayedWeave(ActionWatching.LastWeaponskill)) - return RiddleOfFire; - + if (ActionReady(RiddleOfWind)) return RiddleOfWind; //Perfect Balance if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) { // Odd window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && @@ -152,8 +154,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Even window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - HasEffect(Buffs.Brotherhood) && - HasEffect(Buffs.RiddleOfFire)) + (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && + (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) return PerfectBalance; // Low level @@ -162,7 +164,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb !LevelChecked(RiddleOfFire))) return PerfectBalance; } - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) return All.SecondWind; @@ -233,7 +234,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfFire) || + (HasEffect(Buffs.RiddleOfWind) || GetBuffRemainingTime(Buffs.WindsRumination) < 4)) return WindsReply; @@ -259,6 +260,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; if (actionID is Bootshine or LeapingOpo) { @@ -313,7 +315,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Perfect Balance if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) { // Odd window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && @@ -324,8 +327,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Even window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - HasEffect(Buffs.Brotherhood) && - HasEffect(Buffs.RiddleOfFire)) + (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && + (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) return PerfectBalance; // Low level @@ -418,7 +421,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfFire) || + (HasEffect(Buffs.RiddleOfWind) || GetBuffRemainingTime(Buffs.WindsRumination) < 4)) return WindsReply; } From a1e528d61799e36625adf11828cc811e83ff6950 Mon Sep 17 00:00:00 2001 From: Kage Date: Wed, 18 Sep 2024 16:41:06 +0200 Subject: [PATCH 126/208] Update queen usage --- XIVSlothCombo/Combos/JobHelpers/MCH.cs | 6 +++--- XIVSlothCombo/Combos/PvE/MCH.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MCH.cs b/XIVSlothCombo/Combos/JobHelpers/MCH.cs index 1fd7cea3d..fda0638b8 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MCH.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MCH.cs @@ -289,15 +289,15 @@ public static bool UseQueen(MCHGauge gauge) return true; //odd mins 2nd queen - if (BSUsed is 2 or 5 or 8 && gauge is { Battery: >= 60, LastSummonBatteryPower: 50 }) + if (BSUsed % 3 is 2 && gauge is { Battery: >= 60, LastSummonBatteryPower: 50 }) return true; //odd mins 2nd queen - if (BSUsed is 3 or 6 or 9 && gauge is { Battery: >= 70, LastSummonBatteryPower: 50 }) + if (BSUsed % 3 is 0 && gauge is { Battery: >= 70, LastSummonBatteryPower: 50 }) return true; //odd mins 2nd queen - if (BSUsed is 4 or 7 or 10 && gauge is { Battery: >= 80, LastSummonBatteryPower: 50 }) + if (BSUsed % 3 is 1 && gauge is { Battery: >= 80, LastSummonBatteryPower: 50 }) return true; } diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH.cs index 6582ab9e7..0cb4c2d3c 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH.cs @@ -231,9 +231,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && (BSUsed is 1 || - (BSUsed is 2 or 5 or 8 && Gauge.Battery <= 40) || - (BSUsed is 3 or 6 or 9 && Gauge.Battery <= 50) || - (BSUsed is 4 or 7 or 10 && Gauge.Battery <= 60) || + (BSUsed % 3 is 2 && Gauge.Battery <= 40) || + (BSUsed % 3 is 0 && Gauge.Battery <= 50) || + (BSUsed % 3 is 1 && Gauge.Battery <= 60) || GetBuffRemainingTime(Buffs.ExcavatorReady) < 6)) return OriginalHook(Chainsaw); @@ -476,9 +476,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim LevelChecked(Excavator) && HasEffect(Buffs.ExcavatorReady) && (BSUsed is 1 || - (BSUsed is 2 or 5 or 8 && Gauge.Battery <= 40) || - (BSUsed is 3 or 6 or 9 && Gauge.Battery <= 50) || - (BSUsed is 4 or 7 or 10 && Gauge.Battery <= 60) || + (BSUsed % 3 is 2 && Gauge.Battery <= 40) || + (BSUsed % 3 is 0 && Gauge.Battery <= 50) || + (BSUsed % 3 is 1 && Gauge.Battery <= 60) || GetBuffRemainingTime(Buffs.ExcavatorReady) < 6)) return OriginalHook(Chainsaw); From a5e4c6bd08d2a94d994192bb17acb71c53b1684e Mon Sep 17 00:00:00 2001 From: Kage Date: Fri, 20 Sep 2024 09:47:25 +0200 Subject: [PATCH 127/208] update winds reply --- XIVSlothCombo/Combos/PvE/MNK.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 945ddf97e..dfff50113 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -124,7 +124,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (ActionReady(RiddleOfFire) && CanDelayedWeave(ActionWatching.LastWeaponskill)) return RiddleOfFire; - + // OGCDs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -136,7 +136,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (ActionReady(Brotherhood)) return Brotherhood; - + if (ActionReady(RiddleOfWind)) return RiddleOfWind; @@ -164,6 +164,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb !LevelChecked(RiddleOfFire))) return PerfectBalance; } + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) return All.SecondWind; @@ -234,8 +235,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfWind) || - GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) return WindsReply; // Standard Beast Chakras @@ -417,12 +418,12 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb GetBuffRemainingTime(Buffs.FiresRumination) < 4)) return FiresReply; - if (IsEnabled(CustomComboPreset.MNK_STUseROW) && + if (IsEnabled(CustomComboPreset.MNK_STUseROW) && IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfWind) || - GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) return WindsReply; } @@ -470,7 +471,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionReady(Brotherhood)) return Brotherhood; - + if (ActionReady(RiddleOfWind)) return RiddleOfWind; From c17027649f5952ae980a96fb279c5ff39f8a5eb0 Mon Sep 17 00:00:00 2001 From: Kage Date: Fri, 20 Sep 2024 09:50:48 +0200 Subject: [PATCH 128/208] remove MNK stuff - ty GitHub --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 30 +++++++++---------------- XIVSlothCombo/Combos/PvE/MNK.cs | 31 ++++++++++++-------------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs index e62ce9830..08cac0aef 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ b/XIVSlothCombo/Combos/JobHelpers/MNK.cs @@ -110,10 +110,7 @@ private static bool HasCooldowns() if (Gauge.Nadi != Nadi.NONE) return false; - if (Gauge.RaptorFury != 0) - return false; - - if (Gauge.CoeurlFury != 0) + if (Gauge.RaptorFury != 0 || Gauge.CoeurlFury != 0) return false; return true; @@ -121,7 +118,8 @@ private static bool HasCooldowns() private bool DoPrePullSteps(ref uint actionID) { - if (!LevelChecked) return false; + if (!LevelChecked) + return false; if (CanOpener && PrePullStep == 0) PrePullStep = 1; @@ -129,24 +127,18 @@ private bool DoPrePullSteps(ref uint actionID) if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (Gauge.Chakra < 5 && PrePullStep == 1) - { - actionID = ForbiddenMeditation; + if (Gauge.Chakra == 5 && PrePullStep == 1) PrePullStep++; + else if (PrePullStep == 1) actionID = OriginalHook(Meditation); - return true; - } + if (HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 2) PrePullStep++; + else if (PrePullStep == 2) actionID = FormShift; - if (!HasEffect(Buffs.FormlessFist) && - !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) - { - actionID = FormShift; + if (WasLastAction(DragonKick) && PrePullStep == 3) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 3) actionID = DragonKick; - return true; - } + if (!HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 3) + currentState = OpenerState.FailedOpener; - if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = DragonKick; - if (ActionWatching.CombatActions.Count > 2 && InCombat()) CurrentState = OpenerState.FailedOpener; diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK.cs index 945ddf97e..229539948 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK.cs @@ -98,7 +98,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); - float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; if (actionID is Bootshine or LeapingOpo) { @@ -121,10 +120,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; - if (ActionReady(RiddleOfFire) && - CanDelayedWeave(ActionWatching.LastWeaponskill)) - return RiddleOfFire; - // OGCDs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -136,14 +131,17 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (ActionReady(Brotherhood)) return Brotherhood; - + + if (ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) + return RiddleOfFire; + if (ActionReady(RiddleOfWind)) return RiddleOfWind; //Perfect Balance if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist)) + !HasEffect(Buffs.PerfectBalance)) { // Odd window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && @@ -154,8 +152,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Even window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && - (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) + HasEffect(Buffs.Brotherhood) && + HasEffect(Buffs.RiddleOfFire)) return PerfectBalance; // Low level @@ -164,6 +162,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb !LevelChecked(RiddleOfFire))) return PerfectBalance; } + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) return All.SecondWind; @@ -234,7 +233,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfWind) || + (HasEffect(Buffs.RiddleOfFire) || GetBuffRemainingTime(Buffs.WindsRumination) < 4)) return WindsReply; @@ -260,7 +259,6 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); - float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; if (actionID is Bootshine or LeapingOpo) { @@ -315,8 +313,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Perfect Balance if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist)) + !HasEffect(Buffs.PerfectBalance)) { // Odd window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && @@ -327,8 +324,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Even window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && - (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) + HasEffect(Buffs.Brotherhood) && + HasEffect(Buffs.RiddleOfFire)) return PerfectBalance; // Low level @@ -421,7 +418,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfWind) || + (HasEffect(Buffs.RiddleOfFire) || GetBuffRemainingTime(Buffs.WindsRumination) < 4)) return WindsReply; } From 433368e976d5b48d53a9c5e0c8dd66f13fd28f57 Mon Sep 17 00:00:00 2001 From: Ethan Henderson Date: Sat, 21 Sep 2024 11:09:43 -0600 Subject: [PATCH 129/208] Provide feedback in chat when autoRot is toggled --- XIVSlothCombo/XIVSlothCombo.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 768506c68..84925ec34 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -128,7 +128,13 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) }); DtrBarEntry ??= Svc.DtrBar.Get("Wrath Combo"); - DtrBarEntry.OnClick = () => { Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; Service.Configuration.Save(); }; + DtrBarEntry.OnClick = () => + { + Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; + Service.Configuration.Save(); + + Svc.Chat.Print("Auto-Rotation set to " + (Service.Configuration.RotationConfig.Enabled ? "ON" : "OFF")); + }; Svc.ClientState.Login += PrintLoginMessage; if (Svc.ClientState.IsLoggedIn) ResetFeatures(); @@ -185,7 +191,7 @@ private void OnFrameworkUpdate(IFramework framework) var autoOn = Service.Configuration.RotationConfig.Enabled; DtrBarEntry.Text = new SeString( new IconPayload(autoOn ? BitmapFontIcon.SwordUnsheathed : BitmapFontIcon.SwordSheathed), - new TextPayload($"{(Service.Configuration.RotationConfig.Enabled ? ": On" : ": Off")}") + new TextPayload($"{(autoOn ? ": On" : ": Off")}") ); } @@ -601,6 +607,9 @@ private void OnCommand(string command, string arguments) { Service.Configuration.RotationConfig.Enabled = !Service.Configuration.RotationConfig.Enabled; Service.Configuration.Save(); + + Svc.Chat.Print("Auto-Rotation set to " + (Service.Configuration.RotationConfig.Enabled ? "ON" : "OFF")); + break; } default: From 1abdc438539670611d5d3df05a0254e9103dcf0d Mon Sep 17 00:00:00 2001 From: ace Date: Wed, 25 Sep 2024 11:20:16 -0700 Subject: [PATCH 130/208] AOE combo stuck on Slice --- XIVSlothCombo/Combos/PvE/GNB.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB.cs index 91afa4119..6d85cc471 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB.cs @@ -960,7 +960,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.GNB_AoE_BSOvercap) && !LevelChecked(FatedCircle)) return BurstStrike; } - if (Ammo != MaxCartridges(level)) + if (Ammo != MaxCartridges(level) || + (Ammo == MaxCartridges(level) && !LevelChecked(FatedCircle) && !IsEnabled(CustomComboPreset.GNB_AoE_BSOvercap))) { return DemonSlaughter; } From 94fd6b8c29f224ffacdad76fd6294c8c8409b655 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 15:57:59 -0500 Subject: [PATCH 131/208] Added userconfig splitup base code --- XIVSlothCombo/Window/Functions/Presets.cs | 40 +++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ad52c6eef..ed77d7c94 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -1,6 +1,5 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Components; -using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; using ECommons.DalamudServices; @@ -9,10 +8,10 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using System.Reflection.Emit; using System.Text; using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Core; using XIVSlothCombo.Data; using XIVSlothCombo.Services; @@ -266,12 +265,41 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo } ImGui.PopStyleColor(); } - - UserConfigItems.Draw(preset, enabled); + if (enabled) + { + switch (info.JobID) + { + //case All.JobID: All.Config.Draw(preset); break; + //case AST.JobID: AST.Config.Draw(preset); break; + //case BLM.JobID: BLM.Config.Draw(preset); break; + //case BLU.JobID: BLU.Config.Draw(preset); break; + //case BRD.JobID: BRD.Config.Draw(preset); break; + //case DNC.JobID: DNC.Config.Draw(preset); break; + //case DOL.JobID: DOL.Config.Draw(preset); break; + //case DRG.JobID: DRG.Config.Draw(preset); break; + //case DRK.JobID: DRK.Config.Draw(preset); break; + //case GNB.JobID: GNB.Config.Draw(preset); break; + //case MCH.JobID: MCH.Config.Draw(preset); break; + //case NIN.JobID: NIN.Config.Draw(preset); break; + //case PCT.JobID: PCT.Config.Draw(preset); break; + //case PLD.JobID: PLD.Config.Draw(preset); break; + //case RPR.JobID: RPR.Config.Draw(preset); break; + //case RDM.JobID: RDM.Config.Draw(preset); break; + //case SAM.JobID: SAM.Config.Draw(preset); break; + //case SCH.JobID: SCH.Config.Draw(preset); break; + //case SGE.JobID: SGE.Config.Draw(preset); break; + //case SMN.JobID: SMN.Config.Draw(preset); break; + //case VPR.JobID: VPR.Config.Draw(preset); break; + //case WAR.JobID: WAR.Config.Draw(preset); break; + //case WHM.JobID: WHM.Config.Draw(preset); break; + default: UserConfigItems.Draw(preset, enabled); break; + } + } i++; - var children = presetChildren.ContainsKey(preset) ? presetChildren[preset] : null; + //var children = presetChildren.ContainsKey(preset) ? presetChildren[preset] : null + presetChildren.TryGetValue(preset, out var children); if (children != null) { @@ -381,4 +409,4 @@ private static void EnableParentPresets(CustomComboPreset preset) } } } -} +} \ No newline at end of file From b6cae46e9efe6c73409bc330e81ccffc0fc65b8d Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 15:10:03 -0500 Subject: [PATCH 132/208] Initial File Move --- XIVSlothCombo/Combos/PvE/{ => AST}/AST.cs | 0 XIVSlothCombo/Combos/{JobHelpers/AST.cs => PvE/AST/AST_Helper.cs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => AST}/AST.cs (100%) rename XIVSlothCombo/Combos/{JobHelpers/AST.cs => PvE/AST/AST_Helper.cs} (100%) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST/AST.cs similarity index 100% rename from XIVSlothCombo/Combos/PvE/AST.cs rename to XIVSlothCombo/Combos/PvE/AST/AST.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/AST.cs b/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs similarity index 100% rename from XIVSlothCombo/Combos/JobHelpers/AST.cs rename to XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs From e0407eb78f0bda9fde0074bcf0879e561589a568 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 15:34:53 -0500 Subject: [PATCH 133/208] Reorganization Split Config out to AST_Config.cs Updated references to AST_Helper. Changed Init and Dispose to InitCheckCards and DisposeCheckCards Renamed AST_QuickTargetCards to AST_QuickTargetCards since most places preface it with AST. --- XIVSlothCombo/Combos/PvE/AST/AST.cs | 51 +---- XIVSlothCombo/Combos/PvE/AST/AST_Config.cs | 196 +++++++++++++++++++ XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs | 38 ++-- XIVSlothCombo/Data/ActionWatching.cs | 12 +- XIVSlothCombo/Window/Functions/Presets.cs | 2 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 134 ------------- XIVSlothCombo/Window/TargetHelper.cs | 4 +- XIVSlothCombo/XIVSlothCombo.cs | 6 +- 8 files changed, 229 insertions(+), 214 deletions(-) create mode 100644 XIVSlothCombo/Combos/PvE/AST/AST_Config.cs diff --git a/XIVSlothCombo/Combos/PvE/AST/AST.cs b/XIVSlothCombo/Combos/PvE/AST/AST.cs index 6ceab65bd..38f28cf06 100644 --- a/XIVSlothCombo/Combos/PvE/AST/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST/AST.cs @@ -1,19 +1,16 @@ using Dalamud.Game.ClientState.JobGauge.Enums; -using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Statuses; -using System.Collections; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; namespace XIVSlothCombo.Combos.PvE { - internal static class AST + internal static partial class AST { internal const byte JobID = 33; @@ -129,52 +126,6 @@ internal static Dictionary { Combust3, Debuffs.Combust3 } }; - public static ASTGauge Gauge => CustomComboFunctions.GetJobGauge(); - - public static CardType DrawnCard { get; set; } - - public static class Config - { - public static UserInt - AST_LucidDreaming = new("ASTLucidDreamingFeature", 8000), - AST_EssentialDignity = new("ASTCustomEssentialDignity", 50), - AST_Spire = new("AST_Spire", 80), - AST_Ewer = new("AST_Ewer", 80), - AST_Arrow = new("AST_Arrow", 80), - AST_Bole = new("AST_Bole", 80), - AST_ST_SimpleHeals_Esuna = new("AST_ST_SimpleHeals_Esuna", 100), - AST_DPS_AltMode = new("AST_DPS_AltMode"), - AST_AoEHeals_AltMode = new("AST_AoEHeals_AltMode"), - AST_DPS_DivinationOption = new("AST_DPS_DivinationOption"), - AST_AOE_DivinationOption = new("AST_AOE_DivinationOption"), - AST_DPS_LightSpeedOption = new("AST_DPS_LightSpeedOption"), - AST_AOE_LightSpeedOption = new("AST_AOE_LightSpeedOption"), - AST_DPS_CombustOption = new("AST_DPS_CombustOption"), - AST_QuickTarget_Override = new("AST_QuickTarget_Override"), - AST_ST_DPS_Play_SpeedSetting = new("AST_ST_DPS_Play_SpeedSetting"); - public static UserBool - AST_QuickTarget_SkipDamageDown = new("AST_QuickTarget_SkipDamageDown"), - AST_QuickTarget_SkipRezWeakness = new("AST_QuickTarget_SkipRezWeakness"), - AST_ST_SimpleHeals_Adv = new("AST_ST_SimpleHeals_Adv"), - AST_ST_SimpleHeals_UIMouseOver = new("AST_ST_SimpleHeals_UIMouseOver"), - AST_ST_SimpleHeals_WeaveDignity = new("AST_ST_SimpleHeals_WeaveDignity"), - AST_ST_SimpleHeals_WeaveIntersection = new("AST_ST_SimpleHeals_WeaveIntersection"), - AST_ST_SimpleHeals_WeaveEwer = new("AST_ST_SimpleHeals_WeaveEwer"), - AST_ST_SimpleHeals_WeaveSpire = new("AST_ST_SimpleHeals_WeaveSpire"), - AST_ST_SimpleHeals_WeaveArrow = new("AST_ST_SimpleHeals_WeaveArrow"), - AST_ST_SimpleHeals_WeaveBole = new("AST_ST_SimpleHeals_WeaveBole"), - AST_ST_SimpleHeals_WeaveExalt = new("AST_ST_SimpleHeals_WeaveExalt"), - AST_AoE_SimpleHeals_WeaveLady = new("AST_AoE_SimpleHeals_WeaveLady"), - AST_AoE_SimpleHeals_Opposition = new("AST_AoE_SimpleHeals_Opposition"), - AST_AoE_SimpleHeals_Horoscope = new("AST_AoE_SimpleHeals_Horoscope"), - AST_ST_DPS_OverwriteCards = new("AST_ST_DPS_OverwriteCards"), - AST_AOE_DPS_OverwriteCards = new("AST_AOE_DPS_OverwriteCards"), - AST_ST_DPS_CombustUptime_Adv = new("AST_ST_DPS_CombustUptime_Adv"); - public static UserFloat - AST_ST_DPS_CombustUptime_Threshold = new("AST_ST_DPS_CombustUptime_Threshold"); - } - - internal class AST_Benefic : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.AST_Benefic; diff --git a/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs b/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs new file mode 100644 index 000000000..52761d4e9 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs @@ -0,0 +1,196 @@ +using ImGuiNET; +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; +using static XIVSlothCombo.Extensions.UIntExtensions; +using static XIVSlothCombo.Window.Functions.UserConfig; +using static XIVSlothCombo.Window.Functions.SliderIncrements; + +namespace XIVSlothCombo.Combos.PvE +{ + internal static partial class AST + { + public static class Config + { + public static UserInt + AST_LucidDreaming = new("ASTLucidDreamingFeature", 8000), + AST_EssentialDignity = new("ASTCustomEssentialDignity", 50), + AST_Spire = new("AST_Spire", 80), + AST_Ewer = new("AST_Ewer", 80), + AST_Arrow = new("AST_Arrow", 80), + AST_Bole = new("AST_Bole", 80), + AST_ST_SimpleHeals_Esuna = new("AST_ST_SimpleHeals_Esuna", 100), + AST_DPS_AltMode = new("AST_DPS_AltMode"), + AST_AoEHeals_AltMode = new("AST_AoEHeals_AltMode"), + AST_DPS_DivinationOption = new("AST_DPS_DivinationOption"), + AST_AOE_DivinationOption = new("AST_AOE_DivinationOption"), + AST_DPS_LightSpeedOption = new("AST_DPS_LightSpeedOption"), + AST_AOE_LightSpeedOption = new("AST_AOE_LightSpeedOption"), + AST_DPS_CombustOption = new("AST_DPS_CombustOption"), + AST_QuickTarget_Override = new("AST_QuickTarget_Override"), + AST_ST_DPS_Play_SpeedSetting = new("AST_ST_DPS_Play_SpeedSetting"); + public static UserBool + AST_QuickTarget_SkipDamageDown = new("AST_QuickTarget_SkipDamageDown"), + AST_QuickTarget_SkipRezWeakness = new("AST_QuickTarget_SkipRezWeakness"), + AST_ST_SimpleHeals_Adv = new("AST_ST_SimpleHeals_Adv"), + AST_ST_SimpleHeals_UIMouseOver = new("AST_ST_SimpleHeals_UIMouseOver"), + AST_ST_SimpleHeals_WeaveDignity = new("AST_ST_SimpleHeals_WeaveDignity"), + AST_ST_SimpleHeals_WeaveIntersection = new("AST_ST_SimpleHeals_WeaveIntersection"), + AST_ST_SimpleHeals_WeaveEwer = new("AST_ST_SimpleHeals_WeaveEwer"), + AST_ST_SimpleHeals_WeaveSpire = new("AST_ST_SimpleHeals_WeaveSpire"), + AST_ST_SimpleHeals_WeaveArrow = new("AST_ST_SimpleHeals_WeaveArrow"), + AST_ST_SimpleHeals_WeaveBole = new("AST_ST_SimpleHeals_WeaveBole"), + AST_ST_SimpleHeals_WeaveExalt = new("AST_ST_SimpleHeals_WeaveExalt"), + AST_AoE_SimpleHeals_WeaveLady = new("AST_AoE_SimpleHeals_WeaveLady"), + AST_AoE_SimpleHeals_Opposition = new("AST_AoE_SimpleHeals_Opposition"), + AST_AoE_SimpleHeals_Horoscope = new("AST_AoE_SimpleHeals_Horoscope"), + AST_ST_DPS_OverwriteCards = new("AST_ST_DPS_OverwriteCards"), + AST_AOE_DPS_OverwriteCards = new("AST_AOE_DPS_OverwriteCards"), + AST_ST_DPS_CombustUptime_Adv = new("AST_ST_DPS_CombustUptime_Adv"); + public static UserFloat + AST_ST_DPS_CombustUptime_Threshold = new("AST_ST_DPS_CombustUptime_Threshold"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.AST_ST_DPS: + DrawRadioButton(AST_DPS_AltMode, $"On {Malefic.ActionName()}", "", 0); + DrawRadioButton(AST_DPS_AltMode, $"On {Combust.ActionName()}", $"Alternative DPS Mode. Leaves {Malefic.ActionName()} alone for pure DPS, becomes {Malefic.ActionName()} when features are on cooldown", 1); + break; + + case CustomComboPreset.AST_DPS_Lucid: + DrawSliderInt(4000, 9500, AST_LucidDreaming, "Set value for your MP to be at or under for this feature to work", 150, Hundreds); + break; + + case CustomComboPreset.AST_ST_DPS_CombustUptime: + DrawSliderInt(0, 100, AST_DPS_CombustOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); + + DrawAdditionalBoolChoice(AST_ST_DPS_CombustUptime_Adv, "Advanced Options", "", isConditionalChoice: true); + if (AST_ST_DPS_CombustUptime_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 4, AST_ST_DPS_CombustUptime_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + ImGui.Unindent(); + } + + break; + + case CustomComboPreset.AST_DPS_Divination: + DrawSliderInt(0, 100, AST_DPS_DivinationOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); + break; + + case CustomComboPreset.AST_DPS_LightSpeed: + DrawSliderInt(0, 100, AST_DPS_LightSpeedOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); + break; + + //AOE added + case CustomComboPreset.AST_AOE_Lucid: + DrawSliderInt(4000, 9500, AST_LucidDreaming, "Set value for your MP to be at or under for this feature to work", 150, Hundreds); + break; + + case CustomComboPreset.AST_AOE_Divination: + DrawSliderInt(0, 100, AST_AOE_DivinationOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); + break; + + case CustomComboPreset.AST_AOE_LightSpeed: + DrawSliderInt(0, 100, AST_AOE_LightSpeedOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); + break; + + case CustomComboPreset.AST_AOE_AutoDraw: + DrawAdditionalBoolChoice(AST_AOE_DPS_OverwriteCards, "Overwrite Non-DPS Cards", "Will draw even if you have healing cards remaining."); + break; + + //end aoe added + + case CustomComboPreset.AST_ST_SimpleHeals: + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_Adv, "Advanced Options", "", isConditionalChoice: true); + if (AST_ST_SimpleHeals_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.AST_ST_SimpleHeals_EssentialDignity: + DrawSliderInt(0, 100, AST_EssentialDignity, "Set percentage value"); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveDignity, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_CelestialIntersection: + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveIntersection, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_Exaltation: + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveExalt, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_Spire: + DrawSliderInt(0, 100, AST_Spire, "Set percentage value"); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveSpire, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_Ewer: + DrawSliderInt(0, 100, AST_Ewer, "Set percentage value"); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveEwer, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_Bole: + DrawSliderInt(0, 100, AST_Bole, "Set percentage value"); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveBole, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_Arrow: + DrawSliderInt(0, 100, AST_Arrow, "Set percentage value"); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_WeaveArrow, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_ST_SimpleHeals_Esuna: + DrawSliderInt(0, 100, AST_ST_SimpleHeals_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); + break; + + case CustomComboPreset.AST_AoE_SimpleHeals_AspectedHelios: + DrawRadioButton(AST_AoEHeals_AltMode, $"On {AspectedHelios.ActionName()}", "", 0); + DrawRadioButton(AST_AoEHeals_AltMode, $"On {Helios.ActionName()}", "Alternative AOE Mode. Leaves Aspected Helios alone for manual HoTs", 1); + break; + + case CustomComboPreset.AST_AoE_SimpleHeals_LazyLady: + DrawAdditionalBoolChoice(AST_AoE_SimpleHeals_WeaveLady, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_AoE_SimpleHeals_Horoscope: + DrawAdditionalBoolChoice(AST_AoE_SimpleHeals_Horoscope, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_AoE_SimpleHeals_CelestialOpposition: + DrawAdditionalBoolChoice(AST_AoE_SimpleHeals_Opposition, "Only Weave", "Will only weave this action."); + break; + + case CustomComboPreset.AST_Cards_QuickTargetCards: + DrawRadioButton(AST_QuickTarget_Override, "No Override", "", 0); + DrawRadioButton(AST_QuickTarget_Override, "Hard Target Override", "Overrides selection with hard target if you have one", 1); + DrawRadioButton(AST_QuickTarget_Override, "UI Mousover Override", "Overrides selection with UI mouseover target if you have one", 2); + + ImGui.Spacing(); + DrawAdditionalBoolChoice(AST_QuickTarget_SkipDamageDown, $"Skip targets with a {GetStatusName(62)} debuff", ""); + DrawAdditionalBoolChoice(AST_QuickTarget_SkipRezWeakness, $"Skip targets with a {GetStatusName(43)} or {GetStatusName(44)} debuff", ""); + break; + + case CustomComboPreset.AST_DPS_AutoPlay: + DrawRadioButton(AST_ST_DPS_Play_SpeedSetting, "Fast (1 DPS GCD minimum delay)", "", 1); + DrawRadioButton(AST_ST_DPS_Play_SpeedSetting, "Medium (2 DPS GCD minimum delay)", "", 2); + DrawRadioButton(AST_ST_DPS_Play_SpeedSetting, "Slow (3 DPS GCD minimum delay)", "", 3); + + break; + + case CustomComboPreset.AST_DPS_AutoDraw: + DrawAdditionalBoolChoice(AST_ST_DPS_OverwriteCards, "Overwrite Non-DPS Cards", "Will draw even if you have healing cards remaining."); + break; + } + } + } + } +} diff --git a/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs b/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs index d5b7ea2b8..a8053b65a 100644 --- a/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs @@ -1,20 +1,22 @@ - using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using ECommons.DalamudServices; using ECommons.GameFunctions; -using ECommons.ExcelServices; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Extensions; -using static XIVSlothCombo.Combos.PvE.AST; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.PvE { - internal static class AST + internal static partial class AST { - internal static void Init() + public static ASTGauge Gauge => CustomComboFunctions.GetJobGauge(); + public static CardType DrawnCard { get; set; } + + internal static void InitCheckCards() { Svc.Framework.Update += CheckCards; } @@ -26,7 +28,7 @@ private static void CheckCards(IFramework framework) if (Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.BetweenAreas] || Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.Unconscious]) { - AST_QuickTargetCards.SelectedRandomMember = null; + QuickTargetCards.SelectedRandomMember = null; return; } @@ -36,25 +38,25 @@ private static void CheckCards(IFramework framework) } if (CustomComboFunctions.IsEnabled(CustomComboPreset.AST_Cards_QuickTargetCards) && - (AST_QuickTargetCards.SelectedRandomMember is null || BetterTargetAvailable())) + (QuickTargetCards.SelectedRandomMember is null || BetterTargetAvailable())) { if (CustomComboFunctions.ActionReady(Play1)) - AST_QuickTargetCards.Invoke(); + QuickTargetCards.Invoke(); } if (DrawnCard == CardType.NONE) - AST_QuickTargetCards.SelectedRandomMember = null; + QuickTargetCards.SelectedRandomMember = null; } private static bool BetterTargetAvailable() { - if (AST_QuickTargetCards.SelectedRandomMember is null || - AST_QuickTargetCards.SelectedRandomMember.IsDead || - CustomComboFunctions.OutOfRange(Balance, AST_QuickTargetCards.SelectedRandomMember)) + if (QuickTargetCards.SelectedRandomMember is null || + QuickTargetCards.SelectedRandomMember.IsDead || + CustomComboFunctions.OutOfRange(Balance, QuickTargetCards.SelectedRandomMember)) return true; - var m = AST_QuickTargetCards.SelectedRandomMember as IBattleChara; + var m = QuickTargetCards.SelectedRandomMember as IBattleChara; if ((DrawnCard is CardType.BALANCE && CustomComboFunctions.JobIDs.Melee.Any(x => x == m.ClassJob.Id)) || (DrawnCard is CardType.SPEAR && CustomComboFunctions.JobIDs.Ranged.Any(x => x == m.ClassJob.Id))) return false; @@ -63,7 +65,7 @@ private static bool BetterTargetAvailable() for (int i = 1; i <= 8; i++) //Checking all 8 available slots and skipping nulls & DCs { if (CustomComboFunctions.GetPartySlot(i) is not IBattleChara member) continue; - if (member.GameObjectId == AST_QuickTargetCards.SelectedRandomMember.GameObjectId) continue; + if (member.GameObjectId == QuickTargetCards.SelectedRandomMember.GameObjectId) continue; if (member is null) continue; //Skip nulls/disconnected people if (member.IsDead) continue; if (CustomComboFunctions.OutOfRange(Balance, member)) continue; @@ -83,7 +85,7 @@ private static bool BetterTargetAvailable() if ((DrawnCard is CardType.BALANCE && targets.Any(x => CustomComboFunctions.JobIDs.Melee.Any(y => y == x.ClassJob.Id))) || (DrawnCard is CardType.SPEAR && targets.Any(x => CustomComboFunctions.JobIDs.Ranged.Any(y => y == x.ClassJob.Id)))) { - AST_QuickTargetCards.SelectedRandomMember = null; + QuickTargetCards.SelectedRandomMember = null; return true; } @@ -91,7 +93,7 @@ private static bool BetterTargetAvailable() } - internal class AST_QuickTargetCards : CustomComboFunctions + internal class QuickTargetCards : CustomComboFunctions { internal static List PartyTargets = []; @@ -214,7 +216,7 @@ private static bool SetTarget() } } - internal static void Dispose() + internal static void DisposeCheckCards() { Svc.Framework.Update -= CheckCards; } diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index cc3d26cc7..8ee3856d3 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -113,28 +113,28 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp private unsafe static void CheckForChangedTarget(uint actionId, ref ulong targetObjectId) { if (actionId is AST.Balance or AST.Spear && - Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember is not null && - !OutOfRange(actionId, Svc.ClientState.LocalPlayer!, Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember)) + AST.QuickTargetCards.SelectedRandomMember is not null && + !OutOfRange(actionId, Svc.ClientState.LocalPlayer!, AST.QuickTargetCards.SelectedRandomMember)) { int targetOptions = AST.Config.AST_QuickTarget_Override; switch (targetOptions) { case 0: - Svc.Log.Debug($"Switched to {Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.Name}"); - targetObjectId = Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.GameObjectId; + Svc.Log.Debug($"Switched to {AST.QuickTargetCards.SelectedRandomMember.Name}"); + targetObjectId = AST.QuickTargetCards.SelectedRandomMember.GameObjectId; break; case 1: if (CustomComboFunctions.HasFriendlyTarget()) targetObjectId = Svc.ClientState.LocalPlayer.TargetObject.GameObjectId; else - targetObjectId = Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.GameObjectId; + targetObjectId = AST.QuickTargetCards.SelectedRandomMember.GameObjectId; break; case 2: if (CustomComboFunctions.GetHealTarget(true, true) is not null) targetObjectId = CustomComboFunctions.GetHealTarget(true, true).GameObjectId; else - targetObjectId = Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.GameObjectId; + targetObjectId = AST.QuickTargetCards.SelectedRandomMember.GameObjectId; break; } } diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ed77d7c94..6fc4cc7f8 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -270,7 +270,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo switch (info.JobID) { //case All.JobID: All.Config.Draw(preset); break; - //case AST.JobID: AST.Config.Draw(preset); break; + case AST.JobID: AST.Config.Draw(preset); break; //case BLM.JobID: BLM.Config.Draw(preset); break; //case BLU.JobID: BLU.Config.Draw(preset); break; //case BRD.JobID: BRD.Config.Draw(preset); break; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..9f083f435 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1197,141 +1197,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region ASTROLOGIAN - - if (preset is CustomComboPreset.AST_ST_DPS) - { - UserConfig.DrawRadioButton(AST.Config.AST_DPS_AltMode, "On Malefic", "", 0); - UserConfig.DrawRadioButton(AST.Config.AST_DPS_AltMode, "On Combust", "Alternative DPS Mode. Leaves Malefic alone for pure DPS, becomes Malefic when features are on cooldown", 1); - } - - if (preset is CustomComboPreset.AST_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, AST.Config.AST_LucidDreaming, "Set value for your MP to be at or under for this feature to work", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.AST_ST_DPS_CombustUptime) - { - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_DPS_CombustOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); - - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_DPS_CombustUptime_Adv, "Advanced Options", "", isConditionalChoice: true); - if (PluginConfiguration.GetCustomBoolValue(AST.Config.AST_ST_DPS_CombustUptime_Adv)) - { - ImGui.Indent(); - UserConfig.DrawRoundedSliderFloat(0, 4, AST.Config.AST_ST_DPS_CombustUptime_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); - ImGui.Unindent(); - } - - } - - if (preset is CustomComboPreset.AST_DPS_Divination) - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_DPS_DivinationOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); - - if (preset is CustomComboPreset.AST_DPS_LightSpeed) - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_DPS_LightSpeedOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); - - //AOE added - if (preset is CustomComboPreset.AST_AOE_Lucid) - UserConfig.DrawSliderInt(4000, 9500, AST.Config.AST_LucidDreaming, "Set value for your MP to be at or under for this feature to work", 150, SliderIncrements.Hundreds); - if (preset is CustomComboPreset.AST_AOE_Divination) - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_AOE_DivinationOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); - - if (preset is CustomComboPreset.AST_AOE_LightSpeed) - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_AOE_LightSpeedOption, "Stop using at Enemy HP %. Set to Zero to disable this check."); - - if (preset is CustomComboPreset.AST_AOE_AutoDraw) - { - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AOE_DPS_OverwriteCards, "Overwrite Non-DPS Cards", "Will draw even if you have healing cards remaining."); - } - //end aoe added - - if (preset is CustomComboPreset.AST_ST_SimpleHeals) - { - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_Adv, "Advanced Options", "", isConditionalChoice: true); - if (AST.Config.AST_ST_SimpleHeals_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.AST_ST_SimpleHeals_EssentialDignity) - { - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_EssentialDignity, "Set percentage value"); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveDignity, "Only Weave", "Will only weave this action."); - } - if (preset is CustomComboPreset.AST_ST_SimpleHeals_CelestialIntersection) - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveIntersection, "Only Weave", "Will only weave this action."); - - if (preset is CustomComboPreset.AST_ST_SimpleHeals_Exaltation) - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveExalt, "Only Weave", "Will only weave this action."); - - if (preset is CustomComboPreset.AST_ST_SimpleHeals_Spire) - { - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_Spire, "Set percentage value"); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveSpire, "Only Weave", "Will only weave this action."); - } - if (preset is CustomComboPreset.AST_ST_SimpleHeals_Ewer) - { - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_Ewer, "Set percentage value"); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveEwer, "Only Weave", "Will only weave this action."); - } - if (preset is CustomComboPreset.AST_ST_SimpleHeals_Bole) - { - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_Bole, "Set percentage value"); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveBole, "Only Weave", "Will only weave this action."); - } - if (preset is CustomComboPreset.AST_ST_SimpleHeals_Arrow) - { - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_Arrow, "Set percentage value"); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_SimpleHeals_WeaveArrow, "Only Weave", "Will only weave this action."); - } - if (preset is CustomComboPreset.AST_ST_SimpleHeals_Esuna) - UserConfig.DrawSliderInt(0, 100, AST.Config.AST_ST_SimpleHeals_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); - - if (preset is CustomComboPreset.AST_AoE_SimpleHeals_AspectedHelios) - { - UserConfig.DrawRadioButton(AST.Config.AST_AoEHeals_AltMode, "On Aspected Helios", "", 0); - UserConfig.DrawRadioButton(AST.Config.AST_AoEHeals_AltMode, "On Helios", "Alternative AOE Mode. Leaves Aspected Helios alone for manual HoTs", 1); - } - - if (preset is CustomComboPreset.AST_AoE_SimpleHeals_LazyLady) - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AoE_SimpleHeals_WeaveLady, "Only Weave", "Will only weave this action."); - - if (preset is CustomComboPreset.AST_AoE_SimpleHeals_Horoscope) - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AoE_SimpleHeals_Horoscope, "Only Weave", "Will only weave this action."); - - if (preset is CustomComboPreset.AST_AoE_SimpleHeals_CelestialOpposition) - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AoE_SimpleHeals_Opposition, "Only Weave", "Will only weave this action."); - - if (preset is CustomComboPreset.AST_Cards_QuickTargetCards) - { - UserConfig.DrawRadioButton(AST.Config.AST_QuickTarget_Override, "No Override", "", 0); - UserConfig.DrawRadioButton(AST.Config.AST_QuickTarget_Override, "Hard Target Override", "Overrides selection with hard target if you have one", 1); - UserConfig.DrawRadioButton(AST.Config.AST_QuickTarget_Override, "UI Mousover Override", "Overrides selection with UI mouseover target if you have one", 2); - - ImGui.Spacing(); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_QuickTarget_SkipDamageDown, $"Skip targets with a {ActionWatching.GetStatusName(62)} debuff", ""); - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_QuickTarget_SkipRezWeakness, $"Skip targets with a {ActionWatching.GetStatusName(43)} or {ActionWatching.GetStatusName(44)} debuff", ""); - } - - if (preset is CustomComboPreset.AST_DPS_AutoPlay) - { - UserConfig.DrawRadioButton(AST.Config.AST_ST_DPS_Play_SpeedSetting, "Fast (1 DPS GCD minimum delay)", "", 1); - UserConfig.DrawRadioButton(AST.Config.AST_ST_DPS_Play_SpeedSetting, "Medium (2 DPS GCD minimum delay)", "", 2); - UserConfig.DrawRadioButton(AST.Config.AST_ST_DPS_Play_SpeedSetting, "Slow (3 DPS GCD minimum delay)", "", 3); - - } - - if (preset is CustomComboPreset.AST_DPS_AutoDraw) - { - UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_ST_DPS_OverwriteCards, "Overwrite Non-DPS Cards", "Will draw even if you have healing cards remaining."); - } - - #endregion // ==================================================================================== #region BLACK MAGE diff --git a/XIVSlothCombo/Window/TargetHelper.cs b/XIVSlothCombo/Window/TargetHelper.cs index d7c1daa48..0f8d381ea 100644 --- a/XIVSlothCombo/Window/TargetHelper.cs +++ b/XIVSlothCombo/Window/TargetHelper.cs @@ -22,7 +22,7 @@ internal TargetHelper() : base("###SlothComboTargeteHelper", ImGuiWindowFlags.No internal unsafe void DrawTargetHelper() { - if (Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember is not null) + if (Combos.PvE.AST.QuickTargetCards.SelectedRandomMember is not null) { IntPtr partyPTR = Svc.GameGui.GetAddonByName("_PartyList", 1); if (partyPTR == IntPtr.Zero) @@ -34,7 +34,7 @@ internal unsafe void DrawTargetHelper() for (int i = 1; i <= 8; i++) { if (CustomComboFunctions.GetPartySlot(i) is null) continue; - if (CustomComboFunctions.GetPartySlot(i).GameObjectId == Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.GameObjectId) + if (CustomComboFunctions.GetPartySlot(i).GameObjectId == Combos.PvE.AST.QuickTargetCards.SelectedRandomMember.GameObjectId) { var member = i switch { diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 768506c68..3ba86de0d 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -85,7 +85,7 @@ public static uint? JobID { if (jobID != value && value != null) { - Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember = null; + AST.QuickTargetCards.SelectedRandomMember = null; PvEFeatures.HasToOpenJob = true; } jobID = value; @@ -109,7 +109,7 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) Service.ComboCache = new CustomComboCache(); Service.IconReplacer = new IconReplacer(); ActionWatching.Enable(); - Combos.JobHelpers.AST.Init(); + AST.InitCheckCards(); ConfigWindow = new ConfigWindow(); TargetHelper = new(); @@ -272,7 +272,7 @@ public void Dispose() Service.IconReplacer?.Dispose(); Service.ComboCache?.Dispose(); ActionWatching.Dispose(); - Combos.JobHelpers.AST.Dispose(); + AST.DisposeCheckCards(); DisposeOpeners(); Svc.ClientState.Login -= PrintLoginMessage; From e2038cb5844174c4ddb7ee9f0ae6351c388b6510 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:03:28 -0500 Subject: [PATCH 134/208] Moved Files to new layout --- XIVSlothCombo/Combos/PvE/{ => SCH}/SCH.cs | 0 XIVSlothCombo/Combos/{JobHelpers/SCH.cs => PvE/SCH/SCH_Helper.cs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => SCH}/SCH.cs (100%) rename XIVSlothCombo/Combos/{JobHelpers/SCH.cs => PvE/SCH/SCH_Helper.cs} (100%) diff --git a/XIVSlothCombo/Combos/PvE/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs similarity index 100% rename from XIVSlothCombo/Combos/PvE/SCH.cs rename to XIVSlothCombo/Combos/PvE/SCH/SCH.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs similarity index 100% rename from XIVSlothCombo/Combos/JobHelpers/SCH.cs rename to XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs From a49e945ec10a13e862a611df83af8b34421c757a Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:01:47 -0500 Subject: [PATCH 135/208] Final rearranging --- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 68 +----- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 205 +++++++++++++++++++ XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 18 +- XIVSlothCombo/Window/Functions/Presets.cs | 2 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 142 ------------- 5 files changed, 222 insertions(+), 213 deletions(-) create mode 100644 XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 1d21ce35c..cfbfb78e1 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -1,18 +1,15 @@ -using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Statuses; using System.Collections.Generic; using XIVSlothCombo.Combos.PvE.Content; -using static XIVSlothCombo.Combos.JobHelpers.SCHHelper; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using System.Linq; using XIVSlothCombo.Extensions; namespace XIVSlothCombo.Combos.PvE { - internal static class SCH + internal static partial class SCH { public const byte ClassID = 26; public const byte JobID = 28; @@ -93,69 +90,6 @@ internal static readonly Dictionary { Biolysis, Debuffs.Biolysis } }; - // Class Gauge - - internal static SCHGauge Gauge => CustomComboFunctions.GetJobGauge(); - - internal static bool HasAetherflow(this SCHGauge gauge) => (gauge.Aetherflow > 0); - - internal enum OpenerState - { - PreOpener, - InOpener, - PostOpener, - } - - public static class Config - { - #region DPS - public static UserInt - SCH_ST_DPS_AltMode = new("SCH_ST_DPS_AltMode"), - SCH_ST_DPS_LucidOption = new("SCH_ST_DPS_LucidOption", 6500), - SCH_ST_DPS_BioOption = new("SCH_ST_DPS_BioOption", 10), - SCH_ST_DPS_ChainStratagemOption = new("SCH_ST_DPS_ChainStratagemOption", 10); - public static UserBool - SCH_ST_DPS_Adv = new("SCH_ST_DPS_Adv"), - SCH_ST_DPS_Bio_Adv = new("SCH_ST_DPS_Bio_Adv"), - SCH_ST_DPS_EnergyDrain_Adv = new("SCH_ST_DPS_EnergyDrain_Adv"); - public static UserFloat - SCH_ST_DPS_Bio_Threshold = new("SCH_ST_DPS_Bio_Threshold", 3.0f), - SCH_ST_DPS_EnergyDrain = new("SCH_ST_DPS_EnergyDrain", 3.0f); - public static UserBoolArray - SCH_ST_DPS_Adv_Actions = new("SCH_ST_DPS_Adv_Actions"); - #endregion - - #region Healing - public static UserInt - SCH_AoE_LucidOption = new("SCH_AoE_LucidOption", 6500), - SCH_AoE_Heal_LucidOption = new("SCH_AoE_Heal_LucidOption", 6500), - SCH_ST_Heal_LucidOption = new("SCH_ST_Heal_LucidOption", 6500), - SCH_ST_Heal_AdloquiumOption = new("SCH_ST_Heal_AdloquiumOption"), - SCH_ST_Heal_LustrateOption = new("SCH_ST_Heal_LustrateOption"), - SCH_ST_Heal_ExcogitationOption = new("SCH_ST_Heal_ExcogitationOption"), - SCH_ST_Heal_ProtractionOption = new("SCH_ST_Heal_ProtractionOption"), - SCH_ST_Heal_EsunaOption = new("SCH_ST_Heal_EsunaOption"); - public static UserIntArray - SCH_ST_Heals_Priority = new("SCH_ST_Heals_Priority"); - public static UserBool - SCH_ST_Heal_Adv = new("SCH_ST_Heal_Adv"), - SCH_ST_Heal_UIMouseOver = new("SCH_ST_Heal_UIMouseOver"), - SCH_DeploymentTactics_Adv = new("SCH_DeploymentTactics_Adv"), - SCH_DeploymentTactics_UIMouseOver = new("SCH_DeploymentTactics_UIMouseOver"); - #endregion - - #region Utility - internal static UserBool - SCH_Aetherflow_Recite_Indom = new("SCH_Aetherflow_Recite_Indom"), - SCH_Aetherflow_Recite_Excog = new("SCH_Aetherflow_Recite_Excog"); - internal static UserInt - SCH_Aetherflow_Display = new("SCH_Aetherflow_Display"), - SCH_Aetherflow_Recite_ExcogMode = new("SCH_Aetherflow_Recite_ExcogMode"), - SCH_Aetherflow_Recite_IndomMode = new("SCH_Aetherflow_Recite_IndomMode"), - SCH_Recitation_Mode = new("SCH_Recitation_Mode"); - #endregion - - } /* * SCH_Consolation diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs new file mode 100644 index 000000000..4bb5d8f81 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -0,0 +1,205 @@ +using ImGuiNET; +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Extensions.UIntExtensions; +using static XIVSlothCombo.Window.Functions.UserConfig; +using static XIVSlothCombo.Window.Functions.SliderIncrements; + +namespace XIVSlothCombo.Combos.PvE +{ + internal static partial class SCH + { + internal static class Config + { + #region DPS + public static UserInt + SCH_ST_DPS_AltMode = new("SCH_ST_DPS_AltMode"), + SCH_ST_DPS_LucidOption = new("SCH_ST_DPS_LucidOption", 6500), + SCH_ST_DPS_BioOption = new("SCH_ST_DPS_BioOption", 10), + SCH_ST_DPS_ChainStratagemOption = new("SCH_ST_DPS_ChainStratagemOption", 10); + public static UserBool + SCH_ST_DPS_Adv = new("SCH_ST_DPS_Adv"), + SCH_ST_DPS_Bio_Adv = new("SCH_ST_DPS_Bio_Adv"), + SCH_ST_DPS_EnergyDrain_Adv = new("SCH_ST_DPS_EnergyDrain_Adv"); + public static UserFloat + SCH_ST_DPS_Bio_Threshold = new("SCH_ST_DPS_Bio_Threshold", 3.0f), + SCH_ST_DPS_EnergyDrain = new("SCH_ST_DPS_EnergyDrain", 3.0f); + public static UserBoolArray + SCH_ST_DPS_Adv_Actions = new("SCH_ST_DPS_Adv_Actions"); + #endregion + + #region Healing + public static UserInt + SCH_AoE_LucidOption = new("SCH_AoE_LucidOption", 6500), + SCH_AoE_Heal_LucidOption = new("SCH_AoE_Heal_LucidOption", 6500), + SCH_ST_Heal_LucidOption = new("SCH_ST_Heal_LucidOption", 6500), + SCH_ST_Heal_AdloquiumOption = new("SCH_ST_Heal_AdloquiumOption"), + SCH_ST_Heal_LustrateOption = new("SCH_ST_Heal_LustrateOption"), + SCH_ST_Heal_ExcogitationOption = new("SCH_ST_Heal_ExcogitationOption"), + SCH_ST_Heal_ProtractionOption = new("SCH_ST_Heal_ProtractionOption"), + SCH_ST_Heal_EsunaOption = new("SCH_ST_Heal_EsunaOption"); + public static UserIntArray + SCH_ST_Heals_Priority = new("SCH_ST_Heals_Priority"); + public static UserBool + SCH_ST_Heal_Adv = new("SCH_ST_Heal_Adv"), + SCH_ST_Heal_UIMouseOver = new("SCH_ST_Heal_UIMouseOver"), + SCH_DeploymentTactics_Adv = new("SCH_DeploymentTactics_Adv"), + SCH_DeploymentTactics_UIMouseOver = new("SCH_DeploymentTactics_UIMouseOver"); + #endregion + + #region Utility + internal static UserBool + SCH_Aetherflow_Recite_Indom = new("SCH_Aetherflow_Recite_Indom"), + SCH_Aetherflow_Recite_Excog = new("SCH_Aetherflow_Recite_Excog"); + internal static UserInt + SCH_Aetherflow_Display = new("SCH_Aetherflow_Display"), + SCH_Aetherflow_Recite_ExcogMode = new("SCH_Aetherflow_Recite_ExcogMode"), + SCH_Aetherflow_Recite_IndomMode = new("SCH_Aetherflow_Recite_IndomMode"), + SCH_Recitation_Mode = new("SCH_Recitation_Mode"); + #endregion + + internal static void Draw(CustomComboPreset preset) + { + if (preset is CustomComboPreset.SCH_DPS) + { + DrawAdditionalBoolChoice(SCH_ST_DPS_Adv, "Advanced Action Options", "Change how actions are handled", isConditionalChoice: true); + + if (SCH_ST_DPS_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Ruin/Broils", "Apply options to Ruin and all Broils.", 3, 0); + DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Bio/Bio II/Biolysis", "Apply options to Bio and Biolysis.", 3, 1); + DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Ruin II", "Apply options to Ruin II.", 3, 2); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SCH_DPS_Lucid) + DrawSliderInt(4000, 9500, SCH_ST_DPS_LucidOption, "MP Threshold", 150, Hundreds); + + if (preset is CustomComboPreset.SCH_DPS_Bio) + { + DrawSliderInt(0, 100, SCH_ST_DPS_BioOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); + + DrawAdditionalBoolChoice(SCH_ST_DPS_Bio_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_ST_DPS_Bio_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 4, SCH_ST_DPS_Bio_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SCH_DPS_ChainStrat) + DrawSliderInt(0, 100, SCH_ST_DPS_ChainStratagemOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); + + if (preset is CustomComboPreset.SCH_DPS_EnergyDrain) + { + DrawAdditionalBoolChoice(SCH_ST_DPS_EnergyDrain_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_ST_DPS_EnergyDrain_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 60, SCH_ST_DPS_EnergyDrain, "Aetherflow remaining cooldown:", digits: 1); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SCH_ST_Heal) + { + DrawAdditionalBoolChoice(SCH_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_ST_Heal_Adv) + { + ImGui.Indent(); + DrawAdditionalBoolChoice(SCH_ST_Heal_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SCH_ST_Heal_Lucid) + DrawSliderInt(4000, 9500, SCH_ST_Heal_LucidOption, "MP Threshold", 150, Hundreds); + + if (preset is CustomComboPreset.SCH_ST_Heal_Adloquium) + DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, "Use Adloquium on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); + + if (preset is CustomComboPreset.SCH_ST_Heal_Lustrate) + { + DrawSliderInt(0, 100, SCH_ST_Heal_LustrateOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 3, 0, $"{Lustrate.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SCH_ST_Heal_Excogitation) + { + DrawSliderInt(0, 100, SCH_ST_Heal_ExcogitationOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 3, 1, $"{Excogitation.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SCH_ST_Heal_Protraction) + { + DrawSliderInt(0, 100, SCH_ST_Heal_ProtractionOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 3, 2, $"{Protraction.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SCH_ST_Heal_Esuna) + DrawSliderInt(0, 100, SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); + + if (preset is CustomComboPreset.SCH_AoE_Lucid) + DrawSliderInt(4000, 9500, SCH_AoE_LucidOption, "MP Threshold", 150, Hundreds); + + if (preset is CustomComboPreset.SCH_AoE_Heal_Lucid) + DrawSliderInt(4000, 9500, SCH_AoE_Heal_LucidOption, "MP Threshold", 150, Hundreds); + + if (preset is CustomComboPreset.SCH_DeploymentTactics) + { + DrawAdditionalBoolChoice(SCH_DeploymentTactics_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_DeploymentTactics_Adv) + { + ImGui.Indent(); + DrawAdditionalBoolChoice(SCH_DeploymentTactics_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SCH_Aetherflow) + { + DrawRadioButton(SCH_Aetherflow_Display, "Show Aetherflow On Energy Drain Only", "", 0); + DrawRadioButton(SCH_Aetherflow_Display, "Show Aetherflow On All Aetherflow Skills", "", 1); + } + + if (preset is CustomComboPreset.SCH_Aetherflow_Recite) + { + DrawAdditionalBoolChoice(SCH_Aetherflow_Recite_Excog, "On Excogitation", "", isConditionalChoice: true); + if (SCH_Aetherflow_Recite_Excog) + { + ImGui.Indent(); ImGui.Spacing(); + DrawRadioButton(SCH_Aetherflow_Recite_ExcogMode, "Only when out of Aetherflow Stacks", "", 0); + DrawRadioButton(SCH_Aetherflow_Recite_ExcogMode, "Always when available", "", 1); + ImGui.Unindent(); + } + + DrawAdditionalBoolChoice(SCH_Aetherflow_Recite_Indom, "On Indominability", "", isConditionalChoice: true); + if (SCH_Aetherflow_Recite_Indom) + { + ImGui.Indent(); ImGui.Spacing(); + DrawRadioButton(SCH_Aetherflow_Recite_IndomMode, "Only when out of Aetherflow Stacks", "", 0); + DrawRadioButton(SCH_Aetherflow_Recite_IndomMode, "Always when available", "", 1); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SCH_Recitation) + { + DrawRadioButton(SCH_Recitation_Mode, "Adloquium", "", 0); + DrawRadioButton(SCH_Recitation_Mode, "Succor", "", 1); + DrawRadioButton(SCH_Recitation_Mode, "Indomitability", "", 2); + DrawRadioButton(SCH_Recitation_Mode, "Excogitation", "", 3); + } + + } + } + } +} diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index ae33b7262..7dbe38da8 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -1,10 +1,22 @@ -using static XIVSlothCombo.Combos.PvE.SCH; +using Dalamud.Game.ClientState.JobGauge.Types; +using XIVSlothCombo.CustomComboNS.Functions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.PvE { - internal class SCHHelper + internal static partial class SCH { + // Class Gauge + internal static SCHGauge Gauge => CustomComboFunctions.GetJobGauge(); + internal static bool HasAetherflow(this SCHGauge gauge) => (gauge.Aetherflow > 0); + + internal enum OpenerState + { + PreOpener, + InOpener, + PostOpener, + } + public static int GetMatchingConfigST(int i, out uint action, out bool enabled) { var healTarget = GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ed77d7c94..9871c1f9a 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -286,7 +286,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo //case RPR.JobID: RPR.Config.Draw(preset); break; //case RDM.JobID: RDM.Config.Draw(preset); break; //case SAM.JobID: SAM.Config.Draw(preset); break; - //case SCH.JobID: SCH.Config.Draw(preset); break; + case SCH.JobID: SCH.Config.Draw(preset); break; //case SGE.JobID: SGE.Config.Draw(preset); break; //case SMN.JobID: SMN.Config.Draw(preset); break; //case VPR.JobID: VPR.Config.Draw(preset); break; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..6512d203b 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2211,149 +2211,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region SCHOLAR - if (preset is CustomComboPreset.SCH_DPS) - { - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_ST_DPS_Adv, "Advanced Action Options", "Change how actions are handled", isConditionalChoice: true); - - if (SCH.Config.SCH_ST_DPS_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(SCH.Config.SCH_ST_DPS_Adv_Actions, "On Ruin/Broils", "Apply options to Ruin and all Broils.", 3, 0); - UserConfig.DrawHorizontalMultiChoice(SCH.Config.SCH_ST_DPS_Adv_Actions, "On Bio/Bio II/Biolysis", "Apply options to Bio and Biolysis.", 3, 1); - UserConfig.DrawHorizontalMultiChoice(SCH.Config.SCH_ST_DPS_Adv_Actions, "On Ruin II", "Apply options to Ruin II.", 3, 2); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_ST_DPS_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.SCH_DPS_Bio) - { - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_DPS_BioOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); - - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_ST_DPS_Bio_Adv, "Advanced Options", "", isConditionalChoice: true); - if (PluginConfiguration.GetCustomBoolValue(SCH.Config.SCH_ST_DPS_Bio_Adv)) - { - ImGui.Indent(); - UserConfig.DrawRoundedSliderFloat(0, 4, SCH.Config.SCH_ST_DPS_Bio_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_DPS_ChainStrat) - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_DPS_ChainStratagemOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); - - if (preset is CustomComboPreset.SCH_DPS_EnergyDrain) - { - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_ST_DPS_EnergyDrain_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH.Config.SCH_ST_DPS_EnergyDrain_Adv) - { - ImGui.Indent(); - UserConfig.DrawRoundedSliderFloat(0, 60, SCH.Config.SCH_ST_DPS_EnergyDrain, "Aetherflow remaining cooldown:", digits: 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_ST_Heal) - { - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH.Config.SCH_ST_Heal_Adv) - { - ImGui.Indent(); - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_ST_Heal_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_ST_Heal_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.SCH_ST_Heal_Adloquium) - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_AdloquiumOption, "Use Adloquium on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); - - if (preset is CustomComboPreset.SCH_ST_Heal_Lustrate) - { - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_LustrateOption, "Start using when below HP %. Set to 100 to disable this check"); - UserConfig.DrawPriorityInput(SCH.Config.SCH_ST_Heals_Priority, 3, 0, $"{SCH.Lustrate.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Excogitation) - { - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_ExcogitationOption, "Start using when below HP %. Set to 100 to disable this check"); - UserConfig.DrawPriorityInput(SCH.Config.SCH_ST_Heals_Priority, 3, 1, $"{SCH.Excogitation.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Protraction) - { - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_ProtractionOption, "Start using when below HP %. Set to 100 to disable this check"); - UserConfig.DrawPriorityInput(SCH.Config.SCH_ST_Heals_Priority, 3, 2, $"{SCH.Protraction.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Esuna) - UserConfig.DrawSliderInt(0, 100, SCH.Config.SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); - - if (preset is CustomComboPreset.SCH_AoE_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_AoE_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.SCH_AoE_Heal_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SCH.Config.SCH_AoE_Heal_LucidOption, "MP Threshold", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.SCH_DeploymentTactics) - { - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_DeploymentTactics_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH.Config.SCH_DeploymentTactics_Adv) - { - ImGui.Indent(); - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_DeploymentTactics_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_Aetherflow) - { - UserConfig.DrawRadioButton(SCH.Config.SCH_Aetherflow_Display, "Show Aetherflow On Energy Drain Only", "", 0); - UserConfig.DrawRadioButton(SCH.Config.SCH_Aetherflow_Display, "Show Aetherflow On All Aetherflow Skills", "", 1); - } - - if (preset is CustomComboPreset.SCH_Aetherflow_Recite) - { - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_Aetherflow_Recite_Excog, "On Excogitation", "", isConditionalChoice: true); - if (SCH.Config.SCH_Aetherflow_Recite_Excog) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawRadioButton(SCH.Config.SCH_Aetherflow_Recite_ExcogMode, "Only when out of Aetherflow Stacks", "", 0); - UserConfig.DrawRadioButton(SCH.Config.SCH_Aetherflow_Recite_ExcogMode, "Always when available", "", 1); - ImGui.Unindent(); - } - - UserConfig.DrawAdditionalBoolChoice(SCH.Config.SCH_Aetherflow_Recite_Indom, "On Indominability", "", isConditionalChoice: true); - if (SCH.Config.SCH_Aetherflow_Recite_Indom) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawRadioButton(SCH.Config.SCH_Aetherflow_Recite_IndomMode, "Only when out of Aetherflow Stacks", "", 0); - UserConfig.DrawRadioButton(SCH.Config.SCH_Aetherflow_Recite_IndomMode, "Always when available", "", 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_Recitation) - { - UserConfig.DrawRadioButton(SCH.Config.SCH_Recitation_Mode, "Adloquium", "", 0); - UserConfig.DrawRadioButton(SCH.Config.SCH_Recitation_Mode, "Succor", "", 1); - UserConfig.DrawRadioButton(SCH.Config.SCH_Recitation_Mode, "Indomitability", "", 2); - UserConfig.DrawRadioButton(SCH.Config.SCH_Recitation_Mode, "Excogitation", "", 3); - } - - #endregion // ==================================================================================== #region SUMMONER From 35396800ea3f82d4b22cd37d58bb16d4fc5e203c Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 12:53:11 -0500 Subject: [PATCH 136/208] Config updated to Switch statement --- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 272 ++++++++++----------- 1 file changed, 135 insertions(+), 137 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 4bb5d8f81..84bda713a 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -59,146 +59,144 @@ internal static UserInt internal static void Draw(CustomComboPreset preset) { - if (preset is CustomComboPreset.SCH_DPS) + switch (preset) { - DrawAdditionalBoolChoice(SCH_ST_DPS_Adv, "Advanced Action Options", "Change how actions are handled", isConditionalChoice: true); - - if (SCH_ST_DPS_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Ruin/Broils", "Apply options to Ruin and all Broils.", 3, 0); - DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Bio/Bio II/Biolysis", "Apply options to Bio and Biolysis.", 3, 1); - DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Ruin II", "Apply options to Ruin II.", 3, 2); - ImGui.Unindent(); - } + case CustomComboPreset.SCH_DPS: + DrawAdditionalBoolChoice(SCH_ST_DPS_Adv, "Advanced Action Options", "Change how actions are handled", isConditionalChoice: true); + if (SCH_ST_DPS_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Ruin/Broils", "Apply options to Ruin and all Broils.", 3, 0); + DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Bio/Bio II/Biolysis", "Apply options to Bio and Biolysis.", 3, 1); + DrawHorizontalMultiChoice(SCH_ST_DPS_Adv_Actions, "On Ruin II", "Apply options to Ruin II.", 3, 2); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SCH_DPS_Lucid: + DrawSliderInt(4000, 9500, SCH_ST_DPS_LucidOption, "MP Threshold", 150, Hundreds); + break; + + case CustomComboPreset.SCH_DPS_Bio: + DrawSliderInt(0, 100, SCH_ST_DPS_BioOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); + + DrawAdditionalBoolChoice(SCH_ST_DPS_Bio_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_ST_DPS_Bio_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 4, SCH_ST_DPS_Bio_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SCH_DPS_ChainStrat: + DrawSliderInt(0, 100, SCH_ST_DPS_ChainStratagemOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); + break; + + case CustomComboPreset.SCH_DPS_EnergyDrain: + DrawAdditionalBoolChoice(SCH_ST_DPS_EnergyDrain_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_ST_DPS_EnergyDrain_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 60, SCH_ST_DPS_EnergyDrain, "Aetherflow remaining cooldown:", digits: 1); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SCH_ST_Heal: + DrawAdditionalBoolChoice(SCH_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_ST_Heal_Adv) + { + ImGui.Indent(); + DrawAdditionalBoolChoice(SCH_ST_Heal_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SCH_ST_Heal_Lucid: + DrawSliderInt(4000, 9500, SCH_ST_Heal_LucidOption, "MP Threshold", 150, Hundreds); + break; + + case CustomComboPreset.SCH_ST_Heal_Adloquium: + DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, "Use Adloquium on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); + break; + + case CustomComboPreset.SCH_ST_Heal_Lustrate: + DrawSliderInt(0, 100, SCH_ST_Heal_LustrateOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 3, 0, $"{Lustrate.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_ST_Heal_Excogitation: + DrawSliderInt(0, 100, SCH_ST_Heal_ExcogitationOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 3, 1, $"{Excogitation.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_ST_Heal_Protraction: + DrawSliderInt(0, 100, SCH_ST_Heal_ProtractionOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 3, 2, $"{Protraction.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_ST_Heal_Esuna: + DrawSliderInt(0, 100, SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); + break; + + case CustomComboPreset.SCH_AoE_Lucid: + DrawSliderInt(4000, 9500, SCH_AoE_LucidOption, "MP Threshold", 150, Hundreds); + break; + + case CustomComboPreset.SCH_AoE_Heal_Lucid: + DrawSliderInt(4000, 9500, SCH_AoE_Heal_LucidOption, "MP Threshold", 150, Hundreds); + break; + + case CustomComboPreset.SCH_DeploymentTactics: + DrawAdditionalBoolChoice(SCH_DeploymentTactics_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SCH_DeploymentTactics_Adv) + { + ImGui.Indent(); + DrawAdditionalBoolChoice(SCH_DeploymentTactics_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SCH_Aetherflow: + DrawRadioButton(SCH_Aetherflow_Display, "Show Aetherflow On Energy Drain Only", "", 0); + DrawRadioButton(SCH_Aetherflow_Display, "Show Aetherflow On All Aetherflow Skills", "", 1); + break; + + case CustomComboPreset.SCH_Aetherflow_Recite: + DrawAdditionalBoolChoice(SCH_Aetherflow_Recite_Excog, "On Excogitation", "", isConditionalChoice: true); + if (SCH_Aetherflow_Recite_Excog) + { + ImGui.Indent(); ImGui.Spacing(); + DrawRadioButton(SCH_Aetherflow_Recite_ExcogMode, "Only when out of Aetherflow Stacks", "", 0); + DrawRadioButton(SCH_Aetherflow_Recite_ExcogMode, "Always when available", "", 1); + ImGui.Unindent(); + } + + DrawAdditionalBoolChoice(SCH_Aetherflow_Recite_Indom, "On Indominability", "", isConditionalChoice: true); + if (SCH_Aetherflow_Recite_Indom) + { + ImGui.Indent(); ImGui.Spacing(); + DrawRadioButton(SCH_Aetherflow_Recite_IndomMode, "Only when out of Aetherflow Stacks", "", 0); + DrawRadioButton(SCH_Aetherflow_Recite_IndomMode, "Always when available", "", 1); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SCH_Recitation: + DrawRadioButton(SCH_Recitation_Mode, "Adloquium", "", 0); + DrawRadioButton(SCH_Recitation_Mode, "Succor", "", 1); + DrawRadioButton(SCH_Recitation_Mode, "Indomitability", "", 2); + DrawRadioButton(SCH_Recitation_Mode, "Excogitation", "", 3); + break; } - if (preset is CustomComboPreset.SCH_DPS_Lucid) - DrawSliderInt(4000, 9500, SCH_ST_DPS_LucidOption, "MP Threshold", 150, Hundreds); - - if (preset is CustomComboPreset.SCH_DPS_Bio) - { - DrawSliderInt(0, 100, SCH_ST_DPS_BioOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); - - DrawAdditionalBoolChoice(SCH_ST_DPS_Bio_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH_ST_DPS_Bio_Adv) - { - ImGui.Indent(); - DrawRoundedSliderFloat(0, 4, SCH_ST_DPS_Bio_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_DPS_ChainStrat) - DrawSliderInt(0, 100, SCH_ST_DPS_ChainStratagemOption, "Stop using at Enemy HP%. Set to Zero to disable this check."); - - if (preset is CustomComboPreset.SCH_DPS_EnergyDrain) - { - DrawAdditionalBoolChoice(SCH_ST_DPS_EnergyDrain_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH_ST_DPS_EnergyDrain_Adv) - { - ImGui.Indent(); - DrawRoundedSliderFloat(0, 60, SCH_ST_DPS_EnergyDrain, "Aetherflow remaining cooldown:", digits: 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_ST_Heal) - { - DrawAdditionalBoolChoice(SCH_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH_ST_Heal_Adv) - { - ImGui.Indent(); - DrawAdditionalBoolChoice(SCH_ST_Heal_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Lucid) - DrawSliderInt(4000, 9500, SCH_ST_Heal_LucidOption, "MP Threshold", 150, Hundreds); - - if (preset is CustomComboPreset.SCH_ST_Heal_Adloquium) - DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, "Use Adloquium on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); - - if (preset is CustomComboPreset.SCH_ST_Heal_Lustrate) - { - DrawSliderInt(0, 100, SCH_ST_Heal_LustrateOption, "Start using when below HP %. Set to 100 to disable this check"); - DrawPriorityInput(SCH_ST_Heals_Priority, 3, 0, $"{Lustrate.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Excogitation) - { - DrawSliderInt(0, 100, SCH_ST_Heal_ExcogitationOption, "Start using when below HP %. Set to 100 to disable this check"); - DrawPriorityInput(SCH_ST_Heals_Priority, 3, 1, $"{Excogitation.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Protraction) - { - DrawSliderInt(0, 100, SCH_ST_Heal_ProtractionOption, "Start using when below HP %. Set to 100 to disable this check"); - DrawPriorityInput(SCH_ST_Heals_Priority, 3, 2, $"{Protraction.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SCH_ST_Heal_Esuna) - DrawSliderInt(0, 100, SCH_ST_Heal_EsunaOption, "Stop using when below HP %. Set to Zero to disable this check"); - - if (preset is CustomComboPreset.SCH_AoE_Lucid) - DrawSliderInt(4000, 9500, SCH_AoE_LucidOption, "MP Threshold", 150, Hundreds); - - if (preset is CustomComboPreset.SCH_AoE_Heal_Lucid) - DrawSliderInt(4000, 9500, SCH_AoE_Heal_LucidOption, "MP Threshold", 150, Hundreds); - - if (preset is CustomComboPreset.SCH_DeploymentTactics) - { - DrawAdditionalBoolChoice(SCH_DeploymentTactics_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SCH_DeploymentTactics_Adv) - { - ImGui.Indent(); - DrawAdditionalBoolChoice(SCH_DeploymentTactics_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_Aetherflow) - { - DrawRadioButton(SCH_Aetherflow_Display, "Show Aetherflow On Energy Drain Only", "", 0); - DrawRadioButton(SCH_Aetherflow_Display, "Show Aetherflow On All Aetherflow Skills", "", 1); - } - - if (preset is CustomComboPreset.SCH_Aetherflow_Recite) - { - DrawAdditionalBoolChoice(SCH_Aetherflow_Recite_Excog, "On Excogitation", "", isConditionalChoice: true); - if (SCH_Aetherflow_Recite_Excog) - { - ImGui.Indent(); ImGui.Spacing(); - DrawRadioButton(SCH_Aetherflow_Recite_ExcogMode, "Only when out of Aetherflow Stacks", "", 0); - DrawRadioButton(SCH_Aetherflow_Recite_ExcogMode, "Always when available", "", 1); - ImGui.Unindent(); - } - - DrawAdditionalBoolChoice(SCH_Aetherflow_Recite_Indom, "On Indominability", "", isConditionalChoice: true); - if (SCH_Aetherflow_Recite_Indom) - { - ImGui.Indent(); ImGui.Spacing(); - DrawRadioButton(SCH_Aetherflow_Recite_IndomMode, "Only when out of Aetherflow Stacks", "", 0); - DrawRadioButton(SCH_Aetherflow_Recite_IndomMode, "Always when available", "", 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SCH_Recitation) - { - DrawRadioButton(SCH_Recitation_Mode, "Adloquium", "", 0); - DrawRadioButton(SCH_Recitation_Mode, "Succor", "", 1); - DrawRadioButton(SCH_Recitation_Mode, "Indomitability", "", 2); - DrawRadioButton(SCH_Recitation_Mode, "Excogitation", "", 3); - } - } } } From 63f07a43d926c27d53cabe6f49535e5d2b9abce6 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 13:44:56 -0500 Subject: [PATCH 137/208] Added Dissipation options to heal features --- XIVSlothCombo/Combos/CustomComboPreset.cs | 20 ++++++++++++++------ XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 12 ++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index dc750d88a..30336cfc6 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3949,6 +3949,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Indomitability Ready Only Option", "Only uses Aetherflow is Indomitability is ready to use.", SCH.JobID)] SCH_AoE_Heal_Aetherflow_Indomitability = 16021, + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Disspation Option", "Use Dissipation when out of Aetherflow stacks.", SCH.JobID)] + SCH_AoE_Heal_Dissipation = 16041, + [ParentCombo(SCH_AoE_Heal)] [CustomComboInfo("Indomitability Option", "Use Indomitability before using Succor.", SCH.JobID)] SCH_AoE_Heal_Indomitability = 16022, @@ -3967,23 +3971,27 @@ The three digets after RDM.JobID can be used to reorder items in the list SCH_ST_Heal_Aetherflow = 16025, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Esuna Option", "Applies Esuna to your target if there is a cleansable debuff.", SGE.JobID, 3)] + [CustomComboInfo("Disspation Option", "Use Dissipation when out of Aetherflow stacks.", SCH.JobID, 3)] + SCH_ST_Heal_Dissipation = 16040, + + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Esuna Option", "Applies Esuna to your target if there is a cleansable debuff.", SGE.JobID, 4)] SCH_ST_Heal_Esuna = 16026, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Adloquium Option", "Use Adloquium when missing Galvanize or target HP%% below:", SCH.JobID, 4)] + [CustomComboInfo("Adloquium Option", "Use Adloquium when missing Galvanize or target HP%% below:", SCH.JobID, 5)] SCH_ST_Heal_Adloquium = 16027, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Lustrate Option", "Use Lustrate when target HP%% below:", SCH.JobID, 5)] + [CustomComboInfo("Lustrate Option", "Use Lustrate when target HP%% below:", SCH.JobID, 6)] SCH_ST_Heal_Lustrate = 16028, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Excogitation Option", "Use Excogitation when target HP%% below:", SCH.JobID, 6)] + [CustomComboInfo("Excogitation Option", "Use Excogitation when target HP%% below:", SCH.JobID, 7)] SCH_ST_Heal_Excogitation = 16038, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Protraction Option", "Use Protraction when target HP%% below:", SCH.JobID, 7)] + [CustomComboInfo("Protraction Option", "Use Protraction when target HP%% below:", SCH.JobID, 8)] SCH_ST_Heal_Protraction = 16039, @@ -4031,7 +4039,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion - // Last value = 16039 + // Last value = 16041 #endregion diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index cfbfb78e1..8cb293771 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -434,6 +434,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim InCombat()) return Aetherflow; + if (IsEnabled(CustomComboPreset.SCH_AoE_Heal_Dissipation) + && ActionReady(Dissipation) + && !Gauge.HasAetherflow() + && InCombat()) + return Dissipation; + // Lucid Dreaming if (IsEnabled(CustomComboPreset.SCH_AoE_Heal_Lucid) && All.CanUseLucid(actionID, Config.SCH_AoE_Heal_LucidOption, true)) @@ -497,6 +503,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim InCombat() && CanSpellWeave(actionID)) return Aetherflow; + if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Dissipation) + && ActionReady(Dissipation) + && !Gauge.HasAetherflow() + && InCombat()) + return Dissipation; + // Lucid Dreaming if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Lucid) && ActionReady(All.LucidDreaming) && From 5c51dc538867c6e2cfac35e3ea208d87131d674f Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:35:24 -0500 Subject: [PATCH 138/208] Initial File Move --- XIVSlothCombo/Combos/PvE/{ => SGE}/SGE.cs | 0 XIVSlothCombo/Combos/{JobHelpers/SGE.cs => PvE/SGE/SGE_Helper.cs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => SGE}/SGE.cs (100%) rename XIVSlothCombo/Combos/{JobHelpers/SGE.cs => PvE/SGE/SGE_Helper.cs} (100%) diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs similarity index 100% rename from XIVSlothCombo/Combos/PvE/SGE.cs rename to XIVSlothCombo/Combos/PvE/SGE/SGE.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs similarity index 100% rename from XIVSlothCombo/Combos/JobHelpers/SGE.cs rename to XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs From 7cb98fd3725bd56fda7991fa37efdd538207e6cb Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:46:47 -0500 Subject: [PATCH 139/208] Finished Data Sorting for new layout --- XIVSlothCombo/Combos/PvE/SGE/SGE.cs | 55 +----- XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs | 202 +++++++++++++++++++++ XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs | 18 +- XIVSlothCombo/Window/Functions/Presets.cs | 2 +- 4 files changed, 216 insertions(+), 61 deletions(-) create mode 100644 XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs index ca9e992b6..f2cc133f0 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs @@ -7,13 +7,11 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; -using static XIVSlothCombo.Combos.JobHelpers.SGEHelper; using XIVSlothCombo.Data; -using XIVSlothCombo.Combos.JobHelpers; namespace XIVSlothCombo.Combos.PvE { - internal static class SGE + internal static partial class SGE { internal const byte JobID = 40; @@ -102,57 +100,6 @@ internal static readonly Dictionary { Dosis3, Debuffs.EukrasianDosis3 } }; - // Sage Gauge & Extensions - public static SGEGauge Gauge => CustomComboFunctions.GetJobGauge(); - public static bool HasAddersgall(this SGEGauge gauge) => gauge.Addersgall > 0; - public static bool HasAddersting(this SGEGauge gauge) => gauge.Addersting > 0; - - public static class Config - { - #region DPS - public static UserBool - SGE_ST_DPS_Adv = new("SGE_ST_DPS_Adv"), - SGE_ST_DPS_EDosis_Adv = new("SGE_ST_Dosis_EDosis_Adv"); - public static UserBoolArray - SGE_ST_DPS_Movement = new("SGE_ST_DPS_Movement"); - public static UserInt - SGE_ST_DPS_EDosisHPPer = new("SGE_ST_DPS_EDosisHPPer", 10), - SGE_ST_DPS_Lucid = new("SGE_ST_DPS_Lucid", 6500), - SGE_ST_DPS_Rhizo = new("SGE_ST_DPS_Rhizo"), - SGE_ST_DPS_AddersgallProtect = new("SGE_ST_DPS_AddersgallProtect", 3), - SGE_AoE_DPS_Lucid = new("SGE_AoE_Phlegma_Lucid", 6500), - SGE_AoE_DPS_Rhizo = new("SGE_AoE_DPS_Rhizo"), - SGE_AoE_DPS_AddersgallProtect = new("SGE_AoE_DPS_AddersgallProtect", 3); - public static UserFloat - SGE_ST_DPS_EDosisThreshold = new("SGE_ST_Dosis_EDosisThreshold", 3.0f); - #endregion - - #region Healing - public static UserBool - SGE_ST_Heal_Adv = new("SGE_ST_Heal_Adv"), - SGE_ST_Heal_UIMouseOver = new("SGE_ST_Heal_UIMouseOver"), - SGE_AoE_Heal_KeracholeTrait = new("SGE_AoE_Heal_KeracholeTrait"); - public static UserInt - SGE_ST_Heal_Zoe = new("SGE_ST_Heal_Zoe"), - SGE_ST_Heal_Haima = new("SGE_ST_Heal_Haima"), - SGE_ST_Heal_Krasis = new("SGE_ST_Heal_Krasis"), - SGE_ST_Heal_Pepsis = new("SGE_ST_Heal_Pepsis"), - SGE_ST_Heal_Soteria = new("SGE_ST_Heal_Soteria"), - SGE_ST_Heal_EDiagnosisHP = new("SGE_ST_Heal_EDiagnosisHP"), - SGE_ST_Heal_Druochole = new("SGE_ST_Heal_Druochole"), - SGE_ST_Heal_Taurochole = new("SGE_ST_Heal_Taurochole"), - SGE_ST_Heal_Esuna = new("SGE_ST_Heal_Esuna"); - public static UserIntArray - SGE_ST_Heals_Priority = new("SGE_ST_Heals_Priority"), - SGE_AoE_Heals_Priority = new("SGE_AoE_Heals_Priority"); - public static UserBoolArray - SGE_ST_Heal_EDiagnosisOpts = new("SGE_ST_Heal_EDiagnosisOpts"); - #endregion - - public static UserInt - SGE_Eukrasia_Mode = new("SGE_Eukrasia_Mode"); - } - internal static class Traits { internal const ushort diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs new file mode 100644 index 000000000..811ee7025 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs @@ -0,0 +1,202 @@ +using ImGuiNET; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE +{ + internal static partial class SGE + { + public static class Config + { + #region DPS + public static UserBool + SGE_ST_DPS_Adv = new("SGE_ST_DPS_Adv"), + SGE_ST_DPS_EDosis_Adv = new("SGE_ST_Dosis_EDosis_Adv"); + public static UserBoolArray + SGE_ST_DPS_Movement = new("SGE_ST_DPS_Movement"); + public static UserInt + SGE_ST_DPS_EDosisHPPer = new("SGE_ST_DPS_EDosisHPPer", 10), + SGE_ST_DPS_Lucid = new("SGE_ST_DPS_Lucid", 6500), + SGE_ST_DPS_Rhizo = new("SGE_ST_DPS_Rhizo"), + SGE_ST_DPS_AddersgallProtect = new("SGE_ST_DPS_AddersgallProtect", 3), + SGE_AoE_DPS_Lucid = new("SGE_AoE_Phlegma_Lucid", 6500), + SGE_AoE_DPS_Rhizo = new("SGE_AoE_DPS_Rhizo"), + SGE_AoE_DPS_AddersgallProtect = new("SGE_AoE_DPS_AddersgallProtect", 3); + public static UserFloat + SGE_ST_DPS_EDosisThreshold = new("SGE_ST_Dosis_EDosisThreshold", 3.0f); + #endregion + + #region Healing + public static UserBool + SGE_ST_Heal_Adv = new("SGE_ST_Heal_Adv"), + SGE_ST_Heal_UIMouseOver = new("SGE_ST_Heal_UIMouseOver"), + SGE_AoE_Heal_KeracholeTrait = new("SGE_AoE_Heal_KeracholeTrait"); + public static UserInt + SGE_ST_Heal_Zoe = new("SGE_ST_Heal_Zoe"), + SGE_ST_Heal_Haima = new("SGE_ST_Heal_Haima"), + SGE_ST_Heal_Krasis = new("SGE_ST_Heal_Krasis"), + SGE_ST_Heal_Pepsis = new("SGE_ST_Heal_Pepsis"), + SGE_ST_Heal_Soteria = new("SGE_ST_Heal_Soteria"), + SGE_ST_Heal_EDiagnosisHP = new("SGE_ST_Heal_EDiagnosisHP"), + SGE_ST_Heal_Druochole = new("SGE_ST_Heal_Druochole"), + SGE_ST_Heal_Taurochole = new("SGE_ST_Heal_Taurochole"), + SGE_ST_Heal_Esuna = new("SGE_ST_Heal_Esuna"); + public static UserIntArray + SGE_ST_Heals_Priority = new("SGE_ST_Heals_Priority"), + SGE_AoE_Heals_Priority = new("SGE_AoE_Heals_Priority"); + public static UserBoolArray + SGE_ST_Heal_EDiagnosisOpts = new("SGE_ST_Heal_EDiagnosisOpts"); + #endregion + + public static UserInt + SGE_Eukrasia_Mode = new("SGE_Eukrasia_Mode"); + + internal static void Draw(CustomComboPreset preset) + { + if (preset is CustomComboPreset.SGE_ST_DPS) + UserConfig.DrawAdditionalBoolChoice(SGE_ST_DPS_Adv, $"Apply all selected options to {Dosis2.ActionName()}", $"{Dosis.ActionName()} & {Dosis3.ActionName()} will behave normally."); + + if (preset is CustomComboPreset.SGE_ST_DPS_EDosis) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_DPS_EDosisHPPer, "Stop using at Enemy HP %. Set to Zero to disable this check"); + + UserConfig.DrawAdditionalBoolChoice(SGE_ST_DPS_EDosis_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SGE_ST_DPS_EDosis_Adv) + { + ImGui.Indent(); + UserConfig.DrawRoundedSliderFloat(0, 4, SGE_ST_DPS_EDosisThreshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SGE_ST_DPS_Lucid) + UserConfig.DrawSliderInt(4000, 9500, SGE_ST_DPS_Lucid, "MP Threshold", 150, SliderIncrements.Hundreds); + + if (preset is CustomComboPreset.SGE_ST_DPS_Rhizo) + UserConfig.DrawSliderInt(0, 1, SGE_ST_DPS_Rhizo, "Addersgall Threshold", 150, SliderIncrements.Ones); + + if (preset is CustomComboPreset.SGE_ST_DPS_AddersgallProtect) + UserConfig.DrawSliderInt(1, 3, SGE_ST_DPS_AddersgallProtect, "Addersgall Threshold", 150, SliderIncrements.Ones); + + if (preset is CustomComboPreset.SGE_ST_DPS_Movement) + { + UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Toxikon.ActionName(), $"Use {Toxikon.ActionName()} when Addersting is available.", 4, 0); + UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Dyskrasia.ActionName(), $"Use {Dyskrasia.ActionName()} when in range of a selected enemy target.", 4, 1); + UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Eukrasia.ActionName(), $"Use {Eukrasia.ActionName()}.", 4, 2); + UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Psyche.ActionName(), $"Use {Psyche.ActionName()}.", 4, 3); + } + + if (preset is CustomComboPreset.SGE_AoE_DPS_Lucid) + UserConfig.DrawSliderInt(4000, 9500, SGE_AoE_DPS_Lucid, "MP Threshold", 150, SliderIncrements.Hundreds); + + if (preset is CustomComboPreset.SGE_AoE_DPS_Rhizo) + UserConfig.DrawSliderInt(0, 1, SGE_AoE_DPS_Rhizo, "Addersgall Threshold", 150, SliderIncrements.Ones); + + if (preset is CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) + UserConfig.DrawSliderInt(1, 3, SGE_AoE_DPS_AddersgallProtect, "Addersgall Threshold", 150, SliderIncrements.Ones); + + if (preset is CustomComboPreset.SGE_ST_Heal) + { + UserConfig.DrawAdditionalBoolChoice(SGE_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SGE_ST_Heal_Adv) + { + ImGui.Indent(); + UserConfig.DrawAdditionalBoolChoice(SGE_ST_Heal_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Esuna) + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); + + if (preset is CustomComboPreset.SGE_ST_Heal_Soteria) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, $"Use {Soteria.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 0, $"{Soteria.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Zoe) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, $"Use {Zoe.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 1, $"{Zoe.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Pepsis) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, $"Use {Pepsis.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 2, $"{Pepsis.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Taurochole) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, $"Use {Taurochole.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 3, $"{Taurochole.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Haima) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Haima, $"Use {Haima.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 4, $"{Haima.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Krasis) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, $"Use {Krasis.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 5, $"{Krasis.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_Druochole) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, $"Use {Druochole.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 6, $"{Druochole.ActionName()} Priority: "); + } + + if (preset is CustomComboPreset.SGE_ST_Heal_EDiagnosis) + { + UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, $"Use {EukrasianDiagnosis.ActionName()} when Target HP is at or below set percentage"); + UserConfig.DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {EukrasianDiagnosis.ActionName()}, and normal {Diagnosis.ActionName()} will be unavailable.", 2, 0); + UserConfig.DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); + } + + if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 0, $"{Kerachole.ActionName()} Priority: "); + + if (preset is CustomComboPreset.SGE_AoE_Heal_Ixochole) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 1, $"{Ixochole.ActionName()} Priority: "); + + if (preset is CustomComboPreset.SGE_AoE_Heal_Physis) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 2, $"{Physis.ActionName()} Priority: "); + + if (preset is CustomComboPreset.SGE_AoE_Heal_Holos) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 3, $"{Holos.ActionName()} Priority: "); + + if (preset is CustomComboPreset.SGE_AoE_Heal_Panhaima) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 4, $"{Panhaima.ActionName()} Priority: "); + + if (preset is CustomComboPreset.SGE_AoE_Heal_Pepsis) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 5, $"{Pepsis.ActionName()} Priority: "); + + if (preset is CustomComboPreset.SGE_AoE_Heal_Philosophia) + UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 6, $"{Philosophia.ActionName()} Priority: "); + + + if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) + UserConfig.DrawAdditionalBoolChoice(SGE_AoE_Heal_KeracholeTrait, + "Check for Enhanced Kerachole Trait (Heal over Time)", + $"Enabling this will prevent {Kerachole.ActionName()} from being used when the Heal over Time trait is unavailable."); + + if (preset is CustomComboPreset.SGE_Eukrasia) + { + UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDosis.ActionName()}", "", 0); + UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDiagnosis.ActionName()}", "", 1); + UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianPrognosis.ActionName()}", "", 2); + UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDyskrasia.ActionName()}", "", 3); + } + } + } + } +} diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs index 4adbfb40d..ce2b37bd6 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs @@ -1,15 +1,21 @@ -using Dalamud.Game.ClientState.Objects.Types; -using XIVSlothCombo.Combos.PvE; -using static XIVSlothCombo.Combos.PvE.SGE; +using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Objects.Types; +using XIVSlothCombo.CustomComboNS.Functions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.PvE { - internal class SGEHelper + internal static partial class SGE { + // Sage Gauge & Extensions + public static SGEGauge Gauge => CustomComboFunctions.GetJobGauge(); + public static bool HasAddersgall(this SGEGauge gauge) => gauge.Addersgall > 0; + public static bool HasAddersting(this SGEGauge gauge) => gauge.Addersting > 0; + + public static int GetMatchingConfigST(int i, IGameObject? optionalTarget, out uint action, out bool enabled) { - var healTarget = optionalTarget != null ? optionalTarget : GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); + var healTarget = optionalTarget ?? GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); switch (i) { diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ed77d7c94..198b4bb44 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -287,7 +287,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo //case RDM.JobID: RDM.Config.Draw(preset); break; //case SAM.JobID: SAM.Config.Draw(preset); break; //case SCH.JobID: SCH.Config.Draw(preset); break; - //case SGE.JobID: SGE.Config.Draw(preset); break; + case SGE.JobID: SGE.Config.Draw(preset); break; //case SMN.JobID: SMN.Config.Draw(preset); break; //case VPR.JobID: VPR.Config.Draw(preset); break; //case WAR.JobID: WAR.Config.Draw(preset); break; From 66a42788cd82ca171b4105217cf8399580705246 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:06:43 -0500 Subject: [PATCH 140/208] Uses cleanup --- XIVSlothCombo/Combos/PvE/SGE/SGE.cs | 2 - XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs | 97 +++++++++++----------- XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs | 3 +- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs index f2cc133f0..5ae6f0776 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs @@ -1,4 +1,3 @@ -using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Statuses; using System; @@ -6,7 +5,6 @@ using System.Linq; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; namespace XIVSlothCombo.Combos.PvE diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs index 811ee7025..0da176807 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs @@ -1,7 +1,8 @@ using ImGuiNET; using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Extensions; -using XIVSlothCombo.Window.Functions; +using static XIVSlothCombo.Extensions.UIntExtensions; +using static XIVSlothCombo.Window.Functions.SliderIncrements; +using static XIVSlothCombo.Window.Functions.UserConfig; namespace XIVSlothCombo.Combos.PvE { @@ -55,54 +56,54 @@ public static UserInt internal static void Draw(CustomComboPreset preset) { if (preset is CustomComboPreset.SGE_ST_DPS) - UserConfig.DrawAdditionalBoolChoice(SGE_ST_DPS_Adv, $"Apply all selected options to {Dosis2.ActionName()}", $"{Dosis.ActionName()} & {Dosis3.ActionName()} will behave normally."); + DrawAdditionalBoolChoice(SGE_ST_DPS_Adv, $"Apply all selected options to {Dosis2.ActionName()}", $"{Dosis.ActionName()} & {Dosis3.ActionName()} will behave normally."); if (preset is CustomComboPreset.SGE_ST_DPS_EDosis) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_DPS_EDosisHPPer, "Stop using at Enemy HP %. Set to Zero to disable this check"); + DrawSliderInt(0, 100, SGE_ST_DPS_EDosisHPPer, "Stop using at Enemy HP %. Set to Zero to disable this check"); - UserConfig.DrawAdditionalBoolChoice(SGE_ST_DPS_EDosis_Adv, "Advanced Options", "", isConditionalChoice: true); + DrawAdditionalBoolChoice(SGE_ST_DPS_EDosis_Adv, "Advanced Options", "", isConditionalChoice: true); if (SGE_ST_DPS_EDosis_Adv) { ImGui.Indent(); - UserConfig.DrawRoundedSliderFloat(0, 4, SGE_ST_DPS_EDosisThreshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + DrawRoundedSliderFloat(0, 4, SGE_ST_DPS_EDosisThreshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); ImGui.Unindent(); } } if (preset is CustomComboPreset.SGE_ST_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SGE_ST_DPS_Lucid, "MP Threshold", 150, SliderIncrements.Hundreds); + DrawSliderInt(4000, 9500, SGE_ST_DPS_Lucid, "MP Threshold", 150, Hundreds); if (preset is CustomComboPreset.SGE_ST_DPS_Rhizo) - UserConfig.DrawSliderInt(0, 1, SGE_ST_DPS_Rhizo, "Addersgall Threshold", 150, SliderIncrements.Ones); + DrawSliderInt(0, 1, SGE_ST_DPS_Rhizo, "Addersgall Threshold", 150, Ones); if (preset is CustomComboPreset.SGE_ST_DPS_AddersgallProtect) - UserConfig.DrawSliderInt(1, 3, SGE_ST_DPS_AddersgallProtect, "Addersgall Threshold", 150, SliderIncrements.Ones); + DrawSliderInt(1, 3, SGE_ST_DPS_AddersgallProtect, "Addersgall Threshold", 150, Ones); if (preset is CustomComboPreset.SGE_ST_DPS_Movement) { - UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Toxikon.ActionName(), $"Use {Toxikon.ActionName()} when Addersting is available.", 4, 0); - UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Dyskrasia.ActionName(), $"Use {Dyskrasia.ActionName()} when in range of a selected enemy target.", 4, 1); - UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Eukrasia.ActionName(), $"Use {Eukrasia.ActionName()}.", 4, 2); - UserConfig.DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Psyche.ActionName(), $"Use {Psyche.ActionName()}.", 4, 3); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Toxikon.ActionName(), $"Use {Toxikon.ActionName()} when Addersting is available.", 4, 0); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Dyskrasia.ActionName(), $"Use {Dyskrasia.ActionName()} when in range of a selected enemy target.", 4, 1); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Eukrasia.ActionName(), $"Use {Eukrasia.ActionName()}.", 4, 2); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Psyche.ActionName(), $"Use {Psyche.ActionName()}.", 4, 3); } if (preset is CustomComboPreset.SGE_AoE_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SGE_AoE_DPS_Lucid, "MP Threshold", 150, SliderIncrements.Hundreds); + DrawSliderInt(4000, 9500, SGE_AoE_DPS_Lucid, "MP Threshold", 150, Hundreds); if (preset is CustomComboPreset.SGE_AoE_DPS_Rhizo) - UserConfig.DrawSliderInt(0, 1, SGE_AoE_DPS_Rhizo, "Addersgall Threshold", 150, SliderIncrements.Ones); + DrawSliderInt(0, 1, SGE_AoE_DPS_Rhizo, "Addersgall Threshold", 150, Ones); if (preset is CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) - UserConfig.DrawSliderInt(1, 3, SGE_AoE_DPS_AddersgallProtect, "Addersgall Threshold", 150, SliderIncrements.Ones); + DrawSliderInt(1, 3, SGE_AoE_DPS_AddersgallProtect, "Addersgall Threshold", 150, Ones); if (preset is CustomComboPreset.SGE_ST_Heal) { - UserConfig.DrawAdditionalBoolChoice(SGE_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); + DrawAdditionalBoolChoice(SGE_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); if (SGE_ST_Heal_Adv) { ImGui.Indent(); - UserConfig.DrawAdditionalBoolChoice(SGE_ST_Heal_UIMouseOver, + DrawAdditionalBoolChoice(SGE_ST_Heal_UIMouseOver, "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\n" + "To be used in conjunction with Redirect/Reaction/etc"); @@ -111,90 +112,90 @@ internal static void Draw(CustomComboPreset preset) } if (preset is CustomComboPreset.SGE_ST_Heal_Esuna) - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); + DrawSliderInt(0, 100, SGE_ST_Heal_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); if (preset is CustomComboPreset.SGE_ST_Heal_Soteria) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, $"Use {Soteria.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 0, $"{Soteria.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, $"Use {Soteria.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 0, $"{Soteria.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_Zoe) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, $"Use {Zoe.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 1, $"{Zoe.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, $"Use {Zoe.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 1, $"{Zoe.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_Pepsis) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, $"Use {Pepsis.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 2, $"{Pepsis.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, $"Use {Pepsis.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 2, $"{Pepsis.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_Taurochole) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, $"Use {Taurochole.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 3, $"{Taurochole.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, $"Use {Taurochole.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 3, $"{Taurochole.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_Haima) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Haima, $"Use {Haima.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 4, $"{Haima.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Haima, $"Use {Haima.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 4, $"{Haima.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_Krasis) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, $"Use {Krasis.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 5, $"{Krasis.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, $"Use {Krasis.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 5, $"{Krasis.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_Druochole) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, $"Use {Druochole.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE_ST_Heals_Priority, 7, 6, $"{Druochole.ActionName()} Priority: "); + DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, $"Use {Druochole.ActionName()} when Target HP is at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 6, $"{Druochole.ActionName()} Priority: "); } if (preset is CustomComboPreset.SGE_ST_Heal_EDiagnosis) { - UserConfig.DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, $"Use {EukrasianDiagnosis.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {EukrasianDiagnosis.ActionName()}, and normal {Diagnosis.ActionName()} will be unavailable.", 2, 0); - UserConfig.DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); + DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, $"Use {EukrasianDiagnosis.ActionName()} when Target HP is at or below set percentage"); + DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {EukrasianDiagnosis.ActionName()}, and normal {Diagnosis.ActionName()} will be unavailable.", 2, 0); + DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); } if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 0, $"{Kerachole.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 0, $"{Kerachole.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Ixochole) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 1, $"{Ixochole.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 1, $"{Ixochole.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Physis) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 2, $"{Physis.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 2, $"{Physis.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Holos) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 3, $"{Holos.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 3, $"{Holos.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Panhaima) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 4, $"{Panhaima.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 4, $"{Panhaima.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Pepsis) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 5, $"{Pepsis.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 5, $"{Pepsis.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Philosophia) - UserConfig.DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 6, $"{Philosophia.ActionName()} Priority: "); + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 6, $"{Philosophia.ActionName()} Priority: "); if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) - UserConfig.DrawAdditionalBoolChoice(SGE_AoE_Heal_KeracholeTrait, + DrawAdditionalBoolChoice(SGE_AoE_Heal_KeracholeTrait, "Check for Enhanced Kerachole Trait (Heal over Time)", $"Enabling this will prevent {Kerachole.ActionName()} from being used when the Heal over Time trait is unavailable."); if (preset is CustomComboPreset.SGE_Eukrasia) { - UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDosis.ActionName()}", "", 0); - UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDiagnosis.ActionName()}", "", 1); - UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianPrognosis.ActionName()}", "", 2); - UserConfig.DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDyskrasia.ActionName()}", "", 3); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDosis.ActionName()}", "", 0); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDiagnosis.ActionName()}", "", 1); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianPrognosis.ActionName()}", "", 2); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDyskrasia.ActionName()}", "", 3); } } } diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs index ce2b37bd6..31ed8beea 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Helper.cs @@ -1,6 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; -using XIVSlothCombo.CustomComboNS.Functions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE @@ -8,7 +7,7 @@ namespace XIVSlothCombo.Combos.PvE internal static partial class SGE { // Sage Gauge & Extensions - public static SGEGauge Gauge => CustomComboFunctions.GetJobGauge(); + public static SGEGauge Gauge => GetJobGauge(); public static bool HasAddersgall(this SGEGauge gauge) => gauge.Addersgall > 0; public static bool HasAddersting(this SGEGauge gauge) => gauge.Addersting > 0; From db5ad3e4d54f5b6e497cff0229e1e551a9c3edaa Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 12:55:51 -0500 Subject: [PATCH 141/208] Config changed to switch statement --- XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs | 283 +++++++++++---------- 1 file changed, 143 insertions(+), 140 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs index 0da176807..24662acfd 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs @@ -55,147 +55,150 @@ public static UserInt internal static void Draw(CustomComboPreset preset) { - if (preset is CustomComboPreset.SGE_ST_DPS) - DrawAdditionalBoolChoice(SGE_ST_DPS_Adv, $"Apply all selected options to {Dosis2.ActionName()}", $"{Dosis.ActionName()} & {Dosis3.ActionName()} will behave normally."); - - if (preset is CustomComboPreset.SGE_ST_DPS_EDosis) - { - DrawSliderInt(0, 100, SGE_ST_DPS_EDosisHPPer, "Stop using at Enemy HP %. Set to Zero to disable this check"); - - DrawAdditionalBoolChoice(SGE_ST_DPS_EDosis_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SGE_ST_DPS_EDosis_Adv) - { - ImGui.Indent(); - DrawRoundedSliderFloat(0, 4, SGE_ST_DPS_EDosisThreshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SGE_ST_DPS_Lucid) - DrawSliderInt(4000, 9500, SGE_ST_DPS_Lucid, "MP Threshold", 150, Hundreds); - - if (preset is CustomComboPreset.SGE_ST_DPS_Rhizo) - DrawSliderInt(0, 1, SGE_ST_DPS_Rhizo, "Addersgall Threshold", 150, Ones); - - if (preset is CustomComboPreset.SGE_ST_DPS_AddersgallProtect) - DrawSliderInt(1, 3, SGE_ST_DPS_AddersgallProtect, "Addersgall Threshold", 150, Ones); - - if (preset is CustomComboPreset.SGE_ST_DPS_Movement) - { - DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Toxikon.ActionName(), $"Use {Toxikon.ActionName()} when Addersting is available.", 4, 0); - DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Dyskrasia.ActionName(), $"Use {Dyskrasia.ActionName()} when in range of a selected enemy target.", 4, 1); - DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Eukrasia.ActionName(), $"Use {Eukrasia.ActionName()}.", 4, 2); - DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Psyche.ActionName(), $"Use {Psyche.ActionName()}.", 4, 3); - } - - if (preset is CustomComboPreset.SGE_AoE_DPS_Lucid) - DrawSliderInt(4000, 9500, SGE_AoE_DPS_Lucid, "MP Threshold", 150, Hundreds); - - if (preset is CustomComboPreset.SGE_AoE_DPS_Rhizo) - DrawSliderInt(0, 1, SGE_AoE_DPS_Rhizo, "Addersgall Threshold", 150, Ones); - - if (preset is CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) - DrawSliderInt(1, 3, SGE_AoE_DPS_AddersgallProtect, "Addersgall Threshold", 150, Ones); - - if (preset is CustomComboPreset.SGE_ST_Heal) - { - DrawAdditionalBoolChoice(SGE_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SGE_ST_Heal_Adv) - { - ImGui.Indent(); - DrawAdditionalBoolChoice(SGE_ST_Heal_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Esuna) - DrawSliderInt(0, 100, SGE_ST_Heal_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); - - if (preset is CustomComboPreset.SGE_ST_Heal_Soteria) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, $"Use {Soteria.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 0, $"{Soteria.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Zoe) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, $"Use {Zoe.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 1, $"{Zoe.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Pepsis) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, $"Use {Pepsis.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 2, $"{Pepsis.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Taurochole) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, $"Use {Taurochole.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 3, $"{Taurochole.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Haima) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Haima, $"Use {Haima.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 4, $"{Haima.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Krasis) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, $"Use {Krasis.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 5, $"{Krasis.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Druochole) - { - DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, $"Use {Druochole.ActionName()} when Target HP is at or below set percentage"); - DrawPriorityInput(SGE_ST_Heals_Priority, 7, 6, $"{Druochole.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_EDiagnosis) - { - DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, $"Use {EukrasianDiagnosis.ActionName()} when Target HP is at or below set percentage"); - DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {EukrasianDiagnosis.ActionName()}, and normal {Diagnosis.ActionName()} will be unavailable.", 2, 0); - DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); - } - - if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 0, $"{Kerachole.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Ixochole) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 1, $"{Ixochole.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Physis) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 2, $"{Physis.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Holos) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 3, $"{Holos.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Panhaima) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 4, $"{Panhaima.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Pepsis) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 5, $"{Pepsis.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Philosophia) - DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 6, $"{Philosophia.ActionName()} Priority: "); - - - if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) - DrawAdditionalBoolChoice(SGE_AoE_Heal_KeracholeTrait, - "Check for Enhanced Kerachole Trait (Heal over Time)", - $"Enabling this will prevent {Kerachole.ActionName()} from being used when the Heal over Time trait is unavailable."); - - if (preset is CustomComboPreset.SGE_Eukrasia) + switch (preset) { - DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDosis.ActionName()}", "", 0); - DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDiagnosis.ActionName()}", "", 1); - DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianPrognosis.ActionName()}", "", 2); - DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDyskrasia.ActionName()}", "", 3); + case CustomComboPreset.SGE_ST_DPS: + DrawAdditionalBoolChoice(SGE_ST_DPS_Adv, $"Apply all selected options to {Dosis2.ActionName()}", $"{Dosis.ActionName()} & {Dosis3.ActionName()} will behave normally."); + break; + + case CustomComboPreset.SGE_ST_DPS_EDosis: + DrawSliderInt(0, 100, SGE_ST_DPS_EDosisHPPer, "Stop using at Enemy HP %. Set to Zero to disable this check"); + + DrawAdditionalBoolChoice(SGE_ST_DPS_EDosis_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SGE_ST_DPS_EDosis_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 4, SGE_ST_DPS_EDosisThreshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SGE_ST_DPS_Lucid: + DrawSliderInt(4000, 9500, SGE_ST_DPS_Lucid, "MP Threshold", 150, Hundreds); + break; + + case CustomComboPreset.SGE_ST_DPS_Rhizo: + DrawSliderInt(0, 1, SGE_ST_DPS_Rhizo, "Addersgall Threshold", 150, Ones); + break; + + case CustomComboPreset.SGE_ST_DPS_AddersgallProtect: + DrawSliderInt(1, 3, SGE_ST_DPS_AddersgallProtect, "Addersgall Threshold", 150, Ones); + break; + + case CustomComboPreset.SGE_ST_DPS_Movement: + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Toxikon.ActionName(), $"Use {Toxikon.ActionName()} when Addersting == available.", 4, 0); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Dyskrasia.ActionName(), $"Use {Dyskrasia.ActionName()} when in range of a selected enemy target.", 4, 1); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Eukrasia.ActionName(), $"Use {Eukrasia.ActionName()}.", 4, 2); + DrawHorizontalMultiChoice(SGE_ST_DPS_Movement, Psyche.ActionName(), $"Use {Psyche.ActionName()}.", 4, 3); + break; + + case CustomComboPreset.SGE_AoE_DPS_Lucid: + DrawSliderInt(4000, 9500, SGE_AoE_DPS_Lucid, "MP Threshold", 150, Hundreds); + break; + + case CustomComboPreset.SGE_AoE_DPS_Rhizo: + DrawSliderInt(0, 1, SGE_AoE_DPS_Rhizo, "Addersgall Threshold", 150, Ones); + break; + + case CustomComboPreset.SGE_AoE_DPS_AddersgallProtect: + DrawSliderInt(1, 3, SGE_AoE_DPS_AddersgallProtect, "Addersgall Threshold", 150, Ones); + break; + + case CustomComboPreset.SGE_ST_Heal: + DrawAdditionalBoolChoice(SGE_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); + if (SGE_ST_Heal_Adv) + { + ImGui.Indent(); + DrawAdditionalBoolChoice(SGE_ST_Heal_UIMouseOver, + "Party UI Mouseover Checking", + "Check party member's HP & Debuffs by using mouseover on the party list.\n" + + "To be used in conjunction with Redirect/Reaction/etc"); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.SGE_ST_Heal_Esuna: + DrawSliderInt(0, 100, SGE_ST_Heal_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); + break; + + case CustomComboPreset.SGE_ST_Heal_Soteria: + DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, $"Use {Soteria.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 0, $"{Soteria.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_Zoe: + DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, $"Use {Zoe.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 1, $"{Zoe.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_Pepsis: + DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, $"Use {Pepsis.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 2, $"{Pepsis.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_Taurochole: + DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, $"Use {Taurochole.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 3, $"{Taurochole.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_Haima: + DrawSliderInt(0, 100, SGE_ST_Heal_Haima, $"Use {Haima.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 4, $"{Haima.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_Krasis: + DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, $"Use {Krasis.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 5, $"{Krasis.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_Druochole: + DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, $"Use {Druochole.ActionName()} when Target HP == at or below set percentage"); + DrawPriorityInput(SGE_ST_Heals_Priority, 7, 6, $"{Druochole.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_ST_Heal_EDiagnosis: + DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, $"Use {EukrasianDiagnosis.ActionName()} when Target HP == at or below set percentage"); + DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {EukrasianDiagnosis.ActionName()}, and normal {Diagnosis.ActionName()} will be unavailable.", 2, 0); + DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); + break; + + case CustomComboPreset.SGE_AoE_Heal_Kerachole: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 0, $"{Kerachole.ActionName()} Priority: "); + DrawAdditionalBoolChoice(SGE_AoE_Heal_KeracholeTrait, + "Check for Enhanced Kerachole Trait (Heal over Time)", + $"Enabling this will prevent {Kerachole.ActionName()} from being used when the Heal over Time trait == unavailable."); + break; + + case CustomComboPreset.SGE_AoE_Heal_Ixochole: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 1, $"{Ixochole.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_AoE_Heal_Physis: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 2, $"{Physis.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_AoE_Heal_Holos: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 3, $"{Holos.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_AoE_Heal_Panhaima: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 4, $"{Panhaima.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_AoE_Heal_Pepsis: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 5, $"{Pepsis.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_AoE_Heal_Philosophia: + DrawPriorityInput(SGE_AoE_Heals_Priority, 7, 6, $"{Philosophia.ActionName()} Priority: "); + break; + + case CustomComboPreset.SGE_Eukrasia: + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDosis.ActionName()}", "", 0); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDiagnosis.ActionName()}", "", 1); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianPrognosis.ActionName()}", "", 2); + DrawRadioButton(SGE_Eukrasia_Mode, $"{EukrasianDyskrasia.ActionName()}", "", 3); + break; } } } From 94348a3341965c2c16311fc86bad2b04d27770fb Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 13:48:21 -0500 Subject: [PATCH 142/208] Moved for new layout --- XIVSlothCombo/Combos/PvE/{ => WHM}/WHM.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => WHM}/WHM.cs (100%) diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs similarity index 100% rename from XIVSlothCombo/Combos/PvE/WHM.cs rename to XIVSlothCombo/Combos/PvE/WHM/WHM.cs From 983db59f9dc30a18100b70dbfd6efeb2f51c9bc9 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 14:01:39 -0500 Subject: [PATCH 143/208] Separated config out for new layout --- XIVSlothCombo/Combos/PvE/WHM/WHM.cs | 40 +---- XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs | 161 +++++++++++++++++++ XIVSlothCombo/Window/Functions/Presets.cs | 2 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 106 ------------ 4 files changed, 163 insertions(+), 146 deletions(-) create mode 100644 XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs index 86b8deb6d..e23735116 100644 --- a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs @@ -4,12 +4,11 @@ using System.Linq; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; namespace XIVSlothCombo.Combos.PvE { - internal static class WHM + internal static partial class WHM { public const byte ClassID = 6; public const byte JobID = 24; @@ -86,43 +85,6 @@ internal static readonly Dictionary { Dia, Debuffs.Dia } }; - public static class Config - { - internal static UserInt - WHM_STDPS_Lucid = new("WHMLucidDreamingFeature"), - WHM_STDPS_MainCombo_DoT = new("WHM_ST_MainCombo_DoT"), - WHM_AoEDPS_Lucid = new("WHM_AoE_Lucid"), - WHM_STHeals_Lucid = new("WHM_STHeals_Lucid"), - WHM_STHeals_ThinAir = new("WHM_STHeals_ThinAir"), - WHM_STHeals_Esuna = new("WHM_Cure2_Esuna"), - WHM_STHeals_BenedictionHP = new("WHM_STHeals_BenedictionHP"), - WHM_STHeals_TetraHP = new("WHM_STHeals_TetraHP"), - WHM_STHeals_BenisonHP = new("WHM_STHeals_BenisonHP"), - WHM_STHeals_AquaveilHP = new("WHM_STHeals_AquaveilHP"), - WHM_AoEHeals_Lucid = new("WHM_AoEHeals_Lucid"), - WHM_AoEHeals_ThinAir = new("WHM_AoE_ThinAir"), - WHM_AoEHeals_Cure3MP = new("WHM_AoE_Cure3MP"); - internal static UserBool - WHM_ST_MainCombo_DoT_Adv = new("WHM_ST_MainCombo_DoT_Adv"), - WHM_ST_MainCombo_Adv = new("WHM_ST_MainCombo_Adv"), - WHM_ST_MainCombo_Opener_Swiftcast = new("WHM_ST_Opener_Swiftcast"), - WHM_AoEDPS_PresenceOfMindWeave = new("WHM_AoEDPS_PresenceOfMindWeave"), - WHM_STHeals_UIMouseOver = new("WHM_STHeals_UIMouseOver"), - WHM_STHeals_BenedictionWeave = new("WHM_STHeals_BenedictionWeave"), - WHM_STHeals_TetraWeave = new("WHM_STHeals_TetraWeave"), - WHM_STHeals_BenisonWeave = new("WHM_STHeals_BenisonWeave"), - WHM_STHeals_AquaveilWeave = new("WHM_STHeals_AquaveilWeave"), - WHM_AoEHeals_PlenaryWeave = new("WHM_AoEHeals_PlenaryWeave"), - WHM_AoEHeals_AssizeWeave = new("WHM_AoEHeals_AssizeWeave"), - WHM_AoEHeals_MedicaMO = new("WHM_AoEHeals_MedicaMO"); - internal static UserFloat - WHM_ST_MainCombo_DoT_Threshold = new("WHM_ST_MainCombo_DoT_Threshold"), - WHM_STHeals_RegenTimer = new("WHM_STHeals_RegenTimer"), - WHM_AoEHeals_MedicaTime = new("WHM_AoEHeals_MedicaTime"); - public static UserBoolArray - WHM_ST_MainCombo_Adv_Actions = new("WHM_ST_MainCombo_Adv_Actions"); - } - internal class WHM_SolaceMisery : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.WHM_SolaceMisery; diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs new file mode 100644 index 000000000..d6a562c2b --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs @@ -0,0 +1,161 @@ +using ImGuiNET; +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Extensions.UIntExtensions; +using static XIVSlothCombo.Window.Functions.UserConfig; +using static XIVSlothCombo.Window.Functions.SliderIncrements; + +namespace XIVSlothCombo.Combos.PvE +{ + internal static partial class WHM + { + public static class Config + { + internal static UserInt + WHM_STDPS_Lucid = new("WHMLucidDreamingFeature"), + WHM_STDPS_MainCombo_DoT = new("WHM_ST_MainCombo_DoT"), + WHM_AoEDPS_Lucid = new("WHM_AoE_Lucid"), + WHM_STHeals_Lucid = new("WHM_STHeals_Lucid"), + WHM_STHeals_ThinAir = new("WHM_STHeals_ThinAir"), + WHM_STHeals_Esuna = new("WHM_Cure2_Esuna"), + WHM_STHeals_BenedictionHP = new("WHM_STHeals_BenedictionHP"), + WHM_STHeals_TetraHP = new("WHM_STHeals_TetraHP"), + WHM_STHeals_BenisonHP = new("WHM_STHeals_BenisonHP"), + WHM_STHeals_AquaveilHP = new("WHM_STHeals_AquaveilHP"), + WHM_AoEHeals_Lucid = new("WHM_AoEHeals_Lucid"), + WHM_AoEHeals_ThinAir = new("WHM_AoE_ThinAir"), + WHM_AoEHeals_Cure3MP = new("WHM_AoE_Cure3MP"); + internal static UserBool + WHM_ST_MainCombo_DoT_Adv = new("WHM_ST_MainCombo_DoT_Adv"), + WHM_ST_MainCombo_Adv = new("WHM_ST_MainCombo_Adv"), + WHM_ST_MainCombo_Opener_Swiftcast = new("WHM_ST_Opener_Swiftcast"), + WHM_AoEDPS_PresenceOfMindWeave = new("WHM_AoEDPS_PresenceOfMindWeave"), + WHM_STHeals_UIMouseOver = new("WHM_STHeals_UIMouseOver"), + WHM_STHeals_BenedictionWeave = new("WHM_STHeals_BenedictionWeave"), + WHM_STHeals_TetraWeave = new("WHM_STHeals_TetraWeave"), + WHM_STHeals_BenisonWeave = new("WHM_STHeals_BenisonWeave"), + WHM_STHeals_AquaveilWeave = new("WHM_STHeals_AquaveilWeave"), + WHM_AoEHeals_PlenaryWeave = new("WHM_AoEHeals_PlenaryWeave"), + WHM_AoEHeals_AssizeWeave = new("WHM_AoEHeals_AssizeWeave"), + WHM_AoEHeals_MedicaMO = new("WHM_AoEHeals_MedicaMO"); + internal static UserFloat + WHM_ST_MainCombo_DoT_Threshold = new("WHM_ST_MainCombo_DoT_Threshold"), + WHM_STHeals_RegenTimer = new("WHM_STHeals_RegenTimer"), + WHM_AoEHeals_MedicaTime = new("WHM_AoEHeals_MedicaTime"); + public static UserBoolArray + WHM_ST_MainCombo_Adv_Actions = new("WHM_ST_MainCombo_Adv_Actions"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.WHM_ST_MainCombo: + DrawAdditionalBoolChoice(WHM_ST_MainCombo_Adv, "Advanced Action Options", "Change how actions are handled", isConditionalChoice: true); + + if (WHM_ST_MainCombo_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(WHM_ST_MainCombo_Adv_Actions, "On Stone/Glare", "Apply options to all Stones and Glares.", 3, 0); + DrawHorizontalMultiChoice(WHM_ST_MainCombo_Adv_Actions, "On Aero/Dia", "Apply options to Aeros and Dia.", 3, 1); + DrawHorizontalMultiChoice(WHM_ST_MainCombo_Adv_Actions, $"On {Stone2.ActionName()}", $"Apply options to On {Stone2.ActionName()}.", 3, 2); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.WHM_ST_MainCombo_Lucid: + DrawSliderInt(4000, 9500, WHM_STDPS_Lucid, "Set value for your MP to be at or under for this feature to work.", 150, Hundreds); + break; + + case CustomComboPreset.WHM_ST_MainCombo_DoT: + DrawSliderInt(0, 100, WHM_STDPS_MainCombo_DoT, "Stop using at Enemy HP %. Set to Zero to disable this check."); + + DrawAdditionalBoolChoice(WHM_ST_MainCombo_DoT_Adv, "Advanced Options", "", isConditionalChoice: true); + if (WHM_ST_MainCombo_DoT_Adv) + { + ImGui.Indent(); + DrawRoundedSliderFloat(0, 4, WHM_ST_MainCombo_DoT_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.WHM_AoE_DPS_Lucid: + DrawSliderInt(4000, 9500, WHM_AoEDPS_Lucid, "Set value for your MP to be at or under for this feature to work", 150, Hundreds); + break; + + case CustomComboPreset.WHM_AoE_DPS_PresenceOfMind: + DrawAdditionalBoolChoice(WHM_AoEDPS_PresenceOfMindWeave, "Only Weave or Use Whilst Moving.", "Holy has no weave window so this can only be used to weave against healing or single target damage spells.\n\n" + + "This will minimize the amount of GCD delay you will get but reduce the frequency it will be used."); + break; + case CustomComboPreset.WHM_AoEHeals_Lucid: + DrawSliderInt(4000, 9500, WHM_AoEHeals_Lucid, "Set value for your MP to be at or under for this feature to work", 150, Hundreds); + break; + + case CustomComboPreset.WHM_STHeals_Lucid: + DrawSliderInt(4000, 9500, WHM_STHeals_Lucid, "Set value for your MP to be at or under for this feature to work", 150, Hundreds); + break; + + case CustomComboPreset.WHM_STHeals_Esuna: + DrawSliderInt(0, 100, WHM_STHeals_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); + break; + + case CustomComboPreset.WHM_AoEHeals_ThinAir: + DrawSliderInt(0, 1, WHM_AoEHeals_ThinAir, "How many charges to keep ready? (0 = Use all)"); + break; + + case CustomComboPreset.WHM_AoEHeals_Cure3: + DrawSliderInt(1500, 8500, WHM_AoEHeals_Cure3MP, "Use when MP is above", sliderIncrement: 500); + break; + + case CustomComboPreset.WHM_STHeals: + DrawAdditionalBoolChoice(WHM_STHeals_UIMouseOver, "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\nTo be used in conjunction with Redirect/Reaction/etc."); + break; + + case CustomComboPreset.WHM_STHeals_ThinAir: + DrawSliderInt(0, 1, WHM_STHeals_ThinAir, "How many charges to keep ready? (0 = Use all)"); + break; + + case CustomComboPreset.WHM_STHeals_Regen: + DrawRoundedSliderFloat(0f, 6f, WHM_STHeals_RegenTimer, "Time Remaining Before Refreshing"); + break; + + case CustomComboPreset.WHM_ST_MainCombo_Opener: + DrawAdditionalBoolChoice(WHM_ST_MainCombo_Opener_Swiftcast, "Swiftcast Option", "Adds Swiftcast to the opener."); + break; + + case CustomComboPreset.WHM_STHeals_Benediction: + DrawAdditionalBoolChoice(WHM_STHeals_BenedictionWeave, "Only Weave", ""); + DrawSliderInt(1, 100, WHM_STHeals_BenedictionHP, "Use when target HP% is at or below."); + break; + + case CustomComboPreset.WHM_STHeals_Tetragrammaton: + DrawAdditionalBoolChoice(WHM_STHeals_TetraWeave, "Only Weave", ""); + DrawSliderInt(1, 100, WHM_STHeals_TetraHP, "Use when target HP% is at or below."); + break; + + case CustomComboPreset.WHM_STHeals_Benison: + DrawAdditionalBoolChoice(WHM_STHeals_BenisonWeave, "Only Weave", ""); + DrawSliderInt(1, 100, WHM_STHeals_BenisonHP, "Use when target HP% is at or below."); + break; + + case CustomComboPreset.WHM_STHeals_Aquaveil: + DrawAdditionalBoolChoice(WHM_STHeals_AquaveilWeave, "Only Weave", ""); + DrawSliderInt(1, 100, WHM_STHeals_AquaveilHP, "Use when target HP% is at or below."); + break; + + case CustomComboPreset.WHM_AoEHeals_Assize: + DrawAdditionalBoolChoice(WHM_AoEHeals_AssizeWeave, "Only Weave", ""); + break; + + case CustomComboPreset.WHM_AoEHeals_Plenary: + DrawAdditionalBoolChoice(WHM_AoEHeals_PlenaryWeave, "Only Weave", ""); + break; + + case CustomComboPreset.WHM_AoEHeals_Medica2: + DrawRoundedSliderFloat(0f, 6f, WHM_AoEHeals_MedicaTime, "Time Remaining on Buff to Renew"); + DrawAdditionalBoolChoice(WHM_AoEHeals_MedicaMO, "Party UI Mousover Checking", "Check your mouseover target for the Medica II/III buff.\nTo be used in conjunction with Redirect/Reaction/etc."); + break; + } + + } + } + } +} diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ed77d7c94..0d988967c 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -291,7 +291,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo //case SMN.JobID: SMN.Config.Draw(preset); break; //case VPR.JobID: VPR.Config.Draw(preset); break; //case WAR.JobID: WAR.Config.Draw(preset); break; - //case WHM.JobID: WHM.Config.Draw(preset); break; + case WHM.JobID: WHM.Config.Draw(preset); break; default: UserConfigItems.Draw(preset, enabled); break; } } diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..9daf3154d 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2505,113 +2505,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region WHITE MAGE - if (preset is CustomComboPreset.WHM_ST_MainCombo) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_ST_MainCombo_Adv, "Advanced Action Options", "Change how actions are handled", isConditionalChoice: true); - - if (WHM.Config.WHM_ST_MainCombo_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(WHM.Config.WHM_ST_MainCombo_Adv_Actions, "On Stone/Glare", "Apply options to all Stones and Glares.", 3, 0); - UserConfig.DrawHorizontalMultiChoice(WHM.Config.WHM_ST_MainCombo_Adv_Actions, "On Aero/Dia", "Apply options to Aeros and Dia.", 3, 1); - UserConfig.DrawHorizontalMultiChoice(WHM.Config.WHM_ST_MainCombo_Adv_Actions, "On Stone II", "Apply options to Stone II.", 3, 2); - ImGui.Unindent(); - } - } - - if (preset == CustomComboPreset.WHM_ST_MainCombo_Lucid) - UserConfig.DrawSliderInt(4000, 9500, WHM.Config.WHM_STDPS_Lucid, "Set value for your MP to be at or under for this feature to work.", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.WHM_ST_MainCombo_DoT) - { - UserConfig.DrawSliderInt(0, 100, WHM.Config.WHM_STDPS_MainCombo_DoT, "Stop using at Enemy HP %. Set to Zero to disable this check."); - - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_ST_MainCombo_DoT_Adv, "Advanced Options", "", isConditionalChoice: true); - if (PluginConfiguration.GetCustomBoolValue(WHM.Config.WHM_ST_MainCombo_DoT_Adv)) - { - ImGui.Indent(); - UserConfig.DrawRoundedSliderFloat(0, 4, WHM.Config.WHM_ST_MainCombo_DoT_Threshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); - ImGui.Unindent(); - } - } - - if (preset == CustomComboPreset.WHM_AoE_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, WHM.Config.WHM_AoEDPS_Lucid, "Set value for your MP to be at or under for this feature to work", 150, SliderIncrements.Hundreds); - - if (preset == CustomComboPreset.WHM_AoE_DPS_PresenceOfMind) - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_AoEDPS_PresenceOfMindWeave, "Only Weave or Use Whilst Moving.", "Holy has no weave window so this can only be used to weave against healing or single target damage spells.\n\n" + - "This will minimize the amount of GCD delay you will get but reduce the frequency it will be used."); - - if (preset == CustomComboPreset.WHM_AoEHeals_Lucid) - UserConfig.DrawSliderInt(4000, 9500, WHM.Config.WHM_AoEHeals_Lucid, "Set value for your MP to be at or under for this feature to work", 150, SliderIncrements.Hundreds); - - if (preset == CustomComboPreset.WHM_STHeals_Lucid) - UserConfig.DrawSliderInt(4000, 9500, WHM.Config.WHM_STHeals_Lucid, "Set value for your MP to be at or under for this feature to work", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.WHM_STHeals_Esuna) - UserConfig.DrawSliderInt(0, 100, WHM.Config.WHM_STHeals_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); - - if (preset == CustomComboPreset.WHM_AoEHeals_ThinAir) - UserConfig.DrawSliderInt(0, 1, WHM.Config.WHM_AoEHeals_ThinAir, "How many charges to keep ready? (0 = Use all)"); - - if (preset == CustomComboPreset.WHM_AoEHeals_Cure3) - UserConfig.DrawSliderInt(1500, 8500, WHM.Config.WHM_AoEHeals_Cure3MP, "Use when MP is above", sliderIncrement: 500); - - if (preset == CustomComboPreset.WHM_STHeals) - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_STHeals_UIMouseOver, "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\nTo be used in conjunction with Redirect/Reaction/etc."); - - if (preset == CustomComboPreset.WHM_STHeals_ThinAir) - UserConfig.DrawSliderInt(0, 1, WHM.Config.WHM_STHeals_ThinAir, "How many charges to keep ready? (0 = Use all)"); - - if (preset == CustomComboPreset.WHM_STHeals_Regen) - UserConfig.DrawRoundedSliderFloat(0f, 6f, WHM.Config.WHM_STHeals_RegenTimer, "Time Remaining Before Refreshing"); - - if (preset == CustomComboPreset.WHM_ST_MainCombo_Opener) - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_ST_MainCombo_Opener_Swiftcast, "Swiftcast Option", "Adds Swiftcast to the opener."); - - if (preset == CustomComboPreset.WHM_STHeals_Benediction) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_STHeals_BenedictionWeave, "Only Weave", ""); - UserConfig.DrawSliderInt(1, 100, WHM.Config.WHM_STHeals_BenedictionHP, "Use when target HP% is at or below."); - } - - if (preset == CustomComboPreset.WHM_STHeals_Tetragrammaton) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_STHeals_TetraWeave, "Only Weave", ""); - UserConfig.DrawSliderInt(1, 100, WHM.Config.WHM_STHeals_TetraHP, "Use when target HP% is at or below."); - } - - if (preset == CustomComboPreset.WHM_STHeals_Benison) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_STHeals_BenisonWeave, "Only Weave", ""); - UserConfig.DrawSliderInt(1, 100, WHM.Config.WHM_STHeals_BenisonHP, "Use when target HP% is at or below."); - } - - if (preset == CustomComboPreset.WHM_STHeals_Aquaveil) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_STHeals_AquaveilWeave, "Only Weave", ""); - UserConfig.DrawSliderInt(1, 100, WHM.Config.WHM_STHeals_AquaveilHP, "Use when target HP% is at or below."); - } - - if (preset == CustomComboPreset.WHM_AoEHeals_Assize) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_AoEHeals_AssizeWeave, "Only Weave", ""); - } - - if (preset == CustomComboPreset.WHM_AoEHeals_Plenary) - { - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_AoEHeals_PlenaryWeave, "Only Weave", ""); - } - - if (preset == CustomComboPreset.WHM_AoEHeals_Medica2) - { - UserConfig.DrawRoundedSliderFloat(0f, 6f, WHM.Config.WHM_AoEHeals_MedicaTime, "Time Remaining on Buff to Renew"); - UserConfig.DrawAdditionalBoolChoice(WHM.Config.WHM_AoEHeals_MedicaMO, "Party UI Mousover Checking", "Check your mouseover target for the Medica II/III buff.\nTo be used in conjunction with Redirect/Reaction/etc."); - } - - #endregion // ==================================================================================== #region DOH From bce3efc1d3f92f72671e58372b4c26b352d9231a Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:30:53 -0500 Subject: [PATCH 144/208] Removed SGE from UserConfig.cs --- XIVSlothCombo/Window/Functions/UserConfig.cs | 146 ------------------- 1 file changed, 146 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..a610e9cd4 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1989,153 +1989,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region SAGE - if (preset is CustomComboPreset.SGE_ST_DPS) - UserConfig.DrawAdditionalBoolChoice(SGE.Config.SGE_ST_DPS_Adv, $"Apply all selected options to {SGE.Dosis2.ActionName()}", $"{SGE.Dosis.ActionName()} & {SGE.Dosis3.ActionName()} will behave normally."); - - if (preset is CustomComboPreset.SGE_ST_DPS_EDosis) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_DPS_EDosisHPPer, "Stop using at Enemy HP %. Set to Zero to disable this check"); - - UserConfig.DrawAdditionalBoolChoice(SGE.Config.SGE_ST_DPS_EDosis_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SGE.Config.SGE_ST_DPS_EDosis_Adv) - { - ImGui.Indent(); - UserConfig.DrawRoundedSliderFloat(0, 4, SGE.Config.SGE_ST_DPS_EDosisThreshold, "Seconds remaining before reapplying the DoT. Set to Zero to disable this check.", digits: 1); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SGE_ST_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SGE.Config.SGE_ST_DPS_Lucid, "MP Threshold", 150, SliderIncrements.Hundreds); - - - if (preset is CustomComboPreset.SGE_ST_DPS_Rhizo) - UserConfig.DrawSliderInt(0, 1, SGE.Config.SGE_ST_DPS_Rhizo, "Addersgall Threshold", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.SGE_ST_DPS_AddersgallProtect) - UserConfig.DrawSliderInt(1, 3, SGE.Config.SGE_ST_DPS_AddersgallProtect, "Addersgall Threshold", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.SGE_ST_DPS_Movement) - { - UserConfig.DrawHorizontalMultiChoice(SGE.Config.SGE_ST_DPS_Movement, SGE.Toxikon.ActionName(), $"Use {SGE.Toxikon.ActionName()} when Addersting is available.", 4, 0); - UserConfig.DrawHorizontalMultiChoice(SGE.Config.SGE_ST_DPS_Movement, SGE.Dyskrasia.ActionName(), $"Use {SGE.Dyskrasia.ActionName()} when in range of a selected enemy target.", 4, 1); - UserConfig.DrawHorizontalMultiChoice(SGE.Config.SGE_ST_DPS_Movement, SGE.Eukrasia.ActionName(), $"Use {SGE.Eukrasia.ActionName()}.", 4, 2); - UserConfig.DrawHorizontalMultiChoice(SGE.Config.SGE_ST_DPS_Movement, SGE.Psyche.ActionName(), $"Use {SGE.Psyche.ActionName()}.", 4, 3); - } - - if (preset is CustomComboPreset.SGE_AoE_DPS_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SGE.Config.SGE_AoE_DPS_Lucid, "MP Threshold", 150, SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.SGE_AoE_DPS_Rhizo) - UserConfig.DrawSliderInt(0, 1, SGE.Config.SGE_AoE_DPS_Rhizo, "Addersgall Threshold", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) - UserConfig.DrawSliderInt(1, 3, SGE.Config.SGE_AoE_DPS_AddersgallProtect, "Addersgall Threshold", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.SGE_ST_Heal) - { - UserConfig.DrawAdditionalBoolChoice(SGE.Config.SGE_ST_Heal_Adv, "Advanced Options", "", isConditionalChoice: true); - if (SGE.Config.SGE_ST_Heal_Adv) - { - ImGui.Indent(); - UserConfig.DrawAdditionalBoolChoice(SGE.Config.SGE_ST_Heal_UIMouseOver, - "Party UI Mouseover Checking", - "Check party member's HP & Debuffs by using mouseover on the party list.\n" + - "To be used in conjunction with Redirect/Reaction/etc"); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Esuna) - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); - - if (preset is CustomComboPreset.SGE_ST_Heal_Soteria) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Soteria, $"Use {SGE.Soteria.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 0, $"{SGE.Soteria.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Zoe) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Zoe, $"Use {SGE.Zoe.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 1, $"{SGE.Zoe.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Pepsis) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Pepsis, $"Use {SGE.Pepsis.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 2, $"{SGE.Pepsis.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Taurochole) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Taurochole, $"Use {SGE.Taurochole.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 3, $"{SGE.Taurochole.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Haima) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Haima, $"Use {SGE.Haima.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 4, $"{SGE.Haima.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Krasis) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Krasis, $"Use {SGE.Krasis.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 5, $"{SGE.Krasis.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_Druochole) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_Druochole, $"Use {SGE.Druochole.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawPriorityInput(SGE.Config.SGE_ST_Heals_Priority, 7, 6, $"{SGE.Druochole.ActionName()} Priority: "); - } - - if (preset is CustomComboPreset.SGE_ST_Heal_EDiagnosis) - { - UserConfig.DrawSliderInt(0, 100, SGE.Config.SGE_ST_Heal_EDiagnosisHP, $"Use {SGE.EukrasianDiagnosis.ActionName()} when Target HP is at or below set percentage"); - UserConfig.DrawHorizontalMultiChoice(SGE.Config.SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {SGE.EukrasianDiagnosis.ActionName()}, and normal {SGE.Diagnosis.ActionName()} will be unavailable.", 2, 0); - UserConfig.DrawHorizontalMultiChoice(SGE.Config.SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); - } - - if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 0, $"{SGE.Kerachole.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Ixochole) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 1, $"{SGE.Ixochole.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Physis) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 2, $"{SGE.Physis.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Holos) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 3, $"{SGE.Holos.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Panhaima) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 4, $"{SGE.Panhaima.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Pepsis) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 5, $"{SGE.Pepsis.ActionName()} Priority: "); - - if (preset is CustomComboPreset.SGE_AoE_Heal_Philosophia) - UserConfig.DrawPriorityInput(SGE.Config.SGE_AoE_Heals_Priority, 7, 6, $"{SGE.Philosophia.ActionName()} Priority: "); - - - if (preset is CustomComboPreset.SGE_AoE_Heal_Kerachole) - UserConfig.DrawAdditionalBoolChoice(SGE.Config.SGE_AoE_Heal_KeracholeTrait, - "Check for Enhanced Kerachole Trait (Heal over Time)", - $"Enabling this will prevent {SGE.Kerachole.ActionName()} from being used when the Heal over Time trait is unavailable."); - - if (preset is CustomComboPreset.SGE_Eukrasia) - { - UserConfig.DrawRadioButton(SGE.Config.SGE_Eukrasia_Mode, $"{SGE.EukrasianDosis.ActionName()}", "", 0); - UserConfig.DrawRadioButton(SGE.Config.SGE_Eukrasia_Mode, $"{SGE.EukrasianDiagnosis.ActionName()}", "", 1); - UserConfig.DrawRadioButton(SGE.Config.SGE_Eukrasia_Mode, $"{SGE.EukrasianPrognosis.ActionName()}", "", 2); - UserConfig.DrawRadioButton(SGE.Config.SGE_Eukrasia_Mode, $"{SGE.EukrasianDyskrasia.ActionName()}", "", 3); - } - - #endregion // ==================================================================================== #region SAMURAI From 7be0d84a44f4865ed1efa2372bcd4dfb3d30fd1f Mon Sep 17 00:00:00 2001 From: Mattia Wijns Date: Sun, 29 Sep 2024 01:20:26 +0200 Subject: [PATCH 145/208] mnk refactor to new layout --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 378 ------------------ XIVSlothCombo/Combos/PvE/{ => MNK}/MNK.cs | 55 ++- XIVSlothCombo/Combos/PvE/MNK/MNK_Config.cs | 54 +++ XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs | 389 +++++++++++++++++++ XIVSlothCombo/Window/Functions/Presets.cs | 1 + XIVSlothCombo/Window/Functions/UserConfig.cs | 34 -- 6 files changed, 467 insertions(+), 444 deletions(-) delete mode 100644 XIVSlothCombo/Combos/JobHelpers/MNK.cs rename XIVSlothCombo/Combos/PvE/{ => MNK}/MNK.cs (94%) create mode 100644 XIVSlothCombo/Combos/PvE/MNK/MNK_Config.cs create mode 100644 XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs deleted file mode 100644 index 08cac0aef..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ /dev/null @@ -1,378 +0,0 @@ -using Dalamud.Game.ClientState.JobGauge.Enums; -using ECommons.DalamudServices; -using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; -using XIVSlothCombo.Data; -using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; - -namespace XIVSlothCombo.Combos.JobHelpers; - -internal abstract class MNKHelper : MNK -{ - public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) - { - if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) - return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) - ? DragonKick - : OriginalHook(Bootshine); - - if (HasEffect(Buffs.RaptorForm)) - return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) - ? TwinSnakes - : OriginalHook(TrueStrike); - - if (HasEffect(Buffs.CoeurlForm)) - { - if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) - { - if (!OnTargetsRear() && - TargetNeedsPositionals() && - !HasEffect(Buffs.TrueNorth) && - ActionReady(TrueNorth) && - useTrueNorthIfEnabled) - return TrueNorth; - - return Demolish; - } - - if (LevelChecked(SnapPunch)) - { - if (!OnTargetsFlank() && - TargetNeedsPositionals() && - !HasEffect(Buffs.TrueNorth) && - ActionReady(TrueNorth) && - useTrueNorthIfEnabled) - return TrueNorth; - - return OriginalHook(SnapPunch); - } - } - - return actionId; - } -} - -internal class MNKOpenerLogic : MNK -{ - private OpenerState currentState = OpenerState.PrePull; - - public uint OpenerStep; - - public uint PrePullStep; - - private static uint OpenerLevel => 100; - - public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; - - private static bool CanOpener => HasCooldowns() && LevelChecked; - - public OpenerState CurrentState - { - get => currentState; - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); - if (value == OpenerState.InOpener) OpenerStep = 1; - - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; - } - } - } - - private static bool HasCooldowns() - { - if (GetRemainingCharges(PerfectBalance) < 2) - return false; - - if (!ActionReady(Brotherhood)) - return false; - - if (!ActionReady(RiddleOfFire)) - return false; - - if (!ActionReady(RiddleOfWind)) - return false; - - if (!ActionReady(Meditation) && Gauge.Chakra < 5) - return false; - - if (Gauge.Nadi != Nadi.NONE) - return false; - - if (Gauge.RaptorFury != 0 || Gauge.CoeurlFury != 0) - return false; - - return true; - } - - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (CanOpener && PrePullStep == 0) PrePullStep = 1; - - if (!HasCooldowns()) PrePullStep = 0; - - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (Gauge.Chakra == 5 && PrePullStep == 1) PrePullStep++; - else if (PrePullStep == 1) actionID = OriginalHook(Meditation); - - if (HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 2) PrePullStep++; - else if (PrePullStep == 2) actionID = FormShift; - - if (WasLastAction(DragonKick) && PrePullStep == 3) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 3) actionID = DragonKick; - - if (!HasEffect(Buffs.FormlessFist) && Gauge.Chakra == 5 && PrePullStep == 3) - currentState = OpenerState.FailedOpener; - - if (ActionWatching.CombatActions.Count > 2 && InCombat()) - CurrentState = OpenerState.FailedOpener; - - return true; - } - PrePullStep = 0; - - return false; - } - - private bool DoSlOpener(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (currentState == OpenerState.InOpener) - { - if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && - CanWeave(ActionWatching.LastWeaponskill) && - Gauge.Chakra >= 5 && - OpenerStep > 9) - { - actionID = TheForbiddenChakra; - - return true; - } - - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) - OpenerStep++; - else if (OpenerStep == 1) actionID = PerfectBalance; - - if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = TwinSnakes; - - if (WasLastWeaponskill(Demolish) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Demolish; - - if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Brotherhood; - - if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = LeapingOpo; - - if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = TheForbiddenChakra; - - if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; - - if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = RisingPhoenix; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonKick; - - if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = WindsReply; - - if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = FiresReply; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = LeapingOpo; - - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) - OpenerStep++; - else if (OpenerStep == 14) actionID = PerfectBalance; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = DragonKick; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LeapingOpo; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = DragonKick; - - if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = ElixirBurst; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 19) actionID = LeapingOpo; - - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; - - if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || - (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || - (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || - (actionID is Brotherhood && IsOnCooldown(Brotherhood))) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - Svc.Log.Debug($"Failed at {actionID}"); - CurrentState = OpenerState.FailedOpener; - - return false; - } - - return true; - } - - return false; - } - - private bool DoLlOpener(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (currentState == OpenerState.InOpener) - { - if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && - CanWeave(ActionWatching.LastWeaponskill) && - Gauge.Chakra >= 5 && - OpenerStep > 9) - { - actionID = TheForbiddenChakra; - - return true; - } - - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) - OpenerStep++; - else if (OpenerStep == 1) actionID = PerfectBalance; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = LeapingOpo; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = DragonKick; - - if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Brotherhood; - - if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = LeapingOpo; - - if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = TheForbiddenChakra; - - if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; - - if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = ElixirBurst; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonKick; - - if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = WindsReply; - - if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = FiresReply; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = LeapingOpo; - - if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) - OpenerStep++; - else if (OpenerStep == 14) actionID = PerfectBalance; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = DragonKick; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LeapingOpo; - - if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = DragonKick; - - if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = ElixirBurst; - - if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 19) actionID = LeapingOpo; - - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; - - if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || - (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || - (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || - (actionID is Brotherhood && IsOnCooldown(Brotherhood))) - && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - Svc.Log.Debug($"Failed at {actionID}"); - CurrentState = OpenerState.FailedOpener; - - return false; - } - - return true; - } - - return false; - } - - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } - - public bool DoFullOpener(ref uint actionID, int selectedOpener) - { - if (!LevelChecked) - return false; - - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; - - if (CurrentState == OpenerState.InOpener) - switch (selectedOpener) - { - case 0 when DoLlOpener(ref actionID): - - case 1 when DoSlOpener(ref actionID): - return true; - } - - if (!InCombat()) - { - ResetOpener(); - CurrentState = OpenerState.PrePull; - } - - return false; - } -} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK/MNK.cs similarity index 94% rename from XIVSlothCombo/Combos/PvE/MNK.cs rename to XIVSlothCombo/Combos/PvE/MNK/MNK.cs index 229539948..caa86886c 100644 --- a/XIVSlothCombo/Combos/PvE/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK/MNK.cs @@ -2,16 +2,14 @@ using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Statuses; -using XIVSlothCombo.Combos.JobHelpers; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; -internal class MNK +internal partial class MNK { public const byte ClassID = 2; public const byte JobID = 20; @@ -73,17 +71,6 @@ public const ushort Brotherhood = 1185; } - public static class Config - { - public static UserInt - MNK_ST_SecondWind_Threshold = new("MNK_ST_SecondWindThreshold", 25), - MNK_ST_Bloodbath_Threshold = new("MNK_ST_BloodbathThreshold", 40), - MNK_AoE_SecondWind_Threshold = new("MNK_AoE_SecondWindThreshold", 25), - MNK_AoE_Bloodbath_Threshold = new("MNK_AoE_BloodbathThreshold", 40), - MNK_SelectedOpener = new("MNK_SelectedOpener"), - MNK_VariantCure = new("MNK_Variant_Cure"); - } - internal class MNK_ST_SimpleMode : CustomCombo { internal static MNKOpenerLogic MNKOpener = new(); @@ -98,6 +85,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; if (actionID is Bootshine or LeapingOpo) { @@ -120,6 +108,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb PlayerHealthPercentageHp() <= Config.MNK_VariantCure) return Variant.VariantCure; + if (ActionReady(RiddleOfFire) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) + return RiddleOfFire; + // OGCDs if (CanWeave(ActionWatching.LastWeaponskill)) { @@ -132,16 +124,13 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (ActionReady(Brotherhood)) return Brotherhood; - if (ActionReady(RiddleOfFire) && - CanDelayedWeave(ActionWatching.LastWeaponskill)) - return RiddleOfFire; - if (ActionReady(RiddleOfWind)) return RiddleOfWind; //Perfect Balance if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) { // Odd window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && @@ -152,8 +141,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Even window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - HasEffect(Buffs.Brotherhood) && - HasEffect(Buffs.RiddleOfFire)) + (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && + (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) return PerfectBalance; // Low level @@ -233,12 +222,12 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb if (HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfFire) || - GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) return WindsReply; // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID, true); + return DetermineCoreAbility(actionID, true); } return actionID; @@ -259,6 +248,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; if (actionID is Bootshine or LeapingOpo) { @@ -313,7 +303,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Perfect Balance if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) { // Odd window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && @@ -324,8 +315,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb // Even window if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - HasEffect(Buffs.Brotherhood) && - HasEffect(Buffs.RiddleOfFire)) + (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && + (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) return PerfectBalance; // Low level @@ -414,17 +405,17 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb GetBuffRemainingTime(Buffs.FiresRumination) < 4)) return FiresReply; - if (IsEnabled(CustomComboPreset.MNK_STUseROW) && + if (IsEnabled(CustomComboPreset.MNK_STUseROW) && IsEnabled(CustomComboPreset.MNK_STUseWindsReply) && HasEffect(Buffs.WindsRumination) && LevelChecked(WindsReply) && - (HasEffect(Buffs.RiddleOfFire) || - GetBuffRemainingTime(Buffs.WindsRumination) < 4)) + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) return WindsReply; } // Standard Beast Chakras - return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); + return DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); } return actionID; @@ -467,7 +458,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionReady(Brotherhood)) return Brotherhood; - + if (ActionReady(RiddleOfWind)) return RiddleOfWind; diff --git a/XIVSlothCombo/Combos/PvE/MNK/MNK_Config.cs b/XIVSlothCombo/Combos/PvE/MNK/MNK_Config.cs new file mode 100644 index 000000000..3da4ca451 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/MNK/MNK_Config.cs @@ -0,0 +1,54 @@ +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class MNK +{ + internal static class Config + { + public static UserInt + MNK_ST_SecondWind_Threshold = new("MNK_ST_SecondWindThreshold", 25), + MNK_ST_Bloodbath_Threshold = new("MNK_ST_BloodbathThreshold", 40), + MNK_AoE_SecondWind_Threshold = new("MNK_AoE_SecondWindThreshold", 25), + MNK_AoE_Bloodbath_Threshold = new("MNK_AoE_BloodbathThreshold", 40), + MNK_SelectedOpener = new("MNK_SelectedOpener"), + MNK_VariantCure = new("MNK_Variant_Cure"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.MNK_ST_ComboHeals: + DrawSliderInt(0, 100, Config.MNK_ST_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)"); + + DrawSliderInt(0, 100, Config.MNK_ST_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)"); + + break; + + case CustomComboPreset.MNK_AoE_ComboHeals: + DrawSliderInt(0, 100, Config.MNK_AoE_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)"); + + DrawSliderInt(0, 100, Config.MNK_AoE_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)"); + + break; + + case CustomComboPreset.MNK_STUseOpener: + DrawHorizontalRadioButton(Config.MNK_SelectedOpener, "Double Lunar", "Uses Lunar/Lunar opener", 0); + + DrawHorizontalRadioButton(Config.MNK_SelectedOpener, "Solar Lunar", "Uses Solar/Lunar opener", 1); + + break; + + case CustomComboPreset.MNK_Variant_Cure: + DrawSliderInt(1, 100, Config.MNK_VariantCure, "HP% to be at or under", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs b/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs new file mode 100644 index 000000000..3d96a4b8c --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs @@ -0,0 +1,389 @@ +using Dalamud.Game.ClientState.JobGauge.Enums; +using ECommons.DalamudServices; +using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Data; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class MNK +{ + private static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) + { + if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) + return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) + ? DragonKick + : OriginalHook(Bootshine); + + if (HasEffect(Buffs.RaptorForm)) + return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) + ? TwinSnakes + : OriginalHook(TrueStrike); + + if (HasEffect(Buffs.CoeurlForm)) + { + if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) + { + if (!OnTargetsRear() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; + + return Demolish; + } + + if (LevelChecked(SnapPunch)) + { + if (!OnTargetsFlank() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; + + return OriginalHook(SnapPunch); + } + } + + return actionId; + } + + internal class MNKOpenerLogic + { + private OpenerState currentState = OpenerState.PrePull; + + public uint OpenerStep; + + public uint PrePullStep; + + private static uint OpenerLevel => 100; + + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState + { + get => currentState; + set + { + if (value != currentState) + { + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + + currentState = value; + } + } + } + + private static bool HasCooldowns() + { + if (GetRemainingCharges(PerfectBalance) < 2) + return false; + + if (!ActionReady(Brotherhood)) + return false; + + if (!ActionReady(RiddleOfFire)) + return false; + + if (!ActionReady(RiddleOfWind)) + return false; + + if (!ActionReady(Meditation) && Gauge.Chakra < 5) + return false; + + if (Gauge.Nadi != Nadi.NONE) + return false; + + if (Gauge.RaptorFury != 0) + return false; + + if (Gauge.CoeurlFury != 0) + return false; + + return true; + } + + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) return false; + + if (CanOpener && PrePullStep == 0) PrePullStep = 1; + + if (!HasCooldowns()) PrePullStep = 0; + + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) + { + if (Gauge.Chakra < 5 && PrePullStep == 1) + { + actionID = ForbiddenMeditation; + + return true; + } + + if (!HasEffect(Buffs.FormlessFist) && + !HasEffect(Buffs.RaptorForm) && PrePullStep == 1) + { + actionID = FormShift; + + return true; + } + + if (WasLastAction(DragonKick) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = DragonKick; + + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; + + return true; + } + PrePullStep = 0; + + return false; + } + + private bool DoSlOpener(ref uint actionID) + { + if (!LevelChecked) + return false; + + if (currentState == OpenerState.InOpener) + { + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + CanWeave(ActionWatching.LastWeaponskill) && + Gauge.Chakra >= 5 && + OpenerStep > 9) + { + actionID = TheForbiddenChakra; + + return true; + } + + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) + OpenerStep++; + else if (OpenerStep == 1) actionID = PerfectBalance; + + if (WasLastWeaponskill(TwinSnakes) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = TwinSnakes; + + if (WasLastWeaponskill(Demolish) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = Demolish; + + if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Brotherhood; + + if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) + actionID = RiddleOfFire; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = LeapingOpo; + + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = TheForbiddenChakra; + + if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) + actionID = RiddleOfWind; + + if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = RisingPhoenix; + + if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonKick; + + if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = WindsReply; + + if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FiresReply; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = LeapingOpo; + + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) + OpenerStep++; + else if (OpenerStep == 14) actionID = PerfectBalance; + + if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = DragonKick; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LeapingOpo; + + if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = DragonKick; + + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = ElixirBurst; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 19) actionID = LeapingOpo; + + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || + (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || + (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || + (actionID is Brotherhood && IsOnCooldown(Brotherhood))) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + Svc.Log.Debug($"Failed at {actionID}"); + CurrentState = OpenerState.FailedOpener; + + return false; + } + + return true; + } + + return false; + } + + private bool DoLlOpener(ref uint actionID) + { + if (!LevelChecked) + return false; + + if (currentState == OpenerState.InOpener) + { + if (IsEnabled(CustomComboPreset.MNK_STUseTheForbiddenChakra) && + CanWeave(ActionWatching.LastWeaponskill) && + Gauge.Chakra >= 5 && + OpenerStep > 9) + { + actionID = TheForbiddenChakra; + + return true; + } + + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 1 && OpenerStep == 1) + OpenerStep++; + else if (OpenerStep == 1) actionID = PerfectBalance; + + if (WasLastAction(LeapingOpo) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = LeapingOpo; + + if (WasLastAction(DragonKick) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = DragonKick; + + if (WasLastAction(Brotherhood) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Brotherhood; + + if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) + actionID = RiddleOfFire; + + if (WasLastAction(LeapingOpo) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = LeapingOpo; + + if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = TheForbiddenChakra; + + if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) + actionID = RiddleOfWind; + + if (WasLastAction(ElixirBurst) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = ElixirBurst; + + if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonKick; + + if (WasLastWeaponskill(WindsReply) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = WindsReply; + + if (WasLastWeaponskill(FiresReply) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FiresReply; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = LeapingOpo; + + if (WasLastAction(PerfectBalance) && GetRemainingCharges(PerfectBalance) is 0 && OpenerStep == 14) + OpenerStep++; + else if (OpenerStep == 14) actionID = PerfectBalance; + + if (WasLastWeaponskill(DragonKick) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = DragonKick; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LeapingOpo; + + if (WasLastWeaponskill(DragonKick) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = DragonKick; + + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = ElixirBurst; + + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 19) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 19) actionID = LeapingOpo; + + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if (((actionID == PerfectBalance && GetRemainingCharges(PerfectBalance) == 0) || + (actionID is RiddleOfFire && IsOnCooldown(RiddleOfFire)) || + (actionID is RiddleOfWind && IsOnCooldown(RiddleOfWind)) || + (actionID is Brotherhood && IsOnCooldown(Brotherhood))) + && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + Svc.Log.Debug($"Failed at {actionID}"); + CurrentState = OpenerState.FailedOpener; + + return false; + } + + return true; + } + + return false; + } + + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } + + public bool DoFullOpener(ref uint actionID, int selectedOpener) + { + if (!LevelChecked) + return false; + + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; + + if (CurrentState == OpenerState.InOpener) + switch (selectedOpener) + { + case 0 when DoLlOpener(ref actionID): + + case 1 when DoSlOpener(ref actionID): + return true; + } + + if (!InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; + } + + return false; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ed77d7c94..3858e7105 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -280,6 +280,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo //case DRK.JobID: DRK.Config.Draw(preset); break; //case GNB.JobID: GNB.Config.Draw(preset); break; //case MCH.JobID: MCH.Config.Draw(preset); break; + case MNK.JobID: MNK.Config.Draw(preset); break; //case NIN.JobID: NIN.Config.Draw(preset); break; //case PCT.JobID: PCT.Config.Draw(preset); break; //case PLD.JobID: PLD.Config.Draw(preset); break; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..41734ed2f 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1580,40 +1580,6 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - - #region MONK - - if (preset == CustomComboPreset.MNK_ST_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_SecondWind_Threshold, - "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - - UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_ST_Bloodbath_Threshold, - "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.MNK_AoE_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_AoE_SecondWind_Threshold, - "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - - UserConfig.DrawSliderInt(0, 100, MNK.Config.MNK_AoE_Bloodbath_Threshold, - "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.MNK_STUseOpener && enabled) - { - UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Double Lunar", - "Uses Lunar/Lunar opener", 0); - - UserConfig.DrawHorizontalRadioButton(MNK.Config.MNK_SelectedOpener, "Solar Lunar", - "Uses Solar/Lunar opener", 1); - } - - if (preset == CustomComboPreset.MNK_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, MNK.Config.MNK_VariantCure, "HP% to be at or under", 200); - - #endregion // ==================================================================================== #region NINJA From 19b9dd0da6b1ab0bcd864b6385d03d906af44842 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 29 Sep 2024 09:56:53 +0100 Subject: [PATCH 146/208] Stuff and things --- XIVSlothCombo/AutoRotation/AutoRotationController.cs | 3 --- XIVSlothCombo/Combos/JobHelpers/NIN.cs | 7 +------ XIVSlothCombo/Data/ActionWatching.cs | 11 +++++++++++ XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index d7a544423..73ded9f4d 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -25,9 +25,6 @@ internal static void Run() if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted] || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) return; - if (ActionManager.Instance()->QueuedActionId != 0) - return; - if (!EzThrottler.Throttle("AutoRotController", 150)) return; diff --git a/XIVSlothCombo/Combos/JobHelpers/NIN.cs b/XIVSlothCombo/Combos/JobHelpers/NIN.cs index 37924c8fd..465c869bb 100644 --- a/XIVSlothCombo/Combos/JobHelpers/NIN.cs +++ b/XIVSlothCombo/Combos/JobHelpers/NIN.cs @@ -26,12 +26,7 @@ private static bool TargetHasMugDebuff() return CustomComboFunctions.TargetHasEffect(Debuffs.Mug) || CustomComboFunctions.TargetHasEffect(Debuffs.Dokumori); } - internal static bool InMudra => GetInMudra(); - - private static bool GetInMudra() - { - return !CustomComboFunctions.IsOriginal(Ninjutsu); - } + internal static bool InMudra = false; } internal class MudraCasting : PvE.NIN diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index cc3d26cc7..f494525f5 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -12,6 +12,7 @@ using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; +using static XIVSlothCombo.Combos.JobHelpers.NIN; namespace XIVSlothCombo.Data { @@ -101,6 +102,8 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp TimeLastActionUsed = DateTime.Now; ActionType = actionType; + UpdateHelpers(actionId); + Svc.Log.Verbose($"{actionId} {sequence} {a5} {a6} {a7} {a8} {a9}"); } catch (Exception ex) @@ -110,6 +113,14 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp } } + private static void UpdateHelpers(uint actionId) + { + if (actionId is NIN.Ten or NIN.Chi or NIN.Jin or NIN.TenCombo or NIN.ChiCombo or NIN.JinCombo) + NINHelper.InMudra = true; + else + NINHelper.InMudra = false; + } + private unsafe static void CheckForChangedTarget(uint actionId, ref ulong targetObjectId) { if (actionId is AST.Balance or AST.Spear && diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 6ef46ae6c..b40ade2a3 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.3 + 0.0.0.4 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From 9a48f5bcb320c53a0e724351cbbff8bba76363a3 Mon Sep 17 00:00:00 2001 From: Mattia Wijns Date: Sun, 29 Sep 2024 19:12:21 +0200 Subject: [PATCH 147/208] refactor DRG / new Layout --- XIVSlothCombo/Combos/JobHelpers/DRG.cs | 270 ------------------ XIVSlothCombo/Combos/PvE/{ => DRG}/DRG.cs | 20 +- XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs | 98 +++++++ XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs | 273 +++++++++++++++++++ XIVSlothCombo/Window/Functions/UserConfig.cs | 44 --- 5 files changed, 372 insertions(+), 333 deletions(-) delete mode 100644 XIVSlothCombo/Combos/JobHelpers/DRG.cs rename XIVSlothCombo/Combos/PvE/{ => DRG}/DRG.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs create mode 100644 XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/DRG.cs b/XIVSlothCombo/Combos/JobHelpers/DRG.cs deleted file mode 100644 index 178b642c3..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/DRG.cs +++ /dev/null @@ -1,270 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using ECommons.DalamudServices; -using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; -using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Data; - -namespace XIVSlothCombo.Combos.JobHelpers; - -internal class DRGOpenerLogic : DRG -{ - private OpenerState currentState = OpenerState.PrePull; - - public uint OpenerStep = 1; - - public uint PrePullStep; - - private static uint OpenerLevel => 100; - - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; - - private static bool CanOpener => HasCooldowns() && LevelChecked; - - public OpenerState CurrentState - { - get => currentState; - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); - if (value == OpenerState.InOpener) OpenerStep = 1; - - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; - } - } - } - - private static bool HasCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2) - return false; - - if (!CustomComboFunctions.ActionReady(BattleLitany)) - return false; - - if (!CustomComboFunctions.ActionReady(DragonfireDive)) - return false; - - if (!CustomComboFunctions.ActionReady(LanceCharge)) - return false; - - return true; - } - - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) return false; - - if (CanOpener && PrePullStep == 0) PrePullStep = 1; - - if (!HasCooldowns()) PrePullStep = 0; - - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (CustomComboFunctions.WasLastAction(TrueThrust) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = TrueThrust; - - if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) - CurrentState = OpenerState.FailedOpener; - - return true; - } - - PrePullStep = 0; - - return false; - } - - private bool DoOpener(ref uint actionID) - { - if (!LevelChecked) return false; - - if (currentState == OpenerState.InOpener) - { - if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = SpiralBlow; - - if (CustomComboFunctions.WasLastAction(LanceCharge) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = LanceCharge; - - if (CustomComboFunctions.WasLastAction(ChaoticSpring) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = ChaoticSpring; - - if (CustomComboFunctions.WasLastAction(BattleLitany) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = BattleLitany; - - if (CustomComboFunctions.WasLastAction(Geirskogul) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Geirskogul; - - if (CustomComboFunctions.WasLastAction(WheelingThrust) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = WheelingThrust; - - if (CustomComboFunctions.WasLastAction(HighJump) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = HighJump; - - if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = LifeSurge; - - if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Drakesbane; - - if (CustomComboFunctions.WasLastAction(DragonfireDive) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = DragonfireDive; - - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Nastrond; - - if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = RaidenThrust; - - if (CustomComboFunctions.WasLastAction(Stardiver) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Stardiver; - - if (CustomComboFunctions.WasLastAction(LanceBarrage) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = LanceBarrage; - - if (CustomComboFunctions.WasLastAction(Starcross) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Starcross; - - if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = LifeSurge; - - if (CustomComboFunctions.WasLastAction(HeavensThrust) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = HeavensThrust; - - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Nastrond; - - if (CustomComboFunctions.WasLastAction(RiseOfTheDragon) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = RiseOfTheDragon; - - if (CustomComboFunctions.WasLastAction(FangAndClaw) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = FangAndClaw; - - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = Nastrond; - - if (CustomComboFunctions.WasLastAction(MirageDive) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = MirageDive; - - if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = Drakesbane; - - if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 24) OpenerStep++; - else if (OpenerStep == 24) actionID = RaidenThrust; - - if (CustomComboFunctions.WasLastAction(WyrmwindThrust) && OpenerStep == 25) OpenerStep++; - else if (OpenerStep == 25) actionID = WyrmwindThrust; - - if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 26) - CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 26) actionID = SpiralBlow; - - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; - - if (((actionID == DragonfireDive && CustomComboFunctions.IsOnCooldown(DragonfireDive)) || - (actionID == BattleLitany && CustomComboFunctions.IsOnCooldown(BattleLitany)) || - (actionID == LanceCharge && CustomComboFunctions.IsOnCooldown(LanceCharge)) || - (actionID == LifeSurge && CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2)) && - ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - - return false; - } - - return true; - } - - return false; - } - - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } - - public bool DoFullOpener(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; - - if (CurrentState == OpenerState.InOpener) - if (DoOpener(ref actionID)) - return true; - - if (!CustomComboFunctions.InCombat()) - { - ResetOpener(); - CurrentState = OpenerState.PrePull; - } - - return false; - } -} - -internal class AnimationLock -{ - internal static readonly List FastLocks = - [ - DRG.BattleLitany, - DRG.LanceCharge, - DRG.LifeSurge, - DRG.Geirskogul, - DRG.Nastrond, - DRG.MirageDive, - DRG.WyrmwindThrust, - DRG.RiseOfTheDragon, - DRG.Starcross, - Variant.VariantRampart, - All.TrueNorth - ]; - - internal static readonly List MidLocks = - [ - DRG.Jump, - DRG.HighJump, - DRG.DragonfireDive - ]; - - internal static uint SlowLock => DRG.Stardiver; - - internal static bool CanDRGWeave(uint oGCD) - { - //GCD Ready - No Weave - if (CustomComboFunctions.IsOffCooldown(DRG.TrueThrust)) - return false; - - float gcdTimer = CustomComboFunctions.GetCooldownRemainingTime(DRG.TrueThrust); - - if (FastLocks.Any(x => x == oGCD) && gcdTimer >= 0.6f) - return true; - - if (MidLocks.Any(x => x == oGCD) && gcdTimer >= 0.8f) - return true; - - if (SlowLock == oGCD && gcdTimer >= 1.5f) - return true; - - return false; - } -} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/DRG.cs rename to XIVSlothCombo/Combos/PvE/DRG/DRG.cs index 503e4e005..b873c97b6 100644 --- a/XIVSlothCombo/Combos/PvE/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG.cs @@ -1,15 +1,13 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Statuses; -using XIVSlothCombo.Combos.JobHelpers; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Extensions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; -internal class DRG +internal partial class DRG { public const byte ClassID = 4; public const byte JobID = 22; @@ -79,22 +77,6 @@ public const uint EnhancedLifeSurge = 438; } - public static class Config - { - public static UserInt - DRG_Variant_Cure = new("DRG_VariantCure"), - DRG_ST_LitanyHP = new("DRG_ST_LitanyHP", 2), - DRG_ST_SightHP = new("DRG_ST_SightHP", 2), - DRG_ST_LanceChargeHP = new("DRG_ST_LanceChargeHP", 2), - DRG_ST_SecondWind_Threshold = new("DRG_STSecondWindThreshold", 25), - DRG_ST_Bloodbath_Threshold = new("DRG_STBloodbathThreshold", 40), - DRG_AoE_LitanyHP = new("DRG_AoE_LitanyHP", 5), - DRG_AoE_SightHP = new("DRG_AoE_SightHP", 5), - DRG_AoE_LanceChargeHP = new("DRG_AoE_LanceChargeHP", 5), - DRG_AoE_SecondWind_Threshold = new("DRG_AoE_SecondWindThreshold", 25), - DRG_AoE_Bloodbath_Threshold = new("DRG_AoE_BloodbathThreshold", 40); - } - internal class DRG_ST_SimpleMode : CustomCombo { internal static DRGOpenerLogic DRGOpener = new(); diff --git a/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs new file mode 100644 index 000000000..e522e757d --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs @@ -0,0 +1,98 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class DRG +{ + internal static class Config + { + public static UserInt + DRG_Variant_Cure = new("DRG_VariantCure"), + DRG_ST_LitanyHP = new("DRG_ST_LitanyHP", 2), + DRG_ST_SightHP = new("DRG_ST_SightHP", 2), + DRG_ST_LanceChargeHP = new("DRG_ST_LanceChargeHP", 2), + DRG_ST_SecondWind_Threshold = new("DRG_STSecondWindThreshold", 25), + DRG_ST_Bloodbath_Threshold = new("DRG_STBloodbathThreshold", 40), + DRG_AoE_LitanyHP = new("DRG_AoE_LitanyHP", 5), + DRG_AoE_SightHP = new("DRG_AoE_SightHP", 5), + DRG_AoE_LanceChargeHP = new("DRG_AoE_LanceChargeHP", 5), + DRG_AoE_SecondWind_Threshold = new("DRG_AoE_SecondWindThreshold", 25), + DRG_AoE_Bloodbath_Threshold = new("DRG_AoE_BloodbathThreshold", 40); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.DRG_ST_ComboHeals: + DrawSliderInt(0, 100, DRG_ST_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)"); + + DrawSliderInt(0, 100, DRG_ST_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)"); + + break; + + case CustomComboPreset.DRG_AoE_ComboHeals: + DrawSliderInt(0, 100, DRG_AoE_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)"); + + DrawSliderInt(0, 100, DRG_AoE_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)"); + + break; + + case CustomComboPreset.DRG_Variant_Cure: + DrawSliderInt(1, 100, DRG_Variant_Cure, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.DRG_ST_Litany: + DrawSliderInt(0, 100, DRG_ST_LitanyHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + + case CustomComboPreset.DRG_ST_Lance: + DrawSliderInt(0, 100, DRG_ST_LanceChargeHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + + case CustomComboPreset.DRG_AoE_Litany: + DrawSliderInt(0, 100, DRG_AoE_LitanyHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + + case CustomComboPreset.DRG_AoE_Lance: + DrawSliderInt(0, 100, DRG_AoE_LanceChargeHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + + case CustomComboPreset.DRGPvP_Nastrond: + DrawSliderInt(0, 100, DRGPvP.Config.DRGPvP_LOTD_HPValue, + "Ends Life of the Dragon if HP falls below the set percentage"); + + DrawSliderInt(2, 8, DRGPvP.Config.DRGPvP_LOTD_Duration, + "Seconds remaining of Life of the Dragon buff before using Nastrond if you are still above the set HP percentage."); + + break; + + case CustomComboPreset.DRGPvP_ChaoticSpringSustain: + DrawSliderInt(0, 101, DRGPvP.Config.DRGPvP_CS_HP_Threshold, + "Chaos Spring HP percentage threshold"); + + break; + + case CustomComboPreset.DRGPvP_WyrmwindThrust: + DrawSliderInt(0, 20, DRGPvP.Config.DRGPvP_Distance_Threshold, + "Distance Treshold for Wyrmwind Thrust"); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs new file mode 100644 index 000000000..9c6916f4d --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs @@ -0,0 +1,273 @@ +using System.Collections.Generic; +using System.Linq; +using ECommons.DalamudServices; +using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Combos.PvE.Content; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Data; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class DRG +{ + internal class DRGOpenerLogic + { + private OpenerState currentState = OpenerState.PrePull; + + public uint OpenerStep = 1; + + public uint PrePullStep; + + private static uint OpenerLevel => 100; + + public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState + { + get => currentState; + set + { + if (value != currentState) + { + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + + currentState = value; + } + } + } + + private static bool HasCooldowns() + { + if (CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2) + return false; + + if (!CustomComboFunctions.ActionReady(BattleLitany)) + return false; + + if (!CustomComboFunctions.ActionReady(DragonfireDive)) + return false; + + if (!CustomComboFunctions.ActionReady(LanceCharge)) + return false; + + return true; + } + + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) return false; + + if (CanOpener && PrePullStep == 0) PrePullStep = 1; + + if (!HasCooldowns()) PrePullStep = 0; + + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) + { + if (CustomComboFunctions.WasLastAction(TrueThrust) && PrePullStep == 1) + CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = TrueThrust; + + if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) + CurrentState = OpenerState.FailedOpener; + + return true; + } + + PrePullStep = 0; + + return false; + } + + private bool DoOpener(ref uint actionID) + { + if (!LevelChecked) return false; + + if (currentState == OpenerState.InOpener) + { + if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = SpiralBlow; + + if (CustomComboFunctions.WasLastAction(LanceCharge) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = LanceCharge; + + if (CustomComboFunctions.WasLastAction(ChaoticSpring) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = ChaoticSpring; + + if (CustomComboFunctions.WasLastAction(BattleLitany) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = BattleLitany; + + if (CustomComboFunctions.WasLastAction(Geirskogul) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = Geirskogul; + + if (CustomComboFunctions.WasLastAction(WheelingThrust) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = WheelingThrust; + + if (CustomComboFunctions.WasLastAction(HighJump) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = HighJump; + + if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = LifeSurge; + + if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = Drakesbane; + + if (CustomComboFunctions.WasLastAction(DragonfireDive) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = DragonfireDive; + + if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = Nastrond; + + if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = RaidenThrust; + + if (CustomComboFunctions.WasLastAction(Stardiver) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = Stardiver; + + if (CustomComboFunctions.WasLastAction(LanceBarrage) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = LanceBarrage; + + if (CustomComboFunctions.WasLastAction(Starcross) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = Starcross; + + if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = LifeSurge; + + if (CustomComboFunctions.WasLastAction(HeavensThrust) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = HeavensThrust; + + if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = Nastrond; + + if (CustomComboFunctions.WasLastAction(RiseOfTheDragon) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = RiseOfTheDragon; + + if (CustomComboFunctions.WasLastAction(FangAndClaw) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = FangAndClaw; + + if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = Nastrond; + + if (CustomComboFunctions.WasLastAction(MirageDive) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = MirageDive; + + if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 23) OpenerStep++; + else if (OpenerStep == 23) actionID = Drakesbane; + + if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 24) OpenerStep++; + else if (OpenerStep == 24) actionID = RaidenThrust; + + if (CustomComboFunctions.WasLastAction(WyrmwindThrust) && OpenerStep == 25) OpenerStep++; + else if (OpenerStep == 25) actionID = WyrmwindThrust; + + if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 26) + CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 26) actionID = SpiralBlow; + + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if (((actionID == DragonfireDive && CustomComboFunctions.IsOnCooldown(DragonfireDive)) || + (actionID == BattleLitany && CustomComboFunctions.IsOnCooldown(BattleLitany)) || + (actionID == LanceCharge && CustomComboFunctions.IsOnCooldown(LanceCharge)) || + (actionID == LifeSurge && CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2)) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + CurrentState = OpenerState.FailedOpener; + + return false; + } + + return true; + } + + return false; + } + + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } + + public bool DoFullOpener(ref uint actionID) + { + if (!LevelChecked) + return false; + + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; + + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID)) + return true; + + if (!CustomComboFunctions.InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; + } + + return false; + } + } + + internal class AnimationLock + { + internal static readonly List FastLocks = + [ + BattleLitany, + LanceCharge, + LifeSurge, + Geirskogul, + Nastrond, + MirageDive, + WyrmwindThrust, + RiseOfTheDragon, + Starcross, + Variant.VariantRampart, + All.TrueNorth + ]; + + internal static readonly List MidLocks = + [ + Jump, + HighJump, + DragonfireDive + ]; + + internal static uint SlowLock => Stardiver; + + internal static bool CanDRGWeave(uint oGCD) + { + //GCD Ready - No Weave + if (CustomComboFunctions.IsOffCooldown(TrueThrust)) + return false; + + float gcdTimer = CustomComboFunctions.GetCooldownRemainingTime(TrueThrust); + + if (FastLocks.Any(x => x == oGCD) && gcdTimer >= 0.6f) + return true; + + if (MidLocks.Any(x => x == oGCD) && gcdTimer >= 0.8f) + return true; + + if (SlowLock == oGCD && gcdTimer >= 1.5f) + return true; + + return false; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..cdf945b1a 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1473,50 +1473,6 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region DRAGOON - if (preset == CustomComboPreset.DRG_ST_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_ST_SecondWind_Threshold, "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_ST_Bloodbath_Threshold, "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.DRG_AoE_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_AoE_SecondWind_Threshold, "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_AoE_Bloodbath_Threshold, "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.DRG_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, DRG.Config.DRG_Variant_Cure, "HP% to be at or under", 200); - - if (preset == CustomComboPreset.DRG_ST_Litany) - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_ST_LitanyHP, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); - - if (preset == CustomComboPreset.DRG_ST_Lance) - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_ST_LanceChargeHP, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); - - if (preset == CustomComboPreset.DRG_AoE_Litany) - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_AoE_LitanyHP, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); - - if (preset == CustomComboPreset.DRG_AoE_Lance) - UserConfig.DrawSliderInt(0, 100, DRG.Config.DRG_AoE_LanceChargeHP, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); - - - #region Dragoon PvP - if (preset is CustomComboPreset.DRGPvP_Nastrond) - UserConfig.DrawSliderInt(0, 100, DRGPvP.Config.DRGPvP_LOTD_HPValue, "Ends Life of the Dragon if HP falls below the set percentage", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.DRGPvP_Nastrond) - UserConfig.DrawSliderInt(2, 8, DRGPvP.Config.DRGPvP_LOTD_Duration, "Seconds remaining of Life of the Dragon buff before using Nastrond if you are still above the set HP percentage.", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.DRGPvP_ChaoticSpringSustain) - UserConfig.DrawSliderInt(0, 101, DRGPvP.Config.DRGPvP_CS_HP_Threshold, "Chaos Spring HP percentage threshold", 150, SliderIncrements.Ones); - - if (preset is CustomComboPreset.DRGPvP_WyrmwindThrust) - UserConfig.DrawSliderInt(0, 20, DRGPvP.Config.DRGPvP_Distance_Threshold, "Distance Treshold for Wyrmwind Thrust", 150, SliderIncrements.Ones); - #endregion - - #endregion // ==================================================================================== #region GUNBREAKER From 43e6eaf25c69a8c85c8c5a0df42cc3d864071414 Mon Sep 17 00:00:00 2001 From: Mattia Wijns Date: Sun, 29 Sep 2024 19:19:33 +0200 Subject: [PATCH 148/208] Refactor + New Layout --- XIVSlothCombo/Combos/PvE/{ => MCH}/MCH.cs | 25 +--- XIVSlothCombo/Combos/PvE/MCH/MCH_Config.cs | 120 ++++++++++++++++++ .../MCH.cs => PvE/MCH/MCH_Helper.cs} | 7 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 50 -------- 4 files changed, 124 insertions(+), 78 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => MCH}/MCH.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/MCH/MCH_Config.cs rename XIVSlothCombo/Combos/{JobHelpers/MCH.cs => PvE/MCH/MCH_Helper.cs} (98%) diff --git a/XIVSlothCombo/Combos/PvE/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/MCH.cs rename to XIVSlothCombo/Combos/PvE/MCH/MCH.cs index 6582ab9e7..f153c1e4b 100644 --- a/XIVSlothCombo/Combos/PvE/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs @@ -3,15 +3,13 @@ using ECommons.DalamudServices; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; -using static XIVSlothCombo.Combos.JobHelpers.MCHHelpers; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; -internal class MCH +internal partial class MCH { public const byte JobID = 31; @@ -78,27 +76,6 @@ public const ushort EnhancedMultiWeapon = 605; } - public static class Config - { - public static UserInt - MCH_ST_SecondWindThreshold = new("MCH_ST_SecondWindThreshold", 25), - MCH_AoE_SecondWindThreshold = new("MCH_AoE_SecondWindThreshold", 25), - MCH_VariantCure = new("MCH_VariantCure"), - MCH_AoE_TurretUsage = new("MCH_AoE_TurretUsage"), - MCH_ST_ReassemblePool = new("MCH_ST_ReassemblePool", 0), - MCH_AoE_ReassemblePool = new("MCH_AoE_ReassemblePool", 0), - MCH_ST_WildfireHP = new("MCH_ST_WildfireHP", 1), - MCH_ST_HyperchargeHP = new("MCH_ST_HyperchargeHP", 1), - MCH_ST_QueenOverDrive = new("MCH_ST_QueenOverDrive"); - - public static UserBoolArray - MCH_ST_Reassembled = new("MCH_ST_Reassembled"), - MCH_AoE_Reassembled = new("MCH_AoE_Reassembled"); - - public static UserBool - MCH_AoE_Hypercharge = new("MCH_AoE_Hypercharge"); - } - internal class MCH_ST_SimpleMode : CustomCombo { internal static MCHOpenerLogic MCHOpener = new(); diff --git a/XIVSlothCombo/Combos/PvE/MCH/MCH_Config.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH_Config.cs new file mode 100644 index 000000000..39736d3fb --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH_Config.cs @@ -0,0 +1,120 @@ +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Data; +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class MCH +{ + internal static class Config + { + public static UserInt + MCH_ST_SecondWindThreshold = new("MCH_ST_SecondWindThreshold", 25), + MCH_AoE_SecondWindThreshold = new("MCH_AoE_SecondWindThreshold", 25), + MCH_VariantCure = new("MCH_VariantCure"), + MCH_AoE_TurretUsage = new("MCH_AoE_TurretUsage"), + MCH_ST_ReassemblePool = new("MCH_ST_ReassemblePool", 0), + MCH_AoE_ReassemblePool = new("MCH_AoE_ReassemblePool", 0), + MCH_ST_WildfireHP = new("MCH_ST_WildfireHP", 1), + MCH_ST_HyperchargeHP = new("MCH_ST_HyperchargeHP", 1), + MCH_ST_QueenOverDrive = new("MCH_ST_QueenOverDrive"); + + public static UserBoolArray + MCH_ST_Reassembled = new("MCH_ST_Reassembled"), + MCH_AoE_Reassembled = new("MCH_AoE_Reassembled"); + + public static UserBool + MCH_AoE_Hypercharge = new("MCH_AoE_Hypercharge"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.MCH_ST_Adv_Reassemble: + + DrawSliderInt(0, 1, MCH_ST_ReassemblePool, "Number of Charges to Save for Manual Use"); + + DrawHorizontalMultiChoice(MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(Excavator)}", + "", 5, 0); + + DrawHorizontalMultiChoice(MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(Chainsaw)}", + "", 5, 1); + + DrawHorizontalMultiChoice(MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(AirAnchor)}", + "", 5, 2); + + DrawHorizontalMultiChoice(MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(Drill)}", "", + 5, 3); + + DrawHorizontalMultiChoice(MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(CleanShot)}", + "", 5, 4); + + break; + + case CustomComboPreset.MCH_AoE_Adv_Reassemble: + + DrawSliderInt(0, 1, MCH_AoE_ReassemblePool, "Number of Charges to Save for Manual Use"); + + DrawHorizontalMultiChoice(MCH_AoE_Reassembled, + $"Use on {ActionWatching.GetActionName(SpreadShot)}/{ActionWatching.GetActionName(Scattergun)}", + "", 4, 0); + + DrawHorizontalMultiChoice(MCH_AoE_Reassembled, + $"Use on {ActionWatching.GetActionName(AutoCrossbow)}", "", 4, 1); + + DrawHorizontalMultiChoice(MCH_AoE_Reassembled, $"Use on {ActionWatching.GetActionName(Chainsaw)}", + "", 4, 2); + + DrawHorizontalMultiChoice(MCH_AoE_Reassembled, $"Use on {ActionWatching.GetActionName(Excavator)}", + "", 4, 3); + + break; + + case CustomComboPreset.MCH_ST_Adv_SecondWind: + DrawSliderInt(0, 100, MCH_ST_SecondWindThreshold, + $"{ActionWatching.GetActionName(All.SecondWind)} HP percentage threshold"); + + break; + + case CustomComboPreset.MCH_AoE_Adv_SecondWind: + DrawSliderInt(0, 100, MCH_AoE_SecondWindThreshold, + $"{ActionWatching.GetActionName(All.SecondWind)} HP percentage threshold"); + + break; + + case CustomComboPreset.MCH_AoE_Adv_Queen: + DrawSliderInt(50, 100, MCH_AoE_TurretUsage, "Battery threshold", sliderIncrement: 5); + + break; + + case CustomComboPreset.MCH_AoE_Adv_GaussRicochet: + DrawAdditionalBoolChoice(MCH_AoE_Hypercharge, + $"Use Outwith {ActionWatching.GetActionName(Hypercharge)}", ""); + + break; + + case CustomComboPreset.MCH_Variant_Cure: + DrawSliderInt(1, 100, MCH_VariantCure, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.MCH_ST_Adv_QueenOverdrive: + DrawSliderInt(1, 10, MCH_ST_QueenOverDrive, "HP% for the target to be at or under"); + + break; + + case CustomComboPreset.MCH_ST_Adv_WildFire: + DrawSliderInt(0, 15, MCH_ST_WildfireHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + + case CustomComboPreset.MCH_ST_Adv_Hypercharge: + DrawSliderInt(0, 15, MCH_ST_HyperchargeHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/JobHelpers/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs similarity index 98% rename from XIVSlothCombo/Combos/JobHelpers/MCH.cs rename to XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs index 1fd7cea3d..0217a4ba0 100644 --- a/XIVSlothCombo/Combos/JobHelpers/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs @@ -4,12 +4,11 @@ using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Data; -using static XIVSlothCombo.Combos.PvE.MCH; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers; +namespace XIVSlothCombo.Combos.PvE; -internal abstract class MCHHelpers +internal partial class MCH { internal class MCHOpenerLogic { @@ -254,7 +253,7 @@ public bool DoFullOpener(ref uint actionID) } } - internal static class MCHExtensions + internal class MCHExtensions { public static unsafe bool IsComboExpiring(float Times) { diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..4b20a6488 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1529,56 +1529,6 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region MACHINIST - - if (preset == CustomComboPreset.MCH_ST_Adv_Reassemble) - UserConfig.DrawSliderInt(0, 1, MCH.Config.MCH_ST_ReassemblePool, "Number of Charges to Save for Manual Use"); - - if (preset == CustomComboPreset.MCH_AoE_Adv_Reassemble) - UserConfig.DrawSliderInt(0, 1, MCH.Config.MCH_AoE_ReassemblePool, "Number of Charges to Save for Manual Use"); - - if (preset is CustomComboPreset.MCH_ST_Adv_Reassemble) - { - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.Excavator)}", "", 5, 0); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.Chainsaw)}", "", 5, 1); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.AirAnchor)}", "", 5, 2); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.Drill)}", "", 5, 3); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_ST_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.CleanShot)}", "", 5, 4); - } - - if (preset is CustomComboPreset.MCH_AoE_Adv_Reassemble) - { - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_AoE_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.SpreadShot)}/{ActionWatching.GetActionName(MCH.Scattergun)}", "", 4, 0); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_AoE_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.AutoCrossbow)}", "", 4, 1); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_AoE_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.Chainsaw)}", "", 4, 2); - UserConfig.DrawHorizontalMultiChoice(MCH.Config.MCH_AoE_Reassembled, $"Use on {ActionWatching.GetActionName(MCH.Excavator)}", "", 4, 3); - } - - if (preset == CustomComboPreset.MCH_ST_Adv_SecondWind) - UserConfig.DrawSliderInt(0, 100, MCH.Config.MCH_ST_SecondWindThreshold, $"{ActionWatching.GetActionName(All.SecondWind)} HP percentage threshold", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.MCH_AoE_Adv_SecondWind) - UserConfig.DrawSliderInt(0, 100, MCH.Config.MCH_AoE_SecondWindThreshold, $"{ActionWatching.GetActionName(All.SecondWind)} HP percentage threshold", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.MCH_AoE_Adv_Queen) - UserConfig.DrawSliderInt(50, 100, MCH.Config.MCH_AoE_TurretUsage, "Battery threshold", sliderIncrement: 5); - - if (preset == CustomComboPreset.MCH_AoE_Adv_GaussRicochet) - UserConfig.DrawAdditionalBoolChoice(MCH.Config.MCH_AoE_Hypercharge, $"Use Outwith {ActionWatching.GetActionName(MCH.Hypercharge)}", ""); - - if (preset == CustomComboPreset.MCH_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, MCH.Config.MCH_VariantCure, "HP% to be at or under", 200); - - if (preset == CustomComboPreset.MCH_ST_Adv_QueenOverdrive) - UserConfig.DrawSliderInt(1, 10, MCH.Config.MCH_ST_QueenOverDrive, "HP% for the target to be at or under"); - - if (preset == CustomComboPreset.MCH_ST_Adv_WildFire) - UserConfig.DrawSliderInt(0, 15, MCH.Config.MCH_ST_WildfireHP, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); - - if (preset == CustomComboPreset.MCH_ST_Adv_Hypercharge) - UserConfig.DrawSliderInt(0, 15, MCH.Config.MCH_ST_HyperchargeHP, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); - - #endregion // ==================================================================================== #region MONK From edcf58cee2421f87f13102459c08c695328391d2 Mon Sep 17 00:00:00 2001 From: Mattia Wijns Date: Sun, 29 Sep 2024 19:33:44 +0200 Subject: [PATCH 149/208] reformat --- XIVSlothCombo/Combos/PvE/{ => RPR}/RPR.cs | 30 +---- XIVSlothCombo/Combos/PvE/RPR/RPR_Config.cs | 119 ++++++++++++++++++ .../RPR.cs => PvE/RPR/RPR_Helper.cs} | 5 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 56 --------- 4 files changed, 124 insertions(+), 86 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => RPR}/RPR.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/RPR/RPR_Config.cs rename XIVSlothCombo/Combos/{JobHelpers/RPR.cs => PvE/RPR/RPR_Helper.cs} (99%) diff --git a/XIVSlothCombo/Combos/PvE/RPR.cs b/XIVSlothCombo/Combos/PvE/RPR/RPR.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/RPR.cs rename to XIVSlothCombo/Combos/PvE/RPR/RPR.cs index 398995a5a..94d2da811 100644 --- a/XIVSlothCombo/Combos/PvE/RPR.cs +++ b/XIVSlothCombo/Combos/PvE/RPR/RPR.cs @@ -2,14 +2,12 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; -using static XIVSlothCombo.Combos.JobHelpers.RPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; -internal class RPR +internal partial class RPR { public const byte JobID = 39; @@ -95,26 +93,6 @@ public const ushort DeathsDesign = 2586; } - public static class Config - { - public static UserInt - RPR_SoDThreshold = new("RPRSoDThreshold", 0), - RPR_WoDThreshold = new("RPRWoDThreshold", 1), - RPR_SoDRefreshRange = new("RPRSoDRefreshRange", 6), - RPR_Positional = new("RPR_Positional", 0), - RPR_VariantCure = new("RPRVariantCure"), - RPR_STSecondWindThreshold = new("RPR_STSecondWindThreshold", 25), - RPR_STBloodbathThreshold = new("RPR_STBloodbathThreshold", 40), - RPR_AoESecondWindThreshold = new("RPR_AoESecondWindThreshold", 25), - RPR_AoEBloodbathThreshold = new("RPR_AoEBloodbathThreshold", 40); - - public static UserBoolArray - RPR_SoulsowOptions = new("RPR_SoulsowOptions"); - - public static UserBool - RPR_ST_TrueNorth_Moving = new("RPR_ST_TrueNorth_Moving"); - } - internal class RPR_ST_SimpleMode : CustomCombo { internal static RPROpenerLogic RPROpener = new(); @@ -172,10 +150,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Gluttony if (!JustUsed(Perfectio) && ActionReady(Gluttony)) { - if (trueNorthReady) - return All.TrueNorth; - - return Gluttony; + return trueNorthReady ? All.TrueNorth : Gluttony; } //Bloodstalk @@ -313,6 +288,7 @@ internal class RPR_ST_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { double enemyHP = GetTargetHPPercent(); + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); bool trueNorthDynReady = trueNorthReady; diff --git a/XIVSlothCombo/Combos/PvE/RPR/RPR_Config.cs b/XIVSlothCombo/Combos/PvE/RPR/RPR_Config.cs new file mode 100644 index 000000000..b2a1c5466 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/RPR/RPR_Config.cs @@ -0,0 +1,119 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class RPR +{ + internal static class Config + { + public static UserInt + RPR_SoDThreshold = new("RPRSoDThreshold", 0), + RPR_WoDThreshold = new("RPRWoDThreshold", 1), + RPR_SoDRefreshRange = new("RPRSoDRefreshRange", 6), + RPR_Positional = new("RPR_Positional", 0), + RPR_VariantCure = new("RPRVariantCure"), + RPR_STSecondWindThreshold = new("RPR_STSecondWindThreshold", 25), + RPR_STBloodbathThreshold = new("RPR_STBloodbathThreshold", 40), + RPR_AoESecondWindThreshold = new("RPR_AoESecondWindThreshold", 25), + RPR_AoEBloodbathThreshold = new("RPR_AoEBloodbathThreshold", 40); + + public static UserBoolArray + RPR_SoulsowOptions = new("RPR_SoulsowOptions"); + + public static UserBool + RPR_ST_TrueNorth_Moving = new("RPR_ST_TrueNorth_Moving"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.RPRPvP_Burst_ImmortalPooling: + DrawSliderInt(0, 8, RPRPvP.Config.RPRPvP_ImmortalStackThreshold, + "Set a value of Immortal Sacrifice Stacks to hold for burst."); + + DrawSliderInt(0, 8, RPRPvP.Config.RPRPvP_ImmortalStackThreshold, + "Set a value of Immortal Sacrifice Stacks to hold for burst."); + + break; + + case CustomComboPreset.RPRPvP_Burst_ArcaneCircle: + DrawSliderInt(5, 90, RPRPvP.Config.RPRPvP_ArcaneCircleThreshold, + "Set a HP percentage value. Caps at 90 to prevent waste."); + + DrawSliderInt(5, 90, RPRPvP.Config.RPRPvP_ArcaneCircleThreshold, + "Set a HP percentage value. Caps at 90 to prevent waste."); + + break; + + case CustomComboPreset.RPR_ST_AdvancedMode: + DrawHorizontalRadioButton(RPR_Positional, "Rear First", + "First positional: Gallows.", 0); + + DrawHorizontalRadioButton(RPR_Positional, "Flank First", + "First positional: Gibbet.", 1); + + break; + + case CustomComboPreset.RPR_ST_SoD: + DrawSliderInt(4, 8, RPR_SoDRefreshRange, + "Seconds remaining before refreshing Death's Design."); + + DrawSliderInt(0, 5, RPR_SoDThreshold, + "Set a HP% Threshold for when SoD will not be automatically applied to the target."); + + break; + + case CustomComboPreset.RPR_AoE_WoD: + DrawSliderInt(0, 5, RPR_WoDThreshold, + "Set a HP% Threshold for when WoD will not be automatically applied to the target."); + + break; + + case CustomComboPreset.RPR_ST_ComboHeals: + DrawSliderInt(0, 100, RPR_STSecondWindThreshold, + "HP percent threshold to use Second Wind below (0 = Disabled)"); + + DrawSliderInt(0, 100, RPR_STBloodbathThreshold, + "HP percent threshold to use Bloodbath (0 = Disabled)"); + + break; + + case CustomComboPreset.RPR_AoE_ComboHeals: + DrawSliderInt(0, 100, RPR_AoESecondWindThreshold, + "HP percent threshold to use Second Wind below (0 = Disabled)"); + + DrawSliderInt(0, 100, RPR_AoEBloodbathThreshold, + "HP percent threshold to use Bloodbath below (0 = Disabled)"); + + break; + + case CustomComboPreset.RPR_Soulsow: + DrawHorizontalMultiChoice(RPR_SoulsowOptions, "Harpe", + "Adds Soulsow to Harpe.", + 5, 0); + + DrawHorizontalMultiChoice(RPR_SoulsowOptions, "Slice", + "Adds Soulsow to Slice.", + 5, 1); + + DrawHorizontalMultiChoice(RPR_SoulsowOptions, "Spinning Scythe", + "Adds Soulsow to Spinning Scythe", 5, 2); + + DrawHorizontalMultiChoice(RPR_SoulsowOptions, "Shadow of Death", + "Adds Soulsow to Shadow of Death.", 5, 3); + + DrawHorizontalMultiChoice(RPR_SoulsowOptions, "Blood Stalk", + "Adds Soulsow to Blood Stalk.", 5, 4); + + break; + + case CustomComboPreset.RPR_Variant_Cure: + DrawSliderInt(1, 100, RPR_VariantCure, "HP% to be at or under", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/JobHelpers/RPR.cs b/XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs similarity index 99% rename from XIVSlothCombo/Combos/JobHelpers/RPR.cs rename to XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs index 578e93a76..89ceb000b 100644 --- a/XIVSlothCombo/Combos/JobHelpers/RPR.cs +++ b/XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs @@ -3,12 +3,11 @@ using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Data; -using static XIVSlothCombo.Combos.PvE.RPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers; +namespace XIVSlothCombo.Combos.PvE; -internal abstract class RPR +internal partial class RPR { internal class RPROpenerLogic { diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..bb6cc25c8 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1804,63 +1804,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region REAPER - if (preset == CustomComboPreset.RPRPvP_Burst_ImmortalPooling && enabled) - UserConfig.DrawSliderInt(0, 8, RPRPvP.Config.RPRPvP_ImmortalStackThreshold, "Set a value of Immortal Sacrifice Stacks to hold for burst.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.RPRPvP_Burst_ArcaneCircle && enabled) - UserConfig.DrawSliderInt(5, 90, RPRPvP.Config.RPRPvP_ArcaneCircleThreshold, "Set a HP percentage value. Caps at 90 to prevent waste.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.RPR_ST_AdvancedMode && enabled) - { - UserConfig.DrawHorizontalRadioButton(RPR.Config.RPR_Positional, "Rear First", "First positional: Gallows.", 0); - UserConfig.DrawHorizontalRadioButton(RPR.Config.RPR_Positional, "Flank First", "First positional: Gibbet.", 1); - } - - if (preset == CustomComboPreset.RPRPvP_Burst_ImmortalPooling && enabled) - UserConfig.DrawSliderInt(0, 8, RPRPvP.Config.RPRPvP_ImmortalStackThreshold, "Set a value of Immortal Sacrifice Stacks to hold for burst.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.RPRPvP_Burst_ArcaneCircle && enabled) - UserConfig.DrawSliderInt(5, 90, RPRPvP.Config.RPRPvP_ArcaneCircleThreshold, "Set a HP percentage value. Caps at 90 to prevent waste.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.RPR_ST_SoD && enabled) - { - UserConfig.DrawSliderInt(4, 8, RPR.Config.RPR_SoDRefreshRange, "Seconds remaining before refreshing Death's Design.", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 5, RPR.Config.RPR_SoDThreshold, "Set a HP% Threshold for when SoD will not be automatically applied to the target.", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.RPR_AoE_WoD && enabled) - { - UserConfig.DrawSliderInt(0, 5, RPR.Config.RPR_WoDThreshold, "Set a HP% Threshold for when WoD will not be automatically applied to the target.", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.RPR_ST_ComboHeals && enabled) - { - UserConfig.DrawSliderInt(0, 100, RPR.Config.RPR_STSecondWindThreshold, "HP percent threshold to use Second Wind below (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, RPR.Config.RPR_STBloodbathThreshold, "HP percent threshold to use Bloodbath (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.RPR_AoE_ComboHeals && enabled) - { - UserConfig.DrawSliderInt(0, 100, RPR.Config.RPR_AoESecondWindThreshold, "HP percent threshold to use Second Wind below (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, RPR.Config.RPR_AoEBloodbathThreshold, "HP percent threshold to use Bloodbath below (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.RPR_Soulsow && enabled) - { - UserConfig.DrawHorizontalMultiChoice(RPR.Config.RPR_SoulsowOptions, "Harpe", "Adds Soulsow to Harpe.", 5, 0); - UserConfig.DrawHorizontalMultiChoice(RPR.Config.RPR_SoulsowOptions, "Slice", "Adds Soulsow to Slice.", 5, 1); - UserConfig.DrawHorizontalMultiChoice(RPR.Config.RPR_SoulsowOptions, "Spinning Scythe", "Adds Soulsow to Spinning Scythe", 5, 2); - UserConfig.DrawHorizontalMultiChoice(RPR.Config.RPR_SoulsowOptions, "Shadow of Death", "Adds Soulsow to Shadow of Death.", 5, 3); - UserConfig.DrawHorizontalMultiChoice(RPR.Config.RPR_SoulsowOptions, "Blood Stalk", "Adds Soulsow to Blood Stalk.", 5, 4); - } - - if (preset == CustomComboPreset.RPR_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, RPR.Config.RPR_VariantCure, "HP% to be at or under", 200); - - - #endregion // ==================================================================================== #region RED MAGE From 510d80c6cc33643fd4ccd309a0793b58eb9bed48 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 29 Sep 2024 18:40:38 +0100 Subject: [PATCH 150/208] Pruned `LocalPlayer.TargetObject` checks --- .../AutoRotation/AutoRotationController.cs | 2 ++ XIVSlothCombo/CustomCombo/Functions/Target.cs | 2 +- XIVSlothCombo/Data/ActionWatching.cs | 2 +- XIVSlothCombo/Window/Tabs/Debug.cs | 14 ++++++++------ XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index ebe2cb3b7..acfbe62f9 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -24,6 +24,8 @@ internal static void Run() if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted] || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) return; + if (Player.Object.CurrentCastTime > 0) return; + if (!EzThrottler.Throttle("AutoRotController", 150)) return; diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 1c30f5853..51161676a 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -50,7 +50,7 @@ public static float GetTargetDistance(IGameObject? optionalTarget = null, IGameO /// Bool indicating whether you are in melee range. public static bool InMeleeRange() { - if (LocalPlayer.TargetObject == null) + if (Svc.Targets.Target == null) return false; float distance = GetTargetDistance(); diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index f494525f5..c1f27919b 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -137,7 +137,7 @@ Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember is not null && break; case 1: if (CustomComboFunctions.HasFriendlyTarget()) - targetObjectId = Svc.ClientState.LocalPlayer.TargetObject.GameObjectId; + targetObjectId = Svc.Targets.Target.GameObjectId; else targetObjectId = Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.GameObjectId; break; diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 69b6ba8c9..12d41d213 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -41,6 +41,8 @@ internal class DebugCombo : CustomCombo DebugCombo? comboClass = new(); IPlayerCharacter? LocalPlayer = Svc.ClientState.LocalPlayer; uint[] statusBlacklist = { 360, 361, 362, 363, 364, 365, 366, 367, 368 }; // Duration will not be displayed for these status effects + var target = Svc.Targets.Target; + // Custom Styling static void CustomStyleText(string label, object? value) @@ -97,7 +99,7 @@ static void CustomStyleText(string label, object? value) // Target Status Effects if (ImGui.CollapsingHeader("Target Status Effects")) { - if (LocalPlayer.TargetObject is IBattleChara chara) + if (target != null && target is IBattleChara chara) { foreach (Status? status in chara.StatusList) { @@ -215,12 +217,12 @@ static void CustomStyleText(string label, object? value) ImGui.Spacing(); ImGui.Text("Target Info"); ImGui.Separator(); - CustomStyleText("ObjectId:", LocalPlayer.TargetObject?.GameObjectId); - CustomStyleText("ObjectKind:", LocalPlayer.TargetObject?.ObjectKind); - CustomStyleText("Is BattleChara:", LocalPlayer.TargetObject is IBattleChara); - CustomStyleText("Is PlayerCharacter:", LocalPlayer.TargetObject is IPlayerCharacter); + CustomStyleText("ObjectId:", target?.GameObjectId); + CustomStyleText("ObjectKind:", target?.ObjectKind); + CustomStyleText("Is BattleChara:", target is IBattleChara); + CustomStyleText("Is PlayerCharacter:", target is IPlayerCharacter); CustomStyleText("Distance:", $"{Math.Round(GetTargetDistance(), 2)}y"); - CustomStyleText("Hitbox Radius:", LocalPlayer.TargetObject?.HitboxRadius); + CustomStyleText("Hitbox Radius:", target?.HitboxRadius); CustomStyleText("In Melee Range:", InMeleeRange()); CustomStyleText("Relative Position:", AngleToTarget() is 2 ? "Rear" : (AngleToTarget() is 1 or 3) ? "Flank" : AngleToTarget() is 4 ? "Front" : ""); CustomStyleText("Health:", $"{EnemyHealthCurrentHp().ToString("N0")} / {EnemyHealthMaxHp().ToString("N0")} ({Math.Round(GetTargetHPPercent(), 2)}%)"); diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 34b119b88..6f0e77420 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.4 + 0.0.0.5 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From 60537df8270481718c23b01e360ea9fcc0cae96e Mon Sep 17 00:00:00 2001 From: Mattia Wijns Date: Sun, 29 Sep 2024 19:55:39 +0200 Subject: [PATCH 151/208] refactor --- XIVSlothCombo/Combos/JobHelpers/VPR.cs | 316 ----- XIVSlothCombo/Combos/PvE/VPR.cs | 1193 ------------------ XIVSlothCombo/Combos/PvE/VPR/VPR.cs | 1182 +++++++++++++++++ XIVSlothCombo/Combos/PvE/VPR/VPR_Config.cs | 90 ++ XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs | 326 +++++ XIVSlothCombo/Window/Functions/UserConfig.cs | 52 - 6 files changed, 1598 insertions(+), 1561 deletions(-) delete mode 100644 XIVSlothCombo/Combos/JobHelpers/VPR.cs delete mode 100644 XIVSlothCombo/Combos/PvE/VPR.cs create mode 100644 XIVSlothCombo/Combos/PvE/VPR/VPR.cs create mode 100644 XIVSlothCombo/Combos/PvE/VPR/VPR_Config.cs create mode 100644 XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/VPR.cs b/XIVSlothCombo/Combos/JobHelpers/VPR.cs deleted file mode 100644 index 3258e81b7..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/VPR.cs +++ /dev/null @@ -1,316 +0,0 @@ -using Dalamud.Game.ClientState.JobGauge.Types; -using ECommons.DalamudServices; -using FFXIVClientStructs.FFXIV.Client.Game; -using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Data; -using static XIVSlothCombo.Combos.PvE.VPR; -using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; - -namespace XIVSlothCombo.Combos.JobHelpers -{ - internal class VPRHelpers - { - internal class VPROpenerLogic - { - private static bool HasCooldowns() - { - if (GetRemainingCharges(Vicewinder) < 2) - return false; - - if (!ActionReady(SerpentsIre)) - return false; - - return true; - } - - private static uint OpenerLevel => 100; - - public uint PrePullStep = 0; - - public uint OpenerStep = 0; - - public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; - - private static bool CanOpener => HasCooldowns() && LevelChecked; - - private OpenerState currentState = OpenerState.PrePull; - - public OpenerState CurrentState - { - get - { - return currentState; - } - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; - } - } - } - - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } - - if (!HasCooldowns()) - { - PrePullStep = 0; - } - - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (WasLastAction(ReavingFangs) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) actionID = ReavingFangs; - - if (ActionWatching.CombatActions.Count > 2 && InCombat()) - CurrentState = OpenerState.FailedOpener; - - return true; - } - PrePullStep = 0; - return false; - } - - private bool DoOpener(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (currentState == OpenerState.InOpener) - { - if (WasLastAction(SerpentsIre) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = SerpentsIre; - - if (WasLastAction(SwiftskinsSting) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = SwiftskinsSting; - - if (WasLastAction(Vicewinder) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Vicewinder; - - if (WasLastAction(HuntersCoil) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = HuntersCoil; - - if (WasLastAction(TwinfangBite) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = TwinfangBite; - - if (WasLastAction(TwinbloodBite) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = TwinbloodBite; - - if (WasLastAction(SwiftskinsCoil) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = SwiftskinsCoil; - - if (WasLastAction(TwinbloodBite) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = TwinbloodBite; - - if (WasLastAction(TwinfangBite) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = TwinfangBite; - - if (WasLastAction(Reawaken) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = Reawaken; - - if (WasLastAction(FirstGeneration) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = FirstGeneration; - - if (WasLastAction(FirstLegacy) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = FirstLegacy; - - if (WasLastAction(SecondGeneration) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = SecondGeneration; - - if (WasLastAction(SecondLegacy) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = SecondLegacy; - - if (WasLastAction(ThirdGeneration) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = ThirdGeneration; - - if (WasLastAction(ThirdLegacy) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = ThirdLegacy; - - if (WasLastAction(FourthGeneration) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = FourthGeneration; - - if (WasLastAction(FourthLegacy) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = FourthLegacy; - - if (WasLastAction(Ouroboros) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Ouroboros; - - if (WasLastAction(UncoiledFury) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = UncoiledFury; - - if (WasLastAction(UncoiledTwinfang) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = UncoiledTwinfang; - - if (WasLastAction(UncoiledTwinblood) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = UncoiledTwinblood; - - if (WasLastAction(UncoiledFury) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = UncoiledFury; - - if (WasLastAction(UncoiledTwinfang) && OpenerStep == 24) OpenerStep++; - else if (OpenerStep == 24) actionID = UncoiledTwinfang; - - if (WasLastAction(UncoiledTwinblood) && OpenerStep == 25) OpenerStep++; - else if (OpenerStep == 25) actionID = UncoiledTwinblood; - - if (WasLastAction(HindstingStrike) && OpenerStep == 26) OpenerStep++; - else if (OpenerStep == 26) actionID = HindstingStrike; - - if (WasLastAction(DeathRattle) && OpenerStep == 27) OpenerStep++; - else if (OpenerStep == 27) actionID = DeathRattle; - - if (WasLastAction(Vicewinder) && OpenerStep == 28) OpenerStep++; - else if (OpenerStep == 28) actionID = Vicewinder; - - if (WasLastAction(UncoiledFury) && OpenerStep == 29) OpenerStep++; - else if (OpenerStep == 29) actionID = UncoiledFury; - - if (WasLastAction(UncoiledTwinfang) && OpenerStep == 30) OpenerStep++; - else if (OpenerStep == 30) actionID = UncoiledTwinfang; - - if (WasLastAction(UncoiledTwinblood) && OpenerStep == 31) OpenerStep++; - else if (OpenerStep == 31) actionID = UncoiledTwinblood; - - if (WasLastAction(HuntersCoil) && OpenerStep == 32) OpenerStep++; - else if (OpenerStep == 32) actionID = HuntersCoil; - - if (WasLastAction(TwinfangBite) && OpenerStep == 33) OpenerStep++; - else if (OpenerStep == 33) actionID = TwinfangBite; - - if (WasLastAction(TwinbloodBite) && OpenerStep == 34) OpenerStep++; - else if (OpenerStep == 34) actionID = TwinbloodBite; - - if (WasLastAction(SwiftskinsCoil) && OpenerStep == 35) OpenerStep++; - else if (OpenerStep == 35) actionID = SwiftskinsCoil; - - if (WasLastAction(TwinbloodBite) && OpenerStep == 36) OpenerStep++; - else if (OpenerStep == 36) actionID = TwinbloodBite; - - if (WasLastAction(TwinfangBite) && OpenerStep == 37) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 37) actionID = TwinfangBite; - - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; - - if (((actionID == SerpentsIre && IsOnCooldown(SerpentsIre)) || - (actionID == Vicewinder && GetRemainingCharges(Vicewinder) < 2)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - return true; - } - return false; - } - - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } - - public bool DoFullOpener(ref uint actionID) - { - if (!LevelChecked) - return false; - - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) - return true; - - if (CurrentState == OpenerState.InOpener) - { - if (DoOpener(ref actionID)) - return true; - } - - if (!InCombat()) - { - ResetOpener(); - CurrentState = OpenerState.PrePull; - } - return false; - } - } - - internal class VPRCheckRattlingCoils - { - public static bool HasRattlingCoilStack(VPRGauge gauge) - { - if (gauge.RattlingCoilStacks > 0) - return true; - - else return false; - } - } - - internal class VPRCheckTimers - { - public static bool IsHoningExpiring(float Times) - { - float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - - if ((HasEffect(Buffs.HonedSteel) && GetBuffRemainingTime(Buffs.HonedSteel) < GCD) || - (HasEffect(Buffs.HonedReavers) && GetBuffRemainingTime(Buffs.HonedReavers) < GCD)) - return true; - - else return false; - } - - public static bool IsVenomExpiring(float Times) - { - float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - - if ((HasEffect(Buffs.FlankstungVenom) && GetBuffRemainingTime(Buffs.FlankstungVenom) < GCD) || - (HasEffect(Buffs.FlanksbaneVenom) && GetBuffRemainingTime(Buffs.FlanksbaneVenom) < GCD) || - (HasEffect(Buffs.HindstungVenom) && GetBuffRemainingTime(Buffs.HindstungVenom) < GCD) || - (HasEffect(Buffs.HindsbaneVenom) && GetBuffRemainingTime(Buffs.HindsbaneVenom) < GCD)) - return true; - - else return false; - } - - public static bool IsEmpowermentExpiring(float Times) - { - float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - - if (GetBuffRemainingTime(Buffs.Swiftscaled) < GCD || GetBuffRemainingTime(Buffs.HuntersInstinct) < GCD) - return true; - - else return false; - } - - public unsafe static bool IsComboExpiring(float Times) - { - float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - - if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) - return true; - - else return false; - } - } - } -} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR.cs deleted file mode 100644 index 42a2b0378..000000000 --- a/XIVSlothCombo/Combos/PvE/VPR.cs +++ /dev/null @@ -1,1193 +0,0 @@ -using Dalamud.Game.ClientState.JobGauge.Enums; -using Dalamud.Game.ClientState.JobGauge.Types; -using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Data; -using static XIVSlothCombo.Combos.JobHelpers.VPRHelpers; - -namespace XIVSlothCombo.Combos.PvE -{ - internal class VPR - { - public const byte JobID = 41; - - public const uint - ReavingFangs = 34607, - ReavingMaw = 34615, - Vicewinder = 34620, - HuntersCoil = 34621, - HuntersDen = 34624, - HuntersSnap = 39166, - Vicepit = 34623, - RattlingCoil = 39189, - Reawaken = 34626, - SerpentsIre = 34647, - SerpentsTail = 35920, - Slither = 34646, - SteelFangs = 34606, - SteelMaw = 34614, - SwiftskinsCoil = 34622, - SwiftskinsDen = 34625, - Twinblood = 35922, - Twinfang = 35921, - UncoiledFury = 34633, - WrithingSnap = 34632, - SwiftskinsSting = 34609, - TwinfangBite = 34636, - TwinbloodBite = 34637, - UncoiledTwinfang = 34644, - UncoiledTwinblood = 34645, - HindstingStrike = 34612, - DeathRattle = 34634, - HuntersSting = 34608, - HindsbaneFang = 34613, - FlankstingStrike = 34610, - FlanksbaneFang = 34611, - HuntersBite = 34616, - JaggedMaw = 34618, - SwiftskinsBite = 34617, - BloodiedMaw = 34619, - FirstGeneration = 34627, - FirstLegacy = 34640, - SecondGeneration = 34628, - SecondLegacy = 34641, - ThirdGeneration = 34629, - ThirdLegacy = 34642, - FourthGeneration = 34630, - FourthLegacy = 34643, - Ouroboros = 34631, - LastLash = 34635; - - public static class Buffs - { - public const ushort - FellhuntersVenom = 3659, - FellskinsVenom = 3660, - FlanksbaneVenom = 3646, - FlankstungVenom = 3645, - HindstungVenom = 3647, - HindsbaneVenom = 3648, - GrimhuntersVenom = 3649, - GrimskinsVenom = 3650, - HuntersVenom = 3657, - SwiftskinsVenom = 3658, - HuntersInstinct = 3668, - Swiftscaled = 3669, - Reawakened = 3670, - ReadyToReawaken = 3671, - PoisedForTwinfang = 3665, - PoisedForTwinblood = 3666, - HonedReavers = 3772, - HonedSteel = 3672; - } - - public static class Debuffs - { - } - - public static class Traits - { - public const uint - EnhancedVipersRattle = 530, - EnhancedSerpentsLineage = 533, - SerpentsLegacy = 534; - } - - public static class Config - { - public static UserInt - VPR_ST_SecondWind_Threshold = new("VPR_ST_SecondWindThreshold", 25), - VPR_ST_Bloodbath_Threshold = new("VPR_ST_BloodbathThreshold", 40), - VPR_AoE_SecondWind_Threshold = new("VPR_AoE_SecondWindThreshold", 25), - VPR_AoE_Bloodbath_Threshold = new("VPR_AoE_BloodbathThreshold", 40), - VPR_ST_UncoiledFury_HoldCharges = new("VPR_ST_UncoiledFury_HoldCharges", 1), - VPR_AoE_UncoiledFury_HoldCharges = new("VPR_AoE_UncoiledFury_HoldCharges", 0), - VPR_ST_UncoiledFury_Threshold = new("VPR_ST_UncoiledFury_Threshold", 1), - VPR_AoE_UncoiledFury_Threshold = new("VPR_AoE_UncoiledFury_Threshold", 1), - VPR_ReawakenLegacyButton = new("VPR_ReawakenLegacyButton"), - VPR_VariantCure = new("VPR_VariantCure"); - - public static UserFloat - VPR_ST_Reawaken_Usage = new("VPR_ST_Reawaken_Usage", 2), - VPR_AoE_Reawaken_Usage = new("VPR_AoE_Reawaken_Usage", 2); - } - - internal class VPR_ST_SimpleMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ST_SimpleMode; - internal static VPROpenerLogic VPROpener = new(); - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - int RattlingCoils = gauge.RattlingCoilStacks; - var ireCD = GetCooldownRemainingTime(SerpentsIre); - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; - bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; - bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; - bool in5y = GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - - if (actionID is SteelFangs) - { - // Opener for VPR - if (VPROpener.DoFullOpener(ref actionID)) - return actionID; - - // Variant Cure - if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) - return Variant.VariantCure; - - // Variant Rampart - if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(ActionWatching.LastWeaponskill)) - return Variant.VariantRampart; - - //Serpents Ire - ForceWeave - if (InCombat() && CanWeave(UncoiledFury) && !CappedOnCoils && ActionReady(SerpentsIre)) - return SerpentsIre; - - //oGCDs - if (CanWeave(ActionWatching.LastWeaponskill)) - { - // Legacy Weaves - if (in5y && TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - // Fury Twin Weaves - if (HasEffect(Buffs.PoisedForTwinfang)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.PoisedForTwinblood)) - return OriginalHook(Twinblood); - - //Vice Twin Weaves - if (!HasEffect(Buffs.Reawakened)) - { - //Vicewinder weaves - if (in5y) - { - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - } - } - } - - // Death Rattle - Force to avoid loss - if (in5y && LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) - return OriginalHook(SerpentsTail); - - //GCDs - if (LevelChecked(WrithingSnap) && !InMeleeRange() && HasBattleTarget()) - return (VPRCheckRattlingCoils.HasRattlingCoilStack(gauge)) - ? UncoiledFury - : WrithingSnap; - - //Vicewinder Combo - if (!HasEffect(Buffs.Reawakened) && LevelChecked(Vicewinder) && InMeleeRange()) - { - // Swiftskin's Coil - if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) - return SwiftskinsCoil; - - // Hunter's Coil - if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) - return HuntersCoil; - } - - //Reawakend Usage - if (UseReawaken(gauge)) - return Reawaken; - - //Overcap protection - if (CappedOnCoils && - ((HasCharges(Vicewinder) && !HasEffect(Buffs.SwiftskinsVenom) && !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.Reawakened)) || //spend if Vicewinder is up, after Reawaken - (ireCD <= GCD * 5))) //spend in case under Reawaken right as Ire comes up - return UncoiledFury; - - //Vicewinder Usage - if (HasEffect(Buffs.Swiftscaled) && !VPRCheckTimers.IsComboExpiring(3) && - ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && - !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) - return Vicewinder; - - // Uncoiled Fury usage - if (LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && !VPRCheckTimers.IsComboExpiring(2) && - RattlingCoils > 1 && - !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && - !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && !WasLastWeaponskill(Ouroboros) && - !VPRCheckTimers.IsEmpowermentExpiring(6) && !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) - return UncoiledFury; - - //Reawaken combo - if (HasEffect(Buffs.Reawakened)) - { - //Pre Ouroboros - if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 4) - return OriginalHook(SteelFangs); - - if (gauge.AnguineTribute is 3) - return OriginalHook(ReavingFangs); - - if (gauge.AnguineTribute is 2) - return OriginalHook(HuntersCoil); - - if (gauge.AnguineTribute is 1) - return OriginalHook(SwiftskinsCoil); - } - - //With Ouroboros - if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 5) - return OriginalHook(SteelFangs); - - if (gauge.AnguineTribute is 4) - return OriginalHook(ReavingFangs); - - if (gauge.AnguineTribute is 3) - return OriginalHook(HuntersCoil); - - if (gauge.AnguineTribute is 2) - return OriginalHook(SwiftskinsCoil); - - if (gauge.AnguineTribute is 1) - return OriginalHook(Reawaken); - } - } - - //1-2-3 (4-5-6) Combo - if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) - { - if (lastComboMove is ReavingFangs or SteelFangs) - { - if (LevelChecked(HuntersSting) && - (HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.FlanksbaneVenom))) - return OriginalHook(SteelFangs); - - if (LevelChecked(SwiftskinsSting) && - (HasEffect(Buffs.HindstungVenom) || HasEffect(Buffs.HindsbaneVenom) || - (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) - return OriginalHook(ReavingFangs); - } - - if (lastComboMove is HuntersSting or SwiftskinsSting) - { - if ((HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.HindstungVenom)) && LevelChecked(FlanksbaneFang)) - { - if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom)) - return All.TrueNorth; - - if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom)) - return All.TrueNorth; - - return OriginalHook(SteelFangs); - } - - if ((HasEffect(Buffs.FlanksbaneVenom) || HasEffect(Buffs.HindsbaneVenom)) && LevelChecked(HindstingStrike)) - { - if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindsbaneVenom) && CanDelayedWeave(actionID)) - return All.TrueNorth; - - if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlanksbaneVenom) && CanDelayedWeave(actionID)) - return All.TrueNorth; - - return OriginalHook(ReavingFangs); - } - } - - if (lastComboMove is HindstingStrike or HindsbaneFang or FlankstingStrike or FlanksbaneFang) - return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingFangs) - : OriginalHook(SteelFangs); - } - //LowLevels - return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingFangs) - : OriginalHook(SteelFangs); - } - return actionID; - } - - private static bool UseReawaken(VPRGauge gauge) - { - var ireCD = GetCooldownRemainingTime(SerpentsIre); - - if (LevelChecked(Reawaken) && !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && - !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.SwiftskinsVenom) && - !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang) && - !VPRCheckTimers.IsEmpowermentExpiring(6)) - { - if ((!JustUsed(SerpentsIre, 2.2f) && HasEffect(Buffs.ReadyToReawaken)) || //2min burst - (WasLastWeaponskill(Ouroboros) && gauge.SerpentOffering >= 50 && ireCD >= 50) || //2nd RA - (gauge.SerpentOffering is >= 50 and <= 80 && ireCD is >= 50 and <= 62) || //1min - (gauge.SerpentOffering >= 100) || //overcap - (gauge.SerpentOffering >= 50 && WasLastWeaponskill(FourthGeneration) && !LevelChecked(Ouroboros))) //<100 - return true; - } - return false; - } - } - - internal class VPR_ST_AdvancedMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ST_AdvancedMode; - internal static VPROpenerLogic VPROpener = new(); - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - int uncoiledThreshold = Config.VPR_ST_UncoiledFury_Threshold; - int RattlingCoils = gauge.RattlingCoilStacks; - var enemyHP = GetTargetHPPercent(); - var ireCD = GetCooldownRemainingTime(SerpentsIre); - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; - bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; - bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; - bool in5y = GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - - - if (actionID is SteelFangs) - { - // Variant Cure - if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) - return Variant.VariantCure; - - // Variant Rampart - if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(ActionWatching.LastWeaponskill)) - return Variant.VariantRampart; - - // Opener for VPR - if (IsEnabled(CustomComboPreset.VPR_ST_Opener)) - { - if (VPROpener.DoFullOpener(ref actionID)) - return actionID; - } - - //Serpents Ire - MaxPrio oGCD, ForceWeave this in order to maintain raid buff upkeep or to avoid delay when inside RA - if (IsEnabled(CustomComboPreset.VPR_ST_SerpentsIre) && InCombat() && - CanWeave(UncoiledFury) && !CappedOnCoils && ActionReady(SerpentsIre)) - return SerpentsIre; - - //oGCDs - if (CanWeave(ActionWatching.LastWeaponskill)) - { - // Death Rattle - if (IsEnabled(CustomComboPreset.VPR_ST_SerpentsTail) && in5y && - LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) - return OriginalHook(SerpentsTail); - - // Legacy Weaves - if (IsEnabled(CustomComboPreset.VPR_ST_ReawakenCombo) && in5y && - TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - // Fury Twin Weaves - if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFuryCombo)) - { - if (HasEffect(Buffs.PoisedForTwinfang)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.PoisedForTwinblood)) - return OriginalHook(Twinblood); - } - - //Vice Twin Weaves - if (!HasEffect(Buffs.Reawakened)) - { - if (IsEnabled(CustomComboPreset.VPR_ST_CDs)) - { - //Vicewinder weaves - if (IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && in5y) - { - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - } - } - } - } - - // Death Rattle - Force to avoid loss - if (IsEnabled(CustomComboPreset.VPR_ST_SerpentsTail) && in5y && - LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) - return OriginalHook(SerpentsTail); - - //GCDs - if (IsEnabled(CustomComboPreset.VPR_ST_RangedUptime) && - LevelChecked(WrithingSnap) && !InMeleeRange() && HasBattleTarget()) - return (IsEnabled(CustomComboPreset.VPR_ST_RangedUptimeUncoiledFury) && VPRCheckRattlingCoils.HasRattlingCoilStack(gauge)) - ? UncoiledFury - : WrithingSnap; - - //Vicewinder Combo - if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && - IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && - !HasEffect(Buffs.Reawakened) && LevelChecked(Vicewinder) && InMeleeRange()) - { - // Swiftskin's Coil - if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) - return SwiftskinsCoil; - - // Hunter's Coil - if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) - return HuntersCoil; - } - - //Reawakend Usage - if (IsEnabled(CustomComboPreset.VPR_ST_Reawaken) && UseReawaken(gauge)) - return Reawaken; - - //Overcap protection - if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && CappedOnCoils && - ((HasCharges(Vicewinder) && !HasEffect(Buffs.SwiftskinsVenom) && !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.Reawakened)) || //spend if Vicewinder is up, after Reawaken - (ireCD <= GCD * 5))) //spend in case under Reawaken right as Ire comes up - return UncoiledFury; - - //Vicewinder Usage - if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && - IsEnabled(CustomComboPreset.VPR_ST_Vicewinder) && HasEffect(Buffs.Swiftscaled) && !VPRCheckTimers.IsComboExpiring(3) && - ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && - !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) - return Vicewinder; - - // Uncoiled Fury usage - if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && !VPRCheckTimers.IsComboExpiring(2) && - LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - ((RattlingCoils > Config.VPR_ST_UncoiledFury_HoldCharges) || - (enemyHP < uncoiledThreshold && VPRCheckRattlingCoils.HasRattlingCoilStack(gauge))) && - !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && - !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && !WasLastWeaponskill(Ouroboros) && - !VPRCheckTimers.IsEmpowermentExpiring(3)) - return UncoiledFury; - - //Reawaken combo - if (IsEnabled(CustomComboPreset.VPR_ST_ReawakenCombo) && - HasEffect(Buffs.Reawakened)) - { - //Pre Ouroboros - if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 4) - return OriginalHook(SteelFangs); - - if (gauge.AnguineTribute is 3) - return OriginalHook(ReavingFangs); - - if (gauge.AnguineTribute is 2) - return OriginalHook(HuntersCoil); - - if (gauge.AnguineTribute is 1) - return OriginalHook(SwiftskinsCoil); - } - - //With Ouroboros - if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 5) - return OriginalHook(SteelFangs); - - if (gauge.AnguineTribute is 4) - return OriginalHook(ReavingFangs); - - if (gauge.AnguineTribute is 3) - return OriginalHook(HuntersCoil); - - if (gauge.AnguineTribute is 2) - return OriginalHook(SwiftskinsCoil); - - if (gauge.AnguineTribute is 1) - return OriginalHook(Reawaken); - } - } - - // healing - if (IsEnabled(CustomComboPreset.VPR_ST_ComboHeals)) - { - if (PlayerHealthPercentageHp() <= Config.VPR_ST_SecondWind_Threshold && ActionReady(All.SecondWind)) - return All.SecondWind; - - if (PlayerHealthPercentageHp() <= Config.VPR_ST_Bloodbath_Threshold && ActionReady(All.Bloodbath)) - return All.Bloodbath; - } - - //1-2-3 (4-5-6) Combo - if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) - { - if (lastComboMove is ReavingFangs or SteelFangs) - { - if (LevelChecked(HuntersSting) && - (HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.FlanksbaneVenom))) - return OriginalHook(SteelFangs); - - if (LevelChecked(SwiftskinsSting) && - (HasEffect(Buffs.HindstungVenom) || HasEffect(Buffs.HindsbaneVenom) || - (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) - return OriginalHook(ReavingFangs); - } - - if (lastComboMove is HuntersSting or SwiftskinsSting) - { - if ((HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.HindstungVenom)) && LevelChecked(FlanksbaneFang)) - { - if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && - trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom)) - return All.TrueNorth; - - if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && - trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom)) - return All.TrueNorth; - - return OriginalHook(SteelFangs); - } - - if ((HasEffect(Buffs.FlanksbaneVenom) || HasEffect(Buffs.HindsbaneVenom)) && LevelChecked(HindstingStrike)) - { - if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && - trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindsbaneVenom) && CanDelayedWeave(actionID)) - return All.TrueNorth; - - if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && - trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlanksbaneVenom) && CanDelayedWeave(actionID)) - return All.TrueNorth; - - return OriginalHook(ReavingFangs); - } - } - - if (lastComboMove is HindstingStrike or HindsbaneFang or FlankstingStrike or FlanksbaneFang) - return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingFangs) - : OriginalHook(SteelFangs); - } - //LowLevels - return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingFangs) - : OriginalHook(SteelFangs); - } - return actionID; - } - - private static bool UseReawaken(VPRGauge gauge) - { - var ireCD = GetCooldownRemainingTime(SerpentsIre); - - if (LevelChecked(Reawaken) && !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && - !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.SwiftskinsVenom) && - !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang) && - !VPRCheckTimers.IsEmpowermentExpiring(6)) - { - if ((!JustUsed(SerpentsIre, 2.2f) && HasEffect(Buffs.ReadyToReawaken)) || //2min burst - (WasLastWeaponskill(Ouroboros) && gauge.SerpentOffering >= 50 && ireCD >= 50) || //2nd RA - (gauge.SerpentOffering is >= 50 and <= 80 && ireCD is >= 50 and <= 62) || //1min - (gauge.SerpentOffering >= 100) || //overcap - (gauge.SerpentOffering >= 50 && WasLastWeaponskill(FourthGeneration) && !LevelChecked(Ouroboros))) //<100 - return true; - } - return false; - } - } - - internal class VPR_AoE_Simplemode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_AoE_SimpleMode; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - int RattlingCoils = gauge.RattlingCoilStacks; - var ireCD = GetCooldownRemainingTime(SerpentsIre); - bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; - bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; - bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; - bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - - if (actionID is SteelMaw) - { - if (CanWeave(ActionWatching.LastWeaponskill)) - { - // Variant Cure - if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) - return Variant.VariantCure; - - // Variant Rampart - if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(ActionWatching.LastWeaponskill)) - return Variant.VariantRampart; - - // Death Rattle - if (LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is LastLash) - return OriginalHook(SerpentsTail); - - // Legacy Weaves - if (TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - // Uncoiled combo - if (HasEffect(Buffs.PoisedForTwinfang)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.PoisedForTwinblood)) - return OriginalHook(Twinblood); - - if (!HasEffect(Buffs.Reawakened)) - { - //Vicepit weaves - if (HasEffect(Buffs.FellhuntersVenom) && in5y) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.FellskinsVenom) && in5y) - return OriginalHook(Twinblood); - - //Serpents Ire usage - if (!CappedOnCoils && ActionReady(SerpentsIre)) - return SerpentsIre; - } - } - - //Vicepit combo - if (!HasEffect(Buffs.Reawakened) && in5y) - { - if (SwiftskinsDenReady) - return HuntersDen; - - if (VicepitReady) - return SwiftskinsDen; - } - - //Reawakend Usage - if ((HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && - HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && in5y && - !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && - !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) - return Reawaken; - - //Overcap protection - if (((HasCharges(Vicepit) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.FellhuntersVenom)) || - ireCD <= GCD * 2) && !HasEffect(Buffs.Reawakened) && CappedOnCoils) - return UncoiledFury; - - //Vicepit Usage - if (ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre)) && in5y) - return Vicepit; - - // Uncoiled Fury usage - if (LevelChecked(UncoiledFury) && - VPRCheckRattlingCoils.HasRattlingCoilStack(gauge) && - HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !VicepitReady && !HuntersDenReady && !SwiftskinsDenReady && - !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.FellhuntersVenom) && - !WasLastWeaponskill(JaggedMaw) && !WasLastWeaponskill(BloodiedMaw) && !WasLastAbility(SerpentsIre)) - return UncoiledFury; - - //Reawaken combo - if (HasEffect(Buffs.Reawakened)) - { - //Pre Ouroboros - if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 4) - return OriginalHook(SteelMaw); - - if (gauge.AnguineTribute is 3) - return OriginalHook(ReavingMaw); - - if (gauge.AnguineTribute is 2) - return OriginalHook(HuntersDen); - - if (gauge.AnguineTribute is 1) - return OriginalHook(SwiftskinsDen); - } - - //With Ouroboros - if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 5) - return OriginalHook(SteelMaw); - - if (gauge.AnguineTribute is 4) - return OriginalHook(ReavingMaw); - - if (gauge.AnguineTribute is 3) - return OriginalHook(HuntersDen); - - if (gauge.AnguineTribute is 2) - return OriginalHook(SwiftskinsDen); - - if (gauge.AnguineTribute is 1) - return OriginalHook(Reawaken); - } - } - - // healing - if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) - return All.SecondWind; - - if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) - return All.Bloodbath; - - //1-2-3 (4-5-6) Combo - if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) - { - if (lastComboMove is ReavingMaw or SteelMaw) - { - if (LevelChecked(HuntersBite) && - HasEffect(Buffs.GrimhuntersVenom)) - return OriginalHook(SteelMaw); - - if (LevelChecked(SwiftskinsBite) && - (HasEffect(Buffs.GrimskinsVenom) || (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) - return OriginalHook(ReavingMaw); - } - - if (lastComboMove is HuntersBite or SwiftskinsBite) - { - if (HasEffect(Buffs.GrimhuntersVenom) && LevelChecked(JaggedMaw)) - return OriginalHook(SteelMaw); - - if (HasEffect(Buffs.GrimskinsVenom) && LevelChecked(BloodiedMaw)) - return OriginalHook(ReavingMaw); - } - - if (lastComboMove is BloodiedMaw or JaggedMaw) - return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingMaw) - : OriginalHook(SteelMaw); - } - //for lower lvls - return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingMaw) - : OriginalHook(SteelMaw); - } - return actionID; - } - } - - internal class VPR_AoE_AdvancedMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_AoE_AdvancedMode; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - int uncoiledThreshold = Config.VPR_AoE_UncoiledFury_Threshold; - int RattlingCoils = gauge.RattlingCoilStacks; - var enemyHP = GetTargetHPPercent(); - var ireCD = GetCooldownRemainingTime(SerpentsIre); - bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; - bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; - bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; - bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - - if (actionID is SteelMaw) - { - // Variant Cure - if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) - return Variant.VariantCure; - - // Variant Rampart - if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanWeave(ActionWatching.LastWeaponskill)) - return Variant.VariantRampart; - - if (CanWeave(ActionWatching.LastWeaponskill)) - { - // Death Rattle - if (IsEnabled(CustomComboPreset.VPR_AoE_SerpentsTail) && - LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is LastLash) - return OriginalHook(SerpentsTail); - - // Legacy Weaves - if (IsEnabled(CustomComboPreset.VPR_AoE_ReawakenCombo) && - TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - // Uncoiled combo - if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFuryCombo)) - { - if (HasEffect(Buffs.PoisedForTwinfang)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.PoisedForTwinblood)) - return OriginalHook(Twinblood); - } - - if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && - !HasEffect(Buffs.Reawakened)) - { - //Vicepit weaves - if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) - { - if (HasEffect(Buffs.FellhuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.FellskinsVenom)) - return OriginalHook(Twinblood); - } - - //Serpents Ire usage - if (IsEnabled(CustomComboPreset.VPR_AoE_SerpentsIre) && - !CappedOnCoils && ActionReady(SerpentsIre)) - return SerpentsIre; - } - } - - //Vicepit combo - if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && - IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && - !HasEffect(Buffs.Reawakened) && - (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) - { - if (SwiftskinsDenReady) - return HuntersDen; - - if (VicepitReady) - return SwiftskinsDen; - } - - //Reawakend Usage - if (IsEnabled(CustomComboPreset.VPR_AoE_Reawaken) && - (HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && - HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !HasEffect(Buffs.Reawakened) && - (in5y || IsEnabled(CustomComboPreset.VPR_AoE_Reawaken_DisableRange)) && - !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && - !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) - return Reawaken; - - //Overcap protection - if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFury) && - ((HasCharges(Vicepit) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.FellhuntersVenom)) || - ireCD <= GCD * 2) && !HasEffect(Buffs.Reawakened) && CappedOnCoils) - return UncoiledFury; - - //Vicepit Usage - if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && - IsEnabled(CustomComboPreset.VPR_AoE_Vicepit) && - ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && - (in5y || IsEnabled(CustomComboPreset.VPR_AoE_Vicepit_DisableRange)) && - ((ireCD >= GCD * 5) || !LevelChecked(SerpentsIre))) - return Vicepit; - - // Uncoiled Fury usage - if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFury) && - LevelChecked(UncoiledFury) && - ((RattlingCoils > Config.VPR_AoE_UncoiledFury_HoldCharges) || (enemyHP < uncoiledThreshold && VPRCheckRattlingCoils.HasRattlingCoilStack(gauge))) && - HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - !VicepitReady && !HuntersDenReady && !SwiftskinsDenReady && - !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.FellhuntersVenom) && - !WasLastWeaponskill(JaggedMaw) && !WasLastWeaponskill(BloodiedMaw) && !WasLastAbility(SerpentsIre)) - return UncoiledFury; - - //Reawaken combo - if (IsEnabled(CustomComboPreset.VPR_AoE_ReawakenCombo) && - HasEffect(Buffs.Reawakened)) - { - //Pre Ouroboros - if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 4) - return OriginalHook(SteelMaw); - - if (gauge.AnguineTribute is 3) - return OriginalHook(ReavingMaw); - - if (gauge.AnguineTribute is 2) - return OriginalHook(HuntersDen); - - if (gauge.AnguineTribute is 1) - return OriginalHook(SwiftskinsDen); - } - - //With Ouroboros - if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 5) - return OriginalHook(SteelMaw); - - if (gauge.AnguineTribute is 4) - return OriginalHook(ReavingMaw); - - if (gauge.AnguineTribute is 3) - return OriginalHook(HuntersDen); - - if (gauge.AnguineTribute is 2) - return OriginalHook(SwiftskinsDen); - - if (gauge.AnguineTribute is 1) - return OriginalHook(Reawaken); - } - } - - // healing - if (IsEnabled(CustomComboPreset.VPR_AoE_ComboHeals)) - { - if (PlayerHealthPercentageHp() <= Config.VPR_AoE_SecondWind_Threshold && ActionReady(All.SecondWind)) - return All.SecondWind; - - if (PlayerHealthPercentageHp() <= Config.VPR_AoE_Bloodbath_Threshold && ActionReady(All.Bloodbath)) - return All.Bloodbath; - } - - //1-2-3 (4-5-6) Combo - if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) - { - if (lastComboMove is ReavingMaw or SteelMaw) - { - if (LevelChecked(HuntersBite) && - HasEffect(Buffs.GrimhuntersVenom)) - return OriginalHook(SteelMaw); - - if (LevelChecked(SwiftskinsBite) && - (HasEffect(Buffs.GrimskinsVenom) || (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) - return OriginalHook(ReavingMaw); - } - - if (lastComboMove is HuntersBite or SwiftskinsBite) - { - if (HasEffect(Buffs.GrimhuntersVenom) && LevelChecked(JaggedMaw)) - return OriginalHook(SteelMaw); - - if (HasEffect(Buffs.GrimskinsVenom) && LevelChecked(BloodiedMaw)) - return OriginalHook(ReavingMaw); - } - - if (lastComboMove is BloodiedMaw or JaggedMaw) - return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingMaw) - : OriginalHook(SteelMaw); - } - //for lower lvls - return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) - ? OriginalHook(ReavingMaw) - : OriginalHook(SteelMaw); - } - return actionID; - } - } - - internal class VPR_VicewinderCoils : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_VicewinderCoils; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; - bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; - bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; - - if (actionID is Vicewinder) - { - if (IsEnabled(CustomComboPreset.VPR_VicewinderCoils_oGCDs)) - { - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - } - - // Vicewinder Combo - if (LevelChecked(Vicewinder)) - { - // Swiftskin's Coil - if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) - return SwiftskinsCoil; - - // Hunter's Coil - if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) - return HuntersCoil; - } - } - return actionID; - } - } - - internal class VPR_VicepitDens : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_VicepitDens; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; - bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; - - if (actionID is Vicepit) - { - if (IsEnabled(CustomComboPreset.VPR_VicepitDens_oGCDs)) - { - if (HasEffect(Buffs.FellhuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.FellskinsVenom)) - return OriginalHook(Twinblood); - } - - if (SwiftskinsDenReady) - return HuntersDen; - - if (VicepitReady) - return SwiftskinsDen; - } - return actionID; - } - } - - internal class VPR_UncoiledTwins : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_UncoiledTwins; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is UncoiledFury) - { - if (HasEffect(Buffs.PoisedForTwinfang)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.PoisedForTwinblood)) - return OriginalHook(Twinblood); - } - return actionID; - } - } - - internal class VPR_ReawakenLegacy : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ReawakenLegacy; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - VPRGauge? gauge = GetJobGauge(); - int buttonChoice = Config.VPR_ReawakenLegacyButton; - - if ((buttonChoice is 0 && actionID is Reawaken && HasEffect(Buffs.Reawakened)) || - (buttonChoice is 1 && actionID is SteelFangs && HasEffect(Buffs.Reawakened))) - { - // Legacy Weaves - if (IsEnabled(CustomComboPreset.VPR_ReawakenLegacyWeaves) && - TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 4) - return OriginalHook(SteelFangs); - - if (gauge.AnguineTribute is 3) - return OriginalHook(ReavingFangs); - - if (gauge.AnguineTribute is 2) - return OriginalHook(HuntersCoil); - - if (gauge.AnguineTribute is 1) - return OriginalHook(SwiftskinsCoil); - } - - if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - { - if (gauge.AnguineTribute is 5) - return OriginalHook(SteelFangs); - - if (gauge.AnguineTribute is 4) - return OriginalHook(ReavingFangs); - - if (gauge.AnguineTribute is 3) - return OriginalHook(HuntersCoil); - - if (gauge.AnguineTribute is 2) - return OriginalHook(SwiftskinsCoil); - - if (gauge.AnguineTribute is 1) - return OriginalHook(Reawaken); - } - } - return actionID; - } - } - - internal class VPR_TwinTails : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_TwinTails; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is SerpentsTail) - { - // Death Rattle - if (LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) - return OriginalHook(SerpentsTail); - - // Legacy Weaves - if (TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - if (HasEffect(Buffs.PoisedForTwinfang)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.PoisedForTwinblood)) - return OriginalHook(Twinblood); - - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - - if (HasEffect(Buffs.FellhuntersVenom)) - return OriginalHook(Twinfang); - - if (HasEffect(Buffs.FellskinsVenom)) - return OriginalHook(Twinblood); - - } - return actionID; - } - } - } -} diff --git a/XIVSlothCombo/Combos/PvE/VPR/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR/VPR.cs new file mode 100644 index 000000000..2e448025d --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/VPR/VPR.cs @@ -0,0 +1,1182 @@ +using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; +using XIVSlothCombo.Combos.PvE.Content; +using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.Data; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class VPR +{ + public const byte JobID = 41; + + public const uint + ReavingFangs = 34607, + ReavingMaw = 34615, + Vicewinder = 34620, + HuntersCoil = 34621, + HuntersDen = 34624, + HuntersSnap = 39166, + Vicepit = 34623, + RattlingCoil = 39189, + Reawaken = 34626, + SerpentsIre = 34647, + SerpentsTail = 35920, + Slither = 34646, + SteelFangs = 34606, + SteelMaw = 34614, + SwiftskinsCoil = 34622, + SwiftskinsDen = 34625, + Twinblood = 35922, + Twinfang = 35921, + UncoiledFury = 34633, + WrithingSnap = 34632, + SwiftskinsSting = 34609, + TwinfangBite = 34636, + TwinbloodBite = 34637, + UncoiledTwinfang = 34644, + UncoiledTwinblood = 34645, + HindstingStrike = 34612, + DeathRattle = 34634, + HuntersSting = 34608, + HindsbaneFang = 34613, + FlankstingStrike = 34610, + FlanksbaneFang = 34611, + HuntersBite = 34616, + JaggedMaw = 34618, + SwiftskinsBite = 34617, + BloodiedMaw = 34619, + FirstGeneration = 34627, + FirstLegacy = 34640, + SecondGeneration = 34628, + SecondLegacy = 34641, + ThirdGeneration = 34629, + ThirdLegacy = 34642, + FourthGeneration = 34630, + FourthLegacy = 34643, + Ouroboros = 34631, + LastLash = 34635; + + protected static VPRGauge? gauge = GetJobGauge(); + + public static class Buffs + { + public const ushort + FellhuntersVenom = 3659, + FellskinsVenom = 3660, + FlanksbaneVenom = 3646, + FlankstungVenom = 3645, + HindstungVenom = 3647, + HindsbaneVenom = 3648, + GrimhuntersVenom = 3649, + GrimskinsVenom = 3650, + HuntersVenom = 3657, + SwiftskinsVenom = 3658, + HuntersInstinct = 3668, + Swiftscaled = 3669, + Reawakened = 3670, + ReadyToReawaken = 3671, + PoisedForTwinfang = 3665, + PoisedForTwinblood = 3666, + HonedReavers = 3772, + HonedSteel = 3672; + } + + public static class Debuffs + { + } + + public static class Traits + { + public const uint + EnhancedVipersRattle = 530, + EnhancedSerpentsLineage = 533, + SerpentsLegacy = 534; + } + + internal class VPR_ST_SimpleMode : CustomCombo + { + internal static VPROpenerLogic VPROpener = new(); + + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ST_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int RattlingCoils = gauge.RattlingCoilStacks; + float ireCD = GetCooldownRemainingTime(SerpentsIre); + + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); + bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; + bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; + bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; + bool in5y = GetTargetDistance() <= 5; + + bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || + (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); + float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; + + if (actionID is SteelFangs) + { + // Opener for VPR + if (VPROpener.DoFullOpener(ref actionID)) + return actionID; + + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + + //Serpents Ire - ForceWeave + if (InCombat() && CanWeave(UncoiledFury) && !CappedOnCoils && ActionReady(SerpentsIre)) + return SerpentsIre; + + //oGCDs + if (CanWeave(ActionWatching.LastWeaponskill)) + { + // Legacy Weaves + if (in5y && TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + // Fury Twin Weaves + if (HasEffect(Buffs.PoisedForTwinfang)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.PoisedForTwinblood)) + return OriginalHook(Twinblood); + + //Vice Twin Weaves + if (!HasEffect(Buffs.Reawakened)) + + //Vicewinder weaves + if (in5y) + { + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + } + } + + // Death Rattle - Force to avoid loss + if (in5y && LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) + return OriginalHook(SerpentsTail); + + //GCDs + if (LevelChecked(WrithingSnap) && !InMeleeRange() && HasBattleTarget()) + return VPRHelpers.HasRattlingCoilStack(gauge) + ? UncoiledFury + : WrithingSnap; + + //Vicewinder Combo + if (!HasEffect(Buffs.Reawakened) && LevelChecked(Vicewinder) && InMeleeRange()) + { + // Swiftskin's Coil + if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) + return SwiftskinsCoil; + + // Hunter's Coil + if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) + return HuntersCoil; + } + + //Reawakend Usage + if (VPRHelpers.UseReawaken(gauge)) + return Reawaken; + + //Overcap protection + if (CappedOnCoils && + ((HasCharges(Vicewinder) && !HasEffect(Buffs.SwiftskinsVenom) && + !HasEffect(Buffs.HuntersVenom) && + !HasEffect(Buffs.Reawakened)) || //spend if Vicewinder is up, after Reawaken + ireCD <= GCD * 5)) //spend in case under Reawaken right as Ire comes up + return UncoiledFury; + + //Vicewinder Usage + if (HasEffect(Buffs.Swiftscaled) && !VPRCheckTimers.IsComboExpiring(3) && + ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && + (ireCD >= GCD * 5 || !LevelChecked(SerpentsIre)) && + !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) + return Vicewinder; + + // Uncoiled Fury usage + if (LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && + HasEffect(Buffs.HuntersInstinct) && !VPRCheckTimers.IsComboExpiring(2) && + RattlingCoils > 1 && + !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && + !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && + !WasLastWeaponskill(Ouroboros) && + !VPRCheckTimers.IsEmpowermentExpiring(6) && !VPRCheckTimers.IsVenomExpiring(3) && + !VPRCheckTimers.IsHoningExpiring(3)) + return UncoiledFury; + + //Reawaken combo + if (HasEffect(Buffs.Reawakened)) + { + //Pre Ouroboros + if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 4: + return OriginalHook(SteelFangs); + + case 3: + return OriginalHook(ReavingFangs); + + case 2: + return OriginalHook(HuntersCoil); + + case 1: + return OriginalHook(SwiftskinsCoil); + } + + //With Ouroboros + if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 5: + return OriginalHook(SteelFangs); + + case 4: + return OriginalHook(ReavingFangs); + + case 3: + return OriginalHook(HuntersCoil); + + case 2: + return OriginalHook(SwiftskinsCoil); + + case 1: + return OriginalHook(Reawaken); + } + } + + //1-2-3 (4-5-6) Combo + if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) + { + if (lastComboMove is ReavingFangs or SteelFangs) + { + if (LevelChecked(HuntersSting) && + (HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.FlanksbaneVenom))) + return OriginalHook(SteelFangs); + + if (LevelChecked(SwiftskinsSting) && + (HasEffect(Buffs.HindstungVenom) || HasEffect(Buffs.HindsbaneVenom) || + (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) + return OriginalHook(ReavingFangs); + } + + if (lastComboMove is HuntersSting or SwiftskinsSting) + { + if ((HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.HindstungVenom)) && + LevelChecked(FlanksbaneFang)) + { + if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom)) + return All.TrueNorth; + + if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom)) + return All.TrueNorth; + + return OriginalHook(SteelFangs); + } + + if ((HasEffect(Buffs.FlanksbaneVenom) || HasEffect(Buffs.HindsbaneVenom)) && + LevelChecked(HindstingStrike)) + { + if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindsbaneVenom) && + CanDelayedWeave(actionID)) + return All.TrueNorth; + + if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlanksbaneVenom) && + CanDelayedWeave(actionID)) + return All.TrueNorth; + + return OriginalHook(ReavingFangs); + } + } + + if (lastComboMove is HindstingStrike or HindsbaneFang or FlankstingStrike or FlanksbaneFang) + return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingFangs) + : OriginalHook(SteelFangs); + } + + //LowLevels + return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingFangs) + : OriginalHook(SteelFangs); + } + + return actionID; + } + } + + internal class VPR_ST_AdvancedMode : CustomCombo + { + internal static VPROpenerLogic VPROpener = new(); + + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ST_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int uncoiledThreshold = Config.VPR_ST_UncoiledFury_Threshold; + int RattlingCoils = gauge.RattlingCoilStacks; + float enemyHP = GetTargetHPPercent(); + float ireCD = GetCooldownRemainingTime(SerpentsIre); + + bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); + bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; + bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; + bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; + bool in5y = GetTargetDistance() <= 5; + + bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || + (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); + float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; + + if (actionID is SteelFangs) + { + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + + // Opener for VPR + if (IsEnabled(CustomComboPreset.VPR_ST_Opener)) + if (VPROpener.DoFullOpener(ref actionID)) + return actionID; + + //Serpents Ire - MaxPrio oGCD, ForceWeave this in order to maintain raid buff upkeep or to avoid delay when inside RA + if (IsEnabled(CustomComboPreset.VPR_ST_SerpentsIre) && InCombat() && + CanWeave(UncoiledFury) && !CappedOnCoils && ActionReady(SerpentsIre)) + return SerpentsIre; + + //oGCDs + if (CanWeave(ActionWatching.LastWeaponskill)) + { + // Death Rattle + if (IsEnabled(CustomComboPreset.VPR_ST_SerpentsTail) && in5y && + LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) + return OriginalHook(SerpentsTail); + + // Legacy Weaves + if (IsEnabled(CustomComboPreset.VPR_ST_ReawakenCombo) && in5y && + TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + // Fury Twin Weaves + if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFuryCombo)) + { + if (HasEffect(Buffs.PoisedForTwinfang)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.PoisedForTwinblood)) + return OriginalHook(Twinblood); + } + + //Vice Twin Weaves + if (!HasEffect(Buffs.Reawakened)) + if (IsEnabled(CustomComboPreset.VPR_ST_CDs)) + + //Vicewinder weaves + if (IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && in5y) + { + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + } + } + + // Death Rattle - Force to avoid loss + if (IsEnabled(CustomComboPreset.VPR_ST_SerpentsTail) && in5y && + LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) + return OriginalHook(SerpentsTail); + + //GCDs + if (IsEnabled(CustomComboPreset.VPR_ST_RangedUptime) && + LevelChecked(WrithingSnap) && !InMeleeRange() && HasBattleTarget()) + return IsEnabled(CustomComboPreset.VPR_ST_RangedUptimeUncoiledFury) && + VPRHelpers.HasRattlingCoilStack(gauge) + ? UncoiledFury + : WrithingSnap; + + //Vicewinder Combo + if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && + IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && + !HasEffect(Buffs.Reawakened) && LevelChecked(Vicewinder) && InMeleeRange()) + { + // Swiftskin's Coil + if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) + return SwiftskinsCoil; + + // Hunter's Coil + if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) + return HuntersCoil; + } + + //Reawakend Usage + if (IsEnabled(CustomComboPreset.VPR_ST_Reawaken) && VPRHelpers.UseReawaken(gauge)) + return Reawaken; + + //Overcap protection + if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && CappedOnCoils && + ((HasCharges(Vicewinder) && !HasEffect(Buffs.SwiftskinsVenom) && !HasEffect(Buffs.HuntersVenom) && + !HasEffect(Buffs.Reawakened)) || //spend if Vicewinder is up, after Reawaken + ireCD <= GCD * 5)) //spend in case under Reawaken right as Ire comes up + return UncoiledFury; + + //Vicewinder Usage + if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && + IsEnabled(CustomComboPreset.VPR_ST_Vicewinder) && HasEffect(Buffs.Swiftscaled) && + !VPRCheckTimers.IsComboExpiring(3) && + ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && + (ireCD >= GCD * 5 || !LevelChecked(SerpentsIre)) && + !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) + return Vicewinder; + + // Uncoiled Fury usage + if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && !VPRCheckTimers.IsComboExpiring(2) && + LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + (RattlingCoils > Config.VPR_ST_UncoiledFury_HoldCharges || + (enemyHP < uncoiledThreshold && VPRHelpers.HasRattlingCoilStack(gauge))) && + !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && + !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && + !WasLastWeaponskill(Ouroboros) && + !VPRCheckTimers.IsEmpowermentExpiring(3)) + return UncoiledFury; + + //Reawaken combo + if (IsEnabled(CustomComboPreset.VPR_ST_ReawakenCombo) && + HasEffect(Buffs.Reawakened)) + { + //Pre Ouroboros + if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 4: + return OriginalHook(SteelFangs); + + case 3: + return OriginalHook(ReavingFangs); + + case 2: + return OriginalHook(HuntersCoil); + + case 1: + return OriginalHook(SwiftskinsCoil); + } + + //With Ouroboros + if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 5: + return OriginalHook(SteelFangs); + + case 4: + return OriginalHook(ReavingFangs); + + case 3: + return OriginalHook(HuntersCoil); + + case 2: + return OriginalHook(SwiftskinsCoil); + + case 1: + return OriginalHook(Reawaken); + } + } + + // healing + if (IsEnabled(CustomComboPreset.VPR_ST_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.VPR_ST_SecondWind_Threshold && ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= Config.VPR_ST_Bloodbath_Threshold && ActionReady(All.Bloodbath)) + return All.Bloodbath; + } + + //1-2-3 (4-5-6) Combo + if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) + { + if (lastComboMove is ReavingFangs or SteelFangs) + { + if (LevelChecked(HuntersSting) && + (HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.FlanksbaneVenom))) + return OriginalHook(SteelFangs); + + if (LevelChecked(SwiftskinsSting) && + (HasEffect(Buffs.HindstungVenom) || HasEffect(Buffs.HindsbaneVenom) || + (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) + return OriginalHook(ReavingFangs); + } + + if (lastComboMove is HuntersSting or SwiftskinsSting) + { + if ((HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.HindstungVenom)) && + LevelChecked(FlanksbaneFang)) + { + if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && + trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom)) + return All.TrueNorth; + + if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && + trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom)) + return All.TrueNorth; + + return OriginalHook(SteelFangs); + } + + if ((HasEffect(Buffs.FlanksbaneVenom) || HasEffect(Buffs.HindsbaneVenom)) && + LevelChecked(HindstingStrike)) + { + if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && + trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindsbaneVenom) && + CanDelayedWeave(actionID)) + return All.TrueNorth; + + if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && + trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlanksbaneVenom) && + CanDelayedWeave(actionID)) + return All.TrueNorth; + + return OriginalHook(ReavingFangs); + } + } + + if (lastComboMove is HindstingStrike or HindsbaneFang or FlankstingStrike or FlanksbaneFang) + return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingFangs) + : OriginalHook(SteelFangs); + } + + //LowLevels + return LevelChecked(ReavingFangs) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingFangs) + : OriginalHook(SteelFangs); + } + + return actionID; + } + } + + internal class VPR_AoE_Simplemode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_AoE_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int RattlingCoils = gauge.RattlingCoilStacks; + float ireCD = GetCooldownRemainingTime(SerpentsIre); + bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; + bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; + bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; + bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; + + bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || + (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); + float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; + + if (actionID is SteelMaw) + { + if (CanWeave(ActionWatching.LastWeaponskill)) + { + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + + // Death Rattle + if (LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is LastLash) + return OriginalHook(SerpentsTail); + + // Legacy Weaves + if (TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + // Uncoiled combo + if (HasEffect(Buffs.PoisedForTwinfang)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.PoisedForTwinblood)) + return OriginalHook(Twinblood); + + if (!HasEffect(Buffs.Reawakened)) + { + //Vicepit weaves + if (HasEffect(Buffs.FellhuntersVenom) && in5y) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.FellskinsVenom) && in5y) + return OriginalHook(Twinblood); + + //Serpents Ire usage + if (!CappedOnCoils && ActionReady(SerpentsIre)) + return SerpentsIre; + } + } + + //Vicepit combo + if (!HasEffect(Buffs.Reawakened) && in5y) + { + if (SwiftskinsDenReady) + return HuntersDen; + + if (VicepitReady) + return SwiftskinsDen; + } + + //Reawakend Usage + if ((HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && + HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + !HasEffect(Buffs.Reawakened) && in5y && + !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && + !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) + return Reawaken; + + //Overcap protection + if (((HasCharges(Vicepit) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.FellhuntersVenom)) || + ireCD <= GCD * 2) && !HasEffect(Buffs.Reawakened) && CappedOnCoils) + return UncoiledFury; + + //Vicepit Usage + if (ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && + (ireCD >= GCD * 5 || !LevelChecked(SerpentsIre)) && in5y) + return Vicepit; + + // Uncoiled Fury usage + if (LevelChecked(UncoiledFury) && + VPRHelpers.HasRattlingCoilStack(gauge) && + HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + !VicepitReady && !HuntersDenReady && !SwiftskinsDenReady && + !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellskinsVenom) && + !HasEffect(Buffs.FellhuntersVenom) && + !WasLastWeaponskill(JaggedMaw) && !WasLastWeaponskill(BloodiedMaw) && !WasLastAbility(SerpentsIre)) + return UncoiledFury; + + //Reawaken combo + if (HasEffect(Buffs.Reawakened)) + { + //Pre Ouroboros + if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 4: + return OriginalHook(SteelMaw); + + case 3: + return OriginalHook(ReavingMaw); + + case 2: + return OriginalHook(HuntersDen); + + case 1: + return OriginalHook(SwiftskinsDen); + } + + //With Ouroboros + if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 5: + return OriginalHook(SteelMaw); + + case 4: + return OriginalHook(ReavingMaw); + + case 3: + return OriginalHook(HuntersDen); + + case 2: + return OriginalHook(SwiftskinsDen); + + case 1: + return OriginalHook(Reawaken); + } + } + + // healing + if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.Bloodbath)) + return All.Bloodbath; + + //1-2-3 (4-5-6) Combo + if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) + { + if (lastComboMove is ReavingMaw or SteelMaw) + { + if (LevelChecked(HuntersBite) && + HasEffect(Buffs.GrimhuntersVenom)) + return OriginalHook(SteelMaw); + + if (LevelChecked(SwiftskinsBite) && + (HasEffect(Buffs.GrimskinsVenom) || + (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) + return OriginalHook(ReavingMaw); + } + + if (lastComboMove is HuntersBite or SwiftskinsBite) + { + if (HasEffect(Buffs.GrimhuntersVenom) && LevelChecked(JaggedMaw)) + return OriginalHook(SteelMaw); + + if (HasEffect(Buffs.GrimskinsVenom) && LevelChecked(BloodiedMaw)) + return OriginalHook(ReavingMaw); + } + + if (lastComboMove is BloodiedMaw or JaggedMaw) + return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingMaw) + : OriginalHook(SteelMaw); + } + + //for lower lvls + return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingMaw) + : OriginalHook(SteelMaw); + } + + return actionID; + } + } + + internal class VPR_AoE_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_AoE_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int uncoiledThreshold = Config.VPR_AoE_UncoiledFury_Threshold; + int RattlingCoils = gauge.RattlingCoilStacks; + float enemyHP = GetTargetHPPercent(); + float ireCD = GetCooldownRemainingTime(SerpentsIre); + bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; + bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; + bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; + bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; + + bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || + (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); + float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; + + if (actionID is SteelMaw) + { + // Variant Cure + if (IsEnabled(CustomComboPreset.VPR_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.VPR_VariantCure)) + return Variant.VariantCure; + + // Variant Rampart + if (IsEnabled(CustomComboPreset.VPR_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanWeave(ActionWatching.LastWeaponskill)) + return Variant.VariantRampart; + + if (CanWeave(ActionWatching.LastWeaponskill)) + { + // Death Rattle + if (IsEnabled(CustomComboPreset.VPR_AoE_SerpentsTail) && + LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is LastLash) + return OriginalHook(SerpentsTail); + + // Legacy Weaves + if (IsEnabled(CustomComboPreset.VPR_AoE_ReawakenCombo) && + TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + // Uncoiled combo + if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFuryCombo)) + { + if (HasEffect(Buffs.PoisedForTwinfang)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.PoisedForTwinblood)) + return OriginalHook(Twinblood); + } + + if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && + !HasEffect(Buffs.Reawakened)) + { + //Vicepit weaves + if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) + { + if (HasEffect(Buffs.FellhuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.FellskinsVenom)) + return OriginalHook(Twinblood); + } + + //Serpents Ire usage + if (IsEnabled(CustomComboPreset.VPR_AoE_SerpentsIre) && + !CappedOnCoils && ActionReady(SerpentsIre)) + return SerpentsIre; + } + } + + //Vicepit combo + if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && + IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && + !HasEffect(Buffs.Reawakened) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) + { + if (SwiftskinsDenReady) + return HuntersDen; + + if (VicepitReady) + return SwiftskinsDen; + } + + //Reawakend Usage + if (IsEnabled(CustomComboPreset.VPR_AoE_Reawaken) && + (HasEffect(Buffs.ReadyToReawaken) || gauge.SerpentOffering >= 50) && LevelChecked(Reawaken) && + HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + !HasEffect(Buffs.Reawakened) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_Reawaken_DisableRange)) && + !HasEffect(Buffs.FellhuntersVenom) && !HasEffect(Buffs.FellskinsVenom) && + !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang)) + return Reawaken; + + //Overcap protection + if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFury) && + ((HasCharges(Vicepit) && !HasEffect(Buffs.FellskinsVenom) && !HasEffect(Buffs.FellhuntersVenom)) || + ireCD <= GCD * 2) && !HasEffect(Buffs.Reawakened) && CappedOnCoils) + return UncoiledFury; + + //Vicepit Usage + if (IsEnabled(CustomComboPreset.VPR_AoE_CDs) && + IsEnabled(CustomComboPreset.VPR_AoE_Vicepit) && + ActionReady(Vicepit) && !HasEffect(Buffs.Reawakened) && + (in5y || IsEnabled(CustomComboPreset.VPR_AoE_Vicepit_DisableRange)) && + (ireCD >= GCD * 5 || !LevelChecked(SerpentsIre))) + return Vicepit; + + // Uncoiled Fury usage + if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFury) && + LevelChecked(UncoiledFury) && + (RattlingCoils > Config.VPR_AoE_UncoiledFury_HoldCharges || + (enemyHP < uncoiledThreshold && VPRHelpers.HasRattlingCoilStack(gauge))) && + HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + !VicepitReady && !HuntersDenReady && !SwiftskinsDenReady && + !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellskinsVenom) && + !HasEffect(Buffs.FellhuntersVenom) && + !WasLastWeaponskill(JaggedMaw) && !WasLastWeaponskill(BloodiedMaw) && !WasLastAbility(SerpentsIre)) + return UncoiledFury; + + //Reawaken combo + if (IsEnabled(CustomComboPreset.VPR_AoE_ReawakenCombo) && + HasEffect(Buffs.Reawakened)) + { + //Pre Ouroboros + if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 4: + return OriginalHook(SteelMaw); + + case 3: + return OriginalHook(ReavingMaw); + + case 2: + return OriginalHook(HuntersDen); + + case 1: + return OriginalHook(SwiftskinsDen); + } + + //With Ouroboros + if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 5: + return OriginalHook(SteelMaw); + + case 4: + return OriginalHook(ReavingMaw); + + case 3: + return OriginalHook(HuntersDen); + + case 2: + return OriginalHook(SwiftskinsDen); + + case 1: + return OriginalHook(Reawaken); + } + } + + // healing + if (IsEnabled(CustomComboPreset.VPR_AoE_ComboHeals)) + { + if (PlayerHealthPercentageHp() <= Config.VPR_AoE_SecondWind_Threshold && + ActionReady(All.SecondWind)) + return All.SecondWind; + + if (PlayerHealthPercentageHp() <= Config.VPR_AoE_Bloodbath_Threshold && ActionReady(All.Bloodbath)) + return All.Bloodbath; + } + + //1-2-3 (4-5-6) Combo + if (comboTime > 0 && !HasEffect(Buffs.Reawakened)) + { + if (lastComboMove is ReavingMaw or SteelMaw) + { + if (LevelChecked(HuntersBite) && + HasEffect(Buffs.GrimhuntersVenom)) + return OriginalHook(SteelMaw); + + if (LevelChecked(SwiftskinsBite) && + (HasEffect(Buffs.GrimskinsVenom) || + (!HasEffect(Buffs.Swiftscaled) && !HasEffect(Buffs.HuntersInstinct)))) + return OriginalHook(ReavingMaw); + } + + if (lastComboMove is HuntersBite or SwiftskinsBite) + { + if (HasEffect(Buffs.GrimhuntersVenom) && LevelChecked(JaggedMaw)) + return OriginalHook(SteelMaw); + + if (HasEffect(Buffs.GrimskinsVenom) && LevelChecked(BloodiedMaw)) + return OriginalHook(ReavingMaw); + } + + if (lastComboMove is BloodiedMaw or JaggedMaw) + return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingMaw) + : OriginalHook(SteelMaw); + } + + //for lower lvls + return LevelChecked(ReavingMaw) && HasEffect(Buffs.HonedReavers) + ? OriginalHook(ReavingMaw) + : OriginalHook(SteelMaw); + } + + return actionID; + } + } + + internal class VPR_VicewinderCoils : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_VicewinderCoils; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; + bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; + bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; + + if (actionID is Vicewinder) + { + if (IsEnabled(CustomComboPreset.VPR_VicewinderCoils_oGCDs)) + { + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + } + + // Vicewinder Combo + if (LevelChecked(Vicewinder)) + { + // Swiftskin's Coil + if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) + return SwiftskinsCoil; + + // Hunter's Coil + if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) + return HuntersCoil; + } + } + + return actionID; + } + } + + internal class VPR_VicepitDens : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_VicepitDens; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; + bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; + + if (actionID is Vicepit) + { + if (IsEnabled(CustomComboPreset.VPR_VicepitDens_oGCDs)) + { + if (HasEffect(Buffs.FellhuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.FellskinsVenom)) + return OriginalHook(Twinblood); + } + + if (SwiftskinsDenReady) + return HuntersDen; + + if (VicepitReady) + return SwiftskinsDen; + } + + return actionID; + } + } + + internal class VPR_UncoiledTwins : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_UncoiledTwins; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is UncoiledFury) + { + if (HasEffect(Buffs.PoisedForTwinfang)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.PoisedForTwinblood)) + return OriginalHook(Twinblood); + } + + return actionID; + } + } + + internal class VPR_ReawakenLegacy : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ReawakenLegacy; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int buttonChoice = Config.VPR_ReawakenLegacyButton; + + if ((buttonChoice is 0 && actionID is Reawaken && HasEffect(Buffs.Reawakened)) || + (buttonChoice is 1 && actionID is SteelFangs && HasEffect(Buffs.Reawakened))) + { + // Legacy Weaves + if (IsEnabled(CustomComboPreset.VPR_ReawakenLegacyWeaves) && + TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 4: + return OriginalHook(SteelFangs); + + case 3: + return OriginalHook(ReavingFangs); + + case 2: + return OriginalHook(HuntersCoil); + + case 1: + return OriginalHook(SwiftskinsCoil); + } + + if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 5: + return OriginalHook(SteelFangs); + + case 4: + return OriginalHook(ReavingFangs); + + case 3: + return OriginalHook(HuntersCoil); + + case 2: + return OriginalHook(SwiftskinsCoil); + + case 1: + return OriginalHook(Reawaken); + } + } + + return actionID; + } + } + + internal class VPR_TwinTails : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_TwinTails; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is SerpentsTail) + { + // Death Rattle + if (LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) + return OriginalHook(SerpentsTail); + + // Legacy Weaves + if (TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + if (HasEffect(Buffs.PoisedForTwinfang)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.PoisedForTwinblood)) + return OriginalHook(Twinblood); + + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + + if (HasEffect(Buffs.FellhuntersVenom)) + return OriginalHook(Twinfang); + + if (HasEffect(Buffs.FellskinsVenom)) + return OriginalHook(Twinblood); + } + + return actionID; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/VPR/VPR_Config.cs b/XIVSlothCombo/Combos/PvE/VPR/VPR_Config.cs new file mode 100644 index 000000000..45f87df03 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/VPR/VPR_Config.cs @@ -0,0 +1,90 @@ +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class VPR +{ + internal static class Config + { + public static UserInt + VPR_ST_SecondWind_Threshold = new("VPR_ST_SecondWindThreshold", 25), + VPR_ST_Bloodbath_Threshold = new("VPR_ST_BloodbathThreshold", 40), + VPR_AoE_SecondWind_Threshold = new("VPR_AoE_SecondWindThreshold", 25), + VPR_AoE_Bloodbath_Threshold = new("VPR_AoE_BloodbathThreshold", 40), + VPR_ST_UncoiledFury_HoldCharges = new("VPR_ST_UncoiledFury_HoldCharges", 1), + VPR_AoE_UncoiledFury_HoldCharges = new("VPR_AoE_UncoiledFury_HoldCharges", 0), + VPR_ST_UncoiledFury_Threshold = new("VPR_ST_UncoiledFury_Threshold", 1), + VPR_AoE_UncoiledFury_Threshold = new("VPR_AoE_UncoiledFury_Threshold", 1), + VPR_ReawakenLegacyButton = new("VPR_ReawakenLegacyButton"), + VPR_VariantCure = new("VPR_VariantCure"); + + public static UserFloat + VPR_ST_Reawaken_Usage = new("VPR_ST_Reawaken_Usage", 2), + VPR_AoE_Reawaken_Usage = new("VPR_AoE_Reawaken_Usage", 2); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.VPR_ST_UncoiledFury: + DrawSliderInt(0, 3, VPR_ST_UncoiledFury_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + DrawSliderInt(0, 5, VPR_ST_UncoiledFury_Threshold, "Set a HP% Threshold to use all charges."); + + break; + + case CustomComboPreset.VPR_AoE_UncoiledFury: + DrawSliderInt(0, 3, VPR_AoE_UncoiledFury_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + DrawSliderInt(0, 5, VPR_AoE_UncoiledFury_Threshold, "Set a HP% Threshold to use all charges."); + + break; + + case CustomComboPreset.VPR_ST_Reawaken: + DrawRoundedSliderFloat(0, 10, VPR_ST_Reawaken_Usage, + "Stop using at Enemy HP %. Set to Zero to disable this check.", digits: 1); + + break; + + case CustomComboPreset.VPR_AoE_Reawaken: + DrawRoundedSliderFloat(0, 10, VPR_AoE_Reawaken_Usage, + "Stop using at Enemy HP %. Set to Zero to disable this check.", digits: 1); + + break; + + case CustomComboPreset.VPR_ST_ComboHeals: + DrawSliderInt(0, 100, VPR_ST_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)"); + + DrawSliderInt(0, 100, VPR_ST_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)"); + + break; + + case CustomComboPreset.VPR_AoE_ComboHeals: + DrawSliderInt(0, 100, VPR_AoE_SecondWind_Threshold, + "Second Wind HP percentage threshold (0 = Disabled)"); + + DrawSliderInt(0, 100, VPR_AoE_Bloodbath_Threshold, + "Bloodbath HP percentage threshold (0 = Disabled)"); + + break; + + case CustomComboPreset.VPR_ReawakenLegacy: + DrawRadioButton(VPR_ReawakenLegacyButton, "Replaces Reawaken", + "Replaces Reawaken with Full Generation - Legacy combo.", 0); + + DrawRadioButton(VPR_ReawakenLegacyButton, "Replaces Steel Fangs", + "Replaces Steel Fangs with Full Generation - Legacy combo.", 1); + + break; + + case CustomComboPreset.VPR_Variant_Cure: + DrawSliderInt(1, 100, VPR_VariantCure, "HP% to be at or under", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs b/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs new file mode 100644 index 000000000..ba6fd1522 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs @@ -0,0 +1,326 @@ +using Dalamud.Game.ClientState.JobGauge.Types; +using ECommons.DalamudServices; +using FFXIVClientStructs.FFXIV.Client.Game; +using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Data; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class VPR +{ + internal class VPROpenerLogic + { + private OpenerState currentState = OpenerState.PrePull; + + public uint OpenerStep; + + public uint PrePullStep; + + private static uint OpenerLevel => 100; + + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState + { + get => currentState; + set + { + if (value != currentState) + { + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + + currentState = value; + } + } + } + + private static bool HasCooldowns() + { + if (GetRemainingCharges(Vicewinder) < 2) + return false; + + if (!ActionReady(SerpentsIre)) + return false; + + return true; + } + + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) + return false; + + if (CanOpener && PrePullStep == 0) PrePullStep = 1; + + if (!HasCooldowns()) PrePullStep = 0; + + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) + { + if (WasLastAction(ReavingFangs) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = ReavingFangs; + + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; + + return true; + } + PrePullStep = 0; + + return false; + } + + private bool DoOpener(ref uint actionID) + { + if (!LevelChecked) + return false; + + if (currentState == OpenerState.InOpener) + { + if (WasLastAction(SerpentsIre) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = SerpentsIre; + + if (WasLastAction(SwiftskinsSting) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = SwiftskinsSting; + + if (WasLastAction(Vicewinder) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = Vicewinder; + + if (WasLastAction(HuntersCoil) && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = HuntersCoil; + + if (WasLastAction(TwinfangBite) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = TwinfangBite; + + if (WasLastAction(TwinbloodBite) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = TwinbloodBite; + + if (WasLastAction(SwiftskinsCoil) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = SwiftskinsCoil; + + if (WasLastAction(TwinbloodBite) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = TwinbloodBite; + + if (WasLastAction(TwinfangBite) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = TwinfangBite; + + if (WasLastAction(Reawaken) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = Reawaken; + + if (WasLastAction(FirstGeneration) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = FirstGeneration; + + if (WasLastAction(FirstLegacy) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = FirstLegacy; + + if (WasLastAction(SecondGeneration) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = SecondGeneration; + + if (WasLastAction(SecondLegacy) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = SecondLegacy; + + if (WasLastAction(ThirdGeneration) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = ThirdGeneration; + + if (WasLastAction(ThirdLegacy) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = ThirdLegacy; + + if (WasLastAction(FourthGeneration) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = FourthGeneration; + + if (WasLastAction(FourthLegacy) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = FourthLegacy; + + if (WasLastAction(Ouroboros) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = Ouroboros; + + if (WasLastAction(UncoiledFury) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = UncoiledFury; + + if (WasLastAction(UncoiledTwinfang) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = UncoiledTwinfang; + + if (WasLastAction(UncoiledTwinblood) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = UncoiledTwinblood; + + if (WasLastAction(UncoiledFury) && OpenerStep == 23) OpenerStep++; + else if (OpenerStep == 23) actionID = UncoiledFury; + + if (WasLastAction(UncoiledTwinfang) && OpenerStep == 24) OpenerStep++; + else if (OpenerStep == 24) actionID = UncoiledTwinfang; + + if (WasLastAction(UncoiledTwinblood) && OpenerStep == 25) OpenerStep++; + else if (OpenerStep == 25) actionID = UncoiledTwinblood; + + if (WasLastAction(HindstingStrike) && OpenerStep == 26) OpenerStep++; + else if (OpenerStep == 26) actionID = HindstingStrike; + + if (WasLastAction(DeathRattle) && OpenerStep == 27) OpenerStep++; + else if (OpenerStep == 27) actionID = DeathRattle; + + if (WasLastAction(Vicewinder) && OpenerStep == 28) OpenerStep++; + else if (OpenerStep == 28) actionID = Vicewinder; + + if (WasLastAction(UncoiledFury) && OpenerStep == 29) OpenerStep++; + else if (OpenerStep == 29) actionID = UncoiledFury; + + if (WasLastAction(UncoiledTwinfang) && OpenerStep == 30) OpenerStep++; + else if (OpenerStep == 30) actionID = UncoiledTwinfang; + + if (WasLastAction(UncoiledTwinblood) && OpenerStep == 31) OpenerStep++; + else if (OpenerStep == 31) actionID = UncoiledTwinblood; + + if (WasLastAction(HuntersCoil) && OpenerStep == 32) OpenerStep++; + else if (OpenerStep == 32) actionID = HuntersCoil; + + if (WasLastAction(TwinfangBite) && OpenerStep == 33) OpenerStep++; + else if (OpenerStep == 33) actionID = TwinfangBite; + + if (WasLastAction(TwinbloodBite) && OpenerStep == 34) OpenerStep++; + else if (OpenerStep == 34) actionID = TwinbloodBite; + + if (WasLastAction(SwiftskinsCoil) && OpenerStep == 35) OpenerStep++; + else if (OpenerStep == 35) actionID = SwiftskinsCoil; + + if (WasLastAction(TwinbloodBite) && OpenerStep == 36) OpenerStep++; + else if (OpenerStep == 36) actionID = TwinbloodBite; + + if (WasLastAction(TwinfangBite) && OpenerStep == 37) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 37) actionID = TwinfangBite; + + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if (((actionID == SerpentsIre && IsOnCooldown(SerpentsIre)) || + (actionID == Vicewinder && GetRemainingCharges(Vicewinder) < 2)) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + CurrentState = OpenerState.FailedOpener; + + return false; + } + + return true; + } + + return false; + } + + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } + + public bool DoFullOpener(ref uint actionID) + { + if (!LevelChecked) + return false; + + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; + + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID)) + return true; + + if (!InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; + } + + return false; + } + } + + internal class VPRCheckTimers + { + public static bool IsHoningExpiring(float Times) + { + float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; + + if ((HasEffect(Buffs.HonedSteel) && GetBuffRemainingTime(Buffs.HonedSteel) < GCD) || + (HasEffect(Buffs.HonedReavers) && GetBuffRemainingTime(Buffs.HonedReavers) < GCD)) + return true; + + return false; + } + + public static bool IsVenomExpiring(float Times) + { + float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; + + if ((HasEffect(Buffs.FlankstungVenom) && GetBuffRemainingTime(Buffs.FlankstungVenom) < GCD) || + (HasEffect(Buffs.FlanksbaneVenom) && GetBuffRemainingTime(Buffs.FlanksbaneVenom) < GCD) || + (HasEffect(Buffs.HindstungVenom) && GetBuffRemainingTime(Buffs.HindstungVenom) < GCD) || + (HasEffect(Buffs.HindsbaneVenom) && GetBuffRemainingTime(Buffs.HindsbaneVenom) < GCD)) + return true; + + return false; + } + + public static bool IsEmpowermentExpiring(float Times) + { + float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; + + if (GetBuffRemainingTime(Buffs.Swiftscaled) < GCD || GetBuffRemainingTime(Buffs.HuntersInstinct) < GCD) + return true; + + return false; + } + + public static unsafe bool IsComboExpiring(float Times) + { + float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; + + if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) + return true; + + return false; + } + } + + internal class VPRHelpers + { + public static bool HasRattlingCoilStack(VPRGauge gauge) + { + if (gauge.RattlingCoilStacks > 0) + return true; + + return false; + } + + internal static bool UseReawaken(VPRGauge gauge) + { + float ireCD = GetCooldownRemainingTime(SerpentsIre); + + if (LevelChecked(Reawaken) && !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && + !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.SwiftskinsVenom) && + !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang) && + !VPRCheckTimers.IsEmpowermentExpiring(6)) + if ((!JustUsed(SerpentsIre, 2.2f) && HasEffect(Buffs.ReadyToReawaken)) || //2min burst + (WasLastWeaponskill(Ouroboros) && gauge.SerpentOffering >= 50 && ireCD >= 50) || //2nd RA + (gauge.SerpentOffering is >= 50 and <= 80 && ireCD is >= 50 and <= 62) || //1min + gauge.SerpentOffering >= 100 || //overcap + (gauge.SerpentOffering >= 50 && WasLastWeaponskill(FourthGeneration) && + !LevelChecked(Ouroboros))) //<100 + return true; + + return false; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..12938929e 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -2414,59 +2414,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region VIPER - /* if ((preset == CustomComboPreset.VPR_ST_AdvancedMode && enabled) || (preset == CustomComboPreset.VPR_VicewinderCoils && enabled)) - { - UserConfig.DrawHorizontalRadioButton(VPR.Config.VPR_Positional, "Rear First", "First positional: Swiftskin's Coil.", 0); - UserConfig.DrawHorizontalRadioButton(VPR.Config.VPR_Positional, "Flank First", "First positional: Hunter's Coil.", 1); - }*/ - - if (preset == CustomComboPreset.VPR_ST_UncoiledFury && enabled) - { - UserConfig.DrawSliderInt(0, 3, VPR.Config.VPR_ST_UncoiledFury_HoldCharges, "How many charges to keep ready? (0 = Use all)"); - UserConfig.DrawSliderInt(0, 5, VPR.Config.VPR_ST_UncoiledFury_Threshold, "Set a HP% Threshold to use all charges."); - } - - if (preset == CustomComboPreset.VPR_AoE_UncoiledFury && enabled) - { - UserConfig.DrawSliderInt(0, 3, VPR.Config.VPR_AoE_UncoiledFury_HoldCharges, "How many charges to keep ready? (0 = Use all)"); - UserConfig.DrawSliderInt(0, 5, VPR.Config.VPR_AoE_UncoiledFury_Threshold, "Set a HP% Threshold to use all charges."); - } - - - if (preset is CustomComboPreset.VPR_ST_Reawaken) - { - UserConfig.DrawRoundedSliderFloat(0, 10, VPR.Config.VPR_ST_Reawaken_Usage, "Stop using at Enemy HP %. Set to Zero to disable this check.", digits: 1); - } - - if (preset is CustomComboPreset.VPR_AoE_Reawaken) - { - UserConfig.DrawRoundedSliderFloat(0, 10, VPR.Config.VPR_AoE_Reawaken_Usage, "Stop using at Enemy HP %. Set to Zero to disable this check.", digits: 1); - } - - if (preset == CustomComboPreset.VPR_ST_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, VPR.Config.VPR_ST_SecondWind_Threshold, "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, VPR.Config.VPR_ST_Bloodbath_Threshold, "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.VPR_AoE_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, VPR.Config.VPR_AoE_SecondWind_Threshold, "Second Wind HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, VPR.Config.VPR_AoE_Bloodbath_Threshold, "Bloodbath HP percentage threshold (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.VPR_ReawakenLegacy && enabled) - { - UserConfig.DrawRadioButton(VPR.Config.VPR_ReawakenLegacyButton, "Replaces Reawaken", "Replaces Reawaken with Full Generation - Legacy combo.", 0); - UserConfig.DrawRadioButton(VPR.Config.VPR_ReawakenLegacyButton, "Replaces Steel Fangs", "Replaces Steel Fangs with Full Generation - Legacy combo.", 1); - } - - if (preset == CustomComboPreset.VPR_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, VPR.Config.VPR_VariantCure, "HP% to be at or under", 200); - - #endregion // ==================================================================================== #region WARRIOR From 74b679bb968d28f48b8193efba9b109828d59b9f Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 13:23:41 -0500 Subject: [PATCH 152/208] Added shield checking to GetTargetHPPercent --- XIVSlothCombo/CustomCombo/Functions/Target.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 51161676a..78b26c199 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -66,7 +66,7 @@ public static bool InMeleeRange() /// Gets a value indicating target's HP Percent. CurrentTarget is default unless specified /// Double indicating percentage. - public static float GetTargetHPPercent(IGameObject? OurTarget = null) + public static float GetTargetHPPercent(IGameObject? OurTarget = null, bool includeShield = false) { if (OurTarget is null) { @@ -75,9 +75,13 @@ public static float GetTargetHPPercent(IGameObject? OurTarget = null) return 0; } - return OurTarget is not IBattleChara chara - ? 0 - : (float)chara.CurrentHp / chara.MaxHp * 100; + if (OurTarget is IBattleChara chara) + { + float percent = (float)chara.CurrentHp / chara.MaxHp * 100f; + if (includeShield) percent += chara.ShieldPercentage; + return percent; + } + else return 0; } public static float EnemyHealthMaxHp() From a7a3d9d301c288a0326330c52484e2dce134a977 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 14:38:23 -0500 Subject: [PATCH 153/208] Added userconfig splitup base code electric boogaloo --- XIVSlothCombo/Window/Functions/Presets.cs | 38 ++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 37894fb87..8bd21274d 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -11,6 +11,7 @@ using System.Text; using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Core; using XIVSlothCombo.Data; using XIVSlothCombo.Services; @@ -264,12 +265,41 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo } ImGui.PopStyleColor(); } - - UserConfigItems.Draw(preset, enabled); + if (enabled) + { + switch (info.JobID) + { + //case All.JobID: All.Config.Draw(preset); break; + //case AST.JobID: AST.Config.Draw(preset); break; + //case BLM.JobID: BLM.Config.Draw(preset); break; + //case BLU.JobID: BLU.Config.Draw(preset); break; + //case BRD.JobID: BRD.Config.Draw(preset); break; + //case DNC.JobID: DNC.Config.Draw(preset); break; + //case DOL.JobID: DOL.Config.Draw(preset); break; + //case DRG.JobID: DRG.Config.Draw(preset); break; + //case DRK.JobID: DRK.Config.Draw(preset); break; + //case GNB.JobID: GNB.Config.Draw(preset); break; + //case MCH.JobID: MCH.Config.Draw(preset); break; + //case MNK.JobID: MNK.Config.Draw(preset); break; + //case NIN.JobID: NIN.Config.Draw(preset); break; + //case PCT.JobID: PCT.Config.Draw(preset); break; + //case PLD.JobID: PLD.Config.Draw(preset); break; + //case RPR.JobID: RPR.Config.Draw(preset); break; + //case RDM.JobID: RDM.Config.Draw(preset); break; + //case SAM.JobID: SAM.Config.Draw(preset); break; + //case SCH.JobID: SCH.Config.Draw(preset); break; + //case SGE.JobID: SGE.Config.Draw(preset); break; + //case SMN.JobID: SMN.Config.Draw(preset); break; + //case VPR.JobID: VPR.Config.Draw(preset); break; + //case WAR.JobID: WAR.Config.Draw(preset); break; + //case WHM.JobID: WHM.Config.Draw(preset); break; + default: UserConfigItems.Draw(preset, enabled); break; + } + } i++; - var children = presetChildren.ContainsKey(preset) ? presetChildren[preset] : null; + presetChildren.TryGetValue(preset, out var children); if (children != null) { @@ -379,4 +409,4 @@ private static void EnableParentPresets(CustomComboPreset preset) } } } -} +} \ No newline at end of file From 30ba1b7dd6a4dc7acf6a45be0fdca0c7d35b92c1 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 14:52:01 -0500 Subject: [PATCH 154/208] Added additional heals to Single and AoE heals - Single Heals - Adloquium was ignoring shield checking. Ignoring Shield Checking now an user option like Sage - Added Aetherpact - Added Option to include Shield HP in HP Percent Sliders - AoE Heals - Added Fey Illumination, Whispering Dawn, Seraphism, Fey Blessing, and Consolation with priority Debug: Added HP% and Shield Percent --- XIVSlothCombo/Combos/CustomComboPreset.cs | 62 ++++++++++++------ XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 9 ++- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 46 ++++++++++++-- XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 74 +++++++++++----------- XIVSlothCombo/Window/Tabs/Debug.cs | 2 + 5 files changed, 129 insertions(+), 64 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 699bd7ef8..351e7dd7c 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3937,25 +3937,45 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("AoE Heal Feature", "Replaces Succor with options below:", SCH.JobID, 5)] SCH_AoE_Heal = 16018, - [ParentCombo(SCH_AoE_Heal)] - [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming when MP isn't high enough to cast Succor.", SCH.JobID)] - SCH_AoE_Heal_Lucid = 16019, - - [ParentCombo(SCH_AoE_Heal)] - [CustomComboInfo("Aetherflow Option", "Use Aetherflow when out of Aetherflow stacks.", SCH.JobID)] - SCH_AoE_Heal_Aetherflow = 16020, - - [ParentCombo(SCH_AoE_Heal_Aetherflow)] - [CustomComboInfo("Indomitability Ready Only Option", "Only uses Aetherflow is Indomitability is ready to use.", SCH.JobID)] - SCH_AoE_Heal_Aetherflow_Indomitability = 16021, - - [ParentCombo(SCH_AoE_Heal)] - [CustomComboInfo("Disspation Option", "Use Dissipation when out of Aetherflow stacks.", SCH.JobID)] - SCH_AoE_Heal_Dissipation = 16041, + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Lucid Dreaming Option", "Adds Lucid Dreaming when MP isn't high enough to cast Succor.", SCH.JobID)] + SCH_AoE_Heal_Lucid = 16019, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Aetherflow Option", "Use Aetherflow when out of Aetherflow stacks.", SCH.JobID)] + SCH_AoE_Heal_Aetherflow = 16020, + + [ParentCombo(SCH_AoE_Heal_Aetherflow)] + [CustomComboInfo("Indomitability Ready Only Option", "Only uses Aetherflow is Indomitability is ready to use.", SCH.JobID)] + SCH_AoE_Heal_Aetherflow_Indomitability = 16021, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Disspation Option", "Use Dissipation when out of Aetherflow stacks.", SCH.JobID)] + SCH_AoE_Heal_Dissipation = 16041, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Indomitability Option", "Use Indomitability before using Succor.", SCH.JobID)] + SCH_AoE_Heal_Indomitability = 16022, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Fey Illumination Option", "Use Fey Illumination before using Succor.", SCH.JobID)] + SCH_AoE_Heal_FeyIllumination = 16042, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Whispering Dawn Option", "Use Whispering Dawn before using Succor.", SCH.JobID)] + SCH_AoE_Heal_WhisperingDawn = 16043, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Seraphism Option", "Use Seraphism before using Succor.", SCH.JobID)] + SCH_AoE_Heal_Seraphism = 16044, + + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Fey Blessing Option", "Use Fey Blessing before using Succor.", SCH.JobID)] + SCH_AoE_Heal_FeyBlessing = 16045, - [ParentCombo(SCH_AoE_Heal)] - [CustomComboInfo("Indomitability Option", "Use Indomitability before using Succor.", SCH.JobID)] - SCH_AoE_Heal_Indomitability = 16022, + [ParentCombo(SCH_AoE_Heal)] + [CustomComboInfo("Consolation", "Use Consolation before using Succor.", SCH.JobID)] + SCH_AoE_Heal_Consolation = 16046, [AutoAction(false, true)] [ReplaceSkill(SCH.Physick)] @@ -3994,6 +4014,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Protraction Option", "Use Protraction when target HP%% below:", SCH.JobID, 8)] SCH_ST_Heal_Protraction = 16039, + [ParentCombo(SCH_ST_Heal)] + [CustomComboInfo("Aetherpact Option", "Use Aetherpact when target HP%% below:", SCH.JobID, 8)] + SCH_ST_Heal_Aetherpact = 16047, + #endregion @@ -4039,7 +4063,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion - // Last value = 16041 + // Last value = 16047 #endregion diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 7b6f6ec93..13f72ea14 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -27,6 +27,7 @@ internal const uint Consolation = 16546, Resurrection = 173, Protraction = 25867, + Seraphism = 37014, // Offense Bio = 17864, @@ -520,7 +521,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Esuna) && ActionReady(All.Esuna) && - GetTargetHPPercent(healTarget) >= Config.SCH_ST_Heal_EsunaOption && + GetTargetHPPercent(healTarget,true) >= Config.SCH_ST_Heal_EsunaOption && HasCleansableDebuff(healTarget)) return All.Esuna; @@ -531,7 +532,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (enabled) { - if (GetTargetHPPercent(healTarget) <= config && + if (GetTargetHPPercent(healTarget,true) <= config && ActionReady(spell)) return spell; } @@ -540,7 +541,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && - (FindEffectOnMember(Buffs.Galvanize, healTarget) is null || GetTargetHPPercent(healTarget) <= Config.SCH_ST_Heal_AdloquiumOption)) + GetTargetHPPercent(healTarget,true) <= Config.SCH_ST_Heal_AdloquiumOption && + (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check + (!Config.SCH_ST_Heal_AldoquimOpts[1] || FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null)) //EDiagnosis Check { return OriginalHook(Adloquium); } diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 84bda713a..1a7097727 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -3,6 +3,7 @@ using static XIVSlothCombo.Extensions.UIntExtensions; using static XIVSlothCombo.Window.Functions.UserConfig; using static XIVSlothCombo.Window.Functions.SliderIncrements; +using XIVSlothCombo.Window.Functions; namespace XIVSlothCombo.Combos.PvE { @@ -36,14 +37,18 @@ public static UserInt SCH_ST_Heal_LustrateOption = new("SCH_ST_Heal_LustrateOption"), SCH_ST_Heal_ExcogitationOption = new("SCH_ST_Heal_ExcogitationOption"), SCH_ST_Heal_ProtractionOption = new("SCH_ST_Heal_ProtractionOption"), + SCH_ST_Heal_AetherpactOption = new("SCH_ST_Heal_AetherpactOption"), SCH_ST_Heal_EsunaOption = new("SCH_ST_Heal_EsunaOption"); public static UserIntArray - SCH_ST_Heals_Priority = new("SCH_ST_Heals_Priority"); + SCH_ST_Heals_Priority = new("SCH_ST_Heals_Priority"), + SCH_AoE_Heals_Priority = new ("SCH_AoE_Heals_Priority"); public static UserBool SCH_ST_Heal_Adv = new("SCH_ST_Heal_Adv"), SCH_ST_Heal_UIMouseOver = new("SCH_ST_Heal_UIMouseOver"), SCH_DeploymentTactics_Adv = new("SCH_DeploymentTactics_Adv"), SCH_DeploymentTactics_UIMouseOver = new("SCH_DeploymentTactics_UIMouseOver"); + public static UserBoolArray + SCH_ST_Heal_AldoquimOpts = new("SCH_ST_Heal_AldoquimOpts"); #endregion #region Utility @@ -121,22 +126,29 @@ internal static void Draw(CustomComboPreset preset) break; case CustomComboPreset.SCH_ST_Heal_Adloquium: - DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, "Use Adloquium on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); + DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Use {Adloquium.ActionName()} on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} will be unavailable.", 2, 0); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis}", "Enable to not override an existing Sage's shield.", 2, 1); break; case CustomComboPreset.SCH_ST_Heal_Lustrate: DrawSliderInt(0, 100, SCH_ST_Heal_LustrateOption, "Start using when below HP %. Set to 100 to disable this check"); - DrawPriorityInput(SCH_ST_Heals_Priority, 3, 0, $"{Lustrate.ActionName()} Priority: "); + DrawPriorityInput(SCH_ST_Heals_Priority, 4, 0, $"{Lustrate.ActionName()} Priority: "); break; case CustomComboPreset.SCH_ST_Heal_Excogitation: DrawSliderInt(0, 100, SCH_ST_Heal_ExcogitationOption, "Start using when below HP %. Set to 100 to disable this check"); - DrawPriorityInput(SCH_ST_Heals_Priority, 3, 1, $"{Excogitation.ActionName()} Priority: "); + DrawPriorityInput(SCH_ST_Heals_Priority, 4, 1, $"{Excogitation.ActionName()} Priority: "); break; case CustomComboPreset.SCH_ST_Heal_Protraction: DrawSliderInt(0, 100, SCH_ST_Heal_ProtractionOption, "Start using when below HP %. Set to 100 to disable this check"); - DrawPriorityInput(SCH_ST_Heals_Priority, 3, 2, $"{Protraction.ActionName()} Priority: "); + DrawPriorityInput(SCH_ST_Heals_Priority, 4, 2, $"{Protraction.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_ST_Heal_Aetherpact: + DrawSliderInt(0, 100, SCH_ST_Heal_AetherpactOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_ST_Heals_Priority, 4, 3, $"{Aetherpact.ActionName()} Priority: "); break; case CustomComboPreset.SCH_ST_Heal_Esuna: @@ -151,6 +163,30 @@ internal static void Draw(CustomComboPreset preset) DrawSliderInt(4000, 9500, SCH_AoE_Heal_LucidOption, "MP Threshold", 150, Hundreds); break; + case CustomComboPreset.SCH_AoE_Heal_WhisperingDawn: + DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 0, $"{WhisperingDawn.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_AoE_Heal_FeyIllumination: + DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 1, $"{FeyIllumination.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_AoE_Heal_FeyBlessing: + DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 2, $"{FeyBlessing.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_AoE_Heal_Consolation: + DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 3, $"{Consolation.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_AoE_Heal_Seraphism: + DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 4, $"{Seraphism.ActionName()} Priority: "); + break; + + case CustomComboPreset.SCH_AoE_Heal_Indomitability: + DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 5, $"{Indomitability.ActionName()} Priority: "); + break; + case CustomComboPreset.SCH_DeploymentTactics: DrawAdditionalBoolChoice(SCH_DeploymentTactics_Adv, "Advanced Options", "", isConditionalChoice: true); if (SCH_DeploymentTactics_Adv) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index 7dbe38da8..d67cf34c5 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -35,6 +35,10 @@ public static int GetMatchingConfigST(int i, out uint action, out bool enabled) action = Protraction; enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Protraction); return Config.SCH_ST_Heal_ProtractionOption; + case 3: + action = Aetherpact; + enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Aetherpact); + return Config.SCH_ST_Heal_AetherpactOption; } enabled = false; @@ -42,43 +46,39 @@ public static int GetMatchingConfigST(int i, out uint action, out bool enabled) return 0; } - //public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) - //{ - // switch (i) - // { - // case 0: - // action = PvE.SGE.Kerachole; - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Kerachole) && (!PvE.SGE.Config.SGE_AoE_Heal_KeracholeTrait || (PvE.SGE.Config.SGE_AoE_Heal_KeracholeTrait && TraitLevelChecked(PvE.SGE.Traits.EnhancedKerachole))) && PvE.SGE.Gauge.HasAddersgall(); - // return 0; - // case 1: - // action = PvE.SGE.Ixochole; - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Ixochole) && PvE.SGE.Gauge.HasAddersgall(); - // return 0; - // case 2: - // action = OriginalHook(PvE.SGE.Physis); - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Physis); - // return 0; - // case 3: - // action = PvE.SGE.Holos; - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Holos); - // return 0; - // case 4: - // action = PvE.SGE.Panhaima; - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Panhaima); - // return 0; - // case 5: - // action = PvE.SGE.Pepsis; - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Pepsis) && FindEffect(PvE.SGE.Buffs.EukrasianPrognosis) is not null; - // return 0; - // case 6: - // action = PvE.SGE.Philosophia; - // enabled = IsEnabled(CustomComboPreset.SGE_AoE_Heal_Philosophia); - // return 0; - // } + public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) + { + switch (i) + { + case 0: + action = OriginalHook(WhisperingDawn); + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_WhisperingDawn); + return 0; + case 1: + action = OriginalHook(FeyIllumination); + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_FeyIllumination); + return 0; + case 2: + action = FeyBlessing; + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_FeyBlessing); + return 0; + case 3: + action = Consolation; + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Consolation) && Gauge.SeraphTimer > 0; + return 0; + case 4: + action = Seraphism; + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Seraphism); + return 0; + case 5: + action = Indomitability; + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Indomitability) && Gauge.HasAetherflow(); + return 0; + } - // enabled = false; - // action = 0; - // return 0; - //} + enabled = false; + action = 0; + return 0; + } } } diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 12d41d213..61d1842ef 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -226,6 +226,8 @@ static void CustomStyleText(string label, object? value) CustomStyleText("In Melee Range:", InMeleeRange()); CustomStyleText("Relative Position:", AngleToTarget() is 2 ? "Rear" : (AngleToTarget() is 1 or 3) ? "Flank" : AngleToTarget() is 4 ? "Front" : ""); CustomStyleText("Health:", $"{EnemyHealthCurrentHp().ToString("N0")} / {EnemyHealthMaxHp().ToString("N0")} ({Math.Round(GetTargetHPPercent(), 2)}%)"); + CustomStyleText("Shield:", (GetHealTarget() as ICharacter).ShieldPercentage); + CustomStyleText("Health Percent (+ Shield):", $"{GetTargetHPPercent(GetHealTarget())} / {GetTargetHPPercent(GetHealTarget(), true)}"); ImGui.Indent(); if (ImGui.CollapsingHeader("Relative Target Distances")) { From 1b70524ae96b201593f639bc5a97aa34c2aef462 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 14:59:09 -0500 Subject: [PATCH 155/208] Didn't hit safe FFS --- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 6 +++--- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 13f72ea14..5d48a6430 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -521,7 +521,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Esuna) && ActionReady(All.Esuna) && - GetTargetHPPercent(healTarget,true) >= Config.SCH_ST_Heal_EsunaOption && + GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) >= Config.SCH_ST_Heal_EsunaOption && HasCleansableDebuff(healTarget)) return All.Esuna; @@ -532,7 +532,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (enabled) { - if (GetTargetHPPercent(healTarget,true) <= config && + if (GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= config && ActionReady(spell)) return spell; } @@ -541,7 +541,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && - GetTargetHPPercent(healTarget,true) <= Config.SCH_ST_Heal_AdloquiumOption && + GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption && (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check (!Config.SCH_ST_Heal_AldoquimOpts[1] || FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null)) //EDiagnosis Check { diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 1a7097727..60b6e1681 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -3,7 +3,6 @@ using static XIVSlothCombo.Extensions.UIntExtensions; using static XIVSlothCombo.Window.Functions.UserConfig; using static XIVSlothCombo.Window.Functions.SliderIncrements; -using XIVSlothCombo.Window.Functions; namespace XIVSlothCombo.Combos.PvE { @@ -45,6 +44,7 @@ public static UserIntArray public static UserBool SCH_ST_Heal_Adv = new("SCH_ST_Heal_Adv"), SCH_ST_Heal_UIMouseOver = new("SCH_ST_Heal_UIMouseOver"), + SCH_ST_Heal_IncludeShields = new("SCH_ST_Heal_IncludeShields"), SCH_DeploymentTactics_Adv = new("SCH_DeploymentTactics_Adv"), SCH_DeploymentTactics_UIMouseOver = new("SCH_DeploymentTactics_UIMouseOver"); public static UserBoolArray @@ -117,6 +117,7 @@ internal static void Draw(CustomComboPreset preset) "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\n" + "To be used in conjunction with Redirect/Reaction/etc"); + DrawAdditionalBoolChoice(SCH_ST_Heal_IncludeShields,"Include Shields in HP Percent Sliders",""); ImGui.Unindent(); } break; From 7f5d242176f821ddc9c7e6beb2ed82f57a5caa2e Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:12:14 -0500 Subject: [PATCH 156/208] Added "Include Shields in HP Percent Sliders" for Single Target Heals --- XIVSlothCombo/Combos/PvE/SGE/SGE.cs | 6 +++--- XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs index 5ae6f0776..63503d55f 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs @@ -447,7 +447,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IGameObject? healTarget = GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); if (IsEnabled(CustomComboPreset.SGE_ST_Heal_Esuna) && ActionReady(All.Esuna) && - GetTargetHPPercent(healTarget) >= Config.SGE_ST_Heal_Esuna && + GetTargetHPPercent(healTarget, Config.SGE_ST_Heal_IncludeShields) >= Config.SGE_ST_Heal_Esuna && HasCleansableDebuff(healTarget)) return All.Esuna; @@ -468,14 +468,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (enabled) { - if (GetTargetHPPercent(healTarget) <= config && + if (GetTargetHPPercent(healTarget, Config.SGE_ST_Heal_IncludeShields) <= config && ActionReady(spell)) return spell; } } if (IsEnabled(CustomComboPreset.SGE_ST_Heal_EDiagnosis) && LevelChecked(Eukrasia) && - GetTargetHPPercent(healTarget) <= Config.SGE_ST_Heal_EDiagnosisHP && + GetTargetHPPercent(healTarget, Config.SGE_ST_Heal_IncludeShields) <= Config.SGE_ST_Heal_EDiagnosisHP && (Config.SGE_ST_Heal_EDiagnosisOpts[0] || FindEffectOnMember(Buffs.EukrasianDiagnosis, healTarget) is null) && //Ignore existing shield check (!Config.SGE_ST_Heal_EDiagnosisOpts[1] || FindEffectOnMember(SCH.Buffs.Galvanize, healTarget) is null)) //Galvenize Check return Eukrasia; diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs index 24662acfd..fa796a549 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs @@ -32,6 +32,7 @@ public static UserFloat public static UserBool SGE_ST_Heal_Adv = new("SGE_ST_Heal_Adv"), SGE_ST_Heal_UIMouseOver = new("SGE_ST_Heal_UIMouseOver"), + SGE_ST_Heal_IncludeShields = new("SGE_ST_Heal_IncludeShields"), SGE_AoE_Heal_KeracholeTrait = new("SGE_AoE_Heal_KeracholeTrait"); public static UserInt SGE_ST_Heal_Zoe = new("SGE_ST_Heal_Zoe"), @@ -113,6 +114,7 @@ internal static void Draw(CustomComboPreset preset) "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\n" + "To be used in conjunction with Redirect/Reaction/etc"); + DrawAdditionalBoolChoice(SGE_ST_Heal_IncludeShields, "Include Shields in HP Percent Sliders", ""); ImGui.Unindent(); } break; From 85ab597734a7197d7e5ceebb169b5ddb66bc97c0 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:21:55 -0500 Subject: [PATCH 157/208] Added "Include Shields in HP Percent Sliders" for Single Target Heals --- XIVSlothCombo/Combos/PvE/AST/AST.cs | 12 ++++++------ XIVSlothCombo/Combos/PvE/AST/AST_Config.cs | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/AST/AST.cs b/XIVSlothCombo/Combos/PvE/AST/AST.cs index 38f28cf06..b5a14f656 100644 --- a/XIVSlothCombo/Combos/PvE/AST/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST/AST.cs @@ -502,41 +502,41 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IGameObject? healTarget = this.OptionalTarget != null ? this.OptionalTarget : GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Esuna) && ActionReady(All.Esuna) && - GetTargetHPPercent(healTarget) >= Config.AST_ST_SimpleHeals_Esuna && + GetTargetHPPercent(healTarget, Config.AST_ST_SimpleHeals_IncludeShields) >= Config.AST_ST_SimpleHeals_Esuna && HasCleansableDebuff(healTarget)) return All.Esuna; if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Spire) && Gauge.DrawnCards[2] == CardType.SPIRE && - GetTargetHPPercent(healTarget) <= Config.AST_Spire && + GetTargetHPPercent(healTarget, Config.AST_ST_SimpleHeals_IncludeShields) <= Config.AST_Spire && ActionReady(Play3) && canSpire) return OriginalHook(Play3); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Ewer) && Gauge.DrawnCards[2] == CardType.EWER && - GetTargetHPPercent(healTarget) <= Config.AST_Ewer && + GetTargetHPPercent(healTarget, Config.AST_ST_SimpleHeals_IncludeShields) <= Config.AST_Ewer && ActionReady(Play3) && canEwer) return OriginalHook(Play3); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Arrow) && Gauge.DrawnCards[1] == CardType.ARROW && - GetTargetHPPercent(healTarget) <= Config.AST_Arrow && + GetTargetHPPercent(healTarget, Config.AST_ST_SimpleHeals_IncludeShields) <= Config.AST_Arrow && ActionReady(Play2) && canArrow) return OriginalHook(Play2); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Bole) && Gauge.DrawnCards[1] == CardType.BOLE && - GetTargetHPPercent(healTarget) <= Config.AST_Bole && + GetTargetHPPercent(healTarget, Config.AST_ST_SimpleHeals_IncludeShields) <= Config.AST_Bole && ActionReady(Play2) && canBole) return OriginalHook(Play2); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_EssentialDignity) && ActionReady(EssentialDignity) && - GetTargetHPPercent(healTarget) <= Config.AST_EssentialDignity && + GetTargetHPPercent(healTarget, Config.AST_ST_SimpleHeals_IncludeShields) <= Config.AST_EssentialDignity && canDignity) return EssentialDignity; diff --git a/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs b/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs index 52761d4e9..e2144da1c 100644 --- a/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs +++ b/XIVSlothCombo/Combos/PvE/AST/AST_Config.cs @@ -33,6 +33,7 @@ public static UserBool AST_QuickTarget_SkipRezWeakness = new("AST_QuickTarget_SkipRezWeakness"), AST_ST_SimpleHeals_Adv = new("AST_ST_SimpleHeals_Adv"), AST_ST_SimpleHeals_UIMouseOver = new("AST_ST_SimpleHeals_UIMouseOver"), + AST_ST_SimpleHeals_IncludeShields = new("AST_ST_SimpleHeals_IncludeShields"), AST_ST_SimpleHeals_WeaveDignity = new("AST_ST_SimpleHeals_WeaveDignity"), AST_ST_SimpleHeals_WeaveIntersection = new("AST_ST_SimpleHeals_WeaveIntersection"), AST_ST_SimpleHeals_WeaveEwer = new("AST_ST_SimpleHeals_WeaveEwer"), @@ -111,6 +112,7 @@ internal static void Draw(CustomComboPreset preset) "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\n" + "To be used in conjunction with Redirect/Reaction/etc"); + DrawAdditionalBoolChoice(AST_ST_SimpleHeals_IncludeShields, "Include Shields in HP Percent Sliders", ""); ImGui.Unindent(); } break; From 548e9b51eb596af9608cccd60caf8d49ce9326b8 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 29 Sep 2024 09:58:21 +0100 Subject: [PATCH 158/208] Merge pull request #9 from zbee/autoRot-healTarget [Healers] Update heal targeting to support soft->hard->mouseOver (for AutoRot) --- XIVSlothCombo/Combos/PvE/AST.cs | 2 +- XIVSlothCombo/Combos/PvE/SGE.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index ee2bdcdfb..904a87a54 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -547,7 +547,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var canArrow = (Config.AST_ST_SimpleHeals_WeaveArrow && CanSpellWeave(actionID)) || !Config.AST_ST_SimpleHeals_WeaveArrow; //Grab our target (Soft->Hard->Self) - IGameObject? healTarget = this.OptionalTarget != null ? this.OptionalTarget : GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.AST_ST_SimpleHeals_Adv && Config.AST_ST_SimpleHeals_UIMouseOver); if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Esuna) && ActionReady(All.Esuna) && GetTargetHPPercent(healTarget) >= Config.AST_ST_SimpleHeals_Esuna && diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE.cs index c703ec0ad..f66eef682 100644 --- a/XIVSlothCombo/Combos/PvE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE.cs @@ -498,7 +498,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (HasEffect(Buffs.Eukrasia)) return EukrasianDiagnosis; - IGameObject? healTarget = GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); + IGameObject? healTarget = this.OptionalTarget ?? GetHealTarget(Config.SGE_ST_Heal_Adv && Config.SGE_ST_Heal_UIMouseOver); if (IsEnabled(CustomComboPreset.SGE_ST_Heal_Esuna) && ActionReady(All.Esuna) && GetTargetHPPercent(healTarget) >= Config.SGE_ST_Heal_Esuna && From 038fc3a8e13e5271fbc9616c648c3e3297354a58 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:01:46 -0500 Subject: [PATCH 159/208] Added Single Target heal priority and optional shield checking in HP Percent Sliders --- XIVSlothCombo/Combos/PvE/WHM/WHM.cs | 30 ++++++++--------- XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs | 9 +++++ XIVSlothCombo/Combos/PvE/WHM/WHM_Helper.cs | 39 ++++++++++++++++++++++ 3 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 XIVSlothCombo/Combos/PvE/WHM/WHM_Helper.cs diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs index 4b4922714..723626f86 100644 --- a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs @@ -340,32 +340,28 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool canWeave = CanSpellWeave(actionID, 0.3); bool thinAirReady = LevelChecked(ThinAir) && !HasEffect(Buffs.ThinAir) && GetRemainingCharges(ThinAir) > Config.WHM_STHeals_ThinAir; - bool lucidReady = ActionReady(All.LucidDreaming) && LocalPlayer.CurrentMp <= Config.WHM_STHeals_Lucid; - bool tetraReady = ActionReady(Tetragrammaton) && (!Config.WHM_STHeals_TetraWeave || (Config.WHM_STHeals_TetraWeave && canWeave)) && GetTargetHPPercent(healTarget) <= Config.WHM_STHeals_TetraHP; - bool benisonReady = ActionReady(DivineBenison) && (!Config.WHM_STHeals_BenisonWeave || (Config.WHM_STHeals_BenisonWeave && canWeave)) && GetTargetHPPercent(healTarget) <= Config.WHM_STHeals_BenisonHP; - bool aquaReady = ActionReady(Aquaveil) && (!Config.WHM_STHeals_AquaveilWeave || (Config.WHM_STHeals_AquaveilWeave && canWeave)) && GetTargetHPPercent(healTarget) <= Config.WHM_STHeals_AquaveilHP; - bool benedictionReady = ActionReady(Benediction) && (!Config.WHM_STHeals_BenedictionWeave || (Config.WHM_STHeals_BenedictionWeave && canWeave)) && GetTargetHPPercent(healTarget) <= Config.WHM_STHeals_BenedictionHP; bool regenReady = ActionReady(Regen) && (FindEffectOnMember(Buffs.Regen, healTarget) is null || FindEffectOnMember(Buffs.Regen, healTarget)?.RemainingTime <= Config.WHM_STHeals_RegenTimer); - if (IsEnabled(CustomComboPreset.WHM_STHeals_Benediction) && benedictionReady) - return Benediction; - if (IsEnabled(CustomComboPreset.WHM_STHeals_Esuna) && ActionReady(All.Esuna) && - GetTargetHPPercent(healTarget) >= Config.WHM_STHeals_Esuna && + GetTargetHPPercent(healTarget, Config.WHM_STHeals_IncludeShields) >= Config.WHM_STHeals_Esuna && HasCleansableDebuff(healTarget)) return All.Esuna; - if (IsEnabled(CustomComboPreset.WHM_STHeals_Tetragrammaton) && tetraReady) - return Tetragrammaton; - - if (IsEnabled(CustomComboPreset.WHM_STHeals_Lucid) && canWeave && lucidReady) + if (IsEnabled(CustomComboPreset.WHM_STHeals_Lucid) && All.CanUseLucid(actionID, Config.WHM_STHeals_Lucid)) return All.LucidDreaming; - if (IsEnabled(CustomComboPreset.WHM_STHeals_Benison) && benisonReady && FindEffectOnMember(Buffs.DivineBenison, healTarget) is null) - return DivineBenison; + foreach (var prio in Config.WHM_ST_Heals_Priority.Items.OrderBy(x => x)) + { + var index = Config.WHM_ST_Heals_Priority.IndexOf(prio); + var config = GetMatchingConfigST(index, this.OptionalTarget, out var spell, out bool enabled); - if (IsEnabled(CustomComboPreset.WHM_STHeals_Aquaveil) && aquaReady && FindEffectOnMember(Buffs.Aquaveil, healTarget) is null) - return Aquaveil; + if (enabled) + { + if (GetTargetHPPercent(healTarget, Config.WHM_STHeals_IncludeShields) <= config && + ActionReady(spell)) + return spell; + } + } if (IsEnabled(CustomComboPreset.WHM_STHeals_Regen) && regenReady) return Regen; diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs index d6a562c2b..34e61fa7c 100644 --- a/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM_Config.cs @@ -30,6 +30,7 @@ internal static UserBool WHM_ST_MainCombo_Opener_Swiftcast = new("WHM_ST_Opener_Swiftcast"), WHM_AoEDPS_PresenceOfMindWeave = new("WHM_AoEDPS_PresenceOfMindWeave"), WHM_STHeals_UIMouseOver = new("WHM_STHeals_UIMouseOver"), + WHM_STHeals_IncludeShields = new("WHM_STHeals_IncludeShields"), WHM_STHeals_BenedictionWeave = new("WHM_STHeals_BenedictionWeave"), WHM_STHeals_TetraWeave = new("WHM_STHeals_TetraWeave"), WHM_STHeals_BenisonWeave = new("WHM_STHeals_BenisonWeave"), @@ -43,6 +44,9 @@ internal static UserFloat WHM_AoEHeals_MedicaTime = new("WHM_AoEHeals_MedicaTime"); public static UserBoolArray WHM_ST_MainCombo_Adv_Actions = new("WHM_ST_MainCombo_Adv_Actions"); + internal static UserIntArray + WHM_ST_Heals_Priority = new("WHM_ST_Heals_Priority"), + WHM_AoE_Heals_Priority = new("WHM_AoE_Heals_Priority"); internal static void Draw(CustomComboPreset preset) { @@ -107,6 +111,7 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.WHM_STHeals: DrawAdditionalBoolChoice(WHM_STHeals_UIMouseOver, "Party UI Mouseover Checking", "Check party member's HP & Debuffs by using mouseover on the party list.\nTo be used in conjunction with Redirect/Reaction/etc."); + DrawAdditionalBoolChoice(WHM_STHeals_IncludeShields, "Include Shields in HP Percent Sliders", ""); break; case CustomComboPreset.WHM_STHeals_ThinAir: @@ -124,21 +129,25 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.WHM_STHeals_Benediction: DrawAdditionalBoolChoice(WHM_STHeals_BenedictionWeave, "Only Weave", ""); DrawSliderInt(1, 100, WHM_STHeals_BenedictionHP, "Use when target HP% is at or below."); + DrawPriorityInput(WHM_ST_Heals_Priority, 4, 0, $"{Benediction.ActionName()} Priority: "); break; case CustomComboPreset.WHM_STHeals_Tetragrammaton: DrawAdditionalBoolChoice(WHM_STHeals_TetraWeave, "Only Weave", ""); DrawSliderInt(1, 100, WHM_STHeals_TetraHP, "Use when target HP% is at or below."); + DrawPriorityInput(WHM_ST_Heals_Priority, 4, 1, $"{Tetragrammaton.ActionName()} Priority: "); break; case CustomComboPreset.WHM_STHeals_Benison: DrawAdditionalBoolChoice(WHM_STHeals_BenisonWeave, "Only Weave", ""); DrawSliderInt(1, 100, WHM_STHeals_BenisonHP, "Use when target HP% is at or below."); + DrawPriorityInput(WHM_ST_Heals_Priority, 4, 2, $"{DivineBenison.ActionName()} Priority: "); break; case CustomComboPreset.WHM_STHeals_Aquaveil: DrawAdditionalBoolChoice(WHM_STHeals_AquaveilWeave, "Only Weave", ""); DrawSliderInt(1, 100, WHM_STHeals_AquaveilHP, "Use when target HP% is at or below."); + DrawPriorityInput(WHM_ST_Heals_Priority, 4, 3, $"{Aquaveil.ActionName()} Priority: "); break; case CustomComboPreset.WHM_AoEHeals_Assize: diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM_Helper.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM_Helper.cs new file mode 100644 index 000000000..fdcd697ac --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM_Helper.cs @@ -0,0 +1,39 @@ +using Dalamud.Game.ClientState.Objects.Types; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE +{ + internal static partial class WHM + { + public static int GetMatchingConfigST(int i, IGameObject? optionalTarget, out uint action, out bool enabled) + { + //var healTarget = optionalTarget ?? GetHealTarget(Config.WHM_STHeals_UIMouseOver); + //leaving incase Regen gets a slider and is added + + bool canWeave = CanWeave(OriginalHook(Stone1), 0.3); + switch (i) + { + case 0: + action = Benediction; + enabled = IsEnabled(CustomComboPreset.WHM_STHeals_Benediction) && (!Config.WHM_STHeals_BenedictionWeave || (Config.WHM_STHeals_BenedictionWeave && canWeave)); + return Config.WHM_STHeals_BenedictionHP; + case 1: + action = Tetragrammaton; + enabled = IsEnabled(CustomComboPreset.WHM_STHeals_Tetragrammaton) && (!Config.WHM_STHeals_TetraWeave || (Config.WHM_STHeals_TetraWeave && canWeave)); + return Config.WHM_STHeals_TetraHP; + case 2: + action = DivineBenison; + enabled = IsEnabled(CustomComboPreset.WHM_STHeals_Benison) && (!Config.WHM_STHeals_BenisonWeave || (Config.WHM_STHeals_BenisonWeave && canWeave)); + return Config.WHM_STHeals_BenisonHP; + case 3: + action = Aquaveil; + enabled = IsEnabled(CustomComboPreset.WHM_STHeals_Aquaveil) && (!Config.WHM_STHeals_AquaveilWeave || (Config.WHM_STHeals_AquaveilWeave && canWeave)); + return Config.WHM_STHeals_AquaveilHP; + } + + enabled = false; + action = 0; + return 0; + } + } +} From 14ca3d6bd47422364d0423b979260d5626fad67e Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 23:32:23 -0500 Subject: [PATCH 160/208] Initial Moves --- XIVSlothCombo/Combos/PvE/{ => RDM}/RDM.cs | 0 XIVSlothCombo/Combos/{JobHelpers/RDM.cs => PvE/RDM/RDM_Helper.cs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename XIVSlothCombo/Combos/PvE/{ => RDM}/RDM.cs (100%) rename XIVSlothCombo/Combos/{JobHelpers/RDM.cs => PvE/RDM/RDM_Helper.cs} (100%) diff --git a/XIVSlothCombo/Combos/PvE/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs similarity index 100% rename from XIVSlothCombo/Combos/PvE/RDM.cs rename to XIVSlothCombo/Combos/PvE/RDM/RDM.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs similarity index 100% rename from XIVSlothCombo/Combos/JobHelpers/RDM.cs rename to XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs From ead7685e3becd7a84cf166d8815dd6471561571a Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sat, 28 Sep 2024 23:40:16 -0500 Subject: [PATCH 161/208] Reorganized & Added Simple Mode ST & AoE --- XIVSlothCombo/Combos/CustomComboPreset.cs | 23 +- XIVSlothCombo/Combos/PvE/RDM/RDM.cs | 569 ++++---------- XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs | 177 +++++ XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs | 774 +++++++++++++++---- XIVSlothCombo/Window/Functions/Presets.cs | 2 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 125 --- 6 files changed, 969 insertions(+), 701 deletions(-) create mode 100644 XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 1cdb57fac..4e4d3dd54 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3184,10 +3184,18 @@ New features should be added to the appropriate sections. If more than 10 sub features, use the next feature number if available The three digets after RDM.JobID can be used to reorder items in the list */ + #region Single Target DPS + [AutoAction(false, false)] + [ConflictingCombos(RDM_ST_DPS)] + [ReplaceSkill(RDM.Jolt, RDM.Jolt2, RDM.Jolt3)] + [CustomComboInfo("Simple Mode - Single Target", "Replaces Jolts with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", RDM.JobID, -2)] + RDM_ST_SimpleMode = 13837, + [AutoAction(false, false)] [ReplaceSkill(RDM.Jolt, RDM.Jolt2)] - [CustomComboInfo("Single Target DPS Features", "Enables various Single Target options below.", RDM.JobID, 1)] + [ConflictingCombos(RDM_ST_SimpleMode)] + [CustomComboInfo("Single Target DPS Feature", "Enables various Single Target options below.", RDM.JobID, 1)] RDM_ST_DPS = 13000, [ParentCombo(RDM_ST_DPS)] @@ -3246,6 +3254,13 @@ The three digets after RDM.JobID can be used to reorder items in the list #region AoE DPS [AutoAction(true, false)] [ReplaceSkill(RDM.Scatter, RDM.Impact)] + [ConflictingCombos(RDM_AoE_DPS)] + [CustomComboInfo("Simple Mode - AoE", "Replaces Scatter/Impact with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", RDM.JobID, -1)] + RDM_AoE_SimpleMode = 13838, + + [AutoAction(true, false)] + [ReplaceSkill(RDM.Scatter, RDM.Impact)] + [ConflictingCombos(RDM_AoE_SimpleMode)] [CustomComboInfo("AoE DPS Feature", "Enables various AoE Target options below.", RDM.JobID, 310)] RDM_AoE_DPS = 13310, @@ -3324,7 +3339,7 @@ The three digets after RDM.JobID can be used to reorder items in the list RDM_MagickProtection = 13836, [Variant] - [VariantParent(RDM_ST_DPS, RDM_AoE_DPS)] + [VariantParent(RDM_ST_DPS, RDM_ST_SimpleMode, RDM_AoE_DPS, RDM_AoE_SimpleMode)] [CustomComboInfo("Rampart Option", "Use Variant Rampart on cooldown. Replaces Jolts.", RDM.JobID)] RDM_Variant_Rampart = 13830, @@ -3334,7 +3349,7 @@ The three digets after RDM.JobID can be used to reorder items in the list RDM_Variant_Raise = 13831, [Variant] - [VariantParent(RDM_ST_DPS, RDM_AoE_DPS)] + [VariantParent(RDM_ST_DPS, RDM_ST_SimpleMode, RDM_AoE_DPS, RDM_AoE_SimpleMode)] [CustomComboInfo("Cure Option", "Use Variant Cure when HP is below set threshold. Replaces Jolts.", RDM.JobID)] RDM_Variant_Cure = 13832, @@ -3343,6 +3358,8 @@ The three digets after RDM.JobID can be used to reorder items in the list RDM_Variant_Cure2 = 13833, #endregion + //Last Used 13838 + #endregion #region SAGE diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs index dee8d701e..01e47634c 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs @@ -1,12 +1,9 @@ -using Dalamud.Game.ClientState.Conditions; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; -using static XIVSlothCombo.Combos.JobHelpers.RDMHelper; namespace XIVSlothCombo.Combos.PvE { - internal class RDM + internal static partial class RDM { //7.0 Note //Gauge information is available via RDMMana @@ -90,50 +87,6 @@ public const uint EnhancedAccelerationII = 624; } - public static class Config - { - public static UserInt - RDM_VariantCure = new("RDM_VariantCure"), - RDM_ST_Lucid_Threshold = new("RDM_LucidDreaming_Threshold", 6500), - RDM_AoE_Lucid_Threshold = new("RDM_AoE_Lucid_Threshold", 6500), - RDM_AoE_MoulinetRange = new("RDM_MoulinetRange"); - public static UserBool - RDM_ST_oGCD_OnAction_Adv = new("RDM_ST_oGCD_OnAction_Adv"), - RDM_ST_oGCD_Fleche = new("RDM_ST_oGCD_Fleche"), - RDM_ST_oGCD_ContraSixte = new("RDM_ST_oGCD_ContraSixte"), - RDM_ST_oGCD_Engagement = new("RDM_ST_oGCD_Engagement"), - RDM_ST_oGCD_Engagement_Pooling = new("RDM_ST_oGCD_Engagement_Pooling"), - RDM_ST_oGCD_CorpACorps = new("RDM_ST_oGCD_CorpACorps"), - RDM_ST_oGCD_CorpACorps_Melee = new("RDM_ST_oGCD_CorpACorps_Melee"), - RDM_ST_oGCD_CorpACorps_Pooling = new("RDM_ST_oGCD_CorpACorps_Pooling"), - RDM_ST_oGCD_ViceOfThorns = new("RDM_ST_oGCD_ViceOfThorns"), - RDM_ST_oGCD_Prefulgence = new("RDM_ST_oGCD_Prefulgence"), - RDM_ST_MeleeCombo_Adv = new("RDM_ST_MeleeCombo_Adv"), - RDM_ST_MeleeFinisher_Adv = new("RDM_ST_MeleeFinisher_Adv"), - RDM_ST_MeleeEnforced = new("RDM_ST_MeleeEnforced"), - - RDM_AoE_oGCD_OnAction_Adv = new("RDM_AoE_oGCD_OnAction_Adv"), - RDM_AoE_oGCD_Fleche = new("RDM_AoE_oGCD_Fleche"), - RDM_AoE_oGCD_ContraSixte = new("RDM_AoE_oGCD_ContraSixte"), - RDM_AoE_oGCD_Engagement = new("RDM_AoE_oGCD_Engagement"), - RDM_AoE_oGCD_Engagement_Pooling = new("RDM_AoE_oGCD_Engagement_Pooling"), - RDM_AoE_oGCD_CorpACorps = new("RDM_AoE_oGCD_CorpACorps"), - RDM_AoE_oGCD_CorpACorps_Melee = new("RDM_AoE_oGCD_CorpACorps_Melee"), - RDM_AoE_oGCD_CorpACorps_Pooling = new("RDM_AoE_oGCD_CorpACorps_Pooling"), - RDM_AoE_oGCD_ViceOfThorns = new("RDM_AoE_oGCD_ViceOfThorns"), - RDM_AoE_oGCD_Prefulgence = new("RDM_AoE_oGCD_Prefulgence"), - RDM_AoE_MeleeCombo_Adv = new("RDM_AoE_MeleeCombo_Adv"), - RDM_AoE_MeleeFinisher_Adv = new("RDM_AoE_MeleeFinisher_Adv"); - public static UserBoolArray - RDM_ST_oGCD_OnAction = new("RDM_ST_oGCD_OnAction"), - RDM_ST_MeleeCombo_OnAction = new("RDM_ST_MeleeCombo_OnAction"), - RDM_ST_MeleeFinisher_OnAction = new("RDM_ST_MeleeFinisher_OnAction"), - - RDM_AoE_oGCD_OnAction = new("RDM_AoE_oGCD_OnAction"), - RDM_AoE_MeleeCombo_OnAction = new("RDM_AoE_MeleeCombo_OnAction"), - RDM_AoE_MeleeFinisher_OnAction = new("RDM_AoE_MeleeFinisher_OnAction"); - } - internal class RDM_VariantVerCure : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RdmAny; @@ -143,20 +96,61 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ? Variant.VariantCure : actionID; } - internal class RDM_ST_DPS : CustomCombo + internal class RDM_ST_SimpleMode : CustomCombo { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RDM_ST_DPS; - internal static RDMOpenerLogic RDMOpener = new(); + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RDM_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - //MAIN_COMBO_VARIABLES + if (actionID is Jolt or Jolt2 or Jolt3) + { + //VARIANTS + if (IsEnabled(CustomComboPreset.RDM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RDM_VariantCure)) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.RDM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanSpellWeave(actionID)) + return Variant.VariantRampart; + + // Opener for RDM + if (RDMOpenerLogic.DoFullOpener(ref actionID)) + return actionID; + + //Lucid Dreaming + if (TryLucidDreaming(actionID, 6500, lastComboMove)) return All.LucidDreaming; + + //oGCDs + if (TryOGCDs(actionID, true, out uint oGCDAction)) return oGCDAction; + + //Melee Finisher + if (MeleeCombo.TryMeleeFinisher(lastComboMove, out uint finisherAction)) return finisherAction; - int blackmana = RDMMana.Black;//Gauge.BlackMana; - int whitemana = RDMMana.White;//Gauge.WhiteMana; + //Melee Combo + // Manafication/Embolden Code + if (MeleeCombo.TrySTManaEmbolden(actionID, lastComboMove, level, out uint ManaEmbolden)) return ManaEmbolden; + if (MeleeCombo.TrySTMeleeCombo(actionID, lastComboMove, comboTime, out uint MeleeID)) return MeleeID; - //END_MAIN_COMBO_VARIABLES + //Normal Spell Rotation + if (SpellCombo.TryAcceleration(actionID, lastComboMove, out uint Accel)) return Accel; + if (SpellCombo.TrySTSpellRotation(actionID, out uint SpellID)) return SpellID; + } + + //NO_CONDITIONS_MET + return actionID; + } + } + + internal class RDM_ST_DPS : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RDM_ST_DPS; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { if (actionID is Jolt or Jolt2 or Jolt3) { //VARIANTS @@ -174,7 +168,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Opener for RDM if (IsEnabled(CustomComboPreset.RDM_Balance_Opener)) { - if (RDMOpener.DoFullOpener(ref actionID)) + if (RDMOpenerLogic.DoFullOpener(ref actionID)) return actionID; } } @@ -182,9 +176,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Lucid Dreaming if (IsEnabled(CustomComboPreset.RDM_ST_Lucid) && actionID is Jolt or Jolt2 or Jolt3 - && All.CanUseLucid(actionID, Config.RDM_ST_Lucid_Threshold) - && InCombat() - && RDMLucid.SafetoUse(lastComboMove)) //Don't interupt certain combos + && TryLucidDreaming(actionID, Config.RDM_ST_Lucid_Threshold, lastComboMove)) //Don't interupt certain combos return All.LucidDreaming; //RDM_OGCD @@ -202,7 +194,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionFound && LevelChecked(Corpsacorps)) { - if (OGCDHelper.CanUse(actionID, true, out uint oGCDAction)) return oGCDAction; + if (TryOGCDs(actionID, true, out uint oGCDAction, true)) return oGCDAction; } } //END_RDM_OGCD @@ -217,7 +209,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (Config.RDM_ST_MeleeFinisher_OnAction[1] && actionID is Riposte or EnchantedRiposte) || (Config.RDM_ST_MeleeFinisher_OnAction[2] && actionID is Veraero or Veraero3 or Verthunder or Verthunder3))); - if (ActionFound && MeleeFinisher.CanUse(lastComboMove, out uint finisherAction)) + if (ActionFound && MeleeCombo.TryMeleeFinisher(lastComboMove, out uint finisherAction)) return finisherAction; } //END_RDM_MELEEFINISHER @@ -234,212 +226,38 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionFound) { - //RDM_ST_MANAFICATIONEMBOLDEN - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden) - && LevelChecked(Embolden) - && HasCondition(ConditionFlag.InCombat) - && !HasEffect(Buffs.Dualcast) - && !HasEffect(All.Buffs.Swiftcast) - && !HasEffect(Buffs.Acceleration) - && (GetTargetDistance() <= 3 || (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_CorpsGapCloser) && HasCharges(Corpsacorps)))) - { - //Situation 1: Manafication first - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo) - && level >= 90 - && RDMMana.ManaStacks == 0 - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && RDMMana.Max <= 50 - && (RDMMana.Max >= 42 - || (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_UnbalanceMana) && blackmana == whitemana && blackmana >= 38 && HasCharges(Acceleration))) - && RDMMana.Min >= 31 - && IsOffCooldown(Manafication) - && (IsOffCooldown(Embolden) || GetCooldownRemainingTime(Embolden) <= 3)) - { - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_UnbalanceMana) - && blackmana == whitemana - && blackmana <= 44 - && blackmana >= 38 - && HasCharges(Acceleration)) - return Acceleration; - - return Manafication; - } - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo) - && level >= 90 - && lastComboMove is Zwerchhau or EnchantedZwerchhau - && RDMMana.Max >= 57 - && RDMMana.Min >= 46 - && GetCooldownRemainingTime(Manafication) >= 100 - && IsOffCooldown(Embolden)) - { - return Embolden; - } - - //Situation 2: Embolden first - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo) - && level >= 90 - && lastComboMove is Zwerchhau or EnchantedZwerchhau - && RDMMana.Max <= 57 - && RDMMana.Min <= 46 - && (GetCooldownRemainingTime(Manafication) <= 7 || IsOffCooldown(Manafication)) - && IsOffCooldown(Embolden)) - { - return Embolden; - } - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo) - && level >= 90 - && (RDMMana.ManaStacks == 0 || RDMMana.ManaStacks == 3) - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && RDMMana.Max <= 50 - && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden)) - && IsOffCooldown(Manafication)) - { - return Manafication; - } - - //Situation 3: Just use them together - if ((IsNotEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo) || level < 90) - && ActionReady(Embolden) - && RDMMana.ManaStacks == 0 - && RDMMana.Max <= 50 - && (IsOffCooldown(Manafication) || !LevelChecked(Manafication))) - { - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_UnbalanceMana) - && blackmana == whitemana - && blackmana <= 44 - && HasCharges(Acceleration)) - return Acceleration; - - return Embolden; - } - if ((IsNotEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo) || level < 90) - && ActionReady(Manafication) - && (RDMMana.ManaStacks == 0 || RDMMana.ManaStacks == 3) - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && RDMMana.Max <= 50 - && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden))) - { - return Manafication; - } - - //Situation 4: Level 58 or 59 - if (!LevelChecked(Manafication) && - ActionReady(Embolden) && - RDMMana.Min >= 50) - { - return Embolden; - } - - } //END_RDM_ST_MANAFICATIONEMBOLDEN - - //Normal Combo - if (GetTargetDistance() <= 3 || Config.RDM_ST_MeleeEnforced) - { - if ((lastComboMove is Riposte or EnchantedRiposte) - && LevelChecked(Zwerchhau) - && comboTime > 0f) - return OriginalHook(Zwerchhau); - - if (lastComboMove is Zwerchhau - && LevelChecked(Redoublement) - && comboTime > 0f) - return OriginalHook(Redoublement); - } - - if (((RDMMana.Min >= 50 && LevelChecked(Redoublement)) - || (RDMMana.Min >= 35 && !LevelChecked(Redoublement)) - || (RDMMana.Min >= 20 && !LevelChecked(Zwerchhau))) - && !HasEffect(Buffs.Dualcast)) - { - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_CorpsGapCloser) - && LevelChecked(Corpsacorps) && HasCharges(Corpsacorps) - && GetTargetDistance() > 3) - return Corpsacorps; - - if (IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_UnbalanceMana) - && LevelChecked(Acceleration) - && blackmana == whitemana - && blackmana >= 50 - && !HasEffect(Buffs.Embolden)) - { - if (HasEffect(Buffs.Acceleration) || WasLastAction(Buffs.Acceleration)) - { - //Run the Mana Balance Computer - var actions = RDMMana.CheckBalance(); - - if (actions.useAero && LevelChecked(OriginalHook(Veraero))) return OriginalHook(Veraero); - if (actions.useThunder && LevelChecked(OriginalHook(Verthunder))) return OriginalHook(Verthunder); - } - - if (HasCharges(Acceleration)) return Acceleration; - } - if (GetTargetDistance() <= 3) - return OriginalHook(Riposte); - } - + if (MeleeCombo.TrySTManaEmbolden( + actionID, lastComboMove, level, out uint ManaEmboldenID, + IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden), + IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_CorpsGapCloser), + IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_ManaEmbolden_DoubleCombo), + IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_UnbalanceMana))) + return ManaEmboldenID; + + if (MeleeCombo.TrySTMeleeCombo(actionID, lastComboMove, comboTime, out uint MeleeID, + Config.RDM_ST_MeleeEnforced, + IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_CorpsGapCloser), + IsEnabled(CustomComboPreset.RDM_ST_MeleeCombo_UnbalanceMana))) + return MeleeID; } } - //END_RDM_ST_MELEECOMBO //RDM_ST_ACCELERATION if (IsEnabled(CustomComboPreset.RDM_ST_ThunderAero) && IsEnabled(CustomComboPreset.RDM_ST_ThunderAero_Accel) - && actionID is Jolt or Jolt2 or Jolt3 - && HasCondition(ConditionFlag.InCombat) - && LocalPlayer.IsCasting == false - && RDMMana.ManaStacks == 0 - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && !HasEffect(Buffs.VerfireReady) - && !HasEffect(Buffs.VerstoneReady) - && !HasEffect(Buffs.Acceleration) - && !HasEffect(Buffs.Dualcast) - && !HasEffect(All.Buffs.Swiftcast)) + && actionID is Jolt or Jolt2 or Jolt3) { - if (ActionReady(Acceleration) - && GetCooldown(Acceleration).ChargeCooldownRemaining < 54.5) - return Acceleration; - if (IsEnabled(CustomComboPreset.RDM_ST_ThunderAero_Accel_Swiftcast) - && ActionReady(All.Swiftcast) - && !HasCharges(Acceleration)) - return All.Swiftcast; + if (SpellCombo.TryAcceleration(actionID, lastComboMove, out uint AccID, + IsEnabled(CustomComboPreset.RDM_ST_ThunderAero_Accel_Swiftcast))) + return AccID; } - //END_RDM_ST_ACCELERATION if (actionID is Jolt or Jolt2 or Jolt3) { - if (TraitLevelChecked(Traits.EnhancedAccelerationII) - && HasEffect(Buffs.GrandImpactReady)) - return GrandImpact; - - //RDM_VERFIREVERSTONE - if (IsEnabled(CustomComboPreset.RDM_ST_FireStone) - && !HasEffect(Buffs.Acceleration) - && !HasEffect(Buffs.Dualcast)) - { - //Run the Mana Balance Computer - var actions = RDMMana.CheckBalance(); - if (actions.useFire) return Verfire; - if (actions.useStone) return Verstone; - } - //END_RDM_VERFIREVERSTONE - - //RDM_VERTHUNDERVERAERO - if (IsEnabled(CustomComboPreset.RDM_ST_ThunderAero)) - { - //Run the Mana Balance Computer - var actions = RDMMana.CheckBalance(); - if (actions.useThunder) return OriginalHook(Verthunder); - if (actions.useAero) return OriginalHook(Veraero); - } - //END_RDM_VERTHUNDERVERAERO + if (SpellCombo.TrySTSpellRotation(actionID, out uint SpellID, + IsEnabled(CustomComboPreset.RDM_ST_FireStone), + IsEnabled(CustomComboPreset.RDM_ST_ThunderAero))) + return SpellID; } //NO_CONDITIONS_MET @@ -447,36 +265,81 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } + internal class RDM_AoE_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RDM_AoE_SimpleMode; + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Scatter or Impact) + { + //VARIANTS + if (IsEnabled(CustomComboPreset.RDM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RDM_VariantCure)) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.RDM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanSpellWeave(actionID)) + return Variant.VariantRampart; + + // LUCID + if (TryLucidDreaming(actionID, 6500, lastComboMove)) + return All.LucidDreaming; + + //RDM_OGCD + if (TryOGCDs(actionID, true, out uint oGCDAction, true)) return oGCDAction; + + //RDM_MELEEFINISHER + if (MeleeCombo.TryMeleeFinisher(lastComboMove, out uint finisherAction)) + return finisherAction; + + if (MeleeCombo.TryAoEManaEmbolden(actionID, lastComboMove, out uint ManaEmbolden)) + return ManaEmbolden; + + if (MeleeCombo.TryAoEMeleeCombo(actionID, lastComboMove, comboTime, out uint AoEMeleeID)) + return AoEMeleeID; + + if (SpellCombo.TryAcceleration(actionID, lastComboMove, out uint AccelID)) + return AccelID; + + if (SpellCombo.TryAoESpellRotation(actionID, out uint SpellID)) + return SpellID; + } + return actionID; + } + } + internal class RDM_AoE_DPS : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RDM_AoE_DPS; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - //VARIANTS - if (IsEnabled(CustomComboPreset.RDM_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= GetOptionValue(Config.RDM_VariantCure)) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.RDM_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanSpellWeave(actionID)) - return Variant.VariantRampart; - - // LUCID - if (IsEnabled(CustomComboPreset.RDM_AoE_Lucid) - && actionID is Scatter or Impact - && All.CanUseLucid(actionID, Config.RDM_AoE_Lucid_Threshold) - && InCombat() - && RDMLucid.SafetoUse(lastComboMove)) - return All.LucidDreaming; + if (actionID is Scatter or Impact) + { + //VARIANTS + if (IsEnabled(CustomComboPreset.RDM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= GetOptionValue(Config.RDM_VariantCure)) + return Variant.VariantCure; - //RDM_OGCD - if (IsEnabled(CustomComboPreset.RDM_AoE_oGCD) - && LevelChecked(Corpsacorps) && - actionID is Scatter or Impact && - OGCDHelper.CanUse(actionID, false, out uint oGCDAction)) return oGCDAction; + if (IsEnabled(CustomComboPreset.RDM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanSpellWeave(actionID)) + return Variant.VariantRampart; + + // LUCID + if (IsEnabled(CustomComboPreset.RDM_AoE_Lucid) + && TryLucidDreaming(actionID, Config.RDM_AoE_Lucid_Threshold, lastComboMove)) + return All.LucidDreaming; + + //RDM_OGCD + if (IsEnabled(CustomComboPreset.RDM_AoE_oGCD) + && LevelChecked(Corpsacorps) + && TryOGCDs(actionID, true, out uint oGCDAction, true)) return oGCDAction; + } //RDM_MELEEFINISHER if (IsEnabled(CustomComboPreset.RDM_AoE_MeleeFinisher)) @@ -489,7 +352,7 @@ actionID is Scatter or Impact && (Config.RDM_AoE_MeleeFinisher_OnAction[2] && actionID is Veraero2 or Verthunder2))); - if (ActionFound && MeleeFinisher.CanUse(lastComboMove, out uint finisherAction)) + if (ActionFound && MeleeCombo.TryMeleeFinisher(lastComboMove, out uint finisherAction)) return finisherAction; } //END_RDM_MELEEFINISHER @@ -506,141 +369,27 @@ actionID is Scatter or Impact && if (ActionFound) { - //Finish the combo - if (LevelChecked(Moulinet) - && lastComboMove is EnchantedMoulinet or EnchantedMoulinetDeux - && comboTime > 0f) - return OriginalHook(Moulinet); - - //RDM_AOE_MANAFICATIONEMBOLDEN - if (IsEnabled(CustomComboPreset.RDM_AoE_MeleeCombo_ManaEmbolden)) - { - if (HasCondition(ConditionFlag.InCombat) - && !HasEffect(Buffs.Dualcast) - && !HasEffect(All.Buffs.Swiftcast) - && !HasEffect(Buffs.Acceleration) - && ((GetTargetDistance() <= Config.RDM_AoE_MoulinetRange && RDMMana.ManaStacks == 0) || RDMMana.ManaStacks > 0)) - { - if (ActionReady(Manafication)) - { - //Situation 1: Embolden First (Double) - if (RDMMana.ManaStacks == 2 - && RDMMana.Min >= 22 - && IsOffCooldown(Embolden)) - { - return Embolden; - } - if (((RDMMana.ManaStacks == 3 && RDMMana.Min >= 2) || (RDMMana.ManaStacks == 0 && RDMMana.Min >= 10)) - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && RDMMana.Max <= 50 - && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden))) - { - return Manafication; - } - - //Situation 2: Embolden First (Single) - if (RDMMana.ManaStacks == 0 - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && RDMMana.Max <= 50 - && RDMMana.Min >= 10 - && IsOffCooldown(Embolden)) - { - return Embolden; - } - if (RDMMana.ManaStacks == 0 - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && RDMMana.Max <= 50 - && RDMMana.Min >= 10 - && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden))) - { - return Manafication; - } - } - - //Below Manafication Level - if (ActionReady(Embolden) && !LevelChecked(Manafication) - && RDMMana.Min >= 20) - { - return Embolden; - } - } - //END_RDM_AOE_MANAFICATIONEMBOLDEN - } - - //7.0 Manification Magic Mana - //int Mana = Math.Min(Gauge.WhiteMana, Gauge.BlackMana); - //if (LevelChecked(Manafication)) - //{ - // int ManaBuff = GetBuffStacks(Buffs.MagickedSwordPlay); - // if (ManaBuff > 0) Mana = 50; //ITS FREE REAL ESTATE - //} - - if (LevelChecked(Moulinet) - && LocalPlayer.IsCasting == false - && !HasEffect(Buffs.Dualcast) - && !HasEffect(All.Buffs.Swiftcast) - && !HasEffect(Buffs.Acceleration) - && RDMMana.Min >= 50) - { - if (IsEnabled(CustomComboPreset.RDM_AoE_MeleeCombo_CorpsGapCloser) - && ActionReady(Corpsacorps) - && GetTargetDistance() > Config.RDM_AoE_MoulinetRange) - return Corpsacorps; - - if ((GetTargetDistance() <= Config.RDM_AoE_MoulinetRange && RDMMana.ManaStacks == 0) || RDMMana.ManaStacks >= 1) - return OriginalHook(Moulinet); - } + if (IsEnabled(CustomComboPreset.RDM_AoE_MeleeCombo_ManaEmbolden) + && MeleeCombo.TryAoEManaEmbolden(actionID, lastComboMove, out uint ManaEmbolen, Config.RDM_AoE_MoulinetRange)) + return ManaEmbolen; + + if (MeleeCombo.TryAoEMeleeCombo(actionID, lastComboMove, comboTime, out uint AoEMelee, + Config.RDM_AoE_MoulinetRange, IsEnabled(CustomComboPreset.RDM_AoE_MeleeCombo_CorpsGapCloser))) + return AoEMelee; } } - //END_RDM_AOE_MELEECOMBO - - //RDM_AoE_ACCELERATION - if (IsEnabled(CustomComboPreset.RDM_AoE_Accel) - && actionID is Scatter or Impact - && LocalPlayer.IsCasting == false - && RDMMana.ManaStacks == 0 - && lastComboMove is not Verflare - && lastComboMove is not Verholy - && lastComboMove is not Scorch - && !WasLastAction(Embolden) - && (IsNotEnabled(CustomComboPreset.RDM_AoE_Accel_Weave) || CanSpellWeave(actionID)) - && !HasEffect(Buffs.Acceleration) - && !HasEffect(Buffs.Dualcast) - && !HasEffect(All.Buffs.Swiftcast)) - { - //if (level >= Levels.Acceleration - // && GetCooldown(Acceleration).RemainingCharges > 0 - // && GetCooldown(Acceleration).ChargeCooldownRemaining < 54.5) - if (ActionReady(Acceleration) //check for level and 1 charge minimum - && GetCooldown(Acceleration).ChargeCooldownRemaining < 54.5) - return Acceleration; - if (IsEnabled(CustomComboPreset.RDM_AoE_Accel_Swiftcast) - && ActionReady(All.Swiftcast) - && !HasCharges(Acceleration) - && GetCooldown(Acceleration).ChargeCooldownRemaining < 54.5) - return All.Swiftcast; - } - //END_RDM_AoE_ACCELERATION - //RDM_VERTHUNDERIIVERAEROII if (actionID is Scatter or Impact) { - - if (TraitLevelChecked(Traits.EnhancedAccelerationII) - && HasEffect(Buffs.GrandImpactReady)) - return GrandImpact; - - var actions = RDMMana.CheckBalance(); - if (actions.useThunder2) return OriginalHook(Verthunder2); - if (actions.useAero2) return OriginalHook(Veraero2); + if (IsEnabled(CustomComboPreset.RDM_AoE_Accel) + && SpellCombo.TryAcceleration(actionID, lastComboMove, out uint AccelID, + IsEnabled(CustomComboPreset.RDM_AoE_Accel_Swiftcast), IsEnabled(CustomComboPreset.RDM_AoE_Accel_Weave))) + return AccelID; + + if (SpellCombo.TryAoESpellRotation(actionID, out uint SpellID)) + return SpellID; + } - //END_RDM_VERTHUNDERIIVERAEROII return actionID; } diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs new file mode 100644 index 000000000..e69595adc --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs @@ -0,0 +1,177 @@ +using Dalamud.Interface.Colors; +using ImGuiNET; +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Extensions.UIntExtensions; +using static XIVSlothCombo.Window.Functions.UserConfig; +using static XIVSlothCombo.Window.Functions.SliderIncrements; + +namespace XIVSlothCombo.Combos.PvE +{ + internal static partial class RDM + { + internal static class Config + { + public static UserInt + RDM_VariantCure = new("RDM_VariantCure"), + RDM_ST_Lucid_Threshold = new("RDM_LucidDreaming_Threshold", 6500), + RDM_AoE_Lucid_Threshold = new("RDM_AoE_Lucid_Threshold", 6500), + RDM_AoE_MoulinetRange = new("RDM_MoulinetRange"); + public static UserBool + RDM_ST_oGCD_OnAction_Adv = new("RDM_ST_oGCD_OnAction_Adv"), + RDM_ST_oGCD_Fleche = new("RDM_ST_oGCD_Fleche"), + RDM_ST_oGCD_ContreSixte = new("RDM_ST_oGCD_ContreSixte"), + RDM_ST_oGCD_Engagement = new("RDM_ST_oGCD_Engagement"), + RDM_ST_oGCD_Engagement_Pooling = new("RDM_ST_oGCD_Engagement_Pooling"), + RDM_ST_oGCD_CorpACorps = new("RDM_ST_oGCD_CorpACorps"), + RDM_ST_oGCD_CorpACorps_Melee = new("RDM_ST_oGCD_CorpACorps_Melee"), + RDM_ST_oGCD_CorpACorps_Pooling = new("RDM_ST_oGCD_CorpACorps_Pooling"), + RDM_ST_oGCD_ViceOfThorns = new("RDM_ST_oGCD_ViceOfThorns"), + RDM_ST_oGCD_Prefulgence = new("RDM_ST_oGCD_Prefulgence"), + RDM_ST_MeleeCombo_Adv = new("RDM_ST_MeleeCombo_Adv"), + RDM_ST_MeleeFinisher_Adv = new("RDM_ST_MeleeFinisher_Adv"), + RDM_ST_MeleeEnforced = new("RDM_ST_MeleeEnforced"), + + RDM_AoE_oGCD_OnAction_Adv = new("RDM_AoE_oGCD_OnAction_Adv"), + RDM_AoE_oGCD_Fleche = new("RDM_AoE_oGCD_Fleche"), + RDM_AoE_oGCD_ContreSixte = new("RDM_AoE_oGCD_ContreSixte"), + RDM_AoE_oGCD_Engagement = new("RDM_AoE_oGCD_Engagement"), + RDM_AoE_oGCD_Engagement_Pooling = new("RDM_AoE_oGCD_Engagement_Pooling"), + RDM_AoE_oGCD_CorpACorps = new("RDM_AoE_oGCD_CorpACorps"), + RDM_AoE_oGCD_CorpACorps_Melee = new("RDM_AoE_oGCD_CorpACorps_Melee"), + RDM_AoE_oGCD_CorpACorps_Pooling = new("RDM_AoE_oGCD_CorpACorps_Pooling"), + RDM_AoE_oGCD_ViceOfThorns = new("RDM_AoE_oGCD_ViceOfThorns"), + RDM_AoE_oGCD_Prefulgence = new("RDM_AoE_oGCD_Prefulgence"), + RDM_AoE_MeleeCombo_Adv = new("RDM_AoE_MeleeCombo_Adv"), + RDM_AoE_MeleeFinisher_Adv = new("RDM_AoE_MeleeFinisher_Adv"); + public static UserBoolArray + RDM_ST_oGCD_OnAction = new("RDM_ST_oGCD_OnAction"), + RDM_ST_MeleeCombo_OnAction = new("RDM_ST_MeleeCombo_OnAction"), + RDM_ST_MeleeFinisher_OnAction = new("RDM_ST_MeleeFinisher_OnAction"), + + RDM_AoE_oGCD_OnAction = new("RDM_AoE_oGCD_OnAction"), + RDM_AoE_MeleeCombo_OnAction = new("RDM_AoE_MeleeCombo_OnAction"), + RDM_AoE_MeleeFinisher_OnAction = new("RDM_AoE_MeleeFinisher_OnAction"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.RDM_ST_oGCD: + DrawAdditionalBoolChoice(RDM_ST_oGCD_OnAction_Adv, "Advanced Action Options.", "Changes which action this option will replace.", isConditionalChoice: true); + if (RDM_ST_oGCD_OnAction_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(RDM_ST_oGCD_OnAction, $"{Jolt.ActionName()}s", "", 4, 0, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_oGCD_OnAction, Fleche.ActionName(), "", 4, 1, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_oGCD_OnAction, Riposte.ActionName(), "", 4, 2, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_oGCD_OnAction, Reprise.ActionName(), "", 4, 3, descriptionColor: ImGuiColors.DalamudYellow); + ImGui.Unindent(); + } + + DrawAdditionalBoolChoice(RDM_ST_oGCD_Fleche, Fleche.ActionName(), ""); + DrawAdditionalBoolChoice(RDM_ST_oGCD_ContreSixte, ContreSixte.ActionName(), ""); + DrawAdditionalBoolChoice(RDM_ST_oGCD_Engagement, Engagement.ActionName(), "", isConditionalChoice: true); + if (RDM_ST_oGCD_Engagement) + { + ImGui.Indent(); ImGui.Spacing(); + DrawAdditionalBoolChoice(RDM_ST_oGCD_Engagement_Pooling, "Pool one charge for manual use.", ""); + ImGui.Unindent(); + } + DrawAdditionalBoolChoice(RDM_ST_oGCD_CorpACorps, Corpsacorps.ActionName(), "", isConditionalChoice: true); + if (RDM_ST_oGCD_CorpACorps) + { + ImGui.Indent(); ImGui.Spacing(); + DrawAdditionalBoolChoice(RDM_ST_oGCD_CorpACorps_Melee, "Use only in melee range.", ""); + DrawAdditionalBoolChoice(RDM_ST_oGCD_CorpACorps_Pooling, "Pool one charge for manual use.", ""); + ImGui.Unindent(); + } + DrawAdditionalBoolChoice(RDM_ST_oGCD_ViceOfThorns, ViceOfThorns.ActionName(), ""); + DrawAdditionalBoolChoice(RDM_ST_oGCD_Prefulgence, Prefulgence.ActionName(), ""); + break; + + case CustomComboPreset.RDM_ST_MeleeCombo: + DrawAdditionalBoolChoice(RDM_ST_MeleeCombo_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); + if (RDM_ST_MeleeCombo_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(RDM_ST_MeleeCombo_OnAction, $"{Jolt.ActionName()}s", "", 2, 0, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_MeleeCombo_OnAction, Riposte.ActionName(), "", 2, 1, descriptionColor: ImGuiColors.DalamudYellow); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.RDM_ST_MeleeFinisher: + DrawAdditionalBoolChoice(RDM_ST_MeleeFinisher_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); + if (RDM_ST_MeleeFinisher_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, $"{Jolt.ActionName()}s", "", 3, 0, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, Riposte.ActionName(), "", 3, 1, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, $"{Veraero} & {Verthunder}", "", 3, 2, descriptionColor: ImGuiColors.DalamudYellow); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.RDM_ST_Lucid: + DrawSliderInt(0, 10000, RDM_ST_Lucid_Threshold, $"Add {All.LucidDreaming.ActionName()} when below this MP", sliderIncrement: Hundreds); + break; + + case CustomComboPreset.RDM_AoE_oGCD: + DrawAdditionalBoolChoice(RDM_AoE_oGCD_Fleche, Fleche.ActionName(), ""); + DrawAdditionalBoolChoice(RDM_AoE_oGCD_ContreSixte, ContreSixte.ActionName(), ""); + DrawAdditionalBoolChoice(RDM_AoE_oGCD_Engagement, Engagement.ActionName(), "", isConditionalChoice: true); + if (RDM_AoE_oGCD_Engagement) + { + ImGui.Indent(); ImGui.Spacing(); + DrawAdditionalBoolChoice(RDM_AoE_oGCD_Engagement_Pooling, "Pool one charge for manual use.", ""); + ImGui.Unindent(); + } + DrawAdditionalBoolChoice(RDM_AoE_oGCD_CorpACorps, Corpsacorps.ActionName(), "", isConditionalChoice: true); + if (RDM_AoE_oGCD_CorpACorps) + { + ImGui.Indent(); ImGui.Spacing(); + DrawAdditionalBoolChoice(RDM_AoE_oGCD_CorpACorps_Melee, "Use only in melee range.", ""); + DrawAdditionalBoolChoice(RDM_AoE_oGCD_CorpACorps_Pooling, "Pool one charge for manual use.", ""); + ImGui.Unindent(); + } + DrawAdditionalBoolChoice(RDM_AoE_oGCD_ViceOfThorns, ViceOfThorns.ActionName(), ""); + DrawAdditionalBoolChoice(RDM_AoE_oGCD_Prefulgence, Prefulgence.ActionName(), ""); + break; + + case CustomComboPreset.RDM_AoE_MeleeCombo: + DrawSliderInt(3, 8, RDM_AoE_MoulinetRange, $"Range to use first {Moulinet.ActionName()}, no range restrictions after first {Moulinet.ActionName()}", sliderIncrement: Ones); + DrawAdditionalBoolChoice(RDM_AoE_MeleeCombo_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); + if (RDM_AoE_MeleeCombo_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(RDM_AoE_MeleeCombo_OnAction, $"{Scatter.ActionName()}/{Impact.ActionName()}", "", 2, 0, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_AoE_MeleeCombo_OnAction, Moulinet.ActionName(), "", 2, 1, descriptionColor: ImGuiColors.DalamudYellow); + ImGui.Unindent(); + } + DrawAdditionalBoolChoice(RDM_ST_MeleeEnforced, "Enforced Melee Check", "Once the melee combo has started, don't switch away even if target is out of range."); + break; + + case CustomComboPreset.RDM_AoE_MeleeFinisher: + DrawAdditionalBoolChoice(RDM_AoE_MeleeFinisher_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); + if (RDM_AoE_MeleeFinisher_Adv) + { + ImGui.Indent(); ImGui.Spacing(); + DrawHorizontalMultiChoice(RDM_AoE_MeleeFinisher_OnAction, $"{Scatter.ActionName()}/{Impact.ActionName()}", "", 3, 0, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_AoE_MeleeFinisher_OnAction, Moulinet.ActionName(), "", 3, 1, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_AoE_MeleeFinisher_OnAction, $"{Veraero2.ActionName()} & {Verthunder3.ActionName()}", "", 3, 2, descriptionColor: ImGuiColors.DalamudYellow); + ImGui.Unindent(); + } + break; + + case CustomComboPreset.RDM_AoE_Lucid: + DrawSliderInt(0, 10000, RDM_AoE_Lucid_Threshold, $"Add {All.LucidDreaming.ActionName()} when below this MP", sliderIncrement: Hundreds); + break; + + case CustomComboPreset.RDM_Variant_Cure: + DrawSliderInt(1, 100, RDM_VariantCure, "HP% to be at or under", 200); + break; + } + } + } + } +} diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs index 992b4d988..5848f2689 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs @@ -1,17 +1,17 @@ -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Objects.Types; using ECommons.DalamudServices; using System; using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Data; -using static XIVSlothCombo.Combos.PvE.RDM; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.PvE { - internal class RDMHelper + internal static partial class RDM { - internal class RDMMana + private class RDMMana { private static RDMGauge Gauge => GetJobGauge(); internal static int ManaStacks => Gauge.ManaStacks; @@ -35,87 +35,465 @@ private static int AdjustMana(byte mana) } else return mana; } + } - public static (bool useFire, bool useStone, bool useThunder, bool useAero, bool useThunder2, bool useAero2) CheckBalance() + private static bool TryOGCDs(uint actionID, in bool SingleTarget, out uint newActionID, bool AdvMode = false) + { + var distance = GetTargetDistance(); + + uint placeOGCD = 0; + + //Simple Settings + bool fleche = true; + bool contre = true; + bool engagement = false; + bool vice = true; + bool prefulg = true; + int engagementPool = 0; + bool corpacorps = false; + int corpsacorpsPool = 0; + int corpacorpsRange = 25; + + if (AdvMode) { - //SYSTEM_MANA_BALANCING_MACHINE - //Machine to decide which ver spell should be used. - //Rules: - //1.Avoid perfect balancing [NOT DONE] - // - Jolt adds 2/2 mana - // - Scatter/Impact adds 3/3 mana - // - Verstone/Verfire add 5 mana - // - Veraero/Verthunder add 6 mana - // - Veraero2/Verthunder2 add 7 mana - // - Verholy/Verflare add 11 mana - // - Scorch adds 4/4 mana - // - Resolution adds 4/4 mana - //2.Stay within difference limit [DONE] - //3.Strive to achieve correct mana for double melee combo burst [DONE] - int blackmana = Black; - int whitemana = White; - //Reset outputs - bool useFire = false; - bool useStone = false; - bool useThunder = false; - bool useAero = false; - bool useThunder2 = false; - bool useAero2 = false; + fleche = SingleTarget ? Config.RDM_ST_oGCD_Fleche : Config.RDM_AoE_oGCD_Fleche; + contre = SingleTarget ? Config.RDM_ST_oGCD_ContreSixte : Config.RDM_AoE_oGCD_ContreSixte; + engagement = SingleTarget ? Config.RDM_ST_oGCD_Engagement : Config.RDM_AoE_oGCD_Engagement; + vice = SingleTarget ? Config.RDM_ST_oGCD_ViceOfThorns : Config.RDM_AoE_oGCD_ViceOfThorns; + prefulg = SingleTarget ? Config.RDM_ST_oGCD_Prefulgence : Config.RDM_AoE_oGCD_Prefulgence; + + engagementPool = (SingleTarget && Config.RDM_ST_oGCD_Engagement_Pooling) || (!SingleTarget && Config.RDM_AoE_oGCD_Engagement_Pooling) ? 1 : 0; + corpacorps = SingleTarget ? Config.RDM_ST_oGCD_CorpACorps : Config.RDM_AoE_oGCD_CorpACorps; + corpsacorpsPool = (SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Pooling) || (!SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Pooling) ? 1 : 0; + corpacorpsRange = (SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Melee) || (!SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Melee) ? 3 : 25; + } - //ST - if (LevelChecked(Verthunder) - && (HasEffect(Buffs.Dualcast) || HasEffect(All.Buffs.Swiftcast) || HasEffect(Buffs.Acceleration))) + //Grabs an oGCD to return based on radio options + + if (placeOGCD == 0 + && engagement + && (GetRemainingCharges(Engagement) > engagementPool + || (GetRemainingCharges(Engagement) == 1 && GetCooldownRemainingTime(Engagement) < 3)) + && LevelChecked(Engagement) + && distance <= 3) + placeOGCD = Engagement; + + if (placeOGCD == 0 + && corpacorps + && (GetRemainingCharges(Corpsacorps) > corpsacorpsPool + || (GetRemainingCharges(Corpsacorps) == 1 && GetCooldownRemainingTime(Corpsacorps) < 3)) + && ((GetRemainingCharges(Corpsacorps) >= GetRemainingCharges(Engagement)) || !LevelChecked(Engagement)) // Try to alternate between Corps-a-corps and Engagement + && LevelChecked(Corpsacorps) + && distance <= corpacorpsRange) + placeOGCD = Corpsacorps; + + if (placeOGCD == 0 + && contre + && ActionReady(ContreSixte)) + placeOGCD = ContreSixte; + + if (placeOGCD == 0 + && fleche + && ActionReady(Fleche)) + placeOGCD = Fleche; + + if (placeOGCD == 0 + && vice + && TraitLevelChecked(Traits.EnhancedEmbolden) + && HasEffect(Buffs.ThornedFlourish)) + placeOGCD = ViceOfThorns; + + if (placeOGCD == 0 + && prefulg + && TraitLevelChecked(Traits.EnhancedManaficationIII) + && HasEffect(Buffs.PrefulugenceReady)) + placeOGCD = Prefulgence; + + if (CanSpellWeave(actionID) && placeOGCD != 0) + { + newActionID = placeOGCD; + return true; + } + + if (actionID is Fleche && placeOGCD == 0) // All actions are on cooldown, determine the lowest CD to display on Fleche. + { + placeOGCD = Fleche; + if (contre + && LevelChecked(ContreSixte) + && GetCooldownRemainingTime(placeOGCD) > GetCooldownRemainingTime(ContreSixte)) + placeOGCD = ContreSixte; + if (corpacorps + && LevelChecked(Corpsacorps) + && !HasCharges(Corpsacorps) + && GetCooldownRemainingTime(placeOGCD) > GetCooldownRemainingTime(Corpsacorps)) + placeOGCD = Corpsacorps; + if (engagement + && LevelChecked(Engagement) + && GetCooldownRemainingTime(Engagement) == 0 + && GetCooldownRemainingTime(placeOGCD) > GetCooldownRemainingTime(Engagement)) + placeOGCD = Engagement; + } + if (actionID is Fleche) + { + newActionID = placeOGCD; + return true; + } + + newActionID = 0; + return false; + } + + private static bool TryLucidDreaming(uint actionID, int MPThreshold, uint lastComboMove) + { + return + All.CanUseLucid(actionID, MPThreshold) + && InCombat() + && !HasEffect(Buffs.Dualcast) + && lastComboMove != EnchantedRiposte + && lastComboMove != EnchantedZwerchhau + && lastComboMove != EnchantedRedoublement + && lastComboMove != Verflare + && lastComboMove != Verholy + && lastComboMove != Scorch; // Change abilities to Lucid Dreaming for entire weave window + } + + private class MeleeCombo + { + internal static bool TrySTManaEmbolden(uint actionID, uint lastComboMove, byte level, out uint newActionID, + //Simple Mode Values + bool ManaEmbolden = true, bool GapCloser = true, bool DoubleCombo = true, bool UnBalanceMana = true ) + { + //RDM_ST_MANAFICATIONEMBOLDEN + if (ManaEmbolden + && LevelChecked(Embolden) + && HasCondition(ConditionFlag.InCombat) + && !HasEffect(Buffs.Dualcast) + && !HasEffect(All.Buffs.Swiftcast) + && !HasEffect(Buffs.Acceleration) + && (GetTargetDistance() <= 3 || (GapCloser && HasCharges(Corpsacorps)))) { - if (blackmana <= whitemana || HasEffect(Buffs.VerstoneReady)) useThunder = true; - if (whitemana <= blackmana || HasEffect(Buffs.VerfireReady)) useAero = true; - if (!LevelChecked(Veraero)) useThunder = true; + //Situation 1: Manafication first + if (DoubleCombo + && level >= 90 + && RDMMana.ManaStacks == 0 + && lastComboMove is not Verflare + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && RDMMana.Max <= 50 + && (RDMMana.Max >= 42 + || (UnBalanceMana && RDMMana.Black == RDMMana.White && RDMMana.Black >= 38 && HasCharges(Acceleration))) + && RDMMana.Min >= 31 + && IsOffCooldown(Manafication) + && (IsOffCooldown(Embolden) || GetCooldownRemainingTime(Embolden) <= 3)) + { + if (UnBalanceMana + && RDMMana.Black == RDMMana.White + && RDMMana.Black <= 44 + && RDMMana.Black >= 38 + && HasCharges(Acceleration)) + { + newActionID = Acceleration; + return true; + } + + newActionID = Manafication; + return true; + } + if (DoubleCombo + && level >= 90 + && lastComboMove is Zwerchhau or EnchantedZwerchhau + && RDMMana.Max >= 57 + && RDMMana.Min >= 46 + && GetCooldownRemainingTime(Manafication) >= 100 + && IsOffCooldown(Embolden)) + { + newActionID = Embolden; + return true; + } + + //Situation 2: Embolden first + if (DoubleCombo + && level >= 90 + && lastComboMove is Zwerchhau or EnchantedZwerchhau + && RDMMana.Max <= 57 + && RDMMana.Min <= 46 + && (GetCooldownRemainingTime(Manafication) <= 7 || IsOffCooldown(Manafication)) + && IsOffCooldown(Embolden)) + { + newActionID = Embolden; + return true; + } + if (DoubleCombo + && level >= 90 + && (RDMMana.ManaStacks == 0 || RDMMana.ManaStacks == 3) + && lastComboMove is not Verflare + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && RDMMana.Max <= 50 + && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden)) + && IsOffCooldown(Manafication)) + { + newActionID = Manafication; + return true; + } + + //Situation 3: Just use them together + if ((!DoubleCombo || level < 90) + && ActionReady(Embolden) + && RDMMana.ManaStacks == 0 + && RDMMana.Max <= 50 + && (IsOffCooldown(Manafication) || !LevelChecked(Manafication))) + { + if (UnBalanceMana + && RDMMana.Black == RDMMana.White + && RDMMana.Black <= 44 + && HasCharges(Acceleration)) + { + newActionID = Acceleration; + return true; + } + { + newActionID = Embolden; + return true; + } + } + if ((!DoubleCombo || level < 90) + && ActionReady(Manafication) + && (RDMMana.ManaStacks == 0 || RDMMana.ManaStacks == 3) + && lastComboMove is not Verflare + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && RDMMana.Max <= 50 + && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden))) + { + newActionID = Manafication; + return true; + } + + //Situation 4: Level 58 or 59 + if (!LevelChecked(Manafication) && + ActionReady(Embolden) && + RDMMana.Min >= 50) + { + newActionID = Embolden; + return true; + } + + } //END_RDM_ST_MANAFICATIONEMBOLDEN + newActionID = actionID; + return false; + } + + internal static bool TrySTMeleeCombo(uint actionID, uint lastComboMove, float comboTime, out uint newActionID, + //Simple Mode Values + bool MeleeEnforced = true, bool GapCloser = true, bool UnbalanceMana = true) + { + //Test + if (GapCloser + && ActionReady(Corpsacorps) + && !(CurrentTarget as IBattleChara).IsCasting + && GetTargetDistance() > 3) + { + newActionID = Corpsacorps; + return true; } - if (!HasEffect(Buffs.Dualcast) - && !HasEffect(All.Buffs.Swiftcast) - && !HasEffect(Buffs.Acceleration)) + + //Normal Combo + if (GetTargetDistance() <= 3 || MeleeEnforced) { - //Checking the time remaining instead of just the effect, to stop last second bad casts - bool VerFireReady = GetBuffRemainingTime(Buffs.VerfireReady) >= GetActionCastTime(Verfire); - bool VerStoneReady = GetBuffRemainingTime(Buffs.VerstoneReady) >= GetActionCastTime(Verstone); + if ((lastComboMove is Riposte or EnchantedRiposte) + && LevelChecked(Zwerchhau) + && comboTime > 0f) + { + newActionID = OriginalHook(Zwerchhau); + return true; + } - //Prioritize mana balance - if (blackmana <= whitemana && VerFireReady) useFire = true; - if (whitemana <= blackmana && VerStoneReady) useStone = true; - //Else use the action if we can - if (!useFire && !useStone && VerFireReady) useFire = true; - if (!useFire && !useStone && VerStoneReady) useStone = true; + if (lastComboMove is Zwerchhau + && LevelChecked(Redoublement) + && comboTime > 0f) + { + newActionID= OriginalHook(Redoublement); + return true; + } } - //AoE - if (LevelChecked(Verthunder2) + if (((RDMMana.Min >= 50 && LevelChecked(Redoublement)) + || (RDMMana.Min >= 35 && !LevelChecked(Redoublement)) + || (RDMMana.Min >= 20 && !LevelChecked(Zwerchhau))) + && !HasEffect(Buffs.Dualcast)) + { + if (GapCloser + && ActionReady(Corpsacorps) + && !(CurrentTarget as IBattleChara).IsCasting + && GetTargetDistance() > 3) + { + newActionID = Corpsacorps; + return true; + } + + if (UnbalanceMana + && LevelChecked(Acceleration) + && RDMMana.Black == RDMMana.White + && RDMMana.Black >= 50 + && !HasEffect(Buffs.Embolden)) + { + if (HasEffect(Buffs.Acceleration) || WasLastAction(Buffs.Acceleration)) + { + //Run the Mana Balance Computer + #pragma warning disable IDE0042 + var actions = SpellCombo.GetSpells(); + #pragma warning restore IDE0042 + + if (actions.useAero && LevelChecked(OriginalHook(Veraero))) + { + newActionID = OriginalHook(Veraero); + return true; + } + + if (actions.useThunder && LevelChecked(OriginalHook(Verthunder))) + { + newActionID = OriginalHook(Verthunder); + return true; + } + } + + if (HasCharges(Acceleration)) { + newActionID = Acceleration; return true; + } + + } + if (GetTargetDistance() <= 3) + { + newActionID = OriginalHook(Riposte); + return true; + } + } + + newActionID = actionID; + return false; + } + + internal static bool TryAoEManaEmbolden(uint actionID, uint lastComboMove, out uint newActionID, + //Simple Mode Values + int MoulinetRange = 6)//idk just making this up + { + if (InCombat() && !HasEffect(Buffs.Dualcast) && !HasEffect(All.Buffs.Swiftcast) - && !HasEffect(Buffs.Acceleration)) + && !HasEffect(Buffs.Acceleration) + && ((GetTargetDistance() <= MoulinetRange && RDMMana.ManaStacks == 0) || RDMMana.ManaStacks > 0)) { - if (blackmana <= whitemana || !LevelChecked(Veraero2)) useThunder2 = true; - else useAero2 = true; + if (ActionReady(Manafication)) + { + //Situation 1: Embolden First (Double) + if (RDMMana.ManaStacks == 2 + && RDMMana.Min >= 22 + && IsOffCooldown(Embolden)) + { + newActionID = Embolden; + return true; + } + if (((RDMMana.ManaStacks == 3 && RDMMana.Min >= 2) || (RDMMana.ManaStacks == 0 && RDMMana.Min >= 10)) + && lastComboMove is not Verflare + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && RDMMana.Max <= 50 + && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden))) + { + newActionID = Manafication; + return true; + } + + //Situation 2: Embolden First (Single) + if (RDMMana.ManaStacks == 0 + && lastComboMove is not Verflare + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && RDMMana.Max <= 50 + && RDMMana.Min >= 10 + && IsOffCooldown(Embolden)) + { + newActionID = Embolden; + return true; + } + if (RDMMana.ManaStacks == 0 + && lastComboMove is not Verflare + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && RDMMana.Max <= 50 + && RDMMana.Min >= 10 + && (HasEffect(Buffs.Embolden) || WasLastAction(Embolden))) + { + newActionID = Manafication; + return true; + } + } + + //Below Manafication Level + if (ActionReady(Embolden) && !LevelChecked(Manafication) + && RDMMana.Min >= 20) + { + newActionID = Embolden; + return true; + } } - //END_SYSTEM_MANA_BALANCING_MACHINE - return (useFire, useStone, useThunder, useAero, useThunder2, useAero2); + newActionID = actionID; + return false; } - } - internal class MeleeFinisher - { - internal static bool CanUse(in uint lastComboMove, out uint actionID) + internal static bool TryAoEMeleeCombo(uint actionID, uint lastComboMove, float comboTime, out uint newActionID, + //Simple Mode Values + int MoulinetRange = 6, + bool GapCloser = true) { - int blackmana = RDMMana.Black; - int whitemana = RDMMana.White; + //Finish the combo + if (LevelChecked(Moulinet) + && lastComboMove is EnchantedMoulinet or EnchantedMoulinetDeux + && comboTime > 0f) + { + newActionID = OriginalHook(Moulinet); + return true; + } + if (LevelChecked(Moulinet) + && LocalPlayer.IsCasting == false + && !HasEffect(Buffs.Dualcast) + && !HasEffect(All.Buffs.Swiftcast) + && !HasEffect(Buffs.Acceleration) + && RDMMana.Min >= 50) + { + if (GapCloser + && ActionReady(Corpsacorps) + && GetTargetDistance() > MoulinetRange) + { + newActionID = Corpsacorps; + return true; + } + + if ((GetTargetDistance() <= MoulinetRange && RDMMana.ManaStacks == 0) || RDMMana.ManaStacks >= 1) + { + newActionID = OriginalHook(Moulinet); + return true; + } + + } + + newActionID = actionID; + return false; + } + + internal static bool TryMeleeFinisher(uint lastComboMove, out uint actionID) + { if (RDMMana.ManaStacks >= 3) { - if (blackmana >= whitemana && LevelChecked(Verholy)) + if (RDMMana.Black >= RDMMana.White && LevelChecked(Verholy)) { if ((!HasEffect(Buffs.Embolden) || GetBuffRemainingTime(Buffs.Embolden) < 10) && !HasEffect(Buffs.VerfireReady) && HasEffect(Buffs.VerstoneReady) && GetBuffRemainingTime(Buffs.VerstoneReady) >= 10 - && (blackmana - whitemana <= 18)) + && (RDMMana.Black - RDMMana.White <= 18)) { actionID = Verflare; return true; @@ -129,7 +507,7 @@ internal static bool CanUse(in uint lastComboMove, out uint actionID) && HasEffect(Buffs.VerfireReady) && GetBuffRemainingTime(Buffs.VerfireReady) >= 10 && !HasEffect(Buffs.VerstoneReady) && LevelChecked(Verholy) - && (whitemana - blackmana <= 18)) + && (RDMMana.White - RDMMana.Black <= 18)) { actionID = Verholy; return true; @@ -155,120 +533,192 @@ internal static bool CanUse(in uint lastComboMove, out uint actionID) actionID = 0; return false; } + } - internal class OGCDHelper + private class SpellCombo { - internal static bool CanUse(in uint actionID, in bool SingleTarget, out uint newActionID) + private static bool TryGrandImpact(uint actionID, out uint newActionID) { - var distance = GetTargetDistance(); - - uint placeOGCD = 0; - - bool fleche = SingleTarget ? Config.RDM_ST_oGCD_Fleche : Config.RDM_AoE_oGCD_Fleche; - bool contra = SingleTarget ? Config.RDM_ST_oGCD_ContraSixte : Config.RDM_AoE_oGCD_ContraSixte; - bool engagement = SingleTarget ? Config.RDM_ST_oGCD_Engagement : Config.RDM_AoE_oGCD_Engagement; - bool vice = SingleTarget ? Config.RDM_ST_oGCD_ViceOfThorns : Config.RDM_AoE_oGCD_ViceOfThorns; - bool prefulg = SingleTarget ? Config.RDM_ST_oGCD_Prefulgence : Config.RDM_AoE_oGCD_Prefulgence; - int engagementPool = (SingleTarget && Config.RDM_ST_oGCD_Engagement_Pooling) || (!SingleTarget && Config.RDM_AoE_oGCD_Engagement_Pooling) ? 1 : 0; - - bool corpacorps = SingleTarget ? Config.RDM_ST_oGCD_CorpACorps : Config.RDM_AoE_oGCD_CorpACorps; - int corpsacorpsPool = (SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Pooling) || (!SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Pooling) ? 1 : 0; - int corpacorpsRange = (SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Melee) || (!SingleTarget && Config.RDM_ST_oGCD_CorpACorps_Melee) ? 3 : 25; - - - //Grabs an oGCD to return based on radio options - - if (placeOGCD == 0 - && engagement - && (GetRemainingCharges(Engagement) > engagementPool - || (GetRemainingCharges(Engagement) == 1 && GetCooldownRemainingTime(Engagement) < 3)) - && LevelChecked(Engagement) - && distance <= 3) - placeOGCD = Engagement; - - if (placeOGCD == 0 - && corpacorps - && (GetRemainingCharges(Corpsacorps) > corpsacorpsPool - || (GetRemainingCharges(Corpsacorps) == 1 && GetCooldownRemainingTime(Corpsacorps) < 3)) - && ((GetRemainingCharges(Corpsacorps) >= GetRemainingCharges(Engagement)) || !LevelChecked(Engagement)) // Try to alternate between Corps-a-corps and Engagement - && LevelChecked(Corpsacorps) - && distance <= corpacorpsRange) - placeOGCD = Corpsacorps; - - if (placeOGCD == 0 - && contra - && ActionReady(ContreSixte)) - placeOGCD = ContreSixte; + if (TraitLevelChecked(Traits.EnhancedAccelerationII) + && HasEffect(Buffs.GrandImpactReady) + && !HasEffect(Buffs.Dualcast)) + { + newActionID = GrandImpact; + return true; + } - if (placeOGCD == 0 - && fleche - && ActionReady(Fleche)) - placeOGCD = Fleche; + newActionID = actionID; + return false; + } + internal static bool TryAcceleration(uint actionID, uint lastComboMove, out uint newActionID, bool swiftcast = true, bool AoEWeave = false) + { + //RDM_ST_ACCELERATION + if (InCombat() + && LocalPlayer.IsCasting == false + && RDMMana.ManaStacks == 0 + && lastComboMove is not Verflare //are these needed if the finisher is still going on? + && lastComboMove is not Verholy + && lastComboMove is not Scorch + && !WasLastAction(Embolden) + && (!AoEWeave || CanSpellWeave(actionID)) + && !HasEffect(Buffs.VerfireReady) + && !HasEffect(Buffs.VerstoneReady) + && !HasEffect(Buffs.Acceleration) + && !HasEffect(Buffs.Dualcast) + && !HasEffect(All.Buffs.Swiftcast)) + { + if (ActionReady(Acceleration) + && GetCooldown(Acceleration).ChargeCooldownRemaining < 54.5) + { + newActionID = Acceleration; + return true; + } + if (swiftcast + && ActionReady(All.Swiftcast) + && !HasCharges(Acceleration)) + { + newActionID = All.Swiftcast; + return true; + } + } + //Else + newActionID = actionID; + return false; + } + internal static bool TrySTSpellRotation(uint actionID, out uint newActionID, bool FireStone = true, bool ThunderAero = true) + { + if (TryGrandImpact(actionID, out uint GrandID)) + { + newActionID = GrandID; + return true; + } - if (placeOGCD == 0 - && vice - && TraitLevelChecked(Traits.EnhancedEmbolden) - && HasEffect(Buffs.ThornedFlourish)) - placeOGCD = ViceOfThorns; + //SHUT UP ITS FINE + #pragma warning disable IDE0042 + var actions = GetSpells(); + #pragma warning restore IDE0042 - if (placeOGCD == 0 - && prefulg - && TraitLevelChecked(Traits.EnhancedManaficationIII) - && HasEffect(Buffs.PrefulugenceReady)) - placeOGCD = Prefulgence; + //RDM_VERFIREVERSTONE + if (FireStone + && !HasEffect(Buffs.Acceleration) + && !HasEffect(Buffs.Dualcast)) + { + //Run the Mana Balance Computer + if (actions.useFire) { newActionID = Verfire; return true; } + if (actions.useStone) { newActionID = Verstone; return true; } + } + //END_RDM_VERFIREVERSTONE - if (CanSpellWeave(actionID) && placeOGCD != 0) + //RDM_VERTHUNDERVERAERO + if (ThunderAero) + { + //Run the Mana Balance Computer + if (actions.useThunder) + { + newActionID = OriginalHook(Verthunder); + return true; + } + if (actions.useAero) + { + newActionID = OriginalHook(Veraero); + return true; + } + } + newActionID = actionID; + return false; + } + internal static bool TryAoESpellRotation(uint actionID, out uint newActionID) + { + if (TryGrandImpact(actionID, out uint GrandID)) { - newActionID = placeOGCD; + newActionID = GrandID; return true; } + + //SHUT UP ITS FINE + #pragma warning disable IDE0042 + var actions = GetSpells(); + #pragma warning restore IDE0042 - if (actionID is Fleche && placeOGCD == 0) // All actions are on cooldown, determine the lowest CD to display on Fleche. + if (actions.useThunder2) { - placeOGCD = Fleche; - if (contra - && LevelChecked(ContreSixte) - && GetCooldownRemainingTime(placeOGCD) > GetCooldownRemainingTime(ContreSixte)) - placeOGCD = ContreSixte; - if (corpacorps - && LevelChecked(Corpsacorps) - && !HasCharges(Corpsacorps) - && GetCooldownRemainingTime(placeOGCD) > GetCooldownRemainingTime(Corpsacorps)) - placeOGCD = Corpsacorps; - if (engagement - && LevelChecked(Engagement) - && GetCooldownRemainingTime(Engagement) == 0 - && GetCooldownRemainingTime(placeOGCD) > GetCooldownRemainingTime(Engagement)) - placeOGCD = Engagement; + newActionID = OriginalHook(Verthunder2); + return true; } - if (actionID is Fleche) + if (actions.useAero2) { - newActionID = placeOGCD; + newActionID = OriginalHook(Veraero2); return true; } - newActionID = 0; + newActionID = actionID; return false; } - } - - internal class RDMLucid - { - internal static bool SafetoUse(in uint lastComboMove) + internal static (bool useFire, bool useStone, bool useThunder, bool useAero, bool useThunder2, bool useAero2) GetSpells() { - return - !HasEffect(Buffs.Dualcast) - && lastComboMove != EnchantedRiposte - && lastComboMove != EnchantedZwerchhau - && lastComboMove != EnchantedRedoublement - && lastComboMove != Verflare - && lastComboMove != Verholy - && lastComboMove != Scorch; // Change abilities to Lucid Dreaming for entire weave window + //SYSTEM_MANA_BALANCING_MACHINE + //Machine to decide which ver spell should be used. + //Rules: + //1.Avoid perfect balancing [NOT DONE] + // - Jolt adds 2/2 mana + // - Scatter/Impact adds 3/3 mana + // - Verstone/Verfire add 5 mana + // - Veraero/Verthunder add 6 mana + // - Veraero2/Verthunder2 add 7 mana + // - Verholy/Verflare add 11 mana + // - Scorch adds 4/4 mana + // - Resolution adds 4/4 mana + //2.Stay within difference limit [DONE] + //3.Strive to achieve correct mana for double melee combo burst [DONE] + //Reset outputs + bool useFire = false; + bool useStone = false; + bool useThunder = false; + bool useAero = false; + bool useThunder2 = false; + bool useAero2 = false; + + //ST + if (LevelChecked(Verthunder) + && (HasEffect(Buffs.Dualcast) || HasEffect(All.Buffs.Swiftcast) || HasEffect(Buffs.Acceleration))) + { + if (RDMMana.Black <= RDMMana.White || HasEffect(Buffs.VerstoneReady)) useThunder = true; + if (RDMMana.White <= RDMMana.Black || HasEffect(Buffs.VerfireReady)) useAero = true; + if (!LevelChecked(Veraero)) useThunder = true; + } + if (!HasEffect(Buffs.Dualcast) + && !HasEffect(All.Buffs.Swiftcast) + && !HasEffect(Buffs.Acceleration)) + { + //Checking the time remaining instead of just the effect, to stop last second bad casts + bool VerFireReady = GetBuffRemainingTime(Buffs.VerfireReady) >= GetActionCastTime(Verfire); + bool VerStoneReady = GetBuffRemainingTime(Buffs.VerstoneReady) >= GetActionCastTime(Verstone); + + //Prioritize mana balance + if (RDMMana.Black <= RDMMana.White && VerFireReady) useFire = true; + if (RDMMana.White <= RDMMana.Black && VerStoneReady) useStone = true; + //Else use the action if we can + if (!useFire && !useStone && VerFireReady) useFire = true; + if (!useFire && !useStone && VerStoneReady) useStone = true; + } + + //AoE + if (LevelChecked(Verthunder2) + && !HasEffect(Buffs.Dualcast) + && !HasEffect(All.Buffs.Swiftcast) + && !HasEffect(Buffs.Acceleration)) + { + if (RDMMana.Black <= RDMMana.White || !LevelChecked(Veraero2)) useThunder2 = true; + else useAero2 = true; + } + //END_SYSTEM_MANA_BALANCING_MACHINE + + return (useFire, useStone, useThunder, useAero, useThunder2, useAero2); } } - internal class RDMOpenerLogic + internal static class RDMOpenerLogic { private static bool HasCooldowns() { @@ -301,17 +751,17 @@ private static bool HasCooldowns() private static uint OpenerLevel => 100; - public uint PrePullStep = 0; + public static uint PrePullStep = 0; - public uint OpenerStep = 0; + public static uint OpenerStep = 0; public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; + private static OpenerState currentState = OpenerState.PrePull; - public OpenerState CurrentState + public static OpenerState CurrentState { get { @@ -340,7 +790,7 @@ public OpenerState CurrentState } } - private bool DoPrePullSteps(ref uint actionID) + private static bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; @@ -369,7 +819,7 @@ private bool DoPrePullSteps(ref uint actionID) return false; } - private bool DoOpener(ref uint actionID) + private static bool DoOpener(ref uint actionID) { if (!LevelChecked) return false; @@ -501,13 +951,13 @@ private bool DoOpener(ref uint actionID) return false; } - private void ResetOpener() + private static void ResetOpener() { PrePullStep = 0; OpenerStep = 0; } - public bool DoFullOpener(ref uint actionID) + public static bool DoFullOpener(ref uint actionID) { if (!LevelChecked) return false; diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 8bd21274d..6891c032b 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -285,7 +285,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo //case PCT.JobID: PCT.Config.Draw(preset); break; //case PLD.JobID: PLD.Config.Draw(preset); break; //case RPR.JobID: RPR.Config.Draw(preset); break; - //case RDM.JobID: RDM.Config.Draw(preset); break; + case RDM.JobID: RDM.Config.Draw(preset); break; //case SAM.JobID: SAM.Config.Draw(preset); break; //case SCH.JobID: SCH.Config.Draw(preset); break; //case SGE.JobID: SGE.Config.Draw(preset); break; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 1d25524fc..6032d4d30 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1862,132 +1862,7 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region RED MAGE - if (preset is CustomComboPreset.RDM_ST_oGCD) - { - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_OnAction_Adv, "Advanced Action Options.", "Changes which action this option will replace.", isConditionalChoice: true); - if (RDM.Config.RDM_ST_oGCD_OnAction_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_oGCD_OnAction, "Jolts", "", 4, 0, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_oGCD_OnAction, "Fleche", "", 4, 1, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_oGCD_OnAction, "Riposte", "", 4, 2, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_oGCD_OnAction, "Reprise", "", 4, 3, descriptionColor: ImGuiColors.DalamudYellow); - ImGui.Unindent(); - } - - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_Fleche, "Fleche", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_ContraSixte, "Contra Sixte", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_Engagement, "Engagement", "", isConditionalChoice: true); - if (RDM.Config.RDM_ST_oGCD_Engagement) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_Engagement_Pooling, "Pool one charge for manual use.", ""); - ImGui.Unindent(); - } - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_CorpACorps, "Corp-a-Corps", "", isConditionalChoice: true); - if (RDM.Config.RDM_ST_oGCD_CorpACorps) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_CorpACorps_Melee, "Use only in melee range.", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_CorpACorps_Pooling, "Pool one charge for manual use.", ""); - ImGui.Unindent(); - } - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_ViceOfThorns, "Vice of Thorns", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_oGCD_Prefulgence, "Prefulgence", ""); - } - - if (preset is CustomComboPreset.RDM_ST_MeleeCombo) - { - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_MeleeCombo_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); - if (RDM.Config.RDM_ST_MeleeCombo_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_MeleeCombo_OnAction, "Jolts", "", 2, 0, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_MeleeCombo_OnAction, "Riposte", "", 2, 1, descriptionColor: ImGuiColors.DalamudYellow); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.RDM_ST_MeleeFinisher) - { - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_MeleeFinisher_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); - if (RDM.Config.RDM_ST_MeleeFinisher_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_MeleeFinisher_OnAction, "Jolts", "", 3, 0, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_MeleeFinisher_OnAction, "Riposte", "", 3, 1, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_ST_MeleeFinisher_OnAction, "VerAero & VerThunder", "", 3, 2, descriptionColor: ImGuiColors.DalamudYellow); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.RDM_ST_Lucid) - UserConfig.DrawSliderInt(0, 10000, RDM.Config.RDM_ST_Lucid_Threshold, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); - - // AoE - if (preset is CustomComboPreset.RDM_AoE_oGCD) - { - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_Fleche, "Fleche", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_ContraSixte, "Contra Sixte", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_Engagement, "Engagement", "", isConditionalChoice: true); - if (RDM.Config.RDM_AoE_oGCD_Engagement) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_Engagement_Pooling, "Pool one charge for manual use.", ""); - ImGui.Unindent(); - } - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_CorpACorps, "Corp-a-Corps", "", isConditionalChoice: true); - if (RDM.Config.RDM_AoE_oGCD_CorpACorps) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_CorpACorps_Melee, "Use only in melee range.", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_CorpACorps_Pooling, "Pool one charge for manual use.", ""); - ImGui.Unindent(); - } - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_ViceOfThorns, "Vice of Thorns", ""); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_oGCD_Prefulgence, "Prefulgence", ""); - } - - if (preset is CustomComboPreset.RDM_AoE_MeleeCombo) - { - UserConfig.DrawSliderInt(3, 8, RDM.Config.RDM_AoE_MoulinetRange, "Range to use first Moulinet; no range restrictions after first Moulinet", sliderIncrement: SliderIncrements.Ones); - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_MeleeCombo_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); - if (RDM.Config.RDM_AoE_MeleeCombo_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_AoE_MeleeCombo_OnAction, "Scatter/Impact", "", 2, 0, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_AoE_MeleeCombo_OnAction, "Moulinet", "", 2, 1, descriptionColor: ImGuiColors.DalamudYellow); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.RDM_AoE_MeleeFinisher) - { - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_AoE_MeleeFinisher_Adv, "Advanced Action Options", "Changes which action this option will replace.", isConditionalChoice: true); - if (RDM.Config.RDM_AoE_MeleeFinisher_Adv) - { - ImGui.Indent(); ImGui.Spacing(); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_AoE_MeleeFinisher_OnAction, "Scatter/Impact", "", 3, 0, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_AoE_MeleeFinisher_OnAction, "Moulinet", "", 3, 1, descriptionColor: ImGuiColors.DalamudYellow); - UserConfig.DrawHorizontalMultiChoice(RDM.Config.RDM_AoE_MeleeFinisher_OnAction, "VerAero II & VerThunder II", "", 3, 2, descriptionColor: ImGuiColors.DalamudYellow); - ImGui.Unindent(); - } - } - - if (preset is CustomComboPreset.RDM_AoE_Lucid) - UserConfig.DrawSliderInt(0, 10000, RDM.Config.RDM_AoE_Lucid_Threshold, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); - - if (preset is CustomComboPreset.RDM_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, RDM.Config.RDM_VariantCure, "HP% to be at or under", 200); - - if (preset is CustomComboPreset.RDM_ST_MeleeCombo) - { - UserConfig.DrawAdditionalBoolChoice(RDM.Config.RDM_ST_MeleeEnforced, "Enforced Melee Check", "Once the melee combo has started, don't switch away even if target is out of range."); - } - - #endregion // ==================================================================================== #region SAGE From 666a46cf645a523c5af9fdc575d3471df2a2ac61 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 20:51:16 -0500 Subject: [PATCH 162/208] forgot ActionName for description --- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 60b6e1681..9a0f0322b 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -129,7 +129,7 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.SCH_ST_Heal_Adloquium: DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Use {Adloquium.ActionName()} on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} will be unavailable.", 2, 0); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis}", "Enable to not override an existing Sage's shield.", 2, 1); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); break; case CustomComboPreset.SCH_ST_Heal_Lustrate: From 53d31bb010f6e443b982a5691095ee9be30a3ef2 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 20:54:36 -0500 Subject: [PATCH 163/208] Description update --- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 9a0f0322b..cb602151a 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -128,7 +128,7 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.SCH_ST_Heal_Adloquium: DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Use {Adloquium.ActionName()} on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} will be unavailable.", 2, 0); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 2, 0); DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); break; From 9a740c5d31314689d8179c37e74e6c0bb630d712 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 21:04:31 -0500 Subject: [PATCH 164/208] Moved Aldo to the bottom of menu, Added Fairy Gauge slider to Aetherpact option --- XIVSlothCombo/Combos/CustomComboPreset.cs | 8 ++++---- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 2 ++ XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 351e7dd7c..0bcc2034d 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3999,19 +3999,19 @@ The three digets after RDM.JobID can be used to reorder items in the list SCH_ST_Heal_Esuna = 16026, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Adloquium Option", "Use Adloquium when missing Galvanize or target HP%% below:", SCH.JobID, 5)] + [CustomComboInfo("Adloquium Option", "Use Adloquium when missing Galvanize or target HP%% below:", SCH.JobID, 9)] SCH_ST_Heal_Adloquium = 16027, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Lustrate Option", "Use Lustrate when target HP%% below:", SCH.JobID, 6)] + [CustomComboInfo("Lustrate Option", "Use Lustrate when target HP%% below:", SCH.JobID, 5)] SCH_ST_Heal_Lustrate = 16028, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Excogitation Option", "Use Excogitation when target HP%% below:", SCH.JobID, 7)] + [CustomComboInfo("Excogitation Option", "Use Excogitation when target HP%% below:", SCH.JobID, 6)] SCH_ST_Heal_Excogitation = 16038, [ParentCombo(SCH_ST_Heal)] - [CustomComboInfo("Protraction Option", "Use Protraction when target HP%% below:", SCH.JobID, 8)] + [CustomComboInfo("Protraction Option", "Use Protraction when target HP%% below:", SCH.JobID, 7)] SCH_ST_Heal_Protraction = 16039, [ParentCombo(SCH_ST_Heal)] diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index cb602151a..d387a463e 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -37,6 +37,7 @@ public static UserInt SCH_ST_Heal_ExcogitationOption = new("SCH_ST_Heal_ExcogitationOption"), SCH_ST_Heal_ProtractionOption = new("SCH_ST_Heal_ProtractionOption"), SCH_ST_Heal_AetherpactOption = new("SCH_ST_Heal_AetherpactOption"), + SCH_ST_Heal_AetherpactFairyGauge = new("SCH_ST_Heal_AetherpactFairyGauge"), SCH_ST_Heal_EsunaOption = new("SCH_ST_Heal_EsunaOption"); public static UserIntArray SCH_ST_Heals_Priority = new("SCH_ST_Heals_Priority"), @@ -149,6 +150,7 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.SCH_ST_Heal_Aetherpact: DrawSliderInt(0, 100, SCH_ST_Heal_AetherpactOption, "Start using when below HP %. Set to 100 to disable this check"); + DrawSliderInt(10, 100, SCH_ST_Heal_AetherpactFairyGauge, "Minimal Fairy Gauge to start using Aetherpact", sliderIncrement: Tens); DrawPriorityInput(SCH_ST_Heals_Priority, 4, 3, $"{Aetherpact.ActionName()} Priority: "); break; diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index d67cf34c5..fd784b342 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -37,7 +37,7 @@ public static int GetMatchingConfigST(int i, out uint action, out bool enabled) return Config.SCH_ST_Heal_ProtractionOption; case 3: action = Aetherpact; - enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Aetherpact); + enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Aetherpact) && Gauge.FairyGauge >= Config.SCH_ST_Heal_AetherpactFairyGauge; return Config.SCH_ST_Heal_AetherpactOption; } From 95116926c83aa3b87f5336a99d5779fa64d8a808 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Sun, 29 Sep 2024 21:55:15 -0500 Subject: [PATCH 165/208] Check for both SGE shields --- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 4 +++- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 5d48a6430..4f7df664f 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -543,7 +543,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ActionReady(Adloquium) && GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption && (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check - (!Config.SCH_ST_Heal_AldoquimOpts[1] || FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null)) //EDiagnosis Check + (!Config.SCH_ST_Heal_AldoquimOpts[1] || + (FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null && FindEffectOnMember(SGE.Buffs.EukrasianPrognosis, healTarget) is null) + )) //Eukrasia Shield Check { return OriginalHook(Adloquium); } diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index d387a463e..7e175de9f 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -130,7 +130,7 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.SCH_ST_Heal_Adloquium: DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Use {Adloquium.ActionName()} on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 2, 0); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}/{SGE.EukrasianPrognosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); break; case CustomComboPreset.SCH_ST_Heal_Lustrate: From c398d9c834bee57be2b95e17031eb1b56cec257c Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 2 Oct 2024 17:00:01 +0100 Subject: [PATCH 166/208] Try fixes for healer actions in autorot --- XIVSlothCombo/AutoRotation/AutoRotationController.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index acfbe62f9..fc4c6adb7 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -61,7 +61,7 @@ internal static void Run() } if (healTarget == null && !aoeheal) - AutomateDPS(preset.Key, attributes, gameAct); + AutomateDPS(preset.Key, attributes, gameAct); } @@ -203,7 +203,6 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset return false; var outAct = InvokeCombo(preset, attributes, target); - var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) return false; @@ -216,9 +215,7 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset var canUse = canUseSelf || canUseTarget || areaTargeted; if (canUse && inRange) { - if (target.IsHostile()) - Svc.Targets.Target = target; - + Svc.Targets.Target = target; return ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); } From a3aa8517992e399d36078086e4155cf00e204812 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 2 Oct 2024 17:28:57 +0100 Subject: [PATCH 167/208] SCH fixes --- .../AutoRotation/AutoRotationController.cs | 11 ++++++----- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 18 ++++++++++++------ XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 2 +- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index fc4c6adb7..eb5b0a5ee 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -103,16 +103,12 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr if (attributes.AutoAction.IsAoE) { var ret = AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); - if (ret) - LastHealAt = Environment.TickCount64; return ret; } else { var ret = AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); - if (ret) - LastHealAt = Environment.TickCount64; return ret; } @@ -216,7 +212,12 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset if (canUse && inRange) { Svc.Targets.Target = target; - return ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); + + var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); + if (mode is HealerRotationMode && ret) + LastHealAt = Environment.TickCount64; + + return ret; } return false; diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 4f7df664f..1a1aea44d 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -446,11 +446,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim && All.CanUseLucid(actionID, Config.SCH_AoE_Heal_LucidOption, true)) return All.LucidDreaming; - // Indomitability - if (IsEnabled(CustomComboPreset.SCH_AoE_Heal_Indomitability) && - ActionReady(Indomitability) && - Gauge.HasAetherflow()) - return Indomitability; + foreach (var prio in Config.SCH_AoE_Heals_Priority.Items.OrderBy(x => x)) + { + var index = Config.SCH_AoE_Heals_Priority.IndexOf(prio); + var config = GetMatchingConfigAoE(index, out var spell, out bool enabled); + + if (enabled) + { + if (ActionReady(spell)) + return spell; + } + } } return actionID; } @@ -541,7 +547,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && - GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption && + (GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption || Config.SCH_ST_Heal_AdloquiumOption == 0) && (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check (!Config.SCH_ST_Heal_AldoquimOpts[1] || (FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null && FindEffectOnMember(SGE.Buffs.EukrasianPrognosis, healTarget) is null) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index fd784b342..6c994441e 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -37,7 +37,7 @@ public static int GetMatchingConfigST(int i, out uint action, out bool enabled) return Config.SCH_ST_Heal_ProtractionOption; case 3: action = Aetherpact; - enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Aetherpact) && Gauge.FairyGauge >= Config.SCH_ST_Heal_AetherpactFairyGauge; + enabled = IsEnabled(CustomComboPreset.SCH_ST_Heal_Aetherpact) && Gauge.FairyGauge >= Config.SCH_ST_Heal_AetherpactFairyGauge && IsOriginal(Aetherpact); return Config.SCH_ST_Heal_AetherpactOption; } diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 6f0e77420..363ba6ded 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.5 + 0.0.0.6 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From c6372ed08b1187baf596e9787483a8b987e7876d Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Wed, 2 Oct 2024 19:11:02 -0500 Subject: [PATCH 168/208] Updated ST HP% Slider descriptions --- XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs index fa796a549..20d8f9271 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE_Config.cs @@ -124,42 +124,42 @@ internal static void Draw(CustomComboPreset preset) break; case CustomComboPreset.SGE_ST_Heal_Soteria: - DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, $"Use {Soteria.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Soteria, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 0, $"{Soteria.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_Zoe: - DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, $"Use {Zoe.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Zoe, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 1, $"{Zoe.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_Pepsis: - DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, $"Use {Pepsis.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Pepsis, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 2, $"{Pepsis.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_Taurochole: - DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, $"Use {Taurochole.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Taurochole, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 3, $"{Taurochole.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_Haima: - DrawSliderInt(0, 100, SGE_ST_Heal_Haima, $"Use {Haima.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Haima, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 4, $"{Haima.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_Krasis: - DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, $"Use {Krasis.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Krasis, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 5, $"{Krasis.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_Druochole: - DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, $"Use {Druochole.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_Druochole, "Start using when below HP %. Set to 100 to disable this check."); DrawPriorityInput(SGE_ST_Heals_Priority, 7, 6, $"{Druochole.ActionName()} Priority: "); break; case CustomComboPreset.SGE_ST_Heal_EDiagnosis: - DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, $"Use {EukrasianDiagnosis.ActionName()} when Target HP == at or below set percentage"); + DrawSliderInt(0, 100, SGE_ST_Heal_EDiagnosisHP, "Start using when below HP %. Set to 100 to disable this check."); DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Ignore Shield Check", $"Warning, will force the use of {EukrasianDiagnosis.ActionName()}, and normal {Diagnosis.ActionName()} will be unavailable.", 2, 0); DrawHorizontalMultiChoice(SGE_ST_Heal_EDiagnosisOpts, "Check for Scholar Galvenize", "Enable to not override an existing Scholar's shield.", 2, 1); break; From 04ec84d14d0bc404ad67fa935d8d49bb9589a8c1 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Thu, 3 Oct 2024 07:45:52 +0100 Subject: [PATCH 169/208] More autorot fixes --- .../AutoRotation/AutoRotationController.cs | 16 ++++++++++++---- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index eb5b0a5ee..797cee21c 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -10,6 +10,7 @@ using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; using Action = Lumina.Excel.GeneratedSheets.Action; @@ -48,7 +49,7 @@ internal static void Run() if (action.IsHeal) { - if (!AutomateHealing(preset.Key, attributes, gameAct) && Svc.Targets.Target != null && !Svc.Targets.Target.IsHostile()) + if (!AutomateHealing(preset.Key, attributes, gameAct) && Svc.Targets.Target != null && !Svc.Targets.Target.IsHostile() && Environment.TickCount64 > LastHealAt + 1000) Svc.Targets.Target = null; continue; @@ -102,12 +103,14 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr if (attributes.AutoAction.IsAoE) { + if (Environment.TickCount64 < LastHealAt + 1500) return false; var ret = AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); return ret; } else { + if (Environment.TickCount64 < LastHealAt + 1500) return false; var ret = AutoRotationHelper.ExecuteST(mode, preset, attributes, gameAct); return ret; @@ -163,7 +166,12 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese if (CustomComboFunctions.IsMoving && castTime > 0) return false; - return ActionManager.Instance()->UseAction(ActionType.Action, outAct); + var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct); + + if (ret) + LastHealAt = Environment.TickCount64 + castTime; + + return ret; } } else @@ -215,7 +223,7 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); if (mode is HealerRotationMode && ret) - LastHealAt = Environment.TickCount64; + LastHealAt = Environment.TickCount64 + castTime; return ret; } @@ -347,7 +355,7 @@ private static bool TargetHasRegen(IGameObject target) _ => 0 }; - return CustomComboFunctions.FindEffect(regenBuff) != null; + return CustomComboFunctions.FindEffectOnMember(regenBuff, target) != null; } } diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 363ba6ded..396b59b93 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.6 + 0.0.0.7 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From 4aabac96eaa099d72ecb82f6a4aefe13732b098d Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Wed, 2 Oct 2024 18:06:35 -0500 Subject: [PATCH 170/208] [SCH] Revert of Aldo fixes. Aldo was changed as part of an overhaul, and the description update was overlooked. Reverting changes and updated description to be in parity with Sage. --- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 2 +- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 1a1aea44d..6b036dfd9 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -547,7 +547,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && - (GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption || Config.SCH_ST_Heal_AdloquiumOption == 0) && + GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption && (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check (!Config.SCH_ST_Heal_AldoquimOpts[1] || (FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null && FindEffectOnMember(SGE.Buffs.EukrasianPrognosis, healTarget) is null) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 7e175de9f..21cdf5628 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -128,7 +128,7 @@ internal static void Draw(CustomComboPreset preset) break; case CustomComboPreset.SCH_ST_Heal_Adloquium: - DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Use {Adloquium.ActionName()} on targets at or below HP % even if they have Galvanize\n0 = Only ever use Adloquium on targets without Galvanize\n100 = Always use Adloquium"); + DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Start using when below HP %. Set to 100 to disable this check."); DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 2, 0); DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}/{SGE.EukrasianPrognosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); break; From 1b7b50c9c598eeceaf9d7055b00b26f38e4d3e64 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:21:28 -0500 Subject: [PATCH 171/208] Notes update --- XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs index 5848f2689..3ae5f0f8b 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs @@ -288,7 +288,8 @@ internal static bool TrySTMeleeCombo(uint actionID, uint lastComboMove, float co //Simple Mode Values bool MeleeEnforced = true, bool GapCloser = true, bool UnbalanceMana = true) { - //Test + //I really don't like the idea of Simple / autorot lunging in. + //Need to somehow tell AI it's time to go to melee range or something if (GapCloser && ActionReady(Corpsacorps) && !(CurrentTarget as IBattleChara).IsCasting From db375ad3e3ae17c54b5a40e9731426c5a1e0170f Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 10 Oct 2024 22:03:39 -0500 Subject: [PATCH 172/208] Adding Party Average HP % and Party Buff counting SCH AoE Heals updated to leverage these --- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 3 +- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 31 ++++++++++++++++---- XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 16 ++++++---- XIVSlothCombo/CustomCombo/Functions/Party.cs | 31 ++++++++++++++++++++ XIVSlothCombo/Window/Tabs/Debug.cs | 2 ++ 5 files changed, 70 insertions(+), 13 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 6b036dfd9..94d34a271 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -453,7 +453,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (enabled) { - if (ActionReady(spell)) + if (GetPartyAvgHPPercent() <= config && + ActionReady(spell)) return spell; } } diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 21cdf5628..666196b0b 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -31,6 +31,13 @@ public static UserBoolArray public static UserInt SCH_AoE_LucidOption = new("SCH_AoE_LucidOption", 6500), SCH_AoE_Heal_LucidOption = new("SCH_AoE_Heal_LucidOption", 6500), + SCH_AoE_Heal_SuccorShieldOption = new("SCH_AoE_Heal_SuccorShieldCount",4), + SCH_AoE_Heal_WhisperingDawnOption = new("SCH_AoE_Heal_WhisperingDawnOption"), + SCH_AoE_Heal_FeyIlluminationOption = new("SCH_AoE_Heal_FeyIlluminationOption"), + SCH_AoE_Heal_ConsolationOption = new("SCH_AoE_Heal_ConsolationOption"), + SCH_AoE_Heal_FeyBlessingOption = new("SCH_AoE_Heal_FeyBlessingOption"), + SCH_AoE_Heal_SeraphismOption = new("SCH_AoE_Heal_SeraphismOption"), + SCH_AoE_Heal_IndomitabilityOption = new("SCH_AoE_Heal_IndomitabilityOption"), SCH_ST_Heal_LucidOption = new("SCH_ST_Heal_LucidOption", 6500), SCH_ST_Heal_AdloquiumOption = new("SCH_ST_Heal_AdloquiumOption"), SCH_ST_Heal_LustrateOption = new("SCH_ST_Heal_LustrateOption"), @@ -166,28 +173,40 @@ internal static void Draw(CustomComboPreset preset) DrawSliderInt(4000, 9500, SCH_AoE_Heal_LucidOption, "MP Threshold", 150, Hundreds); break; + case CustomComboPreset.SCH_AoE_Heal: + ImGui.TextUnformatted("Note: Succor will always be available. These options are to provide optional priority to Succor."); + DrawSliderInt(0, 100, SCH_AoE_Heal_SuccorShieldOption, "Shield Check: Percentage of Party Members without shields to check for.", sliderIncrement: 25); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 6, $"{Succor.ActionName()} Priority: "); + break; + case CustomComboPreset.SCH_AoE_Heal_WhisperingDawn: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 0, $"{WhisperingDawn.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_WhisperingDawnOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 0, $"{WhisperingDawn.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_FeyIllumination: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 1, $"{FeyIllumination.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_FeyIlluminationOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 1, $"{FeyIllumination.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_FeyBlessing: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 2, $"{FeyBlessing.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_FeyBlessingOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 2, $"{FeyBlessing.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_Consolation: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 3, $"{Consolation.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_ConsolationOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 3, $"{Consolation.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_Seraphism: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 4, $"{Seraphism.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_SeraphismOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 4, $"{Seraphism.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_Indomitability: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 5, $"{Indomitability.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_IndomitabilityOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 5, $"{Indomitability.ActionName()} Priority: "); break; case CustomComboPreset.SCH_DeploymentTactics: diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index 6c994441e..ff26bc85f 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -53,27 +53,31 @@ public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) case 0: action = OriginalHook(WhisperingDawn); enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_WhisperingDawn); - return 0; + return Config.SCH_AoE_Heal_WhisperingDawnOption; case 1: action = OriginalHook(FeyIllumination); enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_FeyIllumination); - return 0; + return Config.SCH_AoE_Heal_FeyIlluminationOption; case 2: action = FeyBlessing; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_FeyBlessing); - return 0; + return Config.SCH_AoE_Heal_FeyBlessingOption; case 3: action = Consolation; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Consolation) && Gauge.SeraphTimer > 0; - return 0; + return Config.SCH_AoE_Heal_ConsolationOption; case 4: action = Seraphism; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Seraphism); - return 0; + return Config.SCH_AoE_Heal_SeraphismOption; case 5: action = Indomitability; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Indomitability) && Gauge.HasAetherflow(); - return 0; + return Config.SCH_AoE_Heal_IndomitabilityOption; + case 6: + action = OriginalHook(Succor); + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal) && GetPartyBuffPercent(Buffs.Galvanize) <= Config.SCH_AoE_Heal_SuccorShieldOption; + return 0; //Don't HP Check } enabled = false; diff --git a/XIVSlothCombo/CustomCombo/Functions/Party.cs b/XIVSlothCombo/CustomCombo/Functions/Party.cs index 429bb7c02..383fa1ced 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Party.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Party.cs @@ -52,5 +52,36 @@ public static List GetPartyMembers() return null; } } + + public static float GetPartyAvgHPPercent() + { + float HP = 0; + byte Count = 0; + for (int i = 1; i <= 8; i++) //Checking all 8 available slots and skipping nulls & DCs + { + if (GetPartySlot(i) is not IBattleChara member) continue; + if (member is null) continue; //Skip nulls/disconnected people + if (member.IsDead) continue; + + HP += GetTargetHPPercent(member); + Count++; + } + return Count == 0 ? 0 : (float)HP / Count; //Div by 0 check...just in case.... + } + + public static float GetPartyBuffPercent(ushort buff) + { + byte BuffCount = 0; + byte PartyCount = 0; + for (int i = 1; i <= 8; i++) //Checking all 8 available slots and skipping nulls & DCs + { + if (GetPartySlot(i) is not IBattleChara member) continue; + if (member is null) continue; //Skip nulls/disconnected people + if (member.IsDead) continue; + if (FindEffectOnMember(buff, member) is not null) BuffCount++; + PartyCount++; + } + return PartyCount == 0 ? 0 : (float)BuffCount / PartyCount * 100f; //Div by 0 check...just in case.... + } } } diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 61d1842ef..401b74eab 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -228,6 +228,8 @@ static void CustomStyleText(string label, object? value) CustomStyleText("Health:", $"{EnemyHealthCurrentHp().ToString("N0")} / {EnemyHealthMaxHp().ToString("N0")} ({Math.Round(GetTargetHPPercent(), 2)}%)"); CustomStyleText("Shield:", (GetHealTarget() as ICharacter).ShieldPercentage); CustomStyleText("Health Percent (+ Shield):", $"{GetTargetHPPercent(GetHealTarget())} / {GetTargetHPPercent(GetHealTarget(), true)}"); + CustomStyleText("Party Avg HP Percent:", $"{GetPartyAvgHPPercent()}"); + CustomStyleText("Party Avg with Galvanize:", $"{GetPartyBuffPercent(Combos.PvE.SCH.Buffs.Galvanize)}"); ImGui.Indent(); if (ImGui.CollapsingHeader("Relative Target Distances")) { From 025a7e450ca181b7bdc5b6e5610e5ffbe6f1a93a Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Thu, 10 Oct 2024 22:11:15 -0500 Subject: [PATCH 173/208] Removed gap closers from Simple Modes --- XIVSlothCombo/Combos/CustomComboPreset.cs | 4 ++-- XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs | 16 ++-------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 4e4d3dd54..93e36fafe 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3189,7 +3189,7 @@ The three digets after RDM.JobID can be used to reorder items in the list [AutoAction(false, false)] [ConflictingCombos(RDM_ST_DPS)] [ReplaceSkill(RDM.Jolt, RDM.Jolt2, RDM.Jolt3)] - [CustomComboInfo("Simple Mode - Single Target", "Replaces Jolts with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", RDM.JobID, -2)] + [CustomComboInfo("Simple Mode - Single Target", "Replaces Jolts with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.\nTo start the melee combo, you must be within melee range.", RDM.JobID, -2)] RDM_ST_SimpleMode = 13837, [AutoAction(false, false)] @@ -3255,7 +3255,7 @@ The three digets after RDM.JobID can be used to reorder items in the list [AutoAction(true, false)] [ReplaceSkill(RDM.Scatter, RDM.Impact)] [ConflictingCombos(RDM_AoE_DPS)] - [CustomComboInfo("Simple Mode - AoE", "Replaces Scatter/Impact with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", RDM.JobID, -1)] + [CustomComboInfo("Simple Mode - AoE", "Replaces Scatter/Impact with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.\nTo start the melee combo, you must be within melee range.", RDM.JobID, -1)] RDM_AoE_SimpleMode = 13838, [AutoAction(true, false)] diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs index 3ae5f0f8b..471eafafd 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs @@ -286,19 +286,8 @@ internal static bool TrySTManaEmbolden(uint actionID, uint lastComboMove, byte l internal static bool TrySTMeleeCombo(uint actionID, uint lastComboMove, float comboTime, out uint newActionID, //Simple Mode Values - bool MeleeEnforced = true, bool GapCloser = true, bool UnbalanceMana = true) + bool MeleeEnforced = true, bool GapCloser = false, bool UnbalanceMana = true) { - //I really don't like the idea of Simple / autorot lunging in. - //Need to somehow tell AI it's time to go to melee range or something - if (GapCloser - && ActionReady(Corpsacorps) - && !(CurrentTarget as IBattleChara).IsCasting - && GetTargetDistance() > 3) - { - newActionID = Corpsacorps; - return true; - } - //Normal Combo if (GetTargetDistance() <= 3 || MeleeEnforced) { @@ -326,7 +315,6 @@ internal static bool TrySTMeleeCombo(uint actionID, uint lastComboMove, float co { if (GapCloser && ActionReady(Corpsacorps) - && !(CurrentTarget as IBattleChara).IsCasting && GetTargetDistance() > 3) { newActionID = Corpsacorps; @@ -447,7 +435,7 @@ internal static bool TryAoEManaEmbolden(uint actionID, uint lastComboMove, out u internal static bool TryAoEMeleeCombo(uint actionID, uint lastComboMove, float comboTime, out uint newActionID, //Simple Mode Values int MoulinetRange = 6, - bool GapCloser = true) + bool GapCloser = false) { //Finish the combo if (LevelChecked(Moulinet) From 467f5bd0766fe8164f23827994d4eabaafbdbdc0 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 11 Oct 2024 22:42:36 +0100 Subject: [PATCH 174/208] [PUSH] v3.2.0.9 --- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index b567653b4..5d447bbd5 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Sloth - - 3.2.0.8 + 3.2.0.9 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From 412ee77b918f7fa2149c66ecccbf09dd7a7c566c Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:52:48 -0500 Subject: [PATCH 175/208] Forced Melee for Simple AoE MeleeCombo. Not rigging up a Enforced range on AoE (mostly done by the range slider anyways) --- XIVSlothCombo/Combos/PvE/RDM/RDM.cs | 4 +++- XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs | 16 ++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs index 01e47634c..f78baa77d 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs @@ -374,7 +374,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return ManaEmbolen; if (MeleeCombo.TryAoEMeleeCombo(actionID, lastComboMove, comboTime, out uint AoEMelee, - Config.RDM_AoE_MoulinetRange, IsEnabled(CustomComboPreset.RDM_AoE_MeleeCombo_CorpsGapCloser))) + Config.RDM_AoE_MoulinetRange, //Range + IsEnabled(CustomComboPreset.RDM_AoE_MeleeCombo_CorpsGapCloser), //Gap Closer + false)) //Melee range enforced return AoEMelee; } } diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs index 471eafafd..67f14d646 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs @@ -435,15 +435,19 @@ internal static bool TryAoEManaEmbolden(uint actionID, uint lastComboMove, out u internal static bool TryAoEMeleeCombo(uint actionID, uint lastComboMove, float comboTime, out uint newActionID, //Simple Mode Values int MoulinetRange = 6, - bool GapCloser = false) + bool GapCloser = false, + bool MeleeEnforced = true) { - //Finish the combo - if (LevelChecked(Moulinet) + if (GetTargetDistance() <= MoulinetRange || MeleeEnforced) + { + //Finish the combo + if (LevelChecked(Moulinet) && lastComboMove is EnchantedMoulinet or EnchantedMoulinetDeux && comboTime > 0f) - { - newActionID = OriginalHook(Moulinet); - return true; + { + newActionID = OriginalHook(Moulinet); + return true; + } } if (LevelChecked(Moulinet) From d69ccb694dc7925fd45361276043fad9a7c32cba Mon Sep 17 00:00:00 2001 From: ace Date: Sat, 12 Oct 2024 13:49:30 -0700 Subject: [PATCH 176/208] TendoGoken check --- XIVSlothCombo/Combos/PvE/SAM.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM.cs index af62aa85b..2e457cab6 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM.cs @@ -757,6 +757,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!IsMoving && (OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken)) return OriginalHook(Iaijutsu); + if (!IsMoving && LevelChecked(TendoGoken) && (OriginalHook(Iaijutsu) is TendoGoken)) + return OriginalHook(Iaijutsu); + if (LevelChecked(TsubameGaeshi) && (HasEffect(Buffs.KaeshiGokenReady) || HasEffect(Buffs.TendoKaeshiGokenReady))) return OriginalHook(TsubameGaeshi); } @@ -867,6 +870,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!IsMoving && (OriginalHook(Iaijutsu) is TenkaGoken)) return OriginalHook(Iaijutsu); + if (!IsMoving && LevelChecked(TendoGoken) && (OriginalHook(Iaijutsu) is TendoGoken)) + return OriginalHook(Iaijutsu); + if (LevelChecked(TsubameGaeshi) && (HasEffect(Buffs.KaeshiGokenReady) || HasEffect(Buffs.TendoKaeshiGokenReady))) return OriginalHook(TsubameGaeshi); } From 4c08be34fd26856c4644a11b0fd8abcc92b69c5a Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Mon, 14 Oct 2024 14:17:59 +0100 Subject: [PATCH 177/208] Update NIN mudra check (testing change) --- XIVSlothCombo/Combos/JobHelpers/NIN.cs | 7 +------ XIVSlothCombo/Data/ActionWatching.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/NIN.cs b/XIVSlothCombo/Combos/JobHelpers/NIN.cs index 37924c8fd..465c869bb 100644 --- a/XIVSlothCombo/Combos/JobHelpers/NIN.cs +++ b/XIVSlothCombo/Combos/JobHelpers/NIN.cs @@ -26,12 +26,7 @@ private static bool TargetHasMugDebuff() return CustomComboFunctions.TargetHasEffect(Debuffs.Mug) || CustomComboFunctions.TargetHasEffect(Debuffs.Dokumori); } - internal static bool InMudra => GetInMudra(); - - private static bool GetInMudra() - { - return !CustomComboFunctions.IsOriginal(Ninjutsu); - } + internal static bool InMudra = false; } internal class MudraCasting : PvE.NIN diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index 5830bddba..a00b8ae56 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -12,6 +12,7 @@ using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; +using static XIVSlothCombo.Combos.JobHelpers.NIN; namespace XIVSlothCombo.Data { @@ -101,6 +102,8 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp TimeLastActionUsed = DateTime.Now; ActionType = actionType; + UpdateHelpers(actionId); + //Dalamud.Logging.PluginLog.Debug($"{actionId} {sequence} {a5} {a6} {a7} {a8} {a9}"); } catch (Exception ex) @@ -110,6 +113,14 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp } } + private static void UpdateHelpers(uint actionId) + { + if (actionId is NIN.Ten or NIN.Chi or NIN.Jin or NIN.TenCombo or NIN.ChiCombo or NIN.JinCombo) + NINHelper.InMudra = true; + else + NINHelper.InMudra = false; + } + private unsafe static void CheckForChangedTarget(uint actionId, ref ulong targetObjectId) { if (actionId is AST.Balance or AST.Spear && From 9b59519095901b94b93bd40c08fa92c21494fd29 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Mon, 14 Oct 2024 15:02:45 +0100 Subject: [PATCH 178/208] Tighter NIN mudra check --- XIVSlothCombo/Combos/JobHelpers/NIN.cs | 1 + XIVSlothCombo/Window/Functions/Presets.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/NIN.cs b/XIVSlothCombo/Combos/JobHelpers/NIN.cs index 465c869bb..e1e4485c9 100644 --- a/XIVSlothCombo/Combos/JobHelpers/NIN.cs +++ b/XIVSlothCombo/Combos/JobHelpers/NIN.cs @@ -34,6 +34,7 @@ internal class MudraCasting : PvE.NIN /// Checks if the player is in a state to be able to cast a ninjitsu. private static bool CanCast() { + if (NINHelper.InMudra) return true; var gcd = CustomComboFunctions.GetCooldown(GustSlash).CooldownTotal; if (gcd == 0.5) return true; diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index 37e552b93..bbb734dc0 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -132,7 +132,7 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo var subpar = PresetStorage.GetParent(par2); if (subpar != null) { - conflictBuilder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo : subpar?.GetAttribute().FancyName)} -> "); + conflictBuilder.Insert(0, $"{(Attributes.ContainsKey(subpar.Value) ? Attributes[subpar.Value].CustomComboInfo.FancyName : subpar?.GetAttribute().FancyName)} -> "); par2 = subpar!.Value; } From e41239f3002587dd2b8c5f7cfababda65c565cf8 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Mon, 14 Oct 2024 15:03:23 +0100 Subject: [PATCH 179/208] Typo fix --- XIVSlothCombo/Combos/CustomComboPreset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index cd6027a6f..6f27ee6b3 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -1398,7 +1398,7 @@ public enum CustomComboPreset DRG_AoE_DragonfireDive_Movement = 6208, [ParentCombo(DRG_AoE_CDs)] - [CustomComboInfo("Rise of the Dragon Option", "Adds Rise of the Dragonj to the rotation.", DRG.JobID)] + [CustomComboInfo("Rise of the Dragon Option", "Adds Rise of the Dragon to the rotation.", DRG.JobID)] DRG_AoE_RiseOfTheDragon = 6209, [ParentCombo(DRG_AoE_CDs)] From a0d8e4addd96042d85fd4b13361ac1f494cd57a9 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Mon, 14 Oct 2024 15:04:37 +0100 Subject: [PATCH 180/208] [PUSH] 3.2.0.10 --- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 5d447bbd5..6905552b7 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Sloth - - 3.2.0.9 + 3.2.0.10 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From dbaf02c452af5e9f9d5d57967e3043467d89551b Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Tue, 15 Oct 2024 09:30:12 +0100 Subject: [PATCH 181/208] Version bump --- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 396b59b93..e941eebfa 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.7 + 0.0.0.8 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From d1f7ef18be45aff88e0eccb6d260019db620ad40 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:59:45 -0500 Subject: [PATCH 182/208] Fixed missing .ActionName() (Thanks Kage) --- XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs index e69595adc..fb8666352 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs @@ -107,7 +107,7 @@ internal static void Draw(CustomComboPreset preset) ImGui.Indent(); ImGui.Spacing(); DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, $"{Jolt.ActionName()}s", "", 3, 0, descriptionColor: ImGuiColors.DalamudYellow); DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, Riposte.ActionName(), "", 3, 1, descriptionColor: ImGuiColors.DalamudYellow); - DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, $"{Veraero} & {Verthunder}", "", 3, 2, descriptionColor: ImGuiColors.DalamudYellow); + DrawHorizontalMultiChoice(RDM_ST_MeleeFinisher_OnAction, $"{Veraero.ActionName()} & {Verthunder.ActionName()}", "", 3, 2, descriptionColor: ImGuiColors.DalamudYellow); ImGui.Unindent(); } break; From 10c558075e054a4d31cadb32c668d9e0f6894988 Mon Sep 17 00:00:00 2001 From: Tartarga <109563717+Tartarga@users.noreply.github.com> Date: Fri, 1 Nov 2024 10:09:45 -0500 Subject: [PATCH 183/208] Emergency Tactics Added --- XIVSlothCombo/Combos/PvE/SCH/SCH.cs | 13 ++++++++----- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 5 +++-- XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 2 -- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 94d34a271..be0dd1e1b 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -57,7 +57,8 @@ internal const uint Aetherflow = 166, Recitation = 16542, ChainStratagem = 7436, - DeploymentTactics = 3585; + DeploymentTactics = 3585, + EmergencyTactics = 3586; //Action Groups internal static readonly List @@ -548,12 +549,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && - GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption && - (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check - (!Config.SCH_ST_Heal_AldoquimOpts[1] || + GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption) + { + if (Config.SCH_ST_Heal_AldoquimOpts[2] && ActionReady(EmergencyTactics)) return EmergencyTactics; + + if ((Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check + (!Config.SCH_ST_Heal_AldoquimOpts[1] || (FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null && FindEffectOnMember(SGE.Buffs.EukrasianPrognosis, healTarget) is null) )) //Eukrasia Shield Check - { return OriginalHook(Adloquium); } } diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 666196b0b..914d66928 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -136,8 +136,9 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.SCH_ST_Heal_Adloquium: DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Start using when below HP %. Set to 100 to disable this check."); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 2, 0); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}/{SGE.EukrasianPrognosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 3, 0); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Sage Shield Check", "Enable to not override an existing Sage's shield.", 3, 1); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"{EmergencyTactics.ActionName()}", $"Use {EmergencyTactics.ActionName()} before {Adloquium.ActionName()}", 3, 2); break; case CustomComboPreset.SCH_ST_Heal_Lustrate: diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index ff26bc85f..616f47429 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -19,8 +19,6 @@ internal enum OpenerState public static int GetMatchingConfigST(int i, out uint action, out bool enabled) { - var healTarget = GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); - switch (i) { case 0: From b7eeacb32fcd0ffd9a470281546e22445d52809a Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 3 Nov 2024 10:26:05 +0000 Subject: [PATCH 184/208] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 682209ae2..5b0e58c5c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - +
From b967b22e6c7fa4745119b31f4664391fc27e0262 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 8 Nov 2024 10:57:06 +0000 Subject: [PATCH 185/208] Updoot --- .../AutoRotation/AutoRotationConfig.cs | 2 + .../AutoRotation/AutoRotationController.cs | 55 +++++++++++++++---- XIVSlothCombo/Combos/CustomComboPreset.cs | 10 +++- XIVSlothCombo/Combos/PvE/BLM.cs | 5 +- XIVSlothCombo/Combos/PvE/NIN.cs | 4 +- XIVSlothCombo/Combos/PvE/SGE.cs | 10 ++++ XIVSlothCombo/CustomCombo/CustomCombo.cs | 2 - XIVSlothCombo/CustomCombo/Functions/Timer.cs | 50 ++++++----------- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 10 ++++ XIVSlothCombo/XIVSlothCombo.cs | 3 + 10 files changed, 100 insertions(+), 51 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs index 5d98d155d..0a95ec429 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -24,5 +24,7 @@ public class HealerSettings public int AoETargetHPP = 60; public int SingleTargetRegenHPP = 80; public int? AoEHealTargetCount = 2; + public bool ManageKardia = false; + public bool KardiaTanksOnly = false; } } diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 797cee21c..058096c18 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Objects.Types; +using ECommons; using ECommons.DalamudServices; using ECommons.GameFunctions; using ECommons.GameHelpers; @@ -30,6 +31,9 @@ internal static void Run() if (!EzThrottler.Throttle("AutoRotController", 150)) return; + if (Player.Job is ECommons.ExcelServices.Job.SGE && Service.Configuration.RotationConfig.HealerSettings.ManageKardia) + UpdateKardiaTarget(); + foreach (var preset in Service.Configuration.AutoActions.OrderByDescending(x => Presets.Attributes[x.Key].AutoAction.IsHeal) .ThenByDescending(x => Presets.Attributes[x.Key].AutoAction.IsAoE)) { @@ -44,30 +48,52 @@ internal static void Run() continue; var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); - var healTarget = AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode); - var aoeheal = HealerTargeting.CanAoEHeal(outAct); + var healTarget = Player.Object.GetRole() is CombatRole.Healer ? AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode) : null; + var aoeheal = Player.Object.GetRole() is CombatRole.Healer ? HealerTargeting.CanAoEHeal(gameAct) : false; if (action.IsHeal) { if (!AutomateHealing(preset.Key, attributes, gameAct) && Svc.Targets.Target != null && !Svc.Targets.Target.IsHostile() && Environment.TickCount64 > LastHealAt + 1000) Svc.Targets.Target = null; - continue; + if ((healTarget != null && !action.IsAoE) || (aoeheal && action.IsAoE)) + return; + else + continue; } + if (Player.Object.GetRole() is CombatRole.Tank) { AutomateTanking(preset.Key, attributes, gameAct); continue; } - if (healTarget == null && !aoeheal) - AutomateDPS(preset.Key, attributes, gameAct); + AutomateDPS(preset.Key, attributes, gameAct); } } + private static void UpdateKardiaTarget() + { + if (!CustomComboFunctions.LevelChecked(SGE.Kardia)) return; + if (CustomComboFunctions.CombatEngageDuration().TotalSeconds < 3) return; + + foreach (var member in CustomComboFunctions.GetPartyMembers().OrderByDescending(x => x.GetRole() is CombatRole.Tank)) + { + if (Service.Configuration.RotationConfig.HealerSettings.KardiaTanksOnly && member.GetRole() is not CombatRole.Tank) continue; + + var enemiesTargeting = Svc.Objects.Where(x => x.IsTargetable && x.IsHostile() && x.TargetObjectId == member.GameObjectId).Count(); + if (enemiesTargeting > 0 && CustomComboFunctions.FindEffectOnMember(SGE.Buffs.Kardion, member) is null) + { + ActionManager.Instance()->UseAction(ActionType.Action, SGE.Kardia, member.GameObjectId); + return; + } + } + + } + private static bool AutomateDPS(CustomComboPreset preset, Presets.PresetAttributes attributes, uint gameAct) { if (Svc.Targets.Target != null && !Svc.Targets.Target.IsHostile()) return false; @@ -105,7 +131,6 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr { if (Environment.TickCount64 < LastHealAt + 1500) return false; var ret = AutoRotationHelper.ExecuteAoE(mode, preset, attributes, gameAct); - return ret; } else @@ -171,7 +196,7 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese if (ret) LastHealAt = Environment.TickCount64 + castTime; - return ret; + return ret; } } else @@ -181,9 +206,9 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese return false; var target = GetSingleTarget(mode); - var sheet = Svc.Data.GetExcelSheet().GetRow(outAct); + var sheet = Svc.Data.GetExcelSheet().GetRow(gameAct); var mustTarget = sheet.CanTargetHostile; - var numEnemies = CustomComboFunctions.NumberOfEnemiesInRange(outAct, target); + var numEnemies = CustomComboFunctions.NumberOfEnemiesInRange(gameAct, target); if (numEnemies >= Service.Configuration.RotationConfig.DPSSettings.DPSAoETargets || (sheet.EffectRange == 0 && sheet.CanTargetSelf && !mustTarget)) { @@ -211,17 +236,27 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset if (CustomComboFunctions.IsMoving && castTime > 0) return false; + if (outAct is SGE.Druochole && !attributes.AutoAction.IsHeal) + { + if (CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.FindEffectOnMember(SGE.Buffs.Kardion, x) is not null).TryGetFirst(out var newtarget)) + { + Svc.Log.Debug($"DChole switch"); + target = newtarget; + } + } + var areaTargeted = Svc.Data.GetExcelSheet().GetRow(outAct).TargetArea; var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, target.Struct()) != 562; var canUseTarget = ActionManager.CanUseActionOnTarget(outAct, target.Struct()); var canUseSelf = ActionManager.CanUseActionOnTarget(outAct, Player.GameObject); var canUse = canUseSelf || canUseTarget || areaTargeted; + if (canUse && inRange) { Svc.Targets.Target = target; - var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); + var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); if (mode is HealerRotationMode && ret) LastHealAt = Environment.TickCount64 + castTime; diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 7911cbc8a..84d38bc9c 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3398,6 +3398,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Rhizomata Option", "Weaves Rhizomata when Addersgall gauge falls below the specified value.", SGE.JobID, 121)] SGE_ST_DPS_Rhizo = 14007, + [ParentCombo(SGE_ST_DPS)] + [CustomComboInfo("Soteria Option", "Weaves Soteria if you have the Kardia buff.", SGE.JobID)] + SGE_ST_DPS_Soteria = 14056, + [ParentCombo(SGE_ST_DPS)] [CustomComboInfo("Psyche Option", "Weaves Psyche when available.", SGE.JobID, 112)] SGE_ST_DPS_Psyche = 14008, @@ -3409,7 +3413,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region AoE DPS Feature - [AutoAction(false, false)] + [AutoAction(true, false)] [ReplaceSkill(SGE.Dyskrasia, SGE.Dyskrasia2)] [CustomComboInfo("AoE DPS Feature", "Adds various options to Dyskrasia I & II. Requires a target.", SGE.JobID, 200)] SGE_AoE_DPS = 14009, @@ -3438,6 +3442,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Rhizomata Option", "Weaves Rhizomata when Addersgall gauge falls below the specified value.", SGE.JobID, 5)] SGE_AoE_DPS_Rhizo = 14013, + [ParentCombo(SGE_AoE_DPS)] + [CustomComboInfo("Soteria Option", "Weaves Soteria if you have the Kardia buff.", SGE.JobID)] + SGE_AoE_DPS_Soteria = 14057, + [ParentCombo(SGE_AoE_DPS)] [CustomComboInfo("Addersgall Overflow Protection", "Weaves Druochole when Addersgall gauge is greater than or equal to the specified value.", SGE.JobID, 6)] SGE_AoE_DPS_AddersgallProtect = 14053, diff --git a/XIVSlothCombo/Combos/PvE/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM.cs index 6ca66bd9e..b7446191d 100644 --- a/XIVSlothCombo/Combos/PvE/BLM.cs +++ b/XIVSlothCombo/Combos/PvE/BLM.cs @@ -200,7 +200,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (gauge.InAstralFire) { - if (gauge.IsParadoxActive && gcdsInTimer < 2 && curMp >= MP.FireI) return Paradox; @@ -242,7 +241,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } if (gauge.InUmbralIce) { - if (ActionReady(Blizzard3) && gauge.UmbralIceStacks < 3 && TraitLevelChecked(Traits.UmbralHeart)) + if (ActionReady(Blizzard3) && gauge.UmbralIceStacks < 3) { if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0) return Triplecast; @@ -274,7 +273,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if ((curMp + nextMpGain <= 10000 || curMp < 7500)) return Blizzard; - if (ActionReady(Transpose) && CanSpellWeave(ActionWatching.LastSpell)) + if (ActionReady(Transpose) && CanSpellWeave(ActionWatching.LastSpell) && !Fire3.LevelChecked()) return Transpose; if (Fire3.LevelChecked()) diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN.cs index fb88e4f11..f36fb7d85 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN.cs @@ -263,7 +263,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Mug_AlignBefore) && HasEffect(Buffs.ShadowWalker) && GetCooldownRemainingTime(TrickAttack) <= 3 && - ((IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Delayed) && InCombat() && combatDuration.TotalSeconds > 6) || + ((IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Delayed) && InCombat() && CombatEngageDuration().TotalSeconds > 6) || IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Delayed)) && IsOffCooldown(Mug) && Mug.LevelChecked()) @@ -272,7 +272,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack) && HasEffect(Buffs.ShadowWalker) && IsOffCooldown(TrickAttack) && - ((IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Delayed) && InCombat() && combatDuration.TotalSeconds > 8) || + ((IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Delayed) && InCombat() && CombatEngageDuration().TotalSeconds > 8) || IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Delayed))) return OriginalHook(TrickAttack); diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE.cs index f66eef682..8abac9b78 100644 --- a/XIVSlothCombo/Combos/PvE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE.cs @@ -246,6 +246,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ActionReady(Rhizomata) && Gauge.Addersgall <= Config.SGE_AoE_DPS_Rhizo) return Rhizomata; + //Soteria + if (IsEnabled(CustomComboPreset.SGE_AoE_DPS_Soteria) && CanSpellWeave(ActionWatching.LastSpell) && + ActionReady(Soteria) && HasEffect(Buffs.Kardia)) + return Soteria; + // Addersgall Protection if (IsEnabled(CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) && CanSpellWeave(Dosis) && ActionReady(Druochole) && Gauge.Addersgall >= Config.SGE_AoE_DPS_AddersgallProtect) @@ -376,6 +381,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ActionReady(Rhizomata) && Gauge.Addersgall <= Config.SGE_ST_DPS_Rhizo) return Rhizomata; + //Soteria + if (IsEnabled(CustomComboPreset.SGE_ST_DPS_Soteria) && CanSpellWeave(ActionWatching.LastSpell) && + ActionReady(Soteria) && HasEffect(Buffs.Kardia)) + return Soteria; + // Addersgall Protection if (IsEnabled(CustomComboPreset.SGE_ST_DPS_AddersgallProtect) && CanSpellWeave(Dosis) && ActionReady(Druochole) && Gauge.Addersgall >= Config.SGE_ST_DPS_AddersgallProtect) diff --git a/XIVSlothCombo/CustomCombo/CustomCombo.cs b/XIVSlothCombo/CustomCombo/CustomCombo.cs index 070e3625a..02d366732 100644 --- a/XIVSlothCombo/CustomCombo/CustomCombo.cs +++ b/XIVSlothCombo/CustomCombo/CustomCombo.cs @@ -18,8 +18,6 @@ protected CustomCombo() CustomComboInfoAttribute? presetInfo = Preset.GetAttribute(); JobID = presetInfo.JobID; ClassID = JobIDs.JobToClass(JobID); - - StartTimer(); } protected IGameObject? OptionalTarget; diff --git a/XIVSlothCombo/CustomCombo/Functions/Timer.cs b/XIVSlothCombo/CustomCombo/Functions/Timer.cs index 39bbfe3c1..e8d16878e 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Timer.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Timer.cs @@ -1,47 +1,31 @@ -using System; -using System.Timers; +using Dalamud.Game.ClientState.Conditions; +using ECommons.DalamudServices; +using System; namespace XIVSlothCombo.CustomComboNS.Functions { internal abstract partial class CustomComboFunctions { - internal bool restartCombatTimer = true; - internal TimeSpan combatDuration = new(); - internal DateTime combatStart; - internal DateTime combatEnd; - internal Timer? combatTimer; + private static DateTime combatStart = DateTime.Now; - /// Called by the timer in the constructor to keep track of combat duration. - internal void UpdateCombatTimer(object? sender, EventArgs e) - { - if (InCombat()) - { - if (restartCombatTimer) - { - restartCombatTimer = false; - combatStart = DateTime.Now; - } - - combatEnd = DateTime.Now; - } - else - { - restartCombatTimer = true; - combatDuration = TimeSpan.Zero; - } + /// Tells the elapsed time since the combat started. + /// Combat time in seconds. + public static TimeSpan CombatEngageDuration() => InCombat() ? DateTime.Now - combatStart : TimeSpan.Zero; - combatDuration = combatEnd - combatStart; + public static void TimerSetup() + { + Svc.Condition.ConditionChange += OnCombat; } - /// Tells the elapsed time since the combat started. - /// Combat time in seconds. - protected TimeSpan CombatEngageDuration() => combatDuration; + public static void TimerDispose() + { + Svc.Condition.ConditionChange -= OnCombat; + } - protected void StartTimer() + internal static void OnCombat(ConditionFlag flag, bool value) { - combatTimer = new Timer(1000); // in milliseconds - combatTimer.Elapsed += UpdateCombatTimer; - combatTimer.Start(); + if (flag == ConditionFlag.InCombat && value) + combatStart = DateTime.Now; } } } diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index da421175e..18d7757eb 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -1,6 +1,10 @@ using Dalamud.Interface.Components; +using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; +using Lumina.Excel.GeneratedSheets; +using XIVSlothCombo.Combos.PvE; +using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; namespace XIVSlothCombo.Window.Tabs @@ -72,6 +76,12 @@ internal class AutoRotationTab : ConfigWindow cfg.HealerSettings.AoEHealTargetCount = 0; } ImGuiComponents.HelpMarker($"Disabling this will turn off AoE Healing features. Otherwise will require the amount of targets required to be in range of an AoE feature's heal to use."); + ImGui.Spacing(); + changed |= ImGui.Checkbox($"[{Svc.Data.GetExcelSheet().GetRow(40).Abbreviation}] Automatically Manage Kardia", ref cfg.HealerSettings.ManageKardia); + ImGuiComponents.HelpMarker($"Switches {SGE.Kardia.ActionName()} to party members currently being targeted by enemies, prioritising tanks if multiple people are being targeted."); + if (cfg.HealerSettings.ManageKardia) + changed |= ImGui.Checkbox($"Limit {SGE.Kardia.ActionName()} swapping to tanks only", ref cfg.HealerSettings.KardiaTanksOnly); + } if (changed) diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 84925ec34..03136c7d3 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -24,6 +24,7 @@ using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Combos.PvP; using XIVSlothCombo.Core; +using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Services; using XIVSlothCombo.Window; @@ -143,6 +144,7 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) KillRedundantIDs(); HandleConflictedCombos(); + CustomComboFunctions.TimerSetup(); #if DEBUG ConfigWindow.IsOpen = true; @@ -280,6 +282,7 @@ public void Dispose() ActionWatching.Dispose(); Combos.JobHelpers.AST.Dispose(); DisposeOpeners(); + CustomComboFunctions.TimerDispose(); Svc.ClientState.Login -= PrintLoginMessage; P = null; From 214796bb4add2dba0453608d9140f0b65bcc0463 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 8 Nov 2024 11:41:36 +0000 Subject: [PATCH 186/208] Updoot --- XIVSlothCombo/AutoRotation/AutoRotationController.cs | 2 +- XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 058096c18..35c475f07 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -288,7 +288,7 @@ public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttribute public class DPSTargeting { - public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable).OrderByDescending(x => IsPriority(x)); + public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable && ActionManager.GetActionInRangeOrLoS(7, Player.GameObject, x.Struct()) != 562).OrderByDescending(x => IsPriority(x)); private static bool IsPriority(IGameObject x) { diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 914d66928..fa2f3ec0e 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -31,7 +31,7 @@ public static UserBoolArray public static UserInt SCH_AoE_LucidOption = new("SCH_AoE_LucidOption", 6500), SCH_AoE_Heal_LucidOption = new("SCH_AoE_Heal_LucidOption", 6500), - SCH_AoE_Heal_SuccorShieldOption = new("SCH_AoE_Heal_SuccorShieldCount",4), + SCH_AoE_Heal_SuccorShieldOption = new("SCH_AoE_Heal_SuccorShieldCount"), SCH_AoE_Heal_WhisperingDawnOption = new("SCH_AoE_Heal_WhisperingDawnOption"), SCH_AoE_Heal_FeyIlluminationOption = new("SCH_AoE_Heal_FeyIlluminationOption"), SCH_AoE_Heal_ConsolationOption = new("SCH_AoE_Heal_ConsolationOption"), From 352bd12717eed4d733ac7e41219621c8a973c143 Mon Sep 17 00:00:00 2001 From: Kage <95875972+Kagekazu@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:43:05 +0100 Subject: [PATCH 187/208] remove mnk from jobhelpers --- XIVSlothCombo/Combos/JobHelpers/MNK.cs | 1 - 1 file changed, 1 deletion(-) delete mode 100644 XIVSlothCombo/Combos/JobHelpers/MNK.cs diff --git a/XIVSlothCombo/Combos/JobHelpers/MNK.cs b/XIVSlothCombo/Combos/JobHelpers/MNK.cs deleted file mode 100644 index 5f282702b..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/MNK.cs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 43f8fdeb299cb2e4651bb0c287ef7e5a5b8d9245 Mon Sep 17 00:00:00 2001 From: Kage <95875972+Kagekazu@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:54:34 +0100 Subject: [PATCH 188/208] format all classes to the same standard --- XIVSlothCombo/Combos/CustomComboPreset.cs | 142 ++- XIVSlothCombo/Combos/JobHelpers/BLM.cs | 492 ---------- .../Combos/JobHelpers/Enums/OpenerState.cs | 10 - XIVSlothCombo/Combos/JobHelpers/NIN.cs | 648 ------------- XIVSlothCombo/Combos/PvE/ADV.cs | 30 - XIVSlothCombo/Combos/PvE/ADV/ADV.cs | 28 + XIVSlothCombo/Combos/PvE/ADV/ADV_Config.cs | 17 + XIVSlothCombo/Combos/PvE/ALL.cs | 255 ----- XIVSlothCombo/Combos/PvE/ALL/ALL.cs | 253 +++++ XIVSlothCombo/Combos/PvE/ALL/ALL_Config.cs | 17 + XIVSlothCombo/Combos/PvE/BLM.cs | 513 ---------- XIVSlothCombo/Combos/PvE/BLM/BLM.cs | 897 ++++++++++++++++++ XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs | 95 ++ XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs | 300 ++++++ XIVSlothCombo/Combos/PvE/{ => BLU}/BLU.cs | 2 +- XIVSlothCombo/Combos/PvE/BLU/BLU_Config.cs | 17 + XIVSlothCombo/Combos/PvE/{ => BRD}/BRD.cs | 14 +- XIVSlothCombo/Combos/PvE/BRD/BRD_Config.cs | 57 ++ XIVSlothCombo/Combos/PvE/Content/Bozja.cs | 111 ++- XIVSlothCombo/Combos/PvE/Content/Variant.cs | 82 +- XIVSlothCombo/Combos/PvE/{ => DNC}/DNC.cs | 33 +- XIVSlothCombo/Combos/PvE/DNC/DNC_Config.cs | 162 ++++ XIVSlothCombo/Combos/PvE/{ => DOH}/DOH.cs | 2 +- XIVSlothCombo/Combos/PvE/DOH/DOH_Config.cs | 17 + XIVSlothCombo/Combos/PvE/{ => DOL}/DOL.cs | 2 +- XIVSlothCombo/Combos/PvE/DOL/DOL_Config.cs | 17 + XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs | 3 +- XIVSlothCombo/Combos/PvE/{ => DRK}/DRK.cs | 11 +- XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs | 58 ++ XIVSlothCombo/Combos/PvE/Enums/OpenerState.cs | 9 + XIVSlothCombo/Combos/PvE/{ => GNB}/GNB.cs | 14 +- XIVSlothCombo/Combos/PvE/GNB/GNB_Config.cs | 40 + XIVSlothCombo/Combos/PvE/MCH/MCH.cs | 2 +- XIVSlothCombo/Combos/PvE/{ => NIN}/NIN.cs | 32 +- XIVSlothCombo/Combos/PvE/NIN/NIN_Config.cs | 155 +++ XIVSlothCombo/Combos/PvE/NIN/NIN_Helper.cs | 698 ++++++++++++++ XIVSlothCombo/Combos/PvE/{ => PCT}/PCT.cs | 27 +- XIVSlothCombo/Combos/PvE/PCT/PCT_Config.cs | 125 +++ .../PCT.cs => PvE/PCT/PCT_Helper.cs} | 653 +++++++------ XIVSlothCombo/Combos/PvE/{ => PLD}/PLD.cs | 23 +- XIVSlothCombo/Combos/PvE/PLD/PLD_Config.cs | 121 +++ XIVSlothCombo/Combos/PvE/RDM/RDM.cs | 2 +- XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs | 2 +- XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs | 2 +- XIVSlothCombo/Combos/PvE/{ => SAM}/SAM.cs | 30 +- XIVSlothCombo/Combos/PvE/SAM/SAM_Config.cs | 157 +++ .../SAM.cs => PvE/SAM/SAM_Helper.cs} | 133 ++- XIVSlothCombo/Combos/PvE/{ => SMN}/SMN.cs | 20 +- XIVSlothCombo/Combos/PvE/SMN/SMN_Config.cs | 104 ++ XIVSlothCombo/Combos/PvE/{ => WAR}/WAR.cs | 16 +- XIVSlothCombo/Combos/PvE/WAR/WAR_Config.cs | 80 ++ XIVSlothCombo/Data/ActionWatching.cs | 5 +- XIVSlothCombo/Window/Functions/Presets.cs | 38 +- XIVSlothCombo/Window/Functions/UserConfig.cs | 518 ---------- 54 files changed, 4102 insertions(+), 3189 deletions(-) delete mode 100644 XIVSlothCombo/Combos/JobHelpers/BLM.cs delete mode 100644 XIVSlothCombo/Combos/JobHelpers/Enums/OpenerState.cs delete mode 100644 XIVSlothCombo/Combos/JobHelpers/NIN.cs delete mode 100644 XIVSlothCombo/Combos/PvE/ADV.cs create mode 100644 XIVSlothCombo/Combos/PvE/ADV/ADV.cs create mode 100644 XIVSlothCombo/Combos/PvE/ADV/ADV_Config.cs delete mode 100644 XIVSlothCombo/Combos/PvE/ALL.cs create mode 100644 XIVSlothCombo/Combos/PvE/ALL/ALL.cs create mode 100644 XIVSlothCombo/Combos/PvE/ALL/ALL_Config.cs delete mode 100644 XIVSlothCombo/Combos/PvE/BLM.cs create mode 100644 XIVSlothCombo/Combos/PvE/BLM/BLM.cs create mode 100644 XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs create mode 100644 XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs rename XIVSlothCombo/Combos/PvE/{ => BLU}/BLU.cs (99%) create mode 100644 XIVSlothCombo/Combos/PvE/BLU/BLU_Config.cs rename XIVSlothCombo/Combos/PvE/{ => BRD}/BRD.cs (99%) create mode 100644 XIVSlothCombo/Combos/PvE/BRD/BRD_Config.cs rename XIVSlothCombo/Combos/PvE/{ => DNC}/DNC.cs (94%) create mode 100644 XIVSlothCombo/Combos/PvE/DNC/DNC_Config.cs rename XIVSlothCombo/Combos/PvE/{ => DOH}/DOH.cs (93%) create mode 100644 XIVSlothCombo/Combos/PvE/DOH/DOH_Config.cs rename XIVSlothCombo/Combos/PvE/{ => DOL}/DOL.cs (99%) create mode 100644 XIVSlothCombo/Combos/PvE/DOL/DOL_Config.cs rename XIVSlothCombo/Combos/PvE/{ => DRK}/DRK.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs create mode 100644 XIVSlothCombo/Combos/PvE/Enums/OpenerState.cs rename XIVSlothCombo/Combos/PvE/{ => GNB}/GNB.cs (99%) create mode 100644 XIVSlothCombo/Combos/PvE/GNB/GNB_Config.cs rename XIVSlothCombo/Combos/PvE/{ => NIN}/NIN.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/NIN/NIN_Config.cs create mode 100644 XIVSlothCombo/Combos/PvE/NIN/NIN_Helper.cs rename XIVSlothCombo/Combos/PvE/{ => PCT}/PCT.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/PCT/PCT_Config.cs rename XIVSlothCombo/Combos/{JobHelpers/PCT.cs => PvE/PCT/PCT_Helper.cs} (82%) rename XIVSlothCombo/Combos/PvE/{ => PLD}/PLD.cs (96%) create mode 100644 XIVSlothCombo/Combos/PvE/PLD/PLD_Config.cs rename XIVSlothCombo/Combos/PvE/{ => SAM}/SAM.cs (96%) create mode 100644 XIVSlothCombo/Combos/PvE/SAM/SAM_Config.cs rename XIVSlothCombo/Combos/{JobHelpers/SAM.cs => PvE/SAM/SAM_Helper.cs} (80%) rename XIVSlothCombo/Combos/PvE/{ => SMN}/SMN.cs (98%) create mode 100644 XIVSlothCombo/Combos/PvE/SMN/SMN_Config.cs rename XIVSlothCombo/Combos/PvE/{ => WAR}/WAR.cs (97%) create mode 100644 XIVSlothCombo/Combos/PvE/WAR/WAR_Config.cs diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 84d38bc9c..5de0338c8 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -365,19 +365,132 @@ public enum CustomComboPreset // Last value = 1054 #endregion - + #region BLACK MAGE [AutoAction(false, false)] [ReplaceSkill(BLM.Fire)] - [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -10)] - BLM_ST_SimpleMode = 2012, + [ConflictingCombos(BLM_ST_AdvancedMode)] + [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID)] + BLM_ST_SimpleMode = 2001, [AutoAction(true, false)] [ReplaceSkill(BLM.Blizzard2, BLM.HighBlizzard2)] - [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID, -8)] - BLM_AoE_SimpleMode = 2008, + [ConflictingCombos(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID)] + BLM_AoE_SimpleMode = 2002, + + #region Single Target - Advanced + + [AutoAction(false, false)] + [ReplaceSkill(BLM.Fire)] + [ConflictingCombos(BLM_ST_SimpleMode)] + [CustomComboInfo("Advanced Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", BLM.JobID)] + BLM_ST_AdvancedMode = 2100, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Level 100 Opener", "Adds the Balance opener to the rotation.", BLM.JobID)] + BLM_ST_Opener = 2101, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Amplifier", "Add Amplifier to the rotation.", BLM.JobID)] + BLM_ST_Amplifier = 2102, + + [ParentCombo(BLM_ST_AdvancedMode)] [CustomComboInfo("Use Leylines", "Add Leylines to the rotation.", BLM.JobID)] + BLM_ST_LeyLines = 2103, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Foul / Xenoglossy", "Add Foul / Xenoglossy to the rotation.", BLM.JobID)] + BLM_ST_UsePolyglot = 2104, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Foul / Xenoglossy for movement", "Add Foul / Xenoglossy to the rotation as movement option.", BLM.JobID)] + BLM_ST_UsePolyglotMoving = 2105, + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Swiftcast", "Add Swiftcast to the rotation.", BLM.JobID)] + BLM_ST_Swiftcast = 2106, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Triplecast", "Add Triplecast to the rotation.", BLM.JobID)] + BLM_ST_Triplecast = 2107, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Manafont", "Add Manafont to the rotation.", BLM.JobID)] + BLM_ST_Manafont = 2108, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Transpose", "Add Transpose to the rotation.", BLM.JobID)] + BLM_ST_Transpose = 2109, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Thunder", "Add Thunder to the rotation.", BLM.JobID)] + BLM_ST_Thunder = 2110, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Despair", "Add Despair to the rotation.", BLM.JobID)] + BLM_ST_Despair = 2111, + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Use Flarestar", "Add Flarestar to the rotation.", BLM.JobID)] + BLM_ST_Flarestar = 2112, + + #endregion + + #region AoE - Advanced + + [AutoAction(true, false)] + [ReplaceSkill(BLM.Fire)] + [ConflictingCombos(BLM_AoE_SimpleMode)] + [CustomComboInfo("Advanced Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", BLM.JobID)] + BLM_AoE_AdvancedMode = 2200, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Amplifier", "Add Amplifier to the rotation.", BLM.JobID)] + BLM_AoE_Amplifier = 2201, + + [ParentCombo(CustomComboPreset.BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Leylines", "Add Leylines to the rotation.", BLM.JobID)] + BLM_AoE_LeyLines = 2202, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Foul", "Add Foul to the rotation.", BLM.JobID)] + BLM_AoE_UsePolyglot = 2203, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Foul for movement", "Add Foul to the rotation as movement option.", BLM.JobID)] + BLM_AoE_UsePolyglotMoving = 2204, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Swiftcast", "Add Swiftcast to the rotation.", BLM.JobID)] + BLM_AoE_Swiftcast = 2205, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Triplecast", "Add Triplecast to the rotation.", BLM.JobID)] + BLM_AoE_Triplecast = 2206, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Manafont", "Add Manafont to the rotation.", BLM.JobID)] + BLM_AoE_Manafont = 2207, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Transpose", "Add Transpose to the rotation.", BLM.JobID)] + BLM_AoE_Transpose = 2208, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Thunder", "Add Thunder to the rotation.", BLM.JobID)] + BLM_AoE_Thunder = 2209, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Flare", "Add Flare to the rotation.", BLM.JobID)] + BLM_AoE_Flare = 2210, + + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Use Flarestar", "Add Flarestar to the rotation.", BLM.JobID)] + BLM_AoE_Flarestar = 2211, + + #endregion + #region Variant [Variant] @@ -399,31 +512,36 @@ public enum CustomComboPreset #region Miscellaneous [ReplaceSkill(BLM.Transpose)] [CustomComboInfo("Umbral Soul/Transpose Feature", "Replaces Transpose with Umbral Soul when Umbral Soul is available.", BLM.JobID)] - BLM_UmbralSoul = 2001, + BLM_UmbralSoul = 2050, [ReplaceSkill(BLM.LeyLines)] [CustomComboInfo("Between the Ley Lines Feature", "Replaces Ley Lines with Between the Lines when Ley Lines is active.", BLM.JobID)] - BLM_Between_The_LeyLines = 2002, + BLM_Between_The_LeyLines = 2051, [ReplaceSkill(BLM.Blizzard, BLM.Freeze)] [CustomComboInfo("Blizzard I/III Feature", "Replaces Blizzard I with Blizzard III when out of Umbral Ice." + "\nReplaces Freeze with Blizzard II when synced below Lv.40.", BLM.JobID)] - BLM_Blizzard_1to3 = 2003, + BLM_Blizzard_1to3 = 2052, [ReplaceSkill(BLM.Scathe)] [CustomComboInfo("Xenoglossy Feature", "Replaces Scathe with Xenoglossy when available.", BLM.JobID)] - BLM_Scathe_Xeno = 2004, + BLM_Scathe_Xeno = 2053, [ReplaceSkill(BLM.Fire)] [CustomComboInfo("Fire I/III Feature", "Replaces Fire I with Fire III outside of Astral Fire or when Firestarter is up.", BLM.JobID)] - BLM_Fire_1to3 = 2005, + BLM_Fire_1to3 = 2054, [ReplaceSkill(BLM.AetherialManipulation)] [CustomComboInfo("Aetherial Manipulation Feature", "Replaces Aetherial Manipulation with Between the Lines when you are out of active Ley Lines and standing still.", BLM.JobID)] - BLM_Aetherial_Manipulation = 2046, + BLM_Aetherial_Manipulation = 2055, + + [ReplaceSkill(BLM.Triplecast)] + [CustomComboInfo("Triplecast Protection", "Replaces Triplecast with Savage Blade when u already have triplecast active.", BLM.JobID)] + BLM_TriplecastProtection = 2056, #endregion - // Last value = 2057 + // Last value ST = 2112 + //Last Value AoE = 2211 #endregion diff --git a/XIVSlothCombo/Combos/JobHelpers/BLM.cs b/XIVSlothCombo/Combos/JobHelpers/BLM.cs deleted file mode 100644 index 89e3a0dc9..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/BLM.cs +++ /dev/null @@ -1,492 +0,0 @@ -using Dalamud.Game.ClientState.JobGauge.Types; -using ECommons.DalamudServices; -using System; -using System.Linq; -using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; -using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Data; - -namespace XIVSlothCombo.Combos.JobHelpers -{ - internal class BLMOpenerLogic : PvE.BLM - { - private static bool HasCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(Triplecast) < 2) - return false; - if (!CustomComboFunctions.ActionReady(Manafont)) - return false; - if (!CustomComboFunctions.ActionReady(All.Swiftcast)) - return false; - if (!CustomComboFunctions.ActionReady(Amplifier)) - return false; - if (!CustomComboFunctions.ActionReady(All.LucidDreaming) && - Config.BLM_Advanced_OpenerSelection == 1) - return false; - if (!CustomComboFunctions.ActionReady(LeyLines)) - return false; - - return true; - } - - public static bool HasPrePullCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(Sharpcast) < 2) - return false; - - if (CustomComboFunctions.LocalPlayer.CurrentMp < 10000) - return false; - - return true; - } - - private static uint OpenerLevel => 90; - - public uint PrePullStep = 0; - - public uint OpenerStep = 1; - - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; - - private static bool CanOpener => HasCooldowns() && HasPrePullCooldowns() && LevelChecked; - - private OpenerState currentState = OpenerState.PrePull; - - public OpenerState CurrentState - { - get - { - return currentState; - } - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) - { - if (value == OpenerState.FailedOpener) - Svc.Log.Information($"Opener Failed at step {OpenerStep}"); - - ResetOpener(); - } - if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); - - currentState = value; - } - } - } - - private bool DoPrePullSteps(ref uint actionID) - { - if (!LevelChecked) return false; - - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } - - if (!HasCooldowns()) - { - PrePullStep = 0; - } - - if (CurrentState == OpenerState.PrePull && PrePullStep > 0) - { - if (CustomComboFunctions.HasEffect(Buffs.Sharpcast) && PrePullStep == 1) PrePullStep++; - else if (PrePullStep == 1) actionID = Sharpcast; - - if (CustomComboFunctions.LocalPlayer.CastActionId == Fire3 && PrePullStep == 2) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 2) actionID = Fire3; - - if (PrePullStep == 2 && !CustomComboFunctions.HasEffect(Buffs.Sharpcast)) - CurrentState = OpenerState.FailedOpener; - - if (PrePullStep > 1 && CustomComboFunctions.GetResourceCost(actionID) > CustomComboFunctions.LocalPlayer.CurrentMp && ActionWatching.TimeSinceLastAction.TotalSeconds >= 2) - CurrentState = OpenerState.FailedOpener; - - if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) - CurrentState = OpenerState.FailedOpener; - - return true; - } - - PrePullStep = 0; - return false; - } - - private bool DoOpener(ref uint actionID) - { - if (!LevelChecked) return false; - - if (currentState == OpenerState.InOpener) - { - if (Config.BLM_Advanced_OpenerSelection == 0) - { - if (CustomComboFunctions.LocalPlayer.CastActionId == Thunder3 && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = Thunder3; - - if (CustomComboFunctions.WasLastAction(Triplecast) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = Triplecast; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 2 && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 1 && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Amplifier) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Amplifier; - - if (CustomComboFunctions.WasLastAction(LeyLines) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = LeyLines; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 0 && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(All.Swiftcast) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = All.Swiftcast; - - if (CustomComboFunctions.WasLastAction(Fire4) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Triplecast) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = Triplecast; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Despair; - - if (CustomComboFunctions.WasLastAction(Manafont) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = Manafont; - - if (CustomComboFunctions.WasLastAction(Fire4) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Sharpcast) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = Sharpcast; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Despair; - - if (CustomComboFunctions.WasLastAction(Blizzard3) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = Blizzard3; - - if (CustomComboFunctions.WasLastAction(Xenoglossy) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = Xenoglossy; - - if (CustomComboFunctions.WasLastAction(Paradox) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Paradox; - - if (CustomComboFunctions.LocalPlayer.CastActionId == Blizzard4 && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Blizzard4; - - if (CustomComboFunctions.WasLastAction(Thunder3) && OpenerStep == 20) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 20) actionID = Thunder3; - - if (((actionID == Triplecast && CustomComboFunctions.GetRemainingCharges(Triplecast) < 2) || - (actionID == Amplifier && CustomComboFunctions.IsOnCooldown(Amplifier)) || - (actionID == LeyLines && CustomComboFunctions.IsOnCooldown(LeyLines)) || - (actionID == All.LucidDreaming && CustomComboFunctions.IsOnCooldown(All.LucidDreaming)) || - (actionID == Manafont && CustomComboFunctions.IsOnCooldown(Manafont)) || - (actionID == Sharpcast && CustomComboFunctions.GetRemainingCharges(Sharpcast) < 1) || - (actionID == All.Swiftcast && CustomComboFunctions.IsOnCooldown(All.Swiftcast)) || - (actionID == Xenoglossy && Svc.Gauges.Get().PolyglotStacks < 1)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - } - - else - { - - if (CustomComboFunctions.LocalPlayer.CastActionId == Thunder3 && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = Thunder3; - - if (CustomComboFunctions.LocalPlayer.CastActionId == Fire4 && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Triplecast) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Triplecast; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 2 && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 1 && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Amplifier) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = Amplifier; - - if (CustomComboFunctions.WasLastAction(LeyLines) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = LeyLines; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 0 && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Triplecast) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Triplecast; - - if (CustomComboFunctions.WasLastAction(All.LucidDreaming) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = All.LucidDreaming; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Despair; - - if (CustomComboFunctions.WasLastAction(Manafont) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = Manafont; - - if (CustomComboFunctions.WasLastAction(Fire4) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Sharpcast) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = Sharpcast; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Despair; - - if (CustomComboFunctions.WasLastAction(Transpose) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = Transpose; - - if (CustomComboFunctions.WasLastAction(Paradox) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = Paradox; - - if (CustomComboFunctions.WasLastAction(All.Swiftcast) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = All.Swiftcast; - - if (CustomComboFunctions.WasLastAction(Xenoglossy) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Xenoglossy; - - if ((CustomComboFunctions.LocalPlayer.CastActionId == Thunder3 || CustomComboFunctions.WasLastAction(Thunder3)) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = Thunder3; - - if (CustomComboFunctions.LocalPlayer.CurrentMp == CustomComboFunctions.LocalPlayer.MaxMp && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = Blizzard3; - - if (CustomComboFunctions.WasLastAction(Transpose) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = Transpose; - - if ((CustomComboFunctions.LocalPlayer.CastActionId == Fire3 || CustomComboFunctions.WasLastAction(Fire3)) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = Fire3; - - if ((CustomComboFunctions.LocalPlayer.CastActionId == Fire4 || CustomComboFunctions.WasLastAction(Fire4)) && OpenerStep == 24 && ActionWatching.CombatActions.Count == 24) OpenerStep++; - else if (OpenerStep == 24) actionID = Fire4; - - if ((CustomComboFunctions.LocalPlayer.CastActionId == Fire4 || CustomComboFunctions.WasLastAction(Fire4)) && OpenerStep == 25 && ActionWatching.CombatActions.Count == 25) OpenerStep++; - else if (OpenerStep == 25) actionID = Fire4; - - if ((CustomComboFunctions.LocalPlayer.CastActionId == Fire4 || CustomComboFunctions.WasLastAction(Fire4)) && OpenerStep == 26 && ActionWatching.CombatActions.Count == 26) OpenerStep++; - else if (OpenerStep == 26) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 27) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 27) actionID = Despair; - } - - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; - - if (CustomComboFunctions.GetResourceCost(actionID) > CustomComboFunctions.LocalPlayer.CurrentMp && ActionWatching.TimeSinceLastAction.TotalSeconds >= 2) - CurrentState = OpenerState.FailedOpener; - - if (((actionID == Triplecast && CustomComboFunctions.GetRemainingCharges(Triplecast) < 2) || - (actionID == Amplifier && CustomComboFunctions.IsOnCooldown(Amplifier)) || - (actionID == LeyLines && CustomComboFunctions.IsOnCooldown(LeyLines)) || - (actionID == All.LucidDreaming && CustomComboFunctions.IsOnCooldown(All.LucidDreaming)) || - (actionID == Manafont && CustomComboFunctions.IsOnCooldown(Manafont)) || - (actionID == Sharpcast && CustomComboFunctions.GetRemainingCharges(Sharpcast) < 1) || - (actionID == All.Swiftcast && CustomComboFunctions.IsOnCooldown(All.Swiftcast)) || - (actionID == Xenoglossy && Svc.Gauges.Get().PolyglotStacks < 1)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - - return true; - } - - return false; - } - - private bool DoOpenerSimple(ref uint actionID) - { - if (!LevelChecked) return false; - - if (currentState == OpenerState.InOpener) - { - if (CustomComboFunctions.LocalPlayer.CastActionId == Thunder3 && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = Thunder3; - - if (CustomComboFunctions.WasLastAction(Triplecast) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = Triplecast; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 2 && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 1 && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Amplifier) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = Amplifier; - - if (CustomComboFunctions.WasLastAction(LeyLines) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = LeyLines; - - if (CustomComboFunctions.WasLastAction(Fire4) && CustomComboFunctions.GetBuffStacks(Buffs.Triplecast) == 0 && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(All.Swiftcast) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8) actionID = All.Swiftcast; - - if (CustomComboFunctions.WasLastAction(Fire4) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Triplecast) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = Triplecast; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) actionID = Despair; - - if (CustomComboFunctions.WasLastAction(Manafont) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = Manafont; - - if (CustomComboFunctions.WasLastAction(Fire4) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Fire4; - - if (CustomComboFunctions.WasLastAction(Sharpcast) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = Sharpcast; - - if (CustomComboFunctions.WasLastAction(Despair) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = Despair; - - if (CustomComboFunctions.WasLastAction(Blizzard3) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = Blizzard3; - - if (CustomComboFunctions.WasLastAction(Xenoglossy) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = Xenoglossy; - - if (CustomComboFunctions.WasLastAction(Paradox) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Paradox; - - if (CustomComboFunctions.LocalPlayer.CastActionId == Blizzard4 && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = Blizzard4; - - if (CustomComboFunctions.WasLastAction(Thunder3) && OpenerStep == 20) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 20) actionID = Thunder3; - - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) - CurrentState = OpenerState.FailedOpener; - - if (CustomComboFunctions.GetResourceCost(actionID) > CustomComboFunctions.LocalPlayer.CurrentMp && ActionWatching.TimeSinceLastAction.TotalSeconds >= 2) - CurrentState = OpenerState.FailedOpener; - - if (((actionID == Triplecast && CustomComboFunctions.GetRemainingCharges(Triplecast) < 2) || - (actionID == Amplifier && CustomComboFunctions.IsOnCooldown(Amplifier)) || - (actionID == LeyLines && CustomComboFunctions.IsOnCooldown(LeyLines)) || - (actionID == All.LucidDreaming && CustomComboFunctions.IsOnCooldown(All.LucidDreaming)) || - (actionID == Manafont && CustomComboFunctions.IsOnCooldown(Manafont)) || - (actionID == Sharpcast && CustomComboFunctions.GetRemainingCharges(Sharpcast) < 1) || - (actionID == All.Swiftcast && CustomComboFunctions.IsOnCooldown(All.Swiftcast)) || - (actionID == Xenoglossy && Svc.Gauges.Get().PolyglotStacks < 1)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) - { - CurrentState = OpenerState.FailedOpener; - return false; - } - - return true; - } - - return false; - } - - private void ResetOpener() - { - PrePullStep = 0; - OpenerStep = 0; - } - - public bool DoFullOpener(ref uint actionID, bool simpleMode) - { - if (!LevelChecked) return false; - - if (CurrentState == OpenerState.PrePull) - if (DoPrePullSteps(ref actionID)) return true; - - if (CurrentState == OpenerState.InOpener) - { - if (simpleMode) - { - if (DoOpenerSimple(ref actionID)) return true; - } - else - { - if (DoOpener(ref actionID)) return true; - } - } - - if (!CustomComboFunctions.InCombat()) - { - ResetOpener(); - CurrentState = OpenerState.PrePull; - } - - - return false; - } - } - - internal static class BLMExtensions - { - public static bool HasPolyglotStacks(this BLMGauge gauge) => gauge.PolyglotStacks > 0; - } - - internal class BLMHelper : BLM - { - public static float MPAfterCast() - { - var castedSpell = CustomComboFunctions.LocalPlayer.CastActionId; - var gauge = Svc.Gauges.Get(); - int nextMpGain = gauge.UmbralIceStacks switch - { - 0 => 0, - 1 => 2500, - 2 => 5000, - 3 => 10000, - _ => 0 - }; - if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - return Math.Max(CustomComboFunctions.LocalPlayer.MaxMp, CustomComboFunctions.LocalPlayer.CurrentMp + nextMpGain); - - return Math.Max(0, CustomComboFunctions.LocalPlayer.CurrentMp - CustomComboFunctions.GetResourceCost(castedSpell)); - - } - - public static bool DoubleBlizz() - { - var spells = ActionWatching.CombatActions.Where(x => ActionWatching.GetAttackType(x) == ActionWatching.ActionAttackType.Spell && x != CustomComboFunctions.OriginalHook(Thunder) && x != CustomComboFunctions.OriginalHook(Thunder2)).ToList(); - if (spells.Count < 1) return false; - - var firstSpell = spells[^1]; - - if (firstSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - { - var castedSpell = CustomComboFunctions.LocalPlayer.CastActionId; - if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) return true; - - if (spells.Count >= 2) - { - var secondSpell = spells[^2]; - if (secondSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - return true; - } - } - - return false; - - } - } -} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/JobHelpers/Enums/OpenerState.cs b/XIVSlothCombo/Combos/JobHelpers/Enums/OpenerState.cs deleted file mode 100644 index 77dff164c..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/Enums/OpenerState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace XIVSlothCombo.Combos.JobHelpers.Enums -{ - internal enum OpenerState - { - PrePull, - InOpener, - OpenerFinished, - FailedOpener - } -} diff --git a/XIVSlothCombo/Combos/JobHelpers/NIN.cs b/XIVSlothCombo/Combos/JobHelpers/NIN.cs deleted file mode 100644 index 9af849a29..000000000 --- a/XIVSlothCombo/Combos/JobHelpers/NIN.cs +++ /dev/null @@ -1,648 +0,0 @@ -using Dalamud.Game.ClientState.Conditions; -using Dalamud.Game.ClientState.JobGauge.Types; -using ECommons.DalamudServices; -using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Extensions; - -namespace XIVSlothCombo.Combos.JobHelpers -{ - internal class NIN - { - internal class NINHelper : PvE.NIN - { - internal static bool TrickDebuff => TargetHasTrickDebuff(); - private static bool TargetHasTrickDebuff() - { - return CustomComboFunctions.TargetHasEffect(Debuffs.TrickAttack) || CustomComboFunctions.TargetHasEffect(Debuffs.KunaisBane); - } - - internal static bool MugDebuff => TargetHasMugDebuff(); - - private static bool TargetHasMugDebuff() - { - return CustomComboFunctions.TargetHasEffect(Debuffs.Mug) || CustomComboFunctions.TargetHasEffect(Debuffs.Dokumori); - } - - internal static bool InMudra = false; - } - - internal class MudraCasting : PvE.NIN - { - /// Checks if the player is in a state to be able to cast a ninjitsu. - private static bool CanCast() - { - if (NINHelper.InMudra) return true; - var gcd = CustomComboFunctions.GetCooldown(GustSlash).CooldownTotal; - - if (gcd == 0.5) return true; - - if (CustomComboFunctions.GetRemainingCharges(Ten) == 0 && - !CustomComboFunctions.HasEffect(Buffs.Mudra) && - !CustomComboFunctions.HasEffect(Buffs.Kassatsu)) - return false; - - return true; - } - - - private MudraState currentMudra = MudraState.None; - public MudraState CurrentMudra - { - get - { - return currentMudra; - } - set - { - if (value == MudraState.None) - { - justResetMudra = true; - } - else - { - justResetMudra = false; - } - - currentMudra = value; - } - } - - /// Simple method of casting Fuma Shuriken. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastFumaShuriken(ref uint actionID) - { - if (FumaShuriken.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingFumaShuriken) - { - if (!CanCast()) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Ten); - CurrentMudra = MudraState.CastingFumaShuriken; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - - /// Simple method of casting Raiton. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastRaiton(ref uint actionID) - { - if (Raiton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingRaiton) - { - if (!CanCast()) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Chi); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Raiton) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Ten); - CurrentMudra = MudraState.CastingRaiton; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Katon. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastKaton(ref uint actionID) - { - if (Katon.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingKaton) - { - if (!CanCast()) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Ten); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Katon) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Chi); - CurrentMudra = MudraState.CastingKaton; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Hyoton. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastHyoton(ref uint actionID) - { - if (Hyoton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingHyoton) - { - if (!CanCast() || CustomComboFunctions.HasEffect(Buffs.Kassatsu)) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Jin); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Hyoton) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Ten); - CurrentMudra = MudraState.CastingHyoton; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Huton. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastHuton(ref uint actionID) - { - if (Huton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingHuton) - { - if (!CanCast()) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Jin); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Hyoton) - { - actionID = CustomComboFunctions.OriginalHook(Ten); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Huton) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Chi); - CurrentMudra = MudraState.CastingHuton; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Doton. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastDoton(ref uint actionID) - { - if (Doton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingDoton) - { - if (!CanCast()) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Jin); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Hyoton) - { - actionID = CustomComboFunctions.OriginalHook(Chi); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Doton) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Ten); - CurrentMudra = MudraState.CastingDoton; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Suiton. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastSuiton(ref uint actionID) - { - if (Suiton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingSuiton) - { - if (!CanCast()) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Chi); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Raiton) - { - actionID = CustomComboFunctions.OriginalHook(Jin); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is Suiton) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Ten); - CurrentMudra = MudraState.CastingSuiton; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Goka Mekkyaku. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastGokaMekkyaku(ref uint actionID) - { - if (GokaMekkyaku.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingGokaMekkyaku) - { - if (!CanCast() || !CustomComboFunctions.HasEffect(Buffs.Kassatsu)) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Ten); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is GokaMekkyaku) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Chi); - CurrentMudra = MudraState.CastingGokaMekkyaku; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - /// Simple method of casting Hyosho Ranryu. - /// The actionID from the combo. - /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. - public bool CastHyoshoRanryu(ref uint actionID) - { - if (HyoshoRanryu.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingHyoshoRanryu) - { - if (!CanCast() || !CustomComboFunctions.HasEffect(Buffs.Kassatsu)) - { - CurrentMudra = MudraState.None; - return false; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) - { - actionID = CustomComboFunctions.OriginalHook(Jin); - return true; - } - - if (CustomComboFunctions.OriginalHook(Ninjutsu) is HyoshoRanryu) - { - actionID = CustomComboFunctions.OriginalHook(Ninjutsu); - return true; - } - - actionID = CustomComboFunctions.OriginalHook(Chi); - CurrentMudra = MudraState.CastingHyoshoRanryu; - return true; - } - - CurrentMudra = MudraState.None; - return false; - } - - private bool justResetMudra = false; - public bool ContinueCurrentMudra(ref uint actionID) - { - if ((CustomComboFunctions.WasLastAction(FumaShuriken) || - CustomComboFunctions.WasLastAction(Katon) || - CustomComboFunctions.WasLastAction(Raiton) || - CustomComboFunctions.WasLastAction(Hyoton) || - CustomComboFunctions.WasLastAction(Huton) || - CustomComboFunctions.WasLastAction(Doton) || - CustomComboFunctions.WasLastAction(Suiton) || - CustomComboFunctions.WasLastAction(GokaMekkyaku) || - CustomComboFunctions.WasLastAction(HyoshoRanryu)) && - !justResetMudra) - CurrentMudra = MudraState.None; - - - return CurrentMudra switch - { - MudraState.None => false, - MudraState.CastingFumaShuriken => CastFumaShuriken(ref actionID), - MudraState.CastingKaton => CastKaton(ref actionID), - MudraState.CastingRaiton => CastRaiton(ref actionID), - MudraState.CastingHyoton => CastHyoton(ref actionID), - MudraState.CastingHuton => CastHuton(ref actionID), - MudraState.CastingDoton => CastDoton(ref actionID), - MudraState.CastingSuiton => CastSuiton(ref actionID), - MudraState.CastingGokaMekkyaku => CastGokaMekkyaku(ref actionID), - MudraState.CastingHyoshoRanryu => CastHyoshoRanryu(ref actionID), - _ => false, - }; - } - - public enum MudraState - { - None, - CastingFumaShuriken, - CastingKaton, - CastingRaiton, - CastingHyoton, - CastingHuton, - CastingDoton, - CastingSuiton, - CastingGokaMekkyaku, - CastingHyoshoRanryu - - } - } - - internal class NINOpenerLogic : PvE.NIN - { - private static bool HasCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(Ten) < 1) return false; - if (CustomComboFunctions.IsOnCooldown(Mug)) return false; - if (CustomComboFunctions.IsOnCooldown(TenChiJin)) return false; - if (CustomComboFunctions.IsOnCooldown(PhantomKamaitachi)) return false; - if (CustomComboFunctions.IsOnCooldown(Bunshin)) return false; - if (CustomComboFunctions.IsOnCooldown(DreamWithinADream)) return false; - if (CustomComboFunctions.IsOnCooldown(Kassatsu)) return false; - if (CustomComboFunctions.IsOnCooldown(TrickAttack)) return false; - - return true; - } - - private static uint OpenerLevel => 100; - - public uint PrePullStep = 1; - - private uint openerStep = 1; - - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; - - private static bool CanOpener => HasCooldowns() && LevelChecked; - - private OpenerState currentState = OpenerState.OpenerFinished; - - public OpenerState CurrentState - { - get - { - return currentState; - } - set - { - if (value != currentState) - { - if (value == OpenerState.PrePull) PrePullStep = 1; - if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { PrePullStep = 0; OpenerStep = 0; } - - currentState = value; - } - } - } - - public uint OpenerStep - { - get => openerStep; set - { - if (value != openerStep) - { - Svc.Log.Debug($"{value}"); - } - openerStep = value; - } - } - - private bool DoPrePullSteps(ref uint actionID, MudraCasting mudraState) - { - if (!LevelChecked) return false; - - if (CanOpener && PrePullStep == 0 && !CustomComboFunctions.InCombat()) { CurrentState = OpenerState.PrePull; } - - if (CurrentState == OpenerState.PrePull) - { - if (CustomComboFunctions.WasLastAction(Suiton) && PrePullStep == 1) CurrentState = OpenerState.InOpener; - else if (PrePullStep == 1) mudraState.CastSuiton(ref actionID); - - ////Failure states - //if (PrePullStep is (1 or 2) && CustomComboFunctions.InCombat()) { mudraState.CurrentMudra = MudraCasting.MudraState.None; ResetOpener(); } - - return true; - - } - - PrePullStep = 0; - return false; - } - - private bool DoOpener(ref uint actionID, MudraCasting mudraState) - { - if (!LevelChecked) return false; - - if (CurrentState == OpenerState.InOpener) - { - bool inLateWeaveWindow = CustomComboFunctions.CanDelayedWeave(GustSlash, 1, 0); - - if (CustomComboFunctions.WasLastAction(Kassatsu) && OpenerStep == 1) OpenerStep++; - else if (OpenerStep == 1) actionID = CustomComboFunctions.OriginalHook(Kassatsu); - - if (CustomComboFunctions.WasLastAction(SpinningEdge) && OpenerStep == 2) OpenerStep++; - else if (OpenerStep == 2) actionID = CustomComboFunctions.OriginalHook(SpinningEdge); - - if (CustomComboFunctions.WasLastAction(GustSlash) && OpenerStep == 3) OpenerStep++; - else if (OpenerStep == 3) actionID = CustomComboFunctions.OriginalHook(GustSlash); - - if (CustomComboFunctions.WasLastAction(CustomComboFunctions.OriginalHook(Mug)) && OpenerStep == 4) OpenerStep++; - else if (OpenerStep == 4) actionID = CustomComboFunctions.OriginalHook(Mug); - - if (CustomComboFunctions.WasLastAction(Bunshin) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5) actionID = CustomComboFunctions.OriginalHook(Bunshin); - - if (CustomComboFunctions.WasLastAction(PhantomKamaitachi) && OpenerStep == 6) OpenerStep++; - else if (OpenerStep == 6) actionID = CustomComboFunctions.OriginalHook(PhantomKamaitachi); - - if (CustomComboFunctions.WasLastAction(ArmorCrush) && OpenerStep == 7) OpenerStep++; - else if (OpenerStep == 7) actionID = CustomComboFunctions.OriginalHook(ArmorCrush); - - if (CustomComboFunctions.WasLastAction(CustomComboFunctions.OriginalHook(TrickAttack)) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && inLateWeaveWindow) actionID = CustomComboFunctions.OriginalHook(TrickAttack); - - if (CustomComboFunctions.WasLastAction(HyoshoRanryu) && OpenerStep == 9) OpenerStep++; - else if (OpenerStep == 9) mudraState.CastHyoshoRanryu(ref actionID); - - if (CustomComboFunctions.WasLastAction(DreamWithinADream) && OpenerStep == 10) OpenerStep++; - else if (OpenerStep == 10) actionID = CustomComboFunctions.OriginalHook(DreamWithinADream); - - if (CustomComboFunctions.WasLastAction(Raiton) && OpenerStep == 11) OpenerStep++; - else if (OpenerStep == 11) mudraState.CastRaiton(ref actionID); - - if (CustomComboFunctions.WasLastAction(TenChiJin) && OpenerStep == 12) OpenerStep++; - else if (OpenerStep == 12) actionID = CustomComboFunctions.OriginalHook(TenChiJin); - - if (CustomComboFunctions.WasLastAction(TCJFumaShurikenTen) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = CustomComboFunctions.OriginalHook(Ten); - - if (CustomComboFunctions.WasLastAction(TCJRaiton) && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = CustomComboFunctions.OriginalHook(Chi); - - if (CustomComboFunctions.WasLastAction(TCJSuiton) && OpenerStep == 15) OpenerStep++; - else if (OpenerStep == 15) actionID = CustomComboFunctions.OriginalHook(Jin); - - if (CustomComboFunctions.WasLastAction(Meisui) && OpenerStep == 16) OpenerStep++; - else if (OpenerStep == 16) actionID = CustomComboFunctions.OriginalHook(Meisui); - - if (CustomComboFunctions.WasLastAction(FleetingRaiju) && OpenerStep == 17) OpenerStep++; - else if (OpenerStep == 17) actionID = CustomComboFunctions.OriginalHook(FleetingRaiju); - - if (CustomComboFunctions.WasLastAction(ZeshoMeppo) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = CustomComboFunctions.OriginalHook(Bhavacakra); - - if (CustomComboFunctions.WasLastAction(TenriJendo) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = CustomComboFunctions.OriginalHook(TenriJendo); - - if (CustomComboFunctions.WasLastAction(FleetingRaiju) && OpenerStep == 20) OpenerStep++; - else if (OpenerStep == 20) actionID = CustomComboFunctions.OriginalHook(FleetingRaiju); - - if (CustomComboFunctions.WasLastAction(CustomComboFunctions.OriginalHook(Bhavacakra)) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = CustomComboFunctions.OriginalHook(Bhavacakra); - - if (CustomComboFunctions.WasLastAction(Raiton) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) mudraState.CastRaiton(ref actionID); - - if (CustomComboFunctions.WasLastAction(FleetingRaiju) && OpenerStep == 23) CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 23) actionID = CustomComboFunctions.OriginalHook(FleetingRaiju); - - - //Failure states - if ((OpenerStep is 13 or 14 or 15 && CustomComboFunctions.IsMoving) || - (OpenerStep is 8 && !CustomComboFunctions.HasEffect(Buffs.ShadowWalker)) || - (OpenerStep is 18 or 21 && CustomComboFunctions.GetJobGauge().Ninki < 40) || - (OpenerStep is 17 or 20 && !CustomComboFunctions.HasEffect(Buffs.RaijuReady)) || - (OpenerStep is 9 && !CustomComboFunctions.HasEffect(Buffs.Kassatsu))) - ResetOpener(); - - - return true; - } - - return false; - } - - private void ResetOpener() - { - CurrentState = OpenerState.FailedOpener; - } - - private bool openerEventsSetup = false; - - public bool DoFullOpener(ref uint actionID, MudraCasting mudraState) - { - if (!LevelChecked) return false; - - if (!openerEventsSetup) { Svc.Condition.ConditionChange += CheckCombatStatus; openerEventsSetup = true; } - - if (CurrentState == OpenerState.PrePull || CurrentState == OpenerState.FailedOpener) - if (DoPrePullSteps(ref actionID, mudraState)) return true; - - if (CurrentState == OpenerState.InOpener) - if (DoOpener(ref actionID, mudraState)) return true; - - if (CurrentState == OpenerState.OpenerFinished && !CustomComboFunctions.InCombat()) - ResetOpener(); - - return false; - } - - internal void Dispose() - { - Svc.Condition.ConditionChange -= CheckCombatStatus; - } - - private void CheckCombatStatus(ConditionFlag flag, bool value) - { - if (flag == ConditionFlag.InCombat && value == false) ResetOpener(); - } - } - } -} diff --git a/XIVSlothCombo/Combos/PvE/ADV.cs b/XIVSlothCombo/Combos/PvE/ADV.cs deleted file mode 100644 index e0fe12acd..000000000 --- a/XIVSlothCombo/Combos/PvE/ADV.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace XIVSlothCombo.Combos.PvE -{ - internal static class ADV - { - public const byte ClassID = 0; - public const byte JobID = 0; - - public const uint - LucidDreaming = 1204; - - public static class Buffs - { - public const ushort - Placeholder = 0; - } - - public static class Debuffs - { - public const ushort - Placeholder = 0; - } - - public static class Levels - { - public const byte - Placeholder = 0; - } - - } -} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/ADV/ADV.cs b/XIVSlothCombo/Combos/PvE/ADV/ADV.cs new file mode 100644 index 000000000..133dc27ac --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/ADV/ADV.cs @@ -0,0 +1,28 @@ +namespace XIVSlothCombo.Combos.PvE; + +internal partial class ADV +{ + public const byte ClassID = 0; + public const byte JobID = 0; + + public const uint + LucidDreaming = 1204; + + public static class Buffs + { + public const ushort + Placeholder = 0; + } + + public static class Debuffs + { + public const ushort + Placeholder = 0; + } + + public static class Levels + { + public const byte + Placeholder = 0; + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/ADV/ADV_Config.cs b/XIVSlothCombo/Combos/PvE/ADV/ADV_Config.cs new file mode 100644 index 000000000..776db70df --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/ADV/ADV_Config.cs @@ -0,0 +1,17 @@ +namespace XIVSlothCombo.Combos.PvE; + +internal partial class ADV +{ + internal static class Config + { + //Config goes here + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + //Presets + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/ALL.cs b/XIVSlothCombo/Combos/PvE/ALL.cs deleted file mode 100644 index fb4b9af4e..000000000 --- a/XIVSlothCombo/Combos/PvE/ALL.cs +++ /dev/null @@ -1,255 +0,0 @@ -using ECommons.DalamudServices; -using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; - -namespace XIVSlothCombo.Combos.PvE -{ - internal class All - { - public const byte JobID = 0; - - public const uint - Rampart = 7531, - SecondWind = 7541, - TrueNorth = 7546, - Addle = 7560, - Swiftcast = 7561, - LucidDreaming = 7562, - Resurrection = 173, - Raise = 125, - Provoke = 7533, - Shirk = 7537, - Reprisal = 7535, - ArmsLength = 7548, - Esuna = 7568, - Rescue = 7571, - SolidReason = 232, - AgelessWords = 215, - Sleep = 25880, - WiseToTheWorldMIN = 26521, - WiseToTheWorldBTN = 26522, - LowBlow = 7540, - Bloodbath = 7542, - HeadGraze = 7551, - FootGraze = 7553, - LegGraze = 7554, - Feint = 7549, - Interject = 7538, - Peloton = 7557, - LegSweep = 7863, - Repose = 16560, - Sprint = 3; - private const uint - IsleSprint = 31314; - - public static class Buffs - { - public const ushort - Weakness = 43, - WellFed = 48, - Medicated = 49, - Bloodbath = 84, - Swiftcast = 167, - Rampart = 1191, - Peloton = 1199, - LucidDreaming = 1204, - ArmsLength = 1209, - TrueNorth = 1250, - Sprint = 50; - } - - public static class Debuffs - { - public const ushort - Sleep = 3, - Bind = 13, - Heavy = 14, - Addle = 1203, - Reprisal = 1193, - Feint = 1195; - } - - /// - /// Quick Level, Offcooldown, spellweave, and MP check of Lucid Dreaming - /// - /// action id to check weave - /// Player MP less than Threshold check - /// Spell Weave check by default - /// - public static bool CanUseLucid(uint actionID, int MPThreshold, bool weave = true) => - CustomComboFunctions.ActionReady(LucidDreaming) - && CustomComboFunctions.LocalPlayer.CurrentMp <= MPThreshold - && (!weave || CustomComboFunctions.CanSpellWeave(actionID)); - - internal class ALL_IslandSanctuary_Sprint : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_IslandSanctuary_Sprint; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Sprint && Svc.ClientState.TerritoryType is 1055) return IsleSprint; - else return actionID; - } - } - - //Tank Features - internal class ALL_Tank_Interrupt : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Interrupt; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is LowBlow or PLD.ShieldBash) - { - if (CanInterruptEnemy() && ActionReady(Interject)) - return Interject; - if (ActionReady(LowBlow)) - return LowBlow; - if (actionID == PLD.ShieldBash && IsOnCooldown(LowBlow)) - return actionID; - } - - return actionID; - } - } - - internal class ALL_Tank_Reprisal : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Reprisal; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Reprisal) - { - if (TargetHasEffectAny(Debuffs.Reprisal) && IsOffCooldown(Reprisal)) - return OriginalHook(11); - } - - return actionID; - } - } - - //Healer Features - internal class ALL_Healer_Raise : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Healer_Raise; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if ((actionID is WHM.Raise or AST.Ascend or SGE.Egeiro) - || (actionID is SCH.Resurrection && LocalPlayer.ClassJob.Id is SCH.JobID)) - { - if (ActionReady(Swiftcast)) - return Swiftcast; - - if (actionID == WHM.Raise && IsEnabled(CustomComboPreset.WHM_ThinAirRaise) && ActionReady(WHM.ThinAir) && !HasEffect(WHM.Buffs.ThinAir)) - return WHM.ThinAir; - - return actionID; - } - - return actionID; - } - } - - //Caster Features - internal class ALL_Caster_Addle : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Addle; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Addle) - { - if (TargetHasEffectAny(Debuffs.Addle) && IsOffCooldown(Addle)) - return OriginalHook(11); - } - - return actionID; - } - } - - internal class ALL_Caster_Raise : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Raise; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if ((actionID is BLU.AngelWhisper or RDM.Verraise) - || (actionID is SMN.Resurrection && LocalPlayer.ClassJob.Id is SMN.JobID)) - { - if (HasEffect(Buffs.Swiftcast) || HasEffect(RDM.Buffs.Dualcast)) - return actionID; - if (IsOffCooldown(Swiftcast)) - return Swiftcast; - if (LocalPlayer.ClassJob.Id is RDM.JobID && - ActionReady(RDM.Vercure)) - return RDM.Vercure; - } - - return actionID; - } - } - - //Melee DPS Features - internal class ALL_Melee_Feint : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_Feint; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Feint) - { - if (TargetHasEffectAny(Debuffs.Feint) && IsOffCooldown(Feint)) - return OriginalHook(11); - } - - return actionID; - } - } - - internal class ALL_Melee_TrueNorth : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_TrueNorth; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is TrueNorth) - { - if (HasEffect(Buffs.TrueNorth)) - return OriginalHook(11); - } - - return actionID; - } - } - - //Ranged Physical Features - internal class ALL_Ranged_Mitigation : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Mitigation; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is BRD.Troubadour or MCH.Tactician or DNC.ShieldSamba) - { - if ((HasEffectAny(BRD.Buffs.Troubadour) || HasEffectAny(MCH.Buffs.Tactician) || HasEffectAny(DNC.Buffs.ShieldSamba)) && IsOffCooldown(actionID)) - return OriginalHook(11); - } - - return actionID; - } - } - - internal class ALL_Ranged_Interrupt : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Interrupt; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - return (actionID is FootGraze && CanInterruptEnemy() && ActionReady(HeadGraze)) ? HeadGraze : actionID; - } - } - } -} - diff --git a/XIVSlothCombo/Combos/PvE/ALL/ALL.cs b/XIVSlothCombo/Combos/PvE/ALL/ALL.cs new file mode 100644 index 000000000..4e04b5953 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/ALL/ALL.cs @@ -0,0 +1,253 @@ +using ECommons.DalamudServices; +using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.CustomComboNS.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class All +{ + public const byte JobID = 0; + + public const uint + Rampart = 7531, + SecondWind = 7541, + TrueNorth = 7546, + Addle = 7560, + Swiftcast = 7561, + LucidDreaming = 7562, + Resurrection = 173, + Raise = 125, + Provoke = 7533, + Shirk = 7537, + Reprisal = 7535, + Esuna = 7568, + Rescue = 7571, + SolidReason = 232, + AgelessWords = 215, + Sleep = 25880, + WiseToTheWorldMIN = 26521, + WiseToTheWorldBTN = 26522, + LowBlow = 7540, + Bloodbath = 7542, + HeadGraze = 7551, + FootGraze = 7553, + LegGraze = 7554, + Feint = 7549, + Interject = 7538, + Peloton = 7557, + LegSweep = 7863, + Repose = 16560, + Sprint = 3; + + private const uint + IsleSprint = 31314; + + /// + /// Quick Level, Offcooldown, spellweave, and MP check of Lucid Dreaming + /// + /// action id to check weave + /// Player MP less than Threshold check + /// Spell Weave check by default + /// + public static bool CanUseLucid(uint actionID, int MPThreshold, bool weave = true) + { + return CustomComboFunctions.ActionReady(LucidDreaming) + && CustomComboFunctions.LocalPlayer.CurrentMp <= MPThreshold + && (!weave || CustomComboFunctions.CanSpellWeave(actionID)); + } + + public static class Buffs + { + public const ushort + Weakness = 43, + Medicated = 49, + Bloodbath = 84, + Swiftcast = 167, + Rampart = 1191, + Peloton = 1199, + LucidDreaming = 1204, + TrueNorth = 1250, + Sprint = 50; + } + + public static class Debuffs + { + public const ushort + Sleep = 3, + Bind = 13, + Heavy = 14, + Addle = 1203, + Reprisal = 1193, + Feint = 1195; + } + + internal class ALL_IslandSanctuary_Sprint : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_IslandSanctuary_Sprint; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Sprint && Svc.ClientState.TerritoryType is 1055 + ? IsleSprint + : actionID; + } + } + + //Tank Features + internal class ALL_Tank_Interrupt : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Interrupt; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + switch (actionID) + { + case LowBlow or PLD.ShieldBash when CanInterruptEnemy() && ActionReady(Interject): + return Interject; + + case LowBlow or PLD.ShieldBash when ActionReady(LowBlow): + return LowBlow; + + case LowBlow or PLD.ShieldBash when actionID == PLD.ShieldBash && IsOnCooldown(LowBlow): + return actionID; + + default: + return actionID; + } + } + } + + internal class ALL_Tank_Reprisal : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Reprisal; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Reprisal && TargetHasEffectAny(Debuffs.Reprisal) && IsOffCooldown(Reprisal) + ? OriginalHook(11) + : actionID; + } + } + + //Healer Features + internal class ALL_Healer_Raise : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Healer_Raise; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + switch (actionID) + { + case WHM.Raise or AST.Ascend or SGE.Egeiro: + case SCH.Resurrection when LocalPlayer.ClassJob.Id is SCH.JobID: + { + if (ActionReady(Swiftcast)) + return Swiftcast; + + if (actionID == WHM.Raise && IsEnabled(CustomComboPreset.WHM_ThinAirRaise) && + ActionReady(WHM.ThinAir) && !HasEffect(WHM.Buffs.ThinAir)) + return WHM.ThinAir; + + return actionID; + } + + default: + return actionID; + } + } + } + + //Caster Features + internal class ALL_Caster_Addle : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Addle; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Addle && TargetHasEffectAny(Debuffs.Addle) && IsOffCooldown(Addle) + ? OriginalHook(11) + : actionID; + } + } + + internal class ALL_Caster_Raise : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Raise; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + switch (actionID) + { + case BLU.AngelWhisper or RDM.Verraise: + case SMN.Resurrection when LocalPlayer.ClassJob.Id is SMN.JobID: + { + if (HasEffect(Buffs.Swiftcast) || HasEffect(RDM.Buffs.Dualcast)) + return actionID; + + if (IsOffCooldown(Swiftcast)) + return Swiftcast; + + if (LocalPlayer.ClassJob.Id is RDM.JobID && + ActionReady(RDM.Vercure)) + return RDM.Vercure; + + break; + } + } + + return actionID; + } + } + + //Melee DPS Features + internal class ALL_Melee_Feint : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_Feint; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Feint && TargetHasEffectAny(Debuffs.Feint) && IsOffCooldown(Feint) + ? OriginalHook(11) + : actionID; + } + } + + internal class ALL_Melee_TrueNorth : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_TrueNorth; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is TrueNorth && HasEffect(Buffs.TrueNorth) + ? OriginalHook(11) + : actionID; + } + } + + //Ranged Physical Features + internal class ALL_Ranged_Mitigation : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Mitigation; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is BRD.Troubadour or MCH.Tactician or DNC.ShieldSamba && + (HasEffectAny(BRD.Buffs.Troubadour) || HasEffectAny(MCH.Buffs.Tactician) || + HasEffectAny(DNC.Buffs.ShieldSamba)) && IsOffCooldown(actionID) + ? OriginalHook(11) + : actionID; + } + } + + internal class ALL_Ranged_Interrupt : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Interrupt; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is FootGraze && CanInterruptEnemy() && ActionReady(HeadGraze) + ? HeadGraze + : actionID; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/ALL/ALL_Config.cs b/XIVSlothCombo/Combos/PvE/ALL/ALL_Config.cs new file mode 100644 index 000000000..fc2b1606d --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/ALL/ALL_Config.cs @@ -0,0 +1,17 @@ +namespace XIVSlothCombo.Combos.PvE; + +internal partial class ALL +{ + internal static class Config + { + //Config goes here + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + //Presets + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM.cs deleted file mode 100644 index b7446191d..000000000 --- a/XIVSlothCombo/Combos/PvE/BLM.cs +++ /dev/null @@ -1,513 +0,0 @@ -using Dalamud.Game.ClientState.JobGauge.Types; -using System; -using System.Collections.Generic; -using XIVSlothCombo.Combos.JobHelpers; -using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Data; -using XIVSlothCombo.Extensions; - -namespace XIVSlothCombo.Combos.PvE -{ - internal class BLM - { - public const byte ClassID = 7; - public const byte JobID = 25; - - public const uint - Fire = 141, - Blizzard = 142, - Thunder = 144, - Fire2 = 147, - Transpose = 149, - Fire3 = 152, - Thunder3 = 153, - Blizzard3 = 154, - AetherialManipulation = 155, - Scathe = 156, - Manafont = 158, - Freeze = 159, - Flare = 162, - LeyLines = 3573, - Sharpcast = 3574, - Blizzard4 = 3576, - Fire4 = 3577, - BetweenTheLines = 7419, - Thunder4 = 7420, - Triplecast = 7421, - Foul = 7422, - Thunder2 = 7447, - Despair = 16505, - UmbralSoul = 16506, - Xenoglossy = 16507, - Blizzard2 = 25793, - HighFire2 = 25794, - HighBlizzard2 = 25795, - Amplifier = 25796, - Paradox = 25797, - HighThunder = 36986, - HighThunder2 = 36987, - FlareStar = 36989; - - public static class Buffs - { - public const ushort - Thundercloud = 164, - Firestarter = 165, - LeyLines = 737, - CircleOfPower = 738, - Sharpcast = 867, - Triplecast = 1211, - Thunderhead = 3870; - } - - public static class Debuffs - { - public const ushort - Thunder = 161, - Thunder2 = 162, - Thunder3 = 163, - Thunder4 = 1210, - HighThunder = 3871, - HighThunder2 = 3872; - } - - public static class Traits - { - public const uint - UmbralHeart = 295, - EnhancedPolyglot = 297, - AspectMasteryIII = 459, - EnhancedFoul = 461, - EnhancedManafont = 463, - Enochian = 460, - EnhancedPolyglotII = 615; - } - - public static class MP - { - public const int MaxMP = 10000; - - public const int AllMPSpells = 800; //"ALL MP" spell. Only caring about the absolute minimum. - public static int FireI => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(Fire)); - public static int FlareAoE => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(Flare)); - public static int FireAoE => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(Fire2)); - public static int FireIII => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(Fire3)); - public static int BlizzardAoE => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(Blizzard2)); - public static int BlizzardI => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(Blizzard)); - public static int Freeze => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(BLM.Freeze)); - public static int Despair => CustomComboFunctions.GetResourceCost(CustomComboFunctions.OriginalHook(BLM.Despair)); - } - - // Debuff Pairs of Actions and Debuff - public static readonly Dictionary - ThunderList = new() - { - { Thunder, Debuffs.Thunder }, - { Thunder2, Debuffs.Thunder2 }, - { Thunder3, Debuffs.Thunder3 }, - { Thunder4, Debuffs.Thunder4 }, - { HighThunder, Debuffs.HighThunder }, - { HighThunder2, Debuffs.HighThunder2 } - }; - - public static class Config - { - public static UserBool - BLM_Adv_Xeno_Burst = new("BLM_Adv_Xeno_Burst"); - - public static UserBoolArray - BLM_Adv_Cooldowns_Choice = new("BLM_Adv_Cooldowns_Choice"), - BLM_AoE_Adv_Cooldowns_Choice = new("BLM_AoE_Adv_Cooldowns_Choice"), - BLM_Adv_Movement_Choice = new("BLM_Adv_Movement_Choice"); - - public static UserInt - BLM_VariantCure = new("BLM_VariantCure"), - BLM_Adv_Cooldowns = new("BLM_Adv_Cooldowns"), - BLM_Adv_Thunder = new("BLM_Adv_Thunder"), - BLM_Adv_Rotation_Options = new("BLM_Adv_Rotation_Options"), - BLM_Advanced_OpenerSelection = new("BLM_Advanced_OpenerSelection"), - BLM_ST_Adv_ThunderHP = new("BLM_ST_Adv_ThunderHP"), - BLM_AoE_Adv_ThunderHP = new("BLM_AoE_Adv_ThunderHP"), - BLM_AoE_Adv_ThunderUptime = new("BLM_AoE_Adv_ThunderUptime"), - BLM_Adv_ThunderCloud = new("BLM_Adv_ThunderCloud"), - BLM_Adv_InitialCast = new("BLM_Adv_InitialCast"); - - public static UserFloat - BLM_AstralFire_Refresh = new("BLM_AstralFire_Refresh"); - } - - internal class BLM_ST_SimpleMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_ST_SimpleMode; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID != Fire) return actionID; - - var gauge = GetJobGauge(); - var maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - var maxPolyglotCD = maxPolyglot * 30000; - var remainingPolyglotCD = Math.Max(0, (maxPolyglot - gauge.PolyglotStacks) * 30000 + (gauge.EnochianTimer - 30000)); - var curMp = LocalPlayer.CurrentMp; - int nextMpGain = gauge.UmbralIceStacks switch - { - 0 => 0, - 1 => 2500, - 2 => 5000, - 3 => 10000, - _ => 0 - }; - var thunderDebuff = FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); - var elementTimer = gauge.ElementTimeRemaining / 1000f; - var gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(Fire)); - var canSwiftB3 = IsOffCooldown(All.Swiftcast) || ActionReady(Triplecast) || GetBuffStacks(Buffs.Triplecast) > 0; - - if (IsEnabled(CustomComboPreset.BLM_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.BLM_VariantCure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.BLM_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - CanSpellWeave(actionID)) - return Variant.VariantRampart; - - if (HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1) - { - if (thunderDebuff is null || thunderDebuff.RemainingTime < 3) - return OriginalHook(Thunder); - } - - if (ActionReady(Amplifier) && remainingPolyglotCD >= 20000 && CanSpellWeave(ActionWatching.LastSpell)) - return Amplifier; - - if (remainingPolyglotCD < 6000 && gcdsInTimer > 2 && gauge.HasPolyglotStacks()) - return Xenoglossy.LevelChecked() ? Xenoglossy : Foul; - - if (IsMoving) - { - if (ActionReady(Amplifier) && gauge.PolyglotStacks < maxPolyglot) - return Amplifier; - - if (gauge.HasPolyglotStacks()) - return Xenoglossy.LevelChecked() ? Xenoglossy : Foul; - } - - if (CanSpellWeave(actionID) && ActionReady(LeyLines)) - return LeyLines; - - if (gauge.InAstralFire) - { - if (gauge.IsParadoxActive && gcdsInTimer < 2 && curMp >= MP.FireI) - return Paradox; - - if (HasEffect(Buffs.Firestarter)) - { - if (gcdsInTimer < 2 || curMp < MP.FireI || WasLastAbility(Transpose)) - return Fire3; - } - - if (curMp < MP.FireI && Despair.LevelChecked() && curMp >= MP.Despair) - { - if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0) - return Triplecast; - - return Despair; - } - - if (curMp == 0 && FlareStar.LevelChecked() && gauge.AstralSoulStacks == 6) - return FlareStar; - - if (Fire4.LevelChecked()) - { - if (gcdsInTimer > 1 && curMp >= MP.FireI) - return Fire4; - } - - if (curMp >= MP.FireI) - return Fire; - - if (ActionReady(Manafont)) - return Manafont; - - if (ActionReady(Blizzard3) && !canSwiftB3) - return Blizzard3; - - if (ActionReady(Transpose)) - return Transpose; - - } - if (gauge.InUmbralIce) - { - if (ActionReady(Blizzard3) && gauge.UmbralIceStacks < 3) - { - if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0) - return Triplecast; - - if (GetBuffStacks(Buffs.Triplecast) == 0 && IsOffCooldown(All.Swiftcast)) - return All.Swiftcast; - - if (HasEffect(All.Buffs.Swiftcast) || GetBuffStacks(Buffs.Triplecast) > 0) - return Blizzard3; - } - - if (Blizzard4.LevelChecked() && gauge.UmbralHearts < 3 && TraitLevelChecked(Traits.UmbralHeart)) - return Blizzard4; - - if (gauge.IsParadoxActive) - return Paradox; - - if (gauge.HasPolyglotStacks()) - return Xenoglossy.LevelChecked() ? Xenoglossy : Foul; - - if (curMp + nextMpGain >= 7500 && (LocalPlayer.CastActionId == Blizzard || WasLastSpell(Blizzard) || WasLastSpell(Blizzard4))) - { - if (Fire3.LevelChecked()) - return Fire3; - - return Fire; - } - - if ((curMp + nextMpGain <= 10000 || curMp < 7500)) - return Blizzard; - - if (ActionReady(Transpose) && CanSpellWeave(ActionWatching.LastSpell) && !Fire3.LevelChecked()) - return Transpose; - - if (Fire3.LevelChecked()) - return Fire3; - } - - if (Blizzard3.LevelChecked()) - return Blizzard3; - return actionID; - } - } - - internal class BLM_AoE_SimpleMode : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_AoE_SimpleMode; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is not (Blizzard2 or HighBlizzard2)) return actionID; - - var gauge = GetJobGauge(); - var maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - var maxPolyglotCD = maxPolyglot * 30000; - var remainingPolyglotCD = Math.Max(0, (maxPolyglot - gauge.PolyglotStacks) * 30000 + (gauge.EnochianTimer - 30000)); - var curMp = LocalPlayer.CurrentMp; - int nextMpGain = gauge.UmbralIceStacks switch - { - 0 => 0, - 1 => 2500, - 2 => 5000, - 3 => 10000, - _ => 0 - }; - var thunderDebuff = FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); - var elementTimer = gauge.ElementTimeRemaining / 1000f; - var gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); - var canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && (IsOffCooldown(All.Swiftcast) || ActionReady(Triplecast) || GetBuffStacks(Buffs.Triplecast) > 0); - var canWeave = CanSpellWeave(ActionWatching.LastSpell); - - if (IsEnabled(CustomComboPreset.BLM_Variant_Cure) && - IsEnabled(Variant.VariantCure) && - PlayerHealthPercentageHp() <= Config.BLM_VariantCure) - return Variant.VariantCure; - - if (IsEnabled(CustomComboPreset.BLM_Variant_Rampart) && - IsEnabled(Variant.VariantRampart) && - IsOffCooldown(Variant.VariantRampart) && - canWeave) - return Variant.VariantRampart; - - if (HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && Thunder2.LevelChecked()) - { - if (thunderDebuff is null || thunderDebuff.RemainingTime < 3) - return OriginalHook(Thunder2); - } - - if (ActionReady(Amplifier) && remainingPolyglotCD >= 20000 && canWeave) - return Amplifier; - - if (IsMoving) - { - if (ActionReady(Amplifier) && gauge.PolyglotStacks < maxPolyglot) - return Amplifier; - - if (gauge.HasPolyglotStacks()) - return Foul; - } - - if (canWeave && ActionReady(LeyLines)) - return LeyLines; - - if (gauge.InAstralFire) - { - if (curMp == 0 && FlareStar.LevelChecked() && gauge.AstralSoulStacks == 6) - return FlareStar; - - if (!FlareStar.LevelChecked() && Fire2.LevelChecked() && curMp >= MP.FireAoE && (gauge.UmbralHearts > 1 || !TraitLevelChecked(Traits.UmbralHeart))) - return OriginalHook(Fire2); - - if (Flare.LevelChecked() && curMp >= MP.FlareAoE) - { - if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0 && canWeave) - return Triplecast; - - return Flare; - } - - if (Fire2.LevelChecked()) - { - if (gcdsInTimer > 1 && curMp >= MP.FireAoE) - return OriginalHook(Fire2); - } - - if (ActionReady(Manafont)) - return Manafont; - - if (ActionReady(Transpose) && (!TraitLevelChecked(Traits.AspectMasteryIII) || canSwiftF)) - return Transpose; - - if (ActionReady(Blizzard2) && TraitLevelChecked(Traits.AspectMasteryIII)) - return OriginalHook(Blizzard2); - - } - if (gauge.InUmbralIce) - { - if (ActionWatching.WhichOfTheseActionsWasLast(OriginalHook(Fire2), OriginalHook(Freeze), OriginalHook(Flare), OriginalHook(FlareStar)) == OriginalHook(Freeze) && FlareStar.LevelChecked()) - { - if (ActionReady(Transpose) && canWeave) - return Transpose; - - return OriginalHook(Fire2); - } - - if (ActionReady(OriginalHook(Blizzard2)) && gauge.UmbralIceStacks < 3 && TraitLevelChecked(Traits.AspectMasteryIII)) - { - if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0 && canWeave) - return Triplecast; - - if (GetBuffStacks(Buffs.Triplecast) == 0 && IsOffCooldown(All.Swiftcast) && canWeave) - return All.Swiftcast; - - if (HasEffect(All.Buffs.Swiftcast) || GetBuffStacks(Buffs.Triplecast) > 0) - return OriginalHook(Blizzard2); - } - - if (gauge.UmbralIceStacks < 3 && ActionReady(OriginalHook(Blizzard2))) - return OriginalHook(Blizzard2); - - if (Freeze.LevelChecked() && gauge.UmbralHearts < 3 && TraitLevelChecked(Traits.UmbralHeart)) - return Freeze; - - if (gauge.HasPolyglotStacks()) - return Foul; - - if (BLMHelper.DoubleBlizz()) - { - if (Fire2.LevelChecked()) - return OriginalHook(Fire2); - } - - if (curMp < LocalPlayer.MaxMp) - return Freeze.LevelChecked() ? OriginalHook(Freeze) : OriginalHook(Blizzard2); - - if (ActionReady(Transpose) && ((canWeave && Flare.LevelChecked()) || !TraitLevelChecked(Traits.AspectMasteryIII))) - return Transpose; - - if (Fire2.LevelChecked() && TraitLevelChecked(Traits.AspectMasteryIII)) - return OriginalHook(Fire2); - } - - if (Blizzard2.LevelChecked()) - return OriginalHook(Blizzard2); - return actionID; - } - } - - internal class BLM_Variant_Raise : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Variant_Raise; - - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) => - (actionID is All.Swiftcast && HasEffect(All.Buffs.Swiftcast) && IsEnabled(Variant.VariantRaise)) - ? Variant.VariantRaise - : actionID; - } - - internal class BLM_Scathe_Xeno : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Scathe_Xeno; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) => - (actionID is Scathe && LevelChecked(Xenoglossy) && GetJobGauge().HasPolyglotStacks()) - ? Xenoglossy - : actionID; - } - - internal class BLM_Blizzard_1to3 : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Blizzard_1to3; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Blizzard && LevelChecked(Freeze) && !GetJobGauge().InUmbralIce) - return Blizzard3; - - if (actionID is Freeze && !LevelChecked(Freeze)) - return Blizzard2; - - return actionID; - } - } - - internal class BLM_Fire_1to3 : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Fire_1to3; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) => - (actionID is Fire && ((LevelChecked(Fire3) && !GetJobGauge().InAstralFire) || HasEffect(Buffs.Firestarter))) - ? Fire3 - : actionID; - } - - internal class BLM_Between_The_LeyLines : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Between_The_LeyLines; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) => - actionID is LeyLines && HasEffect(Buffs.LeyLines) && LevelChecked(BetweenTheLines) - ? BetweenTheLines - : actionID; - } - - internal class BLM_Aetherial_Manipulation : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Aetherial_Manipulation; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) => - actionID is AetherialManipulation && - ActionReady(BetweenTheLines) && - HasEffect(Buffs.LeyLines) && - !HasEffect(Buffs.CircleOfPower) && - !IsMoving - ? BetweenTheLines - : actionID; - } - - internal class BLM_UmbralSoul : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_UmbralSoul; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) => - actionID is Transpose && GetJobGauge().InUmbralIce && LevelChecked(UmbralSoul) - ? UmbralSoul - : actionID; - } - } -} diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs new file mode 100644 index 000000000..6c1909412 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs @@ -0,0 +1,897 @@ +using System.Collections.Generic; +using XIVSlothCombo.Combos.PvE.Content; +using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.Data; +using XIVSlothCombo.Extensions; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class BLM +{ + public const byte ClassID = 7; + public const byte JobID = 25; + + public const uint + Fire = 141, + Blizzard = 142, + Thunder = 144, + Fire2 = 147, + Transpose = 149, + Fire3 = 152, + Thunder3 = 153, + Blizzard3 = 154, + AetherialManipulation = 155, + Scathe = 156, + Manafont = 158, + Freeze = 159, + Flare = 162, + LeyLines = 3573, + Blizzard4 = 3576, + Fire4 = 3577, + BetweenTheLines = 7419, + Thunder4 = 7420, + Triplecast = 7421, + Foul = 7422, + Thunder2 = 7447, + Despair = 16505, + UmbralSoul = 16506, + Xenoglossy = 16507, + Blizzard2 = 25793, + HighFire2 = 25794, + HighBlizzard2 = 25795, + Amplifier = 25796, + Paradox = 25797, + HighThunder = 36986, + HighThunder2 = 36987, + FlareStar = 36989; + + internal static BLMOpenerLogic BLMOpener = new(); + + // Debuff Pairs of Actions and Debuff + public static readonly Dictionary + ThunderList = new() + { + { Thunder, Debuffs.Thunder }, + { Thunder2, Debuffs.Thunder2 }, + { Thunder3, Debuffs.Thunder3 }, + { Thunder4, Debuffs.Thunder4 }, + { HighThunder, Debuffs.HighThunder }, + { HighThunder2, Debuffs.HighThunder2 } + }; + + private static int nextMpGain => Gauge.UmbralIceStacks switch + { + 0 => 0, + 1 => 2500, + 2 => 5000, + 3 => 10000, + var _ => 0 + }; + + public static class Buffs + { + public const ushort + Thundercloud = 164, + Firestarter = 165, + LeyLines = 737, + CircleOfPower = 738, + Sharpcast = 867, + Triplecast = 1211, + Thunderhead = 3870; + } + + public static class Debuffs + { + public const ushort + Thunder = 161, + Thunder2 = 162, + Thunder3 = 163, + Thunder4 = 1210, + HighThunder = 3871, + HighThunder2 = 3872; + } + + public static class Traits + { + public const uint + UmbralHeart = 295, + EnhancedPolyglot = 297, + AspectMasteryIII = 459, + EnhancedFoul = 461, + EnhancedManafont = 463, + Enochian = 460, + EnhancedPolyglotII = 615; + } + + public static class MP + { + public const int MaxMP = 10000; + + public const int AllMPSpells = 800; //"ALL MP" spell. Only caring about the absolute minimum. + + public static int FireI => GetResourceCost(OriginalHook(Fire)); + + public static int FlareAoE => GetResourceCost(OriginalHook(Flare)); + + public static int FireAoE => GetResourceCost(OriginalHook(Fire2)); + + public static int FireIII => GetResourceCost(OriginalHook(Fire3)); + + public static int BlizzardAoE => GetResourceCost(OriginalHook(Blizzard2)); + + public static int BlizzardI => GetResourceCost(OriginalHook(Blizzard)); + + public static int Freeze => GetResourceCost(OriginalHook(BLM.Freeze)); + + public static int Despair => GetResourceCost(OriginalHook(BLM.Despair)); + } + + internal class BLM_ST_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_ST_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is not Fire) + return actionID; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.BLM_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && canWeave) + return Variant.VariantRampart; + + if (BLMOpener.DoFullOpener(ref actionID)) + return actionID; + + //Weaves + if (canWeave) + { + if (ActionReady(Amplifier) && + remainingPolyglotCD >= 20000) + return Amplifier; + + if (IsEnabled(CustomComboPreset.BLM_ST_LeyLines) && + ActionReady(LeyLines)) + return LeyLines; + } + + if (HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (IsMoving) + { + if (ActionReady(Amplifier) && Gauge.PolyglotStacks < maxPolyglot) + return Amplifier; + + if (BLMHelper.HasPolyglotStacks(Gauge)) + return LevelChecked(Xenoglossy) + ? Xenoglossy + : Foul; + } + + if (Gauge.InAstralFire) + { + if (Gauge.IsParadoxActive && gcdsInTimer < 2 && curMp >= MP.FireI) + return Paradox; + + if ((HasEffect(Buffs.Firestarter) && gcdsInTimer < 2 && + curMp >= MP.FireI) || (HasEffect(Buffs.Firestarter) && Gauge.AstralFireStacks < 3)) + return Fire3; + + if (curMp < MP.FireI && LevelChecked(Despair) && curMp >= MP.Despair) + { + if (canWeave && ActionReady(All.Swiftcast)) + return All.Swiftcast; + + if (canWeave && ActionReady(Triplecast) && + GetBuffStacks(Buffs.Triplecast) == 0 && + GetRemainingCharges(Triplecast) == GetMaxCharges(Triplecast)) + return Triplecast; + + if (HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (BLMHelper.HasPolyglotStacks(Gauge) && gcdsInTimer >= 1 && + (ActionReady(All.Swiftcast) || + (ActionReady(Triplecast) && + GetBuffStacks(Buffs.Triplecast) == 0 && + GetRemainingCharges(Triplecast) == GetMaxCharges(Triplecast)))) + return Xenoglossy.LevelChecked() + ? Xenoglossy + : Foul; + + return Despair; + } + + if (curMp == 0 && LevelChecked(FlareStar) && Gauge.AstralSoulStacks == 6) + return FlareStar; + + if (LevelChecked(Fire4)) + if (gcdsInTimer > 1 && curMp >= MP.FireI) + return Fire4; + + if (curMp >= MP.FireI) + return Fire; + + if (IsEnabled(CustomComboPreset.BLM_ST_Manafont) && + ActionReady(Manafont)) + return HasEffect(Buffs.Firestarter) + ? Fire3 + : Manafont; + + if (ActionReady(Blizzard3) && + (ActionReady(All.Swiftcast) || + HasEffect(Buffs.Triplecast))) + { + if (canWeave && + ActionReady(Transpose)) + return Transpose; + + if (HasEffect(Buffs.Thunderhead) && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (BLMHelper.HasPolyglotStacks(Gauge)) + return LevelChecked(Xenoglossy) + ? Xenoglossy + : Foul; + } + + if (ActionReady(Blizzard3)) + return Blizzard3; + } + + if (Gauge.InUmbralIce) + { + if (ActionReady(Blizzard3) && Gauge.UmbralIceStacks < 3 && TraitLevelChecked(Traits.UmbralHeart)) + { + if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0) + return Triplecast; + + if (GetBuffStacks(Buffs.Triplecast) == 0 && IsOffCooldown(All.Swiftcast)) + return All.Swiftcast; + + if (HasEffect(All.Buffs.Swiftcast) || GetBuffStacks(Buffs.Triplecast) > 0) + return Blizzard3; + } + + if (LevelChecked(Blizzard4) && + Gauge.UmbralHearts < 3 && TraitLevelChecked(Traits.UmbralHeart)) + return Blizzard4; + + if (Gauge.IsParadoxActive) + return Paradox; + + if (BLMHelper.HasPolyglotStacks(Gauge)) + return LevelChecked(Xenoglossy) + ? Xenoglossy + : Foul; + + if (curMp + nextMpGain >= 7500 && + (LocalPlayer.CastActionId == Blizzard || + WasLastSpell(Blizzard) || + WasLastSpell(Blizzard4))) + return LevelChecked(Fire3) + ? Fire3 + : Fire; + + if (curMp + nextMpGain <= 10000 || curMp < 7500) + return Blizzard; + + if (ActionReady(Transpose) && canWeave && + curMp is MP.MaxMP && HasEffect(Buffs.Firestarter)) + return Transpose; + + if (LevelChecked(Fire3)) + return Fire3; + } + + if (LevelChecked(Blizzard3)) + return Blizzard3; + + return actionID; + } + } + + internal class BLM_ST_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_ST_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int PolyglotStacks = Gauge.PolyglotStacks; + float TriplecastChargetime = GetCooldownChargeRemainingTime(Triplecast); + + if (actionID is not Fire) + return actionID; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.BLM_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + canWeave) + return Variant.VariantRampart; + + if (IsEnabled(CustomComboPreset.BLM_ST_Opener)) + if (BLMOpener.DoFullOpener(ref actionID)) + return actionID; + + //Weaves + if (canWeave) + { + if (IsEnabled(CustomComboPreset.BLM_ST_Amplifier) && + ActionReady(Amplifier) && remainingPolyglotCD >= 20000) + return Amplifier; + + if (IsEnabled(CustomComboPreset.BLM_ST_LeyLines) && + ActionReady(LeyLines)) + return LeyLines; + } + + if (IsEnabled(CustomComboPreset.BLM_ST_Thunder) && + HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && LevelChecked(Thunder) && + GetTargetHPPercent() >= Config.BLM_ST_ThunderHP && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (IsMoving) + { + if (IsEnabled(CustomComboPreset.BLM_ST_Amplifier) && + ActionReady(Amplifier) && Gauge.PolyglotStacks < maxPolyglot) + return Amplifier; + + if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglotMoving) && + PolyglotStacks > Config.BLM_ST_UsePolyglotMoving_HoldCharges) + return LevelChecked(Xenoglossy) + ? Xenoglossy + : Foul; + } + + if (Gauge.InAstralFire) + { + if (Gauge.IsParadoxActive && gcdsInTimer < 2 && curMp >= MP.FireI) + return Paradox; + + if ((HasEffect(Buffs.Firestarter) && gcdsInTimer < 2 && + curMp >= MP.FireI) || (HasEffect(Buffs.Firestarter) && Gauge.AstralFireStacks < 3)) + return Fire3; + + if (IsEnabled(CustomComboPreset.BLM_ST_Despair) && + curMp < MP.FireI && LevelChecked(Despair) && curMp >= MP.Despair) + { + if (IsEnabled(CustomComboPreset.BLM_ST_Triplecast) && + canWeave && ActionReady(Triplecast) && + GetBuffStacks(Buffs.Triplecast) == 0 && + (GetRemainingCharges(Triplecast) > Config.BLM_ST_Triplecast_HoldCharges || + TriplecastChargetime <= Config.BLM_ST_Triplecast_ChargeTime)) + return Triplecast; + + if (IsEnabled(CustomComboPreset.BLM_ST_Swiftcast) && + canWeave && ActionReady(All.Swiftcast) && + GetBuffStacks(Buffs.Triplecast) == 0) + return All.Swiftcast; + + if (IsEnabled(CustomComboPreset.BLM_ST_Thunder) && + HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglot) && + (IsEnabled(CustomComboPreset.BLM_ST_Swiftcast) || + IsEnabled(CustomComboPreset.BLM_ST_Triplecast)) && + PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges && gcdsInTimer >= 1 && + (ActionReady(All.Swiftcast) || + (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0))) + return Xenoglossy.LevelChecked() + ? Xenoglossy + : Foul; + + return Despair; + } + + if (IsEnabled(CustomComboPreset.BLM_ST_Flarestar) && + curMp == 0 && LevelChecked(FlareStar) && Gauge.AstralSoulStacks == 6) + return FlareStar; + + if (LevelChecked(Fire4)) + if (gcdsInTimer > 1 && curMp >= MP.FireI) + return Fire4; + + if (curMp >= MP.FireI) + return Fire; + + if (IsEnabled(CustomComboPreset.BLM_ST_Manafont) && + ActionReady(Manafont)) + return HasEffect(Buffs.Firestarter) + ? Fire3 + : Manafont; + + if (ActionReady(Blizzard3) && + ((IsEnabled(CustomComboPreset.BLM_ST_Swiftcast) && ActionReady(All.Swiftcast)) || + HasEffect(Buffs.Triplecast))) + { + if (IsEnabled(CustomComboPreset.BLM_ST_Transpose) && + canWeave && ActionReady(Transpose)) + return Transpose; + + if (IsEnabled(CustomComboPreset.BLM_ST_Thunder) && + HasEffect(Buffs.Thunderhead) && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglot) && + PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges) + return LevelChecked(Xenoglossy) + ? Xenoglossy + : Foul; + } + + if (ActionReady(Blizzard3)) + return Blizzard3; + } + + if (Gauge.InUmbralIce) + { + if (ActionReady(Blizzard3) && Gauge.UmbralIceStacks < 3 && TraitLevelChecked(Traits.UmbralHeart)) + { + if (HasEffect(All.Buffs.Swiftcast) || HasEffect(Buffs.Triplecast)) + return Blizzard3; + + if (IsEnabled(CustomComboPreset.BLM_ST_Swiftcast) && + GetBuffStacks(Buffs.Triplecast) == 0 && IsOffCooldown(All.Swiftcast)) + return All.Swiftcast; + + if (IsEnabled(CustomComboPreset.BLM_ST_Triplecast) && + LevelChecked(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0 && + (GetRemainingCharges(Triplecast) > Config.BLM_ST_Triplecast_HoldCharges || + TriplecastChargetime <= Config.BLM_ST_Triplecast_ChargeTime)) + return Triplecast; + } + + if (LevelChecked(Blizzard4) && Gauge.UmbralHearts < 3 && TraitLevelChecked(Traits.UmbralHeart)) + return Blizzard4; + + if (Gauge.IsParadoxActive) + return Paradox; + + if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglot) && + PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges) + return LevelChecked(Xenoglossy) + ? Xenoglossy + : Foul; + + if (curMp + nextMpGain >= 7500 && + (LocalPlayer.CastActionId == Blizzard || + WasLastSpell(Blizzard) || + WasLastSpell(Blizzard4))) + return LevelChecked(Fire3) + ? Fire3 + : Fire; + + if (curMp + nextMpGain <= 10000 || curMp < 7500) + return Blizzard; + + if (IsEnabled(CustomComboPreset.BLM_ST_Transpose) && + ActionReady(Transpose) && canWeave && + curMp is MP.MaxMP && HasEffect(Buffs.Firestarter)) + return Transpose; + + if (LevelChecked(Fire3)) + return Fire3; + } + + if (LevelChecked(Blizzard3)) + return Blizzard3; + + return actionID; + } + } + + internal class BLM_AoE_SimpleMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_AoE_SimpleMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is not (Blizzard2 or HighBlizzard2)) + return actionID; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.BLM_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanSpellWeave(ActionWatching.LastSpell)) + return Variant.VariantRampart; + + if (WasLastSpell(UmbralSoul)) + return OriginalHook(Fire2); + + if ((HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && Thunder2.LevelChecked() && + thunderDebuffAoE is null) || thunderDebuffAoE.RemainingTime < 3) + return OriginalHook(Thunder2); + + if (ActionReady(Amplifier) && remainingPolyglotCD >= 20000 && CanSpellWeave(ActionWatching.LastSpell)) + return Amplifier; + + if (IsMoving) + { + if (ActionReady(Amplifier) && Gauge.PolyglotStacks < maxPolyglot) + return Amplifier; + + if (BLMHelper.HasPolyglotStacks(Gauge)) + return Foul; + } + + if (CanSpellWeave(ActionWatching.LastSpell) && ActionReady(LeyLines)) + return LeyLines; + + if (Gauge.InAstralFire) + { + if (curMp == 0 && FlareStar.LevelChecked() && Gauge.AstralSoulStacks == 6) + return FlareStar; + + if (!FlareStar.LevelChecked() && Fire2.LevelChecked() && curMp >= MP.FireAoE && + (Gauge.UmbralHearts > 1 || !TraitLevelChecked(Traits.UmbralHeart))) + return OriginalHook(Fire2); + + if (Flare.LevelChecked() && curMp >= MP.FlareAoE) + { + if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0 && + CanSpellWeave(ActionWatching.LastSpell)) + return Triplecast; + + return Flare; + } + + if (Fire2.LevelChecked()) + if (gcdsInTimer > 1 && curMp >= MP.FireAoE) + return OriginalHook(Fire2); + + if (ActionReady(Manafont)) + return Manafont; + + if (ActionReady(Transpose) && (!TraitLevelChecked(Traits.AspectMasteryIII) || canSwiftF)) + return Transpose; + + if (ActionReady(Blizzard2) && TraitLevelChecked(Traits.AspectMasteryIII)) + return OriginalHook(Blizzard2); + } + + if (Gauge.InUmbralIce) + { + if (BLMHelper.HasPolyglotStacks(Gauge)) + return Foul; + + if (ActionWatching.WhichOfTheseActionsWasLast(OriginalHook(Fire2), OriginalHook(Freeze), + OriginalHook(Flare), OriginalHook(FlareStar)) == OriginalHook(Freeze) && + FlareStar.LevelChecked()) + { + if (ActionReady(Transpose) && CanSpellWeave(ActionWatching.LastSpell)) + return Transpose; + + return OriginalHook(Fire2); + } + + if (ActionReady(OriginalHook(Blizzard2)) && Gauge.UmbralIceStacks < 3 && + TraitLevelChecked(Traits.AspectMasteryIII)) + { + if (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0 && + CanSpellWeave(ActionWatching.LastSpell)) + return Triplecast; + + if (GetBuffStacks(Buffs.Triplecast) == 0 && IsOffCooldown(All.Swiftcast) && + CanSpellWeave(ActionWatching.LastSpell)) + return All.Swiftcast; + + if (HasEffect(All.Buffs.Swiftcast) || GetBuffStacks(Buffs.Triplecast) > 0) + return OriginalHook(Blizzard2); + } + + if (Gauge.UmbralIceStacks < 3 && ActionReady(OriginalHook(Blizzard2))) + return OriginalHook(Blizzard2); + + if (Freeze.LevelChecked() && Gauge.UmbralHearts < 3 && TraitLevelChecked(Traits.UmbralHeart)) + return Freeze; + + if (BLMHelper.DoubleBlizz() && Fire2.LevelChecked()) + return OriginalHook(Fire2); + + if (curMp < LocalPlayer.MaxMp) + return Freeze.LevelChecked() + ? OriginalHook(Freeze) + : OriginalHook(Blizzard2); + + if (IsEnabled(CustomComboPreset.BLM_AoE_Transpose) && + ActionReady(Transpose) && + ((CanSpellWeave(ActionWatching.LastSpell) && Flare.LevelChecked()) || + !TraitLevelChecked(Traits.AspectMasteryIII))) + return Transpose; + + if (Fire2.LevelChecked() && TraitLevelChecked(Traits.AspectMasteryIII)) + return OriginalHook(Fire2); + } + + if (Blizzard2.LevelChecked()) + return OriginalHook(Blizzard2); + + return actionID; + } + } + + internal class BLM_AoE_AdvancedMode : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_AoE_AdvancedMode; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + int PolyglotStacks = Gauge.PolyglotStacks; + float TriplecastChargetime = GetCooldownChargeRemainingTime(Triplecast); + + if (actionID is not (Blizzard2 or HighBlizzard2)) + return actionID; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Cure) && + IsEnabled(Variant.VariantCure) && + PlayerHealthPercentageHp() <= Config.BLM_VariantCure) + return Variant.VariantCure; + + if (IsEnabled(CustomComboPreset.BLM_Variant_Rampart) && + IsEnabled(Variant.VariantRampart) && + IsOffCooldown(Variant.VariantRampart) && + CanSpellWeave(ActionWatching.LastSpell)) + return Variant.VariantRampart; + + if (WasLastSpell(UmbralSoul)) + return OriginalHook(Fire2); + + if ((IsEnabled(CustomComboPreset.BLM_AoE_Thunder) && + HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && LevelChecked(Thunder2) && + GetTargetHPPercent() >= Config.BLM_AoE_ThunderHP && + thunderDebuffAoE is null) || thunderDebuffAoE.RemainingTime < 3) + return OriginalHook(Thunder2); + + if (IsEnabled(CustomComboPreset.BLM_AoE_Amplifier) && + ActionReady(Amplifier) && remainingPolyglotCD >= 20000 && CanSpellWeave(ActionWatching.LastSpell)) + return Amplifier; + + if (IsMoving) + { + if (IsEnabled(CustomComboPreset.BLM_AoE_Amplifier) && + ActionReady(Amplifier) && Gauge.PolyglotStacks < maxPolyglot) + return Amplifier; + + if (IsEnabled(CustomComboPreset.BLM_AoE_UsePolyglotMoving) && + PolyglotStacks > Config.BLM_AoE_UsePolyglotMoving_HoldCharges) + return Foul; + } + + if (IsEnabled(CustomComboPreset.BLM_AoE_LeyLines) && + CanSpellWeave(ActionWatching.LastSpell) && ActionReady(LeyLines)) + return LeyLines; + + if (Gauge.InAstralFire) + { + if (IsEnabled(CustomComboPreset.BLM_AoE_Flarestar) && + curMp == 0 && FlareStar.LevelChecked() && Gauge.AstralSoulStacks == 6) + return FlareStar; + + if (!FlareStar.LevelChecked() && Fire2.LevelChecked() && curMp >= MP.FireAoE && + (Gauge.UmbralHearts > 1 || !TraitLevelChecked(Traits.UmbralHeart))) + return OriginalHook(Fire2); + + if (IsEnabled(CustomComboPreset.BLM_AoE_Flare) && + Flare.LevelChecked() && curMp >= MP.FlareAoE) + { + if (LevelChecked(Triplecast) && CanSpellWeave(ActionWatching.LastSpell) && + GetBuffStacks(Buffs.Triplecast) == 0 && + (GetRemainingCharges(Triplecast) > Config.BLM_AoE_Triplecast_HoldCharges || + TriplecastChargetime <= Config.BLM_AoE_Triplecast_ChargeTime)) + return Triplecast; + + return Flare; + } + + if (Fire2.LevelChecked()) + if (gcdsInTimer > 1 && curMp >= MP.FireAoE) + return OriginalHook(Fire2); + + if (IsEnabled(CustomComboPreset.BLM_AoE_Manafont) && + ActionReady(Manafont)) + return Manafont; + + if (IsEnabled(CustomComboPreset.BLM_AoE_Transpose) && + ActionReady(Transpose) && (!TraitLevelChecked(Traits.AspectMasteryIII) || canSwiftF)) + return Transpose; + + if (ActionReady(Blizzard2) && TraitLevelChecked(Traits.AspectMasteryIII)) + return OriginalHook(Blizzard2); + } + + if (Gauge.InUmbralIce) + { + if (IsEnabled(CustomComboPreset.BLM_AoE_UsePolyglot) && + PolyglotStacks > Config.BLM_AoE_UsePolyglot_HoldCharges) + return Foul; + + if (ActionWatching.WhichOfTheseActionsWasLast(OriginalHook(Fire2), OriginalHook(Freeze), + OriginalHook(Flare), OriginalHook(FlareStar)) == OriginalHook(Freeze) && + FlareStar.LevelChecked()) + { + if (IsEnabled(CustomComboPreset.BLM_AoE_Transpose) && + ActionReady(Transpose) && CanSpellWeave(ActionWatching.LastSpell)) + return Transpose; + + return OriginalHook(Fire2); + } + + if (ActionReady(OriginalHook(Blizzard2)) && Gauge.UmbralIceStacks < 3 && + TraitLevelChecked(Traits.AspectMasteryIII)) + { + if (IsEnabled(CustomComboPreset.BLM_AoE_Triplecast) && + LevelChecked(Triplecast) && CanSpellWeave(ActionWatching.LastSpell) && + GetBuffStacks(Buffs.Triplecast) == 0 && + (GetRemainingCharges(Triplecast) > Config.BLM_AoE_Triplecast_HoldCharges || + TriplecastChargetime <= Config.BLM_AoE_Triplecast_ChargeTime)) + return Triplecast; + + if (IsEnabled(CustomComboPreset.BLM_AoE_Swiftcast) && + GetBuffStacks(Buffs.Triplecast) == 0 && IsOffCooldown(All.Swiftcast) && + CanSpellWeave(ActionWatching.LastSpell)) + return All.Swiftcast; + + if (HasEffect(All.Buffs.Swiftcast) || GetBuffStacks(Buffs.Triplecast) > 0) + return OriginalHook(Blizzard2); + } + + if (Gauge.UmbralIceStacks < 3 && ActionReady(OriginalHook(Blizzard2))) + return OriginalHook(Blizzard2); + + if (Freeze.LevelChecked() && Gauge.UmbralHearts < 3 && TraitLevelChecked(Traits.UmbralHeart)) + return Freeze; + + if (BLMHelper.DoubleBlizz() && Fire2.LevelChecked()) + return OriginalHook(Fire2); + + if (curMp < LocalPlayer.MaxMp) + return Freeze.LevelChecked() + ? OriginalHook(Freeze) + : OriginalHook(Blizzard2); + + if (IsEnabled(CustomComboPreset.BLM_AoE_Transpose) && + ActionReady(Transpose) && + ((CanSpellWeave(ActionWatching.LastSpell) && Flare.LevelChecked()) || + !TraitLevelChecked(Traits.AspectMasteryIII))) + return Transpose; + + if (Fire2.LevelChecked() && TraitLevelChecked(Traits.AspectMasteryIII)) + return OriginalHook(Fire2); + } + + if (Blizzard2.LevelChecked()) + return OriginalHook(Blizzard2); + + return actionID; + } + } + + internal class BLM_Variant_Raise : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Variant_Raise; + + protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) + { + return actionID is All.Swiftcast && HasEffect(All.Buffs.Swiftcast) && IsEnabled(Variant.VariantRaise) + ? Variant.VariantRaise + : actionID; + } + } + + internal class BLM_Scathe_Xeno : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Scathe_Xeno; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Scathe && LevelChecked(Xenoglossy) && BLMHelper.HasPolyglotStacks(Gauge) + ? Xenoglossy + : actionID; + } + } + + internal class BLM_Blizzard_1to3 : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Blizzard_1to3; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID switch + { + Blizzard when LevelChecked(Freeze) && !Gauge.InUmbralIce => Blizzard3, + Freeze when !LevelChecked(Freeze) => Blizzard2, + var _ => actionID + }; + } + } + + internal class BLM_Fire_1to3 : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Fire_1to3; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Fire && + ((LevelChecked(Fire3) && !Gauge.InAstralFire) || + HasEffect(Buffs.Firestarter)) + ? Fire3 + : actionID; + } + } + + internal class BLM_Between_The_LeyLines : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Between_The_LeyLines; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is LeyLines && HasEffect(Buffs.LeyLines) && LevelChecked(BetweenTheLines) + ? BetweenTheLines + : actionID; + } + } + + internal class BLM_Aetherial_Manipulation : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_Aetherial_Manipulation; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is AetherialManipulation && + ActionReady(BetweenTheLines) && + HasEffect(Buffs.LeyLines) && + !HasEffect(Buffs.CircleOfPower) && + !IsMoving + ? BetweenTheLines + : actionID; + } + } + + internal class BLM_UmbralSoul : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_UmbralSoul; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Transpose && Gauge.InUmbralIce && LevelChecked(UmbralSoul) + ? UmbralSoul + : actionID; + } + } + + internal class BLM_TriplecastProtection : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_TriplecastProtection; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return actionID is Triplecast && HasEffect(Buffs.Triplecast) && LevelChecked(Triplecast) + ? OriginalHook(11) + : actionID; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs new file mode 100644 index 000000000..dcb02d124 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs @@ -0,0 +1,95 @@ +using XIVSlothCombo.CustomComboNS.Functions; +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class BLM +{ + internal static class Config + { + public static UserInt + BLM_VariantCure = new("BLM_VariantCure"), + BLM_VariantRampart = new("BLM_VariantRampart"), + BLM_ST_Triplecast_HoldCharges = new("BLM_ST_Triplecast_HoldCharges", 0), + BLM_ST_UsePolyglot_HoldCharges = new("BLM_ST_UsePolyglot_HoldCharges", 1), + BLM_ST_UsePolyglotMoving_HoldCharges = new("BLM_ST_UsePolyglotMoving_HoldCharges", 0), + BLM_ST_ThunderHP = new("BHP", 0), + BLM_AoE_Triplecast_HoldCharges = new("BLM_AoE_Triplecast_HoldCharges", 0), + BLM_AoE_UsePolyglot_HoldCharges = new("BLM_AoE_UsePolyglot_HoldCharges", 1), + BLM_AoE_UsePolyglotMoving_HoldCharges = new("BLM_AoE_UsePolyglotMoving_HoldCharges", 0), + BLM_AoE_ThunderHP = new("BLM_AoE_ThunderHP", 5); + + public static UserFloat + BLM_ST_Triplecast_ChargeTime = new("BLM_ST_Triplecast_ChargeTime", 20), + BLM_AoE_Triplecast_ChargeTime = new("BLM_AoE_Triplecast_ChargeTime", 20); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.BLM_Variant_Cure: + DrawSliderInt(1, 100, BLM_VariantCure, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.BLM_Variant_Rampart: + DrawSliderInt(1, 100, BLM_VariantRampart, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.BLM_ST_Triplecast: + DrawSliderInt(0, 1, BLM_ST_Triplecast_HoldCharges, "How many charges to keep ready? (0 = Use all)"); + + DrawSliderInt(10, 20, BLM_ST_Triplecast_ChargeTime, + "Set the amount of time remaining on Triplecast charge before using.(Only when at threshold)"); + + break; + + case CustomComboPreset.BLM_ST_UsePolyglot: + DrawSliderInt(0, 2, BLM_ST_UsePolyglot_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + + break; + + case CustomComboPreset.BLM_ST_UsePolyglotMoving: + DrawSliderInt(0, 2, BLM_ST_UsePolyglotMoving_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + + break; + + case CustomComboPreset.BLM_ST_Thunder: + DrawSliderInt(0, 10, BLM_ST_ThunderHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + + case CustomComboPreset.BLM_AoE_Triplecast: + DrawSliderInt(0, 1, BLM_AoE_Triplecast_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + + DrawSliderInt(10, 20, BLM_AoE_Triplecast_ChargeTime, + "Set the amount of time remaining on Triplecast charge before using.(Only when at threshold)"); + + break; + + case CustomComboPreset.BLM_AoE_UsePolyglot: + DrawSliderInt(0, 2, BLM_AoE_UsePolyglot_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + + break; + + case CustomComboPreset.BLM_AoE_UsePolyglotMoving: + DrawSliderInt(0, 2, BLM_AoE_UsePolyglotMoving_HoldCharges, + "How many charges to keep ready? (0 = Use all)"); + + break; + + case CustomComboPreset.BLM_AoE_Thunder: + DrawSliderInt(0, 10, BLM_AoE_ThunderHP, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)"); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs new file mode 100644 index 000000000..3c65aabf0 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs @@ -0,0 +1,300 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Statuses; +using ECommons.DalamudServices; +using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Data; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class BLM +{ + // BLM Gauge & Extensions + public static BLMGauge Gauge => GetJobGauge(); + + public static int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; + + public static bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + + public static int remainingPolyglotCD = Math.Max(0, + (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); + + public static uint curMp = LocalPlayer.CurrentMp; + + public static Status? thunderDebuffST = + FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); + + public static Status? thunderDebuffAoE = + FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); + + public static float elementTimer = Gauge.ElementTimeRemaining / 1000f; + public static double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(Fire)); + + public static bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && + IsOffCooldown(All.Swiftcast); + + public static int Fire4Count => ActionWatching.CombatActions.Count(x => x == Fire4); + + internal class BLMOpenerLogic + { + private OpenerState currentState = OpenerState.PrePull; + + public uint OpenerStep = 1; + + public uint PrePullStep; + + private static uint OpenerLevel => 100; + + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState + { + get => currentState; + set + { + if (value != currentState) + { + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value is OpenerState.OpenerFinished or OpenerState.FailedOpener) + { + if (value == OpenerState.FailedOpener) + Svc.Log.Information($"Opener Failed at step {OpenerStep}"); + + ResetOpener(); + } + if (value == OpenerState.OpenerFinished) Svc.Log.Information("Opener Finished"); + + currentState = value; + } + } + } + + private static bool HasCooldowns() + { + if (!ActionReady(Manafont)) + return false; + + if (GetRemainingCharges(Triplecast) < 2) + return false; + + if (!ActionReady(All.Swiftcast)) + return false; + + if (!ActionReady(Amplifier)) + return false; + + if (!ActionReady(LeyLines)) + return false; + + return true; + } + + private bool DoPrePullSteps(ref uint actionID) + { + if (!LevelChecked) return false; + + if (CanOpener && PrePullStep == 0) PrePullStep = 1; + + if (!HasCooldowns()) PrePullStep = 0; + + if (CurrentState == OpenerState.PrePull && PrePullStep > 0) + { + if (WasLastAction(Fire3) && HasEffect(Buffs.Thunderhead) && PrePullStep == 1) + CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) actionID = Fire3; + + if (ActionWatching.CombatActions.Count > 2 && InCombat()) + CurrentState = OpenerState.FailedOpener; + + return true; + } + + PrePullStep = 0; + + return false; + } + + private bool DoOpener(ref uint actionID) + { + if (!LevelChecked) return false; + + if (currentState == OpenerState.InOpener) + { + if (WasLastAction(HighThunder) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = HighThunder; + + if (WasLastAction(All.Swiftcast) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = All.Swiftcast; + + if (WasLastAction(Amplifier) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = Amplifier; + + if (WasLastAction(Fire4) && Fire4Count is 1 && OpenerStep == 4) OpenerStep++; + else if (OpenerStep == 4) actionID = Fire4; + + if (WasLastAction(Fire4) && Fire4Count is 2 && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = Fire4; + + if (WasLastAction(Xenoglossy) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = Xenoglossy; + + if (WasLastAction(Triplecast) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = Triplecast; + + if (WasLastAction(LeyLines) && OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8) actionID = LeyLines; + + if (WasLastAction(Fire4) && Fire4Count is 3 && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) actionID = Fire4; + + if (WasLastAction(Fire4) && Fire4Count is 4 && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = Fire4; + + if (WasLastAction(Despair) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) actionID = Despair; + + if (WasLastAction(Manafont) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = Manafont; + + if (WasLastAction(Triplecast) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = Triplecast; + + if (WasLastAction(Fire4) && Fire4Count is 5 && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = Fire4; + + if (WasLastAction(Fire4) && Fire4Count is 6 && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = Fire4; + + if (WasLastAction(FlareStar) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = FlareStar; + + if (WasLastAction(Fire4) && Fire4Count is 7 && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = Fire4; + + if (WasLastAction(HighThunder) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = HighThunder; + + if (WasLastAction(Paradox) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = Paradox; + + if (WasLastAction(Fire4) && Fire4Count is 8 && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = Fire4; + + if (WasLastAction(Fire4) && Fire4Count is 9 && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = Fire4; + + if (WasLastAction(Fire4) && Fire4Count is 10 && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = Fire4; + + if (WasLastAction(Despair) && OpenerStep == 23) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 23) actionID = Despair; + + if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) + CurrentState = OpenerState.FailedOpener; + + if (((actionID == Triplecast && GetRemainingCharges(Triplecast) == 0) || + (actionID == Amplifier && IsOnCooldown(Amplifier)) || + (actionID == LeyLines && IsOnCooldown(LeyLines)) || + (actionID == Manafont && IsOnCooldown(Manafont)) || + (actionID == All.Swiftcast && IsOnCooldown(All.Swiftcast)) || + (actionID == Xenoglossy && Gauge.PolyglotStacks == 0)) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + { + CurrentState = OpenerState.FailedOpener; + + return false; + } + + return true; + } + + return false; + } + + private void ResetOpener() + { + PrePullStep = 0; + OpenerStep = 0; + } + + public bool DoFullOpener(ref uint actionID) + { + if (!LevelChecked) return false; + + if (CurrentState == OpenerState.PrePull) + if (DoPrePullSteps(ref actionID)) + return true; + + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID)) + return true; + + if (!InCombat()) + { + ResetOpener(); + CurrentState = OpenerState.PrePull; + } + + return false; + } + } + + internal class BLMHelper + { + public static bool HasPolyglotStacks(BLMGauge Gauge) => Gauge.PolyglotStacks > 0; + + public static float MPAfterCast() + { + uint castedSpell = LocalPlayer.CastActionId; + + int nextMpGain = Gauge.UmbralIceStacks switch + { + 0 => 0, + 1 => 2500, + 2 => 5000, + 3 => 10000, + var _ => 0 + }; + + return castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2 + ? Math.Max(LocalPlayer.MaxMp, LocalPlayer.CurrentMp + nextMpGain) + : Math.Max(0, LocalPlayer.CurrentMp - GetResourceCost(castedSpell)); + } + + public static bool DoubleBlizz() + { + List spells = ActionWatching.CombatActions.Where(x => + ActionWatching.GetAttackType(x) == ActionWatching.ActionAttackType.Spell && + x != OriginalHook(Thunder) && x != OriginalHook(Thunder2)).ToList(); + + if (spells.Count < 1) return false; + + uint firstSpell = spells[^1]; + + switch (firstSpell) + { + case Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2: + { + uint castedSpell = LocalPlayer.CastActionId; + + if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) + return true; + + if (spells is [.., Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2, var _]) return true; + + break; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/BLU.cs b/XIVSlothCombo/Combos/PvE/BLU/BLU.cs similarity index 99% rename from XIVSlothCombo/Combos/PvE/BLU.cs rename to XIVSlothCombo/Combos/PvE/BLU/BLU.cs index a439cd633..5f0941788 100644 --- a/XIVSlothCombo/Combos/PvE/BLU.cs +++ b/XIVSlothCombo/Combos/PvE/BLU/BLU.cs @@ -3,7 +3,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class BLU + internal partial class BLU { public const byte JobID = 36; diff --git a/XIVSlothCombo/Combos/PvE/BLU/BLU_Config.cs b/XIVSlothCombo/Combos/PvE/BLU/BLU_Config.cs new file mode 100644 index 000000000..e27ae041e --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/BLU/BLU_Config.cs @@ -0,0 +1,17 @@ +namespace XIVSlothCombo.Combos.PvE; + +internal partial class BLU +{ + internal static class Config + { + //Config goes here + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + //Presets + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD/BRD.cs similarity index 99% rename from XIVSlothCombo/Combos/PvE/BRD.cs rename to XIVSlothCombo/Combos/PvE/BRD/BRD.cs index fd27a225b..50da4bbf1 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD/BRD.cs @@ -9,7 +9,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class BRD + internal partial class BRD { public const byte ClassID = 5; public const byte JobID = 23; @@ -73,17 +73,7 @@ public const ushort CausticBite = 1200, Stormbite = 1201; } - - public static class Config - { - public const string - BRD_RagingJawsRenewTime = "ragingJawsRenewTime", - BRD_NoWasteHPPercentage = "noWasteHpPercentage", - BRD_AoENoWasteHPPercentage = "AoENoWasteHpPercentage", - BRD_STSecondWindThreshold = "BRD_STSecondWindThreshold", - BRD_AoESecondWindThreshold = "BRD_AoESecondWindThreshold", - BRD_VariantCure = "BRD_VariantCure"; - } + internal static class Traits { internal const ushort diff --git a/XIVSlothCombo/Combos/PvE/BRD/BRD_Config.cs b/XIVSlothCombo/Combos/PvE/BRD/BRD_Config.cs new file mode 100644 index 000000000..d95ca9329 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/BRD/BRD_Config.cs @@ -0,0 +1,57 @@ +using static XIVSlothCombo.Window.Functions.UserConfig; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class BRD +{ + internal static class Config + { + public const string + BRD_RagingJawsRenewTime = "ragingJawsRenewTime", + BRD_NoWasteHPPercentage = "noWasteHpPercentage", + BRD_AoENoWasteHPPercentage = "AoENoWasteHpPercentage", + BRD_STSecondWindThreshold = "BRD_STSecondWindThreshold", + BRD_AoESecondWindThreshold = "BRD_AoESecondWindThreshold", + BRD_VariantCure = "BRD_VariantCure"; + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.BRD_Adv_RagingJaws: + DrawSliderInt(3, 10, BRD_RagingJawsRenewTime, + "Remaining time (In seconds). Recommended 5, increase little by little if refresh is outside of radiant window"); + + break; + + case CustomComboPreset.BRD_Adv_NoWaste: + DrawSliderInt(1, 10, BRD_NoWasteHPPercentage, "Remaining target HP percentage"); + + break; + + case CustomComboPreset.BRD_AoE_Adv_NoWaste: + DrawSliderInt(1, 10, BRD_AoENoWasteHPPercentage, + "Remaining target HP percentage"); + + break; + + case CustomComboPreset.BRD_ST_SecondWind: + DrawSliderInt(0, 100, BRD_STSecondWindThreshold, + "HP percent threshold to use Second Wind below."); + + break; + + case CustomComboPreset.BRD_AoE_SecondWind: + DrawSliderInt(0, 100, BRD_AoESecondWindThreshold, + "HP percent threshold to use Second Wind below."); + + break; + + case CustomComboPreset.BRD_Variant_Cure: + DrawSliderInt(1, 100, BRD_VariantCure, "HP% to be at or under", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/Content/Bozja.cs b/XIVSlothCombo/Combos/PvE/Content/Bozja.cs index bcb36730a..ffb26d7dd 100644 --- a/XIVSlothCombo/Combos/PvE/Content/Bozja.cs +++ b/XIVSlothCombo/Combos/PvE/Content/Bozja.cs @@ -1,60 +1,59 @@ -namespace XIVSlothCombo.Combos.PvE.Content +namespace XIVSlothCombo.Combos.PvE.Content; + +internal class Bozja { - internal static class Bozja - { - public const uint - LostBanish3 = 20702, - FontOfMagic = 20715, - FontOfPower = 20717, - BannerOfNobleEnds = 20720, - BannerOfHonoredSacrifice = 20721, - LostCure = 20726, - LostCure2 = 20727, - LostCure3 = 20728, - LostCure4 = 20729, - LostIncense = 20731, - LostFlareStar = 22352, - LostRendArmor = 22353, - LostSeraphStrike = 22354, - LostAethershield = 22355, - LostDervish = 22356, - LostBurst = 23909, - LostRampage = 23910, - LostChainspell = 23913, - LostAssassination = 23914, - LostExcellence = 23919, - LostBloodRage = 23921; + public const uint + LostBanish3 = 20702, + FontOfMagic = 20715, + FontOfPower = 20717, + BannerOfNobleEnds = 20720, + BannerOfHonoredSacrifice = 20721, + LostCure = 20726, + LostCure2 = 20727, + LostCure3 = 20728, + LostCure4 = 20729, + LostIncense = 20731, + LostFlareStar = 22352, + LostRendArmor = 22353, + LostSeraphStrike = 22354, + LostAethershield = 22355, + LostDervish = 22356, + LostBurst = 23909, + LostRampage = 23910, + LostChainspell = 23913, + LostAssassination = 23914, + LostExcellence = 23919, + LostBloodRage = 23921; - public static class Buffs - { - public const ushort - MPRefresh = 909, - MPRefresh2 = 1198, - ProfaneEssence = 2320, - IrregularEssence = 2321, - BeastEssence = 2324, - BannerOfNobleEnds = 2326, - BannerOfHonoredSacrifice = 2327, - FontOfMagic = 2332, - LostBravery2 = 2341, - FontOfPower = 2346, - PureElder = 2435, - PureFiendhunter = 2437, - PureIndomitable = 2438, - PureDivine = 2439, - LostAethershield = 2443, - LostDervish = 2444, - ClericStance = 2484, - LostChainspell = 2560, - LostExcellence = 2564, - LostBloodRage = 2566; - } + public static class Buffs + { + public const ushort + MPRefresh = 909, + MPRefresh2 = 1198, + ProfaneEssence = 2320, + IrregularEssence = 2321, + BeastEssence = 2324, + BannerOfNobleEnds = 2326, + BannerOfHonoredSacrifice = 2327, + FontOfMagic = 2332, + LostBravery2 = 2341, + FontOfPower = 2346, + PureElder = 2435, + PureFiendhunter = 2437, + PureIndomitable = 2438, + PureDivine = 2439, + LostAethershield = 2443, + LostDervish = 2444, + ClericStance = 2484, + LostChainspell = 2560, + LostExcellence = 2564, + LostBloodRage = 2566; + } - public static class Debuffs - { - public const ushort - LostFlareStar = 2440, - LostRendArmor = 2441; - } + public static class Debuffs + { + public const ushort + LostFlareStar = 2440, + LostRendArmor = 2441; } -} +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/Content/Variant.cs b/XIVSlothCombo/Combos/PvE/Content/Variant.cs index 8f31b9a04..fa143d22e 100644 --- a/XIVSlothCombo/Combos/PvE/Content/Variant.cs +++ b/XIVSlothCombo/Combos/PvE/Content/Variant.cs @@ -1,50 +1,50 @@ using ECommons.DalamudServices; -namespace XIVSlothCombo.Combos.PvE.Content +namespace XIVSlothCombo.Combos.PvE.Content; + +internal static class Variant { - internal static class Variant + public const uint + VariantUltimatum = 29730, + VariantRaise = 29731, + VariantRaise2 = 29734; + + //1069 = The Sil'dihn Subterrane + //1137 = Mount Rokkon + //1176 = Aloalo Island + public static uint VariantCure => Svc.ClientState.TerritoryType switch { - public const uint - VariantUltimatum = 29730, - VariantRaise = 29731, - VariantRaise2 = 29734; - //1069 = The Sil'dihn Subterrane - //1137 = Mount Rokkon - //1176 = Aloalo Island - public static uint VariantCure => Svc.ClientState.TerritoryType switch - { - 1069 => 29729, - 1137 or 1176 => 33862, - _ => 0 - }; + 1069 => 29729, + 1137 or 1176 => 33862, + _ => 0 + }; - public static uint VariantSpiritDart => Svc.ClientState.TerritoryType switch - { - 1069 => 29732, - 1137 or 1176 => 33863, - _ => 0 - }; + public static uint VariantSpiritDart => Svc.ClientState.TerritoryType switch + { + 1069 => 29732, + 1137 or 1176 => 33863, + _ => 0 + }; - public static uint VariantRampart => Svc.ClientState.TerritoryType switch - { - 1069 => 29733, - 1137 or 1176 => 33864, - _ => 0 - }; + public static uint VariantRampart => Svc.ClientState.TerritoryType switch + { + 1069 => 29733, + 1137 or 1176 => 33864, + _ => 0 + }; - public static class Buffs - { - public const ushort - EmnityUp = 3358, - VulnDown = 3360, - Rehabilitation = 3367, - DamageBarrier = 3405; - } + public static class Buffs + { + public const ushort + EmnityUp = 3358, + VulnDown = 3360, + Rehabilitation = 3367, + DamageBarrier = 3405; + } - public static class Debuffs - { - public const ushort - SustainedDamage = 3359; - } + public static class Debuffs + { + public const ushort + SustainedDamage = 3359; } -} +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC/DNC.cs similarity index 94% rename from XIVSlothCombo/Combos/PvE/DNC.cs rename to XIVSlothCombo/Combos/PvE/DNC/DNC.cs index 4ff1da3b8..e286cdcb2 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC/DNC.cs @@ -1,12 +1,11 @@ using Dalamud.Game.ClientState.JobGauge.Types; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; namespace XIVSlothCombo.Combos.PvE { - internal static class DNC + internal partial class DNC { public const byte JobID = 38; @@ -88,36 +87,6 @@ public const ushort Devilment = 1825; } - public static class Config - { - public static readonly UserInt - DNCEspritThreshold_ST = new UserInt("DNCEspritThreshold_ST", 50); // ST - Esprit threshold - public static readonly UserInt - DNCEspritThreshold_AoE = new UserInt("DNCEspritThreshold_AoE", 50); // AoE - Esprit threshold - - #region Advanced ST Sliders - public static readonly UserInt - DNC_ST_Adv_SSBurstPercent = new UserInt("DNC_ST_Adv_SSBurstPercent", 0), // Standard Step - target HP% threshold - DNC_ST_Adv_TSBurstPercent = new UserInt("DNC_ST_Adv_TSBurstPercent", 0), // Technical Step - target HP% threshold - DNC_ST_Adv_FeatherBurstPercent = new UserInt("DNC_ST_Adv_FeatherBurstPercent", 0), // Feather burst - target HP% threshold - DNC_ST_Adv_SaberThreshold = new UserInt("DNC_ST_Adv_SaberThreshold", 50), // Saber Dance - Esprit threshold - DNC_ST_Adv_PanicHealWaltzPercent = new UserInt("DNC_ST_Adv_PanicHealWaltzPercent", 30), // Curing Waltz - player HP% threshold - DNC_ST_Adv_PanicHealWindPercent = new UserInt("DNC_ST_Adv_PanicHealWindPercent", 20); // Second Wind - player HP% threshold - #endregion - - #region Advanced AoE Sliders - public static readonly UserInt - DNC_AoE_Adv_SSBurstPercent = new UserInt("DNC_AoE_Adv_SSBurstPercent", 0), // Standard Step - target HP% threshold - DNC_AoE_Adv_TSBurstPercent = new UserInt("DNC_AoE_Adv_TSBurstPercent", 0), // Technical Step - target HP% threshold - DNC_AoE_Adv_SaberThreshold = new UserInt("DNC_AoE_Adv_SaberThreshold", 50), // Saber Dance - Esprit threshold - DNC_AoE_Adv_PanicHealWaltzPercent = new UserInt("DNC_AoE_Adv_PanicHealWaltzPercent", 30), // Curing Waltz - player HP% threshold - DNC_AoE_Adv_PanicHealWindPercent = new UserInt("DNC_AoE_Adv_PanicHealWindPercent", 20); // Second Wind - player HP% threshold - #endregion - - public static readonly UserInt - DNCVariantCurePercent = new UserInt("DNCVariantCurePercent"); // Variant Cure - player HP% threshold - } - internal class DNC_DanceComboReplacer : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DNC_DanceComboReplacer; diff --git a/XIVSlothCombo/Combos/PvE/DNC/DNC_Config.cs b/XIVSlothCombo/Combos/PvE/DNC/DNC_Config.cs new file mode 100644 index 000000000..f23ea6978 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/DNC/DNC_Config.cs @@ -0,0 +1,162 @@ +using System.Linq; +using ImGuiNET; +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Services; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class DNC +{ + internal static class Config + { + public static readonly UserInt + DNCEspritThreshold_ST = new("DNCEspritThreshold_ST", 50); // ST - Esprit threshold + + public static readonly UserInt + DNCEspritThreshold_AoE = new("DNCEspritThreshold_AoE", 50); // AoE - Esprit threshold + + #region Advanced ST Sliders + + public static readonly UserInt + DNC_ST_Adv_SSBurstPercent = new("DNC_ST_Adv_SSBurstPercent", 0), // Standard Step - target HP% threshold + DNC_ST_Adv_TSBurstPercent = new("DNC_ST_Adv_TSBurstPercent", 0), // Technical Step - target HP% threshold + DNC_ST_Adv_FeatherBurstPercent = + new("DNC_ST_Adv_FeatherBurstPercent", 0), // Feather burst - target HP% threshold + DNC_ST_Adv_SaberThreshold = new("DNC_ST_Adv_SaberThreshold", 50), // Saber Dance - Esprit threshold + DNC_ST_Adv_PanicHealWaltzPercent = + new("DNC_ST_Adv_PanicHealWaltzPercent", 30), // Curing Waltz - player HP% threshold + DNC_ST_Adv_PanicHealWindPercent = + new("DNC_ST_Adv_PanicHealWindPercent", 20); // Second Wind - player HP% threshold + + #endregion + + #region Advanced AoE Sliders + + public static readonly UserInt + DNC_AoE_Adv_SSBurstPercent = new("DNC_AoE_Adv_SSBurstPercent", 0), // Standard Step - target HP% threshold + DNC_AoE_Adv_TSBurstPercent = new("DNC_AoE_Adv_TSBurstPercent", 0), // Technical Step - target HP% threshold + DNC_AoE_Adv_SaberThreshold = new("DNC_AoE_Adv_SaberThreshold", 50), // Saber Dance - Esprit threshold + DNC_AoE_Adv_PanicHealWaltzPercent = + new("DNC_AoE_Adv_PanicHealWaltzPercent", 30), // Curing Waltz - player HP% threshold + DNC_AoE_Adv_PanicHealWindPercent = + new("DNC_AoE_Adv_PanicHealWindPercent", 20); // Second Wind - player HP% threshold + + #endregion + + public static readonly UserInt + DNCVariantCurePercent = new("DNCVariantCurePercent"); // Variant Cure - player HP% threshold + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.DNC_DanceComboReplacer: + { + int[]? actions = Service.Configuration.DancerDanceCompatActionIDs.Select(x => (int)x).ToArray(); + + bool inputChanged = false; + + inputChanged |= ImGui.InputInt("Emboite (Red) ActionID", ref actions[0], 0); + inputChanged |= ImGui.InputInt("Entrechat (Blue) ActionID", ref actions[1], 0); + inputChanged |= ImGui.InputInt("Jete (Green) ActionID", ref actions[2], 0); + inputChanged |= ImGui.InputInt("Pirouette (Yellow) ActionID", ref actions[3], 0); + + if (inputChanged) + { + //Service.Configuration.DancerDanceCompatActionIDs = actions.Cast().ToArray(); + Service.Configuration.DancerDanceCompatActionIDs = actions.Select(x => (uint)x).ToArray(); + Service.Configuration.Save(); + } + + ImGui.Spacing(); + + break; + } + + case CustomComboPreset.DNC_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, DNCVariantCurePercent, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.DNC_ST_EspritOvercap: + UserConfig.DrawSliderInt(50, 100, DNCEspritThreshold_ST, "Esprit", 150, + SliderIncrements.Fives); + + break; + + case CustomComboPreset.DNC_AoE_EspritOvercap: + UserConfig.DrawSliderInt(50, 100, DNCEspritThreshold_AoE, "Esprit", 150, + SliderIncrements.Fives); + + break; + + case CustomComboPreset.DNC_ST_Adv_SS: + UserConfig.DrawSliderInt(0, 5, DNC_ST_Adv_SSBurstPercent, + "Target HP% to stop using Standard Step below", 75); + + break; + + case CustomComboPreset.DNC_ST_Adv_TS: + UserConfig.DrawSliderInt(0, 5, DNC_ST_Adv_TSBurstPercent, + "Target HP% to stop using Technical Step below", 75); + + break; + + case CustomComboPreset.DNC_ST_Adv_Feathers: + UserConfig.DrawSliderInt(0, 5, DNC_ST_Adv_FeatherBurstPercent, + "Target HP% to dump all pooled feathers below", 75); + + break; + + case CustomComboPreset.DNC_ST_Adv_SaberDance: + UserConfig.DrawSliderInt(50, 100, DNC_ST_Adv_SaberThreshold, "Esprit", 150, + SliderIncrements.Fives); + + break; + + case CustomComboPreset.DNC_ST_Adv_PanicHeals: + UserConfig.DrawSliderInt(0, 100, DNC_ST_Adv_PanicHealWaltzPercent, "Curing Waltz HP%", + 200); + + UserConfig.DrawSliderInt(0, 100, DNC_ST_Adv_PanicHealWindPercent, "Second Wind HP%", + 200); + + break; + + case CustomComboPreset.DNC_AoE_Adv_SS: + UserConfig.DrawSliderInt(0, 10, DNC_AoE_Adv_SSBurstPercent, + "Target HP% to stop using Standard Step below", 75); + + break; + + case CustomComboPreset.DNC_AoE_Adv_TS: + UserConfig.DrawSliderInt(0, 10, DNC_AoE_Adv_TSBurstPercent, + "Target HP% to stop using Technical Step below", 75); + + break; + + case CustomComboPreset.DNC_AoE_Adv_SaberDance: + UserConfig.DrawSliderInt(50, 100, DNC_AoE_Adv_SaberThreshold, "Esprit", 150, + SliderIncrements.Fives); + + break; + + case CustomComboPreset.DNC_AoE_Adv_PanicHeals: + UserConfig.DrawSliderInt(0, 100, DNC_AoE_Adv_PanicHealWaltzPercent, "Curing Waltz HP%", + 200); + + UserConfig.DrawSliderInt(0, 100, DNC_AoE_Adv_PanicHealWindPercent, "Second Wind HP%", 200); + + break; + + case CustomComboPreset.DNCPvP_BurstMode_CuringWaltz: + UserConfig.DrawSliderInt(0, 90, DNCPvP.Config.DNCPvP_WaltzThreshold, + "Curing Waltz HP% - caps at 90 to prevent waste."); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DOH.cs b/XIVSlothCombo/Combos/PvE/DOH/DOH.cs similarity index 93% rename from XIVSlothCombo/Combos/PvE/DOH.cs rename to XIVSlothCombo/Combos/PvE/DOH/DOH.cs index 790055752..db1bef4bb 100644 --- a/XIVSlothCombo/Combos/PvE/DOH.cs +++ b/XIVSlothCombo/Combos/PvE/DOH/DOH.cs @@ -1,6 +1,6 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class DOH + internal partial class DOH { public const byte ClassID = 0; public const byte JobID = 50; diff --git a/XIVSlothCombo/Combos/PvE/DOH/DOH_Config.cs b/XIVSlothCombo/Combos/PvE/DOH/DOH_Config.cs new file mode 100644 index 000000000..0b1656d8b --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/DOH/DOH_Config.cs @@ -0,0 +1,17 @@ +namespace XIVSlothCombo.Combos.PvE; + +internal partial class DOH +{ + internal static class Config + { + //Config goes here + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + //Presets + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DOL.cs b/XIVSlothCombo/Combos/PvE/DOL/DOL.cs similarity index 99% rename from XIVSlothCombo/Combos/PvE/DOL.cs rename to XIVSlothCombo/Combos/PvE/DOL/DOL.cs index 365bfddd6..4e0bb0a3f 100644 --- a/XIVSlothCombo/Combos/PvE/DOL.cs +++ b/XIVSlothCombo/Combos/PvE/DOL/DOL.cs @@ -3,7 +3,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class DOL + internal partial class DOL { public const byte ClassID = 0; public const byte JobID = 51; diff --git a/XIVSlothCombo/Combos/PvE/DOL/DOL_Config.cs b/XIVSlothCombo/Combos/PvE/DOL/DOL_Config.cs new file mode 100644 index 000000000..44705ba34 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/DOL/DOL_Config.cs @@ -0,0 +1,17 @@ +namespace XIVSlothCombo.Combos.PvE; + +internal partial class DOL +{ + internal static class Config + { + //Config goes here + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + //Presets + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs index e522e757d..4106a0ace 100644 --- a/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG_Config.cs @@ -43,8 +43,7 @@ internal static void Draw(CustomComboPreset preset) break; - case CustomComboPreset.DRG_Variant_Cure: - DrawSliderInt(1, 100, DRG_Variant_Cure, "HP% to be at or under", 200); + case CustomComboPreset.DRG_Variant_Cure: DrawSliderInt(1, 100, DRG_Variant_Cure, "HP% to be at or under", 200); break; diff --git a/XIVSlothCombo/Combos/PvE/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK/DRK.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/DRK.cs rename to XIVSlothCombo/Combos/PvE/DRK/DRK.cs index eff77a9a3..874a2f712 100644 --- a/XIVSlothCombo/Combos/PvE/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK/DRK.cs @@ -5,7 +5,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class DRK + internal partial class DRK { public const byte JobID = 32; @@ -76,15 +76,6 @@ public const uint EnhancedDelirium = 572; } - public static class Config - { - public static readonly UserInt - DRK_ST_ManaSpenderPooling = new("DRK_ST_ManaSpenderPooling", 3000), - DRK_ST_LivingDeadThreshold = new("DRK_ST_LivingDeadThreshold", 10), - DRK_AoE_LivingDeadThreshold = new("DRK_AoE_LivingDeadThreshold", 40), - DRK_VariantCure = new("DRKVariantCure"); - } - internal class DRK_ST_Combo : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRK_ST_Combo; diff --git a/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs b/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs new file mode 100644 index 000000000..5f3119db5 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs @@ -0,0 +1,58 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class DRK +{ + internal static class Config + { + public static readonly UserInt + DRK_ST_ManaSpenderPooling = new("DRK_ST_ManaSpenderPooling", 3000), + DRK_ST_LivingDeadThreshold = new("DRK_ST_LivingDeadThreshold", 10), + DRK_AoE_LivingDeadThreshold = new("DRK_AoE_LivingDeadThreshold", 40), + DRK_VariantCure = new("DRKVariantCure"); + + internal static void Draw(CustomComboPreset preset) + { + #region DARK KNIGHT + + switch (preset) + { + case CustomComboPreset.DRK_ST_ManaSpenderPooling: + UserConfig.DrawSliderInt(0, 3000, DRK_ST_ManaSpenderPooling, + "How much MP to save (0 = Use All)", 150, SliderIncrements.Thousands); + + break; + + case CustomComboPreset.DRK_ST_CDs_LivingShadow: + UserConfig.DrawSliderInt(0, 30, DRK_ST_LivingDeadThreshold, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)", 150, + SliderIncrements.Fives); + + break; + + case CustomComboPreset.DRK_AoE_CDs_LivingShadow: + UserConfig.DrawSliderInt(0, 60, DRK_AoE_LivingDeadThreshold, + "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)", 150, + SliderIncrements.Fives); + + break; + + case CustomComboPreset.DRKPvP_Burst: + UserConfig.DrawSliderInt(1, 100, DRKPvP.Config.ShadowbringerThreshold, + "HP% to be at or above to use Shadowbringer"); + + break; + + case CustomComboPreset.DRK_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, DRK_VariantCure, "HP% to be at or under", 200); + + break; + } + + #endregion + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/Enums/OpenerState.cs b/XIVSlothCombo/Combos/PvE/Enums/OpenerState.cs new file mode 100644 index 000000000..c7b462457 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/Enums/OpenerState.cs @@ -0,0 +1,9 @@ +namespace XIVSlothCombo.Combos.JobHelpers.Enums; + +internal enum OpenerState +{ + PrePull, + InOpener, + OpenerFinished, + FailedOpener +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB/GNB.cs similarity index 99% rename from XIVSlothCombo/Combos/PvE/GNB.cs rename to XIVSlothCombo/Combos/PvE/GNB/GNB.cs index 6d85cc471..8b14c3cc5 100644 --- a/XIVSlothCombo/Combos/PvE/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB/GNB.cs @@ -8,7 +8,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class GNB + internal partial class GNB { public const byte JobID = 37; @@ -65,18 +65,6 @@ public const ushort BowShock = 1838, SonicBreak = 1837; } - - public static class Config - { - public const string - GNB_VariantCure = "GNB_VariantCure"; - - public static UserInt - GNB_ST_NoMercyStop = new("GNB_ST_NoMercyStop"), - GNB_AoE_NoMercyStop = new ("GNB_AoE_NoMercyStop"); - } - - internal class GNB_ST_SimpleMode : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.GNB_ST_Simple; diff --git a/XIVSlothCombo/Combos/PvE/GNB/GNB_Config.cs b/XIVSlothCombo/Combos/PvE/GNB/GNB_Config.cs new file mode 100644 index 000000000..c3860e482 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/GNB/GNB_Config.cs @@ -0,0 +1,40 @@ +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class GNB +{ + internal static class Config + { + public const string + GNB_VariantCure = "GNB_VariantCure"; + + public static UserInt + GNB_ST_NoMercyStop = new("GNB_ST_NoMercyStop"), + GNB_AoE_NoMercyStop = new("GNB_AoE_NoMercyStop"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.GNB_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, GNB_VariantCure, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.GNB_ST_NoMercy: + UserConfig.DrawSliderInt(0, 25, GNB_ST_NoMercyStop, + "Stop Usage if Target HP% is below set value.\nTo Disable this option, set to 0."); + + break; + + case CustomComboPreset.GNB_AoE_NoMercy: + UserConfig.DrawSliderInt(0, 25, GNB_AoE_NoMercyStop, + "Stop Usage if Target HP% is below set value.\nTo Disable this option, set to 0."); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/MCH/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs index a861b06ef..9f24faaea 100644 --- a/XIVSlothCombo/Combos/PvE/MCH/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs @@ -48,7 +48,7 @@ public const uint Excavator = 36981, FullMetalField = 36982; - protected static MCHGauge? Gauge = GetJobGauge(); + protected static MCHGauge Gauge => GetJobGauge(); public static class Buffs { diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN/NIN.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/NIN.cs rename to XIVSlothCombo/Combos/PvE/NIN/NIN.cs index f36fb7d85..4c24e81bf 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN/NIN.cs @@ -5,11 +5,10 @@ using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; -using static XIVSlothCombo.Combos.JobHelpers.NIN; namespace XIVSlothCombo.Combos.PvE { - internal class NIN + internal partial class NIN { public const byte ClassID = 29; public const byte JobID = 30; @@ -112,30 +111,7 @@ public const uint EnhancedKasatsu = 250; } - public static class Config - { - public const string - Trick_CooldownRemaining = "Trick_CooldownRemaining", - Mug_NinkiGauge = "Mug_NinkiGauge", - Ninki_BhavaPooling = "Ninki_BhavaPooling", - Ninki_HellfrogPooling = "Ninki_HellfrogPooling", - NIN_SimpleMudra_Choice = "NIN_SimpleMudra_Choice", - Ninki_BunshinPoolingST = "Ninki_BunshinPoolingST", - Ninki_BunshinPoolingAoE = "Ninki_BunshinPoolingAoE", - Advanced_Trick_Cooldown = "Advanced_Trick_Cooldown", - Advanced_DotonTimer = "Advanced_DotonTimer", - Advanced_DotonHP = "Advanced_DotonHP", - BurnKazematoi = "BurnKazematoi", - Advanced_TCJEnderAoE = "Advanced_TCJEnderAoe", - Advanced_ChargePool = "Advanced_ChargePool", - SecondWindThresholdST = "SecondWindThresholdST", - ShadeShiftThresholdST = "ShadeShiftThresholdST", - BloodbathThresholdST = "BloodbathThresholdST", - SecondWindThresholdAoE = "SecondWindThresholdAoE", - ShadeShiftThresholdAoE = "ShadeShiftThresholdAoE", - BloodbathThresholdAoE = "BloodbathThresholdAoE", - NIN_VariantCure = "NIN_VariantCure"; - } + internal class NIN_ST_AdvancedMode : CustomCombo { @@ -187,8 +163,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (Raiton.LevelChecked() && IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_Raiton)) //under 45 will only use Raiton { - if (mudraState.CastRaiton(ref actionID)) - return actionID; + if (mudraState.CastRaiton(ref actionID)) + return actionID; } else if (!Raiton.LevelChecked() && mudraState.CastFumaShuriken(ref actionID) && IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_FumaShuriken)) // 30-35 will use only fuma return actionID; diff --git a/XIVSlothCombo/Combos/PvE/NIN/NIN_Config.cs b/XIVSlothCombo/Combos/PvE/NIN/NIN_Config.cs new file mode 100644 index 000000000..e5fa71402 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/NIN/NIN_Config.cs @@ -0,0 +1,155 @@ +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class NIN +{ + internal static class Config + { + public const string + Trick_CooldownRemaining = "Trick_CooldownRemaining", + Mug_NinkiGauge = "Mug_NinkiGauge", + Ninki_BhavaPooling = "Ninki_BhavaPooling", + Ninki_HellfrogPooling = "Ninki_HellfrogPooling", + NIN_SimpleMudra_Choice = "NIN_SimpleMudra_Choice", + Ninki_BunshinPoolingST = "Ninki_BunshinPoolingST", + Ninki_BunshinPoolingAoE = "Ninki_BunshinPoolingAoE", + Advanced_Trick_Cooldown = "Advanced_Trick_Cooldown", + Advanced_DotonTimer = "Advanced_DotonTimer", + Advanced_DotonHP = "Advanced_DotonHP", + BurnKazematoi = "BurnKazematoi", + Advanced_TCJEnderAoE = "Advanced_TCJEnderAoe", + Advanced_ChargePool = "Advanced_ChargePool", + SecondWindThresholdST = "SecondWindThresholdST", + ShadeShiftThresholdST = "ShadeShiftThresholdST", + BloodbathThresholdST = "BloodbathThresholdST", + SecondWindThresholdAoE = "SecondWindThresholdAoE", + ShadeShiftThresholdAoE = "ShadeShiftThresholdAoE", + BloodbathThresholdAoE = "BloodbathThresholdAoE", + NIN_VariantCure = "NIN_VariantCure"; + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.NIN_Simple_Mudras: + UserConfig.DrawRadioButton(NIN_SimpleMudra_Choice, "Mudra Path Set 1", + "1. Ten Mudras -> Fuma Shuriken, Raiton/Hyosho Ranryu, Suiton (Doton under Kassatsu).\nChi Mudras -> Fuma Shuriken, Hyoton, Huton.\nJin Mudras -> Fuma Shuriken, Katon/Goka Mekkyaku, Doton", + 1); + + UserConfig.DrawRadioButton(NIN_SimpleMudra_Choice, "Mudra Path Set 2", + "2. Ten Mudras -> Fuma Shuriken, Hyoton/Hyosho Ranryu, Doton.\nChi Mudras -> Fuma Shuriken, Katon, Suiton.\nJin Mudras -> Fuma Shuriken, Raiton/Goka Mekkyaku, Huton (Doton under Kassatsu).", + 2); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode: + UserConfig.DrawSliderInt(0, 10, BurnKazematoi, "Target HP% to dump all pooled Kazematoi below"); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_Bhavacakra: + UserConfig.DrawSliderInt(50, 100, Ninki_BhavaPooling, + "Set the minimal amount of Ninki required to have before spending on Bhavacakra."); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack: + UserConfig.DrawSliderInt(0, 21, Trick_CooldownRemaining, + "Set the amount of time remaining on Trick Attack cooldown before trying to set up with Suiton."); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_Bunshin: + UserConfig.DrawSliderInt(50, 100, Ninki_BunshinPoolingST, + "Set the amount of Ninki required to have before spending on Bunshin."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_Bunshin: + UserConfig.DrawSliderInt(50, 100, Ninki_BunshinPoolingAoE, + "Set the amount of Ninki required to have before spending on Bunshin."); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Cooldowns: + UserConfig.DrawSliderInt(0, 21, Advanced_Trick_Cooldown, + "Set the amount of time remaining on Trick Attack cooldown to start saving cooldowns."); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_SecondWind: + UserConfig.DrawSliderInt(0, 100, SecondWindThresholdST, + "Set a HP% threshold for when Second Wind will be used."); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_ShadeShift: + UserConfig.DrawSliderInt(0, 100, ShadeShiftThresholdST, + "Set a HP% threshold for when Shade Shift will be used."); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_Bloodbath: + UserConfig.DrawSliderInt(0, 100, BloodbathThresholdST, + "Set a HP% threshold for when Bloodbath will be used."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_SecondWind: + UserConfig.DrawSliderInt(0, 100, SecondWindThresholdAoE, + "Set a HP% threshold for when Second Wind will be used."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_ShadeShift: + UserConfig.DrawSliderInt(0, 100, ShadeShiftThresholdAoE, + "Set a HP% threshold for when Shade Shift will be used."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_Bloodbath: + UserConfig.DrawSliderInt(0, 100, BloodbathThresholdAoE, + "Set a HP% threshold for when Bloodbath will be used."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_HellfrogMedium: + UserConfig.DrawSliderInt(50, 100, Ninki_HellfrogPooling, + "Set the amount of Ninki required to have before spending on Hellfrog Medium."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_Ninjitsus_Doton: + UserConfig.DrawSliderInt(0, 18, Advanced_DotonTimer, + "Sets the amount of time remaining on Doton before casting again."); + + UserConfig.DrawSliderInt(0, 100, Advanced_DotonHP, + "Sets the max remaining HP percentage of the current target to cast Doton."); + + break; + + case CustomComboPreset.NIN_AoE_AdvancedMode_TCJ: + UserConfig.DrawRadioButton(Advanced_TCJEnderAoE, "Ten Chi Jin Ender 1", + "Ends Ten Chi Jin with Suiton.", 0); + + UserConfig.DrawRadioButton(Advanced_TCJEnderAoE, "Ten Chi Jin Ender 2", + "Ends Ten Chi Jin with Doton.\nIf you have Doton enabled, Ten Chi Jin will be delayed according to the settings in that feature.", + 1); + + break; + + case CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_Raiton: + UserConfig.DrawAdditionalBoolChoice(Advanced_ChargePool, "Pool Charges", + "Waits until at least 2 seconds before your 2nd charge or if Trick Attack debuff is on your target before spending."); + + break; + + case CustomComboPreset.NIN_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, NIN_VariantCure, "HP% to be at or under", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/NIN/NIN_Helper.cs b/XIVSlothCombo/Combos/PvE/NIN/NIN_Helper.cs new file mode 100644 index 000000000..52676fadd --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/NIN/NIN_Helper.cs @@ -0,0 +1,698 @@ +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.JobGauge.Types; +using ECommons.DalamudServices; +using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class NIN +{ + internal class NINHelper + { + internal static bool InMudra = false; + + internal static bool TrickDebuff => TargetHasTrickDebuff(); + + internal static bool MugDebuff => TargetHasMugDebuff(); + + private static bool TargetHasTrickDebuff() + { + return CustomComboFunctions.TargetHasEffect(Debuffs.TrickAttack) || + CustomComboFunctions.TargetHasEffect(Debuffs.KunaisBane); + } + + private static bool TargetHasMugDebuff() + { + return CustomComboFunctions.TargetHasEffect(Debuffs.Mug) || + CustomComboFunctions.TargetHasEffect(Debuffs.Dokumori); + } + } + + internal class MudraCasting + { + public enum MudraState + { + None, + CastingFumaShuriken, + CastingKaton, + CastingRaiton, + CastingHyoton, + CastingHuton, + CastingDoton, + CastingSuiton, + CastingGokaMekkyaku, + CastingHyoshoRanryu + } + + private MudraState currentMudra = MudraState.None; + + private bool justResetMudra; + + public MudraState CurrentMudra + { + get => currentMudra; + set + { + if (value == MudraState.None) + justResetMudra = true; + else + justResetMudra = false; + + currentMudra = value; + } + } + + /// Checks if the player is in a state to be able to cast a ninjitsu. + private static bool CanCast() + { + if (NINHelper.InMudra) return true; + + float gcd = CustomComboFunctions.GetCooldown(GustSlash).CooldownTotal; + + if (gcd == 0.5) return true; + + if (CustomComboFunctions.GetRemainingCharges(Ten) == 0 && + !CustomComboFunctions.HasEffect(Buffs.Mudra) && + !CustomComboFunctions.HasEffect(Buffs.Kassatsu)) + return false; + + return true; + } + + /// Simple method of casting Fuma Shuriken. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastFumaShuriken(ref uint actionID) + { + if (FumaShuriken.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingFumaShuriken) + { + if (!CanCast()) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Ten); + CurrentMudra = MudraState.CastingFumaShuriken; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Raiton. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastRaiton(ref uint actionID) + { + if (Raiton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingRaiton) + { + if (!CanCast()) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Chi); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Raiton) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Ten); + CurrentMudra = MudraState.CastingRaiton; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Katon. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastKaton(ref uint actionID) + { + if (Katon.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingKaton) + { + if (!CanCast()) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Ten); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Katon) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Chi); + CurrentMudra = MudraState.CastingKaton; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Hyoton. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastHyoton(ref uint actionID) + { + if (Hyoton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingHyoton) + { + if (!CanCast() || CustomComboFunctions.HasEffect(Buffs.Kassatsu)) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Jin); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Hyoton) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Ten); + CurrentMudra = MudraState.CastingHyoton; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Huton. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastHuton(ref uint actionID) + { + if (Huton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingHuton) + { + if (!CanCast()) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Jin); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Hyoton) + { + actionID = CustomComboFunctions.OriginalHook(Ten); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Huton) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Chi); + CurrentMudra = MudraState.CastingHuton; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Doton. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastDoton(ref uint actionID) + { + if (Doton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingDoton) + { + if (!CanCast()) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Jin); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Hyoton) + { + actionID = CustomComboFunctions.OriginalHook(Chi); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Doton) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Ten); + CurrentMudra = MudraState.CastingDoton; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Suiton. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastSuiton(ref uint actionID) + { + if (Suiton.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingSuiton) + { + if (!CanCast()) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Chi); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Raiton) + { + actionID = CustomComboFunctions.OriginalHook(Jin); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is Suiton) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Ten); + CurrentMudra = MudraState.CastingSuiton; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Goka Mekkyaku. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastGokaMekkyaku(ref uint actionID) + { + if (GokaMekkyaku.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingGokaMekkyaku) + { + if (!CanCast() || !CustomComboFunctions.HasEffect(Buffs.Kassatsu)) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Ten); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is GokaMekkyaku) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Chi); + CurrentMudra = MudraState.CastingGokaMekkyaku; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + /// Simple method of casting Hyosho Ranryu. + /// The actionID from the combo. + /// True if in a state to cast or continue the ninjitsu, modifies actionID to the step of the ninjitsu. + public bool CastHyoshoRanryu(ref uint actionID) + { + if (HyoshoRanryu.LevelChecked() && CurrentMudra is MudraState.None or MudraState.CastingHyoshoRanryu) + { + if (!CanCast() || !CustomComboFunctions.HasEffect(Buffs.Kassatsu)) + { + CurrentMudra = MudraState.None; + + return false; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is FumaShuriken) + { + actionID = CustomComboFunctions.OriginalHook(Jin); + + return true; + } + + if (CustomComboFunctions.OriginalHook(Ninjutsu) is HyoshoRanryu) + { + actionID = CustomComboFunctions.OriginalHook(Ninjutsu); + + return true; + } + + actionID = CustomComboFunctions.OriginalHook(Chi); + CurrentMudra = MudraState.CastingHyoshoRanryu; + + return true; + } + + CurrentMudra = MudraState.None; + + return false; + } + + public bool ContinueCurrentMudra(ref uint actionID) + { + if ((CustomComboFunctions.WasLastAction(FumaShuriken) || + CustomComboFunctions.WasLastAction(Katon) || + CustomComboFunctions.WasLastAction(Raiton) || + CustomComboFunctions.WasLastAction(Hyoton) || + CustomComboFunctions.WasLastAction(Huton) || + CustomComboFunctions.WasLastAction(Doton) || + CustomComboFunctions.WasLastAction(Suiton) || + CustomComboFunctions.WasLastAction(GokaMekkyaku) || + CustomComboFunctions.WasLastAction(HyoshoRanryu)) && + !justResetMudra) + CurrentMudra = MudraState.None; + + return CurrentMudra switch + { + MudraState.None => false, + MudraState.CastingFumaShuriken => CastFumaShuriken(ref actionID), + MudraState.CastingKaton => CastKaton(ref actionID), + MudraState.CastingRaiton => CastRaiton(ref actionID), + MudraState.CastingHyoton => CastHyoton(ref actionID), + MudraState.CastingHuton => CastHuton(ref actionID), + MudraState.CastingDoton => CastDoton(ref actionID), + MudraState.CastingSuiton => CastSuiton(ref actionID), + MudraState.CastingGokaMekkyaku => CastGokaMekkyaku(ref actionID), + MudraState.CastingHyoshoRanryu => CastHyoshoRanryu(ref actionID), + _ => false + }; + } + } + + internal class NINOpenerLogic + { + private OpenerState currentState = OpenerState.OpenerFinished; + + private bool openerEventsSetup; + + private uint openerStep = 1; + + public uint PrePullStep = 1; + + private static uint OpenerLevel => 100; + + public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; + + private static bool CanOpener => HasCooldowns() && LevelChecked; + + public OpenerState CurrentState + { + get => currentState; + set + { + if (value != currentState) + { + if (value == OpenerState.PrePull) PrePullStep = 1; + if (value == OpenerState.InOpener) OpenerStep = 1; + + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + { + PrePullStep = 0; + OpenerStep = 0; + } + + currentState = value; + } + } + } + + public uint OpenerStep + { + get => openerStep; + set + { + if (value != openerStep) Svc.Log.Debug($"{value}"); + openerStep = value; + } + } + + private static bool HasCooldowns() + { + if (CustomComboFunctions.GetRemainingCharges(Ten) < 1) return false; + if (CustomComboFunctions.IsOnCooldown(Mug)) return false; + if (CustomComboFunctions.IsOnCooldown(TenChiJin)) return false; + if (CustomComboFunctions.IsOnCooldown(PhantomKamaitachi)) return false; + if (CustomComboFunctions.IsOnCooldown(Bunshin)) return false; + if (CustomComboFunctions.IsOnCooldown(DreamWithinADream)) return false; + if (CustomComboFunctions.IsOnCooldown(Kassatsu)) return false; + if (CustomComboFunctions.IsOnCooldown(TrickAttack)) return false; + + return true; + } + + private bool DoPrePullSteps(ref uint actionID, MudraCasting mudraState) + { + if (!LevelChecked) return false; + + if (CanOpener && PrePullStep == 0 && !CustomComboFunctions.InCombat()) CurrentState = OpenerState.PrePull; + + if (CurrentState == OpenerState.PrePull) + { + if (CustomComboFunctions.WasLastAction(Suiton) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + else if (PrePullStep == 1) mudraState.CastSuiton(ref actionID); + + ////Failure states + //if (PrePullStep is (1 or 2) && CustomComboFunctions.InCombat()) { mudraState.CurrentMudra = MudraCasting.MudraState.None; ResetOpener(); } + + return true; + } + + PrePullStep = 0; + + return false; + } + + private bool DoOpener(ref uint actionID, MudraCasting mudraState) + { + if (!LevelChecked) return false; + + if (CurrentState == OpenerState.InOpener) + { + bool inLateWeaveWindow = CustomComboFunctions.CanDelayedWeave(GustSlash, 1, 0); + + if (CustomComboFunctions.WasLastAction(Kassatsu) && OpenerStep == 1) OpenerStep++; + else if (OpenerStep == 1) actionID = CustomComboFunctions.OriginalHook(Kassatsu); + + if (CustomComboFunctions.WasLastAction(SpinningEdge) && OpenerStep == 2) OpenerStep++; + else if (OpenerStep == 2) actionID = CustomComboFunctions.OriginalHook(SpinningEdge); + + if (CustomComboFunctions.WasLastAction(GustSlash) && OpenerStep == 3) OpenerStep++; + else if (OpenerStep == 3) actionID = CustomComboFunctions.OriginalHook(GustSlash); + + if (CustomComboFunctions.WasLastAction(CustomComboFunctions.OriginalHook(Mug)) && OpenerStep == 4) + OpenerStep++; + else if (OpenerStep == 4) actionID = CustomComboFunctions.OriginalHook(Mug); + + if (CustomComboFunctions.WasLastAction(Bunshin) && OpenerStep == 5) OpenerStep++; + else if (OpenerStep == 5) actionID = CustomComboFunctions.OriginalHook(Bunshin); + + if (CustomComboFunctions.WasLastAction(PhantomKamaitachi) && OpenerStep == 6) OpenerStep++; + else if (OpenerStep == 6) actionID = CustomComboFunctions.OriginalHook(PhantomKamaitachi); + + if (CustomComboFunctions.WasLastAction(ArmorCrush) && OpenerStep == 7) OpenerStep++; + else if (OpenerStep == 7) actionID = CustomComboFunctions.OriginalHook(ArmorCrush); + + if (CustomComboFunctions.WasLastAction(CustomComboFunctions.OriginalHook(TrickAttack)) && + OpenerStep == 8) OpenerStep++; + else if (OpenerStep == 8 && inLateWeaveWindow) + actionID = CustomComboFunctions.OriginalHook(TrickAttack); + + if (CustomComboFunctions.WasLastAction(HyoshoRanryu) && OpenerStep == 9) OpenerStep++; + else if (OpenerStep == 9) mudraState.CastHyoshoRanryu(ref actionID); + + if (CustomComboFunctions.WasLastAction(DreamWithinADream) && OpenerStep == 10) OpenerStep++; + else if (OpenerStep == 10) actionID = CustomComboFunctions.OriginalHook(DreamWithinADream); + + if (CustomComboFunctions.WasLastAction(Raiton) && OpenerStep == 11) OpenerStep++; + else if (OpenerStep == 11) mudraState.CastRaiton(ref actionID); + + if (CustomComboFunctions.WasLastAction(TenChiJin) && OpenerStep == 12) OpenerStep++; + else if (OpenerStep == 12) actionID = CustomComboFunctions.OriginalHook(TenChiJin); + + if (CustomComboFunctions.WasLastAction(TCJFumaShurikenTen) && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = CustomComboFunctions.OriginalHook(Ten); + + if (CustomComboFunctions.WasLastAction(TCJRaiton) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = CustomComboFunctions.OriginalHook(Chi); + + if (CustomComboFunctions.WasLastAction(TCJSuiton) && OpenerStep == 15) OpenerStep++; + else if (OpenerStep == 15) actionID = CustomComboFunctions.OriginalHook(Jin); + + if (CustomComboFunctions.WasLastAction(Meisui) && OpenerStep == 16) OpenerStep++; + else if (OpenerStep == 16) actionID = CustomComboFunctions.OriginalHook(Meisui); + + if (CustomComboFunctions.WasLastAction(FleetingRaiju) && OpenerStep == 17) OpenerStep++; + else if (OpenerStep == 17) actionID = CustomComboFunctions.OriginalHook(FleetingRaiju); + + if (CustomComboFunctions.WasLastAction(ZeshoMeppo) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = CustomComboFunctions.OriginalHook(Bhavacakra); + + if (CustomComboFunctions.WasLastAction(TenriJendo) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = CustomComboFunctions.OriginalHook(TenriJendo); + + if (CustomComboFunctions.WasLastAction(FleetingRaiju) && OpenerStep == 20) OpenerStep++; + else if (OpenerStep == 20) actionID = CustomComboFunctions.OriginalHook(FleetingRaiju); + + if (CustomComboFunctions.WasLastAction(CustomComboFunctions.OriginalHook(Bhavacakra)) && + OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = CustomComboFunctions.OriginalHook(Bhavacakra); + + if (CustomComboFunctions.WasLastAction(Raiton) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) mudraState.CastRaiton(ref actionID); + + if (CustomComboFunctions.WasLastAction(FleetingRaiju) && OpenerStep == 23) + CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 23) actionID = CustomComboFunctions.OriginalHook(FleetingRaiju); + + //Failure states + if ((OpenerStep is 13 or 14 or 15 && CustomComboFunctions.IsMoving) || + (OpenerStep is 8 && !CustomComboFunctions.HasEffect(Buffs.ShadowWalker)) || + (OpenerStep is 18 or 21 && CustomComboFunctions.GetJobGauge().Ninki < 40) || + (OpenerStep is 17 or 20 && !CustomComboFunctions.HasEffect(Buffs.RaijuReady)) || + (OpenerStep is 9 && !CustomComboFunctions.HasEffect(Buffs.Kassatsu))) + ResetOpener(); + + return true; + } + + return false; + } + + private void ResetOpener() + { + CurrentState = OpenerState.FailedOpener; + } + + public bool DoFullOpener(ref uint actionID, MudraCasting mudraState) + { + if (!LevelChecked) return false; + + if (!openerEventsSetup) + { + Svc.Condition.ConditionChange += CheckCombatStatus; + openerEventsSetup = true; + } + + if (CurrentState == OpenerState.PrePull || CurrentState == OpenerState.FailedOpener) + if (DoPrePullSteps(ref actionID, mudraState)) + return true; + + if (CurrentState == OpenerState.InOpener) + if (DoOpener(ref actionID, mudraState)) + return true; + + if (CurrentState == OpenerState.OpenerFinished && !CustomComboFunctions.InCombat()) + ResetOpener(); + + return false; + } + + internal void Dispose() + { + Svc.Condition.ConditionChange -= CheckCombatStatus; + } + + private void CheckCombatStatus(ConditionFlag flag, bool value) + { + if (flag == ConditionFlag.InCombat && value == false) ResetOpener(); + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT/PCT.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/PCT.cs rename to XIVSlothCombo/Combos/PvE/PCT/PCT.cs index 2b3579f4d..5ca17c329 100644 --- a/XIVSlothCombo/Combos/PvE/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT/PCT.cs @@ -1,15 +1,13 @@ using Dalamud.Game.ClientState.JobGauge.Types; -using XIVSlothCombo.Combos.JobHelpers; using XIVSlothCombo.Core; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; namespace XIVSlothCombo.Combos.PvE { - internal class PCT + internal partial class PCT { public const byte JobID = 42; @@ -73,28 +71,7 @@ public static class Debuffs { } - - public static class Config - { - public static UserInt - CombinedAetherhueChoices = new("CombinedAetherhueChoices"), - PCT_ST_AdvancedMode_LucidOption = new("PCT_ST_AdvancedMode_LucidOption", 6500), - PCT_AoE_AdvancedMode_HolyinWhiteOption = new("PCT_AoE_AdvancedMode_HolyinWhiteOption", 0), - PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500), - PCT_VariantCure = new("PCT_VariantCure"), - PCT_ST_CreatureStop = new("PCT_ST_CreatureStop"), - PCT_AoE_CreatureStop = new("PCT_AoE_CreatureStop"), - PCT_ST_WeaponStop = new("PCT_ST_WeaponStop"), - PCT_AoE_WeaponStop = new("PCT_AoE_WeaponStop"), - PCT_ST_LandscapeStop = new("PCT_ST_LandscapeStop"), - PCT_AoE_LandscapeStop = new("PCT_AoE_LandscapeStop"); - - public static UserBool - CombinedMotifsMog = new("CombinedMotifsMog"), - CombinedMotifsMadeen = new("CombinedMotifsMadeen"), - CombinedMotifsWeapon = new("CombinedMotifsWeapon"); - } - + internal class PCT_ST_SimpleMode : CustomCombo { diff --git a/XIVSlothCombo/Combos/PvE/PCT/PCT_Config.cs b/XIVSlothCombo/Combos/PvE/PCT/PCT_Config.cs new file mode 100644 index 000000000..6c9e7d89f --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/PCT/PCT_Config.cs @@ -0,0 +1,125 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class PCT +{ + internal static class Config + { + public static UserInt + CombinedAetherhueChoices = new("CombinedAetherhueChoices"), + PCT_ST_AdvancedMode_LucidOption = new("PCT_ST_AdvancedMode_LucidOption", 6500), + PCT_AoE_AdvancedMode_HolyinWhiteOption = new("PCT_AoE_AdvancedMode_HolyinWhiteOption", 0), + PCT_AoE_AdvancedMode_LucidOption = new("PCT_AoE_AdvancedMode_LucidOption", 6500), + PCT_VariantCure = new("PCT_VariantCure"), + PCT_ST_CreatureStop = new("PCT_ST_CreatureStop"), + PCT_AoE_CreatureStop = new("PCT_AoE_CreatureStop"), + PCT_ST_WeaponStop = new("PCT_ST_WeaponStop"), + PCT_AoE_WeaponStop = new("PCT_AoE_WeaponStop"), + PCT_ST_LandscapeStop = new("PCT_ST_LandscapeStop"), + PCT_AoE_LandscapeStop = new("PCT_AoE_LandscapeStop"); + + public static UserBool + CombinedMotifsMog = new("CombinedMotifsMog"), + CombinedMotifsMadeen = new("CombinedMotifsMadeen"), + CombinedMotifsWeapon = new("CombinedMotifsWeapon"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.CombinedAetherhues: + UserConfig.DrawRadioButton(CombinedAetherhueChoices, "Both Single Target & AoE", + $"Replaces both {FireInRed.ActionName()} & {FireIIinRed.ActionName()}", 0); + + UserConfig.DrawRadioButton(CombinedAetherhueChoices, "Single Target Only", + $"Replace only {FireInRed.ActionName()}", 1); + + UserConfig.DrawRadioButton(CombinedAetherhueChoices, "AoE Only", + $"Replace only {FireIIinRed.ActionName()}", 2); + + break; + + case CustomComboPreset.CombinedMotifs: + UserConfig.DrawAdditionalBoolChoice(CombinedMotifsMog, $"{MogoftheAges.ActionName()} Feature", + $"Add {MogoftheAges.ActionName()} when fully drawn and off cooldown."); + + UserConfig.DrawAdditionalBoolChoice(CombinedMotifsMadeen, + $"{RetributionoftheMadeen.ActionName()} Feature", + $"Add {RetributionoftheMadeen.ActionName()} when fully drawn and off cooldown."); + + UserConfig.DrawAdditionalBoolChoice(CombinedMotifsWeapon, $"{HammerStamp.ActionName()} Feature", + $"Add {HammerStamp.ActionName()} when under the effect of {Buffs.HammerTime.StatusName()}."); + + break; + + case CustomComboPreset.PCT_ST_AdvancedMode_LucidDreaming: + UserConfig.DrawSliderInt(0, 10000, PCT_ST_AdvancedMode_LucidOption, + "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); + + break; + + case CustomComboPreset.PCT_AoE_AdvancedMode_HolyinWhite: + UserConfig.DrawSliderInt(0, 5, PCT_AoE_AdvancedMode_HolyinWhiteOption, + "How many charges to keep ready? (0 = Use all)"); + + break; + + case CustomComboPreset.PCT_AoE_AdvancedMode_LucidDreaming: + UserConfig.DrawSliderInt(0, 10000, PCT_AoE_AdvancedMode_LucidOption, + "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); + + break; + + case CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif: + UserConfig.DrawSliderInt(0, 10, PCT_ST_LandscapeStop, "Health % to stop Drawing Motif"); + + break; + + case CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif: + UserConfig.DrawSliderInt(0, 10, PCT_ST_CreatureStop, "Health % to stop Drawing Motif"); + + break; + + case CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif: + UserConfig.DrawSliderInt(0, 10, PCT_ST_WeaponStop, "Health % to stop Drawing Motif"); + + break; + + case CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif: + UserConfig.DrawSliderInt(0, 10, PCT_AoE_LandscapeStop, "Health % to stop Drawing Motif"); + + break; + + case CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif: + UserConfig.DrawSliderInt(0, 10, PCT_AoE_CreatureStop, "Health % to stop Drawing Motif"); + + break; + + case CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif: + UserConfig.DrawSliderInt(0, 10, PCT_AoE_WeaponStop, "Health % to stop Drawing Motif"); + + break; + + case CustomComboPreset.PCT_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, PCT_VariantCure, "HP% to be at or under", 200); + + break; + + // PvP + case CustomComboPreset.PCTPvP_BurstControl: + UserConfig.DrawSliderInt(1, 100, PCTPvP.Config.PCTPvP_BurstHP, "Target HP%", 200); + + break; + + case CustomComboPreset.PCTPvP_TemperaCoat: + UserConfig.DrawSliderInt(1, 100, PCTPvP.Config.PCTPvP_TemperaHP, "Player HP%", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/JobHelpers/PCT.cs b/XIVSlothCombo/Combos/PvE/PCT/PCT_Helper.cs similarity index 82% rename from XIVSlothCombo/Combos/JobHelpers/PCT.cs rename to XIVSlothCombo/Combos/PvE/PCT/PCT_Helper.cs index 01994dea9..3ce2223b5 100644 --- a/XIVSlothCombo/Combos/JobHelpers/PCT.cs +++ b/XIVSlothCombo/Combos/PvE/PCT/PCT_Helper.cs @@ -1,73 +1,41 @@ using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; +using CanvasFlags = Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags; -namespace XIVSlothCombo.Combos.JobHelpers -{ +namespace XIVSlothCombo.Combos.PvE; +internal partial class PCT +{ #region Lvl 100 Opener + internal class PCTOpenerLogicLvl100 : PCT { + private OpenerState currentState = OpenerState.PrePull; + public uint OpenerStep; - private static bool HasCooldowns() - { - if (!CustomComboFunctions.ActionReady(StarryMuse)) - return false; - - if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 3) - return false; - - if (CustomComboFunctions.GetRemainingCharges(SteelMuse) < 2) - return false; - return true; - } - private static bool HasMotifs() - { - var gauge = CustomComboFunctions.GetJobGauge(); - - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Pom)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Weapon)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Landscape)) - return false; - if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) - return false; - return true; - } + public uint PrePullStep; private static uint OpenerLevel => 100; - public uint PrePullStep = 0; - - public uint OpenerStep = 0; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && HasMotifs() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; - public OpenerState CurrentState { - get - { - return currentState; - } + get => currentState; set { if (value != currentState) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) @@ -82,24 +50,52 @@ public OpenerState CurrentState } } + private static bool HasCooldowns() + { + if (!CustomComboFunctions.ActionReady(StarryMuse)) + return false; + + if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 3) + return false; + + if (CustomComboFunctions.GetRemainingCharges(SteelMuse) < 2) + return false; + + return true; + } + + private static bool HasMotifs() + { + PCTGauge gauge = CustomComboFunctions.GetJobGauge(); + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Pom)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Weapon)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Landscape)) + return false; + + if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) + return false; + + return true; + } + private bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns() && !HasMotifs()) - { - PrePullStep = 0; - } + if (!HasCooldowns() && !HasMotifs()) PrePullStep = 0; if (CurrentState == OpenerState.PrePull) { - if (CustomComboFunctions.LocalPlayer.CastActionId == RainbowDrip && PrePullStep == 1) CurrentState = OpenerState.InOpener; + if (CustomComboFunctions.LocalPlayer.CastActionId == RainbowDrip && PrePullStep == 1) + CurrentState = OpenerState.InOpener; else if (PrePullStep == 1) actionID = RainbowDrip; if (CustomComboFunctions.InCombat()) @@ -111,6 +107,7 @@ private bool DoPrePullSteps(ref uint actionID) return true; } PrePullStep = 0; + return false; } @@ -119,7 +116,8 @@ private bool DoOpener(ref uint actionID) if (!LevelChecked) return false; - bool isEarlyOpenerEnabled = CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); + bool isEarlyOpenerEnabled = + CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); if (currentState == OpenerState.InOpener) { @@ -141,7 +139,8 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.LocalPlayer.CastActionId == CustomComboFunctions.OriginalHook(CreatureMotif) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.LocalPlayer.CastActionId == + CustomComboFunctions.OriginalHook(CreatureMotif) && OpenerStep == adjustedStep) OpenerStep++; else if (OpenerStep == adjustedStep) actionID = CustomComboFunctions.OriginalHook(CreatureMotif); adjustedStep++; @@ -156,7 +155,8 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = SubtractivePalette; adjustedStep++; @@ -171,7 +171,8 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; @@ -215,6 +216,7 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.FailedOpener; Svc.Log.Warning("Opener Failed due to timeout."); + return false; } @@ -222,15 +224,16 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.OpenerFinished; Svc.Log.Information("Opener completed successfully."); + return false; } return true; } + return false; } - private void ResetOpener() { PrePullStep = 0; @@ -247,80 +250,47 @@ public bool DoFullOpener(ref uint actionID) return true; if (CurrentState == OpenerState.InOpener) - { if (DoOpener(ref actionID)) return true; - } if (!CustomComboFunctions.InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; } + return false; } } + #endregion - #region Lvl 92 Opener + #region Lvl 92 Opener + internal class PCTOpenerLogicLvl92 : PCT { - private static bool HasCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(SteelMuse) < 2) - return false; - - if (!CustomComboFunctions.ActionReady(ScenicMuse)) - return false; - - if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 2) - return false; - - return true; - } + private OpenerState currentState = OpenerState.PrePull; - private static bool HasMotifs() - { - var gauge = CustomComboFunctions.GetJobGauge(); + public uint OpenerStep; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Pom)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Weapon)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Landscape)) - return false; - if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) - return false; - return true; - } + public uint PrePullStep; private static uint OpenerLevel => 92; - public uint PrePullStep = 0; - - public uint OpenerStep = 0; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && HasMotifs() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; - public OpenerState CurrentState { - get - { - return currentState; - } + get => currentState; set { if (value != currentState) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) @@ -335,24 +305,52 @@ public OpenerState CurrentState } } + private static bool HasCooldowns() + { + if (CustomComboFunctions.GetRemainingCharges(SteelMuse) < 2) + return false; + + if (!CustomComboFunctions.ActionReady(ScenicMuse)) + return false; + + if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 2) + return false; + + return true; + } + + private static bool HasMotifs() + { + PCTGauge gauge = CustomComboFunctions.GetJobGauge(); + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Pom)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Weapon)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Landscape)) + return false; + + if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) + return false; + + return true; + } + private bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns() && !HasMotifs()) - { - PrePullStep = 0; - } + if (!HasCooldowns() && !HasMotifs()) PrePullStep = 0; if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (CustomComboFunctions.LocalPlayer.CastActionId == RainbowDrip && PrePullStep == 1) CurrentState = OpenerState.InOpener; + if (CustomComboFunctions.LocalPlayer.CastActionId == RainbowDrip && PrePullStep == 1) + CurrentState = OpenerState.InOpener; else if (PrePullStep == 1) actionID = RainbowDrip; if (CustomComboFunctions.InCombat()) @@ -364,6 +362,7 @@ private bool DoPrePullSteps(ref uint actionID) return true; } PrePullStep = 0; + return false; } @@ -374,7 +373,8 @@ private bool DoOpener(ref uint actionID) if (currentState == OpenerState.InOpener) { - bool isEarlyOpenerEnabled = CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); + bool isEarlyOpenerEnabled = + CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); if (CustomComboFunctions.WasLastAction(StrikingMuse) && OpenerStep == 1) OpenerStep++; else if (OpenerStep == 1) actionID = StrikingMuse; @@ -392,7 +392,8 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.LocalPlayer.CastActionId == CustomComboFunctions.OriginalHook(CreatureMotif) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.LocalPlayer.CastActionId == + CustomComboFunctions.OriginalHook(CreatureMotif) && OpenerStep == adjustedStep) OpenerStep++; else if (OpenerStep == adjustedStep) actionID = CustomComboFunctions.OriginalHook(CreatureMotif); adjustedStep++; @@ -407,7 +408,8 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = SubtractivePalette; adjustedStep++; @@ -422,7 +424,8 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; @@ -460,12 +463,14 @@ private bool DoOpener(ref uint actionID) if (CustomComboFunctions.WasLastAction(RainbowDrip) && OpenerStep == adjustedStep) OpenerStep++; else if (OpenerStep == adjustedStep) actionID = RainbowDrip; - Svc.Log.Debug($"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); + Svc.Log.Debug( + $"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); if (ActionWatching.TimeSinceLastAction.TotalSeconds > 3) { CurrentState = OpenerState.FailedOpener; Svc.Log.Warning("Opener Failed due to timeout."); + return false; } @@ -473,15 +478,16 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.OpenerFinished; Svc.Log.Information("Opener completed successfully."); + return false; } return true; } + return false; } - private void ResetOpener() { PrePullStep = 0; @@ -498,80 +504,47 @@ public bool DoFullOpener(ref uint actionID) return true; if (CurrentState == OpenerState.InOpener) - { if (DoOpener(ref actionID)) return true; - } if (!CustomComboFunctions.InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; } + return false; } } + #endregion #region Lvl 90 Opener + internal class PCTOpenerLogicLvl90 : PCT { - private static bool HasCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(SteelMuse) < 2) - return false; - - if (!CustomComboFunctions.ActionReady(ScenicMuse)) - return false; - - if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 2) - return false; + private OpenerState currentState = OpenerState.PrePull; - return true; - } + public uint OpenerStep; - private static bool HasMotifs() - { - var gauge = CustomComboFunctions.GetJobGauge(); - - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Pom)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Weapon)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Landscape)) - return false; - if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) - return false; - return true; - } + public uint PrePullStep; private static uint OpenerLevel => 90; - public uint PrePullStep = 0; - - public uint OpenerStep = 0; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && HasMotifs() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; - public OpenerState CurrentState { - get - { - return currentState; - } + get => currentState; set { if (value != currentState) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) @@ -586,24 +559,52 @@ public OpenerState CurrentState } } + private static bool HasCooldowns() + { + if (CustomComboFunctions.GetRemainingCharges(SteelMuse) < 2) + return false; + + if (!CustomComboFunctions.ActionReady(ScenicMuse)) + return false; + + if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 2) + return false; + + return true; + } + + private static bool HasMotifs() + { + PCTGauge gauge = CustomComboFunctions.GetJobGauge(); + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Pom)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Weapon)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Landscape)) + return false; + + if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) + return false; + + return true; + } + private bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns() && !HasMotifs()) - { - PrePullStep = 0; - } + if (!HasCooldowns() && !HasMotifs()) PrePullStep = 0; if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (CustomComboFunctions.WasLastAction(FireInRed) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + if (CustomComboFunctions.WasLastAction(FireInRed) && PrePullStep == 1) + CurrentState = OpenerState.InOpener; else if (PrePullStep == 1) actionID = FireInRed; if (!HasMotifs()) @@ -612,6 +613,7 @@ private bool DoPrePullSteps(ref uint actionID) return true; } PrePullStep = 0; + return false; } @@ -626,10 +628,12 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.FailedOpener; Svc.Log.Warning("Opener Failed due to not being in combat."); + return false; } - bool isEarlyOpenerEnabled = CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); + bool isEarlyOpenerEnabled = + CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); if (CustomComboFunctions.WasLastAction(StrikingMuse) && OpenerStep == 1) OpenerStep++; else if (OpenerStep == 1) actionID = StrikingMuse; @@ -682,58 +686,69 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = SubtractivePalette; adjustedStep++; if (!isEarlyOpenerEnabled) { - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; - if (CustomComboFunctions.WasLastAction(CometinBlack) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(CometinBlack) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = CometinBlack; adjustedStep++; - if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = BlizzardinCyan; adjustedStep++; - if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == adjustedStep) actionID = StoneinYellow; } else { - if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = StoneinYellow; adjustedStep++; - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; - if (CustomComboFunctions.WasLastAction(CometinBlack) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(CometinBlack) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = CometinBlack; adjustedStep++; - if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == adjustedStep) actionID = BlizzardinCyan; } - Svc.Log.Debug($"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); + Svc.Log.Debug( + $"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); if (ActionWatching.TimeSinceLastAction.TotalSeconds > 3) { CurrentState = OpenerState.FailedOpener; Svc.Log.Warning("Opener Failed due to timeout."); + return false; } @@ -741,15 +756,16 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.OpenerFinished; Svc.Log.Information("Opener completed successfully."); + return false; } return true; } + return false; } - private void ResetOpener() { PrePullStep = 0; @@ -766,80 +782,47 @@ public bool DoFullOpener(ref uint actionID) return true; if (CurrentState == OpenerState.InOpener) - { if (DoOpener(ref actionID)) return true; - } if (!CustomComboFunctions.InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; } + return false; } } + #endregion #region Lvl 80 Opener + internal class PCTOpenerLogicLvl80 : PCT { - private static bool HasCooldowns() - { - if (!CustomComboFunctions.ActionReady(SteelMuse)) - return false; - - if (!CustomComboFunctions.ActionReady(ScenicMuse)) - return false; + private OpenerState currentState = OpenerState.PrePull; - if (!CustomComboFunctions.ActionReady(LivingMuse)) - return false; + public uint OpenerStep; - return true; - } - - private static bool HasMotifs() - { - var gauge = CustomComboFunctions.GetJobGauge(); - - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Pom)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Weapon)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Landscape)) - return false; - if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) - return false; - return true; - } + public uint PrePullStep; private static uint OpenerLevel => 80; - public uint PrePullStep = 0; - - public uint OpenerStep = 0; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && HasMotifs() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; - public OpenerState CurrentState { - get - { - return currentState; - } + get => currentState; set { if (value != currentState) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) @@ -854,24 +837,52 @@ public OpenerState CurrentState } } + private static bool HasCooldowns() + { + if (!CustomComboFunctions.ActionReady(SteelMuse)) + return false; + + if (!CustomComboFunctions.ActionReady(ScenicMuse)) + return false; + + if (!CustomComboFunctions.ActionReady(LivingMuse)) + return false; + + return true; + } + + private static bool HasMotifs() + { + PCTGauge gauge = CustomComboFunctions.GetJobGauge(); + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Pom)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Weapon)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Landscape)) + return false; + + if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) + return false; + + return true; + } + private bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns() && !HasMotifs()) - { - PrePullStep = 0; - } + if (!HasCooldowns() && !HasMotifs()) PrePullStep = 0; if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (CustomComboFunctions.WasLastAction(FireInRed) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + if (CustomComboFunctions.WasLastAction(FireInRed) && PrePullStep == 1) + CurrentState = OpenerState.InOpener; else if (PrePullStep == 1) actionID = FireInRed; if (!HasMotifs()) @@ -880,6 +891,7 @@ private bool DoPrePullSteps(ref uint actionID) return true; } PrePullStep = 0; + return false; } @@ -890,7 +902,8 @@ private bool DoOpener(ref uint actionID) if (currentState == OpenerState.InOpener && CustomComboFunctions.InCombat()) { - bool isEarlyOpenerEnabled = CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); + bool isEarlyOpenerEnabled = + CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); if (CustomComboFunctions.WasLastAction(StrikingMuse) && OpenerStep == 1) OpenerStep++; else if (OpenerStep == 1) actionID = StrikingMuse; @@ -927,20 +940,18 @@ private bool DoOpener(ref uint actionID) else if (OpenerStep == adjustedStep) actionID = WingedMuse; adjustedStep++; - if ((CustomComboFunctions.WasLastAction(HammerStamp) || CustomComboFunctions.WasLastAction(HammerBrush)) && OpenerStep == adjustedStep) + + if ((CustomComboFunctions.WasLastAction(HammerStamp) || + CustomComboFunctions.WasLastAction(HammerBrush)) && OpenerStep == adjustedStep) { OpenerStep++; } else if (OpenerStep == adjustedStep) { if (HammerBrush.LevelChecked()) - { actionID = HammerBrush; - } else - { actionID = HammerStamp; - } } adjustedStep++; @@ -949,67 +960,73 @@ private bool DoOpener(ref uint actionID) else if (OpenerStep == adjustedStep) actionID = MogoftheAges; adjustedStep++; - if ((CustomComboFunctions.WasLastAction(HammerStamp) || CustomComboFunctions.WasLastAction(PolishingHammer)) && OpenerStep == adjustedStep) + + if ((CustomComboFunctions.WasLastAction(HammerStamp) || + CustomComboFunctions.WasLastAction(PolishingHammer)) && OpenerStep == adjustedStep) { OpenerStep++; } else if (OpenerStep == adjustedStep) { if (PolishingHammer.LevelChecked()) - { actionID = PolishingHammer; - } else - { actionID = HammerStamp; - } } adjustedStep++; - if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = SubtractivePalette; adjustedStep++; if (!isEarlyOpenerEnabled) { - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; - if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = BlizzardinCyan; adjustedStep++; - if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == adjustedStep) actionID = StoneinYellow; } else { - if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = StoneinYellow; adjustedStep++; - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; - if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == adjustedStep) actionID = BlizzardinCyan; } - - Svc.Log.Debug($"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); + Svc.Log.Debug( + $"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); if (ActionWatching.TimeSinceLastAction.TotalSeconds > 4) { CurrentState = OpenerState.FailedOpener; Svc.Log.Warning("Opener Failed due to timeout."); + return false; } @@ -1017,15 +1034,16 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.OpenerFinished; Svc.Log.Information("Opener completed successfully."); + return false; } return true; } + return false; } - private void ResetOpener() { PrePullStep = 0; @@ -1042,78 +1060,47 @@ public bool DoFullOpener(ref uint actionID) return true; if (CurrentState == OpenerState.InOpener) - { if (DoOpener(ref actionID)) return true; - } if (!CustomComboFunctions.InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; } + return false; } } + #endregion #region Lvl 70 Opener + internal class PCTOpenerLogicLvl70 : PCT { - private static bool HasCooldowns() - { - if (!CustomComboFunctions.ActionReady(SteelMuse)) - return false; + private OpenerState currentState = OpenerState.PrePull; - if (!CustomComboFunctions.ActionReady(ScenicMuse)) - return false; + public uint OpenerStep; - if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 2) - return false; - - return true; - } - - private static bool HasMotifs() - { - var gauge = CustomComboFunctions.GetJobGauge(); - - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Pom)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Weapon)) - return false; - if (!gauge.CanvasFlags.HasFlag(Dalamud.Game.ClientState.JobGauge.Enums.CanvasFlags.Landscape)) - return false; - if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) - return false; - return true; - } + public uint PrePullStep; private static uint OpenerLevel => 70; - public uint PrePullStep = 0; - - public uint OpenerStep = 0; public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; - private static bool CanOpener => HasCooldowns() && HasMotifs() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; + private static bool CanOpener => HasCooldowns() && HasMotifs() && LevelChecked; public OpenerState CurrentState { - get - { - return currentState; - } + get => currentState; set { if (value != currentState) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) @@ -1128,24 +1115,52 @@ public OpenerState CurrentState } } + private static bool HasCooldowns() + { + if (!CustomComboFunctions.ActionReady(SteelMuse)) + return false; + + if (!CustomComboFunctions.ActionReady(ScenicMuse)) + return false; + + if (CustomComboFunctions.GetRemainingCharges(LivingMuse) < 2) + return false; + + return true; + } + + private static bool HasMotifs() + { + PCTGauge gauge = CustomComboFunctions.GetJobGauge(); + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Pom)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Weapon)) + return false; + + if (!gauge.CanvasFlags.HasFlag(CanvasFlags.Landscape)) + return false; + + if (CustomComboFunctions.HasEffect(Buffs.SubtractivePalette)) + return false; + + return true; + } + private bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns() && !HasMotifs()) - { - PrePullStep = 0; - } + if (!HasCooldowns() && !HasMotifs()) PrePullStep = 0; if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (CustomComboFunctions.WasLastAction(FireInRed) && PrePullStep == 1) CurrentState = OpenerState.InOpener; + if (CustomComboFunctions.WasLastAction(FireInRed) && PrePullStep == 1) + CurrentState = OpenerState.InOpener; else if (PrePullStep == 1) actionID = FireInRed; if (!HasMotifs()) @@ -1154,6 +1169,7 @@ private bool DoPrePullSteps(ref uint actionID) return true; } PrePullStep = 0; + return false; } @@ -1164,7 +1180,8 @@ private bool DoOpener(ref uint actionID) if (currentState == OpenerState.InOpener) { - bool isEarlyOpenerEnabled = CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); + bool isEarlyOpenerEnabled = + CustomComboFunctions.IsEnabled(CustomComboPreset.PCT_ST_Advanced_Openers_EarlyOpener); if (CustomComboFunctions.WasLastAction(StrikingMuse) && OpenerStep == 1) OpenerStep++; else if (OpenerStep == 1) actionID = StrikingMuse; @@ -1217,48 +1234,57 @@ private bool DoOpener(ref uint actionID) adjustedStep++; - if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(SubtractivePalette) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = SubtractivePalette; adjustedStep++; if (!isEarlyOpenerEnabled) { - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; - if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = BlizzardinCyan; adjustedStep++; - if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == adjustedStep) actionID = StoneinYellow; } else { - if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(StoneinYellow) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = StoneinYellow; adjustedStep++; - if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) OpenerStep++; + if (CustomComboFunctions.WasLastAction(ThunderinMagenta) && OpenerStep == adjustedStep) + OpenerStep++; else if (OpenerStep == adjustedStep) actionID = ThunderinMagenta; adjustedStep++; - if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(BlizzardinCyan) && OpenerStep == adjustedStep) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == adjustedStep) actionID = BlizzardinCyan; } - Svc.Log.Debug($"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); + Svc.Log.Debug( + $"TimeSinceLastAction: {ActionWatching.TimeSinceLastAction.TotalSeconds}, OpenerStep: {OpenerStep}"); if (ActionWatching.TimeSinceLastAction.TotalSeconds > 4) { CurrentState = OpenerState.FailedOpener; Svc.Log.Warning("Opener Failed due to timeout."); + return false; } @@ -1266,15 +1292,16 @@ private bool DoOpener(ref uint actionID) { CurrentState = OpenerState.OpenerFinished; Svc.Log.Information("Opener completed successfully."); + return false; } return true; } + return false; } - private void ResetOpener() { PrePullStep = 0; @@ -1291,18 +1318,18 @@ public bool DoFullOpener(ref uint actionID) return true; if (CurrentState == OpenerState.InOpener) - { if (DoOpener(ref actionID)) return true; - } if (!CustomComboFunctions.InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; } + return false; } } + #endregion -} +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/PLD.cs b/XIVSlothCombo/Combos/PvE/PLD/PLD.cs similarity index 96% rename from XIVSlothCombo/Combos/PvE/PLD.cs rename to XIVSlothCombo/Combos/PvE/PLD/PLD.cs index 78ecd9f70..97af981f1 100644 --- a/XIVSlothCombo/Combos/PvE/PLD.cs +++ b/XIVSlothCombo/Combos/PvE/PLD/PLD.cs @@ -9,7 +9,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class PLD + internal partial class PLD { public const byte ClassID = 1; public const byte JobID = 19; @@ -69,26 +69,7 @@ public const ushort } private static PLDGauge Gauge => CustomComboFunctions.GetJobGauge(); - - public static class Config - { - public static UserInt - PLD_ST_FoF_Trigger = new("PLD_ST_FoF_Trigger", 0), - PLD_AoE_FoF_Trigger = new("PLD_AoE_FoF_Trigger", 0), - PLD_ST_SheltronOption = new("PLD_ST_SheltronOption", 50), - PLD_AoE_SheltronOption = new("PLD_AoE_SheltronOption", 50), - PLD_Intervene_HoldCharges = new("PLD_Intervene_HoldCharges", 1), - PLD_AoE_Intervene_HoldCharges = new("PLD_AoE_Intervene_HoldCharges", 1), - PLD_Intervene_MeleeOnly = new("PLD_Intervene_MeleeOnly", 1), - PLD_AoE_Intervene_MeleeOnly = new("PLD_AoE_Intervene_MeleeOnly", 1), - PLD_ST_MP_Reserve = new("PLD_ST_MP_Reserve", 1000), - PLD_AoE_MP_Reserve = new("PLD_AoE_MP_Reserve", 1000), - PLD_ShieldLob_SubOption = new("PLD_ShieldLob_SubOption", 1), - PLD_RequiescatOption = new("PLD_RequiescatOption"), - PLD_SpiritsWithinOption = new("PLD_SpiritsWithinOption"), - PLD_VariantCure = new("PLD_VariantCure"); - } - + internal class PLD_ST_SimpleMode : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.PLD_ST_SimpleMode; diff --git a/XIVSlothCombo/Combos/PvE/PLD/PLD_Config.cs b/XIVSlothCombo/Combos/PvE/PLD/PLD_Config.cs new file mode 100644 index 000000000..ab0243dab --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/PLD/PLD_Config.cs @@ -0,0 +1,121 @@ +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class PLD +{ + internal static class Config + { + public static UserInt + PLD_ST_FoF_Trigger = new("PLD_ST_FoF_Trigger", 0), + PLD_AoE_FoF_Trigger = new("PLD_AoE_FoF_Trigger", 0), + PLD_ST_SheltronOption = new("PLD_ST_SheltronOption", 50), + PLD_AoE_SheltronOption = new("PLD_AoE_SheltronOption", 50), + PLD_Intervene_HoldCharges = new("PLD_Intervene_HoldCharges", 1), + PLD_AoE_Intervene_HoldCharges = new("PLD_AoE_Intervene_HoldCharges", 1), + PLD_Intervene_MeleeOnly = new("PLD_Intervene_MeleeOnly", 1), + PLD_AoE_Intervene_MeleeOnly = new("PLD_AoE_Intervene_MeleeOnly", 1), + PLD_ST_MP_Reserve = new("PLD_ST_MP_Reserve", 1000), + PLD_AoE_MP_Reserve = new("PLD_AoE_MP_Reserve", 1000), + PLD_ShieldLob_SubOption = new("PLD_ShieldLob_SubOption", 1), + PLD_RequiescatOption = new("PLD_RequiescatOption"), + PLD_SpiritsWithinOption = new("PLD_SpiritsWithinOption"), + PLD_VariantCure = new("PLD_VariantCure"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + // Fight or Flight + case CustomComboPreset.PLD_ST_AdvancedMode_FoF: + UserConfig.DrawSliderInt(0, 50, PLD_ST_FoF_Trigger, "Target HP%", 200); + + break; + + case CustomComboPreset.PLD_AoE_AdvancedMode_FoF: + UserConfig.DrawSliderInt(0, 50, PLD_AoE_FoF_Trigger, "Target HP%", 200); + + break; + + // Sheltron + case CustomComboPreset.PLD_ST_AdvancedMode_Sheltron: + UserConfig.DrawSliderInt(50, 100, PLD_ST_SheltronOption, "Oath Gauge", 200, 5); + + break; + + case CustomComboPreset.PLD_AoE_AdvancedMode_Sheltron: + UserConfig.DrawSliderInt(50, 100, PLD_AoE_SheltronOption, "Oath Gauge", 200, 5); + + break; + + // Intervene + case CustomComboPreset.PLD_ST_AdvancedMode_Intervene: + UserConfig.DrawSliderInt(0, 1, PLD_Intervene_HoldCharges, "Charges", 200); + + UserConfig.DrawHorizontalRadioButton(PLD_Intervene_MeleeOnly, "Melee Range", + "Uses Intervene while within melee range.\nMay result in minor movement.", 1); + + UserConfig.DrawHorizontalRadioButton(PLD_Intervene_MeleeOnly, "No Movement", + "Only uses Intervene when it would not result in movement (zero distance).", 2); + + break; + + case CustomComboPreset.PLD_AoE_AdvancedMode_Intervene: + UserConfig.DrawSliderInt(0, 1, PLD_AoE_Intervene_HoldCharges, "Charges", 200); + + UserConfig.DrawHorizontalRadioButton(PLD_AoE_Intervene_MeleeOnly, "Melee Range", + "Uses Intervene while within melee range.\nMay result in minor movement.", 1); + + UserConfig.DrawHorizontalRadioButton(PLD_AoE_Intervene_MeleeOnly, "No Movement", + "Only uses Intervene when it would not result in movement (zero distance).", 2); + + break; + + // Shield Lob + case CustomComboPreset.PLD_ST_AdvancedMode_ShieldLob: + UserConfig.DrawHorizontalRadioButton(PLD_ShieldLob_SubOption, "Shield Lob Only", + "Uses only Shield Lob.", 1); + + UserConfig.DrawHorizontalRadioButton(PLD_ShieldLob_SubOption, "Hardcast Holy Spirit", + "Attempts to hardcast Holy Spirit when not moving.\nOtherwise uses Shield Lob.", 2); + + break; + + // MP Reservation + case CustomComboPreset.PLD_ST_AdvancedMode_MP_Reserve: + UserConfig.DrawSliderInt(1000, 5000, PLD_ST_MP_Reserve, "Minimum MP", sliderIncrement: 100); + + break; + + case CustomComboPreset.PLD_AoE_AdvancedMode_MP_Reserve: + UserConfig.DrawSliderInt(1000, 5000, PLD_AoE_MP_Reserve, "Minimum MP", sliderIncrement: 100); + + break; + + // Requiescat Spender Feature + case CustomComboPreset.PLD_Requiescat_Options: + UserConfig.DrawRadioButton(PLD_RequiescatOption, "Confiteor", "", 1); + UserConfig.DrawRadioButton(PLD_RequiescatOption, "Blade of Faith/Truth/Valor", "", 2); + UserConfig.DrawRadioButton(PLD_RequiescatOption, "Confiteor & Blade of Faith/Truth/Valor", "", 3); + UserConfig.DrawRadioButton(PLD_RequiescatOption, "Holy Spirit", "", 4); + UserConfig.DrawRadioButton(PLD_RequiescatOption, "Holy Circle", "", 5); + + break; + + // Spirits Within / Circle of Scorn Feature + case CustomComboPreset.PLD_SpiritsWithin: + UserConfig.DrawRadioButton(PLD_SpiritsWithinOption, "Prioritize Circle of Scorn", "", 1); + UserConfig.DrawRadioButton(PLD_SpiritsWithinOption, "Prioritize Spirits Within / Expiacion", "", 2); + + break; + + // Variant Cure Feature + case CustomComboPreset.PLD_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, PLD_VariantCure, "Player HP%", 200); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs index f78baa77d..26c30411e 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM.cs @@ -3,7 +3,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static partial class RDM + internal partial class RDM { //7.0 Note //Gauge information is available via RDMMana diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs index fb8666352..f4d48b232 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Config.cs @@ -7,7 +7,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static partial class RDM + internal partial class RDM { internal static class Config { diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs index 67f14d646..3855a4000 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs @@ -9,7 +9,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static partial class RDM + internal partial class RDM { private class RDMMana { diff --git a/XIVSlothCombo/Combos/PvE/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM/SAM.cs similarity index 96% rename from XIVSlothCombo/Combos/PvE/SAM.cs rename to XIVSlothCombo/Combos/PvE/SAM/SAM.cs index 2e457cab6..5953d267e 100644 --- a/XIVSlothCombo/Combos/PvE/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM/SAM.cs @@ -11,7 +11,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal class SAM + internal partial class SAM { public const byte JobID = 34; @@ -91,33 +91,7 @@ public const ushort EnhancedMeikyoShishui2 = 593; } - public static class Config - { - public static UserInt - SAM_STSecondWindThreshold = new("SAM_STSecondWindThreshold", 25), - SAM_STBloodbathThreshold = new("SAM_STBloodbathThreshold", 40), - SAM_AoESecondWindThreshold = new("SAM_AoESecondWindThreshold", 25), - SAM_AoEBloodbathThreshold = new("SAM_AoEBloodbathThreshold", 40), - SAM_Kasha_KenkiOvercapAmount = new(nameof(SAM_Kasha_KenkiOvercapAmount), 50), - SAM_Yukaze_KenkiOvercapAmount = new(nameof(SAM_Yukaze_KenkiOvercapAmount), 50), - SAM_Gekko_KenkiOvercapAmount = new(nameof(SAM_Gekko_KenkiOvercapAmount), 50), - SAM_Oka_KenkiOvercapAmount = new(nameof(SAM_Oka_KenkiOvercapAmount), 50), - SAM_Mangetsu_KenkiOvercapAmount = new(nameof(SAM_Mangetsu_KenkiOvercapAmount), 50), - SAM_ST_KenkiOvercapAmount = new(nameof(SAM_ST_KenkiOvercapAmount), 50), - SAM_AoE_KenkiOvercapAmount = new(nameof(SAM_AoE_KenkiOvercapAmount), 50), - SAM_VariantCure = new("SAM_VariantCure"); - - public static UserFloat - SAM_ST_Higanbana_Threshold = new("SAM_ST_Higanbana_Threshold", 1), - SAM_ST_ExecuteThreshold = new("SAM_ST_ExecuteThreshold", 1); - - public static UserBool - SAM_Kasha_KenkiOvercap = new(nameof(SAM_Kasha_KenkiOvercap)), - SAM_Yukaze_KenkiOvercap = new(nameof(SAM_Yukaze_KenkiOvercap)), - SAM_Gekko_KenkiOvercap = new(nameof(SAM_Gekko_KenkiOvercap)), - SAM_Oka_KenkiOvercap = new(nameof(SAM_Oka_KenkiOvercap)), - SAM_Mangetsu_KenkiOvercap = new(nameof(SAM_Mangetsu_KenkiOvercap)); - } + internal class SAM_ST_YukikazeCombo : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_ST_YukikazeCombo; diff --git a/XIVSlothCombo/Combos/PvE/SAM/SAM_Config.cs b/XIVSlothCombo/Combos/PvE/SAM/SAM_Config.cs new file mode 100644 index 000000000..7d4b9e0e3 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/SAM/SAM_Config.cs @@ -0,0 +1,157 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class SAM +{ + internal static class Config + { + public static UserInt + SAM_STSecondWindThreshold = new("SAM_STSecondWindThreshold", 25), + SAM_STBloodbathThreshold = new("SAM_STBloodbathThreshold", 40), + SAM_AoESecondWindThreshold = new("SAM_AoESecondWindThreshold", 25), + SAM_AoEBloodbathThreshold = new("SAM_AoEBloodbathThreshold", 40), + SAM_Kasha_KenkiOvercapAmount = new(nameof(SAM_Kasha_KenkiOvercapAmount), 50), + SAM_Yukaze_KenkiOvercapAmount = new(nameof(SAM_Yukaze_KenkiOvercapAmount), 50), + SAM_Gekko_KenkiOvercapAmount = new(nameof(SAM_Gekko_KenkiOvercapAmount), 50), + SAM_Oka_KenkiOvercapAmount = new(nameof(SAM_Oka_KenkiOvercapAmount), 50), + SAM_Mangetsu_KenkiOvercapAmount = new(nameof(SAM_Mangetsu_KenkiOvercapAmount), 50), + SAM_ST_KenkiOvercapAmount = new(nameof(SAM_ST_KenkiOvercapAmount), 50), + SAM_AoE_KenkiOvercapAmount = new(nameof(SAM_AoE_KenkiOvercapAmount), 50), + SAM_VariantCure = new("SAM_VariantCure"); + + public static UserFloat + SAM_ST_Higanbana_Threshold = new("SAM_ST_Higanbana_Threshold", 1), + SAM_ST_ExecuteThreshold = new("SAM_ST_ExecuteThreshold", 1); + + public static UserBool + SAM_Kasha_KenkiOvercap = new(nameof(SAM_Kasha_KenkiOvercap)), + SAM_Yukaze_KenkiOvercap = new(nameof(SAM_Yukaze_KenkiOvercap)), + SAM_Gekko_KenkiOvercap = new(nameof(SAM_Gekko_KenkiOvercap)), + SAM_Oka_KenkiOvercap = new(nameof(SAM_Oka_KenkiOvercap)), + SAM_Mangetsu_KenkiOvercap = new(nameof(SAM_Mangetsu_KenkiOvercap)); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.SAM_ST_CDs_Iaijutsu: + UserConfig.DrawSliderInt(0, 100, SAM_ST_Higanbana_Threshold, + "Stop using Higanbana on targets below this HP % (0% = always use)."); + + break; + + case CustomComboPreset.SAM_ST_ComboHeals: + UserConfig.DrawSliderInt(0, 100, SAM_STSecondWindThreshold, + "HP percent threshold to use Second Wind below (0 = Disabled)"); + + UserConfig.DrawSliderInt(0, 100, SAM_STBloodbathThreshold, + "HP percent threshold to use Bloodbath (0 = Disabled)"); + + break; + + case CustomComboPreset.SAM_AoE_ComboHeals: + UserConfig.DrawSliderInt(0, 100, SAM_AoESecondWindThreshold, + "HP percent threshold to use Second Wind below (0 = Disabled)"); + + UserConfig.DrawSliderInt(0, 100, SAM_AoEBloodbathThreshold, + "HP percent threshold to use Bloodbath below (0 = Disabled)"); + + break; + + case CustomComboPreset.SAM_ST_Shinten: + UserConfig.DrawSliderInt(50, 85, SAM_ST_KenkiOvercapAmount, + "Set the Kenki overcap amount for ST combos."); + UserConfig.DrawSliderInt(0, 100, SAM_ST_ExecuteThreshold, "HP percent threshold to not save Kenki"); + + break; + + case CustomComboPreset.SAM_AoE_Kyuten: + UserConfig.DrawSliderInt(50, 85, SAM_AoE_KenkiOvercapAmount, + "Set the Kenki overcap amount for AOE combos."); + + break; + + case CustomComboPreset.SAM_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, SAM_VariantCure, "HP% to be at or under", 200); + + break; + + //PvP + case CustomComboPreset.SAMPvP_BurstMode: + UserConfig.DrawSliderInt(0, 2, SAMPvP.Config.SAMPvP_SotenCharges, + "How many charges of Soten to keep ready? (0 = Use All)."); + + break; + + case CustomComboPreset.SAMPvP_KashaFeatures_GapCloser: + UserConfig.DrawSliderInt(0, 100, SAMPvP.Config.SAMPvP_SotenHP, + "Use Soten on enemies below selected HP."); + + break; + + case CustomComboPreset.SAM_ST_KashaCombo: + { + UserConfig.DrawAdditionalBoolChoice(SAM_Kasha_KenkiOvercap, "Kenki Overcap Protection", + "Spends Kenki when at the set value or above."); + + if (SAM_Kasha_KenkiOvercap) + UserConfig.DrawSliderInt(25, 100, SAM_Kasha_KenkiOvercapAmount, "Kenki Amount", + sliderIncrement: SliderIncrements.Fives); + + break; + } + + case CustomComboPreset.SAM_ST_YukikazeCombo: + { + UserConfig.DrawAdditionalBoolChoice(SAM_Yukaze_KenkiOvercap, "Kenki Overcap Protection", + "Spends Kenki when at the set value or above."); + + if (SAM_Yukaze_KenkiOvercap) + UserConfig.DrawSliderInt(25, 100, SAM_Yukaze_KenkiOvercapAmount, "Kenki Amount", + sliderIncrement: SliderIncrements.Fives); + + break; + } + + case CustomComboPreset.SAM_ST_GekkoCombo: + { + UserConfig.DrawAdditionalBoolChoice(SAM_Gekko_KenkiOvercap, "Kenki Overcap Protection", + "Spends Kenki when at the set value or above."); + + if (SAM_Gekko_KenkiOvercap) + UserConfig.DrawSliderInt(25, 100, SAM_Gekko_KenkiOvercapAmount, "Kenki Amount", + sliderIncrement: SliderIncrements.Fives); + + break; + } + + case CustomComboPreset.SAM_AoE_OkaCombo: + { + UserConfig.DrawAdditionalBoolChoice(SAM_Oka_KenkiOvercap, "Kenki Overcap Protection", + "Spends Kenki when at the set value or above."); + + if (SAM_Oka_KenkiOvercap) + UserConfig.DrawSliderInt(25, 100, SAM_Oka_KenkiOvercapAmount, "Kenki Amount", + sliderIncrement: SliderIncrements.Fives); + + break; + } + + case CustomComboPreset.SAM_AoE_MangetsuCombo: + { + UserConfig.DrawAdditionalBoolChoice(SAM_Mangetsu_KenkiOvercap, "Kenki Overcap Protection", + "Spends Kenki when at the set value or above."); + + if (SAM_Mangetsu_KenkiOvercap) + UserConfig.DrawSliderInt(25, 100, SAM_Mangetsu_KenkiOvercapAmount, "Kenki Amount", + sliderIncrement: SliderIncrements.Fives); + + break; + } + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/JobHelpers/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM/SAM_Helper.cs similarity index 80% rename from XIVSlothCombo/Combos/JobHelpers/SAM.cs rename to XIVSlothCombo/Combos/PvE/SAM/SAM_Helper.cs index 4ebe67090..7088b880d 100644 --- a/XIVSlothCombo/Combos/JobHelpers/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM/SAM_Helper.cs @@ -2,87 +2,61 @@ using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; -using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; -namespace XIVSlothCombo.Combos.JobHelpers +namespace XIVSlothCombo.Combos.PvE; + +internal partial class SAM { - internal class SAMHelper : SAM + internal static int SenCount => GetSenCount(); + + internal static bool ComboStarted => GetComboStarted(); + + private static int GetSenCount() { - internal static int SenCount => GetSenCount(); - private static int GetSenCount() - { - var gauge = CustomComboFunctions.GetJobGauge(); - var senCount = 0; - if (gauge.HasGetsu) senCount++; - if (gauge.HasSetsu) senCount++; - if (gauge.HasKa) senCount++; + SAMGauge gauge = CustomComboFunctions.GetJobGauge(); + int senCount = 0; + if (gauge.HasGetsu) senCount++; + if (gauge.HasSetsu) senCount++; + if (gauge.HasKa) senCount++; - return senCount; - } - internal static bool ComboStarted => GetComboStarted(); - private unsafe static bool GetComboStarted() - { - var comboAction = ActionManager.Instance()->Combo.Action; - if (comboAction == CustomComboFunctions.OriginalHook(Hakaze) || comboAction == CustomComboFunctions.OriginalHook(Jinpu) || comboAction == CustomComboFunctions.OriginalHook(Shifu)) - return true; - return false; - } + return senCount; } - - internal class SAMOpenerLogic : SAM + private static unsafe bool GetComboStarted() { - private static bool HasCooldowns() - { - if (!CustomComboFunctions.ActionReady(Senei)) - return false; + uint comboAction = ActionManager.Instance()->Combo.Action; - if (!CustomComboFunctions.ActionReady(Ikishoten)) - return false; - - return true; - } + return comboAction == CustomComboFunctions.OriginalHook(Hakaze) || + comboAction == CustomComboFunctions.OriginalHook(Jinpu) || + comboAction == CustomComboFunctions.OriginalHook(Shifu); + } - public static bool HasPrePullCooldowns() - { - if (CustomComboFunctions.GetRemainingCharges(MeikyoShisui) < 2) - return false; + internal class SAMOpenerLogic + { + private OpenerState currentState = OpenerState.PrePull; - if (CustomComboFunctions.GetRemainingCharges(All.TrueNorth) < 2) - return false; + public uint OpenerStep = 1; - return true; - } + public uint PrePullStep; private static uint OpenerLevel => 100; - public uint PrePullStep = 0; - - public uint OpenerStep = 1; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && HasPrePullCooldowns() && LevelChecked; - private OpenerState currentState = OpenerState.PrePull; - public OpenerState CurrentState { - get - { - return currentState; - } + get => currentState; set { if (value != currentState) { - if (value == OpenerState.PrePull) - { - Svc.Log.Debug($"Entered PrePull Opener"); - } + if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) @@ -97,27 +71,44 @@ public OpenerState CurrentState } } + private static bool HasCooldowns() + { + if (!CustomComboFunctions.ActionReady(Senei)) + return false; + + if (!CustomComboFunctions.ActionReady(Ikishoten)) + return false; + + return true; + } + + public static bool HasPrePullCooldowns() + { + if (CustomComboFunctions.GetRemainingCharges(MeikyoShisui) < 2) + return false; + + if (CustomComboFunctions.GetRemainingCharges(All.TrueNorth) < 2) + return false; + + return true; + } + private bool DoPrePullSteps(ref uint actionID) { if (!LevelChecked) return false; - if (CanOpener && PrePullStep == 0) - { - PrePullStep = 1; - } + if (CanOpener && PrePullStep == 0) PrePullStep = 1; - if (!HasCooldowns()) - { - PrePullStep = 0; - } + if (!HasCooldowns()) PrePullStep = 0; if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { if (CustomComboFunctions.HasEffect(Buffs.MeikyoShisui) && PrePullStep == 1) PrePullStep++; else if (PrePullStep == 1) actionID = MeikyoShisui; - if (CustomComboFunctions.HasEffect(All.Buffs.TrueNorth) && PrePullStep == 2) currentState = OpenerState.InOpener; + if (CustomComboFunctions.HasEffect(All.Buffs.TrueNorth) && PrePullStep == 2) + currentState = OpenerState.InOpener; else if (PrePullStep == 2) actionID = All.TrueNorth; if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) @@ -127,6 +118,7 @@ private bool DoPrePullSteps(ref uint actionID) } PrePullStep = 0; + return false; } @@ -202,22 +194,26 @@ private bool DoOpener(ref uint actionID) if (CustomComboFunctions.WasLastAction(TendoSetsugekka) && OpenerStep == 22) OpenerStep++; else if (OpenerStep == 22) actionID = TendoSetsugekka; - if (CustomComboFunctions.WasLastAction(TendoKaeshiSetsugekka) && OpenerStep == 23) CurrentState = OpenerState.OpenerFinished; + if (CustomComboFunctions.WasLastAction(TendoKaeshiSetsugekka) && OpenerStep == 23) + CurrentState = OpenerState.OpenerFinished; else if (OpenerStep == 23) actionID = TendoKaeshiSetsugekka; - if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) CurrentState = OpenerState.FailedOpener; if (((actionID == Senei && CustomComboFunctions.IsOnCooldown(Senei)) || - (actionID == Ikishoten && CustomComboFunctions.IsOnCooldown(Ikishoten)) || - (actionID == MeikyoShisui && CustomComboFunctions.GetRemainingCharges(MeikyoShisui) < 1)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) + (actionID == Ikishoten && CustomComboFunctions.IsOnCooldown(Ikishoten)) || + (actionID == MeikyoShisui && CustomComboFunctions.GetRemainingCharges(MeikyoShisui) < 1)) && + ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { CurrentState = OpenerState.FailedOpener; + return false; } + return true; } + return false; } @@ -237,16 +233,15 @@ public bool DoFullOpener(ref uint actionID) return true; if (CurrentState == OpenerState.InOpener) - { if (DoOpener(ref actionID)) return true; - } if (!CustomComboFunctions.InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; } + return false; } } diff --git a/XIVSlothCombo/Combos/PvE/SMN.cs b/XIVSlothCombo/Combos/PvE/SMN/SMN.cs similarity index 98% rename from XIVSlothCombo/Combos/PvE/SMN.cs rename to XIVSlothCombo/Combos/PvE/SMN/SMN.cs index 87d17cb37..564b2a24f 100644 --- a/XIVSlothCombo/Combos/PvE/SMN.cs +++ b/XIVSlothCombo/Combos/PvE/SMN/SMN.cs @@ -3,11 +3,10 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; namespace XIVSlothCombo.Combos.PvE { - internal class SMN + internal partial class SMN { public const byte ClassID = 26; public const byte JobID = 27; @@ -134,22 +133,7 @@ public const ushort RefulgentLux = 3874; } - public static class Config - { - public static string - SMN_Lucid = "SMN_Lucid", - SMN_BurstPhase = "SMN_BurstPhase", - SMN_PrimalChoice = "SMN_PrimalChoice", - SMN_SwiftcastPhase = "SMN_SwiftcastPhase", - SMN_Burst_Delay = "SMN_Burst_Delay", - SMN_VariantCure = "SMN_VariantCure"; - - public static UserBoolArray - SMN_ST_Egi_AstralFlow = new("SMN_ST_Egi_AstralFlow"); - - public static UserBool - SMN_ST_CrimsonCycloneMelee = new("SMN_ST_CrimsonCycloneMelee"); - } + internal class SMN_Raise : CustomCombo { diff --git a/XIVSlothCombo/Combos/PvE/SMN/SMN_Config.cs b/XIVSlothCombo/Combos/PvE/SMN/SMN_Config.cs new file mode 100644 index 000000000..53bbc97cd --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/SMN/SMN_Config.cs @@ -0,0 +1,104 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class SMN +{ + internal static class Config + { + public static UserInt + SMN_Lucid = new("SMN_Lucid"), + SMN_BurstPhase = new("SMN_BurstPhase"), + SMN_PrimalChoice = new("SMN_PrimalChoice"), + SMN_SwiftcastPhase = new("SMN_SwiftcastPhase"), + SMN_Burst_Delay = new("SMN_Burst_Delay"), + SMN_VariantCure = new("SMN_VariantCure"); + + public static UserBoolArray + SMN_ST_Egi_AstralFlow = new("SMN_ST_Egi_AstralFlow"); + + public static UserBool + SMN_ST_CrimsonCycloneMelee = new("SMN_ST_CrimsonCycloneMelee"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.SMN_DemiEgiMenu_EgiOrder: + UserConfig.DrawHorizontalRadioButton(SMN_PrimalChoice, "Titan first", + "Summons Titan, Garuda then Ifrit.", 1); + + UserConfig.DrawHorizontalRadioButton(SMN_PrimalChoice, "Garuda first", + "Summons Garuda, Titan then Ifrit.", 2); + + break; + + case CustomComboPreset.SMN_DemiEgiMenu_oGCDPooling: + UserConfig.DrawSliderInt(0, 3, SMN_Burst_Delay, + "Sets the amount of GCDs under Demi summon to wait for oGCD use."); + + UserConfig.DrawHorizontalRadioButton(SMN_BurstPhase, "Solar Bahamut/Bahamut", + "Bursts during Bahamut phase.\nBahamut burst phase becomes Solar Bahamut at Lv100.", 1); + UserConfig.DrawHorizontalRadioButton(SMN_BurstPhase, "Phoenix", "Bursts during Phoenix phase.", 2); + + UserConfig.DrawHorizontalRadioButton(SMN_BurstPhase, "Any Demi Phase", + "Bursts during any Demi Summon phase.", 3); + + UserConfig.DrawHorizontalRadioButton(SMN_BurstPhase, "Flexible (SpS) Option", + "Bursts when Searing Light is ready, regardless of phase.", 4); + + break; + + case CustomComboPreset.SMN_DemiEgiMenu_SwiftcastEgi: + UserConfig.DrawHorizontalRadioButton(SMN_SwiftcastPhase, "Garuda", "Swiftcasts Slipstream", 1); + + UserConfig.DrawHorizontalRadioButton(SMN_SwiftcastPhase, "Ifrit", "Swiftcasts Ruby Ruin/Ruby Rite", + 2); + + UserConfig.DrawHorizontalRadioButton(SMN_SwiftcastPhase, "Flexible (SpS) Option", + "Swiftcasts the first available Egi when Swiftcast is ready.", 3); + + break; + + case CustomComboPreset.SMN_Lucid: + UserConfig.DrawSliderInt(4000, 9500, SMN_Lucid, + "Set value for your MP to be at or under for this feature to take effect.", 150, + SliderIncrements.Hundreds); + + break; + + case CustomComboPreset.SMN_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, SMN_VariantCure, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.SMN_ST_Egi_AstralFlow: + { + UserConfig.DrawHorizontalMultiChoice(SMN_ST_Egi_AstralFlow, "Add Mountain Buster", "", 3, 0); + UserConfig.DrawHorizontalMultiChoice(SMN_ST_Egi_AstralFlow, "Add Crimson Cyclone", "", 3, 1); + UserConfig.DrawHorizontalMultiChoice(SMN_ST_Egi_AstralFlow, "Add Slipstream", "", 3, 2); + + if (SMN_ST_Egi_AstralFlow[1]) + UserConfig.DrawAdditionalBoolChoice(SMN_ST_CrimsonCycloneMelee, + "Enforced Crimson Cyclone Melee Check", "Only uses Crimson Cyclone within melee range."); + + break; + } + + case CustomComboPreset.SMNPvP_BurstMode: + UserConfig.DrawSliderInt(50, 100, SMNPvP.Config.SMNPvP_FesterThreshold, + "Target HP% to cast Fester below.\nSet to 100 use Fester as soon as it's available."); + + break; + + case CustomComboPreset.SMNPvP_BurstMode_RadiantAegis: + UserConfig.DrawSliderInt(0, 90, SMNPvP.Config.SMNPvP_RadiantAegisThreshold, + "Caps at 90 to prevent waste."); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/WAR.cs b/XIVSlothCombo/Combos/PvE/WAR/WAR.cs similarity index 97% rename from XIVSlothCombo/Combos/PvE/WAR.cs rename to XIVSlothCombo/Combos/PvE/WAR/WAR.cs index 15631396c..c7c328c4a 100644 --- a/XIVSlothCombo/Combos/PvE/WAR.cs +++ b/XIVSlothCombo/Combos/PvE/WAR/WAR.cs @@ -6,7 +6,7 @@ namespace XIVSlothCombo.Combos.PvE { - internal static class WAR + internal partial class WAR { public const byte ClassID = 3; public const byte JobID = 21; @@ -56,19 +56,7 @@ public const ushort Placeholder = 1; } - public static class Config - { - public const string - WAR_InfuriateRange = "WarInfuriateRange", - WAR_SurgingRefreshRange = "WarSurgingRefreshRange", - WAR_KeepOnslaughtCharges = "WarKeepOnslaughtCharges", - WAR_KeepInfuriateCharges = "WarKeepInfuriateCharges", - WAR_VariantCure = "WAR_VariantCure", - WAR_FellCleaveGauge = "WAR_FellCleaveGauge", - WAR_DecimateGauge = "WAR_DecimateGauge", - WAR_InfuriateSTGauge = "WAR_InfuriateSTGauge", - WAR_InfuriateAoEGauge = "WAR_InfuriateAoEGauge"; - } + internal class WAR_ST_SimpleMode : CustomCombo { diff --git a/XIVSlothCombo/Combos/PvE/WAR/WAR_Config.cs b/XIVSlothCombo/Combos/PvE/WAR/WAR_Config.cs new file mode 100644 index 000000000..c1ca566d9 --- /dev/null +++ b/XIVSlothCombo/Combos/PvE/WAR/WAR_Config.cs @@ -0,0 +1,80 @@ +using XIVSlothCombo.Combos.PvP; +using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Window.Functions; + +namespace XIVSlothCombo.Combos.PvE; + +internal partial class WAR +{ + internal static class Config + { + public static UserInt + WAR_InfuriateRange = new("WarInfuriateRange"), + WAR_SurgingRefreshRange = new("WarSurgingRefreshRange"), + WAR_KeepOnslaughtCharges = new("WarKeepOnslaughtCharges"), + WAR_KeepInfuriateCharges = new("WarKeepInfuriateCharges"), + WAR_VariantCure = new("WAR_VariantCure"), + WAR_FellCleaveGauge = new("WAR_FellCleaveGauge"), + WAR_DecimateGauge = new("WAR_DecimateGauge"), + WAR_InfuriateSTGauge = new("WAR_InfuriateSTGauge"), + WAR_InfuriateAoEGauge = new("WAR_InfuriateAoEGauge"); + + internal static void Draw(CustomComboPreset preset) + { + switch (preset) + { + case CustomComboPreset.WAR_ST_Advanced_StormsEye: + UserConfig.DrawSliderInt(0, 30, WAR_SurgingRefreshRange, + "Seconds remaining before refreshing Surging Tempest."); + + break; + + case CustomComboPreset.WAR_InfuriateFellCleave: + UserConfig.DrawSliderInt(0, 50, WAR_InfuriateRange, + "Set how much rage to be at or under to use this feature."); + + break; + + case CustomComboPreset.WAR_ST_Advanced_Onslaught: + UserConfig.DrawSliderInt(0, 2, WAR_KeepOnslaughtCharges, + "How many charges to keep ready? (0 = Use All)"); + + break; + + case CustomComboPreset.WAR_ST_Advanced_Infuriate: + UserConfig.DrawSliderInt(0, 2, WAR_KeepInfuriateCharges, + "How many charges to keep ready? (0 = Use All)"); + + UserConfig.DrawSliderInt(0, 50, WAR_InfuriateSTGauge, "Use when gauge is under or equal to"); + + break; + + case CustomComboPreset.WAR_Variant_Cure: + UserConfig.DrawSliderInt(1, 100, WAR_VariantCure, "HP% to be at or under", 200); + + break; + + case CustomComboPreset.WAR_ST_Advanced_FellCleave: + UserConfig.DrawSliderInt(50, 100, WAR_FellCleaveGauge, "Minimum gauge to spend"); + + break; + + case CustomComboPreset.WAR_AoE_Advanced_Decimate: + UserConfig.DrawSliderInt(50, 100, WAR_DecimateGauge, "Minimum gauge to spend"); + + break; + + case CustomComboPreset.WAR_AoE_Advanced_Infuriate: + UserConfig.DrawSliderInt(0, 50, WAR_InfuriateAoEGauge, "Use when gauge is under or equal to"); + + break; + + case CustomComboPreset.WARPvP_BurstMode_Blota: + UserConfig.DrawHorizontalRadioButton(WARPvP.Config.WARPVP_BlotaTiming, "Before Primal Rend", "", 0); + UserConfig.DrawHorizontalRadioButton(WARPvP.Config.WARPVP_BlotaTiming, "After Primal Rend", "", 1); + + break; + } + } + } +} \ No newline at end of file diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index 0082e24c9..aea184679 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -12,7 +12,6 @@ using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; -using static XIVSlothCombo.Combos.JobHelpers.NIN; namespace XIVSlothCombo.Data { @@ -116,9 +115,9 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp private static void UpdateHelpers(uint actionId) { if (actionId is NIN.Ten or NIN.Chi or NIN.Jin or NIN.TenCombo or NIN.ChiCombo or NIN.JinCombo) - NINHelper.InMudra = true; + NIN.NINHelper.InMudra = true; else - NINHelper.InMudra = false; + NIN.NINHelper.InMudra = false; } private unsafe static void CheckForChangedTarget(uint actionId, ref ulong targetObjectId) diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index ae88b7cf6..d340b045b 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -269,29 +269,29 @@ internal unsafe static void DrawPreset(CustomComboPreset preset, CustomComboInfo { switch (info.JobID) { - //case All.JobID: All.Config.Draw(preset); break; + // case All.JobID: All.Config.Draw(preset); break; case AST.JobID: AST.Config.Draw(preset); break; - //case BLM.JobID: BLM.Config.Draw(preset); break; - //case BLU.JobID: BLU.Config.Draw(preset); break; - //case BRD.JobID: BRD.Config.Draw(preset); break; - //case DNC.JobID: DNC.Config.Draw(preset); break; - //case DOL.JobID: DOL.Config.Draw(preset); break; - //case DRG.JobID: DRG.Config.Draw(preset); break; - //case DRK.JobID: DRK.Config.Draw(preset); break; - //case GNB.JobID: GNB.Config.Draw(preset); break; - //case MCH.JobID: MCH.Config.Draw(preset); break; - //case MNK.JobID: MNK.Config.Draw(preset); break; - //case NIN.JobID: NIN.Config.Draw(preset); break; - //case PCT.JobID: PCT.Config.Draw(preset); break; - //case PLD.JobID: PLD.Config.Draw(preset); break; - //case RPR.JobID: RPR.Config.Draw(preset); break; + case BLM.JobID: BLM.Config.Draw(preset); break; + case BLU.JobID: BLU.Config.Draw(preset); break; + case BRD.JobID: BRD.Config.Draw(preset); break; + case DNC.JobID: DNC.Config.Draw(preset); break; + case DOL.JobID: DOL.Config.Draw(preset); break; + case DRG.JobID: DRG.Config.Draw(preset); break; + case DRK.JobID: DRK.Config.Draw(preset); break; + case GNB.JobID: GNB.Config.Draw(preset); break; + case MCH.JobID: MCH.Config.Draw(preset); break; + // case MNK.JobID: MNK.Config.Draw(preset); break; + case NIN.JobID: NIN.Config.Draw(preset); break; + case PCT.JobID: PCT.Config.Draw(preset); break; + case PLD.JobID: PLD.Config.Draw(preset); break; + case RPR.JobID: RPR.Config.Draw(preset); break; case RDM.JobID: RDM.Config.Draw(preset); break; - //case SAM.JobID: SAM.Config.Draw(preset); break; + case SAM.JobID: SAM.Config.Draw(preset); break; case SCH.JobID: SCH.Config.Draw(preset); break; case SGE.JobID: SGE.Config.Draw(preset); break; - //case SMN.JobID: SMN.Config.Draw(preset); break; - //case VPR.JobID: VPR.Config.Draw(preset); break; - //case WAR.JobID: WAR.Config.Draw(preset); break; + case SMN.JobID: SMN.Config.Draw(preset); break; + case VPR.JobID: VPR.Config.Draw(preset); break; + case WAR.JobID: WAR.Config.Draw(preset); break; case WHM.JobID: WHM.Config.Draw(preset); break; default: UserConfigItems.Draw(preset, enabled); break; } diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index d59842956..a7891cf9b 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1189,170 +1189,17 @@ internal static void Draw(CustomComboPreset preset, bool enabled) if (!enabled) return; // ==================================================================================== - #region Misc - - #endregion // ==================================================================================== - #region ADV - - #endregion // ==================================================================================== - // ==================================================================================== - #region BLACK MAGE - - if (preset is CustomComboPreset.BLM_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, BLM.Config.BLM_VariantCure, "HP% to be at or under", 200); - - #endregion // ==================================================================================== - #region BLUE MAGE - - #endregion // ==================================================================================== - #region BARD - - if (preset == CustomComboPreset.BRD_Adv_RagingJaws) - UserConfig.DrawSliderInt(3, 10, BRD.Config.BRD_RagingJawsRenewTime, "Remaining time (In seconds). Recommended 5, increase little by little if refresh is outside of radiant window"); - - if (preset == CustomComboPreset.BRD_Adv_NoWaste) - UserConfig.DrawSliderInt(1, 10, BRD.Config.BRD_NoWasteHPPercentage, "Remaining target HP percentage"); - - if (preset == CustomComboPreset.BRD_AoE_Adv_NoWaste) - UserConfig.DrawSliderInt(1, 10, BRD.Config.BRD_AoENoWasteHPPercentage, "Remaining target HP percentage"); - - if (preset == CustomComboPreset.BRD_ST_SecondWind) - UserConfig.DrawSliderInt(0, 100, BRD.Config.BRD_STSecondWindThreshold, "HP percent threshold to use Second Wind below.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.BRD_AoE_SecondWind) - UserConfig.DrawSliderInt(0, 100, BRD.Config.BRD_AoESecondWindThreshold, "HP percent threshold to use Second Wind below.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.BRD_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, BRD.Config.BRD_VariantCure, "HP% to be at or under", 200); - - #endregion // ==================================================================================== - #region DANCER - - if (preset == CustomComboPreset.DNC_DanceComboReplacer) - { - //int[]? actions = Service.Configuration.DancerDanceCompatActionIDs.Cast().ToArray(); - int[]? actions = Service.Configuration.DancerDanceCompatActionIDs.Select(x => (int)x).ToArray(); - - - bool inputChanged = false; - - inputChanged |= ImGui.InputInt("Emboite (Red) ActionID", ref actions[0], 0); - inputChanged |= ImGui.InputInt("Entrechat (Blue) ActionID", ref actions[1], 0); - inputChanged |= ImGui.InputInt("Jete (Green) ActionID", ref actions[2], 0); - inputChanged |= ImGui.InputInt("Pirouette (Yellow) ActionID", ref actions[3], 0); - - if (inputChanged) - { - //Service.Configuration.DancerDanceCompatActionIDs = actions.Cast().ToArray(); - Service.Configuration.DancerDanceCompatActionIDs = actions.Select(x => (uint)x).ToArray(); - Service.Configuration.Save(); - } - - ImGui.Spacing(); - } - - if (preset == CustomComboPreset.DNC_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, DNC.Config.DNCVariantCurePercent, "HP% to be at or under", 200); - - #region Multi-Button Sliders - - if (preset == CustomComboPreset.DNC_ST_EspritOvercap) - UserConfig.DrawSliderInt(50, 100, DNC.Config.DNCEspritThreshold_ST, "Esprit", 150, SliderIncrements.Fives); - - if (preset == CustomComboPreset.DNC_AoE_EspritOvercap) - UserConfig.DrawSliderInt(50, 100, DNC.Config.DNCEspritThreshold_AoE, "Esprit", 150, SliderIncrements.Fives); - - #endregion - - #region Advanced ST Sliders - - if (preset == CustomComboPreset.DNC_ST_Adv_SS) - UserConfig.DrawSliderInt(0, 5, DNC.Config.DNC_ST_Adv_SSBurstPercent, "Target HP% to stop using Standard Step below", 75); - - if (preset == CustomComboPreset.DNC_ST_Adv_TS) - UserConfig.DrawSliderInt(0, 5, DNC.Config.DNC_ST_Adv_TSBurstPercent, "Target HP% to stop using Technical Step below", 75); - - if (preset == CustomComboPreset.DNC_ST_Adv_Feathers) - UserConfig.DrawSliderInt(0, 5, DNC.Config.DNC_ST_Adv_FeatherBurstPercent, "Target HP% to dump all pooled feathers below", 75); - - if (preset == CustomComboPreset.DNC_ST_Adv_SaberDance) - UserConfig.DrawSliderInt(50, 100, DNC.Config.DNC_ST_Adv_SaberThreshold, "Esprit", 150, SliderIncrements.Fives); - - if (preset == CustomComboPreset.DNC_ST_Adv_PanicHeals) - UserConfig.DrawSliderInt(0, 100, DNC.Config.DNC_ST_Adv_PanicHealWaltzPercent, "Curing Waltz HP%", 200); - - if (preset == CustomComboPreset.DNC_ST_Adv_PanicHeals) - UserConfig.DrawSliderInt(0, 100, DNC.Config.DNC_ST_Adv_PanicHealWindPercent, "Second Wind HP%", 200); - - #endregion - - #region Advanced AoE Sliders - - if (preset == CustomComboPreset.DNC_AoE_Adv_SS) - UserConfig.DrawSliderInt(0, 10, DNC.Config.DNC_AoE_Adv_SSBurstPercent, "Target HP% to stop using Standard Step below", 75); - - if (preset == CustomComboPreset.DNC_AoE_Adv_TS) - UserConfig.DrawSliderInt(0, 10, DNC.Config.DNC_AoE_Adv_TSBurstPercent, "Target HP% to stop using Technical Step below", 75); - - if (preset == CustomComboPreset.DNC_AoE_Adv_SaberDance) - UserConfig.DrawSliderInt(50, 100, DNC.Config.DNC_AoE_Adv_SaberThreshold, "Esprit", 150, SliderIncrements.Fives); - - if (preset == CustomComboPreset.DNC_AoE_Adv_PanicHeals) - UserConfig.DrawSliderInt(0, 100, DNC.Config.DNC_AoE_Adv_PanicHealWaltzPercent, "Curing Waltz HP%", 200); - - if (preset == CustomComboPreset.DNC_AoE_Adv_PanicHeals) - UserConfig.DrawSliderInt(0, 100, DNC.Config.DNC_AoE_Adv_PanicHealWindPercent, "Second Wind HP%", 200); - - #endregion - - #region PvP Sliders - - if (preset == CustomComboPreset.DNCPvP_BurstMode_CuringWaltz) - UserConfig.DrawSliderInt(0, 90, DNCPvP.Config.DNCPvP_WaltzThreshold, "Curing Waltz HP% - caps at 90 to prevent waste.", 150, SliderIncrements.Ones); - - #endregion - - #endregion // ==================================================================================== - #region DARK KNIGHT - - if (preset == CustomComboPreset.DRK_ST_ManaSpenderPooling && enabled) - UserConfig.DrawSliderInt(0, 3000, DRK.Config.DRK_ST_ManaSpenderPooling, "How much MP to save (0 = Use All)", 150, SliderIncrements.Thousands); - - if (preset == CustomComboPreset.DRK_ST_CDs_LivingShadow && enabled) - UserConfig.DrawSliderInt(0, 30, DRK.Config.DRK_ST_LivingDeadThreshold, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)", 150, SliderIncrements.Fives); - - if (preset == CustomComboPreset.DRK_AoE_CDs_LivingShadow && enabled) - UserConfig.DrawSliderInt(0, 60, DRK.Config.DRK_AoE_LivingDeadThreshold, "Stop Using When Target HP% is at or Below (Set to 0 to Disable This Check)", 150, SliderIncrements.Fives); - - if (preset == CustomComboPreset.DRKPvP_Burst) - UserConfig.DrawSliderInt(1, 100, DRKPvP.Config.ShadowbringerThreshold, "HP% to be at or above to use Shadowbringer"); - - if (preset == CustomComboPreset.DRK_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, DRK.Config.DRK_VariantCure, "HP% to be at or under", 200); - - #endregion // ==================================================================================== // ==================================================================================== - #region GUNBREAKER - - if (preset == CustomComboPreset.GNB_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, GNB.Config.GNB_VariantCure, "HP% to be at or under", 200); - if (preset == CustomComboPreset.GNB_ST_NoMercy) - UserConfig.DrawSliderInt(0, 25, GNB.Config.GNB_ST_NoMercyStop, "Stop Usage if Target HP% is below set value.\nTo Disable this option, set to 0."); - if (preset == CustomComboPreset.GNB_AoE_NoMercy) - UserConfig.DrawSliderInt(0, 25, GNB.Config.GNB_AoE_NoMercyStop, "Stop Usage if Target HP% is below set value.\nTo Disable this option, set to 0."); - - #endregion // ==================================================================================== // ==================================================================================== - #region MONK if (preset == CustomComboPreset.MNK_ST_ComboHeals) @@ -1387,384 +1234,19 @@ internal static void Draw(CustomComboPreset preset, bool enabled) #endregion // ==================================================================================== - #region NINJA - - if (preset == CustomComboPreset.NIN_Simple_Mudras) - { - UserConfig.DrawRadioButton(NIN.Config.NIN_SimpleMudra_Choice, "Mudra Path Set 1", $"1. Ten Mudras -> Fuma Shuriken, Raiton/Hyosho Ranryu, Suiton (Doton under Kassatsu).\nChi Mudras -> Fuma Shuriken, Hyoton, Huton.\nJin Mudras -> Fuma Shuriken, Katon/Goka Mekkyaku, Doton", 1); - UserConfig.DrawRadioButton(NIN.Config.NIN_SimpleMudra_Choice, "Mudra Path Set 2", $"2. Ten Mudras -> Fuma Shuriken, Hyoton/Hyosho Ranryu, Doton.\nChi Mudras -> Fuma Shuriken, Katon, Suiton.\nJin Mudras -> Fuma Shuriken, Raiton/Goka Mekkyaku, Huton (Doton under Kassatsu).", 2); - } - if (preset == CustomComboPreset.NIN_ST_AdvancedMode) - UserConfig.DrawSliderInt(0, 10, NIN.Config.BurnKazematoi, "Target HP% to dump all pooled Kazematoi below"); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_Bhavacakra) - UserConfig.DrawSliderInt(50, 100, NIN.Config.Ninki_BhavaPooling, "Set the minimal amount of Ninki required to have before spending on Bhavacakra."); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack) - UserConfig.DrawSliderInt(0, 21, NIN.Config.Trick_CooldownRemaining, "Set the amount of time remaining on Trick Attack cooldown before trying to set up with Suiton."); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_Bunshin) - UserConfig.DrawSliderInt(50, 100, NIN.Config.Ninki_BunshinPoolingST, "Set the amount of Ninki required to have before spending on Bunshin."); - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_Bunshin) - UserConfig.DrawSliderInt(50, 100, NIN.Config.Ninki_BunshinPoolingAoE, "Set the amount of Ninki required to have before spending on Bunshin."); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_TrickAttack_Cooldowns) - UserConfig.DrawSliderInt(0, 21, NIN.Config.Advanced_Trick_Cooldown, "Set the amount of time remaining on Trick Attack cooldown to start saving cooldowns."); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_SecondWind) - UserConfig.DrawSliderInt(0, 100, NIN.Config.SecondWindThresholdST, "Set a HP% threshold for when Second Wind will be used."); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_ShadeShift) - UserConfig.DrawSliderInt(0, 100, NIN.Config.ShadeShiftThresholdST, "Set a HP% threshold for when Shade Shift will be used."); - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_Bloodbath) - UserConfig.DrawSliderInt(0, 100, NIN.Config.BloodbathThresholdST, "Set a HP% threshold for when Bloodbath will be used."); - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_SecondWind) - UserConfig.DrawSliderInt(0, 100, NIN.Config.SecondWindThresholdAoE, "Set a HP% threshold for when Second Wind will be used."); - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_ShadeShift) - UserConfig.DrawSliderInt(0, 100, NIN.Config.ShadeShiftThresholdAoE, "Set a HP% threshold for when Shade Shift will be used."); - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_Bloodbath) - UserConfig.DrawSliderInt(0, 100, NIN.Config.BloodbathThresholdAoE, "Set a HP% threshold for when Bloodbath will be used."); - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_HellfrogMedium) - UserConfig.DrawSliderInt(50, 100, NIN.Config.Ninki_HellfrogPooling, "Set the amount of Ninki required to have before spending on Hellfrog Medium."); - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_Ninjitsus_Doton) - { - UserConfig.DrawSliderInt(0, 18, NIN.Config.Advanced_DotonTimer, "Sets the amount of time remaining on Doton before casting again."); - UserConfig.DrawSliderInt(0, 100, NIN.Config.Advanced_DotonHP, "Sets the max remaining HP percentage of the current target to cast Doton."); - } - - if (preset == CustomComboPreset.NIN_AoE_AdvancedMode_TCJ) - { - UserConfig.DrawRadioButton(NIN.Config.Advanced_TCJEnderAoE, "Ten Chi Jin Ender 1", "Ends Ten Chi Jin with Suiton.", 0); - UserConfig.DrawRadioButton(NIN.Config.Advanced_TCJEnderAoE, $"Ten Chi Jin Ender 2", "Ends Ten Chi Jin with Doton.\nIf you have Doton enabled, Ten Chi Jin will be delayed according to the settings in that feature.", 1); - } - - if (preset == CustomComboPreset.NIN_ST_AdvancedMode_Ninjitsus_Raiton) - { - UserConfig.DrawAdditionalBoolChoice(NIN.Config.Advanced_ChargePool, "Pool Charges", "Waits until at least 2 seconds before your 2nd charge or if Trick Attack debuff is on your target before spending."); - } - - if (preset == CustomComboPreset.NIN_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, NIN.Config.NIN_VariantCure, "HP% to be at or under", 200); - - #endregion // ==================================================================================== - #region PICTOMANCER - if (preset == CustomComboPreset.CombinedAetherhues) - { - UserConfig.DrawRadioButton(PCT.Config.CombinedAetherhueChoices, "Both Single Target & AoE", $"Replaces both {PCT.FireInRed.ActionName()} & {PCT.FireIIinRed.ActionName()}", 0); - UserConfig.DrawRadioButton(PCT.Config.CombinedAetherhueChoices, "Single Target Only", $"Replace only {PCT.FireInRed.ActionName()}", 1); - UserConfig.DrawRadioButton(PCT.Config.CombinedAetherhueChoices, "AoE Only", $"Replace only {PCT.FireIIinRed.ActionName()}", 2); - } - - if (preset == CustomComboPreset.CombinedMotifs) - { - UserConfig.DrawAdditionalBoolChoice(PCT.Config.CombinedMotifsMog, $"{PCT.MogoftheAges.ActionName()} Feature", $"Add {PCT.MogoftheAges.ActionName()} when fully drawn and off cooldown."); - UserConfig.DrawAdditionalBoolChoice(PCT.Config.CombinedMotifsMadeen, $"{PCT.RetributionoftheMadeen.ActionName()} Feature", $"Add {PCT.RetributionoftheMadeen.ActionName()} when fully drawn and off cooldown."); - UserConfig.DrawAdditionalBoolChoice(PCT.Config.CombinedMotifsWeapon, $"{PCT.HammerStamp.ActionName()} Feature", $"Add {PCT.HammerStamp.ActionName()} when under the effect of {PCT.Buffs.HammerTime.StatusName()}."); - } - - if(preset == CustomComboPreset.PCT_ST_AdvancedMode_LucidDreaming ) - { - UserConfig.DrawSliderInt(0, 10000, PCT.Config.PCT_ST_AdvancedMode_LucidOption, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); - } - - if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_HolyinWhite) - { - UserConfig.DrawSliderInt(0, 5, PCT.Config.PCT_AoE_AdvancedMode_HolyinWhiteOption, "How many charges to keep ready? (0 = Use all)"); - } - - if(preset == CustomComboPreset.PCT_AoE_AdvancedMode_LucidDreaming) - { - UserConfig.DrawSliderInt(0, 10000, PCT.Config.PCT_AoE_AdvancedMode_LucidOption, "Add Lucid Dreaming when below this MP", sliderIncrement: SliderIncrements.Hundreds); - } - if (preset == CustomComboPreset.PCT_ST_AdvancedMode_LandscapeMotif) - UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_ST_LandscapeStop, "Health % to stop Drawing Motif"); - if (preset == CustomComboPreset.PCT_ST_AdvancedMode_CreatureMotif) - UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_ST_CreatureStop, "Health % to stop Drawing Motif"); - if (preset == CustomComboPreset.PCT_ST_AdvancedMode_WeaponMotif) - UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_ST_WeaponStop, "Health % to stop Drawing Motif"); - if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_LandscapeMotif) - UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_AoE_LandscapeStop, "Health % to stop Drawing Motif"); - if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_CreatureMotif) - UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_AoE_CreatureStop, "Health % to stop Drawing Motif"); - if (preset == CustomComboPreset.PCT_AoE_AdvancedMode_WeaponMotif) - UserConfig.DrawSliderInt(0, 10, PCT.Config.PCT_AoE_WeaponStop, "Health % to stop Drawing Motif"); - - if (preset == CustomComboPreset.PCT_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, PCT.Config.PCT_VariantCure, "HP% to be at or under", 200); - - // PvP - if (preset == CustomComboPreset.PCTPvP_BurstControl) - UserConfig.DrawSliderInt(1, 100, PCTPvP.Config.PCTPvP_BurstHP, "Target HP%", 200); - - if (preset == CustomComboPreset.PCTPvP_TemperaCoat) - UserConfig.DrawSliderInt(1, 100, PCTPvP.Config.PCTPvP_TemperaHP, "Player HP%", 200); - #endregion // ==================================================================================== - #region PALADIN - - // Fight or Flight - if (preset == CustomComboPreset.PLD_ST_AdvancedMode_FoF) - UserConfig.DrawSliderInt(0, 50, PLD.Config.PLD_ST_FoF_Trigger, "Target HP%", 200); - - if (preset == CustomComboPreset.PLD_AoE_AdvancedMode_FoF) - UserConfig.DrawSliderInt(0, 50, PLD.Config.PLD_AoE_FoF_Trigger, "Target HP%", 200); - - // Sheltron - if (preset == CustomComboPreset.PLD_ST_AdvancedMode_Sheltron) - UserConfig.DrawSliderInt(50, 100, PLD.Config.PLD_ST_SheltronOption, "Oath Gauge", 200, 5); - - if (preset == CustomComboPreset.PLD_AoE_AdvancedMode_Sheltron) - UserConfig.DrawSliderInt(50, 100, PLD.Config.PLD_AoE_SheltronOption, "Oath Gauge", 200, 5); - - // Intervene - if (preset == CustomComboPreset.PLD_ST_AdvancedMode_Intervene) - { - UserConfig.DrawSliderInt(0, 1, PLD.Config.PLD_Intervene_HoldCharges, "Charges", 200); - UserConfig.DrawHorizontalRadioButton(PLD.Config.PLD_Intervene_MeleeOnly, "Melee Range", "Uses Intervene while within melee range.\nMay result in minor movement.", 1); - UserConfig.DrawHorizontalRadioButton(PLD.Config.PLD_Intervene_MeleeOnly, "No Movement", "Only uses Intervene when it would not result in movement (zero distance).", 2); - } - - if (preset == CustomComboPreset.PLD_AoE_AdvancedMode_Intervene) - { - UserConfig.DrawSliderInt(0, 1, PLD.Config.PLD_AoE_Intervene_HoldCharges, "Charges", 200); - UserConfig.DrawHorizontalRadioButton(PLD.Config.PLD_AoE_Intervene_MeleeOnly, "Melee Range", "Uses Intervene while within melee range.\nMay result in minor movement.", 1); - UserConfig.DrawHorizontalRadioButton(PLD.Config.PLD_AoE_Intervene_MeleeOnly, "No Movement", "Only uses Intervene when it would not result in movement (zero distance).", 2); - } - - // Shield Lob - if (preset == CustomComboPreset.PLD_ST_AdvancedMode_ShieldLob) - { - UserConfig.DrawHorizontalRadioButton(PLD.Config.PLD_ShieldLob_SubOption, "Shield Lob Only", "Uses only Shield Lob.", 1); - UserConfig.DrawHorizontalRadioButton(PLD.Config.PLD_ShieldLob_SubOption, "Hardcast Holy Spirit", "Attempts to hardcast Holy Spirit when not moving.\nOtherwise uses Shield Lob.", 2); - } - - // MP Reservation - if (preset == CustomComboPreset.PLD_ST_AdvancedMode_MP_Reserve) - UserConfig.DrawSliderInt(1000, 5000, PLD.Config.PLD_ST_MP_Reserve, "Minimum MP", sliderIncrement: 100); - - if (preset == CustomComboPreset.PLD_AoE_AdvancedMode_MP_Reserve) - UserConfig.DrawSliderInt(1000, 5000, PLD.Config.PLD_AoE_MP_Reserve, "Minimum MP", sliderIncrement: 100); - - // Requiescat Spender Feature - if (preset == CustomComboPreset.PLD_Requiescat_Options) - { - UserConfig.DrawRadioButton(PLD.Config.PLD_RequiescatOption, "Confiteor", "", 1); - UserConfig.DrawRadioButton(PLD.Config.PLD_RequiescatOption, "Blade of Faith/Truth/Valor", "", 2); - UserConfig.DrawRadioButton(PLD.Config.PLD_RequiescatOption, "Confiteor & Blade of Faith/Truth/Valor", "", 3); - UserConfig.DrawRadioButton(PLD.Config.PLD_RequiescatOption, "Holy Spirit", "", 4); - UserConfig.DrawRadioButton(PLD.Config.PLD_RequiescatOption, "Holy Circle", "", 5); - } - - // Spirits Within / Circle of Scorn Feature - if (preset == CustomComboPreset.PLD_SpiritsWithin) - { - UserConfig.DrawRadioButton(PLD.Config.PLD_SpiritsWithinOption, "Prioritize Circle of Scorn", "", 1); - UserConfig.DrawRadioButton(PLD.Config.PLD_SpiritsWithinOption, "Prioritize Spirits Within / Expiacion", "", 2); - } - - // Variant Cure Feature - if (preset == CustomComboPreset.PLD_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, PLD.Config.PLD_VariantCure, "Player HP%", 200); - - #endregion // ==================================================================================== - // ==================================================================================== - // ==================================================================================== - // ==================================================================================== - #region SAMURAI - - if (preset == CustomComboPreset.SAM_ST_CDs_Iaijutsu) - { - UserConfig.DrawSliderInt(0, 100, SAM.Config.SAM_ST_Higanbana_Threshold, "Stop using Higanbana on targets below this HP % (0% = always use).", 150, SliderIncrements.Ones); - } - if (preset == CustomComboPreset.SAM_ST_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, SAM.Config.SAM_STSecondWindThreshold, "HP percent threshold to use Second Wind below (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, SAM.Config.SAM_STBloodbathThreshold, "HP percent threshold to use Bloodbath (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.SAM_AoE_ComboHeals) - { - UserConfig.DrawSliderInt(0, 100, SAM.Config.SAM_AoESecondWindThreshold, "HP percent threshold to use Second Wind below (0 = Disabled)", 150, SliderIncrements.Ones); - UserConfig.DrawSliderInt(0, 100, SAM.Config.SAM_AoEBloodbathThreshold, "HP percent threshold to use Bloodbath below (0 = Disabled)", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.SAM_ST_Shinten) - { - UserConfig.DrawSliderInt(50, 85, SAM.Config.SAM_ST_KenkiOvercapAmount, "Set the Kenki overcap amount for ST combos."); - UserConfig.DrawSliderInt(0, 100, SAM.Config.SAM_ST_ExecuteThreshold, "HP percent threshold to not save Kenki", 150, SliderIncrements.Ones); - } - - if (preset == CustomComboPreset.SAM_AoE_Kyuten) - UserConfig.DrawSliderInt(50, 85, SAM.Config.SAM_AoE_KenkiOvercapAmount, "Set the Kenki overcap amount for AOE combos."); - - if (preset == CustomComboPreset.SAM_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, SAM.Config.SAM_VariantCure, "HP% to be at or under", 200); - - //PvP - if (preset == CustomComboPreset.SAMPvP_BurstMode && enabled) - UserConfig.DrawSliderInt(0, 2, SAMPvP.Config.SAMPvP_SotenCharges, "How many charges of Soten to keep ready? (0 = Use All)."); - - if (preset == CustomComboPreset.SAMPvP_KashaFeatures_GapCloser && enabled) - UserConfig.DrawSliderInt(0, 100, SAMPvP.Config.SAMPvP_SotenHP, "Use Soten on enemies below selected HP."); - - if (preset == CustomComboPreset.SAM_ST_KashaCombo) - { - UserConfig.DrawAdditionalBoolChoice(SAM.Config.SAM_Kasha_KenkiOvercap, "Kenki Overcap Protection", "Spends Kenki when at the set value or above."); - if (SAM.Config.SAM_Kasha_KenkiOvercap) - UserConfig.DrawSliderInt(25, 100, SAM.Config.SAM_Kasha_KenkiOvercapAmount, "Kenki Amount", sliderIncrement: SliderIncrements.Fives); - } - - if (preset == CustomComboPreset.SAM_ST_YukikazeCombo) - { - UserConfig.DrawAdditionalBoolChoice(SAM.Config.SAM_Yukaze_KenkiOvercap, "Kenki Overcap Protection", "Spends Kenki when at the set value or above."); - if (SAM.Config.SAM_Yukaze_KenkiOvercap) - UserConfig.DrawSliderInt(25, 100, SAM.Config.SAM_Yukaze_KenkiOvercapAmount, "Kenki Amount", sliderIncrement: SliderIncrements.Fives); - } - - if (preset == CustomComboPreset.SAM_ST_GekkoCombo) - { - UserConfig.DrawAdditionalBoolChoice(SAM.Config.SAM_Gekko_KenkiOvercap, "Kenki Overcap Protection", "Spends Kenki when at the set value or above."); - if (SAM.Config.SAM_Gekko_KenkiOvercap) - UserConfig.DrawSliderInt(25, 100, SAM.Config.SAM_Gekko_KenkiOvercapAmount, "Kenki Amount", sliderIncrement: SliderIncrements.Fives); - } - - if (preset == CustomComboPreset.SAM_AoE_OkaCombo) - { - UserConfig.DrawAdditionalBoolChoice(SAM.Config.SAM_Oka_KenkiOvercap, "Kenki Overcap Protection", "Spends Kenki when at the set value or above."); - if (SAM.Config.SAM_Oka_KenkiOvercap) - UserConfig.DrawSliderInt(25, 100, SAM.Config.SAM_Oka_KenkiOvercapAmount, "Kenki Amount", sliderIncrement: SliderIncrements.Fives); - } - - if (preset == CustomComboPreset.SAM_AoE_MangetsuCombo) - { - UserConfig.DrawAdditionalBoolChoice(SAM.Config.SAM_Mangetsu_KenkiOvercap, "Kenki Overcap Protection", "Spends Kenki when at the set value or above."); - if (SAM.Config.SAM_Mangetsu_KenkiOvercap) - UserConfig.DrawSliderInt(25, 100, SAM.Config.SAM_Mangetsu_KenkiOvercapAmount, "Kenki Amount", sliderIncrement: SliderIncrements.Fives); - } - - #endregion // ==================================================================================== - // ==================================================================================== - #region SUMMONER - - #region PvE - if (preset == CustomComboPreset.SMN_DemiEgiMenu_EgiOrder) - { - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_PrimalChoice, "Titan first", "Summons Titan, Garuda then Ifrit.", 1); - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_PrimalChoice, "Garuda first", "Summons Garuda, Titan then Ifrit.", 2); - } - - if (preset == CustomComboPreset.SMN_DemiEgiMenu_oGCDPooling) - UserConfig.DrawSliderInt(0, 3, SMN.Config.SMN_Burst_Delay, "Sets the amount of GCDs under Demi summon to wait for oGCD use.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.SMN_DemiEgiMenu_oGCDPooling) - { - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_BurstPhase, "Solar Bahamut/Bahamut", "Bursts during Bahamut phase.\nBahamut burst phase becomes Solar Bahamut at Lv100.", 1); - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_BurstPhase, "Phoenix", "Bursts during Phoenix phase.", 2); - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_BurstPhase, "Any Demi Phase", "Bursts during any Demi Summon phase.", 3); - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_BurstPhase, "Flexible (SpS) Option", "Bursts when Searing Light is ready, regardless of phase.", 4); - } - - if (preset == CustomComboPreset.SMN_DemiEgiMenu_SwiftcastEgi) - { - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_SwiftcastPhase, "Garuda", "Swiftcasts Slipstream", 1); - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_SwiftcastPhase, "Ifrit", "Swiftcasts Ruby Ruin/Ruby Rite", 2); - UserConfig.DrawHorizontalRadioButton(SMN.Config.SMN_SwiftcastPhase, "Flexible (SpS) Option", "Swiftcasts the first available Egi when Swiftcast is ready.", 3); - } - - if (preset == CustomComboPreset.SMN_Lucid) - UserConfig.DrawSliderInt(4000, 9500, SMN.Config.SMN_Lucid, "Set value for your MP to be at or under for this feature to take effect.", 150, SliderIncrements.Hundreds); - - if (preset == CustomComboPreset.SMN_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, SMN.Config.SMN_VariantCure, "HP% to be at or under", 200); - - if (preset == CustomComboPreset.SMN_ST_Egi_AstralFlow) - { - UserConfig.DrawHorizontalMultiChoice(SMN.Config.SMN_ST_Egi_AstralFlow, "Add Mountain Buster", "", 3, 0); - UserConfig.DrawHorizontalMultiChoice(SMN.Config.SMN_ST_Egi_AstralFlow, "Add Crimson Cyclone", "", 3, 1); - UserConfig.DrawHorizontalMultiChoice(SMN.Config.SMN_ST_Egi_AstralFlow, "Add Slipstream", "", 3, 2); - - if (SMN.Config.SMN_ST_Egi_AstralFlow[1]) - UserConfig.DrawAdditionalBoolChoice(SMN.Config.SMN_ST_CrimsonCycloneMelee, "Enforced Crimson Cyclone Melee Check", "Only uses Crimson Cyclone within melee range."); - } - - - - #endregion - - #region PvP - - if (preset == CustomComboPreset.SMNPvP_BurstMode) - UserConfig.DrawSliderInt(50, 100, SMNPvP.Config.SMNPvP_FesterThreshold, "Target HP% to cast Fester below.\nSet to 100 use Fester as soon as it's available.", 150, SliderIncrements.Ones); - - if (preset == CustomComboPreset.SMNPvP_BurstMode_RadiantAegis) - UserConfig.DrawSliderInt(0, 90, SMNPvP.Config.SMNPvP_RadiantAegisThreshold, "Caps at 90 to prevent waste.", 150, SliderIncrements.Ones); - - #endregion - - #endregion // ==================================================================================== - // ==================================================================================== - #region WARRIOR - - if (preset == CustomComboPreset.WAR_ST_Advanced_StormsEye && enabled) - UserConfig.DrawSliderInt(0, 30, WAR.Config.WAR_SurgingRefreshRange, "Seconds remaining before refreshing Surging Tempest."); - - if (preset == CustomComboPreset.WAR_InfuriateFellCleave && enabled) - UserConfig.DrawSliderInt(0, 50, WAR.Config.WAR_InfuriateRange, "Set how much rage to be at or under to use this feature."); - - if (preset == CustomComboPreset.WAR_ST_Advanced_Onslaught && enabled) - UserConfig.DrawSliderInt(0, 2, WAR.Config.WAR_KeepOnslaughtCharges, "How many charges to keep ready? (0 = Use All)"); - - if (preset == CustomComboPreset.WAR_ST_Advanced_Infuriate && enabled) - UserConfig.DrawSliderInt(0, 2, WAR.Config.WAR_KeepInfuriateCharges, "How many charges to keep ready? (0 = Use All)"); - - if (preset == CustomComboPreset.WAR_Variant_Cure) - UserConfig.DrawSliderInt(1, 100, WAR.Config.WAR_VariantCure, "HP% to be at or under", 200); - - if (preset == CustomComboPreset.WAR_ST_Advanced_FellCleave) - UserConfig.DrawSliderInt(50, 100, WAR.Config.WAR_FellCleaveGauge, "Minimum gauge to spend"); - - if (preset == CustomComboPreset.WAR_AoE_Advanced_Decimate) - UserConfig.DrawSliderInt(50, 100, WAR.Config.WAR_DecimateGauge, "Minimum gauge to spend"); - - if (preset == CustomComboPreset.WAR_ST_Advanced_Infuriate) - UserConfig.DrawSliderInt(0, 50, WAR.Config.WAR_InfuriateSTGauge, "Use when gauge is under or equal to"); - - if (preset == CustomComboPreset.WAR_AoE_Advanced_Infuriate) - UserConfig.DrawSliderInt(0, 50, WAR.Config.WAR_InfuriateAoEGauge, "Use when gauge is under or equal to"); - - if (preset == CustomComboPreset.WARPvP_BurstMode_Blota) - { - UserConfig.DrawHorizontalRadioButton(WARPvP.Config.WARPVP_BlotaTiming, "Before Primal Rend", "", 0); - UserConfig.DrawHorizontalRadioButton(WARPvP.Config.WARPVP_BlotaTiming, "After Primal Rend", "", 1); - } - - #endregion // ==================================================================================== - // ==================================================================================== - #region DOH - - #endregion // ==================================================================================== - #region DOL - - #endregion // ==================================================================================== #region PvP VALUES From 46a5b53747cf89b84f121385fadbb5071c2dad42 Mon Sep 17 00:00:00 2001 From: Kage <95875972+Kagekazu@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:34:46 +0100 Subject: [PATCH 189/208] fix BLM --- XIVSlothCombo/Combos/PvE/BLM/BLM.cs | 79 +++++++++++++++++++--- XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs | 60 +++++----------- 2 files changed, 89 insertions(+), 50 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs index 6c1909412..bba6f5a3d 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; @@ -60,7 +62,7 @@ public static readonly Dictionary { HighThunder2, Debuffs.HighThunder2 } }; - private static int nextMpGain => Gauge.UmbralIceStacks switch + protected static int nextMpGain => Gauge.UmbralIceStacks switch { 0 => 0, 1 => 2500, @@ -133,6 +135,21 @@ internal class BLM_ST_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { + int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; + bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + + float elementTimer = Gauge.ElementTimeRemaining / 1000f; + double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + + int remainingPolyglotCD = Math.Max(0, + (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); + + Status? thunderDebuffST = + FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); + + uint curMp = LocalPlayer.CurrentMp; + if (actionID is not Fire) return actionID; @@ -170,7 +187,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionReady(Amplifier) && Gauge.PolyglotStacks < maxPolyglot) return Amplifier; - if (BLMHelper.HasPolyglotStacks(Gauge)) + if (HasPolyglotStacks(Gauge)) return LevelChecked(Xenoglossy) ? Xenoglossy : Foul; @@ -199,7 +216,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) return OriginalHook(Thunder); - if (BLMHelper.HasPolyglotStacks(Gauge) && gcdsInTimer >= 1 && + if (HasPolyglotStacks(Gauge) && gcdsInTimer >= 1 && (ActionReady(All.Swiftcast) || (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0 && @@ -239,7 +256,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) return OriginalHook(Thunder); - if (BLMHelper.HasPolyglotStacks(Gauge)) + if (HasPolyglotStacks(Gauge)) return LevelChecked(Xenoglossy) ? Xenoglossy : Foul; @@ -270,7 +287,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (Gauge.IsParadoxActive) return Paradox; - if (BLMHelper.HasPolyglotStacks(Gauge)) + if (HasPolyglotStacks(Gauge)) return LevelChecked(Xenoglossy) ? Xenoglossy : Foul; @@ -307,6 +324,20 @@ internal class BLM_ST_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { + int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; + bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + + float elementTimer = Gauge.ElementTimeRemaining / 1000f; + double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + + int remainingPolyglotCD = Math.Max(0, + (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); + uint curMp = LocalPlayer.CurrentMp; + + Status? thunderDebuffST = + FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); + int PolyglotStacks = Gauge.PolyglotStacks; float TriplecastChargetime = GetCooldownChargeRemainingTime(Triplecast); @@ -505,6 +536,22 @@ internal class BLM_AoE_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { + int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; + + float elementTimer = Gauge.ElementTimeRemaining / 1000f; + double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + + int remainingPolyglotCD = Math.Max(0, + (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); + uint curMp = LocalPlayer.CurrentMp; + + Status? thunderDebuffAoE = + FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); + + bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && + IsOffCooldown(All.Swiftcast); + if (actionID is not (Blizzard2 or HighBlizzard2)) return actionID; @@ -534,7 +581,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionReady(Amplifier) && Gauge.PolyglotStacks < maxPolyglot) return Amplifier; - if (BLMHelper.HasPolyglotStacks(Gauge)) + if (HasPolyglotStacks(Gauge)) return Foul; } @@ -575,7 +622,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (Gauge.InUmbralIce) { - if (BLMHelper.HasPolyglotStacks(Gauge)) + if (HasPolyglotStacks(Gauge)) return Foul; if (ActionWatching.WhichOfTheseActionsWasLast(OriginalHook(Fire2), OriginalHook(Freeze), @@ -640,6 +687,22 @@ internal class BLM_AoE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { + int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; + + float elementTimer = Gauge.ElementTimeRemaining / 1000f; + double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + + Status? thunderDebuffAoE = + FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); + + int remainingPolyglotCD = Math.Max(0, + (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); + uint curMp = LocalPlayer.CurrentMp; + + bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && + IsOffCooldown(All.Swiftcast); + int PolyglotStacks = Gauge.PolyglotStacks; float TriplecastChargetime = GetCooldownChargeRemainingTime(Triplecast); @@ -808,7 +871,7 @@ internal class BLM_Scathe_Xeno : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - return actionID is Scathe && LevelChecked(Xenoglossy) && BLMHelper.HasPolyglotStacks(Gauge) + return actionID is Scathe && LevelChecked(Xenoglossy) && HasPolyglotStacks(Gauge) ? Xenoglossy : actionID; } diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs index 3c65aabf0..d32191059 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Dalamud.Game.ClientState.JobGauge.Types; -using Dalamud.Game.ClientState.Statuses; using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Data; @@ -15,30 +14,10 @@ internal partial class BLM // BLM Gauge & Extensions public static BLMGauge Gauge => GetJobGauge(); - public static int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : - TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - - public static bool canWeave = CanSpellWeave(ActionWatching.LastSpell); - - public static int remainingPolyglotCD = Math.Max(0, - (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); - - public static uint curMp = LocalPlayer.CurrentMp; - - public static Status? thunderDebuffST = - FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); - - public static Status? thunderDebuffAoE = - FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); - - public static float elementTimer = Gauge.ElementTimeRemaining / 1000f; - public static double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(Fire)); - - public static bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && - IsOffCooldown(All.Swiftcast); - public static int Fire4Count => ActionWatching.CombatActions.Count(x => x == Fire4); + public static bool HasPolyglotStacks(BLMGauge gauge) => gauge.PolyglotStacks > 0; + internal class BLMOpenerLogic { private OpenerState currentState = OpenerState.PrePull; @@ -63,7 +42,7 @@ public OpenerState CurrentState if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; - if (value is OpenerState.OpenerFinished or OpenerState.FailedOpener) + if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) Svc.Log.Information($"Opener Failed at step {OpenerStep}"); @@ -91,9 +70,6 @@ private static bool HasCooldowns() if (!ActionReady(Amplifier)) return false; - if (!ActionReady(LeyLines)) - return false; - return true; } @@ -149,7 +125,7 @@ private bool DoOpener(ref uint actionID) if (WasLastAction(Triplecast) && OpenerStep == 7) OpenerStep++; else if (OpenerStep == 7) actionID = Triplecast; - if (WasLastAction(LeyLines) && OpenerStep == 8) OpenerStep++; + if ((WasLastAction(LeyLines) || IsOnCooldown(LeyLines)) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = LeyLines; if (WasLastAction(Fire4) && Fire4Count is 3 && OpenerStep == 9) OpenerStep++; @@ -249,8 +225,6 @@ public bool DoFullOpener(ref uint actionID) internal class BLMHelper { - public static bool HasPolyglotStacks(BLMGauge Gauge) => Gauge.PolyglotStacks > 0; - public static float MPAfterCast() { uint castedSpell = LocalPlayer.CastActionId; @@ -261,12 +235,13 @@ public static float MPAfterCast() 1 => 2500, 2 => 5000, 3 => 10000, - var _ => 0 + _ => 0 }; - return castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2 - ? Math.Max(LocalPlayer.MaxMp, LocalPlayer.CurrentMp + nextMpGain) - : Math.Max(0, LocalPlayer.CurrentMp - GetResourceCost(castedSpell)); + if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) + return Math.Max(LocalPlayer.MaxMp, LocalPlayer.CurrentMp + nextMpGain); + + return Math.Max(0, LocalPlayer.CurrentMp - GetResourceCost(castedSpell)); } public static bool DoubleBlizz() @@ -279,18 +254,19 @@ public static bool DoubleBlizz() uint firstSpell = spells[^1]; - switch (firstSpell) + if (firstSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) { - case Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2: - { - uint castedSpell = LocalPlayer.CastActionId; + uint castedSpell = LocalPlayer.CastActionId; - if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - return true; + if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) + return true; - if (spells is [.., Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2, var _]) return true; + if (spells.Count >= 2) + { + uint secondSpell = spells[^2]; - break; + if (secondSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) + return true; } } From 70ec5859ff3d7eef3a488102462a04051dc1fdd7 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 8 Nov 2024 16:17:07 +0000 Subject: [PATCH 190/208] RezSuna --- .../AutoRotation/AutoRotationConfig.cs | 3 + .../AutoRotation/AutoRotationController.cs | 62 +++++++++++++++++-- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 5 ++ 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs index 0a95ec429..3df3c8596 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -26,5 +26,8 @@ public class HealerSettings public int? AoEHealTargetCount = 2; public bool ManageKardia = false; public bool KardiaTanksOnly = false; + public bool AutoRez = false; + public bool AutoCleanse = false; + } } diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 35c475f07..555fe4f58 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -2,6 +2,7 @@ using Dalamud.Game.ClientState.Objects.Types; using ECommons; using ECommons.DalamudServices; +using ECommons.ExcelServices; using ECommons.GameFunctions; using ECommons.GameHelpers; using ECommons.Throttlers; @@ -34,6 +35,28 @@ internal static void Run() if (Player.Job is ECommons.ExcelServices.Job.SGE && Service.Configuration.RotationConfig.HealerSettings.ManageKardia) UpdateKardiaTarget(); + var healTarget = Player.Object.GetRole() is CombatRole.Healer ? AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode) : null; + var aoeheal = Player.Object.GetRole() is CombatRole.Healer ? HealerTargeting.CanAoEHeal() : false; + + if (Player.Object.GetRole() is CombatRole.Healer) + { + bool needsHeal = healTarget != null || aoeheal; + + if (Service.Configuration.RotationConfig.HealerSettings.AutoCleanse && !needsHeal) + { + CleanseParty(); + if (CustomComboFunctions.GetPartyMembers().Any((x => CustomComboFunctions.HasCleansableDebuff(x)))) + return; + } + + if (Service.Configuration.RotationConfig.HealerSettings.AutoRez) + { + RezParty(); + if (CustomComboFunctions.GetPartyMembers().Any(x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null)) + return; + } + } + foreach (var preset in Service.Configuration.AutoActions.OrderByDescending(x => Presets.Attributes[x.Key].AutoAction.IsHeal) .ThenByDescending(x => Presets.Attributes[x.Key].AutoAction.IsAoE)) { @@ -48,8 +71,6 @@ internal static void Run() continue; var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); - var healTarget = Player.Object.GetRole() is CombatRole.Healer ? AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode) : null; - var aoeheal = Player.Object.GetRole() is CombatRole.Healer ? HealerTargeting.CanAoEHeal(gameAct) : false; if (action.IsHeal) { @@ -75,6 +96,35 @@ internal static void Run() } + private static void RezParty() + { + uint resSpell = Player.Job switch + { + Job.CNJ or Job.WHM => WHM.Raise, + Job.SCH => SCH.Resurrection, + Job.AST => AST.Ascend, + Job.SGE => SGE.Egeiro, + _ => throw new NotImplementedException(), + }; + + if (Player.Object.CurrentMp >= CustomComboFunctions.GetResourceCost(resSpell)) + { + if (CustomComboFunctions.GetPartyMembers().FindFirst(x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null, out var member)) + { + ActionManager.Instance()->UseAction(ActionType.Action, resSpell, member.GameObjectId); + } + } + } + + private static void CleanseParty() + { + if (ActionManager.Instance()->QueuedActionId == All.Esuna) + ActionManager.Instance()->QueuedActionId = 0; + + if (CustomComboFunctions.GetPartyMembers().FindFirst(x => CustomComboFunctions.HasCleansableDebuff(x), out var member)) + ActionManager.Instance()->UseAction(ActionType.Action, All.Esuna, member.GameObjectId); + } + private static void UpdateKardiaTarget() { if (!CustomComboFunctions.LevelChecked(SGE.Kardia)) return; @@ -244,7 +294,7 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset target = newtarget; } } - + var areaTargeted = Svc.Data.GetExcelSheet().GetRow(outAct).TargetArea; var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, target.Struct()) != 562; var canUseTarget = ActionManager.CanUseActionOnTarget(outAct, target.Struct()); @@ -256,7 +306,7 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset { Svc.Targets.Target = target; - var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); + var ret = ActionManager.Instance()->UseAction(ActionType.Action, outAct, canUseTarget ? target.GameObjectId : Player.Object.GameObjectId); if (mode is HealerRotationMode && ret) LastHealAt = Environment.TickCount64 + castTime; @@ -372,9 +422,9 @@ public static class HealerTargeting return target; } - internal static bool CanAoEHeal(uint outAct) + internal static bool CanAoEHeal(uint outAct = 0) { - var members = CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.InActionRange(outAct, x) && CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP); + var members = CustomComboFunctions.GetPartyMembers().Where(x => (outAct == 0 ? CustomComboFunctions.GetTargetDistance(x) <= 15 : CustomComboFunctions.InActionRange(outAct, x)) && CustomComboFunctions.GetTargetHPPercent(x) <= Service.Configuration.RotationConfig.HealerSettings.AoETargetHPP); if (members.Count() < Service.Configuration.RotationConfig.HealerSettings.AoEHealTargetCount) return false; diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 18d7757eb..710f11cbf 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -77,6 +77,11 @@ internal class AutoRotationTab : ConfigWindow } ImGuiComponents.HelpMarker($"Disabling this will turn off AoE Healing features. Otherwise will require the amount of targets required to be in range of an AoE feature's heal to use."); ImGui.Spacing(); + changed |= ImGui.Checkbox("Auto-Rez", ref cfg.HealerSettings.AutoRez); + ImGuiComponents.HelpMarker("Will attempt to resurrect dead party members."); + changed |= ImGui.Checkbox($"Auto-{All.Esuna.ActionName()}", ref cfg.HealerSettings.AutoCleanse); + ImGuiComponents.HelpMarker($"Will {All.Esuna.ActionName()} any cleansable debuffs (Healing takes priority)."); + changed |= ImGui.Checkbox($"[{Svc.Data.GetExcelSheet().GetRow(40).Abbreviation}] Automatically Manage Kardia", ref cfg.HealerSettings.ManageKardia); ImGuiComponents.HelpMarker($"Switches {SGE.Kardia.ActionName()} to party members currently being targeted by enemies, prioritising tanks if multiple people are being targeted."); if (cfg.HealerSettings.ManageKardia) From 7d05efc8b4c3cf5788d2b47767fb6422bcdda1c3 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 8 Nov 2024 16:22:31 +0000 Subject: [PATCH 191/208] SwiftRezSuna --- XIVSlothCombo/AutoRotation/AutoRotationController.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 555fe4f58..44a00458d 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -109,9 +109,16 @@ private static void RezParty() if (Player.Object.CurrentMp >= CustomComboFunctions.GetResourceCost(resSpell)) { + if (CustomComboFunctions.ActionReady(All.Swiftcast)) + { + ActionManager.Instance()->UseAction(ActionType.Action, All.Swiftcast); + return; + } + if (CustomComboFunctions.GetPartyMembers().FindFirst(x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null, out var member)) { - ActionManager.Instance()->UseAction(ActionType.Action, resSpell, member.GameObjectId); + if (!CustomComboFunctions.IsMoving || CustomComboFunctions.HasEffect(All.Buffs.Swiftcast)) + ActionManager.Instance()->UseAction(ActionType.Action, resSpell, member.GameObjectId); } } } From c4f7454a03e574213271ab35ae22375c1c968760 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 9 Nov 2024 09:34:33 +0000 Subject: [PATCH 192/208] Doot doot --- .../AutoRotation/AutoRotationController.cs | 47 ++++++++++--------- XIVSlothCombo/Combos/PvE/SGE/SGE.cs | 2 +- XIVSlothCombo/CustomCombo/Functions/Target.cs | 39 +++++++++++++-- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 44a00458d..5be26ea7c 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -109,14 +109,14 @@ private static void RezParty() if (Player.Object.CurrentMp >= CustomComboFunctions.GetResourceCost(resSpell)) { - if (CustomComboFunctions.ActionReady(All.Swiftcast)) - { - ActionManager.Instance()->UseAction(ActionType.Action, All.Swiftcast); - return; - } - if (CustomComboFunctions.GetPartyMembers().FindFirst(x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null, out var member)) { + if (CustomComboFunctions.ActionReady(All.Swiftcast)) + { + ActionManager.Instance()->UseAction(ActionType.Action, All.Swiftcast); + return; + } + if (!CustomComboFunctions.IsMoving || CustomComboFunctions.HasEffect(All.Buffs.Swiftcast)) ActionManager.Instance()->UseAction(ActionType.Action, resSpell, member.GameObjectId); } @@ -128,7 +128,7 @@ private static void CleanseParty() if (ActionManager.Instance()->QueuedActionId == All.Esuna) ActionManager.Instance()->QueuedActionId = 0; - if (CustomComboFunctions.GetPartyMembers().FindFirst(x => CustomComboFunctions.HasCleansableDebuff(x), out var member)) + if (CustomComboFunctions.GetPartyMembers().FindFirst(x => CustomComboFunctions.HasCleansableDebuff(x), out var member) && !CustomComboFunctions.IsMoving) ActionManager.Instance()->UseAction(ActionType.Action, All.Esuna, member.GameObjectId); } @@ -139,7 +139,8 @@ private static void UpdateKardiaTarget() foreach (var member in CustomComboFunctions.GetPartyMembers().OrderByDescending(x => x.GetRole() is CombatRole.Tank)) { - if (Service.Configuration.RotationConfig.HealerSettings.KardiaTanksOnly && member.GetRole() is not CombatRole.Tank) continue; + if (Service.Configuration.RotationConfig.HealerSettings.KardiaTanksOnly && member.GetRole() is not CombatRole.Tank && + CustomComboFunctions.FindEffectOnMember(3615, member) is null) continue; var enemiesTargeting = Svc.Objects.Where(x => x.IsTargetable && x.IsHostile() && x.TargetObjectId == member.GameObjectId).Count(); if (enemiesTargeting > 0 && CustomComboFunctions.FindEffectOnMember(SGE.Buffs.Kardion, member) is null) @@ -263,12 +264,12 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese return false; var target = GetSingleTarget(mode); - var sheet = Svc.Data.GetExcelSheet().GetRow(gameAct); + var sheet = Svc.Data.GetExcelSheet().GetRow(outAct); var mustTarget = sheet.CanTargetHostile; var numEnemies = CustomComboFunctions.NumberOfEnemiesInRange(gameAct, target); - if (numEnemies >= Service.Configuration.RotationConfig.DPSSettings.DPSAoETargets || - (sheet.EffectRange == 0 && sheet.CanTargetSelf && !mustTarget)) + if (numEnemies >= Service.Configuration.RotationConfig.DPSSettings.DPSAoETargets) { + bool switched = SwitchOnDChole(attributes, outAct, ref target); var castTime = ActionManager.GetAdjustedCastTime(ActionType.Action, outAct); if (CustomComboFunctions.IsMoving && castTime > 0) return false; @@ -276,7 +277,7 @@ public static bool ExecuteAoE(Enum mode, CustomComboPreset preset, Presets.Prese if (mustTarget) Svc.Targets.Target = target; - return ActionManager.Instance()->UseAction(ActionType.Action, outAct, mustTarget && target != null ? target.GameObjectId : Player.Object.GameObjectId); + return ActionManager.Instance()->UseAction(ActionType.Action, gameAct, (mustTarget && target != null) || switched ? target.GameObjectId : Player.Object.GameObjectId); } } return false; @@ -293,14 +294,7 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset if (CustomComboFunctions.IsMoving && castTime > 0) return false; - if (outAct is SGE.Druochole && !attributes.AutoAction.IsHeal) - { - if (CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.FindEffectOnMember(SGE.Buffs.Kardion, x) is not null).TryGetFirst(out var newtarget)) - { - Svc.Log.Debug($"DChole switch"); - target = newtarget; - } - } + bool switched = SwitchOnDChole(attributes, outAct, ref target); var areaTargeted = Svc.Data.GetExcelSheet().GetRow(outAct).TargetArea; var inRange = ActionManager.GetActionInRangeOrLoS(outAct, Player.GameObject, target.Struct()) != 562; @@ -323,6 +317,17 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset return false; } + private static bool SwitchOnDChole(Presets.PresetAttributes attributes, uint outAct, ref IGameObject newtarget) + { + if (outAct is SGE.Druochole && !attributes.AutoAction.IsHeal) + { + if (CustomComboFunctions.GetPartyMembers().Where(x => CustomComboFunctions.FindEffectOnMember(SGE.Buffs.Kardion, x) is not null).TryGetFirst(out newtarget)) + return true; + } + + return false; + } + public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttributes attributes, IGameObject? optionalTarget = null) { var outAct = attributes.ReplaceSkill.ActionIDs.FirstOrDefault(); @@ -345,7 +350,7 @@ public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttribute public class DPSTargeting { - public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable && ActionManager.GetActionInRangeOrLoS(7, Player.GameObject, x.Struct()) != 562).OrderByDescending(x => IsPriority(x)); + public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable && CustomComboFunctions.IsInLineOfSight(x)).OrderByDescending(x => IsPriority(x)); private static bool IsPriority(IGameObject x) { diff --git a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs index 5f1d4ddb2..0bfdba796 100644 --- a/XIVSlothCombo/Combos/PvE/SGE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE/SGE.cs @@ -198,7 +198,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Soteria; // Addersgall Protection - if (IsEnabled(CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) && CanSpellWeave(Dosis) && + if (IsEnabled(CustomComboPreset.SGE_AoE_DPS_AddersgallProtect) && CanSpellWeave(ActionWatching.LastSpell) && ActionReady(Druochole) && Gauge.Addersgall >= Config.SGE_AoE_DPS_AddersgallProtect) return Druochole; diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 6c042565b..efe7964d4 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -4,16 +4,18 @@ using ECommons; using ECommons.DalamudServices; using ECommons.GameFunctions; +using ECommons.GameHelpers; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Character; +using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.System.Framework; +using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; using System; using System.Linq; using System.Numerics; using XIVSlothCombo.Data; using XIVSlothCombo.Services; using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; -using StructsObject = FFXIVClientStructs.FFXIV.Client.Game.Object; namespace XIVSlothCombo.CustomComboNS.Functions { @@ -141,7 +143,7 @@ public static bool HasFriendlyTarget(IGameObject? OurTarget = null) //if (checkMO && HasFriendlyTarget(tm.MouseOverTarget)) healTarget = tm.MouseOverTarget; if (checkMOPartyUI) { - StructsObject.GameObject* t = Framework.Instance()->GetUIModule()->GetPronounModule()->UiMouseOverTarget; + GameObject* t = Framework.Instance()->GetUIModule()->GetPronounModule()->UiMouseOverTarget; if (t != null && t->GetGameObjectId().ObjectId != 0) { IGameObject? uiTarget = Svc.Objects.Where(x => x.GameObjectId == t->GetGameObjectId().ObjectId).FirstOrDefault(); @@ -208,7 +210,7 @@ public static bool TargetNeedsPositionals() /// protected static unsafe void TargetObject(TargetType target) { - StructsObject.GameObject* t = GetTarget(target); + GameObject* t = GetTarget(target); if (t == null) return; ulong o = PartyTargetingService.GetObjectID(t); IGameObject? p = Svc.Objects.Where(x => x.GameObjectId == o).First(); @@ -221,7 +223,7 @@ public static void TargetObject(IGameObject? target) if (IsInRange(target)) SetTarget(target); } - public unsafe static StructsObject.GameObject* GetTarget(TargetType target) + public unsafe static GameObject* GetTarget(TargetType target) { IGameObject? o = null; @@ -269,7 +271,7 @@ public static void TargetObject(IGameObject? target) return PartyTargetingService.GetGameObjectFromPronounID(50); } - return o != null ? (StructsObject.GameObject*)o.Address : null; + return o != null ? (GameObject*)o.Address : null; } public enum TargetType @@ -530,5 +532,32 @@ public static int CanLineAoe(float effectRange) o.IsTargetable && PointInRect(o.Position - LocalPlayer.Position, LocalPlayer.Rotation, effectRange, 1, 2)); } + + internal unsafe static bool IsInLineOfSight(IGameObject target) + { + var sourcePos = FFXIVClientStructs.FFXIV.Common.Math.Vector3.Zero; + + if (!Player.Available) return false; + + sourcePos = Player.Object.Struct()->Position; + sourcePos.Y += 2; + + var targetPos = target.Struct()->Position; + targetPos.Y += 2; + + var direction = targetPos - sourcePos; + var distance = direction.Magnitude; + + direction = direction.Normalized; + + Vector3 originVect = new Vector3(sourcePos.X, sourcePos.Y, sourcePos.Z); + Vector3 directionVect = new Vector3(direction.X, direction.Y, direction.Z); + + RaycastHit hit; + var flags = stackalloc int[] { 0x4000, 0, 0x4000, 0 }; + var isLoSBlocked = Framework.Instance()->BGCollisionModule->RaycastMaterialFilter(&hit, &originVect, &directionVect, distance, 1, flags); + + return isLoSBlocked == false; + } } } From 01aa2150226d4299bac110200176ccd4ff3b7017 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 9 Nov 2024 10:54:46 +0000 Subject: [PATCH 193/208] Pre-empt HoT --- ECommons | 2 +- .../AutoRotation/AutoRotationConfig.cs | 1 + .../AutoRotation/AutoRotationController.cs | 60 ++++++++++++++++++- XIVSlothCombo/CustomCombo/Functions/Status.cs | 14 +++++ XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 6 +- 5 files changed, 78 insertions(+), 5 deletions(-) diff --git a/ECommons b/ECommons index d77c9db19..07c07e091 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit d77c9db195056fca9e855c7d142bc6cd8566258f +Subproject commit 07c07e09101e0c8a5f770dbea2ca6eafea5ec705 diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs index 3df3c8596..7c3f567e1 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -28,6 +28,7 @@ public class HealerSettings public bool KardiaTanksOnly = false; public bool AutoRez = false; public bool AutoCleanse = false; + public bool PreEmptiveHoT = false; } } diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 5be26ea7c..adbfaa409 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -12,6 +12,7 @@ using XIVSlothCombo.Combos; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; @@ -24,7 +25,7 @@ internal unsafe static class AutoRotationController static long LastHealAt = 0; internal static void Run() { - if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted] || (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat())) + if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted]) return; if (Player.Object.CurrentCastTime > 0) return; @@ -32,7 +33,13 @@ internal static void Run() if (!EzThrottler.Throttle("AutoRotController", 150)) return; - if (Player.Job is ECommons.ExcelServices.Job.SGE && Service.Configuration.RotationConfig.HealerSettings.ManageKardia) + if (Service.Configuration.RotationConfig.HealerSettings.PreEmptiveHoT && Player.Job is Job.CNJ or Job.WHM or Job.AST) + PreEmptiveHot(); + + if (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat()) + return; + + if (Player.Job is Job.SGE && Service.Configuration.RotationConfig.HealerSettings.ManageKardia) UpdateKardiaTarget(); var healTarget = Player.Object.GetRole() is CombatRole.Healer ? AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode) : null; @@ -96,6 +103,53 @@ internal static void Run() } + private static void PreEmptiveHot() + { + if (CustomComboFunctions.InCombat()) + return; + + if (Svc.Targets.FocusTarget is null) + return; + + ushort regenBuff = Player.Job switch + { + Job.AST => AST.Buffs.AspectedBenefic, + Job.CNJ or Job.WHM => WHM.Buffs.Regen, + _ => 0 + }; + + uint regenSpell = Player.Job switch + { + Job.AST => AST.AspectedBenefic, + Job.CNJ or Job.WHM => WHM.Regen, + _ => 0 + }; + + if (regenSpell != 0 && Svc.Targets.FocusTarget != null && (!CustomComboFunctions.MemberHasEffect(regenBuff, Svc.Targets.FocusTarget, true, out var regen) || regen?.RemainingTime <= 5f)) + { + var query = Svc.Objects.Where(x => !x.IsDead && x.ObjectKind == Dalamud.Game.ClientState.Objects.Enums.ObjectKind.BattleNpc).Cast().Where(x => x.BattleNpcKind == Dalamud.Game.ClientState.Objects.Enums.BattleNpcSubKind.Enemy && x.IsTargetable()); + if (!query.Any()) + return; + + if (query.Min(x => CustomComboFunctions.GetTargetDistance(x, Svc.Targets.FocusTarget)) <= 30) + { + var spell = ActionManager.Instance()->GetAdjustedActionId(regenSpell); + + if (Svc.Targets.FocusTarget.IsDead) + return; + + if (!CustomComboFunctions.ActionReady(spell)) + return; + + if (ActionManager.CanUseActionOnTarget(spell, Svc.Targets.FocusTarget.Struct()) && !ActionWatching.OutOfRange(spell, Player.Object, Svc.Targets.FocusTarget)) + { + ActionManager.Instance()->UseAction(ActionType.Action, regenSpell, Svc.Targets.FocusTarget.GameObjectId); + return; + } + } + } + } + private static void RezParty() { uint resSpell = Player.Job switch @@ -202,7 +256,7 @@ private static bool AutomateHealing(CustomComboPreset preset, Presets.PresetAttr public static class AutoRotationHelper { - public static IGameObject? GetSingleTarget(System.Enum rotationMode) + public static IGameObject? GetSingleTarget(Enum rotationMode) { if (rotationMode is DPSRotationMode dpsmode) { diff --git a/XIVSlothCombo/CustomCombo/Functions/Status.cs b/XIVSlothCombo/CustomCombo/Functions/Status.cs index 0cc1e43f0..eeb92cc35 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Status.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Status.cs @@ -97,6 +97,20 @@ public unsafe static float GetDebuffRemainingTime(ushort effectId, bool isPlayer /// Status object or null. public static Status? FindEffectOnMember(ushort effectID, IGameObject? obj) => Service.ComboCache.GetStatus(effectID, obj, null); + /// + /// Checks if a specific object has a certain status and returns the status as an out parameter + /// + /// + /// + /// + /// + /// + public static bool MemberHasEffect(ushort effectID, IGameObject? obj, bool playerOwned, out Status? status) + { + status = Service.ComboCache.GetStatus(effectID, obj, playerOwned ? LocalPlayer.GameObjectId : null); + return status != null; + } + /// Returns the name of a status effect from its ID. /// ID of the status. /// diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 710f11cbf..185036251 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -4,6 +4,7 @@ using ImGuiNET; using Lumina.Excel.GeneratedSheets; using XIVSlothCombo.Combos.PvE; +using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; @@ -82,11 +83,14 @@ internal class AutoRotationTab : ConfigWindow changed |= ImGui.Checkbox($"Auto-{All.Esuna.ActionName()}", ref cfg.HealerSettings.AutoCleanse); ImGuiComponents.HelpMarker($"Will {All.Esuna.ActionName()} any cleansable debuffs (Healing takes priority)."); - changed |= ImGui.Checkbox($"[{Svc.Data.GetExcelSheet().GetRow(40).Abbreviation}] Automatically Manage Kardia", ref cfg.HealerSettings.ManageKardia); + changed |= ImGui.Checkbox($"[{CustomComboFunctions.JobIDs.JobIDToShorthand(SGE.JobID)}] Automatically Manage Kardia", ref cfg.HealerSettings.ManageKardia); ImGuiComponents.HelpMarker($"Switches {SGE.Kardia.ActionName()} to party members currently being targeted by enemies, prioritising tanks if multiple people are being targeted."); if (cfg.HealerSettings.ManageKardia) changed |= ImGui.Checkbox($"Limit {SGE.Kardia.ActionName()} swapping to tanks only", ref cfg.HealerSettings.KardiaTanksOnly); + changed |= ImGui.Checkbox($"[{CustomComboFunctions.JobIDs.JobIDToShorthand(WHM.JobID)}/{CustomComboFunctions.JobIDs.JobIDToShorthand(AST.JobID)}] Pre-emptively apply heal over time on focus target", ref cfg.HealerSettings.PreEmptiveHoT); + ImGuiComponents.HelpMarker($"Applies {WHM.Regen.ActionName()}/{AST.AspectedBenefic.ActionName()} to your focus target when out of combat and they are 30y or less away from an enemy. (Bypasses \"Only in Combat\" setting)"); + } if (changed) From 832145d59b722b109b2ba59870b06215865d3fe2 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 10 Nov 2024 15:35:52 +0000 Subject: [PATCH 194/208] Autorotussy --- .../AutoRotation/AutoRotationConfig.cs | 10 +++-- .../AutoRotation/AutoRotationController.cs | 39 ++++++++++++------- .../CustomCombo/Functions/PlayerCharacter.cs | 3 ++ XIVSlothCombo/CustomCombo/Functions/Target.cs | 2 + XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 15 +++++++ XIVSlothCombo/Window/Tabs/Debug.cs | 2 + XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 7 files changed, 53 insertions(+), 20 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs index 7c3f567e1..102448681 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationConfig.cs @@ -4,7 +4,9 @@ public class AutoRotationConfig { public bool Enabled; public bool InCombatOnly = false; - public bool InPartyCombat = false; + public bool BypassQuest = false; + public bool BypassFATE = false; + public int CombatDelay = 1; public DPSRotationMode DPSRotationMode; public HealerRotationMode HealerRotationMode; public HealerSettings HealerSettings = new(); @@ -15,14 +17,14 @@ public class DPSSettings { public bool FATEPriority = false; public bool QuestPriority = false; - public int? DPSAoETargets = 2; + public int? DPSAoETargets = 3; } public class HealerSettings { public int SingleTargetHPP = 70; - public int AoETargetHPP = 60; - public int SingleTargetRegenHPP = 80; + public int AoETargetHPP = 80; + public int SingleTargetRegenHPP = 60; public int? AoEHealTargetCount = 2; public bool ManageKardia = false; public bool KardiaTanksOnly = false; diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index adbfaa409..874a8e994 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -23,9 +23,14 @@ namespace XIVSlothCombo.AutoRotation internal unsafe static class AutoRotationController { static long LastHealAt = 0; + + static Func RezQuery => x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null && CustomComboFunctions.FindEffectOnMember(148, x) == null && x.IsTargetable(); + internal static void Run() { - if (!Service.Configuration.RotationConfig.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted]) + var cfg = Service.Configuration.RotationConfig; + + if (!cfg.Enabled || !Player.Available || Svc.Condition[ConditionFlag.Mounted]) return; if (Player.Object.CurrentCastTime > 0) return; @@ -33,33 +38,35 @@ internal static void Run() if (!EzThrottler.Throttle("AutoRotController", 150)) return; - if (Service.Configuration.RotationConfig.HealerSettings.PreEmptiveHoT && Player.Job is Job.CNJ or Job.WHM or Job.AST) + if (cfg.HealerSettings.PreEmptiveHoT && Player.Job is Job.CNJ or Job.WHM or Job.AST) PreEmptiveHot(); - if (Service.Configuration.RotationConfig.InCombatOnly && !CustomComboFunctions.InCombat()) + bool combatBypass = (cfg.BypassQuest && DPSTargeting.BaseSelection.Any(x => CustomComboFunctions.IsQuestMob(x))) || (cfg.BypassFATE && CustomComboFunctions.InFATE()); + + if (cfg.InCombatOnly && !CustomComboFunctions.GetPartyMembers().Any(x => x.Struct()->InCombat) && CustomComboFunctions.CombatEngageDuration().TotalSeconds < cfg.CombatDelay && !combatBypass) return; - if (Player.Job is Job.SGE && Service.Configuration.RotationConfig.HealerSettings.ManageKardia) + if (Player.Job is Job.SGE && cfg.HealerSettings.ManageKardia) UpdateKardiaTarget(); - var healTarget = Player.Object.GetRole() is CombatRole.Healer ? AutoRotationHelper.GetSingleTarget(Service.Configuration.RotationConfig.HealerRotationMode) : null; - var aoeheal = Player.Object.GetRole() is CombatRole.Healer ? HealerTargeting.CanAoEHeal() : false; + var healTarget = Player.Object.GetRole() is CombatRole.Healer ? AutoRotationHelper.GetSingleTarget(cfg.HealerRotationMode) : null; + var aoeheal = Player.Object.GetRole() is CombatRole.Healer && HealerTargeting.CanAoEHeal(); if (Player.Object.GetRole() is CombatRole.Healer) { bool needsHeal = healTarget != null || aoeheal; - if (Service.Configuration.RotationConfig.HealerSettings.AutoCleanse && !needsHeal) + if (cfg.HealerSettings.AutoCleanse && !needsHeal) { CleanseParty(); if (CustomComboFunctions.GetPartyMembers().Any((x => CustomComboFunctions.HasCleansableDebuff(x)))) return; } - if (Service.Configuration.RotationConfig.HealerSettings.AutoRez) + if (cfg.HealerSettings.AutoRez) { RezParty(); - if (CustomComboFunctions.GetPartyMembers().Any(x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null)) + if (CustomComboFunctions.GetPartyMembers().Any(RezQuery)) return; } } @@ -78,6 +85,8 @@ internal static void Run() continue; var outAct = AutoRotationHelper.InvokeCombo(preset.Key, attributes); + if (!CustomComboFunctions.ActionReady(gameAct)) + continue; if (action.IsHeal) { @@ -163,7 +172,7 @@ private static void RezParty() if (Player.Object.CurrentMp >= CustomComboFunctions.GetResourceCost(resSpell)) { - if (CustomComboFunctions.GetPartyMembers().FindFirst(x => x.IsDead && CustomComboFunctions.FindEffectOnMember(2648, x) == null, out var member)) + if (CustomComboFunctions.GetPartyMembers().Where(RezQuery).FindFirst(x => x is not null, out var member)) { if (CustomComboFunctions.ActionReady(All.Swiftcast)) { @@ -356,7 +365,6 @@ public static bool ExecuteST(Enum mode, CustomComboPreset preset, Presets.Preset var canUseSelf = ActionManager.CanUseActionOnTarget(outAct, Player.GameObject); var canUse = canUseSelf || canUseTarget || areaTargeted; - if (canUse && inRange) { Svc.Targets.Target = target; @@ -404,13 +412,13 @@ public static uint InvokeCombo(CustomComboPreset preset, Presets.PresetAttribute public class DPSTargeting { - public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable && CustomComboFunctions.IsInLineOfSight(x)).OrderByDescending(x => IsPriority(x)); + public static System.Collections.Generic.IEnumerable BaseSelection => Svc.Objects.Any(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && CustomComboFunctions.IsInLineOfSight(x) && IsPriority(x)) ? Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable && CustomComboFunctions.IsInLineOfSight(x) && IsPriority(x)) : + Svc.Objects.Where(x => x is IBattleChara chara && x.IsHostile() && CustomComboFunctions.IsInRange(x) && !x.IsDead && x.IsTargetable && CustomComboFunctions.IsInLineOfSight(x)); private static bool IsPriority(IGameObject x) { - bool isFate = Service.Configuration.RotationConfig.DPSSettings.FATEPriority && x.Struct()->FateId != 0; - var namePlateIcon = x.Struct()->NamePlateIconId; - bool isQuest = Service.Configuration.RotationConfig.DPSSettings.QuestPriority && namePlateIcon is 71204 or 71144 or 71224 or 71344; + bool isFate = Service.Configuration.RotationConfig.DPSSettings.FATEPriority && x.Struct()->FateId != 0 && CustomComboFunctions.InFATE(); + bool isQuest = Service.Configuration.RotationConfig.DPSSettings.QuestPriority && CustomComboFunctions.IsQuestMob(x); if (Player.Object.GetRole() is CombatRole.Tank && x.TargetObjectId != Player.Object.GameObjectId) return true; @@ -448,6 +456,7 @@ private static bool IsPriority(IGameObject x) public static IGameObject? GetLowestMaxTarget() { + return BaseSelection.OrderBy(x => (x as IBattleChara).MaxHp).ThenBy(x => CustomComboFunctions.GetTargetHPPercent(x)).ThenBy(x => CustomComboFunctions.GetTargetDistance(x)).FirstOrDefault(); } diff --git a/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs b/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs index 73db277f0..5c33e11b8 100644 --- a/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs +++ b/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs @@ -1,6 +1,7 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Objects.SubKinds; using ECommons.DalamudServices; +using FFXIVClientStructs.FFXIV.Client.Game.Fate; using FFXIVClientStructs.FFXIV.Client.Game.UI; using Lumina.Excel.GeneratedSheets; using GameMain = FFXIVClientStructs.FFXIV.Client.Game.GameMain; @@ -45,5 +46,7 @@ public static unsafe bool IsActionUnlocked(uint id) if (unlockLink == 0) return true; return UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(unlockLink); } + + public unsafe static bool InFATE() => FateManager.Instance()->CurrentFate is not null && LocalPlayer.Level <= FateManager.Instance()->CurrentFate->MaxLevel; } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index efe7964d4..5d828f134 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -559,5 +559,7 @@ internal unsafe static bool IsInLineOfSight(IGameObject target) return isLoSBlocked == false; } + + internal unsafe static bool IsQuestMob(IGameObject target) => target.Struct()->NamePlateIconId is 71204 or 71144 or 71224 or 71344; } } diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 185036251..537fba2e6 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -25,6 +25,21 @@ internal class AutoRotationTab : ConfigWindow if (cfg.Enabled) { changed |= ImGui.Checkbox("Only in Combat", ref cfg.InCombatOnly); + + if (cfg.InCombatOnly) + { + changed |= ImGui.Checkbox($"Bypass Only in Combat for Quest Targets", ref cfg.BypassQuest); + ImGuiComponents.HelpMarker("Disables Auto-Mode outside of combat unless you're within range of a quest target."); + + changed |= ImGui.Checkbox($"Bypass Only in Combat for FATE Targets", ref cfg.BypassFATE); + ImGuiComponents.HelpMarker("Disables Auto-Mode outside of combat unless you're synced to a FATE."); + + ImGui.SetNextItemWidth(100f.Scale()); + changed |= ImGui.InputInt("Delay to activate Auto-Rotation once combat starts (seconds)", ref cfg.CombatDelay); + + if (cfg.CombatDelay < 0) + cfg.CombatDelay = 0; + } } if (ImGui.CollapsingHeader("Damage Settings")) diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 1a172d02d..15837a9fe 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -22,6 +22,7 @@ using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using Status = Dalamud.Game.ClientState.Statuses.Status; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; +using FFXIVClientStructs.FFXIV.Client.Game.Fate; namespace XIVSlothCombo.Window.Tabs { @@ -211,6 +212,7 @@ static void CustomStyleText(string label, object? value) CustomStyleText("In PvP:", InPvP()); CustomStyleText("In Combat:", InCombat()); CustomStyleText("Hitbox Radius:", LocalPlayer.HitboxRadius); + CustomStyleText("In FATE:", InFATE()); ImGui.Spacing(); // Target Info diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index e941eebfa..66a643556 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.8 + 0.0.0.10 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From 366edbcb36e44b827abdef1025dee09446ed2a8b Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 13 Nov 2024 06:49:31 +0000 Subject: [PATCH 195/208] API 11 --- ECommons | 2 +- .../Attributes/CustomComboInfoAttribute.cs | 10 +++--- .../Attributes/ReplaceSkillAttribute.cs | 2 +- XIVSlothCombo/Combos/JobHelpers/AST.cs | 19 +++++------ XIVSlothCombo/Combos/JobHelpers/NIN.cs | 2 -- XIVSlothCombo/Combos/JobHelpers/PCT.cs | 5 --- XIVSlothCombo/Combos/PvE/ALL.cs | 6 ++-- XIVSlothCombo/Combos/PvE/AST.cs | 1 - XIVSlothCombo/Combos/PvE/BLM.cs | 1 - XIVSlothCombo/Combos/PvE/BRD.cs | 1 - XIVSlothCombo/Combos/PvE/DNC.cs | 1 - XIVSlothCombo/Combos/PvE/DRK.cs | 1 - XIVSlothCombo/Combos/PvE/NIN.cs | 6 ++-- XIVSlothCombo/Combos/PvE/RDM.cs | 1 - XIVSlothCombo/Combos/PvE/SGE.cs | 1 - XIVSlothCombo/Combos/PvE/WAR.cs | 1 - XIVSlothCombo/Combos/PvE/WHM.cs | 2 ++ XIVSlothCombo/Combos/PvP/GNBPVP.cs | 3 +- XIVSlothCombo/Core/IconReplacer.cs | 10 +++--- XIVSlothCombo/Core/PluginAddressResolver.cs | 6 ++-- XIVSlothCombo/CustomCombo/CustomCombo.cs | 2 +- XIVSlothCombo/CustomCombo/Functions/Action.cs | 2 +- .../CustomCombo/Functions/PlayerCharacter.cs | 4 +-- XIVSlothCombo/CustomCombo/Functions/Status.cs | 1 - XIVSlothCombo/CustomCombo/Functions/Target.cs | 4 ++- XIVSlothCombo/Data/ActionWatching.cs | 26 +++++++-------- XIVSlothCombo/Window/Functions/Presets.cs | 2 -- XIVSlothCombo/Window/Tabs/Debug.cs | 33 +++++++++---------- XIVSlothCombo/XIVSlothCombo.cs | 21 ++++++------ XIVSlothCombo/XIVSlothCombo.csproj | 2 +- XIVSlothCombo/XIVSlothCombo.json | 2 +- 31 files changed, 80 insertions(+), 100 deletions(-) diff --git a/ECommons b/ECommons index d77c9db19..0e0cc76e4 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit d77c9db195056fca9e855c7d142bc6cd8566258f +Subproject commit 0e0cc76e4197e28b2576502f8a059815ce0a3aa4 diff --git a/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs b/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs index 8ab5928a3..a282bffe6 100644 --- a/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs +++ b/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs @@ -1,5 +1,5 @@ using ECommons.DalamudServices; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; using System; using System.Collections.Generic; using System.Globalization; @@ -61,7 +61,7 @@ private static int JobIDToRole(byte jobID) private static uint JobIDToClassJobCategory(byte jobID) { if (Svc.Data.GetExcelSheet().HasRow(jobID)) - return Svc.Data.GetExcelSheet().GetRow(jobID).ClassJobCategory.Row; + return Svc.Data.GetExcelSheet().GetRow(jobID).ClassJobCategory.RowId; return 0; } @@ -84,7 +84,7 @@ private static string JobIDToShorthand(byte key) if (ClassJobs.TryGetValue(key, out var job)) { - return job.Abbreviation.RawString; + return job.Abbreviation.ToString(); } else { @@ -102,10 +102,10 @@ public static string JobIDToName(byte key) //Override DOH/DOL if (key is DOH.JobID) key = 08; //Set to Carpenter if (key is DOL.JobID) key = 16; //Set to Miner - if (ClassJobs.TryGetValue(key, out ClassJob? job)) + if (ClassJobs.TryGetValue(key, out ClassJob job)) { //Grab Category name for DOH/DOL, else the normal Name for the rest - string jobname = key is 08 or 16 ? job.ClassJobCategory.Value.Name : job.Name; + string jobname = key is 08 or 16 ? job.ClassJobCategory.Value.Name.ToString() : job.Name.ToString(); //Job names are all lowercase by default. This capitalizes based on regional rules string cultureID = Svc.ClientState.ClientLanguage switch { diff --git a/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs b/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs index d81d2b3cc..d7bf95773 100644 --- a/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs +++ b/XIVSlothCombo/Attributes/ReplaceSkillAttribute.cs @@ -14,7 +14,7 @@ internal ReplaceSkillAttribute(params uint[] actionIDs) { foreach (uint id in actionIDs) { - if (ActionWatching.ActionSheet.TryGetValue(id, out var action) && action != null) + if (ActionWatching.ActionSheet.TryGetValue(id, out var action)) { ActionNames.Add($"{action.Name}"); ActionIcons.Add(action.Icon); diff --git a/XIVSlothCombo/Combos/JobHelpers/AST.cs b/XIVSlothCombo/Combos/JobHelpers/AST.cs index d5b7ea2b8..c4c3a2e9b 100644 --- a/XIVSlothCombo/Combos/JobHelpers/AST.cs +++ b/XIVSlothCombo/Combos/JobHelpers/AST.cs @@ -1,9 +1,8 @@ - using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using ECommons.DalamudServices; using ECommons.GameFunctions; -using ECommons.ExcelServices; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.CustomComboNS.Functions; @@ -21,7 +20,7 @@ internal static void Init() private static void CheckCards(IFramework framework) { - if (Svc.ClientState.LocalPlayer is null || Svc.ClientState.LocalPlayer.ClassJob.Id != 33) + if (Svc.ClientState.LocalPlayer is null || Svc.ClientState.LocalPlayer.ClassJob.RowId != 33) return; if (Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.BetweenAreas] || Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.Unconscious]) @@ -55,8 +54,8 @@ private static bool BetterTargetAvailable() return true; var m = AST_QuickTargetCards.SelectedRandomMember as IBattleChara; - if ((DrawnCard is CardType.BALANCE && CustomComboFunctions.JobIDs.Melee.Any(x => x == m.ClassJob.Id)) || - (DrawnCard is CardType.SPEAR && CustomComboFunctions.JobIDs.Ranged.Any(x => x == m.ClassJob.Id))) + if ((DrawnCard is CardType.BALANCE && CustomComboFunctions.JobIDs.Melee.Any(x => x == m.ClassJob.RowId)) || + (DrawnCard is CardType.SPEAR && CustomComboFunctions.JobIDs.Ranged.Any(x => x == m.ClassJob.RowId))) return false; var targets = new List(); @@ -80,8 +79,8 @@ private static bool BetterTargetAvailable() } if (targets.Count == 0) return false; - if ((DrawnCard is CardType.BALANCE && targets.Any(x => CustomComboFunctions.JobIDs.Melee.Any(y => y == x.ClassJob.Id))) || - (DrawnCard is CardType.SPEAR && targets.Any(x => CustomComboFunctions.JobIDs.Ranged.Any(y => y == x.ClassJob.Id)))) + if ((DrawnCard is CardType.BALANCE && targets.Any(x => CustomComboFunctions.JobIDs.Melee.Any(y => y == x.ClassJob.RowId))) || + (DrawnCard is CardType.SPEAR && targets.Any(x => CustomComboFunctions.JobIDs.Ranged.Any(y => y == x.ClassJob.RowId)))) { AST_QuickTargetCards.SelectedRandomMember = null; return true; @@ -172,7 +171,7 @@ private static bool SetTarget() //Give card to DPS first for (int i = 0; i <= PartyTargets.Count - 1; i++) { - byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.Id : (byte)0; + byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.RowId : (byte)0; if (((cardDrawn is CardType.BALANCE) && JobIDs.Melee.Contains(job)) || ((cardDrawn is CardType.SPEAR) && JobIDs.Ranged.Contains(job))) { @@ -184,7 +183,7 @@ private static bool SetTarget() //Give card to unsuitable DPS next for (int i = 0; i <= PartyTargets.Count - 1; i++) { - byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.Id : (byte)0; + byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.RowId : (byte)0; if (((cardDrawn is CardType.BALANCE) && JobIDs.Ranged.Contains(job)) || ((cardDrawn is CardType.SPEAR) && JobIDs.Melee.Contains(job))) { @@ -199,7 +198,7 @@ private static bool SetTarget() { for (int i = 0; i <= PartyTargets.Count - 1; i++) { - byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.Id : (byte)0; + byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.RowId : (byte)0; if ((cardDrawn is CardType.BALANCE && JobIDs.Tank.Contains(job)) || (cardDrawn is CardType.SPEAR && JobIDs.Healer.Contains(job))) { diff --git a/XIVSlothCombo/Combos/JobHelpers/NIN.cs b/XIVSlothCombo/Combos/JobHelpers/NIN.cs index e1e4485c9..9af849a29 100644 --- a/XIVSlothCombo/Combos/JobHelpers/NIN.cs +++ b/XIVSlothCombo/Combos/JobHelpers/NIN.cs @@ -1,10 +1,8 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; -using System; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; namespace XIVSlothCombo.Combos.JobHelpers diff --git a/XIVSlothCombo/Combos/JobHelpers/PCT.cs b/XIVSlothCombo/Combos/JobHelpers/PCT.cs index e7761ca6f..0b6acf33f 100644 --- a/XIVSlothCombo/Combos/JobHelpers/PCT.cs +++ b/XIVSlothCombo/Combos/JobHelpers/PCT.cs @@ -1,10 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; diff --git a/XIVSlothCombo/Combos/PvE/ALL.cs b/XIVSlothCombo/Combos/PvE/ALL.cs index f6d049e16..1ba1d8e99 100644 --- a/XIVSlothCombo/Combos/PvE/ALL.cs +++ b/XIVSlothCombo/Combos/PvE/ALL.cs @@ -134,7 +134,7 @@ internal class ALL_Healer_Raise : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { if ((actionID is WHM.Raise or AST.Ascend or SGE.Egeiro) - || (actionID is SCH.Resurrection && LocalPlayer.ClassJob.Id is SCH.JobID)) + || (actionID is SCH.Resurrection && LocalPlayer.ClassJob.Value.RowId is SCH.JobID)) { if (ActionReady(Swiftcast)) return Swiftcast; @@ -173,13 +173,13 @@ internal class ALL_Caster_Raise : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { if ((actionID is BLU.AngelWhisper or RDM.Verraise) - || (actionID is SMN.Resurrection && LocalPlayer.ClassJob.Id is SMN.JobID)) + || (actionID is SMN.Resurrection && LocalPlayer.ClassJob.RowId is SMN.JobID)) { if (HasEffect(Buffs.Swiftcast) || HasEffect(RDM.Buffs.Dualcast)) return actionID; if (IsOffCooldown(Swiftcast)) return Swiftcast; - if (LocalPlayer.ClassJob.Id is RDM.JobID && + if (LocalPlayer.ClassJob.RowId is RDM.JobID && ActionReady(RDM.Vercure)) return RDM.Vercure; } diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 387e5e0eb..f2d0991d5 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -2,7 +2,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Statuses; -using System.Collections; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.Combos.PvE.Content; diff --git a/XIVSlothCombo/Combos/PvE/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM.cs index 11a120d4d..6ca66bd9e 100644 --- a/XIVSlothCombo/Combos/PvE/BLM.cs +++ b/XIVSlothCombo/Combos/PvE/BLM.cs @@ -1,5 +1,4 @@ using Dalamud.Game.ClientState.JobGauge.Types; -using ECommons.DalamudServices; using System; using System.Collections.Generic; using XIVSlothCombo.Combos.JobHelpers; diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 90dc03f51..fd27a225b 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -2,7 +2,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Statuses; using System; -using System.ComponentModel.Design; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; diff --git a/XIVSlothCombo/Combos/PvE/DNC.cs b/XIVSlothCombo/Combos/PvE/DNC.cs index e1b513b2a..4ff1da3b8 100644 --- a/XIVSlothCombo/Combos/PvE/DNC.cs +++ b/XIVSlothCombo/Combos/PvE/DNC.cs @@ -1,6 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Services; diff --git a/XIVSlothCombo/Combos/PvE/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK.cs index d3d2e29ea..eff77a9a3 100644 --- a/XIVSlothCombo/Combos/PvE/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK.cs @@ -1,6 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; diff --git a/XIVSlothCombo/Combos/PvE/NIN.cs b/XIVSlothCombo/Combos/PvE/NIN.cs index ec2c6da4a..289dd6c4e 100644 --- a/XIVSlothCombo/Combos/PvE/NIN.cs +++ b/XIVSlothCombo/Combos/PvE/NIN.cs @@ -1,7 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Statuses; -using ECommons.DalamudServices; -using System; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; @@ -215,7 +213,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (IsNotEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Mug) || (IsEnabled(CustomComboPreset.NIN_ST_AdvancedMode_Mug) && IsOnCooldown(Mug)))) mudraState.CurrentMudra = MudraCasting.MudraState.CastingHyoshoRanryu; - if (NINHelper.InMudra) + if (NINHelper.InMudra || mudraState.CurrentMudra != MudraCasting.MudraState.None) { if (mudraState.ContinueCurrentMudra(ref actionID)) return actionID; @@ -488,7 +486,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim NINGauge? gauge = GetJobGauge(); bool canWeave = CanWeave(GustSlash); bool chargeCheck = IsNotEnabled(CustomComboPreset.NIN_AoE_AdvancedMode_Ninjitsus_ChargeHold) || (IsEnabled(CustomComboPreset.NIN_AoE_AdvancedMode_Ninjitsus_ChargeHold) && GetRemainingCharges(Ten) == 2); - bool inMudraState = HasEffect(Buffs.Mudra); + bool inMudraState = NINHelper.InMudra; int hellfrogPool = GetOptionValue(Config.Ninki_HellfrogPooling); int dotonTimer = GetOptionValue(Config.Advanced_DotonTimer); int dotonThreshold = GetOptionValue(Config.Advanced_DotonHP); diff --git a/XIVSlothCombo/Combos/PvE/RDM.cs b/XIVSlothCombo/Combos/PvE/RDM.cs index 299114148..dee8d701e 100644 --- a/XIVSlothCombo/Combos/PvE/RDM.cs +++ b/XIVSlothCombo/Combos/PvE/RDM.cs @@ -1,5 +1,4 @@ using Dalamud.Game.ClientState.Conditions; -using XIVSlothCombo.Combos.JobHelpers; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; diff --git a/XIVSlothCombo/Combos/PvE/SGE.cs b/XIVSlothCombo/Combos/PvE/SGE.cs index 940e03f67..13b5e8e66 100644 --- a/XIVSlothCombo/Combos/PvE/SGE.cs +++ b/XIVSlothCombo/Combos/PvE/SGE.cs @@ -9,7 +9,6 @@ using XIVSlothCombo.CustomComboNS.Functions; using static XIVSlothCombo.Combos.JobHelpers.SGEHelper; using XIVSlothCombo.Data; -using XIVSlothCombo.Combos.JobHelpers; namespace XIVSlothCombo.Combos.PvE { diff --git a/XIVSlothCombo/Combos/PvE/WAR.cs b/XIVSlothCombo/Combos/PvE/WAR.cs index d1eebaf01..0a8f0743f 100644 --- a/XIVSlothCombo/Combos/PvE/WAR.cs +++ b/XIVSlothCombo/Combos/PvE/WAR.cs @@ -1,4 +1,3 @@ -using System; using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.PvE.Content; diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index bede66d03..24902c5e7 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; +using ECommons.DalamudServices; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.Combos.PvE.Content; @@ -202,6 +203,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } else ActionFound = StoneGlareList.Contains(actionID); //default handling + Svc.Log.Debug($"HERE"); if (ActionFound) { WHMGauge? gauge = GetJobGauge(); diff --git a/XIVSlothCombo/Combos/PvP/GNBPVP.cs b/XIVSlothCombo/Combos/PvP/GNBPVP.cs index edd658690..a53c3c99a 100644 --- a/XIVSlothCombo/Combos/PvP/GNBPVP.cs +++ b/XIVSlothCombo/Combos/PvP/GNBPVP.cs @@ -1,5 +1,4 @@ -using System; -using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; namespace XIVSlothCombo.Combos.PvP diff --git a/XIVSlothCombo/Core/IconReplacer.cs b/XIVSlothCombo/Core/IconReplacer.cs index 8f0c46496..6ccff82e4 100644 --- a/XIVSlothCombo/Core/IconReplacer.cs +++ b/XIVSlothCombo/Core/IconReplacer.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; namespace XIVSlothCombo.Core @@ -64,8 +65,8 @@ private unsafe uint GetIconDetour(IntPtr actionManager, uint actionID) return OriginalHook(actionID); if (ClassLocked() || - (DisabledJobsPVE.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.Id) && !Svc.ClientState.IsPvP) || - (DisabledJobsPVP.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.Id) && Svc.ClientState.IsPvP)) + (DisabledJobsPVE.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.RowId) && !Svc.ClientState.IsPvP) || + (DisabledJobsPVP.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.RowId) && Svc.ClientState.IsPvP)) return OriginalHook(actionID); uint lastComboMove = ActionManager.Instance()->Combo.Action; @@ -76,6 +77,7 @@ private unsafe uint GetIconDetour(IntPtr actionManager, uint actionID) { if (combo.TryInvoke(actionID, level, lastComboMove, comboTime, out uint newActionID)) return newActionID; + } return OriginalHook(actionID); @@ -95,14 +97,14 @@ public unsafe static bool ClassLocked() if (Svc.ClientState.LocalPlayer.Level <= 35) return false; - if (Svc.ClientState.LocalPlayer.ClassJob.Id is + if (Svc.ClientState.LocalPlayer.ClassJob.RowId is (>= 8 and <= 25) or 27 or 28 or >= 30) return false; if (!UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(66049)) return false; - if ((Svc.ClientState.LocalPlayer.ClassJob.Id is 1 or 2 or 3 or 4 or 5 or 6 or 7 or 26 or 29) && + if ((Svc.ClientState.LocalPlayer.ClassJob.RowId is 1 or 2 or 3 or 4 or 5 or 6 or 7 or 26 or 29) && Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.BoundByDuty] && Svc.ClientState.LocalPlayer.Level > 35) return true; diff --git a/XIVSlothCombo/Core/PluginAddressResolver.cs b/XIVSlothCombo/Core/PluginAddressResolver.cs index 401f43d3e..b79b5d8e4 100644 --- a/XIVSlothCombo/Core/PluginAddressResolver.cs +++ b/XIVSlothCombo/Core/PluginAddressResolver.cs @@ -13,10 +13,10 @@ internal class PluginAddressResolver /// public unsafe void Setup(ISigScanner scanner) { - IsActionIdReplaceable = scanner.ScanText("40 53 48 83 EC 20 8B D9 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 74 1F"); + IsActionIdReplaceable = scanner.ScanText("40 53 48 83 EC 20 8B D9 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 74 1B"); - Svc.Log.Verbose("===== X I V S L O T H C O M B O ====="); - Svc.Log.Verbose($"{nameof(IsActionIdReplaceable)} 0x{IsActionIdReplaceable:X}"); + Svc.Log.Debug("===== X I V S L O T H C O M B O ====="); + Svc.Log.Debug($"{nameof(IsActionIdReplaceable)} 0x{IsActionIdReplaceable:X}"); } } } diff --git a/XIVSlothCombo/CustomCombo/CustomCombo.cs b/XIVSlothCombo/CustomCombo/CustomCombo.cs index 9767aae47..31e74b21a 100644 --- a/XIVSlothCombo/CustomCombo/CustomCombo.cs +++ b/XIVSlothCombo/CustomCombo/CustomCombo.cs @@ -49,7 +49,7 @@ public unsafe bool TryInvoke(uint actionID, byte level, uint lastComboMove, floa if (!IsEnabled(Preset)) return false; - uint classJobID = LocalPlayer!.ClassJob.Id; + uint classJobID = LocalPlayer!.ClassJob.RowId; if (classJobID is >= 8 and <= 15) classJobID = DOH.JobID; diff --git a/XIVSlothCombo/CustomCombo/Functions/Action.cs b/XIVSlothCombo/CustomCombo/Functions/Action.cs index 7a79b10ac..e6cb028ca 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Action.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Action.cs @@ -20,7 +20,7 @@ internal abstract partial class CustomComboFunctions /// Checks if the player is high enough level to use the passed Action ID. /// ID of the action. /// - public static bool LevelChecked(uint actionid) => LocalPlayer.Level >= GetLevel(actionid) && NoBlockingStatuses(actionid) && IsActionUnlocked(actionid); + public static bool LevelChecked(uint actionid) => LocalPlayer.Level >= GetLevel(actionid) && NoBlockingStatuses(actionid) && IsActionUnlocked(actionid); /// Checks if the player is high enough level to use the passed Trait ID. /// ID of the action. diff --git a/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs b/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs index b11fd5660..e0e49e545 100644 --- a/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs +++ b/XIVSlothCombo/CustomCombo/Functions/PlayerCharacter.cs @@ -2,7 +2,7 @@ using Dalamud.Game.ClientState.Objects.SubKinds; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game.UI; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; using GameMain = FFXIVClientStructs.FFXIV.Client.Game.GameMain; namespace XIVSlothCombo.CustomComboNS.Functions @@ -37,7 +37,7 @@ internal abstract partial class CustomComboFunctions /// A value indicating a quest has been completed for a job action. public static unsafe bool IsActionUnlocked(uint id) { - var unlockLink = Svc.Data.GetExcelSheet().GetRow(id).UnlockLink; + var unlockLink = Svc.Data.GetExcelSheet().GetRow(id).UnlockLink.RowId; if (unlockLink == 0) return true; return UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(unlockLink); } diff --git a/XIVSlothCombo/CustomCombo/Functions/Status.cs b/XIVSlothCombo/CustomCombo/Functions/Status.cs index f213fbcde..0cc1e43f0 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Status.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Status.cs @@ -1,5 +1,4 @@ using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Game.ClientState.Statuses; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Data; using XIVSlothCombo.Services; diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index d9869f6b1..f7264902c 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -1,8 +1,10 @@ using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.Types; +using ECommons; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.System.Framework; +using Lumina.Excel.Sheets; using System; using System.Linq; using System.Numerics; @@ -180,7 +182,7 @@ public static bool TargetNeedsPositionals() { if (!HasBattleTarget()) return false; if (TargetHasEffectAny(3808)) return false; // Directional Disregard Effect (Patch 7.01) - if (ActionWatching.BNpcSheet.TryGetValue(CurrentTarget.DataId, out var bnpc) && !bnpc.Unknown10) return true; + if (Svc.Data.Excel.GetSheet().TryGetFirst(x => x.RowId == CurrentTarget.DataId, out var bnpc) && !bnpc.IsOmnidirectional) return true; return false; } diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index a00b8ae56..b6b98a1a6 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -4,7 +4,7 @@ using ECommons.DalamudServices; using ECommons.GameFunctions; using FFXIVClientStructs.FFXIV.Client.Game; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; using System; using System.Collections.Generic; using System.Linq; @@ -18,18 +18,15 @@ namespace XIVSlothCombo.Data { public static class ActionWatching { - internal static Dictionary ActionSheet = Svc.Data.GetExcelSheet()! + internal static Dictionary ActionSheet = Svc.Data.GetExcelSheet()! .Where(i => i.RowId is not 7) .ToDictionary(i => i.RowId, i => i); - internal static Dictionary StatusSheet = Svc.Data.GetExcelSheet()! + internal static Dictionary StatusSheet = Svc.Data.GetExcelSheet()! .ToDictionary(i => i.RowId, i => i); internal static Dictionary TraitSheet = Svc.Data.GetExcelSheet()! - .Where(i => i.ClassJobCategory is not null) //All player traits are assigned to a category. Chocobo and other garbage lacks this, thus excluded. - .ToDictionary(i => i.RowId, i => i); - - internal static Dictionary BNpcSheet = Svc.Data.GetExcelSheet()! + .Where(i => i.ClassJobCategory.IsValid) //All player traits are assigned to a category. Chocobo and other garbage lacks this, thus excluded. .ToDictionary(i => i.RowId, i => i); private static readonly Dictionary> statusCache = []; @@ -61,9 +58,8 @@ private static void ReceiveActionEffectDetour(ulong sourceObjectId, IntPtr sourc LastAction = header.ActionId; - ActionSheet.TryGetValue(header.ActionId, out var sheet); - if (sheet != null) - { + if (ActionSheet.TryGetValue(header.ActionId, out var sheet)) + { switch (sheet.ActionCategory.Value.RowId) { case 2: //Spell @@ -271,21 +267,21 @@ public static void Disable() Svc.Condition.ConditionChange -= ResetActions; } - public static int GetLevel(uint id) => ActionSheet.TryGetValue(id, out var action) && action.ClassJobCategory is not null ? action.ClassJobLevel : 255; + public static int GetLevel(uint id) => ActionSheet.TryGetValue(id, out var action) && action.ClassJobCategory.IsValid ? action.ClassJobLevel : 255; public static float GetActionCastTime(uint id) => ActionSheet.TryGetValue(id, out var action) ? action.Cast100ms / (float)10 : 0; public static int GetActionRange(uint id) => ActionSheet.TryGetValue(id, out var action) ? action.Range : -2; // 0 & -1 are valid numbers. -2 is our failure code for InActionRange public static int GetActionEffectRange(uint id) => ActionSheet.TryGetValue(id, out var action) ? action.EffectRange : -1; public static int GetTraitLevel(uint id) => TraitSheet.TryGetValue(id, out var trait) ? trait.Level : 255; - public static string GetActionName(uint id) => ActionSheet.TryGetValue(id, out var action) ? (string)action.Name : "UNKNOWN ABILITY"; + public static string GetActionName(uint id) => ActionSheet.TryGetValue(id, out var action) ? action.Name.ToString() : "UNKNOWN ABILITY"; public static string GetBLUIndex(uint id) { - var aozKey = Svc.Data.GetExcelSheet()!.First(x => x.Action.Row == id).RowId; + var aozKey = Svc.Data.GetExcelSheet()!.First(x => x.Action.RowId == id).RowId; var index = Svc.Data.GetExcelSheet().GetRow(aozKey).Number; return $"#{index} "; } - public static string GetStatusName(uint id) => StatusSheet.TryGetValue(id, out var status) ? (string)status.Name : "Unknown Status"; + public static string GetStatusName(uint id) => StatusSheet.TryGetValue(id, out var status) ? status.Name.ToString() : "Unknown Status"; public static List? GetStatusesByName(string status) { @@ -302,7 +298,7 @@ public static ActionAttackType GetAttackType(uint id) { if (!ActionSheet.TryGetValue(id, out var action)) return ActionAttackType.Unknown; - return action.ActionCategory.Row switch + return action.ActionCategory.RowId switch { 2 => ActionAttackType.Spell, 3 => ActionAttackType.Weaponskill, diff --git a/XIVSlothCombo/Window/Functions/Presets.cs b/XIVSlothCombo/Window/Functions/Presets.cs index bbb734dc0..2f2b698dc 100644 --- a/XIVSlothCombo/Window/Functions/Presets.cs +++ b/XIVSlothCombo/Window/Functions/Presets.cs @@ -1,6 +1,5 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Components; -using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; using ECommons.DalamudServices; @@ -9,7 +8,6 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using System.Reflection.Emit; using System.Text; using XIVSlothCombo.Attributes; using XIVSlothCombo.Combos; diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 06df7e63b..b5c106830 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -4,10 +4,11 @@ using Dalamud.Interface.Utility.Raii; using ECommons.DalamudServices; using ECommons.ImGuiMethods; +using ECommons.Reflection; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.UI; using ImGuiNET; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; using System; using System.Linq; using XIVSlothCombo.Combos; @@ -15,8 +16,6 @@ using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Services; -using static XIVSlothCombo.Combos.JobHelpers.NIN; -using Action = Lumina.Excel.GeneratedSheets.Action; using Status = Dalamud.Game.ClientState.Statuses.Status; namespace XIVSlothCombo.Window.Tabs @@ -31,7 +30,7 @@ internal class DebugCombo : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) => actionID; } - internal static Action? debugSpell; + internal static Lumina.Excel.Sheets.Action? debugSpell; internal unsafe static new void Draw() { DebugCombo? comboClass = new(); @@ -132,7 +131,7 @@ static void CustomStyleText(string label, object? value) } if (ImGui.CollapsingHeader("Action Info")) { - string prev = debugSpell == null ? "Select Action" : $"({debugSpell.RowId}) Lv.{debugSpell.ClassJobLevel}. {debugSpell.Name} - {(debugSpell.IsPvP ? "PvP" : "Normal")}"; + string prev = debugSpell == null ? "Select Action" : $"({debugSpell.Value.RowId}) Lv.{debugSpell.Value.ClassJobLevel}. {debugSpell.Value.Name} - {(debugSpell.Value.IsPvP ? "PvP" : "Normal")}"; ImGuiEx.SetNextItemFullWidth(); using (var comboBox = ImRaii.Combo("###ActionCombo", prev)) { @@ -144,7 +143,7 @@ static void CustomStyleText(string label, object? value) } var classId = CustomComboFunctions.JobIDs.JobToClass(JobID.Value); - foreach (var act in Svc.Data.GetExcelSheet().Where(x => x.IsPlayerAction && x.ClassJob.Row == classId || x.ClassJob.Row == JobID.Value).OrderBy(x => x.ClassJobLevel)) + foreach (var act in Svc.Data.GetExcelSheet().Where(x => x.IsPlayerAction && x.ClassJob.RowId == classId || x.ClassJob.RowId == JobID.Value).OrderBy(x => x.ClassJobLevel)) { if (ImGui.Selectable($"({act.RowId}) Lv.{act.ClassJobLevel}. {act.Name} - {(act.IsPvP ? "PvP" : "Normal")}", debugSpell?.RowId == act.RowId)) { @@ -156,19 +155,19 @@ static void CustomStyleText(string label, object? value) if (debugSpell != null) { - var actionStatus = ActionManager.Instance()->GetActionStatus(ActionType.Action, debugSpell.RowId); - var icon = Svc.Texture.GetFromGameIcon(new(debugSpell.Icon)).GetWrapOrEmpty().ImGuiHandle; + var actionStatus = ActionManager.Instance()->GetActionStatus(ActionType.Action, debugSpell.Value.RowId); + var icon = Svc.Texture.GetFromGameIcon(new(debugSpell.Value.Icon)).GetWrapOrEmpty().ImGuiHandle; ImGui.Image(icon, new System.Numerics.Vector2(60f.Scale(), 60f.Scale())); ImGui.SameLine(); ImGui.Image(icon, new System.Numerics.Vector2(30f.Scale(), 30f.Scale())); CustomStyleText($"Action Status:", $"{actionStatus} ({Svc.Data.GetExcelSheet().GetRow(actionStatus).Text})"); - CustomStyleText($"Action Type:", debugSpell.ActionCategory.Value.Name); - if (debugSpell.UnlockLink != 0) - CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.UnlockLink).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.UnlockLink) ? "Completed" : "Not Completed")})"); - CustomStyleText($"Base Recast:", $"{debugSpell.Recast100ms / 10f}s"); - CustomStyleText($"Max Charges:", $"{debugSpell.MaxCharges}"); - if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.RowId)) - CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.RowId])/1000f:F2}"); + CustomStyleText($"Action Type:", debugSpell.Value.ActionCategory.Value.Name); + if (debugSpell.Value.UnlockLink.RowId != 0) + CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.Value.UnlockLink.RowId).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.Value.UnlockLink.RowId) ? "Completed" : "Not Completed")})"); + CustomStyleText($"Base Recast:", $"{debugSpell.Value.Recast100ms / 10f}s"); + CustomStyleText($"Max Charges:", $"{debugSpell.Value.MaxCharges}"); + if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.Value.RowId)) + CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.Value.RowId])/1000f:F2}"); } } @@ -176,7 +175,7 @@ static void CustomStyleText(string label, object? value) ImGui.Spacing(); ImGui.Text("Player Info"); ImGui.Separator(); - CustomStyleText("Job:", $"{LocalPlayer.ClassJob.GameData.NameEnglish} (ID: {LocalPlayer.ClassJob.Id})"); + CustomStyleText("Job:", $"{LocalPlayer.ClassJob.Value.NameEnglish} (ID: {LocalPlayer.ClassJob.RowId})"); CustomStyleText("Zone:", $"{Svc.Data.GetExcelSheet()?.FirstOrDefault(x => x.RowId == Svc.ClientState.TerritoryType).PlaceName.Value.Name} (ID: {Svc.ClientState.TerritoryType})"); CustomStyleText("In PvP:", CustomComboFunctions.InPvP()); CustomStyleText("In Combat:", CustomComboFunctions.InCombat()); @@ -227,7 +226,7 @@ static void CustomStyleText(string label, object? value) if (CustomComboFunctions.GetPartySlot(i) is not IBattleChara member || member is null) continue; ImGui.TextUnformatted($"Slot {i} ->"); ImGui.SameLine(0, 4f); - CustomStyleText($"{CustomComboFunctions.GetPartySlot(i).Name}", $"({member.ClassJob.GameData.Abbreviation})"); + CustomStyleText($"{CustomComboFunctions.GetPartySlot(i).Name}", $"({member.ClassJob.Value.Abbreviation})"); } } ImGui.Spacing(); diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 8e21ca3a3..20203abea 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -1,4 +1,3 @@ -using Dalamud.Game.ClientState.Statuses; using Dalamud.Game.Command; using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; @@ -9,6 +8,7 @@ using Dalamud.Utility; using ECommons; using ECommons.DalamudServices; +using Lumina.Excel.Sheets; using System; using System.Collections.Generic; using System.IO; @@ -25,6 +25,7 @@ using XIVSlothCombo.Services; using XIVSlothCombo.Window; using XIVSlothCombo.Window.Tabs; +using Status = Dalamud.Game.ClientState.Statuses.Status; namespace XIVSlothCombo { @@ -95,7 +96,7 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) P = this; pluginInterface.Create(); ECommonsMain.Init(pluginInterface, this); - + Service.Configuration = pluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration(); Service.Address = new PluginAddressResolver(); Service.Address.Setup(Svc.SigScanner); @@ -160,7 +161,7 @@ private static void HandleConflictedCombos() private void OnFrameworkUpdate(IFramework framework) { if (Svc.ClientState.LocalPlayer is not null) - JobID = Svc.ClientState.LocalPlayer?.ClassJob?.Id; + JobID = Svc.ClientState.LocalPlayer?.ClassJob.RowId; BlueMageService.PopulateBLUSpells(); TargetHelper.Draw(); @@ -431,13 +432,13 @@ private void OnCommand(string command, string arguments) file.WriteLine($"Installation Repo: {RepoCheckFunctions.FetchCurrentRepo()?.InstalledFromUrl}"); // Installation Repo file.WriteLine(""); file.WriteLine($"Current Job: " + // Current Job - $"{Svc.ClientState.LocalPlayer.ClassJob.GameData.Name} / " + // - Client Name - $"{Svc.ClientState.LocalPlayer.ClassJob.GameData.NameEnglish} / " + // - EN Name - $"{Svc.ClientState.LocalPlayer.ClassJob.GameData.Abbreviation}"); // - Abbreviation - file.WriteLine($"Current Job Index: {Svc.ClientState.LocalPlayer.ClassJob.Id}"); // Job Index + $"{Svc.ClientState.LocalPlayer.ClassJob.Value.Name} / " + // - Client Name + $"{Svc.ClientState.LocalPlayer.ClassJob.Value.NameEnglish} / " + // - EN Name + $"{Svc.ClientState.LocalPlayer.ClassJob.Value.Abbreviation}"); // - Abbreviation + file.WriteLine($"Current Job Index: {Svc.ClientState.LocalPlayer.ClassJob.RowId}"); // Job Index file.WriteLine($"Current Job Level: {Svc.ClientState.LocalPlayer.Level}"); // Job Level file.WriteLine(""); - file.WriteLine($"Current Zone: {Svc.Data.GetExcelSheet()?.FirstOrDefault(x => x.RowId == Svc.ClientState.TerritoryType).PlaceName.Value.Name}"); // Current zone location + file.WriteLine($"Current Zone: {Svc.Data.GetExcelSheet()?.FirstOrDefault(x => x.RowId == Svc.ClientState.TerritoryType).PlaceName.Value.Name}"); // Current zone location file.WriteLine($"Current Party Size: {Svc.Party.Length}"); // Current party size file.WriteLine(""); file.WriteLine($"START ENABLED FEATURES"); @@ -500,8 +501,8 @@ private void OnCommand(string command, string arguments) else { var jobname = ConfigWindow.groupedPresets.Where(x => x.Value.Any(y => y.Info.JobShorthand.Equals(specificJob.ToLower(), StringComparison.CurrentCultureIgnoreCase))).FirstOrDefault().Key; - var jobID = Svc.Data.GetExcelSheet()? - .Where(x => x.Name.RawString.Equals(jobname, StringComparison.CurrentCultureIgnoreCase)) + var jobID = Svc.Data.GetExcelSheet()? + .Where(x => x.Name.ToString().Equals(jobname, StringComparison.CurrentCultureIgnoreCase)) .First() .RowId; diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 6905552b7..0e1b425a6 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -66,7 +66,7 @@ - + diff --git a/XIVSlothCombo/XIVSlothCombo.json b/XIVSlothCombo/XIVSlothCombo.json index 42654f4ca..00c19a340 100644 --- a/XIVSlothCombo/XIVSlothCombo.json +++ b/XIVSlothCombo/XIVSlothCombo.json @@ -2,7 +2,7 @@ "Author": "Team Sloth", "Name": "XIVSlothCombo", "InternalName": "XIVSlothCombo", - "DalamudApiLevel": 10, + "DalamudApiLevel": 11, "Punchline": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "Description": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "RepoUrl": "https://github.com/Nik-Potokar/XIVSlothCombo", From 10012a82e659bcb8f5b80d9fbf665e0d9a0e57a3 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 13 Nov 2024 08:21:00 +0000 Subject: [PATCH 196/208] Updoot --- .../AutoRotation/AutoRotationController.cs | 2 +- XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 3 ++- XIVSlothCombo/CustomCombo/Functions/Target.cs | 3 +++ XIVSlothCombo/CustomCombo/Functions/Timer.cs | 22 +++++++++++++++++++ XIVSlothCombo/Window/Tabs/Debug.cs | 2 ++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 874a8e994..5e65c2c9e 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -43,7 +43,7 @@ internal static void Run() bool combatBypass = (cfg.BypassQuest && DPSTargeting.BaseSelection.Any(x => CustomComboFunctions.IsQuestMob(x))) || (cfg.BypassFATE && CustomComboFunctions.InFATE()); - if (cfg.InCombatOnly && !CustomComboFunctions.GetPartyMembers().Any(x => x.Struct()->InCombat) && CustomComboFunctions.CombatEngageDuration().TotalSeconds < cfg.CombatDelay && !combatBypass) + if (cfg.InCombatOnly && (!CustomComboFunctions.GetPartyMembers().Any(x => x.Struct()->InCombat) || CustomComboFunctions.PartyEngageDuration().TotalSeconds < cfg.CombatDelay) && !combatBypass) return; if (Player.Job is Job.SGE && cfg.HealerSettings.ManageKardia) diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index 616f47429..4c07d5b28 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -1,4 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; +using ECommons.DalamudServices; using XIVSlothCombo.CustomComboNS.Functions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; @@ -75,7 +76,7 @@ public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) case 6: action = OriginalHook(Succor); enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal) && GetPartyBuffPercent(Buffs.Galvanize) <= Config.SCH_AoE_Heal_SuccorShieldOption; - return 0; //Don't HP Check + return 100; //Don't HP Check } enabled = false; diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 5d828f134..4ab3ae192 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -10,6 +10,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; +using Lumina.Excel.GeneratedSheets; using System; using System.Linq; using System.Numerics; @@ -561,5 +562,7 @@ internal unsafe static bool IsInLineOfSight(IGameObject target) } internal unsafe static bool IsQuestMob(IGameObject target) => target.Struct()->NamePlateIconId is 71204 or 71144 or 71224 or 71344; + + internal unsafe static bool IsBoss(IGameObject target) => Svc.Data.GetExcelSheet()?.GetRow(target.DataId).Rank is 2 or 6; } } diff --git a/XIVSlothCombo/CustomCombo/Functions/Timer.cs b/XIVSlothCombo/CustomCombo/Functions/Timer.cs index e8d16878e..475958983 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Timer.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Timer.cs @@ -1,25 +1,47 @@ using Dalamud.Game.ClientState.Conditions; +using Dalamud.Plugin.Services; using ECommons.DalamudServices; +using ECommons.GameFunctions; using System; +using System.Linq; namespace XIVSlothCombo.CustomComboNS.Functions { internal abstract partial class CustomComboFunctions { private static DateTime combatStart = DateTime.Now; + private static DateTime partyCombat = DateTime.Now; + private static bool partyInCombat = false; /// Tells the elapsed time since the combat started. /// Combat time in seconds. public static TimeSpan CombatEngageDuration() => InCombat() ? DateTime.Now - combatStart : TimeSpan.Zero; + public unsafe static TimeSpan PartyEngageDuration() => partyInCombat ? DateTime.Now - partyCombat : TimeSpan.Zero; + public static void TimerSetup() { Svc.Condition.ConditionChange += OnCombat; + Svc.Framework.Update += UpdatePartyTimer; + } + + private unsafe static void UpdatePartyTimer(IFramework framework) + { + if (GetPartyMembers().Any(x => x.Struct()->InCombat) && !partyInCombat) + { + partyInCombat = true; + partyCombat = DateTime.Now; + } + else if (!GetPartyMembers().Any(x => x.Struct()->InCombat)) + { + partyInCombat = false; + } } public static void TimerDispose() { Svc.Condition.ConditionChange -= OnCombat; + Svc.Framework.Update -= UpdatePartyTimer; } internal static void OnCombat(ConditionFlag flag, bool value) diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 15837a9fe..c3f6adbc2 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -213,6 +213,8 @@ static void CustomStyleText(string label, object? value) CustomStyleText("In Combat:", InCombat()); CustomStyleText("Hitbox Radius:", LocalPlayer.HitboxRadius); CustomStyleText("In FATE:", InFATE()); + CustomStyleText("Time in Combat:", CombatEngageDuration().ToString("mm\\:ss")); + CustomStyleText("Party Combat Time:", PartyEngageDuration().ToString("mm\\:ss")); ImGui.Spacing(); // Target Info From 1ac78642be5320a2a0ec147a5c0c6fefaf120788 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Wed, 13 Nov 2024 14:03:20 +0000 Subject: [PATCH 197/208] API 11 Merge --- ECommons | 2 +- .../Attributes/CustomComboInfoAttribute.cs | 4 ++ .../AutoRotation/AutoRotationController.cs | 2 +- XIVSlothCombo/Combos/PvE/ALL/ALL.cs | 6 +-- XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs | 3 +- XIVSlothCombo/Core/IconReplacer.cs | 8 +-- XIVSlothCombo/CustomCombo/Functions/Misc.cs | 10 ++-- XIVSlothCombo/CustomCombo/Functions/Target.cs | 2 +- XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 1 - XIVSlothCombo/Window/Tabs/Debug.cs | 50 ++++++++++--------- XIVSlothCombo/WrathCombo.json | 2 +- XIVSlothCombo/XIVSlothCombo.cs | 1 + 12 files changed, 49 insertions(+), 42 deletions(-) diff --git a/ECommons b/ECommons index 0e0cc76e4..c4e980ec0 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit 0e0cc76e4197e28b2576502f8a059815ce0a3aa4 +Subproject commit c4e980ec0435aa7931e12d8a62aaf79cc4cb2105 diff --git a/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs b/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs index f4cf2cc68..634335e90 100644 --- a/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs +++ b/XIVSlothCombo/Attributes/CustomComboInfoAttribute.cs @@ -1,7 +1,11 @@ using ECommons.DalamudServices; using Lumina.Excel.Sheets; using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using System.Runtime.CompilerServices; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; namespace XIVSlothCombo.Attributes diff --git a/XIVSlothCombo/AutoRotation/AutoRotationController.cs b/XIVSlothCombo/AutoRotation/AutoRotationController.cs index 5e65c2c9e..79759ed7f 100644 --- a/XIVSlothCombo/AutoRotation/AutoRotationController.cs +++ b/XIVSlothCombo/AutoRotation/AutoRotationController.cs @@ -16,7 +16,7 @@ using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; using XIVSlothCombo.Window.Functions; -using Action = Lumina.Excel.GeneratedSheets.Action; +using Action = Lumina.Excel.Sheets.Action; namespace XIVSlothCombo.AutoRotation { diff --git a/XIVSlothCombo/Combos/PvE/ALL/ALL.cs b/XIVSlothCombo/Combos/PvE/ALL/ALL.cs index 4e04b5953..0b9eac7c1 100644 --- a/XIVSlothCombo/Combos/PvE/ALL/ALL.cs +++ b/XIVSlothCombo/Combos/PvE/ALL/ALL.cs @@ -139,7 +139,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim switch (actionID) { case WHM.Raise or AST.Ascend or SGE.Egeiro: - case SCH.Resurrection when LocalPlayer.ClassJob.Id is SCH.JobID: + case SCH.Resurrection when LocalPlayer.ClassJob.RowId is SCH.JobID: { if (ActionReady(Swiftcast)) return Swiftcast; @@ -179,7 +179,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim switch (actionID) { case BLU.AngelWhisper or RDM.Verraise: - case SMN.Resurrection when LocalPlayer.ClassJob.Id is SMN.JobID: + case SMN.Resurrection when LocalPlayer.ClassJob.RowId is SMN.JobID: { if (HasEffect(Buffs.Swiftcast) || HasEffect(RDM.Buffs.Dualcast)) return actionID; @@ -187,7 +187,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsOffCooldown(Swiftcast)) return Swiftcast; - if (LocalPlayer.ClassJob.Id is RDM.JobID && + if (LocalPlayer.ClassJob.RowId is RDM.JobID && ActionReady(RDM.Vercure)) return RDM.Vercure; diff --git a/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs b/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs index 01de1c4ca..2c77683dd 100644 --- a/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/AST/AST_Helper.cs @@ -1,4 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using ECommons.DalamudServices; @@ -55,7 +56,7 @@ private static bool BetterTargetAvailable() CustomComboFunctions.OutOfRange(Balance, QuickTargetCards.SelectedRandomMember)) return true; - var m = AST_QuickTargetCards.SelectedRandomMember as IBattleChara; + var m = QuickTargetCards.SelectedRandomMember as IBattleChara; if ((DrawnCard is CardType.BALANCE && CustomComboFunctions.JobIDs.Melee.Any(x => x == m.ClassJob.RowId)) || (DrawnCard is CardType.SPEAR && CustomComboFunctions.JobIDs.Ranged.Any(x => x == m.ClassJob.RowId))) return false; diff --git a/XIVSlothCombo/Core/IconReplacer.cs b/XIVSlothCombo/Core/IconReplacer.cs index 98c920524..cdd4ee298 100644 --- a/XIVSlothCombo/Core/IconReplacer.cs +++ b/XIVSlothCombo/Core/IconReplacer.cs @@ -65,8 +65,8 @@ private unsafe uint GetIconDetour(IntPtr actionManager, uint actionID) return OriginalHook(actionID); if (ClassLocked() || - (DisabledJobsPVE.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.Id) && !Svc.ClientState.IsPvP) || - (DisabledJobsPVP.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.Id) && Svc.ClientState.IsPvP)) + (DisabledJobsPVE.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.RowId) && !Svc.ClientState.IsPvP) || + (DisabledJobsPVP.Any(x => x == Svc.ClientState.LocalPlayer.ClassJob.RowId) && Svc.ClientState.IsPvP)) return OriginalHook(actionID); uint lastComboMove = ActionManager.Instance()->Combo.Action; @@ -102,14 +102,14 @@ public unsafe static bool ClassLocked() if (Svc.ClientState.LocalPlayer.Level <= 35) return false; - if (Svc.ClientState.LocalPlayer.ClassJob.Id is + if (Svc.ClientState.LocalPlayer.ClassJob.RowId is (>= 8 and <= 25) or 27 or 28 or >= 30) return false; if (!UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(66049)) return false; - if ((Svc.ClientState.LocalPlayer.ClassJob.Id is 1 or 2 or 3 or 4 or 5 or 6 or 7 or 26 or 29) && + if ((Svc.ClientState.LocalPlayer.ClassJob.RowId is 1 or 2 or 3 or 4 or 5 or 6 or 7 or 26 or 29) && Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.BoundByDuty] && Svc.ClientState.LocalPlayer.Level > 35) return true; diff --git a/XIVSlothCombo/CustomCombo/Functions/Misc.cs b/XIVSlothCombo/CustomCombo/Functions/Misc.cs index 23223e93d..75f33a1be 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Misc.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Misc.cs @@ -1,5 +1,5 @@ using ECommons.DalamudServices; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -38,7 +38,7 @@ public static string JobIDToShorthand(byte key) if (ClassJobs.TryGetValue(key, out var job)) { - return job.Abbreviation.RawString; + return job.Abbreviation.ToString(); } else { @@ -56,10 +56,10 @@ public static string JobIDToName(byte key) //Override DOH/DOL if (key is DOH.JobID) key = 08; //Set to Carpenter if (key is DOL.JobID) key = 16; //Set to Miner - if (ClassJobs.TryGetValue(key, out ClassJob? job)) + if (ClassJobs.TryGetValue(key, out ClassJob job)) { //Grab Category name for DOH/DOL, else the normal Name for the rest - string jobname = key is 08 or 16 ? job.ClassJobCategory.Value.Name : job.Name; + string jobname = key is 08 or 16 ? job.ClassJobCategory.Value.Name.ToString() : job.Name.ToString(); //Job names are all lowercase by default. This capitalizes based on regional rules string cultureID = Svc.ClientState.ClientLanguage switch { @@ -80,7 +80,7 @@ public static string JobIDToName(byte key) public static uint JobIDToClassJobCategory(byte jobID) { if (Svc.Data.GetExcelSheet().HasRow(jobID)) - return Svc.Data.GetExcelSheet().GetRow(jobID).ClassJobCategory.Row; + return Svc.Data.GetExcelSheet().GetRow(jobID).ClassJobCategory.RowId; return 0; } diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 131ec1bc9..96dfab3b3 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -10,7 +10,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; using System; using System.Linq; using System.Numerics; diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index 537fba2e6..e5229a203 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -2,7 +2,6 @@ using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; -using Lumina.Excel.GeneratedSheets; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Extensions; diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index b4642ab45..cbc03ec36 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -22,6 +22,8 @@ using Status = Dalamud.Game.ClientState.Statuses.Status; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; using FFXIVClientStructs.FFXIV.Client.Game.Fate; +using Action = Lumina.Excel.Sheets.Action; +using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; namespace XIVSlothCombo.Window.Tabs { @@ -150,10 +152,10 @@ static void CustomStyleText(string label, object? value) } var classId = JobIDs.JobToClass(JobID!.Value); - var cjc = Svc.Data.Excel.GetSheetRaw("ClassJobCategory"); - var cjcColumIdx = cjc.Columns[JobID.Value]; + var cjc = Svc.Data.Excel.GetRawSheet("ClassJobCategory"); + var cjcColumIdx = cjc.Columns[(int)JobID.Value]; - foreach (var act in Svc.Data.GetExcelSheet()!.Where(x => x.IsPlayerAction && (x.ClassJob.Row == classId || x.ClassJob.Row == JobID.Value)).OrderBy(x => x.ClassJobLevel)) + foreach (var act in Svc.Data.GetExcelSheet()!.Where(x => x.IsPlayerAction && (x.ClassJob.RowId == classId || x.ClassJob.RowId == JobID.Value)).OrderBy(x => x.ClassJobLevel)) { if (ImGui.Selectable($"({act.RowId}) Lv.{act.ClassJobLevel}. {act.Name} - {(act.IsPvP ? "PvP" : "Normal")}", debugSpell?.RowId == act.RowId)) { @@ -171,33 +173,33 @@ static void CustomStyleText(string label, object? value) ImGui.SameLine(); ImGui.Image(icon, new System.Numerics.Vector2(30f.Scale(), 30f.Scale())); CustomStyleText($"Action Status:", $"{actionStatus} ({Svc.Data.GetExcelSheet().GetRow(actionStatus).Text})"); - CustomStyleText($"Action Type:", debugSpell.ActionCategory.Value.Name); - if (debugSpell.UnlockLink != 0) - CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.UnlockLink).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.UnlockLink) ? "Completed" : "Not Completed")})"); - CustomStyleText($"Base Recast:", $"{debugSpell.Recast100ms / 10f}s"); - CustomStyleText($"Max Charges:", $"{debugSpell.MaxCharges}"); - CustomStyleText($"Range:", $"{debugSpell.Range}"); - CustomStyleText($"Effect Range:", $"{debugSpell.EffectRange}"); - CustomStyleText($"Can Target Hostile:", $"{debugSpell.CanTargetHostile}"); - CustomStyleText($"Can Target Self:", $"{debugSpell.CanTargetSelf}"); - CustomStyleText($"Can Target Friendly:", $"{debugSpell.CanTargetFriendly}"); - CustomStyleText($"Can Target Party:", $"{debugSpell.CanTargetParty}"); - CustomStyleText($"Can Target Area:", $"{debugSpell.TargetArea}"); - CustomStyleText($"Cast Type:", $"{debugSpell.CastType}"); - if (debugSpell.EffectRange > 0) - CustomStyleText($"Targets Hit:", $"{NumberOfEnemiesInRange(debugSpell.RowId, CurrentTarget)}"); + CustomStyleText($"Action Type:", debugSpell.Value.ActionCategory.Value.Name); + if (debugSpell.Value.UnlockLink.RowId != 0) + CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.Value.UnlockLink.RowId).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.Value.UnlockLink.RowId) ? "Completed" : "Not Completed")})"); + CustomStyleText($"Base Recast:", $"{debugSpell.Value.Recast100ms / 10f}s"); + CustomStyleText($"Max Charges:", $"{debugSpell.Value.MaxCharges}"); + CustomStyleText($"Range:", $"{debugSpell.Value.Range}"); + CustomStyleText($"Effect Range:", $"{debugSpell.Value.EffectRange}"); + CustomStyleText($"Can Target Hostile:", $"{debugSpell.Value.CanTargetHostile}"); + CustomStyleText($"Can Target Self:", $"{debugSpell.Value.CanTargetSelf}"); + CustomStyleText($"Can Target Friendly:", $"{debugSpell.Value.CanTargetAlly}"); + CustomStyleText($"Can Target Party:", $"{debugSpell.Value.CanTargetParty}"); + CustomStyleText($"Can Target Area:", $"{debugSpell.Value.TargetArea}"); + CustomStyleText($"Cast Type:", $"{debugSpell.Value.CastType}"); + if (debugSpell.Value.EffectRange > 0) + CustomStyleText($"Targets Hit:", $"{NumberOfEnemiesInRange(debugSpell.Value.RowId, CurrentTarget)}"); - if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.RowId)) - CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.RowId])/1000f:F2}"); + if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.Value.RowId)) + CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.Value.RowId])/1000f:F2}"); if (Svc.Targets.Target != null) { - var inRange = ActionManager.GetActionInRangeOrLoS(debugSpell.RowId, (GameObject*)LocalPlayer.Address, (GameObject*)Svc.Targets.Target.Address); + var inRange = ActionManager.GetActionInRangeOrLoS(debugSpell.Value.RowId, (GameObject*)LocalPlayer.Address, (GameObject*)Svc.Targets.Target.Address); CustomStyleText("InRange or LoS:", inRange == 0 ? "In range and in line of sight" : $"{inRange}: {Svc.Data.GetExcelSheet().GetRow(inRange).Text}"); - var canUseOnTarget = ActionManager.CanUseActionOnTarget(debugSpell.RowId, Svc.Targets.Target.Struct()); + var canUseOnTarget = ActionManager.CanUseActionOnTarget(debugSpell.Value.RowId, Svc.Targets.Target.Struct()); CustomStyleText($"Can Use on Target:", canUseOnTarget); } - var canUseOnSelf = ActionManager.CanUseActionOnTarget(debugSpell.RowId, Player.GameObject); + var canUseOnSelf = ActionManager.CanUseActionOnTarget(debugSpell.Value.RowId, Player.GameObject); CustomStyleText($"Can Use on Self:", canUseOnSelf); } } @@ -279,7 +281,7 @@ static void CustomStyleText(string label, object? value) if (GetPartySlot(i) is not IBattleChara member || member is null) continue; ImGui.TextUnformatted($"Slot {i} ->"); ImGui.SameLine(0, 4f); - CustomStyleText($"{GetPartySlot(i).Name}", $"({member.ClassJob.GameData.Abbreviation})"); + CustomStyleText($"{GetPartySlot(i).Name}", $"({member.ClassJob.Value.Abbreviation})"); } } ImGui.Spacing(); diff --git a/XIVSlothCombo/WrathCombo.json b/XIVSlothCombo/WrathCombo.json index 853e1fe50..63fc054c1 100644 --- a/XIVSlothCombo/WrathCombo.json +++ b/XIVSlothCombo/WrathCombo.json @@ -2,7 +2,7 @@ "Author": "Team Wrath", "Name": "Wrath Combo", "InternalName": "WrathCombo", - "DalamudApiLevel": 10, + "DalamudApiLevel": 11, "Punchline": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "Description": "Condenses combos and mutually exclusive abilities onto a single button - and then some.", "RepoUrl": "https://github.com/PunishXIV/WrathCombo", diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index ac4029122..ac8b2562e 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -9,6 +9,7 @@ using Dalamud.Utility; using ECommons; using ECommons.DalamudServices; +using Lumina.Excel.Sheets; using PunishLib; using System; using System.Collections.Generic; From 344bcfdacd95d045a79141d05ffd84184f1ffd4b Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Fri, 15 Nov 2024 08:07:05 +0000 Subject: [PATCH 198/208] Update debug gauges --- XIVSlothCombo/Combos/PvE/WHM/WHM.cs | 1 - XIVSlothCombo/Window/Tabs/Debug.cs | 82 +++++++++++++++++++++++++++-- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs index 43a9600ea..1d407bfb2 100644 --- a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs @@ -165,7 +165,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } else ActionFound = StoneGlareList.Contains(actionID); //default handling - Svc.Log.Debug($"HERE"); if (ActionFound) { WHMGauge? gauge = GetJobGauge(); diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index cbc03ec36..7b8101f19 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -24,6 +24,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.Fate; using Action = Lumina.Excel.Sheets.Action; using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; +using Dalamud.Utility; +using ECommons.ExcelServices; namespace XIVSlothCombo.Window.Tabs { @@ -154,7 +156,7 @@ static void CustomStyleText(string label, object? value) var classId = JobIDs.JobToClass(JobID!.Value); var cjc = Svc.Data.Excel.GetRawSheet("ClassJobCategory"); var cjcColumIdx = cjc.Columns[(int)JobID.Value]; - + foreach (var act in Svc.Data.GetExcelSheet()!.Where(x => x.IsPlayerAction && (x.ClassJob.RowId == classId || x.ClassJob.RowId == JobID.Value)).OrderBy(x => x.ClassJobLevel)) { if (ImGui.Selectable($"({act.RowId}) Lv.{act.ClassJobLevel}. {act.Name} - {(act.IsPvP ? "PvP" : "Normal")}", debugSpell?.RowId == act.RowId)) @@ -175,7 +177,7 @@ static void CustomStyleText(string label, object? value) CustomStyleText($"Action Status:", $"{actionStatus} ({Svc.Data.GetExcelSheet().GetRow(actionStatus).Text})"); CustomStyleText($"Action Type:", debugSpell.Value.ActionCategory.Value.Name); if (debugSpell.Value.UnlockLink.RowId != 0) - CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.Value.UnlockLink.RowId).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.Value.UnlockLink.RowId) ? "Completed" : "Not Completed")})"); + CustomStyleText($"Quest:", $"{Svc.Data.GetExcelSheet().GetRow(debugSpell.Value.UnlockLink.RowId).Name} ({(UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(debugSpell.Value.UnlockLink.RowId) ? "Completed" : "Not Completed")})"); CustomStyleText($"Base Recast:", $"{debugSpell.Value.Recast100ms / 10f}s"); CustomStyleText($"Max Charges:", $"{debugSpell.Value.MaxCharges}"); CustomStyleText($"Range:", $"{debugSpell.Value.Range}"); @@ -187,10 +189,10 @@ static void CustomStyleText(string label, object? value) CustomStyleText($"Can Target Area:", $"{debugSpell.Value.TargetArea}"); CustomStyleText($"Cast Type:", $"{debugSpell.Value.CastType}"); if (debugSpell.Value.EffectRange > 0) - CustomStyleText($"Targets Hit:", $"{NumberOfEnemiesInRange(debugSpell.Value.RowId, CurrentTarget)}"); + CustomStyleText($"Targets Hit:", $"{NumberOfEnemiesInRange(debugSpell.Value.RowId, CurrentTarget)}"); if (ActionWatching.ActionTimestamps.ContainsKey(debugSpell.Value.RowId)) - CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.Value.RowId])/1000f:F2}"); + CustomStyleText($"Time Since Last Use:", $"{(Environment.TickCount64 - ActionWatching.ActionTimestamps[debugSpell.Value.RowId]) / 1000f:F2}"); if (Svc.Targets.Target != null) { @@ -218,6 +220,78 @@ static void CustomStyleText(string label, object? value) CustomStyleText("Party Combat Time:", PartyEngageDuration().ToString("mm\\:ss")); ImGui.Spacing(); + ImGui.Spacing(); + ImGui.Text($"Job Gauge"); + ImGui.Separator(); + + switch (Player.Job) + { + case Job.PLD: + Util.ShowStruct(&JobGaugeManager.Instance()->Paladin); + break; + case Job.MNK: + Util.ShowStruct(&JobGaugeManager.Instance()->Monk); + break; + case Job.WAR: + Util.ShowStruct(&JobGaugeManager.Instance()->Warrior); + break; + case Job.DRG: + Util.ShowStruct(&JobGaugeManager.Instance()->Dragoon); + break; + case Job.BRD: + Util.ShowStruct(&JobGaugeManager.Instance()->Bard); + break; + case Job.WHM: + Util.ShowStruct(&JobGaugeManager.Instance()->WhiteMage); + break; + case Job.BLM: + Util.ShowStruct(&JobGaugeManager.Instance()->BlackMage); + break; + case Job.SMN: + Util.ShowStruct(&JobGaugeManager.Instance()->Summoner); + break; + case Job.SCH: + Util.ShowStruct(&JobGaugeManager.Instance()->Scholar); + break; + case Job.NIN: + Util.ShowStruct(&JobGaugeManager.Instance()->Ninja); + break; + case Job.MCH: + Util.ShowStruct(&JobGaugeManager.Instance()->Machinist); + break; + case Job.DRK: + Util.ShowStruct(&JobGaugeManager.Instance()->DarkKnight); + break; + case Job.AST: + Util.ShowStruct(&JobGaugeManager.Instance()->Astrologian); + break; + case Job.SAM: + Util.ShowStruct(&JobGaugeManager.Instance()->Samurai); + break; + case Job.RDM: + Util.ShowStruct(&JobGaugeManager.Instance()->RedMage); + break; + case Job.GNB: + Util.ShowStruct(&JobGaugeManager.Instance()->Gunbreaker); + break; + case Job.DNC: + Util.ShowStruct(&JobGaugeManager.Instance()->Dancer); + break; + case Job.RPR: + Util.ShowStruct(&JobGaugeManager.Instance()->Reaper); + break; + case Job.SGE: + Util.ShowStruct(&JobGaugeManager.Instance()->Sage); + break; + case Job.VPR: + Util.ShowStruct(&JobGaugeManager.Instance()->Viper); + break; + case Job.PCT: + Util.ShowStruct(&JobGaugeManager.Instance()->Pictomancer); + break; + } + + // Target Info ImGui.Spacing(); ImGui.Text("Target Info"); diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index bf7f0bda0..0f7c70384 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.10 + 0.0.0.11 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU From fcf8fbcf57f2631096f2b6b8a08a6db5c20ab35a Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sat, 16 Nov 2024 10:23:00 +0000 Subject: [PATCH 199/208] Update gauge logic --- XIVSlothCombo/Combos/PvE/WHM.cs | 1 - XIVSlothCombo/Data/CustomComboCache.cs | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM.cs index 24902c5e7..90844b016 100644 --- a/XIVSlothCombo/Combos/PvE/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM.cs @@ -203,7 +203,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } else ActionFound = StoneGlareList.Contains(actionID); //default handling - Svc.Log.Debug($"HERE"); if (ActionFound) { WHMGauge? gauge = GetJobGauge(); diff --git a/XIVSlothCombo/Data/CustomComboCache.cs b/XIVSlothCombo/Data/CustomComboCache.cs index 1edbce42f..1f78b82a3 100644 --- a/XIVSlothCombo/Data/CustomComboCache.cs +++ b/XIVSlothCombo/Data/CustomComboCache.cs @@ -5,6 +5,7 @@ using FFXIVClientStructs.FFXIV.Client.Game; using System; using System.Collections.Concurrent; +using System.Reflection; using DalamudStatus = Dalamud.Game.ClientState.Statuses; // conflicts with structs if not defined namespace XIVSlothCombo.Data @@ -26,6 +27,8 @@ internal partial class CustomComboCache : IDisposable private delegate IntPtr GetActionCooldownSlotDelegate(IntPtr actionManager, int cooldownGroup); + private unsafe IntPtr CSAddress => (nint)(JobGaugeManager.Instance()->CurrentGauge); + /// public void Dispose() => Svc.Framework.Update -= Framework_Update; @@ -34,8 +37,11 @@ internal partial class CustomComboCache : IDisposable /// The job gauge. internal T GetJobGauge() where T : JobGaugeBase { - if (!jobGaugeCache.TryGetValue(typeof(T), out JobGaugeBase? gauge)) - gauge = jobGaugeCache[typeof(T)] = Svc.Gauges.Get(); + //Lifted from Dalamud, using our own cache instead of theirs + if (!this.jobGaugeCache.TryGetValue(typeof(T), out var gauge) || gauge.Address != this.CSAddress) + { + gauge = this.jobGaugeCache[typeof(T)] = (T)Activator.CreateInstance(typeof(T), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { this.CSAddress }, null); + } return (T)gauge; } From 5cd9a8c9a9d510d2c7d96a01d4e5b7dd69ccbecc Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 14:02:37 +0000 Subject: [PATCH 200/208] Merge BLM --- ECommons | 2 +- XIVSlothCombo/Combos/CustomComboPreset.cs | 85 +++-- XIVSlothCombo/Combos/PvE/ALL/ALL.cs | 377 ++++++++++----------- XIVSlothCombo/Combos/PvE/BLM/BLM.cs | 374 +++++++++----------- XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs | 20 +- XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs | 81 +++-- 6 files changed, 461 insertions(+), 478 deletions(-) diff --git a/ECommons b/ECommons index c4e980ec0..71ee09f7c 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit c4e980ec0435aa7931e12d8a62aaf79cc4cb2105 +Subproject commit 71ee09f7cc2230a73503b945422760da1368405c diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 5de0338c8..5a2e6baa6 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -365,24 +365,22 @@ public enum CustomComboPreset // Last value = 1054 #endregion - + #region BLACK MAGE - [AutoAction(false, false)] [ReplaceSkill(BLM.Fire)] [ConflictingCombos(BLM_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID)] BLM_ST_SimpleMode = 2001, - [AutoAction(true, false)] + [ReplaceSkill(BLM.Blizzard2, BLM.HighBlizzard2)] [ConflictingCombos(BLM_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID)] BLM_AoE_SimpleMode = 2002, - + #region Single Target - Advanced - [AutoAction(false, false)] [ReplaceSkill(BLM.Fire)] [ConflictingCombos(BLM_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", BLM.JobID)] @@ -393,104 +391,104 @@ public enum CustomComboPreset BLM_ST_Opener = 2101, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Amplifier", "Add Amplifier to the rotation.", BLM.JobID)] + [CustomComboInfo("Amplifier Option", "Add Amplifier to the rotation.", BLM.JobID)] BLM_ST_Amplifier = 2102, - [ParentCombo(BLM_ST_AdvancedMode)] [CustomComboInfo("Use Leylines", "Add Leylines to the rotation.", BLM.JobID)] + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Leylines Option", "Add Leylines to the rotation.", BLM.JobID)] BLM_ST_LeyLines = 2103, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Foul / Xenoglossy", "Add Foul / Xenoglossy to the rotation.", BLM.JobID)] + [CustomComboInfo("Foul/Xenoglossy Option", "Add Foul/Xenoglossy to the rotation.", BLM.JobID)] BLM_ST_UsePolyglot = 2104, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Foul / Xenoglossy for movement", "Add Foul / Xenoglossy to the rotation as movement option.", BLM.JobID)] + [CustomComboInfo("Foul/Xenoglossy for Movement Option", "Add Foul / Xenoglossy to the rotation as movement option.", BLM.JobID)] BLM_ST_UsePolyglotMoving = 2105, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Swiftcast", "Add Swiftcast to the rotation.", BLM.JobID)] + [CustomComboInfo("Swiftcast Option", "Add Swiftcast to the rotation.", BLM.JobID)] BLM_ST_Swiftcast = 2106, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Triplecast", "Add Triplecast to the rotation.", BLM.JobID)] + [CustomComboInfo("Triplecast Option", "Add Triplecast to the rotation.", BLM.JobID)] BLM_ST_Triplecast = 2107, - [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Manafont", "Add Manafont to the rotation.", BLM.JobID)] + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Manafont Option", "Add Manafont to the rotation.", BLM.JobID)] BLM_ST_Manafont = 2108, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Transpose", "Add Transpose to the rotation.", BLM.JobID)] + [CustomComboInfo("Transpose Option", "Add Transpose to the rotation.", BLM.JobID)] BLM_ST_Transpose = 2109, - - [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Thunder", "Add Thunder to the rotation.", BLM.JobID)] + + [ParentCombo(BLM_ST_AdvancedMode)] + [CustomComboInfo("Thunder Option", "Add Thunder to the rotation.", BLM.JobID)] BLM_ST_Thunder = 2110, [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Despair", "Add Despair to the rotation.", BLM.JobID)] + [CustomComboInfo("Despair Option", "Add Despair to the rotation.", BLM.JobID)] BLM_ST_Despair = 2111, - + [ParentCombo(BLM_ST_AdvancedMode)] - [CustomComboInfo("Use Flarestar", "Add Flarestar to the rotation.", BLM.JobID)] - BLM_ST_Flarestar = 2112, - + [CustomComboInfo("Flare Star Option", "Add Flare Star to the rotation.", BLM.JobID)] + BLM_ST_FlareStar = 2112, + #endregion - + #region AoE - Advanced - [AutoAction(true, false)] [ReplaceSkill(BLM.Fire)] [ConflictingCombos(BLM_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", BLM.JobID)] BLM_AoE_AdvancedMode = 2200, [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Amplifier", "Add Amplifier to the rotation.", BLM.JobID)] + [CustomComboInfo("Amplifier Option", "Add Amplifier to the rotation.", BLM.JobID)] BLM_AoE_Amplifier = 2201, - [ParentCombo(CustomComboPreset.BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Leylines", "Add Leylines to the rotation.", BLM.JobID)] + [ParentCombo(BLM_AoE_AdvancedMode)] + [CustomComboInfo("Leylines Option", "Add Leylines to the rotation.", BLM.JobID)] BLM_AoE_LeyLines = 2202, - + [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Foul", "Add Foul to the rotation.", BLM.JobID)] + [CustomComboInfo("Foul Option", "Add Foul to the rotation.", BLM.JobID)] BLM_AoE_UsePolyglot = 2203, [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Foul for movement", "Add Foul to the rotation as movement option.", BLM.JobID)] + [CustomComboInfo("Foul for Movement Option", "Add Foul to the rotation as movement option.", BLM.JobID)] BLM_AoE_UsePolyglotMoving = 2204, [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Swiftcast", "Add Swiftcast to the rotation.", BLM.JobID)] + [CustomComboInfo("Swiftcast Option", "Add Swiftcast to the rotation.", BLM.JobID)] BLM_AoE_Swiftcast = 2205, [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Triplecast", "Add Triplecast to the rotation.", BLM.JobID)] + [CustomComboInfo("Triplecast Option", "Add Triplecast to the rotation.", BLM.JobID)] BLM_AoE_Triplecast = 2206, [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Manafont", "Add Manafont to the rotation.", BLM.JobID)] + [CustomComboInfo("Manafont Option", "Add Manafont to the rotation.", BLM.JobID)] BLM_AoE_Manafont = 2207, [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Transpose", "Add Transpose to the rotation.", BLM.JobID)] + [CustomComboInfo("Transpose Option", "Add Transpose to the rotation.", BLM.JobID)] BLM_AoE_Transpose = 2208, - + [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Thunder", "Add Thunder to the rotation.", BLM.JobID)] + [CustomComboInfo("Thunder Option", "Add Thunder to the rotation.", BLM.JobID)] BLM_AoE_Thunder = 2209, - + [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Flare", "Add Flare to the rotation.", BLM.JobID)] + [CustomComboInfo("Flare Option", "Add Flare to the rotation.", BLM.JobID)] BLM_AoE_Flare = 2210, - + [ParentCombo(BLM_AoE_AdvancedMode)] - [CustomComboInfo("Use Flarestar", "Add Flarestar to the rotation.", BLM.JobID)] - BLM_AoE_Flarestar = 2211, - + [CustomComboInfo("Flare Star Option", "Add Flare Star to the rotation.", BLM.JobID)] + BLM_AoE_FlareStar = 2211, + #endregion - + #region Variant [Variant] @@ -538,6 +536,7 @@ public enum CustomComboPreset [ReplaceSkill(BLM.Triplecast)] [CustomComboInfo("Triplecast Protection", "Replaces Triplecast with Savage Blade when u already have triplecast active.", BLM.JobID)] BLM_TriplecastProtection = 2056, + #endregion // Last value ST = 2112 diff --git a/XIVSlothCombo/Combos/PvE/ALL/ALL.cs b/XIVSlothCombo/Combos/PvE/ALL/ALL.cs index 0b9eac7c1..1ba1d8e99 100644 --- a/XIVSlothCombo/Combos/PvE/ALL/ALL.cs +++ b/XIVSlothCombo/Combos/PvE/ALL/ALL.cs @@ -2,252 +2,251 @@ using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; -namespace XIVSlothCombo.Combos.PvE; - -internal partial class All +namespace XIVSlothCombo.Combos.PvE { - public const byte JobID = 0; - - public const uint - Rampart = 7531, - SecondWind = 7541, - TrueNorth = 7546, - Addle = 7560, - Swiftcast = 7561, - LucidDreaming = 7562, - Resurrection = 173, - Raise = 125, - Provoke = 7533, - Shirk = 7537, - Reprisal = 7535, - Esuna = 7568, - Rescue = 7571, - SolidReason = 232, - AgelessWords = 215, - Sleep = 25880, - WiseToTheWorldMIN = 26521, - WiseToTheWorldBTN = 26522, - LowBlow = 7540, - Bloodbath = 7542, - HeadGraze = 7551, - FootGraze = 7553, - LegGraze = 7554, - Feint = 7549, - Interject = 7538, - Peloton = 7557, - LegSweep = 7863, - Repose = 16560, - Sprint = 3; - - private const uint - IsleSprint = 31314; - - /// - /// Quick Level, Offcooldown, spellweave, and MP check of Lucid Dreaming - /// - /// action id to check weave - /// Player MP less than Threshold check - /// Spell Weave check by default - /// - public static bool CanUseLucid(uint actionID, int MPThreshold, bool weave = true) - { - return CustomComboFunctions.ActionReady(LucidDreaming) - && CustomComboFunctions.LocalPlayer.CurrentMp <= MPThreshold - && (!weave || CustomComboFunctions.CanSpellWeave(actionID)); - } - - public static class Buffs - { - public const ushort - Weakness = 43, - Medicated = 49, - Bloodbath = 84, - Swiftcast = 167, - Rampart = 1191, - Peloton = 1199, - LucidDreaming = 1204, - TrueNorth = 1250, - Sprint = 50; - } - - public static class Debuffs - { - public const ushort - Sleep = 3, - Bind = 13, - Heavy = 14, - Addle = 1203, - Reprisal = 1193, - Feint = 1195; - } - - internal class ALL_IslandSanctuary_Sprint : CustomCombo + internal class All { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_IslandSanctuary_Sprint; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + public const byte JobID = 0; + + public const uint + Rampart = 7531, + SecondWind = 7541, + TrueNorth = 7546, + Addle = 7560, + Swiftcast = 7561, + LucidDreaming = 7562, + Resurrection = 173, + Raise = 125, + Provoke = 7533, + Shirk = 7537, + Reprisal = 7535, + Esuna = 7568, + Rescue = 7571, + SolidReason = 232, + AgelessWords = 215, + Sleep = 25880, + WiseToTheWorldMIN = 26521, + WiseToTheWorldBTN = 26522, + LowBlow = 7540, + Bloodbath = 7542, + HeadGraze = 7551, + FootGraze = 7553, + LegGraze = 7554, + Feint = 7549, + Interject = 7538, + Peloton = 7557, + LegSweep = 7863, + Repose = 16560, + Sprint = 3; + private const uint + IsleSprint = 31314; + + public static class Buffs { - return actionID is Sprint && Svc.ClientState.TerritoryType is 1055 - ? IsleSprint - : actionID; + public const ushort + Weakness = 43, + Medicated = 49, + Bloodbath = 84, + Swiftcast = 167, + Rampart = 1191, + Peloton = 1199, + LucidDreaming = 1204, + TrueNorth = 1250, + Sprint = 50; } - } - //Tank Features - internal class ALL_Tank_Interrupt : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Interrupt; + public static class Debuffs + { + public const ushort + Sleep = 3, + Bind = 13, + Heavy = 14, + Addle = 1203, + Reprisal = 1193, + Feint = 1195; + } - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + /// + /// Quick Level, Offcooldown, spellweave, and MP check of Lucid Dreaming + /// + /// action id to check weave + /// Player MP less than Threshold check + /// Spell Weave check by default + /// + public static bool CanUseLucid(uint actionID, int MPThreshold, bool weave = true) => + CustomComboFunctions.ActionReady(LucidDreaming) + && CustomComboFunctions.LocalPlayer.CurrentMp <= MPThreshold + && (!weave || CustomComboFunctions.CanSpellWeave(actionID)); + + internal class ALL_IslandSanctuary_Sprint : CustomCombo { - switch (actionID) + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_IslandSanctuary_Sprint; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - case LowBlow or PLD.ShieldBash when CanInterruptEnemy() && ActionReady(Interject): - return Interject; + if (actionID is Sprint && Svc.ClientState.TerritoryType is 1055) return IsleSprint; + else return actionID; + } + } - case LowBlow or PLD.ShieldBash when ActionReady(LowBlow): - return LowBlow; + //Tank Features + internal class ALL_Tank_Interrupt : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Interrupt; - case LowBlow or PLD.ShieldBash when actionID == PLD.ShieldBash && IsOnCooldown(LowBlow): - return actionID; + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is LowBlow or PLD.ShieldBash) + { + if (CanInterruptEnemy() && ActionReady(Interject)) + return Interject; + if (ActionReady(LowBlow)) + return LowBlow; + if (actionID == PLD.ShieldBash && IsOnCooldown(LowBlow)) + return actionID; + } - default: - return actionID; + return actionID; } } - } - internal class ALL_Tank_Reprisal : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Reprisal; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + internal class ALL_Tank_Reprisal : CustomCombo { - return actionID is Reprisal && TargetHasEffectAny(Debuffs.Reprisal) && IsOffCooldown(Reprisal) - ? OriginalHook(11) - : actionID; - } - } + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Tank_Reprisal; - //Healer Features - internal class ALL_Healer_Raise : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Healer_Raise; + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Reprisal) + { + if (TargetHasEffectAny(Debuffs.Reprisal) && IsOffCooldown(Reprisal)) + return OriginalHook(11); + } - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + return actionID; + } + } + + //Healer Features + internal class ALL_Healer_Raise : CustomCombo { - switch (actionID) + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Healer_Raise; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - case WHM.Raise or AST.Ascend or SGE.Egeiro: - case SCH.Resurrection when LocalPlayer.ClassJob.RowId is SCH.JobID: + if ((actionID is WHM.Raise or AST.Ascend or SGE.Egeiro) + || (actionID is SCH.Resurrection && LocalPlayer.ClassJob.Value.RowId is SCH.JobID)) { if (ActionReady(Swiftcast)) return Swiftcast; - if (actionID == WHM.Raise && IsEnabled(CustomComboPreset.WHM_ThinAirRaise) && - ActionReady(WHM.ThinAir) && !HasEffect(WHM.Buffs.ThinAir)) + if (actionID == WHM.Raise && IsEnabled(CustomComboPreset.WHM_ThinAirRaise) && ActionReady(WHM.ThinAir) && !HasEffect(WHM.Buffs.ThinAir)) return WHM.ThinAir; return actionID; } - default: - return actionID; + return actionID; } } - } - //Caster Features - internal class ALL_Caster_Addle : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Addle; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + //Caster Features + internal class ALL_Caster_Addle : CustomCombo { - return actionID is Addle && TargetHasEffectAny(Debuffs.Addle) && IsOffCooldown(Addle) - ? OriginalHook(11) - : actionID; - } - } + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Addle; - internal class ALL_Caster_Raise : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Raise; + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Addle) + { + if (TargetHasEffectAny(Debuffs.Addle) && IsOffCooldown(Addle)) + return OriginalHook(11); + } + + return actionID; + } + } - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + internal class ALL_Caster_Raise : CustomCombo { - switch (actionID) + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Caster_Raise; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - case BLU.AngelWhisper or RDM.Verraise: - case SMN.Resurrection when LocalPlayer.ClassJob.RowId is SMN.JobID: + if ((actionID is BLU.AngelWhisper or RDM.Verraise) + || (actionID is SMN.Resurrection && LocalPlayer.ClassJob.RowId is SMN.JobID)) { if (HasEffect(Buffs.Swiftcast) || HasEffect(RDM.Buffs.Dualcast)) return actionID; - if (IsOffCooldown(Swiftcast)) return Swiftcast; - if (LocalPlayer.ClassJob.RowId is RDM.JobID && ActionReady(RDM.Vercure)) return RDM.Vercure; - - break; } - } - return actionID; + return actionID; + } } - } - //Melee DPS Features - internal class ALL_Melee_Feint : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_Feint; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + //Melee DPS Features + internal class ALL_Melee_Feint : CustomCombo { - return actionID is Feint && TargetHasEffectAny(Debuffs.Feint) && IsOffCooldown(Feint) - ? OriginalHook(11) - : actionID; - } - } + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_Feint; - internal class ALL_Melee_TrueNorth : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_TrueNorth; + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is Feint) + { + if (TargetHasEffectAny(Debuffs.Feint) && IsOffCooldown(Feint)) + return OriginalHook(11); + } - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - return actionID is TrueNorth && HasEffect(Buffs.TrueNorth) - ? OriginalHook(11) - : actionID; + return actionID; + } } - } - //Ranged Physical Features - internal class ALL_Ranged_Mitigation : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Mitigation; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + internal class ALL_Melee_TrueNorth : CustomCombo { - return actionID is BRD.Troubadour or MCH.Tactician or DNC.ShieldSamba && - (HasEffectAny(BRD.Buffs.Troubadour) || HasEffectAny(MCH.Buffs.Tactician) || - HasEffectAny(DNC.Buffs.ShieldSamba)) && IsOffCooldown(actionID) - ? OriginalHook(11) - : actionID; + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Melee_TrueNorth; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is TrueNorth) + { + if (HasEffect(Buffs.TrueNorth)) + return OriginalHook(11); + } + + return actionID; + } } - } - internal class ALL_Ranged_Interrupt : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Interrupt; + //Ranged Physical Features + internal class ALL_Ranged_Mitigation : CustomCombo + { + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Mitigation; - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + if (actionID is BRD.Troubadour or MCH.Tactician or DNC.ShieldSamba) + { + if ((HasEffectAny(BRD.Buffs.Troubadour) || HasEffectAny(MCH.Buffs.Tactician) || HasEffectAny(DNC.Buffs.ShieldSamba)) && IsOffCooldown(actionID)) + return OriginalHook(11); + } + + return actionID; + } + } + + internal class ALL_Ranged_Interrupt : CustomCombo { - return actionID is FootGraze && CanInterruptEnemy() && ActionReady(HeadGraze) - ? HeadGraze - : actionID; + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.ALL_Ranged_Interrupt; + + protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) + { + return (actionID is FootGraze && CanInterruptEnemy() && ActionReady(HeadGraze)) ? HeadGraze : actionID; + } } } -} \ No newline at end of file +} + diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs index bba6f5a3d..c0c939ab7 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs @@ -1,155 +1,22 @@ -using System; using System.Collections.Generic; -using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; +using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; +using static XIVSlothCombo.Combos.JobHelpers.BLM; namespace XIVSlothCombo.Combos.PvE; -internal partial class BLM +internal static partial class BLM { - public const byte ClassID = 7; - public const byte JobID = 25; - - public const uint - Fire = 141, - Blizzard = 142, - Thunder = 144, - Fire2 = 147, - Transpose = 149, - Fire3 = 152, - Thunder3 = 153, - Blizzard3 = 154, - AetherialManipulation = 155, - Scathe = 156, - Manafont = 158, - Freeze = 159, - Flare = 162, - LeyLines = 3573, - Blizzard4 = 3576, - Fire4 = 3577, - BetweenTheLines = 7419, - Thunder4 = 7420, - Triplecast = 7421, - Foul = 7422, - Thunder2 = 7447, - Despair = 16505, - UmbralSoul = 16506, - Xenoglossy = 16507, - Blizzard2 = 25793, - HighFire2 = 25794, - HighBlizzard2 = 25795, - Amplifier = 25796, - Paradox = 25797, - HighThunder = 36986, - HighThunder2 = 36987, - FlareStar = 36989; - - internal static BLMOpenerLogic BLMOpener = new(); - - // Debuff Pairs of Actions and Debuff - public static readonly Dictionary - ThunderList = new() - { - { Thunder, Debuffs.Thunder }, - { Thunder2, Debuffs.Thunder2 }, - { Thunder3, Debuffs.Thunder3 }, - { Thunder4, Debuffs.Thunder4 }, - { HighThunder, Debuffs.HighThunder }, - { HighThunder2, Debuffs.HighThunder2 } - }; - - protected static int nextMpGain => Gauge.UmbralIceStacks switch - { - 0 => 0, - 1 => 2500, - 2 => 5000, - 3 => 10000, - var _ => 0 - }; - - public static class Buffs - { - public const ushort - Thundercloud = 164, - Firestarter = 165, - LeyLines = 737, - CircleOfPower = 738, - Sharpcast = 867, - Triplecast = 1211, - Thunderhead = 3870; - } - - public static class Debuffs - { - public const ushort - Thunder = 161, - Thunder2 = 162, - Thunder3 = 163, - Thunder4 = 1210, - HighThunder = 3871, - HighThunder2 = 3872; - } - - public static class Traits - { - public const uint - UmbralHeart = 295, - EnhancedPolyglot = 297, - AspectMasteryIII = 459, - EnhancedFoul = 461, - EnhancedManafont = 463, - Enochian = 460, - EnhancedPolyglotII = 615; - } - - public static class MP - { - public const int MaxMP = 10000; - - public const int AllMPSpells = 800; //"ALL MP" spell. Only caring about the absolute minimum. - - public static int FireI => GetResourceCost(OriginalHook(Fire)); - - public static int FlareAoE => GetResourceCost(OriginalHook(Flare)); - - public static int FireAoE => GetResourceCost(OriginalHook(Fire2)); - - public static int FireIII => GetResourceCost(OriginalHook(Fire3)); - - public static int BlizzardAoE => GetResourceCost(OriginalHook(Blizzard2)); - - public static int BlizzardI => GetResourceCost(OriginalHook(Blizzard)); - - public static int Freeze => GetResourceCost(OriginalHook(BLM.Freeze)); - - public static int Despair => GetResourceCost(OriginalHook(BLM.Despair)); - } - internal class BLM_ST_SimpleMode : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.BLM_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : - TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - bool canWeave = CanSpellWeave(ActionWatching.LastSpell); - - float elementTimer = Gauge.ElementTimeRemaining / 1000f; - double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); - - int remainingPolyglotCD = Math.Max(0, - (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); - - Status? thunderDebuffST = - FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); - - uint curMp = LocalPlayer.CurrentMp; - if (actionID is not Fire) return actionID; @@ -173,8 +40,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim remainingPolyglotCD >= 20000) return Amplifier; - if (IsEnabled(CustomComboPreset.BLM_ST_LeyLines) && - ActionReady(LeyLines)) + if (ActionReady(LeyLines) && + !HasEffect(Buffs.LeyLines)) return LeyLines; } @@ -324,20 +191,6 @@ internal class BLM_ST_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : - TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - bool canWeave = CanSpellWeave(ActionWatching.LastSpell); - - float elementTimer = Gauge.ElementTimeRemaining / 1000f; - double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); - - int remainingPolyglotCD = Math.Max(0, - (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); - uint curMp = LocalPlayer.CurrentMp; - - Status? thunderDebuffST = - FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); - int PolyglotStacks = Gauge.PolyglotStacks; float TriplecastChargetime = GetCooldownChargeRemainingTime(Triplecast); @@ -367,7 +220,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Amplifier; if (IsEnabled(CustomComboPreset.BLM_ST_LeyLines) && - ActionReady(LeyLines)) + ActionReady(LeyLines) && !HasEffect(Buffs.LeyLines)) return LeyLines; } @@ -401,6 +254,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.BLM_ST_Despair) && curMp < MP.FireI && LevelChecked(Despair) && curMp >= MP.Despair) + return Despair; + + if (IsEnabled(CustomComboPreset.BLM_ST_FlareStar) && + curMp == 0 && LevelChecked(FlareStar) && Gauge.AstralSoulStacks == 6) { if (IsEnabled(CustomComboPreset.BLM_ST_Triplecast) && canWeave && ActionReady(Triplecast) && @@ -414,31 +271,36 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim GetBuffStacks(Buffs.Triplecast) == 0) return All.Swiftcast; - if (IsEnabled(CustomComboPreset.BLM_ST_Thunder) && - HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && - (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) - return OriginalHook(Thunder); - - if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglot) && - (IsEnabled(CustomComboPreset.BLM_ST_Swiftcast) || - IsEnabled(CustomComboPreset.BLM_ST_Triplecast)) && - PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges && gcdsInTimer >= 1 && - (ActionReady(All.Swiftcast) || - (ActionReady(Triplecast) && GetBuffStacks(Buffs.Triplecast) == 0))) - return Xenoglossy.LevelChecked() - ? Xenoglossy - : Foul; - - return Despair; - } - - if (IsEnabled(CustomComboPreset.BLM_ST_Flarestar) && - curMp == 0 && LevelChecked(FlareStar) && Gauge.AstralSoulStacks == 6) return FlareStar; + } if (LevelChecked(Fire4)) if (gcdsInTimer > 1 && curMp >= MP.FireI) + { + if (IsEnabled(CustomComboPreset.BLM_ST_Triplecast) && + canWeave && ActionReady(Triplecast) && + GetBuffStacks(Buffs.Triplecast) == 0 && + (GetRemainingCharges(Triplecast) > Config.BLM_ST_Triplecast_HoldCharges || + TriplecastChargetime <= Config.BLM_ST_Triplecast_ChargeTime)) + return Triplecast; + + if (HasEffect(Buffs.Thunderhead) && gcdsInTimer > 1 && + (thunderDebuffST is null || thunderDebuffST.RemainingTime < 3)) + return OriginalHook(Thunder); + + if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglot) && + PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges && + IsEnabled(CustomComboPreset.BLM_ST_Triplecast) && + canWeave && ActionReady(Triplecast) && + GetBuffStacks(Buffs.Triplecast) == 0 && + (GetRemainingCharges(Triplecast) > Config.BLM_ST_Triplecast_HoldCharges || + TriplecastChargetime <= Config.BLM_ST_Triplecast_ChargeTime)) + return Xenoglossy.LevelChecked() + ? Xenoglossy + : Foul; + return Fire4; + } if (curMp >= MP.FireI) return Fire; @@ -498,7 +360,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Paradox; if (IsEnabled(CustomComboPreset.BLM_ST_UsePolyglot) && - PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges) + PolyglotStacks > Config.BLM_ST_UsePolyglot_HoldCharges && + HasEffect(Buffs.Firestarter) && + GetBuffRemainingTime(Buffs.Firestarter) > 3) return LevelChecked(Xenoglossy) ? Xenoglossy : Foul; @@ -523,7 +387,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Fire3; } - if (LevelChecked(Blizzard3)) + if (Blizzard3.LevelChecked()) return Blizzard3; return actionID; @@ -536,22 +400,6 @@ internal class BLM_AoE_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : - TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - - float elementTimer = Gauge.ElementTimeRemaining / 1000f; - double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); - - int remainingPolyglotCD = Math.Max(0, - (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); - uint curMp = LocalPlayer.CurrentMp; - - Status? thunderDebuffAoE = - FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); - - bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && - IsOffCooldown(All.Swiftcast); - if (actionID is not (Blizzard2 or HighBlizzard2)) return actionID; @@ -585,7 +433,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Foul; } - if (CanSpellWeave(ActionWatching.LastSpell) && ActionReady(LeyLines)) + if (CanSpellWeave(ActionWatching.LastSpell) && + ActionReady(LeyLines) && !HasEffect(Buffs.LeyLines)) return LeyLines; if (Gauge.InAstralFire) @@ -687,22 +536,6 @@ internal class BLM_AoE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : - TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - - float elementTimer = Gauge.ElementTimeRemaining / 1000f; - double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); - - Status? thunderDebuffAoE = - FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); - - int remainingPolyglotCD = Math.Max(0, - (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); - uint curMp = LocalPlayer.CurrentMp; - - bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && - IsOffCooldown(All.Swiftcast); - int PolyglotStacks = Gauge.PolyglotStacks; float TriplecastChargetime = GetCooldownChargeRemainingTime(Triplecast); @@ -745,12 +578,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } if (IsEnabled(CustomComboPreset.BLM_AoE_LeyLines) && - CanSpellWeave(ActionWatching.LastSpell) && ActionReady(LeyLines)) + CanSpellWeave(ActionWatching.LastSpell) && + ActionReady(LeyLines) && !HasEffect(Buffs.LeyLines)) return LeyLines; if (Gauge.InAstralFire) { - if (IsEnabled(CustomComboPreset.BLM_AoE_Flarestar) && + if (IsEnabled(CustomComboPreset.BLM_AoE_FlareStar) && curMp == 0 && FlareStar.LevelChecked() && Gauge.AstralSoulStacks == 6) return FlareStar; @@ -957,4 +791,124 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim : actionID; } } + + #region ID's + + public const byte ClassID = 7; + public const byte JobID = 25; + + public const uint + Fire = 141, + Blizzard = 142, + Thunder = 144, + Fire2 = 147, + Transpose = 149, + Fire3 = 152, + Thunder3 = 153, + Blizzard3 = 154, + AetherialManipulation = 155, + Scathe = 156, + Manafont = 158, + Freeze = 159, + Flare = 162, + LeyLines = 3573, + Blizzard4 = 3576, + Fire4 = 3577, + BetweenTheLines = 7419, + Thunder4 = 7420, + Triplecast = 7421, + Foul = 7422, + Thunder2 = 7447, + Despair = 16505, + UmbralSoul = 16506, + Xenoglossy = 16507, + Blizzard2 = 25793, + HighFire2 = 25794, + HighBlizzard2 = 25795, + Amplifier = 25796, + Paradox = 25797, + HighThunder = 36986, + HighThunder2 = 36987, + FlareStar = 36989; + + // Debuff Pairs of Actions and Debuff + public static readonly Dictionary + ThunderList = new() + { + { Thunder, Debuffs.Thunder }, + { Thunder2, Debuffs.Thunder2 }, + { Thunder3, Debuffs.Thunder3 }, + { Thunder4, Debuffs.Thunder4 }, + { HighThunder, Debuffs.HighThunder }, + { HighThunder2, Debuffs.HighThunder2 } + }; + + static int nextMpGain => Gauge.UmbralIceStacks switch + { + 0 => 0, + 1 => 2500, + 2 => 5000, + 3 => 10000, + var _ => 0 + }; + + public static class Buffs + { + public const ushort + Thundercloud = 164, + Firestarter = 165, + LeyLines = 737, + CircleOfPower = 738, + Sharpcast = 867, + Triplecast = 1211, + Thunderhead = 3870; + } + + public static class Debuffs + { + public const ushort + Thunder = 161, + Thunder2 = 162, + Thunder3 = 163, + Thunder4 = 1210, + HighThunder = 3871, + HighThunder2 = 3872; + } + + public static class Traits + { + public const uint + UmbralHeart = 295, + EnhancedPolyglot = 297, + AspectMasteryIII = 459, + EnhancedFoul = 461, + EnhancedManafont = 463, + Enochian = 460, + EnhancedPolyglotII = 615; + } + + public static class MP + { + public const int MaxMP = 10000; + + public const int AllMPSpells = 800; //"ALL MP" spell. Only caring about the absolute minimum. + + public static int FireI => GetResourceCost(OriginalHook(Fire)); + + public static int FlareAoE => GetResourceCost(OriginalHook(Flare)); + + public static int FireAoE => GetResourceCost(OriginalHook(Fire2)); + + public static int FireIII => GetResourceCost(OriginalHook(Fire3)); + + public static int BlizzardAoE => GetResourceCost(OriginalHook(Blizzard2)); + + public static int BlizzardI => GetResourceCost(OriginalHook(Blizzard)); + + public static int Freeze => GetResourceCost(OriginalHook(BLM.Freeze)); + + public static int Despair => GetResourceCost(OriginalHook(BLM.Despair)); + } + + #endregion } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs index dcb02d124..63b4d17d5 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM_Config.cs @@ -8,16 +8,16 @@ internal partial class BLM internal static class Config { public static UserInt - BLM_VariantCure = new("BLM_VariantCure"), - BLM_VariantRampart = new("BLM_VariantRampart"), - BLM_ST_Triplecast_HoldCharges = new("BLM_ST_Triplecast_HoldCharges", 0), - BLM_ST_UsePolyglot_HoldCharges = new("BLM_ST_UsePolyglot_HoldCharges", 1), - BLM_ST_UsePolyglotMoving_HoldCharges = new("BLM_ST_UsePolyglotMoving_HoldCharges", 0), - BLM_ST_ThunderHP = new("BHP", 0), - BLM_AoE_Triplecast_HoldCharges = new("BLM_AoE_Triplecast_HoldCharges", 0), - BLM_AoE_UsePolyglot_HoldCharges = new("BLM_AoE_UsePolyglot_HoldCharges", 1), - BLM_AoE_UsePolyglotMoving_HoldCharges = new("BLM_AoE_UsePolyglotMoving_HoldCharges", 0), - BLM_AoE_ThunderHP = new("BLM_AoE_ThunderHP", 5); + BLM_VariantCure = new("BLM_VariantCure"), + BLM_VariantRampart = new("BLM_VariantRampart"), + BLM_ST_Triplecast_HoldCharges = new("BLM_ST_Triplecast_HoldCharges", 0), + BLM_ST_UsePolyglot_HoldCharges = new("BLM_ST_UsePolyglot_HoldCharges", 1), + BLM_ST_UsePolyglotMoving_HoldCharges = new("BLM_ST_UsePolyglotMoving_HoldCharges", 0), + BLM_ST_ThunderHP = new("BHP", 0), + BLM_AoE_Triplecast_HoldCharges = new("BLM_AoE_Triplecast_HoldCharges", 0), + BLM_AoE_UsePolyglot_HoldCharges = new("BLM_AoE_UsePolyglot_HoldCharges", 1), + BLM_AoE_UsePolyglotMoving_HoldCharges = new("BLM_AoE_UsePolyglotMoving_HoldCharges", 0), + BLM_AoE_ThunderHP = new("BLM_AoE_ThunderHP", 5); public static UserFloat BLM_ST_Triplecast_ChargeTime = new("BLM_ST_Triplecast_ChargeTime", 20), diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs index d32191059..ce2ad5050 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs @@ -2,19 +2,43 @@ using System.Collections.Generic; using System.Linq; using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Statuses; using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.BLM; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE; +namespace XIVSlothCombo.Combos.JobHelpers; -internal partial class BLM +internal class BLM { // BLM Gauge & Extensions - public static BLMGauge Gauge => GetJobGauge(); + public static BLMGauge Gauge = GetJobGauge(); + public static int Fire4Count = ActionWatching.CombatActions.Count(x => x == Fire4); - public static int Fire4Count => ActionWatching.CombatActions.Count(x => x == Fire4); + public static int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; + + public static bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + public static float elementTimer = Gauge.ElementTimeRemaining / 1000f; + public static double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + + public static int remainingPolyglotCD = Math.Max(0, + (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); + + public static Status? thunderDebuffST = + FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); + + public static Status? thunderDebuffAoE = + FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); + + public static bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && + IsOffCooldown(All.Swiftcast); + + public static uint curMp = LocalPlayer.CurrentMp; + public static BLMOpenerLogic BLMOpener = new(); public static bool HasPolyglotStacks(BLMGauge gauge) => gauge.PolyglotStacks > 0; @@ -125,7 +149,7 @@ private bool DoOpener(ref uint actionID) if (WasLastAction(Triplecast) && OpenerStep == 7) OpenerStep++; else if (OpenerStep == 7) actionID = Triplecast; - if ((WasLastAction(LeyLines) || IsOnCooldown(LeyLines)) && OpenerStep == 8) OpenerStep++; + if (HasEffect(Buffs.LeyLines) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = LeyLines; if (WasLastAction(Fire4) && Fire4Count is 3 && OpenerStep == 9) OpenerStep++; @@ -140,11 +164,11 @@ private bool DoOpener(ref uint actionID) if (WasLastAction(Manafont) && OpenerStep == 12) OpenerStep++; else if (OpenerStep == 12) actionID = Manafont; - if (WasLastAction(Triplecast) && OpenerStep == 13) OpenerStep++; - else if (OpenerStep == 13) actionID = Triplecast; + if (WasLastAction(Fire4) && Fire4Count is 5 && OpenerStep == 13) OpenerStep++; + else if (OpenerStep == 13) actionID = Fire4; - if (WasLastAction(Fire4) && Fire4Count is 5 && OpenerStep == 14) OpenerStep++; - else if (OpenerStep == 14) actionID = Fire4; + if (WasLastAction(Triplecast) && OpenerStep == 14) OpenerStep++; + else if (OpenerStep == 14) actionID = Triplecast; if (WasLastAction(Fire4) && Fire4Count is 6 && OpenerStep == 15) OpenerStep++; else if (OpenerStep == 15) actionID = Fire4; @@ -181,7 +205,7 @@ private bool DoOpener(ref uint actionID) (actionID == LeyLines && IsOnCooldown(LeyLines)) || (actionID == Manafont && IsOnCooldown(Manafont)) || (actionID == All.Swiftcast && IsOnCooldown(All.Swiftcast)) || - (actionID == Xenoglossy && Gauge.PolyglotStacks == 0)) && + (actionID == Xenoglossy && !HasPolyglotStacks(Gauge))) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { CurrentState = OpenerState.FailedOpener; @@ -235,13 +259,12 @@ public static float MPAfterCast() 1 => 2500, 2 => 5000, 3 => 10000, - _ => 0 + var _ => 0 }; - if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - return Math.Max(LocalPlayer.MaxMp, LocalPlayer.CurrentMp + nextMpGain); - - return Math.Max(0, LocalPlayer.CurrentMp - GetResourceCost(castedSpell)); + return castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2 + ? Math.Max(LocalPlayer.MaxMp, LocalPlayer.CurrentMp + nextMpGain) + : Math.Max(0, LocalPlayer.CurrentMp - GetResourceCost(castedSpell)); } public static bool DoubleBlizz() @@ -254,20 +277,28 @@ public static bool DoubleBlizz() uint firstSpell = spells[^1]; - if (firstSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) + switch (firstSpell) { - uint castedSpell = LocalPlayer.CastActionId; + case Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2: + { + uint castedSpell = LocalPlayer.CastActionId; - if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - return true; + if (castedSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) + return true; - if (spells.Count >= 2) - { - uint secondSpell = spells[^2]; + if (spells.Count >= 2) + { + uint secondSpell = spells[^2]; - if (secondSpell is Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2) - return true; - } + switch (secondSpell) + { + case Blizzard or Blizzard2 or Blizzard3 or Blizzard4 or Freeze or HighBlizzard2: + return true; + } + } + + break; + } } return false; From 8e502975031679cf657fabcf1fd9e91102fc0edc Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 14:05:21 +0000 Subject: [PATCH 201/208] BRD merge --- XIVSlothCombo/Combos/PvE/BRD/BRD.cs | 98 ++++++++++++++--------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD/BRD.cs index 50da4bbf1..446b433a5 100644 --- a/XIVSlothCombo/Combos/PvE/BRD/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD/BRD.cs @@ -73,7 +73,7 @@ public const ushort CausticBite = 1200, Stormbite = 1201; } - + internal static class Traits { internal const ushort @@ -94,7 +94,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (actionID is HeavyShot or BurstShot) { - + if (IsEnabled(CustomComboPreset.BRD_DoTMaintainance)) { bool venomous = TargetHasEffect(Debuffs.VenomousBite); @@ -120,14 +120,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } if (IsEnabled(CustomComboPreset.BRD_ApexST)) - { - BRDGauge? gauge = GetJobGauge(); + { + BRDGauge? gauge = GetJobGauge(); - if (LevelChecked(ApexArrow) && gauge.SoulVoice == 100) - return ApexArrow; - if (LevelChecked(BlastArrow) && HasEffect(Buffs.BlastArrowReady)) - return BlastArrow; - } + if (LevelChecked(ApexArrow) && gauge.SoulVoice == 100) + return ApexArrow; + if (LevelChecked(BlastArrow) && HasEffect(Buffs.BlastArrowReady)) + return BlastArrow; + } if (HasEffect(Buffs.HawksEye) || HasEffect(Buffs.Barrage)) return OriginalHook(StraightShot); @@ -145,7 +145,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (actionID is IronJaws) { - + if (!LevelChecked(IronJaws)) { Status? venomous = FindTargetEffect(Debuffs.VenomousBite); @@ -267,7 +267,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return actionID; } - } + } internal class BRD_AoE_oGCD : CustomCombo { @@ -278,7 +278,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is RainOfDeath) { BRDGauge? gauge = GetJobGauge(); - bool songWanderer = gauge.Song == Song.WANDERER; + bool songWanderer = gauge.Song == Song.WANDERER; if (LevelChecked(WanderersMinuet) && songWanderer && gauge.Repertoire == 3) return OriginalHook(WanderersMinuet); @@ -331,7 +331,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Limit optimisation to when you are high enough level to benefit from it. if (LevelChecked(WanderersMinuet)) - { + { if (canWeave) { if (songNone) @@ -410,7 +410,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } - + if (canWeave && IsEnabled(CustomComboPreset.BRD_AoE_Adv_oGCD)) { @@ -427,17 +427,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(PitchPerfect); if (ActionReady(Sidewinder)) - { + { if (songWanderer) { if ((HasEffect(Buffs.RagingStrikes) || ragingCD > 10) && (HasEffect(Buffs.BattleVoice) || battleVoiceCD > 10) && (HasEffect(Buffs.RadiantFinale) || radiantCD > 10 || !LevelChecked(RadiantFinale))) - return Sidewinder; + return Sidewinder; } else return Sidewinder; - + } @@ -514,8 +514,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool songWanderer = gauge.Song == Song.WANDERER; bool minuetReady = LevelChecked(WanderersMinuet) && IsOffCooldown(WanderersMinuet); bool balladReady = LevelChecked(MagesBallad) && IsOffCooldown(MagesBallad); - bool paeonReady = LevelChecked(ArmysPaeon) && IsOffCooldown(ArmysPaeon); - + bool paeonReady = LevelChecked(ArmysPaeon) && IsOffCooldown(ArmysPaeon); + if (gauge.SongTimer < 1 || songArmy) { if (minuetReady) @@ -534,7 +534,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return Sidewinder; if (ActionReady(Bloodletter)) return OriginalHook(Bloodletter); - + } return actionID; @@ -599,7 +599,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { openerFinished = false; } - + if (IsEnabled(CustomComboPreset.BRD_Adv_Interrupt) && canInterrupt) return All.HeadGraze; @@ -623,7 +623,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool minuetReady = IsOffCooldown(WanderersMinuet); bool balladReady = IsOffCooldown(MagesBallad); bool paeonReady = IsOffCooldown(ArmysPaeon); - + if (ActionReady(EmpyrealArrow) && JustUsed(WanderersMinuet)) return EmpyrealArrow; @@ -689,30 +689,30 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim bool barrageReady = LevelChecked(Barrage) && IsOffCooldown(Barrage); float battleVoiceCD = GetCooldownRemainingTime(BattleVoice); float ragingCD = GetCooldownRemainingTime(RagingStrikes); - + if (canWeaveDelayed && IsEnabled(CustomComboPreset.BRD_Adv_BuffsRadiant) && radiantReady && (Array.TrueForAll(gauge.Coda, SongIsNotNone) || Array.Exists(gauge.Coda, SongIsWandererMinuet)) && (battleVoiceCD < 3 || ActionReady(BattleVoice)) && (ragingCD < 3 || ActionReady(RagingStrikes))) return RadiantFinale; - + if (canWeaveBuffs && battleVoiceReady && (HasEffect(Buffs.RadiantFinale) || !LevelChecked(RadiantFinale))) return BattleVoice; if (canWeaveBuffs && ragingReady && (HasEffect(Buffs.RadiantFinale) || !LevelChecked(RadiantFinale))) return RagingStrikes; - + //removed requirement to not have hawks eye, it is better to maybe lose 60 potency than allow it to drift a 1000 potency gain out of the window if (canWeaveBuffs && barrageReady && HasEffect(Buffs.RagingStrikes)) - { + { if (LevelChecked(RadiantFinale) && HasEffect(Buffs.RadiantFinale)) return Barrage; else if (LevelChecked(BattleVoice) && HasEffect(Buffs.BattleVoice)) return Barrage; else if (!LevelChecked(BattleVoice) && HasEffect(Buffs.RagingStrikes)) return Barrage; - } - } - + } + } + if (canWeave && IsEnabled(CustomComboPreset.BRD_ST_Adv_oGCD)) { float battleVoiceCD = GetCooldownRemainingTime(BattleVoice); @@ -806,21 +806,21 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim DotRecast windRecast = delegate (int duration) { return (windbite && windRemaining < duration) || (stormbite && stormRemaining < duration); - }; - + }; + if (IsEnabled(CustomComboPreset.BRD_Adv_DoT)) { - if (ActionReady(IronJaws) && IsEnabled(CustomComboPreset.BRD_Adv_RagingJaws) && HasEffect(Buffs.RagingStrikes) && - !WasLastAction(IronJaws) && ragingStrikesDuration < ragingJawsRenewTime && poisonRecast(35) && windRecast(35)) - { - openerFinished = true; - return IronJaws; + if (ActionReady(IronJaws) && IsEnabled(CustomComboPreset.BRD_Adv_RagingJaws) && HasEffect(Buffs.RagingStrikes) && + !WasLastAction(IronJaws) && ragingStrikesDuration < ragingJawsRenewTime && poisonRecast(35) && windRecast(35)) + { + openerFinished = true; + return IronJaws; } if (LevelChecked(Stormbite) && !stormbite) return Stormbite; if (LevelChecked(CausticBite) && !caustic) - return CausticBite; + return CausticBite; if (LevelChecked(Windbite) && !windbite && !LevelChecked(Stormbite)) return Windbite; if (LevelChecked(VenomousBite) && !venomous && !LevelChecked(CausticBite)) @@ -844,7 +844,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim openerFinished = true; return VenomousBite; } - } + } } } @@ -906,7 +906,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { // Doesn't display the lowest cooldown song if they have been used out of order and are all on cooldown. BRDGauge? gauge = GetJobGauge(); - int songTimerInSeconds = gauge.SongTimer / 1000; + int songTimerInSeconds = gauge.SongTimer / 1000; if (ActionReady(WanderersMinuet) || (gauge.Song == Song.WANDERER && songTimerInSeconds > 11)) return WanderersMinuet; @@ -918,7 +918,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return ArmysPaeon; } - + return actionID; } } @@ -1098,10 +1098,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(RadiantEncore); // healing - please move if not appropriate priority - + if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.SecondWind)) return All.SecondWind; - + } bool wideVolleyReady = LevelChecked(WideVolley) && (HasEffect(Buffs.HawksEye) || HasEffect(Buffs.Barrage)); @@ -1282,7 +1282,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(PitchPerfect); if (ActionReady(Sidewinder)) - { + { if (songWanderer) { if ((HasEffect(Buffs.RagingStrikes) || ragingCD > 10) && @@ -1291,7 +1291,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !LevelChecked(RadiantFinale))) return Sidewinder; } - else return Sidewinder; + else return Sidewinder; } @@ -1324,10 +1324,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } // healing - please move if not appropriate priority - + if (PlayerHealthPercentageHp() <= 40 && ActionReady(All.SecondWind)) - return All.SecondWind; - + return All.SecondWind; + } //Moved below weaves bc roobert says it is blocking his weaves from happening @@ -1393,11 +1393,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return VenomousBite; } } - + } if (LevelChecked(BlastArrow) && HasEffect(Buffs.BlastArrowReady)) - return BlastArrow; + return BlastArrow; if (LevelChecked(ApexArrow)) { From 4bb829a2fca5fa6b1114017a92e7564904a9bee4 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 14:07:51 +0000 Subject: [PATCH 202/208] Merge BRD for real this time --- XIVSlothCombo/Combos/PvE/BRD/BRD.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BRD/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD/BRD.cs index 446b433a5..8482f5ad7 100644 --- a/XIVSlothCombo/Combos/PvE/BRD/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD/BRD.cs @@ -441,7 +441,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } - if (LevelChecked(RainOfDeath) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) + if (LevelChecked(RainOfDeath) && !WasLastAction(RainOfDeath) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) { uint rainOfDeathCharges = LevelChecked(RainOfDeath) ? GetRemainingCharges(RainOfDeath) : 0; @@ -745,7 +745,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } - if (ActionReady(Bloodletter) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) + if (ActionReady(Bloodletter) && !(WasLastAction(Bloodletter) || WasLastAction(HeartbreakShot)) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) { uint bloodletterCharges = GetRemainingCharges(Bloodletter); @@ -1066,7 +1066,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim else return Sidewinder; } - if (LevelChecked(RainOfDeath) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) + if (LevelChecked(RainOfDeath) && !WasLastAction(RainOfDeath) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) { uint rainOfDeathCharges = LevelChecked(RainOfDeath) ? GetRemainingCharges(RainOfDeath) : 0; @@ -1295,7 +1295,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } - if (ActionReady(Bloodletter) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) + if (ActionReady(Bloodletter) && !(WasLastAction(Bloodletter) || WasLastAction(HeartbreakShot)) && (empyrealCD > 1 || !LevelChecked(EmpyrealArrow))) { uint bloodletterCharges = GetRemainingCharges(Bloodletter); From a44e1c0d8f8627beb8354c533ef3a98983ac5261 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 15:00:25 +0000 Subject: [PATCH 203/208] Reattach Autorot to BLM --- XIVSlothCombo/Combos/CustomComboPreset.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 5a2e6baa6..89ba8a1f9 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -368,12 +368,13 @@ public enum CustomComboPreset #region BLACK MAGE + [AutoAction(false, false)] [ReplaceSkill(BLM.Fire)] [ConflictingCombos(BLM_ST_AdvancedMode)] [CustomComboInfo("Simple Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID)] BLM_ST_SimpleMode = 2001, - + [AutoAction(true, false)] [ReplaceSkill(BLM.Blizzard2, BLM.HighBlizzard2)] [ConflictingCombos(BLM_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThis is the ideal option for newcomers to the job.", BLM.JobID)] @@ -381,6 +382,7 @@ public enum CustomComboPreset #region Single Target - Advanced + [AutoAction(false, false)] [ReplaceSkill(BLM.Fire)] [ConflictingCombos(BLM_ST_SimpleMode)] [CustomComboInfo("Advanced Mode - Single Target", "Replaces Fire with a full one-button single target rotation.\nThese features are ideal if you want to customize the rotation.", BLM.JobID)] @@ -438,6 +440,7 @@ public enum CustomComboPreset #region AoE - Advanced + [AutoAction(true, false)] [ReplaceSkill(BLM.Fire)] [ConflictingCombos(BLM_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Blizzard II with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", BLM.JobID)] From 10a5797ffbe76782d39ae5393dbccf84e1dabd46 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 17:17:02 +0000 Subject: [PATCH 204/208] More merges --- XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs | 29 ++-- XIVSlothCombo/Combos/PvE/DRG/DRG.cs | 53 +++---- XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs | 120 ++++++++-------- XIVSlothCombo/Combos/PvE/DRK/DRK.cs | 14 +- XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs | 10 +- XIVSlothCombo/Combos/PvE/MCH/MCH.cs | 60 ++------ XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs | 41 ++++-- XIVSlothCombo/Combos/PvE/SMN/SMN.cs | 155 +++++++++++---------- 8 files changed, 228 insertions(+), 254 deletions(-) diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs index ce2ad5050..d8c38c899 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM_Helper.cs @@ -16,29 +16,32 @@ internal class BLM { // BLM Gauge & Extensions public static BLMGauge Gauge = GetJobGauge(); - public static int Fire4Count = ActionWatching.CombatActions.Count(x => x == Fire4); - public static int maxPolyglot = TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : + public static bool canWeave = CanSpellWeave(ActionWatching.LastSpell); + + public static uint curMp = LocalPlayer.CurrentMp; + public static BLMOpenerLogic BLMOpener = new(); + + public static int maxPolyglot => TraitLevelChecked(Traits.EnhancedPolyglotII) ? 3 : TraitLevelChecked(Traits.EnhancedPolyglot) ? 2 : 1; - public static bool canWeave = CanSpellWeave(ActionWatching.LastSpell); - public static float elementTimer = Gauge.ElementTimeRemaining / 1000f; - public static double gcdsInTimer = Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + public static int Fire4Count => ActionWatching.CombatActions.Count(x => x == Fire4); - public static int remainingPolyglotCD = Math.Max(0, + public static float elementTimer => Gauge.ElementTimeRemaining / 1000f; + + public static double gcdsInTimer => Math.Floor(elementTimer / GetActionCastTime(ActionWatching.LastSpell)); + + public static int remainingPolyglotCD => Math.Max(0, (maxPolyglot - Gauge.PolyglotStacks) * 30000 + (Gauge.EnochianTimer - 30000)); - public static Status? thunderDebuffST = + public static Status? thunderDebuffST => FindEffect(ThunderList[OriginalHook(Thunder)], CurrentTarget, LocalPlayer.GameObjectId); - public static Status? thunderDebuffAoE = + public static Status? thunderDebuffAoE => FindEffect(ThunderList[OriginalHook(Thunder2)], CurrentTarget, LocalPlayer.GameObjectId); - public static bool canSwiftF = TraitLevelChecked(Traits.AspectMasteryIII) && - IsOffCooldown(All.Swiftcast); - - public static uint curMp = LocalPlayer.CurrentMp; - public static BLMOpenerLogic BLMOpener = new(); + public static bool canSwiftF => TraitLevelChecked(Traits.AspectMasteryIII) && + IsOffCooldown(All.Swiftcast); public static bool HasPolyglotStacks(BLMGauge gauge) => gauge.PolyglotStacks > 0; diff --git a/XIVSlothCombo/Combos/PvE/DRG/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG.cs index b873c97b6..3fee40aa3 100644 --- a/XIVSlothCombo/Combos/PvE/DRG/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG.cs @@ -3,6 +3,7 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Extensions; +using static XIVSlothCombo.Combos.JobHelpers.DRG; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; @@ -79,21 +80,10 @@ public const uint internal class DRG_ST_SimpleMode : CustomCombo { - internal static DRGOpenerLogic DRGOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - Status? ChaosDoTDebuff; - - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth); - - if (LevelChecked(ChaoticSpring)) - ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaoticSpring); - else ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaosThrust); - if (actionID is TrueThrust) { if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && @@ -133,11 +123,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (ActionReady(LifeSurge) && (GetCooldownRemainingTime(LifeSurge) < 40 || GetCooldownRemainingTime(BattleLitany) > 50) && AnimationLock.CanDRGWeave(LifeSurge) && - HasEffect(Buffs.LanceCharge) && - !HasEffect(Buffs.LifeSurge) && - ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || - (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || - (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) + ((HasEffect(Buffs.LanceCharge) && + !HasEffect(Buffs.LifeSurge) && + ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || + (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || + (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) || + (!LevelChecked(LanceCharge) && JustUsed(VorpalThrust)))) return LifeSurge; //Geirskogul Feature @@ -248,21 +239,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim internal class DRG_ST_AdvancedMode : CustomCombo { - internal static DRGOpenerLogic DRGOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.DRG_ST_AdvancedMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - Status? ChaosDoTDebuff; - - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth); - - if (LevelChecked(ChaoticSpring)) - ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaoticSpring); - else ChaosDoTDebuff = FindTargetEffect(Debuffs.ChaosThrust); - if (actionID is TrueThrust) { if (IsEnabled(CustomComboPreset.DRG_Variant_Cure) && @@ -312,11 +292,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim ActionReady(LifeSurge) && (GetCooldownRemainingTime(LifeSurge) < 40 || GetCooldownRemainingTime(BattleLitany) > 50) && AnimationLock.CanDRGWeave(LifeSurge) && - HasEffect(Buffs.LanceCharge) && - !HasEffect(Buffs.LifeSurge) && - ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || - (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || - (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) + ((HasEffect(Buffs.LanceCharge) && + !HasEffect(Buffs.LifeSurge) && + ((JustUsed(WheelingThrust) && LevelChecked(Drakesbane)) || + (JustUsed(FangAndClaw) && LevelChecked(Drakesbane)) || + (JustUsed(OriginalHook(VorpalThrust)) && LevelChecked(FullThrust)))) || + (!LevelChecked(LanceCharge) && JustUsed(VorpalThrust)))) return LifeSurge; //Geirskogul Feature @@ -752,11 +733,9 @@ internal class DRG_BurstCDFeature : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - if (actionID is LanceCharge) - if (IsOnCooldown(LanceCharge) && ActionReady(BattleLitany)) - return BattleLitany; - - return actionID; + return actionID is LanceCharge && IsOnCooldown(LanceCharge) && ActionReady(BattleLitany) + ? BattleLitany + : actionID; } } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs index 9c6916f4d..21cc869e9 100644 --- a/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG_Helper.cs @@ -1,15 +1,30 @@ using System.Collections.Generic; using System.Linq; +using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Statuses; using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Combos.PvE.Content; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.DRG; +using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE; +namespace XIVSlothCombo.Combos.JobHelpers; -internal partial class DRG +internal class DRG { + // DRG Gauge & Extensions + public static DRGGauge Gauge = GetJobGauge(); + public static DRGOpenerLogic DRGOpener = new(); + + public static Status? ChaosDoTDebuff => FindTargetEffect(LevelChecked(ChaoticSpring) + ? Debuffs.ChaoticSpring + : Debuffs.ChaosThrust); + + public static bool trueNorthReady => TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); + internal class DRGOpenerLogic { private OpenerState currentState = OpenerState.PrePull; @@ -20,7 +35,7 @@ internal class DRGOpenerLogic private static uint OpenerLevel => 100; - public static bool LevelChecked => CustomComboFunctions.LocalPlayer.Level >= OpenerLevel; + public static bool LevelChecked => LocalPlayer.Level >= OpenerLevel; private static bool CanOpener => HasCooldowns() && LevelChecked; @@ -34,7 +49,7 @@ public OpenerState CurrentState if (value == OpenerState.PrePull) Svc.Log.Debug("Entered PrePull Opener"); if (value == OpenerState.InOpener) OpenerStep = 1; - if (value == OpenerState.OpenerFinished || value == OpenerState.FailedOpener) + if (value is OpenerState.OpenerFinished or OpenerState.FailedOpener) { if (value == OpenerState.FailedOpener) Svc.Log.Information($"Opener Failed at step {OpenerStep}"); @@ -50,16 +65,16 @@ public OpenerState CurrentState private static bool HasCooldowns() { - if (CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2) + if (GetRemainingCharges(LifeSurge) < 2) return false; - if (!CustomComboFunctions.ActionReady(BattleLitany)) + if (!ActionReady(BattleLitany)) return false; - if (!CustomComboFunctions.ActionReady(DragonfireDive)) + if (!ActionReady(DragonfireDive)) return false; - if (!CustomComboFunctions.ActionReady(LanceCharge)) + if (!ActionReady(LanceCharge)) return false; return true; @@ -75,11 +90,10 @@ private bool DoPrePullSteps(ref uint actionID) if (CurrentState == OpenerState.PrePull && PrePullStep > 0) { - if (CustomComboFunctions.WasLastAction(TrueThrust) && PrePullStep == 1) - CurrentState = OpenerState.InOpener; + if (WasLastAction(TrueThrust) && PrePullStep == 1) CurrentState = OpenerState.InOpener; else if (PrePullStep == 1) actionID = TrueThrust; - if (ActionWatching.CombatActions.Count > 2 && CustomComboFunctions.InCombat()) + if (ActionWatching.CombatActions.Count > 2 && InCombat()) CurrentState = OpenerState.FailedOpener; return true; @@ -96,92 +110,82 @@ private bool DoOpener(ref uint actionID) if (currentState == OpenerState.InOpener) { - if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 1) OpenerStep++; + if (WasLastAction(SpiralBlow) && OpenerStep == 1) OpenerStep++; else if (OpenerStep == 1) actionID = SpiralBlow; - if (CustomComboFunctions.WasLastAction(LanceCharge) && OpenerStep == 2) OpenerStep++; + if (WasLastAction(LanceCharge) && OpenerStep == 2) OpenerStep++; else if (OpenerStep == 2) actionID = LanceCharge; - if (CustomComboFunctions.WasLastAction(ChaoticSpring) && OpenerStep == 3) OpenerStep++; + if (WasLastAction(ChaoticSpring) && OpenerStep == 3) OpenerStep++; else if (OpenerStep == 3) actionID = ChaoticSpring; - if (CustomComboFunctions.WasLastAction(BattleLitany) && OpenerStep == 4) OpenerStep++; + if (WasLastAction(BattleLitany) && OpenerStep == 4) OpenerStep++; else if (OpenerStep == 4) actionID = BattleLitany; - if (CustomComboFunctions.WasLastAction(Geirskogul) && OpenerStep == 5) OpenerStep++; + if (WasLastAction(Geirskogul) && OpenerStep == 5) OpenerStep++; else if (OpenerStep == 5) actionID = Geirskogul; - if (CustomComboFunctions.WasLastAction(WheelingThrust) && OpenerStep == 6) OpenerStep++; + if (WasLastAction(WheelingThrust) && OpenerStep == 6) OpenerStep++; else if (OpenerStep == 6) actionID = WheelingThrust; - if (CustomComboFunctions.WasLastAction(HighJump) && OpenerStep == 7) OpenerStep++; + if (WasLastAction(HighJump) && OpenerStep == 7) OpenerStep++; else if (OpenerStep == 7) actionID = HighJump; - if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 8) OpenerStep++; + if (WasLastAction(LifeSurge) && OpenerStep == 8) OpenerStep++; else if (OpenerStep == 8) actionID = LifeSurge; - if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 9) OpenerStep++; + if (WasLastAction(Drakesbane) && OpenerStep == 9) OpenerStep++; else if (OpenerStep == 9) actionID = Drakesbane; - if (CustomComboFunctions.WasLastAction(DragonfireDive) && OpenerStep == 10) OpenerStep++; + if (WasLastAction(DragonfireDive) && OpenerStep == 10) OpenerStep++; else if (OpenerStep == 10) actionID = DragonfireDive; - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 11) OpenerStep++; + if (WasLastAction(Nastrond) && OpenerStep == 11) OpenerStep++; else if (OpenerStep == 11) actionID = Nastrond; - if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 12) OpenerStep++; + if (WasLastAction(RaidenThrust) && OpenerStep == 12) OpenerStep++; else if (OpenerStep == 12) actionID = RaidenThrust; - if (CustomComboFunctions.WasLastAction(Stardiver) && OpenerStep == 13) OpenerStep++; + if (WasLastAction(Stardiver) && OpenerStep == 13) OpenerStep++; else if (OpenerStep == 13) actionID = Stardiver; - if (CustomComboFunctions.WasLastAction(LanceBarrage) && OpenerStep == 14) OpenerStep++; + if (WasLastAction(LanceBarrage) && OpenerStep == 14) OpenerStep++; else if (OpenerStep == 14) actionID = LanceBarrage; - if (CustomComboFunctions.WasLastAction(Starcross) && OpenerStep == 15) OpenerStep++; + if (WasLastAction(Starcross) && OpenerStep == 15) OpenerStep++; else if (OpenerStep == 15) actionID = Starcross; - if (CustomComboFunctions.WasLastAction(LifeSurge) && OpenerStep == 16) OpenerStep++; + if (WasLastAction(LifeSurge) && OpenerStep == 16) OpenerStep++; else if (OpenerStep == 16) actionID = LifeSurge; - if (CustomComboFunctions.WasLastAction(HeavensThrust) && OpenerStep == 17) OpenerStep++; + if (WasLastAction(HeavensThrust) && OpenerStep == 17) OpenerStep++; else if (OpenerStep == 17) actionID = HeavensThrust; - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 18) OpenerStep++; - else if (OpenerStep == 18) actionID = Nastrond; + if (WasLastAction(RiseOfTheDragon) && OpenerStep == 18) OpenerStep++; + else if (OpenerStep == 18) actionID = RiseOfTheDragon; - if (CustomComboFunctions.WasLastAction(RiseOfTheDragon) && OpenerStep == 19) OpenerStep++; - else if (OpenerStep == 19) actionID = RiseOfTheDragon; + if (WasLastAction(MirageDive) && OpenerStep == 19) OpenerStep++; + else if (OpenerStep == 19) actionID = MirageDive; - if (CustomComboFunctions.WasLastAction(FangAndClaw) && OpenerStep == 20) OpenerStep++; + if (WasLastAction(FangAndClaw) && OpenerStep == 20) OpenerStep++; else if (OpenerStep == 20) actionID = FangAndClaw; - if (CustomComboFunctions.WasLastAction(Nastrond) && OpenerStep == 21) OpenerStep++; - else if (OpenerStep == 21) actionID = Nastrond; - - if (CustomComboFunctions.WasLastAction(MirageDive) && OpenerStep == 22) OpenerStep++; - else if (OpenerStep == 22) actionID = MirageDive; + if (WasLastAction(Drakesbane) && OpenerStep == 21) OpenerStep++; + else if (OpenerStep == 21) actionID = Drakesbane; - if (CustomComboFunctions.WasLastAction(Drakesbane) && OpenerStep == 23) OpenerStep++; - else if (OpenerStep == 23) actionID = Drakesbane; + if (WasLastAction(RaidenThrust) && OpenerStep == 22) OpenerStep++; + else if (OpenerStep == 22) actionID = RaidenThrust; - if (CustomComboFunctions.WasLastAction(RaidenThrust) && OpenerStep == 24) OpenerStep++; - else if (OpenerStep == 24) actionID = RaidenThrust; - - if (CustomComboFunctions.WasLastAction(WyrmwindThrust) && OpenerStep == 25) OpenerStep++; - else if (OpenerStep == 25) actionID = WyrmwindThrust; - - if (CustomComboFunctions.WasLastAction(SpiralBlow) && OpenerStep == 26) - CurrentState = OpenerState.OpenerFinished; - else if (OpenerStep == 26) actionID = SpiralBlow; + if (WasLastAction(WyrmwindThrust) && OpenerStep == 23) CurrentState = OpenerState.OpenerFinished; + else if (OpenerStep == 23) actionID = WyrmwindThrust; if (ActionWatching.TimeSinceLastAction.TotalSeconds >= 5) CurrentState = OpenerState.FailedOpener; - if (((actionID == DragonfireDive && CustomComboFunctions.IsOnCooldown(DragonfireDive)) || - (actionID == BattleLitany && CustomComboFunctions.IsOnCooldown(BattleLitany)) || - (actionID == LanceCharge && CustomComboFunctions.IsOnCooldown(LanceCharge)) || - (actionID == LifeSurge && CustomComboFunctions.GetRemainingCharges(LifeSurge) < 2)) && + if (((actionID == DragonfireDive && IsOnCooldown(DragonfireDive)) || + (actionID == BattleLitany && IsOnCooldown(BattleLitany)) || + (actionID == LanceCharge && IsOnCooldown(LanceCharge)) || + (actionID == LifeSurge && GetRemainingCharges(LifeSurge) < 2)) && ActionWatching.TimeSinceLastAction.TotalSeconds >= 3) { CurrentState = OpenerState.FailedOpener; @@ -214,7 +218,7 @@ public bool DoFullOpener(ref uint actionID) if (DoOpener(ref actionID)) return true; - if (!CustomComboFunctions.InCombat()) + if (!InCombat()) { ResetOpener(); CurrentState = OpenerState.PrePull; @@ -252,12 +256,12 @@ internal class AnimationLock internal static bool CanDRGWeave(uint oGCD) { + float gcdTimer = GetCooldownRemainingTime(TrueThrust); + //GCD Ready - No Weave - if (CustomComboFunctions.IsOffCooldown(TrueThrust)) + if (IsOffCooldown(TrueThrust)) return false; - float gcdTimer = CustomComboFunctions.GetCooldownRemainingTime(TrueThrust); - if (FastLocks.Any(x => x == oGCD) && gcdTimer >= 0.6f) return true; diff --git a/XIVSlothCombo/Combos/PvE/DRK/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK/DRK.cs index 874a2f712..9dfb5ac09 100644 --- a/XIVSlothCombo/Combos/PvE/DRK/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK/DRK.cs @@ -87,7 +87,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim var gauge = GetJobGauge(); var mpRemaining = Config.DRK_ST_ManaSpenderPooling; - var hpRemaining = Config.DRK_ST_LivingDeadThreshold; + var hpRemainingLiving = Config.DRK_ST_LivingDeadThreshold; + var hpRemainingDelirium = Config.DRK_ST_DeliriumThreshold; // Variant Cure - Heal: Priority to save your life if (IsEnabled(CustomComboPreset.DRK_Variant_Cure) @@ -167,13 +168,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim && IsEnabled(CustomComboPreset.DRK_ST_CDs_LivingShadow) && IsOffCooldown(LivingShadow) && LevelChecked(LivingShadow) - && GetTargetHPPercent() > hpRemaining) + && GetTargetHPPercent() > hpRemainingLiving) return LivingShadow; // Delirium if (IsEnabled(CustomComboPreset.DRK_ST_Delirium) && IsOffCooldown(BloodWeapon) && LevelChecked(BloodWeapon) + && GetTargetHPPercent() > hpRemainingDelirium && ((CombatEngageDuration().TotalSeconds < 8 // Opening Delirium && WasLastWeaponskill(Souleater)) || CombatEngageDuration().TotalSeconds > 8)) // Regular Delirium @@ -286,7 +288,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID != Unleash) return actionID; var gauge = GetJobGauge(); - var hpRemaining = Config.DRK_AoE_LivingDeadThreshold; + var hpRemainingLiving = Config.DRK_AoE_LivingDeadThreshold; + var hpRemainingDelirium = Config.DRK_AoE_DeliriumThreshold; // Variant Cure - Heal: Priority to save your life if (IsEnabled(CustomComboPreset.DRK_Variant_Cure) @@ -329,13 +332,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.DRK_AoE_CDs_LivingShadow) && IsOffCooldown(LivingShadow) && LevelChecked(LivingShadow) - && GetTargetHPPercent() > hpRemaining) + && GetTargetHPPercent() > hpRemainingLiving) return LivingShadow; // Delirium if (IsEnabled(CustomComboPreset.DRK_AoE_Delirium) && IsOffCooldown(BloodWeapon) - && LevelChecked(BloodWeapon)) + && LevelChecked(BloodWeapon) + && GetTargetHPPercent() > hpRemainingDelirium) return OriginalHook(Delirium); if (gauge.DarksideTimeRemaining > 1) diff --git a/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs b/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs index 5f3119db5..32e6db2a3 100644 --- a/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs +++ b/XIVSlothCombo/Combos/PvE/DRK/DRK_Config.cs @@ -9,10 +9,12 @@ internal partial class DRK internal static class Config { public static readonly UserInt - DRK_ST_ManaSpenderPooling = new("DRK_ST_ManaSpenderPooling", 3000), - DRK_ST_LivingDeadThreshold = new("DRK_ST_LivingDeadThreshold", 10), - DRK_AoE_LivingDeadThreshold = new("DRK_AoE_LivingDeadThreshold", 40), - DRK_VariantCure = new("DRKVariantCure"); + DRK_ST_ManaSpenderPooling = new("DRK_ST_ManaSpenderPooling", 3000), + DRK_ST_LivingDeadThreshold = new("DRK_ST_LivingDeadThreshold", 10), + DRK_AoE_LivingDeadThreshold = new("DRK_AoE_LivingDeadThreshold", 40), + DRK_ST_DeliriumThreshold = new("DRK_ST_DeliriumThreshold", 0), + DRK_AoE_DeliriumThreshold = new("DRK_AoE_DeliriumThreshold", 25), + DRK_VariantCure = new("DRKVariantCure"); internal static void Draw(CustomComboPreset preset) { diff --git a/XIVSlothCombo/Combos/PvE/MCH/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs index 9f24faaea..28f94daa9 100644 --- a/XIVSlothCombo/Combos/PvE/MCH/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; @@ -5,6 +6,7 @@ using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; +using static XIVSlothCombo.Combos.JobHelpers.MCH; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; @@ -78,29 +80,10 @@ public const ushort internal class MCH_ST_SimpleMode : CustomCombo { - internal static MCHOpenerLogic MCHOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool interruptReady = ActionReady(All.HeadGraze) && CanInterruptEnemy() && CanDelayedWeave(actionID); - float heatblastRC = GetCooldown(Heatblast).CooldownTotal; - - bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && - GetCooldownRemainingTime(Drill) > heatblastRC * 6) || - (TraitLevelChecked(Traits.EnhancedMultiWeapon) && - GetRemainingCharges(Drill) < GetMaxCharges(Drill) && - GetCooldownRemainingTime(Drill) > heatblastRC * 6); - - bool anchorCD = !LevelChecked(AirAnchor) || - (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); - - bool sawCD = !LevelChecked(Chainsaw) || - (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); - float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - if (actionID is SplitShot or HeatedSplitShot) { if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && @@ -135,7 +118,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return BarrelStabilizer; // Hypercharge - if ((Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + if ((Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHHelper.IsComboExpiring(6) && LevelChecked(Hypercharge) && !Gauge.IsOverheated) { // Ensures Hypercharge is double weaved with WF @@ -153,8 +136,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Queen - if (MCHExtensions.UseQueen(Gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) + if (MCHHelper.UseQueen(Gauge) && + (GetCooldownRemainingTime(Wildfire) > GCD || !LevelChecked(Wildfire))) return OriginalHook(RookAutoturret); // Gauss Round and Ricochet during HC @@ -295,28 +278,10 @@ private static bool ReassembledTools(ref uint actionID, MCHGauge gauge) internal class MCH_ST_AdvancedMode : CustomCombo { - internal static MCHOpenerLogic MCHOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MCH_ST_AdvancedMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool interruptReady = ActionReady(All.HeadGraze) && CanInterruptEnemy() && CanDelayedWeave(actionID); - float heatblastRC = GetCooldown(Heatblast).CooldownTotal; - - bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && - GetCooldownRemainingTime(Drill) > heatblastRC * 6) || - (TraitLevelChecked(Traits.EnhancedMultiWeapon) && - GetRemainingCharges(Drill) < GetMaxCharges(Drill) && - GetCooldownRemainingTime(Drill) > heatblastRC * 6); - - bool anchorCD = !LevelChecked(AirAnchor) || - (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); - - bool sawCD = !LevelChecked(Chainsaw) || - (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); - float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; - bool reassembledExcavator = (IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble) && Config.MCH_ST_Reassembled[0] && (HasEffect(Buffs.Reassembled) || !HasEffect(Buffs.Reassembled))) || @@ -324,7 +289,6 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Reassembled)) || (!HasEffect(Buffs.Reassembled) && GetRemainingCharges(Reassemble) <= Config.MCH_ST_ReassemblePool) || !IsEnabled(CustomComboPreset.MCH_ST_Adv_Reassemble); - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); if (actionID is SplitShot or HeatedSplitShot) { @@ -370,7 +334,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Hypercharge if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Hypercharge) && - (Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHExtensions.IsComboExpiring(6) && + (Gauge.Heat >= 50 || HasEffect(Buffs.Hypercharged)) && !MCHHelper.IsComboExpiring(6) && LevelChecked(Hypercharge) && !Gauge.IsOverheated && GetTargetHPPercent() >= Config.MCH_ST_HyperchargeHP) { @@ -390,8 +354,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Queen if (IsEnabled(CustomComboPreset.MCH_Adv_TurretQueen) && - MCHExtensions.UseQueen(Gauge) && - GetCooldownRemainingTime(Wildfire) > GCD) + MCHHelper.UseQueen(Gauge) && + (GetCooldownRemainingTime(Wildfire) > GCD || !LevelChecked(Wildfire))) return OriginalHook(RookAutoturret); // Gauss Round and Ricochet during HC @@ -432,7 +396,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Full Metal Field if (IsEnabled(CustomComboPreset.MCH_ST_Adv_Stabilizer_FullMetalField) && - HasEffect(Buffs.FullMetalMachinist) && + HasEffect(Buffs.FullMetalMachinist) && (GetCooldownRemainingTime(Wildfire) <= GCD || ActionReady(Wildfire) || GetBuffRemainingTime(Buffs.FullMetalMachinist) <= 6) && LevelChecked(FullMetalField)) @@ -579,8 +543,6 @@ internal class MCH_AoE_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - float GCD = GetCooldown(OriginalHook(SpreadShot)).CooldownTotal; - if (actionID is SpreadShot or Scattergun) { if (IsEnabled(CustomComboPreset.MCH_Variant_Cure) && @@ -668,8 +630,6 @@ internal class MCH_AoE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - float GCD = GetCooldown(OriginalHook(SpreadShot)).CooldownTotal; - bool reassembledScattergun = IsEnabled(CustomComboPreset.MCH_AoE_Adv_Reassemble) && Config.MCH_AoE_Reassembled[0] && HasEffect(Buffs.Reassembled); @@ -789,7 +749,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.MCH_AoE_Adv_Chainsaw) && reassembledChainsaw && - LevelChecked(Chainsaw) && + LevelChecked(Chainsaw) && (GetCooldownRemainingTime(Chainsaw) <= GCD + 0.25 || ActionReady(Chainsaw))) return Chainsaw; diff --git a/XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs index bd8e9f32b..3a4f28851 100644 --- a/XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH_Helper.cs @@ -3,13 +3,39 @@ using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.MCH; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE; +namespace XIVSlothCombo.Combos.JobHelpers; -internal partial class MCH +internal class MCH { + // MCH Gauge & Extensions + public static MCHOpenerLogic MCHOpener = new(); + + public static float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal; + public static float heatblastRC = GetCooldown(Heatblast).CooldownTotal; + public static MCHGauge Gauge = GetJobGauge(); + + public static bool drillCD = !LevelChecked(Drill) || (!TraitLevelChecked(Traits.EnhancedMultiWeapon) && + GetCooldownRemainingTime(Drill) > heatblastRC * 6) || + (TraitLevelChecked(Traits.EnhancedMultiWeapon) && + GetRemainingCharges(Drill) < GetMaxCharges(Drill) && + GetCooldownRemainingTime(Drill) > heatblastRC * 6); + + public static bool anchorCD = !LevelChecked(AirAnchor) || + (LevelChecked(AirAnchor) && GetCooldownRemainingTime(AirAnchor) > heatblastRC * 6); + + public static bool sawCD = !LevelChecked(Chainsaw) || + (LevelChecked(Chainsaw) && GetCooldownRemainingTime(Chainsaw) > heatblastRC * 6); + + public static bool interruptReady => ActionReady(All.HeadGraze) && CanInterruptEnemy() && + CanDelayedWeave(ActionWatching.LastWeaponskill); + + public static int BSUsed => ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); + internal class MCHOpenerLogic { private OpenerState currentState = OpenerState.PrePull; @@ -253,25 +279,20 @@ public bool DoFullOpener(ref uint actionID) } } - internal class MCHExtensions + internal static class MCHHelper { public static unsafe bool IsComboExpiring(float Times) { float GCD = GetCooldown(OriginalHook(SplitShot)).CooldownTotal * Times; - if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) - return true; - - return false; + return ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD; } public static bool UseQueen(MCHGauge gauge) { - int BSUsed = ActionWatching.CombatActions.Count(x => x == BarrelStabilizer); - if (!ActionWatching.HasDoubleWeaved() && !gauge.IsOverheated && !HasEffect(Buffs.Wildfire) && !JustUsed(OriginalHook(Heatblast)) && LevelChecked(OriginalHook(RookAutoturret)) && - !gauge.IsRobotActive && gauge.Battery >= 50) + gauge is { IsRobotActive: false, Battery: >= 50 }) { if (LevelChecked(FullMetalField)) { diff --git a/XIVSlothCombo/Combos/PvE/SMN/SMN.cs b/XIVSlothCombo/Combos/PvE/SMN/SMN.cs index 564b2a24f..a79e4108d 100644 --- a/XIVSlothCombo/Combos/PvE/SMN/SMN.cs +++ b/XIVSlothCombo/Combos/PvE/SMN/SMN.cs @@ -527,7 +527,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } // Emergency priority Demi Nuke to prevent waste if you can't get demi attacks out to satisfy the slider check. - if (OriginalHook(Ruin) is AstralImpulse or UmbralImpulse or FountainOfFire && + if (OriginalHook(Ruin) is AstralImpulse or UmbralImpulse or FountainOfFire && IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_Attacks) && GetCooldown(OriginalHook(Aethercharge)).CooldownElapsed >= 12.5) { if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_Attacks)) @@ -567,7 +567,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim (SummonerBurstPhase is not 4)) || (SummonerBurstPhase == 4 && !HasEffect(Buffs.TitansFavor))) return OriginalHook(Fester); - + } } } @@ -578,7 +578,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Demi Nuke if (OriginalHook(Ruin) is AstralImpulse or UmbralImpulse or FountainOfFire) { - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_Attacks) && IsBahamutReady && (LevelChecked(SummonSolarBahamut) || DemiAttackCount >= burstDelay) + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_Attacks) && IsBahamutReady && (LevelChecked(SummonSolarBahamut) || DemiAttackCount >= burstDelay) && (IsNotEnabled(CustomComboPreset.SMN_SearingLight_Burst) || (LevelChecked(SummonSolarBahamut) || HasEffect(Buffs.SearingLight)))) { if (IsOffCooldown(OriginalHook(EnkindleBahamut)) && LevelChecked(SummonBahamut)) @@ -599,7 +599,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } // Demi Nuke 3: More Boogaloo - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_Attacks) && IsSolarBahamutReady && DemiAttackCount >= burstDelay && + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_Attacks) && IsSolarBahamutReady && DemiAttackCount >= burstDelay && (IsNotEnabled(CustomComboPreset.SMN_SearingLight_Burst) || HasEffect(Buffs.SearingLight))) { if (IsOffCooldown(OriginalHook(EnkindleSolarBahamut)) && LevelChecked(SummonSolarBahamut)) @@ -609,7 +609,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(AstralFlow); } } - + // Lux Solaris if (IsOffCooldown(LuxSolaris) && IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons_LuxSolaris) && HasEffect(Buffs.RefulgentLux) && (PlayerHealthPercentageHp() < 100 || GetBuffRemainingTime(Buffs.RefulgentLux) is < 3 and > 0)) @@ -621,12 +621,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (gauge.HasAetherflowStacks && CanSpellWeave(actionID)) { if (IsNotEnabled(CustomComboPreset.SMN_DemiEgiMenu_oGCDPooling)) - return OriginalHook(Fester); + return OriginalHook(Fester); if (IsEnabled(CustomComboPreset.SMN_DemiEgiMenu_oGCDPooling)) { if (!LevelChecked(SearingLight)) - return OriginalHook(Fester); + return OriginalHook(Fester); if ((((HasEffect(Buffs.SearingLight) && IsNotEnabled(CustomComboPreset.SMN_Advanced_Burst_Any_Option)) || HasEffectAny(Buffs.SearingLight)) && SummonerBurstPhase is 0 or 1 or 2 or 3 && DemiAttackCount >= burstDelay) || @@ -639,49 +639,49 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Lucid Dreaming if (IsEnabled(CustomComboPreset.SMN_Lucid) && ActionReady(All.LucidDreaming) && LocalPlayer.CurrentMp <= lucidThreshold) return All.LucidDreaming; - } - - // Demi - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons)) - { - if (InCombat() && gauge.SummonTimerRemaining == 0 && IsOffCooldown(OriginalHook(Aethercharge)) && - ((LevelChecked(Aethercharge) && !LevelChecked(SummonBahamut)) || // Pre-Bahamut Phase - (IsBahamutReady && LevelChecked(SummonBahamut)) || // Bahamut Phase - (IsPhoenixReady && LevelChecked(SummonPhoenix)) || // Phoenix Phase - (IsSolarBahamutReady && LevelChecked(SummonSolarBahamut)))) // Solar Bahamut Phase - return OriginalHook(Aethercharge); - } - //Ruin4 in Egi Phases - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_Ruin4) && HasEffect(Buffs.FurtherRuin) && - ((!HasEffect(All.Buffs.Swiftcast) && IsMoving && ((HasEffect(Buffs.GarudasFavor) && !IsGarudaAttuned) || (IsIfritAttuned && lastComboMove is not CrimsonCyclone))) || - GetCooldownRemainingTime(OriginalHook(Aethercharge)) is < 2.5f and > 0)) - return Ruin4; - // Egi Features - if (IsEnabled(CustomComboPreset.SMN_DemiEgiMenu_SwiftcastEgi) && LevelChecked(All.Swiftcast)) - { - // Swiftcast Garuda Feature - if (swiftcastPhase is 0 or 1 && LevelChecked(Slipstream) && HasEffect(Buffs.GarudasFavor)) + // Demi + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_DemiSummons)) { - if (CanSpellWeave(actionID) && IsGarudaAttuned && IsOffCooldown(All.Swiftcast)) - return All.Swiftcast; - - if (Config.SMN_ST_Egi_AstralFlow[2] && - ((HasEffect(Buffs.GarudasFavor) && HasEffect(All.Buffs.Swiftcast)) || (gauge.Attunement == 0))) // Astral Flow if Swiftcast is not ready throughout Garuda - return OriginalHook(AstralFlow); + if (InCombat() && gauge.SummonTimerRemaining == 0 && IsOffCooldown(OriginalHook(Aethercharge)) && + ((LevelChecked(Aethercharge) && !LevelChecked(SummonBahamut)) || // Pre-Bahamut Phase + (IsBahamutReady && LevelChecked(SummonBahamut)) || // Bahamut Phase + (IsPhoenixReady && LevelChecked(SummonPhoenix)) || // Phoenix Phase + (IsSolarBahamutReady && LevelChecked(SummonSolarBahamut)))) // Solar Bahamut Phase + return OriginalHook(Aethercharge); } - // Swiftcast Ifrit Feature (Conditions to allow for SpS Ruins to still be under the effect of Swiftcast) - if (swiftcastPhase == 2) + //Ruin4 in Egi Phases + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_Ruin4) && HasEffect(Buffs.FurtherRuin) && + ((!HasEffect(All.Buffs.Swiftcast) && IsMoving && ((HasEffect(Buffs.GarudasFavor) && !IsGarudaAttuned) || (IsIfritAttuned && lastComboMove is not CrimsonCyclone))) || + GetCooldownRemainingTime(OriginalHook(Aethercharge)) is < 2.5f and > 0)) + return Ruin4; + + // Egi Features + if (IsEnabled(CustomComboPreset.SMN_DemiEgiMenu_SwiftcastEgi) && LevelChecked(All.Swiftcast)) { - if (IsOffCooldown(All.Swiftcast) && IsIfritAttuned && lastComboMove is not CrimsonCyclone) + // Swiftcast Garuda Feature + if (swiftcastPhase is 0 or 1 && LevelChecked(Slipstream) && HasEffect(Buffs.GarudasFavor)) { - if (!Config.SMN_ST_Egi_AstralFlow[1] || (Config.SMN_ST_Egi_AstralFlow[1] && gauge.Attunement >= 1)) + if (CanSpellWeave(actionID) && IsGarudaAttuned && IsOffCooldown(All.Swiftcast)) return All.Swiftcast; + + if (Config.SMN_ST_Egi_AstralFlow[2] && + ((HasEffect(Buffs.GarudasFavor) && HasEffect(All.Buffs.Swiftcast)) || (gauge.Attunement == 0))) // Astral Flow if Swiftcast is not ready throughout Garuda + return OriginalHook(AstralFlow); + } + + // Swiftcast Ifrit Feature (Conditions to allow for SpS Ruins to still be under the effect of Swiftcast) + if (swiftcastPhase == 2) + { + if (IsOffCooldown(All.Swiftcast) && IsIfritAttuned && lastComboMove is not CrimsonCyclone) + { + if (!Config.SMN_ST_Egi_AstralFlow[1] || (Config.SMN_ST_Egi_AstralFlow[1] && gauge.Attunement >= 1)) + return All.Swiftcast; + } } } - } // SpS Swiftcast if (swiftcastPhase == 3) @@ -690,8 +690,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Slipstream) && HasEffect(Buffs.GarudasFavor)) { if (CanSpellWeave(actionID) && IsGarudaAttuned && IsOffCooldown(All.Swiftcast)) - return All.Swiftcast; - + return All.Swiftcast; + if (Config.SMN_ST_Egi_AstralFlow[2] && ((HasEffect(Buffs.GarudasFavor) && HasEffect(All.Buffs.Swiftcast)) || (gauge.Attunement == 0))) // Astral Flow if Swiftcast is not ready throughout Garuda return OriginalHook(AstralFlow); @@ -704,52 +704,53 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return All.Swiftcast; } } - - // Gemshine priority casting - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_EgiSummons_Attacks) && - ((IsIfritAttuned && gauge.Attunement >= 1 && HasEffect(All.Buffs.Swiftcast) && lastComboMove is not CrimsonCyclone) || - (HasEffect(Buffs.GarudasFavor) && gauge.Attunement >= 1 && !HasEffect(All.Buffs.Swiftcast) && IsMoving))) - return OriginalHook(Gemshine); - if ((Config.SMN_ST_Egi_AstralFlow[2] && HasEffect(Buffs.GarudasFavor) && (IsNotEnabled(CustomComboPreset.SMN_DemiEgiMenu_SwiftcastEgi) || swiftcastPhase == 2)) || // Garuda - (Config.SMN_ST_Egi_AstralFlow[0] && HasEffect(Buffs.TitansFavor) && lastComboMove is TopazRite or TopazCata && CanSpellWeave(actionID)) || // Titan - (Config.SMN_ST_Egi_AstralFlow[1] && (HasEffect(Buffs.IfritsFavor) && !Config.SMN_ST_CrimsonCycloneMelee && (IsMoving || gauge.Attunement == 0) || (lastComboMove is CrimsonCyclone && InMeleeRange()))) || - (Config.SMN_ST_Egi_AstralFlow[1] && HasEffect(Buffs.IfritsFavor) && Config.SMN_ST_CrimsonCycloneMelee && InMeleeRange())) // Ifrit - return OriginalHook(AstralFlow); + // Gemshine priority casting + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_EgiSummons_Attacks) && + ((IsIfritAttuned && gauge.Attunement >= 1 && HasEffect(All.Buffs.Swiftcast) && lastComboMove is not CrimsonCyclone) || + (HasEffect(Buffs.GarudasFavor) && gauge.Attunement >= 1 && !HasEffect(All.Buffs.Swiftcast) && IsMoving))) + return OriginalHook(Gemshine); - // Gemshine - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_EgiSummons_Attacks) && (IsGarudaAttuned || IsTitanAttuned || IsIfritAttuned)) - return OriginalHook(Gemshine); + if ((Config.SMN_ST_Egi_AstralFlow[2] && HasEffect(Buffs.GarudasFavor) && (IsNotEnabled(CustomComboPreset.SMN_DemiEgiMenu_SwiftcastEgi) || swiftcastPhase == 2)) || // Garuda + (Config.SMN_ST_Egi_AstralFlow[0] && HasEffect(Buffs.TitansFavor) && lastComboMove is TopazRite or TopazCata && CanSpellWeave(actionID)) || // Titan + (Config.SMN_ST_Egi_AstralFlow[1] && (HasEffect(Buffs.IfritsFavor) && !Config.SMN_ST_CrimsonCycloneMelee && (IsMoving || gauge.Attunement == 0) || (lastComboMove is CrimsonCyclone && InMeleeRange()))) || + (Config.SMN_ST_Egi_AstralFlow[1] && HasEffect(Buffs.IfritsFavor) && Config.SMN_ST_CrimsonCycloneMelee && InMeleeRange())) // Ifrit + return OriginalHook(AstralFlow); - // Egi Order - if (IsEnabled(CustomComboPreset.SMN_DemiEgiMenu_EgiOrder) && gauge.SummonTimerRemaining == 0) - { - if (gauge.IsIfritReady && !gauge.IsTitanReady && !gauge.IsGarudaReady && LevelChecked(SummonRuby)) - return OriginalHook(SummonRuby); + // Gemshine + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_EgiSummons_Attacks) && (IsGarudaAttuned || IsTitanAttuned || IsIfritAttuned)) + return OriginalHook(Gemshine); - if (summonerPrimalChoice is 0 or 1) + // Egi Order + if (IsEnabled(CustomComboPreset.SMN_DemiEgiMenu_EgiOrder) && gauge.SummonTimerRemaining == 0) { - if (gauge.IsTitanReady && LevelChecked(SummonTopaz)) - return OriginalHook(SummonTopaz); + if (gauge.IsIfritReady && !gauge.IsTitanReady && !gauge.IsGarudaReady && LevelChecked(SummonRuby)) + return OriginalHook(SummonRuby); - if (gauge.IsGarudaReady && LevelChecked(SummonEmerald)) - return OriginalHook(SummonEmerald); - } + if (summonerPrimalChoice is 0 or 1) + { + if (gauge.IsTitanReady && LevelChecked(SummonTopaz)) + return OriginalHook(SummonTopaz); - if (summonerPrimalChoice == 2) - { - if (gauge.IsGarudaReady && LevelChecked(SummonEmerald)) - return OriginalHook(SummonEmerald); + if (gauge.IsGarudaReady && LevelChecked(SummonEmerald)) + return OriginalHook(SummonEmerald); + } - if (gauge.IsTitanReady && LevelChecked(SummonTopaz)) - return OriginalHook(SummonTopaz); + if (summonerPrimalChoice == 2) + { + if (gauge.IsGarudaReady && LevelChecked(SummonEmerald)) + return OriginalHook(SummonEmerald); + + if (gauge.IsTitanReady && LevelChecked(SummonTopaz)) + return OriginalHook(SummonTopaz); + } } - } - // Ruin 4 - if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_Ruin4) && LevelChecked(Ruin4) && gauge.SummonTimerRemaining == 0 && gauge.AttunmentTimerRemaining == 0 && HasEffect(Buffs.FurtherRuin)) - return Ruin4; + // Ruin 4 + if (IsEnabled(CustomComboPreset.SMN_Advanced_Combo_Ruin4) && LevelChecked(Ruin4) && gauge.SummonTimerRemaining == 0 && gauge.AttunmentTimerRemaining == 0 && HasEffect(Buffs.FurtherRuin)) + return Ruin4; + } return actionID; } From 19a052b784da58cc76f8dd1f677b0111b849529b Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 17:26:02 +0000 Subject: [PATCH 205/208] More merges --- XIVSlothCombo/Combos/CustomComboPreset.cs | 64 +++- XIVSlothCombo/Combos/PvE/BLM/BLM.cs | 1 - XIVSlothCombo/Combos/PvE/DRG/DRG.cs | 1 - XIVSlothCombo/Combos/PvE/DRK/DRK.cs | 1 - XIVSlothCombo/Combos/PvE/GNB/GNB.cs | 1 - XIVSlothCombo/Combos/PvE/MCH/MCH.cs | 2 - XIVSlothCombo/Combos/PvE/MNK/MNK.cs | 301 ++++++++----------- XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs | 142 ++++++--- XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs | 1 - XIVSlothCombo/Combos/PvE/SAM/SAM.cs | 138 ++++++--- XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs | 1 - XIVSlothCombo/Combos/PvE/WHM/WHM.cs | 1 - XIVSlothCombo/Window/Functions/UserConfig.cs | 4 - XIVSlothCombo/Window/Tabs/AutoRotationTab.cs | 1 - XIVSlothCombo/Window/Tabs/Debug.cs | 2 - 15 files changed, 359 insertions(+), 302 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 89ba8a1f9..69e5fc735 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3735,6 +3735,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #region SAMURAI #region Simple ST + [AutoAction(false, false)] [ReplaceSkill(SAM.Hakaze, SAM.Gyofu)] [ConflictingCombos(SAM_ST_AdvancedMode)] @@ -3744,6 +3745,7 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Advanced ST + [AutoAction(false, false)] [ReplaceSkill(SAM.Hakaze, SAM.Gyofu)] [ConflictingCombos(SAM_ST_SimpleMode)] @@ -3808,6 +3810,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Senei Option", "Adds Senei to the rotation.", SAM.JobID)] SAM_ST_CDs_Senei = 15020, + [ParentCombo(SAM_ST_CDs_Senei)] + [CustomComboInfo("Guren Option", "Adds Guren to the rotation if Senei is not unlocked.", SAM.JobID)] + SAM_ST_CDs_Guren = 15021, + #endregion [ParentCombo(SAM_ST_AdvancedMode)] @@ -3826,7 +3832,8 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region Simple AoE - [AutoAction(true, false)] + + [AutoAction(true,false)] [ReplaceSkill(SAM.Fuga, SAM.Fuko)] [ConflictingCombos(SAM_AoE_AdvancedMode)] [CustomComboInfo("Simple Mode - AoE", "Replaces Fuga/Fuko with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", SAM.JobID)] @@ -3835,7 +3842,8 @@ The three digets after RDM.JobID can be used to reorder items in the list #endregion #region AoE Combos - [AutoAction(true, false)] + + [AutoAction(true,false)] [ReplaceSkill(SAM.Fuga, SAM.Fuko)] [ConflictingCombos(SAM_AoE_SimpleMode)] [CustomComboInfo("Advanced Mode - AoE", "Replaces Fuga/Fuko with a full one-button AoE rotation.\nThese features are ideal if you want to customize the rotation.", SAM.JobID)] @@ -3934,7 +3942,7 @@ The three digets after RDM.JobID can be used to reorder items in the list SAM_Iaijutsu = 15201, [ParentCombo(SAM_Iaijutsu)] - [CustomComboInfo("Iaijutsu to Tsubame-Gaeshi", "Replace Iaijutsu with Tsubame-gaeshi when Sen is empty.", SAM.JobID)] + [CustomComboInfo("Iaijutsu to Tsubame-Gaeshi", "Replace Iaijutsu with Tsubame-gaeshi when appropriate.", SAM.JobID)] SAM_Iaijutsu_TsubameGaeshi = 15202, [ParentCombo(SAM_Iaijutsu)] @@ -3950,24 +3958,56 @@ The three digets after RDM.JobID can be used to reorder items in the list #region Shinten Features [ReplaceSkill(SAM.Shinten)] + [CustomComboInfo("Shinten Features", "Collection of Hissatsu: Shinten Features.", SAM.JobID)] + SAM_Shinten = 15251, + + [ParentCombo(SAM_Shinten)] [CustomComboInfo("Shinten to Shoha", "Replace Hissatsu: Shinten with Shoha when Meditation is full.", SAM.JobID)] SAM_Shinten_Shoha = 15205, - [ParentCombo(SAM_Shinten_Shoha)] + [ParentCombo(SAM_Shinten)] [CustomComboInfo("Shinten to Senei", "Replace Hissatsu: Shinten with Senei when its cooldown is up.", SAM.JobID)] - SAM_Shinten_Shoha_Senei = 15206, + SAM_Shinten_Senei = 15206, + + [ParentCombo(SAM_Shinten)] + [CustomComboInfo("Shinten to Zanshin", "Replace Hissatsu: Shinten with Zanshin when usable.", SAM.JobID)] + SAM_Shinten_Zanshin = 15207, #endregion #region Kyuten Features [ReplaceSkill(SAM.Kyuten)] + [CustomComboInfo("Kyuten Features", "Collection of Hissatsu: Kyuten Features.", SAM.JobID)] + SAM_Kyuten = 15252, + + [ParentCombo(SAM_Kyuten)] [CustomComboInfo("Kyuten to Shoha", "Replace Hissatsu: Kyuten with Shoha when Meditation is full.", SAM.JobID)] - SAM_Kyuten_Shoha = 15207, + SAM_Kyuten_Shoha = 15208, - [ParentCombo(SAM_Kyuten_Shoha)] + [ParentCombo(SAM_Kyuten)] [CustomComboInfo("Kyuten to Guren", "Replace Hissatsu: Kyuten with Guren when its cooldown is up.", SAM.JobID)] - SAM_Kyuten_Shoha_Guren = 15208, + SAM_Kyuten_Guren = 15209, + + [ParentCombo(SAM_Kyuten)] + [CustomComboInfo("Kyuten to Zanshin", "Replace Hissatsu: Kyuten with Zanshin when usable.", SAM.JobID)] + SAM_Kyuten_Zanshin = 15210, + + #endregion + + #region Ikishoten Features + + [ReplaceSkill(SAM.Ikishoten)] + [CustomComboInfo("Ikishoten Features", "Collection of Ikishoten Features.", SAM.JobID)] + SAM_Ikishoten = 15253, + + [ParentCombo(SAM_Ikishoten)] + [CustomComboInfo("Ikishoten to Namikiri", "Replace Ikishoten with Ogi Namikiri & Kaeshi Namikiri when available.", SAM.JobID)] + SAM_Ikishoten_Namikiri = 15212, + + [ParentCombo(SAM_Ikishoten)] + [CustomComboInfo("Ikishoten to Shoha", "Replace Ikishoten with Shoha when Meditation is full before Ogi Namikiri.", SAM.JobID)] + SAM_Ikishoten_Shoha = 15213, #endregion @@ -3975,15 +4015,11 @@ The three digets after RDM.JobID can be used to reorder items in the list [ReplaceSkill(SAM.Gyoten)] [CustomComboInfo("Gyoten Feature", "Hissatsu: Gyoten becomes Yaten/Gyoten depending on the distance from your target.", SAM.JobID)] - SAM_GyotenYaten = 15209, - - [ReplaceSkill(SAM.Ikishoten)] - [CustomComboInfo("Ikishoten Namikiri Feature", "Replace Ikishoten with Ogi Namikiri and then Kaeshi Namikiri when available.\nIf you have full Meditation stacks, Ikishoten becomes Shoha while you have Ogi Namikiri ready.", SAM.JobID)] - SAM_Ikishoten_OgiNamikiri = 15210, + SAM_GyotenYaten = 15211, #endregion - #region variant + #region variant [Variant] [VariantParent(SAM_ST_AdvancedMode, SAM_AoE_AdvancedMode)] diff --git a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs index c0c939ab7..55fad2639 100644 --- a/XIVSlothCombo/Combos/PvE/BLM/BLM.cs +++ b/XIVSlothCombo/Combos/PvE/BLM/BLM.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; using XIVSlothCombo.Extensions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; diff --git a/XIVSlothCombo/Combos/PvE/DRG/DRG.cs b/XIVSlothCombo/Combos/PvE/DRG/DRG.cs index 3fee40aa3..f2a8d2c2e 100644 --- a/XIVSlothCombo/Combos/PvE/DRG/DRG.cs +++ b/XIVSlothCombo/Combos/PvE/DRG/DRG.cs @@ -1,5 +1,4 @@ using Dalamud.Game.ClientState.JobGauge.Types; -using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Extensions; diff --git a/XIVSlothCombo/Combos/PvE/DRK/DRK.cs b/XIVSlothCombo/Combos/PvE/DRK/DRK.cs index 9dfb5ac09..e017691b5 100644 --- a/XIVSlothCombo/Combos/PvE/DRK/DRK.cs +++ b/XIVSlothCombo/Combos/PvE/DRK/DRK.cs @@ -1,7 +1,6 @@ using Dalamud.Game.ClientState.JobGauge.Types; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; namespace XIVSlothCombo.Combos.PvE { diff --git a/XIVSlothCombo/Combos/PvE/GNB/GNB.cs b/XIVSlothCombo/Combos/PvE/GNB/GNB.cs index 8b14c3cc5..d8c17130c 100644 --- a/XIVSlothCombo/Combos/PvE/GNB/GNB.cs +++ b/XIVSlothCombo/Combos/PvE/GNB/GNB.cs @@ -3,7 +3,6 @@ using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; -using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data; namespace XIVSlothCombo.Combos.PvE diff --git a/XIVSlothCombo/Combos/PvE/MCH/MCH.cs b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs index 28f94daa9..471313a29 100644 --- a/XIVSlothCombo/Combos/PvE/MCH/MCH.cs +++ b/XIVSlothCombo/Combos/PvE/MCH/MCH.cs @@ -1,5 +1,3 @@ -using System; -using System.Linq; using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using XIVSlothCombo.Combos.PvE.Content; diff --git a/XIVSlothCombo/Combos/PvE/MNK/MNK.cs b/XIVSlothCombo/Combos/PvE/MNK/MNK.cs index caa86886c..69e0a99d1 100644 --- a/XIVSlothCombo/Combos/PvE/MNK/MNK.cs +++ b/XIVSlothCombo/Combos/PvE/MNK/MNK.cs @@ -1,10 +1,8 @@ -using System.Linq; -using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.JobGauge.Types; -using Dalamud.Game.ClientState.Statuses; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.JobHelpers.MNK; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; @@ -54,7 +52,7 @@ public const uint protected static MNKGauge Gauge => GetJobGauge(); - protected static class Buffs + internal static class Buffs { public const ushort TwinSnakes = 101, @@ -73,20 +71,10 @@ public const ushort internal class MNK_ST_SimpleMode : CustomCombo { - internal static MNKOpenerLogic MNKOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); - int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); - int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); - float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; - if (actionID is Bootshine or LeapingOpo) { if (MNKOpener.DoFullOpener(ref actionID, 0)) @@ -128,29 +116,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb return RiddleOfWind; //Perfect Balance - if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist)) - { - // Odd window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - !JustUsed(PerfectBalance, 20) && - HasEffect(Buffs.RiddleOfFire) && - !HasEffect(Buffs.Brotherhood)) - return PerfectBalance; - - // Even window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && - (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) - return PerfectBalance; - - // Low level - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || - !LevelChecked(RiddleOfFire))) - return PerfectBalance; - } + if (MNKHelper.UsePerfectBalance()) + return PerfectBalance; if (PlayerHealthPercentageHp() <= 25 && ActionReady(All.SecondWind)) @@ -227,7 +194,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb return WindsReply; // Standard Beast Chakras - return DetermineCoreAbility(actionID, true); + return MNKHelper.DetermineCoreAbility(actionID, true); } return actionID; @@ -236,20 +203,10 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb internal class MNK_ST_AdvancedMode : CustomCombo { - internal static MNKOpenerLogic MNKOpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.MNK_ST_AdvancedMode; protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - bool bothNadisOpen = Gauge.Nadi.ToString() == "LUNAR, SOLAR"; - bool solarNadi = Gauge.Nadi == Nadi.SOLAR; - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - int opoOpoChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); - int raptorChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); - int coeurlChakra = Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); - float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; - if (actionID is Bootshine or LeapingOpo) { if (IsEnabled(CustomComboPreset.MNK_STUseOpener)) @@ -302,29 +259,8 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb //Perfect Balance if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance) && - ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance) && - !HasEffect(Buffs.FormlessFist)) - { - // Odd window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - !JustUsed(PerfectBalance, 20) && - HasEffect(Buffs.RiddleOfFire) && - !HasEffect(Buffs.Brotherhood)) - return PerfectBalance; - - // Even window - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && - (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) - return PerfectBalance; - - // Low level - if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && - ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || - !LevelChecked(RiddleOfFire))) - return PerfectBalance; - } + MNKHelper.UsePerfectBalance()) + return PerfectBalance; if (IsEnabled(CustomComboPreset.MNK_ST_ComboHeals)) { @@ -349,48 +285,45 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb ? DragonKick : OriginalHook(Bootshine); - if (IsEnabled(CustomComboPreset.MNK_STUsePerfectBalance)) + // Masterful Blitz + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && + !IsOriginal(MasterfulBlitz)) + return OriginalHook(MasterfulBlitz); + + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) { - // Masterful Blitz - if (LevelChecked(MasterfulBlitz) && - !HasEffect(Buffs.PerfectBalance) && - !IsOriginal(MasterfulBlitz)) - return OriginalHook(MasterfulBlitz); + #region Open Solar - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) + if (!solarNadi && !bothNadisOpen) { - #region Open Solar - - if (!solarNadi && !bothNadisOpen) - { - if (coeurlChakra == 0) - return Gauge.CoeurlFury == 0 - ? Demolish - : OriginalHook(SnapPunch); - - if (raptorChakra == 0) - return Gauge.RaptorFury == 0 - ? TwinSnakes - : OriginalHook(TrueStrike); - - if (opoOpoChakra == 0) - return Gauge.OpoOpoFury == 0 - ? DragonKick - : OriginalHook(Bootshine); - } - - #endregion + if (coeurlChakra == 0) + return Gauge.CoeurlFury == 0 + ? Demolish + : OriginalHook(SnapPunch); - #region Open Lunar + if (raptorChakra == 0) + return Gauge.RaptorFury == 0 + ? TwinSnakes + : OriginalHook(TrueStrike); - if (solarNadi || lunarNadi || bothNadisOpen) + if (opoOpoChakra == 0) return Gauge.OpoOpoFury == 0 ? DragonKick : OriginalHook(Bootshine); - - #endregion } + + #endregion + + #region Open Lunar + + if (solarNadi || lunarNadi || bothNadisOpen) + return Gauge.OpoOpoFury == 0 + ? DragonKick + : OriginalHook(Bootshine); + + #endregion } if (IsEnabled(CustomComboPreset.MNK_STUseBuffs)) @@ -415,7 +348,7 @@ protected override uint Invoke(uint actionID, uint lastComboActionID, float comb } // Standard Beast Chakras - return DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); + return MNKHelper.DetermineCoreAbility(actionID, IsEnabled(CustomComboPreset.MNK_STUseTrueNorth)); } return actionID; @@ -428,10 +361,6 @@ internal class MNK_AOE_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - bool nadiNone = Gauge.Nadi == Nadi.NONE; - if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) { if (!InCombat() && Gauge.Chakra < 5 && LevelChecked(Meditation)) @@ -463,14 +392,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return RiddleOfWind; if (ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) - - if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || - GetCooldownRemainingTime(PerfectBalance) <= 4 || - HasEffect(Buffs.Brotherhood) || - (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || - (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) - return PerfectBalance; + !HasEffect(Buffs.PerfectBalance) && + (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || + GetCooldownRemainingTime(PerfectBalance) <= 4 || + HasEffect(Buffs.Brotherhood) || + (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || + (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8))) + return PerfectBalance; if (Gauge.Chakra >= 5 && LevelChecked(HowlingFist) && @@ -484,12 +412,18 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return All.Bloodbath; } - if (HasEffect(Buffs.WindsRumination)) - return WindsReply; - - if (HasEffect(Buffs.FiresRumination)) + if (LevelChecked(FiresReply) && + HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) return FiresReply; + if (HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) + return WindsReply; + // Masterful Blitz if (LevelChecked(MasterfulBlitz) && !HasEffect(Buffs.PerfectBalance) && OriginalHook(MasterfulBlitz) != MasterfulBlitz) @@ -498,14 +432,10 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Perfect Balance if (HasEffect(Buffs.PerfectBalance)) { - if (nadiNone || !lunarNadi) - if (pbStacks?.StackCount > 0) - return LevelChecked(ShadowOfTheDestroyer) - ? ShadowOfTheDestroyer - : Rockbreaker; - - if (lunarNadi) - switch (pbStacks?.StackCount) + #region Open Solar + + if (!solarNadi && !bothNadisOpen) + switch (GetBuffStacks(Buffs.PerfectBalance)) { case 3: return OriginalHook(ArmOfTheDestroyer); @@ -516,6 +446,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim case 1: return Rockbreaker; } + + #endregion + + #region Open Lunar + + if (solarNadi || lunarNadi || bothNadisOpen) + return LevelChecked(ShadowOfTheDestroyer) + ? ShadowOfTheDestroyer + : Rockbreaker; + + #endregion } // Monk Rotation @@ -545,10 +486,6 @@ internal class MNK_AOE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - Status? pbStacks = FindEffectAny(Buffs.PerfectBalance); - bool lunarNadi = Gauge.Nadi == Nadi.LUNAR; - bool nadiNone = Gauge.Nadi == Nadi.NONE; - if (actionID is ArmOfTheDestroyer or ShadowOfTheDestroyer) { if (IsEnabled(CustomComboPreset.MNK_AoEUseMeditation) && @@ -589,20 +526,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance) && ActionReady(PerfectBalance) && - !HasEffect(Buffs.PerfectBalance)) - - // Use Perfect Balance if: - // 1. It's after Bootshine/Dragon Kick. - This doesn't apply to AoE - // 2. At max stacks / before overcap. - // 3. During Brotherhood. - // 4. During Riddle of Fire. - // 5. Prepare Masterful Blitz for the Riddle of Fire & Brotherhood window. - if (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || - GetCooldownRemainingTime(PerfectBalance) <= 4 || - HasEffect(Buffs.Brotherhood) || - (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || - (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8)) - return PerfectBalance; + !HasEffect(Buffs.PerfectBalance) && + (GetRemainingCharges(PerfectBalance) == GetMaxCharges(PerfectBalance) || + GetCooldownRemainingTime(PerfectBalance) <= 4 || + HasEffect(Buffs.Brotherhood) || + (HasEffect(Buffs.RiddleOfFire) && GetBuffRemainingTime(Buffs.RiddleOfFire) < 10) || + (GetCooldownRemainingTime(RiddleOfFire) < 4 && GetCooldownRemainingTime(Brotherhood) < 8))) + return PerfectBalance; if (IsEnabled(CustomComboPreset.MNK_AoEUseHowlingFist) && Gauge.Chakra >= 5 && @@ -626,45 +556,55 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (IsEnabled(CustomComboPreset.MNK_AoEUseROF) && IsEnabled(CustomComboPreset.MNK_AoEUseFiresReply) && - HasEffect(Buffs.FiresRumination)) + LevelChecked(FiresReply) && + HasEffect(Buffs.FiresRumination) && + !HasEffect(Buffs.PerfectBalance) && + !HasEffect(Buffs.FormlessFist)) return FiresReply; if (IsEnabled(CustomComboPreset.MNK_AoEUseROW) && IsEnabled(CustomComboPreset.MNK_AoEUseWindsReply) && - HasEffect(Buffs.WindsRumination)) + HasEffect(Buffs.WindsRumination) && + LevelChecked(WindsReply) && + HasEffect(Buffs.RiddleOfWind) && + GetBuffRemainingTime(Buffs.WindsRumination) < 4) return WindsReply; } // Masterful Blitz - if (IsEnabled(CustomComboPreset.MNK_AoEUsePerfectBalance)) + if (LevelChecked(MasterfulBlitz) && + !HasEffect(Buffs.PerfectBalance) && + OriginalHook(MasterfulBlitz) != MasterfulBlitz) + return OriginalHook(MasterfulBlitz); + + // Perfect Balance + if (HasEffect(Buffs.PerfectBalance)) { - if (LevelChecked(MasterfulBlitz) && - !HasEffect(Buffs.PerfectBalance) && - OriginalHook(MasterfulBlitz) != MasterfulBlitz) - return OriginalHook(MasterfulBlitz); + #region Open Solar - // Perfect Balance - if (HasEffect(Buffs.PerfectBalance)) - { - if (nadiNone || !lunarNadi) - if (pbStacks?.StackCount > 0) - return LevelChecked(ShadowOfTheDestroyer) - ? ShadowOfTheDestroyer - : Rockbreaker; - - if (lunarNadi) - switch (pbStacks?.StackCount) - { - case 3: - return OriginalHook(ArmOfTheDestroyer); - - case 2: - return FourPointFury; - - case 1: - return Rockbreaker; - } - } + if (!solarNadi && !bothNadisOpen) + switch (GetBuffStacks(Buffs.PerfectBalance)) + { + case 3: + return OriginalHook(ArmOfTheDestroyer); + + case 2: + return FourPointFury; + + case 1: + return Rockbreaker; + } + + #endregion + + #region Open Lunar + + if (solarNadi || lunarNadi || bothNadisOpen) + return LevelChecked(ShadowOfTheDestroyer) + ? ShadowOfTheDestroyer + : Rockbreaker; + + #endregion } // Monk Rotation @@ -694,11 +634,10 @@ internal class MNK_PerfectBalance : CustomCombo protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) { - if (actionID is PerfectBalance && - OriginalHook(MasterfulBlitz) != MasterfulBlitz && LevelChecked(MasterfulBlitz)) - return OriginalHook(MasterfulBlitz); - - return actionID; + return actionID is PerfectBalance && OriginalHook(MasterfulBlitz) != MasterfulBlitz && + LevelChecked(MasterfulBlitz) + ? OriginalHook(MasterfulBlitz) + : actionID; } } diff --git a/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs b/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs index 3d96a4b8c..1e94d520a 100644 --- a/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/MNK/MNK_Helper.cs @@ -1,53 +1,102 @@ -using Dalamud.Game.ClientState.JobGauge.Enums; +using System.Linq; +using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using XIVSlothCombo.Combos.JobHelpers.Enums; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.MNK; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE; +namespace XIVSlothCombo.Combos.JobHelpers; -internal partial class MNK +internal class MNK { - private static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) - { - if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) - return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) - ? DragonKick - : OriginalHook(Bootshine); + // MNK Gauge & Extensions + public static float GCD = GetCooldown(OriginalHook(Bootshine)).CooldownTotal; + public static MNKOpenerLogic MNKOpener = new(); + public static MNKGauge Gauge = GetJobGauge(); + + public static bool bothNadisOpen => Gauge.Nadi.ToString() == "LUNAR, SOLAR"; + + public static bool solarNadi => Gauge.Nadi == Nadi.SOLAR; + + public static bool lunarNadi => Gauge.Nadi == Nadi.LUNAR; - if (HasEffect(Buffs.RaptorForm)) - return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) - ? TwinSnakes - : OriginalHook(TrueStrike); + public static int opoOpoChakra => Gauge.BeastChakra.Count(x => x == BeastChakra.OPOOPO); - if (HasEffect(Buffs.CoeurlForm)) + public static int raptorChakra => Gauge.BeastChakra.Count(x => x == BeastChakra.RAPTOR); + + public static int coeurlChakra => Gauge.BeastChakra.Count(x => x == BeastChakra.COEURL); + + internal class MNKHelper + { + public static uint DetermineCoreAbility(uint actionId, bool useTrueNorthIfEnabled) { - if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) + if (HasEffect(Buffs.OpoOpoForm) || HasEffect(Buffs.FormlessFist)) + return Gauge.OpoOpoFury == 0 && LevelChecked(DragonKick) + ? DragonKick + : OriginalHook(Bootshine); + + if (HasEffect(Buffs.RaptorForm)) + return Gauge.RaptorFury == 0 && LevelChecked(TwinSnakes) + ? TwinSnakes + : OriginalHook(TrueStrike); + + if (HasEffect(Buffs.CoeurlForm)) { - if (!OnTargetsRear() && - TargetNeedsPositionals() && - !HasEffect(Buffs.TrueNorth) && - ActionReady(TrueNorth) && - useTrueNorthIfEnabled) - return TrueNorth; - - return Demolish; + if (Gauge.CoeurlFury == 0 && LevelChecked(Demolish)) + { + if (!OnTargetsRear() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; + + return Demolish; + } + + if (LevelChecked(SnapPunch)) + { + if (!OnTargetsFlank() && + TargetNeedsPositionals() && + !HasEffect(Buffs.TrueNorth) && + ActionReady(TrueNorth) && + useTrueNorthIfEnabled) + return TrueNorth; + + return OriginalHook(SnapPunch); + } } - if (LevelChecked(SnapPunch)) + return actionId; + } + + public static bool UsePerfectBalance() + { + if (ActionReady(PerfectBalance) && !HasEffect(Buffs.PerfectBalance) && !HasEffect(Buffs.FormlessFist)) { - if (!OnTargetsFlank() && - TargetNeedsPositionals() && - !HasEffect(Buffs.TrueNorth) && - ActionReady(TrueNorth) && - useTrueNorthIfEnabled) - return TrueNorth; - - return OriginalHook(SnapPunch); + // Odd window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + !JustUsed(PerfectBalance, 20) && + HasEffect(Buffs.RiddleOfFire) && !HasEffect(Buffs.Brotherhood)) + return true; + + // Even window + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + (GetCooldownRemainingTime(Brotherhood) <= GCD * 3 || HasEffect(Buffs.Brotherhood)) && + (GetCooldownRemainingTime(RiddleOfFire) <= GCD * 3 || HasEffect(Buffs.RiddleOfFire))) + return true; + + // Low level + if ((JustUsed(OriginalHook(Bootshine)) || JustUsed(DragonKick)) && + ((HasEffect(Buffs.RiddleOfFire) && !LevelChecked(Brotherhood)) || + !LevelChecked(RiddleOfFire))) + return true; } - } - return actionId; + return false; + } } internal class MNKOpenerLogic @@ -102,9 +151,6 @@ private static bool HasCooldowns() if (!ActionReady(RiddleOfWind)) return false; - if (!ActionReady(Meditation) && Gauge.Chakra < 5) - return false; - if (Gauge.Nadi != Nadi.NONE) return false; @@ -186,8 +232,7 @@ private bool DoSlOpener(ref uint actionID) else if (OpenerStep == 4) actionID = Brotherhood; if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) - actionID = RiddleOfFire; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; else if (OpenerStep == 6) actionID = LeapingOpo; @@ -196,8 +241,7 @@ private bool DoSlOpener(ref uint actionID) else if (OpenerStep == 7) actionID = TheForbiddenChakra; if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) - actionID = RiddleOfWind; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; if (WasLastWeaponskill(RisingPhoenix) && OpenerStep == 9) OpenerStep++; else if (OpenerStep == 9) actionID = RisingPhoenix; @@ -275,30 +319,28 @@ private bool DoLlOpener(ref uint actionID) OpenerStep++; else if (OpenerStep == 1) actionID = PerfectBalance; - if (WasLastAction(LeapingOpo) && OpenerStep == 2) OpenerStep++; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 2) OpenerStep++; else if (OpenerStep == 2) actionID = LeapingOpo; - if (WasLastAction(DragonKick) && OpenerStep == 3) OpenerStep++; + if (WasLastWeaponskill(DragonKick) && OpenerStep == 3) OpenerStep++; else if (OpenerStep == 3) actionID = DragonKick; - if (WasLastAction(Brotherhood) && OpenerStep == 4) OpenerStep++; + if (WasLastAbility(Brotherhood) && OpenerStep == 4) OpenerStep++; else if (OpenerStep == 4) actionID = Brotherhood; if (WasLastAction(RiddleOfFire) && OpenerStep == 5) OpenerStep++; - else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) - actionID = RiddleOfFire; + else if (OpenerStep == 5 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfFire; - if (WasLastAction(LeapingOpo) && OpenerStep == 6) OpenerStep++; + if (WasLastWeaponskill(LeapingOpo) && OpenerStep == 6) OpenerStep++; else if (OpenerStep == 6) actionID = LeapingOpo; if (WasLastAction(TheForbiddenChakra) && OpenerStep == 7) OpenerStep++; else if (OpenerStep == 7) actionID = TheForbiddenChakra; if (WasLastAction(RiddleOfWind) && OpenerStep == 8) OpenerStep++; - else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) - actionID = RiddleOfWind; + else if (OpenerStep == 8 && CanDelayedWeave(ActionWatching.LastWeaponskill)) actionID = RiddleOfWind; - if (WasLastAction(ElixirBurst) && OpenerStep == 9) OpenerStep++; + if (WasLastWeaponskill(ElixirBurst) && OpenerStep == 9) OpenerStep++; else if (OpenerStep == 9) actionID = ElixirBurst; if (WasLastWeaponskill(DragonKick) && OpenerStep == 10) OpenerStep++; diff --git a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs index 3855a4000..e62040886 100644 --- a/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RDM/RDM_Helper.cs @@ -1,6 +1,5 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.JobGauge.Types; -using Dalamud.Game.ClientState.Objects.Types; using ECommons.DalamudServices; using System; using XIVSlothCombo.Combos.JobHelpers.Enums; diff --git a/XIVSlothCombo/Combos/PvE/SAM/SAM.cs b/XIVSlothCombo/Combos/PvE/SAM/SAM.cs index 5953d267e..e4918c49c 100644 --- a/XIVSlothCombo/Combos/PvE/SAM/SAM.cs +++ b/XIVSlothCombo/Combos/PvE/SAM/SAM.cs @@ -91,7 +91,6 @@ public const ushort EnhancedMeikyoShishui2 = 593; } - internal class SAM_ST_YukikazeCombo : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_ST_YukikazeCombo; @@ -243,11 +242,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) return Senei; + //Guren if no Senei + if (!LevelChecked(Senei) && + gauge.Kenki >= 25 && ActionReady(Guren) && + HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) + return Guren; + //Zanshin Usage if (LevelChecked(Zanshin) && gauge.Kenki >= 50 && CanWeave(actionID) && HasEffect(Buffs.ZanshinReady) && - (JustUsed(Higanbana, 7f) || - GetBuffRemainingTime(Buffs.ZanshinReady) <= 6)) + ((JustUsed(Higanbana, 7f) || oneSen && HasEffect(Buffs.OgiNamikiriReady)) || + GetBuffRemainingTime(Buffs.ZanshinReady) <= 6)) //Protection for scuffed runs return Zanshin; if (LevelChecked(Shoha) && gauge.MeditationStacks is 3) @@ -262,11 +267,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Enpi) && !InMeleeRange() && HasBattleTarget()) return Enpi; - if (IsEnabled(CustomComboPreset.SAM_ST_CDs) && - HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) + if (HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) { //Ogi Namikiri Features - if (!IsMoving && ActionReady(OgiNamikiri) && (JustUsed(Higanbana, 5f) || GetBuffRemainingTime(Buffs.OgiNamikiriReady) <= GCD) && + if (!IsMoving && LevelChecked(OgiNamikiri) && + (((JustUsed(Higanbana, 5f) || GetDebuffRemainingTime(Debuffs.Higanbana) > 30) && HasEffect(Buffs.OgiNamikiriReady)) || + GetBuffRemainingTime(Buffs.OgiNamikiriReady) <= GCD) && //Protection for scuffed runs (gauge.Kaeshi == Kaeshi.NAMIKIRI || HasEffect(Buffs.OgiNamikiriReady))) return OriginalHook(OgiNamikiri); @@ -283,10 +289,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } if (!IsMoving && - ((oneSen && enemyHP >= 1 && GetDebuffRemainingTime(Debuffs.Higanbana) <= 19 && JustUsed(Gekko, 3f) && JustUsed(MeikyoShisui, 15f)) || + ((oneSen && enemyHP >= 1 && + ((GetDebuffRemainingTime(Debuffs.Higanbana) <= 19 && JustUsed(Gekko, 3f) && JustUsed(MeikyoShisui, 15f)) || !TargetHasEffect(Debuffs.Higanbana)) || (twoSen && !LevelChecked(MidareSetsugekka)) || (threeSen && - (LevelChecked(MidareSetsugekka) && !HasEffect(Buffs.TsubameReady))))) + (LevelChecked(MidareSetsugekka) && !HasEffect(Buffs.TsubameReady)))))) return OriginalHook(Iaijutsu); } } @@ -296,13 +303,18 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (trueNorthReady) return All.TrueNorth; - if (LevelChecked(Gekko) && (!HasEffect(Buffs.Fugetsu) || (!gauge.Sen.HasFlag(Sen.GETSU) && HasEffect(Buffs.Fuka)))) + if (LevelChecked(Gekko) && + (!HasEffect(Buffs.Fugetsu) || + (!gauge.Sen.HasFlag(Sen.GETSU) && HasEffect(Buffs.Fuka)))) return Gekko; - if (LevelChecked(Kasha) && (!HasEffect(Buffs.Fuka) || (!gauge.Sen.HasFlag(Sen.KA) && HasEffect(Buffs.Fugetsu)))) + if (LevelChecked(Kasha) && + (!HasEffect(Buffs.Fuka) || + (!gauge.Sen.HasFlag(Sen.KA) && HasEffect(Buffs.Fugetsu)))) return Kasha; - if (LevelChecked(Yukikaze) && !gauge.Sen.HasFlag(Sen.SETSU)) + if (LevelChecked(Yukikaze) && + !gauge.Sen.HasFlag(Sen.SETSU)) return Yukikaze; } @@ -448,16 +460,25 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Senei Features - if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Senei) && - gauge.Kenki >= 25 && ActionReady(Senei) && - HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) - return Senei; + if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Senei)) + { + if (gauge.Kenki >= 25 && ActionReady(Senei) && + HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) + return Senei; + + //Guren if no Senei + if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Guren) && + !LevelChecked(Senei) && + gauge.Kenki >= 25 && ActionReady(Guren) && + HasEffect(Buffs.Fugetsu) && HasEffect(Buffs.Fuka)) + return Guren; + } //Zanshin Usage if (IsEnabled(CustomComboPreset.SAM_ST_CDs_Zanshin) && LevelChecked(Zanshin) && gauge.Kenki >= 50 && CanWeave(actionID) && HasEffect(Buffs.ZanshinReady) && - (JustUsed(Higanbana, 7f) || + ((JustUsed(Higanbana, 7f) || oneSen && HasEffect(Buffs.OgiNamikiriReady)) || GetBuffRemainingTime(Buffs.ZanshinReady) <= 6)) return Zanshin; @@ -485,7 +506,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.SAM_ST_CDs_OgiNamikiri) && (!IsEnabled(CustomComboPreset.SAM_ST_CDs_OgiNamikiri_Movement) || (IsEnabled(CustomComboPreset.SAM_ST_CDs_OgiNamikiri_Movement) && !IsMoving)) && - ActionReady(OgiNamikiri) && (JustUsed(Higanbana, 5f) || GetBuffRemainingTime(Buffs.OgiNamikiriReady) <= GCD) && + ActionReady(OgiNamikiri) && + (((JustUsed(Higanbana, 5f) || GetDebuffRemainingTime(Debuffs.Higanbana) > 30) && HasEffect(Buffs.OgiNamikiriReady)) || + GetBuffRemainingTime(Buffs.OgiNamikiriReady) <= GCD) && (gauge.Kaeshi == Kaeshi.NAMIKIRI || HasEffect(Buffs.OgiNamikiriReady))) return OriginalHook(OgiNamikiri); @@ -503,10 +526,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if ((!IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu_Movement) || (IsEnabled(CustomComboPreset.SAM_ST_CDs_Iaijutsu_Movement) && !IsMoving)) && - ((oneSen && enemyHP > HiganbanaThreshold && GetDebuffRemainingTime(Debuffs.Higanbana) <= 19 && JustUsed(Gekko, 3f) && JustUsed(MeikyoShisui, 15f)) || + ((oneSen && enemyHP > HiganbanaThreshold && + ((GetDebuffRemainingTime(Debuffs.Higanbana) <= 19 && JustUsed(Gekko, 3f) && JustUsed(MeikyoShisui, 15f)) || !TargetHasEffect(Debuffs.Higanbana)) || (twoSen && !LevelChecked(MidareSetsugekka)) || (threeSen && - (LevelChecked(MidareSetsugekka) && !HasEffect(Buffs.TsubameReady))))) + (LevelChecked(MidareSetsugekka) && !HasEffect(Buffs.TsubameReady)))))) return OriginalHook(Iaijutsu); } } @@ -728,7 +752,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(TenkaGoken)) { - if (!IsMoving && (OriginalHook(Iaijutsu) is TenkaGoken or TendoGoken)) + if (!IsMoving && (OriginalHook(Iaijutsu) is TenkaGoken)) return OriginalHook(Iaijutsu); if (!IsMoving && LevelChecked(TendoGoken) && (OriginalHook(Iaijutsu) is TendoGoken)) @@ -929,25 +953,33 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Iaijutsu) { - if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_Shoha) && - ActionReady(Shoha) && gauge.MeditationStacks is 3 && CanWeave(actionID)) + bool canAddShoha = IsEnabled(CustomComboPreset.SAM_Iaijutsu_Shoha) && + ActionReady(Shoha) && + gauge.MeditationStacks is 3; + + if (canAddShoha && CanWeave(actionID)) return Shoha; - if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_OgiNamikiri) && - LevelChecked(OgiNamikiri) && HasEffect(Buffs.OgiNamikiriReady)) + if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_OgiNamikiri) && ( + (LevelChecked(OgiNamikiri) && HasEffect(Buffs.OgiNamikiriReady)) || + gauge.Kaeshi == Kaeshi.NAMIKIRI)) return OriginalHook(OgiNamikiri); - if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_TsubameGaeshi) && - ((LevelChecked(TsubameGaeshi) && HasEffect(Buffs.TsubameReady)) || (LevelChecked(TendoKaeshiSetsugekka) && HasEffect(Buffs.TendoKaeshiSetsugekkaReady)))) + if (IsEnabled(CustomComboPreset.SAM_Iaijutsu_TsubameGaeshi) && ( + (LevelChecked(TsubameGaeshi) && (HasEffect(Buffs.TsubameReady) || HasEffect(Buffs.KaeshiGokenReady))) || + (LevelChecked(TendoKaeshiSetsugekka) && (HasEffect(Buffs.TendoKaeshiSetsugekkaReady) || HasEffect(Buffs.TendoKaeshiGokenReady))))) return OriginalHook(TsubameGaeshi); + + if (canAddShoha) + return Shoha; } return actionID; } } - internal class SAM_Shinten_Shoha : CustomCombo + internal class SAM_Shinten : CustomCombo { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_Shinten_Shoha; + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_Shinten; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { @@ -955,20 +987,28 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Shinten) { - if (IsEnabled(CustomComboPreset.SAM_Shinten_Shoha_Senei) && - ActionReady(Senei)) - return Senei; + if (IsEnabled(CustomComboPreset.SAM_Shinten)) + { + if (IsEnabled(CustomComboPreset.SAM_Shinten_Senei) && + ActionReady(Senei)) + return Senei; - if (gauge.MeditationStacks is 3 && ActionReady(Shoha)) - return Shoha; + if (IsEnabled(CustomComboPreset.SAM_Shinten_Zanshin) && + HasEffect(Buffs.ZanshinReady)) + return Zanshin; + + if (IsEnabled(CustomComboPreset.SAM_Shinten_Shoha) && + ActionReady(Shoha) && gauge.MeditationStacks is 3) + return Shoha; + } } return actionID; } } - internal class SAM_Kyuten_Shoha_Guren : CustomCombo + internal class SAM_Kyuten : CustomCombo { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_Kyuten_Shoha; + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_Kyuten; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { @@ -976,11 +1016,16 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Kyuten) { - if (IsEnabled(CustomComboPreset.SAM_Kyuten_Shoha_Guren) && + if (IsEnabled(CustomComboPreset.SAM_Kyuten_Guren) && ActionReady(Guren)) return Guren; - if (gauge.MeditationStacks is 3 && ActionReady(Shoha)) + if (IsEnabled(CustomComboPreset.SAM_Kyuten_Zanshin) && + HasEffect(Buffs.ZanshinReady)) + return Zanshin; + + if (IsEnabled(CustomComboPreset.SAM_Kyuten_Shoha) && + gauge.MeditationStacks is 3 && ActionReady(Shoha)) return Shoha; } @@ -988,9 +1033,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } } - internal class SAM_Ikishoten_OgiNamikiri : CustomCombo + internal class SAM_Ikishoten : CustomCombo { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_Ikishoten_OgiNamikiri; + protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.SAM_Ikishoten; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { @@ -998,8 +1043,19 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (actionID is Ikishoten) { - if ((LevelChecked(OgiNamikiri) && HasEffect(Buffs.OgiNamikiriReady)) || gauge.Kaeshi == Kaeshi.NAMIKIRI) - return OriginalHook(OgiNamikiri); + if (IsEnabled(CustomComboPreset.SAM_Ikishoten)) + { + if (IsEnabled(CustomComboPreset.SAM_Ikishoten_Shoha) && + ActionReady(Shoha) && + HasEffect(Buffs.OgiNamikiriReady) && + gauge.MeditationStacks is 3) + return Shoha; + + if (IsEnabled(CustomComboPreset.SAM_Ikishoten_Namikiri) && + (LevelChecked(OgiNamikiri) && HasEffect(Buffs.OgiNamikiriReady)) || + gauge.Kaeshi == Kaeshi.NAMIKIRI) + return OriginalHook(OgiNamikiri); + } } return actionID; } diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index 4c07d5b28..dacd3bf4f 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -1,5 +1,4 @@ using Dalamud.Game.ClientState.JobGauge.Types; -using ECommons.DalamudServices; using XIVSlothCombo.CustomComboNS.Functions; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; diff --git a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs index 1d407bfb2..723626f86 100644 --- a/XIVSlothCombo/Combos/PvE/WHM/WHM.cs +++ b/XIVSlothCombo/Combos/PvE/WHM/WHM.cs @@ -1,6 +1,5 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; -using ECommons.DalamudServices; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.Combos.PvE.Content; diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 5ae5f8b16..0325b66c6 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -5,15 +5,11 @@ using ECommons.DalamudServices; using ImGuiNET; using System; -using System.Linq; using System.Numerics; using XIVSlothCombo.Combos; -using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Combos.PvP; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS.Functions; -using XIVSlothCombo.Data; -using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; diff --git a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs index e5229a203..dc4e84144 100644 --- a/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs +++ b/XIVSlothCombo/Window/Tabs/AutoRotationTab.cs @@ -1,5 +1,4 @@ using Dalamud.Interface.Components; -using ECommons.DalamudServices; using ECommons.ImGuiMethods; using ImGuiNET; using XIVSlothCombo.Combos.PvE; diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 7b8101f19..5e6947c13 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -7,7 +7,6 @@ using ECommons.GameFunctions; using ECommons.GameHelpers; using ECommons.ImGuiMethods; -using ECommons.Reflection; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.UI; @@ -21,7 +20,6 @@ using XIVSlothCombo.Services; using Status = Dalamud.Game.ClientState.Statuses.Status; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -using FFXIVClientStructs.FFXIV.Client.Game.Fate; using Action = Lumina.Excel.Sheets.Action; using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using Dalamud.Utility; From 97223a20e68b09d696eb6f9f749099229e6f3890 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 17:33:44 +0000 Subject: [PATCH 206/208] More merge --- XIVSlothCombo/Combos/CustomComboPreset.cs | 5 + XIVSlothCombo/Combos/PvE/RPR/RPR.cs | 345 +++++++++++---------- XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs | 58 ++-- 3 files changed, 216 insertions(+), 192 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 69e5fc735..b00d00d70 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -3227,6 +3227,11 @@ public enum CustomComboPreset [CustomComboInfo("Enshroud Combo Option", "Adds Enshroud combo (Void/Cross Reaping, Communio, Lemure's Slice, Sacrificium and Perfectio) on Blood Stalk and Grim Swathe.", RPR.JobID)] RPR_GluttonyBloodSwathe_Enshroud = 12202, + [ParentCombo(RPR_GluttonyBloodSwathe)] + [CustomComboInfo("Sacrificium only Option", "Adds only Sacrificium on Blood Stalk and Grim Swathe while enshrouded.", RPR.JobID)] + RPR_GluttonyBloodSwathe_Sacrificium = 12203, + + // Last value = 12202 #endregion diff --git a/XIVSlothCombo/Combos/PvE/RPR/RPR.cs b/XIVSlothCombo/Combos/PvE/RPR/RPR.cs index 94d2da811..15e401751 100644 --- a/XIVSlothCombo/Combos/PvE/RPR/RPR.cs +++ b/XIVSlothCombo/Combos/PvE/RPR/RPR.cs @@ -1,8 +1,10 @@ using Dalamud.Game.ClientState.JobGauge.Types; +using System; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.Core; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.JobHelpers.RPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; @@ -95,17 +97,10 @@ public const ushort internal class RPR_ST_SimpleMode : CustomCombo { - internal static RPROpenerLogic RPROpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool trueNorthDynReady = trueNorthReady; - float GCD = GetCooldown(Slice).CooldownTotal; - if (actionID is Slice) { //Variant Cure @@ -125,18 +120,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (RPROpener.DoFullOpener(ref actionID)) return actionID; - //Arcane Circle - if (CanDelayedWeave(ActionWatching.LastWeaponskill) && - LevelChecked(ArcaneCircle) && - ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || - (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) - return ArcaneCircle; - //All Weaves if (CanWeave(ActionWatching.LastWeaponskill)) { + //Arcane Cirlce + if (LevelChecked(ArcaneCircle) && + ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || + (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) + return ArcaneCircle; + //Enshroud - if (RPRHelpers.UseEnshroud(Gauge)) + if (RPRHelper.UseEnshroud(Gauge)) return Enshroud; //Gluttony/Bloodstalk @@ -144,14 +138,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && - (GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 || !LevelChecked(ArcaneCircle)) && - !RPRHelpers.IsComboExpiring(3)) + !RPRHelper.IsComboExpiring(3)) { //Gluttony - if (!JustUsed(Perfectio) && ActionReady(Gluttony)) - { - return trueNorthReady ? All.TrueNorth : Gluttony; - } + if (ActionReady(Gluttony) && + (GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 || !LevelChecked(ArcaneCircle))) + return trueNorthReady + ? All.TrueNorth + : Gluttony; //Bloodstalk if (LevelChecked(BloodStalk) && @@ -165,7 +159,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (HasEffect(Buffs.Enshrouded)) { //Sacrificium - if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && + if (Gauge.LemureShroud is 2 && GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 && HasEffect(Buffs.Oblatio) && LevelChecked(Sacrificium)) return OriginalHook(Gluttony); @@ -176,10 +170,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Ranged Attacks - if (!InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget()) + if (!InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget() && + !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.SoulReaver)) { //Communio - if (HasEffect(Buffs.Enshrouded) && Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && + if (HasEffect(Buffs.Enshrouded) && Gauge.LemureShroud is 1 && LevelChecked(Communio)) return Communio; @@ -189,13 +184,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Shadow Of Death - if (RPRHelpers.UseShadowOfDeath()) + if (RPRHelper.UseShadowOfDeath()) return ShadowOfDeath; if (TargetHasEffect(Debuffs.DeathsDesign)) { //Perfectio - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelpers.IsComboExpiring(1)) + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelper.IsComboExpiring(1)) return OriginalHook(Communio); //Gibbet/Gallows @@ -205,7 +200,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Gibbet if (HasEffect(Buffs.EnhancedGibbet)) { - if (trueNorthDynReady && !OnTargetsFlank()) + if (trueNorthReady && !OnTargetsFlank() && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(Gibbet); @@ -215,7 +211,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (HasEffect(Buffs.EnhancedGallows) || (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) { - if (trueNorthDynReady && !OnTargetsRear()) + if (trueNorthReady && !OnTargetsRear() && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(Gallows); @@ -233,7 +230,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (HasEffect(Buffs.Enshrouded)) { //Communio - if (Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && LevelChecked(Communio)) + if (Gauge.LemureShroud is 1 && LevelChecked(Communio)) return Communio; //Void Reaping @@ -248,7 +245,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Soul Slice if (Gauge.Soul <= 50 && ActionReady(SoulSlice) && - !RPRHelpers.IsComboExpiring(3) && !JustUsed(Perfectio) && + !RPRHelper.IsComboExpiring(3) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.ImmortalSacrifice)) @@ -281,19 +278,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim internal class RPR_ST_AdvancedMode : CustomCombo { - internal static RPROpenerLogic RPROpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.RPR_ST_AdvancedMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - double enemyHP = GetTargetHPPercent(); - - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); bool trueNorthDynReady = trueNorthReady; int PositionalChoice = Config.RPR_Positional; - float GCD = GetCooldown(Slice).CooldownTotal; // Prevent the dynamic true north option from using the last charge if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && @@ -321,23 +311,21 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (RPROpener.DoFullOpener(ref actionID)) return actionID; - //Arcane Circle - if (IsEnabled(CustomComboPreset.RPR_ST_CDs) && - IsEnabled(CustomComboPreset.RPR_ST_ArcaneCircle) && - CanDelayedWeave(ActionWatching.LastWeaponskill) && - LevelChecked(ArcaneCircle) && - ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || - (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) - return ArcaneCircle; - //All Weaves if (CanWeave(ActionWatching.LastWeaponskill)) { if (IsEnabled(CustomComboPreset.RPR_ST_CDs)) { + //Arcane Cirlce + if (IsEnabled(CustomComboPreset.RPR_ST_ArcaneCircle) && + LevelChecked(ArcaneCircle) && + ((LevelChecked(Enshroud) && JustUsed(ShadowOfDeath) && IsOffCooldown(ArcaneCircle)) || + (!LevelChecked(Enshroud) && IsOffCooldown(ArcaneCircle)))) + return ArcaneCircle; + //Enshroud if (IsEnabled(CustomComboPreset.RPR_ST_Enshroud) && - RPRHelpers.UseEnshroud(Gauge)) + RPRHelper.UseEnshroud(Gauge)) return Enshroud; //Gluttony/Bloodstalk @@ -345,12 +333,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.ImmortalSacrifice) && !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.PerfectioParata) && - (GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 || !LevelChecked(ArcaneCircle)) && - !RPRHelpers.IsComboExpiring(3)) + !RPRHelper.IsComboExpiring(3)) { //Gluttony if (IsEnabled(CustomComboPreset.RPR_ST_Gluttony) && - !JustUsed(Perfectio) && ActionReady(Gluttony)) + ActionReady(Gluttony) && + (GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 || !LevelChecked(ArcaneCircle))) { if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && trueNorthReady) @@ -374,7 +362,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { //Sacrificium if (IsEnabled(CustomComboPreset.RPR_ST_Sacrificium) && - Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && + Gauge.LemureShroud is 2 && GetCooldownRemainingTime(ArcaneCircle) > GCD * 3 && HasEffect(Buffs.Oblatio) && LevelChecked(Sacrificium)) return OriginalHook(Gluttony); @@ -387,10 +375,11 @@ Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && //Ranged Attacks if (IsEnabled(CustomComboPreset.RPR_ST_RangedFiller) && - !InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget()) + !InMeleeRange() && LevelChecked(Harpe) && HasBattleTarget() && + !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.SoulReaver)) { //Communio - if (HasEffect(Buffs.Enshrouded) && Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && + if (HasEffect(Buffs.Enshrouded) && Gauge.LemureShroud is 1 && LevelChecked(Communio)) return Communio; @@ -402,14 +391,14 @@ Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && //Shadow Of Death if (IsEnabled(CustomComboPreset.RPR_ST_SoD) && - RPRHelpers.UseShadowOfDeath() && enemyHP > Config.RPR_SoDThreshold) + RPRHelper.UseShadowOfDeath() && GetTargetHPPercent() > Config.RPR_SoDThreshold) return ShadowOfDeath; if (TargetHasEffect(Debuffs.DeathsDesign)) { //Perfectio if (IsEnabled(CustomComboPreset.RPR_ST_Perfectio) && - HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelpers.IsComboExpiring(1)) + HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio) && !RPRHelper.IsComboExpiring(1)) return OriginalHook(Communio); //Gibbet/Gallows @@ -423,7 +412,8 @@ Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && !HasEffect(Buffs.EnhancedGallows))) { if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && - trueNorthDynReady && !OnTargetsFlank()) + trueNorthDynReady && !OnTargetsFlank() && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(Gibbet); @@ -435,7 +425,8 @@ Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && !HasEffect(Buffs.EnhancedGallows))) { if (IsEnabled(CustomComboPreset.RPR_ST_TrueNorthDynamic) && - trueNorthDynReady && !OnTargetsRear()) + trueNorthDynReady && !OnTargetsRear() && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(Gallows); @@ -456,7 +447,7 @@ Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && { //Communio if (IsEnabled(CustomComboPreset.RPR_ST_Communio) && - Gauge.LemureShroud is 1 && Gauge.VoidShroud is 0 && LevelChecked(Communio)) + Gauge.LemureShroud is 1 && LevelChecked(Communio)) return Communio; //Void Reaping @@ -474,7 +465,7 @@ Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && //Soul Slice if (IsEnabled(CustomComboPreset.RPR_ST_SoulSlice) && Gauge.Soul <= 50 && ActionReady(SoulSlice) && - !RPRHelpers.IsComboExpiring(3) && !JustUsed(Perfectio) && + !RPRHelper.IsComboExpiring(3) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.IdealHost) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.ImmortalSacrifice)) @@ -514,8 +505,6 @@ internal class RPR_AoE_SimpleMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - float GCD = GetCooldown(SpinningScythe).CooldownTotal; - if (actionID is SpinningScythe) { if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && @@ -553,7 +542,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (!HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.Executioner) && ActionReady(Enshroud) && (Gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && - !RPRHelpers.IsComboExpiring(6)) + !RPRHelper.IsComboExpiring(6)) return Enshroud; if (LevelChecked(Gluttony) && Gauge.Soul >= 50 && !HasEffect(Buffs.Enshrouded) && @@ -612,9 +601,6 @@ internal class RPR_AoE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - double enemyHP = GetTargetHPPercent(); - float GCD = GetCooldown(SpinningScythe).CooldownTotal; - if (actionID is SpinningScythe) { if (IsEnabled(CustomComboPreset.RPR_Variant_Cure) && @@ -631,7 +617,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.RPR_AoE_WoD) && LevelChecked(WhorlOfDeath) && GetDebuffRemainingTime(Debuffs.DeathsDesign) < 6 && !HasEffect(Buffs.SoulReaver) && - enemyHP > Config.RPR_WoDThreshold) + GetTargetHPPercent() > Config.RPR_WoDThreshold) return WhorlOfDeath; if (TargetHasEffect(Debuffs.DeathsDesign)) @@ -658,7 +644,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.RPR_AoE_Enshroud) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Enshrouded) && ActionReady(Enshroud) && (Gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && - !RPRHelpers.IsComboExpiring(6)) + !RPRHelper.IsComboExpiring(6)) return Enshroud; if (IsEnabled(CustomComboPreset.RPR_AoE_Gluttony) && @@ -735,86 +721,102 @@ internal class RPR_GluttonyBloodSwathe : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth); - - if (actionID is GrimSwathe) + switch (actionID) { - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) - { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); - - if (HasEffect(Buffs.Enshrouded)) + case GrimSwathe: { - if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) + { + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); - if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) - return OriginalHook(Gluttony); + if (HasEffect(Buffs.Enshrouded)) + { + switch (Gauge.LemureShroud) + { + case 1 when Gauge.VoidShroud == 0 && LevelChecked(Communio): + return Communio; - if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe)) - return OriginalHook(GrimSwathe); + case 2 when Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio): + return OriginalHook(Gluttony); + } - if (Gauge.LemureShroud > 1) - return OriginalHook(Guillotine); - } - } + if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe)) + return OriginalHook(GrimSwathe); - if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) - return Gluttony; + if (Gauge.LemureShroud > 1) + return OriginalHook(Guillotine); + } + } - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && - (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Guillotine)) - return Guillotine; - } + if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) + return Gluttony; - if (actionID is BloodStalk) - { - if (IsEnabled(CustomComboPreset.RPR_TrueNorthGluttony) && - trueNorthReady && CanWeave(actionID)) - return All.TrueNorth; + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Sacrificium) && + HasEffect(Buffs.Enshrouded) && HasEffect(Buffs.Oblatio)) + return OriginalHook(Gluttony); - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) - { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) - return OriginalHook(Communio); + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && + (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Guillotine)) + return Guillotine; - if (HasEffect(Buffs.Enshrouded)) + break; + } + + case BloodStalk when IsEnabled(CustomComboPreset.RPR_TrueNorthGluttony) && + trueNorthReady: + return All.TrueNorth; + + case BloodStalk: { - if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Enshroud)) + { + if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + return OriginalHook(Communio); - if (Gauge.LemureShroud is 2 && Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio)) - return OriginalHook(Gluttony); + if (HasEffect(Buffs.Enshrouded)) + { + switch (Gauge.LemureShroud) + { + case 1 when Gauge.VoidShroud == 0 && LevelChecked(Communio): + return Communio; - if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) - return OriginalHook(BloodStalk); + case 2 when Gauge.VoidShroud is 1 && HasEffect(Buffs.Oblatio): + return OriginalHook(Gluttony); + } - if (HasEffect(Buffs.EnhancedVoidReaping)) - return OriginalHook(Gibbet); + if (Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice)) + return OriginalHook(BloodStalk); - if (HasEffect(Buffs.EnhancedCrossReaping)) - return OriginalHook(Gallows); + if (HasEffect(Buffs.EnhancedVoidReaping)) + return OriginalHook(Gibbet); - if (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping)) - return OriginalHook(Gallows); - } - } + if (HasEffect(Buffs.EnhancedCrossReaping) || + (!HasEffect(Buffs.EnhancedCrossReaping) && !HasEffect(Buffs.EnhancedVoidReaping))) + return OriginalHook(Gallows); + } + } - if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) - return Gluttony; + if (ActionReady(Gluttony) && !HasEffect(Buffs.Enshrouded) && !HasEffect(Buffs.SoulReaver)) + return Gluttony; - if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && - (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Gibbet)) - { - if (HasEffect(Buffs.EnhancedGibbet)) - return OriginalHook(Gibbet); + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_Sacrificium) && + HasEffect(Buffs.Enshrouded) && HasEffect(Buffs.Oblatio)) + return OriginalHook(Gluttony); - if (HasEffect(Buffs.EnhancedGallows) || - (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - return OriginalHook(Gallows); - } + if (IsEnabled(CustomComboPreset.RPR_GluttonyBloodSwathe_BloodSwatheCombo) && + (HasEffect(Buffs.SoulReaver) || HasEffect(Buffs.Executioner)) && LevelChecked(Gibbet)) + { + if (HasEffect(Buffs.EnhancedGibbet)) + return OriginalHook(Gibbet); + + if (HasEffect(Buffs.EnhancedGallows) || + (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) + return OriginalHook(Gallows); + } + + break; + } } return actionID; @@ -828,11 +830,10 @@ internal class RPR_ArcaneCirclePlentifulHarvest : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - if (actionID is ArcaneCircle) - if (HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest)) - return PlentifulHarvest; - - return actionID; + return actionID is ArcaneCircle && + HasEffect(Buffs.ImmortalSacrifice) && LevelChecked(PlentifulHarvest) + ? PlentifulHarvest + : actionID; } } @@ -854,7 +855,7 @@ internal class RPR_Soulsow : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool[] soulSowOptions = PluginConfiguration.GetCustomBoolArrayValue(Config.RPR_SoulsowOptions); + bool[] soulSowOptions = Config.RPR_SoulsowOptions; bool soulsowReady = LevelChecked(Soulsow) && !HasEffect(Buffs.Soulsow); return (soulSowOptions.Length > 0 && ((actionID is Harpe && soulSowOptions[0]) || @@ -875,24 +876,26 @@ internal class RPR_EnshroudProtection : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth); - - if (actionID is Enshroud) + switch (actionID) { - if (IsEnabled(CustomComboPreset.RPR_TrueNorthEnshroud) && - GetBuffStacks(Buffs.SoulReaver) is 2 && trueNorthReady && CanDelayedWeave(Slice)) + case Enshroud when IsEnabled(CustomComboPreset.RPR_TrueNorthEnshroud) && + GetBuffStacks(Buffs.SoulReaver) is 2 && trueNorthReady && CanDelayedWeave(Slice): return All.TrueNorth; - if (HasEffect(Buffs.SoulReaver)) - { - if (HasEffect(Buffs.EnhancedGibbet)) - return OriginalHook(Gibbet); + case Enshroud: + { + if (HasEffect(Buffs.SoulReaver)) + { + if (HasEffect(Buffs.EnhancedGibbet)) + return OriginalHook(Gibbet); - if (HasEffect(Buffs.EnhancedGallows) || - (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) - return OriginalHook(Gallows); - } + if (HasEffect(Buffs.EnhancedGallows) || + (!HasEffect(Buffs.EnhancedGibbet) && !HasEffect(Buffs.EnhancedGallows))) + return OriginalHook(Gallows); + } + + break; + } } return actionID; @@ -905,24 +908,31 @@ internal class RPR_CommunioOnGGG : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - if (actionID is Gibbet or Gallows && HasEffect(Buffs.Enshrouded)) + switch (actionID) { - if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + case Gibbet or Gallows when HasEffect(Buffs.Enshrouded): + { + if (Gauge is { LemureShroud: 1, VoidShroud: 0 } && LevelChecked(Communio)) + return Communio; - if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && - Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice) && CanWeave(actionID)) - return OriginalHook(BloodStalk); - } + if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && + Gauge.VoidShroud >= 2 && LevelChecked(LemuresSlice) && CanWeave(actionID)) + return OriginalHook(BloodStalk); - if (actionID is Guillotine && HasEffect(Buffs.Enshrouded)) - { - if (Gauge.LemureShroud == 1 && Gauge.VoidShroud == 0 && LevelChecked(Communio)) - return Communio; + break; + } + + case Guillotine when HasEffect(Buffs.Enshrouded): + { + if (Gauge is { LemureShroud: 1, VoidShroud: 0 } && LevelChecked(Communio)) + return Communio; + + if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && + Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) + return OriginalHook(GrimSwathe); - if (IsEnabled(CustomComboPreset.RPR_LemureOnGGG) && - Gauge.VoidShroud >= 2 && LevelChecked(LemuresScythe) && CanWeave(actionID)) - return OriginalHook(GrimSwathe); + break; + } } return actionID; @@ -935,16 +945,17 @@ internal class RPR_EnshroudCommunio : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - if (actionID is Enshroud) + switch (actionID) { - if (HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio)) + case Enshroud when HasEffect(Buffs.PerfectioParata) && LevelChecked(Perfectio): return OriginalHook(Communio); - if (HasEffect(Buffs.Enshrouded) && LevelChecked(Communio)) + case Enshroud when HasEffect(Buffs.Enshrouded) && LevelChecked(Communio): return Communio; - } - return actionID; + default: + return actionID; + } } } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs b/XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs index 89ceb000b..525faaf72 100644 --- a/XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/RPR/RPR_Helper.cs @@ -2,13 +2,24 @@ using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.RPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE; +namespace XIVSlothCombo.Combos.JobHelpers; -internal partial class RPR +internal class RPR { + // RPR Gauge & Extensions + public static float GCD = GetCooldown(Slice).CooldownTotal; + + public static RPROpenerLogic RPROpener = new(); + public static RPRGauge Gauge = GetJobGauge(); + + public static bool trueNorthReady => TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); + internal class RPROpenerLogic { private OpenerState currentState = OpenerState.PrePull; @@ -202,43 +213,32 @@ public bool DoFullOpener(ref uint actionID) } } - internal class RPRHelpers + internal class RPRHelper { public static unsafe bool IsComboExpiring(float Times) { float GCD = GetCooldown(Slice).CooldownTotal * Times; - if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) - return true; - - return false; + return ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD; } public static bool IsBuffExpiring(float Times) { float GCD = GetCooldown(Slice).CooldownTotal * Times; - if ((HasEffect(Buffs.EnhancedGallows) && GetBuffRemainingTime(Buffs.EnhancedGallows) < GCD) || - (HasEffect(Buffs.EnhancedGibbet) && GetBuffRemainingTime(Buffs.EnhancedGibbet) < GCD)) - return true; - - return false; + return (HasEffect(Buffs.EnhancedGallows) && GetBuffRemainingTime(Buffs.EnhancedGallows) < GCD) || + (HasEffect(Buffs.EnhancedGibbet) && GetBuffRemainingTime(Buffs.EnhancedGibbet) < GCD); } public static bool IsDebuffExpiring(float Times) { float GCD = GetCooldown(Slice).CooldownTotal * Times; - if (TargetHasEffect(Debuffs.DeathsDesign) && GetDebuffRemainingTime(Debuffs.DeathsDesign) < GCD) - return true; - - return false; + return TargetHasEffect(Debuffs.DeathsDesign) && GetDebuffRemainingTime(Debuffs.DeathsDesign) < GCD; } public static bool UseEnshroud(RPRGauge gauge) { - float GCD = GetCooldown(Slice).CooldownTotal; - if (LevelChecked(Enshroud) && (gauge.Shroud >= 50 || HasEffect(Buffs.IdealHost)) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && !HasEffect(Buffs.Enshrouded)) @@ -258,7 +258,7 @@ public static bool UseEnshroud(RPRGauge gauge) //2nd part of Double Enshroud if (LevelChecked(PlentifulHarvest) && - WasLastWeaponskill(PlentifulHarvest)) + JustUsed(PlentifulHarvest, 5)) return true; //Natural Odd Minute Shrouds @@ -277,29 +277,37 @@ public static bool UseEnshroud(RPRGauge gauge) public static bool UseShadowOfDeath() { - float GCD = GetCooldown(Slice).CooldownTotal; - if (LevelChecked(ShadowOfDeath) && !HasEffect(Buffs.SoulReaver) && !HasEffect(Buffs.Executioner) && !HasEffect(Buffs.PerfectioParata) && - !HasEffect(Buffs.ImmortalSacrifice) && !IsComboExpiring(1) && !JustUsed(Perfectio) && + !HasEffect(Buffs.ImmortalSacrifice) && !IsComboExpiring(3) && !JustUsed(ShadowOfDeath)) { + //1st part double enshroud if (LevelChecked(PlentifulHarvest) && HasEffect(Buffs.Enshrouded) && GetCooldownRemainingTime(ArcaneCircle) <= GCD * 2 + 1.5 && JustUsed(Enshroud)) return true; + //2nd part double enshroud if (LevelChecked(PlentifulHarvest) && HasEffect(Buffs.Enshrouded) && (GetCooldownRemainingTime(ArcaneCircle) <= GCD || IsOffCooldown(ArcaneCircle)) && (JustUsed(VoidReaping) || JustUsed(CrossReaping))) return true; - if (!HasEffect(Buffs.Enshrouded) && + //lvl 88+ general use + if (LevelChecked(PlentifulHarvest) && !HasEffect(Buffs.Enshrouded) && ((IsEnabled(CustomComboPreset.RPR_ST_SimpleMode) && GetDebuffRemainingTime(Debuffs.DeathsDesign) <= 8) || (IsEnabled(CustomComboPreset.RPR_ST_AdvancedMode) && GetDebuffRemainingTime(Debuffs.DeathsDesign) <= Config.RPR_SoDRefreshRange)) && - (GetCooldownRemainingTime(ArcaneCircle) > GCD * 8 || IsOffCooldown(ArcaneCircle) || - !LevelChecked(ArcaneCircle))) + (GetCooldownRemainingTime(ArcaneCircle) > GCD * 8 || IsOffCooldown(ArcaneCircle))) + return true; + + //below lvl 88 use + if (!LevelChecked(PlentifulHarvest) && + ((IsEnabled(CustomComboPreset.RPR_ST_SimpleMode) && + GetDebuffRemainingTime(Debuffs.DeathsDesign) <= 8) || + (IsEnabled(CustomComboPreset.RPR_ST_AdvancedMode) && + GetDebuffRemainingTime(Debuffs.DeathsDesign) <= Config.RPR_SoDRefreshRange))) return true; } From 5f18132a356992e3303c316659ef7242daf30af8 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 17 Nov 2024 17:39:11 +0000 Subject: [PATCH 207/208] Merges --- XIVSlothCombo/Combos/CustomComboPreset.cs | 8 + XIVSlothCombo/Combos/PvE/VPR/VPR.cs | 332 ++++++++++----------- XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs | 115 +++---- 3 files changed, 220 insertions(+), 235 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index b00d00d70..b36ee63f6 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -4499,6 +4499,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Vicewinder Combo", "Adds Swiftskin's Coil and Hunter's Coil to the rotation.\nWill automatically swap depending on your position.", VPR.JobID)] VPR_ST_VicewinderCombo = 30007, + [ParentCombo(VPR_ST_CDs)] + [CustomComboInfo("Vicewinder Weaves", "Adds Twinfang and Bloodfang to the rotation.", VPR.JobID)] + VPR_ST_VicewinderWeaves = 30013, + #endregion [ParentCombo(VPR_ST_AdvancedMode)] @@ -4580,6 +4584,10 @@ The three digets after RDM.JobID can be used to reorder items in the list [CustomComboInfo("Disable Range Check", "Disables the range check for Swiftskin's Den and Hunter's Den, so they will be used even without a target selected.", VPR.JobID)] VPR_AoE_VicepitCombo_DisableRange = 30113, + [ParentCombo(VPR_AoE_CDs)] + [CustomComboInfo("Vicepit Weaves", "Adds Twinfang and Twinblood to the rotation.", VPR.JobID)] + VPR_AoE_VicepitWeaves = 30115, + #endregion [ParentCombo(VPR_AoE_AdvancedMode)] diff --git a/XIVSlothCombo/Combos/PvE/VPR/VPR.cs b/XIVSlothCombo/Combos/PvE/VPR/VPR.cs index 2e448025d..50159b036 100644 --- a/XIVSlothCombo/Combos/PvE/VPR/VPR.cs +++ b/XIVSlothCombo/Combos/PvE/VPR/VPR.cs @@ -1,8 +1,10 @@ using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.JobGauge.Types; +using System; using XIVSlothCombo.Combos.PvE.Content; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.JobHelpers.VPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; namespace XIVSlothCombo.Combos.PvE; @@ -97,26 +99,12 @@ public const uint internal class VPR_ST_SimpleMode : CustomCombo { - internal static VPROpenerLogic VPROpener = new(); - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.VPR_ST_SimpleMode; protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int RattlingCoils = gauge.RattlingCoilStacks; - float ireCD = GetCooldownRemainingTime(SerpentsIre); - - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; - bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; - bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; bool in5y = GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || - (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - if (actionID is SteelFangs) { // Opener for VPR @@ -156,17 +144,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return OriginalHook(Twinblood); //Vice Twin Weaves - if (!HasEffect(Buffs.Reawakened)) - - //Vicewinder weaves - if (in5y) - { - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); + if (!HasEffect(Buffs.Reawakened) && in5y) + { + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - } + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + } } // Death Rattle - Force to avoid loss @@ -175,7 +160,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //GCDs if (LevelChecked(WrithingSnap) && !InMeleeRange() && HasBattleTarget()) - return VPRHelpers.HasRattlingCoilStack(gauge) + return HasRattlingCoilStack(gauge) ? UncoiledFury : WrithingSnap; @@ -192,33 +177,32 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Reawakend Usage - if (VPRHelpers.UseReawaken(gauge)) + if (VPRHelper.UseReawaken(gauge)) return Reawaken; //Overcap protection if (CappedOnCoils && - ((HasCharges(Vicewinder) && !HasEffect(Buffs.SwiftskinsVenom) && - !HasEffect(Buffs.HuntersVenom) && + ((HasCharges(Vicewinder) && !HasEffect(Buffs.SwiftskinsVenom) && !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.Reawakened)) || //spend if Vicewinder is up, after Reawaken ireCD <= GCD * 5)) //spend in case under Reawaken right as Ire comes up return UncoiledFury; //Vicewinder Usage - if (HasEffect(Buffs.Swiftscaled) && !VPRCheckTimers.IsComboExpiring(3) && + if (HasEffect(Buffs.Swiftscaled) && !VPRHelper.IsComboExpiring(3) && ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && (ireCD >= GCD * 5 || !LevelChecked(SerpentsIre)) && - !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) + !VPRHelper.IsVenomExpiring(3) && !VPRHelper.IsHoningExpiring(3)) return Vicewinder; // Uncoiled Fury usage - if (LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && - HasEffect(Buffs.HuntersInstinct) && !VPRCheckTimers.IsComboExpiring(2) && - RattlingCoils > 1 && + if (LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && + !VPRHelper.IsComboExpiring(2) && + gauge.RattlingCoilStacks > 1 && !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && !WasLastWeaponskill(Ouroboros) && - !VPRCheckTimers.IsEmpowermentExpiring(6) && !VPRCheckTimers.IsVenomExpiring(3) && - !VPRCheckTimers.IsHoningExpiring(3)) + !VPRHelper.IsEmpowermentExpiring(6) && !VPRHelper.IsVenomExpiring(3) && + !VPRHelper.IsHoningExpiring(3)) return UncoiledFury; //Reawaken combo @@ -282,10 +266,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if ((HasEffect(Buffs.FlankstungVenom) || HasEffect(Buffs.HindstungVenom)) && LevelChecked(FlanksbaneFang)) { - if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom)) + if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; - if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom)) + if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(SteelFangs); @@ -295,11 +281,11 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim LevelChecked(HindstingStrike)) { if (trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindsbaneVenom) && - CanDelayedWeave(actionID)) + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; if (trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlanksbaneVenom) && - CanDelayedWeave(actionID)) + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(ReavingFangs); @@ -331,21 +317,11 @@ internal class VPR_ST_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { int uncoiledThreshold = Config.VPR_ST_UncoiledFury_Threshold; - int RattlingCoils = gauge.RattlingCoilStacks; + float enemyHP = GetTargetHPPercent(); - float ireCD = GetCooldownRemainingTime(SerpentsIre); - bool trueNorthReady = TargetNeedsPositionals() && ActionReady(All.TrueNorth) && - !HasEffect(All.Buffs.TrueNorth) && CanDelayedWeave(actionID); - bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; - bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; - bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; bool in5y = GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || - (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - if (actionID is SteelFangs) { // Variant Cure @@ -396,18 +372,16 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Vice Twin Weaves - if (!HasEffect(Buffs.Reawakened)) - if (IsEnabled(CustomComboPreset.VPR_ST_CDs)) - - //Vicewinder weaves - if (IsEnabled(CustomComboPreset.VPR_ST_VicewinderCombo) && in5y) - { - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); + if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && + IsEnabled(CustomComboPreset.VPR_ST_VicewinderWeaves) && + !HasEffect(Buffs.Reawakened) && in5y) + { + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - } + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + } } // Death Rattle - Force to avoid loss @@ -419,7 +393,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (IsEnabled(CustomComboPreset.VPR_ST_RangedUptime) && LevelChecked(WrithingSnap) && !InMeleeRange() && HasBattleTarget()) return IsEnabled(CustomComboPreset.VPR_ST_RangedUptimeUncoiledFury) && - VPRHelpers.HasRattlingCoilStack(gauge) + HasRattlingCoilStack(gauge) ? UncoiledFury : WrithingSnap; @@ -438,7 +412,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim } //Reawakend Usage - if (IsEnabled(CustomComboPreset.VPR_ST_Reawaken) && VPRHelpers.UseReawaken(gauge)) + if (IsEnabled(CustomComboPreset.VPR_ST_Reawaken) && VPRHelper.UseReawaken(gauge)) return Reawaken; //Overcap protection @@ -451,21 +425,21 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Vicewinder Usage if (IsEnabled(CustomComboPreset.VPR_ST_CDs) && IsEnabled(CustomComboPreset.VPR_ST_Vicewinder) && HasEffect(Buffs.Swiftscaled) && - !VPRCheckTimers.IsComboExpiring(3) && + !VPRHelper.IsComboExpiring(3) && ActionReady(Vicewinder) && !HasEffect(Buffs.Reawakened) && InMeleeRange() && (ireCD >= GCD * 5 || !LevelChecked(SerpentsIre)) && - !VPRCheckTimers.IsVenomExpiring(3) && !VPRCheckTimers.IsHoningExpiring(3)) + !VPRHelper.IsVenomExpiring(3) && !VPRHelper.IsHoningExpiring(3)) return Vicewinder; // Uncoiled Fury usage - if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && !VPRCheckTimers.IsComboExpiring(2) && + if (IsEnabled(CustomComboPreset.VPR_ST_UncoiledFury) && !VPRHelper.IsComboExpiring(2) && LevelChecked(UncoiledFury) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && - (RattlingCoils > Config.VPR_ST_UncoiledFury_HoldCharges || - (enemyHP < uncoiledThreshold && VPRHelpers.HasRattlingCoilStack(gauge))) && + (gauge.RattlingCoilStacks > Config.VPR_ST_UncoiledFury_HoldCharges || + (enemyHP < uncoiledThreshold && HasRattlingCoilStack(gauge))) && !VicewinderReady && !HuntersCoilReady && !SwiftskinsCoilReady && !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.ReadyToReawaken) && !WasLastWeaponskill(Ouroboros) && - !VPRCheckTimers.IsEmpowermentExpiring(3)) + !VPRHelper.IsEmpowermentExpiring(3)) return UncoiledFury; //Reawaken combo @@ -541,11 +515,13 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim LevelChecked(FlanksbaneFang)) { if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && - trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom)) + trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindstungVenom) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && - trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom)) + trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlankstungVenom) && + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(SteelFangs); @@ -556,12 +532,12 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && trueNorthReady && !OnTargetsRear() && HasEffect(Buffs.HindsbaneVenom) && - CanDelayedWeave(actionID)) + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; if (IsEnabled(CustomComboPreset.VPR_TrueNorthDynamic) && trueNorthReady && !OnTargetsFlank() && HasEffect(Buffs.FlanksbaneVenom) && - CanDelayedWeave(actionID)) + CanDelayedWeave(ActionWatching.LastWeaponskill)) return All.TrueNorth; return OriginalHook(ReavingFangs); @@ -590,17 +566,8 @@ internal class VPR_AoE_Simplemode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int RattlingCoils = gauge.RattlingCoilStacks; - float ireCD = GetCooldownRemainingTime(SerpentsIre); - bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; - bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; - bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || - (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - if (actionID is SteelMaw) { if (CanWeave(ActionWatching.LastWeaponskill)) @@ -679,7 +646,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Uncoiled Fury usage if (LevelChecked(UncoiledFury) && - VPRHelpers.HasRattlingCoilStack(gauge) && + HasRattlingCoilStack(gauge) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && !VicepitReady && !HuntersDenReady && !SwiftskinsDenReady && !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellskinsVenom) && @@ -782,18 +749,8 @@ internal class VPR_AoE_AdvancedMode : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { int uncoiledThreshold = Config.VPR_AoE_UncoiledFury_Threshold; - int RattlingCoils = gauge.RattlingCoilStacks; - float enemyHP = GetTargetHPPercent(); - float ireCD = GetCooldownRemainingTime(SerpentsIre); - bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; - bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; - bool HuntersDenReady = gauge.DreadCombo == DreadCombo.HuntersDen; bool in5y = HasBattleTarget() && GetTargetDistance() <= 5; - bool CappedOnCoils = (TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 2) || - (!TraitLevelChecked(Traits.EnhancedVipersRattle) && RattlingCoils > 1); - float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; - if (actionID is SteelMaw) { // Variant Cure @@ -836,7 +793,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim !HasEffect(Buffs.Reawakened)) { //Vicepit weaves - if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo) && + if (IsEnabled(CustomComboPreset.VPR_AoE_VicepitWeaves) && (in5y || IsEnabled(CustomComboPreset.VPR_AoE_VicepitCombo_DisableRange))) { if (HasEffect(Buffs.FellhuntersVenom)) @@ -893,8 +850,9 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim // Uncoiled Fury usage if (IsEnabled(CustomComboPreset.VPR_AoE_UncoiledFury) && LevelChecked(UncoiledFury) && - (RattlingCoils > Config.VPR_AoE_UncoiledFury_HoldCharges || - (enemyHP < uncoiledThreshold && VPRHelpers.HasRattlingCoilStack(gauge))) && + (gauge.RattlingCoilStacks > Config.VPR_AoE_UncoiledFury_HoldCharges || + (GetTargetHPPercent() < uncoiledThreshold && + HasRattlingCoilStack(gauge))) && HasEffect(Buffs.Swiftscaled) && HasEffect(Buffs.HuntersInstinct) && !VicepitReady && !HuntersDenReady && !SwiftskinsDenReady && !HasEffect(Buffs.Reawakened) && !HasEffect(Buffs.FellskinsVenom) && @@ -1001,32 +959,33 @@ internal class VPR_VicewinderCoils : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool VicewinderReady = gauge.DreadCombo == DreadCombo.Dreadwinder; - bool HuntersCoilReady = gauge.DreadCombo == DreadCombo.HuntersCoil; - bool SwiftskinsCoilReady = gauge.DreadCombo == DreadCombo.SwiftskinsCoil; - - if (actionID is Vicewinder) + switch (actionID) { - if (IsEnabled(CustomComboPreset.VPR_VicewinderCoils_oGCDs)) - { - if (HasEffect(Buffs.HuntersVenom)) - return OriginalHook(Twinfang); + case Vicewinder: + { + if (IsEnabled(CustomComboPreset.VPR_VicewinderCoils_oGCDs)) + { + if (HasEffect(Buffs.HuntersVenom)) + return OriginalHook(Twinfang); - if (HasEffect(Buffs.SwiftskinsVenom)) - return OriginalHook(Twinblood); - } + if (HasEffect(Buffs.SwiftskinsVenom)) + return OriginalHook(Twinblood); + } - // Vicewinder Combo - if (LevelChecked(Vicewinder)) - { - // Swiftskin's Coil - if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) - return SwiftskinsCoil; + // Vicewinder Combo + if (LevelChecked(Vicewinder)) + { + // Swiftskin's Coil + if ((VicewinderReady && (!OnTargetsFlank() || !TargetNeedsPositionals())) || HuntersCoilReady) + return SwiftskinsCoil; - // Hunter's Coil - if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) - return HuntersCoil; - } + // Hunter's Coil + if ((VicewinderReady && (!OnTargetsRear() || !TargetNeedsPositionals())) || SwiftskinsCoilReady) + return HuntersCoil; + } + + break; + } } return actionID; @@ -1039,25 +998,27 @@ internal class VPR_VicepitDens : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - bool VicepitReady = gauge.DreadCombo == DreadCombo.PitOfDread; - bool SwiftskinsDenReady = gauge.DreadCombo == DreadCombo.SwiftskinsDen; - - if (actionID is Vicepit) + switch (actionID) { - if (IsEnabled(CustomComboPreset.VPR_VicepitDens_oGCDs)) - { - if (HasEffect(Buffs.FellhuntersVenom)) - return OriginalHook(Twinfang); + case Vicepit: + { + if (IsEnabled(CustomComboPreset.VPR_VicepitDens_oGCDs)) + { + if (HasEffect(Buffs.FellhuntersVenom)) + return OriginalHook(Twinfang); - if (HasEffect(Buffs.FellskinsVenom)) - return OriginalHook(Twinblood); - } + if (HasEffect(Buffs.FellskinsVenom)) + return OriginalHook(Twinblood); + } - if (SwiftskinsDenReady) - return HuntersDen; + if (SwiftskinsDenReady) + return HuntersDen; - if (VicepitReady) - return SwiftskinsDen; + if (VicepitReady) + return SwiftskinsDen; + + break; + } } return actionID; @@ -1070,16 +1031,17 @@ internal class VPR_UncoiledTwins : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - if (actionID is UncoiledFury) + switch (actionID) { - if (HasEffect(Buffs.PoisedForTwinfang)) + case UncoiledFury when HasEffect(Buffs.PoisedForTwinfang): return OriginalHook(Twinfang); - if (HasEffect(Buffs.PoisedForTwinblood)) + case UncoiledFury when HasEffect(Buffs.PoisedForTwinblood): return OriginalHook(Twinblood); - } - return actionID; + default: + return actionID; + } } } @@ -1091,48 +1053,53 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { int buttonChoice = Config.VPR_ReawakenLegacyButton; - if ((buttonChoice is 0 && actionID is Reawaken && HasEffect(Buffs.Reawakened)) || - (buttonChoice is 1 && actionID is SteelFangs && HasEffect(Buffs.Reawakened))) + switch (buttonChoice) { - // Legacy Weaves - if (IsEnabled(CustomComboPreset.VPR_ReawakenLegacyWeaves) && - TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) - return OriginalHook(SerpentsTail); - - if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - switch (gauge.AnguineTribute) + case 0 when actionID is Reawaken && HasEffect(Buffs.Reawakened): + case 1 when actionID is SteelFangs && HasEffect(Buffs.Reawakened): { - case 4: - return OriginalHook(SteelFangs); + // Legacy Weaves + if (IsEnabled(CustomComboPreset.VPR_ReawakenLegacyWeaves) && + TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail) + return OriginalHook(SerpentsTail); + + if (!TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 4: + return OriginalHook(SteelFangs); - case 3: - return OriginalHook(ReavingFangs); + case 3: + return OriginalHook(ReavingFangs); - case 2: - return OriginalHook(HuntersCoil); + case 2: + return OriginalHook(HuntersCoil); - case 1: - return OriginalHook(SwiftskinsCoil); - } + case 1: + return OriginalHook(SwiftskinsCoil); + } - if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) - switch (gauge.AnguineTribute) - { - case 5: - return OriginalHook(SteelFangs); + if (TraitLevelChecked(Traits.EnhancedSerpentsLineage)) + switch (gauge.AnguineTribute) + { + case 5: + return OriginalHook(SteelFangs); - case 4: - return OriginalHook(ReavingFangs); + case 4: + return OriginalHook(ReavingFangs); - case 3: - return OriginalHook(HuntersCoil); + case 3: + return OriginalHook(HuntersCoil); - case 2: - return OriginalHook(SwiftskinsCoil); + case 2: + return OriginalHook(SwiftskinsCoil); - case 1: - return OriginalHook(Reawaken); + case 1: + return OriginalHook(Reawaken); + } + + break; } } @@ -1146,37 +1113,38 @@ internal class VPR_TwinTails : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - if (actionID is SerpentsTail) + switch (actionID) { // Death Rattle - if (LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle) + case SerpentsTail when LevelChecked(SerpentsTail) && OriginalHook(SerpentsTail) is DeathRattle: return OriginalHook(SerpentsTail); // Legacy Weaves - if (TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) - && OriginalHook(SerpentsTail) is not SerpentsTail) + case SerpentsTail when TraitLevelChecked(Traits.SerpentsLegacy) && HasEffect(Buffs.Reawakened) + && OriginalHook(SerpentsTail) is not SerpentsTail: return OriginalHook(SerpentsTail); - if (HasEffect(Buffs.PoisedForTwinfang)) + case SerpentsTail when HasEffect(Buffs.PoisedForTwinfang): return OriginalHook(Twinfang); - if (HasEffect(Buffs.PoisedForTwinblood)) + case SerpentsTail when HasEffect(Buffs.PoisedForTwinblood): return OriginalHook(Twinblood); - if (HasEffect(Buffs.HuntersVenom)) + case SerpentsTail when HasEffect(Buffs.HuntersVenom): return OriginalHook(Twinfang); - if (HasEffect(Buffs.SwiftskinsVenom)) + case SerpentsTail when HasEffect(Buffs.SwiftskinsVenom): return OriginalHook(Twinblood); - if (HasEffect(Buffs.FellhuntersVenom)) + case SerpentsTail when HasEffect(Buffs.FellhuntersVenom): return OriginalHook(Twinfang); - if (HasEffect(Buffs.FellskinsVenom)) + case SerpentsTail when HasEffect(Buffs.FellskinsVenom): return OriginalHook(Twinblood); - } - return actionID; + default: + return actionID; + } } } } \ No newline at end of file diff --git a/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs b/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs index ba6fd1522..c3af51cc7 100644 --- a/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/VPR/VPR_Helper.cs @@ -1,14 +1,46 @@ -using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.JobGauge.Enums; +using Dalamud.Game.ClientState.JobGauge.Types; using ECommons.DalamudServices; using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Combos.JobHelpers.Enums; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.Data; +using static XIVSlothCombo.Combos.PvE.VPR; using static XIVSlothCombo.CustomComboNS.Functions.CustomComboFunctions; -namespace XIVSlothCombo.Combos.PvE; +namespace XIVSlothCombo.Combos.JobHelpers; -internal partial class VPR +internal class VPR { + // VPR Gauge & Extensions + + public static float GCD = GetCooldown(OriginalHook(ReavingFangs)).CooldownTotal; + public static float ireCD = GetCooldownRemainingTime(SerpentsIre); + + public static VPROpenerLogic VPROpener = new(); + public static VPRGauge gauge = GetJobGauge(); + + public static bool trueNorthReady => TargetNeedsPositionals() && ActionReady(All.TrueNorth) && + !HasEffect(All.Buffs.TrueNorth); + + public static bool VicewinderReady => gauge.DreadCombo == DreadCombo.Dreadwinder; + + public static bool HuntersCoilReady => gauge.DreadCombo == DreadCombo.HuntersCoil; + + public static bool SwiftskinsCoilReady => gauge.DreadCombo == DreadCombo.SwiftskinsCoil; + + public static bool VicepitReady => gauge.DreadCombo == DreadCombo.PitOfDread; + + public static bool SwiftskinsDenReady => gauge.DreadCombo == DreadCombo.SwiftskinsDen; + + public static bool HuntersDenReady => gauge.DreadCombo == DreadCombo.HuntersDen; + + public static bool CappedOnCoils => + (TraitLevelChecked(Traits.EnhancedVipersRattle) && gauge.RattlingCoilStacks > 2) || + (!TraitLevelChecked(Traits.EnhancedVipersRattle) && gauge.RattlingCoilStacks > 1); + + public static bool HasRattlingCoilStack(VPRGauge Gauge) => Gauge.RattlingCoilStacks > 0; + internal class VPROpenerLogic { private OpenerState currentState = OpenerState.PrePull; @@ -247,80 +279,57 @@ public bool DoFullOpener(ref uint actionID) } } - internal class VPRCheckTimers + internal class VPRHelper { - public static bool IsHoningExpiring(float Times) + public static bool UseReawaken(VPRGauge gauge) { - float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; + float ireCD = GetCooldownRemainingTime(SerpentsIre); - if ((HasEffect(Buffs.HonedSteel) && GetBuffRemainingTime(Buffs.HonedSteel) < GCD) || - (HasEffect(Buffs.HonedReavers) && GetBuffRemainingTime(Buffs.HonedReavers) < GCD)) - return true; + if (LevelChecked(Reawaken) && !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && + !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.SwiftskinsVenom) && + !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang) && + !IsEmpowermentExpiring(6)) + if ((!JustUsed(SerpentsIre, 2.2f) && HasEffect(Buffs.ReadyToReawaken)) || //2min burst + (WasLastWeaponskill(Ouroboros) && gauge.SerpentOffering >= 50 && ireCD >= 50) || //2nd RA + (gauge.SerpentOffering is >= 50 and <= 80 && ireCD is >= 50 and <= 62) || //1min + gauge.SerpentOffering >= 100 || //overcap + (gauge.SerpentOffering >= 50 && WasLastWeaponskill(FourthGeneration) && + !LevelChecked(Ouroboros))) //<100 + return true; return false; } - public static bool IsVenomExpiring(float Times) + public static bool IsHoningExpiring(float Times) { float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - if ((HasEffect(Buffs.FlankstungVenom) && GetBuffRemainingTime(Buffs.FlankstungVenom) < GCD) || - (HasEffect(Buffs.FlanksbaneVenom) && GetBuffRemainingTime(Buffs.FlanksbaneVenom) < GCD) || - (HasEffect(Buffs.HindstungVenom) && GetBuffRemainingTime(Buffs.HindstungVenom) < GCD) || - (HasEffect(Buffs.HindsbaneVenom) && GetBuffRemainingTime(Buffs.HindsbaneVenom) < GCD)) - return true; - - return false; + return (HasEffect(Buffs.HonedSteel) && GetBuffRemainingTime(Buffs.HonedSteel) < GCD) || + (HasEffect(Buffs.HonedReavers) && GetBuffRemainingTime(Buffs.HonedReavers) < GCD); } - public static bool IsEmpowermentExpiring(float Times) + public static bool IsVenomExpiring(float Times) { float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - if (GetBuffRemainingTime(Buffs.Swiftscaled) < GCD || GetBuffRemainingTime(Buffs.HuntersInstinct) < GCD) - return true; - - return false; + return (HasEffect(Buffs.FlankstungVenom) && GetBuffRemainingTime(Buffs.FlankstungVenom) < GCD) || + (HasEffect(Buffs.FlanksbaneVenom) && GetBuffRemainingTime(Buffs.FlanksbaneVenom) < GCD) || + (HasEffect(Buffs.HindstungVenom) && GetBuffRemainingTime(Buffs.HindstungVenom) < GCD) || + (HasEffect(Buffs.HindsbaneVenom) && GetBuffRemainingTime(Buffs.HindsbaneVenom) < GCD); } - public static unsafe bool IsComboExpiring(float Times) + public static bool IsEmpowermentExpiring(float Times) { float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - if (ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD) - return true; - - return false; - } - } - - internal class VPRHelpers - { - public static bool HasRattlingCoilStack(VPRGauge gauge) - { - if (gauge.RattlingCoilStacks > 0) - return true; - - return false; + return GetBuffRemainingTime(Buffs.Swiftscaled) < GCD || GetBuffRemainingTime(Buffs.HuntersInstinct) < GCD; } - internal static bool UseReawaken(VPRGauge gauge) + public static unsafe bool IsComboExpiring(float Times) { - float ireCD = GetCooldownRemainingTime(SerpentsIre); - - if (LevelChecked(Reawaken) && !HasEffect(Buffs.Reawakened) && InActionRange(Reawaken) && - !HasEffect(Buffs.HuntersVenom) && !HasEffect(Buffs.SwiftskinsVenom) && - !HasEffect(Buffs.PoisedForTwinblood) && !HasEffect(Buffs.PoisedForTwinfang) && - !VPRCheckTimers.IsEmpowermentExpiring(6)) - if ((!JustUsed(SerpentsIre, 2.2f) && HasEffect(Buffs.ReadyToReawaken)) || //2min burst - (WasLastWeaponskill(Ouroboros) && gauge.SerpentOffering >= 50 && ireCD >= 50) || //2nd RA - (gauge.SerpentOffering is >= 50 and <= 80 && ireCD is >= 50 and <= 62) || //1min - gauge.SerpentOffering >= 100 || //overcap - (gauge.SerpentOffering >= 50 && WasLastWeaponskill(FourthGeneration) && - !LevelChecked(Ouroboros))) //<100 - return true; + float GCD = GetCooldown(SteelFangs).CooldownTotal * Times; - return false; + return ActionManager.Instance()->Combo.Timer != 0 && ActionManager.Instance()->Combo.Timer < GCD; } } } \ No newline at end of file From 659b60a08fa92de885a3d204d460f25ffd0db3fc Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Mon, 18 Nov 2024 17:53:06 +0000 Subject: [PATCH 208/208] v1.0.0.0 --- XIVSlothCombo/XIVSlothCombo.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XIVSlothCombo/XIVSlothCombo.csproj b/XIVSlothCombo/XIVSlothCombo.csproj index 0f7c70384..02236d449 100644 --- a/XIVSlothCombo/XIVSlothCombo.csproj +++ b/XIVSlothCombo/XIVSlothCombo.csproj @@ -4,7 +4,7 @@ Team Wrath - - 0.0.0.11 + 1.0.0.0 XIVCombo for lazy players Copyleft attick 2021 thanks attick UwU