Skip to content

Releases: brues-code/pfUI

v9.0.13

Choose a tag to compare

@github-actions github-actions released this 13 Jul 05:33

pfUI

v9.0.13 (2026-07-13)

Full Changelog Previous Releases

  • Remove RegisterNewModule call for loothistory
  • Route slash registration through pfUI.api.RegisterSlashCommand
    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.
  • cleanup
  • Skin Arena Frame
  • Simplify GUI toggle logic
  • Remove libtooltip

v9.0.12

Choose a tag to compare

@github-actions github-actions released this 12 Jul 18:51

pfUI

v9.0.12 (2026-07-12)

Full Changelog Previous Releases

  • Replace unusable tooltip scan with C_PlayerInfo.CanUseItem
    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.
  • These modules aren't new anymore
  • Use GetInventoryItemID instead of parsing link
  • cleanup
  • Unused strings
  • Removed redundant compare.basestats setting
    Just disable the module if you don't want stat comparison
  • Restore Inspect UI frame skin
    removed during the tbc purge
  • using GetSpellInfo with just a spell id is dangerous
    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
  • Add Loot History module
    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).
  • Bump min version to 1.6.4
  • Show addon dependencies in tooltip
    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.
  • Show sell value in tooltip when merchant hidden
    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.

v9.0.11

Choose a tag to compare

@github-actions github-actions released this 10 Jul 04:02

pfUI

v9.0.11 (2026-07-10)

Full Changelog Previous Releases

  • Restore hooksecurefunc
  • Restore HookScript
  • Added GetNoNameObject debugging
  • removed tbc logic

v9.0.10

Choose a tag to compare

@github-actions github-actions released this 10 Jul 03:06

pfUI

v9.0.10 (2026-07-10)

Full Changelog Previous Releases

  • Generalize vendor price display across all tooltip types
    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.
  • Revert on-swing queue color when the ability is cancelled
    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.
  • Use a single shared frame for HookAddonOrVariable
    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.

v9.0.9

Choose a tag to compare

@github-actions github-actions released this 09 Jul 05:57

pfUI

v9.0.9 (2026-07-09)

