-- Verify the speed-change (auxiliary) lanes and that the slips no longer cut -- across mainline traffic. -- -- Rebuilds from a CLONED module first (require() cache bypass), then measures. -- Every check below can FAIL -- and asserts it actually tested something, so a -- lookup returning nothing reports FAIL rather than vacuously passing. local sss = game:GetService("ServerScriptService") local ss = game:GetService("ServerStorage") local ws = game:GetService("Workspace") local RS = game:GetService("ReplicatedStorage") local realMod = sss:FindFirstChild("MapBuilder", true) if not realMod then return "MapBuilder not found" end local bust = ss:FindFirstChild("_cachebust") if not bust then bust = Instance.new("Folder") bust.Name = "_cachebust" bust.Parent = ss end for _, ch in ipairs(bust:GetChildren()) do ch:Destroy() end local clone = realMod:Clone() clone.Name = "MapBuilder_aux_" .. tostring(math.random(1e6, 9e6)) clone.Parent = bust local mb = require(clone) local old = ws:FindFirstChild("Map") if old then old:Destroy() end local ok, err = pcall(function() mb.build() end) if not ok then return "BUILD ERROR: " .. tostring(err) end local map = ws:FindFirstChild("Map") if not map then return "no Map after build" end local Circuit = require(RS:WaitForChild("Shared"):WaitForChild("Circuit")) local out = {} local function say(s) table.insert(out, s) end -- Collect the aux lane decks and the slip decks. local aux = {} local decks = { PAWestSlip = {}, PAEastSlip = {} } for _, d in ipairs(map:GetDescendants()) do if d:IsA("BasePart") then local ai = d.Name:match("^AuxLane_(%d+)$") if ai then table.insert(aux, { i = tonumber(ai), p = d.Position, s = d.Size, cf = d.CFrame }) end for slipName, list in pairs(decks) do local idx = d.Name:match("^" .. slipName .. "_Deck_(%d+)$") if idx then table.insert(list, { i = tonumber(idx), p = d.Position, s = d.Size, cf = d.CFrame }) end end end end -- 1. The aux lanes must exist at all. if #aux == 0 then say("FAIL: no AuxLane_* parts were built") return table.concat(out, "\n") end say(("aux lane segments built: %d"):format(#aux)) -- 2. Every aux segment must sit OUTSIDE the mainline deck, not on top of it. -- Measure the gap between the mainline centreline and the aux centreline, -- and compare against that sample's own half-width. local samples = Circuit.samples local minClear, minAt = math.huge, -1 local tested = 0 for _, a in ipairs(aux) do local s = samples[a.i] if s then tested += 1 local d = (Vector3.new(a.p.X, 0, a.p.Z) - Vector3.new(s.pos.X, 0, s.pos.Z)).Magnitude -- inner edge of aux lane relative to mainline centre local innerEdge = d - a.s.X / 2 if innerEdge < minClear then minClear, minAt = innerEdge, a.i end end end if tested == 0 then say("FAIL: no aux segment matched a circuit sample (harness looked up nothing)") else say(("aux inner edge vs mainline centre: min %.1f studs at sample %d (tested %d)") :format(minClear, minAt, tested)) end -- 3. The slip decks must START at the aux lane offset, not on the centreline. -- This is the actual bug the user reported: lat began at 0. for slipName, list in pairs(decks) do table.sort(list, function(x, y) return x.i < y.i end) if #list < 50 then say(("%s FAIL: only %d deck segments"):format(slipName, #list)) else local first = list[1] -- Find the nearest mainline sample to the slip's first segment. local bestD, bestI = math.huge, -1 for i = 1, #samples do local d = (Vector3.new(first.p.X, 0, first.p.Z) - Vector3.new(samples[i].pos.X, 0, samples[i].pos.Z)).Magnitude if d < bestD then bestD, bestI = d, i end end local halfW = 0 do -- Deck half-width at that sample, read off the built road itself. local road = map:FindFirstChild("Road_" .. bestI, true) halfW = road and road.Size.X / 2 or 0 end local innerEdge = bestD - first.s.X / 2 local verdict = (halfW > 0 and innerEdge >= halfW - 1.5) and "PASS" or "FAIL" say(("%s start: centre %.1f from mainline centre, inner edge %.1f, deck half-width %.1f -> %s") :format(slipName, bestD, innerEdge, halfW, verdict)) end end -- 4. Continuity: the slip mouth and the nearest aux segment must be adjacent -- (end-to-end), not overlapping and not separated by a hole. for slipName, list in pairs(decks) do if #list >= 50 then local first = list[1] local bestGap, bestI = math.huge, -1 for _, a in ipairs(aux) do local g = (a.p - first.p).Magnitude if g < bestGap then bestGap, bestI = g, a.i end end local verdict = bestGap <= 90 and "PASS" or "FAIL" say(("%s mouth -> nearest aux segment: %.1f studs (sample %d) -> %s") :format(slipName, bestGap, bestI, verdict)) end end -- 5. The aux lane must be level with the mainline deck at the mouth. local maxStep, stepAt = 0, -1 for _, a in ipairs(aux) do local road = map:FindFirstChild("Road_" .. a.i, true) if road then local step = math.abs((a.p.Y + a.s.Y / 2) - (road.Position.Y + road.Size.Y / 2)) if step > maxStep then maxStep, stepAt = step, a.i end end end say(("aux/mainline surface step: max %.2f studs at sample %d -> %s") :format(maxStep, stepAt, maxStep <= 0.05 and "PASS" or "FAIL")) -- 6. The taper must actually taper: widths should fall to near zero at the end. local wmin, wmax = math.huge, 0 for _, a in ipairs(aux) do wmin = math.min(wmin, a.s.X) wmax = math.max(wmax, a.s.X) end say(("aux width range: %.1f .. %.1f studs -> %s") :format(wmin, wmax, (wmax >= 25 and wmin <= 8) and "PASS (full lane + taper)" or "CHECK")) -- 7. DECELERATION LANES. Each mouth must now have lane on BOTH sides: one -- upstream (decel, for traffic leaving) and one downstream (accel, for -- traffic joining). Group the aux segments into runs and check each slip -- mouth has a run on either side of it. table.sort(aux, function(x, y) return x.i < y.i end) local runs, cur = {}, { aux[1] } for k = 2, #aux do if aux[k].i - aux[k - 1].i > 3 then table.insert(runs, cur); cur = {} end table.insert(cur, aux[k]) end table.insert(runs, cur) say(("aux runs: %d (expect 4 = 2 mouths x {decel, accel})"):format(#runs)) for ri, r in ipairs(runs) do local wlo, whi = math.huge, 0 for _, a in ipairs(r) do wlo = math.min(wlo, a.s.X); whi = math.max(whi, a.s.X) end say((" run %d: samples %d..%d (%d segs) width %.1f..%.1f") :format(ri, r[1].i, r[#r].i, #r, wlo, whi)) end -- Each slip join must sit between a decel run and an accel run. for _, slip in ipairs({ { "PAWestSlip", 525 }, { "PAEastSlip", 551 } }) do local name, join = slip[1], slip[2] local before, after = false, false for _, r in ipairs(runs) do if r[#r].i < join and join - r[#r].i <= 6 then before = true end if r[1].i > join and r[1].i - join <= 6 then after = true end if r[1].i <= join and r[#r].i >= join then -- run spans the join: counts as adjacent on both sides before = true; after = true end end say(("%s join=%d: decel-side run %s, accel-side run %s -> %s") :format(name, join, tostring(before), tostring(after), (before and after) and "PASS" or "FAIL")) end return table.concat(out, "\n")