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 --
2021-03-24 17:46:00 +02:00
-- cpu heavy -- fixed processing rate is 1 chunk per tick
2019-01-05 01:14:15 +02:00
2021-03-24 17:46:00 +02:00
local respawn_interval = 7200 --interval in ticks
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
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 = {
2021-03-24 17:46:00 +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 )
2021-03-24 17:46:00 +02:00
local size = # tbl
for i = size , 1 , - 1 do
local rand = math_random ( size )
tbl [ i ] , tbl [ rand ] = tbl [ rand ] , tbl [ i ]
end
return tbl
2019-01-04 22:09:57 +02:00
end
local function get_surfaces ( )
2021-03-24 17:46:00 +02:00
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
2019-01-04 22:09:57 +02:00
end
local function create_new_fish_spawn_schedule ( )
2021-03-24 17:46:00 +02:00
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
2019-01-04 22:09:57 +02:00
end
local function respawn_fishes_in_chunk ( schedule )
2021-03-24 17:46:00 +02:00
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 } }
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
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
2019-01-04 22:09:57 +02:00
end
local function on_tick ( )
2021-03-24 17:46:00 +02:00
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
2019-01-04 22:09:57 +02:00
end
2021-03-24 17:46:00 +02:00
event.add ( defines.events . on_tick , on_tick )