--[[ diag_builtnose.luau -- END-TO-END measurement. Build each car for real via CarManager._buildForDiag, then measure where the finished shell's nose actually points relative to the chassis forward axis. Why this and not more code reading: the solver computes the right 180-degree yaw (diag_solveryaw) and applies it without centring error (diag_centrefix), yet two cars still look backwards. So something AFTER the PivotTo must be undoing it. Rather than guess which line, measure the finished article. noseDot = (shell nose direction) dot (body LookVector) +1 -> shell nose points where the car drives (CORRECT) -1 -> shell nose points backwards (REVERSED) Cache guard first: require() caches per Studio session, so a stale CarManager would silently build old code and make this whole test a lie. ]] local RS = game:GetService("ReplicatedStorage") local SSS = game:GetService("ServerScriptService") local out = {} local function log(s) table.insert(out, s) end local function find(name) for _, root in ipairs({ SSS, RS, game:GetService("ServerStorage"), workspace }) do local m = root:FindFirstChild(name, true) if m and m:IsA("ModuleScript") then return m end end return nil end local cmMod = find("CarManager") if not cmMod then return "FATAL: CarManager not found" end -- Guard: the reverted source must be what require() hands back. local srcOK = cmMod.Source:find("isFront = zSign < 0", 1, true) ~= nil if not srcOK then return "FATAL: CarManager source is not the reverted version -- aborting" end local ok, CM = pcall(require, cmMod) if not ok then return "FATAL: require(CarManager) failed: " .. tostring(CM) end if type(CM._buildForDiag) ~= "function" then return "FATAL: CarManager._buildForDiag missing (stale require cache?) -- restart Studio" end local Cars = require(RS:WaitForChild("Shared"):WaitForChild("Cars")) local ChassisMod = require(RS:WaitForChild("Shared"):WaitForChild("Chassis")) local TARGETS = { "rx7_fc", "silv_s15", "gtr_r34", "hatch_junk", "hyper_x" } log(string.format("%-11s %-10s %-12s %s", "shell", "noseDot", "yaw err", "verdict")) log(string.rep("-", 62)) local built = 0 for _, name in ipairs(TARGETS) do -- buildCarModel(car: Car, tuning: Tuning) -- NOT a string id. Passing a -- string was the harness bug that produced the CarManager:277 nil error. local carDef = Cars.Get(name) if not carDef then log(string.format("%-11s NOT IN Cars.List", name)) continue end local tuning = ChassisMod.tuningFor(carDef) local okB, car = pcall(CM._buildForDiag, carDef, tuning) if not okB or not car then log(string.format("%-11s BUILD FAILED: %s", name, tostring(car))) continue end built += 1 local body = car:FindFirstChild("Body") or car.PrimaryPart local shell = nil for _, d in ipairs(car:GetChildren()) do if d:IsA("Model") and d:FindFirstChild("Wheels") then shell = d break end end if not body or not shell then log(string.format("%-11s no body/shell on built car", name)) car:Destroy() continue end -- Shell nose in WORLD space, from the shell's own wheel labels. local wf = shell:FindFirstChild("Wheels") local fSum, fN, rSum, rN = Vector3.zero, 0, Vector3.zero, 0 for _, w in ipairs(wf:GetChildren()) do local sum, n = Vector3.zero, 0 if w:IsA("BasePart") then sum, n = w.Position, 1 end for _, d in ipairs(w:GetDescendants()) do if d:IsA("BasePart") then sum, n = sum + d.Position, n + 1 end end if n > 0 then local h = w.Name:sub(1, 1):upper() if h == "F" then fSum, fN = fSum + (sum / n), fN + 1 elseif h == "R" then rSum, rN = rSum + (sum / n), rN + 1 end end end if fN == 0 or rN == 0 then log(string.format("%-11s no F/R labels on built shell", name)) car:Destroy() continue end local nose = (fSum / fN) - (rSum / rN) nose = Vector3.new(nose.X, 0, nose.Z) if nose.Magnitude < 0.01 then log(string.format("%-11s degenerate nose vector", name)) car:Destroy() continue end nose = nose.Unit local fwd = body.CFrame.LookVector fwd = Vector3.new(fwd.X, 0, fwd.Z).Unit local dot = nose:Dot(fwd) local yawErr = math.deg(math.acos(math.clamp(dot, -1, 1))) local verdict if dot > 0.85 then verdict = "CORRECT (nose = drive dir)" elseif dot < -0.85 then verdict = "*** REVERSED ***" else verdict = "skewed" end log( string.format( "%-11s %-10s %-12s %s", name, string.format("%+.3f", dot), string.format("%.1f deg", yawErr), verdict ) ) car:Destroy() end log("") if built == 0 then log(">>> NOTHING BUILT -- this is a FAILURE, not a pass.") else log(string.format(">>> built and measured %d/5 cars, then destroyed them (no scene changes)", built)) log(" This is the finished article, after every stage of the build pipeline.") end return table.concat(out, "\n")