local l=_Tune.FinalDrive*_Tune.FDMult local i=_Tune.Horsepower/100 local x=_Tune.PeakRPM/1000 local L=_Tune.PeakSharpness local D=_Tune.CurveMult function FGC(l)l=l/1000 return(-(l-x)^2*math.min(i/x^2,D^(x/i))+i)*(l-l^L/(L*x)^(L-1))end local V=FGC(_Tune.PeakRPM)local Y=workspace.Gravity/32.2 function GetCurve(i)local x=math.max((FGC(i)*_Tune.Horsepower)/V,0)local L=(car.DriveSeat.CFrame.lookVector.y*_Tune.InclineComp)*Y if _CGear==-1 then L=-L end return x,((((x*(_Tune.EqPoint/i))*_Tune.Ratios[_CGear+2])*l)*math.max(1,1+L))*hpScaling end function Engine()if _CGear==0 then _ClutchOn=false end local i=_Tune.IdleRPM if not _IsOn then i=0 _CGear=0 _ClutchOn=false _GThrot=_Tune.IdleThrottle/100 end local x=0 for l,i in pairs(Drive)do if i.RotVelocity.Magnitude>x then x=i.RotVelocity.Magnitude end end if _ClutchOn then local L=math.max(math.min((((x*_Tune.Ratios[_CGear+2])*l)*30)/math.pi,_Tune.Redline+100),i)local D=math.min(math.abs(L-_RPM)/_Tune.ClutchTol,.9)_RPM=_RPM*D+L*(1-D)_HP,_OutTorque=GetCurve(_RPM)else if _GThrot-_Tune.IdleThrottle/100>0 then _RPM=math.min(_RPM+_Tune.RevAccel*_GThrot,_Tune.Redline+100)else _RPM=math.max(_RPM-_Tune.RevDecay,i)end _OutTorque=0 end local L=0 if _RPM>_Tune.Redline then if _CGear<#_Tune.Ratios-2 then _RPM=_RPM-_Tune.RevBounce L=0 else _RPM=_RPM-_Tune.RevBounce*.5 end else L=((_Tune.Redline+100)*math.pi)/((30*_Tune.Ratios[_CGear+2])*l)end if _TMode=="\065\117\116\111"and _IsOn then _ClutchOn=true if _CGear==0 then _CGear=1 end if _CGear>=1 then if _CGear==1 and(_GBrake>0 and car.DriveSeat.Velocity.Magnitude<20)then _CGear=-1 else if _Tune.AutoShiftMode=="\082\080\077"then if _RPM>_Tune.PeakRPM+_Tune.AutoUpThresh then _CGear=math.min(_CGear+1,#_Tune.Ratios-2)elseif math.max(math.min((((x*_Tune.Ratios[_CGear+1])*l)*30)/math.pi,_Tune.Redline+100),_Tune.IdleRPM)<_Tune.PeakRPM-_Tune.AutoDownThresh then _CGear=math.max(_CGear-1,1)end else if car.DriveSeat.Velocity.Magnitude>math.ceil(((((wDia*math.pi)*(_Tune.PeakRPM+_Tune.AutoUpThresh))/60)/_Tune.Ratios[_CGear+2])/l)then _CGear=math.min(_CGear+1,#_Tune.Ratios-2)elseif car.DriveSeat.Velocity.Magnitude<math.ceil(((((wDia*math.pi)*(_Tune.PeakRPM-_Tune.AutoDownThresh))/60)/_Tune.Ratios[_CGear+1])/l)then _CGear=math.max(_CGear-1,1)end end end else if _GThrot-_Tune.IdleThrottle/100>0 and car.DriveSeat.Velocity.Magnitude<20 then _CGear=1 end end end local D=0 local V=0 local Y=0 local I=0 for l,i in pairs(car.Wheels:GetChildren())do if i.Name=="\070\076"or i.Name=="\070\082"or i.Name=="\070"then D=D+i.RotVelocity.Magnitude V=V+1 elseif i.Name=="\082\076"or i.Name=="\082\082"or i.Name=="\082"then Y=Y+i.RotVelocity.Magnitude I=I+1 end end D=D/V Y=Y/I local g=(D+Y)/2 for l,i in pairs(car.Wheels:GetChildren())do local x=(CFrame.new(i.Position-(i.Arm.CFrame*CFrame.Angles(math.pi/2,-math.pi/2,0)).lookVector,i.Position)*CFrame.Angles(0,math.pi,0)).lookVector local V=1 local I=1 if i.Name=="\070\076"or i.Name=="\082\076"then V=-1 end if _Tune.Config=="\065\087\068"then _OutTorque=(_OutTorque*1.4142135623731)/2 end if i.Name=="\070\076"or i.Name=="\070\082"then I=math.max(0,math.min(1,1+(((i.RotVelocity.Magnitude-D)/D)/(math.max(_Tune.FDiffSlipThres,1)/100))*((_Tune.FDiffLockThres-50)/50)))if _Tune.Config=="\065\087\068"then I=math.max(0,math.min(1,I*(1+(((D-g)/g)/(math.max(_Tune.CDiffSlipThres,1)/100))*((_Tune.CDiffLockThres-50)/50))))end elseif i.Name=="\082\076"or i.Name=="\082\082"then I=math.max(0,math.min(1,1+(((i.RotVelocity.Magnitude-Y)/Y)/(math.max(_Tune.RDiffSlipThres,1)/100))*((_Tune.RDiffLockThres-50)/50)))if _Tune.Config=="\065\087\068"then I=math.max(0,math.min(1,I*(1+(((Y-g)/g)/(math.max(_Tune.CDiffSlipThres,1)/100))*((_Tune.CDiffLockThres-50)/50))))end end _TCSActive=false _ABSActive=false if _PBrake and(_Tune.Config~="\070\087\068"and((i.Name=="\070\076"or i.Name=="\070\082")and car.DriveSeat.Velocity.Magnitude<20 or(i.Name=="\082\082"or i.Name=="\082\076")and car.DriveSeat.Velocity.Magnitude>=20)or _Tune.Config=="\070\087\068"and(i.Name=="\082\082"or i.Name=="\082\076"))then if i["\035\065\086"]:IsA("\066\111\100\121\065\110\103\117\108\097\114\086\101\108\111\099\105\116\121")then i["\035\065\086"].maxTorque=Vector3.new(math.abs(x.x),math.abs(x.y),math.abs(x.z))*PBrakeForce i["\035\065\086"].angularvelocity=Vector3.new()else i["\035\065\086"].MotorMaxTorque=PBrakeForce i["\035\065\086"].AngularVelocity=0 end else if(_TMode=="\077\097\110\117\097\108"or _TMode=="\083\101\109\105")and _GBrake==0 or _TMode=="\065\117\116\111"and(_CGear>-1 and _GBrake==0 or _CGear==-1 and _GThrot-_Tune.IdleThrottle/100==0)then local l=false for x,L in pairs(Drive)do if L==i then l=true end end if l then local l=1 if not script.Parent.IsOn.Value then l=0 end local D=_GThrot if _TMode=="\065\117\116\111"and _CGear==-1 then D=_GBrake end local Y=1 if _TCS then Y=1-math.min(math.max(0,math.abs(i.RotVelocity.Magnitude*(i.Size.x/2)-i.Velocity.Magnitude)-_Tune.TCSThreshold)/_Tune.TCSGradient,1)*(1-_Tune.TCSLimit/100)end if Y<1 then _TCSActive=true end local g=1 if _CGear==-1 then g=-1 end if i["\035\065\086"]:IsA("\066\111\100\121\065\110\103\117\108\097\114\086\101\108\111\099\105\116\121")then i["\035\065\086"].maxTorque=(((((Vector3.new(math.abs(x.x),math.abs(x.y),math.abs(x.z))*_OutTorque)*(1+(i.RotVelocity.Magnitude/60)^1.15))*D)*Y)*I)*l i["\035\065\086"].angularvelocity=((x*V)*L)*g else if i.Name=="\070\082"or i.Name=="\082\082"then g=-g end i["\035\065\086"].MotorMaxTorque=((((_OutTorque*(1+(i.RotVelocity.Magnitude/60)^1.15))*D)*Y)*I)*l i["\035\065\086"].AngularVelocity=L*g end else if i["\035\065\086"]:IsA("\066\111\100\121\065\110\103\117\108\097\114\086\101\108\111\099\105\116\121")then i["\035\065\086"].maxTorque=Vector3.new()i["\035\065\086"].angularvelocity=Vector3.new()else i["\035\065\086"].MotorMaxTorque=0 i["\035\065\086"].AngularVelocity=0 end end else local l=_GBrake if _TMode=="\065\117\116\111"and _CGear==-1 then l=_GThrot end local L=1 if _ABS and math.abs(i.RotVelocity.Magnitude*(i.Size.x/2)-i.Velocity.Magnitude)-_Tune.ABSThreshold>0 then L=0 end if L<1 then _ABSActive=true end if i.Name=="\070\076"or i.Name=="\070\082"or i.Name=="\070"then if i["\035\065\086"]:IsA("\066\111\100\121\065\110\103\117\108\097\114\086\101\108\111\099\105\116\121")then i["\035\065\086"].maxTorque=((Vector3.new(math.abs(x.x),math.abs(x.y),math.abs(x.z))*FBrakeForce)*l)*L else i["\035\065\086"].MotorMaxTorque=(FBrakeForce*l)*L end else if i["\035\065\086"]:IsA("\066\111\100\121\065\110\103\117\108\097\114\086\101\108\111\099\105\116\121")then i["\035\065\086"].maxTorque=((Vector3.new(math.abs(x.x),math.abs(x.y),math.abs(x.z))*RBrakeForce)*l)*L else i["\035\065\086"].MotorMaxTorque=(RBrakeForce*l)*L end end if i["\035\065\086"]:IsA("\066\111\100\121\065\110\103\117\108\097\114\086\101\108\111\099\105\116\121")then i["\035\065\086"].angularvelocity=Vector3.new()else i["\035\065\086"].AngularVelocity=0 end end end end end


	local fFD = _Tune.FinalDrive*_Tune.FDMult

	--Horsepower Curve
	local fgc_h=_Tune.Horsepower/100
	local fgc_n=_Tune.PeakRPM/1000
	local fgc_a=_Tune.PeakSharpness
	local fgc_c=_Tune.CurveMult
	function FGC(x)
		x=x/1000
		return (((-(x-fgc_n)^2)*math.min(fgc_h/(fgc_n^2),fgc_c^(fgc_n/fgc_h)))+fgc_h)*(x-((x^fgc_a)/((fgc_a*fgc_n)^(fgc_a-1))))
	end
	local PeakFGC = FGC(_Tune.PeakRPM)
	
	--Plot Current Horsepower
	local cGrav = workspace.Gravity/32.2
	function GetCurve(x)
		local hp=math.max((FGC(x)*_Tune.Horsepower)/PeakFGC,0)
		local iComp =(car.DriveSeat.CFrame.lookVector.y)*_Tune.InclineComp*cGrav
		if _CGear==-1 then iComp=-iComp end
		return hp,hp*(_Tune.EqPoint/x)*_Tune.Ratios[_CGear+2]*fFD*math.max(1,(1+iComp))*hpScaling
	end
	
	--Powertrain
	function Engine()
		--Neutral Gear
		if _CGear==0 then _ClutchOn = false end
	
		--Car Is Off
		local revMin = _Tune.IdleRPM
		if not _IsOn then 
			revMin = 0 
			_CGear = 0
			_ClutchOn = false
			_GThrot = _Tune.IdleThrottle/100
		end
		
		--Determine RPM
		local maxSpin=0
		for i,v in pairs(Drive) do
			if v.RotVelocity.Magnitude>maxSpin then maxSpin = v.RotVelocity.Magnitude end
		end
		if _ClutchOn then
			local aRPM = math.max(math.min(maxSpin*_Tune.Ratios[_CGear+2]*fFD*30/math.pi,_Tune.Redline+100),revMin)
			local clutchP = math.min(math.abs(aRPM-_RPM)/_Tune.ClutchTol,.9)
			_RPM = _RPM*clutchP  +  aRPM*(1-clutchP)
			_HP,_OutTorque = GetCurve(_RPM)
		else
			if _GThrot-(_Tune.IdleThrottle/100)>0 then
				_RPM = math.min(_RPM+_Tune.RevAccel*_GThrot,_Tune.Redline+100)
			else
				_RPM = math.max(_RPM-_Tune.RevDecay,revMin)
			end
			_OutTorque = 0
		end
		
		--Rev Limiter
		local spLimit = 0
		if _RPM>_Tune.Redline then 
			if _CGear<#_Tune.Ratios-2 then
				_RPM = _RPM-_Tune.RevBounce
				spLimit = 0
			else
				_RPM = _RPM-_Tune.RevBounce*.5
			end
		else
			spLimit = (_Tune.Redline+100)*math.pi/(30*_Tune.Ratios[_CGear+2]*fFD)
		end
		
		--Automatic Transmission
		if _TMode == "Auto" and _IsOn then
			_ClutchOn = true
			if _CGear == 0 then _CGear = 1 end
			if _CGear >= 1 then
				if _CGear==1 and _GBrake > 0  and car.DriveSeat.Velocity.Magnitude < 20 then
					_CGear = -1
				else
					if _Tune.AutoShiftMode == "RPM" then
						if _RPM>(_Tune.PeakRPM+_Tune.AutoUpThresh) then
							_CGear=math.min(_CGear+1,#_Tune.Ratios-2) 
						elseif math.max(math.min(maxSpin*_Tune.Ratios[_CGear+1]*fFD*30/math.pi,_Tune.Redline+100),_Tune.IdleRPM)<(_Tune.PeakRPM-_Tune.AutoDownThresh) then
							_CGear=math.max(_CGear-1,1)
						end
					else
						if car.DriveSeat.Velocity.Magnitude > math.ceil(wDia*math.pi*(_Tune.PeakRPM+_Tune.AutoUpThresh)/60/_Tune.Ratios[_CGear+2]/fFD) then
							_CGear=math.min(_CGear+1,#_Tune.Ratios-2)
						elseif car.DriveSeat.Velocity.Magnitude < math.ceil(wDia*math.pi*(_Tune.PeakRPM-_Tune.AutoDownThresh)/60/_Tune.Ratios[_CGear+1]/fFD) then
							_CGear=math.max(_CGear-1,1)
						end
					end
				end
			else
				if _GThrot-(_Tune.IdleThrottle/100) > 0 and car.DriveSeat.Velocity.Magnitude < 20 then
					_CGear = 1
				end
			end
		end 
		
		--Average Rotational Speed Calculation
		local fwspeed=0
		local fwcount=0
		local rwspeed=0
		local rwcount=0
		
		for i,v in pairs(car.Wheels:GetChildren()) do
			if v.Name=="FL" or v.Name=="FR" or v.Name == "F" then
				fwspeed=fwspeed+v.RotVelocity.Magnitude
				fwcount=fwcount+1
			elseif v.Name=="RL" or v.Name=="RR" or v.Name == "R" then
				rwspeed=rwspeed+v.RotVelocity.Magnitude
				rwcount=rwcount+1
			end
		end
		fwspeed=fwspeed/fwcount
		rwspeed=rwspeed/rwcount	
		local cwspeed=(fwspeed+rwspeed)/2
		
		--Update Wheels
		for i,v in pairs(car.Wheels:GetChildren()) do
			--Reference Wheel Orientation
			local Ref=(CFrame.new(v.Position-((v.Arm.CFrame*CFrame.Angles(math.pi/2,-math.pi/2,0)).lookVector),v.Position)*CFrame.Angles(0,math.pi,0)).lookVector
			local aRef=1
			local diffMult=1
			if v.Name=="FL" or v.Name=="RL" then aRef=-1 end
			
			--AWD Torque Scaling
			if _Tune.Config == "AWD" then _OutTorque = _OutTorque*(2^.5)/2 end
			
			--Differential/Torque-Vectoring
			if v.Name=="FL" or v.Name=="FR" then
				diffMult=math.max(0,math.min(1,1+((((v.RotVelocity.Magnitude-fwspeed)/fwspeed)/(math.max(_Tune.FDiffSlipThres,1)/100))*((_Tune.FDiffLockThres-50)/50))))
				if _Tune.Config == "AWD" then
					diffMult=math.max(0,math.min(1,diffMult*(1+((((fwspeed-cwspeed)/cwspeed)/(math.max(_Tune.CDiffSlipThres,1)/100))*((_Tune.CDiffLockThres-50)/50)))))
				end
			elseif v.Name=="RL" or v.Name=="RR" then
				diffMult=math.max(0,math.min(1,1+((((v.RotVelocity.Magnitude-rwspeed)/rwspeed)/(math.max(_Tune.RDiffSlipThres,1)/100))*((_Tune.RDiffLockThres-50)/50))))
				if _Tune.Config == "AWD" then
					diffMult=math.max(0,math.min(1,diffMult*(1+((((rwspeed-cwspeed)/cwspeed)/(math.max(_Tune.CDiffSlipThres,1)/100))*((_Tune.CDiffLockThres-50)/50)))))
				end
			end
			
			_TCSActive = false
			_ABSActive = false
			--Output
			if _PBrake and ((_Tune.Config ~= "FWD" and (((v.Name=="FL" or v.Name=="FR") and car.DriveSeat.Velocity.Magnitude<20) or ((v.Name=="RR" or v.Name=="RL") and car.DriveSeat.Velocity.Magnitude>=20))) or (_Tune.Config == "FWD" and (v.Name=="RR" or v.Name=="RL"))) then
				--PBrake
				if v["#AV"]:IsA("BodyAngularVelocity") then
					v["#AV"].maxTorque=Vector3.new(math.abs(Ref.x),math.abs(Ref.y),math.abs(Ref.z))*PBrakeForce
					v["#AV"].angularvelocity=Vector3.new()
				else
					v["#AV"].MotorMaxTorque=PBrakeForce
					v["#AV"].AngularVelocity=0
				end
			else
				--Apply Power
				if ((_TMode == "Manual" or _TMode == "Semi") and _GBrake==0) or (_TMode == "Auto" and ((_CGear>-1 and _GBrake==0 ) or (_CGear==-1 and _GThrot-(_Tune.IdleThrottle/100)==0 )))then
					local driven = false
					for _,a in pairs(Drive) do if a==v then driven = true end end
					if driven then
						local on=1
						if not script.Parent.IsOn.Value then on=0 end
						local throt = _GThrot
						if _TMode == "Auto" and _CGear==-1 then throt = _GBrake end
						
						--Apply TCS
						local tqTCS = 1
						if _TCS then
							tqTCS = 1-(math.min(math.max(0,math.abs(v.RotVelocity.Magnitude*(v.Size.x/2) - v.Velocity.Magnitude)-_Tune.TCSThreshold)/_Tune.TCSGradient,1)*(1-(_Tune.TCSLimit/100)))
						end
						if tqTCS < 1 then
							_TCSActive = true
						end
						
						--Update Forces
						local dir = 1
						if _CGear==-1 then dir = -1 end
						if v["#AV"]:IsA("BodyAngularVelocity") then
							v["#AV"].maxTorque=Vector3.new(math.abs(Ref.x),math.abs(Ref.y),math.abs(Ref.z))*_OutTorque*(1+(v.RotVelocity.Magnitude/60)^1.15)*throt*tqTCS*diffMult*on
							v["#AV"].angularvelocity=Ref*aRef*spLimit*dir
						else
							if v.Name=="FR" or v.Name=="RR" then dir=-dir end
							v["#AV"].MotorMaxTorque =_OutTorque*(1+(v.RotVelocity.Magnitude/60)^1.15)*throt*tqTCS*diffMult*on
							v["#AV"].AngularVelocity=spLimit*dir
						end
					else
						if v["#AV"]:IsA("BodyAngularVelocity") then
							v["#AV"].maxTorque=Vector3.new()
							v["#AV"].angularvelocity=Vector3.new()
						else
							v["#AV"].MotorMaxTorque=0
							v["#AV"].AngularVelocity=0
						end
					end
					
				--Brakes
				else
					local brake = _GBrake
					if _TMode == "Auto" and _CGear==-1 then brake = _GThrot end
					
					--Apply ABS
					local tqABS = 1
					if _ABS and math.abs(v.RotVelocity.Magnitude*(v.Size.x/2) - v.Velocity.Magnitude)-_Tune.ABSThreshold>0 then
						tqABS = 0
					end
					if tqABS < 1 then
						_ABSActive = true
					end
					
					--Update Forces
					if v.Name=="FL" or v.Name=="FR" or v.Name=="F" then
						if v["#AV"]:IsA("BodyAngularVelocity") then
							v["#AV"].maxTorque=Vector3.new(math.abs(Ref.x),math.abs(Ref.y),math.abs(Ref.z))*FBrakeForce*brake*tqABS
						else
							v["#AV"].MotorMaxTorque=FBrakeForce*brake*tqABS
						end
					else
						if v["#AV"]:IsA("BodyAngularVelocity") then
							v["#AV"].maxTorque=Vector3.new(math.abs(Ref.x),math.abs(Ref.y),math.abs(Ref.z))*RBrakeForce*brake*tqABS
						else
							v["#AV"].MotorMaxTorque=RBrakeForce*brake*tqABS
						end
					end
					if v["#AV"]:IsA("BodyAngularVelocity") then
						v["#AV"].angularvelocity=Vector3.new()
					else
						v["#AV"].AngularVelocity=0
					end
				end
			end
		end
	end


