18 Commits
Author SHA1 Message Date
Brues 03ea3d5aa5 Clear cancelled resurrections announced over HealComm and CTRA
ParseChatMessage tested the raw message for "RessStop", which no
HealComm message is, so ParseComm's Resurrection/stop/ result was never
acted on. CTRA's RESNO was matched against the whole message, but it
carries the target's name, and the CTRA parser only recognised RES. A
cancelled rez from another player left the icon on the target's frame
until they were revived. RessStop still keeps a rez whose cast landed
and whose accept window is open.
2026-10-29 18:58:15 -05:00
Brues 2b4d33d46a Keep libpredict tracking casts when HealComm is loaded
With HealComm-1.0 present (HealComm, LunaUnitFrames, NotGrid), the
compat hook unregistered every event on libpredict.sender to stop pfUI
broadcasting a duplicate of the player's casts. Since cast detection
moved onto that frame's UNIT_SPELLCAST_* handlers, that also blinded
libpredict to every cast, so the player's own resurrections never put
the rez icon on the target's frame: ParseChatMessage drops the player's
own Resurrection echo, expecting the cast events to have tracked it.

The compat hook now only mutes the outgoing HealComm and CTRA messages.
The HealComm.SendAddonMessage hook that parsed the player's own messages
while solo goes too, since libpredict tracks its own casts directly.
2026-10-29 18:56:51 -05:00
Brues 94dcfb3dad Compute bar layout options instead of tabulating pfGridmath
pfGridmath listed every exact cols x rows grid per bar size; the only
live use was seeding the layout dropdown, which a divisor loop now does.

Everything else that read it was unreachable: every layout option is a
"cols x rows" string, so ResolveBarLayout's BarLayoutFormfactor lookup
never matched, and the actionbar module resets a stored layout that
isn't one before BarLayoutSize/BarButtonAnchor run, so their fallbacks
never fired. BarLayoutFormfactor and env/tables.lua go with it.
2026-10-29 14:16:43 -05:00
Brues 0890905eb6 Drop named-unit frames and the pfValidUnits global
CreateUnitFrame and CreateCastbar could take a character name instead of
a unit token, but every caller passes a token, so that mode and the
empty-label guards around it were dead. The OnClick TargetByName branch
could never run anyway: label was always a string, and "" is truthy.

With that gone, the aggro scan was the only reader of pfValidUnits, so
its unit list now lives in unitframes.lua and is built once at load.

