Help with making a Pet randomizer

Hey, so I’ve been working on this pet unlocking system and I have pretty much everything working except the part of the script where it will choose a random pet. I tried following several tutorials like the @UseCode_Tap but it’s still sometimes doesn’t work with what I have. I even tried to make it round but still was breaking.

local petFound 	= false
	local petNumber = math.random(1,100)
	local pet 		= nil
	
	local Egg		= PD[EggName]
	while petFound == false do
		for i, v in pairs(Egg)do
			local number = math.random(1,v.Rarity)
			local newNumber = math.floor((number/5)*5)
			print(newNumber)
			if number == petNumber then
				petFound = true
				pet = v.Name

				return pet
			end
		end	
		wait()
	end	

Any help would be useful! :slight_smile:

1 Like

Using math.random doesn’t work well for pets. In your script there is only a small chance that the petNumber will be equal to any of the egg’s random number. Instead you want to use weight system. Watch the following video, it’s long but you only need to watch part of it that explains how to find random egg.

2 Likes

If you’ve got a list and you want to choose a random element from it uniformly, you can do

local random = Random.new()

...

local function pickRandom(list)
    return list[random:NextInteger(1, #list)]
end

...

local picked_item = pickRandom(item_list)

If you’ve got a dictionary of items to item weights, you can pick a random item from that dictionary, weighted according to the associated weight, like this:

local item_weights = {
	A = 1,
	B = 5,
	C = 10,
}

local function table_sum(list)
	local result = 0
	for _, value in pairs(list) do
		result = result + value
	end
	return result
end

local function pick_random_weighted(dict_item_weight)
	local weights_sum = table_sum(dict_item_weight)
	local picked_index = random:NextInteger(1, weights_sum)
	local picked_item
        
        --Figure out which item and weight interval the picked index lies in
	local interval_start = 0
	for item, weight in pairs(dict_item_weight) do
		local interval_end = interval_start + weight --Update the weight interval
                
                --Check if this item is in the weight interval...
		if picked_index > interval_start and picked_index <= interval_end then
			picked_item = item  -- ... if so, pick it...
			break -- ... and stop looking.
		end

		interval_start = interval_end --Update the weight interval
	end

	return picked_item
end

--This is how you call the function
pick_random_weighted(item_weights) -- Prints something like 'C' (usually 'C', since it's the most common)

You might want to know the chance that something gets picked:

local function get_weighted_chance(dict_item_weight, item)
	local weights_sum = table_sum(dict_item_weight)
	local item_weight = dict_item_weight[item]
	return item_weight/weights_sum
end

And you can test that it actually works as expected like this:

--Count how many times each item gets picked
local picked_counts = {}
for _ = 1, 100000 do
	local picked = pick_random_weighted(item_weights)
	picked_counts[picked] = (picked_counts[picked] or 0) + 1
end

--Print how often each item was picked
for k, v in pairs(picked_counts) do
	print( ("%s: %d/100000\t(%.0f%%)"):format(tostring(k), v, get_weighted_chance(item_weights, k) * 100) )
end

Which outputs something like

A: 6387/100000 (6%)
B: 31198/100000 (31%)
C: 62415/100000 (62%)

Since A has a weight of 1 and the weight sum is 16 it should have a 1/16=6.25% chance of being picked, so everything seems to work.

2 Likes

Sorry for the late respond, I will check every suggestion once I have time again. And thanks.

1 Like

That is some complicated stuff, but ill try to make it work from what I understand and since I am not a very advanced scripter I will have to scratch my head to figure it out :sweat_smile:

But Thanks!

1 Like

If anything is unclear I can try explaining it

1 Like