2022-01-14 14:08:58 -08:00
-- Copyright (C) 2022 veden
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
2023-03-11 12:53:06 -08:00
if BaseUtilsG then
return BaseUtilsG
2019-02-15 20:17:30 -08:00
end
2023-03-11 12:53:06 -08:00
local BaseUtils = { }
--
local Universe
2017-05-07 23:56:11 -07:00
-- imports
2023-01-02 15:31:07 -08:00
local stringUtils = require ( " StringUtils " )
2017-06-15 18:30:26 -07:00
local mathUtils = require ( " MathUtils " )
2017-05-07 23:56:11 -07:00
local constants = require ( " Constants " )
2018-01-14 23:41:55 -08:00
local chunkPropertyUtils = require ( " ChunkPropertyUtils " )
2019-11-29 16:49:22 -08:00
local mapUtils = require ( " MapUtils " )
2021-12-11 10:42:49 -08:00
local queryUtils = require ( " QueryUtils " )
2017-06-07 17:57:24 -07:00
2017-05-07 23:56:11 -07:00
-- constants
2022-07-09 14:27:53 -07:00
local TIERS = constants.TIERS
2022-07-06 21:14:00 -07:00
local EVO_TO_TIER_MAPPING = constants.EVO_TO_TIER_MAPPING
local PROXY_ENTITY_LOOKUP = constants.PROXY_ENTITY_LOOKUP
local BUILDING_HIVE_TYPE_LOOKUP = constants.BUILDING_HIVE_TYPE_LOOKUP
local COST_LOOKUP = constants.COST_LOOKUP
local UPGRADE_LOOKUP = constants.UPGRADE_LOOKUP
local ENEMY_ALIGNMENT_LOOKUP = constants.ENEMY_ALIGNMENT_LOOKUP
local EVOLUTION_TABLE_ALIGNMENT = constants.EVOLUTION_TABLE_ALIGNMENT
local BUILDING_EVOLVE_LOOKUP = constants.BUILDING_EVOLVE_LOOKUP
2021-11-26 12:25:07 -08:00
local MINIMUM_BUILDING_COST = constants.MINIMUM_BUILDING_COST
2019-12-17 17:09:08 -08:00
local FACTION_MUTATION_MAPPING = constants.FACTION_MUTATION_MAPPING
2018-08-01 20:18:52 -07:00
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
2021-07-21 17:48:52 -07:00
local FACTIONS_BY_DAMAGE_TYPE = constants.FACTIONS_BY_DAMAGE_TYPE
2022-02-27 18:45:42 -08:00
local BASE_GENERATION_STATE_ACTIVE = constants.BASE_GENERATION_STATE_ACTIVE
2019-02-11 22:30:13 -08:00
2018-01-20 23:42:47 -08:00
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
2017-05-07 23:56:11 -07:00
2018-01-14 23:41:55 -08:00
local CHUNK_SIZE = constants.CHUNK_SIZE
2018-01-15 23:21:12 -08:00
2022-02-27 18:45:42 -08:00
local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
2017-05-07 23:56:11 -07:00
-- imported functions
2023-01-02 15:31:07 -08:00
local isMember = stringUtils.isMember
2021-12-11 10:42:49 -08:00
local setPositionXYInQuery = queryUtils.setPositionXYInQuery
2017-06-15 18:30:26 -07:00
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
2017-05-07 23:56:11 -07:00
2019-11-29 16:49:22 -08:00
local getChunkByPosition = mapUtils.getChunkByPosition
2018-01-28 17:51:24 -08:00
2021-12-05 15:33:24 -08:00
local gaussianRandomRangeRG = mathUtils.gaussianRandomRangeRG
2018-01-15 23:21:12 -08:00
2017-05-31 18:46:53 -07:00
local mFloor = math.floor
2023-01-16 12:28:40 -08:00
local tableRemove = table.remove
2018-01-20 23:42:47 -08:00
local mMin = math.min
local mMax = math.max
2020-05-19 19:37:16 -07:00
local next = next
2017-05-19 00:47:24 -07:00
-- module code
2017-05-07 23:56:11 -07:00
2023-03-11 12:53:06 -08:00
local function evoToTier ( evolutionFactor , maxSkips )
2019-11-29 16:49:22 -08:00
local v
2021-11-26 14:00:08 -08:00
local skipsRemaining = maxSkips
2022-07-09 14:27:53 -07:00
for i = TIERS , 1 , - 1 do
2022-07-06 21:14:00 -07:00
if EVO_TO_TIER_MAPPING [ i ] <= evolutionFactor then
2019-11-29 16:49:22 -08:00
v = i
2023-03-11 12:53:06 -08:00
if ( skipsRemaining == 0 ) or ( Universe.random ( ) <= 0.75 ) then
2019-11-29 16:49:22 -08:00
break
2019-03-11 23:03:26 -07:00
end
2021-11-26 14:00:08 -08:00
skipsRemaining = skipsRemaining - 1
2019-10-19 12:13:48 -07:00
end
2019-03-11 23:03:26 -07:00
end
2019-11-29 16:49:22 -08:00
return v
2018-08-01 20:18:52 -07:00
end
2023-03-11 12:53:06 -08:00
local function findBaseMutation ( targetEvolution , excludeFactions )
local tier = evoToTier ( targetEvolution or Universe.evolutionLevel , 2 )
2023-01-02 15:31:07 -08:00
local availableAlignments
2022-07-06 21:14:00 -07:00
local alignments = EVOLUTION_TABLE_ALIGNMENT [ tier ]
2019-02-02 22:01:28 -08:00
2023-01-02 15:31:07 -08:00
if excludeFactions then
availableAlignments = { }
for _ , alignment in pairs ( alignments ) do
if not isMember ( alignment [ 2 ] , excludeFactions ) then
availableAlignments [ # availableAlignments + 1 ] = alignment
end
end
else
availableAlignments = alignments
end
2023-03-11 12:53:06 -08:00
local roll = Universe.random ( )
2023-01-02 15:31:07 -08:00
for i = 1 , # availableAlignments do
local alignment = availableAlignments [ i ]
2018-02-10 12:57:54 -08:00
2019-11-29 16:49:22 -08:00
roll = roll - alignment [ 1 ]
2019-11-03 22:19:22 -08:00
2019-11-29 16:49:22 -08:00
if ( roll <= 0 ) then
return alignment [ 2 ]
end
2018-02-10 12:57:54 -08:00
end
2023-01-02 15:31:07 -08:00
return availableAlignments [ # availableAlignments ]
2019-11-29 16:49:22 -08:00
end
2019-02-02 22:01:28 -08:00
2022-01-16 12:05:34 -08:00
local function initialEntityUpgrade ( baseAlignment , tier , maxTier , map , useHiveType , entityType )
2019-11-29 16:49:22 -08:00
local entity
2019-12-15 17:16:56 -08:00
local useTier
2023-03-11 12:53:06 -08:00
local tierRoll = Universe.random ( )
2019-12-15 17:16:56 -08:00
if ( tierRoll < 0.4 ) then
useTier = maxTier
elseif ( tierRoll < 0.7 ) then
useTier = mMax ( maxTier - 1 , tier )
elseif ( tierRoll < 0.9 ) then
useTier = mMax ( maxTier - 2 , tier )
else
useTier = mMax ( maxTier - 3 , tier )
end
2022-07-06 21:14:00 -07:00
local alignmentTable = BUILDING_EVOLVE_LOOKUP [ baseAlignment ]
2022-10-20 22:29:12 -07:00
if not alignmentTable then
2023-01-02 15:31:07 -08:00
alignmentTable = BUILDING_EVOLVE_LOOKUP [ " neutral " ]
2022-10-20 22:29:12 -07:00
end
2021-12-14 20:28:16 -08:00
local upgrades = alignmentTable [ useTier ]
2019-12-15 17:16:56 -08:00
2022-10-20 22:29:12 -07:00
if alignmentTable and upgrades then
2019-12-15 17:16:56 -08:00
if useHiveType then
for ui = 1 , # upgrades do
local upgrade = upgrades [ ui ]
if upgrade [ 3 ] == useHiveType then
2023-03-11 12:53:06 -08:00
entity = upgrade [ 2 ] [ Universe.random ( # upgrade [ 2 ] ) ]
2019-12-15 17:16:56 -08:00
break
2019-03-11 23:03:26 -07:00
end
2019-12-15 17:16:56 -08:00
end
2020-05-23 20:47:14 -07:00
end
if not entity then
2019-12-15 17:16:56 -08:00
for ui = 1 , # upgrades do
local upgrade = upgrades [ ui ]
2022-01-16 12:05:34 -08:00
if upgrade [ 3 ] == entityType then
2023-03-11 12:53:06 -08:00
entity = upgrade [ 2 ] [ Universe.random ( # upgrade [ 2 ] ) ]
2022-01-16 12:05:34 -08:00
end
end
if not entity then
local mapTypes = FACTION_MUTATION_MAPPING [ entityType ]
for i = 1 , # mapTypes do
local mappedType = mapTypes [ i ]
for ui = 1 , # upgrades do
local upgrade = upgrades [ ui ]
if upgrade [ 3 ] == mappedType then
2023-03-11 12:53:06 -08:00
return upgrade [ 2 ] [ Universe.random ( # upgrade [ 2 ] ) ]
2022-01-16 12:05:34 -08:00
end
end
2019-03-11 23:03:26 -07:00
end
end
2019-11-03 22:19:22 -08:00
end
2019-11-29 16:49:22 -08:00
end
2019-12-15 17:16:56 -08:00
2019-11-29 16:49:22 -08:00
return entity
end
2021-02-19 23:31:36 -08:00
local function entityUpgrade ( baseAlignment , tier , maxTier , originalEntity , map )
2019-11-29 16:49:22 -08:00
local entity
2022-07-06 21:14:00 -07:00
local hiveType = BUILDING_HIVE_TYPE_LOOKUP [ originalEntity.name ]
2019-11-29 16:49:22 -08:00
2019-12-17 17:09:08 -08:00
for t = maxTier , tier , - 1 do
2022-07-06 21:14:00 -07:00
local factionLookup = UPGRADE_LOOKUP [ baseAlignment ] [ t ]
2019-12-17 17:09:08 -08:00
local upgrades = factionLookup [ hiveType ]
if not upgrades then
local mapTypes = FACTION_MUTATION_MAPPING [ hiveType ]
for i = 1 , # mapTypes do
local upgrade = factionLookup [ mapTypes [ i ] ]
if upgrade and ( # upgrade > 0 ) then
2023-03-11 12:53:06 -08:00
entity = upgrade [ Universe.random ( # upgrade ) ]
if Universe.random ( ) < 0.55 then
2019-12-17 17:09:08 -08:00
return entity
end
end
end
elseif ( # upgrades > 0 ) then
2023-03-11 12:53:06 -08:00
entity = upgrades [ Universe.random ( # upgrades ) ]
if Universe.random ( ) < 0.55 then
2020-05-23 20:47:14 -07:00
return entity
2019-03-11 23:03:26 -07:00
end
2019-11-03 22:19:22 -08:00
end
end
2018-01-25 16:52:26 -08:00
return entity
end
2023-03-11 12:53:06 -08:00
function BaseUtils . findEntityUpgrade ( baseAlignment , currentEvo , evoIndex , originalEntity , map , evolve )
2019-11-29 16:49:22 -08:00
local adjCurrentEvo = mMax (
2022-07-06 21:14:00 -07:00
( ( baseAlignment ~= ENEMY_ALIGNMENT_LOOKUP [ originalEntity.name ] ) and 0 ) or currentEvo ,
2019-11-29 16:49:22 -08:00
0
)
2023-03-11 12:53:06 -08:00
local tier = evoToTier ( adjCurrentEvo , 5 )
local maxTier = evoToTier ( evoIndex , 4 )
2018-01-25 16:52:26 -08:00
2019-11-29 16:49:22 -08:00
if ( tier > maxTier ) then
2021-12-04 11:04:13 -08:00
maxTier = tier
2019-11-29 16:49:22 -08:00
end
2019-12-15 17:16:56 -08:00
2019-11-29 16:49:22 -08:00
if evolve then
2021-02-19 23:31:36 -08:00
local chunk = getChunkByPosition ( map , originalEntity.position )
2022-01-16 16:51:43 -08:00
local entityName = originalEntity.name
2022-07-06 21:14:00 -07:00
local entityType = BUILDING_HIVE_TYPE_LOOKUP [ entityName ]
2022-01-16 12:05:34 -08:00
if not entityType then
2023-03-11 12:53:06 -08:00
if Universe.random ( ) < 0.5 then
2022-01-16 12:05:34 -08:00
entityType = " biter-spawner "
else
entityType = " spitter-spawner "
end
end
2023-03-11 12:53:06 -08:00
local roll = Universe.random ( )
2022-01-16 12:05:34 -08:00
local makeHive = ( chunk ~= - 1 ) and
2022-01-16 16:51:43 -08:00
(
( entityType == " biter-spawner " ) or ( entityType == " spitter-spawner " )
)
and
(
(
2022-06-12 22:34:49 -07:00
( roll <= 0.01 ) and
2022-07-06 21:14:00 -07:00
not PROXY_ENTITY_LOOKUP [ entityName ]
2022-01-16 16:51:43 -08:00
)
or
(
2022-06-12 22:34:49 -07:00
( roll <= 0.210 ) and
2023-03-11 17:21:22 -08:00
chunk.resourceGenerator
2022-01-16 16:51:43 -08:00
)
)
2022-01-16 12:05:34 -08:00
return initialEntityUpgrade ( baseAlignment , tier , maxTier , map , ( makeHive and " hive " ) , entityType )
2019-11-29 16:49:22 -08:00
else
2021-02-19 23:31:36 -08:00
return entityUpgrade ( baseAlignment , tier , maxTier , originalEntity , map )
2019-12-15 17:16:56 -08:00
end
2019-11-29 16:49:22 -08:00
end
2023-01-02 15:31:07 -08:00
-- local
2023-03-11 12:53:06 -08:00
function BaseUtils . findBaseInitialAlignment ( evoIndex , excludeFactions )
2021-11-26 14:09:10 -08:00
local dev = evoIndex * 0.15
2023-03-11 12:53:06 -08:00
local evoTop = gaussianRandomRangeRG ( evoIndex - ( evoIndex * 0.075 ) , dev , 0 , evoIndex , Universe.random )
2018-01-25 16:52:26 -08:00
2019-11-29 16:49:22 -08:00
local result
2023-03-11 12:53:06 -08:00
if Universe.random ( ) < 0.05 then
result = { findBaseMutation ( evoTop , excludeFactions ) , findBaseMutation ( evoTop , excludeFactions ) }
2019-11-29 16:49:22 -08:00
else
2023-03-11 12:53:06 -08:00
result = { findBaseMutation ( evoTop , excludeFactions ) }
2018-01-15 23:21:12 -08:00
end
2019-02-02 22:01:28 -08:00
2019-11-29 16:49:22 -08:00
return result
2018-01-15 23:21:12 -08:00
end
2023-03-11 12:53:06 -08:00
function BaseUtils . recycleBases ( )
local bases = Universe.bases
local id = Universe.recycleBaseIterator
2021-11-24 20:49:22 -08:00
local base
if not id then
id , base = next ( bases , nil )
else
base = bases [ id ]
end
2021-02-19 21:41:30 -08:00
if not id then
2023-03-11 12:53:06 -08:00
Universe.recycleBaseIterator = nil
2021-02-19 21:41:30 -08:00
else
2023-03-11 12:53:06 -08:00
Universe.recycleBaseIterator = next ( bases , id )
2022-04-09 19:24:15 -07:00
local map = base.map
if ( base.chunkCount == 0 ) or not map.surface . valid then
2021-02-19 21:41:30 -08:00
bases [ id ] = nil
2023-03-11 12:53:06 -08:00
if Universe.processBaseAIIterator == id then
Universe.processBaseAIIterator = nil
2022-04-29 20:18:50 -07:00
end
2022-04-09 19:24:15 -07:00
if map.surface . valid then
2023-03-11 12:53:06 -08:00
Universe.bases [ id ] = nil
2022-04-09 19:24:15 -07:00
end
2019-02-02 22:01:28 -08:00
end
2018-01-25 21:48:12 -08:00
end
end
2023-03-11 12:53:06 -08:00
function BaseUtils . queueUpgrade ( entity , base , disPos , evolve , register , timeDelay )
Universe.pendingUpgrades [ entity.unit_number ] = {
2023-01-02 13:24:18 -08:00
[ " position " ] = disPos ,
[ " register " ] = register ,
[ " evolve " ] = evolve ,
[ " base " ] = base ,
[ " entity " ] = entity ,
[ " delayTLL " ] = timeDelay
}
2019-02-11 22:30:13 -08:00
end
2023-03-11 12:53:06 -08:00
local function pickMutationFromDamageType ( damageType , roll , base )
2021-07-19 21:22:38 -07:00
local baseAlignment = base.alignment
2021-07-21 17:48:52 -07:00
local damageFactions = FACTIONS_BY_DAMAGE_TYPE [ damageType ]
2021-07-25 17:25:14 -07:00
local mutation
2022-12-26 17:43:41 -08:00
local mutated = false
2021-07-19 21:22:38 -07:00
2022-12-26 17:43:41 -08:00
if damageFactions and ( # damageFactions > 0 ) then
2023-03-11 12:53:06 -08:00
mutation = damageFactions [ Universe.random ( # damageFactions ) ]
2023-01-16 12:28:40 -08:00
if not isMember ( mutation , base.alignmentHistory ) then
if baseAlignment [ 2 ] then
if ( baseAlignment [ 1 ] ~= mutation ) and ( baseAlignment [ 2 ] ~= mutation ) then
mutated = true
if ( roll < 0.05 ) then
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 1 ]
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 2 ]
baseAlignment [ 1 ] = mutation
baseAlignment [ 2 ] = nil
elseif ( roll < 0.75 ) then
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 1 ]
baseAlignment [ 1 ] = mutation
else
baseAlignment [ 2 ] = mutation
end
end
elseif ( baseAlignment [ 1 ] ~= mutation ) then
2022-12-26 17:43:41 -08:00
mutated = true
2023-01-16 12:28:40 -08:00
if ( roll < 0.85 ) then
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 1 ]
baseAlignment [ 1 ] = mutation
else
baseAlignment [ 2 ] = mutation
end
2021-07-21 17:48:52 -07:00
end
end
2021-07-19 21:22:38 -07:00
else
2023-03-11 12:53:06 -08:00
mutation = findBaseMutation ( )
2023-01-16 12:28:40 -08:00
if not isMember ( mutation , base.alignmentHistory ) then
if baseAlignment [ 2 ] then
if ( baseAlignment [ 1 ] ~= mutation ) and ( baseAlignment [ 2 ] ~= mutation ) then
mutated = true
if ( roll < 0.05 ) then
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 1 ]
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 2 ]
baseAlignment [ 1 ] = mutation
baseAlignment [ 2 ] = nil
elseif ( roll < 0.75 ) then
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 1 ]
baseAlignment [ 1 ] = mutation
else
baseAlignment [ 2 ] = mutation
end
end
elseif ( baseAlignment [ 1 ] ~= mutation ) then
2022-12-26 17:43:41 -08:00
mutated = true
2023-01-16 12:28:40 -08:00
if ( roll < 0.85 ) then
base.alignmentHistory [ # base.alignmentHistory + 1 ] = baseAlignment [ 1 ]
base.alignment [ 1 ] = mutation
else
base.alignment [ 2 ] = mutation
end
2021-07-19 21:22:38 -07:00
end
end
end
2023-03-11 12:53:06 -08:00
if mutated and Universe.printBaseAdaptation then
2021-11-25 09:04:52 -08:00
if baseAlignment [ 2 ] then
2021-07-25 17:25:14 -07:00
game.print ( { " description.rampant--adaptation2DebugMessage " ,
2023-01-02 18:49:56 -08:00
base.id ,
base.map . surface.name ,
2021-07-25 17:25:14 -07:00
damageType ,
{ " description.rampant-- " .. baseAlignment [ 1 ] .. " EnemyName " } ,
{ " description.rampant-- " .. baseAlignment [ 2 ] .. " EnemyName " } ,
base.x ,
2021-11-25 09:04:52 -08:00
base.y ,
base.mutations ,
2023-03-11 12:53:06 -08:00
Universe.MAX_BASE_MUTATIONS } )
2021-07-25 17:25:14 -07:00
else
game.print ( { " description.rampant--adaptation1DebugMessage " ,
2023-01-02 18:49:56 -08:00
base.id ,
base.map . surface.name ,
2021-07-25 17:25:14 -07:00
damageType ,
{ " description.rampant-- " .. baseAlignment [ 1 ] .. " EnemyName " } ,
base.x ,
2021-11-25 09:04:52 -08:00
base.y ,
base.mutations ,
2023-03-11 12:53:06 -08:00
Universe.MAX_BASE_MUTATIONS } )
2021-07-25 17:25:14 -07:00
end
end
2023-01-16 12:28:40 -08:00
local alignmentCount = table_size ( base.alignmentHistory )
2023-03-11 12:53:06 -08:00
while ( alignmentCount > Universe.MAX_BASE_ALIGNMENT_HISTORY ) do
2023-01-16 12:28:40 -08:00
tableRemove ( base.alignmentHistory , 1 )
alignmentCount = alignmentCount - 1
end
2022-12-26 17:43:41 -08:00
return mutated
2021-07-19 21:22:38 -07:00
end
2023-03-11 12:53:06 -08:00
function BaseUtils . upgradeBaseBasedOnDamage ( base )
2021-07-19 21:22:38 -07:00
local total = 0
for _ , amount in pairs ( base.damagedBy ) do
total = total + amount
end
2021-07-24 18:20:13 -07:00
local mutationAmount = total * 0.176471
2021-11-25 09:13:43 -08:00
base.damagedBy [ " RandomMutation " ] = mutationAmount
2021-07-19 21:22:38 -07:00
total = total + mutationAmount
local pickedDamage
2023-03-11 12:53:06 -08:00
local roll = Universe.random ( )
2021-07-24 18:20:13 -07:00
for damageTypeName , amount in pairs ( base.damagedBy ) do
base.damagedBy [ damageTypeName ] = amount / total
end
2021-07-19 21:22:38 -07:00
for damageType , amount in pairs ( base.damagedBy ) do
2021-12-08 20:14:21 -08:00
roll = roll - amount
if ( roll <= 0 ) then
2021-07-19 21:22:38 -07:00
pickedDamage = damageType
break
end
end
2023-03-11 12:53:06 -08:00
return pickMutationFromDamageType ( pickedDamage , roll , base )
2021-07-19 21:22:38 -07:00
end
2023-03-11 12:53:06 -08:00
function BaseUtils . processBaseMutation ( chunk , map , base )
2022-03-19 16:29:12 -07:00
if not base.alignment [ 1 ] or
( base.stateGeneration ~= BASE_GENERATION_STATE_ACTIVE ) or
2023-03-11 12:53:06 -08:00
( Universe.random ( ) >= 0.30 )
2022-03-19 16:29:12 -07:00
then
2022-02-23 21:04:34 -08:00
return
end
2022-03-19 16:29:12 -07:00
if ( base.points >= MINIMUM_BUILDING_COST ) then
local surface = map.surface
2023-03-11 12:53:06 -08:00
setPositionXYInQuery ( Universe.pbFilteredEntitiesPointQueryLimited ,
chunk.x + ( CHUNK_SIZE * Universe.random ( ) ) ,
chunk.y + ( CHUNK_SIZE * Universe.random ( ) ) )
2019-11-03 22:19:22 -08:00
2023-03-11 12:53:06 -08:00
local entities = surface.find_entities_filtered ( Universe.pbFilteredEntitiesPointQueryLimited )
2021-02-20 15:31:48 -08:00
if # entities ~= 0 then
local entity = entities [ 1 ]
2022-07-06 21:14:00 -07:00
local cost = ( COST_LOOKUP [ entity.name ] or MAGIC_MAXIMUM_NUMBER )
2021-02-20 15:31:48 -08:00
if ( base.points >= cost ) then
2023-01-02 18:10:13 -08:00
local position = entity.position
2023-03-11 12:53:06 -08:00
BaseUtils.modifyBaseSpecialPoints ( base , - cost , " Scheduling Entity upgrade " , position.x , position.y )
BaseUtils.queueUpgrade ( entity , base , nil , false , true )
2019-11-29 16:49:22 -08:00
end
2019-02-02 22:01:28 -08:00
end
2021-04-30 21:25:55 -07:00
end
2018-01-20 23:42:47 -08:00
end
2023-03-11 12:53:06 -08:00
function BaseUtils . createBase ( map , chunk , tick )
2018-01-14 23:41:55 -08:00
local x = chunk.x
local y = chunk.y
local distance = euclideanDistancePoints ( x , y , 0 , 0 )
2018-01-15 23:21:12 -08:00
2019-11-29 16:49:22 -08:00
local meanLevel = mFloor ( distance * 0.005 )
2018-01-15 23:21:12 -08:00
2019-02-02 22:01:28 -08:00
local distanceIndex = mMin ( 1 , distance * BASE_DISTANCE_TO_EVO_INDEX )
2023-03-11 12:53:06 -08:00
local evoIndex = mMax ( distanceIndex , Universe.evolutionLevel )
2019-11-03 22:19:22 -08:00
2023-01-02 16:11:19 -08:00
local alignment =
2023-03-11 12:53:06 -08:00
( Universe.NEW_ENEMIES and BaseUtils.findBaseInitialAlignment ( evoIndex ) )
2023-01-02 16:11:19 -08:00
or { " neutral " }
2019-02-02 22:01:28 -08:00
2022-03-19 16:29:12 -07:00
local baseLevel = gaussianRandomRangeRG ( meanLevel ,
meanLevel * 0.3 ,
meanLevel * 0.50 ,
meanLevel * 1.50 ,
2023-03-11 12:53:06 -08:00
Universe.random )
2021-12-05 15:33:24 -08:00
local baseDistanceThreshold = gaussianRandomRangeRG ( BASE_DISTANCE_THRESHOLD ,
BASE_DISTANCE_THRESHOLD * 0.2 ,
BASE_DISTANCE_THRESHOLD * 0.75 ,
BASE_DISTANCE_THRESHOLD * 1.50 ,
2023-03-11 12:53:06 -08:00
Universe.random )
2018-01-25 21:13:47 -08:00
local distanceThreshold = ( baseLevel * BASE_DISTANCE_LEVEL_BONUS ) + baseDistanceThreshold
2017-05-11 21:50:06 -07:00
local base = {
2019-02-02 22:01:28 -08:00
x = x ,
y = y ,
2023-03-11 12:53:06 -08:00
distanceThreshold = distanceThreshold * Universe.baseDistanceModifier ,
2022-03-19 16:29:12 -07:00
tick = tick ,
2019-11-29 16:49:22 -08:00
alignment = alignment ,
2023-01-16 12:28:40 -08:00
alignmentHistory = { } ,
2021-04-29 22:24:14 -07:00
damagedBy = { } ,
2021-07-24 18:20:13 -07:00
deathEvents = 0 ,
2021-11-25 09:04:52 -08:00
mutations = 0 ,
2022-03-19 16:29:12 -07:00
stateGeneration = BASE_GENERATION_STATE_ACTIVE ,
2022-02-27 18:45:42 -08:00
stateGenerationTick = 0 ,
2021-12-04 11:04:13 -08:00
chunkCount = 0 ,
2019-03-09 14:47:35 -08:00
createdTick = tick ,
2020-05-19 19:37:16 -07:00
points = 0 ,
2022-02-23 21:04:34 -08:00
unitPoints = 0 ,
2022-02-27 18:45:42 -08:00
stateAI = BASE_AI_STATE_PEACEFUL ,
2022-03-19 16:29:12 -07:00
stateAITick = 0 ,
maxAggressiveGroups = 0 ,
sentAggressiveGroups = 0 ,
2022-10-26 10:55:00 -07:00
resetExpensionGroupsTick = 0 ,
maxExpansionGroups = 0 ,
sentExpansionGroups = 0 ,
2022-02-27 18:45:42 -08:00
activeRaidNests = 0 ,
activeNests = 0 ,
destroyPlayerBuildings = 0 ,
lostEnemyUnits = 0 ,
lostEnemyBuilding = 0 ,
rocketLaunched = 0 ,
builtEnemyBuilding = 0 ,
ionCannonBlasts = 0 ,
artilleryBlasts = 0 ,
2023-01-18 21:38:07 -08:00
resourceChunks = { } ,
resourceChunkCount = 0 ,
2022-02-27 18:45:42 -08:00
temperament = 0.5 ,
temperamentScore = 0 ,
2022-04-09 19:24:15 -07:00
map = map ,
2023-03-11 12:53:06 -08:00
id = Universe.baseId
2017-05-11 21:50:06 -07:00
}
2023-03-11 12:53:06 -08:00
Universe.baseId = Universe.baseId + 1
2018-01-14 23:41:55 -08:00
2021-02-19 23:31:36 -08:00
map.bases [ base.id ] = base
2023-03-11 12:53:06 -08:00
Universe.bases [ base.id ] = base
2019-02-02 22:01:28 -08:00
2017-05-11 21:50:06 -07:00
return base
2017-05-07 23:56:11 -07:00
end
2023-03-11 12:53:06 -08:00
function BaseUtils . modifyBaseUnitPoints ( base , points , tag , x , y )
2021-04-04 21:46:43 -07:00
2023-01-02 18:10:13 -08:00
if points > 0 and base.stateAI == BASE_AI_STATE_PEACEFUL then
return
end
tag = tag or " "
x = x or nil
y = y or nil
base.unitPoints = base.unitPoints + points
local overflowMessage = " "
2023-03-11 12:53:06 -08:00
if base.unitPoints > Universe.maxOverflowPoints then
base.unitPoints = Universe.maxOverflowPoints
2023-01-02 18:10:13 -08:00
overflowMessage = " [Point cap reached] "
end
local printPointChange = " "
2023-03-11 12:53:06 -08:00
if points > 0 and Universe.aiPointsPrintGainsToChat then
2023-01-02 18:10:13 -08:00
printPointChange = " + " .. string.format ( " %.2f " , points )
2023-03-11 12:53:06 -08:00
elseif points < 0 and Universe.aiPointsPrintSpendingToChat then
2023-01-02 18:10:13 -08:00
printPointChange = string.format ( " %.2f " , points )
end
if printPointChange ~= " " then
local gps = " "
if x ~= nil then
gps = " [gps= " .. x .. " , " .. y .. " ] "
2021-04-04 21:46:43 -07:00
end
2023-01-02 18:10:13 -08:00
game.print ( " [ " .. base.id .. " ]: " .. base.map . surface.name .. " " .. printPointChange .. " [ " .. tag .. " ] Unit Total: " .. string.format ( " %.2f " , base.unitPoints ) .. overflowMessage .. gps )
2021-04-04 21:46:43 -07:00
end
2018-01-20 23:42:47 -08:00
end
2023-03-11 12:53:06 -08:00
function BaseUtils . modifyBaseSpecialPoints ( base , points , tag , x , y )
2022-12-02 14:19:14 -05:00
if points > 0 and base.stateAI == BASE_AI_STATE_PEACEFUL then
return
end
2022-11-30 18:50:36 -05:00
tag = tag or " "
x = x or nil
y = y or nil
2023-01-02 18:10:13 -08:00
base.points = base.points + points
2022-11-30 18:50:36 -05:00
local overflowMessage = " "
2023-03-11 12:53:06 -08:00
if base.points > Universe.maxOverflowPoints then
base.points = Universe.maxOverflowPoints
2022-11-30 18:50:36 -05:00
overflowMessage = " [Point cap reached] "
end
local printPointChange = " "
2023-03-11 12:53:06 -08:00
if points > 0 and Universe.aiPointsPrintGainsToChat then
2022-11-30 18:50:36 -05:00
printPointChange = " + " .. string.format ( " %.2f " , points )
2023-03-11 12:53:06 -08:00
elseif points < 0 and Universe.aiPointsPrintSpendingToChat then
2022-11-30 18:50:36 -05:00
printPointChange = string.format ( " %.2f " , points )
end
2023-01-02 18:10:13 -08:00
2022-11-30 18:50:36 -05:00
if printPointChange ~= " " then
local gps = " "
if x ~= nil then
gps = " [gps= " .. x .. " , " .. y .. " ] "
end
2023-01-02 18:10:13 -08:00
game.print ( " [ " .. base.id .. " ]: " .. base.map . surface.name .. " " .. printPointChange .. " [ " .. tag .. " ] Special Total: " .. string.format ( " %.2f " , base.points ) .. overflowMessage .. gps )
2022-11-30 18:50:36 -05:00
end
end
2023-03-11 12:53:06 -08:00
function BaseUtils . init ( universe )
Universe = universe
end
BaseUtilsG = BaseUtils
return BaseUtils