mirror of
https://github.com/Refactorio/RedMew.git
synced 2024-12-16 10:19:27 +02:00
248 lines
8.1 KiB
Lua
248 lines
8.1 KiB
Lua
local Event = require 'utils.event'
|
|
local Generate = require 'map_gen.shared.generate'
|
|
local Global = require 'utils.global'
|
|
local Queue = require 'utils.queue'
|
|
local AlienEvolutionProgress = require 'utils.alien_evolution_progress'
|
|
local RS = require 'map_gen.shared.redmew_surface'
|
|
local Task = require 'utils.task'
|
|
local Token = require 'utils.token'
|
|
local Server = require 'features.server'
|
|
local ShareGlobals = require 'map_gen.maps.danger_ores.modules.shared_globals'
|
|
|
|
return function(config)
|
|
local recent_chunks = Queue.new() -- Keeps track of recently revealed chunks
|
|
local recent_chunks_max = config.recent_chunks_max or 10 -- Maximum number of chunks to track
|
|
local ticks_between_waves = config.ticks_between_waves or (60 * 30)
|
|
local enemy_factor = config.enemy_factor or 5
|
|
local max_enemies_per_wave_per_chunk = config.max_enemies_per_wave_per_chunk or 60
|
|
|
|
local win_data = {
|
|
evolution_rocket_maxed = -1,
|
|
extra_rockets = config.extra_rockets or 100
|
|
}
|
|
|
|
ShareGlobals.data.biters_disabled = false
|
|
_G.rocket_launched_win_data = win_data
|
|
|
|
Global.register(
|
|
{recent_chunks = recent_chunks, win_data = win_data},
|
|
function(tbl)
|
|
recent_chunks = tbl.recent_chunks
|
|
win_data = tbl.win_data
|
|
end
|
|
)
|
|
|
|
local function give_command(group, data)
|
|
local target = data.target
|
|
|
|
if target and target.valid then
|
|
local command = {
|
|
type = defines.command.attack,
|
|
target = target,
|
|
distraction = defines.distraction.by_damage
|
|
}
|
|
group.set_command(command)
|
|
group.start_moving()
|
|
else
|
|
local command = {
|
|
type = defines.command.attack_area,
|
|
destination = data.position,
|
|
radius = 32,
|
|
distraction = defines.distraction.by_damage
|
|
}
|
|
|
|
local members = group.members
|
|
for i = 1, #members do
|
|
local entitiy = members[i]
|
|
entitiy.set_command(command)
|
|
end
|
|
end
|
|
end
|
|
|
|
local do_waves
|
|
local do_wave
|
|
|
|
do_waves =
|
|
Token.register(
|
|
function(data)
|
|
Task.queue_task(do_wave, data, 10)
|
|
end
|
|
)
|
|
|
|
do_wave =
|
|
Token.register(
|
|
function(data)
|
|
if ShareGlobals.data.biters_disabled then
|
|
return false
|
|
end
|
|
|
|
local wave = data.wave
|
|
local last_wave = data.last_wave
|
|
--game.print('wave: ' .. wave .. '/' .. last_wave)
|
|
|
|
local chunk_index = data.chunk_index
|
|
local chunk = data.chunks[chunk_index]
|
|
|
|
if not chunk then
|
|
data.wave = wave + 1
|
|
data.chunk_index = 1
|
|
Task.set_timeout_in_ticks(ticks_between_waves, do_waves, data)
|
|
return false
|
|
end
|
|
|
|
local spawner = data.spawner
|
|
|
|
local aliens = AlienEvolutionProgress.get_aliens(spawner, game.forces.enemy.evolution_factor)
|
|
|
|
local left_top = chunk.area.left_top
|
|
local center = {left_top.x + 16, left_top.y + 16}
|
|
local surface = chunk.surface
|
|
local find_non_colliding_position = surface.find_non_colliding_position
|
|
local create_entity = surface.create_entity
|
|
|
|
local group = surface.create_unit_group {position = center}
|
|
local add_member = group.add_member
|
|
|
|
for name, count in pairs(aliens) do
|
|
for i = 1, count do
|
|
local pos = find_non_colliding_position(name, center, 32, 1)
|
|
if pos then
|
|
local e = {name = name, position = pos, force = 'enemy', center = center, radius = 16, 1}
|
|
local ent = create_entity(e)
|
|
|
|
add_member(ent)
|
|
end
|
|
end
|
|
end
|
|
|
|
give_command(group, data)
|
|
|
|
if chunk_index < recent_chunks_max then
|
|
data.chunk_index = chunk_index + 1
|
|
return true
|
|
end
|
|
|
|
if wave < last_wave then
|
|
data.wave = wave + 1
|
|
data.chunk_index = 1
|
|
Task.set_timeout_in_ticks(ticks_between_waves, do_waves, data)
|
|
end
|
|
|
|
return false
|
|
end
|
|
)
|
|
|
|
local function start_waves(event)
|
|
local num_enemies = enemy_factor * game.forces.player.get_item_launched('satellite')
|
|
local number_of_waves = math.ceil(num_enemies / max_enemies_per_wave_per_chunk)
|
|
local num_enemies_per_wave_per_chunk = math.ceil(num_enemies / number_of_waves)
|
|
|
|
local target = event.rocket_silo
|
|
local position
|
|
if target and target.valid then
|
|
position = target.position
|
|
else
|
|
position = {0, 0}
|
|
end
|
|
|
|
local data = {
|
|
spawner = AlienEvolutionProgress.create_spawner_request(num_enemies_per_wave_per_chunk),
|
|
wave = 1,
|
|
last_wave = number_of_waves,
|
|
chunk_index = 1,
|
|
chunks = Queue.to_array(recent_chunks),
|
|
target = target,
|
|
position = position
|
|
}
|
|
|
|
Task.set_timeout_in_ticks(1, do_waves, data)
|
|
|
|
game.print('Warning incomming biter attack! Number of waves: ' .. number_of_waves)
|
|
end
|
|
|
|
local function rocket_launched(event)
|
|
local entity = event.rocket
|
|
|
|
if not entity or not entity.valid or not entity.force == 'player' then
|
|
return
|
|
end
|
|
|
|
local inventory = entity.get_inventory(defines.inventory.rocket)
|
|
if not inventory or not inventory.valid then
|
|
return
|
|
end
|
|
|
|
local satellite_count = game.forces.player.get_item_launched('satellite')
|
|
if satellite_count == 0 then
|
|
return
|
|
end
|
|
|
|
if ShareGlobals.data.biters_disabled then
|
|
return
|
|
end
|
|
|
|
-- Increase enemy_evolution
|
|
local current_evolution = game.forces.enemy.evolution_factor
|
|
|
|
if (satellite_count % 5) == 0 and win_data.evolution_rocket_maxed == -1 then
|
|
local message =
|
|
'Continued launching of satellites has angered the local biter population, evolution increasing...'
|
|
game.print(message)
|
|
Server.to_discord_bold(message)
|
|
|
|
current_evolution = current_evolution + 0.05
|
|
game.forces.enemy.evolution_factor = current_evolution
|
|
end
|
|
|
|
if current_evolution < 1 then
|
|
start_waves(event)
|
|
return
|
|
end
|
|
|
|
if win_data.evolution_rocket_maxed == -1 then
|
|
win_data.evolution_rocket_maxed = satellite_count
|
|
end
|
|
|
|
local remaining_satellites = win_data.evolution_rocket_maxed + win_data.extra_rockets - satellite_count
|
|
if remaining_satellites > 0 then
|
|
local message =
|
|
'Biters at maximum evolution! Protect the base for an additional ' ..
|
|
remaining_satellites .. ' rockets to wipe them out forever.'
|
|
game.print(message)
|
|
Server.to_discord_bold(message)
|
|
|
|
start_waves(event)
|
|
return
|
|
end
|
|
|
|
local win_message = 'Congratulations! Biters have been wiped from the map!'
|
|
game.print(win_message)
|
|
Server.to_discord_bold(win_message)
|
|
|
|
ShareGlobals.data.biters_disabled = true
|
|
|
|
game.forces.enemy.kill_all_units()
|
|
for _, enemy_entity in pairs(RS.get_surface().find_entities_filtered({force = 'enemy'})) do
|
|
enemy_entity.destroy()
|
|
end
|
|
end
|
|
|
|
local bad_tiles = {'deepwater-green', 'deepwater', 'out-of-map', 'water-green', 'water'}
|
|
|
|
local function chunk_unlocked(chunk)
|
|
local count = chunk.surface.count_tiles_filtered({area = chunk.area, name = bad_tiles, limit = 1})
|
|
if count > 0 then
|
|
return
|
|
end
|
|
|
|
Queue.push(recent_chunks, chunk)
|
|
|
|
while Queue.size(recent_chunks) > recent_chunks_max do
|
|
Queue.pop(recent_chunks)
|
|
end
|
|
end
|
|
|
|
Event.add(defines.events.on_rocket_launched, rocket_launched)
|
|
Event.add(Generate.events.on_chunk_generated, chunk_unlocked)
|
|
end
|