Is there a better way to incorparate luck?

local baseRarityTable = {}
		local luckRarityTable = {}
		local subtractTable = {}
		local totalWeight = 0
		local luck = player:FindFirstChild("OtherStats"):FindFirstChild("Luck").Value
		for i, pet in pairs(RS.Pets[egg]:GetChildren()) do
			baseRarityTable[pet.Name] = pet.Rarity.Value
			totalWeight += pet.Rarity.Value
		end
		local numberOfNonRarePets = 0
		for pet, chance in pairs(baseRarityTable) do
			if chance >= 10 then
				numberOfNonRarePets += 1
			else
				chance *= luck
				table.insert(subtractTable,chance-(RS.Pets[egg]:FindFirstChild(pet).Rarity.Value))
			end
			luckRarityTable[pet] = chance
		end
		for pet, chance in pairs(baseRarityTable) do
			if chance >= 10 then
				for i, subtractAmount in ipairs(subtractTable) do
					chance -= subtractAmount/numberOfNonRarePets
				end
			end
		end

This is what I made to figure out luck, but it is messy and hard to follow. Is there a more efficient way?

I’ve done this system before here how it looks, it’s pretty simple actually:

--Trees Reference with spawn change
local trees = {
	{script.Basic, 50/100}, -- 50%
	{script.Intermediate, 25/100}, -- 25%
	{script.Advanced, 12.5/100}, -- 12.5%
	{script.Neon, 6/100}, -- 6%
	{script.Godly, 1/100} -- 1%
}

--Get a tree based on it's probability to spawn
function getTree()
	local p = math.random()
	local cumulativeProbability = 0
	for name, item in pairs(trees) do
		cumulativeProbability += item[2]
		if p <= cumulativeProbability then
			return item[1]
		end
	end
end
1 Like

I know how to do that, but what I am saying is incorperating the player’s luck. Like if they have 2 luck then all epics and legendaries(Under 10%) have their chances doubled, which has to take away from the less common ones.

By “luck”, you mean like the chance to get the pet, right?

If so, I think what you would need to try using is a weighted random distribution function, which is just long words for “a function that gives biased-ly distributed numbers”.

A function like this:

local function WeightedRandom(min, max, bias)
    return min + (min + max) * math.pow(math.random(), bias)
end

returns a number between min and max (like math.random()) but the bias controls how likely it is to give smaller numbers. (Note: This function also returns floats! If you’re expecting an integer from this function, use math.floor and bump up the max value by 1)


This image above (courtesy of Jibb Smart from StackExchange) shows how the numbers returned change based on the bias (from top to bottom: 1/4, 1/2, 2, 4. 1 is completely linear, like regular math.random).

Therefore, using this, you can have numbers higher up be more likely to generate, like so:

local Luck = 1 -- Set to higher numbers for more luck

local function WeightedRandom(min, max, bias)
    return min + (min + max) * math.pow(math.random(), bias)
end

local ChancesTable = {
    ["Common"] = 0.2,
    ["Rare"] = 0.4,
    ["Epic"] = 0.6,
    ["Legendary"] = 0.8,
    ["Mythical"] = 0.9
}

-- Get reciprocal of the luck value so it works better for the bias function
--local LuckBias = 1 / Luck (edit: the reciprocal is not actually needed sorry)

-- Generate a biased number using the luck bias
local BiasNumber = WeightedRandom(0, 1, Luck)

for rarity, value in pairs(ChancesTable) do
    if value < BiasNumber then
        -- Bias number reached
        return rarity
    end
end

This might be what you’re looking for, it might be not. But I’ll be glad to know if it helped you!

I dont need help with picking the pet randomly, i just need help adjusting the values depending on the player’s luck
For example. Let’s say the base luck table is this
[“Common”] = 70
[“Rare”] = 20
[“Epic”] = 8
[“Legendary”] = 2
This has a total weight of 100. The chance of getting an epic is 8/100 and a legendary is 2/100

If the user has double luck, i would want to legendary and epic values doubled. So the table would become this.
[“Common”] = 70
[“Rare”] = 20
[“Epic”] = 16
[“Legendary”] = 4
The issue with this however is that the total weight is now 110, not 100. The chance of an epic now is 16/110 instead of 16/100 and legendary is 4/110 not 4/100. How would I make the common values go down to keep the total weight 100?

Ok, hold on, lets see what I can think of.

Here’s my answer:
Assuming that you want to do this algorithmically, the way I would do it is

  1. Set up the table to have 2 subtables, one which does not get multiplied (i.e. your common and rare values), and another which does (i.e. your epic and legendaries), to make this easier for you
  2. Multiply the values in the multiplied table by the luck value (as you have done), then take the sum of all the weights and then subtract 100 (lets call this number the weight sum surplus)
  3. Then, divide the weight sum surplus by the amount of values in the table in your no multiply table, and subtract that from all the values in the no multiply table.

I already have this, and this works, but I want to know if there is a better way yto do this?

local function choosePet(player,egg)
		local baseRarityTable = {}
		local luckRarityTable = {}
		local subtractTable = {}
		local totalWeight = 0
		local luck = player:FindFirstChild("OtherStats"):FindFirstChild("Luck").Value
		for i, pet in pairs(RS.Pets[egg]:GetChildren()) do
			baseRarityTable[pet.Name] = pet.Rarity.Value
			totalWeight += pet.Rarity.Value
		end
		local numberOfNonRarePets = 0
		for pet, chance in pairs(baseRarityTable) do
			if chance >= 30 then
				numberOfNonRarePets += 1
			elseif chance <= 10 then
				chance *= luck
				table.insert(subtractTable,chance-(RS.Pets[egg]:FindFirstChild(pet).Rarity.Value))
			end
			luckRarityTable[pet] = chance
		end
		print(numberOfNonRarePets)
		print(baseRarityTable)
		print(subtractTable)
		for pet, chance in pairs(luckRarityTable) do
			if chance >= 30 then
				print(chance)
				for i, subtractAmount in ipairs(subtractTable) do
					chance -= subtractAmount/numberOfNonRarePets
					luckRarityTable[pet] = chance
				end
			end
		end
		
		print(luckRarityTable)
		local selectionNumber = math.random(1,totalWeight)
		local counter = 0
		for petName, chance in pairs(luckRarityTable) do
			counter = counter + chance
			if selectionNumber <= counter then
				player.OtherStats.Index[egg][petName].Value = true
				return RS.Pets[egg][petName]
			end
		end
	end

If there is a better way (other than the weighted random function I proposed earlier), I don’t know it. The code seems to be fine, but I would add some gaps and comments if you’re looking to make it more readable.