Skip to content

Commit

Permalink
Merge pull request #575 from FFXIV-CombatReborn/raiseImprovements
Browse files Browse the repository at this point in the history
Refactor and enhance rotation logic and configurations
  • Loading branch information
LTS-FFXIV authored Jan 15, 2025
2 parents 11b7fc1 + 4919e1a commit f7f27de
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 232 deletions.
4 changes: 2 additions & 2 deletions BasicRotations/Healer/SCH_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ protected override bool HealAreaGCD(out IAction? act)
return base.HealAreaGCD(out act);
}

[RotationDesc(ActionID.AdloquiumPvE, ActionID.PhysickPvE)]
[RotationDesc(ActionID.AdloquiumPvE, ActionID.ManifestationPvE, ActionID.PhysickPvE)]
protected override bool HealSingleGCD(out IAction? act)
{
act = null;
Expand All @@ -193,7 +193,7 @@ protected override bool HealSingleGCD(out IAction? act)
return base.HealSingleGCD(out act);
}

[RotationDesc(ActionID.SuccorPvE)]
[RotationDesc(ActionID.SuccorPvE, ActionID.ConcitationPvE, ActionID.AccessionPvE)]
protected override bool DefenseAreaGCD(out IAction? act)
{
act = null;
Expand Down
140 changes: 68 additions & 72 deletions BasicRotations/Healer/SGE_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ namespace RebornRotations.Healer;
public sealed class SGE_Default : SageRotation
{
#region Config Options
[RotationConfig(CombatType.PvE, Name = "Use new Eukrasian Logic")]
public bool NewELogic { get; set; } = true;

[RotationConfig(CombatType.PvE, Name = "Use spells with cast times to heal. (Ignored if you are the only healer in party)")]
public bool GCDHeal { get; set; } = false;

Expand Down Expand Up @@ -93,7 +90,6 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
}

if (ChoiceEukrasia(out act)) return true;

//if (base.EmergencyAbility(nextGCD, out act)) return true;

if (nextGCD.IsTheSameTo(false, PneumaPvE, EukrasianPrognosisPvE, EukrasianPrognosisIiPvE))
Expand Down Expand Up @@ -193,29 +189,49 @@ protected override bool HealSingleAbility(IAction nextGCD, out IAction? act)

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;
foreach (var member in PartyMembers)
{
if (SoteriaPvE.CanUse(out act) && member.HasStatus(true, StatusID.Kardion) && member.GetHealthRatio() < SoteriaHeal)
{
return true;
}
}

var tank = PartyMembers.GetJobCategory(JobRole.Tank);
if (Addersgall < 1 && (tank.Any(t => t.GetHealthRatio() < OGCDTankHeal) || PartyMembers.Any(b => b.GetHealthRatio() < OGCDHeal)))
foreach (var t in tank)
{
if (HaimaPvE.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)) return true;
if (Addersgall < 1 && t.GetHealthRatio() < OGCDTankHeal)
{
if (HaimaPvE.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)) return true;
if ((!HaimaPvE.EnoughLevel || HaimaPvE.Cooldown.ElapsedAfter(20)) && PanhaimaPvE.CanUse(out act)) return true;
}
}

if ((!HaimaPvE.EnoughLevel || HaimaPvE.Cooldown.ElapsedAfter(20)) && PanhaimaPvE.CanUse(out act)) return true;
foreach (var t in tank)
{
if (t.GetHealthRatio() < ZoeHeal)
{
if (ZoePvE.CanUse(out act)) return true;
}
}

if (tank.Any(t => t.GetHealthRatio() < ZoeHeal))
foreach (var t in tank)
{
if (ZoePvE.CanUse(out act)) return true;
if (t.GetHealthRatio() < KrasisTankHeal)
{
if (KrasisPvE.CanUse(out act)) return true;
}
}

