Kelsidavis-WoWee/tools/editor/cli_list_formats.cpp

144 lines
8.7 KiB
C++
Raw Normal View History

#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)"},
feat(pipeline): add WTSK (Wowee Trade Skill / Recipe) catalog New open format — replaces SkillLineAbility.dbc plus the recipe portions of SkillLine.dbc plus the AzerothCore trade_skill SQL tables. Closes the crafting gap left by WSKL (which carries skill lines but not the recipes that bind to them). 14 professions (Blacksmithing, Tailoring, Engineering, Alchemy, Enchanting, Leatherworking, Jewelcrafting, Inscription, Mining, Skinning, Herbalism, Cooking, FirstAid, Fishing). Each recipe has 4 skill-up bracket thresholds (orange / yellow / green / gray) for skill-up probability, a craft spell cross-ref (WSPL), produced item cross-ref (WIT) with min/max quantity range, an optional tool item, and up to 4 reagent slots (itemId + count). Cross-references with prior formats — craftSpellId points at WSPL.spellId, producedItemId / toolItemId / reagent[].itemId all point at WIT.itemId, and skillId points at WSKL.skillId. CLI: --gen-tsk (3-recipe entry-tier starter), --gen-tsk- blacksmithing (5-recipe progression rough sharpening through truesilver champion), --gen-tsk-alchemy (5-recipe progression minor healing through flask of titans), --info-wtsk, --validate-wtsk with --json variants. Validator catches id=0/duplicates, profession out of range, missing craft spell or produced item, monotonic-bracket check (must be orange <= yellow <= green <= gray), reagent itemId-without-count mismatch, and free-recipe warning (no reagents and no tool). Format graph now exposes 49 distinct binary formats. CLI flag count: 747 → 752.
2026-05-09 19:41:49 -07:00
{"WTSK", ".wtsk", "crafting", "SkillLineAbility.dbc + recipes", "Trade skill recipes (per-profession crafts)"},
feat(pipeline): add WCEQ (Wowee Creature Equipment) — 50th open format Replaces the AzerothCore-style creature_equip_template SQL tables plus the visible-weapon / shield / ranged-slot data that was traditionally embedded in creature templates. Closes a long-standing gap in the creature subsystem: until now WCRT defined a creature's stats, WSPN placed it in the world, and WLOT defined what it drops — but nothing defined what items it visibly equips. Each entry binds a creatureId to up to three equipped items (main hand / off hand / ranged) plus the visual kit that fires when the main-hand weapon is brandished. equipFlags bits encode hidden / dual-wield / shield-offhand / thrown-ranged / 2H polearm to drive the renderer's attachment-point selection. Cross-references with prior formats — creatureId points at WCRT.creatureId, mainHandItemId / offHandItemId / rangedItemId all point at WIT.itemId, and mainHandVisualId points at WSVK.visualKitId so brandished weapons can play their signature glow / aura. CLI: --gen-ceq (3 generic guard/hunter/rogue starters), --gen-ceq-bosses (4 iconic loadouts incl. Frostmourne and Illidan's warglaives, with WSVK visual cross-refs), --gen-ceq-ranged (3 ranged-only rifle/bow/crossbow loadouts), --info-wceq, --validate-wceq with --json variants. Validator catches id=0/duplicates, missing creatureId, all-empty-slots warning, kFlagDualWield without both hand items, kFlagShield without offhand item, mutually-exclusive dual-wield + shield, and 2H polearm with offhand item filled. Format graph milestone: 50 distinct binary formats. CLI flag count: 754 → 760.
2026-05-09 19:48:13 -07:00
{"WCEQ", ".wceq", "creatures", "creature_equip_template", "Creature equipment loadout (visible weapons)"},
feat(pipeline): add WSET (Wowee Item Set / Tier Bonus) catalog 51st open format — replaces ItemSet.dbc + ItemSetSpell.dbc plus the AzerothCore-style item_set_spell SQL data. Closes the tier-bonus gap left by WIT (which describes individual items but not the set bonuses they grant when worn together). Each entry binds up to 8 piece item IDs to up to 4 bonus thresholds — at N pieces worn, the matching bonus spell activates as an aura. Standard 2/4/6/8-piece tier set pattern is the canonical case; 5-piece PvP sets with 2/4 bonuses are also supported. Cross-references with prior formats — itemIds[] point at WIT.itemId, bonusSpellIds[] point at WSPL.spellId, and requiredSkillId points at WSKL.skillId. requiredClassMask is a 32-bit field (uint32_t) so bit positions match WCHC's classId enum directly — Druid (bit 11 = 0x800) and Mage (bit 8 = 0x100) wouldn't fit in a uint8_t. CLI: --gen-itset (2 raid sets — Battlegear of Wrath + Stormrage Raiment, real WoW item/spell IDs), --gen-itset-tier (4 tier-1 progression sets covering plate / cloth / leather / holy plate), --gen-itset-pvp (3 PvP gladiator 5-piece sets with honor-rank skill thresholds), --info-wset, --validate-wset with --json variants. Validator catches id+name+pieceCount required, pieceCount/bonusCount within array bounds, piece- slot drift (0 IDs within count or non-0 IDs past count), bonus thresholds strictly ascending, no bonus threshold exceeding pieceCount (would never trigger), and spellId=0 in any populated bonus slot. Format graph: 50 → 51 binary formats. CLI flag count: 762 → 767.
2026-05-09 19:54:36 -07:00
{"WSET", ".wset", "items", "ItemSet.dbc + ItemSetSpell.dbc", "Item set + tier-bonus catalog"},
feat(pipeline): add WGTP (Wowee Game Tips) catalog 52nd open format — replaces GameTips.dbc plus loading-screen tutorial hint tables. Defines the rotating tips shown during world loads, the contextual tutorial hints that fire on first gameplay events (first quest accept, first death, first dungeon entry), and the persistent tooltip-help strings that explain UI elements. 4 display kinds (LoadingScreen / Tutorial / TooltipHelp / Hint), 7 audience-filter bits (Alliance / Horde / NewPlayer / Hardcore / PvE / PvP / Roleplay) for pool selection, level range gating (minLevel + maxLevel), displayWeight for relative frequency within the pool, optional WPCN condition cross-ref for further gating, and class-mask restriction matching WCHC bit positions. Cross-references with prior formats — conditionId points at WPCN.conditionId for advanced gating; requiredClassMask uses the same WCHC.classId bit layout as WGLY/WSET. CLI: --gen-tips (3 generic loading-screen tips), --gen-tips- new-player (5 onboarding Tutorial-kind tips for level 1-15, weighted higher for new players), --gen-tips-advanced (4 endgame tips for level 70+ covering raid mechanics / arena / daily professions / dungeon finder), --info-wgtp, --validate-wgtp with --json variants. Validator catches id/name/text required, kind 0..3, audienceFilter=0 (tip never shown), invalid level range, displayWeight=0 (in pool but never picked) warning, and brevity check (>280 chars) on Tutorial / Hint kinds that need to fit on screen. Format graph: 51 → 52 binary formats. CLI flag count: 770 → 775.
2026-05-09 20:00:56 -07:00
{"WGTP", ".wgtp", "ui", "GameTips.dbc + tutorial hints", "Game tips / tutorial / loading-screen catalog"},
2026-05-09 20:05:06 -07:00
{"WCMP", ".wcmp", "pets", "CreatureFamily + companion SQL", "Companion / vanity pet catalog"},
feat(pipeline): add WSMC (Wowee Spell Mechanic) catalog 54th open format — replaces SpellMechanic.dbc plus the AzerothCore-style diminishing-returns (DR) tables. Defines crowd-control mechanic categories that spells reference: Stun, Silence, Polymorph, Sleep, Fear, Root, Snare, Slow, Knockback, etc. Each mechanic carries gameplay metadata (breaks-on-damage, can-be-dispelled, default duration, max stacks) plus DR category and dispel type. 8 DR categories (DRNone / DRStun / DRDisorient / DRSilence / DRRoot / DRPolymorph / DRControlled / DRMisc) — the runtime uses these to gate repeated CC on the same target. 7 dispel types (DispelNone / Magic / Curse / Disease / Poison / Enrage / Stealth) bind which dispel spells can remove the mechanic. conflictsMask is a bitmask of OTHER mechanic IDs — only one mechanic from a conflict-group can apply to a target simultaneously. Cross-references with prior formats — mechanicId is referenced by WSPL.spellId entries that apply this CC; this catalog is referenced from spell tags rather than referencing out. CLI: --gen-smc (3 baseline Stun/Silence/Snare), --gen-smc- hard (5 hard-CC: Stun/Polymorph/Sleep/Fear/Knockback with conflictsMask wiring), --gen-smc-roots (4 movement-impair: Root/Snare/Slow stacking 5x/GroundPin breaks-on-damage), --info-wsmc, --validate-wsmc with --json variants. Validator catches id+name required, DR category 0..7, dispel type 0..6, maxStacks=0 (mechanic could never apply), canBeDispelled+DispelNone inconsistency, and self-conflict bit set in conflictsMask (mechanic blocking itself). Format graph: 53 → 54 binary formats. CLI flag count: 784 → 789.
2026-05-09 20:09:44 -07:00
{"WSMC", ".wsmc", "spells", "SpellMechanic.dbc + DR tables", "Spell mechanic / CC category catalog"},
{"WKBD", ".wkbd", "input", "KeyBinding.dbc + default binds", "Default keybinding catalog"},
feat(pipeline): add WSCH (Wowee Spell School) catalog 56th open format — replaces SpellSchools.dbc plus the Resistances.dbc resistance-cap tables. Defines damage schools spells use: Physical, Holy, Fire, Nature, Frost, Shadow, Arcane, plus combined / hybrid schools that count as multiple types simultaneously (Spellfire, Spellshadow, Spellfrost — relevant for resistance-bypass mechanics). 7 canonical schools with single-bit IDs (1, 2, 4, 8, 16, 32, 64) so combinedSchoolMask values line up directly with the spell engine's school-bit enum. Hybrid schools use high-bit IDs (0x80000001+) and their combinedSchoolMask references the canonical bits they qualify as. Each school carries visual identity (color tint, icon), gameplay rules (canBeImmune / canBeAbsorbed / canBeReflected / canCrit), resistance cap at max level, and cast / impact sound IDs. Cross-references with prior formats — castSoundId and impactSoundId point at WSND.soundId; combinedSchoolMask is a bitmask of OTHER WSCH.schoolId values within the same catalog. CLI: --gen-sch (3 base — Physical / Fire / Holy showing non-resistable Holy + non-reflectable Physical), --gen-sch- magical (6 canonical magical schools with proper colors + 365 max-level resistance caps), --gen-sch-combined (3 hybrids — Spellfire / Spellshadow / Spellfrost with multi-bit combinedSchoolMask), --info-wsch, --validate-wsch with --json variants. Validator catches id+name required, reflected-without-absorbed warning (reflected damage should be absorbable), self-referential combinedSchoolMask (school qualifying as itself), and combined-mask references to bits not defined in the same catalog (resolved at runtime across catalogs). Format graph: 55 → 56 binary formats. CLI flag count: 798 → 804.
2026-05-09 20:19:34 -07:00
{"WSCH", ".wsch", "spells", "SpellSchools.dbc + Resistances", "Spell school / damage type catalog"},
feat(pipeline): add WLFG (Wowee Looking-for-Group) catalog 57th open format — replaces LFGDungeons.dbc plus the AzerothCore-style dungeon-finder reward tables. Defines the dungeons / raids that the Dungeon Finder / Raid Browser presents to players, with their level brackets, group-size requirements, role requirements (tank / heal / DPS), and queue-completion rewards. 4 difficulty levels (Normal / Heroic / Mythic / Hardmode — the latter for Ulduar-style toggleable boss difficulty), 4 expansion gates (Classic / TBC / WotLK / TurtleWoW), and 3 role-requirement bits (Tank / Heal / DPS — typically all three for queue-formed groups). Cross-references with prior formats — mapId points at WMS.mapId (the instance map), queueRewardItemId points at WIT.itemId (the random reward bag), firstClearAchievement points at WACH.achievementId. CLI: --gen-lfg (3 classic 5-mans Ragefire/Wailing/Deadmines with real WoW mapIds + level brackets), --gen-lfg-heroic (5 WotLK 80-level heroic 5-mans with emblem rewards + real first-clear achievement IDs from Halls of Lightning through Old Kingdom), --gen-lfg-raid (3 raid entries — Naxx-25, Ulduar-25 Hardmode, ToC-25 Mythic), --info-wlfg, --validate-wlfg with --json variants. Validator catches id+name+mapId required, difficulty 0..3, expansion 0..3, minLevel<=maxLevel, recommended-level outside range warning, unusual groupSize warning (5/10/25/40 are canonical), and zero role mask (queue can't form a balanced group). Format graph: 56 → 57 binary formats. CLI flag count: 804 → 811.
2026-05-09 20:24:21 -07:00
{"WLFG", ".wlfg", "social", "LFGDungeons.dbc + LFG rewards", "LFG / Dungeon Finder catalog"},
feat(pipeline): add WMAC (Wowee Macro / Slash Command) catalog 58th open format — novel format with no direct DBC equivalent. WoW historically stored player macros client-side in the user profile and system slash commands as hardcoded engine handlers; WMAC unifies both into a single structured catalog so default macros, system slash commands, and shipped player presets can be authored, validated, and shipped as content alongside the rest of the open-format graph. 5 macro kinds (SystemSlash for engine /sit /dance handlers, DefaultMacro for shipped presets, PlayerTemplate for user templates, GuildMacro for guild-shared, SharedMacro for account-wide). Multi-line macro bodies are stored verbatim with literal '\n' separators — the client parses /cast / /target / /run lines at runtime. Cross-references with prior formats — requiredClassMask uses WCHC.classId bit positions (Warrior=0x02, etc, same as WGLY/ WSET/WGTP). CLI: --gen-mac (3 system slash — /sit, /dance, /target with [@mouseover] modifier), --gen-mac-combat (4 warrior combat templates — heroic strike spam, charge/intercept stance dance, intercept stance switch, victory rush+bloodthirst fallback — each with default key bindings), --gen-mac-utility (3 universal utility — /follow target, mass /inv with %targetN tokens, /releasecorpse via RepopMe()), --info-wmac, --validate-wmac with --json variants. Validator catches id+name+body required, kind 0..4, body within maxLength cap, body starting with '/' or '#' (slash command or showtooltip annotation), and SystemSlash + classMask warning (slash commands are class- agnostic — restricting them to a class makes no sense). Format graph: 57 → 58 binary formats. CLI flag count: 814 → 819.
2026-05-09 20:30:17 -07:00
{"WMAC", ".wmac", "ui", "(client-side macro storage)", "Macro / slash command catalog"},
// 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