From 5abe211fb65ad406f0571caa3dd032592a1d6464 Mon Sep 17 00:00:00 2001 From: Duane Date: Mon, 1 Aug 2016 03:54:05 -0500 Subject: [PATCH] Add more dungeon-like fortresses. --- abms.lua | 64 +++++------ cavegen.lua | 28 +---- fortress.lua | 302 ++++++++++++++++++++++++++++++++++++--------------- mapgen.lua | 79 +++++++------- mobs.lua | 3 +- 5 files changed, 288 insertions(+), 188 deletions(-) diff --git a/abms.lua b/abms.lua index d357c7c..e5629d5 100644 --- a/abms.lua +++ b/abms.lua @@ -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 diff --git a/cavegen.lua b/cavegen.lua index abca851..f36ff9f 100644 --- a/cavegen.lua +++ b/cavegen.lua @@ -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 diff --git a/fortress.lua b/fortress.lua index 19babcf..0813b37 100644 --- a/fortress.lua +++ b/fortress.lua @@ -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 diff --git a/mapgen.lua b/mapgen.lua index 1dfe662..d62cb86 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -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, diff --git a/mobs.lua b/mobs.lua index 51e2c48..c09122f 100644 --- a/mobs.lua +++ b/mobs.lua @@ -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