Convert any WOM mesh into a WOC collision file via
WoweeCollisionBuilder::addMesh, with optional --weld <eps>
that merges shared positions into a single canonical index
before baking. The weld pass is what makes per-face-shaded
procedural primitives produce a properly indexed collision
mesh — adjacent faces that previously authored 4 unique
verts per face now share 1 corner across all incident
faces, so raycasts can traverse edges naturally.
Also accepts --steep <deg> to control the walkable/steep
classification threshold (default 50° from horizontal,
matching the terrain pipeline).
Smoke-tested end-to-end:
• firepit: 240 verts → WOC with 120 tris (20 walkable
floor, 20 steep stone walls, rest neutral)
• tent_solid: 18 verts welds to 6, produces 8-tri WOC
• canopy: 216 → 56 weld, 108 tris, 30° steep cut
Pairs naturally with --info-mesh-stats --weld for
collision-quality QA before baking.
56th procedural mesh primitive. Builds a rectangular awning
on 4 corner posts with a flat overhead panel and optional
drape lips hanging down from each edge:
• 4 corner posts inset by postR so their outer faces line
up flush with the panel edges above
• flat panel slab spanning the full footprint, sitting on
top of the posts
• optional drape lips on all four panel edges (set drape=0
for a clean flat-top canopy with no hanging fabric)
All axis-aligned boxes; the no-drape variant is fully
watertight (verified via --info-mesh-stats --weld). Useful
for market-square stalls, vendor stations, alchemist booths,
caravan rest stops, and tournament viewing platforms.
Add --info-wob-stats reporting per-group + aggregate
triangle counts, surface area, edge analysis, and watertight
check for WOB buildings. Same flag surface as --info-mesh-stats
including --weld <eps> for true topological closure check
on per-face-vertex meshes.
Also fixes a correctness bug in the weld implementation
of --info-mesh-stats: the previous code used a 64-bit hash
of the quantized position as the equality key, which gave
false-positive collisions that incorrectly merged distinct
vertices. A unit cube's 8 corners collapsed to 2 positions
under the buggy hash. Replace with std::map keyed on the
actual quantized (qx, qy, qz) tuple so equality is exact.
Re-verified: cube 8→8 watertight YES; firepit 240→80
watertight YES (was wrongly reporting 56 unique with 48
non-manifold edges); tent_solid 18→6 watertight YES;
tent_fixed 21→9 with 5 boundary edges at the door perimeter
(correct — door is intentionally open).
50th procedural texture: smooth cosine ridges that lerp
between bgHex (trough) and hiHex (crest) over a configurable
period. Direction defaults to vertical ridges (wave varies
along X) — the standard corrugated-sheet-metal-roof look —
with optional horizontal mode for siding panels and pipe
texturing.
Useful for sheet-metal roofing, corrugated-iron walls,
sci-fi paneling, and any "ridged plate" surface where the
existing flat --gen-texture-metal would read as too uniform.
Default 16px period at 256x256 reads cleanly with about 16
ridges across the tile.
Procedural primitives use per-face vertex layouts so flat
shading works (each box face gets its own 4 corners with a
unique normal). That makes them read as "not watertight" at
the index level even when the geometry is visually closed.
The new --weld <eps> flag quantizes vertex positions onto a
1/eps grid, hashes each cell, and remaps every duplicate to
the canonical (lowest-index) representative before edge
analysis. Edges that cross weld boundaries are then unified
and the manifold check measures topological closure of the
underlying surface.
Validates the full plumbing: tent_solid welds 18 verts → 6
positions and reports YES watertight; tent (with door) welds
21 → 9 and reports the 5-edge door seam as open boundary;
firepit welds 240 → 56 with 0 boundary but 48 non-manifold
edges — the 4-stone corners where adjacent ring stones share
a position, making the surface branchy.
55th procedural mesh primitive. Builds the classic 3-2-1
firewood pyramid:
• 3 cylindrical logs along the bottom row, sitting on
the ground at radii apart
• 2 logs nestled in the gaps of the bottom row
• 1 log crowning the pile
Vertical step uses cos(30°) = sqrt(3)/2 so adjacent logs
touch tangentially, giving the close-packed look of a real
chopped-wood stack. Logs lie horizontally along the Z axis
with closed end caps; sides parameter controls cross-
section smoothness (default 12, range 6..64).
Pairs naturally with --gen-mesh-firepit and --gen-mesh-tent
for outdoor camp / homestead / lumberyard set dressing.
The +X gable's door-fan was wrong: it emitted 5 triangles
including {b, c, br} which spanned across the door cutout
area, and left bl unreferenced. --info-mesh-stats caught
both — surface area was over-reported by 0.10 m^2 and one
triangle was degenerate.
Replace with the correct 4-triangle fan from R1 around the
six-vertex polygon B → bl → dt → br → C → R1 (the original
gable triangle minus the bl-br-dt door notch). All six
vertices are now referenced, no triangle covers the door
area, and surface area matches the visible canvas.
49th procedural texture: horizontal plank-floor pattern.
Each plank gets:
• a hash-derived per-plank brightness offset (-24..+24)
so adjacent boards read as separate pieces of wood
rather than one long stripe
• a 1px horizontal seam at its bottom edge
• a 1px vertical end-seam at a hash-jittered x position,
staggering plank ends across rows
• optional darker grain streaks at evenly-spaced columns
(jittered per plank so the pattern doesn't grid-align)
Useful for inn/tavern floors, ship deck planking, bridge
surfaces, market-stall counters, and any wood-floor surface
where the existing single-grain --gen-texture-wood would
read as one giant board.
Default 16px plank height with 5 grain streaks gives a
recognizable floor at 256x256 without aliasing.
Reports total surface area, per-triangle area histogram
(min/max/mean/median), edge analysis (boundary / manifold /
non-manifold counts), watertight check, and degenerate
triangle count for a single WOM.
Watertightness here is the topological notion: every edge
must be shared by exactly 2 triangles via shared vertex
indices. This is what collision bakes and physics queries
actually need — visually-closed primitives whose adjacent
faces don't weld vertices will (correctly) report as
non-watertight.
Already caught a real defect in handleTent's door-fan
triangulation: the fan covers the door cutout area with
a stray triangle and leaves a vertex unreferenced.
Edge analysis is gated by triCount <= 2M to keep the
unordered_map bounded for huge baked terrain meshes.
54th procedural mesh primitive. Builds a recognizable
campfire setup from axis-aligned boxes only:
• ring of N stone cubes evenly placed at radius ringR
around the firepit center, sitting on the ground
• two crossed log boxes at the center (one along X,
one along Z, slightly raised) — the unmistakable
visual cue separating a firepit from a generic
decorative stone ring
Pairs naturally with --gen-mesh-tent for outdoor camp
set dressing (Horde encampments, Defias hideouts, scout
overlooks). Default 0.5-radius ring with 8 stones reads
cleanly at 1:1 player scale.
Mirror the kMeshTable pattern from cli_gen_mesh.cpp: replace
the 48-row handcoded if/strcmp chain in handleGenTexture
with a static TextureEntry table that the dispatcher walks
linearly. minNextArgs preserves the per-flag arg-count guards
(noise needs 1, gradient needs 3, stained-glass needs 5)
so missing-arg behavior is byte-identical to the old chain.
Each new texture primitive now lands as a one-line table
append instead of another paste-fest at the bottom of the
dispatcher. Saves ~80 lines.
48th procedural texture: brick-offset ring outlines. Even
and odd rows are shifted by half a cell width so each ring
interlocks visually with its neighbors above and below —
the classic chainmail-armor pattern. Each pixel is tested
against the nearest ring center; if its distance lies
inside [ringR - strokeW/2, ringR + strokeW/2] it's
painted as the ring color, otherwise background.
Useful for armor textures (mail tunics, helms, gauntlets),
metallic fabric set dressing on guard NPCs, and dungeon
gate/grate textures. Default ring radius 5 on a 14x10
brick spacing reads cleanly at 256x256 without aliasing.
Collapse the 60-entry handcoded if-chain in handleGenMesh
into a static MeshEntry table { flag, minNextArgs, fn } that
the dispatcher walks linearly. Saves ~120 lines and makes
adding a primitive a single-row append instead of a paste-
fest. Also drop a dead inner-ring computation block in
handleArchway and an unused barCY local in handleCage that
were producing -Wunused-but-set-variable warnings — full
project now compiles cleanly with no warnings.
53rd procedural mesh primitive. Builds a watertight A-frame
tent:
• two sloped roof panels meeting at a ridge that runs along
the X axis
• two triangular gables sealing the ends
• optional inverted-V door notch carved out of the +X gable
(parameterized by doorH and doorW; either set to 0 disables
the cutout for a solid gable)
• bottom face for collision-bake watertightness
Useful set dressing for Horde encampments, troll camps,
Defias bandit hideouts, scout/quartermaster overlooks, and
generic outdoor quest hubs.
Default footprint 1.6 x 1.0 with 0.9 ridge height and a
0.5 x 0.4 door notch — all dimensions overridable on the CLI.
Collapse main.cpp's hand-written ladder of 28 individual
"if --foo and i+N >= argc, print message, return 1" blocks
into a single loop over kMultiArgRequired (struct of flag,
needed count, synopsis).
main.cpp drops from 246 → 126 lines. Adding a new multi-arg
flag now means appending one row to cli_multi_arg_required.cpp
instead of pasting another six lines into the validation
ladder. Mirrors the kArgRequired pattern that handles
single-arg flags.
47th procedural texture: knit fabric V-stitch — each stitch
occupies a cellW x cellH cell holding the V-shape made by
two diagonal strokes meeting at the apex (cellW/2, 0) and
dropping to the cell's bottom corners. Cells tile contiguously
in both axes giving the iconic chevron-zigzag appearance of
knitted fabric stitches.
Useful for sweater fabric, woolly NPC clothing, blanket
textures, mitten/scarf set dressing, dwarven knitwork.
Defaults to 16x12 cells with 2-px stroke width.
Adds cli_dispatch.{hpp,cpp} containing a static table of every
extracted handler family's dispatch function. The table-walker
tryDispatchAll() iterates the table once per argv token, calling
each handler in turn. handleConvertSingle stays as a special-
case call in main.cpp because it threads dataPath through.
main.cpp shrinks from 486 to 236 lines (-250). Adding a new
handler module now requires touching only cli_dispatch.cpp's
include list + table — no main.cpp edits, no growing
if-else chain. The 60+ #include lines for individual cli_*
modules collapse to one #include for cli_dispatch.hpp.
58th procedural mesh: 5-box double archway — 3 vertical posts
(left / shared center / right) plus 2 horizontal lintels each
spanning one opening. Pairs with the existing single
--gen-mesh-archway for plaza approaches, double-door tomb
fronts, formal garden entrances, paired temple entries.
Defaults to 1.40m × 2 openings with 2.40m opening height
(~3.16m total width × 2.60m height including lintels).
Splits the 138-line static-local kArgRequired array (the list
of flags requiring positional args) into a new
cli_arg_required.{hpp,cpp} module with extern linkage. Then
moves the three meta handlers that depended on it out of
main.cpp into cli_introspect.cpp:
- --validate-cli-help (uses the array for self-check)
- --version / -v (3-line printf)
- --help / -h (1-line passthrough)
main.cpp shrinks by 191 lines (677 to 486). Both the early
missing-argument detector in main() and --validate-cli-help
in cli_introspect.cpp now share one source of truth for the
arg-required list.
46th procedural texture: zebra-print stripes — base
horizontal stripes with a sinusoidal y-shift in x so they
undulate organically rather than aligning to the row grid.
Two-color (bg + stripe) for the iconic black-on-white animal-
print effect. Each pixel computes y + amplitude*sin(2π*x/wavelength)
then mods by the stripe period.
Useful for animal-print fabric, savanna grass mats, tribal
clothing, fur tiles. Defaults to 24-px period with 8-px
amplitude on an 80-px wavelength wave.
Moves three per-zone visual / report exporters (--export-png,
--export-zone-deps-md, --export-zone-spawn-png) out of
main.cpp into a new cli_zone_export.{hpp,cpp} module.
- export-png renders heightmap + normal-map + zone-map PNG
triplet for terrain previews
- export-zone-deps-md emits a GitHub-renderable model
dependency table (PR-friendly counterpart to --list-zone-deps)
- export-zone-spawn-png plots top-down spawn distribution PNG
bound to the zone's tile range
main.cpp shrinks by 267 lines (944 to 677) and crosses
below 700 lines on the way down. The previous --info-tilemap
dump used a 64x64 grid; this set complements it with content-
relative views.
57th procedural mesh: 7-box brazier — square base plate,
narrow vertical stem, wider bowl on top of the stem, and 3
flame boxes of varying heights rising from the bowl. The
flame layout is a triangle (tallest center, two shorter on
either side) so the silhouette reads as fire rather than a
uniform block.
Useful for dungeons, temples, watchtowers, throne rooms,
goblin camps — anywhere a fantasy world needs visible light
sources. Defaults to 0.55m bowl on a 0.80m stem (~1.28m
total height).
Moves three project-level handlers (--copy-project,
--zone-summary, --bench-bake-project) out of main.cpp into a
new cli_project_actions.{hpp,cpp} module. None of these fit
the more-specific modules: copy-project does recursive
project-tree duplication, zone-summary collapses validate +
content rollup into one CI-friendly command, bench-bake-project
times per-zone WHM/WOT load to track perf regressions.
main.cpp shrinks by 243 lines (1,187 to 944). Both --json
output modes preserved for CI pipelines.
45th procedural texture: leopard print spots done as the
union of 4 small overlapping sub-circles per spot. The
sub-circle offsets are jittered per-spot so each spot has
an irregular non-circular silhouette without authoring per-
spot polygons. Two-color (bg + spot) for the classic
leopard look.
Useful for animal-print fabric, fur tiles, druidic robes,
shamanic hide drums, hunter armor textures. Defaults to 60
spots of ~8-px radius across 256×256.
Adds --info-mesh-storage-budget and --info-project-models-total
to the existing cli_mesh_info module so all 5 mesh-aggregate
info handlers live together. The first computes per-category
byte breakdowns for a single WOM (positions / normals / UVs /
indices / bones / animations); the second walks every zone in
a project for an aggregate WOM/WOB rollup with per-zone rows.
main.cpp shrinks by 250 lines (1,437 to 1,187). All five
handlers preserve --json output for capacity-planning pipelines.
56th procedural mesh: stepped pyramid speaker stand —
configurable number of steps (2..8) tapering from base to top
with equal step heights for visual rhythm, plus a small
lectern box positioned at the back of the top platform so a
speaker has room in front. Top platform is half the base
footprint, with each step shrinking by an equal increment.
Useful for throne rooms, ceremonial dais, NPC speaker
positions, monument bases, judgment platforms. Defaults to
1.60m base × 3 steps with a 0.30m lectern (~0.96m total).
Moves three derived-data maintenance handlers (--fix-zone,
--regen-collision, --build-woc) out of main.cpp into a new
cli_zone_data.{hpp,cpp} module. Distinct from cli_repair
(which fixes manifest-vs-disk drift): these rebuild derived
terrain data and clean up JSON files via load+save:
- fix-zone re-parses + re-saves every JSON sidecar to apply
load-time scrubs and save-time caps
- regen-collision rebuilds WOC for every WHM/WOT in a zone
- build-woc handles single-tile WOC generation
main.cpp shrinks by 104 lines (1,541 to 1,437).
44th procedural texture: scattered angular runes drawn as
3-5 random stroke segments per glyph. Each stroke uses one
of 8 cardinal/diagonal angles (0/45/90/135/...°) so the
strokes read as deliberate runic carvings rather than random
scribbles. Layout is a sparse grid with per-slot jitter and
~5% empty slots so the result looks hand-carved rather than
mechanical.
Useful for ancient ruins, magical zones, dwarven walls,
necromancer altars, druidic shrines. Defaults to a 64-px
grid spacing yielding ~15 runes in a 256×256 image.
Moves three mesh-aggregate info handlers (--info-zone-models-total,
--list-zone-meshes-detail, --info-mesh) out of main.cpp into a
new cli_mesh_info.{hpp,cpp} module. The first aggregates
WOM/WOB stats across a zone; the second tabulates per-mesh
metrics sorted by triangle count; the third dumps single-WOM
detail (bounds, version, batches, bones, animations, textures).
main.cpp shrinks by 285 lines (1,826 to 1,541). All three
preserve --json output for capacity-planning pipelines.
55th procedural mesh: 6-box garden sundial — square base
plate at floor, central vertical gnomon slab spanning the
diameter (long axis along Z, the blade that casts a shadow),
and 4 small hour-marker nubs at the cardinal points (N/S/E/W)
around the rim.
Useful for monastery courtyards, mage tower observatories,
druidic stone circles, manor gardens — anywhere a fantasy
world wants visible time-keeping. Defaults to 0.80m square
base with 0.35m gnomon (~0.41m total height).
Moves the two basic texture-helper handlers (--gen-texture,
--add-texture-to-zone) out of main.cpp into a new
cli_texture_helpers.{hpp,cpp} module. The first synthesizes
solid hex / checker / grid PNG placeholders; the second
imports an existing PNG into a zone with optional rename and
idempotent re-run support (skip if bytes already match).
Both complement the procedural pattern generators in
cli_gen_texture (which handles the 43 named patterns).
main.cpp shrinks by 196 lines (2,022 to 1,826) and finally
drops below 2K lines.
Moves five self-discovery handlers (--list-commands,
--info-cli-stats, --info-cli-categories, --info-cli-help,
--gen-completion) out of main.cpp into a new
cli_introspect.{hpp,cpp} module. All five auto-discover
commands by parsing printUsage's stdout via tmpfile capture,
so the surface stays self-describing as new flags are added.
Useful for shell completion scripts that re-exec the binary
at completion time, IDE plugins, and 'is there a flag for X?'
search workflows. main.cpp shrinks by 276 lines (2,298 to
2,022). --validate-cli-help stays inline because it needs
direct access to the static-local kArgRequired array.
54th procedural mesh: 5-box cruciform farm pest deterrent —
vertical body post, horizontal cross arm, head box on top of
the body, brimmed hat box that's wider than the head, and a
narrower-but-taller crown box on top of the hat brim. The
cross silhouette + brimmed-hat read as a scarecrow without
needing rotated geometry.
Useful for crop fields, abandoned villages, harvest set
dressing, ritual circles, fields after a battle. Defaults
to 1.80m body × 1.40m arm span (~2.18m total height).
Moves the four cross-reference / content sanity-check
handlers (--check-zone-refs, --check-zone-content,
--check-project-content, --check-project-refs) out of
main.cpp into a new cli_check.{hpp,cpp} module. Each goes
deeper than --validate (which only checks open-format file
presence) — verifying that quest NPC IDs resolve to
creatures.json entries, model paths resolve to on-disk files,
spawn positions sit inside the zone's tile bounds, etc.
main.cpp shrinks by 509 lines (2,807 to 2,298). All four
preserve --json output for CI pipelines.
Moves the two batch-runner handlers (--for-each-zone,
--for-each-tile) out of main.cpp into a new
cli_for_each.{hpp,cpp} module. Both substitute `{}` with the
iterated path (find -exec convention) and shell-escape every
token before passing to std::system. Exit code is the failure
count, capped at 255 so the shell can still see it.
main.cpp shrinks by 157 lines (2,964 to 2,807).
53rd procedural mesh: 6-box rooftop wind indicator — base
plate, tall vertical post, perpendicular N-S and E-W cross
arms (cardinal direction markers), a long horizontal arrow
on top of the cross, and a small tail box at the back end of
the arrow that visually balances the head and gives the arrow
its directional read.
Useful for farm rooftops, chapel spires, town halls,
lighthouse caps, manor turrets — anywhere a fantasy world
wants visible wind direction. Defaults to a 1.50m post with
0.40m cross arms and a 0.55m-half-length arrow (~1.67m total).
Moves the three asset-dependency analysis handlers
(--list-zone-deps, --list-project-orphans,
--remove-project-orphans) out of main.cpp into a new
cli_deps.{hpp,cpp} module. All three surface the relationship
between content references (objects.json + WOB doodad lists)
and on-disk model files: list-deps enumerates what a zone
needs, list-orphans flips that into 'what's on disk but
unreferenced', and remove-orphans deletes the resulting set
(with --dry-run for safe previews).
main.cpp shrinks by 355 lines (3,319 to 2,964) and finally
drops below 3K. The shared 'normalize basename' rule for
matching path references stays duplicated between the list
and remove handlers — a deliberate tradeoff, with comments
flagging the sync requirement.
Moves the project-wide ADT-grid visualization handler
(--info-tilemap) out of main.cpp into a new
cli_tilemap.{hpp,cpp} module. Renders the WoW 64x64 tile
grid showing which tiles are claimed by which zones, with
collision detection (multiple zones claiming the same tile)
and per-zone glyph legend. Empty rows are skipped so the
output stays bounded for projects in one map corner.
main.cpp shrinks by 114 lines (3,433 to 3,319). --json
output mode preserved for CI pipelines.
52nd procedural mesh: woven straw beehive (skep) — 4 stacked
tiers of decreasing width approximating a dome (100% / 90% /
70% / 40% of base width), an optional foundation plate
underneath, and a small entrance notch box on the +Z face
that reads as a cutout rather than texture detail.
Useful for druidic groves, beekeeper farms, hunter camps,
peasant cottages — anywhere a fantasy world wants honey
production. Defaults to 0.70m base × 0.85m tall with a
small 0.05m foundation plate.
Moves the two zone discovery / aggregation handlers
(--list-zones, --zone-stats) out of main.cpp into a new
cli_zone_list.{hpp,cpp} module. The first quickly enumerates
zones across the standard locations (custom_zones, output);
the second walks a project dir computing tile / creature /
quest / per-format byte totals with a per-zone breakdown
table — useful for content-pack release notes and capacity
planning.
main.cpp shrinks by 191 lines (3,624 to 3,433). Both --json
output modes preserved.
43rd procedural texture: organic crack network done via
recursive random walks from N seed nuclei. Each seed spawns
a crack that walks in a random direction for some length,
then with 60% chance branches into one or two more cracks
of half-remaining length. Most cracks die out after a step
or two, a few branch into longer networks — the bias matches
real-world fissure formation.
Useful for cracked mud, dry earth, broken glass, weathered
stone, dragon skin overlays, ice-shard effects. Defaults
to 12 seeds at 40-px max length. Iterative DFS instead of
true recursion so deep branching chains never blow the
stack.
Moves the two Makefile-generation handlers (--gen-makefile,
--gen-project-makefile) out of main.cpp into a new
cli_makefile.{hpp,cpp} module. Both emit GNU make recipes
that rebuild every derived output (.glb / .obj / .stl / .html
/ .csv / .md) from sources via wowee_editor flags, with proper
dependency tracking so make can skip already-up-to-date
outputs. Designers can `make -j$(nproc)` to rebuild all zones
in parallel after a content edit.
main.cpp shrinks by 167 lines (3,791 to 3,624).
51st procedural mesh: 5-box wooden gate — 2 vertical posts on
either side and 3 horizontal cross rails (top, middle, bottom)
spanning the opening. The gate sits flat in the X-Y plane
(rails along X, posts along Y) so it can hang in a wall slot
or fence gap without needing rotation.
Useful for fenced fields, manor entrances, pen openings,
courtyard barriers, dungeon archway closures. Defaults to a
1.80m opening with 1.30m-tall posts. Pairs with
--gen-mesh-fence for complete enclosures, exporting through
the open-format ecosystem (WOM -> OBJ / GLB / STL) so designers
can preview the gate-to-fence joinery in any external tool.
Moves the two manifest-drift fix handlers (--repair-zone,
--repair-project) out of main.cpp into a new cli_repair.{hpp,cpp}
module. Both auto-fix the common manifest-vs-disk
inconsistencies that accumulate when zones are hand-edited or
partially copied — adding orphan WHM tiles to the manifest,
syncing the hasCreatures flag with the actual creatures.json
content, and warning (not removing) for tiles in the manifest
without backing files. Both honor --dry-run for safe previews.
main.cpp shrinks by 155 lines (3,946 to 3,791).
Moves the two cleanup-pass handlers (--strip-zone,
--strip-project) out of main.cpp into a new
cli_strip.{hpp,cpp} module. Both remove derived outputs
(.glb / .obj / .stl / .html / .dot / .csv / .png /
ZONE.md / DEPS.md) leaving only source files. Useful before
--pack-wcp so archives don't carry redundant exports, and
before committing to git so derived blobs don't bloat
history. Both honor --dry-run for safe previews.
main.cpp shrinks by 164 lines (4,110 to 3,946).
Milestone: 50th procedural mesh primitive. 7-box witch's
cauldron — 4 small corner legs at the floor, then three
stacked tiers approximating the curved silhouette of a
cast-iron pot: narrow bottom (60% of rim width), wider mid
(90%), and a still-wider thin rim at the top (100%).
Without rotated faces this stacked-tier approximation is
the cleanest cast-iron-pot read available.
Pairs with --gen-mesh-shrine / --gen-mesh-totem for ritual
and alchemy set dressing — witch huts, druid camps, dungeon
laboratories. Defaults to 0.80 rim width × 0.70 body height
(0.80m total with legs).
Moves the four zone-level lifecycle handlers (--copy-zone,
--rename-zone, --remove-zone, --clear-zone-content) out of
main.cpp into a new cli_zone_mgmt.{hpp,cpp} module. All slug-
aware: copy + rename keep file names and manifest mapName in
sync so the result is self-consistent; clear-content empties
the per-feature JSONs without touching terrain.
main.cpp shrinks by 321 lines (4,431 to 4,110).
42nd procedural texture: hexagonal cell tiling produced by
Voronoi over a triangular seed lattice — alternating-row hex
seeds at horizontal step sqrt(3)*s and vertical step 1.5*s
naturally produce perfect hexagonal Voronoi cells without
needing the full pointy-top hex-tile math.
Border pixels are detected by ratio of second-nearest /
nearest seed distances (1.04x threshold) so border thickness
scales naturally with hex size and stays a couple of pixels
across the whole image. Useful for beehives, dragon scales,
sci-fi panels, magical wards, mosaic tile floors. Defaults
to 16-px hex side.
Moves the three per-tile zone-manifest handlers (--add-tile,
--remove-tile, --list-tiles) out of main.cpp into a new
cli_tiles.{hpp,cpp} module. Zones can span multiple ADT tiles;
these manage that list — add creates a fresh blank WHM/WOT
pair at the new tile, remove drops the entry + deletes
WHM/WOT/WOC files, list prints the manifest with file-presence
flags.
main.cpp shrinks by 185 lines (4,616 to 4,431).
49th procedural mesh: 5-box backless stool — flat square seat
on 4 short legs at the corners. Smaller-footprint counterpart
to --gen-mesh-bench, pairs with --gen-mesh-table for taverns,
workshops, NPC market stalls, dwarven taprooms.
Defaults to 0.36m square seat at 0.49m total height — typical
3-legged-bar-stool proportions. Customizable per dimension so
the same primitive covers child stools, milking stools, and
tall workshop stools.