M3wM3w / ComfyFactorio

A chonky factorio scenario, featuring a whole compilation of different maps.
74 stars 71 forks source link

Biters get stuck in Fish Defender when doing a bunker run #243

Open mweber06 opened 3 years ago

mweber06 commented 3 years ago

image When building a bunker to defend the market, biters in the later waves can get stuck on the sides. This is a game breaking bug because they take up the spawn buffer preventing waves from spawning new biters. While this could be abused to make the game trivial, however, this has the disadvantage of crippling coin income. The most likely outcome is this crippling turret slot purchases for the very last waves at which point it only takes pulling a wave once to spawn the toughest biters with a crippled turret count.

The best fix is to add a counter to look for stuck groups. Most likely they have no commands being issued to them. Should be simple to increment through biter groups with no commands or stalling commands and adding an attack command.

mweber06 commented 3 years ago

After looking through the code I see that there's already a function for this, wake_up_the_biters, however, local biters = surface.find_enemy_units(units[i].position, 24, 'player') This doesn't work in editor mode, I think because there's no players for the game to look for.

mweber06 commented 3 years ago

I've narrowed it down to send_unit_group, it searches forward for an open spot to attack, but it doesn't start searching towards the market once the biters move furthest left. This code will start searching up or down towards the market only when the group has reached the furthest they can go left.

if unit_group.position.x < market.position.x + 48 then
    -- increment up or down based on group y position
    for y = unit_group.position.y, market.position.y, -48 * math.max(-1, math.min(1, unit_group.position.y)) do
        local destination = unit_group.surface.find_non_colliding_position('stone-wall', {x = unit_group.position.x, y = y}, 32, 4)
        if destination then
            commands[#commands + 1] = {
                type = defines.command.attack_area,
                destination = destination,
                radius = 16,
                distraction = defines.distraction.by_enemy
            }
        end
    end
else
    for x = unit_group.position.x, market.position.x, -48 do
        local destination = unit_group.surface.find_non_colliding_position('stone-wall', {x = x, y = unit_group.position.y}, 32, 4)
        if destination then
            commands[#commands + 1] = {
                type = defines.command.attack_area,
                destination = destination,
                radius = 16,
                distraction = defines.distraction.by_enemy
            }
        end
    end
end