From 8f111639314f34ff2aded481a8f86a6422970eac Mon Sep 17 00:00:00 2001 From: Aaron Veden Date: Wed, 26 Oct 2022 10:55:00 -0700 Subject: [PATCH] FACTO-215: Settler groups now follow the expansion map settings for time --- Upgrade.lua | 31 ++++++++++++++++++----------- changelog.txt | 1 + libs/AIAttackWave.lua | 38 +++++++++++++++++------------------- libs/AIPlanning.lua | 24 ++++++++++++++++------- libs/AIPredicates.lua | 45 +++++++++++++++++++++++++++++++++---------- libs/BaseUtils.lua | 5 +++-- libs/Constants.lua | 2 +- libs/MapProcessor.lua | 9 +++++---- libs/MathUtils.lua | 6 +++++- libs/SquadAttack.lua | 6 +++--- 10 files changed, 108 insertions(+), 59 deletions(-) diff --git a/Upgrade.lua b/Upgrade.lua index 25f8547..11f3ede 100644 --- a/Upgrade.lua +++ b/Upgrade.lua @@ -46,6 +46,8 @@ local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE local ENEMY_PHEROMONE = constants.ENEMY_PHEROMONE local CHUNK_TICK = constants.CHUNK_TICK +local TICKS_A_MINUTE = constants.TICKS_A_MINUTE + -- imported functions local sFind = string.find @@ -488,18 +490,7 @@ function upgrade.attempt(universe) 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.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.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 @@ -629,6 +620,24 @@ function upgrade.attempt(universe) local minDiffuse = game.map_settings.pollution.min_to_diffuse universe.pollutionDiffuseMinimum = minDiffuse * 0.75 + universe.expansion = game.map_settings.enemy_expansion.enabled + universe.expansionMaxDistance = game.map_settings.enemy_expansion.max_expansion_distance * CHUNK_SIZE + universe.expansionMinTime = game.map_settings.enemy_expansion.min_expansion_cooldown * TICKS_A_MINUTE + universe.expansionMaxTime = game.map_settings.enemy_expansion.max_expansion_cooldown * TICKS_A_MINUTE + universe.expansionMinSize = game.map_settings.enemy_expansion.settler_group_min_size + universe.expansionMaxSize = game.map_settings.enemy_expansion.settler_group_max_size + + 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 + + for _,base in pairs(universe.bases) do + base.maxExpansionGroups = 0 + base.sentExpansionGroups = 0 + base.resetExpensionGroupsTick = 0 + end + game.print("Rampant - Version 3.2.0") end diff --git a/changelog.txt b/changelog.txt index 920a5fa..b0c40ce 100644 --- a/changelog.txt +++ b/changelog.txt @@ -11,6 +11,7 @@ Version: 3.2.0 - script_raised_built now looks for enemy faction and registers as needed - Fixed worm range scaler setting not adjusting prepareRange so worms could shoot without being out of the ground. (Thanks Garrotte) - When a faction is removed during play alignment table will default to the neutral faction to prevent alignment table being nil + - Fixed settler groups not respecting expansion map setting for min and max time Optimizations: - Moved most constants out of global - Removed new enemy variations setting diff --git a/libs/AIAttackWave.lua b/libs/AIAttackWave.lua index 9a6c247..420b3fa 100644 --- a/libs/AIAttackWave.lua +++ b/libs/AIAttackWave.lua @@ -210,9 +210,10 @@ end function aiAttackWave.formSettlers(map, chunk, base) local universe = map.universe - if (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) and - (map.random() < universe.formSquadThreshold) and - ((base.unitPoints - AI_SETTLER_COST) > 0) + if (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) + and (base.sentExpansionGroups < base.maxExpansionGroups) + and ((base.unitPoints - AI_SETTLER_COST) > 0) + and (map.random() < universe.formSquadThreshold) then local surface = map.surface local squadPath, squadDirection @@ -245,9 +246,7 @@ function aiAttackWave.formSettlers(map, chunk, base) universe.formCommand.unit_count = scaledWaveSize local foundUnits = surface.set_multi_command(universe.formCommand) if (foundUnits > 0) then - if (base.stateAI == BASE_AI_STATE_SIEGE) then - base.sentSiegeGroups = base.sentSiegeGroups + 1 - end + base.sentExpansionGroups = base.sentExpansionGroups + 1 squad.base = base local kamikazeThreshold = calculateKamikazeSettlerThreshold(foundUnits, universe) @@ -276,9 +275,9 @@ end function aiAttackWave.formVengenceSquad(map, chunk, base) local universe = map.universe - if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) and - (map.random() < universe.formSquadThreshold) and - ((base.unitPoints - AI_VENGENCE_SQUAD_COST) > 0) + if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) + and ((base.unitPoints - AI_VENGENCE_SQUAD_COST) > 0) + and (map.random() < universe.formSquadThreshold) then local surface = map.surface local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), @@ -324,9 +323,10 @@ end function aiAttackWave.formVengenceSettler(map, chunk, base) local universe = map.universe - if (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) and - (map.random() < universe.formSquadThreshold) and - ((base.unitPoints - AI_VENGENCE_SQUAD_COST) > 0) + if (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) + and (base.sentExpansionGroups < base.maxExpansionGroups) + and ((base.unitPoints - AI_VENGENCE_SQUAD_COST) > 0) + and (map.random() < universe.formSquadThreshold) then local surface = map.surface local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), @@ -351,6 +351,8 @@ function aiAttackWave.formVengenceSettler(map, chunk, base) universe.formCommand.unit_count = scaledWaveSize local foundUnits = surface.set_multi_command(universe.formCommand) if (foundUnits > 0) then + base.sentExpansionGroups = base.sentExpansionGroups + 1 + squad.base = base squad.kamikaze = map.random() < calculateKamikazeSettlerThreshold(foundUnits, universe) universe.groupNumberToSquad[squad.groupNumber] = squad @@ -372,10 +374,10 @@ end function aiAttackWave.formSquads(map, chunk, base) local universe = map.universe - if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) and - attackWaveValidCandidate(chunk, map, base) and - (map.random() < universe.formSquadThreshold) and - ((base.unitPoints - AI_SQUAD_COST) > 0) + if (universe.squadCount < universe.AI_MAX_SQUAD_COUNT) + and attackWaveValidCandidate(chunk, map, base) + and ((base.unitPoints - AI_SQUAD_COST) > 0) + and (map.random() < universe.formSquadThreshold) then local surface = map.surface local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), @@ -400,10 +402,6 @@ function aiAttackWave.formSquads(map, chunk, base) universe.formCommand.unit_count = scaledWaveSize local foundUnits = surface.set_multi_command(universe.formCommand) if (foundUnits > 0) then - if (base.stateAI == BASE_AI_STATE_SIEGE) then - base.sentSiegeGroups = 0 - end - squad.base = base squad.kamikaze = map.random() < calculateKamikazeSquadThreshold(foundUnits, universe) base.unitPoints = base.unitPoints - AI_SQUAD_COST diff --git a/libs/AIPlanning.lua b/libs/AIPlanning.lua index 7ef70ee..3e4d383 100644 --- a/libs/AIPlanning.lua +++ b/libs/AIPlanning.lua @@ -53,7 +53,7 @@ local RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX = constants.RETREAT_MOVEMENT_PHEROMON local MINIMUM_AI_POINTS = constants.MINIMUM_AI_POINTS local ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS = constants.ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS -local ALL_NESTS_PER_SIEGE_GROUPS = constants.ALL_NESTS_PER_SIEGE_GROUPS +local ALL_NESTS_PER_EXPANSION_GROUPS = constants.ALL_NESTS_PER_EXPANSION_GROUPS local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE @@ -70,6 +70,7 @@ local BASE_AI_MAX_STATE_DURATION = constants.BASE_AI_MAX_STATE_DURATION -- imported functions local randomTickEvent = mathUtils.randomTickEvent +local randomTickDuration = mathUtils.randomTickDuration local upgradeBaseBasedOnDamage = baseUtils.upgradeBaseBasedOnDamage @@ -125,9 +126,11 @@ function aiPlanning.planning(universe, evolutionLevel) universe.expansionMaxSize) universe.settlerWaveDeviation = (universe.settlerWaveSize * 0.33) - universe.settlerCooldown = mFloor(linearInterpolation(evolutionLevel ^ 1.66667, - universe.expansionMaxTime, - universe.expansionMinTime)) + universe.settlerCooldown = randomTickDuration(universe.random, + universe.expansionMinTime, + mFloor(linearInterpolation(evolutionLevel ^ 1.66667, + universe.expansionMaxTime, + universe.expansionMinTime))) universe.unitRefundAmount = AI_UNIT_REFUND * evolutionLevel universe.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolutionLevel * NO_RETREAT_EVOLUTION_BONUS_MAX) @@ -136,7 +139,14 @@ end local function processBase(universe, base, tick) base.maxAggressiveGroups = mCeil(base.activeNests / ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS) - base.maxSiegeGroups = mCeil((base.activeNests + base.activeRaidNests) / ALL_NESTS_PER_SIEGE_GROUPS) + base.maxExpansionGroups = mCeil((base.activeNests + base.activeRaidNests) / ALL_NESTS_PER_EXPANSION_GROUPS) + + if (base.stateAI == BASE_AI_STATE_MIGRATING or base.stateAI == BASE_AI_STATE_SIEGE) + and base.resetExpensionGroupsTick <= tick + then + base.resetExpensionGroupsTick = tick + universe.settlerCooldown + base.sentExpansionGroups = 0 + end local points = (AI_POINT_GENERATOR_AMOUNT * universe.random()) + (base.activeNests * 0.144) + @@ -352,8 +362,8 @@ local function temperamentPlanner(base, evolutionLevel) base.map.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.stateGeneration .. ", sS:" - .. base.sentSiegeGroups .. ", mS:" .. base.maxSiegeGroups + ", mAgg:" .. base.maxAggressiveGroups .. ", baseState:" .. base.stateGeneration .. ", sE:" + .. base.sentExpansionGroups .. ", mE:" .. base.maxExpansionGroups game.print(strConsole) print(strConsole) end diff --git a/libs/AIPredicates.lua b/libs/AIPredicates.lua index 895aa14..337587e 100644 --- a/libs/AIPredicates.lua +++ b/libs/AIPredicates.lua @@ -36,24 +36,49 @@ local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT -- module code function aiPredicates.canAttack(map, base) + local universe = map.universe + local isAggressive = ((base.stateAI == BASE_AI_STATE_AGGRESSIVE) + and (base.sentAggressiveGroups < base.maxAggressiveGroups)) + local isRaiding = (base.stateAI == BASE_AI_STATE_RAIDING) + local isOnslaught = (base.stateAI == BASE_AI_STATE_ONSLAUGHT) + local isRaidSieging = universe.raidAIToggle + and (base.stateAI == BASE_AI_STATE_SIEGE) + and (base.sentExpansionGroups >= base.maxExpansionGroups) + local goodAI = isAggressive or isRaiding or isOnslaught or isRaidSieging + if not goodAI then + return false + end local surface = map.surface - 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))) - local notPeaceful = not surface.peaceful_mode - local nocturalMode = map.universe.aiNocturnalMode + if surface.peaceful_mode then + return false + end + local nocturalMode = universe.aiNocturnalMode local noctural = (not nocturalMode) or (nocturalMode and surface.darkness > 0.65) - return goodAI and notPeaceful and noctural + if not noctural then + return false + end + return true end function aiPredicates.canMigrate(map, base) - local surface = map.surface + local badAIState = (base.stateAI ~= BASE_AI_STATE_MIGRATING) and (base.stateAI ~= BASE_AI_STATE_SIEGE) + if badAIState then + return false + end local universe = map.universe + if not universe.expansion then + return false + end + local surface = map.surface + if surface.peaceful_mode then + return false + end local nocturalMode = universe.aiNocturnalMode - local goodAI = (base.stateAI == BASE_AI_STATE_MIGRATING) or (base.stateAI == BASE_AI_STATE_SIEGE) local noctural = (not nocturalMode) or (nocturalMode and surface.darkness > 0.65) - return goodAI and universe.expansion and not surface.peaceful_mode and noctural + if not noctural then + return false + end + return true end aiPredicatesG = aiPredicates diff --git a/libs/BaseUtils.lua b/libs/BaseUtils.lua index 0478006..6c6d812 100644 --- a/libs/BaseUtils.lua +++ b/libs/BaseUtils.lua @@ -501,8 +501,9 @@ function baseUtils.createBase(map, chunk, tick) stateAITick = 0, maxAggressiveGroups = 0, sentAggressiveGroups = 0, - maxSiegeGroups = 0, - sentSiegeGroups = 0, + resetExpensionGroupsTick = 0, + maxExpansionGroups = 0, + sentExpansionGroups = 0, activeRaidNests = 0, activeNests = 0, destroyPlayerBuildings = 0, diff --git a/libs/Constants.lua b/libs/Constants.lua index 02b146f..0743058 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -163,7 +163,7 @@ constants.BASE_GENERATION_STATE_ACTIVE = 1 -- constants.BASE_AI_STATE_MUTATE = 3 constants.ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS = 30 -constants.ALL_NESTS_PER_SIEGE_GROUPS = 150 +constants.ALL_NESTS_PER_EXPANSION_GROUPS = 150 constants.AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION = 0.5 constants.AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION = 3 diff --git a/libs/MapProcessor.lua b/libs/MapProcessor.lua index 967ef9f..5d24a3b 100644 --- a/libs/MapProcessor.lua +++ b/libs/MapProcessor.lua @@ -452,11 +452,12 @@ function mapProcessor.processVengence(universe) if not map.surface.valid then return end - local chunk = getChunkById(vengencePack.map, chunkId) - if universe.enabledMigration and (universe.random() < 0.075) then - formVengenceSettler(map, chunk, vengencePack.base) + local chunk = getChunkById(map, chunkId) + local base = vengencePack.base + if canMigrate(map, base) and (universe.random() < 0.075) then + formVengenceSettler(map, chunk, base) else - formVengenceSquad(map, chunk, vengencePack.base) + formVengenceSquad(map, chunk, base) end end end diff --git a/libs/MathUtils.lua b/libs/MathUtils.lua index a63545b..42d0524 100644 --- a/libs/MathUtils.lua +++ b/libs/MathUtils.lua @@ -45,9 +45,13 @@ function mathUtils.roundToNearest(number, multiple) end function mathUtils.randomTickEvent(rg, tick, low, high) + return tick + mathUtils.randomTickDuration(rg, low, high) +end + +function mathUtils.randomTickDuration(rg, low, high) local range = high - low local minutesToTick = (range * rg()) + low - return tick + mathUtils.roundToNearest(TICKS_A_MINUTE * minutesToTick, 1) + return mathUtils.roundToNearest(TICKS_A_MINUTE * minutesToTick, 1) end function mathUtils.distort(xorRandom, num, stdDev, min, max) diff --git a/libs/SquadAttack.lua b/libs/SquadAttack.lua index b0125b7..3eba957 100644 --- a/libs/SquadAttack.lua +++ b/libs/SquadAttack.lua @@ -442,6 +442,9 @@ function squadAttack.cleanSquads(universe, tick) end else universe.squadCount = universe.squadCount - 1 + if universe.squadCount < 0 then + universe.squadCount = 0 + end if squad.type == BASE_AI_STATE_AGGRESSIVE then local base = squad.base base.sentAggressiveGroups = base.sentAggressiveGroups - 1 @@ -449,9 +452,6 @@ function squadAttack.cleanSquads(universe, tick) base.sentAggressiveGroups = 0 end end - if universe.squadCount < 0 then - universe.squadCount = 0 - end end squads[groupId] = nil elseif (group.state == 4) then