983 lines
29 KiB
Lua

local upgrade = {}
-- imports
local constants = require("libs/Constants")
-- constants
local DEFINES_COMMAND_GROUP = defines.command.group
local DEFINES_COMMAND_WANDER = defines.command.wander
local DEFINES_COMMAND_BUILD_BASE = defines.command.build_base
local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area
local DEFINES_COMMAND_GO_TO_LOCATION = defines.command.go_to_location
local DEFINES_COMMMAD_COMPOUND = defines.command.compound
local DEFINES_COMMAND_FLEE = defines.command.flee
local DEFINES_COMMAND_STOP = defines.command.stop
local DEFINES_COMPOUND_COMMAND_RETURN_LAST = defines.compound_command.return_last
local DEFINES_DISTRACTION_NONE = defines.distraction.none
local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy
local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
local CHUNK_SIZE = constants.CHUNK_SIZE
local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE
-- imported functions
-- module code
local function addCommandSet(queriesAndCommands)
-- preallocating memory to be used in code, making it fast by reducing garbage generated.
queriesAndCommands.neighbors = {
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
}
queriesAndCommands.cardinalNeighbors = {
-1,
-1,
-1,
-1
}
queriesAndCommands.position = {
x=0,
y=0
}
queriesAndCommands.position2 = {
x=0,
y=0
}
queriesAndCommands.position3 = {
x=0,
y=0
}
queriesAndCommands.chunkOverlapArray = {
-1,
-1,
-1,
-1
}
queriesAndCommands.position2Top = {0, 0}
queriesAndCommands.position2Bottom = {0, 0}
--this is shared between two different queries
queriesAndCommands.area = {
{0, 0},
{0, 0}
}
queriesAndCommands.area2 = {
queriesAndCommands.position2Top,
queriesAndCommands.position2Bottom
}
queriesAndCommands.buildPositionTop = {0, 0}
queriesAndCommands.buildPositionBottom = {0, 0}
queriesAndCommands.buildArea = {
queriesAndCommands.buildPositionTop,
queriesAndCommands.buildPositionBottom
}
queriesAndCommands.countResourcesQuery = {
area=queriesAndCommands.area,
type="resource"
}
queriesAndCommands.hasPlayerStructuresQuery = {
area=queriesAndCommands.area,
force=queriesAndCommands.activePlayerForces,
limit=1
}
-- autofill from constants
local GENERATOR_PHEROMONE_LEVEL = constants.GENERATOR_PHEROMONE_LEVEL
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
queriesAndCommands.filteredEntities_player_pheromones = {}
for lvlName, values in pairs(GENERATOR_PHEROMONE_LEVEL) do
queriesAndCommands.filteredEntities_player_pheromones[lvlName] = {
area=queriesAndCommands.area,
force=queriesAndCommands.activePlayerForces,
type = {}
}
local filtered_types = queriesAndCommands.filteredEntities_player_pheromones[lvlName].type
---------
for entityType, entitylvlName in pairs(BUILDING_PHEROMONES) do
if entitylvlName == lvlName then
filtered_types[#filtered_types+1] = entityType
end
end
if #filtered_types==0 then
queriesAndCommands.filteredEntities_player_pheromones[lvlName] = nil
end
end
-- - !КДА
-- Factorissimo. Yes, this is a "storage-tank" enities
queriesAndCommands.filteredEntitiesPlayerQueryFactorissimo = {
area=queriesAndCommands.area,
force=queriesAndCommands.activePlayerForces,
collision_mask = "player-layer",
type={"storage-tank"}
}
queriesAndCommands.filteredEntitiesUnitQuery = {
area=queriesAndCommands.area,
force="enemy",
type="unit"
}
queriesAndCommands.filteredEntitiesEnemyStructureQuery = {
area=queriesAndCommands.area,
force="enemy",
type={
"turret",
"unit-spawner"
}
}
queriesAndCommands.filteredEntitiesPointQueryLimited = {
position = queriesAndCommands.position,
radius = 10,
limit = 1,
force = "enemy",
type = {
"unit-spawner",
"turret"
}
}
queriesAndCommands.createBuildCloudQuery = {
name = "build-clear-cloud-rampant",
position = queriesAndCommands.position
}
queriesAndCommands.activePlayerForces = {"player"}
queriesAndCommands.nonPlayerForces = {"neutral", "enemy"}
for _,force in pairs(game.forces) do
local add = true
if (force.name ~= "neutral") and (force.name ~= "enemy") then
for i=1,#queriesAndCommands.activePlayerForces do
if (queriesAndCommands.activePlayerForces[i] == force.name) then
add = false
break
end
end
if add then
queriesAndCommands.activePlayerForces[#queriesAndCommands.activePlayerForces+1] = force.name
else
queriesAndCommands.nonPlayerForces[#queriesAndCommands.nonPlayerForces+1] = force.name
end
end
end
queriesAndCommands.filteredEntitiesChunkNeutral = {
area=queriesAndCommands.area,
collision_mask = "player-layer",
type={
"tree",
"simple-entity"
}
}
local sharedArea = {
{0,0},
{0,0}
}
queriesAndCommands.filteredEntitiesCliffQuery = {
area=sharedArea,
type="cliff",
limit = 1
}
queriesAndCommands.filteredTilesPathQuery = {
area=sharedArea,
collision_mask="water-tile",
limit = 1
}
queriesAndCommands.cliffQuery = {
area=queriesAndCommands.area2,
type="cliff"
}
queriesAndCommands.canPlaceQuery = {
name="",
position={0,0}
}
queriesAndCommands.filteredTilesQuery = {
collision_mask="water-tile",
area=queriesAndCommands.area
}
queriesAndCommands.upgradeEntityQuery = {
name = "",
position = nil
}
queriesAndCommands.attackCommand = {
type = DEFINES_COMMAND_ATTACK_AREA,
destination = queriesAndCommands.position,
radius = CHUNK_SIZE * 1.5,
distraction = DEFINES_DISTRACTION_BY_ANYTHING
}
queriesAndCommands.moveCommand = {
type = DEFINES_COMMAND_GO_TO_LOCATION,
destination = queriesAndCommands.position,
pathfind_flags = { cache = true },
distraction = DEFINES_DISTRACTION_BY_ENEMY
}
queriesAndCommands.settleCommand = {
type = DEFINES_COMMAND_BUILD_BASE,
destination = queriesAndCommands.position,
distraction = DEFINES_DISTRACTION_BY_ENEMY,
ignore_planner = true
}
queriesAndCommands.wonderCommand = {
type = DEFINES_COMMAND_WANDER,
wander_in_group = false,
radius = TRIPLE_CHUNK_SIZE*2,
ticks_to_wait = 36000
}
queriesAndCommands.stopCommand = {
type = DEFINES_COMMAND_STOP
}
queriesAndCommands.compoundSettleCommand = {
type = DEFINES_COMMMAD_COMPOUND,
structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST,
commands = {
queriesAndCommands.wonder2Command,
queriesAndCommands.settleCommand
}
}
queriesAndCommands.retreatCommand = {
type = DEFINES_COMMAND_GROUP,
group = nil,
distraction = DEFINES_DISTRACTION_BY_ANYTHING,
use_group_distraction = true
}
queriesAndCommands.fleeCommand = {
type = DEFINES_COMMAND_FLEE,
from = nil,
distraction = DEFINES_DISTRACTION_NONE
}
queriesAndCommands.compoundRetreatGroupCommand = {
type = DEFINES_COMMMAD_COMPOUND,
structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST,
commands = {
queriesAndCommands.stopCommand,
queriesAndCommands.fleeCommand,
queriesAndCommands.retreatCommand
}
}
queriesAndCommands.formGroupCommand = {
type = DEFINES_COMMAND_GROUP,
group = nil,
distraction = DEFINES_DISTRACTION_BY_ANYTHING,
use_group_distraction = false
}
queriesAndCommands.formCommand = {
command = queriesAndCommands.formGroupCommand,
unit_count = 0,
unit_search_distance = TRIPLE_CHUNK_SIZE
}
queriesAndCommands.formRetreatCommand = {
command = queriesAndCommands.compoundRetreatGroupCommand,
unit_count = 1,
unit_search_distance = CHUNK_SIZE
}
end
function upgrade.rebuildActivePlayerForces(universe)
universe.activePlayerForces = {}
universe.nonPlayerForces = {}
local forceIgnored
for _,force in pairs(game.forces) do
forceIgnored = false
if (force.name == "neutral") or (force.name == "enemy") then
forceIgnored = true
elseif game.forces["enemy"].is_friend(force) then
forceIgnored = true
end
if game.forces["enemy"].get_cease_fire(force) then
forceIgnored = true
end
if forceIgnored then
universe.nonPlayerForces[#universe.nonPlayerForces+1] = force.name
else
universe.activePlayerForces[#universe.activePlayerForces+1] = force.name
end
end
addCommandSet(universe)
end
function upgrade.attempt(universe)
local starting = global.version
if not global.version or global.version < 114 then
global.version = 114
if not universe then
universe = {}
global.universe = universe
end
game.forces.enemy.kill_all_units()
universe.safeEntities = {}
universe.aiPointsScaler = settings.global["rampantFixed--aiPointsScaler"].value
universe.aiPointsPrintGainsToChat = settings.global["rampantFixed--aiPointsPrintGainsToChat"].value
universe.aiPointsPrintSpendingToChat = settings.global["rampantFixed--aiPointsPrintSpendingToChat"].value
universe.aiNocturnalMode = settings.global["rampantFixed--permanentNocturnal"].value
universe.mapIterator = nil
universe.retreatThreshold = 0
universe.rallyThreshold = 0
universe.formSquadThreshold = 0
universe.attackWaveSize = 0
universe.attackWaveDeviation = 0
universe.attackWaveUpperBound = 0
universe.unitRefundAmount = 0
universe.regroupIndex = 1
game.map_settings.path_finder.min_steps_to_check_path_find_termination =
constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH
universe.evolutionTableAlignment = {}
universe.kamikazeThreshold = 0
universe.attackWaveLowerBound = 1
universe.expansion = game.map_settings.enemy_expansion.enabled
universe.expansionMaxDistance = game.map_settings.enemy_expansion.max_expansion_distance * CHUNK_SIZE
universe.expansionMaxDistanceDerivation = universe.expansionMaxDistance * 0.33
universe.expansionMinTime = game.map_settings.enemy_expansion.min_expansion_cooldown
universe.expansionMaxTime = game.map_settings.enemy_expansion.max_expansion_cooldown
universe.expansionMinSize = game.map_settings.enemy_expansion.settler_group_min_size
universe.expansionMaxSize = game.map_settings.enemy_expansion.settler_group_max_size
universe.settlerWaveDeviation = 0
universe.settlerWaveSize = 0
universe.enabledMigration = universe.expansion and settings.global["rampantFixed--enableMigration"].value
universe.peacefulAIToggle = settings.global["rampantFixed--peacefulAIToggle"].value
universe.printAIStateChanges = settings.global["rampantFixed--printAIStateChanges"].value
universe.debugTemperament = settings.global["rampantFixed--debugTemperament"].value
universe.enemyAlignmentLookup = {}
game.map_settings.unit_group.min_group_radius = constants.UNIT_GROUP_MAX_RADIUS * 0.5
game.map_settings.unit_group.max_group_radius = constants.UNIT_GROUP_MAX_RADIUS
game.map_settings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
game.map_settings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
game.map_settings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
game.map_settings.max_failed_behavior_count = 3
game.map_settings.unit_group.member_disown_distance = 10
game.map_settings.unit_group.tick_tolerance_when_member_arrives = 60
game.forces.enemy.ai_controllable = true
universe.evolutionLevel = game.forces.enemy.evolution_factor
global.pendingChunks = nil
global.natives = nil
global.map = nil
universe.builderCount = 0
universe.squadCount = 0
addCommandSet(universe)
end
if global.version < 116 then
global.version = 116
universe.maxPoints = 0
-- if (universe.maps) then
-- for _,map in pairs(universe.maps) do
-- for _,base in pairs(map.bases) do
-- base.damagedBy = {}
-- base.deathEvents = 0
-- end
-- end
-- end
--game.print("Rampant - Version 1.1.0, Rampant")
end
if global.version < 118 then
local BASE_DETECTION_PHEROMONE = constants.BASE_DETECTION_PHEROMONE
global.version = 118
addCommandSet(universe)
universe.retribution = 0
if universe.maps then
for _, map in pairs(universe.maps) do
-- local map = universe.maps[1]
------- add new map fields
-- map
if not map.chunkToPlayerBaseDetection then
map.chunkToPlayerBaseDetection = {}
end
if not map.chunkFactions then
map.chunkFactions = {}
end
if not map.chunkFactionCounts then
map.chunkFactionCounts = {}
end
if not map.chunkFactionCounts then
map.squadsGenerated = 0
end
-- chunk[BASE_DETECTION_PHEROMONE]
local BASE_DETECTION_PHEROMONE = constants.BASE_DETECTION_PHEROMONE
local chunksProcessed = 0
for x, nestsY in pairs(map) do
if (type(x) == "number") and (math.floor(x)==x) then
for y, chunk in pairs(nestsY) do
if not chunk[BASE_DETECTION_PHEROMONE] then
chunk[BASE_DETECTION_PHEROMONE] = 0
chunksProcessed = chunksProcessed + 1
end
end
end
end
if chunksProcessed>0 then
game.print("update, "..chunksProcessed.." chunks processed")
end
-- bases
local bases = map.chunkToBase
local basesProcessed = 0
for chunk, base in pairs(bases) do
if base and base.id and not base.chunkFactions then
base.chunkFactions = {}
if universe.evolutionLevel<0.15 then
base.tier = 1
elseif universe.evolutionLevel<0.30 then
base.tier = 2
elseif universe.evolutionLevel<0.50 then
base.tier = 3
elseif universe.evolutionLevel<0.75 then
base.tier = 5
elseif universe.evolutionLevel<0.90 then
base.tier = 8
else
base.tier = 10
end
base.tierHandicap = 0
newAlignment = {}
if not base.alignment[2] then
newAlignment[base.alignment[1]] = 1
else
newAlignment[base.alignment[1]] = 0.8
newAlignment[base.alignment[2]] = 0.2
end
base.alignment = newAlignment
basesProcessed = basesProcessed + 1
end
end
if basesProcessed>0 then
game.print("update, "..basesProcessed.." bases processed")
end
end
--game.print("Rampant fixed, Version 1.0.8")
end
end
if global.version < 119 then
global.version = 119
universe.retribution = 0
end
if global.version < 120 then
global.version = 120
if universe.maps then
local builderCount = 0
local squadCount = 0
for _, map in pairs(universe.maps) do
local squads = map.groupNumberToSquad
for groupNumber, squad in pairs(squads) do
--game.print(serpent.dump(groupNumber))
if squad.settlers then
builderCount = builderCount + 1
else
squadCount = squadCount + 1
end
end
end
universe.builderCount = builderCount
universe.squadCount = squadCount
end
--game.print("Rampant fixed, Version 1.0.13. Recaclulate active squads")
end
if global.version < 121 then
global.version = 121
addCommandSet(universe)
if universe.maps then
local mapsCounter = 0
local mapsToDelete = {}
local lastMap
local deleteMap = false
local squadsCleared = 0
for surfaceIndex, map in pairs(universe.maps) do
local surface = map.surface
deleteMap = constants.SURFACE_IGNORED(surface, universe)
if deleteMap then
mapsToDelete[#mapsToDelete+1] = surfaceIndex
end
end
for i = 1,#mapsToDelete do
local surfaceIndex = mapsToDelete[i]
local map = universe.maps[surfaceIndex]
--- squads check
local squads = map.groupNumberToSquad -- im sure, no nests, bases, squads in factory floor! But just in case, we'll check the squads..
local builderCount = 0
local squadCount = 0
for groupNumber, squad in pairs(squads) do
if squad.settlers then
builderCount = builderCount + 1
else
squadCount = squadCount + 1
end
if squad.group and squad.group.valid then
squad.group.destroy()
end
universe.builderCount = universe.builderCount - builderCount
universe.squadCount = universe.squadCount - squadCount
squadsCleared = squadsCleared + 1
end
-----
if universe.mapIterator == surfaceIndex then
universe.mapIterator = nil
end
universe.maps[surfaceIndex] = nil
mapsCounter = mapsCounter + 1
end
if mapsCounter>0 then
game.print("Rampant fixed, Version 1.0.14. Factorissimo surfaces are excluded:"..mapsCounter..", squads removed: "..squadsCleared)
end
end
end
if global.version < 122 then
--game.print("Rampant fixed, Version 1.0.18")
global.version = 122
universe.processActiveNest = {}
universe.processActiveNestIterator = nil
universe.pendingMutations = {
["chunks"] = {}, -- {x, y, surface.index}
["entities"] = {}
}
end
if global.version < 124 then -- Version 1.1
global.version = 124
universe.surfaceIgnoringSet = {}
universe.surfaceRemoteSettings = {}
universe.chunkToPassScan = {}
universe.pendingChunks = {}
if universe.maps then
local mapsCounter = 0
local mapsToDelete = {}
local lastMap
local deleteMap = false
local squadsCleared = 0
for surfaceIndex, map in pairs(universe.maps) do
local surface = map.surface
deleteMap = constants.SURFACE_IGNORED(surface, universe)
if deleteMap then
mapsToDelete[#mapsToDelete+1] = surfaceIndex
end
end
for i = 1,#mapsToDelete do
local surfaceIndex = mapsToDelete[i]
local map = universe.maps[surfaceIndex]
--- squads check
local squads = map.groupNumberToSquad
local builderCount = 0
local squadCount = 0
for groupNumber, squad in pairs(squads) do
if squad.settlers then
builderCount = builderCount + 1
else
squadCount = squadCount + 1
end
if squad.group and squad.group.valid then
squad.group.destroy()
end
universe.builderCount = universe.builderCount - builderCount
universe.squadCount = universe.squadCount - squadCount
squadsCleared = squadsCleared + 1
end
-----
if universe.mapIterator == surfaceIndex then
universe.mapIterator = nil
end
universe.maps[surfaceIndex] = nil
mapsCounter = mapsCounter + 1
end
if mapsCounter>0 then
game.print("Rampant fixed, Version 1.1.0 Surfaces excluded:"..mapsCounter..", squads removed: "..squadsCleared)
end
for surfaceIndex, map in pairs(universe.maps) do
for event,_ in pairs(map.pendingChunks) do
universe.pendingChunks[event] = true
end
map.pendingChunks = nil
for chunk,_ in pairs(map.chunkToPassScan) do
local chunkIndex = {chunk.x, chunk.y, map.surface.index}
universe.chunkToPassScan[chunkIndex] = true
end
end
end
end
if global.version < 126 then -- Version 1.1.1
global.version = 126
if universe.maps then
for surfaceIndex, map in pairs(universe.maps) do
map.vengenceLimiter = 0
end
end
end
if global.version < 127 then -- Version 1.1.6
global.version = 127
universe.aiDifficulty = settings.global["rampantFixed--aiDifficulty"].value
universe.finalSquadCost = 1
universe.finalVengenceSquadCost = 1
end
if global.version < 128 then -- Version 1.1.9
global.version = 128
if universe.maps then
for surfaceIndex, map in pairs(universe.maps) do
for i, base in pairs(map.bases) do
base.thisIsRampantEnemy = true
end
end
end
game.print({"description.rampantFixed--EnemySettings1_1_9"})
end
if global.version < 129 then -- Version 1.1.10
global.version = 129
if universe.NEW_ENEMIES then
game.print({"description.rampantFixed--EnemySettings1_1_10"})
end
end
if global.version < 131 then -- Version 1.1.11
global.version = 131
if universe.maps then
for surfaceIndex, map in pairs(universe.maps) do
map.chunkToPlayerTurrets = {}
end
end
end
if global.version < 135 then -- Version 1.2.0
global.version = 135
universe.attackWaveMaxSizeEvoPercent = settings.global["rampantFixed--attackWaveMaxSizeEvoPercent"].value
universe.chunkToPlayerCount = {}
universe.processActiveNestIterator = nil
universe.processActiveNest = {}
universe.decomressQueue = {}
if universe.maps then
for surfaceIndex, map in pairs(universe.maps) do
map.chunkToPlayerCount = nil
map.playerToChunk = nil
for chunk, value in pairs (map.chunkToDeathGenerator) do
if (value > - 1) and (value < 1) then
map.chunkToDeathGenerator[chunk] = nil
end
end
end
end
end
if global.version < 136 then -- Version 1.2.3
global.version = 136
upgrade.rebuildActivePlayerForces(universe)
universe.groupNumberToSquad = {}
if universe.maps then
for surfaceIndex, map in pairs(universe.maps) do
for groupNumber, squad in pairs(map.groupNumberToSquad) do
squad.map = map
if squad.settlers then
squad.disbandTick = game.tick + 72000
else
squad.disbandTick = game.tick + 18000
end
universe.groupNumberToSquad[squad.groupNumber] = squad
end
map.groupNumberToSquad = nil
map.squadIterator = nil
end
end
end
if global.version < 137 then -- Version 1.2.5
global.version = 137
universe.unitProtectionData = {}
-- if game.active_mods["space-exploration"] and game.active_mods["combat-mechanics-overhaul"] and game.active_mods["Krastorio2"] then
-- if not settings.startup["rampantFixed--useBlockableSteamAttacks"].value then
-- game.print({"description.rampantFixed--K2_SE_CMO_incompatibilityWarning"})
-- end
-- end
end
if global.version < 138 then -- Version 1.2.8
local BASE_DETECTION_PHEROMONE = constants.BASE_DETECTION_PHEROMONE
global.version = 138
if universe.maps and starting and settings.startup["rampantFixed--newEnemies"].value then
for surfaceIndex, map in pairs(universe.maps) do
local buildings = map.surface.find_entities_filtered({force = "enemy", type={"turret"}})
local buildingsTotal = #buildings
local rndNumber = 0
if buildingsTotal >= 70000 then
rndNumber = 0.95
elseif buildingsTotal >= 35000 then
rndNumber = 0.9
elseif buildingsTotal >= 15000 then
rndNumber = 0.6
end
if rndNumber > 0 then
local wormsDeleted = 0
for i=1,buildingsTotal do
local building = buildings[i]
if math.random() < rndNumber then
building.destroy()
wormsDeleted = wormsDeleted + 1
end
end
if wormsDeleted > 0 then
game.print("update 1.2.8: "..map.surface.name..":".. wormsDeleted.." worm(s) removed")
end
end
end
end
end
if global.version < 139 then -- Version 1.2.11
global.version = 139
universe.unitProtectionData.unitCurrentHP = {}
end
if global.version < 142 then -- Version 1.3
global.version = 142
universe.nonRampantCompressedSquads = {}
universe.bases = {}
universe.baseId = 1
universe.recycleBaseIterator = nil
universe.raiding_minimum_base_threshold = constants.RAIDING_MINIMUM_BASE_THRESHOLD
universe.no_pollution_attack_threshold = constants.NO_POLLUTION_ATTACK_THRESHOLD
universe.AI_MAX_SQUAD_COUNT = settings.global["rampantFixed--maxNumberOfSquads"].value
if universe.maps then
-- local chunkToBaseCleared = 0
local newId = 1
local basesList = {}
for _, map in pairs(universe.maps) do
local bases = map.chunkToBase
local basesProcessed = 0
local evoTier = 1
for tier = 10,1,-1 do
if universe.evoToTierMapping[tier] <= map.evolutionLevel then
evoTier = tier
break
end
end
for chunk, base in pairs(bases) do
if base and base.id then
-- local distance = ((base.x - chunk.x)^2 + (base.y - chunk.y)^2) ^ 0.5
if not basesList[base] then
basesList[base] = base.id
base.id = newId
base.mapIndex = map.surface.index
base.chunks = {}
base.state = BASE_AI_STATE_ACTIVE
if universe.NEW_ENEMIES and (not universe.ALLOW_OTHER_ENEMIES) then
if not base.thisIsRampantEnemy then
base.tier = math.max(evoTier - base.tierHandicap, 1)
base.thisIsRampantEnemy = true
end
end
newId = newId + 1
universe.bases[base.id] = base
end
--if distance <= 150 then
base.chunks[chunk] = true
-- else
-- chunkToBaseCleared = chunkToBaseCleared + 1
-- bases[chunk] = nil
-- end
end
end
map.bases = nil
map.baseIndex = nil
map.baseIncrement = nil
map.baseId = nil
map.recycleBaseIterator = nil
map.chunkFactions = nil
end
-- if chunkToBaseCleared > 0 then
-- game.print("chunkToBase links deleted:"..chunkToBaseCleared)
-- end
universe.baseId = newId
end
addCommandSet(universe)
end
if global.version < 143 then -- Version 1.4.0
global.version = 143
universe.oneTickImmunityUnits = {}
universe.compressedUnits = {}
local compressedUnits = universe.compressedUnits
for groupNumber, squad in pairs(universe.groupNumberToSquad) do
local group = squad.group
if group and squad.compressedMembers then
if squad.smoothCompressed then
local unitNumber
for _, entity in pairs(group.members) do
unitNumber = entity.unit_number
local compressData = squad.compressedMembers[unitNumber]
if compressData then
compressedUnits[unitNumber] = {count = compressData.count, textId = compressData.textId, entity = entity}
end
end
else
for _, entity in pairs(group.members) do
unitNumber = entity.unit_number
entityName = entity.name
local compressData = squad.compressedMembers[entityName]
if compressData then
compressedUnits[unitNumber] = {count = compressData.count, textId = compressData.textId, entity = entity}
squad.compressedMembers[entityName] = nil
end
end
end
squad.compressedMembers = nil
squad.compressed = true
end
end
end
if global.version < 144 then -- Version 1.4.2
global.version = 144
universe.protectedUnits = {}
end
if global.version < 150 then -- Version 1.5
global.version = 150
universe.undergroundSquads = {}
universe.undergroundAttackProbability = 0
end
if global.version < 152 then -- Version 1.5.2
global.version = 152
universe.undergroundAttack = settings.global["rampantFixed--undergroundAttack"].value
end
if global.version < 161 then -- Version 1.6.1
global.version = 161
for chunkIndex,_ in pairs(universe.chunkToPassScan) do
if chunkIndex and (type(attribute) == "table") then
local chunkIndexNew = "x"..chunkIndex[1].."y"..chunkIndex[2].."m"..chunkIndex[3]
local chunkData = {}
for i = 1, 3 do
chunkData[i] = chunkIndex[i]
end
universe.chunkToPassScan[chunkIndexNew] = chunkData
universe.chunkToPassScan[chunkIndex] = nil
end
end
universe.pendingMutations = {
["chunks"] = {}, -- {"x"..x.."y"..y.."m"..surface.index}
["entities"] = {}
}
universe.pendingMutationsIterator = nil
universe.externalControlValues = {}
end
if global.version < 164 then -- Version 1.6.4
global.version = 164
universe.evolveTick = 0
universe.lvlupTick = 0
end
if global.version < 170 then -- Version 1.7.0
global.version = 170
end
if global.version < 172 then -- Version 1.7.2
global.version = 172
universe.randomGenerator = nil
end
if global.version < 180 then -- Version 1.8.0
global.version = 180
universe.growingBases = {}
if universe.maps then
for _, map in pairs(universe.maps) do
map.basesToGrow = {}
end
end
end
if global.version < 183 then -- Version 1.8.3
global.version = 183
universe.debugSettings = {}
universe.allowExternalControl = true
end
return (starting ~= global.version) and global.version
end
function upgrade.compareTable(entities, option, new)
local changed = false
if (entities[option] ~= new) then
entities[option] = new
changed = true
end
return changed, new
end
return upgrade