mirror of
https://codeberg.org/tenplus1/mobs_redo.git
synced 2024-12-24 01:30:22 +01:00
added 'on_map_load' setting to mobs:spawn function to spawn mob in newly loaded areas of map only
This commit is contained in:
parent
39002cf4e7
commit
499d43a9aa
348
api.lua
348
api.lua
@ -9,7 +9,7 @@ local use_cmi = minetest.global_exists("cmi")
|
||||
|
||||
mobs = {
|
||||
mod = "redo",
|
||||
version = "20200825",
|
||||
version = "20200904",
|
||||
intllib = S,
|
||||
invis = minetest.global_exists("invisibility") and invisibility or {}
|
||||
}
|
||||
@ -3699,8 +3699,8 @@ function mobs:spawn_abm_check(pos, node, name)
|
||||
end
|
||||
|
||||
|
||||
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
||||
interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
|
||||
chance, aoc, min_height, max_height, day_toggle, on_spawn, map_load)
|
||||
|
||||
-- Do mobs spawn at all?
|
||||
if not mobs_spawn or not mobs.spawning_mobs[name] then
|
||||
@ -3730,186 +3730,211 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
||||
|
||||
mobs.spawning_mobs[name].aoc = aoc
|
||||
|
||||
minetest.register_abm({
|
||||
local spawn_action = function(pos, node, active_object_count,
|
||||
active_object_count_wider)
|
||||
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
neighbors = neighbors,
|
||||
interval = interval,
|
||||
chance = max(1, (chance * mob_chance_multiplier)),
|
||||
catch_up = false,
|
||||
-- use instead of abm's chance setting when using lbm
|
||||
if map_load and random(max(1, (chance * mob_chance_multiplier))) > 1 then
|
||||
return
|
||||
end
|
||||
|
||||
action = function(pos, node, active_object_count,
|
||||
active_object_count_wider)
|
||||
-- use instead of abm's neighbor setting when using lbm
|
||||
if map_load and not minetest.find_node_near(pos, 1, neighbors) then
|
||||
--print("--- lbm neighbors not found")
|
||||
return
|
||||
end
|
||||
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[name]
|
||||
or not minetest.registered_entities[name] then
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[name]
|
||||
or not minetest.registered_entities[name] then
|
||||
--print("--- mob doesn't exist", name)
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- are we over active mob limit
|
||||
if active_limit > 0 and active_mobs >= active_limit then
|
||||
-- are we over active mob limit
|
||||
if active_limit > 0 and active_mobs >= active_limit then
|
||||
--print("--- active mob limit reached", active_mobs, active_limit)
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- additional custom checks for spawning mob
|
||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
||||
return
|
||||
end
|
||||
-- additional custom checks for spawning mob
|
||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
||||
return
|
||||
end
|
||||
|
||||
-- do not spawn if too many entities in area
|
||||
if active_object_count_wider >= max_per_block then
|
||||
-- do not spawn if too many entities in area
|
||||
if active_object_count_wider
|
||||
and active_object_count_wider >= max_per_block then
|
||||
--print("--- too many entities in area", active_object_count_wider)
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- get total number of this mob in area
|
||||
local num_mob, is_pla = count_mobs(pos, name)
|
||||
-- get total number of this mob in area
|
||||
local num_mob, is_pla = count_mobs(pos, name)
|
||||
|
||||
if not is_pla then
|
||||
if not is_pla then
|
||||
--print("--- no players within active area, will not spawn " .. name)
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if num_mob >= aoc then
|
||||
if num_mob >= aoc then
|
||||
--print("--- too many " .. name .. " in area", num_mob .. "/" .. aoc)
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- if toggle set to nil then ignore day/night check
|
||||
if day_toggle ~= nil then
|
||||
if day_toggle ~= nil then
|
||||
|
||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
||||
|
||||
if tod > 4500 and tod < 19500 then
|
||||
-- daylight, but mob wants night
|
||||
if day_toggle == false then
|
||||
if tod > 4500 and tod < 19500 then
|
||||
-- daylight, but mob wants night
|
||||
if day_toggle == false then
|
||||
--print("--- mob needs night", name)
|
||||
return
|
||||
end
|
||||
else
|
||||
-- night time but mob wants day
|
||||
if day_toggle == true then
|
||||
return
|
||||
end
|
||||
else
|
||||
-- night time but mob wants day
|
||||
if day_toggle == true then
|
||||
--print("--- mob needs day", name)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn above node
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- are we spawning within height limits?
|
||||
if pos.y > max_height
|
||||
or pos.y < min_height then
|
||||
--print("--- height limits not met", name, pos.y)
|
||||
return
|
||||
end
|
||||
|
||||
-- are light levels ok?
|
||||
local light = minetest.get_node_light(pos)
|
||||
if not light
|
||||
or light > max_light
|
||||
or light < min_light then
|
||||
--print("--- light limits not met", name, light)
|
||||
return
|
||||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
--print("--- inside protected area", name)
|
||||
return
|
||||
end
|
||||
|
||||
-- only spawn a set distance away from player
|
||||
local objs = minetest.get_objects_inside_radius(
|
||||
pos, mob_nospawn_range)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
--print("--- player too close", name)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- do we have enough space to spawn mob? (thanks wuzzy)
|
||||
local ent = minetest.registered_entities[name]
|
||||
local width_x = max(1,
|
||||
ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
||||
local min_x, max_x
|
||||
|
||||
if width_x % 2 == 0 then
|
||||
max_x = floor(width_x / 2)
|
||||
min_x = -(max_x - 1)
|
||||
else
|
||||
max_x = floor(width_x / 2)
|
||||
min_x = -max_x
|
||||
end
|
||||
|
||||
local width_z = max(1,
|
||||
ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
||||
local min_z, max_z
|
||||
|
||||
if width_z % 2 == 0 then
|
||||
max_z = floor(width_z / 2)
|
||||
min_z = -(max_z - 1)
|
||||
else
|
||||
max_z = floor(width_z / 2)
|
||||
min_z = -max_z
|
||||
end
|
||||
|
||||
local max_y = max(0,
|
||||
ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
||||
|
||||
for y = 0, max_y do
|
||||
for x = min_x, max_x do
|
||||
for z = min_z, max_z do
|
||||
|
||||
local pos2 = {
|
||||
x = pos.x + x,
|
||||
y = pos.y + y,
|
||||
z = pos.z + z}
|
||||
|
||||
if minetest.registered_nodes[
|
||||
node_ok(pos2).name].walkable == true then
|
||||
--print("--- not enough space to spawn", name)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn mob 1/2 node above ground
|
||||
pos.y = pos.y + 0.5
|
||||
|
||||
-- tweak X/Z spawn pos
|
||||
if width_x % 2 == 0 then
|
||||
pos.x = pos.x + 0.5
|
||||
end
|
||||
|
||||
if width_z % 2 == 0 then
|
||||
pos.z = pos.z + 0.5
|
||||
end
|
||||
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
|
||||
-- print("[mobs] Spawned " .. name .. " at "
|
||||
-- .. minetest.pos_to_string(pos) .. " on "
|
||||
-- .. node.name .. " near " .. neighbors[1])
|
||||
|
||||
if on_spawn then
|
||||
|
||||
local ent = mob:get_luaentity()
|
||||
|
||||
on_spawn(ent, pos)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
-- spawn above node
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- are we spawning within height limits?
|
||||
if pos.y > max_height
|
||||
or pos.y < min_height then
|
||||
--print("--- height limits not met", name, pos.y)
|
||||
return
|
||||
end
|
||||
|
||||
-- are light levels ok?
|
||||
local light = minetest.get_node_light(pos)
|
||||
if not light
|
||||
or light > max_light
|
||||
or light < min_light then
|
||||
--print("--- light limits not met", name, light)
|
||||
return
|
||||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
--print("--- inside protected area", name)
|
||||
return
|
||||
end
|
||||
|
||||
-- only spawn a set distance away from player
|
||||
local objs = minetest.get_objects_inside_radius(pos, mob_nospawn_range)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
--print("--- player too close", name)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- do we have enough space to spawn mob? (thanks wuzzy)
|
||||
local ent = minetest.registered_entities[name]
|
||||
local width_x = max(1, ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
||||
local min_x, max_x
|
||||
|
||||
if width_x % 2 == 0 then
|
||||
max_x = floor(width_x / 2)
|
||||
min_x = -(max_x - 1)
|
||||
else
|
||||
max_x = floor(width_x / 2)
|
||||
min_x = -max_x
|
||||
end
|
||||
|
||||
local width_z = max(1, ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
||||
local min_z, max_z
|
||||
|
||||
if width_z % 2 == 0 then
|
||||
max_z = floor(width_z / 2)
|
||||
min_z = -(max_z - 1)
|
||||
else
|
||||
max_z = floor(width_z / 2)
|
||||
min_z = -max_z
|
||||
end
|
||||
|
||||
local max_y = max(0, ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
||||
|
||||
for y = 0, max_y do
|
||||
for x = min_x, max_x do
|
||||
for z = min_z, max_z do
|
||||
|
||||
local pos2 = {
|
||||
x = pos.x + x,
|
||||
y = pos.y + y,
|
||||
z = pos.z + z}
|
||||
|
||||
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
|
||||
--print("--- not enough space to spawn", name)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn mob 1/2 node above ground
|
||||
pos.y = pos.y + 0.5
|
||||
|
||||
-- tweak X/Z spawn pos
|
||||
if width_x % 2 == 0 then
|
||||
pos.x = pos.x + 0.5
|
||||
end
|
||||
|
||||
if width_z % 2 == 0 then
|
||||
pos.z = pos.z + 0.5
|
||||
end
|
||||
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
|
||||
print("[mobs] Spawned " .. name .. " at "
|
||||
.. minetest.pos_to_string(pos) .. " on "
|
||||
.. node.name .. " near " .. neighbors[1])
|
||||
|
||||
if on_spawn then
|
||||
on_spawn(mob:get_luaentity(), pos)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- are we registering an abm or lbm?
|
||||
if map_load == true then
|
||||
|
||||
minetest.register_lbm({
|
||||
name = name .. "_spawning",
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
run_at_every_load = false,
|
||||
|
||||
action = function(pos, node)
|
||||
spawn_action(pos, node)
|
||||
end
|
||||
})
|
||||
|
||||
else
|
||||
|
||||
minetest.register_abm({
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
neighbors = neighbors,
|
||||
interval = interval,
|
||||
chance = max(1, (chance * mob_chance_multiplier)),
|
||||
catch_up = false,
|
||||
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
spawn_action(pos, node, active_object_count, active_object_count_wider)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -3922,7 +3947,7 @@ function mobs:register_spawn(name, nodes, max_light, min_light, chance,
|
||||
end
|
||||
|
||||
|
||||
-- MarkBu's spawn function
|
||||
-- MarkBu's spawn function (USE this one please)
|
||||
function mobs:spawn(def)
|
||||
|
||||
mobs:spawn_specific(
|
||||
@ -3937,7 +3962,8 @@ function mobs:spawn(def)
|
||||
def.min_height or -31000,
|
||||
def.max_height or 31000,
|
||||
def.day_toggle,
|
||||
def.on_spawn)
|
||||
def.on_spawn,
|
||||
def.on_map_load)
|
||||
end
|
||||
|
||||
|
||||
|
3
api.txt
3
api.txt
@ -383,6 +383,9 @@ default setting and can be omitted:
|
||||
anytime
|
||||
'on_spawn' is a custom function which runs after mob has spawned
|
||||
and gives self and pos values.
|
||||
'on_map_load' when true mobs will have a chance of spawning only
|
||||
when new areas of map are loaded, interval will not be
|
||||
used.
|
||||
|
||||
The older spawn functions are still active and working but have no defaults like
|
||||
the mobs:spawn, so it is recommended to use the above instead.
|
||||
|
@ -23,7 +23,8 @@ Lucky Blocks: 9
|
||||
|
||||
|
||||
Changelog:
|
||||
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game
|
||||
- 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded.
|
||||
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game,
|
||||
(default is 0 for unlimited), removed {immortal} from mob armor, fluid viscocity slows mobs
|
||||
- 1.51 - Added some node checks for dangerous nodes, jumping and falling tweaks, spawn area check (thx for idea wuzzy), re-enabled mob suffocation, add 'mob_nospawn_range' setting
|
||||
- 1.50 - Added new line_of_sight function that uses raycasting if mt5.0 is found, (thanks Astrobe), dont spawn mobs if world anchor nearby (technic or simple_anchor mods), chinese local added
|
||||
|
Loading…
Reference in New Issue
Block a user