Split hostile and non-hostile mob caps
parent
4c3d726882
commit
ae32ce4a0a
|
@ -27,8 +27,11 @@ local table_remove = table.remove
|
|||
local pairs = pairs
|
||||
|
||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_spawning", false)
|
||||
local function mcl_log (message)
|
||||
local function mcl_log (message, property)
|
||||
if LOGGING_ON then
|
||||
if property then
|
||||
message = message .. ": " .. dump(property)
|
||||
end
|
||||
mcl_util.mcl_log (message, "[Mobs spawn]", true)
|
||||
end
|
||||
end
|
||||
|
@ -52,7 +55,7 @@ local MOB_CAP_INNER_RADIUS = 32
|
|||
local aoc_range = 136
|
||||
|
||||
local MISSING_CAP_DEFAULT = 15
|
||||
local MOBS_CAP_CLOSE = 5
|
||||
local MOBS_CAP_CLOSE = 10
|
||||
|
||||
local SPAWN_MAPGEN_LIMIT = mcl_vars.mapgen_limit - 150
|
||||
|
||||
|
@ -63,6 +66,8 @@ local mob_cap = {
|
|||
water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8,
|
||||
water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, --currently unused
|
||||
player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75,
|
||||
global_hostile = tonumber(minetest.settings:get("mcl_mob_cap_hostile")) or 300,
|
||||
global_non_hostile = tonumber(minetest.settings:get("mcl_mob_cap_non_hostile")) or 300,
|
||||
total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500,
|
||||
}
|
||||
|
||||
|
@ -340,15 +345,32 @@ local function count_mobs_all(categorise_by, pos)
|
|||
end
|
||||
|
||||
local function count_mobs_total_cap(mob_type)
|
||||
local total = 0
|
||||
local num = 0
|
||||
local hostile = 0
|
||||
local non_hostile = 0
|
||||
for _,l in pairs(minetest.luaentities) do
|
||||
if l.is_mob then
|
||||
if ( mob_type == nil or l.type == mob_type ) and l.can_despawn and not l.nametag then
|
||||
total = total + 1
|
||||
local nametagged = l.nametag and l.nametag ~= ""
|
||||
if ( mob_type == nil or l.type == mob_type ) and not nametagged then
|
||||
if l.spawn_class == "hostile" then
|
||||
hostile = hostile + 1
|
||||
else
|
||||
non_hostile = non_hostile + 1
|
||||
end
|
||||
num = num + 1
|
||||
else
|
||||
mcl_log("l.nametag", l.name)
|
||||
mcl_log("l.nametag", l.nametag)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
return num
|
||||
mcl_log("Total mobs", total)
|
||||
mcl_log("hostile", hostile)
|
||||
mcl_log("non_hostile", non_hostile)
|
||||
return num, non_hostile, hostile
|
||||
end
|
||||
|
||||
local function output_mob_stats(mob_counts, total_mobs, chat_display)
|
||||
|
@ -704,13 +726,13 @@ local function spawn_check(pos, spawn_def)
|
|||
--mcl_log("Level 3 spawn check passed")
|
||||
return true
|
||||
else
|
||||
mcl_log("Spawn check level 3 failed")
|
||||
--mcl_log("Spawn check level 3 failed")
|
||||
end
|
||||
else
|
||||
mcl_log("Spawn check level 2 failed")
|
||||
--mcl_log("Spawn check level 2 failed")
|
||||
end
|
||||
else
|
||||
mcl_log("Spawn check level 1 failed")
|
||||
--mcl_log("Spawn check level 1 failed")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
@ -831,7 +853,7 @@ if mobs_spawn then
|
|||
-- Get pos to spawn, x and z are randomised, y is range
|
||||
|
||||
|
||||
local function mob_cap_space (pos, mob_type, mob_counts_close, mob_counts_wide)
|
||||
local function mob_cap_space (pos, mob_type, mob_counts_close, mob_counts_wide, cap_space_hostile, cap_space_non_hostile)
|
||||
|
||||
-- Some mob examples
|
||||
--type = "monster", spawn_class = "hostile",
|
||||
|
@ -847,10 +869,20 @@ if mobs_spawn then
|
|||
mob_total_wide = 0
|
||||
end
|
||||
|
||||
local cap_space_wide = type_cap - mob_total_wide
|
||||
if cap_space_wide < 1 then
|
||||
cap_space_wide = 0
|
||||
local cap_space_wide = math.max(type_cap - mob_total_wide, 0)
|
||||
|
||||
local cap_space_available = 0
|
||||
if mob_type == "hostile" then
|
||||
mcl_log("cap_space_global", cap_space_hostile)
|
||||
cap_space_available = math.min(cap_space_hostile, cap_space_wide)
|
||||
else
|
||||
mcl_log("cap_space_global", cap_space_non_hostile)
|
||||
cap_space_available = math.min(cap_space_non_hostile, cap_space_wide)
|
||||
end
|
||||
mcl_log("mob_type", mob_type)
|
||||
mcl_log("cap_space_wide", cap_space_wide)
|
||||
--mcl_log("cap_space_available", cap_space_available)
|
||||
|
||||
|
||||
local mob_total_close = mob_counts_close[mob_type]
|
||||
if not mob_total_close then
|
||||
|
@ -858,12 +890,12 @@ if mobs_spawn then
|
|||
mob_total_close = 0
|
||||
end
|
||||
|
||||
local cap_space_close = close_zone_cap - mob_total_close
|
||||
if cap_space_close < 1 then
|
||||
cap_space_close = 0
|
||||
end
|
||||
local cap_space_close = math.max(close_zone_cap - mob_total_close, 0)
|
||||
mcl_log("cap_space_close", cap_space_close)
|
||||
|
||||
cap_space_available = math.min(cap_space_available, cap_space_close)
|
||||
mcl_log("cap_space_available", cap_space_available)
|
||||
|
||||
--mcl_log("spawn_class: " .. spawn_class)
|
||||
|
||||
if false and mob_type == "water" then
|
||||
mcl_log("mob_type: " .. mob_type .. " and pos: " .. minetest.pos_to_string(pos))
|
||||
|
@ -873,7 +905,7 @@ if mobs_spawn then
|
|||
mcl_log("cap_space_close: " .. cap_space_close)
|
||||
end
|
||||
|
||||
return cap_space_wide, cap_space_close
|
||||
return cap_space_available
|
||||
end
|
||||
|
||||
local function find_spawning_position(pos, max_times)
|
||||
|
@ -884,7 +916,7 @@ if mobs_spawn then
|
|||
|
||||
local y_min, y_max = decypher_limits(pos.y)
|
||||
|
||||
mcl_log("mapgen_limit: " .. SPAWN_MAPGEN_LIMIT)
|
||||
--mcl_log("mapgen_limit: " .. SPAWN_MAPGEN_LIMIT)
|
||||
local i = 0
|
||||
repeat
|
||||
local goal_pos = get_next_mob_spawn_pos(pos)
|
||||
|
@ -916,7 +948,7 @@ if mobs_spawn then
|
|||
return spawning_position
|
||||
end
|
||||
|
||||
local function spawn_a_mob(pos)
|
||||
local function spawn_a_mob(pos, cap_space_hostile, cap_space_non_hostile)
|
||||
--create a disconnected clone of the spawn dictionary, prevents memory leak
|
||||
local mob_library_worker_table = table_copy(spawn_dictionary)
|
||||
|
||||
|
@ -954,22 +986,20 @@ if mobs_spawn then
|
|||
if mob_def and mob_def.name and minetest.registered_entities[mob_def.name] then
|
||||
|
||||
local mob_def_ent = minetest.registered_entities[mob_def.name]
|
||||
--local mob_type = mob_def_ent.type
|
||||
local mob_spawn_class = mob_def_ent.spawn_class
|
||||
|
||||
local mob_spawn_class = mob_def_ent.spawn_class
|
||||
--mcl_log("mob_spawn_class: " .. mob_spawn_class)
|
||||
|
||||
local cap_space_wide, cap_space_close = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide)
|
||||
local cap_space_available = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide, cap_space_hostile, cap_space_non_hostile)
|
||||
|
||||
|
||||
if cap_space_close > 0 and cap_space_wide > 0 then
|
||||
if cap_space_available > 0 then
|
||||
--mcl_log("Cap space available")
|
||||
|
||||
-- Spawn caps for animals and water creatures fill up rapidly. Need to throttle this somewhat
|
||||
-- for performance and for early game challenge. We don't want to reduce hostiles though.
|
||||
local spawn_hostile = (mob_spawn_class == "hostile")
|
||||
local spawn_passive = (mob_spawn_class ~= "hostile") and math.random(100) < peaceful_percentage_spawned
|
||||
-- or not hostile
|
||||
|
||||
--mcl_log("Spawn_passive: " .. tostring(spawn_passive))
|
||||
--mcl_log("Spawn_hostile: " .. tostring(spawn_hostile))
|
||||
|
||||
|
@ -1000,13 +1030,10 @@ if mobs_spawn then
|
|||
local group_min = mob_def_ent.spawn_in_group_min or 1
|
||||
if not group_min then group_min = 1 end
|
||||
|
||||
local amount_to_spawn = math.random(group_min,spawn_in_group)
|
||||
|
||||
if amount_to_spawn > cap_space_wide then
|
||||
mcl_log("Spawning quantity: " .. amount_to_spawn)
|
||||
mcl_log("Throttle amount to cap space: " .. cap_space_wide)
|
||||
amount_to_spawn = cap_space_wide
|
||||
end
|
||||
local amount_to_spawn = math.random(group_min, spawn_in_group)
|
||||
mcl_log("Spawning quantity: " .. amount_to_spawn)
|
||||
amount_to_spawn = math.min(amount_to_spawn, cap_space_available)
|
||||
mcl_log("throttled spawning quantity: " .. amount_to_spawn)
|
||||
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_mobs] A group of " ..amount_to_spawn .. " " .. mob_def.name .. " mob spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1))
|
||||
|
@ -1021,7 +1048,7 @@ if mobs_spawn then
|
|||
|
||||
if spawned then
|
||||
--mcl_log("We have spawned")
|
||||
mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("type", pos)
|
||||
mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("spawn_class", pos)
|
||||
local new_spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES_SUCCESS_RESPIN)
|
||||
if new_spawning_position then
|
||||
mcl_log("Setting new spawning position")
|
||||
|
@ -1034,7 +1061,7 @@ if mobs_spawn then
|
|||
--mcl_log("Spawn check failed")
|
||||
end
|
||||
else
|
||||
mcl_log("Cap space full")
|
||||
--mcl_log("Cap space full")
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1054,7 +1081,13 @@ if mobs_spawn then
|
|||
timer = 0
|
||||
|
||||
local players = get_connected_players()
|
||||
local total_mobs = count_mobs_total_cap()
|
||||
local total_mobs, total_non_hostile, total_hostile = count_mobs_total_cap()
|
||||
|
||||
local cap_space_hostile = math.max(mob_cap.global_hostile - total_hostile, 0)
|
||||
local cap_space_non_hostile = math.max(mob_cap.global_non_hostile - total_non_hostile, 0)
|
||||
mcl_log("global cap_space_hostile", cap_space_hostile)
|
||||
mcl_log("global cap_space_non_hostile", cap_space_non_hostile)
|
||||
|
||||
if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then
|
||||
minetest.log("action","[mcl_mobs] global mob cap reached. no cycle spawning.")
|
||||
return
|
||||
|
@ -1065,7 +1098,7 @@ if mobs_spawn then
|
|||
local dimension = mcl_worlds.pos_to_dimension(pos)
|
||||
-- ignore void and unloaded area
|
||||
if dimension ~= "void" and dimension ~= "default" then
|
||||
spawn_a_mob(pos)
|
||||
spawn_a_mob(pos, cap_space_hostile, cap_space_non_hostile)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -130,9 +130,15 @@ mcl_mob_peaceful_group_percentage_spawned (Peaceful group percentage) int 15 0 1
|
|||
#Percentage of hostile spawn attempts that are group spawns (default:20)
|
||||
mcl_mob_hostile_group_percentage_spawned (Hostile group percentage) int 20 0 100
|
||||
|
||||
#Maximum amount mobs (default:500)
|
||||
#Maximum amount of mobs (default:500)
|
||||
mcl_mob_cap_total (Global mob cap) int 500 0 2048
|
||||
|
||||
#Maximum amount of hostile mobs (default:300)
|
||||
mcl_mob_cap_hostile (Global hostile mob cap) int 300 0 2048
|
||||
|
||||
#Maximum amount of non-hostile mobs (default:300)
|
||||
mcl_mob_cap_non_hostile (Global non-hostile mob cap) int 300 0 2048
|
||||
|
||||
#Maximum amount of mobs per player (default:75)
|
||||
mcl_mob_cap_player (Mob cap per player) int 75 0 2048
|
||||
|
||||
|
|
Loading…
Reference in New Issue