if (tank.Any(t => t.GetHealthRatio() < KrasisTankHeal) || PartyMembers.Any(b => b.GetHealthRatio() < KrasisHeal))
foreach (var member in PartyMembers)
{
if (KrasisPvE.CanUse(out act)) return true;
if (member.GetHealthRatio() < KrasisHeal)
{
if (KrasisPvE.CanUse(out act)) return true;
}
}

return base.HealSingleAbility(nextGCD, out act);
Expand Down Expand Up @@ -246,14 +262,9 @@ protected override bool GeneralAbility(IAction nextGCD, out IAction? act)
// Finally, updates the current Eukrasia action aim if it's different from the incoming action.
private void SetEukrasia(IBaseAction act)
{
if (act == null) return;

if (_EukrasiaActionAim != null && IsLastGCD(true, _EukrasiaActionAim)) return;
if (act == null || (_EukrasiaActionAim != null && IsLastGCD(true, _EukrasiaActionAim))) return;

if (_EukrasiaActionAim != act)
{
_EukrasiaActionAim = act;
}
_EukrasiaActionAim = act;
}

// Clears the Eukrasia action aim, effectively resetting any planned Eukrasia action.
Expand All @@ -273,69 +284,45 @@ private bool ChoiceEukrasia(out IAction? act)
if (!EukrasiaPvE.CanUse(out _)) return false;

// Checks for Eukrasia status.
// Attempts to set correct Eurkrasia action based on availablity and MergedStatus.
// Attempts to set correct Eurkrasia action based on availability and MergedStatus.
if (EukrasianPrognosisIiPvE.CanUse(out _) && EukrasianPrognosisIiPvE.EnoughLevel && MergedStatus.HasFlag(AutoStatus.DefenseArea))
{
SetEukrasia(EukrasianPrognosisIiPvE);
return false;
}

if (EukrasianPrognosisPvE.CanUse(out _) && EukrasianPrognosisPvE.EnoughLevel && MergedStatus.HasFlag(AutoStatus.DefenseArea))
else if (EukrasianPrognosisPvE.CanUse(out _) && EukrasianPrognosisPvE.EnoughLevel && MergedStatus.HasFlag(AutoStatus.DefenseArea))
{
SetEukrasia(EukrasianPrognosisPvE);
return false;
}

if (EukrasianDiagnosisPvE.CanUse(out _) && EukrasianDiagnosisPvE.EnoughLevel && MergedStatus.HasFlag(AutoStatus.DefenseSingle))
else if (EukrasianDiagnosisPvE.CanUse(out _) && EukrasianDiagnosisPvE.EnoughLevel && MergedStatus.HasFlag(AutoStatus.DefenseSingle))
{
SetEukrasia(EukrasianDiagnosisPvE);
return false;
}

if (EukrasianDyskrasiaPvE.CanUse(out _) && EukrasianDyskrasiaPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
else if (EukrasianDyskrasiaPvE.CanUse(out _) && EukrasianDyskrasiaPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
{
SetEukrasia(EukrasianDyskrasiaPvE);
return false;
}

if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _)) && EukrasianDosisIiiPvE.CanUse(out _) && EukrasianDosisIiiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
else if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _)) && EukrasianDosisIiiPvE.CanUse(out _) && EukrasianDosisIiiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
{
SetEukrasia(EukrasianDosisIiiPvE);
return false;
}

if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _)) && EukrasianDosisIiPvE.CanUse(out _) && EukrasianDosisIiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
else if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _)) && EukrasianDosisIiPvE.CanUse(out _) && EukrasianDosisIiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
{
SetEukrasia(EukrasianDosisIiPvE);
return false;
}

if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _)) && EukrasianDosisPvE.CanUse(out _) && EukrasianDosisPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
else if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _)) && EukrasianDosisPvE.CanUse(out _) && EukrasianDosisPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) || !MergedStatus.HasFlag(AutoStatus.DefenseArea)))
{
SetEukrasia(EukrasianDosisPvE);
return false;
}

return false; // Indicates that no specific Eukrasia action was chosen in this cycle.
}
#endregion

