Objectmanager update

To allow for healing tests in Proving Grounds
main
Ofrex 2 years ago
parent bd58c55102
commit 8c691161e4
  1. 726
      scripts/discpriest.lua
  2. 400
      scripts/feraldruid.lua
  3. 337
      scripts/guardiandruid.lua
  4. 476
      scripts/holypriest.lua
  5. 608
      scripts/outlawbak.lua
  6. 906
      scripts/restodruid.lua
  7. 1980
      scripts/subtlety.lua
  8. 39
      src/APL/APL.lua
  9. 40
      src/Aura/Aura.lua
  10. 37
      src/AuraTable/AuraTable.lua
  11. 10
      src/Cache/Cache.lua
  12. 13
      src/Cacheable/Cacheable.lua
  13. 8
      src/Class/Class.lua
  14. 4
      src/ClassMagic/ClassMagic.lua
  15. 13
      src/Command/Command.lua
  16. 12
      src/EventManager/EventManager.lua
  17. 59
      src/Item/Item.lua
  18. 4
      src/ItemBook/ItemBook.lua
  19. 35
      src/List/List.lua
  20. 13
      src/Module/Module.lua
  21. 6
      src/MythicPlusUtils/MythicPlusUtils.lua
  22. 45
      src/NotificationsList/NotificationsList.lua
  23. 13
      src/ObjectManager/ObjectManager.lua
  24. 10
      src/Refreshable/Refreshable.lua
  25. 65
      src/Spell/Spell.lua
  26. 22
      src/SpellBook/SpellBook.lua
  27. 7
      src/Timer/Timer.lua
  28. 253
      src/Unit/Unit.lua
  29. 25
      src/UnitManager/UnitManager.lua
  30. 51
      src/Vector3/Vector3.lua
  31. 45
      src/_bastion.lua

