Huge round bug with swordfighting game, no script analysis or output errors

  1. What do you want to achieve? Keep it simple and clear!

I am making a sword fighting game based off of an Alvinblox tutorial series (How To Make A Roblox Game - Episode 3 - YouTube), with some things slightly and carefully changed. I have copied every single block of code word by word, with some names being different.

  1. What is the issue? Include screenshots / videos if possible!

Unfortunately, the game keeps looping very quickly through every stage of the game (intermission → choosing map → players fight → game over → intermission → …) very quickly in an endless loop, with the players constantly getting respawned and getting their swords back.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I have watched the video about 10-15 times, comparing my code constantly with his for any possible mistakes. Additionally, I put multiple print commands in the entire script to check if there were any mistakes there, but, as seen in the video, the prints work perfectly fine. Asking for help in two different servers (dev section in ROBLOX + RoDevs server) worked to no avail. The variables all match up with the object, the script analysis and output don’t register any errors, and I have been trying to fix this for about 4 hours now.
After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!
This is my code:

	-- Variables
	local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local ServerStorage = game:GetService("ServerStorage")
	local MapsFolder = game.ServerStorage:WaitForChild("Maps")

	local Status = ReplicatedStorage:WaitForChild("Status")
	local GameLength = 60

	local reward = 25 

	-- Game loop

	while true do 
		Status.Value = "Waiting for enough players..." 
		repeat wait(1) until game.Players.NumPlayers >= 2
		Status.Value = "Intermission..."
		wait(10)
		local plrs = {} -- Creates the plrs table
		for i, player in pairs (game.Players:GetPlayers()) do 
			if player then 
				table.insert(plrs, player) -- Adds each player to the plrs table
				
			end
		end  
		wait (2)
		
		local AvailableMaps = MapsFolder:GetChildren()
		local ChosenMap = AvailableMaps[math.random(1, #AvailableMaps)]
		
		Status.Value = ChosenMap.Name.." Chosen"
		local ClonedMap = ChosenMap:Clone()
		ClonedMap.Parent = game.Workspace 
		
		-- Teleport Players to the map	
		
		local SpawnPoints = ClonedMap:FindFirstChild("SpawnPoints")
		if not SpawnPoints then 
			print("Spawnpoints not found!")
		end
		
		local AvailableSpawnPoints = SpawnPoints:GetChildren()
		
		for i, player in pairs(plrs) do 
			if player then 
				character = player.Character
				
				-- Teleport them
				
				character:FindFirstChild("HumanoidRootPart").CFrame = AvailableSpawnPoints[1].CFrame
				table.remove(AvailableSpawnPoints, 1)
				
				-- Give them a sword
				local Sword = ServerStorage.ClassicSword:Clone()
				Sword.Parent = player.Backpack
				
				local GameTag = Instance.new("BoolValue")
				GameTag.Name = "GameTag"
				GameTag.Parent = player.Character
			else
				-- There is no character
				if not player then 
					table.remove(plrs,i)
				end
			end
		end
	end

	Status.Value = "Get ready to fight!"

	wait(2)

	for i = GameLength, 0, -1 do
		wait (1)
		for x, player in pairs(plrs) do
			if player then 
				character = player.Character 
				if not character then
					-- Left the game
				else
					if character:FindFirstChild("GameTag") then
						-- They are still alive
						print(player.Name.." is still in the game.")
					else 
						-- They are dead
						table.remove(plrs,x)
						print(player.Name.." has been removed.")
					end
				end
			else table.remove(plrs,x)
				print(player.Name.." has been removed.")
			end
		end
		Status.Value = "There are "..i.." seconds remaining, and "..#plrs.." left."
		
	if #plrs >0 then
		if #plrs == 1 then
			-- Last person standing
			Status.Value = "The winner is "..plrs[1].Name 
			plrs[1].leaderstats.Cash.Value = plrs[1].leaderstats.Cash.Value + reward -- Rewards the player with variable reward
			end
	else 
			Status.Value = "Nobody won!"
			

		print("End of game!")
	end
	if i == 0 then
	Status.Value = "Time up!"
end
		
		for i, player in pairs(game.Players:GetPlayers()) do 
			character = player.Character
			
			if not character then 
				-- Ignore them
			else 
				if character:FindFirstChild("GameTag")  then
					character.GameTag:Destroy()
				end
				if player.Backpack:FindFirstChild("ClassicalSword") then 
					player.Backpack.ClassicalSword:Destroy()
				end
				if character:FindFirstChild("ClassicalSword") then 
					character.ClassicalSword:Destroy()
				end
				player:LoadCharacter()
			end
		end
		
		ClonedMap:Destroy()
		wait(2)
		Status.Value = "Game ended!"
	end
2 Likes

Several issues.

  1. The game ends immediately because you forgot to separate out the game end code outside of the for loop, so the game ended the moment the game ticked, which obviously isn’t intended.
  2. local plrs = {} was declared inside of a while loop, but was not accessible to the game tick for loop, or anything else for that matter.
  3. Even when the first two issues have been fixed, the ClonedMap variable was declared in a not-so-ideal spot.

I have fixed all the issues described, and it should work now.

-- Variables
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local MapsFolder = game.ServerStorage:WaitForChild("Maps")

local Status = ReplicatedStorage:WaitForChild("Status")
local GameLength = 60

local reward = 25 

-- Game loop

local plrs = {} -- Creates the plrs table
local ClonedMap
while true do 
	Status.Value = "Waiting for enough players..." 
	repeat wait(1) until game.Players.NumPlayers >= 2
	Status.Value = "Intermission..."
	wait(10)
	for i, player in pairs (game.Players:GetPlayers()) do 
		if player then 
			table.insert(plrs, player) -- Adds each player to the plrs table
			
		end
	end  
	wait (2)
	
	local AvailableMaps = MapsFolder:GetChildren()
	local ChosenMap = AvailableMaps[math.random(1, #AvailableMaps)]
	
	Status.Value = ChosenMap.Name.." Chosen"
	ClonedMap = ChosenMap:Clone()
	ClonedMap.Parent = game.Workspace 
	
	-- Teleport Players to the map	
	
	local SpawnPoints = ClonedMap:FindFirstChild("SpawnPoints")
	if not SpawnPoints then 
		print("Spawnpoints not found!")
	end
	
	local AvailableSpawnPoints = SpawnPoints:GetChildren()
	
	for i, player in pairs(plrs) do 
		if player then 
			character = player.Character
			
			-- Teleport them
			
			character:FindFirstChild("HumanoidRootPart").CFrame = AvailableSpawnPoints[1].CFrame
			table.remove(AvailableSpawnPoints, 1)
			
			-- Give them a sword
			local Sword = ServerStorage.ClassicSword:Clone()
			Sword.Parent = player.Backpack

			local GameTag = Instance.new("BoolValue")
			GameTag.Name = "GameTag"
			GameTag.Parent = player.Character
		else
			-- There is no character
			if not player then 
				table.remove(plrs,i)
			end
		end
	end
end

Status.Value = "Get ready to fight!"

wait(2)

for i = GameLength, 0, -1 do
	wait(1)
	for x, player in pairs(plrs) do
		if player then 
			character = player.Character 
			if not character then
				-- Left the game
			else
				if character:FindFirstChild("GameTag") then
					-- They are still alive
					print(player.Name.." is still in the game.")
				else 
					-- They are dead
					table.remove(plrs,x)
					print(player.Name.." has been removed.")
				end
			end
		else table.remove(plrs,x)
			print(player.Name.." has been removed.")
		end
	end
	Status.Value = "There are "..i.." seconds remaining, and "..#plrs.." left."
end

if #plrs >0 then
	if #plrs == 1 then
		-- Last person standing
		Status.Value = "The winner is "..plrs[1].Name 
		plrs[1].leaderstats.Cash.Value = plrs[1].leaderstats.Cash.Value + reward -- Rewards the player with variable reward
	end
else 
	Status.Value = "Nobody won!"
	
	
	print("End of game!")
end
Status.Value = "Time up!"

for i, player in pairs(game.Players:GetPlayers()) do 
	character = player.Character
	
	if not character then 
		-- Ignore them
	else 
		if character:FindFirstChild("GameTag")  then
			character.GameTag:Destroy()
		end
		if player.Backpack:FindFirstChild("ClassicalSword") then 
			player.Backpack.ClassicalSword:Destroy()
		end
		if character:FindFirstChild("ClassicalSword") then 
			character.ClassicalSword:Destroy()
		end
		player:LoadCharacter()
	end
end

if ClonedMap then
	ClonedMap:Destroy()
	ClonedMap = nil
end
wait(2)
Status.Value = "Game ended!"

Unfortunately, that did not fix it: the same issue still appears.
What do you think is the problem?
Thanks in advance for your help.

Afte a bit of testing it appears that this may have broken the game a slight bit more: the TextLabel now only channels through “Intermission…” and “ObbyMap Chosen”. Dying in-game also does not affect the round system at all. Here is a video showing what happened after changing the script.

-- Variables
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local MapsFolder = game.ServerStorage:WaitForChild("Maps")

local Status = ReplicatedStorage:WaitForChild("Status")
local GameLength = 60

local reward = 25 

-- Game loop

while true do 
	Status.Value = "Waiting for enough players..." 
	
	repeat task.wait(1) until game.Players:GetPlayers() >= 2
	
	Status.Value = "Intermission..."
	
	task.wait(10)
	
	local plrs = {} -- Creates the plrs table
	
	for _, player in ipairs(game.Players:GetPlayers()) do 
		if player then 
			table.insert(plrs, player) -- Adds each player to the plrs table
		end
	end  
	
	task.wait(2)

	local AvailableMaps = MapsFolder:GetChildren()
	local ChosenMap = AvailableMaps[math.random(1, #AvailableMaps)]

	Status.Value = `{ChosenMap.Name}, Chosen`
	local ClonedMap = ChosenMap:Clone()
	ClonedMap.Parent = workspace

	-- Teleport Players to the map	

	local SpawnPoints = ClonedMap:FindFirstChild("SpawnPoints")
	
	if not SpawnPoints then 
		error("Spawnpoints not found!")
	end

	local AvailableSpawnPoints = SpawnPoints:GetChildren()

	for index, player in ipairs(plrs) do 
		if player then 
			character = player.Character

			if character then
				local hrp = character:FindFirstChild("HumanoidRootPart")
				hrp.CFrame = AvailableSpawnPoints[1].CFrame
				table.remove(AvailableSpawnPoints, 1)

				-- Give them a sword
				local Sword = ServerStorage.ClassicSword:Clone()
				Sword.Parent = player.Backpack

				local GameTag = Instance.new("BoolValue")
				GameTag.Name = "GameTag"
				GameTag.Value = true
				GameTag.Parent = player.Character
			else
				table.remove(plrs, index)
			end	
		end
	end
	
	Status.Value = "Get ready to fight!"

	task.wait(2)

	for length = GameLength, 0, -1 do
		task.wait(1)
		for index, player in ipairs(plrs) do
			if player then 
				character = player.Character
				
				if not character then
					table.remove(plrs, index)
				else
					if character:FindFirstChild("GameTag") then
						-- They are still alive
						print(player.Name.." is still in the game.")
					else 
						-- They are dead
						table.remove(plrs, index)
						print(player.Name.." has been removed.")
					end
				end
			else
				table.remove(plrs, index)
				print(player.Name.." has been removed.")
			end
		end
		
		Status.Value = "There are "..length.." seconds remaining, and "..#plrs.." left."

		if #plrs > 0 then
			if #plrs == 1 then
				-- Last person standing
				Status.Value = "The winner is "..plrs[1].Name 
				plrs[1].leaderstats.Cash.Value = plrs[1].leaderstats.Cash.Value + reward -- Rewards the player with variable reward
			end
		elseif #plrs == 0 then
			Status.Value = "Nobody won!"

			print("End of game!")
		elseif length == 0 then
			Status.Value = "Time up!"
		end
	end
	
	for _, player in pairs(game.Players:GetPlayers()) do 
		character = player.Character

		if not character then 
			-- Ignore them
		else 
			if character:FindFirstChild("GameTag")  then
				character.GameTag:Destroy()
			end
			if player.Backpack:FindFirstChild("ClassicalSword") then 
				player.Backpack.ClassicalSword:Destroy()
			end
			if character:FindFirstChild("ClassicalSword") then 
				character.ClassicalSword:Destroy()
			end
			player:LoadCharacter()
		end
	end

	ClonedMap:Destroy()
	wait(2)
	Status.Value = "Game ended!"
end

@Bobgamertv1ste This should work.

Thanks for sending me this script.
It fixes the previous problems, but creates a new one: after a player wins the game, they stay in the map itself for an infinite amount of time and gain 25 every second.
Here is a video containing the issue:

-- Variables
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local MapsFolder = game.ServerStorage:WaitForChild("Maps")

local Status = ReplicatedStorage:WaitForChild("Status")
local GameLength = 60

local reward = 25 

-- Game loop

while true do 
	Status.Value = "Waiting for enough players..." 

	repeat task.wait(1) until game.Players:GetPlayers() >= 2

	Status.Value = "Intermission..."

	task.wait(10)

	local plrs = {} -- Creates the plrs table

	for _, player in ipairs(game.Players:GetPlayers()) do 
		if player then 
			table.insert(plrs, player) -- Adds each player to the plrs table
		end
	end  

	task.wait(2)

	local AvailableMaps = MapsFolder:GetChildren()
	local ChosenMap = AvailableMaps[math.random(1, #AvailableMaps)]

	Status.Value = `{ChosenMap.Name}, Chosen`
	local ClonedMap = ChosenMap:Clone()
	ClonedMap.Parent = workspace

	-- Teleport Players to the map	

	local SpawnPoints = ClonedMap:FindFirstChild("SpawnPoints")

	if not SpawnPoints then 
		error("Spawnpoints not found!")
	end

	local AvailableSpawnPoints = SpawnPoints:GetChildren()

	for index, player in ipairs(plrs) do 
		if player then 
			character = player.Character

			if character then
				local hrp = character:FindFirstChild("HumanoidRootPart")
				hrp.CFrame = AvailableSpawnPoints[1].CFrame
				table.remove(AvailableSpawnPoints, 1)

				-- Give them a sword
				local Sword = ServerStorage.ClassicSword:Clone()
				Sword.Parent = player.Backpack

				local GameTag = Instance.new("BoolValue")
				GameTag.Name = "GameTag"
				GameTag.Value = true
				GameTag.Parent = player.Character
			else
				table.remove(plrs, index)
			end	
		end
	end

	Status.Value = "Get ready to fight!"

	task.wait(2)

	for length = GameLength, 0, -1 do
		task.wait(1)
		for index, player in ipairs(plrs) do
			if player then 
				character = player.Character

				if not character then
					table.remove(plrs, index)
				else
					if character:FindFirstChild("GameTag") then
						-- They are still alive
						print(player.Name.." is still in the game.")
					else 
						-- They are dead
						table.remove(plrs, index)
						print(player.Name.." has been removed.")
					end
				end
			else
				table.remove(plrs, index)
				print(player.Name.." has been removed.")
			end
		end

		Status.Value = "There are "..length.." seconds remaining, and "..#plrs.." left."

		if #plrs > 0 then
			if #plrs == 1 then
				-- Last person standing
				Status.Value = "The winner is "..plrs[1].Name 
				plrs[1].leaderstats.Cash.Value += reward -- Rewards the player with variable reward
				
				break
			end
		elseif #plrs == 0 then
			Status.Value = "Nobody won!"

			break
		elseif length == 0 then
			Status.Value = "Time up!"
		end
	end

	for _, player in pairs(game.Players:GetPlayers()) do 
		character = player.Character

		if not character then 
			-- Ignore them
		else 
			if character:FindFirstChild("GameTag")  then
				character.GameTag:Destroy()
			end
			if player.Backpack:FindFirstChild("ClassicalSword") then 
				player.Backpack.ClassicalSword:Destroy()
			end
			if character:FindFirstChild("ClassicalSword") then 
				character.ClassicalSword:Destroy()
			end
			player:LoadCharacter()
		end
	end

	ClonedMap:Destroy()
	wait(2)
	Status.Value = "Game ended!"
end

Forgot to add some breaks mb.

1 Like

Thanks so much for helping me!
btw: on line 16, the game doesn’t work, because it should be

	repeat task.wait(1) until game.Players.NumPlayers >= 2

also, is wait() not the same as task.wait(), but faster?

game.Players.NumPlayers is deprecated, and you should instead use #game.Players:GetPlayers() (I forgot to add a #). And task.wait is superior over wait and won’t throttle your code.

Unlike the deprecated global wait, this function does not throttle and guarantees the resumption of the thread on the first Heartbeat that occurs when it is due. This function also only returns the elapsed time and nothing else.

1 Like

Alright, thanks a lot for your help and information.
Have a nice day!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.