1
0
mirror of https://github.com/veden/Rampant.git synced 2025-07-11 01:10:15 +02:00
Files
Rampant/libs/UnitGroupUtils.lua

273 lines
8.3 KiB
Lua
Raw Normal View History

local unitGroupUtils = {}
-- imports
local mapUtils = require("MapUtils")
2016-08-06 20:38:47 -07:00
local constants = require("Constants")
-- constants
2016-10-14 17:00:18 -07:00
local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
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_FINISHED = defines.group_state.finished
local DEFINES_GROUP_STATE_ATTACKING_TARGET = defines.group_state.attacking_target
local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
2017-05-27 21:50:37 -07:00
local DEFINES_COMMAND_GROUP = defines.command.group
local DEFINES_DISTRACTION_NONE = defines.distraction.none
2017-06-10 01:38:20 -07:00
local MAX_PENALTY_BEFORE_PURGE = constants.MAX_PENALTY_BEFORE_PURGE
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local SQUAD_GUARDING = constants.SQUAD_GUARDING
2017-01-19 21:58:36 -08:00
local GROUP_MERGE_DISTANCE = constants.GROUP_MERGE_DISTANCE
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
-- imported functions
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 tableRemove = table.remove
local tableInsert = table.insert
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
-- module code
2017-01-19 21:58:36 -08:00
2016-08-07 18:35:36 -07:00
function unitGroupUtils.findNearBySquad(natives, position, distance, filter)
local squads = natives.squads
2017-05-31 18:46:53 -07:00
2016-08-25 15:20:06 -07:00
for i=1,#squads do
local squad = squads[i]
2016-08-06 20:38:47 -07:00
local unitGroup = squad.group
2017-05-27 21:50:37 -07:00
if unitGroup.valid and (not filter or (filter and filter[squad.status])) then
if (euclideanDistanceNamed(unitGroup.position, position) <= distance) then
return squad
end
end
end
end
2016-08-06 20:38:47 -07:00
function unitGroupUtils.createSquad(position, surface, natives)
local unitGroup = surface.create_unit_group({position=position})
local squad = { group = unitGroup,
status = SQUAD_GUARDING,
penalties = {},
rabid = false,
frenzy = false,
2016-11-03 16:51:35 -07:00
kamikaze = false,
frenzyPosition = {x = 0,
y = 0},
cycles = 0 }
2016-08-06 20:38:47 -07:00
natives.squads[#natives.squads+1] = squad
return squad
end
function unitGroupUtils.membersToSquad(squad, members, overwriteGroup)
2016-08-07 18:35:36 -07:00
if (members ~= nil) then
2017-05-27 21:50:37 -07:00
local cmd = { type = DEFINES_COMMAND_GROUP,
group = squad.group,
2017-05-27 21:50:37 -07:00
distraction = DEFINES_DISTRACTION_NONE }
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
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
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
local squad = squads[i]
if (squad.group == unitGroup) then
return squad
end
end
local returnSquad = { group = unitGroup,
status = SQUAD_GUARDING,
penalties = {},
rabid = false,
frenzy = false,
kamikaze = false,
frenzyPosition = {x = 0,
y = 0},
cycles = 0 }
squads[#squads+1] = returnSquad
2016-08-06 20:38:47 -07:00
return returnSquad
end
2017-06-10 01:38:20 -07:00
function unitGroupUtils.addSquadMovementPenalty(natives, squad, chunkX, chunkY)
local penalties = squad.penalties
2016-08-25 15:20:06 -07:00
for i=1,#penalties do
local penalty = penalties[i]
if (penalty.x == chunkX) and (penalty.y == chunkY) then
2016-10-14 17:00:18 -07:00
penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
2017-06-10 01:38:20 -07:00
if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then
local group = squad.group
local members = group.members
for x=1,#members do
members[x].destroy()
end
natives.points = natives.points + (#members * natives.unitRefundAmount)
if (natives.points > AI_MAX_OVERFLOW_POINTS) then
natives.points = AI_MAX_OVERFLOW_POINTS
end
group.destroy()
end
return
end
end
2017-06-10 01:38:20 -07:00
if (#penalties == 7) then
tableRemove(penalties, 7)
end
2016-10-14 17:00:18 -07:00
tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
x = chunkX,
y = chunkY })
end
function unitGroupUtils.lookupSquadMovementPenalty(squad, chunkX, chunkY)
local penalties = squad.penalties
2016-08-25 15:20:06 -07:00
for i=1,#penalties do
local penalty = penalties[i]
if (penalty.x == chunkX) and (penalty.y == chunkY) then
return penalty.v
end
end
return 0
end
2016-08-06 20:38:47 -07:00
2017-05-31 18:46:53 -07:00
function unitGroupUtils.calculateKamikazeThreshold(squad, natives)
local squadSizeBonus = mLog((#squad.group.members / natives.attackWaveMaxSize) + 0.1) + 1
return natives.kamikazeThreshold + (NO_RETREAT_SQUAD_SIZE_BONUS_MAX * squadSizeBonus)
2017-01-19 21:58:36 -08:00
end
2017-04-21 16:14:04 -07:00
local function isAttacking(group)
local state = group.state
2017-05-26 17:58:33 -07:00
return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION)
2017-01-19 21:58:36 -08:00
end
2017-05-31 18:46:53 -07:00
function unitGroupUtils.cleanSquads(natives)
2016-08-08 19:18:19 -07:00
local squads = natives.squads
2017-04-21 16:14:04 -07:00
local squadCount = #squads
2017-05-31 18:46:53 -07:00
local weight = natives.unitRefundAmount
local cleanSquads = {}
2017-06-01 00:03:07 -07:00
for i=1, squadCount do
2017-04-21 16:14:04 -07:00
local squad = squads[i]
local group = squad.group
if group.valid then
local memberCount = #group.members
if (memberCount == 0) then
group.destroy()
elseif (memberCount > AI_MAX_BITER_GROUP_SIZE) then
local members = group.members
for x=1,memberCount do
members[x].destroy()
end
2017-05-31 18:46:53 -07:00
natives.points = natives.points + (memberCount * weight)
2017-05-31 18:46:53 -07:00
if (natives.points > AI_MAX_OVERFLOW_POINTS) then
natives.points = AI_MAX_OVERFLOW_POINTS
end
2017-04-21 16:14:04 -07:00
group.destroy()
else
local status = squad.status
local cycles = squad.cycles
if (status == SQUAD_RETREATING) and (cycles == 0) then
squad.status = SQUAD_GUARDING
squad.frenzy = true
2017-05-31 19:48:59 -07:00
local squadPosition = group.position
squad.frenzyPosition.x = squadPosition.x
squad.frenzyPosition.y = squadPosition.y
2017-05-26 17:58:33 -07:00
elseif (group.state == DEFINES_GROUP_STATE_FINISHED) then
squad.status = SQUAD_GUARDING
elseif (cycles > 0) then
squad.cycles = cycles - 1
end
cleanSquads[#cleanSquads+1] = squad
2017-01-19 21:58:36 -08:00
end
end
2016-08-08 19:18:19 -07:00
end
natives.squads = cleanSquads
end
2017-01-19 21:58:36 -08:00
2017-05-31 18:46:53 -07:00
function unitGroupUtils.regroupSquads(natives)
2017-06-01 00:03:07 -07:00
local groupThreshold = AI_SQUAD_MERGE_THRESHOLD
local squads = natives.squads
local squadCount = #squads
2017-05-31 19:48:59 -07:00
local startIndex = natives.regroupIndex
2017-04-21 16:14:04 -07:00
2017-05-31 19:48:59 -07:00
local maxSquadIndex = mMin(startIndex + SQUAD_QUEUE_SIZE, squadCount)
for i=startIndex,maxSquadIndex do
2017-01-19 21:58:36 -08:00
local squad = squads[i]
2017-04-21 16:14:04 -07:00
local group = squad.group
if group.valid and not isAttacking(group) then
2017-04-21 16:14:04 -07:00
local status = squad.status
2017-05-31 19:48:59 -07:00
local memberCount = #group.members
if (memberCount < groupThreshold) then
local squadPosition = group.position
2017-04-21 16:14:04 -07:00
local mergedSquads = false
for x=i+1,squadCount do
local mergeSquad = squads[x]
local mergeGroup = mergeSquad.group
2017-05-31 19:48:59 -07:00
if mergeGroup.valid and (euclideanDistanceNamed(squadPosition, mergeGroup.position) < GROUP_MERGE_DISTANCE) 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
2017-04-21 16:14:04 -07:00
for memberIndex=1, mergeCount do
group.add_member(mergeMembers[memberIndex])
end
if mergeSquad.kamikaze then
squad.kamikaze = true
end
mergedSquads = true
mergeGroup.destroy()
end
memberCount = memberCount + mergeCount
if (memberCount > groupThreshold) then
break
end
end
2017-04-21 16:14:04 -07:00
end
if mergedSquads and not squad.kamikaze then
2017-05-31 18:46:53 -07:00
local kamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold(squad, natives)
if (math.random() < kamikazeThreshold) then
squad.kamikaze = true
end
2017-04-21 16:14:04 -07:00
end
end
end
2017-05-31 19:48:59 -07:00
end
if (maxSquadIndex == squadCount) then
natives.regroupIndex = 1
else
natives.regroupIndex = maxSquadIndex
end
end
return unitGroupUtils