feat(editor): add WTBR (Token Reward) open catalog format

Open replacement for AzerothCore's currency_token_reward SQL
table plus the per-vendor token redemption rows in npc_vendor.
Each entry says "spend N copies of token X to receive reward Y",
with reward type polymorphism: Y can be an item, a spell (taught
to the character), a title, a mount, a companion pet, a currency
conversion, an heirloom unlock, or a cosmetic (tabard / pennant /
fluff). The rewardId field's interpretation depends on the
rewardKind enum.

Distinct from WTKN (Token catalog) which defines the token
currency items themselves. WTKN says "the Champion's Seal exists
as item 44990"; WTBR says "spend 25 Champion's Seals at Argent
Tournament for the Squire's Belt (item 45517)".

Eight rewardKind values cover the full reward space (Item / Spell
/ Title / Mount / Pet / Currency / Heirloom / Cosmetic), and an
8-tier requiredFactionStanding gates by reputation
(Hated / Hostile / Unfriendly / Neutral / Friendly / Honored /
Revered / Exalted) when paired with a non-zero requiredFactionId.

Cross-references back to WTKN (spentTokenItemId), WIT (Item
rewards), WSPL (Spell rewards), WTIT (Title rewards), WMOU
(Mount rewards), WCMP (Pet rewards), WCTR (Currency conversion
rewards), and WFAC (faction-rep gating). findByToken(itemId)
is the engine helper used by vendor frames to populate the
"what can I buy with these?" list.

Three preset emitters: --gen-tbr (5 raid tier-token redemptions
consuming Trophy of the Crusade and Emblem of Frost),
--gen-tbr-pvp (5 PvP rewards spanning honor / arena / conquest
plus title and tabard kinds), --gen-tbr-faction (5 faction-
gated rewards demonstrating each standing tier from Honored
through Exalted).

Validation enforces id+name+spentTokenItemId+spentTokenCount
presence, rewardKind 0..7, requiredFactionStanding 0..7, no
duplicate ids; warns on:
  - rewardId=0 (no actual reward, vendor offers entry but
    grants nothing)
  - requiredFactionStanding > Neutral with requiredFactionId=0
    (rep gate has no faction to check)
  - Currency conversion item -> itself (typo / config bug)

Wired through the cross-format table; WTBR appears automatically
in all 18 cross-format utilities. Format count 87 -> 88; CLI
flag count 1034 -> 1039.
This commit is contained in:
Kelsi 2026-05-09 23:26:13 -07:00
parent 69857eea18
commit c1c4b8fa12
10 changed files with 711 additions and 0 deletions

View file

@ -0,0 +1,135 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
namespace wowee {
namespace pipeline {
// Wowee Open Token Reward catalog (.wtbr) — novel
// replacement for the per-vendor token redemption tables
// (currency_token_reward / npc_vendor token rows). Each
// entry says "spend N copies of token X to receive
// reward Y", with reward type polymorphism: Y can be an
// item, a spell (taught to the character), a title, a
// mount, a companion pet, a currency conversion, or an
// heirloom unlock. The rewardId field's interpretation
// depends on rewardKind.
//
// Distinct from WTKN (Token catalog) which defines the
// token currency items themselves. WTKN says "the
// Champion's Seal exists as item 44990"; WTBR says
// "spend 25 Champion's Seals at Argent Tournament for
// the Squire's Belt (item 45517)".
//
// Cross-references with previously-added formats:
// WTKN: spentTokenItemId references the token currency.
// WIT: rewardId references WIT.itemId for Item kind.
// WSPL: rewardId references WSPL.spellId for Spell kind.
// WTIT: rewardId references WTIT.titleId for Title kind.
// WMOU: rewardId references WMOU.mountId for Mount kind.
// WCMP: rewardId references WCMP.companionId for Pet kind.
// WCTR: rewardId references WCTR.currencyId for Currency
// conversion kind (e.g. 1 Trophy -> 50 Justice).
// WFAC: requiredFactionId references WFAC.factionId for
// reputation-gated rewards.
//
// Binary layout (little-endian):
// magic[4] = "WTBR"
// version (uint32) = current 1
// nameLen + name (catalog label)
// entryCount (uint32)
// entries (each):
// tokenRewardId (uint32)
// nameLen + name
// descLen + description
// spentTokenItemId (uint32)
// spentTokenCount (uint32)
// rewardKind (uint8) / requiredFactionStanding (uint8) / pad[2]
// rewardId (uint32)
// rewardCount (uint32)
// requiredFactionId (uint32)
// iconColorRGBA (uint32)
struct WoweeTokenReward {
enum RewardKind : uint8_t {
Item = 0, // grants WIT item
Spell = 1, // teaches WSPL spell to character
Title = 2, // grants WTIT title
Mount = 3, // unlocks WMOU mount
Pet = 4, // grants WCMP companion pet
Currency = 5, // converts to WCTR currency
Heirloom = 6, // unlocks heirloom from WIT
Cosmetic = 7, // tabard / pennant / fluff
};
enum FactionStanding : uint8_t {
Hated = 0,
Hostile = 1,
Unfriendly = 2,
Neutral = 3,
Friendly = 4,
Honored = 5,
Revered = 6,
Exalted = 7,
};
struct Entry {
uint32_t tokenRewardId = 0;
std::string name;
std::string description;
uint32_t spentTokenItemId = 0;
uint32_t spentTokenCount = 1;
uint8_t rewardKind = Item;
uint8_t requiredFactionStanding = Neutral;
uint8_t pad0 = 0;
uint8_t pad1 = 0;
uint32_t rewardId = 0;
uint32_t rewardCount = 1;
uint32_t requiredFactionId = 0;
uint32_t iconColorRGBA = 0xFFFFFFFFu;
};
std::string name;
std::vector<Entry> entries;
bool isValid() const { return !entries.empty(); }
const Entry* findById(uint32_t tokenRewardId) const;
// Returns all rewards offered for spending the given
// token item id. Used by vendor frames to populate
// the "what can I buy with these?" list.
std::vector<const Entry*> findByToken(uint32_t tokenItemId) const;
static const char* rewardKindName(uint8_t k);
static const char* factionStandingName(uint8_t s);
};
class WoweeTokenRewardLoader {
public:
static bool save(const WoweeTokenReward& cat,
const std::string& basePath);
static WoweeTokenReward load(const std::string& basePath);
static bool exists(const std::string& basePath);
// Preset emitters used by --gen-tbr* variants.
//
// makeRaidTokens — 5 raid tier-token redemptions
// (T9 Conqueror's helm, Vanquisher's
// chest, etc) consuming Trophy of
// the Crusade.
// makePvP — 5 PvP redemptions (Honor → BG
// mount, Arena → arena weapon,
// Conquest → PvP tier helm).
// makeFaction — 5 faction-gated rewards (Argent
// Tournament tabard at Honored,
// Hodir mammoth mount at Exalted,
// Cenarion ring at Revered, etc.)
static WoweeTokenReward makeRaidTokens(const std::string& catalogName);
static WoweeTokenReward makePvP(const std::string& catalogName);
static WoweeTokenReward makeFaction(const std::string& catalogName);
};
} // namespace pipeline
} // namespace wowee