mirror of
https://github.com/FaceDeer/dfcaverns.git
synced 2024-11-13 22:20:28 +01:00
0a0c97b74e
* latest versions of mapgen_helper and subterrane * initial work * call it "minetest_game" compatibility instead of "default" compatibility * Getting started on moving all default dependencies to a single root mod * distilling out more dependencies * fix some typos * more default dependencies * beds * start getting some MCL equivalents set up * mine gas dependencies * reorganize * add some mapgen stuff * getting close to actually being able to run mineclone with this * it actually runs! Crashes with out-of-memory error when you try to go below -64, but it's a start. * hide flowing pit plasma from creative inventory * mineclone 5 settings * Update subterrane * get rid of meselamp dependency, bring in ancient lanterns from deep roads * stair dependencies * add mcl fences * add mcl blast resistance and hardness to everything. Also an alternate name for Nethercap in MCL, since "nether" has another meaning there. * buckets of oil and syrup should work in mineclone now * 'splosions! * make hunters avoid repaired ancient lanterns * mapgen torchspine wasn't having its timer set * split mapgen compatibility code into its own file * bypass dependency indirection for df_farming. * apply threshold alpha to food items, they look better that way * bypass dependency indirection for df_mapitems * bypass dependency indirection for df_primordial_items * bypass dependency indirection for df_trees * bypass dependency indirection for df_underworld_items * bypass dependency indirection for df_caverns * fixing up the puzzle seal to work in both * fix puzzle seal formspec for mcl * create built-in substitutes for fireflies and bones mods for when those aren't available * set up mcl dungeon loot for underworld warriors, port over some translations from default * overlooked a debug * add itemslot backgrounds for mcl * added mineclone groups to all registered nodes. TODO: craftitems. This was extremely tedious. Completely untested, aside from simply running the game. * minor fixes to the built-in bones node * eatable group for edibles * clean up some TODOs * adjust pit plasma abm conditions * add df_ambience * fixing up explosions. Also make slade sand diggable in mcl, and fix a bug in web generators * make tower cap caves less chirpy, fix bigger goblin hut schematic, allow glowing spindlestem extract bottles * avoid an undeclared global check * alas, cave pearls aren't set up right for attached_node_facedir. * bunch of work on mineclone ores, moved main config into df_dependencies * add a few more ores * update depends in mod.conf * add opaque group to light-sensitive dirt types Mineclone adds the "opaque" group only to non-light nodes, and torches check for the opaque group to decide whether they can be placed there. light-sensitive nodes need the "light" paramtype to work, though. So adding the opaque group manually to these. * add a touch of reverb to one of the whisper tracks, it didn't fit with the others without it * bloodthorn also needs to be set opaque * add sound to torchspines * isolate Nethercap translation name to make it easier to swap out in Mineclone contexts * ambience tweak * fix dirt spreads https://github.com/FaceDeer/dfcaverns/issues/35 * adding achievements! Almost all untested yet. * fix a few achievements glitches * tweak some more achievements, add delay when achievements unlock other achievements * fix farming achievements, fix spindlestem callbacks on place * icons for farming achievements * more achievement icons, fix ancient lantern achievement * two more icons, update text * add icons for upper cavern layers * all achievements have icons now. Also add another sound to the magma sea ambience * hook into awards' trigger system to get "x/y" progress displayed for the multi-achievement achievements * ironically, Mineclone has an old version of awards that is incompatible with my trigger work. * every award should now have a description and a difficulty. * removing leftovers * missing callbacks for farmables * put growth restrictions on farmables so the achievement doesn't trigger inappropriately. * enable ores in MCL2, fix some undeclared globals, fix icecap growth in MCL (achievements are a good debugging tool) * get *all* the copper and iron containing nodes * fix old awards mod's handling of grouped dig items * Add a little bonus for players who activate a slade breacher - a handheld 'splosion tool * used the wrong drop method * beef up explosions in MCL, make slade brick craftable from slade sand and lava * better creative mode checks, fix crash when digging walls in MCL * Update subterrane * various bugfixes and tweaks * whipping up a simple puzzle chest to give a clue about ancient numbering The coding is done, but UI and a node mesh need to be done * prepare for some art tomorrow * chest node and sounds * images for the combination dials * add puzzle chests to the underworld buildings * update translations * oops, can't initialize the contents of puzzle chests every time or players get endless stuff * add backgrounds to item slots in MCL * wrap the existing function rather than copy and pasting it * fix bucket dependency in cooking recipes * add _mcl_saturation to edibles
231 lines
8.2 KiB
Lua
231 lines
8.2 KiB
Lua
pit_caves = {}
|
|
|
|
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 log_location
|
|
if minetest.get_modpath("mapgen_helper") and mapgen_helper.log_location_enabled then
|
|
log_location = mapgen_helper.log_first_location
|
|
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
|
|
|
|
pit_caves.get_nearest_pit = get_pit
|
|
|
|
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
|
|
if log_location then log_location("pit_cave", vector.new(x,y,z)) end
|
|
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,
|
|
}) |