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:
@@ -0,0 +1,109 @@
|
||||
--[[
|
||||
diag_shellbuilt.luau -- does the solved yaw actually reach the built car?
|
||||
|
||||
diag_shellyaw2 proved the aligner SEES the problem: hatch_junk and hyper_x
|
||||
are authored nose-toward +Z and solve to yaw ~180, the other three to ~0.
|
||||
That is exactly the "at least two cars are backwards" the user reports, so
|
||||
the cue is right and the question is whether the rotation survives to the
|
||||
built model.
|
||||
|
||||
The earlier attempt measured -11.80 for every car -- that is the CHASSIS
|
||||
wheelbase, i.e. it matched the chassis Wheel_* parts, not the shell's own
|
||||
Wheels folder. This one scopes the search strictly INSIDE the Shell model
|
||||
and skips anything named Wheel_* (the chassis convention), so it can only
|
||||
ever read shell wheels.
|
||||
]]
|
||||
|
||||
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 Shared = ReplicatedStorage:FindFirstChild("Shared")
|
||||
local Cars = require(Shared.Cars)
|
||||
local Chassis = require(Shared.Chassis)
|
||||
|
||||
local orig = ServerScriptService:FindFirstChild("Server", true):FindFirstChild("CarManager")
|
||||
local clone = orig:Clone()
|
||||
clone.Parent = orig.Parent
|
||||
local CarManager = require(clone)
|
||||
|
||||
local pad = Instance.new("Part")
|
||||
pad.Size = Vector3.new(400, 8, 400)
|
||||
pad.Position = Vector3.new(0, 5000, 0)
|
||||
pad.Anchored = true
|
||||
pad.Parent = workspace
|
||||
|
||||
log("chassis forward = -Z. Shell nose must land at NEGATIVE body-local Z.")
|
||||
log("")
|
||||
|
||||
for _, template in ipairs(ReplicatedStorage.CarModels:GetChildren()) do
|
||||
local id = template.Name
|
||||
local car = Cars.Get(id)
|
||||
if not car then
|
||||
log(string.format("%-14s <no car def for this shell id>", id))
|
||||
else
|
||||
local model = CarManager._buildForDiag(car, Chassis.tuningFor(car))
|
||||
model.Parent = workspace
|
||||
model:PivotTo(CFrame.new(0, 5010, 0))
|
||||
for _ = 1, 5 do
|
||||
RunService.Heartbeat:Wait()
|
||||
end
|
||||
|
||||
local body = model.PrimaryPart
|
||||
local shell = model:FindFirstChild("Shell")
|
||||
if not shell then
|
||||
log(string.format("%-14s <no Shell child -- using procedural CarBody>", id))
|
||||
else
|
||||
local inv = body.CFrame:Inverse()
|
||||
-- Only look at wheels INSIDE the shell, and never at chassis Wheel_*.
|
||||
local wf = shell:FindFirstChild("Wheels")
|
||||
local fSum, fN, rSum, rN = Vector3.zero, 0, Vector3.zero, 0
|
||||
if wf then
|
||||
for _, w in ipairs(wf:GetChildren()) do
|
||||
if w.Name:sub(1, 6) ~= "Wheel_" then
|
||||
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 = inv * 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
|
||||
end
|
||||
end
|
||||
if fN > 0 and rN > 0 then
|
||||
local f, r = fSum / fN, rSum / rN
|
||||
local dz = f.Z - r.Z
|
||||
log(
|
||||
string.format(
|
||||
"%-14s shell wheels: frontZ %+6.2f rearZ %+6.2f dZ %+6.2f -> %s",
|
||||
id,
|
||||
f.Z,
|
||||
r.Z,
|
||||
dz,
|
||||
dz < 0 and "CORRECT" or "*** STILL BACKWARDS ***"
|
||||
)
|
||||
)
|
||||
else
|
||||
log(string.format("%-14s <shell has no usable F/R wheels after build (F=%d R=%d)>", id, fN, rN))
|
||||
end
|
||||
end
|
||||
model:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
pad:Destroy()
|
||||
clone:Destroy()
|
||||
return table.concat(out, "\n")
|
||||
Reference in New Issue
Block a user