GUI, Scripts, Commands

Embedded GUI, amended scripts, added bastion interface
main
Ofrex 2 years ago
parent 53679d748f
commit ac9d9740be
  1. 17
      README.md
  2. 954
      scripts/outlaw.lua
  3. 608
      scripts/outlawbak.lua
  4. 287
      scripts/restodruid.lua
  5. 64
      scripts/shadowpriest.lua
  6. 88
      scripts/subtlety.lua
  7. 4
      src/APL/APL.lua
  8. 14
      src/Aura/Aura.lua
  9. 4
      src/AuraTable/AuraTable.lua
  10. 1
      src/Cache/Cache.lua
  11. 6
      src/Cacheable/Cacheable.lua
  12. 1
      src/Class/Class.lua
  13. 2
      src/ClassMagic/ClassMagic.lua
  14. 2
      src/Command/Command.lua
  15. 2
      src/EventManager/EventManager.lua
  16. 113
      src/GUI/Gui.lua
  17. 11
      src/Item/Item.lua
  18. 2
      src/ItemBook/ItemBook.lua
  19. 1
      src/List/List.lua
  20. 1
      src/Module/Module.lua
  21. 159
      src/MythicPlusUtils/MythicPlusUtils.lua
  22. 30
      src/NotificationsList/NotificationsList.lua
  23. 1
      src/ObjectManager/ObjectManager.lua
  24. 6
      src/Refreshable/Refreshable.lua
  25. 10
      src/Spell/Spell.lua
  26. 4
      src/SpellBook/SpellBook.lua
  27. 1
      src/Timer/Timer.lua
  28. 16
      src/Unit/Unit.lua
  29. 6
      src/UnitManager/UnitManager.lua
  30. 1
      src/Vector3/Vector3.lua
  31. 55
      src/_bastion.lua

