Commit graph

10 commits

Author SHA1 Message Date
Kelsi
4868f780cc 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).
2026-05-09 15:37:59 -07:00
Kelsi
f8d7b6b6bd feat(pipeline): add WGOT (Wowee Game Object Template) format
Novel open replacement for AzerothCore-style
gameobject_template SQL tables PLUS the Blizzard
GameObjectDisplayInfo.dbc / GameObject types metadata. The
16th open format added to the editor.

Game objects are the non-creature interactable scenery:
chests (with loot), doors, buttons, mailboxes, herb / ore
gathering nodes, fishing pools, signposts, mounts. Each
has a displayId for the model, a typeId driving its
interaction logic, and optional cross-references to a lock
(future WLCK) and loot table (existing WLOT).

Cross-references with previously-added formats:
  WSPN.entry.entryId (kind=GameObject) -> WGOT.entry.objectId
  WGOT.entry.lootTableId               -> WLOT.entry.creatureId
                                          (loot tables are
                                           universal — chests
                                           and creatures both
                                           key by ID)

The dungeon preset's Bandit Strongbox uses lootTableId=2000
to match WLOT's bandit chest table id, so the demo content
stack already wires together: spawn (WSPN object kind 2000)
-> object template (WGOT 2000) -> loot table (WLOT 2000).

Format:
  • magic "WGOT", version 1, little-endian
  • per object: objectId / displayId / name / typeId /
    size / castBarCaption / requiredSkill +
    requiredSkillValue / lockId / lootTableId /
    minOpenTimeMs..maxOpenTimeMs / flags

Enums:
  • TypeId (16): Door / Button / Chest / Container /
    QuestGiver / Text / Trap / Goober / Transport /
    Mailbox / MineralNode / HerbNode / FishingNode /
    Mount / Sign / Bonfire
  • Flags: Disabled / ScriptOnly / UsableFromMount /
    Despawn / Frozen / QuestGated

API: WoweeGameObjectLoader::save / load / exists /
findById; presets makeStarter (chest + mailbox + sign),
makeDungeon (door + button + 2 chests + trap with proper
WLOT cross-references), makeGather (Peacebloom herb +
Tin Vein ore + fishing pool with skill requirements).

CLI added (5 flags, 507 documented total now):
  --gen-objects / --gen-objects-dungeon / --gen-objects-gather
  --info-wgot / --validate-wgot

Validator catches: objectId=0 + duplicates, size<=0,
minOpenTime>maxOpenTime, gathering node without skill
requirement (anyone can harvest — usually a typo), chest
without loot table (script must populate), requiredSkillValue
set without requiredSkill (incoherent).
2026-05-09 15:31:49 -07:00
Kelsi
02ae17740e feat(pipeline): add WQT (Wowee Quest Template) format
Novel open replacement for AzerothCore-style quest_template
SQL tables PLUS the Blizzard Quest.dbc / QuestObjective.dbc
trio. The 15th open format added to the editor — and the
last gameplay-graph piece the catalog needed.

Cross-references with previously-added formats:
  WQT.giverCreatureId    -> WCRT.entry.creatureId
  WQT.turninCreatureId   -> WCRT.entry.creatureId
  WQT.objective.targetId -> WCRT (kill) / WIT (collect) /
                             WOB (interact)
  WQT.rewardItem.itemId  -> WIT.entry.itemId
  WQT.prevQuestId        -> WQT.entry.questId (intra-format)
  WQT.nextQuestId        -> WQT.entry.questId

Together with WIT / WCRT / WLOT / WSPN / WOMX / WOL / WOW /
WSND, a content pack can now ship a complete RPG zone
(terrain + props + atmosphere + sounds + creatures + items
+ loot + spawns + quests) entirely in open formats with no
SQL or .dbc dependencies. 15 of 15 expected slots filled.

Format:
  • magic "WQTM", version 1, little-endian
  • per quest: questId / title / objective / description /
    minLevel..maxLevel + questLevel / requiredClass+RaceMask /
    prev+nextQuestId / giver+turninCreatureId /
    objectives[] / xpReward + moneyCopperReward /
    rewardItems[] / flags

Per-objective:
  kind (kill/collect/interact/visit/escort/cast),
  targetId, quantity

Per-reward:
  itemId, qty, pickFlags (AutoGiven / PlayerChoice)

Quest flags: Daily / Weekly / Raid / Group / AutoComplete /
              AutoAccept / Repeatable / ClassQuest / Pvp

