Disable PA on/off ramps; restore mainline to pre-ramp state
Three iterations of the Daikoku PA ramps never read as a real
interchange. Measured why, rather than tuning further:
* the entry and exit decks INTERSECTED -- 2547 sample pairs within
30 studs horizontally at <12 studs dY, worst case 0.5 studs apart
at dY=0.0. On screen that is the bowtie tangle of white rails.
* both real Daikoku ramps turn the SAME way (clockwise; the guide
video says "right, right"). This build mirrored them into each
other.
* the real arc wraps OUTSIDE the lot and forms its north/east
boundary. This build cut across the apron interior.
Gated behind BUILD_PA_RAMPS=false rather than deleted -- the radius
was already correct (470 studs vs an OSM-measured mean of 469) and
the merge lands tangent at 0.1-0.2 deg divergence. Both worth keeping.
Also removed two leftovers that would have outlived the ramps:
* rampOpen punched holes in the mainline's outer parapet, railing
and kill wall for ramps that no longer exist -- a barrier gap with
a drop behind it. Sealed via RAMP_EDGE_OPENINGS=false. Verified:
Barrier/EdgeRail/KillWall = 1646 each = 823 samples x 2 edges,
0 road samples without a guard within 90 studs.
* gore zebra hatching painted 1024 bars + 64 boundary lines marking
a junction that is not there. Sealed via RAMP_GORE_MARKINGS=false.
Verified after a cache-busting fresh rebuild (Studio's require() cache
otherwise serves the previous map and reports a false pass):
parts 22628 -> 15988
all ramp part classes = 0
Road = 823 (unchanged), spawn pad + PASpawn intact
clip probe TRUSTWORTHY (control +11/-0), CLIPPING=0
Research and rebuild spec kept for when this is revisited:
reference/ramps/BUILD_SPEC.md, INDEX.md (10 CC-licensed Commons
photos), docs/daikoku-reference-spec.md (OSM circle fits).
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
-- CLIP PROBE v4 -- FULL-WORKSPACE SCOPE. This is the one that finds the
|
||||
-- defect the user can see.
|
||||
--
|
||||
-- WHY v2 AND v3 BOTH RETURNED A FALSE ZERO:
|
||||
-- both scoped obstacles to the `Map` folder. The PA buildings are NOT in
|
||||
-- Map -- they are Creator-Store models parented directly to Workspace as
|
||||
-- siblings: McDonald's (1666 parts), Gas Station 1 (1463), 7 eleven (627),
|
||||
-- Restaurant1, Updated Ramen Shop, Fast Food Restaurant, すき家, Parking lot.
|
||||
-- The probes literally could not see the things being speared. A passing
|
||||
-- positive control did NOT save me: the control proved the metric works,
|
||||
-- not that the SCOPE covers the real obstacles.
|
||||
--
|
||||
-- v4 collects obstacles from the ENTIRE workspace, excluding only the Map
|
||||
-- folder's own drivable/infra parts. Reports per-model hit counts so we know
|
||||
-- exactly which shop each ramp is driving through.
|
||||
|
||||
local ws = game:GetService("Workspace")
|
||||
local map = ws:FindFirstChild("Map")
|
||||
if not map then
|
||||
return "NO MAP"
|
||||
end
|
||||
|
||||
local function isDrivable(n)
|
||||
return n:match("^Road_")
|
||||
or n:find("Ramp")
|
||||
or n == "PAFloor"
|
||||
or n:match("^Apron")
|
||||
or n:match("^Slip")
|
||||
or n:match("^Merge")
|
||||
end
|
||||
|
||||
-- collect drivable parts (ramps especially) from Map
|
||||
local drive = {}
|
||||
for _, d in ipairs(map:GetDescendants()) do
|
||||
if d:IsA("BasePart") and isDrivable(d.Name) then
|
||||
table.insert(drive, d)
|
||||
end
|
||||
end
|
||||
|
||||
-- collect obstacles: every BasePart in workspace that is NOT inside Map.
|
||||
-- These are the imported building models.
|
||||
local obst = {}
|
||||
local modelOf = {}
|
||||
for _, top in ipairs(ws:GetChildren()) do
|
||||
if top ~= map and not top:IsA("Terrain") and not top:IsA("Camera") then
|
||||
if top:IsA("BasePart") then
|
||||
-- loose parts like stray PAPerimeter/PARampKerb: skip, they're infra
|
||||
if not isDrivable(top.Name) and not top.Name:find("Perimeter") and not top.Name:find("Kerb") then
|
||||
table.insert(obst, top)
|
||||
modelOf[top] = top.Name
|
||||
end
|
||||
else
|
||||
for _, d in ipairs(top:GetDescendants()) do
|
||||
if d:IsA("BasePart") then
|
||||
table.insert(obst, d)
|
||||
modelOf[d] = top.Name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #obst == 0 then
|
||||
return "SCOPE FAIL: no obstacles found outside Map"
|
||||
end
|
||||
|
||||
local op = OverlapParams.new()
|
||||
op.FilterType = Enum.RaycastFilterType.Include
|
||||
op.FilterDescendantsInstances = obst
|
||||
op.MaxParts = 20
|
||||
|
||||
-- CONTROL+ : a box at a known obstacle's centre must report a hit
|
||||
local tgt = obst[math.floor(#obst / 2)]
|
||||
local cPos = ws:GetPartBoundsInBox(CFrame.new(tgt.Position), Vector3.new(4, 4, 4), op)
|
||||
-- CONTROL- : empty sky must report zero
|
||||
local cNeg = ws:GetPartBoundsInBox(CFrame.new(0, 40000, 0), Vector3.new(8, 8, 8), op)
|
||||
local trustworthy = #cPos > 0 and #cNeg == 0
|
||||
|
||||
local hits = 0
|
||||
local byModel, byRamp = {}, {}
|
||||
local samples = {}
|
||||
for _, p in ipairs(drive) do
|
||||
local probe = p.Size - Vector3.new(1.0, 1.0, 1.0)
|
||||
if probe.X > 0.5 and probe.Y > 0.5 and probe.Z > 0.5 then
|
||||
local h = ws:GetPartBoundsInBox(p.CFrame, probe, op)
|
||||
if #h > 0 then
|
||||
hits += 1
|
||||
local mn = modelOf[h[1]] or h[1].Name
|
||||
byModel[mn] = (byModel[mn] or 0) + 1
|
||||
local rn = p.Name:gsub("_%d+$", "")
|
||||
byRamp[rn] = (byRamp[rn] or 0) + 1
|
||||
if #samples < 10 then
|
||||
table.insert(
|
||||
samples,
|
||||
("%s@%.0f,%.0f,%.0f IN %s"):format(p.Name, p.Position.X, p.Position.Y, p.Position.Z, mn)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local out = {}
|
||||
table.insert(
|
||||
out,
|
||||
("CONTROL+=%d CONTROL-=%d -> %s"):format(#cPos, #cNeg, trustworthy and "TRUSTWORTHY" or "BROKEN-IGNORE")
|
||||
)
|
||||
table.insert(out, ("drivable=%d obstacles(outside Map)=%d CLIPPING=%d"):format(#drive, #obst, hits))
|
||||
|
||||
local function dump(t, label)
|
||||
local l = {}
|
||||
for k, v in pairs(t) do
|
||||
table.insert(l, ("%s=%d"):format(k, v))
|
||||
end
|
||||
table.sort(l)
|
||||
table.insert(out, label .. ": " .. table.concat(l, " | "))
|
||||
end
|
||||
if hits > 0 then
|
||||
dump(byModel, "MODELS SPEARED")
|
||||
dump(byRamp, "offending ramp groups")
|
||||
for _, s in ipairs(samples) do
|
||||
table.insert(out, " " .. s)
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(out, "\n")
|
||||
Reference in New Issue
Block a user