can you make so each time you reach a target you get an amount of speed that increases with each one -- LocalScript - Place this in StarterPlayer > StarterPlayerScripts
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")

-- CONFIGURATION
local TARGET_PART_NAMES = {"TargetBlock", "TargetBlock2", "TargetBlock3", "TargetBlock4", "TargetBlock5", "TargetBlock6", "TargetBlock7", "TargetBlock8", "TargetBlock9", "TargetBlock10"} -- Array of target blocks in order
local START_PART_NAME = "StartBlock"
local TRIGGER_DISTANCE = 3 -- Distance for target completion

-- Progress tracking variables
local currentStage = 0 -- 0 = not started, 1 = first target, 2 = second target, etc.
local startingDistance = nil
local progressStarted = false
local stageCompleted = {}
local connections = {}

-- Create ScreenGui for progress bar
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "DistanceProgressBar"
screenGui.ResetOnSpawn = false
screenGui.Enabled = false
screenGui.Parent = playerGui

-- Create separate ScreenGui for speed display (always visible)
local speedGui = Instance.new("ScreenGui")
speedGui.Name = "SpeedDisplay"
speedGui.ResetOnSpawn = false
speedGui.Parent = playerGui

-- UI Creation
local backgroundFrame = Instance.new("Frame")
backgroundFrame.Size = UDim2.new(0, 600, 0, 40) -- Back to original height
backgroundFrame.Position = UDim2.new(0.5, -300, 0, -30) -- Back to original position
backgroundFrame.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
backgroundFrame.BorderSizePixel = 2
backgroundFrame.BorderColor3 = Color3.fromRGB(255, 255, 255)
backgroundFrame.Parent = screenGui

local backgroundCorner = Instance.new("UICorner")
backgroundCorner.CornerRadius = UDim.new(0, 8)
backgroundCorner.Parent = backgroundFrame

local progressBar = Instance.new("Frame")
progressBar.Size = UDim2.new(0, 0, 1, 0) -- Back to full height
progressBar.Position = UDim2.new(0, 0, 0, 0) -- Back to original position
progressBar.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
progressBar.BorderSizePixel = 0
progressBar.Parent = backgroundFrame

local progressCorner = Instance.new("UICorner")
progressCorner.CornerRadius = UDim.new(0, 8)
progressCorner.Parent = progressBar

local distanceLabel = Instance.new("TextLabel")
distanceLabel.Size = UDim2.new(1, 0, 1, 0) -- Back to full size
distanceLabel.Position = UDim2.new(0, 0, 0, 0) -- Back to original position
distanceLabel.BackgroundTransparency = 1
distanceLabel.Text = ""
distanceLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
distanceLabel.TextScaled = true
distanceLabel.Font = Enum.Font.GothamBold
distanceLabel.ZIndex = 2
distanceLabel.Parent = backgroundFrame

-- Speed display (always visible - moved to separate GUI)
local speedLabel = Instance.new("TextLabel")
speedLabel.Size = UDim2.new(0, 120, 0, 20)
speedLabel.Position = UDim2.new(0.5, -60, 1, -30) -- Bottom center of screen
speedLabel.BackgroundTransparency = 1
speedLabel.Text = "Speed: 0"
speedLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
speedLabel.TextScaled = true
speedLabel.Font = Enum.Font.Gotham
speedLabel.Parent = speedGui

-- Function to get closest point on part surface to player
local function getClosestPointOnPart(part, playerPosition)
	local partCFrame = part.CFrame
	local partSize = part.Size

	-- Convert player position to part's local space
	local localPosition = partCFrame:PointToObjectSpace(playerPosition)

	-- Clamp to part boundaries (closest surface point)
	local clampedX = math.clamp(localPosition.X, -partSize.X/2, partSize.X/2)
	local clampedY = math.clamp(localPosition.Y, -partSize.Y/2, partSize.Y/2)
	local clampedZ = math.clamp(localPosition.Z, -partSize.Z/2, partSize.Z/2)

	-- Convert back to world space
	local closestPoint = partCFrame:PointToWorldSpace(Vector3.new(clampedX, clampedY, clampedZ))

	return closestPoint
