refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
# include "cli_help.hpp"
# include <cstdio>
namespace wowee {
namespace editor {
namespace cli {
void printUsage ( const char * argv0 ) {
std : : printf ( " Usage: %s --data <path> [options] \n \n " , argv0 ) ;
std : : printf ( " Options: \n " ) ;
std : : printf ( " --data <path> Path to extracted WoW data (manifest.json) \n " ) ;
std : : printf ( " --adt <map> <x> <y> Load an ADT tile on startup \n " ) ;
std : : printf ( " --convert-m2 <path> Convert M2 model to WOM open format (no GUI) \n " ) ;
std : : printf ( " --convert-m2-batch <srcDir> \n " ) ;
std : : printf ( " Bulk M2→WOM conversion across every .m2 in <srcDir> (per-file pass/fail summary) \n " ) ;
std : : printf ( " --convert-wmo <path> Convert WMO building to WOB open format (no GUI) \n " ) ;
std : : printf ( " --convert-wmo-batch <srcDir> \n " ) ;
std : : printf ( " Bulk WMO→WOB conversion across every .wmo in <srcDir> (skips _NNN group files) \n " ) ;
std : : printf ( " --convert-dbc-batch <srcDir> \n " ) ;
std : : printf ( " Bulk DBC→JSON conversion across every .dbc in <srcDir> (sidecars next to source) \n " ) ;
std : : printf ( " --migrate-data-tree <srcDir> \n " ) ;
std : : printf ( " Run all four bulk converters (m2/wmo/blp/dbc) end-to-end on an extracted Data tree \n " ) ;
std : : printf ( " --info-data-tree <srcDir> [--json] \n " ) ;
std : : printf ( " Per-format migration-progress report (m2 vs wom, wmo vs wob, blp vs png, dbc vs json) \n " ) ;
std : : printf ( " --strip-data-tree <srcDir> [--dry-run] \n " ) ;
std : : printf ( " Delete proprietary files (.m2/.wmo/.blp/.dbc) that already have an open sidecar \n " ) ;
std : : printf ( " --audit-data-tree <srcDir> \n " ) ;
std : : printf ( " CI gate: exit 1 if any proprietary file lacks an open sidecar (100%% migration check) \n " ) ;
std : : printf ( " --bench-migrate-data-tree <srcDir> [--json] \n " ) ;
std : : printf ( " Time each step of --migrate-data-tree (m2/wmo/blp/dbc) and report wall-clock per step \n " ) ;
std : : printf ( " --list-data-tree-largest <srcDir> [N] \n " ) ;
std : : printf ( " Top-N largest proprietary files (.m2/.wmo/.blp/.dbc) for migration prioritization \n " ) ;
std : : printf ( " --export-data-tree-md <srcDir> [out.md] \n " ) ;
std : : printf ( " Markdown migration-progress report (per-pair table, share %%, recommended next steps) \n " ) ;
std : : printf ( " --gen-texture <out.png> <colorHex|pattern> [W H] \n " ) ;
std : : printf ( " Synthesize a placeholder texture (solid hex color or 'checker'/'grid'); default 256x256 \n " ) ;
std : : printf ( " --gen-texture-gradient <out.png> <fromHex> <toHex> [vertical|horizontal] [W H] \n " ) ;
std : : printf ( " Synthesize a linear gradient PNG (default vertical, 256x256) \n " ) ;
std : : printf ( " --gen-texture-noise <out.png> [seed] [W H] \n " ) ;
std : : printf ( " Synthesize a smooth value-noise PNG (deterministic from seed; default 256x256) \n " ) ;
std : : printf ( " --gen-texture-noise-color <out.png> <colorAHex> <colorBHex> [seed] [W H] \n " ) ;
std : : printf ( " Same noise pattern but blended between two colors instead of grayscale \n " ) ;
std : : printf ( " --gen-texture-radial <out.png> <centerHex> <edgeHex> [W H] \n " ) ;
std : : printf ( " Synthesize a radial gradient PNG (center→edge, smooth distance-based blend) \n " ) ;
std : : printf ( " --gen-texture-stripes <out.png> <colorAHex> <colorBHex> [stripePx] [diagonal|horizontal|vertical] [W H] \n " ) ;
std : : printf ( " Synthesize a two-color stripe pattern (default 16px diagonal, 256x256) \n " ) ;
std : : printf ( " --gen-texture-dots <out.png> <bgHex> <dotHex> [dotRadius] [spacing] [W H] \n " ) ;
std : : printf ( " Synthesize a polka-dot pattern (default radius 8, spacing 32, 256x256) \n " ) ;
std : : printf ( " --gen-texture-rings <out.png> <colorAHex> <colorBHex> [ringPx] [W H] \n " ) ;
std : : printf ( " Synthesize concentric ring pattern (target/seal style; default 16px rings, 256x256) \n " ) ;
std : : printf ( " --gen-texture-checker <out.png> <colorAHex> <colorBHex> [cellPx] [W H] \n " ) ;
std : : printf ( " Synthesize checkerboard with custom colors (gen-texture's checker is BW only) \n " ) ;
std : : printf ( " --gen-texture-brick <out.png> <brickHex> <mortarHex> [brickW] [brickH] [mortarPx] [W H] \n " ) ;
std : : printf ( " Brick wall pattern with offset rows + mortar lines (default 64× 24, 4px mortar) \n " ) ;
std : : printf ( " --gen-texture-wood <out.png> <lightHex> <darkHex> [grainSpacing] [seed] [W H] \n " ) ;
std : : printf ( " Wood grain pattern with vertical streaks + knots (default spacing 12px, seed 1) \n " ) ;
std : : printf ( " --gen-texture-grass <out.png> <baseHex> <bladeHex> [density] [seed] [W H] \n " ) ;
std : : printf ( " Tiling grass texture with random blade highlights (default density=0.15, seed=1) \n " ) ;
std : : printf ( " --gen-texture-fabric <out.png> <warpHex> <weftHex> [threadPx] [W H] \n " ) ;
std : : printf ( " Woven fabric pattern with alternating warp/weft threads (default thread=4px) \n " ) ;
std : : printf ( " --gen-texture-cobble <out.png> <stoneHex> <mortarHex> [stonePx] [seed] [W H] \n " ) ;
std : : printf ( " Cobblestone street pattern: irregular packed stones (default stone=24px, seed 1) \n " ) ;
std : : printf ( " --gen-texture-marble <out.png> <baseHex> <veinHex> [seed] [veinSharpness] [W H] \n " ) ;
std : : printf ( " Marble pattern with sinusoidal veining (default seed 1, sharpness 8) \n " ) ;
std : : printf ( " --gen-texture-metal <out.png> <baseHex> [seed] [orientation] [W H] \n " ) ;
std : : printf ( " Brushed metal: directional anisotropic noise (orientation: horizontal|vertical) \n " ) ;
std : : printf ( " --gen-texture-leather <out.png> <baseHex> [seed] [grainSize] [W H] \n " ) ;
std : : printf ( " Leather grain: irregular pebbled bumps via cellular noise (default grain=4px) \n " ) ;
std : : printf ( " --gen-texture-sand <out.png> <baseHex> [seed] [rippleSpacing] [W H] \n " ) ;
std : : printf ( " Sand dunes: per-pixel grain noise + sinusoidal ripple bands (default ripple=24px) \n " ) ;
std : : printf ( " --gen-texture-snow <out.png> <baseHex> [seed] [sparkleDensity] [W H] \n " ) ;
std : : printf ( " Snow: soft cool-white base + scattered bright sparkle pixels (default density=0.005) \n " ) ;
2026-05-08 20:33:45 -07:00
std : : printf ( " --gen-texture-lava <out.png> <darkHex> <hotHex> [seed] [crackScale] [W H] \n " ) ;
std : : printf ( " Lava: dark cooled crust with bright glowing cracks via Worley cell boundaries \n " ) ;
2026-05-08 22:01:31 -07:00
std : : printf ( " --gen-texture-tile <out.png> <tileHex> <groutHex> [tilePx] [groutPx] [W H] \n " ) ;
std : : printf ( " Square stone tiles with grout grid (default 32px tiles, 2px grout) \n " ) ;
2026-05-08 23:15:03 -07:00
std : : printf ( " --gen-texture-bark <out.png> <baseHex> <crackHex> [seed] [crackDensity] [W H] \n " ) ;
std : : printf ( " Tree bark: vertical wavy streaks + dark vertical cracks (default density=0.04) \n " ) ;
2026-05-09 00:20:14 -07:00
std : : printf ( " --gen-texture-clouds <out.png> <skyHex> <cloudHex> [seed] [coverage] [W H] \n " ) ;
std : : printf ( " Sky with puffy clouds: multi-octave noise thresholded by coverage (default 0.5) \n " ) ;
2026-05-09 01:32:08 -07:00
std : : printf ( " --gen-texture-stars <out.png> <bgHex> <starHex> [seed] [density] [W H] \n " ) ;
std : : printf ( " Night sky with scattered stars (varied brightness, density 0..1, default 0.005) \n " ) ;
2026-05-09 02:37:06 -07:00
std : : printf ( " --gen-texture-vines <out.png> <wallHex> <vineHex> [seed] [vineCount] [W H] \n " ) ;
std : : printf ( " Wall with climbing vines: meandering vertical paths via random walk (default 8 vines) \n " ) ;
2026-05-09 03:23:01 -07:00
std : : printf ( " --gen-texture-mosaic <out.png> <colorAHex> <colorBHex> <colorCHex> [tilePx] [seed] [W H] \n " ) ;
std : : printf ( " 3-color mosaic: small square tiles with random color picks + grout (default 16px) \n " ) ;
2026-05-09 04:01:49 -07:00
std : : printf ( " --gen-texture-rust <out.png> <metalHex> <rustHex> [seed] [coverage] [W H] \n " ) ;
std : : printf ( " Metal with rust patches: noise blob threshold + per-pixel grain (default coverage=0.4) \n " ) ;
2026-05-09 04:42:31 -07:00
std : : printf ( " --gen-texture-circuit <out.png> <pcbHex> <traceHex> [seed] [traceCount] [W H] \n " ) ;
std : : printf ( " Sci-fi PCB pattern: orthogonal traces with right-angle turns + via dots (default 24 traces) \n " ) ;
2026-05-09 05:11:40 -07:00
std : : printf ( " --gen-texture-coral <out.png> <waterHex> <coralHex> [seed] [branchCount] [W H] \n " ) ;
std : : printf ( " Coral reef: branching tree shapes via random angle walks (default 12 branches) \n " ) ;
2026-05-09 05:38:18 -07:00
std : : printf ( " --gen-texture-flame <out.png> <darkHex> <hotHex> [seed] [W H] \n " ) ;
std : : printf ( " Flame: vertical color gradient from dark base to hot top with noise flicker \n " ) ;
2026-05-09 06:02:13 -07:00
std : : printf ( " --gen-texture-tartan <out.png> <colorAHex> <colorBHex> <colorCHex> [bandPx] [W H] \n " ) ;
std : : printf ( " Tartan plaid: 3-color crossing bands forming Scottish-style overlap pattern \n " ) ;
2026-05-09 06:29:16 -07:00
std : : printf ( " --gen-texture-argyle <out.png> <colorAHex> <colorBHex> <stitchHex> [cellPx] [W H] \n " ) ;
std : : printf ( " Argyle: 45-rotated lozenge checkerboard with diagonal stitch lines (sweater knit) \n " ) ;
2026-05-09 06:49:29 -07:00
std : : printf ( " --gen-texture-herringbone <out.png> <bgHex> <lineHex> [stripH] [lineSpacing] [lineWidth] [W H] \n " ) ;
std : : printf ( " Herringbone: slanted parallel lines that flip direction every strip (chevron / fish-bone) \n " ) ;
2026-05-09 07:06:29 -07:00
std : : printf ( " --gen-texture-scales <out.png> <bgHex> <scaleHex> <rimHex> [cellW] [cellH] [W H] \n " ) ;
std : : printf ( " Scales: half-row-staggered overlapping circles forming fish/dragon/chain-mail look \n " ) ;
2026-05-09 07:19:02 -07:00
std : : printf ( " --gen-texture-stained-glass <out.png> <leadHex> <colorAHex> <colorBHex> <colorCHex> [cells] [W H] \n " ) ;
std : : printf ( " Stained glass: Voronoi cells in 3-color rotation, separated by dark lead lines \n " ) ;
2026-05-09 07:30:50 -07:00
std : : printf ( " --gen-texture-shingles <out.png> <baseHex> <shadowHex> <seamHex> [shingleW] [shingleH] [shadowH] [W H] \n " ) ;
std : : printf ( " Roof shingles: half-offset rows of rectangular tiles with shadow band + vertical seams \n " ) ;
2026-05-09 07:41:17 -07:00
std : : printf ( " --gen-texture-frost <out.png> <bgHex> <iceHex> [seeds] [rayLen] [W H] \n " ) ;
std : : printf ( " Frost: scattered crystal nuclei with 6-spike rosettes that fade with distance \n " ) ;
2026-05-09 07:52:29 -07:00
std : : printf ( " --gen-texture-parquet <out.png> <woodAHex> <woodBHex> <gapHex> [cellSize] [gapW] [W H] \n " ) ;
std : : printf ( " Parquet: basket-weave wood floor pattern with checkered horizontal/vertical plank pairs \n " ) ;
2026-05-09 08:03:54 -07:00
std : : printf ( " --gen-texture-bubbles <out.png> <bgHex> <fillHex> <rimHex> [count] [minR] [maxR] [rimW] [W H] \n " ) ;
std : : printf ( " Bubbles: scattered overlapping circles with bright rims (foam, water, magic) \n " ) ;
2026-05-09 08:14:04 -07:00
std : : printf ( " --gen-texture-spider-web <out.png> <bgHex> <webHex> [spokes] [rings] [W H] \n " ) ;
std : : printf ( " Spider web: N radial spokes + M concentric polygonal rings centered on the image \n " ) ;
2026-05-09 08:24:12 -07:00
std : : printf ( " --gen-texture-gingham <out.png> <bgHex> <stripeHex> <crossHex> [spacing] [width] [W H] \n " ) ;
std : : printf ( " Gingham: 3-tone fabric — bg + perpendicular stripes + darker color where they cross \n " ) ;
2026-05-09 08:40:14 -07:00
std : : printf ( " --gen-texture-lattice <out.png> <bgHex> <lineHex> [spacing] [width] [W H] \n " ) ;
std : : printf ( " Lattice: ±45° diagonal grid forming diamond openings (garden trellis / mesh fence) \n " ) ;
2026-05-09 08:49:51 -07:00
std : : printf ( " --gen-texture-honeycomb <out.png> <fillHex> <borderHex> [hexSide] [W H] \n " ) ;
std : : printf ( " Honeycomb: hexagonal cells via Voronoi over a triangular seed lattice \n " ) ;
2026-05-09 09:06:56 -07:00
std : : printf ( " --gen-texture-cracked <out.png> <bgHex> <crackHex> [seeds] [maxLength] [W H] \n " ) ;
std : : printf ( " Cracked: branching random walks form fissures (mud / glass / dry earth) \n " ) ;
2026-05-09 09:42:10 -07:00
std : : printf ( " --gen-texture-runes <out.png> <bgHex> <runeHex> [gridSpacing] [W H] \n " ) ;
std : : printf ( " Runes: scattered angular glyphs of 3-5 strokes each (8 cardinal/diagonal angles) \n " ) ;
2026-05-09 09:51:58 -07:00
std : : printf ( " --gen-texture-leopard <out.png> <bgHex> <spotHex> [count] [radius] [W H] \n " ) ;
std : : printf ( " Leopard: irregular spots (4 sub-circles each) for animal-print fabric/fur \n " ) ;
2026-05-09 10:03:27 -07:00
std : : printf ( " --gen-texture-zebra <out.png> <bgHex> <stripeHex> [period] [amplitude] [wavelength] [W H] \n " ) ;
std : : printf ( " Zebra: wavy parallel stripes via sinusoidal y-shift (animal-print stripes) \n " ) ;
2026-05-09 10:18:22 -07:00
std : : printf ( " --gen-texture-knit <out.png> <bgHex> <stitchHex> [cellW] [cellH] [strokeW] [W H] \n " ) ;
std : : printf ( " Knit: V-stitch chevron-zigzag pattern reading as knitted fabric stitches \n " ) ;
2026-05-09 10:34:02 -07:00
std : : printf ( " --gen-texture-chainmail <out.png> <bgHex> <ringHex> [cellW] [cellH] [ringR] [strokeW] [W H] \n " ) ;
std : : printf ( " Chainmail: brick-offset ring outlines for armor/mail textures (interlocking metal rings) \n " ) ;
2026-05-09 10:44:13 -07:00
std : : printf ( " --gen-texture-planks <out.png> <bgHex> <seamHex> [plankH] [grains/plank] [seed] [W H] \n " ) ;
std : : printf ( " Planks: horizontal floor boards with per-plank tint, grain streaks, and stagger seams \n " ) ;
2026-05-09 10:50:46 -07:00
std : : printf ( " --gen-texture-corrugated <out.png> <bgHex> <hiHex> [period] [v|h] [W H] \n " ) ;
std : : printf ( " Corrugated: smooth cosine ridges between bg and hi (sheet-metal roofing / siding) \n " ) ;
2026-05-09 11:03:33 -07:00
std : : printf ( " --gen-texture-rope <out.png> <bgHex> <ropeHex> [period] [strandW] [W H] \n " ) ;
std : : printf ( " Rope: two interleaved sinusoidal strands with cylindrical highlight (twisted cordage) \n " ) ;
2026-05-09 11:12:28 -07:00
std : : printf ( " --gen-texture-caustics <out.png> <bgHex> <hiHex> [period] [W H] \n " ) ;
std : : printf ( " Caustics: 4 superimposed sine waves (x/y/x+y/x-y) producing diamond-mesh water shimmer \n " ) ;
2026-05-09 11:20:31 -07:00
std : : printf ( " --gen-texture-starburst <out.png> <bgHex> <rayHex> [rays] [beamWidth] [W H] \n " ) ;
std : : printf ( " Starburst: N rays radiating from center with linear falloff (sun / holy symbol / mosaic hub) \n " ) ;
2026-05-09 11:31:27 -07:00
std : : printf ( " --gen-texture-studs <out.png> <bgHex> <studHex> [stride] [studR] [W H] \n " ) ;
std : : printf ( " Studs: rivet grid with derived inner highlight (3D rivet/stud appearance for armor + leather) \n " ) ;
2026-05-09 11:38:03 -07:00
std : : printf ( " --gen-texture-moss <out.png> <bgHex> <mossHex> [stride] [density 0-100] [seed] [W H] \n " ) ;
std : : printf ( " Moss: irregular spots scattered on a hash-jittered grid (forest floor / weathered stone / swamp) \n " ) ;
2026-05-09 11:44:33 -07:00
std : : printf ( " --gen-texture-woodgrain <out.png> <lightHex> <darkHex> [spacing] [seed] [W H] \n " ) ;
std : : printf ( " Woodgrain: concentric annual rings centered off-image with per-ring jitter (end-cut wood) \n " ) ;
2026-05-09 11:49:20 -07:00
std : : printf ( " --gen-texture-carbon <out.png> <bgHex> <fiberHex> [cellSize] [W H] \n " ) ;
std : : printf ( " Carbon-fiber: 2x2 alternating-orientation weave with sin² fiber highlights (sci-fi/tech panels) \n " ) ;
2026-05-09 11:56:01 -07:00
std : : printf ( " --gen-texture-pinstripe <out.png> <bgHex> <lineHex> [stride] [lineW] [featureEvery] [W H] \n " ) ;
std : : printf ( " Pinstripe: thin vertical lines at every stride; every Nth stripe is doubled-thick feature line \n " ) ;
2026-05-09 12:01:11 -07:00
std : : printf ( " --gen-texture-camo <out.png> <aHex> <bHex> [cellSize] [threshold] [seed] [W H] \n " ) ;
std : : printf ( " Camouflage: 2-octave value noise thresholded into hard bg/fg blobs (woodland disruption pattern) \n " ) ;
2026-05-09 12:08:11 -07:00
std : : printf ( " --gen-texture-snake-skin <out.png> <bgHex> <scaleHex> [cellW] [cellH] [outlineW] [W H] \n " ) ;
std : : printf ( " Snake skin: brick-offset diamond scales (L1 metric) with derived dark outline (reptile / dragon hide) \n " ) ;
2026-05-09 12:14:10 -07:00
std : : printf ( " --gen-texture-mesh-screen <out.png> <bgHex> <wireHex> [stride] [wireW] [W H] \n " ) ;
std : : printf ( " Mesh-screen: orthogonal H+V wire grid (window screen / chain-link / sci-fi grille) \n " ) ;
2026-05-09 12:20:11 -07:00
std : : printf ( " --gen-texture-bamboo <out.png> <bgHex> <bambooHex> [stalkW] [nodeY] [nodeBand] [seed] [W H] \n " ) ;
std : : printf ( " Bamboo: vertical stalks with sin² shading + horizontal node bands (jungle / asian-themed) \n " ) ;
2026-05-09 12:27:15 -07:00
std : : printf ( " --gen-texture-blueprint <out.png> <bgHex> <lineHex> [minorStride] [majorEvery] [minorW] [majorW] [W H] \n " ) ;
std : : printf ( " Blueprint: minor + major grid lines (technical drawing / drafting paper / engineer's table) \n " ) ;
2026-05-09 12:33:25 -07:00
std : : printf ( " --gen-texture-rust-streaks <out.png> <bgHex> <rustHex> [streakCount] [seed] [W H] \n " ) ;
std : : printf ( " Rust streaks: vertical drip bands fading down from hash-jittered tops (weathered metal / hull stains) \n " ) ;
2026-05-09 12:39:38 -07:00
std : : printf ( " --gen-texture-plaid <out.png> <bgHex> <bandHex> [stride] [bandW] [W H] \n " ) ;
std : : printf ( " Plaid: 2 sets of crossed translucent bands; intersections darken via combined half-alpha \n " ) ;
2026-05-09 12:47:28 -07:00
std : : printf ( " --gen-texture-diamond-grid <out.png> <bgHex> <fillHex> [cellW] [cellH] [fillFrac] [W H] \n " ) ;
std : : printf ( " Diamond grid: axis-aligned solid diamonds in cells with bg gaps (clean tile / mosaic / floor inlay) \n " ) ;
2026-05-09 12:52:31 -07:00
std : : printf ( " --gen-texture-houndstooth <out.png> <toothHex> <bgHex> [cellSize] [W H] \n " ) ;
std : : printf ( " Houndstooth: classic textile broken-check pattern via seamless 8x8 motif (Scottish weave) \n " ) ;
2026-05-09 12:57:47 -07:00
std : : printf ( " --gen-texture-chevron <out.png> <bgHex> <lineHex> [period] [stride] [lineW] [W H] \n " ) ;
std : : printf ( " Chevron: stack of V-shape stripes with sharp seams (military / sportswear / heraldic banners) \n " ) ;
2026-05-09 13:03:00 -07:00
std : : printf ( " --gen-texture-dunes <out.png> <bgHex> <lineHex> [verticalSpacing] [period] [amp] [lineW] [W H] \n " ) ;
std : : printf ( " Dunes: stack of parallel sinusoidal curves (desert ground / shallow-water sand / wave ripples) \n " ) ;
2026-05-09 13:08:07 -07:00
std : : printf ( " --gen-texture-swirl <out.png> <bgHex> <armHex> [armCount] [spiralFactor] [armWidth] [W H] \n " ) ;
std : : printf ( " Swirl: N-arm logarithmic spiral (magic sigils / summoning circles / ritual floor markings) \n " ) ;
2026-05-09 13:14:18 -07:00
std : : printf ( " --gen-texture-ironbark <out.png> <baseHex> <crackHex> [streakSpacing] [plateY] [crackW] [seed] [W H] \n " ) ;
std : : printf ( " Ironbark: vertical wood streaks + horizontal plate bands (mature hardwood / sycamore / ironwood) \n " ) ;
2026-05-09 13:19:30 -07:00
std : : printf ( " --gen-texture-mold <out.png> <bgHex> <moldHex> [stride] [thresholdFrac] [seed] [W H] \n " ) ;
std : : printf ( " Mold: Worley-noise field patches (cellars / dungeon walls / sewer overflow / fungal growth) \n " ) ;
2026-05-09 13:25:41 -07:00
std : : printf ( " --gen-texture-embroidery <out.png> <bgHex> <threadHex> [cellSize] [strokeW] [W H] \n " ) ;
std : : printf ( " Embroidery: grid of cross-stitch X marks (counted-thread textile / sampler / folk-art trim) \n " ) ;
2026-05-09 13:30:57 -07:00
std : : printf ( " --gen-texture-lightbeam <out.png> <bgHex> <beamHex> [beamHalfW] [vFadeFrac] [u|d] [W H] \n " ) ;
std : : printf ( " Lightbeam: vertical sun-ray gradient fading horizontally + vertically (sunbeam / holy radiance) \n " ) ;
feat(editor): add --gen-texture-dewdrops scattered-droplets
75th procedural texture: N small water droplets at hash-
derived (cx, cy, R) positions blended onto bg via radial
brightness — bright at the drop center fading to bg at its
edge. Where drops overlap they accumulate brighter
(max-of-individual-contributions, not additive — so the
result stays inside the [bg, drop] color range).
Each drop gets a hash-derived radius in the [maxR/4, maxR]
range so the surface has a natural mix of small and large
droplets. Two-pass (compute brightness map, then write
pixels) so overlap accumulation works correctly.
Useful for morning-grass blades, wet-glass overlays, leaf
surfaces after rain, magic-pool fizz, snake-fountain
splash zones, dragon-breath-aftermath ground.
2026-05-09 13:36:39 -07:00
std : : printf ( " --gen-texture-dewdrops <out.png> <bgHex> <dropHex> [dropCount] [maxR] [seed] [W H] \n " ) ;
std : : printf ( " Dewdrops: scattered translucent water drops with radial brightness (grass / glass / leaf surfaces) \n " ) ;
2026-05-09 13:41:40 -07:00
std : : printf ( " --gen-texture-pinwheel <out.png> <aHex> <bHex> [sectors] [W H] \n " ) ;
std : : printf ( " Pinwheel: alternating colored triangular wedges radiating from center (mandala / wind-rose / wheel inlay) \n " ) ;
2026-05-09 13:46:11 -07:00
std : : printf ( " --gen-texture-scratched-metal <out.png> <baseHex> <scratchHex> [scratchCount] [maxLen] [seed] [W H] \n " ) ;
std : : printf ( " Scratched metal: base color overlaid with N angled hash-derived line segments (worn armor / blades) \n " ) ;
2026-05-09 13:56:41 -07:00
std : : printf ( " --gen-texture-crackle <out.png> <baseHex> <crackHex> [stride] [crackW] [seed] [W H] \n " ) ;
std : : printf ( " Crackle: fine Voronoi cell-boundary cracks (dried mud / parched earth / aged leather) \n " ) ;
2026-05-09 14:03:07 -07:00
std : : printf ( " --gen-texture-star <out.png> <bgHex> <starHex> [points] [innerFrac] [W H] \n " ) ;
std : : printf ( " Star: solid N-pointed star polygon centered (medallions / shields / religious symbols) \n " ) ;
2026-05-09 14:12:04 -07:00
std : : printf ( " --gen-texture-halftone <out.png> <bgHex> <dotHex> [stride] [maxR] [v|h|r] [W H] \n " ) ;
std : : printf ( " Halftone: grid of dots whose radii grow with a v/h/r gradient (comic / newspaper print look) \n " ) ;
2026-05-09 14:20:02 -07:00
std : : printf ( " --gen-texture-bayer <out.png> <aHex> <bHex> [cellSize] [W H] \n " ) ;
std : : printf ( " Bayer: 4x4 ordered-dither matrix tiled (retro / 8-bit / monochrome-CRT effects) \n " ) ;
2026-05-09 14:26:57 -07:00
std : : printf ( " --gen-texture-moon <out.png> <bgHex> <moonHex> [moonR] [phase] [W H] \n " ) ;
std : : printf ( " Moon disc with optional crescent shadow (phase 0=full, =moonR=half, >moonR=crescent) \n " ) ;
2026-05-09 14:42:23 -07:00
std : : printf ( " --gen-texture-damask <out.png> <bgHex> <fgHex> [cell] [W H] \n " ) ;
std : : printf ( " Damask: 4-petal floral motif tiled per cell (palace wallpaper / noble-faction tapestry) \n " ) ;
feat(editor): add --gen-texture-snowflake 6-fold ice crystal
84th procedural texture: 6-fold symmetric snowflake stamp
tiled per cell. Built by computing polar (r, theta) from
the cell center and folding theta into a [0, pi/6] wedge,
so a single arm-shape definition replicates 12 times via
mirror + 60-degree rotation.
Each arm is a thin sliver (sin-based perpendicular distance
test) thickened at two perpendicular knobs at r = 0.40 and
0.70 of the cell-half radius — the knobs provide the
classic "branched ice crystal" silhouette without needing
a separate per-arm subdivision pass.
A small filled center dot anchors the motif at small cell
sizes where the knobs vanish.
Useful for: arctic / winter zones, frost spell effects,
frost-mage themed gear icons, holiday-event decoration,
crystal-shrine backdrops, snowstorm overlays.
Distinct from --gen-texture-snow (random tiny dots, not a
patterned crystal) and --gen-texture-frost (spider-web
crackle, not radial). The first 6-fold-symmetric texture in
the catalogue.
2026-05-09 15:06:32 -07:00
std : : printf ( " --gen-texture-snowflake <out.png> <bgHex> <fgHex> [cell] [W H] \n " ) ;
std : : printf ( " Snowflake: 6-fold symmetric ice crystal stamped per cell (winter zones / frost spell effects) \n " ) ;
2026-05-09 17:09:32 -07:00
std : : printf ( " --gen-texture-gear-cog <out.png> <bgHex> <fgHex> [cell] [teeth] [W H] \n " ) ;
std : : printf ( " Gear cog: mechanical wheel with N alternating teeth + center axle hole (engineering / clockwork themes) \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " --add-texture-to-zone <zoneDir> <png-path> [renameTo] \n " ) ;
std : : printf ( " Copy an existing PNG into <zoneDir> (optionally renaming it on the way in) \n " ) ;
std : : printf ( " --gen-mesh <wom-base> <cube|plane|sphere|cylinder|torus|cone|ramp> [size] \n " ) ;
std : : printf ( " Synthesize a procedural WOM primitive with proper normals, UVs, and bounds \n " ) ;
std : : printf ( " --gen-mesh-textured <wom-base> <cube|plane|sphere|cylinder|torus|cone|ramp> <colorHex|pattern> [size] \n " ) ;
std : : printf ( " Compose a procedural mesh + matching PNG texture wired into the WOM's batch \n " ) ;
std : : printf ( " --gen-mesh-stairs <wom-base> <steps> [stepHeight] [stepDepth] [width] \n " ) ;
std : : printf ( " Procedural straight staircase along +X with N steps (default 5 / 0.2 / 0.3 / 1.0) \n " ) ;
std : : printf ( " --gen-mesh-grid <wom-base> <subdivisions> [size] \n " ) ;
std : : printf ( " Subdivided flat plane on XY (NxN cells, 2N² triangles); useful for LOD demos \n " ) ;
std : : printf ( " --gen-mesh-disc <wom-base> [radius] [segments] \n " ) ;
std : : printf ( " Flat circular disc on XY centered at origin (default radius 1.0, 32 segments) \n " ) ;
std : : printf ( " --gen-mesh-tube <wom-base> [outerRadius] [innerRadius] [height] [segments] \n " ) ;
std : : printf ( " Hollow cylinder/pipe along Y axis (default 1.0/0.7/2.0, 24 segments) \n " ) ;
std : : printf ( " --gen-mesh-capsule <wom-base> [radius] [cylHeight] [segments] [stacks] \n " ) ;
std : : printf ( " Capsule along Y axis: cylinder body with hemispherical caps (default 0.5/1.0/16/8) \n " ) ;
std : : printf ( " --gen-mesh-arch <wom-base> [openingWidth] [openingHeight] [thickness] [depth] [segments] \n " ) ;
std : : printf ( " Doorway arch: two columns + semicircular top (default 1.0/1.5/0.2/0.3, 12 segs) \n " ) ;
std : : printf ( " --gen-mesh-pyramid <wom-base> [sides] [baseRadius] [height] \n " ) ;
std : : printf ( " N-sided polygonal pyramid with apex at +Y (default 4 sides, 1.0/1.0) \n " ) ;
std : : printf ( " --gen-mesh-fence <wom-base> [posts] [postSpacing] [postHeight] [railThick] \n " ) ;
std : : printf ( " Repeating fence: N posts along +X with two horizontal rails between \n " ) ;
std : : printf ( " --gen-mesh-tree <wom-base> [trunkRadius] [trunkHeight] [foliageRadius] \n " ) ;
std : : printf ( " --gen-mesh-rock <wom-base> [radius] [roughness] [subdiv] [seed] \n " ) ;
std : : printf ( " Procedural boulder via subdivided octahedron + smooth noise displacement \n " ) ;
std : : printf ( " --gen-mesh-pillar <wom-base> [radius] [height] [flutes] [capScale] \n " ) ;
std : : printf ( " Fluted classical column with concave flutes + flared cap/base (default 12 flutes) \n " ) ;
std : : printf ( " --gen-mesh-bridge <wom-base> [length] [width] [planks] [railHeight] \n " ) ;
std : : printf ( " Plank bridge with two side rails (default 6 planks across, rails on) \n " ) ;
std : : printf ( " --gen-mesh-tower <wom-base> [radius] [height] [battlements] [battlementH] \n " ) ;
std : : printf ( " Round castle tower with crenellated battlements (default 8 teeth, 0.5m tall) \n " ) ;
std : : printf ( " --gen-mesh-house <wom-base> [width] [depth] [height] [roofHeight] \n " ) ;
std : : printf ( " Simple house: cube body + pyramid roof (default 4× 4× 3 with 2m roof) \n " ) ;
std : : printf ( " --gen-mesh-fountain <wom-base> [basinRadius] [basinHeight] [spoutRadius] [spoutHeight] \n " ) ;
std : : printf ( " Round basin + center spout column (default 1.5/0.5 basin, 0.2/1.5 spout) \n " ) ;
std : : printf ( " --gen-mesh-statue <wom-base> [pedestalSize] [bodyHeight] [headRadius] \n " ) ;
std : : printf ( " Humanoid placeholder: pedestal block + tall body cylinder + head sphere \n " ) ;
std : : printf ( " --gen-mesh-altar <wom-base> [topRadius] [topHeight] [steps] [stepStride] \n " ) ;
std : : printf ( " Round altar: stacked stepped discs descending from a flat top (default 3 steps) \n " ) ;
std : : printf ( " --gen-mesh-portal <wom-base> [width] [height] [postThickness] [lintelHeight] \n " ) ;
std : : printf ( " Doorway frame: two side posts + top lintel (default 2.5w × 4h) \n " ) ;
std : : printf ( " --gen-mesh-archway <wom-base> [width] [pillarHeight] [thickness] [archSegs] \n " ) ;
std : : printf ( " Semicircular arched doorway: two pillars + curved keystone vault (default 12 segs) \n " ) ;
std : : printf ( " --gen-mesh-barrel <wom-base> [topRadius] [midRadius] [height] [hoopThickness] \n " ) ;
std : : printf ( " Tapered barrel: bulges in middle + 2 rim hoops (default 0.4/0.5/1.0/0.06) \n " ) ;
2026-05-08 21:19:51 -07:00
std : : printf ( " --gen-mesh-chest <wom-base> [width] [depth] [bodyHeight] [lidHeight] \n " ) ;
std : : printf ( " Treasure chest: body box + lid box + 3 iron bands + lock plate (default 1.4× 0.9× 0.9) \n " ) ;
2026-05-08 22:37:47 -07:00
std : : printf ( " --gen-mesh-anvil <wom-base> [length] [width] [hornLength] [bodyHeight] \n " ) ;
std : : printf ( " Blacksmith anvil: stepped pedestal + flat work surface + horn taper (default 1.0× 0.4× 0.5× 0.5) \n " ) ;
2026-05-08 23:48:03 -07:00
std : : printf ( " --gen-mesh-mushroom <wom-base> [stalkRadius] [stalkHeight] [capRadius] \n " ) ;
std : : printf ( " Mushroom: cylindrical stalk + hemispherical cap (default 0.1/0.6/0.4) \n " ) ;
2026-05-09 00:52:13 -07:00
std : : printf ( " --gen-mesh-cart <wom-base> [bedLength] [bedWidth] [bedHeight] [wheelRadius] \n " ) ;
std : : printf ( " Wooden cart: rectangular bed + 2 cylindrical wheels (default 1.6/0.8/0.5/0.35) \n " ) ;
2026-05-09 02:10:23 -07:00
std : : printf ( " --gen-mesh-banner <wom-base> [poleHeight] [poleRadius] [flagWidth] [flagHeight] \n " ) ;
std : : printf ( " Banner: vertical pole + rectangular hanging flag (default 3.0/0.05/0.8/1.2) \n " ) ;
2026-05-09 03:00:19 -07:00
std : : printf ( " --gen-mesh-grave <wom-base> [tabletWidth] [tabletHeight] [tabletThickness] [baseWidth] \n " ) ;
std : : printf ( " Tombstone: low rectangular base + vertical tablet (default 0.6/1.0/0.15/0.8) \n " ) ;
2026-05-09 03:43:11 -07:00
std : : printf ( " --gen-mesh-bench <wom-base> [length] [seatHeight] [seatThickness] [seatWidth] \n " ) ;
std : : printf ( " Wooden bench: seat plank + 2 leg slabs (default 1.5/0.5/0.06/0.4) \n " ) ;
2026-05-09 04:25:52 -07:00
std : : printf ( " --gen-mesh-shrine <wom-base> [size] [pillarHeight] [pillarRadius] [roofThickness] \n " ) ;
std : : printf ( " Small canopy: square base + 4 corner pillars + flat roof slab (default 1.5/2/0.1/0.15) \n " ) ;
feat(editor): add --gen-mesh-totem stacked carved totem primitive
Stack of N square blocks with alternating widths: even-indexed
blocks (0, 2, 4...) get full base width, odd blocks (1, 3, 5...)
get 70% — gives the carved-segment look characteristic of
totem poles.
Defaults: baseW=0.5, 5 segments, segH=0.5. Useful for tribal
zones, druid groves, fairgrounds, primitive village markers.
Brings the procedural mesh primitive set to 35.
2026-05-09 04:57:33 -07:00
std : : printf ( " --gen-mesh-totem <wom-base> [width] [segments] [segmentHeight] \n " ) ;
std : : printf ( " Tribal totem: stack of N alternating-width carved blocks (default w=0.5, 5 segs, h=0.5) \n " ) ;
2026-05-09 05:25:39 -07:00
std : : printf ( " --gen-mesh-cage <wom-base> [width] [height] [barsPerSide] [barRadius] \n " ) ;
std : : printf ( " Cage: top/bottom frames + 4 corner posts + N bars per side (default 1.5× 2.0, 5 bars) \n " ) ;
2026-05-09 05:50:23 -07:00
std : : printf ( " --gen-mesh-throne <wom-base> [seatWidth] [seatHeight] [backHeight] [pedestalSize] \n " ) ;
std : : printf ( " Throne: pedestal + seat + backrest + 2 armrests (default 0.8/0.5/1.5/1.2) \n " ) ;
2026-05-09 06:18:42 -07:00
std : : printf ( " --gen-mesh-coffin <wom-base> [length] [width] [height] \n " ) ;
std : : printf ( " Hexagonal coffin: narrow head + wide shoulder + tapered foot prism (default 2.0/0.8/0.6) \n " ) ;
2026-05-09 06:39:39 -07:00
std : : printf ( " --gen-mesh-bookshelf <wom-base> [width] [height] [depth] [shelves] \n " ) ;
std : : printf ( " Bookshelf: 5-panel cabinet with N-1 shelves and rows of varied book boxes (default 1.5/2.0/0.4/4) \n " ) ;
2026-05-09 10:25:38 -07:00
std : : printf ( " --gen-mesh-tent <wom-base> [length] [width] [height] [doorH] [doorW] \n " ) ;
std : : printf ( " Tent: A-frame canvas tent — ridge along X, two sloped roof panels, two gables, door notch on +X (default 1.6/1.0/0.9/0.5/0.4) \n " ) ;
2026-05-09 10:37:37 -07:00
std : : printf ( " --gen-mesh-firepit <wom-base> [ringR] [stones] [stoneSize] [logLen] [logThick] \n " ) ;
std : : printf ( " Firepit: ring of N stone cubes around 2 crossed log boxes (default 0.5/8/0.10/0.45/0.05) \n " ) ;
2026-05-09 10:47:21 -07:00
std : : printf ( " --gen-mesh-woodpile <wom-base> [logR] [logLen] [sides] \n " ) ;
std : : printf ( " Woodpile: 6 cylindrical logs in a 3-2-1 pyramid stack along Z axis (default 0.10/0.80/12) \n " ) ;
2026-05-09 10:59:05 -07:00
std : : printf ( " --gen-mesh-canopy <wom-base> [width] [depth] [height] [postR] [panelT] [drape] \n " ) ;
std : : printf ( " Canopy: 4-post awning with flat top panel and optional drape lips (default 1.6/1.2/2.0/0.05/0.03/0.15) \n " ) ;
2026-05-09 11:08:39 -07:00
std : : printf ( " --gen-mesh-haystack <wom-base> [baseR] [height] [layers] [sides] \n " ) ;
std : : printf ( " Haystack: terraced stack of N frustums tapering to an apex point (default 0.6/0.9/3/12) \n " ) ;
2026-05-09 11:17:28 -07:00
std : : printf ( " --gen-mesh-dock <wom-base> [length] [width] [height] [pilings/side] [pilingW] [deckT] \n " ) ;
std : : printf ( " Dock: flat plank deck on N pairs of square pilings (default 3.0/1.0/0.6/3/0.10/0.10) \n " ) ;
2026-05-09 11:26:15 -07:00
std : : printf ( " --gen-mesh-pergola <wom-base> [length] [width] [height] [postR] [beamT] [crossbeams] \n " ) ;
std : : printf ( " Pergola: 4 corner posts + 2 perimeter beams + N cross beams (open lattice top, no panel) \n " ) ;
2026-05-09 11:34:24 -07:00
std : : printf ( " --gen-mesh-chimney <wom-base> [width] [depth] [height] [capH] [capExtra] \n " ) ;
std : : printf ( " Chimney: rectangular brick shaft topped by a slightly wider rain-cap (default 0.45/0.45/1.8/0.10/0.05) \n " ) ;
2026-05-09 11:39:33 -07:00
std : : printf ( " --gen-mesh-bedroll <wom-base> [length] [radius] [sides] [pillowSize] \n " ) ;
std : : printf ( " Bedroll: horizontal closed cylinder along Z axis with optional pillow box at +Z (camp set dressing) \n " ) ;
2026-05-09 11:46:05 -07:00
std : : printf ( " --gen-mesh-workbench <wom-base> [length] [depth] [height] [legR] [topT] [viseSize] [trayH] \n " ) ;
std : : printf ( " Workbench: 4-legged top slab with optional vise at +X end and back tool tray (blacksmith / crafter) \n " ) ;
2026-05-09 11:52:20 -07:00
std : : printf ( " --gen-mesh-crate-stack <wom-base> [crateSize] [columns] [rows] [layers] [gap] \n " ) ;
std : : printf ( " Crate stack: N× M× K cube grid with small gap between crates (warehouses, cargo holds, dockyards) \n " ) ;
2026-05-09 11:57:38 -07:00
std : : printf ( " --gen-mesh-watchpost <wom-base> [postH] [postW] [platformSize] [platformT] [railingH] [railingW] \n " ) ;
std : : printf ( " Watchpost: tall pole + square platform + 4 corner railing posts (sentry / scout outpost) \n " ) ;
2026-05-09 12:02:35 -07:00
std : : printf ( " --gen-mesh-water-trough <wom-base> [length] [width] [height] [wallT] \n " ) ;
std : : printf ( " Water trough: 4-walled rectangular basin with flat floor (stable / farm / tavern set dressing) \n " ) ;
2026-05-09 12:09:36 -07:00
std : : printf ( " --gen-mesh-training-dummy <wom-base> [baseH] [postW] [torsoSize] [armSpan] [armT] [headSize] \n " ) ;
std : : printf ( " Training dummy: post + cubic torso + cross-bar arms + optional head (sparring / drill yard) \n " ) ;
feat(editor): add --gen-mesh-hitching-post stable fixture
67th procedural mesh primitive. Standard town/stable
hitching post:
• two vertical posts separated by `span`
• horizontal cross-bar at upper-post height (length =
span - postW so it tucks INSIDE the post inner faces,
matching real fence joinery)
• optional decorative caps on each post — set capH=0
for a bare working-yard post
All axis-aligned boxes, exercises every shared helper
(stripExt, initWomDefaults, addFlatBox,
finalizeAsSingleBatch, saveWomOrError). Watertight under
weld (verified 90 manifold edges, 0 boundary, 0
non-manifold).
Useful for stables, taverns with mount parking, town
squares, frontier outposts, ranger camps, post-and-rail
fence segments.
2026-05-09 12:15:41 -07:00
std : : printf ( " --gen-mesh-hitching-post <wom-base> [span] [height] [postW] [barT] [capH] \n " ) ;
std : : printf ( " Hitching post: 2 vertical posts + horizontal cross-bar + optional decorative caps (stable / town square) \n " ) ;
2026-05-09 12:24:00 -07:00
std : : printf ( " --gen-mesh-outhouse <wom-base> [width] [depth] [height] [doorH] [doorW] [roofOverhang] [roofT] \n " ) ;
std : : printf ( " Outhouse: solid body + inset door slab on +Z + overhanging roof slab (privy / tool shed) \n " ) ;
2026-05-09 12:29:09 -07:00
std : : printf ( " --gen-mesh-forge <wom-base> [width] [depth] [baseH] [hoodH] [hoodInset] [chimneyH] [chimneyW] \n " ) ;
std : : printf ( " Blacksmith forge: stone hearth + smaller hood + optional chimney (smithy / armorer set dressing) \n " ) ;
2026-05-09 12:35:15 -07:00
std : : printf ( " --gen-mesh-archery-target <wom-base> [faceR] [faceT] [sides] [postH] [postW] [beamT] \n " ) ;
std : : printf ( " Archery target: round face cylinder on a 2-post stand with cross-beam (training yard / fair scene) \n " ) ;
feat(editor): add --gen-mesh-gravel-pile rubble heap
71st procedural mesh primitive. Hash-distributed pile of
stone cubes in a roughly conical heap. Each stone gets:
• polar position (radial, theta) with sqrt(rand) on radial
so stones aren't bunched at center
• height limited by yMax = pileH * (1 - radial/baseR), so
larger / more numerous stones land near the base and
smaller ones perch on top — natural gravel-pile profile
• size in the 40-100% range of maxStoneSize
The second multi-box "scene" composite primitive (after
--gen-mesh-crate-stack), but using irregular hashed
placement instead of a regular N×M×K grid. Deterministic
from seed: re-running with same args reproduces the
identical pile.
Useful for mine entrances, construction sites, quarries,
ruined walls, abandoned-fort rubble, pirate-cove stash
mounds. Default 24 stones at 0.6 m base radius gives a
reasonable medium-pile.
Uses every shared helper introduced this batch (printWomWrote,
printWomMeshStats, setCenteredBoundsXZ, addFlatBox,
saveWomOrError, parseOpt*, stripExt).
2026-05-09 12:43:03 -07:00
std : : printf ( " --gen-mesh-gravel-pile <wom-base> [stoneCount] [baseR] [pileH] [maxStoneSize] [seed] \n " ) ;
std : : printf ( " Gravel pile: hash-distributed stone cubes in a conical heap (mining / construction / rubble) \n " ) ;
2026-05-09 12:48:55 -07:00
std : : printf ( " --gen-mesh-stone-bench <wom-base> [length] [depth] [seatH] [seatT] [supportW] [supportInset] \n " ) ;
std : : printf ( " Stone bench: long seat slab on 2 block supports near the ends (park / temple / ruined city) \n " ) ;
2026-05-09 12:54:17 -07:00
std : : printf ( " --gen-mesh-mine-cart <wom-base> [length] [width] [bodyH] [wallT] [wheelR] [wheelInset] \n " ) ;
std : : printf ( " Mine cart: open-top bin (5-piece basin) on 4 wheel boxes (mines / dwarven forges / junk yards) \n " ) ;
2026-05-09 12:59:16 -07:00
std : : printf ( " --gen-mesh-hitching-rail <wom-base> [length] [height] [posts] [postW] [barT] \n " ) ;
std : : printf ( " Hitching rail: long horizontal bar on N evenly-spaced posts (taverns / stockyards / market days) \n " ) ;
2026-05-09 13:04:55 -07:00
std : : printf ( " --gen-mesh-pillar-row <wom-base> [count] [span] [height] [pillarW] [capH] [capExtra] \n " ) ;
std : : printf ( " Pillar row: N evenly-spaced rectangular pillars with optional square caps (colonnade / temple ruin) \n " ) ;
2026-05-09 13:11:08 -07:00
std : : printf ( " --gen-mesh-statue-base <wom-base> [bodyW] [bodyH] [plinthExtra] [plinthH] [capitalExtra] [capitalH] \n " ) ;
std : : printf ( " Statue base: 3-tier pedestal (plinth + body + capital) for monuments / hero memorials \n " ) ;
2026-05-09 13:16:06 -07:00
std : : printf ( " --gen-mesh-bird-bath <wom-base> [stemR] [stemH] [basinR] [basinH] [sides] \n " ) ;
std : : printf ( " Bird bath: thin cylindrical stem topped by a wide shallow basin disc (small garden water feature) \n " ) ;
2026-05-09 13:21:03 -07:00
std : : printf ( " --gen-mesh-planter-box <wom-base> [length] [width] [height] [wallT] [soilTopFrac] \n " ) ;
std : : printf ( " Planter box: long open-top wood basin + visible soil-fill block (window sills / kitchen / balcony) \n " ) ;
feat(editor): add --gen-mesh-urn 4-tier pottery vessel
79th procedural mesh primitive. Vertical urn built from 4
stacked tiers using the new addClosedCylinderY helper:
• foot — wide short cylinder (the ground-meeting base)
• body — tall main cylinder (the storage volume)
• neck — narrow constriction
• lip — slightly wider rim cap
Each tier is an independent watertight Y-axis cylinder with
its own ±Y end caps; they're stacked vertically with each
sitting on the previous tier's top.
Useful for temple offerings, mausoleum interiors, kitchen
storage, alchemist labs, funerary scenes, witch-hut detail.
First handler to consume the new addClosedCylinderY helper —
demonstrates the pattern for future cylindrical primitives
(candle, lantern, scroll case, well-pail, etc.).
Watertight under weld (verified 432 manifold edges, 0
boundary, 0 non-manifold).
2026-05-09 13:27:06 -07:00
std : : printf ( " --gen-mesh-urn <wom-base> [bodyR] [bodyH] [footR] [footH] [neckR] [neckH] [lipR] [lipH] [sides] \n " ) ;
std : : printf ( " Urn: 4-tier vertical pottery vessel (foot + body + neck + lip) — temple / mausoleum / kitchen storage \n " ) ;
2026-05-09 13:32:43 -07:00
std : : printf ( " --gen-mesh-candle <wom-base> [waxR] [waxH] [saucerR] [saucerH] [sides] \n " ) ;
std : : printf ( " Candle: thin wax pillar on optional saucer base (set saucerR=0 to skip) — chapels / vigil scenes \n " ) ;
2026-05-09 13:38:06 -07:00
std : : printf ( " --gen-mesh-lantern <wom-base> [baseR] [baseH] [globeR] [globeH] [neckR] [neckH] [capR] [capH] [sides] \n " ) ;
std : : printf ( " Lantern: 4-tier base + glass-globe + neck + cap stack (hand lantern / oil lamp silhouette) \n " ) ;
2026-05-09 13:42:58 -07:00
std : : printf ( " --gen-mesh-chalice <wom-base> [footR] [footH] [stemR] [stemH] [bowlR] [bowlH] [sides] \n " ) ;
std : : printf ( " Chalice: ceremonial 3-tier foot + stem + bowl goblet (chapel / treasure / ritual scene) \n " ) ;
2026-05-09 13:47:37 -07:00
std : : printf ( " --gen-mesh-standing-torch <wom-base> [postR] [postH] [bowlR] [bowlH] [sides] \n " ) ;
std : : printf ( " Standing torch: tall thin post + wider fire-bowl on top (hall lining / dungeon entry / ceremony path) \n " ) ;
2026-05-09 13:58:22 -07:00
std : : printf ( " --gen-mesh-scroll-case <wom-base> [bodyR] [bodyH] [capR] [capH] [sides] \n " ) ;
std : : printf ( " Scroll case: thin tall cylinder + optional wider cap (set capR=0 to skip) — libraries / mage scenes \n " ) ;
2026-05-09 14:15:14 -07:00
std : : printf ( " --gen-mesh-stove <wom-base> [bodyR] [bodyH] [chimneyR] [chimneyH] [sides] \n " ) ;
std : : printf ( " Pot-bellied stove: round cylindrical body + thin chimney column on top (cottage / workshop heating) \n " ) ;
2026-05-09 14:23:23 -07:00
std : : printf ( " --gen-mesh-well-pail <wom-base> [bodyR] [bodyH] [handleW] [handleT] [handleArc] [sides] \n " ) ;
std : : printf ( " Wooden well-pail: closed cylindrical body + thin horizontal handle bar above (water-haul / mop-bucket prop) \n " ) ;
2026-05-09 14:30:18 -07:00
std : : printf ( " --gen-mesh-mug <wom-base> [bodyR] [bodyH] [handleW] [handleH] [handleArm] [sides] \n " ) ;
std : : printf ( " Drinking mug / tankard: closed cylinder body + side handle slab (tavern / banquet / inn dressing) \n " ) ;
2026-05-09 14:43:21 -07:00
std : : printf ( " --gen-mesh-mortar-pestle <wom-base> [bowlR] [bowlH] [pestleR] [pestleH] [sides] \n " ) ;
std : : printf ( " Mortar + pestle: wide squat cylinder (bowl) + thin tall cylinder rising from inside (alchemy / kitchen) \n " ) ;
2026-05-09 16:21:35 -07:00
std : : printf ( " --gen-mesh-rune-stone <wom-base> [baseW] [baseD] [baseH] [stoneW] [stoneD] [stoneH] \n " ) ;
std : : printf ( " Rune stone: wide flat base block + tall narrow monolith (druid grove / witch shrine / ancient ruins) \n " ) ;
2026-05-09 12:22:37 -07:00
std : : printf ( " --gen-camp-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit tent + firepit + bedroll + canopy + woodpile + haystack into outDir as 6 .wom files \n " ) ;
2026-05-09 12:31:34 -07:00
std : : printf ( " --gen-blacksmith-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit forge + anvil + workbench + water-trough + crate-stack + hitching-post into outDir \n " ) ;
2026-05-09 12:45:25 -07:00
std : : printf ( " --gen-village-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit house + outhouse + chimney + hitching-post + well + signpost + haystack into outDir \n " ) ;
2026-05-09 12:51:10 -07:00
std : : printf ( " --gen-temple-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit altar + shrine + brazier + pillar + statue + portal + podium into outDir \n " ) ;
2026-05-09 12:55:50 -07:00
std : : printf ( " --gen-graveyard-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit grave + tombstone + coffin + statue + stone-bench + gravel-pile + cage into outDir \n " ) ;
2026-05-09 13:01:21 -07:00
std : : printf ( " --gen-garden-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit pergola + fountain + stone-bench + shrine + beehive + scarecrow + well into outDir \n " ) ;
2026-05-09 13:06:37 -07:00
std : : printf ( " --gen-dock-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit dock + crate-stack + barrel + canopy + bench + signpost + hitching-post into outDir \n " ) ;
2026-05-09 13:17:49 -07:00
std : : printf ( " --gen-tavern-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit house + chimney + table + bench + barrel + bookshelf + signpost into outDir \n " ) ;
2026-05-09 13:40:18 -07:00
std : : printf ( " --gen-mining-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit gravel-pile + crate-stack + mine-cart + pillar-row + lantern + workbench + hitching-post \n " ) ;
2026-05-09 13:44:48 -07:00
std : : printf ( " --gen-arena-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit training-dummy + archery-target + workbench + crate-stack + bench + water-trough + hitching-rail \n " ) ;
feat(editor): add --gen-kitchen-pack composite (11th themed pack)
Tavern back-of-house / cookhouse scene composite. Pairs
naturally with --gen-tavern-pack (front-of-house common
room) for a complete inn setup.
Emits 7 .wom files into outDir:
• stove — pot-bellied cookfire stove
• cauldron — large hanging pot
• prep-table — flat work surface
• stool — cook's seat
• barrel — water / ale / flour storage
• mug — drink ready for the inn customer
• mortar — herb / spice grinding tool
This is the 11th themed pack (camp, blacksmith, village,
temple, graveyard, garden, dock, tavern, mining, arena,
kitchen). Notable for being the first pack that uses the
two recently-added drinking-vessel + alchemy primitives
(mug from batch 111, mortar-pestle from batch 113), proving
out the "build small primitives, then compose into themed
packs" workflow.
All 7 emitted primitives pass --validate-wom on first
generation. 468 kArgRequired entries total.
2026-05-09 14:53:01 -07:00
std : : printf ( " --gen-kitchen-pack <outDir> \n " ) ;
std : : printf ( " Convenience: emit stove + cauldron + prep-table + stool + barrel + mug + mortar (tavern back-of-house) \n " ) ;
2026-05-09 06:58:38 -07:00
std : : printf ( " --gen-mesh-table <wom-base> [width] [depth] [height] [legThick] [topThick] \n " ) ;
std : : printf ( " Table: flat top slab on 4 corner legs (default 1.6/1.0/0.85/0.10/0.06) \n " ) ;
2026-05-09 07:12:46 -07:00
std : : printf ( " --gen-mesh-lamppost <wom-base> [poleH] [poleT] [baseSize] [lanternSize] [lanternH] \n " ) ;
std : : printf ( " Lamppost: square base + tall pole + lantern body + cap (default 3.0/0.12/0.4/0.35/0.5) \n " ) ;
2026-05-09 07:25:11 -07:00
std : : printf ( " --gen-mesh-bed <wom-base> [length] [width] [legH] [matThick] [headH] [footH] \n " ) ;
std : : printf ( " Bed: 4 legs + mattress + headboard + footboard + pillow (default 2.0/1.2/0.30/0.20/1.0/0.4) \n " ) ;
2026-05-09 07:36:02 -07:00
std : : printf ( " --gen-mesh-ladder <wom-base> [height] [width] [rungs] [railThick] [rungThick] \n " ) ;
std : : printf ( " Ladder: 2 vertical rails + N evenly-spaced horizontal rungs (default 3.0/0.6/8/0.06/0.04) \n " ) ;
2026-05-09 07:47:15 -07:00
std : : printf ( " --gen-mesh-well <wom-base> [outerSize] [wallH] [wallT] [postH] [postT] \n " ) ;
std : : printf ( " Well: 4 stone walls in a hollow square + 2 roof posts + cross beam (default 1.4/0.8/0.15/1.6/0.12) \n " ) ;
2026-05-09 07:58:45 -07:00
std : : printf ( " --gen-mesh-signpost <wom-base> [poleH] [poleT] [baseSize] [signWidth] [signHeight] \n " ) ;
std : : printf ( " Signpost: base + pole + sign board + cap (default 2.5/0.10/0.30/0.80/0.35) \n " ) ;
2026-05-09 08:08:37 -07:00
std : : printf ( " --gen-mesh-mailbox <wom-base> [postH] [postT] [boxL] [boxW] [boxH] \n " ) ;
std : : printf ( " Mailbox: post + horizontal box + side flag (default 1.10/0.08/0.45/0.20/0.20) \n " ) ;
2026-05-09 08:19:04 -07:00
std : : printf ( " --gen-mesh-tombstone <wom-base> [width] [height] [depth] [baseScale] \n " ) ;
std : : printf ( " Tombstone: base plinth + tall slab + decorative crown (default 0.60/1.10/0.18/1.45) \n " ) ;
2026-05-09 08:28:53 -07:00
std : : printf ( " --gen-mesh-crate <wom-base> [size] [postRadius] \n " ) ;
std : : printf ( " Crate: cube body + 4 corner reinforcement posts (default 0.80/0.05) \n " ) ;
2026-05-09 08:44:51 -07:00
std : : printf ( " --gen-mesh-stool <wom-base> [seatSize] [seatThick] [legHeight] [legThick] \n " ) ;
std : : printf ( " Stool: small backless seat on 4 corner legs (default 0.36/0.04/0.45/0.04) \n " ) ;
2026-05-09 08:54:27 -07:00
std : : printf ( " --gen-mesh-cauldron <wom-base> [rimWidth] [bodyHeight] [legHeight] \n " ) ;
std : : printf ( " Cauldron: 4 legs + narrow bottom + wider mid + widest rim tiers (default 0.80/0.70/0.10) \n " ) ;
2026-05-09 09:02:04 -07:00
std : : printf ( " --gen-mesh-gate <wom-base> [openingWidth] [postHeight] [postT] [railT] \n " ) ;
std : : printf ( " Gate: 2 vertical posts + 3 horizontal rails (default 1.80/1.30/0.10/0.06) \n " ) ;
2026-05-09 09:11:36 -07:00
std : : printf ( " --gen-mesh-beehive <wom-base> [baseWidth] [height] [plateH] \n " ) ;
std : : printf ( " Beehive (skep): 4 tapered tiers + entrance notch on +Z face (default 0.70/0.85/0.05) \n " ) ;
2026-05-09 09:20:08 -07:00
std : : printf ( " --gen-mesh-weathervane <wom-base> [postH] [postT] [baseSize] [armLen] [arrowLen] \n " ) ;
std : : printf ( " Weathervane: base + post + N-S/E-W cross arms + arrow with tail (default 1.50/0.05/0.30/0.40/0.55) \n " ) ;
2026-05-09 09:27:56 -07:00
std : : printf ( " --gen-mesh-scarecrow <wom-base> [bodyH] [armSpan] [postT] [headSize] [hatSize] \n " ) ;
std : : printf ( " Scarecrow: cruciform body + cross arms + head + brimmed hat (default 1.80/1.40/0.06/0.22/0.32) \n " ) ;
2026-05-09 09:37:13 -07:00
std : : printf ( " --gen-mesh-sundial <wom-base> [baseSize] [baseH] [gnomonH] [gnomonT] \n " ) ;
std : : printf ( " Sundial: square base + central gnomon slab + 4 cardinal hour markers (default 0.80/0.06/0.35/0.04) \n " ) ;
2026-05-09 09:46:59 -07:00
std : : printf ( " --gen-mesh-podium <wom-base> [baseSize] [stepH] [steps] [lecternSize] \n " ) ;
std : : printf ( " Podium: stepped pyramid + lectern at back of top platform (default 1.60/0.20/3/0.30) \n " ) ;
2026-05-09 09:56:38 -07:00
std : : printf ( " --gen-mesh-brazier <wom-base> [bowlSize] [stemH] [stemT] [baseSize] \n " ) ;
std : : printf ( " Brazier: base + stem + bowl + 3 flame boxes for fire-pit lighting (default 0.55/0.80/0.10/0.35) \n " ) ;
2026-05-09 10:11:24 -07:00
std : : printf ( " --gen-mesh-archway-double <wom-base> [openingW] [openingH] [postT] [lintelT] \n " ) ;
std : : printf ( " Double archway: 3 posts + 2 lintels for twin-opening passages (default 1.40/2.40/0.18/0.20) \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " Procedural tree: cylindrical trunk + spherical foliage (default 0.1/2.0/0.7) \n " ) ;
std : : printf ( " --displace-mesh <wom-base> <heightmap.png> [scale] \n " ) ;
std : : printf ( " Offset each vertex along its normal by heightmap brightness × scale (default 1.0) \n " ) ;
std : : printf ( " --gen-mesh-from-heightmap <wom-base> <heightmap.png> [scaleXZ] [scaleY] \n " ) ;
std : : printf ( " Convert a grayscale PNG into a heightmap mesh (W× H verts, 2(W-1)(H-1) tris) \n " ) ;
std : : printf ( " --export-mesh-heightmap <wom-base> <out.png> <W> <H> \n " ) ;
std : : printf ( " Extract a grayscale heightmap PNG from a row-major W× H heightmap mesh \n " ) ;
std : : printf ( " --add-texture-to-mesh <wom-base> <png-path> [batchIdx] \n " ) ;
std : : printf ( " Bind an existing PNG into a WOM's texturePaths and point batchIdx (default 0) at it \n " ) ;
std : : printf ( " --scale-mesh <wom-base> <factor> \n " ) ;
std : : printf ( " Uniformly scale every vertex and bounds by <factor> (factor > 0) \n " ) ;
std : : printf ( " --translate-mesh <wom-base> <dx> <dy> <dz> \n " ) ;
std : : printf ( " Offset every vertex and bounds by (dx, dy, dz) \n " ) ;
std : : printf ( " --strip-mesh <wom-base> [--bones] [--anims] [--all] \n " ) ;
std : : printf ( " Drop bones / animations from a WOM in place (smaller file, static-only use) \n " ) ;
std : : printf ( " --rotate-mesh <wom-base> <x|y|z> <degrees> \n " ) ;
std : : printf ( " Rotate every vertex + normal around the chosen axis by <degrees> \n " ) ;
std : : printf ( " --center-mesh <wom-base> \n " ) ;
std : : printf ( " Translate so the bounds center lands at origin (no scale/rotation change) \n " ) ;
std : : printf ( " --flip-mesh-normals <wom-base> \n " ) ;
std : : printf ( " Invert every vertex normal (use for inside-out meshes or two-sided pre-flip) \n " ) ;
std : : printf ( " --mirror-mesh <wom-base> <x|y|z> \n " ) ;
std : : printf ( " Mirror every vertex + normal across the chosen axis (also flips winding) \n " ) ;
std : : printf ( " --smooth-mesh-normals <wom-base> \n " ) ;
std : : printf ( " Recompute per-vertex normals as area-weighted averages of incident face normals \n " ) ;
std : : printf ( " --merge-meshes <a-base> <b-base> <out-base> \n " ) ;
std : : printf ( " Combine two WOMs into one (vertex/index buffers concatenated, batches preserved) \n " ) ;
std : : printf ( " --add-item <zoneDir> <name> [id] [quality] [displayId] [itemLevel] \n " ) ;
std : : printf ( " Append one item entry to <zoneDir>/items.json (auto-creates the file) \n " ) ;
std : : printf ( " --random-populate-zone <zoneDir> [--seed N] [--creatures N] [--objects N] \n " ) ;
std : : printf ( " Add random creatures/objects to a zone (seeded for reproducibility) \n " ) ;
std : : printf ( " --random-populate-items <zoneDir> [--seed N] [--count N] [--max-quality Q] \n " ) ;
std : : printf ( " Generate random items.json entries (seeded; quality cap defaults to epic=4) \n " ) ;
std : : printf ( " --gen-zone-texture-pack <zoneDir> [--seed N] \n " ) ;
std : : printf ( " Drop a starter texture pack (grass/dirt/stone/brick/wood/water) into <zoneDir>/textures/ \n " ) ;
std : : printf ( " --gen-zone-mesh-pack <zoneDir> [--seed N] \n " ) ;
std : : printf ( " Drop a starter WOM mesh pack (rock/tree/fence) into <zoneDir>/meshes/ \n " ) ;
std : : printf ( " --gen-zone-starter-pack <zoneDir> [--seed N] \n " ) ;
std : : printf ( " Run both texture-pack + mesh-pack in one pass — full open-format bootstrap \n " ) ;
std : : printf ( " --gen-project-starter-pack <projectDir> [--seed N] \n " ) ;
std : : printf ( " Run starter-pack + audio-pack across every zone — full project-scope bootstrap \n " ) ;
std : : printf ( " --info-zone-summary <zoneDir> [--json] \n " ) ;
std : : printf ( " One-glance health digest for a zone: pack counts/bytes + audit pass/fail \n " ) ;
std : : printf ( " --info-zone-deps <zoneDir> [--json] \n " ) ;
std : : printf ( " Find textures referenced by WOMs but missing from <zoneDir>/textures/ (broken-ref audit) \n " ) ;
std : : printf ( " --info-project-deps <projectDir> \n " ) ;
std : : printf ( " Run --info-zone-deps across every zone; reports per-zone PASS/FAIL + grand total \n " ) ;
std : : printf ( " --info-project-summary <projectDir> [--json] \n " ) ;
std : : printf ( " One-glance status table per zone in a project (BOOTSTRAPPED/PARTIAL/EMPTY) \n " ) ;
std : : printf ( " --gen-zone-readme <zoneDir> [--out <path>] \n " ) ;
std : : printf ( " Auto-generate README.md from zone.json + asset inventory (writes README.md by default) \n " ) ;
std : : printf ( " --gen-project-readme <projectDir> [--out <path>] \n " ) ;
std : : printf ( " Auto-generate PROJECT.md with per-zone status + asset count rollup \n " ) ;
std : : printf ( " --validate-zone-pack <zoneDir> [--json] \n " ) ;
std : : printf ( " Audit a zone's open-format asset pack: textures/meshes/audio counts + WOM validity \n " ) ;
std : : printf ( " --validate-project-packs <projectDir> \n " ) ;
std : : printf ( " Run validate-zone-pack across every zone in a project; exits 1 if any fails \n " ) ;
std : : printf ( " --gen-audio-tone <out.wav> <freqHz> <durationSec> [sampleRate] [waveform] \n " ) ;
std : : printf ( " Synthesize a procedural WAV (PCM-16 mono). Waveform: sine|square|triangle|saw \n " ) ;
std : : printf ( " --gen-audio-noise <out.wav> <durationSec> [sampleRate] [color] [seed] [amplitude] \n " ) ;
std : : printf ( " Synthesize procedural noise WAV. Color: white|pink|brown (default white, amp 0.5) \n " ) ;
std : : printf ( " --gen-audio-sweep <out.wav> <startHz> <endHz> <durationSec> [sampleRate] [shape] \n " ) ;
std : : printf ( " Synthesize frequency sweep (chirp) WAV. Shape: linear|exp (default linear) \n " ) ;
std : : printf ( " --gen-zone-audio-pack <zoneDir> \n " ) ;
std : : printf ( " Drop a starter WAV pack (drone/chime/click/alert) into <zoneDir>/audio/ \n " ) ;
std : : printf ( " --gen-random-zone <name> [tx ty] [--seed N] [--creatures N] [--objects N] [--items N] \n " ) ;
std : : printf ( " End-to-end: scaffold-zone + random-populate-zone + random-populate-items \n " ) ;
std : : printf ( " --gen-random-project <count> [--prefix N] [--seed N] [--creatures N] [--objects N] [--items N] \n " ) ;
std : : printf ( " Generate <count> random zones at once (names like Zone1, Zone2...; tile coords step) \n " ) ;
std : : printf ( " --info-zone-audio <zoneDir> [--json] \n " ) ;
std : : printf ( " Print zone audio config (music + ambience tracks, volumes) \n " ) ;
std : : printf ( " --info-project-audio <projectDir> [--json] \n " ) ;
std : : printf ( " Audio config table across every zone (which zones have music/ambience set) \n " ) ;
std : : printf ( " --snap-zone-to-ground <zoneDir> \n " ) ;
std : : printf ( " Re-snap every creature/object in a zone to actual terrain height \n " ) ;
std : : printf ( " --audit-zone-spawns <zoneDir> [--threshold yards] \n " ) ;
std : : printf ( " List spawns whose Z is more than <threshold> yards off from the terrain (default 5) \n " ) ;
std : : printf ( " --list-zone-spawns <zoneDir> [--json] \n " ) ;
std : : printf ( " Combined creature+object listing for a zone (kind, name, position, key fields) \n " ) ;
std : : printf ( " --diff-zone-spawns <aZoneDir> <bZoneDir> \n " ) ;
std : : printf ( " Compare two zones' creature+object lists (added/removed/moved) \n " ) ;
std : : printf ( " --info-spawn <zoneDir> <creature|object> <index> [--json] \n " ) ;
std : : printf ( " Detailed view of a single creature/object spawn by index \n " ) ;
std : : printf ( " --list-project-spawns <projectDir> [--json] \n " ) ;
std : : printf ( " Combined creature+object listing across every zone (zone column added) \n " ) ;
std : : printf ( " --audit-project-spawns <projectDir> [--threshold yards] \n " ) ;
std : : printf ( " Run --audit-zone-spawns across every zone (per-zone summary + total) \n " ) ;
std : : printf ( " --snap-project-to-ground <projectDir> \n " ) ;
std : : printf ( " Run --snap-zone-to-ground across every zone (per-zone summary + totals) \n " ) ;
std : : printf ( " --list-items <zoneDir> [--json] \n " ) ;
std : : printf ( " Print every item in <zoneDir>/items.json with quality colors and key fields \n " ) ;
std : : printf ( " --export-zone-items-md <zoneDir> [out.md] \n " ) ;
std : : printf ( " Render items.json as a Markdown table grouped by quality (rare/epic/etc.) \n " ) ;
std : : printf ( " --export-project-items-md <projectDir> [out.md] \n " ) ;
std : : printf ( " Project-wide items markdown: per-zone sections, project quality histogram \n " ) ;
std : : printf ( " --export-project-items-csv <projectDir> [out.csv] \n " ) ;
std : : printf ( " Single CSV with every item across every zone (zone column added for grouping) \n " ) ;
std : : printf ( " --info-item <zoneDir> <id|index> [--json] \n " ) ;
std : : printf ( " Detail view for one item (lookup by id, or by index if prefixed with '#') \n " ) ;
std : : printf ( " --set-item <zoneDir> <id|#index> [--name S] [--quality N] [--displayId N] [--itemLevel N] [--stackable N] \n " ) ;
std : : printf ( " Edit fields on an existing item in place; only specified flags are changed \n " ) ;
std : : printf ( " --remove-item <zoneDir> <index> \n " ) ;
std : : printf ( " Remove item at given 0-based index from <zoneDir>/items.json \n " ) ;
std : : printf ( " --copy-zone-items <fromZoneDir> <toZoneDir> [--merge] \n " ) ;
std : : printf ( " Copy items from one zone to another (default replaces; --merge appends with re-id) \n " ) ;
std : : printf ( " --clone-item <zoneDir> <index> [newName] \n " ) ;
std : : printf ( " Duplicate the item at index, assign next free id (and optional name override) \n " ) ;
std : : printf ( " --validate-items <zoneDir> \n " ) ;
std : : printf ( " Schema check on items.json: duplicate ids, quality range, required fields \n " ) ;
std : : printf ( " --validate-project-items <projectDir> \n " ) ;
std : : printf ( " Run --validate-items across every zone (per-zone PASS/FAIL + aggregate) \n " ) ;
std : : printf ( " --info-project-items <projectDir> [--json] \n " ) ;
std : : printf ( " Aggregate item counts and quality histogram across every zone in a project \n " ) ;
std : : printf ( " --convert-dbc-json <dbc-path> [out.json] \n " ) ;
std : : printf ( " Convert one DBC file to wowee JSON sidecar format \n " ) ;
std : : printf ( " --convert-json-dbc <json-path> [out.dbc] \n " ) ;
std : : printf ( " Convert a wowee JSON DBC back to binary DBC for private-server compat \n " ) ;
std : : printf ( " --convert-blp-png <blp-path> [out.png] \n " ) ;
std : : printf ( " Convert one BLP texture to PNG sidecar \n " ) ;
std : : printf ( " --convert-blp-batch <srcDir> \n " ) ;
std : : printf ( " Bulk BLP→PNG conversion across every .blp in <srcDir> (sidecars next to source) \n " ) ;
std : : printf ( " --migrate-wom <wom-base> [out-base] \n " ) ;
std : : printf ( " Upgrade an older WOM (v1/v2) to WOM3 with a default single-batch entry \n " ) ;
std : : printf ( " --migrate-zone <zoneDir> \n " ) ;
std : : printf ( " Run --migrate-wom in-place on every WOM under <zoneDir> \n " ) ;
std : : printf ( " --migrate-project <projectDir> \n " ) ;
std : : printf ( " Run --migrate-zone across every zone in <projectDir> \n " ) ;
std : : printf ( " --migrate-jsondbc <path> [out.json] \n " ) ;
std : : printf ( " Auto-fix a JSON DBC sidecar: add missing format/source, sync recordCount \n " ) ;
std : : printf ( " --list-zones [--json] List discovered custom zones and exit \n " ) ;
std : : printf ( " --zone-stats <projectDir> [--json] \n " ) ;
std : : printf ( " Aggregate counts across every zone in <projectDir> \n " ) ;
std : : printf ( " --info-tilemap <projectDir> [--json] \n " ) ;
std : : printf ( " ASCII-render the 64x64 WoW ADT grid showing tile claims by zone \n " ) ;
std : : printf ( " --list-project-orphans <projectDir> [--json] \n " ) ;
std : : printf ( " Find .wom/.wob files in zones not referenced by any objects.json or doodad list \n " ) ;
std : : printf ( " --remove-project-orphans <projectDir> [--dry-run] \n " ) ;
std : : printf ( " Delete the orphan .wom/.wob files surfaced by --list-project-orphans \n " ) ;
std : : printf ( " --list-zone-deps <zoneDir> [--json] \n " ) ;
std : : printf ( " List external M2/WMO model paths a zone references (objects + WOB doodads) \n " ) ;
std : : printf ( " --export-zone-deps-md <zoneDir> [out.md] \n " ) ;
std : : printf ( " Markdown dep table for a zone (with on-disk presence column) \n " ) ;
std : : printf ( " --export-zone-spawn-png <zoneDir> [out.png] \n " ) ;
std : : printf ( " Top-down PNG of creature + object spawn positions (per-tile-bounded) \n " ) ;
std : : printf ( " --check-zone-refs <zoneDir> [--json] \n " ) ;
std : : printf ( " Verify every referenced model/quest NPC actually exists; exit 1 on missing refs \n " ) ;
std : : printf ( " --check-project-refs <projectDir> [--json] \n " ) ;
std : : printf ( " Run --check-zone-refs across every zone in <projectDir> \n " ) ;
std : : printf ( " --check-zone-content <zoneDir> [--json] \n " ) ;
std : : printf ( " Sanity-check creature/object/quest fields for plausible values \n " ) ;
std : : printf ( " --check-project-content <projectDir> [--json] \n " ) ;
std : : printf ( " Run --check-zone-content across every zone in <projectDir> \n " ) ;
std : : printf ( " --for-each-zone <projectDir> -- <cmd...> \n " ) ;
std : : printf ( " Run <cmd...> for every zone in <projectDir>; '{}' in cmd is replaced with the zone path \n " ) ;
std : : printf ( " --for-each-tile <zoneDir> -- <cmd...> \n " ) ;
std : : printf ( " Run <cmd...> for every tile in <zoneDir>; '{}' replaced with the tile-base path \n " ) ;
std : : printf ( " --scaffold-zone <name> [tx ty] Create a blank zone in custom_zones/<name>/ and exit \n " ) ;
std : : printf ( " --mvp-zone <name> [tx ty] \n " ) ;
std : : printf ( " Scaffold + add a creature + object + quest (with objective+reward) for quick demos \n " ) ;
std : : printf ( " --add-tile <zoneDir> <tx> <ty> [baseHeight] \n " ) ;
std : : printf ( " Add a new ADT tile to an existing zone (extends the manifest's tiles list) \n " ) ;
std : : printf ( " --remove-tile <zoneDir> <tx> <ty> \n " ) ;
std : : printf ( " Remove a tile from a zone (drops manifest entry + deletes WHM/WOT/WOC files) \n " ) ;
std : : printf ( " --list-tiles <zoneDir> [--json] \n " ) ;
std : : printf ( " List every tile in a zone manifest with on-disk file presence \n " ) ;
std : : printf ( " --add-creature <zoneDir> <name> <x> <y> <z> [displayId] [level] \n " ) ;
std : : printf ( " Append one creature spawn to <zoneDir>/creatures.json and exit \n " ) ;
std : : printf ( " --add-object <zoneDir> <m2|wmo> <gamePath> <x> <y> <z> [scale] \n " ) ;
std : : printf ( " Append one object placement to <zoneDir>/objects.json and exit \n " ) ;
std : : printf ( " --add-quest <zoneDir> <title> [giverId] [turnInId] [xp] [level] \n " ) ;
std : : printf ( " Append one quest to <zoneDir>/quests.json and exit \n " ) ;
std : : printf ( " --add-quest-objective <zoneDir> <questIdx> <kill|collect|talk|explore|escort|use> <targetName> [count] \n " ) ;
std : : printf ( " Append one objective to a quest by index \n " ) ;
std : : printf ( " --remove-quest-objective <zoneDir> <questIdx> <objIdx> \n " ) ;
std : : printf ( " Remove the objective at given 0-based index from a quest \n " ) ;
std : : printf ( " --clone-quest <zoneDir> <questIdx> [newTitle] \n " ) ;
std : : printf ( " Duplicate a quest (with all objectives + rewards) and append it \n " ) ;
std : : printf ( " --clone-creature <zoneDir> <idx> [newName] [dx dy dz] \n " ) ;
std : : printf ( " Duplicate a creature spawn (defaults: '<orig> (copy)' offset by 5 yards) \n " ) ;
std : : printf ( " --clone-object <zoneDir> <idx> [dx dy dz] \n " ) ;
std : : printf ( " Duplicate an object placement (defaults: offset by 5 yards X) \n " ) ;
std : : printf ( " --add-quest-reward-item <zoneDir> <questIdx> <itemPath> [more...] \n " ) ;
std : : printf ( " Append item reward(s) to a quest's reward.itemRewards list \n " ) ;
std : : printf ( " --set-quest-reward <zoneDir> <questIdx> [--xp N] [--gold N] [--silver N] [--copper N] \n " ) ;
std : : printf ( " Update XP/coin reward fields on a quest by index \n " ) ;
std : : printf ( " --remove-creature <zoneDir> <index> \n " ) ;
std : : printf ( " Remove creature at given 0-based index from <zoneDir>/creatures.json \n " ) ;
std : : printf ( " --remove-object <zoneDir> <index> \n " ) ;
std : : printf ( " Remove object at given 0-based index from <zoneDir>/objects.json \n " ) ;
std : : printf ( " --remove-quest <zoneDir> <index> \n " ) ;
std : : printf ( " Remove quest at given 0-based index from <zoneDir>/quests.json \n " ) ;
std : : printf ( " --copy-zone <srcDir> <newName> \n " ) ;
std : : printf ( " Duplicate a zone to custom_zones/<slug>/ with renamed slug-prefixed files \n " ) ;
std : : printf ( " --rename-zone <srcDir> <newName> \n " ) ;
std : : printf ( " In-place rename (zone.json + slug-prefixed files + dir); no copy \n " ) ;
std : : printf ( " --remove-zone <zoneDir> [--confirm] \n " ) ;
std : : printf ( " Delete a zone directory entirely (requires --confirm to actually delete) \n " ) ;
std : : printf ( " --clear-zone-content <zoneDir> [--creatures] [--objects] [--quests] [--all] \n " ) ;
std : : printf ( " Wipe one or more content files (terrain + manifest preserved) \n " ) ;
std : : printf ( " --strip-zone <zoneDir> [--dry-run] \n " ) ;
std : : printf ( " Remove derived outputs (.glb/.obj/.stl/.html/.dot/.csv/ZONE.md/DEPS.md) \n " ) ;
std : : printf ( " --strip-project <projectDir> [--dry-run] \n " ) ;
std : : printf ( " Run --strip-zone across every zone (per-zone counts + aggregate freed bytes) \n " ) ;
std : : printf ( " --gen-makefile <zoneDir> [out.mk] \n " ) ;
std : : printf ( " Generate a Makefile that rebuilds every derived output for a zone \n " ) ;
std : : printf ( " --gen-project-makefile <projectDir> [out.mk] \n " ) ;
std : : printf ( " Generate a top-level Makefile that delegates to each zone's per-zone Makefile \n " ) ;
std : : printf ( " --repair-project <projectDir> [--dry-run] \n " ) ;
std : : printf ( " Run --repair-zone across every zone (manifest drift fixes, per-zone summary) \n " ) ;
std : : printf ( " --repair-zone <zoneDir> [--dry-run] \n " ) ;
std : : printf ( " Auto-fix manifest/disk drift (missing tiles in manifest, hasCreatures flag) \n " ) ;
std : : printf ( " --build-woc <wot-base> Generate a WOC collision mesh from WHM/WOT and exit \n " ) ;
std : : printf ( " --regen-collision <zoneDir> Rebuild every WOC under a zone dir and exit \n " ) ;
std : : printf ( " --fix-zone <zoneDir> Re-parse + re-save zone JSONs to apply latest scrubs/caps and exit \n " ) ;
std : : printf ( " --export-png <wot-base> Render heightmap, normal-map, and zone-map PNG previews \n " ) ;
std : : printf ( " --export-obj <wom-base> [out.obj] \n " ) ;
std : : printf ( " Convert a WOM model to Wavefront OBJ for use in Blender/MeshLab \n " ) ;
std : : printf ( " --export-glb <wom-base> [out.glb] \n " ) ;
std : : printf ( " Convert a WOM model to glTF 2.0 binary (.glb) — modern industry standard \n " ) ;
std : : printf ( " --export-stl <wom-base> [out.stl] \n " ) ;
std : : printf ( " Convert a WOM model to ASCII STL — works with any 3D printer slicer \n " ) ;
std : : printf ( " --import-stl <stl-path> [wom-base] \n " ) ;
std : : printf ( " Convert an ASCII STL back into WOM (round-trips with --export-stl) \n " ) ;
std : : printf ( " --export-wob-glb <wob-base> [out.glb] \n " ) ;
std : : printf ( " Convert a WOB building to glTF 2.0 binary (one mesh, per-group primitives) \n " ) ;
std : : printf ( " --export-whm-glb <wot-base> [out.glb] \n " ) ;
std : : printf ( " Convert WHM heightmap to glTF 2.0 binary terrain mesh (per-chunk primitives) \n " ) ;
std : : printf ( " --bake-zone-glb <zoneDir> [out.glb] \n " ) ;
std : : printf ( " Bake every WHM tile in a zone into one glTF (one node per tile) \n " ) ;
std : : printf ( " --bake-zone-stl <zoneDir> [out.stl] \n " ) ;
std : : printf ( " Bake every WHM tile in a zone into one STL for 3D-printing the terrain \n " ) ;
std : : printf ( " --bake-zone-obj <zoneDir> [out.obj] \n " ) ;
std : : printf ( " Bake every WHM tile in a zone into one Wavefront OBJ (one g-block per tile) \n " ) ;
std : : printf ( " --bake-project-obj <projectDir> [out.obj] \n " ) ;
std : : printf ( " Bake every zone in a project into one Wavefront OBJ (one g-block per zone) \n " ) ;
std : : printf ( " --bake-project-stl <projectDir> [out.stl] \n " ) ;
std : : printf ( " Bake every zone in a project into one ASCII STL for full-project printing \n " ) ;
std : : printf ( " --bake-project-glb <projectDir> [out.glb] \n " ) ;
std : : printf ( " Bake every zone in a project into one glTF 2.0 (one mesh per zone) \n " ) ;
2026-05-09 11:01:45 -07:00
std : : printf ( " --bake-wom-collision <wom-base> [out.woc] [--weld <eps>] [--steep <deg>] \n " ) ;
std : : printf ( " Convert a WOM into a WOC collision file (raycast / walkability mesh) with optional vertex weld \n " ) ;
2026-05-09 11:19:09 -07:00
std : : printf ( " --bake-wob-collision <wob-base> [out.woc] [--weld <eps>] [--steep <deg>] \n " ) ;
std : : printf ( " Convert a multi-group WOB building into a single WOC collision file (weld is per-group) \n " ) ;
2026-05-09 11:36:38 -07:00
std : : printf ( " --bake-zone-collision <zoneDir> [out.woc] [--weld <eps>] [--steep <deg>] \n " ) ;
std : : printf ( " Walk every .wom + .wob under zoneDir, weld each independently, append to one shared WOC \n " ) ;
2026-05-09 13:09:28 -07:00
std : : printf ( " --audit-watertight <zoneDir|projectDir> [--weld <eps>] [--json] [--summary] \n " ) ;
std : : printf ( " Walk every .wom under root, run welded watertight check; --summary prints a one-line rollup \n " ) ;
2026-05-09 13:12:42 -07:00
std : : printf ( " --audit-watertight-wob <zoneDir|projectDir> [--weld <eps>] [--json] [--summary] \n " ) ;
std : : printf ( " Walk every .wob, check that EVERY group is closed (per-group weld); --summary prints one-line rollup \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " --import-obj <obj-path> [wom-base] \n " ) ;
std : : printf ( " Convert a Wavefront OBJ back into WOM (round-trips with --export-obj) \n " ) ;
std : : printf ( " --export-wob-obj <wob-base> [out.obj] \n " ) ;
std : : printf ( " Convert a WOB building to Wavefront OBJ (one group per WOB group) \n " ) ;
std : : printf ( " --import-wob-obj <obj-path> [wob-base] \n " ) ;
std : : printf ( " Convert a Wavefront OBJ back into WOB (round-trips with --export-wob-obj) \n " ) ;
std : : printf ( " --export-woc-obj <woc-path> [out.obj] \n " ) ;
std : : printf ( " Convert a WOC collision mesh to OBJ for visualization (per-flag color groups) \n " ) ;
std : : printf ( " --export-whm-obj <wot-base> [out.obj] \n " ) ;
std : : printf ( " Convert a WHM heightmap to OBJ terrain mesh (9x9 outer grid per chunk) \n " ) ;
std : : printf ( " --validate <zoneDir> [--json] \n " ) ;
std : : printf ( " Score zone open-format completeness and exit \n " ) ;
std : : printf ( " --validate-wom <wom-base> [--json] \n " ) ;
std : : printf ( " Deep-check a WOM file for index/bone/batch/bound invariants \n " ) ;
std : : printf ( " --validate-wob <wob-base> [--json] \n " ) ;
std : : printf ( " Deep-check a WOB file for group/portal/doodad invariants \n " ) ;
std : : printf ( " --validate-woc <woc-path> [--json] \n " ) ;
std : : printf ( " Deep-check a WOC collision mesh for finite verts and degeneracy \n " ) ;
std : : printf ( " --validate-whm <wot-base> [--json] \n " ) ;
std : : printf ( " Deep-check a WHM/WOT terrain pair for NaN heights and bad placements \n " ) ;
std : : printf ( " --validate-all <dir> [--json] \n " ) ;
std : : printf ( " Recursively run all per-format validators on every file \n " ) ;
std : : printf ( " --validate-project <projectDir> [--json] \n " ) ;
std : : printf ( " Run --validate-all on every zone in <projectDir>; exit 1 if any zone fails \n " ) ;
std : : printf ( " --bench-validate-project <projectDir> [--json] \n " ) ;
std : : printf ( " Time --validate-project per zone; report avg/min/max latency \n " ) ;
std : : printf ( " --bench-bake-project <projectDir> [--json] \n " ) ;
std : : printf ( " Time WHM/WOT load per zone (proxy for bake cost); report timings \n " ) ;
std : : printf ( " --validate-glb <path> [--json] \n " ) ;
std : : printf ( " Verify a glTF 2.0 binary's structure (magic, chunks, JSON, accessors) \n " ) ;
std : : printf ( " --check-glb-bounds <path> [--json] \n " ) ;
std : : printf ( " Verify position accessor min/max in a .glb actually matches the data \n " ) ;
std : : printf ( " --validate-stl <path> [--json] \n " ) ;
std : : printf ( " Verify an ASCII STL's structure (solid framing, facet/vertex shape, no NaN) \n " ) ;
std : : printf ( " --validate-png <path> [--json] \n " ) ;
std : : printf ( " Verify a PNG's structure (signature, chunks, CRC, IHDR/IDAT/IEND order) \n " ) ;
std : : printf ( " --validate-blp <path> [--json] \n " ) ;
std : : printf ( " Verify a BLP texture (magic, dimensions, mip offsets within file) \n " ) ;
std : : printf ( " --validate-jsondbc <path> [--json] \n " ) ;
std : : printf ( " Verify a JSON DBC sidecar's full schema (per-cell types, row width, format tag) \n " ) ;
std : : printf ( " --info-glb <path> [--json] \n " ) ;
std : : printf ( " Print glTF 2.0 binary metadata (chunks, mesh/primitive counts, accessors) \n " ) ;
std : : printf ( " --info-glb-bytes <path> [--json] \n " ) ;
std : : printf ( " Per-section + per-bufferView byte breakdown of a .glb file \n " ) ;
std : : printf ( " --info-glb-tree <path> \n " ) ;
std : : printf ( " Render glTF structure as a tree (scenes/nodes/meshes/primitives) \n " ) ;
std : : printf ( " --zone-summary <zoneDir> [--json] \n " ) ;
std : : printf ( " One-shot validate + creature/object/quest counts and exit \n " ) ;
std : : printf ( " --info-zone-tree <zoneDir> \n " ) ;
std : : printf ( " Render a hierarchical tree view of a zone's contents (no --json) \n " ) ;
std : : printf ( " --info-project-tree <projectDir> \n " ) ;
std : : printf ( " Tree view of every zone in a project with quick counts (no --json) \n " ) ;
std : : printf ( " --info-project-bytes <projectDir> [--json] \n " ) ;
std : : printf ( " Per-zone byte rollup with proprietary-vs-open category split (size audit) \n " ) ;
std : : printf ( " --validate-project-open-only <projectDir> \n " ) ;
std : : printf ( " Exit 1 if any proprietary Blizzard assets (.m2/.wmo/.blp/.dbc) remain — release gate \n " ) ;
std : : printf ( " --audit-project <projectDir> \n " ) ;
std : : printf ( " Run validate-project + open-only + check-project-refs together; one PASS/FAIL \n " ) ;
std : : printf ( " --bench-audit-project <projectDir> \n " ) ;
std : : printf ( " Time each --audit-project sub-step; shows where the slow ones are \n " ) ;
std : : printf ( " --info-zone-bytes <zoneDir> [--json] \n " ) ;
std : : printf ( " Per-file size breakdown grouped by category, sorted largest-first \n " ) ;
std : : printf ( " --info-project-extents <projectDir> [--json] \n " ) ;
std : : printf ( " Combined spatial bounding box across every zone (per-zone table + project union) \n " ) ;
std : : printf ( " --info-zone-extents <zoneDir> [--json] \n " ) ;
std : : printf ( " Compute the zone's bounding box (XY tile range, Z height min/max) \n " ) ;
std : : printf ( " --info-project-water <projectDir> [--json] \n " ) ;
std : : printf ( " Aggregate water-layer stats across every zone (per-zone breakdown + project totals) \n " ) ;
std : : printf ( " --info-zone-water <zoneDir> [--json] \n " ) ;
std : : printf ( " Aggregate water-layer stats across all tiles (layer count, types, area) \n " ) ;
std : : printf ( " --info-project-density <projectDir> [--json] \n " ) ;
std : : printf ( " Per-zone content density rollup (creatures/objects/quests per tile, project totals) \n " ) ;
std : : printf ( " --info-zone-density <zoneDir> [--json] \n " ) ;
std : : printf ( " Per-tile density (creatures/objects/quests per tile + overall avg) \n " ) ;
std : : printf ( " --export-zone-summary-md <zoneDir> [out.md] \n " ) ;
std : : printf ( " Render a markdown documentation page for a zone (manifest + content) \n " ) ;
std : : printf ( " --export-zone-csv <zoneDir> [outDir] \n " ) ;
std : : printf ( " Emit creatures.csv / objects.csv / quests.csv / items.csv for spreadsheet workflows \n " ) ;
std : : printf ( " --export-zone-checksum <zoneDir> [out.sha256] \n " ) ;
std : : printf ( " Emit a SHA-256 manifest of every source file in a zone (for integrity checks) \n " ) ;
std : : printf ( " --export-project-checksum <projectDir> [out.sha256] \n " ) ;
std : : printf ( " Project-wide SHA-256 manifest (paths are zone-relative) + single project fingerprint \n " ) ;
std : : printf ( " --validate-project-checksum <projectDir> [in.sha256] \n " ) ;
std : : printf ( " Verify PROJECT_SHA256SUMS in-tool (cross-platform, no sha256sum dependency) \n " ) ;
std : : printf ( " --export-zone-html <zoneDir> [out.html] \n " ) ;
std : : printf ( " Emit a single-file HTML viewer next to the zone .glb (model-viewer based) \n " ) ;
std : : printf ( " --export-project-html <projectDir> [out.html] \n " ) ;
std : : printf ( " Generate an index.html linking to every zone's HTML viewer in <projectDir> \n " ) ;
std : : printf ( " --export-project-md <projectDir> [out.md] \n " ) ;
std : : printf ( " Generate a README.md indexing every zone with counts + viewer/bake status \n " ) ;
std : : printf ( " --export-quest-graph <zoneDir> [out.dot] \n " ) ;
std : : printf ( " Render quest-chain DAG as Graphviz DOT (pipe to `dot -Tpng -o quests.png`) \n " ) ;
std : : printf ( " --info <wom-base> [--json] \n " ) ;
std : : printf ( " Print WOM file metadata (version, counts) and exit \n " ) ;
std : : printf ( " --info-batches <wom-base> [--json] \n " ) ;
std : : printf ( " Per-batch breakdown of a WOM3 (index range, texture, blend mode, flags) \n " ) ;
std : : printf ( " --info-textures <wom-base> [--json] \n " ) ;
std : : printf ( " List every texture path referenced by a WOM (with on-disk presence) \n " ) ;
std : : printf ( " --info-doodads <wob-base> [--json] \n " ) ;
std : : printf ( " List every doodad placement in a WOB (model path, position, rotation, scale) \n " ) ;
std : : printf ( " --info-attachments <m2-path> [--json] \n " ) ;
std : : printf ( " List M2 attachment points (weapon mounts, etc.) with bone + offset \n " ) ;
std : : printf ( " --info-particles <m2-path> [--json] \n " ) ;
std : : printf ( " List M2 particle + ribbon emitters (texture, blend, bone) \n " ) ;
std : : printf ( " --info-sequences <m2-path> [--json] \n " ) ;
std : : printf ( " List M2 animation sequences (id, duration, flags) \n " ) ;
std : : printf ( " --info-bones <m2-path> [--json] \n " ) ;
std : : printf ( " List M2 bones with parent tree, key-bone IDs, pivot offsets \n " ) ;
std : : printf ( " --export-bones-dot <wom-base> [out.dot] \n " ) ;
std : : printf ( " Render WOM bone hierarchy as Graphviz DOT (pipe to `dot -Tpng -o bones.png`) \n " ) ;
std : : printf ( " --list-project-meshes <projectDir> [--json] \n " ) ;
std : : printf ( " Project-wide WOM inventory across every zone (vert/tri totals + per-zone breakdown) \n " ) ;
std : : printf ( " --list-project-audio <projectDir> [--json] \n " ) ;
std : : printf ( " Project-wide WAV inventory across every zone (duration/bytes per zone + grand total) \n " ) ;
std : : printf ( " --list-project-textures <projectDir> [--json] \n " ) ;
std : : printf ( " Aggregate texture refs across every WOM in a project (deduped, with zone breakdown) \n " ) ;
std : : printf ( " --list-zone-meshes <zoneDir> [--json] \n " ) ;
std : : printf ( " List every WOM in <zoneDir> with vert/tri/bone/anim/batch counts and file size \n " ) ;
std : : printf ( " --list-zone-audio <zoneDir> [--json] \n " ) ;
std : : printf ( " List every WAV under <zoneDir>/audio/ with format/duration/sample-rate/size \n " ) ;
std : : printf ( " --list-zone-textures <zoneDir> [--json] \n " ) ;
std : : printf ( " Aggregate texture refs across all WOM models in a zone (deduped) \n " ) ;
std : : printf ( " --info-zone-models-total <zoneDir> [--json] \n " ) ;
std : : printf ( " Aggregate WOM/WOB stats across a zone (verts, tris, bones, batches, doodads) \n " ) ;
std : : printf ( " --list-zone-meshes-detail <zoneDir> [--json] \n " ) ;
std : : printf ( " Per-mesh listing of every .wom in a zone, sorted by triangle count \n " ) ;
std : : printf ( " --info-mesh <wom-base> [--json] \n " ) ;
std : : printf ( " Single-mesh detail: bounds, version, batches, bones, textures, attachments in one view \n " ) ;
std : : printf ( " --info-mesh-storage-budget <wom-base> [--json] \n " ) ;
std : : printf ( " Estimated bytes-per-category breakdown for a single WOM (vertices/indices/bones/...) \n " ) ;
2026-05-09 10:41:58 -07:00
std : : printf ( " --info-mesh-stats <wom-base> [--json] \n " ) ;
std : : printf ( " Geometric stats: total surface area, triangle area histogram, edge use, watertight check \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " --list-project-meshes-detail <projectDir> [--json] \n " ) ;
std : : printf ( " Per-mesh listing across every zone in a project (sorted by triangle count) \n " ) ;
std : : printf ( " --info-project-models-total <projectDir> [--json] \n " ) ;
std : : printf ( " Aggregate WOM/WOB stats across an entire project (per-zone breakdown + totals) \n " ) ;
std : : printf ( " --info-wob <wob-base> [--json] \n " ) ;
std : : printf ( " Print WOB building metadata (groups, portals, doodads) and exit \n " ) ;
2026-05-09 10:57:22 -07:00
std : : printf ( " --info-wob-stats <wob-base> [--weld <eps>] [--json] \n " ) ;
std : : printf ( " Per-group + aggregate geometric stats (surface area, edges, watertight) for a WOB building \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " --info-woc <woc-path> [--json] \n " ) ;
std : : printf ( " Print WOC collision metadata (triangle counts, bounds) and exit \n " ) ;
2026-05-09 13:52:07 -07:00
std : : printf ( " --info-wol <wol-base> [--json] \n " ) ;
std : : printf ( " Print WOL lighting keyframes (zone name + per-time-of-day ambient/directional/fog) and exit \n " ) ;
feat(pipeline): add WOL validation + time-of-day sampling
Three additions to the Wowee Open Light format that landed
last commit:
• WoweeLightLoader::sampleAtTime(light, timeMin) returns
the linearly-interpolated keyframe at any time-of-day,
correctly handling wrap-around between the last keyframe
and the first (e.g. 21:00 blends from dusk toward
midnight by going forward through 00:00).
• --validate-wol <wol-base> [--json] walks every keyframe
and reports structural problems: time bounds (must be
[0, 1440)), strict-ascending sort order, fogEnd >
fogStart, finite color components. Exit code 0 PASS /
1 FAIL — CI-friendly.
• --info-wol-at <wol-base> <HH:MM|minutes> samples the
interpolated state at a specific time of day. Useful
for previewing what the renderer would feed in at a
given moment, debugging keyframe gaps, or previewing
a sub-range of the cycle.
Smoke-tested: dawn-to-midnight blend at 03:00 yields a
plausible mid-fade ambient (0.18, 0.16, 0.15) and dusk-to-
midnight wrap at 21:00 yields the symmetric (0.19, 0.145,
0.14). The default 4-keyframe day/night cycle from
makeDefaultDayNight passes --validate-wol cleanly.
2026-05-09 13:54:57 -07:00
std : : printf ( " --info-wol-at <wol-base> <HH:MM|minutes> \n " ) ;
std : : printf ( " Sample the WOL's interpolated lighting at a specific time-of-day (linear blend between keyframes) \n " ) ;
std : : printf ( " --validate-wol <wol-base> [--json] \n " ) ;
std : : printf ( " Walk every keyframe; check time bounds + sort order + fogEnd > fogStart + finite color components \n " ) ;
2026-05-09 13:52:07 -07:00
std : : printf ( " --gen-light <wol-base> [zoneName] \n " ) ;
std : : printf ( " Emit a starter .wol with the canonical 4-keyframe day/night cycle (midnight + dawn + noon + dusk) \n " ) ;
2026-05-09 14:01:26 -07:00
std : : printf ( " --gen-light-cave <wol-base> [zoneName] \n " ) ;
std : : printf ( " Emit a single-keyframe .wol with dim cool ambient + heavy short-range fog (cave / mine interior) \n " ) ;
std : : printf ( " --gen-light-dungeon <wol-base> [zoneName] \n " ) ;
std : : printf ( " Emit a single-keyframe .wol with warm torchlit ambient + medium fog (dungeon / crypt interior) \n " ) ;
std : : printf ( " --gen-light-night <wol-base> [zoneName] \n " ) ;
std : : printf ( " Emit a single-keyframe .wol with moonlit directional + far fog (always-night zone / shadow realm) \n " ) ;
2026-05-09 14:18:14 -07:00
std : : printf ( " --export-wol-json <wol-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wol to a human-editable JSON sidecar (defaults to <base>.wol.json) \n " ) ;
std : : printf ( " --import-wol-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wol.json sidecar back into binary .wol (round-trip with --export-wol-json) \n " ) ;
2026-05-09 14:25:41 -07:00
std : : printf ( " --export-wow-json <wow-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wow to a human-editable JSON sidecar (defaults to <base>.wow.json) \n " ) ;
std : : printf ( " --import-wow-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wow.json sidecar back into binary .wow (accepts type-name string OR typeId int) \n " ) ;
feat(pipeline): add Wowee Open Weather (.wow) zone schedule
8th open-format addition to the Wowee pipeline. Replaces
WoW's WeatherTypes.dbc / WeatherEffect logic with a single
binary file holding a list of weather states for one zone,
each tagged with intensity bounds, a probability weight,
and duration bounds. The renderer / runtime samples one
entry at a time using weighted-random selection, drives
it for a uniform-random duration in [min, max] sec, then
re-rolls.
• Types: Clear / Rain / Snow / Storm / Sandstorm / Fog /
Blizzard (extensible enum).
• Binary format: magic "WOWA", version 1, name, N entries
each storing (typeId, minIntensity, maxIntensity, weight,
minDurationSec, maxDurationSec).
CLI:
• --info-wow <wow-base> [--json] — inspect a WOW
• --gen-weather-temperate — clear + rain + fog (forest)
• --gen-weather-arctic — snow + blizzard + fog (tundra)
• --gen-weather-desert — clear + sandstorm (dunes)
• --gen-weather-stormy — rain + storm + occasional clear
The 8th open format complementing the rest:
M2 → WOM | WMO → WOB | WMO collision → WOC | ADT → WOT
DBC → JsonDBC | BLP → PNG | Light.dbc → WOL | WeatherTypes.dbc → WOW
Smoke-tested all 4 presets + JSON output. Each preset reads
back identically with the expected entry count and weight
distribution.
2026-05-09 14:10:13 -07:00
std : : printf ( " --info-wow <wow-base> [--json] \n " ) ;
std : : printf ( " Print WOW weather entries (zone + per-state type / intensity / weight / duration) and exit \n " ) ;
2026-05-09 14:13:30 -07:00
std : : printf ( " --validate-wow <wow-base> [--json] \n " ) ;
std : : printf ( " Walk every WOW entry; check typeId / intensity bounds [0,1] / weight > 0 / duration min ≤ max \n " ) ;
2026-05-09 14:34:22 -07:00
std : : printf ( " --validate-wom <wom-base> [--json] \n " ) ;
std : : printf ( " Static sanity checks on .wom: index range, bone refs, bound box, batch coverage, animation track count \n " ) ;
2026-05-09 14:38:05 -07:00
std : : printf ( " --gen-world-map <womx-base> [mapName] \n " ) ;
std : : printf ( " Emit .womx world-tile manifest: 64x64 continent grid with all tiles present (open WDT replacement) \n " ) ;
std : : printf ( " --gen-world-map-instance <womx-base> [mapName] \n " ) ;
std : : printf ( " Emit .womx world-tile manifest: 4x4 instance grid (small-world / dungeon scale) \n " ) ;
std : : printf ( " --gen-world-map-arena <womx-base> [mapName] \n " ) ;
std : : printf ( " Emit .womx world-tile manifest: 1x1 single-tile arena (smallest valid world) \n " ) ;
std : : printf ( " --info-womx <womx-base> [--json] \n " ) ;
std : : printf ( " Print WOMX manifest (worldType / gridSize / tilesPresent / defaultLightId / defaultWeatherId) \n " ) ;
std : : printf ( " --validate-womx <womx-base> [--json] \n " ) ;
std : : printf ( " Static checks on .womx: gridSize 1..128, worldType in range, tileBitmap matches expected size \n " ) ;
feat(editor): add WOMX JSON round-trip authoring workflow
Mirrors the WOL/WOW JSON pair from earlier batches: gives
hand-editable access to .womx world-map manifests for
quick tile-bitmap edits without writing a binary patcher.
Tile bitmap is represented as a JSON array of '1'/'0' row
strings — one string per row of the grid. Visual layout
makes missing-row patterns obvious at a glance:
"tiles": [
"10000001",
"01000010",
"00100100",
"00011000",
...
]
Sparse [[x,y]] pair arrays were considered but rejected:
4× larger for a full continent (4096 tiles), and the dense
visual layout is far easier to spot-read for typical
edits like "carve out a hole in this region".
The importer tolerates missing optional fields (uses
WoweeWorldMap defaults), and accepts either worldType
int or worldTypeName string so JSON can be authored by
hand or by tools.
Verified byte-identical round-trip on a 4x4 instance and
a hand-authored 8x8 sparse continent (16/64 tiles, both
defaultLightId and defaultWeatherId preserved through the
JSON layer).
Adds 2 flags to reach 458 documented kArgRequired entries.
All 9 open formats now have established CLI tooling — WOM,
WOB, WOC, WOT, JsonDBC, PNG, WOL, WOW, and WOMX.
2026-05-09 14:39:47 -07:00
std : : printf ( " --export-womx-json <womx-base> [out.json] \n " ) ;
std : : printf ( " Export binary .womx to a human-editable JSON sidecar (rows of '1'/'0' strings, easy to hand-edit) \n " ) ;
std : : printf ( " --import-womx-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .womx.json sidecar back into binary .womx (round-trip with --export-womx-json) \n " ) ;
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
std : : printf ( " --gen-sound-catalog <wsnd-base> [name] \n " ) ;
std : : printf ( " Emit .wsnd starter catalog (one entry per kind: sfx/music/ambient/ui/voice/spell/combat) \n " ) ;
std : : printf ( " --gen-sound-catalog-ambient <wsnd-base> [name] \n " ) ;
std : : printf ( " Emit .wsnd wilderness catalog: looped birds + wind + 3 footstep variants \n " ) ;
std : : printf ( " --gen-sound-catalog-tavern <wsnd-base> [name] \n " ) ;
std : : printf ( " Emit .wsnd tavern catalog: fire-crackle + crowd murmur + drink-clink + door-creak + lute music \n " ) ;
std : : printf ( " --info-wsnd <wsnd-base> [--json] \n " ) ;
std : : printf ( " Print WSND catalog entries (id / kind / flags / volume / 3D distances / file path / label) \n " ) ;
std : : printf ( " --validate-wsnd <wsnd-base> [--json] \n " ) ;
std : : printf ( " Static checks: kind in 0..6, finite distances, 3D needs max>min>=0, no duplicate sound IDs \n " ) ;
feat(editor): add WSND JSON round-trip authoring workflow
Closes the WSND open-format loop with --export-wsnd-json /
--import-wsnd-json, mirroring the WOL/WOW/WOMX JSON pairs
from earlier batches.
Each entry round-trips all 9 fields:
soundId, kind (int + kindName string), flags (int +
flagsList string array), volume, minDistance, maxDistance,
filePath, label.
Both kind and flags are emitted in dual form (int + named):
• kind : 2,
kindName : "ambient",
• flags : 3,
flagsList: ["loop", "3d"]
The importer accepts either form per field, so a hand-author
can write only the named string forms and skip the integer
boilerplate. Missing optional fields fall back to
WoweeSound::Entry defaults.
Verified byte-identical round-trip on the tavern preset
(5 entries with mixed flags and 3D distances).
Adds 2 flags (467 kArgRequired entries total). All 4 binary
formats added in recent batches now have full JSON round-trip:
WOL, WOW, WOMX, WSND.
2026-05-09 14:51:44 -07:00
std : : printf ( " --export-wsnd-json <wsnd-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsnd to a human-editable JSON sidecar (defaults to <base>.wsnd.json) \n " ) ;
std : : printf ( " --import-wsnd-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsnd.json sidecar back into binary .wsnd (accepts either kind int OR kindName string) \n " ) ;
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
std : : printf ( " --gen-spawns <wspn-base> [name] \n " ) ;
std : : printf ( " Emit .wspn starter spawn catalog: 1 creature + 1 game object + 1 doodad near origin \n " ) ;
std : : printf ( " --gen-spawns-camp <wspn-base> [name] \n " ) ;
std : : printf ( " Emit .wspn bandit-camp catalog: 4 creatures around a wander ring + 1 chest + 2 tents \n " ) ;
std : : printf ( " --gen-spawns-village <wspn-base> [name] \n " ) ;
std : : printf ( " Emit .wspn village catalog: 6 friendly NPCs (mixed roles) + 2 signs + 4 corner trees \n " ) ;
std : : printf ( " --info-wspn <wspn-base> [--json] \n " ) ;
std : : printf ( " Print WSPN spawn entries (kind / entryId / position / respawn / wander radius / label) \n " ) ;
std : : printf ( " --validate-wspn <wspn-base> [--json] \n " ) ;
std : : printf ( " Static checks: kind 0..2, finite position/scale/wander, doodads have respawn=0, no orphan entryId=0 \n " ) ;
feat(editor): add WSPN JSON round-trip authoring workflow
Closes the WSPN open-format loop with --export-wspn-json /
--import-wspn-json, mirroring the WOL/WOW/WOMX/WSND JSON
pairs from earlier batches. All 5 binary formats added in
recent batches now have full JSON round-trip authoring.
Each entry round-trips all 12 fields:
kind (int + kindName string), entryId, position[3],
rotation[3], scale, flags (int + flagsList string array),
respawnSec, factionId, questIdRequired, wanderRadius,
label.
Vector fields are emitted as 3-element arrays for natural
JSON layout. Both kind and flags are emitted in dual form
(int + named) so a hand-author can write the named string
forms and skip the integer boilerplate. Missing optional
fields fall back to WoweeSpawns::Entry defaults.
Verified byte-identical round-trip on the village preset
(12 entries: 6 creature + 2 object + 4 doodad). The
position vec3 round-trips through floats with no precision
loss for the typical small-coordinate test cases.
Adds 2 flags (475 kArgRequired entries total).
2026-05-09 14:59:48 -07:00
std : : printf ( " --export-wspn-json <wspn-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wspn to a human-editable JSON sidecar (defaults to <base>.wspn.json) \n " ) ;
std : : printf ( " --import-wspn-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wspn.json sidecar back into binary .wspn (accepts either kind int OR kindName string) \n " ) ;
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
std : : printf ( " --gen-items <wit-base> [name] \n " ) ;
std : : printf ( " Emit .wit starter item catalog: 1 weapon + 1 chest + 1 potion + 1 quest item \n " ) ;
std : : printf ( " --gen-items-weapons <wit-base> [name] \n " ) ;
std : : printf ( " Emit .wit weapon catalog: 5 entries spanning common -> legendary, both 1H and 2H \n " ) ;
std : : printf ( " --gen-items-armor <wit-base> [name] \n " ) ;
std : : printf ( " Emit .wit full mail-armor set: head + chest + legs + feet + hands + cloak (BoE) \n " ) ;
std : : printf ( " --info-wit <wit-base> [--json] \n " ) ;
std : : printf ( " Print WIT item entries (id / ilvl / quality / class / slot / buy price / name) \n " ) ;
std : : printf ( " --validate-wit <wit-base> [--json] \n " ) ;
std : : printf ( " Static checks: itemId>0 + unique, weapon damage>0 + min<=max, equippable durability>0, sell<buy \n " ) ;
2026-05-09 15:13:26 -07:00
std : : printf ( " --export-wit-json <wit-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wit to a human-editable JSON sidecar (defaults to <base>.wit.json) \n " ) ;
std : : printf ( " --import-wit-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wit.json sidecar back into binary .wit (accepts quality/class/slot int OR name string) \n " ) ;
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
std : : printf ( " --gen-loot <wlot-base> [name] \n " ) ;
std : : printf ( " Emit .wlot starter loot catalog: 1 creature with 1 drop slot, 1 item @ 50%%, 0..50 copper \n " ) ;
std : : printf ( " --gen-loot-bandit <wlot-base> [name] \n " ) ;
std : : printf ( " Emit .wlot bandit loot table: dropCount=2, 4 candidate items, 5..50 copper \n " ) ;
std : : printf ( " --gen-loot-boss <wlot-base> [name] \n " ) ;
std : : printf ( " Emit .wlot elite boss table: dropCount=4, 6 candidates incl. quest item + group-only epic, 50..200 silver \n " ) ;
std : : printf ( " --info-wlot <wlot-base> [--json] \n " ) ;
std : : printf ( " Print WLOT loot tables (creatureId / dropCount / money range / per-drop chance + qty + flags) \n " ) ;
std : : printf ( " --validate-wlot <wlot-base> [--json] \n " ) ;
std : : printf ( " Static checks: creatureId>0 + unique, chance in 0..100, minQty<=maxQty, money min<=max \n " ) ;
feat(editor): add WLOT JSON round-trip authoring workflow
Closes the WLOT open-format loop with --export-wlot-json /
--import-wlot-json, mirroring the WOL/WOW/WOMX/WSND/WSPN/WIT
JSON pairs. All 7 binary formats added since WOL now have
full JSON round-trip authoring.
Each loot table round-trips:
• table-level: creatureId, flags (int + flagsList strings),
dropCount, money min/max (copper)
• per-drop: itemId, chancePercent (float),
minQty / maxQty, flags (int + flagsList)
Both flag fields emit dual int + named string-array forms.
A hand-author can write ["quest", "always"] instead of
having to remember that QuestRequired|AlwaysDrop = 5.
Verified byte-identical round-trip on the boss preset
(6 drops including the QuestRequired+AlwaysDrop combo on
the guaranteed quest item, group-only epic at 5%, mass-loot
trade goods at 90%).
Adds 2 flags (495 documented total now).
2026-05-09 15:20:05 -07:00
std : : printf ( " --export-wlot-json <wlot-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wlot to a human-editable JSON sidecar (defaults to <base>.wlot.json) \n " ) ;
std : : printf ( " --import-wlot-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wlot.json sidecar back into binary .wlot (accepts flag int OR flagsList strings) \n " ) ;
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
std : : printf ( " --gen-creatures <wcrt-base> [name] \n " ) ;
std : : printf ( " Emit .wcrt starter creature template: 1 friendly innkeeper (vendor + repair flags) \n " ) ;
std : : printf ( " --gen-creatures-bandit <wcrt-base> [name] \n " ) ;
std : : printf ( " Emit .wcrt bandit (creatureId=1000, matches WSPN camp + WLOT bandit table, equips WIT sword) \n " ) ;
std : : printf ( " --gen-creatures-merchants <wcrt-base> [name] \n " ) ;
std : : printf ( " Emit .wcrt 3-NPC village set (innkeeper / smith / alchemist, matches WSPN village creatureIds) \n " ) ;
std : : printf ( " --info-wcrt <wcrt-base> [--json] \n " ) ;
std : : printf ( " Print WCRT entries (id / level / hp / type / faction / npc-flags / name + subname) \n " ) ;
std : : printf ( " --validate-wcrt <wcrt-base> [--json] \n " ) ;
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
std : : printf ( " Static checks: creatureId>0+unique, level/hp>0, min<=max, attackSpeed>0, behavior flag conflicts \n " ) ;
2026-05-09 15:27:12 -07:00
std : : printf ( " --export-wcrt-json <wcrt-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wcrt to a human-editable JSON sidecar (defaults to <base>.wcrt.json) \n " ) ;
std : : printf ( " --import-wcrt-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wcrt.json sidecar back into binary .wcrt (accepts type/family/flag int OR name forms) \n " ) ;
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
std : : printf ( " --gen-quests <wqt-base> [name] \n " ) ;
std : : printf ( " Emit .wqt starter quest: 'Kill 10 Defias Bandits' giver=4001 (matches WCRT village innkeeper) \n " ) ;
std : : printf ( " --gen-quests-chain <wqt-base> [name] \n " ) ;
std : : printf ( " Emit .wqt 3-quest chain: Investigate -> Recover -> Report (chained via prev/next questId) \n " ) ;
std : : printf ( " --gen-quests-daily <wqt-base> [name] \n " ) ;
std : : printf ( " Emit .wqt daily repeatable quest with the Daily + Repeatable + AutoAccept flag combo \n " ) ;
std : : printf ( " --info-wqt <wqt-base> [--json] \n " ) ;
std : : printf ( " Print WQT entries (questId / level / giver / objectives / rewards / chain links) \n " ) ;
std : : printf ( " --validate-wqt <wqt-base> [--json] \n " ) ;
std : : printf ( " Static checks: questId>0+unique, level>0+min<=max, title not empty, no rewards warning, daily needs repeatable \n " ) ;
feat(editor): add WQT JSON round-trip authoring workflow
Closes the WQT open-format loop with --export-wqt-json /
--import-wqt-json, mirroring the WOL/WOW/WOMX/WSND/WSPN/
WIT/WLOT/WCRT JSON pairs. All 9 binary formats added since
WOL now have full JSON round-trip authoring.
Each quest round-trips:
• 13 scalar fields (id, level range, masks, chain links,
giver/turnin, xp + money reward, flags)
• 3 string fields (title, objective, description)
• objectives array with dual int + name kindName
• rewardItems array with dual int + name pickFlagsList
The flag bitset emits string-array form so a hand-author can
write ["daily", "repeatable", "auto-accept"] instead of
having to remember the bit math. The objective kindName
makes "visit/collect/kill" obvious without needing to know
that kind=3 means VisitArea.
Verified byte-identical round-trip on the 3-quest chain
preset (full feature exercise: prev/next chain links,
mixed objective kinds, AutoComplete bridge quest, player-
choice rewards). Adds 2 flags (509 documented total now).
2026-05-09 15:33:21 -07:00
std : : printf ( " --export-wqt-json <wqt-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wqt to a human-editable JSON sidecar (defaults to <base>.wqt.json) \n " ) ;
std : : printf ( " --import-wqt-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wqt.json sidecar back into binary .wqt (accepts kind/flag int OR name forms) \n " ) ;
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
std : : printf ( " --gen-objects <wgot-base> [name] \n " ) ;
std : : printf ( " Emit .wgot starter object catalog: 1 chest + 1 mailbox + 1 sign \n " ) ;
std : : printf ( " --gen-objects-dungeon <wgot-base> [name] \n " ) ;
std : : printf ( " Emit .wgot dungeon set: door + button + 2 chests (bandit + boss) + spike trap (cross-refs WLOT) \n " ) ;
std : : printf ( " --gen-objects-gather <wgot-base> [name] \n " ) ;
std : : printf ( " Emit .wgot gathering nodes: Peacebloom (herb) + Tin Vein (ore) + Schools of Fish, with skill reqs \n " ) ;
std : : printf ( " --info-wgot <wgot-base> [--json] \n " ) ;
std : : printf ( " Print WGOT entries (objectId / type / lock / loot / required skill / name) \n " ) ;
std : : printf ( " --validate-wgot <wgot-base> [--json] \n " ) ;
std : : printf ( " Static checks: objectId>0+unique, size>0, time min<=max, gathering needs skill, chest warns on no loot \n " ) ;
2026-05-09 15:39:50 -07:00
std : : printf ( " --export-wgot-json <wgot-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgot to a human-editable JSON sidecar (defaults to <base>.wgot.json) \n " ) ;
std : : printf ( " --import-wgot-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgot.json sidecar back into binary .wgot (accepts type/flag int OR name forms) \n " ) ;
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
std : : printf ( " --gen-factions <wfac-base> [name] \n " ) ;
std : : printf ( " Emit .wfac starter: 3 factions (Friendly id=35 / Hostile id=14 / Player id=1) matching WCRT defaults \n " ) ;
std : : printf ( " --gen-factions-alliance <wfac-base> [name] \n " ) ;
std : : printf ( " Emit .wfac Alliance set: header + Stormwind + Darnassus + Ironforge (reciprocal friends) + Defias enemy \n " ) ;
std : : printf ( " --gen-factions-wildlife <wfac-base> [name] \n " ) ;
std : : printf ( " Emit .wfac wildlife: wolves + bears + spiders + kobolds (each hostile to player, ignores other beasts) \n " ) ;
std : : printf ( " --info-wfac <wfac-base> [--json] \n " ) ;
std : : printf ( " Print WFAC entries (id / parent / flags / enemy + friend counts / name) \n " ) ;
std : : printf ( " --validate-wfac <wfac-base> [--json] \n " ) ;
std : : printf ( " Static checks: factionId>0+unique, name not empty, threshold ordering, no self-enemy, no enemy/friend overlap \n " ) ;
2026-05-09 15:45:58 -07:00
std : : printf ( " --export-wfac-json <wfac-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wfac to a human-editable JSON sidecar (defaults to <base>.wfac.json) \n " ) ;
std : : printf ( " --import-wfac-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wfac.json sidecar back into binary .wfac (accepts flag int OR flagsList strings) \n " ) ;
feat(pipeline): add WLCK (Wowee Lock Template) format
Novel open replacement for Blizzard's Lock.dbc. The 18th
open format added to the editor. Closes the cross-reference
gap from WGOT.entry.lockId — until now that field pointed
to a format that didn't exist yet.
A lock is a multi-channel security check. Each lock has up
to 5 independent channels; a player can open the lock by
satisfying ANY ONE channel:
• Item — requires a specific key item (WIT cross-ref)
• Lockpick — requires the lockpicking skill at minimum rank
(rogue / engineering profession)
• Spell — requires casting a specific spell
• Damage — can be forced open with attack damage
Cross-references with previously-added formats:
WGOT.entry.lockId -> WLCK.entry.lockId
WLCK.channel.targetId (Item) -> WIT.entry.itemId
WLCK.channel.targetId (Lockpick) -> future WSKL skillId
WLCK.channel.targetId (Spell) -> future WSPL spellId
The starter and dungeon presets' lockIds (1 and 2)
deliberately match WGOT.makeDungeon's iron-door lockId=1
and bandit-strongbox lockId=2, so the demo content stack
already wires together: WSPN spawn -> WGOT object template
-> WLCK lock template -> WIT key items.
Format:
• magic "WLCK", version 1, little-endian
• per lock: lockId / name / flags / 5 fixed channel slots
• per channel: kind / skillRequired / targetId
• all 5 slots written even when unused (kind=None +
zeroed fields), keeping the per-entry size constant for
fast random access
Enums:
• ChannelKind: None / Item / Lockpick / Spell / Damage
• Flags: DestructOnOpen / RespawnOnKey / TrapOnFail
API: WoweeLockLoader::save / load / exists / findById;
presets makeStarter (Iron Door + Wooden Chest), makeDungeon
(matches WGOT cross-references; light/heavy lockpicks +
boss-key-only seal), makeProfessions (4-tier rogue lockpick
progression at ranks 1/100/175/250).
CLI added (5 flags, 521 documented total now):
--gen-locks / --gen-locks-dungeon / --gen-locks-professions
--info-wlck / --validate-wlck
Validator catches: lockId=0 + duplicates, all-None channels
(lock can never open), Item/Spell/Lockpick channels with
targetId=0 (no resource referenced), unknown channel kind,
skillRequired set on non-Lockpick channel (silently ignored
at runtime — flag as warning).
2026-05-09 15:44:26 -07:00
std : : printf ( " --gen-locks <wlck-base> [name] \n " ) ;
std : : printf ( " Emit .wlck starter: 2 locks (Iron Door key+force, Wooden Chest force-only) — lockId=1 matches WGOT \n " ) ;
std : : printf ( " --gen-locks-dungeon <wlck-base> [name] \n " ) ;
std : : printf ( " Emit .wlck dungeon set: light/heavy lockpicks (lockId=2 matches WGOT bandit chest), boss-key seal \n " ) ;
std : : printf ( " --gen-locks-professions <wlck-base> [name] \n " ) ;
std : : printf ( " Emit .wlck profession-keyed locks at lockpick rank 1/100/175/250 (junkbox tier progression) \n " ) ;
std : : printf ( " --info-wlck <wlck-base> [--json] \n " ) ;
std : : printf ( " Print WLCK lock entries with per-channel detail (kind / target / required skill rank) \n " ) ;
std : : printf ( " --validate-wlck <wlck-base> [--json] \n " ) ;
std : : printf ( " Static checks: lockId>0+unique, at least 1 active channel, item/spell/lockpick need targetId \n " ) ;
2026-05-09 15:52:20 -07:00
std : : printf ( " --export-wlck-json <wlck-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wlck to a human-editable JSON sidecar (defaults to <base>.wlck.json) \n " ) ;
std : : printf ( " --import-wlck-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wlck.json sidecar back into binary .wlck (accepts kind/flag int OR name forms) \n " ) ;
feat(pipeline): add WSKL (Wowee Skill Catalog) format
Novel open replacement for Blizzard's SkillLine.dbc +
SkillLineCategory.dbc + the AzerothCore-style player skill
base tables. The 19th open format added to the editor.
Defines every player-trackable skill: weapon proficiencies
(Swords, Axes, Bows), professions (Mining, Alchemy,
Cooking), languages (Common, Dwarvish), class
specializations (Fire, Frost, Holy, Protection), armor
proficiencies (Mail, Plate), and secondary skills (First
Aid, Lockpicking, Riding).
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Lockpick) -> WSKL.entry.skillId
WGOT.entry.requiredSkill -> WSKL.entry.skillId
The starter preset's skillIds 186 (Mining) and 633
(Lockpicking) deliberately match the canonical IDs already
referenced by WGOT.makeGather and WLCK.makeDungeon —
so the demo content stack now wires together end-to-end:
WGOT herb-node requires skill 186 -> WSKL Mining at rank 1+;
WLCK bandit-strongbox channel requires skill 633 -> WSKL
Lockpicking at rank 1+.
Format:
• magic "WSKL", version 1, little-endian
• per skill: skillId / name / description / categoryId /
canTrain / maxRank / rankPerLevel / iconPath
Enums:
• CategoryId (8): Weapon / Class / Profession /
SecondaryProfession / Language / ArmorProficiency /
Riding / WeaponSpec
API: WoweeSkillLoader::save / load / exists / findById;
presets makeStarter (5-skill demo with cross-referenced
canonical IDs), makeProfessions (12 classic professions:
9 primary + 3 secondary), makeWeapons (16 weapon skills
with canonical SkillLine IDs and rankPerLevel=5 auto-grow).
CLI added (5 flags, 528 documented total now):
--gen-skills / --gen-skills-professions / --gen-skills-weapons
--info-wskl / --validate-wskl
Validator catches: skillId=0 + duplicates, empty name,
maxRank=0, unknown categoryId, suspicious maxRank=1 on
non-Language skill (only languages cap at 1), weapon skill
with rankPerLevel=0 (won't auto-grow on use).
2026-05-09 15:50:25 -07:00
std : : printf ( " --gen-skills <wskl-base> [name] \n " ) ;
std : : printf ( " Emit .wskl starter: Swords + Common + First Aid + Mining (id=186) + Lockpicking (id=633) — matches WGOT/WLCK \n " ) ;
std : : printf ( " --gen-skills-professions <wskl-base> [name] \n " ) ;
std : : printf ( " Emit .wskl 12 classic professions (9 primary + 3 secondary) with canonical SkillLine IDs \n " ) ;
std : : printf ( " --gen-skills-weapons <wskl-base> [name] \n " ) ;
std : : printf ( " Emit .wskl all 16 weapon skills with rankPerLevel=5 auto-grow (use-trained, not trainer-trained) \n " ) ;
std : : printf ( " --info-wskl <wskl-base> [--json] \n " ) ;
std : : printf ( " Print WSKL entries (id / category / max rank / per-level grow / trainer-required / name) \n " ) ;
std : : printf ( " --validate-wskl <wskl-base> [--json] \n " ) ;
std : : printf ( " Static checks: skillId>0+unique, name not empty, maxRank>0, weapon needs rankPerLevel>0 \n " ) ;
2026-05-09 15:59:20 -07:00
std : : printf ( " --export-wskl-json <wskl-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wskl to a human-editable JSON sidecar (defaults to <base>.wskl.json) \n " ) ;
std : : printf ( " --import-wskl-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wskl.json sidecar back into binary .wskl (accepts category int OR categoryName string) \n " ) ;
feat(pipeline): add WSPL (Wowee Spell Catalog) format
Novel open replacement for Blizzard's Spell.dbc +
SpellEffect.dbc + the AzerothCore-style spell_dbc /
spell_proc tables. The 20th open format added to the
editor — completes the canonical-data side of the gameplay
graph.
Each entry holds the metadata side of a spell: name,
description, school, range, mana / cast / cooldown times,
plus a single primary effect. The simplified effect model
(one effectKind + min/max value + misc field) covers the
common cases (damage / heal / buff / debuff / teleport /
summon / dispel) without needing to reproduce the full
multi-effect graph that classic Spell.dbc carries.
Cross-references with previously-added formats:
WLCK.channel.targetId (kind=Spell) -> WSPL.entry.spellId
WQT.objective.targetId (kind=SpellCast) -> WSPL.entry.spellId
WCRT.equippedMain (item with on-use) -> WIT -> WSPL
Format:
• magic "WSPL", version 1, little-endian
• per spell: spellId / name / description / iconPath /
school / targetType / effectKind / cast & cooldown &
GCD ms / manaCost / range min..max / minLevel /
maxStacks / durationMs / effectValueMin..Max /
effectMisc / flags
Enums:
• School (7): Physical / Holy / Fire / Nature / Frost /
Shadow / Arcane
• TargetType (6): Self / Single / Cone / AoeFromSelf /
Line / Ground
• EffectKind (7): Damage / Heal / Buff / Debuff / Teleport /
Summon / Dispel
• Flags: Passive / Hidden / Channeled / Ranged /
AreaOfEffect / Triggered / UnitTargetOnly /
FriendlyOnly / HostileOnly
API: WoweeSpellLoader::save / load / exists / findById;
presets makeStarter (Strike + Lesser Heal + Power Word:
Fortitude + Hearthstone, one per major effect kind),
makeMage (Frostbolt 116 + Fireball 133 + Arcane Intellect
1459 + Blink 1953, canonical Classic spellIds), makeWarrior
(Heroic Strike 78 + Thunder Clap 6343 + Battle Shout 6673 +
Mortal Strike 12294).
CLI added (5 flags, 535 documented total now):
--gen-spells / --gen-spells-mage / --gen-spells-warrior
--info-wspl / --validate-wspl
Validator catches: spellId=0 + duplicates, empty name,
school out of range, effectKind out of range, NaN range,
range/value min>max, FriendlyOnly+HostileOnly conflict
(incoherent), friendly-only with damage/debuff effect
(incoherent), hostile-only with heal/buff effect, buff/debuff
effect with durationMs=0 (instant fade — almost certainly
authoring oversight).
The validator caught a real preset-emitter authoring error
during initial smoke testing — buff spells were setting
effectValueMin without effectValueMax (validator's range
check immediately flagged it), prompting an in-batch fix
to set both fields. This is exactly the catch-the-typo
purpose validators serve.
2026-05-09 15:58:09 -07:00
std : : printf ( " --gen-spells <wspl-base> [name] \n " ) ;
std : : printf ( " Emit .wspl starter spell catalog: 4 spells covering damage / heal / buff / teleport effect kinds \n " ) ;
std : : printf ( " --gen-spells-mage <wspl-base> [name] \n " ) ;
std : : printf ( " Emit .wspl mage spell set: Frostbolt + Fireball + Arcane Intellect + Blink (canonical IDs 116/133/1459/1953) \n " ) ;
std : : printf ( " --gen-spells-warrior <wspl-base> [name] \n " ) ;
std : : printf ( " Emit .wspl warrior spell set: Heroic Strike + Thunder Clap + Battle Shout + Mortal Strike \n " ) ;
std : : printf ( " --info-wspl <wspl-base> [--json] \n " ) ;
std : : printf ( " Print WSPL spell entries (id / school / effect / cast/cd / mana / range / damage range / name) \n " ) ;
std : : printf ( " --validate-wspl <wspl-base> [--json] \n " ) ;
std : : printf ( " Static checks: spellId>0+unique, name not empty, school 0..6, range/value min<=max, friendly+hostile incoherent \n " ) ;
2026-05-09 16:06:29 -07:00
std : : printf ( " --export-wspl-json <wspl-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wspl to a human-editable JSON sidecar (defaults to <base>.wspl.json) \n " ) ;
std : : printf ( " --import-wspl-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wspl.json sidecar back into binary .wspl (accepts school/target/effect/flag int OR name forms) \n " ) ;
feat(pipeline): add WACH (Wowee Achievement Catalog) format
Novel open replacement for Blizzard's Achievement.dbc +
AchievementCriteria.dbc + AchievementCategory.dbc + the
AzerothCore-style character_achievement /
character_achievement_progress SQL tables. The 21st open
format added to the editor.
Each achievement carries display metadata (name, description,
icon, points, faction restriction) plus a list of criteria
the player must satisfy. Criteria mirror the WQT objective
model (kind + targetId + quantity), so the runtime can
reuse the same progress-tracking machinery for both quests
and achievements.
Cross-references with previously-added formats — every
criterion kind has a real format target:
WACH.criteria.targetId (kind=KillCreature) -> WCRT.creatureId
WACH.criteria.targetId (kind=CompleteQuest) -> WQT.questId
WACH.criteria.targetId (kind=LootItem) -> WIT.itemId
WACH.criteria.targetId (kind=CastSpell) -> WSPL.spellId
WACH.criteria.targetId (kind=ReachSkillLevel) -> WSKL.skillId
WACH.criteria.targetId (kind=EarnReputation) -> WFAC.factionId
WACH.criteria.targetId (kind=CompleteAchievement) -> WACH.achievementId
(meta-achievements)
Format:
• magic "WACH", version 1, little-endian
• per achievement: id / categoryId / name / description /
iconPath / titleReward / points / minLevel / faction /
flags / criteria[]
• per criterion: criteriaId / kind / targetId / quantity /
description
Enums:
• CriteriaKind (9): KillCreature / CompleteQuest / LootItem /
ReachLevel / EarnReputation / CastSpell /
ReachSkillLevel / VisitArea /
CompleteAchievement
• Faction: Both / Alliance / Horde
• Flags: HiddenUntilEarned / ServerFirst / RealmFirst /
Tracking / Counter / Account
API: WoweeAchievementLoader::save / load / exists /
findById; presets makeStarter (3 simple kill/quest/level
demos), makeBandit (3 with WCRT/WGOT/WQT cross-refs),
makeMeta (3 base + 1 meta-achievement granting "the
Versatile" title, exercising CompleteAchievement criterion
kind that lets achievements depend on other achievements).
CLI added (5 flags, 542 documented total now):
--gen-achievements / --gen-achievements-bandit / --gen-achievements-meta
--info-wach / --validate-wach
Validator catches: achievementId=0 + duplicates, empty name,
faction out of range, no criteria (achievement can never
be earned), criterion quantity=0, unknown criterion kind,
targetId=0 on criterion kinds that need a real resource
reference (everything except ReachLevel which uses the
quantity field for the level number).
The bandit preset's cross-references close the gameplay
graph end-to-end: kill 50 creatureId=1000 (matches WCRT/
WSPN/WLOT bandit), loot objectId=2000 (matches WGOT bandit
strongbox), complete questId=1 (matches WQT Bandit Trouble).
The meta preset closes a separate loop: 3 sub-achievements
covering Mining (skillId=186), Lockpicking (skillId=633),
and Frostbolt cast count (spellId=116) — each pointing at
a real WSKL/WSPL entry that already exists in the demo
content stack.
2026-05-09 16:04:30 -07:00
std : : printf ( " --gen-achievements <wach-base> [name] \n " ) ;
std : : printf ( " Emit .wach starter: 3 achievements (First Blood / Helping Hand / Coming of Age) \n " ) ;
std : : printf ( " --gen-achievements-bandit <wach-base> [name] \n " ) ;
std : : printf ( " Emit .wach bandit-themed: 3 achievements with cross-refs to WCRT/WGOT/WQT bandit IDs \n " ) ;
std : : printf ( " --gen-achievements-meta <wach-base> [name] \n " ) ;
std : : printf ( " Emit .wach 3 base achievements + 1 meta-achievement (Jack of All Trades, title 'the Versatile') \n " ) ;
std : : printf ( " --info-wach <wach-base> [--json] \n " ) ;
std : : printf ( " Print WACH entries (id / points / faction / flags / criteria with kind+target+qty) \n " ) ;
std : : printf ( " --validate-wach <wach-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, faction 0..2, criteria need targetId+quantity>0 \n " ) ;
feat(editor): add WACH JSON round-trip authoring workflow
Closes the WACH open-format loop with --export-wach-json /
--import-wach-json, mirroring the JSON pairs added for
every other novel binary format. All 15 binary formats
added since WOL now have full JSON round-trip authoring.
Each achievement round-trips:
• 11 scalar fields (id, categoryId, name, description,
icon, titleReward, points, minLevel, faction, flags)
• criteria array with full per-criterion fields
Three enum-typed fields emit dual int + name forms so a
hand-author can use either:
• criterion.kind (kill/quest/loot/level/rep/cast/skill/visit/meta)
• faction (both/alliance/horde)
• flags (hidden/server-first/realm-first/tracking/...)
Verified byte-identical round-trip on the meta preset (4
achievements, 6 criteria including the 3 CompleteAchievement
criteria that wire the meta-achievement to its prerequisites).
Adds 2 flags (546 documented total now).
2026-05-09 16:07:53 -07:00
std : : printf ( " --export-wach-json <wach-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wach to a human-editable JSON sidecar (defaults to <base>.wach.json) \n " ) ;
std : : printf ( " --import-wach-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wach.json sidecar back into binary .wach (accepts kind/faction/flag int OR name forms) \n " ) ;
feat(pipeline): add WTRN (Wowee Trainer / Vendor catalog) format
Novel open replacement for AzerothCore-style npc_trainer +
npc_vendor SQL tables PLUS the Blizzard TrainerSpells.dbc
family. The 22nd open format added to the editor.
Unifies trainer spell lists and vendor item inventories
into one per-NPC entry. A creature flagged Trainer or
Vendor in WCRT references a WTRN entry that lists what they
teach / sell. The same NPC can be both — kindMask is a
bitmask covering the Trainer (0x01) and Vendor (0x02) kinds.
This format closes a major cross-format gap: WCRT.npcFlags
already had Vendor / Trainer bits, but until now there was
no format defining what a vendor sells or what a trainer
teaches. Now an NPC marked Vendor in WCRT has a real
inventory, and an NPC marked Trainer has a real spell list.
Cross-references — every WTRN field has a real format target:
WTRN.entry.npcId -> WCRT.entry.creatureId
WTRN.spell.spellId -> WSPL.entry.spellId
WTRN.spell.requiredSkillId -> WSKL.entry.skillId
WTRN.item.itemId -> WIT.entry.itemId
Format:
• magic "WTRN", version 1, little-endian
• per NPC: npcId / kindMask / greeting + spells[] + items[]
• per spell offer: spellId / moneyCostCopper /
requiredSkillId / requiredSkillRank / requiredLevel
• per item offer: itemId / stockCount (0xFFFFFFFF =
unlimited) / restockSec / extendedCost / moneyCostCopper
(0 = inherit from WIT.buyPrice)
API: WoweeTrainerLoader::save / load / exists / findByNpc;
presets makeStarter (innkeeper 4001 as both trainer +
vendor: teaches First Aid + sells starter items),
makeMageTrainer (NPC 4003 teaches the WSPL mage spells
at scaling cost), makeWeaponVendor (NPC 4002 sells WIT
weapons with mixed unlimited/finite stock + restock timers).
CLI added (5 flags, 551 documented total now):
--gen-trainers / --gen-trainers-mage / --gen-trainers-weapons
--info-wtrn / --validate-wtrn
Validator catches: npcId=0 + duplicates, kindMask=0 (NPC
offers nothing), Trainer flag without spells, Vendor flag
without items, spells/items present without the matching
kind bit (silently ignored at runtime), spellId=0 / itemId=0
in offers, finite stock with restockSec=0 (single-fill —
usually intentional but worth surfacing).
The 3 presets deliberately use npcIds matching WCRT village
merchants (4001/4002/4003) so the demo content stack is
self-consistent: WCRT 4001 has the Vendor + Trainer flag,
and WTRN 4001 actually defines what they sell and teach.
2026-05-09 16:12:58 -07:00
std : : printf ( " --gen-trainers <wtrn-base> [name] \n " ) ;
std : : printf ( " Emit .wtrn starter: 1 NPC (innkeeper 4001) acting as both vendor + trainer with WSKL/WIT cross-refs \n " ) ;
std : : printf ( " --gen-trainers-mage <wtrn-base> [name] \n " ) ;
std : : printf ( " Emit .wtrn mage trainer (npcId=4003): teaches Frostbolt/Fireball/Arcane Intellect/Blink at scaling cost \n " ) ;
std : : printf ( " --gen-trainers-weapons <wtrn-base> [name] \n " ) ;
std : : printf ( " Emit .wtrn weapon vendor (npcId=4002): 5 weapons with mixed unlimited/finite stock + restock timers \n " ) ;
std : : printf ( " --info-wtrn <wtrn-base> [--json] \n " ) ;
std : : printf ( " Print WTRN entries (npc / kind / spells with skill+level reqs / items with stock + restock) \n " ) ;
std : : printf ( " --validate-wtrn <wtrn-base> [--json] \n " ) ;
std : : printf ( " Static checks: npcId>0+unique, kindMask>0, Trainer needs spells, Vendor needs items, no orphan offers \n " ) ;
2026-05-09 16:14:50 -07:00
std : : printf ( " --export-wtrn-json <wtrn-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtrn to a human-editable JSON sidecar (defaults to <base>.wtrn.json) \n " ) ;
std : : printf ( " --import-wtrn-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtrn.json sidecar back into binary .wtrn (accepts kindMask int OR kindList string array) \n " ) ;
feat(pipeline): add WGSP (Wowee Gossip Menu) format
Novel open replacement for AzerothCore-style gossip_menu +
gossip_menu_option + npc_text SQL tables PLUS the Blizzard
NpcText.dbc family. The 23rd open format added to the
editor.
An NPC's dialogue tree: a menu of options the player can
pick from when right-clicking the NPC. Each option may
bridge to another menu, trigger a vendor / trainer
interaction, offer a quest, etc. The simplified per-option
model (kind + actionTarget + flags + moneyCost) covers the
common cases without needing separate npc_text condition
tables.
Closes a major cross-format gap: WCRT.entry.gossipId has
existed since batch 116 (when WCRT was added) but pointed
to a format that didn't exist yet. The innkeeper preset's
menuId=4001 deliberately matches WCRT's Bartleby NPC so
the demo content stack can wire WCRT.gossipId = 4001 once
that field is plumbed through the runtime.
Cross-references:
WCRT.entry.gossipId -> WGSP.entry.menuId
WGSP.option.actionTarget (Submenu) -> WGSP.entry.menuId
WGSP.option.actionTarget (Vendor / Trainer)
-> WTRN.entry.npcId
WGSP.option.actionTarget (Quest) -> WQT.entry.questId
Format:
• magic "WGSP", version 1, little-endian
• per menu: menuId / titleText + options[]
• per option: optionId / text / kind / actionTarget /
requiredFlags / moneyCostCopper
Enums:
• OptionKind (13): Close / Submenu / Vendor / Trainer /
Quest / Tabard / Banker / Innkeeper /
FlightMaster / TextOnly / Script /
Battlemaster / Auctioneer
• OptionFlags: AllianceOnly / HordeOnly / Coinpouch /
QuestGated / Closes
API: WoweeGossipLoader::save / load / exists / findById;
presets makeStarter (1 menu with vendor + trainer + close),
makeInnkeeper (2-menu tree: main menu 4001 with hearth /
vendor / flight / submenu options + lore submenu 4002 that
links back), makeQuestGiver (1 menu with 2 quest options
referencing WQT 1 and 100, plus a paid respec script
exercising the Coinpouch flag with a 10g cost).
CLI added (5 flags, 558 documented total now):
--gen-gossip / --gen-gossip-innkeeper / --gen-gossip-questgiver
--info-wgsp / --validate-wgsp
Validator catches: menuId=0 + duplicates, empty title /
options, unknown option kind, empty option text, Submenu
options pointing at non-existent menuIds (intra-format
cross-reference resolution), Coinpouch flag without
moneyCost (misleading UI), AllianceOnly+HordeOnly conflict.
2026-05-09 16:20:07 -07:00
std : : printf ( " --gen-gossip <wgsp-base> [name] \n " ) ;
std : : printf ( " Emit .wgsp starter: 1 menu with greeting + 3 options (vendor / trainer / close) \n " ) ;
std : : printf ( " --gen-gossip-innkeeper <wgsp-base> [name] \n " ) ;
std : : printf ( " Emit .wgsp 2-menu innkeeper tree (menuId=4001 closes WCRT.gossipId gap; submenu 4002 area lore) \n " ) ;
std : : printf ( " --gen-gossip-questgiver <wgsp-base> [name] \n " ) ;
std : : printf ( " Emit .wgsp questgiver menu: 2 quest options + bank + paid respec (Coinpouch flag, 10g) \n " ) ;
std : : printf ( " --info-wgsp <wgsp-base> [--json] \n " ) ;
std : : printf ( " Print WGSP entries (menuId / title / per-option kind / target / cost / flags) \n " ) ;
std : : printf ( " --validate-wgsp <wgsp-base> [--json] \n " ) ;
std : : printf ( " Static checks: menuId>0+unique, options non-empty, Submenu actionTarget exists, Coinpouch needs cost, faction conflict \n " ) ;
2026-05-09 16:28:12 -07:00
std : : printf ( " --export-wgsp-json <wgsp-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgsp to a human-editable JSON sidecar (defaults to <base>.wgsp.json) \n " ) ;
std : : printf ( " --import-wgsp-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgsp.json sidecar back into binary .wgsp (accepts kind/flag int OR name forms) \n " ) ;
2026-05-09 16:26:27 -07:00
std : : printf ( " --gen-taxi <wtax-base> [name] \n " ) ;
std : : printf ( " Emit .wtax starter: 2 nodes (Stormwind / Goldshire) + 2 paths (round-trip, 50s each, 3 waypoints) \n " ) ;
std : : printf ( " --gen-taxi-region <wtax-base> [name] \n " ) ;
std : : printf ( " Emit .wtax 4-node region: NW/NE/SE/SW outposts on a 500m square + 4-path directed ring \n " ) ;
std : : printf ( " --gen-taxi-continent <wtax-base> [name] \n " ) ;
std : : printf ( " Emit .wtax 6-node hub-spoke continent: central crossroads + 5 outliers + 3 perimeter shortcuts (8 paths) \n " ) ;
std : : printf ( " --info-wtax <wtax-base> [--json] \n " ) ;
std : : printf ( " Print WTAX nodes (id / map / position / name) + paths (id / from->to / cost / waypoint count) \n " ) ;
std : : printf ( " --validate-wtax <wtax-base> [--json] \n " ) ;
std : : printf ( " Static checks: ids>0+unique, finite positions, paths reference real nodes, no self-loop, non-negative delays \n " ) ;
2026-05-09 16:35:01 -07:00
std : : printf ( " --export-wtax-json <wtax-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtax to a human-editable JSON sidecar (defaults to <base>.wtax.json) \n " ) ;
std : : printf ( " --import-wtax-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtax.json sidecar back into binary .wtax (round-trip with --export-wtax-json) \n " ) ;
feat(pipeline): add WTAL (Wowee Talent catalog) format
Novel open replacement for Blizzard's TalentTab.dbc +
Talent.dbc + the AzerothCore-style talent_progression SQL
tables. The 25th open format added to the editor.
Defines class talent specialization trees: per-class set
of named tabs (Arms / Fury / Protection for warrior, Fire
/ Frost / Arcane for mage), each with talents arranged in
a row/column grid, each talent having up to 5 ranks and
an optional prerequisite chain.
Cross-references with previously-added formats:
WTAL.talent.prereqTalentId -> WTAL.talent.talentId
(intra-format chain)
WTAL.talent.rankSpellIds[] -> WSPL.entry.spellId
(spell granted at each rank)
Format:
• magic "WTAL", version 1, little-endian
• per tree: treeId / name / iconPath / requiredClassMask /
talents[] (row, col, maxRank, prereqTalentId+rank,
rankSpellIds[5] zero-padded for unused ranks)
Enums:
• ClassMask: bit positions match canonical CharClasses.dbc
classIds — Warrior / Paladin / Hunter / Rogue / Priest /
DK / Shaman / Mage / Warlock / Druid
API: WoweeTalentLoader::save / load / exists +
WoweeTalent::findTree / findTalent (global lookup across
all trees in the catalog).
Three preset emitters showcase tree shapes:
• makeStarter — 1 small tree (3-talent vertical chain)
• makeWarrior — 3 trees (Arms 4 / Fury 4 / Protection 3)
with WSPL cross-refs at capstones
(Mortal Strike -> WSPL 12294, Battle Shout
-> WSPL 6673, Thunder Clap -> WSPL 6343)
• makeMage — 3 trees (Arcane / Fire / Frost) with
capstones referencing Frostbolt 116 /
Fireball 133 / Blink 1953 from WSPL
CLI added (5 flags, 571 documented total now):
--gen-talents / --gen-talents-warrior / --gen-talents-mage
--info-wtal / --validate-wtal
Validator catches: tree+talent ids=0 or duplicates, empty
tree name, requiredClassMask=0 (every class would see this
tree — usually a typo), maxRank not in 1..5, talent listing
itself as prerequisite, prereqTalentId pointing at a
talent that doesn't exist in this catalog (intra-format
cross-reference resolution), prereqRank=0 or > the prereq
talent's maxRank (catches off-by-one references), gaps in
rankSpellIds progression (rank N has spell but rank N-1
doesn't — usually a typo).
The validator caught a real authoring bug in the makeMage /
makeWarrior presets during smoke testing — initial check
was comparing prereqRank against the WRONG talent's maxRank
(this talent's rather than the prereq's). Fixed in the same
commit by hoisting the check into the cross-reference
resolution pass where the prereq talent is in hand.
2026-05-09 16:33:45 -07:00
std : : printf ( " --gen-talents <wtal-base> [name] \n " ) ;
std : : printf ( " Emit .wtal starter: 1 small tree (3 talents in chain) for class warrior \n " ) ;
std : : printf ( " --gen-talents-warrior <wtal-base> [name] \n " ) ;
std : : printf ( " Emit .wtal warrior trees: Arms (4 talents) + Fury (4) + Protection (3) with WSPL spell cross-refs \n " ) ;
std : : printf ( " --gen-talents-mage <wtal-base> [name] \n " ) ;
std : : printf ( " Emit .wtal mage trees: Arcane (3 talents) + Fire (3) + Frost (3) with WSPL Frostbolt/Fireball/Blink refs \n " ) ;
std : : printf ( " --info-wtal <wtal-base> [--json] \n " ) ;
std : : printf ( " Print WTAL trees + per-talent grid position / max rank / prereq chain / rank-1 spellId \n " ) ;
std : : printf ( " --validate-wtal <wtal-base> [--json] \n " ) ;
std : : printf ( " Static checks: tree+talent ids>0+unique, maxRank 1..5, prereq references resolve, no self-prereq \n " ) ;
2026-05-09 16:41:37 -07:00
std : : printf ( " --export-wtal-json <wtal-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtal to a human-editable JSON sidecar (defaults to <base>.wtal.json) \n " ) ;
std : : printf ( " --import-wtal-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtal.json sidecar back into binary .wtal (round-trip with --export-wtal-json) \n " ) ;
feat(pipeline): add WMS (Wowee Map / Area) catalog format
Novel open replacement for Blizzard's Map.dbc + AreaTable.dbc
+ the AzerothCore-style world_zone SQL tables. The 26th open
format added to the editor.
Defines two related kinds of locator in one catalog:
• Maps — top-level worlds (continents / instances / raids /
battlegrounds / arenas) with a friendly name,
type, expansion tag, and player-count cap.
• Areas — sub-zones within maps with friendly names, parent-
area chain, recommended level range, faction-
territory marker (alliance / horde / contested /
both), exploration XP, and an ambient-sound
cross-reference into WSND.
The runtime uses Areas for minimap labels, location strings
under the player frame, "Discover Sub-zone" XP gains, and
ambient-music selection on zone entry.
Cross-references with previously-added formats:
WMS.area.ambienceSoundId -> WSND.entry.soundId
WMS.area.parentAreaId -> WMS.area.areaId (intra-format
sub-zone hierarchy)
WSPN entries are tied to WMS.area boundaries by
world position (no direct ID — the runtime resolves
position -> area at lookup time)
Format:
• magic "WMSX", version 1, little-endian
• maps[] (each): mapId / name / shortName / mapType /
expansionId / maxPlayers
• areas[] (each): areaId / mapId / parentAreaId / name /
minLevel..maxLevel / factionGroup / explorationXP /
ambienceSoundId
Enums:
• MapType (5): Continent / Instance / Raid / Battleground / Arena
• ExpansionId (5): Classic / Tbc / Wotlk / Cata / Mop
• FactionGroup: Both / Alliance / Horde / Contested
(PvP-flagging zone)
API: WoweeMapsLoader::save / load / exists +
WoweeMaps::findMap / findArea.
Three preset emitters showcase the catalog shape:
• makeStarter — 1 continent + 3 areas with parent chain
(Goldshire is a sub-zone of Elwynn Forest)
• makeClassic — 2 continents + Deadmines instance + 6
areas (Stormwind/Elwynn/Goldshire/Westfall/
Duskwood/Teldrassil/Deadmines) with WSND
ambient-sound refs
• makeBgArena — Alterac Valley (40-player BG) + Nagrand
Arena (5v5 with maxPlayers=10)
CLI added (5 flags, 578 documented total now):
--gen-maps / --gen-maps-classic / --gen-maps-bgarena
--info-wms / --validate-wms
Validator catches: empty map name, unknown mapType / expansion,
BG/Arena with maxPlayers=0 (no participant cap), area ids=0
+ duplicates, empty area name, maxLevel < minLevel, areas
referencing non-existent maps, parentAreaId chains crossing
maps (sub-zones must be on the same world), self-parent.
2026-05-09 16:40:00 -07:00
std : : printf ( " --gen-maps <wms-base> [name] \n " ) ;
std : : printf ( " Emit .wms starter: 1 map (Eastern Kingdoms) + 3 areas (Stormwind / Elwynn / Goldshire) with parent chain \n " ) ;
std : : printf ( " --gen-maps-classic <wms-base> [name] \n " ) ;
std : : printf ( " Emit .wms classic set: 2 continents + Deadmines instance + 6 areas with sub-zone parent chains + WSND refs \n " ) ;
std : : printf ( " --gen-maps-bgarena <wms-base> [name] \n " ) ;
std : : printf ( " Emit .wms PvP maps: Alterac Valley (40-player BG) + Nagrand Arena (5v5) \n " ) ;
std : : printf ( " --info-wms <wms-base> [--json] \n " ) ;
std : : printf ( " Print WMS maps (id / type / expansion / max players) + areas (id / map / parent / level / faction / xp) \n " ) ;
std : : printf ( " --validate-wms <wms-base> [--json] \n " ) ;
std : : printf ( " Static checks: ids unique, areas reference real maps, parent areas exist + same map, BG/Arena needs maxPlayers \n " ) ;
2026-05-09 16:48:34 -07:00
std : : printf ( " --export-wms-json <wms-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wms to a human-editable JSON sidecar (defaults to <base>.wms.json) \n " ) ;
std : : printf ( " --import-wms-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wms.json sidecar back into binary .wms (accepts mapType/expansion/faction int OR name forms) \n " ) ;
feat(pipeline): add WCHC (Wowee Character Classes/Races) format
Novel open replacement for Blizzard's CharClasses.dbc +
CharRaces.dbc + CharStartOutfit.dbc trio. The 27th open
format added to the editor — completes the foundational
character-creation surface.
One file holds three flat arrays:
• classes — playable classes (Warrior / Mage / etc.) with
power type (mana/rage/focus/energy/runic),
base HP+power scaling, faction availability
• races — playable races with faction (Alliance/Horde/
Neutral), starting map+zone, default language
spell, base stats, racial mount spell
• outfits — starting gear loadout per (class, race, gender)
triple, listing item IDs and display slots
Cross-references with previously-added formats:
WCHC.race.startingMapId -> WMS.map.mapId
WCHC.race.startingZoneAreaId -> WMS.area.areaId
WCHC.race.defaultLanguageSpellId -> WSPL.entry.spellId
WCHC.race.mountSpellId -> WSPL.entry.spellId
WCHC.outfit.items.itemId -> WIT.entry.itemId
The starter preset's outfits use real WIT itemIds (1=Worn
Shortsword, 2=Linen Vest, 3=Healing Potion) so the demo
content stack is consistent: a freshly created Human Warrior
in WCHC starts with WIT items 1/2/3, drops them on death
into a WLOT-tracked corpse loot, and can be respawned via
WSPN, etc.
Format:
• magic "WCHC", version 1, little-endian
• classes[]: classId / name / icon / powerType / display /
baseHP+perLevel / basePower+perLevel / factionAvailability
• races[]: raceId / name / icon / factionId / male+female
displayId / 5 base stats / startingMap+zone /
defaultLanguage+mount spell IDs
• outfits[]: classId+raceId+gender + items[]
(each: itemId + displaySlot)
Enums:
• PowerType (6): Mana / Rage / Focus / Energy / RunicPower / Runes
• RaceFaction (3): Alliance / Horde / Neutral
• Gender: Male / Female
• FactionAvailability bitmask: AvailableAlliance, AvailableHorde
API: WoweeCharsLoader::save / load / exists +
WoweeChars::findClass / findRace / findOutfit (by class+race+gender).
CLI added (5 flags, 585 documented total now):
--gen-chars / --gen-chars-alliance / --gen-chars-allraces
--info-wchc / --validate-wchc
Validator catches: ids unique, baseHealth=0 (instant-death
character), factionAvailability=0 (no faction can pick),
empty names, factionId out of range, outfit references to
non-existent class/race ids (cross-format resolution),
gender > 1, outfit items with itemId=0, outfit with no
items (warning — naked character).
2026-05-09 16:47:04 -07:00
std : : printf ( " --gen-chars <wchc-base> [name] \n " ) ;
std : : printf ( " Emit .wchc starter: 2 classes (Warrior + Mage) + 2 races (Human + Orc) + 4 outfits with WIT cross-refs \n " ) ;
std : : printf ( " --gen-chars-alliance <wchc-base> [name] \n " ) ;
std : : printf ( " Emit .wchc Alliance set: 4 classes (Warrior/Paladin/Rogue/Mage) + 4 races (Human/Dwarf/NightElf/Gnome) \n " ) ;
std : : printf ( " --gen-chars-allraces <wchc-base> [name] \n " ) ;
std : : printf ( " Emit .wchc all 8 classic races (4 Alliance + 4 Horde) + 9 classes (no DK) \n " ) ;
std : : printf ( " --info-wchc <wchc-base> [--json] \n " ) ;
std : : printf ( " Print WCHC classes (id / power / hp scaling) + races (faction / starting zone) + outfit item lists \n " ) ;
std : : printf ( " --validate-wchc <wchc-base> [--json] \n " ) ;
std : : printf ( " Static checks: class+race ids unique, baseHealth>0, faction availability set, outfit refs resolve \n " ) ;
2026-05-09 16:55:31 -07:00
std : : printf ( " --export-wchc-json <wchc-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wchc to a human-editable JSON sidecar (defaults to <base>.wchc.json) \n " ) ;
std : : printf ( " --import-wchc-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wchc.json sidecar back into binary .wchc (accepts power/faction/gender int OR name forms) \n " ) ;
feat(pipeline): add WTKN (Wowee Token catalog) format
Novel open replacement for Blizzard's Currency.dbc +
CurrencyCategory.dbc + CurrencyTypes.dbc + the AzerothCore-
style player_currency SQL tables. The 28th open format
added to the editor.
Defines secondary currency tokens beyond gold: Honor Points
(PvP), Arena Points (rated PvP), Marks of Honor (per
battleground), faction reputation tokens, holiday-event
currencies. Each token has a balance cap, optional weekly
cap (regenerating earnings limit), and a category for
grouping in the player's currency tab.
Cross-references:
WTRN.item.extendedCost -> WTKN.entry.tokenId
(vendors can charge in tokens
instead of copper — when
extendedCost > 0 the runtime
looks up the matching token)
Format:
• magic "WTKN", version 1, little-endian
• per token: tokenId / name / description / iconPath /
category / maxBalance / weeklyCap / flags
Enums:
• Category (6): Misc / Pvp / Reputation / Crafting /
Seasonal / Holiday
• Flags: AccountWide / Tradeable / HiddenUntilEarned /
ResetsOnLogout / ConvertsToGold
API: WoweeTokenLoader::save / load / exists / findById.
Three preset emitters showcase typical token shapes:
• makeStarter — 3 tokens (Honor / Marks / Stormwind Guard
rep) covering Pvp + Reputation categories
• makePvp — full PvP set: Honor (75k) + Arena (5k +
weekly 1500) + 6 BG marks of honor for
classic + TBC + WotLK battlegrounds
• makeSeasonal — 4 holiday tokens (Tricky Treats /
Brewfest / Coin of Ancestry / Stranger's
Gift) all flagged ResetsOnLogout to make
them event-bound
CLI added (5 flags, 592 documented total now):
--gen-tokens / --gen-tokens-pvp / --gen-tokens-seasonal
--info-wtkn / --validate-wtkn
Validator catches: tokenId=0 + duplicates, empty name,
unknown category, weeklyCap > maxBalance (cap unreachable),
ResetsOnLogout + AccountWide combo (incoherent — account
state survives logout by definition).
2026-05-09 16:53:11 -07:00
std : : printf ( " --gen-tokens <wtkn-base> [name] \n " ) ;
std : : printf ( " Emit .wtkn starter: 3 tokens (Honor / Marks / Stormwind Guard) covering Pvp + Reputation categories \n " ) ;
std : : printf ( " --gen-tokens-pvp <wtkn-base> [name] \n " ) ;
std : : printf ( " Emit .wtkn full PvP set: Honor (75k cap) + Arena (5k cap, weekly 1500) + 6 BG marks of honor \n " ) ;
std : : printf ( " --gen-tokens-seasonal <wtkn-base> [name] \n " ) ;
std : : printf ( " Emit .wtkn 4 holiday tokens (Tricky Treats / Brewfest / Coin of Ancestry / Stranger's Gift) — ResetsOnLogout \n " ) ;
std : : printf ( " --info-wtkn <wtkn-base> [--json] \n " ) ;
std : : printf ( " Print WTKN entries (id / category / max balance / weekly cap / flags / name) \n " ) ;
std : : printf ( " --validate-wtkn <wtkn-base> [--json] \n " ) ;
std : : printf ( " Static checks: tokenId>0+unique, name not empty, weeklyCap<=maxBalance, no Resets+AccountWide conflict \n " ) ;
2026-05-09 16:56:55 -07:00
std : : printf ( " --export-wtkn-json <wtkn-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtkn to a human-editable JSON sidecar (defaults to <base>.wtkn.json) \n " ) ;
std : : printf ( " --import-wtkn-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtkn.json sidecar back into binary .wtkn (accepts category/flag int OR name forms) \n " ) ;
feat(pipeline): add WTRG (Wowee Area Trigger) format
Novel open replacement for Blizzard's AreaTrigger.dbc +
AreaTriggerTeleport.dbc + the AzerothCore-style
areatrigger_template / areatrigger_teleport SQL tables.
The 29th open format added to the editor.
Defines proximity-based event zones — when a player enters
a defined region (box or sphere), the runtime fires the
trigger's action: teleport to another map, award
exploration XP for a quest, run a server script, gate an
instance entrance behind a key item, mark a PvP boundary,
or simply display a "Discovered: {area name}" banner.
Cross-references with previously-added formats — every
trigger field has a real format target:
WTRG.entry.mapId / areaId -> WMS.map.mapId / WMS.area.areaId
WTRG.actionTarget (Teleport) -> WMS.mapId
WTRG.actionTarget (QuestExploration) -> WQT.questId
WTRG.requiredQuestId -> WQT.entry.questId
WTRG.requiredItemId -> WIT.entry.itemId (key)
Format:
• magic "WTRG", version 1, little-endian
• per trigger: triggerId / mapId / areaId / name /
center vec3 / shape / kind / boxDims vec3 / radius /
actionTarget / dest vec3 / destOrientation /
requiredQuestId / requiredItemId / minLevel
Enums:
• Shape (2): Box / Sphere
• Kind (7): Teleport / QuestExploration / Script /
InstanceEntrance / AreaName / CombatStartZone /
Waypoint
API: WoweeTriggerLoader::save / load / exists / findById.
Three preset emitters showcase common trigger shapes:
• makeStarter — area-name + quest-exploration with
cross-ref to WQT 100 ("Investigate the
Camp")
• makeDungeon — outdoor area-name + portal-style
InstanceEntrance with Deadmines key
gate (WIT itemId 5200, matches
WLCK.makeDungeon's Boss Vault Seal) +
interior exit teleport back outdoors
• makeFlightPath — 2 sphere waypoints near flight masters
so the runtime can auto-open the
flight UI on proximity (matches WTAX
starter node positions)
CLI added (5 flags, 601 documented total now):
--gen-triggers / --gen-triggers-dungeon / --gen-triggers-flightpath
--info-wtrg / --validate-wtrg
Validator catches: triggerId=0 + duplicates, unknown shape /
kind, non-finite center, sphere with radius<=0, box with
all-zero half-extents, teleport / instance with dest=(0,0,0)
(silently does nothing — usually a typo), QuestExploration
without an actionTarget questId.
2026-05-09 17:01:43 -07:00
std : : printf ( " --gen-triggers <wtrg-base> [name] \n " ) ;
std : : printf ( " Emit .wtrg starter: 2 triggers (Goldshire area-name + bandit-camp quest exploration ref WQT 100) \n " ) ;
std : : printf ( " --gen-triggers-dungeon <wtrg-base> [name] \n " ) ;
std : : printf ( " Emit .wtrg dungeon set: outdoor area-name + Deadmines portal (key-gated) + interior exit teleport \n " ) ;
std : : printf ( " --gen-triggers-flightpath <wtrg-base> [name] \n " ) ;
std : : printf ( " Emit .wtrg flight-master proximity waypoints (Stormwind / Goldshire) for auto-open flight UI \n " ) ;
std : : printf ( " --info-wtrg <wtrg-base> [--json] \n " ) ;
std : : printf ( " Print WTRG triggers (id / map / area / kind / shape + dims / dest + facing / quest+key gates) \n " ) ;
std : : printf ( " --validate-wtrg <wtrg-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, finite center, sphere needs radius>0, box needs >=1 nonzero half-extent, quest-explore needs target \n " ) ;
2026-05-09 17:03:27 -07:00
std : : printf ( " --export-wtrg-json <wtrg-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtrg to a human-editable JSON sidecar (defaults to <base>.wtrg.json) \n " ) ;
std : : printf ( " --import-wtrg-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtrg.json sidecar back into binary .wtrg (accepts shape/kind int OR name forms) \n " ) ;
feat(pipeline): add WTIT (Wowee Title catalog) format
Novel open replacement for Blizzard's CharTitles.dbc + the
AzerothCore-style character_title SQL table. The 30th open
format added to the editor.
Defines the player-display titles awarded for completing
achievements ("the Versatile"), reaching PvP ranks
("Sergeant Major" / "Stone Guard"), participating in raids
("Champion of the Naaru"), levelling a profession ("Master
Locksmith"), or seasonal events ("Brewmaster", "the
Hallowed").
Closes a long-standing gap: WACH.entry.titleReward has been
a free-form string since batch 116 with no formal catalog
to resolve against. WTIT systematizes those strings into a
real catalog — the runtime resolves WACH.titleReward to a
WTIT entry by name, then displays the titleId in the player
title selector.
Cross-references:
WACH.entry.titleReward (string) ~= WTIT.entry.name
(string match — runtime
resolves achievement-
granted titles by
looking up matching WTIT
entry by name)
Format:
• magic "WTIT", version 1, little-endian
• per title: titleId / name / nameMale / nameFemale /
iconPath / prefix (suffix vs prefix display) /
category / sortOrder
Enums:
• Category (8): Achievement / Pvp / Raid / ClassTitle /
Event / Profession / Lore / Custom
API: WoweeTitleLoader::save / load / exists +
WoweeTitle::findById / findByName.
Three preset emitters showcase typical title catalogs:
• makeStarter — 4 titles (Versatile / Sergeant /
Champion / Hallowed) covering 4
categories
• makePvp — 28-title classic Honor System ladder
(14 Alliance ranks Private->Grand
Marshal + 14 Horde ranks Scout->High
Warlord)
• makeAchievement — 8 achievement titles including "the
Versatile" matching WACH.makeMeta's
achievement 250 titleReward + capstone
profession titles
CLI added (5 flags, 608 documented total now):
--gen-titles / --gen-titles-pvp / --gen-titles-achievement
--info-wtit / --validate-wtit
Validator catches: titleId=0 + duplicates, empty name,
unknown category, gender variants set on only one side
(causes mixed-gender display when the runtime falls back to
canonical for the unset side).
2026-05-09 17:07:56 -07:00
std : : printf ( " --gen-titles <wtit-base> [name] \n " ) ;
std : : printf ( " Emit .wtit starter: 4 titles covering Achievement / Pvp / Raid / Event categories \n " ) ;
std : : printf ( " --gen-titles-pvp <wtit-base> [name] \n " ) ;
std : : printf ( " Emit .wtit Honor System ladder: 14 Alliance + 14 Horde rank titles (Private..Grand Marshal / Scout..High Warlord) \n " ) ;
std : : printf ( " --gen-titles-achievement <wtit-base> [name] \n " ) ;
std : : printf ( " Emit .wtit achievement titles incl. 'the Versatile' (matches WACH meta-achievement 250 titleReward) \n " ) ;
std : : printf ( " --info-wtit <wtit-base> [--json] \n " ) ;
std : : printf ( " Print WTIT entries (id / sort / prefix vs suffix / category / canonical name) \n " ) ;
std : : printf ( " --validate-wtit <wtit-base> [--json] \n " ) ;
std : : printf ( " Static checks: titleId>0+unique, name not empty, category in 0..7, gender variants paired \n " ) ;
2026-05-09 17:16:41 -07:00
std : : printf ( " --export-wtit-json <wtit-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtit to a human-editable JSON sidecar (defaults to <base>.wtit.json) \n " ) ;
std : : printf ( " --import-wtit-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtit.json sidecar back into binary .wtit (accepts category/prefix int OR name forms) \n " ) ;
feat(pipeline): add WSEA (Wowee Seasonal Event) format
Novel open replacement for Blizzard's GameEvents.dbc + the
AzerothCore-style game_event / game_event_creature /
game_event_gameobject SQL tables. The 31st open format
added to the editor.
Calendar-based content: holidays (Hallow's End, Winter's
Veil), recurring promotional events (Children's Week,
Lunar Festival, Brewfest), one-time anniversaries, and
XP-bonus weekends. Each event has a start date, duration,
optional recurrence (yearly / monthly / weekly), faction
restriction, optional XP bonus, and a reward currency
cross-reference into WTKN.
Cross-references with previously-added formats:
WSEA.entry.tokenIdReward -> WTKN.entry.tokenId
(the seasonal currency the
event hands out — Tricky
Treats during Hallow's End,
Brewfest Tokens during
Brewfest, etc.)
The yearly preset's tokenIdReward values (200/201/202/203)
deliberately match WTKN.makeSeasonal's seasonal token ids
so the demo content stack already wires together: WSEA
yearly events grant WTKN tokens that vendors can charge in
via WTRN.item.extendedCost.
Format:
• magic "WSEA", version 1, little-endian
• per event: eventId / name / description / iconPath /
announceMessage / startDate (Unix epoch seconds) /
duration_seconds / recurrenceDays (0=one-shot, 365=yearly) /
holidayKind / factionGroup / bonusXpPercent / tokenIdReward
Enums:
• HolidayKind (7): Combat / Collection / Racial /
Anniversary / Fishing / Cosmetic /
WorldEvent
• FactionGroup (3): Both / Alliance / Horde
API: WoweeEventLoader::save / load / exists / findById.
Three preset emitters showcase typical event shapes:
• makeStarter — 3 events covering Combat /
Fishing / Anniversary kinds
• makeYearly — 4 yearly holidays with full WTKN
cross-refs (Hallow's End / Brewfest /
Lunar Festival / Winter's Veil)
• makeBonusWeekends — 3 monthly Fri-Sun bonus tiers
(50% / 100% / 200% RAF-style)
CLI added (5 flags, 614 documented total now):
--gen-events / --gen-events-yearly / --gen-events-weekends
--info-wsea / --validate-wsea
Validator catches: eventId=0 + duplicates, empty name,
unknown holidayKind / factionGroup, duration_seconds=0
(event never runs), duration > recurrence period (events
would overlap themselves on next iteration), bonusXpPercent
> 200 (very high — verify intentional).
2026-05-09 17:14:46 -07:00
std : : printf ( " --gen-events <wsea-base> [name] \n " ) ;
std : : printf ( " Emit .wsea starter: 3 events (Brawl Week / Fishing Extravaganza / Anniversary) covering kind categories \n " ) ;
std : : printf ( " --gen-events-yearly <wsea-base> [name] \n " ) ;
std : : printf ( " Emit .wsea 4 yearly holidays (Hallow's End / Brewfest / Lunar Festival / Winter's Veil) with WTKN reward refs \n " ) ;
std : : printf ( " --gen-events-weekends <wsea-base> [name] \n " ) ;
std : : printf ( " Emit .wsea 3 monthly XP-bonus weekends (50%% / 100%% / 200%% RAF tiers) \n " ) ;
std : : printf ( " --info-wsea <wsea-base> [--json] \n " ) ;
std : : printf ( " Print WSEA entries (id / kind / duration / recurrence / xp bonus / token reward / name) \n " ) ;
std : : printf ( " --validate-wsea <wsea-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, kind in 0..6, duration>0, no overlapping recurrence \n " ) ;
2026-05-09 17:24:50 -07:00
std : : printf ( " --export-wsea-json <wsea-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsea to a human-editable JSON sidecar (defaults to <base>.wsea.json) \n " ) ;
std : : printf ( " --import-wsea-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsea.json sidecar back into binary .wsea (accepts kind/faction int OR name forms) \n " ) ;
feat(pipeline): add WMOU (Wowee Mount catalog) format
Novel open replacement for Blizzard's Mount.dbc +
MountCapability.dbc + MountType.dbc + the mount-related
subsets of Spell.dbc / Item.dbc. The 32nd open format added
to the editor.
Defines all summonable steeds: ground mounts, flying mounts,
swimming mounts, racial mounts (Tauren Plainsrunner for
druids), and class mounts (Warlock dreadsteed, Paladin
charger). Each mount has a summon spell, optional teach
item, riding skill prerequisite, speed bonus, and faction
/ race availability mask.
Cross-references with previously-added formats:
WMOU.entry.summonSpellId -> WSPL.entry.spellId
WMOU.entry.itemIdToLearn -> WIT.entry.itemId
WMOU.entry.requiredSkillId -> WSKL.entry.skillId
(Riding skill ID 762)
WCHC.race.mountSpellId ~= WMOU.entry.summonSpellId
(loose match by spellId)
Format:
• magic "WMOU", version 1, little-endian
• per mount: mountId / name / description / icon /
displayId / summonSpellId / itemIdToLearn /
requiredSkillId+Rank / speedPercent / mountKind /
factionId / categoryId / raceMask
Enums:
• Kind (5): Ground / Flying / Swimming / Hybrid /
Aquatic
• Faction (3): Both / Alliance / Horde
• Category (8): Common / Epic / Racial / Event /
Achievement / Pvp / Quest / ClassMount
API: WoweeMountLoader::save / load / exists / findById.
Three preset emitters showcase typical mount catalogs:
• makeStarter — 3 mounts (ground horse + epic flying
gryphon + aquatic riding turtle)
• makeRacial — 6 racial mounts (4 Alliance: Pinto / Ram /
Frostsaber / Mechanostrider; 2 Horde:
Dire Wolf / Skeletal Horse) with raceMask
gating per WCHC race bit positions
• makeFlying — 4 flying mounts spanning Common (60%) ->
Epic (100%) -> Achievement (280%) -> Pvp
(310%) speed tiers
CLI added (5 flags, 621 documented total now):
--gen-mounts / --gen-mounts-racial / --gen-mounts-flying
--info-wmou / --validate-wmou
Validator catches: mountId=0 + duplicates, empty name,
summonSpellId=0 (mount cannot be cast), unknown enum values,
speedPercent=0 (no speed bonus), flying mount with
requiredSkillRank<150 (player can't fly), Racial category
without raceMask (any race could use — usually a typo).
2026-05-09 17:23:00 -07:00
std : : printf ( " --gen-mounts <wmou-base> [name] \n " ) ;
std : : printf ( " Emit .wmou starter: 3 mounts (Brown Horse / Swift Gryphon / Riding Turtle) covering ground/flying/aquatic \n " ) ;
std : : printf ( " --gen-mounts-racial <wmou-base> [name] \n " ) ;
std : : printf ( " Emit .wmou 6 racial mounts (4 Alliance + 2 Horde) with raceMask gating \n " ) ;
std : : printf ( " --gen-mounts-flying <wmou-base> [name] \n " ) ;
std : : printf ( " Emit .wmou 4 flying mounts spanning common/epic/achievement/pvp tiers (60%%/100%%/280%%/310%% speed) \n " ) ;
std : : printf ( " --info-wmou <wmou-base> [--json] \n " ) ;
std : : printf ( " Print WMOU entries (id / kind / speed / required riding rank / faction / category / name) \n " ) ;
std : : printf ( " --validate-wmou <wmou-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, summonSpellId>0, flying needs rank>=150, racial needs raceMask \n " ) ;
2026-05-09 17:33:54 -07:00
std : : printf ( " --export-wmou-json <wmou-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wmou to a human-editable JSON sidecar (defaults to <base>.wmou.json) \n " ) ;
std : : printf ( " --import-wmou-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wmou.json sidecar back into binary .wmou (accepts kind/faction/category int OR name forms) \n " ) ;
feat(pipeline): add WBGD (Wowee Battleground Definition) format
Novel open replacement for Blizzard's BattlemasterList.dbc +
PvpDifficulty.dbc + the AzerothCore-style
battleground_template SQL tables. The 33rd open format
added to the editor.
Defines per-BG gameplay rules: player count brackets,
score-to-win, time limit, objective type (annihilation /
capture flag / control nodes / king of hill / resource race
/ carry object), per-team start positions, respawn timer,
and the WTKN currency token awarded on win.
Cross-references with previously-added formats:
WBGD.entry.mapId -> WMS.map.mapId
(where mapType=Battleground)
WBGD.entry.markTokenId -> WTKN.entry.tokenId
(Mark of Honor for that BG)
The classic preset's markTokenId fields (102/103/104)
deliberately match WTKN.makePvp's "Mark of Honor: Warsong
Gulch / Arathi Basin / Alterac Valley" token ids — so the
demo content stack already wires together: WBGD.scoreToWin
reached → grant WTKN mark → which a vendor in WTRN can
charge in via item.extendedCost.
Format:
• magic "WBGD", version 1, little-endian
• per BG: battlegroundId / mapId / name / description /
objectiveKind / min+maxPlayersPerSide /
minLevel..maxLevel / scoreToWin / timeLimitSeconds /
bracketSize / allianceStart vec3 + facing /
hordeStart vec3 + facing / respawnTimeSeconds /
markTokenId
Enums:
• ObjectiveKind (6): Annihilation / CaptureFlag /
ControlNodes / KingOfHill /
ResourceRace / CarryObject
API: WoweeBattlegroundLoader::save / load / exists /
findById.
Three preset emitters showcase typical BG shapes:
• makeStarter — 1 king-of-hill BG (10v10, 3-cap to win)
• makeClassic — 3 classic BGs with authentic player
counts, level brackets, scoring, and
WTKN cross-refs (Warsong Gulch CTF /
Arathi Basin nodes / Alterac Valley
resource race)
• makeArena — 3 arena formats (Nagrand 2v2 / Blade's
Edge 3v3 / Lordaeron 5v5) — annihilation
objective + no respawn + 25 min cap
CLI added (5 flags, 628 documented total now):
--gen-bg / --gen-bg-classic / --gen-bg-arena
--info-wbgd / --validate-wbgd
Validator catches: bgId=0 + duplicates, empty name, unknown
objectiveKind, player count=0, min>max counts/levels,
scoreToWin=0 (no win condition), non-annihilation BG with
respawnTimeSeconds=0 (losing side cannot recover).
2026-05-09 17:30:59 -07:00
std : : printf ( " --gen-bg <wbgd-base> [name] \n " ) ;
std : : printf ( " Emit .wbgd starter: 1 king-of-hill BG (10v10, 3-cap to win, 30 min limit) \n " ) ;
std : : printf ( " --gen-bg-classic <wbgd-base> [name] \n " ) ;
std : : printf ( " Emit .wbgd 3 classic BGs: Warsong Gulch (CTF) + Arathi Basin (nodes) + Alterac Valley (resource race) \n " ) ;
std : : printf ( " --gen-bg-arena <wbgd-base> [name] \n " ) ;
std : : printf ( " Emit .wbgd 3 arena formats: Nagrand 2v2 + Blade's Edge 3v3 + Lordaeron 5v5 (annihilation) \n " ) ;
std : : printf ( " --info-wbgd <wbgd-base> [--json] \n " ) ;
std : : printf ( " Print WBGD entries (id / map / objective / player counts / level range / score / token reward) \n " ) ;
std : : printf ( " --validate-wbgd <wbgd-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, player counts>0+min<=max, level range valid, scoreToWin>0 \n " ) ;
2026-05-09 17:53:41 -07:00
std : : printf ( " --export-wbgd-json <wbgd-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wbgd to a human-editable JSON sidecar (defaults to <base>.wbgd.json) \n " ) ;
std : : printf ( " --import-wbgd-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wbgd.json sidecar back into binary .wbgd (accepts objectiveKind int OR name string) \n " ) ;
feat(pipeline): add WMAL (Wowee Mail Template) format
Novel open replacement for AzerothCore-style
mail_loot_template SQL + the in-game mail subset of the
inventory + currency systems. The 34th open format added
to the editor.
Defines templated mail messages with currency + item
attachments. Triggered by quest reward delivery (overflow
when bag is full), auction house bid wins / sales,
achievement reward attachments, GM correspondence, holiday
event mailings (Brewfest samples, Hallow's End candy), and
returned-mail-on-rejection.
Cross-references with previously-added formats:
WMAL.entry.senderNpcId -> WCRT.entry.creatureId
WMAL.entry.attachments.itemId -> WIT.entry.itemId
Format:
• magic "WMAL", version 1, little-endian
• per template: templateId / senderNpcId / subject / body /
senderName / moneyCopperAttached / categoryId / cod /
returnable / expiryDays / attachments[] (each: itemId +
quantity)
Enums:
• Category (8): QuestReward / Auction / GmCorrespondence /
AchievementReward / EventMailing / Raffle /
ScriptDelivery / ReturnedMail
API: WoweeMailLoader::save / load / exists / findById.
Three preset emitters showcase typical mail templates:
• makeStarter — 3 templates (quest overflow / auction won /
GM gift) covering the 3 most common
categories
• makeHoliday — 4 holiday samples that cross-reference the
WTKN seasonal token IDs (200=Tricky Treats,
201=Brewfest, 202=Coin of Ancestry,
203=Stranger's Gift) so the demo content
stack ships a full holiday onboarding
experience
• makeAuction — 5-template auction-house family (outbid /
won / sold / expired / cancelled) — runtime
fills in actual bid amounts / sold items
at send time
CLI added (5 flags, 635 documented total now):
--gen-mail / --gen-mail-holiday / --gen-mail-auction
--info-wmal / --validate-wmal
Validator catches: templateId=0 + duplicates, empty subject,
neither senderNpcId nor senderName set (no displayable
sender), unknown category, expiryDays=0 (mail expires
immediately), cod=1 with no money attached (free COD),
empty mail in categories where the runtime doesn't fill in
content (skips Auction / GmCorrespondence / ReturnedMail
where empty templates are intentional).
Two bugs caught + fixed during smoke-test on the auction
preset:
• print formatting glued the `0` from senderNpcId after
the senderName when no NPC was set (rendered as
"Postmaster0" instead of "Postmaster") — fixed with an
explicit if/else split
• validator's "no money + no items" warning was too
aggressive for the Auction category, where templates
are intentionally informational and the runtime fills
in the real values — added Auction + ReturnedMail to
the skip list
2026-05-09 17:41:03 -07:00
std : : printf ( " --gen-mail <wmal-base> [name] \n " ) ;
std : : printf ( " Emit .wmal starter: 3 templates (quest overflow / auction won / GM gift) covering main mail categories \n " ) ;
std : : printf ( " --gen-mail-holiday <wmal-base> [name] \n " ) ;
std : : printf ( " Emit .wmal 4 holiday samples (Tricky Treats / Brewfest / Lunar / Winter's Veil) with WTKN cross-refs \n " ) ;
std : : printf ( " --gen-mail-auction <wmal-base> [name] \n " ) ;
std : : printf ( " Emit .wmal 5-template auction-house family (outbid / won / sold / expired / cancelled) \n " ) ;
std : : printf ( " --info-wmal <wmal-base> [--json] \n " ) ;
std : : printf ( " Print WMAL templates (id / category / sender / subject + body / money + items / cod / expiry) \n " ) ;
std : : printf ( " --validate-wmal <wmal-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, subject not empty, sender set, attachments valid, no money+no items info-only \n " ) ;
2026-05-09 18:04:03 -07:00
std : : printf ( " --export-wmal-json <wmal-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wmal to a human-editable JSON sidecar (defaults to <base>.wmal.json) \n " ) ;
std : : printf ( " --import-wmal-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wmal.json sidecar back into binary .wmal (accepts category int OR name string) \n " ) ;
feat(pipeline): add WGEM (Wowee Gem / Enchantment) format
Novel open replacement for Blizzard's ItemEnchantment.dbc +
GemProperties.dbc + SpellItemEnchantment.dbc. The 35th
open format added to the editor.
Defines two related kinds of item enhancement in one
catalog:
• Gems — socketable jewelry pieces with color
(red / blue / yellow / meta) that fit
into gear sockets, granting stats or
triggering passive spells when socketed
• Enchantments — persistent buffs applied to weapon /
armor pieces, either by an enchanter
spell or by an item proc (Mongoose,
Crusader, Berserking)
Cross-references with previously-added formats:
WGEM.gem.itemIdToInsert -> WIT.entry.itemId
WGEM.gem.spellId -> WSPL.entry.spellId
WGEM.enchantment.spellId -> WSPL.entry.spellId
Format:
• magic "WGEM", version 1, little-endian
• gems[]: gemId / itemIdToInsert / name / color /
statType + statValue / requiredItemQuality / spellId
• enchantments[]: enchantId / name / description /
iconPath / enchantSlot / statType + statValue /
spellId / durationSeconds / chargeCount
Enums:
• Color (8): Meta / Red / Yellow / Blue / Purple /
Green / Orange / Prismatic
• EnchantSlot (5): Permanent / Temporary / SocketColor /
Ring / Cloak
API: WoweeGemLoader::save / load / exists +
WoweeGem::findGem / findEnchant.
Three preset emitters showcase common shapes:
• makeStarter — 3 gems (one per primary color) +
2 enchantments (proc + stat)
• makeGemSet — 6-gem full color palette covering
primary + secondary combinations
• makeEnchants — 5 enchant variants spanning slots
(Mongoose / Deadly Poison / stats ring /
cloak / Berserking)
CLI added (5 flags, 642 documented total now):
--gen-gems / --gen-gems-set / --gen-gems-enchants
--info-wgem / --validate-wgem
Validator catches: ids=0 + duplicates, empty name, color /
slot out of range, stat-only entries with statValue=0 (gem
provides nothing), chargeCount > 0 on non-Temporary
enchant slots (charges silently ignored at runtime).
The validator caught a real preset issue on first run —
the proc enchants (Mongoose / Deadly Poison / Berserking)
had spellId=0 and statValue=0, providing nothing. Fixed by
adding placeholder spellIds in the 28000-29000 range, with
a comment noting they resolve to real WSPL proc spells
when the spell catalog is extended.
2026-05-09 18:01:48 -07:00
std : : printf ( " --gen-gems <wgem-base> [name] \n " ) ;
std : : printf ( " Emit .wgem starter: 3 gems (red/yellow/blue) + 2 enchantments (Crusader proc + Greater Stats) \n " ) ;
std : : printf ( " --gen-gems-set <wgem-base> [name] \n " ) ;
std : : printf ( " Emit .wgem 6-gem full color set (3 primary + 3 secondary purple/green/orange) \n " ) ;
std : : printf ( " --gen-gems-enchants <wgem-base> [name] \n " ) ;
std : : printf ( " Emit .wgem 5 enchant variants (Mongoose / Deadly Poison / stats ring / cloak / Berserking proc) \n " ) ;
std : : printf ( " --info-wgem <wgem-base> [--json] \n " ) ;
std : : printf ( " Print WGEM gems (id / color / stat / item) + enchantments (id / slot / stat / duration / charges) \n " ) ;
std : : printf ( " --validate-wgem <wgem-base> [--json] \n " ) ;
std : : printf ( " Static checks: ids>0+unique, name not empty, color/slot in range, stat-only entries need non-zero value \n " ) ;
2026-05-09 18:12:33 -07:00
std : : printf ( " --export-wgem-json <wgem-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgem to a human-editable JSON sidecar (defaults to <base>.wgem.json) \n " ) ;
std : : printf ( " --import-wgem-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgem.json sidecar back into binary .wgem (accepts color/slot int OR name strings) \n " ) ;
feat(pipeline): add WGLD (Wowee Guild) catalog format
Novel open replacement for AzerothCore-style guild +
guild_member + guild_rank + guild_bank_tab + guild_perk
SQL tables. The 36th open format added to the editor.
Each guild entry holds the complete social-organization
state: header (name, leader, faction, MOTD, info,
creation date, level + experience, bank money, packed
emblem), rank ladder with permissions bitmask + daily
withdraw caps, member roster with rank + join date +
public/officer notes, bank tabs with per-tab and per-rank
deposit / withdraw / view permission masks, and purchased
guild perks referencing WSPL spell IDs.
Cross-references with previously-added formats:
WGLD.entry.factionId ~ WCHC.race.factionId
(guilds are faction-locked)
WGLD.entry.perks.spellId -> WSPL.entry.spellId
Format:
• magic "WGLD", version 1, little-endian
• per guild: header (12 scalar fields + 4 strings) +
ranks[] + members[] + bankTabs[] + perks[]
• per rank: rankIndex / name / permissionsMask /
moneyPerDayCopper
• per member: characterName / rankIndex / joinedDate /
publicNote / officerNote
• per bankTab: tabIndex / name / iconPath /
deposit+withdraw+view permission masks
• per perk: perkId / name / spellId / requiredGuildLevel
Enums:
• Faction (2): Alliance / Horde
• RankPermissionFlags (14): GuildChat / OfficerChat /
Invite / Remove / Promote /
Demote / SetMotd /
EditPublicNote /
EditOfficerNote / ViewBank /
Deposit / Withdraw / Disband /
RepairFromBank
API: WoweeGuildLoader::save / load / exists / findById +
shared addDefaultRanks helper used by both starter and
faction-pair presets.
Three preset emitters:
• makeStarter — 1 small guild, default 5-rank ladder
(GM/Officer/Veteran/Member/Initiate),
3 members borrowing names from WCRT
merchants for cross-format consistency
• makeFull — 1 fleshed-out guild: 6 ranks (with
Recruit added) + 8 members + 4 bank
tabs (officer-only withdraw on tabs
3+4) + 3 perks referencing WSPL
spell IDs (Heroic Strike / Battle
Shout / Thunder Clap as placeholder
perk procs)
• makeFactionPair — 2 parallel guilds, one Alliance + one
Horde, with identical rank structures
CLI added (5 flags, 649 documented total now):
--gen-guilds / --gen-guilds-full / --gen-guilds-pair
--info-wgld / --validate-wgld
Validator catches: guildId=0 + duplicates, empty name /
leaderName, factionId out of range, no ranks (members can't
exist without a rank ladder), member.rankIndex exceeding
the highest defined rank (intra-format cross-reference
resolution), duplicate bank tabIndices, perks with
spellId=0 (perk does nothing).
2026-05-09 18:10:45 -07:00
std : : printf ( " --gen-guilds <wgld-base> [name] \n " ) ;
std : : printf ( " Emit .wgld starter: 1 guild (Sentinels of Dawn) with default 5-rank ladder + 3 members \n " ) ;
std : : printf ( " --gen-guilds-full <wgld-base> [name] \n " ) ;
std : : printf ( " Emit .wgld fleshed-out guild: 6 ranks + 8 members + 4 bank tabs (officer-only on tabs 3+4) + 3 perks \n " ) ;
std : : printf ( " --gen-guilds-pair <wgld-base> [name] \n " ) ;
std : : printf ( " Emit .wgld 2 guilds: 1 Alliance (Light's Vanguard) + 1 Horde (Bloodfang Warband) with parallel ranks \n " ) ;
std : : printf ( " --info-wgld <wgld-base> [--json] \n " ) ;
std : : printf ( " Print WGLD entries (id / faction / level / leader + motd / rank+member+tab+perk counts) \n " ) ;
std : : printf ( " --validate-wgld <wgld-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name+leader not empty, faction 0..1, members reference valid ranks, unique tab indices \n " ) ;
2026-05-09 18:20:43 -07:00
std : : printf ( " --export-wgld-json <wgld-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgld to a human-editable JSON sidecar (defaults to <base>.wgld.json) \n " ) ;
std : : printf ( " --import-wgld-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgld.json sidecar back into binary .wgld (accepts faction int OR name string) \n " ) ;
feat(pipeline): add WPCD (Wowee Player Condition) format
Novel open replacement for Blizzard's PlayerCondition.dbc +
the AzerothCore-style condition_template SQL tables. The
37th open format added to the editor.
Defines reusable boolean conditions that other formats can
reference for gating: "player has quest X completed",
"player level >= N", "player class is mage", "player has
item Y in inventory", "WSEA event Z is active".
Conditions can be grouped and combined with AND/OR
aggregators on a per-group basis: a quest-giver gossip
option that says "show only to level 60 alliance mages
who completed quest 1234" composes 4 conditions sharing
the same groupId with AND aggregation. The runtime walks
each group, applies the group's aggregator, and returns
the boolean result to the caller.
Cross-references with previously-added formats — the
targetId field has a polymorphic interpretation by kind:
WPCD.targetId (kind=QuestCompleted/Active) -> WQT.questId
WPCD.targetId (kind=HasItem) -> WIT.itemId
WPCD.targetId (kind=HasSpell) -> WSPL.spellId
WPCD.targetId (kind=HasAchievement) -> WACH.achievementId
WPCD.targetId (kind=AreaId) -> WMS.areaId
WPCD.targetId (kind=EventActive) -> WSEA.eventId
WPCD.targetId (kind=HasTitle) -> WTIT.titleId
WPCD.targetId (kind=FactionRep) -> WFAC.factionId
WPCD.targetId (kind=Class/Race) -> WCHC class/race id
Future format extensions can reference WPCD.conditionId in
their own gating fields — WTRG triggers gated by player
state, WGSP options visible only when conditions are met,
WMOU summon spells condition-gated by quest progress, etc.
Format:
• magic "WPCD", version 1, little-endian
• per condition: conditionId / groupId (0 = standalone) /
name / description / kind / aggregator / negated /
targetId / minValue / maxValue
Enums:
• Kind (17): AlwaysTrue / AlwaysFalse / QuestCompleted /
QuestActive / HasItem / HasSpell / MinLevel /
MaxLevel / ClassMatch / RaceMatch /
FactionRep / HasAchievement / TeamSize /
GuildLevel / EventActive / AreaId / HasTitle
• Aggregator (2): And / Or
API: WoweeConditionLoader::save / load / exists / findById.
Three preset emitters showcase typical usage:
• makeStarter — 4 standalone conditions covering the most
common kinds (quest-done / has-item /
min-level / class)
• makeGated — 5 conditions in 2 groups demonstrating
AND-aggregation (alliance + mage + lvl 60)
and OR-aggregation (did quest 1 OR quest 100)
• makeEvent — 3 event-gated conditions cross-referencing
WSEA event IDs (Hallow's End / Brewfest /
Winter's Veil)
CLI added (5 flags, 656 documented total now):
--gen-conditions / --gen-conditions-gated / --gen-conditions-event
--info-wpcd / --validate-wpcd
Validator catches: conditionId=0 + duplicates, kind /
aggregator out of range, kinds requiring targetId having
target=0 (skips AlwaysTrue/False, MinLevel/MaxLevel,
TeamSize, GuildLevel which use min/max instead), TeamSize
with min > max.
2026-05-09 18:18:27 -07:00
std : : printf ( " --gen-conditions <wpcd-base> [name] \n " ) ;
std : : printf ( " Emit .wpcd starter: 4 conditions covering quest-done / has-item / min-level / class kinds \n " ) ;
std : : printf ( " --gen-conditions-gated <wpcd-base> [name] \n " ) ;
std : : printf ( " Emit .wpcd 5 conditions in 2 groups (group 100 AND alliance+mage+lvl60; group 200 OR did-quest-1/100) \n " ) ;
std : : printf ( " --gen-conditions-event <wpcd-base> [name] \n " ) ;
std : : printf ( " Emit .wpcd 3 event-gated conditions referencing WSEA event IDs (Hallow's End / Brewfest / Winter's Veil) \n " ) ;
std : : printf ( " --info-wpcd <wpcd-base> [--json] \n " ) ;
std : : printf ( " Print WPCD entries (id / group / kind / aggregator / negated / target / min..max value / name) \n " ) ;
std : : printf ( " --validate-wpcd <wpcd-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, kind in 0..16, aggregator 0..1, kinds that need targetId have non-zero target \n " ) ;
2026-05-09 18:28:47 -07:00
std : : printf ( " --export-wpcd-json <wpcd-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wpcd to a human-editable JSON sidecar (defaults to <base>.wpcd.json) \n " ) ;
std : : printf ( " --import-wpcd-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wpcd.json sidecar back into binary .wpcd (accepts kind/aggregator int OR name forms) \n " ) ;
feat(pipeline): add WPET (Wowee Pet System) catalog
Novel open replacement for AzerothCore-style pet_template +
pet_levelstats SQL + the pet-related subsets of
CreatureFamily.dbc + SpellFamilyName.dbc. The 38th open
format added to the editor.
Defines two related kinds of player-controlled NPCs in
one catalog:
• Pet families — hunter pet families (Wolf / Cat / Bear /
Boar / Raptor / Spider / etc.) with
per-family ability sets, base stat
multipliers, and diet preferences
• Warlock minions — Imp / Voidwalker / Succubus /
Felhunter / Felguard, each with
their own summon spell, creature
template, and ability list
Cross-references with previously-added formats:
WPET.family.familyId -> WCRT.entry.familyId
(matches creature family)
WPET.family.abilities.spellId -> WSPL.entry.spellId
WPET.minion.summonSpellId -> WSPL.entry.spellId
WPET.minion.creatureId -> WCRT.entry.creatureId
(used for stat scaling)
WPET.minion.abilities.spellId -> WSPL.entry.spellId
The starter preset's familyIds (1=Wolf, 2=Cat) match
WCRT::FamilyId enum values, so a hunter taming a wolf via
WCRT links straight through to WPET ability sets.
Format:
• magic "WPET", version 1, little-endian
• families[]: familyId / name / description / icon /
petType / baseAttackSpeed / damageMultiplier /
armorMultiplier / dietMask / abilities[]
• minions[]: minionId / name / summonSpellId / creatureId /
abilities[] (each: spellId / rank / autocastDefault)
Enums:
• PetType (3): Cunning / Ferocity / Tenacity
(WotLK+ talent tree categorization)
• DietFlags: Meat / Fish / Bread / Cheese / Fruit / Fungus
API: WoweePetLoader::save / load / exists +
WoweePet::findFamily / findMinion + dietMaskName helper
that decodes a dietMask into a "meat+fish" string.
Three preset emitters showcase typical pet catalogs:
• makeStarter — 2 hunter families (Wolf + Cat) with full
3-ability sets + 1 warlock Imp
• makeHunter — 8 classic hunter families covering all
3 petType categories with appropriate
diet masks
• makeWarlock — 5 warlock minions each with summon spell
ID and creatureId pointing into WCRT
CLI added (5 flags, 663 documented total now):
--gen-pets / --gen-pets-hunter / --gen-pets-warlock
--info-wpet / --validate-wpet
Validator catches: ids=0 + duplicates, empty name, petType
out of range, baseAttackSpeed<=0 (would divide by zero in
DPS calc), dietMask=0 (pet cannot be fed for happiness),
minion missing summonSpellId / creatureId.
2026-05-09 18:27:02 -07:00
std : : printf ( " --gen-pets <wpet-base> [name] \n " ) ;
std : : printf ( " Emit .wpet starter: 2 hunter families (Wolf + Cat) + 1 warlock minion (Imp) with WSPL ability refs \n " ) ;
std : : printf ( " --gen-pets-hunter <wpet-base> [name] \n " ) ;
std : : printf ( " Emit .wpet 8 classic hunter families (Wolf/Cat/Bear/Boar/Raptor/Hyena/Spider/Crab) with diet+petType \n " ) ;
std : : printf ( " --gen-pets-warlock <wpet-base> [name] \n " ) ;
std : : printf ( " Emit .wpet 5 warlock minions (Imp/Voidwalker/Succubus/Felhunter/Felguard) with summon spell + WCRT ref \n " ) ;
std : : printf ( " --info-wpet <wpet-base> [--json] \n " ) ;
std : : printf ( " Print WPET families (id / petType / atkSpd / dmg+arm mult / diet) + minions (id / summon / creatureId) \n " ) ;
std : : printf ( " --validate-wpet <wpet-base> [--json] \n " ) ;
std : : printf ( " Static checks: ids>0+unique, name not empty, petType 0..2, atkSpeed>0, minion needs summon+creatureId \n " ) ;
2026-05-09 18:37:12 -07:00
std : : printf ( " --export-wpet-json <wpet-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wpet to a human-editable JSON sidecar (defaults to <base>.wpet.json) \n " ) ;
std : : printf ( " --import-wpet-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wpet.json sidecar back into binary .wpet (accepts petType int OR name string) \n " ) ;
feat(pipeline): add WAUC (Wowee Auction House) catalog
Novel open replacement for Blizzard's AuctionHouse.dbc +
the AzerothCore-style auctionhouse / auctionhousebot SQL
tables. The 39th open format added to the editor.
Defines per-house rules for the auction system: faction
access, deposit rate (basis points of buyout price), house
cut on successful sale, three listing duration tiers with
per-tier deposit multipliers, disallowed item-class bitmask,
and the auctioneer NPC.
Cross-references with previously-added formats:
WAUC.entry.auctioneerNpcId -> WCRT.entry.creatureId
(Auctioneer-flagged NPC)
WAUC.entry.disallowedClassMask
bitmask of WIT.Class values
that may not be auctioned at
this house
The faction-pair preset captures the canonical asymmetry:
faction houses charge 5% on a successful sale while neutral
houses charge 15% — the cross-faction tax that makes
neutral AHs profitable for goblins.
Format:
• magic "WAUC", version 1, little-endian
• per house: houseId / auctioneerNpcId / name /
factionAccess / baseDepositRateBp / houseCutRateBp /
maxBidCopper / 3 duration hours + 3 deposit multipliers /
disallowedClassMask
Enums:
• FactionAccess (4): Alliance / Horde / Neutral / Both
• Rates use basis points: 10000 = 100%
API: WoweeAuctionLoader::save / load / exists / findById.
Three preset emitters showcase typical auction setups:
• makeStarter — 1 neutral house with default 12h /
24h / 48h tiers
• makeFactionPair — 3 houses (Stormwind / Orgrimmar /
Booty Bay) with auctioneer NPC IDs
+ canonical faction-vs-neutral cut
rates
• makeRestricted — 1 house disallowing Containers (1) +
Quest items (12) + Keys (13) with
tighter durations + 1000g bid cap
CLI added (5 flags, 670 documented total now):
--gen-auction / --gen-auction-pair / --gen-auction-restricted
--info-wauc / --validate-wauc
Validator catches: houseId=0 + duplicates, empty name,
factionAccess out of range, duration tier=0, durations not
in short<=medium<=long order, houseCutRateBp >= 100% (seller
loses money on a sale), warns on >50% cut.
2026-05-09 18:34:54 -07:00
std : : printf ( " --gen-auction <wauc-base> [name] \n " ) ;
std : : printf ( " Emit .wauc starter: 1 neutral house with stock 12h/24h/48h tiers and 5%% house cut \n " ) ;
std : : printf ( " --gen-auction-pair <wauc-base> [name] \n " ) ;
std : : printf ( " Emit .wauc 3 houses (Stormwind / Orgrimmar / Booty Bay) — faction 5%% cut vs neutral 15%% asymmetry \n " ) ;
std : : printf ( " --gen-auction-restricted <wauc-base> [name] \n " ) ;
std : : printf ( " Emit .wauc 1 house with disallowedClassMask (no Containers/Quest/Keys) + tighter durations + bid cap \n " ) ;
std : : printf ( " --info-wauc <wauc-base> [--json] \n " ) ;
std : : printf ( " Print WAUC houses (id / faction / deposit + cut percent / 3 duration tiers / disallow mask / npc) \n " ) ;
std : : printf ( " --validate-wauc <wauc-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, faction 0..3, durations short<=medium<=long, cut < 100%% \n " ) ;
2026-05-09 18:45:01 -07:00
std : : printf ( " --export-wauc-json <wauc-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wauc to a human-editable JSON sidecar (defaults to <base>.wauc.json) \n " ) ;
std : : printf ( " --import-wauc-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wauc.json sidecar back into binary .wauc (accepts factionAccess int OR name string) \n " ) ;
feat(pipeline): add WCHN (Wowee Chat Channel) catalog
Novel open replacement for Blizzard's ChatChannels.dbc +
the AzerothCore-style chat_channel SQL tables. The 40th
open format added to the editor.
Defines the world chat channel system: General, Trade,
LookingForGroup, GuildRecruitment, LocalDefense, plus
per-zone area channels and custom user-created channels.
Each channel has access rules (faction / level), join
behavior (auto vs opt-in), broadcast policy (announce /
moderated), and optional area / map gating that auto-joins
or auto-leaves the channel as the player moves.
Cross-references with previously-added formats:
WCHN.entry.areaIdGate -> WMS.area.areaId
(channel auto-attaches in this area)
WCHN.entry.mapIdGate -> WMS.map.mapId
(channel auto-attaches on this map)
Format:
• magic "WCHN", version 1, little-endian
• per channel: channelId / name / description /
channelType / factionAccess / autoJoin / announce /
moderated / minLevel / areaIdGate / mapIdGate
Enums:
• ChannelType (10): AreaLocal / Zone / Continent / World /
Trade / LookingForGroup / GuildRecruit /
LocalDefense / Custom / Pvp
• FactionAccess (3): Alliance / Horde / Both
API: WoweeChannelLoader::save / load / exists / findById.
Three preset emitters:
• makeStarter — 4 stock channels (General Zone +
Trade + LFG + GuildRecruit) with
default autoJoin policies
• makeCity — 5 city-specific channels (3 Stormwind +
2 Orgrimmar) with mapId / areaId gates
so they auto-attach on entry
• makeModerated — 3 moderated / restricted channels
(LocalDefense level 10+, WorldDefense
moderated, RaidCoordination level 60+)
CLI added (5 flags, 677 documented total now):
--gen-channels / --gen-channels-city / --gen-channels-moderated
--info-wchn / --validate-wchn
Validator catches: channelId=0 + duplicates, empty name,
unknown channelType / factionAccess, world / continent
channel with area or map gate (gate is silently ignored at
runtime — usually a typo), minLevel=0 (no level gate at all).
2026-05-09 18:43:26 -07:00
std : : printf ( " --gen-channels <wchn-base> [name] \n " ) ;
std : : printf ( " Emit .wchn starter: 4 stock channels (General / Trade / LFG / GuildRecruit) with autoJoin defaults \n " ) ;
std : : printf ( " --gen-channels-city <wchn-base> [name] \n " ) ;
std : : printf ( " Emit .wchn 5 city channels (Stormwind General/Trade/LFG + Orgrimmar General/Trade) with map+area gates \n " ) ;
std : : printf ( " --gen-channels-moderated <wchn-base> [name] \n " ) ;
std : : printf ( " Emit .wchn 3 moderated channels (LocalDefense / WorldDefense moderated / RaidCoordination level 60+) \n " ) ;
std : : printf ( " --info-wchn <wchn-base> [--json] \n " ) ;
std : : printf ( " Print WCHN entries (id / type / faction / autoJoin/announce/moderated / level / map+area gates / name) \n " ) ;
std : : printf ( " --validate-wchn <wchn-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, type 0..9, faction 0..2, world+area-gate combo warning \n " ) ;
2026-05-09 18:52:32 -07:00
std : : printf ( " --export-wchn-json <wchn-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wchn to a human-editable JSON sidecar (defaults to <base>.wchn.json) \n " ) ;
std : : printf ( " --import-wchn-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wchn.json sidecar back into binary .wchn (accepts channelType/factionAccess int OR name string) \n " ) ;
feat(pipeline): add WCMS (Wowee Cinematic) catalog
41st open format — replaces Movie.dbc / CinematicCamera.dbc /
CinematicSequences.dbc plus the AzerothCore cinematic_camera SQL
table. Defines pre-rendered videos, in-engine camera flythroughs,
text crawls, and still images, each with a media path, duration,
skippable flag, and a polymorphic trigger that fires on quest
events / class first-login / zone entry / dungeon clear /
achievements / level milestones.
Cross-references with prior formats — triggerTargetId resolves
by triggerKind to WQT.questId / WMS.areaId / WMS.mapId /
WCHC.classId / WACH.achievementId, and soundtrackId points at
WSND.soundId.
CLI: --gen-cinematics (3-entry starter), --gen-cinematics-intros
(4 class intros), --gen-cinematics-quests (3 quest-bound
cinematics referencing demo questIds 1/100/102), --info-wcms,
--validate-wcms with --json variants. Validator catches
id=0/duplicates, empty name/mediaPath, kind/trigger out of
range, missing target id for non-Manual/Login/LevelUp triggers,
zero-duration entries, and non-skippable pre-rendered videos.
2026-05-09 18:50:43 -07:00
std : : printf ( " --gen-cinematics <wcms-base> [name] \n " ) ;
std : : printf ( " Emit .wcms starter: 3 cinematics (pre-rendered intro / quest cutscene / login splash) \n " ) ;
std : : printf ( " --gen-cinematics-intros <wcms-base> [name] \n " ) ;
std : : printf ( " Emit .wcms 4 class intros (Warrior / Hunter / Rogue / Mage) triggered on first ClassStart \n " ) ;
std : : printf ( " --gen-cinematics-quests <wcms-base> [name] \n " ) ;
std : : printf ( " Emit .wcms 3 quest-bound cinematics referencing WQT questIds 1 / 100 / 102 (start / start / end) \n " ) ;
std : : printf ( " --info-wcms <wcms-base> [--json] \n " ) ;
std : : printf ( " Print WCMS entries (id / kind / trigger / target / duration / skippable / soundtrackId / name) \n " ) ;
std : : printf ( " --validate-wcms <wcms-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name+mediaPath not empty, kind 0..4, trigger 0..8, target required for non-Manual triggers \n " ) ;
2026-05-09 18:56:29 -07:00
std : : printf ( " --export-wcms-json <wcms-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wcms to a human-editable JSON sidecar (defaults to <base>.wcms.json) \n " ) ;
std : : printf ( " --import-wcms-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wcms.json sidecar back into binary .wcms (accepts kind/triggerKind int OR name string) \n " ) ;
feat(pipeline): add WGLY (Wowee Glyph) catalog
42nd open format — replaces GlyphProperties.dbc + GlyphSlot.dbc
plus the AzerothCore-style glyph_properties SQL table. Defines
the WotLK glyph system: per-class inscribable glyphs that
modify spell behavior. Each entry pairs a glyph item (the
inscriber's craft output) with the spell aura that applies the
modification, tagged with a Major / Minor / Prime slot type and
a classMask of allowed classes.
Cross-references with prior formats — spellId points at
WSPL.spellId (the aura), itemId points at WIT.itemId (the
inscribed item), and classMask bit positions match the WCHC
classId enum (1=Warrior, 2=Paladin, 3=Hunter, etc).
CLI: --gen-glyphs (3-entry per-role starter), --gen-glyphs-warrior
(6-entry full warrior allotment), --gen-glyphs-universal (4
classMask=All utility glyphs), --info-wgly, --validate-wgly with
--json variants. Validator catches id=0/duplicates, empty name,
spellId=0 (glyph applies no aura), classMask=0 (no class can
inscribe), itemId=0 warning, requiredLevel<25 warning (below
WotLK glyph threshold), and glyphType out-of-range.
2026-05-09 18:55:22 -07:00
std : : printf ( " --gen-glyphs <wgly-base> [name] \n " ) ;
std : : printf ( " Emit .wgly starter: 3 glyphs (1 warrior + 1 mage + 1 rogue) showing per-class Major slot picks \n " ) ;
std : : printf ( " --gen-glyphs-warrior <wgly-base> [name] \n " ) ;
std : : printf ( " Emit .wgly 6 warrior glyphs (3 major + 3 minor) demonstrating per-class allotment \n " ) ;
std : : printf ( " --gen-glyphs-universal <wgly-base> [name] \n " ) ;
std : : printf ( " Emit .wgly 4 universal glyphs (classMask=All) covering hearthstone/levitate/mounting/salvation \n " ) ;
std : : printf ( " --info-wgly <wgly-base> [--json] \n " ) ;
std : : printf ( " Print WGLY entries (id / type / spellId / itemId / classMask / requiredLevel / name) \n " ) ;
std : : printf ( " --validate-wgly <wgly-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name+spellId not empty, type 0..2, classMask>0, level<25 warning, missing-itemId warning \n " ) ;
2026-05-09 19:01:03 -07:00
std : : printf ( " --export-wgly-json <wgly-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgly to a human-editable JSON sidecar (defaults to <base>.wgly.json) \n " ) ;
std : : printf ( " --import-wgly-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgly.json sidecar back into binary .wgly (accepts glyphType int OR name string) \n " ) ;
feat(pipeline): add WVHC (Wowee Vehicle) catalog
43rd open format — replaces Vehicle.dbc + VehicleSeat.dbc plus
the AzerothCore-style vehicle_template SQL tables. Defines
drivable vehicles: tanks, demolishers, motorcycles, gryphons,
choppers, siege weapons, multi-passenger transports. Each entry
pairs a creature template (the rendered model) with a fixed
seat layout — driver / passenger / gunner seats with their own
attachment points, control flags (kSeatDriver / kSeatGunner /
kSeatPassenger / kSeatHidesPlayer / kSeatNoEjectByCC), and
per-seat abilities mounted to the action bar.
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), flightCapabilityId points
at WMNT.mountId for shared fly-speed tables, and per-seat
controlSpellId / exitSpellId point at WSPL.spellId.
CLI: --gen-vehicles (3-vehicle starter chopper/wind-rider/tank),
--gen-vehicles-siege (3 siege weapons with control spellIds),
--gen-vehicles-flying (3 flying mounts cross-ref WMNT
flightCapabilityIds), --info-wvhc, --validate-wvhc with --json
variants. Validator catches id=0/duplicates, missing creature,
enum out-of-range, empty seat list, flying-vehicle on wrong
movement (would fall through world), driver-flag exclusivity
(0 or >1 drivers), and duplicate seatIndex within a vehicle.
2026-05-09 18:59:49 -07:00
std : : printf ( " --gen-vehicles <wvhc-base> [name] \n " ) ;
std : : printf ( " Emit .wvhc starter: 3 vehicles (chopper / wind rider / salvaged tank) covering ground+air+siege roles \n " ) ;
std : : printf ( " --gen-vehicles-siege <wvhc-base> [name] \n " ) ;
std : : printf ( " Emit .wvhc 3 siege weapons (Demolisher 2-seat / Glaive Thrower / Salvaged Cannon) with control spellIds \n " ) ;
std : : printf ( " --gen-vehicles-flying <wvhc-base> [name] \n " ) ;
std : : printf ( " Emit .wvhc 3 flying mounts (Wind Rider / Storm Gryphon / Twilight Drake) cross-ref WMNT flightCapabilityIds \n " ) ;
std : : printf ( " --info-wvhc <wvhc-base> [--json] \n " ) ;
std : : printf ( " Print WVHC entries with seat layout (id / creature / kind / movement / power / seat count / name) \n " ) ;
std : : printf ( " --validate-wvhc <wvhc-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, creatureId>0, kind/movement/power in range, exactly 1 driver seat, no duplicate seatIndex \n " ) ;
2026-05-09 19:02:17 -07:00
std : : printf ( " --export-wvhc-json <wvhc-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wvhc to a human-editable JSON sidecar with nested seat arrays (defaults to <base>.wvhc.json) \n " ) ;
std : : printf ( " --import-wvhc-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wvhc.json sidecar back into binary .wvhc (accepts vehicleKind/movementKind/powerType int OR name string) \n " ) ;
feat(pipeline): add WHOL (Wowee Holiday) catalog
44th open format — replaces Holidays.dbc + HolidayDescriptions.dbc
+ HolidayNames.dbc plus the AzerothCore-style game_event SQL
tables. Defines time-gated world events: seasonal holidays
(Hallow's End / Brewfest / Winter Veil), weekly call-to-arms BG
bonuses, world-PvP windows (Wintergrasp), one-shot specials, and
recurring daily / weekly resets. Each holiday has a recurrence
rule (Annual / Monthly / WeeklyRecur / OneTime), a calendar
window (startMonth + startDay + durationHours), and optional
cross-refs to a feature creature, an intro quest, and a token /
item reward issued during the window.
Cross-references with prior formats — holidayQuestId points at
WQT.questId, bossCreatureId points at WCRT.creatureId,
itemRewardId points at WIT.itemId, and areaIdGate / mapIdGate
point at WMS.areaId / WMS.mapId.
CLI: --gen-holidays (3 seasonal starter), --gen-holidays-weekly
(3 weekly BG call-to-arms windows), --gen-holidays-special (3
world-PvP / lunar / children events), --info-whol, --validate-whol
with --json variants. Validator catches id=0/duplicates, kind /
recurrence out of range, durationHours=0, invalid month/day for
non-weekly recurrence, and calendar-only events (no quest +
boss + reward) as a warning.
2026-05-09 19:05:33 -07:00
std : : printf ( " --gen-holidays <whol-base> [name] \n " ) ;
std : : printf ( " Emit .whol starter: 3 seasonal holidays (Hallow's End / Brewfest / Winter Veil) with boss+reward+quest cross-refs \n " ) ;
std : : printf ( " --gen-holidays-weekly <whol-base> [name] \n " ) ;
std : : printf ( " Emit .whol 3 weekly call-to-arms BG bonus windows (Warsong Gulch / Arathi Basin / Eye of the Storm) \n " ) ;
std : : printf ( " --gen-holidays-special <whol-base> [name] \n " ) ;
std : : printf ( " Emit .whol 3 special events (Wintergrasp world-PvP / Lunar Festival / Children's Week) \n " ) ;
std : : printf ( " --info-whol <whol-base> [--json] \n " ) ;
std : : printf ( " Print WHOL entries (id / kind / recurrence / start MM/DD / duration / quest+boss+reward IDs / name) \n " ) ;
std : : printf ( " --validate-whol <whol-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, kind 0..5, recurrence 0..3, duration>0, valid month/day for non-weekly, calendar-only warning \n " ) ;
2026-05-09 19:07:08 -07:00
std : : printf ( " --export-whol-json <whol-base> [out.json] \n " ) ;
std : : printf ( " Export binary .whol to a human-editable JSON sidecar (defaults to <base>.whol.json) \n " ) ;
std : : printf ( " --import-whol-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .whol.json sidecar back into binary .whol (accepts holidayKind/recurrence int OR name string) \n " ) ;
feat(pipeline): add WLIQ (Wowee Liquid Type) catalog
45th open format — replaces LiquidType.dbc plus the
AzerothCore-style terrain liquid descriptor data. Defines
liquid materials used by terrain MCNK liquid layers, WMO
interior pools, and procedurally generated fluid bodies in
custom zones. Each liquid pairs a render material (shader +
texture array + flow vectors + fog color) with gameplay data
(damage spell, raw DPS, ambient + splash audio cross-refs).
Cross-references with prior formats — ambientSoundId and
splashSoundId point at WSND.soundId, damageSpellId points at
WSPL.spellId.
10 liquid kinds (Water / Magma / Slime / OceanSalt / FelFire /
HolyLight / TarOil / AcidBog / FrozenWater / UnderworldGoo)
covering both natural and magical fluids. Per-liquid: viscosity
(0=water, 1=slime), flow direction+speed (radians+units/sec),
fog density+RGB, packed minimap RGBA color.
CLI: --gen-liquids (3-entry classic Water/Lava/Slime starter),
--gen-liquids-magical (4 magical pools incl. fel/holy/cosmic),
--gen-liquids-hazardous (3 high-damage liquids with WSPL DoT
cross-refs), --info-wliq, --validate-wliq with --json variants.
Validator catches id=0/duplicates, missing shader/material,
kind out of range, fog/viscosity outside 0..1, hazardous-kind-
without-damage warning, and Water/OceanSalt-with-damage warning
to flag accidental misconfiguration.
2026-05-09 19:10:03 -07:00
std : : printf ( " --gen-liquids <wliq-base> [name] \n " ) ;
std : : printf ( " Emit .wliq starter: 3 stock liquids (Fresh Water / Lava / Sludge Slime) with shaders+sounds+DPS \n " ) ;
std : : printf ( " --gen-liquids-magical <wliq-base> [name] \n " ) ;
std : : printf ( " Emit .wliq 4 magical liquids (Fel Fire / Holy Light / Underworld / Cosmic) with damage spell IDs \n " ) ;
std : : printf ( " --gen-liquids-hazardous <wliq-base> [name] \n " ) ;
std : : printf ( " Emit .wliq 3 high-damage liquids (Naxx Slime / Acid Bog / Fel Lava) with WSPL cross-refs \n " ) ;
std : : printf ( " --info-wliq <wliq-base> [--json] \n " ) ;
std : : printf ( " Print WLIQ entries (id / kind / fog RGB / density / viscosity / DPS / spell+sound IDs / name) \n " ) ;
std : : printf ( " --validate-wliq <wliq-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name+shader+material not empty, kind 0..9, fog/visc 0..1, hazardous-no-damage warning \n " ) ;
2026-05-09 19:11:14 -07:00
std : : printf ( " --export-wliq-json <wliq-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wliq to a human-editable JSON sidecar (defaults to <base>.wliq.json) \n " ) ;
std : : printf ( " --import-wliq-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wliq.json sidecar back into binary .wliq (accepts liquidKind int OR name string) \n " ) ;
2026-05-09 19:14:55 -07:00
std : : printf ( " --list-formats [--json] \n " ) ;
std : : printf ( " Print the catalog of all novel open formats (magic / extension / category / replaces / description) \n " ) ;
2026-05-09 19:16:26 -07:00
std : : printf ( " --info-magic <path> [--json] \n " ) ;
std : : printf ( " Auto-detect any .w* file by 4-byte magic; report format / version / catalog name / entry count + suggest --info-* flag \n " ) ;
2026-05-09 19:27:48 -07:00
std : : printf ( " --summary-dir <dir> [--json] \n " ) ;
std : : printf ( " Recursively walk a directory; report per-format file count, total entries, and bytes for every Wowee open format found \n " ) ;
2026-05-09 19:29:18 -07:00
std : : printf ( " --rename-by-magic <file> [--dry-run] [--force] \n " ) ;
std : : printf ( " Recover the correct .w* extension on a file by reading its 4-byte magic. --dry-run prints the planned move; --force overwrites \n " ) ;
2026-05-09 19:44:52 -07:00
std : : printf ( " --bulk-rename-by-magic <dir> [--dry-run] [--force] \n " ) ;
std : : printf ( " Apply --rename-by-magic recursively to every file in <dir>. Conflicts are skipped without --force; exits 1 if any rename failed \n " ) ;
2026-05-09 19:58:01 -07:00
std : : printf ( " --touch-tree <dir> [--json] [--quiet] \n " ) ;
std : : printf ( " CI integrity check: open every recognized .w* file in <dir>, parse standard header, report PASS/FAIL + extension mismatches. Exit 1 on any failure \n " ) ;
2026-05-09 20:16:27 -07:00
std : : printf ( " --tree-summary-md <dir> [out.md] \n " ) ;
std : : printf ( " Emit a Markdown report of a content tree (per-format counts + per-file detail with catalog name + entry count). Stdout if no out path \n " ) ;
2026-05-09 20:27:16 -07:00
std : : printf ( " --catalog-grep <pattern> <dir> [--case-sensitive] [--json] \n " ) ;
std : : printf ( " Recursively search catalog NAMES (the internal name field) across .w* files in <dir>. Case-insensitive by default. Exit 1 if no match \n " ) ;
feat(editor): add --diff-headers cross-file header comparison
Compares two .w* files at the standard catalog header level:
4-byte magic, version, catalog name, entry count, total file
bytes. Useful for confirming a JSON round-trip didn't drift,
checking whether two preset emissions produced equivalent
output, or quickly diagnosing when a content snapshot has
silently shifted (entry count up means content was added,
file bytes up but everything else same means entry payloads
got fatter).
Output uses = / ≠ markers per field so visual scanning is
fast. Three diagnostic summary cases: identical headers (and
same bytes — possibly byte-equal, run cmp(1) to confirm),
same shape but bytes differ (entry payloads diverged), and
different formats entirely (files are unrelated).
Returns exit 1 if any field differs, so the flag composes
into shell pipelines (`if diff-headers a.wcms b.wcms; then ...`).
World/asset formats stop after magic since their layouts
diverge from the standard catalog header.
Supports --json variant for tooling integration.
2026-05-09 21:27:26 -07:00
std : : printf ( " --diff-headers <fileA> <fileB> [--json] \n " ) ;
std : : printf ( " Compare two .w* files at the standard catalog header level (magic / version / name / entry count / file size). Exit 1 if any field differs \n " ) ;
2026-05-09 21:45:54 -07:00
std : : printf ( " --audit-tree <dir> [--json] \n " ) ;
std : : printf ( " Walk directory recursively and flag corrupted/misnamed Wowee files: too-small, unknown-magic, ext/magic mismatch, magic-without-ext, truncated headers. Exit 1 on any issue \n " ) ;
2026-05-09 21:57:26 -07:00
std : : printf ( " --magic-fix <dir> [--apply] [--json] \n " ) ;
std : : printf ( " Auto-rename files whose extension doesn't match their magic to the canonical extension. Default is dry-run; pass --apply to commit. Skips collisions where the target already exists. Natural follow-up to --audit-tree \n " ) ;
2026-05-09 22:19:09 -07:00
std : : printf ( " --bulk-validate <dir> [--json] \n " ) ;
std : : printf ( " Recursively run each format's --validate-X validator across every recognized .w* file. Reports per-file pass/fail counts; lists failure paths. Asset formats with no validator are skipped. Exit 1 if any failure \n " ) ;
2026-05-09 22:35:12 -07:00
std : : printf ( " --bulk-export-json <dir> [--json] \n " ) ;
std : : printf ( " Recursively export every recognized .w* file to its JSON sidecar via the per-format --export-X-json flag. Useful for git-friendly diffs of binary catalogs. Exit 1 if any failure \n " ) ;
std : : printf ( " --bulk-import-json <dir> [--json] \n " ) ;
std : : printf ( " Recursively import every .wXXX.json sidecar back to its binary .w* form via the per-format --import-X-json flag. Inverse of --bulk-export-json. Exit 1 if any failure \n " ) ;
2026-05-09 22:46:52 -07:00
std : : printf ( " --diff-tree <dirA> <dirB> [--json] \n " ) ;
std : : printf ( " Compare two directory trees of .w* catalogs at the magic+size level. Reports only-in-A / only-in-B / magic-changed / size-changed / identical counts and lists changed paths. Exit 1 if any difference \n " ) ;
2026-05-09 23:07:09 -07:00
std : : printf ( " --orphan-jsons <dir> [--json] \n " ) ;
std : : printf ( " Find .wXXX.json sidecars whose binary .wXXX is missing. Useful after deleting/moving binaries — orphan JSONs accumulate noise and may shadow re-imports. Exit 1 if any orphans found \n " ) ;
2026-05-09 23:18:46 -07:00
std : : printf ( " --list-by-magic <dir> <magic> [--json] \n " ) ;
std : : printf ( " List every file in a directory tree matching a 4-char magic (e.g. WSPL). Reports per-file size + entry count + catalog name + relative path. Exit 1 if no matches \n " ) ;
2026-05-09 23:21:32 -07:00
std : : printf ( " --catalog-stats <file> [--json] \n " ) ;
std : : printf ( " Single-file deep stats — header bytes vs entry-section bytes, average entry size, sampled entry IDs. Useful for sizing analysis (which catalogs are biggest, where do the bytes go) \n " ) ;
feat(pipeline): add WANI (Wowee Animation) catalog
46th open format — replaces AnimationData.dbc plus the
hard-coded animation-id tables in M2 model loaders. Defines
named animations (Stand, Walk, Run, Cast, Death, MountIdle,
Fly, ...) with fallback chains, behavior tier (default /
mounted / sitting / aerial / swimming), and weapon-flag
bitmasks that select the correct animation variant when the
model wields 1H / 2H / dual / bow / rifle / wand / etc.
Cross-references with prior formats — fallbackId resolves
within the same WANI catalog (graceful degradation when the
requested animation is absent: Run falls back to Walk,
Attack2H falls back to Attack1H).
10 weapon-flag constants + 6 behavior flags (Looped,
BlendableCycle, Interruptable, MovementSync, OneShot,
PreserveAtEnd). 5 behavior tiers. CLI: --gen-animations
(5 essentials), --gen-animations-combat (8 weapon-typed
attacks + parry + channel), --gen-animations-movement (6
locomotion anims with tier transitions). Validator catches
id-uniqueness, fallback-self-loop, looped-without-duration,
mutually-exclusive Looped+OneShot flags, weaponFlags=0
warning, and unresolved fallback warnings.
Also extends --list-formats and --info-magic with WANI.
2026-05-09 19:19:13 -07:00
std : : printf ( " --gen-animations <wani-base> [name] \n " ) ;
std : : printf ( " Emit .wani starter: 5 essential animations (Stand / Walk / Run / Death / AttackUnarmed) with fallback chains \n " ) ;
std : : printf ( " --gen-animations-combat <wani-base> [name] \n " ) ;
std : : printf ( " Emit .wani 8 combat anims (1H/2H/dual-wield/bow/rifle/thrown + parry + channel) with weapon-flag bitmasks \n " ) ;
std : : printf ( " --gen-animations-movement <wani-base> [name] \n " ) ;
std : : printf ( " Emit .wani 6 movement anims (Walk/Run/Sprint/Swim/Mount/Fly) with behavior-tier transitions (default/aerial/swim) \n " ) ;
std : : printf ( " --info-wani <wani-base> [--json] \n " ) ;
std : : printf ( " Print WANI entries (id / tier / flags / weapon mask / loop duration / fallback / name) \n " ) ;
std : : printf ( " --validate-wani <wani-base> [--json] \n " ) ;
std : : printf ( " Static checks: id-unique, name not empty, tier 0..4, fallback != self, loop+oneshot exclusivity, looped requires duration \n " ) ;
2026-05-09 19:20:22 -07:00
std : : printf ( " --export-wani-json <wani-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wani to a human-editable JSON sidecar (defaults to <base>.wani.json) \n " ) ;
std : : printf ( " --import-wani-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wani.json sidecar back into binary .wani (accepts behaviorTier int OR name string) \n " ) ;
feat(pipeline): add WSVK (Wowee Spell Visual Kit) catalog
47th open format — replaces SpellVisualKit.dbc +
SpellVisualEffectName.dbc plus the AzerothCore-style spell
visual SQL data. Defines per-spell visual presentations:
cast-bar effect model, projectile model + travel speed +
arc gravity, impact effect model, hand effect on the caster,
and the animations + sounds that fire at cast / channel /
impact time.
Cross-references with prior formats — castAnimId / impactAnimId
/ precastAnimId point at WANI.animationId, castSoundId /
impactSoundId point at WSND.soundId. Spell catalogs (WSPL)
will reference visualKitId here to bind "what mechanically
happens" to "what plays visually."
CLI: --gen-svk (3-kit Frostbolt/Fireball/HealingTouch starter
showing projectile + AoE + heal patterns), --gen-svk-combat
(5 melee/ranged with WANI animation refs), --gen-svk-utility
(4 portal/hearth/mount/resurrect with no projectile),
--info-wsvk, --validate-wsvk with --json variants. Validator
catches id=0/duplicates, missing name, negative speeds/radii,
projectile-model + speed coherence (model without speed =
never travels; speed without model = invisible), and a
no-effect catch-all (no models + no anims + no sounds).
2026-05-09 19:23:36 -07:00
std : : printf ( " --gen-svk <wsvk-base> [name] \n " ) ;
std : : printf ( " Emit .wsvk starter: 3 visual kits (Frostbolt / Fireball / HealingTouch) with projectile + impact + hand effects \n " ) ;
std : : printf ( " --gen-svk-combat <wsvk-base> [name] \n " ) ;
std : : printf ( " Emit .wsvk 5 combat visuals (sword/arrow/groundpound/parry/deflect) with WANI animation cross-refs \n " ) ;
std : : printf ( " --gen-svk-utility <wsvk-base> [name] \n " ) ;
std : : printf ( " Emit .wsvk 4 utility visuals (portal/hearthstone/mount-summon/resurrect) with no projectile \n " ) ;
std : : printf ( " --info-wsvk <wsvk-base> [--json] \n " ) ;
std : : printf ( " Print WSVK entries (id / cast+impact anim IDs / projectile speed+gravity / cast duration / AoE radius / sounds / name) \n " ) ;
std : : printf ( " --validate-wsvk <wsvk-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, no negative speeds/radii, projectile-model + speed coherence, no-effect warning \n " ) ;
2026-05-09 19:24:37 -07:00
std : : printf ( " --export-wsvk-json <wsvk-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsvk to a human-editable JSON sidecar (defaults to <base>.wsvk.json) \n " ) ;
std : : printf ( " --import-wsvk-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsvk.json sidecar back into binary .wsvk \n " ) ;
feat(pipeline): add WWUI (Wowee World-State UI) catalog
48th open format — replaces WorldStateUI.dbc plus the
AzerothCore-style world_state SQL data. Defines on-screen UI
elements that surface server-side world-state variables: BG
scoreboards (flag captures, base controls), Wintergrasp tank
counters, Eye of the Storm flag-carrier indicator, dungeon
boss progress, world-event collection trackers.
Each entry binds a server-side variableIndex to a UI panel
kind (counter / timer / flag-icon / progress-bar / two-sided
score / custom) gated by mapId+areaId, with optional
alwaysVisible and hideWhenZero flags and a chosen panel
position (top / bottom / top-left / top-right / center).
Cross-references with prior formats — mapId points at
WMS.mapId and areaId points at WMS.areaId.
CLI: --gen-wsui (3-entry BG scoreboard starter for WSG/AB/
EotS), --gen-wsui-wintergrasp (4-entry full Wintergrasp UI),
--gen-wsui-dungeon (3-entry boss/keys/treasure hunt UI),
--info-wwui, --validate-wwui with --json variants. Validator
catches id=0/duplicates, kind/position out of range,
variableIndex=0 warning, alwaysVisible+hideWhenZero conflict
warning, and (mapId, variableIndex) collision warning when
two entries would read the same server slot on the same map.
Also extends --list-formats and --info-magic with WWUI.
2026-05-09 19:32:15 -07:00
std : : printf ( " --gen-wsui <wwui-base> [name] \n " ) ;
std : : printf ( " Emit .wwui starter: 3 BG scoreboards (WSG flag captures, AB resources, EotS flag carrier) \n " ) ;
std : : printf ( " --gen-wsui-wintergrasp <wwui-base> [name] \n " ) ;
std : : printf ( " Emit .wwui 4 Wintergrasp UI (alliance+horde tank counts, time remaining, towers controlled) \n " ) ;
std : : printf ( " --gen-wsui-dungeon <wwui-base> [name] \n " ) ;
std : : printf ( " Emit .wwui 3 dungeon UI (boss progress bar, key fragments collected, treasure hunt counter) \n " ) ;
std : : printf ( " --info-wwui <wwui-base> [--json] \n " ) ;
std : : printf ( " Print WWUI entries (id / kind / panel position / always-visible / hide-when-zero / map+area / variableIndex / default / name) \n " ) ;
std : : printf ( " --validate-wwui <wwui-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, kind 0..5, position 0..4, alwaysVis+hideZero conflict, (mapId, varIdx) collision warning \n " ) ;
2026-05-09 19:33:37 -07:00
std : : printf ( " --export-wwui-json <wwui-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wwui to a human-editable JSON sidecar (defaults to <base>.wwui.json) \n " ) ;
std : : printf ( " --import-wwui-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wwui.json sidecar back into binary .wwui (accepts displayKind/panelPosition int OR name string) \n " ) ;
feat(pipeline): add WPCN (Wowee Player Condition) catalog
49th open format — replaces PlayerCondition.dbc plus the
AzerothCore-style condition resolver. Defines reusable
boolean checks that other catalogs reference by conditionId
to gate gossip options, vendor items, quest availability,
achievement criteria, spell trainer offerings.
16 condition kinds (Always, Race, Class, Level, Zone, Map,
Reputation, AchievementWon, QuestComplete, QuestActive,
SpellKnown, ItemEquipped, Faction, InCombat, Mounted,
Resting), 8 comparison ops (==, !=, >, >=, <, <=, in-set,
not-in-set), and 4 chain ops (none, and, or, not) — chain
multiple conditions via chainNextId to express arbitrary
boolean trees.
Cross-references with prior formats — targetIdA is
polymorphic by conditionKind: resolves to WCHC raceId/classId,
WMS areaId/mapId, WFAC factionId, WACH achievementId, WQT
questId, WSPL spellId, or WIT itemId. chainNextId resolves
within the same WPCN catalog.
CLI: --gen-pcn (3 single-check starters), --gen-pcn-quest-gates
(4 cross-format quest gates with real WQT/WFAC/WACH/WMS IDs),
--gen-pcn-composite (3 leaves + 3 chained roots showing AND/
OR/NOT). Validator catches id=0/duplicates, kind/op out of
range, chain self-loop (infinite recursion), chainOp set
without chainNextId (dangling chain), chainNextId set without
chainOp (dead pointer warning), and unresolved chainNextId
references.
2026-05-09 19:36:56 -07:00
std : : printf ( " --gen-pcn <wpcn-base> [name] \n " ) ;
std : : printf ( " Emit .wpcn starter: 3 single-check conditions (level>=60 / race=Human / class=Warrior) \n " ) ;
std : : printf ( " --gen-pcn-quest-gates <wpcn-base> [name] \n " ) ;
std : : printf ( " Emit .wpcn 4 quest-style gates (quest complete, reputation, achievement, zone presence) with cross-refs \n " ) ;
std : : printf ( " --gen-pcn-composite <wpcn-base> [name] \n " ) ;
std : : printf ( " Emit .wpcn 6 entries (3 leaves + 3 chained roots) exercising AND/OR/NOT chainOps for boolean trees \n " ) ;
std : : printf ( " --info-wpcn <wpcn-base> [--json] \n " ) ;
std : : printf ( " Print WPCN entries (id / kind / op / target IDs / int values / chainOp / chainNextId / name) \n " ) ;
std : : printf ( " --validate-wpcn <wpcn-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, kind 0..15, op 0..7, chainOp 0..3, chain self-loop, dangling chainNextId warning \n " ) ;
2026-05-09 19:38:06 -07:00
std : : printf ( " --export-wpcn-json <wpcn-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wpcn to a human-editable JSON sidecar (defaults to <base>.wpcn.json) \n " ) ;
std : : printf ( " --import-wpcn-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wpcn.json sidecar back into binary .wpcn (accepts conditionKind/comparisonOp/chainOp int OR name string) \n " ) ;
feat(pipeline): add WTSK (Wowee Trade Skill / Recipe) catalog
New open format — replaces SkillLineAbility.dbc plus the
recipe portions of SkillLine.dbc plus the AzerothCore
trade_skill SQL tables. Closes the crafting gap left by WSKL
(which carries skill lines but not the recipes that bind to
them).
14 professions (Blacksmithing, Tailoring, Engineering,
Alchemy, Enchanting, Leatherworking, Jewelcrafting,
Inscription, Mining, Skinning, Herbalism, Cooking, FirstAid,
Fishing). Each recipe has 4 skill-up bracket thresholds
(orange / yellow / green / gray) for skill-up probability,
a craft spell cross-ref (WSPL), produced item cross-ref
(WIT) with min/max quantity range, an optional tool item,
and up to 4 reagent slots (itemId + count).
Cross-references with prior formats — craftSpellId points at
WSPL.spellId, producedItemId / toolItemId / reagent[].itemId
all point at WIT.itemId, and skillId points at WSKL.skillId.
CLI: --gen-tsk (3-recipe entry-tier starter), --gen-tsk-
blacksmithing (5-recipe progression rough sharpening through
truesilver champion), --gen-tsk-alchemy (5-recipe progression
minor healing through flask of titans), --info-wtsk,
--validate-wtsk with --json variants. Validator catches
id=0/duplicates, profession out of range, missing craft spell
or produced item, monotonic-bracket check (must be orange <=
yellow <= green <= gray), reagent itemId-without-count
mismatch, and free-recipe warning (no reagents and no tool).
Format graph now exposes 49 distinct binary formats. CLI
flag count: 747 → 752.
2026-05-09 19:41:49 -07:00
std : : printf ( " --gen-tsk <wtsk-base> [name] \n " ) ;
std : : printf ( " Emit .wtsk starter: 3 entry-tier recipes (Coarse Sharpening Stone / Linen Bandage / Minor Healing Potion) \n " ) ;
std : : printf ( " --gen-tsk-blacksmithing <wtsk-base> [name] \n " ) ;
std : : printf ( " Emit .wtsk 5-recipe Blacksmithing progression (rough sharpening → truesilver champion plate) \n " ) ;
std : : printf ( " --gen-tsk-alchemy <wtsk-base> [name] \n " ) ;
std : : printf ( " Emit .wtsk 5-recipe Alchemy progression (minor healing → flask of titans) with reagent slots \n " ) ;
std : : printf ( " --info-wtsk <wtsk-base> [--json] \n " ) ;
std : : printf ( " Print WTSK entries (id / profession / 4 skill brackets / craft spell / produced item / qty / tool / reagent count / name) \n " ) ;
std : : printf ( " --validate-wtsk <wtsk-base> [--json] \n " ) ;
std : : printf ( " Static checks: id>0+unique, name not empty, profession 0..13, craft spell + produced item required, monotonic skill brackets \n " ) ;
2026-05-09 19:43:16 -07:00
std : : printf ( " --export-wtsk-json <wtsk-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtsk to a human-editable JSON sidecar with nested reagents (defaults to <base>.wtsk.json) \n " ) ;
std : : printf ( " --import-wtsk-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtsk.json sidecar back into binary .wtsk (accepts profession int OR name string, reagents array up to 4 slots) \n " ) ;
feat(pipeline): add WCEQ (Wowee Creature Equipment) — 50th open format
Replaces the AzerothCore-style creature_equip_template SQL
tables plus the visible-weapon / shield / ranged-slot data
that was traditionally embedded in creature templates. Closes
a long-standing gap in the creature subsystem: until now WCRT
defined a creature's stats, WSPN placed it in the world, and
WLOT defined what it drops — but nothing defined what items
it visibly equips.
Each entry binds a creatureId to up to three equipped items
(main hand / off hand / ranged) plus the visual kit that
fires when the main-hand weapon is brandished. equipFlags
bits encode hidden / dual-wield / shield-offhand /
thrown-ranged / 2H polearm to drive the renderer's
attachment-point selection.
Cross-references with prior formats — creatureId points at
WCRT.creatureId, mainHandItemId / offHandItemId / rangedItemId
all point at WIT.itemId, and mainHandVisualId points at
WSVK.visualKitId so brandished weapons can play their
signature glow / aura.
CLI: --gen-ceq (3 generic guard/hunter/rogue starters),
--gen-ceq-bosses (4 iconic loadouts incl. Frostmourne and
Illidan's warglaives, with WSVK visual cross-refs),
--gen-ceq-ranged (3 ranged-only rifle/bow/crossbow loadouts),
--info-wceq, --validate-wceq with --json variants. Validator
catches id=0/duplicates, missing creatureId, all-empty-slots
warning, kFlagDualWield without both hand items, kFlagShield
without offhand item, mutually-exclusive dual-wield + shield,
and 2H polearm with offhand item filled.
Format graph milestone: 50 distinct binary formats. CLI flag
count: 754 → 760.
2026-05-09 19:48:13 -07:00
std : : printf ( " --gen-ceq <wceq-base> [name] \n " ) ;
std : : printf ( " Emit .wceq starter: 3 generic creature loadouts (guard 1H+shield, hunter bow, rogue dual-dagger) \n " ) ;
std : : printf ( " --gen-ceq-bosses <wceq-base> [name] \n " ) ;
std : : printf ( " Emit .wceq 4 iconic boss loadouts (Onyxia 2H, Lich King Frostmourne, Sylvanas bow, Illidan dual warglaives) with WSVK refs \n " ) ;
std : : printf ( " --gen-ceq-ranged <wceq-base> [name] \n " ) ;
std : : printf ( " Emit .wceq 3 ranged-only loadouts (rifle / bow / crossbow) — ranged slot only, no melee \n " ) ;
std : : printf ( " --info-wceq <wceq-base> [--json] \n " ) ;
std : : printf ( " Print WCEQ entries (id / creatureId / mainhand+offhand+ranged item IDs / equipFlags / visualKitId / name) \n " ) ;
std : : printf ( " --validate-wceq <wceq-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+creatureId>0+unique, dual-wield/shield/2H polearm flag coherence, mutually-exclusive flag combos \n " ) ;
2026-05-09 19:50:20 -07:00
std : : printf ( " --export-wceq-json <wceq-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wceq to a human-editable JSON sidecar (defaults to <base>.wceq.json) \n " ) ;
std : : printf ( " --import-wceq-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wceq.json sidecar back into binary .wceq (slot fields default to canonical 16/17/18 if omitted) \n " ) ;
feat(pipeline): add WSET (Wowee Item Set / Tier Bonus) catalog
51st open format — replaces ItemSet.dbc + ItemSetSpell.dbc
plus the AzerothCore-style item_set_spell SQL data. Closes
the tier-bonus gap left by WIT (which describes individual
items but not the set bonuses they grant when worn together).
Each entry binds up to 8 piece item IDs to up to 4 bonus
thresholds — at N pieces worn, the matching bonus spell
activates as an aura. Standard 2/4/6/8-piece tier set pattern
is the canonical case; 5-piece PvP sets with 2/4 bonuses are
also supported.
Cross-references with prior formats — itemIds[] point at
WIT.itemId, bonusSpellIds[] point at WSPL.spellId, and
requiredSkillId points at WSKL.skillId. requiredClassMask
is a 32-bit field (uint32_t) so bit positions match WCHC's
classId enum directly — Druid (bit 11 = 0x800) and Mage
(bit 8 = 0x100) wouldn't fit in a uint8_t.
CLI: --gen-itset (2 raid sets — Battlegear of Wrath +
Stormrage Raiment, real WoW item/spell IDs), --gen-itset-tier
(4 tier-1 progression sets covering plate / cloth / leather /
holy plate), --gen-itset-pvp (3 PvP gladiator 5-piece sets
with honor-rank skill thresholds), --info-wset, --validate-wset
with --json variants. Validator catches id+name+pieceCount
required, pieceCount/bonusCount within array bounds, piece-
slot drift (0 IDs within count or non-0 IDs past count),
bonus thresholds strictly ascending, no bonus threshold
exceeding pieceCount (would never trigger), and spellId=0
in any populated bonus slot.
Format graph: 50 → 51 binary formats. CLI flag count: 762
→ 767.
2026-05-09 19:54:36 -07:00
std : : printf ( " --gen-itset <wset-base> [name] \n " ) ;
std : : printf ( " Emit .wset starter: 2 raid sets (Battlegear of Wrath / Stormrage Raiment) — 8-piece tier-2 layouts \n " ) ;
std : : printf ( " --gen-itset-tier <wset-base> [name] \n " ) ;
std : : printf ( " Emit .wset 4 progression tier-1 sets (warrior plate / mage cloth / rogue leather / paladin holy plate) with 2/4/6 bonuses \n " ) ;
std : : printf ( " --gen-itset-pvp <wset-base> [name] \n " ) ;
std : : printf ( " Emit .wset 3 PvP gladiator sets (5-piece) with 2/4 bonuses and honor-rank skill thresholds \n " ) ;
std : : printf ( " --info-wset <wset-base> [--json] \n " ) ;
std : : printf ( " Print WSET entries (id / pieces / bonuses / classMask / skill+rank gates / first item ID / name) \n " ) ;
std : : printf ( " --validate-wset <wset-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+pieceCount required, piece/bonus arrays match counts, monotonic bonus thresholds within pieceCount \n " ) ;
2026-05-09 19:55:50 -07:00
std : : printf ( " --export-wset-json <wset-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wset to a human-editable JSON sidecar with nested itemIds[] + bonuses[] arrays \n " ) ;
std : : printf ( " --import-wset-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wset.json sidecar back into binary .wset (pieceCount/bonusCount derived from array sizes; missing slots cleared) \n " ) ;
feat(pipeline): add WGTP (Wowee Game Tips) catalog
52nd open format — replaces GameTips.dbc plus loading-screen
tutorial hint tables. Defines the rotating tips shown during
world loads, the contextual tutorial hints that fire on first
gameplay events (first quest accept, first death, first
dungeon entry), and the persistent tooltip-help strings that
explain UI elements.
4 display kinds (LoadingScreen / Tutorial / TooltipHelp /
Hint), 7 audience-filter bits (Alliance / Horde / NewPlayer /
Hardcore / PvE / PvP / Roleplay) for pool selection, level
range gating (minLevel + maxLevel), displayWeight for
relative frequency within the pool, optional WPCN condition
cross-ref for further gating, and class-mask restriction
matching WCHC bit positions.
Cross-references with prior formats — conditionId points at
WPCN.conditionId for advanced gating; requiredClassMask uses
the same WCHC.classId bit layout as WGLY/WSET.
CLI: --gen-tips (3 generic loading-screen tips), --gen-tips-
new-player (5 onboarding Tutorial-kind tips for level 1-15,
weighted higher for new players), --gen-tips-advanced (4
endgame tips for level 70+ covering raid mechanics / arena /
daily professions / dungeon finder), --info-wgtp,
--validate-wgtp with --json variants. Validator catches
id/name/text required, kind 0..3, audienceFilter=0 (tip
never shown), invalid level range, displayWeight=0 (in pool
but never picked) warning, and brevity check (>280 chars)
on Tutorial / Hint kinds that need to fit on screen.
Format graph: 51 → 52 binary formats. CLI flag count: 770
→ 775.
2026-05-09 20:00:56 -07:00
std : : printf ( " --gen-tips <wgtp-base> [name] \n " ) ;
std : : printf ( " Emit .wgtp starter: 3 generic loading-screen tips (combat / movement / quest hints) for kAudienceAll \n " ) ;
std : : printf ( " --gen-tips-new-player <wgtp-base> [name] \n " ) ;
std : : printf ( " Emit .wgtp 5 onboarding tutorial tips (hearthstone / talents / mount / quest log / professions) for level 1-15 \n " ) ;
std : : printf ( " --gen-tips-advanced <wgtp-base> [name] \n " ) ;
std : : printf ( " Emit .wgtp 4 endgame tips (raid mechanics / arena / daily professions / dungeon finder) for level 70+ \n " ) ;
std : : printf ( " --info-wgtp <wgtp-base> [--json] \n " ) ;
std : : printf ( " Print WGTP entries (id / kind / audience mask / level range / weight / condition / classMask / name) \n " ) ;
std : : printf ( " --validate-wgtp <wgtp-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+text required, kind 0..3, audienceFilter>0, valid level range, brevity check on tutorial/hint kinds \n " ) ;
2026-05-09 20:02:02 -07:00
std : : printf ( " --export-wgtp-json <wgtp-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgtp to a human-editable JSON sidecar (defaults to <base>.wgtp.json) \n " ) ;
std : : printf ( " --import-wgtp-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgtp.json sidecar back into binary .wgtp (accepts displayKind int OR name string) \n " ) ;
feat(pipeline): add WCMP (Wowee Companion Pet) catalog
53rd open format — replaces the companion-pet portions of
CreatureFamily.dbc plus the AzerothCore-style critter / vanity-
pet SQL data. Distinct from WPET (which covers hunter combat
pets and warlock minions); WCMP covers non-combat "vanity" pets
that follow the player around for cosmetic reasons —
Mechanical Squirrel, Mini Diablo, Panda Cub, dragon hatchlings.
8 companion kinds (Critter, Mechanical, DragonHatchling,
Demonic, Spectral, Elemental, Plush, UndeadCritter), 4
rarity tiers (Common / Uncommon / Rare / Epic), and 3
faction restrictions (AnyFaction / AllianceOnly / HordeOnly).
Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), learnSpellId at
WSPL.spellId (the spell that summons the pet), itemId at
WIT.itemId (the item that teaches the spell), and
idleSoundId at WSND.soundId (idle ambient noise).
CLI: --gen-cmp (3 common vendor pets), --gen-cmp-rare (4
promo / collector pets at Epic rarity — Mini Diablo,
Panda Cub, Zergling, Murky), --gen-cmp-faction (3 faction-
restricted Alliance Lion Cub / Horde Mottled Boar /
neutral Argent Squire), --info-wcmp, --validate-wcmp with
--json variants. Validator catches id+name+creatureId+
learnSpellId required, kind 0..7 / rarity 0..3 / faction
0..2 range, and Epic-rarity-no-itemId warning (most promo
pets need a redemption-code item).
Format graph: 52 → 53 binary formats. CLI flag count: 777
→ 782.
2026-05-09 20:05:06 -07:00
std : : printf ( " --gen-cmp <wcmp-base> [name] \n " ) ;
std : : printf ( " Emit .wcmp starter: 3 common vendor companions (Mechanical Squirrel / Cat / Prairie Dog) \n " ) ;
std : : printf ( " --gen-cmp-rare <wcmp-base> [name] \n " ) ;
std : : printf ( " Emit .wcmp 4 promo / collector pets (Mini Diablo / Panda Cub / Zergling / Murky) at Epic rarity \n " ) ;
std : : printf ( " --gen-cmp-faction <wcmp-base> [name] \n " ) ;
std : : printf ( " Emit .wcmp 3 faction-restricted pets (Alliance Lion Cub / Horde Mottled Boar / Argent Squire any-faction) \n " ) ;
std : : printf ( " --info-wcmp <wcmp-base> [--json] \n " ) ;
std : : printf ( " Print WCMP entries (id / creature / kind / rarity / faction / learn spell+item / idle sound / name) \n " ) ;
std : : printf ( " --validate-wcmp <wcmp-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+creatureId+learnSpellId required, kind 0..7, rarity 0..3, faction 0..2, Epic-no-itemId warning \n " ) ;
2026-05-09 20:06:33 -07:00
std : : printf ( " --export-wcmp-json <wcmp-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wcmp to a human-editable JSON sidecar (defaults to <base>.wcmp.json) \n " ) ;
std : : printf ( " --import-wcmp-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wcmp.json sidecar back into binary .wcmp (accepts companionKind/rarity/factionRestriction int OR name string) \n " ) ;
feat(pipeline): add WSMC (Wowee Spell Mechanic) catalog
54th open format — replaces SpellMechanic.dbc plus the
AzerothCore-style diminishing-returns (DR) tables. Defines
crowd-control mechanic categories that spells reference:
Stun, Silence, Polymorph, Sleep, Fear, Root, Snare, Slow,
Knockback, etc. Each mechanic carries gameplay metadata
(breaks-on-damage, can-be-dispelled, default duration, max
stacks) plus DR category and dispel type.
8 DR categories (DRNone / DRStun / DRDisorient / DRSilence
/ DRRoot / DRPolymorph / DRControlled / DRMisc) — the
runtime uses these to gate repeated CC on the same target.
7 dispel types (DispelNone / Magic / Curse / Disease /
Poison / Enrage / Stealth) bind which dispel spells can
remove the mechanic. conflictsMask is a bitmask of OTHER
mechanic IDs — only one mechanic from a conflict-group can
apply to a target simultaneously.
Cross-references with prior formats — mechanicId is
referenced by WSPL.spellId entries that apply this CC; this
catalog is referenced from spell tags rather than referencing
out.
CLI: --gen-smc (3 baseline Stun/Silence/Snare), --gen-smc-
hard (5 hard-CC: Stun/Polymorph/Sleep/Fear/Knockback with
conflictsMask wiring), --gen-smc-roots (4 movement-impair:
Root/Snare/Slow stacking 5x/GroundPin breaks-on-damage),
--info-wsmc, --validate-wsmc with --json variants. Validator
catches id+name required, DR category 0..7, dispel type
0..6, maxStacks=0 (mechanic could never apply),
canBeDispelled+DispelNone inconsistency, and self-conflict
bit set in conflictsMask (mechanic blocking itself).
Format graph: 53 → 54 binary formats. CLI flag count: 784
→ 789.
2026-05-09 20:09:44 -07:00
std : : printf ( " --gen-smc <wsmc-base> [name] \n " ) ;
std : : printf ( " Emit .wsmc starter: 3 baseline mechanics (Stun / Silence / Snare) covering the most common DR categories \n " ) ;
std : : printf ( " --gen-smc-hard <wsmc-base> [name] \n " ) ;
std : : printf ( " Emit .wsmc 5 hard-CC mechanics (Stun / Polymorph / Sleep / Fear / Knockback) with conflictsMask DR wiring \n " ) ;
std : : printf ( " --gen-smc-roots <wsmc-base> [name] \n " ) ;
std : : printf ( " Emit .wsmc 4 movement-impair mechanics (Root / Snare / Slow stacking / GroundPin breaks-on-damage) \n " ) ;
std : : printf ( " --info-wsmc <wsmc-base> [--json] \n " ) ;
std : : printf ( " Print WSMC entries (id / DR category / dispel type / breaks / dispellable / duration / max stacks / conflicts mask / name) \n " ) ;
std : : printf ( " --validate-wsmc <wsmc-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, DR 0..7 / dispel 0..6, maxStacks>0, dispellable+none-dispel inconsistency, self-conflict bit \n " ) ;
2026-05-09 20:10:59 -07:00
std : : printf ( " --export-wsmc-json <wsmc-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsmc to a human-editable JSON sidecar (defaults to <base>.wsmc.json) \n " ) ;
std : : printf ( " --import-wsmc-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsmc.json sidecar back into binary .wsmc (accepts drCategory/dispelType int OR name string) \n " ) ;
feat(pipeline): add WKBD (Wowee Keybinding) catalog
55th open format — replaces KeyBinding.dbc plus the
AzerothCore-style default-keybind SQL data. Defines the key
bindings shipped with the game: movement (W/A/S/D),
targeting (Tab), action bars (1-9, 0, -, =), UI panels
(C/I/B/P/N/L), chat (Enter), camera (Insert/Delete).
Each binding has an internal action name (SCREAMING_SNAKE
convention — "MOVE_FORWARD"), a primary key, an optional
alternate key, a category for the keybindings UI grouping,
and a flag indicating whether the user can override it.
Hardcoded engine bindings (alt-F4, ESC) set
isUserOverridable=0 so the rebind dialog can't accidentally
break them.
9 categories (Movement / Combat / Targeting / Camera /
UIPanels / Chat / Macro / Bar / Other) for the rebind
dialog grouping.
CLI: --gen-kbd (3 essential WASD/Tab/C bindings), --gen-kbd-
movement (8 movement: WASD + arrow alternates + jump +
autorun), --gen-kbd-ui (10 UI panel bindings covering all
the standard interface windows), --info-wkbd, --validate-wkbd
with --json variants. Validator catches id+actionName+
defaultKey required, category 0..8, alternateKey ==
defaultKey (no point in alt), action-name lowercase warning
(should be SCREAMING_SNAKE), duplicate primary keys (would
silently shadow earlier binding), and duplicate action names.
Format graph: 54 → 55 binary formats. CLI flag count: 791
→ 796.
2026-05-09 20:13:37 -07:00
std : : printf ( " --gen-kbd <wkbd-base> [name] \n " ) ;
std : : printf ( " Emit .wkbd starter: 3 essential bindings (MOVE_FORWARD / TARGET_NEAREST_ENEMY / TOGGLE_CHARACTER) \n " ) ;
std : : printf ( " --gen-kbd-movement <wkbd-base> [name] \n " ) ;
std : : printf ( " Emit .wkbd 8 movement bindings (WASD / arrow keys / jump / autorun) with primary+alternate keys \n " ) ;
std : : printf ( " --gen-kbd-ui <wkbd-base> [name] \n " ) ;
std : : printf ( " Emit .wkbd 10 UI panel bindings (Character C / Inventory I / Bags B / Spellbook P / Talents N / etc) \n " ) ;
std : : printf ( " --info-wkbd <wkbd-base> [--json] \n " ) ;
std : : printf ( " Print WKBD entries (id / category / user-overridable / sort / default key + alt / actionName) \n " ) ;
std : : printf ( " --validate-wkbd <wkbd-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+actionName+defaultKey required, category 0..8, alt!=default, unique action names + primary keys \n " ) ;
2026-05-09 20:15:02 -07:00
std : : printf ( " --export-wkbd-json <wkbd-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wkbd to a human-editable JSON sidecar (defaults to <base>.wkbd.json) \n " ) ;
std : : printf ( " --import-wkbd-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wkbd.json sidecar back into binary .wkbd (accepts category int OR name string; isUserOverridable defaults to 1) \n " ) ;
feat(pipeline): add WSCH (Wowee Spell School) catalog
56th open format — replaces SpellSchools.dbc plus the
Resistances.dbc resistance-cap tables. Defines damage
schools spells use: Physical, Holy, Fire, Nature, Frost,
Shadow, Arcane, plus combined / hybrid schools that count
as multiple types simultaneously (Spellfire, Spellshadow,
Spellfrost — relevant for resistance-bypass mechanics).
7 canonical schools with single-bit IDs (1, 2, 4, 8, 16,
32, 64) so combinedSchoolMask values line up directly with
the spell engine's school-bit enum. Hybrid schools use
high-bit IDs (0x80000001+) and their combinedSchoolMask
references the canonical bits they qualify as. Each school
carries visual identity (color tint, icon), gameplay rules
(canBeImmune / canBeAbsorbed / canBeReflected / canCrit),
resistance cap at max level, and cast / impact sound IDs.
Cross-references with prior formats — castSoundId and
impactSoundId point at WSND.soundId; combinedSchoolMask
is a bitmask of OTHER WSCH.schoolId values within the same
catalog.
CLI: --gen-sch (3 base — Physical / Fire / Holy showing
non-resistable Holy + non-reflectable Physical), --gen-sch-
magical (6 canonical magical schools with proper colors
+ 365 max-level resistance caps), --gen-sch-combined (3
hybrids — Spellfire / Spellshadow / Spellfrost with
multi-bit combinedSchoolMask), --info-wsch, --validate-wsch
with --json variants. Validator catches id+name required,
reflected-without-absorbed warning (reflected damage
should be absorbable), self-referential combinedSchoolMask
(school qualifying as itself), and combined-mask references
to bits not defined in the same catalog (resolved at runtime
across catalogs).
Format graph: 55 → 56 binary formats. CLI flag count: 798
→ 804.
2026-05-09 20:19:34 -07:00
std : : printf ( " --gen-sch <wsch-base> [name] \n " ) ;
std : : printf ( " Emit .wsch starter: 3 base schools (Physical / Fire / Holy) with proper colors+resistance caps \n " ) ;
std : : printf ( " --gen-sch-magical <wsch-base> [name] \n " ) ;
std : : printf ( " Emit .wsch 6 magical schools (Holy / Fire / Nature / Frost / Shadow / Arcane) with canonical schoolId bits \n " ) ;
std : : printf ( " --gen-sch-combined <wsch-base> [name] \n " ) ;
std : : printf ( " Emit .wsch 3 hybrid schools (Spellfire / Spellshadow / Spellfrost) with combinedSchoolMask wiring \n " ) ;
std : : printf ( " --info-wsch <wsch-base> [--json] \n " ) ;
std : : printf ( " Print WSCH entries (schoolId / immune+absorb+reflect+crit flags / resistance cap / combined-mask / name) \n " ) ;
std : : printf ( " --validate-wsch <wsch-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, reflected-without-absorbed warning, combined-mask references defined schools, no self-reference \n " ) ;
2026-05-09 20:20:55 -07:00
std : : printf ( " --export-wsch-json <wsch-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsch to a human-editable JSON sidecar (defaults to <base>.wsch.json) \n " ) ;
std : : printf ( " --import-wsch-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsch.json sidecar back into binary .wsch (canBeImmune/Absorbed/Crit default to 1, canBeReflected to 0) \n " ) ;
feat(pipeline): add WLFG (Wowee Looking-for-Group) catalog
57th open format — replaces LFGDungeons.dbc plus the
AzerothCore-style dungeon-finder reward tables. Defines the
dungeons / raids that the Dungeon Finder / Raid Browser
presents to players, with their level brackets, group-size
requirements, role requirements (tank / heal / DPS), and
queue-completion rewards.
4 difficulty levels (Normal / Heroic / Mythic / Hardmode —
the latter for Ulduar-style toggleable boss difficulty),
4 expansion gates (Classic / TBC / WotLK / TurtleWoW), and
3 role-requirement bits (Tank / Heal / DPS — typically all
three for queue-formed groups).
Cross-references with prior formats — mapId points at
WMS.mapId (the instance map), queueRewardItemId points at
WIT.itemId (the random reward bag), firstClearAchievement
points at WACH.achievementId.
CLI: --gen-lfg (3 classic 5-mans Ragefire/Wailing/Deadmines
with real WoW mapIds + level brackets), --gen-lfg-heroic
(5 WotLK 80-level heroic 5-mans with emblem rewards +
real first-clear achievement IDs from Halls of Lightning
through Old Kingdom), --gen-lfg-raid (3 raid entries —
Naxx-25, Ulduar-25 Hardmode, ToC-25 Mythic), --info-wlfg,
--validate-wlfg with --json variants. Validator catches
id+name+mapId required, difficulty 0..3, expansion 0..3,
minLevel<=maxLevel, recommended-level outside range
warning, unusual groupSize warning (5/10/25/40 are
canonical), and zero role mask (queue can't form a
balanced group).
Format graph: 56 → 57 binary formats. CLI flag count: 804
→ 811.
2026-05-09 20:24:21 -07:00
std : : printf ( " --gen-lfg <wlfg-base> [name] \n " ) ;
std : : printf ( " Emit .wlfg starter: 3 classic 5-man dungeons (Ragefire Chasm / Wailing Caverns / Deadmines) with level brackets \n " ) ;
std : : printf ( " --gen-lfg-heroic <wlfg-base> [name] \n " ) ;
std : : printf ( " Emit .wlfg 5 WotLK 80-level heroic 5-mans with emblem rewards + first-clear achievement IDs \n " ) ;
std : : printf ( " --gen-lfg-raid <wlfg-base> [name] \n " ) ;
std : : printf ( " Emit .wlfg 3 raid entries (Naxxramas-25 / Ulduar-25 Hardmode / ToC-25 Mythic) with larger groupSize \n " ) ;
std : : printf ( " --info-wlfg <wlfg-base> [--json] \n " ) ;
std : : printf ( " Print WLFG entries (id / map / level range / minIlvl / difficulty / groupSize / role mask / expansion / rewards / name) \n " ) ;
std : : printf ( " --validate-wlfg <wlfg-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+mapId required, difficulty 0..3 / expansion 0..3, minLevel<=maxLevel, recommended within range, role mask>0 \n " ) ;
2026-05-09 20:25:30 -07:00
std : : printf ( " --export-wlfg-json <wlfg-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wlfg to a human-editable JSON sidecar (defaults to <base>.wlfg.json) \n " ) ;
std : : printf ( " --import-wlfg-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wlfg.json sidecar back into binary .wlfg (accepts difficulty/expansion int OR name string; groupSize defaults to 5, role mask to kRoleAll) \n " ) ;
feat(pipeline): add WMAC (Wowee Macro / Slash Command) catalog
58th open format — novel format with no direct DBC equivalent.
WoW historically stored player macros client-side in the user
profile and system slash commands as hardcoded engine handlers;
WMAC unifies both into a single structured catalog so default
macros, system slash commands, and shipped player presets can
be authored, validated, and shipped as content alongside the
rest of the open-format graph.
5 macro kinds (SystemSlash for engine /sit /dance handlers,
DefaultMacro for shipped presets, PlayerTemplate for user
templates, GuildMacro for guild-shared, SharedMacro for
account-wide). Multi-line macro bodies are stored verbatim
with literal '\n' separators — the client parses /cast /
/target / /run lines at runtime.
Cross-references with prior formats — requiredClassMask uses
WCHC.classId bit positions (Warrior=0x02, etc, same as WGLY/
WSET/WGTP).
CLI: --gen-mac (3 system slash — /sit, /dance, /target with
[@mouseover] modifier), --gen-mac-combat (4 warrior combat
templates — heroic strike spam, charge/intercept stance dance,
intercept stance switch, victory rush+bloodthirst fallback —
each with default key bindings), --gen-mac-utility (3 universal
utility — /follow target, mass /inv with %targetN tokens,
/releasecorpse via RepopMe()), --info-wmac, --validate-wmac
with --json variants. Validator catches id+name+body required,
kind 0..4, body within maxLength cap, body starting with '/'
or '#' (slash command or showtooltip annotation), and
SystemSlash + classMask warning (slash commands are class-
agnostic — restricting them to a class makes no sense).
Format graph: 57 → 58 binary formats. CLI flag count: 814
→ 819.
2026-05-09 20:30:17 -07:00
std : : printf ( " --gen-mac <wmac-base> [name] \n " ) ;
std : : printf ( " Emit .wmac starter: 3 system slash commands (/sit, /dance, /target with [@mouseover]) \n " ) ;
std : : printf ( " --gen-mac-combat <wmac-base> [name] \n " ) ;
std : : printf ( " Emit .wmac 4 warrior combat macros (Heroic Strike spam, Charge/Intercept stance dance, Victory Rush) with bind keys + classMask \n " ) ;
std : : printf ( " --gen-mac-utility <wmac-base> [name] \n " ) ;
std : : printf ( " Emit .wmac 3 utility macros (/follow target, mass /inv with %%targetN, /releasecorpse via RepopMe) \n " ) ;
std : : printf ( " --info-wmac <wmac-base> [--json] \n " ) ;
std : : printf ( " Print WMAC entries (id / kind / classMask / bindKey / maxLen / body length / name) \n " ) ;
std : : printf ( " --validate-wmac <wmac-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+body required, kind 0..4, body within maxLength, body starts with '/' or '#', SystemSlash + classMask warning \n " ) ;
2026-05-09 20:31:37 -07:00
std : : printf ( " --export-wmac-json <wmac-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wmac to a human-editable JSON sidecar (defaults to <base>.wmac.json; multi-line bodies escape \\ n) \n " ) ;
std : : printf ( " --import-wmac-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wmac.json sidecar back into binary .wmac (accepts macroKind int OR name string; maxLength defaults to 255) \n " ) ;
feat(pipeline): add WCHF (Wowee Character Customization Feature) catalog
59th open format — replaces CharHairGeosets.dbc +
CharFacialHairStyles.dbc plus the variation portions of
CharSections.dbc. Defines per-(race, sex) customization
options the character creation screen exposes: skin colors,
face variations, hair styles, hair colors, facial hair
(beards / mustaches), and race-specific markings (Tauren
horns, Draenei tendrils, Blood Elf ears).
9 feature kinds (SkinColor / FaceVariation / HairStyle /
HairColor / FacialHair / FacialColor / EarStyle / Horns /
Markings) cover the full canonical customization surface.
Each entry is one selectable carousel choice for one
(race, sex, kind) tuple — variationIndex disambiguates.
expansionGate enum gates Blood Elf / Draenei (TBC) and DK
features (WotLK) behind the right expansion unlock.
Cross-references with prior formats — raceId points at
WCHC.race.raceId. requiresExpansion bit positions match
the WLFG expansion enum (Classic=0, TBC=1, WotLK=2,
Turtle=3) for consistency.
CLI: --gen-chf (5 Human Male starter — skin / face / 2
hair styles / facial hair), --gen-chf-bloodelf (8 Blood
Elf Female hair styles, requiresExpansion=TBC — the
iconic TBC race feature), --gen-chf-tauren (6 Tauren Male
features using race-specific Horns kind + 3 facial hair
variations), --info-wchf, --validate-wchf with --json
variants. Validator catches id+name+raceId+texturePath
required, kind 0..8 / sex 0..1 / expansion 0..3, and the
critical (race, sex, kind, variation) tuple-uniqueness
check — duplicates would shadow each other in the create-
character carousel.
Format graph: 58 → 59 binary formats. CLI flag count: 819
→ 826.
2026-05-09 20:35:21 -07:00
std : : printf ( " --gen-chf <wchf-base> [name] \n " ) ;
std : : printf ( " Emit .wchf starter: 5 Human Male features (1 skin / 1 face / 2 hair styles / 1 facial hair) \n " ) ;
std : : printf ( " --gen-chf-bloodelf <wchf-base> [name] \n " ) ;
std : : printf ( " Emit .wchf 8 Blood Elf Female hair styles (TBC iconic feature, requiresExpansion=TBC) \n " ) ;
std : : printf ( " --gen-chf-tauren <wchf-base> [name] \n " ) ;
std : : printf ( " Emit .wchf 6 Tauren Male features (3 horn variants + 3 facial hair) using race-specific kinds \n " ) ;
std : : printf ( " --info-wchf <wchf-base> [--json] \n " ) ;
std : : printf ( " Print WCHF entries (id / race / sex / kind / variation / geoset bits / expansion / name) \n " ) ;
std : : printf ( " --validate-wchf <wchf-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+raceId+texturePath required, kind 0..8 / sex 0..1 / expansion 0..3, unique (race,sex,kind,variation) tuples \n " ) ;
2026-05-09 20:37:01 -07:00
std : : printf ( " --export-wchf-json <wchf-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wchf to a human-editable JSON sidecar (defaults to <base>.wchf.json) \n " ) ;
std : : printf ( " --import-wchf-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wchf.json sidecar back into binary .wchf (accepts featureKind/sexId/requiresExpansion int OR name string) \n " ) ;
feat(pipeline): add WPVP (Wowee PvP Honor / Rank) — 60th open format
60th open format milestone — replaces the AzerothCore-style
PvP rank tables plus the vanilla honor-rank reward chains.
Defines PvP progression rungs: vanilla honor ranks (Private
through Grand Marshal / High Warlord), arena rating brackets
(Combatant / Challenger / Rival / Duelist / Gladiator), and
battleground rated tiers.
5 rank kinds (VanillaHonor / ArenaRating / BattlegroundRated /
WorldPvP / ConquestPoint) cover the canonical PvP progression
surface. Each entry carries an alliance-specific name and a
horde-specific name (Grand Marshal = High Warlord; arena tiers
share the same name on both factions), an honor or rating
threshold, and optional gear cross-refs (chest, gloves,
shoulders) into WIT.
Cross-references with prior formats — titleId points at
WTTL.titleId (the unlock title), chest/gloves/shoulders point
at WIT.itemId for the matching PvP set, bracketBgId points at
WBGD.bgId for battleground-bracket gating.
CLI: --gen-pvp (3 vanilla entry tiers Rank2-4 with alliance
vs horde alternate names), --gen-pvp-alliance (9 vanilla
ranks 6-14 with WTTL+WIT cross-refs and ramping honor
thresholds 50k → 260k), --gen-pvp-arena (5 arena rating
brackets 1500/1750/2000/2200/2400 with 10/20/40/80/160 emblem
rewards), --info-wpvp, --validate-wpvp with --json variants.
Validator catches id+name required, kind 0..4, level range
valid, faction-name pairing (one set without the other is a
typo), threshold monotonicity within a rankKind, arena rating
below 1500 floor, and VanillaHonor with minHonor=0 baseline
warning.
Format graph: 59 → 60 binary formats (milestone). CLI flag
count: 826 → 833.
2026-05-09 20:41:09 -07:00
std : : printf ( " --gen-pvp <wpvp-base> [name] \n " ) ;
std : : printf ( " Emit .wpvp starter: 3 vanilla honor entry tiers (Rank2-4 — Private/Scout, Corporal/Grunt, Sergeant) \n " ) ;
std : : printf ( " --gen-pvp-alliance <wpvp-base> [name] \n " ) ;
std : : printf ( " Emit .wpvp 9 vanilla ranks 6-14 (Knight through Grand Marshal) with WTTL+WIT cross-refs for chest/gloves/shoulders \n " ) ;
std : : printf ( " --gen-pvp-arena <wpvp-base> [name] \n " ) ;
std : : printf ( " Emit .wpvp 5 arena rating brackets (Combatant 1500 / Challenger 1750 / Rival 2000 / Duelist 2200 / Gladiator 2400) \n " ) ;
std : : printf ( " --info-wpvp <wpvp-base> [--json] \n " ) ;
std : : printf ( " Print WPVP entries (id / kind / threshold / emblem reward / title+chest cross-refs / alliance / horde names) \n " ) ;
std : : printf ( " --validate-wpvp <wpvp-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, kind 0..4, level range valid, faction alt names paired, threshold monotonic within kind, arena>=1500 \n " ) ;
2026-05-09 20:42:21 -07:00
std : : printf ( " --export-wpvp-json <wpvp-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wpvp to a human-editable JSON sidecar (defaults to <base>.wpvp.json) \n " ) ;
std : : printf ( " --import-wpvp-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wpvp.json sidecar back into binary .wpvp (accepts rankKind int OR name string; bracket level defaults to 1..80) \n " ) ;
feat(pipeline): add WBNK (Wowee Bag / Bank Slot) catalog
61st open format — replaces ItemBag.dbc plus the bank-storage
and special-purpose container tables. Defines every slot the
player has access to: equipped bags, bank bags, keyring, soul
shard bag, quiver, reagent bag, hunter pet stable.
8 bag kinds (Inventory / Bank / Keyring / Quiver / SoulShard /
Stable / Reagent / Wallet) cover the canonical container
surface. Each entry has a fixed capacity (or 0 = variable,
size set by equipped bag), a display order in the inventory
UI, an unlock state with optional gold cost (bank bags ramp
through 10s / 1g / 10g / 25g / 50g / 100g matching canonical
WoW prices), and an accepts-bag-subclass mask gating which
container kinds may be equipped (generic / herb / enchanting
/ engineer / gem / mining / leather / inscription / quiver /
ammo pouch).
Cross-references with prior formats — fixedBagItemId points
at WIT.itemId for the bag item that always occupies a fixed
slot (0 = player-equipable variable slot).
CLI: --gen-bnk (5 inventory slots — 16-slot fixed main
backpack + 4 player-equippable bag slots accepting generic
containers + herb + enchanting bags), --gen-bnk-bank (8 bank
bag slots with the canonical WoW unlock cost ramp),
--gen-bnk-special (4 special-purpose: 32-slot Keyring fixed,
warlock SoulShardBag, hunter ArrowQuiver, hunter
HuntersStable for 5 pets), --info-wbnk, --validate-wbnk with
--json variants. Validator catches id+name required, kind
0..7, locked-with-zero-cost (slot can never be unlocked),
fixed-slot-with-non-zero-mask (equippable bag would be
ignored), variable slot with empty mask (no bag can fit),
and ambiguous (bagKind, displayOrder) tuples (UI sort would
flicker).
Format graph: 60 → 61 binary formats. CLI flag count: 833
→ 840.
2026-05-09 20:46:06 -07:00
std : : printf ( " --gen-bnk <wbnk-base> [name] \n " ) ;
std : : printf ( " Emit .wbnk starter: 5 inventory slots (16-slot main backpack + 4 player-equippable bag slots) \n " ) ;
std : : printf ( " --gen-bnk-bank <wbnk-base> [name] \n " ) ;
std : : printf ( " Emit .wbnk 8 bank bag slots — first 2 free, then 6 with ascending gold costs (10s/1g/10g/25g/50g/100g) \n " ) ;
std : : printf ( " --gen-bnk-special <wbnk-base> [name] \n " ) ;
std : : printf ( " Emit .wbnk 4 special slots (Keyring fixed, Soul Shard warlock-only, Quiver hunter-only, Hunters Stable for pets) \n " ) ;
std : : printf ( " --info-wbnk <wbnk-base> [--json] \n " ) ;
std : : printf ( " Print WBNK entries (id / kind / size / display order / unlock status + cost / accept-mask / fixed bag item / name) \n " ) ;
std : : printf ( " --validate-wbnk <wbnk-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, kind 0..7, locked-with-zero-cost warning, fixed-slot-with-mask conflict, ambiguous (kind,order) \n " ) ;
2026-05-09 20:47:38 -07:00
std : : printf ( " --export-wbnk-json <wbnk-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wbnk to a human-editable JSON sidecar (defaults to <base>.wbnk.json) \n " ) ;
std : : printf ( " --import-wbnk-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wbnk.json sidecar back into binary .wbnk (accepts bagKind int OR name string; isUnlocked defaults to 1, mask to AnyContainer) \n " ) ;
feat(pipeline): add WRUN (Wowee DK Rune Cost) catalog
62nd open format — replaces RuneCost.dbc plus the DK-specific
portions of ChrPowerType. Defines per-spell rune costs (Blood
/ Frost / Unholy) and runic-power generation / consumption
for the Death Knight class.
4 spell tree branches (BloodTree / FrostTree / UnholyTree /
Generic) classify which spec uses each rune cost. Each entry
binds a spell to its rune cost (how many of each rune kind
the spell consumes), an optional anyDeathConvertCost (extra
Death-rune-acceptable cost for procced abilities), and a
runicPowerCost (negative = generator, positive = spender).
Cross-references with prior formats — spellId points at
WSPL.spellId (the spell that uses this rune cost).
CLI: --gen-rune (3 baseline DK abilities — Death Strike
1F+1U + 20RP gen, Frost Strike pure 40 RP spender, Heart
Strike 1B + 10RP gen), --gen-rune-blood (4 blood-tree DK
abilities — Heart Strike, Death and Decay AoE, Vampiric
Blood tank cooldown, Rune Tap self-heal), --gen-rune-frost
(4 frost-tree — Frost Strike, Howling Blast AoE, Obliterate
finisher, Icy Touch ranged opener applying Frost Fever),
--info-wrun, --validate-wrun with --json variants. Validator
catches id+name+spellId required, branch 0..3, no rune cost
> 2 (DK only has 2 of each rune type so a higher cost can
never be paid), runicPowerCost > 100 (DK RP cap), no-cost
warning (spell consumes nothing — verify it's a
passive/stance/form), and high-RP-generator warning (> 25
RP per cast is unusual).
Format graph: 61 → 62 binary formats. CLI flag count: 840
→ 847.
2026-05-09 20:52:19 -07:00
std : : printf ( " --gen-rune <wrun-base> [name] \n " ) ;
std : : printf ( " Emit .wrun starter: 3 baseline DK rune costs (Death Strike 1F+1U, Frost Strike 40RP spender, Heart Strike 1B) \n " ) ;
std : : printf ( " --gen-rune-blood <wrun-base> [name] \n " ) ;
std : : printf ( " Emit .wrun 4 blood-tree DK rune costs (Heart Strike, Death and Decay AoE, Vampiric Blood, Rune Tap self-heal) \n " ) ;
std : : printf ( " --gen-rune-frost <wrun-base> [name] \n " ) ;
std : : printf ( " Emit .wrun 4 frost-tree DK rune costs (Frost Strike, Howling Blast AoE, Obliterate finisher, Icy Touch opener) \n " ) ;
std : : printf ( " --info-wrun <wrun-base> [--json] \n " ) ;
std : : printf ( " Print WRUN entries (id / spell / B/F/U costs / death-convertible / RP cost+arrow / branch / name) \n " ) ;
std : : printf ( " --validate-wrun <wrun-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+spellId required, branch 0..3, no rune cost > 2 (DK has only 2 of each), runicPower > 100 cap, no-cost warning \n " ) ;
2026-05-09 20:55:07 -07:00
std : : printf ( " --export-wrun-json <wrun-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wrun to a human-editable JSON sidecar (defaults to <base>.wrun.json) \n " ) ;
std : : printf ( " --import-wrun-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wrun.json sidecar back into binary .wrun (accepts spellTreeBranch int OR name string) \n " ) ;
feat(pipeline): add WLDS (Wowee Loading Screen) catalog
63rd open format — replaces LoadingScreens.dbc plus the
per-zone background-image tables. Defines the loading-screen
images shown when the client crosses into a new map /
instance, with optional level-bracket gating and expansion
gating (TBC art only shown if expansion installed).
When multiple screens match the player's current map + level
+ expansion, displayWeight selects randomly between them — a
zone with 3 weighted variants gets a different image roughly
proportional to weight.
4 expansion gates (Classic / TBC / WotLK / TurtleWoW),
isAnimated flag for screens with subtle animation,
isWideAspect flag for 16:9 raid intro art (vs 4:3 standard).
Cross-references with prior formats — mapId points at
WMS.map.mapId (which map triggers this loading screen);
mapId=0 is the catch-all sentinel for screens shown when
no map-specific screen matches.
CLI: --gen-lds (3 base screens — Elwynn level 1-30, Orgrimmar,
GenericFallback level 31-80 catch-all), --gen-lds-instances
(5 WotLK dungeon screens with mapId+expansion cross-refs:
Halls of Lightning/Stone, Utgarde Pinnacle, Violet Hold,
Old Kingdom), --gen-lds-raid (3 raid intro screens —
Naxxramas/Ulduar/ToC at isWideAspect=1 with weight=3),
--info-wlds, --validate-wlds with --json variants. Validator
catches id+name+texture required, expansion 0..3, level range
valid, weight=0 (in pool but never picked), and the practical
catch-all overlap warning when multiple mapId=0 screens share
overlapping level brackets (random pick becomes
non-deterministic).
Format graph: 62 → 63 binary formats. CLI flag count: 847
→ 854.
2026-05-09 20:59:25 -07:00
std : : printf ( " --gen-lds <wlds-base> [name] \n " ) ;
std : : printf ( " Emit .wlds starter: 3 base loading screens (Elwynn / Orgrimmar / GenericFallback catch-all) \n " ) ;
std : : printf ( " --gen-lds-instances <wlds-base> [name] \n " ) ;
std : : printf ( " Emit .wlds 5 WotLK dungeon loading screens (Halls of Lightning / Stone / UP / Violet Hold / Old Kingdom) \n " ) ;
std : : printf ( " --gen-lds-raid <wlds-base> [name] \n " ) ;
std : : printf ( " Emit .wlds 3 raid intro screens (Naxxramas / Ulduar / Trial of the Crusader) with isWideAspect=1 \n " ) ;
std : : printf ( " --info-wlds <wlds-base> [--json] \n " ) ;
std : : printf ( " Print WLDS entries (id / mapId / level range / display weight / expansion / animated+wide flags / name) \n " ) ;
std : : printf ( " --validate-wlds <wlds-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+texture required, expansion 0..3, level range valid, weight=0 warning, catch-all overlap \n " ) ;
2026-05-09 21:01:53 -07:00
std : : printf ( " --export-wlds-json <wlds-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wlds to a human-editable JSON sidecar (defaults to <base>.wlds.json) \n " ) ;
std : : printf ( " --import-wlds-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wlds.json sidecar back into binary .wlds (accepts expansionRequired int OR name string) \n " ) ;
feat(pipeline): add WSUF (Wowee Item Random Suffix) catalog
64th open format — replaces ItemRandomProperties.dbc +
ItemRandomSuffix.dbc plus the AzerothCore-style suffix-roll
tables. Defines random "of the X" suffixes that roll on
green and blue items at world drop ("Sturdy Cloth Cap of
the Bear" = base item + STR + STA suffix).
5 suffix categories (Generic / Elemental / Defensive /
PvPSuffix / Crafted), per-suffix item-quality bracket gating
(only blue+ items can roll PvPSuffix), restricted-slot mask
that limits which equipment slots a suffix can apply to (15
slot bits matching WCEQ slot enum), and up to 5 stat bonus
slots per suffix matching WoW canonical max.
statValuePoints isn't an absolute number — it's a scaling
base that the runtime multiplies by an item-level
coefficient to compute the final per-item bonus, so "of the
Bear" gives proportionally more strength on a level-60 item
than on a level-20 item.
Cross-references with prior formats — statKind values match
WIT.statType enum (STR=4, AGI=3, INT=5, SPI=6, STA=7) so
item generators roll consistent stats with base items.
CLI: --gen-suf (3 generic stat triads — Bear STR+STA, Eagle
INT+SPI, Tiger STR+AGI), --gen-suf-magical (4 elemental
spell-power suffixes restricted to caster-eligible slots),
--gen-suf-pvp (3 PvPSuffix entries with resilience + offensive
stats, blue+ quality only), --info-wsuf, --validate-wsuf with
--json variants. Validator catches id+name required, category
0..4, quality range valid (0..7 covers heirloom), itemQuality
floor<=ceiling, stat-kind/value pairing (kind=0 with value!=0
is a typo, vice versa), and no-stats warning (suffix renames
item without changing it).
Format graph: 63 → 64 binary formats. CLI flag count: 854
→ 861.
2026-05-09 21:05:49 -07:00
std : : printf ( " --gen-suf <wsuf-base> [name] \n " ) ;
std : : printf ( " Emit .wsuf starter: 3 stat-suffix entries (of the Bear STR+STA / of the Eagle INT+SPI / of the Tiger STR+AGI) \n " ) ;
std : : printf ( " --gen-suf-magical <wsuf-base> [name] \n " ) ;
std : : printf ( " Emit .wsuf 4 elemental suffixes (of Fire / of Frost / of Shadow / of Arcane) — flat per-school spell power \n " ) ;
std : : printf ( " --gen-suf-pvp <wsuf-base> [name] \n " ) ;
std : : printf ( " Emit .wsuf 3 PvPSuffix-category entries (of the Champion / of the Gladiator / of Resilience) blue+ only \n " ) ;
std : : printf ( " --info-wsuf <wsuf-base> [--json] \n " ) ;
std : : printf ( " Print WSUF entries (id / category / quality range / restricted slot mask / # populated stat slots / name) \n " ) ;
std : : printf ( " --validate-wsuf <wsuf-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, category 0..4, quality range valid (0..7), stat-kind/value pairing, no-stats warning \n " ) ;
2026-05-09 21:07:58 -07:00
std : : printf ( " --export-wsuf-json <wsuf-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsuf to a human-editable JSON sidecar with nested stats[] arrays (defaults to <base>.wsuf.json) \n " ) ;
std : : printf ( " --import-wsuf-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsuf.json sidecar back into binary .wsuf (accepts suffixCategory int OR name string; missing stat slots cleared) \n " ) ;
feat(pipeline): add WCRR (Wowee Combat Rating Conversion) catalog
65th open format — replaces gtCombatRatings.dbc plus the
per-level rating-to-percentage tables in gtRegenHPPerSpt.dbc
and related stat-curve DBCs. Defines per-rating-type
conversion factors at canonical level breakpoints (1 / 60
/ 70 / 80) — the runtime linearly interpolates between
breakpoints for intermediate levels.
pointsAtLevelN is "how many rating points equal 1% of the
benefit at that level." Higher level = more rating needed
for the same %. Standard WoW WotLK example: 14 crit rating
= 1% crit at L60, but 45.91 = 1% at L80.
5 rating kinds (Combat / Defense / Spell / Resilience /
Other) classify what stat resolver category each rating
belongs to.
CLI: --gen-crr (3 essential combat ratings — Hit/Crit/Haste
at canonical WoW WotLK conversion values), --gen-crr-defensive
(4 defensive — Defense/Dodge/Parry/Block with diminishing-
returns soft-cap percentages), --gen-crr-spell (3 spell —
SpellPower direct 1:1, SpellPenetration flat, MP5 mana
regen), --info-wcrr, --validate-wcrr with --json variants.
Validator catches id+name required, kind 0..4, all
pointsAtLN > 0 (otherwise stat resolver would div-by-zero),
maxBenefitPercent > 0 (rating would never grant any
benefit), and non-monotonic conversion curve warning
(rating cost typically ascends with level for non-flat
ratings like SpellPower).
Format graph: 64 → 65 binary formats. CLI flag count: 861
→ 868.
2026-05-09 21:11:26 -07:00
std : : printf ( " --gen-crr <wcrr-base> [name] \n " ) ;
std : : printf ( " Emit .wcrr starter: 3 essential combat ratings (Hit / Crit / Haste) at canonical L80 conversion values \n " ) ;
std : : printf ( " --gen-crr-defensive <wcrr-base> [name] \n " ) ;
std : : printf ( " Emit .wcrr 4 defensive ratings (Defense / Dodge / Parry / Block) for tank stat scaling with diminishing returns caps \n " ) ;
std : : printf ( " --gen-crr-spell <wcrr-base> [name] \n " ) ;
std : : printf ( " Emit .wcrr 3 spell ratings (SpellPower direct / SpellPenetration flat / MP5 mana regen) for caster stat scaling \n " ) ;
std : : printf ( " --info-wcrr <wcrr-base> [--json] \n " ) ;
std : : printf ( " Print WCRR entries (id / kind / pointsAtL1/L60/L70/L80 conversion floors / max benefit pct / name) \n " ) ;
std : : printf ( " --validate-wcrr <wcrr-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, kind 0..4, all pointsAtLN > 0 (div-by-zero risk), maxPct > 0, monotonic ascending curve \n " ) ;
2026-05-09 21:14:18 -07:00
std : : printf ( " --export-wcrr-json <wcrr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wcrr to a human-editable JSON sidecar (defaults to <base>.wcrr.json) \n " ) ;
std : : printf ( " --import-wcrr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wcrr.json sidecar back into binary .wcrr (accepts ratingKind int OR name string; pointsAtLN default to canonical WoW values) \n " ) ;
feat(pipeline): add WUMV (Wowee Unit Movement Type) catalog
66th open format — replaces UnitMovement.dbc plus the
movement-modifier portions of CreatureModelData.dbc. Defines
movement speed types (walk / run / swim / flight / fly /
pitch) with their canonical baseline speeds in yards-per-
second, plus the temp speed buffs that stack on top
(Sprint, Aspect of the Cheetah, Travel Form).
12 movement categories cover the canonical surface (Walk /
Run / Backward / Swim / SwimBack / Turn / Flight /
FlightBack / Pitch / Fly / FlyBack / TempBuff). baseSpeed
is yards/second for baseline categories and ignored for
TempBuff entries (which use baseMultiplier instead).
maxMultiplier caps stacking — Sprint capped at 1.4 means
Sprint + Aspect of Cheetah doesn't exceed 1.4× run speed.
stackingPriority resolves conflicts when multiple buffs
of equal multiplier compete (higher wins).
CLI: --gen-umv (4 baseline at canonical WoW vanilla speeds:
Walk 2.5y/s, Run 7.0y/s, Swim 4.7y/s, Turn π rad/s),
--gen-umv-flight (5 flight entries — ground-rail Flight
7y/s, free Fly 14y/s, Pitch 1.5 rad/s, backward variants
at slower 4.5y/s), --gen-umv-buffs (5 temp speed buffs
matching real WoW spell auras with proper durations and
stacking priorities), --info-wumv, --validate-wumv with
--json variants. Validator catches id+name required,
category 0..11, baseMultiplier > 0 (otherwise unit freezes
in place), maxMultiplier >= baseMultiplier (cap below
floor would clamp the base down), baseline categories
need baseSpeed > 0, and Run < 3.0y/s warning (canonical
is 7.0y/s).
Format graph: 65 → 66 binary formats. CLI flag count: 870
→ 875.
2026-05-09 21:18:03 -07:00
std : : printf ( " --gen-umv <wumv-base> [name] \n " ) ;
std : : printf ( " Emit .wumv starter: 4 baseline movement types (Walk 2.5y/s / Run 7.0y/s / Swim 4.7y/s / Turn π rad/s) \n " ) ;
std : : printf ( " --gen-umv-flight <wumv-base> [name] \n " ) ;
std : : printf ( " Emit .wumv 5 flight entries (Flight ground-rail / Fly free / FlyBack / FlightBack / Pitch rate) requiring flight skill \n " ) ;
std : : printf ( " --gen-umv-buffs <wumv-base> [name] \n " ) ;
std : : printf ( " Emit .wumv 5 temp speed buffs (Sprint 1.4× / Aspect Cheetah 1.3× / Travel 1.4× / Crusader 1.2× / Wind Walk 1.5× ) \n " ) ;
std : : printf ( " --info-wumv <wumv-base> [--json] \n " ) ;
std : : printf ( " Print WUMV entries (id / category / baseSpeed / multipliers / duration / priority / flight+stack flags / name) \n " ) ;
std : : printf ( " --validate-wumv <wumv-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, category 0..11, baseMultiplier > 0, max >= base, baseline categories need baseSpeed > 0 \n " ) ;
2026-05-09 21:20:13 -07:00
std : : printf ( " --export-wumv-json <wumv-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wumv to a human-editable JSON sidecar (defaults to <base>.wumv.json) \n " ) ;
std : : printf ( " --import-wumv-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wumv.json sidecar back into binary .wumv (accepts movementCategory int OR name string; multipliers default to 1.0/1.4) \n " ) ;
feat(pipeline): add WQSO (Wowee Quest Sort) catalog
67th open format — replaces QuestSort.dbc plus the quest-log
categorization fields in QuestInfo.dbc. Defines the
categories that quests fall into for the quest-log UI:
class quests (Warrior trial, etc), profession quests, daily
quests, holiday events, reputation grinds, dungeon /
heroic / raid quests, repeatables, PvP, tournament.
12 sort kinds (General / ClassQuest / Profession / Daily /
Holiday / Reputation / Dungeon / Raid / Heroic / Repeatable
/ PvP / Tournament). Each WQT (quest) entry can reference
a sortId here to be grouped under the right header in the
quest log. Sorts can be class-restricted (Warrior quests
only show for warriors), profession-restricted, or
faction-reputation-gated.
Cross-references with prior formats — targetClassMask uses
WCHC.classId bit positions (matches WGLY/WSET/WGTP
convention), targetProfessionId points at WTSK.profession
enum, targetFactionId points at WFAC.factionId.
CLI: --gen-qso (3 generic sorts — General catch-all, Daily
reset, Repeatable non-daily), --gen-qso-class (10 class-
specific sorts with proper bit masks for Warrior 0x02
through Druid 0x800), --gen-qso-profession (8 profession
sorts with WTSK profession enum cross-refs), --info-wqso,
--validate-wqso with --json variants. Validator catches
id+name+displayName required, kind 0..11, ClassQuest with
classMask=0 (not actually class-restricted), Profession
with profId=0 + non-Blacksmithing-name (likely typo since
0=Blacksmithing in WTSK), and Reputation with factionId=0
(no faction to grind).
Format graph: 66 → 67 binary formats. CLI flag count: 877
→ 882.
2026-05-09 21:23:38 -07:00
std : : printf ( " --gen-qso <wqso-base> [name] \n " ) ;
std : : printf ( " Emit .wqso starter: 3 generic sorts (General catch-all / Daily reset / Repeatable non-daily) \n " ) ;
std : : printf ( " --gen-qso-class <wqso-base> [name] \n " ) ;
std : : printf ( " Emit .wqso 10 class-specific sorts (Warrior / Paladin / Hunter / Rogue / Priest / DK / Shaman / Mage / Warlock / Druid) \n " ) ;
std : : printf ( " --gen-qso-profession <wqso-base> [name] \n " ) ;
std : : printf ( " Emit .wqso 8 profession sorts (Blacksmithing / Tailoring / Engineering / Alchemy / Enchanting / Leatherworking / Jewelcrafting / Inscription) \n " ) ;
std : : printf ( " --info-wqso <wqso-base> [--json] \n " ) ;
std : : printf ( " Print WQSO entries (id / kind / display priority / classMask / profession / faction / displayName) \n " ) ;
std : : printf ( " --validate-wqso <wqso-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+displayName required, kind 0..11, ClassQuest needs classMask>0, Reputation needs factionId>0 \n " ) ;
2026-05-09 21:25:12 -07:00
std : : printf ( " --export-wqso-json <wqso-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wqso to a human-editable JSON sidecar (defaults to <base>.wqso.json) \n " ) ;
std : : printf ( " --import-wqso-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wqso.json sidecar back into binary .wqso (accepts sortKind int OR name string) \n " ) ;
feat(editor): add WSRG (Spell Range Index) open catalog format
Open replacement for Blizzard's SpellRange.dbc plus the per-spell
range-bucket fields in Spell.dbc. Defines the categorical range
buckets that spells reference instead of carrying their own min/max
yards (every Frostbolt shares one 30y bucket; every Heal shares
one 40y friendly bucket). Each entry carries separate min/max for
hostile vs friendly targets so heals can reach further on allies
than nukes do on enemies, plus an icon color for HUD range
indicators.
Three preset emitters: --gen-srg (3 baseline buckets:
Self/Melee/Spell), --gen-srg-ranged (5 ranged spell buckets:
Short/Medium/Long/VeryLong/Unlimited), --gen-srg-friendly (3
friendly-only buckets where hostile range is 0). --info-wsrg and
--validate-wsrg round out the per-format surface; validation
catches negative ranges, min>max, duplicate ids, out-of-range
rangeKind, and warns on Self+nonzero range or Melee>8y.
Wired through the cross-format table so WSRG appears automatically
in --list-formats, --info-magic, --diff-headers, --summary-dir,
--rename-by-magic, --catalog-grep, --tree-summary-md, and
--touch-tree. Format count 67 -> 68; CLI flag count 885 -> 890.
2026-05-09 21:33:17 -07:00
std : : printf ( " --gen-srg <wsrg-base> [name] \n " ) ;
std : : printf ( " Emit .wsrg starter: 3 baseline range buckets (Self 0-0 / Melee 0-5 / Spell 0-30) \n " ) ;
std : : printf ( " --gen-srg-ranged <wsrg-base> [name] \n " ) ;
std : : printf ( " Emit .wsrg 5 ranged spell buckets (Short 20y / Medium 30y / Long 40y / VeryLong 100y / Unlimited) \n " ) ;
std : : printf ( " --gen-srg-friendly <wsrg-base> [name] \n " ) ;
std : : printf ( " Emit .wsrg 3 friendly-only buckets (Heal 40y / Cleanse 30y / Buff 30y) where hostile range = 0 \n " ) ;
std : : printf ( " --info-wsrg <wsrg-base> [--json] \n " ) ;
std : : printf ( " Print WSRG entries (id / kind / hostile + friendly min-max yards / icon color / name) \n " ) ;
std : : printf ( " --validate-wsrg <wsrg-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, rangeKind 0..6, min<=max, no negatives, no duplicate ids; warns on Self+nonzero range and Melee>8y \n " ) ;
feat(editor): add WSRG JSON round-trip (--export/--import-wsrg-json)
Closes the editing loop on the spell-range bucket catalog: dump a
.wsrg to a JSON sidecar, hand-edit the buckets (rename, retune
yards, recolor HUD indicator), re-import to a byte-identical
binary. The exporter emits both the int rangeKind (0..6) and the
human-readable rangeKindName ("self", "melee", "short", "ranged",
"long", "very-long", "unlimited"); the importer accepts either,
so JSON sidecars stay readable without losing the canonical binary
encoding.
Verified byte-identical round-trip on all three presets (starter,
ranged, friendly). CLI flag count 890 -> 892.
2026-05-09 21:34:43 -07:00
std : : printf ( " --export-wsrg-json <wsrg-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsrg to a human-editable JSON sidecar (defaults to <base>.wsrg.json) \n " ) ;
std : : printf ( " --import-wsrg-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsrg.json sidecar back into binary .wsrg (accepts rangeKind int OR rangeKindName string) \n " ) ;
2026-05-09 21:37:42 -07:00
std : : printf ( " --gen-sct <wsct-base> [name] \n " ) ;
std : : printf ( " Emit .wsct starter: 4 baseline cast time buckets (Instant 0ms / FastCast 1s / MediumCast 1.5s / LongCast 3s) \n " ) ;
std : : printf ( " --gen-sct-channel <wsct-base> [name] \n " ) ;
std : : printf ( " Emit .wsct 3 channeled-spell buckets (TickEvery1s 3s total / TickEvery2s 6s / TickEvery3s 9s) \n " ) ;
std : : printf ( " --gen-sct-ramp <wsct-base> [name] \n " ) ;
std : : printf ( " Emit .wsct 4 level-scaled buckets (perLevelMs > 0; baseMs grows with level, clamped to min/max) \n " ) ;
std : : printf ( " --info-wsct <wsct-base> [--json] \n " ) ;
std : : printf ( " Print WSCT entries (id / kind / baseMs / perLevelMs / minMs / maxMs / iconColor / name) \n " ) ;
std : : printf ( " --validate-wsct <wsct-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, castKind 0..4, baseMs>=0, min<=max, no duplicate ids; warns on Instant+nonzero base, errors on Channel+0 base \n " ) ;
2026-05-09 21:38:56 -07:00
std : : printf ( " --export-wsct-json <wsct-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsct to a human-editable JSON sidecar (defaults to <base>.wsct.json) \n " ) ;
std : : printf ( " --import-wsct-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsct.json sidecar back into binary .wsct (accepts castKind int OR castKindName string) \n " ) ;
feat(editor): add WSDR (Spell Duration Index) — completes WSRG/WSCT/WSDR triplet
Open replacement for SpellDuration.dbc plus per-spell duration
fields in Spell.dbc. Defines the categorical duration buckets
that auras / DoTs / HoTs / buffs reference (5s / 30s / 5min / 1hr
/ UntilCancelled / UntilDeath).
Together with WSRG (range) and WSCT (cast time), this completes a
small triplet of spell-metadata catalogs: instead of every
Frostbolt rank embedding its own range, cast time, and
chill-debuff duration as duplicate fields, each spell holds three
small integer ids that resolve through these three tables. The
engine retunes thousands of spells at once by editing one bucket.
Duration scales with caster level via perLevelMs (a rank-1 Renew
at 9s grows to 12s at lvl 60), then is clamped to maxDurationMs.
Negative baseDurationMs is the canonical sentinel for "no timer"
(UntilCancelled / UntilDeath); resolveAtLevel returns -1 for
those so HUD code can render the indefinite-duration glyph.
Three preset emitters: --gen-sdr (5 baseline tiers from instant
to one-hour), --gen-sdr-buffs (4 long-duration buffs including
UntilDeath), --gen-sdr-dot (4 tick-based DoT/HoT buckets at 3s
ticks). Validation enforces base>0 for Timed/TickBased, base<0
for permanent kinds, max>=base, durationKind 0..4, no duplicate
ids, and warns on Instant+nonzero base.
Wired through the cross-format table; WSDR appears automatically
in all 9 cross-format utilities. Format count 69 -> 70; CLI flag
count 899 -> 904.
2026-05-09 21:41:55 -07:00
std : : printf ( " --gen-sdr <wsdr-base> [name] \n " ) ;
std : : printf ( " Emit .wsdr starter: 5 baseline duration buckets (Instant 0 / Short 5s / Medium 30s / Long 5min / OneHour 60min) \n " ) ;
std : : printf ( " --gen-sdr-buffs <wsdr-base> [name] \n " ) ;
std : : printf ( " Emit .wsdr 4 long-duration buffs (PartyBuff 30m / RaidBuff 60m / WorldBuff 4hr / UntilDeath -1) \n " ) ;
std : : printf ( " --gen-sdr-dot <wsdr-base> [name] \n " ) ;
std : : printf ( " Emit .wsdr 4 DoT/HoT buckets (4-tick 12s / 5-tick 15s / 6-tick 18s / 8-tick 24s) \n " ) ;
std : : printf ( " --info-wsdr <wsdr-base> [--json] \n " ) ;
std : : printf ( " Print WSDR entries (id / kind / baseMs / perLevelMs / maxMs / iconColor / name) \n " ) ;
std : : printf ( " --validate-wsdr <wsdr-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, durationKind 0..4, base>0 for Timed/TickBased, base<0 for permanent kinds, max>=base, no duplicate ids \n " ) ;
2026-05-09 21:43:16 -07:00
std : : printf ( " --export-wsdr-json <wsdr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsdr to a human-editable JSON sidecar (defaults to <base>.wsdr.json) \n " ) ;
std : : printf ( " --import-wsdr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsdr.json sidecar back into binary .wsdr (accepts durationKind int OR durationKindName string) \n " ) ;
2026-05-09 21:49:13 -07:00
std : : printf ( " --gen-cdb <wscd-base> [name] \n " ) ;
std : : printf ( " Emit .wscd starter: 4 baseline cooldown buckets (GlobalCooldown 1.5s / ShortItem 5s / MediumItem 30s / LongItem 60s shared) \n " ) ;
std : : printf ( " --gen-cdb-class <wscd-base> [name] \n " ) ;
std : : printf ( " Emit .wscd 5 mage class buckets (Polymorph family / AlterTime 90s / Counterspell 24s / Blink 15s / IceBlock 5min) \n " ) ;
std : : printf ( " --gen-cdb-items <wscd-base> [name] \n " ) ;
std : : printf ( " Emit .wscd 5 item buckets (HealingPot+ManaPot 60s shared / ManaJade GCD-only / EngineerTrinket 60s / Hearthstone 60min) \n " ) ;
std : : printf ( " --info-wscd <wscd-base> [--json] \n " ) ;
std : : printf ( " Print WSCD entries (id / kind / cooldownMs / category flags / name) — flags decoded as label list \n " ) ;
std : : printf ( " --validate-wscd <wscd-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, bucketKind 0..4, no duplicate ids; warns on Global without OnGCDStart and Spell with SharedWithItems \n " ) ;
2026-05-09 21:50:39 -07:00
std : : printf ( " --export-wscd-json <wscd-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wscd to a human-editable JSON sidecar (defaults to <base>.wscd.json) \n " ) ;
std : : printf ( " --import-wscd-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wscd.json sidecar back into binary .wscd (accepts bucketKind int OR name; categoryFlags as int OR pipe-separated label string) \n " ) ;
feat(editor): add WCEF (Creature Family) open catalog format
Open replacement for CreatureFamily.dbc plus the per-creature
family fields in Creature.dbc. Defines the family categorization
that pet-able beasts share (Bear / Cat / Wolf / Boar / Crab /
Raptor / Devilsaur / etc), each with its own pet talent tree
(Ferocity / Tenacity / Cunning), food preferences as a bitmask
(Meat / Fish / Bread / Cheese / Fruit / Fungus / Raw), the skill
line that family-specific abilities reference, and the minimum
hunter level required to tame it.
Used by the hunter pet system to decide which talent tree a tamed
pet uses, validate that a hunter can tame a creature, match
feeding-table food items to pet preferences, and gate exotic-beast
families behind the Beast Master 51-point talent.
Cross-references back to WCRT (creature.familyId points here) and
WSPL (family-specific abilities reference WSPL spellId via the
skillLine field).
Three preset emitters: --gen-cef (5 baseline families covering
both major talent trees), --gen-cef-ferocity (4 DPS-tree pets
with bleed/howl/armor-shred mechanics), --gen-cef-exotic (4
exotic Beast Master families requiring 51-point talent).
Validation enforces id+name presence, familyKind 0..5, talent
tree 0..3, no duplicate ids, and warns on:
- NotPet families with a non-None talent tree (irrelevant)
- Exotic families with minLevelForTame > 80 (level-cap unreachable)
- Beast/Exotic families with no food types set (pet would starve)
Wired through the cross-format table; WCEF appears automatically
in all 10 cross-format utilities. Format count 71 -> 72; CLI flag
count 914 -> 919.
2026-05-09 21:54:00 -07:00
std : : printf ( " --gen-cef <wcef-base> [name] \n " ) ;
std : : printf ( " Emit .wcef starter: 5 baseline beast families (Bear/Cat/Wolf/Boar/Crab) covering Tenacity + Ferocity trees \n " ) ;
std : : printf ( " --gen-cef-ferocity <wcef-base> [name] \n " ) ;
std : : printf ( " Emit .wcef 4 Ferocity-tree DPS pets (Cat / Wolf / Raptor / Devilsaur) with bleed/howl/armor mechanics \n " ) ;
std : : printf ( " --gen-cef-exotic <wcef-base> [name] \n " ) ;
std : : printf ( " Emit .wcef 4 exotic Beast Master families (Worm / Devilsaur / Chimaera / Core Hound) — Exotic kind, requires 51-pt BM \n " ) ;
std : : printf ( " --info-wcef <wcef-base> [--json] \n " ) ;
std : : printf ( " Print WCEF entries (id / kind / talent tree / tame level / skill line / food types / name) \n " ) ;
std : : printf ( " --validate-wcef <wcef-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, familyKind 0..5, talent tree 0..3, no duplicate ids; warns on NotPet+talent, Exotic+lvl>80, Beast/Exotic with no foods (would starve) \n " ) ;
2026-05-09 21:55:23 -07:00
std : : printf ( " --export-wcef-json <wcef-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wcef to a human-editable JSON sidecar (defaults to <base>.wcef.json) \n " ) ;
std : : printf ( " --import-wcef-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wcef.json sidecar back into binary .wcef (accepts familyKind/petTalentTree int OR name; petFoodTypes int OR pipe-separated label string) \n " ) ;
feat(editor): add WSPC (Spell Power Cost) — completes spell-bucket five-pack
Open replacement for the per-spell power-cost fields in Spell.dbc
plus SpellPowerCost-related side tables. Defines categorical
power-cost buckets that spells reference (LowMana 5% / MediumMana
15% / HighMana 30% of caster max mana; fixed Rage-30 /
Energy-40 / Runic-30 / etc), so spells share cost metadata across
ranks instead of embedding per-rank cost numbers.
Completes the small lookup-bucket five-pack:
WSRG — range bucket
WSCT — cast time bucket
WSDR — duration bucket
WSCD — cooldown bucket
WSPC — power cost bucket (this catalog)
Five small integer ids per spell (range / cast / dur / cd / cost)
replace the dozens of duplicate per-rank fields that Blizzard's
Spell.dbc carries. Editing one bucket here retunes every spell
that references it — change LowMana from 5% to 4% and every
rank-1 bolt across every caster class becomes cheaper.
Cost can be flat (baseCost), per-level scaled (perLevelCost), or
percentage-of-max-power (percentOfBase) — the engine sums
whichever fields are non-zero. resolveCost(id, level, maxPower)
does the math. Twelve power types covering every WoW resource
(Mana / Rage / Focus / Energy / Happiness / Runic Power / Runes /
Soul Shards / Holy Power / Eclipse / Health / NoCost).
Three preset emitters: --gen-spc (4 baseline mana tiers),
--gen-spc-rage (4 fixed warrior rage costs including stance-locked
Whirlwind), --gen-spc-mixed (5 cross-class costs covering every
non-mana power type with refund-on-miss flag for energy).
Validation enforces id+name presence, powerType 0..11, no
duplicate ids; warns on percentOfBase outside [0,1] (would
overflow), NoCost type with non-zero cost fields, and non-NoCost
types with no cost set (would cast for free — easy bug to ship).
Wired through the cross-format table; WSPC appears automatically
in all 11 cross-format utilities. Format count 72 -> 73; CLI flag
count 922 -> 927.
2026-05-09 22:00:55 -07:00
std : : printf ( " --gen-spc <wspc-base> [name] \n " ) ;
std : : printf ( " Emit .wspc starter: 4 baseline mana cost tiers (NoCost / LowMana 5%% / MediumMana 15%% / HighMana 30%%) — %% of caster max mana \n " ) ;
std : : printf ( " --gen-spc-rage <wspc-base> [name] \n " ) ;
std : : printf ( " Emit .wspc 4 fixed warrior rage costs (HeroicStrike 15 / Slam 20 / Whirlwind 25 stance-locked / MortalStrike 30) \n " ) ;
std : : printf ( " --gen-spc-mixed <wspc-base> [name] \n " ) ;
std : : printf ( " Emit .wspc 5 cross-class costs covering every non-mana power type (Hunter Focus 30 / Rogue Energy 40 refund / DK Runic 30 / Paladin Holy 1 / Warlock Shard 1) \n " ) ;
std : : printf ( " --info-wspc <wspc-base> [--json] \n " ) ;
std : : printf ( " Print WSPC entries (id / powerType / baseCost / perLevelCost / percentOfBase / cost flags / name) — flags decoded as label list \n " ) ;
std : : printf ( " --validate-wspc <wspc-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, powerType 0..11, no duplicate ids; warns on percent outside [0,1], NoCost+nonzero, and non-NoCost types with no cost set (would cast for free) \n " ) ;
2026-05-09 22:02:08 -07:00
std : : printf ( " --export-wspc-json <wspc-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wspc to a human-editable JSON sidecar (defaults to <base>.wspc.json) \n " ) ;
std : : printf ( " --import-wspc-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wspc.json sidecar back into binary .wspc (accepts powerType int OR name; costFlags int OR pipe-separated label string) \n " ) ;
feat(editor): add WGFS (Glyph Slot) open catalog format
Open replacement for Blizzard's GlyphSlot.dbc. Defines the
per-class glyph slot layout: which slots a class has (Major /
Minor / Prime), in which display order they appear in the
spellbook UI, and at which character level each slot becomes
available for use.
Distinct from WGLY (GlyphProperties) which defines the individual
glyphs themselves. WGLY says "Glyph of Polymorph exists, costs 1
inscription dust, modifies Polymorph"; WGFS says "the slot that
holds Glyph of Polymorph is the second Major Glyph Slot, unlocks
at level 25, and only Mages have it".
Layout grew across expansions, captured by the three presets:
- --gen-gfs — 6 slots: 3 Major + 3 Minor all-class
baseline (25/50/75 each)
- --gen-gfs-wotlk — 6 slots: 3 Major (15/30/50) + 3 Minor
(15/50/70) matching WotLK 3.3.5a
- --gen-gfs-cata — 9 slots: 3 Prime + 3 Major + 3 Minor
matching Cataclysm
Cross-references back to WGLY (glyphs reference slotKind to
constrain which glyph fits which slot) and WCHC (requiredClassMask
uses the same bit layout as WCHC class IDs).
Validation enforces id+name+classMask presence (classMask=0 means
no class can use the slot — usually a config bug), slotKind 0..2,
no duplicate ids; warns on minLevelToUnlock>80 (would never
unlock at WotLK cap), displayOrder>4 (UI typically shows 3-4),
and (kind+order) collisions for overlapping classMask (two slots
claiming the same UI position would render on top of each other).
isUnlockedFor(id, classBit, level) is the engine helper.
Wired through the cross-format table; WGFS appears automatically
in all 11 cross-format utilities. Format count 73 -> 74; CLI flag
count 929 -> 934.
2026-05-09 22:05:05 -07:00
std : : printf ( " --gen-gfs <wgfs-base> [name] \n " ) ;
std : : printf ( " Emit .wgfs starter: 6 baseline glyph slots (3 Major + 3 Minor) all-class, unlocking at 25/50/75 each \n " ) ;
std : : printf ( " --gen-gfs-wotlk <wgfs-base> [name] \n " ) ;
std : : printf ( " Emit .wgfs WotLK 3.3.5a layout: 3 Major (15/30/50) + 3 Minor (15/50/70), all-class \n " ) ;
std : : printf ( " --gen-gfs-cata <wgfs-base> [name] \n " ) ;
std : : printf ( " Emit .wgfs Cataclysm layout: 3 Prime + 3 Major + 3 Minor (9 slots), all unlocking at 25/50/75 \n " ) ;
std : : printf ( " --info-wgfs <wgfs-base> [--json] \n " ) ;
std : : printf ( " Print WGFS entries (id / kind / displayOrder / minLevelToUnlock / classMask / name) \n " ) ;
std : : printf ( " --validate-wgfs <wgfs-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+classMask required, slotKind 0..2, no duplicate ids; warns on lvl>80, displayOrder>4, and (kind+order) collisions for overlapping classMask \n " ) ;
2026-05-09 22:06:16 -07:00
std : : printf ( " --export-wgfs-json <wgfs-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wgfs to a human-editable JSON sidecar (defaults to <base>.wgfs.json) \n " ) ;
std : : printf ( " --import-wgfs-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wgfs.json sidecar back into binary .wgfs (accepts slotKind int OR slotKindName string) \n " ) ;
feat(editor): add WCDF (Creature Difficulty) open catalog format
Open replacement for Blizzard's CreatureDifficulty.dbc. Maps a
base creature entry to its difficulty variants:
Normal-10 / Normal-25 / Heroic-10 / Heroic-25 in WotLK raid
format. Each variant is itself a separate WCRT creature entry
with its own stats, abilities, and loot.
When a 25-man party engages an instance, the engine looks up the
encounter base creature's difficultyId, reads the normal25Id
field, and spawns that variant instead. This is how Lord
Marrowgar in 25-Heroic ICC has 30M HP and hits for 80k while the
same encounter in 10-Normal has 5M HP and hits for 25k — same
spawn point, different WCRT entries.
5-man dungeons typically use only normal10Id + heroic10Id (the
25-man fields stay 0 — engine falls through to the 10-man
variant when 25-man is queried). World bosses don't scale at
all (all 4 variant fields stay 0, engine falls back to the base
entry).
Cross-references back to WCRT — every non-zero variant id field
points at a WCRT.creatureId entry; the base creature itself
lives in WCRT too.
Three preset emitters: --gen-cdf (4 example bosses with full
4-variant routing), --gen-cdf-wotlk-raid (4 ICC-style raid
bosses Marrowgar/Deathwhisper/Saurfang/LK with all 4 difficulty
variants), --gen-cdf-fiveman (4 5-man dungeon bosses with only
Normal+Heroic 10-man set). resolveVariant(id, mode) is the
engine helper.
Validation enforces id+name+baseCreatureId presence,
spawnGroupKind 0..5, no duplicate ids; warns on:
- WorldBoss kind with non-zero variant ids (world bosses don't scale)
- duplicate baseCreatureId across routes (only first honored)
- all-self-reference non-WorldBoss (creature doesn't actually scale)
- Boss with n25 but not n10 (raid sequencing typo — n10 always
comes with n25)
Wired through the cross-format table; WCDF appears automatically
in all 11 cross-format utilities. Format count 74 -> 75; CLI flag
count 936 -> 941.
2026-05-09 22:10:09 -07:00
std : : printf ( " --gen-cdf <wcdf-base> [name] \n " ) ;
std : : printf ( " Emit .wcdf starter: 4 example boss/mini/add routes with full 4-variant 10/25/H10/H25 mapping \n " ) ;
std : : printf ( " --gen-cdf-wotlk-raid <wcdf-base> [name] \n " ) ;
std : : printf ( " Emit .wcdf 4 ICC-style raid bosses (Marrowgar / Deathwhisper / Saurfang / Lich King) with all 4 difficulty variants \n " ) ;
std : : printf ( " --gen-cdf-fiveman <wcdf-base> [name] \n " ) ;
std : : printf ( " Emit .wcdf 4 5-man dungeon bosses with only Normal+Heroic 10-man variants set (25-man fields stay 0) \n " ) ;
std : : printf ( " --info-wcdf <wcdf-base> [--json] \n " ) ;
std : : printf ( " Print WCDF entries (id / kind / baseCreatureId / 4 variant ids / name) \n " ) ;
std : : printf ( " --validate-wcdf <wcdf-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+baseCreatureId required, spawnGroupKind 0..5, no duplicate ids; warns on WorldBoss with variants, Boss with only n10, duplicate baseIds, all-self-ref non-WorldBoss \n " ) ;
2026-05-09 22:11:16 -07:00
std : : printf ( " --export-wcdf-json <wcdf-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wcdf to a human-editable JSON sidecar (defaults to <base>.wcdf.json) \n " ) ;
std : : printf ( " --import-wcdf-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wcdf.json sidecar back into binary .wcdf (accepts spawnGroupKind int OR spawnGroupKindName string) \n " ) ;
feat(editor): add WMAT (Item Material) open catalog format
Open replacement for Blizzard's Material.dbc plus the Material
and SheatheType fields in ItemDisplayInfo.dbc. Defines the
material categorization that items reference (Cloth / Leather /
Mail / Plate / Wood / Steel / Crystal / Ethereal / etc), each
with its own foley sound (played on item use), impact sound
(played on drop / hit), weight category, and material-property
flags (IsBreakable / IsMagical / IsFlammable / IsConductive /
IsHolyCharged / IsCursed).
The engine plays a sword's metallic clang from impactSoundId
when it hits a stone wall, but a cloth tabard makes no such
sound — the difference is exactly the material assigned by this
catalog. Every armor and weapon item in WIT references a
materialId here.
Twelve materialKind values cover the standard armor classes
(Cloth/Leather/Mail/Plate/Hide), structural materials (Wood /
Stone / Metal), and special categories (Liquid / Organic /
Crystal / Ethereal). Three weight tiers (Light / Medium / Heavy)
control encumbrance UI hints.
Cross-references back to WSND (foleySoundId / impactSoundId
reference WSND sound entries) and forward to WIT (item entries
reference materialId here).
Three preset emitters: --gen-mat (5 armor materials matching
WoW's armor classes), --gen-mat-weapon (5 weapon materials from
breakable+flammable Wood through enchanted endgame steel),
--gen-mat-magical (4 magical materials with special flags
including the IsHolyCharged anti-undead property).
Validation enforces id+name presence, materialKind 0..11,
weightCategory 0..2, no duplicate ids; warns on:
- IsHolyCharged + IsCursed both set (engine picks one,
typically IsCursed wins)
- Plate kind that's not Heavy weight (canonical violation)
- Cloth kind that's not Light weight (canonical violation)
Wired through the cross-format table; WMAT appears automatically
in all 11 cross-format utilities. Format count 75 -> 76; CLI flag
count 943 -> 948.
2026-05-09 22:14:44 -07:00
std : : printf ( " --gen-mat <wmat-base> [name] \n " ) ;
std : : printf ( " Emit .wmat 5 armor materials (Cloth/Leather/Mail/Plate/Hide) with weight categories matching WoW's armor classes \n " ) ;
std : : printf ( " --gen-mat-weapon <wmat-base> [name] \n " ) ;
std : : printf ( " Emit .wmat 5 weapon materials (Wood breakable+flammable / Steel / Mithril / Adamantite / EnchantedSteel magical) \n " ) ;
std : : printf ( " --gen-mat-magical <wmat-base> [name] \n " ) ;
std : : printf ( " Emit .wmat 4 magical materials (Crystal magical+breakable / Ethereal / CursedBone / HolyForged charged) \n " ) ;
std : : printf ( " --info-wmat <wmat-base> [--json] \n " ) ;
std : : printf ( " Print WMAT entries (id / kind / weight / foley/impact sound ids / material flags / name) — flags decoded as label list \n " ) ;
std : : printf ( " --validate-wmat <wmat-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, materialKind 0..11, weightCategory 0..2, no duplicate ids; warns on Holy+Cursed combo, Plate non-heavy, Cloth non-light \n " ) ;
2026-05-09 22:16:13 -07:00
std : : printf ( " --export-wmat-json <wmat-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wmat to a human-editable JSON sidecar (defaults to <base>.wmat.json) \n " ) ;
std : : printf ( " --import-wmat-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wmat.json sidecar back into binary .wmat (accepts materialKind/weightCategory int OR name; materialFlags int OR pipe-separated label string) \n " ) ;
feat(editor): add WPSP (Player Spawn Profile) open catalog format
Open replacement for AzerothCore's playercreateinfo SQL table
plus the per-class/race starting fields in CharStartOutfit.dbc.
Defines the initial state for a newly created character: starting
map / zone / position / facing, bind point (Hearthstone
destination), up to 4 starting items with counts, and up to 4
starting spells.
One entry per (race, class) combination — a Human Warrior spawns
at Northshire Abbey with a Worn Shortsword and Heroic Strike
already learned, while an Orc Hunter spawns in Valley of Trials
with Aimed Shot and a starter rifle. Death Knights have their
own preset spawning at lvl 55 in Acherus, the Ebon Hold.
The race+class fields are bitmasks (mirroring WCHC layout) so
one profile entry can cover multiple class/race combinations
that share starting state. findByRaceClass(raceBit, classBit)
is the engine helper used by character creation.
Cross-references back to WCHC (race/class bit layouts), WMS (map
ids), WIT (starting item ids), and WSPL (starting spell ids).
Three preset emitters: --gen-psp (5 Alliance combos covering
each starting zone from Northshire to Ammen Vale), --gen-psp-horde
(5 Horde combos from Valley of Trials to Sunstrider Isle),
--gen-psp-dk (2 DK combos at lvl 55 in Acherus with Death Coil /
Plague Strike / Death Grip starter loadout).
Validation enforces id+name+race+class+startingLevel presence,
no duplicate ids; warns on (0,0,0) spawn (uninitialized entry),
item id/count mismatch (granted item without count or vice versa),
startingLevel > 80 (above WotLK cap), and Death Knight class
with startingLevel < 55 (DKs canonically start at 55).
Wired through the cross-format table; WPSP appears automatically
in all 12 cross-format utilities. Format count 76 -> 77; CLI flag
count 951 -> 956.
2026-05-09 22:22:57 -07:00
std : : printf ( " --gen-psp <wpsp-base> [name] \n " ) ;
std : : printf ( " Emit .wpsp 5 Alliance starting profiles (Human Warrior / Dwarf Hunter / NightElf Druid / Gnome Mage / Draenei Shaman) with race+class spawn coords \n " ) ;
std : : printf ( " --gen-psp-horde <wpsp-base> [name] \n " ) ;
std : : printf ( " Emit .wpsp 5 Horde starting profiles (Orc Warrior / Tauren Druid / Undead Mage / Troll Hunter / BloodElf Priest) \n " ) ;
std : : printf ( " --gen-psp-dk <wpsp-base> [name] \n " ) ;
std : : printf ( " Emit .wpsp 2 Death Knight profiles (Alliance Human / Horde Orc) starting at lvl 55 in Acherus with DK starter spell loadout \n " ) ;
std : : printf ( " --info-wpsp <wpsp-base> [--json] \n " ) ;
std : : printf ( " Print WPSP entries (id / raceMask / classMask / map / zone / startingLevel / spawn coords / name) \n " ) ;
std : : printf ( " --validate-wpsp <wpsp-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+race+class+startingLevel required, no duplicate ids; warns on (0,0,0) spawn, item id/count mismatch, lvl>80, DK not at 55 \n " ) ;
2026-05-09 22:24:19 -07:00
std : : printf ( " --export-wpsp-json <wpsp-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wpsp to a human-editable JSON sidecar (defaults to <base>.wpsp.json) \n " ) ;
std : : printf ( " --import-wpsp-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wpsp.json sidecar back into binary .wpsp (all per-entry fields preserved verbatim including spawn/bind coords and item/spell ids) \n " ) ;
feat(editor): add WTLE (Talent Tab) open catalog format
Open replacement for Blizzard's TalentTab.dbc plus the per-tab
fields in Spell.dbc / Talent.dbc. Defines the three talent trees
that each class has — Warrior: Arms / Fury / Protection;
Mage: Arcane / Fire / Frost; Paladin: Holy / Protection /
Retribution; etc.
Each tab carries its own name, role hint (DPS / Tank / Healer /
Hybrid / PetClass), display order in the talent UI, background
artwork path (e.g. "WarriorArms" for the parchment background),
icon path, and the class bitmask it belongs to.
Distinct from WTAL (which defines individual talent points) —
WTLE says "the Arms tree exists for Warriors, displays in tab 1,
is a DPS spec"; WTAL says "Mortal Strike is a 1-point talent in
the Arms tree, row 7, requires Improved Charge as a prerequisite".
Cross-references back to WCHC (classMask uses the same bit
layout) and forward to WTAL (talent entries reference tabId
here). findByClass(classBit) returns all tabs for a class
sorted by displayOrder — the talent UI uses this directly to
populate its tab buttons.
Three preset emitters: --gen-tle (Warrior 3 tabs with two DPS +
one Tank), --gen-tle-mage (Mage 3 DPS tabs), --gen-tle-paladin
(Paladin 3 tabs covering all three roles in one preset).
Validation enforces id+name+classMask presence (classMask=0
means no class can use the tab — usually a config bug),
roleHint 0..4, no duplicate ids; warns on empty iconPath
(missing-texture render), empty backgroundFile (no panel art),
displayOrder>3 (UI shows at most 4 tabs), and (classMask +
displayOrder) collisions for overlapping classes (two tabs
claiming the same UI slot for the same class).
Wired through the cross-format table; WTLE appears automatically
in all 12 cross-format utilities. Format count 77 -> 78; CLI flag
count 958 -> 963.
2026-05-09 22:27:18 -07:00
std : : printf ( " --gen-tle <wtle-base> [name] \n " ) ;
std : : printf ( " Emit .wtle Warrior tabs: 3 trees (Arms DPS / Fury DPS / Protection Tank) with canonical icon and background art paths \n " ) ;
std : : printf ( " --gen-tle-mage <wtle-base> [name] \n " ) ;
std : : printf ( " Emit .wtle Mage tabs: 3 trees (Arcane / Fire / Frost), all DPS, with mage-blue icon color \n " ) ;
std : : printf ( " --gen-tle-paladin <wtle-base> [name] \n " ) ;
std : : printf ( " Emit .wtle Paladin tabs: 3 trees covering all 3 roles (Holy Healer / Protection Tank / Retribution DPS) \n " ) ;
std : : printf ( " --info-wtle <wtle-base> [--json] \n " ) ;
std : : printf ( " Print WTLE entries (id / classMask / displayOrder / role / name / backgroundFile) \n " ) ;
std : : printf ( " --validate-wtle <wtle-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+classMask required, roleHint 0..4, no duplicate ids; warns on empty icon/background, displayOrder>3, and (classMask+order) UI position collisions \n " ) ;
2026-05-09 22:28:28 -07:00
std : : printf ( " --export-wtle-json <wtle-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtle to a human-editable JSON sidecar (defaults to <base>.wtle.json) \n " ) ;
std : : printf ( " --import-wtle-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtle.json sidecar back into binary .wtle (accepts roleHint int OR roleHintName string) \n " ) ;
feat(editor): add WCTR (Currency Type) open catalog format
Open replacement for Blizzard's CurrencyTypes.dbc plus the
per-currency cap tables in CurrencyCategory.dbc. Defines the
in-game currencies that are NOT regular item stacks: Honor
Points, Arena Points, Justice Points, Valor Points, Conquest
Points, plus the various faction tokens (Champion's Seal,
Wintergrasp Mark of Honor, Emblem of Frost).
Distinct from regular items in WIT — currencies are tracked
per-character as scalar quantities with weekly + absolute caps,
not as stackable inventory slots. Some currencies are still
backed by a WIT item entry for the icon and tooltip text
(itemId field), while others (Honor, Arena) live entirely in
the currency system.
The cap model captures both shapes:
- maxQuantity = absolute lifetime cap (Honor Points 75k)
- maxQuantityWeekly = weekly earn cap, no absolute cap
(Conquest Points 1650/wk)
- both 0 = uncapped (faction tokens, Emblem of Frost)
earnableNow(id, current, weekly) is the engine helper that
returns the smaller of (remaining absolute, remaining weekly).
Cross-references back to WIT (itemId for tooltip art) and
WFAC (categoryId references factionId for FactionToken kind —
the rep gate that lets you spend the token).
Three preset emitters: --gen-ctr (4 PvP currencies covering
absolute, weekly-only, and uncapped tiers), --gen-ctr-pve (4
PvE raid currencies with same cap variety), --gen-ctr-faction
(4 faction tokens with their categoryId pointing at WFAC
faction ids).
Validation enforces id+name presence, currencyKind 0..5, no
duplicate ids; warns on:
- maxQuantityWeekly > maxQuantity (weekly cap will never be
reached, absolute cap blocks first)
- FactionToken kind with categoryId=0 (rep gate breaks)
- no caps + no itemId + no iconPath (currency has no display
data and unbounded earn rate)
Wired through the cross-format table; WCTR appears automatically
in all 12 cross-format utilities. Format count 78 -> 79; CLI flag
count 965 -> 970.
2026-05-09 22:31:42 -07:00
std : : printf ( " --gen-ctr <wctr-base> [name] \n " ) ;
std : : printf ( " Emit .wctr 4 PvP currencies (Honor 75k cap / Arena 5k weekly / Conquest 1650 weekly / Champion's Seal no cap) \n " ) ;
std : : printf ( " --gen-ctr-pve <wctr-base> [name] \n " ) ;
std : : printf ( " Emit .wctr 4 PvE raid currencies (Justice 4k cap / Valor 1k weekly / Emblem of Frost no cap / Trophy of Crusade no cap) \n " ) ;
std : : printf ( " --gen-ctr-faction <wctr-base> [name] \n " ) ;
std : : printf ( " Emit .wctr 4 faction reputation tokens (Hodir / Cenarion / Argent Dawn / Wintergrasp) — categoryId references WFAC factionId \n " ) ;
std : : printf ( " --info-wctr <wctr-base> [--json] \n " ) ;
std : : printf ( " Print WCTR entries (id / kind / itemId / max+weekly caps / categoryId / accountWide / name) \n " ) ;
std : : printf ( " --validate-wctr <wctr-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, currencyKind 0..5, no duplicate ids; warns on weekly>absolute, FactionToken+cat=0, no caps+no item+no icon \n " ) ;
2026-05-09 22:33:12 -07:00
std : : printf ( " --export-wctr-json <wctr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wctr to a human-editable JSON sidecar (defaults to <base>.wctr.json) \n " ) ;
std : : printf ( " --import-wctr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wctr.json sidecar back into binary .wctr (accepts currencyKind int OR currencyKindName string; isAccountWide bool OR int) \n " ) ;
2026-05-09 22:38:36 -07:00
std : : printf ( " --gen-spr <wspr-base> [name] \n " ) ;
std : : printf ( " Emit .wspr 4 mage portal/teleport reagents (Stormwind/Ironforge/Darnassus/Theramore) consuming Rune of Teleportation \n " ) ;
std : : printf ( " --gen-spr-warlock <wspr-base> [name] \n " ) ;
std : : printf ( " Emit .wspr 4 warlock summons (Imp / Voidwalker / Succubus / Felhunter) each consuming 1 Soul Shard \n " ) ;
std : : printf ( " --gen-spr-rez <wspr-base> [name] \n " ) ;
std : : printf ( " Emit .wspr 3 resurrection variants (Shaman Reincarnation / Priest Resurrection focused / Druid Rebirth no-cost) demonstrating each ReagentKind \n " ) ;
std : : printf ( " --info-wspr <wspr-base> [--json] \n " ) ;
std : : printf ( " Print WSPR entries (id / spellId / kind / used slot count / item x count list / name) \n " ) ;
std : : printf ( " --validate-wspr <wspr-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+spellId required, reagentKind 0..4, no duplicate ids; warns on slot id/count mismatch, SoulShard kind with non-canonical reagent, FocusedItem kind with no slots, duplicate spellId \n " ) ;
2026-05-09 22:40:12 -07:00
std : : printf ( " --export-wspr-json <wspr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wspr to a human-editable JSON sidecar (defaults to <base>.wspr.json). Reagent slot arrays exported as JSON arrays \n " ) ;
std : : printf ( " --import-wspr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wspr.json sidecar back into binary .wspr (accepts reagentKind int OR reagentKindName string; reagent arrays pad with zeros if shorter than 8) \n " ) ;
feat(editor): add WACR (Achievement Criteria) open catalog format
Open replacement for Blizzard's Achievement_Criteria.dbc. Defines
the individual progression criteria that a character must
complete to earn an achievement.
Each WACH achievement has a tree of WACR criteria — "Kill 100
boars" is one criteria entry with criteriaType=KillCreature,
targetId=boarCreatureId, requiredCount=100. Multi-criteria
achievements (e.g. "Visit all 3 capital cities") have one entry
per sub-objective, all referencing the same achievementId, with
progressOrder determining their display sequence in the
achievement UI.
Thirteen criteriaType values cover the full progression variety:
KillCreature / ReachLevel / CompleteQuest / EarnGold /
GainHonor / EarnReputation / ExploreZone / LootItem /
UseItem / CastSpell / PvPKill / DungeonRun / Misc
The targetId field is type-polymorphic — for KillCreature it
references WCRT.creatureId, for CompleteQuest it references
WQT.questId, for ExploreZone it's a WMS.zoneId, etc. The engine
interprets it based on criteriaType.
Cross-references back to WACH (achievementId), WCRT
(KillCreature.targetId), WQT (CompleteQuest.targetId), WIT
(LootItem/UseItem.targetId), WMS (ExploreZone.targetId), WSPL
(CastSpell.targetId). findByAchievement(achId) returns all
criteria for an achievement sorted by progressOrder — used
directly by the achievement UI to render the progress checklist.
Three preset emitters: --gen-acr (5 kill criteria under one
composite achievement showing different creature targets),
--gen-acr-quest (4-step quest progression), --gen-acr-mixed
(5 cross-type criteria demonstrating the full CriteriaType
variety).
Validation enforces id+name+achievementId presence,
criteriaType 0..12, no duplicate ids; warns on:
- missing targetId for type-specific kinds (KillCreature,
CompleteQuest, etc. — engine cannot track without it)
- ReachLevel with requiredCount > 80 (above WotLK cap)
- timeLimitMs set on non-time-sensitive types (engine
ignores it for ReachLevel / EarnGold)
- requiredCount=0 (criteria completes instantly on first
progress event — usually a misconfig)
Wired through the cross-format table; WACR appears automatically
in all 14 cross-format utilities. Format count 80 -> 81; CLI flag
count 981 -> 986.
2026-05-09 22:43:44 -07:00
std : : printf ( " --gen-acr <wacr-base> [name] \n " ) ;
std : : printf ( " Emit .wacr 5 kill-counting criteria (Defias 50 / Murloc 25 / Naga 100 / Dragon 1 / RareElite 1) under one composite achievement \n " ) ;
std : : printf ( " --gen-acr-quest <wacr-base> [name] \n " ) ;
std : : printf ( " Emit .wacr 4 quest-completion criteria (tutorial / starting zone / daily / escort) progression chain \n " ) ;
std : : printf ( " --gen-acr-mixed <wacr-base> [name] \n " ) ;
std : : printf ( " Emit .wacr 5 cross-type criteria (ReachLevel 80 / EarnGold 10k / GainHonor 5k / PvPKill 100 / ExploreZone Stormwind) showing CriteriaType variety \n " ) ;
std : : printf ( " --info-wacr <wacr-base> [--json] \n " ) ;
std : : printf ( " Print WACR entries (id / achievementId / type / targetId / requiredCount / timeLimitMs / progressOrder / name) \n " ) ;
std : : printf ( " --validate-wacr <wacr-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+achievementId required, criteriaType 0..12, no duplicate ids; warns on missing targetId for type-specific kinds, ReachLevel>80, timeLimit on non-timed types, requiredCount=0 \n " ) ;
2026-05-09 22:45:02 -07:00
std : : printf ( " --export-wacr-json <wacr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wacr to a human-editable JSON sidecar (defaults to <base>.wacr.json) \n " ) ;
std : : printf ( " --import-wacr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wacr.json sidecar back into binary .wacr (accepts criteriaType int 0..12 OR criteriaTypeName string) \n " ) ;
feat(editor): add WSEF (Spell Effect Type) open catalog format
Open replacement for the SpellEffect.Effect field meanings in
Spell.dbc plus the engine's hard-coded effect dispatch table.
Defines what each spell-effect integer value actually does —
SCHOOL_DAMAGE=2 deals magical damage, DUMMY=3 is a script hook,
HEAL=10 restores health, ENERGIZE=30 restores power,
APPLY_AURA=6 attaches a buff/debuff, etc.
WotLK's Spell.dbc has 192+ effect type integers, each with its
own resolver in the spell engine. This catalog lets the engine
look up "given effect=10, what resolution behavior do I run?"
via a single table lookup instead of a hard-coded switch
statement, and lets server-custom spells reference new effect
IDs without touching engine code.
Ten effectKind values capture the major behavior families
(Damage / Heal / Aura / Energize / Trigger / Movement / Summon /
Dispel / Dummy / Misc), and a 6-bit behaviorFlags field
captures targeting/gating semantics:
- RequiresTarget — must have a target
- RequiresLineOfSight — LoS check on target
- IsHostileEffect — hostile only (PvP gating)
- IsBeneficialEffect — friendly only
- IgnoresImmunities — bypasses Bubble / IBF / etc
- TriggersGCD — counts toward GCD
Distinct from WAUR (Spell Aura Type, future format) which is the
secondary classification used when effectType is APPLY_AURA. The
two together cover the full spell-effect classification space.
Three preset emitters: --gen-sef (5 damage effects covering
typical Spell.dbc damage IDs), --gen-sef-healing (4 heal
effects all flagged IsBeneficialEffect), --gen-sef-aura (5
aura-application effects covering single-target / pet /
party-wide / area variants).
Validation enforces name presence, effectKind 0..9, no duplicate
ids; warns on:
- both Hostile and Beneficial flags set (engine picks Hostile,
contradiction suggests config bug)
- Damage kind without TriggersGCD (most damage should be on GCD
— env damage is the canonical exception)
- Heal kind without IsBeneficialEffect (engine treats heal as
ungated, may damage enemies)
Wired through the cross-format table; WSEF appears automatically
in all 15 cross-format utilities. Format count 81 -> 82; CLI flag
count 989 -> 994.
2026-05-09 22:50:13 -07:00
std : : printf ( " --gen-sef <wsef-base> [name] \n " ) ;
std : : printf ( " Emit .wsef 5 damage effect entries (SchoolDamage / EnvironmentalDamage / WeaponDamageNoSchool / NormalizedWeaponDmg / PowerBurn) \n " ) ;
std : : printf ( " --gen-sef-healing <wsef-base> [name] \n " ) ;
std : : printf ( " Emit .wsef 4 healing effects (Heal / HealMaxHealth / HealPct / ScriptedHeal) all flagged IsBeneficialEffect \n " ) ;
std : : printf ( " --gen-sef-aura <wsef-base> [name] \n " ) ;
std : : printf ( " Emit .wsef 5 aura-application effects (ApplyAura / ApplyAuraOnPet / AreaAuraParty / AreaAuraOwner / PersistentAreaAura) \n " ) ;
std : : printf ( " --info-wsef <wsef-base> [--json] \n " ) ;
std : : printf ( " Print WSEF entries (id / kind / baseAmount / behavior flags / name) — flags decoded as label list \n " ) ;
std : : printf ( " --validate-wsef <wsef-base> [--json] \n " ) ;
std : : printf ( " Static checks: name required, effectKind 0..9, no duplicate ids; warns on Hostile+Beneficial conflict, Damage without TriggersGCD, Heal without IsBeneficialEffect \n " ) ;
2026-05-09 22:51:40 -07:00
std : : printf ( " --export-wsef-json <wsef-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsef to a human-editable JSON sidecar (defaults to <base>.wsef.json) \n " ) ;
std : : printf ( " --import-wsef-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsef.json sidecar back into binary .wsef (accepts effectKind int OR effectKindName string; behaviorFlags int OR pipe-separated label string) \n " ) ;
feat(editor): add WAUR (Spell Aura Type) — companion to WSEF, CLI flag count breaks 1000
Open replacement for the SpellEffect.EffectAuraType field
meanings used when SpellEffect.Effect=APPLY_AURA. Defines what
each aura-type integer value actually does once an aura is
attached to a unit — PERIODIC_DAMAGE ticks damage every N
seconds, MOD_STAT adds a stat bonus, MOD_INCREASE_SPEED scales
movement, MOD_DAMAGE_PERCENT_DONE scales spell power, etc.
Companion to WSEF — together they cover the full spell-effect
classification space:
WSEF: outer effect ID — what does the effect DO?
(APPLY_AURA, SCHOOL_DAMAGE, HEAL, etc)
WAUR: inner aura type — when WSEF=APPLY_AURA, what KIND
of aura is applied? (PERIODIC_DAMAGE, MOD_STAT,
STUN, ROOT, etc)
Nine auraKind values (Periodic / StatMod / DamageMod /
Movement / Visual / Trigger / Resource / Control / Misc)
classify the major behavior families. Periodic auras carry an
updateFrequencyMs (canonical 3s for DoT/HoT, 2s for energize,
1s for fast triggers). Stackable auras carry a maxStackCount.
Cross-references back to WSEF (this catalog is the secondary
classification that WSEF entry id 6 (APPLY_AURA) dispatches
into) and forward to WSPL (spell entries with effect=APPLY_AURA
reference an auraTypeId here).
Three preset emitters: --gen-aur (5 periodic auras with
canonical tick intervals), --gen-aur-stats (5 stat-modifier
auras instantly applied on attach), --gen-aur-movement (4
movement-impairing CC auras typical of crowd-control spells).
Validation enforces name presence, auraKind 0..8, targetingHint
0..3, no duplicate ids; errors on Periodic kind without
updateFrequencyMs (would never tick); warns on:
- non-Periodic/Trigger kinds with updateFrequencyMs > 0
(engine ignores tick interval)
- maxStackCount > 0 with isStackable=false (cap unreachable)
Wired through the cross-format table; WAUR appears automatically
in all 15 cross-format utilities. Format count 82 -> 83;
CLI flag count 996 -> 1001 — broke the 1000-flag mark.
2026-05-09 22:54:53 -07:00
std : : printf ( " --gen-aur <waur-base> [name] \n " ) ;
std : : printf ( " Emit .waur 5 periodic auras (PeriodicDamage / PeriodicHeal / PeriodicEnergize / PeriodicLeech / PeriodicTriggerSpell) at canonical 3s tick \n " ) ;
std : : printf ( " --gen-aur-stats <waur-base> [name] \n " ) ;
std : : printf ( " Emit .waur 5 stat-modifier auras (ModStat / ModResistance / ModDamageDone / ModHaste / ModCritPercent) — non-periodic, instantly applied \n " ) ;
std : : printf ( " --gen-aur-movement <waur-base> [name] \n " ) ;
std : : printf ( " Emit .waur 4 movement-impairing auras (Stun / ModDecreaseSpeed / ModConfuse / Root) typically applied by CC spells \n " ) ;
std : : printf ( " --info-waur <waur-base> [--json] \n " ) ;
std : : printf ( " Print WAUR entries (id / kind / targeting / stack flag / max stack / tick interval / name) \n " ) ;
std : : printf ( " --validate-waur <waur-base> [--json] \n " ) ;
std : : printf ( " Static checks: name required, auraKind 0..8, targetingHint 0..3, no duplicate ids; errors on Periodic without tick interval; warns on non-periodic with tick interval, maxStackCount without isStackable \n " ) ;
2026-05-09 22:56:20 -07:00
std : : printf ( " --export-waur-json <waur-base> [out.json] \n " ) ;
std : : printf ( " Export binary .waur to a human-editable JSON sidecar (defaults to <base>.waur.json) \n " ) ;
std : : printf ( " --import-waur-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .waur.json sidecar back into binary .waur (accepts auraKind/targetingHint int OR name; isStackable bool OR int) \n " ) ;
feat(editor): add WIQR (Item Quality) open catalog format
Open replacement for the hardcoded item quality tiers in the
WoW client (Poor / Common / Uncommon / Rare / Epic / Legendary
/ Artifact / Heirloom). Defines each tier's tooltip text color,
inventory slot border color, vendor price multiplier, drop-level
gating, and disenchant eligibility.
The hardcoded client uses a fixed color table (gray/white/green/
blue/purple/orange/red/gold). This catalog lets server admins:
- retune the colors (rename "Epic" to "Tier 1" with custom hex)
- add server-custom tiers above Heirloom
- change vendor markup per tier (legendary 50x base price)
- gate quality drops by character level (Heirlooms unlock 80)
The standard preset reproduces the canonical 8-tier scale with
exact hex values from the live client (#9d9d9d through #00ccff)
and standard disenchant rules (Common+ disenchantable, Legendary
and Artifact aren't). The server-custom preset shows 4 tiers
above the standard range with non-standard pricing (Junk 0.1x,
QuestLocked 0.0x unsellable). The raid preset gates 4
progression tiers behind minLevelToDrop=60 with escalating
vendor multipliers up to 50x for Legendary.
Cross-references back to WIT — item entries reference qualityId
here for tooltip color and sort order. canDropAtLevel(id, lvl)
is the engine helper used by loot generation.
Validation enforces name presence, no duplicate ids,
vendorPriceMultiplier >= 0, minLevelToDrop <= maxLevelToDrop;
warns on:
- minLevelToDrop > 80 (unreachable at WotLK cap)
- vendorPriceMultiplier > 100x (sanity check the economy)
- nameColorRGBA with alpha=0 (text would be invisible in
tooltips — common bug when copy-pasting RGB hex without
alpha byte)
Wired through the cross-format table; WIQR appears automatically
in all 15 cross-format utilities. Format count 83 -> 84; CLI
flag count 1003 -> 1008.
2026-05-09 22:59:27 -07:00
std : : printf ( " --gen-iqr <wiqr-base> [name] \n " ) ;
std : : printf ( " Emit .wiqr 8 standard quality tiers (Poor through Heirloom) with canonical hex colors and disenchant rules \n " ) ;
std : : printf ( " --gen-iqr-server <wiqr-base> [name] \n " ) ;
std : : printf ( " Emit .wiqr 4 server-custom tiers (Junk / Weekly / QuestLocked / Donator) with custom colors and non-standard markups \n " ) ;
std : : printf ( " --gen-iqr-raid <wiqr-base> [name] \n " ) ;
std : : printf ( " Emit .wiqr 4 raid progression tiers (T1/T2/T3/Legendary lvl 60+) gated by minLevelToDrop and priced for server economy \n " ) ;
std : : printf ( " --info-wiqr <wiqr-base> [--json] \n " ) ;
std : : printf ( " Print WIQR entries (id / name / nameColor RGBA / vendor multiplier / minLevel / maxLevel / disenchant flag / border texture) \n " ) ;
std : : printf ( " --validate-wiqr <wiqr-base> [--json] \n " ) ;
std : : printf ( " Static checks: name required, no duplicate ids, vendor>=0, min<=max; warns on lvl>80 (unreachable), vendor>100x (sanity), alpha=0 nameColor (invisible) \n " ) ;
2026-05-09 23:00:32 -07:00
std : : printf ( " --export-wiqr-json <wiqr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wiqr to a human-editable JSON sidecar (defaults to <base>.wiqr.json). Colors as RGBA uint32, easy to paste hex values \n " ) ;
std : : printf ( " --import-wiqr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wiqr.json sidecar back into binary .wiqr (canBeDisenchanted accepts bool OR int) \n " ) ;
feat(editor): add WSCS (Skill Cost) open catalog format
Open replacement for Blizzard's SkillCostsData.dbc plus the
per-rank training cost tables. Defines the tiered progression of
trainable skills: each rank unlocks a skill range, requires a
minimum character level, and costs a fixed amount of gold to
learn.
The canonical 6-tier profession progression captured by the
default preset:
Apprentice skill 0-75 lvl 5 1s
Journeyman skill 50-150 lvl 10 5s
Expert skill 125-225 lvl 20 1g
Artisan skill 200-300 lvl 35 5g
Master skill 275-375 lvl 50 10g
Grand Master skill 350-450 lvl 65 25g
Same shape applies to weapon skills (free, level-gated, capped at
5x char level) and riding skills (canonical Vanilla / TBC / WotLK
gold costs from 90g Apprentice through 5000g Artisan flying down
to 1000g Cold Weather Flying).
Five costKind values cover the full training-skill space
(Profession / WeaponSkill / RidingSkill / ClassSkill / Misc).
Each entry's copperCost stores the cost in copper (1g = 10000c)
which the info renderer pretty-prints as "25g 0s 0c".
Cross-references back to WSKL — skill entries reference costId
here for the tiered training schedule. nextTrainable(currentSkill,
characterLevel) is the engine helper that returns the lowest-rank
tier a character qualifies for and hasn't capped yet — used by
trainer NPCs to populate their offered-skill list.
Three preset emitters: --gen-scs (6 profession tiers), --gen-scs-
weapon (5 weapon skill tiers), --gen-scs-riding (5 riding tiers
with canonical gold costs).
Validation enforces id+name presence, costKind 0..4, no duplicate
ids, min<max range; warns on:
- requiredLevel > 80 (unreachable at WotLK cap)
- RidingSkill with requiredLevel < 20 (Apprentice canonically
unlocks at 20)
- Profession kind with copperCost=0 (every standard tier costs
at least a copper — usually a config bug)
Wired through the cross-format table; WSCS appears automatically
in all 15 cross-format utilities. Format count 84 -> 85; CLI
flag count 1010 -> 1015.
2026-05-09 23:04:02 -07:00
std : : printf ( " --gen-scs <wscs-base> [name] \n " ) ;
std : : printf ( " Emit .wscs 6 canonical profession tiers (Apprentice/Journeyman/Expert/Artisan/Master/GrandMaster) with standard skill ranges and gold costs \n " ) ;
std : : printf ( " --gen-scs-weapon <wscs-base> [name] \n " ) ;
std : : printf ( " Emit .wscs 5 weapon skill tiers (Beginner/Trained/Skilled/Expert/Master) — free to train, level-gated, capped at 5x char level \n " ) ;
std : : printf ( " --gen-scs-riding <wscs-base> [name] \n " ) ;
std : : printf ( " Emit .wscs 5 riding skill tiers (Apprentice 60%% / Journeyman 100%% / Expert 150%% / Artisan 280%% / Cold Weather Flying) with canonical Vanilla/TBC/WotLK gold costs \n " ) ;
std : : printf ( " --info-wscs <wscs-base> [--json] \n " ) ;
std : : printf ( " Print WSCS entries (id / rank / kind / minSkill / maxSkill / required level / gold cost / name) \n " ) ;
std : : printf ( " --validate-wscs <wscs-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, costKind 0..4, no duplicate ids, min<max; warns on lvl>80, RidingSkill below lvl 20, Profession with cost=0 \n " ) ;
2026-05-09 23:05:23 -07:00
std : : printf ( " --export-wscs-json <wscs-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wscs to a human-editable JSON sidecar (defaults to <base>.wscs.json) \n " ) ;
std : : printf ( " --import-wscs-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wscs.json sidecar back into binary .wscs (accepts costKind int OR costKindName string) \n " ) ;
feat(editor): add WIFS (Item Flag Set) open catalog format
Open replacement for the bit-flag meanings used in Item.dbc /
item_template.Flags. Documents every individual bit of the
32-bit item flags field with a human-readable name, description,
kind classification, and is-positive hint.
WoW's Item.dbc Flags field packs ~25 bits of metadata like
Heroic, Lootable, NoLoot, Conjured, BindOnPickup, BindOnEquip —
each controlling a specific gameplay behavior. The hardcoded
client knows what each bit means via a switch statement; this
catalog exposes that table to data-driven editors so:
- server admins can document custom flag bits
- tooltip generators can decode "why is this item soulbound?"
via flag-name lookup (decode(0x40240000) returns
["Heroic", "BindOnPickup", "Unique"])
- validators can warn about contradictory flag combinations
Seven flagKind values classify the bit families (Quality / Drop
/ Trade / Magic / Account / Server / Misc), and an isPositive
hint tells UIs whether the flag enhances the item (green) or
restricts it (red).
Cross-references back to WIT (decodes WIT.flags into the
matching named flag list) and WIQR (validators can pair Heroic
flag with WIQR Epic+ quality requirement).
Three preset emitters: --gen-ifs (8 canonical Item.dbc bits
matching the standard 3.3.5a constants), --gen-ifs-binding (5
binding-related flags BindOnPickup / BindOnEquip / etc — all
restrictive so isPositive=0), --gen-ifs-server (5 server-custom
bits in the upper range demonstrating how to overlay extra
metadata without colliding with Blizzard's bits).
Validation enforces id+name+bitMask presence, flagKind 0..6, no
duplicate ids, no duplicate bitMasks (collision means engine
would only honor first matching name when decoding); warns on
multi-bit masks (unusual — usually want individual bits).
decode(flagsValue) is the engine helper that expands a raw
flags integer into its named flag list — used directly by the
tooltip generator and item info renderers. Wired through the
cross-format table; WIFS appears automatically in all 16
cross-format utilities. Format count 85 -> 86; CLI flag count
1018 -> 1023.
2026-05-09 23:10:35 -07:00
std : : printf ( " --gen-ifs <wifs-base> [name] \n " ) ;
std : : printf ( " Emit .wifs 8 canonical Item.dbc flag bits (NoLoot / Conjured / Lootable / Wrapped / Heroic / Deprecated / NoUserDestroy / NoEquipCooldown) \n " ) ;
std : : printf ( " --gen-ifs-binding <wifs-base> [name] \n " ) ;
std : : printf ( " Emit .wifs 5 binding-related flags (BindOnPickup / BindOnEquip / BindOnUse / BindToAccount / Soulbound) — all isPositive=0 (restrict trading) \n " ) ;
std : : printf ( " --gen-ifs-server <wifs-base> [name] \n " ) ;
std : : printf ( " Emit .wifs 5 server-custom flag bits in upper range (Donator / EventReward / Anniversary / Honored / Heroic25man) \n " ) ;
std : : printf ( " --info-wifs <wifs-base> [--json] \n " ) ;
std : : printf ( " Print WIFS entries (id / bitMask hex / kind / +/- positivity / name) — handy for decoding raw item.flags integers \n " ) ;
std : : printf ( " --validate-wifs <wifs-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+bitMask required, flagKind 0..6, no duplicate ids, no duplicate bitMasks (collision); warns on multi-bit masks (unusual, usually want a single bit) \n " ) ;
2026-05-09 23:12:01 -07:00
std : : printf ( " --export-wifs-json <wifs-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wifs to a human-editable JSON sidecar (defaults to <base>.wifs.json) \n " ) ;
std : : printf ( " --import-wifs-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wifs.json sidecar back into binary .wifs (accepts flagKind int OR name; isPositive bool OR int) \n " ) ;
feat(editor): add WBKD (NPC Service Definition) open catalog format
Open replacement for AzerothCore's npc_vendor / npc_trainer /
npc_gossip / npc_options SQL tables plus the engine's hard-coded
service-type dispatch. Defines the kinds of services NPCs can
offer (Banker / Mailbox / Auctioneer / StableMaster /
FlightMaster / Trainer / Innkeeper / Battlemaster / GuildBanker
/ ReagentVendor / TabardVendor / Misc) and the per-service
metadata (gold cost, faction gating, gossip text id).
When a player right-clicks an NPC, the engine looks at the
NPC's serviceId list (from WCRT.npcFlags or equivalent) and
dispatches to the appropriate service-frame handler — Banker
opens the inventory expansion frame, Auctioneer opens the
auction house, StableMaster opens the pet stable. This catalog
defines what each service actually does and what preconditions
it requires.
Cross-references back to WCRT (creature.npcFlags decodes into a
list of service ids defined here), WFAC (factionRequiredId
references factionId for rep-gated services like Argent
Tournament), and WGSP (gossipTextId references menuId for the
"How can I help you?" dialogue line).
Three preset emitters: --gen-bkd (5 city services typical of a
capital city), --gen-bkd-battle (3 battlemaster services for
each Vanilla BG queue), --gen-bkd-profession (4 profession
services). findByKind(kind) is the engine helper used by NPC
spawning to find e.g. all FlightMaster services configured for
a server.
Validation enforces id+name presence, serviceKind 0..11, no
duplicate ids; warns on:
- Mailbox kind with non-zero gossipTextId (mailboxes are
gameobject services with no NPC dialogue; gossip won't show)
- Innkeeper kind with gossipTextId=0 (no welcome/bind dialog;
will silently bind the hearthstone)
- Battlemaster kind with non-zero requiresGold (battle queue
services are typically free)
Wired through the cross-format table; WBKD appears automatically
in all 16 cross-format utilities. Format count 86 -> 87; CLI
flag count 1025 -> 1030.
2026-05-09 23:15:20 -07:00
std : : printf ( " --gen-bkd <wbkd-base> [name] \n " ) ;
std : : printf ( " Emit .wbkd 5 city services (Banker / Mailbox / Innkeeper / Auctioneer / FlightMaster) typical of capital city offerings \n " ) ;
std : : printf ( " --gen-bkd-battle <wbkd-base> [name] \n " ) ;
std : : printf ( " Emit .wbkd 3 battlemaster services (Alterac Valley / Warsong Gulch / Arathi Basin) for queueing into Vanilla BGs \n " ) ;
std : : printf ( " --gen-bkd-profession <wbkd-base> [name] \n " ) ;
std : : printf ( " Emit .wbkd 4 profession services (Blacksmith Trainer / Tailoring Trainer / Reagent Vendor / Stable Master) \n " ) ;
std : : printf ( " --info-wbkd <wbkd-base> [--json] \n " ) ;
std : : printf ( " Print WBKD entries (id / kind / gold cost / faction gate / gossip text id / name) \n " ) ;
std : : printf ( " --validate-wbkd <wbkd-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name required, serviceKind 0..11, no duplicate ids; warns on Mailbox+gossip (no NPC dialog), Innkeeper+no-gossip (silent bind), Battlemaster+gold (queues are free) \n " ) ;
2026-05-09 23:16:32 -07:00
std : : printf ( " --export-wbkd-json <wbkd-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wbkd to a human-editable JSON sidecar (defaults to <base>.wbkd.json) \n " ) ;
std : : printf ( " --import-wbkd-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wbkd.json sidecar back into binary .wbkd (accepts serviceKind int OR serviceKindName string) \n " ) ;
feat(editor): add WTBR (Token Reward) open catalog format
Open replacement for AzerothCore's currency_token_reward SQL
table plus the per-vendor token redemption rows in npc_vendor.
Each entry says "spend N copies of token X to receive reward Y",
with reward type polymorphism: Y can be an item, a spell (taught
to the character), a title, a mount, a companion pet, a currency
conversion, an heirloom unlock, or a cosmetic (tabard / pennant /
fluff). The rewardId field's interpretation depends on the
rewardKind enum.
Distinct from WTKN (Token catalog) which defines the token
currency items themselves. WTKN says "the Champion's Seal exists
as item 44990"; WTBR says "spend 25 Champion's Seals at Argent
Tournament for the Squire's Belt (item 45517)".
Eight rewardKind values cover the full reward space (Item / Spell
/ Title / Mount / Pet / Currency / Heirloom / Cosmetic), and an
8-tier requiredFactionStanding gates by reputation
(Hated / Hostile / Unfriendly / Neutral / Friendly / Honored /
Revered / Exalted) when paired with a non-zero requiredFactionId.
Cross-references back to WTKN (spentTokenItemId), WIT (Item
rewards), WSPL (Spell rewards), WTIT (Title rewards), WMOU
(Mount rewards), WCMP (Pet rewards), WCTR (Currency conversion
rewards), and WFAC (faction-rep gating). findByToken(itemId)
is the engine helper used by vendor frames to populate the
"what can I buy with these?" list.
Three preset emitters: --gen-tbr (5 raid tier-token redemptions
consuming Trophy of the Crusade and Emblem of Frost),
--gen-tbr-pvp (5 PvP rewards spanning honor / arena / conquest
plus title and tabard kinds), --gen-tbr-faction (5 faction-
gated rewards demonstrating each standing tier from Honored
through Exalted).
Validation enforces id+name+spentTokenItemId+spentTokenCount
presence, rewardKind 0..7, requiredFactionStanding 0..7, no
duplicate ids; warns on:
- rewardId=0 (no actual reward, vendor offers entry but
grants nothing)
- requiredFactionStanding > Neutral with requiredFactionId=0
(rep gate has no faction to check)
- Currency conversion item -> itself (typo / config bug)
Wired through the cross-format table; WTBR appears automatically
in all 18 cross-format utilities. Format count 87 -> 88; CLI
flag count 1034 -> 1039.
2026-05-09 23:26:13 -07:00
std : : printf ( " --gen-tbr <wtbr-base> [name] \n " ) ;
std : : printf ( " Emit .wtbr 5 raid tier-token redemptions (T9 Conqueror's helm / Vanquisher's chest / T10 Protector's legs / Trophy Gloves) consuming Trophy of the Crusade and Emblem of Frost \n " ) ;
std : : printf ( " --gen-tbr-pvp <wtbr-base> [name] \n " ) ;
std : : printf ( " Emit .wtbr 5 PvP token redemptions (BG mount / Arena weapon / Wrathful PvP helm / Combatant title / PvP tabard) \n " ) ;
std : : printf ( " --gen-tbr-faction <wtbr-base> [name] \n " ) ;
std : : printf ( " Emit .wtbr 5 faction-rep-gated rewards (Argent tabard @ Honored / Hodir mammoth @ Exalted / Cenarion ring @ Revered / Argent title @ Exalted / Wintergrasp pet @ Honored) \n " ) ;
std : : printf ( " --info-wtbr <wtbr-base> [--json] \n " ) ;
std : : printf ( " Print WTBR entries (id / spent token x count / reward kind / rewardId / faction@standing gate / name) \n " ) ;
std : : printf ( " --validate-wtbr <wtbr-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+spentTokenItemId+count required, rewardKind 0..7, requiredFactionStanding 0..7, no duplicate ids; warns on rewardId=0 (no actual reward), standing>Neutral with factionId=0, Currency conversion item->itself \n " ) ;
2026-05-09 23:28:23 -07:00
std : : printf ( " --export-wtbr-json <wtbr-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wtbr to a human-editable JSON sidecar (defaults to <base>.wtbr.json) \n " ) ;
std : : printf ( " --import-wtbr-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wtbr.json sidecar back into binary .wtbr (accepts rewardKind/requiredFactionStanding int OR name) \n " ) ;
2026-05-09 23:32:25 -07:00
std : : printf ( " --gen-sps <wsps-base> [name] \n " ) ;
std : : printf ( " Emit .wsps 4 weapon-imbue procs (Windfury 20PPM+3sICD / Frostbrand 9PPM / Flametongue 15PPM / Mana Oil 4PPM+5sICD) on DealtMeleeAutoAttack \n " ) ;
std : : printf ( " --gen-sps-aura <wsps-base> [name] \n " ) ;
std : : printf ( " Emit .wsps 4 aura-tied procs (Blessing of Wisdom mana / Molten Armor reflect / Earth Shield heal / Judgement of Wisdom) \n " ) ;
std : : printf ( " --gen-sps-talent <wsps-base> [name] \n " ) ;
std : : printf ( " Emit .wsps 4 talent procs (Clearcasting / Omen of Clarity / Seal of Righteousness / Nightfall) with charge-consuming variants \n " ) ;
std : : printf ( " --info-wsps <wsps-base> [--json] \n " ) ;
std : : printf ( " Print WSPS entries (id / triggerSpellId / fromSpellId / chance%% / PPM / ICD / charges / proc flags) \n " ) ;
std : : printf ( " --validate-wsps <wsps-base> [--json] \n " ) ;
std : : printf ( " Static checks: id+name+triggerSpellId+procFlags required, no duplicate ids; warns on chance outside [0,1], procPpm<0, both chance+ppm set (PPM wins), neither set (never fires) \n " ) ;
2026-05-09 23:34:29 -07:00
std : : printf ( " --export-wsps-json <wsps-base> [out.json] \n " ) ;
std : : printf ( " Export binary .wsps to a human-editable JSON sidecar (defaults to <base>.wsps.json) \n " ) ;
std : : printf ( " --import-wsps-json <json-path> [out-base] \n " ) ;
std : : printf ( " Import a .wsps.json sidecar back into binary .wsps (procFlags accepts int OR pipe-separated label string) \n " ) ;
feat(pipeline): add Wowee Open Weather (.wow) zone schedule
8th open-format addition to the Wowee pipeline. Replaces
WoW's WeatherTypes.dbc / WeatherEffect logic with a single
binary file holding a list of weather states for one zone,
each tagged with intensity bounds, a probability weight,
and duration bounds. The renderer / runtime samples one
entry at a time using weighted-random selection, drives
it for a uniform-random duration in [min, max] sec, then
re-rolls.
• Types: Clear / Rain / Snow / Storm / Sandstorm / Fog /
Blizzard (extensible enum).
• Binary format: magic "WOWA", version 1, name, N entries
each storing (typeId, minIntensity, maxIntensity, weight,
minDurationSec, maxDurationSec).
CLI:
• --info-wow <wow-base> [--json] — inspect a WOW
• --gen-weather-temperate — clear + rain + fog (forest)
• --gen-weather-arctic — snow + blizzard + fog (tundra)
• --gen-weather-desert — clear + sandstorm (dunes)
• --gen-weather-stormy — rain + storm + occasional clear
The 8th open format complementing the rest:
M2 → WOM | WMO → WOB | WMO collision → WOC | ADT → WOT
DBC → JsonDBC | BLP → PNG | Light.dbc → WOL | WeatherTypes.dbc → WOW
Smoke-tested all 4 presets + JSON output. Each preset reads
back identically with the expected entry count and weight
distribution.
2026-05-09 14:10:13 -07:00
std : : printf ( " --gen-weather-temperate <wow-base> [zoneName] \n " ) ;
std : : printf ( " Emit .wow weather schedule: clear-dominant + occasional rain + fog (forest / grassland) \n " ) ;
std : : printf ( " --gen-weather-arctic <wow-base> [zoneName] \n " ) ;
std : : printf ( " Emit .wow weather schedule: snow-dominant + blizzard + fog (tundra / glacier) \n " ) ;
std : : printf ( " --gen-weather-desert <wow-base> [zoneName] \n " ) ;
std : : printf ( " Emit .wow weather schedule: clear-dominant + sandstorm (dunes / wasteland) \n " ) ;
std : : printf ( " --gen-weather-stormy <wow-base> [zoneName] \n " ) ;
std : : printf ( " Emit .wow weather schedule: heavy rain + storm + occasional clear (coastal / monsoon) \n " ) ;
2026-05-09 14:21:55 -07:00
std : : printf ( " --gen-zone-atmosphere <zoneDir> [--name <zoneName>] [--preset default|arctic|desert|stormy|cave] \n " ) ;
std : : printf ( " Convenience: drop both atmosphere.wol + atmosphere.wow into <zoneDir> using a paired light/weather preset \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " --info-wot <wot-base> [--json] \n " ) ;
std : : printf ( " Print WOT/WHM terrain metadata (tile, chunks, height range) and exit \n " ) ;
std : : printf ( " --info-extract <dir> [--json] \n " ) ;
std : : printf ( " Walk extracted asset tree and report open-format coverage and exit \n " ) ;
std : : printf ( " --info-extract-tree <dir> \n " ) ;
std : : printf ( " Hierarchical view of an extracted asset tree grouped by top-level dir + format \n " ) ;
std : : printf ( " --info-extract-budget <dir> [--json] \n " ) ;
std : : printf ( " Per-extension byte breakdown of an extract dir (sized largest-first) \n " ) ;
std : : printf ( " --info-png <path> [--json] \n " ) ;
std : : printf ( " Print PNG header (width, height, channels, bit depth) and exit \n " ) ;
std : : printf ( " --info-blp <path> [--json] \n " ) ;
std : : printf ( " Print BLP texture header (format, compression, mips, dimensions) and exit \n " ) ;
std : : printf ( " --info-m2 <path> [--json] \n " ) ;
std : : printf ( " Print proprietary M2 model metadata (verts, bones, anims, particles) \n " ) ;
std : : printf ( " --info-wmo <path> [--json] \n " ) ;
std : : printf ( " Print proprietary WMO building metadata (groups, portals, doodads) \n " ) ;
std : : printf ( " --info-adt <path> [--json] \n " ) ;
std : : printf ( " Print proprietary ADT terrain metadata (chunks, placements, textures) \n " ) ;
std : : printf ( " --info-jsondbc <path> [--json] \n " ) ;
std : : printf ( " Print JSON DBC sidecar metadata (records, fields, source) and exit \n " ) ;
std : : printf ( " --list-missing-sidecars <dir> [--json] \n " ) ;
std : : printf ( " List proprietary files lacking open-format sidecars (one per line) \n " ) ;
std : : printf ( " --info-zone <dir|json> [--json] \n " ) ;
std : : printf ( " Print zone.json fields (manifest, tiles, audio, flags) and exit \n " ) ;
std : : printf ( " --info-zone-overview <zoneDir> [--json] \n " ) ;
std : : printf ( " One-line compact zone summary (tiles, biome, counts, audio status) \n " ) ;
std : : printf ( " --info-project-overview <projectDir> [--json] \n " ) ;
std : : printf ( " One-line summary per zone in a project (single-page health check) \n " ) ;
std : : printf ( " --copy-project <fromDir> <toDir> \n " ) ;
std : : printf ( " Recursively copy a project tree (every zone subdir + manifests) \n " ) ;
std : : printf ( " --info-creatures <p> [--json] \n " ) ;
std : : printf ( " Print creatures.json summary (counts, behaviors) and exit \n " ) ;
std : : printf ( " --info-creatures-by-faction <p> [--json] \n " ) ;
std : : printf ( " Histogram of creature counts grouped by faction id \n " ) ;
std : : printf ( " --info-creatures-by-level <p> [--json] \n " ) ;
std : : printf ( " Distribution of creature levels (min/max/avg + per-level counts) \n " ) ;
std : : printf ( " --info-objects-by-path <p> [--json] \n " ) ;
std : : printf ( " Histogram of object placements grouped by model path (most-used first) \n " ) ;
std : : printf ( " --info-objects-by-type <p> [--json] \n " ) ;
std : : printf ( " M2 vs WMO breakdown plus scale distribution (min/max/avg) \n " ) ;
std : : printf ( " --info-objects <p> [--json] \n " ) ;
std : : printf ( " Print objects.json summary (counts, types, scale range) and exit \n " ) ;
std : : printf ( " --info-quests <p> [--json] \n " ) ;
std : : printf ( " Print quests.json summary (counts, rewards, chain errors) and exit \n " ) ;
std : : printf ( " --info-quests-by-level <p> [--json] \n " ) ;
std : : printf ( " Distribution of required levels across quests (min/max/avg + bar chart) \n " ) ;
std : : printf ( " --info-quests-by-xp <p> [--json] \n " ) ;
std : : printf ( " Distribution of XP rewards (min/max/avg + per-bucket histogram) \n " ) ;
std : : printf ( " --list-creatures <p> [--json] \n " ) ;
std : : printf ( " List every creature with index, name, position, level (for --remove-creature) \n " ) ;
std : : printf ( " --list-objects <p> [--json] \n " ) ;
std : : printf ( " List every object with index, type, path, position \n " ) ;
std : : printf ( " --list-quests <p> [--json] \n " ) ;
std : : printf ( " List every quest with index, title, giver, XP \n " ) ;
std : : printf ( " --list-quest-objectives <p> <questIdx> [--json] \n " ) ;
std : : printf ( " List every objective on a quest (for --remove-quest-objective) \n " ) ;
std : : printf ( " --list-quest-rewards <p> <questIdx> [--json] \n " ) ;
std : : printf ( " List XP/coin/item rewards on a quest \n " ) ;
std : : printf ( " --info-quest-graph-stats <p> [--json] \n " ) ;
std : : printf ( " Analyze quest chain graph (roots, leaves, depths, cycles, orphans) \n " ) ;
std : : printf ( " --info-creature <p> <idx> [--json] \n " ) ;
std : : printf ( " Print every field for one creature spawn (stats, behavior, AI, flags) \n " ) ;
std : : printf ( " --info-quest <p> <idx> [--json] \n " ) ;
std : : printf ( " Print every field for one quest (objectives + reward + chain in one shot) \n " ) ;
std : : printf ( " --info-object <p> <idx> [--json] \n " ) ;
std : : printf ( " Print every field for one object placement (type, path, transform) \n " ) ;
std : : printf ( " --info-wcp <wcp-path> [--json] \n " ) ;
std : : printf ( " Print WCP archive metadata (name, files) and exit \n " ) ;
std : : printf ( " --info-pack-budget <wcp-path> [--json] \n " ) ;
std : : printf ( " Per-extension byte breakdown of a WCP archive (sized largest-first) \n " ) ;
std : : printf ( " --info-pack-tree <wcp-path> \n " ) ;
std : : printf ( " Render a tree view of a WCP's directory structure with byte sizes \n " ) ;
std : : printf ( " --list-wcp <wcp-path> Print every file inside a WCP archive (sorted by path) and exit \n " ) ;
std : : printf ( " --diff-wcp <a> <b> [--json] \n " ) ;
std : : printf ( " Compare two WCPs file-by-file; exit 0 if identical, 1 otherwise \n " ) ;
std : : printf ( " --diff-zone <a> <b> [--json] \n " ) ;
std : : printf ( " Compare two zone dirs (creatures/objects/quests/manifest); exit 0 if identical \n " ) ;
std : : printf ( " --diff-glb <a> <b> [--json] \n " ) ;
std : : printf ( " Compare two glTF 2.0 binaries structurally; exit 0 if identical \n " ) ;
std : : printf ( " --diff-wom <a-base> <b-base> [--json] \n " ) ;
std : : printf ( " Compare two WOM models (verts, indices, bones, anims, batches, bounds) \n " ) ;
std : : printf ( " --diff-wob <a-base> <b-base> [--json] \n " ) ;
std : : printf ( " Compare two WOB buildings (groups, portals, doodads, totals) \n " ) ;
std : : printf ( " --diff-whm <a-base> <b-base> [--json] \n " ) ;
std : : printf ( " Compare two WHM/WOT terrain pairs (chunks, height range, placements) \n " ) ;
std : : printf ( " --diff-woc <a> <b> [--json] \n " ) ;
std : : printf ( " Compare two WOC collision meshes (triangles, walkable/steep counts, tile) \n " ) ;
std : : printf ( " --diff-jsondbc <a> <b> [--json] \n " ) ;
std : : printf ( " Compare two JSON DBC sidecars (format/source/recordCount/fieldCount) \n " ) ;
std : : printf ( " --diff-extract <a> <b> [--json] \n " ) ;
std : : printf ( " Compare two extracted asset directories (per-extension file count + bytes) \n " ) ;
std : : printf ( " --diff-checksum <a> <b> [--json] \n " ) ;
std : : printf ( " Diff two SHA256SUMS files; report added/removed/changed entries \n " ) ;
std : : printf ( " --pack-wcp <zone> [dst] Pack a zone dir/name into a .wcp archive and exit \n " ) ;
std : : printf ( " --unpack-wcp <wcp> [dst] Extract a WCP archive (default dst=custom_zones/) and exit \n " ) ;
std : : printf ( " --list-commands Print every recognized --flag, one per line, and exit \n " ) ;
2026-05-09 12:25:51 -07:00
std : : printf ( " --list-primitives [--mesh|--texture] [--json] \n " ) ;
std : : printf ( " Filtered list of just procedural primitive flags (--gen-mesh-*, --gen-texture-*) \n " ) ;
2026-05-09 12:51:10 -07:00
std : : printf ( " --list-packs Print every --gen-*-pack composite flag (camp, blacksmith, village, temple…) \n " ) ;
refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).
Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).
main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
std : : printf ( " --info-cli-stats [--json] \n " ) ;
std : : printf ( " Meta-stats on the CLI surface (command count by category prefix) \n " ) ;
std : : printf ( " --info-cli-categories \n " ) ;
std : : printf ( " Group every --flag by verb prefix (gen/info/list/...) for discovery \n " ) ;
std : : printf ( " --info-cli-help <pattern> \n " ) ;
std : : printf ( " Substring-search the help text and print matching command lines \n " ) ;
std : : printf ( " --validate-cli-help [--json] \n " ) ;
std : : printf ( " Self-check: every kArgRequired flag must appear in the help text \n " ) ;
std : : printf ( " --gen-completion <bash|zsh> \n " ) ;
std : : printf ( " Print a shell-completion script for wowee_editor (source it from your rc file) \n " ) ;
std : : printf ( " --version Show version and format info \n \n " ) ;
std : : printf ( " Wowee World Editor v1.0.0 — by Kelsi Davis \n " ) ;
std : : printf ( " Novel open formats: WOT/WHM/WOM/WOB/WOC/WCP + PNG/JSON \n " ) ;
}
} // namespace cli
} // namespace editor
} // namespace wowee