wgt01
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""Generate the tileset palette `twu01palstd.itp` from tiles.py.
|
||||
|
||||
python make_itp.py [out.itp] # default: twu01palstd.itp
|
||||
|
||||
The toolset loads `<set>palstd.itp` when it registers a tileset; without it the
|
||||
set fails to register (blank name in the New Area wizard, "could not create
|
||||
area"). It's a GFF `ITP ` file: MAIN = a list of palette *category* folders, each
|
||||
{ID byte, STRREF (dialog.tlk folder label), LIST of leaves}.
|
||||
|
||||
We emit TWO folders (the verified structure — AGENTS.md §2.3; wut01palstd.itp):
|
||||
* Features (STRREF 63261): one leaf per NON-paint tile, {NAME, RESREF=tile
|
||||
resref}. Each leaf is placeable ONLY because make_set.py backs it with a 1x1
|
||||
[GROUP#] whose Name == this NAME and Tile0 == that tile; the toolset finds the
|
||||
group by the RESREF (its first tile). Paint tiles (tiles.is_paint) are omitted
|
||||
here on purpose — they're brush-laid terrain, not click-placed features.
|
||||
* Terrain (STRREF 8282): the paintable vocabulary — `cobble` and `canal` (each
|
||||
RESREF = terrain name) plus the magic `eraser` leaf (RESREF `eraser`, STRREF
|
||||
63291, no NAME). `raised` is NOT here: it's a height on cobble (Raise/Lower),
|
||||
deferred to the next pass with HasHeightTransition=1 + a cobble-height matrix.
|
||||
Multi-tile groups (folder 63262) would go in a third folder; we have none yet.
|
||||
Built as JSON and converted to GFF with neverwinter.nim's nwn_gff (on PATH).
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import tiles
|
||||
|
||||
STRREF_FEATURES = 63261 # dialog.tlk label for the "Features" palette folder
|
||||
STRREF_TERRAIN = 8282 # dialog.tlk label for the "Terrain" palette folder
|
||||
STRREF_ERASER = 63291 # the magic eraser leaf (no NAME)
|
||||
|
||||
|
||||
def leaf(name, resref):
|
||||
return {"__struct_id": 0,
|
||||
"NAME": {"type": "cexostring", "value": name},
|
||||
"RESREF": {"type": "resref", "value": resref}}
|
||||
|
||||
|
||||
def eraser_leaf():
|
||||
return {"__struct_id": 0,
|
||||
"RESREF": {"type": "resref", "value": "eraser"},
|
||||
"STRREF": {"type": "dword", "value": STRREF_ERASER}}
|
||||
|
||||
|
||||
def category(cid, strref, leaves):
|
||||
return {"__struct_id": 0,
|
||||
"ID": {"type": "byte", "value": cid},
|
||||
"STRREF": {"type": "dword", "value": strref},
|
||||
"LIST": {"type": "list", "value": leaves}}
|
||||
|
||||
|
||||
def build():
|
||||
features = [leaf(tiles.group_name(s), tiles.resref(s))
|
||||
for s in tiles.TILES if not tiles.is_paint(s)]
|
||||
# Paintable terrains = every .set terrain EXCEPT 'raised' (which is a height on
|
||||
# cobble, not a terrain — the Raise/Lower tool, deferred to the next pass).
|
||||
paintable = [t for t in tiles.TERRAINS if t != "raised"] # -> cobble, canal
|
||||
terrain = [leaf(t, t) for t in paintable] + [eraser_leaf()]
|
||||
return {
|
||||
"__data_type": "ITP ",
|
||||
"MAIN": {"type": "list", "value": [
|
||||
category(0, STRREF_FEATURES, features), # ID/STRREF mirror wut01palstd.itp
|
||||
category(2, STRREF_TERRAIN, terrain),
|
||||
]},
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
out = sys.argv[1] if len(sys.argv) > 1 else f"{tiles.PREFIX}palstd.itp"
|
||||
with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as tf:
|
||||
json.dump(build(), tf)
|
||||
js = tf.name
|
||||
try:
|
||||
subprocess.run(["nwn_gff", "-i", js, "-l", "json", "-k", "gff", "-o", out],
|
||||
check=True)
|
||||
finally:
|
||||
os.unlink(js)
|
||||
nfeat = sum(1 for s in tiles.TILES if not tiles.is_paint(s))
|
||||
print(f"wrote {out} ({nfeat} features + paint:cobble,canal + eraser)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user