end

-- Function to get distance to part surface
local function getDistanceToPartSurface(part, playerPosition)
	local closestPoint = getClosestPointOnPart(part, playerPosition)
	return (playerPosition - closestPoint).Magnitude
end



-- Function to clean up connections
local function cleanupConnections()
	for _, connection in pairs(connections) do
		if connection then
			connection:Disconnect()
		end
	end
	connections = {}
end

-- Function to start next stage
local function startNextStage()
	currentStage = currentStage + 1

	if currentStage <= #TARGET_PART_NAMES then
		local targetPart = workspace:FindFirstChild(TARGET_PART_NAMES[currentStage])

		if targetPart and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
			local humanoidRootPart = player.Character.HumanoidRootPart
			startingDistance = getDistanceToPartSurface(targetPart, humanoidRootPart.Position)

			distanceLabel.Text = "Distance: " .. math.floor(startingDistance + 0.5) .. " studs"

			-- Reset progress bar
			progressBar.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
			progressBar.Size = UDim2.new(0, 0, 1, 0)

			screenGui.Enabled = true
			progressStarted = true

			print("Target " .. currentStage .. " started! " .. TARGET_PART_NAMES[currentStage] .. ", Distance:", startingDistance)
		else
			distanceLabel.Text = "Target " .. TARGET_PART_NAMES[currentStage] .. " not found!"
			screenGui.Enabled = true
		end
	else
		-- All stages completed
		distanceLabel.Text = "All Targets Complete!"
		progressBar.Size = UDim2.new(1, 0, 1, 0)
		progressBar.BackgroundColor3 = Color3.fromRGB(255, 215, 0) -- Gold color
		screenGui.Enabled = true

		-- Hide after 3 seconds
		spawn(function()
			wait(3)
			screenGui.Enabled = false
			progressStarted = false
		end)
		print("All targets completed!")
	end
end

