1
0
mirror of https://github.com/veden/Rampant.git synced 2025-01-14 02:23:01 +02:00

see changelog

This commit is contained in:
Aaron Veden 2019-10-20 13:45:43 -07:00
parent e283fa400c
commit 76665ef603
14 changed files with 265 additions and 149 deletions

View File

@ -138,7 +138,7 @@ function upgrade.attempt(natives)
end
if (global.version < constants.VERSION_26) then
game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
-- game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.16")
global.version = constants.VERSION_26
@ -323,6 +323,8 @@ function upgrade.attempt(natives)
game.map_settings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
game.map_settings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
game.map_settings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
game.map_settings.max_failed_behavior_count = 3
for i=#natives.squads,1,-1 do
natives.squads[i].penalties = {}

View File

@ -9,6 +9,9 @@ Date: 10. 13. 2019
- Increased minimum unit count for a retreat from 3 to 6
Optimizations:
- Better object reuse for squad and pending attack, creating less garbage
- Trimmed table creation where possible
- Regrouping squads and builder clean up put onto separate intervals
- Reusing chunk scanner tables
Bugfixes:
- Fixed old savegames penalties having nil chunk index
- Fixed that mining a resource by hand unregister all remaining resource on a tile
@ -16,7 +19,9 @@ Date: 10. 13. 2019
- Fixed chunk scan and player building pheromone generator mismatch
- Fixed ai credits being uncapped and accumulating more than Max Credits available for that evolution level
- Fixed retreating squads being adding to squad set multiple times
- Fixed retreating squads not waiting long enough to assemble all units before movement
- Fixed spitter max projectile range could cause a spitter to attack but not hit a target
- Fixed non retreating group formation not having a distraction modifier
---------------------------------------------------------------------------------------------------
Version: 0.17.28

View File

