Real car meshes + physics-derived suspension + inPA/void fixes
CI / quality (push) Failing after 56s
CI / quality (push) Failing after 56s
Car meshes: - CarManager: clone ReplicatedStorage/CarModels/<carId> as a visual Shell, weld to Body, hide placeholder blocks. Falls back to procedural CarBody when no mesh exists, so cars can be converted one at a time. - Shell parts are Massless/CanCollide=false/CanQuery=false: the constraint chassis and driving feel are untouched. Verified 0 violating parts live. - 5 catalogue cars mapped from the 67-model ServerStorage/CarLibrary import. Suspension (ref docs/CAR_PHYSICS_REFERENCE.txt, devforum 3915628): - BUG: old k=9000 gave 1.10 studs static sag against 0.90 studs total travel, i.e. the suspension sat permanently bottomed out and the spring did no work. - Stiffness now solved from a sag target (70%% of half travel); damping now derived as a damping ratio c = zeta*2*sqrt(k*m) instead of an unrelated constant. Old pair worked out to zeta=0.31 (floaty); now 0.55-0.63. - Measured after fix: ride height 1.97 studs, bounce 0.000, body roll 0.002. Also: Circuit.inPA square test (PAFloor is 520x520, test was a r=260 circle, corners falsely reported outside and spuriously armed runs), and void-fall recovery now moves the character to the spawn pad BEFORE building the car.
This commit is contained in:
@@ -323,6 +323,64 @@ local function buildPA(map: Folder)
|
||||
})
|
||||
ramp.Parent = pa
|
||||
|
||||
-- PERIMETER BARRIERS: the PA floor is a 520x520 slab floating ~46 studs up
|
||||
-- with nothing at its edges. Endurance testing drove straight off the side
|
||||
-- and fell past FallenPartsDestroyHeight (-500), destroying the car and
|
||||
-- stranding the player seatless until the death/respawn cycle caught it.
|
||||
-- Wall every edge, leaving a gap on the side the ramp exits through so the
|
||||
-- route to the expressway stays open.
|
||||
do
|
||||
local rampDir = Vector3.new(road.X - c.X, 0, road.Z - c.Z)
|
||||
-- Which edge does the ramp leave from? Whichever axis dominates.
|
||||
local rampOnX = math.abs(rampDir.X) > math.abs(rampDir.Z)
|
||||
local rampSign = rampOnX and math.sign(rampDir.X) or math.sign(rampDir.Z)
|
||||
local GAP = 70 -- half-width of the opening (ramp is 46 wide)
|
||||
local H, T = 14, 4
|
||||
|
||||
local function wall(name, size, pos)
|
||||
local w = part({
|
||||
Name = name,
|
||||
Size = size,
|
||||
CFrame = CFrame.new(pos),
|
||||
Color = Color3.fromRGB(96, 96, 104),
|
||||
Material = Enum.Material.Concrete,
|
||||
})
|
||||
w.Parent = pa
|
||||
end
|
||||
|
||||
-- Four edges. On the ramp's edge, build two stubs flanking the opening.
|
||||
local edges = {
|
||||
{ onX = true, sign = 1 },
|
||||
{ onX = true, sign = -1 },
|
||||
{ onX = false, sign = 1 },
|
||||
{ onX = false, sign = -1 },
|
||||
}
|
||||
for _, e in ipairs(edges) do
|
||||
local isRampEdge = (e.onX == rampOnX) and (e.sign == rampSign)
|
||||
-- Offset along the edge normal; span the full slab on the other axis.
|
||||
local normal = e.onX and Vector3.new(e.sign * R, 0, 0) or Vector3.new(0, 0, e.sign * R)
|
||||
local base = c + normal + Vector3.new(0, H / 2, 0)
|
||||
local fullSize = e.onX and Vector3.new(T, H, R * 2) or Vector3.new(R * 2, H, T)
|
||||
if not isRampEdge then
|
||||
wall("PAWall", fullSize, base)
|
||||
else
|
||||
-- two stubs, each running from the corner in to the gap edge
|
||||
local stubLen = R - GAP
|
||||
if stubLen > 4 then
|
||||
local half = stubLen / 2
|
||||
local off = GAP + half
|
||||
if e.onX then
|
||||
wall("PAWall", Vector3.new(T, H, stubLen), base + Vector3.new(0, 0, off))
|
||||
wall("PAWall", Vector3.new(T, H, stubLen), base + Vector3.new(0, 0, -off))
|
||||
else
|
||||
wall("PAWall", Vector3.new(stubLen, H, T), base + Vector3.new(off, 0, 0))
|
||||
wall("PAWall", Vector3.new(stubLen, H, T), base + Vector3.new(-off, 0, 0))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local pad = part({
|
||||
Name = "SpawnPad",
|
||||
Size = Vector3.new(120, 2.4, 120),
|
||||
|
||||
Reference in New Issue
Block a user