Teleport Service, detect amount of players

I am trying to create a lobby that teleports a set amount of players to a reserved place (so people cannot join the same server after the match starts).

The script I have so far does that, but for some of the places, I want there to be a minimum and maximum player count. If it is a 2v2 map then I want it to teleport only 4 people if enough join, but after 30 seconds, I would like it to teleport everyone and I will fill the remaining spots with bots on one game mode, but on others, I would like to wait for max players, so basically I need this script to be more customizable.

I have read the examples on teleportservice and searched posts here and tried to make counters in my script, but they always seem to fail and it is hard to test teleport service in a live server when you need 3 or more people to help. Any help is appreciated.

Script:

local TS = game:GetService("TeleportService")
local Players = game:GetService("Players")
local part = script.Parent
local code = TS:ReserveServer(6310791037) 


part.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		local plr = Players:GetPlayerFromCharacter(hit.Parent)
		if plr then
			plr.leaderstats.Playing.Value = true		
		end		
	end	
end)

local playersPlaying = {}

while true do
	for i, v in pairs(Players:GetPlayers()) do
		if v.leaderstats.Playing.Value == true then
			table.insert(playersPlaying,v)
		end
	end
	wait(10)
	if playersPlaying[1] ~= nil then
		TS:TeleportToPrivateServer(6310791037,code,playersPlaying)	
	end	
end

This script is parented to a large block that players touch to go to the game type of their choice. I would also like to make a way to detect if a player changes their mind and decides to not play before the match starts, but I think I can figure that part out on my own, once I get the counters set up correctly. If a touch event is a bad way to do this, I am open to changing that as well. Thanks.

1 Like

So it is pretty crude, but I believe I found the solution. I will wait to mark it if a better one exists.

local TS = game:GetService("TeleportService")
local Players = game:GetService("Players")
local part = script.Parent
local code = TS:ReserveServer(6310791037) 
local rs = game:GetService("ReplicatedStorage")
local db = false

local playersPlaying = {}

part.Touched:Connect(function(hit)
	if db == false then
		db = true
		if hit.Parent:FindFirstChild("Humanoid") then
			local player = Players:GetPlayerFromCharacter(hit.Parent)
			print(player.Name)
			if player and player.leaderstats.Playing.Value == false then
				for i,v in pairs(playersPlaying) do  --loop through table to see if they are already on it
					if v.Name == player.Name then
						wait(1)
						db = false
						print("Match")
						return;
					else
						print("no match")
					end
				end	
				table.insert(playersPlaying,player)  -- insert directly into table instead of using a variable
				print("added player "..player.Name)
                player.leaderstats.Playing.Value = true
				player.PlayerGui.Waiting.Frame.Visible = true  -- added gui to show player count/leave button/start button
			end		
		end	
		wait(1)
		db = false
	end	
end)

rs.RemoteEvents.Start2v2.OnServerEvent:Connect(function(player)  --event for starting without max players
	TS:TeleportToPrivateServer(6310791037,code,playersPlaying)	
end)

rs.RemoteEvents.Leave.OnServerEvent:Connect(function(player) -- event if player leaves the que
	table.remove(playersPlaying,player)
     player.leaderstats.Playing.Value = false
end)

while true do
	for i, v in pairs(playersPlaying) do	
		v.PlayerGui.Waiting.Frame.Count.Text = "Players "..#playersPlaying.."/2" --update gui
	end
	if playersPlaying[2] ~= nil and playersPlaying[1] ~= nil then  --auto teleport when 2 players have joined
		TS:TeleportToPrivateServer(6310791037,code,playersPlaying)	
		for k in pairs (playersPlaying) do  --clear table for next match to be setup
			playersPlaying[k] = nil
		end
	end	
	wait(1)
end

I edited it to keep the variable so a player could not join multiple ques and cause the teleport to fail or bug out the player count

So the issue with this code is the Leave event.
I am unable to remove the player from the table because I need to use the index instead of the value, so I did some research and found that I could use player.UserId instead and that would return a number value to use as the index, but that gave me issues with having to fetch the UserId to teleport and now I am getting an error saying that teleport can only be used on an array of players, which the devblog says is incorrect and I have used in other scripts before. Here is the code to teleport to the 2v2 arena now. Any help would be appreciated.

local TS = game:GetService("TeleportService")
local Players = game:GetService("Players")
local part = script.Parent
local code = TS:ReserveServer(6310791037) 
local rs = game:GetService("ReplicatedStorage")
local db = false

