Allow use of most mapgens. Add some dungeon variety.

This commit is contained in:
Duane 2016-06-23 20:21:38 -05:00
parent 1aebdf3b47
commit 3e3e0c17d6
11 changed files with 280 additions and 211 deletions

View file

@ -12,6 +12,10 @@ fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone)
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
local map_min = {x = minp.x, y = minp.y - 1, z = minp.z}
if not heightmap then
heightmap = {}
end
local cave_1 = minetest.get_perlin_map(fun_caves.cave_noise_1, map_max):get3dMap_flat(map_min)
local cave_2 = minetest.get_perlin_map(fun_caves.cave_noise_2, map_max):get3dMap_flat(map_min)
local cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
@ -29,11 +33,18 @@ fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone)
local ivm = area:index(x, minp.y-1, z)
local height = heightmap[index]
if height >= maxp.y - 1 and data[area:index(x, maxp.y, z)] ~= node['air'] then
height = max_depth
heightmap[index] = height
elseif height <= minp.y then
height = -max_depth
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 data[ivm2] ~= node['air'] and data[ivm2] ~= node['ignore'] then
height = (y < maxp.y + 8) and y or max_depth
break
end
ivm2 = ivm2 - area.ystride
end
heightmap[index] = height
end
@ -92,5 +103,5 @@ fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone)
end
end
return write
return write, heightmap
end

View file

