Hi, I am trying to add a luck system to my RNG game where the player essentially starts out with 1x luck and can get upgrades to add 0.01x luck or 1x or 2x ect. I am trying to understand how to implement this into the base roll system. I have already created a saving stat for the luck as a number just need to have it applied. This is the script which generates the math.
local module = {
rewards = {
{
Name = 'Common',
Chance = 2,
Price = 10
},
{
Name = 'Uncommon',
Chance = 5,
Price = 25
},
{
Name = 'Rare',
Chance = 10,
Price = 100
},
{
Name = 'Epic',
Chance = 50,
Price = 750
}
}
}
local MaxNum = 100000000
function module:MakeNewReward()
local _RandomNum = math.random(1, MaxNum/2) / MaxNum -- Limit to 0.5
local _ReturnTab = nil
warn('Random Number Choosen: '.._RandomNum)
for i = #module.rewards, 1, -1 do
local Chance = (1/module.rewards[i].Chance)
local Price = (module.rewards[i].Price)
print('Current Reward: '..module.rewards[i].Name..', '..Chance)
if _RandomNum <= Chance then _ReturnTab = {
module.rewards[i].Name,
module.rewards[i].Chance,
module.rewards[i].Price
}
warn('Reward choosen, RewardChance '..Chance..' & RandomNum '.._RandomNum.. 'PRICE:'.. Price)
break else continue end
end
return _ReturnTab
end
return module
Funny how your probabilities don’t even add up to 100, although that’s what’s usually done. Don’t get me wrong: it’s NOT necessary for it to happen now, but it’s just something that’s usually done. The actual probabilities for each element are:
common: 2/(2+5+10+50)
uncommon: 5(2+5+10+50)
and so on…
Now, how is it done? Simple as that: generate a number between 1 and your max prob. (i.e. 67). If the number is between 1 and 2 you get common, else if it’s between 3 and 5 you get uncommon, and so on.
Also, careful reader could even add to the post that you probabilities make no sense: why is “common” having a probability of 2/67 while epic is 50/67? I suggest you review your code.
Instead of using the regular chance system try using weighted random. Basically it’s more efficient, and easier. Also allows to implement new rarities and/or change the luck w/o any worries.
Here is an example
local module = {
rewards = {
{
Name = 'Common',
Chance = 50,
Price = 10
},
{
Name = 'Uncommon',
Chance = 10,
Price = 25
},
{
Name = 'Rare',
Chance = 5,
Price = 100
},
{
Name = 'Epic',
Chance = 2,
Price = 750
}
}
}
--
local MaxNum = 0
for i,v in pairs(module.rewards) do
MaxNum += v.Chance
end
-- !! The higher the chance, the more often the rarity is picked
-- !! Chance should be an integer
-- !! Luck should not be negative or equal to 0
function module:MakeNewReward(luck : number)
local _ReturnTab
local chancePicked = math.random(1, MaxNum / luck)
-- You can either put division in or out the brackets
local totalChance = 0
warn('Random Number Choosen: '..chancePicked)
for i,v in pairs(module.rewards) do
totalChance += v.Chance
if totalChance >= chancePicked then
warn('Reward choosen, RewardChance '..v.Chance..' & RandomNum '.. chancePicked .. 'PRICE:'.. v.Price)
_ReturnTab = table.clone(v)
break
end
end
return _ReturnTab
end
return module
Player is an unknown global as it is in a module script i was having issues earlier today with trying to figure out how to call the player within a module script. This is my first time doing actual work with them
This is what I have changed it to and it doesnt error for getting the player
function module:MakeNewReward(luck : number)
local player = game:GetService("Players").LocalPlayer
luck = player.Luck.Luck.Value
local _ReturnTab
local chancePicked = math.random(1, MaxNum / luck)
but it does give the error
ReplicatedStorage.Rewards:43: attempt to index nil with 'Luck'
Im not sure why that would happen as player.Luck.Luck.Value is the correct place for the stat
That seems to solve the error showing up but unfortunately now nothing functions. I will try to see if i can make it work but im assuming that in the script you made it has some key things different that the other scripts might need
You should just add a multiplier to all the values in luck. The exact specifics of this multiplier depends on how exactly you want luck to scale. Note that because of how luck scales so dramatically you will likely want to make the actual luck value non linear in application. And this is just an example of course. And you can make more complex individual multipliers. The important part is that you have to apply the luck multiplier, count up the new luck total and then run the weighted chance algorithm based on the new weights. Here is a quickly written example.
But basically
rewards = {
{
Name = 'Common',
Chance = 50,
Price = 10,
LuckMultiplier = 1.0025
},
{
Name = 'Uncommon',
Chance = 10,
Price = 25,
LuckMultiplier = 1.005
},
{
Name = 'Rare',
Chance = 5,
Price = 100,
LuckMultiplier = 1.01
},
{
Name = 'Epic',
Chance = 2,
Price = 750,
LuckMultiplier = 1.0125
}
}
local function pick_value(effective_luck)
local chances = {}
local chances_sum = 0
for i, v in ipairs(rewards) do
local newChance = v.Chance * math.pow(v.LuckMultiplier, luck) --Remember you may want to transform luck here to not be so dramatic so fast and maybe cap it or go piecewise or whatever
chances[i] = newChance
chances_sum += newChance
end
local r = math.random() * chances_sum
for i,v in ipairs(chances) do
r-=v
if r <= 0 then
return rewards[i]
end
end
error("This was supposed to have hit 0 at this point, so something went wrong")
end