14 Commits
Author SHA1 Message Date
Brues b47df9272d Bump ClassicAPI minimum version to 1.5.11 2026-07-05 23:51:57 -05:00
Brues c0b717878d Always set OnClick handler for action buttons
Ensure the action button OnClick handler is always assigned. Previously SetScript("OnClick", ButtonClick) only ran when HookScript was missing; now HookScript is still added only if absent, but the OnClick script is set unconditionally so existing frames won't miss the click handler. Change is limited to modules/actionbar.lua.
2026-07-05 23:48:02 -05:00
Brues 31c95606d0 Refactor turtle/Nampower checks and libdebuff cleanup
Replace ad-hoc Turtle/Nampower detection with global TURTLE_WOW_VERSION and EventUtil startup flow. Remove legacy IsTurtleWoW and manual PLAYER_ENTERING_WORLD frame; use EventUtil.ContinueOnPlayerLogin. Clean up libdebuff by removing combo-point capture, GetEnhancedDebuffs API, and noisy startup messages; rely on Nampower/AURA_CAST and database fallback for durations. Fix tooltip compare shift handling (cache shift state and pass through). Update xpbar to use TURTLE_WOW_VERSION. Purpose: simplify startup, avoid duplicated logic, and rely on modern APIs for accurate durations.
2026-07-05 23:47:39 -05:00
Brues 3fe072c594 Route hooksecurefunc callers through pfUI.hooksecurefunc; global belongs to ClassicAPI
pfUI's Lua hooksecurefunc lived in pfUI.env and shadowed ClassicAPI's C
global for all pfUI code. Replace it with a thin pfUI.hooksecurefunc shim
that keeps the missing-target no-op our call sites rely on (ClassicAPI
errors on a nil target) and delegates the actual hook to _G.hooksecurefunc.

Migrated all 70 internal call sites (modules/libs/skins) to
pfUI.hooksecurefunc; bare hooksecurefunc now resolves to ClassicAPI's C
version everywhere. Dropped the unused prepend path and the orphaned
pfUI.hooks table.
2026-07-05 14:58:26 -05:00
Brues 9706a74d16 UNIT_INVENTORY_CHANGED -> PLAYER_EQUIPMENT_CHANGED 2026-07-05 14:32:25 -05:00
Brues f9b0b5983a Don't need to worry about caching player guid anymore 2026-07-04 22:46:55 -05:00
Brues 176e131d6b Update README.md 2026-07-04 20:46:19 -05:00
Brues a17229abb1 GetLootSlotItemLink should be GetLootSlotLink 2026-07-04 13:12:40 -05:00
Brues e0cf01772c Update FUNDING.yml 2026-07-03 23:27:18 -05:00
Brues c2d4106170 Update README.md 2026-07-03 22:59:29 -05:00
Brues dbfd337d42 Bump pfUI min to 1.5.8 2026-07-03 21:45:04 -05:00
Brues d834be9f0b Revert "nameplates: hide castbar on remote interrupt / caster death (#11)"
This reverts commit 703d7770ca.
2026-07-03 21:38:05 -05:00
Brues 82a07e1e35 share: rebuild profile export/import on C_EncodingUtil (CBOR+zlib+base64)
Export now diffs the config against defaults and emits
SerializeCBOR -> CompressString (zlib) -> EncodeBase64 with a "!pf1!"
prefix. Import reverses that into a plain table — no loadstring, so a
pasted profile is data and can't execute code. The Decode/Encode button
converts blob <-> editable JSON (SerializeJSON/DeserializeJSON) for
inspection and hand-edits.

Old-format strings still import: standard base64 via DecodeBase64, the
custom LZW decompressor kept import-only, and the resulting Lua source
runs in an EMPTY setfenv sandbox that can only assign its config table.
Decode on a legacy string yields the JSON view, so Encode re-emits it
as a new-format blob (migration path).

Roughly half the paste size of the old LZW format, C-speed instead of
the old bit-string base64 (which froze the client on large configs),
and the format is fully standard — external tools can decode profiles
with stock base64/zlib/CBOR libraries.

