10 Commits
Author SHA1 Message Date
Brues 4eab494a01 Name the installed ClassicAPI version in the outdated popup
"cannot run on this ClassicAPI" named no version, so the player had nothing
to compare against the requirement, and it overstated the failure: pfUI does
load on an old DLL, it just throws wherever it reaches for an API that isn't
there. Put the installed version in the headline and soften it to "will not
work correctly"; the detail line then only has to state the requirement.
2026-09-07 17:55:56 -05:00
Brues bb8ce8fd63 apparently some addons can't figure out -1 for themselves 2026-09-05 07:19:58 -05:00
brues-code 75c4657ab9 ClassicAPI flavor TOCs, and drop the multi-client scaffolding (#53)
* nameplates: source totem icons from UnitCreatedBySpell

Read the totem's icon from the totem-drop spell (UnitCreatedBySpell +
GetSpellTexture) instead of the self-aura at index 1 plus a
UNIT_SPELLCAST_SUCCEEDED capture for active totems. The drop spell is a
broadcast descriptor field present for every summoned unit in range, so
it resolves immediately for passive and active totems alike and gives the
totem's own icon rather than the attack-spell proxy. Drops the
UNIT_SPELLCAST_SUCCEEDED registration and handler.

Re-read the spell each render and key the cached texture on the spell id
so an in-place totem swap (same unit, new drop spell -- no plate re-add)
refreshes the icon without needing the plate to leave and re-enter view.

* CAPI min bumped to 1.13.1

* Gracefully disable pfUI when ClassicAPI is missing

Add API_Check.lua as the first TOC entry. When the ClassicAPI DLL is
absent or below the minimum version it sets pfUI_disabled and stands up
an inert stub so the rest of the addon no-ops instead of flooding load
errors: modules and skins register their bodies into no-ops, and the
setfenv'd api/lib files run inside an environment where CreateFrame and
any missing global resolve to a null object -- so no real frames or live
handlers are created and missing API calls just return null. pfUI.lua
bails early on pfUI_disabled.

* auras: scan through GetAuraSlots instead of by-index loops

Every aura scan loop (unit frame buffs/debuffs, dispel indicators, buff and
custom indicators, player buff frame, buffwatch bars, tooltip buff row) now
enumerates a unit's auras once with C_UnitAuras.GetAuraSlots and reads each
aura by slot id via the positional C_UnitAuras.UnitAuraBySlot. The by-index
getters re-walk the aura array from slot 0 on every call, so a per-button
loop over them was quadratic in the aura count; one enumeration plus a
by-slot read per aura is linear.

pfUI.api.ScanAuraSlots(unit, filter, buf, max) wraps GetAuraSlots' fill-a-
table form (table as the 5th argument) so no vararg Lua frame is involved:
Lua 5.0 allocates an `arg` table for every vararg call, which showed up as
nameplate OnUpdate/OnEvent memory growth in the first cut of this change.

Single by-index reads in tooltip and click handlers are unchanged (one call
each, and SetUnitAura takes the same index).

Requires the ClassicAPI build that adds GetAuraSlots' fill form; on an older
DLL the 5th argument is ignored and ScanAuraSlots would read the first slot
id as the count.

* Show Faction/Race icons in chat

* Load pfUI through ClassicAPI's flavor TOCs

ClassicAPI redirects the read of pfUI\pfUI.toc to a flavored file whenever
the DLL is installed, so which TOC the client opens already answers whether
ClassicAPI is there. Split the manifest three ways and let that do the work:

  pfUI.toc             fallback, reached only when ClassicAPI is missing;
                       loads API_Check.lua and nothing else
  pfUI_ClassicAPI.toc  full addon, every non-Turtle client
  pfUI_Turtle.toc      full addon plus init\turtle.xml, on Turtle

The fallback TOC declares no SavedVariables. It used to, while API_Check.lua
reset pfUI_profiles to an empty table on the disabled path -- which truncated
the player's profiles on logout.

With the missing-DLL case handled by TOC selection, API_Check.lua drops the
null object stub that kept the other ~140 files quiet, along with
pfUI_disabled and the now unreachable early return in pfUI.lua. It keeps the
version gate, which still matters: the flavor redirect landed in ClassicAPI
v1.11.0, below the v1.13.1 pfUI needs, so an old DLL still gets served a
flavor TOC. pfUI.lua also loses a verbatim duplicate of the whole check.

Turtle-only files move to init\turtle.xml: modules\turtle-wow.lua (its
TURTLE_WOW_VERSION guard is now redundant) and the lft, turtle_shop,
barbershop, transmog and ebc skins. turtle-wow registers last instead of
75th of 84; the only ordering it relies on is pfUI.chat, registered 8th.

pfSellData moves to env\selldata.lua, listed only in pfUI_ClassicAPI.toc,
since turtle-wow.lua replaces the table wholesale on Turtle. env\tables.lua
keeps an empty declaration so sellvalue.lua has something to index when the
turtle-wow module is disabled.

The release workflow pinned PFUI_CLASSIC_API_LATEST in pfUI.lua, which has
not held that constant since it moved to API_Check.lua, so the pin was
silently doing nothing. It also switches to brues-code/packager@vCAPI, which
recognizes the _ClassicAPI and _Turtle suffixes and applies the TOC build
type filters to them.

* Split the vendor price tables into their own manifests

Turtle's pfSellData moves out of modules\turtle-wow.lua into
env\selldata_turtle.lua, matching env\selldata.lua for the stock list, and
each is pulled in by the manifest for its client: init\stock.xml from
pfUI_ClassicAPI.toc, init\turtle.xml from pfUI_Turtle.toc. Either way it
loads after init\env.xml and replaces the empty pfSellData declared there.

Turtle's prices used to be assigned inside the turtle-wow module body, which
put them on pfUI.env and skipped them entirely when that module was
disabled. At file scope they land on _G and apply either way.

* Drop the vanilla compat layer

compat\vanilla.lua named the handful of things that differed between clients
back when pfUI targeted several. Only one client remains, so every constant
had exactly one value. Inline each at its use site and delete the file,
init\compat.xml, and both TOC entries.

  COOLDOWN_FRAME_TYPE                    -> "Model"
  LOOT_BUTTON_FRAME_TYPE                 -> "LootButton"
  MINIMAP_TRACKING_FRAME                 -> _G.MiniMapTrackingFrame
  FRIENDS_NAME_LOCATION                  -> "ButtonTextNameLocation"
  EVENTS_MINIMAP_ZONE_UPDATE             -> the event list, in panel.lua
  MICRO_BUTTONS                          -> a local in panel.lua
  NAMEPLATE_OBJECTORDER                  -> a local in nameplates.lua
  ACTIONBAR_SECURE_TEMPLATE_BAR/_BUTTON  -> nil, so the argument goes away

NAMEPLATE_FRAMETYPE and PLAYER_BUFF_START_ID had no readers left.

RunMacroText moves to pfUI.lua. compat\vanilla.lua was setfenv'd into the
pfUI environment, so the function only ever existed on pfUI.env; at file
scope it lands on _G as a real export instead. Nothing in pfUI calls it, and
ClassicAPI neither defines nor looks for a RunMacroText global -- it does
the same throwaway edit box natively in src/macro/Execute.cpp and only
defers to a global RunMacro.

* bump CAPI min to 11303

* auras: uncap the self-debuff tooltip lookup

With selfdebuff on, the displayed debuff list is PLAYER-filtered while
GameTooltip:SetUnitAura indexes the unfiltered HARMFUL list, so both
handlers map one to the other by matching name + sourceGUID. That mapping
scanned slots 1..16 only.

The unfiltered harmful list is not capped at 16. Once a unit's 16 debuff
slots are full the server parks further debuffs in buff slots, and
C_UnitAuras classifies by the aura's polarity flag rather than its slot
range, so it reports those as harmful too -- verified live at 18 harmful on
a 20-aura target. Past the sixteenth the lookup found nothing and fell
through to the raw filtered index, opening the wrong tooltip or none.

Both now enumerate however many harmful auras the unit actually has, via
ScanAuraSlots, which also drops the per-index rescan the by-index accessor
was doing. Each handler gets its own slot buffer: OnEnter can fire while a
refresh is showing/hiding frames under the cursor, so sharing the refresh
buffer could clobber a scan mid-walk.

The nameplate module still collects at most 16 debuffs per plate. That one
is a display cap matching its 16 configured icon frames, not an aura-count
assumption, so it is left alone.

* bump CAPI min to 11304
2026-09-04 19:57:57 -05:00
Brues 5815b9e81e chat: let pfUI's chat colors own their alpha and apply live
Two problems with routing the native transparency slider into the pfUI panel.

RefreshBackgroundAlpha overwrote the alpha of C.chat.global.background on every
refresh, so anyone with custom colors enabled saw their configured opacity
revert on reload, tab switch and dock change. That value carries its own alpha,
is set by the shipped profiles and is shared with the meter skins, so the slider
must not own it. Skip the alpha mirror entirely when custom colors are on; the
slider still drives the panel on the default theme, which is what issue #48 was
actually about.

The colors were also only applied at module load, so the pickers needed a
/reload to show anything. Extract that into ApplyPanelColors and expose it as
pfUI.chat:UpdateConfig, which the gui resolves as U["chat"], so the three chat
color settings take effect on the spot. CreateBackdrop is re-run first to
restore the appearance theme, which is what lets toggling custom colors back
off return the panel to the global theme without a reload.
2026-09-02 11:40:20 -05:00
Brues 60f953178f nameplates: validate unitstr before filling the per-unit cache
cache.player and cache.minion were filled from unitstr before the two guards
that validate it, so a stale identifier poisoned the cache -- and because the
fill is gated on `== nil`, the wrong answer was never recomputed. Players read
back as cache.player == false until the plate was hidden and shown again, which
only appeared to fix it because pool reuse tripped the name/guid wipe.

Two paths produce a stale unitstr: OnUpdate dispatches a targetUpdate to
OnDataChanged before it refreshes plate.istarget, and frameState.mouseoverGuid
is only updated on gaining mouseover, never on losing it.

Hoist the PLAYER_TARGET_CHANGED distrust and the UnitName mismatch check above
the cache fill so an unverified unitstr leaves the cache nil for the next tick
instead of locking in a wrong answer.
2026-09-02 10:56:46 -05:00
Brues 1dc10964a2 luarc: use nested config form so diagnostics settings apply 2026-09-02 10:31:03 -05:00
Brues 0fc08e77c0 Create .pkgmeta 2026-09-02 10:26:28 -05:00
Brues 7f3795b45b Add .luarc.json for Lua 5.1 language server diagnostics 2026-09-02 10:23:48 -05:00
Brues 8eee766652 chat: apply Blizzard per-window transparency to docked backdrops
The native chat background transparency slider drives FCF_SetWindowAlpha,
which only touches the ChatFrame*Background textures pfUI hides on docked
frames, so the visible pfUI backdrop never responded to it.

Mirror the selected window's stored alpha (GetChatWindowInfo) onto the pfUI
backdrop and refresh it from RefreshChat, FCF_SetWindowAlpha and
FCF_SelectDockFrame so the native slider drives it live and persists across
/reload. Default the SetupPositions window alpha to 0.8 to keep the historical
look, and migrate existing installs whose windows still carry the old hard-0
alpha so their chat background is not suddenly transparent.

