mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-28 21:41:06 +01:00
119 lines
3.2 KiB
Lua
119 lines
3.2 KiB
Lua
|
mcl_loottables.register_entry = mcl_util.registration_function(mcl_loottables.entries)
|
||
|
mcl_loottables.register_table = mcl_util.registration_function(mcl_loottables.tables, function(name, def)
|
||
|
local function set_parents(parent)
|
||
|
for _, child in ipairs(parent.children or parent.entries or parent.pools or {}) do
|
||
|
child.parent = parent
|
||
|
set_parents(child)
|
||
|
end
|
||
|
end
|
||
|
set_parents(def)
|
||
|
end)
|
||
|
|
||
|
|
||
|
function mcl_loottables.get_table(def)
|
||
|
local t = type(def)
|
||
|
if t == "nil" then
|
||
|
return {}
|
||
|
elseif t == "string" then
|
||
|
return assert(mcl_loottables.tables[def])
|
||
|
elseif t == "table" then
|
||
|
return def
|
||
|
else
|
||
|
error("invalid loottable type: " .. t)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.get_entry_type(entry)
|
||
|
return assert(mcl_loottables.entries[entry.type])
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.get_candidates(entries, data, func)
|
||
|
local candidates = {}
|
||
|
local functions = {}
|
||
|
for _, entry in ipairs(entries) do
|
||
|
local success = mcl_predicates.do_predicates(entry.conditions, data)
|
||
|
|
||
|
if success then
|
||
|
local children = entry.children
|
||
|
|
||
|
if children then
|
||
|
table.insert_all(candidates, mcl_loottables.get_candidates(children, data, mcl_loottables.get_entry_type(entry).preprocess))
|
||
|
else
|
||
|
table.insert(candidates, entry)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if func and func(success, data) then
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
return candidates
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.do_item_modifiers(itemstack, node, data)
|
||
|
if node then
|
||
|
mcl_functions.do_item_modifiers(itemstack, node.functions, data)
|
||
|
mcl_loottables.do_item_modifiers(itemstack, node.parent, data)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.do_pools(pools, functions, data)
|
||
|
local luck = data.luck or 0
|
||
|
local stacks = {}
|
||
|
for _, pool in ipairs(pools or {}) do
|
||
|
if mcl_conditions.do_conditions(pool.conditions, data) do
|
||
|
local rolls = mcl_loottables.get_number(pool.rolls, data) + mcl_loottables.get_number(pool.bonus_rolls, data) * luck
|
||
|
for i = 1, rolls do
|
||
|
local candidates = mcl_loottables.get_candidates(pool.entries, data)
|
||
|
|
||
|
if #candidates > 0 then
|
||
|
local total_weight = 0
|
||
|
local weights = {}
|
||
|
for _, candidate in ipairs(candidates)
|
||
|
total_weight = total_weight + math.floor((candidate.weight or 1) + (candidate.quality or 0) * luck)
|
||
|
table.insert(weights, total_weight)
|
||
|
end
|
||
|
|
||
|
local selected
|
||
|
local rnd = mcl_util.rand(data.pr, 0, weight - 1)
|
||
|
for i, w in ipairs(weights) do
|
||
|
if rnd < w then
|
||
|
selected = candidates[i]
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local func = mcl_loottables.get_entry_type(entry).process
|
||
|
local stacks = func(selected, data)
|
||
|
|
||
|
for _, stack in ipairs(stacks) do
|
||
|
mcl_loottables.do_item_modifiers(stack, selected, data)
|
||
|
end
|
||
|
table.insert_all(stacks, stack)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return stacks
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.get_loot(def, data)
|
||
|
def = mcl_loottables.get_table(def)
|
||
|
return mcl_loottables.do_pools(def.pools)
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.drop_loot(def, data)
|
||
|
local loot = mcl_loottables.get_loot(def)
|
||
|
local old_loot = table.copy(loot)
|
||
|
for _, stack in ipairs(old_loot) do
|
||
|
local max_stack = stack:get_stack_max()
|
||
|
while max_stack < stack:get_count() do
|
||
|
table.insert(loot, stack:take_items(max_stack))
|
||
|
end
|
||
|
end
|
||
|
return loot
|
||
|
end
|
||
|
|
||
|
function mcl_loottables.fill_chest(def, data)
|
||
|
end
|