@ -27,6 +27,8 @@ local INTERVAL_PLAYER_PROCESS = constants.INTERVAL_PLAYER_PROCESS
local INTERVAL_MAP_PROCESS = constants.INTERVAL_MAP_PROCESS
local INTERVAL_SCAN = constants.INTERVAL_SCAN
local INTERVAL_SQUAD = constants.INTERVAL_SQUAD
local INTERVAL_RESQUAD = constants.INTERVAL_RESQUAD
local INTERVAL_BUILDERS = constants.INTERVAL_BUILDERS
local RECOVER_NEST_COST = constants.RECOVER_NEST_COST
local RECOVER_WORM_COST = constants.RECOVER_WORM_COST
@ -257,6 +259,11 @@ local function rebuildMap()
SENTINEL_IMPASSABLE_CHUNK
}
map.enemiesToSquad = {}
map.enemiesToSquad.len = 0
map.chunkRemovals = {}
map.emptySquadsOnChunk = {}
map.position2Top = {0, 0}
map.position2Bottom = {0, 0}
--this is shared between two different queries
@ -404,7 +411,9 @@ local function rebuildMap()
map.formGroupCommand = { type = DEFINES_COMMAND_GROUP,
group = nil,
distraction = DEFINES_DISTRACTION_NONE }
distraction = DEFINES_DISTRACTION_ANYTHING,
use_group_distraction = false
}
map.formCommand = { command = map.formGroupCommand,
unit_count = 0,
@ -517,11 +526,10 @@ script.on_nth_tick(INTERVAL_PLAYER_PROCESS,
function (event)
local gameRef = game
local surface = gameRef.surfaces[natives.activeSurface]
processPlayers(gameRef.players,
map,
surface,
gameRef.surfaces[natives.activeSurface],
natives,
event.tick)
end)
@ -530,10 +538,9 @@ script.on_nth_tick(INTERVAL_MAP_PROCESS,
function (event)
local gameRef = game
local surface = gameRef.surfaces[natives.activeSurface]
processMap(map,
surface,
gameRef.surfaces[natives.activeSurface],
natives,
event.tick,
gameRef.forces.enemy.evolution_factor)
@ -549,7 +556,7 @@ script.on_nth_tick(INTERVAL_SCAN,
scanMap(map, surface, natives, tick)
map.chunkToPassScan = processScanChunks(map, surface)
processScanChunks(map, surface)
end)
script.on_nth_tick(INTERVAL_LOGIC,
@ -560,6 +567,8 @@ script.on_nth_tick(INTERVAL_LOGIC,
game.forces.enemy.evolution_factor,
tick)
squadsBeginAttack(natives)
if natives.newEnemies then
recycleBases(natives, tick)
end
@ -567,15 +576,25 @@ end)
script.on_nth_tick(INTERVAL_SQUAD,
function ()
local surface = game.surfaces[natives.activeSurface]
squadsBeginAttack(natives)
squadsDispatch(map, surface, natives)
regroupSquads(natives, map)
cleanBuilders(map, natives, surface)
squadsDispatch(map,
game.surfaces[natives.activeSurface],
natives)
end)
script.on_nth_tick(INTERVAL_BUILDERS,
function ()
cleanBuilders(map,
natives,
game.surfaces[natives.activeSurface])
end)
script.on_nth_tick(INTERVAL_RESQUAD,
function ()
regroupSquads(natives, map)
end)
local function onBuild(event)
local entity = event.created_entity or event.entity
if (entity.surface.index == natives.activeSurface) then
@ -885,6 +904,16 @@ local function onInit()
hookEvents()
end
local function onEntitySpawned(event)
local entity = event.entity
if (entity.type ~= "unit") then
local spawner = event.spawner
-- print(spawner.unit_number)
else
-- print("cost")
end
end
local function onCommandDebugger(event)
for i=1,natives.squads.len do
if (natives.squads[i].group.valid) and (natives.squads[i].group.group_number == event.unit_number) then
@ -943,6 +972,7 @@ script.on_event({defines.events.on_built_entity,
defines.events.script_raised_built}, onBuild)
-- script.on_event(defines.events.on_ai_command_completed, onCommandDebugger)
script.on_event(defines.events.on_entity_spawned, onEntitySpawned)
script.on_event(defines.events.on_rocket_launched, onRocketLaunch)
script.on_event(defines.events.on_entity_died, onDeath)

View File

@ -1,5 +1,6 @@
local vanillaBuildings = require("prototypes/buildings/UpdatesVanilla")
local biterFunctions = require("prototypes/utils/BiterUtils")
local neutral = require("prototypes/Neutral")
local acid = require("prototypes/Acid")
local physical = require("prototypes/Physical")
@ -68,6 +69,18 @@ if settings.startup["rampant-newEnemies"].value then
end
data:extend({
biterFunctions.makeUnitSpawner("tester",
{
scale=1.0,
spawningRadius=30,
spawningSpacing=15
},
{},
{{"small-worm-turret", {{0.0, 1.0}, {1.0, 1.0}}}})
})
for _, unitSpawner in pairs(data.raw["unit-spawner"]) do
if settings.startup["rampant-unitSpawnerBreath"].value then
if not unitSpawner.flags then
@ -84,13 +97,8 @@ if settings.startup["rampant-enableSwarm"].value then
{unit.collision_box[1][1] * 0.20, unit.collision_box[1][2] * 0.20},
{unit.collision_box[2][1] * 0.20, unit.collision_box[2][2] * 0.20}
}
if unit.collision_mask == nil then
unit.collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"}
else
unit.collision_mask[#unit.collision_mask+1] = "not-colliding-with-itself"
end
unit.ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = false, path_resolution_modifier = -8, do_seperation = false }
unit.ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = true, path_resolution_modifier = -5, do_seperation = true }
end
end
end

View File

@ -17,7 +17,7 @@ end
for _, robot in pairs(data.raw["logistic-robot"]) do
if not robot.collision_mask then
robot.collision_mask = {}
robot.collision_mask = {}
end
robot.collision_mask[#robot.collision_mask+1] = "layer-11"
@ -34,7 +34,7 @@ end
for _, robot in pairs(data.raw["construction-robot"]) do
if not robot.collision_mask then
robot.collision_mask = {}
robot.collision_mask = {}
end
robot.collision_mask[#robot.collision_mask+1] = "layer-11"
@ -51,7 +51,7 @@ end
for _, robot in pairs(data.raw["combat-robot"]) do
if not robot.collision_mask then
robot.collision_mask = {}
robot.collision_mask = {}
end
robot.collision_mask[#robot.collision_mask+1] = "layer-11"
end
@ -62,7 +62,7 @@ end
--]]
local mapSettings = data.raw["map-settings"]["map-settings"]
mapSettings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
mapSettings.max_failed_behavior_count = 3 -- constants.MAX_FAILED_BEHAVIORS
mapSettings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE
mapSettings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE
@ -73,7 +73,7 @@ mapSettings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX
mapSettings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
data.raw["utility-constants"]["default"].unit_group_pathfinding_resolution = -8
data.raw["utility-constants"]["default"].unit_group_pathfinding_resolution = -5
data.raw["utility-constants"]["default"].unit_group_collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"}

View File

@ -198,6 +198,7 @@ function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
setChunkSettlerTick(map, squadPath, tick + natives.settlerCooldown)
local pending = natives.pendingAttack
pending.len = pending.len + 1
squad.cycles = 30
pending[pending.len] = squad
natives.points = natives.points - AI_SETTLER_COST
else
@ -241,6 +242,7 @@ function aiAttackWave.formVengenceSquad(map, surface, natives, chunk)
if (foundUnits > 0) then
local pending = natives.pendingAttack
pending.len = pending.len + 1
squad.cycles = 13
pending[pending.len] = squad
natives.points = natives.points - AI_VENGENCE_SQUAD_COST
else
@ -285,6 +287,7 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, tick)
if (foundUnits > 0) then
local pending = natives.pendingAttack
pending.len = pending.len + 1
squad.cycles = 30
pending[pending.len] = squad
natives.points = natives.points - AI_SQUAD_COST
if tick and (natives.state == AI_STATE_AGGRESSIVE) then
@ -301,7 +304,7 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, tick)
end
end
end
return (natives.points - AI_SQUAD_COST) > 0
end

View File

@ -30,6 +30,8 @@ local tSort = table.sort
local abs = math.abs
local tRemove = table.remove
-- module code
local origin = {x=0,y=0}
@ -103,9 +105,13 @@ function chunkProcessor.processScanChunks(map, surface)
local topOffset = area[1]
local bottomOffset = area[2]
local removals = {}
local removals = map.chunkRemovals
for chunk,_ in pairs(map.chunkToPassScan) do
local chunkCount = 0
local chunkToPassScan = map.chunkToPassScan
for chunk,_ in pairs(chunkToPassScan) do
local x = chunk.x
local y = chunk.y
@ -119,24 +125,25 @@ function chunkProcessor.processScanChunks(map, surface)
if (chunk == SENTINEL_IMPASSABLE_CHUNK) then
map[x][y] = nil
removals[#removals+1] = chunk
chunkCount = chunkCount + 1
removals[chunkCount] = chunk
end
chunkToPassScan[chunk] = nil
end
if (#removals > 0) then
if (chunkCount > 0) then
local processQueue = map.processQueue
for i=#processQueue,1,-1 do
for ri=#removals,1,-1 do
for ri=chunkCount,1,-1 do
if (removals[ri] == processQueue[i]) then
table.remove(processQueue, i)
table.remove(removals, ri)
tRemove(processQueue, i)
-- tRemove(removals, ri)
break
end
end
end
end
return {}
end
chunkProcessorG = chunkProcessor

View File

@ -211,7 +211,7 @@ function chunkPropertyUtils.removeSquadFromChunk(map, squad)
end
function chunkPropertyUtils.getSquadsOnChunk(map, chunk)
return map.chunkToSquad[chunk] or {}
return map.chunkToSquad[chunk] or map.emptySquadsOnChunk
end
function chunkPropertyUtils.setPlayerBaseGenerator(map, chunk, playerGenerator)

View File

@ -61,6 +61,8 @@ constants.INTERVAL_SCAN = (settings.startup["rampant-liteMode"].value and 42) or
constants.INTERVAL_CHUNK = 17
constants.INTERVAL_LOGIC = 61
constants.INTERVAL_SQUAD = 41
constants.INTERVAL_RESQUAD = 101
constants.INTERVAL_BUILDERS = 300
constants.INTERVAL_SPAWNER = constants.TICKS_A_SECOND * 10
constants.INTERVAL_RALLY = constants.TICKS_A_SECOND * 10
constants.INTERVAL_RETREAT = constants.TICKS_A_SECOND * 10

View File

@ -121,7 +121,7 @@ function movementUtils.scoreNeighborsForAttack(map, natives, chunk, neighborDire
if (nextHighestChunk == nil) then
nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
end
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
end
@ -133,7 +133,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
@ -153,7 +153,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
local nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
local nextHighestScore = -MAGIC_MAXIMUM_NUMBER
local nextHighestDirection
if (highestChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
for x=1,8 do
@ -174,7 +174,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
if (nextHighestChunk == nil) then
nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
end
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
end
@ -211,6 +211,11 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
local nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
local nextHighestScore = -MAGIC_MAXIMUM_NUMBER
local nextHighestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
@ -223,7 +228,28 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
end
end
return highestChunk, highestDirection
if (highestChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if ((neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (neighborChunk ~= chunk) and
canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then
local score = scoreFunction(map, neighborChunk)
if (score > nextHighestScore) then
nextHighestScore = score
nextHighestChunk = neighborChunk
nextHighestDirection = x
end
end
end
end
if (nextHighestChunk == nil) then
nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
end
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
end

View File

@ -143,7 +143,7 @@ local function settleMove(map, squad, natives, surface)
local cmd
local position
local position2
if (distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0))
then
if not ((groupState == DEFINES_GROUP_FINISHED) or ((groupState == DEFINES_GROUP_GATHERING) and (squad.cycles <= 0))) then
@ -168,7 +168,7 @@ local function settleMove(map, squad, natives, surface)
map.buildPositionTop.x = position.x - BASE_CLEAN_DISTANCE
map.buildPositionTop.y = position.y - BASE_CLEAN_DISTANCE
map.buildPositionBottom.x = position.x + BASE_CLEAN_DISTANCE
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
local entities = surface.find_entities_filtered(map.filteredEntitiesClearBuildingQuery)
for i=1,#entities do
@ -178,7 +178,7 @@ local function settleMove(map, squad, natives, surface)
end
end
squad.cycles = 400
squad.cycles = 400
group.set_command(cmd)
else
local attackChunk, attackDirection, nextAttackChunk, nextAttackDirection = scoreNeighborsForSettling(map,
@ -199,15 +199,15 @@ local function settleMove(map, squad, natives, surface)
if not position then
squad.cycles = 30
cmd = map.wonderCommand
group.set_command(cmd)
group.set_command(cmd)
return
else
targetPosition.x = position.x
targetPosition.y = position.y
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) or
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
then
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
then
cmd = map.attackCommand
if not squad.rabid then
@ -224,22 +224,22 @@ local function settleMove(map, squad, natives, surface)
end
end
end
if (nextAttackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
position2 = findMovementPosition(surface, targetPosition2)
if position2 then
targetPosition.x = position2.x
targetPosition.y = position2.y
if ((cmd ~= map.attackCommand) and
((getPlayerBaseGenerator(map, nextAttackChunk) ~= 0) or
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)))
then
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)))
then
cmd = map.attackCommand
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
@ -263,7 +263,7 @@ local function settleMove(map, squad, natives, surface)
map.buildPositionTop.x = position.x - BASE_CLEAN_DISTANCE
map.buildPositionTop.y = position.y - BASE_CLEAN_DISTANCE
map.buildPositionBottom.x = position.x + BASE_CLEAN_DISTANCE
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
local entities = surface.find_entities_filtered(map.filteredEntitiesClearBuildingQuery)
for i=1,#entities do
@ -272,12 +272,12 @@ local function settleMove(map, squad, natives, surface)
entity.die()
end
end
squad.cycles = 400
squad.cycles = 400
group.set_command(cmd)
else
squad.cycles = 23
group.set_command(cmd)
group.set_command(cmd)
end
end
end
@ -326,7 +326,7 @@ local function attackMove(map, squad, natives, surface)
else
targetPosition.x = position.x
targetPosition.y = position.y
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) and
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
then
@ -343,7 +343,7 @@ local function attackMove(map, squad, natives, surface)
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
end
end
end
@ -363,7 +363,7 @@ local function attackMove(map, squad, natives, surface)
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold))
then
cmd = map.attackCommand
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
@ -389,7 +389,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
local pending = natives.pendingAttack
local squadsLen = squads.len
local x = 0
for i=1,squadsLen do
local squad = squads[i]
local group = squad.group
@ -430,7 +430,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
end
end
elseif (status == SQUAD_SETTLING) then
x = x + 1
x = x + 1
squads[x] = squad
if (groupState == DEFINES_GROUP_FINISHED) or
(groupState == DEFINES_GROUP_GATHERING) or
@ -443,10 +443,22 @@ function squadAttack.squadsDispatch(map, surface, natives)
addSquadToChunk(map, chunk, squad)
end
end
elseif (status == SQUAD_RETREATING) and (cycles <= 0) then
pending.len = pending.len + 1
pending[pending.len] = squad
squad.status = SQUAD_GUARDING
elseif (status == SQUAD_RETREATING) then
if (groupState == DEFINES_GROUP_FINISHED) or
(groupState == DEFINES_GROUP_GATHERING) or
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
then
pending.len = pending.len + 1
pending[pending.len] = squad
squad.status = SQUAD_GUARDING
else
x = x + 1
squads[x] = squad
end
local chunk = getChunkByPosition(map, group.position)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad)
end
elseif (status == SQUAD_BUILDING) then
removeSquadFromChunk(map, squad)
natives.building[#natives.building+1] = squad
@ -454,7 +466,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
pending.len = pending.len + 1
pending[pending.len] = squad
else
x = x + 1
x = x + 1
squads[x] = squad
end
if (cycles > 0) then
@ -468,7 +480,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
end
squads.len = x
-- print("end dispatch")
-- if (maxSquadIndex >= #squads) then
-- natives.attackIndex = 1
@ -484,15 +496,17 @@ function squadAttack.squadsBeginAttack(natives)
local squads = natives.squads
local pendingLen = pending.len
local x = 0
for i=1,pendingLen do
local squad = pending[i]
local group = squad.group
if group and group.valid then
if (squad.cycles ~= 0) then
local groupState = group.state
if -- (groupState ~= DEFINES_GROUP_GATHERING) and
(groupState ~= DEFINES_GROUP_FINISHED) and (squad.cycles ~= 0) then
squad.cycles = squad.cycles - 1
x = x + 1
pending[x] = squad
pending[x] = squad
else
local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
if not squad.kamikaze then
@ -510,7 +524,7 @@ function squadAttack.squadsBeginAttack(natives)
squads.len = squads.len + 1
squads[squads.len] = squad
end
end
end
end
end

View File

@ -33,7 +33,7 @@ local addSquadToChunk = chunkPropetyUtils.addSquadToChunk
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
local positionFromDirectionAndFlat = mapUtils.positionFromDirectionAndFlat
local getNeighborChunks = mapUtils.getNeighborChunks
local findNearbyRetreatingSquad = unitGroupUtils.findNearbyRetreatingSquad
local addMovementPenalty = movementUtils.addMovementPenalty
@ -64,60 +64,84 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
local enemiesToSquad = nil
if not squad then
enemiesToSquad = surface.find_enemy_units(position, radius)
performRetreat = #enemiesToSquad > 6
if (mRandom() < calculateKamikazeThreshold(#enemiesToSquad, natives)) then
enemiesToSquad = map.enemiesToSquad
local unitCount = 0
local units = surface.find_enemy_units(position, radius)
for i=1,#units do
local unit = units[i]
if not unit.unit_group then
unitCount = unitCount + 1
enemiesToSquad[unitCount] = unit
end
end
enemiesToSquad.len = unitCount
if (mRandom() < calculateKamikazeThreshold(unitCount, natives)) then
setRetreatTick(map, chunk, tick)
return
end
performRetreat = unitCount > 6
elseif squad.group and squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
performRetreat = #squad.group.members > 6
end
if performRetreat then
setRetreatTick(map, chunk, tick)
local exitPath,exitDirection = scoreNeighborsForRetreat(chunk,
getNeighborChunks(map, chunk.x, chunk.y),
scoreRetreatLocation,
map)
local exitPath,exitDirection,nextExitPath,nextExitDirection = scoreNeighborsForRetreat(chunk,
getNeighborChunks(map,
chunk.x,
chunk.y),
scoreRetreatLocation,
map)
if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
local retreatPosition = findMovementPosition(surface,
positionFromDirectionAndChunk(exitDirection,
position,
map.position,
0.98))
local targetPosition = map.position
local targetPosition2 = map.position2
positionFromDirectionAndFlat(exitDirection, position, targetPosition)
local retreatPosition = findMovementPosition(surface, targetPosition)
if not retreatPosition then
return
end
if (nextExitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
positionFromDirectionAndFlat(nextExitDirection, retreatPosition, targetPosition2)
local retreatPosition2 = findMovementPosition(surface, targetPosition2)
if retreatPosition2 then
retreatPosition.x = retreatPosition2.x
retreatPosition.y = retreatPosition2.y
end
end
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
-- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
local newSquad = findNearbyRetreatingSquad(map, exitPath)
if not newSquad then
newSquad = createSquad(retreatPosition, surface)
local squads = natives.squads
squads.len = squads.len+1
squads[squads.len] = newSquad
end
if newSquad then
newSquad.status = SQUAD_RETREATING
newSquad.cycles = 4
newSquad.cycles = 13
local cmd = map.retreatCommand
local cmd = map.retreatCommand
cmd.group = newSquad.group
if enemiesToSquad then
membersToSquad(cmd, enemiesToSquad, artilleryBlast)
else
membersToSquad(cmd, squad.group.members, true)
membersToSquad(cmd, enemiesToSquad.len, enemiesToSquad, artilleryBlast)
else
membersToSquad(cmd, #squad.group.members, squad.group.members, true)
if squad.rabid then
newSquad.rabid = true
end
end
if not newSquad.rapid then
newSquad.frenzy = true
local squadPosition = newSquad.group.position

View File

@ -82,11 +82,11 @@ function unitGroupUtils.findNearbySquad(map, chunk)
for i=1,#squads do
local squad = squads[i]
local unitGroup = squad.group
if unitGroup and unitGroup.valid then
return squad
if unitGroup and unitGroup.valid then
return squad
end
end
local neighbors = getNeighborChunks(map, chunk.x, chunk.y)
for i=1,#neighbors do
@ -138,15 +138,15 @@ function unitGroupUtils.createSquad(position, surface, group, settlers)
return squad
end
function unitGroupUtils.membersToSquad(cmd, members, overwriteGroup)
if (members ~= nil) then
for i=1,#members do
local member = members[i]
if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
member.set_command(cmd)
end
function unitGroupUtils.membersToSquad(cmd, size, members, overwriteGroup)
-- if (members ~= nil) then
for i=1,size do
local member = members[i]
if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
member.set_command(cmd)
end
end
-- end
end
function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
@ -190,13 +190,7 @@ function unitGroupUtils.cleanBuilders(map, natives, surface)
for i=maxSquadIndex,startIndex,-1 do
local squad = squads[i]
local group = squad.group
if not (group and group.valid) then
tRemove(squads, i)
else
if (squad.cycles > 0) then
squad.cycles = squad.cycles - 1
end
if group and group.valid then
if (group.state == DEFINES_GROUP_FINISHED) or (squad.cycles <= 0) then
if (#group.members > 0) then
local groupPosition = findMovementPosition(surface, group.position)
@ -204,19 +198,23 @@ function unitGroupUtils.cleanBuilders(map, natives, surface)
if not groupPosition then
groupPosition = group.position
end
position.x = groupPosition.x
position.y = groupPosition.y
squad.cycles = 400
group.set_command(cmd)
group.start_moving()
else
tRemove(squads, i)
group.destroy()
end
elseif (squad.cycles > 0) then
squad.cycles = squad.cycles - 1
end
else
tRemove(squads, i)
end
end
@ -227,11 +225,6 @@ function unitGroupUtils.cleanBuilders(map, natives, surface)
end
end
local function isAttacking(group)
local state = group.state
return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION)
end
function unitGroupUtils.regroupSquads(natives, map)
local squads = natives.squads
local squadCount = squads.len
@ -242,39 +235,41 @@ function unitGroupUtils.regroupSquads(natives, map)
for i=startIndex,maxSquadIndex do
local squad = squads[i]
local group = squad.group
if group and group.valid and not isAttacking(group) then
local memberCount = #group.members
if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then
local status = squad.status
local chunk = squad.chunk
if group and group.valid then
local groupState = group.state
if (groupState ~= DEFINES_GROUP_STATE_ATTACKING_TARGET) and (groupState ~= DEFINES_GROUP_STATE_ATTACKING_DISTRACTION) then
local memberCount = #group.members
if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then
local status = squad.status
local chunk = squad.chunk
if chunk then
local chunkSquads = getSquadsOnChunk(map, chunk)
for p=1,#chunkSquads do
local mergeSquad = chunkSquads[p]
if (mergeSquad ~= squad) then
local mergeGroup = mergeSquad.group
if mergeGroup and
mergeGroup.valid and
(mergeSquad.status == status) and
not isAttacking(mergeGroup)
then
local mergeMembers = mergeGroup.members
local mergeCount = #mergeMembers
if ((mergeCount + memberCount) < AI_MAX_BITER_GROUP_SIZE) then
for memberIndex=1, mergeCount do
group.add_member(mergeMembers[memberIndex])
end
mergeGroup.destroy()
end
squad.status = SQUAD_GUARDING
memberCount = memberCount + mergeCount
if (memberCount > AI_SQUAD_MERGE_THRESHOLD) then
break
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local chunkSquads = getSquadsOnChunk(map, chunk)
for p=1,#chunkSquads do
local mergeSquad = chunkSquads[p]
if (mergeSquad ~= squad) then
local mergeGroup = mergeSquad.group
if mergeGroup and mergeGroup.valid and (mergeSquad.status == status) then
local mergeGroupState = mergeGroup.state
if (mergeGroupState ~= DEFINES_GROUP_STATE_ATTACKING_TARGET) and (mergeGroupState ~= DEFINES_GROUP_STATE_ATTACKING_DISTRACTION) then
local mergeMembers = mergeGroup.members
local mergeCount = #mergeMembers
if ((mergeCount + memberCount) < AI_MAX_BITER_GROUP_SIZE) then
for memberIndex=1, mergeCount do
group.add_member(mergeMembers[memberIndex])
end
mergeGroup.destroy()
end
squad.status = SQUAD_GUARDING
memberCount = memberCount + mergeCount
if (memberCount > AI_SQUAD_MERGE_THRESHOLD) then
break
end
end
end
end
end
end
end
end
end
end
end

View File

@ -236,7 +236,7 @@ function biterFunctions.makeBiter(name, biterAttributes, biterAttack, biterResis
dying_sound = make_biter_dying_sounds(biterAttributes.scale),
working_sound = make_biter_calls(biterAttributes.scale),
run_animation = biterrunanimation(biterAttributes.scale, biterAttributes.tint, biterAttributes.tint),
ai_settings = { destroy_when_commands_fail = true, allow_try_return_to_spawner = true, path_resolution_modifier = -8, do_seperation = true }
ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = true, path_resolution_modifier = -5, do_seperation = true }
}
if biterAttributes.collisionMask then
entity.collision_mask = biterAttributes.collisionMask
@ -282,7 +282,7 @@ function biterFunctions.makeSpitter(name, biterAttributes, biterAttack, biterRes
dying_sound = make_spitter_dying_sounds(0.8),
working_sound = make_biter_calls(0.7),
run_animation = spitterrunanimation(biterAttributes.scale, biterAttributes.tint, biterAttributes.tint),
ai_settings = { destroy_when_commands_fail = true, allow_try_return_to_spawner = true, path_resolution_modifier = -8, do_seperation = true }
ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = true, path_resolution_modifier = -5, do_seperation = true }
}
if biterAttributes.collisionMask then
entity.collision_mask = biterAttributes.collisionMask