Skip to content

Commit

Permalink
Merge pull request #525 from FFXIV-CombatReborn/healerbash
Browse files Browse the repository at this point in the history
Update various classes with new properties and logic
  • Loading branch information
LTS-FFXIV authored Jan 4, 2025
2 parents 38ad9c2 + 1fd888e commit 64f53ea
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 28 deletions.
29 changes: 23 additions & 6 deletions BasicRotations/Healer/AST_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ public sealed class AST_Default : AstrologianRotation
[RotationConfig(CombatType.PvE, Name = "Use both stacks of Lightspeed while moving")]
public bool LightspeedMove { get; set; } = true;

[RotationConfig(CombatType.PvE, Name = "Use experimental card logic to pool for divination buff if possible")]
public bool SmartCard { 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 All @@ -24,6 +21,9 @@ public sealed class AST_Default : AstrologianRotation
[RotationConfig(CombatType.PvE, Name = "Prioritize Microcosmos over all other healing when available")]
public bool MicroPrio { get; set; } = false;

[RotationConfig(CombatType.PvE, Name = "Simple Lord of Crowns logic (use under divinaiton)")]
public bool SimpleLord { get; set; } = false;

[Range(4, 20, ConfigUnitType.Seconds)]
[RotationConfig(CombatType.PvE, Name = "Use Earthly Star during countdown timer.")]
public float UseEarthlyStarTime { get; set; } = 15;
Expand Down Expand Up @@ -77,6 +77,10 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
{
if (SynastryPvE.CanUse(out act)) return true;
}

if (DivinationPvE.CanUse(out _)
&& UseBurstMedicine(out act)) return true;

return base.EmergencyAbility(nextGCD, out act);
}

Expand Down Expand Up @@ -167,10 +171,20 @@ protected override bool GeneralAbility(IAction nextGCD, out IAction? act)
act = null;
if (BubbleProtec && Player.HasStatus(true, StatusID.CollectiveUnconscious_848)) return false;

// Use LadyOfCrownsPvE if your party is needs to be topped up or you are about to use Astral Draw (to prevent overwriting)
if (PartyMembersAverHP < .8 && LadyOfCrownsPvE.CanUse(out act)) return true;
if (AstralDrawPvE.Cooldown.WillHaveOneCharge(3) && LadyOfCrownsPvE.CanUse(out act)) return true;

// Use cards if you are about to use Umbral or Astral Draw (to prevent overwriting)
if (AstralDrawPvE.Cooldown.WillHaveOneCharge(3) && InCombat && TheArrowPvE.CanUse(out act)) return true;
if (AstralDrawPvE.Cooldown.WillHaveOneCharge(3) && InCombat && TheBolePvE.CanUse(out act)) return true;
if (UmbralDrawPvE.Cooldown.WillHaveOneCharge(3) && InCombat && TheArrowPvE.CanUse(out act)) return true;
if (UmbralDrawPvE.Cooldown.WillHaveOneCharge(3) && InCombat && TheSpirePvE.CanUse(out act)) return true;

if (AstralDrawPvE.CanUse(out act)) return true;
if (UmbralDrawPvE.CanUse(out act)) return true;
if (((Player.HasStatus(true, StatusID.Divination) || !DivinationPvE.Cooldown.WillHaveOneCharge(45) || !DivinationPvE.EnoughLevel || UmbralDrawPvE.Cooldown.WillHaveOneCharge(3)) && SmartCard || (!SmartCard)) && InCombat && TheBalancePvE.CanUse(out act)) return true;
if (((Player.HasStatus(true, StatusID.Divination) || !DivinationPvE.Cooldown.WillHaveOneCharge(45) || !DivinationPvE.EnoughLevel || UmbralDrawPvE.Cooldown.WillHaveOneCharge(3)) && SmartCard || (!SmartCard)) && InCombat && TheSpearPvE.CanUse(out act)) return true;
if ((Player.HasStatus(true, StatusID.Divination) || !DivinationPvE.Cooldown.WillHaveOneCharge(45) || !DivinationPvE.EnoughLevel || UmbralDrawPvE.Cooldown.WillHaveOneCharge(3)) && InCombat && TheBalancePvE.CanUse(out act)) return true;
if ((Player.HasStatus(true, StatusID.Divination) || !DivinationPvE.Cooldown.WillHaveOneCharge(45) || !DivinationPvE.EnoughLevel || AstralDrawPvE.Cooldown.WillHaveOneCharge(3)) && InCombat && TheSpearPvE.CanUse(out act)) return true;
return base.GeneralAbility(nextGCD, out act);
}

