Commit Graph

70 Commits

Author SHA1 Message Date
Brues b7c3fe5333 Filter unit events with RegisterUnitEvent
ClassicAPI's RegisterUnitEvent registers for an event but only delivers it
when arg1 is one of the given units, so a handler for one unit stops waking
for every other one in the world. Convert the 26 registrations whose unit set
is fixed and known at registration time.

The rule throughout is register the superset and keep the handler's own
check: the filter narrows what arrives, it does not decide what to act on.
castbar is the case that matters -- the player's own casts only ever fire
arg1=="player", never "target"/"focus", so the target and focus bars must
register "player" too, and their UnitIsUnit test is what still rejects a
"player" event while you are targeting a mob.

Two that are not one-line swaps:

  actionbar's two unit events are keys in tables that also drive dispatch, so
  they cannot leave the tables -- and they cannot be plain-registered first,
  because a registration keeps its kind and RegisterUnitEvent over a plain
  one stays plain. They route through a small event_units map instead.

  swingtimer's UNIT_DIED carries a GUID, not a token. The filter is a plain
  case-insensitive string compare with no GUID resolution, so the player's
  own GUID -- fixed for the session -- filters it exactly.

Guards that are now unreachable stay put: the filter applies only when arg1
is a string, so an event that ever fires with a number or no argument is
delivered as if plainly registered, and the handler's own test is what still
rejects it.

