mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-11 11:33:52 +00:00
feat(pipeline): WQGR quest graph catalog (132nd open format)
Novel representation of quest-chain dependencies that vanilla
WoW carried implicitly in QuestRelations.dbc (the prequest
column) + per-quest server scripts. Each WQGR entry binds one
quest to its display name, level/class/race gating,
prerequisite quest list (must be completed first), follow-up
quest hints (next-quest suggestions for the journal UI), and
quest type flags (Normal / Daily / Repeatable / Group / Raid).
Three presets:
--gen-qgr-starter 5-quest linear chain (Northshire human-
starter Q100..Q104, levels 1..8) with
chainHeadHint=1 on Q100
--gen-qgr-branched 4-quest converging DAG (Q200 unlocks
both Q201 + Q202, both required for Q203)
— demonstrates true DAG semantics, not
just linear lists
--gen-qgr-dailies 3 standalone daily quests (Daily type,
no prereqs, no followups)
Validator catches: id+name required, questType 0..4,
factionAccess 0..3, maxLevel >= minLevel, no self-prereq
(catch-22), no missing prereq questId, full DFS cycle detection
on prevQuestIds (progression deadlock — quests would be
unreachable). Reuses the proven cycle-extraction pattern from
WMOD addon manifest (extracts back-edge path so the editor sees
the loop). Warns on followup hint to self/missing-id (advisory
only — followups are hints not contracts) and on
chainHeadHint=1 with non-empty prereqs (contradicts chain-head
semantics).
Format count 131 -> 132. CLI flag count 1382 -> 1389.
This commit is contained in:
parent
25ecdb0813
commit
76cda20297
10 changed files with 847 additions and 0 deletions
152
include/pipeline/wowee_quest_graph.hpp
Normal file
152
include/pipeline/wowee_quest_graph.hpp
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
// Wowee Open Quest Graph catalog (.wqgr) — novel
|
||||
// representation of quest-chain dependencies that
|
||||
// vanilla WoW carried implicitly in
|
||||
// QuestRelations.dbc (the prequest column) +
|
||||
// per-quest server scripts. Each WQGR entry binds
|
||||
// one quest to its display name, level/class/race
|
||||
// gating, prerequisite quest list (must be
|
||||
// completed first), follow-up quest hints (next-
|
||||
// quest suggestions for the journal UI), and quest
|
||||
// type flags (Normal / Daily / Repeatable / Group /
|
||||
// Raid).
|
||||
//
|
||||
// The variable-length prereq array gives the
|
||||
// validator something interesting to check: a DFS
|
||||
// cycle detector flags player-unreachable quests
|
||||
// (Q1 prereq=Q2, Q2 prereq=Q3, Q3 prereq=Q1 is a
|
||||
// progression deadlock — no player could ever
|
||||
// satisfy the cycle).
|
||||
//
|
||||
// Cross-references with previously-added formats:
|
||||
// WQTM: questId references the WQTM quest catalog
|
||||
// (the actual quest objectives + rewards
|
||||
// live in WQTM; WQGR only describes the
|
||||
// dependency graph between them).
|
||||
// WMS: zoneId references the WMS map catalog.
|
||||
//
|
||||
// Binary layout (little-endian):
|
||||
// magic[4] = "WQGR"
|
||||
// version (uint32) = current 1
|
||||
// nameLen + name (catalog label)
|
||||
// entryCount (uint32)
|
||||
// entries (each):
|
||||
// questId (uint32)
|
||||
// nameLen + name
|
||||
// minLevel (uint8)
|
||||
// maxLevel (uint8) — 0 = no upper gate
|
||||
// questType (uint8) — 0=Normal /
|
||||
// 1=Daily /
|
||||
// 2=Repeatable /
|
||||
// 3=Group /
|
||||
// 4=Raid
|
||||
// factionAccess (uint8) — 0=Both /
|
||||
// 1=Alliance /
|
||||
// 2=Horde /
|
||||
// 3=Neutral
|
||||
// classRestriction (uint16) — bitmask of allowed
|
||||
// classIds (0 =
|
||||
// no restriction)
|
||||
// raceRestriction (uint16) — bitmask of allowed
|
||||
// raceIds (0 =
|
||||
// no restriction)
|
||||
// zoneId (uint32)
|
||||
// chainHeadHint (uint8) — 0/1 bool — first
|
||||
// quest in a chain
|
||||
// (UI sort hint)
|
||||
// pad0 (uint8)
|
||||
// pad1 (uint16)
|
||||
// prevCount (uint32) — prereq array
|
||||
// prevQuestIds (uint32 × count)
|
||||
// followupCount (uint32) — hint array
|
||||
// followupQuestIds (uint32 × count)
|
||||
struct WoweeQuestGraph {
|
||||
enum QuestType : uint8_t {
|
||||
Normal = 0,
|
||||
Daily = 1,
|
||||
Repeatable = 2,
|
||||
Group = 3,
|
||||
Raid = 4,
|
||||
};
|
||||
|
||||
enum FactionAccess : uint8_t {
|
||||
Both = 0,
|
||||
Alliance = 1,
|
||||
Horde = 2,
|
||||
Neutral = 3,
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
uint32_t questId = 0;
|
||||
std::string name;
|
||||
uint8_t minLevel = 0;
|
||||
uint8_t maxLevel = 0;
|
||||
uint8_t questType = Normal;
|
||||
uint8_t factionAccess = Both;
|
||||
uint16_t classRestriction = 0;
|
||||
uint16_t raceRestriction = 0;
|
||||
uint32_t zoneId = 0;
|
||||
uint8_t chainHeadHint = 0;
|
||||
uint8_t pad0 = 0;
|
||||
uint16_t pad1 = 0;
|
||||
std::vector<uint32_t> prevQuestIds;
|
||||
std::vector<uint32_t> followupQuestIds;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<Entry> entries;
|
||||
|
||||
bool isValid() const { return !entries.empty(); }
|
||||
|
||||
const Entry* findById(uint32_t questId) const;
|
||||
|
||||
// Returns all quests that have the given questId
|
||||
// as a prereq (the "what unlocks once I finish
|
||||
// this" lookup — used by the journal UI's
|
||||
// "completing this opens" panel).
|
||||
std::vector<const Entry*> findUnlocksFrom(uint32_t questId) const;
|
||||
|
||||
// Returns all quests in a zone — used by the
|
||||
// zone-detail UI to populate the per-zone quest
|
||||
// list.
|
||||
std::vector<const Entry*> findByZone(uint32_t zoneId) const;
|
||||
};
|
||||
|
||||
class WoweeQuestGraphLoader {
|
||||
public:
|
||||
static bool save(const WoweeQuestGraph& cat,
|
||||
const std::string& basePath);
|
||||
static WoweeQuestGraph load(const std::string& basePath);
|
||||
static bool exists(const std::string& basePath);
|
||||
|
||||
// Preset emitters used by --gen-qgr* variants.
|
||||
//
|
||||
// makeStarterChain — 5-quest linear chain
|
||||
// (Northshire human starter
|
||||
// Q1->Q2->Q3->Q4->Q5).
|
||||
// Q1 has chainHeadHint=1.
|
||||
// Levels 1..5.
|
||||
// makeBranchedChain — 4-quest converging chain
|
||||
// (Q1 -> Q2a, Q1 -> Q2b,
|
||||
// both -> Q3). Demonstrates
|
||||
// DAG semantics not just
|
||||
// a linear list.
|
||||
// makeDailies — 3 standalone daily quests
|
||||
// (Daily type, no prereqs,
|
||||
// no follow-ups). Baseline
|
||||
// empty-deps path.
|
||||
static WoweeQuestGraph makeStarterChain(const std::string& catalogName);
|
||||
static WoweeQuestGraph makeBranchedChain(const std::string& catalogName);
|
||||
static WoweeQuestGraph makeDailies(const std::string& catalogName);
|
||||
};
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue