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
+185
View File
@@ -0,0 +1,185 @@
--[[
verify_fixes.luau -- build all five cars with the NEWLY PUSHED code and
measure whether the two fixes actually work. Runs in the EDIT datamodel,
where require() is fresh (no Play-session cache pin), so this is the first
honest test of these fixes.
Checks, per car:
FIX 1 -- FACING (hatch_junk, hyper_x rendered backwards)
Compare mean Z of F* wheel groups vs R* groups in the model's own frame.
Chassis convention: front axle is built at NEGATIVE Z. So frontZ < rearZ
means the car faces the right way. hatch_junk / hyper_x previously came
out reversed because their shell wheel LABELS are swapped, which fooled
the auto-solver into a 180 degree rotation; SHELL_YAW_OVERRIDE pins them
to yaw 0.
FIX 2 -- WHEEL STANCE (rx7_fc wheels protruding from the bodywork)
For each wheel, measure |X| of the wheel's visual centre against |X| of
the axle it hangs from. The old code picked an arbitrary BasePart as the
wheel root (often a rotor/caliper ~0.96 studs inboard of the tyre) and
made THAT concentric with the axle, shoving the tyre outboard by the
difference. Now it picks the largest-volume part (the tyre). Residual
offset should be near zero; anything > 0.35 studs is a visible protrusion.
Everything is measured from the built model, not inferred from source.
Models are destroyed afterwards so Edit is left clean.
]]
local ServerScriptService = game:GetService("ServerScriptService")
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 serverFolder = ServerScriptService:FindFirstChild("Server", true)
local cmMod = serverFolder and serverFolder:FindFirstChild("CarManager")
if not cmMod then
return "FATAL: no CarManager module found"
end
log(
string.format(
"CarManager source: %d bytes, SHELL_YAW_OVERRIDE=%s",
#cmMod.Source,
tostring(cmMod.Source:find("SHELL_YAW_OVERRIDE", 1, true) ~= nil)
)
)
local okCM, CarManager = pcall(require, cmMod)
if not okCM then
return "FATAL: require(CarManager) failed: " .. tostring(CarManager)
end
if typeof(CarManager._buildForDiag) ~= "function" then
return "FATAL: _buildForDiag is "
.. typeof(CarManager._buildForDiag)
.. " -- require() served STALE code, results would be meaningless"
end
log("_buildForDiag present -> NEW code is genuinely running")
-- find Cars + Tuning modules
local function findModule(name)
for _, svc in ipairs({ game:GetService("ReplicatedStorage"), ServerScriptService }) do
local m = svc:FindFirstChild(name, true)
if m and m:IsA("ModuleScript") then
return m
end
end
return nil
end
local carsMod = findModule("Cars")
local chassisMod = findModule("Chassis")
if not carsMod then
return "FATAL: Cars module not found"
end
if not chassisMod then
return "FATAL: Chassis module not found (needed for tuningFor)"
end
local Cars = require(carsMod)
local Chassis = require(chassisMod)
if typeof(Chassis.tuningFor) ~= "function" then
return "FATAL: Chassis.tuningFor is " .. typeof(Chassis.tuningFor)
end
local FRONT_NEG_Z = true -- chassis builds front axle at -Z
local PROTRUDE_TOL = 0.35
log("")
log(string.format("%-10s %8s %8s %-12s | %8s %-10s", "car", "frontZ", "rearZ", "FACING", "maxOff", "STANCE"))
log(string.rep("-", 74))
local built = {}
local anyFail = false
local carList = Cars.List or Cars.All
if typeof(carList) ~= "table" or #carList == 0 then
return "FATAL: could not find a non-empty car list (Cars.List). " .. "Refusing to report a vacuous pass."
end
log(string.format("car list: %d entries", #carList))
for _, car in ipairs(carList) do
if typeof(car) == "table" and car.Id then
local tuning = Chassis.tuningFor(car)
local ok, model = pcall(CarManager._buildForDiag, car, tuning)
if not ok or typeof(model) ~= "Instance" then
log(string.format("%-10s BUILD FAILED: %s", car.Id, tostring(model)))
anyFail = true
else
model.Parent = workspace
built[#built + 1] = model
local pivotInv = model:GetPivot():Inverse()
-- ---- FACING: mean Z of front vs rear wheel groups
local fS, fN, rS, rN = 0, 0, 0, 0
-- ---- STANCE: wheel centre |X| vs its axle |X|
local maxOff = 0
for _, d in ipairs(model:GetDescendants()) do
if d:IsA("BasePart") and d.Name:match("^Wheel_") then
local lbl = d.Name:sub(7, 7):upper()
local z = (pivotInv * d.CFrame).Z
if lbl == "F" then
fS, fN = fS + z, fN + 1
elseif lbl == "R" then
rS, rN = rS + z, rN + 1
end
-- visual tyre centre = centroid of the attached shell parts
local axleX = (pivotInv * d.CFrame).X
local sum, n = Vector3.zero, 0
for _, c in ipairs(d:GetDescendants()) do
if c:IsA("BasePart") then
sum, n = sum + c.Position, n + 1
end
end
if n > 0 then
local visX = (pivotInv * CFrame.new(sum / n)).X
local off = math.abs(math.abs(visX) - math.abs(axleX))
if off > maxOff then
maxOff = off
end
end
end
end
local facing, stance = "n/a", "n/a"
if fN > 0 and rN > 0 then
local fz, rz = fS / fN, rS / rN
local good = FRONT_NEG_Z and (fz < rz) or (fz > rz)
facing = good and "OK" or "BACKWARDS"
if not good then
anyFail = true
end
stance = (maxOff <= PROTRUDE_TOL) and "OK" or "PROTRUDING"
if maxOff > PROTRUDE_TOL then
anyFail = true
end
log(string.format("%-10s %8.2f %8.2f %-12s | %8.3f %-10s", car.Id, fz, rz, facing, maxOff, stance))
else
log(string.format("%-10s (no Wheel_* parts found)", car.Id))
anyFail = true
end
end
end
end
for _, m in ipairs(built) do
m:Destroy()
end
local tested = #built
log("")
if tested == 0 then
log(">>> NOTHING WAS TESTED -- no cars built. This is a FAILURE, not a pass.")
elseif anyFail then
log(string.format(">>> SOME CHECKS FAILED (%d cars tested)", tested))
else
log(string.format(">>> ALL CHECKS PASSED (%d cars tested)", tested))
end
return table.concat(out, "\n")