1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-16 10:19:27 +02:00
RedMew/map_gen/maps/danger_ores/modules/rocket_launched.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