Another found bug in my stupid round system for my stupid game

Alright this is highkey getting really aggravating at this point. My code works and doesn’t work at the same time. What’s supposed to happen is when you die you shouldn’t get any wins, the round shouldn’t get increased by one nor should there be multiple temporary shops for the player to buy from. I’m really hoping this post gets enough attention to at least battle this problem because this is a CRY FOR HELP. So please help me with this and maybe I’ll be able to actually have this game out by the deadline. :pray:
Code:

--//variables
local DS2 = require(1936396537)
local RF = game:GetService("ReplicatedFirst")
local RS = game:GetService("ReplicatedStorage")
local run = game:GetService("RunService")
local players = game:GetService("Players")
local zombs = RS:WaitForChild("Dummies")
local event = RS:WaitForChild("roundEvent")
local deathMsg = RS:WaitForChild("deathMsg")
local round = RS:WaitForChild("round").Value
local dumNum = RS:WaitForChild("dumNum").Value
local startTime = 30
local interlude = 15
local match = true
local dead = false
local win = false
local peds = game.Workspace:WaitForChild("Peds"):GetChildren()
local spawns = game.Workspace:WaitForChild("Ignored").spawnPoints
local spawnNums = spawns:GetChildren()
local status = game:GetService("ServerStorage").Status

