Files
tokyo-wangan-racing/tools/probe_clip_v4.luau
T
jesse c297b20aed 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).
2026-08-03 21:15:25 -04:00

126 lines
3.8 KiB
Luau

-- 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")