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

403 lines
14 KiB
Lua
Raw Normal View History

2019-02-15 20:17:30 -08:00
if (squadAttackG) then
return squadAttackG
end
local squadAttack = {}
-- imports
local constants = require("Constants")
local mapUtils = require("MapUtils")
local movementUtils = require("MovementUtils")
local mathUtils = require("MathUtils")
local chunkPropertyUtils = require("ChunkPropertyUtils")
-- constants
2017-05-13 15:32:16 -07:00
local COMMAND_TIMEOUT = constants.COMMAND_TIMEOUT
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
2016-10-14 17:00:18 -07:00
local BASE_PHEROMONE = constants.BASE_PHEROMONE
2018-02-12 23:10:17 -08:00
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
2021-04-04 21:46:43 -07:00
local FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT
2020-05-23 14:29:56 -07:00
local SQUAD_BUILDING = constants.SQUAD_BUILDING
local SQUAD_RAIDING = constants.SQUAD_RAIDING
2018-02-12 23:10:17 -08:00
local SQUAD_SETTLING = constants.SQUAD_SETTLING
local SQUAD_GUARDING = constants.SQUAD_GUARDING
2019-03-06 22:12:39 -08:00
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
2017-06-10 17:59:06 -07:00
local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER
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
-- imported functions
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
local findMovementPosition = movementUtils.findMovementPosition
2019-03-06 22:12:39 -08:00
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
2019-05-15 22:11:43 -07:00
local addDeathGenerator = chunkPropertyUtils.addDeathGenerator
local getDeathGenerator = chunkPropertyUtils.getDeathGenerator
2019-03-06 22:12:39 -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
local addSquadToChunk = chunkPropertyUtils.addSquadToChunk
2018-01-13 21:48:21 -08:00
local getChunkByXY = mapUtils.getChunkByXY
local positionToChunkXY = mapUtils.positionToChunkXY
local addMovementPenalty = movementUtils.addMovementPenalty
local positionFromDirectionAndFlat = mapUtils.positionFromDirectionAndFlat
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
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
-- module code
2021-02-13 20:49:54 -08:00
local function scoreResourceLocationKamikaze(_, neighborChunk)
2020-05-23 20:47:14 -07:00
local settle = neighborChunk[RESOURCE_PHEROMONE]
return settle - (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
end
2021-02-13 20:49:54 -08:00
local function scoreSiegeLocationKamikaze(_, neighborChunk)
2020-05-23 20:47:14 -07:00
local settle = neighborChunk[BASE_PHEROMONE] +
neighborChunk[RESOURCE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2020-10-18 20:33:01 -07:00
2020-05-23 20:47:14 -07:00
return settle
end
2021-02-13 20:49:54 -08:00
local function scoreResourceLocation(map, neighborChunk)
2020-05-23 14:29:56 -07:00
local settle = -getDeathGenerator(map, neighborChunk) + neighborChunk[RESOURCE_PHEROMONE]
return settle - (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2018-02-12 23:10:17 -08:00
end
2021-02-13 20:49:54 -08:00
local function scoreSiegeLocation(map, neighborChunk)
2020-05-23 20:47:14 -07:00
local settle = -getDeathGenerator(map, neighborChunk) + neighborChunk[BASE_PHEROMONE] +
2020-05-23 14:29:56 -07:00
neighborChunk[RESOURCE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
2020-10-18 20:33:01 -07:00
return settle
end
2021-02-13 20:49:54 -08:00
local function scoreAttackLocation(map, neighborChunk)
2020-05-23 14:29:56 -07:00
local damage = -getDeathGenerator(map, neighborChunk) + neighborChunk[BASE_PHEROMONE] +
(neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
return damage
2019-02-10 22:14:17 -08:00
end
2021-02-13 20:49:54 -08:00
local function scoreAttackKamikazeLocation(_, neighborChunk)
local damage = neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
return damage
end
2021-02-19 21:41:30 -08:00
local function settleMove(map, squad)
local universe = map.universe
local targetPosition = universe.position
local targetPosition2 = universe.position2
2019-03-08 23:13:36 -08:00
local group = squad.group
2019-03-08 23:13:36 -08:00
local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
local scoreFunction = scoreResourceLocation
2021-02-19 23:31:36 -08:00
if (map.state == AI_STATE_SIEGE) then
2020-05-23 20:47:14 -07:00
if squad.kamikaze then
scoreFunction = scoreSiegeLocationKamikaze
else
scoreFunction = scoreSiegeLocation
end
elseif squad.kamikaze then
scoreFunction = scoreResourceLocationKamikaze
2019-03-08 23:13:36 -08:00
end
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, chunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
2020-05-15 13:51:38 -07:00
addSquadToChunk(map, chunk, squad)
2021-02-13 20:49:54 -08:00
addMovementPenalty(squad, chunk)
2019-04-07 22:22:02 -07:00
local distance = euclideanDistancePoints(groupPosition.x,
groupPosition.y,
squad.originPosition.x,
squad.originPosition.y)
local cmd
local position
2021-02-19 21:41:30 -08:00
local surface = map.surface
2020-05-16 15:34:54 -07:00
2019-10-19 12:13:48 -07:00
if (distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0))
2019-04-07 22:22:02 -07:00
then
position = findMovementPosition(surface, groupPosition)
if not position then
position = groupPosition
end
targetPosition.x = position.x
2020-05-16 15:34:54 -07:00
targetPosition.y = position.y
cmd = universe.settleCommand
2019-04-07 22:22:02 -07:00
if squad.kamikaze then
cmd.distraction = DEFINES_DISTRACTION_NONE
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
2019-04-07 22:22:02 -07:00
squad.status = SQUAD_BUILDING
2019-10-19 12:13:48 -07:00
group.set_command(cmd)
2019-04-07 22:22:02 -07:00
else
2021-02-13 20:49:54 -08:00
local attackChunk,
attackDirection,
nextAttackChunk,
nextAttackDirection = scoreNeighborsForSettling(map,
chunk,
getNeighborChunks(map, x, y),
scoreFunction)
2020-05-19 19:37:16 -07:00
2020-05-15 13:51:38 -07:00
if (attackChunk == -1) then
cmd = universe.wonderCommand
2019-10-19 12:13:48 -07:00
group.set_command(cmd)
2019-04-07 22:22:02 -07:00
return
2020-05-19 19:37:16 -07:00
elseif (attackDirection ~= 0) then
local attackPlayerThreshold = universe.attackPlayerThreshold
2020-05-16 15:34:54 -07:00
2020-05-19 19:37:16 -07:00
if (nextAttackChunk ~= -1) then
attackChunk = nextAttackChunk
positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
position = findMovementPosition(surface, targetPosition2)
2019-10-19 12:13:48 -07:00
else
2020-05-19 19:37:16 -07:00
positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
position = findMovementPosition(surface, targetPosition)
end
if position then
2019-10-19 12:13:48 -07:00
targetPosition.x = position.x
targetPosition.y = position.y
if nextAttackChunk then
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, nextAttackChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
else
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, attackChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
2020-05-23 14:29:56 -07:00
end
2020-05-19 19:37:16 -07:00
else
cmd = universe.wonderCommand
2020-05-19 19:37:16 -07:00
group.set_command(cmd)
return
2019-10-19 12:13:48 -07:00
end
2019-10-20 13:45:43 -07:00
2020-05-19 19:37:16 -07:00
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) or
(attackChunk[PLAYER_PHEROMONE] >= attackPlayerThreshold)
then
cmd = universe.attackCommand
2019-10-20 13:45:43 -07:00
2020-05-19 19:37:16 -07:00
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
else
cmd = universe.moveCommand
2020-05-19 19:37:16 -07:00
if squad.rabid or squad.kamikaze then
cmd.distraction = DEFINES_DISTRACTION_NONE
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
2019-10-19 12:13:48 -07:00
end
end
2020-05-19 19:37:16 -07:00
else
cmd = universe.settleCommand
cmd.destination.x = groupPosition.x
cmd.destination.y = groupPosition.y
2019-10-19 12:13:48 -07:00
if squad.kamikaze then
2019-03-08 23:13:36 -08:00
cmd.distraction = DEFINES_DISTRACTION_NONE
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
2019-03-08 23:13:36 -08:00
2020-10-18 20:33:01 -07:00
squad.status = SQUAD_BUILDING
2019-10-19 12:13:48 -07:00
end
2020-05-19 19:37:16 -07:00
group.set_command(cmd)
2018-02-12 23:10:17 -08:00
end
end
2021-02-19 21:41:30 -08:00
local function attackMove(map, squad)
2020-05-19 19:37:16 -07:00
local universe = map.universe
local targetPosition = universe.position
local targetPosition2 = universe.position2
2019-03-07 19:40:55 -08:00
local group = squad.group
2021-02-19 21:41:30 -08:00
local surface = map.surface
2020-05-19 19:37:16 -07:00
local position
2019-03-07 19:40:55 -08:00
local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
2020-05-16 22:06:55 -07:00
local attackScorer = scoreAttackLocation
if squad.kamikaze then
attackScorer = scoreAttackKamikazeLocation
end
local squadChunk = squad.chunk
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, squadChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
2020-05-15 13:51:38 -07:00
addSquadToChunk(map, chunk, squad)
2021-02-13 20:49:54 -08:00
addMovementPenalty(squad, chunk)
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
2021-02-13 20:49:54 -08:00
local attackChunk, attackDirection,
nextAttackChunk, nextAttackDirection = scoreNeighborsForAttack(map,
chunk,
getNeighborChunks(map, x, y),
attackScorer)
local cmd
2020-05-15 13:51:38 -07:00
if (attackChunk == -1) then
cmd = universe.wonderCommand
2019-10-19 12:13:48 -07:00
group.set_command(cmd)
return
2020-05-19 19:37:16 -07:00
elseif (nextAttackChunk ~= -1) then
attackChunk = nextAttackChunk
positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
position = findMovementPosition(surface, targetPosition2)
2019-10-19 12:13:48 -07:00
else
positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
2020-05-19 19:37:16 -07:00
position = findMovementPosition(surface, targetPosition)
end
2020-05-19 19:37:16 -07:00
if not position then
cmd = universe.wonderCommand
2020-05-19 19:37:16 -07:00
group.set_command(cmd)
return
else
targetPosition.x = position.x
targetPosition.y = position.y
if nextAttackChunk then
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, nextAttackChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
else
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, attackChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
2020-05-23 14:29:56 -07:00
end
2020-05-19 19:37:16 -07:00
end
2019-10-20 13:45:43 -07:00
2020-05-19 19:37:16 -07:00
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) and
(attackChunk[PLAYER_PHEROMONE] >= universe.attackPlayerThreshold)
2020-05-19 19:37:16 -07:00
then
cmd = universe.attackCommand
2020-05-19 19:37:16 -07:00
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
2019-10-19 12:13:48 -07:00
end
2020-05-19 19:37:16 -07:00
else
cmd = universe.moveCommand
2020-05-19 19:37:16 -07:00
if squad.rabid or squad.frenzy then
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
2019-02-16 10:45:42 -08:00
end
2018-02-12 23:10:17 -08:00
end
2020-05-19 19:37:16 -07:00
group.set_command(cmd)
2018-02-12 23:10:17 -08:00
end
2021-02-19 21:41:30 -08:00
local function buildMove(map, squad)
2020-05-16 22:06:55 -07:00
local group = squad.group
local universe = map.universe
local position = universe.position
2021-02-19 21:41:30 -08:00
local groupPosition = findMovementPosition(map.surface, group.position)
2020-05-16 22:06:55 -07:00
if not groupPosition then
groupPosition = group.position
end
2019-03-08 16:42:20 -08:00
2020-05-16 22:06:55 -07:00
position.x = groupPosition.x
position.y = groupPosition.y
2019-10-20 13:45:43 -07:00
group.set_command(universe.compoundSettleCommand)
end
function squadAttack.cleanSquads(map, tick)
2021-02-19 23:31:36 -08:00
local squads = map.groupNumberToSquad
local k = map.squadIterator
local squad
if not k then
k, squad = next(squads, k)
else
squad = squads[k]
end
2020-10-18 20:33:01 -07:00
if not k then
map.squadIterator = nil
2020-10-18 20:33:01 -07:00
if (table_size(squads) == 0) then
-- this is needed as the next command remembers the max length a table has been
2021-02-19 23:31:36 -08:00
map.groupNumberToSquad = {}
2020-10-18 20:33:01 -07:00
end
else
map.squadIterator = next(squads, k)
2020-10-18 20:33:01 -07:00
local group = squad.group
if not group.valid then
2021-04-04 21:46:43 -07:00
addDeathGenerator(map, squad.chunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
2020-10-18 20:33:01 -07:00
removeSquadFromChunk(map, squad)
if (map.regroupIterator == k) then
map.regroupIterator = nil
end
2021-02-19 23:31:36 -08:00
local universe = map.universe
2020-10-18 20:33:01 -07:00
if squad.settlers then
2021-02-19 23:31:36 -08:00
universe.builderCount = universe.builderCount - 1
2020-10-18 20:33:01 -07:00
else
2021-02-19 23:31:36 -08:00
universe.squadCount = universe.squadCount - 1
2020-10-18 20:33:01 -07:00
end
squads[k] = nil
elseif (group.state == 4) then
squadAttack.squadDispatch(map, squad, tick)
elseif (squad.commandTick and (squad.commandTick < tick)) then
local cmd = map.universe.wander2Command
squad.commandTick = tick + COMMAND_TIMEOUT
group.set_command(cmd)
group.start_moving()
2020-10-18 20:33:01 -07:00
end
end
end
function squadAttack.squadDispatch(map, squad, tick)
2020-05-16 22:06:55 -07:00
local group = squad.group
if group and group.valid then
2020-05-19 19:37:16 -07:00
local status = squad.status
if (status == SQUAD_RAIDING) then
squad.commandTick = tick + COMMAND_TIMEOUT
2021-02-19 21:41:30 -08:00
attackMove(map, squad)
2020-05-19 19:37:16 -07:00
elseif (status == SQUAD_SETTLING) then
squad.commandTick = tick + COMMAND_TIMEOUT
2021-02-19 21:41:30 -08:00
settleMove(map, squad)
2020-05-19 19:37:16 -07:00
elseif (status == SQUAD_RETREATING) then
squad.commandTick = tick + COMMAND_TIMEOUT
2020-05-19 19:37:16 -07:00
if squad.settlers then
squad.status = SQUAD_SETTLING
2021-02-19 21:41:30 -08:00
settleMove(map, squad)
2020-05-19 19:37:16 -07:00
else
squad.status = SQUAD_RAIDING
2021-02-19 21:41:30 -08:00
attackMove(map, squad)
2020-02-02 11:30:50 -08:00
end
2020-05-19 19:37:16 -07:00
elseif (status == SQUAD_BUILDING) then
squad.commandTick = tick + COMMAND_TIMEOUT
2020-05-16 22:06:55 -07:00
removeSquadFromChunk(map, squad)
2021-02-19 21:41:30 -08:00
buildMove(map, squad)
2020-05-19 19:37:16 -07:00
elseif (status == SQUAD_GUARDING) then
squad.commandTick = tick + COMMAND_TIMEOUT
2020-05-19 19:37:16 -07:00
if squad.settlers then
squad.status = SQUAD_SETTLING
2021-02-19 21:41:30 -08:00
settleMove(map, squad)
2020-05-19 19:37:16 -07:00
else
squad.status = SQUAD_RAIDING
2021-02-19 21:41:30 -08:00
attackMove(map, squad)
2019-10-20 13:45:43 -07:00
end
2021-02-13 20:49:54 -08:00
end
end
end
2019-02-15 20:17:30 -08:00
squadAttackG = squadAttack
return squadAttack