promotional bannermobile promotional banner

SmexyMats - Revived

ver looked at a stack of something in your bags and wondered whether anyone actually needs it? Is it worth keeping for your tailor, selling to a vendor, or sending to the guild bank? SmexyMats answers that the moment you hover the item.
Back to Files

SmexyMats-v1.15.0

File nameSmexyMats-SmexyMats-v1.15.0.zip
Uploader
PmptastyPmptasty
Uploaded
Oct 5, 2026
Downloads
44
Size
1.2 MB
Flavors
RetailMoP ClassicClassic TBCClassicForever
File ID
9065406
Type
R
Release
Supported game versions
  • 12.1.0
  • 12.0.7
  • 12.0.5
  • 5.5.4
  • 4.4.2
  • 3.4.5
  • 2.5.6
  • 1.60.1
  • 1.15.9

What's new

Changelog

[v1.15.0]

New -- generated data for Wrath, Cataclysm and Retail (Midnight)

A player asked on Discord for Midnight data. ItemDB had no tables for Wrath, Cata or Retail, so those three flavours fell back to the hand-made Data/Materials/Materials.lua, which stops at Shadowlands. ItemDB built them on request (inbox 926a2338, ItemDB v1.2.0): Data/Retail, Data/Wrath and Data/Cata, cores from wago (Retail 12.1.0.69933, Cata 4.4.2.60895, the last Wrath 3.4.x), plus Data/Mists/_core/Expansion.lua.

tools/build-itemdb-data.lua gains Wrath, Cata and Retail in FLAVOURS (each list is that flavour's files in ItemDB's TOC order) and reads Mists' new Expansion. It writes ItemDB's expansion -1 ("not known") as blank, so Materials fills that row's expansion in, as for any other blank. Counts from this first round (the second round below supersedes them): Vanilla 1571, TBC 2557, Wrath 3965, Cata 4424, Mists 5921, Forever 2145, Retail 8014. Retail has no Sources, DropRates or RepLoot, and ItemDB's Retail and Cata ItemLocations carry crafted and reputation rows only, so gathered items there show no gathering profession unless Materials has one. No Wrath, Cata or Retail item has "Where to get it" places yet. Regenerating also picked up ItemDB's client spellings of TBC and Mists instance names and its folding of Mists' six "Way of the ..." cooking styles into Cooking.

SmexyMats_Wrath.toc, SmexyMats_Cata.toc and SmexyMats_Mainline.toc load their new Data\Flavour file; Tests/toc_spec.lua now expects one on every TOC. Anniversary runs the TBC TOC and data, unchanged.

ItemDB's Tooltip.lua changed (Adler-32 a3df731c). Its SOURCE_LABEL and sourceLabels (Tooltip.lua:125-157) were re-read against the generator's copy and pick the same words in the same order; only the return shape differs. COPIED_FROM updated.

New -- gathering, instance drops and map places for Wrath, Cata and Retail

Second ItemDB round (inbox e9aefe20, operator: "we should fill these gaps"). The generator's FLAVOURS now read Wrath's DropRates and ItemPlaces, Cata's ItemPlaces, and Retail's Sources and SourceNames, each in ItemDB's TOC order. ItemDB's Cata and Retail ItemLocations now carry gathered rows (from the SkyFire 5.4.8 world DB) and Retail's Sources come from the client's Encounter Journal. Counts from this build: Wrath 3965 items (731 with places), Cata 4896 (978 with places), Retail 8506 (0 with places). Gaps ItemDB named and could not fill: gathering for items added after Mists, so Warlords onward and Midnight ores and herbs fall back to Materials; and Retail places, because SkyFire's map coordinates predate Retail's rebuilt zones. Cata's revamped Deadmines, Shadowfang Keep, Zul'Gurub and Zul'Aman can list a boss twice and ZG/ZA keep a raid label (ItemDB's note, not checked in game). Generated files: Wrath 601 KB, Cata 702 KB, Retail 680 KB, all under Mists' 809 KB.

New -- Retail sources and places from TrinityCore

Third ItemDB round (same thread, ItemDB reply 9b7df0f1). ItemDB rebuilt Retail's ItemLocations from TrinityCore TDB 1210.26091 (client 12.1.0), with SkyFire as a gathering-only supplement, and added Data/Retail/_core/ItemPlaces.lua from TrinityCore spawns. The generator's Retail entry now reads ItemPlaces. Count from this build: Retail 11552 items, 1250 with places (was 8506 / 0). Data/Flavour/Retail.lua is 1.35 MB. Still open and holding the release: gathering for Dragonflight-onward materials, which TrinityCore barely covers (ItemDB: Dragonflight 16/603, The War Within 24/481, Midnight 16/312 reagents with a gathered row); ItemDB is extracting it from AllTheThings' Retail data.

