From 83086a9b57b7b4282ec1696c428ab0dbcb6dcf80 Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.anon> Date: Tue, 30 Jul 2024 15:04:36 +0000 Subject: [PATCH 1/6] 11.0 11.0 --- src/Aura/Aura.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Aura/Aura.lua b/src/Aura/Aura.lua index 056d488..ab0f8f5 100644 --- a/src/Aura/Aura.lua +++ b/src/Aura/Aura.lua @@ -75,6 +75,11 @@ function Aura:New(unit, index, type) return self end + if C_UnitAuras.GetAuraDataByIndex then + local unitAuraInfo = C_UnitAuras.GetAuraDataByIndex(unit:GetOMToken(), index, type) + return Aura:CreateFromUnitAuraInfo(unitAuraInfo) + end + local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index, type) From 744249832639ec6acd0c48877cc37b702256209e Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.anon> Date: Tue, 30 Jul 2024 15:05:13 +0000 Subject: [PATCH 2/6] 11.0 11.0 --- src/Item/Item.lua | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Item/Item.lua b/src/Item/Item.lua index 5a68e98..a20fa48 100644 --- a/src/Item/Item.lua +++ b/src/Item/Item.lua @@ -51,7 +51,13 @@ function Item:New(id) self.ItemID = id -- Register spell in spellbook - local name, spellID = GetItemSpell(self:GetID()) + local name, spellID + + if C_Item.GetItemSpell then + name, spellID = C_Item.GetItemSpell(self:GetID()) + else + name, spellID = GetItemSpell(self:GetID()) + end if spellID then self.spellID = spellID Bastion.Globals.SpellBook:GetSpell(spellID) @@ -69,18 +75,27 @@ end -- Get the Items name ---@return string function Item:GetName() + if C_Item.GetItemInfo then + return C_Item.GetItemName(self:GetID()) + end return GetItemInfo(self:GetID()) end -- Get the Items icon ---@return number function Item:GetIcon() + if C_Item.GetItemIconByID then + return C_Item.GetItemIconByID(self:GetID()) + end return select(3, GetItemInfo(self:GetID())) end -- Get the Items cooldown ---@return number function Item:GetCooldown() + if C_Item.GetItemCooldown then + return select(2, C_Item.GetItemCooldown(self:GetID())) + end return select(2, C_Container.GetItemCooldown(self:GetID())) end @@ -105,6 +120,10 @@ end -- Get the Items cooldown remaining ---@return number function Item:GetCooldownRemaining() + if C_Item.GetItemCooldown then + local start, duration = C_Item.GetItemCooldown(self:GetID()) + return start + duration - GetTime() + end local start, duration = C_Container.GetItemCooldown(self:GetID()) return start + duration - GetTime() end @@ -131,7 +150,11 @@ function Item:Use(unit, condition) self.wasLooking = IsMouselooking() -- Use the Item - UseItemByName(self:GetName(), unit:GetOMToken()) + if C_Item.UseItemByName then + C_Item.UseItemByName(self:GetName(), unit:GetOMToken()) + else + UseItemByName(self:GetName(), unit:GetOMToken()) + end Bastion:Debug("Using", self) @@ -161,18 +184,28 @@ end -- Check if the Item is known ---@return boolean function Item:IsEquipped() + if C_Item.IsEquippedItem then + return C_Item.IsEquippedItem(self:GetID()) + end return IsEquippedItem(self:GetID()) end -- Check if the Item is on cooldown ---@return boolean function Item:IsOnCooldown() + if C_Item.GetItemCooldown then + return select(2, C_Item.GetItemCooldown(self:GetID())) > 0 + end return select(2, C_Container.GetItemCooldown(self:GetID())) > 0 end -- Check if the Item is usable ---@return boolean function Item:IsUsable() + if C_Item.IsUsableItem then + local usable, noMana = C_Item.IsUsableItem(self:GetID()) + return usable or usableExcludes[self:GetID()] + end local usable, noMana = IsUsableItem(self:GetID()) return usable or usableExcludes[self:GetID()] end @@ -187,6 +220,9 @@ end -- Is equippable ---@return boolean function Item:IsEquippable() + if C_Item.IsEquippableItem then + return C_Item.IsEquippableItem(self:GetID()) + end return IsEquippableItem(self:GetID()) end @@ -317,6 +353,9 @@ end -- Get the Items charges ---@return number function Item:GetCharges() + if C_Item.GetItemCount then + return C_Item.GetItemCount(self:GetID()) + end return GetItemCharges(self:GetID()) end From 010d2b411145c7cdf6b1a2e1ea447ed4f1bf3e53 Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.anon> Date: Tue, 30 Jul 2024 15:07:14 +0000 Subject: [PATCH 3/6] 11.0 11.0 --- src/MythicPlusUtils/MythicPlusUtils.lua | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/MythicPlusUtils/MythicPlusUtils.lua b/src/MythicPlusUtils/MythicPlusUtils.lua index f3222b5..13c5cb9 100644 --- a/src/MythicPlusUtils/MythicPlusUtils.lua +++ b/src/MythicPlusUtils/MythicPlusUtils.lua @@ -462,7 +462,14 @@ function MythicPlusUtils:New() return end - local name = GetSpellInfo(spellID) + local name + + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(spellID) + name = info and info.name or '' + else + name = GetSpellInfo(spellID) + end self.loggedCasts[spellID] = true @@ -481,7 +488,14 @@ function MythicPlusUtils:New() return end - local name = GetSpellInfo(spellID) + local name + + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(spellID) + name = info and info.name or '' + else + name = GetSpellInfo(spellID) + end self.loggedCasts[spellID] = true From d0cad5746d16688245003dea9c5945423a75c700 Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.anon> Date: Tue, 30 Jul 2024 15:20:42 +0000 Subject: [PATCH 4/6] 11.0 11.0 --- src/Spell/Spell.lua | 92 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Spell/Spell.lua b/src/Spell/Spell.lua index 824cb60..0aad894 100644 --- a/src/Spell/Spell.lua +++ b/src/Spell/Spell.lua @@ -80,24 +80,53 @@ end -- Get the spells name ---@return string function Spell:GetName() + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(self:GetID()) + return info and info.name or nil + end return GetSpellInfo(self:GetID()) end -- Get the spells icon ---@return number function Spell:GetIcon() + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(self:GetID()) + return info and info.iconID or nil + end return select(3, GetSpellInfo(self:GetID())) end -- Get the spells cooldown ---@return number function Spell:GetCooldown() + if C_Spell.GetSpellCooldown then + local info = C_Spell.GetSpellCooldown(self:GetID()) + return info and info.duration or nil + end return select(2, GetSpellCooldown(self:GetID())) end -- Get the full cooldown (time until all charges are available) ---@return number function Spell:GetFullRechargeTime() + if C_Spell.GetSpellCooldown then + local info = C_Spell.GetSpellCooldown(self:GetID()) + if info.isEnabled == 0 then + return 0 + end + + local chargeInfo = C_Spell.GetSpellCharges(self:GetID()) + if chargeInfo.currentCharges == chargeInfo.maxCharges then + return 0 + end + + if chargeInfo.currentCharges == 0 then + return info.startTime + info.duration - GetTime() + end + + return chargeInfo.cooldownStartTime + chargeInfo.cooldownDuration - GetTime() + end local start, duration, enabled = GetSpellCooldown(self:GetID()) if enabled == 0 then return 0 @@ -136,6 +165,10 @@ end -- Get the spells cooldown remaining ---@return number function Spell:GetCooldownRemaining() + if C_Spell.GetSpellCooldown then + local info = C_Spell.GetSpellCooldown(self:GetID()) + return info and info.startTime + info.duration - GetTime() or nil + end local start, duration = GetSpellCooldown(self:GetID()) return start + duration - GetTime() end @@ -143,6 +176,9 @@ end -- Get the spell count ---@return number function Spell:GetCount() + if C_Spell.GetSpellCastCount then + return C_Spell.GetSpellCastCount(self:GetID()) + end return GetSpellCount(self:GetID()) end @@ -252,6 +288,8 @@ end -- Check if the spell is known ---@return boolean function Spell:IsKnown() + local IsSpellKnown = C_Spell.IsSpellKnown and C_Spell.IsSpellKnown or IsSpellKnown + local IsPlayerSpell = C_Spell.IsPlayerSpell and C_Spell.IsPlayerSpell or IsPlayerSpell local isKnown = IsSpellKnown(self:GetID()) local isPlayerSpell = IsPlayerSpell(self:GetID()) return isKnown or isPlayerSpell @@ -260,12 +298,20 @@ end -- Check if the spell is on cooldown ---@return boolean function Spell:IsOnCooldown() + if C_Spell.GetSpellCooldown then + local info = C_Spell.GetSpellCooldown(self:GetID()) + return info and info.duration > 0 + end return select(2, GetSpellCooldown(self:GetID())) > 0 end -- Check if the spell is usable ---@return boolean function Spell:IsUsable() + if C_Spell.IsSpellUsable then + local usable, noMana = C_Spell.IsSpellUsable(self:GetID()) + return usable or usableExcludes[self:GetID()] and not noMana + end local usable, noMana = IsUsableSpell(self:GetID()) return usable or usableExcludes[self:GetID()] and not noMana end @@ -350,6 +396,9 @@ end -- Check if the spell is castable and cast it ---@return boolean function Spell:HasRange() + if C_Spell.SpellHasRange then + return C_Spell.SpellHasRange(self:GetID()) + end return SpellHasRange(self:GetName()) end @@ -357,6 +406,10 @@ end ---@return number ---@return number function Spell:GetRange() + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(self:GetID()) + return info and info.minRange or nil, info and info.maxRange or nil + end local name, rank, icon, castTime, minRange, maxRange, spellID, originalIcon = GetSpellInfo(self:GetID()) return maxRange, minRange end @@ -365,6 +418,7 @@ end ---@param unit Unit ---@return boolean function Spell:IsInRange(unit) + local IsSpellInRange = C_Spell.IsSpellInRange and C_Spell.IsSpellInRange or IsSpellInRange local hasRange = self:HasRange() local inRange = IsSpellInRange(self:GetName(), unit:GetOMToken()) @@ -406,20 +460,50 @@ end -- Get the spells charges ---@return number function Spell:GetCharges() + if C_Spell.GetSpellCharges then + local info = C_Spell.GetSpellCharges(self:GetID()) + return info and info.currentCharges or nil + end return GetSpellCharges(self:GetID()) end function Spell:GetMaxCharges() + if C_Spell.GetSpellCharges then + local info = C_Spell.GetSpellCharges(self:GetID()) + return info and info.maxCharges or nil + end return select(2, GetSpellCharges(self:GetID())) end function Spell:GetCastLength() + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(self:GetID()) + return info and info.castTime or nil + end return select(4, GetSpellInfo(self:GetID())) end -- Get the spells charges ---@return number function Spell:GetChargesFractional() + if C_Spell.GetSpellCharges then + local info = C_Spell.GetSpellCharges(self:GetID()) + + if info.currentCharges == info.maxCharges then + return info.maxCharges + end + + if info.currentCharges == 0 then + return 0 + end + + local timeSinceStart = GetTime() - info.cooldownStartTime + local timeLeft = info.cooldownDuration - timeSinceStart + local timePerCharge = info.cooldownDuration / info.maxCharges + local chargesFractional = info.currentCharges + (timeLeft / timePerCharge) + + return chargesFractional + end local charges, maxCharges, start, duration = GetSpellCharges(self:GetID()) if charges == maxCharges then @@ -441,6 +525,10 @@ end -- Get the spells charges remaining ---@return number function Spell:GetChargesRemaining() + if C_Spell.GetSpellCharges then + local info = C_Spell.GetSpellCharges(self:GetID()) + return info and info.currentCharges or nil + end local charges, maxCharges, start, duration = GetSpellCharges(self:GetID()) return charges end @@ -546,6 +634,10 @@ end -- GetCost ---@return number function Spell:GetCost() + if C_Spell.GetSpellPowerCost then + local info = C_Spell.GetSpellPowerCost(self:GetID()) + return info and info.cost or 0 + end local cost = GetSpellPowerCost(self:GetID()) return cost and cost.cost or 0 end From f9583a85d8997a77f8bf33680340bc922a3b2ccb Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.anon> Date: Tue, 30 Jul 2024 15:21:33 +0000 Subject: [PATCH 5/6] 11.0 11.0 --- src/SpellBook/SpellBook.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SpellBook/SpellBook.lua b/src/SpellBook/SpellBook.lua index 52119b8..243a4bd 100644 --- a/src/SpellBook/SpellBook.lua +++ b/src/SpellBook/SpellBook.lua @@ -48,6 +48,10 @@ end ---@param name string ---@return Spell function SpellBook:GetSpellByName(name) + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(name) + return self:GetSpell(info.spellID) + end local _, rank, icon, castTime, minRange, maxRange, spellID, originalIcon = GetSpellInfo(name) return self:GetSpell(spellID) end From 86e7aeccec14bfa3f530c892d8c9be4a9279f7cc Mon Sep 17 00:00:00 2001 From: 4n0n <4n0n@tinkr.anon> Date: Tue, 30 Jul 2024 15:25:42 +0000 Subject: [PATCH 6/6] 11.0 11.0 --- src/_bastion.lua | 589 ++++++++++++++++++++++++----------------------- 1 file changed, 302 insertions(+), 287 deletions(-) diff --git a/src/_bastion.lua b/src/_bastion.lua index 380a865..6d92449 100644 --- a/src/_bastion.lua +++ b/src/_bastion.lua @@ -1,9 +1,9 @@ local Tinkr = ... +local Evaulator = Tinkr.Evaluator + ---@class Bastion -local Bastion = { - DebugMode = false -} +local Bastion = {DebugMode = false} Bastion.__index = Bastion function Bastion:Require(file) @@ -50,348 +50,363 @@ function Bastion.require(class) return Bastion:Require("~/src/" .. class .. "/" .. class) end -Bastion.Globals = {} - ----@type ClassMagic -Bastion.ClassMagic = Bastion.require("ClassMagic") ----@type List -Bastion.List = Bastion.require("List") ----@type Library -Bastion.Library = Bastion.require("Library") ----@type NotificationsList, Notification -Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList") ----@type Vector3 -Bastion.Vector3 = Bastion.require("Vector3") ----@type Sequencer -Bastion.Sequencer = Bastion.require("Sequencer") ----@type Command -Bastion.Command = Bastion.require("Command") ----@type Cache -Bastion.Cache = Bastion.require("Cache") ----@type Cacheable -Bastion.Cacheable = Bastion.require("Cacheable") ----@type Refreshable -Bastion.Refreshable = Bastion.require("Refreshable") ----@type Unit -Bastion.Unit = Bastion.require("Unit") ----@type Aura -Bastion.Aura = Bastion.require("Aura") ----@type APL, APLActor, APLTrait -Bastion.APL, Bastion.APLActor, Bastion.APLTrait = Bastion.require("APL") ----@type Module -Bastion.Module = Bastion.require("Module") ----@type UnitManager -Bastion.UnitManager = Bastion.require("UnitManager"):New() ----@type ObjectManager -Bastion.ObjectManager = Bastion.require("ObjectManager"):New() ----@type EventManager -Bastion.EventManager = Bastion.require("EventManager") -Bastion.Globals.EventManager = Bastion.EventManager:New() ----@type Spell -Bastion.Spell = Bastion.require("Spell") ----@type SpellBook -Bastion.SpellBook = Bastion.require("SpellBook") -Bastion.Globals.SpellBook = Bastion.SpellBook:New() ----@type Item -Bastion.Item = Bastion.require("Item") ----@type ItemBook -Bastion.ItemBook = Bastion.require("ItemBook") -Bastion.Globals.ItemBook = Bastion.ItemBook:New() ----@type AuraTable -Bastion.AuraTable = Bastion.require("AuraTable") ----@type Class -Bastion.Class = Bastion.require("Class") ----@type Timer -Bastion.Timer = Bastion.require("Timer") ----@type Timer -Bastion.CombatTimer = Bastion.Timer:New('combat') ----@type MythicPlusUtils -Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New() ----@type NotificationsList -Bastion.Notifications = Bastion.NotificationsList:New() - -local LIBRARIES = {} -local MODULES = {} - -Bastion.Enabled = false - -Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras) - local u = Bastion.UnitManager[unit] - - if u then - u:GetAuras():OnUpdate(auras) - end -end) - -Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...) - local unit, castGUID, spellID = ... - - local spell = Bastion.Globals.SpellBook:GetIfRegistered(spellID) - - if unit == "player" and spell then - spell.lastCastAt = GetTime() - - if spell:GetPostCastFunction() then - spell:GetPostCastFunction()(spell) +-- fenv for all required files +function Bastion.Bootstrap() + + Bastion.Globals = {} + + ---@type ClassMagic + Bastion.ClassMagic = Bastion.require("ClassMagic") + ---@type List + Bastion.List = Bastion.require("List") + ---@type Library + Bastion.Library = Bastion.require("Library") + ---@type NotificationsList, Notification + Bastion.NotificationsList, Bastion.Notification = Bastion.require( + "NotificationsList") + ---@type Vector3 + Bastion.Vector3 = Bastion.require("Vector3") + ---@type Sequencer + Bastion.Sequencer = Bastion.require("Sequencer") + ---@type Command + Bastion.Command = Bastion.require("Command") + ---@type Cache + Bastion.Cache = Bastion.require("Cache") + ---@type Cacheable + Bastion.Cacheable = Bastion.require("Cacheable") + ---@type Refreshable + Bastion.Refreshable = Bastion.require("Refreshable") + ---@type Unit + Bastion.Unit = Bastion.require("Unit") + ---@type Aura + Bastion.Aura = Bastion.require("Aura") + ---@type APL, APLActor, APLTrait + Bastion.APL, Bastion.APLActor, Bastion.APLTrait = Bastion.require("APL") + ---@type Module + Bastion.Module = Bastion.require("Module") + ---@type UnitManager + Bastion.UnitManager = Bastion.require("UnitManager"):New() + ---@type ObjectManager + Bastion.ObjectManager = Bastion.require("ObjectManager"):New() + ---@type EventManager + Bastion.EventManager = Bastion.require("EventManager") + Bastion.Globals.EventManager = Bastion.EventManager:New() + ---@type Spell + Bastion.Spell = Bastion.require("Spell") + ---@type SpellBook + Bastion.SpellBook = Bastion.require("SpellBook") + Bastion.Globals.SpellBook = Bastion.SpellBook:New() + ---@type Item + Bastion.Item = Bastion.require("Item") + ---@type ItemBook + Bastion.ItemBook = Bastion.require("ItemBook") + Bastion.Globals.ItemBook = Bastion.ItemBook:New() + ---@type AuraTable + Bastion.AuraTable = Bastion.require("AuraTable") + ---@type Class + Bastion.Class = Bastion.require("Class") + ---@type Timer + Bastion.Timer = Bastion.require("Timer") + ---@type Timer + Bastion.CombatTimer = Bastion.Timer:New('combat') + ---@type MythicPlusUtils + Bastion.MythicPlusUtils = Bastion.require("MythicPlusUtils"):New() + ---@type NotificationsList + Bastion.Notifications = Bastion.NotificationsList:New() + + local LIBRARIES = {} + local MODULES = {} + + Bastion.Enabled = false + + Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', + function(unit, auras) + local u = Bastion.UnitManager[unit] + + if u then u:GetAuras():OnUpdate(auras) end + end) + + Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", + function(...) + local unit, castGUID, spellID = ... + + local spell = Bastion.Globals.SpellBook:GetIfRegistered(spellID) + + if unit == "player" and spell then + spell.lastCastAt = GetTime() + + if spell:GetPostCastFunction() then + spell:GetPostCastFunction()(spell) + end end - end -end) + end) -local pguid = UnitGUID("player") -local missed = {} + local pguid = UnitGUID("player") + local missed = {} -Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function() - local args = {CombatLogGetCurrentEventInfo()} + Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", + function() + local args = {CombatLogGetCurrentEventInfo()} - local subEvent = args[2] - local sourceGUID = args[4] - local destGUID = args[8] - local spellID = args[12] + local subEvent = args[2] + local sourceGUID = args[4] + local destGUID = args[8] + local spellID = args[12] - -- if sourceGUID == pguid then - -- local args = { CombatLogGetCurrentEventInfo() } + -- if sourceGUID == pguid then + -- local args = { CombatLogGetCurrentEventInfo() } - -- for i = 1, #args do - -- Log(tostring(args[i])) - -- end - -- end + -- for i = 1, #args do + -- Log(tostring(args[i])) + -- end + -- end - local u = Bastion.UnitManager[sourceGUID] - local u2 = Bastion.UnitManager[destGUID] + local u = Bastion.UnitManager[sourceGUID] + local u2 = Bastion.UnitManager[destGUID] - local t = GetTime() + local t = GetTime() - if u then - u:SetLastCombatTime(t) - end + if u then u:SetLastCombatTime(t) end - if u2 then - u2:SetLastCombatTime(t) + if u2 then + u2:SetLastCombatTime(t) - if subEvent == "SPELL_MISSED" and sourceGUID == pguid and spellID == 408 then - local missType = args[15] + if subEvent == "SPELL_MISSED" and sourceGUID == pguid and spellID == + 408 then + local missType = args[15] - if missType == "IMMUNE" then - local castingSpell = u:GetCastingOrChannelingSpell() + if missType == "IMMUNE" then + local castingSpell = u:GetCastingOrChannelingSpell() - if castingSpell then - if not missed[castingSpell:GetID()] then - missed[castingSpell:GetID()] = true + if castingSpell then + if not missed[castingSpell:GetID()] then + missed[castingSpell:GetID()] = true + end end end end end - end -end) + end) + + Bastion.Ticker = C_Timer.NewTicker(0.1, function() + if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then + Bastion.CombatTimer:Start() + elseif Bastion.CombatTimer:IsRunning() and + not UnitAffectingCombat("player") then + Bastion.CombatTimer:Reset() + end -Bastion.Ticker = C_Timer.NewTicker(0.1, function() - if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then - Bastion.CombatTimer:Start() - elseif Bastion.CombatTimer:IsRunning() and not UnitAffectingCombat("player") then - Bastion.CombatTimer:Reset() + if Bastion.Enabled then + Bastion.ObjectManager:Refresh() + for i = 1, #MODULES do MODULES[i]:Tick() end + end + end) + + function Bastion:Register(module) + table.insert(MODULES, module) + Bastion:Print("Registered", module) end - if Bastion.Enabled then - Bastion.ObjectManager:Refresh() + -- Find a module by name + function Bastion:FindModule(name) for i = 1, #MODULES do - MODULES[i]:Tick() + if MODULES[i].name == name then return MODULES[i] end end - end -end) - -function Bastion:Register(module) - table.insert(MODULES, module) - Bastion:Print("Registered", module) -end --- Find a module by name -function Bastion:FindModule(name) - for i = 1, #MODULES do - if MODULES[i].name == name then - return MODULES[i] - end + return nil end - return nil -end - -function Bastion:Print(...) - local args = {...} - local str = "|cFFDF362D[Bastion]|r |cFFFFFFFF" - for i = 1, #args do - str = str .. tostring(args[i]) .. " " + function Bastion:Print(...) + local args = {...} + local str = "|cFFDF362D[Bastion]|r |cFFFFFFFF" + for i = 1, #args do str = str .. tostring(args[i]) .. " " end + print(str) end - print(str) -end -function Bastion:Debug(...) - if not Bastion.DebugMode then - return - end - local args = {...} - local str = "|cFFDF6520[Bastion]|r |cFFFFFFFF" - for i = 1, #args do - str = str .. tostring(args[i]) .. " " + function Bastion:Debug(...) + if not Bastion.DebugMode then return end + local args = {...} + local str = "|cFFDF6520[Bastion]|r |cFFFFFFFF" + for i = 1, #args do str = str .. tostring(args[i]) .. " " end + print(str) end - print(str) -end -local Command = Bastion.Command:New('bastion') + local Command = Bastion.Command:New('bastion') -Command:Register('toggle', 'Toggle bastion on/off', function() - Bastion.Enabled = not Bastion.Enabled - if Bastion.Enabled then - Bastion:Print("Enabled") - else - Bastion:Print("Disabled") - end -end) + Command:Register('toggle', 'Toggle bastion on/off', function() + Bastion.Enabled = not Bastion.Enabled + if Bastion.Enabled then + Bastion:Print("Enabled") + else + Bastion:Print("Disabled") + end + end) -Command:Register('debug', 'Toggle debug mode on/off', function() - Bastion.DebugMode = not Bastion.DebugMode - if Bastion.DebugMode then - Bastion:Print("Debug mode enabled") - else - Bastion:Print("Debug mode disabled") - end -end) - -Command:Register('dumpspells', 'Dump spells to a file', function() - local i = 1 - local rand = math.random(100000, 999999) - while true do - local spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_SPELL) - if not spellName then - do - break - end + Command:Register('debug', 'Toggle debug mode on/off', function() + Bastion.DebugMode = not Bastion.DebugMode + if Bastion.DebugMode then + Bastion:Print("Debug mode enabled") + else + Bastion:Print("Debug mode disabled") end + end) + + Command:Register('dumpspells', 'Dump spells to a file', function() + local i = 1 + local rand = math.random(100000, 999999) + local BOOKTYPE_SPELL = BOOKTYPE_SPELL or (Enum.SpellBookSpellBank.Player and Enum.SpellBookSpellBank.Player or 'spell') + while true do + local spellName, spellSubName + + if C_SpellBook.GetSpellBookItemName then + spellName, spellSubName = C_SpellBook.GetSpellBookItemName(i, BOOKTYPE_SPELL) + else + spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_SPELL) + end + + if not spellName then do break end end - -- use spellName and spellSubName here - local spellID = select(7, GetSpellInfo(spellName)) + -- use spellName and spellSubName here + local spellID - if spellID then - spellName = spellName:gsub("[%W%s]", "") - WriteFile('bastion-' .. UnitClass('player') .. '-' .. rand .. '.lua', - "local " .. spellName .. " = Bastion.Globals.SpellBook:GetSpell(" .. spellID .. ")\n", true) + if C_Spell.GetSpellInfo then + local info = C_Spell.GetSpellInfo(spellName) + spellID = info.spellID + else + spellID = select(7, GetSpellInfo(spellName)) + end + + if spellID then + spellName = spellName:gsub("[%W%s]", "") + WriteFile('bastion-' .. UnitClass('player') .. '-' .. rand .. + '.lua', + "local " .. spellName .. + " = Bastion.Globals.SpellBook:GetSpell(" .. + spellID .. ")\n", true) + end + i = i + 1 end - i = i + 1 - end -end) - -Command:Register('module', 'Toggle a module on/off', function(args) - local module = Bastion:FindModule(args[2]) - if module then - module:Toggle() - if module.enabled then - Bastion:Print("Enabled", module.name) + end) + + Command:Register('module', 'Toggle a module on/off', function(args) + local module = Bastion:FindModule(args[2]) + if module then + module:Toggle() + if module.enabled then + Bastion:Print("Enabled", module.name) + else + Bastion:Print("Disabled", module.name) + end else - Bastion:Print("Disabled", module.name) + Bastion:Print("Module not found") + end + end) + + Command:Register('mplus', 'Toggle m+ module on/off', function(args) + local cmd = args[2] + if cmd == 'debuffs' then + Bastion.MythicPlusUtils:ToggleDebuffLogging() + Bastion:Print("Debuff logging", Bastion.MythicPlusUtils + .debuffLogging and "enabled" or "disabled") + return end - else - Bastion:Print("Module not found") - end -end) - -Command:Register('mplus', 'Toggle m+ module on/off', function(args) - local cmd = args[2] - if cmd == 'debuffs' then - Bastion.MythicPlusUtils:ToggleDebuffLogging() - Bastion:Print("Debuff logging", Bastion.MythicPlusUtils.debuffLogging and "enabled" or "disabled") - return - end - if cmd == 'casts' then - Bastion.MythicPlusUtils:ToggleCastLogging() - Bastion:Print("Cast logging", Bastion.MythicPlusUtils.castLogging and "enabled" or "disabled") - return - end + if cmd == 'casts' then + Bastion.MythicPlusUtils:ToggleCastLogging() + Bastion:Print("Cast logging", + Bastion.MythicPlusUtils.castLogging and "enabled" or + "disabled") + return + end - Bastion:Print("[MythicPlusUtils] Unknown command") - Bastion:Print("Available commands:") - Bastion:Print("debuffs") - Bastion:Print("casts") -end) + Bastion:Print("[MythicPlusUtils] Unknown command") + Bastion:Print("Available commands:") + Bastion:Print("debuffs") + Bastion:Print("casts") + end) -Command:Register('missed', 'Dump the list of immune kidney shot spells', function() - for k, v in pairs(missed) do - Bastion:Print(k) - end -end) + Command:Register('missed', 'Dump the list of immune kidney shot spells', + function() + for k, v in pairs(missed) do Bastion:Print(k) end + end) ----@param library Library -function Bastion:RegisterLibrary(library) - LIBRARIES[library.name] = library -end + ---@param library Library + function Bastion:RegisterLibrary(library) + LIBRARIES[library.name] = library + end -function Bastion:CheckLibraryDependencies() - for k, v in pairs(LIBRARIES) do - if v.dependencies then - for i = 1, #v.dependencies do - local dep = v.dependencies[i] - if LIBRARIES[dep] then - if LIBRARIES[dep].dependencies then - for j = 1, #LIBRARIES[dep].dependencies do - if LIBRARIES[dep].dependencies[j] == v.name then - Bastion:Print("Circular dependency detected between " .. v.name .. " and " .. dep) - return false + function Bastion:CheckLibraryDependencies() + for k, v in pairs(LIBRARIES) do + if v.dependencies then + for i = 1, #v.dependencies do + local dep = v.dependencies[i] + if LIBRARIES[dep] then + if LIBRARIES[dep].dependencies then + for j = 1, #LIBRARIES[dep].dependencies do + if LIBRARIES[dep].dependencies[j] == v.name then + Bastion:Print( + "Circular dependency detected between " .. + v.name .. " and " .. dep) + return false + end end end + else + Bastion:Print("Library " .. v.name .. " depends on " .. + dep .. " but it's not registered") + return false end - else - Bastion:Print("Library " .. v.name .. " depends on " .. dep .. " but it's not registered") - return false end end end + + return true end - return true -end + function Bastion:Import(library) + local lib = self:GetLibrary(library) -function Bastion:Import(library) - local lib = self:GetLibrary(library) + if not lib then error("Library " .. library .. " not found") end - if not lib then - error("Library " .. library .. " not found") + return lib:Resolve() end - return lib:Resolve() -end + function Bastion:GetLibrary(name) + if not LIBRARIES[name] then + error("Library " .. name .. " not found") + end -function Bastion:GetLibrary(name) - if not LIBRARIES[name] then - error("Library " .. name .. " not found") + local library = LIBRARIES[name] + + -- if library.dependencies then + -- for i = 1, #library.dependencies do + -- local dep = library.dependencies[i] + -- if LIBRARIES[dep] then + -- if LIBRARIES[dep].dependencies then + -- for j = 1, #LIBRARIES[dep].dependencies do + -- if LIBRARIES[dep].dependencies[j] == library.name then + -- Bastion:Print("Circular dependency detected between " .. library.name .. " and " .. dep) + -- return false + -- end + -- end + -- end + -- else + -- Bastion:Print("Library " .. v.name .. " depends on " .. dep .. " but it's not registered") + -- return false + -- end + -- end + -- end + + return library end - local library = LIBRARIES[name] - - -- if library.dependencies then - -- for i = 1, #library.dependencies do - -- local dep = library.dependencies[i] - -- if LIBRARIES[dep] then - -- if LIBRARIES[dep].dependencies then - -- for j = 1, #LIBRARIES[dep].dependencies do - -- if LIBRARIES[dep].dependencies[j] == library.name then - -- Bastion:Print("Circular dependency detected between " .. library.name .. " and " .. dep) - -- return false - -- end - -- end - -- end - -- else - -- Bastion:Print("Library " .. v.name .. " depends on " .. dep .. " but it's not registered") - -- return false - -- end - -- end + -- if not Bastion:CheckLibraryDependencies() then + -- return -- end - return library + Load("@Libraries/") + Load("@Modules/") + Load("@") end --- if not Bastion:CheckLibraryDependencies() then --- return --- end - -Load("@Libraries/") -Load("@Modules/") -Load("@") +Bastion.Bootstrap()