Fixes #48
2026-09-02 01:05:47 -05:00
Brues 2b5288a688 nameplates: don't run GetUnitInfo for minions 2026-08-31 16:43:38 -05:00
33 changed files with 5905 additions and 5603 deletions
+3 -3
View File
@@ -23,12 +23,12 @@ jobs:
IFS=. read -r MAJOR MINOR PATCH <<<"$LATEST" IFS=. read -r MAJOR MINOR PATCH <<<"$LATEST"
PACKED=$((MAJOR * 10000 + MINOR * 100 + PATCH)) PACKED=$((MAJOR * 10000 + MINOR * 100 + PATCH))
echo "Pinning PFUI_CLASSIC_API_LATEST to $LATEST ($PACKED)" echo "Pinning PFUI_CLASSIC_API_LATEST to $LATEST ($PACKED)"
sed -i "s/^\([[:space:]]*\)local PFUI_CLASSIC_API_LATEST = .*/\1local PFUI_CLASSIC_API_LATEST = $PACKED/" pfUI.lua sed -i "s/^\([[:space:]]*\)local PFUI_CLASSIC_API_LATEST = .*/\1local PFUI_CLASSIC_API_LATEST = $PACKED/" API_Check.lua
grep 'local PFUI_CLASSIC_API_' pfUI.lua grep 'local PFUI_CLASSIC_API_' API_Check.lua
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Package and release to GitHub - name: Package and release to GitHub
uses: BigWigsMods/packager@v2 uses: brues-code/packager@vCAPI
env: env:
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}
+22
View File
@@ -0,0 +1,22 @@
{
"runtime": {
"version": "Lua 5.1"
},
"diagnostics": {
"disable": ["deprecated"],
"globals": [
"this",
"event",
"arg",
"arg1",
"arg2",
"arg3",
"arg4",
"arg5",
"arg6",
"arg7",
"arg8",
"arg9"
]
}
}
+4
View File
@@ -0,0 +1,4 @@
package-as: pfUI
ignore:
- .luarc.json
+78
View File
@@ -0,0 +1,78 @@
do
-- ClassicAPI dependency gate.
--
-- Which TOC the client opened already answers "is ClassicAPI here?". Whenever
-- the DLL is loaded it redirects the read of `pfUI\pfUI.toc` to
-- `pfUI_Turtle.toc` (Turtle clients) or `pfUI_ClassicAPI.toc` (everything
-- else). Reaching this file from the plain `pfUI.toc` therefore means
-- ClassicAPI is absent -- and that TOC deliberately loads nothing but this
-- file, so there is nothing to disable, only a notice to show.
--
-- The flavor TOCs still need a version gate of their own: the redirect has
-- existed since ClassicAPI v1.11.0, well below the API surface pfUI relies
-- on. There pfUI does load, and will throw wherever it reaches for something
-- the installed DLL doesn't have yet -- the popup names the cause so those
-- errors aren't a mystery.
local PFUI_CLASSIC_API_MIN = 11304 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
local function FormatVersion(packed)
local x = math.floor(packed / 10000)
local y = math.floor(math.mod(packed, 10000) / 100)
local z = math.mod(packed, 100)
return string.format("v%d.%d.%d", x, y, z)
end
local headline, detail
if not CLASSIC_API_VERSION then
headline = "|cff33ffccpf|cffffffffUI|r has been disabled."
detail = "The ClassicAPI DLL isn't loaded. Download the latest release from:"
elseif CLASSIC_API_VERSION < PFUI_CLASSIC_API_MIN then
headline = "|cff33ffccpf|cffffffffUI|r will not work correctly on ClassicAPI " .. FormatVersion(CLASSIC_API_VERSION) .. "."
detail = FormatVersion(PFUI_CLASSIC_API_MIN) .. " or newer is required -- any errors alongside this one are the APIs it is missing. Download the latest release from:"
end
if detail then
local function ShowRequiredPopup()
StaticPopupDialogs["PFUI_CLASSICAPI_REQUIRED"] = {
text = headline .. "\n\n" .. detail,
button1 = OKAY,
hasEditBox = 1,
editBoxWidth = 280,
timeout = 0,
whileDead = 1,
hideOnEscape = 1,
preferredIndex = 3,
OnShow = function()
local editBox = getglobal(this:GetName().."EditBox")
if editBox then
editBox:SetText(PFUI_CLASSIC_API_LATEST_URL)
editBox:HighlightText()
editBox:SetFocus()
end
end,
}
StaticPopup_Show("PFUI_CLASSICAPI_REQUIRED")
DEFAULT_CHAT_FRAME:AddMessage(
headline .. " " .. detail .. " " .. PFUI_CLASSIC_API_LATEST_URL,
1, 0.3, 0.3
)
end
local loginFrame = CreateFrame("Frame")
loginFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
loginFrame:SetScript("OnEvent", function()
loginFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
ShowRequiredPopup()
end)
elseif CLASSIC_API_VERSION < PFUI_CLASSIC_API_LATEST then
EventUtil.ContinueOnPlayerLogin(function()
C_Timer.After(8, function()
DEFAULT_CHAT_FRAME:AddMessage(
"|cff33ffccpf|rUI: ClassicAPI " .. FormatVersion(PFUI_CLASSIC_API_LATEST) .. " is available — " .. PFUI_CLASSIC_API_LATEST_URL,
1, 0.85, 0.3
)
end)
end)
end
end
+59
View File
@@ -204,6 +204,26 @@ function pfUI.api.UnitHasBuff(unit, name)
return C_UnitAuras.GetAuraDataBySpellName(unit, name, "HELPFUL") ~= nil or nil return C_UnitAuras.GetAuraDataBySpellName(unit, name, "HELPFUL") ~= nil or nil
end end
-- [ ScanAuraSlots ]
-- Fills `buf` with the slot ids of the auras on `unit` that match `filter` and
-- returns how many (buf[1..n]; entries past n are cleared), so a module can
-- keep one buffer and refill it every refresh. Read each aura with
-- C_UnitAuras.UnitAuraBySlot(unit, buf[i]) (positional, no table) or
-- GetAuraDataBySlot. One enumeration walks the aura array once, where a
-- by-index loop (UnitAura(unit, i)) re-walks it from the start for every i.
-- Uses GetAuraSlots' fill-a-table form (table as the 5th argument) instead of
-- its vararg return: Lua 5.0 builds an `arg` table for every vararg call, so
-- collecting the returns in a Lua helper would allocate once per scan.
-- unit [string] unit token
-- filter [string] aura filter ("HELPFUL", "HARMFUL|PLAYER", ...)
-- buf [table] reusable buffer, filled in place
-- max [number] optional cap on the slot count (nil = all)
-- return: [number] count of slot ids written to buf
function pfUI.api.ScanAuraSlots(unit, filter, buf, max)
local _, n = C_UnitAuras.GetAuraSlots(unit, filter, max, nil, buf)
return n
end
-- [ IsPlayerGuid ] -- [ IsPlayerGuid ]
-- Returns whether a GUID or unit token refers to the local player. -- Returns whether a GUID or unit token refers to the local player.
-- guid [string] A unit GUID (or unitID) to test. -- guid [string] A unit GUID (or unitID) to test.
@@ -242,6 +262,45 @@ function pfUI.api.GetUnitColor(unitstr)
return classColor:GenerateHexColorMarkup(), classColor:GetRGB() return classColor:GenerateHexColorMarkup(), classColor:GetRGB()
end end
-- [ GetRaceIcon ]
-- Builds an inline race icon texture from the shared races atlas.
-- 'raceKey' [string] englishRace key (e.g. "NightElf")
-- 'sex' [int] unit sex (3 = female)
-- return: [string] inline texture escape, or an empty string
function pfUI.api.GetRaceIcon(raceKey, sex)
if not raceKey then return "" end
local gender = sex == 3 and "FEMALE" or "MALE"
local coords = RACE_ICON_TCOORDS[strupper(raceKey) .. "_" .. gender]
if not coords then return "" end
return string.format(
"|TInterface\\Glues\\CharacterCreate\\UI-CharacterCreate-Races:0:0:0:0:512:512:%d:%d:%d:%d|t",
coords[1] * 512, coords[2] * 512, coords[3] * 512, coords[4] * 512)
end
-- inline faction emblems (cropped from the target-frame PvP banners)
local FACTION_ICON = {
Alliance = "|TInterface\\TargetingFrame\\UI-PVP-Alliance:0:0:0:0:64:64:5:37:3:35|t",
Horde = "|TInterface\\TargetingFrame\\UI-PVP-Horde:0:0:0:0:64:64:5:37:3:35|t",
}
-- [ GetFactionIcon ]
-- Resolves an inline faction emblem from the englishRace key stored in L["race"].
-- 'raceKey' [string] englishRace key (e.g. "Orc")
-- return: [string] inline texture escape, or an empty string
function pfUI.api.GetFactionIcon(raceKey)
local info = raceKey and L["race"][raceKey]
if not info then return "" end
return FACTION_ICON[info.faction] or ""
end
-- [ GetPlayerRaceIcons ]
-- Returns the faction and race emblems of the player character.
-- return: [string] both inline textures, or an empty string
function pfUI.api.GetPlayerRaceIcons()
local _, raceKey = UnitRace("player")
return pfUI.api.GetFactionIcon(raceKey) .. pfUI.api.GetRaceIcon(raceKey, UnitSex("player"))
end
-- [ strvertical ] -- [ strvertical ]
-- Creates vertical text using linebreaks. Multibyte char friendly. -- Creates vertical text using linebreaks. Multibyte char friendly.
-- 'str' [string] String to columnize. -- 'str' [string] String to columnize.
+1
View File
@@ -817,6 +817,7 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("chat", "text", "playerlinks", "1") pfUI:UpdateConfig("chat", "text", "playerlinks", "1")
pfUI:UpdateConfig("chat", "text", "detecturl", "1") pfUI:UpdateConfig("chat", "text", "detecturl", "1")
pfUI:UpdateConfig("chat", "text", "classcolor", "1") pfUI:UpdateConfig("chat", "text", "classcolor", "1")
pfUI:UpdateConfig("chat", "text", "playericons", "0")
pfUI:UpdateConfig("chat", "text", "whosearchunknown", "0") pfUI:UpdateConfig("chat", "text", "whosearchunknown", "0")
pfUI:UpdateConfig("chat", "text", "playerlevel", "0") pfUI:UpdateConfig("chat", "text", "playerlevel", "0")
pfUI:UpdateConfig("chat", "left", "width", "380") pfUI:UpdateConfig("chat", "left", "width", "380")
+51 -30
View File
@@ -4,6 +4,17 @@ setfenv(1, pfUI:GetEnvironment())
pfUI.uf = CreateFrame("Frame", nil, UIParent) pfUI.uf = CreateFrame("Frame", nil, UIParent)
pfUI.uf.frames = {} pfUI.uf.frames = {}
-- Reusable buffer for C_UnitAuras.GetAuraSlots slot ids (filled by
-- ScanAuraSlots, api.lua). Each aura scan in RefreshUnit fills it once, then
-- reads every aura by slot id: one array walk per scan instead of one per index.
-- Scans run back to back and consume the buffer before the next refill.
local auraSlots = {}
-- Separate buffer for the tooltip handlers. They run from OnEnter, which can
-- fire while RefreshUnit is showing/hiding icons under the cursor, so they must
-- not share the refresh buffer.
local tooltipSlots = {}
-- ============================================================================ -- ============================================================================
-- GUID-based Roster Tracking for Smart Updates -- GUID-based Roster Tracking for Smart Updates
-- Only updates frames where the unit actually changed, not ALL 40 frames -- Only updates frames where the unit actually changed, not ALL 40 frames
@@ -88,16 +99,21 @@ local function DebuffOnEnter()
local parent = this:GetParent() local parent = this:GetParent()
-- selfdebuff filters the displayed list to player-cast harmful auras, but -- selfdebuff filters the displayed list to player-cast harmful auras, but
-- SetUnitAura's index has to be into the engine's full HARMFUL list. Look -- SetUnitAura's index has to be into the unfiltered HARMFUL list. Look up
-- up the displayed aura via the PLAYER filter, then scan engine slots for -- the displayed aura via the PLAYER filter, then find its position in the
-- one whose name + sourceGUID match. -- unfiltered list by name + sourceGUID.
--
-- The unfiltered list is NOT capped at 16: once a unit's 16 debuff slots
-- are full the server parks further debuffs in buff slots, and C_UnitAuras
-- reports those as harmful too. So enumerate however many the unit has.
if parent.config and parent.config.selfdebuff == "1" then if parent.config and parent.config.selfdebuff == "1" then
local ownAura = C_UnitAuras.GetAuraDataByIndex(unitstr, this.id, "HARMFUL|PLAYER") local ownAura = C_UnitAuras.GetAuraDataByIndex(unitstr, this.id, "HARMFUL|PLAYER")
if ownAura then if ownAura then
for gameSlot = 1, 16 do local n = ScanAuraSlots(unitstr, "HARMFUL", tooltipSlots)
local check = C_UnitAuras.GetDebuffDataByIndex(unitstr, gameSlot) for i = 1, n do
local check = C_UnitAuras.GetAuraDataBySlot(unitstr, tooltipSlots[i])
if check and check.name == ownAura.name and check.sourceGUID == ownAura.sourceGUID then if check and check.name == ownAura.name and check.sourceGUID == ownAura.sourceGUID then
GameTooltip:SetUnitAura(unitstr, gameSlot, "HARMFUL") GameTooltip:SetUnitAura(unitstr, i, "HARMFUL")
return return
end end
end end
@@ -761,7 +777,7 @@ function pfUI.uf:UpdateConfig()
if not f.buffs[i].cd then if not f.buffs[i].cd then
if cooldown_anim == 1 then if cooldown_anim == 1 then
-- Animation enabled: Use Model frame with CooldownFrameTemplate -- Animation enabled: Use Model frame with CooldownFrameTemplate
f.buffs[i].cd = CreateFrame(COOLDOWN_FRAME_TYPE, f.buffs[i]:GetName() .. "Cooldown", f.buffs[i], "CooldownFrameTemplate") f.buffs[i].cd = CreateFrame("Model", f.buffs[i]:GetName() .. "Cooldown", f.buffs[i], "CooldownFrameTemplate")
else else
-- Animation disabled: Use regular Frame with dummy functions -- Animation disabled: Use regular Frame with dummy functions
f.buffs[i].cd = CreateFrame("Frame", f.buffs[i]:GetName() .. "Cooldown", f.buffs[i]) f.buffs[i].cd = CreateFrame("Frame", f.buffs[i]:GetName() .. "Cooldown", f.buffs[i])
@@ -834,7 +850,7 @@ function pfUI.uf:UpdateConfig()
if not f.debuffs[i].cd then if not f.debuffs[i].cd then
if cooldown_anim == 1 then if cooldown_anim == 1 then
-- Animation enabled: Use Model frame with CooldownFrameTemplate -- Animation enabled: Use Model frame with CooldownFrameTemplate
f.debuffs[i].cd = CreateFrame(COOLDOWN_FRAME_TYPE, f.debuffs[i]:GetName() .. "Cooldown", f.debuffs[i], "CooldownFrameTemplate") f.debuffs[i].cd = CreateFrame("Model", f.debuffs[i]:GetName() .. "Cooldown", f.debuffs[i], "CooldownFrameTemplate")
else else
-- Animation disabled: Use regular Frame with dummy functions -- Animation disabled: Use regular Frame with dummy functions
f.debuffs[i].cd = CreateFrame("Frame", f.debuffs[i]:GetName() .. "Cooldown", f.debuffs[i]) f.debuffs[i].cd = CreateFrame("Frame", f.debuffs[i]:GetName() .. "Cooldown", f.debuffs[i])
@@ -1635,11 +1651,13 @@ function pfUI.uf:RefreshUnit(unit, component)
-- buffs -- buffs
if unit.buffs and ( component == "all" or component == "aura" ) then if unit.buffs and ( component == "all" or component == "aura" ) then
-- one GetAuraSlots enumeration per refresh, then a positional read per
-- slot id: allocates nothing and never re-walks the aura array per icon
ScanAuraSlots(unitstr, "HELPFUL", auraSlots, unit.config.bufflimit)
for i=1, unit.config.bufflimit do for i=1, unit.config.bufflimit do
if not unit.buffs[i] then break end if not unit.buffs[i] then break end
-- positional UnitBuff allocates nothing (vs a table per icon per refresh) local name, icon, count, _, duration, expirationTime, _, _, _, spellId = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
local name, icon, count, _, duration, expirationTime, _, _, _, spellId = C_UnitAuras.UnitBuff(unitstr, i)
if name then if name then
unit.buffs[i].texture:SetTexture(icon) unit.buffs[i].texture:SetTexture(icon)
@@ -1723,6 +1741,13 @@ function pfUI.uf:RefreshUnit(unit, component)
reposition = true reposition = true
end end
-- selfdebuff narrows to player-cast harmful auras via the PLAYER filter.
-- Player-frame debuffs aren't gated on it (it'd hide most party-applied
-- effects on you). One GetAuraSlots enumeration per refresh; the i-th slot
-- is the i-th aura of the filtered list, so `i` stays the tooltip index.
local filter = (unit.label ~= "player" and selfdebuff == "1") and "HARMFUL|PLAYER" or "HARMFUL"
ScanAuraSlots(unitstr, filter, auraSlots, unit.config.debufflimit)
for i=1, unit.config.debufflimit do for i=1, unit.config.debufflimit do
if not unit.debuffs[i] then break end if not unit.debuffs[i] then break end
@@ -1739,12 +1764,8 @@ function pfUI.uf:RefreshUnit(unit, component)
invert_h * ((row+buffrow)*(multiply*default_border + unit.config.debuffsize + 1) + (multiply*default_border + 1))) invert_h * ((row+buffrow)*(multiply*default_border + unit.config.debuffsize + 1) + (multiply*default_border + 1)))
end end
-- selfdebuff narrows to player-cast harmful auras via the PLAYER filter. -- positional read by slot id allocates nothing
-- Player-frame debuffs aren't gated on it (it'd hide most party-applied local name, icon, count, dispelType, duration, expirationTime = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
-- effects on you).
-- positional UnitDebuff allocates nothing; PLAYER predicate honored for selfdebuff
local filter = (unit.label ~= "player" and selfdebuff == "1") and "PLAYER" or nil
local name, icon, count, dispelType, duration, expirationTime = C_UnitAuras.UnitDebuff(unitstr, i, filter)
if name then if name then
texture, stacks, dtype = icon, count, dispelType texture, stacks, dtype = icon, count, dispelType
else else
@@ -1834,8 +1855,9 @@ function pfUI.uf:RefreshUnit(unit, component)
local present = pfUI.uf.dispelPresent or {} local present = pfUI.uf.dispelPresent or {}
pfUI.uf.dispelPresent = present pfUI.uf.dispelPresent = present
for k in pairs(present) do present[k] = nil end for k in pairs(present) do present[k] = nil end
for i=1,16 do local n = ScanAuraSlots(unitstr, "HARMFUL", auraSlots)
local name, _, _, dispelType = C_UnitAuras.UnitDebuff(unitstr, i) for i=1,n do
local name, _, _, dispelType = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
if name and dispelType and dispelType ~= "" then present[dispelType] = true end if name and dispelType and dispelType ~= "" then present[dispelType] = true end
end end
@@ -1925,9 +1947,9 @@ function pfUI.uf:RefreshUnit(unit, component)
local pos = 1 local pos = 1
if table.getn(unit.indicators) > 0 then if table.getn(unit.indicators) > 0 then
local i = 1 local n = ScanAuraSlots(unitstr, "HELPFUL", auraSlots)
while true do for i=1,n do
local name, icon, count, _, _, expirationTime = C_UnitAuras.UnitBuff(unitstr, i) local name, icon, count, _, _, expirationTime = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
if not name then break end if not name then break end
local texLower = string.lower(icon) local texLower = string.lower(icon)
local timeleft = expirationTime > 0 and (expirationTime - GetTime()) or nil local timeleft = expirationTime > 0 and (expirationTime - GetTime()) or nil
@@ -1948,14 +1970,13 @@ function pfUI.uf:RefreshUnit(unit, component)
break break
end end
end end
i = i + 1
end end
end end
if table.getn(unit.indicator_custom) > 0 then if table.getn(unit.indicator_custom) > 0 then
local ai = 1 local n = ScanAuraSlots(unitstr, "HELPFUL", auraSlots)
while true do for i=1,n do
local name, icon, count, _, _, expirationTime = C_UnitAuras.UnitBuff(unitstr, ai) local name, icon, count, _, _, expirationTime = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
if not name then break end if not name then break end
local timeleft = expirationTime > 0 and (expirationTime - GetTime()) or nil local timeleft = expirationTime > 0 and (expirationTime - GetTime()) or nil
local lowerName = string.lower(name) local lowerName = string.lower(name)
@@ -1966,12 +1987,12 @@ function pfUI.uf:RefreshUnit(unit, component)
break break
end end
end end
ai = ai + 1
end end
local debuffFilter = unit.config.selfdebuff == "1" and "PLAYER" or nil local debuffFilter = unit.config.selfdebuff == "1" and "HARMFUL|PLAYER" or "HARMFUL"
for i=1,16 do -- scan for custom debuffs n = ScanAuraSlots(unitstr, debuffFilter, auraSlots)
local name, icon, count, _, _, expirationTime = C_UnitAuras.UnitDebuff(unitstr, i, debuffFilter) for i=1,n do -- scan for custom debuffs
local name, icon, count, _, _, expirationTime = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
if name then if name then
local timeleft = expirationTime > 0 and (expirationTime - GetTime()) or nil local timeleft = expirationTime > 0 and (expirationTime - GetTime()) or nil
for _, filter in pairs(unit.indicator_custom) do for _, filter in pairs(unit.indicator_custom) do
@@ -2233,7 +2254,7 @@ function pfUI.uf:AddIcon(frame, pos, icon, timeleft, stacks, start, duration)
-- Check if parent frame has cooldown animation enabled -- Check if parent frame has cooldown animation enabled
local parent_cooldown_anim = frame.config and tonumber(frame.config.cooldown_anim) or 1 local parent_cooldown_anim = frame.config and tonumber(frame.config.cooldown_anim) or 1
if parent_cooldown_anim == 1 then if parent_cooldown_anim == 1 then
frame.icon[pos].cd = CreateFrame(COOLDOWN_FRAME_TYPE, nil, frame.icon[pos]) frame.icon[pos].cd = CreateFrame("Model", nil, frame.icon[pos])
else else
frame.icon[pos].cd = CreateFrame("Frame", nil, frame.icon[pos]) frame.icon[pos].cd = CreateFrame("Frame", nil, frame.icon[pos])
frame.icon[pos].cd.AdvanceTime = DoNothing frame.icon[pos].cd.AdvanceTime = DoNothing
-43
View File
@@ -1,43 +0,0 @@
-- load pfUI environment
setfenv(1, pfUI:GetEnvironment())
-- [[ Constants ]]--
EVENTS_MINIMAP_ZONE_UPDATE = {"PLAYER_ENTERING_WORLD", "MINIMAP_ZONE_CHANGED"}
MICRO_BUTTONS = {
'CharacterMicroButton', 'SpellbookMicroButton', 'TalentMicroButton',
'QuestLogMicroButton', 'SocialsMicroButton', 'WorldMapMicroButton',
'MainMenuMicroButton', 'HelpMicroButton',
}
NAMEPLATE_OBJECTORDER = { "border", "glow", "name", "level", "levelicon", "raidicon" }
NAMEPLATE_FRAMETYPE = "Button"
MINIMAP_TRACKING_FRAME = _G.MiniMapTrackingFrame
FRIENDS_NAME_LOCATION = "ButtonTextNameLocation"
COOLDOWN_FRAME_TYPE = "Model"
LOOT_BUTTON_FRAME_TYPE = "LootButton"
PLAYER_BUFF_START_ID = -1
ACTIONBAR_SECURE_TEMPLATE_BAR = nil
ACTIONBAR_SECURE_TEMPLATE_BUTTON = nil
--[[ Vanilla API Extensions ]]--
do -- RunMacroText
local obj = { ["GetText"] = function(self) return self.text end }
obj = setmetatable(obj, {__index = function(tab,key)
local value = function() return end
rawset(tab,key,value)
return value
end})
function RunMacroText(text)
obj.text = text
ChatEdit_ParseText(obj, 1)
end
end
-2358
View File
File diff suppressed because it is too large Load Diff
+2377
View File
File diff suppressed because it is too large Load Diff
+2991
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -72,7 +72,6 @@
<Include file="..\modules\totems.lua"/> <Include file="..\modules\totems.lua"/>
<Include file="..\modules\macrotweak.lua"/> <Include file="..\modules\macrotweak.lua"/>
<Include file="..\modules\macroicons.lua"/> <Include file="..\modules\macroicons.lua"/>
<Include file="..\modules\turtle-wow.lua"/>
<Include file="..\modules\superwow.lua"/> <Include file="..\modules\superwow.lua"/>
<Include file="..\modules\innervatecall.lua"/> <Include file="..\modules\innervatecall.lua"/>
<Include file="..\modules\nampower.lua"/> <Include file="..\modules\nampower.lua"/>
+1 -7
View File
@@ -35,12 +35,6 @@
<Include file="..\skins\blizzard\tooltips.lua"/> <Include file="..\skins\blizzard\tooltips.lua"/>
<Include file="..\skins\blizzard\tabard.lua"/> <Include file="..\skins\blizzard\tabard.lua"/>
<Include file="..\skins\blizzard\itemtext.lua"/> <Include file="..\skins\blizzard\itemtext.lua"/>
<Include file="..\skins\blizzard\lft.lua"/>
<Include file="..\skins\blizzard\turtle_shop.lua"/>
<!-- Turtle WoW -->
<Include file="..\skins\blizzard\barbershop.lua"/>
<Include file="..\skins\blizzard\transmog.lua"/>
<Include file="..\skins\blizzard\ebc.lua"/>
<!-- Turtle WoW skins live in init\turtle.xml (pfUI_Turtle.toc only). -->
</Ui> </Ui>
+1 -1
View File
@@ -1,3 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/">
<Include file="..\compat\vanilla.lua"/> <Include file="..\env\tables_stock.lua"/>
</Ui> </Ui>
+14
View File
@@ -0,0 +1,14 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<!-- Turtle WoW only: pulled in by pfUI_Turtle.toc, which ClassicAPI selects
when it detects a Turtle client. Everything in here targets frames that
only a Turtle client ever creates. -->
<Include file="..\env\tables_turtle.lua"/>
<Include file="..\skins\blizzard\lft.lua"/>
<Include file="..\skins\blizzard\turtle_shop.lua"/>
<Include file="..\skins\blizzard\barbershop.lua"/>
<Include file="..\skins\blizzard\transmog.lua"/>
<Include file="..\skins\blizzard\ebc.lua"/>
<Include file="..\modules\turtle-wow.lua"/>
</Ui>
+3 -3
View File
@@ -1016,7 +1016,7 @@ pfUI:RegisterModule("actionbar", function ()
local id = (bar-1)*12+button local id = (bar-1)*12+button
local exists = _G[button_name] and true or nil local exists = _G[button_name] and true or nil
local f = _G[button_name] or CreateFrame("Button", button_name, parent, ACTIONBAR_SECURE_TEMPLATE_BUTTON) local f = _G[button_name] or CreateFrame("Button", button_name, parent)
-- no button available, create a new one -- no button available, create a new one
if not exists then if not exists then
@@ -1042,7 +1042,7 @@ pfUI:RegisterModule("actionbar", function ()
f.slot = id f.slot = id
-- cooldown -- cooldown
f.cd = CreateFrame(COOLDOWN_FRAME_TYPE, f:GetName() .. "Cooldown", f, "CooldownFrameTemplate") f.cd = CreateFrame("Model", f:GetName() .. "Cooldown", f, "CooldownFrameTemplate")
f.cd.pfCooldownStyleAnimation = 1 f.cd.pfCooldownStyleAnimation = 1
f.cd.pfCooldownType = "NOGCD" f.cd.pfCooldownType = "NOGCD"
f.cd.pfCooldownSize = cd_size f.cd.pfCooldownSize = cd_size
@@ -1233,7 +1233,7 @@ pfUI:RegisterModule("actionbar", function ()
-- create frame -- create frame
local init = not bars[i] local init = not bars[i]
bars[i] = bars[i] or CreateFrame("Frame", "pfActionBar" .. barnames[i], UIParent, ACTIONBAR_SECURE_TEMPLATE_BAR) bars[i] = bars[i] or CreateFrame("Frame", "pfActionBar" .. barnames[i], UIParent)
bars[i]:SetID(i) bars[i]:SetID(i)
-- autohide -- autohide
+1 -1
View File
@@ -396,7 +396,7 @@ pfUI:RegisterModule("bags", function ()
if tpl == "BankItemButtonGenericTemplate" then if tpl == "BankItemButtonGenericTemplate" then
local bankslot = pfUI.bags[bag].slots[slot].frame local bankslot = pfUI.bags[bag].slots[slot].frame
local name = "pfBag" .. bag .. "item" .. slot .. "Cooldown" local name = "pfBag" .. bag .. "item" .. slot .. "Cooldown"
bankslot.cd = CreateFrame(COOLDOWN_FRAME_TYPE, name, bankslot, "CooldownFrameTemplate") bankslot.cd = CreateFrame("Model", name, bankslot, "CooldownFrameTemplate")
bankslot.cd:SetAllPoints(bankslot) bankslot.cd:SetAllPoints(bankslot)
bankslot.cd.pfCooldownStyleAnimation = 1 bankslot.cd.pfCooldownStyleAnimation = 1
bankslot.cd.pfCooldownType = "ALL" bankslot.cd.pfCooldownType = "ALL"
+16 -1
View File
@@ -7,6 +7,15 @@ pfUI:RegisterModule("buff", function ()
local br, bg, bb, ba = GetStringColor(pfUI_config.appearance.border.color) local br, bg, bb, ba = GetStringColor(pfUI_config.appearance.border.color)
-- Player aura slot ids, enumerated once per refresh pass (ScanPlayerAuraSlots)
-- and read per button by its aura index: one GetAuraSlots walk per range
-- instead of a by-index walk per button.
local helpfulSlots, harmfulSlots = {}, {}
local function ScanPlayerAuraSlots()
ScanAuraSlots("player", "HELPFUL", helpfulSlots, 32)
ScanAuraSlots("player", "HARMFUL", harmfulSlots, 16)
end
local function RefreshBuffButton(buff) local function RefreshBuffButton(buff)
if buff.btype == "HELPFUL" then if buff.btype == "HELPFUL" then
if C.buffs.separateweapons == "1" then if C.buffs.separateweapons == "1" then
@@ -23,7 +32,8 @@ pfUI:RegisterModule("buff", function ()
CreateBackdropShadow(buff) CreateBackdropShadow(buff)
end end
local name, icon, count, dispelType, _, expirationTime, _, _, _, spellId = C_UnitAuras.UnitAura("player", buff.id, buff.btype) local slots = buff.btype == "HELPFUL" and helpfulSlots or harmfulSlots
local name, icon, count, dispelType, _, expirationTime, _, _, _, spellId = C_UnitAuras.UnitAuraBySlot("player", slots[buff.id])
--detect weapon buffs --detect weapon buffs
if buff.btype == "HELPFUL" and ((C.buffs.separateweapons == "0" and buff.gid <= pfUI.buff.wepbuffs.count) or (pfUI.buff.wepbuffs.count > 0 and buff.weapon ~= nil)) then if buff.btype == "HELPFUL" and ((C.buffs.separateweapons == "0" and buff.gid <= pfUI.buff.wepbuffs.count) or (pfUI.buff.wepbuffs.count > 0 and buff.weapon ~= nil)) then
@@ -166,6 +176,8 @@ pfUI:RegisterModule("buff", function ()
pfUI.buff.wepbuffs.count = 0 pfUI.buff.wepbuffs.count = 0
end end
ScanPlayerAuraSlots()
for i=1,32 do for i=1,32 do
RefreshBuffButton(pfUI.buff.buffs.buttons[i]) RefreshBuffButton(pfUI.buff.buffs.buttons[i])
end end
@@ -246,6 +258,9 @@ pfUI:RegisterModule("buff", function ()
end end
end) end)
-- CreateBuffButton refreshes each new button from the slot buffers
ScanPlayerAuraSlots()
-- Weapon Buffs -- Weapon Buffs
pfUI.buff.wepbuffs = CreateFrame("Frame", "pfWepBuffFrame", UIParent) pfUI.buff.wepbuffs = CreateFrame("Frame", "pfWepBuffFrame", UIParent)
pfUI.buff.wepbuffs.count = 0 pfUI.buff.wepbuffs.count = 0
+28 -10
View File
@@ -73,9 +73,16 @@ pfUI:RegisterModule("buffwatch", function ()
return anchor return anchor
end end
local function GetBuffData(unit, id, type, selfdebuff) -- reusable GetAuraSlots buffer, filled once per RefreshBuffBarFrame
local filter = (selfdebuff and type == "HARMFUL") and "HARMFUL|PLAYER" or type local auraSlots = {}
local name, icon, count, dispelType, _, expirationTime = C_UnitAuras.UnitAura(unit, id, filter)
-- Separate buffer for the tooltip handler: OnEnter can fire while a refresh
-- is showing/hiding bars under the cursor, so it must not share the above.
local tooltipSlots = {}
-- Reads one aura by the slot id GetAuraSlots returned (nil slot -> nil).
local function GetBuffData(unit, slot)
local name, icon, count, dispelType, _, expirationTime = C_UnitAuras.UnitAuraBySlot(unit, slot)
if not name then return end if not name then return end
local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0 local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0
return remaining, icon, name, count, dispelType return remaining, icon, name, count, dispelType
@@ -113,17 +120,22 @@ pfUI:RegisterModule("buffwatch", function ()
GameTooltip:SetUnitAura("player", this.id, this.type) GameTooltip:SetUnitAura("player", this.id, this.type)
elseif this.type == "HARMFUL" then elseif this.type == "HARMFUL" then
-- selfdebuff filters the displayed list to player-cast harmful auras, but -- selfdebuff filters the displayed list to player-cast harmful auras, but
-- SetUnitAura's index has to be into the engine's full HARMFUL list. Look -- SetUnitAura's index has to be into the unfiltered HARMFUL list. Look up
-- up the displayed aura via the PLAYER filter, then scan engine slots for -- the displayed aura via the PLAYER filter, then find its position in the
-- one whose name + sourceGUID match. -- unfiltered list by name + sourceGUID.
--
-- The unfiltered list is NOT capped at 16: once a unit's 16 debuff slots
-- are full the server parks further debuffs in buff slots, and
-- C_UnitAuras reports those as harmful too. So enumerate what it has.
local config = this.parent and this.parent.config local config = this.parent and this.parent.config
if config and config.selfdebuff == "1" then if config and config.selfdebuff == "1" then
local ownAura = C_UnitAuras.GetAuraDataByIndex(this.unit, this.id, "HARMFUL|PLAYER") local ownAura = C_UnitAuras.GetAuraDataByIndex(this.unit, this.id, "HARMFUL|PLAYER")
if ownAura then if ownAura then
for gameSlot = 1, 16 do local n = ScanAuraSlots(this.unit, "HARMFUL", tooltipSlots)
local check = C_UnitAuras.GetDebuffDataByIndex(this.unit, gameSlot) for i = 1, n do
local check = C_UnitAuras.GetAuraDataBySlot(this.unit, tooltipSlots[i])
if check and check.name == ownAura.name and check.sourceGUID == ownAura.sourceGUID then if check and check.name == ownAura.name and check.sourceGUID == ownAura.sourceGUID then
GameTooltip:SetUnitAura(this.unit, gameSlot, "HARMFUL") GameTooltip:SetUnitAura(this.unit, i, "HARMFUL")
break break
end end
end end
@@ -234,9 +246,15 @@ pfUI:RegisterModule("buffwatch", function ()
local function RefreshBuffBarFrame(frame) local function RefreshBuffBarFrame(frame)
-- reinitialize all active buffs -- reinitialize all active buffs
local selfdebuff = frame.config.selfdebuff == "1" local selfdebuff = frame.config.selfdebuff == "1"
local filter = (selfdebuff and frame.type == "HARMFUL") and "HARMFUL|PLAYER" or frame.type
-- one GetAuraSlots enumeration per refresh instead of a by-index walk per
-- bar; the i-th slot is the i-th aura of the filtered list, so `i` stays
-- the index the tooltip / cancel handlers pass to the by-index API
ScanAuraSlots(frame.unit, filter, auraSlots, 32)
for i=1,32 do for i=1,32 do
local timeleft, texture, name, stacks, dtype = GetBuffData(frame.unit, i, frame.type, selfdebuff) local timeleft, texture, name, stacks, dtype = GetBuffData(frame.unit, auraSlots[i])
timeleft = timeleft or 0 timeleft = timeleft or 0
if texture and name and name ~= "" and BuffIsVisible(frame.config, name) then if texture and name and name ~= "" and BuffIsVisible(frame.config, name) then
+97 -23
View File
@@ -63,6 +63,23 @@ pfUI:RegisterModule("chat", function ()
return pfUI_cache["chathistory"][realm][player][id] return pfUI_cache["chathistory"][realm][player][id]
end end
-- [ Chat Panel Colors ]
-- The panels normally inherit pfUI's global appearance theme; custom colors let chat
-- deviate from it. CreateBackdrop is re-run first to restore the theme, so toggling
-- custom colors back off doesn't leave the previous override behind.
local function ApplyPanelColors(panel)
if not panel then return end
CreateBackdrop(panel, default_border, nil, .8)
if C.chat.global.custombg ~= "1" then return end
local r, g, b, a = GetStringColor(C.chat.global.background)
panel.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border)
panel.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end
pfUI.chat = CreateFrame("Frame",nil,UIParent) pfUI.chat = CreateFrame("Frame",nil,UIParent)
pfUI.chat.left = CreateFrame("Frame", "pfChatLeft", UIParent) pfUI.chat.left = CreateFrame("Frame", "pfChatLeft", UIParent)
@@ -76,19 +93,11 @@ pfUI:RegisterModule("chat", function ()
pfUI.chat.left:SetPoint("BOTTOMLEFT", 2*default_border,2*default_border) pfUI.chat.left:SetPoint("BOTTOMLEFT", 2*default_border,2*default_border)
pfUI.chat.left:SetScript("OnShow", function() pfUI.chat:RefreshChat() end) pfUI.chat.left:SetScript("OnShow", function() pfUI.chat:RefreshChat() end)
UpdateMovable(pfUI.chat.left) UpdateMovable(pfUI.chat.left)
CreateBackdrop(pfUI.chat.left, default_border, nil, .8) ApplyPanelColors(pfUI.chat.left)
if C.chat.global.frameshadow == "1" then if C.chat.global.frameshadow == "1" then
CreateBackdropShadow(pfUI.chat.left) CreateBackdropShadow(pfUI.chat.left)
end end
if C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background)
pfUI.chat.left.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border)
pfUI.chat.left.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end
pfUI.chat.left.panelTop = CreateFrame("Frame", "leftChatPanelTop", pfUI.chat.left) pfUI.chat.left.panelTop = CreateFrame("Frame", "leftChatPanelTop", pfUI.chat.left)
pfUI.chat.left.panelTop:ClearAllPoints() pfUI.chat.left.panelTop:ClearAllPoints()
pfUI.chat.left.panelTop:SetHeight(C.global.font_size+default_border*2) pfUI.chat.left.panelTop:SetHeight(C.global.font_size+default_border*2)
@@ -251,19 +260,11 @@ pfUI:RegisterModule("chat", function ()
pfUI.chat.right:SetPoint("BOTTOMRIGHT", -2*default_border,2*default_border) pfUI.chat.right:SetPoint("BOTTOMRIGHT", -2*default_border,2*default_border)
pfUI.chat.right:SetScript("OnShow", function() pfUI.chat:RefreshChat() end) pfUI.chat.right:SetScript("OnShow", function() pfUI.chat:RefreshChat() end)
UpdateMovable(pfUI.chat.right) UpdateMovable(pfUI.chat.right)
CreateBackdrop(pfUI.chat.right, default_border, nil, .8) ApplyPanelColors(pfUI.chat.right)
if C.chat.global.frameshadow == "1" then if C.chat.global.frameshadow == "1" then
CreateBackdropShadow(pfUI.chat.right) CreateBackdropShadow(pfUI.chat.right)
end end
if C.chat.global.custombg == "1" then
local r, g, b, a = GetStringColor(C.chat.global.background)
pfUI.chat.right.backdrop:SetBackdropColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
local r, g, b, a = GetStringColor(C.chat.global.border)
pfUI.chat.right.backdrop:SetBackdropBorderColor(tonumber(r), tonumber(g), tonumber(b), tonumber(a))
end
pfUI.chat.right.panelTop = CreateFrame("Frame", "rightChatPanelTop", pfUI.chat.right) pfUI.chat.right.panelTop = CreateFrame("Frame", "rightChatPanelTop", pfUI.chat.right)
pfUI.chat.right.panelTop:ClearAllPoints() pfUI.chat.right.panelTop:ClearAllPoints()
pfUI.chat.right.panelTop:SetHeight(C.global.font_size+default_border*2) pfUI.chat.right.panelTop:SetHeight(C.global.font_size+default_border*2)
@@ -296,6 +297,68 @@ pfUI:RegisterModule("chat", function ()
end end
end end
-- [ Chat Background Alpha ]
-- Blizzard's per-window transparency slider drives FCF_SetWindowAlpha, which only
-- touches the ChatFrame*Background textures that pfUI hides on docked frames. Mirror
-- the window's stored alpha onto the visible pfUI backdrop so the native slider
-- controls it directly.
local function ApplyChatBackgroundAlpha(panel, frame)
if not (panel and panel.backdrop and frame) then return end
local _, _, _, _, _, alpha = GetChatWindowInfo(frame:GetID())
alpha = tonumber(alpha)
if not alpha then return end
local r, g, b = panel.backdrop:GetBackdropColor()
panel.backdrop:SetBackdropColor(r, g, b, alpha)
end
function pfUI.chat:RefreshBackgroundAlpha()
-- Custom colors own the alpha. C.chat.global.background carries its own alpha, is
-- set by profiles and is shared with the meter skins, so the native slider must not
-- overwrite it -- doing so reverted the configured opacity on every refresh. The
-- slider only drives the panel when the user hasn't opted into pfUI's chat colors.
if C.chat.global.custombg == "1" then return end
-- left panel follows the currently selected docked tab
local selected = SELECTED_CHAT_FRAME
if not (selected and selected:GetParent() == pfUI.chat.left) then
selected = ChatFrame1
end
ApplyChatBackgroundAlpha(pfUI.chat.left, selected)
if C.chat.right.enable == "1" then
ApplyChatBackgroundAlpha(pfUI.chat.right, ChatFrame3)
end
end
-- live config apply, resolved by the gui as U["chat"]. Lets the color pickers
-- take effect on the spot instead of waiting for a /reload.
function pfUI.chat:UpdateConfig()
ApplyPanelColors(pfUI.chat.left)
ApplyPanelColors(pfUI.chat.right)
pfUI.chat:RefreshBackgroundAlpha()
end
function pfUI.chat:MigrateBackgroundAlpha()
-- Runs once per character. The previous SetupPositions default stored a hard 0 window
-- alpha, which now renders the pfUI backdrop fully transparent. Restore the historical
-- 0.8 look for any pfUI-managed window still sitting at 0. Only existing installs that
-- already ran chat setup carry that legacy 0; fresh installs get 0.8 from SetupPositions.
if pfUI_init.chatbgalpha then return end
if not pfUI_init["chat_position"] then return end
pfUI_init.chatbgalpha = true
local frames = { ChatFrame1, ChatFrame2 }
if C.chat.right.enable == "1" then table.insert(frames, ChatFrame3) end
for _, frame in ipairs(frames) do
local _, _, _, _, _, alpha = GetChatWindowInfo(frame:GetID())
alpha = tonumber(alpha)
if alpha and alpha <= 0 then
FCF_SetWindowAlpha(frame, 0.8)
end
end
end
function pfUI.chat:RefreshChat() function pfUI.chat:RefreshChat()
local panelheight = C.global.font_size*1.5 + default_border*2 + 2 local panelheight = C.global.font_size*1.5 + default_border*2 + 2
@@ -447,9 +510,13 @@ pfUI:RegisterModule("chat", function ()
for index, value in pairs(DOCKED_CHAT_FRAMES) do for index, value in pairs(DOCKED_CHAT_FRAMES) do
FCF_UpdateButtonSide(value) FCF_UpdateButtonSide(value)
end end
pfUI.chat:RefreshBackgroundAlpha()
end end
hooksecurefunc("FCF_SaveDock", pfUI.chat.RefreshChat) hooksecurefunc("FCF_SaveDock", pfUI.chat.RefreshChat)
hooksecurefunc("FCF_SetWindowAlpha", function() pfUI.chat:RefreshBackgroundAlpha() end)
hooksecurefunc("FCF_SelectDockFrame", function() pfUI.chat:RefreshBackgroundAlpha() end)
if C.chat.global.tabmouse == "1" then if C.chat.global.tabmouse == "1" then
pfUI.chat.mouseovertab = CreateFrame("Frame") pfUI.chat.mouseovertab = CreateFrame("Frame")
@@ -500,7 +567,7 @@ pfUI:RegisterModule("chat", function ()
FCF_SetLocked(ChatFrame1, 1) FCF_SetLocked(ChatFrame1, 1)
FCF_SetWindowName(ChatFrame1, GENERAL) FCF_SetWindowName(ChatFrame1, GENERAL)
FCF_SetWindowColor(ChatFrame1, 0, 0, 0) FCF_SetWindowColor(ChatFrame1, 0, 0, 0)
FCF_SetWindowAlpha(ChatFrame1, 0) FCF_SetWindowAlpha(ChatFrame1, 0.8)
FCF_SetChatWindowFontSize(ChatFrame1, 12) FCF_SetChatWindowFontSize(ChatFrame1, 12)
ChatFrame1:SetUserPlaced(1) ChatFrame1:SetUserPlaced(1)
@@ -508,7 +575,7 @@ pfUI:RegisterModule("chat", function ()
FCF_SetLocked(ChatFrame2, 1) FCF_SetLocked(ChatFrame2, 1)
FCF_SetWindowName(ChatFrame2, COMBAT_LOG) FCF_SetWindowName(ChatFrame2, COMBAT_LOG)
FCF_SetWindowColor(ChatFrame2, 0, 0, 0) FCF_SetWindowColor(ChatFrame2, 0, 0, 0)
FCF_SetWindowAlpha(ChatFrame2, 0) FCF_SetWindowAlpha(ChatFrame2, 0.8)
FCF_SetChatWindowFontSize(ChatFrame2, 12) FCF_SetChatWindowFontSize(ChatFrame2, 12)
ChatFrame2:SetUserPlaced(1) ChatFrame2:SetUserPlaced(1)
@@ -518,7 +585,7 @@ pfUI:RegisterModule("chat", function ()
FCF_SetLocked(ChatFrame3, 1) FCF_SetLocked(ChatFrame3, 1)
FCF_SetWindowName(ChatFrame3, T["Loot & Spam"]) FCF_SetWindowName(ChatFrame3, T["Loot & Spam"])
FCF_SetWindowColor(ChatFrame3, 0, 0, 0) FCF_SetWindowColor(ChatFrame3, 0, 0, 0)
FCF_SetWindowAlpha(ChatFrame3, 0) FCF_SetWindowAlpha(ChatFrame3, 0.8)
FCF_SetChatWindowFontSize(ChatFrame3, 12) FCF_SetChatWindowFontSize(ChatFrame3, 12)
FCF_UnDockFrame(ChatFrame3) FCF_UnDockFrame(ChatFrame3)
FCF_SetTabPosition(ChatFrame3, 0) FCF_SetTabPosition(ChatFrame3, 0)
@@ -566,6 +633,9 @@ pfUI:RegisterModule("chat", function ()
end end
pfUI.chat:SetScript("OnEvent", function() pfUI.chat:SetScript("OnEvent", function()
-- restore legacy chat windows stuck at 0 alpha before anything reads it
pfUI.chat:MigrateBackgroundAlpha()
-- set the default chat -- set the default chat
FCF_SelectDockFrame(SELECTED_CHAT_FRAME) FCF_SelectDockFrame(SELECTED_CHAT_FRAME)
@@ -757,7 +827,7 @@ pfUI:RegisterModule("chat", function ()
local real, _ = strsplit(":", name) local real, _ = strsplit(":", name)
local color = unknowncolorhex local color = unknowncolorhex
local match = false local match = false
local _, class = C_PlayerCache.GetPlayerInfoByName(real) local _, class, _, raceKey, sex = C_PlayerCache.GetPlayerInfoByName(real)
-- local guid = GetCurrentChatGUID() -- local guid = GetCurrentChatGUID()
-- if guid then -- if guid then
-- _, class = GetPlayerInfoByGUID(guid) -- _, class = GetPlayerInfoByGUID(guid)
@@ -775,8 +845,12 @@ pfUI:RegisterModule("chat", function ()
end end
if C.chat.text.tintunknown == "1" or match then if C.chat.text.tintunknown == "1" or match then
local icon = ""
if match and C.chat.text.playericons == "1" then
icon = GetFactionIcon(raceKey) .. GetRaceIcon(raceKey, sex)
end
text = string.gsub(text, "|Hplayer:"..name.."|h%["..real.."%]|h(.-:-)", text = string.gsub(text, "|Hplayer:"..name.."|h%["..real.."%]|h(.-:-)",
left..color.."|Hplayer:"..name.."|h" .. color .. real .. "|h|r"..right.."%1") left..icon..color.."|Hplayer:"..name.."|h" .. color .. real .. "|h|r"..right.."%1")
end end
end end
end end
+4 -3
View File
@@ -2867,6 +2867,7 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Generate Playerlinks"], C.chat.text, "playerlinks", "checkbox") CreateConfig(nil, T["Generate Playerlinks"], C.chat.text, "playerlinks", "checkbox")
CreateConfig(nil, T["Enable URL Detection"], C.chat.text, "detecturl", "checkbox") CreateConfig(nil, T["Enable URL Detection"], C.chat.text, "detecturl", "checkbox")
CreateConfig(nil, T["Enable Class Colors"], C.chat.text, "classcolor", "checkbox") CreateConfig(nil, T["Enable Class Colors"], C.chat.text, "classcolor", "checkbox")
CreateConfig(nil, T["Show Faction & Race Icons"] .. " " .. GetPlayerRaceIcons(), C.chat.text, "playericons", "checkbox")
CreateConfig(nil, T["Enable Player Levels"], C.chat.text, "playerlevel", "checkbox") CreateConfig(nil, T["Enable Player Levels"], C.chat.text, "playerlevel", "checkbox")
CreateConfig(nil, T["Who Search Unknown Classes (|cffffaaaaExperimental|r)"], C.chat.text, "whosearchunknown", "checkbox") CreateConfig(nil, T["Who Search Unknown Classes (|cffffaaaaExperimental|r)"], C.chat.text, "whosearchunknown", "checkbox")
CreateConfig(nil, T["Colorize Unknown Classes"], C.chat.text, "tintunknown", "checkbox") CreateConfig(nil, T["Colorize Unknown Classes"], C.chat.text, "tintunknown", "checkbox")
@@ -2880,9 +2881,9 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Only Show Chat Dock On Mouseover"], C.chat.global, "tabmouse", "checkbox") CreateConfig(nil, T["Only Show Chat Dock On Mouseover"], C.chat.global, "tabmouse", "checkbox")
CreateConfig(nil, T["Enable Chat Tab Flashing"], C.chat.global, "chatflash", "checkbox") CreateConfig(nil, T["Enable Chat Tab Flashing"], C.chat.global, "chatflash", "checkbox")
CreateConfig(nil, T["Enable Frame Shadow"], C.chat.global, "frameshadow", "checkbox") CreateConfig(nil, T["Enable Frame Shadow"], C.chat.global, "frameshadow", "checkbox")
CreateConfig(nil, T["Enable Custom Colors"], C.chat.global, "custombg", "checkbox") CreateConfig(U["chat"], T["Enable Custom Colors"], C.chat.global, "custombg", "checkbox")
CreateConfig(nil, T["Chat Background Color"], C.chat.global, "background", "color") CreateConfig(U["chat"], T["Chat Background Color"], C.chat.global, "background", "color")
CreateConfig(nil, T["Chat Border Color"], C.chat.global, "border", "color") CreateConfig(U["chat"], T["Chat Border Color"], C.chat.global, "border", "color")
CreateConfig(nil, T["Enable Custom Incoming Whispers Layout"], C.chat.global, "whispermod", "checkbox") CreateConfig(nil, T["Enable Custom Incoming Whispers Layout"], C.chat.global, "whispermod", "checkbox")
CreateConfig(nil, T["Incoming Whispers Color"], C.chat.global, "whisper", "color") CreateConfig(nil, T["Incoming Whispers Color"], C.chat.global, "whisper", "color")
CreateConfig(nil, T["Enable Sticky Chat"], C.chat.global, "sticky", "checkbox") CreateConfig(nil, T["Enable Sticky Chat"], C.chat.global, "sticky", "checkbox")
+1 -1
View File
@@ -511,7 +511,7 @@ pfUI:RegisterModule("loot", function ()
end end
function pfUI.loot:CreateSlot(id) function pfUI.loot:CreateSlot(id)
local frame = CreateFrame(LOOT_BUTTON_FRAME_TYPE, 'pfLootButton'..id, pfUI.loot) local frame = CreateFrame("LootButton", 'pfLootButton'..id, pfUI.loot)
frame:RegisterForClicks('LeftButtonUp', 'RightButtonUp') frame:RegisterForClicks('LeftButtonUp', 'RightButtonUp')
frame:SetPoint("LEFT", border*2, 0) frame:SetPoint("LEFT", border*2, 0)
frame:SetPoint("RIGHT", -border*2, 0) frame:SetPoint("RIGHT", -border*2, 0)
+45 -44
View File
@@ -116,6 +116,7 @@ pfUI:RegisterModule("nameplates", function ()
-- Reusable per-plate debuff display buffer (avoid GC churn from per-call table creation) -- Reusable per-plate debuff display buffer (avoid GC churn from per-call table creation)
local debuffDisplayBuf = {} -- [i] = { effect, texture, stacks, dtype, duration, timeleft } local debuffDisplayBuf = {} -- [i] = { effect, texture, stacks, dtype, duration, timeleft }
for i = 1, 16 do debuffDisplayBuf[i] = {} end for i = 1, 16 do debuffDisplayBuf[i] = {} end
local auraSlots = {} -- reusable GetAuraSlots buffer for the per-plate aura scan
local threatMemory = {} -- guid -> true if mob had player targeted local threatMemory = {} -- guid -> true if mob had player targeted
-- local debuffSeen = {} -- reusable table for debuff tracking (avoid GC churn) -- local debuffSeen = {} -- reusable table for debuff tracking (avoid GC churn)
@@ -296,18 +297,23 @@ pfUI:RegisterModule("nameplates", function ()
return plate.creatureType return plate.creatureType
end end
-- Totem icon, read straight from the game: -- Totem icon: UnitCreatedBySpell returns the totem-drop spell, whose icon IS
-- * Passive totems self-cast their provided buff, so they carry exactly one -- the totem's icon. It's a broadcast descriptor field the client has for every
-- aura whose icon IS the totem's icon (Totem::Summon TOTEM_PASSIVE). -- summoned unit in range, so it resolves immediately for passive and active
-- * Active totems (Searing/Magma/Fire Nova) cast at enemies and hold no -- totems alike -- no self-aura read or attack-cast capture needed.
-- self-aura, so their icon arrives via UNIT_SPELLCAST_SUCCEEDED (cached --
-- into plate.totemIcon by the event handler); nil here until then. -- Re-read the spell every call rather than caching the icon outright: a shaman
-- can swap the totem in place (same unit, new drop spell) with no plate re-add
-- to invalidate a cache, so key the cached texture on the spell id and refresh
-- it only when the spell changes.
local function TotemPlate(plate) local function TotemPlate(plate)
if C.nameplates.totemicons ~= "1" then return nil end if C.nameplates.totemicons ~= "1" then return nil end
if CreatureType(plate) ~= 11 then return nil end if CreatureType(plate) ~= 11 then return nil end
if plate.totemIcon then return plate.totemIcon end local spellId = UnitCreatedBySpell(plate.cachedGuid)
local aura = C_UnitAuras.GetBuffDataByIndex(plate.cachedGuid, 1) if spellId ~= plate.totemSpell then
if aura then plate.totemIcon = aura.icon end plate.totemSpell = spellId
plate.totemIcon = spellId and C_Spell.GetSpellTexture(spellId) or nil
end
return plate.totemIcon return plate.totemIcon
end end
@@ -427,7 +433,7 @@ pfUI:RegisterModule("nameplates", function ()
plate.debuffs[index].cd.SetSequenceTime = DoNothing plate.debuffs[index].cd.SetSequenceTime = DoNothing
else else
-- Use CooldownFrameTemplate for animation -- Use CooldownFrameTemplate for animation
plate.debuffs[index].cd = CreateFrame(COOLDOWN_FRAME_TYPE, plate.platename.."Debuff"..index.."Cooldown", plate.debuffs[index], "CooldownFrameTemplate") plate.debuffs[index].cd = CreateFrame("Model", plate.platename.."Debuff"..index.."Cooldown", plate.debuffs[index], "CooldownFrameTemplate")
plate.debuffs[index].cd:SetAllPoints(plate.debuffs[index]) plate.debuffs[index].cd:SetAllPoints(plate.debuffs[index])
plate.debuffs[index].cd:SetFrameLevel(6) plate.debuffs[index].cd:SetFrameLevel(6)
end end
@@ -499,7 +505,6 @@ nameplates:RegisterEvent("UNIT_SPELLCAST_START")
nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
nameplates:RegisterEvent("UNIT_SPELLCAST_STOP") nameplates:RegisterEvent("UNIT_SPELLCAST_STOP")
nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") nameplates:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
nameplates:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
nameplates:RegisterEvent("PLAYER_GUILD_UPDATE") nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
nameplates:SetScript("OnEvent", function() nameplates:SetScript("OnEvent", function()
@@ -588,6 +593,7 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
plate.nameplate.unit = arg1 plate.nameplate.unit = arg1
plate.nameplate.creatureType = nil -- recompute for the new unit plate.nameplate.creatureType = nil -- recompute for the new unit
plate.nameplate.totemIcon = nil plate.nameplate.totemIcon = nil
plate.nameplate.totemSpell = nil
if guid then if guid then
plateByGuid[guid] = plate.nameplate plateByGuid[guid] = plate.nameplate
-- Seed: the unit may already be mid-cast (its UNIT_SPELLCAST_START -- Seed: the unit may already be mid-cast (its UNIT_SPELLCAST_START
@@ -665,22 +671,6 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
end end
end end
elseif event == "UNIT_SPELLCAST_SUCCEEDED" then
-- Active totems (Searing/Magma/Fire Nova) carry no self-aura, so their
-- attack cast is the only icon source. Capture it once per totem, gated on
-- creature type so a normal caster's spell never styles it as a totem.
if arg1 and strfind(arg1, "^nameplate") then
local guid = UnitGUID(arg1)
local plate = guid and plateByGuid[guid]
if plate and not plate.totemIcon and arg3 and CreatureType(plate) == 11 then
local tex = C_Spell.GetSpellTexture(arg3)
if tex then
plate.totemIcon = tex
plate.castUpdate = true -- re-render now so the icon shows
end
end
end
elseif event == "UNIT_AURA" then elseif event == "UNIT_AURA" then
-- ClassicAPI: fires with arg1 == "nameplateN" when a unit's aura set -- ClassicAPI: fires with arg1 == "nameplateN" when a unit's aura set
-- changes (add/remove/modify). Flag the matching plate so OnUpdate does a -- changes (add/remove/modify). Flag the matching plate so OnUpdate does a
@@ -781,6 +771,8 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
DisableObject(nameplate.original.healthbar) DisableObject(nameplate.original.healthbar)
DisableObject(nameplate.original.castbar) DisableObject(nameplate.original.castbar)
local NAMEPLATE_OBJECTORDER = { "border", "glow", "name", "level", "levelicon", "raidicon" }
for i, object in pairs({parent:GetRegions()}) do for i, object in pairs({parent:GetRegions()}) do
if NAMEPLATE_OBJECTORDER[i] and NAMEPLATE_OBJECTORDER[i] == "raidicon" then if NAMEPLATE_OBJECTORDER[i] and NAMEPLATE_OBJECTORDER[i] == "raidicon" then
nameplate[NAMEPLATE_OBJECTORDER[i]] = object nameplate[NAMEPLATE_OBJECTORDER[i]] = object
@@ -1039,13 +1031,29 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
local mouseover = plate.cachedGuid and plate.cachedGuid == frameState.mouseoverGuid or nil local mouseover = plate.cachedGuid and plate.cachedGuid == frameState.mouseoverGuid or nil
local unitstr = target and "target" or mouseover and "mouseover" or plate.cachedGuid or nil local unitstr = target and "target" or mouseover and "mouseover" or plate.cachedGuid or nil
-- target event sometimes fires too quickly, where nameplate identifiers are not
-- yet updated. So while being inside this event, we cannot trust the unitstr.
if event == "PLAYER_TARGET_CHANGED" then unitstr = nil end
-- remove unitstr when it doesn't resolve to this plate's unit (stale istarget,
-- stale mouseover guid or a despawned unit). Must run before the cache fills
-- below -- an unrelated unitstr would poison cache.player/minion with the
-- *other* unit's answer, and the nil-gate would then never recompute it.
if unitstr and UnitName(unitstr) ~= name then unitstr = nil end
-- resolve player vs npc from plate's own unit so libunitscan can't return -- resolve player vs npc from plate's own unit so libunitscan can't return
-- a player record for an NPC sharing the same name (e.g. Chromie). Stored -- a player record for an NPC sharing the same name (e.g. Chromie). Stored
-- as true/false/nil so it doubles as the GetUnitInfo hint. -- as true/false/nil so it doubles as the GetUnitInfo hint.
if plate.cache.player == nil and unitstr then if plate.cache.player == nil and unitstr then
plate.cache.player = UnitIsPlayer(unitstr) and true or false plate.cache.player = UnitIsPlayer(unitstr) and true or false
end end
local class, ulevel, elite, player, guild = GetUnitInfo(name, true, plate.cache.player) if plate.cache.minion == nil and unitstr then
plate.cache.minion = UnitIsMinion(unitstr) and true or false
end
local class, ulevel, elite, player, guild
if not plate.cache.minion then
class, ulevel, elite, player, guild = GetUnitInfo(name, true, plate.cache.player)
end
if plate.cache.player ~= nil then player = plate.cache.player or nil end if plate.cache.player ~= nil then player = plate.cache.player or nil end
-- Use database level ONLY if current level is ?? (fixes ?? after reload, but doesn't override visible levels) -- Use database level ONLY if current level is ?? (fixes ?? after reload, but doesn't override visible levels)
@@ -1065,18 +1073,11 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
if player and unittype == "ENEMY_NPC" then unittype = "ENEMY_PLAYER" end if player and unittype == "ENEMY_NPC" then unittype = "ENEMY_PLAYER" end
if player and unittype == "FRIENDLY_NPC" then unittype = "FRIENDLY_PLAYER" end if player and unittype == "FRIENDLY_NPC" then unittype = "FRIENDLY_PLAYER" end
elite = plate.original.levelicon:IsShown() and not player and "boss" or elite elite = plate.original.levelicon:IsShown() and not player and "boss" or elite
if not class then plate.wait_for_scan = true end if not class and not plate.cache.minion then plate.wait_for_scan = true end
-- skip data updates on invisible frames -- skip data updates on invisible frames
if not visible then return end if not visible then return end
-- target event sometimes fires too quickly, where nameplate identifiers are not
-- yet updated. So while being inside this event, we cannot trust the unitstr.
if event == "PLAYER_TARGET_CHANGED" then unitstr = nil end
-- remove unitstr on unit name mismatch
if unitstr and UnitName(unitstr) ~= name then unitstr = nil end
-- always make sure to keep plate visible -- always make sure to keep plate visible
plate:Show() plate:Show()
@@ -1110,7 +1111,7 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
local TotemIcon = TotemPlate(plate) local TotemIcon = TotemPlate(plate)
if TotemIcon then if TotemIcon then
-- icon resolved from the totem's aura / attack cast (already a full path) -- icon resolved from the totem-drop spell (already a full path)
plate.totem.icon:SetTexture(TotemIcon) plate.totem.icon:SetTexture(TotemIcon)
plate.glow:Hide() plate.glow:Hide()
@@ -1314,11 +1315,12 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
if unitstr then if unitstr then
local filter = cfg.owndebuffs and "HARMFUL|PLAYER" or "HARMFUL" local filter = cfg.owndebuffs and "HARMFUL|PLAYER" or "HARMFUL"
local now = GetTime() local now = GetTime()
-- positional UnitAura writes straight into the reusable buffer, so the -- one GetAuraSlots enumeration, then positional by-slot reads straight
-- per-plate scan allocates nothing (no per-aura table, no result array) -- into the reusable buffer: the per-plate scan allocates nothing (no
local i = 1 -- per-aura table, no result array) and walks the aura array once
while debuffCount < 16 do local n = ScanAuraSlots(unitstr, filter, auraSlots, 16)
local aname, icon, count, dispelType, duration, expirationTime = C_UnitAuras.UnitAura(unitstr, i, filter) for i = 1, n do
local aname, icon, count, dispelType, duration, expirationTime = C_UnitAuras.UnitAuraBySlot(unitstr, auraSlots[i])
if not aname then break end if not aname then break end
debuffCount = debuffCount + 1 debuffCount = debuffCount + 1
local b = debuffDisplayBuf[debuffCount] local b = debuffDisplayBuf[debuffCount]
@@ -1328,7 +1330,6 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
b.dtype = dispelType b.dtype = dispelType
b.duration = duration b.duration = duration
b.timeleft = (expirationTime and expirationTime > 0) and (expirationTime - now) or nil b.timeleft = (expirationTime and expirationTime > 0) and (expirationTime - now) or nil
i = i + 1
end end
end end
for i = 1, 16 do for i = 1, 16 do
@@ -1551,7 +1552,7 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE")
-- otherwise an NPC sharing a name with a known player flips wait_for_scan -- otherwise an NPC sharing a name with a known player flips wait_for_scan
-- off here, then OnDataChanged re-sets it, every frame until the mob scan -- off here, then OnDataChanged re-sets it, every frame until the mob scan
-- lands. -- lands.
if nameplate.wait_for_scan and GetUnitInfo(name, true, nameplate.cache.player) then if nameplate.wait_for_scan and not nameplate.cache.minion and GetUnitInfo(name, true, nameplate.cache.player) then
nameplate.wait_for_scan = nil nameplate.wait_for_scan = nil
update = true update = true
end end
+10 -4
View File
@@ -457,7 +457,7 @@ pfUI:RegisterModule("panel", function()
do -- Zone do -- Zone
local widget = CreateFrame("Frame", "pfPanelWidgetZone", UIParent) local widget = CreateFrame("Frame", "pfPanelWidgetZone", UIParent)
for _,event in pairs(EVENTS_MINIMAP_ZONE_UPDATE) do for _,event in pairs({"PLAYER_ENTERING_WORLD", "MINIMAP_ZONE_CHANGED"}) do
widget:RegisterEvent(event) widget:RegisterEvent(event)
end end
widget.Tooltip = function() widget.Tooltip = function()
@@ -777,9 +777,15 @@ pfUI:RegisterModule("panel", function()
pfUI.panel.microbutton:SetSize(145, 23) pfUI.panel.microbutton:SetSize(145, 23)
pfUI.panel.microbutton:SetFrameStrata("MEDIUM") pfUI.panel.microbutton:SetFrameStrata("MEDIUM")
for i=1,table.getn(MICRO_BUTTONS) do local microButtons = {
local anchor = _G[MICRO_BUTTONS[i-1]] or pfUI.panel.microbutton 'CharacterMicroButton', 'SpellbookMicroButton', 'TalentMicroButton',
local button = _G[MICRO_BUTTONS[i]] 'QuestLogMicroButton', 'SocialsMicroButton', 'WorldMapMicroButton',
'MainMenuMicroButton', 'HelpMicroButton',
}
for i=1,table.getn(microButtons) do
local anchor = _G[microButtons[i-1]] or pfUI.panel.microbutton
local button = _G[microButtons[i]]
button:ClearAllPoints() button:ClearAllPoints()
button:SetParent(pfUI.panel.microbutton) button:SetParent(pfUI.panel.microbutton)
if i == 1 then if i == 1 then
+1 -1
View File
@@ -81,7 +81,7 @@ pfUI:RegisterModule("socialmod", function ()
if not info or not info.name or info.name == _G.UNKNOWN then break end if not info or not info.name or info.name == _G.UNKNOWN then break end
local name = info.name local name = info.name
local friendName = _G["FriendsFrameFriendButton"..i.."ButtonTextName"] local friendName = _G["FriendsFrameFriendButton"..i.."ButtonTextName"]
local friendLoc = _G["FriendsFrameFriendButton"..i..FRIENDS_NAME_LOCATION] local friendLoc = _G["FriendsFrameFriendButton"..i.."ButtonTextNameLocation"]
local friendInfo = _G["FriendsFrameFriendButton"..i.."ButtonTextInfo"] local friendInfo = _G["FriendsFrameFriendButton"..i.."ButtonTextInfo"]
local caption = friendName or friendLoc local caption = friendName or friendLoc
+11 -7
View File
@@ -189,6 +189,7 @@ pfUI:RegisterModule("tooltip", function ()
-- Icons come from a ClassicAPI object pool: ReleaseAll hides the whole -- Icons come from a ClassicAPI object pool: ReleaseAll hides the whole
-- set each refresh, then we Acquire and re-anchor left-to-right. -- set each refresh, then we Acquire and re-anchor left-to-right.
local BUFF_SIZE, BUFF_SPACING, BUFF_MAX = 20, 2, 32 local BUFF_SIZE, BUFF_SPACING, BUFF_MAX = 20, 2, 32
local auraSlots = {} -- reusable GetAuraSlots buffer for UpdateBuffs
pfUI.tooltip.buffs = CreateFrame("Frame", "pfTooltipBuffs", GameTooltip) pfUI.tooltip.buffs = CreateFrame("Frame", "pfTooltipBuffs", GameTooltip)
pfUI.tooltip.buffs:SetPoint("BOTTOMLEFT", GameTooltipStatusBar, "TOPLEFT", 0, default_border + 2) pfUI.tooltip.buffs:SetPoint("BOTTOMLEFT", GameTooltipStatusBar, "TOPLEFT", 0, default_border + 2)
pfUI.tooltip.buffs:SetHeight(BUFF_SIZE) pfUI.tooltip.buffs:SetHeight(BUFF_SIZE)
@@ -239,17 +240,20 @@ pfUI:RegisterModule("tooltip", function ()
end end
local prev, count = nil, 0 local prev, count = nil, 0
for i = 1, BUFF_MAX do -- one GetAuraSlots enumeration + positional by-slot reads: no per-aura
local aura = C_UnitAuras.GetBuffDataByIndex(unit, i) -- table and no per-index re-walk of the aura array
if not aura then break end local n = ScanAuraSlots(unit, "HELPFUL", auraSlots, BUFF_MAX)
for i = 1, n do
local name, texture, applications, _, _, expirationTime = C_UnitAuras.UnitAuraBySlot(unit, auraSlots[i])
if not name then break end
count = count + 1 count = count + 1
local icon = pfUI.tooltip.buffpool:Acquire() local icon = pfUI.tooltip.buffpool:Acquire()
icon.texture:SetTexture(aura.icon) icon.texture:SetTexture(texture)
icon.stacks:SetText(aura.applications and aura.applications > 1 and aura.applications or "") icon.stacks:SetText(applications and applications > 1 and applications or "")
icon.expirationTime = aura.expirationTime icon.expirationTime = expirationTime
local timeleft = aura.expirationTime and aura.expirationTime > 0 and (aura.expirationTime - GetTime()) or 0 local timeleft = expirationTime and expirationTime > 0 and (expirationTime - GetTime()) or 0
icon.timer:SetText(timeleft > 0 and GetColoredTimeString(timeleft) or "") icon.timer:SetText(timeleft > 0 and GetColoredTimeString(timeleft) or "")
if prev then if prev then
+1 -1
View File
@@ -113,7 +113,7 @@ pfUI:RegisterModule("totems", function ()
self.bar[i].cdbg = self.bar[i].cdbg or CreateFrame("Frame", nil, self.bar[i]) self.bar[i].cdbg = self.bar[i].cdbg or CreateFrame("Frame", nil, self.bar[i])
self.bar[i].cdbg:SetSize(self.iconsize - 3, self.iconsize - 3) self.bar[i].cdbg:SetSize(self.iconsize - 3, self.iconsize - 3)
self.bar[i].cdbg:SetPoint("CENTER", self.bar[i], "CENTER", 0, 0) self.bar[i].cdbg:SetPoint("CENTER", self.bar[i], "CENTER", 0, 0)
self.bar[i].cd = self.bar[i].cd or CreateFrame(COOLDOWN_FRAME_TYPE, "pfTotemsBar"..i.."Cooldown", self.bar[i].cdbg, "CooldownFrameTemplate") self.bar[i].cd = self.bar[i].cd or CreateFrame("Model", "pfTotemsBar"..i.."Cooldown", self.bar[i].cdbg, "CooldownFrameTemplate")
self.bar[i].cd.pfCooldownStyleAnimation = 1 self.bar[i].cd.pfCooldownStyleAnimation = 1
self.bar[i].cd.pfCooldownType = "ALL" self.bar[i].cd.pfCooldownType = "ALL"
+2 -2
View File
@@ -1,7 +1,7 @@
pfUI:RegisterModule("tracking", function () pfUI:RegisterModule("tracking", function ()
MINIMAP_TRACKING_FRAME:UnregisterAllEvents() _G.MiniMapTrackingFrame:UnregisterAllEvents()
MINIMAP_TRACKING_FRAME:Hide() _G.MiniMapTrackingFrame:Hide()
local rawborder, border = GetBorderSize() local rawborder, border = GetBorderSize()
local size = tonumber(C.appearance.minimap.tracking_size) local size = tonumber(C.appearance.minimap.tracking_size)
+1 -2958
View File
File diff suppressed because it is too large Load Diff
+30 -94
View File
@@ -3,6 +3,8 @@ function SlashCmdList.RELOAD(msg, editbox)
ReloadUI() ReloadUI()
end end
local addonName = ...
SLASH_PFUI1 = '/pfui' SLASH_PFUI1 = '/pfui'
function SlashCmdList.PFUI(msg, editbox) function SlashCmdList.PFUI(msg, editbox)
pfUI.gui:SetShown(not pfUI.gui:IsShown()) pfUI.gui:SetShown(not pfUI.gui:IsShown())
@@ -13,79 +15,12 @@ function SlashCmdList.GM(msg, editbox)
ToggleHelpFrame(1) ToggleHelpFrame(1)
end end
pfUI = CreateFrame("Frame", nil, UIParent) local pfUI = CreateFrame("Frame", addonName, UIParent)
pfUI:RegisterEvent("ADDON_LOADED") pfUI:RegisterEvent("ADDON_LOADED")
-- setup bootvar -- setup bootvar
pfUI.bootup = true pfUI.bootup = true
do
-- ClassicAPI dependency check.
-- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus
-- API surface that ClassicAPI polyfills, so presence is required.
local PFUI_CLASSIC_API_MIN = 11204 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
local function FormatVersion(packed)
local x = math.floor(packed / 10000)
local y = math.floor(math.mod(packed, 10000) / 100)
local z = math.mod(packed, 100)
return string.format("v%d.%d.%d", x, y, z)
end
if not CLASSIC_API_VERSION or CLASSIC_API_VERSION < PFUI_CLASSIC_API_MIN then
local minVersion = FormatVersion(PFUI_CLASSIC_API_MIN)
pfUI.disabled = true
local detail
if not CLASSIC_API_VERSION then
detail = "The ClassicAPI DLL isn't loaded. The |cff33ffcc!!!ClassicAPI|r addon ships bundled with it -- delete your |cff33ffcc!!!ClassicAPI|r folder and install the latest release from:"
else
detail = "ClassicAPI " .. minVersion .. " or newer is required. Delete your |cff33ffcc!!!ClassicAPI|r folder and reinstall the latest release from:"
end
local function ShowRequiredPopup()
StaticPopupDialogs["PFUI_CLASSICAPI_REQUIRED"] = {
text = "|cff33ffccpf|cffffffffUI|r has been disabled.\n\n" .. detail,
button1 = OKAY,
hasEditBox = 1,
editBoxWidth = 280,
timeout = 0,
whileDead = 1,
hideOnEscape = 1,
preferredIndex = 3,
OnShow = function()
local editBox = getglobal(this:GetName().."EditBox")
if editBox then
editBox:SetText(PFUI_CLASSIC_API_LATEST_URL)
editBox:HighlightText()
editBox:SetFocus()
end
end,
}
StaticPopup_Show("PFUI_CLASSICAPI_REQUIRED")
DEFAULT_CHAT_FRAME:AddMessage(
"|cff33ffccpf|cffffffffUI|r disabled: " .. detail .. " " .. PFUI_CLASSIC_API_LATEST_URL,
1, 0.3, 0.3
)
end
local loginFrame = CreateFrame("Frame")
loginFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
loginFrame:SetScript("OnEvent", function()
loginFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
ShowRequiredPopup()
end)
elseif CLASSIC_API_VERSION < PFUI_CLASSIC_API_LATEST then
EventUtil.ContinueOnPlayerLogin(function()
C_Timer.After(8, function()
DEFAULT_CHAT_FRAME:AddMessage(
"|cff33ffccpf|rUI: ClassicAPI " .. FormatVersion(PFUI_CLASSIC_API_LATEST) .. " is available — " .. PFUI_CLASSIC_API_LATEST_URL,
1, 0.85, 0.3
)
end)
end)
end
end
pfUI_playerDB = pfUI_playerDB or {} pfUI_playerDB = pfUI_playerDB or {}
pfUI_config = pfUI_config or {} pfUI_config = pfUI_config or {}
pfUI_init = pfUI_init or {} pfUI_init = pfUI_init or {}
@@ -117,35 +52,24 @@ pfUI.env = {}
-- the flag; one that lacks it should drop the flag and get the safe fallback. -- the flag; one that lacks it should drop the flag and get the safe fallback.
pfUI.handlesHookScript = true pfUI.handlesHookScript = true
if not pfUI.disabled then pfUI.events = Mixin({}, CallbackRegistryMixin)
pfUI.events = Mixin({}, CallbackRegistryMixin) pfUI.events:OnLoad()
pfUI.events:OnLoad() pfUI.events:SetUndefinedEventsAllowed(true)
pfUI.events:SetUndefinedEventsAllowed(true)
end
-- check if macro addons are loaded (disables macrotweak/macroscan) -- check if macro addons are loaded (disables macrotweak/macroscan)
function pfUI:MacroAddonsLoaded() function pfUI:MacroAddonsLoaded()
return IsAddOnLoaded("Supermacro") or IsAddOnLoaded("SuperCleveRoidMacros") or IsAddOnLoaded("UltimaMacros") return IsAddOnLoaded("Supermacro") or IsAddOnLoaded("SuperCleveRoidMacros") or IsAddOnLoaded("UltimaMacros")
end end
-- detect current addon path pfUI.name = addonName
local tocs = { "", "-master", "-tbc", "-wotlk" } pfUI.path = "Interface\\AddOns\\" .. addonName
for _, name in pairs(tocs) do
local current = string.format("pfUI%s", name)
local title = C_AddOns.GetAddOnName(current)
if title then
pfUI.name = current
pfUI.path = "Interface\\AddOns\\" .. current
break
end
end
-- handle/convert media dir paths -- handle/convert media dir paths
pfUI.media = setmetatable({}, { __index = function(tab,key) pfUI.media = setmetatable({}, { __index = function(tab,key)
local value = tostring(key) local value = tostring(key)
if strfind(value, "img:") then if value:find("img:") then
value = string.gsub(value, "img:", pfUI.path .. "\\img\\") value = string.gsub(value, "img:", pfUI.path .. "\\img\\")
elseif strfind(value, "font:") then elseif value:find("font:") then
value = string.gsub(value, "font:", pfUI.path .. "\\fonts\\") value = string.gsub(value, "font:", pfUI.path .. "\\fonts\\")
else else
value = string.gsub(value, "Interface\\AddOns\\pfUI\\", pfUI.path .. "\\") value = string.gsub(value, "Interface\\AddOns\\pfUI\\", pfUI.path .. "\\")
@@ -154,9 +78,7 @@ pfUI.media = setmetatable({}, { __index = function(tab,key)
return value return value
end}) end})
-- cache client version pfUI.client = INTERFACE_VERSION
local _, _, _, client = GetBuildInfo()
pfUI.client = client or 11200
-- setup pfUI namespace -- setup pfUI namespace
setmetatable(pfUI.env, {__index = getfenv(0)}) setmetatable(pfUI.env, {__index = getfenv(0)})
@@ -390,14 +312,13 @@ function pfUI:CheckNewModules()
end end
local function BackwardsCompatRegister(func, arg3) local function BackwardsCompatRegister(func, arg3)
if arg3 and type(func) == "string" and type(arg3) == "function" and string.find(func, "vanilla") then if arg3 and type(func) == "string" and type(arg3) == "function" and func:find("vanilla") then
return arg3 return arg3
end end
return func return func
end end
function pfUI:RegisterModule(name, func, arg3) function pfUI:RegisterModule(name, func, arg3)
if pfUI.disabled then return end
if pfUI.module[name] then return end if pfUI.module[name] then return end
func = BackwardsCompatRegister(func, arg3) func = BackwardsCompatRegister(func, arg3)
pfUI.module[name] = func pfUI.module[name] = func
@@ -408,7 +329,6 @@ function pfUI:RegisterModule(name, func, arg3)
end end
function pfUI:RegisterSkin(name, func, arg3) function pfUI:RegisterSkin(name, func, arg3)
if pfUI.disabled then return end
if pfUI.skin[name] then return end if pfUI.skin[name] then return end
func = BackwardsCompatRegister(func, arg3) func = BackwardsCompatRegister(func, arg3)
pfUI.skin[name] = func pfUI.skin[name] = func
@@ -429,7 +349,6 @@ function pfUI:LoadSkin(s)
end end
pfUI:SetScript("OnEvent", function() pfUI:SetScript("OnEvent", function()
if pfUI.disabled then return end
-- make sure to initialize and set our fonts -- make sure to initialize and set our fonts
-- each time an addon got loaded but only -- each time an addon got loaded but only
@@ -443,7 +362,7 @@ pfUI:SetScript("OnEvent", function()
-- "@project-version@" until release tooling substitutes it — mark those -- "@project-version@" until release tooling substitutes it — mark those
-- explicitly as "dev" instead of pretending they're a real numbered build. -- explicitly as "dev" instead of pretending they're a real numbered build.
local raw = tostring(GetAddOnMetadata(pfUI.name, "Version")) local raw = tostring(GetAddOnMetadata(pfUI.name, "Version"))
if strfind(raw, "@") then if raw:find("@") then
pfUI.version.major, pfUI.version.minor, pfUI.version.fix = 0, 0, 0 pfUI.version.major, pfUI.version.minor, pfUI.version.fix = 0, 0, 0
pfUI.version.string = "dev" pfUI.version.string = "dev"
else else
@@ -577,3 +496,20 @@ function pfUI.SetupCVars()
end end
UIParentLoadAddOn("Blizzard_CombatText") UIParentLoadAddOn("Blizzard_CombatText")
end end
do -- RunMacroText
local obj = setmetatable({ ["GetText"] = function(self) return self.text end }, {
__index = function(tab,key)
local value = function() return end
rawset(tab,key,value)
return value
end
})
function RunMacroText(text)
obj.text = text
ChatEdit_ParseText(obj, 1)
end
end
_G.PLAYER_BUFF_START_ID = -1
+5 -7
View File
@@ -8,11 +8,9 @@
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB ## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
## X-Website: https://github.com/brues-code/pfUI ## X-Website: https://github.com/brues-code/pfUI
pfUI.lua # ClassicAPI-less fallback. ClassicAPI redirects this read to pfUI_Turtle.toc
# (Turtle clients) or pfUI_ClassicAPI.toc (everything else), so the client only
# ever reaches THIS file when the DLL is missing. Load the notice and nothing
# else.
init\env.xml API_Check.lua
init\compat.xml
init\api.xml
init\libs.xml
init\skins.xml
init\modules.xml
+23
View File
@@ -0,0 +1,23 @@
## Interface: 11200
## Title: |cff33ffccpf|cffffffffUI
## Author: Shagu - modified by me0wg4ming & brues
## Notes: A complete user interface replacement.
## Notes-ruRU: Полная замена пользовательского интерфейса.
## Version: @project-version@
## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
## X-Website: https://github.com/brues-code/pfUI
# Selected by ClassicAPI on every non-Turtle client. Turtle clients get
# pfUI_Turtle.toc instead, which trades init\stock.xml for init\turtle.xml.
API_Check.lua
pfUI.lua
init\env.xml
init\stock.xml
init\api.xml
init\libs.xml
init\skins.xml
init\modules.xml
+24
View File
@@ -0,0 +1,24 @@
## Interface: 11200
## Title: |cff33ffccpf|cffffffffUI
## Author: Shagu - modified by me0wg4ming & brues
## Notes: A complete user interface replacement.
## Notes-ruRU: Полная замена пользовательского интерфейса.
## Version: @project-version@
## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
## X-Website: https://github.com/brues-code/pfUI
# Selected by ClassicAPI on Turtle WoW, where it wins over pfUI_ClassicAPI.toc.
# Same list with init\stock.xml swapped for init\turtle.xml: the modules, skins
# and vendor prices that only mean anything on a Turtle client.
API_Check.lua
pfUI.lua
init\env.xml
init\api.xml
init\libs.xml
init\skins.xml
init\modules.xml
init\turtle.xml