8.3 KiB
wgt01 — Build Status & Notes
Progress log for the Westgate Urban Foundation MVP tileset (prefix twu01).
Spec: KICKOFF.md. How NWN needs things shaped: ../AGENTS.md.
Last updated: 2026-07-04.
What exists — the generator kit (generator/)
One source of truth (tiles.py) feeds four tools; the two NWN emitters need no
Blender, so they're directly testable.
| File | Role | Needs Blender? |
|---|---|---|
tiles.py |
Single source of truth: 40-tile table, 12 materials, the 12×12 test map, and all pure derivations (paint / height / walkmesh quads / .set corner+crosser mapping). PREFIX=twu01. |
no |
build.py |
Builds westgate_urban_foundation_mvp.blend — 40 tile collections (VIS_/WOK_/BLOCK_ + edge custom props), TILE_EDGE_METADATA text block, PREVIEW_tile_library_grid, PREVIEW_12x12_test_district. Editable preview only (quads OK — the exporters triangulate). |
yes (4.0.2) |
make_mdl.py |
Shipping model path. Pure-Python .mdl + .wok + solid-colour .tga: faces triangulated, one trimesh node per texture (each with bitmap+tverts), embedded aabb walkmesh. |
no |
make_itp.py |
twu01palstd.itp (GFF ITP via nwn_gff) — the palette the toolset needs to register the set. |
no (needs nwn_gff) |
make_wok.py |
Pure-Python ASCII .wok emitter (verts+faces+surfacemat+AABB tree); shared aabb_node() reused by make_mdl. |
no |
make_set.py |
twu01.set (INI, CRLF) from the tile grammar; field order/values mirror stock. |
no |
export_mdl.py |
Alt path, not shipped. Neverblender export — flattens multi-material tiles to one unloadable material, so superseded by make_mdl.py. |
yes + addon |
flake.nix exposes these as apps + a dev shell (pinned Blender 4.0.2,
neverwinter-nim, cleanmodels).
Pipeline (commands)
cd wgt01
nix run .#mdl -- mdl/ # .mdl + .wok + .tga (shipping models)
nix run .#set -- twu01.set # twu01.set (CRLF)
nix run .#itp -- twu01palstd.itp # palette (needs nwn_gff)
nix run .#build -- out.blend # optional: editable .blend preview
# nix run .#export -- out.blend mdl/ # alt Neverblender path (flattens materials)
Verified (2026-07-04)
- models (
make_mdl): 40.mdl+ 40.wok+ 12.tga. Each.mdlhasnewmodel,classification TILE, AuroraBase name == resref, onetrimeshper texture withbitmap+tverts(tris), and the embeddedaabbwalkmesh. E.g.st_s→ 3 trimesh nodes (swlk/curb/wcob);cp1→ 1 withbitmap twu01_wcob. Walkmesh surfacemats: 4 (wok_Stone, walkable) / 7 (wok_Nonwalk). Matches the stocktrs02tile structure field-for-field. .itp:twu01palstd.itpround-trips throughnwn_gff—ITPtype, 40 named entries. Names render, but the structure is wrong (flat folder of raw tile resrefs → unplaceable, no Terrain/eraser folder). See Diagnosis below; needs a rebuild to the 3-folder Terrain/Features/Groups shape..set: CRLF, 40 tiles, 3 terrains (cobble/raised/canal), 2 crossers (ramp/canal_edge).Version=V1.0, stock field order (WalkMesh=msb01, lights=1,VisibilityNode=A,ImageMap2Dlast). Corners/heights from each tile's N/E/S/W edge grammar; non-walkable tiles →PathNode=N.- install path:
~/Documents/Neverwinter Nights/developmentis a symlink to~/.local/share/Neverwinter Nights/development(the toolset's real dir); onenix run .#dev-installstages all 94 loose files there.
Why the models were rebuilt (2026-07-04, pass 2)
The Neverblender export produced tiles the toolset couldn't load — no tverts,
no bitmap, a dangling materialname (>16 chars, no .mtr) — and it
flattened each multi-material tile to a single arbitrary material. NWN needs
UV'd, bitmapped, one-texture-per-node trimeshes. Fixed by generating the .mdl
in pure Python (make_mdl.py) with full control, plus the required
twu01palstd.itp. Symptom that surfaced it: blank tileset name + "could not
create area" in the New Area wizard.
Testing in the toolset — no .hak needed
The toolset reads loose files from ~/Documents/Neverwinter Nights/development/
(confirmed present). One command does build → export → .set → stage:
cd wgt01
nix run .#dev-install # -> build/ (inspectable) + installs 40 .mdl/.wok + twu01.set into development/
It replaces only the twu01* files in development/ (leaves everything else
alone) and keeps the intermediate outputs in ./build/ for inspection. Then in
the toolset: create a small area using the twu01 tileset, place tiles, walk-test
pathing/heights. (Packing a .hak with nwn_erf is deferred until the set is
validated.)
First-pass caveats — tune before shipping
- PathNode is a placeholder (
Awalkable /Nnon-walkable) — verify creature routing per tile shape in the toolset; real pathnode letters matter. - Textures are flat solid-colour
.tgas (one per material, KICKOFF "geometry not art"). They double as an in-toolset grammar read-out; swap in real art later without touching geometry. - No minimaps —
ImageMap2Drefs exist in the.setbut the.tgas don't (skipped by decision; Westgate doesn't use them). - Substitutions:
RA_C= straight-ramp geometry;STA= smooth ramp WOK proxy over stepped visual;SW_C/T/X/Eshare the straight-sidewalk visual. MAT_void_blackis defined but currently unpainted (11/12 materials realised).- Corner terrain is a heuristic from edges — hand-tune adjacency in the toolset.
Git
Branch wgt01-tileset-kit (main still unborn — git branch -f main wgt01-tileset-kit to promote). Commits:
60af184— build guide + 40-tile generator kit1284f15— real.mdl/.wokexport via Neverblender
Diagnosis 2026-07-04 — palette names show but nothing paints
Tiles now carry names, but they're not selectable/paintable, and the standard
Terrain section (paint terrains + eraser, Raise/Lower) is missing. Root cause,
confirmed against the working wut01palstd.itp + wut01.set (see ../AGENTS.md
§2.3 for the full model):
- The toolset has two placement systems and our
.itpuses neither correctly. Ground is laid by Paint Terrain (the toolset corner-matches and auto-picks the model); the palette only click-places[GROUP#]-backed prefabs. It never places raw tile models. - Our
.itpis one flat folder of 40 raw tile resrefs, no Terrain folder, noeraser, and the.sethas[GROUPS] Count=0. So: none of the 40 entries is a feature/group → unplaceable; and with no Terrain folder there's no paint/eraser UI.wut01(123 tiles) lists only its 21 groups in the palette and paints the rest as terrain; itsPRIMARY/SECONDARY RULESareCount=0, so rules aren't the blocker.
The real palette (verified): MAIN = 3 category structs {ID, STRREF folder label, LIST}; leaves {NAME, RESREF}. Folder 8282 = Terrain (leaf RESREF =
terrain/crosser name, plus a magic eraser leaf STRREF 63291); 63261 =
Features (1×1, RESREF = first-tile resref); 63262 = Groups (N×M).
Next passes
- Rebuild
make_itp.py+make_set.pyto the real structure (../AGENTS.md §2.3):.itp: a Terrain folder (eachtiles.TERRAINS/CROSSERSby name + aneraserleaf) so terrain-painting + eraser exist; a Features folder with a 1×1 entry per tile we want click-placeable..set: add[GROUP#](1×1 feature) entries backing those Features leaves (Name== palette NAME,Tile0== that tile's index).- Then in the toolset lay ground via Paint Terrain (cobble/raised/canal), not by clicking tiles.
- Walk-test → tune PathNodes, crossers, corner terrains; add a tileset TLK if
we later want localized palette names (local
NAMEstrings suffice for now). - Textures (art pass, separate note). Source assets live in
/home/vicky/Blender/(e.g.textures/,PBR_Procampur/,td_floor/,new_floors/,pd textures main lib/). Map eachMAT_*intiles.TEXTURESto a chosen texture, replacing the flat solid-colour.tgas. Downscale to ≤2k — NWN handles 4k textures poorly (perf/artifacts). Geometry is unaffected; only the.tga/material path changes. - Pack
.hak(nwn_erf) once validated.