API: WoweeQuestLoader::save / load / exists / findById;
presets makeStarter (1 simple kill quest, references the
bandit creatureId=1000), makeChain (3-quest chain with
prev/next links + AutoComplete bridge + player-choice
rewards), makeDaily (Daily+Repeatable+AutoAccept combo).

CLI added (5 flags, 500 documented total — round milestone):
  --gen-quests / --gen-quests-chain / --gen-quests-daily
  --info-wqt / --validate-wqt

Validator catches: questId=0+duplicates, level=0,
maxLevel<minLevel, empty title, no objectives without
AutoComplete (player can't finish), no rewards at all,
Daily without Repeatable (incoherent), targetId=0,
quantity=0, unknown objective kind, reward itemId=0 or qty=0.

The 3-quest chain demo exercises every major feature:
  • multiple objective kinds (visit / collect / kill)
  • prev/next chain links
  • AutoComplete dialogue-bridge quest
  • PlayerChoice reward (1 of 2 weapons)
2026-05-09 15:25:02 -07:00
Kelsi
b2b84139aa feat(pipeline): add WCRT (Wowee Creature Template) format
Novel open replacement for the AzerothCore-style
creature_template SQL table PLUS the Blizzard
CreatureTemplate / CreatureFamily / CreatureType.dbc trio.
The 14th open format added to the editor.

This is the canonical metadata side of creatures shared
across every spawn instance: HP, level range, faction,
behavior flags, NPC role bits (vendor / trainer /
quest-giver / innkeeper), base damage, equipped gear
references.

Cross-references with the previously-added formats:
  WSPN.entry.entryId    -> WCRT.entry.creatureId
  WLOT.entry.creatureId -> WCRT.entry.creatureId
  WCRT.entry.equipped*  -> WIT.entry.itemId

The 4-format set (WIT + WLOT + WSPN + WCRT) now lets a
content pack define a complete RPG zone's creature
ecosystem: what creatures are, where they spawn, what they
drop, and what gear they carry — entirely in open formats
with no SQL dependencies.

Format:
  • magic "WCRT", version 1, little-endian
  • per entry: creatureId / displayId / name / subname /
    minLevel..maxLevel / baseHealth + healthPerLevel /
    baseMana + manaPerLevel / factionId / npcFlags /
    typeId / familyId / damageMin..Max / attackSpeedMs /
    baseArmor / walkSpeed + runSpeed / gossipId /
    equippedMain + equippedOffhand + equippedRanged /
    aiFlags

Enums:
  • TypeId:   Beast / Dragon / Demon / Elemental / Giant /
              Undead / Humanoid / Critter / Mechanical
  • FamilyId: Wolf / Cat / Bear / Boar / Raptor / Hyena /
              Spider / Gorilla / Crab (for Beast types)
  • NpcFlags: Vendor / QuestGiver / Trainer / Banker /
              Innkeeper / FlightMaster / Auctioneer /
              Repair / Stable
  • Behavior: Passive / Aggressive / FleeLowHp / CallHelp /
              NoLeash

API: WoweeCreatureLoader::save / load / exists /
findById; presets makeStarter (1 innkeeper),
makeBandit (creatureId=1000 matches WSPN/WLOT bandit
references, equips WIT itemId=1001 sword), makeMerchants
(creatureIds 4001/4002/4003 match WSPN village labels).

CLI added (5 flags, 493 documented total):
  --gen-creatures / --gen-creatures-bandit / --gen-creatures-merchants
  --info-wcrt / --validate-wcrt

Validator catches: creatureId=0, duplicates, level=0,
minLevel>maxLevel, baseHealth=0, damageMin>damageMax,
attackSpeed=0, non-positive walk/runSpeed, behavior flag
contradictions (passive+aggressive), vendor with
aggressive behavior (player can't trade).
2026-05-09 15:18:44 -07:00
Kelsi
ff0aa1a3c8 feat(pipeline): add WLOT (Wowee Loot Table) format
Novel open replacement for AzerothCore-style
creature_loot_template / gameobject_loot_template SQL
tables. The 13th open format added to the editor.

Pairs naturally with the WIT item catalog from the
preceding commit: each loot drop's itemId references an
entry in a WIT file, so a content pack ships both the
item definitions and the loot tables that reference them.
The runtime composes WIT + WLOT + WSPN to drive the full
"creature dies, drops items" flow without any SQL.

Format:
  • magic "WLOT", version 1, little-endian
  • per table: creatureId / flags / dropCount /
    moneyMin..Max / itemDropCount + drops[]
  • per drop: itemId / chancePercent (float, 0..100) /
    minQty / maxQty / drop_flags

Table flags: QuestOnly, GroupOnly, Pickpocket
Drop flags:  QuestRequired, GroupRollOnly, AlwaysDrop

dropCount is the slot budget — how many distinct drops
to roll per kill. Each item drop is rolled independently
against its chancePercent (so dropCount=2 with 4 candidate
drops at varying chances gives the classic "up to 2 distinct
items per kill" behavior). Drops with the AlwaysDrop flag
bypass the slot budget — used for guaranteed quest items.

API: WoweeLootLoader::save / load / exists /
findByCreatureId; presets makeStarter (1 table, 1 drop),
makeBandit (4 candidates, dropCount=2, matches the camp
spawns from WSPN at creatureId=1000), makeBoss (6 candidates
including guaranteed quest item via AlwaysDrop and a
group-only epic at 5%).

CLI added (5 flags, 486 documented total now):
  --gen-loot / --gen-loot-bandit / --gen-loot-boss
  --info-wlot / --validate-wlot

Validator catches: creatureId=0, duplicates, chance not in
0..100, NaN chance, money min > max, minQty > maxQty,
dropCount=0 with non-empty drops list (silent dead config).

All 3 presets save / load / re-validate clean. The bandit
table's creatureId=1000 deliberately matches WSPN's
makeCamp creatureId so the open-format demo content pack
already has working cross-references.
2026-05-09 15:11:08 -07:00
Kelsi
9093975bdd feat(pipeline): add WIT (Wowee Item Template) format
Novel open replacement for Blizzard's Item.dbc +
ItemDisplayInfo.dbc + the SQL item_template tables that
AzerothCore-style servers store item definitions in. The
12th open format added to the editor.

A WIT file holds the catalog of all items in a content
pack: weapons, armor, consumables, quest items, trade
goods. Each entry pairs gameplay metadata (stats, level
reqs, flags, weapon damage / speed) with display metadata
(displayId for icon / model, quality color), so the
runtime can render inventory tooltips and equip slots
from a single load.

Format:
  • magic "WITM", version 1, little-endian
  • per item: itemId / displayId / quality / itemClass /
    itemSubClass / inventoryType / flags / requiredLevel /
    itemLevel / sellPrice / buyPrice / maxStack / durability
    / damageMin / damageMax / attackSpeedMs /
    statCount + stats[] / name / description

Enums:
  • Quality:       Poor..Heirloom (8 levels)
  • Class:         Consumable, Weapon, Armor, Quest, ... (13)
  • InventoryType: Head..Cloak..Weapon2H (18 slots)
  • Flags:        Unique, BoP, BoE, QuestItem, Conjured, ...
  • StatType:     Stamina, Strength, Intellect, Defense, ...

API: WoweeItemLoader::save / load / exists / findById;
presets makeStarter (4-item demo), makeWeapons (5 items
common -> legendary), makeArmor (6-piece mail set with
BoE flag).

CLI added (5 flags, 480 documented total now):
  --gen-items / --gen-items-weapons / --gen-items-armor
  --info-wit / --validate-wit

Validator catches: itemId=0, duplicate itemIds, weapons
with 0 damage or attackSpeed, weapons with non-weapon
slot, equippables with durability=0 or maxStack>1, sell
price >= buy price (vendor would lose money), out-of-range
quality.

All 3 presets save / load / re-validate clean. Info-table
output includes a gold/silver/copper price formatter for
hand-readability.
2026-05-09 15:04:48 -07:00
Kelsi
88d1e6229f feat(pipeline): add WSPN (Wowee Spawn Point catalog) format
Novel open replacement for AzerothCore-style scattered
creature_template / gameobject SQL spawn tables PLUS the
ADT MDDF / MODF doodad-placement chunks. The 11th open
format, and the first that covers the live world-content
side (atmosphere + sounds + spawns now form the runtime
"what fills this zone" picture).

A WSPN file holds all spawn points for a zone in a single
table, with kind discriminating creature vs game object
vs static doodad. The same format powers:
  • server runtime  — knows what NPCs / objects to spawn
  • editor          — draws spawn markers
  • renderer        — reads the doodad subset directly to
                       draw static props without going
                       through a server roundtrip

Format:
  • magic "WSPN", version 1, little-endian
  • per entry: kind / entryId / position(3f) / rotation(3f)
    / scale / flags / respawnSec / factionId /
    questIdRequired / wanderRadius / label

Flags packed: disabled (0x01), event-only (0x02),
quest-phased (0x04). Reserved bits for future per-entry
encoding extensions.

API: WoweeSpawnsLoader::save / load / exists; presets
makeStarter (1 each kind), makeCamp (4-bandit ring +
chest + 2 tents), makeVillage (6 NPCs + 2 signs + 4
corner trees).

CLI added (5 flags, 473 documented total now):
  --gen-spawns / --gen-spawns-camp / --gen-spawns-village
  --info-wspn / --validate-wspn

Validator catches: out-of-range kind, NaN/inf coords,
non-positive scale, doodad with non-zero respawn (static
prop misuse), creature with respawn=0 (won't respawn after
kill), entryId=0 (orphan reference).

All 3 presets save / load / re-validate clean. Doodad and
game-object entries explicitly set wanderRadius=0 so the
generated catalogs are noise-free.
2026-05-09 14:57:53 -07:00
Kelsi
36d63d8dd0 feat(pipeline): add WSND (Wowee Sound Catalog) format
Novel open replacement for Blizzard's SoundEntries.dbc +
SoundEntriesAdvanced.dbc. The 10th open format added to the
editor — covers the audio-metadata gap (the previous 9 cover
geometry, terrain, atmosphere, and world manifests, but no
sound metadata).

Format:
  • magic "WSND", version 1, little-endian
  • catalogName + entry count
  • per entry: soundId / kind / flags / volume /
    minDistance / maxDistance / filePath / label

Kind enum (7 categories):
  sfx, music, ambient, ui, voice, spell, combat

Flags packed (3 bits used, rest reserved):
  loop (0x01), 3d (0x02), stream (0x04)

API: WoweeSoundLoader::save / load / exists; presets
makeStarter (one entry per kind), makeAmbient (wilderness
loops + footsteps), makeTavern (fire + crowd + drink + door
+ lute).

CLI added (5 flags, 465 documented total now):
  --gen-sound-catalog <base> [name]
  --gen-sound-catalog-ambient <base> [name]
  --gen-sound-catalog-tavern <base> [name]
  --info-wsnd <base> [--json]
  --validate-wsnd <base> [--json]

Validator catches: out-of-range kind, NaN/inf volume or
distances, 3D sounds with bad min/max, duplicate sound IDs,
empty filePaths.

All 3 presets verified: save / load / validate clean
on first run. Variable-length string fields use length-
prefixed encoding with a 1 MiB sanity cap on read to
prevent corrupted-file allocation blowups.
2026-05-09 14:47:16 -07:00
Kelsi
db47f00657 feat(pipeline): add WOMX (Wowee World Map index) format
Novel open replacement for Blizzard's WDT (top-level world
definition table). The 9th open format added to the editor.

A WOMX file holds the manifest of which terrain tiles exist
within a world plus a tiny bit of map-level metadata. The
runtime consults it before attempting to load any individual
tile (so missing tiles produce a clean "no data" result
instead of a file-not-found error).

Format:
  • magic "WMPX", version 1, little-endian
  • mapName + worldType (continent/instance/battleground/arena)
  • gridSize 1..128 (typically 64 for continents)
  • defaultLightId / defaultWeatherId (atmosphere preset
    refs, 0 if none — wires into the WOL/WOW pair)
  • packed bitmap, 1 bit per tile, row-major
  • A 64x64 manifest is exactly 512 bytes of bitmap

API: WoweeWorldMapLoader::save / load / exists; presets
makeContinent (64x64 full), makeInstance (4x4 full),
makeArena (1x1 full).

CLI added (5 flags, 456 total now):
  --gen-world-map <base> [name]            (continent)
  --gen-world-map-instance <base> [name]   (4x4)
  --gen-world-map-arena <base> [name]      (1x1)
  --info-womx <base> [--json]
  --validate-womx <base> [--json]

Round-trip verified: continent + instance + arena presets
all save / load / re-validate to byte-identical state with
correct tile counts.
2026-05-09 14:38:05 -07:00
Kelsi
0ff13ccd67 refactor(editor): replace 60-handler chain with table-driven dispatch
Adds cli_dispatch.{hpp,cpp} containing a static table of every
extracted handler family's dispatch function. The table-walker
tryDispatchAll() iterates the table once per argv token, calling
each handler in turn. handleConvertSingle stays as a special-
case call in main.cpp because it threads dataPath through.

main.cpp shrinks from 486 to 236 lines (-250). Adding a new
handler module now requires touching only cli_dispatch.cpp's
include list + table — no main.cpp edits, no growing
if-else chain. The 60+ #include lines for individual cli_*
modules collapse to one #include for cli_dispatch.hpp.
2026-05-09 10:15:51 -07:00