The problem with random drops, is that those are random! :).
You could get too much misses in a row, or you could be very very lucky. In my game I use an approach that allows both to keep some randomness, and also to avoid to avoid player frustration.
You need 3 columns in your table monster_drop_rates
drop_ID | find_rate | entropy
Basically each enemy will have configured a couple of possible drops.
enemy_ID | drop_ID1 | drop_ID2 | drop_ID3
Note that each drop have its own entropy (the concept of entropy is the same we see in PathOfExile)
however notes that I improve a bit the PoE concept:
foreach(var drop in enemy.drops)
{
drop.entroy += drop.find_rate*Random(0.75f,1.25f);
}
enemy.drops.SortByEntropy();
var first_drop = enemy.drops.GetFirst();
while(first_drop.entropy>100){
first_drop.entropy -=100;
SpawnDrop(first_drop.drop_ID);
enemy.drops.SortByEntropy();
first_drop = enemy.drops.GetFirst();
}
Basically for each possible drop of a enemy we add a slightly randomized chance, when we get over 100 treshold, we spawn that drop, note that we do that in a loop, so that in example we could spawn multiple items if we set a spawn chance greater than 100 (similiar to what happens in Diablo III).
The content of a drop is randomized too.
What is entropy?
It is just a way to get around very lucky or very unlucky rolls.
In example if you have a item that drops 90% of times, You could still have a 1/1000 chance that item won't be spawned 3 times in a row.
In my system, the % of success is fixed and slightly randomized between 0.75 and 1.25
So actually 90% of success means your success is randomized between
90*0.75 and 90*1.25 = 67,5 and 112,5%
That success rate is added directly to entropy
- Assume you have entropy starting at 13.
- You first roll makes the worst possible outcome 90% dropping chance 90*0.75 = 67,5%
- You add to entropy so 13 + 67,5 = 80,5 (less than 100 => no drop)
- Regardless of what you next roll is you will be sure you will spawn the item (because 80,5+65,5 > 100)
- So if you actually make again a worst roll, you have 80,5+65,5 => greater than 100.
Basically with this system you are sure that items are spawned randomly but without too much misses in a row.
Actually this system will never miss more than twice in a row (and it miss twice only 1 out of 1000 cases, when dropping chance is 90%), and will actually spawn 2 items sometimes, but in average it will spawn items equals to 90% of killed enemies. So it is likely on 10 killed enemies:
- 2 enemies don't spawn drop
- 1 enemy spawn twice the drop
Note that actually it is impossible that an item spawn twice if its drop_rate is <=
than 80%.
Alternative approach
Just set a countdown counter for each drop, but you have to use a "out_of" column instead of a "drop_ratio":
I.E:
drop_ID | out_of | counter
So if you have that drop once out of 100 cases, you just randomize it by a +/- 5%
You just subtract 1, when counter reaches 0, you randomize it again.
if( --drop.counter <=0)
{
DropItem( drop.drop_ID);
drop.counter = drop.out_of*Random(0.95,1.05),
}
While this approach is simpler, that does not allow to handle spanw chances greater than 100%.