--- ============================ HEADER ============================
--- ======= LOCALIZE =======
-- Addon
local addonName , addonTable = ...
-- 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 AoEON = HR.AoEON
local CDsON = HR.CDsON
-- Num/Bool Helper Functions
local num = HR.Commons . Everyone.num
local bool = HR.Commons . Everyone.bool
--- ============================ CONTENT ===========================
--- ======= APL LOCALS =======
-- GUI Settings
local Everyone = HR.Commons . Everyone
local Settings = {
General = HR.GUISettings . General ,
Commons = HR.GUISettings . APL.Hunter . Commons ,
Commons2 = HR.GUISettings . APL.Hunter . Commons2 ,
Survival = HR.GUISettings . APL.Hunter . Survival
}
-- Spells
local S = Spell.Hunter . Survival
-- Items
local I = Item.Hunter . Survival
local OnUseExcludes = {
I.AlgetharPuzzleBox : ID ( ) ,
I.ManicGrieftorch : ID ( ) ,
}
-- Rotation Var
local SummonPetSpells = { S.SummonPet , S.SummonPet2 , S.SummonPet3 , S.SummonPet4 , S.SummonPet5 }
local EnemyCount8ySplash , EnemyList
local BossFightRemains = 11111
local FightRemains = 11111
local MBRSCost = S.MongooseBite : IsAvailable ( ) and S.MongooseBite : Cost ( ) or S.RaptorStrike : Cost ( )
local MeleeRange = S.Lunge : IsAvailable ( ) and 8 or 5
HL : RegisterForEvent ( function ( )
MBRSCost = S.MongooseBite : IsAvailable ( ) and S.MongooseBite : Cost ( ) or S.RaptorStrike : Cost ( )
MeleeRange = S.Lunge : IsAvailable ( ) and 8 or 5
end , " SPELLS_CHANGED " , " LEARNED_SPELL_IN_TAB " )
HL : RegisterForEvent ( function ( )
BossFightRemains = 11111
FightRemains = 11111
end , " PLAYER_REGEN_ENABLED " )
-- Stuns
local StunInterrupts = {
{ S.Intimidation , " Cast Intimidation (Interrupt) " , function ( ) return true ; end } ,
}
-- Bombs
local Bombs = { S.WildfireBomb , S.ShrapnelBomb , S.PheromoneBomb , S.VolatileBomb }
local BombDebuffs = { S.WildfireBombDebuff , S.ShrapnelBombDebuff , S.PheromoneBombDebuff , S.VolatileBombDebuff }
-- Function to see if we're going to cap focus
local function CheckFocusCap ( SpellCastTime , GenFocus )
local GeneratedFocus = GenFocus or 0
return ( Player : Focus ( ) + Player : FocusCastRegen ( SpellCastTime ) + GeneratedFocus < Player : FocusMax ( ) )
end
-- CastCycle/CastTargetIf functions
local function EvaluateTargetIfFilterSerpentStingRemains ( TargetUnit )
-- target_if=min:remains
return ( TargetUnit : DebuffRemains ( S.SerpentStingDebuff ) )
end
local function EvaluateTargetIfFilterBloodseekerRemains ( TargetUnit )
-- target_if=min:bloodseeker.remains
return ( TargetUnit : DebuffRemains ( S.BloodseekerDebuff ) )
end
local function EvaluateTargetIfFilterLatentStacks ( TargetUnit )
-- target_if=max:debuff.latent_poison.stack
return ( TargetUnit : DebuffStack ( S.LatentPoisonDebuff ) )
end
local function EvaluateTargetIfKillCommandST ( TargetUnit )
-- if=cooldown.wildfire_bomb.full_recharge_time<2*gcd&debuff.shredded_armor.down&set_bonus.tier30_4pc
-- Note: All but debuff check handled before CastTargetIf.
return ( TargetUnit : DebuffDown ( S.ShreddedArmorDebuff ) )
end
local function EvaluateTargetIfKillCommandST2 ( TargetUnit )
-- if=full_recharge_time<gcd&focus+cast_regen<focus.max&(cooldown.flanking_strike.remains|!talent.flanking_strike)|debuff.shredded_armor.down&set_bonus.tier30_4pc
return ( S.KillCommand : FullRechargeTime ( ) < Player : GCD ( ) and CheckFocusCap ( S.KillCommand : ExecuteTime ( ) , 21 ) and ( S.FlankingStrike : CooldownDown ( ) or not S.FlankingStrike : IsAvailable ( ) ) or TargetUnit : DebuffDown ( S.ShreddedArmorDebuff ) and Player : HasTier ( 30 , 4 ) )
end
local function EvaluateTargetIfRaptorStrikeCleave ( TargetUnit )
-- if=debuff.latent_poison.stack>8
return ( TargetUnit : DebuffStack ( S.LatentPoisonDebuff ) > 8 )
end
local function EvaluateTargetIfSerpentStingCleave ( TargetUnit )
-- if=refreshable&target.time_to_die>8&(!talent.vipers_venom|talent.hydras_bite)
return ( TargetUnit : DebuffRefreshable ( S.SerpentStingDebuff ) and TargetUnit : TimeToDie ( ) > 8 and ( ( not S.VipersVenom : IsAvailable ( ) ) or S.HydrasBite : IsAvailable ( ) ) )
end
local function EvaluateTargetIfSerpentStingST ( TargetUnit )
-- if=!dot.serpent_sting.ticking&target.time_to_die>7&!talent.vipers_venom
return ( TargetUnit : DebuffDown ( S.SerpentStingDebuff ) and TargetUnit : TimeToDie ( ) > 7 )
end
local function EvaluateTargetIfSerpentStingST2 ( TargetUnit )
-- if=refreshable&!talent.vipers_venom
return ( TargetUnit : DebuffRefreshable ( S.SerpentStingDebuff ) )
end
local function Precombat ( )
-- flask
-- augmentation
-- food
-- variable,name=mb_rs_cost,op=setif,value=action.mongoose_bite.cost,value_else=action.raptor_strike.cost,condition=talent.mongoose_bite
-- Defined with profile variables
-- summon_pet
-- Moved to Pet Management section in APL()
-- snapshot_stat
-- use_item,name=algethar_puzzle_box
if Settings.Commons . Enabled.Trinkets and I.AlgetharPuzzleBox : IsEquippedAndReady ( ) then
if Cast ( I.AlgetharPuzzleBox , nil , Settings.Commons . DisplayStyle.Trinkets ) then return " algethar_puzzle_box precombat 1 " ; end
end
-- steel_trap,precast_time=2
if S.SteelTrap : IsCastable ( ) and Target : DebuffDown ( S.SteelTrapDebuff ) then
if Cast ( S.SteelTrap , nil , nil , not Target : IsInRange ( 40 ) ) then return " steel_trap precombat 2 " ; end
end
-- Manually added: harpoon
if S.Harpoon : IsCastable ( ) and ( Player : BuffDown ( S.AspectoftheEagle ) or not Target : IsInRange ( 30 ) ) then
if Cast ( S.Harpoon , Settings.Survival . GCDasOffGCD.Harpoon , nil , not Target : IsSpellInRange ( S.Harpoon ) ) then return " harpoon precombat 4 " ; end
end
-- Manually added: mongoose_bite or raptor_strike
if Target : IsInMeleeRange ( MeleeRange ) or ( Player : BuffUp ( S.AspectoftheEagle ) and Target : IsInRange ( 40 ) ) then
if S.MongooseBite : IsReady ( ) then
if Cast ( S.MongooseBite ) then return " mongoose_bite precombat 6 " ; end
elseif S.RaptorStrike : IsReady ( ) then
if Cast ( S.RaptorStrike ) then return " raptor_strike precombat 8 " ; end
end
end
end
local function CDs ( )
-- blood_fury,if=buff.coordinated_assault.up|buff.spearhead.up|!talent.spearhead&!talent.coordinated_assault
if S.BloodFury : IsCastable ( ) and ( Player : BuffUp ( S.CoordinatedAssaultBuff ) or Player : BuffUp ( S.SpearheadBuff ) or ( not S.Spearhead : IsAvailable ( ) ) and not S.CoordinatedAssault : IsAvailable ( ) ) then
if Cast ( S.BloodFury , Settings.Commons . OffGCDasOffGCD.Racials ) then return " blood_fury cds 2 " ; end
end
-- harpoon,if=talent.terms_of_engagement.enabled&focus<focus.max
if S.Harpoon : IsCastable ( ) and ( S.TermsofEngagement : IsAvailable ( ) and Player : Focus ( ) < Player : FocusMax ( ) ) then
if Cast ( S.Harpoon , Settings.Survival . GCDasOffGCD.Harpoon , nil , not Target : IsSpellInRange ( S.Harpoon ) ) then return " harpoon cds 4 " ; end
end
if ( Player : BuffUp ( S.CoordinatedAssaultBuff ) or Player : BuffUp ( S.SpearheadBuff ) or ( not S.Spearhead : IsAvailable ( ) ) and not S.CoordinatedAssault : IsAvailable ( ) ) then
-- ancestral_call,if=buff.coordinated_assault.up|buff.spearhead.up|!talent.spearhead&!talent.coordinated_assault
if S.AncestralCall : IsCastable ( ) then
if Cast ( S.AncestralCall , Settings.Commons . OffGCDasOffGCD.Racials ) then return " ancestral_call cds 6 " ; end
end
-- fireblood,if=buff.coordinated_assault.up|buff.spearhead.up|!talent.spearhead&!talent.coordinated_assault
if S.Fireblood : IsCastable ( ) then
if Cast ( S.Fireblood , Settings.Commons . OffGCDasOffGCD.Racials ) then return " fireblood cds 8 " ; end
end
end
-- lights_judgment
if S.LightsJudgment : IsCastable ( ) then
if Cast ( S.LightsJudgment , Settings.Commons . OffGCDasOffGCD.Racials , nil , not Target : IsSpellInRange ( S.LightsJudgment ) ) then return " lights_judgment cds 10 " ; end
end
-- bag_of_tricks,if=cooldown.kill_command.full_recharge_time>gcd
if S.BagofTricks : IsCastable ( ) and ( S.KillCommand : FullRechargeTime ( ) > Player : GCD ( ) ) then
if Cast ( S.BagofTricks , Settings.Commons . OffGCDasOffGCD.Racials , nil , not Target : IsSpellInRange ( S.BagofTricks ) ) then return " bag_of_tricks cds 12 " ; end
end
-- berserking,if=buff.coordinated_assault.up|buff.spearhead.up|!talent.spearhead&!talent.coordinated_assault|time_to_die<13
if S.Berserking : IsCastable ( ) and ( Player : BuffUp ( S.CoordinatedAssaultBuff ) or Player : BuffUp ( S.SpearheadBuff ) or ( not S.Spearhead : IsAvailable ( ) ) and ( not S.CoordinatedAssault : IsAvailable ( ) ) or FightRemains < 13 ) then
if Cast ( S.Berserking , Settings.Commons . OffGCDasOffGCD.Racials ) then return " berserking cds 14 " ; end
end
-- muzzle
-- Handled via Interrupt in APL()
-- potion,if=target.time_to_die<25|buff.coordinated_assault.up|buff.spearhead.up|!talent.spearhead&!talent.coordinated_assault
if Settings.Commons . Enabled.Potions and ( FightRemains < 25 or Player : BuffUp ( S.CoordinatedAssaultBuff ) or Player : BuffUp ( S.SpearheadBuff ) or ( not S.Spearhead : IsAvailable ( ) ) and not S.CoordinatedAssault : IsAvailable ( ) ) then
local PotionSelected = Everyone.PotionSelected ( )
if PotionSelected and PotionSelected : IsReady ( ) then
if Cast ( PotionSelected , nil , Settings.Commons . DisplayStyle.Potions ) then return " potion cds 16 " ; end
end
end
if Settings.Commons . Enabled.Trinkets then
-- use_item,name=algethar_puzzle_box,use_off_gcd=1,if=gcd.remains>gcd.max-0.1
-- Note: Widened the available window by half a second to account for player reaction.
if I.AlgetharPuzzleBox : IsEquippedAndReady ( ) and ( Player : GCDRemains ( ) > Player : GCD ( ) - 0.6 ) then
if Cast ( I.AlgetharPuzzleBox , nil , Settings.Commons . DisplayStyle.Trinkets ) then return " algethar_puzzle_box cds 17 " ; end
end
-- use_item,name=manic_grieftorch,use_off_gcd=1,if=gcd.remains>gcd.max-0.1&!buff.spearhead.up
if I.ManicGrieftorch : IsEquippedAndReady ( ) and ( Player : GCDRemains ( ) > Player : GCD ( ) - 0.6 and Player : BuffDown ( S.SpearheadBuff ) ) then
if Cast ( I.ManicGrieftorch , nil , Settings.Commons . DisplayStyle.Trinkets ) then return " manic_grieftorch cds 18 " ; end
end
end
if Settings.Commons . Enabled.Trinkets or Settings.Commons . Enabled.Items then
-- use_items,use_off_gcd=1,if=gcd.remains>gcd.max-0.1&!buff.spearhead.up
if Player : BuffDown ( S.SpearheadBuff ) 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
-- aspect_of_the_eagle,if=target.distance>=6
if S.AspectoftheEagle : IsCastable ( ) and Settings.Survival . AspectOfTheEagle and not Target : IsInRange ( MeleeRange ) then
if Cast ( S.AspectoftheEagle , Settings.Survival . OffGCDasOffGCD.AspectOfTheEagle ) then return " aspect_of_the_eagle cds 19 " ; end
end
end
local function Cleave ( )
-- kill_command,if=debuff.shredded_armor.down&set_bonus.tier30_4pc
if S.KillCommand : IsCastable ( ) and ( Target : DebuffDown ( S.ShreddedArmorDebuff ) and Player : HasTier ( 30 , 4 ) ) then
if Cast ( S.KillCommand , nil , nil , not Target : IsSpellInRange ( S.KillCommand ) ) then return " kill_command cleave 2 " ; end
end
-- kill_shot,if=buff.coordinated_assault_empower.up
if S.KillShot : IsReady ( ) and ( Player : BuffUp ( S.CoordinatedAssaultEmpowerBuff ) or Settings.Survival . CAKSMacro and Player : BuffUp ( S.CoordinatedAssaultBuff ) and ( S.Bite : IsReady ( ) or S.Claw : IsReady ( ) or S.Smack : IsReady ( ) ) ) then
if Cast ( S.KillShot , nil , nil , not Target : IsSpellInRange ( S.KillShot ) ) then return " kill_shot cleave 4 " ; end
end
-- wildfire_bomb,if=full_recharge_time<gcd|!cooldown.coordinated_assault.remains|buff.coordinated_assault.remains&!buff.coordinated_assault_empower.up
if ( S.WildfireBomb : FullRechargeTime ( ) < Player : GCD ( ) or S.CoordinatedAssault : CooldownUp ( ) or Player : BuffRemains ( S.CoordinatedAssaultBuff ) and Player : BuffDown ( S.CoordinatedAssaultEmpowerBuff ) ) then
for _ , Bomb in pairs ( Bombs ) do
if Bomb : IsCastable ( ) then
if Cast ( Bomb , nil , nil , not Target : IsSpellInRange ( Bomb ) ) then return " wildfire_bomb cleave 6 " ; end
end
end
end
-- death_chakram
if S.DeathChakram : IsCastable ( ) then
if Cast ( S.DeathChakram , nil , Settings.Commons . DisplayStyle.Signature , not Target : IsSpellInRange ( S.DeathChakram ) ) then return " death_chakram cleave 8 " ; end
end
-- stampede
if S.Stampede : IsCastable ( ) and CDsON ( ) then
if Cast ( S.Stampede , nil , nil , not Target : IsSpellInRange ( S.Stampede ) ) then return " stampede cleave 10 " ; end
end
-- coordinated_assault,if=cooldown.fury_of_the_eagle.remains|!talent.fury_of_the_eagle
if S.CoordinatedAssault : IsCastable ( ) and CDsON ( ) and ( S.FuryoftheEagle : CooldownDown ( ) or not S.FuryoftheEagle : IsAvailable ( ) ) then
if Cast ( S.CoordinatedAssault , Settings.Survival . GCDasOffGCD.CoordinatedAssault , nil , not Target : IsSpellInRange ( S.CoordinatedAssault ) ) then return " coordinated_assault cleave 12 " ; end
end
-- explosive_shot
if S.ExplosiveShot : IsReady ( ) then
if Cast ( S.ExplosiveShot , Settings.Commons2 . GCDasOffGCD.ExplosiveShot , nil , not Target : IsSpellInRange ( S.ExplosiveShot ) ) then return " explosive_shot cleave 14 " ; end
end
-- carve,if=cooldown.wildfire_bomb.full_recharge_time>spell_targets%2
if S.Carve : IsReady ( ) and ( S.WildfireBomb : FullRechargeTime ( ) > EnemyCount8ySplash / 2 ) then
if Cast ( S.Carve , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " carve cleave 16 " ; end
end
-- butchery,if=full_recharge_time<gcd|dot.shrapnel_bomb.ticking&(dot.internal_bleeding.stack<2|dot.shrapnel_bomb.remains<gcd)
if S.Butchery : IsReady ( ) and ( S.Butchery : FullRechargeTime ( ) < Player : GCD ( ) or Target : DebuffUp ( S.ShrapnelBombDebuff ) and ( Target : DebuffStack ( S.InternalBleedingDebuff ) < 2 or Target : DebuffRemains ( S.ShrapnelBombDebuff ) < Player : GCD ( ) ) ) then
if Cast ( S.Butchery , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " butchery cleave 18 " ; end
end
-- wildfire_bomb,if=!dot.wildfire_bomb.ticking
for BombNum , Bomb in pairs ( Bombs ) do
if Bomb : IsCastable ( ) and ( Target : DebuffDown ( BombDebuffs [ BombNum ] ) ) then
if Cast ( Bomb , nil , nil , not Target : IsSpellInRange ( Bomb ) ) then return " wildfire_bomb cleave 20 " ; end
end
end
-- fury_of_the_eagle
if S.FuryoftheEagle : IsCastable ( ) then
if Cast ( S.FuryoftheEagle , nil , Settings.Commons . DisplayStyle.Signature , not Target : IsInMeleeRange ( MeleeRange ) ) then return " fury_of_the_eagle cleave 22 " ; end
end
-- carve,if=dot.shrapnel_bomb.ticking
if S.Carve : IsReady ( ) and ( Target : DebuffUp ( S.ShrapnelBombDebuff ) ) then
if Cast ( S.Carve , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " carve cleave 24 " ; end
end
-- flanking_strike,if=focus+cast_regen<focus.max
if S.FlankingStrike : IsCastable ( ) and ( CheckFocusCap ( S.FlankingStrike : ExecuteTime ( ) , 30 ) ) then
if Cast ( S.FlankingStrike , nil , nil , not Target : IsSpellInRange ( S.FlankingStrike ) ) then return " flanking_strike cleave 26 " ; end
end
-- butchery,if=(!next_wi_bomb.shrapnel|!talent.wildfire_infusion)
if S.Butchery : IsReady ( ) and ( ( not S.ShrapnelBomb : IsCastable ( ) ) or not S.WildfireInfusion : IsAvailable ( ) ) then
if Cast ( S.Butchery , nil , nil , not Target : IsInMeleeRange ( 8 ) ) then return " butchery cleave 28 " ; end
end
-- mongoose_bite,target_if=max:debuff.latent_poison.stack,if=debuff.latent_poison.stack>8
if S.MongooseBite : IsReady ( ) then
if Everyone.CastTargetIf ( S.MongooseBite , EnemyList , " max " , EvaluateTargetIfFilterLatentStacks , EvaluateTargetIfRaptorStrikeCleave , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite cleave 30 " ; end
end
-- raptor_strike,target_if=max:debuff.latent_poison.stack,if=debuff.latent_poison.stack>8
if S.RaptorStrike : IsReady ( ) then
if Everyone.CastTargetIf ( S.RaptorStrike , EnemyList , " max " , EvaluateTargetIfFilterLatentStacks , EvaluateTargetIfRaptorStrikeCleave , not Target : IsInMeleeRange ( MeleeRange ) ) then return " raptor_strike cleave 32 " ; end
end
-- kill_command,target_if=min:bloodseeker.remains,if=focus+cast_regen<focus.max&full_recharge_time<gcd
if S.KillCommand : IsCastable ( ) and ( CheckFocusCap ( S.KillCommand : ExecuteTime ( ) ) and S.KillCommand : FullRechargeTime ( ) < Player : GCD ( ) ) then
if Everyone.CastTargetIf ( S.KillCommand , EnemyList , " min " , EvaluateTargetIfFilterBloodseekerRemains , nil , not Target : IsSpellInRange ( S.KillCommand ) ) then return " kill_command cleave 34 " ; end
end
-- carve
if S.Carve : IsReady ( ) then
if Cast ( S.Carve , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " carve cleave 36 " ; end
end
-- kill_shot,if=!buff.coordinated_assault.up
if S.KillShot : IsReady ( ) and ( Player : BuffDown ( S.CoordinatedAssaultBuff ) ) then
if Cast ( S.KillShot , nil , nil , not Target : IsSpellInRange ( S.KillShot ) ) then return " kill_shot cleave 38 " ; end
end
-- steel_trap,if=focus+cast_regen<focus.max
if S.SteelTrap : IsCastable ( ) and ( CheckFocusCap ( S.SteelTrap : ExecuteTime ( ) ) ) then
if Cast ( S.SteelTrap , Settings.Commons2 . GCDasOffGCD.SteelTrap , nil , not Target : IsInRange ( 40 ) ) then return " steel_trap cleave 40 " ; end
end
-- spearhead
if S.Spearhead : IsCastable ( ) and CDsON ( ) then
if Cast ( S.Spearhead , nil , nil , not Target : IsSpellInRange ( S.Spearhead ) ) then return " spearhead cleave 41 " ; end
end
-- mongoose_bite,target_if=min:dot.serpent_sting.remains,if=buff.spearhead.remains
if S.MongooseBite : IsReady ( ) and ( Player : BuffUp ( S.SpearheadBuff ) ) then
if Everyone.CastTargetIf ( S.MongooseBite , EnemyList , " min " , EvaluateTargetIfFilterSerpentStingRemains , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite cleave 42 " ; end
end
-- serpent_sting,target_if=min:remains,if=refreshable&target.time_to_die>8&(!talent.vipers_venom|talent.hydras_bite)
if S.SerpentSting : IsReady ( ) then
if Everyone.CastTargetIf ( S.SerpentSting , EnemyList , " min " , EvaluateTargetIfFilterSerpentStingRemains , EvaluateTargetIfSerpentStingCleave , not Target : IsSpellInRange ( S.SerpentSting ) ) then return " serpent_sting cleave 43 " ; end
end
-- mongoose_bite,target_if=min:dot.serpent_sting.remains
if S.MongooseBite : IsReady ( ) then
if Everyone.CastTargetIf ( S.MongooseBite , EnemyList , " min " , EvaluateTargetIfFilterSerpentStingRemains , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite cleave 44 " ; end
end
-- raptor_strike,target_if=min:dot.serpent_sting.remains
if S.RaptorStrike : IsReady ( ) then
if Everyone.CastTargetIf ( S.RaptorStrike , EnemyList , " min " , EvaluateTargetIfFilterSerpentStingRemains , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " raptor_strike cleave 46 " ; end
end
end
local function ST ( )
-- death_chakram,if=focus+cast_regen<focus.max|talent.spearhead&!cooldown.spearhead.remains
if S.DeathChakram : IsCastable ( ) and ( CheckFocusCap ( S.DeathChakram : ExecuteTime ( ) ) or S.Spearhead : IsAvailable ( ) and S.Spearhead : CooldownUp ( ) ) then
if Cast ( S.DeathChakram , nil , Settings.Commons . DisplayStyle.Signature , not Target : IsSpellInRange ( S.DeathChakram ) ) then return " death_chakram st 2 " ; end
end
-- spearhead,if=focus+action.kill_command.cast_regen>focus.max-10&(cooldown.death_chakram.remains|!talent.death_chakram)
if S.Spearhead : IsCastable ( ) and CDsON ( ) and ( Player : Focus ( ) + Player : FocusCastRegen ( S.KillCommand : ExecuteTime ( ) ) + 21 > Player : FocusMax ( ) - 10 and ( S.DeathChakram : CooldownDown ( ) or not S.DeathChakram : IsAvailable ( ) ) ) then
if Cast ( S.Spearhead , nil , nil , not Target : IsSpellInRange ( S.Spearhead ) ) then return " spearhead st 4 " ; end
end
-- kill_shot,if=buff.coordinated_assault_empower.up
if S.KillShot : IsReady ( ) and ( Player : BuffUp ( S.CoordinatedAssaultEmpowerBuff ) or Settings.Survival . CAKSMacro and Player : BuffUp ( S.CoordinatedAssaultBuff ) and ( S.Bite : IsReady ( ) or S.Claw : IsReady ( ) or S.Smack : IsReady ( ) ) ) then
if Cast ( S.KillShot , nil , nil , not Target : IsSpellInRange ( S.KillShot ) ) then return " kill_shot st 6 " ; end
end
-- wildfire_bomb,if=(raid_event.adds.in>cooldown.wildfire_bomb.full_recharge_time-(cooldown.wildfire_bomb.full_recharge_time%3.5)&debuff.shredded_armor.up&(full_recharge_time<2*gcd|talent.bombardier&!cooldown.coordinated_assault.remains|talent.bombardier&buff.coordinated_assault.up&buff.coordinated_assault.remains<2*gcd)|!raid_event.adds.exists&time_to_die<7)&set_bonus.tier30_4pc
if ( Target : DebuffUp ( S.ShreddedArmorDebuff ) and ( S.WildfireBomb : FullRechargeTime ( ) < 2 * Player : GCD ( ) or S.Bombardier : IsAvailable ( ) and S.CoordinatedAssault : CooldownUp ( ) or S.Bombardier : IsAvailable ( ) and Player : BuffUp ( S.CoordinatedAssaultBuff ) and Player : BuffRemains ( S.CoordinatedAssaultBuff ) < 2 * Player : GCD ( ) ) or FightRemains < 7 ) then
for _ , Bomb in pairs ( Bombs ) do
if Bomb : IsCastable ( ) then
if Cast ( Bomb , nil , nil , not Target : IsSpellInRange ( Bomb ) ) then return " wildfire_bomb st 7 " ; end
end
end
end
-- kill_command,target_if=min:bloodseeker.remains,if=full_recharge_time<gcd&focus+cast_regen<focus.max&buff.deadly_duo.stack>1
if S.KillCommand : IsCastable ( ) and ( S.KillCommand : FullRechargeTime ( ) < Player : GCD ( ) and CheckFocusCap ( S.KillCommand : ExecuteTime ( ) , 21 ) and Player : BuffStack ( S.DeadlyDuoBuff ) > 1 ) then
if Everyone.CastTargetIf ( S.KillCommand , EnemyList , " min " , EvaluateTargetIfFilterBloodseekerRemains , nil , not Target : IsSpellInRange ( S.KillCommand ) ) then return " kill_command st 8 " ; end
end
-- kill_command,target_if=min:bloodseeker.remains,if=cooldown.wildfire_bomb.full_recharge_time<2*gcd&debuff.shredded_armor.down&set_bonus.tier30_4pc
if S.KillCommand : IsCastable ( ) and ( S.WildfireBomb : FullRechargeTime ( ) < 2 * Player : GCD ( ) and Player : HasTier ( 30 , 4 ) ) then
if Everyone.CastTargetIf ( S.KillCommand , EnemyList , " min " , EvaluateTargetIfFilterBloodseekerRemains , EvaluateTargetIfKillCommandST , not Target : IsSpellInRange ( S.KillCommand ) ) then return " kill_command st 9 " ; end
end
-- mongoose_bite,if=buff.spearhead.remains
if S.MongooseBite : IsReady ( ) and ( Player : BuffUp ( S.SpearheadBuff ) ) then
if Cast ( S.MongooseBite , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite st 10 " ; end
end
-- mongoose_bite,if=active_enemies=1&target.time_to_die<focus%(variable.mb_rs_cost-cast_regen)*gcd|buff.mongoose_fury.up&buff.mongoose_fury.remains<gcd
if S.MongooseBite : IsReady ( ) and ( EnemyCount8ySplash == 1 and Target : TimeToDie ( ) < Player : Focus ( ) / ( MBRSCost - Player : FocusCastRegen ( S.MongooseBite : ExecuteTime ( ) ) ) * Player : GCD ( ) or Player : BuffUp ( S.MongooseFuryBuff ) and Player : BuffRemains ( S.MongooseFuryBuff ) < Player : GCD ( ) ) then
if Cast ( S.MongooseBite , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite st 12 " ; end
end
-- kill_shot,if=!buff.coordinated_assault.up
if S.KillShot : IsReady ( ) and ( Player : BuffDown ( S.CoordinatedAssaultBuff ) ) then
if Cast ( S.KillShot , nil , nil , not Target : IsSpellInRange ( S.KillShot ) ) then return " kill_shot st 14 " ; end
end
-- raptor_strike,if=active_enemies=1&target.time_to_die<focus%(variable.mb_rs_cost-cast_regen)*gcd
if S.RaptorStrike : IsReady ( ) and ( EnemyCount8ySplash == 1 and Target : TimeToDie ( ) < Player : Focus ( ) / ( MBRSCost - Player : FocusCastRegen ( S.RaptorStrike : ExecuteTime ( ) ) ) * Player : GCD ( ) ) then
if Cast ( S.RaptorStrike , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " raptor_strike st 16 " ; end
end
-- serpent_sting,target_if=min:remains,if=!dot.serpent_sting.ticking&target.time_to_die>7&!talent.vipers_venom
if S.SerpentSting : IsReady ( ) and ( not S.VipersVenom : IsAvailable ( ) ) then
if Everyone.CastTargetIf ( S.SerpentSting , EnemyList , " min " , EvaluateTargetIfFilterSerpentStingRemains , EvaluateTargetIfSerpentStingST , not Target : IsSpellInRange ( S.SerpentSting ) ) then return " serpent_sting st 18 " ; end
end
-- mongoose_bite,if=talent.alpha_predator&buff.mongoose_fury.up&buff.mongoose_fury.remains<focus%(variable.mb_rs_cost-cast_regen)*gcd
if S.MongooseBite : IsReady ( ) and ( S.AlphaPredator : IsAvailable ( ) and Player : BuffUp ( S.MongooseFuryBuff ) and Player : BuffRemains ( S.MongooseFuryBuff ) < Player : Focus ( ) / ( MBRSCost - Player : FocusCastRegen ( S.MongooseBite : ExecuteTime ( ) ) ) * Player : GCD ( ) ) then
if Cast ( S.MongooseBite , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite st 20 " ; end
end
-- flanking_strike,if=focus+cast_regen<focus.max
if S.FlankingStrike : IsCastable ( ) and ( CheckFocusCap ( S.FlankingStrike : ExecuteTime ( ) , 30 ) ) then
if Cast ( S.FlankingStrike , nil , nil , not Target : IsSpellInRange ( S.FlankingStrike ) ) then return " flanking_strike st 22 " ; end
end
-- stampede
if S.Stampede : IsCastable ( ) and CDsON ( ) then
if Cast ( S.Stampede , Settings.Commons2 . GCDasOffGCD.Stampede , nil , not Target : IsSpellInRange ( S.Stampede ) ) then return " stampede st 23 " ; end
end
-- coordinated_assault,if=!talent.coordinated_kill&target.health.pct<20&(!buff.spearhead.remains&cooldown.spearhead.remains|!talent.spearhead)|talent.coordinated_kill&(!buff.spearhead.remains&cooldown.spearhead.remains|!talent.spearhead)
if S.CoordinatedAssault : IsCastable ( ) and CDsON ( ) and ( ( not S.CoordinatedKill : IsAvailable ( ) ) and Target : HealthPercentage ( ) < 20 and ( Player : BuffDown ( S.SpearheadBuff ) and S.Spearhead : CooldownDown ( ) or not S.Spearhead : IsAvailable ( ) ) or S.CoordinatedKill : IsAvailable ( ) and ( Player : BuffDown ( S.SpearheadBuff ) and S.Spearhead : CooldownDown ( ) or not S.Spearhead : IsAvailable ( ) ) ) then
if Cast ( S.CoordinatedAssault , Settings.Survival . GCDasOffGCD.CoordinatedAssault , nil , not Target : IsSpellInRange ( S.CoordinatedAssault ) ) then return " coordinated_assault st 24 " ; end
end
-- kill_command,target_if=min:bloodseeker.remains,if=full_recharge_time<gcd&focus+cast_regen<focus.max&(cooldown.flanking_strike.remains|!talent.flanking_strike)|debuff.shredded_armor.down&set_bonus.tier30_4pc
if S.KillCommand : IsCastable ( ) then
if Everyone.CastTargetIf ( S.KillCommand , EnemyList , " min " , EvaluateTargetIfFilterBloodseekerRemains , EvaluateTargetIfKillCommandST2 , not Target : IsSpellInRange ( S.KillCommand ) ) then return " kill_command st 28 " ; end
end
-- mongoose_bite,if=dot.shrapnel_bomb.ticking
if S.MongooseBite : IsReady ( ) and ( Target : DebuffUp ( S.ShrapnelBombDebuff ) ) then
if Cast ( S.MongooseBite , nil , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite st 30 " ; end
end
-- serpent_sting,target_if=min:remains,if=refreshable&!talent.vipers_venom
if S.SerpentSting : IsReady ( ) and ( not S.VipersVenom : IsAvailable ( ) ) then
if Everyone.CastTargetIf ( S.SerpentSting , EnemyList , " min " , EvaluateTargetIfFilterSerpentStingRemains , EvaluateTargetIfSerpentStingST2 , not Target : IsSpellInRange ( S.SerpentSting ) ) then return " serpent_sting st 32 " ; end
end
-- wildfire_bomb,if=raid_event.adds.in>cooldown.wildfire_bomb.full_recharge_time-(cooldown.wildfire_bomb.full_recharge_time%3.5)&full_recharge_time<gcd&(!set_bonus.tier29_2pc|active_enemies>1)
if ( S.WildfireBomb : FullRechargeTime ( ) < Player : GCD ( ) and ( ( not Player : HasTier ( 29 , 2 ) ) or EnemyCount8ySplash > 1 ) ) then
for _ , Bomb in pairs ( Bombs ) do
if Bomb : IsCastable ( ) then
if Cast ( Bomb , nil , nil , not Target : IsSpellInRange ( Bomb ) ) then return " wildfire_bomb st 34 " ; end
end
end
end
-- mongoose_bite,target_if=max:debuff.latent_poison.stack,if=buff.mongoose_fury.up
if S.MongooseBite : IsReady ( ) and ( Player : BuffUp ( S.MongooseFuryBuff ) ) then
if Everyone.CastTargetIf ( S.MongooseBite , EnemyList , " max " , EvaluateTargetIfFilterLatentStacks , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite st 36 " ; end
end
-- explosive_shot,if=talent.ranger
if S.ExplosiveShot : IsReady ( ) and ( S.Ranger : IsAvailable ( ) ) then
if Cast ( S.ExplosiveShot , Settings.Commons2 . GCDasOffGCD.ExplosiveShot , nil , not Target : IsSpellInRange ( S.ExplosiveShot ) ) then return " explosive_shot st 37 " ; end
end
-- wildfire_bomb,if=raid_event.adds.in>cooldown.wildfire_bomb.full_recharge_time-(cooldown.wildfire_bomb.full_recharge_time%3.5)&(full_recharge_time<gcd|!dot.wildfire_bomb.ticking&set_bonus.tier30_4pc)
for BombNum , Bomb in pairs ( Bombs ) do
if Bomb : IsCastable ( ) then
if ( S.WildfireBomb : FullRechargeTime ( ) < Player : GCD ( ) or Target : DebuffDown ( BombDebuffs [ BombNum ] ) and Player : HasTier ( 30 , 4 ) ) then
if Cast ( Bomb , nil , nil , not Target : IsSpellInRange ( Bomb ) ) then return " wildfire_bomb st 38 " ; end
end
end
end
-- mongoose_bite,target_if=max:debuff.latent_poison.stack,if=focus+action.kill_command.cast_regen>focus.max-10|set_bonus.tier30_4pc
if S.MongooseBite : IsReady ( ) and ( Player : Focus ( ) + Player : FocusCastRegen ( S.KillCommand : ExecuteTime ( ) ) + 21 > Player : FocusMax ( ) - 10 or Player : HasTier ( 30 , 4 ) ) then
if Everyone.CastTargetIf ( S.MongooseBite , EnemyList , " max " , EvaluateTargetIfFilterLatentStacks , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " mongoose_bite st 40 " ; end
end
-- raptor_strike,target_if=max:debuff.latent_poison.stack
if S.RaptorStrike : IsReady ( ) then
if Everyone.CastTargetIf ( S.RaptorStrike , EnemyList , " max " , EvaluateTargetIfFilterLatentStacks , nil , not Target : IsInMeleeRange ( MeleeRange ) ) then return " raptor_strike st 46 " ; end
end
-- steel_trap
if S.SteelTrap : IsCastable ( ) then
if Cast ( S.SteelTrap , Settings.Commons2 . GCDasOffGCD.SteelTrap , nil , not Target : IsInRange ( 40 ) ) then return " steel_trap st 48 " ; end
end
-- wildfire_bomb,if=raid_event.adds.in>cooldown.wildfire_bomb.full_recharge_time-(cooldown.wildfire_bomb.full_recharge_time%3.5)&!dot.wildfire_bomb.ticking
for BombNum , Bomb in pairs ( Bombs ) do
if Bomb : IsCastable ( ) and ( Target : DebuffDown ( BombDebuffs [ BombNum ] ) ) then
if Cast ( Bomb , nil , nil , not Target : IsSpellInRange ( Bomb ) ) then return " wildfire_bomb st 50 " ; end
end
end
-- kill_command,target_if=min:bloodseeker.remains,if=focus+cast_regen<focus.max
if S.KillCommand : IsCastable ( ) and ( CheckFocusCap ( S.KillCommand : ExecuteTime ( ) , 21 ) ) then
if Everyone.CastTargetIf ( S.KillCommand , EnemyList , " min " , EvaluateTargetIfFilterBloodseekerRemains , nil , not Target : IsSpellInRange ( S.KillCommand ) ) then return " kill_command st 52 " ; end
end
-- coordinated_assault,if=!talent.coordinated_kill&time_to_die>140
if S.CoordinatedAssault : IsCastable ( ) and ( ( not S.CoordinatedKill : IsAvailable ( ) ) and Target : TimeToDie ( ) > 140 ) then
if Cast ( S.CoordinatedAssault , Settings.Survival . GCDasOffGCD.CoordinatedAssault , nil , not Target : IsSpellInRange ( S.CoordinatedAssault ) ) then return " coordinated_assault st 54 " ; end
end
-- fury_of_the_eagle,interrupt=1
if S.FuryoftheEagle : IsCastable ( ) then
if Cast ( S.FuryoftheEagle , nil , Settings.Commons . DisplayStyle.Signature , not Target : IsInMeleeRange ( MeleeRange ) ) then return " fury_of_the_eagle st 56 " ; end
end
end
local function APL ( )
-- Target Count Checking
local EagleUp = Player : BuffUp ( S.AspectoftheEagle )
local AddedRange = S.Lunge : IsAvailable ( ) and 3 or 0
MeleeRange = EagleUp and ( 40 + AddedRange ) or ( 5 + AddedRange )
if AoEON ( ) then
if EagleUp and not Target : IsInMeleeRange ( 8 ) then
EnemyCount8ySplash = Target : GetEnemiesInSplashRangeCount ( 8 )
else
EnemyCount8ySplash = # Player : GetEnemiesInRange ( 8 )
end
else
EnemyCount8ySplash = 1
end
if EagleUp then
EnemyList = Player : GetEnemiesInRange ( 40 )
else
EnemyList = Player : GetEnemiesInRange ( 8 )
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 ( EnemyList , false )
end
end
-- Pet Management; Conditions handled via override
if not ( Player : IsMounted ( ) or Player : IsInVehicle ( ) ) then
if S.SummonPet : IsCastable ( ) then
if Cast ( SummonPetSpells [ Settings.Commons2 . SummonPetSlot ] ) then return " Summon Pet " ; end
end
if S.RevivePet : IsCastable ( ) then
if Cast ( S.RevivePet , Settings.Commons2 . GCDasOffGCD.RevivePet ) then return " Revive Pet " ; end
end
if S.MendPet : IsCastable ( ) then
if Cast ( S.MendPet , Settings.Commons2 . GCDasOffGCD.MendPet ) then return " Mend Pet " ; end
end
end
if Everyone.TargetIsValid ( ) then
-- Out of Combat
if not Player : AffectingCombat ( ) then
local ShouldReturn = Precombat ( ) ; if ShouldReturn then return ShouldReturn ; end
end
-- Exhilaration
if S.Exhilaration : IsCastable ( ) and Player : HealthPercentage ( ) <= Settings.Commons2 . ExhilarationHP then
if Cast ( S.Exhilaration , Settings.Commons2 . GCDasOffGCD.Exhilaration ) then return " Exhilaration " ; end
end
-- muzzle
local ShouldReturn = Everyone.Interrupt ( 5 , S.Muzzle , Settings.Survival . OffGCDasOffGCD.Muzzle , StunInterrupts ) ; if ShouldReturn then return ShouldReturn ; end
-- auto_attack
-- Manually added: If out of range, use Aspect of the Eagle, otherwise Harpoon to get back into range
if not EagleUp and not Target : IsInMeleeRange ( 8 ) then
if S.AspectoftheEagle : IsCastable ( ) then
if Cast ( S.AspectoftheEagle , Settings.Survival . OffGCDasOffGCD.AspectOfTheEagle ) then return " aspect_of_the_eagle oor " ; end
end
if S.Harpoon : IsCastable ( ) then
if Cast ( S.Harpoon , Settings.Survival . GCDasOffGCD.Harpoon , nil , not Target : IsSpellInRange ( S.Harpoon ) ) then return " harpoon oor " ; end
end
end
-- call_action_list,name=cds
if ( CDsON ( ) ) then
local ShouldReturn = CDs ( ) ; if ShouldReturn then return ShouldReturn ; end
end
-- call_action_list,name=st,if=active_enemies<3
if ( EnemyCount8ySplash < 3 ) then
local ShouldReturn = ST ( ) ; if ShouldReturn then return ShouldReturn ; end
end
-- call_action_list,name=cleave,if=active_enemies>2
if ( EnemyCount8ySplash > 2 ) then
local ShouldReturn = Cleave ( ) ; if ShouldReturn then return ShouldReturn ; end
end
-- arcane_torrent
if S.ArcaneTorrent : IsCastable ( ) and CDsON ( ) then
if Cast ( S.ArcaneTorrent , Settings.Commons . OffGCDasOffGCD.Racials , nil , not Target : IsInRange ( 8 ) ) then return " arcane_torrent main 888 " ; end
end
-- PoolFocus if nothing else to do
if HR.CastAnnotated ( S.PoolFocus , false , " WAIT " ) then return " Pooling Focus " ; end
end
end
local function OnInit ( )
HR.Print ( " Survival Hunter rotation is currently a work in progress, but has been updated for patch 10.0. " )
end
HR.SetAPL ( 255 , APL , OnInit )