Requires ClassicAPI with the SerializeCBOR buffer-growth fix (payloads
over 256 bytes returned nil before it).
2026-07-03 21:19:07 -05:00
Brues 703d7770ca nameplates: hide castbar on remote interrupt / caster death (#11)
ClassicAPI's remote-cast cache is stamped from SMSG_SPELL_START and only
expires by computed end time — 1.12 keeps no per-unit interrupt record,
so an interrupted cast kept animating on the plate until its would-be
finish (BG flag caps being the loudest repro).

Nampower does surface the missing signal in Lua: SPELL_FAILED_OTHER
(casterGuid, spellId; fired from the SMSG_SPELL_FAILED_OTHER handler)
and UNIT_DIED (guid). Stamp a guid-keyed suppression time on either
event and have GetCastInfo drop any cast that started before the stamp;
a newer cast clears its unit's entry. Both castbar paths (dedicated
target frame + central loop) already funnel through GetCastInfo, so one
check covers them. The handler only stamps when the unit actually has a
tracked cast, and flags the plate via castUpdate for a same-tick hide.
2026-07-03 19:28:34 -05:00
53 changed files with 270 additions and 555 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
github: [shagu] github: [brues]
ko_fi: shagu buy_me_a_coffee: brues
+12 -4
View File
@@ -1,6 +1,6 @@
# pfUI - ClassicAPI Edition # pfUI - ClassicAPI Edition
[![Turtle WoW](https://img.shields.io/badge/Octo%20WoW-1.18.1-brightgreen.svg)](https://octowow.st/) [![Octo WoW](https://img.shields.io/badge/Octo%20WoW-1.18.1-brightgreen.svg)](https://octowow.st/)
[![ClassicAPI](https://img.shields.io/badge/ClassicAPI-Required-purple.svg)](https://github.com/brues-code/ClassicAPI) [![ClassicAPI](https://img.shields.io/badge/ClassicAPI-Required-purple.svg)](https://github.com/brues-code/ClassicAPI)
[![SuperWoW](https://img.shields.io/badge/SuperWoW-Required-purple.svg)](https://github.com/balakethelock/SuperWoW) [![SuperWoW](https://img.shields.io/badge/SuperWoW-Required-purple.svg)](https://github.com/balakethelock/SuperWoW)
[![Nampower](https://img.shields.io/badge/Nampower-Required-purple.svg)](https://github.com/brues-code/nampower) [![Nampower](https://img.shields.io/badge/Nampower-Required-purple.svg)](https://github.com/brues-code/nampower)
@@ -23,11 +23,19 @@ Since pfUI 6.0.0 includes integrations with client-side DLLs for enhanced functi
### [ClassicAPI](https://github.com/brues-code/ClassicAPI) ### [ClassicAPI](https://github.com/brues-code/ClassicAPI)
Provides: Provides:
- C_NamePlate - Event-driven nameplates (no more per-frame WorldFrame scanning) with real per-plate unit tokens and GUIDs
- C_UnitAuras - Replaces over 3k lines of hand-rolled aura tracking - C_UnitAuras - Replaces over 3k lines of hand-rolled aura tracking
- C_Spell - Replaces thousands of hardcoded spell names for each locale and powers castbar - C_Spell - Replaces thousands of hardcoded spell names for each locale and powers castbar
- Instant Bag Sorting - Real cast bars - Actual cast/channel timing, spellID and interrupt state for any unit (C_Spell.UnitCastingInfo)
- C_EquipmentSet - Focus - A genuine `focus` unit plus `/focus` and `/clearfocus` (FocusUnit / ClearFocus)
- Focus - C_EquipmentSet - Full Equipment Manager with GUID-tracked gear sets (tells apart duplicate/enchanted items)
- Instant Bag Sorting - C_Container.MoveItem / SwapItems instead of cursor pickup/drop
- Sell junk in one call - C_MerchantFrame.GetNumJunkItems / SellAllJunkItems
- Real item data - C_Item counts, quality, sell price and item info by ID
- GUID-based targeting - Nameplates, mouseover and focus resolve by GUID, not by name text
- Faster, safer profile sharing - Engine-side serialize/compress/base64 via C_EncodingUtil
- C_Timer - After / NewTicker replacing hand-rolled OnUpdate throttles
- Feign death, shapeshift and quest-item detection via real API calls
- Plenty other functions - Plenty other functions
### [SuperWoW](https://github.com/balakethelock/SuperWoW) ### [SuperWoW](https://github.com/balakethelock/SuperWoW)
-4
View File
@@ -28,10 +28,6 @@ function pfUI.api.HasNampower()
return GetNampowerVersion and true or false return GetNampowerVersion and true or false
end end
function pfUI.api.IsTurtleWoW()
return C_Spell.GetSpellTexture(46050) == "Interface\\Icons\\Trade_Survival"
end
-- [ GetUnitDistance ] -- [ GetUnitDistance ]
-- Returns distance to unit using best available method -- Returns distance to unit using best available method
-- 'unit1' [string] first unit (default: "player") -- 'unit1' [string] first unit (default: "player")
+2 -2
View File
@@ -1014,7 +1014,7 @@ function pfUI.uf.OnEvent()
-- Raid frames: update_full is set by raid.lua GUID tracker -- Raid frames: update_full is set by raid.lua GUID tracker
elseif this.label == "pet" and event == "UNIT_PET" then elseif this.label == "pet" and event == "UNIT_PET" then
this.update_full = true this.update_full = true
elseif this.label == "player" and (event == "PLAYER_AURAS_CHANGED" or event == "UNIT_INVENTORY_CHANGED") then elseif this.label == "player" and (event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_EQUIPMENT_CHANGED") then
this.update_aura = true this.update_aura = true
elseif this.label == "pet" and event == "UNIT_HAPPINESS" then elseif this.label == "pet" and event == "UNIT_HAPPINESS" then
this.update_full = true this.update_full = true
@@ -1552,7 +1552,7 @@ function pfUI.uf:EnableEvents()
f:RegisterEvent("UNIT_FACTION") f:RegisterEvent("UNIT_FACTION")
f:RegisterEvent("UNIT_AURA") -- frame=buff, frame=debuff f:RegisterEvent("UNIT_AURA") -- frame=buff, frame=debuff
f:RegisterEvent("PLAYER_AURAS_CHANGED") -- label=player && frame=buff f:RegisterEvent("PLAYER_AURAS_CHANGED") -- label=player && frame=buff
f:RegisterEvent("UNIT_INVENTORY_CHANGED") -- label=player && frame=buff f:RegisterEvent("PLAYER_EQUIPMENT_CHANGED") -- label=player && frame=buff (ClassicAPI: weapon-enchant buffs)
f:RegisterEvent("PARTY_MEMBERS_CHANGED") -- label=party, frame=leaderIcon f:RegisterEvent("PARTY_MEMBERS_CHANGED") -- label=party, frame=leaderIcon
f:RegisterEvent("PARTY_LEADER_CHANGED") -- frame=leaderIcon f:RegisterEvent("PARTY_LEADER_CHANGED") -- frame=leaderIcon
f:RegisterEvent("RAID_ROSTER_UPDATE") -- label=raidIcon f:RegisterEvent("RAID_ROSTER_UPDATE") -- label=raidIcon
+10 -26
View File
@@ -28,32 +28,16 @@ ACTIONBAR_SECURE_TEMPLATE_BUTTON = nil
UNITFRAME_SECURE_TEMPLATE = nil UNITFRAME_SECURE_TEMPLATE = nil
--[[ Vanilla API Extensions ]]-- --[[ Vanilla API Extensions ]]--
function hooksecurefunc(tbl, name, func, prepend) -- Safe post-hook helper. The global `hooksecurefunc` belongs to ClassicAPI
if type(tbl) == "string" then -- (its C implementation); this wrapper only adds pfUI's missing-target guard:
prepend, func, name, tbl = func, name, tbl, _G -- ClassicAPI errors when target[name] isn't a function, whereas a lot of our
end -- call sites hook optional/late-loaded frames and rely on a silent no-op.
-- Normalizes the string form, skips when the target is absent, then delegates
if not tbl or not tbl[name] then return end -- to the C version (uncapped args, callback-pcall, taint parity).
function pfUI.hooksecurefunc(tbl, name, func)
pfUI.hooks[tostring(func)] = {} if type(tbl) == "string" then tbl, name, func = _G, tbl, name end
pfUI.hooks[tostring(func)]["old"] = tbl[name] if not tbl or type(tbl[name]) ~= "function" then return end
pfUI.hooks[tostring(func)]["new"] = func return _G.hooksecurefunc(tbl, name, func)
if prepend then
pfUI.hooks[tostring(func)]["function"] = function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
pfUI.hooks[tostring(func)]["new"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
return pfUI.hooks[tostring(func)]["old"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
end
else
pfUI.hooks[tostring(func)]["function"] = function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
local ok, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16 = pcall(pfUI.hooks[tostring(func)]["old"], a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
if not ok then return end
pfUI.hooks[tostring(func)]["new"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
return r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16
end
end
tbl[name] = pfUI.hooks[tostring(func)]["function"]
end end
do -- GetItemInfo do -- GetItemInfo
+18 -145
View File
@@ -14,7 +14,7 @@ setfenv(1, pfUI:GetEnvironment())
-- The public per-aura readers (UnitDebuff, UnitOwnDebuff) were retired in favor -- The public per-aura readers (UnitDebuff, UnitOwnDebuff) were retired in favor
-- of ClassicAPI's C_UnitAuras (which now provides sourceUnit/sourceGUID and -- of ClassicAPI's C_UnitAuras (which now provides sourceUnit/sourceGUID and
-- non-player expirationTime). What remains in libdebuff is the cast-event -- non-player expirationTime). What remains in libdebuff is the cast-event
-- bookkeeping consumed by GetBestAuraCast / GetEnhancedDebuffs and the -- bookkeeping consumed by GetBestAuraCast (libpredict HoT tracking) and the
-- libdebuff_*_hooks broadcast surface (subscribers in actionbar / swingtimer -- libdebuff_*_hooks broadcast surface (subscribers in actionbar / swingtimer
-- / libtotem react to SPELL_GO and SPELL_FAILED). -- / libtotem react to SPELL_GO and SPELL_FAILED).
@@ -43,13 +43,7 @@ if GetNampowerVersion then
end end
end end
-- Nampower startup check: show version info and ensure CVars are set. EventUtil.ContinueOnPlayerLogin(function()
-- Runs the frame after PLAYER_ENTERING_WORLD so Nampower has finished initializing.
local nampowerCheckFrame = CreateFrame("Frame")
nampowerCheckFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
nampowerCheckFrame:SetScript("OnEvent", function()
this:UnregisterAllEvents()
this:SetScript("OnEvent", nil)
RunNextFrame(function() RunNextFrame(function()
if GetNampowerVersion then if GetNampowerVersion then
@@ -58,8 +52,6 @@ nampowerCheckFrame:SetScript("OnEvent", function()
local versionString = major .. "." .. minor .. "." .. patch local versionString = major .. "." .. minor .. "." .. patch
if major > 3 or (major == 3 and minor > 0) or (major == 3 and minor == 0 and patch >= 0) then if major > 3 or (major == 3 and minor > 0) or (major == 3 and minor == 0 and patch >= 0) then
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Nampower v" .. versionString .. " detected - GetUnitField mode enabled!")
if SetCVar and GetCVar then if SetCVar and GetCVar then
local cvarsToEnable = { local cvarsToEnable = {
"NP_EnableSpellStartEvents", "NP_EnableSpellStartEvents",
@@ -89,8 +81,6 @@ nampowerCheckFrame:SetScript("OnEvent", function()
if enabledCount > 0 then if enabledCount > 0 then
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Enabled " .. enabledCount .. " Nampower CVars") DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r Enabled " .. enabledCount .. " Nampower CVars")
elseif alreadyEnabledCount == table.getn(cvarsToEnable) then
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r All required Nampower CVars already enabled")
end end
if failedCount > 0 then if failedCount > 0 then
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00[libdebuff]|r Warning: Could not check/set " .. failedCount .. " CVars") DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00[libdebuff]|r Warning: Could not check/set " .. failedCount .. " CVars")
@@ -202,10 +192,6 @@ pfUI.libdebuff_spell_cast_hooks = pfUI.libdebuff_spell_cast_hooks or {}
pfUI.libdebuff_downrank_blocked_hooks = pfUI.libdebuff_downrank_blocked_hooks or {} pfUI.libdebuff_downrank_blocked_hooks = pfUI.libdebuff_downrank_blocked_hooks or {}
local AURA_CAST_DEDUPE_WINDOW = 0.1 -- Ignore duplicates within 100ms local AURA_CAST_DEDUPE_WINDOW = 0.1 -- Ignore duplicates within 100ms
-- Captured combo points from SPELL_CAST_EVENT (before client consumes them)
-- SPELL_CAST_EVENT fires BEFORE UnitAura updates, so GetComboPoints() still works
local capturedCP = nil
-- Pending cast info for libpredict (heal prediction target tracking) -- Pending cast info for libpredict (heal prediction target tracking)
-- SPELL_CAST_EVENT fires with targetGuid BEFORE SPELLCAST_START, -- SPELL_CAST_EVENT fires with targetGuid BEFORE SPELLCAST_START,
-- which allows libpredict to know the correct target for queued casts. -- which allows libpredict to know the correct target for queued casts.
@@ -278,50 +264,10 @@ local debuffOverwritePairs = {
["Demoralizing Roar"] = "Demoralizing Shout", ["Demoralizing Roar"] = "Demoralizing Shout",
} }
-- Combopoint-based abilities: Only show timers for OUR casts
-- Format: [spellName] = { base = N, perCP = N }
-- Duration formula: duration = base + combopoints * perCP
local combopointAbilities = {
-- Druid
["Rip"] = { base = 8, perCP = 2 },
-- Rogue
["Rupture"] = { base = 6, perCP = 2 },
["Kidney Shot"] = { base = 1, perCP = 1 },
["Slice and Dice"] = { base = 9, perCP = 3 },
["Expose Armor"] = { base = 30, perCP = 0 }, -- fixed 30s
}
-- ============================================================================ -- ============================================================================
-- HELPER FUNCTIONS -- HELPER FUNCTIONS
-- ============================================================================ -- ============================================================================
-- Check if spell is a combo-point ability
local function IsComboPointAbility(spellName)
if not spellName then return false end
return combopointAbilities[spellName] ~= nil
end
-- Get combo-point spell data (base duration and per-CP bonus)
local function GetComboPointData(spellName)
if not spellName then return nil, nil end
local cpData = combopointAbilities[spellName]
if cpData then
return cpData.base, cpData.perCP
end
return nil, nil
end
-- Player GUID Cache
local playerGUID = nil
local function GetPlayerGUID()
if not playerGUID and UnitGUID then
local guid = UnitGUID("player")
playerGUID = guid
end
return playerGUID
end
-- Debug Stats -- Debug Stats
pfUI.libdebuff_debugstats = pfUI.libdebuff_debugstats or { pfUI.libdebuff_debugstats = pfUI.libdebuff_debugstats or {
enabled = false, enabled = false,
@@ -461,7 +407,7 @@ local function GetSlotCaster(guid, auraSlot, spellName)
end end
-- Fallback: Check ownDebuffs -- Fallback: Check ownDebuffs
local myGuid = GetPlayerGUID() local myGuid = GetPlayerGuid()
if ownDebuffs[guid] and ownDebuffs[guid][spellName] then if ownDebuffs[guid] and ownDebuffs[guid][spellName] then
return myGuid, true return myGuid, true
end end
@@ -652,16 +598,7 @@ function libdebuff:GetDuration(effect, rank)
local rank = L["debuffs"][effect][rank] and rank or libdebuff:GetMaxRank(effect) local rank = L["debuffs"][effect][rank] and rank or libdebuff:GetMaxRank(effect)
local duration = L["debuffs"][effect][rank] local duration = L["debuffs"][effect][rank]
if effect == L["dyndebuffs"]["Rupture"] then if effect == L["dyndebuffs"]["Demoralizing Shout"] then
local cp = GetComboPoints() or 0
duration = duration + cp*2
elseif effect == L["dyndebuffs"]["Kidney Shot"] then
local cp = GetComboPoints() or 0
duration = duration + cp*1
elseif effect == "Rip" or effect == L["dyndebuffs"]["Rip"] then
local cp = GetComboPoints() or 0
duration = 8 + cp*2
elseif effect == L["dyndebuffs"]["Demoralizing Shout"] then
local _,_,_,_,count = GetTalentInfo(2,1) local _,_,_,_,count = GetTalentInfo(2,1)
if count and count > 0 then duration = duration + ( duration / 100 * (count*10)) end if count and count > 0 then duration = duration + ( duration / 100 * (count*10)) end
elseif effect == L["dyndebuffs"]["Shadow Word: Pain"] then elseif effect == L["dyndebuffs"]["Shadow Word: Pain"] then
@@ -798,7 +735,7 @@ function libdebuff:GetBestAuraCast(guid, spellName)
local data = ownDebuffs[guid][spellName] local data = ownDebuffs[guid][spellName]
local timeleft = (data.startTime + data.duration) - GetTime() local timeleft = (data.startTime + data.duration) - GetTime()
if timeleft > 0 then if timeleft > 0 then
return data.startTime, data.duration, timeleft, data.rank, GetPlayerGUID() return data.startTime, data.duration, timeleft, data.rank, GetPlayerGuid()
end end
end end
@@ -825,33 +762,6 @@ function libdebuff:GetBestAuraCast(guid, spellName)
return nil return nil
end end
-- ============================================================================
-- API: GetEnhancedDebuffs (for external modules)
-- ============================================================================
function libdebuff:GetEnhancedDebuffs(targetGUID)
if not targetGUID then return nil end
local result = {}
if ownDebuffs[targetGUID] then
local myGuid = GetPlayerGUID()
for spellName, data in pairs(ownDebuffs[targetGUID]) do
local timeleft = (data.startTime + data.duration) - GetTime()
if timeleft > 0 then
result[spellName] = result[spellName] or {}
result[spellName][myGuid] = {
startTime = data.startTime,
duration = data.duration,
texture = data.texture,
rank = data.rank
}
end
end
end
return result
end
-- ============================================================================ -- ============================================================================
-- NAMPOWER EVENT HANDLING -- NAMPOWER EVENT HANDLING
-- ============================================================================ -- ============================================================================
@@ -883,7 +793,7 @@ if hasNampower then
-- Carnage triggered! Refresh Rip & Rake -- Carnage triggered! Refresh Rip & Rake
local guid = carnageState.targetGuid local guid = carnageState.targetGuid
local refreshTime = GetTime() local refreshTime = GetTime()
local myGuid = GetPlayerGUID() local myGuid = GetPlayerGuid()
-- Refresh in ownDebuffs - only if timer still active -- Refresh in ownDebuffs - only if timer still active
if ownDebuffs[guid] then if ownDebuffs[guid] then
@@ -976,14 +886,8 @@ if hasNampower then
end end
end end
end end
elseif event == "PLAYER_ENTERING_WORLD" or event == "PLAYER_TALENT_UPDATE" then
elseif event == "PLAYER_ENTERING_WORLD" then
GetPlayerGUID()
UpdateCarnageRank() UpdateCarnageRank()
elseif event == "PLAYER_TALENT_UPDATE" then
UpdateCarnageRank()
elseif event == "UNIT_HEALTH" then elseif event == "UNIT_HEALTH" then
local guid = arg1 local guid = arg1
if guid and UnitIsDead and UnitIsDead(guid) then if guid and UnitIsDead and UnitIsDead(guid) then
@@ -1078,7 +982,7 @@ if hasNampower then
local selfdebuffMode = pfUI_config and pfUI_config.buffbar and local selfdebuffMode = pfUI_config and pfUI_config.buffbar and
pfUI_config.buffbar.tdebuff and pfUI_config.buffbar.tdebuff.selfdebuff == "1" pfUI_config.buffbar.tdebuff and pfUI_config.buffbar.tdebuff.selfdebuff == "1"
if selfdebuffMode then if selfdebuffMode then
local myGuid2 = GetPlayerGUID() local myGuid2 = GetPlayerGuid()
if casterGuid == myGuid2 then if casterGuid == myGuid2 then
local duration = libdebuff:GetDuration(spellName, castRank) or 0 local duration = libdebuff:GetDuration(spellName, castRank) or 0
if duration > 0 then if duration > 0 then
@@ -1108,7 +1012,7 @@ if hasNampower then
end end
-- Store rank for our casts -- Store rank for our casts
local myGuid = GetPlayerGUID() local myGuid = GetPlayerGuid()
if casterGuid == myGuid then if casterGuid == myGuid then
lastCastRanks[spellName] = { lastCastRanks[spellName] = {
rank = castRank, rank = castRank,
@@ -1181,11 +1085,6 @@ if hasNampower then
pfUI.libpredict_pending_cast.time = nil pfUI.libpredict_pending_cast.time = nil
end end
-- Only capture CPs for combo-point abilities
if spellName and IsComboPointAbility(spellName) then
capturedCP = GetComboPoints() or 0
end
-- Fire registered SPELL_CAST_EVENT hooks -- Fire registered SPELL_CAST_EVENT hooks
if pfUI.libdebuff_spell_cast_hooks then if pfUI.libdebuff_spell_cast_hooks then
for _, fn in pairs(pfUI.libdebuff_spell_cast_hooks) do for _, fn in pairs(pfUI.libdebuff_spell_cast_hooks) do
@@ -1233,37 +1132,17 @@ if hasNampower then
local duration = durationMs and (durationMs / 1000) or 0 local duration = durationMs and (durationMs / 1000) or 0
local startTime = GetTime() local startTime = GetTime()
local myGuid = GetPlayerGUID() local myGuid = GetPlayerGuid()
local isOurs = (myGuid and casterGuid == myGuid) local isOurs = (myGuid and casterGuid == myGuid)
if debugStats.enabled and isOurs then if debugStats.enabled and isOurs then
debugStats.aura_cast = debugStats.aura_cast + 1 debugStats.aura_cast = debugStats.aura_cast + 1
end end
-- Combo-point abilities: Calculate duration based on CPs used -- Duration comes from nampower's AURA_CAST event. ClassicAPI's
if IsComboPointAbility(spellName) then -- C_UnitAuras now resolves combo-scaled durations server-side, so
if isOurs then -- libdebuff only needs the database fallback when AURA_CAST reports 0.
-- OWN casts: use captured CPs from SPELL_CAST_EVENT (if available) if duration == 0 then
local cp = capturedCP or 0
local base, perCP = GetComboPointData(spellName)
if base and perCP then
duration = base + cp * perCP
else
-- Fallback to legacy database
duration = libdebuff:GetDuration(spellName, rankNum)
end
capturedCP = nil -- consumed
else
-- OTHER players: CP unknown, no timer (except Expose Armor = fixed 30s)
local base, perCP = GetComboPointData(spellName)
if perCP and perCP == 0 and base then
duration = base -- fixed duration (Expose Armor)
else
duration = 0 -- CP unknown for other players
end
end
elseif duration == 0 then
-- Non-CP managed spells: use database if AURA_CAST returned 0
duration = libdebuff:GetDuration(spellName, rankNum) or 0 duration = libdebuff:GetDuration(spellName, rankNum) or 0
end end
@@ -1365,15 +1244,12 @@ if hasNampower then
-- Notify unitframes of debuff updates (UNIT_AURA doesn't fire on refreshes!) -- Notify unitframes of debuff updates (UNIT_AURA doesn't fire on refreshes!)
-- Check player -- Check player
if UnitGUID("player") then if IsPlayerGuid(targetGuid) and pfPlayer then
local playerGuid = UnitGUID("player") pfPlayer.update_aura = true
if playerGuid == targetGuid and pfPlayer then
pfPlayer.update_aura = true
end
end end
-- Check target -- Check target
if UnitGUID("target") then if UnitExists("target") then
local tarUnitGUID = UnitGUID("target") local tarUnitGUID = UnitGUID("target")
if tarUnitGUID == targetGuid and pfTarget then if tarUnitGUID == targetGuid and pfTarget then
pfTarget.update_aura = true pfTarget.update_aura = true
@@ -1520,7 +1396,7 @@ if hasNampower then
end end
end end
local myGuid = GetPlayerGUID() local myGuid = GetPlayerGuid()
local isOurs = (myGuid and casterGuid == myGuid) local isOurs = (myGuid and casterGuid == myGuid)
-- Fallback: Check ownDebuffs timing -- Fallback: Check ownDebuffs timing
@@ -1555,7 +1431,6 @@ if hasNampower then
-- CRITICAL FIX: Update ownDebuffs here too for refresh timing! -- CRITICAL FIX: Update ownDebuffs here too for refresh timing!
-- This prevents the gap between DEBUFF_REMOVED and AURA_CAST where buffwatch shows nothing -- This prevents the gap between DEBUFF_REMOVED and AURA_CAST where buffwatch shows nothing
if isOurs and casterGuid then if isOurs and casterGuid then
local myGuid = GetPlayerGUID()
if myGuid and casterGuid == myGuid then if myGuid and casterGuid == myGuid then
-- Check if we have timer data from allAuraCasts -- Check if we have timer data from allAuraCasts
if allAuraCasts[guid] and allAuraCasts[guid][spellName] and allAuraCasts[guid][spellName][casterGuid] then if allAuraCasts[guid] and allAuraCasts[guid][spellName] and allAuraCasts[guid][spellName][casterGuid] then
@@ -1809,5 +1684,3 @@ _G.SlashCmdList["MEMCHECK"] = function()
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00No ownSlots/allSlots (eliminated by GetUnitField approach!)|r") DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00No ownSlots/allSlots (eliminated by GetUnitField approach!)|r")
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff============================================================|r") DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff============================================================|r")
end end
DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99[libdebuff]|r GetUnitField Edition loaded!")
+5 -8
View File
@@ -818,7 +818,7 @@ local hotsetbonus = libtipscan:GetScanner("hotsetbonus")
resetcache:RegisterEvent("PLAYER_ENTERING_WORLD") resetcache:RegisterEvent("PLAYER_ENTERING_WORLD")
resetcache:RegisterEvent("LEARNED_SPELL_IN_TAB") resetcache:RegisterEvent("LEARNED_SPELL_IN_TAB")
resetcache:RegisterEvent("CHARACTER_POINTS_CHANGED") resetcache:RegisterEvent("CHARACTER_POINTS_CHANGED")
resetcache:RegisterEvent("UNIT_INVENTORY_CHANGED") resetcache:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
resetcache:SetScript("OnEvent", function() resetcache:SetScript("OnEvent", function()
if event == "PLAYER_ENTERING_WORLD" then if event == "PLAYER_ENTERING_WORLD" then
-- load and initialize previous caches of spell amounts -- load and initialize previous caches of spell amounts
@@ -829,10 +829,7 @@ resetcache:SetScript("OnEvent", function()
cache = pfUI_cache["prediction"][realm][player]["heals"] cache = pfUI_cache["prediction"][realm][player]["heals"]
end end
if event == "UNIT_INVENTORY_CHANGED" or "PLAYER_ENTERING_WORLD" then if event == "PLAYER_EQUIPMENT_CHANGED" or event == "PLAYER_ENTERING_WORLD" then
-- skip non-player events
if arg1 and arg1 ~= "player" then return end
local gear = "" local gear = ""
for id = 1, 18 do for id = 1, 18 do
gear = gear .. (GetInventoryItemLink("player",id) or "") gear = gear .. (GetInventoryItemLink("player",id) or "")
@@ -902,7 +899,7 @@ local INSTANT_HOT_COOLDOWN = 1.0 -- 1 Sekunde Cooldown (GCD ist 1.5s)
local pendingHots = {} local pendingHots = {}
-- Gather Data by User Actions -- Gather Data by User Actions
hooksecurefunc("CastSpell", function(id, bookType) pfUI.hooksecurefunc("CastSpell", function(id, bookType)
if not libpredict.sender.enabled then return end if not libpredict.sender.enabled then return end
local effect, rank = libspell.GetSpellInfo(id, bookType) local effect, rank = libspell.GetSpellInfo(id, bookType)
if not effect then return end if not effect then return end
@@ -955,7 +952,7 @@ hooksecurefunc("CastSpell", function(id, bookType)
end end
end) end)
hooksecurefunc("CastSpellByName", function(effect, target) pfUI.hooksecurefunc("CastSpellByName", function(effect, target)
if not libpredict.sender.enabled then return end if not libpredict.sender.enabled then return end
local effect, rank = libspell.GetSpellInfo(effect) local effect, rank = libspell.GetSpellInfo(effect)
if not effect then return end if not effect then return end
@@ -1019,7 +1016,7 @@ hooksecurefunc("CastSpellByName", function(effect, target)
end end
end) end)
hooksecurefunc("UseAction", function(slot, target, selfcast) pfUI.hooksecurefunc("UseAction", function(slot, target, selfcast)
if not libpredict.sender.enabled then return end if not libpredict.sender.enabled then return end
if not IsCurrentAction(slot) then return end if not IsCurrentAction(slot) then return end
local kind, id = GetActionInfo(slot) local kind, id = GetActionInfo(slot)
+1 -1
View File
@@ -54,6 +54,6 @@ end
pfUI.api.libtooltip = libtooltip pfUI.api.libtooltip = libtooltip
hooksecurefunc(GameTooltip, "SetBagItem", function(self, container, slot) pfUI.hooksecurefunc(GameTooltip, "SetBagItem", function(self, container, slot)
_, libtooltip.itemCount = GetContainerItemInfo(container, slot) _, libtooltip.itemCount = GetContainerItemInfo(container, slot)
end) end)
+3 -3
View File
@@ -241,14 +241,14 @@ pfUI.libdebuff_spell_go_hooks["libtotem"] = function(spellId)
end end
-- Hook CastSpellByName to store pending name/icon per slot -- Hook CastSpellByName to store pending name/icon per slot
hooksecurefunc("CastSpellByName", function(effect, target) pfUI.hooksecurefunc("CastSpellByName", function(effect, target)
local name, rank, icon, _, _, _, spellId = libspell.GetSpellInfo(effect) local name, rank, icon, _, _, _, spellId = libspell.GetSpellInfo(effect)
if not name then return end if not name then return end
libtotem:CheckAddQueue(name, rank, icon, spellId) libtotem:CheckAddQueue(name, rank, icon, spellId)
end) end)
-- Hook CastSpell to store pending name/icon per slot -- Hook CastSpell to store pending name/icon per slot
hooksecurefunc("CastSpell", function(id, bookType) pfUI.hooksecurefunc("CastSpell", function(id, bookType)
if not id or not bookType then return end if not id or not bookType then return end
if bookType ~= BOOKTYPE_SPELL and bookType ~= BOOKTYPE_PET then return end if bookType ~= BOOKTYPE_SPELL and bookType ~= BOOKTYPE_PET then return end
local name, rank, icon, _, _, _, spellId = libspell.GetSpellInfo(id, bookType) local name, rank, icon, _, _, _, spellId = libspell.GetSpellInfo(id, bookType)
@@ -259,7 +259,7 @@ end)
-- Hook UseAction. GetActionInfo + GetMacroSpell give us the spellID -- Hook UseAction. GetActionInfo + GetMacroSpell give us the spellID
-- directly for both spell-action and macro-action slots, so the -- directly for both spell-action and macro-action slots, so the
-- tooltip-scan fallback (and the "no spellId available" caveat) goes away. -- tooltip-scan fallback (and the "no spellId available" caveat) goes away.
hooksecurefunc("UseAction", function(slot, target, selfcast) pfUI.hooksecurefunc("UseAction", function(slot, target, selfcast)
if not IsCurrentAction(slot) then return end if not IsCurrentAction(slot) then return end
local kind, id = GetActionInfo(slot) local kind, id = GetActionInfo(slot)
local name, rank, spellID local name, rank, spellID
+2 -4
View File
@@ -1013,10 +1013,8 @@ pfUI:RegisterModule("actionbar", function ()
-- no button available, create a new one -- no button available, create a new one
if not exists then if not exists then
-- prepare the button for vanilla -- prepare the button for vanilla
if not f.HookScript then if not f.HookScript then f.HookScript = HookScript end
f.HookScript = HookScript f:SetScript("OnClick", ButtonClick)
f:SetScript("OnClick", ButtonClick)
end
if bar ~= 11 then if bar ~= 11 then
f:RegisterForDrag("LeftButton", "RightButton") f:RegisterForDrag("LeftButton", "RightButton")
+1 -1
View File
@@ -159,7 +159,7 @@ pfUI:RegisterModule("buff", function ()
pfUI.buff = CreateFrame("Frame", "pfGlobalBuffFrame", UIParent) pfUI.buff = CreateFrame("Frame", "pfGlobalBuffFrame", UIParent)
pfUI.buff:RegisterEvent("PLAYER_AURAS_CHANGED") pfUI.buff:RegisterEvent("PLAYER_AURAS_CHANGED")
pfUI.buff:RegisterEvent("UNIT_INVENTORY_CHANGED") pfUI.buff:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
pfUI.buff:RegisterEvent("UNIT_MODEL_CHANGED") pfUI.buff:RegisterEvent("UNIT_MODEL_CHANGED")
pfUI.buff:RegisterEvent("BUFF_UPDATE_DURATION_SELF") pfUI.buff:RegisterEvent("BUFF_UPDATE_DURATION_SELF")
pfUI.buff:RegisterEvent("DEBUFF_UPDATE_DURATION_SELF") pfUI.buff:RegisterEvent("DEBUFF_UPDATE_DURATION_SELF")
+1 -1
View File
@@ -487,7 +487,7 @@ pfUI:RegisterModule("castbar", function ()
-- (the config knob is read at event time so toggling takes effect on the -- (the config knob is read at event time so toggling takes effect on the
-- next craft without a /reload). DoTradeSkill is synchronous; the server -- next craft without a /reload). DoTradeSkill is synchronous; the server
-- roundtrip to SPELLCAST_START gives us plenty of time after this hook. -- roundtrip to SPELLCAST_START gives us plenty of time after this hook.
hooksecurefunc("DoTradeSkill", function(index, num) pfUI.hooksecurefunc("DoTradeSkill", function(index, num)
if pfUI.castbar.player then if pfUI.castbar.player then
pfUI.castbar.player.pendingTradeskillCount = tonumber(num) or 1 pfUI.castbar.player.pendingTradeskillCount = tonumber(num) or 1
end end
+2 -2
View File
@@ -24,7 +24,7 @@ pfUI:RegisterModule("chat", function ()
end end
end end
hooksecurefunc("UnitPopup_OnClick", function(self) pfUI.hooksecurefunc("UnitPopup_OnClick", function(self)
if this.value == "IGNORE_PLAYER" then if this.value == "IGNORE_PLAYER" then
AddIgnore(_G[UIDROPDOWNMENU_INIT_MENU].name) AddIgnore(_G[UIDROPDOWNMENU_INIT_MENU].name)
end end
@@ -449,7 +449,7 @@ pfUI:RegisterModule("chat", function ()
end end
end end
hooksecurefunc("FCF_SaveDock", pfUI.chat.RefreshChat) pfUI.hooksecurefunc("FCF_SaveDock", pfUI.chat.RefreshChat)
if C.chat.global.tabmouse == "1" then if C.chat.global.tabmouse == "1" then
pfUI.chat.mouseovertab = CreateFrame("Frame") pfUI.chat.mouseovertab = CreateFrame("Frame")
+1 -1
View File
@@ -136,5 +136,5 @@ pfUI:RegisterModule("cooldown", function ()
-- vanilla does not have a cooldown frame type, so we hook the -- vanilla does not have a cooldown frame type, so we hook the
-- regular SetTimer function that each one is calling. -- regular SetTimer function that each one is calling.
hooksecurefunc("CooldownFrame_SetTimer", SetCooldown) pfUI.hooksecurefunc("CooldownFrame_SetTimer", SetCooldown)
end) end)
+6 -5
View File
@@ -3,8 +3,9 @@ pfUI:RegisterModule("eqcompare", function ()
local function ShowCompareItem(self, link, shift) local function ShowCompareItem(self, link, shift)
self = self or GameTooltip self = self or GameTooltip
shift = shift or IsShiftKeyDown()
if not link or (not IsShiftKeyDown() and (C.tooltip.compare.showalways ~= "1" or C_Item.IsEquippedItem(link))) then if not link or (not shift and (C.tooltip.compare.showalways ~= "1" or C_Item.IsEquippedItem(link))) then
return return
end end
@@ -88,7 +89,7 @@ pfUI:RegisterModule("eqcompare", function ()
local prevMerchant = ShoppingTooltip1.SetMerchantCompareItem local prevMerchant = ShoppingTooltip1.SetMerchantCompareItem
local function SetMerchantCompareItem(self, index, compareItem) local function SetMerchantCompareItem(self, index, compareItem)
if C.tooltip.compare.basestats == "1" and compareItem == 1 then if C.tooltip.compare.basestats == "1" and compareItem == 1 then
ShowCompareItem(nil, GetMerchantItemLink(index)) ShowCompareItem(nil, GetMerchantItemLink(index), 1)
return false return false
end end
return prevMerchant and prevMerchant(self, index, compareItem) return prevMerchant and prevMerchant(self, index, compareItem)
@@ -97,7 +98,7 @@ pfUI:RegisterModule("eqcompare", function ()
local prevAuction = ShoppingTooltip1.SetAuctionCompareItem local prevAuction = ShoppingTooltip1.SetAuctionCompareItem
local function SetAuctionCompareItem(self, type, index, compareItem) local function SetAuctionCompareItem(self, type, index, compareItem)
if C.tooltip.compare.basestats == "1" and compareItem == 1 then if C.tooltip.compare.basestats == "1" and compareItem == 1 then
ShowCompareItem(nil, GetAuctionItemLink(type, index)) ShowCompareItem(nil, GetAuctionItemLink(type, index), 1)
return false return false
end end
return prevAuction and prevAuction(self, type, index, compareItem) return prevAuction and prevAuction(self, type, index, compareItem)
@@ -110,7 +111,7 @@ pfUI:RegisterModule("eqcompare", function ()
local TooltipHooks = { local TooltipHooks = {
SetLootRollItem = GetLootRollItemLink, SetLootRollItem = GetLootRollItemLink,
SetLootItem = GetLootSlotItemLink, SetLootItem = GetLootSlotLink,
SetQuestLogItem = GetQuestLogItemLink, SetQuestLogItem = GetQuestLogItemLink,
SetQuestItem = GetQuestItemLink, SetQuestItem = GetQuestItemLink,
SetHyperlink = function(link) return link end, SetHyperlink = function(link) return link end,
@@ -139,7 +140,7 @@ pfUI:RegisterModule("eqcompare", function ()
local function HookTooltip(tooltip) local function HookTooltip(tooltip)
for setter, getter in pairs(TooltipHooks) do for setter, getter in pairs(TooltipHooks) do
_G['hooksecurefunc'](tooltip, setter, makeHook(getter)) pfUI.hooksecurefunc(tooltip, setter, makeHook(getter))
end end
end end
+2 -3
View File
@@ -1048,11 +1048,10 @@ pfUI:RegisterModule("equipmentmanager", function()
events:RegisterEvent("EQUIPMENT_SETS_CHANGED") events:RegisterEvent("EQUIPMENT_SETS_CHANGED")
events:RegisterEvent("EQUIPMENT_SWAP_FINISHED") events:RegisterEvent("EQUIPMENT_SWAP_FINISHED")
events:RegisterEvent("EQUIPMENT_SWAP_PENDING") events:RegisterEvent("EQUIPMENT_SWAP_PENDING")
events:RegisterEvent("BAG_UPDATE_DELAYED") -- ClassicAPI debounced; ~4x fewer refreshes than BAG_UPDATE events:RegisterEvent("BAG_UPDATE_DELAYED")
events:RegisterEvent("UNIT_INVENTORY_CHANGED") events:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
events:SetScript("OnEvent", function() events:SetScript("OnEvent", function()
if not frame:IsShown() then return end if not frame:IsShown() then return end
if event == "UNIT_INVENTORY_CHANGED" and arg1 ~= "player" then return end
pfUI.equipmentmanager.Refresh() pfUI.equipmentmanager.Refresh()
end) end)
+2 -2
View File
@@ -150,7 +150,7 @@ pfUI:RegisterSkin("Friends", function ()
end end
-- set positions -- set positions
hooksecurefunc("WhoList_Update", function() pfUI.hooksecurefunc("WhoList_Update", function()
for i = 1, WHOS_TO_DISPLAY do for i = 1, WHOS_TO_DISPLAY do
local level = _G["WhoFrameButton"..i.."Level"] local level = _G["WhoFrameButton"..i.."Level"]
level:ClearAllPoints() level:ClearAllPoints()
@@ -231,7 +231,7 @@ pfUI:RegisterSkin("Friends", function ()
end end
-- set positions -- set positions
hooksecurefunc("GuildStatus_Update", function() pfUI.hooksecurefunc("GuildStatus_Update", function()
for i = 1, GUILDMEMBERS_TO_DISPLAY do for i = 1, GUILDMEMBERS_TO_DISPLAY do
local level = _G["GuildFrameButton"..i.."Level"] local level = _G["GuildFrameButton"..i.."Level"]
level:ClearAllPoints() level:ClearAllPoints()
+1 -1
View File
@@ -86,7 +86,7 @@ pfUI:RegisterModule("gm", function ()
-- pet dropdown -- pet dropdown
-- table.insert(UnitPopupMenus["PET"], "GM_HEADER") -- table.insert(UnitPopupMenus["PET"], "GM_HEADER")
hooksecurefunc("UnitPopup_OnClick", function() pfUI.hooksecurefunc("UnitPopup_OnClick", function()
local dropdownFrame = _G[UIDROPDOWNMENU_INIT_MENU] local dropdownFrame = _G[UIDROPDOWNMENU_INIT_MENU]
local button = this.value local button = this.value
local unit = dropdownFrame.unit local unit = dropdownFrame.unit
+1 -10
View File
@@ -13,15 +13,6 @@ pfUI:RegisterModule("innervatecall", function ()
local INNERVATE_SPELLID = 29166 local INNERVATE_SPELLID = 29166
-- Cache player GUID
local playerGuid = nil
local function GetPlayerGuid()
if not playerGuid and UnitGUID then
playerGuid = UnitGUID("player")
end
return playerGuid
end
-- GUID → name resolution for the target. UnitTokenFromGUID walks the -- GUID → name resolution for the target. UnitTokenFromGUID walks the
-- engine's known unit tokens (player, party, raid, target, ...) and -- engine's known unit tokens (player, party, raid, target, ...) and
-- returns the first one currently bound to the GUID, so we don't have -- returns the first one currently bound to the GUID, so we don't have
@@ -75,7 +66,7 @@ pfUI:RegisterModule("innervatecall", function ()
if spellId ~= INNERVATE_SPELLID then return end if spellId ~= INNERVATE_SPELLID then return end
-- Only announce our own casts -- Only announce our own casts
if casterGuid ~= GetPlayerGuid() then return end if not IsPlayerGuid(casterGuid) then return end
-- Resolve target name from GUID -- Resolve target name from GUID
local targetName = ResolveTargetName(targetGuid) or "Unknown" local targetName = ResolveTargetName(targetGuid) or "Unknown"
+1 -1
View File
@@ -41,7 +41,7 @@ pfUI:RegisterModule("itemcount", function ()
end end
end) end)
hooksecurefunc("SetItemRef", function() pfUI.hooksecurefunc("SetItemRef", function()
if ItemRefTooltip:HasItem() then if ItemRefTooltip:HasItem() then
local _, _, id = ItemRefTooltip:GetItem() local _, _, id = ItemRefTooltip:GetItem()
if id then AddCounts(ItemRefTooltip, id) end if id then AddCounts(ItemRefTooltip, id) end
+2 -2
View File
@@ -392,7 +392,7 @@ pfUI:RegisterModule("loot", function ()
end end
pfUI.loot:RemoveMasterlootMenus() -- remove then add to ensure no duplicate menus pfUI.loot:RemoveMasterlootMenus() -- remove then add to ensure no duplicate menus
pfUI.loot:AddMasterLootMenus() pfUI.loot:AddMasterLootMenus()
hooksecurefunc("UnitPopup_OnClick",function() pfUI.hooksecurefunc("UnitPopup_OnClick",function()
local dropdownFrame = _G[UIDROPDOWNMENU_INIT_MENU] local dropdownFrame = _G[UIDROPDOWNMENU_INIT_MENU]
if not dropdownFrame then return end if not dropdownFrame then return end
local button = this.value local button = this.value
@@ -405,7 +405,7 @@ pfUI:RegisterModule("loot", function ()
end end
end end
end) end)
hooksecurefunc("UnitPopup_HideButtons",function() pfUI.hooksecurefunc("UnitPopup_HideButtons",function()
local dropdownFrame = _G[UIDROPDOWNMENU_INIT_MENU] local dropdownFrame = _G[UIDROPDOWNMENU_INIT_MENU]
local unit = dropdownFrame.unit local unit = dropdownFrame.unit
local name = dropdownFrame.name local name = dropdownFrame.name
+4 -4
View File
@@ -125,13 +125,13 @@ pfUI:RegisterModule("mapcolors", function ()
-- WorldMap -- WorldMap
Initialize('WorldMap') Initialize('WorldMap')
hooksecurefunc('WorldMapButton_OnUpdate', function() pfUI.hooksecurefunc('WorldMapButton_OnUpdate', function()
if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end
UpdateUnitFrames('WorldMap') UpdateUnitFrames('WorldMap')
end) end)
if C.appearance.worldmap.colornames == "1" then if C.appearance.worldmap.colornames == "1" then
hooksecurefunc('WorldMapUnit_OnEnter', function() pfUI.hooksecurefunc('WorldMapUnit_OnEnter', function()
if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end
UpdateUnitColors('WorldMap', WorldMapTooltip) UpdateUnitColors('WorldMap', WorldMapTooltip)
end) end)
@@ -141,13 +141,13 @@ pfUI:RegisterModule("mapcolors", function ()
HookAddonOrVariable("Blizzard_BattlefieldMinimap", function() HookAddonOrVariable("Blizzard_BattlefieldMinimap", function()
Initialize('BattlefieldMinimap') Initialize('BattlefieldMinimap')
hooksecurefunc('BattlefieldMinimap_OnUpdate', function() pfUI.hooksecurefunc('BattlefieldMinimap_OnUpdate', function()
if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end
UpdateUnitFrames('BattlefieldMinimap') UpdateUnitFrames('BattlefieldMinimap')
end) end)
if C.appearance.worldmap.colornames == "1" then if C.appearance.worldmap.colornames == "1" then
hooksecurefunc('BattlefieldMinimapUnit_OnEnter', function() pfUI.hooksecurefunc('BattlefieldMinimapUnit_OnEnter', function()
if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end if ( this.tick or .5) > GetTime() then return else this.tick = GetTime() + .5 end
UpdateUnitColors('BattlefieldMinimap', GameTooltip) UpdateUnitColors('BattlefieldMinimap', GameTooltip)
end) end)
+1 -1
View File
@@ -58,7 +58,7 @@ pfUI:RegisterModule("minimap", function ()
pfUI.minimap:UpdateConfig() pfUI.minimap:UpdateConfig()
hooksecurefunc("ToggleMinimap", function() pfUI.hooksecurefunc("ToggleMinimap", function()
if pfUI.farmmap and pfUI.farmmap:IsShown() then if pfUI.farmmap and pfUI.farmmap:IsShown() then
Minimap:Hide() Minimap:Hide()
return return
-7
View File
@@ -100,12 +100,6 @@ pfUI:RegisterModule("nameplates", function ()
-- PERF: visiblePlateCount maintained event-driven (NAME_PLATE_UNIT_ADDED/_REMOVED) -- PERF: visiblePlateCount maintained event-driven (NAME_PLATE_UNIT_ADDED/_REMOVED)
local visiblePlateCount = 0 local visiblePlateCount = 0
-- wipe polyfill
local wipe = wipe or function(t) for k in pairs(t) do t[k] = nil end end
-- Player GUID for filtering
local PlayerGUID = UnitGUID("player")
-- ============================================================================ -- ============================================================================
-- OPTIMIZATION: Config caching -- OPTIMIZATION: Config caching
-- ============================================================================ -- ============================================================================
@@ -492,7 +486,6 @@ end
elseif event == "PLAYER_ENTERING_WORLD" or event == "ZONE_CHANGED_NEW_AREA" then elseif event == "PLAYER_ENTERING_WORLD" or event == "ZONE_CHANGED_NEW_AREA" then
if event == "PLAYER_ENTERING_WORLD" then if event == "PLAYER_ENTERING_WORLD" then
_, PlayerGUID = UnitExists("player")
CacheConfig() CacheConfig()
this:SetGameVariables() this:SetGameVariables()
RebuildRaidGuidCache() RebuildRaidGuidCache()
+2 -3
View File
@@ -424,7 +424,8 @@ pfUI:RegisterModule("panel", function()
widget:RegisterEvent("PLAYER_REGEN_ENABLED") widget:RegisterEvent("PLAYER_REGEN_ENABLED")
widget:RegisterEvent("PLAYER_DEAD") widget:RegisterEvent("PLAYER_DEAD")
widget:RegisterEvent("PLAYER_UNGHOST") widget:RegisterEvent("PLAYER_UNGHOST")
widget:RegisterEvent("UNIT_INVENTORY_CHANGED") 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.Click = function() ToggleCharacter("PaperDollFrame") end
widget.Tooltip = function() widget.Tooltip = function()
@@ -456,8 +457,6 @@ pfUI:RegisterModule("panel", function()
end end
end end
widget:SetScript("OnEvent", function() widget:SetScript("OnEvent", function()
if event == "UNIT_INVENTORY_CHANGED" and arg1 ~= "player" then return end
local totalCurr, totalMax = 0, 0 local totalCurr, totalMax = 0, 0
for id = INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED do for id = INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED do
local cur, max = GetInventoryItemDurability(id) local cur, max = GetInventoryItemDurability(id)
+1 -1
View File
@@ -141,7 +141,7 @@ pfUI:RegisterModule("player", function ()
end end
end end
hooksecurefunc("UnitPopup_OnClick", function() pfUI.hooksecurefunc("UnitPopup_OnClick", function()
local button = this.value local button = this.value
if button == "RESET_INSTANCES_FIX" then if button == "RESET_INSTANCES_FIX" then
StaticPopup_Show("CONFIRM_RESET_INSTANCES") StaticPopup_Show("CONFIRM_RESET_INSTANCES")
+1 -1
View File
@@ -95,7 +95,7 @@ pfUI:RegisterModule("questitem", function ()
-- itemref tooltip (chat link clicks): hooksecurefunc runs after SetItemRef -- itemref tooltip (chat link clicks): hooksecurefunc runs after SetItemRef
-- populates ItemRefTooltip, so we just read the item back out of the tooltip -- populates ItemRefTooltip, so we just read the item back out of the tooltip
-- instead of re-parsing the "item:NNN" out of the link string. -- instead of re-parsing the "item:NNN" out of the link string.
hooksecurefunc("SetItemRef", function() pfUI.hooksecurefunc("SetItemRef", function()
if IsModifierKeyDown() then return end if IsModifierKeyDown() then return end
if ItemRefTooltip:HasItem() then if ItemRefTooltip:HasItem() then
local _, _, id = ItemRefTooltip:GetItem() local _, _, id = ItemRefTooltip:GetItem()
+1 -1
View File
@@ -164,7 +164,7 @@ pfUI:RegisterModule("raid", function ()
end end
end end
hooksecurefunc("UnitPopup_OnClick", function() pfUI.hooksecurefunc("UnitPopup_OnClick", function()
local dropdownFrame = UIDROPDOWNMENU_INIT_MENU and _G[UIDROPDOWNMENU_INIT_MENU] local dropdownFrame = UIDROPDOWNMENU_INIT_MENU and _G[UIDROPDOWNMENU_INIT_MENU]
if not dropdownFrame then return end if not dropdownFrame then return end
local button = this.value local button = this.value
+1 -1
View File
@@ -40,7 +40,7 @@ pfUI:RegisterModule("sellvalue", function ()
end end
end) end)
hooksecurefunc("SetItemRef", function() pfUI.hooksecurefunc("SetItemRef", function()
if IsModifierKeyDown() then return end if IsModifierKeyDown() then return end
if ItemRefTooltip:HasItem() then if ItemRefTooltip:HasItem() then
local _, _, id = ItemRefTooltip:GetItem() local _, _, id = ItemRefTooltip:GetItem()
+131 -194
View File
@@ -1,93 +1,78 @@
pfUI:RegisterModule("share", function () pfUI:RegisterModule("share", function ()
local function serialize(tbl, comp, name, ignored, spacing) -- Profile sharing rides ClassicAPI's C_EncodingUtil:
local spacing = spacing or "" -- export: diff vs defaults -> SerializeCBOR -> CompressString (zlib)
local match = nil -- -> EncodeBase64, prefixed with the format magic
local tname = ( spacing == "" and "" or "[\"" ) .. name .. ( spacing == "" and "" or "\"]" ) -- import: the reverse, into a plain table — no loadstring, so a
local str = spacing .. tname .. " = {\n" -- pasted profile can't execute code
-- The Decode/Encode button converts between the transport blob and an
-- editable JSON view of the same table.
local MAGIC = "!pf1!"
-- Deep-diff `tbl` against `default`, keeping only changed or added
-- values. `ignored` keys are skipped at the top level only (matches the
-- old serializer: "position"/"disabled" when Ignore Layout is checked).
-- Returns nil when nothing differs.
local function DiffConfig(tbl, default, ignored)
local diff = nil
for k, v in pairs(tbl) do for k, v in pairs(tbl) do
if not ( ignored[k] and spacing == "" ) and ( not comp or not comp[k] or comp[k] ~= tbl[k] ) then if not ( ignored and ignored[k] ) then
local dv = default and default[k]
if type(v) == "table" then if type(v) == "table" then
local result = serialize(tbl[k], comp and comp[k], k, ignored, spacing .. " ") local sub = DiffConfig(v, type(dv) == "table" and dv or nil)
if result then if sub then
match = true diff = diff or {}
str = str .. result diff[k] = sub
end end
elseif type(v) == "string" then elseif v ~= dv and ( type(v) == "string" or type(v) == "number" or type(v) == "boolean" ) then
match = true diff = diff or {}
local escaped = string.gsub(v, "\\", "\\\\") diff[k] = v
escaped = string.gsub(escaped, "\"", "\\\"")
str = str .. spacing .. " [\""..k.."\"] = \"".. escaped .."\",\n"
elseif type(v) == "number" then
match = true
str = str .. spacing .. " [\""..k.."\"] = ".. string.gsub(v, "\\", "\\\\") ..",\n"
end end
end end
end end
return diff
str = str .. spacing .. "}" .. ( spacing == "" and "" or "," ) .. "\n"
return match and str or nil
end end
local function compress(input) -- EditBoxes don't soft-wrap one giant unbroken line; chunk the blob.
-- based on Rochet2's lzw compression local function wrap(str, width)
if type(input) ~= "string" then local out = {}
return nil for i = 1, strlen(str), width do
table.insert(out, strsub(str, i, i + width - 1))
end end
local len = strlen(input) return table.concat(out, "\n")
if len <= 1 then
return "u"..input
end
local dict = {}
for i = 0, 255 do
local ic, iic = strchar(i), strchar(i, 0)
dict[ic] = iic
end
local a, b = 0, 1
local result = {"c"}
local resultlen = 1
local n = 2
local word = ""
for i = 1, len do
local c = strsub(input, i, i)
local wc = word..c
if not dict[wc] then
local write = dict[word]
if not write then
return nil
end
result[n] = write
resultlen = resultlen + strlen(write)
n = n+1
if len <= resultlen then
return "u"..input
end
local str = wc
if a >= 256 then
a, b = 0, b+1
if b >= 256 then
dict = {}
b = 1
end
end
dict[str] = strchar(a,b)
a = a+1
word = c
else
word = wc
end
end
result[n] = dict[word]
resultlen = resultlen+strlen(result[n])
n = n+1
if len <= resultlen then
return "u"..input
end
return table.concat(result)
end end
local function Encode(tbl)
return MAGIC .. wrap(C_EncodingUtil.EncodeBase64(
C_EncodingUtil.CompressString(
C_EncodingUtil.SerializeCBOR(tbl))), 92)
end
local function Decode(text)
if not text then return nil end
text = gsub(text, "%s", "")
if strsub(text, 1, strlen(MAGIC)) ~= MAGIC then return nil end
local ok, result = pcall(function()
return C_EncodingUtil.DeserializeCBOR(
C_EncodingUtil.DecompressString(
C_EncodingUtil.DecodeBase64(strsub(text, strlen(MAGIC) + 1))))
end)
if ok and type(result) == "table" then return result end
return nil
end
local function DecodeJSON(text)
if not text or gsub(text, "%s", "") == "" then return nil end
local ok, result = pcall(function()
return C_EncodingUtil.DeserializeJSON(text)
end)
if ok and type(result) == "table" then return result end
return nil
end
-- Legacy import (pre-!pf1! exports): base64 -> LZW -> Lua source
-- "pfUI_config = {...}". The base64 layer is standard and handled by
-- C_EncodingUtil.DecodeBase64; only the custom LZW format needs the old
-- Lua decoder. Import-only — new exports always use the CBOR pipeline.
local function decompress(input) local function decompress(input)
-- based on Rochet2's lzw compression -- based on Rochet2's lzw compression
if type(input) ~= "string" or strlen(input) < 1 then if type(input) ~= "string" or strlen(input) < 1 then
@@ -159,92 +144,32 @@ pfUI:RegisterModule("share", function ()
return table.concat(result) return table.concat(result)
end end
local function enc(to_encode) local function DecodeLegacy(text)
local index_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' if not text or gsub(text, "%s", "") == "" then return nil end
local bit_pattern = ''
local encoded = ''
local trailing = ''
for i = 1, string.len(to_encode) do -- encoded blob? peel base64 + LZW down to Lua source. Raw (already
local remaining = tonumber(string.byte(string.sub(to_encode, i, i))) -- decoded) source pastes are accepted as-is.
local bin_bits = '' local source = text
for i = 7, 0, -1 do local stripped = gsub(text, "%s", "")
local current_power = math.pow(2, i) local ok, decoded = pcall(function()
if remaining >= current_power then return C_EncodingUtil.DecodeBase64(stripped)
bin_bits = bin_bits .. '1' end)
remaining = remaining - current_power if ok and decoded then
else local decompressed = decompress(decoded)
bin_bits = bin_bits .. '0' if decompressed then source = decompressed end
end
end
bit_pattern = bit_pattern .. bin_bits
end end
if mod(string.len(bit_pattern), 3) == 2 then local chunk = loadstring(source)
trailing = '==' if not chunk then return nil end
bit_pattern = bit_pattern .. '0000000000000000'
elseif mod(string.len(bit_pattern), 3) == 1 then
trailing = '='
bit_pattern = bit_pattern .. '00000000'
end
local count = 0 -- Sandbox the chunk: an empty environment means it can assign its
for i = 1, string.len(bit_pattern), 6 do -- config table but can't reach any global or API function — a legacy
local byte = string.sub(bit_pattern, i, i+5) -- profile string is data, never code.
local offset = tonumber(tonumber(byte, 2)) local sandbox = {}
encoded = encoded .. string.sub(index_table, offset+1, offset+1) setfenv(chunk, sandbox)
count = count + 1 if not pcall(chunk) then return nil end
if count >= 92 then if type(sandbox.pfUI_config) == "table" then return sandbox.pfUI_config end
encoded = encoded .. "\n" return nil
count = 0
end
end
return string.sub(encoded, 1, -1 - string.len(trailing)) .. trailing
end
local function dec(to_decode)
local index_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
local padded = gsub(to_decode,"%s", "")
local unpadded = gsub(padded,"=", "")
local bit_pattern = ''
local decoded = ''
to_decode = gsub(to_decode,"\n", "")
to_decode = gsub(to_decode," ", "")
for i = 1, string.len(unpadded) do
local char = string.sub(to_decode, i, i)
local offset, _ = string.find(index_table, char)
if offset == nil then return nil end
local remaining = tonumber(offset-1)
local bin_bits = ''
for i = 7, 0, -1 do
local current_power = math.pow(2, i)
if remaining >= current_power then
bin_bits = bin_bits .. '1'
remaining = remaining - current_power
else
bin_bits = bin_bits .. '0'
end
end
bit_pattern = bit_pattern .. string.sub(bin_bits, 3)
end
for i = 1, string.len(bit_pattern), 8 do
local byte = string.sub(bit_pattern, i, i+7)
decoded = decoded .. strchar(tonumber(byte, 2))
end
local padding_length = string.len(padded)-string.len(unpadded)
if (padding_length == 1 or padding_length == 2) then
decoded = string.sub(decoded,1,-2)
end
return decoded
end end
do -- Window do -- Window
@@ -309,33 +234,43 @@ pfUI:RegisterModule("share", function ()
this:GetParent():UpdateScrollChildRect() this:GetParent():UpdateScrollChildRect()
this:GetParent():UpdateScrollState() this:GetParent():UpdateScrollState()
local _, error = loadstring(f.scroll.text:GetText()) local text = this:GetText()
if error or string.gsub(this:GetText(), " ", "") == "" then local blob = Decode(text)
f.loadButton:Disable() local json = not blob and DecodeJSON(text) or nil
f.loadButton.text:SetTextColor(1,.5,.5,1) local legacy = not blob and not json and DecodeLegacy(text) or nil
else
if blob or json or legacy then
f.loadButton:Enable() f.loadButton:Enable()
f.loadButton.text:SetTextColor(.5,1,.5,1) f.loadButton.text:SetTextColor(.5,1,.5,1)
else
f.loadButton:Disable()
f.loadButton.text:SetTextColor(1,.5,.5,1)
end end
local trydec = dec(this:GetText()) if blob or legacy then
if string.gsub(this:GetText(), " ", "") == "" then -- decoding a legacy string yields the JSON view; re-encoding it
f.readButton.text:SetText(T["N/A"]) -- from there produces a new-format blob (migration path)
f.readButton:Disable()
elseif not trydec or trydec == "" then
f.readButton:Enable()
f.readButton.text:SetText(T["Encode"])
f.readButton.func = function()
local compressed = enc(compress(f.scroll.text:GetText()))
f.scroll.text:SetText(compressed)
end
else
f.readButton:Enable() f.readButton:Enable()
f.readButton.text:SetText(T["Decode"]) f.readButton.text:SetText(T["Decode"])
f.readButton.func = function() f.readButton.func = function()
local uncompressed = decompress(dec(f.scroll.text:GetText())) local current = f.scroll.text:GetText()
f.scroll.text:SetText(uncompressed) local config = Decode(current) or DecodeLegacy(current)
if config then
f.scroll.text:SetText(C_EncodingUtil.SerializeJSON(config))
end
end end
elseif json then
f.readButton:Enable()
f.readButton.text:SetText(T["Encode"])
f.readButton.func = function()
local config = DecodeJSON(f.scroll.text:GetText())
if config then
f.scroll.text:SetText(Encode(config))
end
end
else
f.readButton:Disable()
f.readButton.text:SetText(T["N/A"])
end end
end) end)
f.scroll:SetScrollChild(f.scroll.text) f.scroll:SetScrollChild(f.scroll.text)
@@ -387,21 +322,23 @@ pfUI:RegisterModule("share", function ()
f.loadButton.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE") f.loadButton.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
f.loadButton.text:SetText(T["Import"]) f.loadButton.text:SetText(T["Import"])
f.loadButton:SetScript("OnClick", function() f.loadButton:SetScript("OnClick", function()
local ImportConfig, error = loadstring(f.scroll.text:GetText()) local text = f.scroll.text:GetText()
if not error and f.scroll.text:GetText() ~= "" then local config = Decode(text) or DecodeJSON(text) or DecodeLegacy(text)
ImportConfig() if not config then return end
pfUI:LoadConfig()
-- Skip firstrun wizard when importing a shared profile _G.pfUI_config = config
-- The imported config is a complete setup, no wizard needed C = _G.pfUI_config
if pfUI.firstrun and pfUI.firstrun.steps then pfUI:LoadConfig()
for _, step in pairs(pfUI.firstrun.steps) do
pfUI_init[step.name] = true -- Skip firstrun wizard when importing a shared profile
end -- The imported config is a complete setup, no wizard needed
if pfUI.firstrun and pfUI.firstrun.steps then
for _, step in pairs(pfUI.firstrun.steps) do
pfUI_init[step.name] = true
end end
CreateQuestionDialog(T["Some settings need to reload the UI to take effect.\nDo you want to reloadUI now?"], ReloadUI)
end end
CreateQuestionDialog(T["Some settings need to reload the UI to take effect.\nDo you want to reloadUI now?"], ReloadUI)
end) end)
end end
@@ -445,9 +382,9 @@ pfUI:RegisterModule("share", function ()
ignored["position"] = f.ignorePosition:GetChecked() ignored["position"] = f.ignorePosition:GetChecked()
ignored["disabled"] = f.ignorePosition:GetChecked() ignored["disabled"] = f.ignorePosition:GetChecked()
local compressed = enc(compress(serialize(myconfig, defconfig, "pfUI_config", ignored))) local encoded = Encode(DiffConfig(myconfig, defconfig, ignored) or {})
f.scroll.text:SetText(compressed) f.scroll.text:SetText(encoded)
f.scroll.text.value = compressed f.scroll.text.value = encoded
f.scroll:SetVerticalScroll(0) f.scroll:SetVerticalScroll(0)
end) end)
end end
@@ -457,4 +394,4 @@ pfUI:RegisterModule("share", function ()
f:Show() f:Show()
end end
end end
end) end)
+2 -2
View File
@@ -51,12 +51,12 @@ pfUI:RegisterModule("skin", function ()
DurabilityFrame.SetPoint = function() return end DurabilityFrame.SetPoint = function() return end
if C.appearance.cd.blizzard == "1" then if C.appearance.cd.blizzard == "1" then
hooksecurefunc("PaperDollItemSlotButton_Update", function() pfUI.hooksecurefunc("PaperDollItemSlotButton_Update", function()
local cooldown = _G[this:GetName().."Cooldown"] local cooldown = _G[this:GetName().."Cooldown"]
if cooldown then cooldown.pfCooldownType = "BLIZZARD" end if cooldown then cooldown.pfCooldownType = "BLIZZARD" end
end) end)
hooksecurefunc("SpellButton_UpdateButton", function() pfUI.hooksecurefunc("SpellButton_UpdateButton", function()
local cooldown = _G[this:GetName().."Cooldown"] local cooldown = _G[this:GetName().."Cooldown"]
if cooldown then cooldown.pfCooldownType = "BLIZZARD" end if cooldown then cooldown.pfCooldownType = "BLIZZARD" end
end) end)
+3 -3
View File
@@ -10,7 +10,7 @@ pfUI:RegisterModule("socialmod", function ()
end end
end) end)
do -- add colors to guild list do -- add colors to guild list
hooksecurefunc("GuildStatus_Update", function() pfUI.hooksecurefunc("GuildStatus_Update", function()
local playerzone = GetRealZoneText() local playerzone = GetRealZoneText()
local off = FauxScrollFrame_GetOffset(GuildListScrollFrame) local off = FauxScrollFrame_GetOffset(GuildListScrollFrame)
for i=1, GUILDMEMBERS_TO_DISPLAY, 1 do for i=1, GUILDMEMBERS_TO_DISPLAY, 1 do
@@ -70,7 +70,7 @@ pfUI:RegisterModule("socialmod", function ()
end end
do -- add colors to friend list do -- add colors to friend list
hooksecurefunc("FriendsList_Update", function() pfUI.hooksecurefunc("FriendsList_Update", function()
if GetNumFriends() == 0 then return end if GetNumFriends() == 0 then return end
local playerzone = GetRealZoneText() local playerzone = GetRealZoneText()
@@ -123,7 +123,7 @@ pfUI:RegisterModule("socialmod", function ()
end end
do -- add colors to who list do -- add colors to who list
hooksecurefunc("WhoList_Update", function() pfUI.hooksecurefunc("WhoList_Update", function()
local num, max = GetNumWhoResults() local num, max = GetNumWhoResults()
local off = FauxScrollFrame_GetOffset(WhoListScrollFrame) local off = FauxScrollFrame_GetOffset(WhoListScrollFrame)
+6 -8
View File
@@ -32,7 +32,6 @@ pfUI:RegisterModule("swingtimer", function ()
isDruid = false, isDruid = false,
cachedHSSlots = {}, cachedCleaveSlots = {}, cachedHSSlots = {}, cachedCleaveSlots = {},
useSpellQueueEvent = false, useSpellQueueEvent = false,
playerGUID = nil,
swingThrottle = 0, swingThrottle = 0,
onSwingCache = {}, onSwingCache = {},
} }
@@ -789,7 +788,7 @@ pfUI:RegisterModule("swingtimer", function ()
events:RegisterEvent("AUTO_ATTACK_SELF") events:RegisterEvent("AUTO_ATTACK_SELF")
events:RegisterEvent("AUTO_ATTACK_OTHER") events:RegisterEvent("AUTO_ATTACK_OTHER")
events:RegisterEvent("PLAYER_ENTERING_WORLD") events:RegisterEvent("PLAYER_ENTERING_WORLD")
events:RegisterEvent("UNIT_INVENTORY_CHANGED") events:RegisterEvent("PLAYER_EQUIPMENT_CHANGED") -- ClassicAPI: per-slot, equipment-only
events:RegisterEvent("PLAYER_REGEN_DISABLED") events:RegisterEvent("PLAYER_REGEN_DISABLED")
events:RegisterEvent("PLAYER_REGEN_ENABLED") events:RegisterEvent("PLAYER_REGEN_ENABLED")
events:RegisterEvent("ACTIONBAR_SLOT_CHANGED") events:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
@@ -832,8 +831,7 @@ pfUI:RegisterModule("swingtimer", function ()
elseif event == "AUTO_ATTACK_OTHER" then elseif event == "AUTO_ATTACK_OTHER" then
-- Parry haste: enemy attacked the player and player parried -- Parry haste: enemy attacked the player and player parried
local targetGuid = arg2 local targetGuid = arg2
if not targetGuid or not S.playerGUID then return end if not targetGuid or not IsPlayerGuid(targetGuid) then return end
if targetGuid ~= S.playerGUID then return end
local victimState = arg5 or 0 local victimState = arg5 or 0
-- VICTIMSTATE_PARRY = 3 -- VICTIMSTATE_PARRY = 3
-- Vanilla: parry reduces the NEXT swing timer by 40% of weapon speed, -- Vanilla: parry reduces the NEXT swing timer by 40% of weapon speed,
@@ -880,12 +878,12 @@ pfUI:RegisterModule("swingtimer", function ()
local _, class = UnitClass("player") local _, class = UnitClass("player")
S.isWarrior = (class == "WARRIOR") S.isWarrior = (class == "WARRIOR")
S.isDruid = (class == "DRUID") S.isDruid = (class == "DRUID")
S.playerGUID = UnitGUID("player")
UpdateWeaponSpeeds() UpdateWeaponSpeeds()
RebuildQueueSlotCache() RebuildQueueSlotCache()
elseif event == "UNIT_INVENTORY_CHANGED" then elseif event == "PLAYER_EQUIPMENT_CHANGED" then
if arg1 and arg1 ~= "player" then return end -- arg1 = changed slot; only weapon slots (main/off/ranged) affect swing speed
if not INVSLOTS_EQUIPABLE_IN_COMBAT[arg1] then return end
UpdateWeaponSpeeds() UpdateWeaponSpeeds()
if S.ohSpeed == 0 then if S.ohSpeed == 0 then
S.ohActive = false S.ohActive = false
@@ -910,7 +908,7 @@ pfUI:RegisterModule("swingtimer", function ()
S.maulQueued = false S.maulQueued = false
elseif event == "UNIT_DIED" then elseif event == "UNIT_DIED" then
if arg1 and arg1 == S.playerGUID then if IsPlayerGuid(arg1) then
ResetAll() ResetAll()
end end
end end
+5 -5
View File
@@ -530,7 +530,7 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
end end
-- replace wim class colors with pfUI ones -- replace wim class colors with pfUI ones
hooksecurefunc("WIM_InitClassProps", function() pfUI.hooksecurefunc("WIM_InitClassProps", function()
for class in pairs(PFUI_CLASS_COLORS) do for class in pairs(PFUI_CLASS_COLORS) do
local wimclass = _G[format("WIM_LOCALIZED_%s",class)] local wimclass = _G[format("WIM_LOCALIZED_%s",class)]
local colorstr = "|c" .. PFUI_CLASS_COLORS[class].colorStr local colorstr = "|c" .. PFUI_CLASS_COLORS[class].colorStr
@@ -547,7 +547,7 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
btnClose:SetWidth(13) btnClose:SetWidth(13)
btnClose:SetHeight(13) btnClose:SetHeight(13)
end end
hooksecurefunc("WIM_Icon_DropDown_Update", function() pfUI.hooksecurefunc("WIM_Icon_DropDown_Update", function()
for i=1,_G.WIM_MaxMenuCount do for i=1,_G.WIM_MaxMenuCount do
local btn = _G["WIM_ConversationMenuTellButton"..i] local btn = _G["WIM_ConversationMenuTellButton"..i]
if i==1 and btn:IsEnabled() == 0 then return end if i==1 and btn:IsEnabled() == 0 then return end
@@ -729,7 +729,7 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
SkinScrollbar(WIM_HelpScrollFrameScrollBar) SkinScrollbar(WIM_HelpScrollFrameScrollBar)
end end
hooksecurefunc("WIM_WindowOnShow", function() pfUI.hooksecurefunc("WIM_WindowOnShow", function()
if this.backdrop then return end -- already skinned if this.backdrop then return end -- already skinned
local windowname = this:GetName() local windowname = this:GetName()
@@ -904,7 +904,7 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
end end
-- trigger the event whenever SuperMacro got an update -- trigger the event whenever SuperMacro got an update
hooksecurefunc("SM_UpdateActionSpell", function() pfUI.hooksecurefunc("SM_UpdateActionSpell", function()
for slot=1,120 do pfUI.bars.update[slot] = true end for slot=1,120 do pfUI.bars.update[slot] = true end
end) end)
end) end)
@@ -922,7 +922,7 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
pfUI.bars.skip_macro = true pfUI.bars.skip_macro = true
-- send clevermacro events to pfUI actionbars -- send clevermacro events to pfUI actionbars
hooksecurefunc("ActionButton_OnEvent", function(event) pfUI.hooksecurefunc("ActionButton_OnEvent", function(event)
events(this, event) events(this, event)
end) end)
end) end)
+4 -62
View File
@@ -1,5 +1,5 @@
-- skip module initialization on every other client than turtle-wow -- skip module initialization on every other client than turtle-wow
if not TargetHPText or not TargetHPPercText then return end if not TURTLE_WOW_VERSION then return end
pfUI:RegisterModule("turtle-wow", function () pfUI:RegisterModule("turtle-wow", function ()
-- Manage Turtle WoW's GroupUI (Turtle_GroupUI addon) vs pfUI frames. -- Manage Turtle WoW's GroupUI (Turtle_GroupUI addon) vs pfUI frames.
@@ -65,14 +65,14 @@ pfUI:RegisterModule("turtle-wow", function ()
HookAddonOrVariable("GroupFrame", function() HookAddonOrVariable("GroupFrame", function()
-- After Turtle's own init, hide frames if pfUI handles them -- After Turtle's own init, hide frames if pfUI handles them
hooksecurefunc("GroupFrame_Toggle", function() pfUI.hooksecurefunc("GroupFrame_Toggle", function()
if pfUIHandlesGroupOrRaid() then if pfUIHandlesGroupOrRaid() then
DisableTurtleGroupFrames() DisableTurtleGroupFrames()
end end
end) end)
-- After every group/raid update, re-hide if pfUI handles them -- After every group/raid update, re-hide if pfUI handles them
hooksecurefunc("GroupFrame_Update", function() pfUI.hooksecurefunc("GroupFrame_Update", function()
if pfUIHandlesGroupOrRaid() then if pfUIHandlesGroupOrRaid() then
DisableTurtleGroupFrames() DisableTurtleGroupFrames()
end end
@@ -86,64 +86,6 @@ pfUI:RegisterModule("turtle-wow", function ()
L["debuffs"]['Moonfire'] = {[1]=9.0,[2]=18.0,[3]=18.0,[4]=18.0,[5]=18.0,[6]=18.0,[7]=18.0,[8]=18.0,[9]=18.0,[10]=18.0,[0]=18.0} L["debuffs"]['Moonfire'] = {[1]=9.0,[2]=18.0,[3]=18.0,[4]=18.0,[5]=18.0,[6]=18.0,[7]=18.0,[8]=18.0,[9]=18.0,[10]=18.0,[0]=18.0}
L["debuffs"]['Deep Wound'] = {[0]=6.0} L["debuffs"]['Deep Wound'] = {[0]=6.0}
-- add custom spell logic to libdebuff
HookScript(libdebuff, "OnEvent", function()
if event == "CHAT_MSG_SPELL_SELF_DAMAGE" then
-- refresh paladin judgements on holy strike
-- taken from: https://github.com/doorknob6/pfUI-turtle/blob/master/modules/debuffs.lua
local holystrike = string.find(string.sub(arg1,6,17), "Holy Strike")
--arg2 is spell dmg when it hits, nil when it misses
if holystrike and arg2 then
for seal in L["judgements"] do
local name = UnitName("target")
local level = UnitLevel("target")
if name and libdebuff.objects[name] then
if level and
libdebuff.objects[name][level] and
libdebuff.objects[name][level][seal] then
libdebuff:AddEffect(name, level, seal)
elseif libdebuff.objects[name][0] and
libdebuff.objects[name][0][seal] then
libdebuff:AddEffect(name, 0, seal)
end
end
end
end
-- refresh rip and rake duration on ferocious bite (Turtle WoW feature)
-- Only refresh if Ferocious Bite actually hit (not missed/dodged/parried/etc.)
local match = string.find(arg1, "Ferocious Bite")
if match and arg2 and not libdebuff:DidSpellFail("Ferocious Bite") then
local name = UnitName("target")
local level = UnitLevel("target")
-- Refresh Rip mit existierender Duration
if libdebuff.objects[name] and libdebuff.objects[name][level] and libdebuff.objects[name][level]["Rip"] then
local existingDuration = libdebuff.objects[name][level]["Rip"].duration
libdebuff:AddEffect(name, level, "Rip", existingDuration)
end
-- Refresh Rake mit existierender Duration
if libdebuff.objects[name] and libdebuff.objects[name][level] and libdebuff.objects[name][level]["Rake"] then
local existingDuration = libdebuff.objects[name][level]["Rake"].duration
libdebuff:AddEffect(name, level, "Rake", existingDuration)
end
end
-- refresh Immolate duration after cast Conflagrate
-- Only refresh if Conflagrate actually hit
local conflagrate = string.find(string.sub(arg1,6,17), "Conflagrate")
if conflagrate and arg2 and not libdebuff:DidSpellFail("Conflagrate") then
local name = UnitName("target")
local level = UnitLevel("target")
if libdebuff.objects[name] and libdebuff.objects[name][level] and libdebuff.objects[name][level]["Immolate"] then
local duration = libdebuff.objects[name][level]["Immolate"].duration
libdebuff:UpdateDuration(name, level, "Immolate", duration - 3)
end
end
end
end)
-- turtle wow totemic recall clear totem indicators -- turtle wow totemic recall clear totem indicators
local _, class = UnitClass("player") local _, class = UnitClass("player")
if libtotem and class == "SHAMAN" then if libtotem and class == "SHAMAN" then
@@ -353,7 +295,7 @@ pfUI:RegisterModule("turtle-wow", function ()
local initialized = false local initialized = false
HookAddonOrVariable("Blizzard_InspectUI", function() HookAddonOrVariable("Blizzard_InspectUI", function()
hooksecurefunc("InspectFrame_Show", function() pfUI.hooksecurefunc("InspectFrame_Show", function()
-- break if theres nothing left to do -- break if theres nothing left to do
if initialized then return end if initialized then return end
+2 -2
View File
@@ -41,12 +41,12 @@ pfUI:RegisterModule("unusable", function ()
end end
-- update on regular pfUI button updates -- update on regular pfUI button updates
hooksecurefunc(pfUI.bag, "UpdateSlot", function(self, bag, slot) pfUI.hooksecurefunc(pfUI.bag, "UpdateSlot", function(self, bag, slot)
pfUI.unusable:UpdateSlot(bag, slot) pfUI.unusable:UpdateSlot(bag, slot)
end) end)
-- update on bank frame itemlock updates -- update on bank frame itemlock updates
hooksecurefunc("BankFrameItemButton_UpdateLock", function() pfUI.hooksecurefunc("BankFrameItemButton_UpdateLock", function()
pfUI.unusable:UpdateSlot(-1, this:GetID()) pfUI.unusable:UpdateSlot(-1, this:GetID())
end) end)
end) end)
+1 -1
View File
@@ -5,7 +5,7 @@ pfUI:RegisterModule("xpbar", function ()
local REST_WINDOW = 300 -- seconds of sliding-window samples for rate calc local REST_WINDOW = 300 -- seconds of sliding-window samples for rate calc
local REST_CAP_MUL = 1.5 -- target rested cap = UnitXPMax * 1.5 local REST_CAP_MUL = 1.5 -- target rested cap = UnitXPMax * 1.5
if IsTurtleWoW() then if TURTLE_WOW_VERSION then
REST_CAP_MUL = 1.13 REST_CAP_MUL = 1.13
end end
+1 -2
View File
@@ -27,7 +27,7 @@ do
-- ClassicAPI dependency check. -- ClassicAPI dependency check.
-- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus -- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus
-- API surface that ClassicAPI polyfills, so presence is required. -- API surface that ClassicAPI polyfills, so presence is required.
local PFUI_CLASSIC_API_MIN = 10507 -- (X*10000 + Y*100 + Z) local PFUI_CLASSIC_API_MIN = 10511 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI" local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest" local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
@@ -99,7 +99,6 @@ pfUI.skins = {}
pfUI.environment = {} pfUI.environment = {}
pfUI.movables = {} pfUI.movables = {}
pfUI.version = {} pfUI.version = {}
pfUI.hooks = {}
pfUI.env = {} pfUI.env = {}
pfUI.events = Mixin({}, CallbackRegistryMixin) pfUI.events = Mixin({}, CallbackRegistryMixin)
+5 -5
View File
@@ -12,7 +12,7 @@ pfUI:RegisterSkin("Auctionhouse", function ()
SkinArrowButton(AuctionsNextPageButton, "right", 18) SkinArrowButton(AuctionsNextPageButton, "right", 18)
end end
hooksecurefunc("AuctionFrame_OnShow", function() pfUI.hooksecurefunc("AuctionFrame_OnShow", function()
AuctionFrame:ClearAllPoints() AuctionFrame:ClearAllPoints()
AuctionFrame:SetPoint("TOPLEFT", 10, -104) AuctionFrame:SetPoint("TOPLEFT", 10, -104)
end) end)
@@ -76,7 +76,7 @@ pfUI:RegisterSkin("Auctionhouse", function ()
item:SetPoint("LEFT", 2, 0) item:SetPoint("LEFT", 2, 0)
end end
end end
hooksecurefunc("AuctionFrameBrowse_Update", function() pfUI.hooksecurefunc("AuctionFrameBrowse_Update", function()
for i = 1, NUM_BROWSE_TO_DISPLAY do for i = 1, NUM_BROWSE_TO_DISPLAY do
HandleIcon(_G["BrowseButton"..i.."Item"], _G["BrowseButton"..i.."ItemIconTexture"]) HandleIcon(_G["BrowseButton"..i.."Item"], _G["BrowseButton"..i.."ItemIconTexture"])
end end
@@ -145,7 +145,7 @@ pfUI:RegisterSkin("Auctionhouse", function ()
item:ClearAllPoints() item:ClearAllPoints()
item:SetPoint("LEFT", 2, 0) item:SetPoint("LEFT", 2, 0)
end end
hooksecurefunc("AuctionFrameBid_Update", function() pfUI.hooksecurefunc("AuctionFrameBid_Update", function()
for i = 1, NUM_BIDS_TO_DISPLAY do for i = 1, NUM_BIDS_TO_DISPLAY do
HandleIcon(_G["BidButton"..i.."Item"], _G["BidButton"..i.."ItemIconTexture"]) HandleIcon(_G["BidButton"..i.."Item"], _G["BidButton"..i.."ItemIconTexture"])
end end
@@ -191,14 +191,14 @@ pfUI:RegisterSkin("Auctionhouse", function ()
item:ClearAllPoints() item:ClearAllPoints()
item:SetPoint("LEFT", 2, 0) item:SetPoint("LEFT", 2, 0)
end end
hooksecurefunc("AuctionFrameAuctions_Update", function() pfUI.hooksecurefunc("AuctionFrameAuctions_Update", function()
for i = 1, NUM_AUCTIONS_TO_DISPLAY do for i = 1, NUM_AUCTIONS_TO_DISPLAY do
HandleIcon(_G["AuctionsButton"..i.."Item"], _G["AuctionsButton"..i.."ItemIconTexture"]) HandleIcon(_G["AuctionsButton"..i.."Item"], _G["AuctionsButton"..i.."ItemIconTexture"])
end end
end) end)
SkinButton(AuctionsItemButton) SkinButton(AuctionsItemButton)
hooksecurefunc("AuctionSellItemButton_OnEvent", function() pfUI.hooksecurefunc("AuctionSellItemButton_OnEvent", function()
if event ~= "NEW_AUCTION_UPDATE" then return end if event ~= "NEW_AUCTION_UPDATE" then return end
HandleIcon(AuctionsItemButton, AuctionsItemButton:GetNormalTexture()) HandleIcon(AuctionsItemButton, AuctionsItemButton:GetNormalTexture())
end) end)
+1 -1
View File
@@ -19,7 +19,7 @@ pfUI:RegisterSkin("Battlefield Minimap", function ()
BattlefieldMinimapTab:Hide() BattlefieldMinimapTab:Hide()
end) end)
hooksecurefunc("BattlefieldMinimap_ShowOpacity", function() pfUI.hooksecurefunc("BattlefieldMinimap_ShowOpacity", function()
OpacityFrame:ClearAllPoints() OpacityFrame:ClearAllPoints()
OpacityFrame:SetPoint("TOPRIGHT", "BattlefieldMinimap", "TOPLEFT", -2*border, 0) OpacityFrame:SetPoint("TOPRIGHT", "BattlefieldMinimap", "TOPLEFT", -2*border, 0)
end) end)
+4 -4
View File
@@ -136,18 +136,18 @@ pfUI:RegisterSkin("Character", function ()
end end
end end
hooksecurefunc("CharacterFrame_OnShow", function() pfUI.hooksecurefunc("CharacterFrame_OnShow", function()
RefreshCharacterSlots() RefreshCharacterSlots()
RefreshPetPosition() RefreshPetPosition()
end) end)
hooksecurefunc("PaperDollItemSlotButton_Update", function() pfUI.hooksecurefunc("PaperDollItemSlotButton_Update", function()
if this:GetParent() == PaperDollFrame then if this:GetParent() == PaperDollFrame then
RefreshCharacterSlot(this) RefreshCharacterSlot(this)
end end
end) end)
hooksecurefunc("PetTab_Update", RefreshPetPosition) pfUI.hooksecurefunc("PetTab_Update", RefreshPetPosition)
StripTextures(PaperDollFrame) StripTextures(PaperDollFrame)
StripTextures(CharacterAttributesFrame) StripTextures(CharacterAttributesFrame)
@@ -270,7 +270,7 @@ pfUI:RegisterSkin("Character", function ()
-- the FactionStanding text from `bar.standingText` on mouseout, so we -- the FactionStanding text from `bar.standingText` on mouseout, so we
-- stash our augmented text there too — otherwise hovering a bar strips -- stash our augmented text there too — otherwise hovering a bar strips
-- the "(N)" suffix off. -- the "(N)" suffix off.
hooksecurefunc("ReputationFrame_Update", function() pfUI.hooksecurefunc("ReputationFrame_Update", function()
if C.character.reputation.repRequired ~= "1" then return end if C.character.reputation.repRequired ~= "1" then return end
local offset = FauxScrollFrame_GetOffset(ReputationListScrollFrame) local offset = FauxScrollFrame_GetOffset(ReputationListScrollFrame)
for i = 1, NUM_FACTIONS_DISPLAYED do for i = 1, NUM_FACTIONS_DISPLAYED do
+2 -2
View File
@@ -150,7 +150,7 @@ pfUI:RegisterSkin("Friends", function ()
end end
-- set positions -- set positions
hooksecurefunc("WhoList_Update", function() pfUI.hooksecurefunc("WhoList_Update", function()
for i = 1, WHOS_TO_DISPLAY do for i = 1, WHOS_TO_DISPLAY do
local level = _G["WhoFrameButton"..i.."Level"] local level = _G["WhoFrameButton"..i.."Level"]
level:ClearAllPoints() level:ClearAllPoints()
@@ -231,7 +231,7 @@ pfUI:RegisterSkin("Friends", function ()
end end
-- set positions -- set positions
hooksecurefunc("GuildStatus_Update", function() pfUI.hooksecurefunc("GuildStatus_Update", function()
for i = 1, GUILDMEMBERS_TO_DISPLAY do for i = 1, GUILDMEMBERS_TO_DISPLAY do
local level = _G["GuildFrameButton"..i.."Level"] local level = _G["GuildFrameButton"..i.."Level"]
level:ClearAllPoints() level:ClearAllPoints()
+2 -2
View File
@@ -24,11 +24,11 @@ pfUI:RegisterSkin("Gossip and Quest", function ()
QuestRewardItemHighlightBG:SetTexture(1,1,1,.2) QuestRewardItemHighlightBG:SetTexture(1,1,1,.2)
QuestRewardItemHighlightBG:SetAllPoints() QuestRewardItemHighlightBG:SetAllPoints()
hooksecurefunc("QuestFrameItems_Update", function() pfUI.hooksecurefunc("QuestFrameItems_Update", function()
QuestRewardItemHighlight:Hide() QuestRewardItemHighlight:Hide()
end) end)
hooksecurefunc("QuestRewardItem_OnClick", function() pfUI.hooksecurefunc("QuestRewardItem_OnClick", function()
if this.type == "choice" then if this.type == "choice" then
QuestRewardItemHighlight:SetAllPoints(this.backdrop) QuestRewardItemHighlight:SetAllPoints(this.backdrop)
QuestRewardItemHighlight:Show() QuestRewardItemHighlight:Show()
+2 -2
View File
@@ -12,7 +12,7 @@ pfUI:RegisterSkin("Mailbox", function ()
StripTextures(SendMailPackageButton) StripTextures(SendMailPackageButton)
SkinButton(SendMailPackageButton, nil, nil, nil, nil, true) SkinButton(SendMailPackageButton, nil, nil, nil, nil, true)
hooksecurefunc("SendMailFrame_Update", function() pfUI.hooksecurefunc("SendMailFrame_Update", function()
HandleIcon(SendMailPackageButton, SendMailPackageButton:GetNormalTexture()) HandleIcon(SendMailPackageButton, SendMailPackageButton:GetNormalTexture())
local _, itemID = GetSendMailItemLink() local _, itemID = GetSendMailItemLink()
@@ -62,7 +62,7 @@ pfUI:RegisterSkin("Mailbox", function ()
do -- OpenMailFrame do -- OpenMailFrame
SkinButton(OpenMailPackageButton, nil, nil, nil, OpenMailPackageButtonIconTexture) SkinButton(OpenMailPackageButton, nil, nil, nil, OpenMailPackageButtonIconTexture)
hooksecurefunc("InboxFrame_OnClick", function(index) pfUI.hooksecurefunc("InboxFrame_OnClick", function(index)
local _, itemID = GetInboxItemLink(index) local _, itemID = GetInboxItemLink(index)
if itemID then if itemID then
local quality = C_Item.GetItemQualityByID(itemID) local quality = C_Item.GetItemQualityByID(itemID)
+2 -2
View File
@@ -6,7 +6,7 @@ pfUI:RegisterSkin("Merchant", function ()
if MerchantGuildBankRepairButton then -- tbc if MerchantGuildBankRepairButton then -- tbc
SkinButton(MerchantGuildBankRepairButton, nil, nil, nil, MerchantGuildBankRepairButtonIcon) SkinButton(MerchantGuildBankRepairButton, nil, nil, nil, MerchantGuildBankRepairButtonIcon)
MerchantGuildBankRepairButtonIcon:SetTexCoord(.59, .82, .06, .54) MerchantGuildBankRepairButtonIcon:SetTexCoord(.59, .82, .06, .54)
hooksecurefunc("MerchantFrame_UpdateRepairButtons", function() pfUI.hooksecurefunc("MerchantFrame_UpdateRepairButtons", function()
MerchantGuildBankRepairButton:ClearAllPoints() MerchantGuildBankRepairButton:ClearAllPoints()
MerchantGuildBankRepairButton:SetPoint("RIGHT", MerchantBuyBackItemItemButton, "LEFT", -14, 0) MerchantGuildBankRepairButton:SetPoint("RIGHT", MerchantBuyBackItemItemButton, "LEFT", -14, 0)
MerchantRepairAllButton:ClearAllPoints() MerchantRepairAllButton:ClearAllPoints()
@@ -56,7 +56,7 @@ pfUI:RegisterSkin("Merchant", function ()
moneyFrame:SetPoint("BOTTOMLEFT", itemButton, "BOTTOMRIGHT", 5, 1) moneyFrame:SetPoint("BOTTOMLEFT", itemButton, "BOTTOMRIGHT", 5, 1)
end end
hooksecurefunc("MerchantFrame_UpdateMerchantInfo", function() pfUI.hooksecurefunc("MerchantFrame_UpdateMerchantInfo", function()
if MerchantFrame.selectedTab == 1 then if MerchantFrame.selectedTab == 1 then
for i = 3, 11, 2 do for i = 3, 11, 2 do
_G["MerchantItem"..i]:ClearAllPoints() _G["MerchantItem"..i]:ClearAllPoints()
+1 -1
View File
@@ -184,7 +184,7 @@ pfUI:RegisterSkin("Options - New", function ()
end end
-- hook after category selection: UpdateOptions is local so we hook its caller -- hook after category selection: UpdateOptions is local so we hook its caller
hooksecurefunc("OptionsListButton_OnClick", SkinControls) pfUI.hooksecurefunc("OptionsListButton_OnClick", SkinControls)
-- also cover initial load -- also cover initial load
HookScript(OptionsFrame, "OnShow", SkinControls) HookScript(OptionsFrame, "OnShow", SkinControls)
end) end)
+1 -1
View File
@@ -19,7 +19,7 @@ pfUI:RegisterSkin("Options - Video", function ()
slider:SetPoint(point, anchor, anchorPoint, x, y - shift) slider:SetPoint(point, anchor, anchorPoint, x, y - shift)
end end
hooksecurefunc("OptionsFrame_Load", function() pfUI.hooksecurefunc("OptionsFrame_Load", function()
OptionsFramePixelShaders:SetWidth(230) OptionsFramePixelShaders:SetWidth(230)
OptionsFrameMiscellaneous:ClearAllPoints() OptionsFrameMiscellaneous:ClearAllPoints()
OptionsFrameMiscellaneous:SetPoint("LEFT", OptionsFramePixelShaders, "RIGHT", 6, 0) OptionsFrameMiscellaneous:SetPoint("LEFT", OptionsFramePixelShaders, "RIGHT", 6, 0)
+1 -1
View File
@@ -192,7 +192,7 @@ pfUI:RegisterSkin("Profession", function ()
reagentlabel:SetTextColor(1,1,1,1) reagentlabel:SetTextColor(1,1,1,1)
local scanner = libtipscan:GetScanner(name) local scanner = libtipscan:GetScanner(name)
hooksecurefunc(SetSelection, function(id) pfUI.hooksecurefunc(SetSelection, function(id)
if id and id ~= 0 then if id and id ~= 0 then
detailscroll:Show() detailscroll:Show()
HandleIcon(icon, icon:GetNormalTexture()) HandleIcon(icon, icon:GetNormalTexture())
+3 -3
View File
@@ -13,7 +13,7 @@ pfUI:RegisterSkin("Quest Log", function ()
StripTextures(QUEST_COUNT) StripTextures(QUEST_COUNT)
QUEST_COUNT:ClearAllPoints() QUEST_COUNT:ClearAllPoints()
hooksecurefunc("QuestLogUpdateQuestCount", function(numQuests) pfUI.hooksecurefunc("QuestLogUpdateQuestCount", function(numQuests)
QUEST_COUNT:ClearAllPoints() QUEST_COUNT:ClearAllPoints()
QUEST_COUNT:SetPoint("BOTTOMRIGHT", QuestLogFrame, "TOPRIGHT", 0, -50) QUEST_COUNT:SetPoint("BOTTOMRIGHT", QuestLogFrame, "TOPRIGHT", 0, -50)
end) end)
@@ -24,7 +24,7 @@ pfUI:RegisterSkin("Quest Log", function ()
QUEST_COUNT:SetPoint("TOPRIGHT", -10, -30) QUEST_COUNT:SetPoint("TOPRIGHT", -10, -30)
end end
hooksecurefunc("QuestLog_OnShow", function() pfUI.hooksecurefunc("QuestLog_OnShow", function()
QuestLogFrame:ClearAllPoints() QuestLogFrame:ClearAllPoints()
QuestLogFrame:SetPoint("TOPLEFT", 10, -104) QuestLogFrame:SetPoint("TOPLEFT", 10, -104)
end) end)
@@ -163,7 +163,7 @@ pfUI:RegisterSkin("Quest Log", function ()
QuestLogListScrollFrame:SetPoint("TOPLEFT", 10, -54) QuestLogListScrollFrame:SetPoint("TOPLEFT", 10, -54)
QuestLogListScrollFrame:SetHeight(350) QuestLogListScrollFrame:SetHeight(350)
hooksecurefunc("QuestLog_Update", function() pfUI.hooksecurefunc("QuestLog_Update", function()
local numEntries = GetNumQuestLogEntries() local numEntries = GetNumQuestLogEntries()
local questIndex, text, level, questTag, isHeader local questIndex, text, level, questTag, isHeader
+2 -2
View File
@@ -38,12 +38,12 @@ pfUI:RegisterSkin("Readycheck", function ()
frame.bar.text:SetPoint("CENTER", 0, 0) frame.bar.text:SetPoint("CENTER", 0, 0)
local max local max
hooksecurefunc("ShowReadyCheck", function() pfUI.hooksecurefunc("ShowReadyCheck", function()
max = ReadyCheckFrame.timer max = ReadyCheckFrame.timer
frame.bar:SetMinMaxValues(0, max) frame.bar:SetMinMaxValues(0, max)
end) end)
hooksecurefunc(update_func, function() pfUI.hooksecurefunc(update_func, function()
if not ReadyCheckFrame.timer then return end if not ReadyCheckFrame.timer then return end
local perc = ReadyCheckFrame.timer/max local perc = ReadyCheckFrame.timer/max
+1 -1
View File
@@ -32,7 +32,7 @@ pfUI:RegisterSkin("GM Survey", function ()
CreateBackdrop(GMSurveyCommentFrame, nil, true, .75) CreateBackdrop(GMSurveyCommentFrame, nil, true, .75)
SkinScrollbar(GMSurveyCommentScrollFrameScrollBar) SkinScrollbar(GMSurveyCommentScrollFrameScrollBar)
GMSurveyFrameComment:SetMaxLetters(2000) GMSurveyFrameComment:SetMaxLetters(2000)
hooksecurefunc("GMSurveyFrame_Update", function() pfUI.hooksecurefunc("GMSurveyFrame_Update", function()
GMSurveyFrameComment:SetWidth(505) GMSurveyFrameComment:SetWidth(505)
end) end)
end) end)
+1 -1
View File
@@ -41,7 +41,7 @@ pfUI:RegisterSkin("Trade", function ()
RecipientButtonBG:SetAllPoints() RecipientButtonBG:SetAllPoints()
end end
hooksecurefunc("TradeFrame_UpdateTargetItem", function(id) pfUI.hooksecurefunc("TradeFrame_UpdateTargetItem", function(id)
HandleIcon(_G["TradeRecipientItem"..id.."ItemButton"], _G["TradeRecipientItem"..id..'IconTexture']) HandleIcon(_G["TradeRecipientItem"..id.."ItemButton"], _G["TradeRecipientItem"..id..'IconTexture'])
end) end)
+1 -1
View File
@@ -36,7 +36,7 @@ pfUI:RegisterSkin("Trainer", function ()
StripTextures(ClassTrainerSkillIcon) StripTextures(ClassTrainerSkillIcon)
SkinButton(ClassTrainerSkillIcon, nil, nil, nil, nil, true) SkinButton(ClassTrainerSkillIcon, nil, nil, nil, nil, true)
hooksecurefunc("ClassTrainer_SetSelection", function() pfUI.hooksecurefunc("ClassTrainer_SetSelection", function()
HandleIcon(ClassTrainerSkillIcon, ClassTrainerSkillIcon:GetNormalTexture()) HandleIcon(ClassTrainerSkillIcon, ClassTrainerSkillIcon:GetNormalTexture())
end) end)