diff --git a/src/server/MapBuilder.luau b/src/server/MapBuilder.luau index b51885c..dae346e 100644 --- a/src/server/MapBuilder.luau +++ b/src/server/MapBuilder.luau @@ -1528,21 +1528,41 @@ local function buildPA(map: Folder) kerb.Parent = pa end - -- Red/white shoulder chevrons. Every Shuto ramp carries - -- these on the outside of the curve -- they read as speed - -- cues in the onboard footage and are the main thing that - -- makes a helix legible from inside the car. Alternating - -- segments only, so they stripe rather than smear. - if s % 2 == 0 then + -- Red/white chevron delineators. + -- + -- CORRECTED 2026-08-03 against 4K dusk onboard footage of + -- the junction (jct_tsubasa_dusk, t=110..140s). These are + -- NOT road-surface paint, which is what the first pass + -- built -- a flat red slab lying on the deck. In reality + -- they are VERTICAL PANELS bolted to the outside face of + -- the concrete barrier, alternating red and white, running + -- continuously along the outside of the curve. They are + -- the main thing that makes a helix legible from inside + -- the car, and on the deck they were nearly invisible. + -- + -- Roblox part granularity can't do a diagonal stripe + -- inside one panel, so alternating whole panels per + -- segment stands in for the diagonal hatching. + -- + -- Outward side of the curve. Taking the raw radial + -- (segMid - O) as the offset direction is WRONG on the + -- straight tangent tail: there the radial is no longer + -- perpendicular to travel, so panels skew along the road + -- (measured: up to 33 studs of along-travel error over the + -- last ~9 segments, walking the panel line diagonally + -- across the deck instead of tracking its edge). + -- + -- Offset along the true perpendicular `rightV` always, and + -- use the radial ONLY to choose which side is outboard. + local radial = Vector3.new(segMid.X - O.X, 0, segMid.Z - O.Z) + if radial.Magnitude > 0.01 and rightV.Magnitude > 0.01 then + local sgn = (rightV:Dot(radial.Unit) >= 0) and 1 or -1 + local face = segMid + rightV * (sgn * RING_W / 2) local chev = part({ Name = "PARampChevron", - Size = Vector3.new(2.2, 0.4, segLen * 0.55), - CFrame = CFrame.lookAt( - segMid + rightV * (turn * RING_W / 2 * 0.86), - segMid + rightV * (turn * RING_W / 2 * 0.86) + (b - a).Unit, - UP - ) * CFrame.new(0, 1.3, 0), - Color = Color3.fromRGB(198, 46, 40), + Size = Vector3.new(0.5, 2.0, segLen), + CFrame = CFrame.lookAt(face, face + (b - a).Unit, UP) * CFrame.new(0, 2.7, 0), + Color = (s % 2 == 0) and Color3.fromRGB(198, 46, 40) or Color3.fromRGB(240, 238, 232), Material = Enum.Material.SmoothPlastic, }) chev.Parent = pa