587 lines
10 KiB
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
|
|
})
|
|
|
|
|
|
|
|
|
|
|