Commit Graph

3779 Commits

Author SHA1 Message Date
Brues 671b7f3574 use C_AddOns.GetAddOnName 2026-05-30 23:18:16 -05:00
Brues 671939fe9e add auto sort on open feature - disabled by default 2026-05-30 00:31:47 -05:00
Brues d1e51e5202 durability panel shows your collective durability 2026-05-30 00:10:12 -05:00
Brues 94aee19967 use pfUI's GetColorGradient instead of Fizzle colors 2026-05-29 23:15:35 -05:00
Brues 23cc286a0c Fixed issue where item durability tooltip was missing items 2026-05-29 23:15:04 -05:00
Brues 841399a0c7 classicapi migration 2026-05-29 22:56:12 -05:00
Brues 07377ad92e rep remaining label 2026-05-29 21:30:43 -05:00
Brues 6af7da55d6 Reputation Frame: Enhance faction standing bars 2026-05-29 18:49:38 -05:00
Brues ed5ecb1f93 character: durability % per inventory slot
Adds a Fizzle-style durability label to each character pane slot.
Renders at the bottom of the slot icon as "N%" colored by the existing
DURABILITY_THRESHOLD_COLORS table (red < orange < yellow < invasion <
green), or hidden when the item has no durability stat (necks, rings,
trinkets) or the slot is empty.

api/api.lua: new pfUI.api.CreateFontString(f, key, layer, size, flags,
font) helper following the CreateBackdrop pattern — idempotent
get-or-create that attaches the FontString to the parent frame as the
named field. Defaults to pfUI.font_default at C.global.font_size with
OUTLINE on the OVERLAY layer.

skins/blizzard/character.lua: scoreText migrated from the inline
"if not frame.scoreText then ..." block to the new helper as a working
example; new durabilityText created the same way at BOTTOM/size 10.
Durability render added to RefreshCharacterSlot — runs on every
PaperDollItemSlotButton_Update so equip/unequip/repair/damage all
refresh automatically.

api/config.lua + modules/gui.lua: new C.character.inventory.durability
toggle (default "1"). GUI lives under a new top-level "Character" tab
→ "Inventory" sub-tab, leaving room for future "Reputation" / "Skills"
sub-tabs at the same level.
2026-05-29 18:31:58 -05:00
Brues 201a77ccbd IsContainerItemOpenable will now tell us if we can actually open the item 2026-05-29 00:31:53 -05:00
Brues b8da28ebac use IsContainerItemOpenable and bump minimum ClassicAPI version to 1.2.1 2026-05-28 14:59:31 -05:00
Brues f988dff29f no need to show count for unique items 2026-05-28 14:31:09 -05:00
Brues 7c5e4a0e08 add Item Count module 2026-05-28 13:24:50 -05:00
Brues 1fd7895ca7 move away from RAID_CLASS_COLORS dependency 2026-05-28 13:06:00 -05:00
Brues 1a7532195a added !!!ClassicAPI to deps 2026-05-28 12:41:50 -05:00
Brues 9adc57cae6 prevent load if classicapi is not installed 2026-05-28 01:01:53 -05:00
Brues 8e92cf47b3 whitespace 2026-05-28 00:25:05 -05:00
Brues d47287da3a use GetContainerItemCharges from classicapi 2026-05-27 23:50:10 -05:00
Brues 3ef78044fb bags: third-party sort addons rebind existing buttons
pfUI's built-in sorter (modules/bags.lua) always creates the sort
buttons on the right/left bag frames now, so the third-party
RegisterBagSort path's "if not pfUI.bag.right.sort" guard would skip
button-creation entirely — yet still set pfUI.thirdparty.bagsort to
the registering addon's name. Net effect: user installed SortBags or
MrPlow, our internal sort runs anyway. Silent override of user intent.

