mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-10 02:53:51 +00:00
feat(pipeline): add WGSP (Wowee Gossip Menu) format
Novel open replacement for AzerothCore-style gossip_menu +
gossip_menu_option + npc_text SQL tables PLUS the Blizzard
NpcText.dbc family. The 23rd open format added to the
editor.
An NPC's dialogue tree: a menu of options the player can
pick from when right-clicking the NPC. Each option may
bridge to another menu, trigger a vendor / trainer
interaction, offer a quest, etc. The simplified per-option
model (kind + actionTarget + flags + moneyCost) covers the
common cases without needing separate npc_text condition
tables.
Closes a major cross-format gap: WCRT.entry.gossipId has
existed since batch 116 (when WCRT was added) but pointed
to a format that didn't exist yet. The innkeeper preset's
menuId=4001 deliberately matches WCRT's Bartleby NPC so
the demo content stack can wire WCRT.gossipId = 4001 once
that field is plumbed through the runtime.
Cross-references:
WCRT.entry.gossipId -> WGSP.entry.menuId
WGSP.option.actionTarget (Submenu) -> WGSP.entry.menuId
WGSP.option.actionTarget (Vendor / Trainer)
-> WTRN.entry.npcId
WGSP.option.actionTarget (Quest) -> WQT.entry.questId
Format:
• magic "WGSP", version 1, little-endian
• per menu: menuId / titleText + options[]
• per option: optionId / text / kind / actionTarget /
requiredFlags / moneyCostCopper
Enums:
• OptionKind (13): Close / Submenu / Vendor / Trainer /
Quest / Tabard / Banker / Innkeeper /
FlightMaster / TextOnly / Script /
Battlemaster / Auctioneer
• OptionFlags: AllianceOnly / HordeOnly / Coinpouch /
QuestGated / Closes
API: WoweeGossipLoader::save / load / exists / findById;
presets makeStarter (1 menu with vendor + trainer + close),
makeInnkeeper (2-menu tree: main menu 4001 with hearth /
vendor / flight / submenu options + lore submenu 4002 that
links back), makeQuestGiver (1 menu with 2 quest options
referencing WQT 1 and 100, plus a paid respec script
exercising the Coinpouch flag with a 10g cost).
CLI added (5 flags, 558 documented total now):
--gen-gossip / --gen-gossip-innkeeper / --gen-gossip-questgiver
--info-wgsp / --validate-wgsp
Validator catches: menuId=0 + duplicates, empty title /
options, unknown option kind, empty option text, Submenu
options pointing at non-existent menuIds (intra-format
cross-reference resolution), Coinpouch flag without
moneyCost (misleading UI), AllianceOnly+HordeOnly conflict.
This commit is contained in:
parent
c3f7286d4a
commit
2de08a3fd0
8 changed files with 710 additions and 0 deletions
123
include/pipeline/wowee_gossip.hpp
Normal file
123
include/pipeline/wowee_gossip.hpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
// Wowee Open Gossip Menu catalog (.wgsp) — novel replacement
|
||||
// for AzerothCore-style gossip_menu + gossip_menu_option +
|
||||
// npc_text SQL tables PLUS the Blizzard NpcText.dbc family.
|
||||
// The 23rd open format added to the editor.
|
||||
//
|
||||
// An NPC's dialogue tree: a menu of options the player can
|
||||
// pick from when right-clicking the NPC. Each option may
|
||||
// bridge to another menu, trigger a vendor / trainer
|
||||
// interaction, offer a quest, etc.
|
||||
//
|
||||
// This format closes the WCRT.gossipId cross-reference gap
|
||||
// from batch 116 — until now WCRT had a gossipId field that
|
||||
// pointed to a format that didn't exist yet.
|
||||
//
|
||||
// Cross-references with previously-added formats:
|
||||
// WCRT.entry.gossipId → WGSP.entry.menuId
|
||||
// WGSP.option.actionTarget (kind=Submenu) → WGSP.entry.menuId
|
||||
// (intra-format chain)
|
||||
// WGSP.option.actionTarget (kind=Vendor / Trainer)
|
||||
// → WTRN.entry.npcId
|
||||
// WGSP.option.actionTarget (kind=Quest) → WQT.entry.questId
|
||||
//
|
||||
// Binary layout (little-endian):
|
||||
// magic[4] = "WGSP"
|
||||
// version (uint32) = current 1
|
||||
// nameLen + name (catalog label)
|
||||
// entryCount (uint32)
|
||||
// entries (each):
|
||||
// menuId (uint32)
|
||||
// titleLen + titleText
|
||||
// optionCount (uint8) + pad[3]
|
||||
// options (optionCount × {
|
||||
// optionId (uint32)
|
||||
// textLen + text
|
||||
// kind (uint8) + pad[3]
|
||||
// actionTarget (uint32)
|
||||
// requiredFlags (uint32)
|
||||
// moneyCostCopper (uint32)
|
||||
// })
|
||||
struct WoweeGossip {
|
||||
enum OptionKind : uint8_t {
|
||||
Close = 0, // closes the menu, no action
|
||||
Submenu = 1, // jumps to another menuId
|
||||
Vendor = 2, // opens vendor inventory window
|
||||
Trainer = 3, // opens trainer spell window
|
||||
Quest = 4, // opens quest dialog
|
||||
Tabard = 5, // opens tabard customization
|
||||
Banker = 6, // opens bank
|
||||
Innkeeper = 7, // sets hearth + opens vendor
|
||||
FlightMaster = 8, // opens taxi node
|
||||
TextOnly = 9, // dialogue only, no action
|
||||
Script = 10, // triggers a server-side script
|
||||
Battlemaster = 11,
|
||||
Auctioneer = 12,
|
||||
};
|
||||
|
||||
enum OptionFlags : uint32_t {
|
||||
AllianceOnly = 0x01,
|
||||
HordeOnly = 0x02,
|
||||
Coinpouch = 0x04, // shows the coin icon when paid
|
||||
QuestGated = 0x08, // visible only with matching quest
|
||||
Closes = 0x10, // closes the menu after the action
|
||||
};
|
||||
|
||||
struct Option {
|
||||
uint32_t optionId = 0;
|
||||
std::string text;
|
||||
uint8_t kind = TextOnly;
|
||||
uint32_t actionTarget = 0; // submenu / NPC / quest id
|
||||
uint32_t requiredFlags = 0;
|
||||
uint32_t moneyCostCopper = 0;
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
uint32_t menuId = 0;
|
||||
std::string titleText;
|
||||
std::vector<Option> options;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<Entry> entries;
|
||||
|
||||
bool isValid() const { return !entries.empty(); }
|
||||
|
||||
// Lookup by menuId — nullptr if not present.
|
||||
const Entry* findById(uint32_t menuId) const;
|
||||
|
||||
static const char* optionKindName(uint8_t k);
|
||||
};
|
||||
|
||||
class WoweeGossipLoader {
|
||||
public:
|
||||
static bool save(const WoweeGossip& cat,
|
||||
const std::string& basePath);
|
||||
static WoweeGossip load(const std::string& basePath);
|
||||
static bool exists(const std::string& basePath);
|
||||
|
||||
// Preset emitters used by --gen-gossip* variants.
|
||||
//
|
||||
// makeStarter — single menu with greeting + 3 options
|
||||
// (vendor / trainer / close).
|
||||
// makeInnkeeper — menu 4001 (matches WCRT.gossipId on
|
||||
// Bartleby): set hearth + browse goods
|
||||
// + bind to flight + close.
|
||||
// makeQuestGiver — branching menu: greeting + 2 quests +
|
||||
// submenu "tell me about the area"
|
||||
// leading to lore text + close.
|
||||
static WoweeGossip makeStarter(const std::string& catalogName);
|
||||
static WoweeGossip makeInnkeeper(const std::string& catalogName);
|
||||
static WoweeGossip makeQuestGiver(const std::string& catalogName);
|
||||
};
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue