# How to make a chance / percentage script

I have made my own script but somene said its inaccurate and I just want to know how to make a script that has a % chance of getting something and also for it to not only include whole numbers but decimal percentages such as 3.1,0.1,0.001

My script:

1 Like

`if chosenchance == 60 or chosenchance > 32 then`
The first condition of this expression is unnecessary, if `chosenchance` is greater than 32 then it can also be 60. The same applies for the other expressions where this logic is used.

1 Like
``````local chances = {
SpeedBoost = 60;
JumpBoost = 32;
Regen =7;
LowGravity = 1;
}

script.Parent.MouseButton1Up:Connect(function()
local x = Random.new():NextNumber(0,100)
print(x) -- or math.round(x)

if x >= chances.LowGravity and x < chances.Regen then
print("LowGravity!")
elseif x>= chances.Regen and x < chances.JumpBoost then
print("Regen!")
elseif x>= chances.JumpBoost and x<chances.SpeedBoost then
print("JumpBoost!")
elseif x>= chances.SpeedBoost then
print("SpeedBoost!")
end
end)
``````

Something like this?

1 Like

what is the random.new():nextnumber(0,100)

Hereâs another idea you can play around with. Rather than relying on fixed percents for the value in the chances dict, it treats those numbers as ratios. So, if there were 3 items in the list that had equal probability, then they would each have the same value. In your given chances dict, the values as ratios are 60:32:7:1, since the total is 100, then the chances of ea are 60/100, 32/100, 7/100, 1/100 or 60%, 32%, etc. You donât need the values in the chances dict to be percents (portions of 100) though; would work fine with other ratios like 1:1:1, which would become 1/3, 1/3, 1/3 or 33%, 33%, 33% as the odds.

Can think of this code as working like a wheel. Each item in your chances dictionary is a wedge on the wheel and its size is proportional to the odds that it will be picked. Something like this if the âwheelâ were linear (letters rep ea item in the list).
`0 [L][..R..][........J........][....................S....................] 100`
when a rand number is picked between the start and end values (0 and 100 in this case), where it falls determines which item is selected. Since âSâ , here, takes up the most space in that range, it is the most likely to be picked.

``````local CHANCES = {
SpeedBoost = 60,
JumpBoost = 32,
Regen = 7,
LowGravity = 1,
}
local sumOfChances	-- could be pre-calculated and stored in constant

-- uses const CHANCES dict
local function getSumOfChances()
local sum = 0
for k,v in pairs(CHANCES) do
sum += v
end
return sum
end

-- uses const CHANCES dict
local function spinTheWheel(sumOfChances)
local randValue = Random.new():NextNumber(0.0, sumOfChances)
local runningCount = 0

for k,v in pairs(CHANCES) do
runningCount += v
if randValue < runningCount then
return k
end
end
end

``````
Example
``````-- test
sumOfChances = getSumOfChances()
testDict = {}

for i = 1, 1000 do
local val = spinTheWheel(sumOfChances)
if testDict[val] == nil then
testDict[val] = 1
else
testDict[val] += 1
end
end

for k,v in pairs(testDict) do
print(k,v)
end
``````

An advantage of this kind of approach is that you donât necessarily have to change all the values when you add a new item to the chances list. For example, lets say we start with two items that are common and equally likely to be chosen. We could assign ea of them the value 100. In that case, the spinner would choose a rand nbr between 0 and 200 with 0-100 going to the first and 1-200 to the second. If we wanted to add a new item that was twice as likely to be chosen as our baseline items, then it could be given the value 200 and the others would stay as they are. If a fourth item was only 1% as likely to be chosen as one of our two baseline items, then it would be given a value of 1. This makes rare items VERY rare as the number of items in the list increases. To combat that you could spin twice: once for a category (rare vs common vs uncommon), then again for a specific item in the category.
The complaint about your code being âinaccurateâ is probably related to the use of the math.random() function. Since you put 0,100 as the arguments, that function actually includes both of those values as options. The default behavior of math.random() without args is to return a decimal value in range [0,1) â includes 0 but not 1. When you pass arguments like math.random(m,n), the behavior changes so that it returns an integer value in range [m,n]âincludes both the m and the n as choices. This means your math.random(0,100) includes an extra value (0,1,2âŚ100 = 101 values). I hope that makes sense. You could likely fix your code into something youâre happy with by changing that line to `math.random(0,99)`. Random:NextInteger(0,100) would be the class equiv and avoids this prob because it returns int values in range [m,n)âexcludes the n by design. The :NextNumber method returns decimal numbers in that same [m,n) range.