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

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Dagothur 2021-05-01 07:52:57 -04:00
commit 722868f6bb
15 changed files with 161 additions and 18956 deletions

View File

@ -401,8 +401,22 @@ function upgrade.attempt(universe)
universe.squadCount = 0
addCommandSet(universe)
end
if global.version < 116 then
global.version = 116
game.print("Rampant - Version 1.0.8")
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.0.10")
end
return (starting ~= global.version) and global.version

View File

@ -1,3 +1,24 @@
---------------------------------------------------------------------------------------------------
Version: 1.0.10
Date: 29. 04. 2021
Contributions:
- Astorin removed old unused ru.cfg locale
Improvements:
- Increased ai baseline point accumulation based on temperament
Tweaks:
- Increased spitter and worm projectile size by 20%
- Decreased spitter and worm projectile speed by ~40%
- Increased baseline ai point accumulation for active nests by x3
- Increased baseline ai point accumulation at min and max temperament by 0.2
- Increased raid nest contribution to temperament by x2.7
- Increased siege chance at max ai temperament by 25%
- Decreased settler cost to ai by 33%
- Increased base ai min and max duration by ~x1.8
- Increased biter base point gain by x3.5
Bugfixes:
- Settlers not spawning as they should do to incorrect weighting on spawn locations
- Fixed new enemies factions not mutating or upgrading structures overtime
---------------------------------------------------------------------------------------------------
Version: 1.0.9
Date: 21. 04. 2021

39
control.lua Executable file → Normal file
View File

@ -343,7 +343,6 @@ local function prepMap(surface)
map.squads = nil
map.pendingAttack = nil
map.building = nil
map.groupNumberToSquad = {}
map.evolutionLevel = game.forces.enemy.evolution_factor
map.canAttackTick = 0
@ -414,8 +413,11 @@ local function onConfigChanged()
universe.buildingHiveTypeLookup["behemoth-worm-turret"] = "turret"
end
if version and (version <= 114) then
for _,surface in pairs(game.surfaces) do
for _,surface in pairs(game.surfaces) do
if not universe.maps then
universe.maps = {}
end
if not universe.maps[surface.index] then
prepMap(surface)
end
end
@ -473,6 +475,20 @@ local function onDeath(event)
if (entityType == "unit") then
if (chunk ~= -1) and event.force and (event.force.name ~= "enemy") then
-- local group = entity.unit_group
-- if group then
-- local damageType = event.damage_type
-- local squad = map.groupNumberToSquad[group.group_number]
-- if squad then
-- local base = squad.base
-- if base then
-- base.damagedBy[damageType] = (base.damagedBy[damageType] or 0) + 0.01
-- base.deathEvents = base.deathEvents + 1
-- end
-- end
-- end
-- drop death pheromone where unit died
deathScent(map, chunk)
@ -493,6 +509,7 @@ local function onDeath(event)
elseif event.force and (event.force.name ~= "enemy") and
((entityType == "unit-spawner") or (entityType == "turret"))
then
if (entityType == "unit-spawner") then
map.points = map.points + RECOVER_NEST_COST
if universe.aiPointsPrintGainsToChat then
@ -506,6 +523,7 @@ local function onDeath(event)
end
unregisterEnemyBaseStructure(map, entity)
unregisterEnemyBaseStructure(map, entity, event.damage_type)
if (chunk ~= -1) then
rallyUnits(chunk, map, tick)
@ -827,6 +845,13 @@ local function onUnitGroupCreated(event)
squad = createSquad(nil, nil, group, settler)
map.groupNumberToSquad[group.group_number] = squad
-- if universe.NEW_ENEMIES then
-- local chunk = getChunkByPosition(map, group.position)
-- if (chunk ~= -1) then
-- squad.base = findNearbyBase(map, chunk)
-- end
-- end
if settler then
universe.builderCount = universe.builderCount + 1
else
@ -857,6 +882,14 @@ local function onUnitGroupCreated(event)
squad = createSquad(nil, nil, group, settler)
map.groupNumberToSquad[group.group_number] = squad
-- if universe.NEW_ENEMIES then
-- local chunk = getChunkByPosition(group.position)
-- if (chunk ~= -1) then
-- squad.base = findNearbyBase(map, chunk)
-- end
-- end
if settler then
universe.builderCount = universe.builderCount + 1
else

View File

