function Chassis.UpdateSteering(i,F)local r=i local G=0 local h=Chassis.GetDriverSeat()local A=VehicleParameters.MaxSpeed local X=VehicleParameters.MaxSteer local C=h.Velocity if LimitSteerAtHighVel then local r=SteerLimit*(math.abs(F)/VehicleParameters.MaxSpeed)+1 i=i/r end SteeringPrismatic.TargetPosition=((i*i)*i)*X end function Chassis.UpdateThrottle(i,F)local r=0 local G=false local h=0 if math.abs(F)<.1 then setMotorMaxAcceleration(math.huge)setMotorTorque(2000)elseif math.sign(F*i)>0 or math.abs(i)<.5 then setMotorMaxAcceleration(math.huge)local A=Chassis.driverSeat.Velocity local X=A.Unit local C=Chassis.driverSeat.CFrame.lookVector local W=X:Dot(C)setMotorTorqueDamped((ActualDrivingTorque*F)*F,W,math.sign(F))local E=W<0 local v=F<0 local q=E and v local l=q and VehicleParameters.ReverseSpeed or VehicleParameters.MaxSpeed r=math.sign(F)*l local H=r local R=(H-i)/H local function D(i)return math.sign(i)*i^2 end local z=math.abs((A.Magnitude/l)*2.5)local t=math.exp((-3*z)*z)h=t if h>0 then G=true end else setMotorMaxAcceleration(100)setMotorTorque((ActualBrakingTorque*F)*F)r=math.sign(F)*500 end Chassis.SetMotorVelocity(r)end local i=false local F function Chassis.Redress()if i then return end i=true local r=Chassis.driverSeat.CFrame.Position+Vector3.new(0,10,0)local G=Chassis.driverSeat.CFrame.RightVector G=Vector3.new(G.x,0,G.z)G=G.Unit local h=Vector3.new(0,1,0)if not F then F=RedressMount.RedressTarget end F.Parent=Workspace.Terrain F.Position=r F.Axis=G F.SecondaryAxis=h RedressMount.RedressOrientation.Enabled=true RedressMount.RedressPosition.Enabled=true wait(1.5)RedressMount.RedressOrientation.Enabled=false RedressMount.RedressPosition.Enabled=false F.Parent=RedressMount wait(2)i=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 i=false end return Chassis
--Set target steering position based on current velocity
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(currentSpeed, throttle)
	local targetVel = 0
	local effectsThrottleState = false
	local gainModifier = 0

	if math.abs(throttle) < 0.1 then
		-- Idling
		setMotorMaxAcceleration(math.huge)
		setMotorTorque(2000)
	elseif math.sign(throttle * currentSpeed) > 0 or math.abs(currentSpeed) < 0.5 then
		setMotorMaxAcceleration(math.huge)

		local velocity = Chassis.driverSeat.Velocity
		local velocityVector = 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)

		local maxSpeed = (useReverse and VehicleParameters.ReverseSpeed or VehicleParameters.MaxSpeed)
		targetVel = math.sign(throttle) * maxSpeed

		-- if we are approaching max speed, we should take that as an indication of throttling down, even if not from input
		local maxAccelSpeed = targetVel
		local speedPercent = ((maxAccelSpeed - currentSpeed) / maxAccelSpeed) -- 0 if max speed, 1 if stopped

		-- lets say we start throttling down after reaching 75% of max speed, then linearly drop to 0
		local function quad(x)
			return math.sign(x) * (x ^ 2)
		end

		local r = math.abs(velocity.Magnitude / maxSpeed * 2.5) -- adding a bit to the max speed so that it sounds better (always trying to rev engines)
		local desiredRPM = math.exp(-3 * r * r)

		gainModifier = desiredRPM

		if gainModifier > 0 then
			effectsThrottleState = true
		end
	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
