feat: add lootContextFor and smeltedForm to Loot
This commit is contained in:
1 parent
ff147c2440
commit
35644f9771
1 file changed
+111
@@ -314,3 +314,114 @@ int LootRoll::totalCount() const {
|
||||
return total;
|
||||
}
|
||||
|
||||
LootContext lootContextFor(const HurtSource& source, ItemId tool, const EnchantSet& toolEnchants,
|
||||
uint32_t seed) {
|
||||
LootContext context;
|
||||
context.seed = seed != 0 ? seed : 0x9e3779b9u;
|
||||
context.killedBy = source.type;
|
||||
context.fiery = source.fiery || isFireDamage(source.type);
|
||||
context.playerKill = source.byPlayer;
|
||||
context.tool = tool;
|
||||
context.toolEnchants = toolEnchants;
|
||||
return context;
|
||||
}
|
||||
|
||||
ItemId smeltedForm(ItemId raw) {
|
||||
switch (raw) {
|
||||
case ItemId::RawPorkchop: return ItemId::CookedPorkchop;
|
||||
case ItemId::RawBeef: return ItemId::CookedBeef;
|
||||
case ItemId::RawMutton: return ItemId::CookedMutton;
|
||||
case ItemId::IronOre: return ItemId::IronIngot;
|
||||
case ItemId::GoldOre: return ItemId::GoldIngot;
|
||||
default: return raw;
|
||||
}
|
||||
}
|
||||
|
||||
bool toolQualifiesFor(Block block, ItemId tool) {
|
||||
if (correctToolFor(block) != ToolType::Pickaxe) return true;
|
||||
|
||||
const ItemInfo& info = itemInfo(tool);
|
||||
if (info.toolType != ToolType::Pickaxe) return false;
|
||||
switch (block) {
|
||||
case Block::DiamondOre:
|
||||
case Block::EmeraldOre:
|
||||
case Block::GoldOre:
|
||||
return info.toolTier == ToolTier::Iron || info.toolTier == ToolTier::Diamond;
|
||||
case Block::IronOre:
|
||||
case Block::LapisOre:
|
||||
case Block::RedstoneOre:
|
||||
return info.toolTier != ToolTier::Wood && info.toolTier != ToolTier::Gold;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const LootTable& blockLootTable(Block block) {
|
||||
static const std::vector<LootTable> tables = buildBlockTables();
|
||||
if (block >= Block::Count) return emptyTable();
|
||||
return tables[static_cast<std::size_t>(block)];
|
||||
}
|
||||
|
||||
const LootTable& mobLootTable(LootTable::MobKind kind) {
|
||||
static const std::vector<LootTable> tables = {
|
||||
zombieTable(),
|
||||
skeletonTable(),
|
||||
creeperTable(),
|
||||
meatTable(ItemId::RawMutton, 1, 2),
|
||||
meatTable(ItemId::RawBeef, 1, 3),
|
||||
meatTable(ItemId::RawPorkchop, 1, 3),
|
||||
};
|
||||
if (kind >= LootTable::MobKind::Count) return emptyTable();
|
||||
return tables[static_cast<std::size_t>(kind)];
|
||||
}
|
||||
|
||||
const LootTable& chestLootTable(LootTable::ChestKind kind) {
|
||||
static const std::vector<LootTable> tables = {
|
||||
dungeonChestTable(),
|
||||
villageChestTable(),
|
||||
templeChestTable(),
|
||||
};
|
||||
if (kind >= LootTable::ChestKind::Count) return emptyTable();
|
||||
return tables[static_cast<std::size_t>(kind)];
|
||||
}
|
||||
|
||||
LootRoll rollLootTable(const LootTable& table, const LootContext& context) {
|
||||
LootRoll roll;
|
||||
uint32_t rng = context.seed != 0 ? context.seed : 0x9e3779b9u;
|
||||
|
||||
for (const LootPool& pool : table.pools) {
|
||||
int rolls = rollBetween(rng, pool.minRolls, pool.maxRolls);
|
||||
rolls += pool.bonusRollsPerLooting * context.looting();
|
||||
for (int r = 0; r < rolls; ++r) {
|
||||
int totalWeight = 0;
|
||||
for (const LootEntry& entry : pool.entries) {
|
||||
if (conditionsPass(entry, context)) totalWeight += entry.weight;
|
||||
}
|
||||
if (totalWeight <= 0) continue;
|
||||
int pick = rollBelow(rng, totalWeight);
|
||||
for (const LootEntry& entry : pool.entries) {
|
||||
if (!conditionsPass(entry, context)) continue;
|
||||
pick -= entry.weight;
|
||||
if (pick >= 0) continue;
|
||||
emitEntry(roll, entry, context, rng);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return roll;
|
||||
}
|
||||
|
||||
LootRoll rollBlockDrops(Block block, const LootContext& context) {
|
||||
if (!toolQualifiesFor(block, context.tool)) return {};
|
||||
return rollLootTable(blockLootTable(block), context);
|
||||
}
|
||||
|
||||
LootRoll rollMobDrops(LootTable::MobKind kind, const LootContext& context) {
|
||||
return rollLootTable(mobLootTable(kind), context);
|
||||
}
|
||||
|
||||
LootRoll rollChestContents(LootTable::ChestKind kind, const LootContext& context) {
|
||||
return rollLootTable(chestLootTable(kind), context);
|
||||
}
|
||||
|
||||
} // namespace vf
|
||||
Reference in new issue
Block a user