Strip the dead button-creation paths; rebind the existing buttons'
OnClick + OnEnter to the registered third-party functions instead.
Third-party addons now actually fire when the user clicks. -53 lines.
2026-05-27 23:30:01 -05:00
Brues 9a618e4709 bags: add /pfBagSort + /pfBankSort buttons
Inline the bag sorter from Bagnon/lib/BagSort.lua — two-pointer stack
consolidation, then a category-then-name sort with poor (gray) items
placed back-to-front so they sit at the end of the last bag. Sort
buttons land in the existing button row on both the bag (right) and
bank (left) frames.

Fixes a destructuring mismatch in the port: pfUI's compat/vanilla.lua
shims GetItemInfo to the modern 10-field return signature (inserts nil
for itemLevel between quality and minlevel), so itype/subtype sit at
positions 6/7 — not 5/6 like the Bagnon original assumes against raw
vanilla. Without the extra placeholder every item fell through to the
"non-gear by quality" bucket.
2026-05-27 23:22:32 -05:00
Brues 6cf5ef4468 Update easteregg.lua 2026-05-27 23:11:44 -05:00
Brues b99f650694 Cap rested xp at 113% on turtle wow 2026-05-27 23:11:44 -05:00
Brues ebbafd0478 refresh gametooltip for rested gains 2026-05-27 23:11:44 -05:00
Brues 04f10b0998 Bag Sort 2026-05-27 23:11:23 -05:00
brues-code f0d9dca63f Classic API Focus (#2)
* focus: migrate to FocusUnit / "focus" token / PLAYER_FOCUS_CHANGED

ClassicAPI now polyfills modern WoW's focus system: FocusUnit / ClearFocus
+ "focus" / "focustarget" unit tokens accepted by every UnitX function +
PLAYER_FOCUS_CHANGED event. Drop pfUI's GUID-juggling pseudo-frame.

- env/tables.lua: add "focus" and "focustarget" to pfValidUnits — the
  focus frames now follow the standard event-driven CreateUnitFrame path
  with f.label = "focus"
- modules/focus.lua: rewrite. Slash commands use FocusUnit / ClearFocus
  directly; no more manual frame.label/unitname/id manipulation. /focus
  <name> still does a target-swap to resolve names → units, then
  FocusUnit("target") captures the GUID before the target is restored.
  PLAYER_FOCUS_CHANGED triggers immediate frame refresh on assign/clear.
- api/unitframes.lua: delete the pseudo-focus block (per-tick "scan all
  units for matching name" loop) and the "focus"/"focustarget" special-
  case in the visibility branch — "focus" is now a real token.
- modules/castbar.lua: bind the focus castbar to unitstr = "focus" once;
  drop the OnUpdate that synced pfUI.castbar.focus from
  pfUI.uf.focus.label/unitname. UnitGUID("focus") resolves at read time.
- Drop C_Minimap.SetFocusByGUID / SetFocusByName / ClearFocus calls —
  C_Minimap subscribes to PLAYER_FOCUS_CHANGED on its own.

Net -183 lines. Focus stops being a pfUI-special pseudo-frame and
becomes "just another unit token" — same treatment as target/player.

* add nameplate to valid units

---------

Co-authored-by: Brues <5278969+brues-code@users.noreply.github.com>
2026-05-27 20:35:15 -05:00
Brues f8b4b5b5a3 Delete pfUI-tbc.toc 2026-05-27 19:34:58 -05:00
Brues 0cddd79c55 backwards for compat for external modules that dont know we updated Registering 2026-05-27 19:00:30 -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 aaba09a17c GetContainerItemID directly 2026-05-25 20:22:07 -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 58609b8c5c phase 1 removing tbc 2026-05-25 18:16:02 -05:00
Brues 199842e220 prevent 'npctarget' invalid unit calls 2026-05-23 15:59:09 -05:00
Brues 1d27f7bed3 class color cleanup 2026-05-23 02:56:00 -05:00
Brues 90fdd8cfc3 typo 2026-05-22 22:50:41 -05:00
Brues 7c752f0264 xpbar: rested gain rate in per-minute instead of per-hour
Per-hour numbers are too coarse to feel actionable while watching a
tent fill — switching to /min so the displayed rate updates in a more
useful range for the actual sampling cadence.
2026-05-22 22:48:04 -05:00
Brues c30dfae7a6 xpbar: track rested-XP gain rate + time to cap
The data frame now subscribes to UPDATE_EXHAUSTION and stores a sliding
5-minute window of (time, exhaustion) samples. The XP tooltip uses the
first/last samples in the window to compute rest gain per hour, and
projects time to reach UnitXPMax * 1.5 at the current rate.

Useful for Turtle WoW's tent mechanic — when you stand under a tent
you accumulate rested XP at an accelerated rate, and now you can see
how long until you cap.

Samples reset on PLAYER_ENTERING_WORLD (zone change can change the
gain rate) and PLAYER_LEVEL_UP (Blizzard rescales exhaustion
proportionally on level-up so prior samples no longer describe the
same gain curve).

The rate/time lines only appear when there are at least 2 samples in
the window and the gain is positive — so they stay hidden when not
actively gaining rested XP.
2026-05-22 22:40:35 -05:00
Brues 00a3e2f691 tracking: PlayerIsDruidInCatForm via GetShapeshiftFormID
The byte-2-of-UNIT_BYTES_1 extraction this function did manually
(math.floor(b/65536) - math.floor(b/16777216)*256 on the GetUnitField
return) is precisely what GetShapeshiftFormID reads under the hood —
descriptor +0x212. Collapses to a one-liner that doesn't need to
mirror the engine's byte layout in Lua.
2026-05-21 17:30:39 -05:00
Brues 11f9cd848b tooltip:GetUnit via HasUnit + UnitTokenFromGUID
GameTooltip:HasUnit() / GameTooltip:GetUnitGUID() ask the tooltip
directly what unit it's displaying (returns the GUID), and
UnitTokenFromGUID resolves that to a unit token. So instead of
iterating mouseover/player/pet/target plus party1..4, partypet1..4,
raid1..40, raidpet1..40 and string-matching each against
GameTooltipTextLeft1:GetText(), this is now a three-line lookup.

Bonus: drops the UnitName / UnitPVPName fallback string match (which
broke on duplicate names across the realm and on tooltips showing PVP
titles that didn't exactly match a token's UnitPVPName output). GUID
is canonical.
2026-05-21 17:27:27 -05:00
Brues 2619b0bd77 autovendor: all paths through C_MerchantFrame
Two-part collapse:

Button-click sell path: was a 0.1s-per-item manual iteration via
UseContainerItem (with processed[] tracking + a merchant-state flag +
OnShow/OnUpdate/OnHide handler trio). Now calls SellJunkAndReport
which fires C_MerchantFrame.SellAllJunkItems and a 0.3s deferred
GetMoney delta reporter. Engine handles per-frame sell pacing.

Button enable/disable check: HasGreyItems() iterated bags 0..4 with
C_Item.GetItemQuality manually. Replaced with
C_MerchantFrame.GetNumJunkItems() > 0 (the engine's canonical answer
to the same question). The button's Update only runs from MERCHANT_SHOW
/ MERCHANT_UPDATE handlers so the "merchant must be open" gate on
GetNumJunkItems is always satisfied.

Side effect: the MERCHANT_SHOW auto-sell path NOW reports income to
chat. Previously only the manual button reported it.

Deleted: HasGreyItems, processed/count/gold state, GetNextGreyItem,
autovendor.merchant flag, OnShow/OnUpdate/OnHide handlers, the
MERCHANT_CLOSED branch.

170 → 104 lines.
2026-05-21 17:24:14 -05:00
Brues 802d47312f pfSellData: drop sell column, use C_Item.GetItemSellPriceByID
Each pfSellData entry was a "sell,buy" string. The sell price duplicates
what C_Item.GetItemSellPriceByID returns from the engine's item DBC, so
it's redundant in our table — only the buy price (curated from real
vendor encounters, not a static item property) needs to live here.

Transformed every [id]="X,Y" entry across env/tables.lua, compat/tbc.lua,
and modules/turtle-wow.lua to [id]=Y via sed. Format is now itemid →
buyPrice (number, copper).

sellvalue.lua: reads sell from C_Item.GetItemSellPriceByID(id), reads
buy from pfSellData[id]. Items that have only a sell price (not in
pfSellData) now display sell-only — previously they got no tooltip
addition because the lookup gated on table membership. Items with
buy-only (sell == 0 in old data) still display buy correctly.

autovendor.lua: replaces the pfSellData[id] gate (which only checked
table membership and unused the parsed sell/buy) with a direct
C_Item.GetItemSellPriceByID > 0 check — the engine's canonical
"is this item sellable to a vendor" answer.
2026-05-21 17:19:29 -05:00
Brues d27db55abf modernize monkey-patched hooks to hooksecurefunc
sellvalue.lua: SetItemRef hook follows the same pattern questitem.lua
got earlier — replaces the local-Hook + _G.SetItemRef monkey-patch with
hooksecurefunc, drops the string.find link-parser, and reads itemID
directly from ItemRefTooltip:GetItem after the original populates the
tooltip. The OnShow path also moves from libtooltip:GetItemLink/GetItemID
to GameTooltip:HasItem/GetItem (libtooltip:GetItemCount stays — it's
populated by libtooltip's own SetBagItem hook and carries the stack
count, which GetItem doesn't return).

unusable.lua: the two post-hooks (pfUI.bag.UpdateSlot and
BankFrameItemButton_UpdateLock) are textbook hooksecurefunc cases —
both ran the original then did extra work, no conditional skip or
return-value tampering. The table form of hooksecurefunc handles
pfUI.bag.UpdateSlot cleanly.
2026-05-21 17:04:00 -05:00
Brues cca7d649e1 innervatecall: ResolveTargetName via UnitTokenFromGUID
The 30-line GUID → name resolver (manually checking player, target, then
walking raid1..40 / party1..4 for a matching UnitGUID) collapses to
calling UnitTokenFromGUID and then UnitName on the returned token.
ClassicAPI's UnitTokenFromGUID walks the same engine unit-token table
internally — same correctness, less Lua.

GetPlayerGuid stays (still used by the AURA_CAST event filter).
2026-05-21 16:57:12 -05:00
Brues 554c447514 swingtimer HS/Cleave detection via spell name compare
GetActionInfo + GetMacroSpell resolve each action slot to a spell name
(or skip if it's an item / empty / non-resolvable macro). The names to
match against come from C_Spell.GetSpellName on the canonical rank-1
spellIDs (78 = Heroic Strike, 845 = Cleave) so the comparison is
locale-independent without hardcoding all ranks: every rank of Heroic
Strike returns the same localized name.

Replaces the old two-path scan (texture string match + hardcoded
English name match against "heroic strike" / "hs" / "cleave"). Closes
two correctness holes the old logic had: macros that cast HS/Cleave
with a custom icon now match correctly, and macros merely *named* "HS"
without actually casting HS no longer false-match.
2026-05-21 16:53:26 -05:00
Brues 314d89e30d librange.GetRangeSlot via GetActionInfo + GetMacroSpell
Replaces the texture-from-action + "no macro text" heuristic with a
proper resolve-to-spellID step. Macros that cast a 40y heal but
display a non-spell icon (custom macro icon, /castsequence wrappers,
etc.) now match correctly — the previous code missed them because
GetActionTexture returns the macro's icon, not the underlying spell's.

C_Spell.GetSpellTexture(spellID) returns the spell's intrinsic icon
path, which is what the class-spell table is keyed on, so the
texture-comparison logic is unchanged.
2026-05-21 16:48:02 -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 8e635afeed GetItemCount via C_Item, reagents via C_Spell.GetSpellReagents
Drops the legacy pfUI.api.GetItemCount wrapper (name-based bag walk +
GetItemInfo per slot) entirely — both call sites switch to direct
C_Item.GetItemCount(itemID) calls.

actionbar reagent counter: drops the SPELL_REAGENTS tooltip-scan +
libtipscan dependency. UpdateSlot now does GetActionInfo(slot) →
spellID → C_Spell.GetSpellReagents → reagent itemID, stored per slot.
Counts update via C_Item.GetItemCount(itemID). reagent_counts is
keyed by itemID instead of localized name string. Multi-reagent
spells now resolve cleanly (only first reagent counted, matching old
single-name behavior). Macro and bag-item actions skip cleanly.

questitem: switches to hooksecurefunc("SetItemRef", ...) + the
modern GameTooltip:HasItem / :GetItem pair instead of monkey-patching
_G.SetItemRef and string.find-parsing the "item:NNN" out of the link.
Drops the libtooltip indirection for the regular tooltip path —
GameTooltip:GetItem returns name + itemID directly. AddTooltip
extended to accept the itemID (both callers already had it and were
discarding it).
2026-05-21 16:20:19 -05:00
Brues 1012a67865 librange: rely on SuperWoW UnitPosition
Drops the three other range-check paths and the target-juggling
machinery they required:

- Nampower IsSpellInRange branch + spellbook-scan to find the spell name
- UnitXP_SP3 distance check (api.lua's UnitInRange wrapper still owns
  the UnitXP precise mode independently)
- Vanilla IsActionInRange fallback that briefly retargeted via
  TargetUnit / TargetLastTarget

With target-juggling gone, this also deletes the support scaffolding it
required: PlaySound override, TargetFrame_OnEvent swap, ReAttack /
lastattack restoration, the wand and combo-points detection frames
(both were suspension guards for target-juggling), the loot/inspect/
trade/combat skip-checks, librange's pfScanActive set/clear (focus.lua
still uses its own), and the librange_isLoggingOut crash workaround
the target-flip path needed.

Target case still uses IsActionInRange (vanilla-native, works for
hostile targets too); friendly party/raid/pet scan uses UnitPosition.
The friendly-only restriction on UnitPosition isn't an issue because
the scan list contains only friendlies anyway.

DPS classes (no 40y healing spell in `spells[class]`) now also get
party/raid range coloring; they only miss the target case, which is
unchanged from before.

328 → 166 lines.
2026-05-21 15:41:33 -05:00
Brues e1cd1ef179 mount cancel via Dismount
Replaces the Phase 1 buff-slot loop + tooltip-scanned mount-string match
with a single Dismount() call. The implementation in ClassicAPI scans
for SPELL_AURA_MOUNTED on the player's auras and sends the cancel
packet itself, so we don't have to maintain a localized list of mount
tooltip patterns ("Increases speed by X%", "Erhöht Tempo um X%", etc.).

Drops pfUI.autoshift.mounts (the 20-line localized-string table) and
pfUI.autoshift.scanner (its only consumer). Module is down to ~50 lines
from ~150 at session start.
2026-05-21 10:40:42 -05:00
Brues 0e0a3f3688 shapeshift cancel via CancelShapeshiftForm
Replaces autoshift's Phase 2 (form-ID → texture lookup → buff iteration →
CancelPlayerBuff(bid)) with a single CancelShapeshiftForm() call. The
implementation in ClassicAPI walks the buff slots and matches via
Spell.dbc effect arrays itself, so we don't have to maintain a form-ID
→ texture map on the Lua side.

Drops pfUI.autoshift.shapeshifts entirely (no longer consulted) and the
turtle-wow.lua block that conditionally appended Tree of Life / Stag
Form textures — Turtle's added DBC rows (form IDs 9 and 11) are handled
natively by the same scan.
2026-05-21 10:31:25 -05:00