2019-02-16 06:17:30 +02:00
|
|
|
if (aiAttackWaveG) then
|
|
|
|
return aiAttackWaveG
|
|
|
|
end
|
2017-06-13 05:16:43 +02:00
|
|
|
local aiAttackWave = {}
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imports
|
|
|
|
|
2016-08-19 04:02:13 +02:00
|
|
|
local constants = require("Constants")
|
|
|
|
local mapUtils = require("MapUtils")
|
2018-09-24 06:56:45 +02:00
|
|
|
local chunkPropertyUtils = require("ChunkPropertyUtils")
|
2016-08-19 04:02:13 +02:00
|
|
|
local unitGroupUtils = require("UnitGroupUtils")
|
2017-11-21 09:27:03 +02:00
|
|
|
local movementUtils = require("MovementUtils")
|
2018-02-14 10:28:42 +02:00
|
|
|
local mathUtils = require("MathUtils")
|
2019-02-28 04:53:59 +02:00
|
|
|
local config = require("__Rampant__/config")
|
2021-04-30 07:24:14 +02:00
|
|
|
local baseUtils = require("BaseUtils")
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- constants
|
|
|
|
|
2016-10-15 02:00:18 +02:00
|
|
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
2016-08-20 04:52:27 +02:00
|
|
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
2018-02-14 10:28:42 +02:00
|
|
|
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
|
2016-08-20 04:52:27 +02:00
|
|
|
|
2019-04-25 08:13:22 +02:00
|
|
|
local AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION = constants.AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION
|
|
|
|
local AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION = constants.AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION
|
|
|
|
|
2016-10-15 02:00:18 +02:00
|
|
|
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
2019-02-20 08:16:43 +02:00
|
|
|
local AI_SETTLER_COST = constants.AI_SETTLER_COST
|
2016-11-04 09:26:19 +02:00
|
|
|
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
|
2019-04-25 08:13:22 +02:00
|
|
|
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
|
2016-10-15 02:00:18 +02:00
|
|
|
|
2020-05-20 04:37:16 +02:00
|
|
|
local COOLDOWN_RALLY = constants.COOLDOWN_RALLY
|
2017-05-14 00:32:16 +02:00
|
|
|
|
2017-06-10 10:38:20 +02:00
|
|
|
local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
|
2016-08-20 04:52:27 +02:00
|
|
|
|
2017-11-21 09:27:03 +02:00
|
|
|
local CHUNK_SIZE = constants.CHUNK_SIZE
|
|
|
|
|
2017-05-27 02:58:33 +02:00
|
|
|
local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE
|
|
|
|
|
2019-02-06 08:25:43 +02:00
|
|
|
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
|
|
|
|
|
2018-02-10 09:57:04 +02:00
|
|
|
local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
|
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imported functions
|
|
|
|
|
2021-04-30 07:24:14 +02:00
|
|
|
local findNearbyBase = baseUtils.findNearbyBase
|
|
|
|
|
2019-04-25 08:13:22 +02:00
|
|
|
local randomTickEvent = mathUtils.randomTickEvent
|
|
|
|
|
2020-05-24 05:47:14 +02:00
|
|
|
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
|
|
|
|
|
2017-07-01 06:36:23 +02:00
|
|
|
local mRandom = math.random
|
|
|
|
|
2017-06-08 02:57:24 +02:00
|
|
|
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
|
|
|
|
2018-09-24 06:56:45 +02:00
|
|
|
local getPassable = chunkPropertyUtils.getPassable
|
|
|
|
local getNestCount = chunkPropertyUtils.getNestCount
|
2019-02-20 08:16:43 +02:00
|
|
|
local getRaidNestActiveness = chunkPropertyUtils.getRaidNestActiveness
|
|
|
|
local getNestActiveness = chunkPropertyUtils.getNestActiveness
|
2018-09-24 06:56:45 +02:00
|
|
|
local getRallyTick = chunkPropertyUtils.getRallyTick
|
|
|
|
local setRallyTick = chunkPropertyUtils.setRallyTick
|
2017-11-21 09:27:03 +02:00
|
|
|
|
2018-02-14 10:28:42 +02:00
|
|
|
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
local getNeighborChunks = mapUtils.getNeighborChunks
|
2017-12-29 07:38:10 +02:00
|
|
|
local getChunkByXY = mapUtils.getChunkByXY
|
2017-11-21 09:27:03 +02:00
|
|
|
local scoreNeighborsForFormation = movementUtils.scoreNeighborsForFormation
|
2018-02-14 10:28:42 +02:00
|
|
|
local scoreNeighborsForResource = movementUtils.scoreNeighborsForResource
|
2016-08-20 04:52:27 +02:00
|
|
|
local createSquad = unitGroupUtils.createSquad
|
2016-10-07 16:30:31 +02:00
|
|
|
local attackWaveScaling = config.attackWaveScaling
|
2018-02-14 10:28:42 +02:00
|
|
|
local settlerWaveScaling = config.settlerWaveScaling
|
2020-05-24 05:47:14 +02:00
|
|
|
local getDeathGenerator = chunkPropertyUtils.getDeathGenerator
|
2016-08-20 04:52:27 +02:00
|
|
|
|
|
|
|
-- module code
|
2016-08-19 04:02:13 +02:00
|
|
|
|
2021-02-20 09:31:36 +02:00
|
|
|
local function attackWaveValidCandidate(chunk, map)
|
2019-02-20 08:16:43 +02:00
|
|
|
local isValid = getNestActiveness(map, chunk)
|
2021-02-20 09:31:36 +02:00
|
|
|
if map.state == AI_STATE_RAIDING then
|
2019-02-20 08:16:43 +02:00
|
|
|
isValid = isValid + getRaidNestActiveness(map, chunk)
|
2017-06-10 10:38:20 +02:00
|
|
|
end
|
2019-02-20 08:16:43 +02:00
|
|
|
return (isValid > 0)
|
2016-10-07 16:30:31 +02:00
|
|
|
end
|
|
|
|
|
2020-05-24 05:47:14 +02:00
|
|
|
local function scoreSettlerLocation(map, neighborChunk)
|
2019-03-10 00:47:35 +02:00
|
|
|
return neighborChunk[RESOURCE_PHEROMONE] +
|
2020-05-24 05:47:14 +02:00
|
|
|
-getDeathGenerator(map, neighborChunk) +
|
2019-03-10 00:47:35 +02:00
|
|
|
-neighborChunk[PLAYER_PHEROMONE]
|
2018-02-14 10:28:42 +02:00
|
|
|
end
|
|
|
|
|
2020-05-24 05:47:14 +02:00
|
|
|
local function scoreSiegeSettlerLocation(map, neighborChunk)
|
2019-03-10 00:47:35 +02:00
|
|
|
return neighborChunk[RESOURCE_PHEROMONE] +
|
|
|
|
neighborChunk[BASE_PHEROMONE] +
|
2020-05-24 05:47:14 +02:00
|
|
|
-getDeathGenerator(map, neighborChunk) +
|
2019-03-10 00:47:35 +02:00
|
|
|
-neighborChunk[PLAYER_PHEROMONE]
|
2019-02-06 08:25:43 +02:00
|
|
|
end
|
|
|
|
|
2020-05-24 05:47:14 +02:00
|
|
|
local function scoreUnitGroupLocation(map, neighborChunk)
|
2019-03-10 00:47:35 +02:00
|
|
|
return neighborChunk[PLAYER_PHEROMONE] +
|
2020-05-24 05:47:14 +02:00
|
|
|
-getDeathGenerator(map, neighborChunk) +
|
2019-03-10 00:47:35 +02:00
|
|
|
neighborChunk[BASE_PHEROMONE]
|
2019-02-06 08:25:43 +02:00
|
|
|
end
|
|
|
|
|
2019-03-10 00:47:35 +02:00
|
|
|
local function validSiegeSettlerLocation(map, neighborChunk)
|
|
|
|
return (getPassable(map, neighborChunk) == CHUNK_ALL_DIRECTIONS) and
|
|
|
|
(getNestCount(map, neighborChunk) == 0)
|
|
|
|
end
|
2019-02-06 08:25:43 +02:00
|
|
|
|
2018-02-14 10:28:42 +02:00
|
|
|
local function validSettlerLocation(map, chunk, neighborChunk)
|
|
|
|
local chunkResource = chunk[RESOURCE_PHEROMONE]
|
2019-03-10 00:47:35 +02:00
|
|
|
return (getPassable(map, neighborChunk) == CHUNK_ALL_DIRECTIONS) and
|
|
|
|
(getNestCount(map, neighborChunk) == 0) and
|
2021-04-30 07:24:14 +02:00
|
|
|
(neighborChunk[RESOURCE_PHEROMONE] >= chunkResource)
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
2018-01-14 07:48:21 +02:00
|
|
|
local function validUnitGroupLocation(map, neighborChunk)
|
2019-03-10 00:47:35 +02:00
|
|
|
return getPassable(map, neighborChunk) == CHUNK_ALL_DIRECTIONS and
|
|
|
|
(getNestCount(map, neighborChunk) == 0)
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
2020-05-20 04:37:16 +02:00
|
|
|
local function visitPattern(o, cX, cY, distance)
|
|
|
|
local startX
|
|
|
|
local endX
|
|
|
|
local stepX
|
|
|
|
local startY
|
|
|
|
local endY
|
|
|
|
local stepY
|
|
|
|
if (o == 0) then
|
2021-02-14 06:49:54 +02:00
|
|
|
startX = cX - distance
|
|
|
|
endX = cX + distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepX = 32
|
2021-02-14 06:49:54 +02:00
|
|
|
startY = cY - distance
|
|
|
|
endY = cY + distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepY = 32
|
|
|
|
elseif (o == 1) then
|
2021-02-14 06:49:54 +02:00
|
|
|
startX = cX + distance
|
|
|
|
endX = cX - distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepX = -32
|
2021-02-14 06:49:54 +02:00
|
|
|
startY = cY + distance
|
|
|
|
endY = cY - distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepY = -32
|
|
|
|
elseif (o == 2) then
|
2021-02-14 06:49:54 +02:00
|
|
|
startX = cX - distance
|
|
|
|
endX = cX + distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepX = 32
|
2021-02-14 06:49:54 +02:00
|
|
|
startY = cY + distance
|
|
|
|
endY = cY - distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepY = -32
|
|
|
|
elseif (o == 3) then
|
2021-02-14 06:49:54 +02:00
|
|
|
startX = cX + distance
|
|
|
|
endX = cX - distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepX = -32
|
2021-02-14 06:49:54 +02:00
|
|
|
startY = cY - distance
|
|
|
|
endY = cY + distance
|
2020-05-20 04:37:16 +02:00
|
|
|
stepY = 32
|
2017-03-25 23:46:30 +02:00
|
|
|
end
|
2020-05-20 04:37:16 +02:00
|
|
|
return startX, endX, stepX, startY, endY, stepY
|
2017-01-20 07:58:36 +02:00
|
|
|
end
|
|
|
|
|
2021-02-14 06:49:54 +02:00
|
|
|
function aiAttackWave.rallyUnits(chunk, map, tick)
|
2021-02-20 09:31:36 +02:00
|
|
|
if ((tick - getRallyTick(map, chunk) > COOLDOWN_RALLY) and (map.points >= AI_VENGENCE_SQUAD_COST)) then
|
2020-05-20 04:37:16 +02:00
|
|
|
setRallyTick(map, chunk, tick)
|
2019-12-07 07:57:20 +02:00
|
|
|
local cX = chunk.x
|
|
|
|
local cY = chunk.y
|
2020-05-20 04:37:16 +02:00
|
|
|
local startX, endX, stepX, startY, endY, stepY = visitPattern(tick % 4, cX, cY, RALLY_CRY_DISTANCE)
|
2021-02-20 09:31:36 +02:00
|
|
|
local vengenceQueue = map.vengenceQueue
|
2020-05-20 04:37:16 +02:00
|
|
|
for x=startX, endX, stepX do
|
|
|
|
for y=startY, endY, stepY do
|
2019-12-07 07:57:20 +02:00
|
|
|
if (x ~= cX) and (y ~= cY) then
|
|
|
|
local rallyChunk = getChunkByXY(map, x, y)
|
2020-05-15 22:51:38 +02:00
|
|
|
if (rallyChunk ~= -1) and (getNestCount(map, rallyChunk) > 0) then
|
2020-05-20 04:37:16 +02:00
|
|
|
local count = vengenceQueue[rallyChunk]
|
|
|
|
if not count then
|
|
|
|
count = 0
|
|
|
|
vengenceQueue[rallyChunk] = count
|
2019-12-07 07:57:20 +02:00
|
|
|
end
|
2020-05-20 04:37:16 +02:00
|
|
|
vengenceQueue[rallyChunk] = count + 1
|
2019-12-07 07:57:20 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-20 04:37:16 +02:00
|
|
|
return true
|
2018-02-17 05:31:29 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-20 07:41:30 +02:00
|
|
|
function aiAttackWave.formSettlers(map, chunk)
|
2021-02-20 09:31:36 +02:00
|
|
|
local universe = map.universe
|
|
|
|
if (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) and
|
|
|
|
(mRandom() < universe.formSquadThreshold) and
|
|
|
|
((map.points - AI_SETTLER_COST) > 0)
|
2020-05-22 21:43:44 +02:00
|
|
|
then
|
2021-02-20 07:41:30 +02:00
|
|
|
local surface = map.surface
|
2019-02-06 08:25:43 +02:00
|
|
|
local squadPath, squadDirection
|
2021-02-20 09:31:36 +02:00
|
|
|
if (map.state == AI_STATE_SIEGE) then
|
2019-02-06 08:25:43 +02:00
|
|
|
squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
|
|
|
validSiegeSettlerLocation,
|
|
|
|
scoreSiegeSettlerLocation,
|
|
|
|
map)
|
|
|
|
else
|
|
|
|
squadPath, squadDirection = scoreNeighborsForResource(chunk,
|
|
|
|
getNeighborChunks(map, chunk.x, chunk.y),
|
|
|
|
validSettlerLocation,
|
|
|
|
scoreSettlerLocation,
|
|
|
|
map)
|
|
|
|
end
|
|
|
|
|
2020-05-20 04:37:16 +02:00
|
|
|
if (squadPath ~= -1) then
|
2019-10-14 07:49:52 +02:00
|
|
|
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
|
|
|
|
positionFromDirectionAndChunk(squadDirection,
|
|
|
|
chunk,
|
2021-02-20 22:44:52 +02:00
|
|
|
universe.position,
|
2019-10-14 07:49:52 +02:00
|
|
|
0.98),
|
|
|
|
CHUNK_SIZE,
|
|
|
|
4,
|
2019-03-06 08:18:03 +02:00
|
|
|
true)
|
2019-10-14 07:49:52 +02:00
|
|
|
if squadPosition then
|
|
|
|
local squad = createSquad(squadPosition, surface, nil, true)
|
2018-02-14 10:28:42 +02:00
|
|
|
|
2021-02-20 09:31:36 +02:00
|
|
|
squad.maxDistance = gaussianRandomRange(universe.expansionMaxDistance * 0.5,
|
|
|
|
universe.expansionMaxDistanceDerivation,
|
2019-10-14 07:49:52 +02:00
|
|
|
10,
|
2021-02-20 09:31:36 +02:00
|
|
|
universe.expansionMaxDistance)
|
2019-02-06 08:25:43 +02:00
|
|
|
|
2021-02-20 09:31:36 +02:00
|
|
|
local scaledWaveSize = settlerWaveScaling(universe)
|
2021-02-20 22:44:52 +02:00
|
|
|
universe.formGroupCommand.group = squad.group
|
|
|
|
universe.formCommand.unit_count = scaledWaveSize
|
|
|
|
local foundUnits = surface.set_multi_command(universe.formCommand)
|
2019-10-14 07:49:52 +02:00
|
|
|
if (foundUnits > 0) then
|
2021-05-01 06:25:55 +02:00
|
|
|
-- if universe.NEW_ENEMIES then
|
|
|
|
-- squad.base = findNearbyBase(map, chunk)
|
|
|
|
-- end
|
2021-02-20 22:44:52 +02:00
|
|
|
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, universe)
|
2021-02-20 09:31:36 +02:00
|
|
|
universe.builderCount = universe.builderCount + 1
|
|
|
|
map.points = map.points - AI_SETTLER_COST
|
2021-05-01 19:26:05 +02:00
|
|
|
if universe.aiPointsPrintSpendingToChat then
|
2021-04-30 15:15:29 +02:00
|
|
|
game.print(map.surface.name .. ": Points: -" .. AI_SETTLER_COST .. ". [Settler] Total: " .. string.format("%.2f", map.points) .. " [gps=" .. squadPosition.x .. "," .. squadPosition.y .. "]")
|
|
|
|
end
|
2021-02-20 09:31:36 +02:00
|
|
|
map.groupNumberToSquad[squad.groupNumber] = squad
|
2019-03-07 08:12:39 +02:00
|
|
|
else
|
|
|
|
if (squad.group.valid) then
|
|
|
|
squad.group.destroy()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-02-14 10:28:42 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-20 07:41:30 +02:00
|
|
|
function aiAttackWave.formVengenceSquad(map, chunk)
|
2021-02-20 09:31:36 +02:00
|
|
|
local universe = map.universe
|
|
|
|
if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) and
|
|
|
|
(mRandom() < universe.formSquadThreshold) and
|
|
|
|
((map.points - AI_VENGENCE_SQUAD_COST) > 0)
|
2020-05-23 23:29:56 +02:00
|
|
|
then
|
2021-02-20 07:41:30 +02:00
|
|
|
local surface = map.surface
|
2019-10-14 07:49:52 +02:00
|
|
|
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
|
|
|
validUnitGroupLocation,
|
|
|
|
scoreUnitGroupLocation,
|
|
|
|
map)
|
2020-05-15 22:51:38 +02:00
|
|
|
if (squadPath ~= -1) then
|
2019-10-14 07:49:52 +02:00
|
|
|
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
|
|
|
|
positionFromDirectionAndChunk(squadDirection,
|
|
|
|
chunk,
|
2021-02-20 22:44:52 +02:00
|
|
|
universe.position,
|
2019-10-14 07:49:52 +02:00
|
|
|
0.98),
|
|
|
|
CHUNK_SIZE,
|
|
|
|
4,
|
2019-03-06 08:18:03 +02:00
|
|
|
true)
|
2019-10-14 07:49:52 +02:00
|
|
|
if squadPosition then
|
|
|
|
local squad = createSquad(squadPosition, surface)
|
2019-02-06 08:25:43 +02:00
|
|
|
|
2019-10-14 07:49:52 +02:00
|
|
|
squad.rabid = mRandom() < 0.03
|
2019-02-20 08:16:43 +02:00
|
|
|
|
2021-02-20 09:31:36 +02:00
|
|
|
local scaledWaveSize = attackWaveScaling(universe)
|
2021-02-20 22:44:52 +02:00
|
|
|
universe.formGroupCommand.group = squad.group
|
|
|
|
universe.formCommand.unit_count = scaledWaveSize
|
|
|
|
local foundUnits = surface.set_multi_command(universe.formCommand)
|
2019-10-14 07:49:52 +02:00
|
|
|
if (foundUnits > 0) then
|
2021-05-01 06:25:55 +02:00
|
|
|
-- if universe.NEW_ENEMIES then
|
|
|
|
-- squad.base = findNearbyBase(map, chunk)
|
|
|
|
-- end
|
2021-02-20 22:44:52 +02:00
|
|
|
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, universe)
|
2021-02-20 09:31:36 +02:00
|
|
|
map.groupNumberToSquad[squad.groupNumber] = squad
|
|
|
|
universe.squadCount = universe.squadCount + 1
|
|
|
|
map.points = map.points - AI_VENGENCE_SQUAD_COST
|
2021-05-01 19:26:05 +02:00
|
|
|
if universe.aiPointsPrintSpendingToChat then
|
2021-04-30 15:15:29 +02:00
|
|
|
game.print(map.surface.name .. ": Points: -" .. AI_VENGENCE_SQUAD_COST .. ". [Vengence] Total: " .. string.format("%.2f", map.points) .. " [gps=" .. squadPosition.x .. "," .. squadPosition.y .. "]")
|
|
|
|
end
|
2019-03-07 08:12:39 +02:00
|
|
|
else
|
|
|
|
if (squad.group.valid) then
|
|
|
|
squad.group.destroy()
|
|
|
|
end
|
2019-10-14 07:49:52 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-02-20 08:16:43 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-20 07:41:30 +02:00
|
|
|
function aiAttackWave.formSquads(map, chunk, tick)
|
2021-02-20 09:31:36 +02:00
|
|
|
local universe = map.universe
|
|
|
|
if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) and
|
|
|
|
attackWaveValidCandidate(chunk, map) and
|
|
|
|
(mRandom() < universe.formSquadThreshold) and
|
|
|
|
((map.points - AI_SQUAD_COST) > 0)
|
2019-02-20 08:16:43 +02:00
|
|
|
then
|
2021-02-20 09:31:36 +02:00
|
|
|
local surface = map.surface
|
2019-10-14 07:49:52 +02:00
|
|
|
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
|
|
|
validUnitGroupLocation,
|
|
|
|
scoreUnitGroupLocation,
|
|
|
|
map)
|
2020-05-15 22:51:38 +02:00
|
|
|
if (squadPath ~= -1) then
|
2019-10-14 07:49:52 +02:00
|
|
|
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
|
|
|
|
positionFromDirectionAndChunk(squadDirection,
|
|
|
|
chunk,
|
2021-02-20 22:44:52 +02:00
|
|
|
universe.position,
|
2019-10-14 07:49:52 +02:00
|
|
|
0.98),
|
|
|
|
CHUNK_SIZE,
|
|
|
|
4,
|
2019-03-06 08:18:03 +02:00
|
|
|
true)
|
2019-10-14 07:49:52 +02:00
|
|
|
if squadPosition then
|
|
|
|
local squad = createSquad(squadPosition, surface)
|
2019-02-06 08:25:43 +02:00
|
|
|
|
2019-10-14 07:49:52 +02:00
|
|
|
squad.rabid = mRandom() < 0.03
|
2017-06-09 07:18:59 +02:00
|
|
|
|
2021-02-20 09:31:36 +02:00
|
|
|
local scaledWaveSize = attackWaveScaling(universe)
|
2021-02-20 22:44:52 +02:00
|
|
|
universe.formGroupCommand.group = squad.group
|
|
|
|
universe.formCommand.unit_count = scaledWaveSize
|
|
|
|
local foundUnits = surface.set_multi_command(universe.formCommand)
|
2019-10-14 07:49:52 +02:00
|
|
|
if (foundUnits > 0) then
|
2021-05-01 06:25:55 +02:00
|
|
|
-- if universe.NEW_ENEMIES then
|
|
|
|
-- squad.base = findNearbyBase(map, chunk)
|
|
|
|
-- end
|
2021-02-20 22:44:52 +02:00
|
|
|
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, universe)
|
2021-02-20 09:31:36 +02:00
|
|
|
map.points = map.points - AI_SQUAD_COST
|
|
|
|
universe.squadCount = universe.squadCount + 1
|
|
|
|
map.groupNumberToSquad[squad.groupNumber] = squad
|
|
|
|
if tick and (map.state == AI_STATE_AGGRESSIVE) then
|
|
|
|
map.canAttackTick = randomTickEvent(tick,
|
2021-04-30 07:24:14 +02:00
|
|
|
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
|
|
|
|
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
|
2019-04-25 08:13:22 +02:00
|
|
|
end
|
2021-05-01 19:26:05 +02:00
|
|
|
if universe.aiPointsPrintSpendingToChat then
|
2021-04-30 15:15:29 +02:00
|
|
|
game.print(map.surface.name .. ": Points: -" .. AI_SQUAD_COST .. ". [Squad] Total: " .. string.format("%.2f", map.points) .. " [gps=" .. squadPosition.x .. "," .. squadPosition.y .. "]")
|
|
|
|
end
|
2019-03-07 08:12:39 +02:00
|
|
|
else
|
|
|
|
if (squad.group.valid) then
|
|
|
|
squad.group.destroy()
|
|
|
|
end
|
2019-10-14 07:49:52 +02:00
|
|
|
end
|
2019-03-07 08:12:39 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-19 04:02:13 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2019-02-20 08:16:43 +02:00
|
|
|
|
2019-02-16 06:17:30 +02:00
|
|
|
aiAttackWaveG = aiAttackWave
|
2017-06-13 05:16:43 +02:00
|
|
|
return aiAttackWave
|