@ -0,0 +1,726 @@
local Tinkr, Bastion = ...
local DiscModule = Bastion.Module:New('disc')
local Evaluator = Tinkr.Util.Evaluator
local Player = Bastion.UnitManager:Get('player')
local None = Bastion.UnitManager:Get('none')
local Target = Bastion.UnitManager:Get('target')
local myconf = Tinkr.Util.Config:New('disc_priest')
local AngelicFeather = Bastion.SpellBook:GetSpell(121536)
local DesperatePrayer = Bastion.SpellBook:GetSpell(19236)
local DispelMagic = Bastion.SpellBook:GetSpell(528)
local Fade = Bastion.SpellBook:GetSpell(586)
local FlashHeal = Bastion.SpellBook:GetSpell(2061)
local LeapofFaith = Bastion.SpellBook:GetSpell(73325)
local Levitate = Bastion.SpellBook:GetSpell(1706)
local MassDispel = Bastion.SpellBook:GetSpell(32375)
local MindBlast = Bastion.SpellBook:GetSpell(8092)
local MindSoothe = Bastion.SpellBook:GetSpell(453)
local MindVision = Bastion.SpellBook:GetSpell(2096)
local PowerInfusion = Bastion.SpellBook:GetSpell(10060)
local PowerWordFortitude = Bastion.SpellBook:GetSpell(21562)
local PowerWordLife = Bastion.SpellBook:GetSpell(373481)
local PowerWordShield = Bastion.SpellBook:GetSpell(17)
local PsychicScream = Bastion.SpellBook:GetSpell(8122)
local Renew = Bastion.SpellBook:GetSpell(139)
local Resurrection = Bastion.SpellBook:GetSpell(2006)
local ShadowWordDeath = Bastion.SpellBook:GetSpell(32379)
local Shadowfiend = Bastion.SpellBook:GetSpell(34433)
local Smite = Bastion.SpellBook:GetSpell(585)
local VampiricEmbrace = Bastion.SpellBook:GetSpell(15286)
local VoidTendrils = Bastion.SpellBook:GetSpell(108920)
local FocusedWill = Bastion.SpellBook:GetSpell(45243)
local BoonoftheAscended = Bastion.SpellBook:GetSpell(325013)
local Apotheosis = Bastion.SpellBook:GetSpell(392941)
local DivineStar = Bastion.SpellBook:GetSpell(110744)
local MassResurrection = Bastion.SpellBook:GetSpell(212036)
local PainSuppression = Bastion.SpellBook:GetSpell(33206)
local Penance = Bastion.SpellBook:GetSpell(47540)
local PowerWordBarrier = Bastion.SpellBook:GetSpell(62618)
local PowerWordRadiance = Bastion.SpellBook:GetSpell(194509)
local PurgetheWicked = Bastion.SpellBook:GetSpell(204197)
local Purify = Bastion.SpellBook:GetSpell(527)
local Rapture = Bastion.SpellBook:GetSpell(47536)
local Schism = Bastion.SpellBook:GetSpell(214621)
local ShadowCovenant = Bastion.SpellBook:GetSpell(314867)
local Atonement = Bastion.SpellBook:GetSpell(81749)
local MasteryGrace = Bastion.SpellBook:GetSpell(271534)
local SinsoftheMany = Bastion.SpellBook:GetSpell(280391)
local Apotheosis = Bastion.SpellBook:GetSpell(392941)
local DivineStar = Bastion.SpellBook:GetSpell(110744)
local MassResurrection = Bastion.SpellBook:GetSpell(212036)
local Purify = Bastion.SpellBook:GetSpell(527)
local ShadowWordPain = Bastion.SpellBook:GetSpell(204197)
local DivineStar = Bastion.SpellBook:GetSpell(110744)
local ShadowWordPain = Bastion.SpellBook:GetSpell(204197)
local Lowest = Bastion.UnitManager:CreateCustomUnit('lowest', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(function(unit)
if unit:IsDead() then
return false
end
if Player:GetDistance(unit) > 40 then
return false
end
if not Player:CanSee(unit) then
return false
end
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end)
if not lowest then
lowest = Player
end
return lowest
end)
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 not unit:IsDead() and Player:CanSee(unit) and
unit:GetAuras():HasAnyStealableAura() then
purge = unit
return true
end
end)
if purge == nil then
purge = None
end
return purge
end)
local DispelTarget = Bastion.UnitManager:CreateCustomUnit('dispel', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(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 not unit:IsDead() and Player:CanSee(unit) and
unit:GetAuras():HasAnyDispelableAura(Purify) then
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end
end)
if lowest == nil then
lowest = None
end
return lowest
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 RenewUnit = Bastion.UnitManager:CreateCustomUnit('renew', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(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 not unit:IsDead() and Player:CanSee(unit) and
(
not unit:GetAuras():FindMy(Renew):IsUp() or
unit:GetAuras():FindMy(Renew):GetRemainingTime() <= 1.6) then
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end
end)
if lowest == nil then
lowest = Player
end
return lowest
end)
local PshieldUnit = Bastion.UnitManager:CreateCustomUnit('pshield', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(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 not unit:IsDead() and Player:CanSee(unit) and
(
not unit:GetAuras():FindMy(PowerWordShield):IsUp()) then
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end
end)
if lowest == nil then
lowest = Player
end
return lowest
end)
local DefaultAPL = Bastion.APL:New('default')
DefaultAPL:AddSpell(
PowerWordFortitude:CastableIf(function(self)
return usepwf and self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordFortitude):IsUp() and not IsMounted()
end):SetTarget(Player)
)
DefaultAPL:AddSpell(
ShadowCovenant:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Player)
)
DefaultAPL:AddSpell(
ShadowWordPain:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Target:GetAuras():FindMy(ShadowWordPain):IsUp()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
PowerWordShield:CastableIf(function(self)
return self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordShield):IsUp() and not IsMounted() and Player:GetHealth() < 80
end):SetTarget(Player)
)
DefaultAPL:AddSpell(
Shadowfiend:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
PowerInfusion:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Player)
)
DefaultAPL:AddSpell(
ShadowWordDeath:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Target:GetHealthPercent() <= 20
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
MindBlast:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
Smite:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
PurgeTheWicked:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Target:GetAuras():PurgeTheWicked()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
Schism:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
Penance:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
DefaultAPL:AddSpell(
Penance:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetHP() <= 70
end):SetTarget(Lowest)
)
DefaultAPL:AddSpell(
DispelMagic:CastableIf(function(self)
return PurgeTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
self:IsInRange(PurgeTarget) and PurgeTarget:GetAuras():HasAnyStealableAura()
end):SetTarget(PurgeTarget)
)
DefaultAPL:AddSpell(
Purify:CastableIf(function(self)
return DispelTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
self:IsInRange(DispelTarget) and DispelTarget:GetAuras():HasAnyDispelableAura(Purify)
end):SetTarget(DispelTarget)
)
DefaultAPL:AddSpell(
PainSuppression:CastableIf(function(self)
return Tank:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Tank) and Tank:GetHP() <= 30
end):SetTarget(Tank)
)
DefaultAPL:AddSpell(
FlashHeal:CastableIf(function(self)
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Lowest) and Lowest:GetHP() <= 65
end):SetTarget(Lowest)
)
DefaultAPL:AddSpell(
PowerWordLife:CastableIf(function(self)
return Lowest:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(Lowest) and Lowest:GetHP() <= 35
end):SetTarget(Lowest)
)
DefaultAPL:AddSpell(
Renew:CastableIf(function(self)
return RenewUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(RenewUnit) and RenewUnit:GetHP() <= 95
end):SetTarget(RenewUnit)
)
DefaultAPL:AddSpell(
PowerWordShield:CastableIf(function(self)
return PshieldUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(PshieldUnit) and PshieldUnit:GetHP() <= 70
end):SetTarget(PshieldUnit)
)
DefaultAPL:AddSpell(
PowerWordRadiance:CastableIf(function(self)
return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:IsInParty() and
self:IsInRange(Player) and Player:GetPartyHPAround(50) >= 3
end):SetTarget(Player)
)
DefaultAPL:AddSpell(
PowerWordBarrier:CastableIf(function(self)
return Player:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:IsInParty() and
self:IsInRange(Player) and Player:GetPartyHPAround(40) >= 3
end):SetTarget(Player)
)
OpenerAPL:AddSpell(
DivineStar:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:IsFacing(target)
end):SetTarget(None):OnCast(function(self)
local loc = Target:GetPosition()
self:Click(loc)
end)
)
DiscModule:Sync(function()
if Player:IsAffectingCombat() then
DefaultAPL:Execute()
end
end)
Bastion:Register(DiscModule)
local tab1 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { resto = { type = 'header', label = 'DPS Options' } },
[2] = { dps1 = { type = 'slider', label = 'DPS Health Threshold', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('dpshealth', 85),
onValueChanged = function(_, value) myconf:Write('dpshealth', value) end },
dps2 = { type = 'slider', label = 'Player Mana Threshold', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('playermana', 85),
onValueChanged = function(_, value) myconf:Write('playermana', value) end }, },
[3] = { autoform = { type = 'header', label = 'Natures Cure' } },
[4] = { pummel = { type = 'checkbox', label = 'Dispell', column = 6,
initialValue = myconf:Read('naturescure1', false),
onValueChanged = function(_, flag) myconf:Write('naturescure1', flag) end }, },
[5] = { resto = { type = 'header', label = 'Soothe' } },
[6] = { incombat = { type = 'checkbox', label = 'Shoote Target', column = 12, order = 1,
initialValue = myconf:Read('soothe', false),
onValueChanged = function(_, flag) myconf:Write('soothe', flag) end }, },
[7] = { resto = { type = 'header', label = 'Dispel Delay Time' } },
[8] = { 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 }, },
[9] = { innervate1 = { type = 'checkbox', label = 'Innervate', column = 6, order = 1,
initialValue = myconf:Read('innervate', false),
onValueChanged = function(_, flag) myconf:Write('innervate', flag) end },
innervate2 = { type = 'slider', label = 'Player Mana', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('innervatemana', 35),
onValueChanged = function(_, value) myconf:Write('innervatemana', value) end }, },
[10] = { frostmage = { type = 'header', label = 'Trinkets' } },
[11] = { pummel = { type = 'checkbox', label = 'Use Trinkets', column = 6,
initialValue = myconf:Read('trinkets', false),
onValueChanged = function(_, flag) myconf:Write('trinkets', flag) end }, },
[12] = { autoform = { type = 'header', label = 'Auto Form' } },
[13] = { pummel = { type = 'checkbox', label = 'Use Auto Form', column = 6,
initialValue = myconf:Read('autoform', false),
onValueChanged = function(_, flag) myconf:Write('autoform', flag) end }, },
},
}
local tab2 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { resto = { 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 = 'Regrowth', 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 }, },
[4] = { resto = { type = 'header', label = 'Defensives' } },
[5] = { bark1 = { type = 'checkbox', label = 'Barkskin', column = 6, order = 1,
initialValue = myconf:Read('barkskin', false),
onValueChanged = function(_, flag) myconf:Write('barkskin', flag) end },
bark2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('barkskinpercent', 35),
onValueChanged = function(_, value) myconf:Write('barkskinpercent', value) end }, },
},
}
local tab3 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { incombat = { type = 'checkbox', label = 'In Combat Healing', column = 6, order = 1,
initialValue = myconf:Read('groupicheal', false),
onValueChanged = function(_, flag) myconf:Write('groupicheal', flag) end },
outcombat = { type = 'checkbox', label = 'Out of Combat Healing', column = 6, order = 2,
initialValue = myconf:Read('groupoocheal', false),
onValueChanged = function(_, flag) myconf:Write('groupoocheal', flag) end }, },
[2] = { lifebloom1 = { type = 'dropdown', label = 'Lifebloom on', column = 6, order = 1,
options = {
{ text = 'Tank Only', value = 'tank'},
{ text = 'All Party', value = 'party'},
{ text = 'Player', value = 'player'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('lifebloomtarget', 'tank'),
onValueChanged = function(_, value) myconf:Write('lifebloomtarget', value) end }, },
[3] = { resto = { type = 'header', label = 'AOE Heals' } },
[4] = { tranq1 = { type = 'checkbox', label = 'Tranquility', column = 6, order = 1,
initialValue = myconf:Read('grptranq', false),
onValueChanged = function(_, flag) myconf:Write('grptranq', flag) end }, },
[5] = { tranq2 = { type = 'slider', label = 'Number of Targets', column = 6, order = 2,
min = 1, max = 10, precision = 0,
initialValue = myconf:Read('tranqtargets', 3),
onValueChanged = function(_, value) myconf:Write('tranqtargets', value) end },
tranq3 = { type = 'slider', label = 'Target Health', column = 6, order = 1,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('tranqpercent', 50),
onValueChanged = function(_, value) myconf:Write('tranqpercent', value) end }, },
[6] = { flourish1 = { type = 'checkbox', label = 'Flourish', column = 6, order = 1,
initialValue = myconf:Read('flourish', false),
onValueChanged = function(_, flag) myconf:Write('flourish', flag) end }, },
[7] = { flourish2 = { type = 'slider', label = 'Number of Targets', column = 6, order = 2,
min = 1, max = 10, precision = 0,
initialValue = myconf:Read('flourishtargets', 3),
onValueChanged = function(_, value) myconf:Write('flourishtargets', value) end },
flourish3 = { type = 'slider', label = 'Target Health', column = 6, order = 1,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('flourishpercent', 50),
onValueChanged = function(_, value) myconf:Write('flourishpercent', value) end }, },
[8] = { convoke1 = { type = 'checkbox', label = 'Convoke The Spirits', column = 6, order = 1,
initialValue = myconf:Read('convoke', false),
onValueChanged = function(_, flag) myconf:Write('convoke', flag) end }, },
[9] = { convoke2 = { type = 'slider', label = 'Number of Targets', column = 6, order = 2,
min = 1, max = 10, precision = 0,
initialValue = myconf:Read('convoketargets', 3),
onValueChanged = function(_, value) myconf:Write('convoketargets', value) end },
convoke3 = { type = 'slider', label = 'Target Health', column = 6, order = 1,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('convokepercent', 50),
onValueChanged = function(_, value) myconf:Write('convokepercent', value) end }, },
[10] = { wild1 = { type = 'checkbox', label = 'Wild Growth', column = 6, order = 1,
initialValue = myconf:Read('grpwildgrowth', false),
onValueChanged = function(_, flag) myconf:Write('grpwildgrowth', flag) end }, },
[11] = { wild2 = { type = 'slider', label = 'Number of Targets', column = 6, order = 2,
min = 1, max = 10, precision = 0,
initialValue = myconf:Read('wildgrowthtargets', 3),
onValueChanged = function(_, value) myconf:Write('wildgrowthtargets', value) end },
wild3 = { type = 'slider', label = 'Target Health', column = 6, order = 1,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('wildgrowthpercent', 80),
onValueChanged = function(_, value) myconf:Write('wildgrowthpercent', value) end }, },
[12] = { incarnationtree1 = { type = 'checkbox', label = 'Incarnation: Tree of Life', column = 6, order = 1,
initialValue = myconf:Read('incarnationtree', false),
onValueChanged = function(_, flag) myconf:Write('incarnationtree', flag) end }, },
[13] = { convoke2 = { type = 'slider', label = 'Number of Targets', column = 6, order = 2,
min = 1, max = 10, precision = 0,
initialValue = myconf:Read('incarnationtreetargets', 3),
onValueChanged = function(_, value) myconf:Write('incarnationtreetargets', value) end },
convoke3 = { type = 'slider', label = 'Target Health', column = 6, order = 1,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('incarnationtreepercent', 50),
onValueChanged = function(_, value) myconf:Write('incarnationtreepercent', value) end }, }
},
}
local tab4 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { resto = { type = 'header', label = 'AOE Heals ' } },
[2] = { ironbark1 = { type = 'dropdown', label = 'Ironbark on', column = 6, order = 1,
options = {
{ text = 'Tank Only', value = 'tank'},
{ text = 'All Party', value = 'party'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('ironbarktarget', 'tank'),
onValueChanged = function(_, value) myconf:Write('ironbarktarget', value) end },
ironbark2 = { type = 'slider', label = 'Target Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('ironbarkpercent', 30),
onValueChanged = function(_, value) myconf:Write('ironbarkpercent', value) end }, },
[3] = { ward1 = { type = 'dropdown', label = 'Cenarion Ward on', column = 6, order = 1,
options = {
{ text = 'Tank Only', value = 'tank'},
{ text = 'All Party', value = 'party'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('wardtarget', 'tank'),
onValueChanged = function(_, value) myconf:Write('wardtarget', value) end },
ward2 = { type = 'slider', label = 'Target Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('wardpercent', 30),
onValueChanged = function(_, value) myconf:Write('wardpercent', value) end }, },
[4] = { natswift1 = { type = 'checkbox', label = 'Natures Swiftness', column = 6, order = 1,
initialValue = myconf:Read('grpnatswift', false),
onValueChanged = function(_, flag) myconf:Write('grpnatswift', flag) end },
natswift2 = { type = 'slider', label = 'Target Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('grpnatswiftpercent', 40),
onValueChanged = function(_, value) myconf:Write('grpnatswiftpercent', value) end }, },
[5] = { swift1 = { type = 'checkbox', label = 'Swiftmend', column = 6, order = 1,
initialValue = myconf:Read('grpswiftmend', false),
onValueChanged = function(_, flag) myconf:Write('grpswiftmend', flag) end },
swift2 = { type = 'slider', label = 'Target Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('grpswiftmendpercent', 60),
onValueChanged = function(_, value) myconf:Write('grpswiftmendpercent', value) end }, },
[6] = { regrowth1 = { type = 'checkbox', label = 'Regrowth', column = 6, order = 1,
initialValue = myconf:Read('grpregrowth', false),
onValueChanged = function(_, flag) myconf:Write('grpregrowth', flag) end },
regrowth2 = { type = 'slider', label = 'Target Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('grpregrowthpercent', 65),
onValueChanged = function(_, value) myconf:Write('grpregrowthpercent', value) end }, },
[7] = { rejuv1 = { type = 'checkbox', label = 'Rejuvenation', column = 6, order = 1,
initialValue = myconf:Read('grprejuv', false),
onValueChanged = function(_, flag) myconf:Write('grprejuv', flag) end },
rejuv2 = { type = 'slider', label = 'Target Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('grprejuvpercent', 85),
onValueChanged = function(_, value) myconf:Write('grprejuvpercent', value) end }, },
},
}
local discpriestconfig = {
layoutConfig = { padding = { top = 30 } },
rows = {
[1] = {
container = {
type = 'tab',
fullSize = true,
tabs = {
{
name = 'player',
title = 'Player Settings',
layout = tab1
},
{
name = 'playerhealing',
title = 'Player Healing',
layout = tab2
},
{
name = 'group',
title = 'Group Healing',
layout = tab3
},
{
name = 'group2',
title = 'AOE Healing ',
layout = tab4
}
},
}
},
},
}
Bastion.settingstemplate(discpriestconfig, 'Disc Priest', 460, 780, 1.00, 0.49, 0.04)

@ -0,0 +1,400 @@
local Tinkr, Bastion = ...
local FeralModule = Bastion.Module:New('feral')
local Evaluator = Tinkr.Util.Evaluator
local Player = Bastion.UnitManager:Get('player')
local None = Bastion.UnitManager:Get('none')
local Target = Bastion.UnitManager:Get('target')
local myconf = Tinkr.Util.Config:New('feral_druid') -- for saving variables
-- Spellbook spells
local Shadowmeld = Bastion.SpellBook:GetSpell(58984)
local Barkskin = Bastion.SpellBook:GetSpell(22812)
local BearForm = Bastion.SpellBook:GetSpell(5487)
--local Berserk = Bastion.SpellBook:GetSpell(50334)
local CatForm = Bastion.SpellBook:GetSpell(768)
local Dash = Bastion.SpellBook:GetSpell(1850)
local EntanglingRoots = Bastion.SpellBook:GetSpell(339)
local FeralFrenzy = Bastion.SpellBook:GetSpell(274837)
local FerociousBite = Bastion.SpellBook:GetSpell(22568)
--local FrenziedRegeneration = Bastion.SpellBook:GetSpell(22842)
local Growl = Bastion.SpellBook:GetSpell(6795)
--local Ironfur = Bastion.SpellBook:GetSpell(192081)
local Mangle = Bastion.SpellBook:GetSpell(33917)
local MarkoftheWild = Bastion.SpellBook:GetSpell(1126)
local Moonfire = Bastion.SpellBook:GetSpell(8921)
local MoonfireDebuff = Bastion.SpellBook:GetSpell(164812)
local PredatorySwiftness = Bastion.SpellBook:GetSpell(69369)
local PrimalWrath = Bastion.SpellBook:GetSpell(285381)
local Prowl = Bastion.SpellBook:GetSpell(5215)
local Rake = Bastion.SpellBook:GetSpell(1822)
local RakeDebuff = Bastion.SpellBook:GetSpell(155722)
local Regrowth = Bastion.SpellBook:GetSpell(8936)
local Revive = Bastion.SpellBook:GetSpell(50769)
local Rip = Bastion.SpellBook:GetSpell(1079)
local Shred = Bastion.SpellBook:GetSpell(5221)
local SkullBash = Bastion.SpellBook:GetSpell(106839)
--local Thrash = Bastion.SpellBook:GetSpell(106830)
local Thrash = Bastion.SpellBook:GetSpell(106832)
local ThrashDebuff = Bastion.SpellBook:GetSpell(106830)
local TigersFury = Bastion.SpellBook:GetSpell(5217)
local TravelForm = Bastion.SpellBook:GetSpell(783)
local Wrath = Bastion.SpellBook:GetSpell(5176)
--local Maul = Bastion.SpellBook:GetSpell(6807)
--local SurvivalInstincts = Bastion.SpellBook:GetSpell(61336)
--local Swipe = Bastion.SpellBook:GetSpell(106785)
local Swipe = Bastion.SpellBook:GetSpell(213764)
local BrutalSlash = Bastion.SpellBook:GetSpell(202028)
local ApexPredator = Bastion.SpellBook:GetSpell(391882)
local Incarnation = Bastion.SpellBook:GetSpell(102543)
-- Define Units
local InterruptTarget = Bastion.UnitManager:CreateCustomUnit('skullbash', function(unit)
local interrupt = 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
interrupt = unit
return true
end
end)
if interrupt == nil then
interrupt = None
end
return interrupt
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)
-- Rotation code here
local function Buffs()
-- Mark of the Wild
local motw = myconf:Read('motw')
MarkoftheWild:Condition('Mark of the Wild', function()
return motw and MarkoftheWild:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(MarkoftheWild):IsUp()
and not Player:IsMounted()
end)
MarkoftheWild:Cast(Player, 'Mark of the Wild')
end
local function DruidProwl()
-- Prowl
Prowl:Condition('Prowl', function()
return Prowl:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Prowl):IsUp()
and Player:GetDistance(Target) <= 25 and not Player:IsMounted() and Target:IsHostile() and not Target:IsDead()
end)
Prowl:Cast(Player, 'Prowl')
end
local function Opener()
-- Rake
Rake:Condition('Rake', function()
return Rake:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:InMelee(Target)
and not Target:GetAuras():FindMy(RakeDebuff):IsUp() and Target:Exists() and Target:IsHostile() and not Target:IsDead()
end)
Rake:Cast(Target, 'Rake')
end
local function Interrupt()
-- Skull Bash
SkullBash:Condition('SkullBash', function()
return SkullBash:IsKnownAndUsable() and InterruptTarget:Exists() and not Player:IsCastingOrChanneling()
end)
C_Timer.After(1.5, function()
SkullBash:Cast(Target, 'SkullBash')
end)
end
local function Damage()
-- Cat Form
CatForm:Condition('Cat Form', function()
return CatForm:IsKnownAndUsable() and not Player:GetAuras():FindMy(CatForm):IsUp()
end)
CatForm:Cast(Player, 'Cat Form')
-- Healing with Predatory Swiftness
Regrowth:Condition('Regrowth', function()
return Regrowth:IsKnownAndUsable() and Player:GetAuras():FindMy(PredatorySwiftness):IsUp()
end)
Regrowth:Cast(Player, 'Regrowth')
-- Cooldowns
-- Tiger's Fury
TigersFury:Condition('Tigers Fury', function()
return TigersFury:IsKnownAndUsable() and not Player:GetAuras():FindMy(TigersFury):IsUp()
end)
TigersFury:Cast(Player, 'Tigers Fury')
-- Feral Frenzy on cooldown and when combo points are zero
FeralFrenzy:Condition('Feral Frenzy', function()
return FeralFrenzy:IsKnownAndUsable() and Player:GetComboPoints(Target) == 0
end)
FeralFrenzy:Cast(Player, 'Feral Frenzy')
-- Incarnation: Avatar of Ashamane
Incarnation:Condition('Incarnation', function()
return Incarnation:IsKnownAndUsable()
end)
Incarnation:Cast(Player, 'Incarnation')
-- Multi Target Rotation
if Player:GetEnemies(8) >= 2 then
-- Primal Wrath at 5 combo points
PrimalWrath:Condition('Primal Wrath', function()
return PrimalWrath:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetComboPoints(Target) >= 5
and (not Target:GetAuras():FindMy(Rip):IsUp() or Target:GetAuras():FindMy(Rip):GetRemainingTime() <= 7)
end)
PrimalWrath:Cast(Target, 'Primal Wrath')
-- Spend Apex Predator Procs on Ferocious Bite
FerociousBite:Condition('Ferocious Bite Apex Predator', function()
return FerociousBite:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetAuras():FindMy(ApexPredator):IsUp()
end)
FerociousBite:Cast(Target, 'Ferocious Bite Apex Predator')
-- Maintain Rake
Rake:Condition('Maintain Rake', function()
return Rake:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:InMelee(Target)
and Target:GetAuras():FindMy(RakeDebuff):GetRemainingTime() <= 4
end)
Rake:Cast(Target, 'Maintain Rake')
-- Cast Thrash if its not up
Thrash:Condition('Thrash', function()
return Thrash:IsKnownAndUsable() and not Target:GetAuras():FindMy(ThrashDebuff):IsUp() and Player:InMelee(Target)
end)
Thrash:Cast(Target, 'Thrash')
-- Avoid capping Brutal Slash charges
BrutalSlash:Condition('Brutal Slash', function()
return BrutalSlash:IsKnownAndUsable() and Player:InMelee(Target)
end)
BrutalSlash:Cast(Target, 'Brutal Slash')
-- Shred to generate combo points
Shred:Condition('Shred', function()
return Shred:IsKnownAndUsable() and Player:InMelee(Target)
end)
Shred:Cast(Target, 'Shred')
end
-- Single Target Rotation
if Player:GetEnemies(8) == 1 then
-- Maintain Rip - you'll want to cast this at 5 combo points
Rip:Condition('Rip', function()
return Rip:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetComboPoints(Target) >= 5
and (not Target:GetAuras():FindMy(Rip):IsUp() or Target:GetAuras():FindMy(Rip):GetRemainingTime() <= 7)
end)
Rip:Cast(Target, 'Rip')
-- Spend Apex Predator Procs on Ferocious Bite
FerociousBite:Condition('Ferocious Bite Apex Predator', function()
return FerociousBite:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetAuras():FindMy(ApexPredator):IsUp()
end)
FerociousBite:Cast(Target, 'Ferocious Bite Apex Predator')
-- If you have 5 combo points and Rip is not in Pandemic then cast Ferocious Bite
FerociousBite:Condition('Ferocious Bite', function()
return FerociousBite:IsKnownAndUsable() and Player:InMelee(Target) and Player:GetComboPoints(Target) >= 5
end)
FerociousBite:Cast(Target, 'Ferocious Bite')
-- Maintain Rake
Rake:Condition('Maintain Rake', function()
return Rake:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:InMelee(Target)
and Target:GetAuras():FindMy(RakeDebuff):GetRemainingTime() <= 4
end)
Rake:Cast(Target, 'Maintain Rake')
-- Avoid capping Brutal Slash charges
BrutalSlash:Condition('Brutal Slash', function()
return BrutalSlash:IsKnownAndUsable() and Player:InMelee(Target)
end)
BrutalSlash:Cast(Target, 'Brutal Slash')
-- Cast Thrash if its not up
Thrash:Condition('Thrash', function()
return Thrash:IsKnownAndUsable() and not Target:GetAuras():FindMy(ThrashDebuff):IsUp() and Player:InMelee(Target)
end)
Thrash:Cast(Target, 'Thrash')
-- Shred to generate combo points
Shred:Condition('Shred', function()
return Shred:IsKnownAndUsable() and Player:InMelee(Target)
end)
Shred:Cast(Target, 'Shred')
end
end
-- Module that dictates workflow
FeralModule:Sync(function()
if not Player:IsAffectingCombat() then
if Buffs() then return end
if DruidProwl() then return end
if Opener() then return end
end
if Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() and not Target:IsDead() then
if Interrupt() then return end
if Damage() then return end
end
end)
Bastion:Register(FeralModule)
local tab1 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { shadpr = { type = 'label', label = 'Open Combat' } },
[2] = { opener = { type = 'dropdown', label = 'Opener', column = 6, order = 1,
options = {
{ text = 'Moonfire', value = 'moonfire'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('opener', 'moonfire'),
onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
[3] = { shadpr = { type = 'label', label = 'Buffs' } },
[4] = { motw = { type = 'checkbox', label = 'Mark of the Wild', column = 12, order = 1,
initialValue = myconf:Read('motw', false),
onValueChanged = function(_, flag) myconf:Write('motw', flag) end }, },
[5] = { shadpr = { type = 'label', label = 'Defensives' } },
[6] = { shield1 = { type = 'checkbox', label = 'Ironfur', column = 6, order = 1,
initialValue = myconf:Read('ironfur', false),
onValueChanged = function(_, flag) myconf:Write('ironfur', flag) end },
shield2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('ironfurpercent', 35),
onValueChanged = function(_, value) myconf:Write('ironfurpercent', value) end }, },
[7] = { dispersion1 = { type = 'checkbox', label = 'Frenzied Regeneration', column = 6, order = 1,
initialValue = myconf:Read('fregen', false),
onValueChanged = function(_, flag) myconf:Write('fregen', flag) end },
dispersion2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('fregenpercent', 35),
onValueChanged = function(_, value) myconf:Write('fregenpercent', value) end }, },
[8] = { shadpr = { type = 'label', label = 'Interrupts' } },
[9] = { silence = { type = 'checkbox', label = 'Skull Bash on CD', column = 12, order = 1,
initialValue = myconf:Read('skullbash', false),
onValueChanged = function(_, flag) myconf:Write('skullbash', flag) end }, },
[10] = { shadpr = { type = 'header', label = 'Purify Disease' } },
[11] = { 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 }, },
[12] = { shadpr = { type = 'header', label = 'Dispel Magic' } },
[13] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1,
initialValue = myconf:Read('dispelic', false),
onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, },
[14] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } },
[15] = { 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 feralconfig = {
layoutConfig = { padding = { top = 30 } },
rows = {
[1] = {
container = {
type = 'tab',
fullSize = true,
tabs = {
{
name = 'player',
title = 'Player Settings',
layout = tab1
},
{
name = 'group',
title = 'Placeholder',
layout = tab2
}
},
}
},
},
}
Bastion.settingstemplate(feralconfig, 'Feral Druid', 400, 600, 1.00, 0.49, 0.04) -- config, Title of Settings Frame, Width, Height, ClassRGB
-- 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

@ -0,0 +1,337 @@
local Tinkr, Bastion = ...
local GuardianModule = Bastion.Module:New('guardian')
local Evaluator = Tinkr.Util.Evaluator
local Player = Bastion.UnitManager:Get('player')
local None = Bastion.UnitManager:Get('none')
local Target = Bastion.UnitManager:Get('target')
local myconf = Tinkr.Util.Config:New('guardian_druid') -- for saving variables
local AutoAttack = Bastion.SpellBook:GetSpell(6603)
local WarStomp = Bastion.SpellBook:GetSpell(20549)
local Barkskin = Bastion.SpellBook:GetSpell(22812)
local BearForm = Bastion.SpellBook:GetSpell(5487)
local Berserk = Bastion.SpellBook:GetSpell(50334)
local CatForm = Bastion.SpellBook:GetSpell(768)
local Dash = Bastion.SpellBook:GetSpell(1850)
local EntanglingRoots = Bastion.SpellBook:GetSpell(339)
local FerociousBite = Bastion.SpellBook:GetSpell(22568)
local FrenziedRegeneration = Bastion.SpellBook:GetSpell(22842)
local Growl = Bastion.SpellBook:GetSpell(6795)
local Ironfur = Bastion.SpellBook:GetSpell(192081)
local Mangle = Bastion.SpellBook:GetSpell(33917)
local MarkoftheWild = Bastion.SpellBook:GetSpell(1126)
local Moonfire = Bastion.SpellBook:GetSpell(8921)
local MoonfireDebuff = Bastion.SpellBook:GetSpell(164812)
local Prowl = Bastion.SpellBook:GetSpell(5215)
local Regrowth = Bastion.SpellBook:GetSpell(8936)
local Revive = Bastion.SpellBook:GetSpell(50769)
local Shred = Bastion.SpellBook:GetSpell(5221)
local SkullBash = Bastion.SpellBook:GetSpell(106839)
local Thrash = Bastion.SpellBook:GetSpell(77758)
local ThrashDebuff = Bastion.SpellBook:GetSpell(192090)
local TravelForm = Bastion.SpellBook:GetSpell(783)
local Wrath = Bastion.SpellBook:GetSpell(5176)
local Maul = Bastion.SpellBook:GetSpell(6807)
local SurvivalInstincts = Bastion.SpellBook:GetSpell(61336)
local Swipe = Bastion.SpellBook:GetSpell(213771)
local InterruptTarget = Bastion.UnitManager:CreateCustomUnit('skullbash', function(unit)
local interrupt = 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
interrupt = unit
return true
end
end)
if interrupt == nil then
interrupt = None
end
return interrupt
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 RestingAPL = Bastion.APL:New('resting')
local OpenerAPL = Bastion.APL:New('opener')
local DefensivesAPL = Bastion.APL:New('defensives')
local STAPL = Bastion.APL:New('st')
local UtilityAPL = Bastion.APL:New('utility')
-- Resting - Out of Combat Actions
local motw = myconf:Read('motw')
RestingAPL:AddSpell(
MarkoftheWild:CastableIf(function(self)
return motw and self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(MarkoftheWild):IsUp() and not IsMounted()
end):SetTarget(Player)
)
-- Opener spells
local opener = myconf:Read('opener')
OpenerAPL:AddSpell(
Moonfire:CastableIf(function(self)
return opener == 'moonfire' and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
-- Defensive spells
local ironfur = myconf:Read('ironfur')
local ironfurpercent = myconf:Read('ironfurpercent')
DefensivesAPL:AddSpell(
Ironfur:CastableIf(function(self)
return ironfur and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Ironfur):IsUp()
and Player:GetHP() <= ironfurpercent
end):SetTarget(Player)
)
-- Heal yourself with Frenzied Regeneration if your health ever dips low
local fregen = myconf:Read('fregen')
local fregenpercent = myconf:Read('fregenpercent')
DefensivesAPL:AddSpell(
FrenziedRegeneration:CastableIf(function(self)
return fregen and self:IsKnownAndUsable() and Player:GetHP() <= fregenpercent
end):SetTarget(Player)
)
-- Utility spells
local skullbash = myconf:Read('skullbash')
UtilityAPL:AddSpell(
SkullBash:CastableIf(function(self)
return skullbash and InterruptTarget:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(InterruptTarget)
)
-- Single Target Action Priority List
-- Bear Form
STAPL:AddSpell(
BearForm:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:GetAuras():FindMy(BearForm):IsUp()
end):SetTarget(Player)
)
-- Auto Attack
STAPL:AddSpell(
AutoAttack:CastableIf(function(self)
return self:IsKnownAndUsable() and not IsCurrentSpell(AutoAttack) and Player:InMelee(Target)
end):SetTarget(Target)
)
-- Opener spells
STAPL:AddSpell(
Moonfire:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Target:GetAuras():FindMy(MoonfireDebuff):IsUp()
end):SetTarget(Target)
)
-- Spend your rage on Maul as required
STAPL:AddSpell(
Maul:CastableIf(function(self)
return self:IsKnownAndUsable() and Player:InMelee(Target)
end):SetTarget(Target)
)
-- Maintain Moonfire on as many mobs as possible
-- Thrash on cooldown
STAPL:AddSpell(
Thrash:CastableIf(function(self)
return not Target:GetAuras():FindMy(ThrashDebuff):IsUp() and Player:InMelee(Target)
end):SetTarget(Target)
)
-- Mangle on cooldown
STAPL:AddSpell(
Mangle:CastableIf(function(self)
return self:IsKnownAndUsable() and Player:InMelee(Target)
end):SetTarget(Target)
)
-- Fill your empty GCDs with Swipe
STAPL:AddSpell(
Swipe:CastableIf(function(self)
return not self:IsOnCooldown() and Player:InMelee(Target)
end):SetTarget(Target)
)
-- Module that dictates APL flow
GuardianModule:Sync(function()
if not Player:IsAffectingCombat() then
RestingAPL:Execute()
end
if not Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() and not Target:IsDead() then
OpenerAPL:Execute()
end
if Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() and not Target:IsDead() then
DefensivesAPL:Execute()
STAPL:Execute()
end
end)
Bastion:Register(GuardianModule)
local tab1 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { shadpr = { type = 'label', label = 'Open Combat' } },
[2] = { opener = { type = 'dropdown', label = 'Opener', column = 6, order = 1,
options = {
{ text = 'Moonfire', value = 'moonfire'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('opener', 'moonfire'),
onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
[3] = { shadpr = { type = 'label', label = 'Buffs' } },
[4] = { motw = { type = 'checkbox', label = 'Mark of the Wild', column = 12, order = 1,
initialValue = myconf:Read('motw', false),
onValueChanged = function(_, flag) myconf:Write('motw', flag) end }, },
[5] = { shadpr = { type = 'label', label = 'Defensives' } },
[6] = { shield1 = { type = 'checkbox', label = 'Ironfur', column = 6, order = 1,
initialValue = myconf:Read('ironfur', false),
onValueChanged = function(_, flag) myconf:Write('ironfur', flag) end },
shield2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('ironfurpercent', 35),
onValueChanged = function(_, value) myconf:Write('ironfurpercent', value) end }, },
[7] = { dispersion1 = { type = 'checkbox', label = 'Frenzied Regeneration', column = 6, order = 1,
initialValue = myconf:Read('fregen', false),
onValueChanged = function(_, flag) myconf:Write('fregen', flag) end },
dispersion2 = { type = 'slider', label = 'Player Health', column = 6, order = 2,
min = 1, max = 100, precision = 0,
initialValue = myconf:Read('fregenpercent', 35),
onValueChanged = function(_, value) myconf:Write('fregenpercent', value) end }, },
[8] = { shadpr = { type = 'label', label = 'Interrupts' } },
[9] = { silence = { type = 'checkbox', label = 'Skull Bash on CD', column = 12, order = 1,
initialValue = myconf:Read('skullbash', false),
onValueChanged = function(_, flag) myconf:Write('skullbash', flag) end }, },
[10] = { shadpr = { type = 'header', label = 'Purify Disease' } },
[11] = { 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 }, },
[12] = { shadpr = { type = 'header', label = 'Dispel Magic' } },
[13] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1,
initialValue = myconf:Read('dispelic', false),
onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, },
[14] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } },
[15] = { 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 guardianconfig = {
layoutConfig = { padding = { top = 30 } },
rows = {
[1] = {
container = {
type = 'tab',
fullSize = true,
tabs = {
{
name = 'player',
title = 'Player Settings',
layout = tab1
},
{
name = 'group',
title = 'Placeholder',
layout = tab2
}
},
}
},
},
}
Bastion.settingstemplate(guardianconfig, 'Guardian Druid', 400, 600, 1.00, 0.49, 0.04) -- config, Title of Settings Frame, Width, Height, ClassRGB
-- 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

@ -0,0 +1,476 @@
local Tinkr, Bastion = ...
local HolyModule = Bastion.Module:New('holypriest')
local Evaluator = Tinkr.Util.Evaluator
local Player = Bastion.UnitManager:Get('player')
local None = Bastion.UnitManager:Get('none')
local Target = Bastion.UnitManager:Get('target')
local myconf = Tinkr.Util.Config:New('holy_priest') -- for saving variables
local ArcaneTorrent = Bastion.SpellBook:GetSpell(232633)
local AutoAttack = Bastion.SpellBook:GetSpell(6603)
local AngelicFeather = Bastion.SpellBook:GetSpell(121536)
local DesperatePrayer = Bastion.SpellBook:GetSpell(19236)
local DispelMagic = Bastion.SpellBook:GetSpell(528)
local Fade = Bastion.SpellBook:GetSpell(586)
local FlashHeal = Bastion.SpellBook:GetSpell(2061)
local HolyNova = Bastion.SpellBook:GetSpell(132157)
local HolyWordSalvation = Bastion.SpellBook:GetSpell(265202)
local LeapofFaith = Bastion.SpellBook:GetSpell(73325)
local Levitate = Bastion.SpellBook:GetSpell(1706)
local MassDispel = Bastion.SpellBook:GetSpell(32375)
local MindSoothe = Bastion.SpellBook:GetSpell(453)
local MindVision = Bastion.SpellBook:GetSpell(2096)
local PowerInfusion = Bastion.SpellBook:GetSpell(10060)
local PowerWordFortitude = Bastion.SpellBook:GetSpell(21562)
local PowerWordLife = Bastion.SpellBook:GetSpell(373481)
local PowerWordShield = Bastion.SpellBook:GetSpell(17)
local PrayerofMending = Bastion.SpellBook:GetSpell(33076)
local PsychicScream = Bastion.SpellBook:GetSpell(8122)
local Renew = Bastion.SpellBook:GetSpell(139)
local Resurrection = Bastion.SpellBook:GetSpell(2006)
local ShadowWordPain = Bastion.SpellBook:GetSpell(589)
local Shadowfiend = Bastion.SpellBook:GetSpell(34433)
local Smite = Bastion.SpellBook:GetSpell(585)
local FocusedWill = Bastion.SpellBook:GetSpell(45243)
local CircleofHealing = Bastion.SpellBook:GetSpell(204883)
local DivineHymn = Bastion.SpellBook:GetSpell(64843)
local DivineWord = Bastion.SpellBook:GetSpell(372760)
local GuardianSpirit = Bastion.SpellBook:GetSpell(47788)
local Halo = Bastion.SpellBook:GetSpell(120517)
local Heal = Bastion.SpellBook:GetSpell(2060)
local HolyFire = Bastion.SpellBook:GetSpell(14914)
local HolyWordSanctify = Bastion.SpellBook:GetSpell(34861)
local HolyWordSerenity = Bastion.SpellBook:GetSpell(2050)
local Lightweaver = Bastion.SpellBook:GetSpell(390993)
local MassResurrection = Bastion.SpellBook:GetSpell(212036)
local PrayerofHealing = Bastion.SpellBook:GetSpell(596)
local Purify = Bastion.SpellBook:GetSpell(527)
local SurgeofLight = Bastion.SpellBook:GetSpell(114255)
local SymbolofHope = Bastion.SpellBook:GetSpell(64901)
local MindBlast = Bastion.SpellBook:GetSpell(14914)
local Lowest = Bastion.UnitManager:CreateCustomUnit('lowest', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(function(unit)
if unit:IsDead() then return false end
if Player:GetDistance(unit) > 40 then return false end
if not Player:CanSee(unit) then return false end
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end)
if not lowest then
lowest = Player
end
return lowest
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 = Player
end
return tank
end)
local Healer = Bastion.UnitManager:CreateCustomUnit('healer', function(unit)
local healer = 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:IsHealer() then
healer = unit
return true
end
return false
end)
if healer == nil then
healer = Player
end
return healer
end)
local PurifyUnit = Bastion.UnitManager:CreateCustomUnit('dispel', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(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 not unit:IsDead() and Player:CanSee(unit) and
unit:GetAuras():HasAnyDispelableAura(Purify) then
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end
end)
if lowest == nil then
lowest = None
end
return lowest
end)
local SanctifyUnit = Bastion.UnitManager:CreateCustomUnit('sanctify', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(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:CanSee(unit) and unit:GetPartyHPAround(10, 70) >= 5
then
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end
end)
if lowest == nil then
lowest = None
end
return lowest
end)
local CoHUnit = Bastion.UnitManager:CreateCustomUnit('coh', function(unit)
local lowest = nil
local lowestHP = math.huge
Bastion.UnitManager:EnumFriends(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:CanSee(unit) and unit:GetPartyHPAround(30, 80) >= 4
then
local hp = unit:GetHP()
if hp < lowestHP then
lowest = unit
lowestHP = hp
end
end
end)
if lowest == nil then
lowest = None
end
return lowest
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 RestingAPL = Bastion.APL:New('resting')
local HealAPL = Bastion.APL:New('heal')
local DamageAPL = Bastion.APL:New('damage')
-- Resting - Out of Combat Actions
local usepwf = myconf:Read('pwf')
RestingAPL:AddSpell(
PowerWordFortitude:CastableIf(function(self)
return usepwf and self:IsKnownAndUsable() and
not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(PowerWordFortitude):IsUp() and not IsMounted()
end):SetTarget(Player)
)
-- HealAPL - Healing here
-- Purify
HealAPL:AddSpell(
Purify:CastableIf(function(self)
return PurifyUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and
self:IsInRange(PurifyUnit) and PurifyUnit:GetAuras():HasAnyDispelableAura(Purify)
end):SetTarget(PurifyUnit)
)
-- Symbol of Hope
HealAPL:AddSpell(
SymbolofHope:CastableIf(function(self)
return Healer:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Healer:GetPP() <= 50
end):SetTarget(Player)
)
-- Guardian Spirit
HealAPL:AddSpell(
GuardianSpirit:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Tank:GetHP() <= 40
end):SetTarget(Tank)
)
-- Flash Heal with Surge of Light
HealAPL:AddSpell(
FlashHeal:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetAuras():FindMy(SurgeofLight):IsUp()
end):SetTarget(Lowest)
)
-- Holy Word: Salvation when the majority of the raid is heavily injured
HealAPL:AddSpell(
HolyWordSalvation:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPartyHPAround(40, 50) >= 5
and not Player:IsMoving()
end):SetTarget(Player)
)
-- Divine Hymn when the majority of the raid is heavily injured
HealAPL:AddSpell(
DivineHymn:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPartyHPAround(40, 40) >= 5
and not Player:IsMoving()
end):SetTarget(Player)
)
-- Divine Word followed by Holy Word: Sanctify (if available) on a cluster of injured allies
-- Divine Word followed by Holy Word: Serenity (if available) on an injured ally
HealAPL:AddSpell(
DivineWord:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(DivineWord):IsUp()
and (Lowest:GetHP() <= 60 or SanctifyUnit:GetPartyHPAround(10, 60) >= 5)
end):SetTarget(Player)
)
-- Holy Word: Sanctify when a cluster of your raid is injured
HealAPL:AddSpell(
HolyWordSanctify:CastableIf(function(self)
return SanctifyUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(SanctifyUnit) and SanctifyUnit:GetPartyHPAround(10, 70) >= 5
end):SetTarget(None):OnCast(function(self)
local loc = SanctifyUnit:GetPosition()
self:Click(loc)
end)
)
-- Holy Word: Serenity on an injured ally
HealAPL:AddSpell(
HolyWordSerenity:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Lowest:GetHP() <= 70
end):SetTarget(Lowest)
)
-- Circle of Healing on cooldown when at least 4 allies are injured
HealAPL:AddSpell(
CircleofHealing:CastableIf(function(self)
return CoHUnit:Exists() and self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
and Player:CanSee(CoHUnit) and CoHUnit:GetPartyHPAround(30, 80) >= 4
end):SetTarget(CoHUnit)
)
-- Prayer of Mending on cooldown, usually on the active tank
HealAPL:AddSpell(
PrayerofMending:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Tank:GetHP() <= 95
end):SetTarget(Tank)
)
-- Halo when most of your raid is injured
HealAPL:AddSpell(
Halo:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetPartyHPAround(30, 70) >= 5
end):SetTarget(Player)
)
-- Power Word: Life for emergency triage on an ally below 35% hitpoints
HealAPL:AddSpell(
PowerWordLife:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Tank:GetHP() <= 35
end):SetTarget(Tank)
)
-- Alternate between Flash Heal and Heal and use Lightweaver buff
HealAPL:AddSpell(
Heal:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and Player:GetAuras():FindMy(Lightweaver):IsUp()
and Lowest:GetHP() <= 90
end):SetTarget(Lowest)
)
HealAPL:AddSpell(
FlashHeal:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Player:GetAuras():FindMy(Lightweaver):IsUp()
and Lowest:GetHP() <= 90
end):SetTarget(Lowest)
)
-- DamageAPL - DPS spells here
-- Cast Shadow Word: Pain if you're moving and nothing else is available
DamageAPL:AddSpell(
ShadowWordPain:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling() and not Target:GetAuras():FindMy(ShadowWordPain):IsUp()
end):SetTarget(Target)
)
-- Cast Smite
DamageAPL:AddSpell(
Smite:CastableIf(function(self)
return self:IsKnownAndUsable() and not Player:IsCastingOrChanneling()
end):SetTarget(Target)
)
-- Module that dictates APL flow
HolyModule:Sync(function()
-- Bastion:Print(Lowest)
-- if not Player:IsAffectingCombat() then
-- RestingAPL:Execute()
-- end
HealAPL:Execute()
-- if Player:IsAffectingCombat() and Target:Exists() and Target:IsHostile() then
-- DamageAPL:Execute()
-- end
end)
Bastion:Register(HolyModule)
local tab1 =
{
layoutConfig = { padding = { top = 40 } },
rows = {
[1] = { shadpr = { type = 'label', label = 'Open Combat' } },
[2] = { opener = { type = 'dropdown', label = 'Opener', column = 6, order = 1,
options = {
{ text = 'Shadow Word: Pain', value = 'swp'},
{ text = 'Shadow Crash', value = 'crash'},
{ text = 'None', value = 'none'},
},
initialValue = myconf:Read('opener', 'shield'),
onValueChanged = function(_, value) myconf:Write('opener', value) end }, },
[3] = { shadpr = { type = 'label', label = 'Buffs' } },
[4] = { pwf = { type = 'checkbox', label = 'Power Word: Fortitude', column = 12, order = 1,
initialValue = myconf:Read('pwf', false),
onValueChanged = function(_, flag) myconf:Write('pwf', flag) end }, },
[5] = { shadpr = { type = 'header', label = 'Defensives' } },
[6] = { 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 }, },
[7] = { 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 }, },
[8] = { shadpr = { type = 'header', label = 'Interrupts' } },
[9] = { 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 }, },
[10] = { shadpr = { type = 'header', label = 'Purify Disease' } },
[11] = { 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 }, },
[12] = { shadpr = { type = 'header', label = 'Dispel Magic' } },
[13] = { incombat = { type = 'checkbox', label = 'In Combat', column = 12, order = 1,
initialValue = myconf:Read('dispelic', false),
onValueChanged = function(_, flag) myconf:Write('dispelic', flag) end }, },
[14] = { shadpr = { type = 'header', label = 'Dispel Delay Time' } },
[15] = { 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 holypriestconfig = {
layoutConfig = { padding = { top = 30 } },
rows = {
[1] = {
container = {
type = 'tab',
fullSize = true,
tabs = {
{
name = 'player',
title = 'Player Settings',
layout = tab1
},
{
name = 'group',
title = 'Placeholder',
layout = tab2
}
},
}
},
},
}
Bastion.settingstemplate(holypriestconfig, 'Holy 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

@ -1,608 +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 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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,8 +1,13 @@
-- Document with emmy lua: https://emmylua.github.io/
-- Create an APL trait for the APL class
---@class APLTrait
local APLTrait = {}
APLTrait.__index = APLTrait
-- Constructor
---@param cb fun():boolean
---@return APLTrait
function APLTrait:New(cb)
local self = setmetatable({}, APLTrait)
@ -13,6 +18,7 @@ function APLTrait:New(cb)
end
-- Evaulate the APL trait
---@return boolean
function APLTrait:Evaluate()
if GetTime() - self.lastcall > 0.1 then
self.lastresult = self.cb()
@ -24,15 +30,18 @@ function APLTrait:Evaluate()
end
-- tostring
---@return string
function APLTrait:__tostring()
return "Bastion.__APLTrait"
end
-- Create an APL actor for the APL class
---@class APLActor
local APLActor = {}
APLActor.__index = APLActor
-- Constructor
---@param actor table
function APLActor:New(actor)
local self = setmetatable({}, APLActor)
@ -43,6 +52,8 @@ function APLActor:New(actor)
end
-- Add a trait to the APL actor
---@param ... APLTrait
---@return APLActor
function APLActor:AddTraits(...)
for _, trait in ipairs({ ... }) do
table.insert(self.traits, trait)
@ -52,11 +63,13 @@ function APLActor:AddTraits(...)
end
-- Get the actor
---@return table
function APLActor:GetActor()
return self.actor
end
-- Evaulate the APL actor
---@return boolean
function APLActor:Evaluate()
for _, trait in ipairs(self.traits) do
if not trait:Evaluate() then
@ -106,21 +119,25 @@ function APLActor:Execute()
end
-- has traits
---@return boolean
function APLActor:HasTraits()
return #self.traits > 0
end
-- tostring
---@return string
function APLActor:__tostring()
return "Bastion.__APLActor"
end
-- APL (Attack priority list) class
---@class APL
local APL = {}
APL.__index = APL
-- Constructor
---@param name string
---@return APL
function APL:New(name)
local self = setmetatable({}, APL)
@ -132,16 +149,23 @@ function APL:New(name)
end
-- Add a variable to the APL
---@param name string
---@param value any
function APL:SetVariable(name, value)
self.variables[name] = value
end
-- Get and evaluate a variable
---@param name string
---@return boolean
function APL:GetVariable(name)
return self.variables[name]
end
-- Add variable
---@param name string
---@param cb fun(...):any
---@return APLActor
function APL:AddVariable(name, cb)
local actor = APLActor:New({ variable = name, cb = cb, _apl = self })
table.insert(self.apl, actor)
@ -149,6 +173,9 @@ function APL:AddVariable(name, cb)
end
-- Add a manual action to the APL
---@param action string
---@param cb fun(...):any
---@return APLActor
function APL:AddAction(action, cb)
local actor = APLActor:New({ action = action, cb = cb })
table.insert(self.apl, actor)
@ -156,6 +183,9 @@ function APL:AddAction(action, cb)
end
-- Add a spell to the APL
---@param spell Spell
---@param condition fun(...):boolean
---@return APLActor
function APL:AddSpell(spell, condition)
local castableFunc = spell.CastableIfFunc
local target = spell:GetTarget()
@ -168,6 +198,9 @@ function APL:AddSpell(spell, condition)
end
-- Add an item to the APL
---@param item Item
---@param condition fun(...):boolean
---@return APLActor
function APL:AddItem(item, condition)
local usableFunc = item.UsableIfFunc
local target = item:GetTarget()
@ -180,6 +213,9 @@ function APL:AddItem(item, condition)
end
-- Add an APL to the APL (for sub APLs)
---@param apl APL
---@param condition fun(...):boolean
---@return APLActor
function APL:AddAPL(apl, condition)
if not condition then
error("Bastion: APL:AddAPL: No condition for APL " .. apl.name)
@ -201,6 +237,7 @@ function APL:Execute()
end
-- tostring
---@return string
function APL:__tostring()
return "Bastion.__APL(" .. self.name .. ")"
end

@ -1,3 +1,5 @@
-- Document with emmy lua: https://emmylua.github.io/
local Tinkr, Bastion = ...
-- Create a new Aura class
@ -19,6 +21,8 @@ function Aura:__index(k)
end
-- Equals
---@param other Aura|Spell
---@return boolean
function Aura:__eq(other)
if getmetatable(other) == Aura then
return self:GetSpell():GetID() == other:GetSpell():GetID()
@ -31,11 +35,16 @@ function Aura:__eq(other)
return false
end
-- tostring
---@return string
function Aura:__tostring()
return "Bastion.__Aura(" .. self:GetSpell():GetID() .. ")" .. " - " .. (self:GetName() or "''")
end
-- Constructor
---@param unit Unit
---@param index number
---@param type string
function Aura:New(unit, index, type)
if unit == nil then
local self = setmetatable({}, Aura)
@ -68,7 +77,8 @@ function Aura:New(unit, index, type)
end
local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal,
spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index, type)
spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index,
type)
local self = setmetatable({}, Aura)
self.aura = {
@ -98,6 +108,9 @@ function Aura:New(unit, index, type)
return self
end
-- Constructor
---@param unitAuraInfo UnitAuraInfo
---@return Aura
function Aura:CreateFromUnitAuraInfo(unitAuraInfo)
local self = setmetatable({}, Aura)
self.aura = {
@ -128,56 +141,67 @@ function Aura:CreateFromUnitAuraInfo(unitAuraInfo)
end
-- Check if the aura is valid
---@return boolean
function Aura:IsValid()
return self.aura.name ~= nil
end
-- Check if the aura is up
---@return boolean
function Aura:IsUp()
return self:IsValid() and (self:GetDuration() == 0 or self:GetRemainingTime() > 0)
end
-- Check if the aura is down
---@return boolean
function Aura:IsDown()
return not self:IsUp()
end
-- Get the auras index
---@return number
function Aura:GetIndex()
return self.aura.index
end
-- Get the auras type
---@return string
function Aura:GetType()
return self.aura.type
end
-- Get the auras name
---@return string
function Aura:GetName()
return self.aura.name
end
-- Get the auras icon
---@return string
function Aura:GetIcon()
return self.aura.icon
end
-- Get the auras count
---@return number
function Aura:GetCount()
return self.aura.count
end
-- Get the auras dispel type
---@return string
function Aura:GetDispelType()
return self.aura.dispelType
end
-- Get the auras duration
---@return number
function Aura:GetDuration()
return self.aura.duration
end
-- Get the auras remaining time
---@return number
function Aura:GetRemainingTime()
local remainingTime = self.aura.expirationTime - GetTime()
@ -189,71 +213,85 @@ function Aura:GetRemainingTime()
end
-- Get the auras expiration time
---@return number
function Aura:GetExpirationTime()
return self.aura.expirationTime
end
-- Get the auras source
---@return Unit
function Aura:GetSource()
return Bastion.UnitManager[self.aura.source]
end
-- Get the auras stealable status
---@return boolean
function Aura:GetIsStealable()
return self.aura.isStealable
end
-- Get the auras nameplate show personal status
---@return boolean
function Aura:GetNameplateShowPersonal()
return self.aura.nameplateShowPersonal
end
-- Get the auras spell id
---@return Spell
function Aura:GetSpell()
return Bastion.SpellBook:GetSpell(self.aura.spellId)
end
-- Get the auras can apply aura status
---@return boolean
function Aura:GetCanApplyAura()
return self.aura.canApplyAura
end
-- Get the auras is boss debuff status
---@return boolean
function Aura:GetIsBossDebuff()
return self.aura.isBossDebuff
end
-- Get the auras cast by player status
---@return boolean
function Aura:GetCastByPlayer()
return self.aura.castByPlayer
end
-- Get the auras nameplate show all status
---@return boolean
function Aura:GetNameplateShowAll()
return self.aura.nameplateShowAll
end
-- Get the auras time mod
---@return number
function Aura:GetTimeMod()
return self.aura.timeMod
end
-- Check if the aura is a buff
---@return boolean
function Aura:IsBuff()
return self.aura.type == "HELPFUL"
end
-- Check if the aura is a debuff
---@return boolean
function Aura:IsDebuff()
return self.aura.type == "HARMFUL"
end
-- Get aura instance id
---@return number
function Aura:GetAuraInstanceID()
return self.aura.auraInstanceID
end
-- Check if the aura is dispelable by a spell
---@param spell Spell
function Aura:IsDispelableBySpell(spell)
if self:GetDispelType() == nil then
return false

@ -5,15 +5,9 @@ local Tinkr, Bastion = ...
local AuraTable = {}
AuraTable.__index = AuraTable
local function tsize(t)
local keys = {}
for k, v in pairs(t) do
table.insert(keys, k)
end
return keys[#keys]
end
-- Constructor
---@param unit Unit
---@return AuraTable
function AuraTable:New(unit)
local self = setmetatable({}, AuraTable)
@ -28,6 +22,8 @@ function AuraTable:New(unit)
return self
end
---@param auras UnitAuraUpdateInfo
---@return nil
function AuraTable:OnUpdate(auras)
if not auras then
self:Update()
@ -73,6 +69,8 @@ function AuraTable:OnUpdate(auras)
end
end
---@param instanceID number
---@return nil
function AuraTable:RemoveInstanceID(instanceID)
if not self.instanceIDLookup[instanceID] then
return
@ -93,6 +91,10 @@ function AuraTable:RemoveInstanceID(instanceID)
end
end
-- Update the aura table
---@param instanceID number
---@param aura Aura
---@return nil
function AuraTable:AddOrUpdateAuraInstanceID(instanceID, aura)
local spellId = aura:GetSpell():GetID()
@ -114,6 +116,7 @@ function AuraTable:AddOrUpdateAuraInstanceID(instanceID, aura)
end
-- Get a units buffs
---@return nil
function AuraTable:GetUnitBuffs()
if Tinkr.classic then
for i = 1, 40 do
@ -152,6 +155,7 @@ function AuraTable:GetUnitBuffs()
end
-- Get a units debuffs
---@return nil
function AuraTable:GetUnitDebuffs()
if Tinkr.classic then
for i = 1, 40 do
@ -190,6 +194,7 @@ function AuraTable:GetUnitDebuffs()
end
-- Update auras
---@return nil
function AuraTable:Update()
-- print("Updating auras for " .. tostring(self.unit))
self:Clear()
@ -203,6 +208,7 @@ function AuraTable:Update()
end
-- Get a units auras
---@return table
function AuraTable:GetUnitAuras()
if not self.did then
self.did = true
@ -226,6 +232,7 @@ function AuraTable:GetUnitAuras()
end
-- Get a units auras
---@return table
function AuraTable:GetMyUnitAuras()
if not self.did then
self.did = true
@ -249,6 +256,7 @@ function AuraTable:GetMyUnitAuras()
end
-- Clear the aura table
---@return nil
function AuraTable:Clear()
self.auras = {}
self.playerAuras = {}
@ -256,6 +264,7 @@ function AuraTable:Clear()
end
-- Check if the unit has a specific aura
---@param spell Spell
---@return Aura
function AuraTable:Find(spell)
local auras = self:GetUnitAuras()
@ -281,6 +290,8 @@ function AuraTable:Find(spell)
return Bastion.Aura:New()
end
-- Check if the unit has a specific aura
---@param spell Spell
---@return Aura
function AuraTable:FindMy(spell)
local auras = self:GetMyUnitAuras()
@ -305,6 +316,10 @@ function AuraTable:FindMy(spell)
return Bastion.Aura:New()
end
-- Check if the unit has a specific aura
---@param spell Spell
---@param source Unit
---@return Aura
function AuraTable:FindFrom(spell, source)
local auras = self:GetUnitAuras()
local aurasub = auras[spell:GetID()]
@ -331,6 +346,8 @@ function AuraTable:FindFrom(spell, source)
end
-- Find the aura from the current unit
---@param spell Spell
---@return Aura
function AuraTable:FindTheirs(spell)
local auras = self:GetUnitAuras()
local aurasub = auras[spell:GetID()]
@ -357,6 +374,7 @@ function AuraTable:FindTheirs(spell)
end
-- Find any
---@param spell Spell
---@return Aura
function AuraTable:FindAny(spell)
local a = self:Find(spell)
@ -368,6 +386,7 @@ function AuraTable:FindAny(spell)
end
-- Has any stealable aura
---@return boolean
function AuraTable:HasAnyStealableAura()
for _, auras in pairs(self:GetUnitAuras()) do
for _, aura in pairs(auras) do
@ -385,6 +404,8 @@ function AuraTable:HasAnyStealableAura()
end
-- Has any dispelable aura
---@param spell Spell
---@return boolean
function AuraTable:HasAnyDispelableAura(spell)
for _, auras in pairs(self:GetUnitAuras()) do
for _, aura in pairs(auras) do

@ -1,13 +1,19 @@
---@class Cache
local Cache = {}
Cache.__index = Cache
-- Constructor
---@return Cache
function Cache:New()
local self = setmetatable({}, Cache)
self.cache = {}
return self
end
---@param key any
---@param value any
---@param duration number
---@return nil
function Cache:Set(key, value, duration)
self.cache = self.cache or {}
self.cache[key] = {
@ -17,6 +23,8 @@ function Cache:Set(key, value, duration)
}
end
---@param key any
---@return any
function Cache:Get(key)
self.cache = self.cache or {}
local cache = self.cache[key]
@ -30,6 +38,8 @@ function Cache:Get(key)
return nil
end
---@param key any
---@return boolean
function Cache:IsCached(key)
self.cache = self.cache or {}
local cache = self.cache[key]

@ -1,10 +1,14 @@
local Tinkr, Bastion = ...
-- Define a Cacheable class
---@class Cacheable
local Cacheable = {
cache = 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
@ -26,11 +30,14 @@ function Cacheable:__index(k)
end
-- When the object is accessed return the value
---@return string
function Cacheable:__tostring()
return "Bastion.__Cacheable(" .. tostring(self.value) .. ")"
end
-- Create
---@param value any
---@param cb fun():any
function Cacheable:New(value, cb)
local self = setmetatable({}, Cacheable)
@ -44,6 +51,7 @@ function Cacheable:New(value, cb)
end
-- Try to update the value
---@return nil
function Cacheable:TryUpdate()
if self.cache:IsCached("value") then
self.value = self.callback()
@ -51,16 +59,19 @@ function Cacheable:TryUpdate()
end
-- Update the value
---@return nil
function Cacheable:Update()
self.value = self.callback()
end
-- Set a new value
---@param value any
function Cacheable:Set(value)
self.value = value
end
-- Set a new callback
---@param cb fun():any
function Cacheable:SetCallback(cb)
self.callback = cb
end

@ -1,6 +1,7 @@
local Tinkr, Bastion = ...
-- Create a new Class class
---@class Class
local Class = {}
function Class:__index(k)
@ -18,6 +19,9 @@ function Class:__index(k)
end
-- Constructor
---@param locale string
---@param name string
---@param id number
function Class:New(locale, name, id)
local self = setmetatable({}, Class)
self.class = {
@ -29,21 +33,25 @@ function Class:New(locale, name, id)
end
-- Get the classes locale
---@return string
function Class:GetLocale()
return self.class.locale
end
-- Get the classes name
---@return string
function Class:GetName()
return self.class.name
end
-- Get the classes id
---@return number
function Class:GetID()
return self.class.id
end
-- Return the classes color
---@return ColorMixin classColor
function Class:GetColor()
return C_ClassColor.GetClassColor(self.class.name)
end

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

@ -1,12 +1,14 @@
-- Create a wow command handler class
---@class Command
local Command = {}
Command.__index = Command
---@return string
function Command:__tostring()
return "Command(" .. self.command .. ")"
end
---@param prefix string
function Command:New(prefix)
local self = setmetatable({}, Command)
@ -21,6 +23,10 @@ function Command:New(prefix)
return self
end
---@param command string
---@param helpmsg string
---@param cb fun(args: table)
---@return nil
function Command:Register(command, helpmsg, cb)
self.commands[command] = {
helpmsg = helpmsg,
@ -28,6 +34,8 @@ function Command:Register(command, helpmsg, cb)
}
end
---@param msg string
---@return table
function Command:Parse(msg)
local args = {}
for arg in msg:gmatch("%S+") do
@ -37,6 +45,8 @@ function Command:Parse(msg)
return args
end
---@param msg string
---@return nil
function Command:OnCommand(msg)
local args = self:Parse(msg)
@ -51,6 +61,7 @@ function Command:OnCommand(msg)
end
end
---@return nil
function Command:PrintHelp()
for k, v in pairs(self.commands) do
print('/' .. self.prefix .. ' ' .. k .. " - " .. v.helpmsg)

@ -1,5 +1,5 @@
-- Create an EventManager class
---@class EventManager
local EventManager = {
events = {},
eventHandlers = {},
@ -10,6 +10,7 @@ local EventManager = {
EventManager.__index = EventManager
-- Constructor
---@return EventManager
function EventManager:New()
local self = setmetatable({}, EventManager)
self.events = {}
@ -31,6 +32,9 @@ function EventManager:New()
end
-- Register an event
---@param event string
---@param handler fun(...)
---@return nil
function EventManager:RegisterEvent(event, handler)
if not self.events[event] then
self.events[event] = {}
@ -40,6 +44,9 @@ function EventManager:RegisterEvent(event, handler)
end
-- Register a wow event
---@param event string
---@param handler fun(...)
---@return nil
function EventManager:RegisterWoWEvent(event, handler)
if not self.wowEventHandlers[event] then
self.wowEventHandlers[event] = {}
@ -50,6 +57,9 @@ function EventManager:RegisterWoWEvent(event, handler)
end
-- Trigger an event
---@param event string
---@param ... any
---@return nil
function EventManager:TriggerEvent(event, ...)
if self.events[event] then
for _, handler in pairs(self.events[event]) do

@ -31,16 +31,20 @@ function Item:__index(k)
end
-- Equals
---@param other Item
---@return boolean
function Item:__eq(other)
return self:GetID() == other:GetID()
end
-- tostring
---@return string
function Item:__tostring()
return "Bastion.__Item(" .. self:GetID() .. ")" .. " - " .. self:GetName()
end
-- Constructor
---@param id number
function Item:New(id)
local self = setmetatable({}, Item)
@ -57,47 +61,58 @@ function Item:New(id)
end
-- Get the Items id
---@return number
function Item:GetID()
return self.ItemID
end
-- Get the Items name
---@return string
function Item:GetName()
return GetItemInfo(self:GetID())
end
-- Get the Items icon
---@return number
function Item:GetIcon()
return select(3, GetItemInfo(self:GetID()))
end
-- Get the Items cooldown
---@return number
function Item:GetCooldown()
return select(2, C_Container.GetItemCooldown(self:GetID()))
end
-- Return the Usable function
---@return function | boolean
function Item:GetUsableFunction()
return self.UsableIfFunc
end
-- Return the preUse function
---@return function | boolean
function Item:GetPreUseFunction()
return self.PreUseFunc
end
-- Get the on Use func
---@return function | boolean
function Item:GetOnUseFunction()
return self.OnUseFunc
end
-- Get the Items cooldown remaining
---@return number
function Item:GetCooldownRemaining()
local start, duration = C_Container.GetItemCooldown(self:GetID())
return start + duration - GetTime()
end
-- Use the Item
---@param unit Unit
---@param condition string
---@return boolean
function Item:Use(unit, condition)
if condition and not self:EvaluateCondition(condition) then
return false
@ -127,46 +142,56 @@ function Item:Use(unit, condition)
if self:GetOnUseFunction() then
self:GetOnUseFunction()(self)
end
return true
end
-- Last use attempt
---@return number
function Item:GetLastUseAttempt()
return self.lastUseAttempt
end
-- Time since last attepmt
---@return number
function Item:GetTimeSinceLastUseAttempt()
return GetTime() - self:GetLastUseAttempt()
end
-- Check if the Item is known
---@return boolean
function Item:IsEquipped()
return IsEquippedItem(self:GetID())
end
-- Check if the Item is on cooldown
---@return boolean
function Item:IsOnCooldown()
return select(2, C_Container.GetItemCooldown(self:GetID())) > 0
end
-- Check if the Item is usable
---@return boolean
function Item:IsUsable()
local usable, noMana = IsUsableItem(self:GetID())
return usable or usableExcludes[self:GetID()]
end
-- Check if the Item is Usable
---@return boolean
function Item:IsEquippedAndUsable()
return ((self:IsEquippable() and self:IsEquipped()) or
(not self:IsEquippable() and self:IsUsable())) and not self:IsOnCooldown()
end
-- Is equippable
---@return boolean
function Item:IsEquippable()
return IsEquippableItem(self:GetID())
end
-- Check if the Item is Usable
---@return boolean
function Item:Usable()
if self:GetUsableFunction() then
return self:GetUsableFunction()(self)
@ -177,6 +202,7 @@ end
-- Set a script to check if the Item is Usable
---@param func fun(self:Item):boolean
---@return Item
function Item:UsableIf(func)
self.UsableIfFunc = func
return self
@ -184,6 +210,7 @@ end
-- Set a script to run before the Item has been Use
---@param func fun(self:Item)
---@return Item
function Item:PreUse(func)
self.PreUseFunc = func
return self
@ -191,17 +218,23 @@ end
-- Set a script to run after the Item has been Use
---@param func fun(self:Item)
---@return Item
function Item:OnUse(func)
self.OnUseFunc = func
return self
end
-- Get was looking
---@return boolean
function Item:GetWasLooking()
return self.wasLooking
end
-- Click the Item
---@param x number
---@param y number
---@param z number
---@return boolean
function Item:Click(x, y, z)
if type(x) == 'table' then
x, y, z = x.x, x.y, x.z
@ -218,6 +251,8 @@ function Item:Click(x, y, z)
end
-- Check if the Item is Usable and Use it
---@param unit Unit
---@return boolean
function Item:Call(unit)
if self:Usable() then
self:Use(unit)
@ -227,6 +262,8 @@ function Item:Call(unit)
end
-- Check if the Item is in range of the unit
---@param unit Unit
---@return boolean
function Item:IsInRange(unit)
local name, rank, icon, UseTime, Itemmin, Itemmax, ItemID = GetItemInfo(self:GetID())
@ -263,11 +300,13 @@ function Item:IsInRange(unit)
end
-- Get the last use time
---@return number
function Item:GetLastUseTime()
return Bastion.SpellBook:GetSpell(self:GetID()):GetLastCastTime()
end
-- Get time since last use
---@return number
function Item:GetTimeSinceLastUse()
if not self:GetLastUseTime() then
return math.huge
@ -276,11 +315,13 @@ function Item:GetTimeSinceLastUse()
end
-- Get the Items charges
---@return number
function Item:GetCharges()
return GetItemCharges(self:GetID())
end
-- Get the Items charges remaining
---@return number
function Item:GetChargesRemaining()
local charges, maxCharges, start, duration = GetItemCharges(self:GetID())
return charges
@ -289,6 +330,7 @@ end
-- Create a condition for the Item
---@param name string
---@param func fun(self:Item)
---@return Item
function Item:Condition(name, func)
self.conditions[name] = {
func = func
@ -297,6 +339,8 @@ function Item:Condition(name, func)
end
-- Get a condition for the Item
---@param name string
---@return function | nil
function Item:GetCondition(name)
local condition = self.conditions[name]
if condition then
@ -307,6 +351,8 @@ function Item:GetCondition(name)
end
-- Evaluate a condition for the Item
---@param name string
---@return boolean
function Item:EvaluateCondition(name)
local condition = self:GetCondition(name)
if condition then
@ -317,6 +363,8 @@ function Item:EvaluateCondition(name)
end
-- Check if the Item has a condition
---@param name string
---@return boolean
function Item:HasCondition(name)
local condition = self:GetCondition(name)
if condition then
@ -327,17 +375,21 @@ function Item:HasCondition(name)
end
-- Set the Items target
---@param unit Unit
---@return Item
function Item:SetTarget(unit)
self.target = unit
return self
end
-- Get the Items target
---@return Unit | nil
function Item:GetTarget()
return self.target
end
-- IsMagicDispel
---@return boolean
function Item:IsMagicDispel()
return ({
[88423] = true
@ -345,6 +397,7 @@ function Item:IsMagicDispel()
end
-- IsCurseDispel
---@return boolean
function Item:IsCurseDispel()
return ({
[88423] = true
@ -352,6 +405,7 @@ function Item:IsCurseDispel()
end
-- IsPoisonDispel
---@return boolean
function Item:IsPoisonDispel()
return ({
[88423] = true
@ -359,16 +413,21 @@ function Item:IsPoisonDispel()
end
-- IsDiseaseDispel
---@return boolean
function Item:IsDiseaseDispel()
return ({
})[self:GetID()]
end
---@param item Item
---@return boolean
function Item:IsItem(item)
return self:GetID() == item:GetID()
end
-- Get the Items spell
---@return Spell | nil
function Item:GetSpell()
if self.spellID then
return Bastion.SpellBook:GetSpell(self.spellID)

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

@ -22,32 +22,42 @@ local List = {
}
List.__index = List
---@param from table | nil
---@return List
function List:New(from)
local self = setmetatable({}, List)
self._list = from or {}
return self
end
---@param value any
---@return nil
function List:push(value)
table.insert(self._list, value)
end
---@return any
function List:pop()
return table.remove(self._list)
end
---@return any
function List:peek()
return self._list[#self._list]
end
---@return number
function List:count()
return #self._list
end
---@return nil
function List:clear()
self._list = {}
end
---@param value any
---@return boolean
function List:contains(value)
for _, v in ipairs(self._list) do
if v == value then
@ -57,6 +67,8 @@ function List:contains(value)
return false
end
---@param value any
---@return boolean
function List:remove(value)
for i, v in ipairs(self._list) do
if v == value then
@ -67,6 +79,8 @@ function List:remove(value)
return false
end
---@param callback fun(value: any): boolean
---@return nil
function List:each(callback)
for _, v in ipairs(self._list) do
if callback(v) then
@ -75,6 +89,8 @@ function List:each(callback)
end
end
---@param callback fun(value: any): boolean
---@return boolean
function List:map(callback)
local newList = List.new()
for _, v in ipairs(self._list) do
@ -83,6 +99,8 @@ function List:map(callback)
return newList
end
---@param callback fun(value: any): boolean
---@return boolean
function List:filter(callback)
local newList = List.new()
for _, v in ipairs(self._list) do
@ -93,6 +111,9 @@ function List:filter(callback)
return newList
end
---@param callback fun(value: any): boolean
---@param initialValue any
---@return boolean
function List:reduce(callback, initialValue)
local result = initialValue
for _, v in ipairs(self._list) do
@ -101,6 +122,8 @@ function List:reduce(callback, initialValue)
return result
end
---@param callback fun(value: any): boolean
---@return boolean | nil
function List:find(callback)
for _, v in ipairs(self._list) do
if callback(v) then
@ -110,6 +133,8 @@ function List:find(callback)
return nil
end
---@param callback fun(value: any): boolean
---@return number | nil
function List:findIndex(callback)
for i, v in ipairs(self._list) do
if callback(v) then
@ -119,10 +144,13 @@ function List:findIndex(callback)
return nil
end
---@param callback fun(value: any): boolean
---@return nil
function List:sort(callback)
table.sort(self._list, callback)
end
---@return List
function List:reverse()
local newList = List.new()
for i = #self._list, 1, -1 do
@ -131,6 +159,7 @@ function List:reverse()
return newList
end
---@return List
function List:clone()
local newList = List.new()
for _, v in ipairs(self._list) do
@ -139,6 +168,8 @@ function List:clone()
return newList
end
---@param list List
---@return List
function List:concat(list)
local newList = List.new()
for _, v in ipairs(self._list) do
@ -150,6 +181,8 @@ function List:concat(list)
return newList
end
---@param separator string
---@return string
function List:join(separator)
local result = ""
for i, v in ipairs(self._list) do
@ -161,10 +194,12 @@ function List:join(separator)
return result
end
---@return string
function List:toString()
return self:join(", ")
end
---@return string
function List:__tostring()
return self:toString()
end

@ -1,13 +1,18 @@
-- Create a module class for a bastion module
---@class Module
local Module = {}
Module.__index = Module
-- __tostring
---@return string
function Module:__tostring()
return "Bastion.__Module(" .. self.name .. ")"
end
-- Constructor
---@param name string
---@return Module
function Module:New(name)
local module = {}
setmetatable(module, Module)
@ -20,16 +25,19 @@ function Module:New(name)
end
-- Enable the module
---@return nil
function Module:Enable()
self.enabled = true
end
-- Disable the module
---@return nil
function Module:Disable()
self.enabled = false
end
-- Toggle the module
---@return nil
function Module:Toggle()
if self.enabled then
self:Disable()
@ -39,11 +47,15 @@ function Module:Toggle()
end
-- Add a function to the sync list
---@param func function
---@return nil
function Module:Sync(func)
table.insert(self.synced, func)
end
-- Remove a function from the sync list
---@param func function
---@return nil
function Module:Unsync(func)
for i = 1, #self.synced do
if self.synced[i] == func then
@ -54,6 +66,7 @@ function Module:Unsync(func)
end
-- Sync
---@return nil
function Module:Tick()
if self.enabled then
for i = 1, #self.synced do

@ -12,6 +12,7 @@ local MythicPlusUtils = {
MythicPlusUtils.__index = MythicPlusUtils
---@return MythicPlusUtils
function MythicPlusUtils:New()
local self = setmetatable({}, MythicPlusUtils)
@ -148,14 +149,19 @@ function MythicPlusUtils:New()
return self
end
---@return nil
function MythicPlusUtils:ToggleDebuffLogging()
self.debuffLogging = not self.debuffLogging
end
---@return nil
function MythicPlusUtils:ToggleCastLogging()
self.castLogging = not self.castLogging
end
---@param unit Unit
---@param percent number
---@return boolean
function MythicPlusUtils:CastingCriticalKick(unit, percent)
local castingSpell = unit:GetCastingOrChannelingSpell()

@ -1,24 +1,26 @@
-- Create a NotificationsList class
---@class NotificationsList
local NotificationsList = {
notifications = {}
}
NotificationsList.__index = NotificationsList
-- Constructor
---@return NotificationsList
function NotificationsList:New()
local self = setmetatable({}, NotificationsList)
-- Create a frame for the notifications
self.frame = CreateFrame("Frame", "BastionNotificationsList", UIParent)
self.frame:SetSize(300, 100)
self.frame:SetSize(600, 60)
self.frame:SetPoint("TOP", UIParent, "TOP", 0, -100)
self.frame:SetFrameStrata("HIGH")
-- Remove notifications after 5 seconds
C_Timer.NewTicker(0.1, function()
for i, notification in ipairs(self.notifications) do
if GetTime() - notification.addedAt > 2 then
if GetTime() - notification.addedAt > notification.duration then
notification:Remove()
table.remove(self.notifications, i)
end
@ -29,18 +31,26 @@ function NotificationsList:New()
end
-- Create a notification class for the notifications list (takes icon and text)
---@class Notification
local Notification = {
}
Notification.__index = Notification
-- Constructor
function Notification:New(list, icon, text)
---@param list NotificationsList
---@param icon string
---@param text string
---@param duration number
---@return Notification
function Notification:New(list, icon, text, duration)
local self = setmetatable({}, Notification)
if not duration then duration = 2 end
-- Create a frame for the notification
self.frame = CreateFrame("Frame", nil, list.frame)
self.frame:SetSize(300, 100)
self.frame:SetPoint("TOP", list.frame, "TOP", 0, 0)
self.frame:SetSize(5, 5)
self.frame:SetPoint("CENTER", list.frame, "CENTER", 0, 0)
self.frame:SetFrameStrata("HIGH")
-- Create a texture for the icon
@ -50,18 +60,23 @@ function Notification:New(list, icon, text)
self.icon:SetTexture(icon)
-- Create a fontstring for the text
self.text = self.frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
self.text:SetPoint("CENTER", self.frame, "CENTER", 10, 0)
self.text = self.frame:CreateFontString(nil, "BACKGROUND", "NumberFontNormal")
self.text:SetPoint("LEFT", self.frame, "LEFT", 32 + 16, 0)
self.text:SetText(text)
self.text:SetFont("Fonts\\FRIZQT__.TTF", 14)
self.text:SetFont("Fonts\\OpenSans-Bold.ttf", 18)
-- set the frame size to the size of the text + icon
self.frame:SetSize(self.text:GetStringWidth() + 32 + 16, 32)
self.addedAt = GetTime()
self.duration = duration
self.list = list
return self
end
-- Remove notification
---@return nil
function Notification:Remove()
-- Fade out the notification frame and remove it after the fade
UIFrameFadeOut(self.frame, 0.2, 1, 0)
@ -75,9 +90,13 @@ function Notification:Remove()
end
-- Add a notification to the list
function NotificationsList:AddNotification(icon, text)
---@param icon string
---@param text string
---@param duration number
---@return nil
function NotificationsList:AddNotification(icon, text, duration)
-- Create a new notification
local notification = Notification:New(self, icon, text)
local notification = Notification:New(self, icon, text, duration)
-- Add the notification to the list
table.insert(self.notifications, notification)
@ -88,15 +107,18 @@ function NotificationsList:AddNotification(icon, text)
end
-- Update the notifications
---@return nil
function NotificationsList:Update()
-- Loop through the notifications
for i, notification in ipairs(self.notifications) do
-- Set the position of the notification
notification.frame:SetPoint("TOP", self.frame, "TOP", 0, -50 * (i - 1))
notification.frame:SetPoint("CENTER", self.frame, "CENTER", 0, -42 * (i - 1))
end
end
-- Remove a notification from the list
---@param notification Notification
---@return nil
function NotificationsList:RemoveNotification(notification)
-- Loop through the notifications
for i, v in ipairs(self.notifications) do
@ -111,6 +133,7 @@ function NotificationsList:RemoveNotification(notification)
end
-- Remove all notifications from the list
---@return nil
function NotificationsList:RemoveAllNotifications()
-- Loop through the notifications
for i, v in ipairs(self.notifications) do

@ -18,6 +18,9 @@ function ObjectManager:New()
end
-- Register a custom list with a callback
---@param name string
---@param cb function
---@return List
function ObjectManager:RegisterList(name, cb)
if self._lists[name] then
return false
@ -32,6 +35,7 @@ function ObjectManager:RegisterList(name, cb)
end
-- reset custom lists
---@return nil
function ObjectManager:ResetLists()
for _, list in pairs(self._lists) do
list.list:clear()
@ -39,6 +43,8 @@ function ObjectManager:ResetLists()
end
-- Refresh custom lists
---@param object table
---@return nil
function ObjectManager:EnumLists(object)
for _, list in pairs(self._lists) do
local r = list.cb(object)
@ -49,10 +55,14 @@ function ObjectManager:EnumLists(object)
end
-- Get a list
---@param name string
---@return List
function ObjectManager:GetList(name)
return self._lists[name].list
end
-- Refresh all lists
---@return nil
function ObjectManager:Refresh()
self.enemies:clear()
self.friends:clear()
@ -61,6 +71,7 @@ function ObjectManager:Refresh()
self:ResetLists()
local objects = Objects()
local _, _, _, _, _, _, _, instanceID = GetInstanceInfo()
for _, object in pairs(objects) do
self:EnumLists(object)
@ -74,7 +85,7 @@ function ObjectManager:Refresh()
if unit:GetID() == 120651 then
self.explosives:push(unit)
elseif unit:IsPlayer() and unit:IsInParty() then
elseif (unit:IsPlayer() and unit:IsInParty()) or (instanceID == 1148 and unit:IsInParty()) then
self.friends:push(unit)
elseif unit:IsEnemy() then
self.enemies:push(unit)

@ -22,11 +22,15 @@ function Refreshable:__index(k)
end
-- When the object is accessed return the value
---@return string
function Refreshable:__tostring()
return "Bastion.__Refreshable(" .. tostring(rawget(self, 'value')) .. ")"
end
-- Create
---@param value any
---@param cb function
---@return Refreshable
function Refreshable:New(value, cb)
local self = setmetatable({}, Refreshable)
@ -40,6 +44,7 @@ function Refreshable:New(value, cb)
end
-- Try to update the value
---@return nil
function Refreshable:TryUpdate()
if self.cache:IsCached("value") then
self.value = self.callback()
@ -47,16 +52,21 @@ function Refreshable:TryUpdate()
end
-- Update the value
---@return nil
function Refreshable:Update()
self.value = self.callback()
end
-- Set a new value
---@param value any
---@return nil
function Refreshable:Set(value)
self.value = value
end
-- Set a new callback
---@param cb function
---@return nil
function Refreshable:SetCallback(cb)
self.callback = cb
end

@ -32,16 +32,21 @@ function Spell:__index(k)
end
-- Equals
---@param other Spell
---@return boolean
function Spell:__eq(other)
return self:GetID() == other:GetID()
end
-- tostring
---@return string
function Spell:__tostring()
return "Bastion.__Spell(" .. self:GetID() .. ")" .. " - " .. self:GetName()
end
-- Constructor
---@param id number
---@return Spell
function Spell:New(id)
local self = setmetatable({}, Spell)
@ -51,59 +56,72 @@ function Spell:New(id)
end
-- Get the spells id
---@return number
function Spell:GetID()
return self.spellID
end
-- Add post cast func
---@param func fun(self:Spell)
---@return Spell
function Spell:PostCast(func)
self.PostCastFunc = func
return self
end
-- Get the spells name
---@return string
function Spell:GetName()
return GetSpellInfo(self:GetID())
end
-- Get the spells icon
---@return number
function Spell:GetIcon()
return select(3, GetSpellInfo(self:GetID()))
end
-- Get the spells cooldown
---@return number
function Spell:GetCooldown()
return select(2, GetSpellCooldown(self:GetID()))
end
-- Return the castable function
---@return fun(self:Spell):boolean
function Spell:GetCastableFunction()
return self.CastableIfFunc
end
-- Return the precast function
---@return fun(self:Spell)
function Spell:GetPreCastFunction()
return self.PreCastFunc
end
-- Get the on cast func
---@return fun(self:Spell)
function Spell:GetOnCastFunction()
return self.OnCastFunc
end
-- Get the spells cooldown remaining
---@return number
function Spell:GetCooldownRemaining()
local start, duration = GetSpellCooldown(self:GetID())
return start + duration - GetTime()
end
-- On cooldown
---@return boolean
function Spell:OnCooldown()
return self:GetCooldownRemaining() > 0
end
-- Cast the spell
---@param unit Unit
---@param condition string
---@return boolean
function Spell:Cast(unit, condition)
if condition and not self:EvaluateCondition(condition) then
return false
@ -140,14 +158,18 @@ function Spell:Cast(unit, condition)
if self:GetOnCastFunction() then
self:GetOnCastFunction()(self)
end
return true
end
-- Get post cast func
---@return fun(self:Spell)
function Spell:GetPostCastFunction()
return self.PostCastFunc
end
-- Check if the spell is known
---@return boolean
function Spell:IsKnown()
local isKnown = IsSpellKnown(self:GetID())
local isPlayerSpell = IsPlayerSpell(self:GetID())
@ -155,22 +177,26 @@ function Spell:IsKnown()
end
-- Check if the spell is on cooldown
---@return boolean
function Spell:IsOnCooldown()
return select(2, GetSpellCooldown(self:GetID())) > 0
end
-- Check if the spell is usable
---@return boolean
function Spell:IsUsable()
local usable, noMana = IsUsableSpell(self:GetID())
return usable or usableExcludes[self:GetID()]
end
-- Check if the spell is castable
---@return boolean
function Spell:IsKnownAndUsable()
return self:IsKnown() and not self:IsOnCooldown() and self:IsUsable()
end
-- Check if the spell is castable
---@return boolean
function Spell:Castable()
if self:GetCastableFunction() then
return self:GetCastableFunction()(self)
@ -181,6 +207,7 @@ end
-- Set a script to check if the spell is castable
---@param func fun(spell:Spell):boolean
---@return Spell
function Spell:CastableIf(func)
self.CastableIfFunc = func
return self
@ -188,6 +215,7 @@ end
-- Set a script to run before the spell has been cast
---@param func fun(spell:Spell)
---@return Spell
function Spell:PreCast(func)
self.PreCastFunc = func
return self
@ -195,17 +223,23 @@ end
-- Set a script to run after the spell has been cast
---@param func fun(spell:Spell)
---@return Spell
function Spell:OnCast(func)
self.OnCastFunc = func
return self
end
-- Get was looking
---@return boolean
function Spell:GetWasLooking()
return self.wasLooking
end
-- Click the spell
---@param x number
---@param y number
---@param z number
---@return boolean
function Spell:Click(x, y, z)
if type(x) == 'table' then
x, y, z = x.x, x.y, x.z
@ -222,6 +256,8 @@ function Spell:Click(x, y, z)
end
-- Check if the spell is castable and cast it
---@param unit Unit
---@return boolean
function Spell:Call(unit)
if self:Castable() then
self:Cast(unit)
@ -230,11 +266,15 @@ function Spell:Call(unit)
return false
end
-- Check if the spell is castable and cast it
---@return boolean
function Spell:HasRange()
return SpellHasRange(self:GetName())
end
-- Check if the spell is in range of the unit
---@param unit Unit
---@return boolean
function Spell:IsInRange(unit)
local hasRange = self:HasRange()
local inRange = IsSpellInRange(self:GetName(), unit:GetOMToken())
@ -251,11 +291,13 @@ function Spell:IsInRange(unit)
end
-- Get the last cast time
---@return number
function Spell:GetLastCastTime()
return self.lastCastAt
end
-- Get time since last cast
---@return number
function Spell:GetTimeSinceLastCast()
if not self:GetLastCastTime() then
return math.huge
@ -264,10 +306,13 @@ function Spell:GetTimeSinceLastCast()
end
-- Get the spells charges
---@return number
function Spell:GetCharges()
return GetSpellCharges(self:GetID())
end
-- Get the spells charges
---@return number
function Spell:GetChargesFractional()
local charges, maxCharges, start, duration = GetSpellCharges(self:GetID())
@ -288,12 +333,16 @@ function Spell:GetChargesFractional()
end
-- Get the spells charges remaining
---@return number
function Spell:GetChargesRemaining()
local charges, maxCharges, start, duration = GetSpellCharges(self:GetID())
return charges
end
-- Create a condition for the spell
---@param name string
---@param func fun(self:Spell):boolean
---@return Spell
function Spell:Condition(name, func)
self.conditions[name] = {
func = func
@ -302,6 +351,8 @@ function Spell:Condition(name, func)
end
-- Get a condition for the spell
---@param name string
---@return function | nil
function Spell:GetCondition(name)
local condition = self.conditions[name]
if condition then
@ -312,6 +363,8 @@ function Spell:GetCondition(name)
end
-- Evaluate a condition for the spell
---@param name string
---@return boolean
function Spell:EvaluateCondition(name)
local condition = self:GetCondition(name)
if condition then
@ -322,6 +375,8 @@ function Spell:EvaluateCondition(name)
end
-- Check if the spell has a condition
---@param name string
---@return boolean
function Spell:HasCondition(name)
local condition = self:GetCondition(name)
if condition then
@ -332,17 +387,21 @@ function Spell:HasCondition(name)
end
-- Set the spells target
---@param unit Unit
---@return Spell
function Spell:SetTarget(unit)
self.target = unit
return self
end
-- Get the spells target
---@return Unit
function Spell:GetTarget()
return self.target
end
-- IsMagicDispel
---@return boolean
function Spell:IsMagicDispel()
return ({
[88423] = true
@ -350,6 +409,7 @@ function Spell:IsMagicDispel()
end
-- IsCurseDispel
---@return boolean
function Spell:IsCurseDispel()
return ({
[88423] = true
@ -357,6 +417,7 @@ function Spell:IsCurseDispel()
end
-- IsPoisonDispel
---@return boolean
function Spell:IsPoisonDispel()
return ({
[88423] = true
@ -364,12 +425,16 @@ function Spell:IsPoisonDispel()
end
-- IsDiseaseDispel
---@return boolean
function Spell:IsDiseaseDispel()
return ({
})[self:GetID()]
end
-- IsSpell
---@param spell Spell
---@return boolean
function Spell:IsSpell(spell)
return self:GetID() == spell:GetID()
end

@ -1,10 +1,12 @@
local Tinkr, Bastion = ...
-- Create a new SpellBook class
---@class SpellBook
local SpellBook = {}
SpellBook.__index = SpellBook
-- Constructor
---@return SpellBook
function SpellBook:New()
local self = setmetatable({}, SpellBook)
self.spells = {}
@ -12,6 +14,7 @@ function SpellBook:New()
end
-- Get a spell from the spellbook
---@return Spell
function SpellBook:GetSpell(id)
if self.spells[id] == nil then
self.spells[id] = Bastion.Spell:New(id)
@ -20,6 +23,25 @@ function SpellBook:GetSpell(id)
return self.spells[id]
end
---@param ... number[]
---@return Spell, ... Spell
function SpellBook:GetSpells(...)
local spells = {}
for _, id in ipairs({ ... }) do
table.insert(spells, self:GetSpell(id))
end
return unpack(spells)
end
---@param name string
---@return Spell
function SpellBook:GetSpellByName(name)
local _, rank, icon, castTime, minRange, maxRange, spellID, originalIcon = GetSpellInfo(name)
return self:GetSpell(spellID)
end
---@return Spell
function SpellBook:GetIfRegistered(id)
return self.spells[id]
end

@ -1,6 +1,7 @@
local Tinkr, Bastion = ...
-- Create a new Timer class
---@class Timer
local Timer = {
startTime = nil,
resetAfterCombat = false,
@ -8,6 +9,8 @@ local Timer = {
Timer.__index = Timer
-- Constructor
---@param type string
---@return Timer
function Timer:New(type)
local self = setmetatable({}, Timer)
self.startTime = nil
@ -16,11 +19,13 @@ function Timer:New(type)
end
-- Start the timer
---@return nil
function Timer:Start()
self.startTime = GetTime()
end
-- Get the time since the timer was started
---@return number
function Timer:GetTime()
if not self:IsRunning() then
return 0
@ -29,11 +34,13 @@ function Timer:GetTime()
end
-- Check if the timer is running
---@return boolean
function Timer:IsRunning()
return self.startTime ~= nil
end
-- Reset the timer
---@return nil
function Timer:Reset()
self.startTime = nil
end

@ -34,16 +34,26 @@ function Unit:__index(k)
end
-- Equals
---@param other Unit
---@return boolean
function Unit:__eq(other)
return UnitIsUnit(self:GetOMToken(), other.unit)
end
-- tostring
---ToString
---
---```lua
---print(Unit:New('player'))
---```
---@return string
function Unit:__tostring()
return "Bastion.__Unit(" .. tostring(self:GetOMToken()) .. ")" .. " - " .. (self:GetName() or '')
end
-- Constructor
---@param unit string
---@return Unit
function Unit:New(unit)
local self = setmetatable({}, Unit)
self.unit = unit
@ -54,85 +64,107 @@ function Unit:New(unit)
end
-- Check if the unit is valid
---@return boolean
function Unit:IsValid()
return self:GetOMToken() ~= nil and self:Exists()
end
-- Check if the unit exists
---@return boolean
function Unit:Exists()
return Object(self:GetOMToken())
end
-- Get the units token
---@return string
function Unit:Token()
return self:GetOMToken()
end
-- Get the units name
---@return string
function Unit:GetName()
return UnitName(self:GetOMToken())
end
-- Get the units GUID
---@return string
function Unit:GetGUID()
return ObjectGUID(self:GetOMToken())
end
-- Get the units health
---@return number
function Unit:GetHealth()
return UnitHealth(self:GetOMToken())
end
-- Get the units max health
---@return number
function Unit:GetMaxHealth()
return UnitHealthMax(self:GetOMToken())
end
-- Get the units health percentage
---@return number
function Unit:GetHP()
return self:GetHealth() / self:GetMaxHealth() * 100
end
-- Get the units health deficit
---@return number
function Unit:GetHealthPercent()
return self:GetHP()
end
-- Get the units power type
---@return number
function Unit:GetPowerType()
return UnitPowerType(self:GetOMToken())
end
-- Get the units power
---@param powerType number | nil
---@return number
function Unit:GetPower(powerType)
local powerType = powerType or self:GetPowerType()
return UnitPower(self:GetOMToken(), powerType)
end
-- Get the units max power
---@param powerType number | nil
---@return number
function Unit:GetMaxPower(powerType)
local powerType = powerType or self:GetPowerType()
return UnitPowerMax(self:GetOMToken(), powerType)
end
-- Get the units power percentage
---@param powerType number | nil
---@return number
function Unit:GetPP(powerType)
local powerType = powerType or self:GetPowerType()
return self:GetPower(powerType) / self:GetMaxPower(powerType) * 100
end
-- Get the units power deficit
---@param powerType number | nil
---@return number
function Unit:GetPowerDeficit(powerType)
local powerType = powerType or self:GetPowerType()
return self:GetMaxPower(powerType) - self:GetPower(powerType)
end
-- Get the units position
---@return Vector3
function Unit:GetPosition()
local x, y, z = ObjectPosition(self:GetOMToken())
return Bastion.Vector3:New(x, y, z)
end
-- Get the units distance from another unit
---@param unit Unit
---@return number
function Unit:GetDistance(unit)
local pself = self:GetPosition()
local punit = unit:GetPosition()
@ -141,36 +173,43 @@ function Unit:GetDistance(unit)
end
-- Is the unit dead
---@return boolean
function Unit:IsDead()
return UnitIsDeadOrGhost(self:GetOMToken())
end
-- Is the unit alive
---@return boolean
function Unit:IsAlive()
return not UnitIsDeadOrGhost(self:GetOMToken())
end
-- Is the unit a pet
---@return boolean
function Unit:IsPet()
return UnitIsUnit(self:GetOMToken(), "pet")
end
-- Is the unit a friendly unit
---@return boolean
function Unit:IsFriendly()
return UnitIsFriend("player", self:GetOMToken())
end
-- IsEnemy
---@return boolean
function Unit:IsEnemy()
return UnitCanAttack("player", self:GetOMToken())
end
-- Is the unit a hostile unit
---@return boolean
function Unit:IsHostile()
return UnitCanAttack(self:GetOMToken(), 'player')
end
-- Is the unit a boss
---@return boolean
function Unit:IsBoss()
if UnitClassification(self:GetOMToken()) == "worldboss" then
return true
@ -187,6 +226,7 @@ function Unit:IsBoss()
return false
end
---@return string
function Unit:GetOMToken()
if not self.unit then
return "none"
@ -195,51 +235,61 @@ function Unit:GetOMToken()
end
-- Is the unit a target
---@return boolean
function Unit:IsTarget()
return UnitIsUnit(self:GetOMToken(), "target")
end
-- Is the unit a focus
---@return boolean
function Unit:IsFocus()
return UnitIsUnit(self:GetOMToken(), "focus")
end
-- Is the unit a mouseover
---@return boolean
function Unit:IsMouseover()
return UnitIsUnit(self:GetOMToken(), "mouseover")
end
-- Is the unit a tank
---@return boolean
function Unit:IsTank()
return UnitGroupRolesAssigned(self:GetOMToken()) == "TANK"
end
-- Is the unit a healer
---@return boolean
function Unit:IsHealer()
return UnitGroupRolesAssigned(self:GetOMToken()) == "HEALER"
end
-- Is the unit a damage dealer
---@return boolean
function Unit:IsDamage()
return UnitGroupRolesAssigned(self:GetOMToken()) == "DAMAGER"
end
-- Is the unit a player
---@return boolean
function Unit:IsPlayer()
return UnitIsPlayer(self:GetOMToken())
end
-- Is the unit a player controlled unit
---@return boolean
function Unit:IsPCU()
return UnitPlayerControlled(self:GetOMToken())
end
-- Get if the unit is affecting combat
---@return boolean
function Unit:IsAffectingCombat()
return UnitAffectingCombat(self:GetOMToken())
end
-- Get the units class id
---@return Class
function Unit:GetClass()
local locale, class, classID = UnitClass(self:GetOMToken())
return Bastion.Class:New(locale, class, classID)
@ -252,6 +302,7 @@ function Unit:GetAuras()
end
-- Get the raw unit
---@return string
function Unit:GetRawUnit()
return self:GetOMToken()
end
@ -266,6 +317,8 @@ local isClassicWow = select(4, GetBuildInfo()) < 40000
local losFlag = bit.bor(0x1, 0x10, 0x100000)
-- Check if the unit can see another unit
---@param unit Unit
---@return boolean
function Unit:CanSee(unit)
-- mechagon smoke cloud
-- local mechagonID = 2097
@ -311,11 +364,13 @@ function Unit:CanSee(unit)
end
-- Check if the unit is casting a spell
---@return boolean
function Unit:IsCasting()
return UnitCastingInfo(self:GetOMToken()) ~= nil
end
-- Get Casting or channeling spell
---@return Spell | nil
function Unit:GetCastingOrChannelingSpell()
local name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, notInterruptible, spellId = UnitCastingInfo(self
.unit)
@ -333,20 +388,25 @@ function Unit:GetCastingOrChannelingSpell()
end
-- Check if the unit is channeling a spell
---@return boolean
function Unit:IsChanneling()
return UnitChannelInfo(self:GetOMToken()) ~= nil
end
-- Check if the unit is casting or channeling a spell
---@return boolean
function Unit:IsCastingOrChanneling()
return self:IsCasting() or self:IsChanneling()
end
-- Check if the unit can attack the target
---@param unit Unit
---@return boolean
function Unit:CanAttack(unit)
return UnitCanAttack(self:GetOMToken(), unit:GetOMToken())
end
---@return number
function Unit:GetChannelOrCastPercentComplete()
local name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, notInterruptible, spellId = UnitCastingInfo(self
.unit)
@ -366,6 +426,8 @@ function Unit:GetChannelOrCastPercentComplete()
return 0
end
-- Check if unit is interruptible
---@return boolean
function Unit:IsInterruptible()
local name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, notInterruptible, spellId = UnitCastingInfo(self
.unit)
@ -383,6 +445,8 @@ function Unit:IsInterruptible()
end
-- Check if unit is interruptible
---@param percent number
---@return boolean
function Unit:IsInterruptibleAt(percent)
if not self:IsInterruptible() then
return false
@ -399,6 +463,8 @@ function Unit:IsInterruptibleAt(percent)
end
-- Get the number of enemies in a given range of the unit and cache the result for .5 seconds
---@param range number
---@return number
function Unit:GetEnemies(range)
local enemies = self.cache:Get("enemies_" .. range)
if enemies then
@ -419,6 +485,7 @@ function Unit:GetEnemies(range)
end
-- Get the number of melee attackers
---@return number
function Unit:GetMeleeAttackers()
local enemies = self.cache:Get("melee_attackers")
if enemies then
@ -438,6 +505,9 @@ function Unit:GetMeleeAttackers()
return count
end
---@param distance number
---@param percent number
---@return number
function Unit:GetPartyHPAround(distance, percent)
local count = 0
@ -452,33 +522,57 @@ function Unit:GetPartyHPAround(distance, percent)
end
-- Is moving
---@return boolean
function Unit:IsMoving()
return GetUnitSpeed(self:GetOMToken()) > 0
end
-- Is moving at all
---@return boolean
function Unit:IsMovingAtAll()
return ObjectMovementFlag(self:GetOMToken()) ~= 0
end
function Unit:GetComboPoints()
---@param unit Unit | nil
---@return number
function Unit:GetComboPoints(unit)
if Tinkr.classic then
if not unit then
return 0
end
return GetComboPoints(self:GetOMToken(), unit:GetOMToken())
end
return UnitPower(self:GetOMToken(), 4)
end
---@return number
function Unit:GetComboPointsMax()
if Tinkr.classic then
return 5
end
return UnitPowerMax(self:GetOMToken(), 4)
end
-- Get combopoints deficit
function Unit:GetComboPointsDeficit()
---@param unit Unit | nil
---@return number
function Unit:GetComboPointsDeficit(unit)
if Tinkr.classic then
return self:GetComboPointsMax() - self:GetComboPoints(unit)
end
return self:GetComboPointsMax() - self:GetComboPoints()
end
-- IsUnit
---@param unit Unit
---@return boolean
function Unit:IsUnit(unit)
return UnitIsUnit(self:GetOMToken(), unit and unit:GetOMToken() or 'none')
end
-- IsTanking
---@param unit Unit
---@return boolean
function Unit:IsTanking(unit)
local isTanking, status, threatpct, rawthreatpct, threatvalue = UnitDetailedThreatSituation(self:GetOMToken(),
unit:GetOMToken())
@ -486,6 +580,8 @@ function Unit:IsTanking(unit)
end
-- IsFacing
---@param unit Unit
---@return boolean
function Unit:IsFacing(unit)
local rot = ObjectRotation(self:GetOMToken())
local x, y, z = ObjectPosition(self:GetOMToken())
@ -506,6 +602,8 @@ function Unit:IsFacing(unit)
end
-- IsBehind
---@param unit Unit
---@return boolean
function Unit:IsBehind(unit)
local rot = ObjectRotation(unit:GetOMToken())
local x, y, z = ObjectPosition(unit:GetOMToken())
@ -525,6 +623,7 @@ function Unit:IsBehind(unit)
return math.abs(angle) > 90
end
---@return number
function Unit:GetMeleeBoost()
if IsPlayerSpell(196924) then
return 3
@ -540,6 +639,8 @@ end
-- return ((myPos.x - targetPos.x) * (myPos.x - targetPos.x)) + ((myPos.y - targetPos.y) * (myPos.y - targetPos.y)) + ((myPos.z - targetPos.z) * (myPos.z - targetPos.z)) <= (float)(fMaxDist * fMaxDist);
-- InMelee
---@param unit Unit
---@return boolean
function Unit:InMelee(unit)
local x, y, z = ObjectPosition(self:GetOMToken())
local x2, y2, z2 = ObjectPosition(unit:GetOMToken())
@ -556,16 +657,21 @@ function Unit:InMelee(unit)
end
-- Get object id
---@return number
function Unit:GetID()
return ObjectID(self:GetOMToken())
end
-- In party
---@return boolean
function Unit:IsInParty()
return UnitInParty(self:GetOMToken())
end
-- Linear regression between time and percent to something
---@param time table
---@param percent table
---@return number, number
function Unit:LinearRegression(time, percent)
local x = time
local y = percent
@ -592,6 +698,8 @@ function Unit:LinearRegression(time, percent)
end
-- Use linear regression to get the health percent at a given time in the future
---@param time number
---@return number
function Unit:PredictHealth(time)
local x = {}
local y = {}
@ -613,6 +721,8 @@ function Unit:PredictHealth(time)
end
-- Use linear regression to guess the time until a given health percent
---@param percent number
---@return number
function Unit:PredictTime(percent)
local x = {}
local y = {}
@ -634,6 +744,7 @@ function Unit:PredictTime(percent)
end
-- Time until death
---@return number
function Unit:TimeToDie()
if self:IsDead() then
self.regression_history = {}
@ -650,16 +761,21 @@ function Unit:TimeToDie()
end
-- Set combat time if affecting combat and return the difference between now and the last time
---@return number
function Unit:GetCombatTime()
return GetTime() - self.last_combat_time
end
-- Set last combat time
---@param time number
---@return nil
function Unit:SetLastCombatTime(time)
self.last_combat_time = time
end
-- Get combat odds (if the last combat time is less than 1 minute ago return 1 / time, else return 0)
-- the closer to 0 the more likely the unit is to be in combat (0 = 100%) 60 = 0%
---@return number
function Unit:InCombatOdds()
local time = self:GetCombatTime()
local percent = 1 - (time / 60)
@ -668,6 +784,7 @@ function Unit:InCombatOdds()
end
-- Get units gcd time
---@return number
function Unit:GetGCD()
local start, duration = GetSpellCooldown(61304)
if start == 0 then
@ -686,6 +803,7 @@ The GCD won't drop below 1 second
More than 50% Haste will drop a spell below 1 second
]]
---@return number
function Unit:GetMaxGCD()
local haste = UnitSpellHaste(self:GetOMToken())
if haste > 50 then
@ -696,6 +814,7 @@ function Unit:GetMaxGCD()
end
-- IsStealthed
---@return boolean
function Unit:IsStealthed()
local Stealth = Bastion.SpellBook:GetSpell(1784)
local Vanish = Bastion.SpellBook:GetSpell(1856)
@ -709,6 +828,7 @@ function Unit:IsStealthed()
end
-- Get unit swing timers
---@return number, number
function Unit:GetSwingTimers()
local main_speed, off_speed = UnitAttackSpeed(self:GetOMToken())
local main_speed = main_speed or 2
@ -728,6 +848,7 @@ function Unit:GetSwingTimers()
return main_speed_remains, off_speed_remains
end
---@return nil
function Unit:WatchForSwings()
Bastion.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
local _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName, _, amount, interrupt, a, b, c, d, offhand, multistrike = CombatLogGetCurrentEventInfo()
@ -759,114 +880,34 @@ function Unit:WatchForSwings()
end)
end
-- GetTimeToShurikenTornado
--[[
spec:RegisterStateTable( "time_to_sht", setmetatable( {}, {
__index = function( t, k )
local n = tonumber( k )
n = n - ( n % 1 )
if not n or n > 5 then return 3600 end
if n <= swings_since_sht then return 0 end
local mh_speed = swings.mainhand_speed
local mh_next = ( swings.mainhand > now - 3 ) and ( swings.mainhand + mh_speed ) or now + ( mh_speed * 0.5 )
local oh_speed = swings.offhand_speed
local oh_next = ( swings.offhand > now - 3 ) and ( swings.offhand + oh_speed ) or now
table.wipe( sht )
if mh_speed and mh_speed > 0 then
for i = 1, 4 do
insert( sht, mh_next + ( i * mh_speed ) )
end
end
if oh_speed and oh_speed > 0 then
for i = 1, 4 do
insert( sht, oh_next + ( i * oh_speed ) )
end
end
local i = 1
while( sht[i] ) do
if sht[i] < last_shadow_techniques + 3 then
table.remove( sht, i )
else
i = i + 1
end
end
if #sht > 0 and n - swings_since_sht < #sht then
table.sort( sht )
return max( 0, sht[ n - swings_since_sht ] - query_time )
else
return 3600
end
end
} ) )
]]
function Unit:GetTimeToShurikenTornado(n)
local now = GetTime()
local sht = {}
local swings = self:GetSwingTimers()
if not self.swings_since_sht then
self.swings_since_sht = 0
end
if not self.last_shadow_techniques then
self.last_shadow_techniques = 0
end
if n <= self.swings_since_sht then
return 0
end
local mh_speed = swings[1]
local mh_next = (self.last_mh > now - 3) and (self.last_mh + mh_speed) or now + (mh_speed * 0.5)
local oh_speed = swings[2]
local oh_next = (self.last_oh > now - 3) and (self.last_oh + oh_speed) or now
table.wipe(sht)
if mh_speed and mh_speed > 0 then
for i = 1, 4 do
table.insert(sht, mh_next + (i * mh_speed))
end
end
if oh_speed and oh_speed > 0 then
for i = 1, 4 do
table.insert(sht, oh_next + (i * oh_speed))
end
end
-- ismounted
---@return boolean
function Unit:IsMounted()
return UnitIsMounted(self.unit)
end
local i = 1
-- isindoors
---@return boolean
function Unit:IsOutdoors()
return ObjectIsOutdoors(self.unit)
end
while (sht[i]) do
if sht[i] < self.last_shadow_techniques + 3 then
table.remove(sht, i)
else
i = i + 1
end
end
-- IsIndoors
---@return boolean
function Unit:IsIndoors()
return not ObjectIsOutdoors(self.unit)
end
if #sht > 0 and n - self.swings_since_sht < #sht then
table.sort(sht)
return math.max(0, sht[n - self.swings_since_sht] - now)
else
return 3600
end
-- IsSubmerged
---@return boolean
function Unit:IsSubmerged()
return ObjectIsSubmerged(self.unit)
end
-- Is the unit indoors
function Unit:IsIndoors()
return IsIndoors()
-- IsDry
---@return boolean
function Unit:IsDry()
return not ObjectIsSubmerged(self.unit)
end
return Unit
return Unit

@ -99,6 +99,7 @@ function UnitManager:__index(k)
end
-- Constructor
---@return UnitManager
function UnitManager:New()
local self = setmetatable({}, UnitManager)
self.units = {}
@ -112,6 +113,7 @@ function UnitManager:Validate(token)
end
-- Get or create a unit
---@param token string
---@return Unit
function UnitManager:Get(token)
-- if not Validate(token) then
@ -142,10 +144,16 @@ function UnitManager:Get(token)
end)
end
-- Get a unit by guid
---@param guid string
---@return Unit
function UnitManager:GetObject(guid)
return self.objects[guid]
end
-- Set a unit by guid
---@param unit Unit
---@return Unit
function UnitManager:SetObject(unit)
self.objects[unit:GetGUID()] = unit
end
@ -174,7 +182,9 @@ function UnitManager:CreateCustomUnit(token, cb)
return cachedUnit
end
-- Enum Friends (party/raid members)
---@description Enumerates all friendly units in the battlefield
---@param cb fun(unit: Unit):boolean
---@return nil
function UnitManager:EnumFriends(cb)
Bastion.ObjectManager.friends:each(function(unit)
if cb(unit) then
@ -185,6 +195,7 @@ end
-- Enum Enemies (object manager)
---@param cb fun(unit: Unit):boolean
---@return nil
function UnitManager:EnumEnemies(cb)
Bastion.ObjectManager.activeEnemies:each(function(unit)
if cb(unit) then
@ -194,6 +205,8 @@ function UnitManager:EnumEnemies(cb)
end
-- Enum Units (object manager)
---@param cb fun(unit: Unit):boolean
---@return nil
function UnitManager:EnumUnits(cb)
Bastion.ObjectManager.enemies:each(function(unit)
if cb(unit) then
@ -203,6 +216,8 @@ function UnitManager:EnumUnits(cb)
end
-- Get the number of friends with a buff (party/raid members)
---@param spell Spell
---@return number
function UnitManager:GetNumFriendsWithBuff(spell)
local count = 0
self:EnumFriends(function(unit)
@ -214,6 +229,7 @@ function UnitManager:GetNumFriendsWithBuff(spell)
end
-- Get the number of friends alive (party/raid members)
---@return number
function UnitManager:GetNumFriendsAlive()
local count = 0
self:EnumFriends(function(unit)
@ -225,7 +241,9 @@ function UnitManager:GetNumFriendsAlive()
end
-- Get the friend with the most friends within a given radius (party/raid members)
-- Return unit, friends
---@param radius number
---@return Unit
---@return table
function UnitManager:GetFriendWithMostFriends(radius)
local unit = nil
local count = 0
@ -254,6 +272,9 @@ function UnitManager:GetFriendWithMostFriends(radius)
end
-- Find the centroid of the most dense area of friends (party/raid members) of a given radius within a given range
---@param radius number
---@param range number
---@return Vector3 | nil
function UnitManager:FindFriendsCentroid(radius, range)
local unit, friends = self:GetFriendWithMostFriends(radius)
if unit == nil then

@ -1,16 +1,22 @@
-- Create a Vector3 class
---@class Vector3
local Vector3 = {}
Vector3.__index = Vector3
---@return string
function Vector3:__tostring()
return "Vector3(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
end
---@param other Vector3
---@return Vector3
function Vector3:__add(other)
return Vector3:New(self.x + other.x, self.y + other.y, self.z + other.z)
end
---@param other Vector3
---@return Vector3
function Vector3:__sub(other)
if type(other) == "number" then
return Vector3:New(self.x - other, self.y - other, self.z - other)
@ -18,30 +24,42 @@ function Vector3:__sub(other)
return Vector3:New(self.x - other.x, self.y - other.y, self.z - other.z)
end
---@param other number
---@return Vector3
function Vector3:__mul(other)
return Vector3:New(self.x * other, self.y * other, self.z * other)
end
---@param other number
---@return Vector3
function Vector3:__div(other)
return Vector3:New(self.x / other, self.y / other, self.z / other)
end
---@param other Vector3
---@return boolean
function Vector3:__eq(other)
return self.x == other.x and self.y == other.y and self.z == other.z
end
---@param other Vector3
---@return boolean
function Vector3:__lt(other)
return self.x < other.x and self.y < other.y and self.z < other.z
end
---@param other Vector3
---@return boolean
function Vector3:__le(other)
return self.x <= other.x and self.y <= other.y and self.z <= other.z
end
---@return Vector3
function Vector3:__unm()
return Vector3:New(-self.x, -self.y, -self.z)
end
---@return number
function Vector3:__len()
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
end
@ -151,6 +169,10 @@ function Vector3:__newindex(k, v)
end
end
---@param x number
---@param y number
---@param z number
---@return Vector3
function Vector3:New(x, y, z)
if x == false then
return Vector3:New(0, 0, 0)
@ -160,18 +182,26 @@ function Vector3:New(x, y, z)
return self
end
---@param rhs Vector3
---@return number
function Vector3:Dot(rhs)
return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
end
---@param rhs Vector3
---@return Vector3
function Vector3:Cross(rhs)
return Vector3:New(self.y * rhs.z - self.z * rhs.y, self.z * rhs.x - self.x * rhs.z, self.x * rhs.y - self.y * rhs.x)
end
---@param b Vector3
---@return number
function Vector3:Distance(b)
return FastDistance(self.x, self.y, self.z, b.x, b.y, b.z)
end
---@param to Vector3
---@return number
function Vector3:Angle(to)
return math.acos(self:Dot(to) /
(
@ -179,6 +209,8 @@ function Vector3:Angle(to)
math.sqrt(to.x * to.x + to.y * to.y + to.z * to.z)))
end
---@param maxLength number
---@return Vector3
function Vector3:ClampMagnitude(maxLength)
if self:Dot(self) > maxLength * maxLength then
return self.normalized * maxLength
@ -188,15 +220,25 @@ function Vector3:ClampMagnitude(maxLength)
end
-- Implement a clamp function
---@param x number
---@param min number
---@param max number
---@return number
local function clamp(x, min, max)
return x < min and min or (x > max and max or x)
end
---@param b Vector3
---@param t number
---@return Vector3
function Vector3:Lerp(b, t)
t = clamp(t, 0, 1)
return Vector3:New(self.x + (b.x - self.x) * t, self.y + (b.y - self.y) * t, self.z + (b.z - self.z) * t)
end
---@param target Vector3
---@param maxDistanceDelta number
---@return Vector3
function Vector3:MoveTowards(target, maxDistanceDelta)
local toVector = target - self
local distance = toVector.magnitude
@ -207,10 +249,14 @@ function Vector3:MoveTowards(target, maxDistanceDelta)
return self + toVector / distance * maxDistanceDelta
end
---@param b Vector3
---@return Vector3
function Vector3:Scale(b)
return Vector3:New(self.x * b.x, self.y * b.y, self.z * b.z)
end
---@param onNormal Vector3
---@return Vector3
function Vector3:Project(onNormal)
local num = onNormal:Dot(onNormal)
if num < 1.401298E-45 then
@ -220,14 +266,19 @@ function Vector3:Project(onNormal)
return onNormal * self:Dot(onNormal) / num
end
---@param planeNormal Vector3
---@return Vector3
function Vector3:ProjectOnPlane(planeNormal)
return self - self:Project(planeNormal)
end
---@param inDirection Vector3
---@return Vector3
function Vector3:Reflect(inNormal)
return -2 * inNormal:Dot(self) * inNormal + self
end
---@return Vector3
function Vector3:Normalize()
local num = self:Dot(self)
if num > 1E-05 then

@ -1,5 +1,6 @@
local Tinkr = ...
---@class Bastion
local Bastion = {
DebugMode = false
}
@ -9,32 +10,56 @@ function Bastion.require(class)
return Tinkr:require("scripts/bastion/src/" .. class .. "/" .. class, Bastion)
end
---@type ClassMagic
Bastion.ClassMagic = Bastion.require("ClassMagic")
---@type List
Bastion.List = Bastion.require("List")
---@type NotificationsList, Notification
Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList")
---@type Vector3
Bastion.Vector3 = Bastion.require("Vector3")
---@type Command
Bastion.Command = Bastion.require("Command")
---@type Cache
Bastion.Cache = Bastion.require("Cache")
---@type Cacheable
Bastion.Cacheable = Bastion.require("Cacheable")
---@type Refreshable
Bastion.Refreshable = Bastion.require("Refreshable")
---@type Unit
Bastion.Unit = Bastion.require("Unit")
---@type Aura
Bastion.Aura = Bastion.require("Aura")
---@type APL, APLActor, APLTrait
Bastion.APL, Bastion.APLActor, Bastion.APLTrait = Bastion.require("APL")
Bastion.Module = Bastion.require("Module")
---@type UnitManager
Bastion.UnitManager = Bastion.require("UnitManager"):New()
---@type ObjectManager
Bastion.ObjectManager = Bastion.require("ObjectManager"):New()
---@type EventManager
Bastion.EventManager = Bastion.require("EventManager"):New()
---@type Spell
Bastion.Spell = Bastion.require("Spell")
---@type SpellBook
Bastion.SpellBook = Bastion.require("SpellBook"):New()
---@type Item
Bastion.Item = Bastion.require("Item")
---@type ItemBook
Bastion.ItemBook = Bastion.require("ItemBook"):New()
---@type AuraTable
Bastion.AuraTable = Bastion.require("AuraTable")
---@type Class
Bastion.Class = Bastion.require("Class")
---@type Timer
Bastion.Timer = Bastion.require("Timer")
Bastion.Gui = Bastion.require("Gui")
---@type Timer
Bastion.CombatTimer = Bastion.Timer:New('combat')
---@type MythicPlusUtils
Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New()
---@type NotificationsList
Bastion.Notifications = Bastion.NotificationsList:New()
Bastion.Gui = Bastion.require("Gui")
Bastion.modules = {}
Bastion.Enabled = false
@ -211,27 +236,21 @@ Command:Register('interface', 'Opens interface menu', function()
else
mainmenu:Show()
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
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') == 'Priest' and GetSpecialization() == 2 then
Tinkr:require("scripts/bastion/scripts/holypriest", Bastion)
Eval('RunMacroText("/bastion module holypriest")', 'bastion')
Eval('RunMacroText("/bastion module holypriest")', 'bastion')
elseif UnitClass('player') == 'Druid' and GetSpecialization() == 2 then
Tinkr:require("scripts/bastion/scripts/feraldruid", Bastion)
Eval('RunMacroText("/bastion module feral")', 'bastion')
elseif UnitClass('player') == 'Druid' and GetSpecialization() == 3 then
Tinkr:require("scripts/bastion/scripts/guardiandruid", Bastion)
Eval('RunMacroText("/bastion module guardian")', 'bastion')
elseif UnitClass('player') == 'Druid' and GetSpecialization() == 4 then
Tinkr:require("scripts/bastion/scripts/restodruid", Bastion)
Eval('RunMacroText("/bastion module resto_druid")', 'bastion')
Eval('RunMacroText("/bastion module resto")', 'bastion')
end
Loading…
Cancel
Save