Skip to content

Commit

Permalink
Merge pull request #517 from FFXIV-CombatReborn/LBL-Paladin
Browse files Browse the repository at this point in the history
Level by level rewrite of Paladin added to Beta
  • Loading branch information
LTS-FFXIV authored Jan 3, 2025
2 parents 7e0229d + 5db0c17 commit 11a00b6
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 3 deletions.
229 changes: 229 additions & 0 deletions BasicRotations/Tank/PLD_Beta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
namespace DefaultRotations.Tank;

[Rotation("Beta", CombatType.PvE, GameVersion = "7.15")]
[SourceCode(Path = "main/BasicRotations/Tank/PLD_Beta.cs")]
[Api(4)]

public sealed class PLD_Beta : PaladinRotation
{
#region Config Options

[RotationConfig(CombatType.PvE, Name = "Prevent actions while you have Passage of Arms up")]
public bool PassageProtec { get; set; } = false;

[RotationConfig(CombatType.PvE, Name = "Use Hallowed Ground with Cover")]
private bool HallowedWithCover { get; set; } = true;

[Range(0, 100, ConfigUnitType.Pixels)]
[RotationConfig(CombatType.PvE, Name = "Use Sheltron at minimum X Oath to prevent over cap (Set to 0 to disable)")]
private int WhenToSheltron { get; set; } = 100;

[Range(0, 1, ConfigUnitType.Percent)]
[RotationConfig(CombatType.PvE, Name = "Health threshold for Intervention (Set to 0 to disable)")]
private float InterventionRatio { get; set; } = 0.6f;

[Range(0, 1, ConfigUnitType.Percent)]
[RotationConfig(CombatType.PvE, Name = "Health threshold for Cover (Set to 0 to disable)")]
private float CoverRatio { get; set; } = 0.3f;
#endregion

private const ActionID ConfiteorPvEActionId = (ActionID)16459;
private new readonly IBaseAction ConfiteorPvE = new BaseAction(ConfiteorPvEActionId);

#region Countdown Logic
protected override IAction? CountDownAction(float remainTime)
{
if (remainTime < HolySpiritPvE.Info.CastTime + CountDownAhead
&& HolySpiritPvE.CanUse(out var act)) return act;

if (remainTime < 15 && DivineVeilPvE.CanUse(out act)) return act;

return base.CountDownAction(remainTime);
}
#endregion

#region Additional oGCD Logic

[RotationDesc(ActionID.CoverPvE)]
protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

if (Player.HasStatus(true, StatusID.Cover) && HallowedWithCover && HallowedGroundPvE.CanUse(out act)) return true;

if (HallowedGroundPvE.CanUse(out act)
&& Player.GetHealthRatio() <= HealthForDyingTanks) return true;

if ((Player.HasStatus(true, StatusID.Rampart) || Player.HasStatus(true, StatusID.Sentinel)) &&
InterventionPvE.CanUse(out act) &&
InterventionPvE.Target.Target?.GetHealthRatio() < 0.6) return true;

if (CoverPvE.CanUse(out act) && CoverPvE.Target.Target?.DistanceToPlayer() < 10 &&
CoverPvE.Target.Target?.GetHealthRatio() < CoverRatio) return true;

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

[RotationDesc]
protected override bool MoveForwardAbility(IAction nextGCD, out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

if (IntervenePvE.CanUse(out act)) return true;
return base.MoveForwardAbility(nextGCD, out act);
}

[RotationDesc(ActionID.DivineVeilPvE, ActionID.PassageOfArmsPvE)]
protected override bool DefenseAreaAbility(IAction nextGCD, out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

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

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

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

[RotationDesc(ActionID.SentinelPvE, ActionID.RampartPvE, ActionID.BulwarkPvE, ActionID.SheltronPvE, ActionID.ReprisalPvE)]
protected override bool DefenseSingleAbility(IAction nextGCD, out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

// If the player has the Hallowed Ground status, don't use any abilities.
if (!Player.HasStatus(true, StatusID.HallowedGround))
{
// If Bulwark can be used, use it and return true.
if (BulwarkPvE.CanUse(out act, skipAoeCheck: true)) return true;

// If Oath can be used, use it and return true.
if (UseOath(out act)) return true;

// If Rampart is not cooling down or has been cooling down for more than 60 seconds, and Sentinel can be used, use Sentinel and return true.
if ((!RampartPvE.Cooldown.IsCoolingDown || RampartPvE.Cooldown.ElapsedAfter(60)) && SentinelPvE.CanUse(out act)) return true;

// If Sentinel is at an enough level and is cooling down for more than 60 seconds, or if Sentinel is not at an enough level, and Rampart can be used, use Rampart and return true.
if ((SentinelPvE.EnoughLevel && SentinelPvE.Cooldown.IsCoolingDown && SentinelPvE.Cooldown.ElapsedAfter(60) || !SentinelPvE.EnoughLevel) && RampartPvE.CanUse(out act)) return true;

// If Reprisal can be used, use it and return true.
if (ReprisalPvE.CanUse(out act, skipAoeCheck: true)) return true;

}
return base.DefenseSingleAbility(nextGCD, out act);
}
#endregion

#region oGCD Logic

[RotationDesc(ActionID.FightOrFlightPvE)]
protected override bool GeneralAbility(IAction nextGCD, out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

if (OathGauge >= WhenToSheltron && WhenToSheltron > 0 && UseOath(out act)) return true;

if (!RiotBladePvE.EnoughLevel && FightOrFlightPvE.CanUse(out act)) return true;
if (!RageOfHalonePvE.EnoughLevel && nextGCD.IsTheSameTo(true, RiotBladePvE) && FightOrFlightPvE.CanUse(out act)) return true;
if (!ProminencePvE.EnoughLevel && nextGCD.IsTheSameTo(true, RageOfHalonePvE) && FightOrFlightPvE.CanUse(out act)) return true;
return base.GeneralAbility(nextGCD, out act);
}
[RotationDesc(ActionID.SpiritsWithinPvE)]
protected override bool AttackAbility(IAction nextGCD, out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

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

if (!RiotBladePvE.EnoughLevel && FightOrFlightPvE.CanUse(out act)) return true;
if (!RageOfHalonePvE.EnoughLevel && nextGCD.IsTheSameTo(true, RiotBladePvE) && FightOrFlightPvE.CanUse(out act)) return true;
if (!SwordOathTrait.EnoughLevel && nextGCD.IsTheSameTo(true, RoyalAuthorityPvE) && FightOrFlightPvE.CanUse(out act)) return true;
if (SwordOathTrait.EnoughLevel && Player.HasStatus(true, StatusID.AtonementReady) && FightOrFlightPvE.CanUse(out act)) return true;

if (IsLastAbility(true, FightOrFlightPvE) && ImperatorPvE.CanUse(out act)) return true;
if (IsLastAbility(true, FightOrFlightPvE) && RequiescatPvE.CanUse(out act)) return true;

if (FightOrFlightPvE.Cooldown.IsCoolingDown && CircleOfScornPvE.CanUse(out act)) return true;
if (FightOrFlightPvE.Cooldown.IsCoolingDown && ExpiacionPvE.CanUse(out act)) return true;
if (FightOrFlightPvE.Cooldown.IsCoolingDown && SpiritsWithinPvE.CanUse(out act)) return true;
if (!IsMoving && IntervenePvE.CanUse(out act, usedUp: HasFightOrFlight)) return true;
return base.AttackAbility(nextGCD, out act);
}
#endregion

#region GCD Logic

[RotationDesc(ActionID.ClemencyPvE)]
protected override bool HealSingleGCD(out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;
if (ClemencyPvE.CanUse(out act)) return true;
return base.HealSingleGCD(out act);
}

[RotationDesc(ActionID.ShieldBashPvE)]
protected override bool MyInterruptGCD(out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

if (LowBlowPvE.Cooldown.IsCoolingDown && ShieldBashPvE.CanUse(out act)) return true;
return base.MyInterruptGCD(out act);
}

protected override bool GeneralGCD(out IAction? act)
{
act = null;
if (PassageProtec && Player.HasStatus(true, StatusID.PassageOfArms)) return false;

// Confiteor Combo
if (BladeOfValorPvE.CanUse(out act)) return true;
if (BladeOfTruthPvE.CanUse(out act)) return true;
if (BladeOfFaithPvE.CanUse(out act)) return true;
if (Player.HasStatus(true, StatusID.Requiescat) && ConfiteorPvE.CanUse(out act, usedUp: true)) return true;

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

if (SepulchrePvE.CanUse(out act)) return true;
if (SupplicationPvE.CanUse(out act)) return true;
if (AtonementPvE.CanUse(out act)) return true;

//AoE
if (Player.HasStatus(true, StatusID.DivineMight) && HolyCirclePvE.CanUse(out act)) return true;
if (ProminencePvE.CanUse(out act)) return true;
if (TotalEclipsePvE.CanUse(out act)) return true;

//Single Target
if (Player.HasStatus(true, StatusID.DivineMight) && HolySpiritPvE.CanUse(out act)) return true;

if (RoyalAuthorityPvE.CanUse(out act)) return true;
if (RageOfHalonePvE.CanUse(out act)) return true;
if (RiotBladePvE.CanUse(out act)) return true;
if (FastBladePvE.CanUse(out act)) return true;

//Ranged
if (HolySpiritPvE.CanUse(out act)) return true;
if (ShieldLobPvE.CanUse(out act)) return true;
return base.GeneralGCD(out act);
}

#endregion

#region Extra Methods

private bool UseOath(out IAction? act)
{
act = null;
if ((InterventionPvE.Target.Target?.GetHealthRatio() <= InterventionRatio) && InterventionPvE.CanUse(out act)) return true;
if (HolySheltronPvE.CanUse(out act)) return true;
if (SheltronPvE.CanUse(out act)) return true;
return false;
}
#endregion
}
2 changes: 1 addition & 1 deletion BasicRotations/Tank/PLD_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class PLD_Default : PaladinRotation
{
#region Config Options

[RotationConfig(CombatType.PvE, Name = "Prevent actions while you have Passage of Prms up")]
[RotationConfig(CombatType.PvE, Name = "Prevent actions while you have Passage of Arms up")]
public bool PassageProtec { get; set; } = false;

[RotationConfig(CombatType.PvE, Name = "Use Hallowed Ground with Cover")]
Expand Down
14 changes: 12 additions & 2 deletions RotationSolver.Basic/Rotations/Basic/PaladinRotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ partial class PaladinRotation
/// <inheritdoc/>
public override MedicineType MedicineType => MedicineType.Strength;

private const ActionID ConfiteorPvEActionId = (ActionID)16459;

/// <summary>
///
/// </summary>
Expand Down Expand Up @@ -86,7 +88,12 @@ public override void DisplayStatus()
ImGui.Text("HasDivineMight: " + HasDivineMight.ToString());
ImGui.Text("HasFightOrFlight: " + HasFightOrFlight.ToString());
ImGui.Text("CanHealAreaAbility: " + CanHealAreaAbility.ToString());
ImGui.Text("CanHealSingleSpell: " + CanHealSingleSpell.ToString());
ImGui.Text("SupplicationReady: " + SupplicationReady.ToString());
ImGui.Text("SepulchreReady: " + SepulchreReady.ToString());
ImGui.Text("BladeOfFaithReady: " + BladeOfFaithReady.ToString());
ImGui.Text("BladeOfTruthReady: " + BladeOfTruthReady.ToString());
ImGui.Text("BladeOfValorReady: " + BladeOfValorReady.ToString());
ImGui.Text("BladeOfHonorReady: " + BladeOfHonorReady.ToString());
}

#endregion
Expand Down Expand Up @@ -307,6 +314,7 @@ static partial void ModifyExpiacionPvE(ref ActionSetting setting)

static partial void ModifyBladeOfFaithPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => BladeOfFaithReady;
setting.ComboIds = [ActionID.ConfiteorPvE];
setting.CreateConfig = () => new ActionConfig()
{
Expand All @@ -316,6 +324,7 @@ static partial void ModifyBladeOfFaithPvE(ref ActionSetting setting)

static partial void ModifyBladeOfTruthPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => BladeOfTruthReady;
setting.ComboIds = [ActionID.BladeOfFaithPvE];
setting.CreateConfig = () => new ActionConfig()
{
Expand All @@ -325,6 +334,7 @@ static partial void ModifyBladeOfTruthPvE(ref ActionSetting setting)

static partial void ModifyBladeOfValorPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => BladeOfValorReady;
setting.ComboIds = [ActionID.BladeOfTruthPvE];
setting.CreateConfig = () => new ActionConfig()
{
Expand All @@ -348,7 +358,7 @@ static partial void ModifyImperatorPvE(ref ActionSetting setting)
}
static partial void ModifyBladeOfHonorPvE(ref ActionSetting setting)
{
setting.StatusNeed = [StatusID.BladeOfHonorReady];
setting.ActionCheck = () => BladeOfHonorReady;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
Expand Down

0 comments on commit 11a00b6

Please sign in to comment.