Random chance for a color to pick

Hello there, for my script I’m wanting to do this. When you spawn in a car it should be able to randomly pick the color and have a chance for that color to be picked.

For Ex:
(If the color red chance was a 0, it wouldn’t get picked at all meaning I don’t want it to pick that color. However with a color like a blue with a chance of 5, it’s more likely to pick that color then the red color with a 0% chance)

Unsure of how this could be written with code.

--local RN = BrickColor.random()

--script.Colors.Value = RN
Colortable = { {"Really Black",10}, 
{"Black",5}, 
{"Bright red",1}, 
{"Lily White",1}, 
{"Institutional white",1}, 
{"Bright green",1}, 
{"Deep blue",1}, 
{"Pine Cone",1}, 
}

PaintObject = script.Parent
PainterPart = "1"
Randomize = math.random(1,#Colortable)

for index, child in pairs(PaintObject:GetDescendants()) do
	if child:IsA("BasePart") and child.Name == PainterPart then
	child.BrickColor = BrickColor.new(Colortable[Randomize])--(Read here) This line of code will give out an error, all that's needed is to change this line of code here.
else end	
end

Please do not write entire scripts or design entire systems.

I believe it’s because when you’re indexing your table with your randomize value, it is returning a table of two items. It should be fixed if you did

 BrickColor.new((Colortable[Randomize])[1])

Let me know if this worked. Also, on another note, your script gets a random color from that table and does not make it more likely to get a color with a higher second number.

Edit: I can give you some tips on how you could add your color chance system if you like if what I said above worked.

1 Like

What are the numbers behind the values, the weights?

It sounds to me like you need a weighted random selection. I’ve already developed a module for an AI system that uses this:

WeightModule
local WeightService = {}

local rand = Random.new()

function WeightService.normalize(weightTable)
	local sum = 0
	local normalized = {}
	for index, weight in ipairs(weightTable) do
		sum += weight
	end
	for index, weight in ipairs(weightTable) do
		local newWeight = weight / sum
		normalized[index] = newWeight
	end
	return normalized
end

function WeightService.nextAction(weightTable)
	local RandomNumber = rand:NextNumber()
	local currentSum = 0
	for index, weight in ipairs(weightTable) do
		currentSum += weight
		if RandomNumber < currentSum then
			return index
		end
	end
end

function WeightService.nextActionByBestWeight(weightTable)
	local bestIndex = 0
	local highestWeight = 0
	for index, weight in ipairs(weightTable) do
		if weight > highestWeight then
			highestWeight = weight
			bestIndex = index
		end
	end
	return bestIndex
end

return WeightService

For this to work, you need two tables. The first table will be the weight identifier table. The second table is, in your case, the colors. To get this working, you need to normalize the values so they all add up to 1. Then, you have a random number from 0 to 1. The random number determines which color will be selected.

Yep the code works fine as given.

For the weighted part, I would start with a dictionary stating the colors and their weights as so:

local weights = {"Bright Red" = 1, "Black" = 5, "Lily White" = 1} -- go on for all the weights you want.
local truetable = {}

for color,v in pairs(weights) do
       for i = 1, v do
           table.insert(truetable, color)
       end
end

local random = math.random(1, #truetable)

local yourcolor = truetable[random]

This creates a table called truetable which has colors in it equal to the chance of obtaining it. Your color picks a color from true table and makes it more likely for a certain color to be selected based on its weight. There are other ways to do this but I feel this is the easiest way to understand. Let me know if you have any questions and mark this solution if it works.

Edit: I forgot to mention but since brickcolors can have spaces make sure to add quotes when putting colors into the weights table.

This is the code so far and there seems to be an error that says this

error: Workspace.Toyota_RAV4.Body_Color.RandomPainter2:16: invalid ‘for’ limit (number expected, got table)

--local RN = BrickColor.random()

--script.Colors.Value = RN
local Colortable = { {"Really Black",15}, 
{"Black",10}, 
{"Bright red",6}, 
{"Lily white",2}, 
{"Institutional white",7}, 
{"Bright green",23}, 
{"Deep blue",4}, 
{"Pine Cone",0}, 
}
local truetable = {}

for ColorPairs,v in pairs(Colortable) do
	for ColorPairs = 1, v do--The error is here
		table.insert(truetable, ColorPairs)
	end
end

PaintObject = script.Parent
PainterPart = "1"
--Randomize = math.random(1,#Colortable)
local Randomize = math.random(1, #truetable)
local yourcolor = truetable[Randomize]

for index, child in pairs(PaintObject:GetDescendants()) do
	if child:IsA("BasePart") and child.Name == PainterPart then
	child.BrickColor = BrickColor.new((Colortable[Randomize])[1])
else end	
end

print((Colortable[Randomize])[1])

That is because you are using a dictionary. Let me explain.

There are two types of tables arrays and dictionaries.

An array:

local array = {"bob", "something", "somethingelse"}

Here there are 3 items in this array and you can get the item by the order it exists. So item 1 would be bob, item 2 would be something. Etc. The index is a number corresponding to the order in which its in.

Dictionary:

local dictionary = {"Red" = 5, "Blue" = 6}

Here, the indexes are Red and Blue, and the corresponding values are 5 and 6. Because its a dictionary, you can’t use numbers to find a specific item. Instead you will have to use the index in this case being Red or Blue.

Your table is an array which has multiple tables as its values. To fix this, change it into a dictionary like this.

Ex:

What you have:

local Colortable = ({"Black", 10}, {"Bright Red"}, 6}

What it should be:

local Colortable = {"Black" = 10, "Bright red" = 6}

My code uses the index of the dictionary (the color) as the value to insert into the true table. An using an array would make it not work as intended. On a further note, you can use dictionaries to avoid doing tables inside tables like you did here however there are some cases when you should use tables inside tables which I’m sure you will encounter eventually.

Hope this helped you! :smile:

Note:
For this line:

child.BrickColor = BrickColor.new((Colortable[Randomize])[1])

change it to

child.BrickColor = BrickColor.new(yourcolor)

and also change

for ColorPairs,v in pairs(Colortable) do
	for ColorPairs = 1, v do--The error is here
		table.insert(truetable, ColorPairs)
	end
end

to this

for ColorPairs,v in pairs(Colortable) do
	for i = 1, v do--The error is here
		table.insert(truetable, ColorPairs)
	end
end

It works great as it should work thanks :slight_smile:

here’s a screenshot of the script working:
RobloxScreenShot20230116_162613881

Glad I could help I hope my explanations made sense.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.