2016-08-18 07:55:08 +02:00
|
|
|
local aiBuilding = {}
|
|
|
|
|
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")
|
|
|
|
local unitGroupUtils = require("UnitGroupUtils")
|
2016-08-27 08:44:17 +02:00
|
|
|
local neighborUtils = require("NeighborUtils")
|
2016-10-07 16:30:31 +02:00
|
|
|
package.path = "../?.lua;" .. package.path
|
|
|
|
local config = require("config")
|
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
|
2016-10-15 02:00:18 +02:00
|
|
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
2016-08-20 04:52:27 +02:00
|
|
|
|
2016-10-15 02:00:18 +02:00
|
|
|
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
2016-11-04 09:26:19 +02:00
|
|
|
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
|
2016-10-15 02:00:18 +02:00
|
|
|
|
2017-05-24 08:46:23 +02:00
|
|
|
local RALLY_TRIGGERED = constants.RALLY_TRIGGERED
|
|
|
|
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
2017-05-14 00:32:16 +02:00
|
|
|
|
2017-06-01 03:46:53 +02:00
|
|
|
local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE
|
2016-08-20 04:52:27 +02:00
|
|
|
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
|
|
|
|
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
|
|
|
|
|
2017-05-27 02:58:33 +02:00
|
|
|
local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE
|
|
|
|
|
|
|
|
local DEFINES_COMMAND_GROUP = defines.command.group
|
|
|
|
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
2017-01-20 07:58:36 +02:00
|
|
|
|
2017-05-28 06:50:37 +02:00
|
|
|
local NEST_COUNT = constants.NEST_COUNT
|
2017-05-12 06:50:06 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imported functions
|
|
|
|
|
2017-06-08 02:57:24 +02:00
|
|
|
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
local getNeighborChunks = mapUtils.getNeighborChunks
|
2017-01-20 07:58:36 +02:00
|
|
|
local getChunkByIndex = mapUtils.getChunkByIndex
|
2017-06-08 02:57:24 +02:00
|
|
|
local scoreNeighborsWithDirection = neighborUtils.scoreNeighborsWithDirection
|
2016-08-20 04:52:27 +02:00
|
|
|
local createSquad = unitGroupUtils.createSquad
|
2016-10-07 16:30:31 +02:00
|
|
|
local attackWaveScaling = config.attackWaveScaling
|
2016-08-20 04:52:27 +02:00
|
|
|
|
|
|
|
-- module code
|
2016-08-19 04:02:13 +02:00
|
|
|
|
2017-06-01 03:46:53 +02:00
|
|
|
local function attackWaveValidCandidate(chunk, natives, surface)
|
2016-10-07 16:30:31 +02:00
|
|
|
local total = 0;
|
|
|
|
|
2017-05-06 11:03:28 +02:00
|
|
|
if natives.attackUsePlayer then
|
2017-04-22 01:14:04 +02:00
|
|
|
local playerPheromone = chunk[PLAYER_PHEROMONE]
|
2017-06-01 03:46:53 +02:00
|
|
|
if (playerPheromone > natives.attackPlayerThreshold) then
|
2017-04-22 01:14:04 +02:00
|
|
|
total = total + chunk[PLAYER_PHEROMONE]
|
|
|
|
end
|
2016-10-07 16:30:31 +02:00
|
|
|
end
|
2017-05-06 11:03:28 +02:00
|
|
|
if natives.attackUsePollution then
|
2017-05-28 06:50:37 +02:00
|
|
|
total = total + surface.get_pollution(chunk)
|
2016-10-07 16:30:31 +02:00
|
|
|
end
|
|
|
|
|
2017-06-01 03:46:53 +02:00
|
|
|
return total > natives.attackWaveThreshold
|
2016-10-07 16:30:31 +02:00
|
|
|
end
|
|
|
|
|
2017-05-28 06:50:37 +02:00
|
|
|
local function scoreUnitGroupLocation(squad, neighborChunk, surface)
|
|
|
|
return surface.get_pollution(neighborChunk) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE]
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function validUnitGroupLocation(x, chunk, neighborChunk)
|
2017-06-01 03:46:53 +02:00
|
|
|
return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE] and (neighborChunk[NEST_COUNT] ~= 0)
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
2017-06-01 03:46:53 +02:00
|
|
|
function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick, tempNeighbors)
|
|
|
|
if (tick - chunk[RALLY_TRIGGERED] > INTERVAL_LOGIC) and (natives.points >= AI_VENGENCE_SQUAD_COST) then
|
2017-05-24 08:46:23 +02:00
|
|
|
chunk[RALLY_TRIGGERED] = tick
|
|
|
|
local cX = chunk.cX
|
|
|
|
local cY = chunk.cY
|
|
|
|
for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE do
|
|
|
|
for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE do
|
|
|
|
local rallyChunk = getChunkByIndex(regionMap, x, y)
|
2017-06-01 03:46:53 +02:00
|
|
|
if rallyChunk and (rallyChunk[NEST_COUNT] ~= 0) and (x ~= cX) and (y ~= cY) then
|
|
|
|
aiBuilding.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST, tempNeighbors)
|
|
|
|
if (natives.points < AI_VENGENCE_SQUAD_COST) then
|
|
|
|
return
|
|
|
|
end
|
2017-05-24 08:46:23 +02:00
|
|
|
end
|
2017-01-20 07:58:36 +02:00
|
|
|
end
|
|
|
|
end
|
2017-03-25 23:46:30 +02:00
|
|
|
end
|
2017-01-20 07:58:36 +02:00
|
|
|
end
|
|
|
|
|
2017-06-01 03:46:53 +02:00
|
|
|
function aiBuilding.formSquads(regionMap, surface, natives, chunk, cost, tempNeighbors)
|
|
|
|
local valid = ((cost == AI_VENGENCE_SQUAD_COST) or
|
|
|
|
((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface)))
|
|
|
|
|
|
|
|
if valid and (math.random() < natives.formSquadThreshold) then
|
|
|
|
|
2017-06-08 02:57:24 +02:00
|
|
|
local squadPath, squadDirection = scoreNeighborsWithDirection(chunk,
|
|
|
|
getNeighborChunks(regionMap, chunk.cX, chunk.cY, tempNeighbors),
|
|
|
|
validUnitGroupLocation,
|
|
|
|
scoreUnitGroupLocation,
|
|
|
|
nil,
|
|
|
|
surface,
|
|
|
|
false)
|
2017-06-01 03:46:53 +02:00
|
|
|
if squadPath then
|
2017-06-09 07:18:59 +02:00
|
|
|
local squadPosition = positionFromDirectionAndChunk(squadDirection, chunk, {x=0,y=0}, 0.98)
|
|
|
|
|
|
|
|
squadPosition = surface.find_non_colliding_position("biter-spawner",
|
|
|
|
squadPosition,
|
|
|
|
32,
|
|
|
|
4)
|
|
|
|
if squadPosition then
|
|
|
|
local squad = createSquad(squadPosition, surface, natives)
|
|
|
|
|
|
|
|
squad.rabid = math.random() < 0.03
|
|
|
|
|
|
|
|
local scaledWaveSize = attackWaveScaling(natives)
|
|
|
|
local foundUnits = surface.set_multi_command({ command = { type = DEFINES_COMMAND_GROUP,
|
|
|
|
group = squad.group,
|
|
|
|
distraction = DEFINES_DISTRACTION_NONE },
|
|
|
|
unit_count = scaledWaveSize,
|
|
|
|
unit_search_distance = TRIPLE_CHUNK_SIZE })
|
|
|
|
if (foundUnits > 0) then
|
|
|
|
natives.points = natives.points - cost
|
|
|
|
end
|
2016-10-07 16:30:31 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-19 04:02:13 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-09-08 22:02:23 +02:00
|
|
|
return aiBuilding
|