Expand All @@ -179,6 +193,9 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
act = null;
if (BubbleProtec && Player.HasStatus(true, StatusID.CollectiveUnconscious_848)) return false;

// Use LordOfCrownsPvE if you have SimpleLord enabled and Divination is active
if (SimpleLord && InCombat && Player.HasStatus(true, StatusID.Divination) && LordOfCrownsPvE.CanUse(out act)) return true;

if (!Player.HasStatus(true, StatusID.Lightspeed)
&& InCombat
&& DivinationPvE.Cooldown.ElapsedAfter(115)
Expand Down Expand Up @@ -207,7 +224,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
}

{
if (((Player.HasStatus(true, StatusID.Divination) || !DivinationPvE.Cooldown.WillHaveOneCharge(45) || !DivinationPvE.EnoughLevel || UmbralDrawPvE.Cooldown.WillHaveOneCharge(3)) && SmartCard || (!SmartCard)) && LordOfCrownsPvE.CanUse(out act)) return true;
if (!SimpleLord && (Player.HasStatus(true, StatusID.Divination) || !DivinationPvE.Cooldown.WillHaveOneCharge(45) || !DivinationPvE.EnoughLevel || UmbralDrawPvE.Cooldown.WillHaveOneCharge(3)) && LordOfCrownsPvE.CanUse(out act)) return true;
}
}
return base.AttackAbility(nextGCD, out act);
Expand Down
31 changes: 19 additions & 12 deletions BasicRotations/Healer/SCH_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,16 @@ public sealed class SCH_Default : ScholarRotation
[RotationConfig(CombatType.PvE, Name = "Remove Aetherpact to conserve resources if party member is above this percentage")]
public float AetherpactRemove { get; set; } = 0.9f;

[Range(0, 5, ConfigUnitType.Seconds)]
[RotationConfig(CombatType.PvE, Name = "How long you need to be moving before Ruin is used")]
public float RuinTime { get; set; } = 0;

[RotationConfig(CombatType.PvE, Name = "Use DOT while moving even if it does not need refresh (disabling is a damage down)")]
public bool DOTUpkeep { get; set; } = true;

[Range(0, 5, ConfigUnitType.Seconds)]
[RotationConfig(CombatType.PvE, Name = "How long you need to be moving before DOT is used (requires above to be enabled)")]
public float DOTTime { get; set; } = 0;
#endregion

