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

185 lines
5.5 KiB
Luau

--[[
diag_wheelroot2.luau -- same investigation as diag_wheelroot, but wrapped
so a failure reports WHERE. The first attempt died with a bare "attempt to
call a nil value" and no line, which tells us nothing; both _buildForDiag
(CarManager:988) and Chassis.tuningFor (Chassis:158) are confirmed to
exist, so the nil is something else in the script.
Runs each stage under pcall + traceback and prints progress markers, so
the last marker printed localises the fault even if the traceback is
swallowed by the executor.
]]
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local out = {}
local function log(...)
local parts = {}
for i = 1, select("#", ...) do
parts[#parts + 1] = tostring((select(i, ...)))
end
table.insert(out, table.concat(parts, " "))
end
local function stage(name, fn)
local ok, err = xpcall(fn, function(e)
return tostring(e) .. "\n" .. debug.traceback("", 2)
end)
if not ok then
log("!! FAILED at stage: " .. name)
log(err)
return false
end
log(" ok: " .. name)
return true
end
local Shared, Cars, Chassis, CarManager, cm
stage("require shared", function()
Shared = ReplicatedStorage:FindFirstChild("Shared")
Cars = require(Shared.Cars)
Chassis = require(Shared.Chassis)
end)
stage("clone+require CarManager", function()
local orig = ServerScriptService:FindFirstChild("Server", true):FindFirstChild("CarManager")
cm = orig:Clone()
cm.Parent = orig.Parent
CarManager = require(cm)
assert(typeof(CarManager._buildForDiag) == "function", "_buildForDiag is " .. typeof(CarManager._buildForDiag))
assert(typeof(Chassis.tuningFor) == "function", "tuningFor is " .. typeof(Chassis.tuningFor))
assert(typeof(Cars.Get) == "function", "Cars.Get is " .. typeof(Cars.Get))
end)
-- ------------------------------------------------- stage 1: template roots
stage("template root pick", function()
log("")
log("=== TEMPLATE: what does line 589 pick as root? ===")
log(string.format("%-12s %-5s %-18s %8s %7s", "car", "grp", "root picked", "offX", "nParts"))
for _, t in ipairs(ReplicatedStorage.CarModels:GetChildren()) do
local wg = t:FindFirstChild("Wheels")
if wg then
for _, w in ipairs(wg:GetChildren()) do
local root = w:IsA("BasePart") and w or w:FindFirstChildWhichIsA("BasePart", true)
local parts = {}
if w:IsA("BasePart") then
parts[1] = w
end
for _, d in ipairs(w:GetDescendants()) do
if d:IsA("BasePart") then
parts[#parts + 1] = d
end
end
if root and #parts > 0 then
local lo, hi = parts[1].Position, parts[1].Position
for _, p in ipairs(parts) do
lo = Vector3.new(
math.min(lo.X, p.Position.X),
math.min(lo.Y, p.Position.Y),
math.min(lo.Z, p.Position.Z)
)
hi = Vector3.new(
math.max(hi.X, p.Position.X),
math.max(hi.Y, p.Position.Y),
math.max(hi.Z, p.Position.Z)
)
end
local centre = (lo + hi) / 2
log(
string.format(
"%-12s %-5s %-18s %8.3f %7d",
t.Name,
w.Name,
root.Name,
math.abs(root.Position.X - centre.X),
#parts
)
)
end
end
end
end
end)
-- ------------------------------------------------- stage 2: built cars
stage("built car check", function()
log("")
log("=== BUILT: tyre offset from its physics cylinder + stray welds ===")
log(string.format("%-12s %-5s %9s %s", "car", "grp", "tyreErrX", "welds to OUTSIDE the group"))
for _, t in ipairs(ReplicatedStorage.CarModels:GetChildren()) do
local car = Cars.Get(t.Name)
if car then
local m = CarManager._buildForDiag(car, Chassis.tuningFor(car))
m.Parent = workspace
m:PivotTo(CFrame.new(0, 5010, 0))
for _ = 1, 4 do
RunService.Heartbeat:Wait()
end
local body = m.PrimaryPart
local shell = m:FindFirstChild("Shell")
local wg = shell and shell:FindFirstChild("Wheels")
if wg and body then
local inv = body.CFrame:Inverse()
for _, w in ipairs(wg:GetChildren()) do
local physName = "Wheel_" .. w.Name:upper()
local phys = m:FindFirstChild(physName)
local group, inGroup = {}, {}
if w:IsA("BasePart") then
group[1], inGroup[w] = w, true
end
for _, d in ipairs(w:GetDescendants()) do
if d:IsA("BasePart") then
group[#group + 1] = d
inGroup[d] = true
end
end
if phys and #group > 0 then
local physX = (inv * phys.Position).X
local best, bestV = group[1], -1
for _, p in ipairs(group) do
local v = p.Size.X * p.Size.Y * p.Size.Z
if v > bestV then
best, bestV = p, v
end
end
local errX = (inv * best.Position).X - physX
local bad = {}
for _, c in ipairs(m:GetDescendants()) do
if c:IsA("WeldConstraint") or c:IsA("Weld") then
local a, b = c.Part0, c.Part1
local aIn = (a ~= nil) and inGroup[a] or false
local bIn = (b ~= nil) and inGroup[b] or false
if (aIn or bIn) and not (aIn and bIn) then
local other = aIn and b or a
local oname = other and other.Name or "nil"
if oname ~= physName then
bad[#bad + 1] = oname
end
end
end
end
log(
string.format(
"%-12s %-5s %9.3f %s",
t.Name,
w.Name,
errX,
#bad > 0 and table.concat(bad, ", ") or "-none-"
)
)
end
end
end
m:Destroy()
end
end
end)
if cm then
cm:Destroy()
end
return table.concat(out, "\n")