Why do these scripts work on my test place but not in another game?

So as a commission for The Garrison, I have made a Tic Tac Toe game:

This game works perfectly fine in the test place, I cannot break it no matter what I do. I’ve tried all sorts of edge cases such as leaving at win etc. but the game will not break.


However, in the Garrison, it is completely broken:

It won’t even function for one round half the time before freezing, then you have to use the quit button to leave (there is an intentional wait in case of server lag)


So why might it only be working in the test place? I’ve watched the Garrison dev set it up in Discord vc, with the readme script so there should be no reason why it wouldn’t work in the Garrison.

Structure of stuff:

Extra notes:

  • There are no errors when run
  • There are no errors when it breaks
  • It just freezes when it feels like it
Code snippets

MainController, inside the part

-- initialisation to avoid cross contamination

TTTID = math.random(1,2147483647)
script.Parent.Parent.TTT_ID.Value = TTTID
script.Parent.Parent.Name = tostring(TTTID)
script.Parent.Parent.Color = Color3.new(math.random(),math.random(),math.random())

RemoteFolder = Instance.new("Folder",game.ReplicatedStorage)
RemoteFolder.Name = tostring(TTTID)
remoteTable = {"ButtonClicked","Move","Quit","TextSet"}

for i = 1,#remoteTable,1 do
	local remoteConcerned = Instance.new("RemoteEvent")
	remoteConcerned.Name = remoteTable[i]
	remoteConcerned.Parent = RemoteFolder
end

-- the actual running of script

player1Value = script.Parent.Parent.Player1
player2Value = script.Parent.Parent.Player2

lastMovedPlayer = nil

function prompt(player)
	print("Player has joined")
	if player.PlayerGui:FindFirstChild("TicTacToeUI") == nil then -- make sure the player doesn't already have the UI in them
		if script.Parent.Parent.GameRunning.Value == false then
			if player1Value.Value == nil then
				-- set up player 1
				player1Value.Value = player
				local newGui = game.ServerStorage.TicTacToeUI:Clone()
				newGui.Parent = player.PlayerGui
				newGui.Enabled = true
				gameFullCheck(0,0)
				player1Value.Value.PlayerGui.TicTacToeUI.CorrectScript.Value = script
				player1Value.Value.PlayerGui.TicTacToeUI.CorrectButtonPressed.Value = RemoteFolder.ButtonClicked
				player1Value.Value.PlayerGui.TicTacToeUI.CorrectMoved.Value = RemoteFolder.Move

			elseif player2Value.Value == nil and player ~= player1Value.Value then
				-- set up player 2
				player2Value.Value = player
				local newGui = game.ServerStorage.TicTacToeUI:Clone()
				newGui.Parent = player.PlayerGui
				newGui.Enabled = true
				gameFullCheck(0,0)
				player2Value.Value.PlayerGui.TicTacToeUI.CorrectScript.Value = script
				player2Value.Value.PlayerGui.TicTacToeUI.CorrectButtonPressed.Value = RemoteFolder.ButtonClicked
				player2Value.Value.PlayerGui.TicTacToeUI.CorrectMoved.Value = RemoteFolder.Move

			else
				print("dont try and break me")
			end
		else
			print("game full right now")
		end
	end
end

