commit f19d7402810637fc32460864104cb792ac5af863
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date: Wed Jul 22 01:05:52 2026 -0500
remove comment
commit 60f4968f06d19d42bdc6347f98ff4d5a34785e97
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date: Wed Jul 22 01:05:06 2026 -0500
Bump ClassicAPI minimum version to 10705
Update the minimum required ClassicAPI version from 10704 (1.7.4) to 10705 (1.7.5).
commit 088dba4c23f4aa7ce98b9ce9d75bc5892cd40520
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date: Wed Jul 22 01:04:04 2026 -0500
Add raid-pet frames: an independent, roster-driven pet grid
New "raidpet" unitframe type that shows raid members' pets (raidpet1..40)
in their own movable block (pfRaidPetCluster), off by default. It's a
flat pool of frames laid out by pfUI.uf.raid:LayoutPets straight from the
raid roster -- cell N shows raidpet<N> -- so it's fully decoupled from how
the raid grid arranges its own slots.
Layout is independent of the raid grid: raidpet carries its own
width/height plus a Layout section (raidlayout / raidpadding / raidfill),
and its own Collapse Empty Slots toggle that packs only the pets that
exist into the leading cells. The raid grid gets the same collapse option
(sequential slot assignment in AddUnitToGroup instead of by subgroup).
Collapsed pets re-pack on roster changes and on UNIT_PET so summons and
dismisses track live without polling.
Also:
- unitframes: a "raidpet" branch in UpdateVisibility (hide when the pet is
out of range or its raid<N> owner is gone), and fix cache_raid so the
"pfRaid" prefix check doesn't misread pfRaidPet<n> frames (char 7 is
non-numeric -> nil compare crash).
- New "Owner Name" text option: on any pet frame (raidpet/partypet/pet) it
shows the owner's class-colored name so you can tell whose pet it is.
- unlock: a pfRaidPet drag cluster, a numeric-suffix guard so pfRaid no
longer matches (and crashes on) pet frames, and RaidPet config mappings.
- config/gui/translations for all of the above.
commit 52f02c8963fe7ec90f36100ebe069c7807529301
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date: Mon Jul 20 23:09:06 2026 -0500
Enumerate chat bubbles via ClassicAPI instead of scanning WorldFrame
ClassicAPI's C_ChatBubbles.GetAllChatBubbles() walks the engine's own
bubble list and returns the exact set of live bubble frames, with real
GetRegions(), so the decoration idiom works unchanged. Replace the
WorldFrame:GetChildren() sweep and drop the IsBubble heuristic (unnamed
frame whose first region is the ChatBubble-Background texture) -- the API
only ever hands back bubbles, so that guess is both redundant and more
fragile than the engine list. Cheaper too: it iterates only live bubbles
rather than every world child on each chat event.
Add a Left Click / Right Click hint to the totem icon tooltip via
AddDoubleLine, matching the panel.lua convention. Reuses the existing
"Left Click" / "Right Click" strings and adds "Recast Totem" /
"Target Totem" as new translation keys (stubbed across all locales; they
fall back to English until translated).
Also drop the now-orphaned "Range Check Interval" string from every
locale manifest -- the setting was removed when librange stopped
scanning, but its translation stubs were left behind.
ClassicAPI now ships GetTotemInfo/GetTotemTimeLeft/GetTotemDuration/
TargetTotem plus a native PLAYER_TOTEM_UPDATE event, backed by a
data-driven tracker (slot from the Spell.dbc summon effect, duration from
SpellDuration.dbc, and object-manager death detection). That's exactly
what libtotem hand-rolled -- and better -- so delete the library outright:
its spellid/icon tables, the CastSpellByName/CastSpell/UseAction hooks,
the SPELL_GO commit path, and the active-totem bookkeeping.
modules/totems.lua becomes a thin consumer of the native API:
- Driven by PLAYER_TOTEM_UPDATE; drop the shaman tick-poller that only
existed because vanilla had no totem event.
- Fix the GetTotemInfo call sites: the native 1st return is tool presence,
not "summoned", so key active state on name/start instead.
- Right-click a totem icon to TargetTotem it; tooltip shows remaining time
via GetTotemTimeLeft.
modules/turtle-wow.lua: drop the Totemic Recall handler that poked
libtotem:Clean() -- the native tracker detects the totems despawning and
clears the slots itself. Also clean up the now-orphaned translation string
and a stale libtotem mention in libdebuff's comment.
Clear existing spell cache tables with table.wipe instead of creating new tables when LEARNED_SPELL_IN_TAB fires. This preserves existing table references (spellmaxrank, spellindex, spellinfo), avoiding stale references and potential bugs while being slightly more efficient. Change applied in libs/libspell.lua.
Replace custom wipe implementation with a call to table.wipe in api/api.lua and update its doc comment to explain behavior (resets Lua 5.0 length via luaL_setn, advises using table.insert). Replace manual table.getn(t)+1 array appends with table.insert in modules/loot.lua (two sites). Makes table operations safer and more idiomatic, avoiding manual metatable handling and getn-based append idioms.
Two fixes to libbagsort's planning stage.
Family-aware placement: the sort treated every bag in the list as
interchangeable storage, so with a quiver / soul / profession bag in the
set it would try to swap a general item into a slot that can't hold it.
The client rejects that swap, but the grid was updated as if it
succeeded, desyncing the plan and corrupting the sort from there on. Now
each destination slot is tagged with its bag's family (via ClassicAPI's
GetItemFamily, which reports bag families reliably) and every item is
routed to a cell that accepts it -- matching specialty bag first,
overflowing to general -- so nothing lands where it can't go and family
items consolidate into their bags for free.
Locale-independent categories: SortCategoryPrefix compared the localized
itemType/quality strings from GetItemInfo, which silently miscategorize
everything on a non-enUS client. Switch to the numeric classID/quality
via C_Item.GetItemInfo and ClassicAPI's Enum.ItemClass / Enum.ItemQuality.
librange was a per-frame position scanner: it swept party/raid unit
tokens, cached each one's distance via UnitPosition, and answered range
queries from that cache. All of it existed only because 1.12 had no cheap
way to check an arbitrary unit's distance. ClassicAPI's UnitInRange does
exactly that C-side (fixed 40y healing range, position miss reported via
the second return), so the whole library collapses to a direct call.
Wins from dropping the cache:
- No staleness. The scanner's zone-death and roster-reindex bugs simply
can't exist without a cache to go stale, so this supersedes the
keep-alive fixes from 756e8840.
- All classes get target-frame range fading. The old target path faked a
40y check via IsActionInRange on a healing spell found on the action
bar, so classes without such a spell (GetRangeSlot returned nil) never
had a working target range check.
The rangecheck == "0" master switch used to be enforced by hiding the
scanner; with no scanner, move that gate into pfUI.api.UnitInRange so
disabling the check still means nothing fades. Threshold is now 40y (the
ClassicAPI constant) rather than the old 45y. Drop the now-dead
rangechecki (Range Check Interval) setting, its GUI row, and migration.
PLAYER_LEAVING_WORLD fires on every loading screen, not just logout, but
librange treated it as terminal: it latched librange_isLoggingOut and
tore OnUpdate off the frame, neither of which was ever restored. So the
first zone (into a BG, dungeon, etc.) permanently killed the distance
scan -- unitdata stopped updating and UnitInSpellRange defaulted every
unit to in-range until /reload, which the next loading screen then undid.
Only PLAYER_LOGOUT is terminal now; PLAYER_LEAVING_WORLD just hides for
the loading screen and PLAYER_ENTERING_WORLD re-shows it.
Also invalidate on RAID_ROSTER_UPDATE / PARTY_MEMBERS_CHANGED: the range
state is cached per unit token, so a roster re-index leaves each unitN
mapped to a different player with stale data. Clear the token cache and
restart the sweep so shifted/joined slots are re-evaluated within one
pass instead of inheriting the previous occupant's range.
Mirror the druid-stealth page switch for priests: swap to the auto page
(8) while in Shadowform, back to the default page when it drops. Driven
by UPDATE_SHAPESHIFT_FORM (form ID 28), which fully covers shadowform on
its own -- no prowl-style stealth substate to chase.
Fold the new state into the existing prowl machinery instead of
duplicating it: prowl/shadowform are mutually exclusive by class, so one
shared `formpaging` flag and one page constant serve both, and the
OnUpdate switch collapses to a single class-gated block.
The item->quest map only changes when a quest enters or leaves the log,
not on progress, yet it was fully rebuilt on every QUEST_LOG_UPDATE burst
(a whole log walk + GetQuestDetails per quest). Maintain it incrementally
from ClassicAPI's QUEST_ACCEPTED / QUEST_REMOVED, keyed on the stable
questID with title/level cached at add time (the old log index shifted on
any add/remove). QUEST_LOG_UPDATE now only drives a one-time login seed
until the detail cache warms, since QUEST_ACCEPTED is suppressed for the
bulk sync; afterward it's a no-op and questing does no rebuilds.
UpdateSlot previously created the glow texture and OnEnter acknowledge
hook on the first pass over every slot, then toggled visibility. Move
both inside the "is new" branch so a slot only allocates when it actually
holds a new item -- most bag/bank slots never do. Behavior is unchanged:
the glow is still created once per slot and reused, and the hook is
installed exactly when it's first needed.
pfUI's TOC depends on the !!!ClassicAPI addon, so a nil CLASSIC_API_VERSION
means the addon loaded but the DLL isn't present -- yet the graceful-disable
branch itself called ClassicAPI APIs (EventUtil.ContinueOnPlayerLogin, and
Mixin/CallbackRegistryMixin for pfUI.events), so it crashed instead of
informing the user.
- Defer the popup with a bare PLAYER_ENTERING_WORLD frame (stock 1.12)
instead of EventUtil/IsLoggedIn/PLAYER_LOGIN (ClassicAPI-era).
- Read the editbox via getglobal rather than _G.
- Guard pfUI.events creation behind `not pfUI.disabled`.
- Reword the notice: since the addon is present but the DLL isn't (or is
outdated), tell the user the addon ships bundled with the DLL and to
delete the !!!ClassicAPI folder and (re)install the latest release.
New module built on ClassicAPI's C_NewItems + BAG_NEW_ITEMS_UPDATED.
Glows bag slots (bags 0-4) holding items acquired since login, keyed on
item GUID so the flag survives rearranging. Hovering an item
acknowledges it (RemoveNewItem); closing the bags clears the rest via
ClearAll. Glow is UI-ActionButton-Border, sized off the slot width so it
tracks the icon_size config.
To stay decoupled from the bag frames, the bag module now broadcasts a
reusable "bag:closed" event through pfUI.events from its OnHide (carrying
the container so subscribers can tell backpack from bank), guarded so the
initial setup Hide() doesn't fire a phantom close.
Config: appearance.bags.newitem + newitem_color, with GUI toggles.
Replace the previous RunNextFrame conflict check with per-addon EventUtil.ContinueOnAddOnLoaded calls in modules/macrotweak.lua so macrotweak is disabled as soon as known conflicting addons load. Simplify variable naming and ensure the disabled flag is set correctly. In skins/blizzard/macro.lua replace separate SetHeight/SetWidth calls with a single SetSize(150,22) for MacroEditButton to tidy UI sizing.
EnterTradeskillMerge sized the merged bar as startMs + single*count, a
zero-latency assumption. Each craft boundary actually costs a server
round-trip, so the real chain runs ~(N-1)*lag longer than the bar
assumed. At the clear the overall fill was clamped to full and looked
done, but the fast per-craft spark tracks real time and came up short by
the accumulated lag -- freezing partway on the final craft.
StartTradeskillCraft now re-pins endTime to each craft's real start
(remaining crafts each still take `single`), so on the last craft
remaining==1 and endTime lands on its true completion. The spark and the
overall progress now reach the right edge together.
The RegisterSlashCommand helper in api/api.lua was effectively unused
(only macrotweak called it); every other command hand-rolled the
SLASH_*/SlashCmdList pair. Convert the existing manual registrations to
the helper with force=true, preserving the current always-bind behavior
while centralizing the pattern behind one code path (and its _G. and
conflict-check handling).
Left as-is: pfUI.lua's /rl, /pfui, /gm (registered before api.lua
defines the helper) and the vendored libs' debug commands.
The libtipscan approach scanned each bag/bank item's tooltip for red
text, then had to carve out broken (0-durability) items since those also
color red. C_PlayerInfo.CanUseItem checks item requirements directly
(proficiency, level, class/race, skill/spell/rep) and ignores item
state, so broken-but-equippable gear is never flagged and the durability
exclusion drops out entirely. Bank slots resolve through
C_Container.GetContainerItemID(-1, slot) instead of the inventory-slot
workaround the scanner needed.
Handful of addons will polyfill their own GetSpellInfo that only accept (bookSlot, bookType) so it's only safe to use C_Spell.GetSpellInfo with just a spell id
A pfUI-native group-loot roll history window built on ClassicAPI's
C_LootHistory backport, adapted from the anniversary Blizzard reference.
- Movable/scrollable window (ESC-closable, Clear button) listing rolled
items; each row expands to per-player rolls.
- Item icon/name/quality rendered via the !!!ClassicAPI Item mixin
(Item:CreateFromItemLink + ContinueOnItemLoad), so uncached items load
asynchronously and repaint their row.
- Winner shown on the collapsed row (name/roll/roll-type) and marked in the
expanded list with a checkmark left of the name (matches the reference).
- Expansion state keys on the stable rollID; events (FULL_UPDATE /
ROLL_CHANGED / ROLL_COMPLETE) drive a rebuild while shown, and re-attach
the scroll child so a growing list scrolls without a /reload.
- Toggle via /loothistory or /lh; optional auto-show on new rolls behind
loothistory.autoshow (default off).
Add display of required and optional addon dependencies to the addons tooltip. Introduce AddDependencyLines helper in modules/addons.lua which lists dependencies with color coding: green for loaded, yellow for present but unloaded, and red for missing (uses new T["Missing"]). Store dependency arrays on addon frames (adeps / aoptdeps) using GetAddOnDependencies and C_AddOns.GetAddOnOptionalDependencies. Add translation keys 'Dependencies', 'Optional Dependencies', and 'Missing' to env/translations_enUS.lua.
When the MerchantFrame is not shown, display the item's total vendor sell value on the tooltip. Adds a guard to call SetTooltipMoney(frame, sell * count) if sell > 0 so stacked items show their combined sell price.
Replace the single GameTooltip hook with a comprehensive hooking system that displays vendor prices across 17+ tooltip methods, including loot, quests, bags, mail, auctions, trades, merchants, and crafting. This ensures players see vendor prices consistently regardless of where they view items.
Pressing Esc (or re-pressing) to cancel a queued Heroic Strike / Cleave /
Maul left the swing bar stuck in its queued color. The color is set on the
on-swing press and only cleared on nampower's ON_SWING_QUEUE_POPPED, which
fires solely when a queued-behind on-swing resolves; nampower's cancel path
touches no on-swing state and emits no event, so the flag never cleared.
Reconcile the event flag against the client's IsCurrentAction, which it does
clear on cancel: ReconcileQueued drops the flag once the client has confirmed
the ability as current and then stops showing it (the true->false transition).
It only acts once current has been seen, so a nampower-initiated cast the
client never flags as current keeps its color until its own pop/resolve --
preserving the reason the event-driven path exists.
RebuildQueueSlotCache now caches Maul slots and runs for druids, and no longer
bails in event mode so the caches stay fresh for reconciliation.
Every HookAddonOrVariable call created its own lurker frame with three
event registrations. Share one frame across all hooks: they accumulate
in a pending list the single OnEvent handler walks, firing and dropping
each whose addon/variable is available, and unregistering events once the
list empties.
Behavior is preserved and slightly hardened: foundConfig now persists on
the shared frame (set on VARIABLES_LOADED and PLAYER_ENTERING_WORLD, both
of which imply config is ready), so a hook registered after config load
fires immediately if its addon is already loaded rather than waiting for
the next event.
commit d63057474083aa67fda2aa28ee6301334ffc4fdf
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date: Mon Jul 6 00:59:17 2026 -0500
Use C_Map.GetMapOverlays instead of hardcoded pfMapOverlayData
ClassicAPI's C_Map.GetMapOverlays reads WorldMapOverlay.dbc directly and
returns the full overlay list for a zone (explored + unexplored) — the
data vanilla's GetMapOverlayInfo withholds. mapreveal now iterates it
straight (named fields: textureName/texturePath/width/height/offsets),
dropping unpack_hash and the pfMapOverlayData tables entirely.
Also fixes the explored-check: it compared the full texture path against
GetMapOverlayInfo's bare-name keys, so the magnifying glass never
suppressed on explored overlays. Now matches on the bare name.
Removes ~870 lines of hand-measured overlay data (base + Turtle).
commit ad12c8209a80cd1211fe08e83f7013d24b5efd2d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date: Sun Jul 5 23:45:09 2026 -0500
utilize HookScript from ClassicAPI
The SPELL_CAST_EVENT hook only called SetQueuedKind, but the queued
color path is gated behind S.useSpellQueueEvent. Nampower fires
SPELL_CAST_EVENT on the actual HS/Cleave/Maul press (not just the
rarer ON_SWING_QUEUED), so flip the event-driven flag there. The
queued color now shows even when the client IsCurrentAction state
does not reflect a natively-queued on-swing ability.