forked from Bastion/Bastion
parent
53679d748f
commit
ac9d9740be
@ -1,13 +1,18 @@ |
||||
All credit to 4n0n for creating the Bastion framework! |
||||
|
||||
Bastion aims to be a highly performant and complete World of Warcraft data visualization layer, as such developers may |
||||
leverage it to create combat rotations, gathering bots, quest bots, and much more! |
||||
|
||||
Pull requests are welcome and encouraged, however I do ask that scripts such as rotations live in their own repository, |
||||
for the moment the included restoration druid rotation is the exception as it serves as a learning resource for developers |
||||
to reference in creating their own scripts. |
||||
|
||||
Feel free to browse around the [Wiki](https://git.tinkr.site/4n0n/bastion/wiki) or just start by reading the code! |
||||
|
||||
## Quick Start |
||||
- [Download](https://git.tinkr.site/4n0n/bastion/archive/main.zip) or clone the repository. |
||||
- [Download](https://git.tinkr.site/RexUK/bastion/archive/main.zip) or clone the repository. |
||||
- Move the bastion folder to your `Tinkr/scripts` folder. |
||||
- Once in-game type `/bastion toggle` to enable the engine. |
||||
- Once in-game type `/bastion interface` to open the main menu. |
||||
|
||||
## Latest changes |
||||
Added Unit:IsIndoors() to Unit.lua |
||||
Changed _bastion.lua to not automatically load all modules |
||||
Added class/spec checks to _bastion.lua to only load the class/spec you're in game with |
||||
Implemented GUI though Gui.lua based on Kaminaris StdUI - https://github.com/kaminaris/StdUi |
||||
|
||||
|
@ -1,954 +0,0 @@ |
||||
local Tinkr, Bastion = ... |
||||
|
||||
local OutlawModule = Bastion.Module:New('outlaw') |
||||
local Evaluator = Tinkr.Util.Evaluator |
||||
local Player = Bastion.UnitManager:Get('player') |
||||
local None = Bastion.UnitManager:Get('none') |
||||
local Target = Bastion.UnitManager:Get('target') |
||||
|
||||
local Stealth = Bastion.SpellBook:GetSpell(115191) |
||||
local Kick = Bastion.SpellBook:GetSpell(1766) |
||||
local CountTheOdds = Bastion.SpellBook:GetSpell(381982) |
||||
local Shadowmeld = Bastion.SpellBook:GetSpell(58984) |
||||
local ShadowDance = Bastion.SpellBook:GetSpell(185313) |
||||
local ShadowDanceAura = Bastion.SpellBook:GetSpell(185422) |
||||
local HiddenOpportunity = Bastion.SpellBook:GetSpell(383281) |
||||
local RollTheBones = Bastion.SpellBook:GetSpell(315508) |
||||
local FanTheHammer = Bastion.SpellBook:GetSpell(381846) |
||||
local ImprovedAmbush = Bastion.SpellBook:GetSpell(381620) |
||||
local SummarilyDispatched = Bastion.SpellBook:GetSpell(381990) |
||||
local BladeFlurry = Bastion.SpellBook:GetSpell(13877) |
||||
local KillingSpree = Bastion.SpellBook:GetSpell(51690) |
||||
local ArcaneTorrent = Bastion.SpellBook:GetSpell(25046) |
||||
local ArcanePulse = Bastion.SpellBook:GetSpell(260364) |
||||
local LightsJudgment = Bastion.SpellBook:GetSpell(255647) |
||||
local BagOfTricks = Bastion.SpellBook:GetSpell(312411) |
||||
local Sepsis = Bastion.SpellBook:GetSpell(385408) |
||||
local BetweenTheEyes = Bastion.SpellBook:GetSpell(315341) |
||||
local GhostlyStrike = Bastion.SpellBook:GetSpell(196937) |
||||
local Dreadblades = Bastion.SpellBook:GetSpell(343142) |
||||
local Subterfuge = Bastion.SpellBook:GetSpell(108208) |
||||
local EchoingReprimand = Bastion.SpellBook:GetSpell(385616) |
||||
local Ambush = Bastion.SpellBook:GetSpell(8676) |
||||
local KeepItRolling = Bastion.SpellBook:GetSpell(381989) |
||||
local Audacity = Bastion.SpellBook:GetSpell(381845) |
||||
local FindWeakness = Bastion.SpellBook:GetSpell(91023) |
||||
local PistolShot = Bastion.SpellBook:GetSpell(185763) |
||||
local Opportunity = Bastion.SpellBook:GetSpell(279876) |
||||
local OpportunityAura = Bastion.SpellBook:GetSpell(195627) |
||||
local GreenskinsWickers = Bastion.SpellBook:GetSpell(386823) |
||||
local QuickDraw = Bastion.SpellBook:GetSpell(196938) |
||||
local Weaponmaster = Bastion.SpellBook:GetSpell(200733) |
||||
local SinisterStrike = Bastion.SpellBook:GetSpell(193315) |
||||
local AdrenalineRush = Bastion.SpellBook:GetSpell(13750) |
||||
local ImprovedAdrenalineRush = Bastion.SpellBook:GetSpell(395422) |
||||
local BladeRush = Bastion.SpellBook:GetSpell(271877) |
||||
local MarkedForDeath = Bastion.SpellBook:GetSpell(137619) |
||||
local ThistleTea = Bastion.SpellBook:GetSpell(381623) |
||||
local PotionOfUnbridledFury = Bastion.SpellBook:GetSpell(169299) |
||||
local Bloodlust = Bastion.SpellBook:GetSpell(2825) |
||||
local BloodFury = Bastion.SpellBook:GetSpell(20572) |
||||
local Berserking = Bastion.SpellBook:GetSpell(26297) |
||||
local Fireblood = Bastion.SpellBook:GetSpell(265221) |
||||
local AncestralCall = Bastion.SpellBook:GetSpell(274738) |
||||
local SliceAndDice = Bastion.SpellBook:GetSpell(315496) |
||||
local SwiftSlasher = Bastion.SpellBook:GetSpell(381988) |
||||
local ColdBlood = Bastion.SpellBook:GetSpell(382245) |
||||
local Dispatch = Bastion.SpellBook:GetSpell(2098) |
||||
local Vanish = Bastion.SpellBook:GetSpell(1856) |
||||
|
||||
local Broadside = Bastion.SpellBook:GetSpell(193356) |
||||
local GrandMelee = Bastion.SpellBook:GetSpell(193358) |
||||
local SkullAndCrossbones = Bastion.SpellBook:GetSpell(199603) |
||||
local TrueBearing = Bastion.SpellBook:GetSpell(193359) |
||||
local LoadedDice = Bastion.SpellBook:GetSpell(256171) |
||||
local BuriedTreasure = Bastion.SpellBook:GetSpell(199600) |
||||
local RuthlessPrecision = Bastion.SpellBook:GetSpell(193357) |
||||
|
||||
local PurgeTarget = Bastion.UnitManager:CreateCustomUnit('purge', function(unit) |
||||
local purge = nil |
||||
|
||||
Bastion.UnitManager:EnumEnemies(function(unit) |
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if unit:GetAuras():HasAnyStealableAura() then |
||||
purge = unit |
||||
return true |
||||
end |
||||
end) |
||||
|
||||
if purge == nil then |
||||
purge = None |
||||
end |
||||
|
||||
return purge |
||||
end) |
||||
|
||||
local KickTarget = Bastion.UnitManager:CreateCustomUnit('kick', function(unit) |
||||
local purge = nil |
||||
|
||||
Bastion.UnitManager:EnumEnemies(function(unit) |
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if Player:InMelee(unit) and unit:IsInterruptible(5) and Player:IsFacing(unit) then |
||||
purge = unit |
||||
return true |
||||
end |
||||
end) |
||||
|
||||
if purge == nil then |
||||
purge = None |
||||
end |
||||
|
||||
return purge |
||||
end) |
||||
|
||||
local Tank = Bastion.UnitManager:CreateCustomUnit('tank', function(unit) |
||||
local tank = nil |
||||
|
||||
Bastion.UnitManager:EnumFriends(function(unit) |
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if unit:IsTank() then |
||||
tank = unit |
||||
return true |
||||
end |
||||
|
||||
return false |
||||
end) |
||||
|
||||
if tank == nil then |
||||
tank = None |
||||
end |
||||
|
||||
return tank |
||||
end) |
||||
|
||||
local Explosive = Bastion.UnitManager:CreateCustomUnit('explosive', function(unit) |
||||
local explosive = nil |
||||
|
||||
Bastion.UnitManager:EnumEnemies(function(unit) |
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if Player:InMelee(unit) and unit:GetID() == 120651 and Player:IsFacing(unit) then |
||||
|
||||
explosive = unit |
||||
return true |
||||
end |
||||
end) |
||||
|
||||
if explosive == nil then |
||||
explosive = None |
||||
end |
||||
|
||||
return explosive |
||||
end) |
||||
|
||||
local DefaultAPL = Bastion.APL:New('default') |
||||
local StealthAPL = Bastion.APL:New('stealth') |
||||
local CDsAPL = Bastion.APL:New('cds') |
||||
local FinishAPL = Bastion.APL:New('finish') |
||||
local BuildAPL = Bastion.APL:New('build') |
||||
local StealthCDsAPL = Bastion.APL:New('stealthcds') |
||||
|
||||
-- # Executed every time the actor is available. |
||||
-- # Restealth if possible (no vulnerable enemies in combat) |
||||
-- actions=stealth |
||||
|
||||
DefaultAPL:AddSpell( |
||||
Stealth:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(Stealth):IsUp() and |
||||
not Player:IsAffectingCombat() and not IsMounted() |
||||
end |
||||
):SetTarget(Player) |
||||
) |
||||
|
||||
-- # Interrupt on cooldown to allow simming interactions with that |
||||
-- actions+=/kick |
||||
DefaultAPL:AddSpell( |
||||
Kick:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and KickTarget:Exists() and self:IsInRange(KickTarget) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and Player:IsFacing(Target) |
||||
end):SetTarget(KickTarget) |
||||
) |
||||
-- # Checks if we are in an appropriate Stealth state for triggering the Count the Odds bonus |
||||
-- actions+=/variable,name=stealthed_cto,value=talent.count_the_odds&(stealthed.basic|buff.shadowmeld.up|buff.shadow_dance.up) |
||||
DefaultAPL:AddVariable( |
||||
'stealthed_cto', |
||||
function() |
||||
return CountTheOdds:IsKnown() and (Player:GetAuras():FindMy(Stealth):IsUp() or |
||||
Player:GetAuras():FindMy(Shadowmeld):IsUp() or |
||||
Player:GetAuras():FindMy(ShadowDanceAura):IsUp()) |
||||
end |
||||
) |
||||
|
||||
local function GetRTBCount() |
||||
local count = 0 |
||||
|
||||
if Player:GetAuras():FindMy(Broadside):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
if Player:GetAuras():FindMy(GrandMelee):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
if Player:GetAuras():FindMy(SkullAndCrossbones):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
if Player:GetAuras():FindMy(TrueBearing):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
if Player:GetAuras():FindMy(LoadedDice):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
if Player:GetAuras():FindMy(BuriedTreasure):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
if Player:GetAuras():FindMy(RuthlessPrecision):IsUp() then |
||||
count = count + 1 |
||||
end |
||||
|
||||
return count |
||||
end |
||||
|
||||
-- # Roll the Bones Reroll Conditions |
||||
-- actions+=/variable,name=rtb_reroll,if=!talent.hidden_opportunity,value=rtb_buffs<2&(!buff.broadside.up&(!talent.fan_the_hammer|!buff.skull_and_crossbones.up)&!buff.true_bearing.up|buff.loaded_dice.up)|rtb_buffs=2&(buff.buried_treasure.up&buff.grand_melee.up|!buff.broadside.up&!buff.true_bearing.up&buff.loaded_dice.up) |
||||
DefaultAPL:AddVariable( |
||||
'rtb_reroll', |
||||
function() |
||||
if not HiddenOpportunity:IsKnown() then |
||||
return GetRTBCount() < 2 and |
||||
(not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
(not FanTheHammer:IsKnown() or |
||||
not Player:GetAuras():FindMy(SkullAndCrossbones):IsUp()) and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp() or |
||||
Player:GetAuras():FindMy(LoadedDice):IsUp()) or |
||||
GetRTBCount() == 2 and |
||||
(Player:GetAuras():FindMy(BuriedTreasure):IsUp() and |
||||
Player:GetAuras():FindMy(GrandMelee):IsUp() or |
||||
not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp() and |
||||
Player:GetAuras():FindMy(LoadedDice):IsUp()) |
||||
end |
||||
end |
||||
) |
||||
|
||||
-- # Additional Reroll Conditions for Keep it Rolling or Count the Odds |
||||
-- actions+=/variable,name=rtb_reroll,if=!talent.hidden_opportunity&(talent.keep_it_rolling|talent.count_the_odds),value=variable.rtb_reroll|((rtb_buffs.normal=0&rtb_buffs.longer>=1)&!(buff.broadside.up&buff.true_bearing.up&buff.skull_and_crossbones.up)&!(buff.broadside.remains>39|buff.true_bearing.remains>39|buff.ruthless_precision.remains>39|buff.skull_and_crossbones.remains>39)) |
||||
DefaultAPL:AddVariable( |
||||
'rtb_reroll', |
||||
function() |
||||
if not HiddenOpportunity:IsKnown() then |
||||
return GetRTBCount() < 2 and |
||||
(not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
(not FanTheHammer:IsKnown() or |
||||
not Player:GetAuras():FindMy(SkullAndCrossbones):IsUp()) and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp() or |
||||
Player:GetAuras():FindMy(LoadedDice):IsUp()) or |
||||
GetRTBCount() == 2 and |
||||
(Player:GetAuras():FindMy(BuriedTreasure):IsUp() and |
||||
Player:GetAuras():FindMy(GrandMelee):IsUp() or |
||||
not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp() and |
||||
Player:GetAuras():FindMy(LoadedDice):IsUp()) |
||||
end |
||||
end |
||||
) |
||||
|
||||
-- # With Hidden Opportunity, prioritize rerolling for Skull and Crossbones over everything else |
||||
-- actions+=/variable,name=rtb_reroll,if=talent.hidden_opportunity,value=!rtb_buffs.will_lose.skull_and_crossbones&(rtb_buffs.will_lose-rtb_buffs.will_lose.grand_melee)<2+buff.loaded_dice.up |
||||
DefaultAPL:AddVariable( |
||||
'rtb_reroll', |
||||
function() |
||||
if HiddenOpportunity:IsKnown() then |
||||
return not Player:GetAuras():FindMy(SkullAndCrossbones):IsUp() and |
||||
((Player:GetAuras():FindMy(SkullAndCrossbones):IsUp() and 1 or 0) - |
||||
(Player:GetAuras():FindMy(GrandMelee):IsUp() and 1 or 0)) < |
||||
2 + (Player:GetAuras():FindMy(LoadedDice):IsUp() and 1 or 0) |
||||
end |
||||
end |
||||
) |
||||
|
||||
-- # Avoid rerolls when we will not have time remaining on the fight or add wave to recoup the opportunity cost of the global |
||||
-- actions+=/variable,name=rtb_reroll,op=reset,if=!(raid_event.adds.remains>12|raid_event.adds.up&(raid_event.adds.in-raid_event.adds.remains)<6|target.time_to_die>12)|fight_remains<12 |
||||
DefaultAPL:AddVariable( |
||||
'rtb_reroll', |
||||
function() |
||||
if not HiddenOpportunity:IsKnown() then |
||||
return GetRTBCount() < 2 and |
||||
(not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
(not FanTheHammer:IsKnown() or |
||||
not Player:GetAuras():FindMy(SkullAndCrossbones):IsUp()) and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp() or |
||||
Player:GetAuras():FindMy(LoadedDice):IsUp()) or |
||||
GetRTBCount() == 2 and |
||||
(Player:GetAuras():FindMy(BuriedTreasure):IsUp() and |
||||
Player:GetAuras():FindMy(GrandMelee):IsUp() or |
||||
not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp() and |
||||
Player:GetAuras():FindMy(LoadedDice):IsUp()) |
||||
end |
||||
end |
||||
) |
||||
|
||||
-- # Ensure we get full Ambush CP gains and aren't rerolling Count the Odds buffs away |
||||
-- actions+=/variable,name=ambush_condition,value=combo_points.deficit>=2+talent.improved_ambush+buff.broadside.up&energy>=50&(!talent.count_the_odds|buff.roll_the_bones.remains>=10) |
||||
DefaultAPL:AddVariable( |
||||
'ambush_condition', |
||||
function() |
||||
return Player:GetComboPointsDeficit() >= 2 + (ImprovedAmbush:IsKnown() and 1 or 0) + |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() and 1 or 0) and |
||||
Player:GetPower() >= 50 and |
||||
(not CountTheOdds:IsKnown() or |
||||
Player:GetAuras():FindMy(RollTheBones):GetRemainingTime() >= 10) |
||||
end |
||||
) |
||||
|
||||
-- # Finish at 6 (5 with Summarily Dispatched talented) CP or CP Max-1, whichever is greater of the two |
||||
-- actions+=/variable,name=finish_condition,value=combo_points>=((cp_max_spend-1)<?(6-talent.summarily_dispatched))|effective_combo_points>=cp_max_spend |
||||
DefaultAPL:AddVariable( |
||||
'finish_condition', |
||||
function() |
||||
return Player:GetComboPoints() >= |
||||
math.min(Player:GetComboPointsMax() - 1, 6 - (SummarilyDispatched:IsKnown() and 1 or 0)) or |
||||
Player:GetComboPoints() >= Player:GetComboPointsMax() |
||||
end |
||||
) |
||||
|
||||
-- # With multiple targets, this variable is checked to decide whether some CDs should be synced with Blade Flurry |
||||
-- actions+=/variable,name=blade_flurry_sync,value=spell_targets.blade_flurry<2&raid_event.adds.in>20|buff.blade_flurry.remains>1+talent.killing_spree.enabled |
||||
DefaultAPL:AddVariable( |
||||
'blade_flurry_sync', |
||||
function() |
||||
return Player:GetMeleeAttackers() < 2 and |
||||
(not Player:GetAuras():FindMy(BladeFlurry):IsUp() or |
||||
Player:GetAuras():FindMy(BladeFlurry):GetRemainingTime() > 1 + |
||||
(KillingSpree:IsKnown() and 1 or 0)) |
||||
end |
||||
) |
||||
|
||||
-- # Higher priority Stealth list for Count the Odds or true Stealth/Vanish that will break in a single global |
||||
-- actions+=/call_action_list,name=stealth,if=stealthed.basic|buff.shadowmeld.up |
||||
DefaultAPL:AddAPL( |
||||
StealthAPL, |
||||
function() |
||||
return Player:IsStealthed() or Player:GetAuras():FindMy(Shadowmeld):IsUp() |
||||
end |
||||
) |
||||
|
||||
-- actions+=/call_action_list,name=cds |
||||
DefaultAPL:AddAPL( |
||||
CDsAPL, |
||||
function() |
||||
return true |
||||
end |
||||
) |
||||
|
||||
-- # Lower priority Stealth list for Shadow Dance |
||||
-- actions+=/call_action_list,name=stealth,if=variable.stealthed_cto |
||||
DefaultAPL:AddAPL( |
||||
StealthAPL, |
||||
function() |
||||
return DefaultAPL:GetVariable('stealthed_cto') |
||||
end |
||||
) |
||||
|
||||
-- actions+=/run_action_list,name=finish,if=variable.finish_condition |
||||
DefaultAPL:AddAPL( |
||||
FinishAPL, |
||||
function() |
||||
return DefaultAPL:GetVariable('finish_condition') |
||||
end |
||||
) |
||||
|
||||
-- actions+=/call_action_list,name=build |
||||
DefaultAPL:AddAPL( |
||||
BuildAPL, |
||||
function() |
||||
return true |
||||
end |
||||
) |
||||
|
||||
-- actions+=/arcane_torrent,if=energy.base_deficit>=15+energy.regen |
||||
DefaultAPL:AddSpell( |
||||
ArcaneTorrent:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Player:GetPowerDeficit() >= 15 + Player:GetPowerRegen() |
||||
end |
||||
):SetTarget(Target) |
||||
|
||||
) |
||||
|
||||
-- actions+=/arcane_pulse |
||||
DefaultAPL:AddSpell( |
||||
ArcanePulse:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions+=/lights_judgment |
||||
DefaultAPL:AddSpell( |
||||
LightsJudgment:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions+=/bag_of_tricks |
||||
DefaultAPL:AddSpell( |
||||
BagOfTricks:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Builders |
||||
-- actions.build=sepsis,target_if=max:target.time_to_die*debuff.between_the_eyes.up,if=target.time_to_die>11&debuff.between_the_eyes.up|fight_remains<11 |
||||
BuildAPL:AddSpell( |
||||
Sepsis:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and ((Target:TimeToDie() > 11 and |
||||
Target:GetAuras():FindMy(BetweenTheEyes):IsUp()) or |
||||
Player:TimeToDie() < 11) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.build+=/ghostly_strike,if=debuff.ghostly_strike.remains<=3&(spell_targets.blade_flurry<=2|buff.dreadblades.up)&!buff.subterfuge.up&target.time_to_die>=5 |
||||
BuildAPL:AddSpell( |
||||
GhostlyStrike:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Target:GetAuras():FindMy(GhostlyStrike):GetRemainingTime() <= 3 and |
||||
(Player:GetMeleeAttackers() <= 2 or Player:GetAuras():FindMy(Dreadblades):IsUp()) and |
||||
not Player:GetAuras():FindMy(Subterfuge):IsUp() and Target:TimeToDie() >= 5 |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.build+=/echoing_reprimand,if=!buff.dreadblades.up |
||||
BuildAPL:AddSpell( |
||||
EchoingReprimand:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(Dreadblades):IsUp() |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # High priority Ambush line to apply Find Weakness or consume Audacity/Sepsis buff before Pistol Shot |
||||
-- actions.build+=/ambush,if=(talent.hidden_opportunity|talent.keep_it_rolling)&(buff.audacity.up|buff.sepsis_buff.up|buff.subterfuge.up&cooldown.keep_it_rolling.ready)|talent.find_weakness&debuff.find_weakness.down |
||||
BuildAPL:AddSpell( |
||||
Ambush:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and ((HiddenOpportunity:IsKnown() or KeepItRolling:IsKnown()) and |
||||
(Player:GetAuras():FindMy(Audacity):IsUp() or Player:GetAuras():FindMy(Sepsis):IsUp() or |
||||
(Player:GetAuras():FindMy(Subterfuge):IsUp() and KeepItRolling:OnCooldown())) or |
||||
(FindWeakness:IsKnown() and Target:GetAuras():FindMy(FindWeakness):IsDown())) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # With Audacity + Hidden Opportunity + Fan the Hammer, use Pistol Shot to proc Audacity any time Ambush is not available |
||||
-- actions.build+=/pistol_shot,if=talent.fan_the_hammer&talent.audacity&talent.hidden_opportunity&buff.opportunity.up&!buff.audacity.up&!buff.subterfuge.up&!buff.shadow_dance.up |
||||
BuildAPL:AddSpell( |
||||
PistolShot:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and FanTheHammer:IsKnown() and Audacity:IsKnown() and |
||||
HiddenOpportunity:IsKnown() and |
||||
Player:GetAuras():FindMy(OpportunityAura):IsUp() and not Player:GetAuras():FindMy(Audacity):IsUp() and |
||||
not Player:GetAuras():FindMy(Subterfuge):IsUp() and not Player:GetAuras():FindMy(ShadowDance):IsUp() |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Use Greenskins Wickers buff immediately with Opportunity unless running Fan the Hammer |
||||
-- actions.build+=/pistol_shot,if=buff.greenskins_wickers.up&(!talent.fan_the_hammer&buff.opportunity.up|buff.greenskins_wickers.remains<1.5) |
||||
BuildAPL:AddSpell( |
||||
PistolShot:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Player:GetAuras():FindMy(GreenskinsWickers):IsUp() and |
||||
(not FanTheHammer:IsKnown() and Player:GetAuras():FindMy(OpportunityAura):IsUp() or |
||||
Player:GetAuras():FindMy(GreenskinsWickers):GetRemainingTime() < 1.5) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- const int stacks = 1 + as<int>( p()->talent.outlaw.fan_the_hammer->effectN( 1 ).base_value() ); |
||||
local function MaxOpportunity() |
||||
return 1 + (FanTheHammer:IsKnown() and 1 or 0) |
||||
end |
||||
|
||||
-- # With Fan the Hammer, consume Opportunity at max stacks or if we will get max 4+ CP and Dreadblades is not up |
||||
-- actions.build+=/pistol_shot,if=talent.fan_the_hammer&buff.opportunity.up&(buff.opportunity.stack>=buff.opportunity.max_stack|buff.opportunity.remains<2) |
||||
BuildAPL:AddSpell( |
||||
PistolShot:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and FanTheHammer:IsKnown() and |
||||
Player:GetAuras():FindMy(OpportunityAura):IsUp() and |
||||
( |
||||
Player:GetAuras():FindMy(OpportunityAura):GetCount() >= |
||||
MaxOpportunity() |
||||
or |
||||
Player:GetAuras():FindMy(OpportunityAura):GetRemainingTime() < 2) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.build+=/pistol_shot,if=talent.fan_the_hammer&buff.opportunity.up&combo_points.deficit>((1+talent.quick_draw)*talent.fan_the_hammer.rank)&!buff.dreadblades.up&(!talent.hidden_opportunity|!buff.subterfuge.up&!buff.shadow_dance.up) |
||||
BuildAPL:AddSpell( |
||||
PistolShot:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and FanTheHammer:IsKnown() and |
||||
Player:GetAuras():FindMy(OpportunityAura):IsUp() and |
||||
Player:GetComboPointsDeficit() > ((1 + (QuickDraw:IsKnown() and 1 or 0)) * 1) and |
||||
not Player:GetAuras():FindMy(Dreadblades):IsUp() and |
||||
(not HiddenOpportunity:IsKnown() or not Player:GetAuras():FindMy(Subterfuge):IsUp() and |
||||
not Player:GetAuras():FindMy(ShadowDance):IsUp()) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.build+=/pool_resource,for_next=1 |
||||
-- actions.build+=/ambush,if=talent.hidden_opportunity|talent.find_weakness&debuff.find_weakness.down |
||||
BuildAPL:AddSpell( |
||||
Ambush:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and (HiddenOpportunity:IsKnown() or |
||||
(FindWeakness:IsKnown() and Target:GetAuras():FindMy(FindWeakness):IsDown())) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Use Pistol Shot with Opportunity if Combat Potency won't overcap energy, when it will exactly cap CP, or when using Quick Draw |
||||
-- actions.build+=/pistol_shot,if=!talent.fan_the_hammer&buff.opportunity.up&(energy.base_deficit>energy.regen*1.5|!talent.weaponmaster&combo_points.deficit<=1+buff.broadside.up|talent.quick_draw.enabled|talent.audacity.enabled&!buff.audacity.up) |
||||
BuildAPL:AddSpell( |
||||
PistolShot:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not FanTheHammer:IsKnown() and |
||||
Player:GetAuras():FindMy(OpportunityAura):IsUp() and |
||||
(Player:GetPowerDeficit() > Player:GetPowerRegen() * 1.5 or |
||||
(not Weaponmaster:IsKnown() and |
||||
Player:GetComboPointsDeficit() <= 1 + (Player:GetAuras():FindMy(Broadside):IsUp() and 1 or 0)) or |
||||
QuickDraw:IsKnown() or |
||||
(Audacity:IsKnown() and not Player:GetAuras():FindMy(Audacity):IsUp())) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
|
||||
-- actions.build+=/sinister_strike |
||||
BuildAPL:AddSpell( |
||||
SinisterStrike:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Cooldowns |
||||
-- actions.cds=adrenaline_rush,if=!buff.adrenaline_rush.up&(!talent.improved_adrenaline_rush|combo_points<=2) |
||||
CDsAPL:AddSpell( |
||||
AdrenalineRush:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(AdrenalineRush):IsUp() and |
||||
(not ImprovedAdrenalineRush:IsKnown() or Player:GetComboPoints() <= 2) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/blade_flurry,if=spell_targets>=2&buff.blade_flurry.remains<gcd |
||||
CDsAPL:AddSpell( |
||||
BladeFlurry:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Target:GetMeleeAttackers() >= 2 and |
||||
Player:GetAuras():FindMy(BladeFlurry):GetRemainingTime() < Player:GetGCD() |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/roll_the_bones,if=buff.dreadblades.down&(rtb_buffs.total=0|variable.rtb_reroll) |
||||
CDsAPL:AddSpell( |
||||
RollTheBones:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Player:GetAuras():FindMy(Dreadblades):IsDown() and |
||||
(GetRTBCount() == 0 or |
||||
DefaultAPL:GetVariable("rtb_reroll")) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/keep_it_rolling,if=!variable.rtb_reroll&(buff.broadside.up+buff.true_bearing.up+buff.skull_and_crossbones.up+buff.ruthless_precision.up)>2&(buff.shadow_dance.down|rtb_buffs>=6) |
||||
CDsAPL:AddSpell( |
||||
RollTheBones:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not DefaultAPL:GetVariable("rtb_reroll") and |
||||
((Player:GetAuras():FindMy(Broadside):IsUp() and 1 or 0) + |
||||
(Player:GetAuras():FindMy(TrueBearing):IsUp() and 1 or 0) + |
||||
(Player:GetAuras():FindMy(SkullAndCrossbones):IsUp() and 1 or 0) + |
||||
(Player:GetAuras():FindMy(RuthlessPrecision):IsUp() and 1 or 0)) > 2 and |
||||
(Player:GetAuras():FindMy(ShadowDance):IsDown() or |
||||
GetRTBCount() >= 6) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/blade_rush,if=variable.blade_flurry_sync&!buff.dreadblades.up&(energy.base_time_to_max>4+stealthed.rogue-spell_targets%3) |
||||
CDsAPL:AddSpell( |
||||
BladeRush:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and DefaultAPL:GetVariable("blade_flurry_sync") and |
||||
not Player:GetAuras():FindMy(Dreadblades):IsUp() and |
||||
(Player:GetTimeToPowerPercent() > 4 + (Player:GetAuras():FindMy(Subterfuge):IsUp() and 1 or 0) + |
||||
(Player:GetAuras():FindMy(ShadowDance):IsUp() and 1 or 0) - Target:GetMeleeAttackers() % 3) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/call_action_list,name=stealth_cds,if=!stealthed.all|talent.count_the_odds&!variable.stealthed_cto |
||||
CDsAPL:AddAPL( |
||||
StealthCDsAPL, |
||||
function() |
||||
return not Player:GetAuras():FindMy(Stealth):IsUp() or |
||||
(CountTheOdds:IsKnown() and not DefaultAPL:GetVariable("stealthed_cto")) |
||||
end |
||||
) |
||||
|
||||
-- actions.cds+=/dreadblades,if=!(variable.stealthed_cto|stealthed.basic|talent.hidden_opportunity&stealthed.rogue)&combo_points<=2&(!talent.marked_for_death|!cooldown.marked_for_death.ready)&target.time_to_die>=10 |
||||
CDsAPL:AddSpell( |
||||
Dreadblades:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not (DefaultAPL:GetVariable("stealthed_cto") or Player:GetAuras():FindMy(Stealth):IsUp() or |
||||
(HiddenOpportunity:IsKnown() and Player:GetAuras():FindMy(Subterfuge):IsUp())) and |
||||
Player:GetComboPoints() <= 2 and |
||||
(not MarkedForDeath:IsKnown() or not MarkedForDeath:CooldownUp()) and |
||||
Target:TimeToDie() >= 10 |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # If adds are up, snipe the one with lowest TTD. Use when dying faster than CP deficit or without any CP. |
||||
-- actions.cds+=/marked_for_death,line_cd=1.5,target_if=min:target.time_to_die,if=raid_event.adds.up&(target.time_to_die<combo_points.deficit|combo_points.deficit>=cp_max_spend-1)&!buff.dreadblades.up |
||||
|
||||
-- # If no adds will die within the next 30s, use MfD on boss without any CP. |
||||
-- actions.cds+=/marked_for_death,if=raid_event.adds.in>30-raid_event.adds.duration&combo_points.deficit>=cp_max_spend-1&!buff.dreadblades.up |
||||
|
||||
-- actions.cds+=/thistle_tea,if=!buff.thistle_tea.up&(energy.base_deficit>=100|fight_remains<charges*6) |
||||
CDsAPL:AddSpell( |
||||
ThistleTea:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Player:GetAuras():FindMy(ThistleTea):IsDown() and |
||||
(Player:GetPowerDeficit() >= 100 or Target:TimeToDie() < ThistleTea:Charges() * 6) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/killing_spree,if=variable.blade_flurry_sync&!stealthed.rogue&debuff.between_the_eyes.up&energy.base_time_to_max>4 |
||||
CDsAPL:AddSpell( |
||||
KillingSpree:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and DefaultAPL:GetVariable("blade_flurry_sync") and |
||||
not Player:GetAuras():FindMy(Subterfuge):IsUp() and |
||||
Target:GetAuras():FindMy(BetweenTheEyes):IsUp() and |
||||
Player:GetTimeToPowerPercent() > 4 |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/shadowmeld,if=!stealthed.all&(talent.count_the_odds&variable.finish_condition|!talent.weaponmaster.enabled&variable.ambush_condition) |
||||
CDsAPL:AddSpell( |
||||
Shadowmeld:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(Stealth):IsUp() and |
||||
(CountTheOdds:IsKnown() and DefaultAPL:GetVariable("finish_condition") or |
||||
not Weaponmaster:IsKnown() and DefaultAPL:GetVariable("ambush_condition")) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/potion,if=buff.bloodlust.react|fight_remains<30|buff.adrenaline_rush.up |
||||
-- CDsAPL:AddItem( |
||||
-- PotionOfUnbridledFury:CastableIf( |
||||
-- function(self) |
||||
-- return self:IsKnownAndUsable() and Player:GetAuras():FindMy(Bloodlust):IsUp() or Target:TimeToDie() < 30 or |
||||
-- Player:GetAuras():FindMy(AdrenalineRush):IsUp() |
||||
-- end |
||||
-- ):SetTarget(Target) |
||||
-- ) |
||||
|
||||
-- actions.cds+=/blood_fury |
||||
CDsAPL:AddSpell( |
||||
BloodFury:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/berserking |
||||
CDsAPL:AddSpell( |
||||
Berserking:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/fireblood |
||||
CDsAPL:AddSpell( |
||||
Fireblood:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.cds+=/ancestral_call |
||||
CDsAPL:AddSpell( |
||||
AncestralCall:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Default conditions for usable items. |
||||
-- actions.cds+=/use_item,name=manic_grieftorch,if=!stealthed.all&!buff.adrenaline_rush.up|fight_remains<5 |
||||
-- actions.cds+=/use_item,name=stormeaters_boon,if=spell_targets.blade_flurry>desired_targets|raid_event.adds.in>60|fight_remains<10 |
||||
-- actions.cds+=/use_item,name=windscar_whetstone,if=spell_targets.blade_flurry>desired_targets|raid_event.adds.in>60|fight_remains<7 |
||||
-- actions.cds+=/use_items,slots=trinket1,if=debuff.between_the_eyes.up|trinket.1.has_stat.any_dps|fight_remains<=20 |
||||
-- actions.cds+=/use_items,slots=trinket2,if=debuff.between_the_eyes.up|trinket.2.has_stat.any_dps|fight_remains<=20 |
||||
|
||||
-- # Finishers BtE to keep the Crit debuff up, if RP is up, or for Greenskins, unless the target is about to die. |
||||
-- actions.finish=between_the_eyes,if=target.time_to_die>3&(debuff.between_the_eyes.remains<4|talent.greenskins_wickers&!buff.greenskins_wickers.up|!talent.greenskins_wickers&buff.ruthless_precision.up) |
||||
FinishAPL:AddSpell( |
||||
BetweenTheEyes:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Target:TimeToDie() > 3 and |
||||
(Target:GetAuras():FindMy(BetweenTheEyes):GetRemainingTime() < 4 or |
||||
GreenskinsWickers:IsKnown() and Player:GetAuras():FindMy(GreenskinsWickers):IsDown() or |
||||
not GreenskinsWickers:IsKnown() and Player:GetAuras():FindMy(RuthlessPrecision):IsUp()) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.finish+=/slice_and_dice,if=buff.slice_and_dice.remains<fight_remains&refreshable&(!talent.swift_slasher|combo_points>=cp_max_spend) |
||||
FinishAPL:AddSpell( |
||||
SliceAndDice:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and |
||||
Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < Target:TimeToDie() and |
||||
Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < 6 and |
||||
(not SwiftSlasher:IsKnown() or Player:GetComboPoints() >= Player:GetComboPointsMax()) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.finish+=/cold_blood |
||||
FinishAPL:AddSpell( |
||||
ColdBlood:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.finish+=/dispatch |
||||
FinishAPL:AddSpell( |
||||
Dispatch:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and true |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Stealth |
||||
-- actions.stealth=blade_flurry,if=talent.subterfuge&talent.hidden_opportunity&spell_targets>=2&!buff.blade_flurry.up |
||||
StealthAPL:AddSpell( |
||||
BladeFlurry:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and Subterfuge:IsKnown() and HiddenOpportunity:IsKnown() and |
||||
Target:GetMeleeAttackers() >= 2 and |
||||
not Player:GetAuras():FindMy(BladeFlurry):IsUp() |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth+=/cold_blood,if=variable.finish_condition |
||||
StealthAPL:AddSpell( |
||||
ColdBlood:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and DefaultAPL:GetVariable('finish_condition') |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth+=/dispatch,if=variable.finish_condition |
||||
StealthAPL:AddSpell( |
||||
Dispatch:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and DefaultAPL:GetVariable('finish_condition') |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth+=/ambush,if=variable.stealthed_cto|stealthed.basic&talent.find_weakness&!debuff.find_weakness.up|talent.hidden_opportunity |
||||
StealthAPL:AddSpell( |
||||
Ambush:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and (DefaultAPL:GetVariable('stealthed_cto') or |
||||
Player:IsStealthed() and FindWeakness:IsKnown() and not Target:GetAuras():FindMy(FindWeakness):IsUp() or |
||||
HiddenOpportunity:IsKnown()) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- # Stealth Cooldowns |
||||
-- actions.stealth_cds=variable,name=vanish_condition,value=talent.hidden_opportunity|!talent.shadow_dance|!cooldown.shadow_dance.ready |
||||
StealthAPL:AddVariable( |
||||
'vanish_condition', |
||||
function() |
||||
return HiddenOpportunity:IsKnown() or not ShadowDance:IsKnown() or not ShadowDance:CooldownUp() |
||||
end |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/variable,name=vanish_opportunity_condition,value=!talent.shadow_dance&talent.fan_the_hammer.rank+talent.quick_draw+talent.audacity<talent.count_the_odds+talent.keep_it_rolling |
||||
StealthAPL:AddVariable( |
||||
'vanish_opportunity_condition', |
||||
function() |
||||
return not ShadowDance:IsKnown() and |
||||
(FanTheHammer:IsKnown() and 1 or 0) + (QuickDraw:IsKnown() and 1 or 0) + (Audacity:IsKnown() and 1 or 0) < |
||||
(CountTheOdds:IsKnown() and 1 or 0) + (KeepItRolling:IsKnown() and 1 or 0) |
||||
end |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/vanish,if=talent.find_weakness&!talent.audacity&debuff.find_weakness.down&variable.ambush_condition&variable.vanish_condition |
||||
StealthAPL:AddSpell( |
||||
Vanish:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and FindWeakness:IsKnown() and not Audacity:IsKnown() and |
||||
not Target:GetAuras():FindMy(FindWeakness):IsUp() and |
||||
DefaultAPL:GetVariable('ambush_condition') and StealthAPL:GetVariable('vanish_condition') |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/vanish,if=talent.hidden_opportunity&!buff.audacity.up&(variable.vanish_opportunity_condition|buff.opportunity.stack<buff.opportunity.max_stack)&variable.ambush_condition&variable.vanish_condition |
||||
StealthAPL:AddSpell( |
||||
Vanish:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and HiddenOpportunity:IsKnown() and |
||||
not Player:GetAuras():FindMy(Audacity):IsUp() and |
||||
(StealthAPL:GetVariable('vanish_opportunity_condition') or |
||||
Player:GetAuras():FindMy(OpportunityAura):GetCount() < |
||||
MaxOpportunity()) and |
||||
DefaultAPL:GetVariable('ambush_condition') and StealthAPL:GetVariable('vanish_condition') |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/vanish,if=(!talent.find_weakness|talent.audacity)&!talent.hidden_opportunity&variable.finish_condition&variable.vanish_condition |
||||
StealthAPL:AddSpell( |
||||
Vanish:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and (not FindWeakness:IsKnown() or Audacity:IsKnown()) and |
||||
not HiddenOpportunity:IsKnown() and |
||||
DefaultAPL:GetVariable('finish_condition') and StealthAPL:GetVariable('vanish_condition') |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/variable,name=shadow_dance_condition,value=talent.shadow_dance&debuff.between_the_eyes.up&(!talent.ghostly_strike|debuff.ghostly_strike.up)&(!talent.dreadblades|!cooldown.dreadblades.ready)&(!talent.hidden_opportunity|!buff.audacity.up&(talent.fan_the_hammer.rank<2|!buff.opportunity.up)) |
||||
StealthAPL:AddVariable( |
||||
'shadow_dance_condition', |
||||
function() |
||||
return ShadowDance:IsKnown() and Target:GetAuras():FindMy(BetweenTheEyes):IsUp() and |
||||
(not GhostlyStrike:IsKnown() or Target:GetAuras():FindMy(GhostlyStrike):IsUp()) and |
||||
(not Dreadblades:IsKnown() or not Dreadblades:CooldownUp()) and |
||||
(not HiddenOpportunity:IsKnown() or not Player:GetAuras():FindMy(Audacity):IsUp() and |
||||
(1 < 2 or not Player:GetAuras():FindMy(OpportunityAura):IsUp())) |
||||
end |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/shadow_dance,if=!talent.keep_it_rolling&variable.shadow_dance_condition&buff.slice_and_dice.up&(variable.finish_condition|talent.hidden_opportunity)&(!talent.hidden_opportunity|!cooldown.vanish.ready) |
||||
StealthAPL:AddSpell( |
||||
ShadowDance:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and not KeepItRolling:IsKnown() and |
||||
StealthAPL:GetVariable('shadow_dance_condition') and |
||||
Player:GetAuras():FindMy(SliceAndDice):IsUp() and |
||||
(DefaultAPL:GetVariable('finish_condition') or HiddenOpportunity:IsKnown()) and |
||||
(not HiddenOpportunity:IsKnown() or not Vanish:CooldownUp()) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
-- actions.stealth_cds+=/shadow_dance,if=talent.keep_it_rolling&variable.shadow_dance_condition&(cooldown.keep_it_rolling.remains<=30|cooldown.keep_it_rolling.remains>120&(variable.finish_condition|talent.hidden_opportunity)) |
||||
StealthAPL:AddSpell( |
||||
ShadowDance:CastableIf( |
||||
function(self) |
||||
return self:IsKnownAndUsable() and KeepItRolling:IsKnown() and |
||||
StealthAPL:GetVariable('shadow_dance_condition') and |
||||
(KeepItRolling:GetCooldownRemaining() <= 30 or |
||||
KeepItRolling:GetCooldownRemaining() > 120 and |
||||
(DefaultAPL:GetVariable('finish_condition') or HiddenOpportunity:IsKnown())) |
||||
end |
||||
):SetTarget(Target) |
||||
) |
||||
|
||||
OutlawModule:Sync(function() |
||||
print(BetweenTheEyes:IsKnownAndUsable()) |
||||
DefaultAPL:Execute() |
||||
end) |
||||
|
||||
Bastion:Register(OutlawModule) |
@ -0,0 +1,608 @@ |
||||
local Tinkr, Bastion = ... |
||||
|
||||
local OutlawModule = Bastion.Module:New('outlaw') |
||||
local Evaluator = Tinkr.Util.Evaluator |
||||
local Player = Bastion.UnitManager:Get('player') |
||||
local None = Bastion.UnitManager:Get('none') |
||||
local Target = Bastion.UnitManager:Get('target') |
||||
|
||||
local RollTheBones = Bastion.SpellBook:GetSpell(315508) |
||||
local SliceAndDice = Bastion.SpellBook:GetSpell(315496) |
||||
local BetweenTheEyes = Bastion.SpellBook:GetSpell(315341) |
||||
local BladeRush = Bastion.SpellBook:GetSpell(271877) |
||||
local Vanish = Bastion.SpellBook:GetSpell(1856) |
||||
local Dispatch = Bastion.SpellBook:GetSpell(2098) |
||||
local Ambush = Bastion.SpellBook:GetSpell(8676) |
||||
local Stealth = Bastion.SpellBook:GetSpell(1784) |
||||
local PistolShot = Bastion.SpellBook:GetSpell(185763) |
||||
local Opportunity = Bastion.SpellBook:GetSpell(195627) |
||||
local SinisterStrike = Bastion.SpellBook:GetSpell(193315) |
||||
local GrandMelee = Bastion.SpellBook:GetSpell(193358) |
||||
local Broadside = Bastion.SpellBook:GetSpell(193356) |
||||
local TrueBearing = Bastion.SpellBook:GetSpell(193359) |
||||
local RuthlessPrecision = Bastion.SpellBook:GetSpell(193357) |
||||
local SkullAndCrossbones = Bastion.SpellBook:GetSpell(199603) |
||||
local BuriedTreasure = Bastion.SpellBook:GetSpell(199600) |
||||
local AdrenalineRush = Bastion.SpellBook:GetSpell(13750) |
||||
local ShadowDance = Bastion.SpellBook:GetSpell(185313) |
||||
local Audacity = Bastion.SpellBook:GetSpell(381845) |
||||
local Flagellation = Bastion.SpellBook:GetSpell(323654) |
||||
local Dreadblades = Bastion.SpellBook:GetSpell(343142) |
||||
local JollyRoger = Bastion.SpellBook:GetSpell(199603) |
||||
local BladeFlurry = Bastion.SpellBook:GetSpell(13877) |
||||
local Kick = Bastion.SpellBook:GetSpell(1766) |
||||
local MarkedForDeath = Bastion.SpellBook:GetSpell(137619) |
||||
local CrimsonVial = Bastion.SpellBook:GetSpell(185311) |
||||
local Shiv = Bastion.SpellBook:GetSpell(5938) |
||||
local KidneyShot = Bastion.SpellBook:GetSpell(408) |
||||
local InstantPoison = Bastion.SpellBook:GetSpell(315584) |
||||
local AtrophicPosion = Bastion.SpellBook:GetSpell(381637) |
||||
local Evasion = Bastion.SpellBook:GetSpell(5277) |
||||
local TricksOfTheTrade = Bastion.SpellBook:GetSpell(57934) |
||||
local CheapShot = Bastion.SpellBook:GetSpell(1833) |
||||
local BagOfTricks = Bastion.SpellBook:GetSpell(312411) |
||||
local AutoAttack = Bastion.SpellBook:GetSpell(6603) |
||||
|
||||
local IrideusFragment = Bastion.ItemBook:GetItem(193743) |
||||
local Healthstone = Bastion.ItemBook:GetItem(5512) |
||||
local WindscarWhetstone = Bastion.ItemBook:GetItem(137486) |
||||
|
||||
local PurgeTarget = Bastion.UnitManager:CreateCustomUnit('purge', function(unit) |
||||
local purge = nil |
||||
|
||||
Bastion.UnitManager:EnumEnemies(function(unit) |
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if unit:GetAuras():HasAnyStealableAura() then |
||||
purge = unit |
||||
return true |
||||
end |
||||
end) |
||||
|
||||
if purge == nil then |
||||
purge = None |
||||
end |
||||
|
||||
return purge |
||||
end) |
||||
|
||||
local KickTarget = Bastion.UnitManager:CreateCustomUnit('kick', function(unit) |
||||
local purge = nil |
||||
|
||||
Bastion.UnitManager:EnumEnemies(function(unit) |
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if Player:InMelee(unit) and unit:IsInterruptible(5) and Player:IsFacing(unit) then |
||||
purge = unit |
||||
return true |
||||
end |
||||
end) |
||||
|
||||
if purge == nil then |
||||
purge = None |
||||
end |
||||
|
||||
return purge |
||||
end) |
||||
|
||||
local Tank = Bastion.UnitManager:CreateCustomUnit('tank', function(unit) |
||||
local tank = nil |
||||
|
||||
Bastion.UnitManager:EnumFriends(function(unit) |
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if unit:IsTank() then |
||||
tank = unit |
||||
return true |
||||
end |
||||
|
||||
return false |
||||
end) |
||||
|
||||
if tank == nil then |
||||
tank = None |
||||
end |
||||
|
||||
return tank |
||||
end) |
||||
|
||||
local Explosive = Bastion.UnitManager:CreateCustomUnit('explosive', function(unit) |
||||
local explosive = nil |
||||
|
||||
Bastion.UnitManager:EnumEnemies(function(unit) |
||||
if unit:IsDead() then |
||||
return false |
||||
end |
||||
|
||||
if not Player:CanSee(unit) then |
||||
return false |
||||
end |
||||
|
||||
if Player:GetDistance(unit) > 40 then |
||||
return false |
||||
end |
||||
|
||||
if Player:InMelee(unit) and unit:GetID() == 120651 and Player:IsFacing(unit) then |
||||
|
||||
explosive = unit |
||||
return true |
||||
end |
||||
end) |
||||
|
||||
if explosive == nil then |
||||
explosive = None |
||||
end |
||||
|
||||
return explosive |
||||
end) |
||||
|
||||
local DefaultAPL = Bastion.APL:New('default') |
||||
local AOEAPL = Bastion.APL:New('aoe') |
||||
local SpecialAPL = Bastion.APL:New('special') |
||||
|
||||
SpecialAPL:AddSpell( |
||||
Kick:CastableIf(function(self) |
||||
return KickTarget:Exists() and Player:InMelee(KickTarget) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() |
||||
end):SetTarget(KickTarget) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
SinisterStrike:CastableIf(function(self) |
||||
return Explosive:Exists() and not Player:IsCastingOrChanneling() |
||||
end):SetTarget(Explosive) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
KidneyShot:CastableIf(function(self) |
||||
return KickTarget:Exists() and Player:InMelee(KickTarget) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
( |
||||
Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or Player:GetAuras():FindMy(Opportunity):IsUp()))) |
||||
|
||||
end):SetTarget(KickTarget) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
CheapShot:CastableIf(function(self) |
||||
return KickTarget:Exists() and Player:InMelee(KickTarget) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and Player:GetAuras():FindMy(Stealth):IsUp() |
||||
end):SetTarget(KickTarget) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
Stealth:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and not Player:IsAffectingCombat() and |
||||
not Player:GetAuras():FindMy(Stealth):IsUp() and not IsMounted() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
CrimsonVial:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetHealthPercent() < 70 |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
Shiv:CastableIf(function(self) |
||||
return PurgeTarget:Exists() and Player:InMelee(PurgeTarget) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and PurgeTarget:GetAuras():HasAnyStealableAura() |
||||
end):SetTarget(PurgeTarget) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
InstantPoison:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
not Player:GetAuras():FindMy(InstantPoison):IsUp() and not Player:IsMoving() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
AtrophicPosion:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
not Player:GetAuras():FindMy(AtrophicPosion):IsUp() and not Player:IsMoving() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddItem( |
||||
Healthstone:UsableIf(function(self) |
||||
return self:IsEquippedAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetHealthPercent() < 40 |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
TricksOfTheTrade:CastableIf(function(self) |
||||
return Tank:Exists() and self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:IsTanking(Target) |
||||
end):SetTarget(Tank) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
Evasion:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetHealthPercent() < 40 |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddItem( |
||||
IrideusFragment:UsableIf(function(self) |
||||
return self:IsEquippedAndUsable() and |
||||
not Player:IsCastingOrChanneling() and (Player:GetMeleeAttackers() > 2 or Target:IsBoss()) |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddItem( |
||||
WindscarWhetstone:UsableIf(function(self) |
||||
return self:IsEquippedAndUsable() and |
||||
not Player:IsCastingOrChanneling() and (Player:GetMeleeAttackers() > 2 or Target:IsBoss()) |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
SpecialAPL:AddSpell( |
||||
BagOfTricks:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Adrenaline Rush on cooldown. |
||||
DefaultAPL:AddSpell( |
||||
AdrenalineRush:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Roll the Bones if you have no combat enhancements active. |
||||
DefaultAPL:AddSpell( |
||||
RollTheBones:CastableIf(function(self) |
||||
local numBuffs = 0 |
||||
if Player:GetAuras():FindMy(Broadside):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(BuriedTreasure):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(GrandMelee):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(RuthlessPrecision):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(SkullAndCrossbones):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(TrueBearing):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
((not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp()) or numBuffs < 2) |
||||
end):SetTarget(Player) |
||||
) |
||||
-- Slice and Dice if at max, or -1 from maximum combo points with Broadside or Opportunity active, if missing or has has 12 or less seconds remaining. |
||||
DefaultAPL:AddSpell( |
||||
SliceAndDice:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
( |
||||
Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or Player:GetAuras():FindMy(Opportunity):IsUp()))) and |
||||
( |
||||
not Player:GetAuras():FindMy(SliceAndDice):IsUp() or |
||||
Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() <= 12 |
||||
) |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Between the Eyes on cooldown if at max, or -1 from maximum combo points with Broadside or Opportunity active. |
||||
DefaultAPL:AddSpell( |
||||
BetweenTheEyes:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
( |
||||
Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or Player:GetAuras():FindMy(Opportunity):IsUp()))) |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Dispatch if at max, or -1 from maximum combo points with Broadside or Opportunity active. |
||||
DefaultAPL:AddSpell( |
||||
Dispatch:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
( |
||||
Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or Player:GetAuras():FindMy(Opportunity):IsUp()))) |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Shadow Dance at or below 3 combo points, and do not have Audacity or Opportunity active and wait until you have at least 80 energy. While active Ambush becomes your highest priority builder. |
||||
DefaultAPL:AddSpell( |
||||
ShadowDance:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetComboPoints(Target) <= 3 and |
||||
not Player:GetAuras():FindMy(Audacity):IsUp() and |
||||
not Player:GetAuras():FindMy(Opportunity):IsUp() and |
||||
Player:GetPower() >= 80 |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Blade Rush if missing 50 or more energy and do not have Flagellation, Dreadblades or Shadow Dance active. |
||||
DefaultAPL:AddSpell( |
||||
BladeRush:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetPower() <= 50 and |
||||
not Player:GetAuras():FindMy(Flagellation):IsUp() and |
||||
not Player:GetAuras():FindMy(Dreadblades):IsUp() and |
||||
not Player:GetAuras():FindMy(ShadowDance):IsUp() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Vanish followed by Ambush if you won't overcap combo points and wait until you have at least 50 energy. |
||||
DefaultAPL:AddSpell( |
||||
Vanish:CastableIf(function(self) |
||||
return Tank:Exists() and Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetComboPoints(Target) <= 4 and |
||||
Player:GetPower() >= 50 and not Player:GetAuras():FindMy(Stealth):IsUp() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Pistol Shot if you have an Opportunity proc and won't overcap combo points. |
||||
DefaultAPL:AddSpell( |
||||
PistolShot:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetAuras():FindMy(Opportunity):IsUp() and |
||||
Player:GetComboPoints(Target) <= 4 |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Use Ambush Icon Ambush instead of Sinister Strike Icon Sinister Strike whenever it is available to cast from any of the procs or cooldowns. |
||||
DefaultAPL:AddSpell( |
||||
Ambush:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Sinister Strike if you won't overcap combo points. |
||||
DefaultAPL:AddSpell( |
||||
SinisterStrike:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetComboPoints(Target) < 5 |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- AOE APL |
||||
|
||||
-- Adrenaline Rush on cooldown. |
||||
AOEAPL:AddSpell( |
||||
AdrenalineRush:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Roll the Bones if you have no combat enhancements active. |
||||
-- Roll the Bones has a large outcome of buffs which include; Broadside, Buried Treasure, Grand Melee, Ruthless Precision, Skull and Crossbones, and True Bearing. The buffs you want to keep this tier are going to be Broadside and True Bearing as single buffs or any combination of 2 or more buffs. Any of the other 4 buffs as a single means it's worth recasting Roll the Bones as soon as you are able to. |
||||
|
||||
AOEAPL:AddSpell( |
||||
RollTheBones:CastableIf(function(self) |
||||
local numBuffs = 0 |
||||
if Player:GetAuras():FindMy(Broadside):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(BuriedTreasure):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(GrandMelee):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(RuthlessPrecision):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(SkullAndCrossbones):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
if Player:GetAuras():FindMy(TrueBearing):IsUp() then |
||||
numBuffs = numBuffs + 1 |
||||
end |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
((not Player:GetAuras():FindMy(Broadside):IsUp() and |
||||
not Player:GetAuras():FindMy(TrueBearing):IsUp()) or numBuffs < 2) |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Blade Flurry when missing. |
||||
AOEAPL:AddSpell( |
||||
BladeFlurry:CastableIf(function(self) |
||||
return self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(not Player:GetAuras():FindMy(self):IsUp() or Player:GetAuras():FindMy(self):GetRemainingTime() <= 2) |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Slice and Dice if at max, or -1 from maximum combo points with Broadside or Opportunity active, if missing or has has 12 or less seconds remaining. |
||||
AOEAPL:AddSpell( |
||||
SliceAndDice:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
(Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or |
||||
Player:GetAuras():FindMy(Opportunity):IsUp()))) and |
||||
(not Player:GetAuras():FindMy(self):IsUp() or |
||||
Player:GetAuras():FindMy(self):GetRemainingTime() <= 12) |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Between the Eyes on cooldown if at max, or -1 from maximum combo points with Broadside or Opportunity active. |
||||
AOEAPL:AddSpell( |
||||
BetweenTheEyes:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
(Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or |
||||
Player:GetAuras():FindMy(Opportunity):IsUp()))) |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Dispatch if at max, or -1 from maximum combo points with Broadside or Opportunity active. |
||||
AOEAPL:AddSpell( |
||||
Dispatch:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
(Player:GetComboPoints(Target) >= 5 or |
||||
(Player:GetComboPoints(Target) >= 4 and |
||||
(Player:GetAuras():FindMy(Broadside):IsUp() or |
||||
Player:GetAuras():FindMy(Opportunity):IsUp()))) |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Shadow Dance at or below 3 combo points, and do not have Audacity or Opportunity active and wait until you have at least 80 energy. While active Ambush becomes your highest priority builder. |
||||
AOEAPL:AddSpell( |
||||
ShadowDance:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetComboPoints(Target) <= 3 and |
||||
not Player:GetAuras():FindMy(Audacity):IsUp() and |
||||
not Player:GetAuras():FindMy(Opportunity):IsUp() and |
||||
Player:GetPower() >= 80 |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Blade Rush if missing 50 or more energy and do not have Flagellation, Dreadblades or Shadow Dance active. |
||||
AOEAPL:AddSpell( |
||||
BladeRush:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetPower() >= 50 and |
||||
not Player:GetAuras():FindMy(Flagellation):IsUp() and |
||||
not Player:GetAuras():FindMy(Dreadblades):IsUp() and |
||||
not Player:GetAuras():FindMy(ShadowDance):IsUp() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Vanish followed by Ambush if you won't overcap combo points and wait until you have at least 50 energy. |
||||
AOEAPL:AddSpell( |
||||
Vanish:CastableIf(function(self) |
||||
return Tank:Exists() and Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetComboPoints(Target) < 5 and |
||||
Player:GetPower() >= 50 and not Player:GetAuras():FindMy(Stealth):IsUp() |
||||
end):SetTarget(Player) |
||||
) |
||||
|
||||
-- Pistol Shot if you have an Opportunity proc and won't overcap combo points. |
||||
AOEAPL:AddSpell( |
||||
PistolShot:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetAuras():FindMy(Opportunity):IsUp() and |
||||
Player:GetComboPoints(Target) < 5 |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
AOEAPL:AddSpell( |
||||
Ambush:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
-- Sinister Strike if you won't overcap combo points. |
||||
AOEAPL:AddSpell( |
||||
SinisterStrike:CastableIf(function(self) |
||||
return Target:Exists() and Player:InMelee(Target) and |
||||
self:IsKnownAndUsable() and |
||||
not Player:IsCastingOrChanneling() and |
||||
Player:GetComboPoints(Target) < 5 |
||||
end):SetTarget(Target) |
||||
) |
||||
|
||||
OutlawModule:Sync(function() |
||||
SpecialAPL:Execute() |
||||
if Player:GetMeleeAttackers() > 1 then |
||||
AOEAPL:Execute() |
||||
else |
||||
DefaultAPL:Execute() |
||||
end |
||||
end) |
||||
|
||||
Bastion:Register(OutlawModule) |
Loading…
Reference in new issue