From 2de08a3fd0c6367c6d6ade42e059eacc46c5a109 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 9 May 2026 16:20:07 -0700 Subject: [PATCH] feat(pipeline): add WGSP (Wowee Gossip Menu) format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- CMakeLists.txt | 3 + include/pipeline/wowee_gossip.hpp | 123 ++++++++++++ src/pipeline/wowee_gossip.cpp | 266 +++++++++++++++++++++++++ tools/editor/cli_arg_required.cpp | 2 + tools/editor/cli_dispatch.cpp | 2 + tools/editor/cli_gossip_catalog.cpp | 293 ++++++++++++++++++++++++++++ tools/editor/cli_gossip_catalog.hpp | 11 ++ tools/editor/cli_help.cpp | 10 + 8 files changed, 710 insertions(+) create mode 100644 include/pipeline/wowee_gossip.hpp create mode 100644 src/pipeline/wowee_gossip.cpp create mode 100644 tools/editor/cli_gossip_catalog.cpp create mode 100644 tools/editor/cli_gossip_catalog.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b3410882..905e83da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,6 +610,7 @@ set(WOWEE_SOURCES src/pipeline/wowee_spells.cpp src/pipeline/wowee_achievements.cpp src/pipeline/wowee_trainers.cpp + src/pipeline/wowee_gossip.cpp src/pipeline/custom_zone_discovery.cpp src/pipeline/dbc_layout.cpp @@ -1366,6 +1367,7 @@ add_executable(wowee_editor tools/editor/cli_spells_catalog.cpp tools/editor/cli_achievements_catalog.cpp tools/editor/cli_trainers_catalog.cpp + tools/editor/cli_gossip_catalog.cpp tools/editor/cli_quest_objective.cpp tools/editor/cli_quest_reward.cpp tools/editor/cli_clone.cpp @@ -1454,6 +1456,7 @@ add_executable(wowee_editor src/pipeline/wowee_spells.cpp src/pipeline/wowee_achievements.cpp src/pipeline/wowee_trainers.cpp + src/pipeline/wowee_gossip.cpp src/pipeline/custom_zone_discovery.cpp src/pipeline/terrain_mesh.cpp diff --git a/include/pipeline/wowee_gossip.hpp b/include/pipeline/wowee_gossip.hpp new file mode 100644 index 00000000..0c96cb3a --- /dev/null +++ b/include/pipeline/wowee_gossip.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include +#include +#include + +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