function Chassis.UpdateSteering(x,e)local P=x local S=0 local j=Chassis.GetDriverSeat()local s=VehicleParameters.MaxSpeed local z=VehicleParameters.MaxSteer local r=j.Velocity if LimitSteerAtHighVel then local P=SteerLimit*(math.abs(e)/VehicleParameters.MaxSpeed)+1 x=x/P end SteeringPrismatic.TargetPosition=((x*x)*x)*z end function Chassis.UpdateThrottle(x,e)local P=0 local S=false local j=0 if math.abs(e)<.1 then setMotorMaxAcceleration(math.huge)setMotorTorque(2000)elseif math.sign(e*x)>0 or math.abs(x)<.5 then setMotorMaxAcceleration(math.huge)local s=Chassis.driverSeat.Velocity local z=s.Unit local r=Chassis.driverSeat.CFrame.lookVector local n=z:Dot(r)setMotorTorqueDamped((ActualDrivingTorque*e)*e,n,math.sign(e))local O=n<0 local V=e<0 local J=O and V local L=J and VehicleParameters.ReverseSpeed or VehicleParameters.MaxSpeed P=math.sign(e)*L local W=P local g=(W-x)/W local function Z(x)return math.sign(x)*x^2 end local t=math.abs((s.Magnitude/L)*2.5)local N=math.exp((-3*t)*t)j=N if j>0 then S=true end else setMotorMaxAcceleration(100)setMotorTorque((ActualBrakingTorque*e)*e)P=math.sign(e)*500 end Chassis.SetMotorVelocity(P)Effects:SetThrottleEnabled(S,j)end local x=false local e function Chassis.Redress()if x then return end x=true local P=Chassis.driverSeat.CFrame.Position+Vector3.new(0,10,0)local S=Chassis.driverSeat.CFrame.RightVector S=Vector3.new(S.x,0,S.z)S=S.Unit local j=Vector3.new(0,1,0)if not e then e=RedressMount.RedressTarget end e.Parent=Workspace.Terrain e.Position=P e.Axis=S e.SecondaryAxis=j RedressMount.RedressOrientation.Enabled=true RedressMount.RedressPosition.Enabled=true wait(1.5)RedressMount.RedressOrientation.Enabled=false RedressMount.RedressPosition.Enabled=false e.Parent=RedressMount wait(2)x=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 x=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)

	Effects:SetThrottleEnabled(effectsThrottleState, gainModifier)
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
