Files
jesse c8dabea53a Daikoku PA: lift mainline over the apron, rebuild both ramps
The PA ring road and the expressway mainline were both at ground level, so
the ring parapet stood INSIDE the carriageway (measured -10.0 studs of
vertical overlap: a wall in the middle of the road).

Reference photos of the real Daikoku Futo PA show the expressway flying
OVER the parking apron on pillars, with the PA at ground level and ramps
climbing up to meet it. Rebuilt to match:

- mainline lifted 38 studs through the junction, eased in/out (max 5.26%
  grade, within real expressway limits)
- PA ring + apron stay at ground level; legacy PARingPillar props removed
- both on/off ramps regraded over the full rise with smoothstep easing,
  segments overlapped 3 studs so wheels can't catch a seam, plus support
  pillars and edge kerbs where the deck is high

Verified in-engine against built parts (tools/diag_daikoku.luau), not just
source: clearance now +28.0 studs, both ramps continuous (max step 5.62,
no gaps). tools/plot_daikoku.py renders the plan/section for comparison.
2026-08-02 15:56:13 -04:00

93 lines
2.6 KiB
Luau

--[[
diag_wallmap.luau -- export every wall/barrier part near the PA as JSON so
it can be plotted top-down on the workstation.
Screen capture of the Studio viewport is unavailable on this machine
(Vinegar/Wine on a nested X display, DXVK renders the viewport so XGetImage
returns black), so instead of a screenshot we dump geometry and draw the
map ourselves. For "are there gaps / is it jumbled" questions a top-down
plot is strictly better than a screenshot anyway: it is to scale and every
part is labelled.
Read-only. Builds nothing, changes nothing.
]]
local Workspace = game:GetService("Workspace")
local WALL_NAMES = {
Barrier = true,
EdgeRail = true,
KillWall = true,
PARingWall = true,
PARingRail = true,
Median = true,
MedianFence = true,
}
local function classify(name)
if WALL_NAMES[name] then
return name
end
-- Median_12 / Road_37 style suffixed names
local base = name:match("^([%a]+)_%d+$")
if base and WALL_NAMES[base] then
return base
end
if name:find("^Road") or name:find("^PARing$") or name == "PARing" then
return "Road"
end
if name == "PAOnRamp" or name == "PAOffRamp" or name == "PARampFlare" then
return "Ramp"
end
if name == "PAApron" or name:find("Apron") then
return "Apron"
end
return nil
end
local out = {}
local counts = {}
-- The bridge truncates payloads at ~100k chars, so only export parts near the
-- PA -- that is the region under investigation anyway. Counts are still taken
-- over the WHOLE map so nothing is hidden by the filter.
local PA = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared"):WaitForChild("Circuit")).PA_CENTER
local NEAR = 900
for _, d in ipairs(Workspace:GetDescendants()) do
if d:IsA("BasePart") then
local kind = classify(d.Name)
if kind then
counts[kind] = (counts[kind] or 0) + 1
local p = d.Position
local dist = math.sqrt((p.X - PA.X) ^ 2 + (p.Z - PA.Z) ^ 2)
if dist <= NEAR then
table.insert(out, {
k = kind,
x = math.floor(p.X * 10) / 10,
y = math.floor(p.Y * 10) / 10,
z = math.floor(p.Z * 10) / 10,
sx = math.floor(d.Size.X * 10) / 10,
sz = math.floor(d.Size.Z * 10) / 10,
r = math.floor(math.deg(select(2, d.CFrame:ToEulerAnglesYXZ())) * 10) / 10,
})
end
end
end
end
local summary = {}
for k, v in pairs(counts) do
table.insert(summary, string.format("%s=%d", k, v))
end
table.sort(summary)
-- execute_luau returns the RETURN VALUE, not stdout -- prints are discarded by
-- the bridge, so hand the payload back directly.
local HttpService = game:GetService("HttpService")
return HttpService:JSONEncode({
counts = table.concat(summary, " "),
total = #out,
parts = out,
})