1
0
mirror of https://github.com/veden/Rampant.git synced 2025-02-05 13:14:51 +02:00

fixed regional bases processing, distribution, cleanup

This commit is contained in:
Aaron Veden 2021-12-04 11:04:13 -08:00
parent f489fe2de9
commit 9dfb61e735
No known key found for this signature in database
GPG Key ID: FF5990B1C6DD3F84
12 changed files with 455 additions and 384 deletions

View File

@ -29,7 +29,8 @@ globals = {
"stringUtilsG",
"unitGroupUtilsG",
"unitUtilsG",
"baseUtilsG"
"baseUtilsG",
"queryUtilsG"
}
max_line_length = false

View File

@ -4,7 +4,10 @@ local upgrade = {}
local constants = require("libs/Constants")
local mathUtils = require("libs/MathUtils")
local chunkPropertyUtils = require("libs/ChunkPropertyUtils")
local mapUtils = require("libs/MapUtils")
local baseUtils = require("libs/BaseUtils")
local chunkProcessor = require("libs/ChunkProcessor")
-- constants
@ -28,8 +31,18 @@ local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE
-- imported functions
local processPendingChunks = chunkProcessor.processPendingChunks
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
local getChunkBase = chunkPropertyUtils.getChunkBase
local removeChunkBase = chunkPropertyUtils.removeChunkBase
local findNearbyBase = baseUtils.findNearbyBase
local createBase = baseUtils.createBase
local setChunkBase = chunkPropertyUtils.setChunkBase
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
local mAbs = math.abs
@ -256,7 +269,7 @@ local function addCommandSet(queriesAndCommands)
queriesAndCommands.upgradeEntityQuery = {
name = "",
position = nil
position = {0,0}
}
queriesAndCommands.attackCommand = {
@ -443,39 +456,91 @@ function upgrade.attempt(universe)
map.pendingUpgrades = {}
map.sentAggressiveGroups = 0
map.maxAggressiveGroups = 1
for chunkXY in map.surface.get_chunks() do
local x = chunkXY.x * 32
local y = chunkXY.y * 32
if not map[x] then
map[x] = {}
end
if not map[x][y] then
queueGeneratedChunk(universe,
{
surface = map.surface,
area = {
left_top = {
x = x,
y = y
}
}
}
)
end
end
local basesToRemove = {}
for i=1,#map.processQueue do
local chunk = map.processQueue[i]
chunk.dOrigin = euclideanDistancePoints(chunk.x, chunk.y, 0, 0)
local base = getChunkBase(map, chunk)
if base then
if not map.bases[base.id] then
map.bases[base.id] = base
end
if not base.damagedBy then
base.damagedBy = {}
end
if not base.deathEvents then
base.deathEvents = 0
end
if not base.chunkCount then
base.chunkCount = 0
end
if not base.mutations then
base.mutations = 0
end
if not base.alignment[1] then
basesToRemove[base.id] = true
end
end
end
tSort(map.processQueue, sorter)
map.pendingChunks = {}
map.chunkToNests = {}
map.chunkToNestIds = {}
map.chunkToHives = {}
map.chunkToHiveIds = {}
map.chunkToTraps = {}
map.chunkToTrapIds = {}
map.chunkToTurrets = {}
map.chunkToTurretIds = {}
map.chunkToUtilities = {}
map.chunkToUtilityIds = {}
for chunkXY in map.surface.get_chunks() do
if map.surface.is_chunk_generated(chunkXY) then
local x = chunkXY.x * 32
local y = chunkXY.y * 32
queueGeneratedChunk(universe,
{
surface = map.surface,
area = {
left_top = {
x = x,
y = y
}
}
}
)
end
end
processPendingChunks(map, tick, true)
for i=1,#map.processQueue do
local chunk = map.processQueue[i]
local base = getChunkBase(map, chunk)
if (getEnemyStructureCount(map, chunk) > 0) then
base.chunkCount = (base.chunkCount or 0) + 1
end
if base and (not base.alignment[1]) then
removeChunkBase(map, chunk, base)
end
if (getEnemyStructureCount(map, chunk) > 0) and not base then
local newBase = findNearbyBase(map, chunk)
if not newBase then
createBase(map, chunk, tick)
else
setChunkBase(map, chunk, newBase)
end
end
if base and getEnemyStructureCount(map, chunk) == 0 then
removeChunkBase(map, chunk, base)
end
end
for baseId in pairs(basesToRemove) do
map.bases[baseId] = nil
end
for _,squad in pairs(map.groupNumberToSquad) do
squad.commandTick = tick
end
tSort(map.processQueue, sorter)
for _,base in pairs(map.bases) do
base.damagedBy = {}
base.deathEvents = 0
base.mutations = 0
end
end
end

View File

@ -39,9 +39,12 @@ Date: 23. 11. 2021
- Added command timeout for unit groups in case a command hangs or unit groups are stuck gathering (Thank you Dimm2101)
- Corrected spelling of wonder command to wander command
- Fixed enemy structures destroyed by the enemy were not being unregistered from Rampants map
- Fixed regional bases would not be corrected distributed or cleaned up on spawners
Framework:
- Fixed Rampant in-memory map visualization tool for debugging
- Added debug mod settings for showing enemy structures being upgraded in place
Removals:
- Removed map deadzones as they were breaking regional bases
---------------------------------------------------------------------------------------------------
Version: 1.1.4

View File

@ -44,6 +44,8 @@ local ENERGY_THIEF_LOOKUP = constants.ENERGY_THIEF_LOOKUP
-- imported functions
local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
local isRampantSetting = stringUtils.isRampantSetting
@ -99,6 +101,7 @@ local findNearbyBase = baseUtils.findNearbyBase
local processActiveNests = mapProcessor.processActiveNests
local getDeathGenerator = chunkPropertyUtils.getDeathGenerator
local setChunkBase = chunkPropertyUtils.setChunkBase
local retreatUnits = squadDefense.retreatUnits
@ -221,9 +224,6 @@ local function onModSettingsChange(event)
upgrade.compareTable(universe,
"adaptationModifier",
settings.global["rampant--adaptationModifier"].value)
upgrade.compareTable(universe,
"deadZoneFrequency",
settings.global["rampant--deadZoneFrequency"].value)
upgrade.compareTable(universe,
"raidAIToggle",
settings.global["rampant--raidAIToggle"].value)
@ -303,10 +303,17 @@ local function prepMap(surface)
map.chunkToTraps = {}
map.chunkToUtilities = {}
map.chunkToHives = {}
map.chunkToNestIds = {}
map.chunkToHiveIds = {}
map.chunkToTrapIds = {}
map.chunkToTurretIds = {}
map.chunkToUtilityIds = {}
map.chunkToPlayerBase = {}
map.chunkToResource = {}
map.chunkToPlayerCount = {}
map.playerToChunk = {}
map.pendingChunks = {}
map.chunkToPassScan = {}
map.chunkToSquad = {}
@ -335,8 +342,6 @@ local function prepMap(surface)
map.chunkScanCounts = {}
map.enemiesToSquad = {}
map.enemiesToSquad.len = 0
map.chunkRemovals = {}
map.processActiveNest = {}
map.tickActiveNest = {}
@ -385,6 +390,7 @@ local function prepMap(surface)
position[2] = y
if surface.is_chunk_generated(position) then
onChunkGenerated({ surface = surface,
tick = tick,
area = { left_top = { x = x * 32,
y = y * 32}}})
end
@ -542,19 +548,22 @@ local function onDeath(event)
end
else
if (event.force and (event.force.name ~= "enemy")) then
if event.force and (event.force.name ~= "enemy") then
local rally = false
if (entityType == "unit-spawner") then
map.points = map.points + RECOVER_NEST_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. RECOVER_NEST_COST .. ". [Nest Lost] Total: " .. string.format("%.2f", map.points))
end
else
rally = true
elseif (entityType == "turret") then
map.points = map.points + RECOVER_WORM_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. RECOVER_WORM_COST .. ". [Worm Lost] Total: " .. string.format("%.2f", map.points))
end
rally = true
end
if (chunk ~= -1) then
if (chunk ~= -1) and rally then
rallyUnits(chunk, map, tick)
if cause and cause.valid then
@ -567,7 +576,12 @@ local function onDeath(event)
end
end
unregisterEnemyBaseStructure(map, entity, event.damage_type)
if universe.buildingHiveTypeLookup[entity.name] or
(entityType == "unit-spawner") or
(entityType == "turret")
then
unregisterEnemyBaseStructure(map, entity, event.damage_type)
end
end
elseif (entity.force.name ~= "enemy") then
@ -659,6 +673,8 @@ local function onEnemyBaseBuild(event)
event.tick)
end
registerEnemyBaseStructure(map, entity, event.tick, base)
upgradeEntity(entity,
base.alignment,
map,
@ -829,6 +845,8 @@ local function onEntitySpawned(event)
event.tick)
end
registerEnemyBaseStructure(map, entity, event.tick, base)
upgradeEntity(entity,
base.alignment,
map,
@ -1053,7 +1071,7 @@ script.on_event(defines.events.on_tick,
universe.processedChunks = universe.processedChunks + PROCESS_QUEUE_SIZE
planning(map, gameRef.forces.enemy.evolution_factor, tick)
if universe.NEW_ENEMIES then
recycleBases(map, tick)
recycleBases(map)
end
cleanUpMapTables(map, tick)
elseif (pick == 1) then
@ -1158,7 +1176,9 @@ remote.add_interface("rampantTests",
exportAiState = tests.exportAiState(nil),
createEnergyTest = tests.createEnergyTest,
killActiveSquads = tests.killActiveSquads,
scanChunkPaths = tests.scanChunkPaths
scanChunkPaths = tests.scanChunkPaths,
scanEnemy = tests.scanEnemy,
getEnemyStructureCount = tests.getEnemyStructureCount
}
)

View File

@ -24,8 +24,6 @@ local BASE_AI_STATE_DORMANT = constants.BASE_AI_STATE_DORMANT
local FACTION_SET = constants.FACTION_SET
local BASE_DEADZONE_TTL = constants.BASE_DEADZONE_TTL
local BASE_AI_MIN_STATE_DURATION = constants.BASE_AI_MIN_STATE_DURATION
local BASE_AI_MAX_STATE_DURATION = constants.BASE_AI_MAX_STATE_DURATION
@ -35,8 +33,6 @@ local BASE_DISTANCE_THRESHOLD = constants.BASE_DISTANCE_THRESHOLD
local BASE_DISTANCE_LEVEL_BONUS = constants.BASE_DISTANCE_LEVEL_BONUS
local BASE_DISTANCE_TO_EVO_INDEX = constants.BASE_DISTANCE_TO_EVO_INDEX
local BASE_COLLECTION_THRESHOLD = constants.BASE_COLLECTION_THRESHOLD
local CHUNK_SIZE = constants.CHUNK_SIZE
-- imported functions
@ -57,7 +53,6 @@ local mMax = math.max
local distort = mathUtils.distort
local getChunkBase = chunkPropertyUtils.getChunkBase
local setChunkBase = chunkPropertyUtils.setChunkBase
local getResourceGenerator = chunkPropertyUtils.getResourceGenerator
@ -213,7 +208,7 @@ local function findEntityUpgrade(baseAlignment, currentEvo, evoIndex, originalEn
local maxTier = evoToTier(universe, evoIndex, 4)
if (tier > maxTier) then
return nil
maxTier = tier
end
if evolve then
@ -240,8 +235,7 @@ local function findBaseInitialAlignment(map, evoIndex)
return result
end
function baseUtils.recycleBases(map, tick)
function baseUtils.recycleBases(map)
local bases = map.bases
local id = map.recycleBaseIterator
local base
@ -254,7 +248,7 @@ function baseUtils.recycleBases(map, tick)
map.recycleBaseIterator = nil
else
map.recycleBaseIterator = next(bases, id)
if ((tick - base.tick) > BASE_COLLECTION_THRESHOLD) then
if base.chunkCount == 0 then
bases[id] = nil
end
end
@ -264,11 +258,6 @@ function baseUtils.upgradeEntity(entity, baseAlignment, map, disPos, evolve, reg
local position = entity.position
local currentEvo = entity.prototype.build_base_evolution_requirement or 0
if not baseAlignment[1] then
entity.destroy()
return nil
end
local distance = mMin(1, euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX)
local evoIndex = mMax(distance, map.evolutionLevel)
@ -289,7 +278,7 @@ function baseUtils.upgradeEntity(entity, baseAlignment, map, disPos, evolve, reg
map,
evolve)
if spawnerName and (spawnerName ~= entity.name) then
if (spawnerName ~= entity.name) then
local entityData = {
["name"] = spawnerName,
["position"] = disPos,
@ -298,7 +287,6 @@ function baseUtils.upgradeEntity(entity, baseAlignment, map, disPos, evolve, reg
map.pendingUpgrades[entity] = entityData
return spawnerName
end
return nil
end
@ -474,7 +462,7 @@ function baseUtils.processBase(chunk, map, tick, base)
base.tick = tick
end
function baseUtils.createBase(map, chunk, tick, rebuilding)
function baseUtils.createBase(map, chunk, tick)
local x = chunk.x
local y = chunk.y
local distance = euclideanDistancePoints(x, y, 0, 0)
@ -486,13 +474,7 @@ function baseUtils.createBase(map, chunk, tick, rebuilding)
local baseTick = tick
local alignment
if (not rebuilding) and (mRandom() < map.universe.deadZoneFrequency) then
alignment = {}
baseTick = BASE_DEADZONE_TTL
else
alignment = findBaseInitialAlignment(map, evoIndex) or {"neutral"}
end
local alignment = findBaseInitialAlignment(map, evoIndex) or {"neutral"}
local baseLevel = gaussianRandomRange(meanLevel, meanLevel * 0.3, meanLevel * 0.50, meanLevel * 1.50)
local baseDistanceThreshold = gaussianRandomRange(BASE_DISTANCE_THRESHOLD,
@ -512,14 +494,13 @@ function baseUtils.createBase(map, chunk, tick, rebuilding)
deathEvents = 0,
mutations = 0,
stateTick = 0,
chunkCount = 0,
createdTick = tick,
points = 0,
id = map.baseId
}
map.baseId = map.baseId + 1
setChunkBase(map, chunk, base)
map.bases[base.id] = base
return base

View File

@ -7,8 +7,6 @@ local chunkProcessor = {}
local chunkUtils = require("ChunkUtils")
local constants = require("Constants")
local baseUtils = require("BaseUtils")
local mapUtils = require("MapUtils")
-- constants
@ -16,11 +14,8 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
-- imported functions
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
local getChunkByPosition = mapUtils.getChunkByPosition
local findNearbyBase = baseUtils.findNearbyBase
local createBase = baseUtils.createBase
local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure
local unregisterEnemyBaseStructure = chunkUtils.unregisterEnemyBaseStructure
local createChunk = chunkUtils.createChunk
local initialScan = chunkUtils.initialScan
@ -51,12 +46,10 @@ local function findInsertionPoint(processQueue, chunk)
return low
end
local function removeProcessQueueChunk(map, chunk)
local processQueue = map.processQueue
local function removeProcessQueueChunk(processQueue, chunk)
local insertionPoint = findInsertionPoint(processQueue, chunk)
for i=insertionPoint,1,-1 do
if (processQueue[i] == chunk) then
constants.gpsDebug(chunk.x+16, chunk.y+16, "removeProcessQueueChunk")
tRemove(processQueue, i)
end
end
@ -109,11 +102,13 @@ function chunkProcessor.processPendingChunks(map, tick, flush)
if map[x][y] then
local chunk = initialScan(map[x][y], map, tick)
if (chunk == -1) then
map[x][y] = nil
removeProcessQueueChunk(processQueue, map[x][y])
map[x][y] = nil
end
else
local chunk = initialScan(createChunk(x, y), map, tick)
local chunk = createChunk(x, y)
map[x][y] = chunk
chunk = initialScan(chunk, map, tick)
if (chunk ~= -1) then
map[x][y] = chunk
tInsert(
@ -121,6 +116,8 @@ function chunkProcessor.processPendingChunks(map, tick, flush)
findInsertionPoint(processQueue, chunk),
chunk
)
else
map[x][y] = nil
end
end
@ -150,37 +147,14 @@ function chunkProcessor.processPendingUpgrades(map, tick)
query.position = entityData.position or entity.position
query.name = entityData.name
local surface = entity.surface
unregisterEnemyBaseStructure(map, entity)
entity.destroy()
if remote.interfaces["kr-creep"] then
remote.call("kr-creep", "spawn_creep_at_position", surface, query.position)
end
local createdEntity = surface.create_entity(query)
if createdEntity and createdEntity.valid and entityData.register then
local chunk = getChunkByPosition(map, createdEntity.position)
if (chunk ~= -1) then
local base = findNearbyBase(map, chunk)
if not base then
base = createBase(map,
chunk,
tick)
end
if base then
chunkUtils.registerEnemyBaseStructure(map, createdEntity, base)
end
else
queueGeneratedChunk(
universe,
{
surface = createdEntity.surface,
area = {
left_top = {
x = createdEntity.position.x,
y = createdEntity.position.y
}
}
}
)
end
if createdEntity and createdEntity.valid then
registerEnemyBaseStructure(map, createdEntity, tick)
end
else
map.pendingUpgradeIterator = next(pendingUpgrades, entity)

View File

@ -41,49 +41,114 @@ function chunkPropertyUtils.getHiveCount(map, chunk)
return map.chunkToHives[chunk] or 0
end
function chunkPropertyUtils.setTurretCount(map, chunk, count)
if (count <= 0) then
map.chunkToTurrets[chunk] = nil
else
map.chunkToTurrets[chunk] = count
function chunkPropertyUtils.addTurretCount(map, chunk, unitNumber)
if not map.chunkToTurretIds[chunk] then
map.chunkToTurretIds[chunk] = {}
end
if not map.chunkToTurretIds[chunk][unitNumber] then
map.chunkToTurretIds[chunk][unitNumber] = true
map.chunkToTurrets[chunk] = (map.chunkToTurrets[chunk] or 0) + 1
end
end
function chunkPropertyUtils.setHiveCount(map, chunk, count)
if (count <= 0) then
map.chunkToHives[chunk] = nil
else
map.chunkToHives[chunk] = count
end
end
function chunkPropertyUtils.setTrapCount(map, chunk, count)
if (count <= 0) then
map.chunkToTraps[chunk] = nil
else
map.chunkToTraps[chunk] = count
end
end
function chunkPropertyUtils.setUtilityCount(map, chunk, count)
if (count <= 0) then
map.chunkToUtilities[chunk] = nil
else
map.chunkToUtilities[chunk] = count
end
end
function chunkPropertyUtils.setNestCount(map, chunk, count)
if (count <= 0) then
map.chunkToNests[chunk] = nil
if (map.processMigrationIterator == chunk) then
map.processMigrationIterator = nil
function chunkPropertyUtils.removeTurretCount(map, chunk, unitNumber)
if map.chunkToTurretIds[chunk] and map.chunkToTurretIds[chunk][unitNumber] then
map.chunkToTurretIds[chunk][unitNumber] = nil
map.chunkToTurrets[chunk] = map.chunkToTurrets[chunk] - 1
if map.chunkToTurrets[chunk] == 0 then
map.chunkToTurretIds[chunk] = nil
map.chunkToTurrets[chunk] = nil
end
if (map.processNestIterator == chunk) then
map.processNestIterator = nil
end
end
function chunkPropertyUtils.addTrapCount(map, chunk, unitNumber)
if not map.chunkToTrapIds[chunk] then
map.chunkToTrapIds[chunk] = {}
end
if not map.chunkToTrapIds[chunk][unitNumber] then
map.chunkToTrapIds[chunk][unitNumber] = true
map.chunkToTraps[chunk] = (map.chunkToTraps[chunk] or 0) + 1
end
end
function chunkPropertyUtils.removeTrapCount(map, chunk, unitNumber)
if map.chunkToTrapIds[chunk] and map.chunkToTrapIds[chunk][unitNumber] then
map.chunkToTrapIds[chunk][unitNumber] = nil
map.chunkToTraps[chunk] = map.chunkToTraps[chunk] - 1
if map.chunkToTraps[chunk] == 0 then
map.chunkToTrapIds[chunk] = nil
map.chunkToTraps[chunk] = nil
end
end
end
function chunkPropertyUtils.addUtilitiesCount(map, chunk, unitNumber)
if not map.chunkToUtilityIds[chunk] then
map.chunkToUtilityIds[chunk] = {}
end
if not map.chunkToUtilityIds[chunk][unitNumber] then
map.chunkToUtilityIds[chunk][unitNumber] = true
map.chunkToUtilities[chunk] = (map.chunkToUtilities[chunk] or 0) + 1
end
end
function chunkPropertyUtils.removeUtilitiesCount(map, chunk, unitNumber)
if map.chunkToUtilityIds[chunk] and map.chunkToUtilityIds[chunk][unitNumber] then
map.chunkToUtilityIds[chunk][unitNumber] = nil
map.chunkToUtilities[chunk] = map.chunkToUtilities[chunk] - 1
if map.chunkToUtilities[chunk] == 0 then
map.chunkToUtilityIds[chunk] = nil
map.chunkToUtilities[chunk] = nil
end
end
end
function chunkPropertyUtils.addHiveCount(map, chunk, unitNumber)
if not map.chunkToHiveIds[chunk] then
map.chunkToHiveIds[chunk] = {}
end
if not map.chunkToHiveIds[chunk][unitNumber] then
map.chunkToHiveIds[chunk][unitNumber] = true
map.chunkToHives[chunk] = (map.chunkToHives[chunk] or 0) + 1
end
end
function chunkPropertyUtils.removeHiveCount(map, chunk, unitNumber)
if map.chunkToHiveIds[chunk] and map.chunkToHiveIds[chunk][unitNumber] then
map.chunkToHiveIds[chunk][unitNumber] = nil
map.chunkToHives[chunk] = map.chunkToHives[chunk] - 1
if map.chunkToHives[chunk] == 0 then
map.chunkToHiveIds[chunk] = nil
map.chunkToHives[chunk] = nil
end
end
end
function chunkPropertyUtils.addNestCount(map, chunk, unitNumber)
if not map.chunkToNestIds[chunk] then
map.chunkToNestIds[chunk] = {}
end
if not map.chunkToNestIds[chunk][unitNumber] then
map.chunkToNestIds[chunk][unitNumber] = true
map.chunkToNests[chunk] = (map.chunkToNests[chunk] or 0) + 1
end
end
function chunkPropertyUtils.removeNestCount(map, chunk, unitNumber)
if map.chunkToNestIds[chunk] and map.chunkToNestIds[chunk][unitNumber] then
map.chunkToNestIds[chunk][unitNumber] = nil
map.chunkToNests[chunk] = map.chunkToNests[chunk] - 1
if map.chunkToNests[chunk] == 0 then
map.chunkToNestIds[chunk] = nil
map.chunkToNests[chunk] = nil
if (map.processMigrationIterator == chunk) then
map.processMigrationIterator = nil
end
if (map.processNestIterator == chunk) then
map.processNestIterator = nil
end
end
else
map.chunkToNests[chunk] = count
end
end
@ -95,8 +160,18 @@ function chunkPropertyUtils.getChunkBase(map, chunk)
return map.chunkToBase[chunk]
end
function chunkPropertyUtils.removeChunkBase(map, chunk, base)
if map.chunkToBase[chunk] then
base.chunkCount = base.chunkCount + 1
map.chunkToBase[chunk] = nil
end
end
function chunkPropertyUtils.setChunkBase(map, chunk, base)
map.chunkToBase[chunk] = base
if not map.chunkToBase[chunk] then
base.chunkCount = base.chunkCount + 1
map.chunkToBase[chunk] = base
end
end
function chunkPropertyUtils.getEnemyStructureCount(map, chunk)

View File

@ -10,6 +10,7 @@ local constants = require("Constants")
local mapUtils = require("MapUtils")
local chunkPropertyUtils = require("ChunkPropertyUtils")
local mathUtils = require("MathUtils")
local queryUtils = require("QueryUtils")
-- constants
@ -47,26 +48,32 @@ local GENERATOR_PHEROMONE_LEVEL_6 = constants.GENERATOR_PHEROMONE_LEVEL_6
-- imported functions
local setNestCount = chunkPropertyUtils.setNestCount
local setAreaInQuery = queryUtils.setAreaInQuery
local setPlayerBaseGenerator = chunkPropertyUtils.setPlayerBaseGenerator
local addPlayerBaseGenerator = chunkPropertyUtils.addPlayerBaseGenerator
local setResourceGenerator = chunkPropertyUtils.setResourceGenerator
local addResourceGenerator = chunkPropertyUtils.addResourceGenerator
local setHiveCount = chunkPropertyUtils.setHiveCount
local setTrapCount = chunkPropertyUtils.setTrapCount
local setTurretCount = chunkPropertyUtils.setTurretCount
local setUtilityCount = chunkPropertyUtils.setUtilityCount
local addNestCount = chunkPropertyUtils.addNestCount
local removeNestCount = chunkPropertyUtils.removeNestCount
local addHiveCount = chunkPropertyUtils.addHiveCount
local removeHiveCount = chunkPropertyUtils.removeHiveCount
local addTrapCount = chunkPropertyUtils.addTrapCount
local removeTrapCount = chunkPropertyUtils.removeTrapCount
local addTurretCount = chunkPropertyUtils.addTurretCount
local removeTurretCount = chunkPropertyUtils.removeTurretCount
local addUtilityCount = chunkPropertyUtils.addUtilityCount
local removeUtilityCount = chunkPropertyUtils.removeUtilityCount
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
local getNestCount = chunkPropertyUtils.getNestCount
local getHiveCount = chunkPropertyUtils.getHiveCount
local getTrapCount = chunkPropertyUtils.getTrapCount
local getUtilityCount = chunkPropertyUtils.getUtilityCount
local getTurretCount = chunkPropertyUtils.getTurretCount
local setRaidNestActiveness = chunkPropertyUtils.setRaidNestActiveness
local setNestActiveness = chunkPropertyUtils.setNestActiveness
local processNestActiveness = chunkPropertyUtils.processNestActiveness
local removeChunkBase = chunkPropertyUtils.removeChunkBase
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
local findNearbyBase = baseUtils.findNearbyBase
@ -100,16 +107,12 @@ local function getEntityOverlapChunks(map, entity)
if boundingBox then
local center = entity.position
local topXOffset
local topYOffset
local bottomXOffset
local bottomYOffset
local topXOffset = boundingBox.left_top.x
local topYOffset = boundingBox.left_top.y
topXOffset = boundingBox.left_top.x
topYOffset = boundingBox.left_top.y
bottomXOffset = boundingBox.right_bottom.x
bottomYOffset = boundingBox.right_bottom.y
local bottomXOffset = boundingBox.right_bottom.x
local bottomYOffset = boundingBox.right_bottom.y
local leftTopChunkX = mFloor((center.x + topXOffset) * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
local leftTopChunkY = mFloor((center.y + topYOffset) * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
@ -229,9 +232,7 @@ function chunkUtils.initialScan(chunk, map, tick)
if (#enemyBuildings > 0) then
if universe.NEW_ENEMIES then
local base = findNearbyBase(map, chunk)
if base then
setChunkBase(map, chunk, base)
else
if not base then
base = createBase(map, chunk, tick)
end
local alignment = base.alignment
@ -246,37 +247,17 @@ function chunkUtils.initialScan(chunk, map, tick)
for i = 1, #enemyBuildings do
local enemyBuilding = enemyBuildings[i]
chunkUtils.registerEnemyBaseStructure(map, enemyBuilding, tick, base)
if not buildingHiveTypeLookup[enemyBuilding.name] then
local newEntity = upgradeEntity(enemyBuilding, alignment, map, nil, true)
if newEntity then
local hiveType = buildingHiveTypeLookup[newEntity]
counts[hiveType] = counts[hiveType] + 1
end
else
local hiveType = buildingHiveTypeLookup[enemyBuilding.name] or
(((enemyBuilding.type == "turret") and "turret") or "biter-spawner")
counts[hiveType] = counts[hiveType] + 1
upgradeEntity(enemyBuilding, alignment, map, nil, true)
end
end
setNestCount(map, chunk, counts["spitter-spawner"] + counts["biter-spawner"])
setUtilityCount(map, chunk, counts["utility"])
setHiveCount(map, chunk, counts["hive"])
setTrapCount(map, chunk, counts["trap"])
setTurretCount(map, chunk, counts["turret"])
else
for i=1,#enemyBuildings do
local building = enemyBuildings[i]
local hiveType = buildingHiveTypeLookup[building.name] or
(((building.type == "turret") and "turret") or "biter-spawner")
counts[hiveType] = counts[hiveType] + 1
chunkUtils.registerEnemyBaseStructure(map, building, tick)
end
setNestCount(map, chunk, counts["spitter-spawner"] + counts["biter-spawner"])
setUtilityCount(map, chunk, counts["utility"])
setHiveCount(map, chunk, counts["hive"])
setTrapCount(map, chunk, counts["trap"])
setTurretCount(map, chunk, counts["turret"])
end
end
@ -340,24 +321,18 @@ end
function chunkUtils.mapScanEnemyChunk(chunk, map)
local universe = map.universe
local buildingHiveTypeLookup = universe.buildingHiveTypeLookup
local buildings = map.surface.find_entities_filtered(universe.filteredEntitiesEnemyStructureQuery)
local query = universe.filteredEntitiesEnemyStructureQuery
setAreaInQuery(query, chunk, CHUNK_SIZE)
local buildings = map.surface.find_entities_filtered(query)
local counts = map.chunkScanCounts
for i=1,#HIVE_BUILDINGS_TYPES do
counts[HIVE_BUILDINGS_TYPES[i]] = 0
end
for i=1,#buildings do
local building = buildings[i]
local hiveType = buildingHiveTypeLookup[building.name] or
(((building.type == "turret") and "turret") or "biter-spawner")
counts[hiveType] = counts[hiveType] + 1
end
setNestCount(map, chunk, counts["spitter-spawner"] + counts["biter-spawner"])
setUtilityCount(map, chunk, counts["utility"])
setHiveCount(map, chunk, counts["hive"])
setTrapCount(map, chunk, counts["trap"])
setTurretCount(map, chunk, counts["turret"])
chunkUtils.registerEnemyBaseStructure(map, building, game.tick)
end
end
function chunkUtils.entityForPassScan(map, entity)
@ -385,7 +360,7 @@ function chunkUtils.createChunk(topX, topY)
return chunk
end
function chunkUtils.colorChunk(chunk, surface, color)
function chunkUtils.colorChunk(chunk, surface, color, ttl)
local lx = math.floor(chunk.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
local ly = math.floor(chunk.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
@ -396,7 +371,7 @@ function chunkUtils.colorChunk(chunk, surface, color)
left_top = {lx, ly},
right_bottom = {lx+32, ly+32},
surface = surface,
time_to_live = 180,
time_to_live = ttl or 180,
draw_on_ground = true,
visible = true
})
@ -419,127 +394,111 @@ function chunkUtils.colorXY(x, y, surface, color)
})
end
function chunkUtils.registerEnemyBaseStructure(map, entity, base)
function chunkUtils.registerEnemyBaseStructure(map, entity, tick, incomingBase)
local entityType = entity.type
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
local overlapArray = getEntityOverlapChunks(map, entity)
local getFunc
local setFunc
local universe = map.universe
local hiveTypeLookup = universe.buildingHiveTypeLookup
local hiveType = hiveTypeLookup[entity.name]
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
local addFunc
local universe = map.universe
local hiveTypeLookup = universe.buildingHiveTypeLookup
local hiveType = hiveTypeLookup[entity.name]
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
addFunc = addNestCount
elseif (hiveType == "turret") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
addFunc = addTurretCount
elseif (hiveType == "trap") then
addFunc = addTrapCount
elseif (hiveType == "utility") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
addFunc = addUtilityCount
elseif (hiveType == "hive") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
addFunc = addHiveCount
else
if (entityType == "turret") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
getFunc = getNestCount
setFunc = setNestCount
elseif (hiveType == "turret") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
getFunc = getTurretCount
setFunc = setTurretCount
elseif (hiveType == "trap") then
getFunc = getTrapCount
setFunc = setTrapCount
elseif (hiveType == "utility") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
getFunc = getUtilityCount
setFunc = setUtilityCount
elseif (hiveType == "hive") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
getFunc = getHiveCount
setFunc = setHiveCount
addFunc = addTurretCount
else
if (entityType == "turret") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
getFunc = getTurretCount
setFunc = setTurretCount
elseif (entityType == "unit-spawner") then
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
getFunc = getNestCount
setFunc = setNestCount
end
map.builtEnemyBuilding = map.builtEnemyBuilding + 1
addFunc = addNestCount
end
end
for i=1,#overlapArray do
local chunk = overlapArray[i]
if (chunk ~= -1) then
setFunc(map, chunk, getFunc(map, chunk) + 1)
setChunkBase(map, chunk, base)
local entityUnitNumber = entity.unit_number
local chunks = getEntityOverlapChunks(map, entity)
for i=1,#chunks do
local chunk = chunks[i]
if (chunk ~= -1) then
local base = incomingBase
if not base then
base = findNearbyBase(map, chunk)
if not base then
base = createBase(map, chunk, tick)
end
end
addFunc(map, chunk, entityUnitNumber)
setChunkBase(map, chunk, base)
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
processNestActiveness(map, chunk)
end
end
end
return entity
end
function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageType)
local entityType = entity.type
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
local overlapArray = getEntityOverlapChunks(map, entity)
local getFunc
local setFunc
local hiveTypeLookup = map.universe.buildingHiveTypeLookup
local hiveType = hiveTypeLookup[entity.name]
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
local removeFunc
local hiveTypeLookup = map.universe.buildingHiveTypeLookup
local hiveType = hiveTypeLookup[entity.name]
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
removeFunc = removeNestCount
elseif (hiveType == "turret") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
removeFunc = removeTurretCount
elseif (hiveType == "trap") then
removeFunc = removeTrapCount
elseif (hiveType == "utility") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
removeFunc = removeUtilityCount
elseif (hiveType == "hive") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
removeFunc = removeHiveCount
else
if (entityType == "turret") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
getFunc = getNestCount
setFunc = setNestCount
elseif (hiveType == "turret") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
getFunc = getTurretCount
setFunc = setTurretCount
elseif (hiveType == "trap") then
getFunc = getTrapCount
setFunc = setTrapCount
elseif (hiveType == "utility") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
getFunc = getUtilityCount
setFunc = setUtilityCount
elseif (hiveType == "hive") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
getFunc = getHiveCount
setFunc = setHiveCount
removeFunc = removeTurretCount
else
if (entityType == "turret") then
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
getFunc = getTurretCount
setFunc = setTurretCount
elseif (entityType == "unit-spawner") then
hiveType = "biter-spawner"
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
getFunc = getNestCount
setFunc = setNestCount
hiveType = "biter-spawner"
map.lostEnemyBuilding = map.lostEnemyBuilding + 1
removeFunc = removeNestCount
end
end
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 damageType and usedBases[base.id] then
usedBases[base.id] = true
local damageTypeName = damageType.name
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 3
base.deathEvents = base.deathEvents + 3
end
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
setRaidNestActiveness(map, chunk, 0)
setNestActiveness(map, chunk, 0)
end
removeFunc(map, chunk, entityUnitNumber)
if (getEnemyStructureCount(map, chunk) <= 0) then
removeChunkBase(map, chunk, base)
end
end
for i=1,#overlapArray do
local chunk = overlapArray[i]
if (chunk ~= -1) then
local count = getFunc(map, chunk)
if count then
local base = getChunkBase(map, chunk)
if damageType and base then
local damageTypeName = damageType.name
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 3
base.deathEvents = base.deathEvents + 3
end
if (count <= 1) then
if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then
setRaidNestActiveness(map, chunk, 0)
setNestActiveness(map, chunk, 0)
end
setFunc(map, chunk, 0)
if (getEnemyStructureCount(map, chunk) == 0) then
setChunkBase(map, chunk, nil)
end
else
setFunc(map, chunk, count - 1)
end
end
end
end
end
end

View File

@ -157,8 +157,6 @@ constants.BASE_AI_MAX_STATE_DURATION = 20
constants.BASE_CLEAN_DISTANCE = 13
constants.BASE_DEADZONE_TTL = constants.TICKS_A_MINUTE * 18
constants.BASE_COLLECTION_THRESHOLD = constants.TICKS_A_MINUTE * 2
constants.BASE_DISTANCE_TO_EVO_INDEX = 1 / 9600
@ -320,37 +318,6 @@ constants.UNIT_GROUP_MAX_SPEED_UP = 2
constants.UNIT_GROUP_MAX_SLOWDOWN = 1.0
constants.UNIT_GROUP_SLOWDOWN_FACTOR = 1.0
constants.CONVERSION_TABLE = {
"neutral",
"fire",
"nuclear",
"suicide",
"neutral",
"acid",
"fire",
"physical",
"laser",
"inferno",
"poison",
"troll",
"fast",
"neutral",
"neutral",
"neutral",
"energy-thief",
"electric",
"wasp",
nil,
"acid",
"acid",
"spawner",
"laser",
"inferno",
"suicide",
"acid",
"spawner"
}
constants.BASE_ALIGNMENT_NEUTRAL = 1
constants.BASE_ALIGNMENT_FIRE = 2
constants.BASE_ALIGNMENT_NUCLEAR = 3
@ -370,15 +337,7 @@ constants.BASE_ALIGNMENT_UNDYING = 16
constants.BASE_ALIGNMENT_ENERGY_THIEF = 17
constants.BASE_ALIGNMENT_ELECTRIC = 18
constants.BASE_ALIGNMENT_WASP = 19
constants.BASE_ALIGNMENT_DEADZONE = 20
constants.BASE_ALIGNMENT_NE = 21
constants.BASE_ALIGNMENT_BOBS = 22
constants.BASE_ALIGNMENT_SPAWNER = 23
constants.BASE_ALIGNMENT_NE_BLUE = 24
constants.BASE_ALIGNMENT_NE_RED = 25
constants.BASE_ALIGNMENT_NE_YELLOW = 26
constants.BASE_ALIGNMENT_NE_GREEN = 27
constants.BASE_ALIGNMENT_NE_PINK = 28
constants.BASE_ALIGNMENT_SPAWNER = 20
-- sentinels

21
libs/QueryUtils.lua Normal file
View File

@ -0,0 +1,21 @@
if queryUtilsG then
return queryUtilsG
end
local queryUtils = {}
function queryUtils.setPositionInQuery(query, position)
local point = query.position
point[1] = position.x
point[2] = position.y
end
function queryUtils.setAreaInQuery(query, topLeftPosition, size)
local area = query.area
area[1][1] = topLeftPosition.x
area[1][2] = topLeftPosition.y
area[2][1] = topLeftPosition.x + size
area[2][2] = topLeftPosition.y + size
end
queryUtilsG = queryUtils
return queryUtils

View File

@ -232,18 +232,17 @@ data:extend({
per_user = false
},
{
type = "double-setting",
name = "rampant--deadZoneFrequency",
description = "rampant--deadZoneFrequency",
setting_type = "runtime-global",
default_value = 0.1,
minimum_value = 0.0,
maximum_value = 1.0,
order = "d[modifier]-a[ai]",
per_user = false
},
-- {
-- type = "double-setting",
-- name = "rampant--deadZoneFrequency",
-- description = "rampant--deadZoneFrequency",
-- setting_type = "runtime-global",
-- default_value = 0.1,
-- minimum_value = 0.0,
-- maximum_value = 1.0,
-- order = "d[modifier]-a[ai]",
-- per_user = false
-- },
{
type = "bool-setting",

View File

@ -6,6 +6,7 @@ local chunkUtils = require("libs/ChunkUtils")
local chunkPropertyUtils = require("libs/ChunkPropertyUtils")
local mapUtils = require("libs/MapUtils")
local baseUtils = require("libs/BaseUtils")
local queryUtils = require("libs/QueryUtils")
-- local tendrilUtils = require("libs/TendrilUtils")
function tests.pheromoneLevels(size)
@ -209,14 +210,6 @@ function tests.createEnemy(x,d)
return game.get_surface(global.natives.activeSurface).create_entity(a)
end
function tests.registeredNest(x)
local entity = tests.createEnemy(x)
chunk.registerEnemyBaseStructure(global.map,
entity,
nil,
game.get_surface(global.natives.activeSurface))
end
function tests.attackOrigin()
local enemy = game.get_surface(global.natives.activeSurface).find_nearest_enemy({position={0,0},
max_distance = 1000})
@ -319,30 +312,51 @@ end
function tests.unitBuildBase()
end
function tests.showBaseGrid()
local n = {}
for k,v in pairs(global.natives.bases) do
n[v] = k % 4
end
local chunks = global.map.chunkToBase
for chunk,base in pairs(chunks) do
local pick = n[base]
local color = "concrete"
if base.alignment == constants.BASE_ALIGNMENT_NE then
color = "hazard-concrete-left"
elseif (pick == 1) then
color = "water"
elseif (pick == 2) then
color = "deepwater"
elseif (pick == 3) then
color = "water-green"
function tests.showBaseGrid(time)
local map = global.universe.maps[game.player.surface.index]
local chunks = map.chunkToBase
for chunk in pairs(chunks) do
local count = chunkPropertyUtils.getEnemyStructureCount(map, chunk)
chunkUtils.mapScanEnemyChunk(chunk, map)
local newCount = chunkPropertyUtils.getEnemyStructureCount(map, chunk)
if newCount ~= count then
constants.gpsDebug(chunk.x+16,chunk.y+16, "f2:" .. tostring(count) .. "/" .. tostring(newCount))
chunkUtils.colorChunk(chunk, game.player.surface.index, {0.3, 0.1, 0.1, 0.6}, time and tonumber(time))
else
chunkUtils.colorChunk(chunk, game.player.surface.index, nil, time and tonumber(time))
end
chunkUtils.colorChunk(chunk.x, chunk.y, color, game.get_surface(global.natives.activeSurface))
end
end
function tests.getEnemyStructureCount()
local map = global.universe.maps[game.player.surface.index]
local chunk = mapUtils.getChunkByPosition(map, game.player.character.position)
print(chunk.x, chunk.y, chunkPropertyUtils.getEnemyStructureCount(map, chunk))
end
function tests.scanEnemy()
local map = global.universe.maps[game.player.surface.index]
local chunk = mapUtils.getChunkByPosition(map, game.player.character.position)
local universe = map.universe
local buildingHiveTypeLookup = universe.buildingHiveTypeLookup
local query = universe.filteredEntitiesEnemyStructureQuery
queryUtils.setAreaInQuery(query, chunk, constants.CHUNK_SIZE)
local buildings = map.surface.find_entities_filtered(query)
local counts = map.chunkScanCounts
for i=1,#constants.HIVE_BUILDINGS_TYPES do
counts[constants.HIVE_BUILDINGS_TYPES[i]] = 0
end
for i=1,#buildings do
local building = buildings[i]
local hiveType = buildingHiveTypeLookup[building.name] or
(((building.type == "turret") and "turret") or "biter-spawner")
counts[hiveType] = counts[hiveType] + 1
end
print(game.tick, serpent.dump(counts))
end
function tests.showMovementGrid()
local chunks = global.map.processQueue
for i=1,#chunks do