1
0
mirror of https://github.com/veden/Rampant.git synced 2025-01-28 03:29:34 +02:00
Rampant/libs/UnitGroupUtils.lua

298 lines
9.6 KiB
Lua
Raw Normal View History

2019-02-15 20:17:30 -08:00
if unitGroupUtilsG then
return unitGroupUtilsG
end
local unitGroupUtils = {}
-- imports
2018-01-13 21:48:21 -08:00
local mapUtils = require("MapUtils")
2016-08-06 20:38:47 -07:00
local constants = require("Constants")
local chunkPropertyUtils = require("ChunkPropertyUtils")
2019-04-07 22:22:02 -07:00
local movementUtils = require("MovementUtils")
-- constants
2019-04-07 22:22:02 -07:00
local DEFINES_GROUP_FINISHED = defines.group_state.finished
2017-05-31 19:48:59 -07:00
local SQUAD_QUEUE_SIZE = constants.SQUAD_QUEUE_SIZE
2017-05-26 17:58:33 -07:00
local DEFINES_GROUP_STATE_ATTACKING_TARGET = defines.group_state.attacking_target
local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local SQUAD_GUARDING = constants.SQUAD_GUARDING
2018-01-13 21:48:21 -08:00
2017-01-19 21:58:36 -08:00
local NO_RETREAT_SQUAD_SIZE_BONUS_MAX = constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX
2017-05-31 18:46:53 -07:00
local AI_MAX_OVERFLOW_POINTS = constants.AI_MAX_OVERFLOW_POINTS
2017-04-15 23:04:22 -07:00
local AI_MAX_BITER_GROUP_SIZE = constants.AI_MAX_BITER_GROUP_SIZE
2017-06-01 00:03:07 -07:00
local AI_SQUAD_MERGE_THRESHOLD = constants.AI_SQUAD_MERGE_THRESHOLD
2017-04-15 23:04:22 -07:00
2019-03-08 16:42:20 -08:00
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions
2019-03-06 22:12:39 -08:00
local tRemove = table.remove
local mRandom = math.random
2019-04-07 22:22:02 -07:00
local findMovementPosition = movementUtils.findMovementPosition
2017-01-19 21:58:36 -08:00
local mLog = math.log10
2017-05-31 19:48:59 -07:00
local mMin = math.min
local getSquadsOnChunk = chunkPropertyUtils.getSquadsOnChunk
2018-01-13 21:48:21 -08:00
local getNeighborChunks = mapUtils.getNeighborChunks
-- module code
2017-01-19 21:58:36 -08:00
2019-03-09 15:16:35 -08:00
function unitGroupUtils.findNearbyRetreatingSquad(map, chunk)
2019-03-08 16:42:20 -08:00
local squads = getSquadsOnChunk(map, chunk)
for i=1,#squads do
local squad = squads[i]
2018-01-13 21:48:21 -08:00
local unitGroup = squad.group
2019-03-05 22:18:03 -08:00
if unitGroup and unitGroup.valid and (squad.status == SQUAD_RETREATING) then
2019-03-08 16:42:20 -08:00
return squad
end
2018-01-13 21:48:21 -08:00
end
local neighbors = getNeighborChunks(map, chunk.x, chunk.y)
for i=1,#neighbors do
2019-03-08 16:42:20 -08:00
local neighbor = neighbors[i]
if neighbor ~= SENTINEL_IMPASSABLE_CHUNK then
squads = getSquadsOnChunk(map, neighbor)
for squadIndex=1,#squads do
local squad = squads[squadIndex]
local unitGroup = squad.group
if unitGroup and unitGroup.valid and (squad.status == SQUAD_RETREATING) then
return squad
end
end
end
end
return nil
end
2019-03-08 16:42:20 -08:00
function unitGroupUtils.findNearbySquad(map, chunk)
2019-03-08 16:42:20 -08:00
local squads = getSquadsOnChunk(map, chunk)
for i=1,#squads do
local squad = squads[i]
local unitGroup = squad.group
if unitGroup and unitGroup.valid then
return squad
end
end
2019-03-08 16:42:20 -08:00
local neighbors = getNeighborChunks(map, chunk.x, chunk.y)
2018-01-13 21:48:21 -08:00
for i=1,#neighbors do
2019-03-08 16:42:20 -08:00
local neighbor = neighbors[i]
if neighbor ~= SENTINEL_IMPASSABLE_CHUNK then
squads = getSquadsOnChunk(map, neighbor)
for squadIndex=1,#squads do
local squad = squads[squadIndex]
local unitGroup = squad.group
if unitGroup and unitGroup.valid then
return squad
end
end
end
end
2019-02-10 22:14:17 -08:00
return nil
end
2018-01-13 21:48:21 -08:00
2019-03-06 22:12:39 -08:00
function unitGroupUtils.createSquad(position, surface, group, settlers)
local unitGroup = group or surface.create_unit_group({position=position})
2019-02-10 22:14:17 -08:00
2018-01-13 21:48:21 -08:00
local squad = {
2019-03-08 16:42:20 -08:00
group = unitGroup,
status = SQUAD_GUARDING,
penalties = {},
rabid = false,
frenzy = false,
2019-02-16 10:45:42 -08:00
settlers = settlers or false,
2019-03-08 16:42:20 -08:00
kamikaze = false,
frenzyPosition = {x = 0,
y = 0},
2019-04-07 22:22:02 -07:00
cycles = 60,
2019-03-08 16:42:20 -08:00
maxDistance = 0,
2019-02-16 10:45:42 -08:00
attackScoreFunction = 1,
2019-03-08 22:23:00 -08:00
originPosition = {x = 0,
y = 0},
2019-03-08 16:42:20 -08:00
chunk = nil
2018-01-13 21:48:21 -08:00
}
2019-03-06 22:12:39 -08:00
2019-03-08 22:23:00 -08:00
if position then
squad.originPosition.x = position.x
squad.originPosition.y = position.y
elseif group then
squad.originPosition.x = group.position.x
squad.originPosition.y = group.position.y
end
2016-08-06 20:38:47 -07:00
return squad
end
2018-01-13 21:48:21 -08:00
function unitGroupUtils.membersToSquad(cmd, members, overwriteGroup)
2016-08-07 18:35:36 -07:00
if (members ~= nil) then
2019-03-08 16:42:20 -08:00
for i=1,#members do
2016-08-06 20:38:47 -07:00
local member = members[i]
2017-05-27 21:50:37 -07:00
if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
2019-03-08 16:42:20 -08:00
member.set_command(cmd)
2016-08-06 20:38:47 -07:00
end
end
end
end
function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
2017-05-31 18:46:53 -07:00
if not unitGroup then
2019-03-08 16:42:20 -08:00
return nil
2016-08-06 20:38:47 -07:00
end
2017-05-31 18:46:53 -07:00
local squads = natives.squads
for i=1,#squads do
2019-03-08 16:42:20 -08:00
local squad = squads[i]
if (squad.group == unitGroup) then
return squad
end
2017-05-31 18:46:53 -07:00
end
2019-03-06 22:12:39 -08:00
local squad = unitGroupUtils.createSquad(nil,nil,unitGroup)
squad.kamikaze = mRandom() < unitGroupUtils.calculateKamikazeThreshold(#unitGroup.members, natives)
return squad
2016-08-06 20:38:47 -07:00
end
function unitGroupUtils.calculateKamikazeThreshold(memberCount, natives)
local squadSizeBonus = mLog((memberCount / natives.attackWaveMaxSize) + 0.1) + 1
2017-05-31 18:46:53 -07:00
return natives.kamikazeThreshold + (NO_RETREAT_SQUAD_SIZE_BONUS_MAX * squadSizeBonus)
2017-01-19 21:58:36 -08:00
end
2017-06-10 17:59:06 -07:00
function unitGroupUtils.recycleBiters(natives, biters)
local unitCount = #biters
for i=1,unitCount do
2019-03-08 16:42:20 -08:00
biters[i].destroy()
2017-06-10 17:59:06 -07:00
end
natives.points = natives.points + (unitCount * natives.unitRefundAmount)
if (natives.points > AI_MAX_OVERFLOW_POINTS) then
2019-03-08 16:42:20 -08:00
natives.points = AI_MAX_OVERFLOW_POINTS
2018-01-13 21:48:21 -08:00
end
end
2019-04-07 22:22:02 -07:00
function unitGroupUtils.cleanBuilders(map, natives, surface)
2019-03-06 22:12:39 -08:00
local squads = natives.building
local squadCount = #squads
local startIndex = natives.cleanBuildingIndex
2019-04-07 22:22:02 -07:00
local position = map.position
local cmd = map.compoundSettleCommand
2019-03-06 22:12:39 -08:00
local maxSquadIndex = mMin(startIndex + SQUAD_QUEUE_SIZE, squadCount)
for i=maxSquadIndex,startIndex,-1 do
2019-03-08 16:42:20 -08:00
local squad = squads[i]
local group = squad.group
if not (group and group.valid) then
tRemove(squads, i)
2019-04-07 22:22:02 -07:00
else
if (squad.cycles > 0) then
squad.cycles = squad.cycles - 1
end
if (group.state == DEFINES_GROUP_FINISHED) or (squad.cycles <= 0) then
if (#group.members > 0) then
local groupPosition = findMovementPosition(surface, group.position)
2019-04-08 16:30:09 -07:00
if not groupPosition then
groupPosition = group.position
end
2019-04-07 22:22:02 -07:00
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
end
2019-03-06 22:12:39 -08:00
end
end
2019-03-08 16:42:20 -08:00
if (maxSquadIndex >= squadCount) then
2019-03-06 22:12:39 -08:00
natives.cleanBuildingIndex = 1
else
natives.cleanBuildingIndex = maxSquadIndex + 1
end
end
2019-03-08 16:42:20 -08:00
local function isAttacking(group)
local state = group.state
return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION)
end
2019-03-06 22:12:39 -08:00
2018-01-13 21:48:21 -08:00
function unitGroupUtils.regroupSquads(natives, map)
local squads = natives.squads
local squadCount = #squads
2017-05-31 19:48:59 -07:00
local startIndex = natives.regroupIndex
2018-01-13 21:48:21 -08:00
2017-05-31 19:48:59 -07:00
local maxSquadIndex = mMin(startIndex + SQUAD_QUEUE_SIZE, squadCount)
for i=startIndex,maxSquadIndex do
2019-03-08 16:42:20 -08:00
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 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
end
end
end
end
2019-02-10 22:14:17 -08:00
end
2019-03-06 22:12:39 -08:00
end
end
2017-05-31 19:48:59 -07:00
end
2019-02-10 22:14:17 -08:00
2019-03-08 16:42:20 -08:00
if (maxSquadIndex >= squadCount) then
2019-03-06 22:12:39 -08:00
natives.regroupIndex = 1
2017-05-31 19:48:59 -07:00
else
2019-03-06 22:12:39 -08:00
natives.regroupIndex = maxSquadIndex + 1
2017-05-31 19:48:59 -07:00
end
end
2019-02-15 20:17:30 -08:00
unitGroupUtilsG = unitGroupUtils
return unitGroupUtils