diff --git a/abms.lua b/abms.lua index a8f31a8..d30e49a 100644 --- a/abms.lua +++ b/abms.lua @@ -21,6 +21,7 @@ local find_nodes_in_area = minetest.find_nodes_in_area local get_item_group = minetest.get_item_group local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air + minetest.register_globalstep(function(dtime) local time = get_us_time() @@ -77,29 +78,6 @@ minetest.register_globalstep(function(dtime) end) --- Exploding fungal fruit -minetest.register_abm({ - nodenames = {"fun_caves:fungal_tree_fruit"}, - interval = 20 * fun_caves.time_factor, - chance = 14, - catch_up = false, - action = function(pos, node) - fun_caves.soft_boom(pos) - end -}) - --- Exploding fungal fruit -- in a fire -minetest.register_abm({ - nodenames = {"fun_caves:fungal_tree_fruit"}, - neighbors = {"fire:basic_flame"}, - interval = 10 * fun_caves.time_factor, - chance = 5, - catch_up = false, - action = function(pos, node) - fun_caves.soft_boom(pos) - end -}) - -- mushroom growth -- small into huge minetest.register_abm({ nodenames = mushrooms, @@ -271,6 +249,102 @@ minetest.register_abm({ }) +local fungal_tree_leaves = {} +for i = 1, 4 do + fungal_tree_leaves[#fungal_tree_leaves+1] = "fun_caves:fungal_tree_leaves_"..i +end + +local leaves = {} +for _, leaf in pairs(fungal_tree_leaves) do + leaves[leaf] = true +end + +-- Exploding fungal fruit +minetest.register_abm({ + nodenames = {"fun_caves:fungal_tree_fruit"}, + interval = 20 * fun_caves.time_factor, + chance = 14, + catch_up = false, + action = function(pos, node) + fun_caves.soft_boom(pos) + end +}) + +-- Exploding fungal fruit -- in a fire +minetest.register_abm({ + nodenames = {"fun_caves:fungal_tree_fruit"}, + neighbors = {"fire:basic_flame"}, + interval = 10 * fun_caves.time_factor, + chance = 5, + catch_up = false, + action = function(pos, node) + fun_caves.soft_boom(pos) + end +}) + +-- fungal spread +minetest.register_abm({ + nodenames = fungal_tree_leaves, + neighbors = {"air", "group:liquid"}, + interval = 2 * fun_caves.time_factor, + chance = 10, + catch_up = false, + action = function(pos, node) + if get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then + remove_node(pos) + return + end + + local grow_pos = {x=pos.x, y=pos.y-1, z=pos.z} + local grow_node = get_node_or_nil(grow_pos) + if grow_node and grow_node.name == "air" then + set_node(grow_pos, {name = node.name}) + return + end + + grow_pos = {x=rand(-1,1)+pos.x, y=rand(-1,1)+pos.y, z=rand(-1,1)+pos.z} + grow_node = get_node_or_nil(grow_pos) + if grow_node and grow_node.name == "air" and get_node_light(grow_pos, nil) <= fun_caves.light_max then + set_node(grow_pos, {name = node.name}) + return + elseif grow_node and leaves[grow_node.name] and grow_node.name ~= node.name then + set_node(grow_pos, {name = 'air'}) + return + end + + if rand(40) == 1 then + set_node(pos, {name = "fun_caves:fungal_tree_fruit"}) + return + end + + if rand(100) == 1 then + set_node(pos, {name = fungal_tree_leaves[rand(#fungal_tree_leaves)]}) + return + end + end +}) + +-- new fungi +minetest.register_abm({ + nodenames = {"default:dirt"}, + neighbors = {"air"}, + interval = 20 * fun_caves.time_factor, + chance = 25, + action = function(pos, node) + if pos.y > 0 then + return + end + + local grow_pos = {x=pos.x, y=pos.y+1, z=pos.z} + local grow_node = get_node_or_nil(grow_pos) + if grow_node and grow_node.name == "air" and (get_node_light(grow_pos, nil) or 99) <= fun_caves.light_max then + set_node(grow_pos, {name = fungal_tree_leaves[rand(#fungal_tree_leaves)]}) + return + end + end +}) + + -- All of this is copied from TNT, but modified to leave stone intact. -- Fill a list with data for content IDs, after all nodes are registered diff --git a/deco.lua b/deco.lua index a2100ce..3e2e614 100644 --- a/deco.lua +++ b/deco.lua @@ -113,10 +113,9 @@ minetest.register_decoration({ }) -dofile(fun_caves.path.."/deco_caves.lua") +dofile(fun_caves.path .. "/deco_caves.lua") --dofile(fun_caves.path.."/deco_dirt.lua") dofile(fun_caves.path.."/deco_plants.lua") dofile(fun_caves.path.."/deco_rocks.lua") --dofile(fun_caves.path.."/deco_ferns.lua") --dofile(fun_caves.path.."/deco_ferns_tree.lua") -dofile(fun_caves.path.."/deco_water.lua") diff --git a/deco_cave_nodes.lua b/deco_cave_nodes.lua deleted file mode 100644 index 6ae0a83..0000000 --- a/deco_cave_nodes.lua +++ /dev/null @@ -1,430 +0,0 @@ --- black (oily) sand -local newnode = fun_caves.clone_node("default:sand") -newnode.description = "Black Sand" -newnode.tiles = {"fun_caves_black_sand.png"} -newnode.groups['falling_node'] = 0 -minetest.register_node("fun_caves:black_sand", newnode) - --- cobble, hot - cobble with lava instead of mortar XD -minetest.register_node("fun_caves:hot_cobble", { - description = "Hot Cobble", - tiles = {"caverealms_hot_cobble.png"}, - is_ground_content = true, - groups = {crumbly=2, surface_hot=3}, - --light_source = 2, - damage_per_second = 1, - sounds = default.node_sound_stone_defaults({ - footstep = {name="default_stone_footstep", gain=0.25}, - }), -}) - --- dirt, glowing -newnode = fun_caves.clone_node("default:dirt") -newnode.description = "Glowing Dirt" -newnode.light_source = default.LIGHT_MAX -newnode.soil = { - base = "fun_caves:glowing_dirt", - dry = "fun_caves:glowing_soil", - wet = "fun_caves:glowing_soil_wet" -} -minetest.register_node("fun_caves:glowing_dirt", newnode) - --- Dirt can become soil. -newnode = fun_caves.clone_node("farming:soil") -newnode.description = "Glowing Soil" -newnode.light_source = default.LIGHT_MAX -newnode.soil = { - base = "fun_caves:glowing_dirt", - dry = "fun_caves:glowing_soil", - wet = "fun_caves:glowing_soil_wet" -} -minetest.register_node("fun_caves:glowing_dirt", newnode) - --- Dirt to soil to wet soil... -newnode = fun_caves.clone_node("farming:soil_wet") -newnode.description = "Wet Glowing Soil" -newnode.light_source = default.LIGHT_MAX -newnode.soil = { - base = "fun_caves:glowing_dirt", - dry = "fun_caves:glowing_soil", - wet = "fun_caves:glowing_soil_wet" -} -minetest.register_node("fun_caves:glowing_dirt", newnode) - --- flame, constant -- does not expire -minetest.register_node("fun_caves:constant_flame", { - description = "Fire", - drawtype = "plantlike", - tiles = {{ - name="fire_basic_flame_animated.png", - animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=1}, - }}, - inventory_image = "fire_basic_flame.png", - light_source = 14, - groups = {igniter=2,dig_immediate=3,hot=3, not_in_creative_inventory=1}, - drop = '', - walkable = false, - buildable_to = true, - damage_per_second = 4, -}) - --- Glowing fungal stone provides an eerie light. -minetest.register_node("fun_caves:glowing_fungal_stone", { - description = "Glowing Fungal Stone", - tiles = {"default_stone.png^vmg_glowing_fungal.png",}, - is_ground_content = true, - light_source = fun_caves.light_max - 4, - groups = {cracky=3, stone=1}, - drop = {items={ {items={"default:cobble"},}, {items={"fun_caves:glowing_fungus",},},},}, - sounds = default.node_sound_stone_defaults(), -}) - --- Glowing fungus grows underground. -minetest.register_node("fun_caves:glowing_fungus", { - description = "Glowing Fungus", - drawtype = "plantlike", - paramtype = "light", - tiles = {"vmg_glowing_fungus.png"}, - inventory_image = "vmg_glowing_fungus.png", - groups = {dig_immediate = 3}, -}) - --- moon glass (glows) -local newnode = fun_caves.clone_node("default:glass") -newnode.light_source = default.LIGHT_MAX -minetest.register_node("fun_caves:moon_glass", newnode) - --- Moon juice is extracted from glowing fungus, to make glowing materials. -minetest.register_node("fun_caves:moon_juice", { - description = "Moon Juice", - drawtype = "plantlike", - paramtype = "light", - tiles = {"vmg_moon_juice.png"}, - inventory_image = "vmg_moon_juice.png", - --groups = {dig_immediate = 3, attached_node = 1}, - groups = {dig_immediate = 3}, - sounds = default.node_sound_glass_defaults(), -}) - --- mushroom cap, giant -minetest.register_node("fun_caves:giant_mushroom_cap", { - description = "Giant Mushroom Cap", - tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"}, - is_ground_content = false, - paramtype = "light", - drawtype = "nodebox", - node_box = { type = "fixed", - fixed = { - {-0.4, -0.5, -0.4, 0.4, 0.0, 0.4}, - {-0.75, -0.5, -0.4, -0.4, -0.25, 0.4}, - {0.4, -0.5, -0.4, 0.75, -0.25, 0.4}, - {-0.4, -0.5, -0.75, 0.4, -0.25, -0.4}, - {-0.4, -0.5, 0.4, 0.4, -0.25, 0.75}, - } }, - light_source = fun_caves.light_max, - groups = {fleshy=1, dig_immediate=3, flammable=2, plant=1}, -}) - --- mushroom cap, huge -minetest.register_node("fun_caves:huge_mushroom_cap", { - description = "Huge Mushroom Cap", - tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"}, - is_ground_content = false, - paramtype = "light", - drawtype = "nodebox", - node_box = { type = "fixed", - fixed = { - {-0.5, -0.5, -0.33, 0.5, -0.33, 0.33}, - {-0.33, -0.5, 0.33, 0.33, -0.33, 0.5}, - {-0.33, -0.5, -0.33, 0.33, -0.33, -0.5}, - {-0.33, -0.33, -0.33, 0.33, -0.17, 0.33}, - } }, - light_source = fun_caves.light_max, - groups = {fleshy=1, dig_immediate=3, flammable=2, plant=1}, -}) - --- mushroom stem, giant or huge -minetest.register_node("fun_caves:giant_mushroom_stem", { - description = "Giant Mushroom Stem", - tiles = {"vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png"}, - is_ground_content = false, - groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2, plant=1}, - sounds = default.node_sound_wood_defaults(), - paramtype = "light", - drawtype = "nodebox", - node_box = { type = "fixed", fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, }}, -}) - --- obsidian, glowing -minetest.register_node("fun_caves:glow_obsidian", { - description = "Glowing Obsidian", - tiles = {"caverealms_glow_obsidian.png"}, - is_ground_content = true, - groups = {stone=2, crumbly=1}, - --light_source = 7, - sounds = default.node_sound_stone_defaults({ - footstep = {name="default_stone_footstep", gain=0.25}, - }), -}) - --- obsidian, glowing, 2 - has traces of lava -minetest.register_node("fun_caves:glow_obsidian_2", { - description = "Hot Glow Obsidian", - tiles = {"caverealms_glow_obsidian2.png"}, - is_ground_content = true, - groups = {stone=2, crumbly=1, surface_hot=3, igniter=1}, - damage_per_second = 1, - --light_source = 9, - sounds = default.node_sound_stone_defaults({ - footstep = {name="default_stone_footstep", gain=0.25}, - }), -}) - --- salt -minetest.register_node("fun_caves:stone_with_salt", { - description = "Cave Stone with Salt", - tiles = {"caverealms_salty2.png"}, - paramtype = "light", - use_texture_alpha = true, - drawtype = "glasslike", - sunlight_propagates = false, - is_ground_content = true, - groups = {stone=1, crumbly=3}, - sounds = default.node_sound_glass_defaults(), -}) -newnode = fun_caves.clone_node("fun_caves:stone_with_salt") - --- salt, radioactive ore -newnode.description = "Salt With Radioactive Ore" -newnode.tiles = {"caverealms_salty2.png^[colorize:#004000:250"} -newnode.light_source = 4 -minetest.register_node("fun_caves:radioactive_ore", newnode) - --- What's a cave without speleothems? -local spel = { - {type1="stalactite", type2="stalagmite", tile="default_stone.png"}, - {type1="stalactite_slimy", type2="stalagmite_slimy", tile="default_stone.png^fun_caves_algae.png"}, - {type1="stalactite_mossy", type2="stalagmite_mossy", tile="default_stone.png^fun_caves_moss.png"}, - {type1="icicle_down", type2="icicle_up", desc="Icicle", tile="caverealms_thin_ice.png", drop="default:ice"}, -} - -for _, desc in pairs(spel) do - minetest.register_node("fun_caves:"..desc.type1, { - description = (desc.desc or "Stalactite"), - tiles = {desc.tile}, - is_ground_content = true, - walkable = false, - paramtype = "light", - drop = (desc.drop or "fun_caves:stalactite"), - drawtype = "nodebox", - node_box = { type = "fixed", - fixed = { - {-0.07, 0.0, -0.07, 0.07, 0.5, 0.07}, - {-0.04, -0.25, -0.04, 0.04, 0.0, 0.04}, - {-0.02, -0.5, -0.02, 0.02, 0.25, 0.02}, - } }, - groups = {rock=1, cracky=3}, - sounds = default.node_sound_stone_defaults(), - }) - - minetest.register_node("fun_caves:"..desc.type2, { - description = (desc.desc or "Stalagmite"), - tiles = {desc.tile}, - is_ground_content = true, - walkable = false, - paramtype = "light", - drop = "fun_caves:stalagmite", - drawtype = "nodebox", - node_box = { type = "fixed", - fixed = { - {-0.07, -0.5, -0.07, 0.07, 0.0, 0.07}, - {-0.04, 0.0, -0.04, 0.04, 0.25, 0.04}, - {-0.02, 0.25, -0.02, 0.02, 0.5, 0.02}, - } }, - groups = {rock=1, cracky=3}, - sounds = default.node_sound_stone_defaults(), - }) -end - --- spikes, hot -- silicon-based life -local spike_size = { 1.0, 1.2, 1.4, 1.6, 1.7 } -fun_caves.hot_spikes = {} - -for i in ipairs(spike_size) do - if i == 1 then - nodename = "fun_caves:hot_spike" - else - nodename = "fun_caves:hot_spike_"..i - end - - fun_caves.hot_spikes[#fun_caves.hot_spikes+1] = nodename - - vs = spike_size[i] - - minetest.register_node(nodename, { - description = "Stone Spike", - tiles = {"fun_caves_hot_spike.png"}, - inventory_image = "fun_caves_hot_spike.png", - wield_image = "fun_caves_hot_spike.png", - is_ground_content = true, - groups = {cracky=3, oddly_breakable_by_hand=1, surface_hot=3}, - damage_per_second = 1, - sounds = default.node_sound_stone_defaults(), - paramtype = "light", - drawtype = "plantlike", - walkable = false, - light_source = i * 2, - buildable_to = true, - visual_scale = vs, - selection_box = { - type = "fixed", - fixed = {-0.5*vs, -0.5*vs, -0.5*vs, 0.5*vs, -5/16*vs, 0.5*vs}, - } - }) -end - --- stone with algae -newnode = fun_caves.clone_node("default:stone") -newnode.description = "Cave Stone With Algae" -newnode.tiles = {"default_stone.png^fun_caves_algae.png"} -newnode.groups = {stone=1, crumbly=3} -newnode.sounds = default.node_sound_dirt_defaults({ - footstep = {name="default_grass_footstep", gain=0.25}, -}) -minetest.register_node("fun_caves:stone_with_algae", newnode) - --- stone with lichen -newnode = fun_caves.clone_node("default:stone") -newnode.description = "Cave Stone With Lichen" -newnode.tiles = {"default_stone.png^fun_caves_lichen.png"} -newnode.groups = {stone=1, crumbly=3} -newnode.sounds = default.node_sound_dirt_defaults({ - footstep = {name="default_grass_footstep", gain=0.25}, -}) -minetest.register_node("fun_caves:stone_with_lichen", newnode) - --- stone with moss -newnode = fun_caves.clone_node("default:stone") -newnode.description = "Cave Stone With Moss" -newnode.tiles = {"default_stone.png^fun_caves_moss.png"} -newnode.groups = {stone=1, crumbly=3} -newnode.sounds = default.node_sound_dirt_defaults({ - footstep = {name="default_grass_footstep", gain=0.25}, -}) -minetest.register_node("fun_caves:stone_with_moss", newnode) - - ------------------------------------- --- recipes ------------------------------------- - --- Mushroom stems can be used as wood and leather, --- ala Journey to the Center of the Earth. -minetest.register_craft({ - output = "default:wood", - recipe = { - {"fun_caves:giant_mushroom_stem"} - } -}) - -minetest.register_craft({ - output = "mobs:leather", - recipe = { - {"fun_caves:giant_mushroom_cap"} - } -}) - -minetest.register_craft({ - output = "dye:red", - recipe = { - {"flowers:mushroom_red"} - } -}) - ---minetest.register_craft({ --- output = "dye:yellow", --- recipe = { --- {"flowers:mushroom_brown"} --- } ---}) - -minetest.register_craft({ - output = 'default:paper 6', - recipe = { - {'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem'}, - } -}) - --- Caps can be cooked and eaten. -minetest.register_node("fun_caves:mushroom_steak", { - description = "Mushroom Steak", - drawtype = "plantlike", - paramtype = "light", - tiles = {"vmg_mushroom_steak.png"}, - inventory_image = "vmg_mushroom_steak.png", - on_use = minetest.item_eat(4), - --groups = {dig_immediate = 3, attached_node = 1}, - groups = {dig_immediate = 3}, -}) - -minetest.register_craft({ - type = "cooking", - output = "fun_caves:mushroom_steak", - recipe = "fun_caves:huge_mushroom_cap", - cooktime = 2, -}) - -minetest.register_craft({ - type = "cooking", - output = "fun_caves:mushroom_steak 2", - recipe = "fun_caves:giant_mushroom_cap", - cooktime = 2, -}) - --- moon juice from fungus -minetest.register_craft({ - output = "fun_caves:moon_juice", - recipe = { - {"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"}, - {"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"}, - {"fun_caves:glowing_fungus", "vessels:glass_bottle", "fun_caves:glowing_fungus"}, - }, -}) - -minetest.register_craft({ - output = "fun_caves:moon_glass", - type = "shapeless", - recipe = { - "fun_caves:moon_juice", - "fun_caves:moon_juice", - "default:glass", - }, -}) - -minetest.register_craft({ - output = "fun_caves:glowing_dirt", - type = "shapeless", - recipe = { - "fun_caves:moon_juice", - "default:dirt", - }, -}) - --- Speleothems can be made into cobblestone, to get them out of inventory. -minetest.register_craft({ - output = "default:cobble", - recipe = { - {"", "", ""}, - {"fun_caves:stalactite", "fun_caves:stalactite", ""}, - {"fun_caves:stalactite", "fun_caves:stalactite", ""}, - }, -}) - -minetest.register_craft({ - output = "default:cobble", - recipe = { - {"", "", ""}, - {"fun_caves:stalagmite", "fun_caves:stalagmite", ""}, - {"fun_caves:stalagmite", "fun_caves:stalagmite", ""}, - }, -}) diff --git a/deco_caves.lua b/deco_caves.lua index 43558b5..6ae0a83 100644 --- a/deco_caves.lua +++ b/deco_caves.lua @@ -1,177 +1,430 @@ -dofile(fun_caves.path .. "/deco_cave_nodes.lua") +-- black (oily) sand +local newnode = fun_caves.clone_node("default:sand") +newnode.description = "Black Sand" +newnode.tiles = {"fun_caves_black_sand.png"} +newnode.groups['falling_node'] = 0 +minetest.register_node("fun_caves:black_sand", newnode) -local min_surface = -80 +-- cobble, hot - cobble with lava instead of mortar XD +minetest.register_node("fun_caves:hot_cobble", { + description = "Hot Cobble", + tiles = {"caverealms_hot_cobble.png"}, + is_ground_content = true, + groups = {crumbly=2, surface_hot=3}, + --light_source = 2, + damage_per_second = 1, + sounds = default.node_sound_stone_defaults({ + footstep = {name="default_stone_footstep", gain=0.25}, + }), +}) -function fun_caves.decorate_cave(node, data, area, minp, y, ivm, biome_val_in) - if not (data[ivm] == node("air") or data[ivm] == node("default:stone")) then - return - end +-- dirt, glowing +newnode = fun_caves.clone_node("default:dirt") +newnode.description = "Glowing Dirt" +newnode.light_source = default.LIGHT_MAX +newnode.soil = { + base = "fun_caves:glowing_dirt", + dry = "fun_caves:glowing_soil", + wet = "fun_caves:glowing_soil_wet" +} +minetest.register_node("fun_caves:glowing_dirt", newnode) - local ivm_below = ivm - area.ystride - local ivm_above = ivm + area.ystride - local biome_val = biome_val_in +-- Dirt can become soil. +newnode = fun_caves.clone_node("farming:soil") +newnode.description = "Glowing Soil" +newnode.light_source = default.LIGHT_MAX +newnode.soil = { + base = "fun_caves:glowing_dirt", + dry = "fun_caves:glowing_soil", + wet = "fun_caves:glowing_soil_wet" +} +minetest.register_node("fun_caves:glowing_dirt", newnode) - ------------------- - local stone_type = node("default:stone") - local stone_depth = 1 +-- Dirt to soil to wet soil... +newnode = fun_caves.clone_node("farming:soil_wet") +newnode.description = "Wet Glowing Soil" +newnode.light_source = default.LIGHT_MAX +newnode.soil = { + base = "fun_caves:glowing_dirt", + dry = "fun_caves:glowing_soil", + wet = "fun_caves:glowing_soil_wet" +} +minetest.register_node("fun_caves:glowing_dirt", newnode) - if y > -200 then - biome_val = biome_val / math.max(1, math.log(200 + y)) - end - ------------------- - --biome_val = 0.55 - ------------------- - if biome_val < -0.65 then - stone_type = node("default:ice") - stone_depth = 2 - elseif biome_val < -0.6 then - stone_type = node("fun_caves:thin_ice") - stone_depth = 2 - elseif biome_val < -0.5 then - stone_type = node("fun_caves:stone_with_lichen") - elseif biome_val < -0.3 then - stone_type = node("fun_caves:stone_with_moss") - elseif biome_val < -0.0 then - stone_type = node("fun_caves:stone_with_lichen") - elseif biome_val < 0.2 then - stone_type = node("fun_caves:stone_with_algae") - elseif biome_val < 0.35 then - stone_type = node("fun_caves:stone_with_salt") - stone_depth = 2 - elseif biome_val < 0.5 then - stone_type = node("default:sand") - stone_depth = 2 - elseif biome_val < 0.6 then - stone_type = node("fun_caves:black_sand") - stone_depth = 2 - else - stone_type = node("fun_caves:hot_cobble") - end - -- "glow" +-- flame, constant -- does not expire +minetest.register_node("fun_caves:constant_flame", { + description = "Fire", + drawtype = "plantlike", + tiles = {{ + name="fire_basic_flame_animated.png", + animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=1}, + }}, + inventory_image = "fire_basic_flame.png", + light_source = 14, + groups = {igniter=2,dig_immediate=3,hot=3, not_in_creative_inventory=1}, + drop = '', + walkable = false, + buildable_to = true, + damage_per_second = 4, +}) - local node_below - if y > minp.y then - node_below = data[ivm - area.ystride] - end - local node_above = data[ivm + area.ystride] +-- Glowing fungal stone provides an eerie light. +minetest.register_node("fun_caves:glowing_fungal_stone", { + description = "Glowing Fungal Stone", + tiles = {"default_stone.png^vmg_glowing_fungal.png",}, + is_ground_content = true, + light_source = fun_caves.light_max - 4, + groups = {cracky=3, stone=1}, + drop = {items={ {items={"default:cobble"},}, {items={"fun_caves:glowing_fungus",},},},}, + sounds = default.node_sound_stone_defaults(), +}) - if data[ivm] == node("default:stone") then - local air_above = false - for i = 1, stone_depth do - if data[ivm + area.ystride * i] == node("air") then - air_above = true - end - end +-- Glowing fungus grows underground. +minetest.register_node("fun_caves:glowing_fungus", { + description = "Glowing Fungus", + drawtype = "plantlike", + paramtype = "light", + tiles = {"vmg_glowing_fungus.png"}, + inventory_image = "vmg_glowing_fungus.png", + groups = {dig_immediate = 3}, +}) - if node_above == node("air") and (stone_type == node("fun_caves:stone_with_algae") or stone_type == node("fun_caves:stone_with_lichen")) and math.random(10) == 1 then - return node("dirt") - end +-- moon glass (glows) +local newnode = fun_caves.clone_node("default:glass") +newnode.light_source = default.LIGHT_MAX +minetest.register_node("fun_caves:moon_glass", newnode) - if air_above then - if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then - return node("fun_caves:radioactive_ore") - elseif stone_type == node("fun_caves:black_sand") and math.random(100) == 1 then - return node("default:coalblock") - elseif node_above == node("air") and stone_type == node("fun_caves:stone_with_moss") and math.random(50) == 1 then - return node("fun_caves:glowing_fungal_stone") - else - return stone_type - end - end +-- Moon juice is extracted from glowing fungus, to make glowing materials. +minetest.register_node("fun_caves:moon_juice", { + description = "Moon Juice", + drawtype = "plantlike", + paramtype = "light", + tiles = {"vmg_moon_juice.png"}, + inventory_image = "vmg_moon_juice.png", + --groups = {dig_immediate = 3, attached_node = 1}, + groups = {dig_immediate = 3}, + sounds = default.node_sound_glass_defaults(), +}) - local air_below = false - for i = 1, stone_depth do - if data[ivm - area.ystride * i] == node("air") then - air_below = true - end - end +-- mushroom cap, giant +minetest.register_node("fun_caves:giant_mushroom_cap", { + description = "Giant Mushroom Cap", + tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"}, + is_ground_content = false, + paramtype = "light", + drawtype = "nodebox", + node_box = { type = "fixed", + fixed = { + {-0.4, -0.5, -0.4, 0.4, 0.0, 0.4}, + {-0.75, -0.5, -0.4, -0.4, -0.25, 0.4}, + {0.4, -0.5, -0.4, 0.75, -0.25, 0.4}, + {-0.4, -0.5, -0.75, 0.4, -0.25, -0.4}, + {-0.4, -0.5, 0.4, 0.4, -0.25, 0.75}, + } }, + light_source = fun_caves.light_max, + groups = {fleshy=1, dig_immediate=3, flammable=2, plant=1}, +}) - if data[ivm] == node("default:stone") and air_below then - if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then - return node("fun_caves:radioactive_ore") - elseif stone_type == node("fun_caves:black_sand") and math.random(100) == 1 then - return node("default:coalblock") - elseif node_below == node("air") and (stone_type == node("fun_caves:stone_with_lichen") or stone_type == node("fun_caves:stone_with_moss")) and math.random(50) == 1 then - return node("fun_caves:glowing_fungal_stone") - else - return stone_type - end - end - end +-- mushroom cap, huge +minetest.register_node("fun_caves:huge_mushroom_cap", { + description = "Huge Mushroom Cap", + tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"}, + is_ground_content = false, + paramtype = "light", + drawtype = "nodebox", + node_box = { type = "fixed", + fixed = { + {-0.5, -0.5, -0.33, 0.5, -0.33, 0.33}, + {-0.33, -0.5, 0.33, 0.33, -0.33, 0.5}, + {-0.33, -0.5, -0.33, 0.33, -0.33, -0.5}, + {-0.33, -0.33, -0.33, 0.33, -0.17, 0.33}, + } }, + light_source = fun_caves.light_max, + groups = {fleshy=1, dig_immediate=3, flammable=2, plant=1}, +}) - if data[ivm] == node("air") then - local sr = math.random(1000) +-- mushroom stem, giant or huge +minetest.register_node("fun_caves:giant_mushroom_stem", { + description = "Giant Mushroom Stem", + tiles = {"vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png"}, + is_ground_content = false, + groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2, plant=1}, + sounds = default.node_sound_wood_defaults(), + paramtype = "light", + drawtype = "nodebox", + node_box = { type = "fixed", fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, }}, +}) - -- hanging down - if node_above == node("default:stone") and sr < 80 then - if stone_type == node("default:ice") then - return node("fun_caves:icicle_down") - elseif stone_type == node("fun_caves:stone_with_algae") then - return node("fun_caves:stalactite_slimy") - elseif stone_type == node("fun_caves:stone_with_moss") then - return node("fun_caves:stalactite_mossy") - elseif stone_type == node("fun_caves:stone_with_lichen") then - return node("fun_caves:stalactite") - elseif stone_type == node("default:stone") then - return node("fun_caves:stalactite") - end - end +-- obsidian, glowing +minetest.register_node("fun_caves:glow_obsidian", { + description = "Glowing Obsidian", + tiles = {"caverealms_glow_obsidian.png"}, + is_ground_content = true, + groups = {stone=2, crumbly=1}, + --light_source = 7, + sounds = default.node_sound_stone_defaults({ + footstep = {name="default_stone_footstep", gain=0.25}, + }), +}) - -- fluids - if y > minp.y and (node_below == node("default:stone") or node_below == node("fun_caves:hot_cobble")) and sr < 3 then - return node("default:lava_source") - elseif node_below == node("fun_caves:stone_with_moss") and sr < 3 then - return node("default:water_source") +-- obsidian, glowing, 2 - has traces of lava +minetest.register_node("fun_caves:glow_obsidian_2", { + description = "Hot Glow Obsidian", + tiles = {"caverealms_glow_obsidian2.png"}, + is_ground_content = true, + groups = {stone=2, crumbly=1, surface_hot=3, igniter=1}, + damage_per_second = 1, + --light_source = 9, + sounds = default.node_sound_stone_defaults({ + footstep = {name="default_stone_footstep", gain=0.25}, + }), +}) - -- standing up - elseif node_below == node("default:ice") and sr < 80 then - return node("fun_caves:icicle_up") - elseif node_below == node("fun_caves:stone_with_algae") and sr < 80 then - return node("fun_caves:stalagmite_slimy") - elseif node_below == node("fun_caves:stone_with_moss") and sr < 80 then - return node("fun_caves:stalagmite_mossy") - elseif node_below == node("fun_caves:stone_with_lichen") and sr < 80 then - return node("fun_caves:stalagmite") - elseif node_below == node("default:stone") and sr < 80 then - return node("fun_caves:stalagmite") - elseif node_below == node("fun_caves:hot_cobble") and sr < 80 then - if sr <= 20 then - return node("fun_caves:hot_spike") - else - return node("fun_caves:hot_spike_"..math.ceil(sr / 20)) - end - elseif node_below == node("fun_caves:black_sand") and sr < 20 then - return node("fun_caves:constant_flame") +-- salt +minetest.register_node("fun_caves:stone_with_salt", { + description = "Cave Stone with Salt", + tiles = {"caverealms_salty2.png"}, + paramtype = "light", + use_texture_alpha = true, + drawtype = "glasslike", + sunlight_propagates = false, + is_ground_content = true, + groups = {stone=1, crumbly=3}, + sounds = default.node_sound_glass_defaults(), +}) +newnode = fun_caves.clone_node("fun_caves:stone_with_salt") - -- vegetation - elseif node_below == node("default:dirt") and (stone_type == node("fun_caves:stone_with_lichen") or stone_type == node("fun_caves:stone_with_algae")) and biome_val >= -0.5 then - if sr < 110 then - return node("flowers:mushroom_red") - elseif sr < 220 then - return node("flowers:mushroom_brown") - elseif node_above == node("air") and sr < 330 then - return node("fun_caves:giant_mushroom_stem") - elseif sr < 360 then - local air_count = 0 - local j - for i = 1, 12 do - j = ivm + area.ystride * i - if j <= #data and data[j] == node("air") then - air_count = air_count + 1 - end - end - if air_count > 5 then - fun_caves.make_fungal_tree(data, area, ivm, math.random(2,math.min(air_count, 12))) - end - end - elseif node_below == node("fun_caves:giant_mushroom_stem") and data[ivm - area.ystride * 2] == node("fun_caves:giant_mushroom_stem") then - return node("fun_caves:giant_mushroom_cap") - elseif node_below == node("fun_caves:giant_mushroom_stem") then - if node_above == node("air") and math.random(3) == 1 then - return node("fun_caves:giant_mushroom_stem") - else - return node("fun_caves:huge_mushroom_cap") - end - end - end +-- salt, radioactive ore +newnode.description = "Salt With Radioactive Ore" +newnode.tiles = {"caverealms_salty2.png^[colorize:#004000:250"} +newnode.light_source = 4 +minetest.register_node("fun_caves:radioactive_ore", newnode) + +-- What's a cave without speleothems? +local spel = { + {type1="stalactite", type2="stalagmite", tile="default_stone.png"}, + {type1="stalactite_slimy", type2="stalagmite_slimy", tile="default_stone.png^fun_caves_algae.png"}, + {type1="stalactite_mossy", type2="stalagmite_mossy", tile="default_stone.png^fun_caves_moss.png"}, + {type1="icicle_down", type2="icicle_up", desc="Icicle", tile="caverealms_thin_ice.png", drop="default:ice"}, +} + +for _, desc in pairs(spel) do + minetest.register_node("fun_caves:"..desc.type1, { + description = (desc.desc or "Stalactite"), + tiles = {desc.tile}, + is_ground_content = true, + walkable = false, + paramtype = "light", + drop = (desc.drop or "fun_caves:stalactite"), + drawtype = "nodebox", + node_box = { type = "fixed", + fixed = { + {-0.07, 0.0, -0.07, 0.07, 0.5, 0.07}, + {-0.04, -0.25, -0.04, 0.04, 0.0, 0.04}, + {-0.02, -0.5, -0.02, 0.02, 0.25, 0.02}, + } }, + groups = {rock=1, cracky=3}, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node("fun_caves:"..desc.type2, { + description = (desc.desc or "Stalagmite"), + tiles = {desc.tile}, + is_ground_content = true, + walkable = false, + paramtype = "light", + drop = "fun_caves:stalagmite", + drawtype = "nodebox", + node_box = { type = "fixed", + fixed = { + {-0.07, -0.5, -0.07, 0.07, 0.0, 0.07}, + {-0.04, 0.0, -0.04, 0.04, 0.25, 0.04}, + {-0.02, 0.25, -0.02, 0.02, 0.5, 0.02}, + } }, + groups = {rock=1, cracky=3}, + sounds = default.node_sound_stone_defaults(), + }) end + +-- spikes, hot -- silicon-based life +local spike_size = { 1.0, 1.2, 1.4, 1.6, 1.7 } +fun_caves.hot_spikes = {} + +for i in ipairs(spike_size) do + if i == 1 then + nodename = "fun_caves:hot_spike" + else + nodename = "fun_caves:hot_spike_"..i + end + + fun_caves.hot_spikes[#fun_caves.hot_spikes+1] = nodename + + vs = spike_size[i] + + minetest.register_node(nodename, { + description = "Stone Spike", + tiles = {"fun_caves_hot_spike.png"}, + inventory_image = "fun_caves_hot_spike.png", + wield_image = "fun_caves_hot_spike.png", + is_ground_content = true, + groups = {cracky=3, oddly_breakable_by_hand=1, surface_hot=3}, + damage_per_second = 1, + sounds = default.node_sound_stone_defaults(), + paramtype = "light", + drawtype = "plantlike", + walkable = false, + light_source = i * 2, + buildable_to = true, + visual_scale = vs, + selection_box = { + type = "fixed", + fixed = {-0.5*vs, -0.5*vs, -0.5*vs, 0.5*vs, -5/16*vs, 0.5*vs}, + } + }) +end + +-- stone with algae +newnode = fun_caves.clone_node("default:stone") +newnode.description = "Cave Stone With Algae" +newnode.tiles = {"default_stone.png^fun_caves_algae.png"} +newnode.groups = {stone=1, crumbly=3} +newnode.sounds = default.node_sound_dirt_defaults({ + footstep = {name="default_grass_footstep", gain=0.25}, +}) +minetest.register_node("fun_caves:stone_with_algae", newnode) + +-- stone with lichen +newnode = fun_caves.clone_node("default:stone") +newnode.description = "Cave Stone With Lichen" +newnode.tiles = {"default_stone.png^fun_caves_lichen.png"} +newnode.groups = {stone=1, crumbly=3} +newnode.sounds = default.node_sound_dirt_defaults({ + footstep = {name="default_grass_footstep", gain=0.25}, +}) +minetest.register_node("fun_caves:stone_with_lichen", newnode) + +-- stone with moss +newnode = fun_caves.clone_node("default:stone") +newnode.description = "Cave Stone With Moss" +newnode.tiles = {"default_stone.png^fun_caves_moss.png"} +newnode.groups = {stone=1, crumbly=3} +newnode.sounds = default.node_sound_dirt_defaults({ + footstep = {name="default_grass_footstep", gain=0.25}, +}) +minetest.register_node("fun_caves:stone_with_moss", newnode) + + +------------------------------------ +-- recipes +------------------------------------ + +-- Mushroom stems can be used as wood and leather, +-- ala Journey to the Center of the Earth. +minetest.register_craft({ + output = "default:wood", + recipe = { + {"fun_caves:giant_mushroom_stem"} + } +}) + +minetest.register_craft({ + output = "mobs:leather", + recipe = { + {"fun_caves:giant_mushroom_cap"} + } +}) + +minetest.register_craft({ + output = "dye:red", + recipe = { + {"flowers:mushroom_red"} + } +}) + +--minetest.register_craft({ +-- output = "dye:yellow", +-- recipe = { +-- {"flowers:mushroom_brown"} +-- } +--}) + +minetest.register_craft({ + output = 'default:paper 6', + recipe = { + {'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem'}, + } +}) + +-- Caps can be cooked and eaten. +minetest.register_node("fun_caves:mushroom_steak", { + description = "Mushroom Steak", + drawtype = "plantlike", + paramtype = "light", + tiles = {"vmg_mushroom_steak.png"}, + inventory_image = "vmg_mushroom_steak.png", + on_use = minetest.item_eat(4), + --groups = {dig_immediate = 3, attached_node = 1}, + groups = {dig_immediate = 3}, +}) + +minetest.register_craft({ + type = "cooking", + output = "fun_caves:mushroom_steak", + recipe = "fun_caves:huge_mushroom_cap", + cooktime = 2, +}) + +minetest.register_craft({ + type = "cooking", + output = "fun_caves:mushroom_steak 2", + recipe = "fun_caves:giant_mushroom_cap", + cooktime = 2, +}) + +-- moon juice from fungus +minetest.register_craft({ + output = "fun_caves:moon_juice", + recipe = { + {"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"}, + {"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"}, + {"fun_caves:glowing_fungus", "vessels:glass_bottle", "fun_caves:glowing_fungus"}, + }, +}) + +minetest.register_craft({ + output = "fun_caves:moon_glass", + type = "shapeless", + recipe = { + "fun_caves:moon_juice", + "fun_caves:moon_juice", + "default:glass", + }, +}) + +minetest.register_craft({ + output = "fun_caves:glowing_dirt", + type = "shapeless", + recipe = { + "fun_caves:moon_juice", + "default:dirt", + }, +}) + +-- Speleothems can be made into cobblestone, to get them out of inventory. +minetest.register_craft({ + output = "default:cobble", + recipe = { + {"", "", ""}, + {"fun_caves:stalactite", "fun_caves:stalactite", ""}, + {"fun_caves:stalactite", "fun_caves:stalactite", ""}, + }, +}) + +minetest.register_craft({ + output = "default:cobble", + recipe = { + {"", "", ""}, + {"fun_caves:stalagmite", "fun_caves:stalagmite", ""}, + {"fun_caves:stalagmite", "fun_caves:stalagmite", ""}, + }, +}) diff --git a/deco_water.lua b/deco_water.lua deleted file mode 100644 index cb5d13e..0000000 --- a/deco_water.lua +++ /dev/null @@ -1,99 +0,0 @@ -local light_depth = -13 -local water_level = 1 - -local water_lily_biomes = {} -for _, i in pairs({"rainforest_swamp", "rainforest", "savanna_swamp", "savanna", "deciduous_forest_swamp", "deciduous_forest", "desertstone_grassland", }) do - water_lily_biomes[i] = true -end -local coral_biomes = {} -for _, i in pairs({"desert_ocean", "savanna_ocean", "rainforest_ocean", }) do - coral_biomes[i] = true -end - -plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = 33, octaves = 3, persist = 0.7, lacunarity = 2.0} - -local function surround(node, data, area, ivm) - -- Check to make sure that a plant root is fully surrounded. - -- This is due to the kludgy way you have to make water plants - -- in minetest, to avoid bubbles. - for x1 = -1,1,2 do - local n = data[ivm+x1] - if n == node("default:river_water_source") or n == node("default:water_source") or n == node("air") then - return false - end - end - for z1 = -area.zstride,area.zstride,2*area.zstride do - local n = data[ivm+z1] - if n == node("default:river_water_source") or n == node("default:water_source") or n == node("air") then - return false - end - end - - return true -end - -local node_match_cache = {} - -function fun_caves.decorate_water(node, data, area, minp, maxp, pos, ivm, biome_in, pn) - if pos.y < light_depth then - return - end - - local biome = biome_in - - local node_below = data[ivm - area.ystride] - local node_above = data[ivm + area.ystride] - - local inside = false - if pos.x < maxp.x and pos.y < maxp.y and pos.z < maxp.z and pos.x > minp.x and pos.y > minp.y and pos.z > minp.z then - inside = true - end - - if pos.y < water_level and data[ivm] == node("default:sand") and node_above == node("default:water_source") and data[ivm + area.ystride * 2] == node("default:water_source") and coral_biomes[biome] and pn < -0.1 and math.random(5) == 1 and surround(node, data, area, ivm) then - return node("fun_caves:staghorn_coral_water_sand") - elseif pos.y < water_level and node_below == node("default:sand") and node_above == node("default:water_source") and data[ivm] == node("default:water_source") and coral_biomes[biome] and pn < -0.1 and math.random(5) < 3 then - local sr = math.random(65) - if sr < 4 then - return node("fun_caves:brain_coral") - elseif sr < 6 then - return node("fun_caves:dragon_eye") - elseif sr < 65 then - return node("fun_caves:pillar_coral") - end - elseif inside and (node_above == node("default:water_source") or node_above == node("default:river_water_source")) and (data[ivm] == node("default:sand") or data[ivm] == node("default:dirt")) then - -- Check the biomes and plant water plants, if called for. - if not surround(node, data, area, ivm) then - return - end - - for _, desc in pairs(fun_caves.water_plants) do - if desc.content_id then - if not node_match_cache[desc.content_id] then - node_match_cache[desc.content_id] = {} - end - - if not node_match_cache[desc.content_id][data[ivm]] then - -- This is a great way to match all node type strings - -- against a given node (or nodes). However, it's slow. - -- To speed it up, we cache the results for each plant - -- on each node, and avoid calling find_nodes every time. - local posm, count = minetest.find_nodes_in_area(pos, pos, desc.place_on) - if #posm > 0 then - node_match_cache[desc.content_id][data[ivm]] = "good" - else - node_match_cache[desc.content_id][data[ivm]] = "bad" - end - end - - if node_match_cache[desc.content_id][data[ivm]] == "good" and desc.fill_ratio and (not desc.biomes or (biome and desc.biomes and table.contains(desc.biomes, biome))) and math.random() <= desc.fill_ratio then - return desc.content_id - end - end - end - elseif pos.y > minp.y and node_below == node("default:river_water_source") and data[ivm] == node("air") and water_lily_biomes[biome] and pn > 0.5 and math.random(15) == 1 then - -- on top of the water - -- I haven't figured out what the decoration manager is - -- doing with the noise functions, but this works ok. - return node("flowers:waterlily") - end -end diff --git a/depends.txt b/depends.txt index b59b69a..cc779d1 100644 --- a/depends.txt +++ b/depends.txt @@ -1,7 +1,7 @@ default flowers wool -mobs -mobs_monster +mobs? +mobs_monster? mobs_slimes? mobs_creeper? diff --git a/fortress.lua b/fortress.lua deleted file mode 100644 index 3189ade..0000000 --- a/fortress.lua +++ /dev/null @@ -1,85 +0,0 @@ --- invisible maze --- hungry maze --- chests (w traps) --- step traps (math based) --- hidden doors/downs --- hot/ice floors - -fun_caves.fortress = function(node, data, area, minp, maxp, level) - local n = 16 - local walls = {} - local floor = node('fun_caves:dungeon_floor_1') - local outer_wall = node('fun_caves:dungeon_wall_2') - local inner_wall = node('fun_caves:dungeon_wall_1') - - for y2 = 0, n-1 do - --for y2 = 0, 0 do - -- walls is zero-based. - for i = 0, 2 * n * n - 1 do - walls[i] = i - end - table.shuffle(walls) - - local dox, doz = math.random(0, n-1), math.random(0, n-1) - for z = minp.z, maxp.z do - for y = minp.y + y2 * 5, minp.y + y2 * 5 + 4 do - local ivm = area:index(minp.x, y, z) - for x = minp.x, maxp.x do - if (y - minp.y) % 5 == 0 then - if math.floor((z - minp.z) / 5) == doz and math.floor((x - minp.x) / 5) == dox and (z - minp.z) % 5 ~= 0 and (x - minp.x) % 5 ~= 0 and y ~= minp.y then - data[ivm] = node("air") - else - data[ivm] = floor - end - elseif x == minp.x or z == minp.z or x == maxp.x or z == maxp.z then - data[ivm] = outer_wall - elseif (z - minp.z) % 5 == 0 or (x - minp.x) % 5 == 0 then - data[ivm] = inner_wall - else - data[ivm] = node("air") - end - ivm = ivm + 1 - end - end - end - - local set = unionfind(n * n) - - for m = 0, #walls do - local c = walls[m] - local a = math.floor(c / 2) - local i = a % n - local j = math.floor(a / n) - local u = c % 2 == 0 and 1 or 0 - local v = c % 2 == 1 and 1 or 0 - local b = a + u + n * v - if i < n - u and j < n - v and set:find(a) ~= set:find(b) then - set:union(a, b) - local x = (i + u) * 5 + minp.x - local y = minp.y + y2 * 5 - local z = (j + v) * 5 + minp.z - --if y > minp.y and math.random(20) == 1 then - -- for z1 = z + 1, z + 4 do - -- ivm = area:index(x+1, y, z1) - -- for x1 = x + 1, x + 4 do - -- data[ivm] = node("air") - -- ivm = ivm + 1 - -- end - -- end - --end - - for z1 = z + (1-v), z + (1-v) * 4 do - for y1 = y + 1, y + 4 do - local ivm = area:index(x + (1-u), y1, z1) - for x1 = x + (1-u), x + (1-u) * 4 do - if x1 < maxp.x and z1 < maxp.z and x1 > minp.x and z1 > minp.z then - data[ivm] = node("air") - end - ivm = ivm + 1 - end - end - end - end - end - end -end diff --git a/fungal_tree.lua b/fungal_tree.lua index 35d8d19..93a8cc0 100644 --- a/fungal_tree.lua +++ b/fungal_tree.lua @@ -114,76 +114,3 @@ minetest.register_craft({ {"flowers:mushroom_brown"} } }) - - -local leaves = {} -for _, leaf in pairs(fungal_tree_leaves) do - leaves[leaf] = true -end - -local get_node_light = minetest.get_node_light -local remove_node = minetest.remove_node -local set_node = minetest.set_node -local get_node_or_nil = minetest.get_node_or_nil - --- fungal spread -minetest.register_abm({ - nodenames = fungal_tree_leaves, - neighbors = {"air", "group:liquid"}, - interval = 2 * fun_caves.time_factor, - chance = 10, - catch_up = false, - action = function(pos, node) - if get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then - remove_node(pos) - return - end - - local grow_pos = {x=pos.x, y=pos.y-1, z=pos.z} - local grow_node = get_node_or_nil(grow_pos) - if grow_node and grow_node.name == "air" then - set_node(grow_pos, {name = node.name}) - return - end - - grow_pos = {x=rand(-1,1)+pos.x, y=rand(-1,1)+pos.y, z=rand(-1,1)+pos.z} - grow_node = get_node_or_nil(grow_pos) - if grow_node and grow_node.name == "air" and get_node_light(grow_pos, nil) <= fun_caves.light_max then - set_node(grow_pos, {name = node.name}) - return - elseif grow_node and leaves[grow_node.name] and grow_node.name ~= node.name then - set_node(grow_pos, {name = 'air'}) - return - end - - if rand(40) == 1 then - set_node(pos, {name = "fun_caves:fungal_tree_fruit"}) - return - end - - if rand(100) == 1 then - set_node(pos, {name = fungal_tree_leaves[rand(#fungal_tree_leaves)]}) - return - end - end -}) - --- new fungi -minetest.register_abm({ - nodenames = {"default:dirt"}, - neighbors = {"air"}, - interval = 20 * fun_caves.time_factor, - chance = 25, - action = function(pos, node) - if pos.y > 0 then - return - end - - local grow_pos = {x=pos.x, y=pos.y+1, z=pos.z} - local grow_node = get_node_or_nil(grow_pos) - if grow_node and grow_node.name == "air" and (get_node_light(grow_pos, nil) or 99) <= fun_caves.light_max then - set_node(grow_pos, {name = fungal_tree_leaves[rand(#fungal_tree_leaves)]}) - return - end - end -}) diff --git a/init.lua b/init.lua index a476234..dfae1f1 100644 --- a/init.lua +++ b/init.lua @@ -54,6 +54,8 @@ dofile(fun_caves.path .. "/unionfind.lua") dofile(fun_caves.path .. "/nodes.lua") dofile(fun_caves.path .. "/deco.lua") dofile(fun_caves.path .. "/fungal_tree.lua") -dofile(fun_caves.path .. "/fortress.lua") dofile(fun_caves.path .. "/mapgen.lua") -dofile(fun_caves.path .. "/mobs.lua") + +if mobs and mobs.mod == "redo" then + dofile(fun_caves.path .. "/mobs.lua") +end diff --git a/mapgen.lua b/mapgen.lua index 61d2541..e66a90e 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -1,7 +1,27 @@ local DEBUG = false -local floor = math.floor -local ceil = math.ceil +local deco_depth = -30 -- place cave stuff this far beneath the surface +local light_depth = -13 -- depth above which to place corals/sea plants +local water_level = 1 +local fortress_depth = -3 -- close to y / 80 +local max_depth = 31000 +local cave_width = 0.05 -- figurative width +local fluid_compression = -200 -- the depth to start planting lava/water +local dirt_ratio = 10 -- place this many stones for every dirt in caves +local radioactive_ratio = 500 -- place this much salt for every radioactive ore +local coalblock_ratio = 100 -- place this many sand for every coalblock +local fungal_stone_ratio = 50 -- place this many stones for every glowing fungus +local water_lily_ratio = 15 -- place this many water for every lily + +local water_lily_biomes = {} +for _, i in pairs({"rainforest_swamp", "rainforest", "savanna_swamp", "savanna", "deciduous_forest_swamp", "deciduous_forest", "desertstone_grassland", }) do + water_lily_biomes[i] = true +end +local coral_biomes = {} +for _, i in pairs({"desert_ocean", "savanna_ocean", "rainforest_ocean", }) do + coral_biomes[i] = true +end + local cave_noise_1 = {offset = 0, scale = 1, seed = 3901, spread = {x = 40, y = 10, z = 40}, octaves = 3, persist = 1, lacunarity = 2} local cave_noise_2 = {offset = 0, scale = 1, seed = -8402, spread = {x = 40, y = 20, z = 40}, octaves = 3, persist = 1, lacunarity = 2} @@ -9,34 +29,35 @@ local cave_noise_3 = {offset = 15, scale = 10, seed = 3721, spread = {x = 40, y local seed_noise = {offset = 0, scale = 32768, seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, persist = 0.4, lacunarity = 2} local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = 903, octaves = 3, persist = 0.5, lacunarity = 2.0} local fortress_noise = {offset = 0, scale = 1, seed = -4082, spread = {x = 7, y = 7, z = 7}, octaves = 4, persist = 1, lacunarity = 2} +local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = 33, octaves = 3, persist = 0.7, lacunarity = 2.0} -local node_cache = {} -local function get_node(name) - if not node_cache then - node_cache = {} - end +-- These may speed up function access. +local rand = math.random +local max = math.max +local min = math.min +local log = math.log +local ceil = math.ceil +local floor = math.floor +local find_nodes_in_area = minetest.find_nodes_in_area - if not node_cache[name] then - node_cache[name] = minetest.get_content_id(name) - if name ~= "ignore" and node_cache[name] == 127 then - print("*** Failure to find node: "..name) - end - end - - return node_cache[name] -end - -local node = get_node -local deco_depth = 30 +-- This tables looks up nodes that aren't already stored. +local node = setmetatable({}, { + __index = function(t, k) + t[k] = minetest.get_content_id(k) + return t[k] + end}) local data = {} --local p2data = {} -- vm rotation data buffer +local node_match_cache = {} + -- Create a table of biome ids, so I can use the biomemap. +local get_biome_id = minetest.get_biome_id local biome_ids = {} for name, desc in pairs(minetest.registered_biomes) do - biome_ids[minetest.get_biome_id(desc.name)] = desc.name + biome_ids[get_biome_id(desc.name)] = desc.name end --local function place_schematic(pos, schem, center) @@ -76,7 +97,7 @@ end -- if yslice[y] or 255 >= math.random(255) then -- local prob = schem.data[isch].prob or schem.data[isch].param1 or 255 -- if prob >= math.random(255) and schem.data[isch].name ~= "air" then --- data[ivm] = node(schem.data[isch].name) +-- data[ivm] = node[schem.data[isch].name] -- end -- local param2 = schem.data[isch].param2 or 0 -- p2data[ivm] = param2 @@ -106,18 +127,43 @@ end -- end --end +local function surround(node, data, area, ivm) + -- Check to make sure that a plant root is fully surrounded. + -- This is due to the kludgy way you have to make water plants + -- in minetest, to avoid bubbles. + for x1 = -1,1,2 do + local n = data[ivm+x1] + if n == node["default:river_water_source"] or n == node["default:water_source"] or n == node["air"] then + return false + end + end + for z1 = -area.zstride,area.zstride,2*area.zstride do + local n = data[ivm+z1] + if n == node["default:river_water_source"] or n == node["default:water_source"] or n == node["air"] then + return false + end + end + + return true +end + fun_caves.is_fortress = function(pos, cs, debug) -- Fix this to get csize, somehow. + -- Remember that this function may be called + -- before any chunks are generated. local cs = cs or {x=80, y=80, z=80} + local offset = floor(cs.y / 2) - 8 + 1 - local y = floor((pos.y + 33) / cs.y) + local y = floor((pos.y + offset) / cs.y) - if y > -3 or (pos.y + 33) % cs.y > cs.y - 5 then + -- Fortresses show up below ground. + -- Calls from the first dungeon level should return false. + if y > fortress_depth or (pos.y + offset) % cs.y > cs.y - 5 then return false end - local x = floor((pos.x + 33) / cs.x) - local z = floor((pos.z + 33) / cs.z) + local x = floor((pos.x + offset) / cs.x) + local z = floor((pos.z + offset) / cs.z) local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z}) if debug then @@ -142,20 +188,111 @@ local function generate(p_minp, p_maxp, seed) local csize = vector.add(vector.subtract(maxp, minp), 1) local noise_area = VoxelArea:new({MinEdge={x=0,y=0,z=0}, MaxEdge=vector.subtract(csize, 1)}) - local write = false - -- use the same seed (based on perlin noise). math.randomseed(minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})) - local fortress = maxp.y / 3100 + local write = false if fun_caves.is_fortress(minp, csize) then - fun_caves.fortress(node, data, area, minp, maxp, ceil(maxp.y / 3100)) write = true + -------------------------------------------------------------- + -- fortress decoration non-loop -- only there to enable breaks + -- Remove this loop to eliminate fortress decorations. + -------------------------------------------------------------- + for deco_non_loop = 1, 1 do + -- invisible maze + -- hungry maze + -- chests (w traps) + -- step traps (math based) + -- hidden doors/downs + -- hot/ice floors + -- + --local level = ceil(maxp.y / 3100) + local n = 16 + local walls = {} + local floor = node['fun_caves:dungeon_floor_1'] + local outer_wall = node['fun_caves:dungeon_wall_2'] + local inner_wall = node['fun_caves:dungeon_wall_1'] + + for y2 = 0, n-1 do + --for y2 = 0, 0 do + -- walls is zero-based. + for i = 0, 2 * n * n - 1 do + walls[i] = i + end + table.shuffle(walls) + + local dox, doz = math.random(0, n-1), math.random(0, n-1) + for z = minp.z, maxp.z do + for y = minp.y + y2 * 5, minp.y + y2 * 5 + 4 do + local ivm = area:index(minp.x, y, z) + for x = minp.x, maxp.x do + if (y - minp.y) % 5 == 0 then + if math.floor((z - minp.z) / 5) == doz and math.floor((x - minp.x) / 5) == dox and (z - minp.z) % 5 ~= 0 and (x - minp.x) % 5 ~= 0 and y ~= minp.y then + data[ivm] = node["air"] + else + data[ivm] = floor + end + elseif x == minp.x or z == minp.z or x == maxp.x or z == maxp.z then + data[ivm] = outer_wall + elseif (z - minp.z) % 5 == 0 or (x - minp.x) % 5 == 0 then + data[ivm] = inner_wall + else + data[ivm] = node["air"] + end + ivm = ivm + 1 + end + end + end + + local set = unionfind(n * n) + + for m = 0, #walls do + local c = walls[m] + local a = math.floor(c / 2) + local i = a % n + local j = math.floor(a / n) + local u = c % 2 == 0 and 1 or 0 + local v = c % 2 == 1 and 1 or 0 + local b = a + u + n * v + if i < n - u and j < n - v and set:find(a) ~= set:find(b) then + set:union(a, b) + local x = (i + u) * 5 + minp.x + local y = minp.y + y2 * 5 + local z = (j + v) * 5 + minp.z + --if y > minp.y and math.random(20) == 1 then + -- for z1 = z + 1, z + 4 do + -- ivm = area:index(x+1, y, z1) + -- for x1 = x + 1, x + 4 do + -- data[ivm] = node["air"] + -- ivm = ivm + 1 + -- end + -- end + --end + + for z1 = z + (1-v), z + (1-v) * 4 do + for y1 = y + 1, y + 4 do + local ivm = area:index(x + (1-u), y1, z1) + for x1 = x + (1-u), x + (1-u) * 4 do + if x1 < maxp.x and z1 < maxp.z and x1 > minp.x and z1 > minp.z then + data[ivm] = node["air"] + end + ivm = ivm + 1 + end + end + end + end + end + end + end + ----------------------------------------------------- + -- end of fortress decoration non-loop + ----------------------------------------------------- else local cave_1 = minetest.get_perlin_map(cave_noise_1, csize):get3dMap_flat(minp) local cave_2 = minetest.get_perlin_map(cave_noise_2, csize):get3dMap_flat(minp) local cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) local biome_n = minetest.get_perlin_map(biome_noise, csize):get3dMap_flat(minp) + local plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) local index = 0 @@ -167,17 +304,17 @@ local function generate(p_minp, p_maxp, seed) local ivm = area:index(x, minp.y, z) local height = heightmap[index] - if height >= maxp.y - 1 and data[area:index(x, maxp.y, z)] ~= node('air') then - height = 31000 + if height >= maxp.y - 1 and data[area:index(x, maxp.y, z)] ~= node['air'] then + height = max_depth heightmap[index] = height elseif height <= minp.y then - height = -31000 + height = -max_depth heightmap[index] = height end for y = minp.y, maxp.y do - if data[ivm] ~= node('air') and y < height - cave_3[index] and cave_1[index3d] * cave_2[index3d] > 0.05 then - data[ivm] = node("air") + if data[ivm] ~= node['air'] and y < height - cave_3[index] and cave_1[index3d] * cave_2[index3d] > cave_width then + data[ivm] = node["air"] write = true if y > 0 and cave_3[index] < 1 and y == height then @@ -185,8 +322,9 @@ local function generate(p_minp, p_maxp, seed) local ivm2 = ivm for y2 = y + 1, maxp.y + 8 do ivm2 = ivm2 + area.ystride - if data[ivm2] ~= node("default:water_source") then - data[ivm2] = node("air") + if data[ivm2] ~= node["default:water_source"] then + data[ivm2] = node["air"] + write = true end end end @@ -210,25 +348,330 @@ local function generate(p_minp, p_maxp, seed) local height = heightmap[index] for y = minp.y, maxp.y do - if y <= height - deco_depth and (height < 31000 or y < 0) then - local new_node = fun_caves.decorate_cave(node, data, area, minp, y, ivm, biome_n[index3d]) - if new_node then - data[ivm] = new_node - write = true + if y <= height + deco_depth and (height < max_depth or y < 0) then + ---------------------------------------------------------- + -- cave decoration non-loop -- only there to enable breaks + -- Remove this loop to eliminate cave decorations. + ---------------------------------------------------------- + for deco_non_loop = 1, 1 do + if not (data[ivm] == node["air"] or data[ivm] == node["default:stone"]) then + break + end + + local biome_val = biome_n[index3d] + local stone_type = node["default:stone"] + local stone_depth = 1 + + -- Compress biomes at the surface to avoid fluids. + if y > fluid_compression then + biome_val = biome_val / max(1, log(y - fluid_compression)) + end + ------------------- + --biome_val = 0.55 + ------------------- + if biome_val < -0.65 then + stone_type = node["default:ice"] + stone_depth = 2 + elseif biome_val < -0.6 then + stone_type = node["fun_caves:thin_ice"] + stone_depth = 2 + elseif biome_val < -0.5 then + stone_type = node["fun_caves:stone_with_lichen"] + elseif biome_val < -0.3 then + stone_type = node["fun_caves:stone_with_moss"] + elseif biome_val < -0.0 then + stone_type = node["fun_caves:stone_with_lichen"] + elseif biome_val < 0.2 then + stone_type = node["fun_caves:stone_with_algae"] + elseif biome_val < 0.35 then + stone_type = node["fun_caves:stone_with_salt"] + stone_depth = 2 + elseif biome_val < 0.5 then + stone_type = node["default:sand"] + stone_depth = 2 + elseif biome_val < 0.6 then + stone_type = node["fun_caves:black_sand"] + stone_depth = 2 + else + stone_type = node["fun_caves:hot_cobble"] + end + -- "glow" + + local node_below + if y > minp.y then + node_below = data[ivm - area.ystride] + end + local node_above = data[ivm + area.ystride] + + if data[ivm] == node["default:stone"] then + local air_above = false + for i = 1, stone_depth do + if data[ivm + area.ystride * i] == node["air"] then + air_above = true + end + end + + if node_above == node["air"] and (stone_type == node["fun_caves:stone_with_algae"] or stone_type == node["fun_caves:stone_with_lichen"]) and rand(dirt_ratio) == 1 then + data[ivm] = node["dirt"] + write = true + break + end + + if air_above then + if stone_type == node["fun_caves:stone_with_salt"] and rand(radioactive_ratio) == 1 then + data[ivm] = node["fun_caves:radioactive_ore"] + write = true + break + elseif stone_type == node["fun_caves:black_sand"] and rand(coalblock_ratio) == 1 then + data[ivm] = node["default:coalblock"] + break + elseif node_above == node["air"] and stone_type == node["fun_caves:stone_with_moss"] and rand(fungal_stone_ratio) == 1 then + data[ivm] = node["fun_caves:glowing_fungal_stone"] + write = true + break + else + data[ivm] = stone_type + write = true + break + end + end + + local air_below = false + for i = 1, stone_depth do + if data[ivm - area.ystride * i] == node["air"] then + air_below = true + end + end + + if data[ivm] == node["default:stone"] and air_below then + if stone_type == node["fun_caves:stone_with_salt"] and rand(radioactive_ratio) == 1 then + data[ivm] = node["fun_caves:radioactive_ore"] + write = true + break + elseif stone_type == node["fun_caves:black_sand"] and rand(coalblock_ratio) == 1 then + data[ivm] = node["default:coalblock"] + write = true + break + elseif node_below == node["air"] and (stone_type == node["fun_caves:stone_with_lichen"] or stone_type == node["fun_caves:stone_with_moss"]) and rand(fungal_stone_ratio) == 1 then + data[ivm] = node["fun_caves:glowing_fungal_stone"] + write = true + break + else + data[ivm] = stone_type + write = true + break + end + end + end + + if data[ivm] == node["air"] then + local sr = rand(1000) + + -- hanging down + if node_above == node["default:stone"] and sr < 80 then + if stone_type == node["default:ice"] then + data[ivm] = node["fun_caves:icicle_down"] + write = true + break + elseif stone_type == node["fun_caves:stone_with_algae"] then + data[ivm] = node["fun_caves:stalactite_slimy"] + write = true + break + elseif stone_type == node["fun_caves:stone_with_moss"] then + data[ivm] = node["fun_caves:stalactite_mossy"] + write = true + break + elseif stone_type == node["fun_caves:stone_with_lichen"] then + data[ivm] = node["fun_caves:stalactite"] + write = true + break + elseif stone_type == node["default:stone"] then + data[ivm] = node["fun_caves:stalactite"] + write = true + break + end + end + + -- fluids + if y > minp.y and (node_below == node["default:stone"] or node_below == node["fun_caves:hot_cobble"]) and sr < 3 then + data[ivm] = node["default:lava_source"] + write = true + break + elseif node_below == node["fun_caves:stone_with_moss"] and sr < 3 then + data[ivm] = node["default:water_source"] + write = true + break + + -- standing up + elseif node_below == node["default:ice"] and sr < 80 then + data[ivm] = node["fun_caves:icicle_up"] + write = true + break + elseif node_below == node["fun_caves:stone_with_algae"] and sr < 80 then + data[ivm] = node["fun_caves:stalagmite_slimy"] + write = true + break + elseif node_below == node["fun_caves:stone_with_moss"] and sr < 80 then + data[ivm] = node["fun_caves:stalagmite_mossy"] + write = true + break + elseif node_below == node["fun_caves:stone_with_lichen"] and sr < 80 then + data[ivm] = node["fun_caves:stalagmite"] + write = true + break + elseif node_below == node["default:stone"] and sr < 80 then + data[ivm] = node["fun_caves:stalagmite"] + write = true + break + elseif node_below == node["fun_caves:hot_cobble"] and sr < 80 then + if sr <= 20 then + data[ivm] = node["fun_caves:hot_spike"] + write = true + break + else + data[ivm] = node["fun_caves:hot_spike_"..ceil(sr / 20)] + write = true + break + end + elseif node_below == node["fun_caves:black_sand"] and sr < 20 then + data[ivm] = node["fun_caves:constant_flame"] + write = true + break + + -- vegetation + elseif node_below == node["default:dirt"] and (stone_type == node["fun_caves:stone_with_lichen"] or stone_type == node["fun_caves:stone_with_algae"]) and biome_val >= -0.5 then + if sr < 110 then + data[ivm] = node["flowers:mushroom_red"] + write = true + break + elseif sr < 220 then + data[ivm] = node["flowers:mushroom_brown"] + write = true + break + elseif node_above == node["air"] and sr < 330 then + data[ivm] = node["fun_caves:giant_mushroom_stem"] + write = true + break + elseif sr < 360 then + local air_count = 0 + local j + for i = 1, 12 do + j = ivm + area.ystride * i + if j <= #data and data[j] == node["air"] then + air_count = air_count + 1 + end + end + if air_count > 5 then + fun_caves.make_fungal_tree(data, area, ivm, rand(2, min(air_count, 12))) + end + end + elseif node_below == node["fun_caves:giant_mushroom_stem"] and data[ivm - area.ystride * 2] == node["fun_caves:giant_mushroom_stem"] then + data[ivm] = node["fun_caves:giant_mushroom_cap"] + write = true + break + elseif node_below == node["fun_caves:giant_mushroom_stem"] then + if node_above == node["air"] and rand(3) == 1 then + data[ivm] = node["fun_caves:giant_mushroom_stem"] + write = true + break + else + data[ivm] = node["fun_caves:huge_mushroom_cap"] + write = true + break + end + end + end end + ----------------------------------------------------- + -- end of cave decoration non-loop + ----------------------------------------------------- elseif y < height then - if data[ivm] == node("air") and (data[ivm - area.ystride] == node('default:stone') or data[ivm - area.ystride] == node('default:sandstone')) then - data[ivm - area.ystride] = node("fun_caves:dirt") + -- This just places non-abm dirt inside caves. + -- Its value is questionable. + if data[ivm] == node["air"] and (data[ivm - area.ystride] == node['default:stone'] or data[ivm - area.ystride] == node['default:sandstone']) then + data[ivm - area.ystride] = node["fun_caves:dirt"] write = true end else - local pn = minetest.get_perlin(plant_noise):get2d({x=x, y=z}) + local pn = plant_n[index] local biome = biome_ids[biomemap[index]] - local new_node = fun_caves.decorate_water(node, data, area, minp, maxp, {x=x,y=y,z=z}, ivm, biome, pn) - if new_node then - data[ivm] = new_node - write = true + ----------------------------------------------------------- + -- water decoration non-loop -- only there to enable breaks + -- Remove this loop to eliminate water decorations. + ----------------------------------------------------------- + for deco_non_loop = 1, 1 do + if y < light_depth then + break + end + + local node_below = data[ivm - area.ystride] + local node_above = data[ivm + area.ystride] + + if y < water_level and data[ivm] == node["default:sand"] and node_above == node["default:water_source"] and data[ivm + area.ystride * 2] == node["default:water_source"] and coral_biomes[biome] and pn < -0.1 and rand(5) == 1 and surround(node, data, area, ivm) then + data[ivm] = node["fun_caves:staghorn_coral_water_sand"] + write = true + break + elseif y < water_level and node_below == node["default:sand"] and node_above == node["default:water_source"] and data[ivm] == node["default:water_source"] and coral_biomes[biome] and pn < -0.1 and rand(5) < 3 then + local sr = rand(65) + if sr < 4 then + data[ivm] = node["fun_caves:brain_coral"] + write = true + break + elseif sr < 6 then + data[ivm] = node["fun_caves:dragon_eye"] + write = true + break + elseif sr < 65 then + data[ivm] = node["fun_caves:pillar_coral"] + write = true + break + end + elseif x < maxp.x and y < maxp.y and z < maxp.z and x > minp.x and y > minp.y and z > minp.z and (node_above == node["default:water_source"] or node_above == node["default:river_water_source"]) and (data[ivm] == node["default:sand"] or data[ivm] == node["default:dirt"]) then + -- Check the biomes and plant water plants, if called for. + if not surround(node, data, area, ivm) then + break + end + + for i = 1, #fun_caves.water_plants do + local desc = fun_caves.water_plants[i] + + if desc.content_id then + if not node_match_cache[desc.content_id] then + node_match_cache[desc.content_id] = {} + end + + if not node_match_cache[desc.content_id][data[ivm]] then + -- This is a great way to match all node type strings + -- against a given node (or nodes). However, it's slow. + -- To speed it up, we cache the results for each plant + -- on each node, and avoid calling find_nodes every time. + local posm, count = find_nodes_in_area({x=x, y=y, z=z}, {x=x, y=y, z=z}, desc.place_on) + if #posm > 0 then + node_match_cache[desc.content_id][data[ivm]] = "good" + else + node_match_cache[desc.content_id][data[ivm]] = "bad" + end + end + + if node_match_cache[desc.content_id][data[ivm]] == "good" and desc.fill_ratio and (not desc.biomes or (biome and desc.biomes and table.contains(desc.biomes, biome))) and rand() <= desc.fill_ratio then + data[ivm] = desc.content_id + write = true + break + end + end + end + elseif y > minp.y and node_below == node["default:river_water_source"] and data[ivm] == node["air"] and water_lily_biomes[biome] and pn > 0.5 and rand(water_lily_ratio) == 1 then + -- on top of the water + -- I haven't figured out what the decoration manager is + -- doing with the noise functions, but this works ok. + data[ivm] = node["flowers:waterlily"] + write = true + break + end end + ----------------------------------------------------- + -- end of water decoration non-loop + ----------------------------------------------------- end ivm = ivm + area.ystride diff --git a/mobs.lua b/mobs.lua index 0ded91d..bc2c0cc 100644 --- a/mobs.lua +++ b/mobs.lua @@ -96,9 +96,9 @@ end if minetest.registered_entities["mobs_creeper:creeper"] then mobs:spawn_specific("mobs_creeper:creeper", - {"fun_caves:stone_with_moss"}, - {"air"}, - -1, 20, 30, 20000, 1, -31000, 31000 + {"fun_caves:stone_with_moss"}, + {"air"}, + -1, 20, 30, 20000, 1, -31000, 31000 ) end diff --git a/textures/mobs_spider.png b/textures/mobs_spider.png new file mode 100644 index 0000000..2b992d1 Binary files /dev/null and b/textures/mobs_spider.png differ