Need help with this chance system

NOTE: I am basing my chance system off of the solution in How do i make a chance system?, so tell me if it is outdated or something.

So I am making a chance system where there is a chance that you get Moltenite instead of Meteorite.

I made a test one on a baseplate and here is the script:

local deb = false
script.Parent.Touched:Connect(function(hit)
	if not deb then
		if hit.Parent:FindFirstChild("Humanoid") then
			if game.Players:GetPlayerFromCharacter(hit.Parent) then
				local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
				local leaderstats = plr.leaderstats
				
				local chances = {
					Cash = 75,
					Crystals = 25
				}
				
				local random = math.random(100)
				
				for i, v in pairs(chances) do
					if random <= v then
						print(i)
						leaderstats[i].Value = leaderstats[i].Value + 1
					else
						--print(i)
					end
				end
				
				script.Parent.Parent = game.ServerStorage
				deb = true
				wait(1)
				deb = false
				script.Parent.Parent = workspace
			end
		end
	end
end)

However, there is one problem. If you get crystals, you also get cash (prints “Crystals” and “Cash”).

How am I supposed to fix this?

END NOTE: Please do not tell me my code is messy, I am not looking for people to say “Your code is messy”. I want to get my problem solved and I will make it less messy later.

1 Like

Alright, right on top of the “if random <= v then” put “random = math.random(100)”
try that

1 Like

Basically, you were using the same randomness value for Cash and Crystals, so if you change it after each value, you have different chances of getting them.

1 Like

Try using NumberRanges : Selecting Value from Table - #3 by un1ND3X

Or,

replace that with


-- the if part of your if statement
leaderstats[i].Value = leaderstats[i].Value + 1
   return
end
	

adding a return.

1 Like
Old reply

In the solution, i’ve seen that inside the else statement, it would substract the random variable wiith the entry weight, something like this:

else
    random = random - v
end

I don’t know if that would be the issue.

Try to finish the loop when you find a random currency, something like this:

local AlreadyFound = false

for i, v in pairs(chances) do
    if not AlreadyFound then
        if random <= v then
            print(i)
            leaderstats[i].Value = leaderstats[i].Value + 1
        else
            random = random - v
        end
    end
end

With your current code, if you get the number 10, the code would search for every item inside your table, and check if the number is smaller than the weight of every item, since the number 10 is smaller than both items you have, then you would recieve two currencies, in the solution of my thread, it would be a function, when it finds an item, it would return the value, since it returns, the code would stop, and your code wouldn’t stop even if you find a result, the way to fix that would be converting the part of the code i quoted in a function, or just check if a result was already found with a boolean variable, as i mentioned before, i hope this helps you

I hope this helps you :+1:

1 Like

You iterate through all of the chances and in some cases random is bigger than 75 and 25, causing you to get both.

Here is some code I wrote to show you how weighted chances would work with your system:

local Debounce = false

local Chances = {
	Cash = 75,
	Crystals = 25
}

local WeightedChances = {}

for Type, Value in next, Chances do -- Iterate through all of the things in the table
	for Loop = 1, Value do -- Add x elements to the WeightedChances table
		table.insert(WeightedChances, tostring(Type)) 
	end
end

function PickChance()
	return WeightedChances[math.random(1, #WeightedChances)] -- Pick a random chance. Think of this like a raffle there are 75 "Cash" tickets and 25 "Crystals" tickets. Picking one randomly should give Cash and Crystals a 75 and 25 percent chance, respectively.
end

function OnTouched(Hit)
	if not Debounce then -- Typical debounce stuff
		
		local Chance = PickChance() -- Store the chance we got in this
		local Player = game:GetService("Players"):GetPlayerFromCharacter(Hit.Parent) -- Get the player that touched the part
		
		if Player then
			local Parent = script.Parent.Parent
			
			Debounce = true 
			Player.leaderstats[Chance].Value = Player.leaderstats[Chance].Value + 1
			script.Parent.Parent = game:GetService("ServerStorage")
			
			coroutine.resume(coroutine.create(function() 
				wait(1)
				script.Parent.Parent = Parent
				Debounce = false	
			end))
		end
	end
end

script.Parent.Touched:Connect(OnTouched)
4 Likes
local deb = false

local Minimum = 25
local Maximum = 700

script.Parent.Touched:Connect(function(hit)
	if not deb then
		if hit.Parent:FindFirstChild("Humanoid") then
			if game.Players:GetPlayerFromCharacter(hit.Parent) then
				local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
				local leaderstats = plr.leaderstats
				
				local chances = {
					Cash = NumberRange.new(250,700),
					Crystals = NumberRange.new(25,70)
				}
				
				local random = math.random(Minimum,Maximum)
				
				for i, v in pairs(chances) do
					if random >= v.Min and random <= v.Max then
						leaderstats[i].Value = leaderstats[i].Value + 1
						print(i)
					end
				end
				
				script.Parent.Parent = game.ServerStorage
				deb = true
				wait(1)
				deb = false
				script.Parent.Parent = workspace
			end
		end
	end
end)

What’s now weird is that sometimes you don’t even get anything. Neither cash or crystals…

Try my code.

I wrote it for you :grinning:

2 Likes