#region Countdown Logic
Expand All @@ -50,11 +58,6 @@ public sealed class SCH_Default : ScholarRotation
#region oGCD Logic
protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
{
if (nextGCD.IsTheSameTo(true, SuccorPvE, AdloquiumPvE))
{
if (RecitationPvE.CanUse(out act)) return true;
}

//Remove Aetherpact
foreach (var item in PartyMembers)
{
Expand All @@ -72,6 +75,9 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
[RotationDesc(ActionID.SummonSeraphPvE, ActionID.ConsolationPvE, ActionID.WhisperingDawnPvE, ActionID.SacredSoilPvE, ActionID.IndomitabilityPvE)]
protected override bool HealAreaAbility(IAction nextGCD, out IAction? act)
{
if (!IndomitabilityPvE.Cooldown.IsCoolingDown && RecitationPvE.CanUse(out act)) return true;
if (IsLastAbility(ActionID.RecitationPvE) && IndomitabilityPvE.CanUse(out act)) return true;

if (AccessionPvE.CanUse(out act)) return true;
if (ConcitationPvE.CanUse(out act)) return true;
if (WhisperingDawnPvE_16537.Cooldown.ElapsedOneChargeAfterGCD(1) || FeyIlluminationPvE_16538.Cooldown.ElapsedOneChargeAfterGCD(1) || FeyBlessingPvE.Cooldown.ElapsedOneChargeAfterGCD(1))
Expand All @@ -82,9 +88,10 @@ protected override bool HealAreaAbility(IAction nextGCD, out IAction? act)
if (FeyBlessingPvE.CanUse(out act)) return true;

if (WhisperingDawnPvE_16537.CanUse(out act)) return true;
if (SacredSoilPvE.CanUse(out act)) return true;
if (IndomitabilityPvE.CanUse(out act)) return true;

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

return base.HealAreaAbility(nextGCD, out act);
}

Expand All @@ -105,7 +112,7 @@ protected override bool HealSingleAbility(IAction nextGCD, out IAction? act)
[RotationDesc(ActionID.FeyIlluminationPvE, ActionID.ExpedientPvE, ActionID.SummonSeraphPvE, ActionID.ConsolationPvE, ActionID.SacredSoilPvE)]
protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act)
{
if (DeploymentTacticsPvE.CanUse(out act)) return true;
if ((DeploymentTacticsPvE.Target.Target?.WillStatusEnd(0, false, DeploymentTacticsPvE.Setting.TargetStatusNeed ?? []) ?? false) && DeploymentTacticsPvE.CanUse(out act)) return true;

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

Expand Down Expand Up @@ -219,12 +226,12 @@ protected override bool GeneralGCD(out IAction? act)
if (RuinPvE.CanUse(out act)) return true;

//Single Instant for when moving.
if (RuinIiPvE.CanUse(out act)) return true;

if (MovingTime > RuinTime && RuinIiPvE.CanUse(out act)) return true;
//Add dot while moving.
if (BiolysisPvE.CanUse(out act, skipStatusProvideCheck: DOTUpkeep)) return true;
if (BioIiPvE.CanUse(out act, skipStatusProvideCheck: DOTUpkeep)) return true;
if (BioPvE.CanUse(out act, skipStatusProvideCheck: DOTUpkeep)) return true;
if (MovingTime > DOTTime && BiolysisPvE.CanUse(out act, skipStatusProvideCheck: DOTUpkeep)) return true;
if (MovingTime > DOTTime && BioIiPvE.CanUse(out act, skipStatusProvideCheck: DOTUpkeep)) return true;
if (MovingTime > DOTTime && BioPvE.CanUse(out act, skipStatusProvideCheck: DOTUpkeep)) return true;

return base.GeneralGCD(out act);
}
Expand Down
11 changes: 9 additions & 2 deletions BasicRotations/Magical/RDM_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ public sealed class RDM_Default : RedMageRotation
//Fine, ill do it myself
[RotationConfig(CombatType.PvE, Name = "Cast manafication outside of embolden window (use at own risk).")]
public bool AnyoneManafication { get; set; } = false;

[RotationConfig(CombatType.PvE, Name = "Use Corps-a-corps when standing still (use at own risk).")]
public bool SuicideByDumb { get; set; } = true;

[RotationConfig(CombatType.PvE, Name = "Use Displacement after Engagement (use at own risk).")]
public bool SuicideByDumber { get; set; } = false;
#endregion

#region Countdown Logic
Expand Down Expand Up @@ -149,8 +155,9 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
if (ViceOfThornsPvE.CanUse(out act, skipAoeCheck: true)) return true;
if (ContreSixtePvE.CanUse(out act, skipAoeCheck: true)) return true;
if (FlechePvE.CanUse(out act)) return true;
if (EngagementPvE.CanUse(out act, usedUp: true)) return true;
if (CorpsacorpsPvE.CanUse(out act) && !IsMoving) return true;
if (EngagementPvE.CanUse(out act, usedUp: !SuicideByDumber)) return true;
if (SuicideByDumb && CorpsacorpsPvE.CanUse(out act) && !IsMoving) return true;
if (SuicideByDumber && EngagementPvE.Cooldown.CurrentCharges == 1 && DisplacementPvE.CanUse(out act, usedUp: true)) return true;

return base.AttackAbility(nextGCD, out act);
}
Expand Down
89 changes: 85 additions & 4 deletions RotationSolver.Basic/Actions/ActionTargetInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,8 @@ private readonly bool CanGetTarget(IGameObject target, IGameObject subTarget)
TargetType.Magical => IGameObjects != null ? RandomMagicalTarget(IGameObjects) : null,
TargetType.Physical => IGameObjects != null ? RandomPhysicalTarget(IGameObjects) : null,
TargetType.DancePartner => FindDancePartner(),
TargetType.TheSpear => FindTheSpear(),
TargetType.TheBalance => FindTheBalance(),
_ => FindHostile(),
};

