Skip to content

Commit

Permalink
Refactor and enhance rotation logic and configurations
Browse files Browse the repository at this point in the history
Refactored SCH, SGE, and WHM rotation logic for better readability and maintainability. Updated `SCH_Default.cs` and `SGE_Default.cs` to iterate over party members and tanks for specific actions. Simplified and refactored methods in `SGE_Default.cs` to remove LINQ. Updated `ECommons` subproject commit.

Removed `IsLastAbilityUsable` and `IsFirstAbilityUsable` checks in `BaseAction.cs`. Added new configuration options in `Configs.cs` for raising players and adjusted `_action4head` value. Updated `DataCenter.cs` with XML documentation comments and adjusted `CalculatedActionAhead`.

Refactored `StatusHelper` and `TargetFilter` methods to use explicit loops instead of LINQ. Improved `CustomRotation` logic with additional checks and conditions. Commented out `UseLimitBreak` method in `CustomRotation_GCD.cs`. Added null checks and early returns in `CustomRotation` methods. Cleaned up debug text in `RotationConfigWindow`.

Simplified `RemoveExpiredVfxData` method in `MajorUpdater`. Enhanced `TargetUpdater` with explicit loops, new configuration checks, and improved logic for determining valid raise targets.
  • Loading branch information
LTS-FFXIV committed Jan 15, 2025
1 parent 11b7fc1 commit 4919e1a
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 4919e1a

Please sign in to comment.