@ -1,4 +1,3 @@
-- I like having different stone scattered about. Sandstone forms
-- in layers. Desert stone... doesn't exist, but let's assume it's
-- another sedementary rock and place it similarly.
@ -23,7 +22,8 @@ minetest.register_craft({
minetest.add_group("default:cactus", {oddly_breakable_by_hand=1})
local biome_mod = {
if fun_caves.use_bi_hi then
local biome_mod = {
coniferous_forest_dunes = { heat_point = 35, humidity_point = 60, },
coniferous_forest = { heat_point = 35, humidity_point = 60, },
coniferous_forest_ocean = { heat_point = 35, humidity_point = 60, },
@ -51,10 +51,10 @@ local biome_mod = {
tundra = { node_river_water = "fun_caves:thin_ice", },
tundra_beach = { node_river_water = "fun_caves:thin_ice", },
tundra_ocean = {},
}
local rereg = {}
}
local rereg = {}
for n, bi in pairs(biome_mod) do
for n, bi in pairs(biome_mod) do
for i, rbi in pairs(minetest.registered_biomes) do
if rbi.name == n then
rereg[#rereg+1] = table.copy(rbi)
@ -63,26 +63,26 @@ for n, bi in pairs(biome_mod) do
end
end
end
end
end
minetest.clear_registered_biomes()
minetest.clear_registered_biomes()
for _, bi in pairs(rereg) do
for _, bi in pairs(rereg) do
minetest.register_biome(bi)
end
end
rereg = {}
for _, dec in pairs(minetest.registered_decorations) do
rereg = {}
for _, dec in pairs(minetest.registered_decorations) do
rereg[#rereg+1] = dec
end
minetest.clear_registered_decorations()
for _, dec in pairs(rereg) do
end
minetest.clear_registered_decorations()
for _, dec in pairs(rereg) do
minetest.register_decoration(dec)
end
rereg = nil
end
rereg = nil
minetest.register_biome({
minetest.register_biome({
name = "desertstone_grassland",
--node_dust = "",
node_top = "default:dirt_with_grass",
@ -100,10 +100,10 @@ minetest.register_biome({
y_max = 31000,
heat_point = 80,
humidity_point = 55,
})
})
minetest.register_decoration({
minetest.register_decoration({
deco_type = "simple",
place_on = {"default:dirt_with_grass"},
sidelen = 80,
@ -112,7 +112,8 @@ minetest.register_decoration({
y_min = 1,
y_max = 31000,
decoration = "default:junglegrass",
})
})
end
-- Create and initialize a table for a schematic.
function fun_caves.schematic_array(width, height, depth)

View file

@ -165,10 +165,14 @@ local function register_flower(name, seed, biomes)
decoration = "fun_caves:"..name,
}
if not fun_caves.use_bi_hi then
param.biomes = nil
end
-- Let rainforest plants show up more often.
local key1 = table.contains(biomes, "rainforest")
local key2 = table.contains(biomes, "desertstone_grassland")
if key1 or key2 then
if fun_caves.use_bi_hi and (key1 or key2) then
if key1 then
table.remove(param.biomes, key1)
else
@ -204,6 +208,10 @@ do
biomes = {"sandstone_grassland", "stone_grassland", "coniferous_forest", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp","sandstone_grassland_ocean", "stone_grassland_ocean", "coniferous_forest_ocean", "deciduous_forest_ocean", "desert_ocean", "savanna_ocean", "desertstone_grassland", },
y_max = 60,
}
if not fun_caves.use_bi_hi then
water_plant_1_def_sand.biomes = nil
end
local water_plant_1_def_soil = table.copy(water_plant_1_def_sand)
water_plant_1_def_soil.place_on = {"group:soil"}
water_plant_1_def_soil.decoration = {"fun_caves:water_plant_1_water_soil",}

View file

@ -47,7 +47,7 @@ for grid_count = 1,6 do
sounds = default.node_sound_stone_defaults(),
})
minetest.register_decoration({
local param = {
deco_type = "simple",
decoration = "fun_caves:small_rocks"..grid_count,
sidelen = 80,
@ -56,7 +56,11 @@ for grid_count = 1,6 do
biomes = {"sandstone_grassland", "tundra", "taiga", "stone_grassland", "coniferous_forest", "deciduous_forest", "desert", "savanna", "rainforest", "desertstone_grassland", },
flags = "place_center_x, place_center_z",
rotation = "random",
})
}
if not fun_caves.use_bi_hi then
param.biomes = nil
end
minetest.register_decoration(param)
default_grid = grid
end

View file

@ -27,7 +27,11 @@ local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z =
-- Air needs to be placed prior to decorations.
fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, biome_ids, underzone, dis_map)
csize = vector.add(vector.subtract(maxp, minp), 1)
local biomemap = minetest.get_mapgen_object("biomemap")
local biomemap
if fun_caves.use_bi_hi then
biomemap = minetest.get_mapgen_object("biomemap")
end
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
local map_min = {x = minp.x, y = minp.y - 1, z = minp.z}
@ -306,7 +310,7 @@ fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, bi
local node_below = data[ivm - area.ystride]
local node_above = data[ivm + area.ystride]
if y < water_level and data[ivm] == node["default:sand"] and node_above == node["default:water_source"] and data[ivm + area.ystride * 2] == node["default:water_source"] and coral_biomes[biome] and pn < -0.1 and math_random(5) == 1 and fun_caves.surround(node, data, area, ivm) then
if y < water_level and data[ivm] == node["default:sand"] and node_above == node["default:water_source"] and data[ivm + area.ystride * 2] == node["default:water_source"] and (not biomemap or coral_biomes[biome]) and pn < -0.1 and math_random(5) == 1 and fun_caves.surround(node, data, area, ivm) then
if math_random(100) == 1 then
data[ivm] = node["fun_caves:precious_coral_water_sand"]
else
@ -314,7 +318,7 @@ fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, bi
end
write = true
break
elseif y < water_level and node_below == node["default:sand"] and node_above == node["default:water_source"] and data[ivm] == node["default:water_source"] and coral_biomes[biome] and pn < -0.1 and math_random(5) < 3 then
elseif y < water_level and node_below == node["default:sand"] and node_above == node["default:water_source"] and data[ivm] == node["default:water_source"] and (not biomemap or coral_biomes[biome]) and pn < -0.1 and math_random(5) < 3 then
if math_random(15) == 1 then
data[ivm] = node["fun_caves:brain_coral"]
write = true
@ -358,14 +362,14 @@ fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, bi
end
end
if node_match_cache[desc.content_id][data[ivm]] == "good" and desc.fill_ratio and (not desc.biomes or (biome and desc.biomes and table.contains(desc.biomes, biome))) and math_random() <= desc.fill_ratio then
if node_match_cache[desc.content_id][data[ivm]] == "good" and desc.fill_ratio and (not desc.biomes or (not biomemap) or (biome and desc.biomes and table.contains(desc.biomes, biome))) and math_random() <= desc.fill_ratio then
data[ivm] = desc.content_id
write = true
break
end
end
end
elseif y > minp.y and node_below == node["default:river_water_source"] and data[ivm] == node["air"] and water_lily_biomes[biome] and pn > 0.5 and math_random(water_lily_ratio) == 1 then
elseif y > minp.y and node_below == node["default:river_water_source"] and data[ivm] == node["air"] and (not biomemap or water_lily_biomes[biome]) and pn > 0.5 and math_random(water_lily_ratio) == 1 then
-- on top of the water
-- I haven't figured out what the decoration manager is
-- doing with the noise functions, but this works ok.

View file

@ -1,23 +1,83 @@
local max_depth = 31000
-- 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)
-- invisible maze
-- hungry maze
-- chests (w traps)
-- step traps (math based)
-- hidden doors/downs
-- hot/ice floors
-- torches
--
local level = math.max(6, math.ceil(maxp.y / math.floor(max_depth / 6)))
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
@ -39,11 +99,14 @@ fun_caves.fortress = function(minp, maxp, data, area, node)
data[ivm] = inner_floor
end
elseif (z - minp.z) % 5 == 0 or (x - minp.x) % 5 == 0 then
--data[ivm] = fun_caves.DEBUG and node["default:glass"] or inner_wall
if y2 == 0 and math.random(3000) == 1 then
treasure_count = treasure_count + 1
data[ivm] = node['fun_caves:coffer']
else
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
@ -56,6 +119,8 @@ fun_caves.fortress = function(minp, maxp, data, area, node)
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)
@ -69,15 +134,6 @@ fun_caves.fortress = function(minp, maxp, data, area, node)
local x = (i + u) * 5 + minp.x
local y = minp.y + y2 * 5
local z = (j + v) * 5 + minp.z
--if y > minp.y and math.random(20) == 1 then
-- for z1 = z + 1, z + 4 do
-- ivm = area:index(x+1, y, z1)
-- for x1 = x + 1, x + 4 do
-- data[ivm] = node["air"]
-- ivm = ivm + 1
-- end
-- end
--end
for z1 = z + (1-v), z + (1-v) * 4 do
for y1 = y + 1, y + 4 do
@ -93,5 +149,35 @@ fun_caves.fortress = function(minp, maxp, data, area, node)
end
end
end
--print(treasure_count)
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

View file

@ -19,6 +19,14 @@ else
end
-- whether to use biomes and heightmap
fun_caves.use_bi_hi = false
local mg_params = minetest.get_mapgen_params()
if mg_params and mg_params.mgname ~= "v6" and mg_params.mgname ~= "v5" then
fun_caves.use_bi_hi = true
end
minetest.register_on_mapgen_init(function(mgparams)
minetest.set_mapgen_params({flags="nocaves,nodungeons"})
end)
@ -66,7 +74,6 @@ end
--dofile(fun_caves.path .. "/recipe_list.lua")
dofile(fun_caves.path .. "/abms.lua")
dofile(fun_caves.path .. "/unionfind.lua")
dofile(fun_caves.path .. "/nodes.lua")
dofile(fun_caves.path .. "/deco.lua")
dofile(fun_caves.path .. "/fungal_tree.lua")

View file

@ -16,11 +16,13 @@ local data = {}
local p2data = {} -- vm rotation data buffer
-- Create a table of biome ids, so I can use the biomemap.
local get_biome_id = minetest.get_biome_id
local biome_ids = {}
for name, desc in pairs(minetest.registered_biomes) do
if fun_caves.use_bi_hi then
-- Create a table of biome ids, so I can use the biomemap.
local get_biome_id = minetest.get_biome_id
for name, desc in pairs(minetest.registered_biomes) do
biome_ids[get_biome_id(desc.name)] = desc.name
end
end
--local function get_decoration(biome)
@ -350,10 +352,14 @@ local function generate(p_minp, p_maxp, seed)
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
vm:get_data(data)
p2data = vm:get_param2_data()
local heightmap = minetest.get_mapgen_object("heightmap")
local heightmap
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local csize = vector.add(vector.subtract(maxp, minp), 1)
if fun_caves.use_bi_hi then
heightmap = minetest.get_mapgen_object("heightmap")
end
-- use the same seed (based on perlin noise).
math.randomseed(minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z}))
@ -383,7 +389,7 @@ local function generate(p_minp, p_maxp, seed)
write = true
else
local write1, write2, write3
write1 = fun_caves.cavegen(minp, maxp, data, area, node, heightmap, underzone)
write1, heightmap = fun_caves.cavegen(minp, maxp, data, area, node, heightmap, underzone)
write2, write_p2 = fun_caves.decogen(minp, maxp, data, p2data, area, node, heightmap, biome_ids, underzone)
write3 = fun_caves.treegen(minp, maxp, data, p2data, area, node)
write = write1 or write2 or write3

View file

@ -160,8 +160,6 @@ for _, mob in pairs(mob_stats) do
minetest.registered_entities[mob.name].armor = mob.armor
if mob.reach then
minetest.registered_entities[mob.name].reach = mob.reach
else
print(mob.name, minetest.registered_entities[mob.name].reach)
end
end
end

View file

@ -42,6 +42,18 @@ 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)
-- ice -- add cold damage
minetest.add_group("default:ice", {surface_cold = 3})

View file

@ -1,68 +0,0 @@
-- All arrays are zero-based.
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
--local u = unionfind(5)
--print(dump(u))
--u:union(1,2)
--print(dump(u))
--u:union(1,2)
--print(dump(u))
--u:union(3,4)
--print(dump(u))
--u:union(1,0)
--print(dump(u))
--u:union(1,3)
--print(dump(u))
--u:union(4)
--print(dump(u))