Expand All @@ -781,14 +783,91 @@ private readonly bool CanGetTarget(IGameObject target, IGameObject subTarget)

if (IGameObjects == null) return null;

var PartyMembers = IGameObjects.Where(ObjectHelper.IsParty);
var partyMembers = new List<IBattleChara>();
foreach (var obj in IGameObjects)
{
if (ObjectHelper.IsParty(obj))
{
partyMembers.Add(obj);
}
}

foreach (var job in DancePartnerPriority)
{
var partner = PartyMembers.FirstOrDefault(member => member.IsJobs(job) && !member.IsDead);
if (partner != null)
foreach (var member in partyMembers)
{
if (member.IsJobs(job) && !member.IsDead)
{
return member;
}
}
}

return RandomMeleeTarget(IGameObjects)
?? RandomRangeTarget(IGameObjects)
?? RandomMagicalTarget(IGameObjects)
?? RandomPhysicalTarget(IGameObjects)
?? null;
}

IBattleChara? FindTheSpear()
{
// The Spear priority based on the info from The Balance Discord for Level 100 Dance Partner
Job[] TheSpearpriority = { Job.PCT, Job.SAM, Job.RPR, Job.VPR, Job.MNK, Job.NIN, Job.DRG, Job.PCT, Job.SAM, Job.BLM, Job.RDM, Job.SMN, Job.MCH, Job.BRD, Job.DNC };

if (IGameObjects == null) return null;

var partyMembers = new List<IBattleChara>();
foreach (var obj in IGameObjects)
{
if (ObjectHelper.IsParty(obj))
{
partyMembers.Add(obj);
}
}

foreach (var job in TheSpearpriority)
{
foreach (var member in partyMembers)
{
return partner;
if (member.IsJobs(job) && !member.IsDead)
{
return member;
}
}
}

return RandomRangeTarget(IGameObjects)
?? RandomMeleeTarget(IGameObjects)
?? RandomMagicalTarget(IGameObjects)
?? RandomPhysicalTarget(IGameObjects)
?? null;
}

