For loop only takes one value from a table

So im creating a roulette with a weighted system and tried importing it to a modulescript. the first for loop prints 1000 as it’s supposed to but the second one prints 15 everytime giving the player extra 5 spins every time.

local rewardModule = {}

rewardModule.spinChance = {
	Nothing = 86.9;
	Extra1Spin = 8.5;
	Extra3Spin = 2.5;
	Extra5Spin = 1.5;
	Coins = .5;
	Ugc = .1;
}

function rewardModule.Spin(plr)
	
	local weight = 0
	
	for _, chance in pairs(rewardModule.spinChance) do
		weight += (chance * 10)
		print("First Chance: "..chance)
		print("First Weight: "..weight)
	end

	local runNumber = math.random(1, weight)
	task.wait()
	weight = 0
	
	for prize, chance in pairs(rewardModule.spinChance) do
		weight += (chance * 10)
		print("weight: "..weight)
		if weight >= runNumber then
			print(plr.Name.." got "..prize)
			--[[if prize == "Extra1Spin" then
				plr.leaderstats.Spins.Value += 1
			elseif prize == "Extra3Spin" then
				plr.leaderstats.Spins.Value += 3
			elseif prize == "Extra5Spin" then
				plr.leaderstats.Spins.Value += 5
			elseif prize == "Coins" then
				plr.Data.Coins.Value += 1
			elseif prize == "Ugc" then
				print("not adding yet")
			end]]
			break
		end
		--print("Module weight: "..weight.." Module Prize: "..prize.." runNumber: "..runNumber)
		return prize, chance
	end
	
	weight = 0
	
end

return rewardModule

3 Likes

I changed the second for loop to this:

for prize, chance in pairs(rewardModule.spinChance) do
		weight += (chance * 10)
		print("chance: "..chance)
		print("weight: "..weight)
		if weight >= runNumber then
			print(plr.Name.." got "..prize)
			--[[if prize == "Extra1Spin" then
				plr.leaderstats.Spins.Value += 1
			elseif prize == "Extra3Spin" then
				plr.leaderstats.Spins.Value += 3
			elseif prize == "Extra5Spin" then
				plr.leaderstats.Spins.Value += 5
			elseif prize == "Coins" then
				plr.Data.Coins.Value += 1
			elseif prize == "Ugc" then
				print("not adding yet")
			end]]
			break
		end
		--print("Module weight: "..weight.." Module Prize: "..prize.." runNumber: "..runNumber)
		return prize, chance
	end

And it only prints 1.5 as shown below.

1 Like

Your not exactly randomizing it I believe.

1 Like
Its 4 AM This Is Probably Not Useful

I would try doing one of the sort:

weight += (chance * math.random(1,10))
--// Randomized Output: First Weight: 4.5

or

weight += (chance * Random.new():NextNumber(1,10))
--// Randomized Output: First Weight: 5.698043722618261 

Which would customize you’re weight.

Your basically looping through the module with pairs so its going to obviously always start at that exact one it always does, so I would possibly recommend picking randomly if that’s what you want.

1 Like

pairs is not an ordered iterator. For the type of system you’re trying to make, you have to loop through the prizes from highest to lowest chance order, which is the order you have them listed, but not necessarily the order that pairs is going to step through them. Your code here is basically implementation-defined behavior. You need to use an array-type table with ipairs instead of a dictionary table in order to achieve this, e.g.:

rewardModule.spinChance = {
	{ prize = "Nothing", chance = 86.9 },
	{ prize = "Extra1Spin", chance = 8.5 },
	{ prize = "Extra3Spin", chance = 2.5 },
	{ prize = "Extra5Spin", chance = 1.5 },
	{ prize = "Coins", chance = .5 },
	{ prize = "Ugc", chance = .1 },
}

If you loop through this with ipairs, it will always loop over the entries in the order they are listed.

1 Like

the first loop on the script i provided was working fine but the second one only gets the first item in the table. it was originally on a server script and worked perfectly fine before. i made the weighted system from this Weighted Chance System post

2 Likes

it goes through every single item in the table and adds them up.
atleast thats what it’s supposed to do

1 Like

You are placing the return here wrong. It not only exits the loop with the first loop entry, but returns that first entry. Replace the break with the return, remove your current return and it should work. I did this:

-- The ModuleScript
local rewardModule = {}

rewardModule.spinChance = {
	Nothing = 86.9;
	Extra1Spin = 8.5;
	Extra3Spin = 2.5;
	Extra5Spin = 1.5;
	Coins = .5;
	Ugc = .1;
}

function rewardModule.Spin(plr)

	local weight = 0

	for _, chance in pairs(rewardModule.spinChance) do
		weight += (chance * 10)
		print("First Chance: "..chance)
		print("First Weight: "..weight)
	end

	local runNumber = math.random(1, weight)
	task.wait()
	weight = 0

	for prize, chance in pairs(rewardModule.spinChance) do
		weight += (chance * 10)
		print("weight: "..weight)
		if weight >= runNumber then
			print(plr.Name.." got "..prize)
			--[[if prize == "Extra1Spin" then
				plr.leaderstats.Spins.Value += 1
			elseif prize == "Extra3Spin" then
				plr.leaderstats.Spins.Value += 3
			elseif prize == "Extra5Spin" then
				plr.leaderstats.Spins.Value += 5
			elseif prize == "Coins" then
				plr.Data.Coins.Value += 1
			elseif prize == "Ugc" then
				print("not adding yet")
			end]]
			return prize, weight, chance, runNumber -- Place the return here instead to return price, weight,... etc. when the player won(or did not win anything)
		end
		--print("Module weight: "..weight.." Module Prize: "..prize.." runNumber: "..runNumber)
	end

	weight = 0

end

return rewardModule
-- Example usage in a LocalScript
local price, weight, chance, number = rewardModule.Spin(player)
print("Price is: " .. price .. " with weight " .. weight .. " and chance " .. chance .. " and number " .. number)

Please note that everything after the return() won’t be executed, i.e., your print("Module weight: "..weight.." Module Prize: (...) will not be executed. If you want to add code afterwards, then break in the loop instead and store the win, weight etc. that won in a specific local variable.

Hope this helps!

3 Likes

Tried multiple variations on your idea and it finally worked. It was something wrong with the ‘break’ function. Much thanks!

1 Like

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