364 lines
8.6 KiB
Lua
364 lines
8.6 KiB
Lua
|
-- Copyright 2015 Eduardo Mezêncio
|
||
|
|
||
|
---------------
|
||
|
-- Constants --
|
||
|
---------------
|
||
|
|
||
|
local modname = "em_dungeon_gen"
|
||
|
|
||
|
local terminal_rarity = 1
|
||
|
local roomsize = 6
|
||
|
local halfrs = math.floor(roomsize / 2)
|
||
|
local wallarea = (roomsize + 1) * (roomsize - 1)
|
||
|
|
||
|
local pit_floors_min, pit_floors_max = 4, 8
|
||
|
local pit_layer_size = pit_floors_max * roomsize
|
||
|
|
||
|
|
||
|
----------------------
|
||
|
-- Helper Functions --
|
||
|
----------------------
|
||
|
|
||
|
local function chance(num, den)
|
||
|
return (math.random(den) <= num)
|
||
|
end
|
||
|
|
||
|
---------------
|
||
|
-- Materials --
|
||
|
---------------
|
||
|
|
||
|
minetest.register_node("em_dungeon_gen:wall", {
|
||
|
drawtype = "glasslike",
|
||
|
tiles = {"em_dungeon_gen_wall.png"},
|
||
|
is_ground_content = false,
|
||
|
sounds = default.node_sound_stone_defaults(),
|
||
|
paramtype = "light",
|
||
|
sunlight_propagates = true,
|
||
|
is_ground_content = false,
|
||
|
light_source = 0,--default.LIGHT_MAX,
|
||
|
})
|
||
|
|
||
|
local c_air = minetest.get_content_id("air")
|
||
|
local c_cobble = minetest.get_content_id("em_dungeon_gen:wall")
|
||
|
local c_mossycobble = minetest.get_content_id("em_dungeon_gen:wall")
|
||
|
local c_torch = minetest.get_content_id("air")
|
||
|
local c_bar_ns = minetest.get_content_id("terminal:terminal")
|
||
|
local c_door = "air" --a
|
||
|
--local c_bar_ew = minetest.get_content_id("default:glass")
|
||
|
|
||
|
local function c_wall()
|
||
|
if chance(1,2) then
|
||
|
return c_cobble
|
||
|
else
|
||
|
return c_mossycobble
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local schematic_stairs = minetest.get_modpath(modname).."/schems/stairs.mts"
|
||
|
|
||
|
------------------
|
||
|
-- Change Spawn --
|
||
|
------------------
|
||
|
|
||
|
local spawn_x, spawn_y, spawn_z = halfrs, 1, halfrs
|
||
|
|
||
|
minetest.register_on_newplayer(function(player)
|
||
|
player:setpos({x = spawn_x, y = spawn_y, z = spawn_z})
|
||
|
end)
|
||
|
|
||
|
minetest.register_on_respawnplayer(function(player)
|
||
|
player:setpos({x = spawn_x, y = spawn_y, z = spawn_z})
|
||
|
return true
|
||
|
end)
|
||
|
|
||
|
|
||
|
-------------------------
|
||
|
-- Map Generation Init --
|
||
|
-------------------------
|
||
|
|
||
|
local mapseed
|
||
|
|
||
|
minetest.register_on_mapgen_init(function(mgparams)
|
||
|
-- if mgparams.mgname ~= "singlenode" then
|
||
|
-- minetest.set_mapgen_params({mgname="singlenode"})
|
||
|
-- end
|
||
|
mapseed = minetest.get_mapgen_params().seed
|
||
|
end)
|
||
|
|
||
|
--------------------
|
||
|
-- Map Generation --
|
||
|
--------------------
|
||
|
|
||
|
minetest.register_on_generated(function(minp, maxp, blockseed)
|
||
|
|
||
|
-- just for now, so that you can take a look from above :)
|
||
|
if minp.y < 20000 then return end
|
||
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||
|
local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
||
|
local data = vm:get_data()
|
||
|
|
||
|
local x_step = va:index(1,0,0) - va:index(0,0,0)
|
||
|
local y_step = va:index(0,1,0) - va:index(0,0,0)
|
||
|
local z_step = va:index(0,0,1) - va:index(0,0,0)
|
||
|
|
||
|
-------------------
|
||
|
-- Floor/Ceiling --
|
||
|
-------------------
|
||
|
|
||
|
math.randomseed(minp.x + minp.y^2 + minp.z^3)
|
||
|
|
||
|
for y = minp.y, maxp.y do
|
||
|
if y % roomsize == 0 then
|
||
|
for z = minp.z, maxp.z do
|
||
|
local index = va:index(minp.x, y, z)
|
||
|
for x = minp.x, maxp.x do
|
||
|
data[index] = c_wall()
|
||
|
index = index + x_step
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- I'm subtracting roomsize at the end here so that each chunk also
|
||
|
-- 'generates' one room outside of it. The reason is to build correctly
|
||
|
-- things that are in the block borders
|
||
|
local minx, miny, minz = minp.x, minp.y, minp.z
|
||
|
if minx % roomsize ~= 0 then minx = minx - (minx % roomsize) - roomsize end
|
||
|
if miny % roomsize ~= 0 then miny = miny - (miny % roomsize) - roomsize end
|
||
|
if minz % roomsize ~= 0 then minz = minz - (minz % roomsize) - roomsize end
|
||
|
|
||
|
------------------------------
|
||
|
-- Walls, Doors and Torches --
|
||
|
------------------------------
|
||
|
|
||
|
local doors, next_door = {}, 1
|
||
|
local stairs, next_stairs = {}, 1
|
||
|
|
||
|
local function place_stuff(x, y, z, ns)
|
||
|
|
||
|
-----------
|
||
|
-- Walls --
|
||
|
-----------
|
||
|
|
||
|
if chance(3,4) then
|
||
|
|
||
|
local xval, zval, step
|
||
|
local rect = {b = math.max(minp.y, y + 1),
|
||
|
t = math.min(maxp.y, y + roomsize - 1)}
|
||
|
|
||
|
if ns then
|
||
|
rect.l = math.max(minp.x, x)
|
||
|
rect.r = math.min(maxp.x, x + roomsize)
|
||
|
xval = rect.l
|
||
|
zval = z
|
||
|
step = x_step
|
||
|
else
|
||
|
rect.l = math.max(minp.z, z)
|
||
|
rect.r = math.min(maxp.z, z + roomsize)
|
||
|
xval = x
|
||
|
zval = rect.l
|
||
|
step = z_step
|
||
|
end
|
||
|
|
||
|
local wallnodes = 0
|
||
|
for yval = rect.b, rect.t do
|
||
|
local index = va:index(xval, yval, zval)
|
||
|
for x_or_z = rect.l, rect.r do
|
||
|
data[index] = c_wall()
|
||
|
wallnodes = wallnodes + 1
|
||
|
index = index + step
|
||
|
end
|
||
|
end
|
||
|
-- This will hopefully ensure that the random number
|
||
|
-- generator is always in the same "position" after
|
||
|
-- generating the wall
|
||
|
while wallnodes < wallarea do
|
||
|
math.random()
|
||
|
wallnodes = wallnodes + 1
|
||
|
end
|
||
|
|
||
|
-----------
|
||
|
-- Doors --
|
||
|
-----------
|
||
|
|
||
|
if chance(1,2) then
|
||
|
|
||
|
local coord = {x = x, y = y + 2, z = z}
|
||
|
|
||
|
if ns then coord.x = coord.x + halfrs
|
||
|
else coord.z = coord.z + halfrs end
|
||
|
|
||
|
-- Portal --
|
||
|
if va:contains(coord.x, coord.y, coord.z) then
|
||
|
data[va:index(coord.x, coord.y, coord.z)] = c_air end
|
||
|
coord.y = coord.y - 1
|
||
|
if va:contains(coord.x, coord.y, coord.z) then
|
||
|
data[va:index(coord.x, coord.y, coord.z)] = c_air end
|
||
|
|
||
|
-- Door (generated later) --
|
||
|
if chance(1,2) then
|
||
|
doors[next_door] = {x=coord.x, y=coord.y, z=coord.z, ns=ns}
|
||
|
next_door = next_door + 1
|
||
|
end
|
||
|
|
||
|
else
|
||
|
|
||
|
if chance(1,2) then
|
||
|
|
||
|
local c_bar
|
||
|
local coord = {x = x, y = y + 2, z = z}
|
||
|
|
||
|
--[[if math.random(1,terminal_rarity) == 1 then
|
||
|
c_bar = c_bar_ns
|
||
|
else
|
||
|
c_bar = c_bar_ew
|
||
|
end--]]
|
||
|
c_bar = c_bar_ns
|
||
|
|
||
|
-- Window --
|
||
|
if va:contains(coord.x, coord.y, coord.z) then
|
||
|
data[va:index(coord.x, coord.y, coord.z)] = c_bar
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for y=miny, maxp.y, roomsize do
|
||
|
for z=minz, maxp.z, roomsize do
|
||
|
for x=minx, maxp.x, roomsize do
|
||
|
|
||
|
math.randomseed(x + y^2 + z^3)
|
||
|
|
||
|
-- Stairs (generated later)
|
||
|
if chance(1, 128) then
|
||
|
|
||
|
stairs[next_stairs] = {x = x, y = y, z = z,
|
||
|
dir = math.random(0,3)}
|
||
|
next_stairs = next_stairs + 1
|
||
|
|
||
|
else
|
||
|
|
||
|
place_stuff(x, y, z, true) -- along the x axis
|
||
|
place_stuff(x, y, z, false) -- along the z axix
|
||
|
|
||
|
-------------
|
||
|
-- Torches --
|
||
|
-------------
|
||
|
|
||
|
if chance(1,8) then
|
||
|
local coord = {x = x + halfrs,
|
||
|
y = y + roomsize - 1,
|
||
|
z = z + halfrs}
|
||
|
if va:contains(coord.x, coord.y, coord.z) then
|
||
|
data[va:index(coord.x, coord.y, coord.z)] = c_torch
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
----------
|
||
|
-- Pits --
|
||
|
----------
|
||
|
|
||
|
local block_depth = maxp.y - minp.y + 1
|
||
|
local pit_layers = math.ceil(block_depth / pit_layer_size) + 2
|
||
|
local first_pit_layer = minp.y - (minp.y % pit_layer_size) - pit_layer_size
|
||
|
|
||
|
local y = first_pit_layer
|
||
|
for layer_count = 1, pit_layers do
|
||
|
|
||
|
for z=minz, maxp.z, roomsize do
|
||
|
for x=minx, maxp.x, roomsize do
|
||
|
|
||
|
math.randomseed(x + y^2 + z^3)
|
||
|
|
||
|
if chance(1, 128) then
|
||
|
|
||
|
local start = math.random(1, pit_floors_max)
|
||
|
local size = math.random(pit_floors_min, pit_floors_max)
|
||
|
|
||
|
local yy = y + start * roomsize
|
||
|
for floor_count = 1, size do
|
||
|
|
||
|
-- Remove torches
|
||
|
if va:contains(x + halfrs, yy - 1, z + halfrs) then
|
||
|
data[va:index(x + halfrs, yy - 1, z + halfrs)] = c_air
|
||
|
end
|
||
|
|
||
|
if yy > maxp.y then break end
|
||
|
|
||
|
if yy >= minp.y then
|
||
|
for zz = math.max(minp.z, z + 1), math.min(maxp.x, z + roomsize - 1) do
|
||
|
|
||
|
local startx = math.max(minp.x, x + 1)
|
||
|
local index = va:index(startx, yy, zz)
|
||
|
for xx = startx, math.min(maxp.x, x + roomsize - 1) do
|
||
|
|
||
|
data[index] = c_air
|
||
|
index = index + x_step
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
yy = yy + roomsize
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
|
||
|
y = y + pit_layer_size
|
||
|
end
|
||
|
|
||
|
|
||
|
vm:set_data(data)
|
||
|
vm:set_lighting({day=0, night=0})
|
||
|
vm:calc_lighting()
|
||
|
vm:write_to_map(data)
|
||
|
|
||
|
-----------------
|
||
|
-- Place Doors --
|
||
|
-----------------
|
||
|
|
||
|
for current_door_index, current_door in pairs(doors) do
|
||
|
|
||
|
local door_dir
|
||
|
|
||
|
if current_door.ns then
|
||
|
door_dir = minetest.dir_to_facedir({x = 0, y = 0, z = 1})
|
||
|
else
|
||
|
door_dir = minetest.dir_to_facedir({x = 1, y = 0, z = 0})
|
||
|
end
|
||
|
|
||
|
local door_pos = {x = current_door.x,
|
||
|
y = current_door.y,
|
||
|
z = current_door.z}
|
||
|
|
||
|
minetest.set_node(door_pos, {name = c_door,
|
||
|
param2 = door_dir})
|
||
|
--door_pos.y = door_pos.y + 1
|
||
|
--minetest.set_node(door_pos, {name = "doors:door_wood_t_1",
|
||
|
-- param2 = door_dir})
|
||
|
|
||
|
end
|
||
|
|
||
|
------------------
|
||
|
-- Place Stairs --
|
||
|
------------------
|
||
|
|
||
|
for unused, s in pairs(stairs) do
|
||
|
|
||
|
minetest.place_schematic({x = s.x, y = s.y + 1, z = s.z},
|
||
|
schematic_stairs, s.dir * 90, {}, true)
|
||
|
if chance(7,8) then
|
||
|
minetest.set_node({x = s.x + halfrs,
|
||
|
y = s.y + 2 * roomsize - 1,
|
||
|
z = s.z + halfrs},
|
||
|
{name = "air"})
|
||
|
end
|
||
|
end
|
||
|
end)
|