function gameFullCheck(wins1,wins2)
	print("Game full check is running....")
	if player1Value.Value ~= nil and player2Value.Value ~= nil then
		print("Game is full, starting")
		
		script.Parent.Enabled = false -- disable the proximity prompt, which should fix the bug of the game being spammed
		
		script.Parent.Parent.BillboardGui.Player1.Text = tostring(player1Value.Value)
		script.Parent.Parent.BillboardGui.Player2.Text = tostring(player2Value.Value)
		script.Parent.Parent.BillboardGui.Enabled = true
		
		gameTable = {
			{nil,nil,nil},
			{nil,nil,nil},
			{nil,nil,nil}
		}
		
		local plr1UI = player1Value.Value.PlayerGui.TicTacToeUI
		local plr2UI = player2Value.Value.PlayerGui.TicTacToeUI
		
		plr1UI.Base.Status.Text = "You are playing against "..tostring(player2Value.Value)
		plr1UI.Base.TTTBody.TicTacToeModules:SetAttribute("ImageId","http://www.roblox.com/asset/?id=12814238844")
		plr1UI.Base.WinCounter.Text = "Wins needed: "..tostring(wins1).."/2"
		plr1UI.PlayingAgainst.Value = player2Value.Value
		plr1UI.CorrectScript.Value = script
		plr1UI.CorrectButtonPressed.Value = RemoteFolder.ButtonClicked
		plr1UI.CorrectMoved.Value = RemoteFolder.Move
		plr1UI.CorrectQuit.Value = RemoteFolder.Quit
		plr1UI.CorrectTextSet.Value = RemoteFolder.TextSet
		
		plr2UI.Base.Status.Text = "You are playing against "..tostring(player1Value.Value)
		plr2UI.Base.TTTBody.TicTacToeModules:SetAttribute("ImageId","http://www.roblox.com/asset/?id=12814239298")
		plr2UI.Base.WinCounter.Text = "Wins needed: "..tostring(wins2).."/2"
		plr2UI.PlayingAgainst.Value = player1Value.Value
		plr2UI.CorrectScript.Value = script
		plr2UI.CorrectButtonPressed.Value = RemoteFolder.ButtonClicked
		plr2UI.CorrectMoved.Value = RemoteFolder.Move
		plr2UI.CorrectQuit.Value = RemoteFolder.Quit
		plr2UI.CorrectTextSet.Value = RemoteFolder.TextSet
		
		script.Parent.Parent.GameRunning.Value = true
		task.wait(2)
		local randomNum = math.random(1,2)
		if randomNum == 1 then
			script.Parent.Parent.PlayerToMove.Value = player1Value.Value
			plr1UI.Base.Status.Text = "Your turn!"
			plr2UI.Base.Status.Text = "Waiting for other player to move..."
		else
			script.Parent.Parent.PlayerToMove.Value = player2Value.Value
			plr2UI.Base.Status.Text = "Your turn!"
			plr1UI.Base.Status.Text = "Waiting for other player to move..."
		end
		lastMovedPlayer = nil
		-- start the game here
		
		local timerScript = script.Parent.Parent.PlayerToMove.Value.PlayerGui.TicTacToeUI.TimerScript:Clone()
		timerScript.Parent = script.Parent.Parent.PlayerToMove.Value.PlayerGui.TicTacToeUI.Base.Timer
		timerScript.Enabled = true
		
		RemoteFolder.Move:FireClient(script.Parent.Parent.PlayerToMove.Value)
	else
		if player1Value.Value ~= nil then
			script.Parent.ObjectText = "1/2 Players"
		else
			script.Parent.ObjectText = "0/2 Players"
		end
	end
end