@ -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 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! 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! Feel free to browse around the [Wiki](https://git.tinkr.site/4n0n/bastion/wiki) or just start by reading the code!
## Quick Start ## 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. - 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)

@ -6,6 +6,8 @@ local Player = Bastion.UnitManager:Get('player')
local None = Bastion.UnitManager:Get('none') local None = Bastion.UnitManager:Get('none')
local Target = Bastion.UnitManager:Get('target') local Target = Bastion.UnitManager:Get('target')
local myconf = Tinkr.Util.Config:New('resto_druid')
local AnomalyDetectionMarkI = Bastion.SpellBook:GetSpell(382499) local AnomalyDetectionMarkI = Bastion.SpellBook:GetSpell(382499)
local AutoAttack = Bastion.SpellBook:GetSpell(6603) local AutoAttack = Bastion.SpellBook:GetSpell(6603)
local MechanismBypass = Bastion.SpellBook:GetSpell(382501) local MechanismBypass = Bastion.SpellBook:GetSpell(382501)
@ -89,6 +91,7 @@ local Lifebloom = Bastion.SpellBook:GetSpell(33763)
local LifebloomAura = Bastion.SpellBook:GetSpell(188550) local LifebloomAura = Bastion.SpellBook:GetSpell(188550)
local NaturesCure = Bastion.SpellBook:GetSpell(88423) local NaturesCure = Bastion.SpellBook:GetSpell(88423)
local NaturesSwiftness = Bastion.SpellBook:GetSpell(132158) local NaturesSwiftness = Bastion.SpellBook:GetSpell(132158)
local MoonkinForm = Bastion.SpellBook:GetSpell(197625)
local Revitalize = Bastion.SpellBook:GetSpell(212040) local Revitalize = Bastion.SpellBook:GetSpell(212040)
local Tranquility = Bastion.SpellBook:GetSpell(740) local Tranquility = Bastion.SpellBook:GetSpell(740)
local MasteryHarmony = Bastion.SpellBook:GetSpell(77495) local MasteryHarmony = Bastion.SpellBook:GetSpell(77495)
@ -385,14 +388,14 @@ local Explosive = Bastion.UnitManager:CreateCustomUnit('explosive', function(uni
return explosive return explosive
end) end)
local RestoCommands = Bastion.Command:New('resto') -- local RestoCommands = Bastion.Command:New('rex')
local PLACE_EFFLO = false -- local PLACE_EFFLO = false
RestoCommands:Register('efflo', 'Request the engine to place an Efflorescence', function() -- RestoCommands:Register('efflo', 'Request the engine to place an Efflorescence', function()
PLACE_EFFLO = true -- PLACE_EFFLO = true
Bastion.Notifications:AddNotification(Efflorescence:GetIcon(), "Efflorescence requested") -- Bastion.Notifications:AddNotification(Efflorescence:GetIcon(), "Efflorescence requested")
end) -- end)
local DefaultAPL = Bastion.APL:New('default') local DefaultAPL = Bastion.APL:New('default')
local DamageAPL = Bastion.APL:New('damage') local DamageAPL = Bastion.APL:New('damage')
@ -405,20 +408,21 @@ DefaultAPL:AddSpell(
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
Efflorescence:CastableIf(function(self) Efflorescence:CastableIf(function(self)
return PLACE_EFFLO and Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return IsShiftKeyDown() and Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(None):OnCast(function(self) end):SetTarget(None):OnCast(function(self)
local loc = Bastion.UnitManager:FindFriendsCentroid(10, 40) --local loc = Target:GetPosition()
PLACE_EFFLO = false
self:Click(loc) self:Click(loc)
end) end)
) )
DefaultAPL:AddAction( DefaultAPL:AddAction(
'cat_form_shift', 'cat_form_shift',
function() function()
if IsShiftKeyDown() and not Player:GetAuras():FindMy(CatForm):IsUp() and not Player:IsCastingOrChanneling() then if IsAltKeyDown() and not Player:GetAuras():FindMy(MoonkinForm):IsUp() and not Player:IsCastingOrChanneling() then
CatForm:Cast(Player) MoonkinForm:Cast(Player)
elseif not IsShiftKeyDown() and Player:GetAuras():FindMy(CatForm):IsUp() then elseif not IsAltKeyDown() and Player:GetAuras():FindMy(MoonkinForm):IsUp() then
CancelShapeshiftForm() CancelShapeshiftForm()
end end
end end
@ -441,23 +445,30 @@ DefaultAPL:AddSpell(
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
NaturesSwiftness:CastableIf(function(self) NaturesSwiftness:CastableIf(function(self)
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Lowest) and Lowest:GetHP() < 70 and Player:CanSee(Lowest) and
(Lowest:GetHP() < 70 or (Player:GetPartyHPAround(40, 65) >= 2 or Player:GetPartyHPAround(40, 70))
)
end):SetTarget(Lowest) end):SetTarget(Lowest)
) )
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
ConvokeTheSpirits:CastableIf(function(self) ConvokeTheSpirits:CastableIf(function(self)
return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
self:IsInRange(Player) and (Player:GetPartyHPAround(40, 70) >= 2 or Player:GetPartyHPAround(40, 75) >= 3) self:IsInRange(Player) and (Player:GetPartyHPAround(40, 65) >= 2 or Player:GetPartyHPAround(40, 60) >= 3)
and (Flourish:IsKnownAndUsable() or Flourish:GetTimeSinceLastCast() > 10) end):SetTarget(Player)
)
DefaultAPL:AddSpell(
MarkoftheWild:CastableIf(function(self)
return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
not Player:GetAuras():FindMy(MarkoftheWild):IsUp()
end):SetTarget(Player) end):SetTarget(Player)
) )
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
Flourish:CastableIf(function(self) Flourish:CastableIf(function(self)
return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
self:IsInRange(Player) and (Player:GetPartyHPAround(40, 70) >= 2 or Player:GetPartyHPAround(40, 75) >= 3) and self:IsInRange(Player) and (Player:GetPartyHPAround(40, 65) >= 2 or Player:GetPartyHPAround(40, 70) >= 3) and
(not ConvokeTheSpirits:IsKnownAndUsable() and ConvokeTheSpirits:GetTimeSinceLastCast() > 10) and (not ConvokeTheSpirits:IsKnownAndUsable() and ConvokeTheSpirits:GetTimeSinceLastCast() > 7) and
WildGrowth:GetTimeSinceLastCast() <= 6 WildGrowth:GetTimeSinceLastCast() <= 6
end):SetTarget(Player) end):SetTarget(Player)
) )
@ -471,7 +482,7 @@ DefaultAPL:AddSpell(
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
AdaptiveSwarm:CastableIf(function(self) AdaptiveSwarm:CastableIf(function(self)
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:IsAffectingCombat()
and Player:CanSee(Lowest) and Player:CanSee(Lowest)
end):SetTarget(Lowest) end):SetTarget(Lowest)
) )
@ -481,7 +492,7 @@ DefaultAPL:AddSpell(
return SwiftmendUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return SwiftmendUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(SwiftmendUnit) and and Player:CanSee(SwiftmendUnit) and
( (
SwiftmendUnit:GetHP() <= 60 or SwiftmendUnit:GetHP() <= 80 or
( (
Lowest:GetPartyHPAround(30, 90) >= 3 or Lowest:GetPartyHPAround(30, 85) >= 2 Lowest:GetPartyHPAround(30, 90) >= 3 or Lowest:GetPartyHPAround(30, 85) >= 2
) )
@ -494,10 +505,12 @@ DefaultAPL:AddSpell(
return WildGrowthUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return WildGrowthUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(WildGrowthUnit) and and Player:CanSee(WildGrowthUnit) and
( (
Player:GetAuras():FindMy(SoulOfTheForest):IsUp() (
or Player:GetAuras():FindMy(SoulOfTheForest):IsUp() and
(WildGrowthUnit:GetPartyHPAround(30, 90) >= 3 or WildGrowthUnit:GetPartyHPAround(30, 85) >= 2) (
) and Player:GetAuras():FindMy(SoulOfTheForest):GetRemainingTime() <= 5 or
WildGrowthUnit:GetPartyHPAround(30, 90) >= 2)) or
(WildGrowthUnit:GetPartyHPAround(30, 90) >= 3 or WildGrowthUnit:GetPartyHPAround(30, 85) >= 2)) and
not Player:IsMoving() not Player:IsMoving()
end):SetTarget(WildGrowthUnit) end):SetTarget(WildGrowthUnit)
) )
@ -538,7 +551,7 @@ DefaultAPL:AddSpell(
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
Rejuvenation:CastableIf(function(self) Rejuvenation:CastableIf(function(self)
return RejuvUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return RejuvUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(RejuvUnit) and (RejuvUnit:GetHP() <= 94) and and Player:CanSee(RejuvUnit) and RejuvUnit:GetHP() <= 90 and
not Player:GetAuras():FindMy(SoulOfTheForest):IsUp() not Player:GetAuras():FindMy(SoulOfTheForest):IsUp()
end):SetTarget(RejuvUnit) end):SetTarget(RejuvUnit)
) )
@ -575,60 +588,214 @@ DefaultAPL:AddSpell(
end):SetTarget(Lowest) end):SetTarget(Lowest)
) )
DamageAPL:AddSpell(
Sunfire:CastableIf(function(self)
return Bastion.UnitManager['target']:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Bastion.UnitManager['target']) and
(
not Bastion.UnitManager['target']:GetAuras():FindMy(SunfireAura):IsUp() or
Bastion.UnitManager['target']:GetAuras():FindMy(SunfireAura):GetRemainingTime() <= 5.4) and
Bastion.UnitManager['target']:IsHostile() and
Bastion.UnitManager['target']:IsAffectingCombat() and Player:GetPP() >= 25
end):SetTarget(Bastion.UnitManager['target'])
)
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
Rejuvenation:CastableIf(function(self) Innervate:CastableIf(function(self)
return RejuvUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:IsAffectingCombat()
and Player:CanSee(RejuvUnit) and (RejuvUnit:GetHP() <= 94 or Player:GetPartyHPAround(40, 90) >= 2) and and Player:GetPP() <= 60
not Player:GetAuras():FindMy(SoulOfTheForest):IsUp() end):SetTarget(Player)
end):SetTarget(RejuvUnit)
) )
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
Sunfire:CastableIf(function(self) TravelForm:CastableIf(function(self)
return Target:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:IsAffectingCombat() and not IsMounted()
and Player:CanSee(Target) and and Player:IsMoving() and not Player:GetAuras():FindMy(TravelForm):IsUp() and not Player:IsIndoors()
( end):SetTarget(Player)
not Target:GetAuras():FindMy(SunfireAura):IsUp() or
Target:GetAuras():FindMy(SunfireAura):GetRemainingTime() <= 5.4) and
Target:IsHostile() and
Target:IsAffectingCombat() and Player:GetPP() >= 25
end):SetTarget(Target)
) )
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
CatForm:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:IsAffectingCombat() and not IsMounted()
and Player:IsMoving() and not Player:GetAuras():FindMy(CatForm):IsUp() and Player:IsIndoors()
end):SetTarget(Player)
)
DamageAPL:AddSpell(
Moonfire:CastableIf(function(self) Moonfire:CastableIf(function(self)
return Target:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return Bastion.UnitManager['target']:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Target) and and Player:CanSee(Bastion.UnitManager['target']) and
( (
not Target:GetAuras():FindMy(MoonfireAura):IsUp() or not Bastion.UnitManager['target']:GetAuras():FindMy(MoonfireAura):IsUp() or
Target:GetAuras():FindMy(MoonfireAura):GetRemainingTime() <= 5.4) and Bastion.UnitManager['target']:GetAuras():FindMy(MoonfireAura):GetRemainingTime() <= 5.4) and
Target:IsHostile() and Bastion.UnitManager['target']:IsHostile() and
Target:IsAffectingCombat() and Player:GetPP() >= 25 Bastion.UnitManager['target']:IsAffectingCombat() and Player:GetPP() >= 25
end):SetTarget(Target) end):SetTarget(Bastion.UnitManager['target'])
) )
DefaultAPL:AddSpell( DamageAPL:AddSpell(
Starsurge:CastableIf(function(self) Starsurge:CastableIf(function(self)
return Target:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return Bastion.UnitManager['target']:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Target) and Target:IsHostile() and and Player:CanSee(Bastion.UnitManager['target']) and Bastion.UnitManager['target']:IsHostile() and
Target:IsAffectingCombat() and Player:GetPP() >= 25 Bastion.UnitManager['target']:IsAffectingCombat() and Player:GetPP() >= 25
end):SetTarget(Target) end):SetTarget(Bastion.UnitManager['target'])
) )
DefaultAPL:AddSpell( DamageAPL:AddSpell(
Wrath:CastableIf(function(self) Wrath:CastableIf(function(self)
return Target:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() return Bastion.UnitManager['target']:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Target) and not Player:IsMoving() and and Player:CanSee(Bastion.UnitManager['target']) and not Player:IsMoving() and
Target:IsHostile() and Bastion.UnitManager['target']:IsHostile() and
Target:IsAffectingCombat() and Player:GetPP() >= 25 Bastion.UnitManager['target']:IsAffectingCombat() and Player:GetPP() >= 25
end):SetTarget(Target) end):SetTarget(Bastion.UnitManager['target'])
) )
RestoModule:Sync(function() RestoModule:Sync(function()
if IsShiftKeyDown() and Player:GetAuras():FindMy(CatForm):IsUp() then if IsAltKeyDown() and Player:GetAuras():FindMy(MoonkinForm):IsUp() then
return DamageAPL:Execute() return DamageAPL:Execute()
end end
DefaultAPL:Execute() DefaultAPL:Execute()
end) end)
Bastion:Register(RestoModule) Bastion:Register(RestoModule)
local tab1 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { shadpr = { type = 'header', label = 'Open Combat' } },
[2] = { opener = { type = 'dropdown', label = 'Healing', column = 6, order = 1,
options = {
{ text = 'Healing 1', value = 'swp'},
{ text = 'Healing 2', value = 'crash'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('opener', 'shield'),
onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
[3] = { swp1 = { type = 'checkbox', label = 'Spread SWP', column = 6, order = 1,
initialValue = myconf:Read('swpspread', false),
onValueChanged = function(_, flag) myconf:Write('swpspread', flag) end },
swp2 = { type = 'slider', label = 'Max Targets', column = 6, order = 2,
min = 1, max = 10, precision = 0,
initialValue = myconf:Read('swptargets', 3),
onValueChanged = function(_, value) myconf:Write('swptargets', value) end }, },
[4] = { shadpr = { type = 'header', label = 'Defensives' } },
[5] = { shield1 = { type = 'checkbox', label = 'Power Word: Shield', column = 6, order = 1,
initialValue = myconf:Read('pws', false),
onValueChanged = function(_, flag) myconf:Write('pws', flag) end },
shield2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('pwspercent', 35),
onValueChanged = function(_, value) myconf:Write('pwspercent', value) end }, },
[6] = { dispersion1 = { type = 'checkbox', label = 'Dispersion', column = 6, order = 1,
initialValue = myconf:Read('dispersion', false),
onValueChanged = function(_, flag) myconf:Write('dispersion', flag) end },
dispersion2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('dispersionpercent', 35),
onValueChanged = function(_, value) myconf:Write('dispersionpercent', value) end }, },
[7] = { shadpr = { type = 'header', label = 'Interrupts' } },
[8] = { silence = { type = 'checkbox', label = 'Silence on CD', column = 6, order = 1,
initialValue = myconf:Read('silence', false),
onValueChanged = function(_, flag) myconf:Write('silence', flag) end },
horror = { type = 'checkbox', label = 'Psychic Horror on CD', column = 6, order = 2,
initialValue = myconf:Read('horror', false),
onValueChanged = function(_, flag) myconf:Write('horror', flag) end }, },
[9] = { shadpr = { type = 'header', label = 'Purify Disease' } },
[10] = { incombat = { type = 'checkbox', label = 'In Combat', column = 6, order = 1,
initialValue = myconf:Read('purifyic', false),
onValueChanged = function(_, flag) myconf:Write('purifyic', flag) end },
outcombat = { type = 'checkbox', label = 'Out of Combat', column = 6, order = 2,
initialValue = myconf:Read('purifyooc', false),
onValueChanged = function(_, flag) myconf:Write('purifyooc', flag) end }, },
[11] = { shadpr = { type = 'header', label = 'Dispel Magic' } },
[12] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1,
initialValue = myconf:Read('dispelic', false),
onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, },
[13] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } },
[14] = { delay = { type = 'slider', label = 'In seconds', column = 6, order = 1,
min = 0.5, max = 2, precision = 1,
initialValue = myconf:Read('dispeldelay', 1),
onValueChanged = function(_, value) myconf:Write('dispeldelay', value) end }, },
},
}
local tab2 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { shadpr = { type = 'header', label = 'Player Healing' } },
[2] = { incombat = { type = 'checkbox', label = 'In Combat Healing', column = 6, order = 1,
initialValue = myconf:Read('playericheal', false),
onValueChanged = function(_, flag) myconf:Write('playericheal', flag) end },
outcombat = { type = 'checkbox', label = 'Out of Combat Healing', column = 6, order = 2,
initialValue = myconf:Read('playeroocheal', false),
onValueChanged = function(_, flag) myconf:Write('playeroocheal', flag) end }, },
[3] = { shadowmend1 = { type = 'checkbox', label = 'Shadow Mend', column = 6, order = 1,
initialValue = myconf:Read('shadowmend', false),
onValueChanged = function(_, flag) myconf:Write('shadowmend', flag) end },
shadowmend2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('shadowmendpercent', 35),
onValueChanged = function(_, value) myconf:Write('shadowmendpercent', value) end }, },
},
}
local restodruidconfig = {
layoutConfig = { padding = { top = 30 } },
rows = {
[1] = {
container = {
type = 'tab',
fullSize = true,
tabs = {
{
name = 'player',
title = 'Player Settings',
layout = tab1
},
{
name = 'group',
title = 'Healing',
layout = tab2
}
},
}
},
},
}
Bastion.settingstemplate(restodruidconfig, 'Resto Druid', 400, 600, 1.00, 1.00, 1.00) --, 0.00, 0.44, 0.87, 'enhsha') --Title of Settings Frame, Width, Height, ClassRGB, Rotation Name
-- Class colours
-- Death Knight 0.77 0.12 0.23 Red
-- Demon Hunter 0.64 0.19 0.79 Dark Magenta
-- Druid 1.00 0.49 0.04 Orange
-- Evoker 0.20 0.58 0.50 Dark Emerald
-- Hunter 0.67 0.83 0.45 Green
-- Mage 0.25 0.78 0.92 Light Blue
-- Monk 0.00 1.00 0.60 Spring Green
-- Paladin 0.96 0.55 0.73 Pink
-- Priest 1.00 1.00 1.00 White
-- Rogue 1.00 0.96 0.41 Yellow
-- Shaman 0.00 0.44 0.87 Blue
-- Warlock 0.53 0.53 0.93 Purple
-- Warrior 0.78 0.61 0.43 Tan

