261 Commits

Author SHA1 Message Date
Brues f657a9e7e8 drop MobHealth3 / MobHealthFrame fallbacks
libhealth ships with pfUI and Nampower's GetUnitField (hard-dep) covers
the real-HP read; the MobHealth integration was a chained last-resort
fallback that could never actually win, and on the nameplate path it
also mixed percentage and real-value scales into the bar's SetMinMaxValues
since it overwrote hp/hpmax without hpmin.
2026-06-27 16:08:39 -05:00
Brues 0cbd9ecf98 Revert "nameplates: drop redundant name check from plate-reassignment gate"
This reverts commit 6ca482fcaa.
2026-06-27 16:01:24 -05:00
Brues 6ca482fcaa nameplates: drop redundant name check from plate-reassignment gate
GUID is the unique identity; the name check was leftover from the
name-only era and became dead weight once cachedGuid (NAME_PLATE_UNIT_
ADDED) was added alongside it.
2026-06-27 15:59:16 -05:00
Brues 8902d43f40 nameplates: wipe full plate.cache on reassignment
The plate-reuse reset only cleared name/guid/player/cdCache, leaving
hp/hpmax/rgb/namecolor/levelcolor/target/mouseover/inCombat behind. The
PERF gates downstream ("only update X when X changed") then skipped bar
fill / color / text updates when the new occupant happened to share a
cached value with the previous one — most easily reproduced on
plate-pool reuse in starting zones (mobs churn fast, percentage values
collide). Nuke the whole cache via table.wipe.

Refs #8.
2026-06-27 15:48:53 -05:00
Brues b79132b9f4 casts: route everything through C_Spell, drop libcast + libdebuff_casts
ClassicAPI's recent C_Spell additions cover remote-unit casts natively
(SMSG_SPELL_START co-hook caching per caster GUID), so the two parallel
cast trackers pfUI was running — libcast.lua and the libdebuff_casts
table inside libdebuff.lua — can both retire.

Migrations:
- modules/castbar.lua: focus/player cast-info gathering reads
  C_Spell.UnitCastingInfo / UnitChannelInfo directly. Fallback ladder
  (libdebuff_casts → pfGetCastInfo → pfGetChannelInfo) collapses into a
  single call. Pushback handlers stop writing back into a non-existent
  cache; the local this.endTime is the source of truth.
- modules/nameplates.lua: GetCastInfo(guid) now resolves to a unit token
  via UnitTokenFromGUID and queries C_Spell, returning the same compact
  struct shape downstream code expected. UpdateCastbar collapses from a
  three-branch hierarchy (dead IterDebuffs / libdebuff_casts / libcast)
  to one C_Spell read.
- modules/afkcam.lua: pfGetCastInfo+pfGetChannelInfo round-trip becomes
  a single C_Spell.UnitCastingInfo("player") or UnitChannelInfo fallback.
- libs/libpredict.lua: HealComm timing uses C_Spell on the sender's unit
  token after a small group-roster walk to resolve the sender's name.

Deletions:
- libs/libcast.lua entirely (-571 lines) plus its init/libs.xml entry.
- libdebuff_casts / libdebuff_item_icons tables and their write sites
  in libs/libdebuff.lua (the SPELL_START_*, SPELL_GO_*, SPELL_FAILED_*
  event handlers stop maintaining them but keep firing the
  libdebuff_*_hooks broadcast surface for actionbar / swingtimer /
  libtotem). SPELLCAST_CHANNEL_STOP now reads the active channel from
  C_Spell.ChannelInfo.
- modules/superwow.lua's supercast block — UNIT_CASTEVENT writes into
  libcast.db are redundant now that C_Spell co-hooks the same packet.
- The cast-bar item-icon override that swapped in a potion/trinket
  icon for item-triggered casts. Spell icon stays; the item-icon
  metadata path (libdebuff_item_icons) went with libdebuff_casts.

Steady Shot synthetic cast bar — Turtle WoW-specific:
- castbar.lua gains a pfUI.synthetic_casts[unit] fallback that fires
  only when C_Spell returns nil, so abilities the engine treats as
  instant but which have a meaningful wait window can still render a
  cast bar.
