here is the full script but be careful. There’s something I’m too lazy to remove:
-- Variables
local char = script.Parent
local humanoid = char:FindFirstChildOfClass("Humanoid")
local debounce = false
-- Customization and settings
local WheelPositions = {
FL = Vector3.new(-3.5, 0, -5),
FR = Vector3.new(3.5, 0, -5),
RL = Vector3.new(-3.5, 0, 5),
RR = Vector3.new(3.5, 0, 5)
}
local SpringLengthMemory = {}
for i, v in pairs(WheelPositions) do
SpringLengthMemory[i] = 0.5
end
local SuspensionMaxLength = 2
local wheelRadius = 1.25
local stiffness = 120
local damper = 5
local wheelFriction = 5
local torque = 20
local maxSpeed = 220
local steerAngle = 35
local smoothSteer = 0.2
-- UI and Visibility
local customFOV = false -- in case you wants the FOV moves with car velocity(.Magnitude)
local currentcamera = workspace.CurrentCamera
local Gauges = game.Players.LocalPlayer.PlayerGui.Gauges
local datunit = "SPS"
local showCircleOnSpeedo = true
-- Player Settings and Configuration
local makePlayerCharacterMassless = true
-- Sounds
local dynamicVolume = false
local Gears = {
Gear = 1
}
local volume = 0.5
-- End Of Variables | Scripting
local function enableJumpButton()
if humanoid then
humanoid.JumpPower = 50
end
end
local function disableJumpButton()
if humanoid then
humanoid.JumpPower = 0
end
end
humanoid.Seated:Connect(function(seated, seatPart)
if seated and seatPart then
if seatPart.Parent.Name == "CarModel" and seatPart:IsA("VehicleSeat") then
local carModel = seatPart.Parent
local carPrim = carModel.PrimaryPart
local serverTakeOverWait = 0
Gauges.Enabled = true
print("Play")
seatPart.Idle.Playing = true
while true do
local delta = game["Run Service"].Heartbeat:Wait()
-- UI Visualization and sounds
local function getCarSpeed()
return math.abs(carPrim.CFrame:vectorToObjectSpace(carPrim.Velocity).Z)
end
local carSpeed = getCarSpeed()
local function GearRatio(num)
return 0.014 * (32/game.Workspace.Gravity)^0.5 / (0.2 * num + 0.08)
end
local Gear = 1
local GearModifier = 0.2
local PitchModifier = 0.7
local rawPitch = carSpeed * GearRatio(Gear + GearModifier)
local ShiftUp = 1.5
local ShiftDown = 0.85
local pitchMaxDelta = 0.8 * delta
if rawPitch > ShiftUp then
Gear = Gear + 1
elseif rawPitch < ShiftDown and Gear > 1 then
Gear = Gear - 1
end
local targetPitch = rawPitch * PitchModifier
local latestPitch = seatPart.Idle.PlaybackSpeed + math.clamp(targetPitch - seatPart.Idle.PlaybackSpeed, -pitchMaxDelta, pitchMaxDelta)
local latestVolume = math.min(targetPitch >= 0.6 and 1 or targetPitch / 0.6, 1)
if customFOV then
currentcamera.FieldOfView = 70 + math.abs(carPrim.Velocity.Magnitude)
end
if showCircleOnSpeedo then
Gauges.Speedometer.NeedleFrame.Circle.Visible = true
else
Gauges.Speedometer.NeedleFrame.Circle.Visible = false
end
-- WeightPart Density is 0.5 in result of 180 (mass)
Gauges.Speedometer.Speed.Text = math.floor(carPrim.CFrame:vectorToObjectSpace(carPrim.Velocity).Magnitude) .. " "..datunit
Gauges.Speedometer.NeedleFrame.Needle.Rotation = 45 + 270 * math.min(carPrim.CFrame:vectorToObjectSpace(carPrim.Velocity).Magnitude/600) -- originally 45 + 225 but now 270 because 45 + 270 = 315 and it's the reach/end point
Gauges.Speedometer.Flip.MouseButton1Click:Connect(function()
Instance.new("BodyGyro", carPrim)
wait(.2)
carPrim.BodyGyro:Remove()
return
end)
print(math.floor(Gauges.Speedometer.NeedleFrame.Needle.Rotation))
print(latestPitch, latestVolume)
print("okay")
seatPart.Idle.PlaybackSpeed = math.max(latestPitch, 0.5)
seatPart.Idle.Volume = 1 * latestVolume
--seatPart.Idle.PlaybackSpeed = 0.8 + PitchSpeed
print("isthisworing?")
print("notokay")
seatPart.HeadsUpDisplay = false
-- Raycast Suspensions, Accelerate and Brake
local carPrim = carModel.PrimaryPart
smoothSteer = math.abs(
seatPart.SteerFloat - smoothSteer)<= delta * 5 and seatPart.SteerFloat or smoothSteer + math.sign(
seatPart.SteerFloat - smoothSteer) * delta * 5
for wheelName, OriginalPosition in pairs(WheelPositions) do
local carCframe = carPrim.CFrame
local rayOrigin = carCframe:ToWorldSpace(CFrame.new(OriginalPosition)).p
local rayDirection = -carCframe.UpVector * (SuspensionMaxLength + wheelRadius)
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {carModel}
local raycast = workspace:Raycast(rayOrigin, rayDirection, rayParams)
if raycast then
local RaycastDistance = (rayOrigin - raycast.Position).Magnitude
local raycastPosition = raycast.Position
local springLength = math.clamp(RaycastDistance - wheelRadius, 0, SuspensionMaxLength)
local stiffnessForce = stiffness * (SuspensionMaxLength - springLength)
local damperForce = damper * ((SpringLengthMemory[wheelName] - springLength)/delta)
local suspensionForceVec3 = carCframe.UpVector * (stiffnessForce + damperForce)
local rotationsOnlyWheelDirCframe = CFrame.lookAt(Vector3.zero, carCframe.LookVector, carCframe.UpVector)
if string.sub(wheelName, 1, 1) == "F" then
rotationsOnlyWheelDirCframe = rotationsOnlyWheelDirCframe * CFrame.Angles(0, -math.rad(smoothSteer * steerAngle), 0 )
end
local LocalVelocity = rotationsOnlyWheelDirCframe:ToObjectSpace(CFrame.new(carPrim:GetVelocityAtPosition(raycastPosition)))
local XForce = rotationsOnlyWheelDirCframe.RightVector * -LocalVelocity.X * wheelFriction
local ZForce = rotationsOnlyWheelDirCframe.LookVector * seatPart.ThrottleFloat * torque * (1 - math.min(1, math.abs(LocalVelocity.Z)/maxSpeed))
SpringLengthMemory[wheelName] = springLength
local absoluteImpulses = XForce + ZForce
carPrim:ApplyImpulseAtPosition(suspensionForceVec3 + absoluteImpulses, raycastPosition)
else
SpringLengthMemory[wheelName] = SuspensionMaxLength
end
end
if seatPart.Occupant ~= humanoid then
humanoid.Parent.PrimaryPart.CFrame = seatPart.CFrame:ToWorldSpace(CFrame.new(-6, 1.5, -2))
Gauges.Enabled = false
seatPart.Idle.Playing = false
carPrim:SetNetworkOwner(nil)
print("notokaykay")
if customFOV then
currentcamera.FieldOfView = 70
end
serverTakeOverWait += delta
if serverTakeOverWait >= 1 then
break
end
end
end
end
end
end)
game.ContextActionService:BindAction("EnterCar", function(n, istate, iobject)
local DrivingAnimation = script.DriverSeat
local DrivingTrack = humanoid:LoadAnimation(DrivingAnimation)
if istate== Enum.UserInputState.Begin then
if humanoid.SeatPart then
local carModel = humanoid.SeatPart:FindFirstAncestorOfClass("Model")
humanoid.Sit = false
DrivingTrack:Stop()
DrivingTrack = nil
enableJumpButton()
--humanoid.Parent.HumanoidRootPart.CFrame = humanoid.SeatPart.CFrame:ToWorldSpace(CFrame.new(-5, 0, 1))
else
local nearestcar,nearestdist = nil, 10
for i, v in pairs(workspace.Vehicles:GetChildren()) do
local dist = (v.PrimaryPart.Position - char.HumanoidRootPart.Position).magnitude
if dist < nearestdist then
nearestcar = v
nearestdist = dist
end
end
if nearestcar then
local entirePrimCFrame = nearestcar.PrimaryPart.CFrame
local carRotations = CFrame.lookAt(Vector3.zero, entirePrimCFrame.LookVector, entirePrimCFrame.UpVector)
game.ReplicatedStorage.AskForDoor:FireServer()
wait(0.2)
local nearestseat
for i, v in pairs(nearestcar:GetChildren()) do
if (v:IsA("VehicleSeat") or v:IsA("Seat")) and not v.Occupant then
local dist = (v.Position - char.HumanoidRootPart.Position).magnitude
if dist < nearestdist then
nearestseat = v
nearestdist = dist
end
end
end
if nearestseat then
local currentCFrame = char.HumanoidRootPart.CFrame
nearestseat:Sit(humanoid)
DrivingTrack:Play()
DrivingTrack.Looped = true
local seatWeld = nearestseat:WaitForChild("SeatWeld")
disableJumpButton()
if seatWeld then
local oldC0 = seatWeld.C0
local oldC1 = seatWeld.C1
seatWeld.C0 = nearestseat.CFrame:ToObjectSpace(currentCFrame)
seatWeld.C1 = CFrame.new()
local Tween = game.TweenService:Create(seatWeld, TweenInfo.new(0.35),{C1 = oldC1,C0 = oldC0})
Tween:Play()
wait(0.2)
end
end
end
end
end
end, false, Enum.KeyCode.E)
local WheelRotations ={}
game["Run Service"]:BindToRenderStep("MoveWheels", 5, function()
for _, vehicles in pairs(workspace.Vehicles:GetChildren()) do
if vehicles.Name == "CarModel" then
local carPrim = vehicles.PrimaryPart
for i, v in pairs(WheelPositions) do
local carCframe = carPrim.CFrame
local rayOrigin = carCframe:ToWorldSpace(CFrame.new(Vector3.new(v.x, v.y - wheelRadius, v.z))).p
local rayDirection = -carCframe.UpVector * SuspensionMaxLength
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {vehicles}
local raycast = workspace:Raycast(rayOrigin, rayDirection, rayParams)
if raycast then
local DatWeld = vehicles.Wheels[i].Weld
DatWeld.C0 = CFrame.new(v - Vector3.new(0, (rayOrigin - raycast.Position).magnitude, 0))
if v.x > 0 then
DatWeld.C0 = DatWeld.C0 * CFrame.Angles(0, math.rad(180), 0)
end
if string.sub(i, 1, 1) == "F" then
DatWeld.C0 = DatWeld.C0 * CFrame.Angles(0, -math.rad(smoothSteer * steerAngle), 0)
end
local localVelocity = CFrame.lookAt(Vector3.zero , carCframe.LookVector, carCframe.UpVector):ToObjectSpace(CFrame.new(carPrim:GetVelocityAtPosition(raycast.Position)))
if not WheelRotations[vehicles] then
WheelRotations[vehicles] = {}
for i, v in pairs(WheelPositions) do
WheelRotations[vehicles][i] = 0.5
end
end
WheelRotations[vehicles][i] += localVelocity.Z/56
DatWeld.C0 = DatWeld.C0 * CFrame.Angles(WheelRotations[vehicles][i], 0, 0)
end
end
end
end
end)
if makePlayerCharacterMassless then
for i, v in pairs(humanoid.Parent:GetChildren()) do
if v:IsA("BasePart") then
v.Massless = true
end
end
end