|
|
|
local Tinkr, Bastion = ...
|
|
|
|
local ProtPaladinModule = Bastion.Module:New('ProtectionPaladin')
|
|
|
|
local Player = Bastion.UnitManager:Get('player')
|
|
|
|
local Target = Bastion.UnitManager:Get('target')
|
|
|
|
local SpellBook = Bastion.SpellBook:New()
|
|
|
|
|
|
|
|
-- Spells
|
|
|
|
local Consecration = SpellBook:GetSpell(26573)
|
|
|
|
local ShieldOfTheRighteous = SpellBook:GetSpell(53600)
|
|
|
|
local Judgment = SpellBook:GetSpell(275779)
|
|
|
|
local HammerOfWrath = SpellBook:GetSpell(24275)
|
|
|
|
local AvengersShield = SpellBook:GetSpell(31935)
|
|
|
|
local BlessedHammer = SpellBook:GetSpell(204019)
|
|
|
|
local WordOfGlory = SpellBook:GetSpell(85673)
|
|
|
|
local AvengingWrath = SpellBook:GetSpell(31884)
|
|
|
|
local DivineShield = SpellBook:GetSpell(642)
|
|
|
|
local HandOfReckoning = SpellBook:GetSpell(62124)
|
|
|
|
local EyeOfTyr = SpellBook:GetSpell(387174)
|
|
|
|
local DivineSteed = SpellBook:GetSpell(190784)
|
|
|
|
local Rebuke = SpellBook:GetSpell(96231)
|
|
|
|
|
|
|
|
-- Buffs
|
|
|
|
local ConsecrationBuff = SpellBook:GetSpell(188370)
|
|
|
|
local ShiningLightBuff = SpellBook:GetSpell(327510)
|
|
|
|
|
|
|
|
-- Helper Functions
|
|
|
|
local function GetEnemiesInRange(range)
|
|
|
|
local count = 0
|
|
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
|
|
if unit:GetDistance(Player) <= range and unit:IsAffectingCombat() then
|
|
|
|
count = count + 1
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
return count
|
|
|
|
end
|
|
|
|
|
|
|
|
local function GetLowestThreatEnemy()
|
|
|
|
local lowestThreatUnit = nil
|
|
|
|
local lowestThreat = math.huge
|
|
|
|
|
|
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
|
|
if unit:IsAffectingCombat() and unit:GetDistance(Player) <= 30 then
|
|
|
|
local _, _, scaledPercent = UnitDetailedThreatSituation(Player:GetOMToken(), unit:GetOMToken())
|
|
|
|
if scaledPercent and scaledPercent < lowestThreat then
|
|
|
|
lowestThreatUnit = unit
|
|
|
|
lowestThreat = scaledPercent
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
return lowestThreatUnit
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Create APLs
|
|
|
|
local DefaultAPL = Bastion.APL:New('default')
|
|
|
|
local CooldownAPL = Bastion.APL:New('cooldown')
|
|
|
|
local DefensiveAPL = Bastion.APL:New('defensive')
|
|
|
|
local InterruptAPL = Bastion.APL:New('interrupt')
|
|
|
|
local ThreatAPL = Bastion.APL:New('threat')
|
|
|
|
|
|
|
|
-- Interrupt APL
|
|
|
|
InterruptAPL:AddSpell(
|
|
|
|
Rebuke:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Target:IsCasting() and Target:IsInterruptible() and Player:IsWithinCombatDistance(Target, 5)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
InterruptAPL:AddSpell(
|
|
|
|
AvengersShield:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Target:IsCasting() and Target:IsInterruptible() and Rebuke:GetCooldownRemaining() > 0 and Player:IsWithinCombatDistance(Target, 30)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Threat Management APL
|
|
|
|
ThreatAPL:AddSpell(
|
|
|
|
HandOfReckoning:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Target:GetDistance(Player) > 10 and Target:GetDistance(Player) <= 30
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
ThreatAPL:AddSpell(
|
|
|
|
AvengersShield:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and GetEnemiesInRange(30) > 1 and Player:IsWithinCombatDistance(Target, 30)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Defensive APL
|
|
|
|
DefensiveAPL:AddSpell(
|
|
|
|
ShieldOfTheRighteous:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:GetPower() >= 3 and Player:GetHP() < 80 and Player:IsWithinCombatDistance(Target, 5)
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefensiveAPL:AddSpell(
|
|
|
|
WordOfGlory:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and (Player:GetPower() >= 3 or Player:GetAuras():FindMy(ShiningLightBuff):IsUp()) and Player:GetHP() < 50
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefensiveAPL:AddSpell(
|
|
|
|
EyeOfTyr:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:GetHP() < 60 and GetEnemiesInRange(8) >= 3
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Cooldown APL
|
|
|
|
CooldownAPL:AddSpell(
|
|
|
|
AvengingWrath:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and GetEnemiesInRange(8) >= 3
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Default APL
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
Consecration:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(ConsecrationBuff):IsUp() and Player:IsWithinCombatDistance(Target, 8)
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
ShieldOfTheRighteous:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:GetPower() >= 3 and Player:IsWithinCombatDistance(Target, 5)
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
AvengersShield:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:IsWithinCombatDistance(Target, 30)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
Judgment:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:IsWithinCombatDistance(Target, 30)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
HammerOfWrath:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and (Target:GetHP() <= 20 or Player:GetAuras():FindMy(AvengingWrath):IsUp()) and Player:IsWithinCombatDistance(Target, 30)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
BlessedHammer:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:IsWithinCombatDistance(Target, 5)
|
|
|
|
end):SetTarget(Target)
|
|
|
|
)
|
|
|
|
|
|
|
|
DefaultAPL:AddSpell(
|
|
|
|
Consecration:CastableIf(function(self)
|
|
|
|
return self:IsKnownAndUsable() and Player:IsWithinCombatDistance(Target, 8)
|
|
|
|
end):SetTarget(Player)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Main rotation logic
|
|
|
|
ProtPaladinModule:Sync(function()
|
|
|
|
-- Check if the player is mounted
|
|
|
|
if IsMounted() or Player:IsMounted() then
|
|
|
|
return -- Exit the function if mounted, pausing the rotation
|
|
|
|
end
|
|
|
|
|
|
|
|
if not Player:IsAffectingCombat() then
|
|
|
|
if not Target:Exists() or Target:IsDead() then
|
|
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
|
|
if unit:IsAlive() and unit:GetDistance(Player) <= 30 then
|
|
|
|
Target = unit
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Dynamic target selection and threat management
|
|
|
|
local lowestThreatEnemy = GetLowestThreatEnemy()
|
|
|
|
if lowestThreatEnemy then
|
|
|
|
Target = lowestThreatEnemy
|
|
|
|
elseif not Target:Exists() or Target:IsDead() or Target:GetDistance(Player) > 30 then
|
|
|
|
Bastion.UnitManager:EnumEnemies(function(unit)
|
|
|
|
if unit:IsAlive() and unit:GetDistance(Player) <= 30 and unit:IsAffectingCombat() then
|
|
|
|
Target = unit
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
InterruptAPL:Execute()
|
|
|
|
ThreatAPL:Execute()
|
|
|
|
DefensiveAPL:Execute()
|
|
|
|
CooldownAPL:Execute()
|
|
|
|
DefaultAPL:Execute()
|
|
|
|
end)
|
|
|
|
|
|
|
|
Bastion:Register(ProtPaladinModule)
|