1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2024-11-13 05:50:17 +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:
TenPlus1 2020-09-04 13:59:14 +01:00
parent 39002cf4e7
commit 499d43a9aa
3 changed files with 192 additions and 162 deletions

348
api.lua
View File

@ -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

View File

@ -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.

View File

@ -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