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).
Closes the WCRT open-format loop with --export-wcrt-json /
--import-wcrt-json, mirroring the WOL/WOW/WOMX/WSND/WSPN/
WIT/WLOT JSON pairs. All 8 binary formats added since WOL
now have full JSON round-trip authoring.
Each creature template round-trips all 22 scalar fields.
Three enum-typed fields emit dual int + name forms so a
hand-author can use either:
• typeId (humanoid / beast / dragon / ...)
• familyId (wolf / cat / bear / ... — for beasts)
• npcFlags (vendor / quest / trainer / innkeeper / ...)
• aiFlags (passive / aggressive / flee / call-help / no-leash)
Both flag bitsets emit string-array forms so a hand-author
can write ["vendor", "innkeeper", "repair"] instead of
having to remember that those bits combine to 0x91.
Verified byte-identical round-trip on the merchants preset
(3 NPCs covering innkeeper / smith / alchemist with mixed
flag combinations). Adds 2 flags (502 documented total now).
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).
Closes the WIT open-format loop with --export-wit-json /
--import-wit-json, mirroring the WOL/WOW/WOMX/WSND/WSPN
JSON pairs. All 6 binary formats added since WOL now have
full JSON round-trip authoring.
Each entry round-trips all 18 scalar fields plus the
variable-length stats array. Three enum-typed fields emit
dual int + name forms so a hand-author can use either:
• quality (poor..heirloom)
• itemClass (consumable / weapon / armor / quest / ...)
• inventoryType (head, chest, weapon-1h, ...)
Stats round-trip with both type int + typeName string so
"strength: 5" reads more naturally than "type=4, value=5"
in hand-edit JSON.
Verified byte-identical round-trip on the makeWeapons
preset (5 items spanning common -> legendary, both 1H and
2H slots, full damage / speed / stat coverage). Adds 2
flags (488 documented total now).
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.
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.
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).
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.
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.
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.
90th procedural mesh: a wider-than-tall closed cylinder
(the mortar bowl) with a thin tall closed cylinder (the
pestle) rising from its center. Bowl reads as carved stone
or wood; pestle reads as a small grinding rod centered in
the rim.
Distinct from existing kitchenware primitives:
• --gen-mesh-cauldron — large + has supporting legs
• --gen-mesh-chalice — 3-tier goblet, no separate utensil
• --gen-mesh-mug — handled drinking cup
• --gen-mesh-bowl — does not exist; this primitive
covers the small-bowl + tool case
Useful for: alchemy lab counters, kitchen / cooking-stove
dressing, herbalist shop interiors, witchcraft NPCs,
quest-giver desks for "grind these herbs" objectives.
124 verts / 112 tris at default 14 sides — two simple
closed cylinders sharing a single batch with shared
texture coords.
83rd procedural texture: ornate damask wallpaper pattern.
Per cell: 4-fold radial petal lobes formed by sin(theta*2)^2,
faded out toward the cell edge, plus a small filled center
dot to anchor the motif visually.
Reads as gilded fabric / palace wallpaper / noble-faction
tapestry — the missing classic-ornament category in the
catalogue (chevron / herringbone / argyle / houndstooth
cover modern geometric patterns; damask covers the older
Western-European decorative arts side).
Useful for: throne-room walls, cathedral interiors, royal
banners, tavern wallpaper, cushion textures, scroll backgrounds,
manuscript decoration, alchemy-shop bottle-label backdrops.
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.
Novel open replacement for Blizzard's WDT (top-level world
definition table). The 9th open format added to the editor.
A WOMX file holds the manifest of which terrain tiles exist
within a world plus a tiny bit of map-level metadata. The
runtime consults it before attempting to load any individual
tile (so missing tiles produce a clean "no data" result
instead of a file-not-found error).
Format:
• magic "WMPX", version 1, little-endian
• mapName + worldType (continent/instance/battleground/arena)
• gridSize 1..128 (typically 64 for continents)
• defaultLightId / defaultWeatherId (atmosphere preset
refs, 0 if none — wires into the WOL/WOW pair)
• packed bitmap, 1 bit per tile, row-major
• A 64x64 manifest is exactly 512 bytes of bitmap
API: WoweeWorldMapLoader::save / load / exists; presets
makeContinent (64x64 full), makeInstance (4x4 full),
makeArena (1x1 full).
CLI added (5 flags, 456 total now):
--gen-world-map <base> [name] (continent)
--gen-world-map-instance <base> [name] (4x4)
--gen-world-map-arena <base> [name] (1x1)
--info-womx <base> [--json]
--validate-womx <base> [--json]
Round-trip verified: continent + instance + arena presets
all save / load / re-validate to byte-identical state with
correct tile counts.
Adds a validator for .wom files mirroring --validate-wol /
--validate-wow. Catches malformed hand-built or import-
corrupted models before they reach the renderer (where bad
data usually crashes or renders blank with no diagnostic).
Hard errors (exit non-zero):
• version not in 1..3
• empty vertex / index list
• index count not a multiple of 3
• triangle indices referencing out-of-range vertices
• boneIndices referencing out-of-range bones
• parentBone referencing out-of-range bones
• inverted AABB (boundMin > boundMax on any axis)
• WOM3 batch.textureIndex out of range
• WOM3 batch range past end of index buffer
• animation has wrong number of bone tracks
Warnings (informational, exit zero):
• boneWeight slots not summing to 0 or 255
• triangles uncovered or double-covered by WOM3 batches
• boundRadius <= 0 (frustum-cull failure)
Adds 451st kArgRequired entry. Smoke test: 0/0/0 errors on
all generated procedural primitives. Both text and --json
output supported, mirroring the other validators.
87th procedural mesh: drinking mug / tankard built from a
closed cylindrical body plus a thin side handle slab. The
handle is positioned on +X with its inner face flush against
the body and centered vertically.
Without rotation the handle is a solid box rather than a
real C-loop, so silhouette reads as a tankard handle rather
than a delicate ring — appropriate for the chunky-prop
aesthetic favored by the existing primitive set. Distinct
from --gen-mesh-chalice (3-tier goblet, no handle) and
--gen-mesh-well-pail (top horizontal handle bar).
Useful for tavern / banquet hall / kitchen dressing, inn
table props, and the eventual --gen-tavern-pack-2 follow-on
(once enough drinking-vessel primitives exist to justify a
dedicated drinkware composite).
86 verts / 68 tris at default 14 sides — a single batch
with shared body + handle texture coords.
82nd procedural texture: solid filled circle of moonHex on
bg, with an optional crescent shadow created by subtracting
a second bg-colored disc offset by `phase` pixels along +X.
Phase reads as the lunar-cycle moment:
• phase = 0 — full moon
• 0 < phase < moonR — gibbous (waning right)
• phase = moonR — half moon
• phase > moonR — crescent (thinner as phase grows)
Useful for night-sky overlays, banner moons (heraldry of
night-themed orders), shrine medallion centers, druid /
priest emblem inserts, lunar-festival decoration, vampire-
zone backdrops.
The simplest centered-disc texture in the catalogue —
pairs naturally with --gen-texture-stars for a complete
night-sky composite.
Mirrors the WOL JSON pair from the previous batch — same
hand-edit authoring loop for the binary .wow weather format:
• --export-wow-json <wow-base> [out.json]
Dumps a .wow to a human-readable JSON sidecar
(defaults to <base>.wow.json). Each entry includes
BOTH the raw typeId (0..6) and the human-friendly
type name ("clear" / "rain" / "snow" / "storm" /
"sandstorm" / "fog" / "blizzard").
• --import-wow-json <json-path> [out-base]
Reads a JSON sidecar and writes back binary .wow.
Accepts either typeId int OR type-name string
(typeId wins if both present). Schema mismatches
fail with a clear message.
Workflow: --gen-weather-* → --export-wow-json → hand-edit
weights / durations / intensities → --import-wow-json →
use in runtime.
Round-trip verified: elwynn.wow → elwynn.wow.json →
elwynn_rt.wow shows byte-identical entries via --info-wow.
Both atmosphere formats now have full JSON authoring support:
WOL: --export-wol-json / --import-wol-json
WOW: --export-wow-json / --import-wow-json
86th procedural mesh primitive. Wooden well-pail / mop-
bucket:
• body — closed cylindrical Y-axis cylinder via
addClosedCylinderY (collision-watertight)
• handle — thin horizontal box floating handleArc above
the rim, spanning at least bodyR×2 wide so its ends
align with the rim's outside edge
Without rotation the handle is a straight bar rather than
a true semicircle, but the bucket-with-handle silhouette
still reads correctly. handleArc parameter controls the
gap between rim and handle (small = handle touches rim;
larger = bucket-being-carried look).
Useful for well scenes (pairs with --gen-mesh-well),
servant-corridor mop scenes, kitchen prep stations,
homestead exteriors, dwarven mine shafts, ocean-ship
swabbing decks. Watertight under weld (verified 102
manifold edges, 0 boundary, 0 non-manifold).
Convenience composite that drops both atmosphere.wol AND
atmosphere.wow into <zoneDir> in a single invocation, using
a paired light/weather preset:
--preset default → makeDefaultDayNight + makeTemperate
--preset arctic → makeNight + makeArctic
--preset desert → makeDefaultDayNight + makeDesert
--preset stormy → makeDefaultDayNight + makeStormy
--preset cave → makeCave + makeTemperate
The preset pairs are curated so the lighting and weather
match the zone climate (arctic uses always-night WOL +
arctic WOW; cave uses dim cave WOL + temperate WOW since
cave weather is rarely visible).
Useful as the canonical "give me a working atmosphere setup
for a fresh zone in one command" entrypoint. Both files
land at <zoneDir>/atmosphere.{wol,wow} where the runtime
loader can find them by convention.
Smoke-tested both default and arctic presets — both produce
files that pass --validate-wol and --validate-wow cleanly.
81st procedural texture: classic 4x4 Bayer ordered-dither
matrix tiled across the image. Each pixel's color comes
from interpolating bg → fg by the matrix value at
(x mod 4, y mod 4) normalized to [0, 1]:
0 8 2 10
12 4 14 6
3 11 1 9
15 7 13 5
cellSize parameter scales the matrix block (default 4 px,
giving a 16-px seamless tile; cellSize=8 gives a 32-px
chunky retro look).
Useful for 8-bit / monochrome-CRT-style backdrops, ordered-
shadow approximations on low-bit palettes, retro arcade
splash overlays, paper-spritesheet rendering, and as a
deterministic alternative to --gen-texture-noise for
binary or near-binary palettes.
Two new commands enable a hand-edit authoring loop for the
binary .wol format:
• --export-wol-json <wol-base> [out.json]
Dumps a .wol to a human-readable JSON sidecar
(defaults to <base>.wol.json). Preserves every
keyframe's time, ambient/directional/fog colors,
directional vector, and fog distances.
• --import-wol-json <json-path> [out-base]
Reads a JSON sidecar and writes back binary .wol.
Validates schema strictly — missing keyframes /
wrong field types fail with a clear error message.
Workflow: --gen-light → --export-wol-json → hand-edit values
in any text editor → --import-wol-json → use in renderer.
Round-trip verified byte-for-byte identical on the existing
sunny.wol fixture: re-import produces the same 4 keyframes
with the same colors, fog distances, and zone name.
85th procedural mesh primitive. Two-cylinder pot-bellied
stove silhouette:
• body — wide round Y-axis cylinder (the stove body that
holds the firebox)
• chimney — thin tall Y-axis cylinder rising from the top
of the body (the smoke vent)
Distinct from --gen-mesh-forge (square stone hearth + hood
+ chimney) and --gen-mesh-chimney (just the rectangular
shaft) — stove is the round-cylinder home / workshop
variant for cottages, smithies, alchemist labs, ranger
huts, dwarven mead-hall corner heaters.
Validates that chimneyR < bodyR so the silhouette always
reads as a wider-bottom-with-thinner-stack shape rather
than a flat tube.
Watertight under weld (verified 192 manifold edges, 0
boundary, 0 non-manifold).
Mirrors --validate-wol but for the .wow weather format. Walks
every entry and reports structural problems:
• unknown weather typeId (above the Blizzard sentinel)
• intensity bounds outside [0, 1] or min > max
• non-positive weight (would zero a row in weighted-random
selection and warp probabilities)
• zero or inverted duration bounds
• non-finite floats
Returns exit code 0 on PASS / 1 on FAIL — CI-friendly. JSON
output via --json for tooling.
All four built-in presets (--gen-weather-temperate / arctic /
desert / stormy) validate clean. The WOW format now has
parity with WOL on the inspect/validate front:
WOL: --info-wol / --info-wol-at / --validate-wol
WOW: --info-wow / --validate-wow
Milestone: kArgRequired now at 440 documented flags.
80th procedural texture: regular grid of dots whose radii
grow with a configurable gradient direction. Three modes:
• v (vertical) — radii grow top-to-bottom
• h (horizontal) — radii grow left-to-right
• r (radial) — radii grow from texture center outward
Mimics the comic-print / newspaper image-reproduction trick
of varying dot size to encode grayscale. Distinct from
--gen-texture-dots (uniform radius across the grid) and
--gen-texture-studs (uniform with derived inner highlight)
— halftone is the gradient-modulated variant.
Useful for retro-comic / newspaper-aesthetic surfaces, vintage-
poster overlays, sci-fi monitor screens (radial mode reads as
CRT vignette), banner gradient detail, dawn/dusk sky overlays.
Default 16-stride / maxR=7 / vertical reads as classic comic
shading at 256x256.
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.
79th procedural texture: solid N-pointed star polygon
centered on the texture. Each pixel computes its polar
(r, θ); the star boundary at any θ alternates between
outer and inner radii using a 2π/N triangular-wave pattern
(0 at sector edges = points, 1 at sector center = valley).
Pixels with r < boundary(θ) are filled with the star color.
Distinct from --gen-texture-starburst (thin rays with bg
between them) and --gen-texture-pinwheel (alternating
solid wedges) — star is a single solid polygon shape.
innerFrac controls the star's "sharpness": near 0 gives
spike-thin star arms; near 1 approximates a circle. Default
0.40 with 5 points gives the classic American-flag star.
The first point is rotated to the top (-Y screen direction)
for canonical orientation.
Useful for medallion centers, shield emblems, religious /
order symbols, magic-circle icons, banner emblems, sheriff-
badge inserts.
Three new single-keyframe WOL presets complement the
existing 4-keyframe day/night cycle from --gen-light:
• --gen-light-cave — dim cool ambient (0.05, 0.05, 0.07)
+ heavy short-range fog (15..80)
for cave / mine interiors
• --gen-light-dungeon — warm torchlit ambient (0.18, 0.14,
0.10) + medium fog (25..200) for
dungeon / crypt interiors
• --gen-light-night — cold blue ambient (0.06, 0.07, 0.12)
+ moonlit directional + far fog
(80..500) for always-night zones
Each preset emits a single-keyframe WOL since enclosed /
fixed-time scenes don't vary with time-of-day. All three
share an emitLightPreset helper so adding more presets
(e.g. --gen-light-tundra, --gen-light-volcanic) is one
line of registration + a maker function.
All four WOL outputs validate clean under --validate-wol
(1 or 4 keyframe(s) valid).
84th procedural mesh primitive. Cylindrical scroll case /
map tube:
• body — thin tall Y-axis cylinder (the case proper)
• cap (optional) — shorter wider cylinder on top, set
capR=0 to skip for a bare stick / rolled-document spine
Distinct from --gen-mesh-chalice (foot + stem + bowl
silhouette) and --gen-mesh-lantern (4-tier base + globe +
neck + cap) — scroll case is the simplest 1-or-2-tier
"tube with lid" prop.
Useful for wizard-tower libraries, archive shelves, mage-
hut detail trim, scribe-table props, scout-courier waist
gear. Validates that capR >= bodyR so the lid always reads
as a proper top closure rather than a degenerate band.
Watertight under weld (verified 168 manifold edges, 0
boundary, 0 non-manifold). Two more clean uses of the
addClosedCylinderY helper.
78th procedural texture: fine cracks following Voronoi cell
boundaries. For each pixel, the algorithm finds the two
nearest jittered cell centers (across 9 surrounding cells);
the difference between (distance to second-nearest) and
(distance to nearest) approximates distance to the cell
boundary line. Pixels under crackW from the boundary get
the crack color; inside cells get the base.
Distinct from --gen-texture-cracked (wide stone cracks at
large scale via random walk) and --gen-texture-frost
(6-spike crystal rosettes from seeded points) — crackle
is the fine-mud / dry-leather / parched-earth variant for
desert ground / aged-document / drought-cracked-mud zones.
Useful for desert-floor zones, aged-leather armor sections,
parched-earth dungeon floors, dragon-burned ground,
mummified-flesh trim, ancient-document parchment.
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.
New open replacement for WoW's Light.dbc / LightParams.dbc /
LightIntBand.dbc / LightFloatBand.dbc stack — a single .wol
file holds a list of time-of-day keyframes for one zone,
each capturing the ambient + directional + fog state at that
moment. The renderer interpolates between adjacent keyframes
by time-of-day.
Binary layout:
magic[4] = "WOLA", version (uint32),
nameLen + name bytes,
keyframeCount + keyframes (each 13 floats + 1 uint32 time)
Per keyframe:
• timeOfDayMin (0..1439 = minutes since midnight)
• ambientColor.rgb, directionalColor.rgb, directionalDir.xyz
• fogColor.rgb, fogStart, fogEnd
CLI:
• --gen-light <wol-base> [zoneName] — emit a starter file
with 4-keyframe day/night cycle (midnight/dawn/noon/dusk)
using reasonable outdoor defaults
• --info-wol <wol-base> [--json] — inspect: zone name +
per-keyframe time-of-day + colors + fog distances
The 7th open-format addition to the Wowee pipeline:
M2 → WOM (model)
WMO → WOB (building)
WMO collision → WOC
ADT → WOT (terrain)
DBC → JsonDBC
BLP → PNG
Light.dbc family → WOL ← new
Smoke-tested round-trip: gen → info shows correct 4 keyframes
at 00:00 / 06:00 / 12:00 / 18:00 with the canonical color
ramps. JSON output for tooling integration.
83rd procedural mesh primitive. Tall standing floor torch:
• post — thin Y-axis cylinder rising from the floor
• bowl — wider shallow Y-axis cylinder (the fire bowl)
sitting on top of the post
Distinct from --gen-mesh-brazier (squat fire-bowl on a
short stem with a wide-base silhouette) — standing-torch
is the tall thin walking-height variant for lining
hallways, ceremonial paths, dungeon entries, palace
entrance walks, watch-station lighting.
Validates that postR < bowlR so the silhouette always
reads as the wider-bowl-on-thinner-pole shape.
Watertight under weld (verified 168 manifold edges, 0
boundary, 0 non-manifold). Two clean addClosedCylinderY
calls — pattern is now well-established for cylindrical
prop primitives.
77th procedural texture: base metal color overlaid with N
short angled line segments brightened against the base.
Each scratch is a hash-derived (cx, cy, length, angle)
segment drawn via integer-stepped line walking from
-len/2 to +len/2 along the angle.
Useful for weathered armor, worn weapon blades (especially
old swords / axes that have seen real use), well-used metal
tools, salvaged hull plating, ancient relic surfaces,
dwarven heirloom finishes.
Default 100 scratches at maxLen=24 gives a moderately worn
look on 256x256; bump scratchCount + maxLen for a heavily
battle-scored aesthetic. Deterministic from seed.
82nd procedural mesh primitive. 3-tier ceremonial chalice:
• foot — wide flat base disc (the goblet's footprint on
the table)
• stem — thin tall connecting column (the holding-grip)
• bowl — wider shallow cup at the top
Validates that stemR < both footR and bowlR so the
silhouette always reads as the classic wide-narrow-wide
goblet shape rather than a degenerate cylinder stack.
Three more primitives that consume the addClosedCylinderY
helper this batch (lantern + chalice from the previous
two commits + this), pattern is now well-established.
Useful for chapel altars, treasure rooms, royal-court
banquet tables, ritual / cult scenes, dwarven mead halls,
fairy-tale storybook props. Watertight under weld
(verified 252 manifold edges, 0 boundary, 0 non-manifold).
Milestone: kArgRequired now reaches 420 documented flags.
76th procedural texture: N alternating colored triangular
wedges radiating from the texture center, each subtending
2π/N radians. Each pixel computes its angle via atan2 and
maps to a sector index; even sectors get color A, odd get
color B.
Distinct from --gen-texture-starburst (thin rays with bg
between them) and --gen-texture-swirl (curved spiral arms)
— pinwheel uses solid-fill alternating wedges with no bg.
Useful for ceiling-decoration medallions, sun-mandala
designs, magical-wheel symbols, wind-rose floor inlays,
heraldic radial backgrounds, druid-circle ground markings.
Default 8 sectors gives the classic pinwheel look; bump
to 12-16 for finer subdivisions, or drop to 2-4 for bold
quadrant patterns.
81st procedural mesh primitive. Hand-held oil lantern via
4 stacked Y-axis cylinders:
• base — short narrow disc (the foot the lantern sits on)
• globe — wider taller cylinder (the glass enclosure
holding the wick)
• neck — narrow constriction above the globe (where the
cap meets the body)
• cap — wider short top (the metal hood that lets vent
smoke escape)
Distinct from --gen-mesh-candle (just wax + saucer) and
--gen-mesh-urn (4-tier pottery shape) — lantern's
wide-narrow-wide tier sequence reads as a glass-enclosed
wick under a metal hood.
Useful for night-watch stations, ranger camps, dwarven
mine tunnels, mausoleum interiors, vigil scenes,
witch-hut shelves. Watertight under weld (verified 336
manifold edges, 0 boundary, 0 non-manifold).
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.
80th procedural mesh primitive. Wax pillar candle:
• saucer (optional) — wider shallow disc base, the drip
catcher that sits on the table
• wax — thin tall pillar standing on the saucer (or
directly on the ground if saucerR=0)
Uses the addClosedCylinderY helper for both pieces — same
two-cylinder pattern as --gen-mesh-bird-bath but with a
much skinnier upper cylinder. The 81-line handler is
mostly arg parsing + validation; geometry is just two
helper calls.
Useful for chapels / shrines, vigil scenes, witch-hut
ritual surfaces, alchemist labs, séance tables, festival-
of-lights ground decoration. Set saucerR=0 for a plain
candle without the saucer (e.g. for stack-them-on-a-cake
contexts).
Watertight under weld (verified — wax + saucer are two
independent closed cylinders).
Milestone: now at 80 procedural mesh primitives.
74th procedural texture: vertical light-beam / sun-ray
gradient. Each pixel's brightness is the product of two
fade factors:
• vertical: 1.0 at the bright end, vFadeFrac at the dim
end (direction flag selects bright-top 'd' or bright-
bottom 'u')
• radial: 1.0 inside the bright core (within beamHalfW of
centerline), then linearly to 0.0 at the texture edge
Two-color blend from bgHex to beamHex by combined brightness.
Useful for dust-mote sunbeams through cathedral windows,
holy radiance auras, crystal glow halos, lighthouse beams,
projector / stage-light columns, ritual-summoning effects.
First procedural texture with a directional flag (u / d) —
flexible orientation for ceiling-down vs floor-up beams.
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).
73rd procedural texture: a grid of X-shape cross stitches.
Each cell holds an X formed by two diagonal strokes from
opposing cell corners through the center. A pixel falls on
a stitch if its in-cell position is within strokeW/2 of
either diagonal axis.
Distinct from --gen-texture-checker (filled squares),
--gen-texture-knit (V-stitch chevron), --gen-texture-lattice
(diagonal trellis). Embroidery is the explicit two-direction
diagonal stitch mark used by counted-thread textile work.
Useful for sampler-cloth detail, folk-art trim, peasant-
clothier border bands, witch-hut wall hangings, hearth-rug
overlays. Default 12-cell / 2-stroke gives a fine X-stitch
look; bump cellSize for chunkier sampler stitches.
78th procedural mesh primitive. Long open-top wooden planter
with a visible soil-fill block:
• 5-piece basin construction (bottom slab + 4 perimeter
walls), same arrangement as --gen-mesh-water-trough
• soil block filling the inner cavity from floor up to
soilTopFrac × height (default 85%), slightly inset from
walls so it visually sits "inside" the wood
Distinct from --gen-mesh-water-trough (square basin without
a soil-fill block) — planter-box is the long elongated
garden variant. Useful for window sills, kitchen herb
gardens, balcony planters, monastery cloister-walk
container plants, market-stall produce display trays.
The 6 non-manifold edges (--info-mesh-stats) are at the
4-wall corners — same expected pattern as water-trough,
where the inner walls share corner positions with each
other.
Milestone: kArgRequired now reaches 411 documented flags.