Files
Brues f497c71523 Filter unit events to their units, rework energytick, drop macrotweak
Eight commits off classicapi_next.

ClassicAPI's RegisterUnitEvent registers for an event but only delivers it
when arg1 is one of the given units, so a handler for one unit stops waking
for every other one in the world. The 26 registrations whose unit set is
fixed at registration time now name it. The rule throughout is register the
superset and keep the handler's own check -- the filter narrows what arrives,
it does not decide what to act on. Guards that look unreachable stay put: the
filter applies only when arg1 is a string, so an event that fires with a
number or no argument is delivered as if plainly registered.

Frames whose unit changes at runtime own their subscriptions instead of
sorting events out per event. unitframes points them at the unitstr
UpdateVisibility already computes -- replacing a string concat, and on a miss
a second concat plus a UnitGUID call, for every frame on every unit event in
the world -- and a frame that is not in use drops its unit events entirely.
nameplates registers per plate against the plate's own token, which is also
the only workable shape: slots have no cap, so any nameplate1..N list would
have been a guess that fails in exactly the crowded scenes where plates
matter. marktracking names mark1 through mark8. A registration keeps its
kind, so none of these can be plain-registered first.

Both teardown paths PLAYER_LOGOUT guards -- the crash 132 -- now cover the
per-frame subscriptions: plates tear down rather than dispatching through
logout, and a unit frame takes itself off the visibility scan so it cannot
re-register what it just dropped.

marktracking also drops its once-a-second full rebuild, which ran for the
whole session whether or not a marker existed anywhere. The ticker is created
and cancelled with group membership. It is deliberately not keyed on a mark
being visible -- a marker on an out-of-range unit shows no row, and that is
the case the poll exists to catch.

nameplates gates the per-plate update against the floor across all four
throttle categories before classifying it, instead of running a GetAlpha, a
castbar IsShown, a cast lookup and up to two libthrottle:Get resolutions on
plates throttled to 10fps that were going to return anyway. Nothing that
would have updated can be turned away by a floor. The four throttles resolve
in CacheConfig, where config changes already land.

energytick sweeps the clock the server actually runs. There is one regen
timer for every power, re-armed every 2s by Player::RegenerateAll and never
touched by casting; the five-second rule changes what a tick pays, not when
it lands. The sweep is a free-running phase lock on that clock, so
Illumination refunds, potions and a Mana Spring totem on its own phase no
longer snap the spark mid-cycle, and an 80ms band keeps a correct tick from
hitching it at the wrap. The FSR window shades rather than predicting a share
of spirit the client cannot compute -- the Casting Regen item ladder is equip
auras absent from the buff list. The energy period is summed from
SPELL_AURA_MOD_ENERGY_REGEN_TIME across the spellbook and buffs, so Blade
Rush is found without GetTalentInfo(2, 16), an ordinal that does not fail
when the tree changes but reads another talent's rank.

macrotweak is gone -- ClassicAPI 1.15 covers it -- with its config entry, its
GUI block, its translations in all eight locales, and actionbar's
ButtonMacroScan, the #showtooltip scanner that fed it.
2026-09-11 00:10:51 -05:00

825 lines
32 KiB
Lua

