From 65a6df1e441ec08763be27df4ef00132e7d149c8 Mon Sep 17 00:00:00 2001 From: Duane Robertson Date: Sat, 28 May 2016 05:24:36 -0500 Subject: [PATCH] Streamline abms. --- abms.lua | 359 +++++++++++++++++++++++++++++++++++--------- danglers.lua | 2 +- deco_cave_nodes.lua | 16 +- fungal_tree.lua | 295 +++++++----------------------------- goblin_coal.lua | 4 +- goblin_cobbler.lua | 4 +- goblin_copper.lua | 4 +- goblin_diamond.lua | 4 +- goblin_digger.lua | 4 +- goblin_gold.lua | 4 +- goblin_ice.lua | 2 +- goblin_iron.lua | 4 +- goblin_king.lua | 4 +- init.lua | 2 +- mapgen.lua | 2 +- nodes.lua | 6 + spider.lua | 2 +- 17 files changed, 374 insertions(+), 344 deletions(-) diff --git a/abms.lua b/abms.lua index 1b90a5a..b0a9f42 100644 --- a/abms.lua +++ b/abms.lua @@ -1,29 +1,45 @@ +-- see also, fungal_tree.lua + -- player surface damage and hunger local dps_delay = 3000000 local last_dps_check = 0 local cold_delay = 5 local hunger_delay = 60 local dps_count = hunger_delay +local get_us_time = minetest.get_us_time +local floor = math.floor +local abs = math.abs +local max = math.max +local rand = math.random +local mushrooms = {"flowers:mushroom_brown", "flowers:mushroom_red"} +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 +local get_connected_players = minetest.get_connected_players +local find_nodes_in_area = minetest.find_nodes_in_area +local get_item_group = minetest.get_item_group + minetest.register_globalstep(function(dtime) local minp, maxp, counts - local time = minetest.get_us_time() + local time = get_us_time() if last_dps_check and time - last_dps_check < dps_delay then return end - local pos, factor + local pos, factor, mob for _, mob in pairs(minetest.luaentities) do if not mob.initial_promotion then pos = mob.object:getpos() if mob.hp_max and mob.object and mob.health and mob.damage then - factor = 1 + (math.max(math.abs(pos.x), math.abs(pos.y), math.abs(pos.z)) / 6200) + factor = 1 + (max(abs(pos.x), abs(pos.y), abs(pos.z)) / 6200) if fun_caves.is_fortress(pos) then factor = factor * 1.5 end - mob.hp_max = math.floor(mob.hp_max * factor) - mob.damage = math.floor(mob.damage * factor) - print("Promoting "..mob.name..": "..mob.hp_max.." at "..pos.x..","..pos.y..","..pos.z) + mob.hp_max = floor(mob.hp_max * factor) + mob.damage = floor(mob.damage * factor) + --print("Promoting "..mob.name..": "..mob.hp_max.." at "..pos.x..","..pos.y..","..pos.z) mob.object:set_hp(mob.hp_max) mob.health = mob.hp_max mob.initial_promotion = true @@ -32,17 +48,20 @@ minetest.register_globalstep(function(dtime) end end - for _, player in pairs(minetest.get_connected_players()) do + local players = get_connected_players() + local player + for i = 1, #players do + player = players[i] minp = vector.subtract(player:getpos(), 0.5) maxp = vector.add(player:getpos(), 0.5) - counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_hot"}) + counts = find_nodes_in_area(minp, maxp, {"group:surface_hot"}) if #counts > 1 then player:set_hp(player:get_hp() - 1) end if dps_count % cold_delay == 0 then - counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_cold"}) + counts = find_nodes_in_area(minp, maxp, {"group:surface_cold"}) if #counts > 1 then player:set_hp(player:get_hp() - 1) end @@ -55,33 +74,56 @@ minetest.register_globalstep(function(dtime) end end - last_dps_check = minetest.get_us_time() + last_dps_check = get_us_time() dps_count = dps_count - 1 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 = {"flowers:mushroom_brown", "flowers:mushroom_red"}, + nodenames = mushrooms, interval = 200 * fun_caves.time_factor, chance = 25, action = function(pos, node) local pos_up = {x=pos.x,y=pos.y+1,z=pos.z} - local node_up = minetest.get_node_or_nil(pos_up) + local node_up = get_node_or_nil(pos_up) if not node_up then return end if node_up.name ~= "air" then return end - local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) + local node_under = get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) if not node_under then return end - if minetest.get_item_group(node_under.name, "soil") ~= 0 and - minetest.get_node_light(pos_up, nil) <= fun_caves.light_max then - minetest.set_node(pos_up, {name = "fun_caves:huge_mushroom_cap"}) - minetest.set_node(pos, {name = "fun_caves:giant_mushroom_stem"}) + if get_item_group(node_under.name, "soil") ~= 0 and + (get_node_light(pos_up, nil) or 99) <= fun_caves.light_max then + set_node(pos_up, {name = "fun_caves:huge_mushroom_cap"}) + set_node(pos, {name = "fun_caves:giant_mushroom_stem"}) end end }) @@ -92,30 +134,30 @@ minetest.register_abm({ interval = 500 * fun_caves.time_factor, chance = 30, action = function(pos, node) - if minetest.get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then - minetest.set_node(pos, {name = "air"}) + if get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then + set_node(pos, {name = "air"}) return end local pos_up = {x=pos.x,y=pos.y+1,z=pos.z} - local node_up = minetest.get_node_or_nil(pos_up) + local node_up = get_node_or_nil(pos_up) if not node_up then return end if node_up.name ~= "air" then return end - local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) + local node_under = get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) if not node_under or node_under.name ~= "fun_caves:giant_mushroom_stem" then return end - node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 2, z = pos.z}) + node_under = get_node_or_nil({x = pos.x, y = pos.y - 2, z = pos.z}) if not node_under then return end - if minetest.get_item_group(node_under.name, "soil") ~= 0 and - minetest.get_node_light(pos_up, nil) <= fun_caves.light_max then - minetest.set_node(pos_up, {name = "fun_caves:giant_mushroom_cap"}) - minetest.set_node(pos, {name = "fun_caves:giant_mushroom_stem"}) + if get_item_group(node_under.name, "soil") ~= 0 and + (get_node_light(pos_up, nil) or 99) <= fun_caves.light_max then + set_node(pos_up, {name = "fun_caves:giant_mushroom_cap"}) + set_node(pos, {name = "fun_caves:giant_mushroom_stem"}) end end }) @@ -127,15 +169,15 @@ minetest.register_abm({ chance = 10, action = function(pos, node) local pos_up = {x=pos.x,y=pos.y+1,z=pos.z} - local node_up = minetest.get_node_or_nil(pos_up) + local node_up = get_node_or_nil(pos_up) if not node_up then return end if node_up.name ~= "air" then return end - if minetest.get_node_light(pos_up, nil) <= fun_caves.light_max then - minetest.set_node(pos_up, {name = "fun_caves:huge_mushroom_cap"}) + if (get_node_light(pos_up, nil) or 99) <= fun_caves.light_max then + set_node(pos_up, {name = "fun_caves:huge_mushroom_cap"}) end end }) @@ -146,60 +188,42 @@ minetest.register_abm({ interval = 15 * fun_caves.time_factor, chance = 10, action = function(pos, node) - if minetest.get_node_light(pos, nil) >= 14 then - minetest.set_node(pos, {name = "air"}) + if get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then + set_node(pos, {name = "air"}) return end local pos_down = pos pos_down.y = pos_down.y - 1 - local pos1, count = minetest.find_nodes_in_area_under_air(vector.subtract(pos_down, 4), vector.add(pos_down, 4), {"group:soil"}) + local pos1, count = find_nodes_in_area_under_air(vector.subtract(pos_down, 4), vector.add(pos_down, 4), {"group:soil"}) if #pos1 < 1 then return end - local random = pos1[math.random(1, #pos1)] + local random = pos1[rand(1, #pos1)] random.y = random.y + 1 - local mushroom_type - if math.random(1,2) == 1 then - mushroom_type = "flowers:mushroom_red" - else - mushroom_type = "flowers:mushroom_brown" - end - if minetest.get_node_light(random, nil) <= fun_caves.light_max then - minetest.set_node(random, {name = mushroom_type}) + if (get_node_light(random, nil) or 99) <= fun_caves.light_max then + set_node(random, {name = mushrooms[rand(#mushrooms)]}) end end }) --- Mushroom spread and death +-- new mushrooms minetest.register_abm({ - nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, - interval = 15 * fun_caves.time_factor, - chance = 10, + nodenames = {"default:dirt"}, + neighbors = {"air"}, + interval = 20 * fun_caves.time_factor, + chance = 25, action = function(pos, node) - if minetest.get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then - minetest.remove_node(pos) - return - end - local random = { - x = pos.x + math.random(-2, 2), - y = pos.y + math.random(-1, 1), - z = pos.z + math.random(-2, 2) - } - local random_node = minetest.get_node_or_nil(random) - if not random_node or random_node.name ~= "air" then - return - end - local node_under = minetest.get_node_or_nil({x = random.x, - y = random.y - 1, z = random.z}) - if not node_under then + if pos.y > 0 then return end - if (minetest.get_item_group(node_under.name, "soil") ~= 0 or - minetest.get_item_group(node_under.name, "tree") ~= 0) and - minetest.get_node_light(pos, 0.5) <= fun_caves.light_max and - minetest.get_node_light(random, 0.5) <= fun_caves.light_max then - minetest.set_node(random, {name = node.name}) + 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 + if (get_node_light(grow_pos, nil) or 99) <= fun_caves.light_max then + set_node(grow_pos, {name = mushrooms[rand(#mushrooms)]}) + return + end end end }) @@ -221,20 +245,20 @@ minetest.register_abm({ end if spike_num < #hot_spikes then - minetest.set_node(pos, {name=hot_spikes[spike_num+1]}) + set_node(pos, {name=hot_spikes[spike_num+1]}) return end local random = { - x = pos.x + math.random(-2, 2), - y = pos.y + math.random(-1, 1), - z = pos.z + math.random(-2, 2) + x = pos.x + rand(-2, 2), + y = pos.y + rand(-1, 1), + z = pos.z + rand(-2, 2) } - local random_node = minetest.get_node_or_nil(random) + local random_node = get_node_or_nil(random) if not random_node or (random_node.name ~= "air" and random_node.name ~= "default:lava_source" and random_node.name ~= "default:lava_flowing") then return end - local node_under = minetest.get_node_or_nil({x = random.x, + local node_under = get_node_or_nil({x = random.x, y = random.y - 1, z = random.z}) if not node_under then return @@ -243,7 +267,196 @@ minetest.register_abm({ --print("node_under ("..random.x..","..(random.y-1)..","..random.z.."): "..node_under.name) if node_under.name == "fun_caves:hot_cobble" or node_under.name == "fun_caves:black_sand" then --print("setting ("..random.x..","..random.y..","..random.z.."): "..node_under.name) - minetest.set_node(random, {name = hot_spikes[1]}) + set_node(random, {name = hot_spikes[1]}) 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 +local cid_data = {} +minetest.after(0, function() + for name, def in pairs(minetest.registered_nodes) do + cid_data[minetest.get_content_id(name)] = { + name = name, + --drops = def.drops, + flammable = def.groups.flammable, + choppy = def.groups.choppy, + fleshy = def.groups.fleshy, + snappy = def.groups.snappy, + on_blast = def.on_blast, + } + end +end) + +local function add_effects(pos, radius) + minetest.add_particlespawner({ + amount = 128, + time = 1, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x=-20, y=-20, z=-20}, + maxvel = {x=20, y=20, z=20}, + minacc = vector.new(), + maxacc = vector.new(), + minexptime = 1, + maxexptime = 3, + minsize = 8, + maxsize = 16, + texture = "tnt_smoke.png", + }) +end + +local function destroy(pos, cid) + if minetest.is_protected(pos, "") then + return + end + local def = cid_data[cid] + if def and def.on_blast then + def.on_blast(vector.new(pos), 1) + return + end + if def.snappy == nil and def.choppy == nil and def.fleshy == nil and def.name ~= "fire:basic_flame" then + return + end + local new = "air" + --if rand(1,2) == 1 then + if true then + local node_under = get_node_or_nil({x = pos.x, + y = pos.y - 1, z = pos.z}) + if node_under and node_under.name ~= "air" then + --new = node.name + end + end + set_node(pos, {name=new}) +end + +local function explode(pos, radius) + local pos = vector.round(pos) + local vm = VoxelManip() + local p1 = vector.subtract(pos, radius) + local p2 = vector.add(pos, radius) + local minp, maxp = vm:read_from_map(p1, p2) + local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) + local data = vm:get_data() + + local drops = {} + local p = {} + + local c_air = minetest.get_content_id("air") + + for z = -radius, radius do + for y = -radius, 4*radius do + local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z) + for x = -radius, radius do + if (x * x) + (y * y / 4) + (z * z) <= + (radius * radius) + rand(-radius, radius) then + local cid = data[vi] + p.x = pos.x + x + p.y = pos.y + y + p.z = pos.z + z + if cid ~= c_air then + destroy(p, cid) + end + end + vi = vi + 1 + end + end + end +end + +local function calc_velocity(pos1, pos2, old_vel, power) + local vel = vector.direction(pos1, pos2) + vel = vector.normalize(vel) + vel = vector.multiply(vel, power) + + -- Divide by distance + local dist = vector.distance(pos1, pos2) + dist = max(dist, 1) + vel = vector.divide(vel, dist) + + -- Add old velocity + vel = vector.add(vel, old_vel) + return vel +end + +local function entity_physics(pos, radius) + -- Make the damage radius larger than the destruction radius + radius = radius * 2 + local objs = minetest.get_objects_inside_radius(pos, radius) + for _, obj in pairs(objs) do + local obj_pos = obj:getpos() + local obj_vel = obj:getvelocity() + local dist = max(1, vector.distance(pos, obj_pos)) + + if obj_vel ~= nil then + obj:setvelocity(calc_velocity(pos, obj_pos, + obj_vel, radius * 10)) + end + + local damage = (4 / dist) * radius + obj:set_hp(obj:get_hp() - damage) + end +end + +fun_caves.soft_boom = function(pos) + if not pos then + return + end + + local node = get_node_or_nil(pos) + if not node then + return + end + + minetest.sound_play("tnt_explode", {pos=pos, gain=1.5, max_hear_distance=2*64}) + local radius = 5 + set_node(pos, {name="air"}) + explode(pos, radius) + entity_physics(pos, radius) + add_effects(pos, radius) +end + +--local function burn(pos) +-- minetest.get_node_timer(pos):start(1) +--end + + +----------------------------------------------- +-- testing only -- remove before distribution +----------------------------------------------- +-- Mushroom spread and death +--minetest.register_abm({ +-- nodenames = mushrooms, +-- interval = 1 * fun_caves.time_factor, +-- chance = 50, +-- action = function(pos, node) +-- if get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then +-- remove_node(pos) +-- return +-- end +-- local random = { +-- x = pos.x + rand(-2, 2), +-- y = pos.y + rand(-1, 1), +-- z = pos.z + rand(-2, 2) +-- } +-- local random_node = get_node_or_nil(random) +-- if not random_node or random_node.name ~= "air" then +-- return +-- end +-- local node_under = get_node_or_nil({x = random.x, +-- y = random.y - 1, z = random.z}) +-- if not node_under then +-- return +-- end +-- +-- if (get_item_group(node_under.name, "soil") ~= 0 or +-- get_item_group(node_under.name, "tree") ~= 0) and +-- get_node_light(pos, 0.5) <= fun_caves.light_max and +-- get_node_light(random, 0.5) <= fun_caves.light_max then +-- set_node(random, {name = node.name}) +-- end +-- end +--}) diff --git a/danglers.lua b/danglers.lua index 779682d..8762f87 100644 --- a/danglers.lua +++ b/danglers.lua @@ -81,7 +81,7 @@ mobs:register_mob("fun_caves:dangler", { end, }) -mobs:register_spawn("fun_caves:dangler", {"fun_caves:stone_with_moss", "fun_caves:stone_with_lichen", "fun_caves:stone_with_algae"}, 14, 0, 2500, 3, 31000) +mobs:register_spawn("fun_caves:dangler", {"fun_caves:stone_with_moss", "fun_caves:stone_with_lichen", "fun_caves:stone_with_algae"}, 14, 0, 2500, 3, -51) mobs:register_egg("fun_caves:dangler", "Dangling Spider", "mobs_cobweb.png", 1) diff --git a/deco_cave_nodes.lua b/deco_cave_nodes.lua index 6f3b377..6ae0a83 100644 --- a/deco_cave_nodes.lua +++ b/deco_cave_nodes.lua @@ -86,7 +86,7 @@ minetest.register_node("fun_caves:glowing_fungus", { paramtype = "light", tiles = {"vmg_glowing_fungus.png"}, inventory_image = "vmg_glowing_fungus.png", - groups = {dig_immediate = 3, attached_node = 1}, + groups = {dig_immediate = 3}, }) -- moon glass (glows) @@ -101,7 +101,8 @@ minetest.register_node("fun_caves:moon_juice", { paramtype = "light", tiles = {"vmg_moon_juice.png"}, inventory_image = "vmg_moon_juice.png", - groups = {dig_immediate = 3, attached_node = 1}, + --groups = {dig_immediate = 3, attached_node = 1}, + groups = {dig_immediate = 3}, sounds = default.node_sound_glass_defaults(), }) @@ -121,7 +122,7 @@ minetest.register_node("fun_caves:giant_mushroom_cap", { {-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, leafdecay=1}, + groups = {fleshy=1, dig_immediate=3, flammable=2, plant=1}, }) -- mushroom cap, huge @@ -139,7 +140,7 @@ minetest.register_node("fun_caves:huge_mushroom_cap", { {-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, leafdecay=1}, + groups = {fleshy=1, dig_immediate=3, flammable=2, plant=1}, }) -- mushroom stem, giant or huge @@ -147,7 +148,7 @@ 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 = {tree=1,choppy=2,oddly_breakable_by_hand=1,flammable=2, plant=1}, + groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2, plant=1}, sounds = default.node_sound_wood_defaults(), paramtype = "light", drawtype = "nodebox", @@ -266,7 +267,7 @@ for i in ipairs(spike_size) do 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, hot=3}, + groups = {cracky=3, oddly_breakable_by_hand=1, surface_hot=3}, damage_per_second = 1, sounds = default.node_sound_stone_defaults(), paramtype = "light", @@ -362,7 +363,8 @@ minetest.register_node("fun_caves:mushroom_steak", { 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, attached_node = 1}, + groups = {dig_immediate = 3}, }) minetest.register_craft({ diff --git a/fungal_tree.lua b/fungal_tree.lua index e8bc86d..35d8d19 100644 --- a/fungal_tree.lua +++ b/fungal_tree.lua @@ -2,7 +2,8 @@ -- Fungal Tree -- ------------------- -local light_max = 8 +local rand = math.random +local max = math.max local colors = {} colors["^[colorize:#FF00FF:60"] = "dye:violet" @@ -16,201 +17,6 @@ newnode.description = "Dry Fiber" minetest.register_node("fun_caves:dry_fiber", newnode) --- Fill a list with data for content IDs, after all nodes are registered -local cid_data = {} -minetest.after(0, function() - for name, def in pairs(minetest.registered_nodes) do - cid_data[minetest.get_content_id(name)] = { - name = name, - --drops = def.drops, - flammable = def.groups.flammable, - choppy = def.groups.choppy, - fleshy = def.groups.fleshy, - snappy = def.groups.snappy, - on_blast = def.on_blast, - } - end -end) - -local function add_effects(pos, radius) - minetest.add_particlespawner({ - amount = 128, - time = 1, - minpos = vector.subtract(pos, radius / 2), - maxpos = vector.add(pos, radius / 2), - minvel = {x=-20, y=-20, z=-20}, - maxvel = {x=20, y=20, z=20}, - minacc = vector.new(), - maxacc = vector.new(), - minexptime = 1, - maxexptime = 3, - minsize = 8, - maxsize = 16, - texture = "tnt_smoke.png", - }) -end - -local function destroy(pos, cid) - if minetest.is_protected(pos, "") then - return - end - local def = cid_data[cid] - if def and def.on_blast then - def.on_blast(vector.new(pos), 1) - return - end - if def.snappy == nil and def.choppy == nil and def.fleshy == nil and def.name ~= "fire:basic_flame" then - return - end - local new = "air" - --if math.random(1,2) == 1 then - if true then - local node_under = minetest.get_node_or_nil({x = pos.x, - y = pos.y - 1, z = pos.z}) - if node_under and node_under.name ~= "air" then - --new = node.name - end - end - minetest.set_node(pos, {name=new}) -end - -local function explode(pos, radius) - local pos = vector.round(pos) - local vm = VoxelManip() - local p1 = vector.subtract(pos, radius) - local p2 = vector.add(pos, radius) - local minp, maxp = vm:read_from_map(p1, p2) - local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) - local data = vm:get_data() - - local drops = {} - local p = {} - - local c_air = minetest.get_content_id("air") - - for z = -radius, radius do - for y = -radius, 4*radius do - local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z) - for x = -radius, radius do - if (x * x) + (y * y / 4) + (z * z) <= - (radius * radius) + math.random(-radius, radius) then - local cid = data[vi] - p.x = pos.x + x - p.y = pos.y + y - p.z = pos.z + z - if cid ~= c_air then - destroy(p, cid) - end - end - vi = vi + 1 - end - end - end -end - -local function calc_velocity(pos1, pos2, old_vel, power) - local vel = vector.direction(pos1, pos2) - vel = vector.normalize(vel) - vel = vector.multiply(vel, power) - - -- Divide by distance - local dist = vector.distance(pos1, pos2) - dist = math.max(dist, 1) - vel = vector.divide(vel, dist) - - -- Add old velocity - vel = vector.add(vel, old_vel) - return vel -end - -local function entity_physics(pos, radius) - -- Make the damage radius larger than the destruction radius - radius = radius * 2 - local objs = minetest.get_objects_inside_radius(pos, radius) - for _, obj in pairs(objs) do - local obj_pos = obj:getpos() - local obj_vel = obj:getvelocity() - local dist = math.max(1, vector.distance(pos, obj_pos)) - - if obj_vel ~= nil then - obj:setvelocity(calc_velocity(pos, obj_pos, - obj_vel, radius * 10)) - end - - local damage = (4 / dist) * radius - obj:set_hp(obj:get_hp() - damage) - end -end - -local function boom(pos) - if not pos then - return - end - local node = minetest.get_node_or_nil(pos) - if not node then - return - end - - minetest.sound_play("tnt_explode", {pos=pos, gain=1.5, max_hear_distance=2*64}) - local radius = 5 - minetest.set_node(pos, {name="air"}) - explode(pos, radius) - entity_physics(pos, radius) - add_effects(pos, radius) -end - -local function burn(pos) - minetest.get_node_timer(pos):start(1) -end - -local good_stone = {} -good_stone["fun_caves:stone_with_lichen"] = true -good_stone["fun_caves:stone_with_algae"] = true -local function find_ground(pos) - for y1 = 1, 16 do - local node = minetest.get_node_or_nil({x=pos.x, y=pos.y-y1, z=pos.z}) - if node then - if minetest.get_item_group(node.name, "soil") ~= 0 or - good_stone[node.name] then - return y1 - end - end - end - - return 1000 -end - - --- Exploding fruit -minetest.register_abm({ - nodenames = {"fun_caves:fungal_tree_fruit"}, - interval = 3 * fun_caves.time_factor, - chance = 20, - action = function(pos, node) - local pos1, count = minetest.find_nodes_in_area(vector.subtract(pos, 1), vector.add(pos, 1), {"fire:basic_flame"}) - if #pos1 > 0 then - boom(pos) - return - end - - local pos1, count = minetest.find_nodes_in_area(vector.subtract(pos, 1), vector.add(pos, 1), fungal_tree_leaves) - if #pos1 < 3 then - minetest.set_node(pos, {name="air"}) - return - end - - local g = find_ground(pos) - if g > 4 and g < 17 then - if math.random(1,17 - g) == 1 then - boom(pos) - end - elseif math.random(1,2) == 1 then - minetest.set_node(pos, {name="air"}) - end - end -}) - - minetest.register_node("fun_caves:fungal_tree_fruit", { description = "Fungal tree fruit", drawtype = "plantlike", @@ -229,14 +35,14 @@ minetest.register_node("fun_caves:fungal_tree_fruit", { groups = {fleshy = 3, dig_immediate = 3, flammable = 2}, --on_use = minetest.item_eat(2), sounds = default.node_sound_leaves_defaults(), - on_timer = boom, - on_punch = boom, + on_timer = fun_caves.soft_boom, + on_punch = fun_caves.soft_boom, }) local fruit = minetest.get_content_id("fun_caves:fungal_tree_fruit") function fun_caves.make_fungal_tree(data, area, ivm, height) - local leaf = minetest.get_content_id(fungal_tree_leaves[math.random(#fungal_tree_leaves)]) + local leaf = minetest.get_content_id(fungal_tree_leaves[rand(#fungal_tree_leaves)]) for y = 0, height do local radius = 1 if y > 1 and y < height - 2 then @@ -244,7 +50,7 @@ function fun_caves.make_fungal_tree(data, area, ivm, height) end for z = -radius,radius do for x = -radius,radius do - local sr = math.random(1,100) + local sr = rand(1,100) local i = ivm + z*area.zstride + y*area.ystride + x if x == 0 and y == 0 and z == 0 then data[i] = leaf @@ -273,7 +79,7 @@ for color, dye in pairs(colors) do tiles = {"fun_caves_fungal_tree_leaves.png"..color}, paramtype = "light", is_ground_content = false, - groups = {snappy=3, flammable=3, leaves=1, plant=1}, + groups = {snappy=3, flammable=3, plant=1}, drop = { max_items = 1, items = { @@ -310,71 +116,74 @@ minetest.register_craft({ }) -local leaves_and_air = table.copy(fungal_tree_leaves) -leaves_and_air[#leaves_and_air+1] = "air" +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 minetest.get_node_light(pos, nil) >= default.LIGHT_MAX - 2 then - minetest.remove_node(pos) - return - end - if find_ground(pos) > 16 then - minetest.remove_node(pos) + 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 = minetest.get_node_or_nil(grow_pos) + local grow_node = get_node_or_nil(grow_pos) if grow_node and grow_node.name == "air" then - minetest.set_node(grow_pos, {name = node.name}) - return - end - if math.random(1,3) ~= 1 then + set_node(grow_pos, {name = node.name}) return end - local foreign = {} - for _, i in pairs(fungal_tree_leaves) do - if i ~= node.name then - foreign[#foreign+1] = i - end - end - local pos1, count = minetest.find_nodes_in_area(vector.subtract(pos, 3), vector.add(pos, 3), foreign) - if #pos1 > 0 then - minetest.set_node(pos1[math.random(1,#pos1)], {name="air"}) + 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 math.random(1,201) == 1 then - local new = fungal_tree_leaves[math.random(1,#fungal_tree_leaves)] - local pos1, count = minetest.find_nodes_in_area({x=pos.x-8, y=pos.y-16, z=pos.z-8}, {x=pos.x+8, y=pos.y+16, z=pos.z+8}, node.name) - for _, p in pairs(pos1) do - minetest.set_node(p, {name=new}) - end + if rand(40) == 1 then + set_node(pos, {name = "fun_caves:fungal_tree_fruit"}) return end - grow_pos = {x = pos.x + math.random(-1,1), y = pos.y + math.random(-1,1), z = pos.z + math.random(-1,1)} - grow_node = minetest.get_node_or_nil(grow_pos) - --if math.random(1,2) == 1 then - minetest.set_node(pos, {name = "air"}) - --end - if not grow_node or not table.contains(leaves_and_air, grow_node.name) or find_ground(grow_pos) > 16 then + 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 - if minetest.get_node_light(grow_pos, nil) <= light_max then - minetest.set_node(pos, {name = "air"}) - if math.random(1,27) == 1 then - minetest.set_node(grow_pos, {name = "fun_caves:fungal_tree_fruit"}) - else - minetest.set_node(grow_pos, {name = node.name}) - end - end end }) diff --git a/goblin_coal.lua b/goblin_coal.lua index b0ac2f2..9d95ada 100644 --- a/goblin_coal.lua +++ b/goblin_coal.lua @@ -121,8 +121,8 @@ mobs:register_mob("fun_caves:goblin_coal", { }) mobs:register_egg("fun_caves:goblin_coal", "Goblin Egg (coal)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_coal", {"default:coalblock", "default:stone_with_coal", "group:fortress"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) -mobs:register_spawn("fun_caves:goblin_coal", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_coal", {"default:coalblock", "default:stone_with_coal", "group:fortress"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) +mobs:register_spawn("fun_caves:goblin_coal", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:stone_with_coal_trap", { description = "Coal Trap", diff --git a/goblin_cobbler.lua b/goblin_cobbler.lua index 5fe2e5d..e5ba5bd 100644 --- a/goblin_cobbler.lua +++ b/goblin_cobbler.lua @@ -124,8 +124,8 @@ mobs:register_mob("fun_caves:goblin_cobble", { end, }) mobs:register_egg("fun_caves:goblin_cobble", "Goblin Egg (cobble)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_cobble", {"group:stone"}, 100, 0, 10 * fun_caves.goblin_spawn_frequency, 3, 101) -mobs:register_spawn("fun_caves:goblin_cobble", {"default:mossycobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_cobble", {"group:stone"}, 100, 0, 10 * fun_caves.goblin_spawn_frequency, 3, -51) +mobs:register_spawn("fun_caves:goblin_cobble", {"default:mossycobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:mossycobble_trap", { description = "Messy Gobblestone", diff --git a/goblin_copper.lua b/goblin_copper.lua index 0940831..bd4f648 100644 --- a/goblin_copper.lua +++ b/goblin_copper.lua @@ -120,8 +120,8 @@ mobs:register_mob("fun_caves:goblin_copper", { end, }) mobs:register_egg("fun_caves:goblin_copper", "Goblin Egg (copper)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_copper", {"default:stone_with_copper", "group:fortress"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) -mobs:register_spawn("fun_caves:goblin_copper", {"default:mossycobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_copper", {"default:stone_with_copper", "group:fortress"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) +mobs:register_spawn("fun_caves:goblin_copper", {"default:mossycobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:stone_with_copper_trap", { description = "Copper Trap", diff --git a/goblin_diamond.lua b/goblin_diamond.lua index daffe7c..10e7f6a 100644 --- a/goblin_diamond.lua +++ b/goblin_diamond.lua @@ -123,8 +123,8 @@ mobs:register_mob("fun_caves:goblin_diamond", { }) mobs:register_egg("fun_caves:goblin_diamond", "Goblin Egg (diamond)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_diamond", {"default:stone_with_diamond" }, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 2, 101) -mobs:register_spawn("fun_caves:goblin_diamond", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 2 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_diamond", {"default:stone_with_diamond" }, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 2, -51) +mobs:register_spawn("fun_caves:goblin_diamond", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 2 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:stone_with_diamond_trap", { description = "Diamond Trap", diff --git a/goblin_digger.lua b/goblin_digger.lua index fdc0571..627466f 100644 --- a/goblin_digger.lua +++ b/goblin_digger.lua @@ -219,6 +219,6 @@ mobs:register_mob("fun_caves:goblin_digger", { }) mobs:register_egg("fun_caves:goblin_digger", "Goblin Egg (digger)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_digger", {"group:stone"}, 100, 0, 20 * fun_caves.goblin_spawn_frequency, 3, 101) -mobs:register_spawn("fun_caves:goblin_digger", {"default:mossycobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_digger", {"group:stone"}, 100, 0, 20 * fun_caves.goblin_spawn_frequency, 3, -51) +mobs:register_spawn("fun_caves:goblin_digger", {"default:mossycobble"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) diff --git a/goblin_gold.lua b/goblin_gold.lua index a9f5a31..ac7335f 100644 --- a/goblin_gold.lua +++ b/goblin_gold.lua @@ -120,8 +120,8 @@ mobs:register_mob("fun_caves:goblin_gold", { end, }) mobs:register_egg("fun_caves:goblin_gold", "Goblin Egg (gold)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_gold", {"default:stone_with_gold" }, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 2, 101) -mobs:register_spawn("fun_caves:goblin_gold", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 2 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_gold", {"default:stone_with_gold" }, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 2, -51) +mobs:register_spawn("fun_caves:goblin_gold", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 2 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:molten_gold_source", { description = "Molten Gold Source", diff --git a/goblin_ice.lua b/goblin_ice.lua index 371681f..c5dc368 100644 --- a/goblin_ice.lua +++ b/goblin_ice.lua @@ -120,7 +120,7 @@ mobs:register_mob("fun_caves:goblin_ice", { }) mobs:register_egg("fun_caves:goblin_ice", "Goblin Egg (ice)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_ice", {"default:ice"}, 100, 0, 5 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_ice", {"default:ice"}, 100, 0, 5 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:ice_trap", { description = "Ice Trap", diff --git a/goblin_iron.lua b/goblin_iron.lua index d0c1896..a95b702 100644 --- a/goblin_iron.lua +++ b/goblin_iron.lua @@ -122,8 +122,8 @@ mobs:register_mob("fun_caves:goblin_iron", { end, }) mobs:register_egg("fun_caves:goblin_iron", "Goblin Egg (iron)", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_iron", {"default:stone_with_iron"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, 101) -mobs:register_spawn("fun_caves:goblin_iron", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 2 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_iron", {"default:stone_with_iron"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 3, -51) +mobs:register_spawn("fun_caves:goblin_iron", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 2 * fun_caves.goblin_spawn_frequency, 3, -51) minetest.register_node("fun_caves:stone_with_iron_trap", { description = "Iron Trap", diff --git a/goblin_king.lua b/goblin_king.lua index adae025..b6cf549 100644 --- a/goblin_king.lua +++ b/goblin_king.lua @@ -125,6 +125,6 @@ mobs:register_mob("fun_caves:goblin_king", { end, }) mobs:register_egg("fun_caves:goblin_king", "Goblin King Egg", "default_mossycobble.png", 1) -mobs:register_spawn("fun_caves:goblin_king", {"default:stone_with_mese"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 1, 101) -mobs:register_spawn("fun_caves:goblin_king", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 3 * fun_caves.goblin_spawn_frequency, 3, 101) +mobs:register_spawn("fun_caves:goblin_king", {"default:stone_with_mese"}, 100, 0, 1 * fun_caves.goblin_spawn_frequency, 1, -51) +mobs:register_spawn("fun_caves:goblin_king", {"default:mossycobble", "fun_caves:hot_cobble"}, 100, 0, 3 * fun_caves.goblin_spawn_frequency, 3, -51) diff --git a/init.lua b/init.lua index 78a8102..a476234 100644 --- a/init.lua +++ b/init.lua @@ -49,6 +49,7 @@ function fun_caves.clone_node(name) end +dofile(fun_caves.path .. "/abms.lua") dofile(fun_caves.path .. "/unionfind.lua") dofile(fun_caves.path .. "/nodes.lua") dofile(fun_caves.path .. "/deco.lua") @@ -56,4 +57,3 @@ 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") -dofile(fun_caves.path .. "/abms.lua") diff --git a/mapgen.lua b/mapgen.lua index b554f9b..b0a726f 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -219,7 +219,7 @@ local function generate(p_minp, p_maxp, seed) end 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("dirt") + data[ivm - area.ystride] = node("fun_caves:dirt") write = true end else diff --git a/nodes.lua b/nodes.lua index 9b142f6..3affa0d 100644 --- a/nodes.lua +++ b/nodes.lua @@ -1,3 +1,9 @@ +-- dirt, cave +local newnode = fun_caves.clone_node("default:dirt") +newnode.drop = "default:dirt" +newnode.groups.soil = 0 +minetest.register_node("fun_caves:dirt", newnode) + -- dungeon floor, basic local newnode = fun_caves.clone_node("default:stone") newnode.description = "Dungeon Stone" diff --git a/spider.lua b/spider.lua index e0daddc..54051f8 100644 --- a/spider.lua +++ b/spider.lua @@ -56,6 +56,6 @@ mobs:register_mob("fun_caves:spider", { end, }) -mobs:register_spawn("fun_caves:spider", {"fun_caves:stone_with_moss", "fun_caves:stone_with_lichen", "fun_caves:stone_with_algae"}, 14, 0, 5000, 2, 31000) +mobs:register_spawn("fun_caves:spider", {"fun_caves:stone_with_moss", "fun_caves:stone_with_lichen", "fun_caves:stone_with_algae"}, 14, 0, 5000, 2, -51) mobs:register_egg("fun_caves:spider", "Deep Spider", "mobs_cobweb.png", 1)