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