mirror of
https://github.com/brues-code/pfUI.git
synced 2026-09-27 01:46:03 +00:00
perf/fix: port experimental optimizations + focus rework + raidmarkers
Performance optimizations ported from experimental: - libdebuff: replace 5s startup timer with next-frame defer - libdebuff: use arg6 auraSlot directly (Nampower 2.29+) instead of GetDebuffSlotMap lookup - libdebuff: invalidate slotMapCache on PLAYER_TARGET_CHANGED - nameplates: detect Nampower 2.27.2+ for GUID-based nameplate lookup Raidmarkers module ported from experimental: - added raidmarkers.lua - added config defaults and GUI section - registered in modules.xml focus.lua rework: - removed CastSpellByNameNoQueue (Nampower's CastSpellByName now supports unit tokens/GUIDs natively) - /focus Name: TargetByName with correct previous target restore + ClearTarget() fallback - /focus Name: prefix match via SlashCmdList.TARGET when exact match fails - suppress UI_ERROR_MESSAGE during targeting attempts swingtimer fixes: - non-Hunter ranged bar now fills left->right like MH/OH - fix 1px artifact on Hunter bar center by using Hide() instead of SetWidth(0.1)
This commit is contained in:
@@ -241,6 +241,23 @@ function pfUI:LoadConfig()
|
||||
pfUI:UpdateConfig("unitframes", nil, "swingtimerrangedcolor",".3,.6,1,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "swingtimerrangedwarncolor",".9,0,0,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "swingtimerhsqueue","1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkerwidth", "80")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkerheight", "14")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkergrow", "down")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkertexture", "Interface\\AddOns\\pfUI\\img\\bar")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkerfontsize","12")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkershowname","1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkershowpct","1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkershownumhp","0")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkershowportrait","0")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_star", "1,.9,0,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_circle", "1,.5,0,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_diamond", ".8,0,.8,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_triangle", "0,.8,0,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_moon", ".7,.7,.7,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_square", "0,.4,.9,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_cross", ".9,0,0,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "raidmarkercolor_skull", "1,1,1,1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "abbrevnum", "1")
|
||||
pfUI:UpdateConfig("unitframes", nil, "castbardecimals", "2")
|
||||
pfUI:UpdateConfig("unitframes", nil, "abbrevname", "1")
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<Include file="..\modules\target.lua"/>
|
||||
<Include file="..\modules\combopoints.lua"/>
|
||||
<Include file="..\modules\swingtimer.lua"/>
|
||||
<Include file="..\modules\raidmarkers.lua"/>
|
||||
<Include file="..\modules\targettarget.lua"/>
|
||||
<Include file="..\modules\targettargettarget.lua"/>
|
||||
<Include file="..\modules\pet.lua"/>
|
||||
|
||||
+84
-97
@@ -44,95 +44,68 @@ if GetNampowerVersion then
|
||||
end
|
||||
end
|
||||
|
||||
-- Delayed Nampower version check (5 seconds after PLAYER_ENTERING_WORLD)
|
||||
-- Nampower startup check: show version info and ensure CVars are set.
|
||||
-- Runs on first OnUpdate after PLAYER_ENTERING_WORLD to give Nampower time to initialize.
|
||||
local nampowerCheckFrame = CreateFrame("Frame")
|
||||
local nampowerCheckTimer = 0
|
||||
local nampowerCheckDone = false
|
||||
nampowerCheckFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
nampowerCheckFrame:RegisterEvent("PLAYER_LOGOUT")
|
||||
nampowerCheckFrame:SetScript("OnEvent", function()
|
||||
-- Handle shutdown to prevent crash 132
|
||||
if event == "PLAYER_LOGOUT" then
|
||||
-- Defer to next frame so Nampower is fully initialized
|
||||
this:SetScript("OnUpdate", function()
|
||||
this:SetScript("OnUpdate", nil)
|
||||
this:UnregisterAllEvents()
|
||||
this:SetScript("OnEvent", nil)
|
||||
this:SetScript("OnUpdate", nil)
|
||||
return
|
||||
end
|
||||
|
||||
nampowerCheckFrame:SetScript("OnUpdate", function()
|
||||
nampowerCheckTimer = nampowerCheckTimer + arg1
|
||||
if nampowerCheckTimer >= 5 and not nampowerCheckDone then
|
||||
nampowerCheckDone = true
|
||||
|
||||
if GetNampowerVersion then
|
||||
local major, minor, patch = GetNampowerVersion()
|
||||
patch = patch or 0
|
||||
local versionString = major .. "." .. minor .. "." .. patch
|
||||
|
||||
if major > 2 or (major == 2 and minor > 38) or (major == 2 and minor == 38 and patch >= 0) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Nampower v" .. versionString .. " detected - GetUnitField mode enabled!")
|
||||
|
||||
-- Enable required Nampower CVars
|
||||
if SetCVar and GetCVar then
|
||||
local cvarsToEnable = {
|
||||
"NP_EnableSpellStartEvents",
|
||||
"NP_EnableSpellGoEvents",
|
||||
"NP_EnableAuraCastEvents",
|
||||
"NP_EnableAutoAttackEvents"
|
||||
}
|
||||
|
||||
local totalCvars = table.getn(cvarsToEnable)
|
||||
local enabledCount = 0
|
||||
local alreadyEnabledCount = 0
|
||||
local failedCount = 0
|
||||
|
||||
for _, cvar in ipairs(cvarsToEnable) do
|
||||
local success, currentValue = pcall(GetCVar, cvar)
|
||||
if success and currentValue then
|
||||
if currentValue == "1" then
|
||||
alreadyEnabledCount = alreadyEnabledCount + 1
|
||||
else
|
||||
local setSuccess = pcall(SetCVar, cvar, "1")
|
||||
if setSuccess then
|
||||
enabledCount = enabledCount + 1
|
||||
else
|
||||
failedCount = failedCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
if GetNampowerVersion then
|
||||
local major, minor, patch = GetNampowerVersion()
|
||||
patch = patch or 0
|
||||
local versionString = major .. "." .. minor .. "." .. patch
|
||||
|
||||
if major > 2 or (major == 2 and minor > 38) or (major == 2 and minor == 38 and patch >= 0) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Nampower v" .. versionString .. " detected - GetUnitField mode enabled!")
|
||||
|
||||
if SetCVar and GetCVar then
|
||||
local cvarsToEnable = {
|
||||
"NP_EnableSpellStartEvents",
|
||||
"NP_EnableSpellGoEvents",
|
||||
"NP_EnableAuraCastEvents",
|
||||
"NP_EnableAutoAttackEvents",
|
||||
}
|
||||
local enabledCount = 0
|
||||
local alreadyEnabledCount = 0
|
||||
local failedCount = 0
|
||||
|
||||
for _, cvar in ipairs(cvarsToEnable) do
|
||||
local success, currentValue = pcall(GetCVar, cvar)
|
||||
if success and currentValue then
|
||||
if currentValue == "1" then
|
||||
alreadyEnabledCount = alreadyEnabledCount + 1
|
||||
else
|
||||
failedCount = failedCount + 1
|
||||
local setSuccess = pcall(SetCVar, cvar, "1")
|
||||
if setSuccess then enabledCount = enabledCount + 1
|
||||
else failedCount = failedCount + 1 end
|
||||
end
|
||||
end
|
||||
|
||||
if enabledCount > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Enabled " .. enabledCount .. " Nampower CVars")
|
||||
end
|
||||
|
||||
if alreadyEnabledCount == totalCvars then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r All required Nampower CVars already enabled")
|
||||
elseif alreadyEnabledCount > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r " .. alreadyEnabledCount .. " CVars were already enabled")
|
||||
end
|
||||
|
||||
if failedCount > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00[libdebuff]|r Warning: Could not check/set " .. failedCount .. " CVars")
|
||||
else
|
||||
failedCount = failedCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
elseif major == 2 and minor == 38 and patch == 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00[libdebuff] WARNING: Nampower v2.38.0 detected!|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00[libdebuff] Please update to v2.38.0 or higher!|r")
|
||||
StaticPopup_Show("LIBDEBUFF_NAMPOWER_UPDATE", versionString)
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[libdebuff] Debuff tracking disabled! Please update Nampower to v2.38.0 or higher.|r")
|
||||
StaticPopup_Show("LIBDEBUFF_NAMPOWER_UPDATE", versionString)
|
||||
|
||||
if enabledCount > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Enabled " .. enabledCount .. " Nampower CVars")
|
||||
elseif alreadyEnabledCount == table.getn(cvarsToEnable) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r All required Nampower CVars already enabled")
|
||||
end
|
||||
if failedCount > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00[libdebuff]|r Warning: Could not check/set " .. failedCount .. " CVars")
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[libdebuff] Nampower not found! Debuff tracking disabled.|r")
|
||||
StaticPopup_Show("LIBDEBUFF_NAMPOWER_MISSING")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[libdebuff] Debuff tracking disabled! Please update Nampower to v2.38.0 or higher.|r")
|
||||
StaticPopup_Show("LIBDEBUFF_NAMPOWER_UPDATE", versionString)
|
||||
end
|
||||
|
||||
nampowerCheckFrame:SetScript("OnUpdate", nil)
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[libdebuff] Nampower not found! Debuff tracking disabled.|r")
|
||||
StaticPopup_Show("LIBDEBUFF_NAMPOWER_MISSING")
|
||||
end
|
||||
end)
|
||||
end)
|
||||
@@ -1588,10 +1561,14 @@ if hasNampower then
|
||||
|
||||
elseif event == "DEBUFF_ADDED_OTHER" then
|
||||
local guid = arg1
|
||||
local displaySlot = arg2 -- This is DISPLAY slot (1-16), NOT aura slot!
|
||||
local displaySlot = arg2 -- Display slot (1-16), compacted
|
||||
local spellId = arg3
|
||||
local stacks = arg4
|
||||
|
||||
local auraSlot_0based = arg6 -- Nampower 2.29+: raw slot 0-based (32-47)
|
||||
|
||||
-- Convert 0-based (Nampower event) to 1-based (Lua GetUnitField array)
|
||||
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
||||
|
||||
-- Invalidate slot map cache for this GUID
|
||||
slotMapCache[guid] = nil
|
||||
|
||||
@@ -1608,11 +1585,13 @@ if hasNampower then
|
||||
return
|
||||
end
|
||||
|
||||
-- Find the REAL aura slot (33-48) via GetUnitField
|
||||
local auraSlot = nil
|
||||
local slotMap = GetDebuffSlotMap(guid)
|
||||
if slotMap and slotMap[displaySlot] then
|
||||
auraSlot = slotMap[displaySlot].auraSlot
|
||||
-- Get auraSlot from event parameter (Nampower 2.29+)
|
||||
-- Fallback to GetUnitField lookup if not available
|
||||
if not auraSlot then
|
||||
local slotMap = GetDebuffSlotMap(guid)
|
||||
if slotMap and slotMap[displaySlot] then
|
||||
auraSlot = slotMap[displaySlot].auraSlot
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: Calculate aura slot if GetUnitField didn't work
|
||||
@@ -1714,9 +1693,13 @@ if hasNampower then
|
||||
|
||||
elseif event == "DEBUFF_REMOVED_OTHER" then
|
||||
local guid = arg1
|
||||
local displaySlot = arg2 -- This is DISPLAY slot (1-16), NOT aura slot!
|
||||
local displaySlot = arg2 -- Display slot (1-16), compacted
|
||||
local spellId = arg3
|
||||
|
||||
local auraSlot_0based = arg6 -- Nampower 2.29+: raw slot 0-based (32-47)
|
||||
|
||||
-- Convert 0-based (Nampower event) to 1-based (Lua GetUnitField array)
|
||||
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
||||
|
||||
-- Invalidate slot map cache for this GUID
|
||||
slotMapCache[guid] = nil
|
||||
|
||||
@@ -1725,8 +1708,8 @@ if hasNampower then
|
||||
if debugStats.enabled then
|
||||
debugStats.debuff_removed = debugStats.debuff_removed + 1
|
||||
if IsCurrentTarget(guid) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("%s |cffff9900[DEBUFF_REMOVED]|r display=%d %s",
|
||||
GetDebugTimestamp(), displaySlot, spellName))
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("%s |cffff9900[DEBUFF_REMOVED]|r display=%d aura=%d (0based=%d) %s",
|
||||
GetDebugTimestamp(), displaySlot, auraSlot or -1, auraSlot_0based or -1, spellName))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1736,15 +1719,17 @@ if hasNampower then
|
||||
return
|
||||
end
|
||||
|
||||
-- Find the auraSlot using displaySlot mapping
|
||||
-- Get auraSlot from event parameter (Nampower 2.29+)
|
||||
-- Fallback to displayToAura mapping if not available
|
||||
local foundAuraSlot = auraSlot
|
||||
if not foundAuraSlot and displayToAura[guid] and displayToAura[guid][displaySlot] then
|
||||
foundAuraSlot = displayToAura[guid][displaySlot]
|
||||
end
|
||||
|
||||
local wasOurs = false
|
||||
local removedCasterGuid = nil
|
||||
local foundAuraSlot = nil
|
||||
|
||||
-- Use displayToAura mapping to find the correct auraSlot
|
||||
if displayToAura[guid] and displayToAura[guid][displaySlot] then
|
||||
foundAuraSlot = displayToAura[guid][displaySlot]
|
||||
|
||||
|
||||
if foundAuraSlot then
|
||||
-- Get ownership info for this specific slot
|
||||
if slotOwnership[guid] and slotOwnership[guid][foundAuraSlot] then
|
||||
local ownership = slotOwnership[guid][foundAuraSlot]
|
||||
@@ -1761,7 +1746,7 @@ if hasNampower then
|
||||
end
|
||||
|
||||
if debugStats.enabled and IsCurrentTarget(guid) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("%s |cffff9900[SLOT CLEARED]|r aura=%d %s wasOurs=%s caster=%s",
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("%s |cffff9900[SLOT CLEARED]|r aura=%d [arg6] %s wasOurs=%s caster=%s",
|
||||
GetDebugTimestamp(), foundAuraSlot, spellName, tostring(wasOurs), DebugGuid(removedCasterGuid)))
|
||||
end
|
||||
end
|
||||
@@ -1796,11 +1781,13 @@ if hasNampower then
|
||||
end
|
||||
|
||||
elseif event == "PLAYER_TARGET_CHANGED" then
|
||||
-- Nothing special needed - GetUnitField will get fresh data on next query
|
||||
if not UnitExists then return end
|
||||
local _, targetGuid = UnitExists("target")
|
||||
|
||||
if targetGuid and targetGuid ~= "" then
|
||||
-- Invalidate slot map cache on retarget
|
||||
-- Prevents stale slot mappings after untarget/retarget cycles
|
||||
slotMapCache[targetGuid] = nil
|
||||
-- Cleanup expired timers for new target
|
||||
CleanupExpiredTimers(targetGuid)
|
||||
end
|
||||
|
||||
+1
-1
@@ -242,4 +242,4 @@ function SlashCmdList.PFSWAPFOCUS(msg)
|
||||
pfUI.uf.focus.unitname = oldunit
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1032,6 +1032,10 @@ pfUI:RegisterModule("gui", "vanilla:tbc", function ()
|
||||
"default:" .. T["Default"],
|
||||
"tukui:TukUI"
|
||||
},
|
||||
["raidmarker_grow"] = {
|
||||
"down:Down",
|
||||
"up:Up",
|
||||
},
|
||||
["uf_color"] = {
|
||||
"0:" .. T["Class"],
|
||||
"1:" .. T["Custom"],
|
||||
@@ -1969,6 +1973,24 @@ pfUI:RegisterModule("gui", "vanilla:tbc", function ()
|
||||
CreateConfig(nil, T["Ranged Warn Color (Hunter)"], C.unitframes, "swingtimerrangedwarncolor", "color")
|
||||
CreateConfig(nil, T["Show HS/Cleave Queue Color (Warrior)"], C.unitframes, "swingtimerhsqueue", "checkbox")
|
||||
|
||||
CreateConfig(nil, "Raid Markers", nil, nil, "header")
|
||||
CreateConfig(nil, "Raid Marker Width", C.unitframes, "raidmarkerwidth")
|
||||
CreateConfig(nil, "Raid Marker Height", C.unitframes, "raidmarkerheight")
|
||||
CreateConfig(nil, "Raid Marker Grow", C.unitframes, "raidmarkergrow", "dropdown", pfUI.gui.dropdowns.raidmarker_grow)
|
||||
CreateConfig(nil, "Raid Marker Texture", C.unitframes, "raidmarkertexture", "dropdown", pfUI.gui.dropdowns.uf_bartexture)
|
||||
CreateConfig(nil, "Raid Marker Font Size", C.unitframes, "raidmarkerfontsize")
|
||||
CreateConfig(nil, "Show Name", C.unitframes, "raidmarkershowname", "checkbox")
|
||||
CreateConfig(nil, "Show Percent HP", C.unitframes, "raidmarkershowpct", "checkbox")
|
||||
CreateConfig(nil, "Show Portrait", C.unitframes, "raidmarkershowportrait", "checkbox")
|
||||
CreateConfig(nil, "Star Color", C.unitframes, "raidmarkercolor_star", "color")
|
||||
CreateConfig(nil, "Circle Color", C.unitframes, "raidmarkercolor_circle", "color")
|
||||
CreateConfig(nil, "Diamond Color", C.unitframes, "raidmarkercolor_diamond", "color")
|
||||
CreateConfig(nil, "Triangle Color", C.unitframes, "raidmarkercolor_triangle", "color")
|
||||
CreateConfig(nil, "Moon Color", C.unitframes, "raidmarkercolor_moon", "color")
|
||||
CreateConfig(nil, "Square Color", C.unitframes, "raidmarkercolor_square", "color")
|
||||
CreateConfig(nil, "Cross Color", C.unitframes, "raidmarkercolor_cross", "color")
|
||||
CreateConfig(nil, "Skull Color", C.unitframes, "raidmarkercolor_skull", "color")
|
||||
|
||||
CreateConfig(U[c], T["Font Options"], nil, nil, "header")
|
||||
CreateConfig(nil, T["Unit Frame Text Font"], C.global, "font_unit", "dropdown", pfUI.gui.dropdowns.fonts)
|
||||
CreateConfig(nil, T["Unit Frame Text Size"], C.global, "font_unit_size")
|
||||
|
||||
+15
-2
@@ -2,8 +2,21 @@ pfUI:RegisterModule("nameplates", "vanilla", function ()
|
||||
-- disable original castbars
|
||||
pcall(SetCVar, "ShowVKeyCastbar", 0)
|
||||
|
||||
-- check for SuperWoW support (use SUPERWOW_VERSION global)
|
||||
local superwow_active = SUPERWOW_VERSION ~= nil
|
||||
-- Check for Nampower support (preferred)
|
||||
local hasNampower = false
|
||||
if GetNampowerVersion then
|
||||
local major, minor, patch = GetNampowerVersion()
|
||||
patch = patch or 0
|
||||
if major > 2 or (major == 2 and minor > 27) or (major == 2 and minor == 27 and patch >= 2) then
|
||||
hasNampower = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for SuperWoW support (fallback)
|
||||
local hasSuperwow = SUPERWOW_VERSION ~= nil
|
||||
|
||||
-- Use either Nampower or SuperWoW for GetName(1) GUID support
|
||||
local superwow_active = hasNampower or hasSuperwow
|
||||
|
||||
-- Local function references for performance
|
||||
local GetTime = GetTime
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
pfUI:RegisterModule("raidmarkers", "vanilla:tbc", function ()
|
||||
-- Requires mark1-mark8 unit tokens (Turtle WoW / Nampower)
|
||||
if not UnitExists("mark1") and not UnitExists("mark8") then
|
||||
if not pcall(function() UnitExists("mark1") end) then return end
|
||||
end
|
||||
|
||||
local rawborder, border = GetBorderSize()
|
||||
|
||||
-- Parse color strings "r,g,b,a" into components
|
||||
local function ParseColor(str, dr, dg, db, da)
|
||||
if not str or str == "" then return dr, dg, db, da end
|
||||
local _, _, r, g, b, a = string.find(str, "([%d%.]+),([%d%.]+),([%d%.]+),([%d%.]+)")
|
||||
if r then
|
||||
return tonumber(r) or dr, tonumber(g) or dg, tonumber(b) or db, tonumber(a) or da
|
||||
end
|
||||
return dr, dg, db, da
|
||||
end
|
||||
|
||||
local markerOrder = { 8, 7, 6, 5, 4, 3, 2, 1 } -- skull, cross, square, moon, triangle, diamond, circle, star
|
||||
local markerTokens = {}
|
||||
for i = 1, 8 do markerTokens[i] = "mark" .. i end
|
||||
|
||||
-- Default colors per marker
|
||||
local defaultColors = {
|
||||
[1] = { 1.0, 0.9, 0.0, 1 }, -- star: yellow
|
||||
[2] = { 1.0, 0.5, 0.0, 1 }, -- circle: orange
|
||||
[3] = { 0.8, 0.0, 0.8, 1 }, -- diamond: purple
|
||||
[4] = { 0.0, 0.8, 0.0, 1 }, -- triangle: green
|
||||
[5] = { 0.7, 0.7, 0.7, 1 }, -- moon: silver
|
||||
[6] = { 0.0, 0.4, 0.9, 1 }, -- square: blue
|
||||
[7] = { 0.9, 0.0, 0.0, 1 }, -- cross: red
|
||||
[8] = { 1.0, 1.0, 1.0, 1 }, -- skull: white
|
||||
}
|
||||
|
||||
local markerConfigKeys = {
|
||||
[1] = "raidmarkercolor_star",
|
||||
[2] = "raidmarkercolor_circle",
|
||||
[3] = "raidmarkercolor_diamond",
|
||||
[4] = "raidmarkercolor_triangle",
|
||||
[5] = "raidmarkercolor_moon",
|
||||
[6] = "raidmarkercolor_square",
|
||||
[7] = "raidmarkercolor_cross",
|
||||
[8] = "raidmarkercolor_skull",
|
||||
}
|
||||
|
||||
local markerColors = {}
|
||||
for i = 1, 8 do
|
||||
local d = defaultColors[i]
|
||||
local r, g, b, a = ParseColor(C.unitframes[markerConfigKeys[i]], d[1], d[2], d[3], d[4])
|
||||
markerColors[i] = { r, g, b, a }
|
||||
end
|
||||
|
||||
local FALLBACK_INTERVAL = 1.0 -- safety net for units that come into range after marker was set
|
||||
local elapsed = 0
|
||||
local isUnlocked = false
|
||||
local ROW_HEIGHT = tonumber(C.unitframes.raidmarkerheight) or 14
|
||||
local BAR_WIDTH = tonumber(C.unitframes.raidmarkerwidth) or 80
|
||||
local GROW = C.unitframes.raidmarkergrow or "down"
|
||||
local rm_texture = C.unitframes.raidmarkertexture or "Interface\\AddOns\\pfUI\\img\\bar"
|
||||
local rm_fontsize = tonumber(C.unitframes.raidmarkerfontsize) or 12
|
||||
local rm_showpct = C.unitframes.raidmarkershowpct ~= "0"
|
||||
local rm_showname = C.unitframes.raidmarkershowname ~= "0"
|
||||
local rm_showportrait = C.unitframes.raidmarkershowportrait ~= "0"
|
||||
local PORTRAIT_SIZE = ROW_HEIGHT
|
||||
|
||||
-- Cache for shortened names: markerIndex -> { name, short }
|
||||
local nameCache = {}
|
||||
|
||||
local function ShortenName(name, row)
|
||||
if not name or name == "" then return "" end
|
||||
local barWidth = row.health:GetWidth()
|
||||
if barWidth < 1 then barWidth = BAR_WIDTH end
|
||||
local available = barWidth - 4
|
||||
if rm_showpct then available = available - 32 end
|
||||
if available < 10 then return nil end
|
||||
row.nametext:SetText(name)
|
||||
if row.nametext:GetStringWidth() <= available then return name end
|
||||
for len = strlen(name) - 1, 1, -1 do
|
||||
local short = strsub(name, 1, len) .. "."
|
||||
row.nametext:SetText(short)
|
||||
if row.nametext:GetStringWidth() <= available then return short end
|
||||
end
|
||||
return strsub(name, 1, 1) .. "."
|
||||
end
|
||||
|
||||
local TOTAL_ROW_WIDTH = BAR_WIDTH + 20 + (rm_showportrait and (PORTRAIT_SIZE + 2) or 0)
|
||||
|
||||
-- Container frame
|
||||
pfUI.raidmarkers = CreateFrame("Frame", "pfMarkerTracker", UIParent)
|
||||
pfUI.raidmarkers:SetFrameStrata("MEDIUM")
|
||||
if GROW == "up" then
|
||||
pfUI.raidmarkers:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -20, 200)
|
||||
else
|
||||
pfUI.raidmarkers:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -20, -200)
|
||||
end
|
||||
pfUI.raidmarkers:SetWidth(TOTAL_ROW_WIDTH)
|
||||
pfUI.raidmarkers:SetHeight(8 * (ROW_HEIGHT + 1) + border * 2 - 1)
|
||||
pfUI.raidmarkers:Hide()
|
||||
|
||||
CreateBackdrop(pfUI.raidmarkers)
|
||||
CreateBackdropShadow(pfUI.raidmarkers)
|
||||
UpdateMovable(pfUI.raidmarkers)
|
||||
|
||||
pfUI.raidmarkers:SetScript("OnMouseUp", function()
|
||||
if pfUI.unlock and pfUI.unlock:IsShown() then
|
||||
this:StopMovingOrSizing()
|
||||
local _, _, _, x, y = this:GetPoint()
|
||||
this:ClearAllPoints()
|
||||
this:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", math.floor(x + 0.5), math.floor(y + 0.5))
|
||||
C.position["pfMarkerTracker"] = C.position["pfMarkerTracker"] or {}
|
||||
C.position["pfMarkerTracker"]["anchor"] = "BOTTOMRIGHT"
|
||||
C.position["pfMarkerTracker"]["xpos"] = math.floor(x + 0.5)
|
||||
C.position["pfMarkerTracker"]["ypos"] = math.floor(y + 0.5)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Create 8 marker rows
|
||||
pfUI.raidmarkers.rows = {}
|
||||
for idx = 1, 8 do
|
||||
local i = markerOrder[idx]
|
||||
|
||||
local row = CreateFrame("Button", nil, pfUI.raidmarkers)
|
||||
row:SetWidth(TOTAL_ROW_WIDTH)
|
||||
row:SetHeight(ROW_HEIGHT)
|
||||
row:Hide()
|
||||
|
||||
row:RegisterForClicks("LeftButtonUp")
|
||||
row:SetScript("OnClick", function()
|
||||
TargetUnit(markerTokens[this.markerIndex])
|
||||
end)
|
||||
|
||||
-- raid icon
|
||||
row.icon = row:CreateTexture(nil, "ARTWORK")
|
||||
row.icon:SetWidth(ROW_HEIGHT)
|
||||
row.icon:SetHeight(ROW_HEIGHT)
|
||||
row.icon:SetPoint("LEFT", row, "LEFT", 1, 0)
|
||||
row.icon:SetTexture(pfUI.media["img:raidicons"])
|
||||
SetRaidTargetIconTexture(row.icon, i)
|
||||
|
||||
-- portrait (right side)
|
||||
row.portrait = row:CreateTexture(nil, "ARTWORK")
|
||||
row.portrait:SetWidth(PORTRAIT_SIZE)
|
||||
row.portrait:SetHeight(PORTRAIT_SIZE)
|
||||
row.portrait:SetPoint("RIGHT", row, "RIGHT", -1, 0)
|
||||
row.portrait:SetTexCoord(.1, .9, .1, .9)
|
||||
if not rm_showportrait then row.portrait:Hide() end
|
||||
|
||||
-- health bar
|
||||
row.health = CreateFrame("StatusBar", nil, row)
|
||||
row.health:SetPoint("LEFT", row.icon, "RIGHT", 2, 0)
|
||||
if rm_showportrait then
|
||||
row.health:SetPoint("RIGHT", row.portrait, "LEFT", -2, 0)
|
||||
else
|
||||
row.health:SetPoint("RIGHT", row, "RIGHT", -1, 0)
|
||||
end
|
||||
row.health:SetHeight(ROW_HEIGHT)
|
||||
row.health:SetMinMaxValues(0, 1)
|
||||
row.health:SetValue(1)
|
||||
row.health:SetStatusBarTexture(rm_texture)
|
||||
local c = markerColors[i]
|
||||
row.health:SetStatusBarColor(c[1] * 0.5, c[2] * 0.5, c[3] * 0.5, c[4] or 0.9)
|
||||
|
||||
-- name text (left)
|
||||
row.nametext = row.health:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
row.nametext:SetPoint("LEFT", row.health, "LEFT", 2, 0)
|
||||
row.nametext:SetFont(pfUI.font_default, rm_fontsize, "OUTLINE")
|
||||
row.nametext:SetTextColor(1, 1, 1, 1)
|
||||
row.nametext:SetJustifyH("LEFT")
|
||||
row.nametext:SetText("")
|
||||
if not rm_showname then row.nametext:Hide() end
|
||||
|
||||
-- hp text (right)
|
||||
row.hptext = row.health:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
row.hptext:SetPoint("RIGHT", row.health, "RIGHT", -2, 0)
|
||||
row.hptext:SetFont(pfUI.font_default, rm_fontsize, "OUTLINE")
|
||||
row.hptext:SetTextColor(1, 1, 1, 1)
|
||||
row.hptext:SetJustifyH("RIGHT")
|
||||
row.hptext:SetText("")
|
||||
if not rm_showpct then row.hptext:Hide() end
|
||||
|
||||
CreateBackdrop(row.health)
|
||||
|
||||
row.markerIndex = i
|
||||
row.label = "mark" -- enables /pfcast mouseover support via GetMouseFocus()
|
||||
row.id = i
|
||||
pfUI.raidmarkers.rows[i] = row
|
||||
end
|
||||
|
||||
local function UpdateDisplay()
|
||||
if isUnlocked then return end
|
||||
local anyActive = false
|
||||
local visibleCount = 0
|
||||
local prevRow
|
||||
|
||||
for idx = 1, 8 do
|
||||
local i = markerOrder[idx]
|
||||
local row = pfUI.raidmarkers.rows[i]
|
||||
local token = markerTokens[i]
|
||||
|
||||
if UnitExists(token) and not UnitIsDead(token) then
|
||||
local hp = UnitHealth(token)
|
||||
local maxhp = UnitHealthMax(token)
|
||||
|
||||
if hp and maxhp and maxhp > 0 and hp > 0 then
|
||||
local pct = hp / maxhp
|
||||
row.health:SetValue(pct)
|
||||
|
||||
if rm_showname then
|
||||
local name = UnitName(token)
|
||||
local cached = nameCache[i]
|
||||
if not cached or cached.name ~= name then
|
||||
local short = ShortenName(name, row)
|
||||
if short then
|
||||
nameCache[i] = { name = name, short = short }
|
||||
end
|
||||
end
|
||||
row.nametext:SetText(nameCache[i] and nameCache[i].short or "")
|
||||
end
|
||||
|
||||
if rm_showpct then
|
||||
row.hptext:SetText(math.floor(pct * 100) .. "%")
|
||||
end
|
||||
|
||||
if rm_showportrait then
|
||||
SetPortraitTexture(row.portrait, token)
|
||||
end
|
||||
|
||||
row:ClearAllPoints()
|
||||
if GROW == "up" then
|
||||
if prevRow then
|
||||
row:SetPoint("BOTTOM", prevRow, "TOP", 0, 1)
|
||||
else
|
||||
row:SetPoint("BOTTOM", pfUI.raidmarkers, "BOTTOM", 0, border)
|
||||
end
|
||||
else
|
||||
if prevRow then
|
||||
row:SetPoint("TOP", prevRow, "BOTTOM", 0, -1)
|
||||
else
|
||||
row:SetPoint("TOP", pfUI.raidmarkers, "TOP", 0, -border)
|
||||
end
|
||||
end
|
||||
row:Show()
|
||||
prevRow = row
|
||||
anyActive = true
|
||||
visibleCount = visibleCount + 1
|
||||
else
|
||||
row:Hide()
|
||||
end
|
||||
else
|
||||
nameCache[i] = nil
|
||||
row:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if anyActive then
|
||||
pfUI.raidmarkers:SetHeight(visibleCount * (ROW_HEIGHT + 1) + border * 2 - 1)
|
||||
pfUI.raidmarkers:Show()
|
||||
elseif not (pfUI.unlock and pfUI.unlock:IsShown()) then
|
||||
pfUI.raidmarkers:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- Unlock mode: show fixed 1-row placeholder so positioning works correctly
|
||||
if pfUI.unlock then
|
||||
local origShow = pfUI.unlock:GetScript("OnShow")
|
||||
pfUI.unlock:SetScript("OnShow", function()
|
||||
if origShow then origShow() end
|
||||
isUnlocked = true
|
||||
-- hide all rows, show container at 1-row height as drag handle
|
||||
for i = 1, 8 do
|
||||
pfUI.raidmarkers.rows[i]:Hide()
|
||||
end
|
||||
pfUI.raidmarkers:SetHeight(ROW_HEIGHT + border * 2)
|
||||
pfUI.raidmarkers:Show()
|
||||
end)
|
||||
|
||||
local origHide = pfUI.unlock:GetScript("OnHide")
|
||||
pfUI.unlock:SetScript("OnHide", function()
|
||||
if origHide then origHide() end
|
||||
isUnlocked = false
|
||||
UpdateDisplay()
|
||||
end)
|
||||
end
|
||||
|
||||
-- Event-driven scanner frame
|
||||
local scanner = CreateFrame("Frame")
|
||||
|
||||
-- RAID_TARGET_UPDATE: fires when a raid marker is set/cleared
|
||||
-- PLAYER_ENTERING_WORLD: fires on login, reload, and zone transitions
|
||||
scanner:RegisterEvent("RAID_TARGET_UPDATE")
|
||||
scanner:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
|
||||
scanner:SetScript("OnEvent", function()
|
||||
UpdateDisplay()
|
||||
end)
|
||||
|
||||
-- Fallback poll at 1s: catches units that come into range AFTER a marker was set
|
||||
-- (no event fires for that case, so we need this safety net)
|
||||
scanner:SetScript("OnUpdate", function()
|
||||
elapsed = elapsed + arg1
|
||||
if elapsed < FALLBACK_INTERVAL then return end
|
||||
elapsed = 0
|
||||
UpdateDisplay()
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user