CI / quality (push) Failing after 1m9s
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
94 lines
3.2 KiB
Luau
94 lines
3.2 KiB
Luau
-- The 10 flagged samples all read barrier=22.9 -- the exact signature of the
|
|
-- RELOCATED parapet (aux lane still exists at 510..524 and 551..565, and its
|
|
-- outer edge carries the rail). probe_final's audit did not re-probe the aux
|
|
-- outer edge, so it mislabelled them. Settle it: for each flagged sample,
|
|
-- measure distance from the AUX OUTER edge to the nearest barrier.
|
|
local out = {}
|
|
local function say(s) table.insert(out, s) end
|
|
|
|
local map = workspace:FindFirstChild("Map")
|
|
if not map then return "Map MISSING" end
|
|
|
|
local deck, bars, aux = {}, {}, {}
|
|
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+)$")
|
|
if k then deck[tonumber(k)] = d end
|
|
if d.Name == "Barrier" or d.Name == "EdgeRail" then table.insert(bars, d) end
|
|
local a = d.Name:match("^AuxLane_(%d+)$")
|
|
if a then aux[tonumber(a)] = d end
|
|
end
|
|
end
|
|
|
|
local UP = Vector3.new(0, 1, 0)
|
|
local function flat(v) return Vector3.new(v.X, 0, v.Z) end
|
|
local function nearest(p, ytol)
|
|
local best = math.huge
|
|
for _, b in ipairs(bars) do
|
|
if math.abs(b.Position.Y - p.Y) < (ytol or 14) then
|
|
local dd = (flat(b.Position) - flat(p)).Magnitude
|
|
if dd < best then best = dd end
|
|
end
|
|
end
|
|
return best
|
|
end
|
|
|
|
local flagged = { 520, 521, 522, 523, 524, 551, 552, 553, 554, 555 }
|
|
local trueHoles = {}
|
|
say("sample | auxHere | barrier@auxOuterEdge | verdict")
|
|
for _, i in ipairs(flagged) do
|
|
local d, a = deck[i], aux[i]
|
|
if d then
|
|
local right = d.CFrame.LookVector:Cross(UP).Unit
|
|
local verdict, dist
|
|
if a then
|
|
-- probe just outboard of the AUX lane, where the rail was moved to
|
|
local outer = a.Position - right * (a.Size.X / 2 + 2)
|
|
dist = nearest(outer)
|
|
verdict = dist < 14 and "OK (parapet relocated to aux edge)" or "HOLE"
|
|
else
|
|
local edge = d.Position - right * (d.Size.X / 2 + 2)
|
|
dist = nearest(edge)
|
|
verdict = dist < 12 and "OK" or "HOLE"
|
|
end
|
|
if verdict == "HOLE" then table.insert(trueHoles, i) end
|
|
say((" %d | aux=%s | %.1f | %s"):format(i, a and "yes" or "no", dist, verdict))
|
|
end
|
|
end
|
|
|
|
say(("TRUE UNGUARDED SAMPLES: %d %s"):format(#trueHoles,
|
|
#trueHoles > 0 and table.concat(trueHoles, ",") or "(none)"))
|
|
|
|
-- Full-loop sweep so nothing elsewhere is missed.
|
|
local swept, holes = 0, {}
|
|
for i, d in pairs(deck) do
|
|
swept += 1
|
|
local right = d.CFrame.LookVector:Cross(UP).Unit
|
|
for _, sgn in ipairs({ -1, 1 }) do
|
|
local edge = d.Position + right * sgn * (d.Size.X / 2 + 2)
|
|
if nearest(edge) >= 12 then
|
|
local a = aux[i]
|
|
local ok = false
|
|
if a then
|
|
local outer = a.Position + right * sgn * (a.Size.X / 2 + 2)
|
|
if nearest(outer) < 14 then ok = true end
|
|
end
|
|
if not ok then
|
|
-- ramp mouth? slip structure nearby counts as guarded
|
|
local sd = math.huge
|
|
for _, p in ipairs(map:GetDescendants()) do
|
|
if p:IsA("BasePart") and p.Name:match("Slip") then
|
|
local dd = (flat(p.Position) - flat(edge)).Magnitude
|
|
if dd < sd then sd = dd end
|
|
end
|
|
end
|
|
if sd > 30 then table.insert(holes, i .. (sgn < 0 and "L" or "R")) end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
say(("FULL SWEEP: %d deck samples, unguarded=%d %s"):format(swept, #holes,
|
|
#holes > 0 and ("-> " .. table.concat(holes, ",")) or "(none)"))
|
|
|
|
return table.concat(out, "\n")
|