mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-10 02:53:51 +00:00
feat(pipeline): add WFAC (Wowee Faction Catalog) format
Novel open replacement for Blizzard's Faction.dbc +
FactionTemplate.dbc + the AzerothCore-style
reputation_reward / reputation_spillover SQL tables. The
17th open format added to the editor.
Combines the "displayable Faction" (player-facing name +
reputation thresholds for friendly/honored/revered/exalted)
with the "FactionTemplate matrix" (which factions are
hostile to which) into one entry. The runtime walks the
catalog to answer two questions:
• "Will faction A attack faction B on sight?" -> enemy list
• "What rep tier is the player with X?" -> thresholds
Cross-references with previously-added formats:
WCRT.entry.factionId -> WFAC.entry.factionId
WFAC.entry.parentFactionId -> WFAC.entry.factionId
WFAC.entry.enemies[] -> WFAC.entry.factionId
WFAC.entry.friends[] -> WFAC.entry.factionId
The starter preset's factionId 35 (Friendly) and 14
(Hostile) deliberately match the WCRT preset defaults, so
the demo content stack is consistent: WCRT.makeBandit's
factionId=14 has a real entry in WFAC.makeStarter that
declares it hostile to friendly NPCs (35) and players (1).
Format:
• magic "WFAC", version 1, little-endian
• per faction: factionId / parentFactionId / name /
description / reputationFlags / baseReputation /
7 ascending tier thresholds (hostile..exalted) /
enemies[] / friends[]
Enums:
• ReputationFlags: VisibleOnTab / AtWarDefault / Hidden /
NoReputation / IsHeader (group label)
• Tier (canonical): Hated / Hostile / Unfriendly /
Neutral / Friendly / Honored /
Revered / Exalted
API: WoweeFactionLoader::save / load / exists / findById +
WoweeFaction::isHostile(a, b); presets makeStarter (3-faction
demo matching WCRT defaults), makeAlliance (header +
Stormwind / Darnassus / Ironforge with reciprocal friend
lists + Defias enemy), makeWildlife (4 beast factions, each
hostile to player but ignoring other beasts).
CLI added (5 flags, 514 documented total now):
--gen-factions / --gen-factions-alliance / --gen-factions-wildlife
--info-wfac / --validate-wfac
Validator catches: factionId=0 + duplicates, empty name,
threshold ordering violations (hostile must be < unfriendly
< neutral < ... < exalted), self-listed as enemy or friend,
faction in both enemies and friends (incoherent).
This commit is contained in:
parent
62e370545f
commit
4868f780cc
8 changed files with 700 additions and 0 deletions
130
include/pipeline/wowee_factions.hpp
Normal file
130
include/pipeline/wowee_factions.hpp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
// Wowee Open Faction Catalog (.wfac) — novel replacement for
|
||||
// Blizzard's Faction.dbc + FactionTemplate.dbc + the
|
||||
// AzerothCore-style reputation_reward / reputation_spillover
|
||||
// SQL tables. The 17th open format added to the editor.
|
||||
//
|
||||
// Combines the "displayable Faction" (player-facing name,
|
||||
// reputation thresholds for friendly/honored/revered/exalted)
|
||||
// with the "FactionTemplate matrix" (which factions are
|
||||
// hostile to which) into one entry. The runtime walks the
|
||||
// catalog to answer two questions:
|
||||
// • "Will faction A attack faction B on sight?" -> enemy list
|
||||
// • "What reputation tier is this player with X?" -> thresholds
|
||||
//
|
||||
// Cross-references:
|
||||
// WCRT.entry.factionId -> WFAC.entry.factionId
|
||||
// WFAC.entry.parentFactionId -> WFAC.entry.factionId
|
||||
// (intra-format hierarchy)
|
||||
// WFAC.entry.enemies[] -> WFAC.entry.factionId
|
||||
// WFAC.entry.friends[] -> WFAC.entry.factionId
|
||||
//
|
||||
// Binary layout (little-endian):
|
||||
// magic[4] = "WFAC"
|
||||
// version (uint32) = current 1
|
||||
// nameLen + name (catalog label)
|
||||
// entryCount (uint32)
|
||||
// entries (each):
|
||||
// factionId (uint32)
|
||||
// parentFactionId (uint32)
|
||||
// nameLen + name
|
||||
// descLen + description
|
||||
// reputationFlags (uint32)
|
||||
// baseReputation (int32)
|
||||
// thresholdHostile (int32)
|
||||
// thresholdUnfriendly (int32)
|
||||
// thresholdNeutral (int32)
|
||||
// thresholdFriendly (int32)
|
||||
// thresholdHonored (int32)
|
||||
// thresholdRevered (int32)
|
||||
// thresholdExalted (int32)
|
||||
// enemyCount (uint8) + pad[3] + enemies[] (factionId × N)
|
||||
// friendCount (uint8) + pad[3] + friends[] (factionId × N)
|
||||
struct WoweeFaction {
|
||||
enum ReputationFlags : uint32_t {
|
||||
VisibleOnTab = 0x01, // shows up in the player's reputation panel
|
||||
AtWarDefault = 0x02, // new players are at-war on first contact
|
||||
Hidden = 0x04, // never shown (internal reputation tracking)
|
||||
NoReputation = 0x08, // gives no reputation gains/losses
|
||||
IsHeader = 0x10, // grouping header (parent), not a faction itself
|
||||
};
|
||||
|
||||
// Canonical reputation tiers — clients use the threshold
|
||||
// values to decide which tier badge to display.
|
||||
enum Tier : int32_t {
|
||||
Hated = -42000,
|
||||
Hostile = -6000,
|
||||
Unfriendly = -3000,
|
||||
Neutral = 0,
|
||||
Friendly = 3000,
|
||||
Honored = 9000,
|
||||
Revered = 21000,
|
||||
Exalted = 42000,
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
uint32_t factionId = 0;
|
||||
uint32_t parentFactionId = 0;
|
||||
std::string name;
|
||||
std::string description;
|
||||
uint32_t reputationFlags = VisibleOnTab;
|
||||
int32_t baseReputation = 0;
|
||||
int32_t thresholdHostile = Hostile;
|
||||
int32_t thresholdUnfriendly = Unfriendly;
|
||||
int32_t thresholdNeutral = Neutral;
|
||||
int32_t thresholdFriendly = Friendly;
|
||||
int32_t thresholdHonored = Honored;
|
||||
int32_t thresholdRevered = Revered;
|
||||
int32_t thresholdExalted = Exalted;
|
||||
std::vector<uint32_t> enemies;
|
||||
std::vector<uint32_t> friends;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<Entry> entries;
|
||||
|
||||
bool isValid() const { return !entries.empty(); }
|
||||
|
||||
// Lookup by factionId — nullptr if not present.
|
||||
const Entry* findById(uint32_t factionId) const;
|
||||
|
||||
// True if A's enemies list contains B (hostile-on-sight).
|
||||
// Does NOT walk parent factions; use isAtWarTransitive
|
||||
// for that.
|
||||
bool isHostile(uint32_t aFactionId, uint32_t bFactionId) const;
|
||||
};
|
||||
|
||||
class WoweeFactionLoader {
|
||||
public:
|
||||
static bool save(const WoweeFaction& cat,
|
||||
const std::string& basePath);
|
||||
static WoweeFaction load(const std::string& basePath);
|
||||
static bool exists(const std::string& basePath);
|
||||
|
||||
// Preset emitters used by --gen-factions* variants.
|
||||
//
|
||||
// makeStarter — 3 factions: Friendly (35), Hostile (14),
|
||||
// PlayerHorde (1). Friendly is enemies of
|
||||
// Hostile, vice versa. Useful as a starter
|
||||
// template.
|
||||
// makeAlliance — Stormwind / Ironforge / Darnassus (with
|
||||
// reciprocal friend lists) + the canonical
|
||||
// Defias enemy.
|
||||
// makeWildlife — neutral wildlife factions: wolves, bears,
|
||||
// spiders, kobolds. Each hostile to players
|
||||
// but not to each other.
|
||||
static WoweeFaction makeStarter(const std::string& catalogName);
|
||||
static WoweeFaction makeAlliance(const std::string& catalogName);
|
||||
static WoweeFaction makeWildlife(const std::string& catalogName);
|
||||
};
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue