Well it’s certainly possible, but implementation relies heavily on what you mean by 2x luck.
Weighted chance is a pretty simple idea.
Start with the simplest case. Equal weight
local rarities = {
'Common',
'Rare',
}
In this case, I merely have to pick one at random
return rarities[math.random(#rarities)]
Now a weighted random… Let’s say (again keeping it simple, we want Common to appear 75% of the time.
We could do this
local rarities = {
'common',
'common',
'common',
'rare',
}
local function pick()
return rarities[math.random(#rarities)]
end
Now it’s weighted. Since common is in the list 3 times and rare in there once, we would expect common to be the result 3/4 times. Now it’s a weighted random. We have 2 more changes to make, but these changes just make it more convenient to work with and use less memory, it’s still fundamentally doing exactly what’s above.
The first change is that writing out a new one for every item is tedious and balancing them is annoying.
So like how you are doing so in you’re example, we will assign a weight. This weight is the amount of times we want it to appear in our list. So to match our last example we can do
local rarities = {
common = 3
rare = 1
}
At this point though, we are going to work with your original data
local rarities = {
['Common'] = 50,
['Uncommon'] = 25,
['Rare'] = 24,
['Legendary'] = 1
}
In which case our pool will have 50 commons listed out and 25 uncommons, 24 rares and 1 legendary.
Now we could write some code that expands that into a list
local pool = {}
for name, count in pairs(rarities) do
for i=1, count do
table.insert(pool, name)
end
end
Which would write it all out so we can just pick a random one from the list again.
However, there is an optimization we can make. It technically won’t be faster, but it will use less memory. Instead of making a list of all the names, we can just keep the count of how many are in each and get a total
local total = 0
for name, count do
total = total + count
end
Now with your example total is equal to 100 since that’s how many entries we would have if we were to expand it out into a list. Now we pick a random number 1-100. This is going to effectively be the index we want in our list.
local r = math.random(100) --If only one value is given it defaults to math.random(1,100) btw
And now since we don’t really have a list of 100 values, we will have to do some math to figure out which category this would have landed in
local function pick()
local r = math.random(total)
for name, count in pairs(rarities) do
r = r - count
if r <= 0 then
return name
end
end
end
Basically we just loop through each value and subtract the amount of entries it would have in the pool. If it ends up being less than or equal to 0, then it would have landed somewhere in the section with that name.
Hopefully this makes sense and you understand weighted random systems better.
To change the effects of luck, you will need to double the entries of an item you want the chance to double for. However, note that because it’s dynamic, you won’t quite double the chances.
Say you double the amount of tickets rare has.
Now there are 48 rares
The older percentages are common 50%, uncommon 25%, rare 24%, legendary 1%. Now that we have doubled the tickets for rare, the new percentages are (tickets/124(total)) common 50/124 = 40.32% uncommon 25/124 = 20.16% rare 48/124 = 38.71% legendary 1/124 = 0.81%.
So the exact definition of 2X is super important here as changing one changes the chances for all. Just keep in mind if you change the amount of entries an item has, you will need to recalculate the total to account for it, otherwise you’ll make some of the entries either more rare than they should be, or impossible to get.