Problem with table chances randomizer

  1. What do you want to achieve? Keep it simple and clear!
    I’m working on ore cluster which have different types and they have a chances, right now i have a code which works quite fine for randomizing, but if chance for few materials are same (100%) it will choose randomly between them, not highest, so if all of them have 100%, it chooses Prelast one instead of last one. That’s all.
  2. What is the issue? Include screenshots / videos if possible!
    1st
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub? Some kind man helped me with that script on different game, where it needed to get all chances, but exactly in this i need highest one

Code:

local PlayerManager = require(game:GetService("ServerScriptService").PlayerManager)
local SettingsUI = Cluster.Settings
local Regenerating = false
local swingsTable = {
	["Stone Rock"] = 15,
	["Coal Rock"] = 50,
	["Iron Rock"] = 150,
	["Diamond Rock"] = 500,
	["Platinum Rock"] = 1500,
	["Space Rock"] = 4000,
	["Callium Rock"] = 6000,
	["Galactic Rock"] = 10000,
	["Stellarite Rock"] = 125000,
	["Desatalite Rock"] = 175000,
	["Singularium Rock"] = 250000
}
local chancesTable = {
	["Singularium Rock"] = 0.00039125,
	["Desatalite Rock"] = 0.0007825,
	["Stellarite Rock"] = 0.001565,
	["Galactic Rock"] = 0.003125,
	["Callium Rock"] = 0.00625,
	["Space Rock"] = 0.0125,
	["Platinum Rock"] = 0.025,
	["Diamond Rock"] = 0.05,
	["Iron Rock"] = 0.25,
	["Coal Rock"]  = 0.25,
	["Stone Rock"] = 0.50038625

}
local productionTable = {
	["Stone Rock"] = 50,
	["Coal Rock"] = 250,
	["Iron Rock"] = 1500,
	["Diamond Rock"] = 2500,
	["Platinum Rock"] = 5000,
	["Space Rock"] = 15000,
	["Callium Rock"] = 25000,
	["Galactic Rock"] = 50000,
	["Stellarite Rock"] = 75000,
	["Desatalite Rock"] = 100000,
	["Singularium Rock"] = 1000000
}

local tierTable = {
	["Stone Rock"] = 123456789 .. "ten".. "eleven",
	["Coal Rock"] = 123456789 .. "ten".. "eleven",
	["Iron Rock"] = 2345678 .. "ten".. "eleven",
	["Diamond Rock"] = 345678 .. "ten".. "eleven",
	["Platinum Rock"] = 45678 .. "ten".. "eleven",
	["Space Rock"] = 5678 .. "ten".. "eleven",
	["Callium Rock"] = 78 .. "ten".. "eleven",
	["Galactic Rock"] = 8 .. "ten".. "eleven",
	["Stellarite Rock"] = 9,
	["Desatalite Rock"] = "ten",
	["Singularium Rock"] = "eleven"
}

local function chooseMaterial() -- randomizer
	local Boost = script.Parent.Parent.Parent.ServerLuck:GetAttribute("Boost")
	for matName, odds in pairs(chancesTable) do
		if math.random() < odds * Boost then
			Cluster:SetAttribute("Material", matName)
		end
	end