@ -1,7 +1,7 @@
{
"name" : "Rampant",
"factorio_version" : "1.1",
"version" : "1.0.9",
"version" : "1.0.10",
"title" : "Rampant",
"author" : "Veden",
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",

View File

@ -12,6 +12,7 @@ local unitGroupUtils = require("UnitGroupUtils")
local movementUtils = require("MovementUtils")
local mathUtils = require("MathUtils")
local config = require("__Rampant__/config")
local baseUtils = require("BaseUtils")
-- constants
@ -35,14 +36,14 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE
local RESOURCE_MINIMUM_FORMATION_DELTA = constants.RESOURCE_MINIMUM_FORMATION_DELTA
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
-- imported functions
local findNearbyBase = baseUtils.findNearbyBase
local randomTickEvent = mathUtils.randomTickEvent
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
@ -107,7 +108,7 @@ local function validSettlerLocation(map, chunk, neighborChunk)
local chunkResource = chunk[RESOURCE_PHEROMONE]
return (getPassable(map, neighborChunk) == CHUNK_ALL_DIRECTIONS) and
(getNestCount(map, neighborChunk) == 0) and
(neighborChunk[RESOURCE_PHEROMONE] >= (chunkResource * RESOURCE_MINIMUM_FORMATION_DELTA))
(neighborChunk[RESOURCE_PHEROMONE] >= chunkResource)
end
local function validUnitGroupLocation(map, neighborChunk)
@ -224,6 +225,9 @@ function aiAttackWave.formSettlers(map, chunk)
universe.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(universe.formCommand)
if (foundUnits > 0) then
-- if universe.NEW_ENEMIES then
-- squad.base = findNearbyBase(map, chunk)
-- end
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, universe)
universe.builderCount = universe.builderCount + 1
map.points = map.points - AI_SETTLER_COST
@ -271,6 +275,9 @@ function aiAttackWave.formVengenceSquad(map, chunk)
universe.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(universe.formCommand)
if (foundUnits > 0) then
-- if universe.NEW_ENEMIES then
-- squad.base = findNearbyBase(map, chunk)
-- end
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, universe)
map.groupNumberToSquad[squad.groupNumber] = squad
universe.squadCount = universe.squadCount + 1
@ -319,14 +326,17 @@ function aiAttackWave.formSquads(map, chunk, tick)
universe.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(universe.formCommand)
if (foundUnits > 0) then
-- if universe.NEW_ENEMIES then
-- squad.base = findNearbyBase(map, chunk)
-- end
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, universe)
map.points = map.points - AI_SQUAD_COST
universe.squadCount = universe.squadCount + 1
map.groupNumberToSquad[squad.groupNumber] = squad
if tick and (map.state == AI_STATE_AGGRESSIVE) then
map.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
if universe.aiPointsPrintSpendingToChat then
game.print(map.surface.name .. ": Points: -" .. AI_SQUAD_COST .. ". [Squad] Total: " .. string.format("%.2f", map.points) .. " [gps=" .. squadPosition.x .. "," .. squadPosition.y .. "]")

27
libs/AIPlanning.lua Executable file → Normal file
View File

@ -57,6 +57,7 @@ function aiPlanning.planning(map, evolution_factor, tick)
universe.evolutionLevel = evolution_factor
local maxPoints = mMax(AI_MAX_POINTS * evolution_factor, MINIMUM_AI_POINTS)
universe.maxPoints = maxPoints
if not universe.ranIncompatibleMessage and universe.newEnemies and
(game.active_mods["bobenemies"] or game.active_mods["Natural_Evolution_Enemies"]) then
@ -94,15 +95,25 @@ function aiPlanning.planning(map, evolution_factor, tick)
universe.unitRefundAmount = AI_UNIT_REFUND * evolution_factor
universe.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX)
local points = ((AI_POINT_GENERATOR_AMOUNT * mRandom()) + (map.activeNests * 0.001) +
(AI_POINT_GENERATOR_AMOUNT * mMax(evolution_factor ^ 2.5, 0.1))) * universe.aiPointsScaler
local points = ((AI_POINT_GENERATOR_AMOUNT * mRandom()) + (map.activeNests * 0.003) +
(AI_POINT_GENERATOR_AMOUNT * mMax(evolution_factor ^ 2.5, 0.1)))
if (map.temperament < 0.05) or (map.temperament > 0.95) then
points = points + 0.3
elseif (map.temperament < 0.25) or (map.temperament > 0.75) then
points = points + 0.2
elseif (map.temperament < 0.40) or (map.temperament > 0.60) then
points = points + 0.1
end
if (map.state == AI_STATE_ONSLAUGHT) then
points = points * 2
end
map.baseIncrement = points
points = points * universe.aiPointsScaler
map.baseIncrement = points * 3.5
local currentPoints = map.points
@ -232,7 +243,7 @@ function aiPlanning.planning(map, evolution_factor, tick)
end
else
if (universe.enabledMigration and universe.raidAIToggle) then
if (roll < 0.2) and universe.siegeAIToggle then
if (roll < 0.25) and universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
elseif (roll < 0.6) then
map.state = AI_STATE_RAIDING
@ -240,7 +251,7 @@ function aiPlanning.planning(map, evolution_factor, tick)
map.state = AI_STATE_ONSLAUGHT
end
elseif (universe.enabledMigration) then
if (roll < 0.2) and universe.siegeAIToggle then
if (roll < 0.25) and universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
else
map.state = AI_STATE_ONSLAUGHT
@ -316,10 +327,10 @@ function aiPlanning.temperamentPlanner(map)
end
if activeRaidNests > 0 then
local val = (0.000221 * activeRaidNests)
local val = (0.0006 * activeRaidNests)
delta = delta - val
else
delta = delta - 0.007232
delta = delta - 0.01
end
if lostEnemyUnits > 0 then

View File

@ -16,11 +16,7 @@ local FACTION_MUTATION_MAPPING = constants.FACTION_MUTATION_MAPPING
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
local BASE_AI_STATE_DORMANT = constants.BASE_AI_STATE_DORMANT
local BASE_AI_STATE_ACTIVE = constants.BASE_AI_STATE_ACTIVE
local BASE_AI_STATE_WORMS = constants.BASE_AI_STATE_WORMS
local BASE_AI_STATE_NESTS = constants.BASE_AI_STATE_NESTS
local BASE_AI_STATE_OVERDRIVE = constants.BASE_AI_STATE_OVERDRIVE
local BASE_AI_STATE_MUTATE = constants.BASE_AI_STATE_MUTATE
local FACTION_SET = constants.FACTION_SET
@ -28,9 +24,7 @@ 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_MIN_TEMPERAMENT_DURATION = constants.BASE_AI_MIN_TEMPERAMENT_DURATION
local BASE_AI_MAX_STATE_DURATION = constants.BASE_AI_MAX_STATE_DURATION
local BASE_AI_MAX_TEMPERAMENT_DURATION = constants.BASE_AI_MAX_TEMPERAMENT_DURATION
local BASE_UPGRADE = constants.BASE_UPGRADE
@ -104,6 +98,8 @@ function baseUtils.findNearbyBase(map, chunk)
end
end
-- print("base found", foundBase)
return foundBase
end
@ -338,7 +334,6 @@ end
function baseUtils.processBase(chunk, map, tick, base)
if not base.alignment[1] then
base.state = BASE_AI_STATE_DORMANT
return
end
@ -349,7 +344,10 @@ function baseUtils.processBase(chunk, map, tick, base)
point.x = chunk.x + (CHUNK_SIZE * mRandom())
point.y = chunk.y + (CHUNK_SIZE * mRandom())
if (base.state == BASE_AI_STATE_ACTIVE) then
local upgradeRoll = mRandom()
if ((base.state == BASE_AI_STATE_MUTATE) and (upgradeRoll < 0.02)) or
((base.state == BASE_AI_STATE_ACTIVE) and (upgradeRoll < 0.1))
then
local entities = surface.find_entities_filtered(universe.filteredEntitiesPointQueryLimited)
if #entities ~= 0 then
local entity = entities[1]
@ -363,44 +361,35 @@ function baseUtils.processBase(chunk, map, tick, base)
end
end
end
elseif (base.state == BASE_AI_STATE_MUTATE) then
end
-- if (base.deathEvents > 1000) then
if (upgradeRoll > 0.95) then
if (base.points >= BASE_UPGRADE) then
if upgradeBase(map, base) then
base.points = base.points - BASE_UPGRADE
end
end
end
-- base.damagedBy = {}
-- base.deathEvents = 0
-- end
if (base.state == BASE_AI_STATE_OVERDRIVE) then
base.points = base.points + (map.baseIncrement * 5)
elseif (base.state ~= BASE_AI_STATE_DORMANT) then
base.points = base.points + map.baseIncrement
base.points = base.points + map.baseIncrement
if (base.points > universe.maxPoints) then
base.points = universe.maxPoints
end
if (base.temperamentTick <= tick) then
base.temperament = mRandom()
base.temperamentTick = randomTickEvent(tick,
BASE_AI_MIN_TEMPERAMENT_DURATION,
BASE_AI_MAX_TEMPERAMENT_DURATION)
end
-- print("baseStats", base.points, base.state, base.deathEvents-- , serpent.dump(base.damagedBy)
-- )
if (base.stateTick <= tick) then
local roll = mRandom() * mMax(1 - map.evolutionLevel, 0.15)
if (roll > map.temperament) then
base.state = BASE_AI_STATE_DORMANT
local roll = mRandom()
if (roll < 0.85) then
base.state = BASE_AI_STATE_ACTIVE
else
roll = mRandom()
if (roll < 0.70) then
base.state = BASE_AI_STATE_ACTIVE
elseif (roll < 0.80) then
base.state = BASE_AI_STATE_NESTS
elseif (roll < 0.90) then
base.state = BASE_AI_STATE_WORMS
elseif (roll < 0.975) then
base.state = BASE_AI_STATE_OVERDRIVE
else
base.state = BASE_AI_STATE_MUTATE
end
base.state = BASE_AI_STATE_MUTATE
end
base.stateTick = randomTickEvent(tick,
BASE_AI_MIN_STATE_DURATION,
@ -443,11 +432,10 @@ function baseUtils.createBase(map, chunk, tick, rebuilding)
distanceThreshold = distanceThreshold,
tick = baseTick,
alignment = alignment,
state = BASE_AI_STATE_DORMANT,
state = BASE_AI_STATE_ACTIVE,
damagedBy = {},
stateTick = 0,
temperamentTick = 0,
createdTick = tick,
temperament = 0,
points = 0,
id = map.baseId
}

