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

96 lines
2.7 KiB
Luau

--[[
diag_shellyaw2.luau -- corrected. The first attempt looked in the wrong
place (CarShells/Shells/Cars) and then measured the CHASSIS wheels, so it
reported an identical -11.80 wheelbase for every car and proved nothing.
Shells actually live in ReplicatedStorage.CarModels[car.Id] (CarManager
line 347). This inspects those templates directly and reports the exact
cue the auto-aligner uses, plus the resulting yaw.
]]
local ReplicatedStorage = 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 models = ReplicatedStorage:FindFirstChild("CarModels")
if not models then
log("ReplicatedStorage.CarModels: MISSING -> every car uses the procedural")
log("CarBody shell, which is authored nose-toward -Z and cannot be backwards.")
return table.concat(out, "\n")
end
log("ReplicatedStorage.CarModels children:")
for _, t in ipairs(models:GetChildren()) do
log(string.format(" %-14s (%s)", t.Name, t.ClassName))
end
log("")
for _, template in ipairs(models:GetChildren()) do
if template:IsA("Model") then
local wf = template:FindFirstChild("Wheels")
if not wf then
log(
string.format(
"%-14s Wheels folder MISSING -> shellYaw = 0 (fails soft, keeps authored yaw)",
template.Name
)
)
else
local pivotInv = template:GetPivot():Inverse()
local fSum, fN, rSum, rN = Vector3.zero, 0, Vector3.zero, 0
local names = {}
for _, w in ipairs(wf:GetChildren()) do
table.insert(names, w.Name)
local part = w:IsA("BasePart") and w or w:FindFirstChildWhichIsA("BasePart", true)
if part then
local h = w.Name:sub(1, 1):upper()
local lp = pivotInv * part.Position
if h == "F" then
fSum, fN = fSum + lp, fN + 1
elseif h == "R" then
rSum, rN = rSum + lp, rN + 1
end
end
end
if fN > 0 and rN > 0 then
local nose = (fSum / fN) - (rSum / rN)
local usable = (math.abs(nose.X) + math.abs(nose.Z)) > 0.05
local yaw = usable and -math.atan2(nose.X, -nose.Z) or 0
log(
string.format(
"%-14s [%s] F=%d R=%d nose=(%.2f,%.2f,%.2f) -> yaw %+.1f deg %s",
template.Name,
table.concat(names, ","),
fN,
rN,
nose.X,
nose.Y,
nose.Z,
math.deg(yaw),
usable and "" or "*** DEGENERATE -> yaw 0 ***"
)
)
else
log(
string.format(
"%-14s [%s] F=%d R=%d -> *** NO F/R CUE, shellYaw = 0, stays as authored ***",
template.Name,
table.concat(names, ","),
fN,
rN
)
)
end
end
end
end
return table.concat(out, "\n")