-- Two questions, measured rather than eyeballed: -- (1) WHERE exactly is the mainline missing barriers? Walk the deck edge and -- report contiguous runs with no Barrier/EdgeRail within reach. -- (User deleted ~106 parts by hand, so gaps are wherever they cut.) -- (2) HOW does the south on-ramp differ from the north off-ramp? Compare the -- two slips feature-by-feature so "make it look like the other" is a -- concrete list of deltas, not a guess. local out = {} local function say(s) table.insert(out, s) end local map = workspace:FindFirstChild("Map") if not map then return "Map MISSING" end -- Collect barrier-ish parts into a coarse spatial hash for fast lookup. local CELL = 60 local grid = {} local function key(x, z) return math.floor(x / CELL) .. ":" .. math.floor(z / CELL) end local barrierCount = 0 for _, d in ipairs(map:GetDescendants()) do if d:IsA("BasePart") and (d.Name == "Barrier" or d.Name == "EdgeRail") then barrierCount += 1 local k = key(d.Position.X, d.Position.Z) grid[k] = grid[k] or {} table.insert(grid[k], d) end end say(("indexed %d Barrier/EdgeRail parts"):format(barrierCount)) local function nearestBarrier(p) local best = math.huge local cx, cz = math.floor(p.X / CELL), math.floor(p.Z / CELL) for dx = -1, 1 do for dz = -1, 1 do local c = grid[(cx + dx) .. ":" .. (cz + dz)] if c then for _, b in ipairs(c) do local d2 = (Vector3.new(b.Position.X, 0, b.Position.Z) - Vector3.new(p.X, 0, p.Z)).Magnitude -- only count barriers at roughly this height if math.abs(b.Position.Y - p.Y) < 14 and d2 < best then best = d2 end end end end end return best end -- Walk the mainline deck parts to build an ordered centreline. local deck = {} for _, d in ipairs(map:GetDescendants()) do if d:IsA("BasePart") then local k = d.Name:match("^Road_(%d+)$") or d.Name:match("^Deck_(%d+)$") or d.Name:match("^RoadDeck_(%d+)$") if k then table.insert(deck, { i = tonumber(k), p = d.Position, cf = d.CFrame, sz = d.Size }) end end end table.sort(deck, function(a, b) return a.i < b.i end) say(("mainline deck parts found: %d"):format(#deck)) if #deck > 0 then local UP = Vector3.new(0, 1, 0) local runs = {} local cur = nil for j, s in ipairs(deck) do local fwd = s.cf.LookVector local right = fwd:Cross(UP).Unit local half = s.sz.X / 2 -- probe just outboard of each edge local gapL = nearestBarrier(s.p - right * (half + 2)) > 12 local gapR = nearestBarrier(s.p + right * (half + 2)) > 12 local bad = gapL or gapR if bad then local side = (gapL and gapR) and "BOTH" or (gapL and "L" or "R") if cur and cur.side == side and s.i - cur.last <= 2 then cur.last = s.i; cur.n += 1 else if cur then table.insert(runs, cur) end cur = { first = s.i, last = s.i, n = 1, side = side, pos = s.p } end else if cur then table.insert(runs, cur); cur = nil end end end if cur then table.insert(runs, cur) end table.sort(runs, function(a, b) return a.n > b.n end) say(("UNBARRIERED RUNS: %d total"):format(#runs)) for j = 1, math.min(#runs, 14) do local r = runs[j] say((" samples %d..%d (%d) side=%s at (%.0f,%.0f,%.0f)"):format( r.first, r.last, r.n, r.side, r.pos.X, r.pos.Y, r.pos.Z)) end end -- (2) Compare the two slips. say("--- SLIP COMPARISON ---") for _, s in ipairs({ "PAWestSlip", "PAEastSlip" }) do local segs, walls, lines, other = {}, 0, 0, {} for _, d in ipairs(map:GetDescendants()) do if d:IsA("BasePart") and d.Name:match("^" .. s) then local k = d.Name:match("^" .. s .. "_Deck_(%d+)$") if k then table.insert(segs, { i = tonumber(k), p = d.Position, sz = d.Size, cf = d.CFrame }) elseif d.Name:match("_Wall_") then walls += 1 elseif d.Name:match("[Ll]ine") then lines += 1 else local nm = d.Name:gsub("^" .. s .. "_", ""):gsub("_%d+$", "") other[nm] = (other[nm] or 0) + 1 end end end table.sort(segs, function(a, b) return a.i < b.i end) local ol = {} for k, v in pairs(other) do table.insert(ol, k .. "=" .. v) end table.sort(ol) if #segs > 0 then -- heading of first and last segment: which way does it run? local h1 = segs[1].cf.LookVector local hN = segs[#segs].cf.LookVector -- curvature: total heading change local turn = 0 for j = 2, #segs do local a = segs[j - 1].cf.LookVector local b = segs[j].cf.LookVector turn += math.deg(math.acos(math.clamp(a:Dot(b), -1, 1))) end say(("%s: segs=%d walls=%d lines=%d startY=%.1f endY=%.1f"):format(s, #segs, walls, lines, segs[1].p.Y, segs[#segs].p.Y)) say((" heading first=(%.2f,%.2f) last=(%.2f,%.2f) totalTurn=%.1fdeg"):format(h1.X, h1.Z, hN.X, hN.Z, turn)) say((" start=(%.0f,%.0f,%.0f) end=(%.0f,%.0f,%.0f)"):format( segs[1].p.X, segs[1].p.Y, segs[1].p.Z, segs[#segs].p.X, segs[#segs].p.Y, segs[#segs].p.Z)) say(" other parts: " .. (#ol > 0 and table.concat(ol, " ") or "none")) end end return table.concat(out, "\n")