Broken Round System consisting of Recursion and Randomizing BrickColor Mechanic

I’m trying to make a Round System like the one made in the popular Color Block on Roblox but I don’t know how to restart the round when a player wins because if I use recursion, I can’t show the gui for voting, and if I use a while loop, I can’t restart the round at all(If I try, the loops that are firing the player’s gui will overlap).

When all the players die in a round, they respawn without seeing the voting gui(my current problem).

Core Round System

(There are many more modules but this is the main one, I will show any of the other modules if asked.)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")

local Remotes = ReplicatedStorage.Remotes
local ServerBinds = ServerStorage.ServerBinds
local ROUND_START = 100
local ROUND_END = 0
local ROUND_UPDATE = 15
local START_TIME = 15
local END_TIME = 0
local MINIMUM_PLAYERS = 1
local VOTING = false


local InRound = require(script.InRound)
local PlayerRemover = require(script.PlayerRemover)
local MapHandler = require(script.MapHandler)
local Colors = require(script.Colors)
local BrickColors = require(script.BrickColors)
local Ending = require(script.Ending)
local ServerStatus = ServerStorage.ServerStatus
local CurrentMap = ServerStorage.CurrentMap

local MapChoices = {
	FlatColorMap = 0,
}

local RoundCounter = 0

local playersInRound = {}
local playersVoted = {}
local playersWhoHaveDied = {}

local Core = {}

function Core:Init()
	local STOP = false
	local PlayersAdded = {}
	repeat
		task.wait(1)
	until #Players:GetPlayers() >= MINIMUM_PLAYERS
	
	ServerStatus.Value = "Intermission"
	Remotes.Voting:FireAllClients("TurnOn")
	VOTING = true
	Remotes.RespawnVote.OnServerEvent:Connect(function(player)
		if VOTING == true then
			Remotes.Voting:FireClient(player,"TurnOn")
		end
	end)
	Remotes.Voting.OnServerEvent:Connect(function(player,vote)
		if typeof(vote) ~= "string" then return end
		if playersVoted[player] and playersVoted[player] == vote then return end
		for i,v in MapChoices do
			if vote == tostring(i) then
				if playersVoted[player] then
					MapChoices[playersVoted[player]] -= 1
				end
				playersVoted[player] = vote
				MapChoices[i] += 1
			end
		end
	end)
	
	for i = START_TIME,END_TIME,-1 do
		Remotes.ShowStatus:FireAllClients("Intermission: " .. tostring(i))
		task.wait(1)
	end
	Remotes.Voting:FireAllClients("TurnOff")
	VOTING = false

	playersVoted = {}
	
	
	for i,player in Players:GetPlayers() do
		table.insert(playersInRound,player)
	end
	
	local ChosenMap,Pos,MapVal = MapHandler:Start(MapChoices)
	local FirstColors = BrickColors:Roll(3)
	Colors:ColorMap(ChosenMap,FirstColors)
	Colors:Update(ChosenMap,FirstColors)
	InRound:Init(playersInRound,Pos)
	CurrentMap.Value = MapVal
	ServerStatus.Value = "Round"
	
	for i,runner in playersInRound do
		local character = runner.Character or runner.CharacterAdded:Wait()
		character.Humanoid.Died:Connect(function()
			PlayerRemover:Die(runner,playersInRound,playersWhoHaveDied)
			if #playersInRound == 1 then
				Ending:Win(Remotes.Ending,playersInRound,playersWhoHaveDied)
				task.wait()
				STOP = true
				task.wait(3)
				self:Reset(ChosenMap)
				self:Init()
				task.wait(1)
				return
				--[[
								repeat
					print(#playersInRound)
					if #playersInRound ~= 0 then continue end
					if ServerStatus.Value == "Intermission" then break end
					STOP = true
					task.wait(3)
					self:Reset(ChosenMap)
					self:Init()
					task.wait(1)
					return
				until #playersInRound == 0
				--]]
			end
		end)
	end
	
	for i = ROUND_START,ROUND_END,-1 do
		if STOP == true then return end
		RoundCounter = i
		if RoundCounter % ROUND_UPDATE == 0 then
			if RoundCounter ~= ROUND_UPDATE then
				local BrickColorsTable = BrickColors:Roll(3)
				Colors:Update(ChosenMap,BrickColorsTable)
			elseif RoundCounter <= ROUND_START - ROUND_UPDATE then
				Colors:Update(ChosenMap,FirstColors)
			end
		end
		Remotes.ShowStatus:FireAllClients("Round: " .. tostring(i))
		task.wait(1)
	end
	
	ServerStatus.Value = "Intermission"
	for i,player in Players:GetPlayers() do
		if table.find(playersInRound,player) then
			PlayerRemover:Init(playersInRound,player)
		end
	end
	self:Reset(ChosenMap)
end

function Core:Reset(map)
	if workspace:FindFirstChild(CurrentMap.Value) then
		workspace:FindFirstChild(CurrentMap.Value):Destroy()
	end
	Remotes.UpdateInfo:FireAllClients("Restart","Color: ","Mode: ",Color3.fromRGB(127, 128, 128))
	ServerStatus.Value = "Intermission"
	RoundCounter = 0
	CurrentMap.Value = ""
	map:Destroy()
	playersInRound = {}
	playersWhoHaveDied = {}
end

return Core

-- Script breaks
-- Keeps moving forward even though someone has already won
-- Slight delay in voting intermission and status changes
Server
require(script.Core):Init()
2 Likes

you can turn off the ResetOnSpawn property for guis so they don’t reset when the character loads

Also you should be able to use while loops or recursion without any problems

pseudocode:

while true do
  vote()
  task.wait(15)
  startGame()

  repeat task.wait() until gameEnded()
end
function startGame()
  vote()
  task.wait(15)
 -- do stuff

  repeat task.wait() until gameEnded()

  startGame()
end
3 Likes

I was thinking of using coroutines and I’m coming across the problem of rounds still overlapping. The loops are being divided into branches and the amount of branches is exponentially increasing. I also fixed the issue with the ResetOnSpawn but I can’t seem to prevent the recursion from making rounds overlap.

Is coroutines a good idea?

Why are the rounds overlapping

If you follow the structure of the pseudocode i gave above then it should work

Whats the reason for the vote function being called in the while loop and startGame function? Also I want the current loop to restart back to the beginning when a player wins so I have to do that at a specific point in the while loop.

I’m also getting the error HumanoidRootPart is not a valid member of Model “Workspace.Violet_sheer”.

Somewhere in my code is happening but I cannot see it. I also called this core2 because I’m using coroutines for this one.

Being spam teleported to map spawn parts, yeah I think recursion is the issue.

If you look at this being used for a round system, I don’t think it would work properly.

1 Like

the loop waits until the game is ended
so it will restart when the game is ended (when a player wins)

the recursion psuedocode does the exact same thing as the while loop
its not branching infinitely but just calling itself over and over again
if you draw it then it would be like a circle

i think using the simple loop is better than recursion, but both will work

while true do -- do this forever
  vote() -- make the players vote
  task.wait(15) -- wait until the vote timer runs out
  startGame() -- set up the game

  repeat task.wait() until gameEnded() -- keep waiting until the game ends
end -- restart the loop after the game ends or a player wins
1 Like

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