- modules/turtle-wow.lua replaces the old libcast.customcast block with
  a Nampower SPELL_QUEUE_EVENT subscriber. ON_SWING_QUEUED matching
  the localized "Steady Shot" name writes a 1.4s synthetic entry;
  ON_SWING_QUEUE_POPPED clears it; castbar's endMs guard self-expires
  the entry as a safety net. Note: haste scaling (libcast.ApplyShotHaste)
  is gone — bar may finish slightly early under +ranged haste buffs.

Net: 152 insertions, 972 deletions.
2026-06-25 01:18:22 -05:00
Brues be6ae25315 libdebuff/nameplates: drop dead per-aura readers and debuff cache
With every external caller of libdebuff:UnitDebuff / :UnitOwnDebuff
now on C_UnitAuras, the two public per-aura readers and the
nameplate-side cache they were feeding have no consumers.

- libs/libdebuff.lua: removes libdebuff:UnitDebuff (~120 lines),
  libdebuff:UnitOwnDebuff (~75 lines), the _ownDebuffSortFunc helper,
  and the local cache table. The slotOwnership / ownDebuffs /
  allAuraCasts / pendingCasts bookkeeping stays — GetBestAuraCast
  (libpredict) and GetEnhancedDebuffs (CleveRoids) still read it, and
  the event handlers maintain it. GetSlotCaster / GetDebuffSlotMap
  stay too; the DEBUFF_ADDED_OTHER handler and the debug printer use
  them. File goes 2010 → 1870 lines.
- modules/nameplates.lua: deletes PlateCacheDebuffs (was already
  rewritten on C_UnitAuras and unused once the display loop bypassed
  the cache), PlateUnitDebuff, the cachedVerify scaffolding, and the
  nameplate.UnitDebuff / nameplate.CacheDebuffs registrations.
- api/config.lua + modules/gui.lua: drops the now-defunct
  "guessdebuffs" knob — its only effect was gating the dead cache.
2026-06-24 22:41:36 -05:00
Brues fd21b24a74 utilize C_UnitAuras for nameplate auras 2026-06-24 19:14:36 -05:00
Brues 7e52683004 nameplates: reset cache.player on plate reassignment to dodge stale hints
The per-unit cache reset only fired when the plate's name changed, so
pool reuse between same-named units (player "Ironforge Guard" → NPC
"Ironforge Guard") carried the previous unit's cache.player into the
next OnDataChanged call. GetUnitInfo then returned the wrong table's
class, unittype flipped to FRIENDLY_PLAYER, and the bar drew in MAGE
class color. Gate the reset on cachedGuid changes too.

Stores cache.player as true/false/nil instead of "PLAYER"/"NPC" so it
flows straight into GetUnitInfo as the isPlayer hint — both in
OnDataChanged and the wait_for_scan retry, which previously dropped
the hint and ping-ponged the flag every frame.
2026-06-22 11:38:19 -05:00
Brues d14d30b00b revert PixelUtil usage 2026-06-22 11:31:27 -05:00
Brues aa912ed20a nameplates: collapse OnDataChanged unit-type resolve to a single pass
Hoists the name-change reset above the GetUnitInfo lookup and folds the
two UnitIsPlayer call sites into one. The earlier shape resolved
cache.player upfront from cachedGuid, then redundantly re-resolved from
unitstr after the name-change reset — and the upfront block could read
stale cache.player on plate reassignment, passing a wrong isPlayer hint
to GetUnitInfo.
2026-06-22 11:15:31 -05:00
Brues 6c64143b60 nameplates: filter libunitscan by player/npc to dodge name collisions
GetUnitInfo() probed the players table first, so an NPC sharing a name
with a known player (e.g. Chromie) inherited the player's class, level,
and guild. Adds an isPlayer hint to GetUnitInfo and resolves each
plate's actual unit type from its cached GUID via UnitIsPlayer before
the lookup. The plate's cache.player gates further work.
2026-06-22 10:11:56 -05:00
Brues fa3f191eea castbar: pixel-snap progress via PixelUtil.SetStatusBarValue
Routes player and nameplate castbar progress through
PixelUtil.SetStatusBarValue so a 1.4s cast on a narrow bar no longer
shimmers across fractional pixels as it ticks. Adds GetMinMaxValues /
GetValue handlers to pfUI's custom StatusBar so PixelUtil can read the
current range.
2026-06-22 10:11:33 -05:00
Brues 5772cf2f91 GetUnitData -> GetUnitInfo
avoid clash
2026-06-17 20:19:42 -05:00
Brues 17291e4d9b nameplates: cut per-tick allocations in OnUpdate path
Six allocation sites firing per visible plate per central tick (or per
throttled OnDataChanged tick) were generating heavy GC pressure visible
in pfDebug's analyzer:

