local Tinkr, _Bastion = ... ---@type Bastion local Bastion = _Bastion local ProtModule = Bastion.Module:New('paladin_protection') local Player = Bastion.UnitManager:Get('player') local Target = Bastion.UnitManager:Get('target') local None = Bastion.UnitManager:Get('none') local CrusaderAura = Bastion.SpellBook:GetSpell(32223) local DevoAura = Bastion.SpellBook:GetSpell(465) local Consecrate = Bastion.SpellBook:GetSpell(26573) local ConsecrateAura = Bastion.SpellBook:GetSpell(188370) local Judgement = Bastion.SpellBook:GetSpell(275779) local AvengersShield = Bastion.SpellBook:GetSpell(31935) local OfDuskAndDawn = Bastion.SpellBook:GetSpell(385125) local BlessingOfTheDawn = Bastion.SpellBook:GetSpell(385127) local BlessingOfTheDusk = Bastion.SpellBook:GetSpell(385126) local ShieldOfTheRighteous = Bastion.SpellBook:GetSpell(53600) local BlessedHammer = Bastion.SpellBook:GetSpell(204019) local Rebuke = Bastion.SpellBook:GetSpell(96231) local AutoAttack = Bastion.SpellBook:GetSpell(6603) local AvengersShieldTarget = Bastion.UnitManager:CreateCustomUnit('avengers_shield', function() local target = nil Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end if not Player:CanSee(unit) then return false end if not AvengersShield:IsInRange(unit) then return false end if unit:IsCasting() and unit:IsInterruptible() then target = unit return true end return false end) if target == nil then if Target:Exists() then target = Target else target = None end end return target end) local KickTarget = Bastion.UnitManager:CreateCustomUnit('kick', function() local kick = nil Bastion.UnitManager:EnumEnemies(function(unit) if unit:IsDead() then return false end if not Player:CanSee(unit) then return false end if Player:GetDistance(unit) > 40 then return false end if unit:IsInterruptible() and Rebuke:IsInRange(unit) then kick = unit return true end -- TODO: Only consider this if the player is in an M+ dungeon -- if Player:InMelee(unit) and Player:IsFacing(unit) and Bastion.MythicPlusUtils:CastingCriticalKick(unit, 5) then -- kick = unit -- return true -- end return false end) if kick == nil then kick = None end return kick end) ---@return boolean local function CombatRotation() -- Attack the target is auto attack isnt active. if AutoAttack:IsKnownAndUsable() and not IsCurrentSpell(AutoAttack:GetID()) and Player:InMelee(Target) and not Target:IsDead() then AutoAttack:Cast(Target) end -- Kick if KickTarget:Exists() and not Player:IsCastingOrChanneling() and Rebuke:IsKnownAndUsable() then Rebuke:Cast(KickTarget) end -- Cast Consecrate if an enemy is in range, and the player isnt moving. if Consecrate:IsKnownAndUsable() and not Player:IsMoving() and not Player:GetAuras():FindMy(ConsecrateAura):IsUp() and Player:GetEnemies(10) >= 1 then return Consecrate:Cast(Player) end -- Handle SoR specially if DuskAndDawn is known. if OfDuskAndDawn:IsKnown() then -- If Blessing of Dawn isnt up, or will expire soon then wait for 5 HP to cast it. if not Player:GetAuras():FindMy(BlessingOfTheDawn):IsUp() or Player:GetAuras():FindMy(BlessingOfTheDawn):GetRemainingTime() < 7 then if Player:GetPower(Enum.PowerType.HolyPower) > 4 and ShieldOfTheRighteous:IsKnownAndUsable() and ShieldOfTheRighteous:IsInRange(Target) then return ShieldOfTheRighteous:Cast(Target) end -- If Blessing of Dawn is up, cast SoR at 3 or more HP elseif Player:GetPower(Enum.PowerType.HolyPower) >= 3 and ShieldOfTheRighteous:IsKnownAndUsable() and ShieldOfTheRighteous:IsInRange(Target) then return ShieldOfTheRighteous:Cast(Target) end else -- If Dusk And Dawn isnt known, rip SoR normally. if ShieldOfTheRighteous:IsKnownAndUsable() and ShieldOfTheRighteous:IsInRange(Target) then return ShieldOfTheRighteous:Cast(Target) end end -- Avengers shield with higher prio than Judgement in AOE. Prefer targets that are casting. if Player:GetEnemies(10) > 1 and AvengersShield:IsKnownAndUsable() and AvengersShieldTarget:Exists() then return AvengersShield:Cast(AvengersShieldTarget) end -- Judgement if Judgement:IsKnownAndUsable() and Target:Exists() and not Player:IsCastingOrChanneling() and Judgement:IsInRange(Target) then return Judgement:Cast(Target) end -- Avengers shield with lower prio than Judgement in ST. Prefer targets that are casting. if Player:GetEnemies(10) == 1 and AvengersShield:IsKnownAndUsable() and AvengersShieldTarget:Exists() then return AvengersShield:Cast(AvengersShieldTarget) end -- Blessed Hammer if there are more than 1 enemy in 10 yds. if BlessedHammer:IsKnownAndUsable() and Player:GetEnemies(10) >= 1 then return BlessedHammer:Cast(Player) end return false end ---@return boolean local function OutOfCombatRotation() return false end local isRunning = false ProtModule:Sync(function() if not isRunning then Bastion:Print('Prot Paladin Started') isRunning = true end if not Player:IsAlive() then return false end -- Cast Crusader Aura if talented and the player is mounted. if Player:IsMounted() and CrusaderAura:IsKnownAndUsable() and not Player:GetAuras():FindMy(CrusaderAura):IsUp() and not Player:IsCastingOrChanneling() then return CrusaderAura:Cast(Player) end -- Cast Devo Aura if the player is not mounted. if not Player:IsMounted() and DevoAura:IsKnownAndUsable() and not Player:GetAuras():FindMy(DevoAura):IsUp() and not Player:IsCastingOrChanneling() then return DevoAura:Cast(Player) end if Player:IsAffectingCombat() then -- Combat Rotation return CombatRotation() else -- Out Of Combat Rotation return OutOfCombatRotation() end end) Bastion:Register(ProtModule)