Issue with leaving elevators

Hello fellow developers,
Recently i’ve been having an issue with my tower defense’s game PVP elevators that teleport you to an in-game match and i can’t seem to find out what’s causing it: Players enter elevators and are teleported flawlessly, but the problem comes when leaving an elevator with more than 1 player.

Supposing there’s 2 players in an elevator (A and B), player A can leave the elevator without an issue, but then when player B tries to, the UI button used to leave simply dissapears without doing anything else, leaving player B stuck in the elevator until someone else (either player A or anyone else) enters the same elevator, which then actually runs the leaving function for player B. No errors seem to appear in output, which only confuses me more. Does anyone know what the problem is here?

Elevators main code
--Only focus in 1v1 related code, 2v2 isn't finished yet.
local Functions = {}

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

local PVP_folder = workspace:WaitForChild("PVP")
local Elevators = PVP_folder:WaitForChild("Elevators")
local one = Elevators:WaitForChild("1V1")
local two = Elevators:WaitForChild("2V2")
local ElevatorNamesData = require(script.Parent.TextColors)

local leaveGuiEvent = ReplicatedStorage:WaitForChild("LeaveGuiEvent")
local PvpData = require(script.Parent:WaitForChild("PvpData"))
local ElevatorFunctions = require(script.Parent:WaitForChild("ElevatorFunctions"))

local function tableAmount(player1:Player?, player2:Player?)
	local Table = {}
	if player1 then
		table.insert(Table, player1)
	end
	if player2 then
		table.insert(Table, player2)
	end
	return Table
end

function Functions.updateBillboard(model:Instance?, playerCount:number?, countdown:number?, status:String?)
	assert(model or playerCount or countdown or  model:FindFirstChild("Billboards") or status, "something is nil")
	local Billboard = model:FindFirstChild("Billboards").GuiPart

	Billboard.SurfaceGui.Frame.players.Text = tostring(playerCount)
	Billboard.SurfaceGui.Frame.time.Text = tostring(countdown)
	Billboard.SurfaceGui.Frame.Status.Text = tostring(status)
end

function Functions.GetElevatorType(elevator)
	if PvpData["1V1"][elevator] then
		return "1v1"
	elseif PvpData["2V2"][elevator] then
		return "2v2"
	else
		return "Failed to get type"
	end
end

function Functions.CanStart(data, Type)
	if Type == "1v1" then
		if data.Red and data.Blue then
			return true
		end
		return false		
	elseif type == "2v2" then
		local required = data.MaxSize

		for index, teamData in pairs(data) do
			if #teamData < required then
				return false
			end
		end
		return true
	end
end

function Functions.CanJoin(player:Player, team:StringValue, data, two:BoolValue)
	if two then
		for i,v in pairs(data) do
			if i ~= team and typeof(v) == "table" then
				if table.find(v, player) then
					return false
				end
			end
		end
		return true	
	end

	for i, v in pairs(data) do
		if i == team then
			continue
		end

		if v == player then
			return false
		end
	end
	return true
end