New -- modern gathering and drop sources, prospecting and milling

Fourth ItemDB round (ItemDB replies 8b382a0a, a5045a52). Retail's ItemLocations now carries gathered rows from AllTheThings' Retail data for items no world DB covered (642 items: Dragonflight 119, The War Within 84, Midnight 117, older 324) and world, zone and instance drop rows from ATT (49,011 items in the file). Every version with a world DB also gained "Jewelcrafting" rows for prospecting results and "Inscription" rows for milling, which WORD_PROF already maps (indices 10 and 9; Tests/data_spec.lua 'draws every data word' green). No generator change; regenerated: TBC 2563, Wrath 3972, Cata 4897, Mists 5923, Retail 11555 items. Still without any source per ItemDB (Dragonflight / The War Within / Midnight): gems 8/5/8, cloth 3/9/2, cooking 0/4/9, pigments 1/0/2, plus 134 others.

Fifth ItemDB round (request d95142e3, ItemDB reply fa206aaf): Retail ItemLocations now 87,178 items, adding disenchanting ("Enchanting"), crushing ("Jewelcrafting") and scrapping ("Engineering") gathered rows, crafted rows from SpellEffect 294/296 and ATT's crafted lists, vendor stock, quest and treasure rewards, and patron rewards ("Crafting Orders", source quest). Dragonflight-onward reagents with no source went 152 to 12, and ItemDB names each: never implemented (219500), removed in 10.2.0 (204193, 204194), raid quest objectives with no world source (209352, 210001, 210009), no source in ATT and no client spell creates them (201832, 228338, 228339, 274476, 205257 'may drop from open world content'), and 210814 (ATT constant not resolved). A follow-up (ItemDB reply b1b9429c) resolved 210814 Artisan's Acuity as a Darkmoon Faire quest reward, leaving 11, and stopped three items reading as dropping from a mount; regenerating it left Retail at 14423 items and the suite at 183/183. A second follow-up (ItemDB reply 0835ad19) added the client's CollectableSource* vendor, quest and boss rows (Retail ItemLocations 96,447 items) and continent names as vendor or quest places; regenerating left Retail at 14423 items, 1265 with places, and the suite at 183/183. Every new word maps (Tests/data_spec.lua 'draws every data word', green). Regenerated: Retail 14423 items, 1265 with places. The README and CurseForge 'materials with no source yet' lines are removed.

Changed -- "Where to get it" reads quest givers

