promotional bannermobile promotional banner

GearMatic

Per-spec upgrade scoring from the Icy Veins guides on tooltips, loot, and bags. Knows the Icy Veins best-in-slot list and marks your real BiS pieces with a skull in bags, on your character sheet, and on loot rolls. Gear Map, Auto Equip, Repair, Junk Sell.

File Details

v2.23.1

  • R
  • Jun 8, 2026
  • 1.78 MB
  • 87
  • 12.0.5+5
  • Classic + 4

File Name

GearMatic-v2.23.1.zip

Supported Versions

  • 12.0.5
  • 5.5.4
  • 4.4.2
  • 3.80.1
  • 2.5.5
  • 1.15.8

GearMatic Changelog

[v2.23.1-release] - 06/08/2026

Changed

  • The General settings page now shows a short, localized description under each addon in the More Infinite Loop Alchemist Addons section, sourced from LibMatic-Settings.

[v2.23.0-release] - 06/07/2026

Added

  • Alert text and the gear icon now use a shared adjustable drop shadow from LibMatic-AlertShadow, with a Shadow strength slider on the Alert Font settings to set how dark the shadow is.
  • Alerts now defer under native full-screen popups (renown, level-up, cinematics) via LibMatic-OverlayGuard, so a gear alert landing during one shows right after the screen clears.
  • /gm test levelup, /gm test renown, and /gm test cinematic fire the sample gear alert behind a look-alike of that native screen, so you can preview the held-then-pop deferral without leveling. Plain /gm test is unchanged.

Fixed

  • The alert sound now plays together with the alert. When an alert is held under a native screen, the sound waits and plays when the alert appears instead of during the screen.
  • An empty gear slot is now treated as a fillable upgrade target, so equipping into an empty slot registers as an upgrade.

In-Game

  • New Shadow strength slider makes gear alerts easier to read. Turn it down for a lighter shadow or to 0 for none.
  • Gear alerts no longer get hidden behind the game's renown, level-up, and cinematic screens. They show right after, and the sound now plays with the alert instead of during the screen.
  • Equipping gear into an empty slot now shows as an upgrade.

[v2.22.0-release] - 06/06/2026

Added

  • 15 new alert sounds available from the shared LibMatic sound pack: Alarm Clock, Anima Cast, Artifact Unlock, Banshee, Deathwing Wound, Epic Loot Toast, Icy Touch, Legendary Toast, LFG Denied, Mission Complete, Shop, Shop 2, Ten, Titan Light, and World Quest Complete.

Changed

  • The alert "Start delay" control is now sourced from LibMatic-Settings' shared BuildCountUpControls instead of a hand-rolled option. No change in behavior.

[v2.21.3-release] - 06/06/2026

Fixed

  • Off-hands and shields showed a false +100% upgrade when a two-handed weapon was equipped. With a 2H weapon in the main hand the off-hand slot is empty but blocked, you cannot equip an off-hand or shield without dropping the 2H. GearMatic was comparing the candidate against the empty off-hand slot (baseline 0) and reporting +100%. It now suppresses off-hand/shield evaluation entirely while a 2H is equipped.
  • Items showed a false +100% upgrade for an alt whose gear GearMatic had never recorded for that slot. For an alt a missing slot means "unknown," not "empty." GearMatic now treats a missing alt baseline as not-comparable and shows no line, instead of assuming an empty slot and claiming a +100% gain.
  • The character gear browser failed to open on retail 12.0 because ItemButtonTemplate did not resolve. The slot buttons now fall back to a plain icon button when the template is unavailable, so the browser opens on every flavor. Also fixed a footerText nil crash that fired on durability updates when the browser was closed or only half-built.

Changed

  • The other-characters lines on an item tooltip now show only characters the item is an upgrade for (at least a 1% gain), not downgrades. A character appears only when the item is actually worth sending to them.
  • Weapons are now filtered by class proficiency, not just armor. An item is no longer shown as an upgrade for a character whose class cannot equip that weapon type (for example a two-handed weapon or staff for a Rogue, a sword for a Priest). Backed by a per-class weapon-type table verified against current-retail sources.

In-Game

  • Off-hands and shields no longer show a false upgrade when you have a two-handed weapon equipped.
  • Items no longer show a false upgrade for one of your other characters until GearMatic has actually seen that character's gear.
  • The character gear browser opens reliably again.
  • On an item's tooltip, your other characters now appear only when the item is an upgrade they can actually use, the right class for the weapon and a real gain.

[v2.21.2-release] - 06/05/2026

Fixed

  • Upgrade/downgrade alert percentages are now fully colored. The alert colored only the digits; the trailing % sign sat after the color reset and stayed the item's rarity color. The whole token (the +/-, the number, and the %) is now colored green for a gain and red for a loss, while the item name keeps its quality color. Fixed in both the static render and the roll-up count animation (LibMatic-CountUp bumped to MINOR 6).
  • Bag upgrade arrow and auto-equip ignored items the game did not loot-tag for the current spec. The current-character gate rejected any item whose C_Item.GetItemSpecInfo list did not include the active spec, so usable upgrades (for example certain trinkets not loot-tagged for a healer spec) showed +X% on the tooltip but got no bag arrow and were skipped by auto-equip. The gate no longer trusts the loot-spec tag for usability; it relies on GearMatic's own scoring and keeps only the hard "For X specialization." tooltip restriction.
  • Items your class cannot wear no longer show any GearMatic per-spec lines. Armor proficiency is class-wide, so an item you cannot equip in your main spec cannot be equipped in any spec. The tooltip previously still showed off-spec "best/2nd best" badges for unwearable armor (for example mail on a cloth class) because the wear check only gated the upgrade/downgrade rows, not the badges.

In-Game

  • Upgrade and downgrade alert percentages are now fully colored: green for a gain, red for a loss.
  • The bag upgrade arrow and auto-equip no longer skip items your spec can use when the game does not label them for your specialization, such as some trinkets.
  • Items your class cannot wear no longer show GearMatic spec lines on their tooltip.

[v2.21.1-release] - 06/05/2026

Fixed

  • Buyback tooltips showed no GearMatic upgrade lines. The SetBuybackItem hook resolved the item link via tooltip:GetItem(), which does not populate for a buyback tooltip on retail (and the modern TooltipDataProcessor callback does not supply a buyback link either), so no link reached the scorer. The hook now resolves the link via the dedicated GetBuybackItemLink(slot) API (the slot index is passed to the SetBuybackItem hook), with the old GetItem path kept as a fallback.

In-Game

  • GearMatic's upgrade and downgrade lines now show on items in the merchant Buyback tab.

[v2.21.0-release] - 06/05/2026

Added

  • Off-spec set building in tooltips. The lines for your other specs now score against gear you own anywhere, including loose items in your bags/reagent bag, not just what is equipped or in a saved Equipment Set. A new owned-item pool (BestItems.GetOwnedPool = equipped + equipment sets + bags) is used for off-spec evaluation only; the current spec still compares against equipped/sets as before. So while you are Discipline, the Holy and Shadow lines reflect the off-spec set you are collecting and show "best"/"2nd best" when an item belongs in it.
  • Colored alert numbers. Gear upgrade/downgrade alerts now tint the rolling number and its +/- sign green for a gain and red for a loss, while the item name keeps its quality color. Powered by a new optional numberColor in LibMatic-CountUp-1.0 (MINOR 5), with a matching path for the non-animated number.

Changed

  • AutoEquip also refuses Warband-until-equipped gear. The bind guard now treats bindType == 9 (Warband-until-equipped, which soulbinds to the character on equip) the same as Bind-on-Equip: skipped from bags unless already bound. An unknown/uncached bind type is now treated as "could bind" (safe skip) rather than "safe to equip".

In-Game

  • When you hover gear, the lines for your other specs now count gear sitting in your bags, so you can build a set for your off-spec and see whether an item improves it.
  • Gear upgrade and downgrade alerts now color the number green when it is a gain and red when it is a loss. The item name keeps its quality color.
  • GearMatic will not auto-equip Warband-until-equipped gear from your bags either, since equipping it binds it to this character. Gear that is already bound still gets equipped automatically.

[v2.20.3-release] - 06/05/2026

Fixed

  • Two-slot gear (trinkets, rings, weapons) showed a false upgrade for an item you already wear. The two-slot baseline compared a candidate against the WEAKER of your two equipped slots, so a lower-item-level copy of a trinket/ring you already have equipped (or a different item in the same unique limit-category) was flagged as beating your other slot, even though the game won't let you equip a second one. Compare now detects when the candidate's item ID is already equipped in the slot group (or its C_Item.GetItemUniqueness limit-category is at cap) and baselines against the equipped copy it would actually replace. Single-slot gear and genuine free-slot upgrades are unaffected. Covered by tools/conflict-baseline-selftest.lua.

