mirror of
https://github.com/veden/Rampant.git
synced 2025-01-14 02:23:01 +02:00
FACTO-59: Finished independent regional base ais
This commit is contained in:
parent
52139e1e3a
commit
12ffd0b2f3
131
Upgrade.lua
131
Upgrade.lua
@ -46,8 +46,6 @@ local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local addBasesToAllEnemyStructures = chunkUtils.addBasesToAllEnemyStructures
|
||||
|
||||
local sFind = string.find
|
||||
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
|
||||
local processPendingChunks = chunkProcessor.processPendingChunks
|
||||
@ -433,13 +431,14 @@ end
|
||||
|
||||
function upgrade.attempt(universe)
|
||||
local starting = global.version
|
||||
if not global.version or global.version < 114 then
|
||||
global.version = 114
|
||||
if not global.version or global.version < 300 then
|
||||
global.version = 300
|
||||
|
||||
if not universe then
|
||||
universe = {}
|
||||
global.universe = universe
|
||||
end
|
||||
|
||||
game.forces.enemy.kill_all_units()
|
||||
|
||||
universe.safeEntities = {}
|
||||
@ -476,6 +475,12 @@ function upgrade.attempt(universe)
|
||||
universe.expansionMinSize = game.map_settings.enemy_expansion.settler_group_min_size
|
||||
universe.expansionMaxSize = game.map_settings.enemy_expansion.settler_group_max_size
|
||||
|
||||
universe.expansionMaxDistanceDerivation = nil
|
||||
universe.expansionLowTargetDistance = (universe.expansionMaxDistance + MINIMUM_EXPANSION_DISTANCE) * 0.33
|
||||
universe.expansionMediumTargetDistance = (universe.expansionMaxDistance + MINIMUM_EXPANSION_DISTANCE) * 0.50
|
||||
universe.expansionHighTargetDistance = (universe.expansionMaxDistance + MINIMUM_EXPANSION_DISTANCE) * 0.75
|
||||
universe.expansionDistanceDeviation = universe.expansionMediumTargetDistance * 0.33
|
||||
|
||||
universe.settlerCooldown = 0
|
||||
universe.settlerWaveDeviation = 0
|
||||
universe.settlerWaveSize = 0
|
||||
@ -500,17 +505,9 @@ function upgrade.attempt(universe)
|
||||
game.forces.enemy.ai_controllable = true
|
||||
|
||||
universe.evolutionLevel = game.forces.enemy.evolution_factor
|
||||
global.pendingChunks = nil
|
||||
global.natives = nil
|
||||
global.map = nil
|
||||
end
|
||||
if global.version < 116 then
|
||||
global.version = 116
|
||||
|
||||
universe.maxPoints = 0
|
||||
end
|
||||
if global.version < 204 then
|
||||
global.version = 204
|
||||
global.pendingChunks = nil -- removes old pendingChunks
|
||||
global.natives = nil -- removes old natives
|
||||
global.map = nil -- removes old map
|
||||
|
||||
universe.eventId = 0
|
||||
universe.chunkId = 0
|
||||
@ -551,39 +548,9 @@ function upgrade.attempt(universe)
|
||||
universe.chunkToPassScanIterator = nil
|
||||
universe.baseId = 0
|
||||
universe.awake = false
|
||||
end
|
||||
if global.version < 205 then
|
||||
global.version = 205
|
||||
|
||||
addCommandSet(universe)
|
||||
end
|
||||
if global.version < 207 then
|
||||
global.version = 207
|
||||
|
||||
for mapId,map in pairs(universe.maps) do
|
||||
local toBeRemoved = not map.surface.valid or isExcludedSurface(map.surface.name)
|
||||
if toBeRemoved then
|
||||
if universe.mapIterator == mapId then
|
||||
universe.mapIterator, universe.activeMap = next(universe.maps, universe.mapIterator)
|
||||
end
|
||||
if universe.processMapAIIterator == mapId then
|
||||
universe.processMapAIIterator = nil
|
||||
end
|
||||
universe.maps[mapId] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if global.version < 208 then
|
||||
global.version = 208
|
||||
|
||||
universe.expansionMaxDistanceDerivation = nil
|
||||
universe.expansionLowTargetDistance = (universe.expansionMaxDistance + MINIMUM_EXPANSION_DISTANCE) * 0.33
|
||||
universe.expansionMediumTargetDistance = (universe.expansionMaxDistance + MINIMUM_EXPANSION_DISTANCE) * 0.50
|
||||
universe.expansionHighTargetDistance = (universe.expansionMaxDistance + MINIMUM_EXPANSION_DISTANCE) * 0.75
|
||||
universe.expansionDistanceDeviation = universe.expansionMediumTargetDistance * 0.33
|
||||
end
|
||||
if global.version < 209 then
|
||||
global.version = 209
|
||||
universe.maxPoints = 0
|
||||
universe.maxOverflowPoints = 0
|
||||
|
||||
if not universe.random then
|
||||
local combinedSeed = settings.startup["rampant--enemySeed"].value+game.default_map_gen_settings.seed
|
||||
@ -594,6 +561,19 @@ function upgrade.attempt(universe)
|
||||
end
|
||||
end
|
||||
|
||||
universe.proxyEntityLookup = {}
|
||||
universe.vanillaEntityLookups = {}
|
||||
|
||||
addCommandSet(universe)
|
||||
|
||||
local evoToTierMapping = {}
|
||||
universe.evoToTierMapping = evoToTierMapping
|
||||
universe.bases = {}
|
||||
|
||||
for i=1,10 do
|
||||
evoToTierMapping[#evoToTierMapping+1] = (((i - 1) * 0.1) ^ 0.5) - 0.05
|
||||
end
|
||||
|
||||
for _,map in pairs(universe.maps) do
|
||||
if (map.surface.valid) then
|
||||
local entities = map.surface.find_entities_filtered({type="land-mine"})
|
||||
@ -606,26 +586,20 @@ function upgrade.attempt(universe)
|
||||
end
|
||||
end
|
||||
|
||||
universe.proxyEntityLookup = {}
|
||||
universe.vanillaEntityLookups = {}
|
||||
end
|
||||
if global.version < 210 then
|
||||
global.version = 210
|
||||
|
||||
addBasesToAllEnemyStructures(universe, game.tick)
|
||||
|
||||
local evoToTierMapping = {}
|
||||
universe.evoToTierMapping = evoToTierMapping
|
||||
|
||||
for i=1,10 do
|
||||
evoToTierMapping[#evoToTierMapping+1] = (((i - 1) * 0.1) ^ 0.5) - 0.05
|
||||
for mapId,map in pairs(universe.maps) do
|
||||
local toBeRemoved = not map.surface.valid or isExcludedSurface(map.surface.name)
|
||||
if toBeRemoved then
|
||||
if universe.mapIterator == mapId then
|
||||
universe.mapIterator, universe.activeMap = next(universe.maps, universe.mapIterator)
|
||||
end
|
||||
if universe.processMapAIIterator == mapId then
|
||||
universe.processMapAIIterator = nil
|
||||
end
|
||||
universe.maps[mapId] = nil
|
||||
end
|
||||
end
|
||||
|
||||
for chunkId in pairs(universe.vengenceQueue) do
|
||||
universe.vengenceQueue[chunkId] = nil
|
||||
end
|
||||
|
||||
game.print("Rampant - Version 2.3.0")
|
||||
game.print("Rampant - Version 3.0.0")
|
||||
end
|
||||
|
||||
return (starting ~= global.version) and global.version
|
||||
@ -650,10 +624,6 @@ function upgrade.prepMap(universe, surface)
|
||||
|
||||
map.activatedMap = false
|
||||
|
||||
-- map.sentSiegeGroups = 0
|
||||
-- map.maxSiegeGroups = 2
|
||||
-- map.maxAggressiveGroups = 1
|
||||
-- map.sentAggressiveGroups = 0
|
||||
map.processedChunks = 0
|
||||
map.processQueue = {}
|
||||
map.processIndex = 1
|
||||
@ -674,6 +644,7 @@ function upgrade.prepMap(universe, surface)
|
||||
map.chunkToTrapIds = {}
|
||||
map.chunkToTurretIds = {}
|
||||
map.chunkToUtilityIds = {}
|
||||
map.drainPylons = {}
|
||||
|
||||
map.chunkToPlayerBase = {}
|
||||
map.chunkToResource = {}
|
||||
@ -700,28 +671,6 @@ function upgrade.prepMap(universe, surface)
|
||||
map.pendingAttack = nil
|
||||
map.building = nil
|
||||
|
||||
-- map.baseIndex = 1
|
||||
-- map.baseIncrement = 0
|
||||
-- map.points = 0
|
||||
-- map.state = constants.AI_STATE_PEACEFUL
|
||||
|
||||
-- map.evolutionLevel = game.forces.enemy.evolution_factor
|
||||
-- map.canAttackTick = 0
|
||||
-- map.drainPylons = {}
|
||||
-- map.activeRaidNests = 0
|
||||
-- map.activeNests = 0
|
||||
-- map.destroyPlayerBuildings = 0
|
||||
-- map.lostEnemyUnits = 0
|
||||
-- map.lostEnemyBuilding = 0
|
||||
-- map.rocketLaunched = 0
|
||||
-- map.builtEnemyBuilding = 0
|
||||
-- map.ionCannonBlasts = 0
|
||||
-- map.artilleryBlasts = 0
|
||||
|
||||
-- map.temperament = 0.5
|
||||
-- map.temperamentScore = 0
|
||||
-- map.stateTick = 0
|
||||
|
||||
map.random = universe.random
|
||||
|
||||
-- queue all current chunks that wont be generated during play
|
||||
|
@ -1,13 +1,16 @@
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 2.3.0
|
||||
Version: 3.0.0
|
||||
improvement:
|
||||
- Modified death pheromone squad path scoring
|
||||
- AI is now per regional base
|
||||
- Regional bases now have there own aggressive and siege squad counter
|
||||
Tweaks:
|
||||
- Added surface minime_dummy_dungeon and minime-preview-character to exclusion list
|
||||
- Increased unit spawner cooldown by 2x
|
||||
- Added point loss on unit death
|
||||
Bugfixes:
|
||||
- Fixed Krastorio2 on_force_created playerforces being nil
|
||||
- Fixed enemy map scan creating bases unnecessarily
|
||||
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 2.2.0
|
||||
|
63
control.lua
63
control.lua
@ -54,6 +54,8 @@ local UNIT_DEATH_POINT_COST = constants.UNIT_DEATH_POINT_COST
|
||||
|
||||
-- imported functions
|
||||
|
||||
local planning = aiPlanning.planning
|
||||
|
||||
local addBasesToAllEnemyStructures = chunkUtils.addBasesToAllEnemyStructures
|
||||
|
||||
local setPointAreaInQuery = queryUtils.setPointAreaInQuery
|
||||
@ -112,7 +114,7 @@ local victoryScent = pheromoneUtils.victoryScent
|
||||
local createSquad = unitGroupUtils.createSquad
|
||||
|
||||
local createBase = baseUtils.createBase
|
||||
local findNearbyBase = baseUtils.findNearbyBase
|
||||
local findNearbyBase = chunkPropertyUtils.findNearbyBase
|
||||
|
||||
local processActiveNests = mapProcessor.processActiveNests
|
||||
|
||||
@ -167,7 +169,7 @@ local function onIonCannonFired(event)
|
||||
base.unitPoints = base.unitPoints + 4000
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. 4000 .. ". [Ion Cannon] Total: " ..
|
||||
string.format("%.2f", base.points))
|
||||
string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -410,10 +412,10 @@ local function onDeath(event)
|
||||
base.lostEnemyUnits = base.lostEnemyUnits + 1
|
||||
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 0.01
|
||||
base.deathEvents = base.deathEvents + 1
|
||||
-- base.points = base.points - UNIT_DEATH_POINT_COST
|
||||
-- if universe.aiPointsPrintSpendingToChat then
|
||||
-- game.print(map.surface.name .. ": Points: -" .. UNIT_DEATH_POINT_COST .. ". [Unit Lost] Total: " .. string.format("%.2f", base.points))
|
||||
-- end
|
||||
base.unitPoints = base.unitPoints - UNIT_DEATH_POINT_COST
|
||||
if universe.aiPointsPrintSpendingToChat then
|
||||
game.print(map.surface.name .. ": Points: -" .. UNIT_DEATH_POINT_COST .. ". [Unit Lost] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
if (universe.random() < universe.rallyThreshold) and not surface.peaceful_mode then
|
||||
rallyUnits(chunk, map, tick, base)
|
||||
end
|
||||
@ -435,16 +437,16 @@ local function onDeath(event)
|
||||
then
|
||||
if base then
|
||||
if (entityType == "unit-spawner") then
|
||||
base.points = base.points + RECOVER_NEST_COST
|
||||
base.unitPoints = base.unitPoints + RECOVER_NEST_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. RECOVER_NEST_COST ..
|
||||
". [Nest Lost] Total: " .. string.format("%.2f", base.points))
|
||||
". [Nest Lost] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
elseif (entityType == "turret") then
|
||||
base.points = base.points + RECOVER_WORM_COST
|
||||
base.unitPoints = base.unitPoints + RECOVER_WORM_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. RECOVER_WORM_COST ..
|
||||
". [Worm Lost] Total: " .. string.format("%.2f", base.points))
|
||||
". [Worm Lost] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
end
|
||||
rallyUnits(chunk, map, tick, base)
|
||||
@ -514,7 +516,7 @@ local function onEnemyBaseBuild(event)
|
||||
event.tick)
|
||||
end
|
||||
|
||||
registerEnemyBaseStructure(map, entity, event.tick, base)
|
||||
registerEnemyBaseStructure(map, entity, base)
|
||||
|
||||
if universe.NEW_ENEMIES then
|
||||
upgradeEntity(entity,
|
||||
@ -644,9 +646,9 @@ local function onRocketLaunch(event)
|
||||
if (chunk ~= -1) then
|
||||
local base = findNearbyBase(map, chunk)
|
||||
base.rocketLaunched = base.rocketLaunched + 1
|
||||
base.points = base.points + 5000
|
||||
base.unitPoints = base.unitPoints + 5000
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. 5000 .. ". [Rocket Launch] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. 5000 .. ". [Rocket Launch] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -706,7 +708,7 @@ local function onEntitySpawned(event)
|
||||
event.tick)
|
||||
end
|
||||
|
||||
registerEnemyBaseStructure(map, entity, event.tick, base, true)
|
||||
registerEnemyBaseStructure(map, entity, base, true)
|
||||
|
||||
upgradeEntity(entity,
|
||||
base,
|
||||
@ -763,14 +765,14 @@ local function onUnitGroupCreated(event)
|
||||
|
||||
if not settler and (universe.squadCount > universe.AI_MAX_SQUAD_COUNT) then
|
||||
group.destroy()
|
||||
base.points = base.points + AI_SQUAD_COST
|
||||
base.unitPoints = base.unitPoints + AI_SQUAD_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
squad = createSquad(nil, map, group, settler)
|
||||
squad = createSquad(nil, map, group, settler, base)
|
||||
universe.groupNumberToSquad[group.group_number] = squad
|
||||
|
||||
squad.base = base
|
||||
@ -792,14 +794,14 @@ local function onUnitGroupCreated(event)
|
||||
|
||||
if not settler and (universe.squadCount > universe.AI_MAX_SQUAD_COUNT) then
|
||||
group.destroy()
|
||||
base.points = base.points + AI_SQUAD_COST
|
||||
base.unitPoints = base.unitPoints + AI_SQUAD_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
squad = createSquad(nil, map, group, settler)
|
||||
squad = createSquad(nil, map, group, settler, base)
|
||||
universe.groupNumberToSquad[group.group_number] = squad
|
||||
|
||||
squad.base = base
|
||||
@ -830,9 +832,9 @@ local function onGroupFinishedGathering(event)
|
||||
squadDispatch(map, squad, event.tick)
|
||||
else
|
||||
group.destroy()
|
||||
base.points = base.points + AI_SETTLER_COST
|
||||
base.unitPoints = base.unitPoints + AI_SETTLER_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SETTLER_COST .. ". [Settler Refund] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SETTLER_COST .. ". [Settler Refund] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -840,9 +842,9 @@ local function onGroupFinishedGathering(event)
|
||||
squadDispatch(map, squad, event.tick)
|
||||
else
|
||||
group.destroy()
|
||||
base.points = base.points + AI_SQUAD_COST
|
||||
base.unitPoints = base.unitPoints + AI_SQUAD_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -855,14 +857,14 @@ local function onGroupFinishedGathering(event)
|
||||
|
||||
if not settler and (universe.squadCount > universe.AI_MAX_SQUAD_COUNT) then
|
||||
group.destroy()
|
||||
base.points = base.points + AI_SQUAD_COST
|
||||
base.unitPoints = base.unitPoints + AI_SQUAD_COST
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
squad = createSquad(nil, map, group, settler)
|
||||
squad = createSquad(nil, map, group, settler, base)
|
||||
universe.groupNumberToSquad[group.group_number] = squad
|
||||
if settler then
|
||||
universe.builderCount = universe.builderCount + 1
|
||||
@ -985,12 +987,13 @@ script.on_event(defines.events.on_tick,
|
||||
elseif (pick == 7) then
|
||||
processPendingChunks(universe, tick)
|
||||
processScanChunks(universe)
|
||||
planning(universe, gameRef.forces.enemy.evolution_factor)
|
||||
end
|
||||
|
||||
processBaseAIs(universe, gameRef.forces.enemy.evolution_factor, tick)
|
||||
processBaseAIs(universe, tick)
|
||||
processActiveNests(universe, tick)
|
||||
processPendingUpgrades(universe, tick)
|
||||
processPendingUpgrades(universe, tick)
|
||||
processPendingUpgrades(universe)
|
||||
processPendingUpgrades(universe)
|
||||
cleanSquads(universe, tick)
|
||||
|
||||
-- game.print({"", "--dispatch4 ", profiler, ", ", pick, ", ", game.tick, " ", universe.random()})
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name" : "Rampant",
|
||||
"factorio_version" : "1.1",
|
||||
"version" : "2.3.0",
|
||||
"version" : "3.0.0",
|
||||
"title" : "Rampant",
|
||||
"author" : "Veden",
|
||||
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
||||
|
@ -54,8 +54,6 @@ local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local findNearbyBase = baseUtils.findNearbyBase
|
||||
|
||||
local calculateKamikazeSettlerThreshold = unitGroupUtils.calculateKamikazeSettlerThreshold
|
||||
local calculateKamikazeSquadThreshold = unitGroupUtils.calculateKamikazeSquadThreshold
|
||||
|
||||
@ -99,7 +97,10 @@ end
|
||||
|
||||
local function attackWaveValidCandidate(chunk, map, base)
|
||||
local isValid = getNestActiveness(map, chunk)
|
||||
if (base.stateAI == BASE_AI_STATE_RAIDING) or (base.stateAI == BASE_AI_STATE_SIEGE) or (base.stateAI == BASE_AI_STATE_ONSLAUGHT) then
|
||||
if (base.stateAI == BASE_AI_STATE_RAIDING) or
|
||||
(base.stateAI == BASE_AI_STATE_SIEGE) or
|
||||
(base.stateAI == BASE_AI_STATE_ONSLAUGHT)
|
||||
then
|
||||
isValid = isValid + getRaidNestActiveness(map, chunk)
|
||||
end
|
||||
return (isValid > 0)
|
||||
@ -216,7 +217,7 @@ function aiAttackWave.formSettlers(map, chunk, base)
|
||||
then
|
||||
local surface = map.surface
|
||||
local squadPath, squadDirection
|
||||
if (map.state == BASE_AI_STATE_SIEGE) then
|
||||
if (base.stateAI == BASE_AI_STATE_SIEGE) then
|
||||
squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
||||
validSiegeSettlerLocation,
|
||||
scoreSiegeSettlerLocation,
|
||||
@ -238,7 +239,7 @@ function aiAttackWave.formSettlers(map, chunk, base)
|
||||
4,
|
||||
true)
|
||||
if squadPosition then
|
||||
local squad = createSquad(squadPosition, map, nil, true)
|
||||
local squad = createSquad(squadPosition, map, nil, true, base)
|
||||
|
||||
local scaledWaveSize = settlerWaveScaling(universe)
|
||||
universe.formGroupCommand.group = squad.group
|
||||
@ -294,7 +295,7 @@ function aiAttackWave.formVengenceSquad(map, chunk, base)
|
||||
4,
|
||||
true)
|
||||
if squadPosition then
|
||||
local squad = createSquad(squadPosition, map)
|
||||
local squad = createSquad(squadPosition, map, nil, false, base)
|
||||
|
||||
squad.rabid = map.random() < 0.03
|
||||
|
||||
@ -342,7 +343,7 @@ function aiAttackWave.formVengenceSettler(map, chunk, base)
|
||||
4,
|
||||
true)
|
||||
if squadPosition then
|
||||
local squad = createSquad(squadPosition, map, nil, true)
|
||||
local squad = createSquad(squadPosition, map, nil, true, base)
|
||||
|
||||
squad.rabid = map.random() < 0.03
|
||||
|
||||
@ -391,7 +392,7 @@ function aiAttackWave.formSquads(map, chunk, base)
|
||||
4,
|
||||
true)
|
||||
if squadPosition then
|
||||
local squad = createSquad(squadPosition, map)
|
||||
local squad = createSquad(squadPosition, map, nil, false, base)
|
||||
|
||||
squad.rabid = map.random() < 0.03
|
||||
|
||||
|
@ -23,32 +23,27 @@ local aiPlanning = {}
|
||||
|
||||
local constants = require("Constants")
|
||||
local mathUtils = require("MathUtils")
|
||||
local baseUtils = require("BaseUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local BASE_PROCESS_INTERVAL = constants.BASE_PROCESS_INTERVAL
|
||||
|
||||
local BASE_GENERATION_STATE_ACTIVE = constants.BASE_GENERATION_STATE_ACTIVE
|
||||
local BASE_GENERATION_STATE_DORMANT = constants.BASE_GENERATION_STATE_DORMANT
|
||||
|
||||
local BASE_GENERATION_MIN_STATE_DURATION = constants.BASE_GENERATION_MIN_STATE_DURATION
|
||||
local BASE_GENERATION_MAX_STATE_DURATION = constants.BASE_GENERATION_MAX_STATE_DURATION
|
||||
|
||||
local TEMPERAMENT_RANGE_MAX = constants.TEMPERAMENT_RANGE_MAX
|
||||
local TEMPERAMENT_RANGE_MIN = constants.TEMPERAMENT_RANGE_MIN
|
||||
local TEMPERAMENT_DIVIDER = constants.TEMPERAMENT_DIVIDER
|
||||
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
|
||||
local ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS = constants.ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS
|
||||
local NO_RETREAT_BASE_PERCENT = constants.NO_RETREAT_BASE_PERCENT
|
||||
local NO_RETREAT_EVOLUTION_BONUS_MAX = constants.NO_RETREAT_EVOLUTION_BONUS_MAX
|
||||
|
||||
local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
|
||||
local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
|
||||
local BASE_AI_STATE_RAIDING = constants.BASE_AI_STATE_RAIDING
|
||||
local BASE_AI_STATE_MIGRATING = constants.BASE_AI_STATE_MIGRATING
|
||||
local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
|
||||
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
|
||||
|
||||
local AI_UNIT_REFUND = constants.AI_UNIT_REFUND
|
||||
|
||||
local AI_MAX_POINTS = constants.AI_MAX_POINTS
|
||||
local AI_POINT_GENERATOR_AMOUNT = constants.AI_POINT_GENERATOR_AMOUNT
|
||||
|
||||
local AI_MIN_STATE_DURATION = constants.AI_MIN_STATE_DURATION
|
||||
local AI_MAX_STATE_DURATION = constants.AI_MAX_STATE_DURATION
|
||||
|
||||
local BASE_RALLY_CHANCE = constants.BASE_RALLY_CHANCE
|
||||
local BONUS_RALLY_CHANCE = constants.BONUS_RALLY_CHANCE
|
||||
@ -57,18 +52,37 @@ local RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN = constants.RETREAT_MOVEMENT_PHEROMON
|
||||
local RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX = constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX
|
||||
local MINIMUM_AI_POINTS = constants.MINIMUM_AI_POINTS
|
||||
|
||||
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
|
||||
local ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS = constants.ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS
|
||||
|
||||
local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
|
||||
local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
|
||||
local BASE_AI_STATE_RAIDING = constants.BASE_AI_STATE_RAIDING
|
||||
local BASE_AI_STATE_MIGRATING = constants.BASE_AI_STATE_MIGRATING
|
||||
local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
|
||||
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
|
||||
local AI_POINT_GENERATOR_AMOUNT = constants.AI_POINT_GENERATOR_AMOUNT
|
||||
|
||||
local BASE_AI_MIN_STATE_DURATION = constants.BASE_AI_MIN_STATE_DURATION
|
||||
local BASE_AI_MAX_STATE_DURATION = constants.BASE_AI_MAX_STATE_DURATION
|
||||
|
||||
|
||||
-- imported functions
|
||||
|
||||
local randomTickEvent = mathUtils.randomTickEvent
|
||||
|
||||
local upgradeBaseBasedOnDamage = baseUtils.upgradeBaseBasedOnDamage
|
||||
|
||||
local linearInterpolation = mathUtils.linearInterpolation
|
||||
|
||||
local mFloor = math.floor
|
||||
local mCeil = math.ceil
|
||||
|
||||
local mMax = math.max
|
||||
local mMin = math.min
|
||||
|
||||
local mCeil = math.ceil
|
||||
|
||||
-- module code
|
||||
|
||||
local function getTimeStringFromTick(tick)
|
||||
@ -82,8 +96,8 @@ local function getTimeStringFromTick(tick)
|
||||
return days .. "d " .. hours .. "h " .. minutes .. "m " .. seconds .. "s"
|
||||
end
|
||||
|
||||
|
||||
local function planning(universe, base, evolutionLevel, tick)
|
||||
function aiPlanning.planning(universe, evolutionLevel)
|
||||
universe.evolutionLevel = evolutionLevel
|
||||
local maxPoints = mMax(AI_MAX_POINTS * evolutionLevel, MINIMUM_AI_POINTS)
|
||||
universe.maxPoints = maxPoints
|
||||
|
||||
@ -101,15 +115,6 @@ local function planning(universe, base, evolutionLevel, tick)
|
||||
universe.attackWaveDeviation = (universe.attackWaveSize * 0.333)
|
||||
universe.attackWaveUpperBound = universe.attackWaveSize + (universe.attackWaveSize * 0.35)
|
||||
|
||||
if (base.canAttackTick < tick) then
|
||||
base.maxAggressiveGroups = mCeil(base.activeNests / ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS)
|
||||
base.sentAggressiveGroups = 0
|
||||
base.canAttackTick = randomTickEvent(universe.random,
|
||||
tick,
|
||||
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
|
||||
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
|
||||
end
|
||||
|
||||
if (universe.attackWaveSize < 1) then
|
||||
universe.attackWaveSize = 2
|
||||
universe.attackWaveDeviation = 1
|
||||
@ -127,18 +132,31 @@ local function planning(universe, base, evolutionLevel, tick)
|
||||
|
||||
universe.unitRefundAmount = AI_UNIT_REFUND * evolutionLevel
|
||||
universe.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolutionLevel * NO_RETREAT_EVOLUTION_BONUS_MAX)
|
||||
end
|
||||
|
||||
local points = ((AI_POINT_GENERATOR_AMOUNT * universe.random()) + (base.activeNests * 0.003) +
|
||||
(AI_POINT_GENERATOR_AMOUNT * mMax(evolutionLevel ^ 2.5, 0.1)))
|
||||
local function processBase(universe, base, tick)
|
||||
|
||||
if (base.canAttackTick < tick) then
|
||||
base.maxAggressiveGroups = mCeil(base.activeNests / ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS)
|
||||
base.sentAggressiveGroups = 0
|
||||
base.canAttackTick = randomTickEvent(universe.random,
|
||||
tick,
|
||||
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
|
||||
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
|
||||
end
|
||||
|
||||
local points = (AI_POINT_GENERATOR_AMOUNT * universe.random()) +
|
||||
(base.activeNests * 0.144) +
|
||||
(AI_POINT_GENERATOR_AMOUNT * mMax(universe.evolutionLevel ^ 2.5, 0.1))
|
||||
|
||||
if (base.temperament == 0) or (base.temperament == 1) then
|
||||
points = points + 0.5
|
||||
points = points + 24
|
||||
elseif (base.temperament < 0.20) or (base.temperament > 0.80) then
|
||||
points = points + 0.3
|
||||
points = points + 14.4
|
||||
elseif (base.temperament < 0.35) or (base.temperament > 0.65) then
|
||||
points = points + 0.2
|
||||
points = points + 9.6
|
||||
elseif (base.temperament < 0.45) or (base.temperament > 0.55) then
|
||||
points = points + 0.1
|
||||
points = points + 4.8
|
||||
end
|
||||
|
||||
if (base.stateAI == BASE_AI_STATE_ONSLAUGHT) then
|
||||
@ -147,23 +165,199 @@ local function planning(universe, base, evolutionLevel, tick)
|
||||
|
||||
points = points * universe.aiPointsScaler
|
||||
|
||||
base.points = points * 30
|
||||
base.unitPoints = points * 30
|
||||
|
||||
local currentPoints = base.points
|
||||
local currentPoints = base.unitPoints
|
||||
|
||||
if (currentPoints <= 0) then
|
||||
currentPoints = 0
|
||||
end
|
||||
|
||||
if (currentPoints < maxPoints) then
|
||||
base.points = currentPoints + points
|
||||
if (currentPoints < universe.maxPoints) then
|
||||
base.unitPoints = currentPoints + points
|
||||
elseif currentPoints > universe.maxOverflowPoints then
|
||||
base.unitPoints = universe.maxOverflowPoints
|
||||
end
|
||||
|
||||
if (currentPoints > maxOverflowPoints) then
|
||||
base.points = maxOverflowPoints
|
||||
if (base.points < universe.maxPoints) then
|
||||
base.points = base.points + (points * 0.75)
|
||||
else
|
||||
base.points = universe.maxPoints
|
||||
end
|
||||
|
||||
local deathThreshold
|
||||
local evolutionLevel = universe.evolutionLevel
|
||||
if (evolutionLevel < 0.5) then
|
||||
deathThreshold = 4500
|
||||
elseif (evolutionLevel < 0.7) then
|
||||
deathThreshold = 7500
|
||||
elseif (evolutionLevel < 0.9) then
|
||||
deathThreshold = 11000
|
||||
else
|
||||
deathThreshold = 16000
|
||||
end
|
||||
|
||||
deathThreshold = universe.adaptationModifier * deathThreshold
|
||||
if ((base.deathEvents > deathThreshold) and (universe.random() > 0.95)) then
|
||||
if (base.mutations < universe.MAX_BASE_MUTATIONS) then
|
||||
base.mutations = base.mutations + 1
|
||||
upgradeBaseBasedOnDamage(universe, base)
|
||||
elseif (base.mutations == universe.MAX_BASE_MUTATIONS) then
|
||||
local roll = universe.random()
|
||||
if (roll < 0.001) then
|
||||
base.mutations = 0
|
||||
if (universe.printBaseAdaptation) then
|
||||
game.print({"description.rampant--adaptationResetDebugMessage",
|
||||
base.x,
|
||||
base.y,
|
||||
base.mutations,
|
||||
universe.MAX_BASE_MUTATIONS})
|
||||
end
|
||||
elseif (roll > 0.999) then
|
||||
base.mutations = base.mutations + 1
|
||||
if (universe.printBaseAdaptation) then
|
||||
game.print({"description.rampant--adaptationFrozenDebugMessage",
|
||||
base.x,
|
||||
base.y})
|
||||
end
|
||||
end
|
||||
end
|
||||
base.damagedBy = {}
|
||||
base.deathEvents = 0
|
||||
end
|
||||
|
||||
if (base.stateGenerationTick <= tick) then
|
||||
local roll = universe.random()
|
||||
if (roll < 0.85) then
|
||||
base.stateGeneration = BASE_GENERATION_STATE_ACTIVE
|
||||
else
|
||||
base.stateGeneration = BASE_GENERATION_STATE_DORMANT
|
||||
end
|
||||
base.stateGenerationTick = randomTickEvent(universe.random,
|
||||
tick,
|
||||
BASE_GENERATION_MIN_STATE_DURATION,
|
||||
BASE_GENERATION_MAX_STATE_DURATION)
|
||||
end
|
||||
|
||||
base.tick = tick
|
||||
end
|
||||
|
||||
local function temperamentPlanner(base, evolutionLevel)
|
||||
local destroyPlayerBuildings = base.destroyPlayerBuildings
|
||||
local lostEnemyUnits = base.lostEnemyUnits
|
||||
local lostEnemyBuilding = base.lostEnemyBuilding
|
||||
local rocketLaunched = base.rocketLaunched
|
||||
local builtEnemyBuilding = base.builtEnemyBuilding
|
||||
local ionCannonBlasts = base.ionCannonBlasts
|
||||
local artilleryBlasts = base.artilleryBlasts
|
||||
local activeNests = base.activeNests
|
||||
local activeRaidNests = base.activeRaidNests
|
||||
|
||||
local currentTemperament = base.temperamentScore
|
||||
local delta = 0
|
||||
|
||||
if activeNests > 0 then
|
||||
local val = (5.76 * activeNests)
|
||||
delta = delta + val
|
||||
else
|
||||
delta = delta - 5.553792
|
||||
end
|
||||
|
||||
if destroyPlayerBuildings > 0 then
|
||||
if currentTemperament > 0 then
|
||||
delta = delta - (5.553792 * destroyPlayerBuildings)
|
||||
else
|
||||
delta = delta + (5.553792 * destroyPlayerBuildings)
|
||||
end
|
||||
end
|
||||
|
||||
if activeRaidNests > 0 then
|
||||
local val = (0.2304 * activeRaidNests)
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta - 3.84
|
||||
end
|
||||
|
||||
if lostEnemyUnits > 0 then
|
||||
local multipler
|
||||
if evolutionLevel < 0.3 then
|
||||
multipler = 0.083328
|
||||
elseif evolutionLevel < 0.5 then
|
||||
multipler = 0.041472
|
||||
elseif evolutionLevel < 0.7 then
|
||||
multipler = 0.020736
|
||||
elseif evolutionLevel < 0.9 then
|
||||
multipler = 0.010368
|
||||
elseif evolutionLevel < 0.9 then
|
||||
multipler = 0.005184
|
||||
else
|
||||
multipler = 0.002592
|
||||
end
|
||||
local val = (multipler * lostEnemyUnits)
|
||||
if (currentTemperament > 0) then
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta + val
|
||||
end
|
||||
end
|
||||
|
||||
if lostEnemyBuilding > 0 then
|
||||
local val = (0.576 * lostEnemyBuilding)
|
||||
if (currentTemperament > 0) then
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta + val
|
||||
end
|
||||
end
|
||||
|
||||
if builtEnemyBuilding > 0 then
|
||||
local val = (0.261952 * builtEnemyBuilding)
|
||||
if (currentTemperament > 0) then
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta + val
|
||||
end
|
||||
else
|
||||
delta = delta - 2.777088
|
||||
end
|
||||
|
||||
if (rocketLaunched > 0) then
|
||||
local val = (27.76 * rocketLaunched)
|
||||
delta = delta + val
|
||||
end
|
||||
|
||||
if (ionCannonBlasts > 0) then
|
||||
local val = (13.924864 * ionCannonBlasts)
|
||||
delta = delta + val
|
||||
end
|
||||
|
||||
if (artilleryBlasts > 0) then
|
||||
local val = (13.924864 * artilleryBlasts)
|
||||
delta = delta + val
|
||||
end
|
||||
|
||||
local universe = base.universe
|
||||
|
||||
delta = delta * universe.temperamentRateModifier
|
||||
base.temperamentScore = mMin(TEMPERAMENT_RANGE_MAX, mMax(TEMPERAMENT_RANGE_MIN, currentTemperament + delta))
|
||||
base.temperament = ((base.temperamentScore + TEMPERAMENT_RANGE_MAX) * TEMPERAMENT_DIVIDER)
|
||||
|
||||
if universe.debugTemperament then
|
||||
game.print("Rampant Stats:\naN:" .. base.activeNests .. ", aRN:" .. base.activeRaidNests .. ", dPB:" ..
|
||||
base.destroyPlayerBuildings .. ", lEU:" .. base.lostEnemyUnits .. ", lEB:" ..
|
||||
base.lostEnemyBuilding .. ", rL:" .. base.rocketLaunched .. ", bEB:" ..
|
||||
base.builtEnemyBuilding .. ", iCB:" .. base.ionCannonBlasts .. ", aB:" ..
|
||||
base.artilleryBlasts .. ", temp:" .. base.temperament .. ", tempScore:" .. base.temperamentScore ..
|
||||
", points:" .. base.points .. ", unitPoints:" .. base.unitPoints .. ", state:" ..
|
||||
constants.stateEnglish[base.stateAI] .. ", surface:" .. base.surface.index .. " [" ..
|
||||
base.surface.name .. "]" .. ", aS:" .. universe.squadCount .. ", aB:" .. universe.builderCount ..
|
||||
", atkSize:" .. universe.attackWaveSize .. ", stlSize:" .. universe.settlerWaveSize ..
|
||||
", formGroup:" .. universe.formSquadThreshold .. ", sAgg:".. base.sentAggressiveGroups ..
|
||||
", mAgg:" .. base.maxAggressiveGroups .. ", baseState:" .. base.generationState ..
|
||||
", baseId:".. base.id)
|
||||
end
|
||||
end
|
||||
|
||||
local function processState(universe, base, tick)
|
||||
|
||||
if (base.stateAITick > tick) or not universe.awake then
|
||||
if (not universe.awake) and (tick >= universe.initialPeaceTime) then
|
||||
universe.awake = true
|
||||
@ -339,129 +533,17 @@ local function planning(universe, base, evolutionLevel, tick)
|
||||
base.ionCannonBlasts = 0
|
||||
base.artilleryBlasts = 0
|
||||
|
||||
base.stateAITick = randomTickEvent(universe.random, tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
|
||||
base.stateAITick = randomTickEvent(universe.random, tick, BASE_AI_MIN_STATE_DURATION, BASE_AI_MAX_STATE_DURATION)
|
||||
|
||||
if universe.printAIStateChanges then
|
||||
game.print(base.index .. ": AI is now: " .. constants.stateEnglish[base.stateAI] .. ", Next state change is in "
|
||||
.. string.format("%.2f", (base.stateAITick - tick) / (60*60)) .. " minutes @ " ..
|
||||
getTimeStringFromTick(base.stateAITick) .. " playtime")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function temperamentPlanner(base, evolutionLevel)
|
||||
local destroyPlayerBuildings = base.destroyPlayerBuildings
|
||||
local lostEnemyUnits = base.lostEnemyUnits
|
||||
local lostEnemyBuilding = base.lostEnemyBuilding
|
||||
local rocketLaunched = base.rocketLaunched
|
||||
local builtEnemyBuilding = base.builtEnemyBuilding
|
||||
local ionCannonBlasts = base.ionCannonBlasts
|
||||
local artilleryBlasts = base.artilleryBlasts
|
||||
local activeNests = base.activeNests
|
||||
local activeRaidNests = base.activeRaidNests
|
||||
|
||||
local currentTemperament = base.temperamentScore
|
||||
local delta = 0
|
||||
|
||||
if activeNests > 0 then
|
||||
local val = (0.015 * activeNests)
|
||||
delta = delta + val
|
||||
else
|
||||
delta = delta - 0.014463
|
||||
end
|
||||
|
||||
if destroyPlayerBuildings > 0 then
|
||||
if currentTemperament > 0 then
|
||||
delta = delta - (0.014463 * destroyPlayerBuildings)
|
||||
else
|
||||
delta = delta + (0.014463 * destroyPlayerBuildings)
|
||||
end
|
||||
end
|
||||
|
||||
if activeRaidNests > 0 then
|
||||
local val = (0.0006 * activeRaidNests)
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta - 0.01
|
||||
end
|
||||
|
||||
if lostEnemyUnits > 0 then
|
||||
local multipler
|
||||
if evolutionLevel < 0.3 then
|
||||
multipler = 0.000217
|
||||
elseif evolutionLevel < 0.5 then
|
||||
multipler = 0.000108
|
||||
elseif evolutionLevel < 0.7 then
|
||||
multipler = 0.000054
|
||||
elseif evolutionLevel < 0.9 then
|
||||
multipler = 0.000027
|
||||
elseif evolutionLevel < 0.9 then
|
||||
multipler = 0.0000135
|
||||
else
|
||||
multipler = 0.00000675
|
||||
end
|
||||
local val = (multipler * lostEnemyUnits)
|
||||
if (currentTemperament > 0) then
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta + val
|
||||
end
|
||||
end
|
||||
|
||||
if lostEnemyBuilding > 0 then
|
||||
local val = (0.0015 * lostEnemyBuilding)
|
||||
if (currentTemperament > 0) then
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta + val
|
||||
end
|
||||
end
|
||||
|
||||
if builtEnemyBuilding > 0 then
|
||||
local val = (0.0006818 * builtEnemyBuilding)
|
||||
if (currentTemperament > 0) then
|
||||
delta = delta - val
|
||||
else
|
||||
delta = delta + val
|
||||
end
|
||||
else
|
||||
delta = delta - 0.007232
|
||||
end
|
||||
|
||||
if (rocketLaunched > 0) then
|
||||
local val = (0.289268 * rocketLaunched)
|
||||
delta = delta + val
|
||||
end
|
||||
|
||||
if (ionCannonBlasts > 0) then
|
||||
local val = (0.144634 * ionCannonBlasts)
|
||||
delta = delta + val
|
||||
end
|
||||
|
||||
if (artilleryBlasts > 0) then
|
||||
local val = (0.144634 * artilleryBlasts)
|
||||
delta = delta + val
|
||||
end
|
||||
|
||||
local universe = base.universe
|
||||
|
||||
delta = delta * universe.temperamentRateModifier
|
||||
base.temperamentScore = mMin(TEMPERAMENT_RANGE_MAX, mMax(TEMPERAMENT_RANGE_MIN, currentTemperament + delta))
|
||||
base.temperament = ((base.temperamentScore + TEMPERAMENT_RANGE_MAX) * TEMPERAMENT_DIVIDER)
|
||||
|
||||
if universe.debugTemperament then
|
||||
if game.tick % 243 == 0 then
|
||||
game.print("Rampant Stats:")
|
||||
game.print("aN:" .. base.activeNests .. ", aRN:" .. base.activeRaidNests .. ", dPB:" .. base.destroyPlayerBuildings ..
|
||||
", lEU:" .. base.lostEnemyUnits .. ", lEB:" .. base.lostEnemyBuilding .. ", rL:" .. base.rocketLaunched .. ", bEB:" .. base.builtEnemyBuilding ..
|
||||
", iCB:" .. base.ionCannonBlasts .. ", aB:" .. base.artilleryBlasts)
|
||||
game.print("temp: " .. base.temperament .. ", tempScore:" .. base.temperamentScore .. ", points:" .. base.points .. ", state:" .. constants.stateEnglish[base.state] .. ", surface:" .. base.surface.index .. " [" .. base.surface.name .. "]")
|
||||
game.print("aS:" .. universe.squadCount .. ", aB:" .. universe.builderCount .. ", atkSize:" .. universe.attackWaveSize .. ", stlSize:" .. universe.settlerWaveSize .. ", formGroup:" .. universe.formSquadThreshold)
|
||||
game.print("sAgg:".. base.sentAggressiveGroups .. ", mAgg:" .. base.maxAggressiveGroups)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function aiPlanning.processBaseAIs(universe, evo, tick)
|
||||
function aiPlanning.processBaseAIs(universe, tick)
|
||||
local baseId = universe.processBaseAIIterator
|
||||
local base
|
||||
if not baseId then
|
||||
@ -474,12 +556,12 @@ function aiPlanning.processBaseAIs(universe, evo, tick)
|
||||
return
|
||||
else
|
||||
universe.processBaseAIIterator = next(universe.bases, baseId)
|
||||
universe.evolutionLevel = evo
|
||||
planning(universe, base, evo, tick)
|
||||
temperamentPlanner(base, evo)
|
||||
if not universe.processBaseAIIterator then
|
||||
if (tick - base.tick) <= BASE_PROCESS_INTERVAL then
|
||||
return
|
||||
end
|
||||
temperamentPlanner(base, universe.evolutionLevel)
|
||||
processState(universe, base, tick)
|
||||
processBase(universe, base, tick)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,7 +37,7 @@ local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
|
||||
|
||||
function aiPredicates.canAttack(map, base)
|
||||
local surface = map.surface
|
||||
local goodAI = (((base.stateAI == BASE_AI_STATE_AGGRESSIVE) and (map.sentAggressiveGroups < map.maxAggressiveGroups)) or
|
||||
local goodAI = (((base.stateAI == BASE_AI_STATE_AGGRESSIVE) and (base.sentAggressiveGroups < base.maxAggressiveGroups)) or
|
||||
(base.stateAI == BASE_AI_STATE_RAIDING) or
|
||||
(base.stateAI == BASE_AI_STATE_ONSLAUGHT) or
|
||||
(map.universe.raidAIToggle and (base.stateAI == BASE_AI_STATE_SIEGE) and (base.sentSiegeGroups >= base.maxSiegeGroups)))
|
||||
|
@ -37,13 +37,9 @@ local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
||||
local FACTIONS_BY_DAMAGE_TYPE = constants.FACTIONS_BY_DAMAGE_TYPE
|
||||
|
||||
local BASE_GENERATION_STATE_ACTIVE = constants.BASE_GENERATION_STATE_ACTIVE
|
||||
local BASE_GENERATION_STATE_DORMANT = constants.BASE_GENERATION_STATE_DORMANT
|
||||
|
||||
local FACTION_SET = constants.FACTION_SET
|
||||
|
||||
local BASE_GENERATION_MIN_STATE_DURATION = constants.BASE_GENERATION_MIN_STATE_DURATION
|
||||
local BASE_GENERATION_MAX_STATE_DURATION = constants.BASE_GENERATION_MAX_STATE_DURATION
|
||||
|
||||
local HIVE_BUILDINGS_COST = constants.HIVE_BUILDINGS_COST
|
||||
|
||||
local BASE_DISTANCE_THRESHOLD = constants.BASE_DISTANCE_THRESHOLD
|
||||
@ -52,17 +48,13 @@ local BASE_DISTANCE_TO_EVO_INDEX = constants.BASE_DISTANCE_TO_EVO_INDEX
|
||||
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
local BASE_PROCESS_INTERVAL = constants.BASE_PROCESS_INTERVAL
|
||||
|
||||
local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
|
||||
|
||||
-- imported functions
|
||||
|
||||
local setPositionXYInQuery = queryUtils.setPositionXYInQuery
|
||||
|
||||
local randomTickEvent = mathUtils.randomTickEvent
|
||||
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
|
||||
local manhattenDistancePoints = mathUtils.manhattenDistancePoints
|
||||
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
|
||||
@ -76,8 +68,6 @@ local mMin = math.min
|
||||
local mMax = math.max
|
||||
local distort = mathUtils.distort
|
||||
|
||||
local getChunkBase = chunkPropertyUtils.getChunkBase
|
||||
|
||||
local getResourceGenerator = chunkPropertyUtils.getResourceGenerator
|
||||
|
||||
local next = next
|
||||
@ -99,34 +89,11 @@ local function evoToTier(universe, evolutionFactor, maxSkips)
|
||||
return v
|
||||
end
|
||||
|
||||
function baseUtils.findNearbyBase(map, chunk)
|
||||
local x = chunk.x
|
||||
local y = chunk.y
|
||||
|
||||
local foundBase = getChunkBase(map, chunk)
|
||||
if foundBase then
|
||||
return foundBase
|
||||
end
|
||||
|
||||
local bases = map.bases
|
||||
local closest = MAGIC_MAXIMUM_NUMBER
|
||||
for _, base in pairs(bases) do
|
||||
local distance = manhattenDistancePoints(base.x, base.y, x, y)
|
||||
if (distance <= base.distanceThreshold) and (distance < closest) then
|
||||
closest = distance
|
||||
foundBase = base
|
||||
end
|
||||
end
|
||||
|
||||
return foundBase
|
||||
end
|
||||
|
||||
local function findBaseMutation(map, targetEvolution)
|
||||
local universe = map.universe
|
||||
local function findBaseMutation(universe, targetEvolution)
|
||||
local tier = evoToTier(universe, targetEvolution or universe.evolutionLevel, 2)
|
||||
local alignments = universe.evolutionTableAlignment[tier]
|
||||
|
||||
local roll = map.random()
|
||||
local roll = universe.random()
|
||||
for i=1,#alignments do
|
||||
local alignment = alignments[i]
|
||||
|
||||
@ -274,15 +241,15 @@ local function findEntityUpgrade(baseAlignment, currentEvo, evoIndex, originalEn
|
||||
end
|
||||
end
|
||||
|
||||
local function findBaseInitialAlignment(map, evoIndex)
|
||||
local function findBaseInitialAlignment(universe, evoIndex)
|
||||
local dev = evoIndex * 0.15
|
||||
local evoTop = gaussianRandomRangeRG(evoIndex - (evoIndex * 0.075), dev, 0, evoIndex, map.random)
|
||||
local evoTop = gaussianRandomRangeRG(evoIndex - (evoIndex * 0.075), dev, 0, evoIndex, universe.random)
|
||||
|
||||
local result
|
||||
if map.random() < 0.05 then
|
||||
result = {findBaseMutation(map, evoTop), findBaseMutation(map, evoTop)}
|
||||
if universe.random() < 0.05 then
|
||||
result = {findBaseMutation(universe, evoTop), findBaseMutation(universe, evoTop)}
|
||||
else
|
||||
result = {findBaseMutation(map, evoTop)}
|
||||
result = {findBaseMutation(universe, evoTop)}
|
||||
end
|
||||
|
||||
return result
|
||||
@ -303,6 +270,7 @@ function baseUtils.recycleBases(map)
|
||||
map.recycleBaseIterator = next(bases, id)
|
||||
if base.chunkCount == 0 then
|
||||
bases[id] = nil
|
||||
map.universe.bases[id] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -353,14 +321,14 @@ function baseUtils.upgradeEntity(entity, base, map, disPos, evolve, register)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function pickMutationFromDamageType(map, damageType, roll, base)
|
||||
local function pickMutationFromDamageType(universe, damageType, roll, base)
|
||||
local baseAlignment = base.alignment
|
||||
|
||||
local damageFactions = FACTIONS_BY_DAMAGE_TYPE[damageType]
|
||||
local mutation
|
||||
|
||||
if (damageFactions and (#damageFactions > 0)) then
|
||||
mutation = damageFactions[map.random(#damageFactions)]
|
||||
mutation = damageFactions[universe.random(#damageFactions)]
|
||||
if baseAlignment[2] then
|
||||
if (roll < 0.05) then
|
||||
baseAlignment[2] = nil
|
||||
@ -378,7 +346,7 @@ local function pickMutationFromDamageType(map, damageType, roll, base)
|
||||
end
|
||||
end
|
||||
else
|
||||
mutation = findBaseMutation(map)
|
||||
mutation = findBaseMutation(universe)
|
||||
if baseAlignment[2] then
|
||||
if (roll < 0.05) then
|
||||
baseAlignment[2] = nil
|
||||
@ -396,7 +364,7 @@ local function pickMutationFromDamageType(map, damageType, roll, base)
|
||||
end
|
||||
end
|
||||
end
|
||||
if (map.universe.printBaseAdaptation) then
|
||||
if (universe.printBaseAdaptation) then
|
||||
if baseAlignment[2] then
|
||||
game.print({"description.rampant--adaptation2DebugMessage",
|
||||
damageType,
|
||||
@ -405,7 +373,7 @@ local function pickMutationFromDamageType(map, damageType, roll, base)
|
||||
base.x,
|
||||
base.y,
|
||||
base.mutations,
|
||||
map.universe.MAX_BASE_MUTATIONS})
|
||||
universe.MAX_BASE_MUTATIONS})
|
||||
else
|
||||
game.print({"description.rampant--adaptation1DebugMessage",
|
||||
damageType,
|
||||
@ -413,12 +381,12 @@ local function pickMutationFromDamageType(map, damageType, roll, base)
|
||||
base.x,
|
||||
base.y,
|
||||
base.mutations,
|
||||
map.universe.MAX_BASE_MUTATIONS})
|
||||
universe.MAX_BASE_MUTATIONS})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function upgradeBaseBasedOnDamage(map, base)
|
||||
function baseUtils.upgradeBaseBasedOnDamage(universe, base)
|
||||
|
||||
local total = 0
|
||||
|
||||
@ -429,7 +397,7 @@ local function upgradeBaseBasedOnDamage(map, base)
|
||||
base.damagedBy["RandomMutation"] = mutationAmount
|
||||
total = total + mutationAmount
|
||||
local pickedDamage
|
||||
local roll = map.random()
|
||||
local roll = universe.random()
|
||||
for damageTypeName,amount in pairs(base.damagedBy) do
|
||||
base.damagedBy[damageTypeName] = amount / total
|
||||
end
|
||||
@ -441,37 +409,30 @@ local function upgradeBaseBasedOnDamage(map, base)
|
||||
end
|
||||
end
|
||||
|
||||
pickMutationFromDamageType(map, pickedDamage, roll, base)
|
||||
pickMutationFromDamageType(universe, pickedDamage, roll, base)
|
||||
end
|
||||
|
||||
function baseUtils.processBase(chunk, map, tick, base)
|
||||
if ((tick - base.generationTick) <= BASE_PROCESS_INTERVAL) then
|
||||
return
|
||||
end
|
||||
|
||||
if not base.alignment[1] then
|
||||
return
|
||||
end
|
||||
|
||||
local surface = map.surface
|
||||
local universe = map.universe
|
||||
setPositionXYInQuery(universe.pbFilteredEntitiesPointQueryLimited,
|
||||
chunk.x + (CHUNK_SIZE * map.random()),
|
||||
chunk.y + (CHUNK_SIZE * map.random()))
|
||||
|
||||
local upgradeRoll = map.random()
|
||||
if (base.generationState == BASE_GENERATION_STATE_ACTIVE) and
|
||||
(base.points >= MINIMUM_BUILDING_COST) and
|
||||
(upgradeRoll < 0.30)
|
||||
function baseUtils.processBaseMutation(chunk, map, base)
|
||||
if not base.alignment[1] or
|
||||
(base.stateGeneration ~= BASE_GENERATION_STATE_ACTIVE) or
|
||||
(map.random() >= 0.30)
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
if (base.points >= MINIMUM_BUILDING_COST) then
|
||||
local surface = map.surface
|
||||
local universe = map.universe
|
||||
setPositionXYInQuery(universe.pbFilteredEntitiesPointQueryLimited,
|
||||
chunk.x + (CHUNK_SIZE * map.random()),
|
||||
chunk.y + (CHUNK_SIZE * map.random()))
|
||||
|
||||
local entities = surface.find_entities_filtered(universe.pbFilteredEntitiesPointQueryLimited)
|
||||
if #entities ~= 0 then
|
||||
local entity = entities[1]
|
||||
local cost = (universe.costLookup[entity.name] or MAGIC_MAXIMUM_NUMBER)
|
||||
if (base.points >= cost) then
|
||||
local newEntity = baseUtils.upgradeEntity(entity,
|
||||
base,
|
||||
map)
|
||||
local newEntity = baseUtils.upgradeEntity(entity, base, map)
|
||||
if newEntity then
|
||||
if universe.printBaseUpgrades then
|
||||
surface.print("[gps=".. entity.position.x ..",".. entity.position.y .."] " .. "Scheduled upgrade for ".. entity.name .. " to " .. newEntity)
|
||||
@ -481,73 +442,6 @@ function baseUtils.processBase(chunk, map, tick, base)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local deathThreshold
|
||||
local evolutionLevel = map.universe.evolutionLevel
|
||||
if (evolutionLevel < 0.5) then
|
||||
deathThreshold = 4500
|
||||
elseif (evolutionLevel < 0.7) then
|
||||
deathThreshold = 7500
|
||||
elseif (evolutionLevel < 0.9) then
|
||||
deathThreshold = 11000
|
||||
else
|
||||
deathThreshold = 16000
|
||||
end
|
||||
|
||||
deathThreshold = universe.adaptationModifier * deathThreshold
|
||||
|
||||
if ((base.deathEvents > deathThreshold) and (upgradeRoll > 0.95)) then
|
||||
if (base.mutations < universe.MAX_BASE_MUTATIONS) then
|
||||
base.mutations = base.mutations + 1
|
||||
upgradeBaseBasedOnDamage(map, base)
|
||||
elseif (base.mutations == universe.MAX_BASE_MUTATIONS) then
|
||||
local roll = map.random()
|
||||
if (roll < 0.001) then
|
||||
base.mutations = 0
|
||||
if (map.universe.printBaseAdaptation) then
|
||||
game.print({"description.rampant--adaptationResetDebugMessage",
|
||||
base.x,
|
||||
base.y,
|
||||
base.mutations,
|
||||
map.universe.MAX_BASE_MUTATIONS})
|
||||
end
|
||||
elseif (roll > 0.999) then
|
||||
base.mutations = base.mutations + 1
|
||||
if (map.universe.printBaseAdaptation) then
|
||||
game.print({"description.rampant--adaptationFrozenDebugMessage",
|
||||
base.x,
|
||||
base.y})
|
||||
end
|
||||
end
|
||||
end
|
||||
base.damagedBy = {}
|
||||
base.deathEvents = 0
|
||||
end
|
||||
|
||||
base.points = base.points + map.baseIncrement
|
||||
base.unitPoints = base.unitPoints + map.baseIncrement
|
||||
|
||||
if (base.points > universe.maxPoints) then
|
||||
base.points = universe.maxPoints
|
||||
end
|
||||
if (base.unitPoints > universe.maxPoints) then
|
||||
base.unitPoints = universe.unitPoints
|
||||
end
|
||||
|
||||
if (base.stateGenerationTick <= tick) then
|
||||
local roll = map.random()
|
||||
if (roll < 0.85) then
|
||||
base.generationState = BASE_GENERATION_STATE_ACTIVE
|
||||
else
|
||||
base.generationState = BASE_GENERATION_STATE_DORMANT
|
||||
end
|
||||
base.stateGenerationTick = randomTickEvent(map.random,
|
||||
tick,
|
||||
BASE_GENERATION_MIN_STATE_DURATION,
|
||||
BASE_GENERATION_MAX_STATE_DURATION)
|
||||
end
|
||||
|
||||
base.generationTick = tick
|
||||
end
|
||||
|
||||
function baseUtils.createBase(map, chunk, tick)
|
||||
@ -557,40 +451,46 @@ function baseUtils.createBase(map, chunk, tick)
|
||||
|
||||
local meanLevel = mFloor(distance * 0.005)
|
||||
|
||||
local universe = map.universe
|
||||
local distanceIndex = mMin(1, distance * BASE_DISTANCE_TO_EVO_INDEX)
|
||||
local evoIndex = mMax(distanceIndex, map.universe.evolutionLevel)
|
||||
local evoIndex = mMax(distanceIndex, universe.evolutionLevel)
|
||||
|
||||
local baseTick = tick
|
||||
local alignment = (universe.NEW_ENEMIES and findBaseInitialAlignment(universe, evoIndex)) or {"neutral"}
|
||||
|
||||
local alignment = findBaseInitialAlignment(map, evoIndex) or {"neutral"}
|
||||
|
||||
local baseLevel = gaussianRandomRangeRG(meanLevel, meanLevel * 0.3, meanLevel * 0.50, meanLevel * 1.50, map.random)
|
||||
local baseLevel = gaussianRandomRangeRG(meanLevel,
|
||||
meanLevel * 0.3,
|
||||
meanLevel * 0.50,
|
||||
meanLevel * 1.50,
|
||||
universe.random)
|
||||
local baseDistanceThreshold = gaussianRandomRangeRG(BASE_DISTANCE_THRESHOLD,
|
||||
BASE_DISTANCE_THRESHOLD * 0.2,
|
||||
BASE_DISTANCE_THRESHOLD * 0.75,
|
||||
BASE_DISTANCE_THRESHOLD * 1.50,
|
||||
map.random)
|
||||
universe.random)
|
||||
local distanceThreshold = (baseLevel * BASE_DISTANCE_LEVEL_BONUS) + baseDistanceThreshold
|
||||
local universe = map.universe
|
||||
|
||||
local base = {
|
||||
x = x,
|
||||
y = y,
|
||||
distanceThreshold = distanceThreshold * map.universe.baseDistanceModifier,
|
||||
tick = baseTick,
|
||||
distanceThreshold = distanceThreshold * universe.baseDistanceModifier,
|
||||
tick = tick,
|
||||
alignment = alignment,
|
||||
state = BASE_GENERATION_STATE_ACTIVE,
|
||||
damagedBy = {},
|
||||
deathEvents = 0,
|
||||
mutations = 0,
|
||||
stateGeneration = BASE_GENERATION_STATE_ACTIVE,
|
||||
stateGenerationTick = 0,
|
||||
chunkCount = 0,
|
||||
createdTick = tick,
|
||||
points = 0,
|
||||
unitPoints = 0,
|
||||
stateAI = BASE_AI_STATE_PEACEFUL,
|
||||
stateAITick = 0,
|
||||
canAttackTick = 0,
|
||||
drainPylons = {},
|
||||
maxAggressiveGroups = 0,
|
||||
sentAggressiveGroups = 0,
|
||||
maxSiegeGroups = 0,
|
||||
sentSiegeGroups = 0,
|
||||
activeRaidNests = 0,
|
||||
activeNests = 0,
|
||||
destroyPlayerBuildings = 0,
|
||||
@ -602,7 +502,8 @@ function baseUtils.createBase(map, chunk, tick)
|
||||
artilleryBlasts = 0,
|
||||
temperament = 0.5,
|
||||
temperamentScore = 0,
|
||||
stateAITick = 0,
|
||||
universe = universe,
|
||||
surface = map.surface,
|
||||
id = universe.baseId
|
||||
}
|
||||
universe.baseId = universe.baseId + 1
|
||||
@ -766,18 +667,16 @@ function baseUtils.rebuildNativeTables(universe, rg)
|
||||
|
||||
local evoIndex = evoToTier(universe, universe.evolutionLevel, 2)
|
||||
|
||||
if universe.maps then
|
||||
for _,map in pairs(universe.maps) do
|
||||
for _,base in pairs(map.bases) do
|
||||
for x=1,2 do
|
||||
local alignment = base.alignment[x]
|
||||
if alignment and not universe.buildingEvolveLookup[alignment] then
|
||||
base.alignment = findBaseInitialAlignment(map, evoIndex)
|
||||
break
|
||||
elseif not alignment and (x == 1) then
|
||||
base.alignment = findBaseInitialAlignment(map, evoIndex)
|
||||
break
|
||||
end
|
||||
if universe.bases then
|
||||
for _,base in pairs(universe.bases) do
|
||||
for x=1,2 do
|
||||
local alignment = base.alignment[x]
|
||||
if alignment and not universe.buildingEvolveLookup[alignment] then
|
||||
base.alignment = findBaseInitialAlignment(universe, evoIndex)
|
||||
break
|
||||
elseif not alignment and (x == 1) then
|
||||
base.alignment = findBaseInitialAlignment(universe, evoIndex)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -159,7 +159,7 @@ function chunkProcessor.processPendingChunks(universe, tick, flush)
|
||||
universe.chunkProcessorIterator = eventId
|
||||
end
|
||||
|
||||
function chunkProcessor.processPendingUpgrades(universe, tick)
|
||||
function chunkProcessor.processPendingUpgrades(universe)
|
||||
local entityId = universe.pendingUpgradeIterator
|
||||
local entityData
|
||||
if not entityId then
|
||||
@ -191,7 +191,7 @@ function chunkProcessor.processPendingUpgrades(universe, tick)
|
||||
setPositionInQuery(query, foundPosition or position)
|
||||
local createdEntity = surface.create_entity(query)
|
||||
if createdEntity and createdEntity.valid then
|
||||
registerEnemyBaseStructure(entityData.map, createdEntity, tick, entityData.base, true)
|
||||
registerEnemyBaseStructure(entityData.map, createdEntity, entityData.base, true)
|
||||
if remote.interfaces["kr-creep"] then
|
||||
remote.call("kr-creep", "spawn_creep_at_position", surface, foundPosition or position)
|
||||
end
|
||||
|
@ -20,6 +20,7 @@ end
|
||||
local chunkPropertyUtils = {}
|
||||
|
||||
local constants = require("Constants")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
@ -33,8 +34,12 @@ local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||
local MOVEMENT_GENERATOR_PERSISTANCE = constants.MOVEMENT_GENERATOR_PERSISTANCE
|
||||
local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
|
||||
|
||||
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
||||
|
||||
-- imported functions
|
||||
|
||||
local manhattenDistancePoints = mathUtils.manhattenDistancePoints
|
||||
|
||||
local mMin = math.min
|
||||
|
||||
-- module code
|
||||
@ -369,11 +374,11 @@ function chunkPropertyUtils.getRaidNestActiveness(map, chunk)
|
||||
return activeness.v or 0
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value)
|
||||
function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value, base)
|
||||
local universe = map.universe
|
||||
if (value <= 0) then
|
||||
if universe.chunkToActiveRaidNest[chunk.id] then
|
||||
map.activeRaidNests = map.activeRaidNests - 1
|
||||
base.activeRaidNests = base.activeRaidNests - 1
|
||||
end
|
||||
if (universe.processActiveRaidSpawnerIterator == chunk.id) then
|
||||
universe.processActiveRaidSpawnerIterator = nil
|
||||
@ -381,7 +386,7 @@ function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value)
|
||||
universe.chunkToActiveRaidNest[chunk.id] = nil
|
||||
else
|
||||
if not universe.chunkToActiveRaidNest[chunk.id] then
|
||||
map.activeRaidNests = map.activeRaidNests + 1
|
||||
base.activeRaidNests = base.activeRaidNests + 1
|
||||
universe.chunkToActiveRaidNest[chunk.id] = {
|
||||
map = map,
|
||||
v = 0
|
||||
@ -399,11 +404,11 @@ function chunkPropertyUtils.getNestActiveness(map, chunk)
|
||||
return activeness.v or 0
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setNestActiveness(map, chunk, value)
|
||||
function chunkPropertyUtils.setNestActiveness(map, chunk, value, base)
|
||||
local universe = map.universe
|
||||
if (value <= 0) then
|
||||
if universe.chunkToActiveNest[chunk.id] then
|
||||
map.activeNests = map.activeNests - 1
|
||||
base.activeNests = base.activeNests - 1
|
||||
end
|
||||
if (universe.processActiveSpawnerIterator == chunk.id) then
|
||||
universe.processActiveSpawnerIterator = nil
|
||||
@ -411,7 +416,7 @@ function chunkPropertyUtils.setNestActiveness(map, chunk, value)
|
||||
universe.chunkToActiveNest[chunk.id] = nil
|
||||
else
|
||||
if not universe.chunkToActiveNest[chunk.id] then
|
||||
map.activeNests = map.activeNests + 1
|
||||
base.activeNests = base.activeNests + 1
|
||||
universe.chunkToActiveNest[chunk.id] = {
|
||||
map = map,
|
||||
v = 0
|
||||
@ -568,18 +573,40 @@ function chunkPropertyUtils.addPlayerBaseGenerator(map, chunk, playerGenerator)
|
||||
map.chunkToPlayerBase[chunk.id] = (map.chunkToPlayerBase[chunk.id] or 0) + playerGenerator
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.findNearbyBase(map, chunk)
|
||||
local x = chunk.x
|
||||
local y = chunk.y
|
||||
|
||||
local foundBase = chunkPropertyUtils.getChunkBase(map, chunk)
|
||||
if foundBase then
|
||||
return foundBase
|
||||
end
|
||||
|
||||
local closest = MAGIC_MAXIMUM_NUMBER
|
||||
for _, base in pairs(map.bases) do
|
||||
local distance = manhattenDistancePoints(base.x, base.y, x, y)
|
||||
if (distance <= base.distanceThreshold) and (distance < closest) then
|
||||
closest = distance
|
||||
foundBase = base
|
||||
end
|
||||
end
|
||||
|
||||
return foundBase
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.processNestActiveness(map, chunk)
|
||||
local nests = chunkPropertyUtils.getNestCount(map, chunk)
|
||||
local base = chunkPropertyUtils.findNearbyBase(map, chunk)
|
||||
if (nests > 0) then
|
||||
local surface = map.surface
|
||||
local activeness = chunkPropertyUtils.getNestActiveness(map, chunk)
|
||||
local universe = map.universe
|
||||
local raidActiveness = chunkPropertyUtils.getRaidNestActiveness(map, chunk)
|
||||
if universe.attackUsePlayer and (chunk[PLAYER_PHEROMONE] > universe.attackPlayerThreshold) then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20), base)
|
||||
elseif (chunk[BASE_PHEROMONE] > 0) then
|
||||
if (surface.get_pollution(chunk) > 0) then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20), base)
|
||||
else
|
||||
local x = chunk.x
|
||||
local y = chunk.y
|
||||
@ -587,26 +614,26 @@ function chunkPropertyUtils.processNestActiveness(map, chunk)
|
||||
position.x = x + 32
|
||||
position.y = y
|
||||
if (surface.get_pollution(position) > 0) then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20), base)
|
||||
else
|
||||
position.x = x - 32
|
||||
if (surface.get_pollution(position) > 0) then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20), base)
|
||||
else
|
||||
position.x = x
|
||||
position.y = y - 32
|
||||
if (surface.get_pollution(position) > 0) then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20), base)
|
||||
else
|
||||
position.y = y + 32
|
||||
if (surface.get_pollution(position) > 0) then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20), base)
|
||||
else
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, activeness - 2)
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, activeness - 2, base)
|
||||
if (chunk[BASE_PHEROMONE] > RAIDING_MINIMUM_BASE_THRESHOLD) then
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, mMin(raidActiveness + 3, 20))
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, mMin(raidActiveness + 3, 20), base)
|
||||
else
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, raidActiveness - 1)
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, raidActiveness - 1, base)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -614,12 +641,12 @@ function chunkPropertyUtils.processNestActiveness(map, chunk)
|
||||
end
|
||||
end
|
||||
else
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, activeness - 5)
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, raidActiveness - 5)
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, activeness - 5, base)
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, raidActiveness - 5, base)
|
||||
end
|
||||
else
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, 0)
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, 0)
|
||||
elseif base then
|
||||
chunkPropertyUtils.setNestActiveness(map, chunk, 0, base)
|
||||
chunkPropertyUtils.setRaidNestActiveness(map, chunk, 0, base)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -94,7 +94,7 @@ local processNestActiveness = chunkPropertyUtils.processNestActiveness
|
||||
local removeChunkBase = chunkPropertyUtils.removeChunkBase
|
||||
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
|
||||
|
||||
local findNearbyBase = baseUtils.findNearbyBase
|
||||
local findNearbyBase = chunkPropertyUtils.findNearbyBase
|
||||
local createBase = baseUtils.createBase
|
||||
|
||||
local upgradeEntity = baseUtils.upgradeEntity
|
||||
@ -261,7 +261,7 @@ function chunkUtils.initialScan(chunk, map, tick)
|
||||
|
||||
for i = 1, #enemyBuildings do
|
||||
local enemyBuilding = enemyBuildings[i]
|
||||
chunkUtils.registerEnemyBaseStructure(map, enemyBuilding, tick, base)
|
||||
chunkUtils.registerEnemyBaseStructure(map, enemyBuilding, base)
|
||||
local entityName = enemyBuilding.name
|
||||
local isVanilla = vanillaEntityTypeLookup[entityName]
|
||||
if isVanilla or (not isVanilla and not buildingHiveTypeLookup[entityName]) then
|
||||
@ -271,7 +271,7 @@ function chunkUtils.initialScan(chunk, map, tick)
|
||||
else
|
||||
for i=1,#enemyBuildings do
|
||||
local building = enemyBuildings[i]
|
||||
chunkUtils.registerEnemyBaseStructure(map, building, tick, base)
|
||||
chunkUtils.registerEnemyBaseStructure(map, building, base)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -347,14 +347,16 @@ function chunkUtils.mapScanEnemyChunk(chunk, map, tick)
|
||||
for i=1,#HIVE_BUILDINGS_TYPES do
|
||||
counts[HIVE_BUILDINGS_TYPES[i]] = 0
|
||||
end
|
||||
local base = findNearbyBase(map, chunk)
|
||||
if not base then
|
||||
base = createBase(map, chunk, tick)
|
||||
end
|
||||
for i=1,#buildings do
|
||||
local building = buildings[i]
|
||||
if (#buildings > 0) then
|
||||
local base = findNearbyBase(map, chunk)
|
||||
if not base then
|
||||
base = createBase(map, chunk, tick)
|
||||
end
|
||||
for i=1,#buildings do
|
||||
local building = buildings[i]
|
||||
|
||||
chunkUtils.registerEnemyBaseStructure(map, building, tick, base)
|
||||
chunkUtils.registerEnemyBaseStructure(map, building, base)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -477,7 +479,7 @@ function chunkUtils.colorXY(x, y, surface, color)
|
||||
})
|
||||
end
|
||||
|
||||
function chunkUtils.registerEnemyBaseStructure(map, entity, tick, incomingBase, skipCount)
|
||||
function chunkUtils.registerEnemyBaseStructure(map, entity, base, skipCount)
|
||||
local entityType = entity.type
|
||||
|
||||
local addFunc
|
||||
@ -510,13 +512,6 @@ function chunkUtils.registerEnemyBaseStructure(map, entity, tick, incomingBase,
|
||||
if (chunk ~= -1) then
|
||||
if addFunc(map, chunk, entityUnitNumber) then
|
||||
added = true
|
||||
local base = incomingBase
|
||||
if not base then
|
||||
base = findNearbyBase(map, chunk)
|
||||
if not base then
|
||||
base = createBase(map, chunk, tick)
|
||||
end
|
||||
end
|
||||
setChunkBase(map, chunk, base)
|
||||
end
|
||||
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
|
||||
@ -525,7 +520,7 @@ function chunkUtils.registerEnemyBaseStructure(map, entity, tick, incomingBase,
|
||||
end
|
||||
end
|
||||
if added and (not skipCount) then
|
||||
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
|
||||
base.builtEnemyBuilding = base.builtEnemyBuilding + 1
|
||||
end
|
||||
end
|
||||
|
||||
@ -554,24 +549,27 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageTypeName, sk
|
||||
end
|
||||
end
|
||||
|
||||
local removed = false
|
||||
local entityUnitNumber = entity.unit_number
|
||||
local usedBases = {}
|
||||
local chunks = getEntityOverlapChunks(map, entity)
|
||||
for i=1,#chunks do
|
||||
local chunk = chunks[i]
|
||||
if (chunk ~= -1) then
|
||||
local base = getChunkBase(map, chunk)
|
||||
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
|
||||
setRaidNestActiveness(map, chunk, 0)
|
||||
setNestActiveness(map, chunk, 0)
|
||||
setRaidNestActiveness(map, chunk, 0, base)
|
||||
setNestActiveness(map, chunk, 0, base)
|
||||
end
|
||||
if removeFunc(map, chunk, entityUnitNumber) then
|
||||
removed = true
|
||||
local base = getChunkBase(map, chunk)
|
||||
if damageTypeName and not usedBases[base.id] then
|
||||
if not usedBases[base.id] then
|
||||
usedBases[base.id] = true
|
||||
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 3
|
||||
base.deathEvents = base.deathEvents + 3
|
||||
if damageTypeName then
|
||||
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 3
|
||||
base.deathEvents = base.deathEvents + 3
|
||||
end
|
||||
if (not skipCount) and (hiveType ~= "trap") then
|
||||
base.lostEnemyBuilding = base.lostEnemyBuilding + 1
|
||||
end
|
||||
end
|
||||
if (getEnemyStructureCount(map, chunk) <= 0) then
|
||||
removeChunkBase(map, chunk, base)
|
||||
@ -579,9 +577,6 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageTypeName, sk
|
||||
end
|
||||
end
|
||||
end
|
||||
if removed and (not skipCount) and (hiveType ~= "trap") then
|
||||
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
|
||||
end
|
||||
end
|
||||
|
||||
function chunkUtils.accountPlayerEntity(entity, map, addObject, base)
|
||||
@ -592,15 +587,15 @@ function chunkUtils.accountPlayerEntity(entity, map, addObject, base)
|
||||
if not addObject then
|
||||
if base then
|
||||
base.destroyPlayerBuildings = base.destroyPlayerBuildings + 1
|
||||
if (base.state == BASE_AI_STATE_ONSLAUGHT) then
|
||||
base.points = base.points + entityValue
|
||||
if (base.stateAI == BASE_AI_STATE_ONSLAUGHT) then
|
||||
base.unitPoints = base.unitPoints + entityValue
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue) .. ". [Structure Kill] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue) .. ". [Structure Kill] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
else
|
||||
base.points = base.points + (entityValue * 0.12)
|
||||
base.unitPoints = base.unitPoints + (entityValue * 0.12)
|
||||
if universe.aiPointsPrintGainsToChat then
|
||||
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue * 0.12) .. ". [Structure Kill] Total: " .. string.format("%.2f", base.points))
|
||||
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue * 0.12) .. ". [Structure Kill] Total: " .. string.format("%.2f", base.unitPoints))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -118,7 +118,7 @@ constants.DIVISOR_DEATH_TRAIL_TABLE = { 0.75, 0.65, 0.55, 0.45, 0.35 }
|
||||
constants.RESOURCE_MINIMUM_FORMATION_DELTA = 15
|
||||
|
||||
constants.MINIMUM_AI_POINTS = 400
|
||||
constants.AI_POINT_GENERATOR_AMOUNT = 0.17721
|
||||
constants.AI_POINT_GENERATOR_AMOUNT = 15
|
||||
constants.AI_SQUAD_COST = 175
|
||||
constants.RECOVER_NEST_COST = constants.AI_SQUAD_COST
|
||||
constants.RECOVER_WORM_COST = constants.AI_SQUAD_COST * 0.5
|
||||
@ -187,7 +187,7 @@ constants.BASE_UPGRADE = 1500
|
||||
constants.BASE_DISTANCE_THRESHOLD = 30 * constants.CHUNK_SIZE
|
||||
constants.BASE_DISTANCE_LEVEL_BONUS = 15
|
||||
|
||||
constants.BASE_PROCESS_INTERVAL = constants.TICKS_A_SECOND
|
||||
constants.BASE_PROCESS_INTERVAL = constants.TICKS_A_SECOND * 20
|
||||
|
||||
-- ai retreat
|
||||
|
||||
@ -1579,7 +1579,7 @@ constants.HIVE_BUILDINGS_COST["spitter-spawner"] = constants.BASE_SPAWNER_UPGRAD
|
||||
constants.HIVE_BUILDINGS_COST["biter-spawner"] = constants.BASE_SPAWNER_UPGRADE
|
||||
constants.HIVE_BUILDINGS_COST["hive"] = constants.BASE_SPAWNER_UPGRADE * 2
|
||||
|
||||
constants.UNIT_DEATH_POINT_COST = 1
|
||||
constants.UNIT_DEATH_POINT_COST = 0.5
|
||||
|
||||
constants.MINIMUM_BUILDING_COST = constants.MAGIC_MAXIMUM_NUMBER
|
||||
for _,cost in pairs(constants.HIVE_BUILDINGS_COST) do
|
||||
|
@ -60,7 +60,7 @@ local COOLDOWN_RETREAT = constants.COOLDOWN_RETREAT
|
||||
|
||||
-- imported functions
|
||||
|
||||
local findNearbyBase = baseUtils.findNearbyBase
|
||||
local findNearbyBase = chunkPropertyUtils.findNearbyBase
|
||||
|
||||
local removeChunkToNest = mapUtils.removeChunkToNest
|
||||
|
||||
@ -68,7 +68,7 @@ local processStaticPheromone = pheromoneUtils.processStaticPheromone
|
||||
local processPheromone = pheromoneUtils.processPheromone
|
||||
|
||||
local getDeathGeneratorRating = chunkPropertyUtils.getDeathGeneratorRating
|
||||
local processBase = baseUtils.processBase
|
||||
local processBaseMutation = baseUtils.processBaseMutation
|
||||
|
||||
local processNestActiveness = chunkPropertyUtils.processNestActiveness
|
||||
local getChunkBase = chunkPropertyUtils.getChunkBase
|
||||
@ -221,13 +221,16 @@ function mapProcessor.processPlayers(players, universe, tick)
|
||||
local char = player.character
|
||||
local map = universe.maps[char.surface.index]
|
||||
if map then
|
||||
local allowingAttacks = canAttack(map, base)
|
||||
local playerChunk = getChunkByPosition(map, char.position)
|
||||
|
||||
if (playerChunk ~= -1) then
|
||||
local base = findNearbyBase(map, playerChunk)
|
||||
if not base then
|
||||
return
|
||||
end
|
||||
local allowingAttacks = canAttack(map, base)
|
||||
local vengence = allowingAttacks and
|
||||
(base.points >= AI_VENGENCE_SQUAD_COST) and
|
||||
(base.unitPoints >= AI_VENGENCE_SQUAD_COST) and
|
||||
((getEnemyStructureCount(map, playerChunk) > 0) or
|
||||
(getDeathGeneratorRating(map, playerChunk) < universe.retreatThreshold))
|
||||
|
||||
@ -479,10 +482,11 @@ function mapProcessor.processNests(universe, tick)
|
||||
processNestActiveness(map, chunk)
|
||||
queueNestSpawners(map, chunk, tick)
|
||||
|
||||
processBase(chunk,
|
||||
map,
|
||||
tick,
|
||||
getChunkBase(map, chunk))
|
||||
if universe.NEW_ENEMIES then
|
||||
processBaseMutation(chunk,
|
||||
map,
|
||||
getChunkBase(map, chunk))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -507,25 +511,25 @@ local function processSpawnersBody(universe, iterator, chunks)
|
||||
end
|
||||
return
|
||||
end
|
||||
local state = chunkPack.map.state
|
||||
if base.state == BASE_AI_STATE_PEACEFUL then
|
||||
local chunk = getChunkById(map, chunkId)
|
||||
local base = findNearbyBase(map, chunk)
|
||||
if base.stateAI == BASE_AI_STATE_PEACEFUL then
|
||||
return
|
||||
end
|
||||
if iterator == "processMigrationIterator" then
|
||||
if (base.state ~= BASE_AI_STATE_MIGRATING) and (state ~= BASE_AI_STATE_SIEGE) then
|
||||
if (base.stateAI ~= BASE_AI_STATE_MIGRATING) and (base.stateAI ~= BASE_AI_STATE_SIEGE) then
|
||||
return
|
||||
end
|
||||
elseif iterator == "processActiveRaidSpawnerIterator" then
|
||||
if (base.state == BASE_AI_STATE_AGGRESSIVE) or (base.state == BASE_AI_STATE_MIGRATING) then
|
||||
if (base.stateAI == BASE_AI_STATE_AGGRESSIVE) or (base.stateAI == BASE_AI_STATE_MIGRATING) then
|
||||
return
|
||||
end
|
||||
elseif iterator == "processActiveSpawnerIterator" then
|
||||
if (base.state == BASE_AI_STATE_MIGRATING) then
|
||||
if (base.stateAI == BASE_AI_STATE_MIGRATING) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local chunk = getChunkById(map, chunkId)
|
||||
local migrate = canMigrate(map, base)
|
||||
local attack = canAttack(map, base)
|
||||
if migrate then
|
||||
|
@ -137,9 +137,7 @@ function mathUtils.euclideanDistancePoints(x1, y1, x2, y2)
|
||||
end
|
||||
|
||||
function mathUtils.manhattenDistancePoints(x1, y1, x2, y2)
|
||||
local xs = x1 - x2
|
||||
local ys = y1 - y2
|
||||
return mAbs(xs + ys)
|
||||
return mAbs((x1 - x2) + (y1 - y2))
|
||||
end
|
||||
|
||||
function mathUtils.euclideanDistanceArray(p1, p2)
|
||||
|
@ -129,7 +129,7 @@ local function settleMove(map, squad)
|
||||
local x, y = positionToChunkXY(groupPosition)
|
||||
local chunk = getChunkByXY(map, x, y)
|
||||
local scoreFunction = scoreResourceLocation
|
||||
if (base.state == BASE_AI_STATE_SIEGE) then
|
||||
if (squad.type == BASE_AI_STATE_SIEGE) then
|
||||
if squad.kamikaze then
|
||||
scoreFunction = scoreSiegeLocationKamikaze
|
||||
else
|
||||
@ -200,7 +200,7 @@ local function settleMove(map, squad)
|
||||
local attackPlayerThreshold = universe.attackPlayerThreshold
|
||||
|
||||
if (nextAttackChunk ~= -1) then
|
||||
if (getPlayerBaseGenerator(map,nextAttackChunk) == 0) or (base.state ~= BASE_AI_STATE_SIEGE) then
|
||||
if (getPlayerBaseGenerator(map,nextAttackChunk) == 0) or (squad.type ~= BASE_AI_STATE_SIEGE) then
|
||||
attackChunk = nextAttackChunk
|
||||
position = findMovementPosition(
|
||||
surface,
|
||||
@ -257,7 +257,7 @@ local function settleMove(map, squad)
|
||||
end
|
||||
|
||||
if (nextAttackChunk ~= -1) and
|
||||
(base.state == BASE_AI_STATE_SIEGE) and
|
||||
(squad.type == BASE_AI_STATE_SIEGE) and
|
||||
(getPlayerBaseGenerator(map, nextAttackChunk) ~= 0)
|
||||
then
|
||||
cmd = universe.settleCommand
|
||||
|
@ -41,7 +41,7 @@ local COOLDOWN_RETREAT = constants.COOLDOWN_RETREAT
|
||||
|
||||
-- imported functions
|
||||
|
||||
local findNearbyBase = baseUtils.findNearbyBase
|
||||
local findNearbyBase = chunkPropertyUtils.findNearbyBase
|
||||
|
||||
local addSquadToChunk = chunkPropertyUtils.addSquadToChunk
|
||||
|
||||
@ -122,7 +122,11 @@ function aiDefense.retreatUnits(chunk, cause, map, tick, radius)
|
||||
if not newSquad then
|
||||
if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) then
|
||||
created = true
|
||||
newSquad = createSquad(position, map)
|
||||
local base = findNearbyBase(map, chunk)
|
||||
if not base then
|
||||
return
|
||||
end
|
||||
newSquad = createSquad(position, map, nil, false, base)
|
||||
else
|
||||
return
|
||||
end
|
||||
@ -143,7 +147,6 @@ function aiDefense.retreatUnits(chunk, cause, map, tick, radius)
|
||||
end
|
||||
|
||||
if created then
|
||||
newSquad.base = findNearbyBase(map, chunk)
|
||||
universe.groupNumberToSquad[newSquad.groupNumber] = newSquad
|
||||
universe.squadCount = universe.squadCount + 1
|
||||
end
|
||||
|
@ -114,7 +114,7 @@ function unitGroupUtils.calculateSettlerMaxDistance(universe)
|
||||
universe.random)
|
||||
end
|
||||
|
||||
function unitGroupUtils.createSquad(position, map, group, settlers)
|
||||
function unitGroupUtils.createSquad(position, map, group, settlers, base)
|
||||
local unitGroup = group or map.surface.create_unit_group({position=position})
|
||||
|
||||
local squad = {
|
||||
@ -122,7 +122,8 @@ function unitGroupUtils.createSquad(position, map, group, settlers)
|
||||
status = SQUAD_GUARDING,
|
||||
rabid = false,
|
||||
penalties = {},
|
||||
base = nil,
|
||||
base = base,
|
||||
type = base.stateAI,
|
||||
frenzy = false,
|
||||
map = map,
|
||||
wanders = 0,
|
||||
|
Loading…
Reference in New Issue
Block a user