function Chassis.UpdateSteering(n,P)local x=n local r=0 local N=Chassis.GetDriverSeat()local l=VehicleParameters.MaxSpeed local e=VehicleParameters.MaxSteer local z=N.Velocity if LimitSteerAtHighVel then local x=SteerLimit*(math.abs(P)/VehicleParameters.MaxSpeed)+1 n=n/x end SteeringPrismatic.TargetPosition=((n*n)*n)*e end function Chassis.UpdateThrottle(n,P)local x=0 if math.abs(P)<.1 then setMotorMaxAcceleration(math.huge)setMotorTorque(2000)elseif math.sign(P*n)>0 or math.abs(n)<.5 then setMotorMaxAcceleration(math.huge)local n=Chassis.driverSeat.Velocity.Unit local r=Chassis.driverSeat.CFrame.lookVector local N=n:Dot(r)setMotorTorqueDamped((ActualDrivingTorque*P)*P,N,math.sign(P))local l=N<0 local e=P<0 local z=l and e x=math.sign(P)*(z and VehicleParameters.ReverseSpeed or VehicleParameters.MaxSpeed)else setMotorMaxAcceleration(100)setMotorTorque((ActualBrakingTorque*P)*P)x=math.sign(P)*500 end Chassis.SetMotorVelocity(x)end local n=false local P function Chassis.Redress()if n then return end n=true local x=Chassis.driverSeat.CFrame.Position+Vector3.new(0,10,0)local r=Chassis.driverSeat.CFrame.RightVector r=Vector3.new(r.x,0,r.z)r=r.Unit local N=Vector3.new(0,1,0)if not P then P=RedressMount.RedressTarget end P.Parent=Workspace.Terrain P.Position=x P.Axis=r P.SecondaryAxis=N RedressMount.RedressOrientation.Enabled=true RedressMount.RedressPosition.Enabled=true wait(1.5)RedressMount.RedressOrientation.Enabled=false RedressMount.RedressPosition.Enabled=false P.Parent=RedressMount wait(2)n=false end function Chassis.Reset()Chassis.UpdateThrottle(1,1)Chassis.UpdateSteering(1,0)Chassis.EnableHandbrake()setMotorTorque(ActualBrakingTorque)Chassis.SetMotorVelocity(0)Chassis.UpdateSteering(0,0)RedressMount.RedressOrientation.Enabled=true RedressMount.RedressPosition.Enabled=true RedressMount.RedressOrientation.Enabled=false RedressMount.RedressPosition.Enabled=false n=false end return Chassis

function Chassis.UpdateSteering(steer, currentVel)
	local baseSteer = steer
	local targetSteer = 0
	
	local vehicleSeat = Chassis.GetDriverSeat()
	local maxSpeed = VehicleParameters.MaxSpeed
	local maxSteer = VehicleParameters.MaxSteer
	
	local currentVelocity = vehicleSeat.Velocity
	
	if LimitSteerAtHighVel then
		local c = SteerLimit * (math.abs(currentVel)/VehicleParameters.MaxSpeed) + 1
		--decrease steer value as speed increases to prevent tipping (handbrake cancels this)
		steer = steer/c
	end
	SteeringPrismatic.TargetPosition = steer * steer * steer * maxSteer
end

function Chassis.UpdateThrottle(currentVel, throttle)
	local targetVel = 0
	if math.abs(throttle) < 0.1 then
		-- Idling
		setMotorMaxAcceleration(math.huge)
		setMotorTorque(2000)
	elseif math.sign(throttle * currentVel) > 0 or math.abs(currentVel) < 0.5 then
		setMotorMaxAcceleration(math.huge)
		
		local velocityVector = Chassis.driverSeat.Velocity.Unit
		local directionalVector = Chassis.driverSeat.CFrame.lookVector
		local dotProd = velocityVector:Dot(directionalVector) -- Dot product is a measure of how similar two vectors are; if they're facing the same direction, it is 1, if they are facing opposite directions, it is -1, if perpendicular, it is 0
		
		setMotorTorqueDamped(ActualDrivingTorque * throttle * throttle, dotProd, math.sign(throttle))
		-- Arbitrary large number
		local movingBackwards = dotProd < 0
		local acceleratingBackwards = throttle < 0
		local useReverse = (movingBackwards and acceleratingBackwards)
		
		targetVel = math.sign(throttle) * (useReverse and VehicleParameters.ReverseSpeed or VehicleParameters.MaxSpeed)
	else
		-- Braking
		setMotorMaxAcceleration(100)
		setMotorTorque(ActualBrakingTorque * throttle * throttle)
		targetVel = math.sign(throttle) * 500
	end
	Chassis.SetMotorVelocity( targetVel )
end

local redressingState = false
local targetAttachment
function Chassis.Redress()
	if redressingState then
		return
	end
	redressingState = true
	local p = Chassis.driverSeat.CFrame.Position + Vector3.new( 0,10,0 )
	local xc = Chassis.driverSeat.CFrame.RightVector
	xc = Vector3.new(xc.x,0,xc.z)
	xc = xc.Unit
	local yc = Vector3.new(0,1,0)

	if not targetAttachment then
		targetAttachment = RedressMount.RedressTarget
	end

	targetAttachment.Parent = Workspace.Terrain
	targetAttachment.Position = p
	targetAttachment.Axis = xc
	targetAttachment.SecondaryAxis = yc
	RedressMount.RedressOrientation.Enabled = true
	RedressMount.RedressPosition.Enabled = true
	wait(1.5)
	RedressMount.RedressOrientation.Enabled = false
	RedressMount.RedressPosition.Enabled = false
	targetAttachment.Parent = RedressMount
	wait(2)
	redressingState = false
end

function Chassis.Reset() --Reset user inputs and redress (For when a player exits the vehicle)
	Chassis.UpdateThrottle(1, 1) --Values must  be changed to replicate to client.
	Chassis.UpdateSteering(1, 0) --i.e. setting vel to 0 when it is 0 wont update to clients
	Chassis.EnableHandbrake()
	setMotorTorque(ActualBrakingTorque)
	Chassis.SetMotorVelocity(0)
	Chassis.UpdateSteering(0, 0)
	RedressMount.RedressOrientation.Enabled = true
	RedressMount.RedressPosition.Enabled = true
	RedressMount.RedressOrientation.Enabled = false
	RedressMount.RedressPosition.Enabled = false
	redressingState = false
end

return Chassis
