diff --git a/scripts/retribution.lua b/scripts/retribution.lua new file mode 100644 index 0000000..5cfe97b --- /dev/null +++ b/scripts/retribution.lua @@ -0,0 +1,852 @@ +---@type _, Bastion +local Tinkr, Bastion = ... + +-- Core +local RetributionModule = Bastion.Module:New('retribution') +local Evaluator = Tinkr.Util.Evaluator +local Time = Bastion.CombatTimer +local Notifications = Bastion.Notifications + +-- Targets +local Player = Bastion.UnitManager:Get('player') +local None = Bastion.UnitManager:Get('none') +local Target = Bastion.UnitManager:Get('target') +local RebukeTarget = Bastion.UnitManager:CreateCustomUnit('kick', function() + local purge = 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 Player:InMelee(unit) and unit:IsInterruptible(5) and Player:IsFacing(unit) then + purge = unit + return true + end + + return false + end) + + if purge == nil then + purge = None + end + + return purge +end) + +-- Spells +local AutoAttack = Bastion.SpellBook:GetSpell(6603) +local ForgeOfLight = Bastion.SpellBook:GetSpell(259930) +local LightsJudgment = Bastion.SpellBook:GetSpell(255647) +local Logging = Bastion.SpellBook:GetSpell(167895) +local MobileBanking = Bastion.SpellBook:GetSpell(83958) +local OverloadElementalDeposit = Bastion.SpellBook:GetSpell(388213) +local ArmorSkills = Bastion.SpellBook:GetSpell(76271) +local Demonbane = Bastion.SpellBook:GetSpell(255653) +local GuildMail = Bastion.SpellBook:GetSpell(83951) +local HastyHearth = Bastion.SpellBook:GetSpell(83944) +local HolyResistance = Bastion.SpellBook:GetSpell(255651) +local Languages = Bastion.SpellBook:GetSpell(79741) +local LightsReckoning = Bastion.SpellBook:GetSpell(255652) +local MasterRiding = Bastion.SpellBook:GetSpell(90265) +local MountUp = Bastion.SpellBook:GetSpell(78633) +local TheQuickandtheDead = Bastion.SpellBook:GetSpell(83950) +local WeaponSkills = Bastion.SpellBook:GetSpell(76294) +local BlessingOfFreedom = Bastion.SpellBook:GetSpell(1044) +local BlessingOfSacrifice = Bastion.SpellBook:GetSpell(6940) +local Consecration = Bastion.SpellBook:GetSpell(26573) +local CrusaderAura = Bastion.SpellBook:GetSpell(32223) +local CrusaderStrike = Bastion.SpellBook:GetSpell(35395) +local DivineShield = Bastion.SpellBook:GetSpell(642) +local DivineSteed = Bastion.SpellBook:GetSpell(190784) +local FlashOfLight = Bastion.SpellBook:GetSpell(19750) +local HammerOfJustice = Bastion.SpellBook:GetSpell(853) +local HammerOfWrath = Bastion.SpellBook:GetSpell(24275) +local HandOfReckoning = Bastion.SpellBook:GetSpell(62124) +local Intercession = Bastion.SpellBook:GetSpell(391054) +local Judgment = Bastion.SpellBook:GetSpell(20271) +local LayonHands = Bastion.SpellBook:GetSpell(633) +local Rebuke = Bastion.SpellBook:GetSpell(96231) +local Redemption = Bastion.SpellBook:GetSpell(7328) +local RetributionAura = Bastion.SpellBook:GetSpell(183435) +local SenseUndead = Bastion.SpellBook:GetSpell(5502) +local Seraphim = Bastion.SpellBook:GetSpell(152262) +local ShieldOftheRighteous = Bastion.SpellBook:GetSpell(53600) +local WordOfGlory = Bastion.SpellBook:GetSpell(85673) +local AspirationOfDivinity = Bastion.SpellBook:GetSpell(385416) +local GoldenPath = Bastion.SpellBook:GetSpell(377128) +local Incandescence = Bastion.SpellBook:GetSpell(385464) +local OfDuskandDawn = Bastion.SpellBook:GetSpell(385125) +local Recompense = Bastion.SpellBook:GetSpell(384914) +local ZealotsParagon = Bastion.SpellBook:GetSpell(391142) +local BladeOfJustice = Bastion.SpellBook:GetSpell(184575) +local Crusade = Bastion.SpellBook:GetSpell(231895) +local DivineStorm = Bastion.SpellBook:GetSpell(53385) +local DivineToll = Bastion.SpellBook:GetSpell(375576) +local Exorcism = Bastion.SpellBook:GetSpell(383185) +local FinalReckoning = Bastion.SpellBook:GetSpell(343721) +local HandOfHindrance = Bastion.SpellBook:GetSpell(183218) +local ShieldOfVengeance = Bastion.SpellBook:GetSpell(184662) +local TemplarsVerdict = Bastion.SpellBook:GetSpell(85256) +local WakeOfAshes = Bastion.SpellBook:GetSpell(255937) +local GreaterJudgment = Bastion.SpellBook:GetSpell(231663) +local MasteryHandOfLight = Bastion.SpellBook:GetSpell(267316) +local AvengingWrath = Bastion.SpellBook:GetSpell(31884) +local ExecutionSentence = Bastion.SpellBook:GetSpell(343527) +local HolyAvenger = Bastion.SpellBook:GetSpell(105809) +local ExecutionersWrath = Bastion.SpellBook:GetSpell(387196) +local RadiantDecree = Bastion.SpellBook:GetSpell(384052) +local JusticarsVengeance = Bastion.SpellBook:GetSpell(215661) +local DivineResonance = Bastion.SpellBook:GetSpell(384027) +local Expurgation = Bastion.SpellBook:GetSpell(383344) +local VanguardsMomentum = Bastion.SpellBook:GetSpell(383314) +local AshesToDust = Bastion.SpellBook:GetSpell(383300) + +-- Items +local AlgetharPuzzleBox = Bastion.ItemBook:GetItem(193701) +local RumblingRuby = Bastion.ItemBook:GetItem(194303) +local DecorationOfFlame = Bastion.ItemBook:GetItem(194299) + +-- Powers +local HolyPower = Enum.PowerType.HolyPower + +-- Velocity +local movements = {} +local lastX, lastY, lastZ +C_Timer.NewTicker(0.1, function() + local x, y, z = ObjectPosition('player') + + if lastX and lastY and lastZ then + local distance = math.sqrt((x - lastX) ^ 2 + (y - lastY) ^ 2 + (z - lastZ) ^ 2) + table.insert(movements, distance) + end + + if #movements > 20 then + table.remove(movements, 1) + end + + lastX, lastY, lastZ = x, y, z +end) + +local function GetAverageVelocity() + local total = 0 + for _, distance in ipairs(movements) do + total = total + distance + end + return total / #movements +end + +local function IsPlayerMoving() + return GetAverageVelocity() >= 0.55 +end + +-- calculate the total distance moved over the last 2 seconds + +-- APLs +local DefaultAPL = Bastion.APL:New('default') +local CooldownsAPL = Bastion.APL:New('cooldowns') +local FinishersAPL = Bastion.APL:New('finishers') +local ESFRPoolingAPL = Bastion.APL:New('es_fr_pooling') +local ESFRActiveAPL = Bastion.APL:New('es_fr_active') +local GeneratorsAPL = Bastion.APL:New('generators') + +local function TimeToHPG() + return math.max( + Player:GetGCD(), + math.min( + Judgment:IsKnown() and Judgment:GetCooldownRemaining() or 999, + CrusaderStrike:IsKnown() and CrusaderStrike:GetCooldownRemaining() or 999, + BladeOfJustice:IsKnown() and BladeOfJustice:GetCooldownRemaining() or 999, + HammerOfWrath:IsKnown() and HammerOfWrath:GetCooldownRemaining() or 999, + WakeOfAshes:IsKnown() and WakeOfAshes:GetCooldownRemaining() or 999, + DivineToll:IsKnown() and DivineToll:GetCooldownRemaining() or 999 + ) + ) +end + +-- actions.cooldowns=potion,if=buff.avenging_wrath.up|buff.crusade.up&buff.crusade.stack=10|fight_remains<25 +-- NYI + +-- actions.cooldowns+=/lights_judgment,if=spell_targets.lights_judgment>=2|!raid_event.adds.exists|raid_event.adds.in>75|raid_event.adds.up +CooldownsAPL:AddSpell( + LightsJudgment:CastableIf(function() + return Target:GetEnemies(8) >= 2 + end):SetTarget(Target) +) + +-- actions.cooldowns+=/use_item,name=algethar_puzzle_box,if=(cooldown.avenging_wrath.remains<5&!talent.crusade|cooldown.crusade.remains<5&talent.crusade)&(holy_power>=5&time<5|holy_power>=3&time>5) +-- actions.cooldowns+=/use_item,slot=trinket1,if=(buff.avenging_wrath.up|buff.crusade.up&buff.crusade.stack=10)&(!trinket.2.has_cooldown|trinket.2.cooldown.remains|variable.trinket_priority=1)|trinket.1.proc.any_dps.duration>=fight_remains +-- actions.cooldowns+=/use_item,slot=trinket2,if=(buff.avenging_wrath.up|buff.crusade.up&buff.crusade.stack=10)&(!trinket.1.has_cooldown|trinket.1.cooldown.remains|variable.trinket_priority=2)|trinket.2.proc.any_dps.duration>=fight_remains +-- actions.cooldowns+=/use_item,slot=trinket1,if=!variable.trinket_1_buffs&(trinket.2.cooldown.remains|!variable.trinket_2_buffs|!buff.crusade.up&cooldown.crusade.remains>20|!buff.avenging_wrath.up&cooldown.avenging_wrath.remains>20) +-- actions.cooldowns+=/use_item,slot=trinket2,if=!variable.trinket_2_buffs&(trinket.1.cooldown.remains|!variable.trinket_1_buffs|!buff.crusade.up&cooldown.crusade.remains>20|!buff.avenging_wrath.up&cooldown.avenging_wrath.remains>20) + +CooldownsAPL:AddItem( + DecorationOfFlame:UsableIf(function() + local result = Player:GetAuras():FindMy(AvengingWrath):IsUp() or + (Player:GetAuras():FindMy(Crusade):IsUp() and + Player:GetAuras():FindMy(Crusade):GetCount() == 10) + return result + end):SetTarget(Player) +) + +-- actions.cooldowns+=/shield_of_vengeance,if=(!talent.execution_sentence|cooldown.execution_sentence.remains<52)&fight_remains>15 +CooldownsAPL:AddSpell( + ShieldOfVengeance:CastableIf(function() + return not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() < 52 + end):SetTarget(Target) +) + +-- actions.cooldowns+=/avenging_wrath,if=((holy_power>=4&time<5|holy_power>=3&time>5)|talent.holy_avenger&cooldown.holy_avenger.remains=0)&(!talent.seraphim|!talent.final_reckoning|cooldown.seraphim.remains>0) +CooldownsAPL:AddSpell( + AvengingWrath:CastableIf(function() + return ( + Player:GetPower(HolyPower) >= 4 and Time:GetTime() < 5 or + Player:GetPower(HolyPower) >= 3 and Time:GetTime() > 5) and + (not HolyAvenger:IsKnown() or not FinalReckoning:IsKnown() or Seraphim:GetCooldownRemaining() > 0) + end):SetTarget(Player) +) + +-- actions.cooldowns+=/crusade,if=holy_power>=5&time<5|holy_power>=3&time>5 +CooldownsAPL:AddSpell( + Crusade:CastableIf(function() + return Crusade:GetCooldownRemaining() == 0 and (Player:GetPower(HolyPower) >= 5 and Time:GetTime() < 5 or + Player:GetPower(HolyPower) >= 3 and Time:GetTime() > 5) + end):SetTarget(Player):OnCast(function(spell) + Notifications:AddNotification(spell:GetIcon(), spell:GetName(), 10) + end) +) + +-- actions.cooldowns+=/holy_avenger,if=time_to_hpg=0&holy_power<=2&(buff.avenging_wrath.up|talent.crusade&(cooldown.crusade.remains=0|buff.crusade.up)|fight_remains<20) +CooldownsAPL:AddSpell( + HolyAvenger:CastableIf(function() + return TimeToHPG() == 0 and Player:GetPower(HolyPower) <= 2 and + ( + Player:GetAuras():FindMy(AvengingWrath):IsUp() or + Crusade:IsKnown() and (Crusade:GetCooldownRemaining() == 0 or Player:GetAuras():FindMy(Crusade):IsUp()) + or + Target:TimeToDie() < 20) + end):SetTarget(Player) +) + +-- actions.cooldowns+=/final_reckoning,if=(holy_power>=4&time<8|holy_power>=3&time>=8)&(cooldown.avenging_wrath.remains>gcd|cooldown.crusade.remains&(!buff.crusade.up|buff.crusade.stack>=10))&(time_to_hpg>0|holy_power=5)&(!talent.seraphim|buff.seraphim.up)&(!raid_event.adds.exists|raid_event.adds.up|raid_event.adds.in>40)&(!buff.avenging_wrath.up|holy_power=5|cooldown.hammer_of_wrath.remains) +CooldownsAPL:AddSpell( + FinalReckoning:CastableIf(function() + return (Player:GetPower(HolyPower) >= 4 and Time:GetTime() < 8 or + Player:GetPower(HolyPower) >= 3 and Time:GetTime() >= 8) and + (AvengingWrath:GetCooldownRemaining() > Player:GetGCD() or Crusade:GetCooldownRemaining() > 0 and + (not Player:GetAuras():FindMy(Crusade):IsUp() or Player:GetAuras():FindMy(Crusade):GetCount() >= 10)) + and + (TimeToHPG() > 0 or Player:GetPower(HolyPower) == 5) and + (not Seraphim:IsKnown() or Player:GetAuras():FindMy(Seraphim):IsUp()) and + (not Player:GetAuras():FindMy(AvengingWrath):IsUp() or Player:GetPower(HolyPower) == 5 or + HammerOfWrath:GetCooldownRemaining() > 0) + end):SetTarget(None):OnCast(function(self) + self:Click(Target:GetPosition()) + end) +) + +-- actions.finishers=variable,name=ds_castable,value=spell_targets.divine_storm>=2|buff.empyrean_power.up&!debuff.judgment.up&!buff.divine_purpose.up|buff.crusade.up&buff.crusade.stack<10&buff.empyrean_legacy.up&!talent.justicars_vengeance +FinishersAPL:AddVariable( + 'ds_castable', + function() + return Player:GetEnemies(8) >= 2 and Player:InMelee(Target) + end +) + +-- actions.finishers+=/seraphim,if= +-- ( +-- cooldown.avenging_wrath.remains > 15 | cooldown.crusade.remains > 15 +-- ) & +-- !talent.final_reckoning & +-- ( +-- !talent.execution_sentence | spell_targets.divine_storm >= 5 +-- ) & +-- fight_remains < 15 & fight_remains > 5 | buff.crusade.up & buff.crusade.stack < 10 +FinishersAPL:AddSpell( + Seraphim:CastableIf(function() + return (AvengingWrath:GetCooldownRemaining() > 15 or Crusade:GetCooldownRemaining() > 15) and + not FinalReckoning:IsKnown() and + (not ExecutionSentence:IsKnown() or Player:GetEnemies(8) >= 5) and + Target:TimeToDie() < 15 and Target:TimeToDie() > 5 or + Player:GetAuras():FindMy(Crusade):IsUp() and Player:GetAuras():FindMy(Crusade):GetCount() < 10 + end):SetTarget(Player) +) + +-- actions.finishers+=/execution_sentence,if=(buff.crusade.down&cooldown.crusade.remains>10|buff.crusade.stack>=3|cooldown.avenging_wrath.remains>10)&(!talent.final_reckoning|cooldown.final_reckoning.remains>10)&target.time_to_die>8&(spell_targets.divine_storm<5|talent.executioners_wrath) +FinishersAPL:AddSpell( + ExecutionSentence:CastableIf(function() + return (not Player:GetAuras():FindMy(Crusade):IsUp() and Crusade:GetCooldownRemaining() > 10 or + Player:GetAuras():FindMy(Crusade):GetCount() >= 3 or + AvengingWrath:GetCooldownRemaining() > 10) and + (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() > 10) and + Target:TimeToDie() > 8 and + (Target:GetEnemies(8) < 5 or ExecutionersWrath:IsKnown()) + end):SetTarget(Target) +) +-- actions.finishers+=/radiant_decree,if=(buff.crusade.down&cooldown.crusade.remains>5|buff.crusade.stack>=3|cooldown.avenging_wrath.remains>5)&(!talent.final_reckoning|cooldown.final_reckoning.remains>5) +FinishersAPL:AddSpell( + RadiantDecree:CastableIf(function() + return (not Player:GetAuras():FindMy(Crusade):IsUp() and Crusade:GetCooldownRemaining() > 5 or + Player:GetAuras():FindMy(Crusade):GetCount() >= 3 or + AvengingWrath:GetCooldownRemaining() > 5) and + (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() > 5) + end):SetTarget(Target) +) + +-- actions.finishers+=/divine_storm,if= +-- variable.ds_castable & +-- ( +-- buff.crusade.up & buff.crusade.stack < 10 +-- ) & ( +-- ( +-- !talent.crusade | cooldown.crusade.remains > gcd * 3 +-- ) & +-- ( +-- !talent.execution_sentence | cooldown.execution_sentence.remains > gcd * 6 |cooldown.execution_sentence.remains > gcd* 4 & holy_power >= 4 | target.time_to_die < 8 | spell_targets.divine_storm >= 5 | !talent.seraphim & cooldown.execution_sentence.remains > gcd * 2 +-- ) &( +-- !talent.final_reckoning | cooldown.final_reckoning.remains>gcd * 6 | cooldown.final_reckoning.remains > gcd * 4 & holy_power >= 4 | !talent.seraphim & cooldown.final_reckoning.remains > gcd * 2 +-- ) | +-- talent.holy_avenger & cooldown.holy_avenger.remains < gcd * 3 | buff.holy_avenger.up | buff.crusade.up & buff.crusade.stack < 10 +-- ) +FinishersAPL:AddSpell( + DivineStorm:CastableIf(function() + return FinishersAPL:GetVariable('ds_castable') and + (Player:GetAuras():FindMy(Crusade):IsUp() and + Player:GetAuras():FindMy(Crusade):GetCount() < 10) and + (not Crusade:IsKnown() or Crusade:GetCooldownRemaining() > 3) and + (not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() > 6 or + ExecutionSentence:GetCooldownRemaining() > 4 and Player:GetPower(HolyPower) >= 4 or + Target:TimeToDie() < 8 or + Target:GetEnemies(8) >= 5 or + not Seraphim:IsKnown() and ExecutionSentence:GetCooldownRemaining() > 2) and + (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() > 6 or + FinalReckoning:GetCooldownRemaining() > 4 and Player:GetPower(HolyPower) >= 4 or + not Seraphim:IsKnown() and FinalReckoning:GetCooldownRemaining() > 2) or + HolyAvenger:IsKnown() and HolyAvenger:GetCooldownRemaining() < 3 or + Player:GetAuras():FindMy(HolyAvenger):IsUp() or + Player:GetAuras():FindMy(Crusade):IsUp() and + Player:GetAuras():FindMy(Crusade):GetCount() < 10 + end):SetTarget(Target) +) + +-- actions.finishers+=/justicars_vengeance,if= +-- (!talent.crusade | cooldown.crusade.remains > gcd*3 ) & +-- (!talent.execution_sentence | cooldown.execution_sentence.remains > gcd*6 | cooldown.execution_sentence.remains > gcd * 4 & holy_power >= 4 | target.time_to_die < 8 | !talent.seraphim & cooldown.execution_sentence.remains > gcd * 2 ) & +-- (!talent.final_reckoning | cooldown.final_reckoning.remains > gcd* 6 | cooldown.final_reckoning.remains > gcd * 4 & holy_power >= 4 | !talent.seraphim & cooldown.final_reckoning.remains > gcd * 2) | +-- talent.holy_avenger & cooldown.holy_avenger.remains < gcd*3 | buff.holy_avenger.up | buff.crusade.up & buff.crusade.stack < 10 +FinishersAPL:AddSpell( + JusticarsVengeance:CastableIf(function() + local a = (not Crusade:IsKnown() or Crusade:GetCooldownRemaining() > Player:GetGCD() * 3) + + local b = ( + not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() > Player:GetGCD() * 6 or + ExecutionSentence:GetCooldownRemaining() > Player:GetGCD() * 4 and Player:GetPower(HolyPower) >= 4 or + Target:TimeToDie() < 8 or + not Seraphim:IsKnown() and ExecutionSentence:GetCooldownRemaining() > Player:GetGCD() * 2) + + local c = not FinalReckoning:IsKnown() or + ( + FinalReckoning:GetCooldownRemaining() > Player:GetGCD() * 6 or + FinalReckoning:GetCooldownRemaining() > Player:GetGCD() * 4 and Player:GetPower(HolyPower) >= 4 or + not Seraphim:IsKnown() and FinalReckoning:GetCooldownRemaining() > Player:GetGCD() * 2) + + local d = HolyAvenger:IsKnown() and HolyAvenger:GetCooldownRemaining() < Player:GetGCD() * 3 or + Player:GetAuras():FindMy(HolyAvenger):IsUp() or + Player:GetAuras():FindMy(Crusade):IsUp() and Player:GetAuras():FindMy(Crusade):GetCount() < 10 + + local result = (a and b and c) or d + + return result + end):SetTarget(Target) +) + +-- actions.finishers+=/templars_verdict,if=(!talent.crusade|cooldown.crusade.remains>gcd*3)&(!talent.execution_sentence|cooldown.execution_sentence.remains>gcd*6|cooldown.execution_sentence.remains>gcd*4&holy_power>=4|target.time_to_die<8|!talent.seraphim&cooldown.execution_sentence.remains>gcd*2)&(!talent.final_reckoning|cooldown.final_reckoning.remains>gcd*6|cooldown.final_reckoning.remains>gcd*4&holy_power>=4|!talent.seraphim&cooldown.final_reckoning.remains>gcd*2)|talent.holy_avenger&cooldown.holy_avenger.remains 3) and + (not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() > 6 or + ExecutionSentence:GetCooldownRemaining() > 4 and Player:GetPower(HolyPower) >= 4 or + Target:TimeToDie() < 8 or + not Seraphim:IsKnown() and ExecutionSentence:GetCooldownRemaining() > 2) and + (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() > 6 or + FinalReckoning:GetCooldownRemaining() > 4 and Player:GetPower(HolyPower) >= 4 or + not Seraphim:IsKnown() and FinalReckoning:GetCooldownRemaining() > 2) or + HolyAvenger:IsKnown() and HolyAvenger:GetCooldownRemaining() < 3 or + Player:GetAuras():FindMy(HolyAvenger):IsUp() or + Player:GetAuras():FindMy(Crusade):IsUp() and + Player:GetAuras():FindMy(Crusade):GetCount() < 10 + end):SetTarget(Target) +) + + +-- actions.es_fr_active+=/call_action_list,name=finishers,if= +-- holy_power=5 | debuff.judgment.up | debuff.final_reckoning.up & +-- (debuff.final_reckoning.remains < gcd.max | spell_targets.divine_storm >= 2 & !talent.execution_sentence) | +-- debuff.execution_sentence.up & debuff.execution_sentence.remains < gcd.max +ESFRActiveAPL:AddAPL( + FinishersAPL, + function() + return Player:GetPower(HolyPower) == 5 or + Target:GetAuras():Find(Judgment):IsUp() or + Target:GetAuras():Find(FinalReckoning):IsUp() and + ( + Target:GetAuras():Find(FinalReckoning):GetRemainingTime() < Player:GetMaxGCD() or + Player:GetEnemies(8) >= 2 and not ExecutionSentence:IsKnown() + ) or + Target:GetAuras():Find(ExecutionSentence):IsUp() and + Target:GetAuras():Find(ExecutionSentence):GetRemainingTime() < Player:GetMaxGCD() + end +) + +-- actions.es_fr_active+=/divine_toll,if=holy_power<=2 +ESFRActiveAPL:AddSpell( + DivineToll:CastableIf(function() + return Player:GetPower(HolyPower) <= 2 + end):SetTarget(Player) +) + + +-- actions.es_fr_active+=/wake_of_ashes,if=holy_power<=2&(debuff.final_reckoning.up&debuff.final_reckoning.remains=5&talent.divine_resonance&talent.execution_sentence) +ESFRActiveAPL:AddSpell( + WakeOfAshes:CastableIf(function() + return Player:GetPower(HolyPower) <= 2 and ( + Target:GetAuras():Find(FinalReckoning):IsUp() and + Target:GetAuras():Find(FinalReckoning):GetRemainingTime() < Player:GetGCD() * 2 and + not DivineResonance:IsKnown() or Target:GetAuras():Find(ExecutionSentence):IsUp() and + Target:GetAuras():Find(ExecutionSentence):GetRemainingTime() < Player:GetGCD() or + Target:GetEnemies(8) >= 5 and DivineResonance:IsKnown() and ExecutionSentence:IsKnown() + ) + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/blade_of_justice,if=talent.expurgation&(!talent.divine_resonance&holy_power<=3|holy_power<=2) +ESFRActiveAPL:AddSpell( + BladeOfJustice:CastableIf(function() + return Expurgation:IsKnown() and + (not DivineResonance:IsKnown() and Player:GetPower(HolyPower) <= 3 or + Player:GetPower(HolyPower) <= 2) + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/judgment,if=!debuff.judgment.up&holy_power>=2 +ESFRActiveAPL:AddSpell( + Judgment:CastableIf(function() + return not Target:GetAuras():Find(Judgment):IsUp() and Player:GetPower(HolyPower) >= 2 + end):SetTarget(Target) +) +-- actions.es_fr_active+=/call_action_list,name=finishers +ESFRActiveAPL:AddAPL( + FinishersAPL, + function() + return true + end +) + +-- actions.es_fr_active+=/wake_of_ashes,if=holy_power<=2 +ESFRActiveAPL:AddSpell( + WakeOfAshes:CastableIf(function() + return Player:GetPower(HolyPower) <= 2 + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/blade_of_justice,if=holy_power<=3 +ESFRActiveAPL:AddSpell( + BladeOfJustice:CastableIf(function() + return Player:GetPower(HolyPower) <= 3 + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/judgment,if=!debuff.judgment.up +ESFRActiveAPL:AddSpell( + Judgment:CastableIf(function() + return not Target:GetAuras():Find(Judgment):IsUp() + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/hammer_of_wrath +ESFRActiveAPL:AddSpell( + HammerOfWrath:CastableIf(function() + return HammerOfWrath:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/crusader_strike +ESFRActiveAPL:AddSpell( + CrusaderStrike:CastableIf(function() + return CrusaderStrike:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/arcane_torrent +-- NYI + +-- actions.es_fr_active+=/exorcism +ESFRActiveAPL:AddSpell( + Exorcism:CastableIf(function() + return Exorcism:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.es_fr_active+=/consecration +ESFRActiveAPL:AddSpell( + Consecration:CastableIf(function() + return Consecration:IsKnownAndUsable() and not IsPlayerMoving() + end):SetTarget(Target) +) + +-- actions.es_fr_pooling=seraphim,if=holy_power=5&(!talent.final_reckoning|cooldown.final_reckoning.remains<=gcd*3)&(!talent.execution_sentence|cooldown.execution_sentence.remains<=gcd*3|talent.final_reckoning) +ESFRPoolingAPL:AddSpell( + Seraphim:CastableIf(function() + return Player:GetPower(HolyPower) == 5 and + (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() <= Player:GetGCD() * 3) and + ( + not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() <= Player:GetGCD() * 3 or + FinalReckoning:IsKnown()) + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/call_action_list,name=finishers,if=holy_power=5|debuff.final_reckoning.up|buff.crusade.up&buff.crusade.stack<10 +ESFRPoolingAPL:AddAPL( + FinishersAPL, + function() + return Player:GetPower(HolyPower) == 5 or Target:GetAuras():Find(FinalReckoning):IsUp() or + Player:GetAuras():FindMy(Crusade):IsUp() and Player:GetAuras():FindMy(Crusade):GetCount() < 10 + end +) + +-- actions.es_fr_pooling+=/hammer_of_wrath,if=talent.vanguards_momentum +ESFRPoolingAPL:AddSpell( + HammerOfWrath:CastableIf(function() + return VanguardsMomentum:IsKnown() + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/wake_of_ashes,if=holy_power<=2&talent.ashes_to_dust&(cooldown.crusade.remains|cooldown.avenging_wrath.remains) +ESFRPoolingAPL:AddSpell( + WakeOfAshes:CastableIf(function() + return Player:GetPower(HolyPower) <= 2 and AshesToDust:IsKnown() and + (Crusade:GetCooldownRemaining() > 0 or AvengingWrath:GetCooldownRemaining() > 0) + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/blade_of_justice,if=holy_power<=3 +ESFRPoolingAPL:AddSpell( + BladeOfJustice:CastableIf(function() + return Player:GetPower(HolyPower) <= 3 + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/judgment,if=!debuff.judgment.up +ESFRPoolingAPL:AddSpell( + Judgment:CastableIf(function() + return not Target:GetAuras():Find(Judgment):IsUp() + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/hammer_of_wrath +ESFRPoolingAPL:AddSpell( + HammerOfWrath:CastableIf(function() + return HammerOfWrath:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/crusader_strike,if=cooldown.crusader_strike.charges_fractional>=1.75&(holy_power<=2|holy_power<=3&cooldown.blade_of_justice.remains>gcd*2|holy_power=4&cooldown.blade_of_justice.remains>gcd*2&cooldown.judgment.remains>gcd*2) +ESFRPoolingAPL:AddSpell( + CrusaderStrike:CastableIf(function() + return CrusaderStrike:GetChargesFractional() >= 1.75 and + (Player:GetPower(HolyPower) <= 2 or + Player:GetPower(HolyPower) <= 3 and BladeOfJustice:GetCooldownRemaining() > Player:GetGCD() * 2 or + Player:GetPower(HolyPower) == 4 and BladeOfJustice:GetCooldownRemaining() > Player:GetGCD() * 2 and + Judgment:GetCooldownRemaining() > Player:GetGCD() * 2) + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/seraphim,if=!talent.final_reckoning&cooldown.execution_sentence.remains<=gcd*3 +ESFRPoolingAPL:AddSpell( + Seraphim:CastableIf(function() + return not FinalReckoning:IsKnown() and ExecutionSentence:GetCooldownRemaining() <= Player:GetGCD() * 3 + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/call_action_list,name=finishers +ESFRPoolingAPL:AddAPL( + FinishersAPL, + function() + return true + end +) + +-- actions.es_fr_pooling+=/crusader_strike +ESFRPoolingAPL:AddSpell( + CrusaderStrike:CastableIf(function() + return CrusaderStrike:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/arcane_torrent,if=holy_power<=4 +-- NYI + +-- actions.es_fr_pooling+=/exorcism +ESFRPoolingAPL:AddSpell( + Exorcism:CastableIf(function() + return Exorcism:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/seraphim,if= +-- ( +-- !talent.final_reckoning | cooldown.final_reckoning.remains <= gcd * 3 +-- ) & ( +-- !talent.execution_sentence | cooldown.execution_sentence.remains <= gcd * 3 | talent.final_reckoning +-- ) +ESFRPoolingAPL:AddSpell( + Seraphim:CastableIf(function() + return (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() <= Player:GetGCD() * 3) and + (not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() <= Player:GetGCD() * 3 or + FinalReckoning:IsKnown()) + end):SetTarget(Target) +) + +-- actions.es_fr_pooling+=/consecration +ESFRPoolingAPL:AddSpell( + Consecration:CastableIf(function() + return Consecration:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.generators=call_action_list,name=finishers,if=holy_power=5|(debuff.judgment.up|holy_power=4)&buff.divine_resonance.up|buff.holy_avenger.up +GeneratorsAPL:AddAPL( + FinishersAPL, + function() + return Player:GetPower(HolyPower) == 5 or + (Target:GetAuras():Find(Judgment):IsUp() or Player:GetPower(HolyPower) == 4) and + Player:GetAuras():FindMy(DivineResonance):IsUp() or + Player:GetAuras():FindMy(HolyAvenger):IsUp() + end +) + +-- actions.generators+=/hammer_of_wrath,if=talent.zealots_paragon +GeneratorsAPL:AddSpell( + HammerOfWrath:CastableIf(function() + return ZealotsParagon:IsKnown() + end):SetTarget(Target) +) + +-- actions.generators+=/wake_of_ashes,if=holy_power<=2&talent.ashes_to_dust&(cooldown.avenging_wrath.remains|cooldown.crusade.remains) +GeneratorsAPL:AddSpell( + WakeOfAshes:CastableIf(function() + return Player:GetPower(HolyPower) <= 2 and AshesToDust:IsKnown() and + (AvengingWrath:GetCooldownRemaining() > 0 or Crusade:GetCooldownRemaining() > 0) + end):SetTarget(Target) +) + +-- actions.generators+=/divine_toll,if= +-- holy_power <= 2 & +-- !debuff.judgment.up & +-- ( +-- !talent.seraphim | buff.seraphim.up +-- ) & +-- !talent.final_reckoning & +-- (!talent.execution_sentence | fight_remains < 8 | spell_targets.divine_storm >= 5 ) & +-- (cooldown.avenging_wrath.remains > 15 | cooldown.crusade.remains > 15 | fight_remains < 8) +GeneratorsAPL:AddSpell( + DivineToll:CastableIf(function() + local a = Player:GetPower(HolyPower) <= 2 + local b = Target:GetAuras():Find(Judgment):IsDown() + local c = (not Seraphim:IsKnown() or Player:GetAuras():FindMy(Seraphim):IsUp()) + local d = not FinalReckoning:IsKnown() + local e = (not ExecutionSentence:IsKnown() or Target:TimeToDie() < 8 or Player:GetEnemies(8) >= 5) + local f = ( + AvengingWrath:GetCooldownRemaining() > 15 or Crusade:GetCooldownRemaining() > 15 or Target:TimeToDie() < 8) + + return a and b and c and e and f + end):SetTarget(Player) +) + +-- actions.generators+=/judgment,if=!debuff.judgment.up&holy_power>=2 +GeneratorsAPL:AddSpell( + Judgment:CastableIf(function() + return Target:GetAuras():Find(Judgment):IsDown() and Player:GetPower(HolyPower) >= 2 + end):SetTarget(Target) +) + +-- actions.generators+=/wake_of_ashes,if=(holy_power=0|holy_power<=2&cooldown.blade_of_justice.remains>gcd*2)&(!raid_event.adds.exists|raid_event.adds.in>20|raid_event.adds.up)&(!talent.seraphim|cooldown.seraphim.remains>5)&(!talent.execution_sentence|cooldown.execution_sentence.remains>15|target.time_to_die<8|spell_targets.divine_storm>=5)&(!talent.final_reckoning|cooldown.final_reckoning.remains>15|fight_remains<8)&(cooldown.avenging_wrath.remains|cooldown.crusade.remains) +GeneratorsAPL:AddSpell( + WakeOfAshes:CastableIf(function() + return (Player:GetPower(HolyPower) == 0 or Player:GetPower(HolyPower) <= 2 and + BladeOfJustice:GetCooldownRemaining() > Player:GetGCD() * 2) and + (not Seraphim:IsKnown() or Seraphim:GetCooldownRemaining() > 5) and + (not ExecutionSentence:IsKnown() or ExecutionSentence:GetCooldownRemaining() > 15 or + Target:TimeToDie() < 8 or + Player:GetEnemies():GetCount() >= 5) and + (not FinalReckoning:IsKnown() or FinalReckoning:GetCooldownRemaining() > 15 or + Target:TimeToDie() < 8) and + (AvengingWrath:GetCooldownRemaining() > 0 or Crusade:GetCooldownRemaining() > 0) + end):SetTarget(Target) +) + +-- actions.generators+=/call_action_list,name=finishers,if=holy_power>=3&buff.crusade.up&buff.crusade.stack<10 +GeneratorsAPL:AddAPL( + FinishersAPL, + function() + return Player:GetPower(HolyPower) >= 3 and Player:GetAuras():FindMy(Crusade):IsUp() and + Player:GetAuras():FindMy(Crusade):GetCount() < 10 + end +) + +-- actions.generators+=/exorcism +GeneratorsAPL:AddSpell( + Exorcism:CastableIf(function() + return Exorcism:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.generators+=/judgment,if=!debuff.judgment.up +GeneratorsAPL:AddSpell( + Judgment:CastableIf(function() + return Target:GetAuras():Find(Judgment):IsDown() + end):SetTarget(Target) +) + +-- actions.generators+=/hammer_of_wrath +GeneratorsAPL:AddSpell( + HammerOfWrath:CastableIf(function() + return HammerOfWrath:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.generators+=/blade_of_justice,if=holy_power<=3 +GeneratorsAPL:AddSpell( + BladeOfJustice:CastableIf(function() + return Player:GetPower(HolyPower) <= 3 + end):SetTarget(Target) +) + +-- actions.generators+=/call_action_list,name=finishers,if=(target.health.pct<=20|buff.avenging_wrath.up|buff.crusade.up|buff.empyrean_power.up) +GeneratorsAPL:AddAPL( + FinishersAPL, + function() + return Target:GetHealthPercent() <= 20 or Player:GetAuras():FindMy(AvengingWrath):IsUp() or + Player:GetAuras():FindMy(Crusade):IsUp() + end +) + +-- actions.generators+=/consecration,if=!consecration.up&spell_targets.divine_storm>=2 +GeneratorsAPL:AddSpell( + Consecration:CastableIf(function() + return Consecration:IsKnownAndUsable() and Player:GetEnemies(8) >= 2 + end):SetTarget(Target) +) + +-- actions.generators+=/crusader_strike,if=cooldown.crusader_strike.charges_fractional>=1.75&(holy_power<=2|holy_power<=3&cooldown.blade_of_justice.remains>gcd*2|holy_power=4&cooldown.blade_of_justice.remains>gcd*2&cooldown.judgment.remains>gcd*2) +GeneratorsAPL:AddSpell( + CrusaderStrike:CastableIf(function() + return CrusaderStrike:IsKnownAndUsable() and + CrusaderStrike:GetChargesFractional() >= 1.75 and + (Player:GetPower(HolyPower) <= 2 or Player:GetPower(HolyPower) <= 3 and + BladeOfJustice:GetCooldownRemaining() > Player:GetGCD() * 2 or + Player:GetPower(HolyPower) == 4 and + BladeOfJustice:GetCooldownRemaining() > Player:GetGCD() * 2 and + Judgment:GetCooldownRemaining() > Player:GetGCD() * 2) + end):SetTarget(Target) +) + +-- actions.generators+=/call_action_list,name=finishers +GeneratorsAPL:AddAPL( + FinishersAPL, + function() + return true + end +) + +-- actions.generators+=/consecration,if=!consecration.up +GeneratorsAPL:AddSpell( + Consecration:CastableIf(function() + return Player:GetAuras():FindMy(Consecration):IsDown() + end):SetTarget(Target) +) + +-- actions.generators+=/crusader_strike +GeneratorsAPL:AddSpell( + CrusaderStrike:CastableIf(function() + return CrusaderStrike:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions.generators+=/arcane_torrent +-- NYI + +-- actions.generators+=/consecration +GeneratorsAPL:AddSpell( + Consecration:CastableIf(function() + return Consecration:IsKnownAndUsable() + end):SetTarget(Target) +) + +-- actions=auto_attack +-- NYI + +-- actions+=/rebuke +DefaultAPL:AddSpell( + Rebuke:CastableIf(function(self) + return RebukeTarget:Exists() and Player:InMelee(RebukeTarget) and + self:IsKnownAndUsable() and + not Player:IsCastingOrChanneling() + end):SetTarget(RebukeTarget):OnCast(function(spell) + Notifications:AddNotification(spell:GetIcon(), spell:GetName()) + end) +) + +-- actions+=/call_action_list,name=cooldowns +DefaultAPL:AddAPL( + CooldownsAPL, + function() + return true + end +) + +-- actions+=/call_action_list,name=es_fr_pooling,if=(talent.execution_sentence&cooldown.execution_sentence.remains<9&spell_targets.divine_storm<5|talent.final_reckoning&cooldown.final_reckoning.remains<9)&(!buff.crusade.up|buff.crusade.stack=10)&target.time_to_die>8 +DefaultAPL:AddAPL( + ESFRPoolingAPL, + function() + return ExecutionSentence:IsKnown() and ExecutionSentence:GetCooldownRemaining() < 9 and Target:GetEnemies(8) < 5 + or + FinalReckoning:IsKnown() and FinalReckoning:GetCooldownRemaining() < 9 and + (not Player:GetAuras():FindMy(Crusade):IsUp() or Player:GetAuras():FindMy(Crusade):GetCount() == 10) and + Target:TimeToDie() > 8 + end +) + +-- actions+=/call_action_list,name=es_fr_active,if=debuff.execution_sentence.up|debuff.final_reckoning.up +DefaultAPL:AddAPL( + ESFRActiveAPL, + function() + return Target:GetAuras():Find(ExecutionSentence):IsUp() or Target:GetAuras():Find(FinalReckoning):IsUp() + end +) + +-- actions+=/call_action_list,name=generators +DefaultAPL:AddAPL( + GeneratorsAPL, + function() + return true + end +) + +local notified = false + +RetributionModule:Sync(function() + if Player:IsAffectingCombat() and not IsMounted() then + DefaultAPL:Execute() + end +end) + +Bastion:Register(RetributionModule)