From 331ac88960cc806b4bb46560b5e81c145d895d12 Mon Sep 17 00:00:00 2001 From: Juraj Vajda Date: Fri, 15 Jan 2016 01:51:53 +0100 Subject: [PATCH] spawners ore initial commit --- API.lua | 169 +++++++++++++++++++++++++---------------- init.lua | 2 + spawners_mobs.lua | 2 +- spawners_ores.lua | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 293 insertions(+), 67 deletions(-) create mode 100644 spawners_ores.lua diff --git a/API.lua b/API.lua index df215b7..8edb36e 100644 --- a/API.lua +++ b/API.lua @@ -41,8 +41,10 @@ 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 + -- remove 'spawners:' from the string local mob_name = string.sub(mob_name,10) @@ -54,102 +56,137 @@ 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 obj then + if mob_name == "default:stone_with_gold" then - if sound_name then - minetest.sound_play(sound_name, { - pos = pos, - max_hear_distance = 32, - gain = 10, - }) + minetest.sound_play(sound_name, { + pos = pos, + max_hear_distance = 32, + gain = 10, + }) + + minetest.set_node(pos, {name="default:stone_with_gold"}) + + else + + 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 end -function spawners.check_around_radius(pos) +function spawners.check_around_radius(pos, check_node) local player_near = false + local found_node = false local radius = 21 + local node_ore_pos = nil for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do if obj:is_player() then player_near = true end end + print("check_node: "..check_node) + if check_node and check_node == "default:stone" then + + node_ore_pos = minetest.find_node_near(pos, 3, {check_node}) + + if node_ore_pos then + found_node = node_ore_pos + print("found stone: "..minetest.pos_to_string(found_node)); + end + end - return player_near + return player_near, found_node end -function spawners.check_node_status(pos, mob, night_only) - local player_near = spawners.check_around_radius(pos) +function spawners.check_node_status(pos, mob, night_only, check_node) + if not check_node then check_node = "air" end + + local player_near, found_node = spawners.check_around_radius(pos, check_node) local random_pos = false - if player_near then + if check_node == "default:stone" and not found_node then + print("no stone found #2") + return false, true + elseif 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 + if not node_light then return false - else - -- pick random from the open sides - local pick_random + 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}) - if #spawn_positions == 1 then - pick_random = #spawn_positions - else - pick_random = math.random(1,#spawn_positions) + -- 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 - - for k, v in pairs (spawn_positions) do - if k == pick_random then - random_pos = v + 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 not touching node what he needs to + 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 - 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 + end -- spawn only at day if not night_only and node_light < min_node_light then + print("not enough light") return false, true end @@ -158,12 +195,12 @@ function spawners.check_node_status(pos, mob, night_only) if not (19359 > tod and tod > 5200) or node_light < min_node_light then return random_pos else - return false, true + return false, true, found_node end end - return random_pos + return random_pos, false, found_node else - return false + return false, true end end \ No newline at end of file diff --git a/init.lua b/init.lua index fbf4c33..c7d076b 100644 --- a/init.lua +++ b/init.lua @@ -4,5 +4,7 @@ dofile(minetest.get_modpath("spawners").."/config.lua") dofile(minetest.get_modpath("spawners").."/API.lua") -- Spawners for mobs dofile(minetest.get_modpath("spawners").."/spawners_mobs.lua") +-- Spawners for ores +dofile(minetest.get_modpath("spawners").."/spawners_ores.lua") print ("[MOD] Spawners 0.3 Loaded.") \ No newline at end of file diff --git a/spawners_mobs.lua b/spawners_mobs.lua index 34d1361..a6d42a7 100644 --- a/spawners_mobs.lua +++ b/spawners_mobs.lua @@ -175,7 +175,7 @@ function spawners.create(mob_name, mod_prefix, size, offset, mesh, texture, nigh elseif waiting then -- waiting status - if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_spawner_waiting" then + if node.name ~= "spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting" then minetest.set_node(pos, {name="spawners:"..mod_prefix.."_"..mob_name.."_spawner_waiting"}) end else diff --git a/spawners_ores.lua b/spawners_ores.lua new file mode 100644 index 0000000..0e280bb --- /dev/null +++ b/spawners_ores.lua @@ -0,0 +1,187 @@ +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) + -- dummy inside the spawner + local dummy_ore_definition = { + hp_max = 1, + physical = false, + collisionbox = {0,0,0,0,0,0}, + visual = "wielditem", + visual_size = size, + timer = 0, + textures={"default:stone_with_gold"}, + makes_footstep_sound = false, + automatic_rotate = math.pi * -3, + m_name = "dummy_ore" + } + + dummy_ore_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_ore_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:"..mob_name.."_spawner_active" then + self.object:remove() + end + end + end + + minetest.register_entity("spawners:dummy_ore_"..mob_name, dummy_ore_definition) + + -- node spawner active + minetest.register_node("spawners:"..mob_name.."_spawner_active", { + description = 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:"..mob_name.."_spawner", + on_construct = function(pos) + pos.y = pos.y + offset + minetest.add_entity(pos,"spawners:dummy_ore_"..mob_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", + 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:"..mob_name.."_spawner", + }) + + -- node spawner inactive (default) + minetest.register_node("spawners:"..mob_name.."_spawner", { + description = 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, found_node = spawners.check_node_status(pos, mob_name, night_only, "default:stone") + + if found_node then + minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner_active"}) + elseif waiting then + minetest.set_node(pos, {name="spawners: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"}, + 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") + + 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"}) + end + + -- enough place to spawn more ores + spawners.start_spawning(found_node, 1, "default:stone_with_gold", "", 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"}) + end + end + + end + }) + +end + +-- create all ore spawners +-- for i, mob_table in ipairs(spawners.mob_tables) do +-- if mob_table then + + 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