diff --git a/src/server/MapBuilder.luau b/src/server/MapBuilder.luau index caa0c3d..ffc8971 100644 --- a/src/server/MapBuilder.luau +++ b/src/server/MapBuilder.luau @@ -1000,11 +1000,25 @@ local function buildPA(map: Folder) local DECK_Y = c.Y + 1 -- top face of the apron slab local C_PAINT = Color3.fromRGB(235, 235, 240) + -- Painted markings are PAINT, not kerbs. They must be flush with the apron. + -- + -- BUG (2026-08-02, test drive): these were spawned 2.2 studs tall sitting + -- at DECK_Y + 0.1, so every stall divider stood ~1.2 studs PROUD of the + -- tarmac -- a kerb-height ridge exactly where you park. Driving the rows + -- meant bouncing over 300+ concrete strips ("like a whole foot out of the + -- ground" -- measured 1.2, and a stud is ~a foot, so: exactly right). + -- + -- Fix: 0.12 studs thick, sunk so its TOP sits a hair above the deck. A + -- decal would be flatter still, but a thin slab keeps this buildable from + -- pure geometry with no asset IDs, and 0.06 studs proud is under tyre + -- resolution -- you cannot feel it. + local PAINT_T = 0.12 local function paint(name, size, x, z, colour) local m = part({ Name = name, - Size = size, - CFrame = CFrame.new(x, DECK_Y + 0.1, z), + -- caller passes the old 2.2 in size.Y; ignore it and use PAINT_T + Size = Vector3.new(size.X, PAINT_T, size.Z), + CFrame = CFrame.new(x, DECK_Y + PAINT_T / 2 - 0.06, z), Color = colour or C_PAINT, Material = Enum.Material.SmoothPlastic, }) @@ -1208,22 +1222,17 @@ local function buildPA(map: Folder) local segCF = CFrame.lookAt(segMid, p1, UP) deck("PARing", Vector3.new(RING_W, 2, segLen), segCF) - -- Ring edge treatment. The OUTER edge (sgn == 1, away from the apron) - -- keeps the full white parapet + dark railing, because behind it is a - -- drop off the structure -- that wall is the only thing stopping a car - -- leaving the world. + -- Ring edge treatment. BOTH edges are now a single low barrier. -- - -- The INNER edge (sgn == -1, facing the parking lot) is now a LOW KERB, - -- not a parapet. Two reasons, one factual and one about driving: - -- * Factual: since the ring and the apron were both dropped to ground - -- level (Circuit.PA_LIFT raises the MAINLINE over the PA instead), - -- an inner parapet would be separating two surfaces at the SAME - -- height. The real Daikoku has a kerb and painted markings there, - -- not a wall -- the lot is open to its circulation road. - -- * Driving: a 44-stud lane walled on both sides is a canyon with no - -- runoff. Clipping the inside of the loop stopped a car dead. - -- The kerb is 1.2 studs, well under the ~2-3 studs a car can climb, so - -- it reads as an edge without being a barrier. + -- CHANGE (2026-08-02, user call): the OUTER edge used to be a tall + -- white parapet + dark railing ringing the whole parking area. That + -- is the "ring barrier" -- it walled the lot in and, combined with the + -- inner kerb, made the circulation road a 44-stud canyon. Ditched in + -- favour of a plain single barrier on the edge of the parking area. + -- + -- Outer keeps a slightly taller barrier than inner because behind the + -- outer edge is still a drop off the structure -- it has to stop a car + -- leaving the world, it just no longer needs to be a parapet+rail. local fwd = (p1 - p0).Unit local outN = (segMid - Vector3.new(c.X, ringY, c.Z)).Unit for _, sgn in ipairs({ 1, -1 }) do @@ -1233,34 +1242,15 @@ local function buildPA(map: Folder) local gate = (sgn == 1) and GATE_OUT or GATE_IN if not nearJunction(ePos, gate) then local eCF = CFrame.lookAt(ePos, ePos + fwd, UP) - if sgn == 1 then - local lip = part({ - Name = "PARingWall", - Size = Vector3.new(2.2, BARRIER_H, segLen + 1), - CFrame = eCF * CFrame.new(0, 1 + BARRIER_H / 2, 0), - Color = C_PARAPET, - Material = Enum.Material.Concrete, - }) - lip.Parent = pa - local lr = part({ - Name = "PARingRail", - Size = Vector3.new(0.6, RAIL_H, segLen + 1), - CFrame = eCF * CFrame.new(0, 1 + BARRIER_H + RAIL_H / 2, 0), - Color = C_RAIL, - Material = Enum.Material.Metal, - }) - lr.Parent = pa - else - local KERB_H = 1.2 - local kerb = part({ - Name = "PARingKerb", - Size = Vector3.new(1.6, KERB_H, segLen + 1), - CFrame = eCF * CFrame.new(0, 1 + KERB_H / 2, 0), - Color = C_PARAPET, - Material = Enum.Material.Concrete, - }) - kerb.Parent = pa - end + local EDGE_H = (sgn == 1) and 3.0 or 1.2 + local edge = part({ + Name = (sgn == 1) and "PARingEdge" or "PARingKerb", + 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 end @@ -1338,8 +1328,16 @@ local function buildPA(map: Folder) -- driving lane at the merge (measured: a 2.4-stud step 14 studs -- right of the centreline, hit as Road_526 -> PARampKerb). A merge -- has to be open, so the last segment carries no kerb. + -- Kerb EVERY segment except the merge mouth. The height test is + -- gone entirely: `h > 8` then `h > 2` both still failed on the + -- foot of the ramp (h = 0.5 .. 0.8 at apron level), which is + -- exactly where the barrier was seen "ending in mid-air" -- the + -- edge began one segment UP the ramp, leaving the first ~40 studs + -- of both ramps completely open on both sides. A ramp edge is + -- continuous in reality regardless of how high it happens to be, + -- so the only exclusion left is the merge, which must stay open. local isMergeSeg = (s >= STEPS - 1) - if h > 2 and not isMergeSeg then + if not isMergeSeg then local fwd2 = (b - a) fwd2 = Vector3.new(fwd2.X, 0, fwd2.Z) if fwd2.Magnitude > 0.01 then