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.
This commit is contained in:
2026-08-02 15:56:13 -04:00
parent 8808b919c3
commit c8dabea53a
51 changed files with 6558 additions and 65 deletions
+167
View File
@@ -0,0 +1,167 @@
--[[
diag_builtnose.luau -- END-TO-END measurement. Build each car for real via
CarManager._buildForDiag, then measure where the finished shell's nose
actually points relative to the chassis forward axis.
Why this and not more code reading: the solver computes the right 180-degree
yaw (diag_solveryaw) and applies it without centring error (diag_centrefix),
yet two cars still look backwards. So something AFTER the PivotTo must be
undoing it. Rather than guess which line, measure the finished article.
noseDot = (shell nose direction) dot (body LookVector)
+1 -> shell nose points where the car drives (CORRECT)
-1 -> shell nose points backwards (REVERSED)
Cache guard first: require() caches per Studio session, so a stale
CarManager would silently build old code and make this whole test a lie.
]]
local RS = game:GetService("ReplicatedStorage")
local SSS = game:GetService("ServerScriptService")
local out = {}
local function log(s)
table.insert(out, s)
end
local function find(name)
for _, root in ipairs({ SSS, RS, game:GetService("ServerStorage"), workspace }) do
local m = root:FindFirstChild(name, true)
if m and m:IsA("ModuleScript") then
return m
end
end
return nil
end
local cmMod = find("CarManager")
if not cmMod then
return "FATAL: CarManager not found"
end
-- Guard: the reverted source must be what require() hands back.
local srcOK = cmMod.Source:find("isFront = zSign < 0", 1, true) ~= nil
if not srcOK then
return "FATAL: CarManager source is not the reverted version -- aborting"
end
local ok, CM = pcall(require, cmMod)
if not ok then
return "FATAL: require(CarManager) failed: " .. tostring(CM)
end
if type(CM._buildForDiag) ~= "function" then
return "FATAL: CarManager._buildForDiag missing (stale require cache?) -- restart Studio"
end
local Cars = require(RS:WaitForChild("Shared"):WaitForChild("Cars"))
local ChassisMod = require(RS:WaitForChild("Shared"):WaitForChild("Chassis"))
local TARGETS = { "rx7_fc", "silv_s15", "gtr_r34", "hatch_junk", "hyper_x" }
log(string.format("%-11s %-10s %-12s %s", "shell", "noseDot", "yaw err", "verdict"))
log(string.rep("-", 62))
local built = 0
for _, name in ipairs(TARGETS) do
-- buildCarModel(car: Car, tuning: Tuning) -- NOT a string id. Passing a
-- string was the harness bug that produced the CarManager:277 nil error.
local carDef = Cars.Get(name)
if not carDef then
log(string.format("%-11s NOT IN Cars.List", name))
continue
end
local tuning = ChassisMod.tuningFor(carDef)
local okB, car = pcall(CM._buildForDiag, carDef, tuning)
if not okB or not car then
log(string.format("%-11s BUILD FAILED: %s", name, tostring(car)))
continue
end
built += 1
local body = car:FindFirstChild("Body") or car.PrimaryPart
local shell = nil
for _, d in ipairs(car:GetChildren()) do
if d:IsA("Model") and d:FindFirstChild("Wheels") then
shell = d
break
end
end
if not body or not shell then
log(string.format("%-11s no body/shell on built car", name))
car:Destroy()
continue
end
-- Shell nose in WORLD space, from the shell's own wheel labels.
local wf = shell:FindFirstChild("Wheels")
local fSum, fN, rSum, rN = Vector3.zero, 0, Vector3.zero, 0
for _, w in ipairs(wf:GetChildren()) do
local sum, n = Vector3.zero, 0
if w:IsA("BasePart") then
sum, n = w.Position, 1
end
for _, d in ipairs(w:GetDescendants()) do
if d:IsA("BasePart") then
sum, n = sum + d.Position, n + 1
end
end
if n > 0 then
local h = w.Name:sub(1, 1):upper()
if h == "F" then
fSum, fN = fSum + (sum / n), fN + 1
elseif h == "R" then
rSum, rN = rSum + (sum / n), rN + 1
end
end
end
if fN == 0 or rN == 0 then
log(string.format("%-11s no F/R labels on built shell", name))
car:Destroy()
continue
end
local nose = (fSum / fN) - (rSum / rN)
nose = Vector3.new(nose.X, 0, nose.Z)
if nose.Magnitude < 0.01 then
log(string.format("%-11s degenerate nose vector", name))
car:Destroy()
continue
end
nose = nose.Unit
local fwd = body.CFrame.LookVector
fwd = Vector3.new(fwd.X, 0, fwd.Z).Unit
local dot = nose:Dot(fwd)
local yawErr = math.deg(math.acos(math.clamp(dot, -1, 1)))
local verdict
if dot > 0.85 then
verdict = "CORRECT (nose = drive dir)"
elseif dot < -0.85 then
verdict = "*** REVERSED ***"
else
verdict = "skewed"
end
log(
string.format(
"%-11s %-10s %-12s %s",
name,
string.format("%+.3f", dot),
string.format("%.1f deg", yawErr),
verdict
)
)
car:Destroy()
end
log("")
if built == 0 then
log(">>> NOTHING BUILT -- this is a FAILURE, not a pass.")
else
log(string.format(">>> built and measured %d/5 cars, then destroyed them (no scene changes)", built))
log(" This is the finished article, after every stage of the build pipeline.")
end
return table.concat(out, "\n")