From ae32ce4a0a41dde8d07d181b3e39a748e9a6ea31 Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 19:26:43 +0100 Subject: [PATCH 1/5] Split hostile and non-hostile mob caps --- mods/ENTITIES/mcl_mobs/spawning.lua | 105 ++++++++++++++++++---------- settingtypes.txt | 8 ++- 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index adff1a918..4a9f6d736 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -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) diff --git a/settingtypes.txt b/settingtypes.txt index 00235e79d..fde9582d8 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -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 From 4d3e8e25e51527a09dc8b3a59f16340cf5a0908b Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 20:06:03 +0100 Subject: [PATCH 2/5] Add water_ambient cap --- mods/ENTITIES/mobs_mc/cod.lua | 2 +- mods/ENTITIES/mobs_mc/salmon.lua | 2 +- mods/ENTITIES/mobs_mc/tropical_fish.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/cod.lua b/mods/ENTITIES/mobs_mc/cod.lua index 9e8b62269..656b2c14c 100644 --- a/mods/ENTITIES/mobs_mc/cod.lua +++ b/mods/ENTITIES/mobs_mc/cod.lua @@ -31,7 +31,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) local cod = { type = "animal", - spawn_class = "water", + spawn_class = "water_ambient", can_despawn = true, passive = true, hp_min = 3, diff --git a/mods/ENTITIES/mobs_mc/salmon.lua b/mods/ENTITIES/mobs_mc/salmon.lua index 19c935389..f8e0c4e02 100644 --- a/mods/ENTITIES/mobs_mc/salmon.lua +++ b/mods/ENTITIES/mobs_mc/salmon.lua @@ -11,7 +11,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) local salmon = { type = "animal", - spawn_class = "water", + spawn_class = "water_ambient", can_despawn = true, passive = true, hp_min = 3, diff --git a/mods/ENTITIES/mobs_mc/tropical_fish.lua b/mods/ENTITIES/mobs_mc/tropical_fish.lua index 702c692b8..79b32bb8b 100644 --- a/mods/ENTITIES/mobs_mc/tropical_fish.lua +++ b/mods/ENTITIES/mobs_mc/tropical_fish.lua @@ -59,7 +59,7 @@ end local tropical_fish = { type = "animal", - spawn_class = "water", + spawn_class = "water_ambient", can_despawn = true, passive = true, hp_min = 3, From afb4540408cfcbf88cae289cb22f8020af61b95e Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 20:08:44 +0100 Subject: [PATCH 3/5] Clean up --- mods/ENTITIES/mcl_mobs/spawning.lua | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 4a9f6d736..10379a6fa 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -64,7 +64,7 @@ local mob_cap = { passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 13, ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, 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 + water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, 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, @@ -361,7 +361,7 @@ local function count_mobs_total_cap(mob_type) end num = num + 1 else - mcl_log("l.nametag", l.name) + mcl_log("l.name", l.name) mcl_log("l.nametag", l.nametag) end @@ -871,6 +871,9 @@ if mobs_spawn then local cap_space_wide = math.max(type_cap - mob_total_wide, 0) + mcl_log("mob_type", mob_type) + mcl_log("cap_space_wide", cap_space_wide) + local cap_space_available = 0 if mob_type == "hostile" then mcl_log("cap_space_global", cap_space_hostile) @@ -879,10 +882,6 @@ if mobs_spawn then 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 @@ -891,11 +890,10 @@ if mobs_spawn then 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("cap_space_close", cap_space_close) + mcl_log("cap_space_available", cap_space_available) if false and mob_type == "water" then mcl_log("mob_type: " .. mob_type .. " and pos: " .. minetest.pos_to_string(pos)) @@ -986,9 +984,7 @@ 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_spawn_class = mob_def_ent.spawn_class - --mcl_log("mob_spawn_class: " .. mob_spawn_class) 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) From 812269264bf4dbb0244ddf4ed3c107b8ffb655bb Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 20:43:15 +0100 Subject: [PATCH 4/5] Add in caps for underground water and axolotl --- mods/ENTITIES/mcl_mobs/spawning.lua | 2 ++ mods/ENTITIES/mobs_mc/axolotl.lua | 2 +- mods/ENTITIES/mobs_mc/glow_squid.lua | 2 +- settingtypes.txt | 9 +++++++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 10379a6fa..f1f00a6a8 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -65,6 +65,8 @@ local mob_cap = { ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8, water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, + water_underground = tonumber(minetest.settings:get("mcl_mob_cap_water_underground")) or 5, + axolotl = tonumber(minetest.settings:get("mcl_mob_cap_axolotl")) or 2, -- TODO should be 5 when lush caves added 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, diff --git a/mods/ENTITIES/mobs_mc/axolotl.lua b/mods/ENTITIES/mobs_mc/axolotl.lua index 124f6bd3a..087f201c7 100644 --- a/mods/ENTITIES/mobs_mc/axolotl.lua +++ b/mods/ENTITIES/mobs_mc/axolotl.lua @@ -2,7 +2,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) local axolotl = { type = "animal", - spawn_class = "water", + spawn_class = "axolotl", can_despawn = true, passive = false, hp_min = 14, diff --git a/mods/ENTITIES/mobs_mc/glow_squid.lua b/mods/ENTITIES/mobs_mc/glow_squid.lua index 5975671b1..2d3f19270 100644 --- a/mods/ENTITIES/mobs_mc/glow_squid.lua +++ b/mods/ENTITIES/mobs_mc/glow_squid.lua @@ -31,7 +31,7 @@ end mcl_mobs.register_mob("mobs_mc:glow_squid", { type = "animal", - spawn_class = "water", + spawn_class = "water_underground", can_despawn = true, passive = true, hp_min = 10, diff --git a/settingtypes.txt b/settingtypes.txt index fde9582d8..eb91b8414 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -151,6 +151,15 @@ mcl_mob_cap_animal (Mob cap animals) int 13 0 1024 #Maximum amount of water mobs that will spawn near a player (default:8) mcl_mob_cap_water (Mob cap water) int 8 0 1024 +#Maximum amount of ambient water mobs that will spawn near a player (default:20) +mcl_mob_cap_water_ambient (Mob cap ambient water) int 20 0 1024 + +#Maximum amount of underground water mobs that will spawn near a player (default:5) +mcl_mob_cap_water_underground (Mob cap underground water) int 5 0 1024 + +#Maximum amount of axolotl mobs that will spawn near a player (default:5) +mcl_mob_cap_axolotl (Mob cap axolotl) int 5 0 1024 + #Maximum amount of ambient mobs that will spawn near a player (default:15) mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024 From c65f8c9e5161a8494d6d3b575e44362dd7570fcd Mon Sep 17 00:00:00 2001 From: ancientmarinerdev Date: Mon, 29 May 2023 21:43:27 +0100 Subject: [PATCH 5/5] Improved early game spawn balance --- mods/ENTITIES/mcl_mobs/spawning.lua | 4 ++-- settingtypes.txt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index f1f00a6a8..c677aeacf 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -61,7 +61,7 @@ local SPAWN_MAPGEN_LIMIT = mcl_vars.mapgen_limit - 150 local mob_cap = { hostile = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70, - passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 13, + passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10, ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15, water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8, water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, @@ -73,7 +73,7 @@ local mob_cap = { total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500, } -local peaceful_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_percentage_spawned")) or 35 +local peaceful_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_percentage_spawned")) or 30 local peaceful_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_group_percentage_spawned")) or 15 local hostile_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_hostile_group_percentage_spawned")) or 20 diff --git a/settingtypes.txt b/settingtypes.txt index eb91b8414..c5d5d32c1 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -121,8 +121,8 @@ mobs_griefing (Mobs change blocks) bool true # If enabled, mobs won't damage particles when they got hurt. mobs_disable_blood (Disable mob damage particles) bool false -#Percentage of peaceful spawn attempts that succeed (default:35) -mcl_mob_peaceful_percentage_spawned (Peaceful percentage success) int 35 0 100 +#Percentage of peaceful spawn attempts that succeed (default:30) +mcl_mob_peaceful_percentage_spawned (Peaceful percentage success) int 30 0 100 #Percentage of peaceful spawn attempts that are group spawns (default:15) mcl_mob_peaceful_group_percentage_spawned (Peaceful group percentage) int 15 0 100 @@ -145,8 +145,8 @@ mcl_mob_cap_player (Mob cap per player) int 75 0 2048 #Maximum amount of monsters that will spawn near a player (default:70) mcl_mob_cap_monster (Mob cap monsters) int 70 0 2048 -#Maximum amount of animals that will spawn near a player (default:13) -mcl_mob_cap_animal (Mob cap animals) int 13 0 1024 +#Maximum amount of animals that will spawn near a player (default:10) +mcl_mob_cap_animal (Mob cap animals) int 10 0 1024 #Maximum amount of water mobs that will spawn near a player (default:8) mcl_mob_cap_water (Mob cap water) int 8 0 1024