ItemDB's final data for its v1.2.0 (ItemDB reply 75e15b31 on d95142e3: Retail ItemLocations 120,895 items, new place words such as Trading Post, Delves and World Boss) was regenerated in: Retail 14423 items, 1265 with places, unchanged. The rebuild warned that ItemDB's Where.lua no longer matched the copy SmexyMats was checked against (d763d3b5, ItemDB's uncommitted working tree). Its diff adds quest-giver places: a q<creature>:<questID> token (ItemDB LibItemDB-1.0.lua:1238) whose second field is the quest, not a drop chance. Ported to Where.lua: GetItemPlaces decodes q into a quest row with questID and no chance; BuildWhereRows shows it as a Quest row on its map, hides the other side's quest givers like vendors, and drops the bare quest-zone row from the sources when a quest giver already covers it. Before the port a q token was silently skipped. No item SmexyMats carries has a q token yet: ItemDB's Retail ItemPlaces.lua has 7,453 and the regenerated Data/Flavour has none (both by grep, the second checked against a vendor-token search that does match), so players see no change from this until a material gains a quest giver; the release notes do not mention it. COPIED_FROM moved to d763d3b5. Specs: Tests/where_spec.lua (decode, rows, faction filter); 186/186, coverage 1523/1523.

The q kind reached SmexyMats unannounced: the generator stamped ItemDB's Tooltip.lua and Where.lua but not LibItemDB-1.0.lua, whose place decoder Where.lua also ports, and it was caught only because ItemDB's Where.lua changed in the same edit. Two guards now (ItemDB thread 077ea78c, after Peer Review's reading on 8acd9f23). Where.lua publishes its letter table as SmexyMats.PLACE_KIND, and Tests/where_spec.lua loads the installed LibItemDB and requires it to equal LibItemDB's published PLACE_KIND (MINOR 40), so a new letter turns the suite red. SmexyMats keeps its own table rather than reading ItemDB's at runtime, because it runs without ItemDB and its data's letters are fixed when the generator runs. And the generator's new COPIED_SPANS stamps just that span of LibItemDB-1.0.lua (unpackPlace to the end of GetItemPlaces, 550e458e) and warns when it changes or cannot be found; both warnings were seen while setting it up (CRLF line ends hid the span at first). 187/187, coverage 1524/1524.

After that "final" note ItemDB rebuilt Retail's core from an item walk on the Retail client (thread 06a6a496: 176,130 items with stats, ItemLocations 121,347, ItemPlaces 43,560; no new place word, kind or file shape). Regenerated: Retail 14429 items, 1269 with places (was 14423 / 1265); 187/187, coverage 1524/1524, luacheck clean.

ItemDB also corrected an earlier note: since its final Retail build a quest objective that nothing else places gets one quest row, its quest's zone (4,064 items); the regenerate above includes them.

tools/build-itemdb-data.lua copied an entity row for every letter-and-digits run in a place string, so a profession condition such as s197 also pulled in creature 197's row. It now reads only each token's leading kind and id.

Changed -- release docs for v1.15.0

README.md and docs/Curseforge_Description.html still said "Where to get it" ran only on Classic Era, Burning Crusade, Mists and WoW Forever, and credited ItemDB's data for those four alone; both now say every version. Retail is described as lightly tried in game (one tooltip seen by the operator) rather than not tried. The v1.15.0 Recent Updates gain a line for the Dragonflight-onward sources.

.pkgmeta loses its comment block (operator, 2026-10-03: no comments in .pkgmeta, they can break CurseForge packaging); the rules it carried moved to CLAUDE.md. The dev-sync dry run still reads all six ignore entries and would copy no docs, Tests, tools or dotfile.

Fixed -- the test suite leaked every addon load and timed out on a busy machine

The full suite failed on 2026-10-04 with (error object is not a string) and no summary while the machine sat at 100% CPU. Rerun with --times --timeout 900 it passed, with core_spec.lua at 28 s of the runner's 60 s per-file limit. The run telemetry showed why: the heap grew ~300 KB per example (3 MB to 50 MB across core_spec.lua), live frames reached 4,669, and one example's full collection took 2.8 s. Tests/env_smexy.lua's load() refreshed only AceAddon, AceLocale and AceConfigDialog; with AceEvent, AceConsole, AceConfigRegistry and AceGUI kept loaded across examples, every earlier SmexyMats object stayed reachable. Which of those four held the references was not traced; the fix below is measured, the path is inferred.

Tests/wowapi pinned from 1665785 to 407bd26, WoWAPITesting's answer to harness thread 6d4a4b6c: anything escaping a spec file is now a named FAIL <file> (escaped the runner) with a traceback, and the summary still prints. Every Adoption-log entry between the two pins is "pin; nothing else" or names nothing SmexyMats uses. 183/183, coverage 1519/1519 on the new pin. load() now resets the Ace3 loader and the library loader (ace.reset(), libs.reset()) and loads all seven Ace3 modules fresh; LibAceGUIWidgets then reloads against the current AceGUI when where_spec.lua asks for it. After: heap flat near 3 MB, 214 frames, core_spec.lua 8 s, the whole suite about 14 s, 181/181 under the default limit. The runner's unnamed exit on a timeout is reported to WoWAPITesting (harness thread 6d4a4b6c).

Fixed -- Retail expansions past Shadowlands would have errored

SmexyMats.ExPacks (Utilities/Utilities.lua) stopped at 8, Shadowlands, and the tooltip indexed ExPacks[EP] unguarded (SmexyCore.lua), so any Retail row naming Dragonflight, The War Within or Midnight would have thrown on every such tooltip. Added 9-11 with names (new enUS locale keys) and colours. There are no logos for them in Icons/, so their icon is nil, geticon() returns an empty string, and the tooltip writes the name even when expansion logos are on. An expansion number with no ExPacks entry now draws no expansion line instead of erroring. The three colours are my picks, not taken from any Blizzard source. Specs: Tests/utilities_spec.lua (9-11 shape), Tests/core_spec.lua (name drawn with logos on; unknown number draws no line), Tests/data_spec.lua (all seven flavours; each row's expansion is within its flavour and has an ExPacks entry).

[v1.14.1]

Fixed -- item tooltips errored on WoW Forever

Reported from WoW Forever: hovering an item in TOGProfessionMaster's crafting tab raised SmexyCore.lua:364: attempt to call a nil value from inside tt:GetItem(), 56 times in one session. On Forever GetItem is not the client's own method but GameTooltipDataMixin:GetItem, a shim over TooltipUtil.GetDisplayedItem (Blizzard_GameTooltip/Mainline/GameTooltip.lua:1031, Blizzard_SharedXMLGame/Tooltip/TooltipUtil.lua:9), and on that tooltip something it calls is nil. Which one was not confirmed in game. I called it unguarded.

The item post-call now reads the item from the tooltip data it is handed (data.hyperlink, else item:<data.id>) and passes it to ModifyItemTooltip, which uses it before asking the tooltip. GetItem itself is now called through pcall and a missing or throwing one counts as "no link", so the stored-link and title fallbacks still run. Tests/core_spec.lua covers all three paths.

Changed -- release docs for v1.14.1

README.md and docs/Curseforge_Description.html checked against the code. Two corrections: the "Where to get it" key binding is under Key Bindings > AddOns > SmexyMats (Bindings.xml declares category="ADDONS"), not Key Bindings > SmexyMats, and it is unbound by default; and on Retail and WoW Forever the lines also show on item tooltips other addons open, since the item post-call covers every item tooltip. The CurseForge page's VersionCheck-1.0 line now says what the README says (a guildmate has a newer SmexyMats). v1.14.1 Recent Updates added, grouped Fixed / Changed.

[v1.14.0]

The first release of the restored SmexyMats. It follows LunixiaLIVE's v1.13.2.

Changed -- release docs for v1.14.0

README.md rewritten player-first: the tooltip lines, the heading and [SM] prefix, where the lines show, the "Where to get it" window (columns, chance notes, faction button, the i help, remembered position, Questbook), slash commands, every option with its default (checked against Data/Options/Defaults.lua), per-version coverage, requirements, Discord for reports, and credits. docs/Curseforge_Description.html gains the same detail and fuller v1.14.0 notes. The comparison-tooltip claim is limited to Retail and WoW Forever, where the item post-call covers every tooltip; the Classic flavours hook GameTooltip and ItemRefTooltip only.

Fixed -- everyday vendor goods read PvP on TBC and Mists

Rebuilt Data/Flavour after ItemDB fixed its TBC and Mists location data (thread 60e304d7): ItemDB's source builder filed any item a battleground quartermaster stocks under that battleground only, so Refreshing Spring Water (159) read Source "PvP" on TBC. It now reads Quest, Vendor, and about 60 TBC and 70 Mists items are corrected the same way. Vanilla was unaffected. The rebuild's drift check flagged ItemDB's Tooltip.lua; its only change was a new _GetTooltipDefault helper, so COPIED_FROM moved to its new checksum with sourceLabels unchanged.

Changed -- the revived CurseForge project

SmexyMats now publishes to its own CurseForge project, smexymats-revived (project ID 1718084), taken over with LunixiaLIVE's permission. Every TOC's X-Curse-Project-ID moved from 270824 (LunixiaLIVE's original project) to 1718084, pinned by Tests/toc_spec.lua. The "Missing Data-Tables" load message, its locale key and all six translations now point at https://www.curseforge.com/wow/addons/smexymats-revived instead of the old project's mods.curse.com address. The CurseForge description is rewritten to the family's section layout and credits LunixiaLIVE as the original developer; the README gains a Credits section saying the same.

Fixed -- WoW Forever tooltips had no heading and no Source line

Found in game on WoW Forever (ItemDB disabled): Rough Stone showed Profession(s) and ItemID only. Two causes. Header defaulted to false; it is now true, matching ItemDB's header default (a profile saved while it was off keeps its saved value). And the per-flavour row can leave the sources or the expansion blank -- ItemDB's Forever row for 2835 is "||Blacksmithing,Engineering, Mining", and no Mists or Forever row carries an expansion -- so SearchDatabase now fills a blank source list or expansion from the Materials tables (the old lookup, now searchMaterials), keeping the flavour data's used-by list. Rough Stone on Forever now reads Drop, Mining and Classic.

Changed -- the copies of ItemDB's code and word list are pinned (audit 67e323f8 item 4)

Tests/data_spec.lua now reads every word the four generated flavours carry and asserts each draws as the Utilities.lua Profs entry of the same name (so SmexyCore.lua's WORD_PROF indices cannot drift from Profs), as one of ItemDB's three own icons (Quest, PvP, Reputation), or as text for the words ItemDB also leaves iconless because no icon was verified: "Crafted", "Poisons" and Mists' six cooking Ways. A new word fails by name. tools/build-itemdb-data.lua stamps the Adler-32 of ItemDB's Tooltip.lua and Where.lua (the files SmexyMats copies code from) into every Data/Flavour header and warns when either differs from COPIED_FROM, so a change in ItemDB surfaces at the next rebuild.

The Reset button's description still promised to "reset your alt database", a feature that never existed; it now says it restores every setting and reloads the UI. The deprecated-global sweep (audit item 1) found only GetItemInfo and GetItemIcon among SmexyMats' calls defined solely in the live tree's Blizzard_Deprecated* files (12.1.0), and both already go through C_Item first.

Fixed -- one Alt+Click opened two Where windows with ItemDB installed

ItemDB and SmexyMats each hooksecurefunc HandleModifiedItemClick, and both default the Where click to ALT-LeftButton, so with both installed one click opened both windows (audit 67e323f8 item 6). New SmexyMats:ItemDBOwnsWhereClick asks the loaded LibItemDB-1.0 whether its click is on (GetTooltipOption("altClick")) and bound, canonically, to the same click as SmexyMats' (GetTooltipOption("whereClick") through ParseClickBinding). When it is, WhereOnModifiedClick yields and the heading drops its click hint (ItemDB's heading already carries one), since ItemDB's window covers every item and SmexyMats' only materials and crafted items. Give the two addons different clicks and each opens its own. An ItemDB with no whereClick setting (older than LibItemDB MINOR 38) is never yielded to. /sm where and the key binding are unaffected.

Fixed -- Retail read item info through a deprecation fallback

GetItemProperties and the Where window called the bare GetItemInfo. On Retail that global is only a deprecation fallback (Blizzard_DeprecatedItemScript/Deprecated_ItemScript.lua: GetItemInfo = C_Item.GetItemInfo), loaded only with the loadDeprecationFallbacks CVar -- without it every item tooltip would have raised. New SmexyMats:ItemInfo resolves C_Item.GetItemInfo first, per call. Found by the session's self-audit.

Changed -- Retail and WoW Forever annotate every item tooltip

Only the live and forever trees' TooltipInfoDocumentation.lua define C_TooltipInfo.GetBagItem, ItemDB's test for its data-driven route -- the same two flavours HasScript("OnTooltipSetItem") already sends to the item post-call, so the route choice already matched. The post-call now annotates every item tooltip it is handed (the comparison tooltips beside GameTooltip included), as ItemDB's does, instead of GameTooltip and ItemRefTooltip only; OnTooltipCleared is hooked once per frame as each is first met, and a tooltip with no name reads no title instead of raising. The Classic flavours still hook GameTooltip and ItemRefTooltip only -- so does ItemDB.

Changed -- icon sizes are sliders; a malformed saved colour draws white

The << / >> buttons and the number line under them became two AceConfig range sliders: profession icons 8-64 (ItemDB's range) and the expansion logo 16-128 (SmexyMats' own, default 50), whole numbers, clamped, showing the default when the saved size is missing. The colour-blind colours now go through SmexyMats:ColorCode, which accepts exactly six hex digits (as ItemDB's setter does) and otherwise draws white -- a malformed escape would have swallowed the text after it.

Added -- the "Where to get it" window, ported from ItemDB

Where.lua (loaded right after SmexyCore.lua in every TOC) is ItemDB's Where.lua on the SmexyMats object: GetItemPlaces (the same packed format, unpacked the same way), GetWhereSources, BuildWhereRows (bosses, then drops, vendors, gathering nodes and chests with zone, chance and spawns, then quest / crafted / reputation / PvP), the faction filter, Questbook tracking with the stop icon, and the click binding (ParseClickBinding, ClickBindingText, IsWhereClick, one hooksecurefunc("HandleModifiedItemClick")). It opens on an item from the chosen click (default Alt+Left, a modifier always required), the unbound key binding in Bindings.xml, or /sm where [item]. The data rides in each Data/Flavour/<Flavour>.lua as a LoadWhereData call, written by tools/build-itemdb-data.lua from ItemDB's ItemPlaces.lua (Vanilla 395 items with places, TBC 825, Mists 1059; Forever ships sources but no places). On Wrath, Cata and Retail there is no Where data and nothing is hooked.

SCOPE, stated because the first write-up called this parity without it: the generator writes Where data only for the items the tooltip covers (reagents and profession-produced items), not for every item ItemDB has places for, so a boss-drop sword reads "No known source (materials and crafted items only)" in SmexyMats where ItemDB lists the drop (audit 67e323f8 #3). Extending it to every item would grow the data files several times over; the scope is said in the window and on the CurseForge page instead.

Two ItemDB features are deliberately not carried: the search strip, which searches ItemDB's item-name database that SmexyMats does not ship; and localised creature / vendor names (ItemDB's PlaceNames files) -- the names are English, while zone names still come from the client. New options: WhereClickEnabled, WhereClick (a select of every modifier combination with the left or right button, validated), WhereOwnFactionOnly; the heading gains the grey "(Alt+Click: where to get it)" hint while the click works on that flavour. LibAceGUIWidgets is an optional dependency in every TOC and a required one in .pkgmeta; without it the window says so in chat.

The generator's first build wrote the separator byte as \31, which Lua reads together with a following digit (\311) as one escape; escapes are now always three digits.

Added -- optional "SmexyMats" heading

New profile setting Header (default off, so the tooltip looks as it did) and its toggle in the options. When on, ProcessTooltip draws a blank line and "SmexyMats" (the wowtoken colour, or colour #1 in colour-blind mode) once, just above the first line it adds, and nothing when every line is switched off -- ItemDB's heading, minus its click hint, which waits for the Where window.

Added -- per-flavour tooltip data, generated from ItemDB

Data/Materials/Materials.lua is one Wowhead-derived table covering every expansion, so a Classic client read later-expansion answers (Deeprock Salt: Mining). ItemDB carries the same tooltip with per-flavour data built from each client's own DB2 tables. tools/build-itemdb-data.lua loads the installed ItemDB's LibItemDB-1.0 and one flavour's data offline, asks it what ItemDB's tooltip asks (GetReagentUses, the expansion tables, GetSources turned into words by a copy of ItemDB's sourceLabels), and writes Data/Flavour/<Flavour>.lua: one [id]="<exp>|<sources>|<used by>" row per item that is a reagent or that a profession produces. Vanilla 1571 items, TBC 2557, Mists 5918, Forever 2145. SmexyMats.toc, _TBC, _Mists and _Camelot load their file after SmexyLoadDB.xml; where one is loaded it is the whole answer, and Materials is not consulted. Wrath, Cata and Retail, for which ItemDB ships no data, keep Materials.

SmexyMats stays standalone: the data is copied into this repo at build time, and nothing reads ItemDB in the game. New source words Quest, PvP, Reputation and Crafted are in Locales/enUS.lua (other locales fall back to English); Quest/PvP/Reputation draw ItemDB's icons (file ids 134327, 132486, 134156), and a word with no icon or locale entry (Mists' "Way of the Wok") prints as it is, read with rawget so AceLocale does not report it missing. Source order is ItemDB's -- producing professions first -- so the sort moved out of FormatToolTipString into the Materials path of SearchDatabase. Tests/toc_spec.lua now allows exactly one Data\Flavour line per TOC, right after SmexyLoadDB.xml, and data_spec.lua checks every generated row's shape.

Added -- release and development tooling

SmexyMats had no packaging, docs or tests of any kind -- one TOC for Interface 20501 and the Lua source. This entry brings it up to the fleet's standard layout, with ItemDB as the reference.

  • Per-flavour TOCs. SmexyMats.toc (Classic Era, 11509), SmexyMats_TBC.toc (20506), SmexyMats_Wrath.toc (30405), SmexyMats_Cata.toc (40402), SmexyMats_Mists.toc (50504), SmexyMats_Camelot.toc (WoW Forever, 16001) and SmexyMats_Mainline.toc (Retail, 120005, 120007, 120100, the list VersionCheck-1.0's TOC declares). The Interface numbers come from the client versions in F:\Blizzard API Docs' per-flavour trees (1.15.9, 2.5.6, 5.5.4, 1.60.1, 12.1.0); Wrath and Cata have no live client and use the numbers ItemDB ships. Every TOC loads the same files as the old one did. ## Version: is now SmexyMats-v1.15.0 for the packager, and the author line credits the original author.
  • .pkgmeta (package as SmexyMats, manual changelog, Ace3 and VersionCheck as required dependencies; docs, Tests, *.ps1, *.code-workspace and CLAUDE.md ignored) and .github/workflows/release.yml (BigWigs packager on a pushed tag).
  • LICENSE (MIT), README.md, CLAUDE.md and docs/Curseforge_Description.html.
  • wow-version-replication.ps1 and .vscode/tasks.json: the dev watcher that copies the shippable files to the other installed flavours, _retail_ included. It differs from the fleet's copy in one respect: it waits on file-system change events (FileSystemWatcher + Register-ObjectEvent without -Action + Wait-Event) instead of polling the tree every two seconds, because writ refuses new timers. The fleet's copy polled because an -Action block runs in another runspace where the script's functions are not in scope; without -Action the events queue in the script's own session, so that reason does not apply. A watcher buffer overflow raises Error, which triggers a full resync.
  • Test harness. WoWAPITesting as a submodule at Tests/wowapi, the .busted shim, .luacheckrc, .luarc.json, .writ-suites.json, .markdownlint.json, and first specs: Tests/toc_spec.lua (every TOC's Interface number, file list and lockstep directives) and Tests/manifest_spec.lua (every shipped .lua is loaded by some manifest).

Fixed -- a clicked item link got no lines while GameTooltip was annotated

ModifyItemTooltip kept one "already annotated" flag for GameTooltip and ItemRefTooltip together, cleared by either tooltip's OnTooltipCleared. With GameTooltip showing an annotated item, a chat link opened in ItemRefTooltip was skipped. The flag is now per tooltip (a weak-keyed table), as ItemDB's tooltip does it. Found while comparing the two for feature parity.

Fixed -- no item annotations on Retail and WoW Forever

HookTooltips hooked OnTooltipSetItem on both tooltips unconditionally. In the Blizzard source that script is hooked only in the three Classic trees (Blizzard_PTRFeedback_Tooltips.lua in classic_era, classic and classic_anniversary); the live and forever trees name it nowhere but the UI schema and register TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, ...) instead. HookTooltips now asks each tooltip HasScript("OnTooltipSetItem"), hooks the script where it exists, and otherwise registers one item post-call that annotates GameTooltip and ItemRefTooltip only. Not verified in a Retail or Forever client yet; the offline specs drive both branches with a tooltip that refuses the script as the client would.

Removed -- SmexyEmbeds.xml

Every TOC loaded SmexyEmbeds.xml, which included ..\Ace3\*.xml from the Ace3 addon's own folder. Ace3 is a hard dependency in every TOC, so the client has loaded it before SmexyMats either way: if the client follows ..\ the file re-ran version-guarded libraries for nothing, and if it does not it was a load error. Which of the two the client does was not verified. The file is gone from all seven TOCs and the repo, and Tests/toc_spec.lua now fails any TOC or loaded XML that references a path outside the addon folder.

Changed -- test harness pinned to 1665785

WoWAPITesting fixed coverage.lua to compile targets the way the client does (a leading UTF-8 BOM skipped) and to print the compiler's error when a target will not load -- the request filed when Materials.lua's BOM stopped the coverage run. Pinned and re-run: 110 specs, 1076/1076 lines.

Fixed -- every flavour called itself "Classic"

The options panel registered as SmexyMats(Classic) and the load message printed Classic as the version, on Retail too. The panel is now SmexyMats, and the message prints the TOC's ## Version: (read through C_AddOns.GetAddOnMetadata or the bare global, whichever the client has -- the same helper now feeds the VersionCheck registration).

Fixed -- ItemRefTooltip read GameTooltip's title

The title fallback in ModifyItemTooltip and the uncached-item message in ProcessTooltip read GameTooltipTextLeft1 whichever tooltip they were processing, so a clicked item link was looked up by whatever GameTooltip last showed. Both now read <tooltip name>TextLeft1 of the tooltip in hand.

Added -- logic specs, 100% line coverage

Tests/env_smexy.lua loads SmexyMats the way its TOC does, against the installed Ace3 on the harness's widget layer (AceConfigDialog builds real frames when the options panel registers), with recording stand-ins for GameTooltip and ItemRefTooltip. Four spec files cover the logic: core_spec.lua (profile building, the hooks, /sm, the VersionCheck registration against the installed library, link parsing, the lookup, every tooltip line and toggle, the uncached-item message, the Classic profession-window path), utilities_spec.lua, options_spec.lua (every toggle, both colour pickers, the size steppers, Reset, the header list) and data_spec.lua (every Sources/Reagents cell the lookup indexes exists and holds item ids). 103 specs; Tests/wowapi/coverage.lua reports 1065/1065 lines across SmexyCore.lua, Utilities.lua, Options.lua, Defaults.lua, Materials.lua and Locales/enUS.lua. .writ-suites.json declares the coverage run and a whole-repo luacheck run, both at zero.

Fixed -- /sm raised an error on every flavour

ChatCommand called InterfaceOptionsFrame_OpenToCategory, which is defined nowhere in the Classic Era 1.15.9 or Retail FrameXML. It now calls Settings.OpenToCategory with the category ID that AceConfigDialog:AddToBlizOptions returns (its second return in the installed Ace3).

Fixed -- the profile WAS the defaults table, so Reset reset nothing

OnInitialize and the Reset button both assigned SmexyMats.defaults.profile itself to SmexyMatsDB.profile, so every setting a player changed was written into the defaults, and Reset handed the changed table back. New SmexyMats:FillProfile copies (deeply) every default the saved profile lacks, so a profile saved by an older version also gains settings added since; Reset builds a fresh copy.

Fixed -- smaller defects found while writing the specs

  • FormatToolTipString(nil) passed SearchDatabase's empty answer to table.sort and raised; it now answers empty strings. Found by the language server's type check.
  • Defaults.lua set ColorBlindPickedOne twice and ColorBlindPickedTwo never.
  • Options.lua used the key Section4 for both the "Commands" and the "Author" header, so the Commands header was silently replaced. The second is now Section6.
  • GetIDFromLink and the profession-window reads required a : after the item id, so a bare item:2589 string parsed as 0. The pattern is now item:(%d+).
  • InstallHook replaced GameTooltip.SetRecipeResultItem / SetRecipeReagentItem by assignment, which taints GameTooltip, and wrapped them even where the client has no such method (Classic), creating one that raises if called. It is gone. HookRecipeTooltips uses hooksecurefunc, only on methods the client has, and only when the data tables loaded. Because a secure hook runs after the client's method -- after the tooltip already asked for its item and found none -- the hook records the recipe's link and annotates the tooltip itself; ModifyItemTooltip now marks a tooltip done only once it found an item, so that second attempt is let through and a later OnTooltipSetItem cannot add the lines twice.
  • Data/Materials/Materials.lua began with a UTF-8 byte order mark, which plain loadfile rejects (the client and the harness loader both strip it). Removed, with trailing whitespace; line count and every number verified unchanged. The coverage tool's loadfile was reported to WoWAPITesting.

Changed -- Options.lua and Utilities.lua built from small constructors

The eleven identical toggle definitions, the two colour pickers, the four size steppers and their labels in Options.lua, and the 28 icon closures in Utilities.lua, are now produced by local builder functions. Output is unchanged, which the specs pin; the colour pickers' unused alpha hex and the dead "100" check went with it, as did Options.lua's unused locale handle.

Added -- guild version check (VersionCheck-1.0)

VersionCheck-1.0 is a hard dependency in all seven TOCs and in .pkgmeta's required-dependencies. SmexyMats:OnEnable (AceAddon fires it at login, after every dependency has loaded) registers the addon object with VC:RegisterCheck(self, <raw TOC Version>), falling back to VC:Enable(self) on a VersionCheck that predates RegisterCheck. The version is passed raw so an unsubstituted SmexyMats-v1.15.0 still marks a dev build. VersionCheck's own TOC declares every flavour SmexyMats ships for, Retail included, so the hard dependency does not stop SmexyMats loading anywhere. Tests/toc_spec.lua now asserts the dependency on every TOC.

Removed -- the "Report errors to chat" option and the code behind it

ProcessTooltip opened with a "cannot fetch item" chat block (with a LID de-duplication this session first "fixed") and a Classic TradeSkillFrame / GetMouseFocus lookup. Neither could run: the only caller, ModifyItemTooltip, calls ProcessTooltip only after ExamineObject has accepted an item with a real id, so the option never printed anything in game. The specs that drove the branch called ProcessTooltip directly, which is why 100% line coverage did not show it. Found in the session self-audit (inbox 67e323f8), confirmed by Peer Review. Removed the branch, the option and its ErrorReporting default, as ItemDB dropped chat error reporting; reversible if wanted.

Changed -- SmexyCore.lua made lint-clean

luacheck reported 138 warnings. Besides the fix above: the SetCurrencyToken hook was removed, because its post-hook named Hook_SetCurrencyToken, which is defined nowhere, so the hook wrapped the method and did nothing; JustTheTip and ExamineObject became file-local functions instead of globals; the doubled ExamineObject(obj) and ExamineObject(obj) tests became single calls; and unused locals, loop variables and trailing whitespace were dropped. C_AddOns and GetAddOnMetadata were added to .luacheckrc and .luarc.json.

Fixed -- the locale files were pulled in with the XML-file element

SmexyLocales.xml loaded all seven Locales/*.lua files with <Include file=...>, which is the element for an XML file; a Lua file is loaded with <Script file=...>. manifest_spec.lua caught it on its first run (all seven reported as loaded by no manifest). Whether the client tolerated the old form in game was not verified. The commented-out block of locales that do not exist (itIT, ptBR, zhCN, zhTW) was removed with it.

This mod has no additional files