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.
93 lines
2.6 KiB
Luau
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,
|
|
})
|