#region Eukrasia Execution
// Attempts to perform a Eukrasia action, based on the current game state and conditions.
private bool DoEukrasia(out IAction? act)
{
act = null;

if (_EukrasiaActionAim != null && _EukrasiaActionAim.CanUse(out act))
else
{
if (EukrasiaPvE.CanUse(out act)) return true;

act = _EukrasiaActionAim;
return true;
return false; // Indicates that no specific Eukrasia action was chosen in this cycle.
}

return false;
}
#endregion

#region Eukrasia Execution
// Attempts to perform a Eukrasia action, based on the current game state and conditions.
private bool DoEukrasianPrognosis(out IAction? act)
{
Expand Down Expand Up @@ -402,7 +389,7 @@ private bool DoEukrasianDosis(out IAction? act)
protected override bool HealAreaGCD(out IAction? act)
{
act = null;
if (HasSwift && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;
if (IsLastAction(ActionID.SwiftcastPvE) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;

if (PartyMembersAverHP < PneumaAOEPartyHeal || DyskrasiaPvE.CanUse(out _) && PartyMembers.GetJobCategory(JobRole.Tank).Any(t => t.GetHealthRatio() < PneumaAOETankHeal))
{
Expand All @@ -421,8 +408,7 @@ protected override bool HealAreaGCD(out IAction? act)
protected override bool HealSingleGCD(out IAction? act)
{
act = null;
if (HasSwift && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;

if (IsLastAction(ActionID.SwiftcastPvE) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;
if (_EukrasiaActionAim != null && DiagnosisPvE.CanUse(out act))
{
return true;
Expand All @@ -433,27 +419,37 @@ protected override bool HealSingleGCD(out IAction? act)
protected override bool GeneralGCD(out IAction? act)
{
act = null;
if (HasSwift && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;
if (IsLastAction(ActionID.SwiftcastPvE) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;

if (PhlegmaPvE.CanUse(out act, usedUp: IsMoving)) return true;

if (PartyMembers.Any(b => b.GetHealthRatio() < PneumaSTPartyHeal && !b.IsDead) || PartyMembers.GetJobCategory(JobRole.Tank).Any(t => t.GetHealthRatio() < PneumaSTTankHeal && !t.IsDead))
foreach (var member in PartyMembers)
{
if (PneumaPvE.CanUse(out act)) return true;
if (member.GetHealthRatio() < PneumaSTPartyHeal && !member.IsDead)
{
if (PneumaPvE.CanUse(out act)) return true;
}
}

foreach (var tank in PartyMembers.GetJobCategory(JobRole.Tank))
{
if (tank.GetHealthRatio() < PneumaSTTankHeal && !tank.IsDead)
{
if (PneumaPvE.CanUse(out act)) return true;
}
}

if (IsMoving && ToxikonPvE.CanUse(out act)) return true;

if (NewELogic && DoEukrasianDyskrasia(out act)) return true;
if (DoEukrasianDyskrasia(out act)) return true;

if ((_EukrasiaActionAim != EukrasianDiagnosisPvE || _EukrasiaActionAim != EukrasianPrognosisPvE || _EukrasiaActionAim != EukrasianPrognosisIiPvE || _EukrasiaActionAim != EukrasianDyskrasiaPvE)
if ((_EukrasiaActionAim != EukrasianDiagnosisPvE || _EukrasiaActionAim != EukrasianPrognosisPvE || _EukrasiaActionAim != EukrasianPrognosisIiPvE || _EukrasiaActionAim != EukrasianDyskrasiaPvE)
&& DyskrasiaPvE.CanUse(out act)) return true;

if (NewELogic && DoEukrasianPrognosis(out act)) return true;
if (NewELogic && DoEukrasianDiagnosis(out act)) return true;
if (!NewELogic && DoEukrasia(out act)) return true;
if (DoEukrasianPrognosis(out act)) return true;
if (DoEukrasianDiagnosis(out act)) return true;

if (NewELogic && DoEukrasianDosis(out act)) return true;
if ( DoEukrasianDosis(out act)) return true;
if (DosisPvE.CanUse(out act)) return true;

if (!InCombat && !Player.HasStatus(true, StatusID.Eukrasia) && EukrasiaPvE.CanUse(out act)) return true;
Expand Down
6 changes: 3 additions & 3 deletions BasicRotations/Healer/WHM_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
protected override bool HealAreaGCD(out IAction? act)
{
act = null;
if (HasSwift && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;
if ((HasSwift || IsLastAction(ActionID.SwiftcastPvE)) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;

if (AfflatusRapturePvE.CanUse(out act)) return true;

Expand All @@ -189,7 +189,7 @@ protected override bool HealAreaGCD(out IAction? act)
protected override bool HealSingleGCD(out IAction? act)
{
act = null;
if (HasSwift && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;
if ((HasSwift || IsLastAction(ActionID.SwiftcastPvE)) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;

if (AfflatusSolacePvE.CanUse(out act)) return true;

Expand All @@ -205,7 +205,7 @@ protected override bool HealSingleGCD(out IAction? act)
protected override bool GeneralGCD(out IAction? act)
{
act = null;
if (HasSwift && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;
if ((HasSwift || IsLastAction(ActionID.SwiftcastPvE)) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise)) return false;

//if (NotInCombatDelay && RegenDefense.CanUse(out act)) return true;

Expand Down
2 changes: 1 addition & 1 deletion ECommons
Submodule ECommons updated 27 files
+17 −0 ECommons/Configuration/DefaultSerializationFactory.cs
+34 −7 ECommons/Configuration/EzConfig.cs
+4 −0 ECommons/Configuration/ISerializationFactory.cs
+12 −0 ECommons/GameFunctions/ObjectFunctions.cs
+2 −1 ECommons/GameHelpers/Player.cs
+23 −2 ECommons/GenericHelpers.cs
+3 −1 ECommons/ImGuiMethods/Box.cs
+1 −1 ECommons/ImGuiMethods/Ref.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/ColorantColoring.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/ContextMenu.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/FreeCompanyCreditShop.cs
+6 −6 ECommons/UIHelpers/AddonMasterImplementations/Gathering.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/GatheringMasterpiece.cs
+2 −2 ECommons/UIHelpers/AddonMasterImplementations/ItemInspectionResult.cs
+3 −3 ECommons/UIHelpers/AddonMasterImplementations/LookingForGroupDetail.cs
+4 −4 ECommons/UIHelpers/AddonMasterImplementations/LotteryWeeklyRewardList.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/MateriaAttachDialog.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/PurifyAutoDialog.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/PurifyResult.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/RetainerSell.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/SalvageAutoDialog.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/SelectIconString.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/SelectOk.cs
+2 −2 ECommons/UIHelpers/AddonMasterImplementations/SelectString.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/SelectYesno.cs
+1 −1 ECommons/UIHelpers/AddonMasterImplementations/TripleTriadRequest.cs
+5 −5 ECommons/UIHelpers/AddonMasterImplementations/WorldTravelFinderStatus.cs
31 changes: 0 additions & 31 deletions RotationSolver.Basic/Actions/BaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,6 @@ public bool CanUse(out IAction act, bool isLastAbility = false, bool isFirstAbil
usedUp = true;
}

if (isLastAbility && !IsLastAbilityUsable()) return false;
if (isFirstAbility && !IsFirstAbilityUsable()) return false;

if (!Info.BasicCheck(skipStatusProvideCheck, skipComboCheck, skipCastingCheck)) return false;

if (!Cooldown.CooldownCheck(usedUp, gcdCountForAbility)) return false;
Expand All @@ -167,34 +164,6 @@ public bool CanUse(out IAction act, bool isLastAbility = false, bool isFirstAbil
return true;
}

private bool IsLastAbilityUsable()
{
if (Service.Config.UseV2AbilityChecks)
{
return IsLastAbilityv2Usable();
}
return DataCenter.InCombat && (DataCenter.NextAbilityToNextGCD <= Math.Max(ActionManagerHelper.GetCurrentAnimationLock(), DataCenter.MinAnimationLock) + Service.Config.IsLastAbilityTimer);
}

private bool IsFirstAbilityUsable()
{
if (Service.Config.UseV2AbilityChecks)
{
return IsFirstAbilityv2Usable();
}
return DataCenter.InCombat && (DataCenter.NextAbilityToNextGCD >= Math.Max(ActionManagerHelper.GetCurrentAnimationLock(), DataCenter.MinAnimationLock) + Service.Config.IsFirstAbilityTimer);
}

private bool IsLastAbilityv2Usable()
{
return DataCenter.InCombat && (DataCenter.DefaultGCDElapsed >= DataCenter.DefaultGCDRemain);
}

private bool IsFirstAbilityv2Usable()
{
return DataCenter.InCombat && (DataCenter.DefaultGCDRemain >= DataCenter.DefaultGCDElapsed);
}

private bool IsTimeToKillValid()
{
return DataCenter.AverageTimeToKill >= Config.TimeToKill && DataCenter.AverageTimeToKill >= Config.TimeToUntargetable;
Expand Down
22 changes: 17 additions & 5 deletions RotationSolver.Basic/Configuration/Configs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,6 @@ public const string
Filter = Extra)]
private static readonly bool _autoOpenChest = true;

[ConditionBool, UI("Use experimental FirstAbility and LastAbility checks",
Filter = Extra)]
private static readonly bool _useV2AbilityChecks = false;

[ConditionBool, UI("Enable RSR click counter in main menu",
Filter = Extra)]
private static readonly bool _enableClickingCount = true;
Expand Down Expand Up @@ -445,6 +441,22 @@ public const string
PvEFilter = JobFilterType.Raise, PvPFilter = JobFilterType.NoJob)]
private static readonly bool _raiseBrinkOfDeath = true;

[JobConfig, UI("Raise non-Healers from bottom of party list to the top (Light Party 2 Healer Behaviour, Experimental)",
Filter = HealingActionCondition, Section = 2,
PvEFilter = JobFilterType.Raise, PvPFilter = JobFilterType.NoJob)]
private static readonly bool _h2 = false;

[JobConfig, UI("Raise Red Mage and Summoners first if no Tanks or Healers are dead (Experimental)",
Filter = HealingActionCondition, Section = 2,
PvEFilter = JobFilterType.Raise, PvPFilter = JobFilterType.NoJob)]
private static readonly bool _offRaiserRaise = false;

[JobConfig, UI("How early before next GCD should RSR use swiftcast for raise (Experimental)",
Filter = HealingActionCondition, Section = 2,
PvEFilter = JobFilterType.Raise, PvPFilter = JobFilterType.NoJob)]
[Range(0, 1.0f, ConfigUnitType.Seconds, 0.01f)]
public float SwiftcastBuffer { get; set; } = 0.6f;

[UI("Random delay range for resurrecting players.",
Filter = HealingActionCondition, Section = 2,
PvEFilter = JobFilterType.Raise, PvPFilter = JobFilterType.NoJob)]
Expand Down Expand Up @@ -706,7 +718,7 @@ public const string
[UI("Action Ahead (How far in advance of GCD being available RSR will try to queue the next GCD)",
Description = "This setting controls how many oGCDs RSR will try to fit in a single GCD window\nLower numbers mean more oGCDs, but potentially more GCD clipping",
Parent = nameof(OverrideActionAheadTimer))]
private readonly float _action4head = 0.4f;
private readonly float _action4head = 0.3f;

[JobConfig]
private readonly string _PvPRotationChoice = string.Empty;
Expand Down
Loading

0 comments on commit f7f27de

Please sign in to comment.