Compare commits

...

27 Commits

Author SHA1 Message Date
4n0n f722d17306 Merge branch 'main' of https://git.tinkr.site/Bastion/Bastion 1 year ago
4n0n 5db2f059d8 Add Spell:Fresh() 1 year ago
4n0n 910387c775 Merge pull request 'main' (#16) from CiscOH/Bastion:main into main 1 year ago
CiscOH 2994e8d1dd remove UnitManager:Validate(token) method 1 year ago
CiscOH eab3bb3a8a Merge pull request 'main' (#4) from Bastion/Bastion:main into main 1 year ago
4n0n e4d4270b60 add bastion requires 1 year ago
4n0n 025c0c5c88 remove 1 year ago
CiscOH 5dc90ce113 Merge pull request 'main' (#3) from Bastion/Bastion:main into main 1 year ago
4n0n bfdd70359d Fix typo 1 year ago
4n0n 5472aa1998 Merge pull request 'main' (#15) from CiscOH/Bastion:main into main 1 year ago
CiscOH ba9de7753f added line break to dump spells 1 year ago
CiscOH 94b584a99b Merge pull request 'Update 'README.md'' (#1) from Bastion/Bastion:main into main 1 year ago
4n0n 6924780785 Update 'README.md' 1 year ago
4n0n febee39182 Add highest/leastof functions to auratable, remove print 1 year ago
4n0n a99e71dd8e Aura table updates 1 year ago
4n0n 36ab641a13 Merge branch 'main' of https://git.tinkr.site/Bastion/Bastion 1 year ago
4n0n e8913d3ab8 Spellbook get list 1 year ago
4n0n 9d594366dd Merge pull request 'Change Unit.ttd_ticker initialization state' (#13) from abunai/Bastion:abunai-ttd-fix into main 1 year ago
abunai 2200a36bdf Change Unit.ttd_ticker initialization state 1 year ago
4n0n 559c4339a4 Fix aura list finding 1 year ago
4n0n 7b3b714d39 Add findanyof 1 year ago
4n0n 1cc8b541f8 Cleanup 1 year ago
4n0n 677229738d Move spellbook and itembook out of globals, remove prints 1 year ago
4n0n 9d47758f8c Merge branch 'main' of https://git.tinkr.site/Bastion/Bastion 1 year ago
4n0n 06916f6bc6 Spellbook and Itembook no longer shared through the engine 1 year ago
4n0n 4c138f1c9f Merge pull request 'More types' (#11) from lyloloq/Bastion:main into main 1 year ago
4n0n f5367327e6 Updated library handling 1 year ago
  1. 2
      .gitignore
  2. 6
      README.md
  3. 11
      scripts/ExampleModule.lua
  4. 21
      scripts/Libraries/ExampleDependency.lua
  5. 15
      scripts/Libraries/ExampleDependencyError.lua
  6. 27
      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,6 +12,8 @@ scripts/Libraries/*
!scripts/.gitkeep
!scripts/ExampleModule.lua
!scripts/Libraries/ExampleLibrary.lua
!scripts/Libraries/ExampleDependency.lua
!scripts/Libraries/ExampleDependencyError.lua
## ignore vscode settings
.vscode/*

@ -10,4 +10,8 @@ Feel free to browse around the [Wiki](https://git.tinkr.site/4n0n/bastion/wiki)
## Quick Start
- [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.
- 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,9 +2,16 @@ local Tinkr, Bastion = ...
local ExampleModule = Bastion.Module:New('ExampleModule')
local Player = Bastion.UnitManager:Get('player')
local FlashHeal = Bastion.SpellBook:GetSpell(2061)
-- Create a local spellbook
local SpellBook = Bastion.SpellBook:New()
local AdvancedMath = Bastion:GetLibrary('AdvancedMath')
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')
print(AdvancedMath:Add(1, 2))

@ -0,0 +1,21 @@
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
}
}))

@ -0,0 +1,15 @@
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,14 +1,25 @@
local Tinkr, Bastion = ...
local ExampleModule = Bastion.Module:New('ExampleModule')
local Player = Bastion.UnitManager:Get('player')
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 AdvancedMath = {}
local CircularDependency = self:Import('Circular') -- Causes a circular dependency error
AdvancedMath.__index = AdvancedMath
Dependable:Test(OtherExports.Test)
function AdvancedMath:Add(a, b)
return a + b
end
local AdvancedMath = {}
Bastion:RegisterLibrary('AdvancedMath', AdvancedMath)
AdvancedMath.__index = AdvancedMath
function AdvancedMath:Add(a, b)
return a + b
end
return AdvancedMath
end
}
}))

@ -1,5 +1,4 @@
-- Document with emmy lua: https://emmylua.github.io/
-- Create an APL trait for the APL class
---@class APLTrait
local APLTrait = {}
@ -55,7 +54,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
@ -85,13 +84,11 @@ 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
@ -111,13 +108,12 @@ 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
@ -189,7 +185,11 @@ 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,7 +199,10 @@ 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
@ -234,7 +237,12 @@ 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)
@ -249,7 +257,10 @@ 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
@ -259,12 +270,10 @@ 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
@ -276,7 +285,10 @@ 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,5 +1,4 @@
-- Document with emmy lua: https://emmylua.github.io/
local Tinkr, Bastion = ...
-- Create a new Aura class
@ -66,19 +65,18 @@ function Aura:New(unit, index, type)
timeMod = 0,
index = nil,
type = nil,
type = nil
}
if self.aura.spellId then
Bastion.SpellBook:GetSpell(self.aura.spellId)
Bastion.Globals.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 = {
@ -100,10 +98,10 @@ function Aura:New(unit, index, type)
auraInstanceID = nil,
index = index,
type = type,
type = type
}
if self.aura.spellId then
Bastion.SpellBook:GetSpell(self.aura.spellId)
Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
end
return self
end
@ -132,11 +130,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.SpellBook:GetSpell(self.aura.spellId)
Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
return self
end
@ -239,7 +237,7 @@ end
-- Get the auras spell id
---@return Spell
function Aura:GetSpell()
return Bastion.SpellBook:GetSpell(self.aura.spellId)
return Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
end
-- Get the auras can apply aura status

@ -384,6 +384,351 @@ 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.SpellBook:GetSpell(spellID)
Bastion.Globals.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 IsItemPending() == 64 then
if IsSpellPending() == 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.SpellBook:GetSpell(self:GetID()):GetLastCastTime()
return Bastion.Globals.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.SpellBook:GetSpell(self.spellID)
return Bastion.Globals.SpellBook:GetSpell(self.spellID)
end
return nil

@ -0,0 +1,115 @@
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,8 +114,12 @@ end
---@return boolean
function List:reduce(callback, initialValue)
local result = initialValue
local done = false
for _, v in ipairs(self._list) do
result = callback(result, v)
result, done = callback(result, v)
if done then
break
end
end
return result
end

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

@ -1,5 +1,4 @@
-- 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
@ -45,12 +44,10 @@ 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,6 +57,12 @@ 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()
@ -523,9 +529,7 @@ end
-- IsDiseaseDispel
---@return boolean
function Spell:IsDiseaseDispel()
return ({
})[self:GetID()]
return ({})[self:GetID()]
end
-- IsSpell

@ -27,13 +27,24 @@ 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 = 0,
ttd_ticker = false,
ttd = 0,
id = false,
}
@ -422,7 +422,7 @@ function Unit:GetCastingOrChannelingSpell()
end
if name then
return Bastion.SpellBook:GetSpell(spellId)
return Bastion.Globals.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 = nil
self.ttd_ticker = false
end
return 0
end
@ -926,12 +926,12 @@ end
-- IsStealthed
---@return boolean
function Unit:IsStealthed()
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)
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)
return self:GetAuras():FindAny(Stealth) or self:GetAuras():FindAny(ShadowDance)
end
@ -959,7 +959,7 @@ end
---@return nil
function Unit:WatchForSwings()
Bastion.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
Bastion.Globals.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,49 +4,6 @@ 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 = {
@ -108,9 +65,6 @@ function UnitManager:New()
return self
end
function UnitManager:Validate(token)
return Validate(token)
end
-- Get or create a unit
---@param token string

@ -6,14 +6,58 @@ 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 require("scripts/bastion/src/" .. class .. "/" .. class, Bastion)
return Bastion:Require("~/src/" .. class .. "/" .. class)
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
@ -41,15 +85,18 @@ Bastion.UnitManager = Bastion.require("UnitManager"):New()
---@type ObjectManager
Bastion.ObjectManager = Bastion.require("ObjectManager"):New()
---@type EventManager
Bastion.EventManager = Bastion.require("EventManager"):New()
Bastion.EventManager = Bastion.require("EventManager")
Bastion.Globals.EventManager = Bastion.EventManager:New()
---@type Spell
Bastion.Spell = Bastion.require("Spell")
---@type SpellBook
Bastion.SpellBook = Bastion.require("SpellBook"):New()
Bastion.SpellBook = Bastion.require("SpellBook")
Bastion.Globals.SpellBook = Bastion.SpellBook:New()
---@type Item
Bastion.Item = Bastion.require("Item")
---@type ItemBook
Bastion.ItemBook = Bastion.require("ItemBook"):New()
Bastion.ItemBook = Bastion.require("ItemBook")
Bastion.Globals.ItemBook = Bastion.ItemBook:New()
---@type AuraTable
Bastion.AuraTable = Bastion.require("AuraTable")
---@type Class
@ -62,11 +109,13 @@ 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.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
local u = Bastion.UnitManager[unit]
if u then
@ -74,10 +123,10 @@ Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
end
end)
Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
local unit, castGUID, spellID = ...
local spell = Bastion.SpellBook:GetIfRegistered(spellID)
local spell = Bastion.Globals.SpellBook:GetIfRegistered(spellID)
if unit == "player" and spell then
spell.lastCastAt = GetTime()
@ -90,7 +139,8 @@ end)
local pguid = UnitGUID("player")
local missed = {}
Bastion.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
local args = {CombatLogGetCurrentEventInfo()}
local subEvent = args[2]
@ -134,15 +184,6 @@ Bastion.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
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()
@ -214,6 +255,7 @@ 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)
@ -231,7 +273,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.SpellBook:GetSpell(" .. spellID .. ")", true)
"local " .. spellName .. " = Bastion.Globals.SpellBook:GetSpell(" .. spellID .. ")\n", true)
end
i = i + 1
end
@ -277,17 +319,79 @@ Command:Register('missed', 'Dump the list of immune kidney shot spells', functio
end
end)
local function Load(dir)
local files = ListFiles(dir)
---@param library Library
function Bastion:RegisterLibrary(library)
LIBRARIES[library.name] = library
end
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)
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)
if not lib then
error("Library " .. library .. " not found")
end
return lib:Resolve()
end
Load("scripts/bastion/scripts/Libraries/")
Load("scripts/bastion/scripts/Modules/")
Load("scripts/bastion/scripts/")
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("@")

Loading…
Cancel
Save