2019-02-15 20:17:30 -08:00
|
|
|
if (squadAttackG) then
|
|
|
|
return squadAttackG
|
|
|
|
end
|
2017-06-12 20:16:43 -07:00
|
|
|
local squadAttack = {}
|
2016-08-17 22:55:08 -07:00
|
|
|
|
2016-08-19 19:52:27 -07:00
|
|
|
-- imports
|
2016-08-17 22:55:08 -07:00
|
|
|
|
|
|
|
local constants = require("Constants")
|
|
|
|
local mapUtils = require("MapUtils")
|
|
|
|
local unitGroupUtils = require("UnitGroupUtils")
|
2017-06-12 20:16:43 -07:00
|
|
|
local movementUtils = require("MovementUtils")
|
2017-06-15 18:30:26 -07:00
|
|
|
local mathUtils = require("MathUtils")
|
2018-01-14 23:41:55 -08:00
|
|
|
local chunkPropertyUtils = require("ChunkPropertyUtils")
|
2018-02-16 17:44:19 -08:00
|
|
|
|
2016-08-19 19:52:27 -07:00
|
|
|
-- constants
|
2017-05-13 15:32:16 -07:00
|
|
|
|
2016-08-19 19:52:27 -07:00
|
|
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
2016-10-14 17:00:18 -07:00
|
|
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
|
|
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
2018-02-12 23:10:17 -08:00
|
|
|
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
|
2016-08-19 19:52:27 -07:00
|
|
|
|
2019-02-16 10:45:42 -08:00
|
|
|
local ATTACK_SCORE_KAMIKAZE = constants.ATTACK_SCORE_KAMIKAZE
|
|
|
|
|
2019-04-07 22:22:02 -07:00
|
|
|
local BASE_CLEAN_DISTANCE = constants.BASE_CLEAN_DISTANCE
|
|
|
|
|
2018-02-16 17:44:19 -08:00
|
|
|
local SQUAD_BUILDING = constants.SQUAD_BUILDING
|
|
|
|
|
2016-08-19 19:52:27 -07:00
|
|
|
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
2018-02-12 23:10:17 -08:00
|
|
|
local SQUAD_SETTLING = constants.SQUAD_SETTLING
|
2016-08-19 19:52:27 -07:00
|
|
|
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
2019-03-06 22:12:39 -08:00
|
|
|
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
|
|
|
|
|
|
|
local AI_MAX_BITER_GROUP_SIZE = constants.AI_MAX_BITER_GROUP_SIZE
|
2016-08-19 19:52:27 -07:00
|
|
|
|
2018-02-18 20:18:04 -08:00
|
|
|
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
|
|
|
|
|
2017-06-10 17:59:06 -07:00
|
|
|
local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER
|
|
|
|
|
2017-05-26 17:58:33 -07: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-06 17:06:50 -08:00
|
|
|
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
2017-05-26 17:58:33 -07:00
|
|
|
local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy
|
|
|
|
local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
|
|
|
|
|
2017-11-20 23:27:03 -08:00
|
|
|
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
|
|
|
|
|
2016-08-19 19:52:27 -07:00
|
|
|
-- imported functions
|
|
|
|
|
2017-06-30 21:36:23 -07:00
|
|
|
local mRandom = math.random
|
2019-03-06 22:12:39 -08:00
|
|
|
local tRemove = table.remove
|
2017-06-30 21:36:23 -07:00
|
|
|
|
2018-02-16 17:44:19 -08:00
|
|
|
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
|
|
|
|
|
2017-06-15 18:30:26 -07:00
|
|
|
local findMovementPosition = movementUtils.findMovementPosition
|
2017-06-12 20:16:43 -07:00
|
|
|
|
2019-03-06 22:12:39 -08:00
|
|
|
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
|
|
|
|
|
2018-02-18 20:18:04 -08:00
|
|
|
local getNestCount = chunkPropertyUtils.getNestCount
|
2018-02-16 19:31:29 -08:00
|
|
|
|
2017-06-07 17:57:24 -07:00
|
|
|
local getNeighborChunks = mapUtils.getNeighborChunks
|
2018-01-14 23:41:55 -08:00
|
|
|
local addSquadToChunk = chunkPropertyUtils.addSquadToChunk
|
2018-01-13 21:48:21 -08:00
|
|
|
local getChunkByXY = mapUtils.getChunkByXY
|
|
|
|
local positionToChunkXY = mapUtils.positionToChunkXY
|
2017-06-15 18:30:26 -07:00
|
|
|
local addMovementPenalty = movementUtils.addMovementPenalty
|
|
|
|
local lookupMovementPenalty = movementUtils.lookupMovementPenalty
|
2017-01-19 21:58:36 -08:00
|
|
|
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
|
2016-10-30 20:24:14 -07:00
|
|
|
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
2016-08-26 23:44:17 -07:00
|
|
|
|
2017-06-15 18:30:26 -07:00
|
|
|
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
2016-09-14 10:12:29 -07:00
|
|
|
|
2018-01-14 23:41:55 -08:00
|
|
|
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
|
2018-02-14 00:28:42 -08:00
|
|
|
local getResourceGenerator = chunkPropertyUtils.getResourceGenerator
|
2017-11-20 23:27:03 -08:00
|
|
|
|
|
|
|
local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack
|
2018-09-23 21:56:45 -07:00
|
|
|
local scoreNeighborsForSettling = movementUtils.scoreNeighborsForSettling
|
2016-08-17 22:55:08 -07:00
|
|
|
|
2016-08-19 19:52:27 -07:00
|
|
|
-- module code
|
|
|
|
|
2018-02-12 23:10:17 -08:00
|
|
|
local function scoreResourceLocation(squad, neighborChunk)
|
2019-02-10 22:14:17 -08:00
|
|
|
local settle = neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[RESOURCE_PHEROMONE]
|
2018-02-14 00:28:42 -08:00
|
|
|
return settle - lookupMovementPenalty(squad, neighborChunk) - (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
2018-02-12 23:10:17 -08:00
|
|
|
end
|
|
|
|
|
2018-02-18 20:18:04 -08:00
|
|
|
local function scoreSiegeLocation(squad, neighborChunk)
|
2019-02-10 22:14:17 -08:00
|
|
|
local settle = neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] + neighborChunk[RESOURCE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
2018-02-18 20:18:04 -08:00
|
|
|
return settle - lookupMovementPenalty(squad, neighborChunk)
|
|
|
|
end
|
|
|
|
|
2019-02-15 20:17:30 -08:00
|
|
|
local function scoreAttackLocation(natives, squad, neighborChunk)
|
2019-02-10 22:14:17 -08:00
|
|
|
local damage
|
|
|
|
|
|
|
|
if (neighborChunk[MOVEMENT_PHEROMONE] >= 0) then
|
|
|
|
damage = neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[BASE_PHEROMONE] ) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
|
|
|
else
|
|
|
|
damage = (neighborChunk[BASE_PHEROMONE] * (1 - (neighborChunk[MOVEMENT_PHEROMONE] / -natives.retreatThreshold))) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
|
|
|
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-20 19:50:36 -08:00
|
|
|
return damage - lookupMovementPenalty(squad, neighborChunk)
|
2016-08-26 23:44:17 -07:00
|
|
|
end
|
|
|
|
|
2019-02-10 22:14:17 -08:00
|
|
|
|
2019-03-08 23:13:36 -08:00
|
|
|
local function settleMove(map, squad, natives, surface)
|
|
|
|
local attackPosition = map.position
|
|
|
|
local group = squad.group
|
|
|
|
|
|
|
|
local groupPosition = group.position
|
|
|
|
local x, y = positionToChunkXY(groupPosition)
|
|
|
|
local chunk = getChunkByXY(map, x, y)
|
|
|
|
local scoreFunction = scoreResourceLocation
|
|
|
|
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
|
|
|
|
local attackChunk, attackDirection = scoreNeighborsForSettling(map,
|
|
|
|
chunk,
|
|
|
|
getNeighborChunks(map, x, y),
|
|
|
|
scoreFunction,
|
|
|
|
squad)
|
|
|
|
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
|
|
|
addSquadToChunk(map, chunk, squad)
|
|
|
|
end
|
2019-04-07 22:22:02 -07:00
|
|
|
|
|
|
|
local resourceGenerator = getResourceGenerator(map, chunk)
|
|
|
|
local distance = euclideanDistancePoints(groupPosition.x,
|
|
|
|
groupPosition.y,
|
|
|
|
squad.originPosition.x,
|
|
|
|
squad.originPosition.y)
|
|
|
|
|
|
|
|
local largeGroup = (#squad.group.members > 80)
|
|
|
|
local cmd
|
|
|
|
local position
|
|
|
|
|
|
|
|
if (distance >= squad.maxDistance) or
|
|
|
|
((resourceGenerator ~= 0) and (getNestCount(map, chunk) == 0))
|
|
|
|
then
|
|
|
|
if not ((group.state == DEFINES_GROUP_FINISHED) or ((group.state == DEFINES_GROUP_GATHERING) and (squad.cycles <= 0))) then
|
|
|
|
-- if (group.state ~= DEFINES_GROUP_FINISHED) then
|
|
|
|
return
|
|
|
|
end
|
2019-03-08 23:13:36 -08:00
|
|
|
|
2019-04-07 22:22:02 -07:00
|
|
|
position = findMovementPosition(surface, groupPosition)
|
|
|
|
|
|
|
|
cmd = map.settleCommand
|
|
|
|
if squad.kamikaze then
|
|
|
|
cmd.distraction = DEFINES_DISTRACTION_NONE
|
|
|
|
else
|
|
|
|
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
|
|
|
|
end
|
|
|
|
|
|
|
|
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
|
|
|
|
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
|
|
|
|
|
|
|
|
squad.cycles = 400
|
|
|
|
|
|
|
|
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-08 23:13:36 -08:00
|
|
|
end
|
2019-04-07 22:22:02 -07:00
|
|
|
end
|
|
|
|
else
|
|
|
|
if (attackChunk == SENTINEL_IMPASSABLE_CHUNK) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) or
|
2019-03-08 23:13:36 -08:00
|
|
|
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
|
|
|
|
then
|
|
|
|
cmd = map.attackCommand
|
|
|
|
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
|
2019-04-07 22:22:02 -07:00
|
|
|
end
|
2019-03-08 23:13:36 -08:00
|
|
|
|
2019-04-07 22:22:02 -07:00
|
|
|
if squad.status ~= SQUAD_BUILDING then
|
|
|
|
position = findMovementPosition(surface,
|
|
|
|
positionFromDirectionAndChunk(attackDirection,
|
|
|
|
groupPosition,
|
|
|
|
attackPosition,
|
|
|
|
(largeGroup and 1.1) or 0.9))
|
|
|
|
end
|
|
|
|
|
|
|
|
if position then
|
|
|
|
squad.cycles = (largeGroup and 6) or 4
|
|
|
|
attackPosition.x = position.x
|
|
|
|
attackPosition.y = position.y
|
2019-03-08 23:13:36 -08:00
|
|
|
|
2019-04-07 22:22:02 -07:00
|
|
|
group.set_command(cmd)
|
|
|
|
group.start_moving()
|
2018-02-12 23:10:17 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2019-03-07 19:40:55 -08:00
|
|
|
local function attackMove(map, squad, natives, surface)
|
2019-03-08 22:23:00 -08:00
|
|
|
local attackPosition = map.position
|
2019-03-07 19:40:55 -08:00
|
|
|
local group = squad.group
|
|
|
|
|
|
|
|
local groupPosition = group.position
|
|
|
|
local x, y = positionToChunkXY(groupPosition)
|
|
|
|
local chunk = getChunkByXY(map, x, y)
|
|
|
|
local attackScorer = scoreAttackLocation
|
|
|
|
if (squad.attackScoreFunction == ATTACK_SCORE_KAMIKAZE) then
|
|
|
|
attackScorer = scoreAttackKamikazeLocation
|
|
|
|
end
|
2019-03-08 16:42:20 -08:00
|
|
|
if squad.chunk and (squad.chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (squad.chunk ~= chunk) then
|
2019-03-08 22:23:00 -08:00
|
|
|
addMovementPenalty(squad, squad.chunk)
|
2019-03-08 16:42:20 -08:00
|
|
|
end
|
2019-03-07 19:40:55 -08:00
|
|
|
local attackChunk, attackDirection = scoreNeighborsForAttack(map,
|
|
|
|
natives,
|
|
|
|
chunk,
|
|
|
|
getNeighborChunks(map, x, y),
|
|
|
|
attackScorer,
|
|
|
|
squad)
|
2019-03-08 16:42:20 -08:00
|
|
|
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK)then
|
2019-03-07 19:40:55 -08:00
|
|
|
addSquadToChunk(map, chunk, squad)
|
2019-03-08 22:23:00 -08:00
|
|
|
end
|
2019-03-07 19:40:55 -08:00
|
|
|
if (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
|
|
|
local playerBaseGenerator = getPlayerBaseGenerator(map, attackChunk)
|
|
|
|
local playerPheromone = attackChunk[PLAYER_PHEROMONE]
|
|
|
|
local cmd
|
|
|
|
local position
|
2019-03-08 16:42:20 -08:00
|
|
|
local largeGroup = (#squad.group.members > 80)
|
2019-03-07 19:40:55 -08:00
|
|
|
|
2019-03-08 23:13:36 -08:00
|
|
|
if (playerBaseGenerator == 0) and (playerPheromone < natives.attackPlayerThreshold) then
|
2019-03-07 19:40:55 -08:00
|
|
|
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
|
|
|
|
|
|
|
|
cmd = map.moveCommand
|
|
|
|
if squad.rabid or squad.frenzy then
|
|
|
|
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
|
|
|
|
else
|
|
|
|
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
|
|
|
|
end
|
|
|
|
else
|
|
|
|
cmd = map.attackCommand
|
|
|
|
|
|
|
|
if not squad.rabid then
|
|
|
|
squad.frenzy = true
|
|
|
|
squad.frenzyPosition.x = groupPosition.x
|
|
|
|
squad.frenzyPosition.y = groupPosition.y
|
|
|
|
end
|
2019-02-16 10:45:42 -08:00
|
|
|
end
|
2019-02-10 22:14:17 -08:00
|
|
|
|
2019-03-07 19:40:55 -08:00
|
|
|
position = findMovementPosition(surface,
|
|
|
|
positionFromDirectionAndChunk(attackDirection,
|
|
|
|
groupPosition,
|
|
|
|
attackPosition,
|
2019-03-08 22:23:00 -08:00
|
|
|
(largeGroup and 1.1) or 0.9))
|
2019-03-07 19:40:55 -08:00
|
|
|
|
|
|
|
if position then
|
2019-03-09 14:47:35 -08:00
|
|
|
squad.cycles = (largeGroup and 6) or 4
|
2019-03-07 19:40:55 -08:00
|
|
|
attackPosition.x = position.x
|
|
|
|
attackPosition.y = position.y
|
|
|
|
|
|
|
|
group.set_command(cmd)
|
|
|
|
group.start_moving()
|
|
|
|
end
|
2018-02-12 23:10:17 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function squadAttack.squadsDispatch(map, surface, natives)
|
2016-08-25 15:20:06 -07:00
|
|
|
local squads = natives.squads
|
2019-03-08 23:13:36 -08:00
|
|
|
-- local attackPosition = map.position
|
|
|
|
-- local attackCmd = map.attackAreaCommand
|
|
|
|
-- local settleCmd = map.settleCommand
|
2019-02-10 22:14:17 -08:00
|
|
|
|
2019-03-08 22:23:00 -08:00
|
|
|
-- print("start dispatch")
|
2019-03-08 16:42:20 -08:00
|
|
|
-- local startIndex = natives.attackIndex
|
|
|
|
|
|
|
|
-- local maxSquadIndex = mMin(startIndex + ATTACK_QUEUE_SIZE, #squads)
|
|
|
|
-- for i=maxSquadIndex,startIndex,-1 do
|
2019-03-06 22:12:39 -08:00
|
|
|
for i=#squads,1,-1 do
|
2016-08-25 15:20:06 -07:00
|
|
|
local squad = squads[i]
|
2016-08-17 22:55:08 -07:00
|
|
|
local group = squad.group
|
2018-02-12 23:10:17 -08:00
|
|
|
if group and group.valid then
|
2019-03-06 22:12:39 -08:00
|
|
|
|
|
|
|
local memberCount = #group.members
|
2019-03-08 16:42:20 -08:00
|
|
|
if (memberCount == 0) then
|
|
|
|
tRemove(squads, i)
|
2019-03-06 22:12:39 -08:00
|
|
|
removeSquadFromChunk(map, squad)
|
2019-03-08 16:42:20 -08:00
|
|
|
group.destroy()
|
|
|
|
elseif (memberCount > AI_MAX_BITER_GROUP_SIZE) then
|
|
|
|
local members = group.members
|
|
|
|
unitGroupUtils.recycleBiters(natives, members)
|
|
|
|
tRemove(squads, i)
|
2019-03-06 22:12:39 -08:00
|
|
|
removeSquadFromChunk(map, squad)
|
2019-03-08 16:42:20 -08:00
|
|
|
group.destroy()
|
|
|
|
else
|
|
|
|
local status = squad.status
|
|
|
|
local cycles = squad.cycles
|
2019-03-07 19:40:55 -08:00
|
|
|
local groupState = group.state
|
2019-03-06 22:12:39 -08:00
|
|
|
|
|
|
|
if (status == SQUAD_RAIDING) then
|
2019-03-07 19:40:55 -08:00
|
|
|
if (groupState == DEFINES_GROUP_FINISHED) or
|
|
|
|
(groupState == DEFINES_GROUP_GATHERING) or
|
|
|
|
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
|
|
|
|
then
|
|
|
|
attackMove(map, squad, natives, surface)
|
|
|
|
end
|
2019-03-06 22:12:39 -08:00
|
|
|
elseif (status == SQUAD_SETTLING) then
|
2019-03-08 23:13:36 -08:00
|
|
|
if (groupState == DEFINES_GROUP_FINISHED) or
|
|
|
|
(groupState == DEFINES_GROUP_GATHERING) or
|
2019-03-09 14:47:35 -08:00
|
|
|
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
|
2019-03-08 23:13:36 -08:00
|
|
|
then
|
|
|
|
settleMove(map, squad, natives, surface)
|
|
|
|
end
|
2019-03-08 22:23:00 -08:00
|
|
|
elseif (status == SQUAD_RETREATING) and (cycles <= 0) then
|
2019-03-06 22:12:39 -08:00
|
|
|
natives.pendingAttack[#natives.pendingAttack+1] = squad
|
|
|
|
squad.status = SQUAD_GUARDING
|
|
|
|
elseif (status == SQUAD_BUILDING) then
|
|
|
|
tRemove(squads, i)
|
|
|
|
removeSquadFromChunk(map, squad)
|
|
|
|
natives.building[#natives.building+1] = squad
|
2019-03-08 16:42:20 -08:00
|
|
|
elseif (status == SQUAD_GUARDING) then
|
|
|
|
tRemove(squads, i)
|
|
|
|
natives.pendingAttack[#natives.pendingAttack+1] = squad
|
2019-03-06 22:12:39 -08:00
|
|
|
end
|
|
|
|
if (cycles > 0) then
|
2019-03-08 16:42:20 -08:00
|
|
|
squad.cycles = cycles - 1
|
2019-03-06 22:12:39 -08:00
|
|
|
end
|
2019-03-08 16:42:20 -08:00
|
|
|
end
|
|
|
|
|
2019-03-06 22:12:39 -08:00
|
|
|
else
|
|
|
|
tRemove(squads, i)
|
|
|
|
removeSquadFromChunk(map, squad)
|
|
|
|
end
|
2016-08-17 22:55:08 -07:00
|
|
|
end
|
2019-03-08 16:42:20 -08:00
|
|
|
|
2019-03-08 22:23:00 -08:00
|
|
|
|
|
|
|
-- print("end dispatch")
|
2019-03-08 16:42:20 -08:00
|
|
|
-- if (maxSquadIndex >= #squads) then
|
|
|
|
-- natives.attackIndex = 1
|
|
|
|
-- else
|
|
|
|
-- natives.attackIndex = maxSquadIndex + 1
|
|
|
|
-- end
|
2016-08-17 22:55:08 -07:00
|
|
|
end
|
|
|
|
|
2019-03-07 19:40:55 -08:00
|
|
|
function squadAttack.squadsBeginAttack(natives)
|
2019-03-06 22:12:39 -08:00
|
|
|
local squads = natives.pendingAttack
|
2016-08-25 15:20:06 -07:00
|
|
|
for i=1,#squads do
|
|
|
|
local squad = squads[i]
|
2019-03-08 16:42:20 -08:00
|
|
|
local group = squad.group
|
2019-03-06 22:12:39 -08:00
|
|
|
if group and group.valid then
|
|
|
|
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
|
|
|
|
natives.squads[#natives.squads+1] = squad
|
2019-03-07 19:40:55 -08:00
|
|
|
else
|
2019-02-10 22:14:17 -08:00
|
|
|
if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then
|
2019-02-16 10:45:42 -08:00
|
|
|
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE
|
2019-02-10 22:14:17 -08:00
|
|
|
end
|
2019-03-06 22:12:39 -08:00
|
|
|
squad.status = SQUAD_RAIDING
|
|
|
|
natives.squads[#natives.squads+1] = squad
|
|
|
|
end
|
|
|
|
end
|
2016-08-17 22:55:08 -07:00
|
|
|
end
|
2019-03-06 22:12:39 -08:00
|
|
|
natives.pendingAttack = {}
|
2016-08-17 22:55:08 -07:00
|
|
|
end
|
|
|
|
|
2019-02-15 20:17:30 -08:00
|
|
|
squadAttackG = squadAttack
|
2017-06-12 20:16:43 -07:00
|
|
|
return squadAttack
|