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.
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.
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.
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.