From e279c46aace7123b0436b682afe9e9408c70625e Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 8 May 2026 10:23:53 +0200 Subject: [PATCH] phase(N.1): add ACME-conformant per-vertex road check Phase N.1 hotfix: scenery near a road still rendered in acdream even with WB-backed generation. Investigation (worktree session 2026-05-08) showed ACME WorldBuilder skips the entire vertex when its road bit is set, before any per-object spawn rolls. ACME line: references/WorldBuilder-ACME-Edition/WorldBuilder/Editors/Landscape/GameScene.cs:1074 if (entry.Road != 0) continue; This check was previously REMOVED in commit 833d167 with a comment claiming retail doesn't have it. The comment was wrong: ACME mirrors retail and keeps the check, and the upstream Chorizite/WorldBuilder we forked omits it (which is why our newly-WB-backed Generate path still produced the bad tree). Adding back to both Generate (legacy) and GenerateViaWb (WB-backed) for parity. This does NOT regress #49: the 9x9 loop expansion that recovered missing edge-vertex scenery is unchanged. Only vertices whose own road bit is set are now skipped -- same as ACME. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.Core/World/SceneryGenerator.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/AcDream.Core/World/SceneryGenerator.cs b/src/AcDream.Core/World/SceneryGenerator.cs index af0be17..8e13667 100644 --- a/src/AcDream.Core/World/SceneryGenerator.cs +++ b/src/AcDream.Core/World/SceneryGenerator.cs @@ -100,10 +100,14 @@ public static class SceneryGenerator uint terrainType = (uint)((raw >> 2) & 0x1F); // bits 2-6 uint sceneType = (uint)((raw >> 11) & 0x1F); // bits 11-15 - // NOTE: retail does NOT skip based on this vertex's road bit. - // The road test happens AFTER displacement via the 4-corner - // polygonal OnRoad check (see below). Removing the - // pre-displacement early-exit restores retail behavior. + // ACME-conformant per-vertex road check (GameScene.cs:1074). + // If this vertex itself is a road vertex, skip ALL scenery + // generation for it. This is retail behavior — the earlier + // claim that retail doesn't have this check (commit 833d167) + // was wrong. The post-displacement OnRoad check below is + // independent and still applies for non-road vertices whose + // displaced position lands on the road ribbon. + if ((raw & 0x3) != 0) continue; if (terrainType >= region.TerrainInfo.TerrainTypes.Count) continue; var sceneTypeList = region.TerrainInfo.TerrainTypes[(int)terrainType].SceneTypes; @@ -300,6 +304,10 @@ public static class SceneryGenerator int i = x * VerticesPerSide + y; ushort raw = block.Terrain[i]; + // ACME-conformant per-vertex road check (GameScene.cs:1074). + // Skip the entire vertex if its road bit is set. + if ((raw & 0x3) != 0) continue; + uint terrainType = (uint)((raw >> 2) & 0x1F); uint sceneType = (uint)((raw >> 11) & 0x1F);