function addMove(playerWhoMoved,button)
	if playerWhoMoved == lastMovedPlayer then
		playerWhoMoved:Kick("lol imagine trying to exploit")
	end
	lastMovedPlayer = playerWhoMoved
	
	playerWhoMoved.PlayerGui.TicTacToeUI.Base.Timer.TimerScript:Destroy()
	playerWhoMoved.PlayerGui.TicTacToeUI.Base.Timer:SetAttribute("TimeLeft",30)
	RemoteFolder.TextSet:FireClient(playerWhoMoved)
	
	-- all params are object values except button which is a string
	
	-- start by changing status of player who moved
	local playingAgainst = nil
	-- get other player securely
	if player1Value.Value == playerWhoMoved then
		playingAgainst = player2Value.Value
	else
		playingAgainst = player1Value.Value
	end
	
	local againstTimer = playingAgainst.PlayerGui.TicTacToeUI.TimerScript:Clone()
	againstTimer.Parent = playingAgainst.PlayerGui.TicTacToeUI.Base.Timer
	againstTimer.Enabled = true
	
	game.ReplicatedStorage.TextSet:FireClient(playerWhoMoved)
	
	local parentIndex = tonumber(string.sub(button,2,2))
	local childIndex = tonumber(string.sub(button,1,1))
	gameTable[parentIndex][childIndex] = playerWhoMoved
	
	for r,x in ipairs(playingAgainst.PlayerGui.TicTacToeUI.Base.TTTBody:GetChildren()) do
		if x.Name == button then
			x.Image = playerWhoMoved.PlayerGui.TicTacToeUI.Base.TTTBody.TicTacToeModules:GetAttribute("ImageId")
		end
	end
	
	-- check if game is won here
	
	local wonValue = nil
	
	for count1 = 1,#gameTable,1 do
		if gameTable[count1][1] == gameTable[count1][2] and gameTable[count1][2] == gameTable[count1][3] and gameTable[count1][3] ~= nil and wonValue == nil then
			playerWhoMoved.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
			playingAgainst.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
			print("player game win text set")
			wonValue = tostring(playerWhoMoved)
			task.wait(5)
		end
	end
	
	if wonValue == nil then
		for count2 = 1,#gameTable,1 do
			if gameTable[1][count2] == gameTable[2][count2] and gameTable[2][count2] == gameTable[3][count2] and gameTable[1][count2] ~= nil then

				playerWhoMoved.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
				playingAgainst.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
				wonValue = tostring(playerWhoMoved)
				task.wait(5)
			end
		end
		if gameTable[1][1] == gameTable[2][2] and gameTable[2][2] == gameTable[3][3] and gameTable[2][2] ~= nil then

			playerWhoMoved.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
			playingAgainst.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
			wonValue = tostring(playerWhoMoved)
			task.wait(5)
		elseif gameTable[1][3] == gameTable[2][2] and gameTable[2][2] == gameTable[3][1] and gameTable[2][2] ~= nil then

			playerWhoMoved.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
			playingAgainst.PlayerGui.TicTacToeUI.Base.Status.Text = "Game won by "..tostring(playerWhoMoved)
			wonValue = tostring(playerWhoMoved)
			task.wait(5)
		end
		
	end
	
	-- is full check
	local full = true
	local tie = false
	
	for count5 = 1,#gameTable,1 do
		for count6 = 1,#gameTable,1 do
			if gameTable[count5][count6] == nil then
				full = false
			end
		end
	end
	if full == true and wonValue == nil then
		tie = true
		playerWhoMoved.PlayerGui.TicTacToeUI.Base.Status.Text = "Tie"
		playingAgainst.PlayerGui.TicTacToeUI.Base.Status.Text = "Tie"
		task.wait(5)
	end
	
	local function restartRound()
		print("Round restarting")
		playerWhoMoved.PlayerGui.TicTacToeUI:Destroy()
		playingAgainst.PlayerGui.TicTacToeUI:Destroy()
		if player1Value:GetAttribute("Wins") < 2 and player2Value:GetAttribute("Wins") < 2 then
			print("cloning gui")
			local newGui = game.ServerStorage.TicTacToeUI:Clone()
			newGui.Parent = playerWhoMoved.PlayerGui
			newGui.Enabled = true
			local newGui2 = game.ServerStorage.TicTacToeUI:Clone()
			newGui2.Parent = playingAgainst.PlayerGui
			newGui2.Enabled = true
			gameFullCheck(player1Value:GetAttribute("Wins"),player2Value:GetAttribute("Wins"))
			print("gui clone done")
		else
			wonValue = Instance.new("ObjectValue",script)
			wonValue.Value = playerWhoMoved
			wonValue.Parent = game.ServerScriptService.TTTWonDataAdd
			
			-- wipe the thing clean
			script.Parent.Parent.Name = tostring(TTTID)
			game.ServerScriptService.RegenerateGame:SetAttribute("GameToWipe",tostring(TTTID))
		end
	end
	
	-- swap players if nobody won
	
	if wonValue == nil and full == false then
		task.wait(0.5)
		RemoteFolder.Move:FireClient(playingAgainst)
		playerWhoMoved.PlayerGui.TicTacToeUI.Base.Status.Text = "Waiting for other player to move..."
		playingAgainst.PlayerGui.TicTacToeUI.Base.Status.Text = "Your turn!"
	else
		if tie == false then
			if playerWhoMoved == player1Value.Value then
				player1Value:SetAttribute("Wins",player1Value:GetAttribute("Wins")+1)
			else
				player2Value:SetAttribute("Wins",player2Value:GetAttribute("Wins")+1)
			end
		end
		restartRound()
	end
end

function playerQuitValues(newValue)
	print(newValue:GetFullName())
	print("Quit remote has been fired, VALUES")
	local playerWhoQuit = newValue.Value
	print(tostring(playerWhoQuit:GetFullName()).." is the player quitting at the moment")
	actuallyQuitTheDamnGameAlreadyFFS(playerWhoQuit)
end

function playerQuitNonValues(newValue)
	print("Quit remote has been fired, NON VALUES")
	local playerWhoQuit = newValue
	if newValue:IsA("Value") then
		playerWhoQuit = newValue.Value
	end
	print(tostring(playerWhoQuit:GetFullName()).." is the player quitting at the moment")
	actuallyQuitTheDamnGameAlreadyFFS(playerWhoQuit)
end

