Speedify dungeons a little and fix chest places (linear, not square)

This commit is contained in:
kay27 2021-03-07 06:00:49 +04:00
parent 45c0c576f7
commit 66febf158a
1 changed files with 70 additions and 39 deletions

View File

@ -108,7 +108,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Check floor and ceiling: Must be *completely* solid -- Check floor and ceiling: Must be *completely* solid
local y_floor = y local y_floor = y
local y_ceiling = y + dim.y + 1 local y_ceiling = y + dim.y + 1
if check then for tx = x, x + dim.x do for tz = z, z + dim.z do if check then for tx = x+1, x+dim.x do for tz = z+1, z+dim.z do
if not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_floor , z = tz}).name].walkable if not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_floor , z = tz}).name].walkable
or not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end or not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end
end end end end end end
@ -121,36 +121,59 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- so entities can get through. -- so entities can get through.
local corners = {} local corners = {}
local walls = { local x2,z2 = x+dim.x+1, z+dim.z+1
-- walls along x axis (contain corners)
{ x, x+dim.x+1, "x", "z", z },
{ x, x+dim.x+1, "x", "z", z+dim.z+1 },
-- walls along z axis (exclude corners)
{ z+1, z+dim.z, "z", "x", x },
{ z+1, z+dim.z, "z", "x", x+dim.x+1 },
}
for w=1, #walls do if mcl_mapgen_core.get_node({x=x, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z}).name == "air" then
local wall = walls[w] openings_counter = openings_counter + 1
for iter = wall[1], wall[2] do if not openings[x] then openings[x]={} end
local pos = {} openings[x][z] = true
pos[wall[3]] = iter table.insert(corners, {x=x, z=z})
pos[wall[4]] = wall[5] end
pos.y = y+1 if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x2] then openings[x2]={} end
openings[x2][z] = true
table.insert(corners, {x=x2, z=z})
end
if mcl_mapgen_core.get_node({x=x, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x] then openings[x]={} end
openings[x][z2] = true
table.insert(corners, {x=x, z=z2})
end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x2] then openings[x2]={} end
openings[x2][z2] = true
table.insert(corners, {x=x2, z=z2})
end
if openings[pos.x] == nil then openings[pos.x] = {} end for wx = x+1, x+dim.x do
local doorname1 = mcl_mapgen_core.get_node(pos).name if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z}).name == "air" then
pos.y = y+2 openings_counter = openings_counter + 1
local doorname2 = mcl_mapgen_core.get_node(pos).name if check and openings_counter > 5 then return end
if doorname1 == "air" and doorname2 == "air" then if not openings[wx] then openings[wx]={} end
openings_counter = openings_counter + 1 openings[wx][z] = true
openings[pos.x][pos.z] = true end
if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z2}).name == "air" then
-- Record corners openings_counter = openings_counter + 1
if wall[3] == "x" and (iter == wall[1] or iter == wall[2]) then if check and openings_counter > 5 then return end
table.insert(corners, {x=pos.x, z=pos.z}) if not openings[wx] then openings[wx]={} end
end openings[wx][z2] = true
end end
end
for wz = z+1, z+dim.z do
if mcl_mapgen_core.get_node({x=x, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=wz}).name == "air" then
openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end
if not openings[x] then openings[x]={} end
openings[x][wz] = true
end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=wz}).name == "air" then
openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end
if not openings[x2] then openings[x2]={} end
openings[x2][wz] = true
end end
end end
@ -178,6 +201,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
openings[cx][czn] = true openings[cx][czn] = true
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if openings_counter < 5 then if openings_counter < 5 then
if not openings[cxn] then openings[cxn]={} end
openings[cxn][cz] = true openings[cxn][cz] = true
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
end end
@ -199,7 +223,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- We assign each position at the wall a number and each chest gets one of these numbers randomly -- We assign each position at the wall a number and each chest gets one of these numbers randomly
local totalChests = 2 -- this code strongly relies on this number being 2 local totalChests = 2 -- this code strongly relies on this number being 2
local totalChestSlots = (dim.x-1) * (dim.z-1) local totalChestSlots = (dim.x + dim.z - 2) * 2
local chestSlots = {} local chestSlots = {}
-- There is a small chance that both chests have the same slot. -- There is a small chance that both chests have the same slot.
-- In that case, we give a 2nd chance for the 2nd chest to get spawned. -- In that case, we give a 2nd chance for the 2nd chest to get spawned.
@ -237,7 +261,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Do not overwrite nodes with is_ground_content == false (e.g. bedrock) -- Do not overwrite nodes with is_ground_content == false (e.g. bedrock)
-- Exceptions: cobblestone and mossy cobblestone so neighborings dungeons nicely connect to each other -- Exceptions: cobblestone and mossy cobblestone so neighborings dungeons nicely connect to each other
local name = mcl_mapgen_core.get_node(p).name local name = mcl_mapgen_core.get_node(p).name
if name == "mcl_core:cobble" or name == "mcl_core:mossycobble" or minetest.registered_nodes[name].is_ground_content then if minetest.registered_nodes[name].is_ground_content or name == "mcl_core:cobble" or name == "mcl_core:mossycobble" then
-- Floor -- Floor
if ty == y then if ty == y then
if pr:next(1,4) == 1 then if pr:next(1,4) == 1 then
@ -251,16 +275,16 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
The solid blocks above the dungeon are considered as the ceiling. The solid blocks above the dungeon are considered as the ceiling.
It is possible (but rare) for a dungeon to generate below sand or gravel. ]] It is possible (but rare) for a dungeon to generate below sand or gravel. ]]
elseif ty > y and (tx == x or tx == maxx or (tz == z or tz == maxz)) then elseif tx == x or tz == z or tx == maxx or tz == maxz then
-- Check if it's an opening first -- Check if it's an opening first
if (not openings[tx][tz]) or ty == maxy then if (ty == maxy) or (not (openings[tx] and openings[tx][tz])) then
-- Place wall or ceiling -- Place wall or ceiling
minetest.swap_node(p, {name = "mcl_core:cobble"}) minetest.swap_node(p, {name = "mcl_core:cobble"})
elseif ty < maxy - 1 then elseif ty < maxy - 1 then
-- Normally the openings are already clear, but not if it is a corner -- Normally the openings are already clear, but not if it is a corner
-- widening. Make sure to clear at least the bottom 2 nodes of an opening. -- widening. Make sure to clear at least the bottom 2 nodes of an opening.
minetest.swap_node(p, {name = "air"}) if name ~= "air" then minetest.swap_node(p, {name = "air"}) end
elseif ty == maxy - 1 and mcl_mapgen_core.get_node(p).name ~= "air" then elseif name ~= "air" then
-- This allows for variation between 2-node and 3-node high openings. -- This allows for variation between 2-node and 3-node high openings.
minetest.swap_node(p, {name = "mcl_core:cobble"}) minetest.swap_node(p, {name = "mcl_core:cobble"})
end end
@ -268,6 +292,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Room interiour -- Room interiour
else else
if (ty==y+1) and (tx==x+1 or tx==maxx-1 or tz==z+1 or tz==maxz-1) and (currentChest < totalChests + 1) and (chestSlots[currentChest] == chestSlotCounter) then
currentChest = currentChest + 1
table.insert(chests, {x=tx, y=ty, z=tz})
else
minetest.swap_node(p, {name = "air"})
end
local forChest = ty==y+1 and (tx==x+1 or tx==maxx-1 or tz==z+1 or tz==maxz-1) local forChest = ty==y+1 and (tx==x+1 or tx==maxx-1 or tz==z+1 or tz==maxz-1)
-- Place next chest at the wall (if it was its chosen wall slot) -- Place next chest at the wall (if it was its chosen wall slot)
@ -275,7 +306,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
currentChest = currentChest + 1 currentChest = currentChest + 1
table.insert(chests, {x=tx, y=ty, z=tz}) table.insert(chests, {x=tx, y=ty, z=tz})
else else
minetest.swap_node(p, {name = "air"}) --minetest.swap_node(p, {name = "air"})
end end
if forChest then if forChest then
chestSlotCounter = chestSlotCounter + 1 chestSlotCounter = chestSlotCounter + 1
@ -341,9 +372,9 @@ local function dungeons_nodes(minp, maxp, blockseed)
local pr = PseudoRandom(blockseed) local pr = PseudoRandom(blockseed)
for a=1, attempts do for a=1, attempts do
local dim = dungeonsizes[pr:next(1, #dungeonsizes)] local dim = dungeonsizes[pr:next(1, #dungeonsizes)]
local x = pr:next(minp.x, maxp.x-dim.x-2) local x = pr:next(minp.x, maxp.x-dim.x-1)
local y = pr:next(ymin , ymax -dim.y-2) local y = pr:next(ymin , ymax -dim.y-1)
local z = pr:next(minp.z, maxp.z-dim.z-2) local z = pr:next(minp.z, maxp.z-dim.z-1)
local p1 = {x=x,y=y,z=z} local p1 = {x=x,y=y,z=z}
local p2 = {x = x+dim.x+1, y = y+dim.y+1, z = z+dim.z+1} local p2 = {x = x+dim.x+1, y = y+dim.y+1, z = z+dim.z+1}
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))