Add more dungeon-like fortresses.

This commit is contained in:
Duane 2016-08-01 03:54:05 -05:00
parent 138858c2a2
commit 5abe211fb6
5 changed files with 288 additions and 188 deletions

View file

@ -162,45 +162,45 @@ minetest.register_globalstep(function(dtime)
return
end
local do_fortress_spawns = (fun_caves.fortress_spawns and #fun_caves.fortress_spawns > 0)
--local do_fortress_spawns = (fun_caves.fortress_spawns and #fun_caves.fortress_spawns > 0)
for i = 1, #players do
local player = players[i]
local pos = player:getpos()
local player_name = player:get_player_name()
if do_fortress_spawns and is_fortress(pos) and dps_count % monster_delay == 0 then
-- How many mobs are up at the moment? This is a rough check.
local mob_count = 0
for _, mob in pairs(minetest.luaentities) do
if mob.health and mob.started_in_fortress then
local dist = vector.subtract(pos, mob.object:getpos())
local dist2 = math.max(math.abs(dist.x), math.abs(dist.y * 5), math.abs(dist.z))
if dist2 < 30 then
mob_count = mob_count + 1
end
end
end
--if do_fortress_spawns and is_fortress(pos) and dps_count % monster_delay == 0 then
-- -- How many mobs are up at the moment? This is a rough check.
-- local mob_count = 0
-- for _, mob in pairs(minetest.luaentities) do
-- if mob.health and mob.started_in_fortress then
-- local dist = vector.subtract(pos, mob.object:getpos())
-- local dist2 = math.max(math.abs(dist.x), math.abs(dist.y * 5), math.abs(dist.z))
-- if dist2 < 30 then
-- mob_count = mob_count + 1
-- end
-- end
-- end
-- If we need more, spawn them.
if mob_count < fortress_mob_count then
local f1 = vector.subtract(pos, fortress_floor)
local f2 = vector.add(pos, fortress_floor)
local floor_nodes = minetest.find_nodes_in_area_under_air(f1, f2, fortress_group)
if not (floor_nodes and type(floor_nodes) == 'table') then
return
end
-- -- If we need more, spawn them.
-- if mob_count < fortress_mob_count then
-- local f1 = vector.subtract(pos, fortress_floor)
-- local f2 = vector.add(pos, fortress_floor)
-- local floor_nodes = minetest.find_nodes_in_area_under_air(f1, f2, fortress_group)
-- if not (floor_nodes and type(floor_nodes) == 'table') then
-- return
-- end
if #floor_nodes > 0 then
local new_mob_pos = floor_nodes[math.random(#floor_nodes)]
new_mob_pos.y = new_mob_pos.y + 2
--------------------------------------
-- Mobs are treated exacty the same. Spawn harder ones differently?
--------------------------------------
local name = fun_caves.fortress_spawns[math.random(#fun_caves.fortress_spawns)]
minetest.add_entity(new_mob_pos, name)
end
end
end
-- if #floor_nodes > 0 then
-- local new_mob_pos = floor_nodes[math.random(#floor_nodes)]
-- new_mob_pos.y = new_mob_pos.y + 2
-- --------------------------------------
-- -- Mobs are treated exacty the same. Spawn harder ones differently?
-- --------------------------------------
-- local name = fun_caves.fortress_spawns[math.random(#fun_caves.fortress_spawns)]
-- minetest.add_entity(new_mob_pos, name)
-- end
-- end
--end
if pos.y >= 11168 and pos.y <= 15168 then
if not players_in_orbit[player_name] then

View file

@ -7,18 +7,7 @@ fun_caves.cave_noise_2 = {offset = 0, scale = 1, seed = -8402, spread = {x = 40,
local cave_noise_3 = {offset = 15, scale = 10, seed = 3721, spread = {x = 40, y = 40, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
local ground_nodes = {}
ground_nodes[minetest.get_content_id('default:stone')] = true
ground_nodes[minetest.get_content_id('default:desert_stone')] = true
ground_nodes[minetest.get_content_id('default:sandstone')] = true
ground_nodes[minetest.get_content_id('default:dirt')] = true
ground_nodes[minetest.get_content_id('default:sand')] = true
ground_nodes[minetest.get_content_id('default:dirt_with_grass')] = true
ground_nodes[minetest.get_content_id('default:dirt_with_snow')] = true
ground_nodes[minetest.get_content_id('default:dirt_with_dry_grass')] = true
fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone)
fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone, ground_nodes)
if not (minp and maxp and data and area and node and type(data) == 'table' and fun_caves.underzones) then
return
end
@ -58,21 +47,6 @@ fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone)
index = index + 1
local height = heightmap[index]
if height and height < maxp.y - 1 and height > minp.y then
--nop
else
height = - max_depth
local ivm2 = area:index(x, maxp.y + 8, z)
for y = maxp.y + 8, minp.y - 8, -1 do
if ground_nodes[data[ivm2]] then
height = (y < maxp.y + 8) and y or max_depth
break
end
ivm2 = ivm2 - area.ystride
end
heightmap[index] = height
end
if crater then
local dist = crater.y - math.sqrt((x - crater.x) ^ 2 + (z - crater.z) ^ 2)
if dist > 0 and (height > maxp.y or height < minp.y + crater.y) then

View file

@ -1,6 +1,7 @@
local max_depth = 31000
local cells = 10
local cell_size = 60 / cells
local fortress_depth = -1 -- close to y / 80
if fun_caves.path then
@ -9,21 +10,87 @@ if fun_caves.path then
end
fun_caves.is_fortress = function(pos, cs)
if not pos then
return
end
-- Fix this to get csize, somehow.
-- Remember that this function may be called
-- before any chunks are generated.
pos = vector.round(pos)
local cs = cs or {x=80, y=80, z=80}
local offset = math.floor(cs.y / 2) - 8 + 1
local x = math.floor((pos.x + offset) / cs.x)
local z = math.floor((pos.z + offset) / cs.z)
return true
--local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z})
--if not (n and type(n) == 'number') then
-- return
--end
--if math.floor((n * 10000) % 13) == 1 then
-- return true
--end
--return false
end
--fun_caves.is_fortress = function(pos, cs)
-- if not pos then
-- return
-- end
--
-- -- Fix this to get csize, somehow.
-- -- Remember that this function may be called
-- -- before any chunks are generated.
--
-- pos = vector.round(pos)
-- local cs = cs or {x=80, y=80, z=80}
-- local offset = math.floor(cs.y / 2) - 8 + 1
--
-- local y = math.floor((pos.y + offset) / cs.y)
--
-- -- Fortresses show up below ground.
-- if y > fortress_depth then
-- return false
-- end
--
-- local x = math.floor((pos.x + offset) / cs.x)
-- local z = math.floor((pos.z + offset) / cs.z)
--
-- local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z})
-- if not (n and type(n) == 'number') then
-- return
-- end
--
-- if math.floor((n * 10000) % 13) == 1 then
-- return true
-- end
--
-- return false
--end
-- dungeon floor, basic
newnode = fun_caves.clone_node("default:stone")
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.legacy_mineral = false
newnode.groups = {fortress = 1}
minetest.register_node("fun_caves:dungeon_floor_1", newnode)
-- dungeon walls, basic
newnode = fun_caves.clone_node("default:sandstone")
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.groups = {fortress = 1}
minetest.register_node("fun_caves:dungeon_wall_1", newnode)
-- dungeon walls, type 2
newnode = fun_caves.clone_node("default:desert_stone")
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.groups = {fortress = 1}
minetest.register_node("fun_caves:dungeon_wall_2", newnode)
@ -368,101 +435,53 @@ fun_caves.fortress = function(minp_in, maxp_in, data, area, node)
return
end
-- 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 minp = table.copy(minp_in)
minp.x = minp.x + 10
minp.z = minp.z + 10
local maxp = table.copy(maxp_in)
maxp.x = maxp.x - 9
maxp.z = maxp.z - 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})
if not floor_1 then
return
for z = minp.z - 1, maxp.z + 1 do
for y = minp.y - 1, maxp.y + 1 do
local ivm = area:index(minp.x - 1, y, z)
for x = minp.x - 1, maxp.x + 1 do
data[ivm] = node['default:cobble']
ivm = ivm + 1
end
end
end
for y2 = 0, cells-1 do
local floor_type = math.random(20)
for cz = 0, 9 do
local oz = minp.z + cz * 6
for cy = 0, 13 do
local oy = minp.y + cy * 6
for cx = 0, 9 do
local ox = minp.x + cx * 6
local room = math.random(2)
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(200) == 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
for rz = 0, 5 do
for ry = 0, 5 do
local ivm = area:index(ox, oy + ry, oz + rz)
if floor_type ~= 3 then
local wall_type = math.random(#designs + 1)
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
for z = minp.z + 1, maxp.z - 1 do
for x = minp.x + 1, maxp.x - 1 do
local ivm = area:index(x, minp.y + y2 * cell_size, z)
if floor_type == 2 then
if data[ivm] ~= node['air'] and data[ivm + area.ystride] == node['air'] then
if level > 3 then
data[ivm + area.ystride] = node['default:lava_source']
else
data[ivm + area.ystride] = node['fun_caves:hot_cobble']
end
end
elseif floor_type == 3 then
if (y2 < 9 or (z - minp_in.z) > 16 or (x - minp_in.x) > 16) and data[ivm] ~= node['air'] then
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']
for rx = 0, 5 do
if room == 1 and (ry == 0 or ry == 5) then
data[ivm] = node['fun_caves:dungeon_floor_1']
elseif room == 1 then
data[ivm] = node['air']
elseif room == 2 and (ry == 1 or ry == 2) and (rz == 2 or rz == 3 or rx == 2 or rx == 3) and (ox + rx >= minp.x + 2 and ox + rx <= maxp.x - 3 and oz + rz >= minp.z + 2 and oz + rz <= maxp.z - 3) then
data[ivm] = node['air']
elseif room == 2 then
data[ivm] = node['fun_caves:dungeon_wall_1']
end
end
end
elseif floor_type == 4 then
for i = 1, (cell_size - 1) do
if data[ivm + area.ystride * i] == node['air'] then
data[ivm + area.ystride * i] = node['default:water_source']
ivm = ivm + 1
end
end
end
@ -470,3 +489,112 @@ fun_caves.fortress = function(minp_in, maxp_in, data, area, node)
end
end
end
--fun_caves.fortress = function(minp_in, maxp_in, data, area, node)
-- if not (minp_in and maxp_in and data and area and node and type(data) == 'table') then
-- return
-- end
--
-- -- 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})
-- if not floor_1 then
-- return
-- end
--
-- 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(200) == 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(#designs + 1)
--
-- 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
-- for z = minp.z + 1, maxp.z - 1 do
-- for x = minp.x + 1, maxp.x - 1 do
-- local ivm = area:index(x, minp.y + y2 * cell_size, z)
--
-- if floor_type == 2 then
-- if data[ivm] ~= node['air'] and data[ivm + area.ystride] == node['air'] then
-- if level > 3 then
-- data[ivm + area.ystride] = node['default:lava_source']
-- else
-- data[ivm + area.ystride] = node['fun_caves:hot_cobble']
-- end
-- end
-- elseif floor_type == 3 then
-- if (y2 < 9 or (z - minp_in.z) > 16 or (x - minp_in.x) > 16) and data[ivm] ~= node['air'] then
-- 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']
-- end
-- end
-- end
-- elseif floor_type == 4 then
-- for i = 1, (cell_size - 1) do
-- if data[ivm + area.ystride * i] == node['air'] then
-- data[ivm + area.ystride * i] = node['default:water_source']
-- end
-- end
-- end
-- end
-- end
-- end
--end

View file

@ -1,6 +1,4 @@
local fortress_depth = -1 -- close to y / 80
local max_depth = 31000
local seed_noise = {offset = 0, scale = 32768, seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, persist = 0.4, lacunarity = 2}
local fortress_noise = {offset = 0, scale = 1, seed = -4082, spread = {x = 7, y = 7, z = 7}, octaves = 4, persist = 1, lacunarity = 2}
@ -45,41 +43,6 @@ end
-- end
--end
fun_caves.is_fortress = function(pos, cs)
if not pos then
return
end
-- Fix this to get csize, somehow.
-- Remember that this function may be called
-- before any chunks are generated.
pos = vector.round(pos)
local cs = cs or {x=80, y=80, z=80}
local offset = math.floor(cs.y / 2) - 8 + 1
local y = math.floor((pos.y + offset) / cs.y)
-- Fortresses show up below ground.
if y > fortress_depth then
return false
end
local x = math.floor((pos.x + offset) / cs.x)
local z = math.floor((pos.z + offset) / cs.z)
local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z})
if not (n and type(n) == 'number') then
return
end
if math.floor((n * 10000) % 13) == 1 then
return true
end
return false
end
fun_caves.place_schematic = function(minp, maxp, data, p2data, area, node, pos, schem, center)
if not (minp and maxp and data and p2data and area and node and pos and schem and type(data) == 'table' and type(p2data) == 'table' and type(schem) == 'table') then
return
@ -365,6 +328,17 @@ fun_caves.cave_biomes = {
}
local ground_nodes = {}
ground_nodes[minetest.get_content_id('default:stone')] = true
ground_nodes[minetest.get_content_id('default:desert_stone')] = true
ground_nodes[minetest.get_content_id('default:sandstone')] = true
ground_nodes[minetest.get_content_id('default:dirt')] = true
ground_nodes[minetest.get_content_id('default:sand')] = true
ground_nodes[minetest.get_content_id('default:dirt_with_grass')] = true
ground_nodes[minetest.get_content_id('default:dirt_with_snow')] = true
ground_nodes[minetest.get_content_id('default:dirt_with_dry_grass')] = true
local function generate(p_minp, p_maxp, seed)
if not (p_minp and p_maxp and seed) then
return
@ -410,6 +384,30 @@ local function generate(p_minp, p_maxp, seed)
end
end
-- Correct heightmap.
local index = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
local height = heightmap[index]
if height and height < maxp.y - 1 and height > minp.y then
--nop
else
height = - max_depth
local ivm2 = area:index(x, maxp.y + 8, z)
for y = maxp.y + 8, minp.y - 8, -1 do
if ground_nodes[data[ivm2]] then
height = (y < maxp.y + 8) and y or max_depth
break
end
ivm2 = ivm2 - area.ystride
end
heightmap[index] = height
end
end
end
local aster = false
if minp.y > 17200 then
-- nop
@ -421,12 +419,11 @@ local function generate(p_minp, p_maxp, seed)
elseif minp.y > 4000 and fun_caves.cloudgen then
write = fun_caves.cloudgen(minp, maxp, data, p2data, area, node)
elseif not underzone and fun_caves.is_fortress(minp, csize) and fun_caves.fortress then
--if not underzone then
fun_caves.fortress(minp, maxp, data, area, node)
write = true
elseif fun_caves.cavegen and fun_caves.decogen and fun_caves.treegen then
local write_cave, write_deco, write_tree, write_pyr, write_vill, h2
write_cave, h2 = fun_caves.cavegen(minp, maxp, data, area, node, heightmap, underzone)
write_cave, h2 = fun_caves.cavegen(minp, maxp, data, area, node, heightmap, underzone, ground_nodes)
if h2 then
heightmap = h2
end
@ -455,7 +452,7 @@ local function generate(p_minp, p_maxp, seed)
vm:set_param2_data(p2data)
end
if fun_caves.DEBUG then
if true or fun_caves.DEBUG then
vm:set_lighting({day = 15, night = 15})
else
-- set_lighting causes lighting artifacts,

View file

@ -851,6 +851,7 @@ local t_mobs = {
}
for _, mob in pairs(t_mobs) do
if minetest.registered_entities[mob] then
fun_caves.fortress_spawns[#fun_caves.fortress_spawns+1] = mob
mobs:register_spawn(mob, {"fun_caves:dungeon_floor_1"}, 20, 0, 2000, 5, 31000)
--fun_caves.fortress_spawns[#fun_caves.fortress_spawns+1] = mob
end
end