From 93f3d105d620c8ba6a69e9eec57f2750f1b6da27 Mon Sep 17 00:00:00 2001 From: Juraj Vajda Date: Tue, 19 Jan 2016 22:13:39 +0100 Subject: [PATCH] added new stuff and spawn multiple blocks --- API.lua | 219 ++++++++++++++-------- spawners_ores.lua | 146 ++++++++------- textures/spawners_spawner_animated_v2.png | Bin 0 -> 3706 bytes 3 files changed, 218 insertions(+), 147 deletions(-) create mode 100644 textures/spawners_spawner_animated_v2.png 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 0000000000000000000000000000000000000000..2393f0c7ce58f20632a64aa59e28b22fc0300f76 GIT binary patch literal 3706 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 M7G(3srfy092Tza9DgXcg literal 0 HcmV?d00001