end
--end of randomizer
local function Regenerate()
	Regenerating = true
	local RegenerateTimer = 10
	while RegenerateTimer > 0 do
		SettingsUI.Frame.OreName.TextLabel.Text = "REGENERATING CLUSTER: "..RegenerateTimer.."s"
		RegenerateTimer -= 1
		wait(1)
	end
	if RegenerateTimer == 0 then
		chooseMaterial()
		--[[local tweenInfo1 = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0)
		local Goal1 = {Size = Vector3.new(6.3, 3.15, 6.3)}
		local tweenInfo3 = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0)
		local Goal3 = {Size = Vector3.new(3.5, 6.5, 6.4)}
		local Tween1 = TweenService:Create(Rock, tweenInfo1, Goal1)
		local Tween3 = TweenService:Create(Rock.Parent.Union, tweenInfo3, Goal3)
		Tween1:Play()
		Tween3:Play()--]]
		wait(1)
		local Material = Cluster:GetAttribute("Material")
		local swingsAmount = swingsTable[Material]
		Cluster:SetAttribute("SwingsLeft", swingsAmount)
		SettingsUI.Frame.HealthFrame.Frame.Frame:TweenSize(UDim2.new(0.98,0,1,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 1, true)	
		SettingsUI.Frame.OreName.TextLabel.Text = Material..""..Cluster:GetAttribute("SwingsLeft").."/"..swingsAmount..")"
		if Cluster:GetAttribute("Material") ~= "Stone Rock" then
		Cluster[Material].Transparency = 0
		Cluster[Material].CanCollide = true
			end
		RegenerateTimer = 240
		Regenerating = false
	end
end

local function onTouch(otherPart)
	local tool = otherPart.Parent
	if tool:IsA('Tool') and string.find(tool.Name, "Pick") and tool.Mining.Value == true and Regenerating == false then
		local Material = Cluster:GetAttribute("Material")
		if string.find(tierTable[Material], tool:GetAttribute("Tier")) then
			local SwingsLeft = Cluster:GetAttribute("SwingsLeft")
			if SwingsLeft > 0 then
				local Damage = otherPart.Parent:GetAttribute("Damage")
				Cluster:SetAttribute("SwingsLeft", SwingsLeft - Damage)
				tool.Mining.Value = false
				local swingsAmount = swingsTable[Material]
				SettingsUI.Frame.OreName.TextLabel.Text = Material..""..SwingsLeft.."/"..swingsAmount..")"
				SettingsUI.Frame.HealthFrame.Frame.Frame:TweenSize(UDim2.new(SwingsLeft/swingsAmount,0,1,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 1, true)
				local pName = otherPart.Parent.Parent.Name
				local player = game:GetService("Players"):FindFirstChild(pName)
				PlayerManager.SetMoney(player, PlayerManager.GetMoney(player) + productionTable[Material] * Damage/10)
			elseif SwingsLeft <= 0 then
				if Cluster:GetAttribute("Material") ~= "Stone Rock" then
				Cluster[Material].Transparency = 1
					Cluster[Material].CanCollide = false
					end
				SettingsUI.Frame.HealthFrame.Frame.Frame:TweenSize(UDim2.new(0,0,1,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 1, true)
				Regenerate()
			end
		end
	end
end
Cluster.Touched:Connect(onTouch)
for _,material in pairs(Cluster:GetChildren()) do
	if material:IsA("UnionOperation") and string.find(material.Name, "Rock") then
		material.Touched:Connect(onTouch)
	end
end
Regenerate()

Bumping this topic, in case no answers

Bump 2 Still can’t understand what is problem (30 letterssssssssssssssssssssssssssssss)

Bump 3, because no answers (30 lettersssssss)

Quick question. Is Singularium a 0.001% chance, or a 0.1% chance?

Sorry it is an old script, i updated it today, let me paste new one, but yes it was a 0.1%

Da new code

local PlayerManager = require(game:GetService("ServerScriptService").PlayerManager)
local SettingsUI = Cluster.Settings
local Regenerating = false
local swingsTable = {
	["Stone Rock"] = 15,
	["Coal Rock"] = 50,
	["Iron Rock"] = 150,
	["Diamond Rock"] = 500,
	["Platinum Rock"] = 1500,
	["Space Rock"] = 4000,
	["Callium Rock"] = 6000,
	["Galactic Rock"] = 10000,
	["Stellarite Rock"] = 125000,
	["Desatalite Rock"] = 175000,
	["Singularium Rock"] = 250000
}
local chancesTable = {
	["Singularium Rock"] = 0.00039125,
	["Desatalite Rock"] = 0.0007825,
	["Stellarite Rock"] = 0.001565,
	["Galactic Rock"] = 0.003125,
	["Callium Rock"] = 0.00625,
	["Space Rock"] = 0.0125,
	["Platinum Rock"] = 0.025,
	["Diamond Rock"] = 0.05,
	["Iron Rock"] = 0.25,
	["Coal Rock"]  = 0.25,
	["Stone Rock"] = 0.50038625

}
local productionTable = {
	["Stone Rock"] = 50,
	["Coal Rock"] = 250,
	["Iron Rock"] = 1500,
	["Diamond Rock"] = 2500,
	["Platinum Rock"] = 5000,
	["Space Rock"] = 15000,
	["Callium Rock"] = 25000,
	["Galactic Rock"] = 50000,
	["Stellarite Rock"] = 75000,
	["Desatalite Rock"] = 100000,
	["Singularium Rock"] = 1000000
}

local tierTable = {
	["Stone Rock"] = 123456789 .. "ten".. "eleven",
	["Coal Rock"] = 123456789 .. "ten".. "eleven",
	["Iron Rock"] = 2345678 .. "ten".. "eleven",
	["Diamond Rock"] = 345678 .. "ten".. "eleven",
	["Platinum Rock"] = 45678 .. "ten".. "eleven",
	["Space Rock"] = 5678 .. "ten".. "eleven",
	["Callium Rock"] = 78 .. "ten".. "eleven",
	["Galactic Rock"] = 8 .. "ten".. "eleven",
	["Stellarite Rock"] = 9,
	["Desatalite Rock"] = "ten",
	["Singularium Rock"] = "eleven"
}

local function chooseMaterial()
	local Boost = script.Parent.Parent.Parent.ServerLuck:GetAttribute("Boost")
	for matName, odds in pairs(chancesTable) do
		if math.random() < odds * Boost then
			Cluster:SetAttribute("Material", matName)
		end
	end
end

local function Regenerate()
	Regenerating = true
	local RegenerateTimer = 10
	while RegenerateTimer > 0 do
		SettingsUI.Frame.OreName.TextLabel.Text = "REGENERATING CLUSTER: "..RegenerateTimer.."s"
		RegenerateTimer -= 1
		wait(1)
	end
	if RegenerateTimer == 0 then
		chooseMaterial()
		--[[local tweenInfo1 = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0)
		local Goal1 = {Size = Vector3.new(6.3, 3.15, 6.3)}
		local tweenInfo3 = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0)
		local Goal3 = {Size = Vector3.new(3.5, 6.5, 6.4)}
		local Tween1 = TweenService:Create(Rock, tweenInfo1, Goal1)
		local Tween3 = TweenService:Create(Rock.Parent.Union, tweenInfo3, Goal3)
		Tween1:Play()
		Tween3:Play()--]]
		wait(1)
		local Material = Cluster:GetAttribute("Material")
		local swingsAmount = swingsTable[Material]
		Cluster:SetAttribute("SwingsLeft", swingsAmount)
		SettingsUI.Frame.HealthFrame.Frame.Frame:TweenSize(UDim2.new(0.98,0,1,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 1, true)	
		SettingsUI.Frame.OreName.TextLabel.Text = Material..""..Cluster:GetAttribute("SwingsLeft").."/"..swingsAmount..")"
		if Cluster:GetAttribute("Material") ~= "Stone Rock" then
		Cluster[Material].Transparency = 0
		Cluster[Material].CanCollide = true
			end
		RegenerateTimer = 240
		Regenerating = false
	end
end

local function onTouch(otherPart)
	local tool = otherPart.Parent
	if tool:IsA('Tool') and string.find(tool.Name, "Pick") and tool.Mining.Value == true and Regenerating == false then
		local Material = Cluster:GetAttribute("Material")
		if string.find(tierTable[Material], tool:GetAttribute("Tier")) then
			local SwingsLeft = Cluster:GetAttribute("SwingsLeft")
			if SwingsLeft > 0 then
				local Damage = otherPart.Parent:GetAttribute("Damage")
				Cluster:SetAttribute("SwingsLeft", SwingsLeft - Damage)
				tool.Mining.Value = false
				local swingsAmount = swingsTable[Material]
				SettingsUI.Frame.OreName.TextLabel.Text = Material..""..SwingsLeft.."/"..swingsAmount..")"
				SettingsUI.Frame.HealthFrame.Frame.Frame:TweenSize(UDim2.new(SwingsLeft/swingsAmount,0,1,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 1, true)
				local pName = otherPart.Parent.Parent.Name
				local player = game:GetService("Players"):FindFirstChild(pName)
				PlayerManager.SetMoney(player, PlayerManager.GetMoney(player) + productionTable[Material] * Damage/10)
			elseif SwingsLeft <= 0 then
				if Cluster:GetAttribute("Material") ~= "Stone Rock" then
				Cluster[Material].Transparency = 1
					Cluster[Material].CanCollide = false
					end
				SettingsUI.Frame.HealthFrame.Frame.Frame:TweenSize(UDim2.new(0,0,1,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 1, true)
				Regenerate()
			end
		end
	end
end
Cluster.Touched:Connect(onTouch)
for _,material in pairs(Cluster:GetChildren()) do
	if material:IsA("UnionOperation") and string.find(material.Name, "Rock") then
		material.Touched:Connect(onTouch)
	end
end
Regenerate()

Bumping topic again (30 lettersssssssss)

Sorry, I’m struggling to create a working script. I’m very bad with with math and probability. I imagine a line cut into different segments, where the line size is 1, and the segements size is the chance of each ore. And then a random number between 0 and 1 would be plotted, on the number line, and which ever segment it hits is the ore you obtained. I’ll try to create a working script in the meantime.

Okay thank you a lot (30 letterssssssssssss)

I tested this, it seems fine.

local chanceTable = {
    Plutonium = 0.5,
    Diamond = 0.1,
    Coal = 0.35,
    Stone = 0.35,
}

local function GetOreObtained()
    local segments = {}
    local total = 0
    for i, v in pairs(chanceTable) do 
        table.insert(segments, {total, total + v, i})
        total += v
    end
    local depth = 1000 -- more depth allows for more preciseness for chance, but takes longer to compute
    -- 1000 depth allows for chances like: 0.0001.
    local x = math.random(0,depth) / depth
    for _, seg in pairs(segments) do
        if seg[1] <= x and x <= seg[2] then
            return seg[3]
        end
    end
    return "Stone"
end

If the values in chanceTable add up to 1, everything should work. If they go over 1, some chances might change unexpectedly. If they go under 1, the chance of Stone increases. You can replace chanceTable with your chancesTable to make it work with your script.

Alright ty let me try it, btw where you return “Stone” in last stroke? Just because i want to change attribute with that value, should i add like

...GetOreObtained(material)

and then set attribute in regenerate script?

“Stone” is just the default ore incase an error happens.

You mean a nil error which says about nil value? Because it was appearing a lot times in my script, which was breaking whole cluster script .

Sure. If it can’t calculate chance, the ore is nil, so it returns Stone by default.

Lol you fixed two of my errors i had, one about highest chance second about nil thing, thank you. And btw now how i should i set thing from this table to attribute

I changed the default to “Unknown”, and printed the result of the function 10 times. It never printed unknown, it just printed random ores respective of their chance of being obtained.

What do you mean by this? The function returns an ore’s name.

But function have no args in it…? or i’m dumb, just don’t understand where and what it returns

EDIT: Ohh i’m dumb i could use

Cluster:SetAttribute("Material", GetOreObtained())

am i right?

EDIT: Well seems that thing works, let me quick add server luck multiplier to it