rejoin the Pokemon Tower across the LAVENDER_TOWN / ROUTE_10 seam

The tower's drawing straddles the map boundary -- roof band and top
window courses in Route 10's last rows, the rest in Lavender -- so each
map folded its half upright alone: two half-buildings, Lavender's under
a fabricated yellow cap.

Buildings templates gain `topRows`: drawing rows composited ABOVE the
matched grid, for a drawing no single map holds. The model is built
from the complete 16-row artwork (96px facade under the real 32px
purple band) while placement still matches only the on-map rows; depth
now derives from the matched footprint rather than sprite height,
identical for every whole-drawing template. A `claimOnly` twin template
claims Route 10's roof rows and stamps nothing, so the top half no
longer also stands as its own building. Both templates verified to
place exactly once, world-wide, at the intended coordinates.
This commit is contained in:
DramaticShape
2026-07-27 04:39:27 -04:00
parent cf25f54352
commit 0b8730fbf6
2 changed files with 89 additions and 56 deletions
+35 -5
View File
@@ -98,9 +98,24 @@ local models = {} -- "<tileset>:<index>" -> prebuilt local quads
-- Composite the template out of the atlas and flood the silhouette in from
-- the border. Returns flat arrays indexed y * W + x.
--
-- `topRows`, when a template carries it, is extra drawing rows composited
-- ABOVE the matched grid: rows of the same drawing that are not on the
-- map this template places on. The Pokemon Tower is the case that needs
-- it -- the drawing straddles the LAVENDER_TOWN / ROUTE_10 boundary, its
-- roof band and top window courses standing in the route's last rows, so
-- no single map's grid holds the whole building. The matcher never sees
-- topRows (placement is still by `tiles` alone); they exist so the MODEL
-- is built from the complete drawing and the tower rises to its real
-- height instead of folding as two half-buildings.
local function read(t, data, perRow)
local tiles = t.tiles
local bh, bw = #tiles, #tiles[1]
if t.topRows then
tiles = {}
for _, row in ipairs(t.topRows) do tiles[#tiles + 1] = row end
for _, row in ipairs(t.tiles) do tiles[#tiles + 1] = row end
end
local bh, bw = #tiles, #t.tiles[1]
local W, H = bw * 8, bh * 8
local col, ax, ay = {}, {}, {}
for sy = 0, H - 1 do
@@ -258,7 +273,13 @@ local function measure(sp, t)
shadeTexel[s] = shadeTexel[s] or shadeTexel[BLACK] or 0
end
return { top = top, ytop = ytop, D = H,
-- Depth is the MATCHED footprint, not the sprite height. The two are
-- the same number for every whole-drawing template (the sprite is
-- built from `tiles` alone), but a template with `topRows` has a
-- sprite taller than its footprint -- the tower's 16-row drawing
-- stands on the 8 rows of it that are actually on the map, and D = H
-- would have pushed its body 64px south into the town plaza.
return { top = top, ytop = ytop, D = #t.tiles * 8,
recess = recess, interior = interior, shadeTexel = shadeTexel }
end
@@ -610,9 +631,18 @@ function Buildings.build(S, map, data, perRow)
if not built then
local key = tileset.id .. ":" .. index
if not models[key] then
local sp = read(t, data, perRow)
local pr = measure(sp, t)
models[key] = emit(model(sp, pr, t), sp, atlasW, atlasH)
if t.claimOnly then
-- claim the cells, stamp nothing: the drawing here is
-- the off-map half of a building another map models in
-- full (the tower's roof rows on ROUTE_10 -- Lavender's
-- placement composites them via topRows). Left to the
-- detector they stood as a second half-building.
models[key] = {}
else
local sp = read(t, data, perRow)
local pr = measure(sp, t)
models[key] = emit(model(sp, pr, t), sp, atlasW, atlasH)
end
end
built = models[key]
end