Rarity system isn't working as intended. (invalid argument #1 to 'pairs' (table expected, got nil))

I’ve been having problems with a rarity system, and so I’m wondering what can I do to fix it? As I have defined the array needed, and I have followed the proper steps as shown to me by another dev forum member. However, despite this, it is still throwing an error each time I try to print the function linked to the rarity system. Below you will find the erroneous code responsible for this.

local MultiplierArray = {
	Rock = 0.35,
	IronOre = 0.25,
	GoldOre = 0.1,
	AzureOre = 0.01,
}

local function chooseIndex(MultiplierArray)
	local weightedSum = 0
	for i, v in pairs(MultiplierArray) do
		weightedSum += v
	end
	local random = Random.new()
	local rnd = random:NextNumber(0, weightedSum)
	print(rnd)
	for i,v in pairs(MultiplierArray) do
		if rnd <= v then
			return i
		else
			rnd -= v
		end
	end
end

Players.PlayerAdded:Connect(chooseIndex())
3 Likes

You need to remove the () in the connection at the bottom. You’re essentially firing the function with no MultiplierArray argument in that case there.

Players.PlayerAdded:Connect(chooseIndex)

There’s a new error, as I’ve changed the faulty line of code, and now I am met with "invalid argument #1 to ‘pairs’ (table expected, got Instance)

That’s because you’re connecting the function directly to PlayerAdded. PlayerAdded will pass anything it gives into that function when it fires, so your “instance” in this case was the player object.

Really simple change, just don’t link the function and connection so closely so you can use variables outside:

Players.PlayerAdded:Connect(function()
    chooseIndex(MultiplierArray)
end)

Also, make sure you rename that table at the top to something else, you don’t want conflicting names in programming.

Or instead of doing that you can just remove the MultiplierArray parameter from the function entirely because there’s no reason for it to be there in the first place.

There may not be a reason in this current example, but it’s better to keep it as a variable in case a different table needs to get fed through (Like a different multiplier array from a different activity).

I’m unsure if I’m understanding this system correctly, but, when I try to do this, nothing is printed out for me to see!

Also, I did change my array to be named something different.

I made a post a long time ago that explains what you have to do to ensure your player (and character) get properly hooked into code. You have to handle the players that exist after connection. If a player is already in the game and then you connect the function, it’s not going to run the code for that player since it already exists.

Players.PlayerAdded:Connect(function()
    chooseIndex(MultiplierArray)
end)
for _, v in Players:GetPlayers() do
    chooseIndex(MultiplierArray)
end

Keep in mind that the principle of what I’m saying is there, but that doesn’t mean it’s the best code. For example, since chooseIndex() is not reliant on a specific player instance, you could just run the function once after the connection and be done.