-- Initialization
Chassis.InitializeDrivingValues()
EffectsInstance:Enable()

RunService.Heartbeat:Connect(function()
	if Ignition and TargetHumanoid then
		local Root = TargetHumanoid.RootPart

		if Car.Chassis.FloorPanel.AssemblyLinearVelocity.Magnitude < 3 and StuckTick <= 50 then
			StuckTick += 1
		elseif StuckTick >= 50 and ReverseTick < 100 and CheckDistance(Car.Chassis.FloorPanel.Position, Root.Position) > 50 then
			ReverseTick += 1
			UpdateThrottleWithComp(-0.7)
			UpdateSteeringWithComp(0)
			return
		else
			StuckTick = 0
			ReverseTick = 0
		end

		if CheckDistance(Car.Chassis.FloorPanel.Position, Root.Position) < 34 and Root.AssemblyLinearVelocity.Magnitude < 16 then
			UpdateThrottleWithComp(0)
		end

		if CheckDistance(Car.Chassis.FloorPanel.Position, Root.Position) > 25 then
			if RaycastToPoint(Car.Chassis.FloorPanel.Position, Root.Position + Root.AssemblyLinearVelocity) == nil then
				local Position = FaceSteerToPosition(Root.Position + Root.AssemblyLinearVelocity) -- Target visible, drive directly and ignore raycasting

				if Position ~= 0 then
					UpdateThrottleWithComp(math.clamp(1.2 - Position, 0.55, 1))
				end
			elseif RaycastToPoint(Car.Chassis.FloorPanel.Position, Root.Position) == nil then
				if TargetHumanoid.SeatPart:FindFirstAncestorWhichIsA("Model"):GetAttribute("MaxSpeed") ~= nil then --In vehicle, PIT if possible
					if PIT(TargetHumanoid.SeatPart:FindFirstAncestorWhichIsA("Model")) == false then
						local Position = FaceSteerToPosition(Root.Position + Root.AssemblyLinearVelocity)

						if Position ~= 0 then
							UpdateThrottleWithComp(math.clamp(1.2 - Position, 0.55, 1))
						end
					end
				else
					local Position = FaceSteerToPosition(Root.Position) -- We can't drive ahead of our target, but we can drive to the target

					if Position ~= 0 then
						UpdateThrottleWithComp(math.clamp(1.2 - Position, 0.55, 1))
					end
				end
			else -- Obstacles detected, avoid collisions
				local FrontResult = Raycast(Car.Chassis.FloorPanel.Position, Car.Chassis.FloorPanel.CFrame.LookVector * RaycastDistance)
				local RightResult = Raycast(Car.Chassis.FloorPanel.Position, Car.Chassis.FloorPanel.CFrame.RightVector * RaycastDistance)
				local LeftResult = Raycast(Car.Chassis.FloorPanel.Position, Car.Chassis.FloorPanel.CFrame.RightVector * -RaycastDistance)
				local BackResult = Raycast(Car.Chassis.FloorPanel.Position, Car.Chassis.FloorPanel.CFrame.LookVector * -RaycastDistance)

				local FrontDistance, RightDistance, LeftDistance, BackDistance = RaycastDistance, RaycastDistance, RaycastDistance, RaycastDistance

				if FrontResult ~= nil then
					FrontDistance = CheckDistance(Car.Chassis.FloorPanel.Position, FrontResult.Position)
				end

				if RightResult ~= nil then
					RightDistance = CheckDistance(Car.Chassis.FloorPanel.Position, RightResult.Position)
				end

				if LeftResult ~= nil then
					LeftDistance = CheckDistance(Car.Chassis.FloorPanel.Position, LeftResult.Position)
				end

				if BackResult ~= nil then
					BackDistance = CheckDistance(Car.Chassis.FloorPanel.Position, BackResult.Position)
				end

				if (RightDistance < 50 or LeftDistance < 50) and FrontDistance > 25 and Reverse == false then
					if LeftDistance > RightDistance then -- Turn left
						local Position = UpdateSteeringWithComp(RightDistance / 50)
						UpdateThrottleWithComp(math.clamp(1.2 - Position, 0.2, 1))
					else
						local Position = UpdateSteeringWithComp(-LeftDistance / 50)
						UpdateThrottleWithComp(math.clamp(1.2 - Position, 0.2, 1))
					end
				elseif FrontDistance <= 25 and Reverse == true then
					Reverse = true
					if BackDistance >= 20 then
						UpdateThrottleToSpeed(-10)
						UpdateSteeringWithComp(0)
					else
						UpdateThrottleToSpeed(5)
						if LeftDistance > RightDistance then
							UpdateSteeringWithComp(1)
						else
							UpdateSteeringWithComp(-1)
						end
					end
					if FrontDistance >= 25 then
						Reverse = false
					end
				else
					FaceSteerToPosition(Root.Position + Root.AssemblyLinearVelocity)
				end
			end
		end
	else
		UpdateThrottleWithComp(0)
	end
end)

Car.SetHumanoidTarget.Event:Connect(function(target)
	TargetHumanoid = target
end)

Car.ToggleIgnition.Event:Connect(function(bool)
	Ignition = bool
end)

task.spawn(function()
	local Sirens = {Car.Chassis.FloorPanel.Wail, Car.Chassis.FloorPanel.Yelp, Car.Chassis.FloorPanel.Priority}
	while task.wait(math.random(2, 4)) do
		if Ignition and TargetHumanoid then
			local SirenToPlay = math.random(1, 3)

			for i, v: Sound in pairs(Sirens) do
				if i == SirenToPlay then
					if not v.IsPlaying then
						v:Play()
					end
				else
					v:Stop()
				end
			end
		end
	end
end)