SmexyMats-v1.15.0
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) andSmexyMats_Mainline.toc(Retail,120005, 120007, 120100, the list VersionCheck-1.0's TOC declares). The Interface numbers come from the client versions inF:\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 nowSmexyMats-v1.15.0for 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-workspaceandCLAUDE.mdignored) and.github/workflows/release.yml(BigWigs packager on a pushed tag).LICENSE(MIT),README.md,CLAUDE.mdanddocs/Curseforge_Description.html.wow-version-replication.ps1and.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-ObjectEventwithout-Action+Wait-Event) instead of polling the tree every two seconds, because writ refuses new timers. The fleet's copy polled because an-Actionblock runs in another runspace where the script's functions are not in scope; without-Actionthe events queue in the script's own session, so that reason does not apply. A watcher buffer overflow raisesError, which triggers a full resync.- Test harness. WoWAPITesting as a submodule at
Tests/wowapi, the.bustedshim,.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) andTests/manifest_spec.lua(every shipped.luais 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)passedSearchDatabase's empty answer totable.sortand raised; it now answers empty strings. Found by the language server's type check.Defaults.luasetColorBlindPickedOnetwice andColorBlindPickedTwonever.Options.luaused the keySection4for both the "Commands" and the "Author" header, so the Commands header was silently replaced. The second is nowSection6.GetIDFromLinkand the profession-window reads required a:after the item id, so a bareitem:2589string parsed as 0. The pattern is nowitem:(%d+).InstallHookreplacedGameTooltip.SetRecipeResultItem/SetRecipeReagentItemby 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.HookRecipeTooltipsuseshooksecurefunc, 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;ModifyItemTooltipnow marks a tooltip done only once it found an item, so that second attempt is let through and a laterOnTooltipSetItemcannot add the lines twice.Data/Materials/Materials.luabegan with a UTF-8 byte order mark, which plainloadfilerejects (the client and the harness loader both strip it). Removed, with trailing whitespace; line count and every number verified unchanged. The coverage tool'sloadfilewas 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

