From 031c68009cd6380973af188e75d0617da7491480 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 28 Jan 2024 21:54:53 -0600 Subject: [PATCH] Fix Types --- src/APL/APL.lua | 297 ++++++-------------- src/APLActor/APLActor.lua | 141 ++++++++++ src/APLTrait/APLTrait.lua | 42 +++ src/Aura/Aura.lua | 24 +- src/AuraTable/AuraTable.lua | 136 ++++----- src/Cache/Cache.lua | 5 +- src/Cacheable/Cacheable.lua | 23 +- src/Class/Class.lua | 8 +- src/ClassMagic/ClassMagic.lua | 2 +- src/Command/Command.lua | 7 +- src/Config/Config.lua | 2 +- src/EventManager/EventManager.lua | 13 +- src/Item/Item.lua | 48 ++-- src/ItemBook/ItemBook.lua | 8 +- src/Library/Library.lua | 10 +- src/List/List.lua | 45 +-- src/Module/Module.lua | 11 +- src/MythicPlusUtils/MythicPlusUtils.lua | 27 +- src/Notification/Notification.lua | 69 +++++ src/NotificationList/NotificationList.lua | 92 ++++++ src/NotificationsList/NotificationsList.lua | 147 ---------- src/ObjectManager/ObjectManager.lua | 69 +++-- src/Refreshable/Refreshable.lua | 4 +- src/Sequencer/Sequencer.lua | 6 +- src/Spell/Spell.lua | 165 ++++++----- src/SpellBook/SpellBook.lua | 20 +- src/TimeToDie/TimeToDie.lua | 46 ++- src/Timer/Timer.lua | 5 +- src/Unit/Unit.lua | 75 ++--- src/UnitManager/UnitManager.lua | 57 ++-- src/Vector3/Vector3.lua | 164 +++++------ src/_bastion.lua | 183 ++++++++---- 32 files changed, 1054 insertions(+), 897 deletions(-) create mode 100644 src/APLActor/APLActor.lua create mode 100644 src/APLTrait/APLTrait.lua create mode 100644 src/Notification/Notification.lua create mode 100644 src/NotificationList/NotificationList.lua delete mode 100644 src/NotificationsList/NotificationsList.lua diff --git a/src/APL/APL.lua b/src/APL/APL.lua index 5aa83f0..e0a99d1 100644 --- a/src/APL/APL.lua +++ b/src/APL/APL.lua @@ -1,174 +1,9 @@ --- Create an APL trait for the APL class ----@class APLTrait ----@field cb fun(actor?: APLActorTable):boolean ----@field lastcall number -local APLTrait = {} -APLTrait.__index = APLTrait - --- Constructor ----@param cb fun(actor?: APLActorTable):boolean ----@return APLTrait -function APLTrait:New(cb) - local self = setmetatable({}, APLTrait) - - self.cb = cb - self.lastcall = 0 - - return self -end - --- Evaulate the APL trait ----@param actor? APLActorTable ----@return boolean -function APLTrait:Evaluate(actor) - if GetTime() - self.lastcall > 0.1 then - self.lastresult = self.cb(actor) - self.lastcall = GetTime() - return self.lastresult - end - - return self.lastresult -end - --- tostring ----@return string -function APLTrait:__tostring() - return "Bastion.__APLTrait" -end - ----@class APLActorTableBase ----@field type "spell" | "item" | "apl" | "sequencer" | "variable" | "action" - ----@alias APLActorTable APLActorSpellTable | APLActorItemTable | APLActorAPLTable | APLActorSequencerTable | APLActorVariableTable | APLActorActionTable - --- Create an APL actor for the APL class ----@class APLActor ----@field actor APLActorTable ----@field traits APLTrait[] ----@field name string -local APLActor = {} -APLActor.__index = APLActor - --- Constructor ----@param actor APLActorTable -function APLActor:New(actor) - local self = setmetatable({}, APLActor) - if actor.type == "spell" then - self.name = string.format("[%s] `%s`<%s>", "spell", actor.spell:GetName(), actor.spell:GetID()) - elseif actor.type == "item" then - self.name = string.format("[%s] `%s`<%s>", "item", actor.item:GetName(), actor.item:GetID()) - elseif actor.type == "apl" then - self.name = string.format("[%s] `%s`", "apl", actor.apl.name) - elseif actor.type == "sequencer" then - self.name = string.format("[%s]", "sequencer") - elseif actor.type == "variable" then - self.name = string.format("[%s] `%s`", "variable", actor.variable) - elseif actor.type == "action" then - self.name = string.format("[%s] `%s`", "action", actor.action) - else - self.name = string.format("[%s] Unknown", actor.type) - end - self.actor = actor - self.traits = {} - - return self -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) - end - - return self -end - --- Get the actor ----@return APLActorTable -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(self:GetActor()) then - return false - end - end - - return true -end - --- Execute -function APLActor:Execute() - local actorTable = self:GetActor() - -- If the actor is a sequencer we don't want to continue executing the APL if the sequencer is not finished - if actorTable.type == "sequencer" then - ---@cast actorTable APLActorSequencerTable - if actorTable.condition and actorTable.condition() and not actorTable.sequencer:Finished() then - actorTable.sequencer:Execute() - return true - end - - if not actorTable.condition and not actorTable.sequencer:Finished() then - actorTable.sequencer:Execute() - return true - end - - -- Check if the sequencer can be reset and reset it if it can - if actorTable.sequencer:ShouldReset() then - actorTable.sequencer:Reset() - end - end - if actorTable.type == "apl" then - ---@cast actorTable APLActorAPLTable - if actorTable.condition and actorTable.condition() then - -- print("Bastion: APL:Execute: Executing sub APL " .. actorTable.apl.name) - if actorTable.apl:Execute() then - return true - end - end - end - if actorTable.type == "spell" then - ---@cast actorTable APLActorSpellTable - return actorTable.spell:CastableIf(actorTable.castableFunc):OnCast(actorTable.onCastFunc):Cast(actorTable.target, actorTable.condition) - end - if actorTable.type == "item" then - ---@cast actorTable APLActorItemTable - return actorTable.item:UsableIf(actorTable.usableFunc):Use(actorTable.target, actorTable.condition) - end - if self:GetActor().type == "action" then - ---@cast actorTable APLActorActionTable - -- print("Bastion: APL:Execute: Executing action " .. actorTable.action) - self:GetActor().cb() - end - if actorTable.type == "variable" then - ---@cast actorTable APLActorVariableTable - -- print("Bastion: APL:Execute: Setting variable " .. actorTable.variable) - actorTable._apl.variables[actorTable.variable] = actorTable.cb(actorTable._apl) - end - return false -end - --- has traits ----@return boolean -function APLActor:HasTraits() - return #self.traits > 0 -end - --- tostring ----@return string -function APLActor:__tostring() - return string.format("Bastion.__APLActor(%s)", self.name) -end +---@type Tinkr, Bastion +local Tinkr, Bastion = ... -- APL (Attack priority list) class ----@class APL ----@field apl APLActor[] +---@class Bastion.APL +---@field apl Bastion.APLActor[] ---@field variables table ---@field name string ---@field last { successful: { name: string, time: number, index: number }, attempted: { name: string, time: number, index: number } } @@ -177,14 +12,25 @@ APL.__index = APL -- Constructor ---@param name string ----@return APL +---@return Bastion.APL function APL:New(name) local self = setmetatable({}, APL) self.apl = {} self.variables = {} self.name = name - self.last = {} + self.last = { + successful = { + name = "", + time = -1, + index = -1, + }, + attempted = { + name = "", + time = -1, + index = -1, + }, + } return self end @@ -203,17 +49,17 @@ function APL:GetVariable(name) return self.variables[name] end ----@class APLActorVariableTable : APLActorTableBase +---@class Bastion.APL.Actor.Variable.Table : Bastion.APLActor.Table.Base ---@field variable string ---@field cb fun(...):any ----@field _apl APL +---@field _apl Bastion.APL -- Add variable ---@param name string ---@param cb fun(...):any ----@return APLActor +---@return Bastion.APLActor function APL:AddVariable(name, cb) - local actor = APLActor:New({ + local actor = Bastion.APLActor:New({ type = "variable", variable = name, cb = cb, @@ -223,16 +69,16 @@ function APL:AddVariable(name, cb) return actor end ----@class APLActorActionTable : APLActorTableBase +---@class Bastion.APL.Actor.Action.Table : Bastion.APLActor.Table.Base ---@field action string ---@field cb fun(...):any -- Add a manual action to the APL ---@param action string ---@param cb fun(...):any ----@return APLActor +---@return Bastion.APLActor function APL:AddAction(action, cb) - local actor = APLActor:New({ + local actor = Bastion.APLActor:New({ type = "action", action = action, cb = cb, @@ -241,23 +87,23 @@ function APL:AddAction(action, cb) return actor end ----@class APLActorSpellTable : APLActorTableBase ----@field spell Spell ----@field condition? string|fun(self: Spell): boolean ----@field castableFunc false | fun(self: Spell): boolean ----@field target Unit | false ----@field onCastFunc false | fun(self: Spell):any +---@class Bastion.APL.Actor.Spell.Table : Bastion.APLActor.Table.Base +---@field spell Bastion.Spell +---@field condition? string|fun(self: Bastion.Spell): boolean +---@field castableFunc false | fun(self: Bastion.Spell): boolean +---@field target Bastion.Unit | false +---@field onCastFunc false | fun(self: Bastion.Spell):any -- Add a spell to the APL ----@param spell Spell ----@param condition? string|fun(self: Spell):boolean ----@return APLActor +---@param spell Bastion.Spell +---@param condition? string|fun(self: Bastion.Spell):boolean +---@return Bastion.APLActor function APL:AddSpell(spell, condition) local castableFunc = spell.CastableIfFunc local onCastFunc = spell.OnCastFunc local target = spell:GetTarget() - local actor = APLActor:New({ + local actor = Bastion.APLActor:New({ type = "spell", spell = spell, condition = condition, @@ -271,21 +117,21 @@ function APL:AddSpell(spell, condition) return actor end ----@class APLActorItemTable : APLActorTableBase ----@field item Item ----@field condition? string | fun(self: Item): boolean +---@class Bastion.APL.Actor.Item.Table : Bastion.APLActor.Table.Base +---@field item Bastion.Item +---@field condition? string | fun(self: Bastion.Item): boolean ---@field usableFunc false | fun(...): boolean ----@field target Unit | nil +---@field target Bastion.Unit | nil -- Add an item to the APL ----@param item Item ----@param condition? string | fun(self: Item): boolean ----@return APLActor +---@param item Bastion.Item +---@param condition? string | fun(self: Bastion.Item): boolean +---@return Bastion.APLActor function APL:AddItem(item, condition) local usableFunc = item.UsableIfFunc local target = item:GetTarget() - local actor = APLActor:New({ + local actor = Bastion.APLActor:New({ type = "item", item = item, condition = condition, @@ -298,19 +144,19 @@ function APL:AddItem(item, condition) return actor end ----@class APLActorAPLTable : APLActorTableBase ----@field apl APL +---@class Bastion.APL.Actor.APL.Table : Bastion.APLActor.Table.Base +---@field apl Bastion.APL ---@field condition? fun(...):boolean -- Add an APL to the APL (for sub APLs) ----@param apl APL +---@param apl Bastion.APL ---@param condition fun(...):boolean ----@return APLActor +---@return Bastion.APLActor function APL:AddAPL(apl, condition) if not condition then error("Bastion: APL:AddAPL: No condition for APL " .. apl.name) end - local actor = APLActor:New({ + local actor = Bastion.APLActor:New({ type = "apl", apl = apl, condition = condition, @@ -319,35 +165,50 @@ function APL:AddAPL(apl, condition) return actor end +---@param name string +---@param enabled? boolean +function APL:ToggleAPL(name, enabled) + for _, actor in ipairs(self.apl) do + if actor.actor.type == "apl" and actor.name == name then + actor.enabled = type(enabled) == "boolean" and enabled or not actor.enabled + break + end + end +end + +function APL:UpdateLastAttempted(name, index) + self.last.attempted.name = name + self.last.attempted.time = GetTime() + self.last.attempted.index = index +end + +function APL:UpdateLastSuccessful(name, index) + self.last.successful.name = name + self.last.successful.time = GetTime() + self.last.successful.index = index +end + -- Execute the APL function APL:Execute() for i, actor in ipairs(self.apl) do - self.last.attempted = { - name = actor.name, - time = GetTime(), - index = i, - } - if (not actor:HasTraits() or actor:Evaluate()) and actor:Execute() then - self.last.successful = { - name = actor.name, - time = GetTime(), - index = i, - } + self:UpdateLastAttempted(actor.name, i) + if actor.enabled and (not actor:HasTraits() or actor:Evaluate()) and actor:Execute() then + self:UpdateLastSuccessful(actor.name, i) return true end end end ----@class APLActorSequencerTable : APLActorTableBase ----@field sequencer Sequencer +---@class Bastion.APL.Actor.Sequencer.Table : Bastion.APLActor.Table.Base +---@field sequencer Bastion.Sequencer ---@field condition? fun(...):boolean -- Add a Sequencer to the APL ----@param sequencer Sequencer +---@param sequencer Bastion.Sequencer ---@param condition fun(...):boolean ----@return APLActor +---@return Bastion.APLActor function APL:AddSequence(sequencer, condition) - local actor = APLActor:New({ + local actor = Bastion.APLActor:New({ type = "sequencer", sequencer = sequencer, condition = condition, @@ -362,4 +223,4 @@ function APL:__tostring() return "Bastion.__APL(" .. self.name .. ")" end -return APL, APLActor, APLTrait +return APL diff --git a/src/APLActor/APLActor.lua b/src/APLActor/APLActor.lua new file mode 100644 index 0000000..cdfc7a4 --- /dev/null +++ b/src/APLActor/APLActor.lua @@ -0,0 +1,141 @@ +---@type Tinkr, Bastion +local Tinkr, Bastion = ... + +---@class Bastion.APLActor.Table.Base +---@field type "spell" | "item" | "apl" | "sequencer" | "variable" | "action" + +---@alias Bastion.APLActor.Table Bastion.APL.Actor.Spell.Table | Bastion.APL.Actor.Item.Table | Bastion.APL.Actor.APL.Table | Bastion.APL.Actor.Sequencer.Table | Bastion.APL.Actor.Variable.Table | Bastion.APL.Actor.Action.Table + +-- Create an APL actor for the APL class +---@class Bastion.APLActor +---@field actor Bastion.APLActor.Table +---@field enabled boolean +---@field traits Bastion.APLTrait[] +---@field name string +local APLActor = {} +APLActor.__index = APLActor + +-- Constructor +---@param actor Bastion.APLActor.Table +function APLActor:New(actor) + local self = setmetatable({}, APLActor) + if actor.type == "spell" then + local name = actor.spell:GetName() or "Unknown" + local id = actor.spell:GetID() or 0 + self.name = string.format("[%s] `%s`<%s>", "spell", name, id) + elseif actor.type == "item" then + local name = actor.item:GetName() or "Unknown" + local id = actor.item:GetID() or 0 + self.name = string.format("[%s] `%s`<%s>", "item", name, id) + elseif actor.type == "apl" then + self.name = string.format("[%s] `%s`", "apl", actor.apl.name) + elseif actor.type == "sequencer" then + self.name = string.format("[%s]", "sequencer") + elseif actor.type == "variable" then + self.name = string.format("[%s] `%s`", "variable", actor.variable) + elseif actor.type == "action" then + self.name = string.format("[%s] `%s`", "action", actor.action) + else + self.name = string.format("[%s] Unknown", actor.type) + end + self.actor = actor + self.enabled = true + self.traits = {} + + return self +end + +-- Add a trait to the APL actor +---@param ... Bastion.APLTrait +---@return Bastion.APLActor +function APLActor:AddTraits(...) + for _, trait in ipairs({ ... }) do + table.insert(self.traits, trait) + end + + return self +end + +-- Get the actor +---@return Bastion.APLActor.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(self:GetActor()) then + return false + end + end + + return true +end + +-- Execute +function APLActor:Execute() + local actorTable = self:GetActor() + -- If the actor is a sequencer we don't want to continue executing the APL if the sequencer is not finished + if actorTable.type == "sequencer" then + ---@cast actorTable Bastion.APL.Actor.Sequencer.Table + if actorTable.condition and actorTable.condition() and not actorTable.sequencer:Finished() then + actorTable.sequencer:Execute() + return true + end + + if not actorTable.condition and not actorTable.sequencer:Finished() then + actorTable.sequencer:Execute() + return true + end + + -- Check if the sequencer can be reset and reset it if it can + if actorTable.sequencer:ShouldReset() then + actorTable.sequencer:Reset() + end + end + if actorTable.type == "apl" then + ---@cast actorTable Bastion.APL.Actor.APL.Table + if actorTable.condition and actorTable.condition() then + -- print("Bastion: APL:Execute: Executing sub APL " .. actorTable.apl.name) + if actorTable.apl:Execute() then + return true + end + end + end + if actorTable.type == "spell" then + ---@cast actorTable Bastion.APL.Actor.Spell.Table + return actorTable.spell:CastableIf(actorTable.castableFunc):OnCast(actorTable.onCastFunc):Cast(actorTable.target, + actorTable.condition) + end + if actorTable.type == "item" then + ---@cast actorTable Bastion.APL.Actor.Item.Table + return actorTable.item:UsableIf(actorTable.usableFunc):Use(actorTable.target, actorTable.condition) + end + if self:GetActor().type == "action" then + ---@cast actorTable Bastion.APL.Actor.Action.Table + -- print("Bastion: APL:Execute: Executing action " .. actorTable.action) + self:GetActor().cb() + end + if actorTable.type == "variable" then + ---@cast actorTable Bastion.APL.Actor.Variable.Table + -- print("Bastion: APL:Execute: Setting variable " .. actorTable.variable) + actorTable._apl.variables[actorTable.variable] = actorTable.cb(actorTable._apl) + end + return false +end + +-- has traits +---@return boolean +function APLActor:HasTraits() + return #self.traits > 0 +end + +-- tostring +---@return string +function APLActor:__tostring() + return string.format("Bastion.__APLActor(%s)", self.name) +end + +return APLActor diff --git a/src/APLTrait/APLTrait.lua b/src/APLTrait/APLTrait.lua new file mode 100644 index 0000000..7de6529 --- /dev/null +++ b/src/APLTrait/APLTrait.lua @@ -0,0 +1,42 @@ +---@type Tinkr, Bastion +local Tinkr, Bastion = ... + +-- Create an APL trait for the APL class +---@class Bastion.APLTrait +---@field cb fun(actor?: Bastion.APLActor.Table):boolean +---@field lastcall number +local APLTrait = {} +APLTrait.__index = APLTrait + +-- Constructor +---@param cb fun(actor?: Bastion.APLActor.Table):boolean +---@return Bastion.APLTrait +function APLTrait:New(cb) + local self = setmetatable({}, APLTrait) + + self.cb = cb + self.lastcall = 0 + + return self +end + +-- Evaulate the APL trait +---@param actor? Bastion.APLActor.Table +---@return boolean +function APLTrait:Evaluate(actor) + if GetTime() - self.lastcall > 0.1 then + self.lastresult = self.cb(actor) + self.lastcall = GetTime() + return self.lastresult + end + + return self.lastresult +end + +-- tostring +---@return string +function APLTrait:__tostring() + return "Bastion.__APLTrait" +end + +return APLTrait diff --git a/src/Aura/Aura.lua b/src/Aura/Aura.lua index f4ee9a4..1ebc5dd 100644 --- a/src/Aura/Aura.lua +++ b/src/Aura/Aura.lua @@ -2,7 +2,7 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... ----@class AuraAuraData +---@class Bastion.Aura.Aura.Data ---@field auraInstanceID? number ---@field name? string ---@field icon? number @@ -24,8 +24,8 @@ local Tinkr, Bastion = ... ---@field type? string -- Create a new Aura class ----@class Aura ----@field aura AuraAuraData +---@class Bastion.Aura +---@field aura Bastion.Aura.Aura.Data local Aura = {} function Aura:__index(k) @@ -43,7 +43,7 @@ function Aura:__index(k) end -- Equals ----@param other Aura | Spell +---@param other Bastion.Aura | Bastion.Spell ---@return boolean function Aura:__eq(other) if getmetatable(other) == Aura then @@ -64,12 +64,12 @@ function Aura:__tostring() end -- Constructor ----@param unit? Unit +---@param unit? Bastion.Unit ---@param index? number ---@param type? string function Aura:New(unit, index, type) if unit == nil or index == nil or type == nil then - ---@class Aura + ---@class Bastion.Aura local self = setmetatable({}, Aura) self.aura = { name = nil, @@ -101,7 +101,7 @@ function Aura:New(unit, index, type) local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod, v1, v2, v3, v4 = UnitAura(unit:GetOMToken(), index, type) - ---@class Aura + ---@class Bastion.Aura local self = setmetatable({}, Aura) self.aura = { name = name, @@ -165,9 +165,9 @@ end -- Constructor ---@param unitAuraInfo AuraData ----@return Aura +---@return Bastion.Aura function Aura:CreateFromUnitAuraInfo(unitAuraInfo) - ---@class Aura + ---@class Bastion.Aura local self = setmetatable({}, Aura) --[[ applications @@ -298,7 +298,7 @@ function Aura:GetExpirationTime() end -- Get the auras source ----@return Unit +---@return Bastion.Unit function Aura:GetSource() return Bastion.UnitManager[self.aura.source] end @@ -316,7 +316,7 @@ function Aura:GetNameplateShowPersonal() end -- Get the auras spell id ----@return Spell +---@return Bastion.Spell function Aura:GetSpell() return Bastion.Globals.SpellBook:GetSpell(self.aura.spellId) end @@ -370,7 +370,7 @@ function Aura:GetAuraInstanceID() end -- Check if the aura is dispelable by a spell ----@param spell Spell +---@param spell Bastion.Spell function Aura:IsDispelableBySpell(spell) if (self:GetDispelType() == "" or self:GetDispelType() == nil) and self:GetIsStealable() and spell:IsEnrageDispel() then return true diff --git a/src/AuraTable/AuraTable.lua b/src/AuraTable/AuraTable.lua index 40683d8..988bf25 100644 --- a/src/AuraTable/AuraTable.lua +++ b/src/AuraTable/AuraTable.lua @@ -3,20 +3,20 @@ local Tinkr, Bastion = ... ---@alias auraInstanceId integer ----@class AuraInstanceTable ----@field [spellId] { [auraInstanceId]: Aura } +---@class Bastion.Aura.Instance.Table +---@field [spellId] { [auraInstanceId]: Bastion.Aura } -- Create a new AuraTable class ----@class AuraTable ----@field unit Unit ----@field playerAuras AuraInstanceTable ----@field auras AuraInstanceTable +---@class Bastion.AuraTable +---@field unit Bastion.Unit +---@field playerAuras Bastion.Aura.Instance.Table +---@field auras Bastion.Aura.Instance.Table local AuraTable = {} AuraTable.__index = AuraTable -- Constructor ----@param unit Unit ----@return AuraTable +---@param unit Bastion.Unit +---@return Bastion.AuraTable function AuraTable:New(unit) local self = setmetatable({}, AuraTable) @@ -103,7 +103,7 @@ end -- Update the aura table ---@param instanceID number ----@param aura Aura +---@param aura Bastion.Aura ---@return nil function AuraTable:AddOrUpdateAuraInstanceID(instanceID, aura) local spellId = aura:GetSpell():GetID() @@ -219,7 +219,7 @@ function AuraTable:Update() end -- Get a units auras ----@return table> +---@return table> function AuraTable:GetUnitAuras() if not self.did then self.did = true @@ -274,8 +274,8 @@ function AuraTable:Clear() end -- Check if the unit has a specific aura ----@param spell Spell ----@return Aura +---@param spell Bastion.Spell +---@return Bastion.Aura function AuraTable:Find(spell) local auras = self:GetUnitAuras() local aurasub = auras[spell:GetID()] @@ -300,8 +300,8 @@ function AuraTable:Find(spell) end -- Check if the unit has a specific aura ----@param spell Spell ----@return Aura +---@param spell Bastion.Spell +---@return Bastion.Aura function AuraTable:FindMy(spell) local auras = self:GetMyUnitAuras() local aurasub = auras[spell:GetID()] @@ -326,9 +326,9 @@ function AuraTable:FindMy(spell) end -- Check if the unit has a specific aura ----@param spell Spell ----@param source "any" | Unit ----@return Aura +---@param spell Bastion.Spell +---@param source "any" | Bastion.Unit +---@return Bastion.Aura function AuraTable:FindFrom(spell, source) if type(source) == "string" and source == "any" then return self:FindAny(spell) @@ -359,8 +359,8 @@ function AuraTable:FindFrom(spell, source) end -- Find the aura from the current unit ----@param spell Spell ----@return Aura +---@param spell Bastion.Spell +---@return Bastion.Aura function AuraTable:FindTheirs(spell) local auras = self:GetUnitAuras() local aurasub = auras[spell:GetID()] @@ -387,8 +387,8 @@ function AuraTable:FindTheirs(spell) end -- Find any ----@param spell Spell ----@return Aura +---@param spell Bastion.Spell +---@return Bastion.Aura function AuraTable:FindAny(spell) local a = self:Find(spell) if a:IsValid() then @@ -399,8 +399,8 @@ function AuraTable:FindAny(spell) end -- FindAnyOf ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindAnyOf(spells) return spells:reduce(function(acc, cur) local aura = self:FindAny(cur) @@ -412,8 +412,8 @@ function AuraTable:FindAnyOf(spells) end -- FindAnyOfMy ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindAnyOfMy(spells) return spells:reduce(function(acc, cur) local aura = self:FindMy(cur) @@ -425,8 +425,8 @@ function AuraTable:FindAnyOfMy(spells) end -- FindAnyOfTheirs ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindAnyOfTheirs(spells) return spells:reduce(function(acc, cur) local aura = self:FindTheirs(cur) @@ -438,9 +438,9 @@ function AuraTable:FindAnyOfTheirs(spells) end -- FindAnyFrom ----@param spells List ----@param source Unit ----@return Aura +---@param spells Bastion.List +---@param source Bastion.Unit +---@return Bastion.Aura function AuraTable:FindAnyFrom(spells, source) return spells:reduce(function(acc, cur) local aura = self:FindFrom(cur, source) @@ -452,8 +452,8 @@ function AuraTable:FindAnyFrom(spells, source) end -- FindLongestOf ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindLongestOf(spells) return spells:reduce(function(acc, cur) local aura = self:Find(cur) @@ -470,8 +470,8 @@ function AuraTable:FindLongestOf(spells) end -- FindLongestOfMy ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindLongestOfMy(spells) return spells:reduce(function(acc, cur) local aura = self:FindMy(cur) @@ -488,8 +488,8 @@ function AuraTable:FindLongestOfMy(spells) end -- FindLongestOfTheirs ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindLongestOfTheirs(spells) return spells:reduce(function(acc, cur) local aura = self:FindTheirs(cur) @@ -506,9 +506,9 @@ function AuraTable:FindLongestOfTheirs(spells) end -- FindLongestOfFrom ----@param spells List ----@param source Unit ----@return Aura +---@param spells Bastion.List +---@param source Bastion.Unit +---@return Bastion.Aura function AuraTable:FindLongestOfFrom(spells, source) return spells:reduce(function(acc, cur) local aura = self:FindFrom(cur, source) @@ -525,8 +525,8 @@ function AuraTable:FindLongestOfFrom(spells, source) end -- FindShortestOf ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindShortestOf(spells) return spells:reduce(function(acc, cur) local aura = self:Find(cur) @@ -543,8 +543,8 @@ function AuraTable:FindShortestOf(spells) end -- FindShortestOfMy ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindShortestOfMy(spells) return spells:reduce(function(acc, cur) local aura = self:FindMy(cur) @@ -561,8 +561,8 @@ function AuraTable:FindShortestOfMy(spells) end -- FindShortestOfTheirs ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindShortestOfTheirs(spells) return spells:reduce(function(acc, cur) local aura = self:FindTheirs(cur) @@ -579,9 +579,9 @@ function AuraTable:FindShortestOfTheirs(spells) end -- FindShortestOfFrom ----@param spells List ----@param source Unit ----@return Aura +---@param spells Bastion.List +---@param source Bastion.Unit +---@return Bastion.Aura function AuraTable:FindShortestOfFrom(spells, source) return spells:reduce(function(acc, cur) local aura = self:FindFrom(cur, source) @@ -598,8 +598,8 @@ function AuraTable:FindShortestOfFrom(spells, source) end -- FindMostOf ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindMostOf(spells) return spells:reduce(function(acc, cur) local aura = self:Find(cur) @@ -616,8 +616,8 @@ function AuraTable:FindMostOf(spells) end -- FindMostOfMy ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindMostOfMy(spells) return spells:reduce(function(acc, cur) local aura = self:FindMy(cur) @@ -634,8 +634,8 @@ function AuraTable:FindMostOfMy(spells) end -- FindMostOfTheirs ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindMostOfTheirs(spells) return spells:reduce(function(acc, cur) local aura = self:FindTheirs(cur) @@ -652,9 +652,9 @@ function AuraTable:FindMostOfTheirs(spells) end -- FindMostOfFrom ----@param spells List ----@param source Unit ----@return Aura +---@param spells Bastion.List +---@param source Bastion.Unit +---@return Bastion.Aura function AuraTable:FindMostOfFrom(spells, source) return spells:reduce(function(acc, cur) local aura = self:FindFrom(cur, source) @@ -671,8 +671,8 @@ function AuraTable:FindMostOfFrom(spells, source) end -- FindLeastOf ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindLeastOf(spells) return spells:reduce(function(acc, cur) local aura = self:Find(cur) @@ -689,8 +689,8 @@ function AuraTable:FindLeastOf(spells) end -- FindLeastOfMy ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindLeastOfMy(spells) return spells:reduce(function(acc, cur) local aura = self:FindMy(cur) @@ -707,8 +707,8 @@ function AuraTable:FindLeastOfMy(spells) end -- FindLeastOfTheirs ----@param spells List ----@return Aura +---@param spells Bastion.List +---@return Bastion.Aura function AuraTable:FindLeastOfTheirs(spells) return spells:reduce(function(acc, cur) local aura = self:FindTheirs(cur) @@ -725,9 +725,9 @@ function AuraTable:FindLeastOfTheirs(spells) end -- FindLeastOfFrom ----@param spells List ----@param source Unit ----@return Aura +---@param spells Bastion.List +---@param source Bastion.Unit +---@return Bastion.Aura function AuraTable:FindLeastOfFrom(spells, source) return spells:reduce(function(acc, cur) local aura = self:FindFrom(cur, source) @@ -744,7 +744,7 @@ function AuraTable:FindLeastOfFrom(spells, source) end -- Has any stealable aura ----@param spell? Spell +---@param spell? Bastion.Spell ---@return boolean function AuraTable:HasAnyStealableAura(spell) for _, auras in pairs(self:GetUnitAuras()) do @@ -781,7 +781,7 @@ function AuraTable:GetStealableAura() end -- Has any dispelable aura ----@param spell Spell +---@param spell Bastion.Spell ---@return boolean function AuraTable:HasAnyDispelableAura(spell) for _, auras in pairs(self:GetUnitAuras()) do diff --git a/src/Cache/Cache.lua b/src/Cache/Cache.lua index f9468d5..fa6d328 100644 --- a/src/Cache/Cache.lua +++ b/src/Cache/Cache.lua @@ -1,9 +1,9 @@ ----@class Cache +---@class Bastion.Cache local Cache = {} Cache.__index = Cache -- Constructor ----@return Cache +---@return Bastion.Cache function Cache:New() local self = setmetatable({}, Cache) self.cache = {} @@ -13,7 +13,6 @@ 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] = { diff --git a/src/Cacheable/Cacheable.lua b/src/Cacheable/Cacheable.lua index 07e6967..f1d2bac 100644 --- a/src/Cacheable/Cacheable.lua +++ b/src/Cacheable/Cacheable.lua @@ -2,12 +2,13 @@ local Tinkr, Bastion = ... ----@class Cacheable ----@field cache? Cache +---@class Bastion.Cacheable +---@field cache? Bastion.Cache local Cacheable = { cache = nil, callback = nil, value = nil, + args = nil, -- __eq = function(self, other) -- return self.value.__eq(self.value, other) -- end @@ -24,7 +25,7 @@ function Cacheable:__index(k) end if not self.cache:IsCached("self") then - self.value = self.callback() + self.value = self.callback(SafeUnpack(self.args)) self.cache:Set("self", self.value, 0.5) end @@ -38,14 +39,17 @@ end -- Create ---@generic V +---@generic P ---@param value V ----@param cb fun(): V +---@param cb fun(...:P): V +---@param ... P ---@return V -function Cacheable:New(value, cb) +function Cacheable:New(value, cb, ...) local self = setmetatable({}, Cacheable) self.cache = Bastion.Cache:New() self.value = value + self.args = SafePack(...) self.callback = cb self.cache:Set("self", self.value, 0.5) @@ -62,7 +66,7 @@ end -- Update the value function Cacheable:Update() - self.value = self.callback() + self.value = self.callback(SafeUnpack(self.args)) end -- Set a new value @@ -72,9 +76,12 @@ function Cacheable:Set(value) end -- Set a new callback ----@param cb fun():any -function Cacheable:SetCallback(cb) +---@generic P +---@param cb fun(...: P):any +---@param ... P +function Cacheable:SetCallback(cb, ...) self.callback = cb + self.args = SafePack(...) end return Cacheable diff --git a/src/Class/Class.lua b/src/Class/Class.lua index 04bda47..95fcbd9 100644 --- a/src/Class/Class.lua +++ b/src/Class/Class.lua @@ -2,7 +2,8 @@ local Tinkr, Bastion = ... -- Create a new Class class ----@class Class +---@class Bastion.Class +---@field class Class.Class local Class = {} function Class:__index(k) @@ -19,10 +20,7 @@ function Class:__index(k) return response end ----@class Class ----@field class Class.class - ----@class Class.class +---@class Class.Class ---@field locale string ---@field name string ---@field id number diff --git a/src/ClassMagic/ClassMagic.lua b/src/ClassMagic/ClassMagic.lua index b255ccd..0666b99 100644 --- a/src/ClassMagic/ClassMagic.lua +++ b/src/ClassMagic/ClassMagic.lua @@ -1,4 +1,4 @@ ----@class ClassMagic +---@class Bastion.ClassMagic local ClassMagic = {} ClassMagic.__index = ClassMagic diff --git a/src/Command/Command.lua b/src/Command/Command.lua index 03af256..f38c0be 100644 --- a/src/Command/Command.lua +++ b/src/Command/Command.lua @@ -1,10 +1,11 @@ -- Create a wow command handler class ----@class Command +---@class Bastion.Command ---@field command string ----@field commands Command.commands[] +---@field commands Bastion.Command.Commands[] +---@field prefix string local Command = {} ----@class Command.commands +---@class Bastion.Command.Commands ---@field helpmsg string ---@field cb fun(args: table) diff --git a/src/Config/Config.lua b/src/Config/Config.lua index 8d1f08b..1f7ad1d 100644 --- a/src/Config/Config.lua +++ b/src/Config/Config.lua @@ -1,7 +1,7 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... ----@class Config +---@class Bastion.Config ---@field instantiated boolean ---@field config Tinkr.Util.Config.Instance ---@field defaults nil | table diff --git a/src/EventManager/EventManager.lua b/src/EventManager/EventManager.lua index d9d9439..1e001a8 100644 --- a/src/EventManager/EventManager.lua +++ b/src/EventManager/EventManager.lua @@ -2,25 +2,18 @@ local Tinkr, Bastion = ... -- Create an EventManager class ----@class EventManager +---@class Bastion.EventManager ---@field frame Frame ---@field events table ---@field eventHandlers table ---@field wowEventHandlers table ---@field selfCombatEventHandlers table ---@field CombatEventHandlers table -local EventManager = { - events = {}, - eventHandlers = {}, - wowEventHandlers = {}, - selfCombatEventHandlers = {}, - CombatEventHandlers = {}, - frame = nil, -} +local EventManager = {} EventManager.__index = EventManager -- Constructor ----@return EventManager +---@return Bastion.EventManager function EventManager:New() local self = setmetatable({}, EventManager) self.events = {} diff --git a/src/Item/Item.lua b/src/Item/Item.lua index 91414bb..e497dc4 100644 --- a/src/Item/Item.lua +++ b/src/Item/Item.lua @@ -2,13 +2,13 @@ local Tinkr, Bastion = ... -- Create a new Item class ----@class Item +---@class Bastion.Item ---@field ItemID number ----@field UsableIfFunc boolean | fun(self:Item):boolean ----@field PreUseFunc boolean | fun(self:Item) ----@field target boolean | Unit ----@field conditions table ----@field OnUseFunc boolean | fun(self:Item) +---@field UsableIfFunc boolean | fun(self:Bastion.Item):boolean +---@field PreUseFunc boolean | fun(self:Bastion.Item) +---@field target boolean | Bastion.Unit +---@field conditions table +---@field OnUseFunc boolean | fun(self:Bastion.Item) ---@field spellID number | nil local Item = { UsableIfFunc = false, @@ -47,7 +47,7 @@ function Item:__index(k) end -- Equals ----@param other Item +---@param other Bastion.Item ---@return boolean function Item:__eq(other) return self:GetID() == other:GetID() @@ -126,8 +126,8 @@ function Item:GetCooldownRemaining() end -- Use the Item ----@param unit Unit ----@param condition? string | fun(self:Item):boolean +---@param unit Bastion.Unit +---@param condition? string | fun(self:Bastion.Item):boolean ---@return boolean function Item:Use(unit, condition) if condition then @@ -219,24 +219,24 @@ function Item:Usable() end -- Set a script to check if the Item is Usable ----@param func fun(self:Item):boolean ----@return Item +---@param func fun(self:Bastion.Item):boolean +---@return Bastion.Item function Item:UsableIf(func) self.UsableIfFunc = func return self end -- Set a script to run before the Item has been Use ----@param func fun(self:Item) ----@return Item +---@param func fun(self:Bastion.Item) +---@return Bastion.Item function Item:PreUse(func) self.PreUseFunc = func return self end -- Set a script to run after the Item has been Use ----@param func fun(self:Item) ----@return Item +---@param func fun(self:Bastion.Item) +---@return Bastion.Item function Item:OnUse(func) self.OnUseFunc = func return self @@ -269,7 +269,7 @@ function Item:Click(x, y, z) end -- Check if the Item is Usable and Use it ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Item:Call(unit) if self:Usable() then @@ -280,7 +280,7 @@ function Item:Call(unit) end -- Check if the Item is in range of the unit ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Item:IsInRange(unit) local name, rank, icon, UseTime, Itemmin, Itemmax, ItemID = GetItemInfo(self:GetID()) @@ -343,8 +343,8 @@ end -- Create a condition for the Item ---@param name string ----@param func fun(self:Item) ----@return Item +---@param func fun(self:Bastion.Item) +---@return Bastion.Item function Item:Condition(name, func) self.conditions[name] = { func = func, @@ -388,15 +388,15 @@ function Item:HasCondition(name) end -- Set the Items target ----@param unit Unit ----@return Item +---@param unit Bastion.Unit +---@return Bastion.Item function Item:SetTarget(unit) self.target = unit return self end -- Get the Items target ----@return Unit | boolean +---@return Bastion.Unit | boolean function Item:GetTarget() return self.target end @@ -431,14 +431,14 @@ function Item:IsDiseaseDispel() return ({})[self:GetID()] end ----@param item Item +---@param item Bastion.Item ---@return boolean function Item:IsItem(item) return self:GetID() == item:GetID() end -- Get the Items spell ----@return Spell | nil +---@return Bastion.Spell | nil function Item:GetSpell() if self.spellID then return Bastion.Globals.SpellBook:GetSpell(self.spellID) diff --git a/src/ItemBook/ItemBook.lua b/src/ItemBook/ItemBook.lua index dcb7585..ab4a7de 100644 --- a/src/ItemBook/ItemBook.lua +++ b/src/ItemBook/ItemBook.lua @@ -4,13 +4,13 @@ local Tinkr, Bastion = ... ---@alias itemId integer -- Create a new ItemBook class ----@class ItemBook ----@field items table +---@class Bastion.ItemBook +---@field items table local ItemBook = {} ItemBook.__index = ItemBook -- Constructor ----@return ItemBook +---@return Bastion.ItemBook function ItemBook:New() local self = setmetatable({}, ItemBook) self.items = {} @@ -19,7 +19,7 @@ end -- Get a spell from the ItemBook ---@param id number ----@return Item +---@return Bastion.Item function ItemBook:GetItem(id) if self.items[id] == nil then self.items[id] = Bastion.Item:New(id) diff --git a/src/Library/Library.lua b/src/Library/Library.lua index 568353f..eacfc7a 100644 --- a/src/Library/Library.lua +++ b/src/Library/Library.lua @@ -1,7 +1,7 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... ----@class Library +---@class Bastion.Library ---@field name string | nil ---@field dependencies table ---@field exports table @@ -19,12 +19,12 @@ local Library = { Library.__index = Library ----@class NewLibrary +---@class Bastion.Library.New ---@field name string ----@field exports? { default: fun(self: Library):any } +---@field exports? { default: fun(self: Bastion.Library):any } ----@param library NewLibrary ----@return Library +---@param library Bastion.Library.New +---@return Bastion.Library function Library:New(library) local self = { name = library.name or nil, diff --git a/src/List/List.lua b/src/List/List.lua index eeb023c..289686f 100644 --- a/src/List/List.lua +++ b/src/List/List.lua @@ -1,20 +1,22 @@ ----@class List ----@operator add(any): List ----@operator sub(any): List +---@class Bastion.List: { _list: I[] } +---@operator add(any): Bastion.List +---@operator sub(any): Bastion.List local List = { -- Add overload - ---@param self List - ---@param value any - ---@return List + ---@param self Bastion.List + ---@generic I + ---@param value I + ---@return Bastion.List __add = function(self, value) self:push(value) return self end, -- Subtract overload - ---@param self List - ---@param value any - ---@return List + ---@param self Bastion.List + ---@generic I + ---@param value I + ---@return Bastion.List __sub = function(self, value) self:remove(value) return self @@ -22,8 +24,9 @@ local List = { } List.__index = List ----@param from table | nil ----@return List +---@generic I : table +---@param from? I[] +---@return Bastion.List | Bastion.List function List:New(from) local self = setmetatable({}, List) self._list = from or {} @@ -31,7 +34,6 @@ function List:New(from) end ---@param value any ----@return nil function List:push(value) table.insert(self._list, value) end @@ -92,8 +94,8 @@ function List:each(callback) end ---@generic I : any ----@param callback fun(value: I): boolean ----@return List +---@param callback fun(value: I): I +---@return Bastion.List | Bastion.List function List:map(callback) local newList = List:New() for _, v in ipairs(self._list) do @@ -104,7 +106,7 @@ end ---@generic I : any ---@param callback fun(value: I): boolean ----@return List +---@return Bastion.List | Bastion.List function List:filter(callback) local newList = List:New() for _, v in ipairs(self._list) do @@ -134,7 +136,7 @@ end ---@generic I ---@param callback fun(value: I): boolean ----@return boolean | nil +---@return I function List:find(callback) for _, v in ipairs(self._list) do if callback(v) then @@ -144,7 +146,8 @@ function List:find(callback) return nil end ----@param callback fun(value: any): boolean +---@generic I +---@param callback fun(value: I): boolean ---@return number | nil function List:findIndex(callback) for i, v in ipairs(self._list) do @@ -155,13 +158,13 @@ function List:findIndex(callback) return nil end ----@param callback fun(...): boolean +---@generic I : any +---@param callback fun(a: I, b: I): 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 @@ -170,7 +173,6 @@ function List:reverse() return newList end ----@return List function List:clone() local newList = List:New() for _, v in ipairs(self._list) do @@ -179,8 +181,7 @@ function List:clone() return newList end ----@param list List ----@return List +---@param list Bastion.List function List:concat(list) local newList = List:New() for _, v in ipairs(self._list) do diff --git a/src/Module/Module.lua b/src/Module/Module.lua index 8f0ca29..9e9367f 100644 --- a/src/Module/Module.lua +++ b/src/Module/Module.lua @@ -1,6 +1,6 @@ -- Create a module class for a bastion module ----@class Module +---@class Bastion.Module ---@field name string ---@field enabled boolean ---@field synced function[] @@ -15,7 +15,7 @@ end -- Constructor ---@param name string ----@return Module +---@return Bastion.Module function Module:New(name) local module = {} setmetatable(module, Module) @@ -28,13 +28,11 @@ 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 @@ -51,25 +49,22 @@ 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 table.remove(self.synced, i) - return + break end end end -- Sync ----@return nil function Module:Tick() if self.enabled then for i = 1, #self.synced do diff --git a/src/MythicPlusUtils/MythicPlusUtils.lua b/src/MythicPlusUtils/MythicPlusUtils.lua index 2d73b1f..cc503c1 100644 --- a/src/MythicPlusUtils/MythicPlusUtils.lua +++ b/src/MythicPlusUtils/MythicPlusUtils.lua @@ -1,20 +1,31 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... ----@class MythicPlusUtils +---@class Bastion.MythicPlusUtils.KickEntry +---@field isKick boolean +---@field isStun boolean +---@field isDisorient boolean + +---@class Bastion.MythicPlusUtils +---@field random number +---@field aoeBosses table +---@field tankBusters table +---@field debuffLogging boolean +---@field castLogging boolean +---@field loggedCasts table +---@field loggedDebuffs table +---@field kickList table> local MythicPlusUtils = { debuffLogging = false, castLogging = false, - random = "", loggedCasts = {}, loggedDebuffs = {}, kickList = {}, - aoeBosses = {}, } MythicPlusUtils.__index = MythicPlusUtils ----@return MythicPlusUtils +---@return Bastion.MythicPlusUtils function MythicPlusUtils:New() local self = setmetatable({}, MythicPlusUtils) @@ -227,7 +238,7 @@ function MythicPlusUtils:New() false, false, }, - }, -- Thundering Squall + }, -- Thundering Squall [257899] = { -- Painful Motivation [0] = { true, @@ -1259,7 +1270,7 @@ function MythicPlusUtils:ToggleCastLogging() self.castLogging = not self.castLogging end ----@param unit Unit +---@param unit Bastion.Unit ---@param percent? number ---@return boolean function MythicPlusUtils:CastingCriticalKick(unit, percent) @@ -1288,7 +1299,7 @@ function MythicPlusUtils:CastingCriticalKick(unit, percent) return false end ----@param unit Unit +---@param unit Bastion.Unit ---@param percent number ---@return boolean function MythicPlusUtils:CastingCriticalStun(unit, percent) @@ -1317,7 +1328,7 @@ function MythicPlusUtils:CastingCriticalStun(unit, percent) return false end ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function MythicPlusUtils:IsAOEBoss(unit) return self.aoeBosses[unit:GetID()] diff --git a/src/Notification/Notification.lua b/src/Notification/Notification.lua new file mode 100644 index 0000000..905fb07 --- /dev/null +++ b/src/Notification/Notification.lua @@ -0,0 +1,69 @@ +---@type Tinkr, Bastion +local Tinkr, Bastion = ... + +-- Create a notification class for the notifications list (takes icon and text) +---@class Bastion.Notification +---@field icon Texture +---@field text FontString +---@field frame Frame +---@field addedAt number +---@field duration number +---@field list Bastion.NotificationList +local Notification = { +} +Notification.__index = Notification + +-- Constructor +---@param list Bastion.NotificationList +---@param icon string +---@param text string +---@param duration number +---@return Bastion.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(5, 5) + self.frame:SetPoint("CENTER", list.frame, "CENTER", 0, 0) + self.frame:SetFrameStrata("HIGH") + + -- Create a texture for the icon + self.icon = self.frame:CreateTexture(nil, "ARTWORK") + self.icon:SetSize(32, 32) + self.icon:SetPoint("LEFT", self.frame, "LEFT", 0, 0) + self.icon:SetTexture(icon) + + -- Create a fontstring for the text + 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\\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) + C_Timer.After(0.5, function() + self.frame:Hide() + self.frame:ClearAllPoints() + self.frame:SetParent(nil) + self.frame = nil + self.list:Update() + end) +end + +return Notification diff --git a/src/NotificationList/NotificationList.lua b/src/NotificationList/NotificationList.lua new file mode 100644 index 0000000..97b2b88 --- /dev/null +++ b/src/NotificationList/NotificationList.lua @@ -0,0 +1,92 @@ +---@type Tinkr, Bastion +local Tinkr, Bastion = ... + +-- Create a NotificationList class + +---@class Bastion.NotificationList +---@field frame Frame +local NotificationList = { + notifications = {} +} +NotificationList.__index = NotificationList + +-- Constructor +---@return Bastion.NotificationList +function NotificationList:New() + local self = setmetatable({}, NotificationList) + + -- Create a frame for the notifications + self.frame = CreateFrame("Frame", "BastionNotificationList", UIParent) + 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 > notification.duration then + notification:Remove() + table.remove(self.notifications, i) + end + end + end) + + return self +end + +-- Add a notification to the list +---@param icon string +---@param text string +---@param duration number +---@return nil +function NotificationList:AddNotification(icon, text, duration) + -- Create a new notification + local notification = Bastion.Notification:New(self, icon, text, duration) + + -- Add the notification to the list + table.insert(self.notifications, notification) + UIFrameFadeIn(notification.frame, 0.2, 0, 1) + + -- Update the notifications + self:Update() +end + +-- Update the notifications +---@return nil +function NotificationList:Update() + -- Loop through the notifications + for i, notification in ipairs(self.notifications) do + -- Set the position of the notification + notification.frame:SetPoint("CENTER", self.frame, "CENTER", 0, -42 * (i - 1)) + end +end + +-- Remove a notification from the list +---@param notification Bastion.Notification +---@return nil +function NotificationList:RemoveNotification(notification) + -- Loop through the notifications + for i, v in ipairs(self.notifications) do + -- Check if the notification is the one we want to remove + if v == notification then + -- Remove the notification from the list + table.remove(self.notifications, i) + notification:Remove() + break + end + end +end + +-- Remove all notifications from the list +---@return nil +function NotificationList:RemoveAllNotifications() + -- Loop through the notifications + for i, v in ipairs(self.notifications) do + -- Remove the notification from the list + table.remove(self.notifications, i) + self.notifications[i]:Remove() + end +end + +-- Remove all notifications +return NotificationList diff --git a/src/NotificationsList/NotificationsList.lua b/src/NotificationsList/NotificationsList.lua deleted file mode 100644 index 7b416b5..0000000 --- a/src/NotificationsList/NotificationsList.lua +++ /dev/null @@ -1,147 +0,0 @@ --- 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(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 > notification.duration then - notification:Remove() - table.remove(self.notifications, i) - end - end - end) - - return self -end - --- Create a notification class for the notifications list (takes icon and text) ----@class Notification -local Notification = { -} -Notification.__index = Notification - --- Constructor ----@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(5, 5) - self.frame:SetPoint("CENTER", list.frame, "CENTER", 0, 0) - self.frame:SetFrameStrata("HIGH") - - -- Create a texture for the icon - self.icon = self.frame:CreateTexture(nil, "ARTWORK") - self.icon:SetSize(32, 32) - self.icon:SetPoint("LEFT", self.frame, "LEFT", 0, 0) - self.icon:SetTexture(icon) - - -- Create a fontstring for the text - 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\\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) - C_Timer.After(0.5, function() - self.frame:Hide() - self.frame:ClearAllPoints() - self.frame:SetParent(nil) - self.frame = nil - self.list:Update() - end) -end - --- Add a notification to the list ----@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, duration) - - -- Add the notification to the list - table.insert(self.notifications, notification) - UIFrameFadeIn(notification.frame, 0.2, 0, 1) - - -- Update the notifications - self:Update() -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("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 - -- Check if the notification is the one we want to remove - if v == notification then - -- Remove the notification from the list - table.remove(self.notifications, i) - notification:Remove() - break - end - end -end - --- Remove all notifications from the list ----@return nil -function NotificationsList:RemoveAllNotifications() - -- Loop through the notifications - for i, v in ipairs(self.notifications) do - -- Remove the notification from the list - table.remove(self.notifications, i) - self.notifications[i]:Remove() - end -end - --- Remove all notifications -return NotificationsList, Notification diff --git a/src/ObjectManager/ObjectManager.lua b/src/ObjectManager/ObjectManager.lua index c632552..e5a6075 100644 --- a/src/ObjectManager/ObjectManager.lua +++ b/src/ObjectManager/ObjectManager.lua @@ -1,14 +1,16 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... ----@class ObjectManager ----@field _lists table ----@field enemies List ----@field friends List ----@field activeEnemies List ----@field explosives List ----@field incorporeal List ----@field others List +---@class Bastion.ObjectManager +---@field _lists table +---@field afflicted Bastion.List +---@field enemies Bastion.List +---@field critters Bastion.List +---@field friends Bastion.List +---@field activeEnemies Bastion.List +---@field explosives Bastion.List +---@field incorporeal Bastion.List +---@field others Bastion.List local ObjectManager = {} ObjectManager.__index = ObjectManager @@ -18,10 +20,12 @@ function ObjectManager:New() self._lists = {} self.enemies = Bastion.List:New() + self.critters = Bastion.List:New() self.friends = Bastion.List:New() self.activeEnemies = Bastion.List:New() self.explosives = Bastion.List:New() self.incorporeal = Bastion.List:New() + self.afflicted = Bastion.List:New() self.others = Bastion.List:New() return self @@ -29,8 +33,8 @@ end -- Register a custom list with a callback ---@param name string ----@param cb fun(object: TinkrObjectReference): false | Unit ----@return List | false +---@param cb fun(object: TinkrObjectReference): false | Bastion.Unit +---@return Bastion.List | false function ObjectManager:RegisterList(name, cb) if self._lists[name] then return false @@ -66,7 +70,7 @@ end -- Get a list ---@param name string ----@return List +---@return Bastion.List function ObjectManager:GetList(name) return self._lists[name].list end @@ -74,7 +78,9 @@ end -- Refresh all lists ---@return nil function ObjectManager:Refresh() + self.afflicted:clear() self.enemies:clear() + self.critters:clear() self.friends:clear() self.activeEnemies:clear() self.explosives:clear() @@ -88,25 +94,32 @@ function ObjectManager:Refresh() self:EnumLists(object) if ({ [5] = true, [6] = true, [7] = true })[ObjectType(object)] then - local unit = Bastion.UnitManager:GetObject(ObjectGUID(object)) - if not unit then - unit = Bastion.Unit:New(object) - Bastion.UnitManager:SetObject(unit) - end + local objectGUID = ObjectGUID(object) + if objectGUID then + local unit = Bastion.UnitManager:GetObject(objectGUID) + if not unit then + unit = Bastion.Unit:New(object) + Bastion.UnitManager:SetObject(unit) + end - if unit:GetID() == 204560 then - self.incorporeal:push(unit) - elseif unit:GetID() == 120651 then - self.explosives:push(unit) - elseif unit:IsPlayer() and (unit:IsInParty() or unit == Bastion.UnitManager["player"]) then - self.friends:push(unit) - elseif unit:IsEnemy() then - self.enemies:push(unit) - if unit:InCombatOdds() > 80 then - self.activeEnemies:push(unit) + if ObjectType(object) == 5 and ObjectCreatureType(object) == 8 then + self.critters:push(unit) + elseif unit:GetID() == 204560 then + self.incorporeal:push(unit) + elseif unit:GetID() == 204773 then + self.afflicted:push(unit) + elseif unit:GetID() == 120651 then + self.explosives:push(unit) + elseif unit:IsPlayer() and (unit:IsInParty() or unit == Bastion.UnitManager["player"]) then + self.friends:push(unit) + elseif unit:IsEnemy() then + self.enemies:push(unit) + if unit:InCombatOdds() > 80 or unit:IsAffectingCombat() then + self.activeEnemies:push(unit) + end + else + self.others:push(unit) end - else - self.others:push(unit) end end end diff --git a/src/Refreshable/Refreshable.lua b/src/Refreshable/Refreshable.lua index 051791e..60f1bea 100644 --- a/src/Refreshable/Refreshable.lua +++ b/src/Refreshable/Refreshable.lua @@ -2,9 +2,9 @@ local Tinkr, Bastion = ... -- Define a Refreshable class ----@class Refreshable +---@class Bastion.Refreshable +---@field cache Bastion.Cache local Refreshable = { - cache = nil, callback = nil, value = nil, __eq = function(self, other) diff --git a/src/Sequencer/Sequencer.lua b/src/Sequencer/Sequencer.lua index 591ff2d..6b1495b 100644 --- a/src/Sequencer/Sequencer.lua +++ b/src/Sequencer/Sequencer.lua @@ -1,17 +1,17 @@ -- Create a sequencer class that takes a table of actions and executes them in order ----@class Sequencer +---@class Bastion.Sequencer ---@field resetCondition? fun(): boolean ---@field abortCondition? fun(): boolean ---@field actions SequencerAction[] local Sequencer = {} Sequencer.__index = Sequencer ----@alias SequencerAction fun(sequence: Sequencer):boolean +---@alias SequencerAction fun(sequence: Bastion.Sequencer):boolean -- Constructor ---@param actions table ---@param resetCondition? fun(): boolean ----@return Sequencer +---@return Bastion.Sequencer function Sequencer:New(actions, resetCondition) local self = setmetatable({}, Sequencer) diff --git a/src/Spell/Spell.lua b/src/Spell/Spell.lua index 94249c3..901ff81 100644 --- a/src/Spell/Spell.lua +++ b/src/Spell/Spell.lua @@ -1,66 +1,54 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... ----@class Spell.Traits.Cast +---@class Bastion.Spell.Traits.Cast ---@field moving boolean ---@field dead boolean ---@field global boolean ---@field casting boolean ---@field channeling boolean ---@field override boolean +---@field talent boolean | spellId ----@class Spell.Traits.Target +---@class Bastion.Spell.Traits.Target ---@field exists boolean ---@field player boolean ----@class Spell.Traits ----@field cast Spell.Traits.Cast ----@field target Spell.Traits.Target +---@class Bastion.Spell.Traits +---@field cast Bastion.Spell.Traits.Cast +---@field target Bastion.Spell.Traits.Target ----@class Spell.Traits.Cast.Params : Spell.Traits.Cast, { [string]?: boolean } ----@class Spell.Traits.Target.Params : Spell.Traits.Target, { [string]?: boolean } +---@class Bastion.Spell.Traits.Cast.Params : Bastion.Spell.Traits.Cast, { [string]?: boolean } +---@class Spell.Traits.Target.Params : Bastion.Spell.Traits.Target, { [string]?: boolean } ----@class Spell.Traits.Params ----@field cast? Spell.Traits.Cast.Params +---@class Bastion.Spell.Traits.Params +---@field cast? Bastion.Spell.Traits.Cast.Params ---@field target? Spell.Traits.Target.Params ----@class Spell.Aura ----@field spell Spell ----@field source? Unit ----@field target? Unit +---@class Bastion.Spell.Aura +---@field spell Bastion.Spell +---@field source? Bastion.Unit +---@field target? Bastion.Unit ---@field lastApplied number -- Create a new Spell class ----@class Spell ----@field auras table ----@field CastableIfFunc false | fun(self:Spell):boolean +---@class Bastion.Spell +---@field auras table +---@field CastableIfFunc false | fun(self:Bastion.Spell):boolean ---@field damage number ----@field damageFormula false | fun(self:Spell):number +---@field damageFormula false | fun(self:Bastion.Spell):number ---@field lastCastAt number | false ---@field lastCastAttempt number | false ----@field OnCastFunc fun(self:Spell) | false ----@field overrides { [spellId]: fun(self: Spell): Spell } ----@field PostCastFunc fun(self:Spell) | false ----@field PreCastFunc fun(self:Spell) | false +---@field OnCastFunc fun(self:Bastion.Spell) | false +---@field overrides { [spellId]: fun(self: Bastion.Spell): Bastion.Spell } +---@field PostCastFunc fun(self:Bastion.Spell) | false +---@field PreCastFunc fun(self:Bastion.Spell) | false ---@field release_at false ---@field spellID number ----@field target Unit | false ----@field traits Spell.Traits +---@field target Bastion.Unit | false +---@field traits Bastion.Spell.Traits ---@field wasLooking boolean -local Spell = { - auras = {}, - CastableIfFunc = false, - conditions = {}, - damage = 0, - damageFormula = false, - lastCastAt = false, - lastCastAttempt = false, - OnCastFunc = false, - overrides = {}, - PostCastFunc = false, - PreCastFunc = false, - release_at = false, -} +local Spell = {} local usableExcludes = { [18562] = true, @@ -81,7 +69,7 @@ function Spell:__index(k) end -- Equals ----@param other Spell +---@param other Bastion.Spell function Spell:__eq(other) return self:GetID() == other:GetID() end @@ -94,9 +82,17 @@ end -- Constructor ---@param id number function Spell:New(id) - ---@class Spell + ---@class Bastion.Spell local self = setmetatable({}, Spell) self.auras = {} + self.CastableIfFunc = false + self.damage = 0 + self.damageFormula = false + self.lastCastAt = false + self.lastCastAttempt = false + self.OnCastFunc = false + self.PostCastFunc = false + self.release_at = false self.conditions = {} self.overrides = {} self.spellID = id @@ -108,6 +104,7 @@ function Spell:New(id) casting = false, channeling = false, override = false, + talent = false, }, target = { exists = true, @@ -137,7 +134,7 @@ function Spell:GetID(ignoreOverride) end -- Add post cast func ----@param func fun(self:Spell) +---@param func fun(self:Bastion.Spell) function Spell:PostCast(func) self.PostCastFunc = func return self @@ -202,21 +199,21 @@ function Spell:OnCooldown() end -- Clear castable function ----@return Spell +---@return Bastion.Spell function Spell:ClearCastableFunction() self.CastableIfFunc = false return self end ----@param spell Spell ----@param func fun(self: Spell): boolean +---@param spell Bastion.Spell +---@param func fun(self: Bastion.Spell): boolean function Spell:AddOverrideSpell(spell, func) self.overrides[spell:GetID()] = func end -- Cast the spell ----@param unit Unit ----@param condition? string | fun(self:Spell):boolean +---@param unit Bastion.Unit +---@param condition? string | fun(self:Bastion.Spell):boolean ---@return boolean function Spell:Cast(unit, condition) if condition then @@ -237,12 +234,14 @@ function Spell:Cast(unit, condition) end -- Check if the mouse was looking + ---@type boolean self.wasLooking = IsMouselooking() -- if unit:GetOMToken() contains 'nameplate' then we need to use Object wrapper to cast local u = unit and unit:GetOMToken() or self.traits.target.player and "none" or "none" if type(u) == "string" and string.find(u, "nameplate") then + ---@diagnostic disable-next-line: cast-local-type u = Object(u) end @@ -264,7 +263,7 @@ function Spell:Cast(unit, condition) end -- ForceCast the spell ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Spell:ForceCast(unit) -- Check if the mouse was looking @@ -273,6 +272,7 @@ function Spell:ForceCast(unit) -- if unit:GetOMToken() contains 'nameplate' then we need to use Object wrapper to cast local u = unit and unit:GetOMToken() or self.traits.target.player and "none" or "none" if type(u) == "string" and string.find(u, "nameplate") then + ---@diagnostic disable-next-line: cast-local-type u = Object(u) end @@ -338,7 +338,7 @@ function Spell:IsKnownAndUsable(override) return self:IsKnown(override) and not self:IsOnCooldown() and self:IsUsable(override ~= nil and false or true) end ----@param traits Spell.Traits.Params +---@param traits Bastion.Spell.Traits.Params function Spell:SetTraits(traits) for _, trait in pairs({ "cast", "target" }) do if type(traits[trait]) == "table" then @@ -353,7 +353,7 @@ function Spell:SetTraits(traits) end function Spell:EvaluateTraits() - local player = Bastion.UnitManager["player"] + local player = Bastion.UnitManager:Get("player") if not self.traits.cast.global and player:GetGCD() > 0 then return false @@ -379,6 +379,10 @@ function Spell:EvaluateTraits() return false end + if self.traits.cast.talent and not IsPlayerSpell(type(self.traits.cast.talent) == "number" and tonumber(self.traits.cast.talent) or self:GetID()) then + return false + end + return true end @@ -388,28 +392,29 @@ function Spell:Castable() return false end if self:GetCastableFunction() then - return self:GetCastableFunction()(self) and self:IsKnownAndUsable(self.traits.cast.override or nil) + return self:GetCastableFunction()(self) and + self:IsKnownAndUsable(type(self.traits.cast.override) ~= nil and self.traits.cast.override or nil) end - return self:IsKnownAndUsable(self.traits.cast.override or nil) + return self:IsKnownAndUsable(type(self.traits.cast.override) ~= nil and self.traits.cast.override or nil) end -- Set a script to check if the spell is castable ----@param func fun(spell:Spell):boolean +---@param func fun(spell:Bastion.Spell):boolean function Spell:CastableIf(func) self.CastableIfFunc = func return self end -- Set a script to run before the spell has been cast ----@param func fun(spell:Spell) +---@param func fun(spell:Bastion.Spell) function Spell:PreCast(func) self.PreCastFunc = func return self end -- Set a script to run after the spell has been cast ----@param func fun(spell:Spell) +---@param func fun(spell:Bastion.Spell) function Spell:OnCast(func) self.OnCastFunc = func return self @@ -422,7 +427,7 @@ function Spell:GetWasLooking() end -- Click the spell ----@param x number|Vector3 +---@param x number|Bastion.Vector3 ---@param y? number ---@param z? number ---@return boolean @@ -445,18 +450,12 @@ function Spell:Click(x, y, z) end -- Check if the spell is castable and cast it ----@param unit Unit ----@return boolean +---@param unit Bastion.Unit function Spell:Call(unit) - if self:Castable() then - self:Cast(unit) - return true - end - return false + return self:Cast(unit) end -- Check if the spell is castable and cast it ----@return boolean function Spell:HasRange() return SpellHasRange(self:GetName()) end @@ -470,7 +469,7 @@ function Spell:GetRange() end -- Check if the spell is in range of the unit ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Spell:IsInRange(unit) local hasRange = self:HasRange() @@ -484,7 +483,7 @@ function Spell:IsInRange(unit) return true end - return Bastion.UnitManager["player"]:InMelee(unit) + return Bastion.UnitManager:Get("player"):InMelee(unit) end -- Get the last cast time @@ -570,8 +569,8 @@ end -- Create a condition for the spell ---@param name string ----@param func fun(self:Spell):boolean ----@return Spell +---@param func fun(self:Bastion.Spell):boolean +---@return Bastion.Spell function Spell:Condition(name, func) self.conditions[name] = { func = func, @@ -581,7 +580,7 @@ end -- Get a condition for the spell ---@param name string ----@return { func: fun(self: Spell): boolean } | nil +---@return { func: fun(self: Bastion.Spell): boolean } | nil function Spell:GetCondition(name) local condition = self.conditions[name] if condition then @@ -616,8 +615,8 @@ function Spell:HasCondition(name) end -- Set the spells target ----@param unit Unit ----@return Spell +---@param unit Bastion.Unit +---@return Bastion.Spell function Spell:SetTarget(unit) self.target = unit return self @@ -671,7 +670,7 @@ function Spell:IsDiseaseDispel() end -- IsSpell ----@param spell Spell +---@param spell Bastion.Spell ---@return boolean function Spell:IsSpell(spell) return self:GetID() == spell:GetID() @@ -690,7 +689,7 @@ function Spell:IsFree() return self:GetCost() == 0 end ----@param damageFormula fun(self:Spell): number +---@param damageFormula fun(self:Bastion.Spell): number function Spell:RegisterDamageFormula(damageFormula) self.damageFormula = damageFormula end @@ -704,19 +703,19 @@ function Spell:Damage() end end ----@param target Unit ----@param source? "any" | Unit +---@param target Bastion.Unit +---@param source? "any" | Bastion.Unit function Spell:GetAura(target, source) if type(source) == "nil" then - source = Bastion.UnitManager["player"] + source = Bastion.UnitManager:Get("player") end return target:GetAuras():FindFrom(self, source) end ----@param spell Spell ----@param source? Unit ----@param target? Unit +---@param spell Bastion.Spell +---@param source? Bastion.Unit +---@param target? Bastion.Unit function Spell:TrackAura(spell, source, target) self.auras[spell:GetID()] = { spell = spell, @@ -726,9 +725,9 @@ function Spell:TrackAura(spell, source, target) } end ----@param aura Spell ----@param source? Unit ----@param target? Unit +---@param aura Bastion.Spell +---@param source? Bastion.Unit +---@param target? Bastion.Unit function Spell:CheckAuraStatus(aura, source, target) for id, trackedAura in pairs(self.auras) do if aura:GetID() == id then @@ -738,9 +737,9 @@ function Spell:CheckAuraStatus(aura, source, target) return false end ----@param spell Spell ----@param source? Unit ----@param target? Unit +---@param spell Bastion.Spell +---@param source? Bastion.Unit +---@param target? Bastion.Unit function Spell:UpdateAura(spell, source, target) if not self.auras[spell:GetID()] then self:TrackAura(spell, source, target) diff --git a/src/SpellBook/SpellBook.lua b/src/SpellBook/SpellBook.lua index 70c8cd9..695063a 100644 --- a/src/SpellBook/SpellBook.lua +++ b/src/SpellBook/SpellBook.lua @@ -2,14 +2,14 @@ local Tinkr, Bastion = ... -- Create a new SpellBook class ----@class SpellBook ----@field spells table ----@field auras { [spellId]: { [spellId]: { spell: Spell, source?: Unit, target?: Unit, lastApplied: number } } } +---@class Bastion.SpellBook +---@field spells table +---@field auras { [spellId]: { [spellId]: { spell: Bastion.Spell, source?: Bastion.Unit, target?: Bastion.Unit, lastApplied: number } } } local SpellBook = {} SpellBook.__index = SpellBook -- Constructor ----@return SpellBook +---@return Bastion.SpellBook function SpellBook:New() local self = setmetatable({}, SpellBook) self.spells = {} @@ -28,7 +28,7 @@ end ]] -- Get a spell from the spellbook ---@param id integer ----@return Spell +---@return Bastion.Spell function SpellBook:GetSpell(id) local override = FindSpellOverrideByID(id) if self.spells[id] == nil then @@ -45,7 +45,7 @@ function SpellBook:GetSpell(id) end ---@param ... integer ----@return Spell, ... Spell +---@return Bastion.Spell, ... Spell function SpellBook:GetSpells(...) local spells = {} for _, id in ipairs({ ... }) do @@ -55,8 +55,8 @@ function SpellBook:GetSpells(...) return unpack(spells) end ----@param aura Spell ----@return Spell[] +---@param aura Bastion.Spell +---@return Bastion.Spell[] function SpellBook:GetAuraSpells(aura) local spells = {} for _, spell in pairs(self.spells) do @@ -69,7 +69,7 @@ function SpellBook:GetAuraSpells(aura) end ---@param ... integer ----@return List +---@return Bastion.List function SpellBook:GetList(...) local spells = {} for _, id in ipairs({ ... }) do @@ -80,7 +80,7 @@ function SpellBook:GetList(...) end ---@param name string ----@return Spell +---@return Bastion.Spell function SpellBook:GetSpellByName(name) local _, rank, icon, castTime, minRange, maxRange, spellID, originalIcon = GetSpellInfo(name) return self:GetSpell(spellID) diff --git a/src/TimeToDie/TimeToDie.lua b/src/TimeToDie/TimeToDie.lua index e247340..1f3c093 100644 --- a/src/TimeToDie/TimeToDie.lua +++ b/src/TimeToDie/TimeToDie.lua @@ -10,7 +10,7 @@ end local Cache = Bastion.Globals.UnitInfo --- An attempt to integrate HeroLib TTD timers. ----@class TimeToDie +---@class Bastion.TimeToDie local TimeToDie = { Settings = { -- Refresh time (seconds) : min=0.1, max=2, default = 0.1 @@ -29,8 +29,7 @@ local TimeToDie = { } function TimeToDie:IterableUnits() - return Bastion.List:New():concat(Bastion.ObjectManager.enemies):concat(Bastion.ObjectManager.explosives):concat( - Bastion.ObjectManager.incorporeal) + return Bastion.ObjectManager.enemies end function TimeToDie:Refresh() @@ -38,24 +37,22 @@ function TimeToDie:Refresh() local historyCount = TimeToDie.Settings.HistoryCount local historyTime = TimeToDie.Settings.HistoryTime local ttdCache = TimeToDie.Cache - local iterableUnits = TimeToDie:IterableUnits() + local iterableUnits = Bastion.ObjectManager.enemies local units = TimeToDie.Units local existingUnits = TimeToDie.ExistingUnits wipe(existingUnits) - local thisUnit - ---@param unit Unit + ---@param unit Bastion.Unit iterableUnits:each(function(unit) - thisUnit = unit - if thisUnit:Exists() then - local unitGUID = thisUnit:GetGUID() + if unit:Exists() then + local unitGUID = unit:GetGUID() -- Check if we didn't already scanned this unit. if unitGUID and not existingUnits[unitGUID] then existingUnits[unitGUID] = true - local healthPercentage = thisUnit:GetHealthPercent() + local healthPercentage = unit:GetHealthPercent() -- Check if it's a valid unit - if Player:CanAttack(thisUnit) and healthPercentage < 100 then + if healthPercentage < 100 then local unitTable = units[unitGUID] -- Check if we have seen one time this unit, if we don't then initialize it. if not unitTable or healthPercentage > unitTable[1][1][2] then @@ -123,33 +120,33 @@ TimeToDie.specialTTDPercentageData = { ----- Castle Nathria ----- --- Stone Legion Generals -- General Kaal leaves the fight at 50% if General Grashaal has not fight yet. We take 49% as check value since it get -95% dmg reduction at 50% until intermission is over. - ---@param self Unit + ---@param self Bastion.Unit [168112] = function(self) return (not self:CheckHPFromBossList(168113, 99) and 49) or 0 end, --- Sun King's Salvation -- Shade of Kael'thas fight is 60% -> 45% and then 10% -> 0%. - ---@param self Unit + ---@param self Bastion.Unit [165805] = function(self) return (self:GetHealthPercent() > 20 and 45) or 0 end, ----- Sanctum of Domination ----- --- Eye of the Jailer leaves at 66% and 33% - ---@param self Unit + ---@param self Bastion.Unit [180018] = function(self) return (self:GetHealthPercent() > 66 and 66) or (self:GetHealthPercent() <= 66 and self:GetHealthPercent() > 33 and 33) or 0 end, --- Painsmith Raznal leaves at 70% and 40% - ---@param self Unit + ---@param self Bastion.Unit [176523] = function(self) return (self:GetHealthPercent() > 70 and 70) or (self:GetHealthPercent() <= 70 and self:GetHealthPercent() > 40 and 40) or 0 end, --- Fatescribe Roh-Kalo phases at 70% and 40% - ---@param self Unit + ---@param self Bastion.Unit [179390] = function(self) return (self:GetHealthPercent() > 70 and 70) or (self:GetHealthPercent() <= 70 and self:GetHealthPercent() > 40 and 40) or 0 end, --- Sylvanas Windrunner intermission at 83% and "dies" at 50% (45% in MM) - ---@param self Unit + ---@param self Bastion.Unit [180828] = function(self) local _, _, difficultyId = GetInstanceInfo() return (self:GetHealthPercent() > 83 and 83) or @@ -166,7 +163,7 @@ TimeToDie.specialTTDPercentageData = { -- Hymdall leaves the fight at 10%. [94960] = 10, -- Fenryr leaves the fight at 60%. We take 50% as check value since it doesn't get immune at 60%. - ---@param self Unit + ---@param self Bastion.Unit [95674] = function(self) return (self:GetHealthPercent() > 50 and 60) or 0 end, -- Odyn leaves the fight at 80%. [95676] = 80, @@ -176,14 +173,15 @@ TimeToDie.specialTTDPercentageData = { ----- Trial of Valor ----- --- Odyn -- Hyrja & Hymdall leaves the fight at 25% during first stage and 85%/90% during second stage (HM/MM). - ---@param self Unit + ---@param self Bastion.Unit [114360] = function(self) local _, _, difficultyId = GetInstanceInfo() return (not self:CheckHPFromBossList(114263, 99) and 25) or (difficultyId == 16 and 85) or 90 end, - ---@param self Unit + ---@param self Bastion.Unit [114361] = function(self) + local _, _, difficultyId = GetInstanceInfo() return (not self:CheckHPFromBossList(114263, 99) and 25) or (difficultyId == 16 and 85) or 90 end, @@ -191,7 +189,7 @@ TimeToDie.specialTTDPercentageData = { [114263] = 10, ----- Nighthold ----- --- Elisande leaves the fight two times at 10% then normally dies. She looses 50% power per stage (100 -> 50 -> 0). - ---@param self Unit + ---@param self Bastion.Unit [106643] = function(self) return (self:GetPower() > 0 and 10) or 0 end, --- Warlord of Draenor (WoD) @@ -215,7 +213,7 @@ TimeToDie.specialTTDPercentageData = { } -- Returns the max fight length of boss units, or the current selected target if no boss units ----@param enemies? List +---@param enemies? Bastion.List ---@param bossOnly? boolean function TimeToDie.FightRemains(enemies, bossOnly) local bossExists, maxTimeToDie @@ -236,7 +234,7 @@ function TimeToDie.FightRemains(enemies, bossOnly) -- If we specify an AoE range, iterate through all the targets in the specified range if enemies then - ---@param enemy Unit + ---@param enemy Bastion.Unit enemies:each(function(enemy) if (enemy:InCombatOdds() > 80 or enemy:IsDummy()) and enemy:TimeToDieIsNotValid() then maxTimeToDie = math.max(maxTimeToDie or 0, enemy:TimeToDie2()) @@ -262,7 +260,7 @@ function TimeToDie.BossFightRemainsIsNotValid() end -- Returns if the current fight length meets the requirements. ----@param enemies? List +---@param enemies? Bastion.List ---@param operator CompareThisTable ---@param value number ---@param checkIfValid boolean diff --git a/src/Timer/Timer.lua b/src/Timer/Timer.lua index f4888b8..f2bd5f1 100644 --- a/src/Timer/Timer.lua +++ b/src/Timer/Timer.lua @@ -2,7 +2,8 @@ local Tinkr, Bastion = ... -- Create a new Timer class ----@class Timer +---@class Bastion.Timer +---@field type string local Timer = { startTime = nil, resetAfterCombat = false, @@ -11,7 +12,7 @@ Timer.__index = Timer -- Constructor ---@param type string ----@return Timer +---@return Bastion.Timer function Timer:New(type) local self = setmetatable({}, Timer) self.startTime = nil diff --git a/src/Unit/Unit.lua b/src/Unit/Unit.lua index 8c28b5b..f3f81c9 100644 --- a/src/Unit/Unit.lua +++ b/src/Unit/Unit.lua @@ -2,22 +2,17 @@ local Tinkr, Bastion = ... -- Create a new Unit class ----@class Unit +---@class Bastion.Unit ---@field id boolean | number ---@field ttd_ticker false | cbObject ----@field unit TinkrObjectReference ----@field aura_table AuraTable | nil +---@field unit? TinkrObjectReference +---@field aura_table Bastion.AuraTable | nil local Unit = { - ---@type Cache + ---@type Bastion.Cache cache = nil, aura_table = nil, ---@type UnitId | WowGameObject unit = nil, - last_shadow_techniques = 0, - swings_since_sht = 0, - last_off_attack = 0, - last_main_attack = 0, - last_combat_time = 0, ttd_ticker = false, ttd = 0, id = false, --[[ @asnumber ]] @@ -42,7 +37,7 @@ function Unit:__index(k) end -- Equals ----@param other Unit +---@param other Bastion.Unit ---@return boolean function Unit:__eq(other) return UnitIsUnit(self:GetOMToken(), other:GetOMToken()) @@ -61,10 +56,15 @@ end -- Constructor ---@param unit? TinkrObjectReference ----@return Unit function Unit:New(unit) + ---@class Bastion.Unit local self = setmetatable({}, Unit) self.unit = unit + self.last_shadow_techniques = 0 + self.swings_since_sht = 0 + self.last_off_attack = 0 + self.last_main_attack = 0 + self.last_combat_time = 0 self.cache = Bastion.Cache:New() self.aura_table = Bastion.AuraTable:New(self) self.regression_history = {} @@ -89,7 +89,6 @@ function Unit:Token() end -- Get the units name ----@return string? function Unit:GetName() local unitName, realm = UnitName(self:GetOMToken()) return unitName @@ -181,14 +180,14 @@ function Unit:GetPowerDeficit(powerType) end -- Get the units position ----@return Vector3 +---@return Bastion.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 +---@param unit Bastion.Unit ---@return number function Unit:GetDistance(unit) local pself = self:GetPosition() @@ -244,8 +243,7 @@ function Unit:IsHostile() return UnitCanAttack(self:GetOMToken(), "player") end ----@param unit Unit ----@return number +---@param unit Bastion.Unit function Unit:GetReaction(unit) return UnitReaction(unit:GetOMToken(), self:GetOMToken()) end @@ -354,14 +352,14 @@ function Unit:IsAffectingCombat() end -- Get the units class id ----@return Class +---@return Bastion.Class function Unit:GetClass() local locale, class, classID = UnitClass(self:GetOMToken()) return Bastion.Class:New(locale, class, classID) end -- Get the units auras ----@return AuraTable +---@return Bastion.AuraTable function Unit:GetAuras() return self.aura_table end @@ -382,7 +380,7 @@ local isClassicWow = select(4, GetBuildInfo()) < 40000 local losFlag = bit.bor(0x1, 0x10) -- Check if the unit can see another unit ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:CanSee(unit) -- mechagon smoke cloud @@ -455,7 +453,7 @@ function Unit:GetTimeCastIsAt(percent) end -- Get Casting or channeling spell ----@return Spell | nil +---@return Bastion.Spell | nil function Unit:GetCastingOrChannelingSpell() local name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, notInterruptible, spellId = UnitCastingInfo( self:GetOMToken()) @@ -503,10 +501,12 @@ function Unit:IsCastingOrChanneling() end function Unit:CastTarget() - return self:IsCastingOrChanneling() and Bastion.UnitManager:Get(ObjectCastingTarget(self:GetOMToken())) + ---@diagnostic disable-next-line: param-type-mismatch + return self:IsCastingOrChanneling() and Bastion.UnitManager:Get(ObjectCastingTarget(self:GetOMToken())) or + Bastion.UnitManager:Get("none") end ----@param unit Unit +---@param unit Bastion.Unit function Unit:CastTargetIsUnit(unit) return self:IsCastingOrChanneling() and self:CastTarget():IsUnit(unit) end @@ -516,7 +516,7 @@ function Unit:IsImmobilized() end -- Check if the unit can attack the target ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:CanAttack(unit) return UnitCanAttack(self:GetOMToken(), unit:GetOMToken()) @@ -655,7 +655,7 @@ function Unit:IsMovingAtAll() return ObjectMovementFlag(self:GetOMToken()) ~= 0 end ----@param unit? Unit +---@param unit? Bastion.Unit ---@return number function Unit:GetComboPoints(unit) if Tinkr.classic or Tinkr.era then @@ -676,7 +676,7 @@ function Unit:GetComboPointsMax() end -- Get combopoints deficit ----@param unit Unit | nil +---@param unit Bastion.Unit | nil ---@return number function Unit:GetComboPointsDeficit(unit) if Tinkr.classic or Tinkr.era then @@ -686,14 +686,14 @@ function Unit:GetComboPointsDeficit(unit) end -- IsUnit ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:IsUnit(unit) return UnitIsUnit(self:GetOMToken(), unit and unit:GetOMToken() or "none") end -- IsTanking ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:IsTanking(unit) local isTanking, status, threatpct, rawthreatpct, threatvalue = UnitDetailedThreatSituation(self:GetOMToken(), @@ -702,7 +702,7 @@ function Unit:IsTanking(unit) end -- IsFacing ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:IsFacing(unit) local rot = ObjectRotation(self:GetOMToken()) @@ -725,7 +725,7 @@ function Unit:IsFacing(unit) end -- IsBehind ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:IsBehind(unit) local rot = ObjectRotation(unit:GetOMToken()) @@ -747,7 +747,7 @@ function Unit:IsBehind(unit) end -- IsInfront ----@param unit Unit +---@param unit Bastion.Unit ---@return boolean function Unit:IsInfront(unit) return not self:IsBehind(unit) @@ -783,7 +783,7 @@ 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 +---@param unit Bastion.Unit ---@return boolean function Unit:InMelee(unit) local x, y, z = ObjectPosition(self.unit) @@ -809,10 +809,12 @@ end -- Get object id function Unit:GetID() - if self.id then + if self.id ~= false then + ---@type number return self.id end self.id = ObjectID(self:GetOMToken()) + ---@type number return self.id or 0 end @@ -970,6 +972,7 @@ end ---@return number function Unit:InCombatOdds() local time = self:GetCombatTime() + local percent = 1 - (time / 60) return percent * 100 @@ -1162,7 +1165,7 @@ end -- Is the unit within distance of the target (combat reach + distance) --- If the target is within 8 combat yards (8 + combat reach) of the unit ----@param Target Unit +---@param Target Bastion.Unit ---@param Distance number ---@return boolean function Unit:IsWithinCombatDistance(Target, Distance) @@ -1173,7 +1176,7 @@ function Unit:IsWithinCombatDistance(Target, Distance) end -- Check if the unit is within X yards (consider combat reach) ----@param Target Unit +---@param Target Bastion.Unit ---@param Distance number ---@return boolean function Unit:IsWithinDistance(Target, Distance) @@ -1181,7 +1184,7 @@ function Unit:IsWithinDistance(Target, Distance) end -- Get the angle between the unit and the target in raidans ----@param Target Unit +---@param Target Bastion.Unit ---@return number function Unit:GetAngle(Target) if not Target:Exists() then @@ -1201,7 +1204,7 @@ function Unit:GetFacing() end -- Check if target is within a arc around the unit (angle, distance) accounting for a rotation of self ----@param Target Unit +---@param Target Bastion.Unit ---@param Angle number ---@param Distance number ---@param rotation? number diff --git a/src/UnitManager/UnitManager.lua b/src/UnitManager/UnitManager.lua index d0a27df..f928630 100644 --- a/src/UnitManager/UnitManager.lua +++ b/src/UnitManager/UnitManager.lua @@ -1,20 +1,18 @@ ---@type Tinkr, Bastion local Tinkr, Bastion = ... -local ObjectManager = Tinkr.Util.ObjectManager - local Unit = Bastion.Unit ----@class UnitManager.CustomUnit ----@field unit Cacheable | Unit ----@field cb fun(): Unit +---@class Bastion.UnitManager.CustomUnit +---@field unit Bastion.Cacheable | Bastion.Unit +---@field cb fun(): Bastion.Unit -- Create a new UnitManager class ----@class UnitManager : { [UnitId]: Unit } ----@field units table ----@field customUnits table ----@field objects table ----@field cache Cache +---@class Bastion.UnitManager +---@field units table +---@field customUnits table +---@field objects table +---@field cache Bastion.Cache local UnitManager = { units = {}, customUnits = {}, @@ -27,7 +25,6 @@ function UnitManager:__index(k) if k == "none" then return self:Get("none") end - if UnitManager[k] then return UnitManager[k] end @@ -66,9 +63,9 @@ function UnitManager:__index(k) end -- Constructor ----@return UnitManager +---@return Bastion.UnitManager function UnitManager:New() - ---@class UnitManager + ---@class Bastion.UnitManager local self = setmetatable({}, UnitManager) self.units = {} self.customUnits = {} @@ -78,7 +75,7 @@ end -- Get or create a unit ---@param token UnitId ----@return Unit +---@return Bastion.Unit function UnitManager:Get(token) -- if not Validate(token) then -- error("UnitManager:Get - Invalid token: " .. token) @@ -90,6 +87,7 @@ function UnitManager:Get(token) if token == "none" then self.objects["none"] = Unit:New() else + ---@diagnostic disable-next-line: param-type-mismatch self.objects[tguid] = Unit:New(Object(tguid)) end end @@ -101,6 +99,7 @@ function UnitManager:Get(token) if token == "none" then self.objects["none"] = Unit:New() else + ---@diagnostic disable-next-line: param-type-mismatch self.objects[tguid] = Unit:New(Object(tguid)) end end @@ -110,21 +109,21 @@ end -- Get a unit by guid ---@param guid string | WowGameObject ----@return Unit +---@return Bastion.Unit function UnitManager:GetObject(guid) return self.objects[guid] end -- Set a unit by guid ----@param unit Unit +---@param unit Bastion.Unit function UnitManager:SetObject(unit) self.objects[unit:GetGUID()] = unit end -- Create a custom unit and cache it for .5 seconds ----@generic V :Unit +---@generic V :Bastion.Unit ---@param token string ----@param cb fun(): Unit +---@param cb fun(): Bastion.Unit function UnitManager:CreateCustomUnit(token, cb) local unit = cb() local cachedUnit = Bastion.Cacheable:New(unit, cb) @@ -143,7 +142,7 @@ function UnitManager:CreateCustomUnit(token, cb) end ---@description Enumerates all friendly units in the battlefield ----@param cb fun(unit: Unit):boolean +---@param cb fun(unit: Bastion.Unit):boolean ---@return nil function UnitManager:EnumFriends(cb) Bastion.ObjectManager.friends:each(function(unit) @@ -155,7 +154,7 @@ function UnitManager:EnumFriends(cb) end -- Enum Enemies (object manager) ----@param cb fun(unit: Unit):boolean +---@param cb fun(unit: Bastion.Unit):boolean ---@return nil function UnitManager:EnumEnemies(cb) Bastion.ObjectManager.activeEnemies:each(function(unit) @@ -167,7 +166,7 @@ function UnitManager:EnumEnemies(cb) end -- Enum Units (object manager) ----@param cb fun(unit: Unit):boolean +---@param cb fun(unit: Bastion.Unit):boolean ---@return nil function UnitManager:EnumUnits(cb) Bastion.ObjectManager.enemies:each(function(unit) @@ -179,7 +178,7 @@ function UnitManager:EnumUnits(cb) end -- Enum Incorporeal (object manager) ----@param cb fun(unit: Unit):boolean +---@param cb fun(unit: Bastion.Unit):boolean ---@return nil function UnitManager:EnumIncorporeal(cb) Bastion.ObjectManager.incorporeal:each(function(unit) @@ -191,7 +190,7 @@ function UnitManager:EnumIncorporeal(cb) end -- Get the number of enemies with a debuff ----@param spell Spell +---@param spell Bastion.Spell ---@param range? number ---@return number function UnitManager:GetNumEnemiesWithDebuff(spell, range) @@ -209,7 +208,7 @@ function UnitManager:GetNumEnemiesWithDebuff(spell, range) end -- Get the number of friends with a buff (party/raid members) ----@param spell Spell +---@param spell Bastion.Spell ---@return number function UnitManager:GetNumFriendsWithBuff(spell) local count = 0 @@ -237,8 +236,8 @@ end -- Get the friend with the most friends within a given radius (party/raid members) ---@param radius number ----@return Unit | nil ----@return Unit[] +---@return Bastion.Unit | nil +---@return Bastion.Unit[] function UnitManager:GetFriendWithMostFriends(radius) local unit = nil local count = 0 @@ -270,7 +269,7 @@ function UnitManager:GetFriendWithMostFriends(radius) end -- Get the enemy with the most enemies within a given radius ----@return Unit|nil, Unit[] +---@return Bastion.Unit|nil, Bastion.Unit[] function UnitManager:GetEnemiesWithMostEnemies(radius) local unit = nil local count = 0 @@ -304,7 +303,7 @@ 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 +---@return Bastion.Vector3 | nil function UnitManager:FindFriendsCentroid(radius, range) local unit, friends = self:GetFriendWithMostFriends(radius) if unit == nil then @@ -335,7 +334,7 @@ end -- Find the centroid of the most dense area of enemies of a given radius within a given range ---@param radius number ---@param range number ----@return Vector3 | nil +---@return Bastion.Vector3 | nil function UnitManager:FindEnemiesCentroid(radius, range) local unit, enemies = self:GetEnemiesWithMostEnemies(radius) if unit == nil then diff --git a/src/Vector3/Vector3.lua b/src/Vector3/Vector3.lua index f9596c7..ca9663e 100644 --- a/src/Vector3/Vector3.lua +++ b/src/Vector3/Vector3.lua @@ -1,11 +1,32 @@ -- Create a Vector3 class ----@class Vector3 ----@operator add(Vector3): Vector3 ----@operator sub(Vector3|number): Vector3 ----@operator mul(number): Vector3 ----@operator div(number): Vector3 ----@operator unm(): Vector3 +---@class Bastion.Vector3 +---@field length number +---@field normalized Bastion.Vector3 +---@field magnitude number +---@field sqrMagnitude number +---@field zero Bastion.Vector3 +---@field one Bastion.Vector3 +---@field up Bastion.Vector3 +---@field down Bastion.Vector3 +---@field left Bastion.Vector3 +---@field right Bastion.Vector3 +---@field forward Bastion.Vector3 +---@field back Bastion.Vector3 +---@field positiveInfinity Bastion.Vector3 +---@field negativeInfinity Bastion.Vector3 +---@field nan Bastion.Vector3 +---@field epsilon number +---@field maxValue number +---@field minValue number +---@field x number +---@field y number +---@field z number +---@operator add(Bastion.Vector3): Bastion.Vector3 +---@operator sub(Bastion.Vector3|number): Bastion.Vector3 +---@operator mul(number): Bastion.Vector3 +---@operator div(number): Bastion.Vector3 +---@operator unm(): Bastion.Vector3 ---@operator len(): number local Vector3 = {} Vector3.__index = Vector3 @@ -15,14 +36,14 @@ function Vector3:__tostring() return "Vector3(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")" end ----@param other Vector3 ----@return Vector3 +---@param other Bastion.Vector3 +---@return Bastion.Vector3 function Vector3:__add(other) return Vector3:New(self.x + other.x, self.y + other.y, self.z + other.z) end ----@param other Vector3 | number ----@return Vector3 +---@param other Bastion.Vector3 | number +---@return Bastion.Vector3 function Vector3:__sub(other) if type(other) == "number" then return Vector3:New(self.x - other, self.y - other, self.z - other) @@ -31,36 +52,36 @@ function Vector3:__sub(other) end ---@param other number ----@return Vector3 +---@return Bastion.Vector3 function Vector3:__mul(other) return Vector3:New(self.x * other, self.y * other, self.z * other) end ---@param other number ----@return Vector3 +---@return Bastion.Vector3 function Vector3:__div(other) return Vector3:New(self.x / other, self.y / other, self.z / other) end ----@param other Vector3 +---@param other Bastion.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 +---@param other Bastion.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 +---@param other Bastion.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 +---@return Bastion.Vector3 function Vector3:__unm() return Vector3:New(-self.x, -self.y, -self.z) end @@ -70,134 +91,114 @@ function Vector3:__len() return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) end +---@param k string function Vector3:__index(k) if Vector3[k] then return Vector3[k] end - ---@class Vector3 - ---@field length number + if k == "length" then return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) end - ---@class Vector3 - ---@field normalized Vector3 + if k == "normalized" then local length = math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) return Vector3:New(self.x / length, self.y / length, self.z / length) end - ---@class Vector3 - ---@field magnitude number + if k == "magnitude" then return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) end - ---@class Vector3 - ---@field sqrMagnitude number + if k == "sqrMagnitude" then return self.x * self.x + self.y * self.y + self.z * self.z end - ---@class Vector3 - ---@field zero Vector3 + if k == "zero" then return Vector3:New(0, 0, 0) end - ---@class Vector3 - ---@field one Vector3 + if k == "one" then return Vector3:New(1, 1, 1) end - ---@class Vector3 - ---@field up Vector3 + if k == "up" then return Vector3:New(0, 1, 0) end - ---@class Vector3 - ---@field down Vector3 + if k == "down" then return Vector3:New(0, -1, 0) end - ---@class Vector3 - ---@field left Vector3 + if k == "left" then return Vector3:New(-1, 0, 0) end - ---@class Vector3 - ---@field right Vector3 + if k == "right" then return Vector3:New(1, 0, 0) end - ---@class Vector3 - ---@field forward Vector3 + if k == "forward" then return Vector3:New(0, 0, 1) end - ---@class Vector3 - ---@field back Vector3 + if k == "back" then return Vector3:New(0, 0, -1) end - ---@class Vector3 - ---@field positiveInfinity Vector3 + if k == "positiveInfinity" then return Vector3:New(math.huge, math.huge, math.huge) end - ---@class Vector3 - ---@field negativeInfinity Vector3 + if k == "negativeInfinity" then return Vector3:New(-math.huge, -math.huge, -math.huge) end - ---@class Vector3 - ---@field nan Vector3 + if k == "nan" then return Vector3:New(0 / 0, 0 / 0, 0 / 0) end - ---@class Vector3 - ---@field epsilon number + if k == "epsilon" then return 1.401298E-45 end - ---@class Vector3 - ---@field maxValue number + if k == "maxValue" then return 3.402823E+38 end - ---@class Vector3 - ---@field minValue number + if k == "minValue" then return -3.402823E+38 end - ---@class Vector3 - ---@field x number + if k == "x" then return self[1] end - ---@class Vector3 - ---@field y number + if k == "y" then return self[2] end - ---@class Vector3 - ---@field z number + if k == "z" then return self[3] end @@ -220,7 +221,7 @@ end ---@param x number ---@param y number ---@param z number ----@return Vector3 +---@return Bastion.Vector3 function Vector3:New(x, y, z) if x == false then return Vector3:New(0, 0, 0) @@ -230,37 +231,38 @@ function Vector3:New(x, y, z) return self end ----@param rhs Vector3 +---@param rhs Bastion.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 +---@param rhs Bastion.Vector3 +---@return Bastion.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 +---@param b Bastion.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 +---@param to Bastion.Vector3 function Vector3:GetAbsoluteAngle(to) return self:NormalizeOrientation(math.atan2(to.y - self.y, to.x - self.x)) end ----@param to Vector3 +---@param to Bastion.Vector3 ---@return number function Vector3:Angle(to) - return math.acos(self:Dot(to) / (math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) * math.sqrt(to.x * to.x + to.y * to.y + to.z * to.z))) + return math.acos(self:Dot(to) / + (math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) * math.sqrt(to.x * to.x + to.y * to.y + to.z * to.z))) end ---@param maxLength number ----@return Vector3 +---@return Bastion.Vector3 function Vector3:ClampMagnitude(maxLength) if self:Dot(self) > maxLength * maxLength then return self.normalized * maxLength @@ -269,7 +271,7 @@ function Vector3:ClampMagnitude(maxLength) return self end ----@return Vector3 +---@return Bastion.Vector3 function Vector3:directionOrZero() local mag = self.magnitude if mag < 0.0000001 then @@ -290,17 +292,17 @@ local function clamp(x, min, max) return x < min and min or (x > max and max or x) end ----@param b Vector3 +---@param b Bastion.Vector3 ---@param t number ----@return Vector3 +---@return Bastion.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 target Bastion.Vector3 ---@param maxDistanceDelta number ----@return Vector3 +---@return Bastion.Vector3 function Vector3:MoveTowards(target, maxDistanceDelta) local toVector = target - self local distance = toVector.magnitude @@ -311,14 +313,14 @@ function Vector3:MoveTowards(target, maxDistanceDelta) return self + toVector / distance * maxDistanceDelta end ----@param b Vector3 ----@return Vector3 +---@param b Bastion.Vector3 +---@return Bastion.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 +---@param onNormal Bastion.Vector3 +---@return Bastion.Vector3 function Vector3:Project(onNormal) local num = onNormal:Dot(onNormal) if num < 1.401298E-45 then @@ -328,19 +330,19 @@ function Vector3:Project(onNormal) return onNormal * self:Dot(onNormal) / num end ----@param planeNormal Vector3 ----@return Vector3 +---@param planeNormal Bastion.Vector3 +---@return Bastion.Vector3 function Vector3:ProjectOnPlane(planeNormal) return self - self:Project(planeNormal) end ----@param inNormal Vector3 ----@return Vector3 +---@param inNormal Bastion.Vector3 +---@return Bastion.Vector3 function Vector3:Reflect(inNormal) return -2 * inNormal:Dot(self) * inNormal + self end ----@return Vector3 +---@return Bastion.Vector3 function Vector3:Normalize() local num = self:Dot(self) if num > 1E-05 then diff --git a/src/_bastion.lua b/src/_bastion.lua index 5622ca4..6b38661 100644 --- a/src/_bastion.lua +++ b/src/_bastion.lua @@ -13,23 +13,94 @@ local ThirdPartyModulesBase = string.format("%s/%s", TinkrScriptsBase, "BastionS Bastion.__index = Bastion ----@param file string ----@param ... any ----@return any ... -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(string.format("%s%s", BastionScriptsBase, file), Bastion, ...) - elseif file:sub(1, 1) == "~" then - file = file:sub(2) - -- print("2") - return require(string.format("%s%s", BastionBase, file), Bastion, ...) +---@class Bastion.LoadedFiles.Table +---@field [number] { originalPath: string, loadedPath: string, reloadable: boolean, order: number, newPath: string } +Bastion.LoadedFiles = {} + +---@param filePath string +function Bastion:CheckIfLoaded(filePath) + for i, file in ipairs(Bastion.LoadedFiles) do + if file.loadedPath == filePath or file.originalPath == filePath or file.newPath == filePath then + return true + end + end + return false +end + +---@param path string +---@param extension string +---@return string +local function AppendExtension(path, extension) + return string.format("%s.%s", path, extension) +end + +---@param path string +---@param extensions string|string[] +local function CheckFileExtensions(path, extensions) + local exts = {} + if type(extensions) == "string" then + exts = { extensions } else - -- print("Normal req") - return require(file, Bastion, ...) + exts = extensions end + + for i, extension in ipairs(exts) do + local newPath = path + if newPath:sub(extension:len() * -1) ~= extension then + newPath = AppendExtension(newPath, extension) + end + if FileExists(newPath) then + return newPath:sub(1, (extension:len() + 2) * -1), true + end + end + return path, false +end + +--- 0 = Failed, 1 = Success, 2 = Already Loaded +---@param filePath string | { filePath: string, reloadable: boolean } +---@param ... any +---@return 0|1|2, ... +function Bastion:Require(filePath, ...) + local loadedFile = { + originalPath = type(filePath) == "table" and filePath.filePath or tostring(filePath), + newPath = type(filePath) == "table" and filePath.filePath or tostring(filePath), + loadedPath = type(filePath) == "table" and filePath.filePath or tostring(filePath), + reloadable = type(filePath) == "table" and filePath.reloadable or false, + order = #Bastion.LoadedFiles + 1, + } + + local filePathModifier = loadedFile.originalPath:sub(1, 1) + + if filePathModifier == "@" then + -- If require starts with an @ then we require from the scripts/bastion/scripts folder + loadedFile.newPath = string.format("%s%s", BastionScriptsBase, loadedFile.originalPath:sub(2)) + loadedFile.loadedPath = loadedFile.newPath + elseif filePathModifier == "~" then + -- If file path starts with a ~ then we require from the scripts/bastion folder + loadedFile.newPath = string.format("%s%s", BastionBase, loadedFile.originalPath:sub(2)) + loadedFile.loadedPath = loadedFile.newPath + end + + loadedFile.loadedPath = loadedFile.newPath + + local found = false + -- Check if file path has a .lua or .luac extension. If not, try to add one and check if the file exists + loadedFile.loadedPath, found = CheckFileExtensions(loadedFile.newPath, { "lua", "luac" }) + + if not found then + Log(string.format("Bastion:Require - Not Found: %s (%s)", loadedFile.newPath, loadedFile.originalPath)) + return 0, SafePack(nil) + end + + if not loadedFile.reloadable then + if Bastion:CheckIfLoaded(loadedFile.loadedPath) then + --Log(string.format("Bastion:Require - Already loaded: %s (%s)", loadedFile.newPath, loadedFile.originalPath)) + return 2, SafePack(nil) + end + end + + table.insert(Bastion.LoadedFiles, loadedFile) + return 1, SafePack(require(loadedFile.loadedPath, Bastion, ...)) end local loadExamples = false @@ -82,50 +153,57 @@ local function LoadThird() end end ----@generic V +---@generic V : string ---@param class `V` ---@return V ... function Bastion.require(class) + ---@cast class string + local newClass = class:gsub("Bastion%.", "") -- return require("scripts/bastion/src/" .. class .. "/" .. class, Bastion) - return Bastion:Require("~/src/" .. class .. "/" .. class) + local success, result = Bastion:Require("~/src/" .. newClass .. "/" .. newClass) + if success == 0 then + Log("Bastion.require - Failed to load " .. class .. ": " .. result) + end + return SafeUnpack(result) end Bastion.Globals = {} -Bastion.ClassMagic = Bastion.require("ClassMagic") -Bastion.List = Bastion.require("List") -Bastion.Library = Bastion.require("Library") ----@type NotificationsList, Notification -Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList") -Bastion.Vector3 = Bastion.require("Vector3") -Bastion.Sequencer = Bastion.require("Sequencer") -Bastion.Command = Bastion.require("Command") -Bastion.Cache = Bastion.require("Cache") -Bastion.Cacheable = Bastion.require("Cacheable") -Bastion.Refreshable = Bastion.require("Refreshable") -Bastion.Unit = Bastion.require("Unit") -Bastion.Aura = Bastion.require("Aura") ----@type APL, APLActor, APLTrait -Bastion.APL, Bastion.APLActor, Bastion.APLTrait = Bastion.require("APL") -Bastion.Module = Bastion.require("Module") -Bastion.UnitManager = Bastion.require("UnitManager"):New() -Bastion.ObjectManager = Bastion.require("ObjectManager"):New() -Bastion.EventManager = Bastion.require("EventManager") +Bastion.ClassMagic = Bastion.require("Bastion.ClassMagic") +Bastion.List = Bastion.require("Bastion.List") +Bastion.Library = Bastion.require("Bastion.Library") +Bastion.Notification = Bastion.require("Bastion.Notification") +Bastion.NotificationList = Bastion.require("Bastion.NotificationList") +Bastion.Vector3 = Bastion.require("Bastion.Vector3") +Bastion.Sequencer = Bastion.require("Bastion.Sequencer") +Bastion.Command = Bastion.require("Bastion.Command") +Bastion.Cache = Bastion.require("Bastion.Cache") +Bastion.Cacheable = Bastion.require("Bastion.Cacheable") +Bastion.Refreshable = Bastion.require("Bastion.Refreshable") +Bastion.Unit = Bastion.require("Bastion.Unit") +Bastion.Aura = Bastion.require("Bastion.Aura") +Bastion.APLTrait = Bastion.require("Bastion.APLTrait") +Bastion.APLActor = Bastion.require("Bastion.APLActor") +Bastion.APL = Bastion.require("Bastion.APL") +Bastion.Module = Bastion.require("Bastion.Module") +Bastion.UnitManager = Bastion.require("Bastion.UnitManager"):New() +Bastion.ObjectManager = Bastion.require("Bastion.ObjectManager"):New() +Bastion.EventManager = Bastion.require("Bastion.EventManager") Bastion.Globals.EventManager = Bastion.EventManager:New() -Bastion.Spell = Bastion.require("Spell") -Bastion.SpellBook = Bastion.require("SpellBook") +Bastion.Spell = Bastion.require("Bastion.Spell") +Bastion.SpellBook = Bastion.require("Bastion.SpellBook") Bastion.Globals.SpellBook = Bastion.SpellBook:New() -Bastion.Item = Bastion.require("Item") -Bastion.ItemBook = Bastion.require("ItemBook") +Bastion.Item = Bastion.require("Bastion.Item") +Bastion.ItemBook = Bastion.require("Bastion.ItemBook") Bastion.Globals.ItemBook = Bastion.ItemBook:New() -Bastion.AuraTable = Bastion.require("AuraTable") -Bastion.Class = Bastion.require("Class") -Bastion.Timer = Bastion.require("Timer") +Bastion.AuraTable = Bastion.require("Bastion.AuraTable") +Bastion.Class = Bastion.require("Bastion.Class") +Bastion.Timer = Bastion.require("Bastion.Timer") Bastion.CombatTimer = Bastion.Timer:New("combat") -Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New() -Bastion.Notifications = Bastion.NotificationsList:New() -Bastion.Config = Bastion.require("Config") -Bastion.TimeToDie = Bastion.require("TimeToDie") +Bastion.MythicPlusUtils = Bastion.require("Bastion.MythicPlusUtils"):New() +Bastion.Notifications = Bastion.NotificationList:New() +Bastion.Config = Bastion.require("Bastion.Config") +Bastion.TimeToDie = Bastion.require("Bastion.TimeToDie") ---@enum (key) CompareThisTable @@ -150,14 +228,14 @@ Bastion.Utils = { } local LIBRARIES = {} ----@type Module[] +---@type Bastion.Module[] local MODULES = {} Bastion.Enabled = false Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_AURA", function(unit, auras) - ---@type Unit | nil - local u = Bastion.UnitManager[unit] + ---@type Bastion.Unit | nil + local u = Bastion.UnitManager:Get(unit) if u then u:GetAuras():OnUpdate(auras) @@ -211,6 +289,8 @@ Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", fun -- Log(tostring(args[i])) -- end -- end + --Bastion.UnitManager:SetCombatTime(sourceGUID) + --Bastion.UnitManager:SetCombatTime(destGUID) local u = Bastion.UnitManager[sourceGUID] local u2 = Bastion.UnitManager[destGUID] @@ -223,7 +303,6 @@ Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", fun if u2 then u2:SetLastCombatTime(t) - if subEvent == "SPELL_MISSED" and sourceGUID == pguid and spellID == 408 then local missType = args[15] @@ -385,7 +464,7 @@ Command:Register("missed", "Dump the list of immune kidney shot spells", functio end end) ----@param library Library +---@param library Bastion.Library function Bastion:RegisterLibrary(library) LIBRARIES[library.name] = library end