Novel replacement for the GuildBankTabard / TabardConfig
blob that vanilla WoW stores per-guild in guild_member
SQL. Each entry is one tabard design: triplet of
(background pattern + color, border pattern + color,
emblem glyph + color), plus optional guild and creator
attribution and a server-approval flag for tabard-
moderation policies.
Five background patterns (Solid / Gradient / Chevron /
Quartered / Starburst), four border patterns (None /
Thin / Thick / Decorative), and 1024 possible emblem
glyph IDs. Three preset emitters demonstrate the
convention: makeAllianceClassic (4 Alliance-themed
system tabards: Lion, DwarvenHammer, KulTirasAnchor,
HighlordSword), makeHordeClassic (4 Horde: Wolfhead,
CrossedAxes, Skull, Pyramid), makeFactionVendor (6
faction-rep tabards spanning Argent Crusade, Ebon
Blade, Sons of Hodir, Wyrmrest Accord, Kalu'ak,
Frenzyheart Tribe).
Validator's most novel check is a color-similarity
heuristic — squared RGB distance between background and
emblem colors. If under 1500 (empirically derived
threshold for visual readability), warns the operator
that the emblem won't be readable against its
background. Also catches alpha=0 on any color layer
(would render fully transparent), pattern enum out-of-
range, and emblemId>1023 (beyond canonical glyph
range).
Also added per-magic explicit primary-key override to
--catalog-pluck and --catalog-find so they pick the
right field for catalogs where the heuristic fails.
WTBD has creatorPlayerId/emblemId/guildId all
alphabetically before tabardId, and guildId can't be
filtered globally because WGLD uses it as a primary
key. The override table is small (1 entry currently —
WTBD->tabardId) and grows only when a new format
catches the same conflict.
Format count 102 -> 103. CLI flag count 1141 -> 1146.
Novel replacement for the EmotesText.dbc + EmotesTextSound
+ EmotesTextData trio that maps /slash-emote commands
(/dance, /wave, /laugh, etc.) to their visible chat text,
animation ID, and per-race voice clip. Each entry binds
one slashCommand to an animationId (refs WANI), soundId
(refs WSND), targetMessage / noTargetMessage formats,
emote kind (Social / Combat / RolePlay / System), sex
filter (Both / Male / Female), required race bit, and a
TTS hint (Talk / Whisper / Yell / Silent) for accessibility
text-to-speech engines.
Three preset emitters covering the canonical emote
buckets: makeBasic (8 universal social emotes — wave /
bow / laugh / cheer / cry / sleep / kneel / applaud),
makeCombat (5 combat-themed — roar / threaten / charge /
victory / surrender), makeRolePlay (6 RP-focused — bonk
/ ponder / soothe / plead / shoo / scoff). Animation IDs
match AnimationData.dbc convention so existing WoW client
mods continue to play the right anims.
Validator catches authoring bugs unique to slash-command
parsing: leading '/' on slashCommand (chat parser strips
it before lookup so the entry would be doubly-prefixed),
uppercase letters (parser case-folds before lookup so the
entry is unreachable), duplicate slash commands (parser
dispatches by exact match — ambiguity would crash the
chat input handler), %s token counts that don't match
target/no-target distinction.
Also expanded --catalog-pluck's foreign-key filter to
include animationId / soundId / particleId / ribbonId /
vehicleId / seatId / currencyId / trainerId / vendorId /
mailTemplateId — caught during smoke-test where pluck
mis-identified WEMO entries by animationId instead of
emoteId. Same class of bug as the WHRT areaId fix.
Format count 100 -> 101. CLI flag count 1126 -> 1131.
New utility extracts a single entry by id from any
registered catalog format without dumping the whole file.
Useful when a catalog has hundreds of entries and you
only want to inspect one — e.g. "show me WBOS encounter
102" or "what's in WHRT bind 204".
Auto-detects format from the file's 4-byte magic, looks
up the registered --info-* flag in the format table,
spawns that handler as a subprocess with --json, then
filters the entries[] array to just the matching id. The
primary-key field is auto-discovered: prefers the first
*Id field that ISN'T a known foreign-key reference (mapId,
areaId, spellId, npcId, factionId, etc. — 25 known
external-ref names filtered out). Falls back to first
remaining *Id, then first numeric field.
Without the foreign-key filter, alphabetical key
iteration in nlohmann::json picks the wrong field — for
WHRT entries with both areaId and bindId, naive code
would identify by areaId and miss obvious lookups.
Caught during smoke-test and fixed before commit.
Output formats: terminal table (default) or --json.
Accepts file path with or without the .wXXX extension.
CLI flag count 1111 -> 1112.