We only ever built the inner region-to-region borders, never a wall
at the island's own outer rim (girdle) — nothing stopped the player
walking off into the (collision-less) pavilion below. Added
_build_edge_barrier(): 6 invisible BoxShape3D walls along the girdle
chords.
Also found the actual bug behind "one POI is outside": a facet's true
outer boundary is a straight hexagon chord, not an arc, so its usable
radius varies with angle — girdle_radius only at the two corners,
dropping to girdle_radius*cos(30°) (~87%) at the facet's own bisector.
Ort6 was placed at exactly the bisector angle with radius 44, just
past the true edge (~43.3 there) despite being "inside" the naive
[table_radius, girdle_radius] range. Moved it to angle 38°/radius 36,
comfortable inside the true boundary at that angle.
Verified headless: pushing the player outward with constant velocity
for 3 simulated seconds pins it at radius 42.64 (never crosses the
~43.3 true edge), settled and on_floor=true throughout. Re-verified
the POI/gate group logic still passes after moving Ort6.
_build_region_borders() previously only bordered the 6 seams between
adjacent outer regions (table corner -> girdle corner). Generalized
_build_ridge() into _build_border_segment(p0, p1), which chains
overlap-guaranteed props along any straight 3D segment, and reused it
for the 6 table edges (table corner -> next table corner) as well —
these separate the center region from each outer region.
Verified headless the same way as the ridges: 43/43 pairs on one
table edge genuinely overlap (worst case -0.13 units). 744 border
props total across all 12 edges now.
_build_ridge() now picks each prop's real-world collision radius
(shape radius * scale, same values as elsewhere in main.tscn) and
places it so its hitbox is guaranteed to overlap the previous one's
(border_overlap=0.8 of the combined radii), correcting the step
iteratively since the facet is sloped so distance isn't purely
radial. Lateral jitter shrunk to 0.05 so it can't itself exceed the
smallest possible combined radius (two forest props) and break the
guarantee.
Verified headless by measuring actual 3D distance between every
consecutive pair of props on one ridge against their combined radii:
83/83 pairs genuinely overlap, worst case still -0.13 units of
overlap (no gap anywhere). 504 border props total across all 6
ridges (was 142 with the old fixed-spacing approach).
The random step jitter in _build_region_borders() was still ±4.0, a
constant left over from before the island rescale — at the new
border_spacing of 3.5 that could produce near-zero or even negative
steps as often as it produced 7.5-unit gaps, independent of position
along the ridge (hence gaps showing up near the center too, just by
bad luck). Jitter is now proportional to border_spacing (±25%), and
spacing itself tightened to 1.5 for a denser wall.
Verified headless: 142 border props total, max gap along one ridge
now ~1.9 units (was up to 7.5), consistent from table edge to girdle.
Island geometry (table/girdle/crown/pavilion radii, border spacing)
scaled down ~5x. The player capsule, camera distance and mountain/
forest scale factors were already correctly tuned to the small world
scale established elsewhere in main.tscn; the island itself was the
outlier (girdle radius 260 vs. a ~0.5-tall player), making border
props and the player look like specks. Shrinking the island was the
smaller change versus rescaling every already-tuned system.
Player now spawns partway out on one outer facet (region) instead of
on the center table, so a walk toward the middle is an actual journey
around/through the outer regions rather than starting there.
Verified headless with a physics simulation on the new sloped spawn
point: player settles and stays on_floor=true, no fall-through.
Player gets its own CapsuleShape3D (was a small CylinderShape3D, never
actually shared with anything — the shared oversized capsule flagged
earlier only affects the 4 mountain props, unrelated to the player).
Real cause of the fall-through: the crown collision is a zero-thickness
trimesh and the player spawned with exactly zero clearance sitting
right on the surface, a classic tunneling setup. Fixed by giving the
trimesh backface_collision (collide from both sides) and spawning the
player with a bit of headroom so it settles onto the floor instead of
starting embedded in it. Verified headless: player now falls from
spawn height to rest exactly on the surface and stays on_floor=true
over a 3s simulated run.
Promote debug/HexDiamondIsland.gd to terrain.gd at project root now
that main.tscn depends on it, and swap it in for the old flat
checkerboard Ground (Player/Camera/POI untouched, table sits at the
same y=0 the old ground surface used).
Add _build_region_borders(): places mountain.glb/mountain2v5.glb/
forest.glb (same models, scale factors and hitbox sizes already used
elsewhere in main.tscn) continuously along the 6 ridges between table
corners and girdle corners, i.e. the shared edges between adjacent
outer regions.