View File

@ -73,6 +73,7 @@ local createBase = baseUtils.createBase
local upgradeEntity = baseUtils.upgradeEntity
local getChunkBase = chunkPropertyUtils.getChunkBase
local setChunkBase = chunkPropertyUtils.setChunkBase
local setPassable = chunkPropertyUtils.setPassable
local setPathRating = chunkPropertyUtils.setPathRating
@ -469,7 +470,7 @@ function chunkUtils.registerEnemyBaseStructure(map, entity, base)
return entity
end
function chunkUtils.unregisterEnemyBaseStructure(map, entity)
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)
@ -520,6 +521,11 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity)
setNestActiveness(map, chunk, 0)
end
setFunc(map, chunk, 0)
-- local base = getChunkBase(map, chunk)
-- if base then
-- base.damagedBy[damageType] = (base.damagedBy[damageType] or 0) + 1
-- base.deathEvents = base.deathEvents + 1
-- end
if (getEnemyStructureCount(map, chunk) == 0) then
setChunkBase(map, chunk, nil)
end

View File

@ -121,7 +121,7 @@ constants.AI_SQUAD_COST = 175
constants.RECOVER_NEST_COST = constants.AI_SQUAD_COST
constants.RECOVER_WORM_COST = constants.AI_SQUAD_COST * 0.5
constants.AI_VENGENCE_SQUAD_COST = 45
constants.AI_SETTLER_COST = 400
constants.AI_SETTLER_COST = 300
constants.AI_BASE_BUILDING_COST = 500
constants.AI_TUNNEL_COST = 100
constants.AI_MAX_POINTS = 15500
@ -166,10 +166,8 @@ constants.AI_MAX_STATE_DURATION = 25
constants.AI_MIN_TEMPERAMENT_DURATION = 25
constants.AI_MAX_TEMPERAMENT_DURATION = 32
constants.BASE_AI_MIN_STATE_DURATION = 2
constants.BASE_AI_MAX_STATE_DURATION = 10
constants.BASE_AI_MIN_TEMPERAMENT_DURATION = 5
constants.BASE_AI_MAX_TEMPERAMENT_DURATION = 15
constants.BASE_AI_MIN_STATE_DURATION = 12
constants.BASE_AI_MAX_STATE_DURATION = 20
-- ai base

View File

