subgames/mods/survivalgames/chests.lua

213 lines
7.0 KiB
Lua

-- name("default:stone"), rarity(0-1), wert(1-10), count({min, max}), wear(nil), ("survivalgames")
treasurer.register_treasure("default:diamond",0.01,9,1,nil,"survivalgames")
treasurer.register_treasure("default:steel_ingot",0.03,5,{1,3},nil,"survivalgames")
treasurer.register_treasure("default:cactus",0.06,5,{1,5},nil,"survivalgames")
treasurer.register_treasure("default:wood",0.05,1,{5,20},nil,"survivalgames")
treasurer.register_treasure("default:sword_steel",0.02,6,1,nil,"survivalgames")
treasurer.register_treasure("tnt:tnt_burning",0.01,6,{3,7},nil,"survivalgames")
treasurer.register_treasure("bucket:bucket_water",0.015,4,1,nil,"survivalgames")
treasurer.register_treasure("bucket:bucket_lava",0.01,4,1,nil,"survivalgames")
local chest_formspec =
"size[8,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[current_name;main;0,0.3;8,4;]" ..
"list[current_player;main;0,4.85;8,1;]" ..
"list[current_player;main;0,6.08;8,3;8]" ..
"listring[current_name;main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
minetest.register_node("survivalgames:chest", {
description = "Chest",
tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
paramtype2 = "facedir",
groups = {choppy = 2, oddly_breakable_by_hand = 2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if player then
minetest.chat_send_player(player:get_player_name(),
"You're not allowed to put things in treasure chests!")
return 0
end
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", chest_formspec)
meta:set_string("infotext", "Chest")
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("main")
end,
on_metadata_inventory_move = function(pos, from_list, from_index,
to_list, to_index, count, player)
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
if vector.distance(vector.round(player:get_pos()), pos) > 6 then
return 0
end
local inv = minetest.get_inventory({type = "node", pos=pos})
if not inv or inv:is_empty("main") then
minetest.set_node(pos, {name="air"})
minetest.show_formspec(player:get_player_name(), "", player:get_inventory_formspec())
end
end,
})
--[[ here are some configuration variables ]]
local chests_per_chunk = 1 -- number of chests per chunk. 15 is a bit high, an actual mod might have a lower number
local h_min = -40 -- minimum chest spawning height, relative to water_level
local h_max = 80 -- maximum chest spawning height, relative to water_level
local t_min = 2 -- minimum amount of treasures found in a chest
local t_max = 5 -- maximum amount of treasures found in a chest
local get_node = minetest.get_node
local env = minetest.env
local function findGroundLevel(pos, y_min, y_max)
local ground = nil
local top = y_max
for y = y_max, y_min, -1 do
local p = {x=pos.x,y=y,z=pos.z}
local name = get_node(p).name
if name == "air" or name == "default:water_source" or name == "default:lava_source" then
top = y
break
end
end
for y=top,y_min,-1 do
local p = {x=pos.x,y=y,z=pos.z}
local name = get_node(p).name
if name ~= "air" and name ~= "default:water_source" and name ~= "default:lava_source" then
ground = y
break
end
end
return ground
end
local function getFacedirs(pos, ground)
-- secondly: rotate the chest
-- find possible faces
local xp, xm, zp, zm
xp = minetest.get_node({x=pos.x+1, y=ground+1, z=pos.z})
xm = minetest.get_node({x=pos.x-1, y=ground+1, z=pos.z})
zp = minetest.get_node({x=pos.x, y=ground+1, z=pos.z+1})
zm = minetest.get_node({x=pos.x, y=ground+1, z=pos.z-1})
-- Set Facedirs
local facedirs = {}
if xp.name=="air" or xp.name=="default:water_source" then
table.insert(facedirs, minetest.dir_to_facedir({x=-1,y=0,z=0}))
end
if xm.name=="air" or xm.name=="default:water_source" then
table.insert(facedirs, minetest.dir_to_facedir({x=1,y=0,z=0}))
end
if zp.name=="air" or zp.name=="default:water_source" then
table.insert(facedirs, minetest.dir_to_facedir({x=0,y=0,z=-1}))
end
if zm.name=="air" or zm.name=="default:water_source" then
table.insert(facedirs, minetest.dir_to_facedir({x=0,y=0,z=1}))
end
return facedirs
end
local function placeChest(pos, chest_pos, ground, nn)
local chest = {name = "survivalgames:chest"}
local facedirs = getFacedirs(pos, ground)
-- choose a random face (if possible)
if #facedirs == 0 then
minetest.set_node({x=pos.x,y=ground+1, z=pos.z+1}, {name=nn})
chest.param2 = minetest.dir_to_facedir({x=0,y=0,z=1})
else
chest.param2 = facedirs[math.floor(math.random(#facedirs))]
end
-- Lastly: place the chest
minetest.set_node(chest_pos, chest)
-- Get treasure
local treasure_amount = math.ceil(math.random(t_min, t_max))
local height = math.abs(h_min) - math.abs(h_max)
local y_norm = (ground+1) - h_min
local scale = 1 - (y_norm/height)
local treasures = treasurer.select_random_treasures(treasure_amount, nil, nil, "survivalgames")
-- Add Treasure to Chst
local meta = minetest.get_meta(chest_pos)
local inv = meta:get_inventory()
for i=1, #treasures do
inv:set_stack("main", i, treasures[i])
end
end
--[[ here comes the generation code
the interesting part which involes treasurer comes way below
]]
minetest.register_on_generated(function(minp, maxp, seed)
if minp.y > 100 or maxp.y < -50 or math.random(4) ~= 1 then return end
local inside = false
for _, ldata in pairs(survivalgames.lobbys) do
if ldata.mappos1 and ldata.mappos2 and is_inside_area(ldata.mappos1, ldata.mappos2, maxp) then
inside = true
break
end
end
if not inside then return end
minp = {x=minp.x, y=minp.y, z=minp.z}
maxp = {x=maxp.x, y=maxp.y, z=maxp.z}
-- chests minimum and maximum spawn height
local height_min = h_min
local height_max = h_max
if(maxp.y < height_min or minp.y > height_max) then
return
end
local y_min = math.max(minp.y, height_min)
local y_max = math.min(maxp.y, height_max)
local attempts = 0
local chests_placed = 0
while chests_placed < chests_per_chunk and attempts < chests_per_chunk + 6 do
attempts = attempts + 1
local pos = {
x = math.random(minp.x, maxp.x),
y = minp.y,
z = math.random(minp.z, maxp.z)
}
-- Find ground level
local ground = findGroundLevel(pos, y_min, y_max)
if ground ~= nil then
local chest_pos = {x = pos.x, y = ground + 1, z = pos.z}
-- Don't spawn at barrier
if chest_pos.z == 0 then
chest_pos.z = -1
end
local nn = minetest.get_node(chest_pos).name -- chest node name (before it becomes a chest)
if nn == "air" or nn == "default:water_source" then
placeChest(pos, chest_pos, ground, nn)
chests_placed = chests_placed + 1
end
end
end
end)