many worldgen mods and gonna try technic now
@@ -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.
|
||||
@@ -0,0 +1,159 @@
|
||||
if minetest.get_modpath("dungeon_loot") then
|
||||
|
||||
if df_caverns.config.enable_underworld then
|
||||
dungeon_loot.register({
|
||||
{name = "df_underworld_items:glow_amethyst", chance = 0.3, count = {1, 12}, y = {-32768, df_caverns.config.lava_sea_level}},
|
||||
})
|
||||
end
|
||||
|
||||
if df_caverns.config.enable_oil_sea and minetest.get_modpath("bucket") then
|
||||
dungeon_loot.register({
|
||||
{name = "oil:oil_bucket", chance = 0.5, count = {1, 3}, y = {-32768, df_caverns.config.ymax}},
|
||||
})
|
||||
end
|
||||
|
||||
if df_caverns.config.enable_lava_sea then
|
||||
dungeon_loot.register({
|
||||
{name = "df_mapitems:mese_crystal", chance = 0.25, count = {1, 5}, y = {-32768, df_caverns.config.sunless_sea_min}},
|
||||
{name = "df_mapitems:glow_mese", chance = 0.1, count = {1, 3}, y = {-32768, df_caverns.config.sunless_sea_min}},
|
||||
})
|
||||
end
|
||||
|
||||
dungeon_loot.register({
|
||||
{name = "df_farming:cave_wheat_seed", chance = 0.5, count = {1, 10}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_farming:cave_bread", chance = 0.8, count = {1, 10}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_farming:pig_tail_thread", chance = 0.7, count = {1, 10}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_farming:plump_helmet_spawn", chance = 0.4, count = {1, 8}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_farming:plump_helmet_4_picked", chance = 0.8, count = {1, 15}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_trees:glowing_bottle_red", chance = 0.6, count = {1, 20}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_trees:glowing_bottle_green", chance = 0.5, count = {1, 20}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_trees:glowing_bottle_cyan", chance = 0.4, count = {1, 15}, y = {-32768, df_caverns.config.ymax}},
|
||||
{name = "df_trees:glowing_bottle_golden", chance = 0.3, count = {1, 5}, y = {-32768, df_caverns.config.ymax}},
|
||||
|
||||
{name = "df_farming:pig_tail_seed", chance = 0.5, count = {1, 10}, y = {-32768, df_caverns.config.level1_min}},
|
||||
{name = "df_mapitems:med_crystal", chance = 0.2, count = {1, 2}, y = {-32768, df_caverns.config.level1_min}},
|
||||
|
||||
{name = "df_farming:dimple_cup_seed", chance = 0.3, count = {1, 10}, y = {-32768, df_caverns.config.level2_min}},
|
||||
{name = "df_farming:quarry_bush_seed", chance = 0.3, count = {1, 5}, y = {-32768, df_caverns.config.level2_min}},
|
||||
{name = "df_farming:sweet_pod_seed", chance = 0.3, count = {1, 5}, y = {-32768, df_caverns.config.level2_min}},
|
||||
{name = "df_mapitems:big_crystal", chance = 0.1, count = {1, 1}, y = {-32768, df_caverns.config.level2_min}},
|
||||
{name = "df_trees:torchspine_ember", chance = 0.3, count = {1, 3}, y = {-32768, df_caverns.config.level2_min}},
|
||||
{name = "ice_sprites:ice_sprite_bottle", chance = 0.1, count = {1, 1}, y = {-32768, df_caverns.config.level2_min}},
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
if minetest.get_modpath("bones_loot") and df_caverns.config.enable_underworld then
|
||||
|
||||
if minetest.get_modpath("default") then
|
||||
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,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:tulip_black", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:dandelion_white", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:dandelion_yellow", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:rose", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:tulip", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:chrysanthemum_green", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "flowers:geranium", chance = 0.1, 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
|
||||
{name = "tnt:gunpowder", chance = 0.4, count = {1,10}, types = {"underworld_warrior"}},
|
||||
{name = "tnt:tnt_stick", chance = 0.3, count = {1,6}, types = {"underworld_warrior"}},
|
||||
|
||||
{name = "vessels:steel_bottle", chance = 0.4, count = {1,3}, types = {"underworld_warrior"}},
|
||||
{name = "vessels:glass_bottle", chance = 0.2, count = {1,2}, types = {"underworld_warrior"}},
|
||||
{name = "vessels:glass_fragments", chance = 0.1, count = {1,4}, types = {"underworld_warrior"}},
|
||||
|
||||
{name = "default:book", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:paper", chance = 0.1, count = {1,6}, types = {"underworld_warrior"}},
|
||||
{name = "default:skeleton_key", chance = 0.05, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:torch", chance = 0.75, count = {1,10}, types = {"underworld_warrior"}},
|
||||
|
||||
{name = "default:pick_bronze", chance = 0.15, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{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.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"}},
|
||||
{name = "default:axe_diamond", chance = 0.15, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:sword_bronze", chance = 0.5, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:sword_steel", chance = 0.75, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:sword_mese", chance = 0.35, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:sword_diamond", chance = 0.35, count = {1,1}, types = {"underworld_warrior"}},
|
||||
|
||||
{name = "default:coal_lump", chance = 0.5, count = {1,5}, types = {"underworld_warrior"}},
|
||||
{name = "default:mese_crystal", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:diamond", chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:steel_ingot", chance = 0.2, count = {1,3}, types = {"underworld_warrior"}},
|
||||
{name = "default:copper_ingot", chance = 0.1, count = {1,2}, types = {"underworld_warrior"}},
|
||||
{name = "default:bronze_ingot", chance = 0.2, count = {1,5}, types = {"underworld_warrior"}},
|
||||
{name = "default:gold_ingot", chance = 0.3, count = {1,3}, types = {"underworld_warrior"}},
|
||||
{name = "default:mese_crystal_fragment", chance = 0.4, count = {1,5}, types = {"underworld_warrior"}},
|
||||
{name = "default:obsidian_shard", chance = 0.4, count = {1,3}, types = {"underworld_warrior"}},
|
||||
{name = "default:flint", chance = 0.3, count = {1,1}, types = {"underworld_warrior"}},
|
||||
{name = "default:sign_wall_wood", chance = 0.1, count = {1,4}, types = {"underworld_warrior"}},
|
||||
{name = "default:sign_wall_steel", chance = 0.1, count = {1,2}, types = {"underworld_warrior"}},
|
||||
{name = "default:ladder_wood", chance = 0.5, count = {1,10}, types = {"underworld_warrior"}},
|
||||
{name = "default:ladder_steel", chance = 0.2, count = {1,5}, types = {"underworld_warrior"}},
|
||||
{name = "default:meselamp", chance = 0.1, count = {1,2}, types = {"underworld_warrior"}},
|
||||
{name = "default:mese_post_light", chance = 0.25, count = {1,5}, types = {"underworld_warrior"}},
|
||||
})
|
||||
end
|
||||
|
||||
if minetest.get_modpath("mcl_core") then
|
||||
bones_loot.register_loot({
|
||||
-- Taken from the ruined portal loot table in mcl
|
||||
{name = "mcl_core:iron_nugget", types = {"underworld_warrior"}, chance = 40/50, count ={9, 18}},
|
||||
{name = "mcl_core:flint", types = {"underworld_warrior"}, chance = 40/50, count ={9, 18}},
|
||||
{name = "mcl_core:obsidian", types = {"underworld_warrior"}, chance = 40/50, count ={1, 2}},
|
||||
{name = "mcl_fire:fire_charge", types = {"underworld_warrior"}, chance = 40/50, count ={1, 1}},
|
||||
{name = "mcl_fire:flint_and_steel", types = {"underworld_warrior"}, chance = 40/50, count ={1, 1}},
|
||||
{name = "mcl_core:gold_nugget", types = {"underworld_warrior"}, chance = 15/50, count ={4, 24}},
|
||||
{name = "mcl_core:apple_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_tools:axe_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_farming:hoe_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_tools:pick_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_tools:shovel_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_tools:sword_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_armor:helmet_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_armor:chestplate_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_armor:leggings_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_armor:boots_gold", types = {"underworld_warrior"}, chance = 15/50, count ={1, 1}},
|
||||
{name = "mcl_potions:speckled_melon", types = {"underworld_warrior"}, chance = 5/50, count ={4, 12}},
|
||||
{name = "mcl_farming:carrot_item_gold", types = {"underworld_warrior"}, chance = 5/50, count ={4, 12}},
|
||||
{name = "mcl_core:gold_ingot", types = {"underworld_warrior"}, chance = 5/50, count ={2, 8}},
|
||||
{name = "mcl_clock:clock", types = {"underworld_warrior"}, chance = 5/50, count ={1,1}},
|
||||
{name = "mesecons_pressureplates:pressure_plate_gold_off", types = {"underworld_warrior"}, chance = 5/50, count ={1,1}},
|
||||
{name = "mobs_mc:gold_horse_armor", types = {"underworld_warrior"}, chance = 5/50, count ={1,1}},
|
||||
{name = "mcl_bells:bell", types = {"underworld_warrior"}, chance = 1/50, count ={1,1}},
|
||||
{name = "mcl_core:apple_gold_enchanted", types = {"underworld_warrior"}, chance = 1/50, count ={1,1}},
|
||||
})
|
||||
|
||||
for flower_name, _ in pairs(mcl_flowers.registered_simple_flowers) do
|
||||
bones_loot.register_loot({
|
||||
{name = flower_name, chance = 0.1, count = {1,1}, types = {"underworld_warrior"}},
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
bones_loot.register_loot({
|
||||
{name = "ice_sprites:ice_sprite_bottle", chance = 0.025, count = {1, 1}, types = {"underworld_warrior"}},
|
||||
{name = "df_underworld_items:glow_amethyst", chance = 0.25, count = {1, 2}, types = {"underworld_warrior"}},
|
||||
})
|
||||
|
||||
if df_caverns.config.enable_lava_sea then
|
||||
bones_loot.register_loot({name = "df_mapitems:mese_crystal", chance = 0.25, count = {1, 2}, types = {"underworld_warrior"}})
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
local add_biome_restrictions = function(root_table, function_name, biome_set)
|
||||
local old_function = root_table[function_name]
|
||||
root_table[function_name] = function(pos)
|
||||
local biome = df_caverns.get_biome(pos)
|
||||
return old_function(pos) and biome_set[biome]
|
||||
end
|
||||
end
|
||||
|
||||
if df_caverns.config.restrict_trees_to_biomes then
|
||||
|
||||
if minetest.get_modpath("df_trees") then
|
||||
add_biome_restrictions(df_trees, "black_cap_growth_permitted", {blackcap = true})
|
||||
add_biome_restrictions(df_trees, "blood_thorn_growth_permitted", {bloodthorn = true})
|
||||
add_biome_restrictions(df_trees, "fungiwood_growth_permitted", {fungiwood = true, fungispore = true})
|
||||
add_biome_restrictions(df_trees, "goblin_cap_growth_permitted", {goblincap = true, towergoblin = true})
|
||||
add_biome_restrictions(df_trees, "nether_cap_growth_permitted", {nethercap = true})
|
||||
add_biome_restrictions(df_trees, "spore_tree_growth_permitted", {sporetree = true, fungispore = true})
|
||||
add_biome_restrictions(df_trees, "tower_cap_growth_permitted", {towercap = true, towergoblin = true})
|
||||
add_biome_restrictions(df_trees, "tunnel_tube_growth_permitted", {tunneltube = true})
|
||||
-- Deliberately not biome-restricted
|
||||
--add_biome_restrictions(df_trees, "torchspine_growth_permitted", {})
|
||||
--add_biome_restrictions(df_trees, "spindlestem_growth_permitted", {})
|
||||
end
|
||||
|
||||
if minetest.get_modpath("df_primordial_items") then
|
||||
add_biome_restrictions(df_primordial_items, "primordial_mushroom_growth_permitted", {["primordial fungus"] = true})
|
||||
add_biome_restrictions(df_primordial_items, "giant_mycelium_growth_permitted", {["primordial fungus"] = true})
|
||||
add_biome_restrictions(df_primordial_items, "giant_fern_growth_permitted", {["primordial jungle"] = true})
|
||||
add_biome_restrictions(df_primordial_items, "jungle_mushroom_growth_permitted", {["primordial jungle"] = true})
|
||||
add_biome_restrictions(df_primordial_items, "jungletree_growth_permitted", {["primordial jungle"] = true})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if df_caverns.config.restrict_farmables_to_biomes and minetest.get_modpath("df_farming") then
|
||||
add_biome_restrictions(df_farming.growth_permitted, "df_farming:cave_wheat_seed",
|
||||
{fungiwood = true, tunneltube = true, sporetree = true, fungispore = true})
|
||||
add_biome_restrictions(df_farming.growth_permitted, "df_farming:dimple_cup_seed",
|
||||
{towergoblin = true})
|
||||
add_biome_restrictions(df_farming.growth_permitted, "df_farming:pig_tail_seed",
|
||||
{sporetree = true, fungispore = true})
|
||||
add_biome_restrictions(df_farming.growth_permitted, "df_farming:quarry_bush_seed",
|
||||
{bloodthorn = true})
|
||||
add_biome_restrictions(df_farming.growth_permitted, "df_farming:sweet_pod_seed",
|
||||
{tunneltube = true, fungispore = true})
|
||||
add_biome_restrictions(df_farming.growth_permitted, "df_farming:plump_helmet_spawn",
|
||||
{fungiwood = true, towercap = true, goblincap = true, towergoblin = true})
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
df_caverns = {}
|
||||
df_caverns.config = df_dependencies.config
|
||||
|
||||
--grab a shorthand for the filepath of the mod
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
--load companion lua files
|
||||
dofile(modpath.."/node_ids.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")
|
||||
dofile(modpath.."/primordial.lua")
|
||||
dofile(modpath.."/dungeon_loot.lua")
|
||||
dofile(modpath.."/growth_restrictions.lua")
|
||||
@@ -0,0 +1,157 @@
|
||||
if not df_caverns.config.enable_lava_sea then
|
||||
return
|
||||
end
|
||||
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_lava = df_caverns.node_id.lava
|
||||
local c_meseore = df_caverns.node_id.meseore
|
||||
local c_mese_crystal = df_caverns.node_id.mese_crystal
|
||||
local c_mese_crystal_block = df_caverns.node_id.mese_crystal_block
|
||||
local c_obsidian = df_caverns.node_id.obsidian
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
end
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y > y_max or pos.y < y_min then
|
||||
return
|
||||
end
|
||||
return "lava_sea"
|
||||
end)
|
||||
|
||||
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
|
||||
if log_location then log_location("magma_sea", area:position(vi)) end
|
||||
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
|
||||
if log_location then log_location("magma_sea_meseore", area:position(vi)) end
|
||||
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
|
||||
if log_location then log_location("magma_sea_mesecrystal", area:position(vi)) end
|
||||
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)
|
||||
if log_location then log_location("magma_sea_mesebig", area:position(vi)) 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 time_taken = os.clock() - t_start -- how long this chunk took, in seconds
|
||||
mapgen_helper.record_time("df_caverns lava sea", time_taken)
|
||||
end)
|
||||
@@ -0,0 +1,341 @@
|
||||
local c_water = df_caverns.node_id.water
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_dirt = df_caverns.node_id.dirt
|
||||
local c_dirt_moss = df_caverns.node_id.dirt_moss
|
||||
local c_gravel = df_caverns.node_id.gravel
|
||||
local c_wet_flowstone = df_caverns.node_id.wet_flowstone
|
||||
local c_dry_flowstone = df_caverns.node_id.dry_flowstone
|
||||
local c_spindlestem_white = df_caverns.node_id.spindlestem_white
|
||||
|
||||
local tower_cap_shrublist
|
||||
local fungiwood_shrublist
|
||||
|
||||
local chasms_path = minetest.get_modpath("chasms")
|
||||
|
||||
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 log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
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
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y < df_caverns.config.level1_min or pos.y > df_caverns.config.ymax then
|
||||
return nil
|
||||
end
|
||||
return get_biome(heat, humidity)
|
||||
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 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.04 then
|
||||
df_trees.spawn_spindlestem_vm(vi+ystride, area, data, data_param2, c_spindlestem_white)
|
||||
end
|
||||
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)
|
||||
elseif math.random() < 0.04 then
|
||||
df_trees.spawn_spindlestem_vm(vi+ystride, area, data, data_param2)
|
||||
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, 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
|
||||
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[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)
|
||||
if log_location then log_location("level1_flooded_"..biome_name, area:position(vi)) end
|
||||
elseif biome_name == "towercap" then
|
||||
tower_cap_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level1_towercap", area:position(vi)) end
|
||||
elseif biome_name == "fungiwood" then
|
||||
fungiwood_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level1_fungiwood", area:position(vi)) end
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
df_caverns.wet_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level1_barren_wet", area:position(vi)) end
|
||||
else
|
||||
df_caverns.dry_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level1_barren_dry", area:position(vi)) end
|
||||
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[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[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, c_gravel)
|
||||
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[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[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
local ystride = area.ystride
|
||||
|
||||
if log_location then
|
||||
local flood_name = ""
|
||||
if flooded_caverns then flood_name = "_flooded" end
|
||||
log_location("level1_warren_"..biome_name..flood_name, area:position(vi))
|
||||
end
|
||||
|
||||
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, c_gravel)
|
||||
end
|
||||
|
||||
if biome_name ~= "barren" then
|
||||
local cracks = nvals_cracks[index2d]
|
||||
if cracks > 0.25 then
|
||||
local rand = math.random()
|
||||
if rand > cracks then
|
||||
if math.random() < 0.25 then
|
||||
data[vi] = c_dirt_moss
|
||||
else
|
||||
data[vi] = c_dirt
|
||||
end
|
||||
if data[vi+ystride] == c_air and math.random() < 0.25 then
|
||||
df_caverns.place_shrub(vi+ystride, area, data, data_param2, tower_cap_shrublist)
|
||||
end
|
||||
end
|
||||
if rand > cracks*2 then
|
||||
df_trees.spawn_spindlestem_vm(vi+ystride, area, data, data_param2)
|
||||
end
|
||||
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[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[vi] > 0)
|
||||
|
||||
if dry and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
|
||||
if chasms_path then
|
||||
local pos = area:position(vi)
|
||||
if chasms.is_in_chasm_without_taper(pos) then
|
||||
local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
if flooded_caverns and pos.y < subsea_level then
|
||||
data[vi] = c_water
|
||||
else
|
||||
data[vi] = c_air
|
||||
end
|
||||
end
|
||||
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,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
@@ -0,0 +1,424 @@
|
||||
local c_water = df_caverns.node_id.water
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_dirt = df_caverns.node_id.dirt
|
||||
local c_dirt_moss = df_caverns.node_id.dirt_moss
|
||||
local c_gravel = df_caverns.node_id.gravel
|
||||
|
||||
local c_stillworm = df_caverns.node_id.stillworm
|
||||
local c_pebble_fungus = df_caverns.node_id.pebble_fungus
|
||||
local c_red = df_caverns.node_id.spindlestem_red
|
||||
|
||||
local c_wet_flowstone = df_caverns.node_id.wet_flowstone
|
||||
local c_dry_flowstone = df_caverns.node_id.dry_flowstone
|
||||
|
||||
local c_veinstone = df_caverns.node_id.veinstone
|
||||
local c_pearls = df_caverns.node_id.pearls
|
||||
|
||||
local chasms_path = minetest.get_modpath("chasms")
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y < df_caverns.config.level2_min or pos.y >= df_caverns.config.level1_min then
|
||||
return nil
|
||||
end
|
||||
return get_biome(heat, humidity)
|
||||
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.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, data_param2)
|
||||
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_pebble_fungus
|
||||
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, data_param2)
|
||||
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_stillworm
|
||||
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
|
||||
local vein_area
|
||||
|
||||
-- Partly fill flooded caverns and warrens
|
||||
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
|
||||
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, 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
|
||||
if log_location then log_location("level2_veinstone", area:position(vi)) end
|
||||
end
|
||||
end
|
||||
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
|
||||
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[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)
|
||||
if log_location then log_location("level2_flooded_"..biome_name, area:position(vi)) end
|
||||
elseif biome_name == "barren" then
|
||||
if flooded_caverns then
|
||||
df_caverns.wet_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level2_barren_wet", area:position(vi)) end
|
||||
else
|
||||
df_caverns.dry_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level2_barren_dry", area:position(vi)) end
|
||||
end
|
||||
elseif biome_name == "goblincap" then
|
||||
goblin_cap_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level2_goblincap", area:position(vi)) end
|
||||
elseif biome_name == "sporetree" then
|
||||
spore_tree_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level2_sporetree", area:position(vi)) end
|
||||
elseif biome_name == "tunneltube" then
|
||||
tunnel_tube_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level2_tunneltube", area:position(vi)) 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[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[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, c_gravel)
|
||||
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[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
|
||||
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
|
||||
if not flooded_caverns and (biome_name == "barren" or biome_name == "sporetree") and nvals_cracks[index2d] > 0.5 then
|
||||
for i= 1, 4 do
|
||||
if math.random() > 0.5 then
|
||||
local index = vi-i*ystride
|
||||
if data[index] == c_air then
|
||||
df_mapitems.place_against_surface_vm(c_pearls, index, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- air pockets
|
||||
local ystride = area.ystride
|
||||
local cracks = nvals_cracks[index2d]
|
||||
if cracks > 0.4 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.6 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[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if log_location then
|
||||
local flood_name = ""
|
||||
if flooded_caverns then flood_name = "_flooded" end
|
||||
log_location("level2_warren_"..biome_name..flood_name, area:position(vi))
|
||||
end
|
||||
|
||||
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, c_gravel)
|
||||
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[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
|
||||
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
|
||||
|
||||
if not flooded_caverns and (biome_name == "barren" or biome_name == "sporetree") and nvals_cracks[index2d] > 0.5 then
|
||||
for i= 1, 4 do
|
||||
if math.random() > 0.5 then
|
||||
local index = vi-i*ystride
|
||||
if data[index] == c_air then
|
||||
df_mapitems.place_against_surface_vm(c_pearls, index, area, data, data_param2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- air pockets
|
||||
local cracks = nvals_cracks[index2d]
|
||||
if cracks > 0.4 and data[vi-ystride] == c_water then
|
||||
data[vi-ystride] = c_air
|
||||
if cracks > 0.6 and data[vi-ystride*2] == c_water then
|
||||
data[vi-ystride*2] = c_air
|
||||
end
|
||||
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 dry = (biome_name == "barren") and (nvals_cave[vi] > 0)
|
||||
|
||||
if dry and data[vi] == c_wet_flowstone then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
|
||||
if chasms_path then
|
||||
local pos = area:position(vi)
|
||||
if chasms.is_in_chasm_without_taper(pos) then
|
||||
local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
if flooded_caverns and pos.y < subsea_level then
|
||||
data[vi] = c_water
|
||||
else
|
||||
data[vi] = c_air
|
||||
end
|
||||
end
|
||||
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,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,583 @@
|
||||
local c_water = df_caverns.node_id.water
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_desert_sand = df_caverns.node_id.desert_sand
|
||||
local c_stone_with_coal = df_caverns.node_id.stone_with_coal
|
||||
local c_silver_sand = df_caverns.node_id.silver_sand
|
||||
local c_snow = df_caverns.node_id.snow
|
||||
local c_ice = df_caverns.node_id.ice
|
||||
local c_hoar_moss = df_caverns.node_id.hoar_moss
|
||||
local c_gravel = df_caverns.node_id.gravel
|
||||
local c_oil = df_caverns.node_id.oil
|
||||
local c_cobble_fungus_fine = df_caverns.node_id.cobble_fungus_fine
|
||||
local c_cobble_fungus = df_caverns.node_id.cobble_fungus
|
||||
local c_cobble = df_caverns.node_id.cobble
|
||||
local c_wet_flowstone = df_caverns.node_id.wet_flowstone
|
||||
local c_dry_flowstone = df_caverns.node_id.dry_flowstone
|
||||
local c_glow_ore = df_caverns.node_id.glow_ore
|
||||
local c_salty_cobble = df_caverns.node_id.salty_cobble
|
||||
local c_salt_crystal = df_caverns.node_id.salt_crystal
|
||||
local c_sprite = df_caverns.node_id.sprite
|
||||
local c_webs_egg = df_caverns.node_id.big_webs_egg
|
||||
|
||||
local chasms_path = minetest.get_modpath("chasms")
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y < df_caverns.config.level3_min or pos.y >= df_caverns.config.level2_min then
|
||||
return nil
|
||||
end
|
||||
local biome = get_biome(heat, humidity)
|
||||
if biome == "bloodnether" then
|
||||
local cavern_value = subterrane.get_cavern_value("cavern layer 3", pos)
|
||||
if cavern_value == nil then
|
||||
-- this shouldn't happen, the pos.y check above should prevent it.
|
||||
return nil
|
||||
end
|
||||
if cavern_value < 0 then
|
||||
return "nethercap"
|
||||
end
|
||||
return "bloodthorn"
|
||||
end
|
||||
return biome
|
||||
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)
|
||||
local ai = vi+area.ystride
|
||||
|
||||
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] ~= 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
|
||||
data_param2[ai] = math.random(1,4)-1
|
||||
end
|
||||
else
|
||||
local param2 = abs_cracks*1000000 - math.floor(abs_cracks*1000000/4)*4
|
||||
local height = math.floor(abs_cracks * 66)
|
||||
subterrane.stalagmite(ai, 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(ai, area, data, data_param2)
|
||||
data[vi] = c_desert_sand
|
||||
else
|
||||
if math.random() < 0.1 then
|
||||
df_caverns.place_shrub(ai, 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, 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
|
||||
|
||||
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
|
||||
if log_location then log_location("level3_blackcap_oil", vector.new(x,y,z)) end
|
||||
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
|
||||
if log_location then log_location("level3_nethercap_floating_ice", vector.new(x,y,z)) end
|
||||
end
|
||||
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[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. Not using df_caverns.flooded_cavern_floor to make level 3 water darker
|
||||
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
|
||||
if log_location then log_location("level3_flooded_"..biome_name, area:position(vi)) 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)
|
||||
if log_location then log_location("level3_barren_dry", area:position(vi)) end
|
||||
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
|
||||
if log_location then log_location("level3_barren_wet", area:position(vi)) end
|
||||
end
|
||||
elseif biome_name == "blackcap" then
|
||||
black_cap_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level3_blackcap", area:position(vi)) end
|
||||
elseif biome_name == "bloodnether" then
|
||||
if flooded_caverns then
|
||||
nether_cap_cavern_floor(cracks, abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level3_nethercap", area:position(vi)) end
|
||||
else
|
||||
blood_thorn_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("level3_bloodthorn", area:position(vi)) end
|
||||
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[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
|
||||
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
|
||||
data[bi] = c_salt_crystal
|
||||
data_param2[bi] = 19 + math.random(1,4)
|
||||
end
|
||||
else
|
||||
df_caverns.stalactites(abs_cracks, vert_rand, vi, area, data, data_param2, false)
|
||||
end
|
||||
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[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, c_gravel)
|
||||
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 humidity = humiditymap[index2d]
|
||||
local biome_name = get_biome(heatmap[index2d], humidity)
|
||||
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
|
||||
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
|
||||
if c_webs_egg and humidity < 40 and nvals_cracks[index2d] > 0.5 and math.random() < 0.1 then
|
||||
local index = vi-ystride
|
||||
if data[index] == c_air then
|
||||
data[index] = c_webs_egg
|
||||
minetest.get_node_timer(area:position(index)):start(1)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- air pockets
|
||||
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[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
|
||||
|
||||
if log_location then
|
||||
local flood_name = ""
|
||||
if flooded_caverns then flood_name = "_flooded" end
|
||||
log_location("level3_warren_"..biome_name..flood_name, area:position(vi))
|
||||
end
|
||||
|
||||
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[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, c_gravel)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- Column material override for dry and icy biomes
|
||||
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[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({x=pos.z, y=pos.y, z=pos.x}) > 0.5 then
|
||||
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
|
||||
|
||||
if chasms_path then
|
||||
local pos = area:position(vi)
|
||||
if chasms.is_in_chasm_without_taper(pos) then
|
||||
if flooded_caverns and pos.y < subsea_level then
|
||||
data[vi] = c_water -- this puts a crack in the ice of icy biomes, but why not? A crack in the ice is interesting.
|
||||
else
|
||||
data[vi] = c_air
|
||||
end
|
||||
end
|
||||
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,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
# textdomain: df_caverns
|
||||
|
||||
|
||||
### underworld.lua ###
|
||||
|
||||
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
|
||||
A glowing pit=Eine leuchtende Grube
|
||||
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
|
||||
Ancient ruin=Alte Ruine
|
||||
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
|
||||
Mysterious seal=Geheimnisvolles Siegel
|
||||
@@ -0,0 +1,11 @@
|
||||
# textdomain: df_caverns
|
||||
|
||||
|
||||
### underworld.lua ###
|
||||
|
||||
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
|
||||
A glowing pit=Un pozzo luminoso
|
||||
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
|
||||
Ancient ruin=Antica rovina
|
||||
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
|
||||
Mysterious seal=Sigillo misterioso
|
||||
@@ -0,0 +1,8 @@
|
||||
# textdomain: df_caverns
|
||||
|
||||
|
||||
### underworld.lua ###
|
||||
|
||||
A glowing pit=
|
||||
Ancient ruin=
|
||||
Mysterious seal=
|
||||
@@ -0,0 +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 = df_dependencies, subterrane, df_trees, df_mapitems,
|
||||
optional_depends = df_farming, ice_sprites, oil, df_underworld_items, magma_conduits, bones_loot, named_waypoints, name_generator, fireflies, chasms, big_webs, mcl_flowers, mine_gas
|
||||
@@ -0,0 +1,81 @@
|
||||
df_caverns.node_id = {}
|
||||
|
||||
minetest.after(0, function() df_caverns.node_id = nil end) -- should only be used during initialization.
|
||||
|
||||
if df_dependencies.node_name_fireflies then
|
||||
df_caverns.node_id.fireflies = minetest.get_content_id(df_dependencies.node_name_fireflies)
|
||||
end
|
||||
|
||||
df_caverns.node_id.cobble = minetest.get_content_id(df_dependencies.node_name_cobble)
|
||||
df_caverns.node_id.desert_sand = minetest.get_content_id(df_dependencies.node_name_desert_sand)
|
||||
df_caverns.node_id.dirt = minetest.get_content_id(df_dependencies.node_name_dirt)
|
||||
df_caverns.node_id.gravel = minetest.get_content_id(df_dependencies.node_name_gravel)
|
||||
df_caverns.node_id.ice = minetest.get_content_id(df_dependencies.node_name_ice)
|
||||
df_caverns.node_id.lava = minetest.get_content_id(df_dependencies.node_name_lava_source)
|
||||
df_caverns.node_id.meseore = minetest.get_content_id(df_dependencies.node_name_stone_with_mese)
|
||||
df_caverns.node_id.mossycobble = minetest.get_content_id(df_dependencies.node_name_mossycobble)
|
||||
df_caverns.node_id.obsidian = minetest.get_content_id(df_dependencies.node_name_obsidian)
|
||||
df_caverns.node_id.sand = minetest.get_content_id(df_dependencies.node_name_sand)
|
||||
df_caverns.node_id.silver_sand = minetest.get_content_id(df_dependencies.node_name_silver_sand)
|
||||
df_caverns.node_id.snow = minetest.get_content_id(df_dependencies.node_name_snow)
|
||||
df_caverns.node_id.stone = minetest.get_content_id(df_dependencies.node_name_stone)
|
||||
df_caverns.node_id.stone_with_coal = minetest.get_content_id(df_dependencies.node_name_stone_with_coal)
|
||||
df_caverns.node_id.water = minetest.get_content_id(df_dependencies.node_name_water_source)
|
||||
|
||||
if minetest.get_modpath("big_webs") then
|
||||
df_caverns.node_id.big_webs = minetest.get_content_id("big_webs:webbing")
|
||||
df_caverns.node_id.big_webs_egg = minetest.get_content_id("big_webs:web_egg")
|
||||
end
|
||||
|
||||
if minetest.get_modpath("ice_sprites") then
|
||||
df_caverns.node_id.sprite = minetest.get_content_id("ice_sprites:ice_sprite")
|
||||
end
|
||||
|
||||
if minetest.get_modpath("df_farming") then
|
||||
df_caverns.node_id.dead_fungus = minetest.get_content_id("df_farming:dead_fungus")
|
||||
end
|
||||
|
||||
df_caverns.node_id.air = minetest.get_content_id("air")
|
||||
|
||||
df_caverns.node_id.cobble_fungus = minetest.get_content_id("df_mapitems:cobble_with_floor_fungus")
|
||||
df_caverns.node_id.cobble_fungus_fine = minetest.get_content_id("df_mapitems:cobble_with_floor_fungus_fine")
|
||||
df_caverns.node_id.dirt_moss = minetest.get_content_id("df_mapitems:dirt_with_cave_moss")
|
||||
df_caverns.node_id.dry_flowstone = minetest.get_content_id("df_mapitems:dry_flowstone")
|
||||
df_caverns.node_id.glow_ore = minetest.get_content_id("df_mapitems:glow_ruby_ore")
|
||||
df_caverns.node_id.hoar_moss = minetest.get_content_id("df_mapitems:ice_with_hoar_moss")
|
||||
df_caverns.node_id.mese_crystal = minetest.get_content_id("df_mapitems:mese_crystal")
|
||||
df_caverns.node_id.mese_crystal_block = minetest.get_content_id("df_mapitems:glow_mese")
|
||||
df_caverns.node_id.pearls = minetest.get_content_id("df_mapitems:cave_pearls")
|
||||
df_caverns.node_id.pebble_fungus = minetest.get_content_id("df_mapitems:dirt_with_pebble_fungus")
|
||||
df_caverns.node_id.rock_rot = minetest.get_content_id("df_mapitems:rock_rot")
|
||||
df_caverns.node_id.spongestone = minetest.get_content_id("df_mapitems:spongestone")
|
||||
df_caverns.node_id.salt_crystal = minetest.get_content_id("df_mapitems:salt_crystal")
|
||||
df_caverns.node_id.salty_cobble = minetest.get_content_id("df_mapitems:salty_cobble")
|
||||
df_caverns.node_id.sand_scum = minetest.get_content_id("df_mapitems:sand_scum")
|
||||
df_caverns.node_id.stillworm = minetest.get_content_id("df_mapitems:dirt_with_stillworm")
|
||||
df_caverns.node_id.veinstone = minetest.get_content_id("df_mapitems:veinstone")
|
||||
df_caverns.node_id.wet_flowstone = minetest.get_content_id("df_mapitems:wet_flowstone")
|
||||
|
||||
df_caverns.node_id.spindlestem_red = minetest.get_content_id("df_trees:spindlestem_cap_red")
|
||||
df_caverns.node_id.spindlestem_white = minetest.get_content_id("df_trees:spindlestem_cap_white")
|
||||
|
||||
df_caverns.node_id.amethyst = minetest.get_content_id("df_underworld_items:glow_amethyst")
|
||||
df_caverns.node_id.glowstone = minetest.get_content_id("df_underworld_items:glowstone")
|
||||
df_caverns.node_id.pit_plasma = minetest.get_content_id("df_underworld_items:pit_plasma")
|
||||
df_caverns.node_id.slade = minetest.get_content_id("df_underworld_items:slade")
|
||||
df_caverns.node_id.slade_block = minetest.get_content_id("df_underworld_items:slade_block")
|
||||
|
||||
df_caverns.node_id.oil = minetest.get_content_id("oil:oil_source")
|
||||
|
||||
df_caverns.node_id.gas = minetest.get_content_id("mine_gas:gas")
|
||||
df_caverns.node_id.gas_wisp = minetest.get_content_id("mine_gas:gas_wisp")
|
||||
|
||||
df_caverns.node_id.giant_mycelium = minetest.get_content_id("df_primordial_items:giant_hypha_apical_mapgen")
|
||||
df_caverns.node_id.ivy = minetest.get_content_id("df_primordial_items:jungle_ivy")
|
||||
df_caverns.node_id.jungle_dirt = minetest.get_content_id("df_primordial_items:dirt_with_jungle_grass")
|
||||
df_caverns.node_id.mycelial_dirt = minetest.get_content_id("df_primordial_items:dirt_with_mycelium")
|
||||
df_caverns.node_id.orb = minetest.get_content_id("df_primordial_items:glow_orb_hanging")
|
||||
df_caverns.node_id.packed_roots = minetest.get_content_id("df_primordial_items:packed_roots")
|
||||
df_caverns.node_id.plant_matter = minetest.get_content_id("df_primordial_items:plant_matter")
|
||||
df_caverns.node_id.root_1 = minetest.get_content_id("df_primordial_items:jungle_roots_1")
|
||||
df_caverns.node_id.root_2 = minetest.get_content_id("df_primordial_items:jungle_roots_2")
|
||||
@@ -0,0 +1,131 @@
|
||||
if not df_caverns.config.enable_oil_sea then
|
||||
return
|
||||
end
|
||||
|
||||
local c_oil = df_caverns.node_id.oil
|
||||
local c_gas = df_caverns.node_id.gas
|
||||
local c_gas_wisp = df_caverns.node_id.gas_wisp
|
||||
local c_lava = df_caverns.node_id.lava
|
||||
local c_obsidian = df_caverns.node_id.obsidian
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y > y_max or pos.y < y_min then
|
||||
return
|
||||
end
|
||||
return "oil_sea"
|
||||
end)
|
||||
|
||||
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
|
||||
if math.random() < 0.00025 and ((y < median + 3) or (y > ceiling_height - 3)) then
|
||||
data[vi] = c_gas_wisp
|
||||
else
|
||||
data[vi] = c_gas
|
||||
end
|
||||
else
|
||||
data[vi] = c_oil
|
||||
if log_location then log_location("oil_sea", area:position(vi)) end
|
||||
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 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({
|
||||
ore_type = "scatter",
|
||||
ore = "mine_gas:gas_seep",
|
||||
wherein = df_dependencies.node_name_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,
|
||||
})
|
||||
@@ -0,0 +1,508 @@
|
||||
if not df_caverns.config.enable_primordial or not minetest.get_modpath("df_primordial_items") then
|
||||
return
|
||||
end
|
||||
|
||||
local c_air = df_caverns.node_id.air
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
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 giant_mycelium_timer_spread = tonumber(minetest.settings:get("dcaverns_giant_mycelium_timer_spread")) or 10
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y < df_caverns.config.primordial_min or pos.y > df_caverns.config.primordial_max then
|
||||
return nil
|
||||
end
|
||||
if subterrane.get_cavern_value("primordial", pos) < 0 then
|
||||
return "primordial jungle"
|
||||
end
|
||||
return "primordial fungus"
|
||||
end)
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
-- Fungal biome
|
||||
|
||||
local c_orb = df_caverns.node_id.orb
|
||||
local c_mycelial_dirt = df_caverns.node_id.mycelial_dirt
|
||||
local c_dirt = df_caverns.node_id.dirt
|
||||
local c_giant_mycelium = df_caverns.node_id.giant_mycelium
|
||||
|
||||
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 = df_caverns.node_id.jungle_dirt
|
||||
local c_plant_matter = df_caverns.node_id.plant_matter
|
||||
local c_packed_roots = df_caverns.node_id.packed_roots
|
||||
local c_glowstone = df_caverns.node_id.glowstone
|
||||
local c_ivy = df_caverns.node_id.ivy
|
||||
local c_root_2 = df_caverns.node_id.root_2
|
||||
local c_root_1 = df_caverns.node_id.root_1
|
||||
local c_fireflies = df_caverns.node_id.fireflies
|
||||
|
||||
local jungle_cavern_floor = function(abs_cracks, humidity, vi, area, data, data_param2)
|
||||
local ystride = area.ystride
|
||||
local humidityfactor = humidity/100
|
||||
|
||||
if log_location then
|
||||
local pos = area:position(vi)
|
||||
log_location("primordial_jungle", pos)
|
||||
if humidityfactor < 0.25 then
|
||||
log_location("primordial_jungle_low_humidity", pos)
|
||||
elseif humidityfactor > 0.75 then
|
||||
log_location("primordial_jungle_high_humidity", pos)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
minetest.get_node_timer(area:position(firefly_vi)):start(1)
|
||||
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
|
||||
minetest.get_node_timer(area:position(firefly_vi)):start(1)
|
||||
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)
|
||||
if log_location then log_location("primordial_mushrooms", area:position(vi)) 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 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)
|
||||
if log_location then log_location("primordial_jungle_warren", area:position(vi)) end
|
||||
else
|
||||
mushroom_warren_floor(abs_cracks, vi, area, data, data_param2)
|
||||
if log_location then log_location("primordial_mushroom_warren", area:position(vi)) end
|
||||
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 = df_dependencies.node_name_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,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "vein",
|
||||
ore = "df_underworld_items:glowstone",
|
||||
wherein = {
|
||||
"default:stone",
|
||||
"default:stone_with_coal",
|
||||
"default:stone_with_iron",
|
||||
"default:stone_with_copper",
|
||||
"default:stone_with_tin",
|
||||
"default:stone_with_gold",
|
||||
"default:stone_with_diamond",
|
||||
"default:dirt",
|
||||
"default:sand",
|
||||
"default:desert_sand",
|
||||
"default:silver_sand",
|
||||
"default:gravel",
|
||||
},
|
||||
column_height_min = 2,
|
||||
column_height_max = 6,
|
||||
y_min = df_caverns.config.primordial_min,
|
||||
y_max = df_caverns.config.primordial_max,
|
||||
noise_threshold = 0.9,
|
||||
noise_params = {
|
||||
offset = 0,
|
||||
scale = 3,
|
||||
spread = {x=400, y=400, z=400},
|
||||
seed = 25111,
|
||||
octaves = 4,
|
||||
persist = 0.5,
|
||||
flags = "eased",
|
||||
},
|
||||
random_factor = 0,
|
||||
})
|
||||
|
||||
-- Rather than make plants farmable, have them randomly respawn in jungle soil. You can only get them down there by foraging, not farming.
|
||||
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,
|
||||
})
|
||||
|
||||
-- an ABM to extinguish fires on the primordial layer. Glowstone next to plant life equals too much fire.
|
||||
local fire_enabled = minetest.settings:get_bool("enable_fire")
|
||||
if fire_enabled == nil then
|
||||
-- enable_fire setting not specified, check for disable_fire
|
||||
local fire_disabled = minetest.settings:get_bool("disable_fire")
|
||||
if fire_disabled == nil then
|
||||
-- Neither setting specified, check whether singleplayer
|
||||
fire_enabled = minetest.is_singleplayer()
|
||||
else
|
||||
fire_enabled = not fire_disabled
|
||||
end
|
||||
end
|
||||
if fire_enabled and minetest.get_modpath("fire") then
|
||||
local primordial_min = df_caverns.config.primordial_min
|
||||
local primordial_max = df_caverns.config.primordial_max
|
||||
minetest.register_abm({
|
||||
label = "Remove fire in the primordial layer",
|
||||
nodenames = {"fire:basic_flame"},
|
||||
--neighbors = {"fire:basic_flame"},
|
||||
interval = 3,
|
||||
chance = 3,
|
||||
catch_up = false,
|
||||
action = function(pos)
|
||||
local pos_y = pos.y
|
||||
if pos_y > primordial_min and pos_y < primordial_max then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
local n1 = { name = "df_underworld_items:slade_block", force_place=true }
|
||||
local n2 = { name = df_dependencies.node_name_stair_outer_slade_brick, param2 = 1, force_place=true }
|
||||
local n3 = { name = df_dependencies.node_name_stair_slade_brick, force_place=true }
|
||||
local n4 = { name = df_dependencies.node_name_stair_outer_slade_brick, force_place=true }
|
||||
local n5 = { name = "air", force_place=true }
|
||||
local n6 = { name = "df_underworld_items:slade_seal", force_place=true }
|
||||
local n7 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 1, force_place=true }
|
||||
local n8 = { name = "df_underworld_items:slade_brick", force_place=true }
|
||||
local n9 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 3, force_place=true }
|
||||
local n10 = { name = "df_underworld_items:slade_wall", force_place=true }
|
||||
local n11 = { name = "df_underworld_items:ancient_lantern_slade_worn", prob=192 } -- 50% chance of being force-placed
|
||||
local n12 = { name = df_dependencies.node_name_stair_outer_slade_brick, param2 = 2, force_place=true }
|
||||
local n13 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 2, force_place=true }
|
||||
local n14 = { name = df_dependencies.node_name_stair_outer_slade_brick, 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, n11, 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,
|
||||
n11, n10, n11,
|
||||
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, n11, n5,
|
||||
n5, n5, n5,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
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 = df_dependencies.node_name_stair_outer_slade_brick, param2 = 1, force_place=true }
|
||||
local n6 = { name = df_dependencies.node_name_stair_slade_brick, force_place=true }
|
||||
local n7 = { name = df_dependencies.node_name_stair_outer_slade_brick, force_place=true }
|
||||
local n9 = { name = df_dependencies.node_name_slab_slade_brick, param2 = 23, force_place=true }
|
||||
local n10 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 1, force_place=true }
|
||||
local n11 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 3, force_place=true }
|
||||
local n14 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 23, force_place=true }
|
||||
local n15 = { name = df_dependencies.node_name_stair_outer_slade_brick, param2 = 2, force_place=true }
|
||||
local n16 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 2, force_place=true }
|
||||
local n17 = { name = df_dependencies.node_name_stair_outer_slade_brick, 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 = df_dependencies.node_name_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,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
local n1 = { name = "df_underworld_items:slade_block", force_place=true }
|
||||
local n2 = { name = df_dependencies.node_name_stair_outer_slade_brick, param2 = 1, force_place=true }
|
||||
local n3 = { name = df_dependencies.node_name_stair_slade_brick, force_place=true }
|
||||
local n4 = { name = df_dependencies.node_name_stair_outer_slade_brick, force_place=true }
|
||||
local n5 = { name = "air", force_place=true }
|
||||
local n6 = { name = "df_underworld_items:slade_seal", force_place=true }
|
||||
local n7 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 1, force_place=true }
|
||||
local n8 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 3, force_place=true }
|
||||
local n9 = { name = df_dependencies.node_name_stair_outer_slade_brick, param2 = 2, force_place=true }
|
||||
local n10 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 2, force_place=true }
|
||||
local n11 = { name = df_dependencies.node_name_stair_outer_slade_brick, 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,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
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 = df_dependencies.node_name_stair_outer_slade_brick, param2 = 1, force_place=true }
|
||||
local n6 = { name = df_dependencies.node_name_stair_slade_brick, force_place=true }
|
||||
local n7 = { name = df_dependencies.node_name_stair_outer_slade_brick, force_place=true }
|
||||
local n11 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 1, force_place=true }
|
||||
local n12 = { name = df_dependencies.node_name_slab_slade_brick, param2 = 22, force_place=true}
|
||||
local n13 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 3, force_place=true }
|
||||
local n15 = { name = df_dependencies.node_name_stair_outer_slade_brick, param2 = 2, force_place=true }
|
||||
local n16 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 2, force_place=true }
|
||||
local n17 = { name = df_dependencies.node_name_stair_outer_slade_brick, 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 = df_dependencies.node_name_stair_slade_brick, param2 = 2, force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n9 = { name = df_dependencies.node_name_stair_slade_brick, force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n14 = { name = df_dependencies.node_name_stair_slade_brick, param2 = 1, force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
|
||||
|
||||
local n18 = { name = "df_underworld_items:puzzle_chest_closed", param2 = 1, prob=192 } -- 50% chance of being force-placed.
|
||||
|
||||
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, n18, 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,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
local n1 = { name = "df_underworld_items:slade_brick", force_place=false, place_on_condition=mapgen_helper.buildable_to }
|
||||
local n2 = { name = df_dependencies.node_name_stair_inner_slade_brick, param2 = 1, force_place=true }
|
||||
local n3 = { name = df_dependencies.node_name_stair_inner_slade_brick, force_place=true }
|
||||
local n4 = { name = "df_underworld_items:slade_brick", force_place=true }
|
||||
local n5 = { name = df_dependencies.node_name_stair_inner_slade_brick, param2 = 2, force_place=true }
|
||||
local n6 = { name = df_dependencies.node_name_stair_inner_slade_brick, 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,
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,296 @@
|
||||
-- This file contains code that is used by multiple different cavern layers.
|
||||
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_cobble = df_caverns.node_id.cobble
|
||||
local c_cobble_fungus = df_caverns.node_id.cobble_fungus
|
||||
local c_cobble_fungus_fine = df_caverns.node_id.cobble_fungus_fine
|
||||
local c_dead_fungus = df_caverns.node_id.dead_fungus
|
||||
local c_dirt = df_caverns.node_id.dirt
|
||||
local c_dirt_moss = df_caverns.node_id.dirt_moss
|
||||
local c_dry_flowstone = df_caverns.node_id.dry_flowstone
|
||||
local c_fireflies = df_caverns.node_id.fireflies
|
||||
local c_glowstone = df_caverns.node_id.glowstone
|
||||
local c_ice = df_caverns.node_id.ice
|
||||
local c_mossycobble = df_caverns.node_id.mossycobble
|
||||
local c_oil = df_caverns.node_id.oil
|
||||
local c_sand_scum = df_caverns.node_id.sand_scum
|
||||
local c_spongestone = df_caverns.node_id.spongestone
|
||||
local c_rock_rot = df_caverns.node_id.rock_rot
|
||||
local c_water = df_caverns.node_id.water
|
||||
local c_wet_flowstone = df_caverns.node_id.wet_flowstone
|
||||
local c_webs = df_caverns.node_id.big_webs
|
||||
local c_webs_egg = df_caverns.node_id.big_webs_egg
|
||||
|
||||
df_caverns.data_param2 = {} -- shared among all mapgens to reduce memory clutter
|
||||
|
||||
local get_biome_at_pos_list = {} -- a list of methods of the form function(pos, heat, humidity) to allow modpack-wide queries about what should grow where
|
||||
df_caverns.register_biome_check = function(func)
|
||||
table.insert(get_biome_at_pos_list, func)
|
||||
end
|
||||
df_caverns.get_biome = function(pos)
|
||||
pos = vector.round(pos)
|
||||
local heat = minetest.get_heat(pos)
|
||||
local humidity = minetest.get_humidity(pos)
|
||||
for _, val in pairs(get_biome_at_pos_list) do
|
||||
local biome = val(pos, heat, humidity)
|
||||
if biome ~= nil then
|
||||
return biome
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- for testing
|
||||
--local debug_timer = 0
|
||||
--minetest.register_globalstep(function(dtime)
|
||||
-- debug_timer = debug_timer + dtime
|
||||
-- if debug_timer > 5 then
|
||||
-- local singleplayer = minetest.get_player_by_name("singleplayer")
|
||||
-- if singleplayer then
|
||||
-- minetest.debug(df_caverns.get_biome(singleplayer:get_pos()))
|
||||
-- end
|
||||
-- debug_timer = debug_timer - 5
|
||||
-- end
|
||||
--end)
|
||||
|
||||
-- prevent mapgen from using these nodes as a base for stalactites or stalagmites
|
||||
local dont_build_speleothems_on = {}
|
||||
for _, content_id in pairs(df_mapitems.wet_stalagmite_ids) do
|
||||
dont_build_speleothems_on[content_id] = true
|
||||
end
|
||||
for _, content_id in pairs(df_mapitems.dry_stalagmite_ids) do
|
||||
dont_build_speleothems_on[content_id] = true
|
||||
end
|
||||
if minetest.get_modpath("big_webs") then
|
||||
dont_build_speleothems_on[c_webs] = true
|
||||
dont_build_speleothems_on[c_webs_egg] = true
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
|
||||
df_caverns.stalagmites = function(abs_cracks, vert_rand, vi, area, data, data_param2, wet, reverse_sign)
|
||||
if dont_build_speleothems_on[data[vi]] then
|
||||
return
|
||||
end
|
||||
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_sand_scum
|
||||
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
|
||||
|
||||
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
|
||||
elseif abs_cracks < 0.8 then
|
||||
data[vi] = c_rock_rot
|
||||
else
|
||||
data[vi] = c_spongestone
|
||||
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
|
||||
|
||||
df_caverns.tunnel_floor = function(minp, maxp, area, vi, nvals_cracks, data, data_param2, wet, dirt_node)
|
||||
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]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
|
||||
if wet then
|
||||
if abs_cracks < 0.05 and data[vi+ystride] == c_air and not dont_build_speleothems_on[data[vi]] 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
|
||||
elseif dirt_node and abs_cracks > 0.5 and data[vi-ystride] ~= c_air then
|
||||
data[vi] = dirt_node
|
||||
end
|
||||
else
|
||||
if abs_cracks < 0.025 and data[vi+ystride] == c_air and not dont_build_speleothems_on[data[vi]] 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 dirt_node and cracks > 0.5 and data[vi-ystride] ~= c_air then
|
||||
data[vi] = dirt_node
|
||||
end
|
||||
end
|
||||
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]
|
||||
local abs_cracks = math.abs(cracks)
|
||||
|
||||
if wet then
|
||||
if abs_cracks < 0.05 and data[vi-ystride] == c_air and not dont_build_speleothems_on[data[vi]] 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 dont_build_speleothems_on[data[vi]] 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
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
-- 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[c_ice] = true -- needed for nethercap cavern water covering
|
||||
dfcaverns_nodes[c_oil] = true -- needed for blackcap oil slicks
|
||||
if c_fireflies then
|
||||
dfcaverns_nodes[c_fireflies] = true -- used in the primordial caverns
|
||||
end
|
||||
dfcaverns_nodes[c_glowstone] = nil
|
||||
dfcaverns_mods = nil
|
||||
return not dfcaverns_nodes[c_node]
|
||||
end
|
||||
@@ -0,0 +1,454 @@
|
||||
local c_water = df_caverns.node_id.water
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_dirt = df_caverns.node_id.dirt
|
||||
local c_dirt_moss = df_caverns.node_id.dirt_moss
|
||||
local c_sand = df_caverns.node_id.sand
|
||||
local c_gravel = df_caverns.node_id.gravel
|
||||
local c_wet_flowstone = df_caverns.node_id.wet_flowstone
|
||||
local c_dry_flowstone = df_caverns.node_id.dry_flowstone
|
||||
local c_lava = df_caverns.node_id.lava
|
||||
local c_obsidian = df_caverns.node_id.obsidian
|
||||
|
||||
local chasms_path = minetest.get_modpath("chasms")
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
end
|
||||
|
||||
local c_coral_table = {}
|
||||
for node_name, node_def in pairs(minetest.registered_nodes) do
|
||||
if minetest.get_item_group(node_name, "dfcaverns_cave_coral") > 0 then
|
||||
table.insert(c_coral_table, minetest.get_content_id(node_name))
|
||||
end
|
||||
end
|
||||
|
||||
local towergoblin_shrublist
|
||||
local fungispore_shrublist
|
||||
|
||||
if minetest.get_modpath("df_farming") then
|
||||
towergoblin_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
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y < df_caverns.config.sunless_sea_min or pos.y >= df_caverns.config.level3_min then
|
||||
return nil
|
||||
end
|
||||
if pos.y < sea_level then
|
||||
return "sunless undersea"
|
||||
elseif heat > hot_zone_boundary then
|
||||
return "barren" -- hot zone
|
||||
elseif heat > middle_zone_boundary then
|
||||
return "fungispore"
|
||||
elseif heat > cool_zone_boundary then
|
||||
return "towergoblin"
|
||||
else
|
||||
return "barren" -- cool zone
|
||||
end
|
||||
end)
|
||||
|
||||
local towergoblin_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, towergoblin_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, data_param2)
|
||||
elseif math.random() < 0.02 then
|
||||
df_trees.spawn_spindlestem_vm(vi+ystride, area, data, data_param2)
|
||||
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, data_param2)
|
||||
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
|
||||
if log_location then log_location("sunless_sea_river", vector.new(x,y,z)) end
|
||||
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
|
||||
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
|
||||
|
||||
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)
|
||||
if log_location then log_location("sunless_sea_hot", area:position(vi)) end
|
||||
elseif heat > middle_zone_boundary then
|
||||
fungispore_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("sunless_sea_fungispore", area:position(vi)) end
|
||||
elseif heat > cool_zone_boundary then
|
||||
towergoblin_cavern_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("sunless_sea_towergoblin", area:position(vi)) end
|
||||
else
|
||||
cool_zone_floor(abs_cracks, vert_rand, vi, area, data, data_param2)
|
||||
if log_location then log_location("sunless_sea_cool", area:position(vi)) end
|
||||
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_castle_coral(area, data, vi+area.ystride, iterations)
|
||||
if log_location then log_location("sunless_sea_castle_coral", area:position(vi)) end
|
||||
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)
|
||||
if log_location then log_location("sunless_sea_warren", area:position(vi)) end
|
||||
end
|
||||
end
|
||||
|
||||
-- columns
|
||||
for _, vi in ipairs(node_arrays.column_nodes) do
|
||||
if data[vi] == c_wet_flowstone then
|
||||
if area:get_y(vi) > sea_level then
|
||||
local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
|
||||
local heat = heatmap[index2d]
|
||||
if heat > hot_zone_boundary then
|
||||
data[vi] = c_dry_flowstone
|
||||
end
|
||||
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
|
||||
|
||||
if chasms_path then
|
||||
local pos = area:position(vi)
|
||||
if chasms.is_in_chasm(pos) then
|
||||
if pos.y <= sea_level then
|
||||
data[vi] = c_water
|
||||
else
|
||||
data[vi] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
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,
|
||||
is_ground_content = df_caverns.is_ground_content,
|
||||
})
|
||||
@@ -0,0 +1,87 @@
|
||||
-- surface tunnels
|
||||
|
||||
local y_max = 200
|
||||
local y_min = df_caverns.config.ymax
|
||||
|
||||
local c_stone = df_caverns.node_id.stone
|
||||
local c_air = df_caverns.node_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
|
||||
return
|
||||
end
|
||||
|
||||
local t_start = os.clock()
|
||||
|
||||
local vm, data, data_param2, area = mapgen_helper.mapgen_vm_data_param2()
|
||||
local data_changed = false
|
||||
|
||||
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_y = eminp.y-1
|
||||
|
||||
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
|
||||
-- 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
|
||||
|
||||
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
|
||||
data_changed = true
|
||||
df_caverns.tunnel_floor(minp, maxp, area, previous_potential_floor_vi, nvals_cracks, data, data_param2, humidity > 30)
|
||||
end
|
||||
if y <= maxp_y and y >= minp_y then
|
||||
data_changed = true
|
||||
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, humidity > 30)
|
||||
end
|
||||
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
|
||||
|
||||
if data_changed then
|
||||
--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()
|
||||
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)
|
||||
@@ -0,0 +1,628 @@
|
||||
if not df_caverns.config.enable_underworld or not minetest.get_modpath("df_underworld_items") then
|
||||
return
|
||||
end
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local bones_loot_path = minetest.get_modpath("bones_loot")
|
||||
local bones_node = df_dependencies.node_name_bones
|
||||
local named_waypoints_path = minetest.get_modpath("named_waypoints")
|
||||
local name_generator_path = minetest.get_modpath("name_generator")
|
||||
|
||||
local hunters_enabled = minetest.get_modpath("hunter_statue") and df_underworld_items.config.underworld_hunter_statues
|
||||
|
||||
local log_location
|
||||
if mapgen_helper.log_location_enabled then
|
||||
log_location = mapgen_helper.log_first_location
|
||||
end
|
||||
|
||||
-- Exposed as a global so that other mods can override it.
|
||||
df_caverns.populate_puzzle_chest = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
for i = 1, math.random(1,8) do
|
||||
local item = ItemStack(df_underworld_items.colour_items[math.random(1,#df_underworld_items.colour_items)])
|
||||
--item:set_count(math.random(1,4))
|
||||
inv:add_item("main", item)
|
||||
end
|
||||
end
|
||||
|
||||
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 name_generator_path then
|
||||
name_generator.parse_lines(io.lines(modpath.."/underworld_names.cfg"))
|
||||
|
||||
name_pit = function()
|
||||
return name_generator.generate("glowing_pits")
|
||||
end
|
||||
name_ruin = function()
|
||||
return name_generator.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 = df_caverns.node_id.slade
|
||||
local c_slade_block = df_caverns.node_id.slade_block
|
||||
local c_air = df_caverns.node_id.air
|
||||
local c_water = df_caverns.node_id.water
|
||||
|
||||
local c_glowstone = df_caverns.node_id.glowstone
|
||||
local c_amethyst = df_caverns.node_id.amethyst
|
||||
local c_pit_plasma = df_caverns.node_id.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
|
||||
|
||||
--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
|
||||
|
||||
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)
|
||||
local ret = math.random()
|
||||
math.randomseed(next_seed)
|
||||
return ret
|
||||
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.floor(math.random() * bordered_scale + min_xz.x + border_width)
|
||||
point.y = 0
|
||||
point.z = math.floor(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")) % 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^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)
|
||||
math.randomseed(next_seed)
|
||||
return {location = location, radius = radius, variance = variance, depth = depth}
|
||||
end
|
||||
|
||||
df_caverns.get_nearest_glowing_pit = get_pit
|
||||
|
||||
local perlin_pit = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=30, y=30, z=30},
|
||||
seed = 901,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
|
||||
-------------------------------------
|
||||
|
||||
minetest.register_chatcommand("find_pit", {
|
||||
params = "",
|
||||
privs = {server=true},
|
||||
decription = "find a nearby glowing pit",
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pit = get_pit(player:get_pos())
|
||||
if pit then
|
||||
minetest.chat_send_player(name, "Pit location: x=" .. math.floor(pit.location.x) .. " z=" .. math.floor(pit.location.z))
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
df_caverns.register_biome_check(function(pos, heat, humidity)
|
||||
if pos.y > y_max or pos.y < y_min then
|
||||
return
|
||||
end
|
||||
return "underworld"
|
||||
end)
|
||||
|
||||
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)
|
||||
|
||||
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 == 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
|
||||
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)
|
||||
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 -2.5 then
|
||||
if y < median + floor_displace + wave - pit.depth or y < underside_height + plasma_depth_min then
|
||||
data[vi] = c_pit_plasma
|
||||
if log_location then log_location("underworld_pit", vector.new(x,y,z)) end
|
||||
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 >= 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
|
||||
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)
|
||||
local lamp_pos = vector.new(building.pos.x, building.pos.y+6, building.pos.z)
|
||||
minetest.after(math.random()*10, function()
|
||||
-- not all of these locations will get a lamp, but it's easier to just set four
|
||||
-- timers than to worry about testing first.
|
||||
minetest.get_node_timer({x=lamp_pos.x+1, y=lamp_pos.y, z=lamp_pos.z}):start(math.random()*30)
|
||||
minetest.get_node_timer({x=lamp_pos.x-1, y=lamp_pos.y, z=lamp_pos.z}):start(math.random()*30)
|
||||
minetest.get_node_timer({x=lamp_pos.x, y=lamp_pos.y, z=lamp_pos.z+1}):start(math.random()*30)
|
||||
minetest.get_node_timer({x=lamp_pos.x, y=lamp_pos.y, z=lamp_pos.z-1}):start(math.random()*30)
|
||||
end)
|
||||
elseif building.building_type == "small building" then
|
||||
mapgen_helper.place_schematic_on_data(data, data_param2, area, building.pos, small_building_schematic, building.rotation)
|
||||
local pos = building.pos
|
||||
minetest.after(1, function()
|
||||
local puzzle_chest = minetest.find_node_near(pos, 4, {"df_underworld_items:puzzle_chest_closed"}, true)
|
||||
if puzzle_chest then
|
||||
local def = minetest.registered_nodes["df_underworld_items:puzzle_chest_closed"]
|
||||
def.can_dig(puzzle_chest) -- initializes the inventory
|
||||
df_caverns.populate_puzzle_chest(puzzle_chest)
|
||||
end
|
||||
end)
|
||||
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 name_generator_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
|
||||
if log_location then log_location("underworld_building", building.pos) 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
|
||||
minetest.log("error", "unrecognized underworld building type: " .. tostring(building.building_type))
|
||||
end
|
||||
end
|
||||
end
|
||||
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))
|
||||
if log_location then log_location("underworld_puzzle_seal", puzzle_seal) 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()
|
||||
|
||||
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)
|
||||
local z = math.random(minp.z, maxp.z)
|
||||
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)-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])
|
||||
if math.random() < zone/2 then -- bones are more common in the built-up areas
|
||||
local floor_node = minetest.get_node({x=x, y=floor_height, z=z})
|
||||
local floor_node_def = minetest.registered_nodes[floor_node.name]
|
||||
if floor_node_def and not floor_node_def.buildable_to then
|
||||
local y = floor_height + 1
|
||||
while y < ceiling_height do
|
||||
local target_pos = {x=x, y=y, z=z}
|
||||
local target_node = minetest.get_node(target_pos)
|
||||
if target_node.name == "air" then
|
||||
bones_loot.place_bones(target_pos, "underworld_warrior", math.random(3, 10), nil, true)
|
||||
break
|
||||
elseif target_node.name == bones_node then
|
||||
-- don't stack bones on bones, it looks silly
|
||||
break
|
||||
end
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if hunters_enabled then
|
||||
local x = math.random(minp.x, maxp.x)
|
||||
local z = math.random(minp.z, maxp.z)
|
||||
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)-1
|
||||
local zone = math.abs(nvals_zone[index2d])
|
||||
if math.random() < zone / 4 then -- hunters are more common in the built-up areas. zone/4 gives ~ 400 hunters per square kilometer.
|
||||
for y = floor_height, floor_height+20 do
|
||||
local target_pos = {x=x, y=y, z=z}
|
||||
local target_node = minetest.get_node(target_pos)
|
||||
if minetest.get_item_group(target_node.name, "slade") == 0 then
|
||||
minetest.set_node(target_pos, {name="df_underworld_items:hunter_statue"})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
@@ -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"
|
||||
}
|
||||