diff --git a/API.lua b/API.lua index 8edb36e..6f1ccc5 100644 --- a/API.lua +++ b/API.lua @@ -41,10 +41,8 @@ end -- start spawning mobs function spawners.start_spawning(pos, how_many, mob_name, mod_prefix, sound_custom) if not pos or not how_many or not mob_name then return end - print("mod_prefix: "..mod_prefix) - print("mob_name: "..mob_name) - local sound_name + local sound_name -- remove 'spawners:' from the string local mob_name = string.sub(mob_name,10) @@ -56,8 +54,61 @@ function spawners.start_spawning(pos, how_many, mob_name, mod_prefix, sound_cust end for i=1,how_many do + local obj = minetest.add_entity(pos, mod_prefix..":"..mob_name) - if mob_name == "default:stone_with_gold" then + if obj then + if sound_name then + minetest.sound_play(sound_name, { + pos = pos, + max_hear_distance = 32, + gain = 10, + }) + end + end + end +end + +function spawners.add_effects(pos, radius) + minetest.add_particlespawner({ + amount = 32, + time = .5, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x=-1, y=-10, z=-1}, + maxvel = {x=1, y=10, z=1}, + minacc = vector.new(), + maxacc = vector.new(), + minexptime = .5, + maxexptime = 1, + minsize = 2, + maxsize = 8, + texture = "smoke_particle.png", + }) +end + +-- start spawning ores +function spawners.start_spawning_ores(pos, ore_name, sound_custom, spawners_pos) + if not pos or not ore_name then return end + + local sound_name + local player_near = false + + -- use custom sounds + if sound_custom ~= "" then + sound_name = sound_custom + else + sound_name = false + end + + local how_many = math.random(0,2) + how_many = how_many+1 + print("how_many: "..how_many) + + for i=1, how_many do + print("i: "..i) + + if i > 1 then + player_near, pos = spawners.check_around_radius_ores(pos, "default:stone") minetest.sound_play(sound_name, { pos = pos, @@ -65,27 +116,25 @@ function spawners.start_spawning(pos, how_many, mob_name, mod_prefix, sound_cust gain = 10, }) - minetest.set_node(pos, {name="default:stone_with_gold"}) - + minetest.set_node(pos, {name=ore_name}) + spawners.add_effects(pos, 1) + print("#2 spawing "..ore_name.." at "..minetest.pos_to_string(pos)) else + minetest.sound_play(sound_name, { + pos = pos, + max_hear_distance = 32, + gain = 10, + }) - local obj = minetest.add_entity(pos, mod_prefix..":"..mob_name) - - if obj then - if sound_name then - minetest.sound_play(sound_name, { - pos = pos, - max_hear_distance = 32, - gain = 10, - }) - end - end + minetest.set_node(pos, {name=ore_name}) + print("#1 spawing "..ore_name.." at "..minetest.pos_to_string(pos)) + spawners.add_effects(pos, 1) end end end -function spawners.check_around_radius(pos, check_node) +function spawners.check_around_radius(pos) local player_near = false local found_node = false local radius = 21 @@ -96,8 +145,16 @@ function spawners.check_around_radius(pos, check_node) player_near = true end end + + return player_near +end + +function spawners.check_around_radius_ores(pos, check_node) + local player_near = spawners.check_around_radius(pos); + local found_node = false + local node_ore_pos = nil print("check_node: "..check_node) - if check_node and check_node == "default:stone" then + if check_node then node_ore_pos = minetest.find_node_near(pos, 3, {check_node}) @@ -110,16 +167,11 @@ function spawners.check_around_radius(pos, check_node) return player_near, found_node end -function spawners.check_node_status(pos, mob, night_only, check_node) - if not check_node then check_node = "air" end +function spawners.check_node_status(pos, mob, night_only) + local player_near = spawners.check_around_radius(pos) - local player_near, found_node = spawners.check_around_radius(pos, check_node) - local random_pos = false - - if check_node == "default:stone" and not found_node then - print("no stone found #2") - return false, true - elseif player_near then + if player_near then + local random_pos = false local min_node_light = 10 local tod = minetest.get_timeofday() * 24000 local node_light = minetest.get_node_light(pos) @@ -127,66 +179,65 @@ function spawners.check_node_status(pos, mob, night_only, check_node) if not node_light then return false end - print("node_light: "..node_light) - if check_node == "air" then - local spawn_positions = {} - local right = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z}) - local front = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1}) - local left = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z}) - local back = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-1}) - local top = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}) - local bottom = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) - -- make sure that at least one side of the spawner is open - if right.name == "air" then - table.insert(spawn_positions, {x=pos.x+1.5, y=pos.y, z=pos.z}) - end - if front.name == "air" then - table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z+1.5}) - end - if left.name == "air" then - table.insert(spawn_positions, {x=pos.x-1.5, y=pos.y, z=pos.z}) - end - if back.name == "air" then - table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z-1.5}) - end - if top.name == "air" then - table.insert(spawn_positions, {x=pos.x, y=pos.y+1.5, z=pos.z}) - end - if bottom.name == "air" then - table.insert(spawn_positions, {x=pos.x, y=pos.y-1.5, z=pos.z}) - end + local spawn_positions = {} + local right = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z}) + local front = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1}) + local left = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z}) + local back = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-1}) + local top = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}) + local bottom = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) - if #spawn_positions < 1 then - -- spawner is not touching node what he needs to - return false + -- make sure that at least one side of the spawner is open + if right.name == "air" then + table.insert(spawn_positions, {x=pos.x+1.5, y=pos.y, z=pos.z}) + end + if front.name == "air" then + table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z+1.5}) + end + if left.name == "air" then + table.insert(spawn_positions, {x=pos.x-1.5, y=pos.y, z=pos.z}) + end + if back.name == "air" then + table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z-1.5}) + end + if top.name == "air" then + table.insert(spawn_positions, {x=pos.x, y=pos.y+1.5, z=pos.z}) + end + if bottom.name == "air" then + table.insert(spawn_positions, {x=pos.x, y=pos.y-1.5, z=pos.z}) + end + + if #spawn_positions < 1 then + -- spawner is cloed from all sides + return false + else + -- pick random from the open sides + local pick_random + + if #spawn_positions == 1 then + pick_random = #spawn_positions else - -- pick random from the open sides - local pick_random - - if #spawn_positions == 1 then - pick_random = #spawn_positions - else - pick_random = math.random(1,#spawn_positions) - end - - for k, v in pairs (spawn_positions) do - if k == pick_random then - random_pos = v - end + pick_random = math.random(1,#spawn_positions) + end + + for k, v in pairs (spawn_positions) do + if k == pick_random then + random_pos = v end end + end - -- check the node above and below the found air node - local node_above = minetest.get_node({x=random_pos.x, y=random_pos.y+1, z=random_pos.z}).name - local node_below = minetest.get_node({x=random_pos.x, y=random_pos.y-1, z=random_pos.z}).name - - if not (node_above == "air" or node_below == "air") then return false end + -- check the node above and below the found air node + local node_above = minetest.get_node({x=random_pos.x, y=random_pos.y+1, z=random_pos.z}).name + local node_below = minetest.get_node({x=random_pos.x, y=random_pos.y-1, z=random_pos.z}).name + + if not (node_above == "air" or node_below == "air") then + return false end -- spawn only at day if not night_only and node_light < min_node_light then - print("not enough light") return false, true end @@ -203,4 +254,16 @@ function spawners.check_node_status(pos, mob, night_only, check_node) else return false, true end +end + +function spawners.check_node_status_ores(pos, ore_name, check_node) + if not check_node then return end + + local player_near, found_node = spawners.check_around_radius_ores(pos, check_node) + + if player_near then + return false, found_node + else + return true, false + end end \ No newline at end of file diff --git a/spawners_ores.lua b/spawners_ores.lua index 0e280bb..cda234d 100644 --- a/spawners_ores.lua +++ b/spawners_ores.lua @@ -1,6 +1,4 @@ -local max_obj_per_mapblock = tonumber(minetest.setting_get("max_objects_per_block")) -local tmp = {} -function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_only, sound_custom) +function spawners.create_ore(ore_name, mod_prefix, size, offset, texture, sound_custom) -- dummy inside the spawner local dummy_ore_definition = { hp_max = 1, @@ -9,7 +7,7 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ visual = "wielditem", visual_size = size, timer = 0, - textures={"default:stone_with_gold"}, + textures={"default:"..ore_name}, makes_footstep_sound = false, automatic_rotate = math.pi * -3, m_name = "dummy_ore" @@ -26,17 +24,17 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ self.timer = self.timer + dtime local n = minetest.get_node_or_nil(self.object:getpos()) if self.timer > 2 then - if n and n.name and n.name ~= "spawners:"..mob_name.."_spawner_active" then + if n and n.name and n.name ~= "spawners:"..ore_name.."_spawner_active" and n.name ~= "spawners:"..ore_name.."_spawner_waiting" then self.object:remove() end end end - minetest.register_entity("spawners:dummy_ore_"..mob_name, dummy_ore_definition) + minetest.register_entity("spawners:dummy_ore_"..ore_name, dummy_ore_definition) -- node spawner active - minetest.register_node("spawners:"..mob_name.."_spawner_active", { - description = mob_name.." spawner active", + minetest.register_node("spawners:"..ore_name.."_spawner_active", { + description = ore_name.." spawner active", paramtype = "light", light_source = 4, drawtype = "allfaces", @@ -46,7 +44,7 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ sunlight_propagates = true, tiles = { { - name = "spawners_spawner_animated.png", + name = "spawners_spawner_animated_v2.png", animation = { type = "vertical_frames", aspect_w = 16, @@ -57,16 +55,16 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ }, is_ground_content = true, groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1}, - drop = "spawners:"..mob_name.."_spawner", + drop = "spawners:"..ore_name.."_spawner", on_construct = function(pos) pos.y = pos.y + offset - minetest.add_entity(pos,"spawners:dummy_ore_"..mob_name) + minetest.add_entity(pos,"spawners:dummy_ore_"..ore_name) end, }) -- node spawner waiting for light - everything is ok but too much light or not enough light - minetest.register_node("spawners:spawner_waiting", { - description = "spawner waiting", + minetest.register_node("spawners:"..ore_name.."_spawner_waiting", { + description = ore_name.." spawner waiting", paramtype = "light", light_source = 2, drawtype = "allfaces", @@ -86,12 +84,16 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ }, is_ground_content = true, groups = {cracky=1,level=2,not_in_creative_inventory=1}, - drop = "spawners:"..mob_name.."_spawner", + drop = "spawners:"..ore_name.."_spawner", + on_construct = function(pos) + pos.y = pos.y + offset + minetest.add_entity(pos,"spawners:dummy_ore_"..ore_name) + end, }) -- node spawner inactive (default) - minetest.register_node("spawners:"..mob_name.."_spawner", { - description = mob_name.." spawner", + minetest.register_node("spawners:"..ore_name.."_spawner", { + description = ore_name.." spawner", paramtype = "light", drawtype = "allfaces", walkable = true, @@ -101,75 +103,41 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ is_ground_content = true, groups = {cracky=1,level=2}, on_construct = function(pos) - local random_pos, waiting, found_node = spawners.check_node_status(pos, mob_name, night_only, "default:stone") + local waiting, found_node = spawners.check_node_status_ores(pos, ore_name, "default:stone") if found_node then - minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner_active"}) + minetest.set_node(pos, {name="spawners:"..ore_name.."_spawner_active"}) elseif waiting then - minetest.set_node(pos, {name="spawners:spawner_waiting"}) + minetest.set_node(pos, {name="spawners:"..ore_name.."_spawner_waiting"}) else end end, }) - -- node spawner overheated - minetest.register_node("spawners:"..mob_name.."_spawner_overheat", { - description = mob_name.." spawner overheated", - paramtype = "light", - light_source = 2, - drawtype = "allfaces", - walkable = true, - sounds = default.node_sound_stone_defaults(), - catch_up = false, - damage_per_second = 4, - sunlight_propagates = true, - tiles = {"spawners_spawner.png^[colorize:#FF000030"}, - is_ground_content = true, - groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1}, - drop = "spawners:"..mob_name.."_spawner", - on_construct = function(pos) - minetest.get_node_timer(pos):start(60) - end, - on_timer = function(pos, elapsed) - minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner"}) - end, - }) - -- abm minetest.register_abm({ - nodenames = {"spawners:"..mob_name.."_spawner", "spawners:"..mob_name.."_spawner_active", "spawners:"..mob_name.."_spawner_overheat", "spawners:spawner_waiting"}, + nodenames = {"spawners:"..ore_name.."_spawner", "spawners:"..ore_name.."_spawner_active", "spawners:"..ore_name.."_spawner_waiting"}, interval = 5, chance = 5, action = function(pos, node, active_object_count, active_object_count_wider) - local random_pos, waiting, found_node = spawners.check_node_status(pos, mob_name, night_only, "default:stone") + local waiting, found_node = spawners.check_node_status_ores(pos, ore_name, "default:stone") + + print("ore_name: "..ore_name) if found_node then -- make sure the right node status is shown - if node.name ~= "spawners:"..mob_name.."_spawner_active" then - minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner"}) + if node.name ~= "spawners:"..ore_name.."_spawner_active" then + minetest.set_node(pos, {name="spawners:"..ore_name.."_spawner"}) end -- enough place to spawn more ores - spawners.start_spawning(found_node, 1, "default:stone_with_gold", "", sound_custom) + spawners.start_spawning_ores(found_node, "default:"..ore_name, sound_custom) - -- spawners.start_spawning(random_pos, 1, "spawners:"..mob_name, mod_prefix, sound_custom) - - elseif waiting then - -- waiting status - print("waiting status") - if node.name ~= "spawners:spawner_waiting" then - minetest.set_node(pos, {name="spawners:spawner_waiting"}) - end else - -- no random_pos found - print("no random_pos found") - if minetest.get_node_timer(pos):is_started() then - minetest.get_node_timer(pos):stop() - end - - if node.name ~= "spawners:"..mob_name.."_spawner" then - minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner"}) + -- waiting status + if node.name ~= "spawners:"..ore_name.."_spawner_waiting" then + minetest.set_node(pos, {name="spawners:"..ore_name.."_spawner_waiting"}) end end @@ -178,10 +146,50 @@ function spawners.create_ore(mob_name, mod_prefix, size, offset, texture, night_ end --- create all ore spawners --- for i, mob_table in ipairs(spawners.mob_tables) do --- if mob_table then +-- default:stone_with_gold +spawners.create_ore("stone_with_gold", "", {x=.33,y=.33}, 0, {"default_stone.png^default_mineral_gold.png"}, "tnt_ignite") + +spawners.create_ore("stone_with_coal", "", {x=.33,y=.33}, 0, {"default_stone.png^default_mineral_gold.png"}, "tnt_ignite") + +spawners.create_ore("stone_with_iron", "", {x=.33,y=.33}, 0, {"default_stone.png^default_mineral_gold.png"}, "tnt_ignite") + +spawners.create_ore("stone_with_copper", "", {x=.33,y=.33}, 0, {"default_stone.png^default_mineral_gold.png"}, "tnt_ignite") + + +-- recipes +minetest.register_craft({ + output = "spawners:stone_with_gold_spawner", + recipe = { + {"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"}, + {"xpanes:bar", "default:goldblock", "xpanes:bar"}, + {"default:diamondblock", "xpanes:bar", "default:diamondblock"}, + } +}) + +minetest.register_craft({ + output = "spawners:stone_with_coal_spawner", + recipe = { + {"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"}, + {"xpanes:bar", "default:coalblock", "xpanes:bar"}, + {"default:diamondblock", "xpanes:bar", "default:diamondblock"}, + } +}) + +minetest.register_craft({ + output = "spawners:stone_with_iron_spawner", + recipe = { + {"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"}, + {"xpanes:bar", "default:steelblock", "xpanes:bar"}, + {"default:diamondblock", "xpanes:bar", "default:diamondblock"}, + } +}) + +minetest.register_craft({ + output = "spawners:stone_with_copper_spawner", + recipe = { + {"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"}, + {"xpanes:bar", "default:copperblock", "xpanes:bar"}, + {"default:diamondblock", "xpanes:bar", "default:diamondblock"}, + } +}) - spawners.create_ore("stone_with_gold", "", {x=.33,y=.33}, 0, {"default_stone.png^default_mineral_gold.png"}, false, "tnt_ignite") --- end --- end \ No newline at end of file diff --git a/textures/spawners_spawner_animated_v2.png b/textures/spawners_spawner_animated_v2.png new file mode 100644 index 0000000..2393f0c Binary files /dev/null and b/textures/spawners_spawner_animated_v2.png differ