minetest_potions/minetunnels.lua

587 lines
10 KiB
Lua

--[[
torches
loot
doors
traps
mining side-tunnels
minerals embedded in walls
cave-ins
signs
poisonous or explosive mine gasses
room types:
barracks, with beds
dining hall, kitchen
ore storage room
chemistry lab
fancy exterior entrance
]]
minetest.register_node("potions:trap_floor", {
description = "Trap Floor",
drawtype = "node",
tiles = {"default_stone_brick.png"},
groups = {cracky=3,},
})
local function trigger_trap(pos)
local n = minetest.get_node(pos)
if not n or n.name ~= "potions:trap_floor" then
return
end
minetest.swap_node(pos, {name="default:stonebrick"})
minetest.spawn_falling_node(pos)
minetest.after(.3, trigger_trap, {x=pos.x-1, y=pos.y, z=pos.z})
minetest.after(.3, trigger_trap, {x=pos.x+1, y=pos.y, z=pos.z})
minetest.after(.3, trigger_trap, {x=pos.x, y=pos.y, z=pos.z+1})
minetest.after(.3, trigger_trap, {x=pos.x, y=pos.y, z=pos.z-1})
end
minetest.register_abm({
nodenames = {"potions:trap_floor"},
interval = 3,
chance = 10,
action = function(pos)
local objs = minetest.get_objects_inside_radius(pos, 4)
local found = false
for _,o in ipairs(objs) do
if o:is_player() then
found = true
break
end
end
if found then
trigger_trap(pos)
end
end,
})
minetest.register_node("potions:trap_seed", {
description = "Trap seed",
drawtype = "node",
tiles = {"default_mese.png"},
groups = {cracky=3,},
on_construct = function(pos)
potions.build_trap_below(
{x=pos.x-4, y=pos.y-5, z=pos.z-6},
{x=pos.x+4, y=pos.y-1, z=pos.z+6},
1, 1, "default:river_water_source"
)
end,
})
minetest.register_node("potions:minetunnel_seed", {
description = "Minetunnel seed",
drawtype = "node",
tiles = {"default_mese.png"},
groups = {cracky=3,},
})
local function set_column(pos, height, node)
if type(node) == "string" then
node = {name=node}
end
for i = 0,height-1,1 do
minetest.set_node({x=pos.x, y=pos.y+i, z=pos.z}, node)
end
end
local function brace_ceiling(pos, name)
local a = minetest.get_node(pos)
if a then
local def = minetest.registered_nodes[a.name]
if def and def.groups.falling_node then
minetest.set_node(pos, {name=name})
end
end
end
local function tunnel_stack(pos, height, bottom, top, rot)
if rot then
minetest.set_node({x=pos.x, y=pos.y-1, z=pos.z}, {name=bottom, param2 = rot})
else
minetest.set_node({x=pos.x, y=pos.y-1, z=pos.z}, {name=bottom})
end
set_column(pos, height - 1, "air")
brace_ceiling({x=pos.x, y=pos.y+height-1, z=pos.z}, top)
end
function potions.build_trap_below(minp, maxp, fall_depth, lava_depth, lava_node)
-- set the floor
for x = minp.x,maxp.x do
for z = minp.z,maxp.z do
minetest.set_node({x=x, y=maxp.y, z=z}, {name="potions:trap_floor"})
end
end
-- empty space underneath
local y = maxp.y-1
while y > maxp.y-fall_depth-1 do
for x = minp.x,maxp.x do
for z = minp.z,maxp.z do
minetest.set_node({x=x, y=y, z=z}, {name="air"})
end
end
y=y-1
end
-- lava pool
while y > maxp.y-fall_depth-1-lava_depth do
for x = minp.x,maxp.x do
for z = minp.z,maxp.z do
minetest.set_node({x=x, y=y, z=z}, {name=lava_node})
end
end
y=y-1
end
-- TODO: container for lava
end
local function build_tunnel(pos, dir, length, props)
print('buildign tunnel at '..dump(pos))
local floor_rot
local def = minetest.registered_nodes[props.nodes.floor]
if def and def.paramtype2 == 'facedir' then
floor_rot = minetest.dir_to_facedir({x=-dir.x,y=0,z=-dir.z})
end
local width = props.tunnel_width
local w = math.floor(width / 2)
local w = math.floor(width / 2)
local x = 0
local y = 0
while x < length do
for z = 1,width do
local p = {
x = pos.x + x*dir.x + (z-w-1)*dir.z,
y = pos.y - y,
z = pos.z + (z-w-1)*dir.x + x*dir.z
}
tunnel_stack(p, props.tunnel_height, props.nodes.floor, props.nodes.ceiling, floor_rot)
if props.railpos and props.railpos == z then
minetest.set_node(p, {name=props.nodes.rail})
end
end
x = x + 1
end
return {x=pos.x + x*dir.x, y=pos.y, z=pos.z + x*dir.z}
end
local function build_descending_entrance(pos, dir, depth_into_stone, props)
print('buildign entrance at '..dump(pos))
local floor_rot
local def = minetest.registered_nodes[props.nodes.floor]
if def and def.paramtype2 == 'facedir' then
floor_rot = minetest.dir_to_facedir({x=-dir.x,y=0,z=-dir.z})
end
local width = props.tunnel_width
local w = math.floor(width / 2)
local x = 0
local y = 0
while y < 10 do
for z = 1,width do
local p = {
x = pos.x + x*dir.x + (z-w-1)*dir.z,
y = pos.y - y,
z = pos.z + (z-w-1)*dir.x + x*dir.z
}
if props.railpos and props.railpos == z then
tunnel_stack(p, 5, props.nodes.floor, props.nodes.ceiling, floor_rot)
minetest.set_node(p, {name=props.nodes.rail})
else
tunnel_stack(p, 5, props.nodes.stair, props.nodes.ceiling, floor_rot)
end
end
y = y + 1
x = x + 1
end
return {x=pos.x + x*dir.x, y=pos.y - y, z=pos.z + x*dir.z}
end
local function build_room(entrance_pos, dir, props)
end
local function build_junction(pos, dirs, props)
-- TODO: replace tunnel_stack with something that doesn't destroy rail
-- so this fn can be called on existing junctions
local z, x
local width = props.tunnel_width
local w = math.floor(width / 2)
-- hollow out the cavity
for z = 1,width do
for x = 1,width do
local p = {
x = pos.x + (x-w-1)*dir.x + (z-w-1)*dir.z,
y = pos.y + 2,
z = pos.z + (z-w-1)*dir.x + (x-w-1)*dir.z
}
set_column(p, height - 2, "air")
minetest.set_node({x=p.x, y=pos.y, z=p.z}, props.nodes.floor)
brace_ceiling({x=p.x, y=pos.y+props.tunnel_height, z=p.z}, props.nodes.ceiling)
end
end
for k,v in pairs(dirs) do
-- install rails
for z = w,width do
for x = w,width do
minetest.set_node({
x=pos.x + v.x*x + v.z*z,
y=pos.y+1,
z=pos.z + v.z*x + v.x*z
}, props.nodes.rail)
end
end
end
end
local function random_dir()
local d = {
{x=1, z=0},
{x=-1, z=0},
{x=0, z=1},
{x=0, z=-1},
}
return d[math.random(4)]
end
local function random_new_dir(olddir)
local d = {
{x=1, z=0},
{x=-1, z=0},
{x=0, z=1},
{x=0, z=-1},
}
local i = math.random(4)
local a = d[i]
if a.x == olddir.x and a.z == olddir.z then
a = d[((i + 1) % 4) + 1]
end
return a
end
local function random_perpendicular(dir)
local d
if dir.x == 0 then
d = {
{x=1, z=0},
{x=-1, z=0},
}
else
d = {
{x=0, z=1},
{x=0, z=-1},
}
end
return d[math.random(2)]
end
local function build_mine(pos, props)
print('building mine at '..dump(pos))
local nodes = {
props.nodes.floor
}
for i = 2,props.tunnel_width do
table.insert(nodes, props.nodes.stair)
end
local p2 = build_descending_entrance(
pos,
props.primary_dir,
props.min_mine_depth,
props
)
print("1")
local p3 = p2
local last_dir = props.primary_dir
for i = 1,4 do
p3 = build_tunnel(
p3,
last_dir,
props.min_tunnel_len + math.random(props.max_tunnel_len - props.min_tunnel_len),
props
)
last_dir = random_perpendicular(last_dir)
end
print("2")
local p4 = build_descending_entrance(
p3,
last_dir,
props.tunnel_height + 2 + math.random(10),
props
)
print("3")
-- p4 = build_tunnel({x=p3.x-1, y=p3.y, z=p3.z}, {x=0,z=1}, 2, 4, 10, "default:stonebrick", "default:stonebrick")
end
local function mf(x, n)
return math.floor(x / n)
end
local function vdadd(pos, dir, length)
return {
x = pos.x + (dir.x * length),
y = pos.y,
z = pos.z + (dir.z * length),
}
end
local function build_mine_maze(pos, o)
local q = 0
local data = {
stack = {},
log = {},
}
local function encode(pos)
return "x"..mf(pos.x,2).."y"..mf(pos.y,2).."z"..mf(pos.z,2)
end
local function do_run(pos, dir, length)
local n = vector.add(pos, 0)
for i = 1,length do
minetest.set_node(n, {name="default:cobble"})
n.x = n.x + dir.x
n.z = n.z + dir.z
n.y = n.y + (dir.y or 0)
end
return n
end
local function direction_ok(pos, dir, length)
local e = encode(vdadd(pos, dir, length))
local g = data.log[e]
return g == nil
end
table.insert(data.stack, {
n = {x=pos.x, y=pos.y-1, z=pos.z},
dir = {x=1, z=0},
})
while q < 10 do
local n = table.remove(data.stack, 1)
if n == nil then
break
end
local e = encode(n.n)
local g = data.log[e]
data.log[e] = 1
if g == nil then
local n2 = do_run(n.n, n.dir, 10)
local newdir = n.dir
for i = 1,3 do
newdir = random_new_dir(newdir)
if direction_ok(n2, newdir, 10) then
table.insert(data.stack, {
n = n2,
dir = newdir
})
break
elseif math.random(2) == 2 then
table.insert(data.stack, {
n = {x=n2.x, y=n2.y+1, z=n2.z},
dir = newdir
})
break
end
end
-- minetest.set_node(n.n, {name="default:cobble"})
-- if math.random(20) < 19 then table.insert(data.stack, {x=n.x+2, y=n.y, z=n.z}) end
-- if math.random(20) < 19 then table.insert(data.stack, {x=n.x-2, y=n.y, z=n.z}) end
-- if math.random(20) < 3 then table.insert(data.stack, {x=n.x, y=n.y, z=n.z+2}) end
-- if math.random(20) < 3 then table.insert(data.stack, {x=n.x, y=n.y, z=n.z-2}) end
end
q = q + 1
end
end
local function build_minetunnel(pos)
local props = {
nodes = {
floor = "default:stonebrick",
stair = "stairs:stair_stonebrick",
slab = "stairs:slab_stonebrick",
rail = "carts:rail",
ceiling = "default:cobble",
torch = "default:torch",
chest = "default:chest",
},
min_mine_depth = 15,
max_mine_depth = 50,
min_tunnel_len = 6,
max_tunnel_len = 10,
tunnel_width = 3,
tunnel_height = 4,
primary_dir = random_dir(),
torch_chance = 50,
railpos = 2,
}
build_mine(pos, props)
-- p2 = build_descending_entrance(pos, {x=1,z=0}, 2, 10, {"carts:rail", "stairs:stair_cobble"}, "")
-- p3 = build_tunnel(p2, {x=1,z=0}, 2, 4, 10, "default:stonebrick", "default:stonebrick")
-- p3 = build_tunnel({x=p3.x-1, y=p3.y, z=p3.z}, {x=0,z=1}, 2, 4, 10, "default:stonebrick", "default:stonebrick")
end
minetest.register_node("potions:maze_seed", {
description = "Maze seed",
drawtype = "node",
tiles = {"default_mese.png"},
groups = {cracky=3,},
on_construct = function(pos)
build_mine_maze({x=pos.x, y=pos.y-1, z=pos.z})
end,
})
minetest.register_abm({
nodenames = "potions:minetunnel_seed",
chance = 1,
interval = 3,
action = function(pos, node)
minetest.after(2, function()
minetest.set_node(pos, {name="air"})
-- pos.y = pos.y - 1
build_minetunnel(pos)
end)
end
})