What's the best way to get a table of players from the module to a local script?

So here, I’m trying to make a spectate system that only spectates players only in a round. But I have been trying to figure out how would I be able to get the table of players in the module to my local script???

If you would like to see the module and spectate system please feel free to ask!

In order to help, I need a bit more context. Please send some snippets from the two scripts in question.

Module:

local moduleFunction = {}
local playersInRound = {}
local connections = {}

local playerInfo = {
	AFK = false; 
	InRound = false 
}

function moduleFunction.ReturnPlayersInfo()
	return playerInfo
end
---------------------------------------------------------------------------------------------------------------------------
-- // Game Functions \\ --
---------------------------------------------------------------------------------------------------------------------------
function moduleFunction.AddValue()
	local Players = game:GetService("Players")
	Players.PlayerAdded:Connect(function(player)

		local isPlaying  = Instance.new("BoolValue")
		isPlaying.Name = "IsPlaying" 
		isPlaying.Parent = player 

	end)
end

function moduleFunction.Countdown(numS, numE, change, parent, text)
	for i = numS, numE, change do
		parent.Value = text..i
		wait(1)
	end
end

function moduleFunction.AddPlayer(player)
	if player:IsA("Player") then
		if playerInfo.AFK == false then
			playerInfo.InRound = true
			print(player)
			table.insert(playersInRound, player) 
			connections[player.Name] = player.Character.Humanoid.Died:Connect(function()
				table.remove(playersInRound, table.find(playersInRound, player))
			end)
		elseif playerInfo.AFK == true then
			warn("Player is afk. Was not added to the list")
			playerInfo.InRound = false
		end	
	end
end

function moduleFunction.PlayerLeft()
	connections["Removing"] = game.Players.PlayerRemoving:Connect(function(player) 
		local playerLeft = table.find(playersInRound, player)
		if playerLeft then
			table.remove(playersInRound, playerLeft)
			playerInfo.InRound = false
		end
	end)
end

function moduleFunction.TileDissaper(parent)
	for _,Part in ipairs(parent:GetChildren()) do
		if Part:IsA("Part") then
			Part.OnTouchedTile.Touched:Connect(function(hit)
				if hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
					if Part.Transparency == 0 then
						for i = 0, 1, 0.0625 do
							Part.Transparency = i
							wait()
						end
						Part:Destroy()
					end
				end
			end)
		end
	end
end

--[[function moduleFunction.PlayersAlive()
	return playersInRound
end--]]

function moduleFunction.CheckWinner(parent)
	if #playersInRound > 1 then
		while #playersInRound >= 2 do
			parent.Value = "Game in progress"
			wait()
			if #playersInRound == 1 then
				local player = playersInRound[1]
				print("The Winner is: " .. player.Name)
				parent.Value = player.Name .. " has won this round!"
				wait(5)
			elseif #playersInRound == 0 then
				print("There was not a single winner.")
				parent.Value = "No one won this round"
				wait(5)
			end
		end
	end
end

function moduleFunction.RemovePlayer()
	for _, connection in pairs(connections) do 
		connection:Disconnect()
		wait()
	end

	for _, player in pairs(playersInRound)do
		player:LoadCharacter()
		wait()
	end	
	
	playerInfo.InRound = false
	playersInRound = {}
end 

return moduleFunction

Local Script (spectate):

local debounce = false
local toggle = script.Parent.Parent.Buttons.SpectateButton.ImageButtonRoundify12px
local frame = script.Parent
local otherFrame = script.Parent.Parent.InventoryFrame
local otherFrame2 = script.Parent.Parent.SettingsFrame
local previous = frame.PrevButton.Button
local next = frame.NextButton.Button
local status = frame.RoundifyImage12px.Status
local camera = game.Workspace.CurrentCamera
local num = 1
local gameModule = require(game.ReplicatedStorage.GameModule)



status.Text = game.Players.LocalPlayer.Name

