Shrink fortresses and add non-maze levels.
This commit is contained in:
parent
955d4db7ad
commit
f44735e032
3 changed files with 159 additions and 76 deletions
246
fortress.lua
246
fortress.lua
|
@ -1,4 +1,6 @@
|
||||||
local max_depth = 31000
|
local max_depth = 31000
|
||||||
|
local cells = 10
|
||||||
|
local cell_size = 60 / cells
|
||||||
|
|
||||||
|
|
||||||
dofile(fun_caves.path .. "/trophies.lua")
|
dofile(fun_caves.path .. "/trophies.lua")
|
||||||
|
@ -36,6 +38,12 @@ newnode.tiles = {'fun_caves_blank.png'}
|
||||||
newnode.pointable = false
|
newnode.pointable = false
|
||||||
minetest.register_node("fun_caves:dungeon_wall_invisible", newnode)
|
minetest.register_node("fun_caves:dungeon_wall_invisible", newnode)
|
||||||
|
|
||||||
|
newnode = fun_caves.clone_node("default:meselamp")
|
||||||
|
newnode.description = "Dungeon Light"
|
||||||
|
newnode.light_source = 10
|
||||||
|
newnode.groups = {fortress = 1}
|
||||||
|
minetest.register_node("fun_caves:dungeon_light", newnode)
|
||||||
|
|
||||||
|
|
||||||
local treasures = {
|
local treasures = {
|
||||||
{'fun_caves:aquamarine', 'fun_caves:garnet', 'fun_caves:zoisite', 'fun_caves:coral_gem', 'fun_caves:moonstone', 'fun_caves:pure_copper', 'fun_caves:sky_iron', 'fun_caves:sky_iron', 'fun_caves:sky_iron', 'fun_caves:sky_iron', 'default:obsidian'},
|
{'fun_caves:aquamarine', 'fun_caves:garnet', 'fun_caves:zoisite', 'fun_caves:coral_gem', 'fun_caves:moonstone', 'fun_caves:pure_copper', 'fun_caves:sky_iron', 'fun_caves:sky_iron', 'fun_caves:sky_iron', 'fun_caves:sky_iron', 'default:obsidian'},
|
||||||
|
@ -154,90 +162,35 @@ function unionfind(max)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Now back to the actual fortress code...
|
local function maze_floor(y2, minp, maxp, data, area, node)
|
||||||
|
|
||||||
fun_caves.fortress = function(minp, maxp, data, area, node)
|
|
||||||
-- hungry maze
|
|
||||||
-- chests (w traps)
|
|
||||||
-- step traps (math based)
|
|
||||||
-- hidden doors/downs
|
|
||||||
-- hot/ice floors
|
|
||||||
-- torches
|
|
||||||
--
|
|
||||||
local level = math.min(6, math.ceil(maxp.y / math.floor(max_depth / -6)))
|
|
||||||
local n = 16
|
|
||||||
local walls = {}
|
|
||||||
local inner_floor = node['fun_caves:dungeon_floor_1']
|
|
||||||
local outer_wall = node['fun_caves:dungeon_wall_2']
|
|
||||||
local inner_wall = node['fun_caves:dungeon_wall_1']
|
|
||||||
local treasure_count = 0
|
|
||||||
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
|
||||||
local floor_1 = minetest.get_perlin_map(floor_noise_1, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
|
|
||||||
|
|
||||||
for y2 = 0, n-1 do
|
|
||||||
local floor_type = math.random(20)
|
|
||||||
|
|
||||||
--for y2 = 0, 0 do
|
|
||||||
-- walls is zero-based.
|
-- walls is zero-based.
|
||||||
for i = 0, 2 * n * n - 1 do
|
local walls = {}
|
||||||
|
for i = 0, 2 * cells * cells - 1 do
|
||||||
walls[i] = i
|
walls[i] = i
|
||||||
end
|
end
|
||||||
table.shuffle(walls)
|
table.shuffle(walls)
|
||||||
|
|
||||||
local dox, doz = math.random(0, n-1), math.random(0, n-1)
|
local set = unionfind(cells * cells)
|
||||||
for z = minp.z, maxp.z do
|
|
||||||
for y = minp.y + y2 * 5, minp.y + y2 * 5 + 4 do
|
|
||||||
local ivm = area:index(minp.x, y, z)
|
|
||||||
for x = minp.x, maxp.x do
|
|
||||||
if x == minp.x or z == minp.z or x == maxp.x or z == maxp.z then
|
|
||||||
data[ivm] = outer_wall
|
|
||||||
elseif (y - minp.y) % 5 == 0 then
|
|
||||||
if math.floor((z - minp.z) / 5) == doz and math.floor((x - minp.x) / 5) == dox and (z - minp.z) % 5 ~= 0 and (x - minp.x) % 5 ~= 0 and y ~= minp.y then
|
|
||||||
data[ivm] = node["air"]
|
|
||||||
else
|
|
||||||
data[ivm] = inner_floor
|
|
||||||
end
|
|
||||||
elseif (z - minp.z) % 5 == 0 or (x - minp.x) % 5 == 0 then
|
|
||||||
if y2 == 0 and math.random(3000) == 1 then
|
|
||||||
treasure_count = treasure_count + 1
|
|
||||||
data[ivm] = node['fun_caves:coffer']
|
|
||||||
elseif floor_type == 1 and level > 3 then
|
|
||||||
data[ivm] = node['fun_caves:dungeon_wall_invisible']
|
|
||||||
elseif floor_type == 1 then
|
|
||||||
data[ivm] = node['fun_caves:dungeon_wall_transparent']
|
|
||||||
elseif floor_type ~= 3 then
|
|
||||||
data[ivm] = inner_wall
|
|
||||||
end
|
|
||||||
else
|
|
||||||
data[ivm] = node["air"]
|
|
||||||
end
|
|
||||||
ivm = ivm + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local set = unionfind(n * n)
|
|
||||||
|
|
||||||
-- Remove walls in a continuous path.
|
-- Remove walls in a continuous path.
|
||||||
if floor_type ~= 3 then
|
for m = 0, #walls-1 do
|
||||||
for m = 0, #walls do
|
|
||||||
local c = walls[m]
|
local c = walls[m]
|
||||||
local a = math.floor(c / 2)
|
local a = math.floor(c / 2)
|
||||||
local i = a % n
|
local i = a % cells
|
||||||
local j = math.floor(a / n)
|
local j = math.floor(a / cells)
|
||||||
local u = c % 2 == 0 and 1 or 0
|
local u = c % 2 == 0 and 1 or 0
|
||||||
local v = c % 2 == 1 and 1 or 0
|
local v = c % 2 == 1 and 1 or 0
|
||||||
local b = a + u + n * v
|
local b = a + u + cells * v
|
||||||
if i < n - u and j < n - v and set:find(a) ~= set:find(b) then
|
if i < cells - u and j < cells - v and set:find(a) ~= set:find(b) then
|
||||||
set:union(a, b)
|
set:union(a, b)
|
||||||
local x = (i + u) * 5 + minp.x
|
local x = (i + u) * cell_size + minp.x
|
||||||
local y = minp.y + y2 * 5
|
local y = minp.y + y2 * cell_size
|
||||||
local z = (j + v) * 5 + minp.z
|
local z = (j + v) * cell_size + minp.z
|
||||||
|
|
||||||
for z1 = z + (1-v), z + (1-v) * 4 do
|
for z1 = z + (1-v), z + (1-v) * (cell_size - 1) do
|
||||||
for y1 = y + 1, y + 4 do
|
for y1 = y + 1, y + (cell_size - 1) do
|
||||||
local ivm = area:index(x + (1-u), y1, z1)
|
local ivm = area:index(x + (1-u), y1, z1)
|
||||||
for x1 = x + (1-u), x + (1-u) * 4 do
|
for x1 = x + (1-u), x + (1-u) * (cell_size - 1) do
|
||||||
if x1 < maxp.x and z1 < maxp.z and x1 > minp.x and z1 > minp.z then
|
if x1 < maxp.x and z1 < maxp.z and x1 > minp.x and z1 > minp.z then
|
||||||
data[ivm] = node["air"]
|
data[ivm] = node["air"]
|
||||||
end
|
end
|
||||||
|
@ -249,11 +202,151 @@ fun_caves.fortress = function(minp, maxp, data, area, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local designs = {
|
||||||
|
{
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
local function design_floor(y2, minp, maxp, data, area, node)
|
||||||
|
local design = designs[math.random(#designs)]
|
||||||
|
|
||||||
|
local py = minp.y + y2 * cell_size
|
||||||
|
for z = 1, 10 do
|
||||||
|
for x = 1, 9 do
|
||||||
|
if design[z * 2 - 1][x * 2] == 0 then
|
||||||
|
local px = minp.x + x * cell_size
|
||||||
|
local pz = minp.z + (z - 1) * cell_size
|
||||||
|
for z1 = pz + 1, pz + cell_size - 1 do
|
||||||
|
local ivm = area:index(px, py + 1, z1)
|
||||||
|
for y1 = py + 1, py + cell_size - 1 do
|
||||||
|
data[ivm] = node['air']
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for z = 1, 9 do
|
||||||
|
for x = 1, 10 do
|
||||||
|
if design[z * 2][x * 2 - 1] == 0 then
|
||||||
|
local px = minp.x + (x - 1) * cell_size
|
||||||
|
local pz = minp.z + z * cell_size
|
||||||
|
for x1 = px + 1, px + cell_size - 1 do
|
||||||
|
local ivm = area:index(x1, py + 1, pz)
|
||||||
|
for y1 = py + 1, py + cell_size - 1 do
|
||||||
|
data[ivm] = node['air']
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for z = 1, 9 do
|
||||||
|
for x = 1, 9 do
|
||||||
|
if design[z * 2][x * 2] == 0 then
|
||||||
|
local px = minp.x + x * cell_size
|
||||||
|
local pz = minp.z + z * cell_size
|
||||||
|
local ivm = area:index(px, py + 1, pz)
|
||||||
|
for y1 = py + 1, py + cell_size - 1 do
|
||||||
|
data[ivm] = node['air']
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
fun_caves.fortress = function(minp_in, maxp_in, data, area, node)
|
||||||
|
-- hungry maze
|
||||||
|
-- chests (w traps)
|
||||||
|
-- step traps (math based)
|
||||||
|
-- hidden doors/downs
|
||||||
|
-- hot/ice floors
|
||||||
|
-- torches
|
||||||
|
--
|
||||||
|
local minp = vector.add(minp_in, 10)
|
||||||
|
local maxp = vector.subtract(maxp_in, 9)
|
||||||
|
local level = math.min(6, math.ceil(maxp.y / math.floor(max_depth / -6)))
|
||||||
|
local inner_floor = node['fun_caves:dungeon_floor_1']
|
||||||
|
local outer_wall = node['fun_caves:dungeon_wall_2']
|
||||||
|
local inner_wall = node['fun_caves:dungeon_wall_1']
|
||||||
|
local treasure_count = 0
|
||||||
|
local csize = vector.add(vector.subtract(maxp_in, minp_in), 1)
|
||||||
|
local floor_1 = minetest.get_perlin_map(floor_noise_1, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp_in.x, y=minp_in.z})
|
||||||
|
|
||||||
|
for y2 = 0, cells-1 do
|
||||||
|
local floor_type = math.random(20)
|
||||||
|
|
||||||
|
local dox, doz = math.random(0, cells-1), math.random(0, cells-1)
|
||||||
|
for z = minp.z, maxp.z do
|
||||||
|
for y = minp.y + y2 * cell_size, minp.y + y2 * cell_size + (cell_size - 1) do
|
||||||
|
local ivm = area:index(minp.x, y, z)
|
||||||
|
for x = minp.x, maxp.x do
|
||||||
|
if x == minp.x or z == minp.z or x == maxp.x or z == maxp.z then
|
||||||
|
data[ivm] = outer_wall
|
||||||
|
elseif (y - minp.y) % cell_size == 0 then
|
||||||
|
if math.floor((z - minp.z) / cell_size) == doz and math.floor((x - minp.x) / cell_size) == dox and (z - minp.z) % cell_size ~= 0 and (x - minp.x) % cell_size ~= 0 and y ~= minp.y then
|
||||||
|
data[ivm] = node["air"]
|
||||||
|
else
|
||||||
|
data[ivm] = inner_floor
|
||||||
|
end
|
||||||
|
elseif floor_type ~= 3 and ((z - minp.z) % cell_size == 0 or (x - minp.x) % cell_size == 0) then
|
||||||
|
if y == minp.y + y2 * cell_size + 3 and ((z - minp.z) % cell_size == 3 or (x - minp.x) % cell_size == 3) and math.random(5) == 1 then
|
||||||
|
data[ivm] = node['fun_caves:dungeon_light']
|
||||||
|
elseif floor_type == 1 and level > 3 then
|
||||||
|
data[ivm] = node['fun_caves:dungeon_wall_invisible']
|
||||||
|
elseif floor_type == 1 then
|
||||||
|
data[ivm] = node['fun_caves:dungeon_wall_transparent']
|
||||||
|
elseif floor_type ~= 3 then
|
||||||
|
data[ivm] = inner_wall
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if y2 == 0 and y == minp.y + y2 * cell_size + 1 and data[ivm - area.ystride] ~= node['air'] and math.random(300) == 1 then
|
||||||
|
treasure_count = treasure_count + 1
|
||||||
|
data[ivm] = node['fun_caves:coffer']
|
||||||
|
else
|
||||||
|
data[ivm] = node["air"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ivm = ivm + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if floor_type ~= 3 then
|
||||||
|
local wall_type = math.random(2)
|
||||||
|
|
||||||
|
if wall_type == 1 then
|
||||||
|
maze_floor(y2, minp, maxp, data, area, node)
|
||||||
|
else
|
||||||
|
design_floor(y2, minp, maxp, data, area, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local index = 0
|
local index = 0
|
||||||
for z = minp.z + 1, maxp.z - 1 do
|
for z = minp.z + 1, maxp.z - 1 do
|
||||||
for x = minp.x + 1, maxp.x - 1 do
|
for x = minp.x + 1, maxp.x - 1 do
|
||||||
index = index + 1
|
local ivm = area:index(x, minp.y + y2 * cell_size, z)
|
||||||
local ivm = area:index(x, minp.y + y2 * 5, z)
|
|
||||||
|
|
||||||
if floor_type == 2 then
|
if floor_type == 2 then
|
||||||
if data[ivm] ~= node['air'] and data[ivm + area.ystride] == node['air'] then
|
if data[ivm] ~= node['air'] and data[ivm + area.ystride] == node['air'] then
|
||||||
|
@ -264,13 +357,16 @@ fun_caves.fortress = function(minp, maxp, data, area, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif floor_type == 3 then
|
elseif floor_type == 3 then
|
||||||
if data[ivm] ~= node['air'] then
|
if (y2 < 9 or (z - minp_in.z) > 16 or (x - minp_in.x) > 16) and data[ivm] ~= node['air'] then
|
||||||
for i = 1, math.min(4, math.floor(4 * math.abs(floor_1[index]))) do
|
local index = (z - minp_in.z) * csize.x + x - minp_in.x
|
||||||
|
for i = 1, math.min((cell_size - 1), math.floor((cell_size - 1) * math.abs(floor_1[index]))) do
|
||||||
|
if data[ivm + area.ystride * i] == node['air'] then
|
||||||
data[ivm + area.ystride * i] = node['default:dirt']
|
data[ivm + area.ystride * i] = node['default:dirt']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
elseif floor_type == 4 then
|
elseif floor_type == 4 then
|
||||||
for i = 1, 4 do
|
for i = 1, (cell_size - 1) do
|
||||||
if data[ivm + area.ystride * i] == node['air'] then
|
if data[ivm + area.ystride * i] == node['air'] then
|
||||||
data[ivm + area.ystride * i] = node['default:water_source']
|
data[ivm + area.ystride * i] = node['default:water_source']
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,8 +52,7 @@ fun_caves.is_fortress = function(pos, cs)
|
||||||
local y = math.floor((pos.y + offset) / cs.y)
|
local y = math.floor((pos.y + offset) / cs.y)
|
||||||
|
|
||||||
-- Fortresses show up below ground.
|
-- Fortresses show up below ground.
|
||||||
-- Calls from the first dungeon level should return false.
|
if y > fortress_depth then
|
||||||
if y > fortress_depth or (pos.y + offset) % cs.y > cs.y - 5 then
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,9 +60,7 @@ fun_caves.is_fortress = function(pos, cs)
|
||||||
local z = math.floor((pos.z + offset) / cs.z)
|
local z = math.floor((pos.z + offset) / cs.z)
|
||||||
|
|
||||||
local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z})
|
local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z})
|
||||||
if fun_caves.DEBUG and math.floor((n * 10000) % 4) == 1 then
|
if math.floor((n * 10000) % (fun_caves.DEBUG and 4 or 19)) == 1 then
|
||||||
return true
|
|
||||||
elseif math.floor((n * 10000) % 19) == 1 then
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -43,28 +43,21 @@ local function teleporter(user, area, power)
|
||||||
elseif area == 'dungeon' then
|
elseif area == 'dungeon' then
|
||||||
newpos = {}
|
newpos = {}
|
||||||
local base_pos = table.copy(pos)
|
local base_pos = table.copy(pos)
|
||||||
|
base_pos.x = base_pos.x - (base_pos.x + 32) % 80 + 12
|
||||||
|
base_pos.z = base_pos.z - (base_pos.z + 32) % 80 + 12
|
||||||
if power > 0 then
|
if power > 0 then
|
||||||
base_pos.y = fun_caves.underzones[({'Caina','Phlegethos','Dis','Minauros', 'Phlegethos','Styx'})[power]].lower_bound
|
base_pos.y = fun_caves.underzones[({'Caina','Phlegethos','Dis','Minauros', 'Phlegethos','Styx'})[power]].lower_bound
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check below the top level
|
base_pos.y = base_pos.y - (base_pos.y + 32) % 80 - 15
|
||||||
base_pos.y = base_pos.y - (base_pos.y + 32) % 80 - 12
|
|
||||||
|
|
||||||
for i = 1, 4000 do
|
for i = 1, 8000 do
|
||||||
newpos = {
|
newpos = {
|
||||||
x = base_pos.x + (math.random(5) - math.random(5)) * 80,
|
x = base_pos.x + (math.random(5) - math.random(5)) * 80,
|
||||||
y = base_pos.y - math.random(50) * 80,
|
y = base_pos.y - math.random(50) * 80,
|
||||||
z = base_pos.z + (math.random(5) - math.random(5)) * 80,
|
z = base_pos.z + (math.random(5) - math.random(5)) * 80,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- avoid walls
|
|
||||||
if newpos.x % 16 == 0 then
|
|
||||||
newpos.x = newpos.x + 1
|
|
||||||
end
|
|
||||||
if newpos.z % 16 == 0 then
|
|
||||||
newpos.z = newpos.z + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if fun_caves.is_fortress(newpos) then
|
if fun_caves.is_fortress(newpos) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
@ -73,9 +66,6 @@ local function teleporter(user, area, power)
|
||||||
if not fun_caves.is_fortress(newpos) then
|
if not fun_caves.is_fortress(newpos) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- place on the top level
|
|
||||||
newpos.y = newpos.y + 10
|
|
||||||
elseif area == 'underworld' then
|
elseif area == 'underworld' then
|
||||||
local good = false
|
local good = false
|
||||||
local base_pos = table.copy(pos)
|
local base_pos = table.copy(pos)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue