Specific scenario causes code to only sometimes break

I have the following code which works for the most part except in the following scenario:

In the test with multiple clients in studio if I join with multiple clients so like 8 for example and then all of them but one leave the last one could get stuck never progressing onto the win area

here is the code:

help is appreciated

local SpotsFolder = game.Workspace:WaitForChild("Spots")
local WinSpot = game.Workspace.WinSpot
local Data = require(game.ServerScriptService:WaitForChild("PlayerData"):WaitForChild("Data"))
local Players = game:GetService("Players")
local PlayersInGame = 0
local Emitter = game.Workspace["Eye of Rah"].Character.Head.ParticleEmitter

function win(player)

	local char = player.Character

	SpotsFolder.Spot1.MoveTo.Occupant.Value = ""

	if char then
		player:FindFirstChild("Spot").Value = 0
		char.Humanoid:MoveTo(WinSpot.MoveTo.Position)
		Data.Profiles[player].Data.Wins += 1

		for i, player in pairs(Players:GetPlayers()) do
			local plrPosition = player:FindFirstChild("Spot")

			if plrPosition then
				if plrPosition.Value > 1 then
					local hum  = player.Character.Humanoid

					task.spawn(moveHum, hum)
				end
			end
		end
		task.wait(1.25)
		Emitter:Emit(100)
		task.wait(1.75)

		print(player.Name, " has won")

		if char then
			char.HumanoidRootPart.CFrame = SpotsFolder:FindFirstChild("Spot"..PlayersInGame).MoveTo.CFrame + Vector3.new(0,6,0)
			char.HumanoidRootPart.CFrame = CFrame.lookAt(char.HumanoidRootPart.Position, SpotsFolder:FindFirstChild("Spot"..PlayersInGame).LookAt.Position)	
			SpotsFolder:FindFirstChild("Spot"..PlayersInGame).MoveTo.Occupant.Value = char.Name
			player:FindFirstChild("Spot").Value = PlayersInGame

			if PlayersInGame == 1 then
			--	task.wait(1)
			--	task.spawn(win, player)
			end
		end		
	end
end

function moveHum(hum)
	local root = hum.Parent.HumanoidRootPart

	if root then
		local player = Players:GetPlayerFromCharacter(root.Parent)
		local plrPosition = player:FindFirstChild("Spot")

		if plrPosition then
			if plrPosition.Value > 1 then				
				if hum then
					plrPosition.Value -= 1
					hum:MoveTo(SpotsFolder:FindFirstChild("Spot"..plrPosition.Value).MoveTo.Position)
					SpotsFolder:FindFirstChild("Spot"..plrPosition.Value).MoveTo.Occupant.Value = hum.Parent.Name
					hum.MoveToFinished:Wait()
					if root then
						root.CFrame = CFrame.lookAt(root.Position, SpotsFolder:FindFirstChild("Spot"..plrPosition.Value).LookAt.Position)

						if plrPosition.Value == 1 then
							--task.wait(3.1)
						--	task.spawn(win,player)
						end
					end
				end	
			else
				--task.wait(3.1)
				--task.spawn(win,player)
			end		
		end	
	end
end

function assign(player)
	local char = player.Character or player.CharacterAdded:Wait()

	for i, part in pairs(char:GetChildren()) do
		if part:IsA("BasePart") then
			part.CollisionGroup = "Player"
		end
	end

	local root = char:WaitForChild("HumanoidRootPart")

	PlayersInGame += 1	

	local newVal = Instance.new('NumberValue',player)
	newVal.Name = "Spot"
	newVal.Value = PlayersInGame

	local assignSpot = SpotsFolder:FindFirstChild("Spot"..PlayersInGame)
	assignSpot.MoveTo.Occupant.Value = player.Name
	root.CFrame = assignSpot.MoveTo.CFrame + Vector3.new(0,6,0)
	root.CFrame = CFrame.lookAt(root.Position, assignSpot.LookAt.Position)	

	if newVal.Value == 1 then
	--	task.wait(5)
	--	task.spawn(win, player)
	end
end

function plrLeftAdjust(playerLeftPosition)
	for i, player in pairs(Players:GetPlayers()) do
		local plrPosition = player:FindFirstChild("Spot")

		if plrPosition then
			if plrPosition.Value > playerLeftPosition then

				local hum  = player.Character.Humanoid

				task.spawn(moveHum, hum)
			end
		end
	end
end

for i, player in pairs(Players:GetPlayers()) do
	task.spawn(assign, player)
end

Players.PlayerAdded:Connect(function(player)
	task.spawn(assign, player)
end)

Players.PlayerRemoving:Connect(function(player)
	local playerPosition = player.Spot.Value
	PlayersInGame -= 1
	if playerPosition ~= 0 then
		task.spawn(plrLeftAdjust, playerPosition)
	end
end)


function swapHum(movingForwards)
	if not movingForwards then return end  

	local spotValue = movingForwards:FindFirstChild("Spot")
	if not spotValue then return end 

	local forwardPointValue = spotValue.Value - 1
	if forwardPointValue < 1 then return end 

	local forwardSpot = SpotsFolder:FindFirstChild("Spot"..forwardPointValue)
	if not forwardSpot then return end 

	local movingBackName = forwardSpot.MoveTo.Occupant.Value
	local movingBack = Players:GetPlayerFromCharacter(game.Workspace:FindFirstChild(movingBackName))

	if not movingBack then return end 

	local movingBackSpot = movingBack:FindFirstChild("Spot")
	if not movingBackSpot then return end 


	movingBackSpot.Value = forwardPointValue + 1
	spotValue.Value = forwardPointValue


	SpotsFolder:FindFirstChild("Spot" .. movingBackSpot.Value).MoveTo.Occupant.Value = movingBack.Name
	forwardSpot.MoveTo.Occupant.Value = movingForwards.Name

	
	local movingBackChar = movingBack.Character
	local movingForwardsChar = movingForwards.Character

	if movingBackChar and movingBackChar:FindFirstChild("HumanoidRootPart") then
		local backRoot = movingBackChar.HumanoidRootPart
		backRoot.CFrame = SpotsFolder:FindFirstChild("Spot" .. movingBackSpot.Value).MoveTo.CFrame + Vector3.new(0, 6, 0)
		backRoot.CFrame = CFrame.lookAt(backRoot.Position, SpotsFolder:FindFirstChild("Spot" .. movingBackSpot.Value).LookAt.Position)
	end

	if movingForwardsChar and movingForwardsChar:FindFirstChild("HumanoidRootPart") then
		local forwardRoot = movingForwardsChar.HumanoidRootPart
		forwardRoot.CFrame = forwardSpot.MoveTo.CFrame + Vector3.new(0, 6, 0)
		forwardRoot.CFrame = CFrame.lookAt(forwardRoot.Position, forwardSpot.LookAt.Position)
	end
end

task.wait(5)

task.spawn(function()
	while task.wait(5) do
		local player = Players:GetPlayerFromCharacter(game.Workspace:FindFirstChild(SpotsFolder.Spot1.MoveTo.Occupant.Value))
		if player then
			task.spawn(win, player)
		end
	end
end)

local MS = game:GetService("MarketplaceService")

local function process(info)

	local userId = info.PlayerId
	local productId = info.ProductId
	local player = game.Players:GetPlayerByUserId(userId)

	if info.ProductId == 2840392821 then

		if player:FindFirstChild('Spot').Value > 1 then
			swapHum(player)
			return Enum.ProductPurchaseDecision.PurchaseGranted
		else
			return Enum.ProductPurchaseDecision.NotProcessedYet
		end

	end

end


MS.ProcessReceipt = process