- Home /
Weighted loot decision from a pre selected pool
Hey guys. I am doing a xml based loot table system for my framework im making . I am trying to do weighted loot drops using these tables.
I basically have a list of items correctly loading and spawning in the crates except i beleive i am not doing truly weighted loot. Each item has a % chance between 0 and 100 which transtaltes to a max loot weight selectable by the user. Assume the max weight is 10,000 for now. so weight 0 = 0% and 10000 = 100%.
//Get references to random items
foreach (int item in lootBucket)
{
LootItem rollItem = selectedTable.GetItem(item);
int finalWeight = GetRandomWeight(3);
Debug.Log("Rolling for " + rollItem.itemId + ", item weight = " + rollItem.weight + ", roll = " + finalWeight);
if (finalWeight < rollItem.weight - weightOffset)
{
finalLoot.Add(rollItem);
numberLeft--;
}
}
This works out whether or not the random Weight is less than the weight of that of the object. if it is it gets spawned. But i am under the assumption that truly weighted loot uses the sum of all weights in the list of loot. How would this be applied to my method?
I'm thinking a weight range? for example Object A = 1-3, Object B = 4-7, etc. Otherwise you'll end up with multiple drops OR never getting certain drops. At that point you can't really check for lower-than, but the actual range containing the rolled number.
So say 4 items A B C D... A has a weight of 4000 (40%) B with 2000 (20%) C 7500 (75%) and D 50 (0.5%) The way it works is it goes through a list it would say
A -> Generate Random Weight between 0 and 10 000 -> Less than A weight -> Drop else dont
It would continue on for the list. If i did it like this
A = 0 - 4000 B = 0 - 2000 which brings me to my question. Ive seen people do this but the loot is in order from rarest to most common. Would i have to re arrange my list of loot to be in order of rarity? Or do i do it like total weight = A weight + b weight + C weight + D and then get my ranges?
Then A -> Drops when 0 - 4000 is called B drops when 4001 - 6000 is called C drops when 6001 - 13500 and D will drop if 13501 - 13550?
Im guessing the example above is where the sum of weights comes in?
Answer by Jamoy1993 · May 21, 2017 at 01:05 AM
Adding to my reply from RobAnthem this is what i have got
//Caclulates the weights by iterating through the list, adding each weight to the end range of the previous + 1. public void CalculateWeights() { if(items.Count > 0) { totalProbability = 0; bool start = true; LootItem previous = items[0];
for (int x = 0; x < items.Count; x++)
{
LootItem current = items[x];
if (start)
{
//First item
start = false;
current.weightRange = new Vector2(0, current.weight);
}
else
{
current.weightRange = new Vector2(previous.weightRange.y + 1, previous.weightRange.y + current.weight);
}
totalProbability += current.weight;
previous = current;
}
}
}
//Actual selection algorithm, checks if the current item is within range and selects it based on the weight ranges set in the above function. Rater than choosing from the table of items, it uses the table as a whole and selects from that using the random weight between the total value of the table...
List<LootItem> finalLoot = new List<LootItem>();
if(selectedTable != null)
{
//Get references to random items
while (numberToSpawn > 0)
{
int weight = GetRandomWeightInRange(3, 0, selectedTable.totalProbability);
foreach (LootItem item in selectedTable.items)
{
if(CheckWeight(weight, item.weightRange))
{
//We have spawned an item
finalLoot.Add(item);
numberToSpawn--;
break;
}
}
}
}
return finalLoot;