From 48fa6cd025c69b2bcd0100821b39ee54003bd7df Mon Sep 17 00:00:00 2001 From: Dusk-92 Date: Sun, 30 Aug 2026 10:24:04 +0200 Subject: [PATCH] Harden module initialization order --- mods/raid-compact-layout.lua | 91 ++++++++++++++++------------ mods/raid-dispel-indicators.lua | 2 +- mods/raid-hide-party.lua | 68 +++++++++++---------- mods/raid-party.lua | 75 ++++++++++++----------- mods/raid.lua | 44 +++++++++++--- mods/reduced-actionbar-bags.lua | 18 ++++-- mods/reduced-actionbar-micromenu.lua | 18 ++++-- 7 files changed, 188 insertions(+), 128 deletions(-) diff --git a/mods/raid-compact-layout.lua b/mods/raid-compact-layout.lua index fa0a2b9..60e2eb3 100644 --- a/mods/raid-compact-layout.lua +++ b/mods/raid-compact-layout.lua @@ -11,61 +11,72 @@ local module = ShaguTweaks:register({ }) module.enable = function(self) - -- overwrite config - ShaguTweaksRaidCluster.config["raid.width"] = 64 - ShaguTweaksRaidCluster.config["raid.height"] = 12 - ShaguTweaksRaidCluster.config["raid.rows"] = 40 + if not ShaguTweaks.RaidFrame_OnReady then return end - -- disable mana bars - ShaguTweaks.UnitFrame_NewComponent('compact layout', { - events = { }, - create = function(frame) - frame.compact = true + ShaguTweaks.RaidFrame_OnReady(function(raid) + -- overwrite config before unit frames are created + raid.cluster.config["raid.width"] = 64 + raid.cluster.config["raid.height"] = 12 + raid.cluster.config["raid.rows"] = 40 - -- hide mana bar - frame.mana:Hide() + -- disable mana bars + ShaguTweaks.UnitFrame_NewComponent('compact layout', { + events = { }, + create = function(frame) + frame.compact = true - -- move player text to healthbar - frame.text:SetParent(frame.bar) - frame.icon:SetParent(frame.bar) - -- move raid icon - frame.icon:ClearAllPoints() - frame.icon:SetPoint("LEFT", frame.bar, "LEFT", 0, 0) + -- hide mana bar + frame.mana:Hide() - end, - update = function(frame, event) - -- compact mode is handled by the base text component + -- move player text to healthbar + frame.text:SetParent(frame.bar) + frame.icon:SetParent(frame.bar) + + -- move raid icon + frame.icon:ClearAllPoints() + frame.icon:SetPoint("LEFT", frame.bar, "LEFT", 0, 0) + end, + update = function(frame, event) + -- compact mode is handled by the base text component + end + }) + + local headerTitle = T["Show Group Headers"] + local headerEnabled = ShaguTweaks_config and ShaguTweaks_config[headerTitle] + if headerEnabled == nil then + local headerModule = ShaguTweaks.mods and ShaguTweaks.mods[headerTitle] + headerEnabled = headerModule and headerModule.enabled and 1 or 0 end - }) - -- wait for the game to be loaded - local delay = CreateFrame("Frame") - delay:SetScript("OnUpdate", function() - this.elapsed = (this.elapsed or 0) + arg1 + -- No header module means there is nothing to wait for or reposition. + if headerEnabled ~= 1 then return end + + local delay = CreateFrame("Frame") + delay:SetScript("OnUpdate", function() + this.elapsed = (this.elapsed or 0) + (arg1 or 0) + this.total = (this.total or 0) + (arg1 or 0) if this.elapsed < .10 then return end this.elapsed = 0 if ShaguTweaksRaidHeaders then - -- modify group headers - for i=1, 8 do + for i = 1, 8 do if ShaguTweaksRaidHeaders[i] then - -- read raid anchor per group header local _, anchor = ShaguTweaksRaidHeaders[i]:GetPoint() - - -- remove background and move to the left - --ShaguTweaksRaidHeaders[i]:SetBackdrop(nil) - ShaguTweaksRaidHeaders[i]:ClearAllPoints() - ShaguTweaksRaidHeaders[i]:SetPoint("LEFT", anchor, "LEFT", -6, 6) - ShaguTweaksRaidHeaders[i]:SetWidth(16) - ShaguTweaksRaidHeaders[i]:SetHeight(16) - --ShaguTweaksRaidHeaders[i].text:SetTextColor(.5,.5,.5,1) - ShaguTweaksRaidHeaders[i].text:SetText(i) - ShaguTweaksRaidHeaders[i]:SetAlpha(.75) + if anchor then + ShaguTweaksRaidHeaders[i]:ClearAllPoints() + ShaguTweaksRaidHeaders[i]:SetPoint("LEFT", anchor, "LEFT", -6, 6) + ShaguTweaksRaidHeaders[i]:SetWidth(16) + ShaguTweaksRaidHeaders[i]:SetHeight(16) + ShaguTweaksRaidHeaders[i].text:SetText(i) + ShaguTweaksRaidHeaders[i]:SetAlpha(.75) + end end end - -- disable delay only after headers were actually available + this:Hide() + elseif this.total >= 10 then + -- Fail closed instead of polling forever if headers never materialize. this:Hide() end + end) end) - end diff --git a/mods/raid-dispel-indicators.lua b/mods/raid-dispel-indicators.lua index 832d920..f8b75e2 100644 --- a/mods/raid-dispel-indicators.lua +++ b/mods/raid-dispel-indicators.lua @@ -62,7 +62,7 @@ module.enable = function(self) update = function(frame, event) -- ignore empty or unrelated events if not event then return end - if arg1 and this.unitstr ~= arg1 then return end + if arg1 and frame.unitstr ~= arg1 then return end -- affected debuffs frame.affected = frame.affected or {} diff --git a/mods/raid-hide-party.lua b/mods/raid-hide-party.lua index 611e76d..3fb332b 100644 --- a/mods/raid-hide-party.lua +++ b/mods/raid-hide-party.lua @@ -11,47 +11,51 @@ local module = ShaguTweaks:register({ }) module.enable = function(self) - local raid = ShaguTweaksRaidFrame - if not raid then return end + if not ShaguTweaks.RaidFrame_OnReady then return end - local originals = {} - local hidden = false - - for i = 1, MAX_PARTY_MEMBERS do - local frame = _G["PartyMemberFrame" .. i] - if frame then originals[frame] = frame.Show end - end - - local function SetPartyFramesHidden(state) - if state == hidden then return end - hidden = state + ShaguTweaks.RaidFrame_OnReady(function(raid) + local originals = {} + local hidden = false for i = 1, MAX_PARTY_MEMBERS do local frame = _G["PartyMemberFrame" .. i] - if frame then - if state then - frame.Show = function() return end - frame:Hide() - else - frame.Show = originals[frame] - if GetPartyMember(i) then frame:Show() else frame:Hide() end + if frame then originals[frame] = frame.Show end + end + + local function SetPartyFramesHidden(state) + if state == hidden then return end + hidden = state + + for i = 1, MAX_PARTY_MEMBERS do + local frame = _G["PartyMemberFrame" .. i] + if frame then + if state then + frame.Show = function() return end + frame:Hide() + else + frame.Show = originals[frame] + if GetPartyMember(i) then frame:Show() else frame:Hide() end + end end end end - end - local function UpdatePartyFrames() - SetPartyFramesHidden(raid:IsShown()) - end + local function UpdatePartyFrames() + local active = raid:IsShown() and raid.cluster and raid.cluster:IsShown() + SetPartyFramesHidden(active and true or false) + end - ShaguTweaks.HookScript(raid, "OnShow", UpdatePartyFrames) - ShaguTweaks.HookScript(raid, "OnHide", UpdatePartyFrames) + ShaguTweaks.HookScript(raid, "OnShow", UpdatePartyFrames) + ShaguTweaks.HookScript(raid, "OnHide", UpdatePartyFrames) + ShaguTweaks.HookScript(raid.cluster, "OnShow", UpdatePartyFrames) + ShaguTweaks.HookScript(raid.cluster, "OnHide", UpdatePartyFrames) - local watcher = CreateFrame("Frame", nil, UIParent) - watcher:RegisterEvent("PLAYER_ENTERING_WORLD") - watcher:RegisterEvent("RAID_ROSTER_UPDATE") - watcher:RegisterEvent("PARTY_MEMBERS_CHANGED") - watcher:SetScript("OnEvent", UpdatePartyFrames) + local watcher = CreateFrame("Frame", nil, UIParent) + watcher:RegisterEvent("PLAYER_ENTERING_WORLD") + watcher:RegisterEvent("RAID_ROSTER_UPDATE") + watcher:RegisterEvent("PARTY_MEMBERS_CHANGED") + watcher:SetScript("OnEvent", UpdatePartyFrames) - UpdatePartyFrames() + UpdatePartyFrames() + end) end diff --git a/mods/raid-party.lua b/mods/raid-party.lua index 139536b..06775a9 100644 --- a/mods/raid-party.lua +++ b/mods/raid-party.lua @@ -11,52 +11,53 @@ local module = ShaguTweaks:register({ }) module.enable = function(self) - local raid = ShaguTweaksRaidFrame - if not raid then return end + if not ShaguTweaks.RaidFrame_OnReady then return end - local RaidOnEvent = raid:GetScript("OnEvent") - raid:RegisterEvent("PARTY_LEADER_CHANGED") - raid:RegisterEvent("PARTY_LOOT_METHOD_CHANGED") - raid:RegisterEvent("PARTY_MEMBERS_CHANGED") + ShaguTweaks.RaidFrame_OnReady(function(raid) + local RaidOnEvent = raid:GetScript("OnEvent") + raid:RegisterEvent("PARTY_LEADER_CHANGED") + raid:RegisterEvent("PARTY_LOOT_METHOD_CHANGED") + raid:RegisterEvent("PARTY_MEMBERS_CHANGED") - raid:SetScript("OnEvent", function() - -- run default scripts - if RaidOnEvent then RaidOnEvent() end + raid:SetScript("OnEvent", function() + -- run default scripts + if RaidOnEvent then RaidOnEvent() end - -- break here in normal raid scenario - if UnitInRaid("player") then return end + -- break here in normal raid scenario + if UnitInRaid("player") then return end - -- check for party mode - if GetNumPartyMembers() > 0 then - -- initialize raid frame - local x, y = 1, 0 - for index = 1, 40 do - -- clear current unitstr assignments - this.cluster.frames[index].unitstr = nil - this.cluster.frames[index]:Hide() + -- check for party mode + if GetNumPartyMembers() > 0 then + -- initialize raid frame + local x, y = 1, 0 + for index = 1, 40 do + -- clear current unitstr assignments + this.cluster.frames[index].unitstr = nil + this.cluster.frames[index]:Hide() - if index <= 5 then - -- determine best unitstr - local unitstr = index == 1 and "player" or "party" .. index-1 + if index <= 5 then + -- determine best unitstr + local unitstr = index == 1 and "player" or "party" .. index-1 - -- assign party to first raid group of frames - this.cluster.frames[index].unitstr = unitstr - this.cluster.frames[index].groupid = 1 - this.cluster.frames[index]:Show() + -- assign party to first raid group of frames + this.cluster.frames[index].unitstr = unitstr + this.cluster.frames[index].groupid = 1 + this.cluster.frames[index]:Show() - -- save required raid frame size - if UnitExists(unitstr) then - y = math.max(y, index) + -- save required raid frame size + if UnitExists(unitstr) then + y = math.max(y, index) + end end end - end - -- set raid frame size - raid.cluster:SetWidth(x * (raid.cluster.config["raid.width"]+2) + 6) - raid.cluster:SetHeight(y * (raid.cluster.config["raid.height"]+1) + 7) - raid:Show() - else - raid:Hide() - end + -- set raid frame size + raid.cluster:SetWidth(x * (raid.cluster.config["raid.width"]+2) + 6) + raid.cluster:SetHeight(y * (raid.cluster.config["raid.height"]+1) + 7) + raid:Show() + else + raid:Hide() + end + end) end) end diff --git a/mods/raid.lua b/mods/raid.lua index 3bfa805..e5964ab 100644 --- a/mods/raid.lua +++ b/mods/raid.lua @@ -18,6 +18,32 @@ local module = ShaguTweaks:register({ }) local components = {} +local raidReadyCallbacks = {} +local raidReadyFrame + +-- Raid submodules are enabled from an unordered ShaguTweaks.mods table. +-- Queue work that needs the actual raid frame so submodules never depend on +-- which module happens to be visited first by pairs(). +ShaguTweaks.RaidFrame_OnReady = function(callback) + if type(callback) ~= "function" then return end + + if raidReadyFrame then + callback(raidReadyFrame) + else + table.insert(raidReadyCallbacks, callback) + end +end + +local function NotifyRaidFrameReady(raid) + raidReadyFrame = raid + + local callbacks = raidReadyCallbacks + raidReadyCallbacks = {} + + for i = 1, table.getn(callbacks) do + callbacks[i](raid) + end +end local backdrop = { border = { @@ -134,7 +160,7 @@ local UnitFrame_OnEvent = function() if not this.events[event] then return end -- run update functions for each frame - for id, component in pairs(this.events[event]) do + for _, component in ipairs(this.events[event]) do component.update(this, event) end end @@ -170,12 +196,12 @@ local CreateUnitFrame = function(parent, i) frame:RegisterEvent("PARTY_MEMBERS_CHANGED") frame:RegisterEvent("PLAYER_ENTERING_WORLD") - for id, object in pairs(components) do + for _, object in ipairs(components) do -- create component frames object.create(frame) -- register component update events - for _, event in pairs(object.events) do + for _, event in ipairs(object.events) do frame:RegisterEvent(event) frame.events[event] = frame.events[event] or {} table.insert(frame.events[event], object) @@ -225,7 +251,7 @@ UnitFrame_NewComponent('health', { update = function(frame, event) -- ignore empty or unrelated events if not event then return end - if arg1 and this.unitstr ~= arg1 then return end + if arg1 and frame.unitstr ~= arg1 then return end -- update statusbar values frame.bar:SetMinMaxValues(0, UnitHealthMax(frame.unitstr)) @@ -269,7 +295,7 @@ UnitFrame_NewComponent('mana', { update = function(frame, event) -- ignore empty or unrelated events if not event then return end - if arg1 and this.unitstr ~= arg1 then return end + if arg1 and frame.unitstr ~= arg1 then return end -- update mana bar values frame.mana:SetMinMaxValues(0, UnitManaMax(frame.unitstr)) @@ -484,7 +510,7 @@ module.enable = function(self) local x, y = 0, 0 for group = 1, 8 do if RAID_SUBGROUP_LISTS and RAID_SUBGROUP_LISTS[group] then - for id, unit in pairs(RAID_SUBGROUP_LISTS[group]) do + for id, unit in ipairs(RAID_SUBGROUP_LISTS[group]) do -- assign proper unitstrs to frames local index = (group - 1) * 5 + id local frame = this.cluster.frames[index] @@ -612,11 +638,11 @@ module.enable = function(self) if not raid.cluster.frames then return end - for _, frame in pairs(raid.cluster.frames) do + for _, frame in ipairs(raid.cluster.frames) do if frame:IsVisible() and frame.unitstr and UnitName(frame.unitstr) then local tickers = frame.events['FRAME_TICK_250'] if tickers then - for _, component in pairs(tickers) do + for _, component in ipairs(tickers) do component.update(frame, 'FRAME_TICK_250') end end @@ -624,4 +650,6 @@ module.enable = function(self) end end) end + + NotifyRaidFrameReady(raid) end diff --git a/mods/reduced-actionbar-bags.lua b/mods/reduced-actionbar-bags.lua index b1ca08b..f022d2b 100644 --- a/mods/reduced-actionbar-bags.lua +++ b/mods/reduced-actionbar-bags.lua @@ -15,8 +15,16 @@ local module = ShaguTweaks:register({ }) module.enable = function(self) - -- only run if reduced actionbar is enabled - if ShaguTweaks_config[T["Reduced Actionbar Size"]] == 0 then return end + -- The ShaguTweaks loader initializes module config while iterating an + -- unordered table. On a fresh install the Reduced Actionbar key may not have + -- been visited yet, so fall back to that module's declared default. + local reducedTitle = T["Reduced Actionbar Size"] + local reducedEnabled = ShaguTweaks_config and ShaguTweaks_config[reducedTitle] + if reducedEnabled == nil then + local reducedModule = ShaguTweaks.mods and ShaguTweaks.mods[reducedTitle] + reducedEnabled = reducedModule and reducedModule.enabled and 1 or 0 + end + if reducedEnabled ~= 1 then return end local frames = { KeyRingButton, CharacterBag3Slot, CharacterBag2Slot, CharacterBag1Slot, @@ -71,7 +79,7 @@ module.enable = function(self) if not this.mousedisabled then -- disable mouse events on all frames this.mousedisabled = true - for _, frame in pairs(frames) do + for _, frame in ipairs(frames) do frame:EnableMouse(0) end end @@ -79,7 +87,7 @@ module.enable = function(self) if this.mousedisabled then -- enable all mouse events again this.mousedisabled = false - for _, frame in pairs(frames) do + for _, frame in ipairs(frames) do frame:EnableMouse(1) end end @@ -92,7 +100,7 @@ module.enable = function(self) ShaguTweaks.DarkenFrame(bagframe) - for id, frame in pairs(frames) do + for id, frame in ipairs(frames) do local anchor = frames[id-1] or bagframe frame:ClearAllPoints() frame:SetPoint("LEFT", anchor, id == 1 and "LEFT" or "RIGHT", id == 1 and 5 or 2, 0) diff --git a/mods/reduced-actionbar-micromenu.lua b/mods/reduced-actionbar-micromenu.lua index 84da3bf..3d1b4cf 100644 --- a/mods/reduced-actionbar-micromenu.lua +++ b/mods/reduced-actionbar-micromenu.lua @@ -15,8 +15,16 @@ local module = ShaguTweaks:register({ }) module.enable = function(self) - -- only run if reduced actionbar is enabled - if ShaguTweaks_config[T["Reduced Actionbar Size"]] == 0 then return end + -- The ShaguTweaks loader initializes module config while iterating an + -- unordered table. On a fresh install the Reduced Actionbar key may not have + -- been visited yet, so fall back to that module's declared default. + local reducedTitle = T["Reduced Actionbar Size"] + local reducedEnabled = ShaguTweaks_config and ShaguTweaks_config[reducedTitle] + if reducedEnabled == nil then + local reducedModule = ShaguTweaks.mods and ShaguTweaks.mods[reducedTitle] + reducedEnabled = reducedModule and reducedModule.enabled and 1 or 0 + end + if reducedEnabled ~= 1 then return end local frames = { CharacterMicroButton, SpellbookMicroButton, TalentMicroButton, @@ -72,7 +80,7 @@ module.enable = function(self) if not this.mousedisabled then -- disable mouse events on all frames this.mousedisabled = true - for _, frame in pairs(frames) do + for _, frame in ipairs(frames) do frame:EnableMouse(0) end end @@ -80,7 +88,7 @@ module.enable = function(self) if this.mousedisabled then -- enable all mouse events again this.mousedisabled = false - for _, frame in pairs(frames) do + for _, frame in ipairs(frames) do frame:EnableMouse(1) end end @@ -93,7 +101,7 @@ module.enable = function(self) ShaguTweaks.DarkenFrame(microframe) - for id, frame in pairs(frames) do + for id, frame in ipairs(frames) do local anchor = frames[id-1] or microframe frame:ClearAllPoints() frame:SetPoint("LEFT", anchor, id == 1 and "LEFT" or "RIGHT", id == 1 and 3.5 or -2, id==1 and 10 or 0)