1
0
mirror of https://github.com/veden/Rampant.git synced 2025-01-03 22:52:20 +02:00
Rampant/libs/SquadAttack.lua

536 lines
21 KiB
Lua
Raw Normal View History

2019-02-16 06:17:30 +02:00
if (squadAttackG) then
return squadAttackG
end
local squadAttack = {}
-- imports
local constants = require("Constants")
local mapUtils = require("MapUtils")
local unitGroupUtils = require("UnitGroupUtils")
local movementUtils = require("MovementUtils")
local mathUtils = require("MathUtils")
local chunkPropertyUtils = require("ChunkPropertyUtils")
-- constants
2017-05-14 00:32:16 +02:00
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
2016-10-15 02:00:18 +02:00
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
local BASE_PHEROMONE = constants.BASE_PHEROMONE
2018-02-13 09:10:17 +02:00
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
2019-02-16 20:45:42 +02:00
local ATTACK_SCORE_KAMIKAZE = constants.ATTACK_SCORE_KAMIKAZE
2019-05-16 07:11:43 +02:00
local DIVISOR_DEATH_TRAIL_TABLE = constants.DIVISOR_DEATH_TRAIL_TABLE
2019-04-08 07:22:02 +02:00
local BASE_CLEAN_DISTANCE = constants.BASE_CLEAN_DISTANCE
local SQUAD_BUILDING = constants.SQUAD_BUILDING
local SQUAD_RAIDING = constants.SQUAD_RAIDING
2018-02-13 09:10:17 +02:00
local SQUAD_SETTLING = constants.SQUAD_SETTLING
local SQUAD_GUARDING = constants.SQUAD_GUARDING
2019-03-07 08:12:39 +02:00
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local AI_MAX_BITER_GROUP_SIZE = constants.AI_MAX_BITER_GROUP_SIZE
2019-10-19 21:13:48 +02:00
local ATTACK_QUEUE_SIZE = constants.ATTACK_QUEUE_SIZE
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
2017-06-11 02:59:06 +02:00
local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER
2017-05-27 02:58:33 +02:00
local DEFINES_GROUP_FINISHED = defines.group_state.finished
local DEFINES_GROUP_GATHERING = defines.group_state.gathering
local DEFINES_GROUP_MOVING = defines.group_state.moving
2019-03-07 03:06:50 +02:00
local DEFINES_DISTRACTION_NONE = defines.distraction.none
2017-05-27 02:58:33 +02:00
local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy
local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
2017-11-21 09:27:03 +02:00
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions
local mRandom = math.random
2019-05-16 07:11:43 +02:00
local mMin = math.min
2019-03-07 08:12:39 +02:00
local tRemove = table.remove
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
local findMovementPosition = movementUtils.findMovementPosition
2019-03-07 08:12:39 +02:00
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
2019-05-16 07:11:43 +02:00
local addDeathGenerator = chunkPropertyUtils.addDeathGenerator
local getDeathGenerator = chunkPropertyUtils.getDeathGenerator
2019-03-07 08:12:39 +02:00
local getNestCount = chunkPropertyUtils.getNestCount
2018-02-17 05:31:29 +02:00
2017-06-08 02:57:24 +02:00
local getNeighborChunks = mapUtils.getNeighborChunks
local addSquadToChunk = chunkPropertyUtils.addSquadToChunk
2018-01-14 07:48:21 +02:00
local getChunkByXY = mapUtils.getChunkByXY
local positionToChunkXY = mapUtils.positionToChunkXY
local addMovementPenalty = movementUtils.addMovementPenalty
local lookupMovementPenalty = movementUtils.lookupMovementPenalty
2017-01-20 07:58:36 +02:00
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
2016-10-31 05:24:14 +02:00
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
local positionFromDirectionAndFlat = mapUtils.positionFromDirectionAndFlat
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
local getResourceGenerator = chunkPropertyUtils.getResourceGenerator
2017-11-21 09:27:03 +02:00
2019-10-19 21:13:48 +02:00
local getChunkByPosition = mapUtils.getChunkByPosition
2017-11-21 09:27:03 +02:00
local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack
2018-09-24 06:56:45 +02:00
local scoreNeighborsForSettling = movementUtils.scoreNeighborsForSettling
-- module code
2018-02-13 09:10:17 +02:00
local function scoreResourceLocation(squad, neighborChunk)
2019-02-11 08:14:17 +02:00
local settle = neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[RESOURCE_PHEROMONE]
return settle - lookupMovementPenalty(squad, neighborChunk) - (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2018-02-13 09:10:17 +02:00
end
local function scoreSiegeLocation(squad, neighborChunk)
2019-02-11 08:14:17 +02:00
local settle = neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] + neighborChunk[RESOURCE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
return settle - lookupMovementPenalty(squad, neighborChunk)
end
2019-02-16 06:17:30 +02:00
local function scoreAttackLocation(natives, squad, neighborChunk)
2019-02-11 08:14:17 +02:00
local damage
local movementPheromone = neighborChunk[MOVEMENT_PHEROMONE]
2019-02-11 08:14:17 +02:00
if (movementPheromone >= 0) then
2019-10-19 21:13:48 +02:00
damage = movementPheromone + (neighborChunk[BASE_PHEROMONE]) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2019-02-11 08:14:17 +02:00
else
damage = (neighborChunk[BASE_PHEROMONE] * (1 - (movementPheromone / -natives.retreatThreshold))) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2019-02-11 08:14:17 +02:00
end
return damage - lookupMovementPenalty(squad, neighborChunk)
end
local function scoreAttackKamikazeLocation(natives, squad, neighborChunk)
local damage = neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2017-12-21 05:50:36 +02:00
return damage - lookupMovementPenalty(squad, neighborChunk)
end
2019-02-11 08:14:17 +02:00
2019-03-09 09:13:36 +02:00
local function settleMove(map, squad, natives, surface)
local targetPosition = map.position
2019-10-19 21:13:48 +02:00
local targetPosition2 = map.position2
2019-03-09 09:13:36 +02:00
local group = squad.group
2019-03-09 09:13:36 +02:00
local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
local scoreFunction = scoreResourceLocation
2019-10-19 21:13:48 +02:00
local groupState = group.state
2019-03-09 09:13:36 +02:00
if (natives.state == AI_STATE_SIEGE) then
scoreFunction = scoreSiegeLocation
end
if squad.chunk and (squad.chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (squad.chunk ~= chunk) then
addMovementPenalty(squad, squad.chunk)
end
2019-03-09 09:13:36 +02:00
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad)
end
2019-04-08 07:22:02 +02:00
local distance = euclideanDistancePoints(groupPosition.x,
groupPosition.y,
squad.originPosition.x,
squad.originPosition.y)
local cmd
local position
2019-10-19 21:13:48 +02:00
local position2
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if (distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0))
2019-04-08 07:22:02 +02:00
then
2019-10-19 21:13:48 +02:00
if not ((groupState == DEFINES_GROUP_FINISHED) or ((groupState == DEFINES_GROUP_GATHERING) and (squad.cycles <= 0))) then
2019-04-08 07:22:02 +02:00
return
end
2019-04-08 07:22:02 +02:00
position = findMovementPosition(surface, groupPosition)
if not position then
position = groupPosition
end
2019-04-08 07:22:02 +02:00
cmd = map.settleCommand
if squad.kamikaze then
cmd.distraction = DEFINES_DISTRACTION_NONE
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
2019-04-08 07:22:02 +02:00
squad.status = SQUAD_BUILDING
map.buildPositionTop.x = position.x - BASE_CLEAN_DISTANCE
map.buildPositionTop.y = position.y - BASE_CLEAN_DISTANCE
map.buildPositionBottom.x = position.x + BASE_CLEAN_DISTANCE
2019-10-20 22:45:43 +02:00
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
2019-04-08 07:22:02 +02:00
local entities = surface.find_entities_filtered(map.filteredEntitiesClearBuildingQuery)
for i=1,#entities do
local entity = entities[i]
if entity.valid and (entity.type ~= "cliff") then
entity.die()
2019-03-09 09:13:36 +02:00
end
end
2019-10-19 21:13:48 +02:00
2019-10-20 22:45:43 +02:00
squad.cycles = 400
2019-10-19 21:13:48 +02:00
group.set_command(cmd)
2019-04-08 07:22:02 +02:00
else
2019-10-19 21:13:48 +02:00
local attackChunk, attackDirection, nextAttackChunk, nextAttackDirection = scoreNeighborsForSettling(map,
chunk,
getNeighborChunks(map, x, y),
scoreFunction,
squad)
2019-04-08 07:22:02 +02:00
if (attackChunk == SENTINEL_IMPASSABLE_CHUNK) then
2019-10-19 21:13:48 +02:00
squad.cycles = 30
cmd = map.wonderCommand
group.set_command(cmd)
2019-04-08 07:22:02 +02:00
return
2019-10-19 21:13:48 +02:00
else
positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
position = findMovementPosition(surface, targetPosition)
if not position then
squad.cycles = 30
cmd = map.wonderCommand
2019-10-20 22:45:43 +02:00
group.set_command(cmd)
2019-10-19 21:13:48 +02:00
return
else
targetPosition.x = position.x
targetPosition.y = position.y
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) or
2019-10-20 22:45:43 +02:00
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
then
2019-10-19 21:13:48 +02:00
cmd = map.attackCommand
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
else
cmd = map.moveCommand
if squad.rabid or squad.kamikaze then
cmd.distraction = DEFINES_DISTRACTION_NONE
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
end
end
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if (nextAttackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
position2 = findMovementPosition(surface, targetPosition2)
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if position2 then
targetPosition.x = position2.x
targetPosition.y = position2.y
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if ((cmd ~= map.attackCommand) and
((getPlayerBaseGenerator(map, nextAttackChunk) ~= 0) or
2019-10-20 22:45:43 +02:00
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)))
then
2019-10-19 21:13:48 +02:00
cmd = map.attackCommand
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
end
end
end
2019-04-08 07:22:02 +02:00
end
2019-10-19 21:13:48 +02:00
if (attackDirection == 0) then
cmd = map.settleCommand
if squad.kamikaze then
2019-03-09 09:13:36 +02:00
cmd.distraction = DEFINES_DISTRACTION_NONE
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
2019-03-09 09:13:36 +02:00
2019-10-19 21:13:48 +02:00
squad.status = SQUAD_BUILDING
2019-10-19 21:13:48 +02:00
map.buildPositionTop.x = position.x - BASE_CLEAN_DISTANCE
map.buildPositionTop.y = position.y - BASE_CLEAN_DISTANCE
map.buildPositionBottom.x = position.x + BASE_CLEAN_DISTANCE
2019-10-20 22:45:43 +02:00
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
2019-03-09 09:13:36 +02:00
2019-10-19 21:13:48 +02:00
local entities = surface.find_entities_filtered(map.filteredEntitiesClearBuildingQuery)
for i=1,#entities do
local entity = entities[i]
if entity.valid and (entity.type ~= "cliff") then
entity.die()
end
end
2019-10-20 22:45:43 +02:00
squad.cycles = 400
2019-10-19 21:13:48 +02:00
group.set_command(cmd)
else
squad.cycles = 23
2019-10-20 22:45:43 +02:00
group.set_command(cmd)
2019-10-19 21:13:48 +02:00
end
2018-02-13 09:10:17 +02:00
end
end
2019-03-08 05:40:55 +02:00
local function attackMove(map, squad, natives, surface)
local targetPosition = map.position
local targetPosition2 = map.position2
2019-03-08 05:40:55 +02:00
local group = squad.group
local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
2019-10-19 21:13:48 +02:00
local attackScorer = ((squad.attackScoreFunction == ATTACK_SCORE_KAMIKAZE) and scoreAttackKamikazeLocation)
or scoreAttackLocation
local squadChunk = squad.chunk
if (squadChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (squadChunk ~= chunk) then
addMovementPenalty(squad, squadChunk)
end
2019-03-09 02:42:20 +02:00
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK)then
2019-03-08 05:40:55 +02:00
addSquadToChunk(map, chunk, squad)
end
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
local attackChunk, attackDirection, nextAttackChunk, nextAttackDirection = scoreNeighborsForAttack(map,
natives,
chunk,
getNeighborChunks(map, x, y),
attackScorer,
squad)
2019-10-19 21:13:48 +02:00
if (attackChunk == SENTINEL_IMPASSABLE_CHUNK) then
squad.cycles = 30
cmd = map.wonderCommand
group.set_command(cmd)
return
else
positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
local position = findMovementPosition(surface, targetPosition)
if not position then
2019-10-19 21:13:48 +02:00
squad.cycles = 30
cmd = map.wonderCommand
group.set_command(cmd)
return
2019-10-19 21:13:48 +02:00
else
targetPosition.x = position.x
targetPosition.y = position.y
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) and
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
then
cmd = map.attackCommand
2019-10-19 21:13:48 +02:00
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
2019-03-08 05:40:55 +02:00
else
2019-10-19 21:13:48 +02:00
cmd = map.moveCommand
if squad.rabid or squad.frenzy then
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
2019-10-20 22:45:43 +02:00
end
end
2019-10-19 21:13:48 +02:00
end
2019-10-19 21:13:48 +02:00
local position2
2019-10-19 21:13:48 +02:00
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
cmd = map.attackCommand
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
end
end
2019-02-16 20:45:42 +02:00
end
2019-02-11 08:14:17 +02:00
2019-10-19 21:13:48 +02:00
squad.cycles = 23
group.set_command(cmd)
2018-02-13 09:10:17 +02:00
end
end
function squadAttack.squadsDispatch(map, surface, natives)
2016-08-26 00:20:06 +02:00
local squads = natives.squads
2019-02-11 08:14:17 +02:00
2019-03-09 08:23:00 +02:00
-- print("start dispatch")
2019-03-09 02:42:20 +02:00
-- local startIndex = natives.attackIndex
-- local maxSquadIndex = mMin(startIndex + ATTACK_QUEUE_SIZE, #squads)
-- for i=maxSquadIndex,startIndex,-1 do
2019-10-19 21:13:48 +02:00
local pending = natives.pendingAttack
local squadsLen = squads.len
local x = 0
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
for i=1,squadsLen do
2016-08-26 00:20:06 +02:00
local squad = squads[i]
local group = squad.group
2018-02-13 09:10:17 +02:00
if group and group.valid then
2019-03-07 08:12:39 +02:00
local memberCount = #group.members
2019-03-09 02:42:20 +02:00
if (memberCount == 0) then
2019-03-07 08:12:39 +02:00
removeSquadFromChunk(map, squad)
2019-05-16 07:11:43 +02:00
local deathGen = getDeathGenerator(map, squad.chunk)
local penalties = squad.penalties
2019-10-19 21:13:48 +02:00
for xc=1,mMin(#squad.penalties,5) do
2019-05-16 07:11:43 +02:00
addDeathGenerator(map,
2019-10-19 21:13:48 +02:00
penalties[xc].c,
deathGen * DIVISOR_DEATH_TRAIL_TABLE[xc])
2019-05-16 07:11:43 +02:00
end
group.destroy()
2019-03-09 02:42:20 +02:00
elseif (memberCount > AI_MAX_BITER_GROUP_SIZE) then
local members = group.members
unitGroupUtils.recycleBiters(natives, members)
2019-03-07 08:12:39 +02:00
removeSquadFromChunk(map, squad)
2019-03-09 02:42:20 +02:00
group.destroy()
else
local status = squad.status
local cycles = squad.cycles
2019-03-08 05:40:55 +02:00
local groupState = group.state
2019-03-07 08:12:39 +02:00
if (status == SQUAD_RAIDING) then
2019-10-19 21:13:48 +02:00
x = x + 1
squads[x] = squad
2019-03-08 05:40:55 +02:00
if (groupState == DEFINES_GROUP_FINISHED) or
2019-10-19 21:13:48 +02:00
(groupState == DEFINES_GROUP_GATHERING) or
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
2019-03-08 05:40:55 +02:00
then
attackMove(map, squad, natives, surface)
2019-10-19 21:13:48 +02:00
else
local chunk = getChunkByPosition(map, group.position)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad)
end
2019-03-08 05:40:55 +02:00
end
2019-03-07 08:12:39 +02:00
elseif (status == SQUAD_SETTLING) then
2019-10-20 22:45:43 +02:00
x = x + 1
2019-10-19 21:13:48 +02:00
squads[x] = squad
2019-03-09 09:13:36 +02:00
if (groupState == DEFINES_GROUP_FINISHED) or
2019-10-19 21:13:48 +02:00
(groupState == DEFINES_GROUP_GATHERING) or
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
2019-03-09 09:13:36 +02:00
then
settleMove(map, squad, natives, surface)
2019-10-19 21:13:48 +02:00
else
local chunk = getChunkByPosition(map, group.position)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad)
end
2019-03-09 09:13:36 +02:00
end
2019-10-20 22:45:43 +02:00
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
2019-03-07 08:12:39 +02:00
elseif (status == SQUAD_BUILDING) then
removeSquadFromChunk(map, squad)
natives.building[#natives.building+1] = squad
2019-03-09 02:42:20 +02:00
elseif (status == SQUAD_GUARDING) then
2019-10-19 21:13:48 +02:00
pending.len = pending.len + 1
pending[pending.len] = squad
else
2019-10-20 22:45:43 +02:00
x = x + 1
2019-10-19 21:13:48 +02:00
squads[x] = squad
2019-03-07 08:12:39 +02:00
end
if (cycles > 0) then
squad.cycles = cycles - 1
end
end
2019-03-07 08:12:39 +02:00
else
removeSquadFromChunk(map, squad)
end
end
2019-03-09 02:42:20 +02:00
2019-10-19 21:13:48 +02:00
squads.len = x
2019-10-20 22:45:43 +02:00
2019-03-09 08:23:00 +02:00
-- print("end dispatch")
2019-03-09 02:42:20 +02:00
-- if (maxSquadIndex >= #squads) then
-- natives.attackIndex = 1
-- else
-- natives.attackIndex = maxSquadIndex + 1
-- end
end
2019-10-19 21:13:48 +02:00
2019-03-08 05:40:55 +02:00
function squadAttack.squadsBeginAttack(natives)
local pending = natives.pendingAttack
local squads = natives.squads
2019-10-19 21:13:48 +02:00
local pendingLen = pending.len
local x = 0
2019-10-20 22:45:43 +02:00
2019-10-19 21:13:48 +02:00
for i=1,pendingLen do
local squad = pending[i]
2019-03-09 02:42:20 +02:00
local group = squad.group
2019-03-07 08:12:39 +02:00
if group and group.valid then
2019-10-20 22:45:43 +02:00
local groupState = group.state
if -- (groupState ~= DEFINES_GROUP_GATHERING) and
(groupState ~= DEFINES_GROUP_FINISHED) and (squad.cycles ~= 0) then
squad.cycles = squad.cycles - 1
2019-10-19 21:13:48 +02:00
x = x + 1
2019-10-20 22:45:43 +02:00
pending[x] = squad
2019-10-19 21:13:48 +02:00
else
local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
if not squad.kamikaze then
squad.kamikaze = (mRandom() < kamikazeThreshold)
end
if squad.settlers then
squad.status = SQUAD_SETTLING
2019-10-19 21:13:48 +02:00
squads.len = squads.len + 1
squads[squads.len] = squad
else
if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE
end
squad.status = SQUAD_RAIDING
2019-10-19 21:13:48 +02:00
squads.len = squads.len + 1
squads[squads.len] = squad
2019-02-11 08:14:17 +02:00
end
2019-10-20 22:45:43 +02:00
end
2019-03-07 08:12:39 +02:00
end
end
2019-10-19 21:13:48 +02:00
pending.len = x
end
2019-02-16 06:17:30 +02:00
squadAttackG = squadAttack
return squadAttack