local H=_Tune.FinalDrive*_Tune.FDMult local W=_Tune.Horsepower/100 local A=_Tune.PeakRPM/1000 local T=_Tune.PeakSharpness local y=_Tune.CurveMult function FGC(H)H=H/1000 return(-(H-A)^2*math.min(W/A^2,y^(A/W))+W)*(H-H^T/(T*A)^(T-1))end local G=FGC(_Tune.PeakRPM)local j=workspace.Gravity/26.5 function GetCurve(W)local A=math.max((FGC(W)*_Tune.Horsepower)/G,0)local T=(car.DriveSeat.CFrame.lookVector.y*_Tune.InclineComp)*j if _CGear==-1 then T=-T end return A,((((A*(_Tune.EqPoint/W))*_Tune.Ratios[_CGear+2])*H)*math.max(1,1+T))*hpScaling end function Engine()if _CGear==0 then _ClutchOn=false end local W=_Tune.IdleRPM if not _IsOn then W=0 _CGear=0 _ClutchOn=false _GThrot=_Tune.IdleThrottle/100 end local A=0 for H,W in pairs(Drive)do if W.RotVelocity.Magnitude>A then A=W.RotVelocity.Magnitude end end if _ClutchOn then local T=math.max(math.min((((A*_Tune.Ratios[_CGear+2])*H)*30)/math.pi,_Tune.Redline+100),W)local y=math.min(math.abs(T-_RPM)/_Tune.ClutchTol,.9)_RPM=_RPM*y+T*(1-y)_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,W)end _OutTorque=0 end local T=0 if _RPM>_Tune.Redline then if _CGear<#_Tune.Ratios-2 then _RPM=_RPM-_Tune.RevBounce T=0 else _RPM=_RPM-_Tune.RevBounce*.5 end else T=((_Tune.Redline+100)*math.pi)/((30*_Tune.Ratios[_CGear+2])*H)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<0)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((((A*_Tune.Ratios[_CGear+1])*H)*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])/H)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])/H)then _CGear=math.max(_CGear-1,1)end end end else if _GThrot-_Tune.IdleThrottle/100>0 and car.DriveSeat.Velocity.Magnitude<0 then _CGear=1 end end end local y=0 local G=0 local j=0 local B=0 for H,W in pairs(car.Wheels:GetChildren())do if W.Name=="\070\076"or W.Name=="\070\082"or W.Name=="\070"then y=y+W.RotVelocity.Magnitude G=G+1 elseif W.Name=="\082\076"or W.Name=="\082\082"or W.Name=="\082"then j=j+W.RotVelocity.Magnitude B=B+1 end end y=y/G j=j/B local V=(y+j)/2 for H,W in pairs(car.Wheels:GetChildren())do local A=(CFrame.new(W.Position-(W.Arm.CFrame*CFrame.Angles(math.pi/2,-math.pi/2,0)).lookVector,W.Position)*CFrame.Angles(0,math.pi,0)).lookVector local G=1 local B=1 if W.Name=="\070\076"or W.Name=="\082\076"then G=-1 end if _Tune.Config=="\065\087\068"then _OutTorque=(_OutTorque*1.4142135623731)/2 end if W.Name=="\070\076"or W.Name=="\070\082"then B=math.max(0,math.min(1,1+(((W.RotVelocity.Magnitude-y)/y)/(math.max(_Tune.FDiffSlipThres,1)/100))*((_Tune.FDiffLockThres-50)/50)))if _Tune.Config=="\065\087\068"then B=math.max(0,math.min(1,B*(1+(((y-V)/V)/(math.max(_Tune.CDiffSlipThres,1)/100))*((_Tune.CDiffLockThres-50)/50))))end elseif W.Name=="\082\076"or W.Name=="\082\082"then B=math.max(0,math.min(1,1+(((W.RotVelocity.Magnitude-j)/j)/(math.max(_Tune.RDiffSlipThres,1)/100))*((_Tune.RDiffLockThres-50)/50)))if _Tune.Config=="\065\087\068"then B=math.max(0,math.min(1,B*(1+(((j-V)/V)/(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((W.Name=="\070\076"or W.Name=="\070\082")and car.DriveSeat.Velocity.Magnitude<20 or(W.Name=="\082\082"or W.Name=="\082\076")and car.DriveSeat.Velocity.Magnitude>=20)or _Tune.Config=="\070\087\068"and(W.Name=="\082\082"or W.Name=="\082\076"))then W["\035\065\086"].maxTorque=Vector3.new(math.abs(A.x),math.abs(A.y),math.abs(A.z))*PBrakeForce W["\035\065\086"].angularvelocity=Vector3.new()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 H=false for A,T in pairs(Drive)do if T==W then H=true end end if H then local H=1 if not car.DriveSeat.IsOn.Value then H=0 end local y=_GThrot if _TMode=="\065\117\116\111"and _CGear==-1 then y=_GBrake end local j=1 if _TCS then j=1-math.min(math.max(0,math.abs(W.RotVelocity.Magnitude*(W.Size.x/2)-W.Velocity.Magnitude)-_Tune.TCSThreshold)/_Tune.TCSGradient,1)*(1-_Tune.TCSLimit/100)end if j<1 then _TCSActive=true end local V=1 if _CGear==-1 then V=-1 end W["\035\065\086"].maxTorque=(((((Vector3.new(math.abs(A.x),math.abs(A.y),math.abs(A.z))*_OutTorque)*(1+(W.RotVelocity.Magnitude/60)^1.15))*y)*j)*B)*H W["\035\065\086"].angularvelocity=((A*G)*T)*V else W["\035\065\086"].maxTorque=Vector3.new()W["\035\065\086"].angularvelocity=Vector3.new()end else local H=_GBrake if _TMode=="\065\117\116\111"and _CGear==-1 then H=_GThrot end local T=1 if _ABS and math.abs(W.RotVelocity.Magnitude*(W.Size.x/2)-W.Velocity.Magnitude)-_Tune.ABSThreshold>0 then T=0 end if T<1 then _ABSActive=true end if W.Name=="\070\076"or W.Name=="\070\082"or W.Name=="\070"then W["\035\065\086"].maxTorque=((Vector3.new(math.abs(A.x),math.abs(A.y),math.abs(A.z))*FBrakeForce)*H)*T else W["\035\065\086"].maxTorque=((Vector3.new(math.abs(A.x),math.abs(A.y),math.abs(A.z))*RBrakeForce)*H)*T end W["\035\065\086"].angularvelocity=Vector3.new()end end end end
--[[Engine]]

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 / 26.5
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 ---dum
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, 0.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 * 0.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 < 0 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 < 0 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 ^ 0.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
			v["#AV"].maxTorque = Vector3.new(math.abs(Ref.x), math.abs(Ref.y), math.abs(Ref.z)) * PBrakeForce
			v["#AV"].angularvelocity = Vector3.new()
		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 car.DriveSeat.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
					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
					v["#AV"].maxTorque = Vector3.new()
					v["#AV"].angularvelocity = Vector3.new()
				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
					v["#AV"].maxTorque = Vector3.new(math.abs(Ref.x), math.abs(Ref.y), math.abs(Ref.z))
						* FBrakeForce
						* brake
						* tqABS
				else
					v["#AV"].maxTorque = Vector3.new(math.abs(Ref.x), math.abs(Ref.y), math.abs(Ref.z))
						* RBrakeForce
						* brake
						* tqABS
				end
				v["#AV"].angularvelocity = Vector3.new()
			end
		end
	end
end
