local O=.35 local w=0 local h=0 local M=false local j=0 local i=1 local B=1.5 local C=.85 local X=1 local m=script.Parent.Engine m:Play()local function e(O)return.014/(.2*O+.08)end while true do wait()h=(w/#Wheels+h)/2 w=0 for I,r in pairs(Wheels)do local l=r.Wheel local J=(-Base.CFrame.UpVector*l.Size.Y)/1.925 local V,c,H=Raycast.new(l.Position,J,script.Parent.Parent)if V then local I=-(r.Wheel.CFrame:vectorToObjectSpace(l.RotVelocity)).X w=w+math.abs(I)local J=l.Velocity+((I*l.Size.Y)/2)*l.CFrame.rightVector:Cross(H)local V=l.CFrame:vectorToObjectSpace(J)local k=J.magnitude r.AttCenter.Position=AttachmentPart.CFrame:PointToObjectSpace(c)local Y=AttachmentPart.CFrame:VectorToObjectSpace((H:Cross(l.Velocity)).unit)local q=(Y*.044)*math.clamp(k-27,0,80)^.5+H*.175 r.AttL.Position=r.AttCenter.Position+q r.AttR.Position=r.AttCenter.Position-q r.Smoke.Rate=math.max(0,k-27)^.5 r.DriftSound.Pitch=(math.clamp(4.1/k^.28,.9,2.2)+r.DriftSound.Pitch*3)/4 r.DriftSound.Volume=(math.clamp(.009*k^1.2,0,2.5)+r.DriftSound.Volume*3)/4 m.Volume=.1+.4*math.max(Throttle.Value,0)local P=h*e(i)if not M then if P>B then X=i i=i+1 M=true j=elapsedTime()elseif P<C and i>1 then X=i i=i-1 M=true j=elapsedTime()end else local w=(elapsedTime()-j)/O P=h*(w*e(i)+(1-w)*e(X))if w>=1 then M=false end end m.Pitch=math.max(P,.3)if k>21 then r.Beam.Enabled=true r.Smoke.Enabled=true if not r.DriftSound.Playing then r.DriftSound:Play()end else r.Beam.Enabled=false r.Smoke.Enabled=false if r.DriftSound.Playing then r.DriftSound:Stop()end end else r.Beam.Enabled=false r.Smoke.Enabled=false if r.DriftSound.Playing then r.DriftSound:Stop()end end end end

local ShiftLength = 0.35
local OmegaSum = 0
local AvgOmega = 0
local Shifting = false
local ShiftStart = 0
local Gear = 1
local ShiftUp = 1.5
local ShiftDown = 0.85
local OldGear = 1
local EngineSound = script.Parent.Engine
EngineSound:Play()
local function GearRatio(Num)
	return 0.014 / (0.2*Num+ 0.08)
end

while true do
	wait()
	AvgOmega = (OmegaSum/(#Wheels) + AvgOmega)/2 
	OmegaSum = 0
	for i,v in pairs(Wheels) do
		local Wheel = v.Wheel
		--Raycast to find if the wheel is touching the ground
		local OffsetVector = -Base.CFrame.UpVector*Wheel.Size.Y/1.925
		local Hit, Pos, Normal = Raycast.new(Wheel.Position, OffsetVector,script.Parent.Parent)
		--Touching
		if Hit then	
			--Calculate velocity of bottom of wheel
			local Omega = -v.Wheel.CFrame:vectorToObjectSpace(Wheel.RotVelocity).X
			OmegaSum = OmegaSum + math.abs(Omega)
			local ContactVelocity = Wheel.Velocity + Omega * Wheel.Size.Y/2 * Wheel.CFrame.rightVector:Cross(Normal)
			local ObjSpaceVel = Wheel.CFrame:vectorToObjectSpace(ContactVelocity)
			local SlideSpeed = ContactVelocity.magnitude 
			
			--Position Attachments	
			v.AttCenter.Position = AttachmentPart.CFrame:PointToObjectSpace(Pos)
			local PerpVector = AttachmentPart.CFrame:VectorToObjectSpace( (Normal:Cross(Wheel.Velocity).unit ))
			local Offset = PerpVector*0.044*(math.clamp(SlideSpeed-27,0,80))^0.5 + Normal*0.175
			v.AttL.Position = v.AttCenter.Position + Offset
			v.AttR.Position = v.AttCenter.Position - Offset
			v.Smoke.Rate = (math.max(0,SlideSpeed-27))^0.5
			
			--Tyre Sound
			v.DriftSound.Pitch = ( math.clamp(4.1/(SlideSpeed^0.28),0.9,2.2) + v.DriftSound.Pitch*3)/4
			v.DriftSound.Volume = ( math.clamp(0.009*SlideSpeed^1.2,0,2.5) + v.DriftSound.Volume*3)/4
			
			--Engine Sounds
			EngineSound.Volume = 0.1 + 0.4 * math.max(Throttle.Value,0)
			local RawPitch = AvgOmega*GearRatio(Gear)
			if not Shifting then
				if RawPitch > ShiftUp then
					OldGear = Gear
					Gear = Gear + 1
					Shifting = true
					ShiftStart = elapsedTime()
				elseif RawPitch < ShiftDown and Gear > 1 then
					OldGear = Gear
					Gear = Gear - 1
					Shifting = true
					ShiftStart = elapsedTime()
				end
			else
				local pct = (elapsedTime() -ShiftStart)/ShiftLength
				RawPitch = AvgOmega*(pct*GearRatio(Gear) + (1-pct)*GearRatio(OldGear))
				if pct>=1 then
					Shifting = false
				end
			end
			EngineSound.Pitch = math.max(RawPitch,.3)
			
			
			--Enable or disable tyre sounds and trails
			if SlideSpeed > 21 then
				v.Beam.Enabled = true
				v.Smoke.Enabled = true
				if not v.DriftSound.Playing then
					v.DriftSound:Play()
				end
			else
				v.Beam.Enabled = false
				v.Smoke.Enabled = false
				if v.DriftSound.Playing then
					v.DriftSound:Stop()
				end
			end
		else --Airborn
			v.Beam.Enabled = false
			v.Smoke.Enabled = false
			if v.DriftSound.Playing then
				v.DriftSound:Stop()
			end
		end
	end
end
