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
+161
View File
@@ -0,0 +1,161 @@
--[[
verify_convention.luau -- prove the forward convention is now consistent.
Deliberately NOT measuring anything derived from a constant. The previous
harness read Wheel_* positions, which come straight from
Chassis.WHEELBASE_HALF (5.9) -- identical for every car whether or not any
fix applied, so it passed vacuously. Here every assertion is a RELATIONSHIP
that genuinely differs between the broken and fixed builds:
1. The steering servo must sit on the axle that LEADS under throttle.
Broken build: servos on the trailing axle (shopping-cart caster).
2. The shell nose must point the same way the seat drives.
Broken build: 180 degrees opposed.
3. DRIVE_SIGN must spin the wheels toward the direction of travel.
Builds each car via the real path (Chassis.tuningFor + _buildForDiag) in
the Edit datamodel, where require() is fresh.
]]
local SSS = game:GetService("ServerScriptService")
local RS = game:GetService("ReplicatedStorage")
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 findModule(name: string): ModuleScript?
for _, root in ipairs({ SSS, RS }) do
local hit = root:FindFirstChild(name, true)
if hit and hit:IsA("ModuleScript") then
return hit
end
end
return nil
end
local cmMod = findModule("CarManager")
local carsMod = findModule("Cars")
local chassisMod = findModule("Chassis")
if not (cmMod and carsMod and chassisMod) then
return "FATAL: missing module(s)"
end
local CarManager = require(cmMod)
local Cars = require(carsMod)
local Chassis = require(chassisMod)
if typeof(CarManager._buildForDiag) ~= "function" then
return "FATAL: _buildForDiag absent -- stale CarManager, refusing to report"
end
log(string.format("Chassis.DRIVE_SIGN = %s", tostring(Chassis.DRIVE_SIGN)))
log("")
local carList = Cars.List or Cars.All
if typeof(carList) ~= "table" or #carList == 0 then
return "FATAL: empty car list"
end
log(string.format("%-11s %-22s %-24s %s", "car", "steered axle", "shell nose vs drive", "verdict"))
log(string.rep("-", 78))
local tested, failed = 0, 0
for _, car in ipairs(carList) do
if typeof(car) ~= "table" or not car.Id then
continue
end
local tuning = Chassis.tuningFor(car)
local ok, model = pcall(CarManager._buildForDiag, car, tuning)
if not ok or typeof(model) ~= "Instance" then
log(string.format("%-11s BUILD FAILED: %s", car.Id, tostring(model)))
failed += 1
continue
end
local body = model:FindFirstChild("Body")
local seat
for _, d in ipairs(model:GetDescendants()) do
if d:IsA("VehicleSeat") then
seat = d
break
end
end
if not (body and body:IsA("BasePart") and seat) then
log(string.format("%-11s NO BODY/SEAT", car.Id))
failed += 1
model:Destroy()
continue
end
tested += 1
local inv = body.CFrame:Inverse()
-- Direction of travel under positive throttle, in body-local space.
local driveZ = inv:VectorToObjectSpace(seat.CFrame.LookVector).Z
local drivePos = driveZ > 0
-- (1) Which axle carries the steering servos?
local servoZ, servoN = 0, 0
for _, d in ipairs(model:GetDescendants()) do
if d:IsA("HingeConstraint") and d.ActuatorType == Enum.ActuatorType.Servo then
local host = d.Parent
if host and host:IsA("BasePart") then
servoZ += (inv * host.CFrame).Z
servoN += 1
end
end
end
local steerLeads, steerTxt = false, "no servos"
if servoN > 0 then
local sm = servoZ / servoN
steerLeads = (drivePos and sm > 0) or (not drivePos and sm < 0)
steerTxt = string.format("z=%+.2f %s", sm, steerLeads and "LEADS" or "TRAILS")
end
-- (2) Shell nose vs direction of travel.
local shell
for _, c in ipairs(model:GetChildren()) do
if c:IsA("Model") then
shell = c
break
end
end
local shellOk, shellTxt = true, "no shell"
if shell then
local shellLook = shell:GetPivot().LookVector
local seatLook = seat.CFrame.LookVector
local a = Vector3.new(shellLook.X, 0, shellLook.Z)
local b = Vector3.new(seatLook.X, 0, seatLook.Z)
if a.Magnitude > 1e-4 and b.Magnitude > 1e-4 then
local deg = math.deg(math.acos(math.clamp(a.Unit:Dot(b.Unit), -1, 1)))
shellOk = deg < 30
shellTxt = string.format("%.1f deg %s", deg, shellOk and "OK" or "FLIPPED")
end
end
local pass = (servoN == 0 or steerLeads) and shellOk
if not pass then
failed += 1
end
log(string.format("%-11s %-22s %-24s %s", car.Id, steerTxt, shellTxt, pass and "PASS" or "FAIL"))
model:Destroy()
end
log("")
if tested == 0 then
log(">>> NOTHING TESTED -- this is a FAILURE, not a pass.")
elseif failed > 0 then
log(string.format(">>> %d/%d FAILED", failed, tested))
else
log(string.format(">>> ALL %d CARS PASS: steered axle leads, shell faces travel", tested))
end
return table.concat(out, "\n")