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,88 @@
|
||||
-- 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")
|
||||
Reference in New Issue
Block a user