caverealms = {} --create a container for functions and constants local function table_contains(tbl, val) for _, v in pairs(tbl) do if v == val then return true end end return false end --grab a shorthand for the filepath of the mod local modpath = minetest.get_modpath(minetest.get_current_modname()) --[[ -- debug privileges minetest.register_on_joinplayer(function(player) local name = player:get_player_name() local privs = minetest.get_player_privs(name) privs.fly = true privs.fast = true privs.teleport = true privs.noclip = true minetest.set_player_privs(name, privs) local p = player:get_pos() if p.y > -100 then player:set_pos({x=0, y=-20000, z= 0}) end end) --]] --load companion lua files dofile(modpath .. "/config.lua") --configuration file; holds various constants dofile(modpath .. "/crafting.lua") --crafting recipes dofile(modpath .. "/nodes.lua") --node definitions dofile(modpath .. "/functions.lua") --function definitions dofile(modpath .. "/plants.lua") dofile(modpath .. "/hotsprings.lua") if minetest.get_modpath("mobs_monster") then if caverealms.config.dm_spawn == true then dofile(modpath .. "/dungeon_master.lua") --special DMs for DM's Lair biome end end -- Parameters local YMIN = caverealms.config.ymin -- Approximate realm limits. local YMAX = caverealms.config.ymax local TCAVE = caverealms.config.tcave --0.5 -- Cave threshold. 1 = small rare caves, 0.5 = 1/3rd ground volume, 0 = 1/2 ground volume local BLEND = 128 -- Cave blend distance near YMIN, YMAX local STAGCHA = caverealms.config.stagcha --0.002 --chance of stalagmites local STALCHA = caverealms.config.stalcha --0.003 --chance of stalactites local CRYSTAL = caverealms.config.crystal --0.0004 --chance of glow crystal formations local SALTCRYCHA = caverealms.config.salt_crystal --0.007 --chance of salt crystal cubes local GEMCHA = caverealms.config.gemcha --0.03 --chance of small glow gems local HOTSCHA = 0.009 --chance of hotsprings local MUSHCHA = caverealms.config.mushcha --0.04 --chance of mushrooms local MYCCHA = caverealms.config.myccha --0.03 --chance of mycena mushrooms local WORMCHA = caverealms.config.wormcha --0.03 --chance of glow worms local GIANTCHA = caverealms.config.giantcha --0.001 -- chance of giant mushrooms local ICICHA = caverealms.config.icicha --0.035 -- chance of icicles local FLACHA = caverealms.config.flacha --0.04 --chance of constant flames local DM_TOP = caverealms.config.dm_top -- -4000 --level at which Dungeon Master Realms start to appear local DM_BOT = caverealms.config.dm_bot -- -5000 --level at which "" ends local DEEP_CAVE = caverealms.config.deep_cave -- -7000 --level at which deep cave biomes take over -- 3D noise for caves local np_cave = { offset = 0, scale = 1, spread = { x = 512, y = 256, z = 512 }, -- squashed 2:1 seed = 59033, octaves = 6, persist = 0.63, } -- 3D noise for wave local np_wave = { offset = 0, scale = 1, spread = { x = 256, y = 256, z = 256 }, seed = -400000000089, octaves = 3, persist = 0.67, } -- 2D noise for biome local np_biome = { offset = 0, scale = 1, spread = { x = 250, y = 250, z = 250 }, seed = 9130, octaves = 3, persist = 0.5, } -- 2D noise for biome local np_biome_evil = { offset = 0, scale = 1, spread = { x = 200, y = 200, z = 200 }, seed = 9130, octaves = 3, persist = 0.5, } local np_biome_wonder = { offset = 0, scale = 1, spread = { x = 400, y = 400, z = 400 }, seed = 8943, octaves = 2, persist = 0.45, } -- Stuff subterrain = {} local yblmin = YMIN + BLEND * 1.5 local yblmax = YMAX - BLEND * 1.5 -- On generated function minetest.register_on_generated(function(minp, maxp, seed) --if out of range of caverealms limits if minp.y > YMAX or maxp.y < YMIN then return --quit; otherwise, you'd have stalagmites all over the place end --easy reference to commonly used values local t1 = os.clock() local x1 = maxp.x local y1 = maxp.y local z1 = maxp.z local x0 = minp.x local y0 = minp.y local z0 = minp.z --print ("[caverealms] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local area = VoxelArea:new({ MinEdge = emin, MaxEdge = emax }) local data = vm:get_data() local vparam2 = vm:get_param2_data() --grab content IDs local c_air = minetest.get_content_id("air") local c_stone = minetest.get_content_id("default:stone") local c_desertstone = minetest.get_content_id("default:desert_stone") local c_sandstone = minetest.get_content_id("default:sandstone") local c_obsidian = minetest.get_content_id("default:obsidian") local c_sand = minetest.get_content_id("default:sand") local c_water = minetest.get_content_id("default:water_source") local c_lava = minetest.get_content_id("default:lava_source") local c_iced = minetest.get_content_id("default:ice") local c_ssand = minetest.get_content_id("default:silver_sand") local c_thinice = minetest.get_content_id("caverealms:thin_ice") local c_crystal = minetest.get_content_id("caverealms:glow_crystal") local c_gem = minetest.get_content_id("caverealms:glow_gem") local c_saltgem = minetest.get_content_id("caverealms:salt_gem") print(c_saltgem) local c_spike = minetest.get_content_id("caverealms:spike") local c_moss = minetest.get_content_id("caverealms:stone_with_moss") local c_lichen = minetest.get_content_id("caverealms:stone_with_lichen") local c_algae = minetest.get_content_id("caverealms:stone_with_algae") local c_salt = minetest.get_content_id("caverealms:stone_with_salt") local c_hcobble = minetest.get_content_id("caverealms:hot_cobble") local c_gobsidian = minetest.get_content_id("caverealms:glow_obsidian") local c_gobsidian2 = minetest.get_content_id("caverealms:glow_obsidian_2") local c_coalblock = minetest.get_content_id("default:coalblock") local c_desand = minetest.get_content_id("default:desert_sand") local c_coaldust = minetest.get_content_id("caverealms:coal_dust") local c_fungus = minetest.get_content_id("caverealms:fungus") local c_mycena = minetest.get_content_id("caverealms:mycena") local c_worm_blue = minetest.get_content_id("caverealms:glow_worm") local c_worm_green = minetest.get_content_id("caverealms:glow_worm_green") local c_worm_red = minetest.get_content_id("caverealms:glow_worm_red") local c_fire_vine = minetest.get_content_id("caverealms:fire_vine") local c_iciu = minetest.get_content_id("caverealms:icicle_up") local c_icid = minetest.get_content_id("caverealms:icicle_down") local c_flame = minetest.get_content_id("caverealms:constant_flame") local c_bflame = minetest.get_content_id("caverealms:constant_flame_blue") local c_firefly = minetest.get_content_id("fireflies:firefly") local c_bluefly = minetest.get_content_id("caverealms:butterfly_blue") -- ethereal --if minetest.get_modpath("ethereal") then local c_bluegrass = minetest.get_content_id("ethereal:crystalgrass") local c_greemush = minetest.get_content_id("ethereal:illumishroom2") local c_redmush = minetest.get_content_id("ethereal:illumishroom") --else --end --too_many_stones --if minetest.get_modpath("too_many_stones") then local c_torangecrys = minetest.get_content_id("too_many_stones:crocoite_crystal") local c_tredcrys = minetest.get_content_id("too_many_stones:eudialite_crystal") local c_fakesalt = minetest.get_content_id("too_many_stones:rose_quartz_crystal") -- local c_tyellocrys = minetest.get_content_id("too_many_stones:citrine_crystal") local c_tsmokecrys = minetest.get_content_id("too_many_stones:smokey_quartz_crystal") local c_tyellowcrys = minetest.get_content_id("too_many_stones:heliodor_crystal") local c_tgreen1crys = minetest.get_content_id("too_many_stones:tourmaline_green_crystal") local c_tgreen2crys = minetest.get_content_id("too_many_stones:prasiolite_crystal") local c_fakeice1 = minetest.get_content_id("too_many_stones:celestine_crystal") local c_fakeice2 = minetest.get_content_id("too_many_stones:moonstone_crystal") local c_fakeice3 = minetest.get_content_id("too_many_stones:quartz_crystal") print(c_fakeice3) --else --end --everness --if minetest.get_modpath("everness") then local c_bluetwist = minetest.get_content_id("everness:twisted_crystal_grass") local c_icevine = minetest.get_content_id("everness:lumabus_vine_1") local c_purplevine = minetest.get_content_id("everness:whispering_gourd_vine_1") local c_icicles_c = minetest.get_content_id("everness:frosted_icicle") local c_icicles_f = minetest.get_content_id("everness:frosted_icicle_floor") local c_crystcyan = minetest.get_content_id("everness:crystal_cyan") -- local c_crystorange = minetest.get_content_id("everness:crystal_orange") -- local c_crystpurple = minetest.get_content_id("everness:crystal_purple") -- local c_flamepurple = minetest.get_content_id("everness:flame_permanent_purple") local c_frostedice = minetest.get_content_id("everness:frosted_ice") local c_mosspurple = minetest.get_content_id("everness:ivis_moss") local c_bluelant = minetest.get_content_id("everness:blue_vine_lantern") local c_redlant = minetest.get_content_id("everness:glowing_pillar") local c_redplant = minetest.get_content_id("everness:bloodspore_plant") local erdkristall = { c_torangecrys, c_tredcrys, c_fakesalt, c_tyellocrys, c_tsmokecrys, c_tyellowcrys, c_tgreen1crys, c_tgreen2crys, c_fakeice1, c_fakeice2, c_fakeice3, c_crystcyan, c_crystorange, c_crystpurple, } --else --end --herbs --if minetest.get_modpath("herbs") then local c_amanita = minetest.get_content_id("herbs:mushroom_amanita_green") --else --end --riesenpilz -- if minetest.get_modpath("riesenpilz") then local c_blueglowshroom = minetest.get_content_id("riesenpilz:glowshroom") --else --end -- crystals local c_crystore = minetest.get_content_id("caverealms:glow_ore") local c_emerald = minetest.get_content_id("caverealms:glow_emerald") local c_emore = minetest.get_content_id("caverealms:glow_emerald_ore") local c_mesecry = minetest.get_content_id("caverealms:glow_mese") local c_meseore = minetest.get_content_id("default:stone_with_mese") local c_ruby = minetest.get_content_id("caverealms:glow_ruby") local c_rubore = minetest.get_content_id("caverealms:glow_ruby_ore") local c_citrine = minetest.get_content_id("caverealms:glow_citrine") local c_citore = minetest.get_content_id("caverealms:glow_citrine_ore") local c_ameth = minetest.get_content_id("caverealms:glow_amethyst") local c_amethore = minetest.get_content_id("caverealms:glow_amethyst_ore") local c_hotspring = minetest.get_content_id("caverealms:hotspring_water_source") local stone_nodes = { [c_stone] = 1, [c_desertstone] = 1, [c_sandstone] = 1, [c_coalblock] = 1, [c_sand] = 1, [c_desand] = 1, [c_obsidian] = 1, } if nil ~= minetest.get_modpath("geology") then stone_nodes[minetest.get_content_id("geology:gneiss")] = 1 stone_nodes[minetest.get_content_id("geology:slate")] = 1 stone_nodes[minetest.get_content_id("geology:jade")] = 1 stone_nodes[minetest.get_content_id("geology:granite")] = 1 stone_nodes[minetest.get_content_id("geology:marble")] = 1 stone_nodes[minetest.get_content_id("geology:basalt")] = 1 stone_nodes[minetest.get_content_id("geology:chalk")] = 1 stone_nodes[minetest.get_content_id("geology:ors")] = 1 stone_nodes[minetest.get_content_id("geology:serpentine")] = 1 stone_nodes[minetest.get_content_id("geology:shale")] = 1 stone_nodes[minetest.get_content_id("geology:schist")] = 1 stone_nodes[minetest.get_content_id("geology:anthracite")] = 1 end --mandatory values local sidelen = x1 - x0 + 1 --length of a mapblock local chulens = { x = sidelen, y = sidelen, z = sidelen } --table of chunk edges local chulens2D = { x = sidelen, y = sidelen, z = 1 } local minposxyz = { x = x0, y = y0, z = z0 } --bottom corner local minposxz = { x = x0, y = z0 } --2D bottom corner local nvals_biome_e = minetest.get_perlin_map(np_biome_evil, chulens2D):get2dMap_flat({ x = x0 + 150, y = z0 + 50 }) --2D noise for biomes (will be 3D humidity/temp later) local nvals_biome_w = minetest.get_perlin_map(np_biome_wonder, chulens2D):get2dMap_flat({ x = x0 + 150, y = z0 + 50 }) --2D noise for biomes (will be 3D humidity/temp later) local nixyz = 1 --3D node index local nixz = 1 --2D node index local nixyz2 = 1 --second 3D index for second loop for z = z0, z1 do -- for each xy plane progressing northwards --increment indices nixyz = nixyz + 1 --decoration loop for y = y0, y1 do -- for each x row progressing upwards local is_deep = false if y < DEEP_CAVE then is_deep = true end local vi = area:index(x0, y, z) for x = x0, x1 do -- for each node do local ai = area:index(x, y + 1, z) --above index local bi = area:index(x, y - 1, z) --below index local mode = 0 -- nothing, 1 = ground, 2 = ceiling if data[vi] == c_air then if stone_nodes[data[bi]] ~= nil then --ground mode = 1 elseif stone_nodes[data[ai]] ~= nil and y < y1 then -- ceiling mode = 2 end end if mode > 0 then local a2i = area:index(x, y + 2, z) --above index --determine biome local biome = 0 --preliminary declaration local n_biome_e = nvals_biome_e[nixz] --make an easier reference to the noise local n_biome_w = nvals_biome_w[nixz] --make an easier reference to the noise local n_biome = (n_biome_e + n_biome_w) / 2 local floor = c_hcobble local floor_depth = 1 local worms = {} local worm_max_len = 1 local no_mites = false local no_tites = false local decos = {} local decos2 = {} local deco_mul = 1 local wiggle = (math.random() - 0.5) / 20 n_biome_e = n_biome_e + wiggle n_biome_w = n_biome_w + wiggle if n_biome_e < -0.33 then if n_biome_w < -0.33 then -- algae if is_deep then --deep algae deco worms = { c_worm_green, c_tyellowcrys } decos = { c_mycena, c_greemush, c_tyellowcrys, c_amanita } else -- normal algae worms = { c_worm_green } decos = { c_mycena } end floor = c_algae worm_max_len = 3 if mode == 1 and data[ai] == c_air and math.random() < 0.03 then data[ai] = c_firefly end elseif n_biome_w < 0.33 then -- moss if is_deep then --deep moss deco worms = { c_worm_green, c_tgreen1crys, c_tgreen2crys, c_worm_blue } decos = { c_mycena, c_greemush, c_tgreen1crys, c_tgreen2crys, } deco_mul = 2 else -- normal moss worms = { c_worm_green } decos = { c_mycena } end floor = c_moss worm_max_len = 3 deco_mul = 2.0 if mode == 1 and data[ai] == c_air and math.random() < 0.001 then caverealms:grow_green_mushroom(x, y - 1, z, area, data) end else -- lichen if is_deep then --magical lichen deco worms = { c_crystpurple, c_crystpurple, c_purplevine } decos = { c_mosspurple, c_flamepurple, c_crystpurple, c_bluetwist, c_tyellocrys, } else -- normal lichen worms = { c_worm_blue } decos = { c_mycena, c_fungus, c_fungus } end floor = c_lichen worm_max_len = 1 deco_mul = 3.3 if mode == 1 and data[ai] == c_air and math.random() < 0.003 then data[ai] = c_bluefly end end elseif n_biome_e < 0.33 then if n_biome_w < -0.33 then -- desert if math.random() < 0.05 then floor = c_coalblock elseif math.random() < 0.15 then floor = c_coaldust else if is_deep then floor = c_hcobble else floor = c_desand end end if is_deep then decos = { c_redplant, c_redlant, c_flame, c_torangecrys, c_redplant, c_flame, c_torangecrys, c_crystorange, } worms = { c_worm_red, c_torangecrys } else decos = { c_tyellocrys, c_flame, c_spike, c_tsmokecrys, c_crystorange, } worms = { c_tyellocrys, c_tsmokecrys } end deco_mul = 2 floor_depth = 2 worm_max_len = 1 elseif n_biome_w < 0.33 then -- salt floor = c_salt floor_depth = 2 worms = { c_fakesalt } worm_max_len = 1 no_mites = true decos = { c_saltgem } if is_deep then decos = { c_saltgem, c_fakesalt } end else if is_deep then --magic deep glacial floor = c_frostedice floor_depth = 2 worms = { c_icevine, c_crystcyan, c_crystcyan, c_icicles_c, c_worm_blue } worm_max_len = 1 decos = { c_crystcyan, c_blueglowshroom, c_bluetwist, c_bflame, c_icicles_f, c_bluelant, c_iciu, c_iciu, c_icicles_f, c_bluegrass, } deco_mul = 2 else --glacial floor = c_thinice floor_depth = 2 worms = { c_icid, c_worm_blue } worm_max_len = 1 decos = { c_gem, c_iciu } deco_mul = 2 end end else if n_biome_w < -0.33 then -- hotspring floor = c_hcobble worms = { c_worm_red } worm_max_len = 1 if mode == 1 and math.random() < 0.005 then caverealms:spawn_hotspring(x, y, z, area, data, math.random(4) + 2) end decos = { c_fire_vine, c_redmush } deco_mul = 0.7 elseif n_biome_w < 0.33 then -- dungeon if math.random() < 0.5 then floor = c_gobsidian else floor = c_gobsidian2 end worms = { c_worm_red, c_tredcrys } worm_max_len = 4 decos = { c_flame, c_flame, c_bflame, c_fire_vine, c_tredcrys } else -- deep glacial floor = c_iced floor_depth = 3 worms = { c_icid, c_icicles_c, c_icid, c_icicles_c, c_fakeice1, c_fakeice2, c_fakeice3 } worm_max_len = 1 decos = { c_bflame, c_iciu, c_icicles_f, c_bflame, c_iciu, c_icicles_f, c_fakeice1, c_fakeice2, c_fakeice3, } end end -- place floor if mode == 1 then --ground for i = 1, floor_depth do local ii = area:index(x, y - i, z) if stone_nodes[data[bi]] ~= nil then data[ii] = floor end end -- minetest.set_node(pos + vector.new(x, y, z), {name = crystal, param2 = 1}) -- decorations if math.random() < ICICHA * deco_mul and data[bi] ~= c_hotspring then local deco = decos[math.random(1, #decos)] if table_contains(erdkristall, deco) then local paramzwei = minetest.dir_to_facedir((vector.new(2, 0, 0)), true) vparam2[vi] = paramzwei end data[vi] = deco end -- salt crystals if floor == c_salt and math.random() < SALTCRYCHA then caverealms:salt_stalagmite(x, y - 1, z, area, data) end -- stone stalagmites if math.random() < STAGCHA then caverealms:stalagmite(x, y, z, area, data) end -- crystal stalagmites if not no_mites and math.random() < CRYSTAL then local ore local cry if n_biome_e < -0.33 then -- non-evil if n_biome_w < -0.33 then --algae if math.random(10) == 1 then --chance 1/10 for mese ore = c_emore cry = c_emerald else ore = c_meseore cry = c_mesecry end elseif n_biome_w < 0.33 then --moss if is_deep then --deep moss if math.random(10) == 1 then ore = c_crystore cry = c_crystal else ore = c_emore cry = c_emerald end else --normal moss ore = c_emore cry = c_emerald end else --lichen if is_deep then --magical lichen local tschu = math.random(8) if tschu == 1 then --chance 1/10 for mese ore = c_meseore cry = c_mesecry elseif tschu == 2 then ore = c_crystore cry = c_crystal else ore = c_amethore cry = c_ameth end else --lichen ore = c_amethore cry = c_ameth end end elseif n_biome_e < 0.33 then -- moderately evil if n_biome_w < -0.33 then if is_deep then --hot cobble if math.random(3) == 1 then ore = c_citore cry = c_citrine else ore = c_rubore cry = c_ruby end else if math.random(3) == 1 then --desert / sand ore = c_meseore cry = c_mesecry else ore = c_citore cry = c_citrine end end elseif n_biome_w < 0.33 then --salt ore = c_meseore cry = c_mesecry else if is_deep then --magic deep glacial if math.random(3) == 1 then ore = c_iced cry = c_thinice else ore = c_crystore cry = c_crystal end else --glacial if math.random(5) == 1 then ore = c_crystore cry = c_crystal else ore = c_iced cry = c_thinice end end end else -- very evil if n_biome_w < -0.33 then --hotcobble-hotsprings if math.random(3) == 1 then ore = c_citore cry = c_citrine else ore = c_rubore cry = c_ruby end elseif n_biome_w < 0.33 then --obsidian-dungeon if math.random(10) == 1 then ore = c_crystore cry = c_crystal else ore = c_rubore cry = c_ruby end else --deep_glacial if math.random(3) == 1 then ore = c_crystore cry = c_crystal else ore = c_iced cry = c_thinice end end end local base = floor caverealms:crystal_stalagmite(x, y - 1, z, area, data, ore, cry, base) end if n_biome_w > 0.5 and n_biome_e < -0.33 and math.random() < GIANTCHA then --giant mushrooms caverealms:giant_shroom(x, y, z, area, data) end elseif mode == 2 then -- place ceiling if math.random() < ICICHA then local worm = worms[math.random(1, #worms)] local wdepth = math.random(1, worm_max_len) for i = 0, wdepth - 1 do local ii = area:index(x, y - i, z) if data[ii] == c_air then data[ii] = worm end end end -- stalactites if not no_tites and math.random() < CRYSTAL then local ore local cry if n_biome_e < -0.33 then -- non-evil if n_biome_w < -0.33 then --algae if math.random(10) == 1 then --chance 1/10 for mese ore = c_emore cry = c_emerald else ore = c_meseore cry = c_mesecry end elseif n_biome_w < 0.33 then --moss ore = c_emore cry = c_emerald else --lichen if is_deep then --magical lichen local tschu = math.random(6) if tschu == 1 then --chance 1/10 for mese ore = c_meseore cry = c_mesecry elseif tschu == 2 then ore = c_crystore cry = c_crystal else ore = c_amethore cry = c_ameth end else --lichen ore = c_amethore cry = c_ameth end end elseif n_biome_e < 0.33 then -- moderately evil if n_biome_w < -0.33 then if is_deep then --hot cobble if math.random(3) == 1 then ore = c_citore cry = c_citrine else ore = c_rubore cry = c_ruby end else if math.random(3) == 1 then --desert / sand ore = c_meseore cry = c_mesecry else ore = c_citore cry = c_citrine end end elseif n_biome_w < 0.33 then --salt ore = c_meseore cry = c_mesecry else if is_deep then --magic deep glacial if math.random(3) == 1 then ore = c_iced cry = c_thinice else ore = c_crystore cry = c_crystal end else --glacial if math.random(5) == 1 then ore = c_crystore cry = c_crystal else ore = c_iced cry = c_thinice end end end else -- very evil if n_biome_w < -0.33 then --hotcobble-hotsprings if math.random(3) == 1 then ore = c_citore cry = c_citrine else ore = c_rubore cry = c_ruby end elseif n_biome_w < 0.33 then --obsidian-dungeon if math.random(20) == 1 then ore = c_crystore cry = c_crystal else ore = c_rubore cry = c_ruby end else --deep_glacial if math.random(3) == 1 then ore = c_crystore cry = c_crystal else ore = c_iced cry = c_thinice end end end local base = c_stone caverealms:crystal_stalactite(x, y, z, area, data, ore, cry, base) end end end nixyz2 = nixyz2 + 1 nixz = nixz + 1 vi = vi + 1 end nixz = nixz - sidelen --shift the 2D index back end nixz = nixz + sidelen --shift the 2D index up a layer end --send data back to voxelmanip vm:set_data(data) vm:set_param2_data(vparam2) --calc lighting vm:set_lighting({ day = 0, night = 0 }) vm:calc_lighting() --write it to world vm:write_to_map(data) --local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took --print ("[caverealms] "..chugent.." ms") --tell people how long end) print("[caverealms] loaded!")