feat: add toolHarvestLevel and toolAllows to LootTables

This commit is contained in:
dualfroz committed 2026-09-08 17:21:18 +02:00
1 parent 85d4de6d70
commit fdebb884e6
1 file changed
+159
+159
View File
@@ -471,3 +471,162 @@ std::vector<ChestFill> buildChestFills() {
chestEntry(ItemId::GoldSword, 5, 1, 1), chestEntry(ItemId::GoldSword, 5, 1, 1),
chestEntry(ItemId::DiamondGem, 2, 1, 3)})); chestEntry(ItemId::DiamondGem, 2, 1, 3)}));
fills.push_back(chestFillOf(Structure::EndShip, "endShip", 2, 3, 1, 1,
{chestEntry(ItemId::DiamondGem, 5, 1, 3),
chestEntry(ItemId::EmeraldGem, 5, 1, 3),
chestEntry(ItemId::GoldIngot, 5, 1, 6),
chestEntry(ItemId::IronIngot, 5, 1, 6),
chestEntry(ItemId::DiamondSword, 2, 1, 1),
chestEntry(ItemId::DiamondPickaxe, 2, 1, 1)}));
return fills;
}
std::vector<LootTable> buildFishingTables() {
std::vector<LootTable> tables;
LootPool fish;
fish.entries = {chestEntry(ItemId::RawPorkchop, 34, 1, 1), chestEntry(ItemId::RawBeef, 33, 1, 1),
chestEntry(ItemId::RawMutton, 33, 1, 1)};
LootPool treasure;
treasure.entries = {chestEntry(ItemId::GoldIngot, 25, 1, 1),
chestEntry(ItemId::LapisLazuli, 25, 1, 3),
chestEntry(ItemId::EmeraldGem, 20, 1, 1),
chestEntry(ItemId::IronIngot, 20, 1, 2),
chestEntry(ItemId::DiamondGem, 10, 1, 1)};
LootPool junk;
junk.entries = {chestEntry(ItemId::Stick, 30, 1, 2), chestEntry(ItemId::RottenFlesh, 25, 1, 1),
chestEntry(ItemId::Gravel, 20, 1, 1), chestEntry(ItemId::Leaves, 15, 1, 1),
chestEntry(ItemId::WoodHoe, 10, 1, 1)};
for (const LootPool& pool : {fish, treasure, junk}) {
LootTable table;
table.pools.push_back(pool);
tables.push_back(table);
}
return tables;
}
const LootTable& emptyLootTable() {
static const LootTable table;
return table;
}
} // namespace
int toolHarvestLevel(ToolTier tier) {
switch (tier) {
case ToolTier::None: return 0;
case ToolTier::Wood: return 1;
case ToolTier::Gold: return 1;
case ToolTier::Stone: return 2;
case ToolTier::Iron: return 3;
case ToolTier::Diamond: return 4;
}
return 0;
}
bool toolAllows(const BlockDropRule& rule, ItemId tool) {
if (!rule.toolRequiredForDrop) return true;
const ItemInfo& info = itemInfo(tool);
if (info.toolType != rule.harvestTool) return false;
return toolHarvestLevel(info.toolTier) >= toolHarvestLevel(rule.minimumTier);
}
LootTable blockRuleTable(const BlockDropRule& rule) {
LootTable table;
ItemId harvested = rule.silkTouchDrop();
if (harvested != ItemId::None) {
LootEntry silk;
silk.item = harvested;
silk.conditions = LootEntry::SilkTouched;
appendPool(table, silk);
}
if (rule.drop != ItemId::None) {
LootEntry broken;
broken.item = rule.drop;
broken.minCount = rule.minCount;
broken.maxCount = rule.maxCount;
broken.chance = rule.dropChance;
broken.conditions = LootEntry::NotSilkTouched;
if (rule.firedDrop != ItemId::None) broken.conditions |= LootEntry::NotFiery;
if (rule.minCount != rule.maxCount) broken.functions |= LootEntry::CountRange;
if (rule.fortuneMultiplies) broken.functions |= LootEntry::OreFortune;
if (rule.chancePerFortune > 0.0f) {
broken.functions |= LootEntry::ChanceFortune;
broken.chancePerLevel = rule.chancePerFortune;
}
appendPool(table, broken);
}
if (rule.firedDrop != ItemId::None) {
LootEntry burned;
burned.item = rule.firedDrop;
burned.minCount = rule.minCount;
burned.maxCount = rule.maxCount;
burned.conditions = LootEntry::NotSilkTouched | LootEntry::Fiery;
if (rule.minCount != rule.maxCount) burned.functions |= LootEntry::CountRange;
appendPool(table, burned);
}
if (rule.bonusDrop != ItemId::None) {
LootEntry bonus;
bonus.item = rule.bonusDrop;
bonus.minCount = rule.bonusMin;
bonus.maxCount = rule.bonusMax;
bonus.chance = rule.bonusChance;
bonus.conditions = LootEntry::NotSilkTouched;
if (rule.bonusMin != rule.bonusMax) bonus.functions |= LootEntry::CountRange;
appendPool(table, bonus);
}
return table;
}
LootTable mobRuleTable(const MobDropRule& rule) {
LootTable table;
if (rule.drop != ItemId::None) {
LootEntry common;
common.item = rule.drop;
common.minCount = rule.minCount;
common.maxCount = rule.maxCount;
if (rule.minCount != rule.maxCount) common.functions |= LootEntry::CountRange;
if (rule.lootingRaisesCount) common.functions |= LootEntry::LootingBonus;
if (rule.dropNeedsPlayerKill) common.conditions |= LootEntry::PlayerKill;
if (rule.firedDrop != ItemId::None) common.conditions |= LootEntry::NotFiery;
appendPool(table, common);
if (rule.firedDrop != ItemId::None) {
LootEntry cooked = common;
cooked.item = rule.firedDrop;
cooked.conditions = (common.conditions & ~LootEntry::NotFiery) | LootEntry::Fiery;
appendPool(table, cooked);
}
}
if (rule.rareDrop != ItemId::None) {
LootEntry rare;
rare.item = rule.rareDrop;
rare.chance = rule.rareChance;
rare.chancePerLevel = rule.rareChancePerLooting;
if (rule.rareChancePerLooting > 0.0f) rare.functions |= LootEntry::ChanceLooting;
if (rule.rareNeedsPlayerKill) rare.conditions |= LootEntry::PlayerKill;
appendPool(table, rare);
}
return table;
}
LootTableId LootTableId::ofBlock(Block block) {
return LootTableId{Domain::Block, static_cast<uint16_t>(block)};
}
LootTableId LootTableId::ofMob(MobDropRule::Species species) {
return LootTableId{Domain::Mob, static_cast<uint16_t>(species)};
}
LootTableId LootTableId::ofChest(ChestFill::Structure structure) {
return LootTableId{Domain::Chest, static_cast<uint16_t>(structure)};
}