Kelsidavis-WoWee/tools/editor/cli_list_formats.cpp
Kelsi bf8d55cb3e feat(editor): add WTLE (Talent Tab) open catalog format
Open replacement for Blizzard's TalentTab.dbc plus the per-tab
fields in Spell.dbc / Talent.dbc. Defines the three talent trees
that each class has — Warrior: Arms / Fury / Protection;
Mage: Arcane / Fire / Frost; Paladin: Holy / Protection /
Retribution; etc.

Each tab carries its own name, role hint (DPS / Tank / Healer /
Hybrid / PetClass), display order in the talent UI, background
artwork path (e.g. "WarriorArms" for the parchment background),
icon path, and the class bitmask it belongs to.

Distinct from WTAL (which defines individual talent points) —
WTLE says "the Arms tree exists for Warriors, displays in tab 1,
is a DPS spec"; WTAL says "Mortal Strike is a 1-point talent in
the Arms tree, row 7, requires Improved Charge as a prerequisite".

Cross-references back to WCHC (classMask uses the same bit
layout) and forward to WTAL (talent entries reference tabId
here). findByClass(classBit) returns all tabs for a class
sorted by displayOrder — the talent UI uses this directly to
populate its tab buttons.

Three preset emitters: --gen-tle (Warrior 3 tabs with two DPS +
one Tank), --gen-tle-mage (Mage 3 DPS tabs), --gen-tle-paladin
(Paladin 3 tabs covering all three roles in one preset).

Validation enforces id+name+classMask presence (classMask=0
means no class can use the tab — usually a config bug),
roleHint 0..4, no duplicate ids; warns on empty iconPath
(missing-texture render), empty backgroundFile (no panel art),
displayOrder>3 (UI shows at most 4 tabs), and (classMask +
displayOrder) collisions for overlapping classes (two tabs
claiming the same UI slot for the same class).

Wired through the cross-format table; WTLE appears automatically
in all 12 cross-format utilities. Format count 77 -> 78; CLI flag
count 958 -> 963.
2026-05-09 22:27:18 -07:00

163 lines
11 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"},
// 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