Spawners Mobs - refactor finalized

master
Juraj Vajda 2018-01-06 23:31:21 -05:00
parent e7c13ed83c
commit ac99689081
22 changed files with 856 additions and 629 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
settings.txt
config.lua

View File

@ -1,31 +1,50 @@
# Spawners #
This MOD for Minetest let the player craft mob and ore Spawner blocks. Mobs/Ores are spawning randomly in a short intervals.
From version 0.6 Pyramids can be spawned in desert and environmental spwaners are added. Environmental spawners are used for spawning inside of temples and dungeons (mapgen v6 default minetest game). - Thanks to BlockMen. These kind of spawners are very rarely dropping real mob spawners, in any other case they don't drop anything.
# Spawners Modpack #
This MOD for Minetest adds multiple spawner blocks. There ara no ABM's used and this modpack is developed with focus on the best multiplayer online server performace.
Easy to implement new mob mods just look in to config.lua.
New features can be enabled/disabled in settings.txt file.
Currently it works with [Pyramids Mummy](https://forum.minetest.net/viewtopic.php?id=7063), [Mobs Redo](https://forum.minetest.net/viewtopic.php?f=11&t=9917) and [Creatures](https://forum.minetest.net/viewtopic.php?f=11&t=8638).
Currently it works with [Mobs Redo](https://forum.minetest.net/viewtopic.php?f=11&t=9917) and [Creatures](https://forum.minetest.net/viewtopic.php?f=11&t=8638) but other mob mods can be easily added to config.lua
![spawners_promo.jpg](https://bitbucket.org/repo/y69Me7/images/3793257566-spawners_promo.jpg)
![spawner_waiting_medium.gif](https://bitbucket.org/repo/y69Me7/images/246761582-spawner_waiting_medium.gif) ![spawner_animated_medium.gif](https://bitbucket.org/repo/y69Me7/images/1359872529-spawner_animated_medium.gif)
## YouTube video ##
[Minetest - spawners MOD v0.1](https://youtu.be/TlaMVl0ZDtw)
## Spawners Ores ##
## Mod dependencies ##
![Spawners Ores](spawners_ores/screenshot.png)
This MOD for Minetest let the player craft ore Spawners. Ores are spawning randomly in a short intervals and you get 10% more ores from inputed ingots. Ores are spawning only in default:stone so make sure there is one around. This MOD is giving the option of creating lumps back from ingots.
### Mod dependencies ###
* default
* fake_fire?
## Spawners Mobs ##
This MOD for Minetest let the player craft Mob Spawners. Mobs are spawning randomly in a short intervals. This MOD is giving the option of creating mob farms and grinders.
![Spawners Mobs](spawners_mobs/screenshot.png)
### Mod dependencies ###
* default
* fire?
* xpanes?
* mobs?
* creatures?
* pyramids?
mobs redo, creatures are supported mods
* bones?
fake_fire, xpanes for recipes
bones are for mob drops only
## Spawners Environmental ##
This MOD for Minetest adds environmental spawners to the map. When enabled, the spawners will be added to newly generated Dungeons (Uruk Hai) and Temples (Spider). They are dropping a real mob spawner by change (very small chance).
![Spawners Mobs](spawners_env/screenshot.png)
### Mod dependencies ###
* default
## Links ##
[[Mod]Minetest Forum Page](https://forum.minetest.net/viewtopic.php?f=11&t=13857)
@ -36,9 +55,15 @@ fake_fire, xpanes for recipes
[G+ Community](https://plus.google.com/communities/105201070842404099845)
## License ##
WTFPL
![WTFPL](http://www.wtfpl.net/wp-content/uploads/2012/12/wtfpl-badge-1.png)
## Changelog ##
### 1.0 ###
* refactored Spawners Ores - best multiplayer performance usable on online servers
* refactored Spawners Mobs - best multiplayer performance usable on online servers
* refactored Spawners Env - best multiplayer performance usable on online servers
### 0.6 ###
* inherited BlockMen Pyramid mod, so now Spawners can spawn Pyramids in desert (mapgen v6)
* spawning Pyramids work independently from BlockMen Pyramids mod (can be removed) but works also besides BlockMen Pyramid mod

View File

@ -1 +0,0 @@
This MOD for Minetest let the player craft mob and ore Spawner blocks. Mobs/Ores are spawning randomly in a short intervals.

View File

@ -1,165 +1,13 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
0. You just DO WHAT THE FUCK YOU WANT TO.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

238
spawners_env/config.lua Normal file
View File

@ -0,0 +1,238 @@
-- * [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 : boolean : string] - If true mobs will spawn "only" during the night or in dark areas, default:true. Writing "disable" will disable light check and it will spawn in both states (night and day)
-- [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, remove/add the one you want to load
ENABLED_MODS = {"mobs", "creatures"}
-- mobs properties - setup all you mobs here
MOBS_PROPS = {
["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_wool.png^mobs_sheep_base.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 = "pumba",
egg_name_custom = "",
dummy_size = {x = 0.62, y = 0.62},
dummy_offset = -0.3,
dummy_mesh = "mobs_pumba.x",
dummy_texture = {"mobs_pumba.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_mobs_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 = ""
-- },
{
name = "spider",
egg_name_custom = "",
dummy_size = {x = 2, y = 2},
dummy_offset = -0.2,
dummy_mesh = "mobs_spider.x",
dummy_texture = {"mobs_spider.png"},
night_only = true,
sound_custom = "",
env = true
},
{
name = "stone_monster",
egg_name_custom = "",
dummy_size = {x = 0.5, y = 0.5},
dummy_offset = 0.05,
dummy_mesh = "mobs_stone_monster.b3d",
dummy_texture = {"mobs_stone_monster.png"},
night_only = true,
sound_custom = "mobs_stonemonster"
},
{
name = "oerkki",
egg_name_custom = "",
dummy_size = {x = 0.5, y = 0.5},
dummy_offset = 0.05,
dummy_mesh = "mobs_oerkki.b3d",
dummy_texture = {"mobs_oerkki.png"},
night_only = true,
sound_custom = ""
},
{
name = "tree_monster",
egg_name_custom = "",
dummy_size = {x = 0.4, y = 0.4},
dummy_offset = 0.05,
dummy_mesh = "mobs_tree_monster.b3d",
dummy_texture = {"mobs_tree_monster.png"},
night_only = true,
sound_custom = "mobs_treemonster"
}
},
["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 = false,
sound_custom = ""
},
{
name = "oerrki",
egg_name_custom = "creatures:oerrki_spawn_egg",
dummy_size = {x = 0.4, y = 0.4},
dummy_offset = -0.5,
dummy_mesh = "creatures_oerrki.b3d",
dummy_texture = {"creatures_oerrki.png"},
night_only = false,
sound_custom = "creatures_oerrki_idle"
}
}
}
--
-- check for 3rd party dependencies
--
-- include mummy mobs redo addon (spawner)
if minetest.get_modpath("mobs") ~= nil then
-- enable spawner
table.insert(ENABLED_MODS, "spawners_mobs")
-- configure spawner
MOBS_PROPS["spawners_mobs"] = {
{
name = "mummy",
egg_name_custom = "",
dummy_size = {x = 0.4, y = 0.4},
dummy_offset = 0,
dummy_mesh = "spawners_mobs_mummy.b3d",
dummy_texture = {"spawners_mobs_mummy.png"},
night_only = true,
sound_custom = "spawners_mobs_mummy"
},
{
name = "bunny_evil",
egg_name_custom = "",
dummy_size = {x = 1, y = 1},
dummy_offset = 0.2,
dummy_mesh = "spawners_mobs_evil_bunny.b3d",
dummy_texture = {"spawners_mobs_evil_bunny.png"},
night_only = true,
sound_custom = "spawners_mobs_bunny"
},
{
name = "uruk_hai",
egg_name_custom = "",
dummy_size = {x = 0.5, y = 0.5},
dummy_offset = 0,
dummy_mesh = "spawners_mobs_character.b3d",
dummy_texture = {"spawners_mobs_uruk_hai.png", "spawners_mobs_trans.png","spawners_mobs_galvornsword.png", "spawners_mobs_trans.png"},
night_only = true,
sound_custom = "spawners_mobs_barbarian_yell2",
env = true
},
{
name = "balrog",
egg_name_custom = "",
dummy_size = {x = 0.2, y = 0.2},
dummy_offset = 0,
dummy_mesh = "spawners_mobs_balrog.b3d",
dummy_texture = {"spawners_mobs_balrog.png"},
night_only = "disable",
sound_custom = "spawners_mobs_howl",
env = true,
boss = true
}
}
end

View File

@ -1,2 +1 @@
default
spawners_mobs

View File

@ -1,7 +1,7 @@
MOD_NAME = minetest.get_current_modname()
-- Spawners configurations
dofile(minetest.get_modpath("spawners_mobs").."/config.lua")
dofile(minetest.get_modpath(MOD_NAME).."/config.lua")
-- API
dofile(minetest.get_modpath(MOD_NAME).."/api.lua")

BIN
spawners_env/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

View File

@ -0,0 +1,3 @@
SPAWN_PYRAMIDS = false
SPAWNERS_GENERATE = true
CHESTS_GENERATE = false

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -1,6 +1,10 @@
-- main tables
spawners_mobs = {}
spawners_mobs.mob_tables = {}
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 = 20
local tick_short_max = 20
-- check if mods exists and build tables
for k, mob_mod in ipairs(ENABLED_MODS) do
@ -48,23 +52,12 @@ for k, mob_mod in ipairs(ENABLED_MODS) do
end
end
function spawners_mobs.meta_get_int(key, pos)
local meta = minetest.get_meta(pos)
return meta:get_int(key)
end
function spawners_mobs.meta_set_int(key, value, pos)
local meta = minetest.get_meta(pos)
meta:set_int(key, value)
end
function spawners_mobs.meta_set_str(key, value, pos)
local meta = minetest.get_meta(pos)
meta:set_string(key, value)
end
-- particles
--
-- Particles
--
function spawners_mobs.cloud_booom(pos)
if not enable_particles then return end
minetest.add_particlespawner({
amount = 5,
time = 2,
@ -83,6 +76,8 @@ function spawners_mobs.cloud_booom(pos)
end
function spawners_mobs.add_flame_effects(pos)
if not enable_particles then return end
local id = minetest.add_particlespawner({
amount = 6,
time = 0,
@ -103,6 +98,8 @@ function spawners_mobs.add_flame_effects(pos)
end
function spawners_mobs.add_smoke_effects(pos)
if not enable_particles then return end
local id = minetest.add_particlespawner({
amount = 1,
time = 0,
@ -122,9 +119,47 @@ function spawners_mobs.add_smoke_effects(pos)
return id
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")
tick_counter = tick_counter + 1
meta:set_int("tick", tick_counter)
-- print("tick_counter: "..tick_counter)
-- rusty spawner
if tick_counter >= tick_max then
spawners_mobs.set_status(pos, "rusty")
return
end
minetest.get_node_timer(pos):start(math.random(40, 80))
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)
end
minetest.get_node_timer(pos):start(math.random(20, 40))
end
--
-- Core Functions
--
-- start spawning mobs
function spawners_mobs.start_spawning(random_pos, mob_name, mod_prefix, sound_custom)
if not (random_pos or how_many or mob_name) then return end
function spawners_mobs.start_spawning(spawn_area_random_pos, mob_name, mod_prefix, sound_custom)
if not (spawn_area_random_pos or how_many or mob_name) then return end
local sound_name = mod_prefix.."_"..mob_name
-- use custom sounds
@ -132,34 +167,27 @@ function spawners_mobs.start_spawning(random_pos, mob_name, mod_prefix, sound_cu
sound_name = sound_custom
end
-- remove 'spawners_mobs:' from the string
print("#2 mod_prefix: "..mod_prefix)
print("#2 mob_name: "..mob_name)
-- local mob_name = string.sub(mob_name,15)
-- 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(#sheep_colors)]
end
local how_many = math.random(2)
print("how_many: ", how_many)
for i = 1, how_many do
for i = 1, #spawn_area_random_pos do
-- spawn a bit more above the block - prevent spawning inside the block
random_pos.y = random_pos.y + 0.5
spawn_area_random_pos[i].y = spawn_area_random_pos[i].y + 0.5
spawners_mobs.cloud_booom(random_pos)
spawners_mobs.cloud_booom(spawn_area_random_pos[i])
minetest.after(1, function()
local obj = minetest.add_entity(random_pos, mod_prefix..":"..mob_name)
-- 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 = random_pos,
max_hear_distance = 10,
pos = spawn_area_random_pos[i],
max_hear_distance = 8,
gain = 0.3
})
end
@ -168,53 +196,12 @@ function spawners_mobs.start_spawning(random_pos, mob_name, mod_prefix, sound_cu
end
end
function spawners_mobs.check_around_radius(pos, mob)
local player_near = false
local radius = 21
local mobs = {}
function spawners_mobs.on_timer(pos, elapsed)
local meta = minetest.get_meta(pos)
local idx = meta:get_int("idx") or nil
local mob_table = spawners_mobs.mob_tables[idx] or false
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do
local luae = obj:get_luaentity()
-- check for number of mobs near by
if luae ~= nil and luae.name ~= nil and mob ~= nil then
local mob_name = string.split(luae.name, ":")
mob_name = mob_name[2]
if mob_name == mob then
table.insert(mobs, mob)
end
if #mobs >= 8 then
player_near = false
return player_near
end
end
-- check for player near by
if obj:is_player() then
player_near = true
end
end
return player_near
end
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
-- is area protected against name?
if not protector.can_dig(protector.radius, pos, name, false, 1) then
return true
end
-- otherwise can dig or place
return old_is_protected(pos, name)
end
function spawners_mobs.check_node_status(pos, mob, night_only)
-- re-factor
if not mob_table then return end
local posmin = { x = pos.x - 4, y = pos.y - 1, z = pos.z - 4 }
local posmax = { x = pos.x + 4, y = pos.y + 1, z = pos.z + 4 }
@ -222,58 +209,98 @@ function spawners_mobs.check_node_status(pos, mob, night_only)
local entities_near = 0
local entities_max = 6
local node_light_min = 13
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner") or ""
local mod_prefix = meta:get_string("mod_prefix") or false
local mob_name = meta:get_string("mob_name") or false
local sound_custom = meta:get_string("sound_custom") or ""
print("#1 mod_prefix: "..mod_prefix)
print("#1 mob_name: "..mob_name)
if not (mod_prefix or mob_name) then return end
local mod_prefix = mob_table.mod_prefix
local mob_name = mob_table.name
local sound_custom = mob_table.sound_custom
local night_only = mob_table.night_only
local max_objects = max_obj_per_mapblock / 4
-- check spawner light
local node_light = minetest.get_node_light(pos)
if (not node_light or node_light < node_light_min) and night_only then
-- too dark - spawn only hostile mobs
print("too dark - spawn only hostile mobs")
elseif node_light >= node_light_min and not night_only then
-- enough light - spawn only friendly mobs
print("enough light - spawn only friendly mobs")
else
-- too dark for friendly mob to spawn or too light for hostile mob to spawn
print("too dark for friendly mob to spawn or too light for hostile mob to spawn")
-- tick short
-- 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
-- light
elseif node_light >= node_light_min and night_only then
-- 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")
-- get random spawn position from spawn area
local random_idx = math.random(#spawn_area_pos)
local random_pos = spawn_area_pos[random_idx]
local random_pos_above = minetest.get_node({ x = random_pos.x, y = random_pos.y + 1, z = random_pos.z }).name
-- check if there is enough place to spawn mob
if random_pos_above ~= "air" then
-- tick short
print("no random position found")
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
-- don't do anything and try again later when random position is protected
if minetest.is_protected(random_pos, owner) then
print("random pos is protected")
minetest.record_protection_violation(random_pos, owner)
-- tick short
-- spawn 2 mobs on 2 different positions by chance
local how_many = math.random(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
@ -288,11 +315,11 @@ function spawners_mobs.check_node_status(pos, mob, night_only)
local tmp_mob_name = string.split(object:get_luaentity().name, ":")[2]
-- sheeps have colors in names
if string.find(tmp_mob_name, "sheep") and string.find(mob, "sheep") then
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 then
elseif tmp_mob_name == mob_name then
-- print("found entity: "..tmp_mob_name)
entities_near = entities_near + 1
end
@ -307,102 +334,128 @@ function spawners_mobs.check_node_status(pos, mob, night_only)
-- 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
-- tick short
print("max entities reached "..entities_max.." or player not near")
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 idx = meta:get_int("idx")
local mob_table = spawners_mobs.mob_tables[idx] or false
if not mob_table then return end
local mod_prefix = mob_table.mod_prefix
local mob_name = mob_table.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 and id_smoke and id_flame ~= nil and id_smoke ~= nil then
minetest.delete_particlespawner(id_flame)
minetest.delete_particlespawner(id_smoke)
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)
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
--
-- waiting
--
elseif set_status == "waiting" and meta_status ~= set_status then
-- delete particles
if id_flame and id_smoke and id_flame ~= nil and id_smoke ~= nil then
minetest.delete_particlespawner(id_flame)
minetest.delete_particlespawner(id_smoke)
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"})
--
-- rusty
--
elseif set_status == "rusty" and meta_status ~= set_status then
-- delete particles
if id_flame and id_smoke and id_flame ~= nil and id_smoke ~= nil then
minetest.delete_particlespawner(id_flame)
minetest.delete_particlespawner(id_smoke)
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
-- start spawning
-- minetest.set_node(random_pos, { name = "default:apple" })
spawners_mobs.start_spawning(random_pos, mob_name, mod_prefix, sound_custom)
-- /re-factor
-- if player_near then
-- local random_pos = false
-- local min_node_light = 10
-- local tod = minetest.get_timeofday() * 24000
-- local node_light = minetest.get_node_light(pos)
-- if not node_light then
-- return false
-- end
-- local spawn_positions = {}
-- local right = minetest.get_node_or_nil({x=pos.x+1, y=pos.y, z=pos.z})
-- local front = minetest.get_node_or_nil({x=pos.x, y=pos.y, z=pos.z+1})
-- local left = minetest.get_node_or_nil({x=pos.x-1, y=pos.y, z=pos.z})
-- local back = minetest.get_node_or_nil({x=pos.x, y=pos.y, z=pos.z-1})
-- local top = minetest.get_node_or_nil({x=pos.x, y=pos.y+1, z=pos.z})
-- local bottom = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z})
-- -- make sure that at least one side of the spawner is open
-- if right ~= nil and right.name == "air" then
-- table.insert(spawn_positions, {x=pos.x+1.5, y=pos.y, z=pos.z})
-- end
-- if front ~= nil and front.name == "air" then
-- table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z+1.5})
-- end
-- if left ~= nil and left.name == "air" then
-- table.insert(spawn_positions, {x=pos.x-1.5, y=pos.y, z=pos.z})
-- end
-- if back ~= nil and back.name == "air" then
-- table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z-1.5})
-- end
-- if top ~= nil and top.name == "air" then
-- table.insert(spawn_positions, {x=pos.x, y=pos.y+1.5, z=pos.z})
-- end
-- if bottom ~= nil and 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(#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
-- if night_only ~= "disable" then
-- -- 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
-- end
-- -- random_pos, waiting
-- return random_pos, false
-- else
-- -- random_pos, waiting
-- return false, true
-- end
end

238
spawners_mobs/config.lua Normal file
View File

@ -0,0 +1,238 @@
-- * [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 : boolean : string] - If true mobs will spawn "only" during the night or in dark areas, default:true. Writing "disable" will disable light check and it will spawn in both states (night and day)
-- [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, remove/add the one you want to load
ENABLED_MODS = {"mobs", "creatures"}
-- mobs properties - setup all you mobs here
MOBS_PROPS = {
["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_wool.png^mobs_sheep_base.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 = "pumba",
egg_name_custom = "",
dummy_size = {x = 0.62, y = 0.62},
dummy_offset = -0.3,
dummy_mesh = "mobs_pumba.x",
dummy_texture = {"mobs_pumba.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_mobs_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 = ""
-- },
{
name = "spider",
egg_name_custom = "",
dummy_size = {x = 2, y = 2},
dummy_offset = -0.2,
dummy_mesh = "mobs_spider.x",
dummy_texture = {"mobs_spider.png"},
night_only = true,
sound_custom = "",
env = true
},
{
name = "stone_monster",
egg_name_custom = "",
dummy_size = {x = 0.5, y = 0.5},
dummy_offset = 0.05,
dummy_mesh = "mobs_stone_monster.b3d",
dummy_texture = {"mobs_stone_monster.png"},
night_only = true,
sound_custom = "mobs_stonemonster"
},
{
name = "oerkki",
egg_name_custom = "",
dummy_size = {x = 0.5, y = 0.5},
dummy_offset = 0.05,
dummy_mesh = "mobs_oerkki.b3d",
dummy_texture = {"mobs_oerkki.png"},
night_only = true,
sound_custom = ""
},
{
name = "tree_monster",
egg_name_custom = "",
dummy_size = {x = 0.4, y = 0.4},
dummy_offset = 0.05,
dummy_mesh = "mobs_tree_monster.b3d",
dummy_texture = {"mobs_tree_monster.png"},
night_only = true,
sound_custom = "mobs_treemonster"
}
},
["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 = false,
sound_custom = ""
},
{
name = "oerrki",
egg_name_custom = "creatures:oerrki_spawn_egg",
dummy_size = {x = 0.4, y = 0.4},
dummy_offset = -0.5,
dummy_mesh = "creatures_oerrki.b3d",
dummy_texture = {"creatures_oerrki.png"},
night_only = false,
sound_custom = "creatures_oerrki_idle"
}
}
}
--
-- check for 3rd party dependencies
--
-- include mummy mobs redo addon (spawner)
if minetest.get_modpath("mobs") ~= nil then
-- enable spawner
table.insert(ENABLED_MODS, "spawners_mobs")
-- configure spawner
MOBS_PROPS["spawners_mobs"] = {
{
name = "mummy",
egg_name_custom = "",
dummy_size = {x = 0.4, y = 0.4},
dummy_offset = 0,
dummy_mesh = "spawners_mobs_mummy.b3d",
dummy_texture = {"spawners_mobs_mummy.png"},
night_only = true,
sound_custom = "spawners_mobs_mummy"
},
{
name = "bunny_evil",
egg_name_custom = "",
dummy_size = {x = 1, y = 1},
dummy_offset = 0.2,
dummy_mesh = "spawners_mobs_evil_bunny.b3d",
dummy_texture = {"spawners_mobs_evil_bunny.png"},
night_only = true,
sound_custom = "spawners_mobs_bunny"
},
{
name = "uruk_hai",
egg_name_custom = "",
dummy_size = {x = 0.5, y = 0.5},
dummy_offset = 0,
dummy_mesh = "spawners_mobs_character.b3d",
dummy_texture = {"spawners_mobs_uruk_hai.png", "spawners_mobs_trans.png","spawners_mobs_galvornsword.png", "spawners_mobs_trans.png"},
night_only = true,
sound_custom = "spawners_mobs_barbarian_yell2",
env = true
},
{
name = "balrog",
egg_name_custom = "",
dummy_size = {x = 0.2, y = 0.2},
dummy_offset = 0,
dummy_mesh = "spawners_mobs_balrog.b3d",
dummy_texture = {"spawners_mobs_balrog.png"},
night_only = "disable",
sound_custom = "spawners_mobs_howl",
env = true,
boss = true
}
}
end

View File

@ -0,0 +1 @@
This MOD for Minetest let the player craft Mob Spawners. Mobs are spawning randomly in a short intervals. This MOD is giving the option of creating mob farms and grinders.

View File

@ -5,7 +5,7 @@ local bunny_evil_def = {
passive = false,
attack_type = "dogfight",
group_attack = true,
pathfinding = true,
pathfinding = false,
reach = 2,
damage = 3,
hp_min = 25,

View File

@ -6,7 +6,7 @@ local uruk_hai_def = {
passive = false,
hp_min = 40,
hp_max = 65,
pathfinding = true,
pathfinding = false,
attack_type = "dogfight",
group_attack = true,
reach = 2,

1
spawners_mobs/mod.conf Normal file
View File

@ -0,0 +1 @@
name = spawners_mobs

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

View File

@ -1,135 +1,86 @@
local max_obj_per_mapblock = tonumber(minetest.settings:get("max_objects_per_block"))
--
-- * CREATE ALL SPAWNERS NODES *
-- CREATE ALL SPAWNERS NODES
--
function spawners_mobs.create(mob_table, idx)
local mob_name = mob_table.name
local mod_prefix = mob_table.mod_prefix
local size = mob_table.dummy_size
local mesh = mob_table.dummy_mesh
local texture = mob_table.dummy_texture
function spawners_mobs.create(mob_name, mod_prefix, size, offset, mesh, texture, night_only, sound_custom)
--
-- DUMMY INSIDE THE SPAWNER
--
local dummy_definition = {
minetest.register_entity("spawners_mobs:dummy_"..mod_prefix.."_"..mob_name, {
hp_max = 1,
physical = true,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
visual_size = size,
collisionbox = {0,0,0,0,0,0},
mesh = mesh,
textures = texture,
physical = false,
makes_footstep_sound = false,
timer = 0,
automatic_rotate = math.pi * -3,
m_name = "dummy"
}
static_save = false,
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_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active" then
self.object:remove()
end
on_activate = function(self, staticdata, dtime_s)
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
end
minetest.register_entity("spawners_mobs:dummy_"..mod_prefix.."_"..mob_name, dummy_definition)
})
--
-- ACTIVE SPAWNER
-- DEFAULT SPAWNER
--
minetest.register_node("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active", {
description = mod_prefix.."_"..mob_name.." spawner active",
minetest.register_node("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner", {
description = mod_prefix.."_"..mob_name.." spawner",
paramtype = "light",
light_source = 6,
paramtype2 = "glasslikeliquidlevel",
drawtype = "glasslike_framed_optional",
walkable = true,
sounds = default.node_sound_metal_defaults(),
damage_per_second = 4,
sunlight_propagates = true,
tiles = {"spawners_mobs_spawner_16.png"},
is_ground_content = true,
groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1},
drop = "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner",
is_ground_content = false,
groups = {cracky=1,level=2},
stack_max = 1,
light_source = 6,
on_timer = spawners_mobs.on_timer,
on_construct = function(pos)
spawners_mobs.meta_set_str("infotext", mod_prefix.." "..mob_name.." spawner (active)", pos)
-- set meta
local meta = minetest.get_meta(pos)
meta:set_int("idx", idx)
meta:set_int("tick", 0)
meta:set_int("tick_short", 0)
pos.y = pos.y + offset
minetest.add_entity(pos,"spawners_mobs:dummy_"..mod_prefix.."_"..mob_name)
spawners_mobs.set_status(pos, "active")
spawners_mobs.tick_short(pos)
end,
-- add particles
local id_flame = spawners_mobs.add_flame_effects(pos)
local id_smoke = spawners_mobs.add_smoke_effects(pos)
spawners_mobs.meta_set_int("id_flame", id_flame, pos)
spawners_mobs.meta_set_int("id_smoke", id_smoke, pos)
minetest.get_node_timer(pos):start(10)
after_place_node = function(pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
meta:set_string("owner", placer:get_player_name())
end,
on_destruct = function(pos)
-- delete particles
local id_flame = spawners_mobs.meta_get_int("id_flame", pos)
local id_smoke = spawners_mobs.meta_get_int("id_smoke", pos)
if id_flame and id_smoke and id_flame ~= 0 and id_smoke ~= 0 then
minetest.delete_particlespawner(id_flame)
minetest.delete_particlespawner(id_smoke)
end
end,
on_timer = function(pos, elapsed)
local id_flame = spawners_mobs.meta_get_int("id_flame", pos)
local id_smoke = spawners_mobs.meta_get_int("id_smoke", pos)
local player_near = spawners_mobs.check_around_radius(pos)
-- delete particles
if id_flame and id_smoke and id_flame ~= nil and id_smoke ~= nil and id_flame ~= 0 and id_smoke ~= 0 and player_near == false then
minetest.delete_particlespawner(id_flame)
minetest.delete_particlespawner(id_smoke)
spawners_mobs.meta_set_int("id_flame", 0, pos)
spawners_mobs.meta_set_int("id_smoke", 0, pos)
end
-- add particles
if player_near == true then
-- delete particles before adding new ones
if id_flame and id_smoke and id_flame ~= nil and id_smoke ~= nil then
minetest.delete_particlespawner(id_flame)
minetest.delete_particlespawner(id_smoke)
end
id_flame = spawners_mobs.add_flame_effects(pos)
id_smoke = spawners_mobs.add_smoke_effects(pos)
spawners_mobs.meta_set_int("id_flame", id_flame, pos)
spawners_mobs.meta_set_int("id_smoke", id_smoke, pos)
end
minetest.get_node_timer(pos):start(10)
end,
-- delete particles and remove dummy
spawners_mobs.set_status(pos, "waiting")
end
})
--
-- WAITING SPAWNER
--
-- waiting for light - everything is ok but too much light or not enough light
minetest.register_node("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_waiting", {
description = mod_prefix.."_"..mob_name.." spawner waiting",
paramtype = "light",
light_source = 2,
paramtype2 = "glasslikeliquidlevel",
drawtype = "glasslike_framed_optional",
walkable = true,
sounds = default.node_sound_metal_defaults(),
walkable = true,
sunlight_propagates = true,
tiles = {
{
@ -142,178 +93,51 @@ function spawners_mobs.create(mob_name, mod_prefix, size, offset, mesh, texture,
},
}
},
is_ground_content = true,
is_ground_content = false,
groups = {cracky=1,level=2,not_in_creative_inventory=1},
light_source = 4,
drop = "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner",
on_construct = function(pos)
spawners_mobs.meta_set_str("infotext", mod_prefix.." "..mob_name.." spawner (waiting)", pos)
end,
on_timer = spawners_mobs.on_timer
})
--
-- INACTIVE SPAWNER (DEFAULT)
-- RUSTY SPAWNER
--
minetest.register_node("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner", {
description = mod_prefix.."_"..mob_name.." spawner",
minetest.register_node("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_rusty", {
description = mod_prefix.."_"..mob_name.." spawner rusty",
paramtype = "light",
paramtype2 = "glasslikeliquidlevel",
drawtype = "glasslike_framed_optional",
walkable = true,
sounds = default.node_sound_metal_defaults(),
sunlight_propagates = true,
tiles = {"spawners_mobs_spawner_16.png"},
is_ground_content = true,
groups = {cracky=1,level=2},
stack_max = 1,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("status", "default")
meta:set_string("mod_prefix", mod_prefix)
meta:set_string("sound_custom", sound_custom)
meta:set_string("mob_name", mob_name)
local random_pos, waiting = spawners_mobs.check_node_status(pos, mob_name, night_only)
spawners_mobs.meta_set_str("infotext", mod_prefix.." "..mob_name.." spawner (inactive)", pos)
if random_pos then
-- set active node after dummy was removed
minetest.after(2, function()
minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active"})
end)
elseif waiting then
minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_waiting"})
else
-- print("no position and not waiting")
end
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
meta:set_string("owner", placer:get_player_name())
end
})
--
-- OVERHEATED SPAWNER
--
minetest.register_node("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_overheat", {
description = mod_prefix.."_"..mob_name.." spawner overheated",
paramtype = "light",
light_source = 2,
paramtype2 = "glasslikeliquidlevel",
drawtype = "glasslike_framed_optional",
walkable = true,
sounds = default.node_sound_metal_defaults(),
damage_per_second = 4,
sunlight_propagates = true,
tiles = {"spawners_mobs_spawner_16.png^[colorize:#FF000030"},
is_ground_content = true,
groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1},
drop = "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner",
on_construct = function(pos)
spawners_mobs.meta_set_str("infotext", mod_prefix.." "..mob_name.." spawner is overheated - too many items/entities in the area", pos)
minetest.get_node_timer(pos):start(60)
end,
on_timer = function(pos, elapsed)
minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner"})
tiles = {"spawners_mobs_spawner_rusty.png"},
is_ground_content = false,
groups = {cracky=1,level=2,not_in_creative_inventory=1},
drop = "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner"
})
--
-- replacement LBM for pre-nodetimer spawners
--
minetest.register_lbm({
name = "spawners_mobs:start_nodetimer_"..mod_prefix.."_"..mob_name.."_spawner",
nodenames = "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner",
action = function(pos, node)
spawners_mobs.tick_short(pos)
end,
})
--
-- * LBM *
-- COMPATIBILITY
--
-- minetest.register_lbm({
-- name = "spawners_mobs:set_to_active",
-- nodenames = {
-- "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active",
-- "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_overheat",
-- "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_waiting"
-- },
-- run_at_every_load = true,
-- action = function(pos, node)
-- minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner"})
-- end,
-- })
--
-- * ABM *
--
minetest.register_abm({
nodenames = {
"spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner",
"spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active",
"spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_overheat",
"spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_waiting"
},
neighbors = {"air"},
interval = 1,
chance = 1,
-- interval = 10,
-- chance = 10,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
local random_pos, waiting = spawners_mobs.check_node_status(pos, mob_name, night_only)
-- minetest.log("action", "[Mod][Spawners] checking for: "..mob_name.." at "..minetest.pos_to_string(pos))
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_mobs:"..mob_name.."_spawner_overheat" then
minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_overheat"})
end
-- extend the timeout if still too many entities in map block
if node.name == "spawners_mobs:"..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_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active" then
minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active"})
end
-- enough place to spawn more mobs
spawners_mobs.start_spawning(random_pos, 1, "spawners_mobs:"..mob_name, mod_prefix, sound_custom)
elseif waiting then
-- waiting status
if node.name ~= "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_waiting" then
minetest.set_node(pos, {name="spawners_mobs:"..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_mobs:"..mod_prefix.."_"..mob_name.."_spawner" then
minetest.set_node(pos, {name="spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner"})
end
end
end
})
minetest.register_alias("spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner_active", "spawners_mobs:"..mod_prefix.."_"..mob_name.."_spawner")
end
--
-- * INIT 'CREATE' FOR ALL SPAWNERS *
-- INIT 'CREATE' FOR ALL SPAWNERS
--
for i, mob_table in ipairs(spawners_mobs.mob_tables) do
if mob_table then
spawners_mobs.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
spawners_mobs.create(mob_table, i)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B