@ -45,15 +45,6 @@ function mapUtils.getChunkByPosition(map, position)
return -1
end
function mapUtils.getChunkByUnalignedXY(map, x, y)
local chunkX = map[mFloor(x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE]
if chunkX then
local chunkY = mFloor(y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
return chunkX[chunkY] or -1
end
return -1
end
function mapUtils.positionToChunkXY(position)
local chunkX = mFloor(position.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
local chunkY = mFloor(position.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE

View File

@ -10,6 +10,7 @@ local mapUtils = require("MapUtils")
local unitGroupUtils = require("UnitGroupUtils")
local movementUtils = require("MovementUtils")
local chunkPropertyUtils = require("ChunkPropertyUtils")
local baseUtils = require("BaseUtils")
-- constants
@ -24,6 +25,8 @@ local COOLDOWN_RETREAT = constants.COOLDOWN_RETREAT
-- imported functions
local findNearbyBase = baseUtils.findNearbyBase
local addSquadToChunk = chunkPropertyUtils.addSquadToChunk
local positionFromDirectionAndFlat = mapUtils.positionFromDirectionAndFlat
@ -112,6 +115,9 @@ function aiDefense.retreatUnits(chunk, cause, map, tick, radius)
end
if created then
-- if universe.NEW_ENEMIES then
-- newSquad.base = findNearbyBase(map, chunk)
-- end
map.groupNumberToSquad[newSquad.groupNumber] = newSquad
universe.squadCount = universe.squadCount + 1
end

View File

@ -81,6 +81,7 @@ function unitGroupUtils.createSquad(position, surface, group, settlers)
status = SQUAD_GUARDING,
rabid = false,
penalties = {},
base = nil,
frenzy = false,
settlers = settlers or false,
kamikaze = false,

File diff suppressed because it is too large Load Diff

View File

@ -1067,7 +1067,7 @@ function biterFunctions.createProjectileAttack(attributes, projectile, animation
projectile_creation_distance = 0.6,
range = attributes.range or 20,
min_attack_distance = (attributes.range and (attributes.range - 2)) or 20,
lead_target_for_projectile_speed = 0.6,
lead_target_for_projectile_speed = 0.95,
use_shooter_direction = true,
ammo_type =
{

View File

@ -1,5 +1,6 @@
local projectileUtils = {}
function projectileUtils.makeProjectile(attributes, attack)
local n = attributes.name .. "-projectile-rampant"
@ -11,7 +12,8 @@ function projectileUtils.makeProjectile(attributes, attack)
collision_mask = attributes.attackCollisionMask or {"layer-13"},
direction_only = attributes.attackDirectionOnly,
piercing_damage = attributes.attackPiercingDamage or 0,
acceleration = attributes.attackAcceleration or 0.02,
acceleration = attributes.attackAcceleration or 0.000001,
max_speed = math.min(math.max(attributes.scale*0.60, 0.4), 0.7),
force_condition = (settings.startup["rampant--disableCollidingProjectiles"].value and "not-same") or nil,
action = attack,
animation =
@ -21,10 +23,10 @@ function projectileUtils.makeProjectile(attributes, attack)
width = 22,
height = 84,
frame_count = 15,
shift = util.mul_shift(util.by_pixel(-2, 30), attributes.scale or 1),
shift = util.mul_shift(util.by_pixel(-2, 30), attributes.scale*1.2 or 1),
tint = attributes.tint2,
priority = "high",
scale = (attributes.scale or 1),
scale = (attributes.scale*1.2 or 1),
animation_speed = 1,
hr_version =
{
@ -33,10 +35,10 @@ function projectileUtils.makeProjectile(attributes, attack)
width = 42,
height = 164,
frame_count = 15,
shift = util.mul_shift(util.by_pixel(-2, 31), attributes.scale or 1),
shift = util.mul_shift(util.by_pixel(-2, 31), attributes.scale*1.2 or 1),
tint = attributes.tint2,
priority = "high",
scale = 0.5 * (attributes.scale or 1),
scale = 0.5 * (attributes.scale*1.2 or 1),
animation_speed = 1,
}
},
@ -48,9 +50,9 @@ function projectileUtils.makeProjectile(attributes, attack)
height = 84,
frame_count = 15,
priority = "high",
shift = util.mul_shift(util.by_pixel(-2, 30), attributes.scale or 1),
shift = util.mul_shift(util.by_pixel(-2, 30), attributes.scale*1.2 or 1),
draw_as_shadow = true,
scale = (attributes.scale or 1),
scale = (attributes.scale*1.2 or 1),
animation_speed = 1,
hr_version =
{
@ -59,10 +61,10 @@ function projectileUtils.makeProjectile(attributes, attack)
width = 42,
height = 164,
frame_count = 15,
shift = util.mul_shift(util.by_pixel(-2, 31), attributes.scale or 1),
shift = util.mul_shift(util.by_pixel(-2, 31), attributes.scale*1.2 or 1),
draw_as_shadow = true,
priority = "high",
scale = 0.5 * (attributes.scale or 1),
scale = 0.5 * (attributes.scale*1.2 or 1),
animation_speed = 1,
}
},