Left alone: api/unitframes.lua (the frame's unit changes at runtime and the
handler also matches on GUID), nameplates' six nameplateN events, libdebuff
and libpredict's UNIT_HEALTH (genuinely any unit), and raid.lua's UNIT_PET
(any raid member can own the pet).
2026-09-09 13:24:17 -05:00
Brues 8796fab6d8 libpredict: predict incoming heals for built-in click casting (#44)
Built-in click casting drives the cast through secure frame attributes,
bypassing the CastSpell/CastSpellByName/UseAction hooks that populate
spell_queue -- so the heal-prediction lookup in the SPELL_START_SELF
handler missed and no incoming heal showed.

Populate spell_queue from the cast's own rank-specific spellId (via
C_Spell.GetSpellName/GetSpellSubtext) right before the cache lookup, so
prediction works regardless of how the cast was initiated. Deriving the
rank from the actual spellId also fixes stale-rank lookups when a prior
keybind cast left a different rank of the same spell queued.
2026-08-24 21:37:41 -05:00
Brues b6931359b0 Use the real UKNOWNBEING global in libpredict guards
The 1.12 client defines Blizzard's own misspelling, UKNOWNBEING
("Unknown Being"); UNKNOWNBEING does not exist and resolves to nil, so
both guards never matched. Point them at the real global.
2026-08-10 01:13:47 -05:00
roby-brok e017dbf515 Fix guards, cache keys and comparisons that never match (#40)
* chat: detect whispers before the timestamp is prepended

Whisper detection tests for the whisper colour code at position 1, but the
timestamp is prepended first, so with timestamps enabled the code is no longer
at position 1 and every whisper failed the test -- losing both the recolour and
the correct chat-history entry.

(cherry picked from commit 4b69d597631c422d9360a94ff129323288a28cc2)

* macrotweak + libpredict: inverted install guard, misspelled globals

macrotweak: _AddHistoryLine is the backup slot this block creates, so it is nil
until line 18 runs. Guarding on its truthiness meant the chat-history filter
never installed at all -- macro calls kept landing in chat input history.

libpredict: UKNOWNBEING / UNKOWNBEING are misspelled, so both resolve to nil and
the guards never matched the real UNKNOWNBEING. Neutral if the global is absent
on this client, correct if present.

Not needed: his libpredict already fixed the always-true
'event == "A" or "B"' condition (libs/libpredict.lua:828).

(cherry picked from commit 4068110dc4134823f1c09f60ca5f8959302cd14f)

* mapreveal: look the explore cache up by the key it is actually stored under

explorecaches is keyed by the plain area name (line ~160), but the hover frame
carried only a decorated 'mapFileName (area)' display string, so every lookup
missed and the hover highlight never fired. Store the plain name alongside it
and key off that; the tooltip keeps the decorated string.

(cherry picked from commit 5e6fe969a03a88c68e28614548b9d44db562ab9a)

* socialmod: don't clobber the friend-online match with the offline one

The offline match was assigned unconditionally over the online match, so a
friend coming online never had lastseen recorded.

(cherry picked from commit ad927806c46042163f84bde4db1082726bedf28b)

* swingtimer: off-hand weapons are inventory type 22, not 21

The off-hand slot accepts one-hand (13) and off-hand (22) weapons. Type 21 is
INVTYPE_WEAPONMAINHAND and can never be equipped there, so the off-hand swing
timer never recognised a real off-hand weapon.

The other two swingtimer fixes are not needed here: his hunter check already
uses UnitClassBase (locale-independent, better than our UnitClass second
return), and his generic on-next-swing detection covers Raptor Strike without
our hardcoded spell-id list.

(cherry picked from commit 9ab7f5f7224d12361ca6cd5a49181cbb4bebd387)

* superwow: compare the version numerically, not by exact string

SUPERWOW_VERSION == "1.5" silently disables the GUID-to-name combat text hook
on any release past 1.5. Currently 1.5 here, so this is forward-compat only.

Not needed: the clickthrough slash commands already go through
RegisterSlashCommand, which writes _G properly.

(cherry picked from commit 82a37752a5782479849ce7e1304c24733c2ff97a)

* api: measure a real pixel against UIParent, not the uiScale cvar

The uiScale cvar caps at 1.0 while both the pixelperfect module and the
firstrun slider push UIParent past it via SetScale, and it is ignored entirely
while useUiScale is off, so borders came out the wrong thickness on the
Huge/Large presets. Ask the frame for its effective scale instead, and guard an
unparseable gxResolution.

Also cache GetItemLinkByName and count its failures: the scan walked every id
on each call with no memory, so an unresolvable name hitched on every tooltip
hover. Raise the ceiling from 25818 to 61000 as well -- Octo/Turtle custom
items live well past the vanilla range and never resolved.

(cherry picked from commit dac2d3416aef85a4c4b71c0239d93d309e76e30b)

* init: load pixelperfect first so GetPerfectPixel caches the right scale

pixelperfect sets the UI scale that GetPerfectPixel measures against, and that
value is cached on first use. Loading it 56th baked in the previous scale.

(cherry picked from commit dd89a210330583f890a51a82b29e968f3ad36b34)

* modules: route two global overrides through _G so they leave the sandbox

pfUI.env has __index but no __newindex, so a bare global assignment inside a
RegisterModule closure is written into the sandbox table and never reaches _G.
unitxp's BattlefieldFrame_Show override therefore never fired the BG queue-pop
notification, and RaidFrame.lua never saw GROUP_REPLACE_PARTY.

The slash-command half of this fix is not needed here: RegisterSlashCommand
already writes through _G.

(cherry picked from commit 617c8320aca2465af62cf0ff5be7dceaed29a3b2)

* bags: remove the duplicate search OnHide handler

Two byte-identical frame.search OnHide handlers were installed back to back;
the second overwrote the first, so the first was dead code.

(cherry picked from commit e77650448b92e5d7f18ae58632e4531cb2813ea6)

* buffwatch: invalidate the filter cache when a skill is listed

fcache is built once per config table and never cleared, so ctrl/shift-clicking
a skill onto the whitelist or blacklist had no effect until the next reload.

* roll: actually capture the everyone-passed subject

strfind(LOOT_ROLL_ALL_PASSED, LOOT_ROLL_PASSED) has no captures, so `everyone`
was always nil, never reached the blacklist, and "Everyone has passed on: X"
was recorded as a real player passing.

Builds a sample from LOOT_ROLL_ALL_PASSED and runs the same LOOT_ROLL_PASSED
match the scanner uses, so the subject is captured the way it will actually
appear.
2026-08-10 01:13:32 -05:00
Brues 00292ca3b4 Focus/Nameplates now respond solely to UNIT_* events
commit 70b1e66c2d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sun Jul 26 18:30:18 2026 -0500

    Use SetSize/SetShown and simplify minimap/map

commit 7b6bfe9975
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 11:27:14 2026 -0500

    Include raidpet frames in /pftest test mode

    The unit-frame test toggle (showall) only previews frames that exist and
    are positioned. Raidpet frames are created when raidpet.visible == "1",
    but LayoutPets' collapse mode only positions pets whose raidpet<N> unit
    actually exists, so solo/in test mode they stayed hidden.

    Add a showall branch to LayoutPets that mirror-lays every pet cell and
    shows it (bypassing collapse and the roster gate), still guarded by the
    existing showpets check so nothing happens when raidpet is disabled. Call
    LayoutPets from the /pftest handler so the grid updates immediately on
    toggle-on and restores to the normal layout on toggle-off.

commit 4c65c38647
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:34:33 2026 -0500

    Remove unused RangeCache local in UnitInRange

commit 6c96bbbe6c
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:34:33 2026 -0500

    Use Clamp() for the two-sided clamps in ui-widgets

    Replace the hand-rolled math.min/math.max and if/elseif clamp idioms in the
    status bar and scroll frame with Clamp(). Equivalent for every value seen
    (min <= max always holds), just clearer.

commit 830e0a0be1
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:34:33 2026 -0500

    Drop vanilla GetItemInfo shim for C_Item.GetItemInfo

    The compat/vanilla.lua GetItemInfo override reshaped vanilla's tuple into
    retail order by inserting nil at slot 4 (itemLevel), but truncated at 8
    fields, dropping itemEquipLoc/itemTexture. ClassicAPI's global GetItemInfo
    keeps the vanilla shape (its hook only warms the item cache), so the shim
    stayed necessary but incomplete.

    Remove it and point the three callers at ClassicAPI's C_Item.GetItemInfo,
    which returns the full 18-field retail tuple. Positions 1-8 are identical
    to the old shim output, so bags/roll are unchanged; character.lua's
    itemSlot (equipLoc, field 9) was always nil under the truncating shim and
    now resolves correctly for ShaguScore.

commit c0da63657d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:09:34 2026 -0500

    Various cleanup

    Removes version compatibility checks for TBC/Vanilla, consolidating code to target a single WoW version. Refactors repetitive SetWidth/SetHeight calls to SetSize for cleaner code. Removes duplicate function definitions from unitxp module and simplifies conditional show/hide operations using SetShown.

commit 11a6302c2d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 09:53:37 2026 -0500

    Delegate pfUI.api.strsplit to ClassicAPI's strsplit

    Replace the Lua pattern-based implementation with a thin wrapper around
    ClassicAPI's C-level strsplit. Keeps the pfUI.api.strsplit entry point for
    backwards compatibility with addons that call it, while dropping the
    redundant reimplementation.

    Behavioral note: the old version used ([^delim]+) which silently collapsed
    empty fields; delegating to real strsplit now preserves them
    ("a,,b" -> "a", "", "b"). All in-repo callers split numeric color tuples,
    version strings, or build name-keyed lookup tables, none of which are
    affected by empty-field preservation.

commit 67c126eac8
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 01:01:02 2026 -0500

    Bump ClassicAPI minimum version to 1.8.0

commit a6cf157518
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 00:49:50 2026 -0500

    read spell rank via C_Spell.GetSpellSubtext

    The rank string comes from the spell subtext ("Rank N"), which ClassicAPI's
    C_Spell.GetSpellSubtext returns directly -- so drop nampower's
    GetSpellRecField(spellId, "rank") here. The existing "Rank " gsub parse is
    unchanged.

commit 4b1ba99b4f
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 00:33:20 2026 -0500

    Move player info overlay onto ClassicAPI (drop Nampower)

    The haste/spell-power overlay read both values through Nampower and disabled
    itself entirely without it. Move both to ClassicAPI so it works on any
    ClassicAPI client:

    - Spell power: GetSpellPower("net") (nampower) -> GetSpellBonusDamage(i)
      (ClassicAPI, same per-school field). Merged the build+scan into one loop;
      the default school seeds the tiebreak so equal schools still favor it.
    - Haste: GetUnitField("player", "modCastSpeed") -> UnitSpellHaste("player"),
      which returns the haste percentage directly (the (1/modCastSpeed-1)*100
      conversion is now baked in, off the same UNIT_MOD_CAST_SPEED field, signed).
    - Dropped the "if not GetUnitField then return" gate -- UpdateInfoText no
      longer touches Nampower, so the overlay runs everywhere.

commit 7df4aa6d50
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 00:32:44 2026 -0500

    Hook the real global _G.UnitHealth for feign death

    Inside a RegisterModule body, `function UnitHealth(...)` defines UnitHealth on
    the pfUI environment, not the real global -- so the feign-death real-HP fix
    only reached callers that resolve UnitHealth through pfUI's env, and missed
    _G consumers (Blizzard frames, other addons). Hook _G.UnitHealth explicitly
    (and capture oldUnitHealth from _G) so the un-gate applies everywhere.

commit b0bf2fd869
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 21:10:58 2026 -0500

    Refactor nampower module

    Simplify reactive spell storage by using spell IDs instead of texture/name tables. Update to use modern C_Spell APIs (GetSpellTexture, GetSpellName) instead of manual texture paths. Consolidate SetWidth/SetHeight calls to SetSize and use print() instead of DEFAULT_CHAT_FRAME:AddMessage().

commit 0b06961333
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 20:54:23 2026 -0500

    Use GetNamePlateForUnit for target lookups; drop dead ScanGuid block

    - Replace the three GetNamePlateForGUID(UnitGUID("target")) round-trips with
      GetNamePlateForUnit("target"), which resolves the token to a GUID internally
      -- no UnitGUID string detour, and it returns nil for no-target/no-plate so
      the UnitExists guards collapse. GetNamePlateForGUID is left for raw-GUID cases.
    - Remove the dead libunitscan.ScanGuid nameplate block (ScanGuid was deleted
      from libunitscan long ago, so the guard was never true) -- it carried the
      last GetUnitField("npcFlags") read.

commit 3e6210086e
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 20:54:23 2026 -0500

    Drop Nampower stats system and polling from unit frames

    GetUnitStats now reads health/power straight from UnitHealth/UnitPower
    (the descriptor fields the server broadcasts) -- for a real unit token
    GetUnitField read nothing different, so the whole Nampower-vs-fallback
    apparatus was measuring a distinction that no longer exists. Removed:

    - The stats system: pfUI.uf.stats, pfUIStatsFrame + UpdateStatsDisplay, the
      lastUnitStats change-cache, the /pfuistats slash command, and every counter
      increment (event/heartbeat/earlyReturn/throttledSkip/nampower/fallback).
    - All GetUnitField health reads (GetUnitStats, heal-prediction, health-gradient
      color) -- collapsed to the UnitHealth/UnitHealthMax they already fell back to.
    - The heartbeat-polling backstop and its fallbackThrottle/lastEventUpdate deps.
      Frames now refresh on events only; eventless frames still use their own tick,
      and range/aggro still run in the eventless-actions block.

commit 63001b7b0c
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 20:09:42 2026 -0500

    Move nameplates onto ClassicAPI stable nameplate tokens

    ClassicAPI now assigns retail-exact, per-plate-stable "nameplateN" tokens and
    fires vanilla UNIT_* events for them, so the nameplate module can key off the
    token instead of Nampower/SuperWoW GUID primitives:

    - Events: UNIT_AURA_GUID/UNIT_FLAGS_GUID -> UNIT_AURA/UNIT_FLAGS, matched by
      the "nameplateN" token (guarded on the token prefix, since these also fire
      for target/party/raid). Registered unconditionally -- no GetUnitField gate.
    - Health: GetUnitField(guid, "health"/"maxHealth") -> UnitHealth/UnitHealthMax
      on the plate's cached token. Same UNIT_FIELD_HEALTH the server broadcasts
      (real HP on Turtle; the ~= 100 scaled-vs-real guard is unchanged).
    - Combat/target in GetCombatStateColor: GetUnitField("flags") + HasFlag ->
      UnitAffectingCombat(token); GetUnitField("target") + SuperWoW "<guid>target"
      -> the "nameplateNtarget" chain. Dropped the now-dead HasFlag,
      UNIT_FLAG_IN_COMBAT, and guidTargetTokenCache.
    - GetCastInfo now takes the token directly; every caller already holds it, so
      the UnitTokenFromGUID(guid) round-trip is gone (unused module-wide now).

    NAME_PLATE_UNIT_ADDED caches the token as plate.nameplate.unit alongside the
    GUID; REMOVED clears both. GUID is retained only as the stable cache key
    (debuffCache/threatMemory/combatColorCache). Only GetUnitField("npcFlags")
    remains -- it has no token/vanilla equivalent.

commit ce1c49fcbb
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 18:20:06 2026 -0500

    Make focus/focustarget event-driven via ClassicAPI unit events

    ClassicAPI now fires UNIT_* (health/mana/aura/...) with arg1 == "focus" and
    arg1 == "focustarget", observed per-unit like target/party/raid. Both frames
    already registered those events (focus/focustarget are in pfValidUnits) and
    their OnEvent already matches arg1 == label, so the 0.2s polling ticks were
    pure workarounds for the missing events. Drop both ticks; the frames now
    refresh on-event like target, with range/glow still on the shared 0.5s state
    pass and PLAYER_FOCUS_CHANGED still driving assign/clear.
2026-07-26 18:32:36 -05:00
Brues 7389c241a4 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
2026-07-11 09:47:46 -05:00
Brues 13a08b0ea3 Restore hooksecurefunc 2026-07-09 23:01:52 -05:00
Brues ee7c729bcb remove select 2026-07-07 09:16:33 -05:00
Brues 3fe072c594 Route hooksecurefunc callers through pfUI.hooksecurefunc; global belongs to ClassicAPI
pfUI's Lua hooksecurefunc lived in pfUI.env and shadowed ClassicAPI's C
global for all pfUI code. Replace it with a thin pfUI.hooksecurefunc shim
that keeps the missing-target no-op our call sites rely on (ClassicAPI
errors on a nil target) and delegates the actual hook to _G.hooksecurefunc.

Migrated all 70 internal call sites (modules/libs/skins) to
pfUI.hooksecurefunc; bare hooksecurefunc now resolves to ClassicAPI's C
version everywhere. Dropped the unused prepend path and the orphaned
pfUI.hooks table.
2026-07-05 14:58:26 -05:00
Brues 9706a74d16 UNIT_INVENTORY_CHANGED -> PLAYER_EQUIPMENT_CHANGED 2026-07-05 14:32:25 -05:00
Brues fc75e091a4 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.
2026-06-27 18:56:50 -05:00
Brues 760d8992b6 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.
2026-06-27 18:54:04 -05:00
Brues 62a99ac410 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.
2026-06-27 18:41:11 -05:00
Brues deeec89955 predict + libdebuff + swingtimer: drop hardcoded spell data
Replace per-locale name tables and per-rank ID lists with single
canonical-rank lookups through C_Spell. Spell.dbc bits hoisted to
named constants at module top.

libpredict:
- Four 7-locale tables (PRAYER_OF_HEALING / REJUVENATION / RENEW /
  REGROWTH) collapsed to one C_Spell.GetSpellName(rank1id) call each.
- 25-entry SPELL_IDS (all ranks of Rejuv + Renew) for SPELL_GO_SELF
  HoT detection replaced by name comparison against REJUVENATION /
  RENEW. No per-rank ID maintenance.

libdebuff:
- GetSpellRecField(id, "name") → C_Spell.GetSpellName(id) at all call
  sites; the presence-guard pattern is gone (ClassicAPI is a hard
  dep, per memory).
- GetSpellRecField(id, "rank") → C_Spell.GetSpellSubtext(id).

swingtimer:
- Hoist FLAG_AUTOATTACK / ATTR_KEEP_SWINGS / ATTR_ON_NEXT_SWING to
  module-top constants via tonumber("0xNN", 16) so the SPELL_GO_SELF
  hot path stops re-parsing them on every call. Lua 5.0 has no hex
  number literals; strtoul-backed tonumber handles the "0x" prefix.
2026-06-27 18:22:03 -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 d6951b386e unitframes/buffwatch/libpredict: route aura reads through C_UnitAuras
ClassicAPI's recent C_UnitAuras additions (sourceUnit / sourceGUID /
non-player expirationTime / the PLAYER filter token) finally cover
everything libdebuff:UnitDebuff and :UnitOwnDebuff were doing — caster
attribution, accurate timing for non-player units, and the own-debuffs
filter. Migrating the remaining callers off the libdebuff readers.

