16 Commits

Author SHA1 Message Date
cf17a2cc93 allow anchoring against unloaded blocks 2021-03-28 15:10:34 -06:00
bc691e95c1 final touch-ups before merging 2021-03-28 15:02:05 -06:00
2f4ceaa096 add chasms to the guide 2021-03-28 13:28:31 -06:00
33c191fc03 make webs slightly more prevalent 2021-03-28 13:01:50 -06:00
fd392311d6 make webs snappy 2021-03-28 02:58:32 -06:00
126efd8a67 fix up tunnel webs 2021-03-28 01:55:56 -06:00
0c5d49ffd5 add webs to level 3 tunnels, fix sunless sea chasms 2021-03-27 18:33:13 -06:00
293f0c5092 fix web generator 2021-03-27 15:33:28 -06:00
e17cb0823d reverse the dependencies for df_caverns and chasms, let chasms go first. 2021-03-27 15:25:54 -06:00
c6f26e5bec add rare big webs to the chasms, to give them a unique feature 2021-03-27 03:51:58 -06:00
d2b5443a25 ensure dfcaverns get carved before chasms
this has an unfortunate tradeoff. Chasms will no longer have floating giant columns in them, but will also no longer have smaller stalactites and stalagmites. Also will carve chasms through lake water. Not sure if this is ideal.
2021-03-27 01:21:19 -06:00
6f82e017f4 make veinstone punchable instead of right-clickable 2021-03-26 21:37:00 -06:00
417ab233ac overgenerate caverns to eliminate floating stalactites 2021-03-26 21:27:33 -06:00
a9dfec969b prevent chasms from breaching oil and magma seas, make veinstone actually do something 2021-03-25 23:13:19 -06:00
ed54ceec93 tweak default chasm settings 2021-03-24 22:37:51 -06:00
eb2fbf0d99 initial chasms mod 2021-03-22 23:33:05 -06:00
13 changed files with 11 additions and 314 deletions

View File

@ -5,7 +5,7 @@ Sounds and textures are under various licenses, see the license.txt file in the
License for Code License for Code
---------------- ----------------
Copyright (C) 2021 FaceDeer Copyright (C) 2018 FaceDeer
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -79,7 +79,6 @@ end
local web_line = function(pos, dir, distance) local web_line = function(pos, dir, distance)
local anchored
local web_spine = {} local web_spine = {}
for i = 0, distance do for i = 0, distance do
local web_pos = vector.add(pos, vector.multiply(dir,i)) local web_pos = vector.add(pos, vector.multiply(dir,i))

View File

@ -2,17 +2,6 @@ local data = {}
chasms = {} chasms = {}
local ignore = {}
-- Use this to set node types to be left alone by chasm-carving
chasms.register_ignore = function(node_name)
ignore[minetest.get_content_id(node_name)] = true
end
chasms.ignore_content_id = function(content_id)
return ignore[content_id]
end
local maxy = tonumber(minetest.settings:get("chasms_maxy")) or -50 local maxy = tonumber(minetest.settings:get("chasms_maxy")) or -50
local miny = tonumber(minetest.settings:get("chasms_miny")) or -2500 local miny = tonumber(minetest.settings:get("chasms_miny")) or -2500
local falloff = tonumber(minetest.settings:get("chasms_falloff")) or 100 local falloff = tonumber(minetest.settings:get("chasms_falloff")) or 100
@ -140,18 +129,16 @@ minetest.register_on_generated(function(minp, maxp, seed)
local waver = math.min(math.max(math.floor(waver_data[i]+0.5), -waver_strength), waver_strength) local waver = math.min(math.max(math.floor(waver_data[i]+0.5), -waver_strength), waver_strength)
local intensity = get_intensity(y) local intensity = get_intensity(y)
if chasm_data[chasm_area:index(x+waver, y, z)]*intensity > chasms_threshold then if chasm_data[chasm_area:index(x+waver, y, z)]*intensity > chasms_threshold then
if not ignore[data[i]] then if webs_present then
if webs_present then webs = webs or calculate_web_array(minp, maxp) -- only calculate webs when we know we're in a chasm
webs = webs or calculate_web_array(minp, maxp) -- only calculate webs when we know we're in a chasm if webs[y + z*z_displace] and math.random() < 0.85 then -- random holes in the web
if webs[y + z*z_displace] and math.random() < 0.85 then -- random holes in the web data[i] = c_web
data[i] = c_web minetest.get_node_timer({x=x,y=y,z=z}):start(1) -- this timer will check for unsupported webs
minetest.get_node_timer({x=x,y=y,z=z}):start(1) -- this timer will check for unsupported webs
else
data[i] = c_air
end
else else
data[i] = c_air data[i] = c_air
end end
else
data[i] = c_air
end end
end end
end end

View File

@ -356,8 +356,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do for _, vi in ipairs(node_arrays.tunnel_ceiling_nodes) do
local index2d = mapgen_helper.index2di(minp, maxp, area, vi) local index2d = mapgen_helper.index2di(minp, maxp, area, vi)
local humidity = humiditymap[index2d] local biome_name = get_biome(heatmap[index2d], humiditymap[index2d])
local biome_name = get_biome(heatmap[index2d], humidity)
local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not. local flooded_caverns = nvals_cave[vi] < 0 -- this indicates if we're in the "flooded" set of caves or not.
local ystride = area.ystride local ystride = area.ystride
@ -368,7 +367,7 @@ local decorate_level_3 = function(minp, maxp, seed, vm, node_arrays, area, data)
else else
df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false) df_caverns.tunnel_ceiling(minp, maxp, area, vi, nvals_cracks, data, data_param2, false)
end end
if c_webs_egg and humidity < 40 and nvals_cracks[index2d] > 0.5 and math.random() < 0.1 then if c_webs_egg and (biome_name == "barren" or biome_name == "blackcap") and nvals_cracks[index2d] > 0.5 and math.random() < 0.1 then
local index = vi-ystride local index = vi-ystride
if data[index] == c_air then if data[index] == c_air then
data[index] = c_webs_egg data[index] = c_webs_egg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

