Basic rotations that work
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OkRotations/AugmentationEvoker.lua

319 lines
9.9 KiB

local Tinkr, Bastion = ...
local AugmentationModule = Bastion.Module:New('AugmentationEvoker')
local Player = Bastion.UnitManager:Get('player')
local Target = Bastion.UnitManager:Get('target')
local Focus = Bastion.UnitManager:Get('focus')
local SpellBook = Bastion.SpellBook:New()
-- Ensure EventManager is properly initialized
local EventManager = Bastion.EventManager:New()
-- Constants for Ebon Might logic
local EBON_MIGHT_MIN_ENEMIES = 1
local EBON_MIGHT_MIN_TTD = 12 -- seconds
local EBON_MIGHT_MIN_ESSENCE = 50 -- percent of max essence
-- Spells
local Prescience = SpellBook:GetSpell(409311)
local EbonMight = SpellBook:GetSpell(395152)
local FireBreath = SpellBook:GetSpell(382266)
local Upheaval = SpellBook:GetSpell(396286)
local Eruption = SpellBook:GetSpell(395160)
local LivingFlame = SpellBook:GetSpell(361469)
local TipTheScales = SpellBook:GetSpell(370553)
local Hover = SpellBook:GetSpell(358267)
local AzureStrike = SpellBook:GetSpell(362969)
local BlisteringScales = SpellBook:GetSpell(360827)
local TimeSkip = SpellBook:GetSpell(404977)
-- Buffs and Debuffs
local PrescienceBuff = SpellBook:GetSpell(410089)
local EbonMightBuff = SpellBook:GetSpell(395296)
local EssenceBurstBuff = SpellBook:GetSpell(369299)
-- Talents
local LeapingFlames = SpellBook:GetSpell(370901)
-- Create APLs
local CooldownAPL = Bastion.APL:New('cooldown')
local BuffAPL = Bastion.APL:New('buff')
local DamageAPL = Bastion.APL:New('damage')
local MovementAPL = Bastion.APL:New('movement')
-- Empowered spell handling
local empowering = {}
function Player:GetEmpoweredStage()
local stage = 0
local _, _, _, startTime, _, _, _, spellID, _, numStages = UnitChannelInfo(self:GetOMToken())
if numStages and numStages > 0 then
startTime = startTime / 1000
local currentTime = GetTime()
local stageDuration = 0
for i = 1, numStages do
stageDuration = stageDuration + GetUnitEmpowerStageDuration((self:GetOMToken()), i - 1) / 1000
if startTime + stageDuration > currentTime then
break
end
stage = i
end
end
return stage
end
EventManager:RegisterWoWEvent("UNIT_SPELLCAST_EMPOWER_START", function(...)
local unit, _, id = ...
if not unit then return end
local guid = UnitGUID(unit)
if not guid then return end
empowering[guid] = -1
end)
EventManager:RegisterWoWEvent("UNIT_SPELLCAST_EMPOWER_STOP", function(...)
local unit, _, id = ...
if not unit then return end
local guid = UnitGUID(unit)
if not guid then return end
empowering[guid] = nil
end)
function Player:GetUnitEmpowerStage()
local name, _, _, startTime, endTime, _, _, _, _, numStages = UnitChannelInfo(self:GetOMToken())
if name and empowering[self:GetGUID()] == -1 then
empowering[self:GetGUID()] = numStages
end
if not name then
return empowering[self:GetGUID()] or 0
end
local getStageDuration = function(stage)
if stage == numStages then
return GetUnitEmpowerHoldAtMaxTime(self:GetOMToken())
else
return GetUnitEmpowerStageDuration(self:GetOMToken(), stage - 1)
end
end
local time = GetTime() - (startTime / 1000)
local higheststage = 0
local sumdur = 0
for i = 1, numStages - 1 do
local duration = getStageDuration(i) / 1000
sumdur = sumdur + duration
if time > sumdur then
higheststage = i
end
end
return higheststage
end
-- Helper Functions
local function GetPrescienceTargets()
local targets = Bastion.List:New()
if Focus:Exists() and not Focus:IsTank() and Player:GetDistance(Focus) <= 40 and Player:CanSee(Focus) then
targets:push(Focus)
end
Bastion.UnitManager:EnumFriends(function(unit)
if targets:count() >= 2 then return true end
if unit ~= Focus and unit:IsPlayer() and not unit:IsTank() and Player:GetDistance(unit) <= 40 and Player:CanSee(unit) then
local aura = unit:GetAuras():FindMy(PrescienceBuff)
if not aura:IsUp() or aura:GetRemainingTime() < 10 then
targets:push(unit)
end
end
end)
return targets
end
local function IsEbonMightActive()
return Player:GetAuras():FindMy(EbonMightBuff):IsUp()
end
local function IsEssenceCapped()
return Player:GetPower() >= Player:GetMaxPower() or Player:GetAuras():FindMy(EssenceBurstBuff):GetCount() == 2
end
local function ShouldCastEbonMight()
local viableEnemyCount = 0
local playerEssencePercent = (Player:GetPower() / Player:GetMaxPower()) * 100
Bastion.UnitManager:EnumEnemies(function(unit)
if unit:IsAffectingCombat() and unit:TimeToDie() >= EBON_MIGHT_MIN_TTD then
viableEnemyCount = viableEnemyCount + 1
end
end)
local isBossFight = Target:Exists() and Target:IsBoss()
local hasEnoughEssence = playerEssencePercent >= EBON_MIGHT_MIN_ESSENCE
if isBossFight then
return hasEnoughEssence and Target:TimeToDie() >= EBON_MIGHT_MIN_TTD
else
return viableEnemyCount >= EBON_MIGHT_MIN_ENEMIES and hasEnoughEssence
end
end
-- Custom Units
local PrescienceTarget = Bastion.UnitManager:CreateCustomUnit('presciencetarget', function()
local targets = GetPrescienceTargets()
return targets:count() > 0 and targets:peek() or Player
end)
local EbonMightTarget = Bastion.UnitManager:CreateCustomUnit('ebonmighttarget', function()
local target = nil
Bastion.UnitManager:EnumFriends(function(unit)
if unit:IsPlayer() and Player:GetDistance(unit) <= 40 and Player:CanSee(unit) then
target = unit
return true
end
end)
return target or Player
end)
local DamageTarget = Bastion.UnitManager:CreateCustomUnit('damagetarget', function()
local target = nil
local highestHealth = 0
Bastion.UnitManager:EnumEnemies(function(unit)
if unit:IsAffectingCombat() and Player:IsWithinCombatDistance(unit, 40) and Player:CanSee(unit) then
local health = unit:GetHealth()
if health > highestHealth then
target = unit
highestHealth = health
end
end
end)
return target or Target
end)
local TankTarget = Bastion.UnitManager:CreateCustomUnit('tanktarget', function()
local tank = nil
Bastion.UnitManager:EnumFriends(function(unit)
if unit:IsTank() and Player:GetDistance(unit) <= 40 and Player:CanSee(unit) then
tank = unit
return true
end
end)
return tank or Player
end)
-- Cooldown APL
CooldownAPL:AddSpell(
EbonMight:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and ShouldCastEbonMight()
end):SetTarget(EbonMightTarget)
)
CooldownAPL:AddSpell(
TipTheScales:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
IsEbonMightActive() and (FireBreath:IsKnownAndUsable() or Upheaval:IsKnownAndUsable())
end):SetTarget(Player)
)
CooldownAPL:AddSpell(
TimeSkip:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Player)
)
-- Buff APL
BuffAPL:AddSpell(
Prescience:CastableIf(function(self)
return GetPrescienceTargets():count() > 0 and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(PrescienceTarget):OnCast(function(self)
local targets = GetPrescienceTargets()
if targets:count() > 1 then
self:Cast(targets[2] or Player)
end
end)
)
BuffAPL:AddSpell(
BlisteringScales:CastableIf(function(self)
return TankTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
not TankTarget:GetAuras():FindMy(BlisteringScales):IsUp()
end):SetTarget(TankTarget)
)
-- Damage APL
DamageAPL:AddSpell(
FireBreath:CastableIf(function(self)
return DamageTarget:IsAffectingCombat() and IsEbonMightActive()
end):SetTarget(DamageTarget):OnCast(function(self)
local empowerStage = Player:GetUnitEmpowerStage()
if empowerStage >= 1 then
C_Timer.After(0.1, function()
self:ForceCast(DamageTarget)
end)
end
end)
)
DamageAPL:AddSpell(
Upheaval:CastableIf(function(self)
return DamageTarget:IsAffectingCombat() and IsEbonMightActive()
end):SetTarget(DamageTarget):OnCast(function(self)
local empowerStage = Player:GetUnitEmpowerStage()
if empowerStage >= 1 then
self:ForceCast(DamageTarget)
end
end)
)
DamageAPL:AddSpell(
Eruption:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
(IsEbonMightActive() or IsEssenceCapped())
end):SetTarget(DamageTarget)
)
DamageAPL:AddSpell(
LivingFlame:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
(LeapingFlames:IsKnown() or not FireBreath:IsKnownAndUsable())
end):SetTarget(DamageTarget)
)
-- Movement APL
MovementAPL:AddSpell(
Hover:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(Hover):IsUp()
end):SetTarget(Player)
)
MovementAPL:AddSpell(
AzureStrike:CastableIf(function(self)
return self:IsKnownAndUsable() and Player:IsMoving() and not Player:GetAuras():FindMy(Hover):IsUp()
end):SetTarget(DamageTarget)
)
-- Module Sync
AugmentationModule:Sync(function()
-- Check if the player is mounted
if Player:IsMounted() then
return -- Exit the function if mounted, effectively disabling all APLs
end
if not Player:IsAffectingCombat() then
BuffAPL:Execute()
return
end
CooldownAPL:Execute()
BuffAPL:Execute()
if DamageAPL:Execute() then
return
end
MovementAPL:Execute()
end)
Bastion:Register(AugmentationModule)