2019-01-04 22:09:57 +02:00
-- this module respawns fish in all water tiles on every surface with a player on it -- by mewmew --
2019-01-05 01:14:15 +02:00
-- cpu heavy -- fixed processing rate is 1 chunk per tick
2019-01-06 20:41:58 +02:00
local respawn_interval = 7200 --interval in ticks
2019-01-05 01:14:15 +02:00
global.fish_respawner_water_tiles_per_fish = 32 --amount of water tiles required per fish >> high values = less fish density, low values = high fish density
2019-01-06 20:41:58 +02:00
global.fish_respawner_max_respawnrate_per_chunk = 1 --maximum amount of fish that will spawn each interval in one chunk
2019-01-04 22:09:57 +02:00
local valid_water_tiles = {
2019-01-05 01:14:15 +02:00
" water " ,
" deepwater " ,
" water-green " ,
" deepwater-green "
2019-01-04 22:09:57 +02:00
}
local event = require ' utils.event '
local math_random = math.random
local function shuffle ( tbl )
local size = # tbl
for i = size , 1 , - 1 do
2019-01-05 01:14:15 +02:00
local rand = math_random ( size )
2019-01-04 22:09:57 +02:00
tbl [ i ] , tbl [ rand ] = tbl [ rand ] , tbl [ i ]
end
return tbl
end
local function get_surfaces ( )
local surfaces = { }
for _ , player in pairs ( game.connected_players ) do
if not surfaces [ player.surface . index ] then
surfaces [ player.surface . index ] = player.surface
end
end
return surfaces
end
local function create_new_fish_spawn_schedule ( )
global.fish_respawn_chunk_schedule = { }
local surfaces = get_surfaces ( )
if # surfaces == 0 then return end
for _ , surface in pairs ( surfaces ) do
for chunk in surface.get_chunks ( ) do
global.fish_respawn_chunk_schedule [ # global.fish_respawn_chunk_schedule + 1 ] = { chunk = { x = chunk.x , y = chunk.y } , surface_index = surface.index }
end
end
global.fish_respawn_chunk_schedule = shuffle ( global.fish_respawn_chunk_schedule )
return global.fish_respawn_chunk_schedule
end
local function respawn_fishes_in_chunk ( schedule )
local surface = game.surfaces [ schedule.surface_index ]
local chunk = schedule.chunk
local chunk_area = { { chunk.x * 32 , chunk.y * 32 } , { chunk.x * 32 + 32 , chunk.y * 32 + 32 } }
2019-01-05 01:14:15 +02:00
local water_tiles = surface.find_tiles_filtered ( { area = chunk_area , name = valid_water_tiles } )
if # water_tiles < global.fish_respawner_water_tiles_per_fish then return end
local chunk_fish_count = surface.count_entities_filtered ( { area = chunk_area , type = " fish " } )
local fish_to_spawn = math.floor ( ( # water_tiles - ( global.fish_respawner_water_tiles_per_fish * chunk_fish_count ) ) / global.fish_respawner_water_tiles_per_fish )
if fish_to_spawn <= 0 then return end
if fish_to_spawn > global.fish_respawner_max_respawnrate_per_chunk then fish_to_spawn = global.fish_respawner_max_respawnrate_per_chunk end
2019-01-04 22:09:57 +02:00
water_tiles = shuffle ( water_tiles )
for _ , tile in pairs ( water_tiles ) do
if surface.can_place_entity ( { name = " fish " , position = tile.position } ) then
surface.create_entity ( { name = " water-splash " , position = tile.position } )
surface.create_entity ( { name = " fish " , position = tile.position } )
fish_to_spawn = fish_to_spawn - 1
if fish_to_spawn <= 0 then return end
end
end
end
local function on_tick ( )
local i = game.tick % respawn_interval
if i == 0 then create_new_fish_spawn_schedule ( ) return end
if not global.fish_respawn_chunk_schedule [ i ] then return end
respawn_fishes_in_chunk ( global.fish_respawn_chunk_schedule [ i ] )
global.fish_respawn_chunk_schedule [ i ] = nil
end
event.add ( defines.events . on_tick , on_tick )