local playersPlaying = {}

part.Touched:Connect(function(hit)
	if db == false then
		db = true
		if hit.Parent:FindFirstChild("Humanoid") then
			local player = Players:GetPlayerFromCharacter(hit.Parent)
			print(player.Name)
			if player and player.leaderstats.Playing.Value == false then
				for i,v in pairs(playersPlaying) do
					local plr = game:GetService("Players"):GetPlayerByUserId(v)
					if plr.Name == player.Name then
						wait(1)
						db = false
						print("Match")
						return;
					else
						print("no match")
					end
				end	
				table.insert(playersPlaying,player.UserId)
				print("added player "..player.Name)
				player.PlayerGui.Waiting.Frame.Title.Text = "2 v 2 VS"
				player.PlayerGui.Waiting.Frame.Visible = true
				player.leaderstats.Playing.Value = true
			end		
		end	
		wait(1)
		db = false
	end	
end)

rs.RemoteEvents.Start2v2.OnServerEvent:Connect(function(player)
	for i, v in pairs(playersPlaying) do	
		local plr = game:GetService("Players"):GetPlayerByUserId(v)
		plr.PlayerGui.Waiting.Frame.Count.Text = "Teleporting..."
		TS:TeleportToPrivateServer(6310791037,code,{plr})
	end	
	for k in pairs (playersPlaying) do
		playersPlaying[k] = nil
	end
end)

rs.RemoteEvents.Leave.OnServerEvent:Connect(function(player)
	for i, v in pairs(playersPlaying) do	
		local plr = game:GetService("Players"):GetPlayerByUserId(v)
		if plr.Name == player.Name then
			player.leaderstats.Playing.Value = false
			player.PlayerGui.Waiting.Frame.Visible = false
			playersPlaying[i] = nil
		end	
	end	
end)

while true do
	for i, v in pairs(playersPlaying) do			
		local plr = game:GetService("Players"):GetPlayerByUserId(v)
		plr.PlayerGui.Waiting.Frame.Count.Text = "Players "..#playersPlaying.."/4"
	end
	if playersPlaying[2] ~= nil and playersPlaying[1] ~= nil and playersPlaying[3] ~= nil and playersPlaying[4] ~= nil  then
		for i, v in pairs(playersPlaying) do	
			local plr = game:GetService("Players"):GetPlayerByUserId(v)
			plr.PlayerGui.Waiting.Frame.Count.Text = "Teleporting..."
			TS:TeleportToPrivateServer(6310791037,code,{plr})
		end
		for k in pairs (playersPlaying) do
			playersPlaying[k] = nil
		end
	end	
	wait(1)
end

Okay I think I figured out a solution, but it is still really messy.

On the start event, I included a check to see if plr.Name = player.Name since I am passing the player when it fires.

I couldn’t do that for the group teleport though since it is in a while loop, so I created a second table comprised of the players and teleported them that way.

rs.RemoteEvents.Start2v2.OnServerEvent:Connect(function(player)
	for i, v in pairs(playersPlaying) do	
		local plr = game:GetService("Players"):GetPlayerByUserId(v)
		if plr.Name == player.Name then
			plr.PlayerGui.Waiting.Frame.Count.Text = "Teleporting..."
			TS:TeleportToPrivateServer(6319949860,code,{player})
		end	
	end	
	for k in pairs (playersPlaying) do
		playersPlaying[k] = nil
	end
end)


I also had to consider now that my auto start will never succeed because it is looking for the first four indexes of the table when I changed them to save as UserId instead.

while true do
	for i, v in pairs(playersPlaying) do			
		local plr = game:GetService("Players"):GetPlayerByUserId(v)
		plr.PlayerGui.Waiting.Frame.Count.Text = "Players "..#playersPlaying.."/4"
	end
	local pready = {}
	if #playersPlaying == 4  then
		for i, v in pairs(playersPlaying) do	
			local plr = game:GetService("Players"):GetPlayerByUserId(v)
			plr.PlayerGui.Waiting.Frame.Count.Text = "Teleporting..."		
			table.insert(pready, plr)
		end
		TS:TeleportToPrivateServer(6319949860,code,pready)
		for k in pairs (playersPlaying) do
			playersPlaying[k] = nil
		end
		for k in pairs (pready) do
			pready[k] = nil
		end
	end	
	wait(1)
end

One last edit, I made a check to make sure more than max players could not join the que

if player and player.leaderstats.Playing.Value == false then and #playersPlaying < 4 then
1 Like