-- Function to check if player has reached any target blocks and resume from there
local function checkForTargetProgress()
	if not player.Character or not player.Character:FindFirstChild("HumanoidRootPart") then
		return
	end

	local humanoidRootPart = player.Character.HumanoidRootPart
	local playerPosition = humanoidRootPart.Position

	-- Check which targets the player is close to (indicating they've reached them)
	for i = #TARGET_PART_NAMES, 1, -1 do -- Check from last to first
		local targetPart = workspace:FindFirstChild(TARGET_PART_NAMES[i])
		if targetPart then
			local distanceToTarget = getDistanceToPartSurface(targetPart, playerPosition)

			-- If player is very close to a target block (within 10 studs), assume they've reached this checkpoint
			if distanceToTarget <= 10 then
				-- Mark all previous stages as completed
				for j = 1, i do
					stageCompleted[j] = true
				end

				-- Start the next stage (or complete if this was the last one)
				currentStage = i
				if currentStage < #TARGET_PART_NAMES then
					startNextStage()
				else
					-- Player is at the final target
					distanceLabel.Text = "All Targets Complete!"
					progressBar.Size = UDim2.new(1, 0, 1, 0)
					progressBar.BackgroundColor3 = Color3.fromRGB(255, 215, 0)
					screenGui.Enabled = true
					progressStarted = true
				end
				return
			end
		end
	end
end

-- Function to complete current stage
local function completeCurrentStage()
	if currentStage > 0 and currentStage <= #TARGET_PART_NAMES then
		local targetPart = workspace:FindFirstChild(TARGET_PART_NAMES[currentStage])

		if targetPart then
			-- Mark stage as completed
			stageCompleted[currentStage] = true

			print("Target " .. currentStage .. " completed! " .. TARGET_PART_NAMES[currentStage])

			-- Immediately start next stage without delay
			startNextStage()
		end
	end
end

-- Function to setup touch events
local function setupTouchEvents()
	cleanupConnections()

	local startPart = workspace:FindFirstChild(START_PART_NAME)

	-- Setup start part touch event
	if startPart then
		connections[#connections + 1] = startPart.Touched:Connect(function(hit)
			if not progressStarted and hit.Parent == player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
				startNextStage() -- Start first stage
			end
		end)
	end

	-- Setup touch events for all target parts
	for i, targetName in pairs(TARGET_PART_NAMES) do
		local targetPart = workspace:FindFirstChild(targetName)
		if targetPart then
			connections[#connections + 1] = targetPart.Touched:Connect(function(hit)
				if progressStarted and currentStage == i and not stageCompleted[i] and hit.Parent == player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
					local humanoidRootPart = player.Character.HumanoidRootPart
					local distanceToTarget = getDistanceToPartSurface(targetPart, humanoidRootPart.Position)

					-- Only complete if player is actually close to the target
					if distanceToTarget <= TRIGGER_DISTANCE then
						completeCurrentStage()
					end
				end
			end)
		end
	end
end

-- Main update loop
local function updateLoop()
	-- Update speed display (always runs)
	if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
		local humanoidRootPart = player.Character.HumanoidRootPart
		local velocity = humanoidRootPart.AssemblyLinearVelocity
		local speed = math.sqrt(velocity.X^2 + velocity.Z^2) -- Only horizontal speed
		speedLabel.Text = "Speed: " .. math.floor(speed + 0.5)
	else
		speedLabel.Text = "Speed: 0"
	end

	-- Only run progress logic if character exists
	if not (player.Character and player.Character:FindFirstChild("HumanoidRootPart")) then
		return
	end

	local humanoidRootPart = player.Character.HumanoidRootPart
	local startPart = workspace:FindFirstChild(START_PART_NAME)

	-- Setup touch events once when parts are found
	local anyPartFound = startPart ~= nil
	for _, targetName in pairs(TARGET_PART_NAMES) do
		if workspace:FindFirstChild(targetName) then
			anyPartFound = true
			break
		end
	end

	if anyPartFound and #connections == 0 then
		setupTouchEvents()
	end

	-- Update progress bar
	if progressStarted and currentStage > 0 and currentStage <= #TARGET_PART_NAMES and not stageCompleted[currentStage] then
		local targetPart = workspace:FindFirstChild(TARGET_PART_NAMES[currentStage])

		if targetPart and startingDistance then
			local currentDistance = getDistanceToPartSurface(targetPart, humanoidRootPart.Position)
			distanceLabel.Text = "Distance: " .. math.floor(currentDistance + 0.5) .. " studs"

			-- Calculate progress based on surface distance
			local distanceChange = startingDistance - currentDistance
			local progress = math.clamp(distanceChange / startingDistance, 0, 1)

			progressBar.Size = UDim2.new(progress, 0, 1, 0)

			-- Color interpolation (Green to Red like original)
			local green = math.clamp((1 - progress) * 255, 0, 255)
			local red = math.clamp(progress * 255, 0, 255)
			progressBar.BackgroundColor3 = Color3.fromRGB(red, green, 0)

			-- Check if close enough to target (backup completion check)
			if currentDistance <= TRIGGER_DISTANCE then
				completeCurrentStage()
			end
		end
	end
end

-- Connect update loop
RunService.Heartbeat:Connect(updateLoop)

-- Handle respawn
player.CharacterAdded:Connect(function()
	wait(1)

	-- Reset state
	progressStarted = false
	currentStage = 0
	startingDistance = nil
	stageCompleted = {}

	-- Reset UI
	screenGui.Enabled = false
	distanceLabel.Text = ""
	progressBar.Size = UDim2.new(0, 0, 1, 0)
	progressBar.BackgroundColor3 = Color3.fromRGB(0, 255, 0)

	-- Clean up old connections and setup new ones
	cleanupConnections()
	wait(0.5) -- Small delay to ensure character is fully loaded
	setupTouchEvents()

	-- Check if player spawned near any target blocks and resume progress
	wait(0.5) -- Additional delay to ensure position is stable
	checkForTargetProgress()

	print("Character respawned, checking for progress resumption")
end)