2017-06-13 05:16:43 +02:00
|
|
|
local squadAttack = {}
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imports
|
2016-08-18 07:55:08 +02:00
|
|
|
|
|
|
|
local constants = require("Constants")
|
|
|
|
local mapUtils = require("MapUtils")
|
|
|
|
local unitGroupUtils = require("UnitGroupUtils")
|
2016-08-27 08:44:17 +02:00
|
|
|
local playerUtils = require("PlayerUtils")
|
2017-06-13 05:16:43 +02:00
|
|
|
local movementUtils = require("MovementUtils")
|
2017-06-16 03:30:26 +02:00
|
|
|
local mathUtils = require("MathUtils")
|
2017-11-21 09:27:03 +02:00
|
|
|
local chunkUtils = require("ChunkUtils")
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- constants
|
2017-05-14 00:32:16 +02:00
|
|
|
|
2016-08-20 04:52:27 +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
|
2016-08-20 04:52:27 +02:00
|
|
|
|
|
|
|
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
|
|
|
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
|
|
|
|
2017-11-21 09:27:03 +02:00
|
|
|
local CHUNK_SIZE = constants.CHUNK_SIZE
|
2016-08-20 04:52:27 +02:00
|
|
|
|
2017-06-11 02:59:06 +02:00
|
|
|
local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER
|
|
|
|
|
2017-05-28 06:50:37 +02:00
|
|
|
local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area
|
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
|
|
|
|
local DEFINES_GROUP_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
|
|
|
|
local DEFINES_GROUP_ATTACKING_TARGET = defines.group_state.attacking_target
|
|
|
|
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
|
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imported functions
|
|
|
|
|
2017-07-01 06:36:23 +02:00
|
|
|
local mRandom = math.random
|
|
|
|
|
2017-06-16 03:30:26 +02:00
|
|
|
local findMovementPosition = movementUtils.findMovementPosition
|
2017-06-13 05:16:43 +02:00
|
|
|
|
2017-06-08 02:57:24 +02:00
|
|
|
local getNeighborChunks = mapUtils.getNeighborChunks
|
2016-08-28 02:57:20 +02:00
|
|
|
local getChunkByPosition = mapUtils.getChunkByPosition
|
2017-06-16 03:30:26 +02:00
|
|
|
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
|
2016-08-27 08:44:17 +02:00
|
|
|
|
2017-06-16 03:30:26 +02:00
|
|
|
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
2016-09-14 19:12:29 +02:00
|
|
|
|
2016-08-27 08:44:17 +02:00
|
|
|
local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPosition
|
2017-11-21 09:27:03 +02:00
|
|
|
local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator
|
|
|
|
|
|
|
|
local positionToChunkXY = mapUtils.positionToChunkXY
|
2016-08-27 08:44:17 +02:00
|
|
|
|
2017-11-21 09:27:03 +02:00
|
|
|
local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- module code
|
|
|
|
|
2017-06-11 02:59:06 +02:00
|
|
|
local function scoreAttackLocation(squad, neighborChunk)
|
2017-06-24 20:41:57 +02:00
|
|
|
local damage = (2*neighborChunk[MOVEMENT_PHEROMONE]) + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
2017-12-21 05:50:36 +02:00
|
|
|
return damage - lookupMovementPenalty(squad, neighborChunk)
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
2017-06-13 05:16:43 +02:00
|
|
|
function squadAttack.squadsAttack(regionMap, surface, natives)
|
2016-08-26 00:20:06 +02:00
|
|
|
local squads = natives.squads
|
2016-09-14 19:12:29 +02:00
|
|
|
local attackPosition
|
|
|
|
local attackCmd
|
2017-05-27 02:58:33 +02:00
|
|
|
|
2016-09-14 19:12:29 +02:00
|
|
|
if (#squads > 0) then
|
2017-06-16 03:30:26 +02:00
|
|
|
attackPosition = regionMap.position
|
2017-05-28 06:50:37 +02:00
|
|
|
attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA,
|
2016-09-14 19:12:29 +02:00
|
|
|
destination = attackPosition,
|
2017-11-21 09:27:03 +02:00
|
|
|
radius = CHUNK_SIZE,
|
2017-05-27 02:58:33 +02:00
|
|
|
distraction = DEFINES_DISTRACTION_BY_ENEMY }
|
2016-09-14 19:12:29 +02:00
|
|
|
end
|
2017-06-01 09:03:07 +02:00
|
|
|
|
2016-08-26 00:20:06 +02:00
|
|
|
for i=1,#squads do
|
|
|
|
local squad = squads[i]
|
2016-08-18 07:55:08 +02:00
|
|
|
local group = squad.group
|
2017-05-24 08:46:23 +02:00
|
|
|
if group.valid and (squad.status == SQUAD_RAIDING) then
|
|
|
|
local groupState = group.state
|
2017-05-27 02:58:33 +02:00
|
|
|
if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles == 0)) then
|
|
|
|
local groupPosition = group.position
|
2017-12-29 07:38:10 +02:00
|
|
|
local chunk = getChunkByPosition(regionMap, groupPosition)
|
2017-11-21 09:27:03 +02:00
|
|
|
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
2017-06-11 02:59:06 +02:00
|
|
|
local attackChunk, attackDirection = scoreNeighborsForAttack(chunk,
|
2017-12-29 07:38:10 +02:00
|
|
|
getNeighborChunks(regionMap, chunk.x, chunk.y),
|
2017-06-11 02:59:06 +02:00
|
|
|
scoreAttackLocation,
|
|
|
|
squad)
|
2017-12-21 05:50:36 +02:00
|
|
|
addMovementPenalty(natives, squad, chunk)
|
2017-11-21 09:27:03 +02:00
|
|
|
if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
|
|
|
local playerBaseGenerator = getPlayerBaseGenerator(regionMap, attackChunk)
|
|
|
|
if (playerBaseGenerator == 0) or ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then
|
2017-06-10 10:38:20 +02:00
|
|
|
|
2017-06-13 05:16:43 +02:00
|
|
|
squad.cycles = ((#squad.group.members > 80) and 6) or 4
|
2016-09-14 19:12:29 +02:00
|
|
|
|
2017-05-28 06:50:37 +02:00
|
|
|
local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)
|
|
|
|
squad.frenzy = moreFrenzy
|
2016-09-14 19:12:29 +02:00
|
|
|
|
|
|
|
if squad.rabid or squad.frenzy then
|
2017-05-27 02:58:33 +02:00
|
|
|
attackCmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
|
2016-09-14 19:12:29 +02:00
|
|
|
else
|
2017-05-27 02:58:33 +02:00
|
|
|
attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
|
2016-09-14 19:12:29 +02:00
|
|
|
end
|
2017-06-10 10:38:20 +02:00
|
|
|
|
2017-11-21 09:27:03 +02:00
|
|
|
local position = findMovementPosition(surface, positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.35))
|
2017-06-13 05:16:43 +02:00
|
|
|
if position then
|
|
|
|
attackPosition.x = position.x
|
|
|
|
attackPosition.y = position.y
|
2017-12-21 05:50:36 +02:00
|
|
|
|
2017-06-10 10:38:20 +02:00
|
|
|
group.set_command(attackCmd)
|
|
|
|
group.start_moving()
|
|
|
|
else
|
2018-01-01 07:49:36 +02:00
|
|
|
addMovementPenalty(natives, squad, attackChunk)
|
2017-06-10 10:38:20 +02:00
|
|
|
end
|
2016-09-14 19:12:29 +02:00
|
|
|
elseif not squad.frenzy and not squad.rabid and
|
2017-05-27 02:58:33 +02:00
|
|
|
((groupState == DEFINES_GROUP_ATTACKING_DISTRACTION) or (groupState == DEFINES_GROUP_ATTACKING_TARGET) or
|
2017-11-21 09:27:03 +02:00
|
|
|
(playerBaseGenerator ~= 0)) then
|
2016-10-15 02:00:18 +02:00
|
|
|
squad.frenzy = true
|
2017-05-27 02:58:33 +02:00
|
|
|
squad.frenzyPosition.x = groupPosition.x
|
|
|
|
squad.frenzyPosition.y = groupPosition.y
|
2016-09-14 19:12:29 +02:00
|
|
|
end
|
2016-11-04 01:51:35 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-08-18 07:55:08 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-13 05:16:43 +02:00
|
|
|
function squadAttack.squadsBeginAttack(natives, players)
|
2016-08-26 00:20:06 +02:00
|
|
|
local squads = natives.squads
|
|
|
|
for i=1,#squads do
|
|
|
|
local squad = squads[i]
|
2017-06-01 03:46:53 +02:00
|
|
|
local group = squad.group
|
|
|
|
if (squad.status == SQUAD_GUARDING) and group.valid then
|
|
|
|
local kamikazeThreshold = calculateKamikazeThreshold(squad, natives)
|
2017-12-29 07:38:10 +02:00
|
|
|
|
|
|
|
local groupPosition = group.position
|
2017-12-21 05:50:36 +02:00
|
|
|
if playersWithinProximityToPosition(players, groupPosition, 100) then
|
2016-09-14 19:12:29 +02:00
|
|
|
squad.frenzy = true
|
2017-06-01 03:46:53 +02:00
|
|
|
squad.frenzyPosition.x = groupPosition.x
|
|
|
|
squad.frenzyPosition.y = groupPosition.y
|
2016-09-14 19:12:29 +02:00
|
|
|
end
|
2017-05-14 00:32:16 +02:00
|
|
|
|
2017-12-21 05:50:36 +02:00
|
|
|
squad.kamikaze = mRandom() < kamikazeThreshold
|
|
|
|
squad.status = SQUAD_RAIDING
|
2016-10-15 02:00:18 +02:00
|
|
|
end
|
2016-08-18 07:55:08 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-13 05:16:43 +02:00
|
|
|
return squadAttack
|