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.
This commit is contained in:
Kelsi 2026-05-09 22:27:18 -07:00
parent 9a09831957
commit bf8d55cb3e
10 changed files with 661 additions and 0 deletions

View file

@ -0,0 +1,110 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
namespace wowee {
namespace pipeline {
// Wowee Open Talent Tab catalog (.wtle) — novel
// 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), display order in the talent UI,
// background artwork path, icon, and the class bitmask
// it belongs to.
//
// Distinct from WTAL (Talents) which defines individual
// talent points and their effects. 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 with previously-added formats:
// WCHC: classMask uses the same bit layout as WCHC
// class IDs.
// WTAL: talent entries reference tabId here.
//
// Binary layout (little-endian):
// magic[4] = "WTLE"
// version (uint32) = current 1
// nameLen + name (catalog label)
// entryCount (uint32)
// entries (each):
// tabId (uint32)
// nameLen + name
// descLen + description
// classMask (uint32)
// displayOrder (uint8) / roleHint (uint8) / pad[2]
// iconPathLen + iconPath
// backgroundFileLen + backgroundFile
// iconColorRGBA (uint32)
struct WoweeTalentTab {
enum RoleHint : uint8_t {
DPS = 0, // damage-dealing spec
Tank = 1, // mitigation spec
Healer = 2, // healing spec
Hybrid = 3, // can fill multiple roles
PetClass = 4, // hunter/warlock pet-focused tree
};
struct Entry {
uint32_t tabId = 0;
std::string name;
std::string description;
uint32_t classMask = 0;
uint8_t displayOrder = 0;
uint8_t roleHint = DPS;
uint8_t pad0 = 0;
uint8_t pad1 = 0;
std::string iconPath;
std::string backgroundFile;
uint32_t iconColorRGBA = 0xFFFFFFFFu;
};
std::string name;
std::vector<Entry> entries;
bool isValid() const { return !entries.empty(); }
const Entry* findById(uint32_t tabId) const;
// Return all tabs for the given class, in displayOrder.
// The talent UI uses this to populate the three (or
// four, for druids) tab buttons.
std::vector<const Entry*> findByClass(uint32_t classBit) const;
static const char* roleHintName(uint8_t r);
};
class WoweeTalentTabLoader {
public:
static bool save(const WoweeTalentTab& cat,
const std::string& basePath);
static WoweeTalentTab load(const std::string& basePath);
static bool exists(const std::string& basePath);
// Preset emitters used by --gen-tle* variants.
//
// makeWarrior — 3 tabs (Arms DPS / Fury DPS /
// Protection Tank) with the
// canonical Warrior icon paths.
// makeMage — 3 tabs (Arcane / Fire / Frost),
// all DPS, with the canonical Mage
// icon paths.
// makePaladin — 3 tabs (Holy Healer / Protection
// Tank / Retribution DPS) covering
// all three roles in one preset.
static WoweeTalentTab makeWarrior(const std::string& catalogName);
static WoweeTalentTab makeMage(const std::string& catalogName);
static WoweeTalentTab makePaladin(const std::string& catalogName);
};
} // namespace pipeline
} // namespace wowee