How will I go about making a chance system that supports Luck Boosts?

Me in the back after reading the last line while searching through dev forum for a total of 9 hrs on this system: screams in agony

Do I use the function to find the Calculated Chance on each Roll?

Hey, just came back and thought about it, I was totally dumb for thinking of using ^3 when the increase in the multiplier can just be linear. The Formula is really simple
f(x) = multiplier/max * chance
Basically, you’d be able to do:

function calculateChanceMultiplier(chance, maxMultiplier)
return multiplier/maxChance * chance
end

That’s that.

Now, you mentioned having 46 rarities. I’d recommend storing them in a module script in a table sort of like

module = {
Epic = 20,
Legendary = 10
}
return module

But I’m not sure if that is actually important in your case. Just keep in the back of your mind.

I’ve never implemented a system like this, but I guess when you roll and I don’t know what yours works like, but upon rolling, you probably get a table of all chances, then you use math.random or whatever and get one of them depending on the math.random return? In that case, whenever you roll and get the table of chances, just multiply the chance by the chance multiplier.

Hope this works and helps!

Wait, If I multiply the chance, doesn’t that make it more rare?

I worked on a small start of the RandomHandler script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StatsFolder = ReplicatedStorage:WaitForChild("Stats")
local EventsFolder = ReplicatedStorage:WaitForChild("Events")

local activateRoll = EventsFolder:WaitForChild("ActivateRoll")
local messages = EventsFolder:WaitForChild("Messages")

local totalStats = StatsFolder:GetChildren()

local function SelectRarity(player)
	
	local luckboost = player.Boosts.Luck.Value
	
	--randomizer code
	
end

activateRoll.OnServerInvoke = function(player)
	
	player.leaderstats.Rolls.Value += 1
	local t = {}
	
	for i=1, workspace.GameInfo.RollAmount.Value - 1 do
		
		table.insert(t, StatsFolder[SelectRarity(player)])
		
	end
	
	local s = StatsFolder[SelectRarity(player)]
	
	if s.Value >= 750 then
		
		messages:FireAllClients(player.Name .. " has gotten " .. s.Name .. "! (1/" .. s.Value .. ")")
		
	end
	
	table.insert(t, s)
	
	print(s)
	
	return t
	
end
1 Like

It depens on what your system works like… If so, I think this should fix it:

function calculateChanceMultiplier(chance, maxMultiplier)
  return -multiplier/maxChance * chance + maxChance
end

Seems fine, if you need a reference on how to make a weight based luck system there is this post which is quite helpful:

I can use that, but how would I make the NumberRange fit the numbervalue? I could give you permissions to the game if you’d like.

No need, when you :GetChildren() you can sort that table to go from largest to smallest, that way you don’t need to define a maximum, you just check if the rand is higher than the value. You can use table.sort for this.

local rarities= ...:GetChildren()
table.sort(rarities, function(a, b)
  return a.Value > b.Value
end

I think that should work.

What do I do after that? Do I use the thing you showed me?

You should probably recalculate the chances depending on their multiplier before you sort them. Then when you get the random number, you should multiply the maximum by the max multiplier as well.

Im gonna go eat lunch, please list a lot of script examples on what I can do…

function calculateChanceMultiplier(chance, maxMultiplier) -- Calculates the multiplier for each rarity
	return maxMultiplier/maxChance * chance
end

local function selectRarity(player) -- Selects one of the rarities provided
	local luck = player.Boosts.Luck.Value
	-- Get the rarities, multiply them, and sort them
	local rarityTable = totalStats:GetChildren() -- table with all the chance values
	for _, chance in pairs(rarityTable) do -- Calculate the new chances by multiplying with luck boost
		chance.Value *= calculateChanceMultiplier(chance.Value, luck)--multiply with multiplier
	end
	table.sort(rarityTable, function(a, b)
		return a.Value > b.Value
	end
	-- Select one of them
	local rand = math.random(rarityTable[1].Value, rarityTable[#rarityTable].Value)
	for _, chance in pairs(rarityTable) do
		if chance.Value >= rand then
			return chance -- Picked this one
		end
	end
end

From here, you’ll want to have the client invoke the server to Select a rarity and give it to the player, as well as tell the client which one it received so that it can do the appropriate effects locally.

These functions might not work entirely with your script and you might need to fix them up a bit.

I changed things up and it says that argument #2 for random is empty.

local maxChance = 25000

function calculateChanceMultiplier(chance, maxMultiplier) -- Calculates the multiplier for each rarity
	return maxMultiplier/maxChance * chance
end

local function selectRarity(player) -- Selects one of the rarities provided
	local luck = player.Boosts.Luck.Value
	-- Get the rarities, multiply them, and sort them
	local rarityTable = totalStats -- table with all the chance values
	local rarities = {}
	
	for _, chance in pairs(rarityTable) do -- Calculate the new chances by multiplying with luck boost
		table.insert(rarities, {chance.Name, chance.Value * calculateChanceMultiplier(chance.Value, luck)})
	end
	table.sort(rarities, function(a, b)
		return a[2] > b[2]
	end)
	-- Select one of them
	local rand = math.random(rarities[1][2], rarities[#totalStats][2])
	for _, chance in pairs(rarities) do
		if chance[2] >= rand then
			return StatsFolder[chance[1]] -- Picked this one
		end
	end
end

try to make #totalStats #rarities instead.

local rand = math.random(rarities[1][2], rarities[#rarities][2])

Did that too, still output the same result.

Did you convert the totalStats to a table or is it still a folder? If its a folder you need to :GetChildren().

I tried putting the maxChance in #2 argument, BUT it always gave me the rarest rarity.

It’s using :GetChildren() so thats not the issue.

By the way, I printed the table, and I checked what the rarest rarity is, and its the same value.

I forgot that we’d have to switch the values for the random around since the table is sorted higehst to lowest and also, we’ll need to implement the reversed multiplier from earlier here because of that:

function calculateChanceMultiplier(chance, maxMultiplier)
	return -maxMultiplier/maxChance * chance + maxMultiplier
end
local rand = math.random(rarities[#rarities][2], rarities[1][2])

I tested and it runs properly for me, let me know if it works for you.