In-Game

  • Fixed trinkets, rings, and weapons showing a false upgrade arrow when you already have a better copy of the same item equipped (you can't wear two). GearMatic now compares against the copy you are already wearing instead of your other slot.

[v2.20.2-release] - 06/05/2026

Fixed

  • Item tooltip upgrade/downgrade percentages were wrong for gear with bonus/upgrade IDs. On retail, the tooltip hook scored a base item link (item ID only, missing the bonus/upgrade/crafting IDs) handed to it by TooltipDataProcessor, so crafted and Bind-on-Equip gear read base-template stats and showed wildly wrong verdicts (a real upgrade could display as a ~90% downgrade). appendUpgradeLinesImpl now prefers the rendered tooltip:GetItem() link, which carries the full bonus/upgrade/crafting IDs. The bag overlay, auto-equip, quest-reward, and loot scorers already used full links (GetContainerItemLink/GetLootSlotLink/GetItem) and were unaffected.

In-Game

  • Fixed gear upgrade and downgrade percentages in item tooltips that could show wildly wrong values (often a big downgrade) for crafted and Bind-on-Equip gear. Tooltips now read the item's real stats.

[v2.20.1-release] - 06/05/2026

Fixed

  • AutoEquip never binds a Bind-on-Equip item. The bag-upgrade sweep previously swapped any wearable upgrade into its slot via EquipCursorItem without checking bind type, so a Bind-on-Equip item that scored as an upgrade got bound to the character permanently. A new Compat.WouldBindOnEquip check (item bindType == 2 plus C_Item.IsBound on the bag slot) now gates the armor sweep, the weapon candidate gathering, and the weapon equip step. Items that are already soulbound, Bind-on-Pickup, or no-bind are still equipped normally. Covered by tools/autoequip-boe-selftest.lua.

In-Game

  • GearMatic no longer auto-equips Bind-on-Equip gear from your bags, so it can't bind something you were keeping to sell or trade. Gear that is already Soulbound still gets equipped automatically, just like before.

[v2.20.0-release] - 06/04/2026

Added

  • Roll-up number animation on upgrade/downgrade alerts (default on). When an alert shows a gear-score change, the number rolls up to its value instead of appearing instantly. A toggle restores the instant number.
  • Settings Profiles tab. Generic settings tabs were rebuilt on LibMatic-Settings and a Profiles tab added; settings are now backed by an AceDB profile with a one-time migration that preserves existing settings, tracked characters, and scales.
  • Full-name command help, with the help text localized into every shipped locale.

Changed

  • Moved to LibMatic shared modules. Options-panel registration routes through LibMatic's RegisterPanel/OpenPanel, the in-game changelog popup renders via LibMatic-ChangeLog with shared styling, the login banner uses the shared startup banner, and alert sounds come from LibMatic-SoundPack. LibMatic is consumed as an in-repo symlink and bundled as a packager external.
  • Removed the alert test-position button from the options.

Fixed

  • No error on login. ns.db is now guarded before reading profile.showLoginNag, so a login-timing path no longer errors.
  • Changelog popup toggle is bound to the showChangeLogPopup key, so the General-settings toggle controls the popup correctly.

In-Game

  • Gear upgrade and downgrade alert numbers now roll up when they appear. Prefer the instant number? Turn off the roll-up animation in the options.
  • New Profiles tab in the settings. Save your GearMatic settings as profiles and switch between them; your existing settings carry over automatically.
  • Fixed an error that could appear at login.

[v2.19.0-release] - 06/02/2026

Changed

  • Pawn auto-import now defaults OFF (pawnAutoImport = false in DEFAULT_SETTINGS). New profiles use GearMatic's bundled scales unless the user enables Pawn import in the options. Existing profiles keep their saved value (ApplyDefaults only fills unset keys).
  • GearMatic_Mists.toc interface bumped to 50504 for Mists of Pandaria Classic 5.5.4.

Added

  • Discord icon in the General Support group (discord.tga), wired through the shared LibMatic-Settings discordIcon hook.
  • "More Infinite Loop Alchemist Addons" group in General options, linking CritMatic and RepMatic with their icons and copy-CurseForge-link boxes (new critmatic-icon.tga / repmatic-icon.tga in Textures/). New locale key settings_group_more_addons.

[v2.18.0-release] - 05/31/2026

In-Game

  • Items you can equip now show the correct upgrade again. A higher item-level piece sitting in your bags was making genuine upgrades look like big downgrades.
  • When GearMatic posts your gear upgrades to guild chat, it now spaces them out to about one per minute, so a batch of auto-equips no longer spams the guild.

Fixed

  • Best-owned baseline no longer raw-scans loose bag items. Scoring/V2/BestItems.lua rebuild had a for bag = 0, NumBagSlots() loop that pushed every bag item into the pool, so a high-ilvl item stashed in bags became the pool best and genuine upgrades scored as large downgrades (real case: ilvl171 feet showed -81% vs an unequipped bag boot, identical across all three specs). Restored to equipped + equipment-sets only, matching v2.16.0. Commit e952d17.

Added

  • Guild broadcast cooldown: gear-upgrade chat broadcasts to the GUILD channel are throttled to one per 60s in Social.lua (GetTime gate, matching CritMatic). Party/raid/instance channels stay unthrottled, so AutoEquip sweeps no longer flood guild chat. Commit df36ee2.

[v2.17.2-release] - 05/31/2026

In-Game

  • The gear-upgrade chat broadcast now leads with a skull icon instead of a star, and the icon shows correctly in every game language.

Changed

  • Social broadcast marker changed from {rt1} (star) to {rt8} (skull) in Social.lua, and the matching settings_social_desc help text updated across all 12 locales. The numeric {rtN} raid-target token is locale-independent, so the skull renders on every client (the {skull} keyword would only work on enUS).

[v2.17.1-release] - 05/31/2026

In-Game

  • The interface is now fully translated in every supported language (German, French, Spanish, Italian, Portuguese, Russian, Korean, and Chinese).

Changed

  • Localization: filled the 38 keys that every non-English locale (and enGB) was missing, so they no longer fall back to English. Covers loadout slot-action hints, the Pawn and vendor settings, the changelog-popup toggle, current_spec_marker, tooltip_best/tooltip_second_best, and the load splash. Translated for deDE, esES, esMX, frFR, itIT, koKR, ptBR, ruRU, zhCN, zhTW (plus enGB), matching each file's existing diacritic/style convention; all %d/%s format specifiers and |cff...|r color codes preserved. Each locale now covers the full 239-key enUS set (0 missing, 0 duplicates, all pass luac -p).

[v2.17.0-release] - 05/31/2026

In-Game

  • Item tooltips now show your upgrade chance for every spec you have, with your active spec listed first and marked (current).
  • One-handed weapons in your bags no longer show a false upgrade arrow when your class can't dual-wield them.
  • The gear-slot swap window now correctly lists the items you can put in that slot.
  • Upgrade markers for your other characters now show up correctly again.
  • The character browser no longer blocks your keyboard while it is open.

Added

  • Per-spec upgrade rows in item tooltips lead with the active spec, promoted to the top of the list and tagged with a (current) marker via the new SI.GetActiveSpecIndex() (resolved from C_SpecializationInfo.GetSpecialization).

Fixed

  • Compare.EvaluateForChar ran the current character's can-wear / off-spec gate (ShouldEvaluateForCurrentChar) for ALL characters, so alt upgrade rows (tooltip alt lines, BestAltUpgrade feeding the bag/loot/quest overlays) were suppressed for any item the logged-in character couldn't use. The gate now only applies when scoring the current character; alts are class-filtered by their own callers.
  • One-hand weapon baseline (BestItems.CompareBaseline) and best/2nd-best assignment (assignOneHandedBestItems) treated non-dual-wield classes as dual-wielders, so a 1H weapon was compared against the off-hand frill and inferior weapons read as upgrades (false bag chevron) or as a spurious "2nd best" badge. Both paths are now gated on CanDualWield().
  • GetItemInfoInstant equipLoc was destructured at return position 9 (the GetItemInfo layout) instead of position 4 in Loadouts/SlotFlyout.lua and Loadouts/Equip.lua, so the slot-swap candidate grid was always empty and the 2H unequip-first step never fired.
  • Pawn scale import derived specID from trailing digits of the scale name instead of the scale's real SpecID field, and the Resilience stat alias mapped to a misspelled key (resilienceitrating), dropping resilience weight from every score. Both corrected (alias and export map now use resilience; import reads pawnScale.SpecID first).
  • The full character scan never cleared a slot that is now genuinely empty, so an unequipped item lingered in saved data and inflated the tracked average item level. Empty slots are now cleared.
  • Durability helpers (CountLowDurability, MinDurabilityPct) could divide a nil durability from legacy saved rows; the loop now guards on slot.durability.
  • Auto-equip's combat guard checked only UnitAffectingCombat; it now also returns true on InCombatLockdown() so it won't attempt a protected weapon swap during the combat-lockdown tail.
  • The character browser frame enabled keyboard capture without SetPropagateKeyboardInput, trapping every keystroke (movement, action bars, chat) while the window was open. It now consumes only LEFT/RIGHT/ESCAPE and passes everything else through.

Changed

  • Removed an unreachable duplicate export slash subcommand.

[v2.16.0-release] - 05/30/2026

In-Game

  • AutoEquip no longer loops swapping your weapons during combat, and now picks the best weapon setup for your spec, a two-hander or dual-wielding two one-handers, whichever scores higher.

Fixed

  • AutoEquip thrash loop. Equipping a weapon fires BAG_UPDATE_DELAYED, which re-ran the sweep; the just-removed weapon (now in bags) re-qualified because a 2H-blocked off-hand slot (score 0) was treated as a free "empty" slot, so any 1H was force-equipped into it, kicking out the 2H, then the 2H beat the lone 1H and re-equipped, looping every 0.5s and broadcasting each swap to guild chat. Added self-retrigger suppression (ignores the BAG_UPDATE_DELAYED an auto-equip itself causes for 1.5s), an anti-oscillation guard (won't re-equip an item it just displaced for 10s), and 2H-occupancy awareness (a blocked off-hand is no longer treated as a free slot).

Changed

  • AutoEquip now solves for the optimal weapon configuration instead of greedily filling the weakest slot. Each sweep scores every weapon (equipped + bags) with the active stat weights and picks the highest-scoring valid config: best two-hander alone, best two one-handers (dual-wield, gated on CanDualWield()), best one-hander + off-hand/shield, or main-hand alone, then equips toward it only when it beats the current weapons by the min-delta threshold. The decision is a fixed point, so it converges and stops. Planner and guards are covered by a unit test.

[v2.15.6-release] - 05/30/2026

In-Game

  • GearMatic's bag upgrade markers no longer break your cast bar or spam errors during combat in dungeons, raids, and arenas.

Fixed

  • v2.15.5 wrapped scanFrame/scanContainer in pcall to swallow the secret-boolean error, but pcall catches the error without stopping taint propagation: execution stayed tainted-by-GearMatic and the taint spread to Blizzard's secure CastingBarFrame (and was misattributed to other addons, e.g. "execution tainted by 'RepMatic'"). Confirmed via taint.log: BagOverlay.lua:135 boolean-tested a secret IsShown() ~130,000 times in an instance, poisoning the global ON_BAR_HIGHLIGHT_MARKS and the cast bar's animation tables. Real fix: scanFrame now skips forbidden frames and frames carrying any secret aspect (IsForbidden() / HasAnySecretAspect(), both SimpleFrameScriptObjectAPI base methods verified via the wow-api MCP) BEFORE the boolean test, so the secret value is never tested and no taint is generated. The full EnumerateFrames walk still runs, so third-party bag overlays (Bagnon, AdiBags, BetterBags, ElvUI, ArkInventory, Bagshui) keep working; only secret/forbidden frames are skipped.

[v2.15.5-release] - 05/29/2026

In-Game

  • GearMatic's bag upgrade markers no longer cause errors in dungeons, raids, and arenas.

Fixed

  • BagOverlay.refreshAll walks the whole frame tree via EnumerateFrames to find bag item buttons (retail bag buttons are matched by their methods, not fixed names, so this scan runs everywhere including instances). On retail 12.0 (Midnight) it reached secret-value frames such as the cooldown viewer and aura frames, where frame:IsShown() returns a secret boolean; boolean-testing it at line 140 threw attempt to perform boolean test on a secret boolean value (execution tainted by 'GearMatic'), once per such frame per scan tick (the reported 100x). Secret values only activate in instanced/combat content, which is why it only fired in dungeons, raids, and arenas. Wrapped each foreign-frame probe (scanFrame/scanContainer) in pcall, so any error from inspecting a frame GearMatic does not own (secret IsShown/IsVisible/IsObjectType, the earlier non-string GetName, or anything future) is caught and that frame is skipped, while the sweep continues and real bag buttons are still decorated. BagOverlay only colors its own overlay textures and calls no protected functions, so the brief secret-read taint is inert (no blocked actions). Closes the whole "poke a foreign frame on the secret-values API" class for the bag scan.

[v2.15.4-release] - 05/29/2026

In-Game

  • GearMatic no longer causes errors while WoW's built-in damage meter is open.

Fixed

  • BagOverlay.refreshAll walks the entire frame tree via EnumerateFrames (once per second on a poll, plus on bag events) and ran looksLikeBagItemButton on the retail damage meter's DamageMeterEntry rows. For those ScrollBoxListView buttons frame:GetName() returns a non-string (a FontString), so line 95's n:find("ContainerFrame") threw attempt to call a nil value (method 'find'), spamming once per meter row per update (the reported 113x). Guarded with type(n) == "string" before any string method, so meter rows are correctly rejected and real bag buttons (Blizzard ContainerFrame*, Bagnon, AdiBags, BetterBags, ElvUI, ArkInventory, Bagshui) are still detected. Hardened the same GetName()-assumed-string pattern in BagOverlay.decorateContainerFrame and in ItemTooltipHook (addLineBold, alreadyAdded), which concatenate the name into a _G[...] lookup, so no sibling variant can surface. Behavior is unchanged for valid names; only non-string returns now bail instead of crashing.

[v2.15.3-release] - 05/29/2026

In-Game

  • GearMatic no longer interferes with unit tooltips in dungeons, raids, and arenas.

Fixed

  • UnitTooltipHook.appendUnitInfo threw bad argument #1 to 'UnitIsPlayer' ... Secret values are only allowed during untainted execution on retail 12.0 (Midnight). tooltip:GetUnit() returns a secret unit token whenever the hovered unit's identity is sealed (combat against non-player/pet units, and dungeon/raid/arena instances), and passing that token to UnitIsPlayer (then UnitName) crashed during tainted addon execution via the TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Unit) path. Added an isSecretValue helper (nil-safe wrapper around the Mainline issecretvalue global) and now bail before any Unit API call when the unit token, or the resolved name/realm, is secret. Classic flavors are unaffected (issecretvalue is nil there, so the guard returns false and the legacy OnTooltipSetUnit path is unchanged). The mouseover summary only ever matched the player's own stored characters, so suppressing sealed units removes no working functionality, it only replaces the error with graceful silence in the contexts where the line could never resolve anyway.

[v2.15.2-release] - 05/28/2026

In-Game

  • Item tooltips were listing each of your class specs twice. Every spec now appears once.
  • Your equipped weapons now rank the way rings and trinkets do. With two one-hand weapons, one shows best and the other second best instead of both showing best. A two-handed weapon shows best.

Fixed

  • ScaleImport.GetScalesForClass deduped class scales by specID when present and by name otherwise. A Pawn-imported scale (specID = spec index, name Pawn:...) and the bundled default for the same spec (specID = nil, name = spec) therefore never collided, so both rendered and every spec showed twice. The v2.15.0 retail default pool made this fire for any class that had both a Pawn import and a bundled default. Dedup now keys on the normalized spec name (falling back to specID, then name) so the two sources collapse to one row, with the user/Pawn scale winning. Bundled scales also get a resolved specID via GetSpecializationInfoForClassID so the rows sort in stable spec order.
  • BestItems.GetRank for INVTYPE_WEAPON checked secondStripped fields that assignOneHandedBestItems never populates (it splits the two one-hand weapons into separate main-hand / off-hand rows that each carry only best), so a weapon could only ever return best or nil, never second, unlike trinkets and rings. GetRank now maps the main-hand row to best and the off-hand row to second, trusting the placement assignOneHandedBestItems already computed. On a tie the off-hand item wins the top slot (slot 16 is scanned before slot 17, so the later equal-scoring weapon wins the >= swap), so two equal-scoring weapons no longer both show best.

[v2.15.1-release] - 05/28/2026

In-Game

  • The upgrade arrow on quest reward items now reflects your current spec only. An item that is only an upgrade for one of your off-specs no longer shows the arrow when it is not an upgrade for the spec you are actually playing.

Fixed

  • QuestRewardHook.evaluateOne dropped its off-spec fallback for the current character. The reward-button chevron now fires only when the active (current-spec) scale delta is >= 0.5%; previously it looped over every class spec and lit the chevron if ANY spec cleared the threshold, so a Discipline priest saw the arrow on an item that was only a Holy/Shadow upgrade. The now-unused scalesForCurrentClass helper was removed. BagOverlay and LootHook were already current-spec-only (EvaluateForChar), verified unchanged.

[v2.15.0-release] - 05/28/2026

In-Game

  • Retail gear scoring now uses real per-spec stat weights for all 39 modern specs. Every item now shows an accurate, distinct upgrade value for each spec instead of the same number for every item.
  • Items that rank as your best or 2nd best for a slot now show the best / 2nd best badge in tooltips even when they sit in your bags or are offered as a quest reward, not only when already equipped. Bag or quest copies of the item you are already wearing still stay unmarked.

Changed

  • tools/gm_emit_retail.py rewritten to parse references/pawn/AskMrRobot.lua (real differentiated per-spec weights) instead of ScaleTemplates.lua (the uniform primary=1 / every secondary=0.5 starter templates). Maps the 15 AMR stat names to GearMatic extractor keys (HasteRating->hasterating, CritRating->critrating, Versatility->versatility, MaxDamage->maxdamage, MovementSpeed->speed, Indestructible->indestructible, etc). Spec display names are read from the source's inline comments so newly added specs (e.g. the third Demon Hunter spec) need no map update.
  • Scales/defaults.lua ["retail"] block regenerated: 40 specs across all 13 classes, each with its own differentiated weights. Replaces the prior placeholder stub block where every spec and every secondary stat shared identical weights, which made all items score the same.

Fixed

  • ItemTooltipHook.lua: the per-spec tooltip rows no longer drop a spec when a non-equipped item ranks best or 2nd best in that scale's pool. BestItems.GetRank is now consulted for non-equipped items too; a badge renders unless the item shares its itemID with the item already equipped in that slot (preserving the v2.13.1 duplicate-suppression). Previously such items showed neither a badge (badges were equipped-only) nor a chevron (suppressed by the best/2nd guard), so the row vanished.

[v2.14.1-release] - 05/27/2026

In-Game

  • Item tooltips show one row per spec for your class even when you have only imported a scale for one of them. A priest with only a Discipline scale now also sees Holy and Shadow rows, populated from the bundled defaults.
  • Equipped items show the best / 2nd best badge again in tooltips, including the comparison tooltip that pops up when you hover a quest reward or a bag item. The previous fix that stopped duplicate badges on bag copies was over-tightened and accidentally suppressed the badge on the real equipped slot.

Fixed

  • ScaleImport.GetScalesForClass now backfills ns.DefaultScales[flavor] entries for the character's class on top of the user-imported saved scales. Dedupes by specID (and by name as a fallback) so the same spec never renders twice. Restores the v2.13.0 multi-spec tooltip promise when the user only imported a subset of class specs.
  • ItemTooltipHook.isCurrentlyEquippedLink now uses a fingerprint fallback (itemID:enchant:gem1:gem2:gem3:gem4:suffix) after the strict link match, with %d* (zero-or-more digits) on every field so Mists Classic 5.5.x links that serialize empty fields as :: (instead of :0: like older clients) still match. Equipped detection works again in compare tooltips, standalone equipped tooltips, and quest-reward shopping tooltips, while bag duplicates with different enchant/gem fragments still fail the fingerprint (so v2.13.1's duplicate-badge protection is preserved).

[v2.14.0-release] - 05/27/2026

In-Game

  • Equip and upgrade alerts now color the item name by its actual rarity (green for uncommon, blue for rare, purple for epic, orange for legendary) instead of always purple.

Changed

  • Alert.ShowGearEquipped and Alert.ShowGearUpgrade now derive the alert text color from the item's quality via C_Item.GetItemQualityColor, falling back to the user-configured fontColor when quality is unknown (uncached GetItemInfo). Alert.ShowGearDowngrade continues to use fontColorLoss (red) so the loss indicator stays distinct from rarity. itemIconAndName now also returns the quality alongside icon and name.

[v2.13.1-release] - 05/27/2026

In-Game

  • Quest reward and bag duplicates of items you already have equipped no longer get a misleading best badge. Only the actual item in the equipped slot gets the badge.

Fixed

  • isCurrentlyEquippedLink reverted to strict full-link match. The itemID-fallback added in 2.12.0 returned true for any item whose itemID matched something in an equipped slot — including quest-reward copies and bag duplicates. Strict link-match avoids the false positive; the rare link-format-differs case now falls through to the chevron path, where a 0% delta self-comparison suppresses the line cleanly.
  • Badge gate in appendUpgradeLinesImpl requires equipped == true. BestItems.GetRank's stripped-link match also fired for duplicates (since strip ignores enchant, two copies of the same item with no enchants have identical stripped links). Just tightening isCurrentlyEquippedLink wasn't enough — GetRank had to be gated behind the equipped check too. Equipped items still get the correct best/2nd-best rank from GetRank, defaulting to "best" if GetRank returns nil (link-format edge cases).

[v2.13.0-release] - 05/27/2026

In-Game

  • Item tooltips now show one line per spec for your class. Hover any item and you'll see a separate best / 2nd best / +X% upgrade / -X% downgrade line for each spec you have a scale for (Elemental, Enhancement, Restoration, etc), each with its own spec icon.
  • Switching specs in-game now auto-updates which scale is treated as current. Swap from Restoration to Elemental and the chevron/badge follows; no need to run a slash command after every spec change.
  • Auto-equip still respects only the current spec, never your off-spec lines.

Added

  • SI.GetScalesForClass(charKey) in ScaleImport.lua. Returns every scale in GearMaticDB.scales[charKey] whose class field matches the character's class, sorted by specID ascending. Filters out the _active sentinel key.
  • iconForSpec(class, specIndex) helper in ItemTooltipHook.lua resolves any spec's tooltip icon through GetSpecializationInfoForClassID(classID, specIndex) via a local CLASS_NAME_TO_ID map (WARRIOR=1 .. EVOKER=13). Falls back to the class-circles icon when the API doesn't return a per-spec result.
  • Per-spec tooltip rows. appendUpgradeLinesImpl now loops over SI.GetScalesForClass(currentKey) instead of evaluating only the active scale. Each scale gets its own row: kind = "badge" (best / 2nd best) when BestItems.GetRank returns non-nil OR the item is currently equipped, otherwise kind = "chevron" from EvaluateAgainstScale with the threshold |delta| >= 0.5%. Rows pushed to the existing rows table and rendered with the same render loop that previously handled chevron-only rows.

Fixed

  • SI.GetActiveScale ordering inverted. Previous order: bag._active → spec match → any class match. New order: spec match → bag._active → any class match. The old order meant swapping specs left _active pointing at the previous spec's scale, so the chevron/badge stayed on the wrong spec. The new order detects the current spec via getCurrentSpecIndex() and returns the matching scale first; _active is now a fallback for cases where no per-spec scale exists.
  • Off-spec rows on the same character no longer show Charname (Spec): parens. formatLine and formatBadge now select the row icon from eval.scale.specID / scale.specID when available, so the spec icon comes from the scale, not from "is this the current spec?" The isCurrent flag is now strictly "same character" — current-spec AND off-spec on the player's own char both set isCurrent = true and use the no-name format; only different-character rows (multi-char tooltip) get the alt format.
  • Green border on upgrades still works under multi-spec render. The old code referenced a single currentEval variable that no longer exists; replaced with a fresh EvaluateForChar lookup right before the border check (current spec only, by design).

[v2.12.0-release] - 05/27/2026

In-Game

  • Currently-equipped items now show a best or 2nd best badge on the tooltip instead of the +X% upgrade / -X% downgrade percentage. Trinkets included. Bag items still show the percentage chevron as before. PvP and PvE gear treated the same way once equipped.

Added

  • BestItems.GetRank(scale, equipLoc, itemLink) in Scoring/V2/BestItems.lua. Returns "best" / "second" / nil by stripping the candidate's enchant and comparing against row.bestStripped / row.secondStripped in the pool. Special-cases INVTYPE_WEAPON to check both INVTYPE_WEAPONMAINHAND and INVTYPE_WEAPONOFFHAND rows (one-handed weapons can sit in either slot). General path covers single-slot and the rest of TWO_SLOT_LOCS.
  • Trinkets are now tracked in the BestItems pool. Removed INVTYPE_TRINKET from SKIP_EQUIPLOCS and added to TWO_SLOT_LOCS (two trinket slots, slot 13 + 14). Equipped trinkets now get the best / 2nd best badge.
  • formatBadge(scale, rank, isCurrent) in ItemTooltipHook.lua. Renders the badge line with the active spec name (class-colored) plus the rank text from new L["tooltip_best"] = "%s: |cff8ec3e6best|r" / L["tooltip_second_best"] = "%s: |cff8ec3e62nd best|r" (light-blue badge color, distinct from the chevron's green/red).

Fixed

  • appendUpgradeLinesImpl always shows a badge on equipped items. Rank comes from BestItems.GetRank when the pool has the item indexed; if the item is currently equipped but GetRank returned nil (link-format mismatch, brand-new item the pool hasn't seen yet, etc), rank defaults to "best" so the slot is never blank. Old isCurrentlyEquippedLink early-return now only fires AFTER the badge gate, which means it never actually triggers — equipped items always have a rank one way or another.
  • isCurrentlyEquippedLink now matches by itemID as a fallback. Full-link == comparison can fail when tooltip:GetItem()'s link format differs slightly from GetInventoryItemLink("player", slot)'s format (enchant slot ordering, bonus IDs, upgrade tags). Fallback parses item:(%-?%d+) from both links and compares the integer itemID; matches if either path agrees.
  • assignOneHandedBestItems preserves bestStripped when rewriting pool["INVTYPE_WEAPON"] into pool["INVTYPE_WEAPONMAINHAND"] and pool["INVTYPE_WEAPONOFFHAND"]. Previously only best and bestLink were carried over, so GetRank's row.bestStripped == stripped check always failed for one-handed weapons and the equipped weapon never matched as "best". secondStripped carried over too where applicable.

[v2.11.0-release] - 05/26/2026

In-Game

  • Weapons now correctly factor their damage range into upgrade scoring. Previously only damage-per-second contributed; daggers, swords, and other weapons looked far worse than they actually were. DPS specs see the biggest swing — a weapon's mainline +Min/+Max damage now feeds the scale weights the same way Intellect, Agility, etc do.
  • New /gm audit slash command: hover any item and run it to see exactly how each stat in your active scale contributes to the score, which stats are weighted but not extracted from the item, and which stats are extracted but ignored by your scale.
  • Healer items from Vanilla / TBC / Wrath now parse the +Healing and +Spell Damage tooltip lines instead of dropping them.

Added

  • /gm audit [link|itemID] slash subcommand. New Debug.AuditItem in Debug/Score.lua. Resolves item via hover cache, GameTooltip, ItemRefTooltip, ShoppingTooltip, or inline arg. Walks the active scale's weights table alphabetically; for each weight, prints key w=<weight> v=<extracted> contrib=<weight*value> or yellow-flags as GAP when weighted-but-zero. Suppresses contribution display for -1000000 ignore-sentinel weights. After the weighted-stats section, lists extracted-but-not-in-scale orphans. Final two lines print the audit total alongside Score.ScoreItem result so any divergence (socket potential, AP redirect, Wrathion bonus) is visible. Appends raw tooltip lines at the end for diagnosing remaining extraction gaps.
  • Weapon damage range tooltip extraction. New Norm.ExtractDamageRange(text) in Scoring/V2/StatNormalize.lua parses "N - N Damage" lines via three patterns with progressively looser anchors (^%s*...%s*$, ^%s*..., no anchors). Returns (minDmg, maxDmg) as two numeric returns. Wired into Extract.ReadViaTooltip to push stats.mindamage and stats.maxdamage. Pawn-style scales weight mindamage = maxdamage heavily on weapons; previously these were always 0 in the extracted stats table, undervaluing every weapon vs scoring.
  • Vanilla/TBC healing + spell-damage tooltip extraction. Norm.ExtractHealing(text) matches +N Healing plus Equip: Increases healing done by spells and effects by up to N and Equip: Increases healing done by magical spells and effects by up to N. Norm.ExtractSpellDamage(text) matches the equivalent damage-side patterns. Both wired into ReadViaTooltip. ITEM_MOD_SPELL_HEALING_DONE_SHORT API mapping flipped to healingpower (matches PawnIntegration's Hp/HealPower alias canonical key) so API and tooltip paths converge on the same key.

Fixed

  • Extract.Read now uses API path as source of truth. Previously on retail the merge logic preferred ReadViaTooltip whenever it returned a non-empty table, which silently dropped every API-only stat (Versatility, Avoidance, Leech, Speed, Indestructible were all missed pre-2.10.0 because of this). Now Extract.Read always starts with the full API result, then supplements only for TOOLTIP_ONLY_KEYS = {weaponspeed, mindamage, maxdamage, redsocket, yellowsocket, bluesocket, metasocket, prismaticsocket, cogwheelsocket, shatouchedsocket, indestructible}. Any other tooltip-extracted key only fills in when the API didn't provide it (Classic flavors where API may be sparser). Adding a new class scale now Just Works because the API path knows every stat on every item for every class on every flavor; no per-stat pattern audit needed.
  • Multi-return-value collapse bug in Extract.ReadViaTooltip. The previous wiring local minDmg, maxDmg = S2.Normalize.ExtractDamageRange and S2.Normalize.ExtractDamageRange(line) collapsed Lua's two-return value to one because the and operator only forwards a single value. ExtractDamageRange correctly returned (4, 8) for "4 - 8 Damage" but maxDmg was always nil, the if minDmg and maxDmg guard always failed, and weapon damage was never pushed to the stats table. Replaced with explicit if X then local a, b = X(line) blocks.
  • StatNormalize tooltip patterns for modern tertiaries (Versatility, Avoidance, Leech, Indestructible, movement Speed) shipped in 2.10.0 stay in place but are now mostly defensive — the API path covers these on retail, and the tooltip patterns serve as fallback for any flavor where the API path doesn't (Classic Era resists, etc).

[v2.10.0-release] - 05/26/2026

In-Game

  • Auto-sell junk (grey-quality items) at vendors. Defaults on. Toggle in /gm settings -> General -> Vendor automation.
  • Auto-repair at vendors. Uses guild bank funds first if your rank allows and the withdrawal limit covers the cost; otherwise spends personal gold. Defaults on. Toggle in the same panel.
  • Mark any non-grey item as junk so it sells alongside grey-quality items. Two ways: SHIFT+RIGHT-CLICK the item in your bag, or /gm junk add <link> / /gm junk remove <link> / /gm junk list / /gm junk clear.
  • Items with Versatility, Avoidance, Leech, Indestructible, or movement Speed now score correctly. Previously these stats were being dropped from item evaluation, making some items look like bigger downgrades than they actually were (e.g. a dagger with +4 Versatility was being scored as if it had none).
  • Fixed an error message that appeared on retail every time you mouseovered another player.

Added

  • Vendor automation module (VendorAutomation.lua). New CreateFrame "GearMaticVendorAutomationFrame" registers MERCHANT_SHOW and MERCHANT_CLOSED. On show, fires VA.AutoRepair() then VA.SellJunk(). On close, cancels any in-flight sell queue.
  • Throttled auto-sell. VA.SellJunk walks bags 0-4 once, queues every slot with quality == 0 OR VA.IsJunk(itemID) true, then drains the queue via C_Timer.NewTicker(SELL_INTERVAL=0.2) calling C_Container.UseContainerItem. The 0.2s spacing stays under WoW's per-second action throttle. Re-reads container info before each sell so items moved/equipped mid-queue are skipped. Prints "auto-sold N junk items for Xg Ys Zc" summary on completion.
  • Guild-bank-first auto-repair. VA.AutoRepair checks CanMerchantRepair, then CanGuildBankRepair + GetGuildBankWithdrawMoney (with IsInGuild guard). Calls RepairAllItems(1) to draw from guild funds when both allowed and the bank limit (or -1 = unlimited) covers GetRepairAllCost(); otherwise RepairAllItems() for personal funds. Prints "auto-repaired for X (guild/personal funds)" summary, or "auto-repair skipped: need X, have Y" when personal funds short.
  • Per-character junk-list rules. GearMaticDB.junkRules[charKey] is an itemID set. VA.MarkJunk(itemID), VA.UnmarkJunk(itemID), VA.IsJunk(itemID), VA.ListJunk(), VA.ClearJunk() manage entries. Sell loop checks quality == 0 OR VA.IsJunk(itemID) so flagged whites sell alongside greys.
  • /gm junk slash subcommand. /gm junk add <link|itemID>, /gm junk remove <link|itemID> (alias rm), /gm junk list, /gm junk clear. Item link parsing extracts itemID from the item:N substring, or accepts a bare numeric ID.
  • SHIFT+RIGHT-CLICK on bag items toggles junk status. hooksecurefunc("ContainerFrameItemButton_OnModifiedClick", ...) fires only when the global exists (Classic + Retail both have it). Resolves bag/slot via button:GetBagID() / button:GetID() with fallbacks to button.bag / button.slot / button:GetParent():GetID(). No conflict with default WoW behavior (no native action on that combo for bag items).
  • GUI toggles in General tab. New "Vendor automation" inline group at order=25 holds autoSellJunk and autoRepair toggles, both full-width. Both default true in DEFAULT_SETTINGS.

Fixed

  • Tooltip parser missed Versatility, Avoidance, Leech, Indestructible, and movement Speed. Scoring/V2/StatNormalize.lua LINE_PATTERNS built patterns only for classic-era secondaries. On retail Extract.Read prefers ReadViaTooltip when non-empty, so these stats were silently dropped even though ReadViaAPI had them. Symptom: weapons with Versatility scored ~5 points per stack lower than they should have. Added five add(withValue(ITEM_MOD_*), key) calls plus one add(bare(...)) for Indestructible. Falls back to English literals when the ITEM_MOD_* global doesn't exist on a flavor.
  • OnTooltipSetUnit HookScript error on retail Dragonflight+. UnitTooltipHook.lua now detects TooltipDataProcessor.AddTooltipPostCall + Enum.TooltipDataType.Unit and uses the modern API on 10.0+; pcall-falls-back to HookScript("OnTooltipSetUnit") on Classic flavors. The legacy handler was removed from GameTooltip in 10.0 and was throwing "Doesn't have a OnTooltipSetUnit script" on every retail login.
  • release.sh was nuking install-dir symlinks. The post-package sync did unconditional rm -rf "$target"; cp -R "$STAGED_DIR" "$target" on every flavor dir, replacing any pre-existing symlink with a copy of the packaged build. Now skips the copy when [ -L "$target" ] (target is already a symlink), preserving live-edit setups while still copying for flavors that don't have a symlink.

[v2.9.0-release] - 05/26/2026

In-Game

  • Weapons that grant raw +Attack Power (older expansion gear, heirlooms) now contribute to your DPS-spec scoring correctly on retail. Previously the value was being silently dropped.
  • New /gm export scale <name> command outputs a portable stat-weight string you can share with other players or paste into other stat-weight tools.
  • Fixed an error that appeared when mousing over players on retail.

Added

  • Public addon API for plugin scales. Three new functions on the GearMatic global: AddPluginScale(providerName, scaleName, classID, specID, weights) registers a class/spec-tagged stat-weight scale at runtime; RemovePluginScale(providerName, scaleName) clears it; ListPluginScales([providerName]) enumerates current-character plugin scales. Plugin scales persist in GearMaticDB.scales[charKey] under <provider>:<scale> with source = "plugin:<provider>", coexisting with Pawn-imported and user-pasted scales. Weights accept either lowercase canonical keys or Pawn-style CapitalCase via the existing normalisePawnKey path.
  • /gm export scale <name> slash command. Pawn.ExportScale serializes a stored GearMatic scale back to standard Pawn import-string format. Reverse-maps canonical lowercase keys to Pawn CapitalCase via a static table, with a live PawnCommon.Scales[name].Values probe overriding when Pawn is loaded so re-exports preserve the original key spelling. -1000000 weights export as =X (Pawn's PawnIgnoreStatValue sentinel). Class= and Spec= lines emitted from the scale's stored class/specID. Embedded double-quotes in the scale name get stripped because Pawn's parser regex can't handle them; the slash output prints a note documenting the rename.
  • AP→max(STR, AGI) redirect on retail. Scoring/V2/Score.lua:113-121 routes any attackpower-keyed weight through whichever of strength or agility carries the larger weight in the active scale. Scoring/V2/StatExtract.lua adds AP_SKIP_KEYS_RETAIL = {attackpower, rangedattackpower, feralattackpower} and skips those keys in ReadViaAPI so synthesized retail AP doesn't double-count when the redirect applies. Merge guard at lines 162-167 only fires when the API path wins so real +N Attack Power tooltip text on legacy gear is preserved.

Fixed

  • OnTooltipSetUnit HookScript error on retail. UnitTooltipHook.lua now detects TooltipDataProcessor.AddTooltipPostCall + Enum.TooltipDataType.Unit and uses the modern API on Dragonflight+ (10.0+); falls back to the legacy HookScript("OnTooltipSetUnit") on Classic flavors via pcall. The legacy script handler was removed from GameTooltip in 10.0 and was throwing "Doesn't have a OnTooltipSetUnit script" on every retail login.

[v2.8.0-release] - 05/25/2026

In-Game

  • Wands now correctly show an upgrade line and score on Mists Classic. They were silently skipped on flavors where the old ranged slot doesn't exist.
  • Items that are an upgrade for your current spec now show with a green tooltip border, a quick visual cue to help you spot upgrades at a glance.
  • Items with empty sockets factor those sockets into the upgrade calculation. A socketable piece now correctly outranks an identical socketless one.
  • On Mists Classic, items eligible for the legendary cloak quest line get a bonus socket factored into scoring.
  • Repeated hovers of the same item feel snappier; an internal cache speeds up the second look.
  • Bag changes, vendor sells, and spec swaps refresh stale scoring automatically.

Added

  • Wrathion PrismaticSocket bonus on Mists Classic. New Scales/wrathion_items_mists.lua carries ~179 itemIDs from Heart of Fear, Terrace of Endless Spring, Throne of Thunder, and BS-craftable epics, exposed as ns.WrathionUpgradeableItemIDs. Scoring/V2/Sockets.lua adds Sockets.WrathionAdjustedStats(stats, itemLink) which returns a shallow copy with prismaticsocket = (existing or 0) + 1 when the itemID is eligible. Score.ScoreItem consults this right after Extract.Read.
  • Basic socket potential scoring. Sockets.PotentialFor(stats, scale) now returns empty * gemAmount * bestGemmableWeight instead of the prior stub 0. Counts empty red/yellow/blue/prismatic sockets (meta is excluded; metasocketeffect carries its own weight). gemAmount per flavor: Mists=320, Cata=240, Wrath=60, TBC=12; 0 elsewhere. Best stat is the max weight across strength, agility, intellect, spirit, stamina, critrating, hasterating, masteryrating, hitrating, expertiserating, dodgerating, parryrating, spellhitrating, spellpower, attackpower.
  • 200-entry FIFO item-parse cache. New cacheGet / cachePut / cacheClear helpers in Scoring/V2/StatExtract.lua cap at CACHE_MAX = 200, keyed on itemLink. FIFO eviction via table.remove(order, 1). Extract.Read returns the cached table on hit (skipping both ReadViaAPI and ReadViaTooltip) and inserts the result on miss. Measured 0.90ms miss vs 0.001ms hit on a Mists epic. ns.StatExtract_ClearCache() exposed for external invalidation.
  • Green tooltip border on upgrades. ItemTooltipHook.lua adds setTooltipBorderUpgrade / resetTooltipBorder helpers. setTooltipBorderUpgrade tries tooltip.NineSlice:SetBorderColor(0, 1, 0, 1) first, falls back to tooltip:SetBackdropBorderColor(0, 1, 0, 1). Triggered when the CURRENT character's eval delta is >= 0.5 percent; alt rows don't trigger border. Reset via OnHide HookScript on GameTooltip, ItemRefTooltip, ShoppingTooltip1, ShoppingTooltip2. Gated by GearMaticDB.settings.colorTooltipBorder (defaults true).
  • Three more BestItems invalidation events. Scoring/V2/BestItems.lua registers ITEM_LOCKED, MERCHANT_UPDATE, PLAYER_SPECIALIZATION_CHANGED (Mists+), and ACTIVE_TALENT_GROUP_CHANGED (Wrath/Cata). Latter two are pcall-protected via pcall(refreshFrame.RegisterEvent, refreshFrame, ...) for flavors that don't support them.
  • /gm wrathion <itemID> diagnostic. Mists-only slash subcommand prints listed=, with=, without=, diff= for the supplied itemID, toggling ns.WrathionUpgradeableItemIDs temporarily to compare scores with and without the Wrathion bonus.

Fixed

  • Wand-slot bug on Mists+ flavors. Compat.SlotsForEquipLoc("INVTYPE_RANGEDRIGHT") and ("INVTYPE_RANGED") now return { 16 } on flavors where HasRangedSlot is false (Mists 5.0+, retail). Previously the function returned nil, EvaluateForChar got no slot, and wands silently dropped out of the tooltip upgrade pipeline. Wand of the San'layn and other WotLK-era wands report INVTYPE_RANGEDRIGHT from GetItemInfo even on Mists Classic where the game equips them into slot 16.
  • Quest reward overlay threshold parity. QuestRewardHook.lua evaluateOne threshold lowered from >= 1 to >= 0.5 percent for both the current-spec eval and the multi-scale fallback, matching the tooltip-upgrade-line threshold.
  • Pawn scale converter rejected scales with any zero weight. PawnIntegration.convertPawnScale now accepts a Pawn scale as long as at least one weight is positive; previously, a scale with Stamina = 0.1 and other strong positives was passed through but any scale with even one zero-or-negative weight returned nil.
  • Compare.lua baseline now uses BestItems pool for current char. baselineForCurrentChar calls S2.BestItems.CompareBaseline(scale, equipLoc) first when the character is the player's current character, falling back to the worst-equipped-slot lookup otherwise. This matches the broader pattern of comparing against your single best-in-slot baseline.
  • Self-comparison early-out in evaluateImpl. Compare.evaluateImpl early-returns nil when the candidate is already the best or second-best for that slot, preventing the item-vs-itself baseline from generating misleading positive deltas.

Changed

  • Wrathion bonus is now copy-on-apply. Replaced Sockets.ApplyWrathionBonus(stats, itemLink) (in-place mutator) with Sockets.WrathionAdjustedStats(stats, itemLink) (returns either the input table or a shallow copy with prismaticsocket+1). Required so the LRU-cached raw stats table from Extract.Read isn't mutated on each scored hover; the cache stays clean.
  • StatExtract cache cleared alongside BestItems cache. BestItems.Invalidate now also calls ns.StatExtract_ClearCache() so equipment / bag / vendor / spec events flush both caches together.

Diagnostics

  • /gm wrathion <itemID> prints whether an itemID is Wrathion-eligible plus a with/without score comparison.

[v2.7.0-release] - 05/25/2026

In-Game

  • Items your class can't equip (a wand on a Warrior, a 2H mace on a Rogue, a polearm on a Mage, etc) no longer falsely score as upgrades.
  • On retail, the GearMatic upgrade line now appears on bag item tooltips and the green up-arrow now appears on bag item icons. Both were missing on the new combined bag UI.
  • Auto-equip is smarter: it won't try to swap your shield for a 1H weapon when your spec can't dual-wield, and it won't claim it equipped something when the game silently blocked the swap. Duplicate "equipped X" toasts on /reload are gone.
  • Removed the login pop-up nag on retail. Retail scoring runs on GearMatic's own bundled stat weights.

Added

  • Class weapon-proficiency gate. New Scales/weapon_proficiency.lua carries a per-class banned-subclass table keyed by Blizzard subClassID integers (0..19 from Enum.ItemWeaponSubclass). Score.ScoreItem consults the gate via C_Item.GetItemInfoInstant for classID == 2 items and short-circuits to (0, false) when the class can't wield that subclass. Runtime patch adds [0] Axe1H to ROGUE's banned set on Classic / TBC.
  • Right-hand tooltip text extraction. StatExtract.readTooltipLinesViaDataAPI and readTooltipLinesViaFrame now walk both leftText and rightText (and TextRight<N> font strings) per line. StatNormalize adds a ^STAT_SPEED %s+(N.NN)$ pattern that captures weapon attack speed into stats.weaponspeed. Score.ScoreItem applies the SpeedBaseline subtraction when the active scale defines speedBaseline. Dormant on every bundled scale today, ready for future SpeedBaseline scales.
  • Per-method hooksecurefunc fan-out on retail. ItemTooltipHook.lua now hooks 21 named GameTooltip:Set* methods (SetBagItem, SetInventoryItem, SetHyperlink, SetItemByID, SetBuybackItem, SetMerchantItem, SetLootItem, SetLootRollItem, SetQuestItem, SetQuestLogItem, SetSendMailItem, SetInboxItem, SetTradePlayerItem, SetTradeTargetItem, SetTradeSkillItem, SetGuildBankItem, SetHeirloomByItemID, SetRecipeResultItem, SetVoidItem, SetVoidDepositItem, SetVoidWithdrawalItem) plus ItemRefTooltip:SetHyperlink, :SetItemByID, and ShoppingTooltip1/2:SetHyperlink, in addition to the existing TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, ...) path. Bag tooltips on retail 11.0+'s combined bag UI do not route through TooltipDataProcessor for the candidate-side tooltip, so the line was missing pre-2.7. Per-method hooks resolve the link from the call args and dispatch to the same appendUpgradeLines flow. Re-entrancy guarded by tooltip.__gmInUse + alreadyAdded.

Fixed

  • Bag overlay missing on retail combined bag. BagOverlay.looksLikeBagItemButton and getButtonItemLink now recognize the modern ItemButton mixin via :GetBagID() and :GetSlotAndBagID(), on top of the legacy .bag / .info.hyperlink checks. Retail 11.0+ ContainerFrameCombinedBagsSlot<N> buttons now get the green up-chevron overlay.
  • Tooltip line hanging outside the tooltip border on retail. appendUpgradeLinesImpl now calls tooltip:Show() on every flavor after addLineBold, not only on Classic. Per-method hooksecurefunc on GameTooltip:SetBagItem fires after the tooltip finished its layout pass; without an explicit Show() the backdrop did not grow to wrap the new line.
  • Auto-equip toast printing even when the equip silently failed. AutoEquip.RunSweep now compares GetInventoryItemLink(targetSlot) before vs after EquipCursorItem and only counts the equip + prints the toast when the slot's item id flipped to the candidate's id. EquipCursorItem clears the cursor even on a silent rejection (item-class restriction, ilvl gate), so the prior if CursorHasItem() then ... else equipped+1 check produced false positives.
  • Auto-equip targeting the shield slot for a 1H weapon. New slotHoldsShieldOrHoldable(17) guard in findBestSwapForLink restricts INVTYPE_WEAPON candidates to {16} when the off-hand currently holds an INVTYPE_SHIELD or INVTYPE_HOLDABLE. The lower-score-wins picker was choosing slot 17 (shield) for a 1H weapon on Resto Shaman because Resto's intellect-heavy scale rates shields lower than 1H weapons; the resulting EquipCursorItem(17) silently failed because Resto can't dual-wield.
  • Duplicate auto-equip toast on /reload. New sweepPending / sweepInProgress flags in the OnEvent handler ensure only one sweep is scheduled or running at a time. BAG_UPDATE_DELAYED + PLAYER_ENTERING_WORLD both schedule a sweep on /reload, and the new combined bag's BAG_UPDATE_DELAYED can fire multiple times in quick succession; racing sweeps were each finding the same upgrade in flight and printing the toast twice.
  • /gm score silent on retail. Debug/Score.lua installHooks was calling GameTooltip:HookScript("OnTooltipSetItem", ...) at file load time; retail 10.0.2+ removed the OnTooltipSetItem script handler, the HookScript threw, file load aborted, and ns.Debug.Score.RunForHoveredItem was never assigned. Every HookScript is now pcall-guarded and a TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, ...) parallel registration keeps the link-cache working on retail.

Changed

  • Bag overlay chevron now sits 5px inside the item's top-right corner (was 1px outside) for visual breathing room against the new bag UI's slot icons.
  • Removed the retail login nag that prompted players to install a third-party scoring addon. Retail bundled scales (39 specs across 13 classes) drive scoring directly. Removed L["nag_retail_pawn"] from every locale and dropped the C_Timer.After(5, function() print(...) end) block in Core.lua:OnPlayerLogin.

Diagnostics

  • /gm score dumps S2.Extract.Read, Extract.ReadViaAPI, and Extract.ReadViaTooltip results per item so the stat pipeline can be inspected end-to-end.
  • /gm score prints the tooltip-line gate states (autoEnabled, Compat.CanWearItem, isCurrentlyEquipped, minLevel / playerLevel / equipLoc / classID / subclassID) so a missing GearMatic line can be localised to a specific gate.

[v2.6.0-release] - 05/25/2026

In-Game

  • Quest reward items now show a green chevron on every icon that's an upgrade for any of your character's specs. If the item is wearable only by another character on your account, the chevron shows yellow instead.
  • Tooltip upgrade line is cleaner: a single arrow instead of doubled, and duplicate lines from refresh cycles no longer stack.
  • Auto-equip is now ON by default for new characters. You can still turn it off in Settings.
  • Two unused toggles were removed from the Stat Import tab in Settings.

Added

  • Quest reward overlay rewrite (Pawn-aligned). QuestRewardHook.lua now hooks QuestInfo_Display with a template.elements filter for QuestInfo_ShowRewards, mirrors Pawn's positional indexing (choices first 1..N, statics N+1..N+M), iterates both GetNumQuestChoices and GetNumQuestRewards, supports the quest-log pane via GetNumQuestLogRewards / GetNumQuestLogChoices / SetQuestLogItem, and uses a hidden scanner tooltip's SetQuestItem / SetQuestLogItem + :GetItem() to bypass the 9.0+ GetQuestItemLink bug. Buttons resolved via QuestInfo_GetRewardButton(QuestInfoFrame.rewardsFrame, idx) with _G name fallback for classic.
  • Multi-spec quest reward evaluation. New Compare.EvaluateAgainstScale(scale) and S2.EvaluateAgainstScale bypass the off-spec gate so an item that's an upgrade for any of your class's scales (current spec, alt specs, bundled defaults) gets the overlay - not just the active spec.

Fixed

  • Tooltip duplicate-line dedup. appendUpgradeLines now skips appending if a "GearMatic" header is already present in the tooltip; prevents TooltipDataProcessor refresh cycles from stacking duplicate upgrade lines on the same hover.
  • Quest reward overlay was only marking ONE "best winner". Dropped the priority/armor-tie-break filter; every wearable upgrade now gets the green chevron, matching the Pawn UX.
  • Quest reward overlay missed static-only rewards. The old code's if count <= 1 then return end killed decoration whenever there were no choice items - many quests give all rewards as static and got nothing.

Changed

  • Tooltip chevron uses a single up/down arrow (was doubled) to match Pawn's tooltip visual.
  • Quest reward chevron overlay anchor shifted from -2, -2 to -7, -2 so the icon sits 5px further inside the button's right edge.
  • Tooltip chevron texture has a -5 inline offset so the arrow sits flush against the spec text instead of leaving a gap.
  • autoEquipUpgrades default flipped from false to true. New characters opt into the auto-equip behavior by default; existing characters keep whatever value is already in SavedVariables.
  • Removed GearMaticDB.settings.deferToPawn (Settings row, Core default, and the BagOverlay guard that consulted it). The bag-overlay path now always evaluates via our own scoring, no Pawn-defer wrapper.
  • Removed GearMaticDB.settings.preferPawnWeights (Settings row, Core default, and the ScaleImport.GetActiveScale branch that auto-picked a Pawn scale when both addons were loaded). Active scale now always comes from the character's own bag (_active first, then any class-matching scale, then bundled defaults). The bestPawnScaleFor helper is removed as it had no remaining callers.

[v2.5.0] - 05/25/2026

In-Game

  • Retail (The War Within) is supported. Every modern spec across all 13 classes ships with bundled stat weights. Hover an item and the GearMatic line shows the upgrade % for your current spec.
  • Items restricted to a different spec (the "For X specialization" line in the tooltip) no longer score as an upgrade for your current spec.
  • The upgrade line in the tooltip is now compact and easier to scan: bold text, your spec name in your class color, the colon in your class color, and an up/down arrow showing direction.
  • Sidegrades (0% lines) are no longer shown. The tooltip only adds a line when the item is meaningfully better or worse.
  • Paste a stat-weight string from Raidbots or Wowhead with /gm import ( ... ). Works on every flavor.
  • Revert to the bundled defaults with /gm reset, or just drop a pasted scale with /gm clear pasted.
  • New /gmc slash command opens a copyable window with the last 200 chat lines, for getting chat output out of WoW.

Added

  • Retail flavor TOC. GearMatic_Mainline.toc (Interface 120005) wired into the BigWigs packager so retail builds populate alongside Classic flavors.
  • Bundled Pawn-parity weights for all 39 modern retail specs, including Evoker (Devastation / Preservation / Augmentation) and Demon Hunter (Havoc / Vengeance). Generated from Pawn's ScaleTemplates.lua via tools/gm_emit_retail.py with verified zero weight drift across all 39 specs.
  • Tertiary stat extraction: leech, speed, avoidance are now read from item tooltips and scored if the active scale weights them.
  • Universal Pawn-format import (( Pawn: v1: Name=...: stat=value, ... )) handled on every flavor. Pasted scales tagged with source = "pasted" so the companion-program skull rule still distinguishes them from gearmatic-sim scales.
  • Reset / clear slash commands: /gm clear pasted drops the current character's pasted scale and reverts to the bundled default. /gm reset clears every imported / sim / pasted scale on the current character.
  • /gm copychat / /gmc opens a scrollable EditBox with the last 200 chat lines, color codes stripped, highlight-all preselected.

Fixed

  • Retail tooltip line wasn't rendering at all because GameTooltip:GetItem() returns nil on 10.0.2+. Switched the retail hook path to TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, ...) with re-entrancy guarding to stop the recursion loop that froze the client.
  • Retail stat extraction now uses C_TooltipInfo.GetHyperlink as the primary source (matches what Pawn reads) with the legacy frame scanner as a Classic fallback. The previous mix of GetItemStats + frame scanner produced inflated numbers because it counted hidden API-only stats that Pawn never sees.
  • Off-spec items: gate consults C_Item.GetItemSpecInfo first and falls back to a tooltip-text scan ("For X specialization") for low-level quest rewards that ship without spec metadata.
  • Baseline math: the worst-equipped slot scan now skips empty slots and clamps near-zero baselines via an epsilon, so a single low-armor off-hand can't blow the upgrade % up into the hundreds.
  • 1H weapon comparison: when the off-hand currently holds a shield or holdable, the baseline scan excludes slot 17 so a 1H weapon is compared against the main-hand baseline alone (matches Pawn's UnusableStats = { "IsOffHand" } shape).
  • Pawn-import alias keys: import paths map resiliencerating -> resilience, armorpenrating -> armorpen, and route ranged / feral attack power into their dedicated extractor keys instead of collapsing into the generic attackpower bucket.

Changed

  • Tooltip line format: spec icon + class-colored spec name + class-colored colon + double up/down arrow + bold pct text. Drops the prior wordy "for current" phrasing in favor of the compact <icon> <Spec>: >>+X% upgrade shape.
  • references/pawn/ checked into the repo as the canonical reference for parity work (Pawn 2.13.11 source).

[v2.4.7-release] - 05/24/2026

In-Game

  • The upgrade % shown in the tooltip is now more accurate on Anniversary, Era, SoD, Classic and TBC characters.
  • Druid Feral DPS and Feral Tank now have their own bundled stat weights on Anniversary, Era, SoD, Classic and TBC (previously only Balance and Restoration shipped).

Fixed

  • Full Pawn parity for the bundled TBC and Vanilla (Anniversary / Era / SoD) scales. The prior blocks used import-alias stat keys (resiliencerating, armorpenrating) that never matched the keys GearMatic's stat extractor actually produces (resilience, armorpen), so those weights silently scored zero. Ranged AP and Feral AP were stored under attackpower instead of the extractor's rangedattackpower / feralattackpower. Vanilla armor-penetration weights were stored as the raw Pawn coefficient instead of the rating-per-percent expanded value (e.g. Arms armorpen was 1.1 instead of 3.75 * 1.1 = 4.125). Regenerated both blocks verbatim from Pawn's ClassicHawsJon templates with the correct extractor keys, added the tie-breaker stats Pawn ships (per-school resists, hp5, mana, defenserating, dodgerating, parryrating, metasocketeffect, allresist), and added the missing Druid Feral DPS + Feral Tank specs. Verified 0 weight drift against Pawn across all 28 TBC + 28 Vanilla + 34 Mists specs.

[v2.4.6-release] - 05/19/2026

Changed

  • Excluded *.png source image files from the packaged .zip via .pkgmeta ignore. WoW only loads .tga at runtime; the PNGs (Logo.png 2.7 MB, Textures/GearMatic-Medallion.png 2.2 MB) were source-only and added ~5 MB of dead weight to every download.

[v2.4.5-release] - 05/19/2026

In-Game

  • Your spec now shows up correctly on Mists Classic (Disc Priest, Resto Druid, Prot Warrior, etc). The loadout window header, the /gm browser, and stat-weight matching all read the right spec again.
  • Discord link in General Settings now points at the shared GearMatic / CritMatic / RepMatic Discord server.

Fixed

  • Spec detection on Mists Classic 5.5.x (_classic_ flavor). Blizzard moved every spec / talent global into the new C_SpecializationInfo namespace; the legacy GetSpecialization / GetSpecializationInfo globals return nil unless the player runs /console loadDeprecationFallbacks 1. Scanner.detectSpecName now probes C_SpecializationInfo.GetSpecialization first and falls through to the unqualified globals for Cata / Wrath / Vanilla. Without this, the GearMatic Loadout window and SavedVariables for Mists Classic characters lost their spec label even when the character clearly had an active spec in-game. v2.3.1 added the pcall wrap; v2.4.5 adds the actual namespace path that returns the spec name.

Added

  • Talent + glyph capture in SavedVariables. Scanner.detectTalents now reads the player's active spec group + the selected tier/column picks (via C_SpecializationInfo.GetTalentInfo on Mists Classic, GetTalentInfo on Cata/Wrath, falling back to the 3-tab GetTalentTabInfo model on TBC/Vanilla). Scanner.detectGlyphs reads enabled glyph sockets via GetGlyphSocketInfo. Both persist into GearMaticDB.chars[charKey].talents / .glyphs on every scan and on Scanner.RefreshSpec, ready for downstream features.

[v2.4.1-release] - 05/18/2026

In-Game

  • Fixed a game freeze when trying to log out or exit. Quitting WoW with GearMatic enabled used to throw an "action blocked" error and lock the exit dialog. The exit flow is clean now.

Fixed

  • Critical: ADDON_ACTION_FORBIDDEN blocking game exit. Two files contained StaticPopupDialogs = StaticPopupDialogs or {} (Loadouts/Sidebar.lua and Loadouts/SpecHook.lua). Even though or short-circuits to the existing Blizzard table, the assignment writes the global, which marks _G.StaticPopupDialogs as having been written by GearMatic. WoW's taint system then propagated that flag through every subsequent secure read of the table, including Blizzard_StaticPopup's lookup of FORCE_QUIT.OnAccept during the exit dialog, which forbade the protected ForceQuit() call. Removed both fallback assignments; entries are now added with direct key writes (StaticPopupDialogs["GEARMATIC_..."] = { ... }), which mutate keys without writing the global itself.

[v2.4.0-release] - 05/18/2026

In-Game

  • Loadouts launched on Vanilla and TBC. Save named gear sets per character and swap between them with one click.
  • Sidebar lives on the Character window. Toggle it with the new chestplate button next to the close X.
  • Double-click a loadout to equip it; drag it onto an action bar to make a one-click macro; right-click for Rename, Change Icon, Save Current, Export, Delete.
  • Alt-hover any equipment slot for a per-slot menu: Ignore Slot, Place In Bags, or pick a replacement from a grid of candidates in your bags.
  • Built-in icon picker with search and Items / Spells filtering.
  • Party / raid / guild GearMatic users see your loadout swaps in chat (toggleable in Settings; never SAY/YELL).
  • Spec change prompts a non-intrusive "switch to loadout X?" popup. Never auto-swaps gear. "Don't ask again" supported per character.
  • New /gm subcommands: loadouts, save, load, rename, delete, export, import, unequip, icon.
  • Loadouts tab in Settings on Vanilla and TBC. Wrath / Cata / Mists keep using Blizzard's built-in Equipment Manager.
  • Loadout strings export with a new GMLOv2 format. Old GMLO:01 codes prompt you to save and re-export.
  • Full translations for every new string in all 12 supported locales.

Added

  • Loadouts (Vanilla and TBC only): save and switch named gear sets per character with full Gears-parity UX.
  • PaperDoll-attached sidebar with toggle button on the character frame title strip.
  • Double-click a loadout row to equip; drag onto an action bar; right-click for context menu (Rename / Change Icon / Save Current / Export / Delete).
  • Alt-hover any equipment slot for a per-slot flyout: Ignore Slot, Place In Bags, and a grid of candidate replacement items from bags (one-click swap).
  • Built-in icon picker (uses Blizzard's IconDataProviderMixin) with search and All/Items/Spells filter.
  • AceComm peer broadcast of loadout swaps to party/raid/guild GearMatic users, with a 5-second per-sender throttle. Only fires on real swaps; never SAY/YELL; toggleable in Settings.
  • Drag-to-action-bar via per-character macros, auto-recreated on rename. Macro slot cap honors MAX_CHARACTER_MACROS.
  • Non-modal spec-change suggest popup; per-character "don't ask" list. Never auto-swaps.
  • New /gm subcommands: loadouts, save, load, rename, delete, export, import, unequip, icon.
  • Settings tab "Loadouts" appears only on Vanilla and TBC.
  • Loadout strings export as GMLOv2:.... Legacy GMLO:01: exports prompt the user to save and re-export.
  • Translations for every new key into all 12 supported locales (enUS, enGB, deDE, esES, esMX, frFR, itIT, koKR, ptBR, ruRU, zhCN, zhTW).
  • Wrath / Cata / Mists are intentionally not supported, those clients have Blizzard's built-in Equipment Manager.
  • Sidebar title icon: silver portrait ring (BlueMenuRing desaturated + cool tint) with the new GearMatic-Medallion brand artwork, parked on the CharacterFrame title bar over the X close button. Ring + medallion show/hide together with the sidebar.
  • Sidebar visibility is now persisted per character in GearMaticDB.settings.loadoutSidebarShown. Toggling off via the paperdoll button (or the sidebar X) stays off across /reload and CharacterFrame re-opens; default is on for fresh installs.
  • Sidebar title bar reanchored to fill the full width: TopLeftCorner switched to the clean UI-Frame-TopCornerLeft texcoords and TopBorder + LeftBorder reanchored off the new corner so the gold strip no longer cuts off where the old portrait socket used to overhang.
  • "Add new loadout" row renders "ADD" in Anton 18pt next to the green plus icon.

[v2.3.1-release] - 05/16/2026

In-Game

  • Fixed /gm scan and the /gm browser on Mists Classic 5.5.3. Previously the browser showed mostly empty slot squares despite your character having a full gear set, and /gm scan appeared to do nothing.
  • Slot icons no longer go blank right after login. Item icons are cached when scanning so the browser fills in immediately.
  • Equipping or swapping an item never wipes the previous slot data, even if WoW's item info isn't loaded yet.

Fixed

  • Critical: MoP Classic 5.5.3 scan abort. Scanner.detectSpecName called GetNumTalentTabs / GetTalentTabInfo after a type(...) == "function" check. Blizzard kept the function symbols but now throws "Script_GetNumTalentTabs: API unsupported in this version of World of Warcraft." on call, which aborted both Scanner.RefreshSpec and Scanner.ScanCurrentCharacter silently (no chat error unless /console scriptErrors 1 was set). Symptoms on MoP Classic: /gm scan appeared to do nothing, the /gm browser showed mostly empty slot squares despite full gear, and saved-vars drifted down to a handful of stale slots. Fix: every legacy talent-API call (and the modern GetSpecialization calls, defense in depth) is now pcall-wrapped; on failure detectSpecName returns nil and the caller falls through to the prior entry.spec value so the rest of the scan completes normally.
  • Slot grid icons rendering blank against cold item-info cache. The /gm browser called GetItemIcon(itemLink) live at paint time, which returns nil for items WoW has evicted from its per-item cache (common right after login for items the player has not interacted with). With no GET_ITEM_INFO_RECEIVED repaint hook, those slots stayed blank until the cache warmed up. Fix: Scanner.readSlot now captures the icon at scan time (from GetItemInfo's 10th return, falling back to GetItemIcon), persists it on the saved slot entry, and the browser's paintSlot prefers slotData.icon before the live lookups.
  • Slot data wiped on cold-cache reads. Scanner.ScanCurrentCharacter and Scanner.RescanSlot both overwrote a slot with nil whenever readSlot returned no link AND no id, even when the slot had real data from a previous session. On a fresh login this could persist a 19-slot character with only 4 surviving slots once cache warmed too slowly. Fix: when readSlot reports nil for a slot we already had data for, treat as ambiguous (cold cache, not a real unequip) and trigger a retry instead of wiping. RescanSlot gains a per-call retry counter so PLAYER_EQUIPMENT_CHANGED firing before item info loads no longer destroys saved data. Initial-scan retry budget bumped from 5 to 10 (2.5s -> 5s).
  • AutoEquip wrote partial slot entries. After equipping, AutoEquip.refreshSlotInData set entry.slots[slotID] = { itemLink = link } and nothing else. itemID, itemLevel, rarity, name, classID, durability all stayed nil on the affected slot. Compat.AverageItemLevel silently skipped the partial slot when computing iLvl, and the browser had nothing to display beyond the link. Fix: after capturing the link, run GetItemInfo once and persist the full slot shape (itemID, itemLevel, rarity, name, icon, classID, durability, durabilityMax), matching Scanner.readSlot. Also stops wiping the slot on transient nil link reads right after EquipCursorItem, which the API can return for a frame on Classic clients.

Static syntax check (luac -p) clean across every Lua module before tagging.

[v2.3.0-release] - 05/16/2026

In-Game

  • On-screen alert banner pops every time you equip a piece. Big icon, a colored arrow (double green = upgrade, single green = side / first-fill, red = downgrade), and a percent number for the score change. Upgrades chime, downgrades play the raid-warning sound.
  • Settings panel rebuilt into seven cleaner tabs (General, Detection, Alert Font, Sound, Social, Stat Import, Change Log).
  • Nineteen new sounds bundled (LevelUp, Solid-Alert, Heroism Cast, Magic Beam, Jedi Beam, Batman Punch, Blue / Green Portal, Thunder, Whoop, Codec, Clamps, Blast, Coin, Shotgun, Boop, Combo Breaker, Done, Heaven) and selectable for the upgrade chime.
  • Smarter scoring for low-level alts: every new piece is scored correctly from level 1, even before you pick a spec.
  • Wrong armor type is now heavily penalized so leather on a warrior or mail on a mage stops looking like an upgrade.
  • Heirlooms get a small score bump and are protected from being recommended as a swap target.
  • Quest items and a built-in locked-item list (fishing poles, specialty pieces) are protected from auto-equip and from upgrade recommendations.
  • Fix: stopped showing "+100% upgrade" on every white item.
  • Twelve-locale translation coverage for every new string.

Added

  • On-screen gear alert. Equip any piece and a banner pops with the item icon, a coloured chevron, and a score-delta percent. Upgrades show a double green chevron with a "Level Up" chime; downgrades show a red chevron with the WoW raid-warning sound; sidegrades and first-fills get a single green chevron. Sound only plays the first time you ever equip a given item on that character so repeat swaps stay quiet. Banner position, font (LibSharedMedia), colours, format strings, max stacked messages, start delay, fade time, and uppercase treatment are all configurable in the new Alert Font sub-tab. Manual previews via /gm test (upgrade) and /gm test2 (downrank).
  • Settings panel restructure into seven tabs. General (alert toggle, chat toggle, minimap, changelog popup, Support, About), Detection (the old tracking + smart-detect + auto-equip controls), Alert Font (sub-tabs for General, Notification format, Font), Sound (Upgrade sound on top, Downrank sound, Mute all), Social (unchanged), Stat Import (unchanged), Change Log (toggle + Open Now button).
  • Bundled sound library. Nineteen OGGs ship with the addon (LevelUp, Solid-Alert, Heroism_Cast, MagicBeam, JediBeam, BatmanPunch, BluePortal, GreenPortal, Thunder, Whoop, Codec, Clamps, Blast, Coin, Shotgun, Boop, COMBO-BREAKER, Done, Heaven) all registered with LibSharedMedia so they appear in every LSM-aware dropdown across your UI. Plus Raid Warning registered against Blizzard's built-in chime as the default Downrank sound.
  • Class-default stat weights for low-level alts. Spec-less characters (level 1-9 with no talent points) now fall back to a class-wide weight set instead of the rarity-and-ilvl heuristic, so a fresh hunter scores every quest reward correctly from level 1. The bundled wowsims defaults still take over the moment a spec is detected.
  • Armor proficiency penalty in scoring. Cloth on a level-50 warrior, leather on a level-50 hunter, and similar wrong-tier pieces get heavy score multipliers so they stop showing as upgrades over the proper armor type. Soft 10-percent penalty inside a ten-level grace window, hard 50-percent past it. Foreign armor types your class can't wear at all (e.g. mail on a mage) score at five percent.
  • Stat overcap halving. When your current hit, spell-hit, or expertise rating is already past the soft cap, GearMatic halves that stat's weight when scoring new pieces so it doesn't recommend you stack what you already cap.
  • Heirloom score bias. Heirloom-quality items get a 10 percent score boost so they don't lose to slightly higher-ilvl quest greens. Heirlooms are also protected against being recommended as swap targets when the equipped piece is also an heirloom.
  • Quest / locked-item protection. Quest-bound items are never flagged as upgrade swaps or picked up by auto-equip. A built-in locked-ID list shields fishing poles and specialty gear loadouts from being clobbered by a regular weapon recommendation.
  • Implicit armor weight. Stat-weighted scoring now also credits the raw armor value of a piece at the minimum positive weight times 0.1, so an armor-rich piece doesn't lose to a stat-equal but armor-light piece when the scale doesn't explicitly weight ARMOR.
  • Branded chat output helper. New ns:Print() prefixes every chat line GearMatic emits with the purple brand color. Load message moved off ADDON_LOADED onto a delayed C_Timer.After on PLAYER_LOGIN (8 seconds if ElvUI is loaded, 4 seconds otherwise) so it lands after the chat-frame splash instead of being hidden under it.
  • Twelve-locale coverage for every new string. Fifty-four new keys translated into enGB, deDE, esES, esMX, frFR, itIT, koKR, ptBR, ruRU, zhCN, zhTW. Slot names in the alert chat-line now read from the WoW client's localized INVTYPE_* globals.

Fixed

  • "+100% upgrade for current spec" bug on every white item. Scoring now reads live GetInventoryItemLink("player", slotID) for the logged-in character instead of trusting the saved-vars snapshot, and refuses to claim +100% when the equipped slot has an item we just couldn't score yet (returns nil so the tooltip line is suppressed entirely rather than lying). Truly empty slots still get a +100% correctly. Alts whose gear has never been scanned are also suppressed so the tooltip doesn't spam fake upgrades for every untracked alt.
  • GetItemStats guarded for Vanilla. Wrapped the call so the absent-on-Classic-Era API falls cleanly into the fallback path instead of hard-erroring.

Changed

  • All print() and chat output routed through localization. slash_auto_*, slash_clear_usage, slash_equip_none, slash_scan_done, autoequip_in_combat, autoequip_missing_api, autoequip_cursor_abort, comm_no_peers, scaleimport_no_profiles, pawn_not_loaded, nag_retail_pawn, settings_libs_missing, and alert_chat_equipped all flow through ns.L[] now.
  • Every Lua comment stripped from the project. Cleaner codebase; behavior unchanged. TOC ## directives are not comments and stay.

Static syntax check (luac -p) clean across every Lua module before tagging.

[v2.2.0-release] - 05/15/2026

In-Game

  • X / Twitter row added to the About section in Settings, under the Infinite Loop Alchemist profile name.

Added

  • X / Twitter row in the About section. New Textures/x-logo.tga (128x128 RGBA, bottom-left origin, matches the existing Buy Me A Coffee asset) plus an X icon and copyable https://x.com/infiniteloopalc input rendered directly under the "Infinite Loop Alchemist" profile name. Strings localized in all 12 locales via settings_about_x.

Static syntax check (luac -p) clean across every Lua module before tagging.

[v2.1.0-release] - 05/10/2026

Added

  • GearMatic-to-GearMatic version ping over AceComm-3.0. New Comm.lua module registers the addon-message prefix GearMatic and broadcasts VER:<x.y.z> once on PLAYER_LOGIN to GUILD plus the appropriate group channel (INSTANCE_CHAT in instances, else RAID, else PARTY). Peers' versions are silently collected into ns.Comm.peers. New /gm peers slash subcommand prints which guildmates / party / raid members are running GearMatic this session, so the channel is testable without a UI. Plumbing only at this stage; no loot-drop or upgrade-broadcast wiring yet.

Changed

  • TOC Interface numbers refreshed to current live Classic builds so the addon stops reporting "Out of Date" on launch:
    • GearMatic_Mists.toc: 50500 -> 50503 (MoP Classic 5.5.3)
    • GearMatic_Wrath.toc: 30403 -> 38001 (Wrath / Titan Reforged)
    • GearMatic_Vanilla.toc: 11508 (unchanged, Classic Era 1.15.8)
    • GearMatic_TBC.toc: 20505 (unchanged, TBC Anniversary 2.5.5)
    • GearMatic_Cata.toc: 40402 (unchanged)

Removed

  • GearMatic_Mainline.toc deleted; retail / Mainline is no longer a supported flavor. Two reasons stack here:

    1. wowsims (https://wowsims.github.io/) does not target retail, so the Pawn-format scoring weights GearMatic relies on don't exist for Midnight specs. The addon's core "is this an upgrade for my spec" decision has nothing to read against on retail.
    2. Blizzard's patch 12.0 ("Midnight") combat-addon block, which the Ace3 maintainer summarized as "Blizzard blocked the ability to use the COMBAT_LOG_EVENT_UNFILTERED event", knocks out the broader ecosystem this addon was designed to live in.

    Will be reconsidered if/when wowsims publishes retail weights and Blizzard relaxes the addon API restrictions.

Static syntax check (luac -p) clean across every Lua module before tagging.

[v2.0.1-release] - 05/09/2026

Fixed

  • Auto-equip no longer ping-pongs items in and out of the same slot when the addon's slot snapshot is briefly empty. Scanner.readSlot used to wipe a slot whenever GetInventoryItemLink returned nil, which it does for a frame on Classic / Anniversary right after EquipCursorItem and during the inventory-loading window on login. A wiped slot looked "empty" to the next sweep and triggered a "+100% over empty" stomp, kicking off Frayed Shoes / Thug Boots back-and-forth swaps even when the player already had the better piece equipped. Scanner now treats a nil link with a present GetInventoryItemID as needs-retry instead of empty, so valid slot data is never erased by a transient API hiccup.
  • AutoEquip cross-checks the live inventory before trusting an empty DB slot. Belt-and-suspenders for the Scanner fix: even if the DB says slot 8 is empty, AutoEquip now calls GetInventoryItemLink("player", targetSlot) once before the safety check; if the live API reports an item, it syncs the DB back to that link and rescores so we never equip "+100% over empty" against a real piece.

Changed

  • Changelog popup now uses the same parchment + wood-border look as CritMatic. Switched from the Blizzard Tooltip (dark) backdrop to Blizzard Parchment 2 background with a Blizzard Achievement Wood border at edge size 15. Body text is now MoK 15pt in dark grey (0.2, 0.2, 0.2) so it reads cleanly on the parchment, with Anton kept as a fallback if MoK is unavailable. Same CritMatic palette, same warm "old paper" feel.

[v2.0.0-release] - 05/09/2026

Removed (breaking)

  • Send to /say toggle and the SAY broadcast path are gone. /say is muted in instances by Blizzard, and on Classic / Anniversary the post-EquipCursorItem timing made the broadcast unreliable in practice. Removing the option entirely is cleaner than continuing to ship a half-working channel. Group channels (PARTY / RAID / INSTANCE_CHAT) and GUILD remain. Existing GearMaticDB.settings.social.sendToSay = true saved-vars are now silently ignored.

Changed

  • Social channel selection rewritten in the Questie style. Modeled on Questie's _QuestieAnnounce.GetChatMessageChannel: a single group-context channel is picked based on where the player is (battleground -> INSTANCE_CHAT, raid -> RAID or INSTANCE_CHAT for LFG, party -> PARTY or INSTANCE_CHAT for LFG), and GUILD is added as an additional simulcast when toggled and you're in a guild. No more "blast to SAY + GUILD + PARTY all at once" - one group channel, plus guild.
  • Brand color is now purple #9212d5 everywhere. Replaced the old soft-blue #7777ff across chat lines, tooltip score header, minimap button tooltip, Loadout window title, the new in-game popup, and the load message so the addon reads consistently in chat.

Added

  • In-game changelog popup, modeled on CritMatic's. Shows automatically on first login after a version bump (gated on a new General-tab toggle "Show changelog popup on update", default on), with the same AceGUI Frame + ScrollFrame layout, grey body text, and Anton font as CritMatic. Manual open with /gm changelog (or /gm log). Capped at the latest 3 release entries plus a pointer to the full CHANGE_LOG.md on GitHub or CurseForge.
  • /gmhelp slash command alias that prints the full slash-command help directly, matching CritMatic's /cmhelp. The original /gm help still works.
  • Branded multi-color load message, modeled on CritMatic's: GearMatic: v X.Y.Z Loaded! - Use /gm for options - /gmhelp for all slash commands, with the addon name and slash commands in purple and the body text grey.
  • Login chat is quieter. The "GearMatic: smart upgrade detection is on. Type /gm auto off to disable." hint and the "GearMatic: registered config under Interface > AddOns > GearMatic (or just type /gm)." line are removed. The branded load message is now the only chat output on login.

Fixed

  • Auto-equip no longer stomps a just-equipped upgrade with a worse bag item in the same sweep. When two candidates for the same slot lived in your bags (e.g. Frayed Shoes + Thug Boots in feet), the sweep equipped the first one, then on the very next iteration still saw the slot as empty/weak in its in-memory snapshot, scored the second item as "+100% over empty", and equipped it over the first. Both items would show "+100%" in chat and you'd end up with the worse one equipped and the better one back in your bag. The sweep now refreshes the in-memory equipped snapshot from the known bag link after each successful equip, rather than calling GetInventoryItemLink (which can return nil for a frame on Classic / Anniversary right after EquipCursorItem and would erase the snapshot we just wrote). Subsequent candidates always compare against what was just equipped.
  • Auto-equip weapon swaps no longer leave a ghost off-hand/main-hand entry in the in-memory snapshot. Equipping a two-hander correctly clears slot 17 (the displaced off-hand) from the snapshot, and equipping a shield / off-hand / holdable into slot 17 over a two-hander correctly clears slot 16. Prevents stale weapon-slot entries from biasing later iterations of the same sweep and from showing the wrong off-hand in the loadout window until the next full scan.
  • /say (and other Social) broadcasts no longer drop on auto-equip swaps. The Social handler used GetInventoryItemLink to read the just-equipped item, but on Classic / Anniversary that API can return nil for one frame right after EquipCursorItem, which made Social.OnEquipChange bail at if not id then return end and never reach SendChatMessage. AutoEquip now hands Social the known bag link directly via a new Social.RecordEquip path, which broadcasts immediately and updates the lastEquipped cache. The PLAYER_EQUIPMENT_CHANGED handler still services player-driven (drag-drop, EquipmentManager) equips, with a 1-second post-RecordEquip guard that ignores nil-link timing glitches without breaking real unequip detection.
  • Scoring.ScoreItem no longer returns nil for armor-only items. On Classic, low-level gear like Frayed Shoes or Thug Boots may have GetItemStats return nil because they only carry an armor value. The previous code returned nil in that case, which downstream code read as a score of 0 and produced phantom "+100% over equipped" deltas during a sweep. ScoreItem now falls back to ilvl-rarity scoring (with the fallback flag set, so the auto-equip occupied-slot safety hardening still requires a real stat-weighted scale before swapping).
  • Fallback score now reads the actual armor value from the item tooltip and weights it heavily. Without this, low-level Vanilla gear scored only on ilvl * rarity_multiplier, so a higher-rarity / equal-ilvl piece with zero armor could outscore a lower-rarity piece with 5+ armor and auto-equip would pick the worse one. Scoring now opens a hidden tooltip frame, reads the "X Armor" line, caches the result by item ID, and folds armor into the fallback score at 10x weight (ilvl * rarity_mult + armor * 10) so armor is the dominant signal for armor pieces. Frayed Shoes (5 armor) now reliably beats Thug Boots (0 armor) on score alone.
  • Auto-equip safety hardening relaxed for armor-piece upgrades in fallback mode. The v1.0.8 hardening required a real stat-weighted scale (Pawn) before it would swap into an occupied slot. That was correct for stat-driven items where ilvl alone can mislead, but it blocked obvious armor upgrades on leveling characters with no Pawn scale. AutoEquip now allows the swap into an occupied armor slot when the candidate has strictly more armor than the equipped item (read from the live tooltip, same scanner the score uses). Applies only to true armor slots (head, shoulder, chest, waist, legs, feet, wrist, hand, cloak, shield). Non-armor slots (rings, trinkets, weapons, ranged) keep the strict v1.0.8 rule because their value is in stats, not armor. Combined with the cursor-flow hardening, the worst case is still "wrong stat priority for casters in fallback" - never a destroyed item.

Changed

  • Auto-equip success line stays branded "GearMatic" (no rename). Local chat-frame line continues to be |cff7777ffGearMatic|r equipped X (+N%). It is suppressed only when /say will actually carry the announcement (SAY toggle on, not in an instance, slot was occupied). Other Social toggles (party / raid / guild / bg) do not suppress the local print, so you always have a personal record when /say cannot fire.

Added

  • Bundled the same Anton font CritMatic uses for its alerts. Registered with LibSharedMedia as Anton. Loadout window title, header, and footer now render in Anton with an outline so the two addons share a visual identity. Falls back to Blizzard fonts if the file is missing.

Changed

  • Loadout slot textures now show clearly. Empty slot art renders at the same size as the item icon (both at full slot extent with 7%/7% texture-coord trim to remove the dark border that comes baked into Blizzard's slot art), and a dark slot background is laid behind so the slot is visible against the loadout window backdrop. Each slot uses its specific Blizzard art: Head, Neck, Shoulder, Back, Chest, Shirt, Tabard, Wrists, Hands, Waist, Legs, Feet, Finger, Trinket, MainHand, SecondaryHand, Ranged.
  • Loadout prev/next buttons are now greyed out at the boundaries: prev disabled on the first character, next disabled on the last, both disabled when only one character is tracked. The cycle no longer wraps around past the last alt.
  • Tooltip and quest/loot indicators no longer show the red downgrade chevron for sidegrades. Items in the -1% to +1% range get a clean line with no chevron prefix; only true downgrades (delta <= -1) get the red chevron.

[v1.0.8-release] - 05/09/2026

Added

  • New General-tab toggle: "Prefer Pawn weights for scoring" (default on, disabled when Pawn is not installed). When on, GearMatic auto-picks the Pawn-imported scale that matches your class (and spec when possible) and uses those weights for every scoring path (tooltip, quest reward, loot, bag overlay, browser, auto-equip). No manual "Set Active" click needed. When off, GearMatic falls back to your manually selected profile or its bundled defaults.

  • Renamed the cross-character browser to Loadout. Window title now reads "GearMatic Loadout". New slash command /gm loadout (the old /gm browser, /gm browse, /gm chars aliases still work).

  • New keybinding in General settings: "Open loadout". Bind any key to instantly open the Loadout window. Reapplied on login.

  • Quest reward chevron now uses armor value as a third tiebreaker after armor-type priority and delta. When two leather pieces tie at +100% for a Rogue, the one with more armor wins. Helps when an empty slot gives both items the same delta but one is objectively better-protected.

  • New "Run auto-equip sweep now" button in the Auto-equip group on the General tab. Triggers a single sweep on demand, even with the master toggle off. Same hardened safety path applies.

  • Auto-equip cursor flow can no longer lose an item. ClearCursor() removed entirely from the swap path. New flow: pick up the bag item → EquipCursorItem(slot) → if anything left on cursor, drop it back into the bag slot we just picked from (which is empty by definition) → if even that fails, abort with a chat message telling the user "item is on your cursor, drop it manually, nothing was lost." Worst case is the new item stays in the bag and the previously-equipped item stays equipped. There is no path to a destroyed/lost item.

  • Critical auto-equip safety hardening. Auto-equip will no longer swap into an occupied slot when GearMatic cannot make a real comparison. Specifically: an upgrade is only auto-equipped over an existing item when (a) a real stat-weight scale is active (not the iLvl fallback), (b) both the candidate and currently-equipped item produced positive non-fallback scores, and (c) the raw stat-weighted delta clears the user's minimum percent. Filling a genuinely empty slot still works as before. This closes the path where a missing spec / not-yet-cached scoring caused the equipped item to read as score=0 and any bag item to read as a "+100% upgrade", which on a fragile cursor swap could lose the previously-equipped item.

  • Auto-equip swap is now atomic via EquipCursorItem instead of PickupContainerItem + PickupInventoryItem + ClearCursor. Same pattern EquipmentManager and Pawn use. Eliminates the edge case where the previously-equipped item could fall off the cursor when its origin slot was already occupied. Falls back to the old path on clients without EquipCursorItem.

  • Auto-equip now triggers on PLAYER_ENTERING_WORLD (login / /reload / zone change) too, not just on bag updates and combat-end. If you enable the toggle while items are already in your bags, a /reload is now enough; you no longer have to wait for a bag update or combat-end event before existing upgrades get equipped.

  • /gm equip prints a sweep summary: sweep done, considered N upgrade(s), equipped M. Helps debug "why didn't anything equip".

  • "Cannot auto-equip in combat" message no longer spams the chat for automatic sweeps; it only prints when you ran /gm equip manually while in combat.

  • Loadout window redesigned as a paperdoll. Real WoW slot textures and item icons, two-column gear layout matching the Blizzard character pane, weapon row at the bottom. Per-slot durability bar colored green/yellow/red. Hover any slot for the full item tooltip with durability percent. Header shows class-colored character name, race, class, level, spec. Footer shows iLvl, lowest-slot durability, and (N/total) position. Prev / Next buttons at the bottom corners cycle through every alt on the realm; left/right arrow keys also navigate while focused.

[v1.0.7-release] - 05/09/2026

Changed

  • Stat Import tab help text now explicitly mentions both wowsims.github.io exports and the Pawn addon as sources, with both names highlighted, so users understand the single paste box accepts strings from either.

[v1.0.6-release] - 05/09/2026

Added

  • LICENSE file at the repo root: All Rights Reserved. Embedded third-party libraries (Ace3, LibStub, etc.) keep their own original licenses.
  • Every TOC now declares ## X-License: All Rights Reserved.

[v1.0.5-release] - 05/09/2026

Added

  • New General-tab toggle: "Defer to Pawn for tooltip and bag overlay". When Pawn is loaded and the toggle is on, GearMatic hides its current-spec tooltip line and green bag chevron so they do not duplicate Pawn's display. Yellow alt-aware chevrons, quest reward chevron, loot chevron, cross-character browser, durability nag, auto-equip, and social broadcasts stay live (Pawn does not provide those). Disabled-grey when Pawn is not installed. Default off.

[v1.0.4-release] - 05/09/2026

Added

  • Saved profiles list now shows a blue [Pawn] tag next to scales that were auto-imported from the Pawn addon, so you can tell at a glance which profile came from where.
  • One-time login warning on retail when Pawn is not loaded: GearMatic does not bundle retail stat weights, so on Mainline you need Pawn installed for accurate scoring. Without Pawn (or a manually pasted scale), GearMatic on retail falls back to item-level only.

Notes

  • Retail requires Pawn. Bundled wowsims weights only cover Vanilla through Mists. On retail, install Pawn with your usual scales and GearMatic will auto-import them.

[v1.0.3-release] - 05/09/2026

Added

  • Retail / Mainline support, backed by Pawn. GearMatic_Mainline.toc is back (Interface 110005). Spec auto-detect now uses GetSpecialization() first on retail, then falls through to the classic talent API. GearMatic does not bundle retail wowsims weights, so on retail the recommended path is: install Pawn with your usual scales and let GearMatic auto-import them on login (or paste your own scale via /gm import).

[v1.0.2-release] - 05/09/2026

Added

  • Real Pawn integration. If the Pawn addon is loaded, GearMatic now imports every non-hidden Pawn scale into your saved profiles automatically on login. Toggle in General settings ("Auto-import scales from Pawn"), or run on demand with the new "Sync Pawn scales now" button or /gm pawn slash command.

Changed

  • Replaced the dead ## OptionalDeps: Pawn declaration in every TOC with a real runtime integration. The TOC line was previously a no-op that implied an integration we did not actually deliver.

[v1.0.1-release] - 05/08/2026

Removed

  • Dropped Retail / Mainline support. The addon was never actually compatible with retail (no retail spec API, no retail wowsims weights bundled). Removing the broken GearMatic_Mainline.toc so users on Dragonflight / War Within do not install something that silently fails.

[v1.0.0-release] - 05/08/2026

Initial public release.

Added

  • Cross-character equipped gear tracker with login durability nag.
  • Smart upgrade detection driven by Pawn-format stat weights.
  • Bundled wowsims default scales for Vanilla, TBC, Wrath, Cata, Mists (57 specs).
  • Auto-detect spec from talents.
  • Tooltip overlay on bag, vendor, AH, group loot, and mail items.
  • Quest reward window chevron for the best reward for your spec, with class armor priority (Plate > Mail > Leather > Cloth).
  • Loot window chevron on upgrades.
  • Bag overlay chevron on bag items, compatible with Bagnon and most bag addons.
  • Yellow chevron variant for items the current character cannot wear but at least one alt can.
  • Auto-equip toggle for out-of-combat upgrade swaps. Manual sweep with /gm equip.
  • Cross-character browser at /gm browser showing iLvl, lowest durability, and per-slot scores.
  • Stat profiles tab in settings: paste, save, switch active scale, per-profile keybinds, and a cycle keybind.
  • Social tab broadcasts equip changes to /say (skipped in instances), /party, /raid, /guild, and /battleground.
  • Minimap button (off by default).
  • Sidebar settings layout via Ace3 with General, Stat Import, and Social tabs.