- IterDebuffs callback in PlateCacheDebuffs was a fresh closure per call.
  Hoisted to a module-level function with state in _pcdSelf / _pcdNow /
  _pcdId, matching the pattern the icon-grid IterDebuffs already used.

- string.format("%.2f", remaining) in UpdateCastbar fired every frame per
  active castbar. Factored into SetCastbarText helper that compares a
  rounded integer (centi- or deci-seconds) and only formats + SetTexts
  when the displayed value would actually change. lastTextTick reset
  alongside lastEndTime so back-to-back casts don't collide.

- guid.."target" concat in GetCombatStateColor hit Lua's string intern
  pool every call. Cached in guidTargetTokenCache, evicted alongside
  the other per-guid caches in NAME_PLATE_UNIT_REMOVED.

- plate.name:SetText was unconditional; moved inside the existing
  plate.cache.name change gate so it only fires on real unit changes.

- plate.level:SetText (string.format) was unconditional; gated behind a
  new (level, elite) cache so the format only runs on level-up or
  elite-state flips.

- C_NamePlate.GetNamePlates() poll every 0.5s allocated a fresh Lua
  table just to read its length. Replaced with a visiblePlateCount
  counter maintained event-driven from NAME_PLATE_UNIT_ADDED/_REMOVED.
2026-06-17 13:30:31 -05:00
Brues 50d06f2e7a nameplates: cachedGuid + percent-mode guard + name text position
- Switch the four GUID reads in OnDataChanged from plate.parent:GetName(1)
  (SuperWoW idiom) to plate.cachedGuid (set by NAME_PLATE_UNIT_ADDED via
  UnitGUID(token)). Move the initial OnDataChanged call out of
  OnConfigChange's CREATE path so it runs after UNIT_ADDED has populated
  cachedGuid; re-add it explicitly in the user-config-change loop.

- Reject GetUnitField's health/maxHealth when maxHealth == 100 — the
  engine writes (hp_percent, 100) into UnitFields for non-detailed units
  (UPDATE_PARTIAL packets carry percent only). Without this guard,
  Nampower's raw field read returns the percent and the nameplate displays
  "5 / 100" as if it were real HP. Mirrors libhealth's heuristic so we
  fall through to its estimator instead.

- New config: nametextpos (LEFT/CENTER/RIGHT, defaults to CENTER).
  Decouple the bar's anchor from the name so the name's JustifyH can
  shift left/right without dragging the bar with it.
