diff --git a/mods/CORE/mcl_loot/description.txt b/mods/CORE/mcl_loot/description.txt new file mode 100644 index 00000000..30ba9a6f --- /dev/null +++ b/mods/CORE/mcl_loot/description.txt @@ -0,0 +1 @@ +API for filling a chest with random treasures. diff --git a/mods/CORE/mcl_loot/init.lua b/mods/CORE/mcl_loot/init.lua new file mode 100644 index 00000000..62af02a8 --- /dev/null +++ b/mods/CORE/mcl_loot/init.lua @@ -0,0 +1,89 @@ +mcl_loot = {} + +--[[ +Select a number of itemstacks out of a pool of treasure definitions randomly. + +Parameters: +* loot_definitions: Probabilities and information about the loot to select. Syntax: + +{ + stacks_min = 1, -- Mamimum number of item stacks to get + stacks_max = 3, -- Number of repetitions, maximum + items = { -- Table of possible loot items. This function selects between stacks_min and stacks_max of these. + { + itemstring = "example:item1", -- Which item to select + amount_min = 1, -- Minimum size of itemstack. Optional (default: 1) + amount_max = 10, -- Maximum size of item stack. Must not exceed item definition's stack_max. Optional (default: 1) + wear_min = 1, -- Minimum wear value. Must be at lest 1. Optional (default: no wear) + wear_max = 1, -- Maxiumum wear value. Must be at lest 1. Optional (default: no wear) + weight = 5, -- Likelihood of this item being selected + }, + { -- more tables like above, one table per item stack } + } +} +* pr: PseudoRandom object + +How weight works: The probability of a single item stack being selected is weight/total_weight, with +total_weight being the sum of all weight values in the items table. + +Returns: Table of itemstrings +]] +function mcl_loot.get_loot(loot_definitions, pr) + local items = {} + + local total_weight = 0 + for i=1, #loot_definitions.items do + total_weight = total_weight + loot_definitions.items[i].weight + end + + local stacks = pr:next(loot_definitions.stacks_min, loot_definitions.stacks_max) + for s=1, stacks do + local r = pr:next(1, total_weight) + + local accumulated_weight = 0 + local item + for i=1, #loot_definitions.items do + accumulated_weight = accumulated_weight + loot_definitions.items[i].weight + if accumulated_weight >= r then + item = loot_definitions.items[i] + break + end + end + if item then + local itemstring = item.itemstring + if item.amount_min and item.amount_max then + itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max) + end + if item.wear_min and item.wear_max then + if not item.amount_min and not item.amount_max then + itemstring = itemstring .. " 1" + end + itemstring = itemstring .. " " .. pr:next(item.wear_min, item.wear_max) + end + table.insert(items, itemstring) + else + minetest.log("error", "[mcl_loot] INTERNAL ERROR! Failed to select random loot item!") + end + end + + return items +end + +--[[ +Repeat mcl_loot.get_loot multiple times for various loot_definitions. +Useful for filling chests. + +* multi_loot_definitions: Table of loot_definitions (see mcl_loot.get_loot) +* pr: PseudoRandom object + +Returns: Table of itemstrings ]] +function mcl_loot.get_multi_loot(multi_loot_definitions, pr) + local items = {} + for m=1, #multi_loot_definitions do + local group = mcl_loot.get_loot(multi_loot_definitions[m], pr) + for g=1, #group do + table.insert(items, group[g]) + end + end + return items +end diff --git a/mods/CORE/mcl_loot/mod.conf b/mods/CORE/mcl_loot/mod.conf new file mode 100644 index 00000000..8406dcc2 --- /dev/null +++ b/mods/CORE/mcl_loot/mod.conf @@ -0,0 +1 @@ +name = mcl_loot diff --git a/mods/MAPGEN/tsm_railcorridors/depends.txt b/mods/MAPGEN/tsm_railcorridors/depends.txt index 77c9001f..a53609c6 100644 --- a/mods/MAPGEN/tsm_railcorridors/depends.txt +++ b/mods/MAPGEN/tsm_railcorridors/depends.txt @@ -1,5 +1,6 @@ mcl_init mcl_util mcl_core +mcl_loot mcl_tnt mcl_farming diff --git a/mods/MAPGEN/tsm_railcorridors/gameconfig.lua b/mods/MAPGEN/tsm_railcorridors/gameconfig.lua index 5f57bd05..8f8039d7 100644 --- a/mods/MAPGEN/tsm_railcorridors/gameconfig.lua +++ b/mods/MAPGEN/tsm_railcorridors/gameconfig.lua @@ -30,69 +30,46 @@ end -- MineClone 2's treasure function. Gets all treasures for a single chest. -- Based on information from Minecraft Wiki. function tsm_railcorridors.get_treasures(pr) - local items = {} - -- First roll - local r1 = pr:next(1,71) - if r1 <= 30 then - table.insert(items, "mobs:nametag") - elseif r1 <= 50 then - table.insert(items, "mcl_core:apple_gold") - elseif r1 <= 60 then - -- TODO: Enchanted Book - table.insert(items, "mcl_books:book") - elseif r1 <= 65 then - -- Nothing! - elseif r1 <= 70 then - table.insert(items, "mcl_tools:pick_iron") - else - -- TODO: Enchanted Golden Apple - table.insert(items, "mcl_core:apple_gold") - end - - -- Second roll - local r2stacks = pr:next(2,4) - for i=1, r2stacks do - local r2 = pr:next(1,83) - if r2 <= 15 then - table.insert(items, "mcl_farming:bread "..pr:next(1,3)) - elseif r2 <= 25 then - table.insert(items, "mcl_core:coal_lump "..pr:next(3,8)) - elseif r2 <= 35 then - table.insert(items, "mcl_farming:beetroot_seeds "..pr:next(2,4)) - elseif r2 <= 45 then - table.insert(items, "mcl_farming:melon_seeds "..pr:next(2,4)) - elseif r2 <= 55 then - table.insert(items, "mcl_farming:pumpkin_seeds "..pr:next(2,4)) - elseif r2 <= 65 then - table.insert(items, "mcl_core:iron_ingot "..pr:next(1,5)) - elseif r2 <= 70 then - table.insert(items, "mcl_dye:blue "..pr:next(4,9)) - elseif r2 <= 75 then - table.insert(items, "mesecons:redstone "..pr:next(4,9)) - elseif r2 <= 80 then - table.insert(items, "mcl_core:gold_ingot "..pr:next(1,3)) - else - table.insert(items, "mcl_core:diamond "..pr:next(1,2)) - end - end - - -- Third roll - for i=1, 3 do - local r3 = pr:next(1,50) - if r3 <= 20 then - table.insert(items, "mcl_minecarts:rail "..pr:next(4,8)) - elseif r3 <= 35 then - table.insert(items, "mcl_torches:torch "..pr:next(1,16)) - elseif r3 <= 40 then - -- TODO: Activator Rail - table.insert(items, "mcl_minecarts:rail "..pr:next(1,4)) - elseif r3 <= 45 then - -- TODO: Detector Rail - table.insert(items, "mcl_minecarts:rail "..pr:next(1,4)) - else - table.insert(items, "mcl_minecarts:golden_rail "..pr:next(1,4)) - end - end + local items = mcl_loot.get_multi_loot({ + { + stacks_min = 1, + stacks_max = 1, + items = { + { itemstring = "mobs:nametag", weight = 30 }, + { itemstring = "mcl_core:apple_gold", weight = 20 }, + { itemstring = "mcl_books:book", weight = 10 }, -- TODO: Enchanted Book + { itemstring = "", weight = 5}, + { itemstring = "mcl_core:pick_iron", weight = 5 }, + { itemstring = "mcl:core:apple_gold", weight = 1 }, -- TODO: Enchanted Golden Apple + } + }, + { + stacks_min = 2, + stacks_max = 4, + items = { + { itemstring = "mcl_farming:bread", weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:coal_lump", weight = 10, amount_min = 3, amount_max = 8 }, + { itemstring = "mcl_farming:beetroot_seeds", weight = 10, amount_min = 2, amount_max = 4 }, + { itemstring = "mcl_farming:melon_seeds", weight = 10, amount_min = 2, amount_max = 4 }, + { itemstring = "mcl_farming:pumpkin_seeds", weight = 10, amount_min = 2, amount_max = 4 }, + { itemstring = "mcl_core:iron_ingot", weight = 10, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_dye:bye", weight = 5, amount_min = 4, amount_max = 9 }, + { itemstring = "mesecons:redstone", weight = 5, amount_min = 4, amount_max = 9 }, + { itemstring = "mcl_core:gold_ingot", weight = 5, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:diamond", weight = 3, amount_min = 1, amount_max = 2 }, + } + }, + { + stacks_min = 3, + stacks_max = 3, + items = { + { itemstring = "mcl_minecarts:rail", weight = 20, amount_min = 4, amount_max = 8 }, + { itemstring = "mcl_torches:torch", weight = 15, amount_min = 1, amount_max = 16 }, + { itemstring = "mcl_minecarts:rail", weight = 5, amount_min = 1, amount_max = 4 }, -- TODO: Activator Rail + { itemstring = "mcl_minecarts:rail", weight = 5, amount_min = 1, amount_max = 4 }, -- TODO: Detector Rail + { itemstring = "mcl_minecarts:golden_rail", weight = 5, amount_min = 1, amount_max = 4 }, + } + }}, pr) return items end