Refactoring: Nampower Integration & SuperWoW Cleanup

* Replaced SuperWoW GUID with native Turtle WoW GUID in focus system
* Added memoization API for `/pfcast` and `/castfocus` performance boost
* Moved Druid mana bar from superwow.lua to nampower.lua
* Cleaned up superwow.lua - removed duplicate/migrated code
* Updated GUI: "Druid Settings" replaces "SuperWoW Settings" header
* Focus system now standalone - no SuperWoW dependency required
This commit is contained in:
Meow
2026-02-16 14:20:31 +01:00
parent 3cf64ceffd
commit def000a7c4
6 changed files with 477 additions and 488 deletions
-474
View File
@@ -23,14 +23,6 @@ SlashCmdList["PFDLLSTATUS"] = function()
chat:AddMessage(" |cffff0000Nampower|r: Not detected")
end
-- UnitXP
local hasUnitXP = pcall(UnitXP, "nop", "nop")
if hasUnitXP then
chat:AddMessage(" |cff00ff00UnitXP_SP3|r: Detected")
else
chat:AddMessage(" |cffff0000UnitXP_SP3|r: Not detected")
end
-- Check if castbar exists for indicator positioning
if pfUI.castbar and pfUI.castbar.player then
chat:AddMessage(" |cff00ff00Castbar|r: Available for indicator anchoring")
@@ -41,42 +33,11 @@ SlashCmdList["PFDLLSTATUS"] = function()
-- Check indicator frames
if pfUI.uf and pfUI.uf.target then
chat:AddMessage(" |cff00ff00Target frame|r: exists")
if pfUI.uf.target.behindIndicator then
chat:AddMessage(" |cff00ff00Behind indicator|r: created")
else
chat:AddMessage(" |cffff0000Behind indicator|r: NOT created")
end
if pfUI.uf.target.losIndicator then
chat:AddMessage(" |cff00ff00LOS indicator|r: created")
else
chat:AddMessage(" |cffff0000LOS indicator|r: NOT created")
end
else
chat:AddMessage(" |cffff0000Target frame|r: NOT found")
end
end
-- UnitXP Behind/LOS test command
SLASH_PFBEHIND1 = "/pfbehind"
SlashCmdList["PFBEHIND"] = function()
local chat = DEFAULT_CHAT_FRAME
if not UnitExists("target") then
chat:AddMessage("|cff33ffccpfUI|r: No target")
return
end
local hasUnitXP = pcall(UnitXP, "nop", "nop")
if not hasUnitXP then
chat:AddMessage("|cff33ffccpfUI|r: UnitXP not available")
return
end
local successB, behind = pcall(UnitXP, "behind", "player", "target")
local successL, inSight = pcall(UnitXP, "inSight", "player", "target")
chat:AddMessage("|cff33ffccpfUI|r: Behind=" .. tostring(behind) .. " LOS=" .. tostring(inSight))
end
pfUI:RegisterModule("superwow", "vanilla", function ()
if SetAutoloot and SpellInfo and not SUPERWOW_VERSION then
-- Turn every enchanting link that we create in the enchanting frame,
@@ -122,426 +83,6 @@ pfUI:RegisterModule("superwow", "vanilla", function ()
end)
end
-- Add native mouseover support
if SUPERWOW_VERSION and pfUI.uf and pfUI.uf.mouseover then
_G.SlashCmdList.PFCAST = function(msg)
local func = loadstring(msg or "")
local unit = "mouseover"
if not UnitExists(unit) then
local frame = GetMouseFocus()
if frame.label and frame.id then
unit = frame.label .. frame.id
elseif UnitExists("target") then
unit = "target"
elseif GetCVar("autoSelfCast") == "1" then
unit = "player"
else
return
end
end
if func then
-- set mouseover to target for script if needed
local switch_target = not UnitIsUnit("target", unit)
if switch_target then TargetUnit(unit) end
func()
if switch_target then TargetLastTarget() end
else
-- write temporary unit name
pfUI.uf.mouseover.unit = unit
-- cast spell to unitstr
CastSpellByName(msg, unit)
-- remove temporary mouseover unit
pfUI.uf.mouseover.unit = nil
end
end
end
-- Add support for druid mana bars
-- Uses Nampower's GetUnitField to get base mana when in shapeshift form
local hasNampower = (GetUnitField ~= nil)
-- Add support for player secondary power bar (shows base mana when in shapeshift form)
-- Works with SuperWoW OR Nampower - both extend UnitMana() to return base mana as second value
-- Only for Druids (only class that can shapeshift in Vanilla)
-- Controlled by "Show Druid Mana Bar" setting
local _, playerClass = UnitClass("player")
if hasNampower and pfUI.uf and pfUI.uf.player and playerClass == "DRUID" and pfUI_config.unitframes.druidmanabar == "1" then
local rawborder, default_border = GetBorderSize("unitframes")
local config = pfUI.uf.player.config
-- Create secondary mana bar below the power bar
local playerMana = CreateFrame("StatusBar", "pfPlayerSecondaryMana", pfUI.uf.player)
playerMana:SetFrameStrata(pfUI.uf.player:GetFrameStrata())
playerMana:SetFrameLevel(pfUI.uf.player:GetFrameLevel() + 5)
playerMana:SetStatusBarTexture(pfUI.media[config.pbartexture])
-- Mana color
local manacolor = config.defcolor == "0" and config.manacolor or C.unitframes.manacolor
local r, g, b, a = pfUI.api.strsplit(",", manacolor)
playerMana:SetStatusBarColor(r, g, b, a)
-- Use SAME size as normal power bar (pwidth/pheight from config)
local width = config.pwidth ~= "-1" and config.pwidth or config.width
local height = config.pheight
playerMana:SetWidth(width)
playerMana:SetHeight(height)
playerMana:SetPoint("TOPLEFT", pfUI.uf.player.power, "BOTTOMLEFT", 0, -2*default_border - (config.pspace or 0))
playerMana:SetPoint("TOPRIGHT", pfUI.uf.player.power, "BOTTOMRIGHT", 0, -2*default_border - (config.pspace or 0))
playerMana:Hide()
CreateBackdrop(playerMana)
CreateBackdropShadow(playerMana)
-- Text overlay - same font settings as power bar
local fontname = pfUI.font_unit
local fontsize = tonumber(pfUI_config.global.font_unit_size)
local fontstyle = pfUI_config.global.font_unit_style
if config.customfont == "1" then
fontname = pfUI.media[config.customfont_name]
fontsize = tonumber(config.customfont_size)
fontstyle = config.customfont_style
end
playerMana.text = playerMana:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
playerMana.text:SetFontObject(GameFontWhite)
playerMana.text:SetFont(fontname, fontsize, fontstyle)
playerMana.text:SetPoint("CENTER", playerMana, "CENTER", 0, 0)
-- Set text color like normal power bar (mana = type 0)
local tr, tg, tb = 1, 1, 1
if config["powercolor"] == "1" then
tr = ManaBarColor[0].r
tg = ManaBarColor[0].g
tb = ManaBarColor[0].b
end
if C.unitframes.pastel == "1" then
tr, tg, tb = (tr + .75) * .5, (tg + .75) * .5, (tb + .75) * .5
end
playerMana.text:SetTextColor(tr, tg, tb, 1)
-- Update function
local function UpdatePlayerSecondaryMana()
local powerType = UnitPowerType("player")
-- Only show when NOT using mana (i.e., in Bear/Cat form)
if powerType == 0 then
playerMana:Hide()
return
end
-- Get base mana using Nampower's GetUnitField
local baseMana, baseMaxMana
if GetUnitField then
local _, guid = UnitExists("player")
if guid then
baseMana = GetUnitField(guid, "power1")
baseMaxMana = GetUnitField(guid, "maxPower1")
end
end
-- Round down power values (Nampower can return decimals, especially for rage)
if baseMana then baseMana = math.floor(baseMana) end
if baseMaxMana then baseMaxMana = math.floor(baseMaxMana) end
if type(baseMana) ~= "number" or type(baseMaxMana) ~= "number" or baseMaxMana == 0 then
playerMana:Hide()
return
end
-- Update bar
playerMana:SetMinMaxValues(0, baseMaxMana)
playerMana:SetValue(baseMana)
-- Update text based on power text config (uses same setting as normal power bar)
-- Check txtpowercenter first (centered text), then txtpowerright, then txtpowerleft
local textConfig = config.txtpowercenter or config.txtpowerright or config.txtpowerleft
if not textConfig or textConfig == "" or textConfig == "none" then
-- No text configured - hide text
playerMana.text:SetText("")
elseif textConfig == "power" then
playerMana.text:SetText(Abbreviate(baseMana))
elseif textConfig == "powermax" then
playerMana.text:SetText(Abbreviate(baseMaxMana))
elseif textConfig == "powerperc" then
local perc = math.ceil(baseMana / baseMaxMana * 100)
playerMana.text:SetText(perc)
elseif textConfig == "powermiss" then
local miss = math.ceil(baseMana - baseMaxMana)
playerMana.text:SetText(miss == 0 and "0" or Abbreviate(miss))
elseif textConfig == "powerdyn" then
local perc = math.ceil(baseMana / baseMaxMana * 100)
if perc == 100 then
playerMana.text:SetText(Abbreviate(baseMana))
else
playerMana.text:SetText(string.format("%s - %s%%", Abbreviate(baseMana), perc))
end
elseif textConfig == "powerminmax" then
playerMana.text:SetText(string.format("%s/%s", Abbreviate(baseMana), Abbreviate(baseMaxMana)))
else
-- Default: show dynamic (value + percentage if not full)
local perc = math.ceil(baseMana / baseMaxMana * 100)
if perc == 100 then
playerMana.text:SetText(Abbreviate(baseMana))
else
playerMana.text:SetText(string.format("%s - %s%%", Abbreviate(baseMana), perc))
end
end
playerMana:Show()
end
-- Register events
playerMana:RegisterEvent("UNIT_MANA")
playerMana:RegisterEvent("UNIT_MAXMANA")
playerMana:RegisterEvent("UNIT_DISPLAYPOWER")
playerMana:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
playerMana:RegisterEvent("PLAYER_LOGOUT")
playerMana:SetScript("OnEvent", function()
-- Handle shutdown to prevent crash 132
if event == "PLAYER_LOGOUT" then
this:UnregisterAllEvents()
this:SetScript("OnEvent", nil)
return
end
if arg1 == nil or arg1 == "player" then
UpdatePlayerSecondaryMana()
end
end)
-- Initial update
UpdatePlayerSecondaryMana()
-- Store reference
pfUI.uf.player.secondaryMana = playerMana
end
-- Add support for target secondary power bar (shows base mana when target is in shapeshift form)
-- Works with SuperWoW OR Nampower - both extend UnitMana() to return base mana as second value
-- Controlled by "Show Druid Mana Bar" setting - available for ALL classes
if hasNampower and pfUI.uf and pfUI.uf.target and pfUI_config.unitframes.druidmanabar == "1" then
local rawborder, default_border = GetBorderSize("unitframes")
local config = pfUI.uf.target.config
-- Create secondary mana bar below the power bar
local targetMana = CreateFrame("StatusBar", "pfTargetSecondaryMana", pfUI.uf.target)
targetMana:SetFrameStrata(pfUI.uf.target:GetFrameStrata())
targetMana:SetFrameLevel(pfUI.uf.target:GetFrameLevel() + 5)
targetMana:SetStatusBarTexture(pfUI.media[config.pbartexture])
-- Mana color
local manacolor = config.defcolor == "0" and config.manacolor or C.unitframes.manacolor
local r, g, b, a = pfUI.api.strsplit(",", manacolor)
targetMana:SetStatusBarColor(r, g, b, a)
-- Use SAME size as normal power bar (pwidth/pheight from config)
local width = config.pwidth ~= "-1" and config.pwidth or config.width
local height = config.pheight -- Same height as power bar!
targetMana:SetWidth(width)
targetMana:SetHeight(height)
targetMana:SetPoint("TOPLEFT", pfUI.uf.target.power, "BOTTOMLEFT", 0, -2*default_border - (config.pspace or 0))
targetMana:SetPoint("TOPRIGHT", pfUI.uf.target.power, "BOTTOMRIGHT", 0, -2*default_border - (config.pspace or 0))
targetMana:Hide()
CreateBackdrop(targetMana)
CreateBackdropShadow(targetMana)
-- Text overlay - same font settings as power bar
local fontname = pfUI.font_unit
local fontsize = tonumber(pfUI_config.global.font_unit_size)
local fontstyle = pfUI_config.global.font_unit_style
if config.customfont == "1" then
fontname = pfUI.media[config.customfont_name]
fontsize = tonumber(config.customfont_size)
fontstyle = config.customfont_style
end
targetMana.text = targetMana:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
targetMana.text:SetFontObject(GameFontWhite)
targetMana.text:SetFont(fontname, fontsize, fontstyle)
targetMana.text:SetPoint("CENTER", targetMana, "CENTER", 0, 0)
-- Set text color like normal power bar (mana = type 0)
-- Uses powercolor setting and pastel effect
local function UpdateTextColor()
local tr, tg, tb = 1, 1, 1
if config["powercolor"] == "1" then
tr = ManaBarColor[0].r
tg = ManaBarColor[0].g
tb = ManaBarColor[0].b
end
if C.unitframes.pastel == "1" then
tr, tg, tb = (tr + .75) * .5, (tg + .75) * .5, (tb + .75) * .5
end
targetMana.text:SetTextColor(tr, tg, tb, 1)
end
UpdateTextColor()
-- Update function
local function UpdateTargetSecondaryMana()
if not UnitExists("target") then
targetMana:Hide()
return
end
local powerType = UnitPowerType("target")
-- Only show if target is NOT using mana (i.e., in shapeshift form with energy/rage)
if powerType == 0 then
-- Target is using mana as primary power - no need for secondary bar
targetMana:Hide()
return
end
-- Get base mana using Nampower's GetUnitField
local baseMana, baseMaxMana
if GetUnitField then
local _, guid = UnitExists("target")
if guid then
baseMana = GetUnitField(guid, "power1")
baseMaxMana = GetUnitField(guid, "maxPower1")
end
end
-- Round down power values (Nampower can return decimals, especially for rage)
if baseMana then baseMana = math.floor(baseMana) end
if baseMaxMana then baseMaxMana = math.floor(baseMaxMana) end
-- Check if we got valid mana values
if type(baseMana) ~= "number" or type(baseMaxMana) ~= "number" or baseMaxMana == 0 then
targetMana:Hide()
return
end
-- Update bar
targetMana:SetMinMaxValues(0, baseMaxMana)
targetMana:SetValue(baseMana)
-- Update text based on power text config (uses same setting as normal power bar)
local textConfig = config.txtpowercenter or config.txtpowerright or config.txtpowerleft
if not textConfig or textConfig == "" or textConfig == "none" then
targetMana.text:SetText("")
elseif textConfig == "power" then
targetMana.text:SetText(Abbreviate(baseMana))
elseif textConfig == "powermax" then
targetMana.text:SetText(Abbreviate(baseMaxMana))
elseif textConfig == "powerperc" then
local perc = math.ceil(baseMana / baseMaxMana * 100)
targetMana.text:SetText(perc)
elseif textConfig == "powermiss" then
local miss = math.ceil(baseMana - baseMaxMana)
targetMana.text:SetText(miss == 0 and "0" or Abbreviate(miss))
elseif textConfig == "powerdyn" then
local perc = math.ceil(baseMana / baseMaxMana * 100)
if perc == 100 then
targetMana.text:SetText(Abbreviate(baseMana))
else
targetMana.text:SetText(string.format("%s - %s%%", Abbreviate(baseMana), perc))
end
elseif textConfig == "powerminmax" then
targetMana.text:SetText(string.format("%s/%s", Abbreviate(baseMana), Abbreviate(baseMaxMana)))
else
local perc = math.ceil(baseMana / baseMaxMana * 100)
if perc == 100 then
targetMana.text:SetText(Abbreviate(baseMana))
else
targetMana.text:SetText(string.format("%s - %s%%", Abbreviate(baseMana), perc))
end
end
targetMana:Show()
end
-- Register events
targetMana:RegisterEvent("PLAYER_TARGET_CHANGED")
targetMana:RegisterEvent("UNIT_MANA")
targetMana:RegisterEvent("UNIT_MAXMANA")
targetMana:RegisterEvent("UNIT_DISPLAYPOWER")
targetMana:RegisterEvent("PLAYER_LOGOUT")
targetMana:SetScript("OnEvent", function()
-- Handle shutdown to prevent crash 132
if event == "PLAYER_LOGOUT" then
this:UnregisterAllEvents()
this:SetScript("OnEvent", nil)
return
end
if event == "PLAYER_TARGET_CHANGED" then
UpdateTargetSecondaryMana()
elseif arg1 == "target" then
UpdateTargetSecondaryMana()
end
end)
-- Store reference
pfUI.uf.target.secondaryMana = targetMana
end
-- Add support for guid based focus frame
if SUPERWOW_VERSION and pfUI.uf and pfUI.uf.focus then
local focus = function(unitstr)
-- try to read target's unit guid
local _, guid = UnitExists(unitstr)
if guid and pfUI.uf.focus then
-- update focus frame
pfUI.uf.focus.unitname = nil
pfUI.uf.focus.label = guid
pfUI.uf.focus.id = ""
-- update focustarget frame
pfUI.uf.focustarget.unitname = nil
pfUI.uf.focustarget.label = guid .. "target"
pfUI.uf.focustarget.id = ""
end
return guid
end
-- extend the builtin /focus slash command
local legacyfocus = SlashCmdList.PFFOCUS
function SlashCmdList.PFFOCUS(msg)
-- try to perform guid based focus
local guid = focus("target")
-- run old focus emulation
if not guid then legacyfocus(msg) end
end
-- extend the builtin /swapfocus slash command
local legacyswapfocus = SlashCmdList.PFSWAPFOCUS
function SlashCmdList.PFSWAPFOCUS(msg)
-- save previous focus values
local oldlabel = pfUI.uf.focus.label or ""
local oldid = pfUI.uf.focus.id or ""
-- try to perform guid based focus
local guid = focus("target")
-- target old focus
if guid and oldlabel and oldid then
TargetUnit(oldlabel..oldid)
end
-- run old focus emulation
if not guid then legacyswapfocus(msg) end
end
end
-- NOTE: SuperWoW libdebuff enhancement removed.
-- UNIT_CASTEVENT fires before resist/miss/dodge events arrive,
-- which breaks the failed spell detection system in libdebuff.
-- DoT timers use the standard hook-based fallback instead.
-- TrackUnit API for adding group members to minimap
-- Tracks friendly units on the minimap for easier group coordination
if TrackUnit and C.unitframes.track_group == "1" then
@@ -607,21 +148,6 @@ pfUI:RegisterModule("superwow", "vanilla", function ()
end
end
-- Enhanced SpellInfo API wrapper
if SpellInfo then
pfUI.api.GetSpellInfo = function(spellId)
local name, rank, texture, minRange, maxRange = SpellInfo(spellId)
return {
name = name,
rank = rank,
texture = texture,
minRange = minRange,
maxRange = maxRange,
spellId = spellId
}
end
end
-- Clickthrough Mode API
-- Allows clicking through corpses to loot underneath
if Clickthrough then