Compare commits

..

No commits in common. 'f722d173060a3c14699656c453bbba89c766d06c' and '630fcfc3d9ad9c1728789cf08698c6a1547de3ae' have entirely different histories.

  1. 2
      .gitignore
  2. 4
      README.md
  3. 11
      scripts/ExampleModule.lua
  4. 21
      scripts/Libraries/ExampleDependency.lua
  5. 15
      scripts/Libraries/ExampleDependencyError.lua
  6. 25
      scripts/Libraries/ExampleLibrary.lua
  7. 42
      src/APL/APL.lua
  8. 20
      src/Aura/Aura.lua
  9. 345
      src/AuraTable/AuraTable.lua
  10. 8
      src/Item/Item.lua
  11. 115
      src/Library/Library.lua
  12. 6
      src/List/List.lua
  13. 6
      src/MythicPlusUtils/MythicPlusUtils.lua
  14. 3
      src/Sequencer/Sequencer.lua
  15. 14
      src/Spell/Spell.lua
  16. 13
      src/SpellBook/SpellBook.lua
  17. 20
      src/Unit/Unit.lua
  18. 46
      src/UnitManager/UnitManager.lua
  19. 158
      src/_bastion.lua

2
.gitignore vendored

@ -12,8 +12,6 @@ scripts/Libraries/*
!scripts/.gitkeep
!scripts/ExampleModule.lua
!scripts/Libraries/ExampleLibrary.lua
!scripts/Libraries/ExampleDependency.lua
!scripts/Libraries/ExampleDependencyError.lua
## ignore vscode settings
.vscode/*

@ -11,7 +11,3 @@ Feel free to browse around the [Wiki](https://git.tinkr.site/4n0n/bastion/wiki)
- [Download](https://git.tinkr.site/4n0n/bastion/archive/main.zip) or clone the repository.
- Move the bastion folder to your `Tinkr/scripts` folder.
- Once in-game type `/bastion toggle` to enable the engine.
## Developer Information
- [Issue Template](https://git.tinkr.site/Bastion/Bastion/wiki/Issues)
- [Pull Requests](https://git.tinkr.site/Bastion/Bastion/wiki/Pull-Requests)

@ -2,16 +2,9 @@ local Tinkr, Bastion = ...
local ExampleModule = Bastion.Module:New('ExampleModule')
local Player = Bastion.UnitManager:Get('player')
-- Create a local spellbook
local SpellBook = Bastion.SpellBook:New()
local FlashHeal = Bastion.SpellBook:GetSpell(2061)
local FlashHeal = SpellBook:GetSpell(2061)
-- Get a global spell (this can collide with other modules, so be careful)
-- This is useful for caching common spells that you might not actually cast, and to avoid needless spell creation inline
local FlashHeal = Bastion.Globals.SpellBook:GetSpell(2061)
local AdvancedMath = Bastion:Import('AdvancedMath')
local AdvancedMath = Bastion:GetLibrary('AdvancedMath')
print(AdvancedMath:Add(1, 2))

@ -1,21 +0,0 @@
local Tinkr, Bastion = ...
local Player = Bastion.UnitManager:Get('player')
Bastion:RegisterLibrary(Bastion.Library:New({
name = 'Dependable',
exports = {
default = function()
local Dependable = {}
Dependable.__index = Dependable
function Dependable:Test(a)
print(a)
end
return Dependable
end,
Test = 5
}
}))

@ -1,15 +0,0 @@
local Tinkr, Bastion = ...
Bastion:RegisterLibrary(Bastion.Library:New({
name = 'Circular',
exports = {
default = function(self)
-- Return default first, and then the remaining exports
local Math, OtherExports = self:Import('AdvancedMath')
print(Math:Add(1, 2))
return 'Circular'
end
}
}))

@ -1,25 +1,14 @@
local Tinkr, Bastion = ...
Bastion:RegisterLibrary(Bastion.Library:New({
name = 'AdvancedMath',
exports = {
default = function(self) -- Function exports are called when the library is loaded
-- Return default first, and then the remaining exports
local Dependable, OtherExports = self:Import('Dependable')
local ExampleModule = Bastion.Module:New('ExampleModule')
local Player = Bastion.UnitManager:Get('player')
local CircularDependency = self:Import('Circular') -- Causes a circular dependency error
local AdvancedMath = {}
Dependable:Test(OtherExports.Test)
AdvancedMath.__index = AdvancedMath
local AdvancedMath = {}
AdvancedMath.__index = AdvancedMath
function AdvancedMath:Add(a, b)
function AdvancedMath:Add(a, b)
return a + b
end
end
return AdvancedMath
end
}
}))
Bastion:RegisterLibrary('AdvancedMath', AdvancedMath)

@ -1,4 +1,5 @@
-- Document with emmy lua: https://emmylua.github.io/
-- Create an APL trait for the APL class
---@class APLTrait
local APLTrait = {}
@ -54,7 +55,7 @@ end
---@param ... APLTrait
---@return APLActor
function APLActor:AddTraits(...)
for _, trait in ipairs({...}) do
for _, trait in ipairs({ ... }) do
table.insert(self.traits, trait)
end
@ -84,11 +85,13 @@ function APLActor:Execute()
-- If the actor is a sequencer we don't want to continue executing the APL if the sequencer is not finished
if self:GetActor().sequencer then
if self:GetActor().condition and self:GetActor().condition() and not self:GetActor().sequencer:Finished() then
print("Execute?")
self:GetActor().sequencer:Execute()
return true
end
if not self:GetActor().condition and not self:GetActor().sequencer:Finished() then
print("Execute?")
self:GetActor().sequencer:Execute()
return true
end
@ -108,12 +111,13 @@ function APLActor:Execute()
if self:GetActor().condition then
-- print("Bastion: APL:Execute: Condition for spell " .. self:GetActor().spell:GetName())
self:GetActor().spell:CastableIf(self:GetActor().castableFunc):OnCast(self:GetActor().onCastFunc):Cast(
self:GetActor().target, self:GetActor().condition)
self:GetActor().target,
self:GetActor().condition)
end
-- print("Bastion: APL:Execute: No condition for spell " .. self:GetActor().spell:GetName())
self:GetActor().spell:CastableIf(self:GetActor().castableFunc):OnCast(self:GetActor().onCastFunc):Cast(
self:GetActor().target)
self:GetActor().spell:CastableIf(self:GetActor().castableFunc):OnCast(self:GetActor().onCastFunc):Cast(self
:GetActor().target)
end
if self:GetActor().item then
if self:GetActor().condition then
@ -185,11 +189,7 @@ end
---@param cb fun(...):any
---@return APLActor
function APL:AddVariable(name, cb)
local actor = APLActor:New({
variable = name,
cb = cb,
_apl = self
})
local actor = APLActor:New({ variable = name, cb = cb, _apl = self })
table.insert(self.apl, actor)
return actor
end
@ -199,10 +199,7 @@ end
---@param cb fun(...):any
---@return APLActor
function APL:AddAction(action, cb)
local actor = APLActor:New({
action = action,
cb = cb
})
local actor = APLActor:New({ action = action, cb = cb })
table.insert(self.apl, actor)
return actor
end
@ -237,12 +234,7 @@ function APL:AddItem(item, condition)
local usableFunc = item.UsableIfFunc
local target = item:GetTarget()
local actor = APLActor:New({
item = item,
condition = condition,
usableFunc = usableFunc,
target = target
})
local actor = APLActor:New({ item = item, condition = condition, usableFunc = usableFunc, target = target })
table.insert(self.apl, actor)
@ -257,10 +249,7 @@ function APL:AddAPL(apl, condition)
if not condition then
error("Bastion: APL:AddAPL: No condition for APL " .. apl.name)
end
local actor = APLActor:New({
apl = apl,
condition = condition
})
local actor = APLActor:New({ apl = apl, condition = condition })
table.insert(self.apl, actor)
return actor
end
@ -270,10 +259,12 @@ function APL:Execute()
for _, actor in ipairs(self.apl) do
if actor:HasTraits() and actor:Evaluate() then
if actor:Execute() then
print("BREAQK", actor)
break
end
else
if actor:Execute() then
print("BREAQK", actor)
break
end
end
@ -285,10 +276,7 @@ end
---@param condition fun(...):boolean
---@return APLActor
function APL:AddSequence(sequencer, condition)
local actor = APLActor:New({
sequencer = sequencer,
condition = condition
})
local actor = APLActor:New({ sequencer = sequencer, condition = condition })
table.insert(self.apl, actor)
return actor
end

@ -1,4 +1,5 @@
-- Document with emmy lua: https://emmylua.github.io/
local Tinkr, Bastion = ...
-- Create a new Aura class
@ -65,18 +66,19 @@ function Aura:New(unit, index, type)
timeMod = 0,
index = nil,
type = nil
type = nil,
}
if self.aura.spellId then
Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
Bastion.SpellBook:GetSpell(self.aura.spellId)
end
return self
end
local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId,
canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index, type)
local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal,
spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index,
type)
local self = setmetatable({}, Aura)
self.aura = {
@ -98,10 +100,10 @@ function Aura:New(unit, index, type)
auraInstanceID = nil,
index = index,
type = type
type = type,
}
if self.aura.spellId then
Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
Bastion.SpellBook:GetSpell(self.aura.spellId)
end
return self
end
@ -130,11 +132,11 @@ function Aura:CreateFromUnitAuraInfo(unitAuraInfo)
auraInstanceID = unitAuraInfo.auraInstanceID,
index = nil,
type = unitAuraInfo.isHarmful and "HARMFUL" or "HELPFUL"
type = unitAuraInfo.isHarmful and "HARMFUL" or "HELPFUL",
}
-- Register spell in spellbook
Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
Bastion.SpellBook:GetSpell(self.aura.spellId)
return self
end
@ -237,7 +239,7 @@ end
-- Get the auras spell id
---@return Spell
function Aura:GetSpell()
return Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
return Bastion.SpellBook:GetSpell(self.aura.spellId)
end
-- Get the auras can apply aura status

@ -384,351 +384,6 @@ function AuraTable:FindAny(spell)
return self:FindMy(spell)
end
-- FindAnyOf
---@param spells List
---@return Aura
function AuraTable:FindAnyOf(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindAny(cur)
if aura:IsValid() then
return aura, true
end
return acc
end, Bastion.Aura:New())
end
-- FindAnyOfMy
---@param spells List
---@return Aura
function AuraTable:FindAnyOfMy(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindMy(cur)
if aura:IsValid() then
return aura, true
end
return acc
end, Bastion.Aura:New())
end
-- FindAnyOfTheirs
---@param spells List
---@return Aura
function AuraTable:FindAnyOfTheirs(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindTheirs(cur)
if aura:IsValid() then
return aura, true
end
return acc
end, Bastion.Aura:New())
end
-- FindAnyFrom
---@param spells List
---@param source Unit
---@return Aura
function AuraTable:FindAnyFrom(spells, source)
return spells:reduce(function(acc, cur)
local aura = self:FindFrom(cur, source)
if aura:IsValid() then
return aura, true
end
return acc
end, Bastion.Aura:New())
end
-- FindLongestOf
---@param spells List
---@return Aura
function AuraTable:FindLongestOf(spells)
return spells:reduce(function(acc, cur)
local aura = self:Find(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() > acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLongestOfMy
---@param spells List
---@return Aura
function AuraTable:FindLongestOfMy(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindMy(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() > acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLongestOfTheirs
---@param spells List
---@return Aura
function AuraTable:FindLongestOfTheirs(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindTheirs(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() > acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLongestOfFrom
---@param spells List
---@param source Unit
---@return Aura
function AuraTable:FindLongestOfFrom(spells, source)
return spells:reduce(function(acc, cur)
local aura = self:FindFrom(cur, source)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() > acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindShortestOf
---@param spells List
---@return Aura
function AuraTable:FindShortestOf(spells)
return spells:reduce(function(acc, cur)
local aura = self:Find(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() < acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindShortestOfMy
---@param spells List
---@return Aura
function AuraTable:FindShortestOfMy(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindMy(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() < acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindShortestOfTheirs
---@param spells List
---@return Aura
function AuraTable:FindShortestOfTheirs(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindTheirs(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() < acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindShortestOfFrom
---@param spells List
---@param source Unit
---@return Aura
function AuraTable:FindShortestOfFrom(spells, source)
return spells:reduce(function(acc, cur)
local aura = self:FindFrom(cur, source)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetRemainingTime() < acc:GetRemainingTime() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindMostOf
---@param spells List
---@return Aura
function AuraTable:FindMostOf(spells)
return spells:reduce(function(acc, cur)
local aura = self:Find(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() > acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindMostOfMy
---@param spells List
---@return Aura
function AuraTable:FindMostOfMy(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindMy(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() > acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindMostOfTheirs
---@param spells List
---@return Aura
function AuraTable:FindMostOfTheirs(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindTheirs(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() > acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindMostOfFrom
---@param spells List
---@param source Unit
---@return Aura
function AuraTable:FindMostOfFrom(spells, source)
return spells:reduce(function(acc, cur)
local aura = self:FindFrom(cur, source)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() > acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLeastOf
---@param spells List
---@return Aura
function AuraTable:FindLeastOf(spells)
return spells:reduce(function(acc, cur)
local aura = self:Find(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() < acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLeastOfMy
---@param spells List
---@return Aura
function AuraTable:FindLeastOfMy(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindMy(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() < acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLeastOfTheirs
---@param spells List
---@return Aura
function AuraTable:FindLeastOfTheirs(spells)
return spells:reduce(function(acc, cur)
local aura = self:FindTheirs(cur)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() < acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- FindLeastOfFrom
---@param spells List
---@param source Unit
---@return Aura
function AuraTable:FindLeastOfFrom(spells, source)
return spells:reduce(function(acc, cur)
local aura = self:FindFrom(cur, source)
if aura:IsValid() then
if not acc:IsValid() then
return aura
end
if aura:GetCount() < acc:GetCount() then
return aura
end
end
return acc
end, Bastion.Aura:New())
end
-- Has any stealable aura
---@return boolean
function AuraTable:HasAnyStealableAura()

@ -54,7 +54,7 @@ function Item:New(id)
local name, spellID = GetItemSpell(self:GetID())
if spellID then
self.spellID = spellID
Bastion.Globals.SpellBook:GetSpell(spellID)
Bastion.SpellBook:GetSpell(spellID)
end
return self
@ -239,7 +239,7 @@ function Item:Click(x, y, z)
if type(x) == 'table' then
x, y, z = x.x, x.y, x.z
end
if IsSpellPending() == 64 then
if IsItemPending() == 64 then
MouselookStop()
Click(x, y, z)
if self:GetWasLooking() then
@ -302,7 +302,7 @@ end
-- Get the last use time
---@return number
function Item:GetLastUseTime()
return Bastion.Globals.SpellBook:GetSpell(self:GetID()):GetLastCastTime()
return Bastion.SpellBook:GetSpell(self:GetID()):GetLastCastTime()
end
-- Get time since last use
@ -430,7 +430,7 @@ end
---@return Spell | nil
function Item:GetSpell()
if self.spellID then
return Bastion.Globals.SpellBook:GetSpell(self.spellID)
return Bastion.SpellBook:GetSpell(self.spellID)
end
return nil

@ -1,115 +0,0 @@
local Tinkr, Bastion = ...
---@class Library
---@field name string
---@field dependencies table
---@field exports table
---@field resolved table
local Library = {
name = nil,
dependencies = {},
exports = {
default = function()
return nil
end
},
resolved = nil
}
Library.__index = Library
---@param name string
---@param library table
---@return Library
function Library:New(library)
local self = {
name = library.name or nil,
dependencies = {},
exports = library.exports or {
default = function()
return nil
end
},
resolved = nil
}
self = setmetatable(self, Library)
return self
end
function Library:ResolveExport(export)
if type(export) == 'function' then
return export(self)
end
return export
end
function Library:Resolve()
if not self.exports then
error("Library " .. self.name .. " has no exports")
end
if self.resolved then
if self.exports.default then
return self.resolved[1], self.resolved[2]
end
return unpack(self.resolved)
end
if self.exports.default then
-- return default first if it exists
local default = self.exports.default
local remaining = {}
for k, v in pairs(self.exports) do
if k ~= 'default' then
remaining[k] = self:ResolveExport(v)
end
end
self.resolved = {self:ResolveExport(default), remaining}
return self.resolved[1], self.resolved[2]
end
self.resolved = {}
for k, v in pairs(self.exports) do
self.resolved[k] = self:ResolveExport(v)
end
return unpack(self.resolved)
end
function Library:DependsOn(other)
for _, dependency in pairs(self.dependencies) do
if dependency == other then
return true
end
end
return false
end
---@param library string
function Library:Import(library)
local lib = Bastion:GetLibrary(library)
if not lib then
error("Library " .. library .. " does not exist")
end
if not table.contains(self.dependencies, library) then
table.insert(self.dependencies, library)
end
if lib:DependsOn(self.name) then
error("Circular dependency detected between " .. self.name .. " and " .. library)
end
return lib:Resolve()
end
return Library

@ -114,12 +114,8 @@ end
---@return boolean
function List:reduce(callback, initialValue)
local result = initialValue
local done = false
for _, v in ipairs(self._list) do
result, done = callback(result, v)
if done then
break
end
result = callback(result, v)
end
return result
end

@ -430,7 +430,7 @@ function MythicPlusUtils:New()
}
}
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
if not self.debuffLogging then
return
end
@ -453,7 +453,7 @@ function MythicPlusUtils:New()
end
end)
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_SPELLCAST_START', function(unitTarget, castGUID, spellID)
Bastion.EventManager:RegisterWoWEvent('UNIT_SPELLCAST_START', function(unitTarget, castGUID, spellID)
if not self.castLogging then
return
end
@ -472,7 +472,7 @@ function MythicPlusUtils:New()
]], true)
end)
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_SPELLCAST_CHANNEL_START', function(unitTarget, castGUID, spellID)
Bastion.EventManager:RegisterWoWEvent('UNIT_SPELLCAST_CHANNEL_START', function(unitTarget, castGUID, spellID)
if not self.castLogging then
return
end

@ -1,4 +1,5 @@
-- Create a sequencer class that takes a table of actions and executes them in order
---@class Sequencer
---@field resetCondition fun(): boolean
---@field abortCondition fun(): boolean
@ -44,10 +45,12 @@ end
---@return boolean
function Sequencer:Next()
if self:Finished() then
print("Its finished?")
return false
end
local action = self.actions[self.index]
print("Attempting action: " .. self.index .. "")
if action(self) then
self.index = self.index + 1
return true

@ -12,11 +12,11 @@ local Spell = {
lastCastAt = false,
conditions = {},
target = false,
release_at = false
release_at = false,
}
local usableExcludes = {
[18562] = true
[18562] = true,
}
function Spell:__index(k)
@ -57,12 +57,6 @@ function Spell:New(id)
return self
end
-- Duplicator
---@return Spell
function Spell:Fresh()
return Spell:New(self:GetID())
end
-- Get the spells id
---@return number
function Spell:GetID()
@ -529,7 +523,9 @@ end
-- IsDiseaseDispel
---@return boolean
function Spell:IsDiseaseDispel()
return ({})[self:GetID()]
return ({
})[self:GetID()]
end
-- IsSpell

@ -27,24 +27,13 @@ end
---@return Spell, ... Spell
function SpellBook:GetSpells(...)
local spells = {}
for _, id in ipairs({...}) do
for _, id in ipairs({ ... }) do
table.insert(spells, self:GetSpell(id))
end
return unpack(spells)
end
---@param ... number[]
---@return List
function SpellBook:GetList(...)
local spells = {}
for _, id in ipairs({...}) do
table.insert(spells, self:GetSpell(id))
end
return Bastion.List:New(spells)
end
---@param name string
---@return Spell
function SpellBook:GetSpellByName(name)

@ -13,7 +13,7 @@ local Unit = {
last_off_attack = 0,
last_main_attack = 0,
last_combat_time = 0,
ttd_ticker = false,
ttd_ticker = 0,
ttd = 0,
id = false,
}
@ -422,7 +422,7 @@ function Unit:GetCastingOrChannelingSpell()
end
if name then
return Bastion.Globals.SpellBook:GetSpell(spellId)
return Bastion.SpellBook:GetSpell(spellId)
end
return nil
@ -838,7 +838,7 @@ function Unit:TimeToDie()
self.regression_history = {}
if self.ttd_ticker then
self.ttd_ticker:Cancel()
self.ttd_ticker = false
self.ttd_ticker = nil
end
return 0
end
@ -926,12 +926,12 @@ end
-- IsStealthed
---@return boolean
function Unit:IsStealthed()
local Stealth = Bastion.Globals.SpellBook:GetSpell(1784)
local Vanish = Bastion.Globals.SpellBook:GetSpell(1856)
local ShadowDance = Bastion.Globals.SpellBook:GetSpell(185422)
local Subterfuge = Bastion.Globals.SpellBook:GetSpell(115192)
local Shadowmeld = Bastion.Globals.SpellBook:GetSpell(58984)
local Sepsis = Bastion.Globals.SpellBook:GetSpell(328305)
local Stealth = Bastion.SpellBook:GetSpell(1784)
local Vanish = Bastion.SpellBook:GetSpell(1856)
local ShadowDance = Bastion.SpellBook:GetSpell(185422)
local Subterfuge = Bastion.SpellBook:GetSpell(115192)
local Shadowmeld = Bastion.SpellBook:GetSpell(58984)
local Sepsis = Bastion.SpellBook:GetSpell(328305)
return self:GetAuras():FindAny(Stealth) or self:GetAuras():FindAny(ShadowDance)
end
@ -959,7 +959,7 @@ end
---@return nil
function Unit:WatchForSwings()
Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
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()

@ -4,6 +4,49 @@ local ObjectManager = Tinkr.Util.ObjectManager
local Unit = Bastion.Unit
local prefixes = {
'^player',
'^pet',
'^vehicle',
'^target',
'^focus',
'^mouseover',
'^none',
'^npc',
'^party[1-4]',
'^raid[1-4]?[0-9]',
'^boss[1-5]',
'^arena[1-5]'
}
-- Validate a unit is a valid token
local function Validate(token)
local start, index
local length, offset = string.len(token), 0
for i = 1, #prefixes do
start, index = string.find(token, prefixes[i])
if start then
offset = index + 1
if offset > length then
return true
else
while true do
start, index = string.find(token, 'target', offset, true)
if start then
offset = index + 1
if offset > length then
return true
end
else
return false
end
end
end
end
end
return false
end
-- Create a new UnitManager class
---@class UnitManager
local UnitManager = {
@ -65,6 +108,9 @@ function UnitManager:New()
return self
end
function UnitManager:Validate(token)
return Validate(token)
end
-- Get or create a unit
---@param token string

@ -6,58 +6,14 @@ local Bastion = {
}
Bastion.__index = Bastion
function Bastion:Require(file)
-- If require starts with an @ then we require from the scripts/bastion/scripts folder
if file:sub(1, 1) == '@' then
file = file:sub(2)
-- print('1')
return require('scripts/bastion/scripts/' .. file, Bastion)
elseif file:sub(1, 1) == "~" then
file = file:sub(2)
-- print("2")
return require('scripts/bastion/' .. file, Bastion)
else
-- print("Normal req")
return require(file, Bastion)
end
end
local function Load(dir)
local dir = dir
if dir:sub(1, 1) == '@' then
dir = dir:sub(2)
dir = 'scripts/bastion/scripts/' .. dir
end
if dir:sub(1, 1) == '~' then
dir = dir:sub(2)
dir = 'scripts/bastion/' .. dir
end
local files = ListFiles(dir)
for i = 1, #files do
local file = files[i]
if file:sub(-4) == ".lua" or file:sub(-5) == '.luac' then
return Bastion:Require(dir .. file:sub(1, -5))
end
end
end
function Bastion.require(class)
-- return require("scripts/bastion/src/" .. class .. "/" .. class, Bastion)
return Bastion:Require("~/src/" .. class .. "/" .. class)
return require("scripts/bastion/src/" .. class .. "/" .. class, Bastion)
end
Bastion.Globals = {}
---@type ClassMagic
Bastion.ClassMagic = Bastion.require("ClassMagic")
---@type List
Bastion.List = Bastion.require("List")
---@type Library
Bastion.Library = Bastion.require("Library")
---@type NotificationsList, Notification
Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList")
---@type Vector3
@ -85,18 +41,15 @@ Bastion.UnitManager = Bastion.require("UnitManager"):New()
---@type ObjectManager
Bastion.ObjectManager = Bastion.require("ObjectManager"):New()
---@type EventManager
Bastion.EventManager = Bastion.require("EventManager")
Bastion.Globals.EventManager = Bastion.EventManager:New()
Bastion.EventManager = Bastion.require("EventManager"):New()
---@type Spell
Bastion.Spell = Bastion.require("Spell")
---@type SpellBook
Bastion.SpellBook = Bastion.require("SpellBook")
Bastion.Globals.SpellBook = Bastion.SpellBook:New()
Bastion.SpellBook = Bastion.require("SpellBook"):New()
---@type Item
Bastion.Item = Bastion.require("Item")
---@type ItemBook
Bastion.ItemBook = Bastion.require("ItemBook")
Bastion.Globals.ItemBook = Bastion.ItemBook:New()
Bastion.ItemBook = Bastion.require("ItemBook"):New()
---@type AuraTable
Bastion.AuraTable = Bastion.require("AuraTable")
---@type Class
@ -109,13 +62,11 @@ Bastion.CombatTimer = Bastion.Timer:New('combat')
Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New()
---@type NotificationsList
Bastion.Notifications = Bastion.NotificationsList:New()
local LIBRARIES = {}
local MODULES = {}
Bastion.Enabled = false
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
local u = Bastion.UnitManager[unit]
if u then
@ -123,10 +74,10 @@ Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
end
end)
Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
local unit, castGUID, spellID = ...
local spell = Bastion.Globals.SpellBook:GetIfRegistered(spellID)
local spell = Bastion.SpellBook:GetIfRegistered(spellID)
if unit == "player" and spell then
spell.lastCastAt = GetTime()
@ -139,8 +90,7 @@ end)
local pguid = UnitGUID("player")
local missed = {}
Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
Bastion.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
local args = {CombatLogGetCurrentEventInfo()}
local subEvent = args[2]
@ -184,6 +134,15 @@ Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", fun
end
end)
function Bastion:RegisterLibrary(name, payload)
LIBRARIES[name] = payload
-- Bastion:Print("Registered Library", name)
end
function Bastion:GetLibrary(name)
return LIBRARIES[name]
end
Bastion.Ticker = C_Timer.NewTicker(0.1, function()
if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then
Bastion.CombatTimer:Start()
@ -255,7 +214,6 @@ Command:Register('debug', 'Toggle debug mode on/off', function()
Bastion:Print("Debug mode disabled")
end
end)
Command:Register('dumpspells', 'Dump spells to a file', function()
local i = 1
local rand = math.random(100000, 999999)
@ -273,7 +231,7 @@ Command:Register('dumpspells', 'Dump spells to a file', function()
if spellID then
spellName = spellName:gsub("[%W%s]", "")
WriteFile('bastion-' .. UnitClass('player') .. '-' .. rand .. '.lua',
"local " .. spellName .. " = Bastion.Globals.SpellBook:GetSpell(" .. spellID .. ")\n", true)
"local " .. spellName .. " = Bastion.SpellBook:GetSpell(" .. spellID .. ")", true)
end
i = i + 1
end
@ -319,79 +277,17 @@ Command:Register('missed', 'Dump the list of immune kidney shot spells', functio
end
end)
---@param library Library
function Bastion:RegisterLibrary(library)
LIBRARIES[library.name] = library
end
function Bastion:CheckLibraryDependencies()
for k, v in pairs(LIBRARIES) do
if v.dependencies then
for i = 1, #v.dependencies do
local dep = v.dependencies[i]
if LIBRARIES[dep] then
if LIBRARIES[dep].dependencies then
for j = 1, #LIBRARIES[dep].dependencies do
if LIBRARIES[dep].dependencies[j] == v.name then
Bastion:Print("Circular dependency detected between " .. v.name .. " and " .. dep)
return false
end
end
end
else
Bastion:Print("Library " .. v.name .. " depends on " .. dep .. " but it's not registered")
return false
end
end
end
end
return true
end
function Bastion:Import(library)
local lib = self:GetLibrary(library)
local function Load(dir)
local files = ListFiles(dir)
if not lib then
error("Library " .. library .. " not found")
for i = 1, #files do
local file = files[i]
if file:sub(-4) == ".lua" or file:sub(-5) == '.luac' then
require(dir .. file:sub(1, -5), Bastion)
end
return lib:Resolve()
end
function Bastion:GetLibrary(name)
if not LIBRARIES[name] then
error("Library " .. name .. " not found")
end
local library = LIBRARIES[name]
-- if library.dependencies then
-- for i = 1, #library.dependencies do
-- local dep = library.dependencies[i]
-- if LIBRARIES[dep] then
-- if LIBRARIES[dep].dependencies then
-- for j = 1, #LIBRARIES[dep].dependencies do
-- if LIBRARIES[dep].dependencies[j] == library.name then
-- Bastion:Print("Circular dependency detected between " .. library.name .. " and " .. dep)
-- return false
-- end
-- end
-- end
-- else
-- Bastion:Print("Library " .. v.name .. " depends on " .. dep .. " but it's not registered")
-- return false
-- end
-- end
-- end
return library
end
-- if not Bastion:CheckLibraryDependencies() then
-- return
-- end
Load("@Libraries/")
Load("@Modules/")
Load("@")
Load("scripts/bastion/scripts/Libraries/")
Load("scripts/bastion/scripts/Modules/")
Load("scripts/bastion/scripts/")

Loading…
Cancel
Save