642 lines
23 KiB
Lua
642 lines
23 KiB
Lua
--[[
|
|
Let the player craft Mob Spawners. Mobs are spawning randomly in a short intervals, giving the option of creating mob farms and grinders.
|
|
Copyright (C) 2016 - 2023 SaKeL <juraj.vajda@gmail.com>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it pos the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to juraj.vajda@gmail.com
|
|
--]]
|
|
|
|
-- main tables
|
|
spawners_mobs = {
|
|
registered_spawners = {}
|
|
}
|
|
|
|
local max_obj_per_mapblock = tonumber(minetest.settings:get('max_objects_per_block'))
|
|
local enable_particles = minetest.settings:get_bool('enable_particles')
|
|
local tick_max = 30
|
|
local tick_short_max = 20
|
|
|
|
function spawners_mobs.register_spawner(name, def)
|
|
def.mod_prefix = name:split(':')[1]
|
|
def.mob_name = name:split(':')[2]
|
|
|
|
-- Entity inside the spawner
|
|
local ent_name = 'spawners_mobs:dummy_' .. def.mod_prefix .. '_' .. def.mob_name
|
|
local ent_def = {
|
|
hp_max = 1,
|
|
visual = def.dummy_visual or 'mesh',
|
|
visual_size = def.dummy_size,
|
|
collisionbox = { 0, 0, 0, 0, 0, 0 },
|
|
mesh = def.dummy_mesh,
|
|
textures = def.dummy_texture,
|
|
physical = false,
|
|
makes_footstep_sound = false,
|
|
automatic_rotate = math.pi * -3,
|
|
static_save = false,
|
|
timer = 0,
|
|
on_activate = function(self, staticdata, dtime_s)
|
|
self.object:set_velocity({ x = 0, y = 0, z = 0 })
|
|
self.object:set_acceleration({ x = 0, y = 0, z = 0 })
|
|
self.object:set_armor_groups({ immortal = 1 })
|
|
end
|
|
}
|
|
|
|
minetest.register_entity(ent_name, ent_def)
|
|
|
|
-- Default spawner (active)
|
|
local node_def = {}
|
|
node_def.description = def.mod_prefix .. '_' .. def.mob_name .. ' spawner'
|
|
node_def.paramtype = 'light'
|
|
node_def.paramtype2 = 'glasslikeliquidlevel'
|
|
node_def.drawtype = 'glasslike_framed_optional'
|
|
node_def.walkable = true
|
|
node_def.sounds = default.node_sound_metal_defaults()
|
|
node_def.sunlight_propagates = true
|
|
node_def.tiles = { 'spawners_mobs_spawner_16.png' }
|
|
node_def.is_ground_content = false
|
|
node_def.groups = {
|
|
-- MTG
|
|
cracky = 1,
|
|
level = 2
|
|
}
|
|
node_def.stack_max = 1
|
|
node_def.light_source = 6
|
|
node_def.on_timer = spawners_mobs.on_timer
|
|
node_def.on_construct = function(pos)
|
|
-- set meta
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_int('tick', 0)
|
|
meta:set_int('tick_short', 0)
|
|
|
|
spawners_mobs.set_status(pos, 'active')
|
|
spawners_mobs.tick_short(pos)
|
|
end
|
|
|
|
node_def.after_place_node = function(pos, placer, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string('owner', placer:get_player_name())
|
|
|
|
meta:set_string('infotext', def.mob_name .. ' spawner\nowner: ' .. placer:get_player_name() .. '\nspawner is active')
|
|
end
|
|
|
|
node_def.on_destruct = function(pos)
|
|
-- delete particles and remove dummy
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
end
|
|
|
|
local node_name = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner'
|
|
|
|
minetest.register_node(node_name, node_def)
|
|
spawners_mobs.registered_spawners[node_name] = def
|
|
|
|
-- Waiting spawner
|
|
local node_def_waiting = table.copy(node_def)
|
|
node_name = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner_waiting'
|
|
node_def_waiting.description = def.mod_prefix .. '_' .. def.mob_name .. ' spawner waiting'
|
|
node_def_waiting.tiles = {
|
|
{
|
|
name = 'spawners_mobs_spawner_waiting_animated_16.png',
|
|
animation = {
|
|
type = 'vertical_frames',
|
|
aspect_w = 16,
|
|
aspect_h = 16,
|
|
length = 2.0
|
|
}
|
|
}
|
|
}
|
|
node_def_waiting.groups = { cracky = 1, level = 2, not_in_creative_inventory = 1 }
|
|
node_def_waiting.light_source = 4
|
|
node_def_waiting.drop = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner'
|
|
node_def_waiting.on_timer = spawners_mobs.on_timer
|
|
node_def_waiting.on_construct = nil
|
|
node_def_waiting.after_place_node = nil
|
|
node_def_waiting.on_destruct = nil
|
|
|
|
minetest.register_node(node_name, node_def_waiting)
|
|
spawners_mobs.registered_spawners[node_name] = def
|
|
|
|
-- Rusty spawner
|
|
local node_def_rusty = table.copy(node_def)
|
|
node_name = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner_rusty'
|
|
node_def_rusty.description = def.mod_prefix .. '_' .. def.mob_name .. ' spawner rusty'
|
|
node_def_rusty.tiles = { 'spawners_mobs_spawner_rusty.png' }
|
|
node_def_rusty.groups = { cracky = 1, level = 2, not_in_creative_inventory = 1 }
|
|
node_def_rusty.drop = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner'
|
|
node_def_rusty.on_timer = nil
|
|
node_def_rusty.on_construct = nil
|
|
node_def_rusty.after_place_node = nil
|
|
node_def_rusty.on_destruct = nil
|
|
|
|
minetest.register_node(node_name, node_def_rusty)
|
|
spawners_mobs.registered_spawners[node_name] = def
|
|
|
|
-- Recipes
|
|
local mob_egg = name
|
|
|
|
if def.egg_name_custom and def.egg_name_custom ~= '' then
|
|
mob_egg = def.egg_name_custom
|
|
end
|
|
|
|
if minetest.registered_items[mob_egg] then
|
|
-- recipes
|
|
minetest.register_craft({
|
|
output = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner',
|
|
recipe = {
|
|
{ 'default:diamondblock', 'fire:flint_and_steel', 'default:diamondblock' },
|
|
{ 'xpanes:bar_flat', mob_egg, 'xpanes:bar_flat' },
|
|
{ 'default:diamondblock', 'xpanes:bar_flat', 'default:diamondblock' },
|
|
}
|
|
})
|
|
end
|
|
|
|
--
|
|
-- LBM
|
|
--
|
|
minetest.register_lbm({
|
|
name = 'spawners_mobs:start_nodetimer_' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner',
|
|
nodenames = 'spawners_mobs:' .. def.mod_prefix .. '_' .. def.mob_name .. '_spawner',
|
|
action = function(pos)
|
|
spawners_mobs.tick_short(pos)
|
|
end,
|
|
})
|
|
end
|
|
|
|
--
|
|
-- Particles
|
|
--
|
|
function spawners_mobs.cloud_booom(pos)
|
|
if not enable_particles then
|
|
return
|
|
end
|
|
|
|
minetest.add_particlespawner({
|
|
amount = 5,
|
|
time = 2,
|
|
minpos = vector.subtract({ x = pos.x - 0.3, y = pos.y, z = pos.z - 0.3 }, 0.3),
|
|
maxpos = vector.add({ x= pos.x + 0.3, y = pos.y, z = pos.z + 0.3 }, 0.3),
|
|
minvel = { x = 0.1, y = 0.1, z = 0.1 },
|
|
maxvel = { x = 0.2, y = 0.2, z = 0.2 },
|
|
minacc = vector.new({ x = -0.1, y = 0.3, z = -0.1 }),
|
|
maxacc = vector.new({ x = 0.1, y = 0.6, z = 0.1 }),
|
|
minexptime = 2,
|
|
maxexptime = 3,
|
|
minsize = 16,
|
|
maxsize = 24,
|
|
texture = 'spawners_mobs_smoke_particle_2.png',
|
|
animation = {
|
|
type = 'vertical_frames',
|
|
-- Width of a frame in pixels
|
|
aspect_w = 16,
|
|
-- Height of a frame in pixels
|
|
aspect_h = 16,
|
|
-- Full loop length
|
|
length = 2.0,
|
|
},
|
|
})
|
|
end
|
|
|
|
function spawners_mobs.add_flame_effects(pos)
|
|
if not enable_particles then
|
|
return
|
|
end
|
|
|
|
return minetest.add_particlespawner({
|
|
amount = 6,
|
|
time = 0,
|
|
minpos = vector.subtract({ x = pos.x - 0.001, y = pos.y - 0.001, z = pos.z - 0.001 }, 0.5),
|
|
maxpos = vector.add({ x = pos.x + 0.001, y = pos.y + 0.001, z = pos.z + 0.001 }, 0.5),
|
|
minvel = { x = -0.1, y = -0.1, z = -0.1 },
|
|
maxvel = { x = 0.1, y = 0.1, z = 0.1 },
|
|
minacc = vector.new(),
|
|
maxacc = vector.new(),
|
|
minexptime = 1,
|
|
maxexptime = 5,
|
|
minsize = 0.5,
|
|
maxsize = 2.5,
|
|
texture = 'spawners_mobs_flame_particle_2.png',
|
|
})
|
|
end
|
|
|
|
function spawners_mobs.add_smoke_effects(pos)
|
|
if not enable_particles then
|
|
return
|
|
end
|
|
|
|
return minetest.add_particlespawner({
|
|
amount = 1,
|
|
time = 0,
|
|
minpos = vector.subtract({ x = pos.x - 0.001, y = pos.y - 0.001, z = pos.z - 0.001 }, 0.5),
|
|
maxpos = vector.add({ x = pos.x + 0.001, y = pos.y + 0.001, z = pos.z + 0.001 }, 0.5),
|
|
minvel = { x = -0.5, y = 0.5, z = -0.5 },
|
|
maxvel = { x = 0.5, y = 1.5, z = 0.5 },
|
|
minacc = vector.new({ x = -0.1, y = 0.1, z = -0.1 }),
|
|
maxacc = vector.new({ x = 0.1, y = 0.3, z = 0.1 }),
|
|
minexptime = 0.5,
|
|
maxexptime = 2,
|
|
minsize = 0.5,
|
|
maxsize = 2,
|
|
texture = 'spawners_mobs_smoke_particle.png^[transform' .. math.random(0, 3),
|
|
})
|
|
end
|
|
|
|
--
|
|
-- Timers
|
|
--
|
|
-- how often node timers for spawners will tick, +/- some random value
|
|
function spawners_mobs.tick(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local tick_counter = meta:get_int('tick')
|
|
local owner = meta:get_string('owner')
|
|
local privs = minetest.get_player_privs(owner);
|
|
|
|
-- not for admin
|
|
if not privs.privs then
|
|
tick_counter = tick_counter + 1
|
|
meta:set_int('tick', tick_counter)
|
|
end
|
|
|
|
-- print('tick_counter: ' .. tick_counter .. ' at ' .. minetest.pos_to_string(pos))
|
|
|
|
-- rusty spawner
|
|
if tick_counter >= tick_max then
|
|
spawners_mobs.set_status(pos, 'rusty')
|
|
return
|
|
end
|
|
|
|
minetest.get_node_timer(pos):start(math.random(5, 15))
|
|
end
|
|
|
|
-- how often a spawn failure tick is retried (e.g. too dark)
|
|
function spawners_mobs.tick_short(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local tick_short_counter = meta:get_int('tick_short')
|
|
|
|
if tick_short_counter >= tick_short_max then
|
|
spawners_mobs.tick(pos)
|
|
return
|
|
else
|
|
tick_short_counter = tick_short_counter + 1
|
|
meta:set_int('tick_short', tick_short_counter)
|
|
-- print('tick_short_counter: ' .. tick_short_counter .. ' at ' .. minetest.pos_to_string(pos))
|
|
end
|
|
minetest.get_node_timer(pos):start(math.random(5, 10))
|
|
-- minetest.get_node_timer(pos):start(math.random(10, 20))
|
|
end
|
|
|
|
--
|
|
-- Core Functions
|
|
--
|
|
-- start spawning mobs
|
|
function spawners_mobs.start_spawning(spawn_area_random_pos, mob_name, mod_prefix, sound_custom)
|
|
if not (spawn_area_random_pos or mob_name) then
|
|
return
|
|
end
|
|
|
|
local sound_name = mod_prefix .. '_' .. mob_name
|
|
-- use custom sounds
|
|
if sound_custom ~= '' then
|
|
sound_name = sound_custom
|
|
end
|
|
|
|
-- use random colors for sheeps
|
|
if mob_name == 'sheep_white' then
|
|
local sheep_colors = { 'black', 'blue', 'brown', 'cyan', 'dark_green', 'dark_grey', 'green', 'grey', 'magenta', 'orange', 'pink', 'red', 'violet', 'white', 'yellow' }
|
|
mob_name = 'sheep_' .. sheep_colors[math.random(1, #sheep_colors)]
|
|
end
|
|
|
|
for i = 1, #spawn_area_random_pos do
|
|
-- spawn a bit more above the block - prevent spawning inside the block
|
|
spawn_area_random_pos[i].y = spawn_area_random_pos[i].y + 0.5
|
|
|
|
spawners_mobs.cloud_booom(spawn_area_random_pos[i])
|
|
|
|
minetest.after(1, function()
|
|
-- minetest.set_node(spawn_area_random_pos[i], {name = 'default:apple' })
|
|
local obj = minetest.add_entity(spawn_area_random_pos[i], mod_prefix .. ':' .. mob_name)
|
|
if obj then
|
|
if sound_name then
|
|
minetest.sound_play(sound_name, {
|
|
pos = spawn_area_random_pos[i],
|
|
max_hear_distance = 16,
|
|
gain = 0.5
|
|
})
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
function spawners_mobs.on_timer(pos, elapsed)
|
|
local meta = minetest.get_meta(pos)
|
|
local node = minetest.get_node(pos)
|
|
local mob_table = spawners_mobs.registered_spawners[node.name]
|
|
|
|
if not mob_table then
|
|
return
|
|
end
|
|
|
|
local posmin = { x = pos.x - 3, y = pos.y - 1, z = pos.z - 3 }
|
|
local posmax = { x = pos.x + 4, y = pos.y + 1, z = pos.z + 4 }
|
|
local player_near = false
|
|
local entities_near = 0
|
|
local entities_max = 6
|
|
local node_light_min = 13
|
|
|
|
local owner = meta:get_string('owner') or ''
|
|
local mod_prefix = mob_table.mod_prefix
|
|
local mob_name = mob_table.mob_name
|
|
local sound_custom = mob_table.sound_custom
|
|
local night_only = mob_table.night_only
|
|
local max_objects = max_obj_per_mapblock / 4
|
|
local offset = mob_table.dummy_offset
|
|
local has_dummy = false
|
|
|
|
local objects_inside_radius = minetest.get_objects_inside_radius(pos, 0.5)
|
|
|
|
for _, obj in ipairs(objects_inside_radius) do
|
|
local lua_ent = obj:get_luaentity()
|
|
|
|
if lua_ent then
|
|
if lua_ent.name == 'spawners_mobs:dummy_' .. mod_prefix .. '_' .. mob_name then
|
|
has_dummy = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if not has_dummy and meta:get_string('status') == 'active' then
|
|
minetest.add_entity({ x = pos.x, y = pos.y + offset, z = pos.z }, 'spawners_mobs:dummy_' .. mod_prefix .. '_' .. mob_name)
|
|
end
|
|
|
|
-- check spawner light
|
|
local node_light = minetest.get_node_light(pos)
|
|
|
|
-- dark
|
|
if (not node_light or node_light < node_light_min) and not night_only then
|
|
-- print('Too dark for mob ( ' .. mob_name .. ' ) to spawn. Waiting for day .. .')
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
|
|
-- set infotext
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nToo dark for mob to spawn. Waiting for day .. .')
|
|
spawners_mobs.tick_short(pos)
|
|
return
|
|
|
|
elseif node_light >= node_light_min and night_only then
|
|
-- light
|
|
-- print('Too much light for mob ( ' .. mob_name .. ' ) to spawn. Waiting for night .. .')
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
|
|
-- set infotext
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nToo much light for mob to spawn. Waiting for night .. .')
|
|
spawners_mobs.tick_short(pos)
|
|
return
|
|
end
|
|
|
|
-- positions where mobs can spawn
|
|
local spawn_area_pos = minetest.find_nodes_in_area(posmin, posmax, 'air')
|
|
|
|
-- check if there is enough place to spawn mob
|
|
if #spawn_area_pos < 1 then
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
|
|
-- set infotext
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nNot enough place to spawn mob. Find more space!')
|
|
spawners_mobs.tick(pos)
|
|
return
|
|
end
|
|
|
|
-- spawn 2 mobs on 2 different positions by chance
|
|
local how_many = math.random(1, 2)
|
|
local spawn_area_random_pos = {}
|
|
|
|
-- get random spawn position from spawn area
|
|
for i = 1, how_many do
|
|
while #spawn_area_random_pos < how_many and #spawn_area_pos > 0 do
|
|
|
|
local random_pos = spawn_area_pos[math.random(#spawn_area_pos)]
|
|
local random_pos_above = minetest.get_node({ x = random_pos.x, y = random_pos.y + 1, z = random_pos.z }).name
|
|
|
|
if random_pos_above == 'air' and not minetest.is_protected(random_pos, owner) then
|
|
table.insert(spawn_area_random_pos, random_pos)
|
|
-- print('spawn_area_random_pos: ' .. #spawn_area_random_pos)
|
|
else
|
|
table.remove(spawn_area_pos, i)
|
|
-- print('spawn_area_pos: ' .. #spawn_area_pos)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
-- print(dump(spawn_area_random_pos))
|
|
|
|
-- check if there is still enough place to spawn mob
|
|
if #spawn_area_random_pos < 1 then
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
|
|
-- set infotext
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nNot enough place to spawn mob. Searching for new location .. .')
|
|
spawners_mobs.tick_short(pos)
|
|
return
|
|
end
|
|
|
|
-- area where player and entity count will be detected
|
|
local activation_area = minetest.get_objects_inside_radius(pos, 16)
|
|
|
|
-- prevent object clutter on the map
|
|
if #activation_area > max_objects then
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
|
|
-- set infotext
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nToo many objects in the area (' .. #activation_area .. '/' .. max_objects .. '), clean-up dropped objects first!')
|
|
spawners_mobs.tick_short(pos)
|
|
return
|
|
end
|
|
|
|
for k, object in ipairs(activation_area) do
|
|
-- find player inside activation area
|
|
if object:is_player() then
|
|
player_near = true
|
|
-- print('found player: ' .. object:get_player_name())
|
|
end
|
|
|
|
-- find entities inside activation area
|
|
if not object:is_player()
|
|
and object:get_luaentity()
|
|
and object:get_luaentity().name ~= '__builtin:item'
|
|
then
|
|
local tmp_mob_name = string.split(object:get_luaentity().name, ':')[2]
|
|
|
|
if tmp_mob_name ~= nil then
|
|
-- sheeps have colors in names
|
|
if string.find(tmp_mob_name, 'sheep') and string.find(mob_name, 'sheep') and not string.find(tmp_mob_name, 'dummy') then
|
|
-- print('found entity: ' .. tmp_mob_name)
|
|
entities_near = entities_near + 1
|
|
|
|
elseif tmp_mob_name == mob_name then
|
|
-- print('found entity: ' .. tmp_mob_name)
|
|
entities_near = entities_near + 1
|
|
end
|
|
else
|
|
minetest.log('warning', '[spawners_mobs] tmp_mob_name was nil, luaentity name was: ' .. object:get_luaentity().name .. ' at: ' .. minetest.pos_to_string(object:get_pos()))
|
|
end
|
|
end
|
|
|
|
-- stop looping when met all conditions
|
|
if entities_near >= entities_max and player_near then
|
|
-- print('max entities reached ' .. entities_max .. ' and player_near found, breaking .. ')
|
|
break
|
|
end
|
|
end
|
|
|
|
-- don't do anything and try again later when player not near or max entities reached
|
|
if entities_near >= entities_max or not player_near then
|
|
spawners_mobs.set_status(pos, 'waiting')
|
|
|
|
-- sheeps have color in the name
|
|
-- local name = mob_name
|
|
-- if string.find(mob_name, 'sheep') then
|
|
-- name = 'sheep'
|
|
-- end
|
|
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nmax mobs reached: ' .. entities_near .. '/' .. entities_max) -- or player not near
|
|
spawners_mobs.tick_short(pos)
|
|
return
|
|
end
|
|
|
|
-- start spawning
|
|
spawners_mobs.start_spawning(spawn_area_random_pos, mob_name, mod_prefix, sound_custom)
|
|
|
|
spawners_mobs.set_status(pos, 'active')
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nspawner is active reached: ' .. entities_near .. '/' .. entities_max)
|
|
|
|
meta:set_int('tick', 0)
|
|
meta:set_int('tick_short', 0)
|
|
|
|
spawners_mobs.tick(pos)
|
|
end
|
|
|
|
--
|
|
-- Status Manager
|
|
--
|
|
function spawners_mobs.set_status(pos, set_status)
|
|
local meta = minetest.get_meta(pos)
|
|
local node = minetest.get_node(pos)
|
|
local mob_table = spawners_mobs.registered_spawners[node.name]
|
|
|
|
if not mob_table then
|
|
return
|
|
end
|
|
|
|
local mod_prefix = mob_table.mod_prefix
|
|
local mob_name = mob_table.mob_name
|
|
local offset = mob_table.dummy_offset
|
|
|
|
-- get meta
|
|
local owner = meta:get_string('owner')
|
|
local meta_status = meta:get_string('status')
|
|
local id_flame = meta:get_int('id_flame')
|
|
local id_smoke = meta:get_int('id_smoke')
|
|
|
|
--
|
|
-- active
|
|
--
|
|
if set_status == 'active' then
|
|
-- remove particles and add them again - keeps particles after server restart
|
|
-- delete particles
|
|
if id_flame ~= -1 and id_smoke ~= -1 then
|
|
-- print('#1 delete id_flame: ' .. id_flame .. ' at ' .. minetest.pos_to_string(pos))
|
|
-- print('#1 delete id_smoke: ' .. id_smoke .. ' at ' .. minetest.pos_to_string(pos))
|
|
minetest.delete_particlespawner(id_flame)
|
|
minetest.delete_particlespawner(id_smoke)
|
|
meta:set_int('id_flame', -1)
|
|
meta:set_int('id_smoke', -1)
|
|
end
|
|
|
|
-- add particles
|
|
id_flame = spawners_mobs.add_flame_effects(pos)
|
|
id_smoke = spawners_mobs.add_smoke_effects(pos)
|
|
meta:set_int('id_flame', id_flame)
|
|
meta:set_int('id_smoke', id_smoke)
|
|
-- print('#1 add id_flame: ' .. id_flame .. ' at ' .. minetest.pos_to_string(pos))
|
|
-- print('#1 add id_smoke: ' .. id_smoke .. ' at ' .. minetest.pos_to_string(pos))
|
|
|
|
if meta_status ~= set_status then
|
|
-- add dummy entity
|
|
minetest.add_entity({ x = pos.x, y = pos.y + offset, z = pos.z }, 'spawners_mobs:dummy_' .. mod_prefix .. '_' .. mob_name)
|
|
|
|
meta:set_string('status', 'active')
|
|
|
|
minetest.swap_node(pos, { name = 'spawners_mobs:' .. mod_prefix .. '_' .. mob_name .. '_spawner' })
|
|
end
|
|
elseif set_status == 'waiting' and meta_status ~= set_status then
|
|
--
|
|
-- waiting
|
|
--
|
|
|
|
-- delete particles
|
|
if id_flame ~= -1 and id_smoke ~= -1 then
|
|
-- print('#2 delete id_flame: ' .. id_flame .. ' at ' .. minetest.pos_to_string(pos))
|
|
-- print('#2 delete id_smoke: ' .. id_smoke .. ' at ' .. minetest.pos_to_string(pos))
|
|
minetest.delete_particlespawner(id_flame)
|
|
minetest.delete_particlespawner(id_smoke)
|
|
meta:set_int('id_flame', -1)
|
|
meta:set_int('id_smoke', -1)
|
|
end
|
|
|
|
-- remove dummy
|
|
local objs = minetest.get_objects_inside_radius(pos, 0.5)
|
|
if objs then
|
|
for _, obj in ipairs(objs) do
|
|
if obj and obj:get_luaentity() and obj:get_luaentity().name == 'spawners_mobs:dummy_' .. mod_prefix .. '_' .. mob_name then
|
|
obj:remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
meta:set_string('status', 'waiting')
|
|
|
|
minetest.swap_node(pos, { name = 'spawners_mobs:' .. mod_prefix .. '_' .. mob_name .. '_spawner_waiting' })
|
|
elseif set_status == 'rusty' and meta_status ~= set_status then
|
|
--
|
|
-- rusty
|
|
--
|
|
|
|
-- delete particles
|
|
if id_flame ~= -1 and id_smoke ~= -1 then
|
|
-- print('#3 delete id_flame: ' .. id_flame .. ' at ' .. minetest.pos_to_string(pos))
|
|
-- print('#3 delete id_smoke: ' .. id_smoke .. ' at ' .. minetest.pos_to_string(pos))
|
|
minetest.delete_particlespawner(id_flame)
|
|
minetest.delete_particlespawner(id_smoke)
|
|
meta:set_int('id_flame', -1)
|
|
meta:set_int('id_smoke', -1)
|
|
end
|
|
|
|
-- remove dummy
|
|
local objs = minetest.get_objects_inside_radius(pos, 0.5)
|
|
if objs then
|
|
for _, obj in ipairs(objs) do
|
|
if obj and obj:get_luaentity() and obj:get_luaentity().name == 'spawners_mobs:dummy_' .. mod_prefix .. '_' .. mob_name then
|
|
obj:remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
meta:set_string('status', 'rusty')
|
|
|
|
minetest.swap_node(pos, { name = 'spawners_mobs:' .. mod_prefix .. '_' .. mob_name .. '_spawner_rusty' })
|
|
|
|
-- set infotext
|
|
meta:set_string('infotext', mob_name .. ' spawner\nowner: ' .. owner .. '\nSpawner was searching for too long and got rusted! Dig up the spawner and place it again.')
|
|
return
|
|
end
|
|
end
|