mirror of
https://github.com/FaceDeer/dfcaverns.git
synced 2025-03-22 12:40:26 +01:00
* initial chasms mod * tweak default chasm settings * prevent chasms from breaching oil and magma seas, make veinstone actually do something * overgenerate caverns to eliminate floating stalactites * make veinstone punchable instead of right-clickable * 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. * add rare big webs to the chasms, to give them a unique feature * reverse the dependencies for df_caverns and chasms, let chasms go first. * fix web generator * add webs to level 3 tunnels, fix sunless sea chasms * fix up tunnel webs * make webs snappy * make webs slightly more prevalent * add chasms to the guide * final touch-ups before merging * allow anchoring against unloaded blocks
169 lines
5.5 KiB
Lua
169 lines
5.5 KiB
Lua
local data = {}
|
|
|
|
chasms = {}
|
|
|
|
local maxy = tonumber(minetest.settings:get("chasms_maxy")) or -50
|
|
local miny = tonumber(minetest.settings:get("chasms_miny")) or -2500
|
|
local falloff = tonumber(minetest.settings:get("chasms_falloff")) or 100
|
|
|
|
local web_probability = 0.15 -- the chance that a given mapblock will have webbing criss-crossing the chasm
|
|
|
|
local chasms_threshold = tonumber(minetest.settings:get("chasms_threshold")) or 0.9
|
|
local np_chasms_default = {
|
|
offset = 0,
|
|
scale = 1,
|
|
spread = {x = 50, y = 1000, z = 3000},
|
|
seed = 94586,
|
|
octaves = 2,
|
|
persist = 0.63,
|
|
lacunarity = 2.0,
|
|
}
|
|
local np_chasms = minetest.settings:get_np_group("chasms_params") or np_chasms_default
|
|
-- For some reason, these numbers are returned as strings by get_np_group.
|
|
local tonumberize_params = function(params)
|
|
params.scale = tonumber(params.scale)
|
|
params.lacunarity = tonumber(params.lacunarity)
|
|
params.spread.x = tonumber(params.spread.x)
|
|
params.spread.y = tonumber(params.spread.y)
|
|
params.spread.z = tonumber(params.spread.z)
|
|
params.offset = tonumber(params.offset)
|
|
params.persistence = tonumber(params.persistence)
|
|
end
|
|
tonumberize_params(np_chasms)
|
|
local nobj_chasm
|
|
local chasm_data = {}
|
|
|
|
local waver_strength = 8
|
|
local waver_vector = {x=waver_strength, y=0, z=0}
|
|
local np_waver = {
|
|
offset = 0,
|
|
scale = waver_strength,
|
|
spread = {x = 50, y = 50, z = 50},
|
|
seed = 49585,
|
|
octaves = 2,
|
|
persist = 0.63,
|
|
lacunarity = 2.0,
|
|
}
|
|
local nobj_waver
|
|
local waver_data = {}
|
|
|
|
local minfalloff = miny + falloff
|
|
local maxfalloff = maxy - falloff
|
|
local get_intensity = function(y)
|
|
if y < miny or y > maxy then
|
|
return 0
|
|
end
|
|
if y <= maxfalloff and y >= minfalloff then
|
|
return 1
|
|
end
|
|
if y < minfalloff then
|
|
return (y-miny)/falloff
|
|
end
|
|
-- if y > maxfalloff then
|
|
return (maxy-y)/falloff
|
|
-- end
|
|
end
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_web
|
|
|
|
local big_webs_path = minetest.get_modpath("big_webs")
|
|
if big_webs_path then
|
|
c_web = minetest.get_content_id("big_webs:webbing")
|
|
end
|
|
|
|
local z_displace = 10000
|
|
|
|
|
|
local calculate_web_array = function(minp, maxp)
|
|
local seed = math.random()*10000000
|
|
math.randomseed(minp.y + z_displace*minp.z) -- use consistent seeds across the x axis
|
|
local webs = {}
|
|
for count = 1, math.random(5,20) do
|
|
local width = math.random(5, 25)
|
|
local direction_vertical = math.random() > 0.5
|
|
local web_y = math.random(minp.y+8, maxp.y-8)
|
|
local web_z = math.random(minp.z+8, maxp.z-8)
|
|
for i = -math.floor(width/2), math.ceil(width/2) do
|
|
if direction_vertical then
|
|
webs[(web_y+i) + web_z*z_displace] = true
|
|
else
|
|
webs[web_y + (web_z+i)*z_displace] = true
|
|
end
|
|
end
|
|
end
|
|
math.randomseed(seed)
|
|
return webs
|
|
end
|
|
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
if minp.y >= maxy or maxp.y <= miny then
|
|
return
|
|
end
|
|
|
|
-- check if webs are present
|
|
local webs
|
|
local webs_present = false
|
|
if big_webs_path then
|
|
local seed = math.random()*10000000
|
|
math.randomseed(minp.y + z_displace*minp.z) -- use consistent seeds across the x axis
|
|
if math.random() < web_probability then
|
|
webs_present = true
|
|
end
|
|
math.randomseed(seed)
|
|
end
|
|
|
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
|
vm:get_data(data)
|
|
|
|
nobj_chasm = nobj_chasm or minetest.get_perlin_map(np_chasms, {x = emax.x - emin.x + 1 + waver_strength*2, y = emax.y - emin.y + 1, z = emax.z - emin.z + 1})
|
|
nobj_chasm:get_3d_map_flat(vector.subtract(emin, waver_vector), chasm_data)
|
|
|
|
nobj_waver = nobj_waver or minetest.get_perlin_map(np_waver, {x = emax.x - emin.x + 1, y = emax.y - emin.y + 1, z = emax.z - emin.z + 1})
|
|
nobj_waver:get_3d_map_flat(emin, waver_data)
|
|
|
|
local chasm_area = VoxelArea:new{MinEdge = vector.subtract(emin, waver_vector), MaxEdge = vector.add(emax, waver_vector)}
|
|
local data_area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
|
|
|
|
for i, x, y, z in data_area:iterp_xyz(emin, emax) do
|
|
local waver = math.min(math.max(math.floor(waver_data[i]+0.5), -waver_strength), waver_strength)
|
|
local intensity = get_intensity(y)
|
|
if chasm_data[chasm_area:index(x+waver, y, z)]*intensity > chasms_threshold then
|
|
if webs_present then
|
|
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
|
|
data[i] = c_web
|
|
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
|
|
data[i] = c_air
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:calc_lighting()
|
|
vm:write_to_map()
|
|
end)
|
|
|
|
local nobj_local_chasm = minetest.get_perlin(np_chasms)
|
|
local nobj_local_waver = minetest.get_perlin(np_waver)
|
|
|
|
chasms.is_in_chasm = function(pos)
|
|
nobj_local_chasm = nobj_local_chasm or minetest.get_perlin(np_chasms)
|
|
nobj_local_waver = nobj_local_waver or minetest.get_perlin(np_waver)
|
|
local waver = math.min(math.max(math.floor(nobj_local_waver:get_3d(pos)+0.5), -waver_strength), waver_strength)
|
|
local chasm_value = nobj_local_chasm:get_3d({x=pos.x+waver, y=pos.y, z=pos.z})
|
|
return chasm_value*get_intensity(pos.y) > chasms_threshold
|
|
end
|
|
|
|
-- A little cheaper to run, for mapgens that know they don't have to worry about the tops and bottoms of chasms
|
|
chasms.is_in_chasm_without_taper = function(pos)
|
|
nobj_local_chasm = nobj_local_chasm or minetest.get_perlin(np_chasms)
|
|
nobj_local_waver = nobj_local_waver or minetest.get_perlin(np_waver)
|
|
local waver = math.min(math.max(math.floor(nobj_local_waver:get_3d(pos)+0.5), -waver_strength), waver_strength)
|
|
local chasm_value = nobj_local_chasm:get_3d({x=pos.x+waver, y=pos.y, z=pos.z})
|
|
return chasm_value > chasms_threshold
|
|
end |