Kelsidavis-WoWee/tools/editor/cli_list_formats.cpp
Kelsi c9b822002f feat(editor): add WEMO (Emote Definition) — 101st open format
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.
2026-05-10 00:53:33 -07:00

186 lines
13 KiB
C++

#include "cli_list_formats.hpp"
#include "cli_arg_parse.hpp"
#include <nlohmann/json.hpp>
#include <cstdio>
#include <cstring>
#include <string>
namespace wowee {
namespace editor {
namespace cli {
namespace {
// Static catalog of every novel open format the editor can
// currently emit, parse, and round-trip. Adding a new format
// requires appending one row here so --list-formats stays
// authoritative. The list is intentionally kept in
// introduction order so users can correlate against the
// commit history.
struct FormatRow {
const char* magic; // 4-char binary magic
const char* extension; // file suffix (with dot)
const char* category; // grouping label
const char* replaces; // proprietary source(s)
const char* description;
};
constexpr FormatRow kFormats[] = {
// World / asset / pipeline foundations.
{"WOM ", ".wom", "asset", "M2", "M2 model — bones / vertices / animations"},
{"WOB ", ".wob", "asset", "WMO", "WMO building — groups / portals / collision"},
{"WHM ", ".whm", "world", "ADT heightmap", "ADT terrain heightmap tile"},
{"WOT ", ".wot", "world", "ADT textures", "ADT terrain texture splats + alpha layers"},
{"WOW ", ".wow", "world", "WDT/WDL", "Per-zone world manifest + weather"},
// Catalog / DBC replacements.
{"WITM", ".wit", "items", "Item.dbc + item_template", "Item catalog (gear, consumables, quest items)"},
{"WCRT", ".wcrt", "creatures", "creature_template", "Creature catalog (NPCs, mobs, vendors)"},
{"WSPN", ".wspn", "wspn", "creature SQL", "Creature/object spawns by zone+coord"},
{"WLOT", ".wlot", "loot", "creature_loot_template", "Loot tables and drop chances"},
{"WGOT", ".wgot", "objects", "gameobject_template", "GameObject catalog (chests / doors)"},
{"WSND", ".wsnd", "audio", "SoundEntries.dbc", "Sound entry catalog"},
{"WSPL", ".wspl", "spells", "Spell.dbc + spell_template", "Spell catalog (effects, durations, costs)"},
{"WQTM", ".wqt", "quests", "quest_template + Quest*.dbc", "Quest catalog (objectives, rewards)"},
{"WMSX", ".wms", "maps", "Map.dbc + AreaTable.dbc", "Map and area catalog"},
{"WCHC", ".wchc", "chars", "ChrClasses.dbc + ChrRaces.dbc", "Class + race catalog"},
{"WACH", ".wach", "achieve", "Achievement.dbc + Criteria.dbc", "Achievement catalog with criteria"},
{"WTRN", ".wtrr", "trainers", "npc_trainer + Spell.dbc", "Trainer catalog (spell teaching)"},
{"WGSP", ".wgoss", "gossip", "gossip_menu + npc_gossip", "Gossip menu / dialog tree catalog"},
{"WTAX", ".wtax", "taxi", "TaxiNodes.dbc + TaxiPath.dbc", "Flight path catalog (taxi network)"},
{"WTAL", ".wtal", "talents", "Talent.dbc + TalentTab.dbc", "Talent tree catalog"},
{"WTKN", ".wtkn", "tokens", "ItemExtendedCost + currency", "Token / currency catalog"},
{"WTRG", ".wtrg", "triggers", "AreaTrigger.dbc + areatrigger", "Area trigger catalog"},
{"WTIT", ".wttl", "titles", "CharTitles.dbc", "Player title catalog"},
{"WSEA", ".wevt", "events", "GameEvent + spell_script", "Scripted event catalog"},
{"WMOU", ".wmnt", "mounts", "Mount.dbc + spell_mount", "Mount catalog (ground+flying)"},
{"WBGD", ".wbgd", "battle", "BattlemasterList.dbc + bg_*", "Battleground definition catalog"},
{"WMAL", ".wmal", "mail", "mail + mail_external", "In-game mail message catalog"},
{"WGEM", ".wgem", "gems", "GemProperties.dbc + Enchant.dbc", "Gem + enchantment catalog"},
{"WGLD", ".wgld", "guilds", "guild + guild_member", "Guild catalog (charters, ranks)"},
{"WPCD", ".wcnd", "cond", "Conditions + spell_proc_event", "Reusable condition rule catalog"},
{"WPET", ".wpet", "pets", "CreatureFamily.dbc + pet SQL", "Hunter pet + warlock minion catalog"},
{"WAUC", ".wauc", "auction", "auctionhouse + npc_auctioneer", "Auction house rules catalog"},
{"WCHN", ".wchn", "channels", "ChatChannels.dbc + chat_channel", "Chat channel catalog"},
{"WCMS", ".wcms", "cinematic", "Movie.dbc + CinematicCamera.dbc", "Cinematic catalog (videos, cutscenes)"},
{"WGLY", ".wgly", "glyphs", "GlyphProperties.dbc + GlyphSlot", "WotLK glyph catalog"},
{"WVHC", ".wvhc", "vehicles", "Vehicle.dbc + VehicleSeat.dbc", "Vehicle + seat-layout catalog"},
{"WHOL", ".whol", "holiday", "Holidays.dbc + game_event", "Calendar holiday + event catalog"},
{"WLIQ", ".wliq", "liquids", "LiquidType.dbc", "Liquid material catalog (water/lava/slime)"},
{"WANI", ".wani", "anim", "AnimationData.dbc", "Animation ID + fallback + weapon-flag catalog"},
{"WSVK", ".wsvk", "spellfx", "SpellVisualKit.dbc + SpellVisFx", "Spell visual kit (cast/proj/impact effects)"},
{"WWUI", ".wwui", "ui", "WorldStateUI.dbc + world_state", "World-state UI (BG scoreboards / siege counters)"},
{"WPCN", ".wpcn", "logic", "PlayerCondition.dbc + conditions", "Player condition (gates, AND/OR/NOT chains)"},
{"WTSK", ".wtsk", "crafting", "SkillLineAbility.dbc + recipes", "Trade skill recipes (per-profession crafts)"},
{"WCEQ", ".wceq", "creatures", "creature_equip_template", "Creature equipment loadout (visible weapons)"},
{"WSET", ".wset", "items", "ItemSet.dbc + ItemSetSpell.dbc", "Item set + tier-bonus catalog"},
{"WGTP", ".wgtp", "ui", "GameTips.dbc + tutorial hints", "Game tips / tutorial / loading-screen catalog"},
{"WCMP", ".wcmp", "pets", "CreatureFamily + companion SQL", "Companion / vanity pet catalog"},
{"WSMC", ".wsmc", "spells", "SpellMechanic.dbc + DR tables", "Spell mechanic / CC category catalog"},
{"WKBD", ".wkbd", "input", "KeyBinding.dbc + default binds", "Default keybinding catalog"},
{"WSCH", ".wsch", "spells", "SpellSchools.dbc + Resistances", "Spell school / damage type catalog"},
{"WLFG", ".wlfg", "social", "LFGDungeons.dbc + LFG rewards", "LFG / Dungeon Finder catalog"},
{"WMAC", ".wmac", "ui", "(client-side macro storage)", "Macro / slash command catalog"},
{"WCHF", ".wchf", "chars", "CharHairGeosets + CharFacialHair", "Character hair / face customization catalog"},
{"WPVP", ".wpvp", "pvp", "honor / arena rank tables", "PvP honor rank + arena tier catalog"},
{"WBNK", ".wbnk", "items", "ItemBag.dbc + bank slots", "Bag / bank / special slot catalog"},
{"WRUN", ".wrun", "spells", "RuneCost.dbc + ChrPowerType DK", "Death Knight rune cost catalog"},
{"WLDS", ".wlds", "ui", "LoadingScreens.dbc", "Per-zone loading screen catalog"},
{"WSUF", ".wsuf", "items", "ItemRandomProperties + Suffix", "Item random-suffix bonus catalog"},
{"WCRR", ".wcrr", "stats", "gtCombatRatings.dbc + curves", "Combat rating conversion catalog"},
{"WUMV", ".wumv", "stats", "UnitMovement.dbc + speed mods", "Unit movement type / speed catalog"},
{"WQSO", ".wqso", "quests", "QuestSort.dbc + QuestInfo cats", "Quest sort / category catalog"},
{"WSRG", ".wsrg", "spells", "SpellRange.dbc + per-spell range", "Spell range bucket catalog"},
{"WSCT", ".wsct", "spells", "SpellCastTimes.dbc + cast scaling","Spell cast time bucket catalog"},
{"WSDR", ".wsdr", "spells", "SpellDuration.dbc + per-spell dur","Spell duration bucket catalog"},
{"WSCD", ".wscd", "spells", "SpellCooldown.dbc + shared cd grp","Spell cooldown category catalog"},
{"WCEF", ".wcef", "creatures", "CreatureFamily.dbc + pet trees", "Creature / pet family catalog"},
{"WSPC", ".wspc", "spells", "Spell.dbc power-cost fields", "Spell power cost bucket catalog"},
{"WGFS", ".wgfs", "glyphs", "GlyphSlot.dbc", "Glyph slot layout catalog"},
{"WCDF", ".wcdf", "creatures", "CreatureDifficulty.dbc", "Creature difficulty variant catalog"},
{"WMAT", ".wmat", "items", "Material.dbc + ItemDisplayInfo", "Item material catalog"},
{"WPSP", ".wpsp", "chars", "playercreateinfo SQL + StartOutfit","Player spawn profile catalog"},
{"WTLE", ".wtle", "talents", "TalentTab.dbc", "Talent tab / tree catalog"},
{"WCTR", ".wctr", "currency", "CurrencyTypes.dbc + caps", "Currency type catalog"},
{"WSPR", ".wspr", "spells", "Spell.dbc Reagent[8]+Count[8]", "Spell reagent set catalog"},
{"WACR", ".wacr", "achieve", "Achievement_Criteria.dbc", "Achievement criteria catalog"},
{"WSEF", ".wsef", "spells", "SpellEffect.Effect dispatch", "Spell effect type catalog"},
{"WAUR", ".waur", "spells", "SpellEffect.EffectAuraType", "Spell aura type catalog"},
{"WIQR", ".wiqr", "items", "Item quality tier colors+rules", "Item quality tier catalog"},
{"WSCS", ".wscs", "skills", "SkillCostsData.dbc + train tiers", "Skill cost / training tier catalog"},
{"WIFS", ".wifs", "items", "Item.dbc Flags bit meanings", "Item flag bit catalog"},
{"WBKD", ".wbkd", "npcs", "npc_vendor + npc_trainer SQL", "NPC service definition catalog"},
{"WTBR", ".wtbr", "tokens", "currency_token_reward SQL", "Token reward redemption catalog"},
{"WSPS", ".wsps", "spells", "spell_proc_event SQL + Spell.dbc", "Spell proc trigger catalog"},
{"WCMR", ".wcmr", "creatures", "creature_movement waypoints SQL", "Creature patrol path catalog"},
{"WBOS", ".wbos", "raid", "instance_encounter SQL", "Boss encounter definition catalog"},
{"WHLD", ".whld", "raid", "InstanceTemplate.dbc reset fields","Instance lockout schedule catalog"},
{"WSTC", ".wstc", "pets", "stable_slot SQL + hunter UI", "Hunter stable slot catalog"},
{"WSTM", ".wstm", "stats", "gtChanceTo*.dbc + gtRegen*.dbc", "Stat modifier curve catalog"},
{"WACT", ".wact", "ui", "Hardcoded class default action bar","Action bar layout catalog"},
{"WGRP", ".wgrp", "social", "LFG group-composition rules", "Group composition catalog (role quotas)"},
{"WHRT", ".whrt", "social", "SMSG_BINDPOINTUPDATE bind list", "Hearthstone bind point catalog"},
{"WSCB", ".wscb", "server", "MOTD + scheduled SMSG_NOTIFICATION","Server channel broadcast catalog"},
{"WCMG", ".wcmg", "spells", "Stance/Form/Aspect mutex tables", "Combat maneuver group catalog (mutex spells)"},
{"WMSP", ".wmsp", "server", "realmlist + SMSG_REALM_LIST data", "Master server profile / realmlist catalog"},
{"WEMO", ".wemo", "social", "EmotesText.dbc + EmotesTextSound", "Emote definition catalog (/dance, /wave, etc.)"},
// Additional pipeline catalogs without the alternating
// gen/info/validate CLI surface (loaded by the engine
// directly).
{"WFAC", ".wfac", "factions", "Faction.dbc + FactionTemplate", "Faction + reputation catalog"},
{"WLCK", ".wlck", "locks", "Lock.dbc", "Lock + key requirement catalog"},
{"WSKL", ".wskl", "skills", "SkillLine.dbc + SkillLineAbility","Skill / profession catalog"},
{"WOLA", ".wola", "light", "Light.dbc + LightParams.dbc", "Outdoor lighting / sky color catalog"},
{"WOWA", ".wowa", "weather", "weather + LightParams", "Per-zone weather schedule catalog"},
{"WMPX", ".wmpx", "worldmap", "WorldMapArea.dbc", "World map / minimap zone catalog"},
};
constexpr size_t kFormatsCount =
sizeof(kFormats) / sizeof(kFormats[0]);
int handleList(int& i, int argc, char** argv) {
bool jsonOut = consumeJsonFlag(i, argc, argv);
if (jsonOut) {
nlohmann::json j;
j["count"] = kFormatsCount;
nlohmann::json arr = nlohmann::json::array();
for (const auto& row : kFormats) {
arr.push_back({
{"magic", row.magic},
{"extension", row.extension},
{"category", row.category},
{"replaces", row.replaces},
{"description", row.description},
});
}
j["formats"] = arr;
std::printf("%s\n", j.dump(2).c_str());
return 0;
}
std::printf("Wowee open formats: %zu total\n", kFormatsCount);
std::printf("\n");
std::printf(" magic ext category replaces description\n");
std::printf(" ------- ------- ----------- -------------------------------- -----------\n");
for (const auto& row : kFormats) {
std::printf(" %-7s %-7s %-11s %-32s %s\n",
row.magic, row.extension, row.category,
row.replaces, row.description);
}
return 0;
}
} // namespace
bool handleListFormats(int& i, int argc, char** argv, int& outRc) {
if (std::strcmp(argv[i], "--list-formats") == 0) {
outRc = handleList(i, argc, argv); return true;
}
return false;
}
} // namespace cli
} // namespace editor
} // namespace wowee