Full Changelog Previous Releases

  • Utilizing ClassicAPI 1.6.0
    commit d630574
    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 ad12c82
    Author: Brues 5278969+brues-code@users.noreply.github.com
    Date: Sun Jul 5 23:45:09 2026 -0500
    utilize HookScript from ClassicAPI
  • Show on-swing queue color on every HS/Cleave/Maul press
    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.
  • logically sort Castbar options
  • Split castbar config into General/Player/Target/Focus subcategories
    The castbar options were one long list. Break them into four subentries
    under the Castbar parent (matching the Settings/Actionbar layout):
    General (fonts, colors, texture, disable-blizzard) plus one page each for
    Player, Target, and Focus. Drops the now-redundant per-unit header rows.
  • Add spell name & timer text alignment options for unit frame castbars
    Adds per-unit (player/target/focus) dropdowns to align the castbar
    spell name (left text) and cast timer (right text) Left/Center/Right.
    Both share a castbaralign dropdown; defaults preserve current behavior
    (name LEFT, timer RIGHT). Applied at castbar creation, so takes effect
    on /reload like the other castbar options.
  • Don't let the pet bar dodge reposition the stance bar during unlock
    The pet bar force-shows in unlock mode, and its OnShow/OnHide dodge
    handlers re-anchor the stance bar above the pet bar. That yanked the
    stance bar off its real position while unlocking (dodging a pet bar
    that isn't actually active), so it appeared to vanish and only returned
    when unlock ended. Skip the dodge re-anchor while unlock is active so
    the stance bar stays put and can be positioned.
  • remove select

v9.0.8

Choose a tag to compare

@github-actions github-actions released this 07 Jul 04:37

pfUI

v9.0.8 (2026-07-06)

Full Changelog Previous Releases

  • prevent camera from constantly resetting
  • utilize HEARTHSTONE_BOUND
  • utilize UnitIsAFK
  • Clear castbar unlock preview when leaving unlock mode
    The unlock preview drives the bar via alpha: the OnUpdate forces alpha=1
    while the drag handle is shown. On lock, with no active cast (endTime nil)
    and no fadeout, the idle branch returned early and left the empty bar
    stuck at alpha 1. Reset leftover alpha to 0 in that branch so the preview
    clears once the drag handle hides. Fixes #16.

v9.0.7

Choose a tag to compare

@github-actions github-actions released this 06 Jul 04:56

pfUI

v9.0.7 (2026-07-06)

Full Changelog Previous Releases

  • Bump ClassicAPI minimum version to 1.5.11
  • Always set OnClick handler for action buttons
    Ensure the action button OnClick handler is always assigned. Previously SetScript("OnClick", ButtonClick) only ran when HookScript was missing; now HookScript is still added only if absent, but the OnClick script is set unconditionally so existing frames won't miss the click handler. Change is limited to modules/actionbar.lua.
  • Refactor turtle/Nampower checks and libdebuff cleanup
    Replace ad-hoc Turtle/Nampower detection with global TURTLE_WOW_VERSION and EventUtil startup flow. Remove legacy IsTurtleWoW and manual PLAYER_ENTERING_WORLD frame; use EventUtil.ContinueOnPlayerLogin. Clean up libdebuff by removing combo-point capture, GetEnhancedDebuffs API, and noisy startup messages; rely on Nampower/AURA_CAST and database fallback for durations. Fix tooltip compare shift handling (cache shift state and pass through). Update xpbar to use TURTLE_WOW_VERSION. Purpose: simplify startup, avoid duplicated logic, and rely on modern APIs for accurate durations.
  • Route hooksecurefunc callers through pfUI.hooksecurefunc; global belongs to ClassicAPI
    pfUI's Lua hooksecurefunc lived in pfUI.env and shadowed ClassicAPI's C
    global for all pfUI code. Replace it with a thin pfUI.hooksecurefunc shim
    that keeps the missing-target no-op our call sites rely on (ClassicAPI
    errors on a nil target) and delegates the actual hook to _G.hooksecurefunc.
    Migrated all 70 internal call sites (modules/libs/skins) to
    pfUI.hooksecurefunc; bare hooksecurefunc now resolves to ClassicAPI's C
    version everywhere. Dropped the unused prepend path and the orphaned
    pfUI.hooks table.
  • UNIT_INVENTORY_CHANGED -> PLAYER_EQUIPMENT_CHANGED
  • Don't need to worry about caching player guid anymore
  • Update README.md
  • GetLootSlotItemLink should be GetLootSlotLink
  • Update FUNDING.yml
  • Update README.md
  • Bump pfUI min to 1.5.8
  • Revert "nameplates: hide castbar on remote interrupt / caster death (#11)"
  • share: rebuild profile export/import on C_EncodingUtil (CBOR+zlib+base64)
    Export now diffs the config against defaults and emits
    SerializeCBOR -> CompressString (zlib) -> EncodeBase64 with a "!pf1!"
    prefix. Import reverses that into a plain table — no loadstring, so a
    pasted profile is data and can't execute code. The Decode/Encode button
    converts blob <-> editable JSON (SerializeJSON/DeserializeJSON) for
    inspection and hand-edits.
    Old-format strings still import: standard base64 via DecodeBase64, the
    custom LZW decompressor kept import-only, and the resulting Lua source
    runs in an EMPTY setfenv sandbox that can only assign its config table.
    Decode on a legacy string yields the JSON view, so Encode re-emits it
    as a new-format blob (migration path).
    Roughly half the paste size of the old LZW format, C-speed instead of
    the old bit-string base64 (which froze the client on large configs),
    and the format is fully standard — external tools can decode profiles
    with stock base64/zlib/CBOR libraries.
    Requires ClassicAPI with the SerializeCBOR buffer-growth fix (payloads
    over 256 bytes returned nil before it).
  • nameplates: hide castbar on remote interrupt / caster death (#11)
    ClassicAPI's remote-cast cache is stamped from SMSG_SPELL_START and only
    expires by computed end time — 1.12 keeps no per-unit interrupt record,
    so an interrupted cast kept animating on the plate until its would-be
    finish (BG flag caps being the loudest repro).
    Nampower does surface the missing signal in Lua: SPELL_FAILED_OTHER
    (casterGuid, spellId; fired from the SMSG_SPELL_FAILED_OTHER handler)
    and UNIT_DIED (guid). Stamp a guid-keyed suppression time on either
    event and have GetCastInfo drop any cast that started before the stamp;
    a newer cast clears its unit's entry. Both castbar paths (dedicated
    target frame + central loop) already funnel through GetCastInfo, so one
    check covers them. The handler only stamps when the unit actually has a
    tracked cast, and flags the plate via castUpdate for a same-tick hide.

v9.0.6

Choose a tag to compare

@github-actions github-actions released this 03 Jul 07:34

pfUI

v9.0.6 (2026-07-03)

Full Changelog Previous Releases

  • bump classicapi min to 1.5.7
  • eqcompare: rewrite on top of ClassicAPI SetHyperlinkCompareItem
    Drop the manual C_Item.GetItemStatDelta rendering (inline annotations
    and bottom-block summary) in favor of driving native shopping tooltips
    via SetHyperlinkCompareItem — the 3.3.5 flow now available through
    ClassicAPI. Way less code, and Blizzard's own comparison rendering
    handles all stat types uniformly.
    Also revert the mode dropdown back to a single basestats checkbox — the
    new implementation doesn't distinguish base vs extended (Blizzard's
    tooltip shows everything the item exposes), so the two-level control
    was redundant. Existing basestats configs pass through unchanged.
    AtlasLootTooltip now goes through the shared HookTooltip helper instead
    of a bespoke OnShow shim.
  • eqcompare: collapse basestats/extendedstats checkboxes into a mode dropdown
    Replace the two-checkbox arrangement (Compare Base Stats + Compare
    Extended Stats, with the latter gated on the former) with a single
    "Item Comparison" dropdown offering Off / Base / Extended. Migrate
    existing configs.
    Also route CreateConfig's value-change sites through pfUI.events
    ("config:changed", category, config) so callers can react to arbitrary
    setting changes without frame-specific plumbing. Use it here to grey
    out "Always Show Item Comparison" when the mode is Off.
  • eqcompare: skip paperdoll owners in showalways mode
    Comparing an equipped slot's tooltip against itself is pointless — every
    delta is zero. Skip that case when showalways=1. Shift-hover still
    forces the comparison unconditionally.
  • eqcompare: hook Set* via hooksecurefunc + unify base/extended stat block
    Refactor delta rendering:
    • extendedstats on -> all stats (base + extended + DPS + block value)
      appended at the bottom via AddDoubleLine
    • extendedstats off -> base stats annotated inline; nothing at the bottom
      Requires ClassicAPI's 60-line tooltip fix so the bottom block isn't
      truncated. DPS and block value were previously extended-only inline
      matches — moved into BASE_STAT_KEYS so they also show at the bottom.
      Also extract MakeDependent(child, parent) helper from the local
      gate-lambda in gui.lua so the base/extended checkbox pairing generalizes.
  • no select
  • Update README.md
  • bump ClassicAPI version
  • eqcompare: use C_Item.GetItemStatDelta for the comparison math
    Replaces the twin-tooltip text extraction/comparison pair
    (ExtractAttributes + CompareAttributes) with a single delta pull from
    ClassicAPI's C_Item.GetItemStatDelta(equippedLink, newLink).
    Base stats (Str/Agi/Sta/Int/Spi/Mana/Health + Armor + resistances) stay
    annotated inline on their existing tooltip line: iterate the tooltip's
    FontString regions (no more _G["...TextLeft"..i] name lookup), match the
    "+N Foo" prefix, look up the trailing noun in a label→key map, append
    (+delta)/(-delta) from the ClassicAPI delta table.
    Extended stats (attack power / ranged AP / spell damage/healing / crit
    ratings / hit ratings / mana regen / defense / DPS) don't emit their own
    line — vanilla mixes them into equip-spell descriptions ("Equip:
    Increases your critical strike chance by 1%") — so aggregate them into
    a "Compared to equipped:" block at the bottom via AddDoubleLine. New
    tooltip.compare.extendedstats config knob (default 1) gates that
    block; it depends on basestats being on (its GUI checkbox grays out
    otherwise). DPS rounded to one decimal — ClassicAPI derives it from
    damage/delay so it lands as a raw float.
    Random-suffix bonuses ("of the Bear" etc.) now count correctly since
    GetItemStatDelta walks item-record + equip-spell auras + suffix
    enchants server-side.
  • eqcompare: numeric InventoryType lookup, drop bagtypes/itemtypes locales
    Both sub-tables carried per-locale strings only so pfUI's own code could
    match against localized text. ClassicAPI's numeric item APIs replace
    both:
    • GetBagFamily now reads classID/subClassID from C_Item.GetItemInfoInstant
      and switches on the numbers (class 1 = Container, class 11 = Quiver).
    • eqcompare pulls the itemID from GameTooltip:GetItem(), fetches the
      numeric invType via C_Item.GetItemInventoryTypeByID, and looks up the
      destination slot(s) in a numeric slotTable keyed by Enum.InventoryType.
      Pair-slot invtypes (finger / trinket / one-hand weapon) list both
      destinations directly, so the "_other" string-concat hack is gone.
      Removes the setglobal INVTYPE_* injection, the tooltip text scan, and
      the itemtypes + bagtypes locale sub-tables across all 7 files.
  • locales: strip 4 dead sub-tables (hunterpaging, interrupts, spells, icons)
    Audited every consumer of pfUI_locale[*][key] across the codebase. Four
    sub-tables have no non-locale-file readers left:
    - hunterpaging — old auto-page trigger removed
    - interrupts — replaced by Nampower SPELL_INTERRUPTED events
    - spells — replaced by ClassicAPI Spell.dbc lookups
    - icons — replaced by ClassicAPI C_Spell.GetSpellName / icon path
    Removed the entries from all 7 locale files. ~18k dead lines gone,
    ~70% shrink per file.
  • replace poll-until-cancel OnUpdate frames with C_Timer / RunNextFrame
    Seven ad-hoc OnUpdate handlers were only spinning long enough to reach
    a known deadline or a next-frame defer, then unhooking themselves.
    Convert them to their proper primitives:
    • autovendor: 0.3s wait after junk sell → C_Timer.After(0.3, ...)
    • innervatecall: cooldown-expiry ready ping → C_Timer.After(cd, ...)
    • focus: re-arm UI_ERROR_MESSAGE next tick → RunNextFrame
    • macrotweak: conflict scan after addons load → RunNextFrame
    • ui-widgets (CreateQuestionDialog): font-measure resize → RunNextFrame
    • libdebuff: post-PEW Nampower init → RunNextFrame
    • bubbles: WorldFrame scan after chat event → RunNextFrame
      Net -18 lines and no more throwaway frames sitting on the OnUpdate list.
  • add pfUI.events callback registry, replace addoncompat OnUpdate poll
    Introduce a central pfUI.events registry (ClassicAPI's
    CallbackRegistryMixin, undefined events allowed) initialized in pfUI.lua
    before any module body runs, so publishers/subscribers don't depend on
    module load order.
    firstrun sets pfUI.firstrun.completed and fires firstrun:complete at
    the point NextStep detects no pending steps. PLAYER_ENTERING_WORLD re-
    enters this path on every zone, so the flag is a one-shot guard.
    addoncompat drops its 0.1s OnUpdate poll and either RunQueues immediately
    (returning user, all steps already done) or subscribes to the event.
  • unitframes: clear stale aura swirl on target swap
    Buff and debuff slots only called CooldownFrame_SetTimer on the
    expirationTime > 0 (or duration > 0 for buffs) paths. When the new
    target's aura at the same slot index had neither — permanent / passive
    auras like Retribution Aura — neither branch fired and the slot kept
    displaying the previous target's swirl/timer.
    Add an explicit 0/0/0 clear on every path that doesn't set a real
    timer, so the button always starts from a known state.
    Fixes #13.

v9.0.5

Choose a tag to compare

@github-actions github-actions released this 28 Jun 09:30

pfUI

v9.0.5 (2026-06-28)

Full Changelog Previous Releases

  • buffs: cancel by spellID instead of GetPlayerBuff slot index
    GetPlayerBuff(PLAYER_BUFF_START_ID + this.id, filter) assumes the
    visual index pfUI shows matches the engine's slot order. When that
    mismapping happens — most easily reproduced by stacking buffs that
    share a slot family — right-clicking one buff cancels another.
    C_Spell.CancelSpellByID(spellID) ships CMSG_CANCEL_AURA keyed to the
    spell, not a slot, so it's immune to whatever order the slot table is
    in. Cache spellId on the button at refresh time in buff.lua; in the
    unitframes/buffwatch handlers fetch the aura fresh via
    C_UnitAuras.GetAuraDataByIndex at click time.
    Fixes #10.
  • character cleanup

v9.0.4

Choose a tag to compare

@github-actions github-actions released this 28 Jun 04:31

pfUI

v9.0.4 (2026-06-28)

Full Changelog Previous Releases

  • Texture ArenaFrame
  • tooltip: optional movement-speed line via GetUnitSpeed
    New tooltip.movespeed config knob (default off, checkbox in the GUI's
    tooltip page). When on, the unit tooltip gains a "Speed: N%" line where
    N is the unit's run speed normalized to vanilla's 7.0 yd/s base — 100
    unmounted, 160 on a 60% mount, 200 on epic, less under snares.
    Uses runSpeed (return 2 of GetUnitSpeed), not currentSpeed, so the
    number reflects what the unit would be running at — visible even
    while they're standing still. runSpeed is 0 for out-of-range units, so
    the line is skipped in that case.
  • show CLASSIC_API_VERSION in /pfdll
  • Clean up throttle
  • player: drop talent-side modCastingTime fudge from haste display
    The player frame's "Effective Haste" mode was hardcoded talent-position
    scrapes: GetTalentInfo(1, 16) for the Mage "Accelerated Arcana"
    (flat 5%) and GetTalentInfo(1, 14) for the Warlock "Rapid Deterioration"
    (3% per rank), folded into the displayed haste % via
    (1 / (modCastSpeed * modCastingTime) - 1) * 100.
    That's two problems in one:
    • Hardcoded talent indices and effect percentages — brittle to any
      Turtle tree reshuffle or retune.
    • Conceptually muddled: it folds gear-haste and talent-cast-reduction
      into one number that's hard to read as anything specific. The actual
      effective cast time is already shown on the cast bar via
      C_Spell.UnitCastingInfo (engine helper accounts for SpellMod op 10).
      Drop modCastingTime, the LEARNED_SPELL_IN_TAB watcher frame that
      maintained it, the per-class talent scrape, and the hasteMode == "2"
      display branch. Collapse the now-binary "display_haste" config from a
      3-option dropdown to a checkbox. Users on legacy "2" will see the
      checkbox unchecked once and can re-enable with a single click.
  • finish UnitInRaid("player") → IsInRaid() sweep
    Four more sites: GetUnbuffedRoster + SendChatMessageWide in api.lua,
    the loot menu's inRaid local, and the raid module's early-return
    guard. Same intent, named helper.
  • finish IsInRaid sweep across remaining "raid count > 0" sites
    Three more if GetNumRaidMembers() > 0 then raid-vs-party branches
    switched to if IsInRaid(). Same intent, named helper. Repo is now
    clean of the legacy idiom (verified with a final grep).
    Loops that actually need the count (for i = 1, GetNumRaidMembers() do GetRaidRosterInfo(i)) keep the call — only the boolean form changes.
  • thirdparty-vanilla: collapse solo check to not IsInGroup()
    The HealComm self-message guard was not UnitInRaid("player") and GetNumPartyMembers() < 1 — the long form of "in no group at all."
  • switch group-membership checks to IsInGroup / IsInRaid
    ClassicAPI ships modern IsInGroup() / IsInRaid() backports — drop the
    GetNumPartyMembers() > 0 and GetNumRaidMembers() > 0 idioms (and the
    GetNumPartyMembers() > 0 or GetNumRaidMembers() > 0 conflation) for the
    named-intent variants. UnitInRaid("player") → IsInRaid() at the same
    sites.
  • mouseover/libpredict: drop legacy spell-target plumbing
    With Nampower as a hard dep, /pfcast for spell names always takes the
    early CastSpellByName(msg, unit) path. The fallback branch that did the
    SpellTargetUnit dance (resolve a friendly unit token, disable AutoSelf
    Cast, call SpellTargetUnit) hasn't been reachable in a while, and it
    dragged a pile of supporting infrastructure with it.
    modules/mouseover.lua:
    • Drop the st_units token list, GetUnitString helper, and the
      UnitTokenFromGUID rewrite of GetUnitString — all only used by the
      dead fallback.
    • Drop the NoSelfCast helper (only the dead fallback called it).
    • Drop the pfMouseOver frame; its only purpose was to hold a .unit
      field the dead fallback wrote and libpredict's hook read.
    • The macro path collapses to: if not the current target, swap target,
      run the loadstring'd func, restore the previous target.
    • 99 lines → 34.
      libs/libpredict.lua:
    • Drop the dead local mouseover = pfUI.uf.mouseover.unit plumbing in
      the CastSpellByName hook — pfUI.uf.mouseover is gone and the field
      was permanently nil anyway. The three target or mouseover or default
      fallback chains collapse to target or default.
      Modern mouseover/click-to-cast detection in libpredict goes through
      pfUI.libpredict_pending_cast (populated by libdebuff from Nampower's
      SPELL_CAST_EVENT) — that path is GUID-based, server-authoritative, and
      untouched.