Commit graph

6 commits

Author SHA1 Message Date
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