---Engine


function Engine()
	script.Parent:WaitForChild("Gauges")
	script.Parent:WaitForChild("Status")
	local down1
	local down2
	local Drive={
		car.Wheels.FL:GetChildren(),
		car.Wheels.FR:GetChildren(),
		car.Wheels.RL:GetChildren(),
		car.Wheels.RR:GetChildren()
	}
	local Tc={
		Speed=0,
		ThrotAccel=.1,
		ThrotDecay=.4,
		ClutchAccel=.1,
		ClutchDecay=.5,
		FreeAccel=.1,
		FreeDecay=.01,
		BrakeAccel=.5,
		BrakeDecay=.5,
		ExpGradient=2,
		MaxTorque=100000,
		BrakeMaxTorque=100000,
		BExpGradient=2,
		Brakes=4000,		--Brake Force
		ClutchGain=6000,
		ClutchStall=0,
		ShiftSpeed=.3,
		ClutchShiftSpeed=.7,
		RevBounceP=.93,
		VariableThrotAdj=.1,
		Trans={
	--	Tuning:  http://i.imgur.com/wbHZPI7.png
	--		   [1]		  [2]		  [3]		 [4]		   [5]		  [6]			[7]			  [8]		  [9]
	--	  	{Int Tq	, 	Peak Tq	, 	Peak Sp	, 	Max Sp	, 	Tq Decay, 	Limiter	,	C Tolerance	,	C Gain	,	C Stall	}
			{14000	,	19000	,	41		,	68		,	17		,	8		,	.7			,	.5		,	0		},		--1st
			{10000	,	12000	,	61		,	82		,	20		,	10		,	.2			,	.3		,	0		},		--2nd
			{8000	,	10000	,	115		,	103		,	27		,	13		,	.1			,	.2		,	0		},		--3rd
			{5000	,	9000	,	150		,	136		,	28		,	20		,	.08			,	.15		,	0	    },		--4th
			{2500	,	8800	,	177		,	157		,	50		,	30		,	.06			,	.1		,	0		},
			{2500	,	8400	,	177		,	177		,	50		,	30		,	.06			,	.1		,	0		},
			{2500	,	8000	,	177		,	198		,	50		,	30		,	.06			,	.1		,	0		},		--5th		--6th
		},
		ReverseTq=14000,		--Reverse Torque
		ReverseSp=30,		--Max Reverse Speed
		FDiffPerc=-.2,		--Front Differential 	(-1 -> 1) *value < 0 is outer wheel biased
		CDiffPerc=.25,		--Center Differential	(-1 -> 1) *value < 0 is front biased
		RDiffPerc=-.2,		--Rear Differential		(-1 -> 1) *value < 0 is outer wheel biased
		DTrainDist=-.5,		--Power Distribution	(See below diagram)
					--  Rear  <-|-------|-------|-------|-------|->  Front
					-- Biased  -1        		0     		   	1   Biased
					--  	   RWD    		   AWD   		   FWD
	-------------------------------------------
		ThrotP=0,
		MaxThrotP=1,
		BrakeP=0,
		ClutchP=0,
		Throttle=0,
		Brake=0,
		Clutch=0,
		Gear=1,
		GearShift=1,
		PrevGear=1,
		RPM=0,
		Units={
			{"SPS",1},
			{"MPH",.682},
			{"KPH",1.097}
		},
		CUnit=1
	}
		local Friction={
		TractionControl=true,
		FDownforce=0000,	--Front Downforce (Unsprung)
		RDownforce=40000,	--Rear Downforce  (Unsprung)
		FFChange=0,
		FTolerance=10,
		FMaxDiff=40,
		FDecay=1,
		FGripGain=1,
		RFChange=-40000,
		RTolerance=10,
		RMaxDiff=40,
		RDecay=.01,
		RGripGain=.01,
		PBrakeForce=40000,
		SkidTol=40,
	-----------------------------------------
		PBrake=false,
		FSkid=0,
		RSkid=0,
	}
	for i,v in pairs(Drive) do
		for n,a in pairs(v) do
			if a.Wheel:FindFirstChild("#AV") then
				a.Wheel:FindFirstChild("#AV"):Destroy()
			end
			local AV=Instance.new("BodyAngularVelocity",a.Wheel)
			AV.Name="#AV"
			AV.angularvelocity=Vector3.new(0,0,0)
			AV.maxTorque=Vector3.new(0,0,0)
			AV.P=Tc.MaxTorque
		end
	end
	mouse.Button1Up:connect(function() down1=false end)
	mouse.Button1Down:connect(function() down1=true end)
	mouse.Button2Up:connect(function() down2=false end)
	mouse.Button2Down:connect(function() down2=true end)
	mouse.WheelForward:connect(function()
		if GMode==1 then
			Tc.MaxThrotP=math.min(1,Tc.MaxThrotP+Tc.VariableThrotAdj)
		end
	end)
	mouse.WheelBackward:connect(function()
		if GMode==1 then
			Tc.MaxThrotP=math.max(0,Tc.MaxThrotP-Tc.VariableThrotAdj)
		end
	end)
	mouse.KeyDown:connect(function(key)
		if key=="q" then
			Tc.PrevGear=Tc.Gear
			Tc.GearShift=0
			Tc.Gear=math.max(Tc.Gear-1,-1)
		elseif key=="e" then
			Tc.PrevGear=Tc.Gear
			Tc.GearShift=0
			Tc.Gear=math.min(Tc.Gear+1,#Tc.Trans)
		elseif (string.byte(key)==48 and GMode==1) or (key=="p" and GMode==0) then
			Friction.PBrake=1
		elseif (key=="w" and GMode==1) or (string.byte(key)==48 and GMode==0) then
			Tc.Clutch=1
		elseif key=="t" then
			Friction.TractionControl=not Friction.TractionControl
		end
	end)
	mouse.KeyUp:connect(function(key)
		if (string.byte(key)==48 and GMode==1) or (key=="p" and GMode==0) then
			Friction.PBrake=0
		elseif (key=="w" and GMode==1) or (string.byte(key)==48 and GMode==0) then
			Tc.Clutch=0
		end
	end)
	local function AChassis()
		if GMode==0 then
			Tc.MaxThrotP=1
			Tc.MaxBrakeP=1
			Tc.Throttle=math.max(car.DriveSeat.Throttle,0)
			Tc.Brake=math.max(-car.DriveSeat.Throttle,0)
		elseif GMode==1 then
			Tc.MaxBrakeP=1
			if down1 then
				Tc.Throttle=1
			else
				Tc.Throttle=0
			end
			if down2 then
				Tc.Brake=1
			else
				Tc.Brake=0
			end
		else
			Friction.PBrake=ButtonL1
			Tc.Clutch=ButtonR1
			Tc.Throttle=math.ceil(RTriggerValue)
			Tc.MaxThrotP=RTriggerValue
			Tc.Brake=math.ceil(LTriggerValue)
			Tc.MaxBrakeP=LTriggerValue^Tc.BExpGradient
			if Tc.ControllerGUp==0 and ButtonY==1 then
				Tc.PrevGear=Tc.Gear
				Tc.GearShift=0
				Tc.Gear=math.min(Tc.Gear+1,#Tc.Trans)
			elseif Tc.ControllerGDown==0 and ButtonX==1 then
				Tc.PrevGear=Tc.Gear
				Tc.GearShift=0
				Tc.Gear=math.max(Tc.Gear-1,-1)
			end
			Tc.ControllerGUp=ButtonY
			Tc.ControllerGDown=ButtonX
		end
		if Tc.Throttle==1 then
			Tc.ThrotP=math.min(Tc.MaxThrotP,Tc.ThrotP+Tc.ThrotAccel)
		else
			Tc.ThrotP=math.max(0,Tc.ThrotP-Tc.ThrotDecay)
		end
		if Tc.Brake==1 then
			Tc.BrakeP=math.min(Tc.MaxBrakeP,Tc.BrakeP+Tc.BrakeAccel)
		else
			Tc.BrakeP=math.max(0,Tc.BrakeP-Tc.BrakeDecay)
		end
		if Tc.Clutch==1 or Tc.Gear==0 then
			Tc.ClutchP=math.max(0,Tc.ClutchP-Tc.ClutchDecay)
		else
			Tc.ClutchP=math.min(1,Tc.ClutchP+Tc.ClutchAccel)
		end
		-------------
		Tc.GearShift=math.min(1,Tc.GearShift+Tc.ShiftSpeed+(Tc.ClutchShiftSpeed*(1-Tc.ClutchP)))
		---GearChangeBeta
		local tol=Tc.Trans[math.max(Tc.Gear,1)][7]
		local NSGear=Tc.Trans[math.max(Tc.Gear,1)][4]+Tc.Trans[math.max(Tc.Gear,1)][6]+3
		local OSGear=Tc.Trans[math.max(Tc.PrevGear,1)][4]+Tc.Trans[math.max(Tc.PrevGear,1)][6]+3
		local toprev=OSGear+((NSGear-OSGear)*Tc.GearShift)
		local gearDiff=(Tc.RPM*NSGear)-(Tc.RPM*OSGear)
		local stall=1
		local stalltq=0
		if math.abs(gearDiff)>tol then
			stall=Tc.GearShift
			if gearDiff>0 then
				stalltq=Tc.Trans[Tc.Gear][8]*(1-Tc.GearShift)
			else
				stalltq=Tc.Trans[Tc.Gear][9]*(1-Tc.GearShift)
			end
		end
		-------------
		local frev=0
		local rrev=0
		for i,v in pairs(Drive[1]) do
			frev=math.max(frev,v.Wheel.RotVelocity.Magnitude)
		end
		for i,v in pairs(Drive[2]) do
			frev=math.max(frev,v.Wheel.RotVelocity.Magnitude)
		end
		for i,v in pairs(Drive[3]) do
			rrev=math.max(rrev,v.Wheel.RotVelocity.Magnitude)
		end
		for i,v in pairs(Drive[4]) do
			rrev=math.max(rrev,v.Wheel.RotVelocity.Magnitude)
		end
		local rev=rrev/toprev
		if Tc.DTrainDist==1 then
			rev=frev/toprev
		elseif Tc.DTrainDist~=-1 then
			rev=math.max(rev,frev/toprev)
		end
		local rGain=(Tc.ThrotP*2)-1
		if rGain>0 then
			rGain=rGain*Tc.FreeAccel
		else
			rGain=rGain*Tc.FreeDecay
		end
		Tc.RPM=math.min(1,math.max(0,rev*Tc.ClutchP^.3,(Tc.RPM+rGain)*(1-Tc.ClutchP)^.3))
		-- A-Chassis 5.0
		for i,a in pairs(Drive) do
			for n,v in pairs(a) do
				local tq=0
				if Tc.Gear>0 then
					Tc.Speed=toprev
					if v.Wheel.RotVelocity.Magnitude<Tc.Trans[Tc.Gear][4] then
						local tPerc=math.min(v.Wheel.RotVelocity.Magnitude/Tc.Trans[Tc.Gear][3],1)
						local tqChange=Tc.Trans[Tc.Gear][2]-Tc.Trans[Tc.Gear][1]
						tq=(Tc.Trans[Tc.Gear][1]+(tPerc*tqChange))
					else
						if v.Wheel.RotVelocity.Magnitude<Tc.Trans[Tc.Gear][4]+Tc.Trans[Tc.Gear][6]-1 then
							local tPerc=(v.Wheel.RotVelocity.Magnitude-Tc.Trans[Tc.Gear][4])/Tc.Trans[Tc.Gear][5]
							local tqChange=Tc.Trans[Tc.Gear][2]
							tq=(math.max(0,Tc.Trans[Tc.Gear][2]-(tPerc*tqChange)))
						else
							Tc.Speed=(Tc.Trans[Tc.Gear][4]+Tc.Trans[Tc.Gear][6])*Tc.RevBounceP
							tq=Tc.Trans[Tc.Gear][2]*2
						end
					end
				elseif Tc.Gear==0 then
					tq=0
				else
					Tc.Speed=-Tc.ReverseSp
					tq=Tc.ReverseTq
				end
				if i==1 then
					tq=tq*(1-(GSteer*Tc.FDiffPerc))*(1+math.abs(GSteer*Tc.CDiffPerc))*(1+Tc.DTrainDist)
				elseif i==2 then
					tq=tq*(1+(GSteer*Tc.FDiffPerc))*(1+math.abs(GSteer*Tc.CDiffPerc))*(1+Tc.DTrainDist)
				elseif i==3 then
					tq=tq*(1-(GSteer*Tc.RDiffPerc))*(1-math.abs(GSteer*Tc.CDiffPerc))*(1-Tc.DTrainDist)
				else
					tq=tq*(1+(GSteer*Tc.RDiffPerc))*(1-math.abs(GSteer*Tc.CDiffPerc))*(1-Tc.DTrainDist)
				end
				tq=tq*Tc.ThrotP*Tc.ClutchP^Tc.ExpGradient
				tq=tq+(tq*stalltq)
				local br=Tc.Brakes*Tc.BrakeP^Tc.ExpGradient
				tq=math.abs(tq-br)
				Tc.Speed=Tc.Speed*(1-math.ceil(Tc.BrakeP))
				if i>2 and Friction.PBrake==1 then
					Tc.Speed=0
					tq=Friction.PBrakeForce
				end
				local Ref=v.Axle.CFrame.lookVector
				local Speed=Tc.Speed
				if i==1 or i==3 then Speed=-Speed end
				local TqVector=1
				if Friction.TractionControl then
					TqVector=math.max(0,Friction.SkidTol-math.abs((v.Wheel.RotVelocity.Magnitude*(v.Wheel.Size.X/2))-v.Wheel.Velocity.Magnitude))/Friction.SkidTol
					if TqVector<.7 then
						script.Parent.Gauges.Speedo.TC.Visible=true
					else
						script.Parent.Gauges.Speedo.TC.Visible=false
					end
				else
					script.Parent.Gauges.Speedo.TC.Visible=false
				end
				v.Wheel["#AV"].maxTorque=Vector3.new(math.abs(Ref.x),math.abs(Ref.y),math.abs(Ref.z))*tq*TqVector
				v.Wheel["#AV"].angularvelocity=Ref*Speed*stall
				v.Wheel["#AV"].P=Tc.MaxTorque*TqVector
			end
		end
	end
	script.Parent.Gauges.Speedo.Units.MouseButton1Click:connect(function()
		if Tc.CUnit>=3 then
			Tc.CUnit=1
		else
			Tc.CUnit=Tc.CUnit+1
		end
		script.Parent.Gauges.Speedo.Units.Text=Tc.Units[Tc.CUnit][1]
	end)
	local numbers={180354176,180354121,180354128,180354131,180354134,180354138,180354146,180354158,180354160,180354168,180355596,180354115}
	local function Speedometer()
		--Sound
		car.DriveSeat.Rev.Pitch=car.DriveSeat.Rev.SetPitch.Value+car.DriveSeat.Rev.SetRev.Value*Tc.RPM
		car.DriveSeat.Rel.Pitch=car.DriveSeat.Rel.SetPitch.Value+car.DriveSeat.Rel.SetRev.Value*Tc.RPM
		car.DriveSeat.Rev.Volume=car.DriveSeat.Rev.SetVolume.Value*Tc.ThrotP
		car.DriveSeat.Rel.Volume=car.DriveSeat.Rel.SetVolume.Value*(1-Tc.ThrotP)
		
		if Tc.Throttle ~= 1 then
			car.DriveSeat.Backfire.Volume=math.min(math.max((Tc.RPM-.5)/.5,0)*.7,car.DriveSeat.Backfire.Volume+.07)
		else
			car.DriveSeat.Backfire.Volume=math.max(car.DriveSeat.Backfire.Volume-.07,0)
		end
		--Afterburn
		if Tc.PrevThrot~=Tc.Throttle and Tc.RPM > .6 then
			local a=math.random(0,1)
			if a==1 then
				coroutine.resume(coroutine.create(function()
					for i,v in pairs(car.Body.Exhaust:GetChildren()) do
						v.Afterburn.Rate=10
					end
					wait(.1)
					for i,v in pairs(car.Body.Exhaust:GetChildren()) do
						v.Afterburn.Rate=0
					end
				end))
			end
		end
		--Speedo
		local fwheel=Tc.RPM*(Tc.Trans[math.max(Tc.Gear,1)][4]+Tc.Trans[math.max(Tc.Gear,1)][6])
		local z1=math.min(1,math.max(0,fwheel-(Tc.Trans[math.max(Tc.Gear,1)][3]*.5))/(Tc.Trans[math.max(Tc.Gear,1)][3]-(Tc.Trans[math.max(Tc.Gear,1)][3]*.5)))
		local z2=math.min(1,math.max(0,fwheel-Tc.Trans[math.max(Tc.Gear,1)][4])/Tc.Trans[math.max(Tc.Gear,1)][6])
		local blue=1-z1
		local red=z2*2
		local green=0
		if fwheel>Tc.Trans[math.max(Tc.Gear,1)][4] then
			green=1-z2
		else
			green=math.max(.45,z1*2)
		end
		for i,v in pairs(script.Parent.Gauges.Tach:GetChildren()) do
			local n=tonumber(string.match(v.Name, "%d+"))
			if n~=nil then
				if n%2 == 0 then
					v.P.Size=UDim2.new(0,4,0,((1-math.abs(Tc.RPM-((n-1)/18)))^12*-40)-10)
				else
					v.P.Size=UDim2.new(0,6,0,((1-math.abs(Tc.RPM-((n-1)/18)))^12*-40)-10)
				end
				v.P.BackgroundColor3 = Color3.new(red,green,blue)
			end
		end
		local sp=car.DriveSeat.Velocity.Magnitude*Tc.Units[Tc.CUnit][2]
		if sp<1000 then
			local nnn=math.floor(sp/100)
			local nn=(math.floor(sp/10))-(nnn*10)
			local n=(math.floor(sp)-(nn*10))-(nnn*100)
			script.Parent.Gauges.Speedo.A.Image="http://www.roblox.com/asset/?id="..numbers[n+1]
			if sp>=10 then
				script.Parent.Gauges.Speedo.B.Image="http://www.roblox.com/asset/?id="..numbers[nn+1]
			else
				script.Parent.Gauges.Speedo.B.Image="http://www.roblox.com/asset/?id="..numbers[12]
			end
			if sp>=100 then
				script.Parent.Gauges.Speedo.C.Image="http://www.roblox.com/asset/?id="..numbers[nnn+1]
			else
				script.Parent.Gauges.Speedo.C.Image="http://www.roblox.com/asset/?id="..numbers[12]
			end
		else
			script.Parent.Gauges.Speedo.A.Image="http://www.roblox.com/asset/?id="..numbers[10]
			script.Parent.Gauges.Speedo.B.Image="http://www.roblox.com/asset/?id="..numbers[10]	
			script.Parent.Gauges.Speedo.C.Image="http://www.roblox.com/asset/?id="..numbers[10]
		end
		if Tc.Gear>=0 then
			script.Parent.Gauges.Gear.G.Image="http://www.roblox.com/asset/?id="..numbers[Tc.Gear+1]
		else
			script.Parent.Gauges.Gear.G.Image="http://www.roblox.com/asset/?id="..numbers[11]
		end
		--Status Indicators
		script.Parent.Status.Clutch.B.Size=UDim2.new(0,4,-Tc.ClutchP,0)
		script.Parent.Status.Throttle.B.Size=UDim2.new(0,4,-Tc.ThrotP,0)
		script.Parent.Status.Brakes.B.Size=UDim2.new(0,4,-Tc.BrakeP,0)
		script.Parent.Status.ThrotLimit.B.Size=UDim2.new(0,4,-Tc.MaxThrotP,0)
		GSpeed=car.DriveSeat.Velocity.Magnitude
		GTopSp=Tc.Trans[#Tc.Trans][4]+Tc.Trans[#Tc.Trans][6]
		GRev=Tc.RPM
		GThrottle=Tc.ThrotP
		GBrake=Tc.BrakeP
		Tc.PrevThrot=Tc.Throttle
	end
	local function Smoke()
		local tireSP={}
		for i,v in pairs(Drive) do
			for n,a in pairs(v) do
				if a.Wheel:FindFirstChild("Smoke")~=nil and a.Wheel:FindFirstChild("Squeal")~=nil then
					if workspace:FindPartOnRay(Ray.new(a.Wheel.Position,Vector3.new(0,-a.Wheel.Size.X/2,0)),car) then
						a.Wheel.Smoke.Enabled=math.abs((a.Wheel.RotVelocity.Magnitude*(a.Wheel.Size.X/2))-a.Wheel.Velocity.Magnitude)>20
						a.Wheel.Squeal.Volume=math.min(1,math.max(0,math.abs((a.Wheel.RotVelocity.Magnitude*(a.Wheel.Size.X/2))-a.Wheel.Velocity.Magnitude)-20)/20)
					else
						a.Wheel.Smoke.Enabled=false
						a.Wheel.Squeal.Volume=0
					end
				end
			end
		end
	end
	--run:BindToRenderStep("AChassis",Enum.RenderPriority.Last.Value,AChassis)
	--run:BindToRenderStep("Speedometer",Enum.RenderPriority.Last.Value,Speedometer)
	--run:BindToRenderStep("Smoke",Enum.RenderPriority.Last.Value,Smoke)
	--table.insert(Binded,"AChassis")
	--table.insert(Binded,"Speedometer")
	--table.insert(Binded,"Smoke")
	table.insert(LoopRun,AChassis)
	table.insert(LoopRun,Speedometer)
	table.insert(LoopRun,Smoke)
end
Engine()