Attempt to Call a nil Value

I just added the first two game modes to my game

Only issue is the round module errors at line 28. “Attempt to call nil value”

I have it set up to choose a random number from 1 to the number of gamemodes in the gamemodes module, but this doesn’t work since it doesn’t know how many functions are inside of it. If I called the functions by name instead of table number, I’m sure it would work, but I can’t think of how to do so since the round module is dependent on the gamemodes module.


Code:

Round Module
local Players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")

local mainGame = replicatedStorage:WaitForChild("MainGame")
local gameValues = mainGame:WaitForChild("GameValues")

local status = gameValues:WaitForChild("Status")

local gamemodes = require(script:WaitForChild("Gamemodes"))

local round = {}

function round.Waiting(numberOfPlayers, minimumPlayers)
	status.Value = minimumPlayers.." ready players are required to start ("..numberOfPlayers.."/"..minimumPlayers.." players)"
end

function round.Intermission(intermissionTime)
	for i=intermissionTime,0,-1 do
		status.Value = "Intermission ("..i..")"
		task.wait(1)
	end
end

function round.StartRound(gameLength)
	local chosenMode = 1 --// Doing this later. Set to one for now to test | math.random(1, #gamemodes)
	status.Value = ""
	
	gamemodes[chosenMode](gameLength)
end

return round

Gamemodes Module
local Players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverStorage = game:GetService("ServerStorage")
local lighting = game:GetService("Lighting")
local tweenService = game:GetService("TweenService")
local serverStorage = game:GetService("ServerStorage")
local soundService = game:GetService("SoundService")
local marketPlaceService = game:GetService("MarketplaceService")

local musicFolder = soundService:WaitForChild("GameMusic")
local otherSounds = soundService:WaitForChild("OtherSounds")

local maps = serverStorage:WaitForChild("MainGame"):WaitForChild("Maps")

local mainGame = replicatedStorage:WaitForChild("MainGame")
local remotes = mainGame:WaitForChild("Remotes")
local gameValues = mainGame:WaitForChild("GameValues")

local mobsFolder = serverStorage:WaitForChild("MainGame"):WaitForChild("Enemies")

local status = gameValues:WaitForChild("Status")

local cashReward = 75
local expReward = 50

local mob = require(script.Parent:WaitForChild("Mob"))

local gamepasses = {
	VIP = 123723006
}

local projectileTools = {
	"Time Bomb"
}

local function toMS(s)
	return ("%02i:%02i"):format(s/60%60, s%60)
end

local function unpackageTools(player, pack)
	local clone = pack:Clone()

	for _, tool in pairs(clone:GetChildren()) do
		for __, Script in pairs(tool:GetDescendants()) do
			if Script:IsA("Script") and Script.Enabled == false then
				Script.Enabled = true
			end
		end

		tool.Parent = player.Backpack
	end

	clone:Destroy()
end

-- >>: Game Modes
local gamemodes = {}

