From 5d6519c6404f38f26d56181b48edf95a5657ba6c Mon Sep 17 00:00:00 2001 From: Aaron Veden Date: Tue, 21 Mar 2023 23:09:51 -0700 Subject: [PATCH] FACTO-236: Hives now use script controlled expansion --- changelog.txt | 2 + control.lua | 12 ++-- libs/BaseUtils.lua | 146 +++++++++++++++++++++++++++++++++++++++----- libs/ChunkUtils.lua | 82 ++++++++++++++++++++++++- libs/Constants.lua | 59 ++++++++++++++++-- libs/Processor.lua | 125 +++++++++++++++++++++++++++++-------- libs/Upgrade.lua | 7 +++ 7 files changed, 382 insertions(+), 51 deletions(-) diff --git a/changelog.txt b/changelog.txt index ac9fba5..a7b924e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -16,6 +16,7 @@ Version: 3.2.0 - When enemies die there body parts can fill in water tiles. Can be disabled in mod settings. - Added base mutation history to prevent mutations to previously mutated factions. Configurable amount of history in Mod Settings. - Hives now produce a single upper tier unit + - Hives now have a controlled expansion that doesn't use the unit-spawner non-unit spawning capabilities of the factorio engine Compatibility: - Added interface for adding and removing excluded surfaces Tweaks: @@ -69,6 +70,7 @@ Version: 3.2.0 - Removed unneeded iterators - Moved map properties directly into chunk object - Moved background chunk scanning under a mod setting for when mods don't raise events + - Pending upgrades are limited to 100 queued events for existing entity mutation and hive entity creation Framework: - Consolidated most libraries diff --git a/control.lua b/control.lua index 2df9115..ebd0f12 100644 --- a/control.lua +++ b/control.lua @@ -51,6 +51,8 @@ local PLAYER_PHEROMONE = Constants.PLAYER_PHEROMONE local UNIT_DEATH_POINT_COST = Constants.UNIT_DEATH_POINT_COST +local PENDING_UPGRADE_CREATION_THESHOLD = Constants.PENDING_UPGRADE_CREATION_THESHOLD + local MAX_HIVE_TTL = Constants.MAX_HIVE_TTL local MIN_HIVE_TTL = Constants.MIN_HIVE_TTL local DEV_HIVE_TTL = Constants.DEV_HIVE_TTL @@ -119,6 +121,7 @@ local scanPlayerMap = Processor.scanPlayerMap local scanResourceMap = Processor.scanResourceMap local processNests = Processor.processNests +local processHives = Processor.processHives local rallyUnits = Squad.rallyUnits @@ -955,7 +958,7 @@ script.on_event(defines.events.on_tick, function () local gameRef = game local tick = gameRef.tick - local range = (Universe.legacyChunkScanning and 5) or 4 + local range = (Universe.legacyChunkScanning and 4) or 3 local pick = tick % range -- local profiler = game.create_profiler() @@ -967,6 +970,8 @@ script.on_event(defines.events.on_tick, recycleBases() end cleanUpMapTables(tick) + planning(gameRef.forces.enemy.evolution_factor) + processHives(tick) elseif (pick == 1) then processPlayers(gameRef.connected_players, tick) elseif (pick == 2) then @@ -975,11 +980,8 @@ script.on_event(defines.events.on_tick, disperseVictoryScent() processAttackWaves() processClouds(tick) - elseif (pick == 3) then - processPendingUpgrades(tick) processScanChunks() - planning(gameRef.forces.enemy.evolution_factor) - elseif (pick == 4) then + elseif (pick == 3) then if map then scanPlayerMap(map) scanResourceMap(map) diff --git a/libs/BaseUtils.lua b/libs/BaseUtils.lua index 2f7257f..295ee49 100644 --- a/libs/BaseUtils.lua +++ b/libs/BaseUtils.lua @@ -32,6 +32,8 @@ local MapUtils = require("MapUtils") -- Constants +local PENDING_UPGRADE_CREATION_THESHOLD = Constants.PENDING_UPGRADE_CREATION_THESHOLD + local TIERS = Constants.TIERS local EVO_TO_TIER_MAPPING = Constants.EVO_TO_TIER_MAPPING local BUILDING_HIVE_TYPE_LOOKUP = Constants.BUILDING_HIVE_TYPE_LOOKUP @@ -256,7 +258,42 @@ local function entityUpgrade(baseAlignment, tier, maxTier, originalEntity) return entity end -function BaseUtils.findEntityUpgrade(baseAlignment, currentEvo, evoIndex, originalEntity, map, evolve) +local function findEntityCreation(baseAlignment, evoIndex, position, map, entityType) + local tier = evoToTier(evoIndex, 5) + local maxTier = evoToTier(evoIndex, 4) + + if (tier > maxTier) then + maxTier = tier + end + + local chunk = getChunkByPosition(map, position) + if not entityType then + if Universe.random() < 0.5 then + entityType = "biter-spawner" + else + entityType = "spitter-spawner" + end + end + local roll = Universe.random() + local makeHive = (chunk ~= -1) and + ( + (entityType == "biter-spawner") or (entityType == "spitter-spawner") + ) + and + ( + ( + (roll <= 0.01) + ) + or + ( + (roll <= 0.210) and + chunk.resourceGenerator + ) + ) + return initialEntityUpgrade(baseAlignment, tier, maxTier, (makeHive and "hive"), entityType) +end + +local function findEntityUpgrade(baseAlignment, currentEvo, evoIndex, originalEntity, map, evolve) local adjCurrentEvo = mMax( ((baseAlignment ~= ENEMY_ALIGNMENT_LOOKUP[originalEntity.name]) and 0) or currentEvo, 0 @@ -405,37 +442,115 @@ function BaseUtils.queueUpgrade(entity, base, disPos, evolve, timeDelay) local currentEvo = entity.prototype.build_base_evolution_requirement or 0 - local distance = mMin(1, euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX) + local distance = mMin( + 1, + euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX + ) local evoIndex = mMax(distance, Universe.evolutionLevel) - local name = BaseUtils.findEntityUpgrade(pickedBaseAlignment, - currentEvo, - evoIndex, - entity, - map, - evolve) + local name = findEntityUpgrade(pickedBaseAlignment, + currentEvo, + evoIndex, + entity, + map, + evolve) - if name == entity.name then + local entityName = entity.name + if name == entityName then return end + local surface = map.surface if not evolve and Universe.printBaseUpgrades then - local surface = base.map.surface surface.print( "["..base.id.."]:"..surface.name.." Upgrading " - .. entity.name .. " to " .. name + .. entityName .. " to " .. name .. " [gps=".. position.x ..",".. position.y .."]" ) end - Universe.pendingUpgrades[entity.unit_number] = { + local unitNumber = entity.unit_number + + position = surface.find_non_colliding_position( + name, + position, + 8, + 1, + true + ) + + Universe.pendingUpgrades[Universe.upgradeId] = { ["position"] = position, ["map"] = map, ["name"] = name, ["entity"] = entity, ["delayTLL"] = timeDelay, + ["hive"] = Universe.hives[unitNumber] or Universe.hiveData[unitNumber], ["state"] = 1 } + Universe.pendingUpgradesLength = Universe.pendingUpgradesLength + 1 + Universe.upgradeId = Universe.upgradeId + 1 +end + +function BaseUtils.queueCreation(base, position, entityType, timeDelay, hiveData) + local map = base.map + local baseAlignment = base.alignment + + if Universe.pendingUpgradesLength > PENDING_UPGRADE_CREATION_THESHOLD then + return + end + + local pickedBaseAlignment + if baseAlignment[2] then + if Universe.random() < 0.75 then + pickedBaseAlignment = baseAlignment[2] + else + pickedBaseAlignment = baseAlignment[1] + end + else + pickedBaseAlignment = baseAlignment[1] + end + + local distance = mMin( + 1, + euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX + ) + local evoIndex = mMax(distance, Universe.evolutionLevel) + + local name = findEntityCreation( + pickedBaseAlignment, + evoIndex, + position, + map, + entityType + ) + + if not name then + return + end + + position = map.surface.find_non_colliding_position( + name, + position, + 8, + 1, + true + ) + + if not position then + return + end + + Universe.pendingUpgrades[Universe.upgradeId] = { + ["position"] = position, + ["map"] = map, + ["name"] = name, + ["delayTLL"] = timeDelay, + ["hive"] = hiveData, + ["state"] = 2 + } + Universe.pendingUpgradesLength = Universe.pendingUpgradesLength + 1 + Universe.upgradeId = Universe.upgradeId + 1 end local function pickMutationFromDamageType(damageType, roll, base) @@ -561,9 +676,10 @@ function BaseUtils.upgradeBaseBasedOnDamage(base) end function BaseUtils.processBaseMutation(chunk, map, base) - if not base.alignment[1] or - (base.stateGeneration ~= BASE_GENERATION_STATE_ACTIVE) or - (Universe.random() >= 0.30) + if not base.alignment[1] + or (base.stateGeneration ~= BASE_GENERATION_STATE_ACTIVE) + or (Universe.random() >= 0.30) + or (Universe.pendingUpgradesLength > PENDING_UPGRADE_CREATION_THESHOLD) then return end diff --git a/libs/ChunkUtils.lua b/libs/ChunkUtils.lua index 6820d20..6738050 100644 --- a/libs/ChunkUtils.lua +++ b/libs/ChunkUtils.lua @@ -35,6 +35,8 @@ local Utils = require("Utils") -- Constants +local BUILDING_HIVE_TIER_LOOKUP = Constants.BUILDING_HIVE_TIER_LOOKUP + local VANILLA_ENTITY_TYPE_LOOKUP = Constants.VANILLA_ENTITY_TYPE_LOOKUP local BUILDING_HIVE_TYPE_LOOKUP = Constants.BUILDING_HIVE_TYPE_LOOKUP @@ -62,6 +64,14 @@ local RESOURCE_NORMALIZER = Constants.RESOURCE_NORMALIZER local CHUNK_TICK = Constants.CHUNK_TICK +local DEV_HIVE_TTL = Constants.DEV_HIVE_TTL +local MAX_HIVE_TTL = Constants.MAX_HIVE_TTL +local MIN_HIVE_TTL = Constants.MIN_HIVE_TTL + +local HIVE_MAX_NESTS = Constants.HIVE_MAX_NESTS +local HIVE_MAX_TURRETS = Constants.HIVE_MAX_TURRETS +local HIVE_MAX_HIVES = Constants.HIVE_MAX_HIVES + local GENERATOR_PHEROMONE_LEVEL_1 = Constants.GENERATOR_PHEROMONE_LEVEL_1 local GENERATOR_PHEROMONE_LEVEL_3 = Constants.GENERATOR_PHEROMONE_LEVEL_3 local GENERATOR_PHEROMONE_LEVEL_5 = Constants.GENERATOR_PHEROMONE_LEVEL_5 @@ -104,6 +114,8 @@ local createBase = BaseUtils.createBase local modifyBaseUnitPoints = BaseUtils.modifyBaseUnitPoints local euclideanDistancePoints = MathUtils.euclideanDistancePoints +local gaussianRandomRangeRG = MathUtils.gaussianRandomRangeRG +local linearInterpolation = MathUtils.linearInterpolation local setPassable = ChunkPropertyUtils.setPassable local setPathRating = ChunkPropertyUtils.setPathRating @@ -427,8 +439,47 @@ function ChunkUtils.colorXY(x, y, surface, color) }) end +local function registerHive(base, entityUnitNumber, hiveType, name, position, tick) + if hiveType == "hive" then + if not Universe.hives[entityUnitNumber] then + local tier = BUILDING_HIVE_TIER_LOOKUP[name] + local maxNests = HIVE_MAX_NESTS[tier] + local maxTurrets = HIVE_MAX_TURRETS[tier] + local maxHives + local rollHives = Universe.random() + if rollHives < 0.05 then + maxHives = HIVE_MAX_HIVES[tier] + else + maxHives = 0 + end + local hiveData = { + hiveId = entityUnitNumber, + position = position, + base = base, + hive = 0, + nest = 0, + turret = 0, + maxNests = ((maxNests > 0) and (Universe.random(maxNests) - 1)) or 0, + maxTurrets = ((maxTurrets > 0) and (Universe.random(maxTurrets) - 1)) or 0, + maxHives = ((maxHives > 0) and (Universe.random(maxHives) - 1)) or 0, + tier = tier, + tick = tick + gaussianRandomRangeRG( + linearInterpolation(Universe.evolutionLevel, MAX_HIVE_TTL, MIN_HIVE_TTL), + DEV_HIVE_TTL, + MIN_HIVE_TTL, + MAX_HIVE_TTL, + Universe.random + ) + } + Universe.hives[entityUnitNumber] = hiveData + Universe.activeHives[entityUnitNumber] = hiveData + end + end +end + function ChunkUtils.registerEnemyBaseStructure(entity, base, tick, skipCount) - local hiveType = BUILDING_HIVE_TYPE_LOOKUP[entity.name] + local name = entity.name + local hiveType = BUILDING_HIVE_TYPE_LOOKUP[name] local addFunc = registerTypeToAddFn[hiveType] @@ -451,11 +502,39 @@ function ChunkUtils.registerEnemyBaseStructure(entity, base, tick, skipCount) end end end + registerHive(base, entityUnitNumber, hiveType, name, entity.position, tick) if added and (not skipCount) then base.builtEnemyBuilding = base.builtEnemyBuilding + 1 end end +local function unregisterHive(entityUnitNumber, hiveType) + if Universe.hives[entityUnitNumber] then + Universe.hives[entityUnitNumber] = nil + Universe.activeHives[entityUnitNumber] = nil + if Universe.hiveIterator == entityUnitNumber then + Universe.hiveIterator = nil + end + else + local hiveData = Universe.hiveData[entityUnitNumber] + if hiveData then + Universe.activeHives[hiveData.hiveId] = hiveData + local adjustedHiveType = ( + ( + (hiveType == "spitter-spawner") + or (hiveType == "biter-spawner") + ) + and "nest" + ) or hiveType + hiveData[adjustedHiveType] = hiveData.nest - 1 + if hiveData[adjustedHiveType] < 0 then + hiveData[adjustedHiveType] = 0 + end + Universe.hiveData[entityUnitNumber] = nil + end + end +end + function ChunkUtils.unregisterEnemyBaseStructure(map, entity, damageTypeName, skipCount) local hiveType = BUILDING_HIVE_TYPE_LOOKUP[entity.name] @@ -490,6 +569,7 @@ function ChunkUtils.unregisterEnemyBaseStructure(map, entity, damageTypeName, sk end end end + unregisterHive(entityUnitNumber, hiveType) end function ChunkUtils.accountPlayerEntity(entity, map, addObject, base) diff --git a/libs/Constants.lua b/libs/Constants.lua index 6248968..5f612da 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -72,6 +72,7 @@ constants.DOUBLE_CHUNK_SIZE = constants.CHUNK_SIZE * 2 constants.TRIPLE_CHUNK_SIZE = constants.CHUNK_SIZE * 3 constants.HALF_CHUNK_SIZE = constants.CHUNK_SIZE / 2 constants.QUARTER_CHUNK_SIZE = constants.HALF_CHUNK_SIZE / 2 +constants.EIGHTH_CHUNK_SIZE = constants.QUARTER_CHUNK_SIZE / 2 constants.CHUNK_SIZE_DIVIDER = 1 / constants.CHUNK_SIZE @@ -1529,6 +1530,8 @@ constants.HIVE_BUILDINGS_TYPES = { "hive" } +constants.PENDING_UPGRADE_CREATION_THESHOLD = 100 + constants.VICTORY_SCENT_MULTIPLER = {} for x=1,9 do for y=1,9 do @@ -1569,21 +1572,57 @@ for _,cost in pairs(constants.HIVE_BUILDINGS_COST) do end end +constants.HIVE_MAX_NESTS = { + 2, + 3, + 3, + 4, + 4, + 4, + 5, + 5, + 6, + 6 +} +constants.HIVE_MAX_TURRETS = { + 4, + 4, + 5, + 5, + 6, + 6, + 7, + 7, + 8, + 8 +} +constants.HIVE_MAX_HIVES = { + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 2, + 2, + 2 +} + constants.FACTION_MUTATION_MAPPING = {} constants.FACTION_MUTATION_MAPPING["spitter-spawner"] = {"biter-spawner", "hive"} constants.FACTION_MUTATION_MAPPING["biter-spawner"] = {"spitter-spawner", "hive"} constants.FACTION_MUTATION_MAPPING["hive"] = {"utility", "biter-spawner", "spitter-spawner"} -constants.FACTION_MUTATION_MAPPING["turret"] = {"trap"} -constants.FACTION_MUTATION_MAPPING["trap"] = {"turret"} +constants.FACTION_MUTATION_MAPPING["turret"] = {} constants.FACTION_MUTATION_MAPPING["utility"] = {"hive", "biter-spawner", "spitter-spawner"} function constants.gpsDebug(x, y, msg) game.print("[gps=".. x .. "," .. y .. "]" .. msg) end -constants.MAX_HIVE_TTL = 2485 -constants.MIN_HIVE_TTL = 890 -constants.DEV_HIVE_TTL = 150 +constants.MAX_HIVE_TTL = 12400 +constants.MIN_HIVE_TTL = 4800 +constants.DEV_HIVE_TTL = 450 local rg = mathUtils.xorRandom(settings.startup["rampant--enemySeed"].value) @@ -1599,6 +1638,8 @@ local costLookup = {} constants.COST_LOOKUP = costLookup --costLookup local buildingHiveTypeLookup = {} constants.BUILDING_HIVE_TYPE_LOOKUP = buildingHiveTypeLookup --buildingHiveTypeLookup +local buildingHiveTierLookup = {} +constants.BUILDING_HIVE_TIER_LOOKUP = buildingHiveTierLookup --buildingHiveTierLookup local vanillaEntityLookup = {} constants.VANILLA_ENTITY_TYPE_LOOKUP = vanillaEntityLookup --vanillaEntityTypeLookup local entitySkipCountLookup = {} @@ -1611,6 +1652,13 @@ buildingHiveTypeLookup["medium-worm-turret"] = "turret" buildingHiveTypeLookup["big-worm-turret"] = "turret" buildingHiveTypeLookup["behemoth-worm-turret"] = "turret" +buildingHiveTierLookup["biter-spawner"] = 1 +buildingHiveTierLookup["spitter-spawner"] = 1 +buildingHiveTierLookup["small-worm-turret"] = 1 +buildingHiveTierLookup["medium-worm-turret"] = 1 +buildingHiveTierLookup["big-worm-turret"] = 1 +buildingHiveTierLookup["behemoth-worm-turret"] = 1 + vanillaEntityLookup["biter-spawner"] = true vanillaEntityLookup["spitter-spawner"] = true vanillaEntityLookup["small-worm-turret"] = true @@ -1696,6 +1744,7 @@ for i=1,#constants.FACTION_SET do enemyAlignmentLookup[entry] = faction.type costLookup[entry] = constants.HIVE_BUILDINGS_COST[building.type] buildingHiveTypeLookup[entry] = building.type + buildingHiveTierLookup[entry] = t variationSet[#variationSet+1] = entry for _,unit in pairs(faction.units) do if isMember(unit.attributes, "skipKillCount") then diff --git a/libs/Processor.lua b/libs/Processor.lua index 5f5a88d..e1b32d3 100644 --- a/libs/Processor.lua +++ b/libs/Processor.lua @@ -38,6 +38,8 @@ local MathUtils = require("MathUtils") -- Constants local CHUNK_SIZE = Constants.CHUNK_SIZE +local EIGHTH_CHUNK_SIZE = Constants.EIGHTH_CHUNK_SIZE +local HALF_CHUNK_SIZE = Constants.HALF_CHUNK_SIZE local PLAYER_PHEROMONE_GENERATOR_AMOUNT = Constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT @@ -55,22 +57,27 @@ local AI_VENGENCE_SQUAD_COST = Constants.AI_VENGENCE_SQUAD_COST local COOLDOWN_DRAIN = Constants.COOLDOWN_DRAIN local COOLDOWN_RALLY = Constants.COOLDOWN_RALLY local COOLDOWN_RETREAT = Constants.COOLDOWN_RETREAT -local BASE_DISTANCE_TO_EVO_INDEX = Constants.BASE_DISTANCE_TO_EVO_INDEX + +local BUILDING_HIVE_TYPE_LOOKUP = Constants.BUILDING_HIVE_TYPE_LOOKUP + +local DEV_HIVE_TTL = Constants.DEV_HIVE_TTL +local MAX_HIVE_TTL = Constants.MAX_HIVE_TTL +local MIN_HIVE_TTL = Constants.MIN_HIVE_TTL -- imported functions +local distortPositionConcentricCircles = MathUtils.distortPositionConcentricCircles +local linearInterpolation = MathUtils.linearInterpolation +local gaussianRandomRangeRG = MathUtils.gaussianRandomRangeRG local findInsertionPoint = MapUtils.findInsertionPoint local createChunk = ChunkUtils.createChunk local initialScan = ChunkUtils.initialScan -local euclideanDistancePoints = MathUtils.euclideanDistancePoints local removeChunkFromMap = MapUtils.removeChunkFromMap local chunkPassScan = ChunkUtils.chunkPassScan -local findEntityUpgrade = BaseUtils.findEntityUpgrade local unregisterEnemyBaseStructure = ChunkUtils.unregisterEnemyBaseStructure -local registerEnemyBaseStructure = ChunkUtils.registerEnemyBaseStructure local setPositionInQuery = Utils.setPositionInQuery local addPlayerGenerator = ChunkPropertyUtils.addPlayerGenerator @@ -78,6 +85,8 @@ local findNearbyBase = ChunkPropertyUtils.findNearbyBase local removeChunkToNest = MapUtils.removeChunkToNest +local queueCreation = BaseUtils.queueCreation + local processPheromone = MapUtils.processPheromone local getCombinedDeathGeneratorRating = ChunkPropertyUtils.getCombinedDeathGeneratorRating @@ -476,6 +485,60 @@ function Processor.processClouds(tick) map.surface.create_entity(Universe.obaCreateBuildCloudQuery) end +function Processor.processHives(tick) + local entityId = Universe.hiveIterator + local hiveData + if not entityId then + entityId, hiveData = next(Universe.activeHives, nil) + else + hiveData = Universe.activeHives[entityId] + end + if not entityId then + Universe.hiveIterator = nil + return + end + if tick < hiveData.tick then + return + end + Universe.hiveIterator = next(Universe.activeHives, entityId) + local base = hiveData.base + local map = base.map + if not map.surface.valid then + Universe.activeHives[entityId] = nil + return + end + hiveData.tick = tick + + gaussianRandomRangeRG( + linearInterpolation(Universe.evolutionLevel, MAX_HIVE_TTL, MIN_HIVE_TTL), + DEV_HIVE_TTL, + MIN_HIVE_TTL, + MAX_HIVE_TTL, + Universe.random + ) + + local timeDelay = 0 + + local position = distortPositionConcentricCircles( + Universe.random, + hiveData.position, + EIGHTH_CHUNK_SIZE * hiveData.tier, + EIGHTH_CHUNK_SIZE + ) + + if hiveData.nest < hiveData.maxNests then + local entityType = "biter-spawner" + if Universe.random() < 0.5 then + entityType = "spitter-spawner" + end + queueCreation(base, position, entityType, timeDelay, hiveData) + elseif hiveData.turret < hiveData.maxTurrets then + queueCreation(base, position, "turret", timeDelay, hiveData) + elseif hiveData.hive < hiveData.maxHives then + queueCreation(base, position, "hive", timeDelay, hiveData) + else + Universe.activeHives[entityId] = nil + end +end function Processor.processPendingChunks(tick, flush) local pendingChunks = Universe.pendingChunks @@ -544,52 +607,64 @@ function Processor.processPendingChunks(tick, flush) end function Processor.processPendingUpgrades(tick) - local entityId, entityData = next(Universe.pendingUpgrades, nil) - if not entityId then - if tableSize(Universe.pendingUpgrades) == 0 then + local upgradeId, entityData = next(Universe.pendingUpgrades, nil) + if not upgradeId then + if Universe.pendingUpgradesLength == 0 then Universe.pendingUpgrades = {} end return end local entity = entityData.entity - if (entityData.state ~= 3) and not entity.valid then - Universe.pendingUpgrades[entityId] = nil + if (entityData.state ~= 2) and not entity.valid then + Universe.pendingUpgrades[upgradeId] = nil + Universe.pendingUpgradesLength = Universe.pendingUpgradesLength - 1 return end if entityData.delayTLL and tick < entityData.delayTLL then return end + local state = entityData.state if state == 1 then local map = entityData.map unregisterEnemyBaseStructure(map, entity, nil, true) - - entityData.position = map.surface.find_non_colliding_position( - entityData.name, - entityData.position, - 8, - 1, - true - ) - - entityData.state = 2 - elseif state == 2 then entity.destroy() if not entityData.name or not entityData.position then - Universe.pendingUpgrades[entityId] = nil + Universe.pendingUpgrades[upgradeId] = nil + Universe.pendingUpgradesLength = Universe.pendingUpgradesLength - 1 return end - entityData.state = 3 - elseif state == 3 then - Universe.pendingUpgrades[entityId] = nil + entityData.state = 2 + else + Universe.pendingUpgrades[upgradeId] = nil + Universe.pendingUpgradesLength = Universe.pendingUpgradesLength - 1 local query = Queries.createEntityQuery local name = entityData.name query.name = name local position = entityData.position setPositionInQuery(query, position) local surface = entityData.map.surface - surface.create_entity(query) + local newEntity = surface.create_entity(query) + if newEntity and newEntity.valid then + local hiveType = BUILDING_HIVE_TYPE_LOOKUP[name] + if hiveType == "hive" then + Universe.hives[newEntity.unit_number] = entityData.hive + else + local hiveData = entityData.hive + if hiveData then + Universe.hiveData[newEntity.unit_number] = entityData.hive + local adjustedHiveType = ( + ( + (hiveType == "spitter-spawner") + or (hiveType == "biter-spawner") + ) + and "nest" + ) or hiveType + hiveData[adjustedHiveType] = hiveData[adjustedHiveType] + 1 + end + end + end if remote.interfaces["kr-creep"] then remote.call( "kr-creep", diff --git a/libs/Upgrade.lua b/libs/Upgrade.lua index 2b07268..6457386 100644 --- a/libs/Upgrade.lua +++ b/libs/Upgrade.lua @@ -451,6 +451,7 @@ function Upgrade.addUniverseProperties() Universe.printAIStateChanges = settings.global["rampant--printAIStateChanges"].value Universe.debugTemperament = settings.global["rampant--debugTemperament"].value + Universe.upgradeId = 0 Universe.eventId = 0 Universe.chunkId = 0 Universe.maps = {} @@ -480,6 +481,11 @@ function Upgrade.addUniverseProperties() Universe.chunkToRallys = {} Universe.chunkToPassScan = {} + Universe.hiveData = {} + Universe.hives = {} + Universe.activeHives = {} + Universe.hiveIterator = nil + Universe.baseId = 0 Universe.awake = false @@ -497,6 +503,7 @@ function Upgrade.addUniverseProperties() Universe.excludedSurfaces = {} Universe.pendingUpgrades = {} + Universe.pendingUpgradesLength = 0 Universe.settlePurpleCloud = {} end end