- api/unitframes.lua: collapses the debuff render path's three-branch
  if/else into a single C_UnitAuras.GetAuraDataByIndex with a HARMFUL
  or HARMFUL|PLAYER filter selected by the selfdebuff config; tooltip
  slot-finders match by sourceGUID instead of libdebuff's caster flag;
  custom-debuff indicator scan unifies the same way.
- modules/buffwatch.lua: GetBuffData drops the libdebuff fallback;
  tooltip slot-finder mirrors the unitframes pattern.
- libs/libpredict.lua: drops the orphaned UnitHasBuff slot-loop (no
  callers left).
- api/api.lua: pfUI.api.UnitHasBuff tightens from a HELPFUL iteration
  to a single GetAuraDataBySpellName lookup.

Each site that builds a cooldown ring from expirationTime carries the
talent-extension guard — when expirationTime exceeds the dbc base
duration (e.g. Shadow Affinity → SW:P), clamp start to now and use the
remaining time as the effective duration so CooldownFrame_SetTimer
doesn't get a future start it treats as "not yet begun".
2026-06-24 22:41:13 -05:00
Brues 2f17546c1a UseAction hooks: GetActionInfo + GetMacroSpell, drop tooltip scans
The three UseAction hooks in libtotem / libpredict / libcast all did
the same dance: filter out macros via GetActionText, then tooltip-scan
the action to recover the spell name + rank. ClassicAPI's
GetActionInfo + GetMacroSpell make both steps unnecessary:

