fix(pa): square perimeter barrier instead of circular ring edge

The remaining barrier was emitted per ring-road ARC segment, so it inherited
the ring's circle (radius ~412 about PA centre). The parking area is a SQUARE
828x828 apron, so an inscribed circle bulges past the lot at the four corners
and cuts inside it at the four edge midpoints -- it sliced across the parking
area rather than following its perimeter, which is the 'second ring'.

PARingEdge/PARingKerb are gone. Replaced with PAPerimeter: four straight runs
along the apron edge, 40-stud segments, 3.0 tall, with gaps opened where the
ramps cross the boundary so the lot is not sealed.

Verified in live Edit datamodel: PAPerimeter n=78, X -4536..-3711 (span 825),
Z -7882..-7057 (span 825) against the 828-stud slab -- square, matching the
apron. PARingEdge ABSENT, PARingKerb ABSENT.
This commit is contained in:
2026-08-03 00:42:48 -04:00
parent fed0c0ed20
commit 3a74e15f6e
+77 -25
View File
@@ -1222,33 +1222,19 @@ local function buildPA(map: Folder)
local segCF = CFrame.lookAt(segMid, p1, UP) local segCF = CFrame.lookAt(segMid, p1, UP)
deck("PARing", Vector3.new(RING_W, 2, segLen), segCF) deck("PARing", Vector3.new(RING_W, 2, segLen), segCF)
-- Ring edge treatment. -- Ring edge: NO barrier on the circulation road any more.
-- --
-- CHANGE (2026-08-02, user call, third pass): the edge used to be
-- emitted here, per ring-road arc segment, so it inherited the ring's
-- CIRCLE -- radius ~412 about the PA centre. But the parking area is a
-- SQUARE 828 x 828 apron (real Daikoku Futo is 181 m x 174 m, see the
-- layout note above). A circle inscribed in that square bulges past
-- the apron at the four corners and cuts INSIDE it at the four edge
-- midpoints, so the barrier visibly sliced across the lot instead of
-- following its perimeter -- read as a second ring.
-- --
-- CHANGE (2026-08-02, user call, second pass): first pass only swapped -- The perimeter barrier is now built ONCE, after this loop, as four
-- the outer parapet+rail for a low edge and KEPT the inner kerb, which -- straight runs along the apron edge. Nothing is emitted per-arc.
-- left two concentric barriers (69 outer + 64 inner) still ringing the
-- lot -- visibly the same "ring barrier" from the driver's seat. The
-- ask was a single barrier on the edge of the parking area, so the
-- inner edge is now nothing at all: the lot and its circulation road
-- are the same continuous surface, which is how the real PA reads.
-- Only the outer edge gets a barrier, because behind it is a drop off
-- the structure.
local fwd = (p1 - p0).Unit
local outN = (segMid - Vector3.new(c.X, ringY, c.Z)).Unit
local ePos = segMid + outN * (RING_W / 2)
if not nearJunction(ePos, GATE_OUT) then
local eCF = CFrame.lookAt(ePos, ePos + fwd, UP)
local EDGE_H = 3.0
local edge = part({
Name = "PARingEdge",
Size = Vector3.new(1.6, EDGE_H, segLen + 1),
CFrame = eCF * CFrame.new(0, 1 + EDGE_H / 2, 0),
Color = C_PARAPET,
Material = Enum.Material.Concrete,
})
edge.Parent = pa
end
-- No pillars under the ring any more. The ring is now a GROUND-LEVEL -- No pillars under the ring any more. The ring is now a GROUND-LEVEL
-- circulation road sharing the apron slab (Circuit.PA_LIFT raises the -- circulation road sharing the apron slab (Circuit.PA_LIFT raises the
@@ -1258,6 +1244,72 @@ local function buildPA(map: Folder)
-- Mainline pillars are built in buildRoad; see PA_LIFT. -- Mainline pillars are built in buildRoad; see PA_LIFT.
end end
-- PERIMETER BARRIER -------------------------------------------------------
-- A single simple barrier following the EDGE OF THE PARKING AREA, which is
-- a square apron (APRON half-extent), not the circular ring road. Built as
-- four straight runs of short segments so gaps can be opened wherever a
-- ramp crosses the boundary -- otherwise the barrier would seal the PA and
-- trap the player. Segment length is kept modest so a gap lands cleanly.
do
local PERIM_H = 3.0
local PERIM_T = 1.6
local SEG = 40
-- Sit the barrier just inside the slab edge so it reads as the lot's
-- own kerb line rather than floating off the asphalt.
local half = APRON - PERIM_T / 2 - 1
local baseY = DECK_Y + 1 + PERIM_H / 2
-- Ramps tee in at the ring; open the perimeter where a ramp's centre
-- line crosses the square, plus clearance for the full ramp width.
local GATE = 90
local function blocked(x, z)
for _, jn in ipairs(junctions) do
-- Project the junction outward onto the square boundary and
-- compare against this segment's centre.
local d = Vector3.new(x - jn.ringPt.X, 0, z - jn.ringPt.Z)
if d.Magnitude <= GATE then
return true
end
end
return false
end
local n = 0
for _, side in ipairs({ "N", "S", "E", "W" }) do
local along = -half
while along < half do
local segLen = math.min(SEG, half - along)
local mid = along + segLen / 2
local x, z, sizeV
if side == "N" then
x, z = c.X + mid, c.Z - half
sizeV = Vector3.new(segLen + 0.5, PERIM_H, PERIM_T)
elseif side == "S" then
x, z = c.X + mid, c.Z + half
sizeV = Vector3.new(segLen + 0.5, PERIM_H, PERIM_T)
elseif side == "W" then
x, z = c.X - half, c.Z + mid
sizeV = Vector3.new(PERIM_T, PERIM_H, segLen + 0.5)
else
x, z = c.X + half, c.Z + mid
sizeV = Vector3.new(PERIM_T, PERIM_H, segLen + 0.5)
end
if not blocked(x, z) then
local seg = part({
Name = "PAPerimeter",
Size = sizeV,
CFrame = CFrame.new(x, baseY, z),
Color = C_PARAPET,
Material = Enum.Material.Concrete,
})
seg.Parent = pa
n = n + 1
end
along = along + segLen
end
end
end
-- Two ramps: mainline -> ring (entry) and ring -> mainline (exit). -- Two ramps: mainline -> ring (entry) and ring -> mainline (exit).
-- `junctions` was resolved above (the ring wall needed it to place gates); -- `junctions` was resolved above (the ring wall needed it to place gates);
-- reuse it so the ramp deck and the wall opening can never disagree. -- reuse it so the ramp deck and the wall opening can never disagree.