fix(kit): cap bay count and fill the storey spread; fetch the retail reference

Kit layout, found while starting the retail pass:
- Bays were round(width / 4.96), so 6922 (65.8 m wide) got 13 bays - a window every
  4.96 m across a 37 m block. Capped at MAX_BAYS = 9, widening the module instead.
- Storeys were assumed exactly 310 cm apart, leaving ~1.6 m of bare wall under the
  cornice on a tall building. The spread is now derived from the available height
  (usable / storeys), so the top band lands inside the volume.
  Result: 6922 9x11 (was 13x11), theatre 8x6, 6806 7x3, 6800 4x3, TCL 9x5.

Retail references: fetched Art/reference/retail-neighbours/01-lee-drug-and-neighbor.jpg
(Gb321, CC BY-SA 4.0) - 6800 and its neighbour at street level, confirmed to show
shopfronts and parapets. Commons has nothing for 6822 or 6806-6820, so those two
remain blocked on reference photography; recorded in TODO.

Re-applied the kit, repackaged, screenshots re-rendered and verified 4/4, packaged
QA all PASS.
This commit is contained in:
zwitschi committed 2026-11-08 22:05:08 +01:00
1 parent 743a290ac9
commit bc5da3a8ab
9 files changed
+46 -14

No files matched your search

+18 -2
View File
@@ -123,12 +123,28 @@ def apply_to_actor(actor, kit, materials=None, prefix=None):
f"({width / 100:.1f} x {height / 100:.1f} m)")
return 0
# Bays: the kit module is one window bay (4.96 m). A very wide building gets a
# bay count that keeps the rhythm readable rather than one window per 4.96 m of
# frontage — 6922 is 65.8 m wide, which is 13 bays, giving a window every 4.96 m
# across a 37 m tall block: the rhythm reads as a wall of glass, not a building.
# Above MAX_BAYS the module is widened instead, so the bay count stays legible.
MAX_BAYS = 9
bays = max(1, int(round(width / BAY_CM)))
if bays > MAX_BAYS:
bays = MAX_BAYS
bay_w = width / bays # actual bay width for this building
# Street face: the frontage runs along X, and the street is at smaller Y.
face_y = mn.y
base_z = mn.z
storeys = max(1, int((height - SHOP_FLOOR_CM) // STOREY_CM))
# Storeys never overrun the volume: cap the count so the top band (cornice +
# parapet, 145 cm) always lands inside the building.
storeys = max(1, int((height - SHOP_FLOOR_CM - 145.0) // STOREY_CM) + 1)
top_z = base_z + height
# Windows above the shopfront, spread over the available height rather than
# assumed to be exactly STOREY_CM apart, so a 37 m block does not leave a gap
# of bare wall under the cornice.
usable = max(0.0, (top_z - 145.0) - (base_z + SHOP_FLOOR_CM))
storey_step = (usable / storeys) if storeys else STOREY_CM
def kit_material(name):
if materials is None:
@@ -153,7 +169,7 @@ def apply_to_actor(actor, kit, materials=None, prefix=None):
# upper storeys: window bays
for storey in range(storeys):
if "Kit_WindowBay" in kit:
z = base_z + SHOP_FLOOR_CM + STOREY_CM * storey + 65.0
z = base_z + SHOP_FLOOR_CM + storey_step * storey + 65.0
if _spawn(kit["Kit_WindowBay"], unreal.Vector(cx, face_y, z),
f"{prefix}window_{bay}_{storey}", kit_material("Kit_WindowBay")):
placed += 1