# Copyright (c) 2026 Dominic Masters # # This software is released under the MIT License. # https://opensource.org/licenses/MIT """ Generates chunk 0_0_0.dcf with a small hill in the centre. Hill layout (tile coordinates, 0-based): y=5: . . . . . . N N . . . . . . . . RAMP_NORTH (south slope) y=6: . . . . . E H H W . . . . . . . Hill top (H), RAMP_EAST/WEST y=7: . . . . . E H H W . . . . . . . y=8: . . . . . . S S . . . . . . . . RAMP_SOUTH (north slope) x=6 x=7 """ import struct, os # Must match src/dusk/rpg/overworld/chunk.h and tile.h CHUNK_WIDTH = 16 CHUNK_HEIGHT = 16 CHUNK_DEPTH = 32 CHUNK_W_F = float(CHUNK_WIDTH) TILE_NULL = 0 TILE_GROUND = 1 TILE_RAMP_NORTH = 2 TILE_RAMP_SOUTH = 3 TILE_RAMP_EAST = 4 TILE_RAMP_WEST = 5 TILE_SIZE = 4 # sizeof(tile_t) = sizeof(int) VERT_SIZE = 20 # sizeof(meshvertex_t): uv[2] + pos[3] floats FILE_VER = 2 # Hill geometry parameters HILL_X = frozenset({6, 7}) HILL_Y = frozenset({6, 7}) HILL_H = 1.0 def tile_idx(cx, cy, cz): return cz * CHUNK_WIDTH * CHUNK_HEIGHT + cy * CHUNK_WIDTH + cx def make_vert(u, v, px, py, pz): return struct.pack('<5f', u, v, px, py, pz) def quad_verts(cx, cy, z_sw, z_se, z_ne, z_nw): """ Build 6 vertices (2 triangles) for a tile quad. Heights at each corner: SW=south-west, SE=south-east, NE=north-east, NW=north-west. UV formula (verified against existing DCF data): u = (cy + within_x) / CHUNK_WIDTH where within_x in {0,1} v = (cx + within_y) / CHUNK_HEIGHT where within_y in {0,1} """ u0 = cy / CHUNK_W_F u1 = (cy + 1) / CHUNK_W_F v0 = cx / CHUNK_W_F v1 = (cx + 1) / CHUNK_W_F x0, x1 = float(cx), float(cx + 1) y0, y1 = float(cy), float(cy + 1) SW = make_vert(u0, v0, x0, y0, float(z_sw)) SE = make_vert(u1, v0, x1, y0, float(z_se)) NE = make_vert(u1, v1, x1, y1, float(z_ne)) NW = make_vert(u0, v1, x0, y1, float(z_nw)) return SW + SE + NE + SW + NE + NW def flat(cx, cy, z): return quad_verts(cx, cy, z, z, z, z) def ramp_north(cx, cy): return quad_verts(cx, cy, 0, 0, HILL_H, HILL_H) def ramp_south(cx, cy): return quad_verts(cx, cy, HILL_H, HILL_H, 0, 0) def ramp_east(cx, cy): return quad_verts(cx, cy, 0, HILL_H, HILL_H, 0) def ramp_west(cx, cy): return quad_verts(cx, cy, HILL_H, 0, 0, HILL_H) def generate(): tiles = [TILE_GROUND] * (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) ramps_n = frozenset((cx, 5) for cx in HILL_X) ramps_s = frozenset((cx, 8) for cx in HILL_X) ramps_e = frozenset((5, cy) for cy in HILL_Y) ramps_w = frozenset((8, cy) for cy in HILL_Y) for cx, cy in ramps_n: tiles[tile_idx(cx, cy, 0)] = TILE_RAMP_NORTH for cx, cy in ramps_s: tiles[tile_idx(cx, cy, 0)] = TILE_RAMP_SOUTH for cx, cy in ramps_e: tiles[tile_idx(cx, cy, 0)] = TILE_RAMP_EAST for cx, cy in ramps_w: tiles[tile_idx(cx, cy, 0)] = TILE_RAMP_WEST for cx in HILL_X: for cy in HILL_Y: tiles[tile_idx(cx, cy, 1)] = TILE_GROUND verts = bytearray() for cx in range(CHUNK_WIDTH): for cy in range(CHUNK_HEIGHT): pos = (cx, cy) if cx in HILL_X and cy in HILL_Y: continue if pos in ramps_n: verts += ramp_north(cx, cy) elif pos in ramps_s: verts += ramp_south(cx, cy) elif pos in ramps_e: verts += ramp_east(cx, cy) elif pos in ramps_w: verts += ramp_west(cx, cy) else: verts += flat(cx, cy, 0) for cx in sorted(HILL_X): for cy in sorted(HILL_Y): verts += flat(cx, cy, HILL_H) vert_count = len(verts) // VERT_SIZE tile_bytes = struct.pack(f'<{len(tiles)}i', *tiles) buf = bytearray() buf += b'DCF\x00' buf += struct.pack('