diff --git a/core/src/Loot.cpp b/core/src/Loot.cpp index f5a17ba..23df435 100644 --- a/core/src/Loot.cpp +++ b/core/src/Loot.cpp @@ -156,3 +156,161 @@ LootTable leavesTable() { LootEntry silk = fixedDrop(ItemId::Leaves); silk.conditions = LootEntry::SilkTouched; + // The item palette has no sapling, so a wood cutting stands in as the + // replantable drop; Fortune improves its odds the way vanilla does. + LootEntry cutting = chanceDrop(ItemId::Wood, 0.05f, 0.04f, LootEntry::ChanceFortune); + cutting.conditions = LootEntry::NotSilkTouched; + + LootEntry apple = chanceDrop(ItemId::Apple, 0.005f, 0.0f, 0); + apple.conditions = LootEntry::NotSilkTouched; + + LootEntry sticks = rangedDrop(ItemId::Stick, 1, 2); + sticks.chance = 0.02f; + sticks.conditions = LootEntry::NotSilkTouched; + + LootTable table; + addPool(table, silk); + addPool(table, cutting); + addPool(table, apple); + addPool(table, sticks); + return table; +} + +LootTable zombieTable() { + LootEntry flesh = rangedDrop(ItemId::RottenFlesh, 0, 2); + flesh.functions = LootEntry::CountRange | LootEntry::LootingBonus; + + LootEntry ingot = chanceDrop(ItemId::IronIngot, 0.025f, 0.01f, LootEntry::ChanceLooting); + ingot.conditions = LootEntry::PlayerKill; + + LootTable table; + addPool(table, flesh); + addPool(table, ingot); + return table; +} + +LootTable skeletonTable() { + LootEntry shafts = rangedDrop(ItemId::Stick, 0, 2); + shafts.functions = LootEntry::CountRange | LootEntry::LootingBonus; + + LootEntry coal = chanceDrop(ItemId::CoalLump, 0.05f, 0.01f, LootEntry::ChanceLooting); + coal.conditions = LootEntry::PlayerKill; + + LootTable table; + addPool(table, shafts); + addPool(table, coal); + return table; +} + +LootTable creeperTable() { + LootEntry powder = rangedDrop(ItemId::Gunpowder, 0, 2); + powder.functions = LootEntry::CountRange | LootEntry::LootingBonus; + + LootTable table; + addPool(table, powder); + return table; +} + +LootTable meatTable(ItemId rawMeat, int minCount, int maxCount) { + LootEntry meat = rangedDrop(rawMeat, minCount, maxCount); + meat.functions = LootEntry::CountRange | LootEntry::LootingBonus | LootEntry::SmeltIfFiery; + + LootTable table; + addPool(table, meat); + return table; +} + +LootTable dungeonChestTable() { + LootPool pool; + pool.minRolls = 2; + pool.maxRolls = 4; + pool.entries = { + weightedDrop(ItemId::IronIngot, 10, 1, 4), weightedDrop(ItemId::Bread, 10, 1, 1), + weightedDrop(ItemId::CoalLump, 10, 1, 4), weightedDrop(ItemId::RedstoneDust, 5, 1, 4), + weightedDrop(ItemId::GoldIngot, 5, 1, 4), weightedDrop(ItemId::LapisLazuli, 5, 1, 3), + weightedDrop(ItemId::Apple, 8, 1, 3), weightedDrop(ItemId::DiamondGem, 1, 1, 2), + }; + LootTable table; + table.pools.push_back(pool); + return table; +} + +LootTable villageChestTable() { + LootPool pool; + pool.minRolls = 3; + pool.maxRolls = 5; + pool.entries = { + weightedDrop(ItemId::Bread, 10, 1, 3), weightedDrop(ItemId::Apple, 8, 1, 3), + weightedDrop(ItemId::Stick, 6, 1, 4), weightedDrop(ItemId::IronIngot, 5, 1, 2), + weightedDrop(ItemId::WoodHoe, 3, 1, 1), weightedDrop(ItemId::EmeraldGem, 2, 1, 2), + }; + LootTable table; + table.pools.push_back(pool); + return table; +} + +LootTable templeChestTable() { + LootPool pool; + pool.minRolls = 2; + pool.maxRolls = 4; + pool.entries = { + weightedDrop(ItemId::Gunpowder, 5, 1, 8), weightedDrop(ItemId::RottenFlesh, 5, 3, 7), + weightedDrop(ItemId::GoldIngot, 5, 1, 3), weightedDrop(ItemId::Bread, 5, 1, 1), + weightedDrop(ItemId::LapisLazuli, 2, 1, 3), weightedDrop(ItemId::DiamondGem, 1, 1, 3), + weightedDrop(ItemId::EmeraldGem, 1, 1, 3), + }; + LootTable table; + table.pools.push_back(pool); + return table; +} + +std::vector buildBlockTables() { + std::size_t blockCount = static_cast(Block::Count); + std::vector tables(blockCount); + for (std::size_t i = 0; i < blockCount; ++i) { + tables[i] = selfDropTable(static_cast(i)); + } + tables[static_cast(Block::Bedrock)] = LootTable{}; + tables[static_cast(Block::Stone)] = stoneTable(); + tables[static_cast(Block::Grass)] = selfDropTable(Block::Dirt); + tables[static_cast(Block::Leaves)] = leavesTable(); + tables[static_cast(Block::CoalOre)] = + oreTable(Block::CoalOre, ItemId::CoalLump, 1, 1); + tables[static_cast(Block::IronOre)] = + oreTable(Block::IronOre, ItemId::IronOre, 1, 1); + tables[static_cast(Block::GoldOre)] = + oreTable(Block::GoldOre, ItemId::GoldOre, 1, 1); + tables[static_cast(Block::DiamondOre)] = + oreTable(Block::DiamondOre, ItemId::DiamondGem, 1, 1); + tables[static_cast(Block::EmeraldOre)] = + oreTable(Block::EmeraldOre, ItemId::EmeraldGem, 1, 1); + tables[static_cast(Block::LapisOre)] = + oreTable(Block::LapisOre, ItemId::LapisLazuli, 4, 9); + tables[static_cast(Block::RedstoneOre)] = + oreTable(Block::RedstoneOre, ItemId::RedstoneDust, 4, 5); + tables[static_cast(Block::Glowstone)] = + oreTable(Block::Glowstone, ItemId::Glowstone, 2, 4); + return tables; +} + +const LootTable& emptyTable() { + static const LootTable table; + return table; +} + +} // namespace + +int LootRoll::countOf(ItemId item) const { + int total = 0; + for (const ItemSlot& stack : items) { + if (stack.item == item) total += stack.count; + } + return total; +} + +int LootRoll::totalCount() const { + int total = 0; + for (const ItemSlot& stack : items) total += stack.count; + return total; +} +