271 lines
8.5 KiB
Lua
271 lines
8.5 KiB
Lua
local max_depth = 31000
|
|
|
|
|
|
dofile(fun_caves.path .. "/trophies.lua")
|
|
dofile(fun_caves.path .. "/tesseract.lua")
|
|
|
|
|
|
-- dungeon floor, basic
|
|
newnode = fun_caves.clone_node("default:stone")
|
|
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.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.description = "Dungeon Stone"
|
|
newnode.groups = {fortress = 1}
|
|
minetest.register_node("fun_caves:dungeon_wall_2", newnode)
|
|
|
|
newnode = fun_caves.clone_node("default:glass")
|
|
newnode.description = "Dungeon Stone"
|
|
newnode.groups = {fortress = 1}
|
|
minetest.register_node("fun_caves:dungeon_wall_transparent", newnode)
|
|
|
|
newnode = fun_caves.clone_node("default:glass")
|
|
newnode.description = "Dungeon Stone"
|
|
newnode.groups = {fortress = 1}
|
|
newnode.tiles = {'fun_caves_blank.png'}
|
|
newnode.pointable = false
|
|
minetest.register_node("fun_caves:dungeon_wall_invisible", newnode)
|
|
|
|
|
|
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:metallic_ice', 'fun_caves:metallic_ice', 'fun_caves:metallic_ice', 'fun_caves:metallic_ice', 'default:obsidian'},
|
|
{'fun_caves:aquamarine', 'fun_caves:garnet', 'fun_caves:zoisite', 'fun_caves:coral_gem', 'fun_caves:moonstone', 'default:obsidian'},
|
|
{'fun_caves:aquamarine', 'fun_caves:garnet', 'fun_caves:zoisite', 'fun_caves:coral_gem', 'fun_caves:moonstone', 'default:obsidian'},
|
|
{'fun_caves:aquamarine', 'fun_caves:garnet', 'fun_caves:zoisite', 'fun_caves:coral_gem', 'fun_caves:moonstone', 'default:obsidian'},
|
|
{'fun_caves:aquamarine', 'fun_caves:garnet', 'fun_caves:zoisite', 'fun_caves:coral_gem', 'fun_caves:moonstone', 'default:obsidian'},
|
|
}
|
|
local filler = {'default:apple 10', 'default:coal_lump 10', 'default:wood 10'}
|
|
local trophies = {
|
|
{'fun_caves:unobtainium', 'fun_caves:philosophers_stone'},
|
|
{'fun_caves:unobtainium', 'fun_caves:philosophers_stone'},
|
|
{'fun_caves:unobtainium', 'fun_caves:philosophers_stone'},
|
|
{'fun_caves:unobtainium', 'fun_caves:philosophers_stone'},
|
|
{'fun_caves:unobtainium', 'fun_caves:philosophers_stone'},
|
|
{'fun_caves:unobtainium', 'fun_caves:philosophers_stone'},
|
|
}
|
|
local chest_formspec =
|
|
"size[8,9]" ..
|
|
default.gui_bg ..
|
|
default.gui_bg_img ..
|
|
default.gui_slots ..
|
|
"list[current_name;main;0,0.3;8,4;]" ..
|
|
"list[current_player;main;0,4.85;8,1;]" ..
|
|
"list[current_player;main;0,6.08;8,3;8]" ..
|
|
"listring[current_name;main]" ..
|
|
"listring[current_player;main]" ..
|
|
default.get_hotbar_bg(0,4.85)
|
|
|
|
local newnode = fun_caves.clone_node("default:chest")
|
|
newnode.description = "Treasure Chest"
|
|
newnode.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos)
|
|
local ready = meta:get_string('formspec')
|
|
if ready == '' then
|
|
local level = math.max(6, math.ceil(pos.y / math.floor(max_depth / 6)))
|
|
local big_item = treasures[level][math.random(#treasures[level])]
|
|
meta:set_string("formspec", chest_formspec)
|
|
local inv = meta:get_inventory()
|
|
inv:set_size("main", 8*4)
|
|
inv:add_item('main', big_item)
|
|
for i = 1, math.random(4) do
|
|
inv:add_item('main', filler[math.random(#filler)])
|
|
end
|
|
if math.random(10) == 1 then
|
|
inv:add_item('main', trophies[level][math.random(#trophies[level])])
|
|
end
|
|
end
|
|
end
|
|
minetest.register_node("fun_caves:coffer", newnode)
|
|
|
|
|
|
-- All arrays in the maze functions are zero-based.
|
|
local floor_noise_1 = {offset = 0, scale = 1, seed = 1587, spread = {x = 30, y = 30, z = 30}, octaves = 3, persist = 1, lacunarity = 2}
|
|
|
|
function table.shuffle(self)
|
|
local j
|
|
local t = self
|
|
|
|
for i = #t, 1, -1 do
|
|
j = math.random(0, i)
|
|
t[i], t[j] = t[j], t[i]
|
|
end
|
|
end
|
|
|
|
function unionfind(max)
|
|
local u = { _parent = {}, _rank = {} }
|
|
|
|
for i = 0, max-1 do
|
|
u._parent[i] = i
|
|
u._rank[i] = 0
|
|
end
|
|
|
|
u.find = function(self, i)
|
|
local p = self._parent[i]
|
|
if i == p then
|
|
return i
|
|
end
|
|
self._parent[i] = self:find(p)
|
|
return self._parent[i]
|
|
end
|
|
|
|
u.union = function(self, i, j)
|
|
i = i or 0
|
|
j = j or 0
|
|
local root1 = self:find(i)
|
|
local root2 = self:find(j)
|
|
|
|
if root1 == root2 then
|
|
return
|
|
end
|
|
|
|
if self._rank[root1] > self._rank[root2] then
|
|
self._parent[root2] = root1
|
|
elseif self._rank[root2] > self._rank[root1] then
|
|
self._parent[root1] = root2
|
|
else
|
|
self._parent[root2] = root1
|
|
self._rank[root1] = self._rank[root1] + 1
|
|
end
|
|
end
|
|
|
|
return u
|
|
end
|
|
|
|
|
|
-- Now back to the actual fortress code...
|
|
|
|
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.
|
|
for i = 0, 2 * n * n - 1 do
|
|
walls[i] = i
|
|
end
|
|
table.shuffle(walls)
|
|
|
|
local dox, doz = math.random(0, n-1), math.random(0, n-1)
|
|
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.
|
|
if floor_type ~= 3 then
|
|
for m = 0, #walls do
|
|
local c = walls[m]
|
|
local a = math.floor(c / 2)
|
|
local i = a % n
|
|
local j = math.floor(a / n)
|
|
local u = c % 2 == 0 and 1 or 0
|
|
local v = c % 2 == 1 and 1 or 0
|
|
local b = a + u + n * v
|
|
if i < n - u and j < n - v and set:find(a) ~= set:find(b) then
|
|
set:union(a, b)
|
|
local x = (i + u) * 5 + minp.x
|
|
local y = minp.y + y2 * 5
|
|
local z = (j + v) * 5 + minp.z
|
|
|
|
for z1 = z + (1-v), z + (1-v) * 4 do
|
|
for y1 = y + 1, y + 4 do
|
|
local ivm = area:index(x + (1-u), y1, z1)
|
|
for x1 = x + (1-u), x + (1-u) * 4 do
|
|
if x1 < maxp.x and z1 < maxp.z and x1 > minp.x and z1 > minp.z then
|
|
data[ivm] = node["air"]
|
|
end
|
|
ivm = ivm + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local index = 0
|
|
for z = minp.z + 1, maxp.z - 1 do
|
|
for x = minp.x + 1, maxp.x - 1 do
|
|
index = index + 1
|
|
local ivm = area:index(x, minp.y + y2 * 5, 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 data[ivm] ~= node['air'] then
|
|
for i = 1, math.min(4, math.floor(4 * math.abs(floor_1[index]))) do
|
|
data[ivm + area.ystride * i] = node['default:dirt']
|
|
end
|
|
end
|
|
elseif floor_type == 4 then
|
|
for i = 1, 4 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
|