Move "steal item" logic to DropProvider

This commit is contained in:
P0nk
2023-03-15 22:22:14 +01:00
parent 6bf8785f22
commit 703ae30a27
11 changed files with 94 additions and 26 deletions

View File

@@ -2,10 +2,12 @@ package database.drop;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import server.ItemInformationProvider;
import server.life.MonsterDropEntry;
import server.life.MonsterGlobalDropEntry;
import java.util.List;
import java.util.Optional;
public class DropProvider {
private final DropDao dropDao;
@@ -19,8 +21,12 @@ public class DropProvider {
this.dropDao = dropDao;
}
private List<MonsterDrop> getMonsterDrops(int monsterId) {
return monsterDropCache.get(monsterId, dropDao::getMonsterDrops);
}
public List<MonsterDropEntry> getMonsterDropEntries(int monsterId) {
return monsterDropCache.get(monsterId, dropDao::getMonsterDrops).stream()
return getMonsterDrops(monsterId).stream()
.map(this::mapToDropEntry)
.toList();
}
@@ -52,4 +58,37 @@ public class DropProvider {
return new MonsterGlobalDropEntry(globalDrop.itemId(), globalDrop.chance(), globalDrop.continent(),
globalDrop.minQuantity(), globalDrop.maxQuantity(), questId);
}
/**
* The chance of an item to be stolen is calculated like this: (item chance) / (sum of all item chances)
* It works just like "lottery scheduling", but with droppable items instead of OS processes.
*/
public Optional<MonsterDropEntry> getRandomStealDrop(int monsterId) {
List<MonsterDrop> relevantDrops = getMonsterDrops(monsterId).stream()
.filter(this::isNonQuestItem)
.toList();
if (relevantDrops.isEmpty()) {
return Optional.empty();
}
final long totalChance = relevantDrops.stream()
.mapToLong(MonsterDrop::chance)
.sum();
final long winningTicket = (long) Math.floor(Math.random() * totalChance);
long remainingChance = totalChance;
for (MonsterDrop drop : relevantDrops) {
remainingChance -= drop.chance();
if (winningTicket >= remainingChance) {
return Optional.of(mapToDropEntry(drop));
}
}
return Optional.empty();
}
private boolean isNonQuestItem(MonsterDrop drop) {
ItemInformationProvider ii = ItemInformationProvider.getInstance();
return !ii.isQuestItem(drop.itemId()) && !ii.isPartyQuestItem(drop.itemId());
}
}