function Functions.OneVone(player, hit, elevator, Team)
	local data = PvpData["1V1"][elevator]
	local canJoin = Functions.CanJoin(player, Team, data)
	local team = nil

	if data[Team] == nil and canJoin then
		data[Team] = player
		team = data[Team]

		hit.Parent:MoveTo(elevator[Team .. "Part"]:GetChildren()[1].Position +Vector3.new(0,2,0))
	else
		return
	end

	local canStart = Functions.CanStart(data, "1v1")

	leaveGuiEvent:FireClient(player)

	leaveGuiEvent.OnServerEvent:Once(function(p)
		for index, d in pairs(data) do
			print(index, d)
			if d == p then
				data[index]=nil
				print("Found and removed")
				break
			end
		end


		p.Character:MoveTo(elevator.LeavePos.Value)
		Functions.updateBillboard(elevator,  #tableAmount(data.Red, data.Blue), 0, "")
	end)

	if canStart then
		for i = 10, 1, -1 do
			data = PvpData["1V1"][elevator]
			canStart = Functions.CanStart(data, "1v1")

			if not canStart then
				break
			end
			Functions.updateBillboard(elevator, #tableAmount(data.Red, data.Blue), i, "Countdown")
			task.wait(1)
		end
		canStart = Functions.CanStart(data, "1v1")

		if not canStart then
			return
		end

		ElevatorFunctions.Teleport_Players({data.Red, data.Blue}, 10433192845, {team = Team, Map =elevator:GetAttribute("Map")})
		data.Blue = nil
		data.Red = nil
	else
		Functions.updateBillboard(elevator, 1, 0, "")	
		return
	end
end

function Functions.table(table1:Table?, table2:Table?)
	return #table1 + #table2
end

function Functions.twoVtwo(player, character, elevator, team)
	local data = PvpData["2V2"][elevator]
	local MaxSize = data.MaxSize
	local SelectedTable = data[team]

	if #SelectedTable < MaxSize and not table.find(SelectedTable, player) and Functions.CanJoin(player, team, data, true) then
		table.insert(SelectedTable, player)
		print("Added player")
		local canStart = Functions.CanStart(data, "2v2")
		leaveGuiEvent:FireClient(player)

		if canStart then
			for i =10, 1, -1 do
				canStart = Functions.CanStart(data, "2v2")
				
				if not canStart then
					break
				end
				Functions.updateBillboard(elevator, Functions.table(data.Red, data.Blue), i, "Countdown")
			end
		end
	else
		return
	end
end


function Functions.HandleTouch(hit, elevator, Team)
	local player = Players:GetPlayerFromCharacter(hit.Parent)

	if not player then return end

	local Type = Functions.GetElevatorType(elevator)

	if Type == "1v1" then
		task.spawn(Functions.OneVone, player, hit, elevator, Team)
	elseif Type == "2v2" then
		Functions.twoVtwo(player, hit.Parent, elevator, Team)
	end
end

for index, elevator in pairs(one:GetChildren()) do
	if not elevator:FindFirstChild("Hitboxes") then
		warn(elevator.Name .. " does not have a hitbox")
		continue
	end

	elevator.Billboards.MapName.BillboardGui.Frame.TextLabel.Text = ElevatorNamesData[elevator.Name].Text
	elevator.Billboards.MapName.BillboardGui.Frame.TextLabel.TextColor3 = ElevatorNamesData[elevator.Name].TextColor3
	elevator.LeavePos.Value = elevator.Leaver.Position

	elevator.Hitboxes.Blue.Touched:Connect(function(hit)
		Functions.HandleTouch(hit, elevator, tostring(elevator.Hitboxes.Blue))
	end)
	elevator.Hitboxes.Red.Touched:Connect(function(hit)
		Functions.HandleTouch(hit, elevator, tostring(elevator.Hitboxes.Red))
	end)
end

for index, elevator in pairs(two:GetChildren()) do
	if not elevator:FindFirstChild("Hitboxes") then
		warn(elevator.Name .. " does not have a hitbox")
		continue
	end

	--elevator.Billboards.MapName.BillboardGui.Frame.TextLabel.Text = ElevatorNamesData[elevator.Name].Text
	--elevator.Billboards.MapName.BillboardGui.Frame.TextLabel.TextColor3 = ElevatorNamesData[elevator.Name].TextColor3
	--elevator.LeavePos.Value = elevator.Leaver.Position

	elevator.Hitboxes.Blue.Touched:Connect(function(hit)
		Functions.HandleTouch(hit, elevator, tostring(elevator.Hitboxes.Blue))
	end)
	elevator.Hitboxes.Red.Touched:Connect(function(hit)
		Functions.HandleTouch(hit, elevator, tostring(elevator.Hitboxes.Red))
	end)
end


return Functions
Leaving button code
local leaveGuiEvent = game.ReplicatedStorage.LeaveGuiEvent

local player = game.Players.LocalPlayer

 leaveGuiEvent.OnClientEvent:Connect(function()
 
 player.PlayerGui.MainGui.leaveButton.Visible = true
 
 end)
 
 player.PlayerGui.MainGui.leaveButton.Activated:connect(function()
 
 leaveGuiEvent:FireServer()
 
 player.PlayerGui.MainGui.leaveButton.Visible = false
 
 end)
PVP Data script
return {

["1V1"] = {},

["2V2"] = {}

}
Data setup script
local data = require(script.Parent:WaitForChild("PvpData"))

local oneVone = workspace:WaitForChild("PVP"):WaitForChild("Elevators"):WaitForChild("1V1")
local twoVtwo = workspace:WaitForChild("PVP"):WaitForChild("Elevators"):WaitForChild("2V2")

for index, map in pairs(oneVone:GetChildren()) do
	data["1V1"][map] = {
		
	}
end

for index, map in pairs(twoVtwo:GetChildren()) do
	data["2V2"][map] = {
		["Red"] = {},
		["Blue"] = {},
		MaxSize = 2
	}
end

print(data)

require(script.Parent:WaitForChild("PvpModule"))

Thanks for reading!

1 Like