mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-10 02:53:51 +00:00
Novel open replacement for Blizzard's TalentTab.dbc +
Talent.dbc + the AzerothCore-style talent_progression SQL
tables. The 25th open format added to the editor.
Defines class talent specialization trees: per-class set
of named tabs (Arms / Fury / Protection for warrior, Fire
/ Frost / Arcane for mage), each with talents arranged in
a row/column grid, each talent having up to 5 ranks and
an optional prerequisite chain.
Cross-references with previously-added formats:
WTAL.talent.prereqTalentId -> WTAL.talent.talentId
(intra-format chain)
WTAL.talent.rankSpellIds[] -> WSPL.entry.spellId
(spell granted at each rank)
Format:
• magic "WTAL", version 1, little-endian
• per tree: treeId / name / iconPath / requiredClassMask /
talents[] (row, col, maxRank, prereqTalentId+rank,
rankSpellIds[5] zero-padded for unused ranks)
Enums:
• ClassMask: bit positions match canonical CharClasses.dbc
classIds — Warrior / Paladin / Hunter / Rogue / Priest /
DK / Shaman / Mage / Warlock / Druid
API: WoweeTalentLoader::save / load / exists +
WoweeTalent::findTree / findTalent (global lookup across
all trees in the catalog).
Three preset emitters showcase tree shapes:
• makeStarter — 1 small tree (3-talent vertical chain)
• makeWarrior — 3 trees (Arms 4 / Fury 4 / Protection 3)
with WSPL cross-refs at capstones
(Mortal Strike -> WSPL 12294, Battle Shout
-> WSPL 6673, Thunder Clap -> WSPL 6343)
• makeMage — 3 trees (Arcane / Fire / Frost) with
capstones referencing Frostbolt 116 /
Fireball 133 / Blink 1953 from WSPL
CLI added (5 flags, 571 documented total now):
--gen-talents / --gen-talents-warrior / --gen-talents-mage
--info-wtal / --validate-wtal
Validator catches: tree+talent ids=0 or duplicates, empty
tree name, requiredClassMask=0 (every class would see this
tree — usually a typo), maxRank not in 1..5, talent listing
itself as prerequisite, prereqTalentId pointing at a
talent that doesn't exist in this catalog (intra-format
cross-reference resolution), prereqRank=0 or > the prereq
talent's maxRank (catches off-by-one references), gaps in
rankSpellIds progression (rank N has spell but rank N-1
doesn't — usually a typo).
The validator caught a real authoring bug in the makeMage /
makeWarrior presets during smoke testing — initial check
was comparing prereqRank against the WRONG talent's maxRank
(this talent's rather than the prereq's). Fixed in the same
commit by hoisting the check into the cross-reference
resolution pass where the prereq talent is in hand.
115 lines
3.8 KiB
C++
115 lines
3.8 KiB
C++
#pragma once
|
||
|
||
#include <cstdint>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace wowee {
|
||
namespace pipeline {
|
||
|
||
// Wowee Open Talent catalog (.wtal) — novel replacement for
|
||
// Blizzard's TalentTab.dbc + Talent.dbc + the AzerothCore-
|
||
// style talent_progression SQL tables. The 25th open format
|
||
// added to the editor.
|
||
//
|
||
// Defines class talent specialization trees: a per-class set
|
||
// of named tabs (Arms / Fury / Protection for warrior, Fire
|
||
// / Frost / Arcane for mage, etc.), each with up to N
|
||
// talents arranged in a row/column grid, each talent having
|
||
// up to 5 ranks and an optional prerequisite chain.
|
||
//
|
||
// Cross-references with previously-added formats:
|
||
// WTAL.talent.prereqTalentId → WTAL.talent.talentId
|
||
// (intra-format chain)
|
||
// WTAL.talent.rankSpellIds[] → WSPL.entry.spellId
|
||
// (spell granted at each rank)
|
||
//
|
||
// Binary layout (little-endian):
|
||
// magic[4] = "WTAL"
|
||
// version (uint32) = current 1
|
||
// nameLen + name (catalog label)
|
||
// treeCount (uint32)
|
||
// trees (each):
|
||
// treeId (uint32)
|
||
// nameLen + name
|
||
// iconLen + iconPath
|
||
// requiredClassMask (uint32)
|
||
// talentCount (uint16) + pad[2]
|
||
// talents (talentCount × {
|
||
// talentId (uint32)
|
||
// row (uint8) / col (uint8) / maxRank (uint8) / pad[1]
|
||
// prereqTalentId (uint32) / prereqRank (uint8) / pad[3]
|
||
// rankSpellIds[5] (uint32 each, zero-padded for unused ranks)
|
||
// })
|
||
struct WoweeTalent {
|
||
static constexpr int kMaxRanks = 5;
|
||
|
||
// Class IDs follow Blizzard's CharClasses.dbc canonical
|
||
// bit positions (bit N corresponds to classId N+1):
|
||
// 1=Warrior 2=Paladin 3=Hunter 4=Rogue 5=Priest
|
||
// 6=DK 7=Shaman 8=Mage 9=Warlock 10=- 11=Druid
|
||
enum ClassMask : uint32_t {
|
||
ClassWarrior = 1u << 0,
|
||
ClassPaladin = 1u << 1,
|
||
ClassHunter = 1u << 2,
|
||
ClassRogue = 1u << 3,
|
||
ClassPriest = 1u << 4,
|
||
ClassDK = 1u << 5,
|
||
ClassShaman = 1u << 6,
|
||
ClassMage = 1u << 7,
|
||
ClassWarlock = 1u << 8,
|
||
ClassDruid = 1u << 10,
|
||
};
|
||
|
||
struct Talent {
|
||
uint32_t talentId = 0;
|
||
uint8_t row = 0;
|
||
uint8_t col = 0;
|
||
uint8_t maxRank = 1;
|
||
uint32_t prereqTalentId = 0;
|
||
uint8_t prereqRank = 0;
|
||
uint32_t rankSpellIds[kMaxRanks] = {0, 0, 0, 0, 0};
|
||
};
|
||
|
||
struct Tree {
|
||
uint32_t treeId = 0;
|
||
std::string name;
|
||
std::string iconPath;
|
||
uint32_t requiredClassMask = 0;
|
||
std::vector<Talent> talents;
|
||
};
|
||
|
||
std::string name;
|
||
std::vector<Tree> trees;
|
||
|
||
bool isValid() const { return !trees.empty(); }
|
||
|
||
const Tree* findTree(uint32_t treeId) const;
|
||
// Talent lookup is global across all trees (talentIds are
|
||
// expected to be unique within a single .wtal catalog).
|
||
const Talent* findTalent(uint32_t talentId) const;
|
||
};
|
||
|
||
class WoweeTalentLoader {
|
||
public:
|
||
static bool save(const WoweeTalent& cat,
|
||
const std::string& basePath);
|
||
static WoweeTalent load(const std::string& basePath);
|
||
static bool exists(const std::string& basePath);
|
||
|
||
// Preset emitters used by --gen-talents* variants.
|
||
//
|
||
// makeStarter — 1 small tree (3 talents, no prereqs).
|
||
// makeWarrior — 3 trees (Arms / Fury / Protection) each
|
||
// with a handful of talents, prerequisite
|
||
// chains, and rankSpellIds wired to WSPL
|
||
// warrior preset spells where applicable.
|
||
// makeMage — 3 trees (Arcane / Fire / Frost) with
|
||
// links to WSPL mage preset spell IDs.
|
||
static WoweeTalent makeStarter(const std::string& catalogName);
|
||
static WoweeTalent makeWarrior(const std::string& catalogName);
|
||
static WoweeTalent makeMage(const std::string& catalogName);
|
||
};
|
||
|
||
} // namespace pipeline
|
||
} // namespace wowee
|