IBattleChara? FindTheBalance()
{
// The Balance priority based on the info from The Balance Discord for Level 100 Dance Partner
Job[] TheBalancepriority = { Job.PCT, Job.SAM, Job.BLM, Job.RDM, Job.SMN, Job.MCH, Job.BRD, Job.DNC, Job.RPR, Job.VPR, Job.MNK, Job.NIN, Job.DRG };

if (IGameObjects == null) return null;

var partyMembers = new List<IBattleChara>();
foreach (var obj in IGameObjects)
{
if (ObjectHelper.IsParty(obj))
{
partyMembers.Add(obj);
}
}

foreach (var job in TheBalancepriority)
{
foreach (var member in partyMembers)
{
if (member.IsJobs(job) && !member.IsDead)
{
return member;
}
}
}

Expand Down Expand Up @@ -1136,6 +1215,8 @@ public enum TargetType : byte
Magical,
Self,
DancePartner,
TheBalance,
TheSpear,
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

Expand Down
2 changes: 2 additions & 0 deletions RotationSolver.Basic/DataCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ public static TargetingType TargetingType

internal static float StopMovingRaw { get; set; }

internal static float MovingRaw { get; set; }

public static unsafe ushort FateId
{
get
Expand Down
4 changes: 2 additions & 2 deletions RotationSolver.Basic/Rotations/Basic/AstrologianRotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static partial void ModifyTheBalancePvE(ref ActionSetting setting)
setting.ActionCheck = () => HasBalance;
setting.TargetStatusProvide = [StatusID.TheBalance_3887, StatusID.Weakness,
StatusID.BrinkOfDeath];
setting.TargetType = TargetType.Melee;
setting.TargetType = TargetType.TheBalance;
setting.IsFriendly = true;
}

Expand All @@ -190,7 +190,7 @@ static partial void ModifyTheSpearPvE(ref ActionSetting setting)
setting.ActionCheck = () => HasSpear;
setting.TargetStatusProvide = [StatusID.TheSpear_3889, StatusID.Weakness,
StatusID.BrinkOfDeath];
setting.TargetType = TargetType.Range;
setting.TargetType = TargetType.TheSpear;
setting.IsFriendly = true;
}

Expand Down
8 changes: 8 additions & 0 deletions RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,14 @@ public static float LiveComboTime
[Description("Stop moving time")]
public static float StopMovingTime => IsMoving ? 0 : DataCenter.StopMovingRaw + DataCenter.DefaultGCDRemain;


/// <summary>
/// How long the player has been moving.
/// <br>WARNING: Do Not make this method the main of your rotation.</br>
/// </summary>
[Description("Moving time")]
public static float MovingTime => IsMoving ? DataCenter.MovingRaw + DataCenter.DefaultGCDRemain : 0;

/// <summary>
/// Time from GCD.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions RotationSolver/UI/RotationConfigWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2656,6 +2656,7 @@ private static unsafe void DrawStatus()
ImGui.Text($"Height: {Player.Character->ModelContainer.CalculateHeight()}");
ImGui.Text($"OnlineStatus: {Player.OnlineStatus}");
ImGui.Text($"Moving: {DataCenter.IsMoving}");
ImGui.Text($"Moving Time: {DataCenter.MovingRaw}");
ImGui.Text($"Stop Moving: {DataCenter.StopMovingRaw}");
ImGui.Text($"CountDownTime: {Service.CountDownTime}");
ImGui.Text($"Combo Time: {DataCenter.ComboTime}");
Expand Down
10 changes: 8 additions & 2 deletions RotationSolver/Updaters/ActionUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ private unsafe static void UpdateSlots()
}
}

static DateTime _startMovingTime = DateTime.MinValue;
static DateTime _stopMovingTime = DateTime.MinValue;

private unsafe static void UpdateMoving()
{
var last = DataCenter.IsMoving;
Expand All @@ -127,14 +129,18 @@ private unsafe static void UpdateMoving()
{
_stopMovingTime = DateTime.Now;
}
else if (DataCenter.IsMoving)
else if (DataCenter.IsMoving && !last)
{
_stopMovingTime = DateTime.MinValue;
_startMovingTime = DateTime.Now;
}

DataCenter.StopMovingRaw = _stopMovingTime == DateTime.MinValue
? 0
: (float)(DateTime.Now - _stopMovingTime).TotalSeconds;

DataCenter.MovingRaw = _startMovingTime == DateTime.MinValue
? 0
: (float)(DateTime.Now - _startMovingTime).TotalSeconds;
}

static DateTime _startCombatTime = DateTime.MinValue;
Expand Down

0 comments on commit 64f53ea

Please sign in to comment.