parent
306948de16
commit
03037ebeb8
@ -0,0 +1,319 @@ |
||||
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) |
Loading…
Reference in new issue