lootchests = {} lootchests.loot_table = {} lootchests.spawn_chests = asuna.content.wayfarer.loot_chests local S = minetest.get_translator(minetest.get_current_modname()) local debug = minetest.settings:get("lootchests_debug") or false local function list_length(list) local count = 0 for _,_ in pairs(list) do count = count + 1 end return count end lootchests.add_to_loot_table = function(key, add) if not lootchests.loot_table[key] then lootchests.loot_table[key] = {} end for _,v in pairs(add) do table.insert(lootchests.loot_table[key], v) end end local water_nodes = { "default:water_source", "default:river_water_source", "default:lava_source", "ethereal:quicksand2", } lootchests.register_lootchest = function(def) if not def.name or not def.description then minetest.log("error", S("[lootchests] Missing fields in chest definition!")) return end if not lootchests.loot_table[def.name] then minetest.log("error", S("[lootchests] Missing loot table for") .. " " .. def.name .. "!") return end local tiles = def.tiles or { "default_chest_top.png", "default_chest_top.png", "default_chest_side.png", "default_chest_side.png", "default_chest_front.png", } local sounds = def.sounds or default.node_sound_wood_defaults() local groups = def.groups or {choppy = 2, oddly_breakable_by_hand = 2} local rarity = def.spawn_in_rarity or 512 local fill_ratio = def.spawn_on_rarity or 512 local ymax = def.ymax or 31000 local ymin = def.ymin or -31000 local slot_spawn_chance = def.slot_spawn_chance or 0.25 local slots = def.slots or 32 local node_box = def.node_box or { type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, } local marker_drawtype = "airlike" local marker_groups = {dig_immediate = 2, not_in_creative_inventory = 1} if debug then marker_drawtype = nil marker_groups = {dig_immediate = 2} end minetest.register_node(def.name .. "_marker", { drawtype = marker_drawtype, description = def.description .. " " .. S("Spawn Marker"), tiles = {"lootchests_marker_top.png", "lootchests_marker_side.png"}, groups = marker_groups, paramtype2 = "facedir", }) minetest.register_node(def.name, { description = def.description, drawtype = def.drawtype, tiles = tiles, node_box = node_box, selection_box = node_box, groups = groups, sounds = sounds, paramtype = "light", on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", "size[8,9]" .. default.gui_bg .. default.gui_bg_img .. default.gui_slots .. "list[current_name;main;0,0;8,5;]" .. "list[current_player;main;0,5;8,4;]" .. "listring[current_name;main]" .. "listring[current_player;main]" ) meta:set_string("infotext", def.description) local inv = meta:get_inventory() inv:set_size("main", slots) end, can_dig = function(pos,player) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv:is_empty("main") end, }) -- Function for checking underwater local check_water if not def.underwater then check_water = function(pos) for _,waterpos in ipairs({ { x = pos.x - 1, y = pos.y, z = pos.z - 1 }, { x = pos.x + 1, y = pos.y, z = pos.z - 1 }, { x = pos.x - 1, y = pos.y, z = pos.z + 1 }, { x = pos.x + 1, y = pos.y, z = pos.z + 1 }, }) do for _,water_node in ipairs(water_nodes) do if minetest.get_node(waterpos).name == water_node then return true -- found nearby water, trigger check end end end return false -- did not find nearby water, do not trigger check end else check_water = function() return false -- check never triggers end end if not debug and lootchests.spawn_chests then minetest.register_lbm({ label = S("Upgrade") .. " " .. def.description, name = def.name .. "_marker_replace", nodenames = def.name .. "_marker", run_at_every_load = true, action = function(pos, node) if check_water(pos) then minetest.set_node(pos, {name = "default:water_source", param2 = 0}) return -- loot chest is underwater and should not be, do not place here else minetest.set_node(pos, {name = def.name, param2 = 0}) end local rand = PcgRandom(pos.x * pos.y * pos.z) local inv = minetest.get_inventory({type = "node", pos = pos}) for i = 1, slots do if rand:next(0,100) <= slot_spawn_chance then local item_def = lootchests.loot_table[def.name][rand:next(1, #lootchests.loot_table[def.name])] local item_name = item_def[#item_def < 3 and 1 or rand:next(1,#item_def - 1)] local stack = ItemStack(item_name) if minetest.registered_tools[item_name] then stack:set_wear(rand:next(1,65535)) else stack:set_count(rand:next(1, item_def[#item_def])) end inv:set_stack("main", i, stack) end end end, }) end if def.spawn_in and lootchests.spawn_chests then minetest.register_ore({ ore_type = "scatter", ore = def.name .. "_marker", wherein = def.spawn_in, clust_scarcity = rarity * rarity * rarity, clust_num_ores = 1, clust_size = 25, y_min = ymin, y_max = ymax, }) end if def.spawn_on and lootchests.spawn_chests then minetest.register_decoration({ deco_type = "simple", place_on = def.spawn_on, spawn_by = def.spawn_by, num_spawn_by = def.num_spawn_by, sidelen = 80, fill_ratio = 1/fill_ratio, y_min = ymin, y_max = ymax, flags = "force_placement, all_floors", decoration = def.name .. "_marker", }) end end