From 643b63e91a416b2bbd0a55d1db815240e4704608 Mon Sep 17 00:00:00 2001 From: Juraj Vajda Date: Tue, 12 Jan 2016 22:26:44 +0100 Subject: [PATCH 1/3] performance tweaks and config beginning --- config.lua | 25 +++++++++++++++++++++++++ init.lua | 23 +++++++++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 config.lua diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..eda7c79 --- /dev/null +++ b/config.lua @@ -0,0 +1,25 @@ +-- mod what should be enabled and loded +ENABLED_MODS = {"mobs", "pyramids", "creatures"} + +-- mobs properties - setup all you mobs here +MOBS_PROPS = { + ["mobs"] = { + {name = "mobs name 1"}, + {name = "mobs name 2"}, + {name = "mobs name 3"}, + }, + + ["pyramids"] = { + {name = "pyramids name 1"}, + {name = "pyramids name 2"}, + {name = "pyramids name 3"} + }, + + + ["creatures"] = { + {name = "creatures name 1"}, + {name = "creatures name 2"}, + {name = "creatures name 3"} + } + +} diff --git a/init.lua b/init.lua index feb73d2..554e21d 100644 --- a/init.lua +++ b/init.lua @@ -1,11 +1,22 @@ +-- user settings local max_obj_per_mapblock = tonumber(minetest.setting_get("max_objects_per_block")) - +dofile(minetest.get_modpath("spawners").."/config.lua") -- main table spawners = {} -- list of mods spawners.mob_mods = {"mobs", "pyramids", "creatures"} -- table holding all mobs info spawners.mob_tables = {} +for k, mod1 in ipairs(ENABLED_MODS) do + print("********************** key: "..k..", val: "..mod1) + + for j, mobs1 in ipairs(MOBS_PROPS[mod1]) do + print(mobs1.name) + + + + end +end -- check if mods exists and build tables for k, v in ipairs(spawners.mob_mods) do @@ -90,7 +101,7 @@ function spawners.check_around_radius(pos) local player_near = false local radius = 21 - for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do + for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do if obj:is_player() then player_near = true end @@ -300,6 +311,7 @@ function spawners.create(mob_name, mod_prefix, size, offset, mesh, texture, nigh light_source = 2, drawtype = "allfaces", walkable = true, + catch_up = false, damage_per_second = 4, sunlight_propagates = true, tiles = {"spawners_spawner.png^[colorize:#FF000030"}, @@ -318,10 +330,9 @@ function spawners.create(mob_name, mod_prefix, size, offset, mesh, texture, nigh minetest.register_abm({ nodenames = {"spawners:"..mod_prefix.."_"..mob_name.."_spawner", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_active", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}, neighbors = {"air"}, - interval = 2.0, - chance = 20, + interval = 5.0, + chance = 8, action = function(pos, node, active_object_count, active_object_count_wider) - local random_pos, waiting = spawners.check_node_status(pos, mob_name, night_only) @@ -398,4 +409,4 @@ for i, mob_table in ipairs(spawners.mob_tables) do end end -print ("[MOD] Spawners 0.2 Loaded.") \ No newline at end of file +print ("[MOD] Spawners 0.3 Loaded.") \ No newline at end of file From c26389c8c10854c9b540c6c0d683444e2cf46183 Mon Sep 17 00:00:00 2001 From: Juraj Vajda Date: Thu, 14 Jan 2016 00:18:37 +0100 Subject: [PATCH 2/3] big cleanup and tweaks --- API.lua | 169 ++++++++++++++++ config.lua | 147 ++++++++++++-- init.lua | 412 +------------------------------------- sounds/spawners_bunny.ogg | Bin 0 -> 37905 bytes spawners_mobs.lua | 204 +++++++++++++++++++ 5 files changed, 510 insertions(+), 422 deletions(-) create mode 100644 API.lua create mode 100644 sounds/spawners_bunny.ogg create mode 100644 spawners_mobs.lua diff --git a/API.lua b/API.lua new file mode 100644 index 0000000..df215b7 --- /dev/null +++ b/API.lua @@ -0,0 +1,169 @@ +-- main tables +spawners = {} +spawners.mob_tables = {} + +-- check if mods exists and build tables +for k, mob_mod in ipairs(ENABLED_MODS) do + local modpath = minetest.get_modpath(mob_mod) + -- list of mobs and their info + if (modpath) then + for j, mob in ipairs(MOBS_PROPS[mob_mod]) do + local mob_egg = nil + + if mob_mod == "mobs" and not (mobs.mod == "redo") then goto continue end + + table.insert(spawners.mob_tables, {name=mob.name, mod_prefix=mob_mod, egg_name_custom=mob.egg_name_custom, dummy_size=mob.dummy_size, dummy_offset=mob.dummy_offset, dummy_mesh=mob.dummy_mesh, dummy_texture=mob.dummy_texture, night_only=mob.night_only, sound_custom=mob.sound_custom}) + + -- use custom egg or create a default egg + if mob.egg_name_custom ~= "" then + mob_egg = mob.egg_name_custom + else + mob_egg = mob_mod..":"..mob.name + end + + -- recipes + minetest.register_craft({ + output = "spawners:"..mob_mod.."_"..mob.name.."_spawner", + recipe = { + {"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"}, + {"xpanes:bar", mob_egg, "xpanes:bar"}, + {"default:diamondblock", "xpanes:bar", "default:diamondblock"}, + } + }) + + ::continue:: + end + else + print("[MOD] Spawners: MOD "..mob_mod.." not found.") + end +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 + + local sound_name + -- remove 'spawners:' from the string + local mob_name = string.sub(mob_name,10) + + -- use custom sounds + if sound_custom ~= "" then + sound_name = sound_custom + else + sound_name = mod_prefix.."_"..mob_name + end + + for i=1,how_many do + 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 + end + +end + +function spawners.check_around_radius(pos) + local player_near = false + local radius = 21 + + for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do + if obj:is_player() then + player_near = true + end + end + + return player_near +end + +function spawners.check_node_status(pos, mob, night_only) + local player_near = spawners.check_around_radius(pos) + local random_pos = false + + if player_near then + local min_node_light = 10 + local tod = minetest.get_timeofday() * 24000 + local node_light = minetest.get_node_light(pos) + 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 not node_light then return false end + + -- 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 closed 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 = 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 + + -- spawn only at day + if not night_only and node_light < min_node_light then + return false, true + end + + -- spawn only at night + if night_only then + if not (19359 > tod and tod > 5200) or node_light < min_node_light then + return random_pos + else + return false, true + end + end + + return random_pos + else + return false + end +end \ No newline at end of file diff --git a/config.lua b/config.lua index eda7c79..3c0499a 100644 --- a/config.lua +++ b/config.lua @@ -1,25 +1,144 @@ --- mod what should be enabled and loded +-- * [name : string] - Name of the mob used in the mod. + +-- [egg_name_custom : string] - Custom name for the egg item. If empty default name will be used i.e. 'mobs:chicken'. + +-- * [dummy_size : table] - Size of the rotating dummy inside the node. + +-- * [dummy_offset : integer] - Offset on Y axis of the dummy inside the node. + +-- * [dummy_mesh : string] - Filename of the model used fot he mob. + +-- * [dummy_texture : table] - Textures used for the mob. + +-- * [night_only : string] - If true mobs will spawn only during the night or in dark areas, default:true. + +-- [sound_custom : string] - Custom name for the sound file name if differ from default: i.e 'mobs_cow'. + +-- [*] -> MANDATORY - has to be filled in! + +-- mods what should be enabled and loded ENABLED_MODS = {"mobs", "pyramids", "creatures"} -- mobs properties - setup all you mobs here MOBS_PROPS = { - ["mobs"] = { - {name = "mobs name 1"}, - {name = "mobs name 2"}, - {name = "mobs name 3"}, + ["mobs"] = { -- MOBS REDO CONFIG + { + name="sheep_white", + egg_name_custom="", + dummy_size={x=0.52,y=0.52}, + dummy_offset=0.2, + dummy_mesh="mobs_sheep.b3d", + dummy_texture={"mobs_sheep_white.png"}, + night_only=false, + sound_custom="mobs_sheep" + }, + { + name="cow", + egg_name_custom="", + dummy_size={x=0.3,y=0.3}, + dummy_offset=-0.3, + dummy_mesh="mobs_cow.x", + dummy_texture={"mobs_cow.png"}, + night_only=false, + sound_custom="" + }, + { + name="chicken", + egg_name_custom="", + dummy_size={x=0.9,y=0.9}, + dummy_offset=0.2, + dummy_mesh="mobs_chicken.x", + dummy_texture={"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png"}, + night_only=false, + sound_custom="" + }, + { + name="warthog", + egg_name_custom="", + dummy_size={x=0.62,y=0.62}, + dummy_offset=-0.3, + dummy_mesh="mobs_warthog.x", + dummy_texture={"mobs_warthog.png"}, + night_only=false, + sound_custom="mobs_pig" + }, + { + name="bunny", + egg_name_custom="", + dummy_size={x=1,y=1}, + dummy_offset=0.2, + dummy_mesh="mobs_bunny.b3d", + dummy_texture={"mobs_bunny_brown.png"}, + night_only=false, + sound_custom="spawners_bunny" + }, + { + name="kitten", + egg_name_custom="", + dummy_size={x=0.32,y=0.32}, + dummy_offset=0, + dummy_mesh="mobs_kitten.b3d", + dummy_texture={"mobs_kitten_ginger.png"}, + night_only=false, + sound_custom="" + } }, - ["pyramids"] = { - {name = "pyramids name 1"}, - {name = "pyramids name 2"}, - {name = "pyramids name 3"} + ["pyramids"] = { -- PYRAMIDS MOD CONFIG + { + name="mummy", + egg_name_custom="pyramids:spawn_egg", + dummy_size={x=3.3,y=3.3}, + dummy_offset=-0.3, + dummy_mesh="pyramids_mummy.x", + dummy_texture={"pyramids_mummy.png"}, + night_only=false, + sound_custom="mummy" + } }, - ["creatures"] = { - {name = "creatures name 1"}, - {name = "creatures name 2"}, - {name = "creatures name 3"} + ["creatures"] = { -- CREATURES MOD CONFIG + { + name="chicken", + egg_name_custom="creatures:chicken_spawn_egg", + dummy_size={x=0.9,y=0.9}, + dummy_offset=-0.3, + dummy_mesh="creatures_chicken.b3d", + dummy_texture={"creatures_chicken.png"}, + night_only=false, + sound_custom="" + }, + { + name="ghost", + egg_name_custom="creatures:ghost_spawn_egg", + dummy_size={x=0.7,y=0.7}, + dummy_offset=-0.5, + dummy_mesh="creatures_ghost.b3d", + dummy_texture={"creatures_ghost.png"}, + night_only=true, + sound_custom="" + }, + { + name="sheep", + egg_name_custom="creatures:sheep_spawn_egg", + dummy_size={x=0.6,y=0.6}, + dummy_offset=-0.3, + dummy_mesh="creatures_sheep.b3d", + dummy_texture={"creatures_sheep.png^creatures_sheep_white.png"}, + night_only=false, + sound_custom="" + }, + { + name="zombie", + egg_name_custom="creatures:zombie_spawn_egg", + dummy_size={x=0.5,y=0.5}, + dummy_offset=-0.5, + dummy_mesh="creatures_zombie.b3d", + dummy_texture={"creatures_zombie.png"}, + night_only=true, + sound_custom="" + } } -} +} \ No newline at end of file diff --git a/init.lua b/init.lua index 554e21d..fbf4c33 100644 --- a/init.lua +++ b/init.lua @@ -1,412 +1,8 @@ -- user settings -local max_obj_per_mapblock = tonumber(minetest.setting_get("max_objects_per_block")) dofile(minetest.get_modpath("spawners").."/config.lua") --- main table -spawners = {} --- list of mods -spawners.mob_mods = {"mobs", "pyramids", "creatures"} --- table holding all mobs info -spawners.mob_tables = {} -for k, mod1 in ipairs(ENABLED_MODS) do - print("********************** key: "..k..", val: "..mod1) - - for j, mobs1 in ipairs(MOBS_PROPS[mod1]) do - print(mobs1.name) - - - - end -end - --- check if mods exists and build tables -for k, v in ipairs(spawners.mob_mods) do - - local modpath = minetest.get_modpath(v) - - -- list of mobs and their info - if (modpath) then - - -- MOBS REDO CONFIG - if v == "mobs" and mobs.mod == "redo" then - table.insert(spawners.mob_tables, {name="sheep_white", mod_prefix=v, egg_name_custom="", dummy_size={x=0.52,y=0.52}, dummy_offset=0.2, dummy_mesh="mobs_sheep.b3d", dummy_texture={"mobs_sheep_white.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="cow", mod_prefix=v, egg_name_custom="", dummy_size={x=0.3,y=0.3}, dummy_offset=-0.3, dummy_mesh="mobs_cow.x", dummy_texture={"mobs_cow.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="chicken", mod_prefix=v, egg_name_custom="", dummy_size={x=0.9,y=0.9}, dummy_offset=0.2, dummy_mesh="mobs_chicken.x", dummy_texture={"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="warthog", mod_prefix=v, egg_name_custom="", dummy_size={x=0.62,y=0.62}, dummy_offset=-0.3, dummy_mesh="mobs_warthog.x", dummy_texture={"mobs_warthog.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="bunny", mod_prefix=v, egg_name_custom="", dummy_size={x=1,y=1}, dummy_offset=0.2, dummy_mesh="mobs_bunny.b3d", dummy_texture={"mobs_bunny_brown.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="kitten", mod_prefix=v, egg_name_custom="", dummy_size={x=0.32,y=0.32}, dummy_offset=0, dummy_mesh="mobs_kitten.b3d", dummy_texture={"mobs_kitten_ginger.png"}, night_only=false}) - end - - -- PYRAMIDS MOD CONFIG - if v == "pyramids" then - table.insert(spawners.mob_tables, {name="mummy", mod_prefix=v, egg_name_custom="pyramids:spawn_egg", dummy_size={x=3.3,y=3.3}, dummy_offset=-0.3, dummy_mesh="pyramids_mummy.x", dummy_texture={"pyramids_mummy.png"}, night_only=false}) - end - - -- CREATURES MOD CONFIG - if v == "creatures" then - table.insert(spawners.mob_tables, {name="chicken", mod_prefix=v, egg_name_custom="creatures:chicken_spawn_egg", dummy_size={x=0.9,y=0.9}, dummy_offset=-0.3, dummy_mesh="creatures_chicken.b3d", dummy_texture={"creatures_chicken.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="ghost", mod_prefix=v, egg_name_custom="creatures:ghost_spawn_egg", dummy_size={x=0.7,y=0.7}, dummy_offset=-0.5, dummy_mesh="creatures_ghost.b3d", dummy_texture={"creatures_ghost.png"}, night_only=true}) - - table.insert(spawners.mob_tables, {name="sheep", mod_prefix=v, egg_name_custom="creatures:sheep_spawn_egg", dummy_size={x=0.6,y=0.6}, dummy_offset=-0.3, dummy_mesh="creatures_sheep.b3d", dummy_texture={"creatures_sheep.png^creatures_sheep_white.png"}, night_only=false}) - - table.insert(spawners.mob_tables, {name="zombie", mod_prefix=v, egg_name_custom="creatures:zombie_spawn_egg", dummy_size={x=0.5,y=0.5}, dummy_offset=-0.5, dummy_mesh="creatures_zombie.b3d", dummy_texture={"creatures_zombie.png"}, night_only=true}) - end - - else - print("[MOD] Spawners: MOD "..v.." not found.") - end -end - --- start spawning mobs -function spawners.start_spawning(pos, how_many, mob_name, mod_prefix) - if not pos or not how_many or not mob_name then return end - - local sound_name - -- remove 'spawners:' from the string - local mob_name = string.sub(mob_name,10) - - -- fix some namings - if mob_name == "sheep_white" then - sound_name = "sheep" - elseif mob_name == "warthog" then - sound_name = "pig" - else - sound_name = mob_name - end - - for i=1,how_many do - local obj = minetest.add_entity(pos, mod_prefix..":"..mob_name) - - if obj then - - if sound_name then - minetest.sound_play(mod_prefix.."_"..sound_name, { - pos = pos, - max_hear_distance = 32, - gain = 10, - }) - end - - end - - end -end - -function spawners.check_around_radius(pos) - local player_near = false - local radius = 21 - - for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do - if obj:is_player() then - player_near = true - end - end - - return player_near -end - -function spawners.check_node_status(pos, mob, night_only) - local player_near = spawners.check_around_radius(pos) - local random_pos = false - - if player_near then - local min_node_light = 10 - local tod = minetest.get_timeofday() * 24000 - local node_light = minetest.get_node_light(pos) - local spawn_positions = {} - local front = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z}) - local right = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1}) - local back = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z}) - local left = 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 not node_light then return false end - - -- make sure that at least one side of the spawner is open - if front.name == "air" then - table.insert(spawn_positions, {x=pos.x+1.5, y=pos.y, z=pos.z}) - end - if right.name == "air" then - table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z+1.5}) - end - if back.name == "air" then - table.insert(spawn_positions, {x=pos.x-1.5, y=pos.y, z=pos.z}) - end - if left.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 closed 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 = 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 - - -- spawn only at day - if not night_only and node_light < min_node_light then - return false, true - end - - -- spawn only at night - if night_only then - if not (19359 > tod and tod > 5200) or node_light < min_node_light then - return random_pos - else - return false, true - end - end - - return random_pos - else - return false - end -end - -function spawners.create(mob_name, mod_prefix, size, offset, mesh, texture, night_only) - -- dummy inside the spawner - local dummy_definition = { - hp_max = 1, - physical = true, - collisionbox = {0,0,0,0,0,0}, - visual = "mesh", - visual_size = size, - mesh = mesh, - textures = texture, - makes_footstep_sound = false, - timer = 0, - automatic_rotate = math.pi * -3, - m_name = "dummy" - } - - dummy_definition.on_activate = function(self) - self.object:setvelocity({x=0, y=0, z=0}) - self.object:setacceleration({x=0, y=0, z=0}) - self.object:set_armor_groups({immortal=1}) - end - - -- remove dummy after dug up the spawner - dummy_definition.on_step = function(self, dtime) - 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:"..mod_prefix.."_"..mob_name.."_spawner_active" then - self.object:remove() - end - end - end - - minetest.register_entity("spawners:dummy_"..mod_prefix.."_"..mob_name, dummy_definition) - - -- node spawner active - minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner_active", { - description = mod_prefix.."_"..mob_name.." spawner active", - paramtype = "light", - light_source = 4, - drawtype = "allfaces", - walkable = true, - damage_per_second = 4, - sunlight_propagates = true, - tiles = { - { - name = "spawners_spawner_animated.png", - animation = { - type = "vertical_frames", - aspect_w = 16, - aspect_h = 16, - length = 2.0 - }, - } - }, - is_ground_content = true, - groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1}, - drop = "spawners:"..mod_prefix.."_"..mob_name.."_spawner", - on_construct = function(pos) - pos.y = pos.y + offset - minetest.add_entity(pos,"spawners:dummy_"..mod_prefix.."_"..mob_name) - end, - }) - - -- node spawner waiting for light - everything is ok but too much light or not enough light - minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting", { - description = mod_prefix.."_"..mob_name.." spawner waiting", - paramtype = "light", - light_source = 2, - drawtype = "allfaces", - walkable = true, - sunlight_propagates = true, - tiles = { - { - name = "spawners_spawner_off_animated.png", - animation = { - type = "vertical_frames", - aspect_w = 16, - aspect_h = 16, - length = 2.0 - }, - } - }, - is_ground_content = true, - groups = {cracky=1,level=2,not_in_creative_inventory=1}, - drop = "spawners:"..mod_prefix.."_"..mob_name.."_spawner", - }) - - -- node spawner inactive (default) - minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner", { - description = mod_prefix.."_"..mob_name.." spawner", - paramtype = "light", - drawtype = "allfaces", - walkable = true, - sunlight_propagates = true, - tiles = {"spawners_spawner.png"}, - is_ground_content = true, - groups = {cracky=1,level=2}, - on_construct = function(pos) - local random_pos, waiting = spawners.check_node_status(pos, mob_name, night_only) - - if random_pos then - minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_active"}) - elseif waiting then - minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}) - else - end - end, - }) - - -- node spawner overheated - minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat", { - description = mod_prefix.."_"..mob_name.." spawner overheated", - paramtype = "light", - light_source = 2, - drawtype = "allfaces", - walkable = true, - 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:"..mod_prefix.."_"..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:"..mod_prefix.."_"..mob_name.."_spawner"}) - end, - }) - - -- abm - minetest.register_abm({ - nodenames = {"spawners:"..mod_prefix.."_"..mob_name.."_spawner", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_active", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}, - neighbors = {"air"}, - interval = 5.0, - chance = 8, - action = function(pos, node, active_object_count, active_object_count_wider) - - local random_pos, waiting = spawners.check_node_status(pos, mob_name, night_only) - - if random_pos then - - -- do not spawn if too many active entities in map block and call cooldown - if active_object_count_wider > max_obj_per_mapblock then - - -- make sure the right node status is shown - if node.name ~= "spawners:"..mob_name.."_spawner_overheat" then - minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat"}) - end - - -- extend the timeout if still too many entities in map block - if node.name == "spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat" then - minetest.get_node_timer(pos):stop() - minetest.get_node_timer(pos):start(60) - end - - return - end - - -- make sure the right node status is shown - if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_active" then - minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_active"}) - end - - -- enough place to spawn more mobs - spawners.start_spawning(random_pos, 1, "spawners:"..mob_name, mod_prefix) - - elseif waiting then - -- waiting status - if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_spawner_waiting" then - minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}) - end - else - -- no random_pos found - if minetest.get_node_timer(pos):is_started() then - minetest.get_node_timer(pos):stop() - end - - if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner" then - minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner"}) - end - end - - end - }) - -end - --- create all spawners and crafting recipes -for i, mob_table in ipairs(spawners.mob_tables) do - if mob_table then - - local mob_egg - if mob_table.egg_name_custom ~= "" then - mob_egg = mob_table.egg_name_custom - else - mob_egg = mob_table.mod_prefix..":"..mob_table.name - end - - -- spawners - spawners.create(mob_table.name, mob_table.mod_prefix, mob_table.dummy_size, mob_table.dummy_offset, mob_table.dummy_mesh, mob_table.dummy_texture, mob_table.night_only) - -- recipes - minetest.register_craft({ - output = "spawners:"..mob_table.mod_prefix.."_"..mob_table.name.."_spawner", - recipe = { - {"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"}, - {"xpanes:bar", mob_egg, "xpanes:bar"}, - {"default:diamondblock", "xpanes:bar", "default:diamondblock"}, - } - }) - end -end +-- API +dofile(minetest.get_modpath("spawners").."/API.lua") +-- Spawners for mobs +dofile(minetest.get_modpath("spawners").."/spawners_mobs.lua") print ("[MOD] Spawners 0.3 Loaded.") \ No newline at end of file diff --git a/sounds/spawners_bunny.ogg b/sounds/spawners_bunny.ogg new file mode 100644 index 0000000000000000000000000000000000000000..0fa0f46e763f2c81450c3bf8cec2831c2c557fee GIT binary patch literal 37905 zcmagF1y~%fMCIcLx7<9mi*7X z=Y02lpZm_!+uPGMUDZ|ftDfrFSw%}rRR9L~*AYo5#sA!_!mODDk%BxNT}-T9pF2Qe zmCs+$!xQxPs|BR^Jo3Mf=aJ8p@ssFNOu;|@zhfBoA4bejx|X$*6_cWiCApooiN;^{ zt;;Qtv877^6|0Z7mu7CG|%fT?(O z0KfzQBPuXPl7%$5C^?VTJ1tr2xz+zRA}u+hpTIPlW#GRma&|L30DuDmXpv(JcBO45 zAeIC)u`am~YX$BSa>PjG4G412)f-cX;>KcIhY2t>61p}#0JV*f6h#QG%5!BBP7z7~ zt-^?1hA2w1Tu|sra|2OWhscBESPu%56nG9w3u1YG(l$xjpvsT405 zlyNww*~C@V969kdII%#w*utjTISD_koVL<$A;UNI(Qy~?GeiwF0 zSN1_yK4_726B|yJ8~-Ku;=i2m>~;VUVj=E#CLV@bLxpkHg+tSof6-Nb5o(HOi~R4$ zhrf7%DnjweBGo1Ui7npvuUP`1Yzgv^MA80{1ic_UZ<{=0D&uk-f|0S4TZWrC`!zx> zlcu#SE%UDj?IsAfpuPl;r1$5hPi44HNTX#G{nPTs&P1##n}PNb?qy*N5E?_Tv!2O7 zEL+loj@6#Z*ez|vg|;G+GijPy)&Al4FIbcrWKDd9Y(hswEN9xbBI`q2w`N%<}BN+G;NbVPlV1i3gOp!$D7Kf3P%Q6HmB#nuckSPmNQX!-%atr*cIXM6X zWBx_)e^q~>{11u?6C>$HXdA{@M;V^0%H9c{!`fa9{khNi34-|0t8^#LC#z&@#=+ zsLIB#uBNW(VXytsedTkA{x|paMZfjM7{iyL{}WjM9XS9rXoCO7WU@&#%V1WJf(Y_I z4*svmamF1?ARbPjlC7tbpJ5okU{}0kpT-eaW|vpR)1St3pT##<<umOcWP3F+Znu?ZIBPsu|Nnxdo`X)t3d z0UMaQ7~6C!t6)ZYxGnAMzL@G~xL~iJ_AgfQxPMu3sxLNk zD7&dEtD9@9scUPuJl>ZyL4ZtD7)=1Vu~+W7Bv7eh9$ z{Wb}nIWNw;L#f6K=Ek4h*J-UYtZnj3%QI-p%gf4}?aQmHbo2Mi^UFu-Ez7GbN9t=T zs_hP;)augmdWQ0HhKl;i`*McE=F;-Es*(EI%<786=2O&OhQl_e^6Kh}`lDxRTh-x! z^I_ZDcg5h*;)N^hi%Sd&Gy6vU>Q4{bm>bh1gw)&fc2(VvKpD*ZhD*ggG~?r+l^&ERBU6=%g*0Bx7CmEWE5AUpE#iT-BDNc){kGpli>+kl`v*wJ@g=10|T+ zcg$z_p8l8SCN_)%3no?1!s+T#5~0F(mvy2c$ulNUR*5Rn&=Izh8Je;WP>WW%L!nUAKc-_-)%Z;asVZcFRhAkG z1&gY_G#z>XID$^-=|P%}oegyNb+vg~DvB7ytU zpgB%4!E@>Xy~#f3AJI?(^mG79fb0=JS6QyH|4vN)-9rAqC{YH@v#>Ovck2OyS4jV4 zaoH~|4twa%d_g$+H^8-IOG0Zq0={#yHaW1s@{ zMeZ|ND8yu-sCvc-MKIJ2|MUgN|92lI&)z@Kf&yyqpX-v9ME*hxDG%BQCV_&C_HT=WjNL;DsUb{;c3s+2D8=OcN$7l}LzWow*cY zKf!!5OA)TBitT=uNwl)!CsP@g-pXVR8QO%v8JEf?k1^=3k{k(mi%G%uK?sCPFa#A8 z3Uii*zA2w*r$!Vskf8PqBPJr0`@ z(@Ki8l)E8AL=o1yJK|+&Haj+6JEmV zPjMzQJd%SBg&v$h|0H+3c@ znN@lftFTYf?~sY0%FdU)0x{=5i!t#^qsESff_=XdcoYU1_?ibFy_r+cId&+V#Ebz; z=_toC^6|D9xN&vDF^n?JFCk6I1KFu;vBC&PXxLwuM*cW+^Qo!#H=9Y$NnCnOKYeBV za>(U>q@wCSvY?64?yIBuLcZe^e?|J&$wvgU#b%)>z3hR)qf#_pj7J=KapQFoEMrG? zHsTc%A}_NSni%FHlkJDRViy*m5-dq4%9^di9&h?7ZRYk(^+5c}CKKW_1bVHjm+v9^ zxs2|)q(#4JU$wos7cRDTn=2Z@qBlP*zM%LqxNudN0hvKKAXYUjB_q5V%2_*E!7?fn zNVBUz8nNyjn-yN`dU$xZ(Qq5TgE{E%n!YM{oR{U(WVzQP zPGyr^6!}HM9LHWiG*y?Xw2}Q&Us?p?CgG@NzIiYAx?E3nN?qWv-z4;sjfTkdYyIP+ zN7rEAd%L#6Z*TnbOH(V5fFis9QsPKC%3?n^M2lMgNK>OKY!xdk6Tu&!S#c z!_uk_u@Fg7$Ek4F)vmN3T9kGN0RpM8azSZMv%rLk@LFGAA)|MtR{hNKjE}{W_UFcz zBTutI60DblwjSwQJPy~Mt|wo@yf7>ES9Baj34Ws^NK;keM^1n0vz)=Y`dwEsy8ntp zL>YD>9po*;Y1EG({K4`EV?=_+%SeFAXEty)Jc|{hR->N9n%~}>TF4#$budgJj|w5x zuReM7qR%@-C1Y*H-!e3Dgs^f9pDYOG@gCGz;vZt+^p9@d(v?#G$Qlm->U{Jy5l8kZ z{1to?vky*d^OwvI+UvrLgEc=yt0eH4f63~j9SiAHXoKWX+jVKjp?4O~ssvcQ zeJvHLYGXpEP9(Qn9y!4#;T?D}`Z3JXkqpDpfgWjq7Ro~-jGDSSC63>Y^_x~=$kS7kQ^e?t zZy0M|s2nN!k~f4s2xdk9u=rhF@oC&X8s5T>lqu#X-R-`IP)fs8Sf~-)S`K&yTB2DrLJEf2!;U+z9JspPYOeNfPvmjOP3<~h zyE)kGIpM_*w2vCmp3}#(M_$~0^X8qMzChh_U+2IOyG~5(va>Jhw0u(n-locf#AysE zs(rbkQ;Nsql%*{!HPmSCohGj_@jRI*QuzHIN2B~^Rk6c=#|ogegsT?$z%C336q^Qo zK>Yr)G_-*~C`$8Vuu<#vUi{DE|Gy_Ue>o7^#4eE~96v z^UpSB^KwjWmL|Aw1JVT@u!A2Surj>;ZR7GK9gq}SNUw-q-F_xs!$xD<{Js|Kei`!( z5!QCJJlxP_eK4JGkAhmKoe^(X_YmFQZ1r_zQb2W10oO=N$H6&c34^R_#u!-amz#1q zZdqY(i0j2CSIvcMT#N6;ntszWT1j$G4Qm>~_$)8#sa&^GN5mN$wIk_L@~O)}O(cPK z$0KUZJ~_J}({Z~AtQWvq3M>lcB|;eBM6kb%_u_7*oO2|5&pU7_E|cppecV6JFxFqd zuQ*IL0OfN z^W?#j5quEw9_M{_yW*ZvbKTDUK6ce11gr3+z50>K>V%(Z#96r2p8-mYO=}Nzn-4Hi z@v&bGM6wJR?^533d{>W|4*WXzhHB6exHus_>5E@q9k86iLqPK&Xq4wVuRmMCf<5hX zq!1c+m{QwQ*(vW&I^y@$k82P+^R(0yrMg(q+OLtTt~s8I$HDKjNF-9r4WB|`^#4L_ zal@gP%C4lgO^=pA3S<}K1bkrN#tpzx)us$6cd<^HT}CRty1O3ROHI;Qp0xe!saT9L zAk0|TmadRJhq z;^q5xE}89&`(-Cy)E5o~%A+L%^f7*(u8~@~jL5>l6rHsi&X@%5jD|6qVqQm;SO!UiZNu!QxB5 zlGJ8S>ZnAnyOXaJK^-V@w9RQx!4X*TgwdVwmKO&1-z708H3B#&xIYJ#e}aF;F3g<~ zGn@1P?p=B$EpQCMWkrq={ZZW^lQZjW{o2Ijgkh*K1AbIH$};-5-p9(n1dO-!E{d`w zoC|os$;gLaYFOmOKUWmq6c&eumbpSM2lfe&YvY;3^YPqLydeSu%{4k$a^8q!v*Iz!Ap-1~Z!;2*MKC_3vHdC zmy$2JkI;p*-UjKeDE4i>*;i>tfY_Rj<~al*>3=#|+xUe1i9;&AM<<%{<@fv4ykreb zQpUDnqZr%^cl|sHcwZ9EQ8EV+M?7D=Kv9x87n4FVyp|Mr2=br#i;V7R&r+%1+iarZ z5Vn4{4t*uOYQoAg=V0bFb41gt6pIvxSD&aqb9!!Yj-kWd%@iEBuB^ zTE?6<8$~~yquE0&iWA9Rc%j*9i*sd6?Mw%(+f{p_IhNE^9EuP`r0&np{c@(^NsO1@ zR5w50JaT`3>wtGSH3c^mkCXgpAcP;n|u9klY%!*`8se=6jw;Ot;MO$D`c{^OL!H z`x5!QOXmm5=9C35hW&=jxCMLJupEi^fHfE3c4bwXykfP9eJmQL%_NvZb`v9j5iT!g z7~!y|UiBdGx=zPDi_odaFcp_L>+uCn69!-h;>T{W>z4iY9os488yC@)lPn?A5R+SV zF0K7rt4Rxhxuj9|EBe|sx*7aqq_hoDKzzDXAbB3HJMSE3iH0Epq{xqJGoM#b>z=VM zhap|ZRtd)J)@tY^L&2t74P7XV*1HYs~`rj2v@E zBoDTK9ksmSmlL?xjRIAIQF02vJ9uyzjGYP zB(w6p{^Sn7A)$&&e_V$Qo)#OD!MVY66ez>9!e#$Sz#jRz7W$3Ag4rgB!?3J>Wl#~q z$Q-=nO{mi+t!&w(Q?qqdb5jTp@18y92Dm+9R-%`;f^0H2{6U=Xj%@{&%T3L5i1f{C z$_5;d&HL{rE3CXa6|tql>s3=0tKRF&@~GWL62|v@rFJr)2SqJ9jF*jmOqO>q_o3z^ zQ?TMuP&KnsWC!0FZ1&Zfbwtqt$&U|k8!+A90R&~V_C9YTYiF~EK{QLQ;S4c;m+}U* zrtu-1A_0)uRU}9V-HD|OO$wbKvNhk&gJ(Uay!f5%*2Bu)VzkfR!(J-B5!dh|6oM#k zYfYqySU3tIDDyoHGdbezs(+rR;Ap0%?moI41r-|L!VTsG?PE+wq_?=Ji@uveRM&KQKO|g-L10dqtp+wTR z@Ue#P_%Yzmr~(~JvLChSUg`bi2^C*aJR^6H;OKFWUj|pk%f;Ob*1bQ`qKMf5C@xRJ6qI`~mRlBYULQH5uhEM4*o-@JTX4n#Cq zbNkkOGl;F}FQ2|Fz`ri&^k~CjxuBi&nrdC}{hVWG z0b{h5NdDdH>Rw1AOYRyavX~P=%g|LV?#jMgvjz80v}-?5L3! zav47?4Jo9(uy%sLc=>nk>`+46>Bk6w5vxfs*8E#_p)_;ZIg!!NPy37LnzG-Ner0HD zvG27Iwb~Tx2sxbNQ^0jPHH?lJ=wgH_ya5dG)e42}bYSt=Zj$l)Bm#&A%h?$;trItU#MrY zX-;17RVi2gX9STJjtG(i>NRY4t1ktZ2AgEs@{+;V(_JNwt47?7ntJ(>WXt$3`EB3U z9%0hrnrlbyi0jPyy)e$KG}Hc}`;J=hW2fRMFjR(2oZqF8#FD}4kNI&+qJnW=Eq*#? zg*H&Yi^_#cU>JJ@l^}oNjv$E*y?3{sE+NLswEj}x8+;SO%-hc0ATO?VI=EeZ*3kE1 zx89*j#>0*T=u8co0g(VWS$3PnyS};Q%LKBS1Q&1(0vGRX_#6i--Zw*5>`BvDd$u%} zKGxLi%I3#eX3}xv2jxrs`W*W-Ty)krz$wZ4hv;5FoAxe|ftLBV%8ll(u5N!%k8ur| zQd(go+~LKnPcSOt*c){XCS@i679(X*oOWK%-73b)gcfg(ep=O0cX_;%2lTfu`AyT; z(k{Z@#Hy5j^;zpqQS&=g(wIc1`;ih&qfZsZmsjJ#sgHKkdQvDc`{PYeEgkDCt3+?z zEW+O-6WSu)Up*35Dlt83FKs)-GN*k-uj<9)#{j?{)+0nUB(xm_w7a*uZeuM~6bR?l zly7tLF!ELH&mKt|&sCb=ZDk|t3@baRzkIo}#3H}zd9j^{mY?n;up$2yST>TdhJ=u; zuznoGUjDjTUz55VCbtlCdJ{Rl@RD{ZV|>@;j;U2N*D!bQG!~7ijk+X2+Z8s02I+`KD<+OBKD!QdozSA-%~eMl@c?h3oKp=2*jX)1~4QHzJ`)m?gOO9ZM$z#ytel;j0m z+P4o3sC07oO@6e?;p+Qy%F_y|%EZ5pi@^<#Rk{yX+eV|sL9+2YuXH`!Z!pXV-Lslf zFhhh5rQ)kQi3ONmWvnA*6CGyf;xz5Cf}`_@F8Mp`ict(N7M98lc1T#^?QWGy@xo*% z#%{e~%|o1BS&S?WHQp_GKgm}y;x*i*57N_k_k$ie*cD=oTaNx-8Y;%F^3-ymi&6Jhe;mOS>OC{GeRu6 zAk|he`|u*kjjN8_1TjZXH=B90N$WcW$3_bslx_Vl~M zS}gszZsjYKuyI4TX|^nRj~50M+@t`r$6r~DZ+z;%cB{QHDooR_B1}oV^VjzkQJ$-& zXX40`9#H6r3ykGlpccDomjgL4#;5Kw!01Kx+N`?C$>J`sJ#7cL+hrN5Yf5!Qrv6D( z`d&>p1q!}m--=E#;oUFxfsx3UIMQVikUb*4{+KK-t3&fju&d9J99;X!86o(Q4_~h` zFg>17GBEikp)i`Z_|EjQWVk!!C^GSe-WRK8>Li9aUz|Zg#9)weC5NfZHj(fpic`=8 zBRdh^r!=+8P)&Jb4>3`^S7z8hj$G_k-sRt3(gJ+P?OKFY3=Dlod+u5ri7P+koz2Rs zCjaR8ar4pac`#l1zM??GI^2OPd?WzGB|!etxk0wy$y{S)l^?W?6<1;7*6mf%)1ZRxe1}y;zZRy(hd{p-6{Q7Rc36zikN$k z8v@1izUug549b-_6swX{Un6B6`f%n@PE!dm(#J zb?>4>HrL_BlPE$8=Xf&DCQgUhb~Z(J-R+--kd-zV>=5WX?#wlOpI!V@R93Z+abas>jo-9}>O%7su5tW(0Mg!^)) z8bTy5l7DFsbPj**&*o6XrCNd8w$J&fvP6<~4mU&v;7n=0*bz2#sQaVf@|Dc3c%=8l z>fGOEF=07gGWINr_oM0E%UyboRzv-C(H`I()?@yjhE0|HI~g*Vk^a+1)3AEGJ89SQ z14D@Ys`{#1sOJhLNqg?09$V3OqNFjuW}dg8=-YS6mIUIPKbV0`m(R?;ShS|zywmFG zNyJ7+T%*x~fx2d56J%VWD{xoAE{_x?e}Z7&fjo(bB(;&H0-kJ`5P#;CaLtD3{aq<9g_E4^RZvNg<| zptOPNO;Sk(6e9Z(OU-yTrr8_p!XJFs>w0BT&ZNA&r7|(Y9k>rB8CTG7P%zOKUD?#7h;Fzk;;9yQ)N#b137 zUt-!=QRXtfTyUmv+^k{ey%21}Z9!_Q4IK(kc_+N1NF<+R^A1)i)=TTYU8<|~Nwf-{ z!=k=*Q=xOgZ)v^5ZoR;;oKmG}$O@Nt9O7zFcvMX%v%;KREQ*+o-xnGf4ueN|J>Kcf z$qF)MEmp1$j!A^yS#CY zyc?%MFLygM{cd6`4b-~xelMYLjl!kB8ApZLPda-tIUVL^u_JDm{+-I{vSL5u*g}N) z#23lGtIG6|_&?@2dJEx5ZC` z(3o;ue8_wc4gxsrPv+a{YrAC2bZaz^_eba9*vv1^SR+ zqhr#VZz4wNk7z>tu1uw^Dd_0F(iw+OJJ+N^2l=TuD&qqTEI>1->k?32-gg_psq?lf zLXPCoYwQib<;{E7->tU~*7i1snUr&H|2&%WoINP+sz2`E-F0^2-bs?^{`M)4er)^dw;7GfpoPMMMwglqFS_|iK!kbCbx-pZVY}IYZRDcHkEKpm z=JVp@k2k+Kk9GMchAYtT5?~zp?30O!>zFdUJJi{=krtTD+^@Nm1S>Kh>TYS!4cwnM zqyS$>re+lhj2BW|T_ZFg3ph+G#@EyJi4BLVgl;-M+TUz?cue2&eR)SWoG~Vd-d3G* zGa-09py22zNFf+H@l@V_px;)9Jl&FIen&Y3<2{;>kW(=&SBmWyZ~2z%XHQUslIMi! zOp8j}u%1(lv0rD>&a$iLPgLa$NjOztoyK?@h1Icd;T4A)-h@2SX^?DoVe!kUd2(S$ z4UFAR`^1ZSE`NGj4f>8O55>}@`7fli|CPHEQG~nq_VJ+ zOYGe4Q0hb3n4Oou&L`1$Kv!8gZcQC@>sM?ZE6HkJlEx2z;w zzEyHRg{m}4za7hkW>-@+UDutpQI9WMk8e|OL5GxJHk_*#9-a0*D#Bc$rzaL^JgjcE z+uHX~9PNb3dYSq+HOLo`7*<$6S9f0x6*?AvrA3(*#FT=`W?tZ5FEup(`%%O5%MP;h zmOL2i| zx>WTt8z@MtcKJCoz*ARLRPnVL9Bn#(z<)G;wiUzd!S*|J`c+@1og{&-Q4gI3H4+L9 z3ITEwHH#1lf%ReD21;0rC-{3C3`B9)4^D#a{ob4c_l(tQUf@Hy;Q6j9L$s*=OWTuZ z`^Kn@xl(EzWTXV|kDeiYBe)4C@Try^5g=jWKF8+=SOoUD2^eHGR^6q2p$8XAmX#dh z&4do^mn3GVsAHtFDfP*9v;0mlg&^cP0ypBY%L-UEHQRJHjFloyLoOfshOOwXv8WiS za~@FxWS$gIFe9->`R`oIwb=^j7;(EX;1hWz15g@2aLWZL_E>)6`~7Wfe$7jp64zQW z-8i}8K!*5>;24S5qrp58Jq8eb>_!zXjHiNxX7L(MWjeNdDnWv1c_1Z~Qr{sp|xwmAVH}k89 zy?;1LNnA`S_D;=IP(+n&pl&|k+xTt#i$>nW&6(DA$-492dQ7|jhH^}4=PQaH&Y>vD zZXbkmWa`~0h=@xSzrCMg#%!mwEvaztmsz321!-dlWuu6#O3mJVm&w$)yV(q5WBpk4 zeQoBTfD&DLDWv+1v3|s{Zh8z1E7PEr#rvT6O^(vs{OG(-4Ln`H$*D-a;KxCkCIS+- z7w{^X4!87_WuCw``jwD< zz~%I#P0KDdx}$?PcN^^8o8K9S#Qk}E-Bdiu{At1ar`+BiRVXxBAxK<>%(YE6-M0STTp-r=nxE<63fcCPEswQfp}W`G#)w(d))jfws4s4drGkYL{+9Z|Y|Z0&+nI2CF;$Q|h#1sJ;p ziNWzWzNT?L9T`?!@f6MR^gZjX@D>FN`u60QEx;*{u{vE#PwhIS_nz3cOCjv$sp%Krl1L7fVVNz( zv>^P#KICHc#1#oRLcYo;>9>>0n3ANWH0bp2u(MO?)m3l6Bb*K2&hW}!JoJu;%h2>b z`%r!EYtr@OP!1@3d>Dfb2%6DVsn*ZTbQZSTH7E3?tO&c9)E+K}zL=)8U_g^`-tBkg zm-J}kY|gWNC5B5t2lQCT3NgdeOL)zMHaT#h;6`!O7-`UAe_S=`)TftEcUO{z!r+|{ zmP9Cv(FvfJFMS#tC$!Z9X|*UgEy}{~Q1Kbl$azC$8*!P)161BdvUH;c+#+?yXf16! zVe^xh6!G1il=%=5eg3Ik;`yUraGP+-#ATxiqwfk1MGDw31&vrq=mvdyqLLD@9yP#Z zV(n=il=S_Wmehp6R1%%ls(Gb-e)Soq5`DBbkOh=%0CULKJnzBJ%|$$qXvi}BZOva_ z+b@Ns#w2Zk`tZ*<+4r=}IQJKggq|}JQ57GCf5F3gI-gGJA@smMJ}3~T#O)oDom={M z-~McS^GUNS+w^mOiuE05H(Vbmia|G;i7`;iA9>1J#%?}iwC>viR|eUGQy{*6rs;{u z_e6;;OJt>39*0tPyKg1m3qVkPQ6d7N+u>-_(DDG;U-WHkHCg#xj$?-E#$}%a=J(Wf zZ;WhSak2!%G+yzA&qSjHwDNrTs{Dl77AM^CHR&v z98tU<#Eg+E!{ev!x|j2nu|ab&|ws8FEki(d}H#kev+ z=a7sSZo!FXx<(x}Q8clbeE9)+=dPKwmHUO6pJ_ctNN2gosbK_@7vaL#{=h19YAh4s9C51q{7(Z5v067umoZKdL)t zCF%~+w@%5nrHhU0rUd!)pN4ZKjZfm_7r*%g1vlr+D#X5YK`cpv9Q|hAetVn*enCd9 zzL+t!USwpb%>m zY~e~rg;diP;9hi~t)NF3$kZ_ri{?W3v}l%{uwIx(r#Gl!cU{o?QNdonrPv<2yvSn3 z`4z}G2_Y?m&JY-3v!*K#^5!U&WmnmK-(Knvxf@)l7dsxtbV5e-6D&ZD=vT?kTrI-M z)0Hq1Mt__(-;o_-RA3A#yBhAMNAm?*u69P@+)Tk`fn+1Z)IpTR41l!~&k9e94U%fw z-L9Zc(CM6ghm3*1LiW6p+dA;>)Xw z3vgjh=6PqpKyiUliHyqrYG|Co#1n>C+jV|&;5+8{5pTW;Fqx6n**U& zI`4ff$ym*JRIW~m065M^Az0wG77D=A@@*Nf+V?6VCxyqtp9!3@pgQZ_o?J$!{)aZU z)rlQu?ZvxJzjkl*jQ$lR_*`@bv+jl+>!G%=Bi3PUD!G-B>qjjfl>RI|$!hjH<6V0r zC)45)lD0>O%b;2Cih}e!!)z;6Gus@G6O8X0N3wh?MvJ42q%qaEpJd--Wm<)~pH>J3 z$^>tf>|Zv4Yfx2JaDTT*(IXDT8y&et9NBI$jK_Uw@|IQhn+BD>BeaQ%l4R~A|H@>7 zkDjf(H>tpuW26(@MSItFSxIe_3@-moo^lAQm8BsX&!uq*8^o7j-eZ$)Ym4yx2{J%VfLZDmB=d+@>1lp$IsyRoB+ z)*sFCQ_DsJ(bBkdDfkx7X`LVL9o!*qJh#bCj!Tmde3RyXk_M_83K1gUs70~m@6}j! z;@+klSqBU?=pt`^vqbFwd}W})jp{M8ZP$2EZ&pX?`63_bXUJ}s%a&XR_*%l>+5vcv zzg-7g4xo*m_8sd_1q`QYh)>4Lv`A@_Eb%i zj1NZ7|FY1tp3b7G8K0uQc7`gD%RpF7>8BeSFRzs269c1d*Simn#$K_szK*gx&`j*@ zR5nIm#Gs}5gzg_e9CNIQ2*dE+NSamnCWdgT%-HMVC< zZAtZzlKDXA`mvM3RnnA9cGS<$U)>7U+~PyO2yk0)-q|rCqU@!Z+B*^(lOo_<{Jv2( zROM5zuVTK!m59tQ{4Qr}H)_J%i^2~QNL4LEl_+mId^@bnsfNV|Bx<%3V5Il#P9n94Lc)HvKq{JC+h+8N1n z>i5Zgfdk*C*biM`g6*njvwYvaqq$6?Qc_rNdS*ASZSVf)tpr8?PxNdah*U}CWJQ{b3J-qbX*cvWWnvgb-TVRhVU->NGCAZ#1bc($sI!{bgnMPgY3Zx-Kdu zK+eBZ{?0ZE@nbqZc3-nIes#iAdKx-eDpygnYRPa+n!!d|>;dMJXskE5Hp(9Cqd8n>$F(LM{J8>|{MQ?X_ zKU>e^%(f1QW!B3KGuU;SiM>BGSn`tV3yg<(jZl6l7*n)R1>>Ez7dlhEA1VI z1K015-GI$X~m9mv-m>t79Y*0DW^Gs;0!b%k=oUPVXm`>ubdca?s#9uh$?Y;~tz zhMQfPM=93km4&o7sZW^kLv-q5-k(1+&Mw_l$Noz@iCA5(y+1i8WzeDB+yXe1EbjgX zs3+czQI3x)dO7k=-pM$DY4ALHttLA~iA*ormp>9sMafpmgy7mWli^-iqy8)`NtvN# z1b5%FZEBt%9wXBN-lgT7q1w`a9c?LwfPg!%Z)SY*c&SH{T)a$i89@)^7f($0nJ)6T zH;jW=vk^V*f|!Wmw+wrqBSPmSk#2R&%g6iE*jsj0^;cPszt|(@`BCVE1#3W>5xeL3 z_0(Bh`6~&%uWMZbcc+*umhx*qM+*+o0Kr%7Q&PxZQO_iUjABW*{XMl=+*|^)9kWm= z>zPXixD*-NP4;>x2T+ZgoSA@V5V$WEPArY`k?zBcZRbWuDuwEfjJnxc@vte6pZ9Jt zUP0`c$Q^ItR{AaD9f>-{QXCMBF015%6yJ-v*nuwuxwe>-Z}(^;p7=)HAUdA4=Cf9* zI+iIL(j~FJ#vb5V@XP%d*AU1KOICSuK;8qsr-}mt!L-yBPNd9@!(Ean@Pa2@80JO@cyZG4Y7@3&pp-&X(p?{g6 zW1wf}WT&TNW#!<4Tyb%6adNV={ysifJ))zhhj4I#8NfUoY@GD0Y+zOv&YgFJo>(62 z-{FIYO04trkS;=NkQ>(g_*bG9R>aL`uu4X@2=6Qq4V_Aw^PHdN?9EP9P64|sk8lvn z{uyjdGy+pH_Uc zjQcL?lJ}Cvy2`$my5LRXXxdX%wlGXm&9!N*0kUpUlzO!oHtPxr{gZ^?m^Cyt5z0(! zqk>=4n((inQ^o3|JB3}$`!2U!gGI1eW+=x&cFSEN)Z*u>6$UNo<#=We}-b zu!-X2at}*z(ycxQi8YNZ)R5uaTb)~_aNj>M)|EKU3R`_O^N)@s2f`#*Y;hYl4Fw*haF%C)d(La zi3+_LKro`xsq22RGh?v+*^E^M51~E9)bO2gpvYk!GvQiwJSZ4_lr0{FWSnsdAB`J& zEFjN`L@vMAG!T@tI!5hLy^VFH3jaa{&6yu5`B8@4i5$z=dm0oiwr(-mkD%hSLcY?} zH(}P?q~Oqx{$s*xLn1ZxXDVGTAML~t%<;iC?YQs7f$o?3j>|)_3fkML(r4XQZh7?~xX-W&X)_?;hhUa}Td{iyEs2b|>Da?qCj`LeOV!Rbo zjgR9UZAXcLp6{EmLd|yKR9ssKAs9~ELGDxZ1H19Wd9Jn@|yKpxd=Avu^m@QLS+VPy?pi4Oe_6>Z@L^d08p{$){}Y~kMEUP#+?;$dGLe{aw`lm}Jc z-e2DbTM+dvAM+EeAHd1z{7TlT{~rL%Kr_FN1>)$p1j@xw@K(!$;nzRuxmsCxxh3X} z_vi7OZof>bMuuPvjar zB^#BQ%<$@dgB{mxIyC2_8w~UW>_JOBN>VQcPv}EHx?JCSmNU+`j(Of;1pm(JFD}0L zV!L6Bf$=%|lFoeocK=1?)#tRn@gD#LLJOeMgsBMg#I{zKK$XXz88zTD6^|y)$hJR1 zi6TpC@OeSQoacQaupm-Vvrs5;FJ%KO3(QGb!i>xfpJWe zCdR%>qZYIntdZxey1P0tof2>tb8bGL9V8|epMA5xS}aWK*+3U_3-9G1%BJrU>T357 zklp~xooM$tj_!PrhTkgysyJGdrWHx&s3)~LR;$T%W5-m_Z#P{piW!kVvqw8#8X{F# zrekF$%PDu9BB7m;?pV6Ff(yAKYhk|fyjv*zbXiT%vQ()Q>}Zj>>hdFGs=g+bFJ}Nd z*>*o>vav79wG1`5m>r;2c%7giukN(KJI0k}0EwqRtAd)K$f8d`6s;I8v0Etd8o42Y z3C;KqWwtBafcGsr0Gt)Q#)eSa7!Wl=T0;jNv4T=}wYT(q!>0Brmh$!dX*d`+a_BB# zUj0u|UwW`X z;z?3}_zi7eEs4#(rB8iQ`u;PdNp~Qg(^*G|673s?a`W0lb8?yEcP1jwb(wsf!Jj(h z{CK>s7|UfT)L&N*&v^Ed=|qvAVgQsWck1l0raPPsugnH%%p?r7c2W<=195b^zMPX@ zOhG%vSZ(Y3!DLf6|2vmIdX;_WsCq311U^f}09FW~7oomtQpP7QUlW_2V&1pM+T>F# z-6g$NgFWnMEr3T+(4_g)%l%;gUjucSSPj%UONmxoMPp2OQ~@f*OZA#cO=JoWsqJ$4 zu&J1WJnh-nyF*jBQE`lw20H_4cW(K5YbK0McR{_qMou8#d^O5;9$cT-9t%>1q9_pZ9vbiH6M z{MqFif7ZfZ8x)xdUY5%M0Tckh=~YYfjU5;#e)(-;LPMZ_BN} z<78d)OBfuwnaeH*^!aJV#DE(OW>sjbV>vur>8R4dfLnktdAY{~*^0*&LmZzD0 zW@%??|9DRr$m03~Oh}T{T2c5_tuQcK5>PWxoH*WEL9&If5O{B?Fk`nXvVpd%R(1*K zX;`bM2^W&!t4|+kIk<(zB>ZT_1-=|d&tgjzmg+Uv48JN+hET>bb%TneeDTt zoPuh#`oVx5ql%0vQLh((3UVQ~$k9(^G|+xUywR{!Iw>j#!95902cEX$0RXB%1~@V5 zkzv+=6`=gKWaG5a+EEgN>fZKCdC8i!ZEHNdaqyMH@zQ^(hs{cy=6k&qxiI;$OqR*A zNLxhc^Hsb13f`i1ky}V~M5>c#+*1~YUGNh8Vc2SeiC55-1Cp*d6>G@rL)tFU4C^d(QCnuQBWex_Lu%oO_t7h_Ym^X zMa;)ddSa-gDttZ;e1EVULH-S;RlQxkqdMQu#ME_VkmJ0K{EhtI<#0X=QN&n;{=1$0RYZ^880FNMPH>&`JU&5(270r&qF`2&D85Rmp{BN z`Cr?9DSzJV{CPFQPX5l|uAtoEBD%wy5uC;&-Rt66O@FLEE0>x)`f$#1$B}wg90aHX zC(S!!uxo2dHYfi6Dz%pM%3g*h<#RoE&>PEl3;TI`yg+i zo3DiRud%9UIbk-VF|t}s6*^OgCC(TxFpBF|4t--4`-Z(#(ke4gOGz^#Bk(8w@)AOv z0={VF@W=%wK~{sF-$Q$3RCvfx=CoRW4bT8~g|m32WA}-2Z<)cyfn1CAEX6i8Iq)HvoWyfeDY8$Rc4gopgUxf64HqwH^Fj|Z zR2sCQ^J9z%et-<}1zTE1N!Mv;mH0{dY+4Pk#=lfIw5kz9S@_PtqzgLAXzI0TAq9c? zmeRvWH&vgs*(XbcI@BjKrJLY$3FnSCeVf7NdfeX|g!09Fbf->-W~uMDO>xltCYni{ z5oR^Vbn251T`jSMCSoJ(*TZV9JlMq+)0q=x-AW~ZEkTi6b+b*r-c?PYYqkBocUHEp z1v&s^?Yuyu%EfR{Yh!K!xDYY*9s%o9NT%UEr<$g#$OTMaPnO?q!s+WiKZz*nvVg!yzBNHrw}^JW9MN(`sb z`$iUQI&Zfn=gxsf_ppdh{JR-Z%{G&2tuP3j2@%oLX0)s+ZxIF`uaKlZc>XGP5FA;H zT=Z0%Zl{2h`v}G8+%Dgi_AeAa;)B{4k1i$al+*nHqzOgD(`Xdse4^_d0Og{bX)sa?|o|60Icye+S9Ppvj&4yq%WdM*xPQ; z*UZ)VCDL^n%Tqs+&(7cxXy2>BZ;Y7Ao8LYF43U^4PQA@)GN6TULhOeSIitsXEK?h z-DvspWde)|{V>R)1b?n4sMi`T0IU78`HOsN-OU+J%`Yb7G09n9H@$bUOGP{Hyiy;J zZC5O2Fm}4#j&*eaoGrbcpt8sGDLYHOR45n6Hvj){hDuJz4EmS)+dO8RJ8LtWA6Na4yQz z^C~JiPFR{o=uw*^rNc5M zyd`8b9ZV5-u>h_PiI9drNl=dE<{ufv+H26{GxZ{%-pLk=+N57E*kJ0uy%K%9k1g@b z%x(p|6(J2qVGPis@K*v^qQK<+p={ga+f6}2wSw>6w)MP>gv)s|Y6J zpa9JIbXZbJ7z4!hZNepX-MD*RBt-%De?Z@L4Oc7jN4C#%SS&SkyFMlf)Az^E0g|NoA^^-K%VDjkYPd9yKN+A> z>oGEJ=%oAj_f5?4P30DwR;buo*FYjh>nY6>Y&XJB-!T%>UBY7ldZim?BR~LFka^CJ zVy=&4eq!Eb1PD+4X`+3twPu;{&cT4UUjjjH?U3Y|Oqj>-$L~#fo=wdyo1!tZ@Gjf$ z?Zlc6AKE>1hcg&dab?x|6%!FNLI*iJe`Us%#8pPE&vm!!Y@DQqO#NlJ#RbR@kyYg0 zjLlcr=B3T%&bIWX+KeLf_x9$u^v+P^DV9CJ^E3}$qd3}Nv&cPDoq*CB`6G21gG609q%&T3R` z5j>Ij2A(xHG*4$|Qvd)!Edc-k0001r8Av?_0001ZvmMSO?J6lKDls}U?CB{fEG;W6 zH8wWuhiU8&yJE!IAf) z`ESG8)jlo1pBk#1jon=4J+oo(1{1%Gsn|pI9iH3quQa;i4$<4eWTL(`uJ6K2pH=-3 z51Tx?!haBvZK?%uFl+fiO?@Nna`x5k#FJU?=mKj_;69*>_ZC~ZjNb2%??Qc#w-qJy z+IQH2c_a~+o+XB+ka^o98#Z)7pl3Ou+>&#)t>yRc!HdmzX^z|BFe?w~5FlG}n61+n zGRb* znHAO(=AaV~;r_XA1|7Et_zEuZ^Yb$|_9+{T5&eQTC@W#nY(wZIcl*6~#-o`*tz%M|i_#YijCWwny#Wv>xk^NyUANSQ>hdio|+emH~w&Sc>jVdl} zUL71(%aq2nbtQ6Is{|;UeLd%VbHBKGczWFo%f=|$oj8U#e6gKFYYHk2o^N=cU&ZIF zP77ewRkI}tBsvRNP;-TekQCQfJF!Tk_kPS-Wh+f@kFLz@q1X8{C^tyE?+TdL^JstP z$J6Eziy#vE)f;9p7>ocCd^~#;JEWeqi?sl4xT<`Xb<~=uEBn_{PfPW_v(0@tZU~QU zntnQHIlC}4bv6IOW^v$bdQVEd#S#Tdw&arS(gP54_Z4dJxn(8adlor27k^PS zWO~AVqJ?Y1Me^7mhZ7%fH!Z~I5 zR$E}SU{|?@*93#?o{}Ra;7MQS-8^>V<;IKFvj*H$oOM1K6xtN|QT*8nL^77cz-G86 zY`CK5=M%3S1?Tw;Ri;jp+D=gHE*8HEGWfp~?O83vR z*&!{tiA2^sz56)M5anqLH<)dWGxGz~a!uyWIXYF&C=k!jS+?Hxt;4E{P{U>=R@!goh-mZ3WL8pi@{pW%|F&D_@qosnaUr9=q*P%h%=^)>0gM zys0VflsRAtT>VN|U<3eo(F=?bUEZC+5nJ@a_f4ZdwJ+iraoBOl;Gh$Rv;_5&0G#zo z7+C@YV5Ua`BhhiekYy)C4(w7l*+aT!ndOXQ)|Ob6wXZ>A3;=xn3X_K^tSB@Br`nc~ z5^I?LGzy>*sXOI*u5V00{0?*G*D0M#f1LZp6#$I=N}~ZM9f>6|JJk~~no{h^?*UIr z)?#7u+RRP0JGzM!FO0~ZvkR#gGr0=1?feD^>HtMHnr%s3h);hOY<1vCnPx_J^=XKcZOSz|>=ug;mJAau z8Ua!FZ3(&R4utXi(#}?LZ$rNMn*s3D20!=$J-+wLStx4E;iG!W+Ncw);3GBN&qjwO zjb4VKE1f8Da?}9&g|o3EGJysFPriG8#Z#_W=2-#8G*%_0ovbx;F=sTnSUwy#4sH&# zhcb7W7hiw8pOO{JZuji=^l-vA?e{P3*vQL-si`u42HTi2pGjF;$Ln(;+#n-ox`C`C0a|ESO>% z;#D}mo-^wgpu831*XC0OBn7J^a{FH4!pIOJB!f67Qz;Qgoc;%J<DGQyC);@A7MGKicIaP~&M^`)`m&zvT`0{USCd;y-8qk=&O=s*&jDqrXy zAY4^xsc4+mf-X;fZ4NVAPbpu0KY!(}-Jr|^cg(dhwC*R?vcdlR6H3yqQ7Q{EGN3ju z7gaYaf3@~uxQ>UHzV?>*61VH)zmpBa`w_^hxfpRqv1+_5*O!lHUvbJVx%q-{D#u!d z+7=l{UItDxO^bY&6Eq7Lsz;P>Nz{Kii>AEQFKTvioFTIAyUSmvn%+s@A~_T++D}Hy zX^cb*U2y_vpszE_j^yz_BDiF*#m?GRY08~{?*TpK0gbqa#7GYBi0$113!}5H^u1Ki zoXFtD1|Eh3fB^si+*g{%7htR;sgjK`S_!VzzvpS*rq>zwm(^r9A7B4)eOBWgzWO$Y zYlaWcS~M8o9HX%f7Y0+*G(CJeU|QwGjtL!`t7q}fOe6>yesEzD-2~$mc;1BLmJqJH z>erz)w%29mBI*zFnS%3VfdaFdIXIbx0h?$X(r&ca_Z^sZx`;3;E{)5octF||kYuk4 zrAo__t?SKW&`p`&xfx}1Unbm!SWeU^?c7NPt@=zqZSlRa&#_1yg}>*U-ydCRpl>ofE6vWXALxU|(mcGx8}cY($pnpzz#LdfEm(VLFFN&?|Z zSNF7?xU~~K4ty`YjP$&hI3Ja^Uj=hI_eGKhi5Mu7V1*i_4{ZgZB|lg9K7%D4JkUP{ zmN$Aa<04X+&ybx!Zj1@zUTL%MpMZjLCnhJU+hRZ1+TBZxn%|;l4MB3e@)gD_`63RQ z1EDOBNAR67w>ftutbo!J(q7hPPJh!@yi*^Sp?35lKmz`SqW}N^0GwPv#{t4)ET=6g zv@(kJ_XArm`SUw6`*TL(YI^FCldN~h)4i5axeC_3<4V0VLkow5l4~*s^4OS2ok@i|%#=~BuxsrgrC4Sisk`ARTO-zpxF{ODTv$XRf0m_7P zZ(+Wc-%%nEawdGuSuHd+0=|Yz27m$paB^G82QVG0Vw8o` zN@%X3v1xMe>869`LsN-+anm*Bc5C_aUcEDWn3(vXpsC(e<&l)wTgT0U+K-1rH;NYN zqs*Z6(ul#cR!nx=ucN#f2IdQPnpLU0#IBeUAkT`=7D;OjEZOzXM7MDm?#{b6#!Oe& zArVpH6FSOL73smrtM$1009TaQenQEBXrTqrn}_)psx{qS+4{`J%th+)>pn2okd6>zx-?KYFR^TAm+#cb=+wCrZ~ye`J9bZx(u~I)rcs7`c9mJZz)xmMkI2Rw0=Z&6P3r)cj<$YHNG7wQvu&HFhk*+uO zGIySp?YR8v&DGbYMIUxWmE_e$jIy|lw0ppr`L8+|3# zk*yAS11W>O4oiB!IT;?W!(F#iTer)?_{^rrO0<>kDM?wIsg!0; zyDq^{VP$uvU!c}c-w^BeREk za3zP5{j7h??W}sfFL}mV32FO;XsWRSltl=RngQ0{Q`D;}^v2mYFlodLsA`WhnNsnXeG2=PFWUdqQxl5`xqfM! z*R2*9S+}4m=~P6nO3#f7;S>|_2ETR{#XWbpdW(fYU0Uo`W!GZ1eyN*^f3G)Hg3iE3 zFz_N_yy*aXDlah(#Vql3M|wHeT+ABY1>z8rrpK3OCju&k?e(a)MTcUiE&vvW!-)a` z2mr6^BageXqq~LS0aQ4xN~4?@-)a8ooqOF9yVX0(ox0?Hm(T889gl?K$)$Weo)+y@ zkd%iixz6s{{~w;csp*by);;JR&y88wjYwkt$+{g$O__-mtS*dm(uwD!d9YOP!PoXRLbS$+>f#qRno15Gk(t(+IVY9t%DX1T;=pM5C8<= zX9P$`%st@;{d-YGUNx3ji_1!#@si`f+PGSNtvVy?M$Ag07JJ^NIeGt003dF&*T>8<>=V$*Wl&U@GLbmGU?sm=jP+vuPo9SA9^lkqoIWxGk$J)Zc8AiVxfO$Efm{C+xnsR&kw2szK%io`e{&{z2 z`zmkX<^IIRO%;9l`TdKYeWCnMT}k{WFICaTcuGk1p?e556EvPbxizeUK--k{SvQZ# zHd1jYPqXl9b)nAN$cAeesv6?Z71 zvleHG$R3+mm@(CfM{}emEm1qY--n|@h!71EC}ggJ8j`uTNcHLF`u6KM&IF{I!f5MmKh(^;+ea4*Yi+wnd%c$L-te`6+3;d<k|3|Z?pRK@K*sUw{+PG z9g2Kym8{HxRGx+O0G@V}4uAk=2g-1+^TU4vdR39sN(<$*;(ET8O9yRMU(Lsxhh7={ zd47v^v!q-Lztec4Dr;R0qm``&K;-=*SlPA295UE8aB{CfOHS8B>RTzTjO?p)5RNSp zIYwy>A(}5%HQyCS=lxbRwiT~tDrNbwpthH#KK`nu`=*6#H)GBx1l+2*eO3-C)t`5Zr(LOrX0X~Lfkpch!oVaae%oylP5>pk+GumlhvNstI|GoUs zp-eM8{+TuS^P&Ijl3VW(6I{Ar_`$O?Yhps-wNF0W##h{Ttrb=~HmO}Mr-#}BpENXa zhO7BNe?dwW=ZY(iZdgM#Hn(wEZ;8e2k=7cW*6ZVOsjqhF10B6YY&sPvYE>|SUMQ=u z0B#)bh61xOWxR`qj<5IQb@*xjLAf>(qJA#e>V`y%?iXb9q^nffHSEHAyLIQ@eYA1A ze|)uXH@=387(f94aM~_~G=XVbiHXr@;gN!JGkxdwpnsP0#N5;A{eRa+hW{NtvrRdC z=H1k(&0ElAgXv3v#s_at+3Gt2S_rbm;%eURLkmht9n;6&r`NC{6pjg9ZToEe<*nVl zKpKEnN8Q*$#_r`Y(abTh47dF6ZtW>!T;$OhEiZ~riy-&fHOv)yq4rWqGMX{6FC?1e zIr%b82kL8AE~~P8?pNB3n2i5a2@28{itLMhANE`^spw*FMd&n)InD`s-2vmgaE!Ly z%!*#v7FnZ8X>G2|7KE6?#!Zn~|pti2)%ic~U{lqZcA%SdD%t?l`m4XB&Ex!bE`Mqbik zOvM1P8fVn>=h`>m81TBL&$S{k!+#?q2W#KxIq8HDbct!fUbHssM=YmPLH^*#(dyad zb%+)tON(oc&%ILDyHc4Z^Ys0#9HiwyOh=Gf72&gkD@B2JzzTB%3IP6wOBlce0N~!r z@OA)<nHT~45F7)e5=0=M3R!g-MR~=mtHft$k z*LG=&Z@XrPu=Xgg+A2niPvu8AHMgCB*1Ekaa<&F*&4$^Gub|aGX*#N*5_q(~Z{UnQ z*r$e}r9~>W*4yzhe2)MrG;-esrGdNDf~TG5h5mcdJEPs!FDb-_h^*D8I_)b)g>3o{ zgHx?{)y%50Szt`K|E@C8JB4qA&Y|gFNYS>JAe%3Q-j|{&rN>Xw$|rhZHVt-#Q-J|G zpnw9;-t)P8$a*7M>;&{`j3pK2=v-u8Hq7^yzss=F_}1gc;r@$Tu4k$mJ2swz4{j$q zOcr)hYFL={7EajTIB9JX6n57vGgj5^V;0Q5+YE zEVC~9{=D3xs#0sOd#lNPw5B2+*utW~rTV-aE&2My*SQOrLU&K!L|;J)0-LbVl;T>! zx_2d=Yrp4lV+lfb8QAd5;ZkB>O%6pq0ZH%1zO3)itzPSH0v8kIDv@+D)z2d#hR6b3GnAHQ#is=A1JGGRG=gg8EWx(#K1<9e(Z|4I|I;m@@t>YSo=SKyI&qAh3v(4YNPz0e6g<`atdKIFms^}fX6BDRWGFwJUs zs>*EDMbGSm{Fa~-6w18cG~nYiy@~u{`6+ZL#=tw?JE|Yi((`fqr2oXs{eRH2tN~PP4B*NwfO3N_?1;=ovOoWUQ?5cUDrd;pP=lU>c890B}~(^yvA3D!o-WEbim*cGh{rf|+@*Q6jP8CR- zR#^5b{h88Ef*hy8j+X^$oI&2YH$w=?RH;umq2TVCqF1H8sO9h z(54_D9ldbrL|YTmOixq4r?(E`>Yg8&t@*NPukJaCiyL3=rVtG^N~E64Ud+fo4)S9` zP{Z(r0^ZbLy*Z(sPbQMdQR`G>{w_r)g>|zMJ$N!oj=|W>Sv5vnSlGy=dOYORKPe(| zD|oR?8cE;76EpJk@U81KsNXIVb-hO1ieYVg&+sSOznyFBeN>x;=8?Arnn|=y>2*VO zRtxr!rnYKy#QS5{TGChhkK%Du#*K#Pg?IbH9tezEM}iJ}u#$;V$vvwXd+CtHC4R+V z`R?c3E+VXoyP^QzmNSll0|2nRZb>70;Up}_B;@&4G5vma*!IGWb@R;FwjHml{r4m9 z?brKr^}iBNe%&=6?VCo~bwqY55w-ngd%mm&fSS3Xwyj#7y4>er+K6kuEe#MFMd?av zE(Zalk?rbeLjqBAnm?vqf{?GrA7sn6Q9+)|45MJWt|3X#p`}qJ*xis!-*RgJWany& z$)hY{ksJ=Yo_frPc8fN@0mmJrj=#QE5qyZuRI16Xo5L{Om5%M3s%*jlSgyC#d^Lg| zr0Xn&YTsGsQ4%g`k&Z2;_F{?A%3CU<@;lm^?*RUm^O6Dv#;Q)hNhekn|ov}hEy<09v?PAWaasbB0&HtC6zlhR)d z+7GyFPP@lX z08w2N`A=uA8Mz?pt3xtkTV+kT$2?RfTCX^(z-B?pGNI8|de>!=>RbK@T!?kf>mEJF z!`6^ml)3OLRU&Kp9ON{YcB)jW3K1rrF?PCw8S%qyZ#AgEKFm z9z=|@BbRM}G3*DbtnrO;Ooy~{OLDYnY-r?7$63z(ZkG}V`{Bd4>_=%w&6C(&vR zdNd})LpM`av#j*)T8C*n+dcuhmE(mbt_NfWGkD$k{mgYyy<2axtbnSvs=UNSr7Ryr z`WqV-b|6?hx@vitF`Yc{&ugz7v8m0MFK*;Wgp{h#ntmw~gh`K+ULpYHt|t)DzM>SV z{NTfl5W2Lkah&>|0gcjo&O!tUrHwsMm*U(_C>f}kT9?@f{0%;8#7s{mh7sO*vOj5M zYGg5|+ralT%@K)&K)+)aHnq%;;Hd>-MkU#xY!p7v-#U;N1k3Vao~178W-nT0A0(wl0pejz?1YD0R9CG z6aiUx8cl-K9c{Q|n-26UC?E5VNQ_p5=v($CVF>W?!E?I7V&J zAH`Zqv6k_=9VWcZ-EN+MwY+VZ=**dpen@rmiH8gAyyMcdA>Ni+)P3@qJOEx6%s`L1t_=wAd#9+>Gyqj4S4=(ao2c2h|N8r6@Wu9E zOZo8S=Dm>ekfr5Le{<&4-rxi;%|qP!I1$ejl&tUT$W315%3HL{xs`b7MiLSdK*v?6 z&pi92Fu;+Kl#$rj{mow0R?X`=EUEj)vy$_aHNg|RT{bacNW@8jljJM9 zSR9mj+dk1YOjE?ueTIOT2gOTupGA~uR)ETswC+Uj%7IngyfN}+2CcAA1oNUls@>XD zV=ie1kKGjU>G`s>T8ep7KECtun6mWe&{UR4^W^gUtu^*4ROAwT(dG)U0e%LwNe!bH zja=cn&j4=B115gB(op#_YolnzWo~>h%slw=_no|u@xpRzm&_jM^A}!ZpOG~5PoGU2 z&t1}*HgXP}G$7dT;JKNTM7*;%%ScQmT~-Iu*nWY+T${2iytUA}UCOBE9hc%>8UonQmp;7MrfQ_5I& zGe)#fkPhF99C3&?qbnPJ22?PEOinCvWaP9@Yu@RAv4T=L%1#R-Tgr#=(8mXc>1TTv zLdvy^wl*(s;`yw(WoDcQx_NgCLfdJl5$k=$58xG0`uKi(wVhYyk_NmdkgQ5tX4|q~ zl&9KI1yoXZaWXR;(fdMa?Fm7koT82(ynHI>x`uZ#3=ZPq_*3?WQcO@|&{eZ*VS%kt zdgNVFHV$MjK|_8O!9?}qzlf@oxU**efp~O5ZEuey#mW(Zn*A3dG z9A#x@qYJyiu_82m;keD^mOx?)I4(ey`3}Iaa-~_(@7rkE0iFirB12w^iAsn#C-un% zqZ|V0P1DK%sPeUQCLuub4t$+)J#0Dp>Z?D}%w44!U;XQ|(}tt9QB)#z8~Z*j1qvO! zL7o3RUo=5J2G(uUmnKCPQ908_+8qMp(^3vD6snsW&R8%u6DEt3omE>l^j@5~Jh}xd z>$64VG#LARPOsFP4)7jCQN?oW2Y7#-z%SR2{!%CXyPc&4sMlM-akEV%Y3-8BiH!_E zg1zQ#Q5+9%McC3`c+-9WY|y*b*5*|^2y%iX5dUlF?;&J`Onr!Pt|dZ=y3oYt7u={8jclOpe5(%fYua zr`un@-F&!CDD%>4UgE)CvT51r_{aq>1(Z z_pBg`;A%|i6+YB-4;%tM4L_MOa(!k)Mw`c-E^^AC?*9;yM-xMa8~>|3G@B9axSTvH z4i&tEJay1+nG&z^4$&^A*mF*ps2rxm&KFuio$UWGQ~1<&wsOqM6bMW4NN&VEuoVz4 zME)Ts*h+I3?}gA4YsQEnw@gr?j(nC>t)nA9n)iYZ6W*2Mfd(7^;Msx}4VWiktQw6U z@JMYU)BP3KDEG%a3Uc_z@$sHDUa|jaKH4>3R%V;tyZCRQ$+&U|ZX)9p%dOr$Qf$&F zIh>R{L@EjV zu3esPanTqw_dY*{{7=hBsofN>?Ie%X_er$>elNuvXy{Y5ZpA0wRx|2E1p9!H zO7b@w6|u{yqjghI%|VL@U_IWR(-Z{&c9r9)1`1F>#M60thI%Mc%yNZ*vDa2BSNWc1 z=E=t|x7hS{xEkIS=JFp0uTJJ}+W#}#rqB9R&n9Ay=!-MfZeR{3;MNy>-N-Byzk7f* zin_C3U~*qc=w`dcbiiqs6d$o9&vw?Q7U*m3mbv=};d3~*>*#jR{@v)0)NZct8emRR znO#ZMGeXOi>Xs5_0j^fdg^$?11WQr3rd{?~Z}6};N+T>C(VH0Bn1#%#VerN#OG;CwrDK~y^LVU5)d`6#+4-jYs=MU*@xrU zOCMo_hR!+wWc~aKD6ts=rkESJ5S#su5^vpLY>f{_geJ&pYGylp zJ=7eZc5nh?@5+WLop+=;2$bzm$^&Z|C6f;NlR&xY?wo1uoGycNrTbg9d3OGgPp1GR z^1sb)%2t&5`N(khZrXlt0RVc1%a9Vb1u94cPaaSG6gfRV0;UdX^yMnqcS38+pO41T zYnR`GMwYi7ZCIbN%z8HU>eu#{tO++;z~(KzTfTbEX8l!3-5hN#3tQ#huGZ$s5L8NR zo7l`7e&JX4HeWu4k*&$Q)>YF2r%CF1E*6YBx<&SAYuK_c!`XK-3}pqhKqPdlHS&3o zX@|F}j97bRdToO<^h?p#)z(q=C4Sl^nU!PNMASqSgSnXjF@{LC5WDuSFPp>! zo)vA>2ULU(KPFisB~~4?@`UPH;VmWan+>rj0vzSj*b7S9H!Mp|47(-)&H*;I;|)bz z)4~eCv&X0Lo!9eW*tyXin6!TRuGPZx9MjLK{I9S1q3K(g_%>(|xdpY+26sSc(8>Fj-+p z#z#2G3WQN~C#$cgNEK}P3Mk_!xpXS?6alzOxHV3Jchqvdu09*gj!*3~UicmL8tq)f z$QDJ91AO(0fbAgwfZqiK2~mDro0C*Y>(EowaGqlnbB>+ZRoxbJOI*B=09^G-5l;Xd z@S6q^Dc*j*3N)n@)wCaR1~c|A?z(t$4V6+EBurJ&=XE-4`AUK936KFZ6~HK=bJww- zgrTF`oSGUZv}QGUb#l+~jMIpUGAsBFT=|MMk0u#YW0rJnUJ3~jDU$z+iAy@!oXzg3 zbON$(Y3?$DGt?aB>o@yNsCNK_?TW-2!6nm4A@sWoq~6SL&uTM8s>{D$l+>>Mm=w8a zCp+afhVVlQld7SUGeHo)JJ{m^jO_}cG-N5&15+PtRB9i0CY#Kdwr=AY@A2ee=%Gs4 zwwN(oK8%>Nr5?K5l1Fmn@3jR0lmSbLvQ?17z>8u*3hcdgNkmVSrF`Z_+ZIHzOK(BG zwmPj;nE#nwNdE>>{T1+BowrLry%%lFwYyyukr?CX2>AW1HU=1wcKTe=rds5?W=qG`gBBnfMue+t(UWA#u@|9dixu}Us zcn8uQ(nBAy-UE^q%mD$21yTp@+a1k!x1D#UmQ5(k6`Fi5lo7aq;o&DGBl9zPTa=vDQh6K~O^aEj9HVq8bSyWHo9OFMp zIJy5FR~`gruzjzGKs}PEML`MxEL~2A;py*3a%Kazl}Lu8ZrD_NOlUp0aW>l0Q<}U5Q3k*0VBjl<{9sKCI!CM+v8H#RFOEh{NCHtpir z;OXV*;o&PQD=I86D>XJV^6KN%CoU>{`Fxyh$jA-O+_At&v68ovFw6+teSK%MqnA>_ z%eNlFOnc&s-Sf67nyU9wf3 zD`%!6+^+AQ56xWwZ25c*2(%}`M(~U^&^8UJO(5e1sIy`Pa+Z> zH1m*=RHMmZ&!G9CINLJuh=@#-vO>e<`xXUKKa+Rhv|)g+!mZ?=@H zRkf78Gg|mbNr)|hLgQIo{hy$w2O5R5B!jU40ABao!|UtqsIzAwzkso=s?$`8yKfPpb$Y8etTMnf0G4GTi%CHsF!~!I?RS!lFbvlO* zfdJoDPK~UF}3jje{Jduv@xL=k0XO@IuN_3+8)TtB}VvBgyRU z5p+o_Ghu2sRv}ia(uTE;0JZDpdo(H)+bJ;LL97bScAi=0ZIgkH(3&We4ULZ73I}wv z*@Xc9mh+wh0svrX>E$qTOsh=3ah?}hP~W{awK8YT-o7n+^xFQlODdHf`TAEPKRoPe zVsW2K?*s(I6j+>ky>tYXqGxh(d!akRf0Thoy}1RfYQ-d&rM+2bQMZF+m`=NeBOi<< zNpYh=G26suE#=3mO=eMadF^{VVwJq%oscepGWRhyEQ(Xhkv+7Ypkx91Ng|A#ykBs1 zj51|{e_=Dk8g_3F3%;MKD=We4&0s0IRpfRtR`E``(v2~gsx%bbv>m!rx9%L>z+>$Q zXo()h;qE)CX0zQ_bn1KK`08Z`}3+-?iODE-fo>59LJ1LL-aOM}e z)4|ig?2os8{CxW{wb{1oujiVkC&E0RmB-lSBzSgY`e*t#0gHzdcX^(sCOlM<8JBu~ zw1O-1d~O_e!)1oio3L2pvi9G@n%VQ9MjzBmV|HBMNR;(>porTb$>@o;%AoVS#_sG2 z;!ygFl<#~m@tBJ-`D2%k`tDbUuu4f(QoPICH&F<<@$Uu7+0&VmVY?_NdC@fIw>>1# zrbttH8L5bhLUt7q`A*^3A`)fxowPZSi1S1u06rEZ7zw5w_9aXbaL>HKMPR~Ml@yUf zN@)|Kz6&s^T}?A}+#jJ({YAu;71rl=jCo!$K`Kx=3a4E}*0eBScR zlVT6_kwl*j->+SzhON^{VE>s1hnsdl8;NBO!ZTO8^zrz#=&g{n9PM9o^ZMrmA_696 zKtuidQvP!*GwtKnwa#>|tvdz8iKRiN>_@zrqTR^ z93@;mJ|uB?)u%A?h}95JyY;fmDN1vGg`NFl7M7TDePv*ZVA=`UYO%!JH$lq!xMH;U z02zB*2VuR_BXKdnd(E5^1pvMVm2&76m|&v&m!$LkywY(i2$tVxZ z30_~z8RI16^=t%8vF$zdCd%LHCA(~&iI#aA%95UPKf+9$* zmW2!|;ly{5EzFlTvkY%P7>ss^B@4uP8V%c%<1;{0loI6uZDt3)2IMt@K@W|T87S?O z1`q(o>at54ZCywkO5B?I`IdDZj}MBkzO}cb@9rf&+RIcTFEKbt^4=fl2_+kB#2@5Z$g`^fa_omRpe(s;q(>~qcj+ecnVQ&7yA*e{N5klu!#<<*)FT{uUu7VFc8@*?Zp&ZOEl1F6+gp zYMwB9$@NS6fFk%|0#Q|RRr;qM!Mo_Y8}(3j2xecSHd3v?C?sUZ2*)R=o^EGa&$18lP4$2@ZGbN zdT+^Uw~0p*acr7CDe7*K;EM z)(NS7sY->p0$lY_C>aboeEEj9QvxYOMrd+M#1dV+I3hDg4~R>nk|DuiC(D?M-YPje z01W-gl+i3I;6(VjMT0QBIBA|{16f4j{m0bfJxe$mcV`4^t>*2??noLi$)@=LT>1P2 z7*uG4HA4s-C%&AO>PB{~sFjc({x0W1>(d=g+>8@6nb3Vr#`65T1kL`SsrgLxU=q3;SVk+Wed-wF71OO!MiUoy`a|QOV z8V$;|nY-6aTBK1ME42JAEc9T$=c1bNMd*8ZArfiMqLdpv|SJOuE6ADp&Vd2QhCxBLTf1ajMp>D4q67>V=MyQ zPG4z)j!|HcG-7TIzV>Ks=cSe;Oj3_Ef@$bJpR8%fC~z*_PX;Xnx_PyA?#L#JN$-xX zxN2Hd-M(NqHLe9Ji?~RwYe88h7*#40=t7jrof3Ad(2EQmE}rP9i3c8QT+Iv zXBnSn4jmaL>cv0$=Ss$EOPbejE1MfCdM?93t_j$5ww&&lPQKS_Wki^53r5JsO5&8M zUY&6XmM)3c31nwnhzp7rmo@27!-$2Gw2ezp-&XacD~^NYnd%jcM<3? zNG>p(HTT5bD|h7}%_^jHpv zv%j{52-Wmj`X`h10v)^^sX5gx17uea=?C85JR|U{HrJ*z9RXT${+Y6VWuPU%1HOjy z8bAjC;4U|`(GEMc$jiNYCD-m)KBX+=R7QJ(HR{-`Tu({7A5}u>6e5vrCML7n7goDQnLG0d=0vQr zcIU5hSrw_!wDgE^;KCU~c|z-3(Idx-q6=yl3z9FIw~&-rqwUGjA@*Zhc^`L*Q`FCK z8AB{R)NQCw=CWGbv9|I6s_WIWO2Nl+D)X+q8*7`EUn(Mlglm)FTZ!d^a{&^3q(1;k zThq_B=Kw|xBT0g8oG&=V%1G(}bn$!yC~XA@nNbNC!OKorleCC|D$G^d_fX{rdH*n6 zN@U!f3?Tu8`TUG~2ni4}cQQc(cp+>t*OLyhrpa3w+RN?#<%+_44%)Y=W<@dz5VtG~ z31kJ!aiIP?IN`4c;8IjuuPN0qgdTUCwr_;@-$A$)hYTJY)Nt_nWRw6;XJ=CY1Sk3d z000000E!t%JqiE-0M)$XU;`~RG-M6SFtBceG$w(4fxt*%eR%G{Hg>roH#d@8KpCQz z)U^Cv+pV)s`}8ud`3GzjeNd9keky$|eVjn07Q^=S7n1{ejo&=cA!)Inim&m>U{1aH z+B&1ueATzdnW{-i^kD=1_(XIoz?dU#j-+pPs9>7u+a}4lY 2 then + if n and n.name and n.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_active" then + self.object:remove() + end + end + end + + minetest.register_entity("spawners:dummy_"..mod_prefix.."_"..mob_name, dummy_definition) + + -- node spawner active + minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner_active", { + description = mod_prefix.."_"..mob_name.." spawner active", + paramtype = "light", + light_source = 4, + drawtype = "allfaces", + walkable = true, + sounds = default.node_sound_stone_defaults(), + damage_per_second = 4, + sunlight_propagates = true, + tiles = { + { + name = "spawners_spawner_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0 + }, + } + }, + is_ground_content = true, + groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1}, + drop = "spawners:"..mod_prefix.."_"..mob_name.."_spawner", + on_construct = function(pos) + pos.y = pos.y + offset + minetest.add_entity(pos,"spawners:dummy_"..mod_prefix.."_"..mob_name) + end, + }) + + -- node spawner waiting for light - everything is ok but too much light or not enough light + minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting", { + description = mod_prefix.."_"..mob_name.." spawner waiting", + paramtype = "light", + light_source = 2, + drawtype = "allfaces", + walkable = true, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + tiles = { + { + name = "spawners_spawner_off_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0 + }, + } + }, + is_ground_content = true, + groups = {cracky=1,level=2,not_in_creative_inventory=1}, + drop = "spawners:"..mod_prefix.."_"..mob_name.."_spawner", + }) + + -- node spawner inactive (default) + minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner", { + description = mod_prefix.."_"..mob_name.." spawner", + paramtype = "light", + drawtype = "allfaces", + walkable = true, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + tiles = {"spawners_spawner.png"}, + is_ground_content = true, + groups = {cracky=1,level=2}, + on_construct = function(pos) + local random_pos, waiting = spawners.check_node_status(pos, mob_name, night_only) + + if random_pos then + minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_active"}) + elseif waiting then + minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}) + else + end + end, + }) + + -- node spawner overheated + minetest.register_node("spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat", { + description = mod_prefix.."_"..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:"..mod_prefix.."_"..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:"..mod_prefix.."_"..mob_name.."_spawner"}) + end, + }) + + -- abm + minetest.register_abm({ + nodenames = {"spawners:"..mod_prefix.."_"..mob_name.."_spawner", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_active", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat", "spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}, + neighbors = {"air"}, + interval = 5.0, + chance = 8, + action = function(pos, node, active_object_count, active_object_count_wider) + + local random_pos, waiting = spawners.check_node_status(pos, mob_name, night_only) + + if random_pos then + + -- do not spawn if too many active entities in map block and call cooldown + if active_object_count_wider > max_obj_per_mapblock then + + -- make sure the right node status is shown + if node.name ~= "spawners:"..mob_name.."_spawner_overheat" then + minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat"}) + end + + -- extend the timeout if still too many entities in map block + if node.name == "spawners:"..mod_prefix.."_"..mob_name.."_spawner_overheat" then + minetest.get_node_timer(pos):stop() + minetest.get_node_timer(pos):start(60) + end + + return + end + + -- make sure the right node status is shown + if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_active" then + minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_active"}) + end + + -- enough place to spawn more mobs + spawners.start_spawning(random_pos, 1, "spawners:"..mob_name, mod_prefix, sound_custom) + + elseif waiting then + -- waiting status + if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_spawner_waiting" then + minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}) + end + else + -- no random_pos found + if minetest.get_node_timer(pos):is_started() then + minetest.get_node_timer(pos):stop() + end + + if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner" then + minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner"}) + end + end + + end + }) + +end + +-- create all spawners and crafting recipes +for i, mob_table in ipairs(spawners.mob_tables) do + if mob_table then + + -- spawners + spawners.create(mob_table.name, mob_table.mod_prefix, mob_table.dummy_size, mob_table.dummy_offset, mob_table.dummy_mesh, mob_table.dummy_texture, mob_table.night_only, mob_table.sound_custom) + end +end \ No newline at end of file From 8d38193603ec0f9f56072a51c72c241ea8ff5e09 Mon Sep 17 00:00:00 2001 From: Juraj Vajda Date: Thu, 14 Jan 2016 00:31:53 +0100 Subject: [PATCH 3/3] README update --- README.md | 10 ++++++++++ spawners_mobs.lua | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7153601..d6e97f0 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,16 @@ fake_fire, xpanes for recipes WTFPL ## Changelog ## +### 0.3 ### +* new folder and file structure +* more convenient disable/enable, add/remove new MODs in config.lua file - added property for custom sounds +* added sound for bunny +* fixed sound for pyramids:mummy +* added footsteps and digging sounds for the spawners +* shorter and more effective code, easier to read, fixed variable namings +* ABM tweak - longer delay to trigger but bigger chance for spawn entity +* disabled ABM catch_up + ### 0.2 ### * support pyramids mod - mummy * support creatures mod diff --git a/spawners_mobs.lua b/spawners_mobs.lua index 29058e9..118b316 100644 --- a/spawners_mobs.lua +++ b/spawners_mobs.lua @@ -194,11 +194,10 @@ function spawners.create(mob_name, mod_prefix, size, offset, mesh, texture, nigh end --- create all spawners and crafting recipes +-- create all spawners for i, mob_table in ipairs(spawners.mob_tables) do if mob_table then - -- spawners spawners.create(mob_table.name, mob_table.mod_prefix, mob_table.dummy_size, mob_table.dummy_offset, mob_table.dummy_mesh, mob_table.dummy_texture, mob_table.night_only, mob_table.sound_custom) end end \ No newline at end of file