2026-06-16 19:53:52 -05:00
Brues 1fd7895ca7 move away from RAID_CLASS_COLORS dependency 2026-05-28 13:06:00 -05:00
brues-code ed06968fa3 C_NamePlate (#1)
* nameplates: drive discovery + GUID lookup via C_NamePlate

ClassicAPI now provides the modern C_NamePlate API and the matching
NAME_PLATE_CREATED / NAME_PLATE_UNIT_ADDED / NAME_PLATE_UNIT_REMOVED
events. Replace the WorldFrame:GetChildren polling + manual GUID
dictionary with event-driven plumbing.

- Drop the per-tick WorldFrame:GetNumChildren / GetChildren scan
- Delete IsNamePlate() border-texture filter (events only deliver
  nameplate frames)
- Delete the guidRegistry table + its OnShow/OnUpdate maintenance;
  every lookup now goes through C_NamePlate.GetNamePlateForGUID
- Move per-GUID cache cleanup (debuffCache / threatMemory /
  combatColorCache / libdebuff_casts) from the OnUpdate visibility
  scan to a NAME_PLATE_UNIT_REMOVED handler — fires exactly once
  per unit going out of range
- NAME_PLATE_CREATED drives nameplates.OnCreate; NAME_PLATE_UNIT_ADDED
  sets cachedGuid and drives nameplates.OnShow (so OnCreate no longer
  calls OnShow directly and no longer HookScripts the parent)
- visiblePlateCount uses table.getn(C_NamePlate.GetNamePlates())

Net -64 lines, with a meaningful reduction in per-tick CPU (no more
WorldFrame child iteration + region/texture filter every 50ms).

* nameplates: switch UNIT_ADDED/REMOVED handlers to nameplateN tokens

ClassicAPI's NAME_PLATE_UNIT_ADDED / _REMOVED events now ship the
"nameplateN" unit token as arg1 (matching modern WoW) instead of the
GUID string.

- UNIT_ADDED: resolve plate via C_NamePlate.GetNamePlateForUnit(arg1);
  derive the cache-key GUID via UnitGUID(arg1)
- UNIT_REMOVED: same lookup pattern; compute UnitGUID(arg1) inside the
  handler before the slot recycles (per docs guarantee)

The other six GetNamePlateForGUID call sites (libdebuff aura callbacks,
UNIT_FLAGS_GUID, PLAYER_TARGET_CHANGED, combo-point handler, castbar
frame) stay on the GUID flavor — they receive real GUIDs from other
event paths.

---------

Co-authored-by: Brues <5278969+brues-code@users.noreply.github.com>
2026-05-27 00:40:31 -05:00
Brues 710be52f35 phase 3 removing tbc
Drop the now-vestigial expansion plumbing.

- Delete modules/thirdparty-tbc.lua + its xml Include
- Strip 10 tbc-tagged CreateConfig calls in modules/gui.lua
- Drop the expansion arg from CreateConfig() signature + the disabled-
  entry rendering path that depended on it
- Drop the showdisabled GUI toggle + its default
- Simplify pfUI:RegisterModule / pfUI:RegisterSkin to (name, func) only
- Strip the leading version arg ("vanilla:tbc", etc.) from all 114
  Register call sites
- Delete the pfUI.expansion variable
2026-05-25 18:50:53 -05:00
Brues ba566cdd53 phase 2 removing tbc
Strip dead pfUI.client > 11200 and pfUI.expansion == "tbc" branches now
that vanilla is the only supported client.

- pfUI.lua: hardcode expansion = "vanilla"; collapse force_region matrix
- compat/vanilla.lua, libs/{libcast,libdebuff,libtotem,libunitscan,
  focus}: drop always-false early-returns
- api/unitframes.lua: delete TargetBuffOnUpdate poller + tbc visibility
  and secure-template branches; click-cast keeps only vanilla path
- api/ui-widgets.lua: unconditional EffectiveScale divide
- env/tables.lua: drop unused focus/focustarget pfValidUnits entries
- modules/actionbar.lua: simplify EnablePaging, drop ButtonSwitch/
  petvisibility, unwrap prowl block, single keybind-remap path
- modules/{castbar,chat,cooldown,loot,questitem,totems}: unwrap
  always-true conditionals
- modules/nameplates.lua: cfg-only fake-cooldown gate, unwrap overlap/
  clickthrough + mouselook blocks
- modules/friends.lua + skins/blizzard/friends.lua: maxtab = 4
- skins/blizzard/{help,game_menu,questlog}: drop tbc-only branches
2026-05-25 18:40:17 -05:00
Brues 1d27f7bed3 class color cleanup 2026-05-23 02:56:00 -05:00
Brues b18e6ffa67 refresh buff durations on player 2026-05-21 02:35:46 -05:00
Meow 6fb45b3971 nameplate fixes
- fixed raidicon to bug out if nameplates for specific unit types are hidden
- fixed raidicon to NOT be behind the nameplate when nameplates are shown
2026-04-04 00:28:11 +02:00
Meow d1692288f4 raid icon fix 2026-04-03 01:15:25 +02:00
Meow a0e3fbb00d taking over nameplates.lua from experiment branch 2026-04-02 06:07:50 +02:00
Meow 22968b6c23 added back throttle control for players in pfui 2026-04-02 04:55:29 +02:00
Meow 136aca02c5 Performance update for nameplates: optimize update loop, combat detection and debuff rendering
- Decouple OnValueChanged from OnDataChanged to prevent expensive
  full updates on every HP tick

- Replace UnitAffectingCombat(guid) with GetUnitField(flags) bitcheck
  and add 0.2s per-GUID throttle cache for GetCombatStateColor

- Gate HP bar SetMinMaxValues/SetValue and text formatting behind
  hp/hpmax change detection

- Inline castbar update into per-plate OnUpdate loop, remove dedicated
  castbarFrame overhead

- Switch debuff slot cache from name-keyed to slot-index-keyed to fix
  timer reset bug when debuffs shift after expiry

- Add raidGuidCache (rebuilt on RAID_ROSTER_UPDATE/PARTY_MEMBERS_CHANGED)
  for O(1) offtank target-name lookup

- Add UNIT_FLAGS_GUID event support for instant combat flag notification
  (Nampower)

- Extract RebuildOfftanks() to ensure offtanks table is populated at
  startup, not only on config change

- Reuse childs table across scan ticks to reduce GC pressure

- Add zoominstant config option to skip zoom animation

- Add combatColorCache cleanup on plate hide and combat leave

Please report any bugs that appear after this change, since it is a huge change.
2026-04-02 04:15:18 +02:00
Meow aa2cb95ec2 Several changes
Fix stale debuff icons/tooltips on target frame after target swap
Fix debuffs not showing on nameplates for timer-less spells (e.g. Hurricane)
Fix buffwatch timer visually speeding up when another debuff fades
Remove 50ms aura cache (slotMapCache/auraFC) - caused stale debuff data
Remove "Show Only Own Debuffs" from unitframes and nameplates GUI
Force selfdebuff=0 for unitframes/nameplates on login to reset old SavedVariables
2026-03-31 19:51:36 +02:00
Meow 88c8968158 Adjusted raidicons to be in FRONT of the health bar, not behind it 2026-03-31 02:52:00 +02:00
Meow 491fcd51c8 New option to pick Original or pfui raid marks! 2026-03-31 02:20:53 +02:00
Meow 91590b5025 Changed the raid icons to use the original Blizzard icons! 2026-03-31 01:43:05 +02:00
Meow 77f50fbf9b possible fix for timers vanishing on nameplates. 2026-03-30 16:20:42 +02:00
Meow c1c9b4b55e fixed castbar being not smooth for some rare case players on nameplates 2026-03-29 01:30:47 +01:00
Meow f43b7c7342 changed nameplate castbars to look more smooth 2026-03-26 13:30:48 +01:00
acid9000 637970bd66 Update nameplates.lua - raid icons always visible
<img width="660" height="441" alt="20260323 raid icon persist example" src="https://github.com/user-attachments/assets/095243fe-9904-4cf5-b210-4857aaa945ec" />


Changing parent from nameplate.health to plate allows raid icons to be shown even when nameplate health bar isn't shown. 

Particularly useful if you have friendly nameplate healthbars disabled and friendlies have raid marks (e.g. tanks, marked player to stack on, etc)
2026-03-24 15:41:17 -04:00
Meow c04d795704 possible fix for nameplate debuffs not showing up 2026-03-23 12:57:38 +01:00
Meow 2ef9c5ee1e Refactor nameplate cast tracking to be fully GUID-based
Problem:
Since a recent Turtle-WoW update, nameplates would show the same castbar on all mobs sharing a name (e.g. multiple "Defias Rogue Wizard"). Additionally, a targeted mob that was not casting would incorrectly display the castbar of a nearby mob with the same name.

Changes:
**`modules/nameplates.lua`**
- Removed `hasNampower` version-sniffing entirely. Nampower is a hard requirement for pfUI; all related guards have been removed and the code runs unconditionally.
- Castbar lookup now always uses `nameplate.cachedGuid` directly — never `GetUnitGUID("target")` or a unit name string.
- Removed dead fallback block using `UnitCastingInfo("target")`.
- Restored fallback via `pfGetCastInfo(cachedGuid)` / `pfGetChannelInfo(cachedGuid)` (see libcast changes below) for casts not tracked by libdebuff (e.g. already-in-progress casts on login).

**`libs/libcast.lua`**
- Renamed `UnitCastingInfo` → `pfGetCastInfo` and `UnitChannelInfo` → `pfGetChannelInfo` to avoid confusion with the Blizzard API of the same name, which does not exist in Vanilla.
- Name-based fallback lookup (`libcast.db[unitName]`) is now skipped when a GUID is available. This prevents cast bleed between mobs that share a name.

**`libs/libpredict.lua`, `modules/castbar.lua`, `modules/afkcam.lua`**
- Updated all call sites to use the renamed `pfGetCastInfo` / `pfGetChannelInfo`.
2026-03-23 10:47:42 +01:00
Meow cd4a3343cb Revert "this should fix no-target mobs casting with the same name"
This reverts commit 35ec17d9a0.
2026-03-22 17:07:52 +01:00
Meow 35ec17d9a0 this should fix no-target mobs casting with the same name 2026-03-22 17:06:18 +01:00
Meow 68ff49be24 fixed castbar for channeling units 2026-03-22 10:38:53 +01:00
Meow aced71a75f full control over castbar nameplate throttle 2026-03-22 01:29:10 +01:00
Meow f6d0cf7ba1 added a 100fps throttle for nameplates internally 2026-03-21 13:31:01 +01:00
Meow a7bfff5d33 Added new throttle option for nameplate castbar 2026-03-21 08:05:45 +01:00
Meow 4fb4035f0c fixed a rare case where debuffs not been shown for nameplates 2026-03-04 03:02:26 +01:00
Meow 3922d9879e fixed typos and cleaned up comments 2026-03-02 19:13:45 +01:00
Meow c7aca0de99 GUID replacements
* Replace all `local _, guid = UnitExists(unit)` with `GetUnitGUID(unit)` (Nampower 3.0.0+)
* Bump minimum required Nampower version to 3.0.0
2026-03-02 10:41:49 +01:00
Meow cfbc1644fe removed superwow checkups, not required anymore
removed superwow checkups, not required anymore
2026-02-28 21:47:19 +01:00
Meow bd36d91189 added option to show debuffs only for enemys OR friendly nameplates
added option to show debuffs only for enemys OR friendly nameplates
2026-02-28 21:32:17 +01:00
Meow 988dfc7079 fix for nameplates and castbars
Removed SuperWoW dependency from castbar and nameplate cast detection. Cast interrupts (sidestep, spell failed) now correctly stop the castbar by setting event = "FAIL" / event = "CAST" on the libdebuff cache entry instead of nil-ing it — preventing stale local references from keeping the castbar alive. UnitCastingInfo fallback is retained for non-Nampower environments but no longer overrides Nampower cast state.
2026-02-28 10:18:30 +01:00
Meow 236a2fce6c perf/fix: port experimental optimizations + focus rework + raidmarkers
Performance optimizations ported from experimental:
- libdebuff: replace 5s startup timer with next-frame defer
- libdebuff: use arg6 auraSlot directly (Nampower 2.29+) instead of GetDebuffSlotMap lookup
- libdebuff: invalidate slotMapCache on PLAYER_TARGET_CHANGED
- nameplates: detect Nampower 2.27.2+ for GUID-based nameplate lookup

Raidmarkers module ported from experimental:
- added raidmarkers.lua
- added config defaults and GUI section
- registered in modules.xml

focus.lua rework:
- removed CastSpellByNameNoQueue (Nampower's CastSpellByName now supports unit tokens/GUIDs natively)
- /focus Name: TargetByName with correct previous target restore + ClearTarget() fallback
- /focus Name: prefix match via SlashCmdList.TARGET when exact match fails
- suppress UI_ERROR_MESSAGE during targeting attempts

swingtimer fixes:
- non-Hunter ranged bar now fills left->right like MH/OH
- fix 1px artifact on Hunter bar center by using Hide() instead of SetWidth(0.1)
2026-02-22 19:08:37 +01:00
Meow 7165be5636 fix for nameplates sometimes not showing casttimes of mobs
fix for nameplates sometimes not showing casttimes of mobs
2026-02-18 13:37:40 +01:00