players.PlayerAdded:Connect(function(plr)
	local gui = plr:WaitForChild("PlayerGui")
	local UI

	for i, v in pairs(RF.UI:GetChildren()) do
		local difUI = v:Clone()

		difUI.Parent = gui
		if difUI.Name == "MainUI" then
			UI = difUI
		end
	end
	
	--//spawning the player
	RS.spawnPlr.OnServerEvent:Connect(function(plr)
		plr:LoadCharacter()
		match = true
	end)
	
	plr.CharacterAdded:Connect(function(char)
		print("character added working")
		local wins = DS2("wins", plr)
		local points = plr.leaderstats:WaitForChild("Points")
		local shopModel = RS.Shop.Models.tempShop
		
		local shopClone = shopModel:Clone()
		
		local function died()
			match = false
			status.Value = "Intermission"
			round = 0
			event:FireAllClients(round, status.Value)
			task.wait(2)
			points.Value = 0
			for _,v in pairs(peds) do
				v:Destroy()
			end
			startTime = 30
			dumNum = 10
			UI.zombsLeft.Text = ""
			dead = true
			
			if shopClone.Parent == game.Workspace then
				shopClone:Destroy()
			end
		end
		
		--//starting game
		plr.CharacterAppearanceLoaded:Connect(function()
			RS:WaitForChild("ammo"):FireClient(plr)
			local hum = char:WaitForChild("Humanoid")
			dead = false
			status.Value = "Intermission"
			UI.zombsLeft.Text = ""
			
			run.Stepped:Connect(function()
				hum.Died:Connect(function()
					died()
				end)
			end)
			
			while dead == false and match == true do
				
				task.wait()
				if plr:HasAppearanceLoaded() then
					
					--// loads temporary shop for player
					if status.Value == "Intermission" then
						shopClone = shopModel:Clone()
						shopClone.Parent = game.Workspace
						task.wait(interlude)
						shopClone:Destroy()
					end
					
					round += 1
					event:FireAllClients(round, status.Value)

					--//spawns in zombies
					if dead ~= true and match == true then
						for i = 0, dumNum-1, 1 do
							local randSpawn = math.random(#spawnNums)
							print(randSpawn)
							local randTime = math.random(1,7)
							local wTime = randTime / 10
							local clone = zombs.Dummy:Clone()
							print(wTime)
							task.wait(wTime)

							local rand = math.random(1, 5)


							local spawnPoint = spawns:FindFirstChild(randSpawn)
							clone.HumanoidRootPart.Position = spawnPoint.Position

							clone.Parent = game.Workspace.Peds
							if round >= 7 then
								local tanky = zombs.Tanky:Clone()

								if rand == 3 then
									tanky.Parent = game.Workspace.Peds
									tanky.HumanoidRootPart.Position = spawnPoint.Position
									clone:Destroy()
								end
							elseif round >= 3 then
								local speedy = zombs.Speedy:Clone()

								if rand == 1 then
									speedy.Parent = game.Workspace.Peds
									speedy.HumanoidRootPart.Position = spawnPoint.Position
									clone:Destroy()
								end
							end
						end
					else
						break
					end
					
					--//makes player in round and increases amount of zombies for next round
					status.Value = "Round"
					event:FireAllClients(round, status.Value)
					dumNum += 3
					
					
					if status.Value == "Round" and dead ~= true then
						print("got into round")
						
						--//checks again if player has died during round
						
						for i = startTime, 0, -1 do
							peds = game.Workspace.Peds:GetChildren()
							if status.Value == "Round" and dead == false then
								UI.zombsLeft.Text = "Zombies left: "..#peds
							
								if #peds == 0 then
									status.Value = "Intermission"
									event:FireAllClients(round, status.Value)
									win = true
									break
								end

							else
								break
							end
							task.wait(1)
						end
						
						while not (#peds == 0) do
							peds = game.Workspace.Peds:GetChildren()

							event:FireAllClients("Over Time")
							
							task.wait()
							if #peds == 0 then
								status.Value = "Intermission"
								event:FireAllClients(round, status.Value)
								win = true
								break
							end
							
							UI.zombsLeft.Text = "Zombies left: "..#peds
						end
						
						if #peds == 0 then
							status.Value = "Intermission"
							event:FireAllClients(round, status.Value)
							win = true
							UI.zombsLeft.Text = ""
						end

						if status.Value == "Round" and dead == true then
							break
						else
							status.Value = "Intermission"
							event:FireAllClients(round, status.Value)
							win = true
						end
					else
						break
					end
					
					--//increases amount of time per round and wins
					if win == true then
						startTime += 15
						wins:Increment(1)
						win = false
						print("player won")
					end

				end
			end
		end)
	end)
end)


This is a video of what’s happening using roblox’s video recording cause I don’t feel like pulling out OBS (1.5 MB)
'Preciate the support if any (I know for a fact there won’t :sob:)
-Dza

1 Like

I know this might be a stupid question, but have you tried checking whether or not the died() function is ever called? I couldn’t really find any problems that might cause the issues present other than the died() function not being called.

I put a print statement in the function to make sure it runs and it printed 164x that i died so the function is working properly

PS: ty for responding :]

That’s strange, I’ll try to take a look to see if I can figure out the problem.

First, you don’t need to have the hum.Died within a run.Stepped.

Just leave have hum.Died on its own, like this:

plr.CharacterAppearanceLoaded:Connect(function()
			RS:WaitForChild("ammo"):FireClient(plr)
			local hum = char:WaitForChild("Humanoid")
			dead = false
			status.Value = "Intermission"
			UI.zombsLeft.Text = ""

			hum.Died:Connect(function()
				died()
			end)

I believe that is why you see the died() function being called 164 times, as it created 164 connections of the hum.Died event. I’m not sure if it is the reason the store is breaking, but fixing that should help with optimization and debugging in general, since the hum.Died event is being called way more than it should be.

Next, I’m not sure if I’m misunderstanding, but if this script is the one that handles spawning the player in, then I think you should put the plr.CharacterAppearanceLoaded event within the RS.spawnPlr.OnServerEvent, since you are spawning the character then anyway.

It would look something like this:

RS.spawnPlr.OnServerEvent:Connect(function(plr)
	plr:LoadCharacter()
	match = true

	plr.CharacterAppearanceLoaded:Connect(function()
		RS:WaitForChild("ammo"):FireClient(plr)

Finally, I think you should remove the shopClone idea, and instead just change the shop’s parent instead. Have it initially in ReplicatedStorage like normal, and when you need the shop, just change the shop.Parent to workspace.

I don’t think this will really fix the major issues, but hopefully it helps a little with optimization and debugging.

I’ll reply again if I find any more problems.

Wait, I think I might have figured out the issue. The way you have it right now, you are not disconnecting the plr.CharacterAppearanceLoaded event at all, and you just continuously create more while keeping the old ones, causing them to stack up. Currently, the round system and how every spawns in general is dictated within CharacterAppearanceLoaded connected function. What this does is every single time the player respawns, a new plr.CharacterAppearanceLoaded event is connected and the function which spawns the shop and such is played.

Basically, when you spawn for the first time, a shop is spawned. When you spawn for the second time, the CharacterAppearanceLoaded event created from your first spawn fires, creating a shop, but a new one is also fired, creating a second shop. This continues as you die over and over again, which is what causes the problem.

This also means that having multiple players join will likely cause the same problem, as a CharacterAppearanceLoaded event will be connected for each one.

Unfortunately, the solution to this problem will likely require you to do a big rewrite of your current system. The best solution I could think of is to make it so that the CharacterAppearanceLoaded event is connected only once.

PS: The problem might not only be within the CharacterAppearanceLoaded event, and I simply focused on that event because it was the most prominent one.

This actually sounds like the most probable reason as to why everything isn’t working properly. Thank you so much for figuring this out because I 100% would’ve quit this game and not worked on it at all. I’m gonna learn about how to disconnect events and such so that I don’t have to rewrite everything but if I do, that’s fine.
Thanks again! :smiley:

No problem!

Here is my attempt at rewriting the script to make it work:

--//variables
local DS2 = require(1936396537)
local RF = game:GetService("ReplicatedFirst")
local RS = game:GetService("ReplicatedStorage")
local run = game:GetService("RunService")
local players = game:GetService("Players")
local zombs = RS:WaitForChild("Dummies")
local event = RS:WaitForChild("roundEvent")
local deathMsg = RS:WaitForChild("deathMsg")
local round = RS:WaitForChild("round").Value
local dumNum = RS:WaitForChild("dumNum").Value
local startTime = 30
local interlude = 15
local match = true
local dead = false
local win = false
local peds = game.Workspace:WaitForChild("Peds"):GetChildren()
local spawns = game.Workspace:WaitForChild("Ignored").spawnPoints
local spawnNums = spawns:GetChildren()
local status = game:GetService("ServerStorage").Status

players.PlayerAdded:Connect(function(plr)
	local gui = plr:WaitForChild("PlayerGui")
	local UI

	for i, v in pairs(RF.UI:GetChildren()) do
		local difUI = v:Clone()

		difUI.Parent = gui
		if difUI.Name == "MainUI" then
			UI = difUI
		end
	end
	
	RS.spawnPlr.OnServerEvent:Connect(function(plr)
		--Intialize died event
		local diedEvent = nil
		
		--Load character
		plr:LoadCharacter()
		match = true
		
		--Load player stats and shop
		local wins = DS2("wins", plr)
		local points = plr.leaderstats:WaitForChild("Points")
		local shopModel = RS.Shop.Models.tempShop

		local shopClone = shopModel:Clone()
		
		plr.CharacterAppearanceLoaded:Wait() --Wait until the character appearance is loaded
		
		--Starting the game
		print("character added working")
		local char = plr.Character
		
		local wins = DS2("wins", plr)
		local points = plr.leaderstats:WaitForChild("Points")
		local shopModel = RS.Shop.Models.tempShop

		local shopClone = shopModel:Clone()

		--//starting game
		RS:WaitForChild("ammo"):FireClient(plr)
		local hum = char:WaitForChild("Humanoid")
		dead = false
		status.Value = "Intermission"
		UI.zombsLeft.Text = ""
		
		diedEvent = hum.Died:Connect(function()
			match = false
			status.Value = "Intermission"
			round = 0
			event:FireAllClients(round, status.Value)
			task.wait(2)
			points.Value = 0
			for _,v in pairs(peds) do
				v:Destroy()
			end
			startTime = 30
			dumNum = 10
			UI.zombsLeft.Text = ""
			dead = true

			if shopClone.Parent == game.Workspace then
				shopClone:Destroy()
			end
			
			diedEvent:Disconnect()
		end)

		while dead == false and match == true do
			--// loads temporary shop for player
			if status.Value == "Intermission" then
				shopClone = shopModel:Clone()
				shopClone.Parent = game.Workspace
				task.wait(interlude)
				shopClone:Destroy()
			end

			round += 1
			event:FireAllClients(round, status.Value)

			--//spawns in zombies
			if dead ~= true and match == true then
				for i = 0, dumNum-1, 1 do
					local randSpawn = math.random(#spawnNums)
					print(randSpawn)
					local randTime = math.random(1,7)
					local wTime = randTime / 10
					local clone = zombs.Dummy:Clone()
					print(wTime)
					task.wait(wTime)

					local rand = math.random(1, 5)

					local spawnPoint = spawns:FindFirstChild(randSpawn)
					clone.HumanoidRootPart.Position = spawnPoint.Position

					clone.Parent = game.Workspace.Peds
					if round >= 7 then
						local tanky = zombs.Tanky:Clone()

						if rand == 3 then
							tanky.Parent = game.Workspace.Peds
							tanky.HumanoidRootPart.Position = spawnPoint.Position
							clone:Destroy()
						end
					elseif round >= 3 then
						local speedy = zombs.Speedy:Clone()

						if rand == 1 then
							speedy.Parent = game.Workspace.Peds
							speedy.HumanoidRootPart.Position = spawnPoint.Position
							clone:Destroy()
						end
					end
				end
			else
				break
			end

			--//makes player in round and increases amount of zombies for next round
			status.Value = "Round"
			event:FireAllClients(round, status.Value)
			dumNum += 3


			if status.Value == "Round" and dead ~= true then
				print("got into round")

				--//checks again if player has died during round

				for i = startTime, 0, -1 do
					peds = game.Workspace.Peds:GetChildren()
					if status.Value == "Round" and dead == false then
						UI.zombsLeft.Text = "Zombies left: "..#peds

						if #peds == 0 then
							status.Value = "Intermission"
							event:FireAllClients(round, status.Value)
							win = true
							break
						end

					else
						break
					end
					task.wait(1)
				end

				while not (#peds == 0) do
					peds = game.Workspace.Peds:GetChildren()

					event:FireAllClients("Over Time")

					task.wait()
					if #peds == 0 then
						status.Value = "Intermission"
						event:FireAllClients(round, status.Value)
						win = true
						break
					end

					UI.zombsLeft.Text = "Zombies left: "..#peds
				end

				if #peds == 0 then
					status.Value = "Intermission"
					event:FireAllClients(round, status.Value)
					win = true
					UI.zombsLeft.Text = ""
				end

				if status.Value == "Round" and dead == true then
					break
				else
					status.Value = "Intermission"
					event:FireAllClients(round, status.Value)
					win = true
				end
			else
				break
			end

			--//increases amount of time per round and wins
			if win == true then
				startTime += 15
				wins:Increment(1)
				win = false
				print("player won")
			end
		end
	end)
end)

I didn’t really change what happens, but rather when it happens. I’ll reply with a list of the main changes I made later.

Note: There is likely going to be bugs within the code

This is actually a start, so I have been troubleshooting and testing this out for a bit now and realized that the connection I do need to disconnect is the characterappearance loaded function. Your code does actually work to an extent, my only issue is if a player resets before the round has started, that’s when rounds get stacked on top of each other.

So here are the changes I made to the script:

  • The big one, changing how CharacterAppearanceLoaded is used. Instead of making the game start whenever the CharacterAppearanceLoaded event is called, I instead made it so that the script waits for the CharacterAppearanceLoaded event is called, and then run the code by doing CharacterAppearanceLoaded:Wait(). This makes it so that the game can only be ran once whenever the spawnPlr event is called (hopefully)
  • I also put the code within the CharacterAdded event from the original script into RS.spawnPlr instead simply because from what I see, CharacterAdded will be immediately called after RS.spawnPlr is called anyway. However, I might be mistaken, so you can just put everything after line 41 into a CharacterAddedEvent instead.
  • Just adding some comments to make the code easier to follow hopefully
  • Putting hum.Died within a variable, so that it can disconnect itself when the event is called, preventing it from ever running multiple times.
  • Deleted the died() function, and simply put its content within hum.Died:Connect(function()) instead

I hope I was able provide enough help, and good luck with your game!

2 Likes

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