pfUI:RegisterModule("panel", function()
-- initialize gold cache if not yet happened
pfUI_cache["gold"] = pfUI_cache["gold"] or {}
local font = C.panel.use_unitfonts == "1" and pfUI.font_unit or pfUI.font_default
local font_size = C.panel.use_unitfonts == "1" and C.global.font_unit_size or C.global.font_size
local rawborder, default_border = GetBorderSize("panels")
do -- Widgets
do -- Clock & Timer
local widget = CreateFrame("Frame", "pfPanelWidgetClock",UIParent)
widget.Tooltip = function()
GameTooltip:ClearLines()
GameTooltip_SetDefaultAnchor(GameTooltip, this)
local fmt = C.global.twentyfour == "0" and "%I:%M %p" or "%H:%M"
local time = date(fmt)
local servertime = date(fmt, GetServerEpoch())
GameTooltip:AddLine("|cff555555" .. T["Time"])
GameTooltip:AddDoubleLine(T["Localtime"], "|cffffffff" .. time)
GameTooltip:AddDoubleLine(T["Servertime"], "|cffffffff".. servertime)
GameTooltip:AddLine(" ")
if TimeManagerFrame then
GameTooltip:AddDoubleLine(T["Left Click"], "|cffffffff" .. T["Show/Hide TimeManager"])
else
GameTooltip:AddDoubleLine(T["Left Click"], "|cffffffff" .. T["Show/Hide Timer"])
GameTooltip:AddDoubleLine(T["Right Click"], "|cffffffff" .. T["Reset Timer"])
end
GameTooltip:Show()
end
widget.Click = function()
this:RegisterForClicks("LeftButtonUp", "RightButtonUp")
if TimeManagerFrame then
if TimeManagerClockButton.alarmFiring then
TimeManager_TurnOffAlarm()
end
ToggleTimeManager()
return
end
if arg1 == "LeftButton" then
widget.timerFrame:SetShown(not widget.timerFrame:IsShown())
elseif arg1 == "RightButton" then
widget.timerFrame.Snapshot = GetTime()
end
end
C_Timer.NewTicker(1, function()
local secondsenabled = C.panel.seconds == "1"
local fmt
if C.global.twentyfour == "0" then
fmt = secondsenabled and "%I:%M:%S %p" or "%I:%M %p"
else
fmt = secondsenabled and "%H:%M:%S" or "%H:%M"
end
local time = C.global.servertime == "1" and date(fmt, GetServerEpoch()) or date(fmt)
pfUI.panel:OutputPanel("time", time, widget.Tooltip, widget.Click)
end)
widget.timerFrame = CreateFrame("Frame", "pfUITimer", UIParent)
widget.timerFrame:Hide()
widget.timerFrame:SetSize(120, 35)
widget.timerFrame:SetPoint("TOP", 0, -100)
UpdateMovable(widget.timerFrame)
widget.timerFrame.text = widget.timerFrame:CreateFontString("Status", "LOW", "GameFontNormal")
widget.timerFrame.text:SetFontObject(GameFontWhite)
widget.timerFrame.text:SetFont(font, font_size, "OUTLINE")
widget.timerFrame.text:SetAllPoints(widget.timerFrame)
widget.timerFrame:SetScript("OnUpdate", function()
if not widget.timerFrame.Snapshot then widget.timerFrame.Snapshot = GetTime() end
widget.timerFrame.curTime = SecondsToTime(floor(GetTime() - widget.timerFrame.Snapshot))
if widget.timerFrame.curTime ~= "" then
widget.timerFrame.text:SetText("|c33cccccc" .. widget.timerFrame.curTime)
else
widget.timerFrame.text:SetText("|cffff3333 --- " .. T["NEW TIMER"] .. " ---")
end
end)
-- Combat Timer
widget.combat = CreateFrame("Frame", "pfUICombatTimer", UIParent)
widget.combat:RegisterEvent("PLAYER_ENTERING_WORLD")
widget.combat:RegisterEvent("PLAYER_REGEN_ENABLED")
widget.combat:RegisterEvent("PLAYER_REGEN_DISABLED")
widget.combat:SetScript("OnEvent", function()
if event == "PLAYER_REGEN_DISABLED" then
if UnitAffectingCombat("player") and not this.combat then
this.combat = GetTime()
end
elseif event == "PLAYER_REGEN_ENABLED" then
if this.combat then
this.lastcombat = GetTime() - this.combat
this.combat = nil
pfUI.panel:OutputPanel("combat", "|cffffffff" .. SecondsToTime(ceil(this.lastcombat)))
end
elseif event == "PLAYER_ENTERING_WORLD" then
pfUI.panel:OutputPanel("combat", T["Combat"] .. ": " .. NOT_APPLICABLE)
end
end)
C_Timer.NewTicker(1, function()
if widget.combat.combat then
pfUI.panel:OutputPanel("combat", "|cffffaaaa" .. SecondsToTime(ceil(GetTime() - widget.combat.combat)))
end
end)
end
do -- FPS & Lag
local widget = CreateFrame("Frame", "pfPanelWidgetLag", UIParent)
local lag, fps, laghex, fpshex, _
widget.Tooltip = function()
local active = 0
GameTooltip:ClearLines()
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:AddLine("|cff555555" .. T["Systeminfo"])
for i=1, GetNumAddOns() do
if IsAddOnLoaded(i) then
active = active + 1
end
end
local memkb, gckb = gcinfo()
local memmb = memkb and memkb > 0 and round((memkb or 0)/1000, 2) .. " MB" or UNAVAILABLE
local gcmb = gckb and gckb > 0 and round((gckb or 0)/1000, 2) .. " MB" or UNAVAILABLE
local nin, nout, nping = GetNetStats()
GameTooltip:AddDoubleLine(T["Active Addons"], "|cffffffff" .. active .. "|cff555555 / |cffffffff" .. GetNumAddOns())
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(T["Memory Usage"], "|cffffffff" .. memmb)
GameTooltip:AddDoubleLine(T["Next Memory Cleanup"], "|cffffffff" .. gcmb)
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(T["Network Down"], "|cffffffff" .. round(nin,1) .. "KB/s")
GameTooltip:AddDoubleLine(T["Network Up"], "|cffffffff" .. round(nout,1) .. "KB/s")
GameTooltip:AddDoubleLine(T["Network Latency"], "|cffffffff" .. nping .. "ms")
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(T["Graphic Renderer"], "|cffffffff" .. GetCVar("gxApi"))
GameTooltip:AddDoubleLine(T["Screen Resolution"], "|cffffffff" .. GetCVar("gxResolution"))
GameTooltip:AddDoubleLine(T["UI-Scale"], "|cffffffff" .. round(UIParent:GetEffectiveScale(),2))
GameTooltip:Show()
end
widget.Click = function()
if pfUI.addons and pfUI.addons:IsShown() then
pfUI.addons:Hide()
elseif pfUI.addons then
pfUI.addons:Show()
end
end
C_Timer.NewTicker(1, function()
fps = floor(GetFramerate())
_, _, lag = GetNetStats()
if C.panel.fpscolors == "1" then
_, _, _, fpshex = GetColorGradient(fps > 0 and fps/60 or 0)
_, _, _, laghex = GetColorGradient(lag > 0 and 60/lag or 0)
fps = fpshex .. fps .. "|r"
lag = laghex .. lag .. "|r"
end
pfUI.panel:OutputPanel("fps", fps .. " " .. T["fps"] .. " & " .. lag .. " " .. T["ms"], widget.Tooltip, widget.Click)
end)
end
do -- XP & Kills To Level
local widget = CreateFrame("Frame", "pfPanelWidgetXP", UIParent)
local curexp, difexp, maxexp, remexp, oldexp, remstring
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("PLAYER_XP_UPDATE")
widget:SetScript("OnEvent", function()
if UnitLevel("player") < _G.MAX_PLAYER_LEVEL then
curexp = UnitXP("player")
if oldexp ~= nil then
difexp = curexp - oldexp
maxexp = UnitXPMax("player")
if difexp > 0 then
remexp = floor((maxexp - curexp)/difexp)
remstring = "|cff555555 [" .. remexp .. "]|r"
else
remstring = nil
end
end
oldexp = curexp
local a=UnitXP("player")
local b=UnitXPMax("player")
local xprested = tonumber(GetXPExhaustion())
if remstring == nil then remstring = "" end
if xprested ~= nil then
pfUI.panel:OutputPanel("exp", T["Exp"] .. ": |cffaaaaff"..floor((a/b)*100).."%"..remstring)
else
pfUI.panel:OutputPanel("exp", T["Exp"] .. ": " .. floor((a/b)*100) .. "%" .. remstring)
end
else
pfUI.panel:OutputPanel("exp", T["Exp"] .. ": " .. NOT_APPLICABLE)
end
end)
end
do -- Bagspace
local widget = CreateFrame("Frame", "pfPanelWidgetBag", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("BAG_UPDATE_DELAYED")
widget:SetScript("OnEvent", function()
local maxslots = 0
local usedslots = 0
for bag = 0,4 do
if C.panel.bag.ignorespecial ~= "1" or GetBagFamily(bag) == "BAG" then
local bagsize = GetContainerNumSlots(bag)
maxslots = maxslots + bagsize
for j = 1,bagsize do
local itemID = C_Container.GetContainerItemID(bag,j)
if itemID then
usedslots = usedslots + 1
end
end
end
end
local freeslots = maxslots - usedslots
pfUI.panel:OutputPanel("bagspace", freeslots .. " (" .. usedslots .. "/" .. maxslots .. ")", nil, OpenAllBags)
end)
end
do -- Gold
local widget = CreateFrame("Frame", "pfPanelWidgetGold", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("PLAYER_MONEY")
widget.Click = function()
if IsShiftKeyDown() then
-- read current data
local realm = GetRealmName()
local unit = UnitName("player")
local money = GetMoney()
-- reset gold value and hide tooltip
pfUI_cache["gold"][realm] = { [unit] = money }
GameTooltip:Hide()
else
OpenAllBags()
end
end
widget.Tooltip = function()
local gold = floor(GetMoney()/ 10000)
local silver = floor(mod((GetMoney()/100),100))
local copper = floor(mod(GetMoney(),100))
local dmod = ""
if pfUI.panel.diffMoney < 0 then
dmod = "|cffff8888-"
elseif pfUI.panel.diffMoney > 0 then
dmod = "|cff88ff88+"
end
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:ClearLines()
GameTooltip:AddLine("|cff555555" .. T["Money"])
GameTooltip:AddDoubleLine(T["Login"] .. ":", CreateGoldString(pfUI.panel.initMoney))
GameTooltip:AddDoubleLine(T["Now"] .. ":", CreateGoldString(GetMoney()))
GameTooltip:AddDoubleLine("|cffffffff","")
local totalgold = 0
for name, gold in pairs(pfUI_cache["gold"][GetRealmName()]) do
totalgold = totalgold + gold
if name ~= UnitName("player") then
GameTooltip:AddDoubleLine(name .. ":", CreateGoldString(gold))
end
end
GameTooltip:AddDoubleLine("|cffffffff","")
GameTooltip:AddDoubleLine(T["This Session"] .. ":", dmod .. CreateGoldString(math.abs(pfUI.panel.diffMoney)))
GameTooltip:AddDoubleLine(T["Total Gold"] .. ":", CreateGoldString(totalgold))
GameTooltip:AddLine(" ")
GameTooltip:AddLine(T["Shift-Click to reset all money totals"], .5, .5, .5, 1)
GameTooltip:Show()
end
widget:SetScript("OnEvent", function()
local realm = GetRealmName()
local unit = UnitName("player")
local money = GetMoney()
local goldstr = CreateGoldString(GetMoney())
pfUI.panel.initMoney = pfUI.panel.initMoney or money
pfUI.panel.diffMoney = money - pfUI.panel.initMoney
pfUI_cache["gold"][realm] = pfUI_cache["gold"][realm] or {}
pfUI_cache["gold"][realm][unit] = money
pfUI.panel:OutputPanel("gold", goldstr, widget.Tooltip, widget.Click)
end)
end
do -- Friends
local widget = CreateFrame("Frame", "pfPanelWidgetFriends", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("FRIENDLIST_UPDATE")
widget.Tooltip = function()
local init = nil
local all = GetNumFriends()
local playerzone = GetRealZoneText()
for friendIndex=1, all do
local info = C_FriendList.GetFriendInfoByIndex(friendIndex)
if info and info.connected and info.classFilename and info.level then
if not init then
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:ClearLines()
GameTooltip:AddLine("|cff555555" .. T["Friends Online"])
init = true
end
local ccolor = PFUI_CLASS_COLORS[info.classFilename]
local lcolor = GetDifficultyColor(tonumber(info.level)) or { 1, 1, 1 }
local zcolor = info.area == playerzone and "|cff33ffcc" or "|cffcccccc"
GameTooltip:AddDoubleLine(ccolor:WrapTextInColorCode(info.name) .. rgbhex(lcolor) .. " [" .. info.level .. "]", zcolor .. info.area)
end
end
GameTooltip:Show()
end
widget.Click = function() ToggleFriendsFrame(1) end
widget:SetScript("OnEvent", function()
local online = C_FriendList.GetNumOnlineFriends()
pfUI.panel:OutputPanel("friends", FRIENDS .. ": " .. online, widget.Tooltip, widget.Click)
end)
end
do -- Guild
local widget = CreateFrame("Frame", "pfPanelWidgetGuild", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("GUILD_ROSTER_UPDATE")
widget:RegisterEvent("PLAYER_GUILD_UPDATE")
widget.Tooltip = function()
-- skip without guild
if not IsInGuild() then return end
local raidparty = {}
for i=1,4 do -- detect people in group
if UnitExists("party"..i) then
raidparty[UnitName("party"..i)] = true
end
end
for i=1,40 do -- detect people in raid
if UnitExists("raid"..i) then
raidparty[UnitName("raid"..i)] = true
end
end
local all = GetNumGuildMembers()
local playerzone = GetRealZoneText()
local off = FauxScrollFrame_GetOffset(GuildListScrollFrame)
local left, field, init
for i=1, all do
local name, _, _, level, class, zone, _, _, online = GetGuildRosterInfo(off + i)
if online then
if not init then
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:ClearLines()
GameTooltip:AddLine("|cff555555" .. T["Guild Online"])
init = true
end
local ccolor = PFUI_CLASS_COLORS[L["class"][class]] or { 1, 1, 1 }
local lcolor = GetDifficultyColor(tonumber(level)) or { 1, 1, 1 }
local level = "|cff555555" .. "[" .. rgbhex(lcolor) .. level .. "|cff555555]"
local raid = raidparty[name] and "|cff555555[|cff33ffccG|cff555555]|r" or ""
if not left then
left = level .. raid .. " " .. rgbhex(ccolor) .. name
else
field = rgbhex(ccolor) .. name .. " " .. raid .. level
GameTooltip:AddDoubleLine(left, field)
left = nil
end
end
end
if left then
GameTooltip:AddDoubleLine(left, "")
end
GameTooltip:Show()
end
widget.Click = function() ToggleFriendsFrame(3) end
widget:SetScript("OnEvent", function()
if IsInGuild() then
local count = 0
for i = 1, GetNumGuildMembers() do
local _, _, _, _, _, _, _, _, online = GetGuildRosterInfo(i)
if online then count = count + 1 end
end
pfUI.panel:OutputPanel("guild", GUILD .. ": " .. count, widget.Tooltip, widget.Click)
else
pfUI.panel:OutputPanel("guild", GUILD .. ": " .. NOT_APPLICABLE, widget.Tooltip, widget.Click)
end
end)
C_Timer.NewTicker(60, function()
if IsInGuild() then GuildRoster() end
end)
end
do -- Durability / Repair
local widget = CreateFrame("Frame", "pfPanelWidgetRepair", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("PLAYER_MONEY")
widget:RegisterEvent("PLAYER_REGEN_ENABLED")
widget:RegisterEvent("PLAYER_DEAD")
widget:RegisterEvent("PLAYER_UNGHOST")
widget:RegisterEvent("PLAYER_EQUIPMENT_CHANGED") -- ClassicAPI: equip/unequip changes total durability
widget:RegisterEvent("UPDATE_INVENTORY_DURABILITY") -- ClassicAPI: combat wear / repair
widget.Click = function() ToggleCharacter("PaperDollFrame") end
widget.Tooltip = function()
local totalRep = 0
local itemLines = {}
for id = INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED do
local cur, max = GetInventoryItemDurability(id)
if cur and max then
totalRep = totalRep + (GetInventoryItemRepairCost(id) or 0)
local repPercent = floor(cur / max * 100)
if repPercent < 100 then
local _, _, _, hex = GetColorGradient(repPercent/100)
local link = GetInventoryItemLink("player", id)
local texture = GetInventoryItemTexture("player", id)
if texture then
link = CreateSimpleTextureMarkup(texture, 24) .. " " .. link
end
itemLines[table.getn(itemLines)+1] = {
link,
string.format("%s%s%%|r", hex, repPercent)
}
end
end
end
if totalRep > 0 then
GameTooltip:ClearLines()
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:AddLine(REPAIR_COST.." " .. CreateGoldString(totalRep), 0.3333, 0.3333, 0.3333)
for _,line in ipairs(itemLines) do
GameTooltip:AddDoubleLine(line[1],line[2])
end
GameTooltip:Show()
end
end
widget:SetScript("OnEvent", function()
local totalCurr, totalMax = 0, 0
for id = INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED do
local cur, max = GetInventoryItemDurability(id)
if cur and max then
totalCurr = totalCurr + cur
totalMax = totalMax + max
end
end
local armorPercent = totalMax > 0 and floor(totalCurr / totalMax * 100) or 100
pfUI.panel:OutputPanel("durability", armorPercent .. "% " .. ARMOR, widget.Tooltip, widget.Click)
end)
end
do -- Zone
local widget = CreateFrame("Frame", "pfPanelWidgetZone", UIParent)
for _,event in pairs({"PLAYER_ENTERING_WORLD", "MINIMAP_ZONE_CHANGED"}) do
widget:RegisterEvent(event)
end
widget.Tooltip = function()
local real = GetRealZoneText()
local sub = GetSubZoneText()
GameTooltip:ClearLines()
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:AddLine("|cffffffff" .. real)
GameTooltip:AddLine(sub)
local posX, posY = GetPlayerMapPosition("player")
if posX ~= 0 and posY ~= 0 then
GameTooltip:AddLine("|cffaaaaaa" .. round(posX * 100, 1) .. ", " .. round(posY * 100, 1))
end
GameTooltip:Show()
end
widget.Click = function()
WorldMapFrame:SetShown(not WorldMapFrame:IsShown())
end
widget:SetScript("OnEvent", function()
pfUI.panel:OutputPanel("zone", GetMinimapZoneText(), widget.Tooltip, widget.Click)
end)
end
do -- Ammo
local widget = CreateFrame("Frame", "pfPanelWidgetAmmo", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterUnitEvent("UNIT_INVENTORY_CHANGED", "player")
widget:RegisterEvent("BAG_UPDATE_DELAYED")
widget.Tooltip = function()
if GetInventoryItemQuality("player", 0) then
local ammo = GetInventoryItemCount("player", 0)
GameTooltip:ClearLines()
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:SetInventoryItem("player", 0)
GameTooltip:AddLine(T["Count"] .. ": " .. ammo, .3,1,.8)
GameTooltip:Show()
end
end
widget:SetScript("OnEvent", function()
if not GetInventoryItemQuality("player", 0) then
pfUI.panel:OutputPanel("ammo", AMMOSLOT .. ": -")
else
pfUI.panel:OutputPanel("ammo", AMMOSLOT .. ": " .. GetInventoryItemCount("player", 0), tooltip)
end
end)
end
do
-- Hearthstone bind location
local hearth = CreateFrame("Frame", "pfPanelBindLocation", UIParent)
hearth:RegisterEvent("PLAYER_ENTERING_WORLD")
hearth:RegisterEvent("HEARTHSTONE_BOUND")
hearth:SetScript("OnEvent", function()
pfUI.panel:OutputPanel("bindlocation", T["Hearthstone"] .. ": " .. (GetBindLocation() or T["Not Set"]))
end)
local itemIDs = {
soulshard = 6265,
flashpowder = 5140,
thistletea = 7676,
blindpowder = 5530
}
local function AddItemToPanel(panelType)
local itemID = itemIDs[panelType]
if C_Item.IsItemDataCachedByID(itemID) then
local itemName, count = C_Item.GetItemNameByID(itemID), C_Item.GetItemCount(itemID)
pfUI.panel:OutputPanel(panelType, itemName .. ": " .. count)
else
local item = Item:CreateFromItemID(itemID)
item:ContinueOnItemLoad(function()
local itemName, count = item:GetItemName(), C_Item.GetItemCount(item:GetItemID())
pfUI.panel:OutputPanel(panelType, itemName .. ": " .. count)
end)
end
end
local class = UnitClassBase('player')
if class == "WARLOCK" then
-- Soulshards
local widget = CreateFrame("Frame", "pfPanelWidgetSoulshard", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("BAG_UPDATE_DELAYED")
widget:SetScript("OnEvent", function()
AddItemToPanel("soulshard")
end)
end
if class == "ROGUE" then
-- Flash Powder
local widget = CreateFrame("Frame", "pfPanelFlashPowder", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("BAG_UPDATE_DELAYED")
widget:SetScript("OnEvent", function()
AddItemToPanel("flashpowder")
end)
-- Thistle Tea
local widget = CreateFrame("Frame", "pfPanelThistleTea", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("BAG_UPDATE_DELAYED")
widget:SetScript("OnEvent", function()
AddItemToPanel("thistletea")
end)
-- Blinding Powder
local widget = CreateFrame("Frame", "pfPanelBlindingPowder", UIParent)
widget:RegisterEvent("PLAYER_ENTERING_WORLD")
widget:RegisterEvent("BAG_UPDATE_DELAYED")
widget:SetScript("OnEvent", function()
AddItemToPanel("blindpowder")
end)
end
end
end
pfUI.panel = {}
pfUI.panel.modules = {}
-- list of available panel fields
pfUI.panel.options = { "time", "fps", "exp", "gold", "friends",
"guild", "durability", "zone", "ammo", "bagspace" }
local panels = {}
function pfUI.panel:OutputPanel(entry, value, tooltip, func)
-- return if not yet fully initialized
if not pfUI.panel.minimap then return end
-- initialize then panels if not yet done
if not panels[1] then
panels = {
{ pfUI.panel.left.left, C.panel.left.left },
{ pfUI.panel.left.center, C.panel.left.center },
{ pfUI.panel.left.right, C.panel.left.right },
{ pfUI.panel.right.left, C.panel.right.left },
{ pfUI.panel.right.center, C.panel.right.center },
{ pfUI.panel.right.right, C.panel.right.right },
{ pfUI.panel.minimap, C.panel.other.minimap },
}
end
for i,p in pairs(panels) do
local frame, config = p[1], p[2]
if config == entry then
frame.text:SetText(value)
if not frame.initialized or frame.initialized ~= entry then
if tooltip then
frame:SetScript("OnEnter", tooltip)
frame:SetScript("OnLeave", function() GameTooltip:Hide() end)
end
if func then
frame:SetScript("OnClick", func)
end
frame.initialized = entry
end
end
end
end
local function CreatePanelButton(parent, width, location, tjustify)
local frame = CreateFrame("Button", nil, parent)
frame:SetFrameLevel(0)
frame:ClearAllPoints()
frame:SetSize(width, parent:GetHeight())
frame:SetPoint(location, 0, 0)
frame.text = frame:CreateFontString("Status", "LOW", "GameFontNormal")
frame.text:ClearAllPoints()
frame.text:SetAllPoints(frame)
frame.text:SetPoint(location, 0, 0)
frame.text:SetJustifyH(tjustify)
frame.text:SetFont(font, font_size, "OUTLINE")
frame.text:SetFontObject(GameFontWhite)
return frame
end
local function CreatePanel(panelname, default_border)
local frame = CreateFrame("Frame", panelname, UIParent)
frame:SetFrameStrata("FULLSCREEN")
frame:ClearAllPoints()
frame:SetFrameStrata("DIALOG")
frame:SetHeight(C.global.font_size*1.5)
CreateBackdrop(frame, default_border, nil)
CreateBackdropShadow(frame)
return frame
end
local function CreatePanelHide(parent, leftright)
parent.hide = CreateFrame("Button", nil, parent)
parent.hide:SetFrameLevel(4)
parent.hide:SetPoint(leftright, parent.backdrop, leftright, 0, 0)
parent.hide:SetPoint("TOP", parent.backdrop, "TOP", 0, 0)
parent.hide:SetPoint("BOTTOM", parent.backdrop, "BOTTOM", 0, 0)
parent.hide:SetWidth(12)
return parent.hide
end
local function CreatePanelHideTexture(parent, framename, leftright)
SkinButton(parent)
parent:SetBackdropColor(0,0,0,0)
parent.texture = parent:CreateTexture(framename)
local imgstring = "img:" .. leftright
parent.texture:SetTexture(pfUI.media[imgstring])
parent.texture:SetPoint("CENTER", 0, 0)
parent.texture:SetSize(8, 8)
parent.texture:SetVertexColor(.25,.25,.25,1)
return parent.texture
end
-- left panel
pfUI.panel.left = CreatePanel("pfPanelLeft", default_border)
pfUI.panel.left.hide = CreatePanelHide(pfUI.panel.left, "LEFT", -5)
pfUI.panel.left.hide.texture = CreatePanelHideTexture(pfUI.panel.left.hide, "pfPanelLeftHide", "left")
if pfUI.chat then
pfUI.panel.left:SetScale(pfUI.chat.left:GetScale())
pfUI.panel.left:SetWidth(tonumber(C.chat.left.width) - 4)
pfUI.panel.left:SetPoint("BOTTOM", pfUI.chat.left, "BOTTOM", 0, 2)
else
pfUI.panel.left:SetWidth(C.chat.left.width)
pfUI.panel.left:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", 5, 5)
end
UpdateMovable(pfUI.panel.left)
pfUI.panel.left.hide:SetScript("OnClick", function()
pfUI.chat.left:SetShown(not pfUI.chat.left:IsShown())
end)
if not pfUI.chat then pfUI.panel.left.hide:Hide() end
-- buttons for left panel
local width = pfUI.panel.left:GetWidth() / 3 - 2
width = C.panel.left.left == "none" and C.panel.left.right == "none" and pfUI.panel.left:GetWidth() - 2 or width
width = C.panel.left.center == "none" and pfUI.panel.left:GetWidth() / 2 - 2 or width
pfUI.panel.left.left = CreatePanelButton(pfUI.panel.left, width, "LEFT", "CENTER")
pfUI.panel.left.center = CreatePanelButton(pfUI.panel.left, width, "CENTER", "CENTER")
pfUI.panel.left.right = CreatePanelButton(pfUI.panel.left, width, "RIGHT", "CENTER")
if C.panel.left.left == "none"
and C.panel.left.center == "none"
and C.panel.left.right == "none" then
pfUI.panel.left:Hide()
end
-- right panel
pfUI.panel.right = CreatePanel("pfPanelRight", default_border)
pfUI.panel.right.hide = CreatePanelHide(pfUI.panel.right, "RIGHT", 5)
pfUI.panel.right.hide.texture = CreatePanelHideTexture(pfUI.panel.right.hide, "pfPanelRightHide", "right")
if pfUI.chat then
pfUI.panel.right:SetScale(pfUI.chat.right:GetScale())
pfUI.panel.right:SetWidth(tonumber(C.chat.right.width) - 4)
pfUI.panel.right:SetPoint("BOTTOM", pfUI.chat.right, "BOTTOM", 0, 2)
else
pfUI.panel.right:SetWidth(C.chat.right.width)
pfUI.panel.right:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -5, 5)
end
UpdateMovable(pfUI.panel.right)
pfUI.panel.right.hide:SetScript("OnClick", function()
pfUI.chat.right:SetShown(not pfUI.chat.right:IsShown())
end)
if not pfUI.chat then pfUI.panel.right.hide:Hide() end
-- buttons for right panel
local width = pfUI.panel.right:GetWidth() / 3 - 2
width = C.panel.right.left == "none" and C.panel.right.right == "none" and pfUI.panel.right:GetWidth() - 2 or width
width = C.panel.right.center == "none" and pfUI.panel.right:GetWidth() / 2 - 2 or width
pfUI.panel.right.left = CreatePanelButton(pfUI.panel.right, width, "LEFT", "CENTER")
pfUI.panel.right.center = CreatePanelButton(pfUI.panel.right, width, "CENTER", "CENTER")
pfUI.panel.right.right = CreatePanelButton(pfUI.panel.right, width, "RIGHT", "CENTER")
if C.panel.right.left == "none"
and C.panel.right.center == "none"
and C.panel.right.right == "none" then
pfUI.panel.right:Hide()
end
pfUI.panel.minimap = CreateFrame("Button", "pfPanelMinimap", UIParent)
if pfUI.minimap then
pfUI.panel.minimap:SetWidth(pfUI.minimap:GetWidth())
pfUI.panel.minimap:SetPoint("TOPLEFT", pfUI.minimap, "BOTTOMLEFT", 0 , -default_border*3)
pfUI.panel.minimap:SetPoint("TOPRIGHT", pfUI.minimap, "BOTTOMRIGHT", 0 , default_border*3)
else
pfUI.panel.minimap:SetWidth(200)
pfUI.panel.minimap:SetPoint("TOP", UIParent, "TOP", 0, -5)
end
pfUI.panel.minimap:SetHeight(C.global.font_size*1.5)
pfUI.panel.minimap:SetFrameStrata("MEDIUM")
CreateBackdrop(pfUI.panel.minimap, default_border)
CreateBackdropShadow(pfUI.panel.minimap)
UpdateMovable(pfUI.panel.minimap)
pfUI.panel.minimap.text = pfUI.panel.minimap:CreateFontString("MinimapZoneText", "LOW", "GameFontNormal")
pfUI.panel.minimap.text:SetFont(font, font_size, "OUTLINE")
pfUI.panel.minimap.text:SetAllPoints()
pfUI.panel.minimap.text:SetFontObject(GameFontWhite)
if C.panel.other.minimap == "none" then pfUI.panel.minimap:Hide() end
-- MicroButtons
if C.panel.micro.enable == "1" then
pfUI.panel.microbutton = CreateFrame("Frame", "pfPanelMicroButton", UIParent)
pfUI.panel.microbutton:SetPoint("TOP", pfUI.panel.minimap, "BOTTOM", 0, -2*default_border)
UpdateMovable(pfUI.panel.microbutton)
pfUI.panel.microbutton:SetSize(145, 23)
pfUI.panel.microbutton:SetFrameStrata("MEDIUM")
local microButtons = {
'CharacterMicroButton', 'SpellbookMicroButton', 'TalentMicroButton',
'QuestLogMicroButton', 'SocialsMicroButton', 'WorldMapMicroButton',
'MainMenuMicroButton', 'HelpMicroButton',
}
for i=1,table.getn(microButtons) do
local anchor = _G[microButtons[i-1]] or pfUI.panel.microbutton
local button = _G[microButtons[i]]
button:ClearAllPoints()
button:SetParent(pfUI.panel.microbutton)
if i == 1 then
button:SetPoint("LEFT", pfUI.panel.microbutton, "LEFT", 1, 10)
else
button:SetPoint("TOPLEFT", anchor, "TOPRIGHT", 1, 0)
end
button:SetScale(.6)
button.frame = CreateFrame("Frame", "backdrop", button)
button.frame:SetScale(1.4)
button.frame:SetPoint("TOPLEFT", button, "TOPLEFT", 1, -16)
button.frame:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -1, 1)
CreateBackdrop(button.frame, default_border)
button:Show()
end
end
pfUI.panel.autohide = CreateFrame("Frame", nil, UIParent)
pfUI.panel.autohide:RegisterEvent("PLAYER_ENTERING_WORLD")
pfUI.panel.autohide:SetScript("OnEvent", function()
if C.panel.hide_leftchat == "1" then
EnableAutohide(pfUI.panel.left, 2)
end
if C.panel.hide_rightchat == "1" then
EnableAutohide(pfUI.panel.right, 2)
end
if C.panel.hide_minimap == "1" then
EnableAutohide(pfUI.panel.minimap, 2)
end
if C.panel.hide_microbar == "1" then
EnableAutohide(pfUI.panel.microbutton, 2)
end
end)
end)