Digging for RNG Solutions

In this case, you can do something like that (using @JKbings0099 's script as a reference):

local rarities = {
    {name = "Mythical", chance = 1/10000},
    {name = "Legendary", chance = 1/1000},
    {name = "Epic", chance = 1/100},
    {name = "Rare", chance = 1/10},
    {name = "Uncommon", chance = 1/4},
    {name = "Common", chance = 1/2}
}

local function rollRarity()
    local current_raritiy
    local possible_rarities = {}

    for i = #rarities, 1, -1 do
        if math.random() < rarities[i].chance then
            current_rarity = rarities[i].chance

            for i = #rarities, 1, -1 do
                if current_rarity == rarities[i].chance then
                    table.insert(rarities[i].name)
                end
            end

            return possible_rarities[math.random(1, #possible_rarities)]
        end
    end
    return "Common"
end

print("You obtained: " .. rollRarity())
1 Like

I’m gonna be out for most of the day, so I’ll test this out when I get home. This does look basically what I’m looking for though so I’m like 99% sure it will be it! :partying_face:

This feels kinda over complicated? Idk something about use a pair loop in a pair loop makes me cringe :grimacing:

That’s the answer for what you want though. You can change stuff as you wish later.

1 Like

What you marked as the solution is just a less developed rarity/item rolling system. It will still give misleading results due to the math.random() being called multiple times throughout the for loop.

You can fix that like this:

Edit: You also cannot use percentages for rarities with the current solution if you desire to do so.

Why would you store math.random() though? We are not storing math.random(), we are creating several math.randoms for purpose.

I mean, now that I’ve thought about that, I think it’s better storing math.random outside the loop

By that you can do this:

local rarities = {
    {name = "Mythical", chance = 1/10000},
    {name = "Legendary", chance = 1/1000},
    {name = "Epic", chance = 1/100},
    {name = "Rare", chance = 1/10},
    {name = "Uncommon", chance = 1/4},
    {name = "Common", chance = 1/2}
}

local function rollRarity()
    local value = math.random()
    local current_raritiy
    local possible_rarities = {}

    for i = #rarities, 1, -1 do
        if value < rarities[i].chance then
            current_rarity = rarities[i].chance

            for i = #rarities, 1, -1 do
                if current_rarity == rarities[i].chance then
                    table.insert(rarities[i].name)
                end
            end

            return possible_rarities[math.random(1, #possible_rarities)]
        end
    end
    return "Common"
end

print("You obtained: " .. rollRarity())

To clarify, I am talking only about the math.random() in this line:

The problem is you are creating a new random number in each iteration of the for loop.

If I get a 0.01 as my random number (I rolled a 1% rarity, yay!), that should be what determines the rarity of the item I unlock.

Currently, that does not happen. On the each iteration it will pick a rarity based on a new random number because the random number keeps changing.

Yes, you are correct. Thanks for clarifying it! ^^

1 Like

While looking at it some more, this code doesn’t even function. It will error. Have you tested this? I have spent many hours refining the system I provided because I use it in my games.

Error, where? I didn’t test it. I’ve made it with my cellphone which is bad

My point is, I have provided a robust solution that does the exact same thing with much more care and thought put into it. It seems counterproductive to spend time on an apparently underdeveloped solution.

I don’t want to come across as rude btw, that is not my goal at all. We’re both doing the OP a service by spending our time to assist.

I actually agree. I’ve made that script within a few minutes, it’s not meant to be robust or anything. I think your answer should be marked as the solution, as it is more efficient and better-looking in general. :smile:

1 Like

I appreciate your understanding.

But, it’s possible he prefers the more rudimentary route. If that is the case, I can help fix it up.

Here is the fixed current solution (you still cannot use percentage based chances or apply luck boosts, but everything does work properly now):

-- Note: 'rarities' must be ordered from rarest to most common (descending rarity)
local rarities = {
    {name = "Mythical", chance = 1/10000, items = {"Mythical_1", "Mythical_2"}},
    {name = "Legendary", chance = 1/1000, items = {"Legendary_1", "Legendary_2"}},
    {name = "Epic", chance = 1/100, items = {"Epic_1", "Epic_2"}},
    {name = "Rare", chance = 1/10, items = {"Rare_1", "Rare_2"}},
    {name = "Uncommon", chance = 1/4, items = {"Uncommon_1", "Uncommon_2"}},
    {name = "Common", chance = 1/2, items = {"Common_1", "Common_2"}}
}

local function rollItem()
    local randNum = math.random()
    local rolledRarity = rarities[#rarities] -- Start with the "Common" rarity as a backup (this means that the 'chance' of "Common" is actually '1')
    for i = 1, #rarities do
        if randNum < rarities[i].chance then
            rolledRarity = rarities[i]
            break
        end
    end
    return rolledRarity.items[math.random(1, #rolledRarity.items)] 
end

print("You obtained: " .. rollItem())