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;
|
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