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.
766 lines
55 KiB
766 lines
55 KiB
--- ============================ HEADER ============================
|
|
--- ======= LOCALIZE =======
|
|
-- Addon
|
|
local addonName, addonTable = ...
|
|
-- HeroDBC
|
|
local DBC = HeroDBC.DBC
|
|
-- HeroLib
|
|
local HL = HeroLib
|
|
local Cache = HeroCache
|
|
local Unit = HL.Unit
|
|
local Player = Unit.Player
|
|
local Target = Unit.Target
|
|
local Pet = Unit.Pet
|
|
local Spell = HL.Spell
|
|
local MultiSpell = HL.MultiSpell
|
|
local Item = HL.Item
|
|
-- HeroRotation
|
|
local HR = HeroRotation
|
|
local Cast = HR.Cast
|
|
local CastLeft = HR.CastLeft
|
|
local CDsON = HR.CDsON
|
|
local AoEON = HR.AoEON
|
|
local FBCast
|
|
-- Num/Bool Helper Functions
|
|
local num = HR.Commons.Everyone.num
|
|
local bool = HR.Commons.Everyone.bool
|
|
-- lua
|
|
local max = math.max
|
|
local ceil = math.ceil
|
|
-- Commons
|
|
local Mage = HR.Commons.Mage
|
|
|
|
--- ============================ CONTENT ===========================
|
|
--- ======= APL LOCALS =======
|
|
-- luacheck: max_line_length 9999
|
|
|
|
-- Define S/I for spell and item arrays
|
|
local S = Spell.Mage.Fire
|
|
local I = Item.Mage.Fire
|
|
|
|
-- Create table to exclude above trinkets from On Use function
|
|
local OnUseExcludes = {
|
|
-- GladiatorsBadge
|
|
I.CrimsonGladiatorsBadge:ID(),
|
|
I.ObsidianGladiatorsBadge:ID(),
|
|
-- Other Trinkets
|
|
I.HornofValor:ID(),
|
|
I.IrideusFragment:ID(),
|
|
I.MoonlitPrism:ID(),
|
|
I.SpoilsofNeltharus:ID(),
|
|
I.TimebreachingTalon:ID(),
|
|
I.TomeofUnstablePower:ID(),
|
|
I.VoidmendersShadowgem:ID(),
|
|
}
|
|
|
|
-- GUI Settings
|
|
local Everyone = HR.Commons.Everyone
|
|
local Settings = {
|
|
General = HR.GUISettings.General,
|
|
Commons = HR.GUISettings.APL.Mage.Commons,
|
|
Fire = HR.GUISettings.APL.Mage.Fire
|
|
}
|
|
|
|
-- Trinket Item Objects
|
|
local Equip = Player:GetEquipment()
|
|
local Trinket1 = Equip[13] and Item(Equip[13]) or Item(0)
|
|
local Trinket2 = Equip[14] and Item(Equip[14]) or Item(0)
|
|
|
|
-- Variables from Precombat
|
|
-- variable,name=disable_combustion,op=reset
|
|
local var_disable_combustion = not CDsON()
|
|
-- variable,name=firestarter_combustion,default=-1,value=talent.sun_kings_blessing,if=variable.firestarter_combustion<0
|
|
local var_firestarter_combustion = S.SunKingsBlessing:IsAvailable()
|
|
-- variable,name=hot_streak_flamestrike,if=variable.hot_streak_flamestrike=0,value=3*talent.flame_patch+999*!talent.flame_patch
|
|
local var_hot_streak_flamestrike = (S.FlamePatch:IsAvailable()) and 3 or 999
|
|
-- variable,name=hard_cast_flamestrike,if=variable.hard_cast_flamestrike=0,value=999
|
|
local var_hard_cast_flamestrike = 999
|
|
-- variable,name=combustion_flamestrike,if=variable.combustion_flamestrike=0,value=3*talent.flame_patch+999*!talent.flame_patch
|
|
local var_combustion_flamestrike = var_hot_streak_flamestrike
|
|
-- variable,name=skb_flamestrike,if=variable.skb_flamestrike=0,value=3
|
|
local var_skb_flamestrike = 3
|
|
-- variable,name=arcane_explosion,if=variable.arcane_explosion=0,value=999
|
|
local var_arcane_explosion = 999
|
|
-- variable,name=arcane_explosion_mana,default=40,op=reset
|
|
local var_arcane_explosion_mana = 40
|
|
-- variable,name=combustion_shifting_power,if=variable.combustion_shifting_power=0,value=999
|
|
local var_combustion_shifting_power = 999
|
|
-- variable,name=combustion_cast_remains,default=0.3,op=reset
|
|
-- Note: Increased to 0.6 to give more player reaction time.
|
|
local var_combustion_cast_remains = 0.6
|
|
-- variable,name=overpool_fire_blasts,default=0,op=reset
|
|
local var_overpool_fire_blasts = 0
|
|
-- variable,name=skb_duration,value=dbc.effect.1016075.base_value
|
|
-- Note: This is the duration of Sun King's Blessing's free Combustion
|
|
local var_skb_duration = 6
|
|
-- variable,name=combustion_on_use,value=equipped.gladiators_badge|equipped.moonlit_prism|equipped.irideus_fragment|equipped.spoils_of_neltharus|equipped.tome_of_unstable_power|equipped.timebreaching_talon|equipped.horn_of_valor
|
|
local var_combustion_on_use = I.CrimsonGladiatorsBadge:IsEquipped() or I.ObsidianGladiatorsBadge:IsEquipped() or I.MoonlitPrism:IsEquipped() or I.IrideusFragment:IsEquipped() or I.SpoilsofNeltharus:IsEquipped() or I.TomeofUnstablePower:IsEquipped() or I.TimebreachingTalon:IsEquipped() or I.HornofValor:IsEquipped()
|
|
-- variable,name=on_use_cutoff,value=20,if=variable.combustion_on_use
|
|
local var_on_use_cutoff = (var_combustion_on_use) and 20 or 0
|
|
|
|
-- Variables that need to be set later
|
|
-- variable,name=time_to_combustion,value=fight_remains+100,if=variable.disable_combustion
|
|
local var_time_to_combustion
|
|
|
|
-- Other variables used in the rotation
|
|
local var_kindling_reduction = (S.Kindling:IsAvailable()) and 0.4 or 1
|
|
local var_shifting_power_before_combustion = false
|
|
local var_item_cutoff_active = false
|
|
local var_phoenix_pooling = false
|
|
local var_fire_blast_pooling = false
|
|
local var_combustion_ready_time = 0
|
|
local var_combustion_precast_time = 0
|
|
local var_sun_kings_blessing_max_stack = 8
|
|
local var_improved_scorch_max_stack = 3
|
|
local CombustionUp
|
|
local CombustionDown
|
|
local ShiftingPowerTickReduction = 3
|
|
local BossFightRemains = 11111
|
|
local FightRemains = 11111
|
|
local GCDMax
|
|
|
|
-- Enemy variables
|
|
local EnemiesCount8ySplash,EnemiesCount10ySplash,EnemiesCount16ySplash
|
|
local EnemiesCount10yMelee,EnemiesCount18yMelee
|
|
local Enemies8ySplash,Enemies10yMelee,Enemies18yMelee
|
|
local UnitsWithIgniteCount
|
|
|
|
HL:RegisterForEvent(function()
|
|
var_combustion_on_use = I.CrimsonGladiatorsBadge:IsEquipped() or I.ObsidianGladiatorsBadge:IsEquipped() or I.MoonlitPrism:IsEquipped() or I.IrideusFragment:IsEquipped() or I.SpoilsofNeltharus:IsEquipped() or I.TomeofUnstablePower:IsEquipped() or I.TimebreachingTalon:IsEquipped() or I.HornofValor:IsEquipped()
|
|
var_on_use_cutoff = (var_combustion_on_use) and 20 or 0
|
|
Equip = Player:GetEquipment()
|
|
Trinket1 = Equip[13] and Item(Equip[13]) or Item(0)
|
|
Trinket2 = Equip[14] and Item(Equip[14]) or Item(0)
|
|
end, "PLAYER_EQUIPMENT_CHANGED")
|
|
|
|
HL:RegisterForEvent(function()
|
|
S.Pyroblast:RegisterInFlight()
|
|
S.Fireball:RegisterInFlight()
|
|
S.Meteor:RegisterInFlightEffect(351140)
|
|
S.Meteor:RegisterInFlight()
|
|
S.PhoenixFlames:RegisterInFlightEffect(257542)
|
|
S.PhoenixFlames:RegisterInFlight()
|
|
S.Pyroblast:RegisterInFlight(S.CombustionBuff)
|
|
S.Fireball:RegisterInFlight(S.CombustionBuff)
|
|
end, "LEARNED_SPELL_IN_TAB")
|
|
S.Pyroblast:RegisterInFlight()
|
|
S.Fireball:RegisterInFlight()
|
|
S.Meteor:RegisterInFlightEffect(351140)
|
|
S.Meteor:RegisterInFlight()
|
|
S.PhoenixFlames:RegisterInFlightEffect(257542)
|
|
S.PhoenixFlames:RegisterInFlight()
|
|
S.Pyroblast:RegisterInFlight(S.CombustionBuff)
|
|
S.Fireball:RegisterInFlight(S.CombustionBuff)
|
|
|
|
HL:RegisterForEvent(function()
|
|
BossFightRemains = 11111
|
|
FightRemains = 11111
|
|
end, "PLAYER_REGEN_ENABLED")
|
|
|
|
HL:RegisterForEvent(function()
|
|
var_firestarter_combustion = S.SunKingsBlessing:IsAvailable()
|
|
var_hot_streak_flamestrike = 3 * num(S.FlamePatch:IsAvailable()) + 999 * num(not S.FlamePatch:IsAvailable())
|
|
var_combustion_flamestrike = var_hot_streak_flamestrike
|
|
var_kindling_reduction = (S.Kindling:IsAvailable()) and 0.4 or 1
|
|
end, "SPELLS_CHANGED", "LEARNED_SPELL_IN_TAB")
|
|
|
|
local function FirestarterActive()
|
|
return (S.Firestarter:IsAvailable() and (Target:HealthPercentage() > 90))
|
|
end
|
|
|
|
local function FirestarterRemains()
|
|
return S.Firestarter:IsAvailable() and ((Target:HealthPercentage() > 90) and Target:TimeToX(90) or 0) or 0
|
|
end
|
|
|
|
local function SearingTouchActive()
|
|
return S.SearingTouch:IsAvailable() and Target:HealthPercentage() < 30
|
|
end
|
|
|
|
local function ImprovedScorchActive()
|
|
return S.ImprovedScorch:IsAvailable() and Target:HealthPercentage() < 30
|
|
end
|
|
|
|
local function ShiftingPowerFullReduction()
|
|
return ShiftingPowerTickReduction * S.ShiftingPower:BaseDuration() / S.ShiftingPower:BaseTickTime()
|
|
end
|
|
|
|
local function UseFreeCast()
|
|
return Player:IsCasting() or Player:IsMoving()
|
|
end
|
|
|
|
local function FreeCastAvailable()
|
|
local FSInFlight = FirestarterActive() and (num(S.Pyroblast:InFlight()) + num(S.Fireball:InFlight())) or 0
|
|
FSInFlight = FSInFlight + num(S.PhoenixFlames:InFlight())
|
|
return Player:BuffUp(S.HotStreakBuff) or Player:BuffUp(S.HyperthermiaBuff) or (Player:BuffUp(S.HeatingUpBuff) and (ImprovedScorchActive() and Player:IsCasting(S.Scorch) or FirestarterActive() and (Player:IsCasting(S.Fireball) or Player:IsCasting(S.Pyroblast) or S.Pyroblast:InFlight()))) or num(Player:BuffUp(S.HeatingUpBuff)) + FSInFlight >= 2
|
|
end
|
|
|
|
local function UnitsWithIgnite(enemies)
|
|
local WithIgnite = 0
|
|
for _, CycleUnit in pairs(enemies) do
|
|
if CycleUnit:DebuffUp(S.IgniteDebuff) then
|
|
WithIgnite = WithIgnite + 1
|
|
end
|
|
end
|
|
return WithIgnite
|
|
end
|
|
|
|
local function HotStreakInFlight()
|
|
local total = 0
|
|
if S.Fireball:InFlight() or S.PhoenixFlames:InFlight() then
|
|
total = total + 1
|
|
end
|
|
return total
|
|
end
|
|
|
|
local function Precombat()
|
|
-- flask
|
|
-- food
|
|
-- augmentation
|
|
-- arcane_intellect
|
|
if S.ArcaneIntellect:IsCastable() and (Player:BuffDown(S.ArcaneIntellect, true) or Everyone.GroupBuffMissing(S.ArcaneIntellect)) then
|
|
if Cast(S.ArcaneIntellect, Settings.Commons.GCDasOffGCD.ArcaneIntellect) then return "arcane_intellect precombat 2"; end
|
|
end
|
|
-- variable,name=disable_combustion,op=reset
|
|
-- Note: Moved to APL(), since the users may enable or disable CDsON at any time.
|
|
-- variable,name=firestarter_combustion,default=-1,value=talent.sun_kings_blessing,if=variable.firestarter_combustion<0
|
|
-- variable,name=hot_streak_flamestrike,if=variable.hot_streak_flamestrike=0,value=3*talent.flame_patch+999*!talent.flame_patch
|
|
-- variable,name=hard_cast_flamestrike,if=variable.hard_cast_flamestrike=0,value=999
|
|
-- variable,name=combustion_flamestrike,if=variable.combustion_flamestrike=0,value=3*talent.flame_patch+999*!talent.flame_patch
|
|
-- variable,name=skb_flamestrike,if=variable.skb_flamestrike=0,value=3
|
|
-- variable,name=arcane_explosion,if=variable.arcane_explosion=0,value=999
|
|
-- variable,name=arcane_explosion_mana,default=40,op=reset
|
|
-- variable,name=combustion_shifting_power,if=variable.combustion_shifting_power=0,value=999
|
|
-- variable,name=combustion_cast_remains,default=0.3,op=reset
|
|
-- variable,name=overpool_fire_blasts,default=0,op=reset
|
|
-- Note: Moved to initial declarations and SPELLS_CHANGED/LEARNED_SPELL_IN_TAB
|
|
-- variable,name=time_to_combustion,value=fight_remains+100,if=variable.disable_combustion
|
|
-- Note: Moved to APL(), since the users may enable or disable CDsON at any time.
|
|
-- variable,name=skb_duration,value=dbc.effect.1016075.base_value
|
|
-- Note: Moved to initial declarations and SPELLS_CHANGED/LEARNED_SPELL_IN_TAB
|
|
-- variable,name=combustion_on_use,value=equipped.gladiators_badge|equipped.moonlit_prism|equipped.irideus_fragment|equipped.spoils_of_neltharus|equipped.tome_of_unstable_power|equipped.timebreaching_talon|equipped.horn_of_valor
|
|
-- variable,name=on_use_cutoff,value=20,if=variable.combustion_on_use
|
|
-- Note: Moved to initial declarations and PLAYER_EQUIPMENT_CHANGED
|
|
-- snapshot_stats
|
|
-- mirror_image
|
|
if CDsON() and S.MirrorImage:IsCastable() and Settings.Fire.MirrorImagesBeforePull then
|
|
if Cast(S.MirrorImage, Settings.Fire.GCDasOffGCD.MirrorImage) then return "mirror_image precombat 2"; end
|
|
end
|
|
-- flamestrike,if=active_enemies>=variable.hot_streak_flamestrike
|
|
-- Note: Can't calculate enemies in Precombat
|
|
-- pyroblast
|
|
if S.Pyroblast:IsReady() and not Player:IsCasting(S.Pyroblast) then
|
|
if Cast(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast precombat 4"; end
|
|
end
|
|
-- Manually added: fireball
|
|
if S.Fireball:IsReady() then
|
|
if Cast(S.Fireball, nil, nil, not Target:IsSpellInRange(S.Fireball)) then return "fireball precombat 6"; end
|
|
end
|
|
end
|
|
|
|
local function ActiveTalents()
|
|
-- living_bomb,if=active_enemies>1&buff.combustion.down&(variable.time_to_combustion>cooldown.living_bomb.duration|variable.time_to_combustion<=0)
|
|
if S.LivingBomb:IsReady() and (EnemiesCount10ySplash > 1 and CombustionDown and (var_time_to_combustion > S.LivingBomb:CooldownRemains() or var_time_to_combustion <= 0)) then
|
|
if Cast(S.LivingBomb, nil, nil, not Target:IsSpellInRange(S.LivingBomb)) then return "living_bomb active_talents 2"; end
|
|
end
|
|
-- meteor,if=variable.time_to_combustion<=0|buff.combustion.remains>travel_time|!talent.sun_kings_blessing&(cooldown.meteor.duration<variable.time_to_combustion|fight_remains<variable.time_to_combustion)
|
|
if S.Meteor:IsReady() and (var_time_to_combustion <= 0 or Player:BuffRemains(S.CombustionBuff) > S.Meteor:TravelTime() or (not S.SunKingsBlessing:IsAvailable()) and (45 < var_time_to_combustion or FightRemains < var_time_to_combustion)) then
|
|
if Cast(S.Meteor, nil, nil, not Target:IsInRange(40)) then return "meteor active_talents 4"; end
|
|
end
|
|
-- dragons_breath,if=talent.alexstraszas_fury&(buff.combustion.down&!buff.hot_streak.react)&(buff.feel_the_burn.up|time>15)&!firestarter.remains&!talent.tempered_flames
|
|
-- dragons_breath,if=talent.alexstraszas_fury&(buff.combustion.down&!buff.hot_streak.react)
|
|
if S.DragonsBreath:IsReady() and (S.AlexstraszasFury:IsAvailable() and (CombustionDown and Player:BuffDown(S.HotStreakBuff)) and (Player:BuffUp(S.FeeltheBurnBuff) or HL.CombatTime() > 15) and FirestarterRemains() == 0 and not S.TemperedFlames:IsAvailable()) then
|
|
if Settings.Fire.StayDistance and not Target:IsInRange(12) then
|
|
if CastLeft(S.DragonsBreath) then return "dragons_breath active_talents 6 left"; end
|
|
else
|
|
if Cast(S.DragonsBreath) then return "dragons_breath active_talents 6"; end
|
|
end
|
|
end
|
|
-- dragons_breath,if=talent.alexstraszas_fury&(buff.combustion.down&!buff.hot_streak.react)&(buff.feel_the_burn.up|time>15)&talent.tempered_flames
|
|
if S.DragonsBreath:IsReady() and (S.AlexstraszasFury:IsAvailable() and (CombustionDown and Player:BuffDown(S.HotStreakBuff)) and (Player:BuffUp(S.FeeltheBurnBuff) or HL.CombatTime() > 15) and S.TemperedFlames:IsAvailable()) then
|
|
if Settings.Fire.StayDistance and not Target:IsInRange(12) then
|
|
if CastLeft(S.DragonsBreath) then return "dragons_breath active_talents 8 left"; end
|
|
else
|
|
if Cast(S.DragonsBreath) then return "dragons_breath active_talents 8"; end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function CombustionCooldowns()
|
|
-- potion
|
|
if Settings.Commons.Enabled.Potions then
|
|
local PotionSelected = Everyone.PotionSelected()
|
|
if PotionSelected and PotionSelected:IsReady() then
|
|
if Cast(PotionSelected, nil, Settings.Commons.DisplayStyle.Potions) then return "potion combustion_cooldowns 2"; end
|
|
end
|
|
end
|
|
-- blood_fury
|
|
if S.BloodFury:IsCastable() then
|
|
if Cast(S.BloodFury, Settings.Commons.OffGCDasOffGCD.Racials) then return "blood_fury combustion_cooldowns 4"; end
|
|
end
|
|
-- berserking,if=buff.combustion.up
|
|
if S.Berserking:IsCastable() and (CombustionUp) then
|
|
if Cast(S.Berserking, Settings.Commons.OffGCDasOffGCD.Racials) then return "berserking combustion_cooldowns 6"; end
|
|
end
|
|
-- fireblood
|
|
if S.Fireblood:IsCastable() then
|
|
if Cast(S.Fireblood, Settings.Commons.OffGCDasOffGCD.Racials) then return "fireblood combustion_cooldowns 8"; end
|
|
end
|
|
-- ancestral_call
|
|
if S.AncestralCall:IsCastable() then
|
|
if Cast(S.AncestralCall, Settings.Commons.OffGCDasOffGCD.Racials) then return "ancestral_call combustion_cooldowns 10"; end
|
|
end
|
|
-- invoke_external_buff,name=power_infusion,if=buff.power_infusion.down
|
|
-- invoke_external_buff,name=blessing_of_summer,if=buff.blessing_of_summer.down
|
|
-- Note: Not handling external buffs
|
|
-- time_warp,if=talent.temporal_warp&buff.exhaustion.up
|
|
if S.TimeWarp:IsReady() and Settings.Fire.UseTemporalWarp and (S.TemporalWarp:IsAvailable() and Player:BloodlustExhaustUp()) then
|
|
if Cast(S.TimeWarp, Settings.Commons.OffGCDasOffGCD.TimeWarp) then return "time_warp combustion_cooldowns 12"; end
|
|
end
|
|
if Settings.Commons.Enabled.Trinkets then
|
|
-- use_item,effect_name=gladiators_badge
|
|
if I.CrimsonGladiatorsBadge:IsEquippedAndReady() then
|
|
if Cast(I.CrimsonGladiatorsBadge, nil, Settings.Commons.DisplayStyle.Trinkets) then return "gladiators_badge (crimson) combustion_cooldowns 14"; end
|
|
end
|
|
if I.ObsidianGladiatorsBadge:IsEquippedAndReady() then
|
|
if Cast(I.ObsidianGladiatorsBadge, nil, Settings.Commons.DisplayStyle.Trinkets) then return "gladiators_badge (obsidian) combustion_cooldowns 16"; end
|
|
end
|
|
-- use_item,name=irideus_fragment
|
|
if I.IrideusFragment:IsEquippedAndReady() then
|
|
if Cast(I.IrideusFragment, nil, Settings.Commons.DisplayStyle.Trinkets) then return "irideus_fragment combustion_cooldowns 18"; end
|
|
end
|
|
-- use_item,name=spoils_of_neltharus
|
|
if I.SpoilsofNeltharus:IsEquippedAndReady() then
|
|
if Cast(I.SpoilsofNeltharus, nil, Settings.Commons.DisplayStyle.Trinkets) then return "spoils_of_neltharus combustion_cooldowns 20"; end
|
|
end
|
|
-- use_item,name=tome_of_unstable_power
|
|
if I.TomeofUnstablePower:IsEquippedAndReady() then
|
|
if Cast(I.TomeofUnstablePower, nil, Settings.Commons.DisplayStyle.Trinkets) then return "tome_of_unstable_power combustion_cooldowns 22"; end
|
|
end
|
|
-- use_item,name=timebreaching_talon
|
|
if I.TimebreachingTalon:IsEquippedAndReady() then
|
|
if Cast(I.TimebreachingTalon, nil, Settings.Commons.DisplayStyle.Trinkets) then return "timebreaching_talon combustion_cooldowns 24"; end
|
|
end
|
|
-- use_item,name=voidmenders_shadowgem
|
|
if I.VoidmendersShadowgem:IsEquippedAndReady() then
|
|
if Cast(I.VoidmendersShadowgem, nil, Settings.Commons.DisplayStyle.Trinkets) then return "voidmenders_shadowgem combustion_cooldowns 26"; end
|
|
end
|
|
-- use_item,name=horn_of_valor
|
|
if I.HornofValor:IsEquippedAndReady() then
|
|
if Cast(I.HornofValor, nil, Settings.Commons.DisplayStyle.Trinkets) then return "horn_of_valor combustion_cooldowns 28"; end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function CombustionPhase()
|
|
-- lights_judgment,if=buff.combustion.down
|
|
if CDsON() and S.LightsJudgment:IsCastable() and (CombustionDown) then
|
|
if Cast(S.LightsJudgment, Settings.Commons.OffGCDasOffGCD.Racials) then return "lights_judgment combustion_phase 2"; end
|
|
end
|
|
-- bag_of_tricks,if=buff.combustion.down
|
|
if CDsON() and S.BagofTricks:IsCastable() and (CombustionDown) then
|
|
if Cast(S.BagofTricks, Settings.Commons.OffGCDasOffGCD.Racials) then return "bag_of_tricks combustion_phase 4"; end
|
|
end
|
|
-- living_bomb,if=active_enemies>1&buff.combustion.down
|
|
if S.LivingBomb:IsReady() and AoEON() and (EnemiesCount10ySplash > 1 and CombustionDown) then
|
|
if Cast(S.LivingBomb, nil, nil, not Target:IsSpellInRange(S.LivingBomb)) then return "living_bomb combustion_phase 6"; end
|
|
end
|
|
-- call_action_list,name=combustion_cooldowns,if=buff.combustion.remains>variable.skb_duration|fight_remains<20
|
|
if Player:BuffRemains(S.CombustionBuff) > var_skb_duration or FightRemains < 20 then
|
|
local ShouldReturn = CombustionCooldowns(); if ShouldReturn then return ShouldReturn; end
|
|
end
|
|
-- use_item,name=hyperthread_wristwraps,if=hyperthread_wristwraps.fire_blast>=2&action.fire_blast.charges=0
|
|
-- use_item,name=neural_synapse_enhancer,if=variable.time_to_combustion>60
|
|
-- Note: Not handling items from Mechagon...
|
|
-- phoenix_flames,if=set_bonus.tier30_2pc&!action.phoenix_flames.in_flight&debuff.charring_embers.remains<2*gcd.max
|
|
if S.PhoenixFlames:IsCastable() and (Player:HasTier(30, 2) and (not S.PhoenixFlames:InFlight()) and Target:DebuffRemains(S.CharringEmbersDebuff) < 2 * GCDMax) then
|
|
if Cast(S.PhoenixFlames, nil, nil, not Target:IsSpellInRange(S.PhoenixFlames)) then return "phoenix_flames combustion_phase 8"; end
|
|
end
|
|
-- call_action_list,name=active_talents
|
|
local ShouldReturn = ActiveTalents(); if ShouldReturn then return ShouldReturn; end
|
|
-- combustion from below
|
|
if S.Combustion:IsReady() and (HotStreakInFlight() == 0 and CombustionDown and var_time_to_combustion <= 0 and (Player:IsCasting(S.Scorch) and S.Scorch:ExecuteRemains() < var_combustion_cast_remains or Player:IsCasting(S.Fireball) and S.Fireball:ExecuteRemains() < var_combustion_cast_remains or Player:IsCasting(S.Pyroblast) and S.Pyroblast:ExecuteRemains() < var_combustion_cast_remains or Player:IsCasting(S.Flamestrike) and S.Flamestrike:ExecuteRemains() < var_combustion_cast_remains or S.Meteor:InFlight() and S.Meteor:InFlightRemains() < var_combustion_cast_remains)) then
|
|
if Cast(S.Combustion, Settings.Fire.OffGCDasOffGCD.Combustion) then return "combustion combustion_phase 10"; end
|
|
end
|
|
-- flamestrike,if=buff.combustion.down&buff.fury_of_the_sun_king.up&buff.fury_of_the_sun_king.remains>cast_time&buff.fury_of_the_sun_king.expiration_delay_remains=0&cooldown.combustion.remains<cast_time&active_enemies>=variable.skb_flamestrike
|
|
-- TODO: Handle expiration_delay_remains
|
|
if AoEON() and S.Flamestrike:IsReady() and (not Player:IsCasting(S.Flamestrike)) and (CombustionDown and Player:BuffUp(S.FuryoftheSunKingBuff) and Player:BuffRemains(S.FuryoftheSunKingBuff) > S.Flamestrike:CastTime() and S.Combustion:CooldownRemains() < S.Flamestrike:CastTime() and EnemiesCount8ySplash >= var_skb_flamestrike) then
|
|
if Cast(S.Flamestrike, nil, nil, not Target:IsInRange(40)) then return "flamestrike combustion_phase 12"; end
|
|
end
|
|
-- pyroblast,if=buff.combustion.down&buff.fury_of_the_sun_king.up&buff.fury_of_the_sun_king.remains>cast_time&buff.fury_of_the_sun_king.expiration_delay_remains=0
|
|
if S.Pyroblast:IsReady() and (not Player:IsCasting(S.Pyroblast)) and (CombustionDown and Player:BuffUp(S.FuryoftheSunKingBuff) and Player:BuffRemains(S.FuryoftheSunKingBuff) > S.Pyroblast:CastTime()) then
|
|
if Cast(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast combustion_phase 14"; end
|
|
end
|
|
-- fireball,if=buff.combustion.down&cooldown.combustion.remains<cast_time&active_enemies<2
|
|
if S.Fireball:IsReady() and (CombustionDown and S.Combustion:CooldownRemains() < S.Fireball:CastTime() and EnemiesCount8ySplash < 2) then
|
|
if Cast(S.Fireball, nil, nil, not Target:IsSpellInRange(S.Fireball)) then return "fireball combustion_phase 16"; end
|
|
end
|
|
-- scorch,if=buff.combustion.down&cooldown.combustion.remains<cast_time
|
|
if S.Scorch:IsReady() and (CombustionDown and S.Combustion:CooldownRemains() < S.Scorch:CastTime()) then
|
|
if Cast(S.Scorch, nil, nil, not Target:IsSpellInRange(S.Scorch)) then return "scorch combustion_phase 18"; end
|
|
end
|
|
-- combustion,use_off_gcd=1,use_while_casting=1,if=hot_streak_spells_in_flight=0&buff.combustion.down&variable.time_to_combustion<=0&(action.scorch.executing&action.scorch.execute_remains<variable.combustion_cast_remains|action.fireball.executing&action.fireball.execute_remains<variable.combustion_cast_remains|action.pyroblast.executing&action.pyroblast.execute_remains<variable.combustion_cast_remains|action.flamestrike.executing&action.flamestrike.execute_remains<variable.combustion_cast_remains|action.meteor.in_flight&action.meteor.in_flight_remains<variable.combustion_cast_remains)
|
|
-- Note: Moved above the previous four lines, due to use_while_casting.
|
|
-- fire_blast,use_off_gcd=1,use_while_casting=1,if=!variable.fire_blast_pooling&(!improved_scorch.active|action.scorch.executing|debuff.improved_scorch.remains>3)&(buff.fury_of_the_sun_king.down|action.pyroblast.executing)&buff.combustion.up&!buff.hyperthermia.react&!buff.hot_streak.react&hot_streak_spells_in_flight+buff.heating_up.react*(gcd.remains>0)<2
|
|
if S.FireBlast:IsReady() and (not FreeCastAvailable()) and ((not var_fire_blast_pooling) and ((not ImprovedScorchActive()) or Player:IsCasting(S.Scorch) or Target:DebuffRemains(S.ImprovedScorchDebuff) > 3) and (Player:BuffDown(S.FuryoftheSunKingBuff) or Player:IsCasting(S.Pyroblast)) and CombustionUp and Player:BuffDown(S.HyperthermiaBuff) and Player:BuffDown(S.HotStreakBuff) and HotStreakInFlight() + num(Player:BuffUp(S.HeatingUpBuff)) * num(Player:GCDRemains() > 0) < 2) then
|
|
if FBCast(S.FireBlast) then return "fire_blast combustion_phase 20"; end
|
|
end
|
|
-- flamestrike,if=(buff.hot_streak.react&active_enemies>=variable.combustion_flamestrike)|(buff.hyperthermia.react&active_enemies>=variable.combustion_flamestrike-talent.hyperthermia)
|
|
if AoEON() and S.Flamestrike:IsReady() and UseFreeCast() and ((Player:BuffUp(S.HotStreakBuff) and EnemiesCount8ySplash >= var_combustion_flamestrike) or (Player:BuffUp(S.HyperthermiaBuff) and EnemiesCount8ySplash >= var_combustion_flamestrike - num(S.Hyperthermia:IsAvailable()))) then
|
|
if Cast(S.Flamestrike, nil, nil, not Target:IsInRange(40)) then return "flamestrike combustion_phase 22"; end
|
|
end
|
|
-- pyroblast,if=buff.hyperthermia.react
|
|
if S.Pyroblast:IsReady() and UseFreeCast() and (Player:BuffUp(S.HyperthermiaBuff)) then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast combustion_phase 24"; end
|
|
end
|
|
-- pyroblast,if=buff.hot_streak.react&buff.combustion.up
|
|
if S.Pyroblast:IsReady() and UseFreeCast() and (Player:BuffUp(S.HotStreakBuff) and CombustionUp) then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast combustion_phase 26"; end
|
|
end
|
|
-- pyroblast,if=prev_gcd.1.scorch&buff.heating_up.react&active_enemies<variable.combustion_flamestrike&buff.combustion.up
|
|
if S.Pyroblast:IsReady() and (Player:PrevGCDP(1, S.Scorch) and Player:BuffUp(S.HeatingUpBuff) and EnemiesCount8ySplash < var_combustion_flamestrike and CombustionUp) then
|
|
if Cast(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast combustion_phase 28"; end
|
|
end
|
|
-- shifting_power,if=buff.combustion.up&!action.fire_blast.charges&(action.phoenix_flames.charges<action.phoenix_flames.max_charges|talent.alexstraszas_fury)&variable.combustion_shifting_power
|
|
if S.ShiftingPower:IsReady() and (CombustionUp and S.FireBlast:Charges() == 0 and (S.PhoenixFlames:Charges() < S.PhoenixFlames:MaxCharges() or S.AlexstraszasFury:IsAvailable()) and var_combustion_shifting_power) then
|
|
if Cast(S.ShiftingPower, nil, Settings.Commons.DisplayStyle.Signature, not Target:IsInRange(18)) then return "shifting_power combustion_phase 30"; end
|
|
end
|
|
-- flamestrike,if=buff.fury_of_the_sun_king.up&buff.fury_of_the_sun_king.remains>cast_time&active_enemies>=variable.skb_flamestrike&buff.fury_of_the_sun_king.expiration_delay_remains=0
|
|
if AoEON() and S.Flamestrike:IsReady() and (not Player:IsCasting(S.Flamestrike)) and (Player:BuffUp(S.FuryoftheSunKingBuff) and Player:BuffRemains(S.FuryoftheSunKingBuff) > S.Flamestrike:CastTime() and EnemiesCount8ySplash >= var_skb_flamestrike) then
|
|
if Cast(S.Flamestrike, nil, nil, not Target:IsInRange(40)) then return "flamestrike combustion_phase 32"; end
|
|
end
|
|
-- pyroblast,if=buff.fury_of_the_sun_king.up&buff.fury_of_the_sun_king.remains>cast_time&buff.fury_of_the_sun_king.expiration_delay_remains=0
|
|
if S.Pyroblast:IsReady() and (not Player:IsCasting(S.Pyroblast)) and (Player:BuffUp(S.FuryoftheSunKingBuff) and Player:BuffRemains(S.FuryoftheSunKingBuff) > S.Pyroblast:CastTime()) then
|
|
if Cast(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast combustion_phase 34"; end
|
|
end
|
|
-- scorch,if=improved_scorch.active&debuff.improved_scorch.remains<3
|
|
if S.Scorch:IsReady() and (ImprovedScorchActive() and Target:DebuffRemains(S.ImprovedScorchDebuff) < 3) then
|
|
if Cast(S.Scorch, nil, nil, not Target:IsSpellInRange(S.Scorch)) then return "scorch combustion_phase 36"; end
|
|
end
|
|
-- phoenix_flames,if=set_bonus.tier30_2pc&travel_time<buff.combustion.remains&buff.heating_up.react+hot_streak_spells_in_flight<2&(debuff.charring_embers.remains<2*gcd.max|buff.flames_fury.up)
|
|
if S.PhoenixFlames:IsCastable() and (Player:HasTier(30, 2) and S.PhoenixFlames:TravelTime() < Player:BuffRemains(S.CombustionBuff) and num(Player:BuffUp(S.HeatingUpBuff)) + HotStreakInFlight() < 2 and (Target:DebuffRemains(S.CharringEmbersDebuff) < 2 * GCDMax or Player:BuffUp(S.FlamesFuryBuff))) then
|
|
if Cast(S.PhoenixFlames, nil, nil, not Target:IsSpellInRange(S.PhoenixFlames)) then return "phoenix_flames combustion_phase 38"; end
|
|
end
|
|
-- fireball,if=buff.combustion.remains>cast_time&buff.flame_accelerant.react
|
|
if S.Fireball:IsReady() and (Player:BuffRemains(S.CombustionBuff) > S.Fireball:CastTime() and Player:BuffUp(S.FlameAccelerantBuff)) then
|
|
if Cast(S.Fireball, nil, nil, not Target:IsSpellInRange(S.Fireball)) then return "fireball combustion_phase 40"; end
|
|
end
|
|
-- phoenix_flames,if=!set_bonus.tier30_2pc&!talent.alexstraszas_fury&travel_time<buff.combustion.remains&buff.heating_up.react+hot_streak_spells_in_flight<2
|
|
if S.PhoenixFlames:IsCastable() and ((not Player:HasTier(30, 2)) and (not S.AlexstraszasFury:IsAvailable()) and S.PhoenixFlames:TravelTime() < Player:BuffRemains(S.CombustionBuff) and num(Player:BuffUp(S.HeatingUpBuff)) + HotStreakInFlight() < 2) then
|
|
if Cast(S.PhoenixFlames, nil, nil, not Target:IsSpellInRange(S.PhoenixFlames)) then return "phoenix_flames combustion_phase 42"; end
|
|
end
|
|
-- scorch,if=buff.combustion.remains>cast_time&cast_time>=gcd.max
|
|
if S.Scorch:IsReady() and (Player:BuffRemains(S.CombustionBuff) > S.Scorch:CastTime() and S.Scorch:CastTime() >= GCDMax) then
|
|
if Cast(S.Scorch, nil, nil, not Target:IsSpellInRange(S.Scorch)) then return "scorch combustion_phase 44"; end
|
|
end
|
|
-- fireball,if=buff.combustion.remains>cast_time
|
|
if S.Fireball:IsReady() and (Player:BuffRemains(S.CombustionBuff) > S.Fireball:CastTime()) then
|
|
if Cast(S.Fireball, nil, nil, not Target:IsSpellInRange(S.Fireball)) then return "fireball combustion_phase 46"; end
|
|
end
|
|
-- living_bomb,if=buff.combustion.remains<gcd.max&active_enemies>1
|
|
if S.LivingBomb:IsReady() and (Player:BuffRemains(S.CombustionBuff) < GCDMax and EnemiesCount10ySplash > 1) then
|
|
if Cast(S.LivingBomb, nil, nil, not Target:IsSpellInRange(S.LivingBomb)) then return "living_bomb combustion_phase 48"; end
|
|
end
|
|
-- ice_nova,if=buff.combustion.remains<gcd.max
|
|
if S.IceNova:IsCastable() and (Player:BuffRemains(S.CombustionBuff) < GCDMax) then
|
|
if Cast(S.IceNova, nil, nil, not Target:IsSpellInRange(S.IceNova)) then return "ice_nova combustion_phase 50"; end
|
|
end
|
|
end
|
|
|
|
local function CombustionTiming()
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=combustion_ready_time,value=cooldown.combustion.remains*expected_kindling_reduction
|
|
var_combustion_ready_time = S.Combustion:CooldownRemains() * var_kindling_reduction
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=combustion_precast_time,value=action.fireball.cast_time*(active_enemies<variable.combustion_flamestrike)+action.flamestrike.cast_time*(active_enemies>=variable.combustion_flamestrike)-variable.combustion_cast_remains
|
|
var_combustion_precast_time = S.Fireball:CastTime() * num(EnemiesCount8ySplash < var_combustion_flamestrike) + S.Flamestrike:CastTime() * num(EnemiesCount8ySplash >= var_combustion_flamestrike) - var_combustion_cast_remains
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,value=variable.combustion_ready_time
|
|
var_time_to_combustion = var_combustion_ready_time
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,op=max,value=firestarter.remains,if=talent.firestarter&!variable.firestarter_combustion
|
|
if S.Firestarter:IsAvailable() and not var_firestarter_combustion then
|
|
var_time_to_combustion = max(FirestarterRemains(), var_time_to_combustion)
|
|
end
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,op=max,value=(buff.sun_kings_blessing.max_stack-buff.sun_kings_blessing.stack)*(3*gcd.max),if=talent.sun_kings_blessing&firestarter.active&buff.fury_of_the_sun_king.down
|
|
if S.SunKingsBlessing:IsAvailable() and FirestarterActive() and Player:BuffDown(S.FuryoftheSunKingBuff) then
|
|
var_time_to_combustion = max(((var_sun_kings_blessing_max_stack - Player:BuffStack(S.SunKingsBlessingBuff)) * (3 * GCDMax)), var_time_to_combustion)
|
|
end
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,op=max,value=cooldown.gladiators_badge_345228.remains,if=equipped.gladiators_badge&cooldown.gladiators_badge_345228.remains-20<variable.time_to_combustion
|
|
if I.CrimsonGladiatorsBadge:IsEquipped() and I.CrimsonGladiatorsBadge:CooldownRemains() - 20 < var_time_to_combustion then
|
|
var_time_to_combustion = max(I.CrimsonGladiatorsBadge:CooldownRemains(), var_time_to_combustion)
|
|
end
|
|
if I.ObsidianGladiatorsBadge:IsEquipped() and I.ObsidianGladiatorsBadge:CooldownRemains() - 20 < var_time_to_combustion then
|
|
var_time_to_combustion = max(I.ObsidianGladiatorsBadge:CooldownRemains(), var_time_to_combustion)
|
|
end
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,op=max,value=buff.combustion.remains
|
|
var_time_to_combustion = max(Player:BuffRemains(S.CombustionBuff), var_time_to_combustion)
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,op=max,value=raid_event.adds.in,if=raid_event.adds.exists&raid_event.adds.count>=3&raid_event.adds.duration>15
|
|
-- Note: Skipping this, as we don't handle SimC's raid_event
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,value=raid_event.vulnerable.in*!raid_event.vulnerable.up,if=raid_event.vulnerable.exists&variable.combustion_ready_time<raid_event.vulnerable.in
|
|
-- Note: Skipping this, as we don't handle SimC's raid_event
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=time_to_combustion,value=variable.combustion_ready_time,if=variable.combustion_ready_time+cooldown.combustion.duration*(1-(0.4+0.2*talent.firestarter)*talent.kindling)<=variable.time_to_combustion|variable.time_to_combustion>fight_remains-20
|
|
if var_combustion_ready_time + 120 * (1 - (0.4 + 0.2 * num(S.Firestarter:IsAvailable())) * num(S.Kindling:IsAvailable())) <= var_time_to_combustion or var_time_to_combustion > FightRemains - 20 then
|
|
var_time_to_combustion = var_combustion_ready_time
|
|
end
|
|
end
|
|
|
|
local function FirestarterFireBlasts()
|
|
-- fire_blast,use_while_casting=1,if=!variable.fire_blast_pooling&!buff.hot_streak.react&(action.fireball.execute_remains>gcd.remains|action.pyroblast.executing)&buff.heating_up.react+hot_streak_spells_in_flight=1&(cooldown.shifting_power.ready|charges>1|buff.feel_the_burn.remains<2*gcd.max)
|
|
if S.FireBlast:IsReady() and (not FreeCastAvailable()) and ((not var_fire_blast_pooling) and Player:BuffDown(S.HotStreakBuff) and (S.Fireball:ExecuteRemains() > Player:GCDRemains() or Player:IsCasting(S.Pyroblast)) and num(Player:BuffUp(S.HeatingUpBuff)) + HotStreakInFlight() == 1 and (S.ShiftingPower:CooldownUp() or S.FireBlast:Charges() > 1 or Player:BuffRemains(S.FeeltheBurnBuff) < 2 * GCDMax)) then
|
|
if FBCast(S.FireBlast) then return "fire_blast firestarter_fire_blasts 2"; end
|
|
end
|
|
-- fire_blast,use_off_gcd=1,if=!variable.fire_blast_pooling&buff.heating_up.react+hot_streak_spells_in_flight=1&(talent.feel_the_burn&buff.feel_the_burn.remains<gcd.remains|cooldown.shifting_power.ready&(!set_bonus.tier30_2pc|debuff.charring_embers.remains>2*gcd.max))
|
|
-- Note: Added check to not cast Fire Blast when HotStreakBuff is active.
|
|
if S.FireBlast:IsReady() and (not FreeCastAvailable()) and ((not var_fire_blast_pooling) and num(Player:BuffUp(S.HeatingUpBuff)) + HotStreakInFlight() == 1 and (S.FeeltheBurn:IsAvailable() and Player:BuffRemains(S.FeeltheBurnBuff) < Player:GCDRemains() or S.ShiftingPower:CooldownUp() and ((not Player:HasTier(30, 2)) or Target:DebuffRemains(S.CharringEmbersDebuff) > 2 * GCDMax))) then
|
|
if FBCast(S.FireBlast) then return "fire_blast firestarter_fire_blasts 4"; end
|
|
end
|
|
end
|
|
|
|
local function StandardRotation()
|
|
-- flamestrike,if=active_enemies>=variable.hot_streak_flamestrike&(buff.hot_streak.react|buff.hyperthermia.react)
|
|
if AoEON() and S.Flamestrike:IsReady() and UseFreeCast() and (EnemiesCount8ySplash >= var_hot_streak_flamestrike and (Player:BuffUp(S.HotStreakBuff) or Player:BuffUp(S.HyperthermiaBuff))) then
|
|
if Cast(S.Flamestrike, nil, nil, not Target:IsInRange(40)) then return "flamestrike standard_rotation 2"; end
|
|
end
|
|
-- pyroblast,if=buff.hyperthermia.react
|
|
if S.Pyroblast:IsReady() and UseFreeCast() and (Player:BuffUp(S.HyperthermiaBuff)) then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast standard_rotation 4"; end
|
|
end
|
|
if UseFreeCast() then
|
|
-- pyroblast,if=buff.hot_streak.react&(buff.hot_streak.remains<action.fireball.execute_time)
|
|
if S.Pyroblast:IsReady() and (Player:BuffUp(S.HotStreakBuff) and Player:BuffRemains(S.HotStreakBuff) < S.Fireball:ExecuteTime()) then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast standard_rotation 6"; end
|
|
end
|
|
-- pyroblast,if=buff.hot_streak.react&(hot_streak_spells_in_flight|firestarter.active|talent.alexstraszas_fury&action.phoenix_flames.charges)
|
|
if S.Pyroblast:IsReady() and (Player:BuffUp(S.HotStreakBuff) and (HotStreakInFlight() > 0 or FirestarterActive() or S.AlexstraszasFury:IsAvailable() and S.PhoenixFlames:Charges() > 0)) then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast standard_rotation 8"; end
|
|
end
|
|
-- pyroblast,if=buff.hot_streak.react&searing_touch.active
|
|
if S.Pyroblast:IsReady() and (Player:BuffUp(S.HotStreakBuff) and SearingTouchActive()) then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast standard_rotation 10"; end
|
|
end
|
|
end
|
|
-- flamestrike,if=active_enemies>=variable.skb_flamestrike&buff.fury_of_the_sun_king.up&buff.fury_of_the_sun_king.expiration_delay_remains=0"
|
|
if AoEON() and S.Flamestrike:IsReady() and (not Player:IsCasting(S.Flamestrike)) and (EnemiesCount8ySplash >= var_skb_flamestrike and Player:BuffUp(S.FuryoftheSunKingBuff)) then
|
|
if Cast(S.Flamestrike, nil, nil, not Target:IsInRange(40)) then return "flamestrike standard_rotation 12"; end
|
|
end
|
|
-- pyroblast,if=buff.fury_of_the_sun_king.up&buff.fury_of_the_sun_king.expiration_delay_remains=0
|
|
if S.Pyroblast:IsReady() and (not Player:IsCasting(S.Pyroblast)) and (Player:BuffUp(S.FuryoftheSunKingBuff)) then
|
|
if Cast(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast standard_rotation 14"; end
|
|
end
|
|
-- fire_blast,use_off_gcd=1,use_while_casting=1,if=!firestarter.active&!variable.fire_blast_pooling&buff.fury_of_the_sun_king.down&(((action.fireball.executing&(action.fireball.execute_remains<0.5|!talent.hyperthermia)|action.pyroblast.executing&(action.pyroblast.execute_remains<0.5|!talent.hyperthermia))&buff.heating_up.react)|(searing_touch.active&(!improved_scorch.active|debuff.improved_scorch.stack=debuff.improved_scorch.max_stack|full_recharge_time<3)&(buff.heating_up.react&!action.scorch.executing|!buff.hot_streak.react&!buff.heating_up.react&action.scorch.executing&!hot_streak_spells_in_flight)))
|
|
if S.FireBlast:IsReady() and (not FreeCastAvailable()) and ((not FirestarterActive()) and (not var_fire_blast_pooling) and Player:BuffDown(S.FuryoftheSunKingBuff) and (((Player:IsCasting(S.Fireball) and (S.Fireball:ExecuteRemains() < 0.5 or not S.Hyperthermia:IsAvailable()) or Player:IsCasting(S.Pyroblast) and (S.Pyroblast:ExecuteRemains() < 0.5 or not S.Hyperthermia:IsAvailable())) and Player:BuffUp(S.HeatingUpBuff)) or (SearingTouchActive() and ((not ImprovedScorchActive()) or Target:DebuffStack(S.ImprovedScorchDebuff) == var_improved_scorch_max_stack or S.FireBlast:FullRechargeTime() < 3) and (Player:BuffUp(S.HeatingUpBuff) and (not Player:IsCasting(S.Scorch)) or Player:BuffDown(S.HotStreakBuff) and Player:BuffDown(S.HeatingUpBuff) and Player:IsCasting(S.Scorch) and HotStreakInFlight() == 0)))) then
|
|
if FBCast(S.FireBlast) then return "fire_blast standard_rotation 16"; end
|
|
end
|
|
-- pyroblast,if=prev_gcd.1.scorch&buff.heating_up.react&searing_touch.active&active_enemies<variable.hot_streak_flamestrike
|
|
if S.Pyroblast:IsReady() and UseFreeCast() and Player:BuffUp(S.HeatingUpBuff) and var_searing_touch_active and EnemiesCount8ySplash < var_hot_streak_flamestrike then
|
|
if CastLeft(S.Pyroblast, nil, nil, not Target:IsSpellInRange(S.Pyroblast)) then return "pyroblast standard_rotation 18"; end
|
|
end
|
|
-- phoenix_flames,if=set_bonus.tier30_2pc&debuff.charring_embers.remains<2*gcd.max
|
|
if S.PhoenixFlames:IsCastable() and (Player:HasTier(30, 2) and Target:DebuffRemains(S.CharringEmbersDebuff) < 2 * GCDMax) then
|
|
if Cast(S.PhoenixFlames, nil, nil, not Target:IsSpellInRange(S.PhoenixFlames)) then return "phoenix_flames standard_rotation 20"; end
|
|
end
|
|
-- scorch,if=improved_scorch.active&debuff.improved_scorch.stack<debuff.improved_scorch.max_stack
|
|
if S.Scorch:IsReady() and (ImprovedScorchActive() and Target:DebuffStack(S.ImprovedScorchDebuff) < var_improved_scorch_max_stack) then
|
|
if Cast(S.Scorch, nil, nil, not Target:IsSpellInRange(S.Scorch)) then return "scorch standard_rotation 22"; end
|
|
end
|
|
-- phoenix_flames,if=!talent.alexstraszas_fury&!buff.hot_streak.react&!variable.phoenix_pooling&buff.flames_fury.up
|
|
if S.PhoenixFlames:IsCastable() and ((not S.AlexstraszasFury:IsAvailable()) and Player:BuffDown(S.HotStreakBuff) and (not var_phoenix_pooling) and Player:BuffUp(S.FlamesFuryBuff)) then
|
|
if Cast(S.PhoenixFlames, nil, nil, not Target:IsSpellInRange(S.PhoenixFlames)) then return "phoenix_flames standard_rotation 24"; end
|
|
end
|
|
-- phoenix_flames,if=talent.alexstraszas_fury&!buff.hot_streak.react&hot_streak_spells_in_flight=0&(!variable.phoenix_pooling&buff.flames_fury.up|charges_fractional>2.5|charges_fractional>1.5&buff.feel_the_burn.remains<2*gcd.max)
|
|
if S.PhoenixFlames:IsCastable() and (S.AlexstraszasFury:IsAvailable() and Player:BuffDown(S.HotStreakBuff) and HotStreakInFlight() == 0 and ((not var_phoenix_pooling) and Player:BuffUp(S.FlamesFuryBuff) or S.PhoenixFlames:ChargesFractional() > 2.5 or S.PhoenixFlames:ChargesFractional() > 1.5 and Player:BuffRemains(S.FeeltheBurnBuff) < 2 * GCDMax)) then
|
|
if Cast(S.PhoenixFlames, nil, nil, not Target:IsSpellInRange(S.PhoenixFlames)) then return "phoenix_flames standard_rotation 26"; end
|
|
end
|
|
-- call_action_list,name=active_talents
|
|
local ShouldReturn = ActiveTalents(); if ShouldReturn then return ShouldReturn; end
|
|
-- dragons_breath,if=active_enemies>1
|
|
if AoEON() and S.DragonsBreath:IsReady() and (EnemiesCount16ySplash > 1) then
|
|
if Settings.Fire.StayDistance and not Target:IsInRange(12) then
|
|
if CastLeft(S.DragonsBreath) then return "dragons_breath standard_rotation 28 left"; end
|
|
else
|
|
if Cast(S.DragonsBreath) then return "dragons_breath standard_rotation 28"; end
|
|
end
|
|
end
|
|
-- scorch,if=searing_touch.active
|
|
if S.Scorch:IsReady() and (SearingTouchActive()) then
|
|
if Cast(S.Scorch, nil, nil, not Target:IsSpellInRange(S.Scorch)) then return "scorch standard_rotation 30"; end
|
|
end
|
|
-- arcane_explosion,if=active_enemies>=variable.arcane_explosion&mana.pct>=variable.arcane_explosion_mana
|
|
if AoEON() and S.ArcaneExplosion:IsReady() and (EnemiesCount10yMelee >= var_arcane_explosion and Player:ManaPercentageP() >= var_arcane_explosion_mana) then
|
|
if Settings.Fire.StayDistance and not Target:IsInRange(10) then
|
|
if CastLeft(S.ArcaneExplosion) then return "arcane_explosion standard_rotation 32 left"; end
|
|
else
|
|
if Cast(S.ArcaneExplosion) then return "arcane_explosion standard_rotation 32"; end
|
|
end
|
|
end
|
|
-- flamestrike,if=active_enemies>=variable.hard_cast_flamestrike
|
|
if AoEON() and S.Flamestrike:IsReady() and (EnemiesCount8ySplash >= var_hard_cast_flamestrike) then
|
|
if Cast(S.Flamestrike, nil, nil, not Target:IsInRange(40)) then return "flamestrike standard_rotation 34"; end
|
|
end
|
|
-- pyroblast,if=talent.tempered_flames&!buff.flame_accelerant.react
|
|
-- fireball
|
|
if S.Fireball:IsReady() then
|
|
if Cast(S.Fireball, nil, nil, not Target:IsSpellInRange(S.Fireball)) then return "fireball standard_rotation 36"; end
|
|
end
|
|
end
|
|
|
|
--- ======= ACTION LISTS =======
|
|
local function APL()
|
|
-- Check which cast style we should use for Fire Blast
|
|
if Settings.Fire.ShowFireBlastLeft then
|
|
FBCast = CastLeft
|
|
else
|
|
FBCast = Cast
|
|
end
|
|
|
|
-- Update our enemy tables
|
|
Enemies8ySplash = Target:GetEnemiesInSplashRange(8)
|
|
Enemies10yMelee = Player:GetEnemiesInMeleeRange(10)
|
|
Enemies18yMelee = Player:GetEnemiesInMeleeRange(18)
|
|
if AoEON() then
|
|
EnemiesCount8ySplash = Target:GetEnemiesInSplashRangeCount(8)
|
|
EnemiesCount10ySplash = Target:GetEnemiesInSplashRangeCount(10)
|
|
EnemiesCount16ySplash = Target:GetEnemiesInSplashRangeCount(16)
|
|
EnemiesCount10yMelee = #Enemies10yMelee
|
|
EnemiesCount18yMelee = #Enemies18yMelee
|
|
else
|
|
EnemiesCount8ySplash = 1
|
|
EnemiesCount10ySplash = 1
|
|
EnemiesCount16ySplash = 1
|
|
EnemiesCount10yMelee = 1
|
|
EnemiesCount18yMelee = 1
|
|
end
|
|
|
|
if Everyone.TargetIsValid() or Player:AffectingCombat() then
|
|
-- Calculate fight_remains
|
|
BossFightRemains = HL.BossFightRemains(nil, true)
|
|
FightRemains = BossFightRemains
|
|
if FightRemains == 11111 then
|
|
FightRemains = HL.FightRemains(Enemies8ySplash, false)
|
|
end
|
|
|
|
-- Check how many units have ignite
|
|
UnitsWithIgniteCount = UnitsWithIgnite(Enemies8ySplash)
|
|
|
|
-- variable,name=disable_combustion,op=reset (from Precombat)
|
|
var_disable_combustion = not CDsON()
|
|
|
|
-- variable,name=time_to_combustion,value=fight_remains+100,if=variable.disable_combustion (from Precombat)
|
|
if var_disable_combustion then
|
|
var_time_to_combustion = 99999
|
|
end
|
|
|
|
-- Define gcd.max
|
|
GCDMax = Player:GCD() + 0.25
|
|
|
|
-- Get our Combustion status
|
|
CombustionUp = Player:BuffUp(S.CombustionBuff)
|
|
CombustionDown = not CombustionUp
|
|
end
|
|
|
|
if Everyone.TargetIsValid() then
|
|
-- call precombat
|
|
if not Player:AffectingCombat() then
|
|
local ShouldReturn = Precombat(); if ShouldReturn then return ShouldReturn; end
|
|
end
|
|
-- Manually added: Also CastLeft Pyroblast if we have a freebie
|
|
if S.Pyroblast:IsReady() and UseFreeCast() and FreeCastAvailable() then
|
|
if CastLeft(S.Pyroblast) then return "pyroblast free"; end
|
|
end
|
|
-- counterspell
|
|
local ShouldReturn = Everyone.Interrupt(40, S.Counterspell, Settings.Commons.OffGCDasOffGCD.Counterspell, false); if ShouldReturn then return ShouldReturn; end
|
|
-- call_action_list,name=combustion_timing,if=!variable.disable_combustion
|
|
if not var_disable_combustion then
|
|
CombustionTiming()
|
|
end
|
|
-- time_warp,if=talent.temporal_warp&(buff.exhaustion.up|interpolated_fight_remains<buff.bloodlust.duration)
|
|
if CDsON() and S.TimeWarp:IsReady() and (S.TemporalWarp:IsAvailable() and Player:BloodlustExhaustUp()) then
|
|
if Cast(S.TimeWarp, Settings.Commons.OffGCDasOffGCD.TimeWarp) then return "time_warp main 2"; end
|
|
end
|
|
-- potion,if=buff.potion.duration>variable.time_to_combustion+buff.combustion.duration
|
|
if Settings.Commons.Enabled.Potions then
|
|
local PotionSelected = Everyone.PotionSelected()
|
|
if PotionSelected and PotionSelected:IsReady() and (PotionSelected:BuffDuration() > var_time_to_combustion + 12) then
|
|
if Cast(PotionSelected, nil, Settings.Commons.DisplayStyle.Potions) then return "potion main 4"; end
|
|
end
|
|
end
|
|
-- variable,name=shifting_power_before_combustion,value=variable.time_to_combustion>cooldown.shifting_power.remains
|
|
var_shifting_power_before_combustion = var_time_to_combustion > S.ShiftingPower:CooldownRemains()
|
|
if Settings.Commons.Enabled.Trinkets then
|
|
-- variable,name=item_cutoff_active,value=(variable.time_to_combustion<variable.on_use_cutoff|buff.combustion.remains>variable.skb_duration&!cooldown.item_cd_1141.remains)&((trinket.1.has_cooldown&trinket.1.cooldown.remains<variable.on_use_cutoff)+(trinket.2.has_cooldown&trinket.2.cooldown.remains<variable.on_use_cutoff)>1)
|
|
var_item_cutoff_active = (var_time_to_combustion < var_on_use_cutoff or Player:BuffRemains(S.CombustionBuff) > var_skb_duration and (I.DragonfireBombDispenser:CooldownUp() or not I.DragonfireBombDispenser:IsEquipped())) and (num(Trinket1:Cooldown() > 0 and Trinket1:CooldownRemains() < var_on_use_cutoff) + num(Trinket2:Cooldown() and Trinket2:CooldownRemains() < var_on_use_cutoff) > 1)
|
|
-- use_item,effect_name=gladiators_badge,if=variable.time_to_combustion>cooldown-5
|
|
if I.CrimsonGladiatorsBadge:IsEquippedAndReady() and (var_time_to_combustion > I.CrimsonGladiatorsBadge:Cooldown() - 5) then
|
|
if Cast(I.CrimsonGladiatorsBadge, nil, Settings.Commons.DisplayStyle.Trinkets) then return "gladiators_badge (crimson) main 6"; end
|
|
end
|
|
if I.ObsidianGladiatorsBadge:IsEquippedAndReady() and (var_time_to_combustion > I.ObsidianGladiatorsBadge:Cooldown() - 5) then
|
|
if Cast(I.ObsidianGladiatorsBadge, nil, Settings.Commons.DisplayStyle.Trinkets) then return "gladiators_badge (obsidian) main 8"; end
|
|
end
|
|
-- use_item,name=moonlit_prism,if=variable.time_to_combustion<=5|fight_remains<variable.time_to_combustion
|
|
if I.MoonlitPrism:IsEquippedAndReady() and (var_time_to_combustion <= 5 or FightRemains < var_time_to_combustion) then
|
|
if Cast(I.MoonlitPrism, nil, Settings.Commons.DisplayStyle.Trinkets) then return "moonlit_prism main 10"; end
|
|
end
|
|
-- use_items,if=!variable.item_cutoff_active
|
|
if (Settings.Commons.Enabled.Trinkets or Settings.Commons.Enabled.Items) and not var_item_cutoff_active then
|
|
local ItemToUse, ItemSlot, ItemRange = Player:GetUseableItems(OnUseExcludes)
|
|
if ItemToUse then
|
|
local DisplayStyle = Settings.Commons.DisplayStyle.Trinkets
|
|
if ItemSlot ~= 13 and ItemSlot ~= 14 then DisplayStyle = Settings.Commons.DisplayStyle.Items end
|
|
if ((ItemSlot == 13 or ItemSlot == 14) and Settings.Commons.Enabled.Trinkets) or (ItemSlot ~=13 and ItemSlot ~= 14 and Settings.Commons.Enabled.Items) then
|
|
if Cast(ItemToUse, nil, DisplayStyle, not Target:IsInRange(ItemRange)) then return "Generic use_items for " .. ItemToUse:Name(); end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=fire_blast_pooling,value=buff.combustion.down&action.fire_blast.charges_fractional+(variable.time_to_combustion+action.shifting_power.full_reduction*variable.shifting_power_before_combustion)%cooldown.fire_blast.duration-1<cooldown.fire_blast.max_charges+variable.overpool_fire_blasts%cooldown.fire_blast.duration-(buff.combustion.duration%cooldown.fire_blast.duration)%%1&variable.time_to_combustion<fight_remains
|
|
var_fire_blast_pooling = CombustionDown and S.FireBlast:ChargesFractional() + (var_time_to_combustion + ShiftingPowerFullReduction() * num(var_shifting_power_before_combustion)) / S.FireBlast:Cooldown() - 1 < S.FireBlast:MaxCharges() + var_overpool_fire_blasts / S.FireBlast:Cooldown() - (12 / S.FireBlast:Cooldown()) % 1 and var_time_to_combustion < FightRemains
|
|
-- call_action_list,name=combustion_phase,if=variable.time_to_combustion<=0|buff.combustion.up|variable.time_to_combustion<variable.combustion_precast_time&cooldown.combustion.remains<variable.combustion_precast_time
|
|
if not var_disable_combustion and (var_time_to_combustion <= 0 or CombustionUp or var_time_to_combustion < var_combustion_precast_time and S.Combustion:CooldownRemains() < var_combustion_precast_time) then
|
|
local ShouldReturn = CombustionPhase(); if ShouldReturn then return ShouldReturn; end
|
|
end
|
|
-- variable,use_off_gcd=1,use_while_casting=1,name=fire_blast_pooling,value=searing_touch.active&action.fire_blast.full_recharge_time>3*gcd.max,if=!variable.fire_blast_pooling&talent.sun_kings_blessing
|
|
if (not var_fire_blast_pooling) and S.SunKingsBlessing:IsAvailable() then
|
|
var_fire_blast_pooling = SearingTouchActive() and S.FireBlast:FullRechargeTime() > 3 * GCDMax
|
|
end
|
|
-- shifting_power,if=buff.combustion.down&(action.fire_blast.charges=0|variable.fire_blast_pooling)&!buff.hot_streak.react&variable.shifting_power_before_combustion
|
|
if S.ShiftingPower:IsReady() and (CombustionDown and (S.FireBlast:Charges() == 0 or var_fire_blast_pooling) and Player:BuffDown(S.HotStreakBuff) and var_shifting_power_before_combustion) then
|
|
if Cast(S.ShiftingPower, nil, Settings.Commons.DisplayStyle.Signature, not Target:IsInRange(18)) then return "shifting_power main 12"; end
|
|
end
|
|
-- variable,name=phoenix_pooling,if=active_enemies<variable.combustion_flamestrike,value=(variable.time_to_combustion+buff.combustion.duration-5<action.phoenix_flames.full_recharge_time+cooldown.phoenix_flames.duration-action.shifting_power.full_reduction*variable.shifting_power_before_combustion&variable.time_to_combustion<fight_remains|talent.sun_kings_blessing)&!talent.alexstraszas_fury
|
|
-- Note: Swapped SunKingsBlessing check to the front so we can avoid lots of math if it's talented.
|
|
if EnemiesCount8ySplash < var_combustion_flamestrike then
|
|
var_phoenix_pooling = (S.SunKingsBlessing:IsAvailable() or var_time_to_combustion + 7 < S.PhoenixFlames:FullRechargeTime() + S.PhoenixFlames:Cooldown() - ShiftingPowerFullReduction() * num(var_shifting_power_before_combustion) and var_time_to_combustion < FightRemains) and not S.AlexstraszasFury:IsAvailable()
|
|
end
|
|
-- variable,name=phoenix_pooling,if=active_enemies>=variable.combustion_flamestrike,value=(variable.time_to_combustion<action.phoenix_flames.full_recharge_time-action.shifting_power.full_reduction*variable.shifting_power_before_combustion&variable.time_to_combustion<fight_remains|talent.sun_kings_blessing)&!talent.alexstraszas_fury
|
|
-- Note: Swapped SunKingsBlessing check to the front so we can avoid lots of math if it's talented.
|
|
if EnemiesCount8ySplash >= var_combustion_flamestrike then
|
|
var_phoenix_pooling = (S.SunKingsBlessing:IsAvailable() or var_time_to_combustion < S.PhoenixFlames:FullRechargeTime() - ShiftingPowerFullReduction() * num(var_shifting_power_before_combustion) and var_time_to_combustion < FightRemains) and not S.AlexstraszasFury:IsAvailable()
|
|
end
|
|
-- fire_blast,use_off_gcd=1,use_while_casting=1,if=!variable.fire_blast_pooling&variable.time_to_combustion>0&active_enemies>=variable.hard_cast_flamestrike&!firestarter.active&!buff.hot_streak.react&(buff.heating_up.react&action.flamestrike.execute_remains<0.5|charges_fractional>=2)
|
|
if S.FireBlast:IsReady() and (not FreeCastAvailable()) and ((not var_fire_blast_pooling) and var_time_to_combustion > 0 and EnemiesCount8ySplash >= var_hard_cast_flamestrike and (not FirestarterActive()) and Player:BuffDown(S.HotStreakBuff) and (Player:BuffUp(S.HeatingUpBuff) and S.Flamestrike:ExecuteRemains() < 0.5 or S.FireBlast:ChargesFractional() >= 2)) then
|
|
if FBCast(S.FireBlast) then return "fire_blast main 14"; end
|
|
end
|
|
-- call_action_list,name=firestarter_fire_blasts,if=buff.combustion.down&firestarter.active&variable.time_to_combustion>0
|
|
if CombustionDown and FirestarterActive() and var_time_to_combustion > 0 then
|
|
local ShouldReturn = FirestarterFireBlasts(); if ShouldReturn then return ShouldReturn; end
|
|
end
|
|
-- fire_blast,use_while_casting=1,if=action.shifting_power.executing&full_recharge_time<action.shifting_power.tick_reduction
|
|
if S.FireBlast:IsReady() and (not FreeCastAvailable()) and (Player:IsCasting(S.ShiftingPower) and S.FireBlast:FullRechargeTime() < ShiftingPowerTickReduction) then
|
|
if FBCast(S.FireBlast) then return "fire_blast main 16"; end
|
|
end
|
|
-- call_action_list,name=standard_rotation,if=variable.time_to_combustion>0&buff.combustion.down
|
|
if var_time_to_combustion > 0 and CombustionDown then
|
|
local ShouldReturn = StandardRotation(); if ShouldReturn then return ShouldReturn; end
|
|
end
|
|
-- ice_nova,if=!searing_touch.active
|
|
if S.IceNova:IsCastable() and (not SearingTouchActive()) then
|
|
if Cast(S.IceNova, nil, nil, not Target:IsSpellInRange(S.IceNova)) then return "ice_nova main 18"; end
|
|
end
|
|
-- scorch
|
|
if S.Scorch:IsReady() then
|
|
if Cast(S.Scorch, nil, nil, not Target:IsSpellInRange(S.Scorch)) then return "scorch main 20"; end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function Init()
|
|
HR.Print("Fire Mage rotation is currently a work in progress, but has been updated for patch 10.1.5.")
|
|
end
|
|
|
|
HR.SetAPL(63, APL, Init)
|
|
|