Weighted powerup systems

Hey I need to create some sort of weighted powerup system for Dogfight. Basically I need a way of having it so the good powerups are rarer than the slightly less useful ones. Does anyone have a good system for this? The only way I can think of is creating duplicate entries in the powerups table but this is hardly ideal and doesn’t really work. Anyone got a way I can just set a value so 50% of the time you get this powerup and 10% of the time you get this one?

[lua]
function RegisterPowerup(tab, class)
print(“REGISTERING”,class)
table.insert(DF_POWERUPS, {TABLE=tab,CLASS=class})
end
[/lua]

That is my powerup register function tab being the ENT tab in the scripted entity and class being its class name.

I don’t know if this is the best way to do this, but this seems to work well:

[lua]local PowerUps = {
{ “Banana”, 1 },
{ “Apple”, 3 },
{ “Orange”, 6 }
}
local Max = 10

function GetRandomPowerup()
local val = math.random( 0, Max )
local offset = 0

for _, powerup in pairs( PowerUps ) do
	if ( val >= offset and val < offset + powerup[2] ) then
		return powerup[1]
	end
	
	offset = offset + powerup[2]
end

end[/lua]

Results when testing 1000 items:


10% bananas, 23.8% apples and 57.7% oranges
9.9% bananas, 26.6% apples and 55% oranges
11.2% bananas, 29.1% apples and 48.4% oranges
8.7% bananas, 28.2% apples and 53.8% oranges
10% bananas, 26.9% apples and 55% oranges
7.7% bananas, 26.7% apples and 56.9% oranges

Yer I was thinking something like that, better than my old idea of just duplicating entires. Going to try and do something but with more automation, so you just put ENT.Weight = 20 and it calculates the offset etc for you as it registers each powerup.

If anyone is interested:

[lua]

DF_POWERUPS = {}
DF_POWERUPS_WEIGHT_TOTAL = 0

function RegisterPowerup(tab, class)
print(“REGISTERING”,class)
table.insert(DF_POWERUPS, {TABLE=tab,CLASS=class})
end

function CalculateWeights()
for k,v in pairs(DF_POWERUPS) do
v.TABLE.MinSelect = DF_POWERUPS_WEIGHT_TOTAL
DF_POWERUPS_WEIGHT_TOTAL = DF_POWERUPS_WEIGHT_TOTAL + v.TABLE.PowerupWeight
v.TABLE.MaxSelect = DF_POWERUPS_WEIGHT_TOTAL
end
for k,v in pairs(DF_POWERUPS) do
local frc = (v.TABLE.MaxSelect - v.TABLE.MinSelect) / DF_POWERUPS_WEIGHT_TOTAL
print(“CHANCE FOR”, v.CLASS, math.floor(frc * 100)…"%")
end
end

hook.Add(“Initialize”, “Powerupinit”, CalculateWeights)

//returns the table of a random powerup
function GetRandomPowerup()
local target = math.random(1,DF_POWERUPS_WEIGHT_TOTAL)
for _,pwp in pairs(DF_POWERUPS) do
if pwp.TABLE.MinSelect < target and pwp.TABLE.MaxSelect >= target then
return pwp
end
end
end
[/lua]

the TABLE part of the powerup contains the whole of the ENT table. ENT.PowerupWeight is how often it will come up (1 being rare).