function gamemodes.Standard(gameLength)
	local plrs = {}

	for i, player in pairs(Players:GetPlayers()) do
		table.insert(plrs,player)
	end

	task.wait(2)

	local availableSongs = soundService:WaitForChild("GameMusic"):GetChildren()
	local chosenSong = availableSongs[math.random(1,#availableSongs)]

	local availableMaps = maps:GetChildren()
	local chosenMap = availableMaps[math.random(1,#availableMaps)]

	status.Value = chosenMap.Name.." was selected"

	task.wait(2)

	local newMap = chosenMap:Clone()
	newMap.Name = chosenMap.Name
	newMap.Parent = workspace

	local spawnPoints = newMap:FindFirstChild("SpawnPoints")

	if not spawnPoints then
		warn("Critical Error: There are no spawn points in "..chosenMap.Name.."!")
	end

	local availableSpawns = spawnPoints:GetChildren()

	for i=5,0,-1 do
		status.Value = "Game will start in "..i
		task.wait(1)
	end

	remotes:WaitForChild("RoundMusic"):FireAllClients(chosenSong, "On")

	for i, plr in pairs(plrs) do
		if plr then
			local character = plr.Character

			coroutine.resume(coroutine.create(function()
				if not character then 
					plr:LoadCharacter()
					wait(0.1)
					character = plr.Character
				end

				wait(1.2)

				character.HumanoidRootPart.Position = availableSpawns[1].Position + Vector3.new(0, 8, 0)

				local toolPack = replicatedStorage.MainGame.Tools.WeaponPacks:FindFirstChild(plr.EquippedPack.Value)
				unpackageTools(plr, toolPack)

				local gameTag = Instance.new("BoolValue")
				gameTag.Name = "GameTag"
				gameTag.Parent = character
			end));
		else
			if not plr then
				table.remove(plrs,i)
			end
		end

	end

	wait(1.3)

	for i = gameLength, 0, -1 do
		local count = 0
		local maxCount = 3
		for o = 1, 6, 1 do
			if count == maxCount then
				mobsFolder:GetChildren()
				mob.Spawn()
			end
			task.wait(0.25)
		end
		if count == maxCount then
			count = 0
		end

		for x, player in pairs(plrs) do
			if player then
				local character = player.Character

				if not character then
					table.remove(plrs,x)
				else
					if character:FindFirstChild("GameTag") then
						--Still in game
						continue
					else
						table.remove(plrs,x)

						if player.leaderstats.Level.Value ~= 0 then
							player.leaderstats.Cash.Value += (cashReward + math.floor(cashReward * player.leaderstats.Level.Value / 10) * player.Multiplier.Value)
							player.leaderstats.Level.CurrentExp.Value += (expReward + math.floor(cashReward * player.leaderstats.Level.Value / 10) * player.Multiplier.Value)
						else
							player.leaderstats.Cash.Value += (5 * player.Multiplier.Value)
							player.leaderstats.Level.CurrentExp.Value += (10 * player.Multiplier.Value)
						end

						player.leaderstats.Deaths.Value += 1
					end
				end
			else
				table.remove(plrs,x)
			end
		end

		status.Value = "Time: "..toMS(i).." remaining"

		if #plrs == 0 then
			status.Value = "Restarting: No one survived."
			break
		elseif i == 0 then
			status.Value = "Restarting: Time has run out."

			for q, ply in pairs(plrs) do
				if ply.leaderstats.Level.Value ~= 0 then
					ply.leaderstats.Cash.Value += (cashReward + math.floor(cashReward * ply.leaderstats.Level.Value / 10) * ply.Multiplier.Value)
					ply.leaderstats.Level.CurrentExp.Value += (expReward + math.floor(cashReward * ply.leaderstats.Level.Value / 10) * ply.Multiplier.Value)
				else
					ply.leaderstats.Cash.Value += (cashReward * ply.Multiplier.Value)
					ply.leaderstats.Level.CurrentExp.Value += (expReward * ply.Multiplier.Value)
				end

				ply.leaderstats.Wins.Value += 1
			end

			break
		end
		
		count += 1
		
		wait(1)
	end

	wait(1.5)

	for i, player in pairs(Players:GetPlayers()) do
		local character = player.Character

		if not character then
			continue
		else
			if character:FindFirstChild("GameTag") then
				character.GameTag:Destroy()
			end

			for _, tool in pairs(player.Backpack:GetChildren()) do
				if tool:IsA("Tool") then
					tool:Destroy()
				end
			end

			for _, tool in pairs(character:GetChildren()) do
				if tool:IsA("Tool") then
					tool:Destroy()
				end
			end

		end

		player:LoadCharacter()
	end

	table.clear(plrs)

	remotes:WaitForChild("RoundMusic"):FireAllClients(chosenSong, "Off")

	status.Value = "Cleaning up map..."

	wait(3)

	newMap:Destroy()

	wait(7)
end

--[[function gamemodes.Wave(gameLength)
	
end

function gamemodes.PlayerAttack(gameLength)
	
end

function gamemodes.HardcoreWave(gameLength)
	
end

function gamemodes.Infection(gameLength)
	
end--]]

return gamemodes


Organization of the scripts (doubt this is helpful, but just in case lol):
image


I do a similar thing in my admin command script, but the only difference is it uses the command name when calling the function in the module, not the table number. But I actually have a way to get the command name; I do not have a way to get the function name for the game mode.


If you can help me figure this out, thank you!
Thank you even if you can’t!

Best regards,
Amora

There isn’t a lot of Specification on your Issue, nor a specification on where everything is

Sorry. Haven’t slept in like 3 days. Can’t think at all lol


Let me try to explain better: my issue is the round module erroring (line 28) since I tried calling a “nil” value, when really it isn’t nil, it just likes to think it is because scripts can’t read the index number of something in a module script (i.e. print(#gamemodes) returns 0, causing there to be no index, resulting in the error when calling gamemodes[1]()).

The specific line causing the issue is gamemodes[chosenMode](gameLength) in the round module. I need a way to call the specific function name. I will be able to do that when I add voting, but I’m nowhere near that step, so it is of paramount importance I get this fixed now so I don’t waste hours implementing something and breaking the entire game.

Go to sleep, the next day you will be like: Well ofcourse i know where the issue is!

You’re simply trying to call a key that does not exist within gamemodes.

local chosenMode = 1
status.Value = ""
	
gamemodes[chosenMode](gameLength)

If you want to pick a random function, you can simply do (I don’t think you can just call a random function):

local gamemodesList = {gamemodes.Standard, gamemodes.Wave} -- ...
local chosenGamemode = gamemodesList[math.random(#gamemodesList)]
chosenGamemode(gameLength)
1 Like

God, I’m so stupid.

I don’t remember anything about what I was thinking, honestly. Especially after going to bed last night lol.
I might’ve thought to do that but ruled it out because I’d forget to add new gamemodes to that table when I add more gamemodes to the module, even though by the time I do that I’d already have voting in place :laughing:

I was prob like “I’m gonna forget to add this stuff, so lemme do smth different even though this will work perfectly fine”. I hate myself

2 Likes

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