- GetActionInfo returns ("spell", spellID) or ("macro", macroSlot)
- GetMacroSpell resolves a macroSlot to (name, rank, spellID) at the
  highest known rank, parsed engine-side at macro save time

So macros are no longer skipped — they resolve to their cast spell
just like a raw spell action. libtotem queue gains a real spellID
(the previous "no spellId available, icon-based fallback" comment is
obsolete). libcast also wins: it can feed the resolved spellID
through FindSpellBookSlotByID + libspell.GetSpellInfo(slot, "spell")
without the name-with-rank-suffix string concat round-trip.

Drops libtipscan:GetScanner("prediction") usage in libtotem and
libpredict, and libtipscan:GetScanner("libcast") in libcast.
2026-05-21 16:45:57 -05:00
Brues b18e6ffa67 refresh buff durations on player 2026-05-21 02:35:46 -05:00
Meow 0ef3bd0148 fixed a bug where targeting an offline player predicted heals on them 2026-04-11 21:49:54 +02:00
Meow 10dee38b0f libpredict
Fixed heal prediction showing on hostile targets when healing friendly units via mouseover or click-to-cast
2026-04-03 05:32:55 +02:00
Meow cc11831ada fixed heals being shown as prediction on hostile targets. 2026-03-30 16:21:25 +02:00
Meow b041a16744 Update libpredict.lua 2026-03-25 10:57:47 +01:00
Meow 80fe64e997 advanced libpredict 2026-03-24 18:40:58 +01:00
Meow aa73e60372 prayer of healing fix - now always predicts the priests group/target 2026-03-24 12:35:56 +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 f5d2c48933 more fixes for heal predictions
more fixes for heal predictions
2026-03-03 08:29:00 +01:00
Meow c8500efae9 fix for heal predictions with healcomm users
fix for heal predictions with healcomm users
2026-03-03 00:43:24 +01:00
Meow e939f1f96a added debug message
added debug message
2026-03-02 13:33:49 +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 c16e0c7c38 libpredict comment changes
Changed my german comments to english comments =D
2026-03-02 08:54:37 +01:00
Meow 3fbce5be8f libpredict.lua changes!
* Removed SuperWoW dependency (UNIT_CASTEVENT removed)
* Replaced SPELLCAST_START/STOP/FAILED/INTERRUPTED/DELAYED with Nampower equivalents (SPELL_START_SELF, SPELL_GO_SELF, SPELL_FAILED_SELF, SPELL_DELAYED_SELF)
* Replaced CHAT_MSG_SPELL_SELF_BUFF text parsing with SPELL_HEAL_BY_SELF for accurate heal amounts including crit detection
* Routed SPELL_START_SELF/OTHER, SPELL_GO_SELF/OTHER, SPELL_FAILED_OTHER through existing libdebuff hook system to avoid duplicate event registration
* Added 60-second resurrection timer: symbol persists after successful cast even if caster attempts and cancels a second cast
* Added GUID->Name cache for reliable target resolution when casting resurrection on dead players (UnitExists returns nil for corpses)
* Auto-enables NP_EnableSpellHealEvents CVar required for SPELL_HEAL_BY_SELF
2026-03-02 08:51:23 +01:00
Meow f1048bd7bb Revert "possible fix for libpredict to not show resses that are canceled."
This reverts commit 947b11f918.
2026-02-20 20:25:16 +01:00
Meow 947b11f918 possible fix for libpredict to not show resses that are canceled.
possible fix for libpredict to not show resses that are canceled.
2026-02-20 19:03:28 +01:00
Meow 9055dad52f fixed healcomm and libpredict not sharing same stop messages
fixed healcomm and libpredict not sharing same stop messages
2026-02-20 04:38:05 +01:00
Meow 8248e4ed91 possible fix for healpredicts with queued casting
possible fix for healpredicts with queued casting
2026-02-18 22:45:07 +01:00
Meow 3cf64ceffd string.find fix - missing parameters, thanks to jrc13245
string.find fix - missing parameters, thanks to jrc13245
2026-02-16 05:52:42 +01:00
Meow f7bcad6266 fixed a typo
fixed a typo
2026-02-11 19:41:44 +01:00
Meow b2fc8a73b1 fixed libpredict not showing own heals/resses
- Thanks at liiora for reporting this.
- Short explain, the new libpredict uses nampower for it's prediction, in all my tests i had a lots of debug messages added to track if everything works. Seeing my own messages twice i assumed, i can improve the performance by ignoring "player".  This also bugged the self-prediction because now your own abilitys were ignored. (FIXED NOW)
2026-02-10 08:51:00 +01:00
Meow f43b8f19f8 update for libdebuff
Read the readme!
Version push
2026-02-06 16:32:13 +01:00
Meow 37beca7103 New throttling menu
New throttling menu
2026-02-06 08:07:33 +01:00
Meow 54355c9019 enhanced merge into master
Final release!
2026-02-04 22:48:30 +01:00
Meow 10a1def220 4 possibles fixes.
1. Healpredict working properly together with Healcomm users.
2. Hots duration timers shared across all pfui users in the raid/group
3. Fix for nameplates vibrating when zoom is activve.
2026-01-10 00:37:23 +01:00
Meow 5d0e195d1e performance update
performance update
2026-01-03 12:58:31 +01:00
shagu 2e5ed4d7e7 libpredict: use selfcast if addons set true as target 2025-08-16 09:56:39 +02:00
shagu 73561eda4a compat: make hooksecurefunc append by default 2025-07-30 20:18:52 +02:00
shagu 32b14706f8 libpredict: update renew set bonus duration 2025-05-25 17:05:51 +02:00
shagu 060f8de940 libpredict: increase default renew duration to 15 2025-05-25 14:49:36 +02:00
shagu af2278da6b libpredict: add support for on-self in cast hook 2025-04-20 12:08:25 +02:00
shagu bedd293ce7 libpredict: add support for target arg in cast hook 2025-04-19 23:32:48 +02:00
shagu 925654fe09 libpredict: add fallback target to self 2025-03-28 21:35:01 +01:00