Files
jesse 6e50f9718d
CI / quality (push) Failing after 1m9s
Aux-lane suppression + PA geometry fixes; probe/verify tooling
MapBuilder.luau
  - Suppress the aux lane across samples 525-550 (AUX_SUPPRESS_FROM/TO),
    honoring the user's hand deletion in Studio so a rebuild no longer
    regenerates it.
  - Smoothstep the width ramp over AUX_BLEND=5 samples on each side. A hard
    cut produced a 26-stud lateral fence jog; the blend removes it.
  - DO NOT remove this suppression. Re-enabling it resurrects geometry the
    user deleted by hand.

rokit.toml
  - rojo 7.5.1 -> 7.7.0 to match the auto-updating Studio plugin.
    Server older than plugin fails the handshake with
    "attempt to index number with 'protocolVersion'".

tools/
  - 34 read-only probe/verify/capture scripts used to measure the datamodel
    instead of reasoning from source.

Verified-good baseline at this commit:
  total parts       16788
  PAWestSlip        60 segs, 34.4 deg total bend, worst 1.4, 0 kinks >5
  PAEastSlip        60 segs, 30.7 deg total bend, worst 1.3, 0 kinks >5
  AuxLane parts     30 (samples 525-550 deliberately absent)
  barrier coverage  823 samples, 0 unguarded
  fence jogs >10st  0
2026-08-06 08:27:47 -04:00

89 lines
3.0 KiB
Luau

-- Which side of the deck does each slip + aux lane sit on?
-- Answers: are both existing slips on the SAME carriageway (so "the opposite"
-- means the other carriageway), or is one an entry and one an exit?
local ws = game:GetService("Workspace")
local RS = game:GetService("ReplicatedStorage")
local Circuit = require(RS:WaitForChild("Shared"):WaitForChild("Circuit"))
local map = ws:FindFirstChild("Map")
if not map then return "NOMAP" end
local samples = Circuit.samples
local out = {}
local function say(s) table.insert(out, s) end
-- Signed lateral offset of a world point from the mainline at sample i.
-- Positive = one side, negative = the other. Uses the deck's own right vector.
local function sideOf(i, p)
local n = #samples
local a = samples[((i - 1) % n) + 1]
local b = samples[(i % n) + 1]
local fwd = (b.pos - a.pos)
fwd = Vector3.new(fwd.X, 0, fwd.Z).Unit
local right = Vector3.new(-fwd.Z, 0, fwd.X)
local rel = Vector3.new(p.X - a.pos.X, 0, p.Z - a.pos.Z)
return rel:Dot(right)
end
local SLIPS = { { "PAWestSlip", 525, 537 }, { "PAEastSlip", 551, 539 } }
for _, s in ipairs(SLIPS) do
local name, join, land = s[1], s[2], s[3]
local first, last, nseg = nil, nil, 0
local maxI = -1
for _, d in ipairs(map:GetDescendants()) do
if d:IsA("BasePart") then
local k = tonumber(d.Name:match("^" .. name .. "_Deck_(%d+)$") or "")
if k then
nseg += 1
if k <= 1 then first = d end
if k > maxI then maxI, last = k, d end
end
end
end
if not first then
say(name .. ": FAIL no deck parts")
else
local lat = sideOf(join, first.Position)
say(("%s: segs=%d mouth lateral %+.1f (%s side) mouthY=%.1f landY=%.1f -> %s")
:format(name, nseg, lat, lat > 0 and "RIGHT" or "LEFT",
first.Position.Y, last and last.Position.Y or -1,
(last and last.Position.Y < first.Position.Y) and "DESCENDS (exit/off-ramp)"
or "CLIMBS (entry/on-ramp)"))
end
end
-- Aux lanes: which side, grouped by contiguous sample index.
local aux = {}
for _, d in ipairs(map:GetDescendants()) do
if d:IsA("BasePart") then
local ai = tonumber(d.Name:match("^AuxLane_(%d+)$") or "")
if ai then table.insert(aux, { i = ai, p = d.Position }) end
end
end
table.sort(aux, function(x, y) return x.i < y.i end)
if #aux == 0 then
say("AUX: FAIL none built")
else
local groups, cur = {}, { aux[1] }
for k = 2, #aux do
if aux[k].i - aux[k - 1].i > 3 then
table.insert(groups, cur); cur = {}
end
table.insert(cur, aux[k])
end
table.insert(groups, cur)
for gi, g in ipairs(groups) do
local mid = g[math.max(1, math.floor(#g / 2))]
local lat = sideOf(mid.i, mid.p)
say(("AUX group %d: samples %d..%d (%d segs) lateral %+.1f (%s side)")
:format(gi, g[1].i, g[#g].i, #g, lat, lat > 0 and "RIGHT" or "LEFT"))
end
end
-- Does the deck carry traffic both ways, and is there a median?
local med = 0
for _, d in ipairs(map:GetDescendants()) do
if d:IsA("BasePart") and d.Name:match("^Median") then med += 1 end
end
say(("median parts: %d (deck is one slab split into two carriageways)"):format(med))
return table.concat(out, "\n")