Loot Table Function

Hi. I made a loot table function that uses weights. It works fine but I am just wondering if this is very inefficient or not.

local spawns = {
	gun1 = {
		weight = 5;
	},
	gun2 = {
		weight = 1;
	}
}

function choose()
	local tbl = {}
	for k,v in pairs(spawns) do
		for x=1, v.weight do
			table.insert(tbl, k)
		end
	end
	return tbl[math.random(1, #tbl)]
end

print(choose())

The table could be changed. Just make it

gun1 = 5
gun2 = 1

Instead of making a new table.

It’s pretty inefficient, since a weight of 1000 would translate to 1000 table assignment calls; while not costly within itself, it can be; it’s inefficient.

We can fix that though, we can modify your current choose function’s logic to look like this:

function choose()
	local sumOfWeights = 0
	
	for _, entry in pairs(spawns) do
		sumOfWeights = sumOfWeights + entry.weight
	end
	
	local randomValue = math.random(0, sumOfWeights)
	
	for key, entry in pairs(spawns) do
		if randomValue <= entry.weight then
			return key
		else
			randomValue = randomValue - entry.weight
		end
	end
end

This would be more efficient, although I still don’t advise it. Here’s the current issues I see still:

  1. It’s prone to typos. If you have a large loot table and misspell “weight”, good luck finding that bug easily. You should focus on a paradigm like functional programming or OOP where errors are more concise.

  2. It’s not extendable at all. This works for one loot table in one case. This isn’t really ever advised in any scope of a project.

With these issues in mind, check here to see an example minimal implementation of loot tables.

1 Like