function actuallyQuitTheDamnGameAlreadyFFS(playerWhoQuit)
	local other = nil
	if player1Value.Value == playerWhoQuit then
		other = player2Value.Value
	elseif player2Value.Value == playerWhoQuit then
		other = player1Value.Value
	else
		other = nil
	end
	-- wipe the thing clean
	script.Parent.Parent.Name = tostring(TTTID)
	game.ServerScriptService.RegenerateGame:SetAttribute("GameToWipe",tostring(TTTID)) -- set an attribute to wipe the game
	playerWhoQuit.PlayerGui.TicTacToeUI:Destroy()
	print("destroyed gui successfully")
	if other ~= nil then
		other.PlayerGui.TicTacToeUI.Base.Status.Text = "Other player has quit."
		task.wait(5)
		if other.PlayerGui.TicTacToeUI ~= nil then
			other.PlayerGui.TicTacToeUI:Destroy()
		end
	end
end

script.Parent.PromptButtonHoldEnded:Connect(prompt)
RemoteFolder.ButtonClicked.OnServerEvent:Connect(addMove)
script.ChildAdded:Connect(playerQuitValues)
RemoteFolder.Quit.OnServerEvent:Connect(playerQuitNonValues)

RefreshGame:

-- Warning: Do not move the Play part into a folder!

function checkPlayersInGame()
	if script.Parent.Parent.Player2.Value ~= nil then
		print("Checking for both players in game...")
		local isOneInGame = false
		local isTwoInGame = false
		for r,x in ipairs(game.Players:GetChildren()) do
			if x == script.Parent.Parent.Player1.Value then
				isOneInGame = true
				print("Player 1 is in the game")
			elseif x == script.Parent.Parent.Player2.Value then
				isTwoInGame = true
				print("Player 2 is in the game")
			end
		end
		if isOneInGame == false or isTwoInGame == false then
			game.ServerScriptService.RegenerateGame:SetAttribute("GameToWipe",tostring(script.Parent.Parent.TTT_ID.Value)) -- set an attribute to wipe the game
		end
	end
end

function bypassCheckGameWiper(playerWhoDied)
	warn("A player has died. Urgent checks are being run...")
	if script.Parent.Parent.Player1.Value == playerWhoDied or script.Parent.Parent.Player2.Value == playerWhoDied then
		game.ServerScriptService.RegenerateGame:SetAttribute("GameToWipe",tostring(script.Parent.Parent.TTT_ID.Value)) -- set an attribute to wipe the game
	end
end

game.ReplicatedStorage.PlayerDied.OnServerEvent:Connect(bypassCheckGameWiper)

if script.Parent.Parent.Parent ~= game.ServerStorage then
	while true do
		task.wait(10)
		checkPlayersInGame()
	end
end

RegenerateGame:

function attributeReceived()
	print(script:GetAttribute("GameToWipe"))
	local partPosition = nil
	for r,x in ipairs(game.Workspace:GetDescendants()) do
		if x.Name == script:GetAttribute("GameToWipe") then
			print("Found")
			partPosition = x.Position
			x:Destroy()
		end
	end
	local newGamePart = game.ServerStorage.Play:Clone()
	newGamePart.Parent = workspace
	newGamePart.Position = partPosition
end

script:GetAttributeChangedSignal("GameToWipe"):Connect(attributeReceived)

Player Died Remote Script

local players = game:GetService("Players")
local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")

humanoid.Died:Connect(function()
	game.ReplicatedStorage.PlayerDied:FireServer()
end)

No possible way to answer this without seeing the Tic Tac Toe Scripts Branch in the studio.
Clearly they are not being set up the same or something else is changing the setup in The Garrison that is making the other game not work as intended. That would be my guess …

1 Like

Do you know of any factors that could change the setup? I can check for them right now.

I’ve watched him set it up in a Discord vc whilst he was screensharing. It seems all fine to me

Possible

I am totally guessing here … with the information provided.
Say the TTT used a folder on the workbench named data and TG also used that same named folder or a gui name most anything they both refer to and use that is custom made. Like a folder name … If one changes that, the other will then fail.

1 Like

Ah, I can see where you’re coming from
However, when he was setting stuff up he did search for the script names and whatnot to check there were no duplicates from old versions, of which none were found

If this was from a tutorial, delete everything and try again slower … All I can say.

1 Like

Nope, actually coded by myself

Provide more useful information.

2 Likes

Specifically, what information do you want?

Code / Structure / Output

1 Like

This is pretty much impossible to find out the problem because we don’t know the actual code. Provide some code and we can help.

1 Like

I’ve just dumped the load of code that’s relevant here

1 Like