Browse Source

added 'on_map_load' setting to mobs:spawn function to spawn mob in newly loaded areas of map only

pull/74/head
TenPlus1 3 weeks ago
parent
commit
499d43a9aa
3 changed files with 163 additions and 132 deletions
  1. +158
    -131
      api.lua
  2. +3
    -0
      api.txt
  3. +2
    -1
      readme.MD

+ 158
- 131
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
return
end
end
end

-- spawn above node
pos.y = pos.y + 1
-- 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
-- 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
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
-- 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
return
end

-- mobs cannot spawn in protected areas when enabled
if not spawn_protected
and minetest.is_protected(pos, "") then
-- 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
return
end

-- only spawn a set distance away from player
local objs = minetest.get_objects_inside_radius(
pos, mob_nospawn_range)
-- only spawn a set distance away from player
local objs = minetest.get_objects_inside_radius(pos, mob_nospawn_range)

for n = 1, #objs do
for n = 1, #objs do

if objs[n]:is_player() then
if objs[n]:is_player() then
--print("--- player too close", name)
return
end
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
-- 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
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
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
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)
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
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}
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
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
--print("--- not enough space to spawn", name)
return
end
end
end
return
end
end
end
end

-- spawn mob 1/2 node above ground
pos.y = pos.y + 0.5
-- 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
-- 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

if width_z % 2 == 0 then
pos.z = pos.z + 0.5
end

local mob = minetest.add_entity(pos, name)
-- are we registering an abm or lbm?
if map_load == true then

-- print("[mobs] Spawned " .. name .. " at "
-- .. minetest.pos_to_string(pos) .. " on "
-- .. node.name .. " near " .. neighbors[1])
minetest.register_lbm({
name = name .. "_spawning",
label = name .. " spawning",
nodenames = nodes,
run_at_every_load = false,

if on_spawn then
action = function(pos, node)
spawn_action(pos, node)
end
})

local ent = mob:get_luaentity()
else

on_spawn(ent, pos)
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
end


@@ -3922,7 +3947,7 @@ function mobs:register_spawn(name, nodes, max_light, min_light, chance,
end


-- 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
- 0
api.txt 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.


+ 2
- 1
readme.MD 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


Loading…
Cancel
Save