toggle.MouseButton1Click:connect(function() 
	-- local players = gameModule.PlayersAlive()
	-- if #players < 1 then return end
	otherFrame.Visible = false
	otherFrame.Position = UDim2.new(0.499, 0, 0.369, 0)
	otherFrame2.Visible = false
	otherFrame2.Position = UDim2.new(0.499, 0, 0.369, 0)
	if frame.Visible == false then
		debounce = true
		frame.Visible = true
		frame:TweenPosition(UDim2.new(0.218, 0, 0.646, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.0625, true)
		debounce = false
	elseif frame.Visible == true then
		debounce = true
		frame.Visible = false
		frame.Position = UDim2.new(0.218, 0, 0.716, 0)
		debounce = false
	end	
end)

previous.MouseButton1Click:Connect(function()
	local players = gameModule.PlayersAlive()
	print("clicked")
	local max = #players
	num = num - 1
	print(num)
	if num < 1 then
		num = max
	end
	if num >= 0 then
		print("num is greater than 0")
		local player = players[num]
		local playerLocation = game.Players:FindFirstChild(player.Name)
		print(player.Name)
		if playerLocation then
			print("player location")
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)

next.MouseButton1Click:Connect(function()
	local players = gameModule.PlayersAlive()
	local max = #players
	num = num + 1
	print(num)
	if num > max then
		num = 1
	end
	
	if num >= 1 then
		print(players)
		local player = players[num]
		print(player)
		local playerLocation = game.Players:FindFirstChild(player.Name)
		print(player.Name)
		if playerLocation then
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)

frame.Changed:Connect(function()
	if not frame.Visible then
		camera.CameraSubject = game.Players.LocalPlayer.Character.Humanoid
		status.Text = game.Players.LocalPlayer.Name
	end
end)

Note: ignore the game module functions in the local script. I was just testing out.

You need to place playersInRound within the moduleFunction table.

Your playersInRound variable is local to the module itself. It cannot be seen outside of its environment.

The reason is that modules return a table after they are required. This is how you are able to get OOP like classes in roblox.

Module:

local moduleFunction = {}
moduleFunction.playersInRound = {}

OR

local moduleFunction = {
    playersInRound = {}
}

LocalScript (You can now use gameModule.playersInRound)

gameModule.playersInRound[YOUR_INDEX_HERE]

Hope this helps :slight_smile:

Ok so I did everything but for the index I would want to get all the players in the table. How would I do that?

the gameModule.playersInRound is just a reference to the table within the module.

If you wanted to loop through the players, you can do:

   for index, player in ipairs(gameModule.playersInRound) do
      -- Code Here
   end

I mean I wasn’t asking for that but ok. Yes so I set everything up and I tested it with 2 players and it gave me this error.

the line of code is of course the game module part here is the whole spectate system again.

local debounce = false
local toggle = script.Parent.Parent.Buttons.SpectateButton.ImageButtonRoundify12px
local frame = script.Parent
local otherFrame = script.Parent.Parent.InventoryFrame
local otherFrame2 = script.Parent.Parent.SettingsFrame
local previous = frame.PrevButton.Button
local next = frame.NextButton.Button
local status = frame.RoundifyImage12px.Status
local camera = game.Workspace.CurrentCamera
local num = 1
local gameModule = require(game.ReplicatedStorage.GameModule)



status.Text = game.Players.LocalPlayer.Name

toggle.MouseButton1Click:connect(function() 
	-- local players = gameModule.PlayersAlive()
	-- if #players < 1 then return end
	otherFrame.Visible = false
	otherFrame.Position = UDim2.new(0.499, 0, 0.369, 0)
	otherFrame2.Visible = false
	otherFrame2.Position = UDim2.new(0.499, 0, 0.369, 0)
	if frame.Visible == false then
		debounce = true
		frame.Visible = true
		frame:TweenPosition(UDim2.new(0.218, 0, 0.646, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.0625, true)
		debounce = false
	elseif frame.Visible == true then
		debounce = true
		frame.Visible = false
		frame.Position = UDim2.new(0.218, 0, 0.716, 0)
		debounce = false
	end	
end)

previous.MouseButton1Click:Connect(function()
	local players = gameModule.playersInRound()
	print("clicked")
	local max = #players
	num = num - 1
	print(num)
	if num < 1 then
		num = max
	end
	if num >= 0 then
		print("num is greater than 0")
		local player = players[num]
		local playerLocation = game.Players:FindFirstChild(player.Name)
		print(player.Name)
		if playerLocation then
			print("player location")
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)

next.MouseButton1Click:Connect(function()
	local players = gameModule.playersInRound()
	local max = #players
	num = num + 1
	print(num)
	if num > max then
		num = 1
	end
	
	if num >= 1 then
		print(players)
		local player = players[num]
		print(player)
		local playerLocation = game.Players:FindFirstChild(player.Name)
		print(player.Name)
		if playerLocation then
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)

frame.Changed:Connect(function()
	if not frame.Visible then
		camera.CameraSubject = game.Players.LocalPlayer.Character.Humanoid
		status.Text = game.Players.LocalPlayer.Name
	end
end)

My goal here is to get the table and use it for the spectate system.

Like I said before, playersInRound is a table, not a function.

Write it like this:
local players = gameModule.playersInRound

Another issue that may arise is within your module. Any time you need to change this table inside of the module, you must reference playersInRound like this:

moduleFunction.playersInRound

Ok so I did all of that. But for some reason it gives another error

and when I test it, (like print (player)) then it just prints nil. Why is that?

Note: I did it with 2 PLAYERS during a round and the round was already in progress. (players were in that table)

Please send me a pastebin of both modules. Its hard for me to tell what line that is on.

Module:
https://pastebin.com/P3eAgpWL
Spectate System (local script):
https://pastebin.com/P4gZZPF1

1 Like

Okay, so within your Spectate System script I see no calls to the modules AddPlayer() method. The table is empty because there are no calls to this method.

Yes but I used the AddPlayer() method on the game script which runs basically the game in general. Wait so it doesn’t save the table???

Would you like to see the game script?

1 Like

No, let me explain.

Think of modules as boxes. When you call require(), it creates a brand new box for that code to run in.

Therefore, if you call require inside of the game script and the spectate script. This will create two completely separate boxes. Thus creating two different playersInRound tables.

If you need to use the module from the core script, you will need to create that single box (require()) and pass a reference to that box to your spectate script.

A way of doing this is to change your Spectate Server Script to a Module Script and referencing it inside of the game script itself. Game frameworks like AGF (Aero Game Framework) work this way as well, so that may be something to look into if you don’t mind doing some refactoring.

1 Like

Could you show an example??? I’m a bit confused on what to do.

1 Like

For sure, no worries. I sent you a PM.