Module:Sandbox/LootTable

local java_data = mw.text.jsonDecode(require('Module:Sandbox/LootTable/Java.json'))

local p = { calc_average_amount_this_item_per_pool = function(			min_stacksize, max_stacksize,			min_pool_rolls, max_pool_rolls,			item_weight, pool_total_item_weight )

local avg_stacksize = ( min_stacksize + max_stacksize ) / 2 local avg_rolls = ( min_pool_rolls + max_pool_rolls ) / 2

return avg_stacksize * avg_rolls * item_weight / pool_total_item_weight

end,

calc_chance_any_of_this_item_per_pool = function(			min_pool_rolls, max_pool_rolls,			item_weight, pool_total_item_weight )

local inverse_result = 0 -- 1 - inverse_result = return value local inverse_item_weight = pool_total_item_weight - item_weight

-- will be used for the division in the for loop to avoid the slightly -- less performant math.pow. The divisor already includes the probability -- of picking any specific number of rolls. local cur_dividend = pool_total_item_weight local cur_divisor = pool_total_item_weight * (max_pool_rolls - min_pool_rolls + 1) for i = 0, max_pool_rolls do			if i >= min_pool_rolls then inverse_result = inverse_result + cur_dividend / cur_divisor end cur_dividend = cur_dividend * inverse_item_weight -- simulate pow cur_divisor = cur_divisor * pool_total_item_weight -- simulate pow end

return 1 - inverse_result end,

get_tables_and_items = function(data) local items = {} local loottables = {}

for table_id, details in pairs(java_data) do           loottables[table_id] = { category = details.category, sub_category = details.sub_category, type = details.type, pools = {}, }           for pool_i, pool in ipairs(details["loot_table"]["pools"]) do                loottables[table_id].pools[pool_i] = { min_rolls = 1, max_rolls = 1, total_weight = 0 }               if type(pool.rolls) == "number" then loottables[table_id].pools[pool_i].min_rolls = pool.rolls loottables[table_id].pools[pool_i].max_rolls = pool.rolls else loottables[table_id].pools[pool_i].min_rolls = pool.rolls.min loottables[table_id].pools[pool_i].max_rolls = pool.rolls.max end

-- TODO parse conditions

for i, entry in ipairs(pool["entries"]) do                   if entry["type"] == "minecraft:item" then local item = { id = entry["name"], min_stacksize = 1, max_stacksize = 1, item_weight = entry["weight"] or 1, pool = pool_i, loot_table = table_id, }                       if entry["functions"] then for i, func in ipairs(entry["functions"]) do                               if func["function"] == "minecraft:set_count" then item.min_stacksize = func["count"]["min"] or 1 item.max_stacksize = func["count"]["max"] or 1 -- TODO parse other functions end end end

loottables[table_id].pools[pool_i].total_weight = loottables[table_id].pools[pool_i].total_weight + item.item_weight

if items[item.id] then table.insert(items[item.id], item) else items[item.id] = {item} end end end end end return items, loottables end,

current_frame = nil }

p.loot_tables = function( ... ) p.current_frame = mw.getCurrentFrame

local args = { ... }	if args[1] == p.current_frame then args = require( 'Module:ProcessArgs' ).merge( true ) else args = args[1] end

-- transform args into usable list

local loot_tables, columns = {}, {}

local filtered_loot_tables = {}

for i, table_id in ipairs(loot_tables) do       if java_data[table_id] then filtered_loot_tables[table_id] = {java_data[table_id]} elseif table_id == "all" then filtered_loot_tables = java_data else filtered_loot_tables = java_data end end

local items, loottables = p.get_tables_and_items(filtered_loot_tables) local output = '{| class="wikitable sortable"\n|-\n! Item !! Pool !! Chance per pool !! Average amount per pool' for item_id, item_data in pairs(items) do       for _, item in ipairs(item_data) do            local chance = p.calc_chance_any_of_this_item_per_pool(                loottables[item.loot_table].pools[item.pool].min_rolls,                loottables[item.loot_table].pools[item.pool].max_rolls,                item.item_weight,                loottables[item.loot_table].pools[item.pool].total_weight            ) local avg_amount = p.calc_average_amount_this_item_per_pool(               item.min_stacksize,                item.max_stacksize,                loottables[item.loot_table].pools[item.pool].min_rolls,                loottables[item.loot_table].pools[item.pool].max_rolls,                item.item_weight,                loottables[item.loot_table].pools[item.pool].total_weight            ) output = output .. string.format('\n|-\n| %s || %d || %f || %f', item_id, item.pool, chance, args[1]) end end output = output .. '\n|}' return output end

return p