View File

@ -168,12 +168,6 @@ Not all vast open spaces underground are the result of aeons of erosion by water
The great extent of chasms makes them hospitable to small flying creatures, and their narrowness makes the hospitable to creatures that feed on them - giant cave spider webs can be found strung across them here and there. A dubious salvation for anyone falling from above. The great extent of chasms makes them hospitable to small flying creatures, and their narrowness makes the hospitable to creatures that feed on them - giant cave spider webs can be found strung across them here and there. A dubious salvation for anyone falling from above.
# Pit caves
![Looking up from the bottom of a pit](./df_caverns/screenshots/pit_cave.jpg)
A pit cave is a type of cave which contains one or more significant vertical shafts rather than being predominantly a conventional horizontal cave passage. Pit caves typically form in limestone as a result of long-term erosion by water. Given the vast scope of the flowstone formations found throughout the upper layers of the world's caverns, correspondingly gigantic pits can also be found. They sometimes breach the surface of the world, and at their greatest extent can have a drop over two kilometers deep. Bring plenty of rope when exploring such abysses.
# Sunless Sea # Sunless Sea
![Sunless river](./df_caverns/screenshots/sunless_river.jpg) ![Sunless river](./df_caverns/screenshots/sunless_river.jpg)

View File

@ -1,22 +0,0 @@
License for Code
----------------
Copyright (C) 2021 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.

View File

@ -1,18 +0,0 @@
A pit cave, shaft cave or vertical cave—or often simply called a pit (in the US) or pot (in the UK); jama in South Slavic languages scientific and colloquial vocabulary (borrowed since early research in the Western Balkan Dinaric Alpine karst)—is a type of cave which contains one or more significant vertical shafts rather than being predominantly a conventional horizontal cave passage. Pit caves typically form in limestone as a result of long-term erosion by water.
In the real world, the deepest known vertical drop in a cave is 603m in Vrtoglavica Cave in Slovenia. This mod adds pits of varying depth, with some under the default settings being up to 2500m deep. They are widely scattered and not all of them breach the surface, so they are a rare find, but with the right tools a pit cave can give access to a huge swath of underground terrain.
## Settings and commands
The following settings are available for configuring pit cave generation:
pit_caves_min_bottom (Lower limit of bottoms of pits) int -2500
pit_caves_max_bottom (Upper limit of bottoms of pits) int -500
pit_caves_min_top (Lower limit of tops of pits) int -100
pit_caves_max_top (Upper limit of tops of pits) int 100
pit_caves_mapblock_spacing (Average number of map blocks between pits) int 16
pit_caves_seal_ocean (Seal off pits that are under ocean water) bool true
The pit_caves_seal_ocean setting isn't perfect, some map generation scenarios can result in a gap through which water can flow. But it's better than having drain holes everywhere.
Users with the "server" privilege can use the ``/find_pit_caves`` command, which will list the locations of nearby pit caves.

