From 8e1cb23495b043aa36e4a378529ccd1a12db5d13 Mon Sep 17 00:00:00 2001 From: LTS-FFXIV <127939494+LTS-FFXIV@users.noreply.github.com> Date: Mon, 6 Jan 2025 06:43:39 -0600 Subject: [PATCH] Enhance healing and defense logic, update configurations - Added checks for various PvE abilities in SCH_Default class methods. - Updated countdown and emergency logic in SGE_Default class. - Streamlined HealAreaAbility method in SGE_Default class. - Added new configuration options in WAR_Default class. - Improved null handling and readability in ObjectHelper class. - Modified action settings in SageRotation and WarriorRotation classes. - Updated RotationConfigWindow to include buttons for copying plugin repos. --- BasicRotations/Healer/SCH_Default.cs | 15 ++++++-- BasicRotations/Healer/SGE_Default.cs | 38 ++++++++++--------- BasicRotations/Tank/WAR_Default.cs | 37 ++++++++++++++++-- RotationSolver.Basic/Helpers/ObjectHelper.cs | 7 ++-- .../Rotations/Basic/SageRotation.cs | 1 + .../Rotations/Basic/WarriorRotation.cs | 8 +++- RotationSolver/UI/RotationConfigWindow.cs | 30 ++++++++++----- 7 files changed, 97 insertions(+), 39 deletions(-) diff --git a/BasicRotations/Healer/SCH_Default.cs b/BasicRotations/Healer/SCH_Default.cs index 030f214f9..50d5415ea 100644 --- a/BasicRotations/Healer/SCH_Default.cs +++ b/BasicRotations/Healer/SCH_Default.cs @@ -99,13 +99,16 @@ protected override bool HealAreaAbility(IAction nextGCD, out IAction? act) protected override bool HealSingleAbility(IAction nextGCD, out IAction? act) { var haveLink = PartyMembers.Any(p => p.HasStatus(true, StatusID.FeyUnion_1223)); - if (ManifestationPvE.CanUse(out act)) return true; - if (AetherpactPvE.CanUse(out act) && FairyGauge >= 70 && !haveLink) return true; if (ProtractionPvE.CanUse(out act)) return true; + if (IsLastAbility(ActionID.RecitationPvE) && ExcogitationPvE.CanUse(out act)) return true; + + if (AetherpactPvE.CanUse(out act) && FairyGauge >= 70 && !haveLink) return true; if (ExcogitationPvE.CanUse(out act)) return true; if (LustratePvE.CanUse(out act)) return true; if (AetherpactPvE.CanUse(out act) && !haveLink) return true; + if (ExcogitationPvE.CanUse(out act)) return true; + return base.HealSingleAbility(nextGCD, out act); } @@ -172,6 +175,8 @@ protected override bool HealAreaGCD(out IAction? act) if (HasSwift && SwiftLogic && ResurrectionPvE.CanUse(out _)) return false; if (SuccorPvE.CanUse(out act)) return true; + if (ConcitationPvE.CanUse(out act, skipCastingCheck: true)) return true; + if (AccessionPvE.CanUse(out act)) return true; return base.HealAreaGCD(out act); } @@ -182,8 +187,9 @@ protected override bool HealSingleGCD(out IAction? act) act = null; if (HasSwift && SwiftLogic && ResurrectionPvE.CanUse(out _)) return false; - + if (AdloquiumPvE.CanUse(out act)) return true; + if (ManifestationPvE.CanUse(out act, skipCastingCheck: true)) return true; if (PhysickPvE.CanUse(out act)) return true; return base.HealSingleGCD(out act); @@ -197,6 +203,9 @@ protected override bool DefenseAreaGCD(out IAction? act) if (HasSwift && SwiftLogic && ResurrectionPvE.CanUse(out _)) return false; if (SuccorPvE.CanUse(out act)) return true; + if (ConcitationPvE.CanUse(out act, skipCastingCheck: true)) return true; + if (AccessionPvE.CanUse(out act)) return true; + return base.DefenseAreaGCD(out act); } diff --git a/BasicRotations/Healer/SGE_Default.cs b/BasicRotations/Healer/SGE_Default.cs index ee876d080..b35207af6 100644 --- a/BasicRotations/Healer/SGE_Default.cs +++ b/BasicRotations/Healer/SGE_Default.cs @@ -65,9 +65,10 @@ public sealed class SGE_Default : SageRotation #region Countdown Logic protected override IAction? CountDownAction(float remainTime) { - if (remainTime < DosisPvE.Info.CastTime + CountDownAhead - && DosisPvE.CanUse(out var act)) return act; + if (remainTime < PneumaPvE.Info.CastTime + CountDownAhead + && PneumaPvE.CanUse(out var act)) return act; if (remainTime <= 3 && UseBurstMedicine(out act)) return act; + if (remainTime <= 5 && EukrasiaPvE.CanUse(out act)) return act; return base.CountDownAction(remainTime); } #endregion @@ -85,20 +86,17 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) { if (base.EmergencyAbility(nextGCD, out act)) return true; - if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianDiagnosisPvE, - EukrasianPrognosisPvE, EukrasianPrognosisIiPvE, DiagnosisPvE, PrognosisPvE)) + if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianPrognosisPvE, EukrasianPrognosisIiPvE)) { if (ZoePvE.CanUse(out act)) return true; } - if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianDiagnosisPvE, - EukrasianPrognosisPvE, EukrasianPrognosisIiPvE, DiagnosisPvE, PrognosisPvE)) + if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianDiagnosisPvE, DiagnosisPvE, PrognosisPvE)) { if (KrasisPvE.CanUse(out act)) return true; } - if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianDiagnosisPvE, - EukrasianPrognosisPvE, EukrasianPrognosisIiPvE, DiagnosisPvE, PrognosisPvE)) + if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianPrognosisPvE, EukrasianPrognosisIiPvE, DiagnosisPvE, PrognosisPvE)) { if (PhilosophiaPvE.CanUse(out act)) return true; } @@ -109,6 +107,11 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act) [RotationDesc(ActionID.PanhaimaPvE, ActionID.KeracholePvE, ActionID.HolosPvE)] protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act) { + if (!PanhaimaPvE.Cooldown.IsCoolingDown) + { + if (PhysisIiPvE.CanUse(out act)) return true; + } + if (Addersgall <= 1) { if (PanhaimaPvE.CanUse(out act)) return true; @@ -124,6 +127,11 @@ protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act) [RotationDesc(ActionID.HaimaPvE, ActionID.TaurocholePvE, ActionID.PanhaimaPvE, ActionID.KeracholePvE, ActionID.HolosPvE)] protected override bool DefenseSingleAbility(IAction nextGCD, out IAction? act) { + if (!HaimaPvE.Cooldown.IsCoolingDown) + { + if (KrasisPvE.CanUse(out act)) return true; + } + if (Addersgall <= 1) { if (HaimaPvE.CanUse(out act)) return true; @@ -146,16 +154,14 @@ protected override bool DefenseSingleAbility(IAction nextGCD, out IAction? act) [RotationDesc(ActionID.KeracholePvE, ActionID.PhysisPvE, ActionID.HolosPvE, ActionID.IxocholePvE)] protected override bool HealAreaAbility(IAction nextGCD, out IAction? act) { - if (PhysisIiPvE.CanUse(out act)) return true; - if (!PhysisIiPvE.EnoughLevel && PhysisPvE.CanUse(out act)) return true; - if (KeracholePvE.CanUse(out act) && EnhancedKeracholeTrait.EnoughLevel) return true; - if (HolosPvE.CanUse(out act) && PartyMembersAverHP < HolosHeal) return true; - if (IxocholePvE.CanUse(out act)) return true; - if (KeracholePvE.CanUse(out act)) return true; + if (PhysisIiPvE.CanUse(out act)) return true; + if (!PhysisIiPvE.EnoughLevel && PhysisPvE.CanUse(out act)) return true; + + if (HolosPvE.CanUse(out act) && PartyMembersAverHP < HolosHeal) return true; return base.HealAreaAbility(nextGCD, out act); } @@ -165,8 +171,6 @@ protected override bool HealSingleAbility(IAction nextGCD, out IAction? act) { if (TaurocholePvE.CanUse(out act)) return true; - if (KeracholePvE.CanUse(out act) && EnhancedKeracholeTrait.EnoughLevel) return true; - if ((!TaurocholePvE.EnoughLevel || TaurocholePvE.Cooldown.IsCoolingDown) && DruocholePvE.CanUse(out act)) return true; if (SoteriaPvE.CanUse(out act) && PartyMembers.Any(b => b.HasStatus(true, StatusID.Kardion) && b.GetHealthRatio() < SoteriaHeal)) return true; @@ -194,8 +198,6 @@ protected override bool HealSingleAbility(IAction nextGCD, out IAction? act) if (KrasisPvE.CanUse(out act)) return true; } - if (KeracholePvE.CanUse(out act)) return true; - return base.HealSingleAbility(nextGCD, out act); } diff --git a/BasicRotations/Tank/WAR_Default.cs b/BasicRotations/Tank/WAR_Default.cs index 3d7dfe20d..47443f64e 100644 --- a/BasicRotations/Tank/WAR_Default.cs +++ b/BasicRotations/Tank/WAR_Default.cs @@ -12,9 +12,19 @@ public sealed class WAR_Default : WarriorRotation [RotationConfig(CombatType.PvE, Name = "Use Bloodwhetting/Raw intuition on single enemies")] public bool SoloIntuition { get; set; } = false; + [Range(0, 1, ConfigUnitType.Percent)] + [RotationConfig(CombatType.PvE, Name = "Bloodwhetting/Raw intuition heal threshold")] + public float HealIntuition { get; set; } = 0.7f; + [RotationConfig(CombatType.PvE, Name = "Use Primal Rend while moving (Danger)")] public bool YEET { get; set; } = false; + [RotationConfig(CombatType.PvE, Name = "Use both stacks of Onslaught during burst while standing still")] + public bool YEETBurst { get; set; } = true; + + [RotationConfig(CombatType.PvE, Name = "Use a stack of Onslaught during when its about to overcap while standing still")] + public bool YEETCooldown { get; set; } = false; + [Range(1, 20, ConfigUnitType.Yalms)] [RotationConfig(CombatType.PvE, Name = "Max distance you can be from the boss for Primal Rend use (Danger, setting too high will get you killed)")] public float PrimalRendDistance { get; set; } = 2; @@ -69,11 +79,20 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) if (Player.HasStatus(false, StatusID.Wrathful) && PrimalWrathPvE.CanUse(out act, skipAoeCheck: true)) return true; - if (OnslaughtPvE.CanUse(out act, usedUp: IsBurstStatus) && + if (YEETBurst && OnslaughtPvE.CanUse(out act, usedUp: IsBurstStatus) && !IsMoving && - !IsLastAction(true, OnslaughtPvE) && - !IsLastAction(true, UpheavalPvE) && - Player.HasStatus(false, StatusID.SurgingTempest)) + !IsLastAction(false, OnslaughtPvE) && + !IsLastAction(false, UpheavalPvE) && + Player.HasStatus(true, StatusID.SurgingTempest)) + { + return true; + } + + if (YEETCooldown && OnslaughtPvE.CanUse(out act, usedUp: true) && + !IsMoving && + !IsLastAction(false, OnslaughtPvE) && + OnslaughtPvE.Cooldown.WillHaveXChargesGCD(OnslaughtMax, 1) && + Player.HasStatus(true, StatusID.SurgingTempest)) { return true; } @@ -84,6 +103,16 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act) protected override bool GeneralAbility(IAction nextGCD, out IAction? act) { + if ((InCombat && Player.GetHealthRatio() < HealIntuition && NumberOfHostilesInRange > 0) || (InCombat && PartyMembers.Count() is 1 && NumberOfHostilesInRange > 0)) + { + if (BloodwhettingPvE.CanUse(out act)) return true; + } + + if ((InCombat && Player.GetHealthRatio() < HealIntuition && NumberOfHostilesInRange > 0) || (InCombat && PartyMembers.Count() is 1 && NumberOfHostilesInRange > 0)) + { + if (RawIntuitionPvE.CanUse(out act)) return true; + } + if (Player.GetHealthRatio() < ThrillOfBattleHeal) { if (ThrillOfBattlePvE.CanUse(out act)) return true; diff --git a/RotationSolver.Basic/Helpers/ObjectHelper.cs b/RotationSolver.Basic/Helpers/ObjectHelper.cs index 33143d01c..4da1579d1 100644 --- a/RotationSolver.Basic/Helpers/ObjectHelper.cs +++ b/RotationSolver.Basic/Helpers/ObjectHelper.cs @@ -47,7 +47,7 @@ internal static bool CanProvoke(this IGameObject target) { foreach (var n in ns1) { - if (!string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name.ExtractText()).Success) + if (!string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name?.ExtractText() ?? string.Empty).Success) { return false; } @@ -55,13 +55,14 @@ internal static bool CanProvoke(this IGameObject target) } //Target can move or too big and has a target - if ((target.GetObjectNPC()?.Unknown0 == 0 || target.HitboxRadius >= 5) // Unknown12 used to be the flag checked for the mobs ability to move, honestly just guessing on this one + var targetNpc = target.GetObjectNPC(); + if ((targetNpc?.Unknown0 == 0 || target.HitboxRadius >= 5) // Unknown12 used to be the flag checked for the mobs ability to move, honestly just guessing on this one && (target.TargetObject?.IsValid() ?? false)) { //the target is not a tank role if (Svc.Objects.SearchById(target.TargetObjectId) is IBattleChara battle && !battle.IsJobCategory(JobRole.Tank) - && (Vector3.Distance(target.Position, Player.Object.Position) > 5)) + && (Vector3.Distance(target.Position, Player.Object?.Position ?? Vector3.Zero) > 5)) { return true; } diff --git a/RotationSolver.Basic/Rotations/Basic/SageRotation.cs b/RotationSolver.Basic/Rotations/Basic/SageRotation.cs index bcb5621db..84585f7a0 100644 --- a/RotationSolver.Basic/Rotations/Basic/SageRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/SageRotation.cs @@ -380,6 +380,7 @@ static partial void ModifyPhilosophiaPvE(ref ActionSetting setting) { setting.StatusProvide = [StatusID.Philosophia]; setting.TargetStatusProvide = [StatusID.Eudaimonia]; + setting.TargetType = TargetType.Self; setting.CreateConfig = () => new ActionConfig() { AoeCount = 1, diff --git a/RotationSolver.Basic/Rotations/Basic/WarriorRotation.cs b/RotationSolver.Basic/Rotations/Basic/WarriorRotation.cs index 345acebc0..3eb1ffa8a 100644 --- a/RotationSolver.Basic/Rotations/Basic/WarriorRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/WarriorRotation.cs @@ -11,6 +11,11 @@ partial class WarriorRotation /// public static byte BeastGauge => JobGauge.BeastGauge; + /// + /// + /// + public static byte OnslaughtMax => EnhancedOnslaughtTrait.EnoughLevel ? (byte)3 : (byte)2; + /// /// Holds the remaining amount of InnerRelease stacks /// @@ -34,13 +39,14 @@ public static byte BerserkStacks return stacks == byte.MaxValue ? (byte)3 : stacks; } } - + /// public override void DisplayStatus() { ImGui.Text("InnerReleaseStacks: " + InnerReleaseStacks.ToString()); ImGui.Text("BerserkStacks: " + BerserkStacks.ToString()); ImGui.Text("BeastGaugeValue: " + BeastGauge.ToString()); + ImGui.Text("OnslaughtMax: " + OnslaughtMax.ToString()); } private sealed protected override IBaseAction TankStance => DefiancePvE; diff --git a/RotationSolver/UI/RotationConfigWindow.cs b/RotationSolver/UI/RotationConfigWindow.cs index 3485c0f29..1e68d21c1 100644 --- a/RotationSolver/UI/RotationConfigWindow.cs +++ b/RotationSolver/UI/RotationConfigWindow.cs @@ -1017,7 +1017,6 @@ private static void DrawAboutLinks() private void DrawAutoduty() { - ImGui.TextWrapped("This is a gentle reminder that RSR is not a botting tool, and while I have taken steps to help it work better with Autoduty please keep that in mind"); ImGui.Spacing(); ImGui.TextWrapped("This menu is mostly for troubleshooting purposes and is a good first step to share to get assistance."); @@ -1085,15 +1084,15 @@ private void DrawAutoduty() // Create a new list of AutoDutyPlugin objects var pluginsToCheck = new List { - new IncompatiblePlugin { Name = "AutoDuty" }, - new IncompatiblePlugin { Name = "vnavmesh" }, - new IncompatiblePlugin { Name = "BossMod Reborn" }, - new IncompatiblePlugin { Name = "Boss Mod" }, - new IncompatiblePlugin { Name = "Avarice" }, - new IncompatiblePlugin { Name = "Deliveroo" }, - new IncompatiblePlugin { Name = "AutoRetainer" }, - new IncompatiblePlugin { Name = "SkipCutscene" }, - new IncompatiblePlugin { Name = "AntiAfkKick" }, + new IncompatiblePlugin { Name = "AutoDuty", Url = "https://puni.sh/api/repository/herc" }, + new IncompatiblePlugin { Name = "vnavmesh", Url = "https://puni.sh/api/repository/veyn" }, + new IncompatiblePlugin { Name = "BossMod Reborn", Url = "https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json" }, + new IncompatiblePlugin { Name = "Boss Mod", Url = "" }, + new IncompatiblePlugin { Name = "Avarice", Url = "https://love.puni.sh/ment.json" }, + new IncompatiblePlugin { Name = "Deliveroo", Url = "https://plugins.carvel.li/" }, + new IncompatiblePlugin { Name = "AutoRetainer", Url = "https://love.puni.sh/ment.json" }, + new IncompatiblePlugin { Name = "SkipCutscene", Url = "https://raw.githubusercontent.com/KangasZ/DalamudPluginRepository/main/plugin_repository.json" }, + new IncompatiblePlugin { Name = "AntiAfkKick", Url = "https://raw.githubusercontent.com/NightmareXIV/MyDalamudPlugins/main/pluginmaster.json" }, // Add more plugins as needed }; @@ -1112,6 +1111,16 @@ private void DrawAutoduty() bool isInstalled = plugin.IsInstalled; + // Add a button to copy the URL to the clipboard if the plugin is not installed + if (!isInstalled) + { + if (ImGui.Button($"Copy Repo URL##{plugin.Name}")) + { + ImGui.SetClipboardText(plugin.Url); + } + ImGui.SameLine(); + } + // Determine the color and text for "Boss Mod" Vector4 color; string text; @@ -1130,6 +1139,7 @@ private void DrawAutoduty() ImGui.PushStyleColor(ImGuiCol.Text, color); ImGui.TextWrapped(text); ImGui.PopStyleColor(); + ImGui.Spacing(); } }