1015 lines
31 KiB
Lua
1015 lines
31 KiB
Lua
-- Parameters
|
|
|
|
-- Approximate generation limits
|
|
local YMIN = -33000
|
|
local YMAX = 33000
|
|
local XMIN = -33000
|
|
local XMAX = 33000
|
|
local ZMIN = -33000
|
|
local ZMAX = 33000
|
|
local YMAXSPA = -33 -- Maximum y for initial catacomb spawn and steps in air
|
|
|
|
-- Spawn and generation
|
|
local TCATSPA = 2.0 -- 3D noise threshold for initial chamber
|
|
local TCATA = -2.0 -- 3D noise for generation limit
|
|
local GEN = true -- Enable spawn and generation
|
|
local OBCHECK = true -- Enable chamber obstruction check
|
|
local ABMINT = 1 -- ABM interval multiplier, 1 = fast generation
|
|
|
|
-- Spawn and generation noise
|
|
local np_cata = {
|
|
offset = 0,
|
|
scale = 1,
|
|
spread = {x = 256, y = 256, z = 256},
|
|
seed = 5829058,
|
|
octaves = 3,
|
|
persist = 0.5,
|
|
lacunarity = 2.0,
|
|
--flags = ""
|
|
}
|
|
|
|
-- Passages
|
|
local MINPLEN = 3 -- Min max length
|
|
local MAXPLEN = 32
|
|
local MINPWID = 3 -- Min max outer width
|
|
local MAXPWID = 24
|
|
|
|
-- Chambers
|
|
local MINCWID = 6 -- Min max outer EW NS widths, min max outer height.
|
|
local MAXCWID = 32
|
|
local MINCHEI = 6
|
|
local MAXCHEI = 32
|
|
|
|
|
|
-- Nodes
|
|
|
|
minetest.register_node("catacomb:cobble", {
|
|
description = "Mod cobblestone",
|
|
tiles = {"default_cobble.png"},
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
drop = "default:cobble",
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:stairn", {
|
|
description = "Stair north",
|
|
tiles = {"default_cobble.png"},
|
|
drawtype = "nodebox",
|
|
paramtype = "light",
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
|
{-0.5, 0, 0, 0.5, 0.5, 0.5},
|
|
},
|
|
},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:stairs", {
|
|
description = "Stair south",
|
|
tiles = {"default_cobble.png"},
|
|
drawtype = "nodebox",
|
|
paramtype = "light",
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
|
{-0.5, 0, -0.5, 0.5, 0.5, 0},
|
|
},
|
|
},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:staire", {
|
|
description = "Stair East",
|
|
tiles = {"default_cobble.png"},
|
|
drawtype = "nodebox",
|
|
paramtype = "light",
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
|
{0, 0, -0.5, 0.5, 0.5, 0.5},
|
|
},
|
|
},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:stairw", {
|
|
description = "Stair west",
|
|
tiles = {"default_cobble.png"},
|
|
drawtype = "nodebox",
|
|
paramtype = "light",
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
|
{-0.5, 0, -0.5, 0, 0.5, 0.5},
|
|
},
|
|
},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:chambern", {
|
|
description = "Chamber spawner north",
|
|
tiles = {"default_cobble.png"},
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:chambers", {
|
|
description = "Chamber spawner south",
|
|
tiles = {"default_cobble.png"},
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:chambere", {
|
|
description = "Chamber spawner east",
|
|
tiles = {"default_cobble.png"},
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
minetest.register_node("catacomb:chamberw", {
|
|
description = "Chamber spawner west",
|
|
tiles = {"default_cobble.png"},
|
|
is_ground_content = false,
|
|
groups = {cracky = 3, stone = 2},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
|
|
|
|
-- On generated function
|
|
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
local x0 = minp.x
|
|
local y0 = minp.y
|
|
local z0 = minp.z
|
|
local x1 = maxp.x
|
|
local y1 = maxp.y
|
|
local z1 = maxp.z
|
|
|
|
-- Check mapchunk is within limits
|
|
if not (x0 > XMIN and x1 < XMAX and
|
|
y0 > YMIN and y1 <= YMAXSPA and
|
|
z0 > ZMIN and z1 < ZMAX) or not GEN then
|
|
return
|
|
end
|
|
|
|
-- Check minimum point is within catacomb spawn volume
|
|
local nobj_cata = minetest.get_perlin(np_cata)
|
|
local nval_cata = nobj_cata:get3d({x = x0, y = y0, z = z0})
|
|
if nval_cata < TCATSPA then
|
|
--print ("[catacomb] Spawn noise " .. nval_cata)
|
|
return
|
|
end
|
|
|
|
-- Check for nearby catacomb cobble
|
|
local sidelen = x1 - x0 + 1
|
|
local sidelen2 = sidelen * 2
|
|
local c_catcobble = minetest.get_content_id("catacomb:cobble")
|
|
for vmvns = z0 - sidelen2, z0 + sidelen2, sidelen do -- Step sidelen
|
|
for vmvud = y0 - sidelen2, y0 + sidelen2, sidelen do
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x0 - sidelen2, y = vmvud, z = vmvns}
|
|
local pos2 = {x = x0 + sidelen2, y = vmvud, z = vmvns}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
|
|
for vi = 1, sidelen * 4 do
|
|
if data[vi] == c_catcobble then
|
|
print ("[catacomb] First chamber obstructed")
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Spawn first chamber
|
|
local t1 = os.clock()
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
local c_cobble = minetest.get_content_id("default:cobble")
|
|
local c_mobble = minetest.get_content_id("default:mossycobble")
|
|
local c_stobble = minetest.get_content_id("stairs:stair_cobble")
|
|
local c_chambers = minetest.get_content_id("catacomb:chambers")
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x0, y = y0, z = z0}
|
|
local pos2 = {x = x0 + MAXCWID, y = y0 + MAXCHEI, z = z0 + MAXCWID}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
|
|
local exoffs = math.random(0, MAXCWID - 3)
|
|
|
|
for z = z0, z0 + MAXCWID do
|
|
for y = y0, y0 + MAXCHEI do
|
|
local vi = area:index(x0, y, z)
|
|
for x = x0, x0 + MAXCWID do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_air
|
|
and nodid ~= c_ignore
|
|
and nodid ~= c_cobble
|
|
and nodid ~= c_mobble
|
|
and nodid ~= c_stobble then
|
|
if z == z0 and y == y0 and x == x0 + exoffs then
|
|
data[vi] = c_chambers
|
|
elseif (z > z0 and z < z0 + MAXCWID
|
|
and y > y0 and y < y0 + MAXCHEI
|
|
and x > x0 and x < x0 + MAXCWID) then
|
|
data[vi] = c_air
|
|
else
|
|
data[vi] = c_catcobble
|
|
end
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
|
|
local chugent = math.ceil((os.clock() - t1) * 1000)
|
|
print ("[catacomb] Spawn first chamber " .. chugent ..
|
|
" ms minp " .. x0 .. " " .. y0 .. " " .. z0)
|
|
end)
|
|
|
|
|
|
-- ABM
|
|
|
|
-- Chamber north
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"catacomb:chambern"},
|
|
interval = 16 * ABMINT,
|
|
chance = 1,
|
|
catch_up = false,
|
|
action = function(pos, node)
|
|
--local t1 = os.clock()
|
|
local x = pos.x
|
|
local y = pos.y
|
|
local z = pos.z
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
local c_cobble = minetest.get_content_id("default:cobble")
|
|
local c_mobble = minetest.get_content_id("default:mossycobble")
|
|
local c_leaves = minetest.get_content_id("default:leaves")
|
|
local c_jleaves = minetest.get_content_id("default:jungleleaves")
|
|
local c_apple = minetest.get_content_id("default:apple")
|
|
local c_stobble = minetest.get_content_id("stairs:stair_cobble")
|
|
|
|
local c_catcobble = minetest.get_content_id("catacomb:cobble")
|
|
local c_stairn = minetest.get_content_id("catacomb:stairn")
|
|
local c_stairs = minetest.get_content_id("catacomb:stairs")
|
|
local c_chambern = minetest.get_content_id("catacomb:chambern")
|
|
local c_chambere = minetest.get_content_id("catacomb:chambere")
|
|
local c_chamberw = minetest.get_content_id("catacomb:chamberw")
|
|
|
|
-- Measure existing chamber wall width
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x + MINPWID, y = y, z = z}
|
|
local pos2 = {x = x + MAXCWID, y = y, z = z}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
|
|
local wallwid = MINPWID
|
|
local vi = area:index(x + MINPWID, y, z)
|
|
for i = MINPWID, MAXCWID do
|
|
if data[vi] ~= c_catcobble then
|
|
wallwid = i
|
|
break
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
|
|
-- Calculate dimensions of passage and chamber
|
|
local passwid = math.random(MINPWID, math.min(MAXPWID, wallwid)) -- Width including walls
|
|
local passdlu = math.random(-1, 1) -- Passage direction, -1 down, 0 level, 1 up.
|
|
local passlen = math.random(MINPLEN, MAXPLEN)
|
|
|
|
local chamew = math.random(math.max(passwid, MINCWID), MAXCWID) - 1
|
|
local chamns = math.random(MINCWID, MAXCWID) - 1
|
|
local chamhei = math.random(MINCHEI, MAXCHEI) - 1
|
|
local chamhoff = -math.random(0, chamew + 1 - passwid) -- Chamber W offset relative to passage
|
|
local chamvoff = math.min(passdlu * passlen, passlen - 1)
|
|
local exoffn = math.random(0, chamew - 3)
|
|
local exoffe = math.random(0, chamns - 3)
|
|
local exoffw = math.random(0, chamns - 3)
|
|
|
|
local vmvd = math.min(chamvoff, 0) -- Voxelmanip volume edges relative to spawner
|
|
local vmvu = math.max(chamvoff + chamhei, 5)
|
|
local vmvw = chamhoff
|
|
local vmve = chamhoff + chamew
|
|
local vmvn = chamns + passlen
|
|
|
|
-- Read entire volume
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x + vmvw, y = y + vmvd, z = z}
|
|
local pos2 = {x = x + vmve, y = y + vmvu, z = z + vmvn}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
local vvii = emax.x - emin.x + 1
|
|
local nvii = (emax.y - emin.y + 1) * vvii
|
|
|
|
local vi = area:index(x, y, z) -- Remove spawner
|
|
data[vi] = c_catcobble
|
|
|
|
-- Check for obstruction
|
|
if OBCHECK then
|
|
for k = passlen + 1, vmvn do
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x + chamhoff, y + j, z + k)
|
|
for i = 0, chamew do
|
|
local nodid = data[vi]
|
|
if nodid == c_catcobble then
|
|
vm:set_data(data) -- To remove spawner
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
--print ("[catacomb] Chamber obstructed")
|
|
return
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Carve hole in chamber wall
|
|
local vi = area:index(x + 1, y + 1, z)
|
|
for j = 1, 4 do
|
|
for i = 1, passwid - 2 do
|
|
data[vi] = c_air
|
|
vi = vi + 1
|
|
end
|
|
vi = vi - passwid + 2 + vvii -- Back 2, up 1.
|
|
end
|
|
|
|
-- Spawn passage
|
|
local vi = area:index(x, y, z + 1)
|
|
for k = 1, passlen do
|
|
for j = 1, 6 do
|
|
for i = 1, passwid do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_ignore then
|
|
if passdlu ~= 0 and j == 1 -- steps spawn in underground air
|
|
and not (passdlu == 1 and k == 1)
|
|
and not (passdlu == -1 and k == len)
|
|
and (i >= 2 and i <= passwid - 1)
|
|
and (nodid ~= c_air or y <= YMAXSPA) then
|
|
if passdlu == -1 then
|
|
data[vi] = c_stairs
|
|
data[vi - vvii] = c_catcobble
|
|
else
|
|
data[vi] = c_stairn
|
|
data[vi - vvii] = c_catcobble
|
|
end
|
|
elseif passdlu == 0 and j == 1 and
|
|
(i >= 2 and i <= passwid - 1) then
|
|
data[vi] = c_catcobble -- Level passage floor spawns in air
|
|
elseif nodid ~= c_air then
|
|
if j == 1 or j == 6 or i == 1 or i == passwid then
|
|
data[vi] = c_catcobble
|
|
else
|
|
data[vi] = c_air
|
|
end
|
|
end
|
|
end
|
|
vi = vi + 1 -- Eastwards 1
|
|
end
|
|
vi = vi - passwid + vvii -- Back passwid, up 1.
|
|
end
|
|
vi = vi + (passdlu - 6) * vvii + nvii -- Down 5 or 6 or 7, northwards 1.
|
|
end
|
|
|
|
-- Decide whether to place spawners in chamber
|
|
local nobj_cata = minetest.get_perlin(np_cata)
|
|
local spawn = GEN and nobj_cata:get3d(
|
|
{x = x + chamhoff, y = y + chamvoff, z = z + vmvn}) > TCATA and
|
|
x > XMIN and x < XMAX and y > YMIN and y < YMAX and z > ZMIN and z < ZMAX
|
|
|
|
-- Spawn chamber
|
|
for k = passlen + 1, vmvn do
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x + chamhoff, y + j, z + k)
|
|
for i = 0, chamew do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_air
|
|
and nodid ~= c_ignore
|
|
and nodid ~= c_cobble -- Default dungeons remain TODO update for new dungeons
|
|
and nodid ~= c_mobble
|
|
and nodid ~= c_stobble then
|
|
if spawn and k == vmvn and j == chamvoff and i == exoffn then
|
|
data[vi] = c_chambern
|
|
elseif spawn and i == chamew and j == chamvoff and
|
|
k == passlen + 1 + exoffe then
|
|
data[vi] = c_chambere
|
|
elseif spawn and i == 0 and j == chamvoff and
|
|
k == passlen + 1 + exoffw then
|
|
data[vi] = c_chamberw
|
|
elseif (k > passlen + 1 and k < vmvn and j > chamvoff and
|
|
j < chamvoff + chamhei and i > 0 and i < chamew) or
|
|
(k == passlen + 1 and j > chamvoff and j <= chamvoff + 4 and
|
|
(i > -chamhoff and i < -chamhoff + passwid - 1)) then
|
|
data[vi] = c_air
|
|
else
|
|
data[vi] = c_catcobble
|
|
end
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
|
|
--local chugent = math.ceil((os.clock() - t1) * 1000)
|
|
--print ("[catacomb] Chamber North " .. chugent .. "ms")
|
|
end,
|
|
})
|
|
|
|
|
|
-- Chamber south
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"catacomb:chambers"},
|
|
interval = 17 * ABMINT,
|
|
chance = 1,
|
|
catch_up = false,
|
|
action = function(pos, node)
|
|
--local t1 = os.clock()
|
|
local x = pos.x
|
|
local y = pos.y
|
|
local z = pos.z
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
local c_cobble = minetest.get_content_id("default:cobble")
|
|
local c_mobble = minetest.get_content_id("default:mossycobble")
|
|
local c_leaves = minetest.get_content_id("default:leaves")
|
|
local c_jleaves = minetest.get_content_id("default:jungleleaves")
|
|
local c_apple = minetest.get_content_id("default:apple")
|
|
local c_stobble = minetest.get_content_id("stairs:stair_cobble")
|
|
|
|
local c_catcobble = minetest.get_content_id("catacomb:cobble")
|
|
local c_stairn = minetest.get_content_id("catacomb:stairn")
|
|
local c_stairs = minetest.get_content_id("catacomb:stairs")
|
|
local c_chambers = minetest.get_content_id("catacomb:chambers")
|
|
local c_chambere = minetest.get_content_id("catacomb:chambere")
|
|
local c_chamberw = minetest.get_content_id("catacomb:chamberw")
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x + MINPWID, y = y, z = z}
|
|
local pos2 = {x = x + MAXCWID, y = y, z = z}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
|
|
local wallwid = MINPWID
|
|
local vi = area:index(x + MINPWID, y, z)
|
|
for i = MINPWID, MAXCWID do
|
|
if data[vi] ~= c_catcobble then
|
|
wallwid = i
|
|
break
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
|
|
local passwid = math.random(MINPWID, math.min(MAXPWID, wallwid)) -- width including walls
|
|
local passdlu = math.random(-1, 1) -- passage direction, -1 down, 0 level, 1 up
|
|
local passlen = math.random(MINPLEN, MAXPLEN)
|
|
|
|
local chamew = math.random(math.max(passwid, MINCWID), MAXCWID) - 1
|
|
local chamns = math.random(MINCWID, MAXCWID) - 1
|
|
local chamhei = math.random(MINCHEI, MAXCHEI) - 1
|
|
local chamhoff = -math.random(0, chamew + 1 - passwid) -- chamber W offset relative to passage
|
|
local chamvoff = math.min(passdlu * passlen, passlen - 1)
|
|
local exoffs = math.random(0, chamew - 3)
|
|
local exoffe = math.random(0 + 3, chamns)
|
|
local exoffw = math.random(0 + 3, chamns)
|
|
|
|
local vmvd = math.min(chamvoff, 0) -- voxel manip volume edges relative to spawner
|
|
local vmvu = math.max(chamvoff + chamhei, 5)
|
|
local vmvw = chamhoff
|
|
local vmve = chamhoff + chamew
|
|
local vmvs = chamns + passlen
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x + vmvw, y = y + vmvd, z = z - vmvs}
|
|
local pos2 = {x = x + vmve, y =y + vmvu, z = z}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
local vvii = emax.x - emin.x + 1
|
|
local nvii = (emax.y - emin.y + 1) * vvii
|
|
|
|
local vi = area:index(x, y, z) -- remove spawner
|
|
data[vi] = c_catcobble
|
|
|
|
if OBCHECK then -- check for obstruction
|
|
for k = passlen + 1, vmvs do
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x + chamhoff, y + j, z - k)
|
|
for i = 0, chamew do
|
|
local nodid = data[vi]
|
|
if nodid == c_catcobble then
|
|
vm:set_data(data) -- abort chamber spawn
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
--print ("[catacomb] Chamber obstructed")
|
|
return
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local vi = area:index(x + 1, y + 1, z) -- spawn passage
|
|
for j = 1, 4 do -- carve hole in chamber wall
|
|
for i = 1, passwid - 2 do
|
|
data[vi] = c_air
|
|
vi = vi + 1
|
|
end
|
|
vi = vi - passwid + 2 + vvii -- back 2, up 1
|
|
end
|
|
|
|
local vi = area:index(x, y, z - 1)
|
|
for k = 1, passlen do
|
|
for j = 1, 6 do
|
|
for i = 1, passwid do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_ignore then
|
|
if passdlu ~= 0 and j == 1
|
|
and not (passdlu == 1 and k == 1)
|
|
and not (passdlu == -1 and k == len)
|
|
and (i >= 2 and i <= passwid - 1)
|
|
and (nodid ~= c_air or y <= YMAXSPA) then
|
|
if passdlu == -1 then
|
|
data[vi] = c_stairn
|
|
data[vi - vvii] = c_catcobble
|
|
else
|
|
data[vi] = c_stairs
|
|
data[vi - vvii] = c_catcobble
|
|
end
|
|
elseif passdlu == 0 and j == 1 and
|
|
(i >= 2 and i <= passwid - 1) then
|
|
data[vi] = c_catcobble
|
|
elseif nodid ~= c_air then
|
|
if j == 1 or j == 6 or i == 1 or i == passwid then
|
|
data[vi] = c_catcobble
|
|
else
|
|
data[vi] = c_air
|
|
end
|
|
end
|
|
end
|
|
vi = vi + 1 -- eastwards 1
|
|
end
|
|
vi = vi - passwid + vvii -- back passwid, up 1
|
|
end
|
|
vi = vi + (passdlu - 6) * vvii - nvii -- down 5 or 6 or 7, southwards 1
|
|
end
|
|
|
|
-- Decide whether to place spawners in chamber
|
|
local nobj_cata = minetest.get_perlin(np_cata)
|
|
local spawn = GEN and nobj_cata:get3d(
|
|
{x = x + chamhoff, y = y + chamvoff, z = z - vmvs}) > TCATA and
|
|
x > XMIN and x < XMAX and y > YMIN and y < YMAX and z > ZMIN and z < ZMAX
|
|
|
|
for k = passlen + 1, vmvs do -- spawn chamber
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x + chamhoff, y + j, z - k)
|
|
for i = 0, chamew do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_air
|
|
and nodid ~= c_ignore
|
|
and nodid ~= c_cobble -- default dungeons remain
|
|
and nodid ~= c_mobble
|
|
and nodid ~= c_stobble then
|
|
if spawn and k == vmvs and j == chamvoff and i == exoffs then
|
|
data[vi] = c_chambers
|
|
elseif spawn and i == chamew and j == chamvoff and
|
|
k == passlen + 1 + exoffe then
|
|
data[vi] = c_chambere
|
|
elseif spawn and i == 0 and j == chamvoff and
|
|
k == passlen + 1 + exoffw then
|
|
data[vi] = c_chamberw
|
|
elseif (k > passlen + 1 and k < vmvs and j > chamvoff and
|
|
j < chamvoff + chamhei and i > 0 and i < chamew) or
|
|
(k == passlen + 1 and j > chamvoff and j <= chamvoff + 4 and
|
|
(i > -chamhoff and i < -chamhoff + passwid - 1)) then
|
|
data[vi] = c_air
|
|
else
|
|
data[vi] = c_catcobble
|
|
end
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
|
|
--local chugent = math.ceil((os.clock() - t1) * 1000)
|
|
--print ("[catacomb] Chamber south " .. chugent .. "ms")
|
|
end,
|
|
})
|
|
|
|
-- Chamber east
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"catacomb:chambere"},
|
|
interval = 18 * ABMINT,
|
|
chance = 1,
|
|
catch_up = false,
|
|
action = function(pos, node)
|
|
--local t1 = os.clock()
|
|
local x = pos.x
|
|
local y = pos.y
|
|
local z = pos.z
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
local c_cobble = minetest.get_content_id("default:cobble")
|
|
local c_mobble = minetest.get_content_id("default:mossycobble")
|
|
local c_leaves = minetest.get_content_id("default:leaves")
|
|
local c_jleaves = minetest.get_content_id("default:jungleleaves")
|
|
local c_apple = minetest.get_content_id("default:apple")
|
|
local c_stobble = minetest.get_content_id("stairs:stair_cobble")
|
|
|
|
local c_catcobble = minetest.get_content_id("catacomb:cobble")
|
|
local c_staire = minetest.get_content_id("catacomb:staire")
|
|
local c_stairw = minetest.get_content_id("catacomb:stairw")
|
|
local c_chambern = minetest.get_content_id("catacomb:chambern")
|
|
local c_chambers = minetest.get_content_id("catacomb:chambers")
|
|
local c_chambere = minetest.get_content_id("catacomb:chambere")
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x, y = y, z = z + MINPWID}
|
|
local pos2 = {x = x, y = y, z = z + MAXCWID}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
local vvii = emax.x - emin.x + 1
|
|
local nvii = (emax.y - emin.y + 1) * vvii
|
|
|
|
local wallwid = MINPWID
|
|
local vi = area:index(x, y, z + MINPWID)
|
|
for i = MINPWID, MAXCWID do
|
|
if data[vi] ~= c_catcobble then
|
|
wallwid = i
|
|
break
|
|
end
|
|
vi = vi + nvii
|
|
end
|
|
|
|
local passwid = math.random(MINPWID, math.min(MAXPWID, wallwid)) -- width including walls
|
|
local passdlu = math.random(-1, 1) -- passage direction, -1 down, 0 level, 1 up
|
|
local passlen = math.random(MINPLEN, MAXPLEN)
|
|
|
|
local chamns = math.random(math.max(passwid, MINCWID), MAXCWID) - 1
|
|
local chamew = math.random(MINCWID, MAXCWID) - 1
|
|
local chamhei = math.random(MINCHEI, MAXCHEI) - 1
|
|
local chamhoff = -math.random(0, chamns + 1 - passwid) -- chamber S offset relative to passage
|
|
local chamvoff = math.min(passdlu * passlen, passlen - 1)
|
|
local exoffe = math.random(0, chamns - 3)
|
|
local exoffn = math.random(0, chamew - 3)
|
|
local exoffs = math.random(0, chamew - 3)
|
|
|
|
local vmvd = math.min(chamvoff, 0) -- voxel manip volume edges relative to spawner
|
|
local vmvu = math.max(chamvoff + chamhei, 5)
|
|
local vmvs = chamhoff
|
|
local vmvn = chamhoff + chamns
|
|
local vmve = chamew + passlen
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x, y = y + vmvd, z = z + vmvs}
|
|
local pos2 = {x=x + vmve, y = y + vmvu, z = z + vmvn}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
local vvii = emax.x - emin.x + 1
|
|
local nvii = (emax.y - emin.y + 1) * vvii
|
|
|
|
local vi = area:index(x, y, z) -- remove spawner
|
|
data[vi] = c_catcobble
|
|
|
|
if OBCHECK then -- check for obstruction
|
|
for k = chamhoff, vmvn do
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x + passlen + 1, y + j, z + k)
|
|
for i = 0, chamew do
|
|
local nodid = data[vi]
|
|
if nodid == c_catcobble then
|
|
vm:set_data(data) -- abort chamber spawn
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
--print ("[catacomb] Chamber obstructed")
|
|
return
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local vi = area:index(x, y + 1, z + 1) -- spawn passage
|
|
for j = 1, 4 do -- carve hole in chamber wall
|
|
for k = 1, passwid - 2 do
|
|
data[vi] = c_air
|
|
vi = vi + nvii
|
|
end
|
|
vi = vi - (passwid - 2) * nvii + vvii -- back 2, up 1
|
|
end
|
|
|
|
local vi = area:index(x + 1, y, z)
|
|
for i = 1, passlen do
|
|
for j = 1, 6 do
|
|
for k = 1, passwid do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_ignore then
|
|
if passdlu ~= 0 and j == 1
|
|
and not (passdlu == 1 and i == 1)
|
|
and not (passdlu == -1 and i == len)
|
|
and (k >= 2 and k <= passwid - 1)
|
|
and (nodid ~= c_air or y <= YMAXSPA) then
|
|
if passdlu == -1 then
|
|
data[vi] = c_stairw
|
|
data[vi - vvii] = c_catcobble
|
|
else
|
|
data[vi] = c_staire
|
|
data[vi - vvii] = c_catcobble
|
|
end
|
|
elseif passdlu == 0 and j == 1 and
|
|
(k >= 2 and k <= passwid - 1) then
|
|
data[vi] = c_catcobble
|
|
elseif nodid ~= c_air then
|
|
if j == 1 or j == 6 or k == 1 or k == passwid then
|
|
data[vi] = c_catcobble
|
|
else
|
|
data[vi] = c_air
|
|
end
|
|
end
|
|
end
|
|
vi = vi + nvii -- northwards 1
|
|
end
|
|
vi = vi - passwid * nvii + vvii -- back passwid, up 1
|
|
end
|
|
vi = vi + (passdlu - 6) * vvii + 1 -- down 5 or 6 or 7, eastwards 1
|
|
end
|
|
|
|
-- Decide whether to place spawners in chamber
|
|
local nobj_cata = minetest.get_perlin(np_cata)
|
|
local spawn = GEN and nobj_cata:get3d(
|
|
{x = x + vmve, y = y + chamvoff, z = z + chamhoff}) > TCATA and
|
|
x > XMIN and x < XMAX and y > YMIN and y < YMAX and z > ZMIN and z < ZMAX
|
|
|
|
for k = chamhoff, vmvn do -- spawn chamber
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x + passlen + 1, y + j, z + k)
|
|
for i = 0, chamew do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_air
|
|
and nodid ~= c_ignore
|
|
and nodid ~= c_cobble -- default dungeons remain
|
|
and nodid ~= c_mobble
|
|
and nodid ~= c_stobble then
|
|
if spawn and k == chamhoff + exoffe and
|
|
j == chamvoff and i == chamew then
|
|
data[vi] = c_chambere
|
|
elseif spawn and i == exoffn and j == chamvoff and k == vmvn then
|
|
data[vi] = c_chambern
|
|
elseif spawn and i == exoffs and j == chamvoff and k == chamhoff then
|
|
data[vi] = c_chambers
|
|
elseif (k > chamhoff and k < vmvn and j > chamvoff and
|
|
j < chamvoff + chamhei and i > 0 and i < chamew) or
|
|
(i == 0 and j > chamvoff and j <= chamvoff + 4 and
|
|
(k > 0 and k < passwid - 1)) then
|
|
data[vi] = c_air
|
|
else
|
|
data[vi] = c_catcobble
|
|
end
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
|
|
--local chugent = math.ceil((os.clock() - t1) * 1000)
|
|
--print ("[catacomb] Chamber east " .. chugent .. "ms")
|
|
end,
|
|
})
|
|
|
|
-- Chamber west
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"catacomb:chamberw"},
|
|
interval = 19 * ABMINT,
|
|
chance = 1,
|
|
catch_up = false,
|
|
action = function(pos, node)
|
|
--local t1 = os.clock()
|
|
local x = pos.x
|
|
local y = pos.y
|
|
local z = pos.z
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
local c_cobble = minetest.get_content_id("default:cobble")
|
|
local c_mobble = minetest.get_content_id("default:mossycobble")
|
|
local c_leaves = minetest.get_content_id("default:leaves")
|
|
local c_jleaves = minetest.get_content_id("default:jungleleaves")
|
|
local c_apple = minetest.get_content_id("default:apple")
|
|
local c_stobble = minetest.get_content_id("stairs:stair_cobble")
|
|
|
|
local c_catcobble = minetest.get_content_id("catacomb:cobble")
|
|
local c_staire = minetest.get_content_id("catacomb:staire")
|
|
local c_stairw = minetest.get_content_id("catacomb:stairw")
|
|
local c_chambern = minetest.get_content_id("catacomb:chambern")
|
|
local c_chambers = minetest.get_content_id("catacomb:chambers")
|
|
local c_chamberw = minetest.get_content_id("catacomb:chamberw")
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x, y = y, z = z + MINPWID}
|
|
local pos2 = {x = x, y = y, z = z + MAXCWID}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
local vvii = emax.x - emin.x + 1
|
|
local nvii = (emax.y - emin.y + 1) * vvii
|
|
|
|
local wallwid = MINPWID
|
|
local vi = area:index(x, y, z + MINPWID)
|
|
for i = MINPWID, MAXCWID do
|
|
if data[vi] ~= c_catcobble then
|
|
wallwid = i
|
|
break
|
|
end
|
|
vi = vi + nvii
|
|
end
|
|
|
|
local passwid = math.random(MINPWID, math.min(MAXPWID, wallwid)) -- width including walls
|
|
local passdlu = math.random(-1, 1) -- passage direction, -1 down, 0 level, 1 up
|
|
local passlen = math.random(MINPLEN, MAXPLEN)
|
|
|
|
local chamns = math.random(math.max(passwid, MINCWID), MAXCWID) - 1
|
|
local chamew = math.random(MINCWID, MAXCWID) - 1
|
|
local chamhei = math.random(MINCHEI, MAXCHEI) - 1
|
|
local chamhoff = -math.random(0, chamns + 1 - passwid) -- chamber S offset relative to passage
|
|
local chamvoff = math.min(passdlu * passlen, passlen - 1)
|
|
local exoffw = math.random(0, chamns - 3)
|
|
local exoffn = math.random(0, chamew - 3)
|
|
local exoffs = math.random(0, chamew - 3)
|
|
|
|
local vmvd = math.min(chamvoff, 0) -- voxel manip volume edges relative to spawner
|
|
local vmvu = math.max(chamvoff + chamhei, 5)
|
|
local vmvs = chamhoff
|
|
local vmvn = chamhoff + chamns
|
|
local vmvw = chamew + passlen
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
local pos1 = {x = x - vmvw, y = y + vmvd, z = z + vmvs}
|
|
local pos2 = {x = x, y = y + vmvu, z = z + vmvn}
|
|
local emin, emax = vm:read_from_map(pos1, pos2)
|
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
|
local data = vm:get_data()
|
|
local vvii = emax.x - emin.x + 1
|
|
local nvii = (emax.y - emin.y + 1) * vvii
|
|
|
|
local vi = area:index(x, y, z) -- remove spawner
|
|
data[vi] = c_catcobble
|
|
|
|
if OBCHECK then -- check for obstruction
|
|
for k = chamhoff, vmvn do
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x - vmvw, y + j, z + k)
|
|
for i = 0, chamew - 1 do
|
|
local nodid = data[vi]
|
|
if nodid == c_catcobble then
|
|
vm:set_data(data) -- abort chamber spawn
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
--print ("[catacomb] Chamber obstructed")
|
|
return
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local vi = area:index(x, y + 1, z + 1) -- spawn passage
|
|
for j = 1, 4 do -- carve hole in chamber wall
|
|
for k = 1, passwid - 2 do
|
|
data[vi] = c_air
|
|
vi = vi + nvii
|
|
end
|
|
vi = vi - (passwid - 2) * nvii + vvii -- back 2, up 1
|
|
end
|
|
|
|
local vi = area:index(x - 1, y, z)
|
|
for i = 1, passlen do
|
|
for j = 1, 6 do
|
|
for k = 1, passwid do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_ignore then
|
|
if passdlu ~= 0 and j == 1
|
|
and not (passdlu == 1 and i == 1)
|
|
and not (passdlu == -1 and i == len)
|
|
and (k >= 2 and k <= passwid - 1)
|
|
and (nodid ~= c_air or y <= YMAXSPA) then
|
|
if passdlu == -1 then
|
|
data[vi] = c_staire
|
|
data[vi - vvii] = c_catcobble
|
|
else
|
|
data[vi] = c_stairw
|
|
data[vi - vvii] = c_catcobble
|
|
end
|
|
elseif passdlu == 0 and j == 1 and
|
|
(k >= 2 and k <= passwid - 1) then
|
|
data[vi] = c_catcobble
|
|
elseif nodid ~= c_air then
|
|
if j == 1 or j == 6 or k == 1 or k == passwid then
|
|
data[vi] = c_catcobble
|
|
else
|
|
data[vi] = c_air
|
|
end
|
|
end
|
|
end
|
|
vi = vi + nvii -- northwards 1
|
|
end
|
|
vi = vi - passwid * nvii + vvii -- back passwid, up 1
|
|
end
|
|
vi = vi + (passdlu - 6) * vvii - 1 -- down 5 or 6 or 7, westwards 1
|
|
end
|
|
|
|
-- Decide whether to place spawners in chamber
|
|
local nobj_cata = minetest.get_perlin(np_cata)
|
|
local spawn = GEN and nobj_cata:get3d(
|
|
{x = x - vmvw, y = y + chamvoff, z = z + chamhoff}) > TCATA and
|
|
x > XMIN and x < XMAX and y > YMIN and y < YMAX and z > ZMIN and z < ZMAX
|
|
|
|
for k = chamhoff, vmvn do -- spawn chamber
|
|
for j = chamvoff, chamvoff + chamhei do
|
|
local vi = area:index(x - vmvw, y + j, z + k)
|
|
for i = 0, chamew - 1 do
|
|
local nodid = data[vi]
|
|
if nodid ~= c_air
|
|
and nodid ~= c_ignore
|
|
and nodid ~= c_cobble -- default dungeons remain
|
|
and nodid ~= c_mobble
|
|
and nodid ~= c_stobble then
|
|
if spawn and k == chamhoff + exoffw and j == chamvoff and i == 0 then
|
|
data[vi] = c_chamberw
|
|
elseif spawn and i == exoffn and j == chamvoff and k == vmvn then
|
|
data[vi] = c_chambern
|
|
elseif spawn and i == exoffs and j == chamvoff and k == chamhoff then
|
|
data[vi] = c_chambers
|
|
elseif (k > chamhoff and k < vmvn and j > chamvoff and
|
|
j < chamvoff + chamhei and i > 0 and i < chamew - 1) or
|
|
(i == chamew - 1 and j > chamvoff and j <= chamvoff + 4 and
|
|
(k > 0 and k < passwid - 1)) then
|
|
data[vi] = c_air
|
|
else
|
|
data[vi] = c_catcobble
|
|
end
|
|
end
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
vm:update_map()
|
|
|
|
--local chugent = math.ceil((os.clock() - t1) * 1000)
|
|
--print ("[catacomb] Chamber west " .. chugent .. "ms")
|
|
end,
|
|
})
|