Aux-lane suppression + PA geometry fixes; probe/verify tooling
CI / quality (push) Failing after 1m9s
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
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
-- Is the fused aux run genuine continuous pavement (a weaving section), or
|
||||
-- overlapping/duplicated parts? Checks per-sample coverage, duplicate indices,
|
||||
-- and the width profile across both mouths.
|
||||
local ws = game:GetService("Workspace")
|
||||
local map = ws:FindFirstChild("Map")
|
||||
if not map then return "NOMAP" end
|
||||
|
||||
local seen, dupes = {}, 0
|
||||
local byIdx = {}
|
||||
for _, d in ipairs(map:GetDescendants()) do
|
||||
if d:IsA("BasePart") then
|
||||
local i = tonumber(d.Name:match("^AuxLane_(%d+)$") or "")
|
||||
if i then
|
||||
if seen[i] then dupes += 1 end
|
||||
seen[i] = true
|
||||
byIdx[i] = d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local out = {}
|
||||
local function say(s) table.insert(out, s) end
|
||||
say(("duplicate AuxLane indices: %d -> %s"):format(dupes, dupes == 0 and "PASS" or "FAIL"))
|
||||
|
||||
-- Walk 505..570 and report which samples have lane and how wide.
|
||||
local missing = {}
|
||||
local prof = {}
|
||||
for i = 505, 570 do
|
||||
local p = byIdx[i]
|
||||
if p then
|
||||
table.insert(prof, ("%d:%.0f"):format(i, p.Size.X))
|
||||
else
|
||||
table.insert(missing, i)
|
||||
table.insert(prof, ("%d:--"):format(i))
|
||||
end
|
||||
end
|
||||
say("width profile (sample:width, -- = no lane):")
|
||||
say(" " .. table.concat(prof, " "))
|
||||
say("gaps in 505..570: " .. (#missing > 0 and table.concat(missing, ",") or "none"))
|
||||
|
||||
-- The only gaps should be the ramp noses (the ramp deck covers those).
|
||||
-- Derive coverage from the ACTUAL ramp deck parts, but test the point where
|
||||
-- the AUX LANE would sit (deck edge + half lane width) -- NOT the mainline
|
||||
-- centreline. Testing proximity to the centreline marked 26 samples as "nose"
|
||||
-- because the ramp spirals past them at other heights, which would mask any
|
||||
-- real hole and make this check vacuously pass. The nose test must also match
|
||||
-- in HEIGHT: a ramp 50 studs below the deck does not cover the deck's edge.
|
||||
local samples = require(game:GetService("ReplicatedStorage")
|
||||
:WaitForChild("Shared"):WaitForChild("Circuit")).samples
|
||||
local decks = {}
|
||||
for _, d in ipairs(map:GetDescendants()) do
|
||||
if d:IsA("BasePart") and d.Name:match("Slip_Deck_") then
|
||||
table.insert(decks, d)
|
||||
end
|
||||
end
|
||||
|
||||
local HALF, AUXW, SIDE = 30, 26, -1
|
||||
local function auxPointAt(i)
|
||||
local n = #samples
|
||||
local a = samples[((i - 1) % n) + 1]
|
||||
local b = samples[(i % n) + 1]
|
||||
local f = b.pos - a.pos
|
||||
f = Vector3.new(f.X, 0, f.Z).Unit
|
||||
local r = Vector3.new(-f.Z, 0, f.X)
|
||||
return a.pos + r * (SIDE * (HALF + AUXW / 2)), a.pos.Y
|
||||
end
|
||||
|
||||
local NOSE, noseWhy = {}, {}
|
||||
for _, i in ipairs(missing) do
|
||||
local p, deckY = auxPointAt(i)
|
||||
for _, d in ipairs(decks) do
|
||||
local flat = (Vector3.new(d.Position.X, 0, d.Position.Z)
|
||||
- Vector3.new(p.X, 0, p.Z)).Magnitude
|
||||
local dy = math.abs(d.Position.Y - deckY)
|
||||
-- Must overlap the lane footprint horizontally AND be at deck level.
|
||||
if flat <= AUXW and dy <= 6 then
|
||||
NOSE[i] = true
|
||||
noseWhy[i] = ("%s flat=%.0f dy=%.0f"):format(d.Name, flat, dy)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local noseList = {}
|
||||
for i in pairs(NOSE) do table.insert(noseList, i) end
|
||||
table.sort(noseList)
|
||||
say(("ramp-nose-covered gaps (%d): %s"):format(#noseList, table.concat(noseList, ",")))
|
||||
for _, i in ipairs(noseList) do
|
||||
say((" %d covered by %s"):format(i, noseWhy[i]))
|
||||
end
|
||||
|
||||
local lo, hi = math.huge, -1
|
||||
for k in pairs(byIdx) do
|
||||
lo = math.min(lo, k); hi = math.max(hi, k)
|
||||
end
|
||||
local bad = {}
|
||||
for _, i in ipairs(missing) do
|
||||
-- Samples outside the lane's own extent are not holes; only flag gaps that
|
||||
-- sit strictly between the first and last aux segment.
|
||||
if i > lo and i < hi and not NOSE[i] then table.insert(bad, i) end
|
||||
end
|
||||
say(("lane run extent: %d..%d"):format(lo, hi))
|
||||
say(("non-nose gaps inside the lane run: %s -> %s"):format(#bad > 0 and table.concat(bad, ",") or "none",
|
||||
#bad == 0 and "PASS (only ramp noses uncovered)" or "FAIL (hole in pavement)"))
|
||||
|
||||
-- Between the two mouths, is the lane continuously full width (a real weaving
|
||||
-- section) rather than tapering out and back in?
|
||||
local weaveMin = math.huge
|
||||
local weaveTested = 0
|
||||
for i = 528, 548 do
|
||||
local p = byIdx[i]
|
||||
if p then
|
||||
weaveTested += 1
|
||||
weaveMin = math.min(weaveMin, p.Size.X)
|
||||
end
|
||||
end
|
||||
if weaveTested == 0 then
|
||||
say("weave section: FAIL nothing tested")
|
||||
else
|
||||
say(("weave section 528..548: %d segs, min width %.1f -> %s")
|
||||
:format(weaveTested, weaveMin,
|
||||
weaveMin >= 24 and "PASS (continuous full-width weaving lane)" or "TAPERS"))
|
||||
end
|
||||
return table.concat(out, "\n")
|
||||
Reference in New Issue
Block a user