@ -1,7 +1,5 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
Tinkr:require("scripts.bastion.ui", Bastion)
local ShadowModule = Bastion.Module:New('shadow') local ShadowModule = Bastion.Module:New('shadow')
local Evaluator = Tinkr.Util.Evaluator local Evaluator = Tinkr.Util.Evaluator
local Player = Bastion.UnitManager:Get('player') local Player = Bastion.UnitManager:Get('player')
@ -122,13 +120,13 @@ local usepwf = myconf:Read('pwf')
local useshadowform = myconf:Read('shadowform') local useshadowform = myconf:Read('shadowform')
RestingAPL:AddSpell( RestingAPL:AddSpell(
PowerWordFortitude:CastableIf(function(self) PowerWordFortitude:CastableIf(function(self)
return usepwf == 'yes' and self:IsKnownAndUsable() and return usepwf and self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordFortitude):IsUp() and not IsMounted() not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordFortitude):IsUp() and not IsMounted()
end):SetTarget(Player) end):SetTarget(Player)
) )
RestingAPL:AddSpell( RestingAPL:AddSpell(
Shadowform:CastableIf(function(self) Shadowform:CastableIf(function(self)
return useshadowform == 'yes' and self:IsKnownAndUsable() and return useshadowform and self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Shadowform):IsUp() and not IsMounted() not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Shadowform):IsUp() and not IsMounted()
end):SetTarget(Player) end):SetTarget(Player)
) )
@ -289,7 +287,7 @@ local tab1 =
{ {
layoutConfig = { padding = { top = 40 } }, layoutConfig = { padding = { top = 40 } },
rows = { rows = {
[1] = { shadpr = { type = 'header', label = 'Open Combat' } }, [1] = { shadpr = { type = 'label', label = 'Open Combat' } },
[2] = { opener = { type = 'dropdown', label = 'Opener', column = 6, order = 1, [2] = { opener = { type = 'dropdown', label = 'Opener', column = 6, order = 1,
options = { options = {
@ -300,18 +298,19 @@ local tab1 =
initialValue = myconf:Read('opener', 'shield'), initialValue = myconf:Read('opener', 'shield'),
onValueChanged = function(_, value) myconf:Write('opener', value) end }, }, onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
[3] = { swp1 = { type = 'checkbox', label = 'Spread SWP', column = 6, order = 1, [3] = { shadpr = { type = 'label', label = 'Buffs' } },
initialValue = myconf:Read('swpspread', false),
onValueChanged = function(_, flag) myconf:Write('swpspread', flag) end }, [4] = { pwf = { type = 'checkbox', label = 'Power Word: Fortitude', column = 6, order = 1,
initialValue = myconf:Read('pwf', false),
onValueChanged = function(_, flag) myconf:Write('pwf', flag) end },
swp2 = { type = 'slider', label = 'Max Targets', column = 6, order = 2, shadform = { type = 'checkbox', label = 'Shadowform', column = 6, order = 2,
min = 1, max = 10, precision = 0, initialValue = myconf:Read('shadowform', false),
initialValue = myconf:Read('swptargets', 3), onValueChanged = function(_, flag) myconf:Write('shadowform', flag) end }, },
onValueChanged = function(_, value) myconf:Write('swptargets', value) end }, },
[4] = { shadpr = { type = 'header', label = 'Defensives' } }, [5] = { shadpr = { type = 'header', label = 'Defensives' } },
[5] = { shield1 = { type = 'checkbox', label = 'Power Word: Shield', column = 6, order = 1, [6] = { shield1 = { type = 'checkbox', label = 'Power Word: Shield', column = 6, order = 1,
initialValue = myconf:Read('pws', false), initialValue = myconf:Read('pws', false),
onValueChanged = function(_, flag) myconf:Write('pws', flag) end }, onValueChanged = function(_, flag) myconf:Write('pws', flag) end },
@ -320,7 +319,7 @@ local tab1 =
initialValue = myconf:Read('pwspercent', 35), initialValue = myconf:Read('pwspercent', 35),
onValueChanged = function(_, value) myconf:Write('pwspercent', value) end }, }, onValueChanged = function(_, value) myconf:Write('pwspercent', value) end }, },
[6] = { dispersion1 = { type = 'checkbox', label = 'Dispersion', column = 6, order = 1, [7] = { dispersion1 = { type = 'checkbox', label = 'Dispersion', column = 6, order = 1,
initialValue = myconf:Read('dispersion', false), initialValue = myconf:Read('dispersion', false),
onValueChanged = function(_, flag) myconf:Write('dispersion', flag) end }, onValueChanged = function(_, flag) myconf:Write('dispersion', flag) end },
@ -329,9 +328,9 @@ local tab1 =
initialValue = myconf:Read('dispersionpercent', 35), initialValue = myconf:Read('dispersionpercent', 35),
onValueChanged = function(_, value) myconf:Write('dispersionpercent', value) end }, }, onValueChanged = function(_, value) myconf:Write('dispersionpercent', value) end }, },
[7] = { shadpr = { type = 'header', label = 'Interrupts' } }, [8] = { shadpr = { type = 'header', label = 'Interrupts' } },
[8] = { silence = { type = 'checkbox', label = 'Silence on CD', column = 6, order = 1, [9] = { silence = { type = 'checkbox', label = 'Silence on CD', column = 6, order = 1,
initialValue = myconf:Read('silence', false), initialValue = myconf:Read('silence', false),
onValueChanged = function(_, flag) myconf:Write('silence', flag) end }, onValueChanged = function(_, flag) myconf:Write('silence', flag) end },
@ -339,9 +338,9 @@ local tab1 =
initialValue = myconf:Read('horror', false), initialValue = myconf:Read('horror', false),
onValueChanged = function(_, flag) myconf:Write('horror', flag) end }, }, onValueChanged = function(_, flag) myconf:Write('horror', flag) end }, },
[9] = { shadpr = { type = 'header', label = 'Purify Disease' } }, [10] = { shadpr = { type = 'header', label = 'Purify Disease' } },
[10] = { incombat = { type = 'checkbox', label = 'In Combat', column = 6, order = 1, [11] = { incombat = { type = 'checkbox', label = 'In Combat', column = 6, order = 1,
initialValue = myconf:Read('purifyic', false), initialValue = myconf:Read('purifyic', false),
onValueChanged = function(_, flag) myconf:Write('purifyic', flag) end }, onValueChanged = function(_, flag) myconf:Write('purifyic', flag) end },
@ -349,15 +348,15 @@ local tab1 =
initialValue = myconf:Read('purifyooc', false), initialValue = myconf:Read('purifyooc', false),
onValueChanged = function(_, flag) myconf:Write('purifyooc', flag) end }, }, onValueChanged = function(_, flag) myconf:Write('purifyooc', flag) end }, },
[11] = { shadpr = { type = 'header', label = 'Dispel Magic' } }, [12] = { shadpr = { type = 'header', label = 'Dispel Magic' } },
[12] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1, [13] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1,
initialValue = myconf:Read('dispelic', false), initialValue = myconf:Read('dispelic', false),
onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, }, onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, },
[13] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } }, [14] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } },
[14] = { delay = { type = 'slider', label = 'In seconds', column = 6, order = 1, [15] = { delay = { type = 'slider', label = 'In seconds', column = 6, order = 1,
min = 0.5, max = 2, precision = 1, min = 0.5, max = 2, precision = 1,
initialValue = myconf:Read('dispeldelay', 1), initialValue = myconf:Read('dispeldelay', 1),
onValueChanged = function(_, value) myconf:Write('dispeldelay', value) end }, }, onValueChanged = function(_, value) myconf:Write('dispeldelay', value) end }, },
@ -406,7 +405,7 @@ local shadpriestconfig = {
}, },
{ {
name = 'group', name = 'group',
title = 'Healing', title = 'Placeholder',
layout = tab2 layout = tab2
} }
}, },
@ -414,4 +413,19 @@ local shadpriestconfig = {
}, },
}, },
} }
Bastion.setupsettingsframe(shadpriestconfig, 'Rex Shadow Priest', 400, 600, 1.00, 1.00, 1.00) --, 0.00, 0.44, 0.87, 'enhsha') --Title of Settings Frame, Width, Height, ClassRGB, Rotation Name Bastion.settingstemplate(shadpriestconfig, 'Shadow Priest', 400, 600, 1.00, 1.00, 1.00) --, 0.00, 0.44, 0.87, 'enhsha') --Title of Settings Frame, Width, Height, ClassRGB, Rotation Name
-- Class colours
-- Death Knight 0.77 0.12 0.23 Red
-- Demon Hunter 0.64 0.19 0.79 Dark Magenta
-- Druid 1.00 0.49 0.04 Orange
-- Evoker 0.20 0.58 0.50 Dark Emerald
-- Hunter 0.67 0.83 0.45 Green
-- Mage 0.25 0.78 0.92 Light Blue
-- Monk 0.00 1.00 0.60 Spring Green
-- Paladin 0.96 0.55 0.73 Pink
-- Priest 1.00 1.00 1.00 White
-- Rogue 1.00 0.96 0.41 Yellow
-- Shaman 0.00 0.44 0.87 Blue
-- Warlock 0.53 0.53 0.93 Purple
-- Warrior 0.78 0.61 0.43 Tan