/focusname resolves the name with UnitTokenFromName (exact first, then
prefix) instead of swapping the target and muting UIErrorsFrame.
2026-10-29 14:00:54 -05:00
Brues 6c76a88467 Draw unit frame bars with the native StatusBar
The custom bar sized its textures in Lua from GetWidth(), so it had to
track how ClassicAPI reports the UI scale (#71), and it stretched the bar
texture instead of cropping it. The engine's StatusBar does that layout
itself.

The background of the missing part is a second StatusBar that fills
from the other end (ClassicAPI's SetReverseFill), one frame level below
the fill, so the incoming-heal texture still draws between the two.
SetFrameLevel moves both, and the health and power bars now sit two
levels above their backdrops. SetStatusBarBackgroundTexture becomes
SetStatusBarBackgroundColor, as it only ever took a color.
2026-10-29 11:06:02 -05:00
Brues 35c32f365e Remove scaledsize fix 2026-10-29 10:38:28 -05:00
Brues 6dcb5162be bags: use ClassicAPI's native item search
C_Container.SetItemSearch drives the search box; slots dim from isFiltered on INVENTORY_SEARCH_UPDATE and on each slot update. Matches name, subclass, equip slot and equipment set names. Drops the tooltip-scanning full-text option.
2026-10-29 10:35:28 -05:00
Brues 8afafe71cf Drop RunMacroText fallback and dead actionbar spellslot branches
ClassicAPI 1.18 provides RunMacroText natively; bump CAPI min to 1.18.0. spellslot/booktype/scanmacro were only ever cleared, never set.
2026-10-29 10:35:28 -05:00
Brues 99ed538ee7 bump CAPI min to 1.17.10 2026-10-29 10:35:28 -05:00
Brues f382039f21 panel: show per-addon memory in FPS & Lag tooltip
Use UpdateAddOnMemoryUsage/GetAddOnMemoryUsage like Blizzard's MainMenuBar performance tooltip: total addon memory plus the top 3 consumers, formatted with the TOTAL_MEM/ADDON_MEM global strings. Guarded so the tooltip falls back gracefully on clients without these APIs.
2026-10-29 10:35:28 -05:00
Brues 8307dd757e Bump ClassicAPI minimum 1.17.4 2026-10-29 10:35:28 -05:00
Brues 5ab5337bbc Keep status bars true to their value on ClassicAPI 1.18.0
ClassicAPI 1.18.0 divides the UI scale out of an anchored frame's
GetWidth/GetHeight, as 4.3.4 does. The status bar still divided it out
itself, so under a UI scale below 1 the bar emptied early (at 29% health
on a 0.71 scale). Only divide on older ClassicAPI.

Fixes #71
2026-10-29 10:33:55 -05:00
Brues d15b1cd320 Only declare RunMacroText if it doesn't exist 2026-10-28 12:21:34 -05:00
0cabf2ec29 Add equipment manager auto-switching and "Unused" items panel (#70)
* Add equipment manager auto-switching and "Unused" items panel

Equipment manager (modules/equipmentmanager.lua):
- Add automatic set switching: ordered triggers (mounted, swimming,
  eating/drinking, shapeshift form/stance, zone, instance type, time
  of day, resting, stealthed, targeting a boss) equip a set; topmost
  matching trigger wins, with a 0.5s debounce
- Never swap gear in combat, while dead or casting; optionally restore
  the previous gear via a hidden "pfUI Auto-Restore" set
- Add an "Unused" side panel listing equippable items in bags, bank
  and paperdoll that no set uses, with an ignore list (tools and quest
  disguises pre-ignored), bank snapshot and bag highlighting
- Persist triggers, ignore list and bank snapshot in new per-character
  SavedVariable pfUI_eqmgr (all three .toc files)
- Add Character > Equipment Manager options (autoswitch, announce,
  minimum item quality, include bank) in gui.lua and config.lua
- Hide ignored-slot overlays when the manager frame is closed

Add frFR translations for the new equipment manager strings.

* equipmentmanager: lean on ClassicAPI for unused scan and autoswitch

- Unused panel: list items via GetInventoryItemsForSlot instead of
  hand-packing locations and walking the bags.
- Bank snapshot: record set membership while the bank is open.
  GetItemLocations reports bank items as missing once it closes, so set
  items in the bank were listed as unused.
- Autoswitch: check CanUseEquipmentSets and the UseEquipmentSet result
  before marking a trigger applied, and retry when the swap is blocked.
- Drive the engine from events (aura, form, zone, resting, target,
  regen) instead of a 4 Hz ticker; poll only swimming, time and eating.
- Detect eating/drinking by the localized names of the Food (433) and
  Drink (430) auras instead of hardcoded locale strings and icon paths.
- Drop presence guards on APIs that always exist; use strsplittable and
  strtrim for trigger values.

* equipmentmanager: wake the dining trigger on player health/mana events

Drop dining from the poll: listen to UNIT_HEALTH/UNIT_MANA for the player
while a dining trigger is enabled, so taking the set off once full is
event-driven. Register UNIT_AURA for the player only.

* equipmentmanager: split trigger values with strsplit

strsplittable needs ClassicAPI 1.17.11; strsplit has been there since
1.7.3, so this keeps the minimum where it is.

* equipmentmanager: let the trigger hint wrap

---------

Co-authored-by: Duciel <336374+Duciel@users.noreply.github.com>
Co-authored-by: Brues <5278969+brues-code@users.noreply.github.com>
2026-10-27 11:02:44 -05:00
Brues fe376b8e51 Keep buff timer text above the cooldown sweep 2026-10-25 20:32:49 -05:00
Brues e326cea05e Add radial sweeps to buff/debuff icon display 2026-10-25 20:26:45 -05:00
Brues d9e74b3bc5 Add per-frame reverse toggle for cooldown sweeps 2026-10-25 20:24:12 -05:00
Brues 0e428de74c Fix inactive nameplate alpha capped at 99%
CacheConfig clamped notargalpha to 0.99, so a 100% setting never reached full opacity. Clamp to 1.0 instead and detect the target plate by GUID comparison only, removing the alpha-based fallback that required the headroom.
2026-10-25 20:00:50 -05:00
32 changed files with 1667 additions and 378 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ do
-- on. There pfUI does load, and will throw wherever it reaches for something
-- the installed DLL doesn't have yet -- the popup names the cause so those
-- errors aren't a mystery.
local PFUI_CLASSIC_API_MIN = 11703 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_MIN = 11800 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
+21 -48
View File
@@ -1353,15 +1353,18 @@ end
-- [ Bar Layout Options ] --
-- 'barsize' size of bar in number of buttons
-- returns: array of options as strings for pfUI.gui.bar
-- returns: array of options as strings for pfUI.gui.bar: every grid
-- that fits the bar exactly, plus common uneven ones
function pfUI.api.BarLayoutOptions(barsize)
assert(barsize > 0 and barsize <= NUM_ACTIONBAR_BUTTONS,"BarLayoutOptions: barsize "..tostring(barsize).." is invalid")
local options, seen = {}, {}
local function add(option)
if not seen[option] then table.insert(options, option); seen[option] = true end
end
for i,layout in ipairs(pfGridmath[barsize]) do
add(string.format("%d x %d",layout[1],layout[2]))
for cols = 1, barsize do
if barsize % cols == 0 then
add(string.format("%d x %d", cols, barsize / cols))
end
end
for _, option in ipairs({
"1 x 12", "1 x 10", "2 x 10", "2 x 5", "3 x 10", "3 x 5", "3 x 3",
@@ -1381,49 +1384,23 @@ function pfUI.api.BarLayoutOptions(barsize)
return options
end
-- [ Bar Layout Formfactor ] --
-- 'option' string option as used in pfUI_config.bars[bar].option
-- returns: integer formfactor
local formfactors = {}
setmetatable(formfactors, {__mode = "v"}) -- weak table so values not referenced are collected on next gc
function pfUI.api.BarLayoutFormfactor(option)
if formfactors[option] then
return formfactors[option]
else
for barsize,_ in ipairs(pfGridmath) do
local options = pfUI.api.BarLayoutOptions(barsize)
for i,opt in ipairs(options) do
if opt == option then
formfactors[option] = i
return formfactors[option]
end
end
end
end
end
-- 'formfactor' has to be a "cols x rows" string; the actionbar module resets
-- a stored layout that isn't one before it lays out a bar
local function ResolveBarLayout(barsize, formfactor, uneven)
local layout = tostring(formfactor or "")
local _, _, a, b = string.find(layout, "(%d+)%s*x%s*(%d+)")
if a and b then
local cols, rows = tonumber(a), tonumber(b)
cols = math.min(NUM_ACTIONBAR_BUTTONS, math.max(1, cols))
rows = math.min(NUM_ACTIONBAR_BUTTONS, math.max(1, rows))
local orientation = string.upper(uneven or "DOWN")
local mode = (orientation == "LEFT" or orientation == "RIGHT") and "cols" or "rows"
if mode == "rows" then
cols = math.max(1, math.min(cols, barsize))
rows = math.max(1, math.ceil(barsize / cols))
else
rows = math.max(1, math.min(rows, barsize))
cols = math.max(1, math.ceil(barsize / rows))
end
return cols, rows, mode, orientation
local _, _, a, b = string.find(formfactor, "(%d+)%s*x%s*(%d+)")
local cols, rows = tonumber(a), tonumber(b)
cols = math.min(NUM_ACTIONBAR_BUTTONS, math.max(1, cols))
rows = math.min(NUM_ACTIONBAR_BUTTONS, math.max(1, rows))
local orientation = string.upper(uneven or "DOWN")
local mode = (orientation == "LEFT" or orientation == "RIGHT") and "cols" or "rows"
if mode == "rows" then
cols = math.max(1, math.min(cols, barsize))
rows = math.max(1, math.ceil(barsize / cols))
else
rows = math.max(1, math.min(rows, barsize))
cols = math.max(1, math.ceil(barsize / rows))
end
local index = pfUI.api.BarLayoutFormfactor(layout)
if not index then return nil end
local cols, rows = unpack(pfGridmath[barsize][index])
return cols, rows, "rows", "DOWN"
return cols, rows, mode, orientation
end
-- [ Bar Layout Size ] --
@@ -1434,7 +1411,6 @@ end
function pfUI.api.BarLayoutSize(bar,barsize,formfactor,iconsize,bordersize,padding,uneven,fillmode)
assert(barsize > 0 and barsize <= NUM_ACTIONBAR_BUTTONS,"BarLayoutSize: barsize "..tostring(barsize).." is invalid")
local cols, rows = ResolveBarLayout(barsize, formfactor, uneven)
if not cols or not rows then cols, rows = unpack(pfGridmath[barsize][1]) end
local width = (iconsize + bordersize*2+padding) * cols + padding
local height = (iconsize + bordersize*2+padding) * rows + padding
bar._size = {width,height}
@@ -1452,9 +1428,6 @@ end
function pfUI.api.BarButtonAnchor(button,basename,buttonindex,barsize,formfactor,iconsize,bordersize,padding,uneven,fillmode)
assert(barsize > 0 and barsize <= NUM_ACTIONBAR_BUTTONS,"BarButtonAnchor: barsize "..tostring(barsize).." is invalid")
local cols, rows, mode, orientation = ResolveBarLayout(barsize, formfactor, uneven)
if not cols or not rows then
cols, rows, mode, orientation = unpack(pfGridmath[barsize][1]), "rows", "DOWN"
end
-- fillmode: remap buttonindex to slotindex (grid position in native fill order)
-- only needed when fill direction differs from layout mode
+11 -1
View File
@@ -71,6 +71,8 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("buffs", nil, "debuffrowsize", "16")
pfUI:UpdateConfig("buffs", nil, "textinside", "0")
pfUI:UpdateConfig("buffs", nil, "fontsize", "-1")
pfUI:UpdateConfig("buffs", nil, "cooldown_anim", "1")
pfUI:UpdateConfig("buffs", nil, "cooldown_reverse", "1")
pfUI:UpdateConfig("buffbar", "pbuff", "enable", "0")
pfUI:UpdateConfig("buffbar", "pbuff", "use_unitfonts", "0")
@@ -169,11 +171,11 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("appearance", "bags", "newitem_color", "1,1,1,1")
pfUI:UpdateConfig("appearance", "bags", "borderlimit", "1")
pfUI:UpdateConfig("appearance", "bags", "borderonlygear", "0")
pfUI:UpdateConfig("appearance", "bags", "fulltext", "1")
pfUI:UpdateConfig("appearance", "bags", "movable", "0")
pfUI:UpdateConfig("appearance", "bags", "abovechat", "0")
pfUI:UpdateConfig("appearance", "bags", "hidechat", "0")
pfUI:UpdateConfig("appearance", "bags", "icon_size", "-1")
pfUI:UpdateConfig("appearance", "bags", "cooldown_reverse", "0")
pfUI:UpdateConfig("appearance", "bags", "bagrowlength", "10")
pfUI:UpdateConfig("appearance", "bags", "bankrowlength", "10")
pfUI:UpdateConfig("appearance", "bags", "autoSortOnOpen", "0")
@@ -516,6 +518,7 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("unitframes", unit, "pspace", "-3")
pfUI:UpdateConfig("unitframes", unit, "cooldown_text", "1")
pfUI:UpdateConfig("unitframes", unit, "cooldown_anim", "0")
pfUI:UpdateConfig("unitframes", unit, "cooldown_reverse", "1")
pfUI:UpdateConfig("unitframes", unit, "buffs", "TOPLEFT")
pfUI:UpdateConfig("unitframes", unit, "buffsize", "20")
pfUI:UpdateConfig("unitframes", unit, "bufflimit", "32")
@@ -682,6 +685,7 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("bars", nil, "bind_size", "8")
pfUI:UpdateConfig("bars", nil, "bind_color", "1,1,0,1")
pfUI:UpdateConfig("bars", nil, "cd_size", "12")
pfUI:UpdateConfig("bars", nil, "cooldown_reverse", "0")
pfUI:UpdateConfig("bars", "gryphons", "texture", "None")
pfUI:UpdateConfig("bars", "gryphons", "color", ".6,.6,.6,1")
@@ -695,6 +699,7 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("totems", nil, "iconsize", "26")
pfUI:UpdateConfig("totems", nil, "spacing", "3")
pfUI:UpdateConfig("totems", nil, "showbg", "0")
pfUI:UpdateConfig("totems", nil, "cooldown_reverse", "1")
pfUI:UpdateConfig("panel", nil, "use_unitfonts", "0")
pfUI:UpdateConfig("panel", nil, "hide_leftchat", "0")
@@ -942,6 +947,7 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("nameplates", nil, "debufftimers", "1")
pfUI:UpdateConfig("nameplates", nil, "debufftext", "1")
pfUI:UpdateConfig("nameplates", nil, "debuffanim", "0")
pfUI:UpdateConfig("nameplates", nil, "debreverse", "1")
pfUI:UpdateConfig("abuttons", nil, "enable", "1")
pfUI:UpdateConfig("abuttons", nil, "position", "bottom")
@@ -969,6 +975,10 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("character", "inventory", "durability", "1")
pfUI:UpdateConfig("character", "inventory", "equipflyout", "0")
pfUI:UpdateConfig("equipmentmanager", nil, "autoswitch", "1")
pfUI:UpdateConfig("equipmentmanager", nil, "announce", "1")
pfUI:UpdateConfig("equipmentmanager", nil, "unusedquality", "1")
pfUI:UpdateConfig("equipmentmanager", nil, "unusedbank", "1")
pfUI:UpdateConfig("character", "reputation", "repRequired", "1")
pfUI:UpdateConfig("thirdparty", nil, "chatbg", "1")
pfUI:UpdateConfig("thirdparty", nil, "showmeter", "0")
+37 -71
View File
@@ -3,15 +3,19 @@ setfenv(1, pfUI:GetEnvironment())
do -- statusbars
local animations = {}
local stepsize, val
local width, height, point
local stepsize
-- native StatusBar methods the bar overrides
local statusbar = CreateFrame("StatusBar")
local SetValue, SetMinMaxValues = statusbar.SetValue, statusbar.SetMinMaxValues
local SetOrientation, SetFrameLevel = statusbar.SetOrientation, statusbar.SetFrameLevel
local animate = CreateFrame("Frame", "pfStatusBarAnimation", UIParent)
animate:SetScript("OnUpdate", function()
stepsize = tonumber(pfUI_config.unitframes.animation_speed)
for bar in pairs(animations) do
if not bar.val_ or abs(bar.val_ - bar.val) < stepsize or bar.instant then
if not bar.val_ or abs(bar.val_ - bar.val) < stepsize then
bar:DisplayValue(bar.val)
elseif bar.val ~= bar.val_ then
bar:DisplayValue(bar.val_ + min((bar.val-bar.val_) / stepsize, max(bar.val-bar.val_, 30 / GetFramerate())))
@@ -21,7 +25,8 @@ do -- statusbars
local handlers = {
["DisplayValue"] = function(self, val)
val = Clamp(val, self.min, self.max)
local smin, smax = self:GetMinMaxValues()
val = Clamp(val, smin, smax)
-- remove animation queue
if val == self.val_ then
@@ -30,53 +35,20 @@ do -- statusbars
-- set current visible value
self.val_ = val
SetValue(self, val)
if self.mode == "vertical" then
height = self:GetHeight()
height = height / self:GetEffectiveScale()
point = height / (self.max - self.min) * (val - self.min)
-- keep values in limits
point = Clamp(point, 0, height)
-- set point to zero if value and max is zero
if val == 0 then point = 0 end
-- set status bar position/size
self.bar:SetPoint("TOPLEFT", self, "TOPLEFT", 0, - height + point)
self.bar:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0)
-- set background bar position/size
self.bg:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
self.bg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, point)
else
width = self:GetWidth()
width = width / self:GetEffectiveScale()
point = width / (self.max - self.min) * (val - self.min)
-- keep values in limits
point = Clamp(point, 0, width)
-- set point to zero if value and max is zero
if val == 0 then point = 0 end
-- set status bar position/size
self.bar:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
self.bar:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", - width + point, 0)
-- set background bar position/size
self.bg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0)
self.bg:SetPoint("TOPLEFT", self, "TOPLEFT", point, 0)
end
-- the background fills the missing part, all of an empty range
self.bg:SetValue(smax > smin and (smax - val) / (smax - smin) or 1)
end,
["SetMinMaxValues"] = function(self, smin, smax, smooth)
-- smoothen the transition by keeping the value at the same percentage as before
if smooth and self.max and self.max > 0 and smax > 0 and self.max ~= smax then
self.val_ = (self.val_ or self.val) / self.max * smax
local _, oldmax = self:GetMinMaxValues()
if smooth and oldmax > 0 and smax > 0 and oldmax ~= smax then
self.val_ = (self.val_ or self.val) / oldmax * smax
end
self.min, self.max = smin, smax
SetMinMaxValues(self, smin, smax)
self:DisplayValue(self.val_ or self.val)
end,
@@ -89,41 +61,35 @@ do -- statusbars
end
end,
["SetStatusBarTexture"] = function(self, r, g, b, a)
self.bar:SetTexture(r, g, b, a)
end,
["SetStatusBarColor"] = function(self, r, g, b, a)
self.bar:SetVertexColor(r, g, b, a)
end,
["SetStatusBarBackgroundTexture"] = function(self, r, g, b, a)
self.bg:SetTexture(r, g, b, a)
end,
["SetStatusBarBackgroundColor"] = function(self, r, g, b, a)
self.bg:SetVertexColor(r, g, b, a)
self.bg:SetColorFill(r, g, b, a)
end,
["SetOrientation"] = function(self, mode)
self.mode = strlower(mode)
["SetOrientation"] = function(self, orientation)
SetOrientation(self, orientation)
self.bg:SetOrientation(orientation)
end,
-- the background stays one level below the fill, under anything else
-- drawn on the fill's frame
["SetFrameLevel"] = function(self, level)
SetFrameLevel(self, level)
self.bg:SetFrameLevel(level - 1)
end,
}
function pfUI.api.CreateStatusBar(name, parent)
local f = CreateFrame("Button", name, parent)
f:EnableMouse(false)
local f = CreateFrame("StatusBar", name, parent)
SetMinMaxValues(f, 0, 100)
SetValue(f, 0)
f.val = 0
f.bar = f:CreateTexture(nil, "NORMAL")
f.bar:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
f.bar:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
f.bg = f:CreateTexture(nil, "BACKGROUND")
f.bg:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
f.bg:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
-- set some default values
f.min, f.max, f.val = 0, 100, 0
f.bg = CreateFrame("StatusBar", nil, f)
f.bg:SetFrameLevel(f:GetFrameLevel() - 1)
f.bg:SetAllPoints(f)
f.bg:SetReverseFill(true)
f.bg:SetMinMaxValues(0, 1)
f.bg:SetValue(1)
-- add all handler functions to the object
for name, func in pairs(handlers) do
+60 -40
View File
@@ -235,7 +235,50 @@ function pfUI.api.GetUnitStats(unitstr)
end
local aggrodata = { }
local aggroScan = nil -- static { u, t, tt } triples, built once so the hot scan allocates nothing
-- every unit whose target or target's target UnitHasAggro checks, as static
-- { u, t, tt } triples so the hot scan allocates nothing
local aggroScan = { }
do
local function add(u)
local t = u .. "target"
table.insert(aggroScan, { u = u, t = t, tt = t .. "target" })
end
add("pet")
add("player")
add("target")
add("mouseover")
add("focus")
add("focustarget")
add("focustargettarget")
add("pettarget")
add("playertarget")
add("targettarget")
add("mouseovertarget")
add("targettargettarget")
for i=1,4 do
add("party" .. i)
add("party" .. i .. "target")
add("partypet" .. i)
add("partypet" .. i .. "target")
end
for i=1,40 do
add("raid" .. i)
add("raid" .. i .. "target")
add("raidpet" .. i)
add("raidpet" .. i .. "target")
add("nameplate" .. i)
add("nameplate" .. i .. "target")
end
end
function pfUI.api.UnitHasAggro(unit)
local now = GetTime()
local data = aggrodata[unit]
@@ -250,16 +293,6 @@ function pfUI.api.UnitHasAggro(unit)
data.state = 0
if UnitExists(unit) and UnitIsFriend(unit, "player") then
-- pfValidUnits never changes after load, so precompute the "<u>target" /
-- "<u>targettarget" token strings once instead of concatenating per call.
if not aggroScan then
aggroScan = {}
for u in pairs(pfValidUnits) do
local t = u .. "target"
table.insert(aggroScan, { u = u, t = t, tt = t .. "target" })
end
end
for i = 1, table.getn(aggroScan) do
local s = aggroScan[i]
if UnitExists(s.t) and UnitIsUnit(s.t, unit) and UnitCanAttack(s.u, unit) then
@@ -349,11 +382,10 @@ function pfUI.uf:UpdateVisibility()
-- this runs for every frame five times a second, so only touch the
-- attribute when the unit actually changed
local unitstr = (self.label or "") .. (self.id or "")
local unit = unitstr ~= "" and unitstr or nil
if unit ~= self.unitstr then
self.unitstr = unit
self:SetAttribute("unit", unit)
local unitstr = self.label .. self.id
if unitstr ~= self.unitstr then
self.unitstr = unitstr
self:SetAttribute("unit", unitstr)
end
-- anything but "show"/"hide" means "show if the unit exists"
local visibility = "exists"
@@ -395,9 +427,7 @@ function pfUI.uf:UpdateVisibility()
self:RegisterUnitEvents(visibility ~= "hide" and self.unitstr or nil)
-- vanilla visibility
if self.unitname then
self:Show()
elseif visibility == "hide" then
if visibility == "hide" then
self:Hide()
elseif visibility == "show" then
self:Show()
@@ -470,6 +500,7 @@ function pfUI.uf:UpdateConfig()
local cooldown_text = tonumber(f.config.cooldown_text)
local cooldown_anim = tonumber(f.config.cooldown_anim)
local cooldown_reverse = tonumber(f.config.cooldown_reverse) or 0
local relative_point = "BOTTOM"
if f.config.panchor == "TOPLEFT" then
@@ -507,6 +538,8 @@ function pfUI.uf:UpdateConfig()
if tonumber(f.config.height) < 0 then f.hp:Hide() end
pfUI.api.CreateBackdrop(f.hp, default_border)
-- one level above the backdrop for the bar's background, one more for its fill
f.hp.bar:SetFrameLevel(f.hp.backdrop:GetFrameLevel() + 2)
f.hp.bar:SetStatusBarTexture(pfUI.media[f.config.bartexture])
f.hp.bar:SetAllPoints(f.hp)
if f.config.verticalbar == "1" then
@@ -521,7 +554,7 @@ function pfUI.uf:UpdateConfig()
if custombg == "1" then
local cr, cg, cb, ca = GetStringColor(custombgcolor)
cr, cg, cb, ca = tonumber(cr), tonumber(cg), tonumber(cb), tonumber(ca)
f.hp.bar:SetStatusBarBackgroundTexture(cr,cg,cb,ca)
f.hp.bar:SetStatusBarBackgroundColor(cr,cg,cb,ca)
end
f.power:ClearAllPoints()
@@ -530,7 +563,7 @@ function pfUI.uf:UpdateConfig()
if tonumber(f.config.pheight) < 0 then f.power:Hide() end
pfUI.api.CreateBackdrop(f.power, default_border)
f.power.bar:SetFrameLevel(f.power.backdrop:GetFrameLevel() + 1)
f.power.bar:SetFrameLevel(f.power.backdrop:GetFrameLevel() + 2)
f.power.bar:SetStatusBarTexture(pfUI.media[f.config.pbartexture])
f.power.bar:SetAllPoints(f.power)
@@ -540,7 +573,7 @@ function pfUI.uf:UpdateConfig()
if custompbg == "1" then
local cr, cg, cb, ca = GetStringColor(custompbgcolor)
cr, cg, cb, ca = tonumber(cr), tonumber(cg), tonumber(cb), tonumber(ca)
f.power.bar:SetStatusBarBackgroundTexture(cr,cg,cb,ca)
f.power.bar:SetStatusBarBackgroundColor(cr,cg,cb,ca)
end
local fontname, fontsize, fontstyle
@@ -829,6 +862,7 @@ function pfUI.uf:UpdateConfig()
f.buffs[i].cd.pfCooldownType = "ALL"
f.buffs[i].cd.pfCooldownStyleText = cooldown_text
f.buffs[i].cd.pfCooldownStyleAnimation = cooldown_anim
f.buffs[i].cd.pfCooldownReverse = cooldown_reverse
f.buffs[i].cd:SetAlpha(cooldown_anim == 1 and 1 or 0)
-- immediately show/hide existing cooldown text
@@ -889,6 +923,7 @@ function pfUI.uf:UpdateConfig()
f.debuffs[i].cd.pfCooldownType = "ALL"
f.debuffs[i].cd.pfCooldownStyleText = cooldown_text
f.debuffs[i].cd.pfCooldownStyleAnimation = cooldown_anim
f.debuffs[i].cd.pfCooldownReverse = cooldown_reverse
f.debuffs[i].cd:SetAlpha(cooldown_anim == 1 and 1 or 0)
-- immediately show/hide existing cooldown text
@@ -1241,8 +1276,6 @@ function pfUI.uf.OnUpdate()
end
end
if not this.label or this.label == "" then return end
-- update portrait on first visible frame
if this.portrait and this.portrait.model and this.portrait.model.update then
this.portrait.model.lastUnit = UnitName(this.portrait.model.update)
@@ -1329,11 +1362,7 @@ end
-- ============================================================
function pfUI.uf.OnClick()
if not this.label and this.unitname then
TargetByName(this.unitname, true)
else
pfUI.uf:ClickAction(arg1)
end
pfUI.uf:ClickAction(arg1)
end
function pfUI.uf:ClickAction(button)
@@ -1430,13 +1459,6 @@ function pfUI.uf:CreateUnitFrame(unit, id, config, tick)
f.config = config or pfUI_config.unitframes.fallback
f.tick = tick
-- disable events for unknown unitstrings
if not pfValidUnits[strlower(unit) .. id] then
f.unitname = unit
f.label, f.id = "", ""
f.RegisterEvent = function() return end
end
CreateBackdropShadow(f)
f.hp = CreateFrame("Frame",nil, f)
@@ -1487,7 +1509,7 @@ function pfUI.uf:CreateUnitFrame(unit, id, config, tick)
f.incHeal = CreateFrame("Frame", nil, f.hp)
-- Texture lives on hp.bar for correct draw order:
-- hp.bar.bg (BACKGROUND) < incHeal (BORDER) < hp.bar.bar (NORMAL)
-- hp.bar.bg (a level below) < incHeal (BORDER) < hp.bar's fill (ARTWORK)
f.incHeal.texture = f.hp.bar:CreateTexture(nil, "BORDER")
f.incHeal.texture:SetAllPoints(f.incHeal)
-- Override Show/Hide since texture lives on hp.bar, not incHeal
@@ -1553,9 +1575,7 @@ function pfUI.uf:CreateUnitFrame(unit, id, config, tick)
f:Hide()
end
if f.label ~= "" then
f:SetAttribute("unit", f.label .. f.id)
end
f:SetAttribute("unit", f.label .. f.id)
-- register frame for clique
_G.ClickCastFrames = ClickCastFrames or {}
-50
View File
@@ -1,50 +0,0 @@
-- barlength = {[formfactor]={cols, rows}}
pfGridmath = {
[1] = {{1,1}},
[2] = {{2,1},{1,2}},
[3] = {{3,1},{1,3}},
[4] = {{4,1},{2,2},{1,4}},
[5] = {{5,1},{1,5}},
[6] = {{6,1},{3,2},{2,3},{1,6}},
[7] = {{7,1},{1,7}},
[8] = {{8,1},{4,2},{2,4},{1,8}},
[9] = {{9,1},{3,3},{1,9}},
[10] = {{10,1},{5,2},{2,5},{1,10}},
[11] = {{11,1},{1,11}},
[12] = {{12,1},{6,2},{4,3},{3,4},{2,6},{1,12}}
}
-- list of valid unitstrings
pfValidUnits = {}
pfValidUnits["pet"] = true
pfValidUnits["player"] = true
pfValidUnits["target"] = true
pfValidUnits["mouseover"] = true
pfValidUnits["focus"] = true
pfValidUnits["focustarget"] = true
pfValidUnits["focustargettarget"] = true
pfValidUnits["pettarget"] = true
pfValidUnits["playertarget"] = true
pfValidUnits["targettarget"] = true
pfValidUnits["mouseovertarget"] = true
pfValidUnits["targettargettarget"] = true
for i=1,4 do
pfValidUnits["party" .. i] = true
pfValidUnits["party" .. i .. "target"] = true
pfValidUnits["partypet" .. i] = true
pfValidUnits["partypet" .. i .. "target"] = true
end
for i=1,40 do
pfValidUnits["raid" .. i] = true
pfValidUnits["raid" .. i .. "target"] = true
pfValidUnits["raidpet" .. i] = true
pfValidUnits["raidpet" .. i .. "target"] = true
pfValidUnits["nameplate" .. i] = true
pfValidUnits["nameplate" .. i .. "target"] = true
end
-1
View File
@@ -281,7 +281,6 @@ pfUI_translation["deDE"] = {
["Enable Energy Ticks"] = nil,
["Enable Extended Guild Information"] = nil,
["Enable Frame Shadow"] = nil,
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = nil,
["Enable Item Quality Color For Equipment Only"] = nil,
["Enable \"Loot & Spam\" Chat Window"] = nil,
-1
View File
@@ -290,7 +290,6 @@ pfUI_translation["enUS"] = {
["Enable Energy Ticks"] = nil,
["Enable Extended Guild Information"] = nil,
["Enable Frame Shadow"] = nil,
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = nil,
["Enable Item Quality Color For Equipment Only"] = nil,
["Enable \"Loot & Spam\" Chat Window"] = nil,
-1
View File
@@ -281,7 +281,6 @@ pfUI_translation["esES"] = {
["Enable Energy Ticks"] = "Activar tics de energía",
["Enable Extended Guild Information"] = "Activar información de hermandad extendida",
["Enable Frame Shadow"] = "Activar sombra del marco",
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = "Activar indicadores",
["Enable Item Quality Color For Equipment Only"] = "Mostrar el color de calidad de objetos solo para equipo",
["Enable \"Loot & Spam\" Chat Window"] = "Activar ventana de chat \"Botín y spam\"",
+70 -1
View File
@@ -281,7 +281,6 @@ pfUI_translation["frFR"] = {
["Enable Energy Ticks"] = "Activer la barre de rechargement d'énergie",
["Enable Extended Guild Information"] = "Activer les informations de guilde étendues",
["Enable Frame Shadow"] = "Activer l'ombre des cadres",
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = "Activer les indicateurs",
["Enable Item Quality Color For Equipment Only"] = "Activer la couleur de la qualité des objets seulement sur les pièces d'équipement",
["Enable \"Loot & Spam\" Chat Window"] = "Activer la fenêtre de chat \"Butins & Spam\"",
@@ -890,4 +889,74 @@ pfUI_translation["frFR"] = {
["Zonetime"] = nil,
["Zoom & Fade"] = "Zoom et fondu",
["Zoom Target Nameplate"] = "Zoom la cible des barres de vie flottantes",
["%d items, %d ignored"] = "%d objets, %d ignorés",
["Add the current zone"] = "Ajouter la zone actuelle",
["Announce Automatic Set Switches In Chat"] = "Annoncer les changements automatiques d'ensemble dans le chat",
["Any Form"] = "N'importe quelle forme",
["Aquatic Form"] = "Forme aquatique",
["Automatic Set Switching"] = "Changement automatique d'ensemble",
["Battle Stance"] = "Posture de combat",
["Battleground"] = "Champ de bataille",
["Bear Form"] = "Forme d'ours",
["Berserker Stance"] = "Posture berserker",
["Cat Form"] = "Forme de félin",
["Condition met, but a trigger higher in the list wins"] = "Condition remplie, mais un déclencheur plus haut dans la liste est prioritaire",
["Create an equipment set first."] = "Créez d'abord un ensemble d'équipement.",
["Currently active"] = "Actuellement actif",
["Defensive Stance"] = "Posture défensive",
["Do Nothing"] = "Ne rien faire",
["Dungeon"] = "Donjon",
["Eating / Drinking"] = "Manger / Boire",
["Enable Automatic Set Switching"] = "Activer le changement automatique d'ensemble",
["Equip"] = "Équiper",
["Equip sets automatically when mounted, swimming, eating, in a zone, at a given time and more."] = "Équipe automatiquement des ensembles en monture, en nageant, en mangeant, dans une zone, à une heure donnée, etc.",
["Equipment Manager"] = "Gestionnaire d'équipement",
["Equippable items in your bags, bank and paperdoll that no equipment set uses."] = "Objets équipables dans vos sacs, votre banque et sur votre personnage qu'aucun ensemble n'utilise.",
["Equipping %s"] = "Équipement de %s",
["Equipping %s (%s)"] = "Équipement de %s (%s)",
["Every equippable item is part of a set."] = "Tous les objets équipables font partie d'un ensemble.",
["Ghost Wolf"] = "Loup fantôme",
["Here"] = "Ici",
["Ignored (Right-Click to unignore)"] = "Ignoré (clic droit pour ne plus ignorer)",
["In Bags"] = "Dans les sacs",
["In Bank"] = "En banque",
["Include Bank Items"] = "Inclure les objets en banque",
["Instance Type"] = "Type d'instance",
["Items Not In Any Set"] = "Objets hors de tout ensemble",
["Local time window, e.g. 20:00-23:00"] = "Plage horaire locale, ex. 20:00-23:00",
["Minimum Item Quality"] = "Qualité minimale des objets",
["Moonkin Form"] = "Forme de sélénien",
["Mounted"] = "En monture",
["New Trigger"] = "Nouveau déclencheur",
["No Form (Caster)"] = "Sans forme (lanceur de sorts)",
["No set selected"] = "Aucun ensemble choisi",
["No triggers yet. Click \"New Trigger\" to add one."] = "Aucun déclencheur. Cliquez sur \"Nouveau déclencheur\" pour en ajouter un.",
["Not part of any equipment set"] = "Ne fait partie d'aucun ensemble",
["Open World"] = "Monde extérieur",
["Resting (Inn / City)"] = "Repos (auberge / ville)",
["Restore Previous Gear"] = "Remettre l'équipement précédent",
["Restoring previous gear"] = "Remise de l'équipement précédent",
["Select a trigger to edit it."] = "Sélectionnez un déclencheur pour le modifier.",
["Selected Trigger"] = "Déclencheur sélectionné",
["Separate several zones with ;"] = "Séparez plusieurs zones par ;",
["Shadowform"] = "Forme d'Ombre",
["Shapeshift Form / Stance"] = "Forme / Posture",
["Shift-Click: Link Ctrl-Click: Preview\nRight-Click: Ignore / Unignore"] = "Maj-clic : lien Ctrl-clic : aperçu\nClic droit : ignorer / ne plus ignorer",
["Show Ignored"] = "Afficher les ignorés",
["Stealth"] = "Camouflage",
["Stealthed"] = "Camouflé",
["Swimming"] = "À la nage",
["Targeting A Boss"] = "Cible un boss",
["Time Of Day"] = "Heure de la journée",
["Travel Form"] = "Forme de voyage",
["Tree of Life Form"] = "Forme d'arbre de vie",
["Triggers"] = "Déclencheurs",
["Triggers higher in the list take priority. Gear is never swapped in combat, while dead or while casting: the switch waits until it can happen."] = "Les déclencheurs en haut de la liste sont prioritaires. L'équipement n'est jamais changé en combat, mort ou pendant une incantation : le changement attend que ce soit possible.",
["Unused"] = "Inutilisés",
["Value"] = "Valeur",
["When"] = "Quand",
["When It Ends"] = "À la fin",
["Windows may wrap past midnight (22:00-02:00)."] = "Une plage peut passer minuit (22:00-02:00).",
["Zone"] = "Zone",
["Zone or subzone name"] = "Nom de zone ou de sous-zone",
}
-1
View File
@@ -281,7 +281,6 @@ pfUI_translation["koKR"] = {
["Enable Energy Ticks"] = "Energy Ticks 활성화",
["Enable Extended Guild Information"] = "길드 정보 확장 사용",
["Enable Frame Shadow"] = nil,
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = nil,
["Enable Item Quality Color For Equipment Only"] = "착용장비 전용 아이템품질 색상 활성화",
["Enable \"Loot & Spam\" Chat Window"] = "\"루팅 & 스팜\"채팅 창 사용",
-1
View File
@@ -281,7 +281,6 @@ pfUI_translation["ruRU"] = {
["Enable Energy Ticks"] = "Включить восполнение энергии",
["Enable Extended Guild Information"] = "Включить расширенную информацию о гильдии",
["Enable Frame Shadow"] = "Включить тень окон",
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = "Включить индикаторы",
["Enable Item Quality Color For Equipment Only"] = "Включить цвет качества предметов только для экипировки",
["Enable \"Loot & Spam\" Chat Window"] = "Включить окно чата \"Добыча & Спам\"",
-1
View File
@@ -281,7 +281,6 @@ pfUI_translation["zhCN"] = {
["Enable Energy Ticks"] = "显示能量刻度",
["Enable Extended Guild Information"] = "公会信息扩展显示",
["Enable Frame Shadow"] = "启用框架阴影",
["Enable Full-Text Search"] = "启用全文搜索",
["Enable Indicators"] = "启用指示器",
["Enable Item Quality Color For Equipment Only"] = "仅在装备上显示品质颜色",
["Enable \"Loot & Spam\" Chat Window"] = "启用[拾取、综合]聊天窗口",
-1
View File
@@ -281,7 +281,6 @@ pfUI_translation["zhTW"] = {
["Enable Energy Ticks"] = "顯示能量刻度",
["Enable Extended Guild Information"] = "公會資訊擴展顯示",
["Enable Frame Shadow"] = "啟用框架陰影",
["Enable Full-Text Search"] = nil,
["Enable Indicators"] = nil,
["Enable Item Quality Color For Equipment Only"] = "僅在裝備上顯示品質顏色",
["Enable \"Loot & Spam\" Chat Window"] = "啟用[拾取、綜合]聊天視窗",
-1
View File
@@ -7,7 +7,6 @@
<Include file="..\env\locales_esES.lua"/>
<Include file="..\env\locales_ruRU.lua"/>
<Include file="..\env\tables.lua"/>
<Include file="..\env\profiles.lua"/>
<Include file="..\env\translations_enUS.lua"/>
+6 -4
View File
@@ -482,13 +482,15 @@ function libpredict:ParseChatMessage(sender, msg, comm)
if cmd and ctratarget and cmd == "RES" and ctratarget ~= "" and ctratarget ~= UNKNOWN then
msgtype = "Ress"
target = ctratarget
elseif cmd == "RESNO" then
msgtype = "RessStop"
end
end
if msgtype == "Stop" and sender then
libpredict:HealStop(sender)
return
elseif ( msg == "RessStop" or msg == "RESNO" ) and sender then
elseif msgtype == "RessStop" and sender then
libpredict:RessStop(sender)
return
elseif msgtype == "Delay" and time then
@@ -834,7 +836,6 @@ local pendingHots = {}
-- Gather Data by User Actions
hooksecurefunc("CastSpell", function(id, bookType)
if not libpredict.sender.enabled then return end
local effect, rank = libspell.GetSpellInfo(id, bookType)
if not effect then return end
spell_queue[1] = effect
@@ -887,7 +888,6 @@ hooksecurefunc("CastSpell", function(id, bookType)
end)
hooksecurefunc("CastSpellByName", function(effect, target)
if not libpredict.sender.enabled then return end
local effect, rank = libspell.GetSpellInfo(effect)
if not effect then return end
@@ -951,7 +951,6 @@ hooksecurefunc("CastSpellByName", function(effect, target)
end)
hooksecurefunc("UseAction", function(slot, target, selfcast)
if not libpredict.sender.enabled then return end
if not IsCurrentAction(slot) then return end
local kind, id = GetActionInfo(slot)
local effect, rank
@@ -1012,8 +1011,10 @@ hooksecurefunc("UseAction", function(slot, target, selfcast)
end)
libpredict.sender = CreateFrame("Frame", "pfPredictionSender", UIParent)
-- cleared when a HealComm addon already broadcasts this player's casts
libpredict.sender.enabled = true
libpredict.sender.SendHealCommMsg = function(self, msg)
if not self.enabled then return end
-- Smart channel selection: Only send to relevant channel to avoid duplicates
if IsInRaid() then
-- In raid: Only send to RAID (includes all raid members)
@@ -1026,6 +1027,7 @@ libpredict.sender.SendHealCommMsg = function(self, msg)
-- BG groups are handled by RAID channel
end
libpredict.sender.SendResCommMsg = function(self, msg)
if not self.enabled then return end
-- Smart channel selection: Only send to relevant channel to avoid duplicates
if IsInRaid() then
-- In raid: Only send to RAID (includes all raid members)
+2 -14
View File
@@ -382,8 +382,6 @@ pfUI:RegisterModule("actionbar", function ()
end
elseif self.spellID then
GameTooltip:SetSpellByID(self.spellID)
elseif self.spellslot and self.booktype then
GameTooltip:SetSpell(self.spellslot, self.booktype)
else
GameTooltip:SetAction(self.id)
end
@@ -456,11 +454,6 @@ pfUI:RegisterModule("actionbar", function ()
id = self.bar == 1 and self.slot or sid-((self.bar)-1)*12
end
-- overwrite with spell macro texture where possible
if self.spellslot and self.booktype then
texture = GetSpellTexture(self.spellslot, self.booktype)
end
if not self.showempty and self.backdrop and not texture and grid == 0 then
self.backdrop:Hide()
self.hide = true
@@ -590,9 +583,6 @@ pfUI:RegisterModule("actionbar", function ()
start, duration, enable = GetShapeshiftFormCooldown(button.id)
elseif button.bar == 12 then
start, duration, enable = GetPetActionCooldown(button.id)
elseif button.spellslot and button.booktype then
start, duration = GetSpellCooldown(button.spellslot, button.booktype)
enable = 1
else
start, duration, enable = GetActionCooldown(button.id)
end
@@ -1045,6 +1035,7 @@ pfUI:RegisterModule("actionbar", function ()
-- cooldown
f.cd = CreateFrame("Cooldown", f:GetName() .. "Cooldown", f, "CooldownFrameTemplate")
f.cd.pfCooldownStyleAnimation = 1
f.cd.pfCooldownReverse = tonumber(C.bars.cooldown_reverse) or 0
f.cd.pfCooldownType = "NOGCD"
f.cd.pfCooldownSize = cd_size
@@ -1149,8 +1140,6 @@ pfUI:RegisterModule("actionbar", function ()
f.count:SetJustifyH("RIGHT")
f.count:SetJustifyV("BOTTOM")
f.scanmacro, f.spellslot, f.booktype = nil, nil, nil
-- range glow color
f.rangeColor = GetStringColorObject(C.bars.rangecolor)
@@ -1217,8 +1206,7 @@ pfUI:RegisterModule("actionbar", function ()
end
-- the stored layout is invalid, temporary fallback
local _, _, fcols, frows = string.find(tostring(formfactor or ""), "(%d+)%s*x%s*(%d+)")
if not ((fcols and frows) or pfGridmath[buttons][BarLayoutFormfactor(formfactor)]) then
if not fcols2 or not frows2 then
formfactor = BarLayoutOptions(buttons)[1]
end
+31 -55
View File
@@ -6,8 +6,6 @@ pfUI:RegisterModule("bags", function ()
[1804] = {frame="picklock"},
}
local scanner = libtipscan:GetScanner("input_search")
local function BagSortOpts()
return {
reverse = C.appearance.bags.sortreverse == "1",
@@ -95,6 +93,7 @@ pfUI:RegisterModule("bags", function ()
pfUI.bag:RegisterEvent("ITEM_LOCK_CHANGED")
pfUI.bag:RegisterEvent("SPELLS_CHANGED")
pfUI.bag:RegisterEvent("MERCHANT_CLOSED")
pfUI.bag:RegisterEvent("INVENTORY_SEARCH_UPDATE")
pfUI.bag.delay = { UpdateBag = {} }
@@ -122,6 +121,11 @@ pfUI:RegisterModule("bags", function ()
pfUI.bag:UpdateItemLock()
end
if this.delay.UpdateSearch then
this.delay.UpdateSearch = nil
pfUI.bag:UpdateSearch()
end
for bag in pairs(this.delay.UpdateBag) do
this.delay.UpdateBag[bag] = nil
pfUI.bag:UpdateBag(bag)
@@ -159,6 +163,10 @@ pfUI:RegisterModule("bags", function ()
this.delay.UpdateItemLock = true
end
if event == "INVENTORY_SEARCH_UPDATE" then
this.delay.UpdateSearch = true
end
if event == "PLAYERBANKSLOTS_CHANGED" then
this.delay.UpdateBag[-1] = true
end
@@ -377,6 +385,21 @@ pfUI:RegisterModule("bags", function ()
end
end
-- dim the slots that the bag search (C_Container.SetItemSearch) filters out
local searchInfo = {}
function pfUI.bag:UpdateSlotSearch(bag, slot)
local info = C_Container.GetContainerItemInfo(bag, slot, searchInfo)
pfUI.bags[bag].slots[slot].frame:SetAlpha(info and info.isFiltered and .25 or 1)
end
function pfUI.bag:UpdateSearch()
for bag = -2, 11 do
for slot in ipairs(pfUI.bags[bag].slots) do
pfUI.bag:UpdateSlotSearch(bag, slot)
end
end
end
function pfUI.bag:UpdateSlot(bag, slot)
if not pfUI.bags[bag] then return end
@@ -398,11 +421,13 @@ pfUI:RegisterModule("bags", function ()
local name = "pfBag" .. bag .. "item" .. slot .. "Cooldown"
bankslot.cd = CreateFrame("Cooldown", name, bankslot, "CooldownFrameTemplate")
bankslot.cd.pfCooldownStyleAnimation = 1
bankslot.cd.pfCooldownReverse = tonumber(C.appearance.bags.cooldown_reverse) or 0
bankslot.cd.pfCooldownType = "NOGCD"
else
local bagslot = pfUI.bags[bag].slots[slot].frame
bagslot.cd = _G[bagslot:GetName().."Cooldown"]
bagslot.cd.pfCooldownType = "NOGCD"
bagslot.cd.pfCooldownReverse = tonumber(C.appearance.bags.cooldown_reverse) or 0
end
if not pfUI.bags[bag].slots[slot].frame.backdrop then
@@ -463,6 +488,7 @@ pfUI:RegisterModule("bags", function ()
SetItemButtonTexture(pfUI.bags[bag].slots[slot].frame, texture)
SetItemButtonCount(pfUI.bags[bag].slots[slot].frame, count)
SetItemButtonDesaturated(pfUI.bags[bag].slots[slot].frame, locked, 0.5, 0.5, 0.5)
pfUI.bag:UpdateSlotSearch(bag, slot)
local hasItem = texture and 1 or nil
pfUI.bags[bag].slots[slot].frame.hasItem = hasItem
@@ -1008,7 +1034,6 @@ pfUI:RegisterModule("bags", function ()
-- bag search
if not frame.search then
frame.search = CreateFrame("Frame", "pfBagSearch", frame)
frame.search.db = {}
frame.search:SetHeight(12)
frame.search:SetPoint("TOPLEFT", frame, "TOPLEFT", default_border, -default_border)
frame.search:SetPoint("TOPRIGHT", frame.sort, "TOPLEFT", -default_border*3, -default_border)
@@ -1033,51 +1058,12 @@ pfUI:RegisterModule("bags", function ()
frame.search.edit:SetScript("OnEditFocusLost", function()
this:SetText(T["Search"])
for bag=-2, 11 do
local bagsize = GetContainerNumSlots(bag)
if bag == -2 and pfUI.bag.showKeyring == true then bagsize = GetKeyRingSize() end
for slot=1, bagsize do
pfUI.bags[bag].slots[slot].frame:SetAlpha(1)
end
end
C_Container.SetItemSearch("")
end)
frame.search.edit:SetScript("OnTextChanged", function()
if this:GetText() == T["Search"] then return end
for bag=-2, 11 do
local bagsize = GetContainerNumSlots(bag)
if bag == -2 and pfUI.bag.showKeyring == true then bagsize = GetKeyRingSize() end
for slot=1, bagsize do
pfUI.bags[bag].slots[slot].frame:SetAlpha(.25)
local texture, itemCount, locked, quality, readable = GetContainerItemInfo(bag, slot)
if itemCount then
local itemLink = GetContainerItemLink(bag, slot)
local itemstring = string.sub(itemLink, string.find(itemLink, "%[")+1, string.find(itemLink, "%]")-1)
if C.appearance.bags.fulltext == "1" then
if not frame.search.db[itemLink] then
scanner:SetBagItem(bag, slot)
local text = scanner:Text()
local str = ""
for k, v in pairs(text) do
str = str .. (v[1] or "") .. (v[2] or "")
end
frame.search.db[itemLink] = strlower(str)
end
if strfind(frame.search.db[itemLink], strlower(this:GetText()), 1, true) then
pfUI.bags[bag].slots[slot].frame:SetAlpha(1)
end
end
if strfind(strlower(itemstring), strlower(this:GetText()), 1, true) then
pfUI.bags[bag].slots[slot].frame:SetAlpha(1)
end
end
end
end
C_Container.SetItemSearch(this:GetText())
end)
frame.search:SetScript("OnLeave", function()
@@ -1092,17 +1078,7 @@ pfUI:RegisterModule("bags", function ()
frame.search:SetScript("OnHide", function()
frame.search.edit:SetText(T["Search"])
for bag = -2, 11 do
if pfUI.bags[bag] then
local bagsize = GetContainerNumSlots(bag)
if bag == -2 and pfUI.bag.showKeyring == true then bagsize = GetKeyRingSize() end
for slot = 1, bagsize do
if pfUI.bags[bag] and pfUI.bags[bag].slots[slot] then
pfUI.bags[bag].slots[slot].frame:SetAlpha(1)
end
end
end
end
C_Container.SetItemSearch("")
end)
end
else
+43 -3
View File
@@ -33,7 +33,7 @@ pfUI:RegisterModule("buff", function ()
end
local slots = buff.btype == "HELPFUL" and helpfulSlots or harmfulSlots
local name, icon, count, dispelType, _, expirationTime, _, _, _, spellId = C_UnitAuras.UnitAuraBySlot("player", slots[buff.id])
local name, icon, count, dispelType, duration, expirationTime, _, _, _, spellId = C_UnitAuras.UnitAuraBySlot("player", slots[buff.id])
--detect weapon buffs
if buff.btype == "HELPFUL" and ((C.buffs.separateweapons == "0" and buff.gid <= pfUI.buff.wepbuffs.count) or (pfUI.buff.wepbuffs.count > 0 and buff.weapon ~= nil)) then
@@ -84,6 +84,28 @@ pfUI:RegisterModule("buff", function ()
return
end
-- drive the sweep from the aura duration (weapon enchants and permanent
-- auras report no usable total, so those buttons stay text-only)
if buff.mode == buff.btype and duration and duration > 0 and expirationTime and expirationTime > 0 then
local now = GetTime()
local timeleft = expirationTime - now
if timeleft > 0 then
local effDuration = duration > timeleft and duration or timeleft
local newStart = now + timeleft - effDuration
if buff.cdStart == nil or abs(buff.cdStart - newStart) > .5 or buff.cdDuration ~= effDuration then
CooldownFrame_SetTimer(buff.cd, newStart, effDuration, 1)
buff.cdStart = newStart
buff.cdDuration = effDuration
end
else
CooldownFrame_SetTimer(buff.cd, 0, 0, 0)
buff.cdStart = nil
end
else
CooldownFrame_SetTimer(buff.cd, 0, 0, 0)
buff.cdStart = nil
end
buff:Show()
end
@@ -106,17 +128,33 @@ pfUI:RegisterModule("buff", function ()
buff.texture:SetTexCoord(.07,.93,.07,.93)
buff.texture:SetAllPoints(buff)
buff.timer = buff:CreateFontString(nil, "OVERLAY", "GameFontNormal")
-- overlay lifts the texts above the sweep: a child frame renders above
-- all of its parent's own regions, so the timer would dim under the
-- dark wedge otherwise (same reason pfCooldownText is its own frame)
buff.overlay = CreateFrame("Frame", nil, buff)
buff.overlay:SetAllPoints(buff)
buff.timer = buff.overlay:CreateFontString(nil, "OVERLAY", "GameFontNormal")
buff.timer:SetTextColor(1,1,1,1)
buff.timer:SetJustifyH("CENTER")
buff.timer:SetJustifyV("CENTER")
buff.stacks = buff:CreateFontString(nil, "OVERLAY", "GameFontNormal")
buff.stacks = buff.overlay:CreateFontString(nil, "OVERLAY", "GameFontNormal")
buff.stacks:SetTextColor(1,1,1,1)
buff.stacks:SetJustifyH("RIGHT")
buff.stacks:SetJustifyV("BOTTOM")
buff.stacks:SetAllPoints(buff)
-- radial sweep (the template covers the button and starts hidden;
-- the cooldown hook drives it from here, text stays with buff.timer)
buff.cd = CreateFrame("Cooldown", buttonName .. "Cooldown", buff, "CooldownFrameTemplate")
buff.cd:SetFrameLevel(buff:GetFrameLevel() + 1)
buff.overlay:SetFrameLevel(buff:GetFrameLevel() + 2)
buff.cd.pfCooldownType = "ALL"
buff.cd.pfCooldownStyleText = 0
buff.cd.pfCooldownStyleAnimation = tonumber(C.buffs.cooldown_anim) or 0
buff.cd.pfCooldownReverse = tonumber(C.buffs.cooldown_reverse) or 0
buff:RegisterForClicks("RightButtonUp")
buff.weapon = weapon
@@ -307,6 +345,8 @@ pfUI:RegisterModule("buff", function ()
offsetY = -(rowcount) * ((C.buffs.textinside == "1" and 0 or (fontsize*1.5))+buffSize+2*buffSpacing)
end
buff:SetSize(buffSize, buffSize)
buff.cd.pfCooldownStyleAnimation = tonumber(C.buffs.cooldown_anim) or 0
buff.cd.pfCooldownReverse = tonumber(C.buffs.cooldown_reverse) or 0
buff:ClearAllPoints()
buff:SetPoint("TOPRIGHT", relFrame, "TOPRIGHT",offsetX, offsetY)
+6 -11
View File
@@ -150,8 +150,8 @@ pfUI:RegisterModule("castbar", function ()
-- One-shot poll: read C_Spell for the bar's unit, stamp or clear. Called
-- from event handlers (cast start, target/focus change), never per-frame.
local function RefreshBar(cb, rank)
local query = cb.unitstr ~= "" and cb.unitstr or cb.unitname
if not query or (cb.unitstr ~= "" and not UnitExists(cb.unitstr)) then
local query = cb.unitstr
if not UnitExists(query) then
ClearBar(cb)
return
end
@@ -178,7 +178,7 @@ pfUI:RegisterModule("castbar", function ()
end
end
local function CreateCastbar(name, parent, unitstr, unitname)
local function CreateCastbar(name, parent, unitstr)
local cb = CreateFrame("Frame", name, parent or UIParent)
cb:SetHeight(C.global.font_size * 1.5)
@@ -186,7 +186,6 @@ pfUI:RegisterModule("castbar", function ()
cb:SetFrameLevel(8)
cb.unitstr = unitstr
cb.unitname = unitname
-- icon
cb.icon = CreateFrame("Frame", nil, cb)
@@ -277,7 +276,7 @@ pfUI:RegisterModule("castbar", function ()
-- Non-player bars: if the unit disappears (target died / detarget),
-- drop the bar immediately.
if this.unitstr ~= "" and this.unitstr ~= "player" and not UnitExists(this.unitstr) then
if this.unitstr ~= "player" and not UnitExists(this.unitstr) then
ClearBar(this)
return
end
@@ -423,13 +422,12 @@ pfUI:RegisterModule("castbar", function ()
-- endMs. delay is a positive magnitude; OnUpdate signs it "+" for casts
-- and "-" for channels. Skipped during a tradeskill merge.
if this.endTime and not this.tradeskillTotal then
local query = this.unitstr ~= "" and this.unitstr or this.unitname
local startMs, endMs
if this.isChannel then
local _, _, _, s, e = C_Spell.UnitChannelInfo(query)
local _, _, _, s, e = C_Spell.UnitChannelInfo(unit)
startMs, endMs = s, e
else
local _, _, _, s, e = C_Spell.UnitCastingInfo(query)
local _, _, _, s, e = C_Spell.UnitCastingInfo(unit)
startMs, endMs = s, e
end
if startMs and endMs then
@@ -544,9 +542,6 @@ pfUI:RegisterModule("castbar", function ()
pfUI.castbar.focus:SetHeight(C.castbar.focus.height)
end
-- bind castbar to the "focus" unit token; the GUID resolves at read time
pfUI.castbar.focus.unitstr = "focus"
UpdateMovable(pfUI.castbar.focus)
end
end)
+6
View File
@@ -142,6 +142,12 @@ pfUI:RegisterModule("cooldown", function ()
this:SetAlpha(0)
end
-- reversed sweep direction (ClassicAPI backports SetReverse with the
-- modern Cooldown frame; stock Model swipes don't have it, so guard it)
if this.pfCooldownReverse == 1 and this.SetReverse then
this:SetReverse(true)
end
-- print time as text on cooldown frames
if ( not this.pfCooldownStyleText or this.pfCooldownStyleText == 1)
and start > 0 and duration > 0 and (not enable or enable > 0) then
File diff suppressed because it is too large Load Diff
+5 -28
View File
@@ -29,38 +29,15 @@ pfUI:RegisterModule("focus", function ()
end)
-- /focus and /clearfocus live in ClassicAPI's SlashCommandsRegistry now.
-- /focusname is pfUI-specific because the engine has no name→GUID
-- lookup for off-screen units — we resolve via a short target-swap.
-- `/focus Name` takes the nearest prefix match; /focusname tries the exact
-- name first, so "Bob" still wins over a nearer "Bobby".
pfUI.api.RegisterSlashCommand("PFFOCUSNAME", { '/focusname', '/pffocusname' }, function(msg)
if msg == "" then return end
local prevGUID = UnitGUID("target")
local prevPlayer = UnitIsUnit("target", "player")
-- Suppress async "Unknown unit" errors fired by TargetByName misses.
UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE")
-- Try exact match first, then prefix match via /target.
TargetByName(msg, true)
if not UnitExists("target") then
SlashCmdList.TARGET(msg)
end
if UnitExists("target") then
FocusUnit("target")
end
RunNextFrame(function()
UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE")
end)
if prevGUID and prevGUID ~= "0x0000000000000000" then
TargetUnit(prevGUID)
elseif prevPlayer then
TargetUnit("player")
else
ClearTarget()
local unit = UnitTokenFromName(msg, true) or UnitTokenFromName(msg)
if unit then
FocusUnit(unit)
end
end, true)
+22 -1
View File
@@ -2341,6 +2341,7 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(U[c], T["Timer"], nil, nil, "header")
CreateConfig(U[c], T["Show Timer Text"], C.unitframes[c], "cooldown_text", "checkbox")
CreateConfig(Reload, T["Show Timer Animation"], C.unitframes[c], "cooldown_anim", "checkbox")
CreateConfig(Reload, T["Reverse Timer Animation"], C.unitframes[c], "cooldown_reverse", "checkbox")
CreateConfig(U[c], T["Buffs"], nil, nil, "header")
CreateConfig(U[c], T["Buff Position"], C.unitframes[c], "buffs", "dropdown", pfUI.gui.dropdowns.uf_buff_position)
@@ -2427,6 +2428,21 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Always Show Equipment Slot Flyouts"], C.character.inventory, "equipflyout", "checkbox")
end)
CreateGUIEntry(T["Character"], T["Equipment Manager"], function()
CreateConfig(nil, T["Automatic Set Switching"], nil, nil, "header")
CreateConfig(U["equipmentmanager"], T["Enable Automatic Set Switching"], C.equipmentmanager, "autoswitch", "checkbox")
CreateConfig(U["equipmentmanager"], T["Announce Automatic Set Switches In Chat"], C.equipmentmanager, "announce", "checkbox")
CreateConfig(nil, T["Items Not In Any Set"], nil, nil, "header")
CreateConfig(U["equipmentmanager"], T["Minimum Item Quality"], C.equipmentmanager, "unusedquality", "dropdown", {
"0:" .. ITEM_QUALITY0_DESC,
"1:" .. ITEM_QUALITY1_DESC,
"2:" .. ITEM_QUALITY2_DESC,
"3:" .. ITEM_QUALITY3_DESC,
"4:" .. ITEM_QUALITY4_DESC,
})
CreateConfig(U["equipmentmanager"], T["Include Bank Items"], C.equipmentmanager, "unusedbank", "checkbox")
end)
CreateGUIEntry(T["Character"], T["Reputation"], function()
CreateConfig(nil, T["Show Reputation Remaining"], C.character.reputation, "repRequired", "checkbox")
end)
@@ -2443,8 +2459,8 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Hide Chat When Bags Are Opened"], C.appearance.bags, "hidechat", "checkbox")
CreateConfig(nil, T["Bagslots Per Row"], C.appearance.bags, "bagrowlength")
CreateConfig(nil, T["Bankslots Per Row"], C.appearance.bags, "bankrowlength")
CreateConfig(nil, T["Enable Full-Text Search"], C.appearance.bags, "fulltext")
CreateConfig(nil, T["Item Slot Size"], C.appearance.bags, "icon_size")
CreateConfig(Reload, T["Reverse Cooldown Animation"], C.appearance.bags, "cooldown_reverse", "checkbox")
CreateConfig(nil, T["Auto Sell Grey Items"], C.global, "autosell", "checkbox")
CreateConfig(nil, T["Auto Repair Items"], C.global, "autorepair", "checkbox")
CreateConfig(nil, T["Auto Sort When Opening Bags"], C.appearance.bags, "autoSortOnOpen", "checkbox")
@@ -2495,6 +2511,8 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(U["buff"], T["Number Of Debuffs Per Row"], C.buffs, "debuffrowsize")
CreateConfig(U["buff"], T["Show Duration Inside Buff"], C.buffs, "textinside", "checkbox")
CreateConfig(U["buff"], T["Buff Font Size"], C.buffs, "fontsize")
CreateConfig(Reload, T["Show Timer Animation"], C.buffs, "cooldown_anim", "checkbox")
CreateConfig(Reload, T["Reverse Timer Animation"], C.buffs, "cooldown_reverse", "checkbox")
end)
CreateGUIEntry(T["Buffs"], T["Totem Icons"], function()
@@ -2502,6 +2520,7 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(U["totems"], T["Icon Size"], C.totems, "iconsize")
CreateConfig(U["totems"], T["Spacing"], C.totems, "spacing", "dropdown", pfUI.gui.dropdowns.spacing)
CreateConfig(U["totems"], T["Show Background"], C.totems, "showbg", "checkbox")
CreateConfig(Reload, T["Reverse Cooldown Animation"], C.totems, "cooldown_reverse", "checkbox")
end)
CreateGUIEntry(T["Buffs"], T["Player Buff Bar"], function()
@@ -2591,6 +2610,7 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(U["bars"], T["Keybind Text Size"], C.bars, "bind_size")
CreateConfig(U["bars"], T["Keybind Text Color"], C.bars, "bind_color", "color")
CreateConfig(nil, T["Cooldown Text Size"], C.bars, "cd_size")
CreateConfig(Reload, T["Reverse Cooldown Animation"], C.bars, "cooldown_reverse", "checkbox")
CreateConfig(nil, T["Auto Paging"], nil, nil, "header")
CreateConfig(U["bars"], T["Switch Pages On Alt Key Press"], C.bars, "pagemasteralt", "checkbox")
@@ -2960,6 +2980,7 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(U["nameplates"], T["Enable Debuff Timers"], C.nameplates, "debufftimers", "checkbox")
CreateConfig(U["nameplates"], T["Show Timer Text"], C.nameplates, "debufftext", "checkbox")
CreateConfig(Reload, T["Show Timer Animation"], C.nameplates, "debuffanim", "checkbox")
CreateConfig(Reload, T["Reverse Timer Animation"], C.nameplates, "debreverse", "checkbox")
CreateConfig(U["nameplates"], T["Filter Mode"], C.nameplates.debuffs, "filter", "dropdown", pfUI.gui.dropdowns.buffbarfilter)
CreateConfig(U["nameplates"], T["Blacklist"], C.nameplates.debuffs, "blacklist", "list")
+11 -7
View File
@@ -130,8 +130,8 @@ pfUI:RegisterModule("nameplates", function ()
cfg.targetcastbar = C.nameplates["targetcastbar"] == "1"
cfg.notargalpha = tonumber(C.nameplates.notargalpha) or 0.5
if cfg.notargalpha > 1 then cfg.notargalpha = cfg.notargalpha / 100 end
-- Clamp to 0.99 so non-target plates never reach 1.0 (used for target detection)
if cfg.notargalpha > 0.99 then cfg.notargalpha = 0.99 end
-- Clamp to 1.0 so a 100% setting yields full opacity (target detection is GUID-based)
if cfg.notargalpha > 1 then cfg.notargalpha = 1 end
cfg.namefightcolor = C.nameplates.namefightcolor == "1"
cfg.spellname = C.nameplates.spellname == "1"
cfg.showhp = C.nameplates.showhp == "1"
@@ -159,6 +159,7 @@ pfUI:RegisterModule("nameplates", function ()
cfg.debufftimers = C.nameplates.debufftimers == "1"
cfg.debuffanim = tonumber(C.nameplates.debuffanim) or 0
cfg.debufftext = tonumber(C.nameplates.debufftext) or 1
cfg.debreverse = tonumber(C.nameplates.debreverse) or 0
-- Throttle delays, resolved once instead of per plate per tick.
-- libthrottle:Get walks the saved-variable table, a defaults fallback and a
@@ -445,6 +446,7 @@ pfUI:RegisterModule("nameplates", function ()
-- Set initial config flags (will be cached per-cooldown later)
plate.debuffs[index].cd.pfCooldownStyleAnimation = cfg.debuffanim
plate.debuffs[index].cd.pfCooldownReverse = cfg.debreverse or 0
plate.debuffs[index].cd.pfCooldownStyleText = cfg.debufftext
plate.debuffs[index].cd.pfCooldownType = "ALL"
end
@@ -486,6 +488,7 @@ pfUI:RegisterModule("nameplates", function ()
local cooldown_anim = tonumber(C.nameplates.debuffanim) or 0
nameplate.debuffs[i].cd.pfCooldownStyleText = cooldown_text
nameplate.debuffs[i].cd.pfCooldownStyleAnimation = cooldown_anim
nameplate.debuffs[i].cd.pfCooldownReverse = tonumber(C.nameplates.debreverse) or 0
end
end
@@ -1396,12 +1399,14 @@ nameplates:RegisterUnitEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", "target", "focu
local cd = plate.debuffs[index].cd
cd:Show()
if not cachedStart or abs(cachedStart - newStart) > 0.5 then
if not cd.configCached or cd.cachedAnim ~= cfg.debuffanim or cd.cachedText ~= cfg.debufftext then
if not cd.configCached or cd.cachedAnim ~= cfg.debuffanim or cd.cachedText ~= cfg.debufftext or cd.cachedReverse ~= cfg.debreverse then
cd.pfCooldownStyleAnimation = cfg.debuffanim
cd.pfCooldownStyleText = cfg.debufftext
cd.pfCooldownReverse = cfg.debreverse or 0
cd:SetAlpha(cfg.debuffanim == 1 and 1 or 0)
cd.cachedAnim = cfg.debuffanim
cd.cachedText = cfg.debufftext
cd.cachedReverse = cfg.debreverse
cd.configCached = true
end
CooldownFrame_SetTimer(cd, newStart, effDuration, 1)
@@ -1445,11 +1450,10 @@ nameplates:RegisterUnitEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", "target", "focu
if not hasEventUpdate and (nameplate.lasttick or 0) + cfg.throttle_min > now then return end
-- PERF: Intelligent throttling based on target/castbar status and plate count
-- Use GUID comparison as primary target detection: instant, immune to alpha transitions,
-- Use GUID comparison for target detection: instant, immune to alpha transitions,
-- and immediately correct on de-target (unlike istarget which updates one tick later)
local targetGuid = state and state.targetGuid
local target = (targetGuid and nameplate.cachedGuid and targetGuid == nameplate.cachedGuid) or
(state and state.targetGuid and frame:GetAlpha() >= 0.99) or nil
local target = (targetGuid and nameplate.cachedGuid and targetGuid == nameplate.cachedGuid) or nil
-- Target plate castbar runs on its own dedicated frame (nameplates.castbarFrame).
-- For non-target plates with castbar active, use castbar throttle to ensure
-- smooth animation without overloading the central loop.
@@ -1967,4 +1971,4 @@ nameplates:RegisterUnitEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", "target", "focu
end)
pfUI.nameplates = nameplates
end)
end)
+45
View File
@@ -128,6 +128,51 @@ pfUI:RegisterModule("panel", function()
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(T["Memory Usage"], "|cffffffff" .. memmb)
GameTooltip:AddDoubleLine(T["Next Memory Cleanup"], "|cffffffff" .. gcmb)
-- AddOn memory usage (see MainMenuBarPerformanceBarFrame_OnEnter in MainMenuBar.lua)
local ADDON_MEM_KB_ABBR = _G.ADDON_MEM_KB_ABBR or "(%.0f KB) %s";
local ADDON_MEM_MB_ABBR = _G.ADDON_MEM_MB_ABBR or "(%.2f MB) %s";
local TOTAL_MEM_KB_ABBR = _G.TOTAL_MEM_KB_ABBR or "AddOn Memory: %.0f KB";
local TOTAL_MEM_MB_ABBR = _G.TOTAL_MEM_MB_ABBR or "AddOn Memory: %.2f MB";
UpdateAddOnMemoryUsage()
local totalMem = 0
local topAddOns = {}
for i = 1, GetNumAddOns() do
local mem = GetAddOnMemoryUsage(i)
if mem and mem > 0 then
totalMem = totalMem + mem
for j = 1, 3 do
if not topAddOns[j] or mem > topAddOns[j].value then
for k = 3, j + 1, -1 do
topAddOns[k] = topAddOns[k - 1]
end
topAddOns[j] = { value = mem, name = C_AddOns.GetAddOnName(i) }
break
end
end
end
end
if totalMem > 0 then
local str
if totalMem > 1000 then
str = format(TOTAL_MEM_MB_ABBR, totalMem / 1000)
else
str = format(TOTAL_MEM_KB_ABBR, totalMem)
end
GameTooltip:AddLine(" ")
GameTooltip:AddLine(str, 1, 1, 1)
for i = 1, 3 do
if not topAddOns[i] then break end
if topAddOns[i].value > 1000 then
str = format(ADDON_MEM_MB_ABBR, topAddOns[i].value / 1000, topAddOns[i].name)
else
str = format(ADDON_MEM_KB_ABBR, topAddOns[i].value, topAddOns[i].name)
end
GameTooltip:AddLine(str, 1, 1, 1)
end
end
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(T["Network Down"], "|cffffffff" .. round(nin,1) .. "KB/s")
GameTooltip:AddDoubleLine(T["Network Up"], "|cffffffff" .. round(nout,1) .. "KB/s")
+2 -14
View File
@@ -1172,21 +1172,9 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
end)
local EnableHealComm = function()
-- hook healcomm's addon message to parse single-player events
-- HealComm-1.0 already broadcasts this player's casts: keep libpredict
-- tracking them, but stop it sending a second copy
if AceLibrary and AceLibrary:HasInstance("HealComm-1.0") and pfUI.api.libpredict then
local HealComm = AceLibrary("HealComm-1.0")
-- use pfUI frames to draw healComm predictions
local pfHookHealCommSendAddonMessage = HealComm.SendAddonMessage
function HealComm.SendAddonMessage(this, msg)
if not IsInGroup() then
libpredict:ParseChatMessage(UnitName("player"), msg, "HealComm")
end
pfHookHealCommSendAddonMessage(this, msg)
end
-- disable pfUI predictions
pfUI.api.libpredict.sender:UnregisterAllEvents()
pfUI.api.libpredict.sender.enabled = nil
end
end
+1
View File
@@ -115,6 +115,7 @@ pfUI:RegisterModule("totems", function ()
self.bar[i].cdbg:SetPoint("CENTER", self.bar[i], "CENTER", 0, 0)
self.bar[i].cd = self.bar[i].cd or CreateFrame("Cooldown", "pfTotemsBar"..i.."Cooldown", self.bar[i].cdbg, "CooldownFrameTemplate")
self.bar[i].cd.pfCooldownStyleAnimation = 1
self.bar[i].cd.pfCooldownReverse = tonumber(pfUI_config.totems.cooldown_reverse) or 0
self.bar[i].cd.pfCooldownType = "ALL"
self.bar[i]:RegisterForClicks("LeftButtonUp", "RightButtonUp")
-15
View File
@@ -497,19 +497,4 @@ function pfUI.SetupCVars()
UIParentLoadAddOn("Blizzard_CombatText")
end
do -- RunMacroText
local obj = setmetatable({ ["GetText"] = function(self) return self.text end }, {
__index = function(tab,key)
local value = function() return end
rawset(tab,key,value)
return value
end
})
function RunMacroText(text)
obj.text = text
ChatEdit_ParseText(obj, 1)
end
end
_G.PLAYER_BUFF_START_ID = -1
+1 -1
View File
@@ -5,7 +5,7 @@
## Notes-ruRU: Полная замена пользовательского интерфейса.
## Version: @project-version@
## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB, pfUI_eqmgr
## X-Website: https://github.com/brues-code/pfUI
# ClassicAPI-less fallback. ClassicAPI redirects this read to pfUI_Turtle.toc
+1 -1
View File
@@ -5,7 +5,7 @@
## Notes-ruRU: Полная замена пользовательского интерфейса.
## Version: @project-version@
## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB, pfUI_eqmgr
## X-Website: https://github.com/brues-code/pfUI
# Selected by ClassicAPI on every non-Turtle client. Turtle clients get
+1 -1
View File
@@ -5,7 +5,7 @@
## Notes-ruRU: Полная замена пользовательского интерфейса.
## Version: @project-version@
## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB, pfUI_eqmgr
## X-Website: https://github.com/brues-code/pfUI
# Selected by ClassicAPI on Turtle WoW, where it wins over pfUI_ClassicAPI.toc.