View File

@ -1,221 +0,0 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
local S = minetest.get_translator(minetest.get_current_modname())
local min_depth = tonumber(minetest.settings:get("pit_caves_min_bottom") or -2500)
local max_depth = tonumber(minetest.settings:get("pit_caves_max_bottom") or -500)
local min_top = tonumber(minetest.settings:get("pit_caves_min_top") or -100)
local max_top = tonumber(minetest.settings:get("pit_caves_max_top") or 100)
local seal_ocean = minetest.settings:get_bool("pit_caves_seal_ocean", true)
assert(min_depth < max_depth, "pit_caves_min_bottom is above pit_caves_max_bottom")
assert(min_top < max_top, "pit_caves_min_top is above pit_caves_max_top")
assert(max_depth < min_top, "pit_caves_max_bottom is above pit_caves_min_top")
local pit_radius = 3 -- approximate minimum radius of pit - noise adds a lot to this
local region_mapblocks = tonumber(minetest.settings:get("pit_caves_mapblock_spacing") or 16)
local mapgen_chunksize = tonumber(minetest.get_mapgen_setting("chunksize"))
local pit_region_size = region_mapblocks * mapgen_chunksize * 16
local c_air = minetest.get_content_id("air")
local c_gravel = c_air
local water_node
if minetest.get_modpath("default") then
c_gravel = minetest.get_content_id("default:gravel")
if seal_ocean then
water_node = "default:water_source"
end
end
local ignore
if minetest.get_modpath("chasms") then
-- the chasms mod already sets up a method to allow chasms to avoid overwriting stalactites and whatnot,
-- hijack that.
ignore = chasms.ignore_content_id
end
local water_level = tonumber(minetest.get_mapgen_setting("water_level"))
local mapgen_seed = tonumber(minetest.get_mapgen_setting("seed")) % 2^16
local scatter_2d = function(min_xz, gridscale, border_width)
local bordered_scale = gridscale - 2 * border_width
local point = {}
point.x = math.floor(math.random() * bordered_scale + min_xz.x + border_width)
point.y = 0
point.z = math.floor(math.random() * bordered_scale + min_xz.z + border_width)
return point
end
-- For some reason, map chunks generate with -32, -32, -32 as the "origin" minp. To make the large-scale grid align with map chunks it needs to be offset like this.
local get_corner = function(pos)
return {x = math.floor((pos.x+32) / pit_region_size) * pit_region_size - 32, z = math.floor((pos.z+32) / pit_region_size) * pit_region_size - 32}
end
local get_pit = function(pos)
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 + 1)
local location = scatter_2d(corner_xz, pit_region_size, 0)
local depth = math.floor(math.random() * (max_depth - min_depth) + min_depth)
local top = math.floor(math.random() * (max_top - min_top) + min_top)
math.randomseed(next_seed)
return {location = location, depth = depth, top = top}
end
local perlin_params = {
offset = 0,
scale = 1,
spread = {x=30, y=30, z=30},
seed = 45011,
octaves = 3,
persist = 0.67
}
local data = {}
minetest.register_on_generated(function(minp, maxp, seed)
if minp.y > max_top or maxp.y < min_depth then
return
end
local pit = get_pit(minp)
if pit == nil then
return -- no pit in this map region
end
local location_x = pit.location.x
local location_z = pit.location.z
-- early out if the pit is too far away to matter
-- The plus 20 is because the noise being added will generally be in the 0-20 range, see the "distance" calculation below
if location_x - 20 > maxp.x or
location_x + 20 < minp.x or
location_z - 20 > maxp.z or
location_z + 20 < minp.z
then
return
end
local top = pit.top
local depth = pit.depth
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
vm:get_data(data)
if water_node and minp.y <= water_level and maxp.y >= water_level-240 then
local test_node = minetest.get_node(vector.new(location_x, water_level, location_z))
if test_node.name == water_node then
top = math.min(-32, top) -- we're coming up under the ocean, abort the pit.
-- note that this does depend on the water-level map block having been generated already,
-- which could lead to a sharp cutoff if that's not the case - if the player's coming
-- up a pit from below into an unexplored ocean, for example. But it should still at least
-- seal the hole before the ocean pours down into it, so that's acceptable. And I expect
-- most of the time the surface world will be explored first before pits are discovered.
end
end
local nvals_perlin = mapgen_helper.perlin3d("pit_caves:pit", emin, emax, perlin_params)
for vi, x, y, z in area:iterp_xyz(emin, emax) do
if not (ignore and ignore(data[vi])) then
local distance_perturbation = (nvals_perlin[vi]+1)*10
local distance = vector.distance({x=x, y=y, z=z}, {x=location_x, y=y, z=location_z}) - distance_perturbation
local taper_min = top - 40
if y < top and y > depth then
if y > top - 40 then
-- taper the top end
distance = distance - ((taper_min - y)/2)
end
if distance < pit_radius then
if y < depth + 20 and data[vi] ~= c_air then
data[vi] = c_gravel
else
data[vi] = c_air
end
end
end
end
end
--send data back to voxelmanip
vm:set_data(data)
--calc lighting
vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()
--write it to world
vm:write_to_map()
end)
----------------------------------------------------------------------------------------------
-- Debugging and sightseeing commands
function round(val, decimal)
if (decimal) then
return math.floor( (val * 10^decimal) + 0.5) / (10^decimal)
else
return math.floor(val+0.5)
end
end
local send_pit_state = function(pos, name)
local pit = get_pit(pos)
if pit == nil then
return false
end
local location = {x=math.floor(pit.location.x), y=pit.top, z=math.floor(pit.location.z)}
minetest.chat_send_player(name, S("Pit at @1, bottom @2", minetest.pos_to_string(location), pit.depth))
return true
end
local send_nearby_states = function(pos, name)
local retval = false
retval = send_pit_state({x=pos.x-pit_region_size, y=0, z=pos.z+pit_region_size}, name) or retval
retval = send_pit_state({x=pos.x, y=0, z=pos.z+pit_region_size}, name) or retval
retval = send_pit_state({x=pos.x+pit_region_size, y=0, z=pos.z+pit_region_size}, name) or retval
retval = send_pit_state({x=pos.x-pit_region_size, y=0, z=pos.z}, name) or retval
retval = send_pit_state(pos, name) or retval
retval = send_pit_state({x=pos.x+pit_region_size, y=0, z=pos.z}, name) or retval
retval = send_pit_state({x=pos.x-pit_region_size, y=0, z=pos.z-pit_region_size}, name) or retval
retval = send_pit_state({x=pos.x, y=0, z=pos.z-pit_region_size}, name) or retval
retval = send_pit_state({x=pos.x+pit_region_size, y=0, z=pos.z-pit_region_size}, name) or retval
return retval
end
minetest.register_chatcommand("find_pit_caves", {
params = "pos", -- Short parameter description
description = S("find the pits near the player's map region, or in the map region containing pos if provided"),
func = function(name, param)
if minetest.check_player_privs(name, {server = true}) then
local pos = {}
pos.x, pos.y, pos.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
pos.x = tonumber(pos.x)
pos.y = tonumber(pos.y)
pos.z = tonumber(pos.z)
if pos.x and pos.y and pos.z then
if not send_nearby_states(pos, name) then
minetest.chat_send_player(name, S("No pits near @1", minetest.pos_to_string(pos)))
end
return true
else
local playerobj = minetest.get_player_by_name(name)
pos = playerobj:get_pos()
if not send_nearby_states(pos, name) then
pos.x = math.floor(pos.x)
pos.y = math.floor(pos.y)
pos.z = math.floor(pos.z)
minetest.chat_send_player(name, S("No pits near @1", minetest.pos_to_string(pos)))
end
return true
end
else
return false, S("You need the server privilege to use this command.")
end
end,
})

View File

@ -1,11 +0,0 @@
# textdomain: pit_caves
### init.lua ###
No pits near @1=
Pit at @1, bottom @2=
You need the server privilege to use this command.=
find the pits near the player's map region, or in the map region containing pos if provided=

View File

@ -1,4 +0,0 @@
name = pit_caves
description = Inserts very tall "pit" caves underground
depends =
optional_depends = mapgen_helper, default, chasms

View File

@ -1,6 +0,0 @@
pit_caves_min_bottom (Lower limit of bottoms of pits) int -2500
pit_caves_max_bottom (Upper limit of bottoms of pits) int -500
pit_caves_min_top (Lower limit of tops of pits) int -100
pit_caves_max_top (Upper limit of tops of pits) int 100
pit_caves_mapblock_spacing (Average number of map blocks between pits) int 16
pit_caves_seal_ocean (Seal off pits that are under ocean water) bool true