@ -775,7 +775,6 @@ local GrandMelee = Bastion.SpellBook:GetSpell(193358)
local Broadside = Bastion.SpellBook:GetSpell(193356) local Broadside = Bastion.SpellBook:GetSpell(193356)
local TrueBearing = Bastion.SpellBook:GetSpell(193359) local TrueBearing = Bastion.SpellBook:GetSpell(193359)
local RuthlessPrecision = Bastion.SpellBook:GetSpell(193357) local RuthlessPrecision = Bastion.SpellBook:GetSpell(193357)
local DeviousStratagem = Bastion.SpellBook:GetSpell(193531)
local SkullAndCrossbones = Bastion.SpellBook:GetSpell(199603) local SkullAndCrossbones = Bastion.SpellBook:GetSpell(199603)
local ShadowFocus = Bastion.SpellBook:GetSpell(108209) local ShadowFocus = Bastion.SpellBook:GetSpell(108209)
local BuriedTreasure = Bastion.SpellBook:GetSpell(199600) local BuriedTreasure = Bastion.SpellBook:GetSpell(199600)
@ -844,8 +843,7 @@ local FindWeakness = Bastion.SpellBook:GetSpell(91023)
local ImprovedShurikenStorm = Bastion.SpellBook:GetSpell(319951) local ImprovedShurikenStorm = Bastion.SpellBook:GetSpell(319951)
local RefreshingHealingPotion = Bastion.ItemBook:GetItem(191380)
local ElementalPotionOfPower = Bastion.ItemBook:GetItem(191389)
local IrideusFragment = Bastion.ItemBook:GetItem(193743) local IrideusFragment = Bastion.ItemBook:GetItem(193743)
local Healthstone = Bastion.ItemBook:GetItem(5512) local Healthstone = Bastion.ItemBook:GetItem(5512)
local WindscarWhetstone = Bastion.ItemBook:GetItem(137486) local WindscarWhetstone = Bastion.ItemBook:GetItem(137486)
@ -999,38 +997,6 @@ local FinishAPL = Bastion.APL:New('finish')
local BuildAPL = Bastion.APL:New('build') local BuildAPL = Bastion.APL:New('build')
local ItemsAPL = Bastion.APL:New('items') local ItemsAPL = Bastion.APL:New('items')
ItemsAPL:AddItem(
Healthstone:UsableIf(function(self)
return self:IsEquippedAndUsable() and
not Player:IsCastingOrChanneling() and
Player:GetHealthPercent() < 40
end):SetTarget(Player)
)
ItemsAPL:AddItem(
RefreshingHealingPotion:UsableIf(function(self)
return self:IsEquippedAndUsable() and
not Player:IsCastingOrChanneling() and
Player:GetHealthPercent() < 40
end):SetTarget(Player)
)
ItemsAPL:AddSpell(
TricksOfTheTrade:CastableIf(function(self)
return Tank:Exists() and self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and
Player:IsTanking(Target)
end):SetTarget(Tank)
)
ItemsAPL:AddSpell(
Evasion:CastableIf(function(self)
return self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and
Player:GetHealthPercent() < 40
end):SetTarget(Player)
)
ItemsAPL:AddItem( ItemsAPL:AddItem(
IrideusFragment:UsableIf(function(self) IrideusFragment:UsableIf(function(self)
return self:IsEquippedAndUsable() and return self:IsEquippedAndUsable() and
@ -1038,13 +1004,6 @@ ItemsAPL:AddItem(
end):SetTarget(Player) end):SetTarget(Player)
) )
ItemsAPL:AddItem(
ElementalPotionOfPower:UsableIf(function(self)
return self:IsEquippedAndUsable() and
not Player:IsCastingOrChanneling() and (Player:GetMeleeAttackers() > 2 or Target:IsBoss())
end):SetTarget(Player)
)
ItemsAPL:AddItem( ItemsAPL:AddItem(
WindscarWhetstone:UsableIf(function(self) WindscarWhetstone:UsableIf(function(self)
return Target:Exists() and Player:InMelee(Target) and self:IsEquippedAndUsable() and return Target:Exists() and Player:InMelee(Target) and self:IsEquippedAndUsable() and
@ -1110,7 +1069,7 @@ DefaultAPL:AddVariable(
'snd_condition', 'snd_condition',
function() function()
return Player:GetAuras():FindMy(SliceAndDice):IsUp() or return Player:GetAuras():FindMy(SliceAndDice):IsUp() or
Player:GetEnemies(10) >= ConsumeCPMax() Player:GetEnemies(10) >= Player:GetComboPointsMax()
end end
) )
@ -1207,7 +1166,7 @@ DefaultAPL:AddAPL(
DefaultAPL:AddSpell( DefaultAPL:AddSpell(
SliceAndDice:CastableIf( SliceAndDice:CastableIf(
function(self) function(self)
return self:IsKnownAndUsable() and Player:GetEnemies(10) < ConsumeCPMax() and return self:IsKnownAndUsable() and Player:GetEnemies(10) < Player:GetComboPointsMax() and
Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < Player:GetGCD() and Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < Player:GetGCD() and
Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() > 6 and Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() > 6 and
Player:GetComboPoints() >= 4 Player:GetComboPoints() >= 4
@ -1258,7 +1217,7 @@ DefaultAPL:AddAPL(
DefaultAPL:AddAPL( DefaultAPL:AddAPL(
FinishAPL, FinishAPL,
function() function()
return DefaultAPL:GetVariable('effective_combo_points') >= ConsumeCPMax() return DefaultAPL:GetVariable('effective_combo_points') >= Player:GetComboPointsMax()
end end
) )
@ -1346,9 +1305,9 @@ BuildAPL:AddSpell(
BuildAPL:AddVariable( BuildAPL:AddVariable(
'anima_helper', 'anima_helper',
function() function()
return not EchoingReprimand:IsKnown() or ((not (DefaultAPL:GetVariable('is_next_cp_animacharged') and return not EchoingReprimand:IsKnown() or (not (DefaultAPL:GetVariable('is_next_cp_animacharged') and
(Player:GetTimeToShurikenTornado(3) < 0.5 or Player:GetTimeToShurikenTornado(4) < 1) and (Player:GetTimeToShurikenTornado(3) < 0.5 or Player:GetTimeToShurikenTornado(4) < 1) and
Player:GetPower() < 60))) Player:GetPower() < 60))
end end
) )
@ -1388,8 +1347,7 @@ CDsAPL:AddSpell(
CDsAPL:AddSpell( CDsAPL:AddSpell(
SymbolsOfDeath:CastableIf( SymbolsOfDeath:CastableIf(
function(self) function(self)
return Player:IsAffectingCombat() and self:IsKnownAndUsable() and return self:IsKnownAndUsable() and Player:GetAuras():FindMy(ShurikenTornado):IsUp() and
Player:GetAuras():FindMy(ShurikenTornado):IsUp() and
Player:GetAuras():FindMy(ShurikenTornado):GetRemainingTime() <= 3.5 Player:GetAuras():FindMy(ShurikenTornado):GetRemainingTime() <= 3.5
end end
):SetTarget(Player) ):SetTarget(Player)
@ -1592,16 +1550,6 @@ FinishAPL:AddVariable(
end end
) )
-- return ( cp + 1 ) * p()->buffs.slice_and_dice->data().duration();
function GetTriggeredDuration()
return (Player:GetComboPoints() + 1) * 6
end
-- return p()->buffs.slice_and_dice->remains() < get_triggered_duration( as<int>( p()->current_effective_cp( false ) ) ) * 0.3;
function Refreshable(aura, target)
return target:GetAuras():FindMy(aura):GetRemainingTime() < GetTriggeredDuration() * 0.3
end
-- actions.finish+=/slice_and_dice,if=!variable.premed_snd_condition&spell_targets.shuriken_storm<6&!buff.shadow_dance.up&buff.slice_and_dice.remains<fight_remains&refreshable -- actions.finish+=/slice_and_dice,if=!variable.premed_snd_condition&spell_targets.shuriken_storm<6&!buff.shadow_dance.up&buff.slice_and_dice.remains<fight_remains&refreshable
FinishAPL:AddSpell( FinishAPL:AddSpell(
SliceAndDice:CastableIf( SliceAndDice:CastableIf(
@ -1610,7 +1558,7 @@ FinishAPL:AddSpell(
Player:GetEnemies(10) < 6 and Player:GetEnemies(10) < 6 and
not Player:GetAuras():FindMy(ShadowDanceAura):IsUp() and not Player:GetAuras():FindMy(ShadowDanceAura):IsUp() and
Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < Target:TimeToDie() and Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < Target:TimeToDie() and
Refreshable(SliceAndDice, Player) Player:GetAuras():FindMy(SliceAndDice):GetRemainingTime() < 6
end end
):SetTarget(Player) ):SetTarget(Player)
) )
@ -1649,7 +1597,7 @@ FinishAPL:AddSpell(
(not DefaultAPL:GetVariable('skip_rupture') or (not DefaultAPL:GetVariable('skip_rupture') or
DefaultAPL:GetVariable('priority_rotation')) and DefaultAPL:GetVariable('priority_rotation')) and
Target:TimeToDie() - Target:GetAuras():FindMy(Rupture):GetRemainingTime() > 6 and Target:TimeToDie() - Target:GetAuras():FindMy(Rupture):GetRemainingTime() > 6 and
Refreshable(Rupture, Target) Target:GetAuras():FindMy(Rupture):GetRemainingTime() < 6
end end
):SetTarget(Target) ):SetTarget(Target)
) )
@ -1706,7 +1654,7 @@ FinishAPL:AddSpell(
not DefaultAPL:GetVariable('priority_rotation') and not DefaultAPL:GetVariable('priority_rotation') and
Player:GetEnemies(10) >= 2 and Player:GetEnemies(10) >= 2 and
RuptureTarget:TimeToDie() >= (2 * Player:GetComboPoints()) and RuptureTarget:TimeToDie() >= (2 * Player:GetComboPoints()) and
Refreshable(Rupture, RuptureTarget) RuptureTarget:GetAuras():FindMy(Rupture):GetRemainingTime() < 6
end end
):SetTarget(RuptureTarget) ):SetTarget(RuptureTarget)
) )
@ -1913,25 +1861,11 @@ StealthedAPL:AddSpell(
):SetTarget(Target) ):SetTarget(Target)
) )
--[[
double consume_cp_max() const
{
return COMBO_POINT_MAX + as<double>( talent.rogue.deeper_stratagem->effectN( 2 ).base_value() +
talent.outlaw.devious_stratagem->effectN( 2 ).base_value() +
talent.subtlety.secret_stratagem->effectN( 2 ).base_value() );
}
]]
function ConsumeCPMax()
return 5 + (DeeperStratagem:IsKnownAndUsable() and 1 or 0) + (DeviousStratagem:IsKnownAndUsable() and 1 or 0) +
(SecretStratagem:IsKnownAndUsable() and 1 or 0)
end
-- actions.stealthed+=/call_action_list,name=finish,if=variable.effective_combo_points>=cp_max_spend -- actions.stealthed+=/call_action_list,name=finish,if=variable.effective_combo_points>=cp_max_spend
StealthedAPL:AddAPL( StealthedAPL:AddAPL(
FinishAPL, FinishAPL,
function(self) function(self)
return DefaultAPL:GetVariable('effective_combo_points') >= ConsumeCPMax() return DefaultAPL:GetVariable('effective_combo_points') >= Player:GetComboPointsMax()
end end
) )

@ -1,5 +1,4 @@
-- Create an APL trait for the APL class -- Create an APL trait for the APL class
---@class APLTrait
local APLTrait = {} local APLTrait = {}
APLTrait.__index = APLTrait APLTrait.__index = APLTrait
@ -30,7 +29,6 @@ function APLTrait:__tostring()
end end
-- Create an APL actor for the APL class -- Create an APL actor for the APL class
---@class APLActor
local APLActor = {} local APLActor = {}
APLActor.__index = APLActor APLActor.__index = APLActor
@ -118,7 +116,7 @@ function APLActor:__tostring()
end end
-- APL (Attack priority list) class -- APL (Attack priority list) class
---@class APL
local APL = {} local APL = {}
APL.__index = APL APL.__index = APL

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Aura class -- Create a new Aura class
---@class Aura
local Aura = {} local Aura = {}
function Aura:__index(k) function Aura:__index(k)
@ -18,19 +17,6 @@ function Aura:__index(k)
return response return response
end end
-- Equals
function Aura:__eq(other)
if getmetatable(other) == Aura then
return self:GetSpell():GetID() == other:GetSpell():GetID()
end
if getmetatable(other) == Bastion.Spell then
return self:GetSpell():GetID() == other:GetID()
end
return false
end
function Aura:__tostring() function Aura:__tostring()
return "Bastion.__Aura(" .. self:GetSpell():GetID() .. ")" .. " - " .. (self:GetName() or "''") return "Bastion.__Aura(" .. self:GetSpell():GetID() .. ")" .. " - " .. (self:GetName() or "''")
end end

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new AuraTable class -- Create a new AuraTable class
---@class AuraTable
local AuraTable = {} local AuraTable = {}
AuraTable.__index = AuraTable AuraTable.__index = AuraTable
@ -197,7 +196,6 @@ function AuraTable:Clear()
end end
-- Check if the unit has a specific aura -- Check if the unit has a specific aura
---@return Aura
function AuraTable:Find(spell) function AuraTable:Find(spell)
local auras = self:GetUnitAuras() local auras = self:GetUnitAuras()
local aurasub = auras[spell:GetID()] local aurasub = auras[spell:GetID()]
@ -219,7 +217,6 @@ function AuraTable:Find(spell)
return Bastion.Aura:New() return Bastion.Aura:New()
end end
---@return Aura
function AuraTable:FindMy(spell) function AuraTable:FindMy(spell)
local aurasub = self.playerAuras[spell:GetID()] local aurasub = self.playerAuras[spell:GetID()]
@ -241,7 +238,6 @@ function AuraTable:FindMy(spell)
end end
-- Find any -- Find any
---@return Aura
function AuraTable:FindAny(spell) function AuraTable:FindAny(spell)
local a = self:Find(spell) local a = self:Find(spell)
if a:IsValid() then if a:IsValid() then

@ -1,4 +1,3 @@
---@class Cache
local Cache = {} local Cache = {}
Cache.__index = Cache Cache.__index = Cache

@ -1,14 +1,10 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Define a Cacheable class -- Define a Cacheable class
---@class Cacheable
local Cacheable = { local Cacheable = {
cache = nil, cache = nil,
callback = nil, callback = nil,
value = nil, value = nil
__eq = function(self, other)
return self.value.__eq(self.value, other)
end
} }
-- On index check the cache to be valid and return the value or reconstruct the value and return it -- On index check the cache to be valid and return the value or reconstruct the value and return it

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Class class -- Create a new Class class
---@class Class
local Class = {} local Class = {}
function Class:__index(k) function Class:__index(k)

@ -1,8 +1,6 @@
---@class ClassMagic
local ClassMagic = {} local ClassMagic = {}
ClassMagic.__index = ClassMagic ClassMagic.__index = ClassMagic
---@return any
function ClassMagic:Resolve(Class, key) function ClassMagic:Resolve(Class, key)
if Class[key] or Class[key] == false then if Class[key] or Class[key] == false then
return Class[key] return Class[key]

@ -1,5 +1,5 @@
-- Create a wow command handler class -- Create a wow command handler class
---@class Command
local Command = {} local Command = {}
Command.__index = Command Command.__index = Command

@ -1,5 +1,5 @@
-- Create an EventManager class -- Create an EventManager class
---@class EventManager
local EventManager = { local EventManager = {
events = {}, events = {},
eventHandlers = {}, eventHandlers = {},

@ -1,13 +1,10 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
--local Common = Tinkr.Common
--local Exports = Tinkr:require('Routine.Modules.Exports') --local Command = Bastion.Command:New('bastion')
local Command = Tinkr.Util.Commands:New('rex')
--local OM = Tinkr.Util.ObjectManager
--UI Co-ordinates --UI Co-ordinates
local GUI = { points = {"CENTER"}, } local GUI = { points = {"CENTER"}, }
local SETTINGS = { points = {"CENTER"}, } local SETTINGS = { points = {"CENTER"}, }
local ESP = { points = {"CENTER"}, }
local BUTTONS = { points = {"CENTER"}, } local BUTTONS = { points = {"CENTER"}, }
Tinkr:require('scripts.bastion.libs.LibStub.LibStub', Bastion) Tinkr:require('scripts.bastion.libs.LibStub.LibStub', Bastion)
@ -38,28 +35,14 @@ Tinkr:require("scripts.bastion.libs.StdUi.widgets.Tab", Bastion)
Tinkr:require("scripts.bastion.libs.StdUi.widgets.Spell", Bastion) Tinkr:require("scripts.bastion.libs.StdUi.widgets.Spell", Bastion)
Tinkr:require("scripts.bastion.libs.StdUi.widgets.ContextMenu", Bastion) Tinkr:require("scripts.bastion.libs.StdUi.widgets.ContextMenu", Bastion)
-- Class colours
-- Death Knight 0.77 0.12 0.23 Red
-- Demon Hunter 0.64 0.19 0.79 Dark Magenta
-- Druid 1.00 0.49 0.04 Orange
-- Hunter 0.67 0.83 0.45 Green
-- Mage 0.25 0.78 0.92 Light Blue
-- Monk 0.00 1.00 0.60 Spring Green
-- Paladin 0.96 0.55 0.73 Pink
-- Priest 1.00 1.00 1.00 White
-- Rogue 1.00 0.96 0.41 Yellow
-- Shaman 0.00 0.44 0.87 Blue
-- Warlock 0.53 0.53 0.93 Purple
-- Warrior 0.78 0.61 0.43 Tan
--Initial Frame Setup --Initial Frame Setup
function Bastion.setupsettingsframe(config, title, width, height, newr, newg, newb) function Bastion.settingstemplate(config, title, width, height, newr, newg, newb)
local StdUi = LibStub('StdUi'):NewInstance() local StdUi = LibStub('StdUi'):NewInstance()
StdUi.config = { StdUi.config = {
font = { font = {
family = 'GameFontNormal', family = 'GameFontNormal',
size = 10, size = 10,
titleSize = 12, titleSize = 10,
effect = 'NONE', effect = 'NONE',
strata = 'OVERLAY', strata = 'OVERLAY',
color = { color = {
@ -100,7 +83,6 @@ function Bastion.setupsettingsframe(config, title, width, height, newr, newg, ne
local settingsframe = StdUi:Window(UIParent, width, height, title) local settingsframe = StdUi:Window(UIParent, width, height, title)
settingsframe:Hide() settingsframe:Hide()
settingsframe:SetPoint(SETTINGS.points[1], SETTINGS.points[2], SETTINGS.points[3], SETTINGS.points[4], SETTINGS.points[5]) settingsframe:SetPoint(SETTINGS.points[1], SETTINGS.points[2], SETTINGS.points[3], SETTINGS.points[4], SETTINGS.points[5])
--settingsframe:SetFont(StdUi.config.font.family,StdUi.config.font.titleSize)
StdUi:BuildWindow(settingsframe, config) StdUi:BuildWindow(settingsframe, config)
StdUi:EasyLayout(settingsframe, { padding = { top = 40 } }) StdUi:EasyLayout(settingsframe, { padding = { top = 40 } })
settingsframe:SetScript("OnMouseUp", function(self) settingsframe:SetScript("OnMouseUp", function(self)
@ -109,12 +91,9 @@ function Bastion.setupsettingsframe(config, title, width, height, newr, newg, ne
SETTINGS.points = {a, nil, c, d, e} SETTINGS.points = {a, nil, c, d, e}
end) end)
--Main Menu (Settings, Enable Rotation, ESP, Buttons) --Main Menu (Settings, Enable Rotation, etc)
_G.buttons = {} _G.buttons = {}
local enabled = false local enabled = false
local espenabled = false
local espunitsenabled = false
local espobjectsenabled = false
buttons.aoeenabled = false buttons.aoeenabled = false
buttons.buffsenabled = false buttons.buffsenabled = false
buttons.cooldownsenabled = false buttons.cooldownsenabled = false
@ -122,10 +101,9 @@ function Bastion.setupsettingsframe(config, title, width, height, newr, newg, ne
buttons.dpsenabled = false buttons.dpsenabled = false
buttons.healenabled = false buttons.healenabled = false
buttons.rotationenabled = false buttons.rotationenabled = false
local mainmenu = StdUi:Window(nil, 150, 310, title) _G.mainmenu = StdUi:Window(nil, 150, 280, title)
mainmenu:Hide() mainmenu:Hide()
mainmenu:SetPoint(GUI.points[1], GUI.points[2], GUI.points[3], GUI.points[4], GUI.points[5]) mainmenu:SetPoint(GUI.points[1], GUI.points[2], GUI.points[3], GUI.points[4], GUI.points[5])
--mainmenu:SetFont(StdUi.config.font.family,StdUi.config.font.titleSize)
mainmenu:SetUserPlaced(true) mainmenu:SetUserPlaced(true)
local aoebutton = StdUi:HighlightButton(mainmenu, 130, 20, 'AOE') local aoebutton = StdUi:HighlightButton(mainmenu, 130, 20, 'AOE')
StdUi:GlueTop(aoebutton, mainmenu, 10, -40, 'LEFT') StdUi:GlueTop(aoebutton, mainmenu, 10, -40, 'LEFT')
@ -141,32 +119,13 @@ function Bastion.setupsettingsframe(config, title, width, height, newr, newg, ne
StdUi:GlueTop(healbutton, dpsbutton, 0, -30, 'LEFT') StdUi:GlueTop(healbutton, dpsbutton, 0, -30, 'LEFT')
local enablebutton = StdUi:HighlightButton(mainmenu, 130, 20, 'Rotation') local enablebutton = StdUi:HighlightButton(mainmenu, 130, 20, 'Rotation')
StdUi:GlueTop(enablebutton, healbutton, 0, -30, 'LEFT') StdUi:GlueTop(enablebutton, healbutton, 0, -30, 'LEFT')
local espbutton = StdUi:Button(mainmenu, 130, 20, 'Open ESP')
StdUi:GlueTop(espbutton, enablebutton, 0, -30, 'LEFT')
local settingsbutton = StdUi:Button(mainmenu, 130, 20, 'Settings') local settingsbutton = StdUi:Button(mainmenu, 130, 20, 'Settings')
StdUi:GlueTop(settingsbutton, espbutton, 0, -30, 'LEFT') StdUi:GlueTop(settingsbutton, enablebutton, 0, -30, 'LEFT')
mainmenu:SetScript("OnMouseUp", function(self) mainmenu:SetScript("OnMouseUp", function(self)
self:StopMovingOrSizing() self:StopMovingOrSizing()
local a,b,c,d,e = self:GetPoint() local a,b,c,d,e = self:GetPoint()
GUI.points = {a, nil, c, d, e} GUI.points = {a, nil, c, d, e}
end) end)
--ESP Menu
local espmenu = StdUi:Window(nil, 200, 140, 'ESP Settings')
espmenu:Hide()
espmenu:SetPoint(ESP.points[1], ESP.points[2], ESP.points[3], ESP.points[4], ESP.points[5])
--espmenu:SetFont(StdUi.config.font.family,StdUi.config.font.titleSize)
espmenu:SetUserPlaced(true)
local enableespcheck = StdUi:Button(espmenu, 180, 20, 'Enable/Disable ESP');
StdUi:GlueTop(enableespcheck, espmenu, 10, -40, 'LEFT');
local espunitscheck = StdUi:Button(espmenu, 180, 20, 'Show Units');
StdUi:GlueTop(espunitscheck, enableespcheck, 0, -30, 'LEFT');
local espobjectscheck = StdUi:Button(espmenu, 180, 20, 'Show Objects');
StdUi:GlueTop(espobjectscheck, espunitscheck, 0, -30, 'LEFT');
espmenu:SetScript("OnMouseUp", function(self)
self:StopMovingOrSizing()
local a,b,c,d,e = self:GetPoint()
ESP.points = {a, nil, c, d, e}
end)
--Open/Hide Settings Window OnClick --Open/Hide Settings Window OnClick
settingsbutton:SetScript('OnClick', function () settingsbutton:SetScript('OnClick', function ()
if settingsframe:IsShown() then if settingsframe:IsShown() then
@ -175,48 +134,6 @@ function Bastion.setupsettingsframe(config, title, width, height, newr, newg, ne
settingsframe:Show() settingsframe:Show()
end end
end) end)
--Enable/Disable Rotation OnClick
enablebutton:SetScript('OnClick', function ()
if enabled == false then
Eval('RunMacroText("/bastion toggle")', 'bastion')
enabled = true
elseif enabled == true then
Eval('RunMacroText("/bastion toggle")', 'bastion')
enabled = false
end
end)
--Open/Hide ESP Window OnClick
espbutton:SetScript('OnClick', function ()
if espmenu:IsShown() then
espmenu:Hide()
else
espmenu:Show()
end
end)
--Enable/Disable ESP Draw OnClick
enableespcheck:SetScript('OnClick', function ()
if espenabled == false then
rexesp('enable', nil, nil)
espenabled = true
elseif espenabled == true then
rexesp('disable', nil, nil)
espenabled = false
end
end)
--Enable/Disable ESP Units OnClick
espunitscheck:SetScript('OnClick', function ()
if espunitsenabled == false then
rexesp(nil, 'unitenable', nil)
espunitsenabled = true
end
end)
--Enable/Disable ESP Objects OnClick
espobjectscheck:SetScript('OnClick', function ()
if espobjectsenabled == false then
rexesp(nil, nil, 'objectenable')
espobjectsenabled = true
end
end)
--Enable/Disable AOE Button OnClick --Enable/Disable AOE Button OnClick
aoebutton:SetScript('OnClick', function() aoebutton:SetScript('OnClick', function()
if buttons.aoeenabled == false then if buttons.aoeenabled == false then
@ -289,13 +206,13 @@ function Bastion.setupsettingsframe(config, title, width, height, newr, newg, ne
buttons.rotationenabled = false buttons.rotationenabled = false
end end
end) end)
--Toggle Main Menu -- --Toggle Main Menu
Command:Register({'open'}, function() -- Command:Register('interface', 'Opens interface menu', function()
if mainmenu:IsShown() then -- if mainmenu:IsShown() then
mainmenu:Hide() -- mainmenu:Hide()
else -- else
mainmenu:Show() -- mainmenu:Show()
end -- end
end) -- end)
end end

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Item class -- Create a new Item class
---@class Item
local Item = { local Item = {
UsableIfFunc = false, UsableIfFunc = false,
PreUseFunc = false, PreUseFunc = false,
@ -30,11 +29,6 @@ function Item:__index(k)
return response return response
end end
-- Equals
function Item:__eq(other)
return self:GetID() == other:GetID()
end
-- tostring -- tostring
function Item:__tostring() function Item:__tostring()
return "Bastion.__Item(" .. self:GetID() .. ")" .. " - " .. self:GetName() return "Bastion.__Item(" .. self:GetID() .. ")" .. " - " .. self:GetName()
@ -176,21 +170,18 @@ function Item:Usable()
end end
-- Set a script to check if the Item is Usable -- Set a script to check if the Item is Usable
---@param func fun(self:Item):boolean
function Item:UsableIf(func) function Item:UsableIf(func)
self.UsableIfFunc = func self.UsableIfFunc = func
return self return self
end end
-- Set a script to run before the Item has been Use -- Set a script to run before the Item has been Use
---@param func fun(self:Item)
function Item:PreUse(func) function Item:PreUse(func)
self.PreUseFunc = func self.PreUseFunc = func
return self return self
end end
-- Set a script to run after the Item has been Use -- Set a script to run after the Item has been Use
---@param func fun(self:Item)
function Item:OnUse(func) function Item:OnUse(func)
self.OnUseFunc = func self.OnUseFunc = func
return self return self
@ -287,8 +278,6 @@ function Item:GetChargesRemaining()
end end
-- Create a condition for the Item -- Create a condition for the Item
---@param name string
---@param func fun(self:Item)
function Item:Condition(name, func) function Item:Condition(name, func)
self.conditions[name] = { self.conditions[name] = {
func = func func = func

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new ItemBook class -- Create a new ItemBook class
---@class ItemBook
local ItemBook = {} local ItemBook = {}
ItemBook.__index = ItemBook ItemBook.__index = ItemBook
@ -13,7 +12,6 @@ function ItemBook:New()
end end
-- Get a spell from the ItemBook -- Get a spell from the ItemBook
---@return Item
function ItemBook:GetItem(id) function ItemBook:GetItem(id)
if self.items[id] == nil then if self.items[id] == nil then
self.items[id] = Bastion.Item:New(id) self.items[id] = Bastion.Item:New(id)

@ -1,6 +1,5 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
---@class List
local List = {} local List = {}
List.__index = List List.__index = List

@ -1,6 +1,5 @@
-- Create a module class for a bastion module -- Create a module class for a bastion module
---@class Module
local Module = {} local Module = {}
Module.__index = Module Module.__index = Module

@ -1,6 +1,5 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
---@class MythicPlusUtils
local MythicPlusUtils = { local MythicPlusUtils = {
debuffLogging = false, debuffLogging = false,
random = '' random = ''
@ -13,71 +12,117 @@ function MythicPlusUtils:New()
self.random = math.random(1000000, 9999999) self.random = math.random(1000000, 9999999)
self.kickList = { self.kickList = {
-- Algeth'ar Academy -- Algeth'ar Academy
[396812] = true, -- https://www.wowhead.com/spell=396812/mystic-blast [388392] = true, -- Monotonous Lecture
[388392] = true, -- https://www.wowhead.com/spell=388392/monotonous-lecture [396812] = true, -- Mystic Blast
[388863] = true, -- https://www.wowhead.com/spell=388863/mana-void [377389] = true, -- Call of the Flock
[388862] = true, -- https://www.wowhead.com/spell=388862/surge [396640] = true, -- Healing Touch
[377389] = true, -- https://www.wowhead.com/spell=377389/call-of-the-flock [387843] = true, -- Astral Bomb
[388623] = true, -- https://www.wowhead.com/spell=388623/branch-out [387955] = true, -- Celestial Shield
[396640] = true, -- https://www.wowhead.com/spell=396640/healing-touch [387910] = true, -- Astral Whirlwind
[387975] = true, -- https://www.wowhead.com/spell=387975/arcane-missiles
[387843] = true, -- https://www.wowhead.com/spell=387843/astral-bomb -- Azure Vault
-- [375602] = true, -- Erratic Growth
[387564] = true, -- Mystic Vapors
-- [386546] = true, -- Waking Bane
[389804] = true, -- Heavy Tome
[377488] = true, -- Icy Bindings
-- Brackenhide
[382249] = true, -- Earth Bolt
[367500] = true, -- Hideous Cackle
[377950] = true, -- Greater Healing Rapids
[385029] = true, -- Screech
[373804] = true, -- Touch of Decay
[381770] = true, -- Gushing Ooze
[374544] = true, -- Burst of Decay
-- Halls of Infusion
[374066] = true, -- Earth Shield
[374339] = true, -- Demoralizing Shout
[374045] = true, -- Expulse
[374080] = true, -- Blasting Gust
[389443] = true, -- Purifying Blast
[395694] = true, -- Elemental Focus
[374563] = true, -- Dazzle
[385141] = true, -- Thunderstorm
[374706] = true, -- Pyretic Burst
[375384] = true, -- Rumbling Earth
[375950] = true, -- Ice Shards
[377348] = true, -- Tidal Divergence
[377402] = true, -- Aqueous Barrier
[387618] = true, -- Infuse
-- Neltharus
[378282] = true, -- Molten Core
[372615] = true, -- Ember Reach
[395427] = true, -- Burning Roar
[372538] = true, -- Melt
[384161] = true, -- Mote of Combustion
[382795] = true, -- Molten Barrier
-- Nokhud
[384365] = true, -- Disruptive Shout
[386024] = true, -- Tempest
[387411] = true, -- Death Bolt Volley
[387606] = true, -- Dominate
[376725] = true, -- Storm Bolt
[384808] = true, -- Guardian Wind
[383823] = true, -- Rally the Clan (CC to interrupt)
[387135] = true, -- Arcing Strike (CC to interrupt)
[373395] = true, -- Bloodcurdling Shout
-- Ruby Life Pools
[373017] = true, -- Roaring Blaze
[392398] = true, -- Crackling Detonation
[392451] = true, -- Flashfire
[385310] = true, -- Lightning Bolt
[375602] = true, -- Erratic Growth
-- [386546] = true, -- Waking Bane
-- [387564] = true, -- Mystic Vapors
[373932] = true, -- Illusionary Bolt
[386546] = true, -- Waking Bane
-- Uldaman
[369675] = true, -- Chain Lightning
[369674] = true, -- Stone Spike
[369823] = true, -- Spiked Carapace
[369603] = true, -- Defensive Bulwark
[369399] = true, -- Stone Bolt
[369400] = true, -- Earthen Ward
-- Court of Stars -- Court of Stars
[211401] = true, -- https://wowhead.com/spell=211401 [211401] = true, -- Drifting Embers
[207980] = true, -- https://wowhead.com/spell=207980 [211464] = true, -- Fel Detonation
[208165] = true, -- https://wowhead.com/spell=208165 [207980] = true, -- Disintegration Beam
[207881] = true, -- https://wowhead.com/spell=207881 [208165] = true, -- Withering Soul
[209413] = true, -- https://wowhead.com/spell=209413 [207881] = true, -- Infernal Eruption
-- Halls of Valor -- Halls of Valor
[198595] = true, -- https://wowhead.com/spell=198595 [198595] = true, -- Thunderous Bolt
[198959] = true, -- https://wowhead.com/spell=198959 [198959] = true, -- Etch
[215433] = true, -- https://wowhead.com/spell=215433 [192288] = true, -- Searing Light
[192288] = true, -- https://wowhead.com/spell=192288 [199726] = true, -- Unruly Yell
[199726] = true, -- https://wowhead.com/spell=199726 [198750] = true, -- Surge
[198750] = true, -- https://wowhead.com/spell=198750
-- Ruby Life Pools
[372749] = true, -- https://wowhead.com/spell=372749
[373803] = true, -- https://wowhead.com/spell=373803
[373017] = true, -- https://wowhead.com/spell=373017
[392398] = true, -- https://wowhead.com/spell=392398
[392451] = true, -- https://wowhead.com/spell=392451
[385310] = true, -- https://wowhead.com/spell=385310
-- Shadowmoon Burial Grounds -- Shadowmoon Burial Grounds
[152818] = true, -- https://wowhead.com/spell=152818 [152818] = true, -- Shadow Mend
[156776] = true, -- https://wowhead.com/spell=156776 [153153] = true, -- Dark Communion (CC to interrupt)
[156722] = true, -- https://wowhead.com/spell=156722 [156776] = true, -- Rending Voidlash
[398206] = true, -- https://wowhead.com/spell=398206 [156722] = true, -- Void Bolt
[153524] = true, -- https://wowhead.com/spell=153524 [398206] = true, -- Death Blast
[156718] = true, -- https://wowhead.com/spell=156718 [156718] = true, -- Necrotic Burst
[153524] = true, -- Plague Spit
-- Temple of the Jade Serpent -- Temple of the Jade Serpent
[397888] = true, -- https://wowhead.com/spell=397888 [397888] = true, -- Hydrolance
[395859] = true, -- https://wowhead.com/spell=395859 [114646] = true, -- Haunting Gaze
[396073] = true, -- https://wowhead.com/spell=396073 [395859] = true, -- Haunting Scream
[397914] = true, -- https://wowhead.com/spell=397914 [396073] = true, -- Cat Nap
[397914] = true, -- Defiling Mist
-- The Azure Vault
[375602] = true, -- https://wowhead.com/spell=375602 [315584] = true
[387564] = true, -- https://wowhead.com/spell=387564
[373932] = true, -- https://wowhead.com/spell=373932
[386546] = true, -- https://wowhead.com/spell=386546
[389804] = true, -- https://wowhead.com/spell=389804
[377488] = true, -- https://wowhead.com/spell=377488
[377503] = true, -- https://wowhead.com/spell=377503
-- NO
[384365] = true, -- https://wowhead.com/spell=384365
[386012] = true, -- https://wowhead.com/spell=386012
[386024] = true, -- https://wowhead.com/spell=386024
[387411] = true, -- https://wowhead.com/spell=387411
[387606] = true, -- https://wowhead.com/spell=387606
[373395] = true, -- https://wowhead.com/spell=373395
[376725] = true, -- https://wowhead.com/spell=376725
} }
Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras) Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)

@ -1,6 +1,5 @@
-- Create a NotificationsList class -- Create a NotificationsList class
---@class NotificationsList
local NotificationsList = { local NotificationsList = {
notifications = {} notifications = {}
} }
@ -12,14 +11,14 @@ function NotificationsList:New()
-- Create a frame for the notifications -- Create a frame for the notifications
self.frame = CreateFrame("Frame", "BastionNotificationsList", UIParent) self.frame = CreateFrame("Frame", "BastionNotificationsList", UIParent)
self.frame:SetSize(600, 60) self.frame:SetSize(300, 100)
self.frame:SetPoint("TOP", UIParent, "TOP", 0, -100) self.frame:SetPoint("TOP", UIParent, "TOP", 0, -100)
self.frame:SetFrameStrata("HIGH") self.frame:SetFrameStrata("HIGH")
-- Remove notifications after 5 seconds -- Remove notifications after 5 seconds
C_Timer.NewTicker(0.1, function() C_Timer.NewTicker(0.1, function()
for i, notification in ipairs(self.notifications) do for i, notification in ipairs(self.notifications) do
if GetTime() - notification.addedAt > notification.duration then if GetTime() - notification.addedAt > 2 then
notification:Remove() notification:Remove()
table.remove(self.notifications, i) table.remove(self.notifications, i)
end end
@ -30,21 +29,18 @@ function NotificationsList:New()
end end
-- Create a notification class for the notifications list (takes icon and text) -- Create a notification class for the notifications list (takes icon and text)
---@class Notification
local Notification = { local Notification = {
} }
Notification.__index = Notification Notification.__index = Notification
-- Constructor -- Constructor
function Notification:New(list, icon, text, duration) function Notification:New(list, icon, text)
local self = setmetatable({}, Notification) local self = setmetatable({}, Notification)
if not duration then duration = 2 end
-- Create a frame for the notification -- Create a frame for the notification
self.frame = CreateFrame("Frame", nil, list.frame) self.frame = CreateFrame("Frame", nil, list.frame)
self.frame:SetSize(5, 5) self.frame:SetSize(300, 100)
self.frame:SetPoint("CENTER", list.frame, "CENTER", 0, 0) self.frame:SetPoint("TOP", list.frame, "TOP", 0, 0)
self.frame:SetFrameStrata("HIGH") self.frame:SetFrameStrata("HIGH")
-- Create a texture for the icon -- Create a texture for the icon
@ -54,16 +50,12 @@ function Notification:New(list, icon, text, duration)
self.icon:SetTexture(icon) self.icon:SetTexture(icon)
-- Create a fontstring for the text -- Create a fontstring for the text
self.text = self.frame:CreateFontString(nil, "BACKGROUND", "NumberFontNormal") self.text = self.frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
self.text:SetPoint("LEFT", self.frame, "LEFT", 32 + 16, 0) self.text:SetPoint("CENTER", self.frame, "CENTER", 10, 0)
self.text:SetText(text) self.text:SetText(text)
self.text:SetFont("Fonts\\OpenSans-Bold.ttf", 18) self.text:SetFont("Fonts\\FRIZQT__.TTF", 14)
-- set the frame size to the size of the text + icon
self.frame:SetSize(self.text:GetStringWidth() + 32 + 16, 32)
self.addedAt = GetTime() self.addedAt = GetTime()
self.duration = duration
self.list = list self.list = list
return self return self
@ -83,9 +75,9 @@ function Notification:Remove()
end end
-- Add a notification to the list -- Add a notification to the list
function NotificationsList:AddNotification(icon, text, duration) function NotificationsList:AddNotification(icon, text)
-- Create a new notification -- Create a new notification
local notification = Notification:New(self, icon, text, duration) local notification = Notification:New(self, icon, text)
-- Add the notification to the list -- Add the notification to the list
table.insert(self.notifications, notification) table.insert(self.notifications, notification)
@ -100,7 +92,7 @@ function NotificationsList:Update()
-- Loop through the notifications -- Loop through the notifications
for i, notification in ipairs(self.notifications) do for i, notification in ipairs(self.notifications) do
-- Set the position of the notification -- Set the position of the notification
notification.frame:SetPoint("CENTER", self.frame, "CENTER", 0, -42 * (i - 1)) notification.frame:SetPoint("TOP", self.frame, "TOP", 0, -50 * (i - 1))
end end
end end

@ -1,6 +1,5 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
---@class ObjectManager
local ObjectManager = {} local ObjectManager = {}
ObjectManager.__index = ObjectManager ObjectManager.__index = ObjectManager

@ -1,14 +1,10 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Define a Refreshable class -- Define a Refreshable class
---@class Refreshable
local Refreshable = { local Refreshable = {
cache = nil, cache = nil,
callback = nil, callback = nil,
value = nil, value = nil
__eq = function(self, other)
return self.value.__eq(self.value, other)
end
} }
-- On index check the cache to be valid and return the value or reconstruct the value and return it -- On index check the cache to be valid and return the value or reconstruct the value and return it

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Spell class -- Create a new Spell class
---@class Spell
local Spell = { local Spell = {
CastableIfFunc = false, CastableIfFunc = false,
PreCastFunc = false, PreCastFunc = false,
@ -31,11 +30,6 @@ function Spell:__index(k)
return response return response
end end
-- Equals
function Spell:__eq(other)
return self:GetID() == other:GetID()
end
-- tostring -- tostring
function Spell:__tostring() function Spell:__tostring()
return "Bastion.__Spell(" .. self:GetID() .. ")" .. " - " .. self:GetName() return "Bastion.__Spell(" .. self:GetID() .. ")" .. " - " .. self:GetName()
@ -56,7 +50,6 @@ function Spell:GetID()
end end
-- Add post cast func -- Add post cast func
---@param func fun(self:Spell)
function Spell:PostCast(func) function Spell:PostCast(func)
self.PostCastFunc = func self.PostCastFunc = func
return self return self
@ -180,21 +173,18 @@ function Spell:Castable()
end end
-- Set a script to check if the spell is castable -- Set a script to check if the spell is castable
---@param func fun(spell:Spell):boolean
function Spell:CastableIf(func) function Spell:CastableIf(func)
self.CastableIfFunc = func self.CastableIfFunc = func
return self return self
end end
-- Set a script to run before the spell has been cast -- Set a script to run before the spell has been cast
---@param func fun(spell:Spell)
function Spell:PreCast(func) function Spell:PreCast(func)
self.PreCastFunc = func self.PreCastFunc = func
return self return self
end end
-- Set a script to run after the spell has been cast -- Set a script to run after the spell has been cast
---@param func fun(spell:Spell)
function Spell:OnCast(func) function Spell:OnCast(func)
self.OnCastFunc = func self.OnCastFunc = func
return self return self

@ -1,12 +1,10 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new SpellBook class -- Create a new SpellBook class
---@class SpellBook
local SpellBook = {} local SpellBook = {}
SpellBook.__index = SpellBook SpellBook.__index = SpellBook
-- Constructor -- Constructor
---@return SpellBook
function SpellBook:New() function SpellBook:New()
local self = setmetatable({}, SpellBook) local self = setmetatable({}, SpellBook)
self.spells = {} self.spells = {}
@ -14,7 +12,6 @@ function SpellBook:New()
end end
-- Get a spell from the spellbook -- Get a spell from the spellbook
---@return Spell
function SpellBook:GetSpell(id) function SpellBook:GetSpell(id)
if self.spells[id] == nil then if self.spells[id] == nil then
self.spells[id] = Bastion.Spell:New(id) self.spells[id] = Bastion.Spell:New(id)
@ -23,7 +20,6 @@ function SpellBook:GetSpell(id)
return self.spells[id] return self.spells[id]
end end
---@return Spell
function SpellBook:GetIfRegistered(id) function SpellBook:GetIfRegistered(id)
return self.spells[id] return self.spells[id]
end end

@ -1,7 +1,6 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Timer class -- Create a new Timer class
---@class Timer
local Timer = { local Timer = {
startTime = nil, startTime = nil,
resetAfterCombat = false, resetAfterCombat = false,

@ -1,12 +1,9 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Unit class -- Create a new Unit class
---@class Unit
local Unit = { local Unit = {
cache = nil, cache = nil,
---@type AuraTable
aura_table = nil, aura_table = nil,
---@type Unit
unit = nil, unit = nil,
last_shadow_techniques = 0, last_shadow_techniques = 0,
swings_since_sht = 0, swings_since_sht = 0,
@ -28,11 +25,6 @@ function Unit:__index(k)
return response return response
end end
-- Equals
function Unit:__eq(other)
return UnitIsUnit(self.unit, other.unit)
end
-- tostring -- tostring
function Unit:__tostring() function Unit:__tostring()
return "Bastion.__Unit(" .. tostring(self.unit) .. ")" .. " - " .. (self:GetName() or '') return "Bastion.__Unit(" .. tostring(self.unit) .. ")" .. " - " .. (self:GetName() or '')
@ -224,7 +216,12 @@ end
-- Get if the unit is affecting combat -- Get if the unit is affecting combat
function Unit:IsAffectingCombat() function Unit:IsAffectingCombat()
return UnitAffectingCombat(self.unit) return UnitAffectingCombat('player', self.unit)
end
-- Is the unit indoors
function Unit:IsIndoors()
return IsIndoors()
end end
-- Get the units class id -- Get the units class id
@ -234,7 +231,6 @@ function Unit:GetClass()
end end
-- Get the units auras -- Get the units auras
---@return AuraTable
function Unit:GetAuras() function Unit:GetAuras()
return self.aura_table return self.aura_table
end end

@ -48,7 +48,6 @@ local function Validate(token)
end end
-- Create a new UnitManager class -- Create a new UnitManager class
---@class UnitManager
local UnitManager = { local UnitManager = {
units = {}, units = {},
customUnits = {}, customUnits = {},
@ -109,7 +108,6 @@ function UnitManager:Validate(token)
end end
-- Get or create a unit -- Get or create a unit
---@return Unit
function UnitManager:Get(token) function UnitManager:Get(token)
-- if not Validate(token) then -- if not Validate(token) then
-- error("UnitManager:Get - Invalid token: " .. token) -- error("UnitManager:Get - Invalid token: " .. token)
@ -147,9 +145,6 @@ function UnitManager:SetObject(unit)
end end
-- Create a custom unit and cache it for .5 seconds -- Create a custom unit and cache it for .5 seconds
---@param token string
---@param cb fun():Unit
---@return Unit
function UnitManager:CreateCustomUnit(token, cb) function UnitManager:CreateCustomUnit(token, cb)
local unit = cb() local unit = cb()
local cachedUnit = Bastion.Cacheable:New(unit, cb) local cachedUnit = Bastion.Cacheable:New(unit, cb)
@ -180,7 +175,6 @@ function UnitManager:EnumFriends(cb)
end end
-- Enum Enemies (object manager) -- Enum Enemies (object manager)
---@param cb fun(unit: Unit):boolean
function UnitManager:EnumEnemies(cb) function UnitManager:EnumEnemies(cb)
Bastion.ObjectManager.activeEnemies:each(function(unit) Bastion.ObjectManager.activeEnemies:each(function(unit)
if cb(unit) then if cb(unit) then

@ -1,6 +1,5 @@
-- Create a Vector3 class -- Create a Vector3 class
---@class Vector3
local Vector3 = {} local Vector3 = {}
Vector3.__index = Vector3 Vector3.__index = Vector3

@ -1,6 +1,5 @@
local Tinkr = ... local Tinkr = ...
---@class Bastion
local Bastion = { local Bastion = {
DebugMode = false DebugMode = false
} }
@ -10,54 +9,31 @@ function Bastion.require(class)
return Tinkr:require("scripts/bastion/src/" .. class .. "/" .. class, Bastion) return Tinkr:require("scripts/bastion/src/" .. class .. "/" .. class, Bastion)
end end
---@type ClassMagic
Bastion.ClassMagic = Bastion.require("ClassMagic") Bastion.ClassMagic = Bastion.require("ClassMagic")
---@type List
Bastion.List = Bastion.require("List") Bastion.List = Bastion.require("List")
---@type NotificationsList, Notification
Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList") Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList")
---@type Vector3
Bastion.Vector3 = Bastion.require("Vector3") Bastion.Vector3 = Bastion.require("Vector3")
---@type Command
Bastion.Command = Bastion.require("Command") Bastion.Command = Bastion.require("Command")
---@type Cache
Bastion.Cache = Bastion.require("Cache") Bastion.Cache = Bastion.require("Cache")
---@type Cacheable
Bastion.Cacheable = Bastion.require("Cacheable") Bastion.Cacheable = Bastion.require("Cacheable")
---@type Refreshable
Bastion.Refreshable = Bastion.require("Refreshable") Bastion.Refreshable = Bastion.require("Refreshable")
---@type Unit
Bastion.Unit = Bastion.require("Unit") Bastion.Unit = Bastion.require("Unit")
---@type Aura
Bastion.Aura = Bastion.require("Aura") Bastion.Aura = Bastion.require("Aura")
---@type APL, APLActor, APLTrait
Bastion.APL, Bastion.APLActor, Bastion.APLTrait = Bastion.require("APL") Bastion.APL, Bastion.APLActor, Bastion.APLTrait = Bastion.require("APL")
Bastion.Module = Bastion.require("Module") Bastion.Module = Bastion.require("Module")
---@type UnitManager
Bastion.UnitManager = Bastion.require("UnitManager"):New() Bastion.UnitManager = Bastion.require("UnitManager"):New()
---@type ObjectManager
Bastion.ObjectManager = Bastion.require("ObjectManager"):New() Bastion.ObjectManager = Bastion.require("ObjectManager"):New()
---@type EventManager
Bastion.EventManager = Bastion.require("EventManager"):New() Bastion.EventManager = Bastion.require("EventManager"):New()
---@type Spell
Bastion.Spell = Bastion.require("Spell") Bastion.Spell = Bastion.require("Spell")
---@type SpellBook
Bastion.SpellBook = Bastion.require("SpellBook"):New() Bastion.SpellBook = Bastion.require("SpellBook"):New()
---@type Item
Bastion.Item = Bastion.require("Item") Bastion.Item = Bastion.require("Item")
---@type ItemBook
Bastion.ItemBook = Bastion.require("ItemBook"):New() Bastion.ItemBook = Bastion.require("ItemBook"):New()
---@type AuraTable
Bastion.AuraTable = Bastion.require("AuraTable") Bastion.AuraTable = Bastion.require("AuraTable")
---@type Class
Bastion.Class = Bastion.require("Class") Bastion.Class = Bastion.require("Class")
---@type Timer
Bastion.Timer = Bastion.require("Timer") Bastion.Timer = Bastion.require("Timer")
---@type Timer Bastion.Gui = Bastion.require("Gui")
Bastion.CombatTimer = Bastion.Timer:New('combat') Bastion.CombatTimer = Bastion.Timer:New('combat')
---@type MythicPlusUtils
Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New() Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New()
---@type NotificationsList
Bastion.Notifications = Bastion.NotificationsList:New() Bastion.Notifications = Bastion.NotificationsList:New()
Bastion.modules = {} Bastion.modules = {}
@ -202,11 +178,28 @@ Command:Register('mplus', 'Toggle m+ module on/off', function(args)
Bastion:Print("debuffs") Bastion:Print("debuffs")
end) end)
local files = ListFiles("scripts/bastion/scripts") --Toggle Main Menu
Command:Register('interface', 'Opens interface menu', function()
for i = 1, #files do if mainmenu:IsShown() then
local file = files[i] mainmenu:Hide()
if file:sub(-4) == ".lua" or file:sub(-5) == '.luac' then else
Tinkr:require("scripts/bastion/scripts/" .. file:sub(1, -5), Bastion) mainmenu:Show()
end end
end)
-- local files = ListFiles("scripts/bastion/scripts")
-- for i = 1, #files do
-- local file = files[i]
-- if file:sub(-4) == ".lua" or file:sub(-5) == '.luac' then
-- Tinkr:require("scripts/bastion/scripts/" .. file:sub(1, -5), Bastion)
-- end
-- end
if UnitClass('player') == 'Priest' and GetSpecialization() == 3 then
Tinkr:require("scripts/bastion/scripts/shadowpriest", Bastion)
Eval('RunMacroText("/bastion module shadow")', 'bastion')
elseif UnitClass('player') == 'Druid' and GetSpecialization() == 4 then
Tinkr:require("scripts/bastion/scripts/restodruid", Bastion)
Eval('RunMacroText("/bastion module resto_druid")', 'bastion')
end end
Loading…
Cancel
Save