From f4685c9e014c75604da04cda784421381e29b7e2 Mon Sep 17 00:00:00 2001 From: Dusk-92 Date: Sun, 30 Aug 2026 09:13:12 +0200 Subject: [PATCH] Optimize and harden raid frames --- mods/raid-aggro-indicator.lua | 7 +-- mods/raid-combat-feedback.lua | 7 +-- mods/raid-compact-layout.lua | 14 +++-- mods/raid-dispel-indicators.lua | 11 +++- mods/raid-healing-predictions.lua | 19 ++++--- mods/raid-hide-party.lua | 72 +++++++++++++------------ mods/raid-party.lua | 2 +- mods/raid.lua | 90 +++++++++++++++---------------- 8 files changed, 123 insertions(+), 99 deletions(-) diff --git a/mods/raid-aggro-indicator.lua b/mods/raid-aggro-indicator.lua index 9494012..2f4c1e1 100644 --- a/mods/raid-aggro-indicator.lua +++ b/mods/raid-aggro-indicator.lua @@ -18,7 +18,7 @@ local backdrop = { } -- basic unitstrings -unitstrings = { +local unitstrings = { ["pet"] = true, ["player"] = true, ["target"] = true, ["mouseover"] = true } @@ -31,12 +31,13 @@ for i=1,40 do unitstrings["raidpet" .. i] = true end -- cached aggro detection function local aggrodata = { } local function UnitHasAggro(unit) - if aggrodata[unit] and GetTime() < aggrodata[unit].check + 1 then + local now = GetTime() + if aggrodata[unit] and now < aggrodata[unit].check + 1 then return aggrodata[unit].state end aggrodata[unit] = aggrodata[unit] or { } - aggrodata[unit].check = GetTime() + aggrodata[unit].check = now aggrodata[unit].state = 0 if UnitExists(unit) and UnitIsFriend(unit, "player") then diff --git a/mods/raid-combat-feedback.lua b/mods/raid-combat-feedback.lua index cffda9f..89b1fac 100644 --- a/mods/raid-combat-feedback.lua +++ b/mods/raid-combat-feedback.lua @@ -12,16 +12,17 @@ local module = ShaguTweaks:register({ module.enable = function(self) ShaguTweaks.UnitFrame_NewComponent('combat feedback', { + onupdate = true, events = { 'UNIT_COMBAT', }, create = function(frame) -- create combat feedback text - frame.feedback = frame.mana:CreateFontString("feedback"..GetTime(), "OVERLAY", "NumberFontNormalHuge") + frame.feedback = frame.mana:CreateFontString(nil, "OVERLAY", "NumberFontNormalHuge") frame.feedback:SetFont(DAMAGE_TEXT_FONT, 12, "OUTLINE") frame.feedback:SetParent(frame.mana) - frame.feedback:ClearAllPoints(frame.bar) + frame.feedback:ClearAllPoints() frame.feedback:SetPoint("CENTER", frame.bar, "CENTER", 0, 0) frame.feedbackFontHeight = 12 @@ -32,7 +33,7 @@ module.enable = function(self) update = function(frame, event) if event and event == 'UNIT_COMBAT' then -- update with latest values - if arg1 ~= this.unitstr then return end + if arg1 ~= frame.unitstr then return end CombatFeedback_OnCombatEvent(arg2, arg3, arg4, arg5) else -- animate combat text diff --git a/mods/raid-compact-layout.lua b/mods/raid-compact-layout.lua index 8b81837..fa0a2b9 100644 --- a/mods/raid-compact-layout.lua +++ b/mods/raid-compact-layout.lua @@ -20,6 +20,8 @@ module.enable = function(self) ShaguTweaks.UnitFrame_NewComponent('compact layout', { events = { }, create = function(frame) + frame.compact = true + -- hide mana bar frame.mana:Hide() @@ -32,14 +34,17 @@ module.enable = function(self) end, update = function(frame, event) - -- disable all second lines - frame.info = nil + -- compact mode is handled by the base text component end }) -- wait for the game to be loaded local delay = CreateFrame("Frame") delay:SetScript("OnUpdate", function() + this.elapsed = (this.elapsed or 0) + arg1 + if this.elapsed < .10 then return end + this.elapsed = 0 + if ShaguTweaksRaidHeaders then -- modify group headers for i=1, 8 do @@ -58,10 +63,9 @@ module.enable = function(self) ShaguTweaksRaidHeaders[i]:SetAlpha(.75) end end + -- disable delay only after headers were actually available + this:Hide() end - - -- disable delay - this:Hide() end) end diff --git a/mods/raid-dispel-indicators.lua b/mods/raid-dispel-indicators.lua index e77605d..832d920 100644 --- a/mods/raid-dispel-indicators.lua +++ b/mods/raid-dispel-indicators.lua @@ -1,5 +1,6 @@ local _G = ShaguTweaks.GetGlobalEnv() local T = ShaguTweaks.T +local API = ShaguTweaks.API or {} local module = ShaguTweaks:register({ title = T["Show Dispel Indicators"], @@ -68,7 +69,15 @@ module.enable = function(self) for dtype in pairs(debuffs) do frame.affected[dtype] = nil end for i = 1, 16 do - local _, _, dtype = UnitDebuff(frame.unitstr, i) + local dtype + if API.aurapositional and API.UnitDebuff then + local _, _, _, debuffType = API.UnitDebuff(frame.unitstr, i) + dtype = debuffType + else + local _, _, debuffType = UnitDebuff(frame.unitstr, i) + dtype = debuffType + end + if dtype then frame.affected[dtype] = true end end diff --git a/mods/raid-healing-predictions.lua b/mods/raid-healing-predictions.lua index d7eedf5..3525240 100644 --- a/mods/raid-healing-predictions.lua +++ b/mods/raid-healing-predictions.lua @@ -12,7 +12,9 @@ local module = ShaguTweaks:register({ module.enable = function(self) ShaguTweaks.UnitFrame_NewComponent('healing predictions', { - events = { }, + events = { + 'FRAME_TICK_250', + }, create = function(frame) -- create green prediction healthbar @@ -29,18 +31,19 @@ module.enable = function(self) local res = ShaguTweaks.libpredict:UnitHasIncomingResurrection(frame.unitstr) -- update bar size if required - if heal ~= this.predict_lastval then + if heal ~= frame.predict_lastval then if heal and heal > 0 then local health, maxHealth = UnitHealth(frame.unitstr), UnitHealthMax(frame.unitstr) - local healthWidth = 62 * health / maxHealth - local incWidth = 62 * heal / maxHealth - local width = math.min(62, healthWidth + incWidth) - frame.predict:SetWidth(width) + local barWidth = frame.bar:GetWidth() + local healthWidth = maxHealth > 0 and barWidth * health / maxHealth or 0 + local incWidth = maxHealth > 0 and barWidth * heal / maxHealth or 0 + frame.predict:SetWidth(math.min(barWidth, healthWidth + incWidth)) + frame.predict:Show() else - frame.predict:SetWidth(-1) + frame.predict:Hide() end - this.predict_lastval = heal + frame.predict_lastval = heal end -- update healing state diff --git a/mods/raid-hide-party.lua b/mods/raid-hide-party.lua index 8541adb..611e76d 100644 --- a/mods/raid-hide-party.lua +++ b/mods/raid-hide-party.lua @@ -11,41 +11,47 @@ local module = ShaguTweaks:register({ }) module.enable = function(self) - local show = _G['PartyMemberFrame1'].Show - local hide = function() return end + local raid = ShaguTweaksRaidFrame + if not raid then return end - local scanner = CreateFrame("Frame", nil, UIParent) - scanner:SetScript("OnUpdate", function() - if ShaguTweaksRaidFrame and ShaguTweaksRaidFrame:IsShown() then - if not this.disable then - -- disable all party frames - for i = 1, MAX_PARTY_MEMBERS do - local frame = _G['PartyMemberFrame' .. i] - if frame then - frame.Show = hide - frame:Hide() - 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 + + 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 - - this.disable = true - end - else - if this.disable then - -- enable all party frames - for i = 1, MAX_PARTY_MEMBERS do - for i = 1, MAX_PARTY_MEMBERS do - local frame = _G['PartyMemberFrame' .. i] - if frame then - frame.Show = show - if GetPartyMember(i) then - frame:Show() - end - end - end - end - - this.disable = nil end end - end) + end + + local function UpdatePartyFrames() + SetPartyFramesHidden(raid:IsShown()) + end + + ShaguTweaks.HookScript(raid, "OnShow", UpdatePartyFrames) + ShaguTweaks.HookScript(raid, "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) + + UpdatePartyFrames() end diff --git a/mods/raid-party.lua b/mods/raid-party.lua index 4f385d3..139536b 100644 --- a/mods/raid-party.lua +++ b/mods/raid-party.lua @@ -21,7 +21,7 @@ module.enable = function(self) raid:SetScript("OnEvent", function() -- run default scripts - RaidOnEvent() + if RaidOnEvent then RaidOnEvent() end -- break here in normal raid scenario if UnitInRaid("player") then return end diff --git a/mods/raid.lua b/mods/raid.lua index 2d73bb8..4dcd96e 100644 --- a/mods/raid.lua +++ b/mods/raid.lua @@ -1,6 +1,6 @@ local _G = ShaguTweaks.GetGlobalEnv() local T = ShaguTweaks.T -local rgbhex = ShaguTweaks.rgbhex +local API = ShaguTweaks.API or {} local module = ShaguTweaks:register({ title = T["Enable Raid Frames"], @@ -44,22 +44,21 @@ local GetFramePosition = function(i, rows) end local UnitInRange = function(unitstr) - if SUPERWOW_VERSION then - -- 40y range check + if not unitstr then return false end + + -- Prefer positional range data whenever the client exposes UnitPosition + -- (SuperWoW or another compatibility layer), then fall back to Vanilla. + if type(UnitPosition) == "function" then local x1, y1, z1 = UnitPosition("player") - local x2, y2, z2 = UnitPosition(this.unitstr) + local x2, y2, z2 = UnitPosition(unitstr) - -- only continue if we got position values if x1 and y1 and z1 and x2 and y2 and z2 then local distance = ((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)^.5 if distance < 40 then return true end end - else - -- 28y range check - if CheckInteractDistance(this.unitstr, 4) then return true end end - return false + return CheckInteractDistance(unitstr, 4) and true or false end -- Unit Frames @@ -83,26 +82,24 @@ local UnitFrame_OnLeave = function() end local UnitFrame_OnUpdate = function() - -- abort on invalid unit frames if not this.unitstr or not UnitName(this.unitstr) then this:Hide() return end - -- run update functions of all components - for component in pairs(this.update) do + -- Only components that explicitly need frame-by-frame animation run here. + for component in pairs(this.onupdate) do component.update(this) end - -- run 250ms tick pseudo events - this.tick250 = this.tick250 or 0 - if this.events['FRAME_TICK_250'] and this.tick250 < GetTime() then - -- set next tick time - this.tick250 = GetTime() + .250 - - -- run update functions for each frame - for id, component in pairs(this.events['FRAME_TICK_250']) do - component.update(this, 'FRAME_TICK_250') + -- Shared 250 ms pseudo-event using the elapsed frame time instead of GetTime. + if this.events['FRAME_TICK_250'] then + this.tick250 = (this.tick250 or 0) - (arg1 or 0) + if this.tick250 <= 0 then + this.tick250 = .250 + for _, component in pairs(this.events['FRAME_TICK_250']) do + component.update(this, 'FRAME_TICK_250') + end end end end @@ -170,7 +167,7 @@ local CreateUnitFrame = function(parent, i) ['PLAYER_ENTERING_WORLD'] = { }, } - frame.update = {} + frame.onupdate = {} -- assign required events and scripts frame:SetScript("OnEvent", UnitFrame_OnEvent) @@ -201,8 +198,10 @@ local CreateUnitFrame = function(parent, i) table.insert(frame.events['PARTY_MEMBERS_CHANGED'], object) table.insert(frame.events['PLAYER_ENTERING_WORLD'], object) - -- register update function - frame.update[object] = true + -- only register true frame-by-frame components + if object.onupdate then + frame.onupdate[object] = true + end end -- save frame to parent @@ -244,7 +243,7 @@ UnitFrame_NewComponent('health', { if class and RAID_CLASS_COLORS[class] then r, g, b = RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b end - frame.bar:SetStatusBarColor(r, g, b, a) + frame.bar:SetStatusBarColor(r, g, b, 1) end }) @@ -283,13 +282,15 @@ UnitFrame_NewComponent('mana', { frame.mana:SetValue(UnitMana(frame.unitstr)) -- update mana bar colors - local color = ManaBarColor[UnitPowerType(frame.unitstr)] + local color = ManaBarColor[UnitPowerType(frame.unitstr)] or { r = .2, g = .2, b = 1 } frame.mana:SetStatusBarColor(color.r, color.g, color.b, 1) end }) UnitFrame_NewComponent('text', { - events = { }, + events = { + 'FRAME_TICK_250', + }, create = function(frame) -- create caption text @@ -303,10 +304,12 @@ UnitFrame_NewComponent('text', { update = function(frame, event) -- update caption text local name = UnitName(frame.unitstr) or "" - local info = frame.info and "\n"..frame.info or "" + local info = (not frame.compact and frame.info) and "\n"..frame.info or "" frame.text:SetText(name .. info) frame.info = nil + if frame.compact then return end + -- update info states if not UnitIsConnected(frame.unitstr) then frame.info = "|cffaaaaaaOffline|r" @@ -561,15 +564,20 @@ module.enable = function(self) pushed:SetHeight(110) pushed:SetAlpha(.5) - raid.toggle:SetScript("OnMouseDown", function() - if IsShiftKeyDown() then - this.dragging = true + local function UpdateToggleDrag() + local px, py = GetCursorPosition() + local scale = raid.toggle:GetEffectiveScale() + px, py = px / scale, py / scale + raid.toggle:ClearAllPoints() + raid.toggle:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", -8, py-32) + end - local px, py = GetCursorPosition() - local scale = this:GetEffectiveScale() - px, py = px / scale, py / scale - raid.toggle:ClearAllPoints() - raid.toggle:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", -8, py-32) + raid.toggle:SetScript("OnMouseDown", function() + local shift = API.IsShiftKeyDown and API.IsShiftKeyDown() or IsShiftKeyDown() + if shift then + this.dragging = true + this:SetScript("OnUpdate", UpdateToggleDrag) + UpdateToggleDrag() else if raid.cluster:IsShown() then raid.toggle.icon:SetTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Disabled") @@ -583,15 +591,7 @@ module.enable = function(self) raid.toggle:SetScript("OnMouseUp", function() this.dragging = false - end) - - raid.toggle:SetScript("OnUpdate", function() - if not this.dragging then return end - - local px, py = GetCursorPosition() - local scale = this:GetEffectiveScale() - px, py = px / scale, py / scale - raid.toggle:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", -8, py-32) + this:SetScript("OnUpdate", nil) end) end