Modpack refactor (#4)
Split this mod into a set of sub-mods in a modpack, and in the process did a whole bunch of renovations. * updated Subterrane's API to allow for more patterned placement of things * added "warrens" * clean separation of flooded and non-flooded caverns * rearranged biomes to make cavern layers more distinct * added oil layer * added underworld layer
22
df_caverns/LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
License for Code
|
||||
----------------
|
||||
|
||||
Copyright (C) 2018 FaceDeer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
50
df_caverns/config.lua
Normal file
@ -0,0 +1,50 @@
|
||||
local CONFIG_FILE_PREFIX = "dfcaverns_"
|
||||
|
||||
df_caverns.config = {}
|
||||
|
||||
local print_settingtypes = false
|
||||
|
||||
local function setting(stype, name, default, description)
|
||||
local value
|
||||
if stype == "bool" then
|
||||
value = minetest.setting_getbool(CONFIG_FILE_PREFIX..name)
|
||||
elseif stype == "string" then
|
||||
value = minetest.setting_get(CONFIG_FILE_PREFIX..name)
|
||||
elseif stype == "int" or stype == "float" then
|
||||
value = tonumber(minetest.setting_get(CONFIG_FILE_PREFIX..name))
|
||||
end
|
||||
if value == nil then
|
||||
value = default
|
||||
end
|
||||
df_caverns.config[name] = value
|
||||
|
||||
if print_settingtypes then
|
||||
minetest.debug(CONFIG_FILE_PREFIX..name.." ("..description..") "..stype.." "..tostring(default))
|
||||
end
|
||||
end
|
||||
|
||||
--Caverns
|
||||
|
||||
setting("float", "vertical_cavern_scale", 256, "Vertical cavern dimension scale")
|
||||
setting("float", "horizontal_cavern_scale", 256, "Horizontal cavern dimension scale")
|
||||
setting("float", "cavern_threshold", 0.5, "Cavern threshold")
|
||||
setting("float", "sunless_sea_threshold", 0.4, "Cavern threshold for sunless seas (higher number means sparser caverns)")
|
||||
setting("float", "tunnel_flooding_threshold", 0.25, "Threshold for flooding tunnels around flooded caverns")
|
||||
|
||||
setting("int", "ymax", -193, "Upper limit of level 1")
|
||||
setting("int", "level1_min", -832, "Upper limit of level 2")
|
||||
setting("int", "level2_min", -1472, "Upper limit of level 3")
|
||||
setting("int", "level3_min", -2112, "Upper limit of the sunless seas")
|
||||
setting("int", "sunless_sea_min", -2512, "Lower limit of the sunless seas")
|
||||
|
||||
setting("bool", "enable_oil_sea", true, "Enable oil sea")
|
||||
df_caverns.config.enable_oil_sea = df_caverns.config.enable_oil_sea and minetest.get_modpath("oil") ~= nil
|
||||
setting("int", "oil_sea_level", -2700, "Oil sea level")
|
||||
|
||||
setting("bool", "enable_lava_sea", true, "Enable magma sea")
|
||||
setting("int", "lava_sea_level", -2900, "Lava sea level")
|
||||
|
||||
setting("bool", "enable_underworld", true, "Enable underworld")
|
||||
df_caverns.config.enable_underworld = df_caverns.config.enable_underworld and minetest.get_modpath("df_underworld_items") ~= nil
|
||||
setting("int", "underworld_level", -3200, "Underworld level")
|
||||
setting("int", "underworld_glowing_pit_mapblocks", 8, "Average pit spacing measured in mapblocks")
|
9
df_caverns/depends.txt
Normal file
@ -0,0 +1,9 @@
|
||||
default
|
||||
subterrane
|
||||
df_farming?
|
||||
df_trees
|
||||
df_mapitems
|
||||
ice_sprites?
|
||||
oil?
|
||||
df_underworld_items?
|
||||
magma_conduits?
|
1
df_caverns/description.txt
Normal file
@ -0,0 +1 @@
|
||||
Adds vast underground caverns in the style of Dwarf Fortress, complete with underground flora in diverse biomes. Also adds stalactite/stalagmite decorations in the smaller tunnels.
|
17
df_caverns/init.lua
Normal file
@ -0,0 +1,17 @@
|
||||
df_caverns = {}
|
||||
|
||||
--grab a shorthand for the filepath of the mod
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
--load companion lua files
|
||||
dofile(modpath.."/config.lua")
|
||||
|
||||
dofile(modpath.."/shared.lua")
|
||||
dofile(modpath.."/surface_tunnels.lua")
|
||||
dofile(modpath.."/level1.lua")
|
||||
dofile(modpath.."/level2.lua")
|
||||
dofile(modpath.."/level3.lua")
|
||||
dofile(modpath.."/sunless_sea.lua")
|
||||
dofile(modpath.."/oil_sea.lua")
|
||||
dofile(modpath.."/lava_sea.lua")
|
||||
dofile(modpath.."/underworld.lua")
|
147
df_caverns/lava_sea.lua
Normal file
@ -0,0 +1,147 @@
|
||||
if not df_caverns.config.enable_lava_sea then
|
||||
return
|
||||
end
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_lava = minetest.get_content_id("default:lava_source")
|
||||
local c_meseore = minetest.get_content_id("default:stone_with_mese")
|
||||
local c_mese_crystal = minetest.get_content_id("df_mapitems:mese_crystal")
|
||||
local c_mese_crystal_block = minetest.get_content_id("df_mapitems:glow_mese")
|
||||
local c_obsidian = minetest.get_content_id("default:obsidian")
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
local perlin_cave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=100, y=100, z=100},
|
||||
seed = -787324,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
-- large-scale rise and fall
|
||||
local perlin_wave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=1000, y=1000, z=1000},
|
||||
seed = 256664,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
local perlin_mese = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=500, y=500, z=500},
|
||||
seed = -50001,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
local median = df_caverns.config.lava_sea_level
|
||||
local floor_mult = 60
|
||||
local floor_displace = -25
|
||||
local ceiling_mult = -40
|
||||
local ceiling_displace = 15
|
||||
local wave_mult = 10
|
||||
|
||||
local y_max = median + 2*wave_mult + -2*ceiling_mult + ceiling_displace
|
||||
local y_min = median - 2*wave_mult - 2*floor_mult + floor_displace
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--if out of range of cave definition limits, abort
|
||||
if minp.y > y_max or maxp.y < y_min then
|
||||
return
|
||||
end
|
||||
|
||||
local t_start = os.clock()
|
||||
|
||||
math.randomseed(minp.x + minp.y*2^8 + minp.z*2^16 + seed) -- make decorations consistent between runs
|
||||
|
||||
local vm, data, data_param2, area = mapgen_helper.mapgen_vm_data_param2()
|
||||
|
||||
local nvals_cave = mapgen_helper.perlin2d("df_caverns:lava_cave", minp, maxp, perlin_cave)
|
||||
local nvals_wave = mapgen_helper.perlin2d("df_caverns:lava_wave", minp, maxp, perlin_wave)
|
||||
local nvals_mese = mapgen_helper.perlin2d("df_caverns:lava_mese", minp, maxp, perlin_mese)
|
||||
local nvals_lavasurface = mapgen_helper.perlin2d("df_cavern:cracks", minp, maxp, df_caverns.np_cracks)
|
||||
|
||||
for vi, x, y, z in area:iterp_yxz(minp, maxp) do
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
|
||||
local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
local lava = nvals_lavasurface[index2d]
|
||||
|
||||
local floor_height = math.floor(abs_cave * floor_mult + floor_displace + median + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
local lava_height = math.floor(median + lava * 2)
|
||||
|
||||
if y >= floor_height - 2 and y >= ceiling_height and y < ceiling_height + 2 and y <= lava_height + 2 and not mapgen_helper.buildable_to(data[vi]) then
|
||||
data[vi] = c_obsidian -- obsidian ceiling
|
||||
elseif y > floor_height and y < ceiling_height then
|
||||
if y > lava_height then
|
||||
data[vi] = c_air
|
||||
else
|
||||
data[vi] = c_lava
|
||||
end
|
||||
elseif y > floor_height - 5 and y < ceiling_height and y <= lava_height + 2 and not mapgen_helper.buildable_to(data[vi]) then
|
||||
data[vi] = c_obsidian -- thick obsidian floor
|
||||
elseif y < lava_height and data[vi] == c_air then
|
||||
data[vi] = c_lava
|
||||
end
|
||||
end
|
||||
|
||||
-- decoration loop.
|
||||
for x = minp.x + 1, maxp.x-1 do
|
||||
for z = minp.z + 1, maxp.z -1 do
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
local mese_intensity = math.abs(nvals_mese[index2d])
|
||||
|
||||
local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
local floor_height = math.floor(abs_cave * floor_mult + floor_displace + median + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
|
||||
local lava = nvals_lavasurface[index2d]
|
||||
local lava_height = math.floor(median + lava * 2)
|
||||
|
||||
if mese_intensity > 0.65 and ceiling_height > lava_height + 1 and ceiling_height > floor_height + 1 and ceiling_height <= maxp.y and ceiling_height >= minp.y then
|
||||
local vi = area:index(x, ceiling_height, z)
|
||||
if not mapgen_helper.buildable_to(data[vi]) then
|
||||
-- decorate ceiling
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_meseore
|
||||
elseif mese_intensity > 0.75 and math.random() < 0.1 then
|
||||
data[vi] = c_meseore
|
||||
local bi = vi-area.ystride
|
||||
data[bi] = c_mese_crystal
|
||||
data_param2[bi] = math.random(1,4) + 19
|
||||
elseif mese_intensity > 0.85 and math.random() < 0.025 then
|
||||
subterrane.big_stalactite(vi-area.ystride, area, data, 6, 13, c_meseore, c_meseore, c_mese_crystal_block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--send data back to voxelmanip
|
||||
vm:set_data(data)
|
||||
vm:set_param2_data(data_param2)
|
||||
--calc lighting
|
||||
vm:set_lighting({day = 0, night = 0})
|
||||
vm:calc_lighting()
|
||||
|
||||
vm:update_liquids()
|
||||
--write it to world
|
||||
vm:write_to_map()
|
||||
|
||||
local chunk_generation_time = math.ceil((os.clock() - t_start) * 1000) --grab how long it took
|
||||
if chunk_generation_time < 1000 then
|
||||
minetest.log("info", "[df_caverns] lava sea mapblock generation took "..chunk_generation_time.." ms") --tell people how long
|
||||
else
|
||||
minetest.log("warning", "[df_caverns] lava sea took "..chunk_generation_time.." ms to generate map block "
|
||||
.. minetest.pos_to_string(minp) .. minetest.pos_to_string(maxp))
|
||||
end
|
||||
end)
|
274
df_caverns/level1.lua
Normal file
@ -0,0 +1,274 @@
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_dirt = minetest.get_content_id("default:dirt")
|
||||
local c_dirt_moss = minetest.get_content_id("df_mapitems:dirt_with_cave_moss")
|
||||
|
||||
local c_wet_flowstone = minetest.get_content_id("df_mapitems:wet_flowstone")
|
||||
local c_dry_flowstone = minetest.get_content_id("df_mapitems:dry_flowstone")
|
||||
|
||||
local tower_cap_shrublist
|
||||
local fungiwood_shrublist
|
||||
|
||||
if minetest.get_modpath("df_farming") then
|
||||
tower_cap_shrublist = {
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
fungiwood_shrublist = {
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
end
|
||||
|
||||
local subsea_level = df_caverns.config.level1_min - (df_caverns.config.level1_min - df_caverns.config.ymax) * 0.33
|
||||
local flooding_threshold = math.min(df_caverns.config.tunnel_flooding_threshold, df_caverns.config.cavern_threshold)
|
||||
|
||||
local get_biome = function(heat, humidity)
|
||||
if humidity < 23 then -- about 20% of locations fall below this threshold
|
||||
return "barren"
|
||||
elseif heat < 50 then
|
||||
return "towercap"
|
||||
else
|
||||
return "fungiwood"
|
||||
end
|
||||
end
|
||||
|
||||
local tower_cap_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air and data[vi-ystride] ~= c_water then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, tower_cap_shrublist)
|
||||
elseif math.random() < 0.01 and abs_cracks > 0.25 then
|
||||
df_trees.spawn_tower_cap_vm(vi+ystride, area, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local fungiwood_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air and data[vi-ystride] ~= c_water then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, fungiwood_shrublist)
|
||||
elseif math.random() < 0.03 and abs_cracks > 0.35 then
|
||||
df_trees.spawn_fungiwood_vm(vi+ystride, area, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
math.randomseed(minp.x + minp.y*2^8 + minp.z*2^16 + seed) -- make decorations consistent between runs
|
||||
|
||||
local heatmap = minetest.get_mapgen_object("heatmap")
|
||||
local humiditymap = minetest.get_mapgen_object("humiditymap")
|
||||
local data_param2 = df_caverns.data_param2
|
||||
vm:get_param2_data(data_param2)
|
||||
local nvals_cracks = mapgen_helper.perlin2d("df_cavern:cracks", minp, maxp, df_caverns.np_cracks)
|
||||
local nvals_cave = node_arrays.nvals_cave
|
||||
local cave_area = node_arrays.cave_area
|
||||
|
||||
-- Partly fill flooded caverns and warrens
|
||||
if minp.y <= subsea_level then
|
||||
for vi in area:iterp(minp, maxp) do
|
||||
if data[vi] == c_air and area:get_y(vi) <= subsea_level and nvals_cave[cave_area:transform(area, vi)] < -flooding_threshold then
|
||||
data[vi] = c_water
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Cavern floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_floor_nodes) do
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local abs_cracks = math.abs(nvals_cracks[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if minp.y < subsea_level and area:get_y(vi) < subsea_level and flooded_caverns then
|
||||
-- underwater floor
|
||||
df_caverns.flooded_cavern_floor(abs_cracks, vert_rand, vi, area, data)
|
||||
elseif biome_name == "towercap" then
|
||||
tower_cap_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif biome_name == "fungiwood" then
|
||||
fungiwood_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
df_caverns.wet_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
df_caverns.dry_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Cavern ceilings
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_ceiling_nodes) do
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local abs_cracks = math.abs(nvals_cracks[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level then
|
||||
-- underwater ceiling, do nothing
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
-- wet barren
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
end
|
||||
else
|
||||
-- dry barren
|
||||
if abs_cracks < 0.075 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
else -- all the other biomes
|
||||
df_caverns.glow_worm_cavern_ceiling(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Tunnel floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Tunnel ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
else
|
||||
-- air pockets
|
||||
local ystride = area.ystride
|
||||
local cracks = nvals_cracks[index2d]
|
||||
if cracks > 0.5 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.7 and data[vi-ystride*2] == c_water then
|
||||
data[vi-ystride*2] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Warren floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Warren ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
-- else air pockets?
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Column material override for dry biome
|
||||
|
||||
for _, vi in ipairs(node_arrays.column_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local dry = (biome_name == "barren") and (nvals_cave[cave_area:transform(area, vi)] > 0)
|
||||
|
||||
if dry and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_param2_data(data_param2)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
subterrane.register_layer({
|
||||
name = "cavern layer 1",
|
||||
y_max = df_caverns.config.ymax,
|
||||
y_min = df_caverns.config.level1_min,
|
||||
cave_threshold = df_caverns.config.cavern_threshold,
|
||||
boundary_blend_range = 64, -- range near ymin and ymax over which caves diminish to nothing
|
||||
perlin_cave = df_caverns.perlin_cave,
|
||||
perlin_wave = df_caverns.perlin_wave,
|
||||
solidify_lava = true,
|
||||
columns = {
|
||||
maximum_radius = 10,
|
||||
minimum_radius = 4,
|
||||
node = "df_mapitems:wet_flowstone",
|
||||
weight = 0.25,
|
||||
maximum_count = 50,
|
||||
minimum_count = 0,
|
||||
},
|
||||
decorate = decorate_level_1,
|
||||
warren_region_variability_threshold = 0.33,
|
||||
double_frequency = true,
|
||||
})
|
341
df_caverns/level2.lua
Normal file
@ -0,0 +1,341 @@
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_dirt = minetest.get_content_id("default:dirt")
|
||||
local c_dirt_moss = minetest.get_content_id("df_mapitems:dirt_with_cave_moss")
|
||||
|
||||
local c_wet_flowstone = minetest.get_content_id("df_mapitems:wet_flowstone")
|
||||
local c_dry_flowstone = minetest.get_content_id("df_mapitems:dry_flowstone")
|
||||
|
||||
local c_veinstone = minetest.get_content_id("df_mapitems:veinstone")
|
||||
local wall_vein_perlin_params = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x = 50, y = 50, z = 50},
|
||||
seed = 2199,
|
||||
octaves = 3,
|
||||
persist = 0.63,
|
||||
lacunarity = 2.0,
|
||||
flags = "eased",
|
||||
}
|
||||
|
||||
local subsea_level = df_caverns.config.level2_min - (df_caverns.config.level2_min - df_caverns.config.level1_min) * 0.33 -- "sea level" for the flooded caverns.
|
||||
local flooding_threshold = math.min(df_caverns.config.tunnel_flooding_threshold, df_caverns.config.cavern_threshold) -- cavern value out to which we're flooding tunnels and warrens
|
||||
|
||||
local get_biome = function(heat, humidity)
|
||||
if humidity < 23 then -- about 20% of locations fall below this threshold
|
||||
return "barren"
|
||||
elseif heat < 40 then
|
||||
return "goblincap" -- about 33% are below this threshold
|
||||
elseif heat < 60 then
|
||||
return "sporetree" -- another 33%
|
||||
else
|
||||
return "tunneltube"
|
||||
end
|
||||
end
|
||||
|
||||
local goblin_cap_shrublist
|
||||
local tunnel_tube_shrublist
|
||||
local spore_tree_shrublist
|
||||
|
||||
if minetest.get_modpath("df_farming") then
|
||||
goblin_cap_shrublist = {
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
tunnel_tube_shrublist = {
|
||||
df_farming.spawn_sweet_pod_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
spore_tree_shrublist = {
|
||||
df_farming.spawn_pig_tail_vm,
|
||||
df_farming.spawn_pig_tail_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
end
|
||||
|
||||
local goblin_cap_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, goblin_cap_shrublist)
|
||||
elseif math.random() < 0.015 then
|
||||
df_trees.spawn_goblin_cap_vm(vi+ystride, area, data)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local spore_tree_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, spore_tree_shrublist)
|
||||
elseif math.random() < 0.05 then
|
||||
df_trees.spawn_spore_tree_vm(vi+ystride, area, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local tunnel_tube_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, tunnel_tube_shrublist)
|
||||
elseif math.random() < 0.05 then
|
||||
df_trees.spawn_tunnel_tube_vm(vi+ystride, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
math.randomseed(minp.x + minp.y*2^8 + minp.z*2^16 + seed) -- make decorations consistent between runs
|
||||
|
||||
local heatmap = minetest.get_mapgen_object("heatmap")
|
||||
local humiditymap = minetest.get_mapgen_object("humiditymap")
|
||||
local data_param2 = df_caverns.data_param2
|
||||
vm:get_param2_data(data_param2)
|
||||
local nvals_cracks = mapgen_helper.perlin2d("df_cavern:cracks", minp, maxp, df_caverns.np_cracks)
|
||||
local nvals_cave = node_arrays.nvals_cave
|
||||
local cave_area = node_arrays.cave_area
|
||||
local cavern_def = node_arrays.cavern_def
|
||||
|
||||
local vein_noise
|
||||
|
||||
-- Partly fill flooded caverns and warrens
|
||||
for vi in area:iterp(minp, maxp) do
|
||||
local cave_val = nvals_cave[cave_area:transform(area, vi)]
|
||||
if cave_val < -flooding_threshold then
|
||||
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local cave_threshold = cavern_def.cave_threshold
|
||||
|
||||
--check if we're just inside the boundary of the (negazone) cavern threshold
|
||||
if biome_name == "barren" and cave_val < -cave_threshold and cave_val > -cave_threshold - 0.01 then
|
||||
-- add giant rooty structures to the flooded barren caverns
|
||||
if vein_noise == nil then
|
||||
vein_noise = mapgen_helper.perlin3d("df_caverns:wall_veins", minp, maxp, wall_vein_perlin_params)
|
||||
end
|
||||
-- we can reuse cave_area here, its extents are minp, maxp too.
|
||||
if data[vi] == c_air and math.abs(vein_noise[cave_area:transform(area, vi)]) < 0.02 then
|
||||
data[vi] = c_veinstone
|
||||
end
|
||||
end
|
||||
if data[vi] == c_air and area:get_y(vi) <= subsea_level then
|
||||
data[vi] = c_water -- otherwise, fill air with water when below sea level
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Cavern floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_floor_nodes) do
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local abs_cracks = math.abs(nvals_cracks[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if minp.y < subsea_level and area:get_y(vi) < subsea_level and flooded_caverns then
|
||||
-- underwater floor
|
||||
df_caverns.flooded_cavern_floor(abs_cracks, vert_rand, vi, area, data)
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
df_caverns.wet_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
df_caverns.dry_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
elseif biome_name == "goblincap" then
|
||||
goblin_cap_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif biome_name == "sporetree" then
|
||||
spore_tree_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif biome_name == "tunneltube" then
|
||||
tunnel_tube_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Cavern ceilings
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_ceiling_nodes) do
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local abs_cracks = math.abs(nvals_cracks[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level then
|
||||
-- underwater ceiling, do nothing
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
-- wet barren
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
end
|
||||
else
|
||||
-- dry barren
|
||||
if abs_cracks < 0.075 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
local y = area:get_y(vi)
|
||||
local y_proportional = (y - df_caverns.config.level1_min) / (df_caverns.config.level2_min - df_caverns.config.level1_min)
|
||||
if abs_cracks * y_proportional > 0.3 and math.random() < 0.005 * y_proportional then
|
||||
df_mapitems.place_big_crystal_cluster(area, data, data_param2, vi, math.random(0,1), true)
|
||||
end
|
||||
end
|
||||
else -- all the other biomes
|
||||
df_caverns.glow_worm_cavern_ceiling(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Tunnel floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Tunnel ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
else
|
||||
-- air pockets
|
||||
local ystride = area.ystride
|
||||
local cracks = nvals_cracks[index2d]
|
||||
if cracks > 0.5 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.7 and data[vi-ystride*2] == c_water then
|
||||
data[vi-ystride*2] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Warren floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Warren ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name ~= "barren" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
-- else air pockets?
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Column material override for dry biome
|
||||
|
||||
for _, vi in ipairs(node_arrays.column_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local dry = (biome_name == "barren") and (nvals_cave[cave_area:transform(area, vi)] > 0)
|
||||
|
||||
if dry and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_param2_data(data_param2)
|
||||
end
|
||||
|
||||
subterrane.register_layer({
|
||||
name = "cavern layer 2",
|
||||
y_max = df_caverns.config.level1_min-1,
|
||||
y_min = df_caverns.config.level2_min,
|
||||
cave_threshold = df_caverns.config.cavern_threshold,
|
||||
boundary_blend_range = 64, -- range near ymin and ymax over which caves diminish to nothing
|
||||
perlin_cave = df_caverns.perlin_cave,
|
||||
perlin_wave = df_caverns.perlin_wave,
|
||||
solidify_lava = true,
|
||||
columns = {
|
||||
maximum_radius = 15,
|
||||
minimum_radius = 4,
|
||||
node = "df_mapitems:wet_flowstone",
|
||||
weight = 0.25,
|
||||
maximum_count = 50,
|
||||
minimum_count = 5,
|
||||
},
|
||||
decorate = decorate_level_2,
|
||||
warren_region_variability_threshold = 0.33,
|
||||
double_frequency = true,
|
||||
})
|
||||
|
510
df_caverns/level3.lua
Normal file
@ -0,0 +1,510 @@
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_desert_sand = minetest.get_content_id("default:desert_sand")
|
||||
local c_stone_with_coal = minetest.get_content_id("default:stone_with_coal")
|
||||
|
||||
local c_silver_sand = minetest.get_content_id("default:silver_sand")
|
||||
local c_snow = minetest.get_content_id("default:snow")
|
||||
local c_ice = minetest.get_content_id("default:ice")
|
||||
local c_hoar_moss = minetest.get_content_id("df_mapitems:ice_with_hoar_moss")
|
||||
local c_gravel = minetest.get_content_id("default:gravel")
|
||||
|
||||
local c_oil = minetest.get_content_id("oil:oil_source")
|
||||
|
||||
local c_cobble_fungus_fine = minetest.get_content_id("df_mapitems:cobble_with_floor_fungus_fine")
|
||||
local c_cobble_fungus = minetest.get_content_id("df_mapitems:cobble_with_floor_fungus")
|
||||
local c_cobble = minetest.get_content_id("default:cobble")
|
||||
|
||||
local c_wet_flowstone = minetest.get_content_id("df_mapitems:wet_flowstone")
|
||||
local c_dry_flowstone = minetest.get_content_id("df_mapitems:dry_flowstone")
|
||||
|
||||
local c_glow_ore = minetest.get_content_id("df_mapitems:glow_ruby_ore")
|
||||
|
||||
local c_sprite
|
||||
if minetest.get_modpath("ice_sprites") then
|
||||
c_sprite = minetest.get_content_id("ice_sprites:ice_sprite")
|
||||
end
|
||||
|
||||
local subsea_level = df_caverns.config.level3_min - (df_caverns.config.level3_min - df_caverns.config.level2_min) * 0.33
|
||||
local flooding_threshold = math.min(df_caverns.config.tunnel_flooding_threshold, df_caverns.config.cavern_threshold)
|
||||
|
||||
local ice_thickness = 3
|
||||
|
||||
local get_biome = function(heat, humidity)
|
||||
if humidity < 23 then -- about 20% of locations fall below this threshold
|
||||
return "barren"
|
||||
elseif heat < 50 then
|
||||
return "blackcap"
|
||||
else
|
||||
return "bloodnether"
|
||||
end
|
||||
end
|
||||
|
||||
local black_cap_shrublist
|
||||
local nether_cap_shrublist
|
||||
local blood_thorn_shrublist
|
||||
|
||||
if minetest.get_modpath("df_farming") then
|
||||
black_cap_shrublist = {
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
}
|
||||
nether_cap_shrublist = {
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
blood_thorn_shrublist = {
|
||||
df_farming.spawn_quarry_bush_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
}
|
||||
end
|
||||
|
||||
local hoar_moss_perlin_params = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x = 3, y = 30, z = 3},
|
||||
seed = 345421,
|
||||
octaves = 3,
|
||||
persist = 0.63,
|
||||
lacunarity = 2.0,
|
||||
flags = "eased",
|
||||
}
|
||||
|
||||
local black_cap_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_stone_with_coal
|
||||
else
|
||||
data[vi] = c_cobble_fungus
|
||||
end
|
||||
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
elseif abs_cracks < 0.15 and math.random() < 0.3 then
|
||||
df_trees.spawn_torchspine_vm(vi+area.ystride, area, data, data_param2)
|
||||
else
|
||||
if math.random() < 0.05 then
|
||||
df_caverns.place_shrub(vi+area.ystride, area, data, data_param2, black_cap_shrublist)
|
||||
elseif math.random() < 0.01 and abs_cracks > 0.25 then
|
||||
df_trees.spawn_black_cap_vm(vi+area.ystride, area, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local nether_cap_cavern_floor = function(cracks, abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalagmite(vi+ystride, area, data, 6, 15, c_ice, c_ice, c_ice)
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = abs_cracks * 50
|
||||
if vert_rand > 0.5 then
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, math.floor(height), df_mapitems.icicle_ids)
|
||||
else
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, math.floor(height*0.5), df_mapitems.dry_stalagmite_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if cracks < -0.3 then
|
||||
data[vi] = c_silver_sand
|
||||
if math.random() < 0.025 then
|
||||
df_trees.spawn_nether_cap_vm(vi+ystride, area, data)
|
||||
elseif math.random() < 0.05 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, nether_cap_shrublist)
|
||||
elseif cracks < -0.4 and cracks > -0.6 then
|
||||
data[vi + ystride] = c_snow
|
||||
end
|
||||
elseif cracks > 0.1 then
|
||||
if math.random() < 0.002 then
|
||||
df_trees.spawn_nether_cap_vm(vi+ystride, area, data)
|
||||
else
|
||||
data[vi] = c_ice
|
||||
end
|
||||
if cracks > 0.4 then
|
||||
data[vi + ystride] = c_ice
|
||||
if cracks > 0.6 then
|
||||
data[vi + 2*ystride] = c_ice
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local nether_cap_cavern_ceiling = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
if vert_rand < 0.01 then
|
||||
subterrane.big_stalactite(vi-ystride, area, data, 6, 15, c_ice, c_ice, c_ice)
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = abs_cracks * 50
|
||||
if vert_rand > 0.5 then
|
||||
subterrane.stalactite(vi-ystride, area, data, data_param2, param2, math.floor(height), df_mapitems.icicle_ids)
|
||||
else
|
||||
subterrane.stalactite(vi-ystride, area, data, data_param2, param2, math.floor(height*0.5), df_mapitems.dry_stalagmite_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
if c_sprite and abs_cracks < 0.5 and math.random() < 0.02 then
|
||||
local sprite_vi = vi-ystride*math.random(1,5)
|
||||
if data[sprite_vi] == c_air and area:containsi(sprite_vi) then
|
||||
data[sprite_vi] = c_sprite
|
||||
minetest.get_node_timer(area:position(sprite_vi)):start(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local blood_thorn_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.075 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalagmite(vi+area.ystride, area, data, 6, 15, c_dry_flowstone, c_dry_flowstone, c_dry_flowstone)
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 66)
|
||||
subterrane.stalagmite(vi+area.ystride, area, data, data_param2, param2, height, df_mapitems.dry_stalagmite_ids)
|
||||
end
|
||||
elseif math.random() > abs_cracks + 0.66 then
|
||||
df_trees.spawn_blood_thorn_vm(vi+area.ystride, area, data, data_param2)
|
||||
data[vi] = c_desert_sand
|
||||
else
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+area.ystride, area, data, data_param2, blood_thorn_shrublist)
|
||||
data[vi] = c_desert_sand
|
||||
elseif math.random() > 0.25 then
|
||||
data[vi] = c_desert_sand
|
||||
else
|
||||
data[vi] = c_cobble
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hoar_moss_generator
|
||||
|
||||
local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
math.randomseed(minp.x + minp.y*2^8 + minp.z*2^16 + seed) -- make decorations consistent between runs
|
||||
|
||||
local heatmap = minetest.get_mapgen_object("heatmap")
|
||||
local humiditymap = minetest.get_mapgen_object("humiditymap")
|
||||
local data_param2 = df_caverns.data_param2
|
||||
vm:get_param2_data(data_param2)
|
||||
local nvals_cracks = mapgen_helper.perlin2d("df_cavern:cracks", minp, maxp, df_caverns.np_cracks)
|
||||
local nvals_cave = node_arrays.nvals_cave
|
||||
local cave_area = node_arrays.cave_area
|
||||
local cavern_def = node_arrays.cavern_def
|
||||
|
||||
-- Partly fill flooded caverns and warrens
|
||||
if minp.y <= subsea_level then
|
||||
for vi in area:iterp(minp, maxp) do
|
||||
local y = area:get_y(vi)
|
||||
if y <= subsea_level and nvals_cave[cave_area:transform(area, vi)] < -flooding_threshold then
|
||||
if data[vi] == c_air and y <= subsea_level then
|
||||
data[vi] = c_water
|
||||
end
|
||||
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
|
||||
if biome_name == "blackcap" then
|
||||
-- oil slick
|
||||
local cave = math.abs(nvals_cave[cave_area:transform(area, vi)])
|
||||
if y == subsea_level and data[vi] == c_water and cave + nvals_cracks[index2d]*0.025 < cavern_def.cave_threshold + 0.1 then
|
||||
data[vi] = c_oil
|
||||
end
|
||||
elseif biome_name == "bloodnether" and y <= subsea_level and y > subsea_level - ice_thickness and data[vi] == c_water then
|
||||
-- floating ice
|
||||
data[vi] = c_ice
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Cavern floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_floor_nodes) do
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level then
|
||||
-- underwater floor
|
||||
local ystride = area.ystride
|
||||
if abs_cracks > 0.25 and data[vi-ystride] ~= c_water then
|
||||
data[vi] = c_gravel
|
||||
end
|
||||
-- put in only the large stalagmites that won't get in the way of the water
|
||||
if abs_cracks < 0.1 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalagmite(vi+ystride, area, data, 6, 15, c_wet_flowstone, c_wet_flowstone, c_wet_flowstone)
|
||||
end
|
||||
end
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
-- wet zone floor
|
||||
df_caverns.dry_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
-- dry zone floor, add crystals
|
||||
if abs_cracks < 0.075 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
elseif abs_cracks > 0.3 and math.random() < 0.005 then
|
||||
df_mapitems.place_big_crystal_cluster(area, data, data_param2, vi+area.ystride, math.random(0,2), false)
|
||||
end
|
||||
end
|
||||
elseif biome_name == "blackcap" then
|
||||
black_cap_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif biome_name == "bloodnether" then
|
||||
if flooded_caverns then
|
||||
nether_cap_cavern_floor(cracks, abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
blood_thorn_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Cavern ceilings
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_ceiling_nodes) do
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local abs_cracks = math.abs(nvals_cracks[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level then
|
||||
-- underwater ceiling, do nothing
|
||||
|
||||
elseif biome_name == "blackcap" then
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_stone_with_coal
|
||||
end
|
||||
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
-- wet zone ceiling
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
end
|
||||
else
|
||||
-- dry zone ceiling, add crystals
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
if abs_cracks > 0.3 and math.random() < 0.005 then
|
||||
df_mapitems.place_big_crystal_cluster(area, data, data_param2, vi, math.random(0,3), true)
|
||||
end
|
||||
end
|
||||
|
||||
elseif biome_name == "bloodnether" then
|
||||
if flooded_caverns then
|
||||
--Nethercap ceiling
|
||||
nether_cap_cavern_ceiling(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
-- bloodthorn ceiling
|
||||
if abs_cracks < 0.075 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
elseif abs_cracks > 0.75 and math.random() < 0.05 then
|
||||
data[vi] = c_glow_ore
|
||||
df_mapitems.place_big_crystal(data, data_param2, vi-area.ystride, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
-- Tunnel floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name == "blackcap" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Tunnel ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
if flooded_caverns or biome_name == "blackcap" then
|
||||
-- we're in flooded areas or are not barren
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
else
|
||||
-- air pockets
|
||||
local ystride = area.ystride
|
||||
local cracks = nvals_cracks[index2d]
|
||||
if cracks > 0.5 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.7 and data[vi-ystride*2] == c_water then
|
||||
data[vi-ystride*2] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------
|
||||
-- Warren ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level then
|
||||
-- underwater ceiling, do nothing
|
||||
elseif biome_name == "bloodnether" and flooded_caverns then
|
||||
-- Nethercap warrens
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.15 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalactite(vi-ystride, area, data, 6, 15, c_ice, c_ice, c_ice)
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = abs_cracks * 50
|
||||
if vert_rand > 0.5 then
|
||||
subterrane.stalactite(vi-ystride, area, data, data_param2, param2, math.floor(height), df_mapitems.icicle_ids)
|
||||
else
|
||||
subterrane.stalactite(vi-ystride, area, data, data_param2, param2, math.floor(height*0.5), df_mapitems.dry_stalagmite_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if flooded_caverns or biome_name == "blackcap" then
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Warren floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if minp.y < subsea_level and area:get_y(vi) < subsea_level and flooded_caverns then
|
||||
-- underwater floor, do nothing
|
||||
elseif biome_name == "bloodnether" and flooded_caverns then
|
||||
-- nethercap warren
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.15 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalagmite(vi+ystride, area, data, 6, 15, c_ice, c_ice, c_ice)
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height =abs_cracks * 50
|
||||
if vert_rand > 0.5 then
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, math.floor(height), df_mapitems.icicle_ids)
|
||||
else
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, math.floor(height*0.5), df_mapitems.dry_stalagmite_ids)
|
||||
end
|
||||
end
|
||||
elseif cracks > 0.4 then
|
||||
data[vi + ystride] = c_ice
|
||||
if cracks > 0.6 then
|
||||
data[vi + 2*ystride] = c_ice
|
||||
end
|
||||
end
|
||||
else
|
||||
if flooded_caverns or biome_name == "blackcap" then
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Column material override for dry biome
|
||||
for _, vi in ipairs(node_arrays.column_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
|
||||
local flooded_caverns = nvals_cave[cave_area:transform(area, vi)] < 0
|
||||
|
||||
if biome_name == "bloodnether" and data[vi] == c_wet_flowstone then
|
||||
if not flooded_caverns then
|
||||
data[vi] = c_dry_flowstone -- bloodthorn
|
||||
else
|
||||
if area:get_y(vi) > subsea_level - ice_thickness then
|
||||
if data[vi + 1] == c_air or data[vi - 1] == c_air or data[vi + area.zstride] == c_air or data[vi - area.zstride] == c_air then
|
||||
--surface node, potential hoar moss streak
|
||||
-- This particular Perlin noise is only called in small amounts on rare occasions, so don't bother
|
||||
-- with the full blown generated array rigamarole.
|
||||
hoar_moss_generator = hoar_moss_generator or minetest.get_perlin(hoar_moss_perlin_params)
|
||||
local pos = area:position(vi)
|
||||
if hoar_moss_generator.get_3d and hoar_moss_generator:get_3d({x=pos.z, y=pos.y, z=pos.x}) > 0.5 then -- TODO: version 0.4.16 gets no hoar moss
|
||||
data[vi] = c_hoar_moss
|
||||
else
|
||||
data[vi] = c_ice
|
||||
end
|
||||
else
|
||||
data[vi] = c_ice
|
||||
end
|
||||
else
|
||||
data[vi] = c_water -- ice columns shouldn't extend below the surface of the water. There should probably be a bulge below, though. Not sure best way to implement that.
|
||||
end
|
||||
end
|
||||
elseif biome_name == "barren" and not flooded_caverns and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_param2_data(data_param2)
|
||||
end
|
||||
|
||||
-- Layer 3
|
||||
subterrane.register_layer({
|
||||
name = "cavern layer 3",
|
||||
y_max = df_caverns.config.level2_min-1,
|
||||
y_min = df_caverns.config.level3_min,
|
||||
cave_threshold = df_caverns.config.cavern_threshold,
|
||||
boundary_blend_range = 64, -- range near ymin and ymax over which caves diminish to nothing
|
||||
perlin_cave = df_caverns.perlin_cave,
|
||||
perlin_wave = df_caverns.perlin_wave,
|
||||
solidify_lava = true,
|
||||
columns = {
|
||||
maximum_radius = 20,
|
||||
minimum_radius = 5,
|
||||
node = "df_mapitems:wet_flowstone",
|
||||
weight = 0.25,
|
||||
maximum_count = 50,
|
||||
minimum_count = 10,
|
||||
},
|
||||
decorate = decorate_level_3,
|
||||
warren_region_variability_threshold = 0.33,
|
||||
double_frequency = true,
|
||||
})
|
1
df_caverns/mod.conf
Normal file
@ -0,0 +1 @@
|
||||
name = df_caverns
|
118
df_caverns/oil_sea.lua
Normal file
@ -0,0 +1,118 @@
|
||||
if not df_caverns.config.enable_oil_sea then
|
||||
return
|
||||
end
|
||||
|
||||
local c_oil = minetest.get_content_id("oil:oil_source")
|
||||
local c_gas = minetest.get_content_id("oil:gas")
|
||||
local c_lava = minetest.get_content_id("default:lava_source")
|
||||
local c_obsidian = minetest.get_content_id("default:obsidian")
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
local perlin_cave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=300, y=300, z=300},
|
||||
seed = 6000089,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
-- large-scale rise and fall
|
||||
local perlin_wave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=1000, y=1000, z=1000},
|
||||
seed = 10089,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
local median = df_caverns.config.oil_sea_level
|
||||
local floor_mult = -80
|
||||
local floor_displace = 60
|
||||
local ceiling_mult = 40
|
||||
local ceiling_displace = -30
|
||||
local wave_mult = 10
|
||||
|
||||
local c_lava_set
|
||||
|
||||
local y_max = median + 2*wave_mult + 2*ceiling_mult + ceiling_displace
|
||||
local y_min = median - 2*wave_mult + 2*floor_mult + floor_displace
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--if out of range of cave definition limits, abort
|
||||
if minp.y > y_max or maxp.y < y_min then
|
||||
return
|
||||
end
|
||||
|
||||
local t_start = os.clock()
|
||||
|
||||
local vm, data, area = mapgen_helper.mapgen_vm_data()
|
||||
|
||||
local nvals_cave = mapgen_helper.perlin2d("df_caverns:oil_cave", minp, maxp, perlin_cave)
|
||||
local nvals_wave = mapgen_helper.perlin2d("df_caverns:oil_wave", minp, maxp, perlin_wave)
|
||||
|
||||
if c_lava_set == nil then
|
||||
c_lava_set = {}
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
if def.groups ~= nil and def.groups.lava ~= nil then
|
||||
c_lava_set[minetest.get_content_id(name)] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for vi, x, y, z in area:iterp_yxz(minp, maxp) do
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
|
||||
local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
|
||||
local floor_height = math.floor(abs_cave * floor_mult + floor_displace + median + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
|
||||
if y > floor_height - 5 and y < ceiling_height + 5 then
|
||||
if c_lava_set[data[vi]] then
|
||||
data[vi] = c_obsidian
|
||||
end
|
||||
end
|
||||
if y > floor_height and y < ceiling_height then
|
||||
if y > median then
|
||||
data[vi] = c_gas
|
||||
else
|
||||
data[vi] = c_oil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--send data back to voxelmanip
|
||||
vm:set_data(data)
|
||||
--calc lighting
|
||||
vm:set_lighting({day = 0, night = 0})
|
||||
vm:calc_lighting()
|
||||
|
||||
vm:update_liquids()
|
||||
--write it to world
|
||||
vm:write_to_map()
|
||||
|
||||
local chunk_generation_time = math.ceil((os.clock() - t_start) * 1000) --grab how long it took
|
||||
if chunk_generation_time < 1000 then
|
||||
minetest.log("info", "[df_caverns] oil sea mapblock generation took "..chunk_generation_time.." ms") --tell people how long
|
||||
else
|
||||
minetest.log("warning", "[df_caverns] oil sea took "..chunk_generation_time.." ms to generate map block "
|
||||
.. minetest.pos_to_string(minp) .. minetest.pos_to_string(maxp))
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = "oil:gas_seep",
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 32 * 32 * 32,
|
||||
clust_num_ores = 27,
|
||||
clust_size = 6,
|
||||
y_max = df_caverns.config.sunless_sea_min,
|
||||
y_min = y_min,
|
||||
})
|
35
df_caverns/schematics/lamppost.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local outer_stair = "stairs:stair_outer_slade_brick"
|
||||
if stairs.register_stair_outer == nil then -- 0.4.16 compatibility
|
||||
outer_stair = "df_underworld_items:slade_brick"
|
||||
end
|
||||
|
||||
local n1 = { name = "df_underworld_items:slade_block", force_place=true }
|
||||
local n2 = { name = outer_stair, param2 = 1, force_place=true }
|
||||
local n3 = { name = "stairs:stair_slade_brick", force_place=true }
|
||||
local n4 = { name = outer_stair, force_place=true }
|
||||
local n5 = { name = "air", force_place=true }
|
||||
local n6 = { name = "df_underworld_items:slade_seal", force_place=true }
|
||||
local n7 = { name = "stairs:stair_slade_brick", param2 = 1, force_place=true }
|
||||
local n8 = { name = "df_underworld_items:slade_brick", force_place=true }
|
||||
local n9 = { name = "stairs:stair_slade_brick", param2 = 3, force_place=true }
|
||||
local n10 = { name = "df_underworld_items:slade_wall", force_place=true }
|
||||
local n11 = { name = "default:meselamp", force_place=true }
|
||||
local n12 = { name = outer_stair, param2 = 2, force_place=true }
|
||||
local n13 = { name = "stairs:stair_slade_brick", param2 = 2, force_place=true }
|
||||
local n14 = { name = outer_stair, param2 = 3, force_place=true }
|
||||
|
||||
return {
|
||||
name = "df_caverns:lamppost",
|
||||
size = {x = 3, y = 15, z = 3},
|
||||
center_pos = {x = 1, y = 7, z = 1},
|
||||
data = {
|
||||
n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1,
|
||||
n1, n1, n1, n1, n1, n1, n1, n2, n3, n4, n5, n5, n5, n5, n5, n5, n5,
|
||||
n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n1, n1, n1, n1, n5, n1,
|
||||
n1, n5, n1, n1, n5, n1, n1, n5, n1, n1, n5, n1, n1, n5, n1, n1, n6,
|
||||
n1, n7, n8, n9, n5, n8, n5, n5, n8, n5, n5, n10, n5, n5, n10, n5, n5,
|
||||
n11, n5, n5, n5, n5, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1,
|
||||
n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n12, n13, n14, n5,
|
||||
n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5, n5,
|
||||
}
|
||||
}
|
120
df_caverns/schematics/medium_building.lua
Normal file
@ -0,0 +1,120 @@
|
||||
local outer_stair = "stairs:stair_outer_slade_brick"
|
||||
if stairs.register_stair_outer == nil then -- 0.4.16 compatibility
|
||||
outer_stair = "df_underworld_items:slade_brick"
|
||||
end
|
||||
|
||||
local n1 = { name = "ignore"}
|
||||
local n8 = { name = "air", force_place=true }
|
||||
|
||||
local n3 = { name = "df_underworld_items:slade_brick", force_place=true }
|
||||
local n4 = { name = "df_underworld_items:slade_wall", force_place=true }
|
||||
local n5 = { name = outer_stair, param2 = 1, force_place=true }
|
||||
local n6 = { name = "stairs:stair_slade_brick", force_place=true }
|
||||
local n7 = { name = outer_stair, force_place=true }
|
||||
local n9 = { name = "stairs:slab_slade_brick", param2 = 23, force_place=true }
|
||||
local n10 = { name = "stairs:stair_slade_brick", param2 = 1, force_place=true }
|
||||
local n11 = { name = "stairs:stair_slade_brick", param2 = 3, force_place=true }
|
||||
local n14 = { name = "stairs:stair_slade_brick", param2 = 23, force_place=true }
|
||||
local n15 = { name = outer_stair, param2 = 2, force_place=true }
|
||||
local n16 = { name = "stairs:stair_slade_brick", param2 = 2, force_place=true }
|
||||
local n17 = { name = outer_stair, param2 = 3, force_place=true }
|
||||
|
||||
-- foundation nodes
|
||||
local n2 = { name = "df_underworld_items:slade_brick", force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n12 = { name = "df_underworld_items:slade_wall", force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n13 = { name = "stairs:stair_slade_brick", param2 = 1, force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
|
||||
|
||||
return {
|
||||
name = "df_caverns:medium_building",
|
||||
size = {x = 15, y = 12, z = 8},
|
||||
center_pos = {x = 10, y = 6, z = 3},
|
||||
data = {
|
||||
n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1,
|
||||
n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1,
|
||||
n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1,
|
||||
n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n3, n3, n3,
|
||||
n3, n3, n3, n3, n3, n1, n1, n1, n1, n1, n1, n1, n3, n4, n4, n4, n4,
|
||||
n4, n4, n3, n1, n1, n1, n1, n1, n1, n1, n3, n4, n4, n4, n4, n4, n4,
|
||||
n3, n1, n1, n1, n1, n1, n1, n1, n3, n3, n3, n3, n3, n3, n3, n3, n1,
|
||||
n1, n1, n1, n1, n1, n1, n3, n4, n4, n4, n4, n4, n4, n3, n1, n1, n1,
|
||||
n1, n1, n1, n1, n3, n4, n4, n4, n4, n4, n4, n3, n1, n1, n1, n1, n1,
|
||||
n1, n1, n5, n6, n6, n6, n6, n6, n6, n7, n1, n1, n1, n1, n1, n1, n1,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2,
|
||||
n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n1, n1, n1, n1, n1, n1, n1, n3, n3, n3, n3, n3, n3, n3, n3, n1, n1,
|
||||
n1, n1, n1, n1, n8, n4, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1,
|
||||
n1, n1, n8, n4, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1,
|
||||
n1, n3, n9, n9, n9, n9, n9, n9, n3, n1, n1, n1, n1, n1, n1, n1, n4,
|
||||
n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n4, n8, n8,
|
||||
n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n10, n9, n9, n9, n9,
|
||||
n9, n9, n11, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n1, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n1, n1, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1,
|
||||
n1, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1,
|
||||
n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1,
|
||||
n12, n12, n3, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1, n1, n1, n1,
|
||||
n12, n3, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n8, n3,
|
||||
n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n3, n9, n9,
|
||||
n9, n9, n9, n9, n3, n1, n1, n1, n1, n1, n1, n1, n4, n8, n8, n8, n8,
|
||||
n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n4, n8, n8, n8, n8, n8, n8,
|
||||
n4, n1, n1, n1, n1, n1, n1, n1, n10, n9, n9, n9, n9, n9, n9, n11, n1,
|
||||
n13, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n13,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n13, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n13, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n13, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n13, n3, n3, n3, n3,
|
||||
n3, n3, n3, n3, n1, n1, n1, n1, n1, n1, n8, n8, n8, n8, n8, n8, n8,
|
||||
n8, n4, n1, n1, n1, n1, n1, n1, n8, n8, n8, n8, n8, n8, n8, n8, n4,
|
||||
n1, n1, n1, n1, n1, n1, n1, n3, n9, n9, n9, n9, n9, n9, n3, n1, n1,
|
||||
n1, n1, n1, n1, n1, n4, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1,
|
||||
n1, n1, n1, n4, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1,
|
||||
n1, n10, n9, n9, n9, n9, n9, n9, n11, n1, n13, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n13, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n1, n1, n1, n13, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n2, n1, n1, n1, n1, n13, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n1, n1, n1, n1, n1, n13, n2, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n1, n1, n1, n1, n1, n1, n13, n3, n3, n3, n3, n3, n3, n3, n3, n1, n1,
|
||||
n1, n1, n1, n1, n8, n8, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1,
|
||||
n1, n1, n8, n8, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1,
|
||||
n1, n3, n9, n9, n9, n9, n9, n9, n3, n1, n1, n1, n1, n1, n1, n1, n4,
|
||||
n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n4, n8, n8,
|
||||
n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n10, n9, n9, n9, n9,
|
||||
n9, n9, n11, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n1, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n1, n1, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1,
|
||||
n1, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1,
|
||||
n12, n12, n12, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1,
|
||||
n12, n12, n3, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1, n1, n1, n1,
|
||||
n12, n3, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n8, n3,
|
||||
n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n3, n9, n9,
|
||||
n9, n9, n9, n9, n3, n1, n1, n1, n1, n1, n1, n1, n4, n8, n8, n8, n8,
|
||||
n8, n8, n4, n1, n1, n1, n1, n1, n1, n1, n4, n8, n8, n8, n8, n8, n8,
|
||||
n4, n1, n1, n1, n1, n1, n1, n1, n10, n9, n9, n9, n9, n9, n9, n11, n1,
|
||||
n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1,
|
||||
n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1,
|
||||
n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n3, n3, n3, n3,
|
||||
n3, n3, n3, n3, n1, n1, n1, n1, n1, n1, n8, n4, n8, n8, n14, n11, n8,
|
||||
n8, n4, n1, n1, n1, n1, n1, n1, n8, n4, n8, n14, n11, n8, n8, n8, n4,
|
||||
n1, n1, n1, n1, n1, n1, n1, n3, n14, n11, n8, n8, n8, n9, n3, n1, n1,
|
||||
n1, n1, n1, n1, n1, n4, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1,
|
||||
n1, n1, n1, n4, n8, n8, n8, n8, n8, n8, n4, n1, n1, n1, n1, n1, n1,
|
||||
n1, n10, n9, n9, n9, n9, n9, n9, n11, n1, n1, n1, n1, n1, n1, n1, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n1, n1, n1, n1, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1,
|
||||
n1, n1, n1, n1, n1, n1, n3, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1,
|
||||
n1, n1, n1, n1, n3, n4, n4, n4, n4, n4, n4, n3, n1, n1, n1, n1, n1,
|
||||
n1, n1, n3, n4, n4, n4, n4, n4, n4, n3, n1, n1, n1, n1, n1, n1, n1,
|
||||
n3, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1, n1, n1, n1, n1, n3, n4,
|
||||
n4, n4, n4, n4, n4, n3, n1, n1, n1, n1, n1, n1, n1, n3, n4, n4, n4,
|
||||
n4, n4, n4, n3, n1, n1, n1, n1, n1, n1, n1, n15, n16, n16, n16, n16,
|
||||
n16, n16, n17,
|
||||
}
|
||||
}
|
29
df_caverns/schematics/oubliette.lua
Normal file
@ -0,0 +1,29 @@
|
||||
local outer_stair = "stairs:stair_outer_slade_brick"
|
||||
if stairs.register_stair_outer == nil then -- 0.4.16 compatibility
|
||||
outer_stair = "df_underworld_items:slade_brick"
|
||||
end
|
||||
|
||||
local n1 = { name = "df_underworld_items:slade_block", force_place=true }
|
||||
local n2 = { name = outer_stair, param2 = 1, force_place=true }
|
||||
local n3 = { name = "stairs:stair_slade_brick", force_place=true }
|
||||
local n4 = { name = outer_stair, force_place=true }
|
||||
local n5 = { name = "air", force_place=true }
|
||||
local n6 = { name = "df_underworld_items:slade_seal", force_place=true }
|
||||
local n7 = { name = "stairs:stair_slade_brick", param2 = 1, force_place=true }
|
||||
local n8 = { name = "stairs:stair_slade_brick", param2 = 3, force_place=true }
|
||||
local n9 = { name = outer_stair, param2 = 2, force_place=true }
|
||||
local n10 = { name = "stairs:stair_slade_brick", param2 = 2, force_place=true }
|
||||
local n11 = { name = outer_stair, param2 = 3, force_place=true }
|
||||
|
||||
return {
|
||||
name="df_caverns:oubliette",
|
||||
size = {x = 3, y = 9, z = 3},
|
||||
center_pos = {x = 1, y = 7, z = 1},
|
||||
data = {
|
||||
n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1,
|
||||
n1, n1, n1, n1, n1, n1, n1, n2, n3, n4, n1, n1, n1, n1, n5, n1, n1,
|
||||
n5, n1, n1, n5, n1, n1, n5, n1, n1, n5, n1, n1, n5, n1, n1, n6, n1,
|
||||
n7, n5, n8, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n1,
|
||||
n1, n1, n1, n1, n1, n1, n1, n1, n1, n1, n9, n10, n11,
|
||||
},
|
||||
}
|
76
df_caverns/schematics/small_building.lua
Normal file
@ -0,0 +1,76 @@
|
||||
local outer_stair = "stairs:stair_outer_slade_brick"
|
||||
if stairs.register_stair_outer == nil then -- 0.4.16 compatibility
|
||||
outer_stair = "df_underworld_items:slade_brick"
|
||||
end
|
||||
|
||||
local n1 = { name = "ignore" }
|
||||
local n10 = { name = "air", force_place=true }
|
||||
|
||||
local n3 = { name = "df_underworld_items:slade_brick", force_place=true }
|
||||
local n4 = { name = "df_underworld_items:slade_wall", force_place=true }
|
||||
local n5 = { name = outer_stair, param2 = 1, force_place=true }
|
||||
local n6 = { name = "stairs:stair_slade_brick", force_place=true }
|
||||
local n7 = { name = outer_stair, force_place=true }
|
||||
local n11 = { name = "stairs:stair_slade_brick", param2 = 1, force_place=true }
|
||||
local n12 = { name = "stairs:slab_slade_brick", param2 = 22, force_place=true}
|
||||
local n13 = { name = "stairs:stair_slade_brick", param2 = 3, force_place=true }
|
||||
local n15 = { name = outer_stair, param2 = 2, force_place=true }
|
||||
local n16 = { name = "stairs:stair_slade_brick", param2 = 2, force_place=true }
|
||||
local n17 = { name = outer_stair, param2 = 3, force_place=true }
|
||||
|
||||
-- foundation nodes
|
||||
local n2 = { name = "df_underworld_items:slade_brick", force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n8 = { name = "stairs:stair_slade_brick", param2 = 2, force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n9 = { name = "stairs:stair_slade_brick", force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n14 = { name = "stairs:stair_slade_brick", param2 = 1, force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
|
||||
return {
|
||||
name = "df_caverns:small_building",
|
||||
size = {x = 11, y = 9, z = 7},
|
||||
center_pos = {x = 7, y = 5, z = 3},
|
||||
data = {
|
||||
n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1,
|
||||
n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n2, n2, n2,
|
||||
n2, n2, n2, n2, n1, n1, n1, n1, n3, n3, n3, n3, n3, n3, n3, n1, n1,
|
||||
n1, n1, n3, n4, n4, n4, n4, n4, n3, n1, n1, n1, n1, n3, n4, n4, n4,
|
||||
n4, n4, n3, n1, n1, n1, n1, n5, n6, n6, n6, n6, n6, n7, n1, n1, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n8, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n9, n2, n2, n2, n2, n2, n2,
|
||||
n2, n1, n1, n1, n1, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1, n10, n4,
|
||||
n10, n10, n10, n10, n10, n4, n1, n1, n1, n10, n4, n10, n10, n10, n10,
|
||||
n10, n4, n1, n1, n1, n1, n11, n12, n12, n12, n12, n12, n13, n1, n1,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n1, n1, n8, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n1, n1, n1, n9, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1, n10,
|
||||
n3, n10, n10, n10, n10, n10, n4, n1, n1, n1, n10, n3, n10, n10, n10,
|
||||
n10, n10, n4, n1, n1, n1, n1, n11, n12, n12, n12, n12, n12, n13, n14,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n14, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n2, n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1,
|
||||
n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n1, n1, n1, n2, n3, n3, n3, n3, n3, n3, n3, n1, n1, n1,
|
||||
n10, n10, n10, n10, n10, n10, n10, n4, n1, n1, n1, n10, n10, n10,
|
||||
n10, n10, n10, n10, n4, n1, n1, n1, n1, n11, n12, n12, n12, n12, n12,
|
||||
n13, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n1, n1, n9, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n1, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n2, n2, n2,
|
||||
n2, n2, n2, n2, n2, n1, n1, n1, n8, n3, n3, n3, n3, n3, n3, n3, n1,
|
||||
n1, n1, n10, n3, n10, n10, n10, n10, n10, n4, n1, n1, n1, n10, n3,
|
||||
n10, n10, n10, n10, n10, n4, n1, n1, n1, n1, n11, n12, n12, n12, n12,
|
||||
n12, n13, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2,
|
||||
n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2,
|
||||
n2, n1, n1, n9, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n8, n2,
|
||||
n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n3, n3, n3, n3, n3, n3, n3,
|
||||
n1, n1, n1, n10, n4, n10, n10, n10, n10, n10, n4, n1, n1, n1, n10,
|
||||
n4, n10, n10, n10, n10, n10, n4, n1, n1, n1, n1, n11, n12, n12, n12,
|
||||
n12, n12, n13, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1,
|
||||
n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n2, n2, n2, n2, n2, n2,
|
||||
n2, n2, n2, n1, n1, n2, n2, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1,
|
||||
n1, n2, n2, n2, n2, n2, n2, n2, n1, n1, n1, n1, n3, n3, n3, n3, n3,
|
||||
n3, n3, n1, n1, n1, n1, n3, n4, n4, n4, n4, n4, n3, n1, n1, n1, n1,
|
||||
n3, n4, n4, n4, n4, n4, n3, n1, n1, n1, n1, n15, n16, n16, n16, n16,
|
||||
n16, n17,
|
||||
}
|
||||
}
|
21
df_caverns/schematics/small_slab.lua
Normal file
@ -0,0 +1,21 @@
|
||||
local inner_stair = "stairs:stair_inner_slade_brick"
|
||||
if stairs.register_stair_inner == nil then -- 0.4.16 compatibility
|
||||
inner_stair = "df_underworld_items:slade_brick"
|
||||
end
|
||||
|
||||
|
||||
local n1 = { name = "df_underworld_items:slade_brick", force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n2 = { name = inner_stair, param2 = 1, force_place=true }
|
||||
local n3 = { name = inner_stair, force_place=true }
|
||||
local n4 = { name = "df_underworld_items:slade_brick", force_place=true }
|
||||
local n5 = { name = inner_stair, param2 = 2, force_place=true }
|
||||
local n6 = { name = inner_stair, param2 = 3, force_place=true }
|
||||
|
||||
return {
|
||||
name = "df_caverns:small_slab",
|
||||
size = {y = 2, x = 2, z = 3},
|
||||
center_pos = {x = 1, y = 1, z = 1},
|
||||
data = {
|
||||
n1, n1, n2, n3, n1, n1, n4, n4, n1, n1, n5, n6,
|
||||
}
|
||||
}
|
BIN
df_caverns/screenshots/black_cap.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
df_caverns/screenshots/bloodthorn.jpg
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
df_caverns/screenshots/cave_coral_snareweed.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
df_caverns/screenshots/crystals.jpg
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
df_caverns/screenshots/farmable_plants.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
df_caverns/screenshots/fungiwood.jpg
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
df_caverns/screenshots/glowing_pit.jpg
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
df_caverns/screenshots/goblin_cap.jpg
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
df_caverns/screenshots/magma_sea_mese.jpg
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
df_caverns/screenshots/mine_gas.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
df_caverns/screenshots/nethercap.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
df_caverns/screenshots/spore_tree.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
df_caverns/screenshots/sunless_river.jpg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
df_caverns/screenshots/tower_cap.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
df_caverns/screenshots/tunnel_tube.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
df_caverns/screenshots/underworld.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
40
df_caverns/settingtypes.txt
Normal file
@ -0,0 +1,40 @@
|
||||
[Cavern dimensions]
|
||||
#Note that this doesn't guarantee caverns of this setting's size. This setting
|
||||
#affects the scale of features in the perlin noise that is used to build caverns.
|
||||
#Most caverns will be smaller than this (and a few might be larger)
|
||||
dfcaverns_vertical_cavern_scale (Vertical cavern dimension scale) float 256
|
||||
#Note that this doesn't guarantee caverns of this setting's size. This setting
|
||||
#affects the scale of features in the perlin noise that is used to build caverns.
|
||||
#Most caverns will be smaller than this (and a few might be larger)
|
||||
dfcaverns_horizontal_cavern_scale (Horizontal cavern dimension scale) float 256
|
||||
#Determines threshold for cave generation. Higher number means sparser, smaller caverns
|
||||
dfcaverns_cavern_threshold (Cavern threshold) float 0.5 0.0 1.0
|
||||
#Determines threshold for lower sea cave generation. Higher number means sparser, smaller caverns
|
||||
dfcaverns_sunless_sea_threshold (Cavern threshold for sunless sea) float 0.4 0.0 1.0
|
||||
#Determines how far out water extends into tunnels below the 'sea level' of from flooded
|
||||
#caverns. Lower numbers give more flooded tunnel. If this number equals the cavern
|
||||
#threshold tunnels will not be flooded at all, if it is 0 then half the tunnels will be flooded.
|
||||
dfcaverns_tunnel_flooding_threshold (Tunnel flooding threshold) float 0.25 0.0 1.0
|
||||
|
||||
[Cavern depth borders]
|
||||
#maximum boundary for cavern depths are most efficient when they fit the formula (x*80-32-1)
|
||||
#where x is an integer. That way you don't get map blocks that straddle two cavern layers.
|
||||
dfcaverns_ymax (Upper limit of level 1) int -193
|
||||
#minimum boundaries for cavern depths are most efficient when they fit the formula (x*80-32)
|
||||
#where x is an integer. that way you don't get map blocks that straddle two cavern layers.
|
||||
dfcaverns_level1_min (Upper limit of level 2) int -832
|
||||
dfcaverns_level2_min (Upper limit of level 3) int -1472
|
||||
dfcaverns_level3_min (Upper limit of the sunless sea) int -2112
|
||||
dfcaverns_sunless_sea_min (Lower limit of the sunless sea) int -2512
|
||||
|
||||
[Lower Levels]
|
||||
dfcaverns_enable_oil_sea (Generate oil sea) bool true
|
||||
dfcaverns_oil_sea_level (Oil sea level) int -2700
|
||||
|
||||
dfcaverns_enable_lava_sea (Generate magma sea) bool true
|
||||
dfcaverns_lava_sea_level (Lava sea level) int -2900
|
||||
|
||||
dfcaverns_enable_underworld (Generate underworld) bool true
|
||||
dfcaverns_underworld_level (Underworld level) int -3200
|
||||
#Set this to 0 to disable glowing pit generation entirely.
|
||||
dfcaverns_underworld_glowing_pit_mapblocks(Average pit spacing measured in mapblocks) int 8
|
210
df_caverns/shared.lua
Normal file
@ -0,0 +1,210 @@
|
||||
-- This file contains code that is used by multiple different cavern layers.
|
||||
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_dirt = minetest.get_content_id("default:dirt")
|
||||
local c_gravel = minetest.get_content_id("default:gravel")
|
||||
|
||||
local c_dirt_moss = minetest.get_content_id("df_mapitems:dirt_with_cave_moss")
|
||||
local c_cobble_fungus = minetest.get_content_id("df_mapitems:cobble_with_floor_fungus")
|
||||
local c_cobble_fungus_fine = minetest.get_content_id("df_mapitems:cobble_with_floor_fungus_fine")
|
||||
local c_cobble = minetest.get_content_id("default:cobble")
|
||||
local c_mossycobble = minetest.get_content_id("default:mossycobble")
|
||||
|
||||
local c_wet_flowstone = minetest.get_content_id("df_mapitems:wet_flowstone")
|
||||
local c_dry_flowstone = minetest.get_content_id("df_mapitems:dry_flowstone")
|
||||
|
||||
df_caverns.data_param2 = {}
|
||||
|
||||
--------------------------------------------------
|
||||
|
||||
df_caverns.stalagmites = function(abs_cracks, vert_rand, vi, area, data, data_param2, wet, reverse_sign)
|
||||
local flowstone
|
||||
local stalagmite_ids
|
||||
if wet then
|
||||
flowstone = c_wet_flowstone
|
||||
stalagmite_ids = df_mapitems.wet_stalagmite_ids
|
||||
else
|
||||
flowstone = c_dry_flowstone
|
||||
stalagmite_ids = df_mapitems.dry_stalagmite_ids
|
||||
end
|
||||
|
||||
local height_mult = 1
|
||||
local ystride = area.ystride
|
||||
if reverse_sign then
|
||||
ystride = - ystride
|
||||
height_mult = -1
|
||||
end
|
||||
|
||||
if vert_rand < 0.004 then
|
||||
if reverse_sign then
|
||||
subterrane.big_stalactite(vi+ystride, area, data, 6, 15, flowstone, flowstone, flowstone)
|
||||
else
|
||||
subterrane.big_stalagmite(vi+ystride, area, data, 6, 15, flowstone, flowstone, flowstone)
|
||||
end
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 50)
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, height*height_mult, stalagmite_ids)
|
||||
end
|
||||
data[vi] = flowstone
|
||||
end
|
||||
|
||||
df_caverns.stalactites = function(abs_cracks, vert_rand, vi, area, data, data_param2, wet)
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, wet, true)
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
df_caverns.flooded_cavern_floor = function(abs_cracks, vert_rand, vi, area, data)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.25 then
|
||||
data[vi] = c_mossycobble
|
||||
elseif data[vi-ystride] ~= c_water then
|
||||
data[vi] = c_dirt
|
||||
end
|
||||
|
||||
-- put in only the large stalagmites that won't get in the way of the water
|
||||
if abs_cracks < 0.1 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalagmite(vi+ystride, area, data, 6, 15, c_wet_flowstone, c_wet_flowstone, c_wet_flowstone)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local c_dead_fungus
|
||||
if minetest.get_modpath("df_farming") then
|
||||
c_dead_fungus = minetest.get_content_id("df_farming:dead_fungus")
|
||||
end
|
||||
|
||||
df_caverns.dry_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.075 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
elseif abs_cracks < 0.4 then
|
||||
data[vi] = c_cobble
|
||||
elseif abs_cracks < 0.6 then
|
||||
data[vi] = c_cobble_fungus_fine
|
||||
else
|
||||
data[vi] = c_cobble_fungus
|
||||
if c_dead_fungus and math.random() < 0.05 then
|
||||
data[vi+area.ystride] = c_dead_fungus
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
df_caverns.wet_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif abs_cracks < 0.6 then
|
||||
data[vi] = c_cobble
|
||||
else
|
||||
data[vi] = c_mossycobble
|
||||
if c_dead_fungus and math.random() < 0.05 then
|
||||
data[vi+area.ystride] = c_dead_fungus
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
|
||||
df_caverns.glow_worm_cavern_ceiling = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif abs_cracks < 0.5 and abs_cracks > 0.3 and math.random() < 0.3 then
|
||||
df_mapitems.glow_worm_ceiling(area, data, vi-area.ystride)
|
||||
end
|
||||
end
|
||||
|
||||
local content_in_list=function(content, list)
|
||||
for i, v in ipairs(list) do
|
||||
if content == v then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
df_caverns.tunnel_floor = function(minp, maxp, area, vi, nvals_cracks, data, data_param2, wet)
|
||||
local ystride = area.ystride
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
|
||||
if wet then
|
||||
if abs_cracks < 0.05 and data[vi+ystride] == c_air and not content_in_list(data[vi], df_mapitems.wet_stalagmite_ids) then -- make sure data[vi] is not already flowstone. Stalagmites from lower levels are acting as base for further stalagmites
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 100)
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, height, df_mapitems.wet_stalagmite_ids)
|
||||
data[vi] = c_wet_flowstone
|
||||
end
|
||||
else
|
||||
if abs_cracks < 0.025 and data[vi+ystride] == c_air and not content_in_list(data[vi], df_mapitems.dry_stalagmite_ids) then -- make sure data[vi] is not already flowstone. Stalagmites from lower levels are acting as base for further stalagmites
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 100)
|
||||
subterrane.stalagmite(vi+ystride, area, data, data_param2, param2, height, df_mapitems.dry_stalagmite_ids)
|
||||
elseif cracks > 0.5 and data[vi-ystride] ~= c_air then
|
||||
data[vi] = c_gravel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
df_caverns.tunnel_ceiling = function(minp, maxp, area, vi, nvals_cracks, data, data_param2, wet)
|
||||
local ystride = area.ystride
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
|
||||
if wet then
|
||||
if abs_cracks < 0.05 and data[vi-ystride] == c_air and not content_in_list(data[vi], df_mapitems.wet_stalagmite_ids) then -- make sure data[vi] is not already flowstone. Stalagmites from lower levels are acting as base for further stalagmites
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 100)
|
||||
subterrane.stalactite(vi-ystride, area, data, data_param2, param2, height, df_mapitems.wet_stalagmite_ids)
|
||||
data[vi] = c_wet_flowstone
|
||||
end
|
||||
else
|
||||
if abs_cracks < 0.025 and data[vi-ystride] == c_air and not content_in_list(data[vi], df_mapitems.dry_stalagmite_ids) then -- make sure data[vi] is not already flowstone. Stalagmites from lower levels are acting as base for further stalagmites
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 100)
|
||||
subterrane.stalactite(vi-ystride, area, data, data_param2, param2, height, df_mapitems.dry_stalagmite_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
df_caverns.perlin_cave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=df_caverns.config.horizontal_cavern_scale, y=df_caverns.config.vertical_cavern_scale, z=df_caverns.config.horizontal_cavern_scale},
|
||||
seed = -400000000089,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
df_caverns.perlin_wave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=df_caverns.config.horizontal_cavern_scale * 2, y=df_caverns.config.vertical_cavern_scale, z=df_caverns.config.horizontal_cavern_scale * 2}, -- squashed 2:1
|
||||
seed = 59033,
|
||||
octaves = 6,
|
||||
persist = 0.63
|
||||
}
|
||||
|
||||
-- Used for making lines of dripstone, and in various other places where small-scale patterns are needed
|
||||
df_caverns.np_cracks = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x = 20, y = 20, z = 20},
|
||||
seed = 5717,
|
||||
octaves = 3,
|
||||
persist = 0.63,
|
||||
lacunarity = 2.0,
|
||||
}
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
df_caverns.place_shrub = function(vi, area, data, param2_data, shrub_list)
|
||||
if shrub_list == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local shrub = shrub_list[math.random(#shrub_list)]
|
||||
shrub(vi, area, data, param2_data)
|
||||
end
|
391
df_caverns/sunless_sea.lua
Normal file
@ -0,0 +1,391 @@
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_dirt = minetest.get_content_id("default:dirt")
|
||||
local c_dirt_moss = minetest.get_content_id("df_mapitems:dirt_with_cave_moss")
|
||||
local c_sand = minetest.get_content_id("default:sand")
|
||||
local c_gravel = minetest.get_content_id("default:gravel")
|
||||
local c_wet_flowstone = minetest.get_content_id("df_mapitems:wet_flowstone")
|
||||
local c_dry_flowstone = minetest.get_content_id("df_mapitems:dry_flowstone")
|
||||
local c_lava = minetest.get_content_id("default:lava_source")
|
||||
local c_obsidian = minetest.get_content_id("default:obsidian")
|
||||
|
||||
local mushroom_shrublist
|
||||
local fungispore_shrublist
|
||||
|
||||
if minetest.get_modpath("df_farming") then
|
||||
mushroom_shrublist = {
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_plump_helmet_vm,
|
||||
df_farming.spawn_dimple_cup_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
fungispore_shrublist = {
|
||||
df_farming.spawn_pig_tail_vm,
|
||||
df_farming.spawn_sweet_pod_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_cave_wheat_vm,
|
||||
df_farming.spawn_dead_fungus_vm,
|
||||
df_farming.spawn_cavern_fungi_vm,
|
||||
}
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
local perlin_cave_sunless_sea = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=df_caverns.config.horizontal_cavern_scale * 2, y=df_caverns.config.vertical_cavern_scale * 0.5, z=df_caverns.config.horizontal_cavern_scale * 2},
|
||||
seed = -400000000089,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
local perlin_wave_sunless_sea = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=df_caverns.config.horizontal_cavern_scale * 4, y=df_caverns.config.vertical_cavern_scale * 0.5, z=df_caverns.config.horizontal_cavern_scale * 4}, -- squashed 2:1
|
||||
seed = 59033,
|
||||
octaves = 6,
|
||||
persist = 0.63
|
||||
}
|
||||
|
||||
local perlin_cave_rivers = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=400, y=400, z=400},
|
||||
seed = -400000000089,
|
||||
octaves = 3,
|
||||
persist = 0.67,
|
||||
flags = "", -- remove "eased" flag, makes the paths of rivers a bit jaggedier and more interesting that curvy smooth paths
|
||||
}
|
||||
|
||||
-- large-scale rise and fall to make the seam between roof and floor less razor-flat and make the rivers shallower and deeper in various places
|
||||
local perlin_wave_rivers = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=800, y=800, z=800},
|
||||
seed = -4000089,
|
||||
octaves = 3,
|
||||
persist = 0.67,
|
||||
}
|
||||
|
||||
local sea_level = df_caverns.config.level3_min - (df_caverns.config.level3_min - df_caverns.config.sunless_sea_min) * 0.5
|
||||
|
||||
local floor_mult = 100
|
||||
local floor_displace = -10
|
||||
local ceiling_mult = -200
|
||||
local ceiling_displace = 20
|
||||
local wave_mult = 7
|
||||
local ripple_mult = 15
|
||||
local y_max_river = sea_level + 2*wave_mult + ceiling_displace + ripple_mult
|
||||
local y_min_river = sea_level - 2*wave_mult + floor_displace
|
||||
|
||||
local hot_zone_boundary = 70
|
||||
local middle_zone_boundary = 50
|
||||
local cool_zone_boundary = 30
|
||||
|
||||
local mushroom_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air and data[vi-ystride] ~= c_water then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, mushroom_shrublist)
|
||||
elseif abs_cracks > 0.25 then
|
||||
if math.random() < 0.01 then
|
||||
df_trees.spawn_tower_cap_vm(vi+ystride, area, data)
|
||||
elseif math.random() < 0.01 then
|
||||
df_trees.spawn_goblin_cap_vm(vi+ystride, area, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local fungispore_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, true)
|
||||
elseif data[vi-ystride] ~= c_air and data[vi-ystride] ~= c_water then -- leave the ground as rock if it's only one node thick
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt
|
||||
else
|
||||
data[vi] = c_dirt_moss
|
||||
end
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, fungispore_shrublist)
|
||||
elseif abs_cracks > 0.35 then
|
||||
if math.random() < 0.025 then
|
||||
df_trees.spawn_fungiwood_vm(vi+ystride, area, data)
|
||||
elseif math.random() < 0.025 then
|
||||
df_trees.spawn_spore_tree_vm(vi+ystride, area, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local cool_zone_ceiling = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
end
|
||||
|
||||
local hot_zone_ceiling = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
-- dry zone ceiling, add crystals
|
||||
if abs_cracks < 0.1 then
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
if abs_cracks > 0.3 and math.random() < 0.005 then
|
||||
df_mapitems.place_big_crystal_cluster(area, data, data_param2, vi, math.random(0,3), true)
|
||||
end
|
||||
end
|
||||
|
||||
local cool_zone_floor = df_caverns.dry_cavern_floor
|
||||
|
||||
local hot_zone_floor = function(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.075 then
|
||||
df_caverns.stalagmites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
elseif abs_cracks > 0.3 and math.random() < 0.005 then
|
||||
df_mapitems.place_big_crystal_cluster(area, data, data_param2, vi+area.ystride, math.random(0,2), false)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local decorate_sunless_sea = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
math.randomseed(minp.x + minp.y*2^8 + minp.z*2^16 + seed) -- make decorations consistent between runs
|
||||
|
||||
local heatmap = minetest.get_mapgen_object("heatmap")
|
||||
local data_param2 = df_caverns.data_param2
|
||||
vm:get_param2_data(data_param2)
|
||||
local nvals_cracks = mapgen_helper.perlin2d("df_cavern:cracks", minp, maxp, df_caverns.np_cracks)
|
||||
|
||||
local minp_below = minp.y <= sea_level
|
||||
local maxp_above = maxp.y > sea_level
|
||||
|
||||
local nvals_cave = mapgen_helper.perlin2d("df_caverns:sunless_sea", minp, maxp, perlin_cave_rivers) --cave noise for structure
|
||||
local nvals_wave = mapgen_helper.perlin2d("df_caverns:sunless_sea_wave", minp, maxp, perlin_wave_rivers) --cave noise for structure
|
||||
|
||||
local skip_next = false -- mapgen is proceeding upward on the y axis,
|
||||
--if this is true it skips a step to allow for things to be placed above the floor
|
||||
|
||||
-- creates "river" caverns
|
||||
for vi, x, y, z in area:iterp_yxz(minp, maxp) do
|
||||
if not skip_next then
|
||||
if y < y_max_river and y > y_min_river then
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
local abs_cave = math.abs(nvals_cave[index2d])
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
local cracks = nvals_cracks[index2d]
|
||||
|
||||
local ripple = cracks * ((y - y_min_river) / (y_max_river - y_min_river)) * ripple_mult
|
||||
|
||||
-- above floor and below ceiling
|
||||
local floor_height = math.floor(abs_cave * floor_mult + sea_level + floor_displace + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + sea_level + ceiling_displace + wave + ripple)
|
||||
|
||||
-- deal with lava
|
||||
if y <= floor_height and y > floor_height - 3 and y < sea_level + 5 and data[vi] == c_lava then
|
||||
data[vi] = c_obsidian
|
||||
end
|
||||
|
||||
if y == floor_height and y < sea_level and not mapgen_helper.buildable_to(data[vi]) then
|
||||
if cracks > 0.2 then
|
||||
data[vi] = c_sand
|
||||
if cracks > 0.5 then
|
||||
data[vi+area.ystride] = c_sand
|
||||
skip_next = true
|
||||
end
|
||||
else
|
||||
data[vi] = c_gravel
|
||||
end
|
||||
elseif y > floor_height and y < ceiling_height and data[vi] ~= c_wet_flowstone then
|
||||
data[vi] = c_air
|
||||
elseif y == ceiling_height and not mapgen_helper.buildable_to(data[vi]) then
|
||||
df_caverns.glow_worm_cavern_ceiling(math.abs(cracks),
|
||||
mapgen_helper.xz_consistent_randomi(area, vi), vi, area, data, data_param2)
|
||||
end
|
||||
|
||||
-- Deal with lava
|
||||
if y >= ceiling_height and y < ceiling_height + 5 and y > sea_level - 5 and data[vi] == c_lava then
|
||||
data[vi] = c_obsidian
|
||||
end
|
||||
end
|
||||
-- convert all air below sea level into water
|
||||
if y <= sea_level and data[vi] == c_air then
|
||||
data[vi] = c_water
|
||||
end
|
||||
else
|
||||
skip_next = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Cavern floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local heat = heatmap[index2d]
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local y = area:get_y(vi)
|
||||
|
||||
-- The vertically squished aspect of these caverns produces too many very thin shelves, this blunts them
|
||||
if mapgen_helper.buildable_to(data[vi-area.ystride]) then
|
||||
if y <= sea_level then
|
||||
data[vi] = c_water
|
||||
else
|
||||
data[vi] = c_air
|
||||
end
|
||||
end
|
||||
|
||||
-- extra test is needed because the rivers can remove nodes that Subterrane marked as floor.
|
||||
if not mapgen_helper.buildable_to(data[vi]) then
|
||||
if y >= sea_level then
|
||||
if heat > hot_zone_boundary then
|
||||
hot_zone_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif heat > middle_zone_boundary then
|
||||
fungispore_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif heat > cool_zone_boundary then
|
||||
mushroom_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
cool_zone_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
elseif y >= sea_level - 30 then
|
||||
if math.random() < 0.005 then
|
||||
df_mapitems.place_snareweed_patch(area, data, vi, data_param2, 6)
|
||||
else
|
||||
data[vi] = c_dirt
|
||||
end
|
||||
else
|
||||
data[vi] = c_sand
|
||||
if math.random() < 0.001 then
|
||||
local iterations = math.random(1, 6)
|
||||
df_mapitems.spawn_coral_pile(area, data, vi, iterations)
|
||||
df_mapitems.spawn_cave_coral(area, data, vi+area.ystride, iterations)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Cavern ceilings
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local heat = heatmap[index2d]
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local vert_rand = mapgen_helper.xz_consistent_randomi(area, vi)
|
||||
local y = area:get_y(vi)
|
||||
|
||||
if y > sea_level and not mapgen_helper.buildable_to(data[vi]) then
|
||||
if heat > hot_zone_boundary then
|
||||
hot_zone_ceiling(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
elseif heat > cool_zone_boundary then
|
||||
df_caverns.glow_worm_cavern_ceiling(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
else
|
||||
cool_zone_ceiling(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Tunnel floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_floor_nodes) do
|
||||
if area:get_y(vi) >= sea_level and not mapgen_helper.buildable_to(data[vi]) then
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Tunnel ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do
|
||||
if area:get_y(vi) > sea_level and not mapgen_helper.buildable_to(data[vi]) then
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
-- air pockets
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local ystride = area.ystride
|
||||
if cracks > 0.6 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.8 and data[vi-ystride*2] == c_water then
|
||||
data[vi-ystride*2] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Warren ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_ceiling_nodes) do
|
||||
if area:get_y(vi) > sea_level and not mapgen_helper.buildable_to(data[vi]) then
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
else
|
||||
-- air pockets
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local ystride = area.ystride
|
||||
if cracks > 0.6 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.8 and data[vi-ystride*2] == c_water then
|
||||
data[vi-ystride*2] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Warren floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_floor_nodes) do
|
||||
if area:get_y(vi) >= sea_level and not mapgen_helper.buildable_to(data[vi]) then
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi, nvals_cracks, data, data_param2, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- columns
|
||||
for _, vi in ipairs(node_arrays.column_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local heat = heatmap[index2d]
|
||||
|
||||
if area:get_y(vi) > sea_level and heat > hot_zone_boundary and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
vm:set_param2_data(data_param2)
|
||||
end
|
||||
|
||||
--Sunless Sea
|
||||
subterrane.register_layer({
|
||||
name = "sunless sea",
|
||||
y_max = df_caverns.config.level3_min-1,
|
||||
y_min = df_caverns.config.sunless_sea_min,
|
||||
cave_threshold = df_caverns.config.sunless_sea_threshold,
|
||||
perlin_cave = perlin_cave_sunless_sea,
|
||||
perlin_wave = perlin_wave_sunless_sea,
|
||||
solidify_lava = true,
|
||||
columns = {
|
||||
maximum_radius = 20,
|
||||
minimum_radius = 5,
|
||||
node = "df_mapitems:wet_flowstone",
|
||||
weight = 0.5,
|
||||
maximum_count = 60,
|
||||
minimum_count = 10,
|
||||
},
|
||||
decorate = decorate_sunless_sea,
|
||||
double_frequency = false,
|
||||
})
|
66
df_caverns/surface_tunnels.lua
Normal file
@ -0,0 +1,66 @@
|
||||
-- surface tunnels
|
||||
|
||||
local y_max = -10
|
||||
local y_min = df_caverns.config.ymax
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--if out of range of cave definition limits, abort
|
||||
if minp.y > y_max or maxp.y < y_min then
|
||||
return
|
||||
end
|
||||
|
||||
local t_start = os.clock()
|
||||
|
||||
local vm, data, data_param2, area = mapgen_helper.mapgen_vm_data_param2()
|
||||
local humiditymap = minetest.get_mapgen_object("humiditymap")
|
||||
local nvals_cracks = mapgen_helper.perlin2d("df_cavern:cracks", minp, maxp, df_caverns.np_cracks)
|
||||
|
||||
local previous_state = "outside_region"
|
||||
local previous_y = minp.y
|
||||
|
||||
for vi, x, y, z in area:iterp_yxz(minp, maxp) do
|
||||
|
||||
if y < previous_y then
|
||||
previous_state = "outside_region"
|
||||
end
|
||||
previous_y = y
|
||||
|
||||
if y < y_max then
|
||||
if mapgen_helper.buildable_to(data[vi]) then
|
||||
if previous_state == "in_rock" and not mapgen_helper.buildable_to(data[vi-area.ystride]) then
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
local humidity = humiditymap[index2d]
|
||||
df_caverns.tunnel_floor(minp, maxp, area, vi-area.ystride, nvals_cracks, data, data_param2, humidity > 30)
|
||||
end
|
||||
previous_state = "in_tunnel"
|
||||
else
|
||||
if previous_state == "in_tunnel" and not mapgen_helper.buildable_to(data[vi]) then
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
local humidity = humiditymap[index2d]
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, humidity > 30)
|
||||
end
|
||||
previous_state = "in_rock"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--send data back to voxelmanip
|
||||
vm:set_data(data)
|
||||
vm:set_param2_data(data_param2)
|
||||
--calc lighting
|
||||
vm:set_lighting({day = 0, night = 0})
|
||||
vm:calc_lighting()
|
||||
|
||||
vm:update_liquids()
|
||||
--write it to world
|
||||
vm:write_to_map()
|
||||
|
||||
local chunk_generation_time = math.ceil((os.clock() - t_start) * 1000) --grab how long it took
|
||||
if chunk_generation_time < 1000 then
|
||||
minetest.log("info", "[df_caverns surface tunnels] "..chunk_generation_time.." ms") --tell people how long
|
||||
else
|
||||
minetest.log("warning", "[df_caverns surface tunnels] took "..chunk_generation_time.." ms to generate map block "
|
||||
.. minetest.pos_to_string(minp) .. minetest.pos_to_string(maxp))
|
||||
end
|
||||
|
||||
end)
|
396
df_caverns/underworld.lua
Normal file
@ -0,0 +1,396 @@
|
||||
if not df_caverns.config.enable_underworld then
|
||||
return
|
||||
end
|
||||
|
||||
local c_slade = minetest.get_content_id("df_underworld_items:slade")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
|
||||
local c_glowstone = minetest.get_content_id("df_underworld_items:glowstone")
|
||||
local c_amethyst = minetest.get_content_id("df_underworld_items:glow_amethyst")
|
||||
local c_pit_plasma = minetest.get_content_id("df_underworld_items:pit_plasma")
|
||||
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local oubliette_schematic = dofile(MP.."/schematics/oubliette.lua")
|
||||
local lamppost_schematic = dofile(MP.."/schematics/lamppost.lua")
|
||||
local small_slab_schematic = dofile(MP.."/schematics/small_slab.lua")
|
||||
local small_building_schematic = dofile(MP.."/schematics/small_building.lua")
|
||||
local medium_building_schematic = dofile(MP.."/schematics/medium_building.lua")
|
||||
|
||||
local perlin_cave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=200, y=200, z=200},
|
||||
seed = 88233498,
|
||||
octaves = 6,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
-- large-scale rise and fall to make the seam between stone and slade less razor-flat
|
||||
local perlin_wave = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=1000, y=1000, z=1000},
|
||||
seed = 993455,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
-- building zones
|
||||
local perlin_zone = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=500, y=500, z=500},
|
||||
seed = 199422,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
local median = df_caverns.config.underworld_level
|
||||
local floor_mult = 20
|
||||
local floor_displace = -10
|
||||
local ceiling_mult = -40
|
||||
local ceiling_displace = 20
|
||||
local wave_mult = 50
|
||||
|
||||
local y_max = median + 2*wave_mult + ceiling_displace + -2*ceiling_mult
|
||||
local y_min = median - 2*wave_mult + floor_displace - 2*floor_mult
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Buildings
|
||||
|
||||
local oubliette_threshold = 0.8
|
||||
local town_threshold = 1.1
|
||||
|
||||
local local_random = function(x, z)
|
||||
math.randomseed(x + z*2^16)
|
||||
return math.random()
|
||||
end
|
||||
|
||||
-- create a deterministic list of buildings
|
||||
local get_buildings = function(emin, emax, nvals_zone)
|
||||
local buildings = {}
|
||||
for x = emin.x, emax.x do
|
||||
for z = emin.z, emax.z do
|
||||
|
||||
local index2d = mapgen_helper.index2d(emin, emax, x, z)
|
||||
local zone = math.abs(nvals_zone[index2d])
|
||||
|
||||
if zone > oubliette_threshold and zone < town_threshold then
|
||||
-- oubliette zone
|
||||
--zone = (zone - oubliette_threshold)/(town_threshold-oubliette_threshold) -- turn this into a 0-1 spread
|
||||
local building_val = local_random(x, z)
|
||||
if building_val > 0.98 then
|
||||
building_val = (building_val - 0.98)/0.02
|
||||
local building_type
|
||||
if building_val < 0.8 then
|
||||
building_type = "oubliette"
|
||||
elseif building_val < 0.9 then
|
||||
building_type = "open oubliette"
|
||||
else
|
||||
building_type = "lamppost"
|
||||
end
|
||||
table.insert(buildings,
|
||||
{
|
||||
pos = {x=x, y=0, z=z}, -- y to be determined later
|
||||
building_type = building_type,
|
||||
bounding_box = {minpos={x=x-2, z=z-2}, maxpos={x=x+2, z=z+2}},
|
||||
priority = math.floor(building_val * 10000000) % 1000, -- indended to allow for deterministic removal of overlapping buildings
|
||||
}
|
||||
)
|
||||
end
|
||||
elseif zone > town_threshold then
|
||||
-- town zone
|
||||
local building_val = local_random(x, z)
|
||||
if building_val > 0.9925 then
|
||||
building_val = (building_val - 0.9925)/0.0075
|
||||
|
||||
local building_type
|
||||
local bounding_box
|
||||
local priority = math.floor(building_val * 10000000) % 1000
|
||||
local rotation = (priority % 4) * 90
|
||||
|
||||
if building_val < 0.75 then
|
||||
building_type = "small building"
|
||||
local boundmin, boundmax = mapgen_helper.get_schematic_bounding_box({x=x, y=0, z=z}, small_building_schematic, rotation)
|
||||
bounding_box = {minpos=boundmin, maxpos=boundmax}
|
||||
elseif building_val < 0.85 then
|
||||
building_type = "medium building"
|
||||
local boundmin, boundmax = mapgen_helper.get_schematic_bounding_box({x=x, y=0, z=z}, medium_building_schematic, rotation)
|
||||
bounding_box = {minpos=boundmin, maxpos=boundmax}
|
||||
else
|
||||
building_type = "small slab"
|
||||
local boundmin, boundmax = mapgen_helper.get_schematic_bounding_box({x=x, y=0, z=z}, small_slab_schematic, rotation)
|
||||
bounding_box = {minpos=boundmin, maxpos=boundmax}
|
||||
end
|
||||
|
||||
table.insert(buildings,
|
||||
{
|
||||
pos = {x=x, y=0, z=z}, -- y to be determined later
|
||||
building_type = building_type,
|
||||
bounding_box = bounding_box,
|
||||
rotation = rotation,
|
||||
priority = priority, -- indended to allow for deterministic removal of overlapping buildings
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- eliminate overlapping buildings
|
||||
local building_count = table.getn(buildings)
|
||||
local overlap_count = 0
|
||||
for i = 1, building_count-1 do
|
||||
local curr_building = buildings[i]
|
||||
for j = i+1, building_count do
|
||||
local test_building = buildings[j]
|
||||
if test_building ~= nil and curr_building ~= nil and mapgen_helper.intersect_exists_xz(
|
||||
curr_building.bounding_box.minpos,
|
||||
curr_building.bounding_box.maxpos,
|
||||
test_building.bounding_box.minpos,
|
||||
test_building.bounding_box.maxpos) then
|
||||
|
||||
if curr_building.priority < test_building.priority then -- this makes elimination of overlapping buildings deterministic
|
||||
buildings[i] = nil
|
||||
j=building_count+1
|
||||
else
|
||||
buildings[j] = nil
|
||||
end
|
||||
overlap_count = overlap_count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if building_count > 50 and overlap_count > building_count * 2/3 then
|
||||
minetest.log("warning", "[df_caverns] underworld mapgen generated " ..
|
||||
tostring(building_count) .. " buildings and " .. tostring(overlap_count) ..
|
||||
" were eliminated as overlapping, if this happens a lot consider reducing building" ..
|
||||
" generation probability to improve efficiency.")
|
||||
end
|
||||
|
||||
local compacted_buildings = {}
|
||||
for _, building in pairs(buildings) do
|
||||
compacted_buildings[minetest.hash_node_position(building.pos)] = building
|
||||
end
|
||||
|
||||
return compacted_buildings
|
||||
end
|
||||
|
||||
-----------------------------------------------------------
|
||||
-- Pits
|
||||
|
||||
local radius_pit_max = 40 -- won't actually be this wide, there'll be crystal spires around it
|
||||
local radius_pit_variance = 10
|
||||
local plasma_depth_min = 5
|
||||
local plasma_depth_max = 75
|
||||
|
||||
local region_mapblocks = df_caverns.config.underworld_glowing_pit_mapblocks -- One glowing pit in each region this size
|
||||
local mapgen_chunksize = tonumber(minetest.get_mapgen_setting("chunksize"))
|
||||
local pit_region_size = region_mapblocks * mapgen_chunksize * 16
|
||||
|
||||
local scatter_2d = function(min_xz, gridscale, border_width)
|
||||
local bordered_scale = gridscale - 2 * border_width
|
||||
local point = {}
|
||||
point.x = math.random() * bordered_scale + min_xz.x + border_width
|
||||
point.y = 0
|
||||
point.z = math.random() * bordered_scale + min_xz.z + border_width
|
||||
return point
|
||||
end
|
||||
|
||||
-- For some reason, map chunks generate with -32, -32, -32 as the "origin" minp. To make the large-scale grid align with map chunks it needs to be offset like this.
|
||||
local get_corner = function(pos)
|
||||
return {x = math.floor((pos.x+32) / pit_region_size) * pit_region_size - 32, z = math.floor((pos.z+32) / pit_region_size) * pit_region_size - 32}
|
||||
end
|
||||
|
||||
local mapgen_seed = tonumber(minetest.get_mapgen_setting("seed"))
|
||||
|
||||
local get_pit = function(pos)
|
||||
if region_mapblocks < 1 then return nil end
|
||||
|
||||
local corner_xz = get_corner(pos)
|
||||
local next_seed = math.random(1, 1000000000)
|
||||
math.randomseed(corner_xz.x + corner_xz.z * 2 ^ 8 + mapgen_seed)
|
||||
local location = scatter_2d(corner_xz, pit_region_size, radius_pit_max + radius_pit_variance)
|
||||
local variance_multiplier = math.random()
|
||||
local radius = variance_multiplier * (radius_pit_max - 15) + 15
|
||||
local variance = radius_pit_variance/2 + radius_pit_variance*variance_multiplier/2
|
||||
local depth = math.random(plasma_depth_min, plasma_depth_max)
|
||||
math.randomseed(next_seed)
|
||||
return {location = location, radius = radius, variance = variance, depth = depth}
|
||||
end
|
||||
|
||||
local perlin_pit = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=30, y=30, z=30},
|
||||
seed = 901,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
-------------------------------------
|
||||
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
|
||||
--if out of range of cave definition limits, abort
|
||||
if minp.y > y_max or maxp.y < y_min then
|
||||
return
|
||||
end
|
||||
|
||||
local t_start = os.clock()
|
||||
|
||||
local vm, data, data_param2, area = mapgen_helper.mapgen_vm_data_param2()
|
||||
local emin = area.MinEdge
|
||||
local emax = area.MaxEdge
|
||||
|
||||
local nvals_cave = mapgen_helper.perlin2d("df_caverns:underworld_cave", emin, emax, perlin_cave) --cave noise for structure
|
||||
local nvals_wave = mapgen_helper.perlin2d("df_caverns:underworld_wave", emin, emax, perlin_wave) --cave noise for structure
|
||||
local nvals_zone = mapgen_helper.perlin2d("df_caverns:underworld_zone", emin, emax, perlin_zone) --building zones
|
||||
|
||||
local pit = get_pit(minp)
|
||||
--minetest.chat_send_all(minetest.pos_to_string(pit.location))
|
||||
|
||||
local buildings = get_buildings(emin, emax, nvals_zone)
|
||||
|
||||
local pit_uninitialized = true
|
||||
local nvals_pit, area_pit
|
||||
|
||||
for vi, x, y, z in area:iterp_yxz(minp, maxp) do
|
||||
if y > y_min then
|
||||
local index2d = mapgen_helper.index2d(emin, emax, x, z)
|
||||
local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
|
||||
local floor_height = math.floor(abs_cave * floor_mult + median + floor_displace + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
if y <= floor_height then
|
||||
data[vi] = c_slade
|
||||
if pit and
|
||||
pit.location.x - radius_pit_max - radius_pit_variance < maxp.x and
|
||||
pit.location.x + radius_pit_max + radius_pit_variance > minp.x and
|
||||
pit.location.z - radius_pit_max - radius_pit_variance < maxp.z and
|
||||
pit.location.z + radius_pit_max + radius_pit_variance > minp.z
|
||||
then
|
||||
-- there's a pit nearby
|
||||
if pit_uninitialized then
|
||||
nvals_pit, area_pit = mapgen_helper.perlin3d("df_cavern:perlin_cave", minp, maxp, perlin_pit) -- determine which areas are spongey with warrens
|
||||
pit_uninitialized = false
|
||||
end
|
||||
local pit_value = nvals_pit[area_pit:index(x,y,z)] * pit.variance
|
||||
local distance = vector.distance({x=x, y=y, z=z}, {x=pit.location.x, y=y, z=pit.location.z}) + pit_value
|
||||
if distance < pit.radius -3 then
|
||||
if y < y_min + 4 then -- make a layer of amethyst at the bottom of the pit to keep the plasma from digging infinitely downward.
|
||||
data[vi] = c_amethyst
|
||||
elseif y < median + floor_displace + wave - pit.depth then
|
||||
data[vi] = c_pit_plasma
|
||||
else
|
||||
data[vi] = c_air
|
||||
end
|
||||
elseif distance < pit.radius then
|
||||
data[vi] = c_amethyst
|
||||
elseif distance < radius_pit_max and y == floor_height - 4 then
|
||||
if math.random() > 0.95 then
|
||||
df_underworld_items.underworld_shard(data, area, vi)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif y < ceiling_height and data[vi] ~= c_amethyst then
|
||||
data[vi] = c_air
|
||||
elseif data[vi] == c_water then
|
||||
data[vi] = c_air -- no water down here
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Ceiling decoration
|
||||
for x = minp.x + 1, maxp.x-1 do
|
||||
for z = minp.z + 1, maxp.z -1 do
|
||||
local index2d = mapgen_helper.index2d(emin, emax, x, z)
|
||||
local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
local floor_height = math.floor(abs_cave * floor_mult + median + floor_displace + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
|
||||
if ceiling_height > floor_height + 5 and ceiling_height < maxp.y and ceiling_height > minp.y then
|
||||
local vi = area:index(x, ceiling_height, z)
|
||||
if (
|
||||
--test if we're nestled in a crevice
|
||||
(not mapgen_helper.buildable_to(data[vi-area.ystride + 1]) and not mapgen_helper.buildable_to(data[vi-area.ystride - 1])) or
|
||||
(not mapgen_helper.buildable_to(data[vi-area.ystride + area.zstride]) and not mapgen_helper.buildable_to(data[vi-area.ystride - area.zstride]))
|
||||
)
|
||||
then
|
||||
data[vi] = c_glowstone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- buildings
|
||||
for x = emin.x + 5, emax.x - 5 do
|
||||
for z = emin.z + 5, emax.z - 5 do
|
||||
|
||||
local skip = false
|
||||
if pit and
|
||||
pit.location.x - radius_pit_max - radius_pit_variance < x and
|
||||
pit.location.x + radius_pit_max + radius_pit_variance > x and
|
||||
pit.location.z - radius_pit_max - radius_pit_variance < z and
|
||||
pit.location.z + radius_pit_max + radius_pit_variance > z
|
||||
then
|
||||
if vector.distance(pit.location, {x=x, y=0, z=z}) < radius_pit_max + radius_pit_variance then
|
||||
-- there's a pit nearby
|
||||
skip = true
|
||||
end
|
||||
end
|
||||
if not skip then
|
||||
local index2d = mapgen_helper.index2d(emin, emax, x, z)
|
||||
local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
local floor_height = math.floor(abs_cave * floor_mult + median + floor_displace + wave)
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
|
||||
if ceiling_height > floor_height and floor_height <= maxp.y and floor_height >= minp.y then
|
||||
local building = buildings[minetest.hash_node_position({x=x,y=0,z=z})]
|
||||
if building ~= nil then
|
||||
building.pos.y = floor_height
|
||||
--minetest.chat_send_all("placing " .. building.building_type .. " at " .. minetest.pos_to_string(building.pos))
|
||||
if building.building_type == "oubliette" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, oubliette_schematic)
|
||||
elseif building.building_type == "open oubliette" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, oubliette_schematic, 0, {["df_underworld_items:slade_seal"] = "air"})
|
||||
elseif building.building_type == "lamppost" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, lamppost_schematic)
|
||||
elseif building.building_type == "small building" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, small_building_schematic, building.rotation)
|
||||
elseif building.building_type == "medium building" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, medium_building_schematic, building.rotation)
|
||||
elseif building.building_type == "small slab" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, small_slab_schematic, building.rotation)
|
||||
else
|
||||
minetest.log("error", "unrecognized underworld building type: " .. tostring(building.building_type))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--send data back to voxelmanip
|
||||
vm:set_data(data)
|
||||
vm:set_param2_data(data_param2)
|
||||
--calc lighting
|
||||
vm:set_lighting({day = 0, night = 0})
|
||||
vm:calc_lighting()
|
||||
vm:update_liquids()
|
||||
--write it to world
|
||||
vm:write_to_map()
|
||||
|
||||
local chunk_generation_time = math.ceil((os.clock() - t_start) * 1000) --grab how long it took
|
||||
if chunk_generation_time < 1000 then
|
||||
minetest.log("info", "[df_caverns] underworld mapblock generation took "..chunk_generation_time.." ms") --tell people how long
|
||||
else
|
||||
minetest.log("warning", "[df_caverns] underworld took "..chunk_generation_time.." ms to generate map block "
|
||||
.. minetest.pos_to_string(minp) .. minetest.pos_to_string(maxp))
|
||||
end
|
||||
end)
|