Spawning: fix random weighted choice
This commit is contained in:
parent
59c5d54cbe
commit
402e4e7b79
40
mods/ENTITIES/mcl_mobs/spawning.lua
Normal file → Executable file
40
mods/ENTITIES/mcl_mobs/spawning.lua
Normal file → Executable file
@ -613,8 +613,8 @@ function mcl_mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_
|
|||||||
spawn_dictionary[key]["check_position"] = check_position
|
spawn_dictionary[key]["check_position"] = check_position
|
||||||
|
|
||||||
summary_chance = summary_chance + chance
|
summary_chance = summary_chance + chance
|
||||||
end
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
local two_pi = 2 * math.pi
|
local two_pi = 2 * math.pi
|
||||||
local function get_next_mob_spawn_pos(pos)
|
local function get_next_mob_spawn_pos(pos)
|
||||||
@ -973,9 +973,21 @@ if mobs_spawn then
|
|||||||
return spawning_position
|
return spawning_position
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local cumulative_chance = nil
|
||||||
|
local mob_library_worker_table = nil
|
||||||
|
local function initialize_spawn_data()
|
||||||
|
if not mob_library_worker_table then
|
||||||
|
mob_library_worker_table = table_copy(spawn_dictionary)
|
||||||
|
end
|
||||||
|
if not cumulative_chance then
|
||||||
|
cumulative_chance = 0
|
||||||
|
for k, v in pairs(mob_library_worker_table) do
|
||||||
|
cumulative_chance = cumulative_chance + v.chance
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function spawn_a_mob(pos, cap_space_hostile, cap_space_non_hostile)
|
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)
|
|
||||||
|
|
||||||
local spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES)
|
local spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES)
|
||||||
if not spawning_position then
|
if not spawning_position then
|
||||||
@ -992,18 +1004,25 @@ if mobs_spawn then
|
|||||||
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||||
local noise = perlin_noise:get_3d(spawning_position)
|
local noise = perlin_noise:get_3d(spawning_position)
|
||||||
local current_summary_chance = summary_chance
|
local current_summary_chance = summary_chance
|
||||||
|
local spawn_loop_counter = #mob_library_worker_table
|
||||||
|
|
||||||
table.shuffle(mob_library_worker_table)
|
while spawn_loop_counter > 0 do
|
||||||
|
table.shuffle(mob_library_worker_table)
|
||||||
while #mob_library_worker_table > 0 do
|
local mob_chance_offset = math_random(1, cumulative_chance)
|
||||||
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
|
||||||
local mob_index = 1
|
local mob_index = 1
|
||||||
local mob_chance = mob_library_worker_table[mob_index].chance
|
local mob_chance = mob_library_worker_table[mob_index].chance
|
||||||
local step_chance = mob_chance
|
local step_chance = mob_chance
|
||||||
while step_chance < mob_chance_offset do
|
while step_chance < mob_chance_offset do
|
||||||
mob_index = mob_index + 1
|
mob_index = mob_index + 1
|
||||||
mob_chance = mob_library_worker_table[mob_index].chance
|
if mob_index <= #mob_library_worker_table then
|
||||||
step_chance = step_chance + mob_chance
|
mob_chance = mob_library_worker_table[mob_index].chance
|
||||||
|
step_chance = step_chance + mob_chance
|
||||||
|
else
|
||||||
|
step_chance = 1000000
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if mob_index > #mob_library_worker_table then
|
||||||
|
mob_index = 1
|
||||||
end
|
end
|
||||||
--minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance)
|
--minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance)
|
||||||
|
|
||||||
@ -1089,7 +1108,7 @@ if mobs_spawn then
|
|||||||
|
|
||||||
end
|
end
|
||||||
current_summary_chance = current_summary_chance - mob_chance
|
current_summary_chance = current_summary_chance - mob_chance
|
||||||
table_remove(mob_library_worker_table, mob_index)
|
spawn_loop_counter = spawn_loop_counter - 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1101,6 +1120,7 @@ if mobs_spawn then
|
|||||||
|
|
||||||
timer = timer + dtime
|
timer = timer + dtime
|
||||||
if timer < WAIT_FOR_SPAWN_ATTEMPT then return end
|
if timer < WAIT_FOR_SPAWN_ATTEMPT then return end
|
||||||
|
initialize_spawn_data()
|
||||||
timer = 0
|
timer = 0
|
||||||
|
|
||||||
local players = get_connected_players()
|
local players = get_connected_players()
|
||||||
|
Loading…
Reference in New Issue
Block a user