Files
tokyo-wangan-racing/tools/diag_access_clip.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

146 lines
3.4 KiB
Luau

-- Diagnose the two reported defects:
-- (1) ramps not accessible in either direction (connectivity)
-- (2) ramps pass through buildings (clipping)
-- Uses native GetPartBoundsInBox so this stays fast on ~22k parts.
local ws = game:GetService("Workspace")
local map = ws:FindFirstChild("Map")
if not map then
return "NO MAP"
end
local BUILDING = {
Building = true,
TokyoTower = true,
TowerDeck = true,
TowerAntenna = true,
ShiodomeTower = true,
TowerCrown = true,
DietTower = true,
RoppongiHills = true,
TokyoStation = true,
StationDome = true,
Skytree = true,
GinzaBlock = true,
NationalDiet = true,
BridgeTower = true,
TowerCrossbeam = true,
Structure = true,
PalaceWall = true,
}
local ramp, drivable = {}, {}
for _, d in ipairs(map:GetDescendants()) do
if d:IsA("BasePart") then
local n = d.Name
if n:find("PAEntryRamp") or n:find("PAExitRamp") then
table.insert(ramp, d)
elseif n:match("^Road_%d+$") or n == "PAFloor" then
table.insert(drivable, d)
end
end
end
if #ramp == 0 then
return "no ramp parts"
end
-- ---------- (2) BUILDING CLIP CHECK ----------
local op = OverlapParams.new()
op.MaxParts = 40
local clipHits, clipNames, worst = 0, {}, {}
for _, r in ipairs(ramp) do
local hits = ws:GetPartBoundsInBox(r.CFrame, r.Size, op)
for _, h in ipairs(hits) do
if h ~= r and BUILDING[h.Name] then
clipHits += 1
clipNames[h.Name] = (clipNames[h.Name] or 0) + 1
if #worst < 5 then
table.insert(worst, ("%s@%.0f,%.0f,%.0f"):format(r.Name, r.Position.X, r.Position.Y, r.Position.Z))
end
break
end
end
end
-- CONTROL: same probe against mainline Road_ parts (known-good, should be ~0)
local ctrlHits, ctrlN = 0, 0
for i = 1, #drivable, 9 do
local d = drivable[i]
ctrlN += 1
local hits = ws:GetPartBoundsInBox(d.CFrame, d.Size, op)
for _, h in ipairs(hits) do
if h ~= d and BUILDING[h.Name] then
ctrlHits += 1
break
end
end
end
local cn = {}
for k, v in pairs(clipNames) do
table.insert(cn, k .. "=" .. v)
end
-- ---------- (1) CONNECTIVITY ----------
-- Ramp basename groups, then endpoints of each group by trailing index.
local groups = {}
for _, r in ipairs(ramp) do
local base, idx = r.Name:match("^(.-)_?(%d+)$")
base = base or r.Name
idx = tonumber(idx) or 0
local g = groups[base]
if not g then
g = { lo = math.huge, hi = -math.huge, loP = nil, hiP = nil, n = 0 }
groups[base] = g
end
g.n += 1
if idx < g.lo then
g.lo, g.loP = idx, r
end
if idx > g.hi then
g.hi, g.hiP = idx, r
end
end
-- For an endpoint, find nearest drivable surface and report gap + height delta.
local function nearestDrivable(p)
local bd, bp = math.huge, nil
for _, d in ipairs(drivable) do
local dd = (d.Position - p).Magnitude
if dd < bd then
bd, bp = dd, d
end
end
return bd, bp
end
local lines = {}
for base, g in pairs(groups) do
if g.loP and g.hiP then
local d1, p1 = nearestDrivable(g.loP.Position)
local d2, p2 = nearestDrivable(g.hiP.Position)
table.insert(
lines,
("%s n=%d | START gap=%.0f dY=%.1f to %s | END gap=%.0f dY=%.1f to %s"):format(
base,
g.n,
d1,
p1 and (g.loP.Position.Y - p1.Position.Y) or -999,
p1 and p1.Name or "nil",
d2,
p2 and (g.hiP.Position.Y - p2.Position.Y) or -999,
p2 and p2.Name or "nil"
)
)
end
end
return ("CLIP ramp=%d/%d parts hit buildings [%s] samples=[%s] || CONTROL road %d/%d hit\n%s"):format(
clipHits,
#ramp,
table.concat(cn, ", "),
table.concat(worst, " ; "),
ctrlHits,
ctrlN,
table.concat(lines, "\n")
)