Primordial cavern layer (#12)
* bring in the art assets from ClockGen's "better_caves_modpack" under CC BY 4.0,, code written from scratch. * update mapgen_helper * import ClockGen's giant mushroom schematics, make them and giant ferns growable * add giant jungle mushroom, rough out actual cavern layer code framework * fungal ceiling decorations * decorate fungal floor a bit * update mapgen_helper * update primordial mushroom schematic placement to ensure it fits * add giant mycelium fungoidal structure * add giant mycelium to mapgen * fix settings for giant mycelium * make mycelium grow when players aren't present * allow mycelium growth to pause when it hits unloaded areas * add a use for giant mycelium * make giant mushrooms edible, make jungle trees growable * rough out the jungle biome * Make a spectrum of jungle growth * optimize pngs, add is_ground_content to everything * use custom is_ground_content method * fix a crash with veinstone, and simplify nvals_cave lookup now that overgen covers the same area * more fixes for overgen support * remove unintentional airspace from underside of slade * fix for overgen crash in level 2 * primordial column material, add sealed shafts to underworld * add seal block * Set up puzzle seals to be able to dig a staircase shaft through the slade layer. TODO: the puzzle to guard the trigger. * puzzle seals now fully functional. Need to add clues for decoding the keys next. * add a small bit of anti-griefing - the seal breach bell only tolls globally 13 times per activation * add flowers to the underworld warrior bones * switch to a different key bell * fancy up the puzzle seal temples with some custom blocks, add sub-slade grid passages * add a clue to the seal formspec * tweak background of inscription 2 so it's less obviously a copy of the background for inscription 1 * switch to compositing to save a few bytes * fancy up the seal's upper surface with inscriptions to make the formspec feel consistent * puzzle particle, bones were only spawning on top of structures * fix ice/oil on level 3, tweak some loot probabilities * add trail mod support * remove deprecated files * boost default plant growth delay, add growing selection boxes * update map colours * add named waypoints to the underworld * try a more efficient way of changing the interiors of columns * polishing up the Primordial layer * update guide with some Primordial teasers * updated magma sea screenshot * update mapgen_helper and subterrane * reduce density of megaflora a bit - was too hard to walk through * spreading_dirt_type depends on light, create my own ABM instead * add names to the glowing pits and some of the ruins * separate setting for ruin markers * record identity of slade-breachers * make mycelia climbable * update subterrane * change surface tunnel detection to allow above-ground stalactites and stalagmites * add rare thicker Goblin Caps, suitable for use as huts. * better goblin cap schematics * update colours * make it slightly harder to dig down through amethyst sheathing of pits * fixing up fungus light sensitivity, tree growth code * fix a few minor bugs * update deprecated functions * add various eating sounds * make mapping kit requirement more flexible * update spindlestem growth code, remove deprecated functions * fix leftover undefined variable * add fireflies to primordial, spread out the post-mapgen node timer for plant matter a bit more. * fix bones formspec * add lbm to upgrade old bones * fix slade undiggability * make torchspines smokey and manually lightable * fix drop definitions * generate dry stalactites in near-surface caverns. * caverns become far too smokey, alas * add pitter patter of spore tree spores, alternate paper recipe * new mapgen_helper metrics * add smokey back to torchspine now that it can be dialed down a bit * replace glowstone texture with a new animated one * switch from ABM to node timer for mapgen mycelium growth * make mapgen mycelium timer delay configurable * improve the efficiency of giant mycelium growth using flat node array, fewer dereferences * remove the smoke from torchspines again - it doesn't dissipate that deep underground * give slade a more muted, gloomy hue to differentiate it from nether stone * update screenshots with new slade colors * update mapgen_helper
@ -7,11 +7,11 @@ 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)
|
||||
value = minetest.settings:get_bool(CONFIG_FILE_PREFIX..name, default)
|
||||
elseif stype == "string" then
|
||||
value = minetest.setting_get(CONFIG_FILE_PREFIX..name)
|
||||
value = minetest.settings:get(CONFIG_FILE_PREFIX..name)
|
||||
elseif stype == "int" or stype == "float" then
|
||||
value = tonumber(minetest.setting_get(CONFIG_FILE_PREFIX..name))
|
||||
value = tonumber(minetest.settings:get(CONFIG_FILE_PREFIX..name))
|
||||
end
|
||||
if value == nil then
|
||||
value = default
|
||||
@ -48,3 +48,7 @@ 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")
|
||||
|
||||
setting("bool", "enable_primordial", true, "Enable primordial cavern")
|
||||
setting("int", "primordial_max", -3393, "Upper limit to primordial caverns")
|
||||
setting("int", "primordial_min", -4032, "Lower limit to primordial caverns")
|
||||
|
@ -1,10 +0,0 @@
|
||||
default
|
||||
subterrane
|
||||
df_farming?
|
||||
df_trees
|
||||
df_mapitems
|
||||
ice_sprites?
|
||||
oil?
|
||||
df_underworld_items?
|
||||
magma_conduits?
|
||||
bones_loot?
|
@ -1 +0,0 @@
|
||||
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.
|
@ -49,8 +49,14 @@ bones_loot.register_loot({
|
||||
{name = "binoculars:binoculars", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "boats:boat", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "bucket:bucket_empty", chance = 0.3, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "fire:flint_and_steel", chance = 0.3, count = {1,2}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:tulip_black", chance = 0.01, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "fire:flint_and_steel", chance = 0.3, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:tulip_black", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:dandelion_white", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:dandelion_yellow", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:rose", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:tulip", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:chrysanthemum_green", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:geranium", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "map:mapping_kit", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "screwdriver:screwdriver", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
-- don't give the player tnt:tnt, they can craft that from this if tnt is enabled for them
|
||||
@ -70,10 +76,10 @@ bones_loot.register_loot({
|
||||
{name = "default:pick_steel", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:pick_mese", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:pick_diamond", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_bronze", chance = 0.15, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_steel", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_mese", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_diamond", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_bronze", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_steel", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_mese", chance = 0.025, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:shovel_diamond", chance = 0.025, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:axe_bronze", chance = 0.3, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:axe_steel", chance = 0.5, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:axe_mese", chance = 0.15, count = {1,1}, types = {"underworld_warrior"}},
|
||||
|
@ -15,4 +15,5 @@ dofile(modpath.."/sunless_sea.lua")
|
||||
dofile(modpath.."/oil_sea.lua")
|
||||
dofile(modpath.."/lava_sea.lua")
|
||||
dofile(modpath.."/underworld.lua")
|
||||
dofile(modpath.."/dungeon_loot.lua")
|
||||
dofile(modpath.."/primordial.lua")
|
||||
dofile(modpath.."/dungeon_loot.lua")
|
||||
|
@ -137,11 +137,6 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--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
|
||||
local time_taken = os.clock() - t_start -- how long this chunk took, in seconds
|
||||
mapgen_helper.record_time("df_caverns lava sea", time_taken)
|
||||
end)
|
@ -96,8 +96,9 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
|
||||
-- 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
|
||||
for vi, x, y, z in area:iterp_yxz(area.MinEdge, area.MaxEdge) do
|
||||
-- convert all air below sea level into water
|
||||
if y <= subsea_level and data[vi] == c_air and nvals_cave[vi] < -flooding_threshold then
|
||||
data[vi] = c_water
|
||||
end
|
||||
end
|
||||
@ -111,7 +112,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -137,7 +138,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -164,7 +165,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -182,7 +183,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -210,7 +211,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
local ystride = area.ystride
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
@ -249,7 +250,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -268,7 +269,7 @@ local decorate_level_1 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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)
|
||||
local dry = (biome_name == "barren") and (nvals_cave[vi] > 0)
|
||||
|
||||
if dry and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
@ -300,4 +301,5 @@ subterrane.register_layer({
|
||||
decorate = decorate_level_1,
|
||||
warren_region_variability_threshold = 0.33,
|
||||
double_frequency = true,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
@ -79,7 +79,7 @@ local goblin_cap_cavern_floor = function(abs_cracks, vert_rand, vi, area, data,
|
||||
elseif math.random() < 0.02 then
|
||||
df_trees.spawn_spindlestem_vm(vi+ystride, area, data, data_param2, c_red)
|
||||
elseif math.random() < 0.015 then
|
||||
df_trees.spawn_goblin_cap_vm(vi+ystride, area, data)
|
||||
df_trees.spawn_goblin_cap_vm(vi+ystride, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
@ -98,7 +98,7 @@ local spore_tree_cavern_floor = function(abs_cracks, vert_rand, vi, area, data,
|
||||
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)
|
||||
df_trees.spawn_spore_tree_vm(vi+ystride, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -135,28 +135,29 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
local cavern_def = node_arrays.cavern_def
|
||||
|
||||
local vein_noise
|
||||
local vein_area
|
||||
|
||||
-- Partly fill flooded caverns and warrens
|
||||
for vi in area:iterp(minp, maxp) do
|
||||
local cave_val = nvals_cave[cave_area:transform(area, vi)]
|
||||
for vi, x, y, z in area:iterp_yxz(area.MinEdge, area.MaxEdge) do
|
||||
local cave_val = nvals_cave[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
|
||||
if mapgen_helper.is_pos_within_box({x=x, y=y, z=z}, minp, maxp) 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
|
||||
--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, vein_area = mapgen_helper.perlin3d("df_caverns:wall_veins", minp, maxp, wall_vein_perlin_params)
|
||||
end
|
||||
if data[vi] == c_air and math.abs(vein_noise[vein_area:transform(area, vi)]) < 0.02 then
|
||||
data[vi] = c_veinstone
|
||||
end
|
||||
end
|
||||
end
|
||||
if data[vi] == c_air and area:get_y(vi) <= subsea_level then
|
||||
if data[vi] == c_air and y <= subsea_level then
|
||||
data[vi] = c_water -- otherwise, fill air with water when below sea level
|
||||
end
|
||||
end
|
||||
@ -170,7 +171,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -198,7 +199,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -230,7 +231,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -248,7 +249,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
local ystride = area.ystride
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
@ -287,7 +288,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -305,7 +306,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
local ystride = area.ystride
|
||||
|
||||
if not (flooded_caverns and minp.y < subsea_level and area:get_y(vi) < subsea_level) then
|
||||
@ -345,7 +346,7 @@ local decorate_level_2 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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)
|
||||
local dry = (biome_name == "barren") and (nvals_cave[vi] > 0)
|
||||
|
||||
if dry and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
@ -375,5 +376,6 @@ subterrane.register_layer({
|
||||
decorate = decorate_level_2,
|
||||
warren_region_variability_threshold = 0.33,
|
||||
double_frequency = true,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
|
||||
|
@ -28,7 +28,7 @@ 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 subsea_level = math.floor(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
|
||||
@ -165,7 +165,7 @@ local blood_thorn_cavern_floor = function(abs_cracks, vert_rand, vi, area, data,
|
||||
if abs_cracks < 0.075 then
|
||||
if vert_rand < 0.004 then
|
||||
subterrane.big_stalagmite(ai, area, data, 6, 15, c_dry_flowstone, c_dry_flowstone, c_dry_flowstone)
|
||||
elseif data[vi] ~= air and math.random() < 0.5 then
|
||||
elseif data[vi] ~= c_air and math.random() < 0.5 then
|
||||
data[vi] = c_salty_cobble
|
||||
if data[ai] == c_air and math.random() < 0.25 then
|
||||
data[ai] = c_salt_crystal
|
||||
@ -207,25 +207,25 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
|
||||
-- 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
|
||||
for vi, x, y, z in area:iterp_yxz(area.MinEdge, area.MaxEdge) do
|
||||
local cave = nvals_cave[vi]
|
||||
if y <= subsea_level and cave < -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
|
||||
if (mapgen_helper.is_pos_within_box({x=x, y=y, z=z}, minp, maxp)) then
|
||||
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
|
||||
if y == subsea_level and data[vi] == c_water and math.abs(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
|
||||
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
|
||||
@ -240,7 +240,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -285,7 +285,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -321,7 +321,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
else
|
||||
-- bloodthorn ceiling
|
||||
if abs_cracks < 0.075 then
|
||||
if data[vi] ~= air and math.random() < 0.5 then
|
||||
if data[vi] ~= c_air and math.random() < 0.5 then
|
||||
data[vi] = c_salty_cobble
|
||||
local bi = vi - area.ystride
|
||||
if data[bi] == c_air and math.random() < 0.25 then
|
||||
@ -346,7 +346,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -364,7 +364,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -393,7 +393,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -431,7 +431,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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.
|
||||
local flooded_caverns = nvals_cave[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
|
||||
@ -473,7 +473,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
|
||||
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
|
||||
local flooded_caverns = nvals_cave[vi] < 0
|
||||
|
||||
if biome_name == "bloodnether" and data[vi] == c_wet_flowstone then
|
||||
if not flooded_caverns then
|
||||
@ -527,4 +527,5 @@ subterrane.register_layer({
|
||||
decorate = decorate_level_3,
|
||||
warren_region_variability_threshold = 0.33,
|
||||
double_frequency = true,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
|
26
df_caverns/locale/template.pot
Normal file
@ -0,0 +1,26 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-25 13:52-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: df_caverns\underworld.lua:12
|
||||
msgid "A glowing pit"
|
||||
msgstr ""
|
||||
|
||||
#: df_caverns\underworld.lua:27
|
||||
msgid "A mysterious seal"
|
||||
msgstr ""
|
6
df_caverns/locale/update.bat
Normal file
@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
|
||||
cd ..
|
||||
set LIST=
|
||||
for /r %%X in (*.lua) do set LIST=!LIST! %%X
|
||||
..\..\intllib\tools\xgettext.bat %LIST%
|
@ -1,4 +1,4 @@
|
||||
name = df_caverns
|
||||
description = 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.
|
||||
depends = default, subterrane, df_trees, df_mapitems
|
||||
optional_depends = df_farming, ice_sprites, oil, df_underworld_items, magma_conduits, bones_loot
|
||||
optional_depends = df_farming, ice_sprites, oil, df_underworld_items, magma_conduits, bones_loot, named_waypoints, namegen, fireflies
|
@ -102,13 +102,8 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--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
|
||||
local time_taken = os.clock() - t_start -- how long this chunk took, in seconds
|
||||
mapgen_helper.record_time("df_caverns oil sea", time_taken)
|
||||
end)
|
||||
|
||||
minetest.register_ore({
|
||||
|
425
df_caverns/primordial.lua
Normal file
@ -0,0 +1,425 @@
|
||||
if not df_caverns.config.enable_primordial or not minetest.get_modpath("df_primordial_items") then
|
||||
return
|
||||
end
|
||||
|
||||
local perlin_cave_primordial = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=df_caverns.config.horizontal_cavern_scale, y=df_caverns.config.vertical_cavern_scale*0.5, z=df_caverns.config.horizontal_cavern_scale},
|
||||
seed = 14055553,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
local perlin_wave_primordial = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=df_caverns.config.horizontal_cavern_scale, y=df_caverns.config.vertical_cavern_scale*0.5, z=df_caverns.config.horizontal_cavern_scale},
|
||||
seed = 923444,
|
||||
octaves = 6,
|
||||
persist = 0.63
|
||||
}
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
local giant_mycelium_timer_spread = tonumber(minetest.settings:get("dcaverns_giant_mycelium_timer_spread")) or 10
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
-- Fungal biome
|
||||
|
||||
local c_orb = minetest.get_content_id("df_primordial_items:glow_orb_hanging")
|
||||
local c_mycelial_dirt = minetest.get_content_id("df_primordial_items:dirt_with_mycelium")
|
||||
local c_dirt = minetest.get_content_id("default:dirt")
|
||||
local c_giant_mycelium = minetest.get_content_id("df_primordial_items:giant_hypha_apical_mapgen")
|
||||
|
||||
local fungal_plants = {
|
||||
minetest.get_content_id("df_primordial_items:fungal_grass_1"),
|
||||
minetest.get_content_id("df_primordial_items:fungal_grass_2"),
|
||||
minetest.get_content_id("df_primordial_items:glow_orb"),
|
||||
minetest.get_content_id("df_primordial_items:glow_orb_stalks"),
|
||||
minetest.get_content_id("df_primordial_items:glow_pods"),
|
||||
}
|
||||
|
||||
local fungal_plant_names = {}
|
||||
local fungal_plants = {}
|
||||
for node_name, node_def in pairs(minetest.registered_nodes) do
|
||||
if minetest.get_item_group(node_name, "primordial_fungal_plant") > 0 then
|
||||
table.insert(fungal_plant_names, node_name)
|
||||
table.insert(fungal_plants, minetest.get_content_id(node_name))
|
||||
end
|
||||
end
|
||||
|
||||
local mushroom_cavern_floor = function(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
local humidityfactor = humidity/200 + 0.5
|
||||
abs_cracks = abs_cracks * humidityfactor
|
||||
|
||||
if abs_cracks < 0.7 then
|
||||
data[vi] = c_mycelial_dirt
|
||||
elseif abs_cracks < 1 then
|
||||
data[vi] = c_dirt
|
||||
end
|
||||
|
||||
local rand = math.random() * math.min(abs_cracks, 1) * humidityfactor
|
||||
if rand < 0.0005 then
|
||||
local mycelium_index = vi+ystride
|
||||
data[mycelium_index] = c_giant_mycelium
|
||||
minetest.get_node_timer(area:position(mycelium_index)):start(math.random(1,giant_mycelium_timer_spread))
|
||||
elseif rand < 0.003 then
|
||||
local schematic = df_primordial_items.get_primordial_mushroom()
|
||||
local rotation = (math.random(1,4)-1)*90
|
||||
mapgen_helper.place_schematic_on_data_if_it_fits(data, data_param2, area, area:position(vi+ystride), schematic, rotation)
|
||||
elseif rand < 0.05 then
|
||||
data[vi+ystride] = fungal_plants[math.random(1,5)]
|
||||
end
|
||||
end
|
||||
|
||||
local mushroom_cavern_ceiling = function(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
local humidityfactor = humidity/200 + 0.5
|
||||
abs_cracks = abs_cracks * humidityfactor
|
||||
|
||||
if abs_cracks < 0.5 then
|
||||
data[vi] = c_mycelial_dirt
|
||||
if abs_cracks < 0.3 then
|
||||
local rand = math.random() * humidityfactor
|
||||
if rand < 0.002 then
|
||||
local mycelium_index = vi-ystride
|
||||
data[mycelium_index] = c_giant_mycelium
|
||||
minetest.get_node_timer(area:position(mycelium_index)):start(math.random(1,giant_mycelium_timer_spread))
|
||||
elseif rand < 0.03 then
|
||||
df_primordial_items.spawn_ceiling_spire_vm(vi, area, data)
|
||||
elseif rand < 0.2 then
|
||||
data[vi-ystride] = c_orb
|
||||
data_param2[vi-ystride] = math.random(0,179)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mushroom_warren_ceiling = function(abs_cracks, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
|
||||
if abs_cracks < 0.3 then
|
||||
data[vi] = c_mycelial_dirt
|
||||
if abs_cracks < 0.2 then
|
||||
local rand = math.random()
|
||||
if rand < 0.001 then
|
||||
local mycelium_index = vi-ystride
|
||||
data[mycelium_index] = c_giant_mycelium
|
||||
minetest.get_node_timer(area:position(mycelium_index)):start(math.random(1,giant_mycelium_timer_spread))
|
||||
elseif rand < 0.2 then
|
||||
data[vi-ystride] = c_orb
|
||||
data_param2[vi-ystride] = math.random(0,179)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mushroom_warren_floor = function(abs_cracks, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.7 then
|
||||
data[vi] = c_mycelial_dirt
|
||||
elseif abs_cracks < 1 then
|
||||
data[vi] = c_dirt
|
||||
end
|
||||
local rand = math.random() * math.min(abs_cracks, 1)
|
||||
if rand < 0.001 then
|
||||
local mycelium_index = vi+ystride
|
||||
data[mycelium_index] = c_giant_mycelium
|
||||
minetest.get_node_timer(area:position(mycelium_index)):start(math.random(1,giant_mycelium_timer_spread))
|
||||
elseif rand < 0.03 then
|
||||
data[vi+ystride] = fungal_plants[math.random(1,5)]
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------
|
||||
-- Jungle biome
|
||||
|
||||
local jungle_plant_names = {}
|
||||
local jungle_plants = {}
|
||||
for node_name, node_def in pairs(minetest.registered_nodes) do
|
||||
if minetest.get_item_group(node_name, "primordial_jungle_plant") > 0 then
|
||||
table.insert(jungle_plant_names, node_name)
|
||||
table.insert(jungle_plants, minetest.get_content_id(node_name))
|
||||
end
|
||||
end
|
||||
|
||||
local c_jungle_dirt = minetest.get_content_id("df_primordial_items:dirt_with_jungle_grass")
|
||||
local c_plant_matter = minetest.get_content_id("df_primordial_items:plant_matter")
|
||||
local c_packed_roots = minetest.get_content_id("df_primordial_items:packed_roots")
|
||||
local c_glowstone = minetest.get_content_id("df_underworld_items:glowstone")
|
||||
local c_ivy = minetest.get_content_id("df_primordial_items:jungle_ivy")
|
||||
local c_root_2 = minetest.get_content_id("df_primordial_items:jungle_roots_2")
|
||||
local c_root_1 = minetest.get_content_id("df_primordial_items:jungle_roots_1")
|
||||
|
||||
local c_fireflies
|
||||
if minetest.get_modpath("fireflies") then
|
||||
c_fireflies = minetest.get_content_id("fireflies:firefly")
|
||||
end
|
||||
|
||||
local jungle_cavern_floor = function(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
local humidityfactor = humidity/100
|
||||
|
||||
data[vi] = c_jungle_dirt
|
||||
|
||||
local rand = math.random()
|
||||
if rand < 0.025 * humidityfactor then
|
||||
local fern_schematic = df_primordial_items.get_fern_schematic()
|
||||
local rotation = (math.random(1,4)-1)*90
|
||||
mapgen_helper.place_schematic_on_data_if_it_fits(data, data_param2, area, area:position(vi+ystride), fern_schematic, rotation)
|
||||
elseif rand < 0.025 * (1-humidityfactor) then
|
||||
df_primordial_items.spawn_jungle_mushroom_vm(vi+ystride, area, data)
|
||||
elseif rand < 0.05 * (1-humidityfactor) then
|
||||
df_primordial_items.spawn_jungle_tree_vm(math.random(8,14), vi+ystride, area, data)
|
||||
elseif rand < 0.3 then
|
||||
data[vi+ystride] = jungle_plants[math.random(1,#jungle_plants)]
|
||||
end
|
||||
|
||||
if c_fireflies and math.random() < 0.01 then
|
||||
local firefly_vi = vi + ystride * math.random(1, 5)
|
||||
if data[firefly_vi] == c_air then
|
||||
data[firefly_vi] = c_fireflies
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local jungle_cavern_ceiling = function(abs_cracks, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.25 then
|
||||
data[vi] = c_glowstone
|
||||
elseif abs_cracks > 0.75 and math.random() < 0.1 then
|
||||
local ystride = area.ystride
|
||||
data[vi] = c_dirt
|
||||
local index = vi - ystride
|
||||
local hanging_node
|
||||
if math.random() < 0.5 then
|
||||
hanging_node = c_ivy
|
||||
else
|
||||
hanging_node = c_root_2
|
||||
end
|
||||
for i = 1, math.random(16) do
|
||||
if data[index] == c_air then
|
||||
data[index] = hanging_node
|
||||
index = index - ystride
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local jungle_warren_ceiling = function(abs_cracks, vi, area, data, data_param2)
|
||||
if abs_cracks < 0.1 then
|
||||
data[vi] = c_glowstone
|
||||
elseif abs_cracks > 0.75 and math.random() < 0.1 then
|
||||
local ystride = area.ystride
|
||||
data[vi] = c_dirt
|
||||
local index = vi - ystride
|
||||
local hanging_node
|
||||
if math.random() < 0.5 then
|
||||
hanging_node = c_root_1
|
||||
else
|
||||
hanging_node = c_root_2
|
||||
end
|
||||
for i = 1, math.random(8) do
|
||||
if data[index] == c_air then
|
||||
data[index] = hanging_node
|
||||
index = index - ystride
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local jungle_warren_floor = function(abs_cracks, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
if abs_cracks < 0.7 then
|
||||
data[vi] = c_jungle_dirt
|
||||
local rand = math.random() * abs_cracks
|
||||
if rand < 0.1 then
|
||||
data[vi+ystride] = jungle_plants[math.random(1,#jungle_plants)]
|
||||
end
|
||||
elseif abs_cracks < 1 then
|
||||
data[vi] = c_dirt
|
||||
end
|
||||
|
||||
if c_fireflies and math.random() < 0.005 then
|
||||
local firefly_vi = vi + ystride * math.random(1, 5)
|
||||
if data[firefly_vi] == c_air then
|
||||
data[firefly_vi] = c_fireflies
|
||||
end
|
||||
end
|
||||
end
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
local decorate_primordial = 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 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 cave_area = node_arrays.cave_area
|
||||
local nvals_cave = node_arrays.nvals_cave
|
||||
|
||||
local humiditymap = minetest.get_mapgen_object("humiditymap")
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Cavern floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local humidity = humiditymap[index2d]
|
||||
local jungle = nvals_cave[vi] < 0
|
||||
|
||||
if jungle then
|
||||
jungle_cavern_floor(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
else
|
||||
mushroom_cavern_floor(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Cavern ceilings
|
||||
|
||||
for _, vi in ipairs(node_arrays.cavern_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local jungle = nvals_cave[vi] < 0
|
||||
local humidity = humiditymap[index2d]
|
||||
if jungle then
|
||||
jungle_cavern_ceiling(abs_cracks, vi, area, data, data_param2)
|
||||
else
|
||||
mushroom_cavern_ceiling(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Tunnel floors
|
||||
|
||||
-- for _, vi in ipairs(node_arrays.tunnel_floor_nodes) do
|
||||
-- end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Tunnel ceiling
|
||||
|
||||
-- for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do
|
||||
-- end
|
||||
|
||||
------------------------------------------------------
|
||||
-- Warren ceiling
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_ceiling_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local jungle = nvals_cave[vi] < 0
|
||||
|
||||
if jungle then
|
||||
jungle_warren_ceiling(abs_cracks, vi, area, data, data_param2)
|
||||
else
|
||||
mushroom_warren_ceiling(abs_cracks, vi, area, data, data_param2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Warren floors
|
||||
|
||||
for _, vi in ipairs(node_arrays.warren_floor_nodes) do
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
local jungle = nvals_cave[vi] < 0
|
||||
|
||||
if jungle then
|
||||
jungle_warren_floor(abs_cracks, vi, area, data, data_param2)
|
||||
else
|
||||
mushroom_warren_floor(abs_cracks, vi, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
|
||||
-- columns
|
||||
-- no flowstone below the Sunless Sea, replace with something else
|
||||
local random_dir = {1, -1, area.zstride, -area.zstride}
|
||||
for _, vi in ipairs(node_arrays.column_nodes) do
|
||||
local jungle = nvals_cave[vi] < 0
|
||||
if jungle then
|
||||
data[vi] = c_plant_matter
|
||||
minetest.get_node_timer(area:position(vi)):start(math.random(30, 120))
|
||||
else
|
||||
data[vi] = c_mycelial_dirt
|
||||
if math.random() < 0.05 then
|
||||
local rand_vi = vi + random_dir[math.random(1,4)]
|
||||
if data[rand_vi] == c_air then
|
||||
data[rand_vi] = c_giant_mycelium
|
||||
minetest.get_node_timer(area:position(rand_vi)):start(math.random(1,giant_mycelium_timer_spread))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_param2_data(data_param2)
|
||||
end
|
||||
|
||||
--Primordial Caverns
|
||||
subterrane.register_layer({
|
||||
name = "primordial",
|
||||
y_max = df_caverns.config.primordial_max,
|
||||
y_min = df_caverns.config.primordial_min,
|
||||
cave_threshold = df_caverns.config.sunless_sea_threshold, -- Make the caves a bit bigger than above
|
||||
perlin_cave = perlin_cave_primordial,
|
||||
perlin_wave = perlin_wave_primordial,
|
||||
solidify_lava = true,
|
||||
columns = {
|
||||
maximum_radius = 20,
|
||||
minimum_radius = 5,
|
||||
node = "default:stone", -- no flowstone below the Sunless Sea, replace with something else
|
||||
weight = 0.5,
|
||||
maximum_count = 60,
|
||||
minimum_count = 10,
|
||||
},
|
||||
decorate = decorate_primordial,
|
||||
double_frequency = true,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
|
||||
-- Rather than make plants farmable, have them randomly respawn in jungle soil. You can only get them down there.
|
||||
minetest.register_abm({
|
||||
label = "Primordial plant growth",
|
||||
nodenames = {"df_primordial_items:dirt_with_jungle_grass"},
|
||||
neighbors = {"air"},
|
||||
interval = 60.0,
|
||||
chance = 50,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
if minetest.find_node_near(pos, 2, {"group:primordial_jungle_plant"}) == nil then
|
||||
local pos_above = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
local node_above = minetest.get_node(pos_above)
|
||||
if node_above.name == "air" then
|
||||
minetest.set_node(pos_above, {name = jungle_plant_names[math.random(1,#jungle_plant_names)]})
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Primordial fungus growth",
|
||||
nodenames = {"df_primordial_items:dirt_with_mycelium"},
|
||||
neighbors = {"air"},
|
||||
interval = 60.0,
|
||||
chance = 50,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
if minetest.find_node_near(pos, 3, {"group:primordial_fungal_plant"}) == nil then
|
||||
local pos_above = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
local node_above = minetest.get_node(pos_above)
|
||||
if node_above.name == "air" then
|
||||
minetest.set_node(pos_above, {name = fungal_plant_names[math.random(1,#fungal_plant_names)]})
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 146 KiB |
BIN
df_caverns/screenshots/mysterious_seal.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
df_caverns/screenshots/primordial_fungal.jpg
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
df_caverns/screenshots/primordial_jungle.jpg
Normal file
After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 40 KiB |
@ -37,4 +37,37 @@ 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
|
||||
dfcaverns_underworld_glowing_pit_mapblocks(Average pit spacing measured in mapblocks) int 8
|
||||
|
||||
[Underworld feature HUD]
|
||||
|
||||
dfcaverns_underworld_hud_requires_item (Require an item to view waypoints) bool true
|
||||
#Players can still discover the locations of volcanoes without this, but waypoints
|
||||
#will only be visible in their hud if they have this item in their inventory. You can also
|
||||
#specify "group:groupname" here. Leave it blank to default to map:mapping_kit.
|
||||
dfcaverns_underworld_hud_item_required (Specify the item or group required) string map:mapping_kit
|
||||
|
||||
|
||||
dfcaverns_show_pits_in_hud (Show pit locations in HUD) bool true
|
||||
dfcaverns_pit_discovery_range (Pit discovery range) int 60
|
||||
dfcaverns_pit_visibility_range (Pit visibility range) int 500
|
||||
|
||||
dfcaverns_show_seals_in_hud (Seal locations in HUD) bool true
|
||||
dfcaverns_seal_discovery_range (Seal discovery range) int 10
|
||||
dfcaverns_seal_visibility_range (Seal visibility range) int 200
|
||||
|
||||
dfcaverns_show_ruins_in_hud (Ruin locations visible in HUD) bool true
|
||||
dfcaverns_ruin_discovery_range (Ruin discovery range) int 40
|
||||
dfcaverns_ruin_visibility_range (Ruin visibility range) int 250
|
||||
|
||||
[Primordial]
|
||||
dfcaverns_enable_primordial (Generate primordial caverns) bool true
|
||||
dfcaverns_primordial_max (Upper limit of primordial caverns) int -3393
|
||||
dfcaverns_primordial_min (Lower limit of primordial caverns) int -4032
|
||||
|
||||
# This setting is pretty technical, it spreads out the
|
||||
# construction of giant mycelium networks on mapgen
|
||||
# over this many seconds. If you're experiencing lag spikes
|
||||
# during mapgen of Primordial cavern layer mushroom caverns
|
||||
# then increasing this number may help.
|
||||
dcaverns_giant_mycelium_timer_spread (Giant Mycelium mapgen timer spread) int 10
|
@ -124,6 +124,9 @@ local content_in_list=function(content, list)
|
||||
end
|
||||
|
||||
df_caverns.tunnel_floor = function(minp, maxp, area, vi, nvals_cracks, data, data_param2, wet)
|
||||
if maxp.y > -30 then
|
||||
wet = false
|
||||
end
|
||||
local ystride = area.ystride
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
@ -148,6 +151,10 @@ df_caverns.tunnel_floor = function(minp, maxp, area, vi, nvals_cracks, data, dat
|
||||
end
|
||||
|
||||
df_caverns.tunnel_ceiling = function(minp, maxp, area, vi, nvals_cracks, data, data_param2, wet)
|
||||
if maxp.y > -30 then
|
||||
wet = false
|
||||
end
|
||||
|
||||
local ystride = area.ystride
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local cracks = nvals_cracks[index2d]
|
||||
@ -207,4 +214,37 @@ df_caverns.place_shrub = function(vi, area, data, param2_data, shrub_list)
|
||||
|
||||
local shrub = shrub_list[math.random(#shrub_list)]
|
||||
shrub(vi, area, data, param2_data)
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
-- This method allows subterrane to overgenerate caves without destroying any of the decorations
|
||||
local dfcaverns_nodes = nil
|
||||
local dfcaverns_mods = {
|
||||
"df_farming:",
|
||||
"df_mapitems:",
|
||||
"df_primordial_items:",
|
||||
"df_trees:",
|
||||
"df_underworld_items:",
|
||||
"ice_sprites:",
|
||||
"mine_gas:",
|
||||
}
|
||||
df_caverns.is_ground_content = function(c_node)
|
||||
if dfcaverns_nodes then
|
||||
return not dfcaverns_nodes[c_node]
|
||||
end
|
||||
dfcaverns_nodes = {}
|
||||
for k, v in pairs(minetest.registered_nodes) do
|
||||
for _, prefix in ipairs(dfcaverns_mods) do
|
||||
if k:sub(1, #prefix) == prefix then
|
||||
dfcaverns_nodes[minetest.get_content_id(k)] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
dfcaverns_nodes[minetest.get_content_id("default:ice")] = true -- needed for nethercap cavern water covering
|
||||
dfcaverns_nodes[minetest.get_content_id("oil:oil_source")] = true -- needed for blackcap oil slicks
|
||||
if minetest.get_modpath("fireflies") then
|
||||
dfcaverns_nodes[minetest.get_content_id("fireflies:firefly")] = true -- used in the primordial caverns
|
||||
end
|
||||
dfcaverns_mods = nil
|
||||
return not dfcaverns_nodes[c_node]
|
||||
end
|
@ -107,7 +107,7 @@ local mushroom_cavern_floor = function(abs_cracks, vert_rand, vi, area, data, da
|
||||
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)
|
||||
df_trees.spawn_goblin_cap_vm(vi+ystride, area, data, data_param2)
|
||||
elseif math.random() < 0.02 then
|
||||
df_trees.spawn_spindlestem_vm(vi+ystride, area, data, data_param2)
|
||||
end
|
||||
@ -131,7 +131,7 @@ local fungispore_cavern_floor = function(abs_cracks, vert_rand, vi, area, data,
|
||||
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)
|
||||
df_trees.spawn_spore_tree_vm(vi+ystride, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -223,15 +223,20 @@ local decorate_sunless_sea = function(minp, maxp, seed, vm, node_arrays, area, d
|
||||
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
|
||||
|
||||
if minp.y <= sea_level then
|
||||
for vi, x, y, z in area:iterp_yxz(area.MinEdge, area.MaxEdge) do
|
||||
-- convert all air below sea level into water
|
||||
if y <= sea_level and data[vi] == c_air then
|
||||
data[vi] = c_water
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Cavern floors
|
||||
@ -375,6 +380,7 @@ local decorate_sunless_sea = function(minp, maxp, seed, vm, node_arrays, area, d
|
||||
else
|
||||
data[vi] = c_coral_table[math.random(1,3)]
|
||||
data_param2[vi] = math.random(1,4)-1
|
||||
minetest.get_node_timer(area:position(vi)):start(math.random(10, 60))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -401,4 +407,5 @@ subterrane.register_layer({
|
||||
},
|
||||
decorate = decorate_sunless_sea,
|
||||
double_frequency = false,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
|
@ -1,8 +1,11 @@
|
||||
-- surface tunnels
|
||||
|
||||
local y_max = -10
|
||||
local y_max = 200
|
||||
local y_min = df_caverns.config.ymax
|
||||
|
||||
local c_stone = minetest.get_content_id("default:stone")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
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
|
||||
@ -12,36 +15,55 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
local t_start = os.clock()
|
||||
|
||||
local vm, data, data_param2, area = mapgen_helper.mapgen_vm_data_param2()
|
||||
|
||||
local eminp = {x=minp.x, y=area.MinEdge.y, z=minp.z}
|
||||
local emaxp = {x=maxp.x, y=area.MaxEdge.y, z=maxp.z}
|
||||
local minp_y = minp.y
|
||||
local maxp_y = maxp.y
|
||||
|
||||
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
|
||||
local previous_y = eminp.y-1
|
||||
|
||||
for vi, x, y, z in area:iterp_yxz(minp, maxp) do
|
||||
local previous_potential_floor_vi
|
||||
local previous_potential_floor_y
|
||||
local previous_node
|
||||
|
||||
for vi, x, y, z in area:iterp_yxz(eminp, emaxp) do
|
||||
|
||||
if y < previous_y then
|
||||
previous_state = "outside_region"
|
||||
-- we've started a new column, initialize everything
|
||||
previous_potential_floor_vi = nil
|
||||
previous_potential_floor_y = nil
|
||||
previous_node = nil
|
||||
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)
|
||||
local current_node = data[vi]
|
||||
if previous_node and y < y_max then
|
||||
if current_node == c_air and previous_node == c_stone then
|
||||
-- this may be a floor, but only if we eventually hit a ceiling in this column
|
||||
previous_potential_floor_vi = vi-area.ystride
|
||||
previous_potential_floor_y = y-1
|
||||
elseif current_node == c_stone and previous_node == c_air and previous_potential_floor_vi then
|
||||
-- we hit a ceiling after passing through a floor
|
||||
local index2d = mapgen_helper.index2d(minp, maxp, x, z)
|
||||
local humidity = humiditymap[index2d]
|
||||
if previous_potential_floor_y <= maxp_y and previous_potential_floor_y >= minp_y then
|
||||
df_caverns.tunnel_floor(minp, maxp, area, previous_potential_floor_vi, 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]
|
||||
if y <= maxp_y and y >= minp_y then
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, humidity > 30)
|
||||
end
|
||||
previous_state = "in_rock"
|
||||
previous_potential_floor_vi = nil
|
||||
elseif not mapgen_helper.buildable_to(current_node) then
|
||||
-- we've entered a non-stone ceiling of some kind. Abort potential floor-ceiling pair detection.
|
||||
previous_potential_floor_vi = nil
|
||||
end
|
||||
end
|
||||
previous_node = current_node
|
||||
|
||||
end
|
||||
|
||||
--send data back to voxelmanip
|
||||
@ -55,12 +77,6 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--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
|
||||
|
||||
local time_taken = os.clock() - t_start -- how long this chunk took, in seconds
|
||||
mapgen_helper.record_time("df_caverns surface tunnels", time_taken)
|
||||
end)
|
||||
|
@ -1,10 +1,82 @@
|
||||
if not df_caverns.config.enable_underworld or not minetest.get_modpath("df_underworld_items") then
|
||||
return
|
||||
end
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
local S = minetest.get_translator("df_caverns")
|
||||
|
||||
local bones_loot_path = minetest.get_modpath("bones_loot")
|
||||
local named_waypoints_path = minetest.get_modpath("named_waypoints")
|
||||
local namegen_path = minetest.get_modpath("namegen")
|
||||
|
||||
local name_pit = function() end
|
||||
local name_ruin = function() end
|
||||
|
||||
if named_waypoints_path then
|
||||
|
||||
local item_required = nil
|
||||
if minetest.settings:get_bool("dfcaverns_underworld_hud_requires_item", true) then
|
||||
local setting_item_required = minetest.settings:get("dfcaverns_underworld_hud_item_required")
|
||||
if setting_item_required == nil or setting_item_required == "" then
|
||||
setting_item_required = "map:mapping_kit"
|
||||
end
|
||||
item_required = setting_item_required
|
||||
end
|
||||
|
||||
local pit_waypoint_def = {
|
||||
default_name = S("A glowing pit"),
|
||||
default_color = 0xFF88FF,
|
||||
discovery_volume_radius = tonumber(minetest.settings:get("dfcaverns_pit_discovery_range")) or 60,
|
||||
visibility_requires_item = item_required,
|
||||
}
|
||||
|
||||
if minetest.settings:get_bool("dfcaverns_show_pits_in_hud", true) then
|
||||
pit_waypoint_def.visibility_volume_radius = tonumber(minetest.settings:get("dfcaverns_pit_visibility_range")) or 500
|
||||
pit_waypoint_def.on_discovery = named_waypoints.default_discovery_popup
|
||||
end
|
||||
named_waypoints.register_named_waypoints("glowing_pits", pit_waypoint_def)
|
||||
|
||||
local seal_waypoint_def = {
|
||||
default_name = S("Mysterious seal"),
|
||||
default_color = 0x9C2233,
|
||||
discovery_volume_radius = tonumber(minetest.settings:get("dfcaverns_seal_discovery_range")) or 10,
|
||||
visibility_requires_item = item_required,
|
||||
}
|
||||
|
||||
if minetest.settings:get_bool("dfcaverns_show_seals_in_hud", true) then
|
||||
seal_waypoint_def.visibility_volume_radius = tonumber(minetest.settings:get("dfcaverns_seal_visibility_range")) or 200
|
||||
seal_waypoint_def.on_discovery = named_waypoints.default_discovery_popup
|
||||
end
|
||||
named_waypoints.register_named_waypoints("puzzle_seals", seal_waypoint_def)
|
||||
|
||||
if namegen_path then
|
||||
namegen.parse_lines(io.lines(modpath.."/underworld_names.cfg"))
|
||||
|
||||
name_pit = function()
|
||||
return namegen.generate("glowing_pits")
|
||||
end
|
||||
name_ruin = function()
|
||||
return namegen.generate("underworld_ruins")
|
||||
end
|
||||
|
||||
local underworld_ruin_def = {
|
||||
default_name = S("Ancient ruin"),
|
||||
discovery_volume_radius = tonumber(minetest.settings:get("dfcaverns_ruin_discovery_range")) or 40,
|
||||
visibility_requires_item = item_required,
|
||||
}
|
||||
if minetest.settings:get_bool("dfcaverns_show_ruins_in_hud", true) then
|
||||
underworld_ruin_def.visibility_volume_radius = tonumber(minetest.settings:get("dfcaverns_ruin_visibility_range")) or 250
|
||||
underworld_ruin_def.on_discovery = named_waypoints.default_discovery_popup
|
||||
end
|
||||
|
||||
named_waypoints.register_named_waypoints("underworld_ruins", underworld_ruin_def)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local c_slade = minetest.get_content_id("df_underworld_items:slade")
|
||||
local c_slade_block = minetest.get_content_id("df_underworld_items:slade_block")
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_water = minetest.get_content_id("default:water_source")
|
||||
|
||||
@ -60,6 +132,9 @@ local y_min = median - 2*wave_mult + floor_displace - 2*floor_mult
|
||||
|
||||
--df_caverns.config.underworld_min = y_min
|
||||
|
||||
--local poisson = mapgen_helper.get_poisson_points({x=-32000, z=-32000}, {x=32000, z=32000}, 1000)
|
||||
--minetest.debug(dump(poisson.objects))
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Buildings
|
||||
|
||||
@ -67,8 +142,11 @@ local oubliette_threshold = 0.8
|
||||
local town_threshold = 1.1
|
||||
|
||||
local local_random = function(x, z)
|
||||
local next_seed = math.floor(math.random()*2^21)
|
||||
math.randomseed(x + z*2^16)
|
||||
return math.random()
|
||||
local ret = math.random()
|
||||
math.randomseed(next_seed)
|
||||
return ret
|
||||
end
|
||||
|
||||
-- create a deterministic list of buildings
|
||||
@ -196,9 +274,9 @@ 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.x = math.floor(math.random() * bordered_scale + min_xz.x + border_width)
|
||||
point.y = 0
|
||||
point.z = math.random() * bordered_scale + min_xz.z + border_width
|
||||
point.z = math.floor(math.random() * bordered_scale + min_xz.z + border_width)
|
||||
return point
|
||||
end
|
||||
|
||||
@ -207,19 +285,19 @@ 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 mapgen_seed = tonumber(minetest.get_mapgen_setting("seed")) % 2^21
|
||||
|
||||
local get_pit = function(pos)
|
||||
if region_mapblocks < 1 then return nil end
|
||||
|
||||
local corner_xz = get_corner(pos)
|
||||
local next_seed = math.floor(math.random() * 2^31)
|
||||
local next_seed = math.floor(math.random() * 2^21)
|
||||
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)
|
||||
local depth = math.random(plasma_depth_min, plasma_depth_max)
|
||||
math.randomseed(next_seed)
|
||||
return {location = location, radius = radius, variance = variance, depth = depth}
|
||||
end
|
||||
@ -242,11 +320,12 @@ minetest.register_chatcommand("find_pit", {
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pit = get_pit(player:get_pos())
|
||||
minetest.chat_send_player(name, "Pit location: x=" .. math.floor(pit.location.x) .. " z=" .. math.floor(pit.location.z))
|
||||
if pit then
|
||||
minetest.chat_send_player(name, "Pit location: x=" .. math.floor(pit.location.x) .. " z=" .. math.floor(pit.location.z))
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
|
||||
--if out of range of cave definition limits, abort
|
||||
@ -266,7 +345,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
|
||||
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
|
||||
@ -279,8 +358,16 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
local wave = nvals_wave[index2d] * wave_mult
|
||||
|
||||
local floor_height = math.floor(abs_cave * floor_mult + median + floor_displace + wave)
|
||||
|
||||
if named_waypoints_path and floor_height == y and pit and pit.location.x == x and pit.location.z == z then
|
||||
named_waypoints.add_waypoint("glowing_pits", {x=x, y=y, z=z}, {name=name_pit()})
|
||||
end
|
||||
|
||||
local underside_height = math.floor(y_min + math.abs(wave) / 5)+2 -- divide wave by five to smooth out the underside of the slade, we only want the interface to ripple a little down here
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
if y < floor_height and y > y_min + math.abs(wave) / 5 then -- divide wave by five to smooth out the underside of the slade, we only want the interface to ripple a little down here
|
||||
if (y == underside_height or y == underside_height - 1) and (x % 8 == 0 or z % 8 == 0) then
|
||||
data[vi] = c_air
|
||||
elseif y < floor_height and y > underside_height then
|
||||
data[vi] = c_slade
|
||||
if pit and
|
||||
pit.location.x - radius_pit_max - radius_pit_variance < maxp.x and
|
||||
@ -290,13 +377,13 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
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
|
||||
nvals_pit, area_pit = mapgen_helper.perlin3d("df_cavern:perlin_cave", minp, maxp, perlin_pit)
|
||||
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 < median + floor_displace + wave - pit.depth then
|
||||
if distance < pit.radius -2.5 then
|
||||
if y < median + floor_displace + wave - pit.depth or y < underside_height + plasma_depth_min then
|
||||
data[vi] = c_pit_plasma
|
||||
else
|
||||
data[vi] = c_air
|
||||
@ -308,8 +395,8 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
df_underworld_items.underworld_shard(data, area, vi)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif y < ceiling_height and data[vi] ~= c_amethyst then
|
||||
end
|
||||
elseif y >= floor_height and 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
|
||||
@ -369,7 +456,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
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)
|
||||
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
|
||||
@ -378,6 +465,11 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
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)
|
||||
if named_waypoints_path and namegen_path then
|
||||
if not next(named_waypoints.get_waypoints_in_area("underworld_ruins", vector.subtract(building.pos, 250), vector.add(building.pos, 250))) then
|
||||
named_waypoints.add_waypoint("underworld_ruins", {x=building.pos.x, y=floor_height+1, z=building.pos.z}, {name=name_ruin()})
|
||||
end
|
||||
end
|
||||
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
|
||||
@ -388,6 +480,25 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- puzzle seal
|
||||
local puzzle_seal = nil
|
||||
if pit_uninitialized and math.random() < 0.05 then
|
||||
local index2d = mapgen_helper.index2d(emin, emax, minp.x + 3, minp.z + 3)
|
||||
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 underside_height = math.floor(y_min + math.abs(wave) / 5)
|
||||
|
||||
if floor_height < maxp.y and floor_height > minp.y then
|
||||
for plat_vi in area:iter(minp.x, floor_height-6, minp.z, minp.x+6, floor_height, minp.z+6) do
|
||||
data[plat_vi] = c_slade_block
|
||||
end
|
||||
puzzle_seal = {x=minp.x+3, y=floor_height+1, z=minp.z+3}
|
||||
minetest.log("info", "Puzzle seal generated at " .. minetest.pos_to_string(puzzle_seal))
|
||||
end
|
||||
end
|
||||
|
||||
--send data back to voxelmanip
|
||||
vm:set_data(data)
|
||||
@ -399,6 +510,17 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
--write it to world
|
||||
vm:write_to_map()
|
||||
|
||||
if puzzle_seal ~= nil then
|
||||
if named_waypoints_path then
|
||||
named_waypoints.add_waypoint("puzzle_seals", puzzle_seal)
|
||||
end
|
||||
|
||||
minetest.place_schematic({x=puzzle_seal.x-3, y=puzzle_seal.y, z=puzzle_seal.z-3}, df_underworld_items.seal_temple_schem, 0, {}, true)
|
||||
local node_name = minetest.get_node(puzzle_seal).name
|
||||
local node_def = minetest.registered_nodes[node_name]
|
||||
node_def.on_construct(puzzle_seal)
|
||||
end
|
||||
|
||||
if bones_loot_path then
|
||||
for i = 1, 30 do
|
||||
local x = math.random(minp.x, maxp.x)
|
||||
@ -406,7 +528,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
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 floor_height = math.floor(abs_cave * floor_mult + median + floor_displace + wave)-1
|
||||
local ceiling_height = math.floor(abs_cave * ceiling_mult + median + ceiling_displace + wave)
|
||||
if floor_height < ceiling_height then
|
||||
local zone = math.abs(nvals_zone[index2d])
|
||||
@ -433,11 +555,6 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
local time_taken = os.clock() - t_start -- how long this chunk took, in seconds
|
||||
mapgen_helper.record_time("df_caverns underworld", time_taken)
|
||||
end)
|
||||
|
18
df_caverns/underworld_names.cfg
Normal file
@ -0,0 +1,18 @@
|
||||
name "glowing_pits" {
|
||||
customGroupA = "Actinic, Amethyst, Angry, Atrocious, Bad, Blighted, Baneful, Baleful, Beastly, Calamitous, Corrupt, Crazed, Damnable, Demoniacal, Demonic, Depraved, Destructive, Devilish, Diabolical, Disastrous, Execrable, Fiendish, Foul, Frenzied, Glaring, Harmful, Hateful, Heinous, Hellish, Hideous, Infernal, Iniquitous, Injurious, Loathsome, Lost, Maleficent, Malevolent, Malicious, Malignant, Manic, Nefarious, Nightmare, Obscene, Offensive, Pernicious, Poison, Possessed, Rancorous, Repugnant, Repulsive, Revolting, Spiteful, Unhallowed, Unpleasant, Vicious, Vile, Villainous, Violent, Wicked, Wrathful"
|
||||
|
||||
customGroupB = "Abyss, Aperture, Breach, Cavity, Chasm, Crevasse, Depth, Deep, Fissure, Funnel, Gate, Gulf, Hell, Hole, Hollow, Inferno, Maw, Mouth, Opening, Pit, Portal, Puncture, Ravager, Rent, Rift, Rim, Schism, Shaft, Split, Throat, Void, Well"
|
||||
|
||||
customGroupC = "Adversity, Affliction, Annihilation, Bale, Bane, Blight, Calamity, Cataclysm, Catastrophe, Collapse, Conclusion, Condemnation, Death, Defeat, Destiny, Destruction, Disaster, Doom, Downfall, Failure, Grief, Harm, Hazard, Judgment, Karma, Misadventure, Mischance, Misfortune, Mishap, Ruin, Ruination, Tragedy, Undoing, Verdict, Woe"
|
||||
|
||||
rules = "%50The_$A_$B, The_$B_of_$C, %10The_$A_$B_of_$C"
|
||||
}
|
||||
|
||||
name "underworld_ruins" {
|
||||
|
||||
customGroupA = "Abandoned, Absent, Adrift, Alien, Anonymous, Bare, Barren, Blank, Buried, Clandestine, Cloaked, Concealed, Covered, Cryptic, Dark, Dead, Depleted, Deserted, Desolate, Despoiled, Destitute, Devoid, Disappeared, Distant, Exhausted, Empty, Forfeit, Forfeited, Forsaken, Hidden, Incognito, Indiscernible, Invisible, Irretrievable, Irrevocable, Masked, Mislaid, Misplaced, Mystic, Mystical, Nameless, Obscured, Secluded, Secret, Sequestered, Shadowy, Shrouded, Stark, Strange, Uncelebrated, Uncharted, Undiscovered, Unexplained, Unexplored, Unfamiliar, Unfilled, Unidentified, Unknown, Unnamed, Unredeemed, Unsung, Untold, Vacant, Vacated, Vanished, Veiled, Wayward, Warrior's, King's, Knave's, Coward's, Cardinal's, Priest's, Soldier's, Noble, Steadfast, Children's, Howling, Silent, Grinding, Dusty"
|
||||
|
||||
customGroupB = "Temple, Chapel, House, Sanctuary, Shrine, Fortress, Tomb, Crypt, Graves, Citadel, Garrison, Rampart, Redoubt, Refuge, Asylum, Haven, Hideout, Retreat, Shelter, Stronghold, Covert, Den, Settlement, Preserve, Seat, Watch, Bulwark, Necropolis, Catacomb, Ruin, Hulk, Wreck"
|
||||
|
||||
rules = "The_$A_$B"
|
||||
}
|