mirror of
https://github.com/veden/Rampant.git
synced 2025-01-14 02:23:01 +02:00
see changelog
This commit is contained in:
parent
e283fa400c
commit
76665ef603
@ -138,7 +138,7 @@ function upgrade.attempt(natives)
|
||||
end
|
||||
if (global.version < constants.VERSION_26) then
|
||||
|
||||
game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
|
||||
-- game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
|
||||
|
||||
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.16")
|
||||
global.version = constants.VERSION_26
|
||||
@ -323,6 +323,8 @@ function upgrade.attempt(natives)
|
||||
game.map_settings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
|
||||
game.map_settings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
|
||||
game.map_settings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
|
||||
|
||||
game.map_settings.max_failed_behavior_count = 3
|
||||
|
||||
for i=#natives.squads,1,-1 do
|
||||
natives.squads[i].penalties = {}
|
||||
|
@ -9,6 +9,9 @@ Date: 10. 13. 2019
|
||||
- Increased minimum unit count for a retreat from 3 to 6
|
||||
Optimizations:
|
||||
- Better object reuse for squad and pending attack, creating less garbage
|
||||
- Trimmed table creation where possible
|
||||
- Regrouping squads and builder clean up put onto separate intervals
|
||||
- Reusing chunk scanner tables
|
||||
Bugfixes:
|
||||
- Fixed old savegames penalties having nil chunk index
|
||||
- Fixed that mining a resource by hand unregister all remaining resource on a tile
|
||||
@ -16,7 +19,9 @@ Date: 10. 13. 2019
|
||||
- Fixed chunk scan and player building pheromone generator mismatch
|
||||
- Fixed ai credits being uncapped and accumulating more than Max Credits available for that evolution level
|
||||
- Fixed retreating squads being adding to squad set multiple times
|
||||
- Fixed retreating squads not waiting long enough to assemble all units before movement
|
||||
- Fixed spitter max projectile range could cause a spitter to attack but not hit a target
|
||||
- Fixed non retreating group formation not having a distraction modifier
|
||||
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 0.17.28
|
||||
|
56
control.lua
56
control.lua
@ -27,6 +27,8 @@ local INTERVAL_PLAYER_PROCESS = constants.INTERVAL_PLAYER_PROCESS
|
||||
local INTERVAL_MAP_PROCESS = constants.INTERVAL_MAP_PROCESS
|
||||
local INTERVAL_SCAN = constants.INTERVAL_SCAN
|
||||
local INTERVAL_SQUAD = constants.INTERVAL_SQUAD
|
||||
local INTERVAL_RESQUAD = constants.INTERVAL_RESQUAD
|
||||
local INTERVAL_BUILDERS = constants.INTERVAL_BUILDERS
|
||||
|
||||
local RECOVER_NEST_COST = constants.RECOVER_NEST_COST
|
||||
local RECOVER_WORM_COST = constants.RECOVER_WORM_COST
|
||||
@ -257,6 +259,11 @@ local function rebuildMap()
|
||||
SENTINEL_IMPASSABLE_CHUNK
|
||||
}
|
||||
|
||||
map.enemiesToSquad = {}
|
||||
map.enemiesToSquad.len = 0
|
||||
map.chunkRemovals = {}
|
||||
|
||||
map.emptySquadsOnChunk = {}
|
||||
map.position2Top = {0, 0}
|
||||
map.position2Bottom = {0, 0}
|
||||
--this is shared between two different queries
|
||||
@ -404,7 +411,9 @@ local function rebuildMap()
|
||||
|
||||
map.formGroupCommand = { type = DEFINES_COMMAND_GROUP,
|
||||
group = nil,
|
||||
distraction = DEFINES_DISTRACTION_NONE }
|
||||
distraction = DEFINES_DISTRACTION_ANYTHING,
|
||||
use_group_distraction = false
|
||||
}
|
||||
|
||||
map.formCommand = { command = map.formGroupCommand,
|
||||
unit_count = 0,
|
||||
@ -517,11 +526,10 @@ script.on_nth_tick(INTERVAL_PLAYER_PROCESS,
|
||||
function (event)
|
||||
|
||||
local gameRef = game
|
||||
local surface = gameRef.surfaces[natives.activeSurface]
|
||||
|
||||
processPlayers(gameRef.players,
|
||||
map,
|
||||
surface,
|
||||
gameRef.surfaces[natives.activeSurface],
|
||||
natives,
|
||||
event.tick)
|
||||
end)
|
||||
@ -530,10 +538,9 @@ script.on_nth_tick(INTERVAL_MAP_PROCESS,
|
||||
function (event)
|
||||
|
||||
local gameRef = game
|
||||
local surface = gameRef.surfaces[natives.activeSurface]
|
||||
|
||||
processMap(map,
|
||||
surface,
|
||||
gameRef.surfaces[natives.activeSurface],
|
||||
natives,
|
||||
event.tick,
|
||||
gameRef.forces.enemy.evolution_factor)
|
||||
@ -549,7 +556,7 @@ script.on_nth_tick(INTERVAL_SCAN,
|
||||
|
||||
scanMap(map, surface, natives, tick)
|
||||
|
||||
map.chunkToPassScan = processScanChunks(map, surface)
|
||||
processScanChunks(map, surface)
|
||||
end)
|
||||
|
||||
script.on_nth_tick(INTERVAL_LOGIC,
|
||||
@ -560,6 +567,8 @@ script.on_nth_tick(INTERVAL_LOGIC,
|
||||
game.forces.enemy.evolution_factor,
|
||||
tick)
|
||||
|
||||
squadsBeginAttack(natives)
|
||||
|
||||
if natives.newEnemies then
|
||||
recycleBases(natives, tick)
|
||||
end
|
||||
@ -567,15 +576,25 @@ end)
|
||||
|
||||
script.on_nth_tick(INTERVAL_SQUAD,
|
||||
function ()
|
||||
local surface = game.surfaces[natives.activeSurface]
|
||||
|
||||
squadsBeginAttack(natives)
|
||||
squadsDispatch(map, surface, natives)
|
||||
regroupSquads(natives, map)
|
||||
|
||||
cleanBuilders(map, natives, surface)
|
||||
squadsDispatch(map,
|
||||
game.surfaces[natives.activeSurface],
|
||||
natives)
|
||||
end)
|
||||
|
||||
script.on_nth_tick(INTERVAL_BUILDERS,
|
||||
function ()
|
||||
cleanBuilders(map,
|
||||
natives,
|
||||
game.surfaces[natives.activeSurface])
|
||||
end)
|
||||
|
||||
|
||||
script.on_nth_tick(INTERVAL_RESQUAD,
|
||||
function ()
|
||||
regroupSquads(natives, map)
|
||||
end)
|
||||
|
||||
|
||||
local function onBuild(event)
|
||||
local entity = event.created_entity or event.entity
|
||||
if (entity.surface.index == natives.activeSurface) then
|
||||
@ -885,6 +904,16 @@ local function onInit()
|
||||
hookEvents()
|
||||
end
|
||||
|
||||
local function onEntitySpawned(event)
|
||||
local entity = event.entity
|
||||
if (entity.type ~= "unit") then
|
||||
local spawner = event.spawner
|
||||
-- print(spawner.unit_number)
|
||||
else
|
||||
-- print("cost")
|
||||
end
|
||||
end
|
||||
|
||||
local function onCommandDebugger(event)
|
||||
for i=1,natives.squads.len do
|
||||
if (natives.squads[i].group.valid) and (natives.squads[i].group.group_number == event.unit_number) then
|
||||
@ -943,6 +972,7 @@ script.on_event({defines.events.on_built_entity,
|
||||
defines.events.script_raised_built}, onBuild)
|
||||
|
||||
-- script.on_event(defines.events.on_ai_command_completed, onCommandDebugger)
|
||||
script.on_event(defines.events.on_entity_spawned, onEntitySpawned)
|
||||
|
||||
script.on_event(defines.events.on_rocket_launched, onRocketLaunch)
|
||||
script.on_event(defines.events.on_entity_died, onDeath)
|
||||
|
@ -1,5 +1,6 @@
|
||||
local vanillaBuildings = require("prototypes/buildings/UpdatesVanilla")
|
||||
|
||||
local biterFunctions = require("prototypes/utils/BiterUtils")
|
||||
local neutral = require("prototypes/Neutral")
|
||||
local acid = require("prototypes/Acid")
|
||||
local physical = require("prototypes/Physical")
|
||||
@ -68,6 +69,18 @@ if settings.startup["rampant-newEnemies"].value then
|
||||
|
||||
end
|
||||
|
||||
data:extend({
|
||||
biterFunctions.makeUnitSpawner("tester",
|
||||
{
|
||||
scale=1.0,
|
||||
spawningRadius=30,
|
||||
spawningSpacing=15
|
||||
},
|
||||
{},
|
||||
{{"small-worm-turret", {{0.0, 1.0}, {1.0, 1.0}}}})
|
||||
})
|
||||
|
||||
|
||||
for _, unitSpawner in pairs(data.raw["unit-spawner"]) do
|
||||
if settings.startup["rampant-unitSpawnerBreath"].value then
|
||||
if not unitSpawner.flags then
|
||||
@ -84,13 +97,8 @@ if settings.startup["rampant-enableSwarm"].value then
|
||||
{unit.collision_box[1][1] * 0.20, unit.collision_box[1][2] * 0.20},
|
||||
{unit.collision_box[2][1] * 0.20, unit.collision_box[2][2] * 0.20}
|
||||
}
|
||||
if unit.collision_mask == nil then
|
||||
unit.collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"}
|
||||
else
|
||||
unit.collision_mask[#unit.collision_mask+1] = "not-colliding-with-itself"
|
||||
end
|
||||
|
||||
unit.ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = false, path_resolution_modifier = -8, do_seperation = false }
|
||||
unit.ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = true, path_resolution_modifier = -5, do_seperation = true }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -17,7 +17,7 @@ end
|
||||
|
||||
for _, robot in pairs(data.raw["logistic-robot"]) do
|
||||
if not robot.collision_mask then
|
||||
robot.collision_mask = {}
|
||||
robot.collision_mask = {}
|
||||
end
|
||||
robot.collision_mask[#robot.collision_mask+1] = "layer-11"
|
||||
|
||||
@ -34,7 +34,7 @@ end
|
||||
|
||||
for _, robot in pairs(data.raw["construction-robot"]) do
|
||||
if not robot.collision_mask then
|
||||
robot.collision_mask = {}
|
||||
robot.collision_mask = {}
|
||||
end
|
||||
robot.collision_mask[#robot.collision_mask+1] = "layer-11"
|
||||
|
||||
@ -51,7 +51,7 @@ end
|
||||
|
||||
for _, robot in pairs(data.raw["combat-robot"]) do
|
||||
if not robot.collision_mask then
|
||||
robot.collision_mask = {}
|
||||
robot.collision_mask = {}
|
||||
end
|
||||
robot.collision_mask[#robot.collision_mask+1] = "layer-11"
|
||||
end
|
||||
@ -62,7 +62,7 @@ end
|
||||
--]]
|
||||
local mapSettings = data.raw["map-settings"]["map-settings"]
|
||||
|
||||
mapSettings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
|
||||
mapSettings.max_failed_behavior_count = 3 -- constants.MAX_FAILED_BEHAVIORS
|
||||
|
||||
mapSettings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE
|
||||
mapSettings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE
|
||||
@ -73,7 +73,7 @@ mapSettings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX
|
||||
mapSettings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
|
||||
|
||||
|
||||
data.raw["utility-constants"]["default"].unit_group_pathfinding_resolution = -8
|
||||
data.raw["utility-constants"]["default"].unit_group_pathfinding_resolution = -5
|
||||
data.raw["utility-constants"]["default"].unit_group_collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"}
|
||||
|
||||
|
||||
|
@ -198,6 +198,7 @@ function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
|
||||
setChunkSettlerTick(map, squadPath, tick + natives.settlerCooldown)
|
||||
local pending = natives.pendingAttack
|
||||
pending.len = pending.len + 1
|
||||
squad.cycles = 30
|
||||
pending[pending.len] = squad
|
||||
natives.points = natives.points - AI_SETTLER_COST
|
||||
else
|
||||
@ -241,6 +242,7 @@ function aiAttackWave.formVengenceSquad(map, surface, natives, chunk)
|
||||
if (foundUnits > 0) then
|
||||
local pending = natives.pendingAttack
|
||||
pending.len = pending.len + 1
|
||||
squad.cycles = 13
|
||||
pending[pending.len] = squad
|
||||
natives.points = natives.points - AI_VENGENCE_SQUAD_COST
|
||||
else
|
||||
@ -285,6 +287,7 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, tick)
|
||||
if (foundUnits > 0) then
|
||||
local pending = natives.pendingAttack
|
||||
pending.len = pending.len + 1
|
||||
squad.cycles = 30
|
||||
pending[pending.len] = squad
|
||||
natives.points = natives.points - AI_SQUAD_COST
|
||||
if tick and (natives.state == AI_STATE_AGGRESSIVE) then
|
||||
@ -301,7 +304,7 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, tick)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return (natives.points - AI_SQUAD_COST) > 0
|
||||
end
|
||||
|
||||
|
@ -30,6 +30,8 @@ local tSort = table.sort
|
||||
|
||||
local abs = math.abs
|
||||
|
||||
local tRemove = table.remove
|
||||
|
||||
-- module code
|
||||
|
||||
local origin = {x=0,y=0}
|
||||
@ -103,9 +105,13 @@ function chunkProcessor.processScanChunks(map, surface)
|
||||
local topOffset = area[1]
|
||||
local bottomOffset = area[2]
|
||||
|
||||
local removals = {}
|
||||
local removals = map.chunkRemovals
|
||||
|
||||
for chunk,_ in pairs(map.chunkToPassScan) do
|
||||
local chunkCount = 0
|
||||
|
||||
local chunkToPassScan = map.chunkToPassScan
|
||||
|
||||
for chunk,_ in pairs(chunkToPassScan) do
|
||||
local x = chunk.x
|
||||
local y = chunk.y
|
||||
|
||||
@ -119,24 +125,25 @@ function chunkProcessor.processScanChunks(map, surface)
|
||||
if (chunk == SENTINEL_IMPASSABLE_CHUNK) then
|
||||
map[x][y] = nil
|
||||
|
||||
removals[#removals+1] = chunk
|
||||
chunkCount = chunkCount + 1
|
||||
removals[chunkCount] = chunk
|
||||
end
|
||||
|
||||
chunkToPassScan[chunk] = nil
|
||||
end
|
||||
|
||||
if (#removals > 0) then
|
||||
if (chunkCount > 0) then
|
||||
local processQueue = map.processQueue
|
||||
for i=#processQueue,1,-1 do
|
||||
for ri=#removals,1,-1 do
|
||||
for ri=chunkCount,1,-1 do
|
||||
if (removals[ri] == processQueue[i]) then
|
||||
table.remove(processQueue, i)
|
||||
table.remove(removals, ri)
|
||||
tRemove(processQueue, i)
|
||||
-- tRemove(removals, ri)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {}
|
||||
end
|
||||
|
||||
chunkProcessorG = chunkProcessor
|
||||
|
@ -211,7 +211,7 @@ function chunkPropertyUtils.removeSquadFromChunk(map, squad)
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.getSquadsOnChunk(map, chunk)
|
||||
return map.chunkToSquad[chunk] or {}
|
||||
return map.chunkToSquad[chunk] or map.emptySquadsOnChunk
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setPlayerBaseGenerator(map, chunk, playerGenerator)
|
||||
|
@ -61,6 +61,8 @@ constants.INTERVAL_SCAN = (settings.startup["rampant-liteMode"].value and 42) or
|
||||
constants.INTERVAL_CHUNK = 17
|
||||
constants.INTERVAL_LOGIC = 61
|
||||
constants.INTERVAL_SQUAD = 41
|
||||
constants.INTERVAL_RESQUAD = 101
|
||||
constants.INTERVAL_BUILDERS = 300
|
||||
constants.INTERVAL_SPAWNER = constants.TICKS_A_SECOND * 10
|
||||
constants.INTERVAL_RALLY = constants.TICKS_A_SECOND * 10
|
||||
constants.INTERVAL_RETREAT = constants.TICKS_A_SECOND * 10
|
||||
|
@ -121,7 +121,7 @@ function movementUtils.scoreNeighborsForAttack(map, natives, chunk, neighborDire
|
||||
if (nextHighestChunk == nil) then
|
||||
nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
end
|
||||
|
||||
|
||||
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
|
||||
end
|
||||
|
||||
@ -133,7 +133,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
|
||||
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local highestDirection
|
||||
|
||||
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
|
||||
@ -153,7 +153,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
|
||||
local nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
local nextHighestScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local nextHighestDirection
|
||||
|
||||
|
||||
if (highestChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
|
||||
for x=1,8 do
|
||||
@ -174,7 +174,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
|
||||
if (nextHighestChunk == nil) then
|
||||
nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
end
|
||||
|
||||
|
||||
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
|
||||
end
|
||||
|
||||
@ -211,6 +211,11 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
|
||||
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local highestDirection
|
||||
|
||||
local nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
local nextHighestScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local nextHighestDirection
|
||||
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
|
||||
@ -223,7 +228,28 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
|
||||
end
|
||||
end
|
||||
|
||||
return highestChunk, highestDirection
|
||||
if (highestChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
|
||||
if ((neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (neighborChunk ~= chunk) and
|
||||
canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then
|
||||
local score = scoreFunction(map, neighborChunk)
|
||||
if (score > nextHighestScore) then
|
||||
nextHighestScore = score
|
||||
nextHighestChunk = neighborChunk
|
||||
nextHighestDirection = x
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (nextHighestChunk == nil) then
|
||||
nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
end
|
||||
|
||||
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
|
||||
end
|
||||
|
||||
|
||||
|
@ -143,7 +143,7 @@ local function settleMove(map, squad, natives, surface)
|
||||
local cmd
|
||||
local position
|
||||
local position2
|
||||
|
||||
|
||||
if (distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0))
|
||||
then
|
||||
if not ((groupState == DEFINES_GROUP_FINISHED) or ((groupState == DEFINES_GROUP_GATHERING) and (squad.cycles <= 0))) then
|
||||
@ -168,7 +168,7 @@ local function settleMove(map, squad, natives, surface)
|
||||
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
|
||||
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
|
||||
|
||||
local entities = surface.find_entities_filtered(map.filteredEntitiesClearBuildingQuery)
|
||||
for i=1,#entities do
|
||||
@ -178,7 +178,7 @@ local function settleMove(map, squad, natives, surface)
|
||||
end
|
||||
end
|
||||
|
||||
squad.cycles = 400
|
||||
squad.cycles = 400
|
||||
group.set_command(cmd)
|
||||
else
|
||||
local attackChunk, attackDirection, nextAttackChunk, nextAttackDirection = scoreNeighborsForSettling(map,
|
||||
@ -199,15 +199,15 @@ local function settleMove(map, squad, natives, surface)
|
||||
if not position then
|
||||
squad.cycles = 30
|
||||
cmd = map.wonderCommand
|
||||
group.set_command(cmd)
|
||||
group.set_command(cmd)
|
||||
return
|
||||
else
|
||||
targetPosition.x = position.x
|
||||
targetPosition.y = position.y
|
||||
|
||||
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) or
|
||||
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
|
||||
then
|
||||
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
|
||||
then
|
||||
cmd = map.attackCommand
|
||||
|
||||
if not squad.rabid then
|
||||
@ -224,22 +224,22 @@ local function settleMove(map, squad, natives, surface)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if (nextAttackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
|
||||
|
||||
position2 = findMovementPosition(surface, targetPosition2)
|
||||
|
||||
|
||||
if position2 then
|
||||
targetPosition.x = position2.x
|
||||
targetPosition.y = position2.y
|
||||
|
||||
|
||||
if ((cmd ~= map.attackCommand) and
|
||||
((getPlayerBaseGenerator(map, nextAttackChunk) ~= 0) or
|
||||
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)))
|
||||
then
|
||||
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)))
|
||||
then
|
||||
cmd = map.attackCommand
|
||||
|
||||
|
||||
if not squad.rabid then
|
||||
squad.frenzy = true
|
||||
squad.frenzyPosition.x = groupPosition.x
|
||||
@ -263,7 +263,7 @@ local function settleMove(map, squad, natives, surface)
|
||||
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
|
||||
map.buildPositionBottom.y = position.y + BASE_CLEAN_DISTANCE
|
||||
|
||||
local entities = surface.find_entities_filtered(map.filteredEntitiesClearBuildingQuery)
|
||||
for i=1,#entities do
|
||||
@ -272,12 +272,12 @@ local function settleMove(map, squad, natives, surface)
|
||||
entity.die()
|
||||
end
|
||||
end
|
||||
|
||||
squad.cycles = 400
|
||||
|
||||
squad.cycles = 400
|
||||
group.set_command(cmd)
|
||||
else
|
||||
squad.cycles = 23
|
||||
group.set_command(cmd)
|
||||
group.set_command(cmd)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -326,7 +326,7 @@ local function attackMove(map, squad, natives, surface)
|
||||
else
|
||||
targetPosition.x = position.x
|
||||
targetPosition.y = position.y
|
||||
|
||||
|
||||
if (getPlayerBaseGenerator(map, attackChunk) ~= 0) and
|
||||
(attackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold)
|
||||
then
|
||||
@ -343,7 +343,7 @@ local function attackMove(map, squad, natives, surface)
|
||||
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
|
||||
else
|
||||
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -363,7 +363,7 @@ local function attackMove(map, squad, natives, surface)
|
||||
(nextAttackChunk[PLAYER_PHEROMONE] >= natives.attackPlayerThreshold))
|
||||
then
|
||||
cmd = map.attackCommand
|
||||
|
||||
|
||||
if not squad.rabid then
|
||||
squad.frenzy = true
|
||||
squad.frenzyPosition.x = groupPosition.x
|
||||
@ -389,7 +389,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
|
||||
local pending = natives.pendingAttack
|
||||
local squadsLen = squads.len
|
||||
local x = 0
|
||||
|
||||
|
||||
for i=1,squadsLen do
|
||||
local squad = squads[i]
|
||||
local group = squad.group
|
||||
@ -430,7 +430,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
|
||||
end
|
||||
end
|
||||
elseif (status == SQUAD_SETTLING) then
|
||||
x = x + 1
|
||||
x = x + 1
|
||||
squads[x] = squad
|
||||
if (groupState == DEFINES_GROUP_FINISHED) or
|
||||
(groupState == DEFINES_GROUP_GATHERING) or
|
||||
@ -443,10 +443,22 @@ function squadAttack.squadsDispatch(map, surface, natives)
|
||||
addSquadToChunk(map, chunk, squad)
|
||||
end
|
||||
end
|
||||
elseif (status == SQUAD_RETREATING) and (cycles <= 0) then
|
||||
pending.len = pending.len + 1
|
||||
pending[pending.len] = squad
|
||||
squad.status = SQUAD_GUARDING
|
||||
elseif (status == SQUAD_RETREATING) then
|
||||
if (groupState == DEFINES_GROUP_FINISHED) or
|
||||
(groupState == DEFINES_GROUP_GATHERING) or
|
||||
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
|
||||
then
|
||||
pending.len = pending.len + 1
|
||||
pending[pending.len] = squad
|
||||
squad.status = SQUAD_GUARDING
|
||||
else
|
||||
x = x + 1
|
||||
squads[x] = squad
|
||||
end
|
||||
local chunk = getChunkByPosition(map, group.position)
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
addSquadToChunk(map, chunk, squad)
|
||||
end
|
||||
elseif (status == SQUAD_BUILDING) then
|
||||
removeSquadFromChunk(map, squad)
|
||||
natives.building[#natives.building+1] = squad
|
||||
@ -454,7 +466,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
|
||||
pending.len = pending.len + 1
|
||||
pending[pending.len] = squad
|
||||
else
|
||||
x = x + 1
|
||||
x = x + 1
|
||||
squads[x] = squad
|
||||
end
|
||||
if (cycles > 0) then
|
||||
@ -468,7 +480,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
|
||||
end
|
||||
|
||||
squads.len = x
|
||||
|
||||
|
||||
-- print("end dispatch")
|
||||
-- if (maxSquadIndex >= #squads) then
|
||||
-- natives.attackIndex = 1
|
||||
@ -484,15 +496,17 @@ function squadAttack.squadsBeginAttack(natives)
|
||||
local squads = natives.squads
|
||||
local pendingLen = pending.len
|
||||
local x = 0
|
||||
|
||||
|
||||
for i=1,pendingLen do
|
||||
local squad = pending[i]
|
||||
local group = squad.group
|
||||
if group and group.valid then
|
||||
if (squad.cycles ~= 0) then
|
||||
local groupState = group.state
|
||||
if -- (groupState ~= DEFINES_GROUP_GATHERING) and
|
||||
(groupState ~= DEFINES_GROUP_FINISHED) and (squad.cycles ~= 0) then
|
||||
squad.cycles = squad.cycles - 1
|
||||
x = x + 1
|
||||
pending[x] = squad
|
||||
pending[x] = squad
|
||||
else
|
||||
local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
|
||||
if not squad.kamikaze then
|
||||
@ -510,7 +524,7 @@ function squadAttack.squadsBeginAttack(natives)
|
||||
squads.len = squads.len + 1
|
||||
squads[squads.len] = squad
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -33,7 +33,7 @@ local addSquadToChunk = chunkPropetyUtils.addSquadToChunk
|
||||
|
||||
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
|
||||
|
||||
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
local positionFromDirectionAndFlat = mapUtils.positionFromDirectionAndFlat
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
local findNearbyRetreatingSquad = unitGroupUtils.findNearbyRetreatingSquad
|
||||
local addMovementPenalty = movementUtils.addMovementPenalty
|
||||
@ -64,60 +64,84 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
|
||||
local enemiesToSquad = nil
|
||||
|
||||
if not squad then
|
||||
enemiesToSquad = surface.find_enemy_units(position, radius)
|
||||
performRetreat = #enemiesToSquad > 6
|
||||
if (mRandom() < calculateKamikazeThreshold(#enemiesToSquad, natives)) then
|
||||
enemiesToSquad = map.enemiesToSquad
|
||||
local unitCount = 0
|
||||
local units = surface.find_enemy_units(position, radius)
|
||||
for i=1,#units do
|
||||
local unit = units[i]
|
||||
if not unit.unit_group then
|
||||
unitCount = unitCount + 1
|
||||
enemiesToSquad[unitCount] = unit
|
||||
end
|
||||
end
|
||||
enemiesToSquad.len = unitCount
|
||||
if (mRandom() < calculateKamikazeThreshold(unitCount, natives)) then
|
||||
setRetreatTick(map, chunk, tick)
|
||||
return
|
||||
end
|
||||
performRetreat = unitCount > 6
|
||||
elseif squad.group and squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
|
||||
performRetreat = #squad.group.members > 6
|
||||
end
|
||||
|
||||
if performRetreat then
|
||||
setRetreatTick(map, chunk, tick)
|
||||
local exitPath,exitDirection = scoreNeighborsForRetreat(chunk,
|
||||
getNeighborChunks(map, chunk.x, chunk.y),
|
||||
scoreRetreatLocation,
|
||||
map)
|
||||
local exitPath,exitDirection,nextExitPath,nextExitDirection = scoreNeighborsForRetreat(chunk,
|
||||
getNeighborChunks(map,
|
||||
chunk.x,
|
||||
chunk.y),
|
||||
scoreRetreatLocation,
|
||||
map)
|
||||
if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
local retreatPosition = findMovementPosition(surface,
|
||||
positionFromDirectionAndChunk(exitDirection,
|
||||
position,
|
||||
map.position,
|
||||
0.98))
|
||||
local targetPosition = map.position
|
||||
local targetPosition2 = map.position2
|
||||
|
||||
positionFromDirectionAndFlat(exitDirection, position, targetPosition)
|
||||
|
||||
local retreatPosition = findMovementPosition(surface, targetPosition)
|
||||
|
||||
if not retreatPosition then
|
||||
return
|
||||
end
|
||||
|
||||
if (nextExitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
positionFromDirectionAndFlat(nextExitDirection, retreatPosition, targetPosition2)
|
||||
|
||||
local retreatPosition2 = findMovementPosition(surface, targetPosition2)
|
||||
|
||||
if retreatPosition2 then
|
||||
retreatPosition.x = retreatPosition2.x
|
||||
retreatPosition.y = retreatPosition2.y
|
||||
end
|
||||
end
|
||||
|
||||
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
|
||||
-- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
|
||||
|
||||
local newSquad = findNearbyRetreatingSquad(map, exitPath)
|
||||
|
||||
|
||||
if not newSquad then
|
||||
newSquad = createSquad(retreatPosition, surface)
|
||||
local squads = natives.squads
|
||||
squads.len = squads.len+1
|
||||
squads[squads.len] = newSquad
|
||||
end
|
||||
|
||||
|
||||
if newSquad then
|
||||
newSquad.status = SQUAD_RETREATING
|
||||
newSquad.cycles = 4
|
||||
newSquad.cycles = 13
|
||||
|
||||
local cmd = map.retreatCommand
|
||||
local cmd = map.retreatCommand
|
||||
cmd.group = newSquad.group
|
||||
if enemiesToSquad then
|
||||
membersToSquad(cmd, enemiesToSquad, artilleryBlast)
|
||||
else
|
||||
membersToSquad(cmd, squad.group.members, true)
|
||||
membersToSquad(cmd, enemiesToSquad.len, enemiesToSquad, artilleryBlast)
|
||||
else
|
||||
membersToSquad(cmd, #squad.group.members, squad.group.members, true)
|
||||
if squad.rabid then
|
||||
newSquad.rabid = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not newSquad.rapid then
|
||||
newSquad.frenzy = true
|
||||
local squadPosition = newSquad.group.position
|
||||
|
@ -82,11 +82,11 @@ function unitGroupUtils.findNearbySquad(map, chunk)
|
||||
for i=1,#squads do
|
||||
local squad = squads[i]
|
||||
local unitGroup = squad.group
|
||||
if unitGroup and unitGroup.valid then
|
||||
return squad
|
||||
if unitGroup and unitGroup.valid then
|
||||
return squad
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local neighbors = getNeighborChunks(map, chunk.x, chunk.y)
|
||||
|
||||
for i=1,#neighbors do
|
||||
@ -138,15 +138,15 @@ function unitGroupUtils.createSquad(position, surface, group, settlers)
|
||||
return squad
|
||||
end
|
||||
|
||||
function unitGroupUtils.membersToSquad(cmd, members, overwriteGroup)
|
||||
if (members ~= nil) then
|
||||
for i=1,#members do
|
||||
local member = members[i]
|
||||
if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
|
||||
member.set_command(cmd)
|
||||
end
|
||||
function unitGroupUtils.membersToSquad(cmd, size, members, overwriteGroup)
|
||||
-- if (members ~= nil) then
|
||||
for i=1,size do
|
||||
local member = members[i]
|
||||
if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
|
||||
member.set_command(cmd)
|
||||
end
|
||||
end
|
||||
-- end
|
||||
end
|
||||
|
||||
function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
|
||||
@ -190,13 +190,7 @@ function unitGroupUtils.cleanBuilders(map, natives, surface)
|
||||
for i=maxSquadIndex,startIndex,-1 do
|
||||
local squad = squads[i]
|
||||
local group = squad.group
|
||||
if not (group and group.valid) then
|
||||
tRemove(squads, i)
|
||||
else
|
||||
if (squad.cycles > 0) then
|
||||
squad.cycles = squad.cycles - 1
|
||||
end
|
||||
|
||||
if group and group.valid then
|
||||
if (group.state == DEFINES_GROUP_FINISHED) or (squad.cycles <= 0) then
|
||||
if (#group.members > 0) then
|
||||
local groupPosition = findMovementPosition(surface, group.position)
|
||||
@ -204,19 +198,23 @@ function unitGroupUtils.cleanBuilders(map, natives, surface)
|
||||
if not groupPosition then
|
||||
groupPosition = group.position
|
||||
end
|
||||
|
||||
|
||||
position.x = groupPosition.x
|
||||
position.y = groupPosition.y
|
||||
|
||||
squad.cycles = 400
|
||||
|
||||
|
||||
group.set_command(cmd)
|
||||
group.start_moving()
|
||||
else
|
||||
tRemove(squads, i)
|
||||
group.destroy()
|
||||
end
|
||||
elseif (squad.cycles > 0) then
|
||||
squad.cycles = squad.cycles - 1
|
||||
end
|
||||
else
|
||||
tRemove(squads, i)
|
||||
end
|
||||
end
|
||||
|
||||
@ -227,11 +225,6 @@ function unitGroupUtils.cleanBuilders(map, natives, surface)
|
||||
end
|
||||
end
|
||||
|
||||
local function isAttacking(group)
|
||||
local state = group.state
|
||||
return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION)
|
||||
end
|
||||
|
||||
function unitGroupUtils.regroupSquads(natives, map)
|
||||
local squads = natives.squads
|
||||
local squadCount = squads.len
|
||||
@ -242,39 +235,41 @@ function unitGroupUtils.regroupSquads(natives, map)
|
||||
for i=startIndex,maxSquadIndex do
|
||||
local squad = squads[i]
|
||||
local group = squad.group
|
||||
if group and group.valid and not isAttacking(group) then
|
||||
local memberCount = #group.members
|
||||
if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then
|
||||
local status = squad.status
|
||||
local chunk = squad.chunk
|
||||
if group and group.valid then
|
||||
local groupState = group.state
|
||||
if (groupState ~= DEFINES_GROUP_STATE_ATTACKING_TARGET) and (groupState ~= DEFINES_GROUP_STATE_ATTACKING_DISTRACTION) then
|
||||
local memberCount = #group.members
|
||||
if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then
|
||||
local status = squad.status
|
||||
local chunk = squad.chunk
|
||||
|
||||
if chunk then
|
||||
local chunkSquads = getSquadsOnChunk(map, chunk)
|
||||
for p=1,#chunkSquads do
|
||||
local mergeSquad = chunkSquads[p]
|
||||
if (mergeSquad ~= squad) then
|
||||
local mergeGroup = mergeSquad.group
|
||||
if mergeGroup and
|
||||
mergeGroup.valid and
|
||||
(mergeSquad.status == status) and
|
||||
not isAttacking(mergeGroup)
|
||||
then
|
||||
local mergeMembers = mergeGroup.members
|
||||
local mergeCount = #mergeMembers
|
||||
if ((mergeCount + memberCount) < AI_MAX_BITER_GROUP_SIZE) then
|
||||
for memberIndex=1, mergeCount do
|
||||
group.add_member(mergeMembers[memberIndex])
|
||||
end
|
||||
mergeGroup.destroy()
|
||||
end
|
||||
squad.status = SQUAD_GUARDING
|
||||
memberCount = memberCount + mergeCount
|
||||
if (memberCount > AI_SQUAD_MERGE_THRESHOLD) then
|
||||
break
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
local chunkSquads = getSquadsOnChunk(map, chunk)
|
||||
for p=1,#chunkSquads do
|
||||
local mergeSquad = chunkSquads[p]
|
||||
if (mergeSquad ~= squad) then
|
||||
local mergeGroup = mergeSquad.group
|
||||
if mergeGroup and mergeGroup.valid and (mergeSquad.status == status) then
|
||||
local mergeGroupState = mergeGroup.state
|
||||
if (mergeGroupState ~= DEFINES_GROUP_STATE_ATTACKING_TARGET) and (mergeGroupState ~= DEFINES_GROUP_STATE_ATTACKING_DISTRACTION) then
|
||||
local mergeMembers = mergeGroup.members
|
||||
local mergeCount = #mergeMembers
|
||||
if ((mergeCount + memberCount) < AI_MAX_BITER_GROUP_SIZE) then
|
||||
for memberIndex=1, mergeCount do
|
||||
group.add_member(mergeMembers[memberIndex])
|
||||
end
|
||||
mergeGroup.destroy()
|
||||
end
|
||||
squad.status = SQUAD_GUARDING
|
||||
memberCount = memberCount + mergeCount
|
||||
if (memberCount > AI_SQUAD_MERGE_THRESHOLD) then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -236,7 +236,7 @@ function biterFunctions.makeBiter(name, biterAttributes, biterAttack, biterResis
|
||||
dying_sound = make_biter_dying_sounds(biterAttributes.scale),
|
||||
working_sound = make_biter_calls(biterAttributes.scale),
|
||||
run_animation = biterrunanimation(biterAttributes.scale, biterAttributes.tint, biterAttributes.tint),
|
||||
ai_settings = { destroy_when_commands_fail = true, allow_try_return_to_spawner = true, path_resolution_modifier = -8, do_seperation = true }
|
||||
ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = true, path_resolution_modifier = -5, do_seperation = true }
|
||||
}
|
||||
if biterAttributes.collisionMask then
|
||||
entity.collision_mask = biterAttributes.collisionMask
|
||||
@ -282,7 +282,7 @@ function biterFunctions.makeSpitter(name, biterAttributes, biterAttack, biterRes
|
||||
dying_sound = make_spitter_dying_sounds(0.8),
|
||||
working_sound = make_biter_calls(0.7),
|
||||
run_animation = spitterrunanimation(biterAttributes.scale, biterAttributes.tint, biterAttributes.tint),
|
||||
ai_settings = { destroy_when_commands_fail = true, allow_try_return_to_spawner = true, path_resolution_modifier = -8, do_seperation = true }
|
||||
ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = true, path_resolution_modifier = -5, do_seperation = true }
|
||||
}
|
||||
if biterAttributes.collisionMask then
|
||||
entity.collision_mask = biterAttributes.collisionMask
|
||||
|
Loading…
Reference in New Issue
Block a user