mirror of
https://github.com/veden/Rampant.git
synced 2025-09-16 09:16:43 +02:00
Stable merged with ai toggle
This commit is contained in:
@@ -55,6 +55,11 @@ Configure Options not in game menu:
|
|||||||
|
|
||||||
# Version History
|
# Version History
|
||||||
|
|
||||||
|
0.15.11 -
|
||||||
|
- Tweak: Increased rally cry chance from 0.02(@100 evo) to 0.08(@100 evo) compensate for the once per logic cycle per chunk
|
||||||
|
- Improvement: Added negative score contribution to nest causing biters to move around nests instead of through
|
||||||
|
- Improvement: Increased player pheromone for weight multipler from 25 to 50 for hunting parties
|
||||||
|
|
||||||
0.15.10 -
|
0.15.10 -
|
||||||
- Fix: nil chunk in pheromone utils(https://mods.factorio.com/mods/Veden/Rampant/discussion/13806)
|
- Fix: nil chunk in pheromone utils(https://mods.factorio.com/mods/Veden/Rampant/discussion/13806)
|
||||||
- Tweak: Increased failed behaviors before dispanding from 3 to 6
|
- Tweak: Increased failed behaviors before dispanding from 3 to 6
|
||||||
|
23
Upgrade.lua
23
Upgrade.lua
@@ -10,8 +10,6 @@ local mathUtils = require("libs/MathUtils")
|
|||||||
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
||||||
local INTERVAL_PROCESS = constants.INTERVAL_PROCESS
|
local INTERVAL_PROCESS = constants.INTERVAL_PROCESS
|
||||||
|
|
||||||
local MAX_RALLY_CRIES = constants.MAX_RALLY_CRIES
|
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
local roundToNearest = mathUtils.roundToNearest
|
local roundToNearest = mathUtils.roundToNearest
|
||||||
@@ -80,7 +78,6 @@ function upgrade.attempt(natives, regionMap)
|
|||||||
global.version = constants.VERSION_16
|
global.version = constants.VERSION_16
|
||||||
end
|
end
|
||||||
if (global.version < constants.VERSION_18) then
|
if (global.version < constants.VERSION_18) then
|
||||||
print(global.version)
|
|
||||||
|
|
||||||
natives.safeEntities = {}
|
natives.safeEntities = {}
|
||||||
natives.safeEntityName = {}
|
natives.safeEntityName = {}
|
||||||
@@ -132,20 +129,18 @@ function upgrade.attempt(natives, regionMap)
|
|||||||
game.surfaces[1].print("Rampant - Version 0.15.10")
|
game.surfaces[1].print("Rampant - Version 0.15.10")
|
||||||
global.version = constants.VERSION_22
|
global.version = constants.VERSION_22
|
||||||
end
|
end
|
||||||
if (global.version < constants.VERSION_22) then
|
if (global.version < constants.VERSION_23) then
|
||||||
|
|
||||||
natives.bases = {}
|
|
||||||
|
|
||||||
natives.baseDistanceMin = 0
|
|
||||||
|
|
||||||
natives.baseIndex = 1
|
|
||||||
|
|
||||||
natives.randomGenerator = game.create_random_generator()
|
|
||||||
|
|
||||||
game.forces.enemy.ai_controllable = false
|
game.forces.enemy.ai_controllable = false
|
||||||
|
|
||||||
game.surfaces[1].print("Rampant - Version 0.15.10")
|
natives.useCustomAI = settings.startup["rampant-useCustomAI"].value
|
||||||
global.version = constants.VERSION_22
|
natives.bases = {}
|
||||||
|
natives.baseDistanceMin = 0
|
||||||
|
natives.baseIndex = 1
|
||||||
|
natives.randomGenerator = game.create_random_generator()
|
||||||
|
|
||||||
|
game.surfaces[1].print("Rampant - Version 0.15.11")
|
||||||
|
global.version = constants.VERSION_23
|
||||||
end
|
end
|
||||||
return starting ~= global.version
|
return starting ~= global.version
|
||||||
end
|
end
|
||||||
|
78
control.lua
78
control.lua
@@ -15,6 +15,7 @@ local aiPlanning = require("libs/AIPlanning")
|
|||||||
local interop = require("libs/Interop")
|
local interop = require("libs/Interop")
|
||||||
local tests = require("tests")
|
local tests = require("tests")
|
||||||
local upgrade = require("Upgrade")
|
local upgrade = require("Upgrade")
|
||||||
|
local baseUtils = require("libs/BaseUtils")
|
||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
@@ -55,8 +56,8 @@ local squadBeginAttack = aiAttack.squadBeginAttack
|
|||||||
local retreatUnits = aiDefense.retreatUnits
|
local retreatUnits = aiDefense.retreatUnits
|
||||||
|
|
||||||
local addRemovePlayerEntity = entityUtils.addRemovePlayerEntity
|
local addRemovePlayerEntity = entityUtils.addRemovePlayerEntity
|
||||||
local removeEnemyBase = entityUtils.removeEnemyBase
|
local unregisterEnemyBaseStructure = baseUtils.unregisterEnemyBaseStructure
|
||||||
--local makeImmortalEntity = entityUtils.makeImmortalEntity
|
local makeImmortalEntity = entityUtils.makeImmortalEntity
|
||||||
|
|
||||||
local processBases = baseProcessor.processBases
|
local processBases = baseProcessor.processBases
|
||||||
|
|
||||||
@@ -82,10 +83,31 @@ local function onChunkGenerated(event)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function reprocessChunks()
|
||||||
|
game.surfaces[1].print("Rampant - Reindexing chunks, please wait")
|
||||||
|
-- clear old regionMap processing Queue
|
||||||
|
-- prevents queue adding duplicate chunks
|
||||||
|
-- chunks are by key, so should overwrite old
|
||||||
|
regionMap.processQueue = {}
|
||||||
|
regionMap.processPointer = 1
|
||||||
|
regionMap.scanPointer = 1
|
||||||
|
-- clear pending chunks, will be added when loop runs below
|
||||||
|
pendingChunks = {}
|
||||||
|
|
||||||
|
-- queue all current chunks that wont be generated during play
|
||||||
|
local surface = game.surfaces[1]
|
||||||
|
for chunk in surface.get_chunks() do
|
||||||
|
onChunkGenerated({ tick = game.tick,
|
||||||
|
surface = surface,
|
||||||
|
area = { left_top = { x = chunk.x * 32,
|
||||||
|
y = chunk.y * 32 }}})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function onModSettingsChange(event)
|
local function onModSettingsChange(event)
|
||||||
|
|
||||||
if event and (string.sub(event.setting, 1, 7) ~= "rampant") then
|
if event and (string.sub(event.setting, 1, 7) ~= "rampant") then
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
natives.safeBuildings = settings.global["rampant-safeBuildings"].value
|
natives.safeBuildings = settings.global["rampant-safeBuildings"].value
|
||||||
@@ -112,31 +134,21 @@ local function onModSettingsChange(event)
|
|||||||
natives.attackPlayerThreshold = settings.global["rampant-attackPlayerThreshold"].value
|
natives.attackPlayerThreshold = settings.global["rampant-attackPlayerThreshold"].value
|
||||||
natives.aiNocturnalMode = settings.global["rampant-permanentNocturnal"].value
|
natives.aiNocturnalMode = settings.global["rampant-permanentNocturnal"].value
|
||||||
natives.aiPointsScaler = settings.global["rampant-aiPointsScaler"].value
|
natives.aiPointsScaler = settings.global["rampant-aiPointsScaler"].value
|
||||||
|
|
||||||
|
local useCustomAI = natives.useCustomAI
|
||||||
|
natives.useCustomAI = settings.startup["rampant-useCustomAI"].value
|
||||||
|
if not useCustomAI and natives.useCustomAI then
|
||||||
|
reprocessChunks()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function onConfigChanged()
|
local function onConfigChanged()
|
||||||
|
if upgrade.attempt(natives, regionMap) and onModSettingsChange(nil) then
|
||||||
if upgrade.attempt(natives, regionMap) then
|
reprocessChunks()
|
||||||
onModSettingsChange(nil)
|
|
||||||
|
|
||||||
game.surfaces[1].print("Rampant - Reindexing chunks, please wait")
|
|
||||||
-- clear old regionMap processing Queue
|
|
||||||
-- prevents queue adding duplicate chunks
|
|
||||||
-- chunks are by key, so should overwrite old
|
|
||||||
regionMap.processQueue = {}
|
|
||||||
regionMap.processPointer = 1
|
|
||||||
regionMap.scanPointer = 1
|
|
||||||
-- clear pending chunks, will be added when loop runs below
|
|
||||||
pendingChunks = {}
|
|
||||||
|
|
||||||
-- queue all current chunks that wont be generated during play
|
|
||||||
local surface = game.surfaces[1]
|
|
||||||
for chunk in surface.get_chunks() do
|
|
||||||
onChunkGenerated({ tick = game.tick,
|
|
||||||
surface = surface,
|
|
||||||
area = { left_top = { x = chunk.x * 32,
|
|
||||||
y = chunk.y * 32 }}})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -161,7 +173,9 @@ local function onTick(event)
|
|||||||
|
|
||||||
processPlayers(players, regionMap, surface, natives, evolutionFactor, tick)
|
processPlayers(players, regionMap, surface, natives, evolutionFactor, tick)
|
||||||
|
|
||||||
processBases(regionMap, surface, natives, tick)
|
if (natives.useCustomAI) then
|
||||||
|
processBases(regionMap, surface, natives, tick)
|
||||||
|
end
|
||||||
|
|
||||||
squadBeginAttack(natives, players, evolutionFactor)
|
squadBeginAttack(natives, players, evolutionFactor)
|
||||||
squadAttack(regionMap, surface, natives)
|
squadAttack(regionMap, surface, natives)
|
||||||
@@ -173,7 +187,7 @@ end
|
|||||||
|
|
||||||
local function onBuild(event)
|
local function onBuild(event)
|
||||||
local entity = event.created_entity
|
local entity = event.created_entity
|
||||||
addRemoveEntity(regionMap, entity, natives, true, false)
|
addRemovePlayerEntity(regionMap, entity, natives, true, false)
|
||||||
if natives.safeBuildings then
|
if natives.safeBuildings then
|
||||||
if natives.safeEntities[entity.type] or natives.safeEntityName[entity.name] then
|
if natives.safeEntities[entity.type] or natives.safeEntityName[entity.name] then
|
||||||
entity.destructible = false
|
entity.destructible = false
|
||||||
@@ -198,7 +212,7 @@ local function onDeath(event)
|
|||||||
-- drop death pheromone where unit died
|
-- drop death pheromone where unit died
|
||||||
deathScent(deathChunk)
|
deathScent(deathChunk)
|
||||||
|
|
||||||
if ((event.force ~= nil) and (event.force.name == "player")) then
|
if event.force and (event.force.name == "player") then
|
||||||
local evolutionFactor = entity.force.evolution_factor
|
local evolutionFactor = entity.force.evolution_factor
|
||||||
local tick = event.tick
|
local tick = event.tick
|
||||||
|
|
||||||
@@ -224,7 +238,7 @@ local function onDeath(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
elseif (entity.type == "unit-spawner") or (entity.type == "turret") then
|
elseif (entity.type == "unit-spawner") or (entity.type == "turret") then
|
||||||
removeEnemyBase(regionMap, entity)
|
unregisterEnemyBaseStructure(regionMap, entity)
|
||||||
end
|
end
|
||||||
elseif (entity.force.name == "player") then
|
elseif (entity.force.name == "player") then
|
||||||
local creditNatives = false
|
local creditNatives = false
|
||||||
@@ -247,7 +261,7 @@ end
|
|||||||
|
|
||||||
local function onSurfaceTileChange(event)
|
local function onSurfaceTileChange(event)
|
||||||
local player = game.players[event.player_index]
|
local player = game.players[event.player_index]
|
||||||
if (player.surface.index==1) then
|
if (player.surface.index == 1) then
|
||||||
aiBuilding.fillTunnel(regionMap, player.surface, natives, event.positions)
|
aiBuilding.fillTunnel(regionMap, player.surface, natives, event.positions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -303,7 +317,9 @@ remote.add_interface("rampantTests",
|
|||||||
baseStats = tests.baseStats,
|
baseStats = tests.baseStats,
|
||||||
baseTiles = tests.baseTiles,
|
baseTiles = tests.baseTiles,
|
||||||
mergeBases = tests.mergeBases,
|
mergeBases = tests.mergeBases,
|
||||||
clearBases = tests.clearBases
|
clearBases = tests.clearBases,
|
||||||
|
getOffsetChunk = tests.getOffsetChunk,
|
||||||
|
registeredNest = tests.registeredNest
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name" : "Rampant",
|
"name" : "Rampant",
|
||||||
"factorio_version" : "0.15",
|
"factorio_version" : "0.15",
|
||||||
"version" : "0.15.10",
|
"version" : "0.15.11",
|
||||||
"title" : "Rampant",
|
"title" : "Rampant",
|
||||||
"author" : "Veden",
|
"author" : "Veden",
|
||||||
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
||||||
|
@@ -19,6 +19,9 @@ local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
|||||||
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
|
|
||||||
|
local NEST_COUNT = constants.NEST_COUNT
|
||||||
|
|
||||||
|
local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area
|
||||||
local DEFINES_GROUP_FINISHED = defines.group_state.finished
|
local DEFINES_GROUP_FINISHED = defines.group_state.finished
|
||||||
local DEFINES_GROUP_GATHERING = defines.group_state.gathering
|
local DEFINES_GROUP_GATHERING = defines.group_state.gathering
|
||||||
local DEFINES_GROUP_MOVING = defines.group_state.moving
|
local DEFINES_GROUP_MOVING = defines.group_state.moving
|
||||||
@@ -49,40 +52,20 @@ local function validLocation(x, chunk, neighborChunk)
|
|||||||
return canMoveChunkDirection(x, chunk, neighborChunk)
|
return canMoveChunkDirection(x, chunk, neighborChunk)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function scoreAttackLocation(position, squad, neighborChunk, surface)
|
local function scoreAttackLocation(squad, neighborChunk, surface)
|
||||||
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||||
local r = surface.get_pollution(position) + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 25) --- neighborChunk[ENEMY_BASE_GENERATOR]
|
local r = surface.get_pollution(neighborChunk) + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 50)
|
||||||
return r - squadMovementPenalty
|
return r - squadMovementPenalty - (neighborChunk[NEST_COUNT] * 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
function aiAttack.squadAttack(regionMap, surface, natives)
|
function aiAttack.squadAttack(regionMap, surface, natives)
|
||||||
local squads = natives.squads
|
local squads = natives.squads
|
||||||
local attackPosition
|
local attackPosition
|
||||||
local attackCmd
|
local attackCmd
|
||||||
|
|
||||||
--[[
|
|
||||||
Constants populated by the factorio runtime
|
|
||||||
--]]
|
|
||||||
-- local DEFINES_GROUP_FINISHED
|
|
||||||
-- local DEFINES_GROUP_GATHERING
|
|
||||||
-- local DEFINES_GROUP_MOVING
|
|
||||||
-- local DEFINES_GROUP_ATTACKING_DISTRACTION
|
|
||||||
-- local DEFINES_GROUP_ATTACKING_TARGET
|
|
||||||
|
|
||||||
-- local DEFINES_DISTRACTION_BY_ENEMY
|
|
||||||
-- local DEFINES_DISTRACTION_BY_ANYTHING
|
|
||||||
|
|
||||||
if (#squads > 0) then
|
if (#squads > 0) then
|
||||||
-- DEFINES_GROUP_FINISHED = defines.group_state.finished
|
|
||||||
-- DEFINES_GROUP_GATHERING = defines.group_state.gathering
|
|
||||||
-- DEFINES_GROUP_MOVING = defines.group_state.moving
|
|
||||||
-- DEFINES_GROUP_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
|
|
||||||
-- DEFINES_GROUP_ATTACKING_TARGET = defines.group_state.attacking_target
|
|
||||||
-- DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy
|
|
||||||
-- DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
|
|
||||||
|
|
||||||
attackPosition = {x=0, y=0}
|
attackPosition = {x=0, y=0}
|
||||||
attackCmd = { type = defines.command.attack_area,
|
attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA,
|
||||||
destination = attackPosition,
|
destination = attackPosition,
|
||||||
radius = 28,
|
radius = 28,
|
||||||
distraction = DEFINES_DISTRACTION_BY_ENEMY }
|
distraction = DEFINES_DISTRACTION_BY_ENEMY }
|
||||||
@@ -102,7 +85,6 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
|||||||
scoreAttackLocation,
|
scoreAttackLocation,
|
||||||
squad,
|
squad,
|
||||||
surface,
|
surface,
|
||||||
attackPosition,
|
|
||||||
true)
|
true)
|
||||||
addSquadMovementPenalty(squad, chunk.cX, chunk.cY)
|
addSquadMovementPenalty(squad, chunk.cX, chunk.cY)
|
||||||
if attackChunk then
|
if attackChunk then
|
||||||
@@ -117,8 +99,8 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
|||||||
squad.cycles = 4
|
squad.cycles = 4
|
||||||
end
|
end
|
||||||
|
|
||||||
local outsideFrenzyRadius = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) > 100)
|
local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)
|
||||||
squad.frenzy = not outsideFrenzyRadius
|
squad.frenzy = moreFrenzy
|
||||||
|
|
||||||
if squad.rabid or squad.frenzy then
|
if squad.rabid or squad.frenzy then
|
||||||
attackCmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
|
attackCmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
|
||||||
|
@@ -33,7 +33,7 @@ local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE
|
|||||||
local DEFINES_COMMAND_GROUP = defines.command.group
|
local DEFINES_COMMAND_GROUP = defines.command.group
|
||||||
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
||||||
|
|
||||||
local CHUNK_BASE = constants.CHUNK_BASE
|
local NEST_COUNT = constants.NEST_COUNT
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ local function attackWaveValidCandidate(chunk, natives, surface, evolutionFactor
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if natives.attackUsePollution then
|
if natives.attackUsePollution then
|
||||||
total = total + surface.get_pollution({chunk.pX, chunk.pY})
|
total = total + surface.get_pollution(chunk)
|
||||||
end
|
end
|
||||||
|
|
||||||
local threshold = natives.attackThresholdRange
|
local threshold = natives.attackThresholdRange
|
||||||
@@ -66,12 +66,12 @@ local function attackWaveValidCandidate(chunk, natives, surface, evolutionFactor
|
|||||||
return total > ((threshold - delta) + natives.attackThresholdMin)
|
return total > ((threshold - delta) + natives.attackThresholdMin)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function scoreUnitGroupLocation(position, squad, neighborChunk, surface)
|
local function scoreUnitGroupLocation(squad, neighborChunk, surface)
|
||||||
return surface.get_pollution(position) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE]
|
return surface.get_pollution(neighborChunk) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE]
|
||||||
end
|
end
|
||||||
|
|
||||||
local function validUnitGroupLocation(x, chunk, neighborChunk)
|
local function validUnitGroupLocation(x, chunk, neighborChunk)
|
||||||
return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE] and neighborChunk[CHUNK_BASE] ~= nil
|
return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE] and neighborChunk[NEST_COUNT] ~= 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, evolutionFactor, tick)
|
function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, evolutionFactor, tick)
|
||||||
@@ -82,7 +82,7 @@ function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, evolutionFact
|
|||||||
for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE do
|
for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE do
|
||||||
for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE do
|
for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE do
|
||||||
local rallyChunk = getChunkByIndex(regionMap, x, y)
|
local rallyChunk = getChunkByIndex(regionMap, x, y)
|
||||||
if rallyChunk and (x ~= cX) and (y ~= cY) and (rallyChunk[ENEMY_BASE_GENERATOR] ~= 0) then
|
if rallyChunk and (x ~= cX) and (y ~= cY) and (rallyChunk[NEST_COUNT] ~= 0) then
|
||||||
aiBuilding.formSquads(regionMap, surface, natives, rallyChunk, evolutionFactor, AI_VENGENCE_SQUAD_COST)
|
aiBuilding.formSquads(regionMap, surface, natives, rallyChunk, evolutionFactor, AI_VENGENCE_SQUAD_COST)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -91,24 +91,23 @@ function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, evolutionFact
|
|||||||
end
|
end
|
||||||
|
|
||||||
function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_factor, cost)
|
function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_factor, cost)
|
||||||
if (natives.points > cost) and (chunk[CHUNK_BASE] ~= nil) and (#natives.squads < (AI_MAX_SQUAD_COUNT * evolution_factor)) then
|
if (natives.points > cost) and (chunk[NEST_COUNT] ~= 0) and (#natives.squads < (AI_MAX_SQUAD_COUNT * evolution_factor)) then
|
||||||
local valid = not surface.peaceful_mode and
|
local valid = not surface.peaceful_mode and
|
||||||
((cost == AI_VENGENCE_SQUAD_COST) or
|
((cost == AI_VENGENCE_SQUAD_COST) or
|
||||||
((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface, evolution_factor)))
|
((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface, evolution_factor)))
|
||||||
|
|
||||||
if valid and (math.random() < mMax((0.25 * evolution_factor), 0.10)) then
|
if valid and (math.random() < mMax((0.25 * evolution_factor), 0.10)) then
|
||||||
local squadPosition = {x=0, y=0}
|
|
||||||
local squadPath, _ = scoreNeighbors(chunk,
|
local squadPath, _ = scoreNeighbors(chunk,
|
||||||
getNeighborChunks(regionMap, chunk.cX, chunk.cY),
|
getNeighborChunks(regionMap, chunk.cX, chunk.cY),
|
||||||
validUnitGroupLocation,
|
validUnitGroupLocation,
|
||||||
scoreUnitGroupLocation,
|
scoreUnitGroupLocation,
|
||||||
nil,
|
nil,
|
||||||
surface,
|
surface,
|
||||||
squadPosition,
|
|
||||||
false)
|
false)
|
||||||
if (squadPath ~= nil) then
|
if squadPath then
|
||||||
squadPosition.x = squadPath.pX + HALF_CHUNK_SIZE
|
local squadPosition = { x = squadPath.x + HALF_CHUNK_SIZE,
|
||||||
squadPosition.y = squadPath.pY + HALF_CHUNK_SIZE
|
y = squadPath.y + HALF_CHUNK_SIZE }
|
||||||
|
|
||||||
local squad = createSquad(squadPosition, surface, natives)
|
local squad = createSquad(squadPosition, surface, natives)
|
||||||
|
|
||||||
|
@@ -25,7 +25,8 @@ local RETREAT_TRIGGERED = constants.RETREAT_TRIGGERED
|
|||||||
|
|
||||||
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
||||||
|
|
||||||
local NEST_BASE = constants.NEST_BASE
|
local NEST_COUNT = constants.NEST_COUNT
|
||||||
|
local WORM_COUNT = constants.WORM_COUNT
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
@@ -43,20 +44,19 @@ local function validRetreatLocation(x, chunk, neighborChunk)
|
|||||||
return canMoveChunkDirection(x, chunk, neighborChunk)
|
return canMoveChunkDirection(x, chunk, neighborChunk)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function scoreRetreatLocation(position, squad, neighborChunk, surface)
|
local function scoreRetreatLocation(squad, neighborChunk, surface)
|
||||||
local safeScore = -neighborChunk[BASE_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE]
|
local safeScore = -neighborChunk[BASE_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE]
|
||||||
local dangerScore = surface.get_pollution(position) + (neighborChunk[PLAYER_PHEROMONE] * 100) --+ (neighborChunk[ENEMY_BASE_GENERATOR] * 50)
|
local dangerScore = surface.get_pollution(neighborChunk) + (neighborChunk[PLAYER_PHEROMONE] * 100) --+ (neighborChunk[ENEMY_BASE_GENERATOR] * 50)
|
||||||
return safeScore - dangerScore
|
return safeScore - dangerScore
|
||||||
end
|
end
|
||||||
|
|
||||||
function aiDefense.retreatUnits(chunk, squad, regionMap, surface, natives, tick)
|
function aiDefense.retreatUnits(chunk, squad, regionMap, surface, natives, tick)
|
||||||
if (tick - chunk[RETREAT_TRIGGERED] > INTERVAL_LOGIC) and (#chunk[NEST_BASE] == 0) then
|
if (tick - chunk[RETREAT_TRIGGERED] > INTERVAL_LOGIC) and (chunk[NEST_COUNT] == 0) and (chunk[WORM_COUNT] == 0) then
|
||||||
local performRetreat = false
|
local performRetreat = false
|
||||||
local enemiesToSquad
|
local enemiesToSquad = nil
|
||||||
|
|
||||||
if (squad == nil) then
|
if not squad then
|
||||||
enemiesToSquad = surface.find_enemy_units({x=chunk.pX,
|
enemiesToSquad = surface.find_enemy_units(chunk, RETREAT_GRAB_RADIUS)
|
||||||
y=chunk.pY}, RETREAT_GRAB_RADIUS)
|
|
||||||
performRetreat = #enemiesToSquad > 0
|
performRetreat = #enemiesToSquad > 0
|
||||||
elseif squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
|
elseif squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
|
||||||
performRetreat = #squad.group.members > 1
|
performRetreat = #squad.group.members > 1
|
||||||
@@ -64,31 +64,29 @@ function aiDefense.retreatUnits(chunk, squad, regionMap, surface, natives, tick)
|
|||||||
|
|
||||||
if performRetreat then
|
if performRetreat then
|
||||||
chunk[RETREAT_TRIGGERED] = tick
|
chunk[RETREAT_TRIGGERED] = tick
|
||||||
local retreatPosition = {x=0, y=0}
|
|
||||||
local exitPath,_ = scoreNeighborsWithDirection(chunk,
|
local exitPath,_ = scoreNeighborsWithDirection(chunk,
|
||||||
getNeighborChunksWithDirection(regionMap, chunk.cX, chunk.cY),
|
getNeighborChunksWithDirection(regionMap, chunk.cX, chunk.cY),
|
||||||
validRetreatLocation,
|
validRetreatLocation,
|
||||||
scoreRetreatLocation,
|
scoreRetreatLocation,
|
||||||
nil,
|
nil,
|
||||||
surface,
|
surface,
|
||||||
retreatPosition,
|
|
||||||
false)
|
false)
|
||||||
if exitPath then
|
if exitPath then
|
||||||
retreatPosition.x = exitPath.pX + HALF_CHUNK_SIZE
|
local retreatPosition = { x = exitPath.x + HALF_CHUNK_SIZE,
|
||||||
retreatPosition.y = exitPath.pY + HALF_CHUNK_SIZE
|
y = exitPath.y + HALF_CHUNK_SIZE }
|
||||||
|
|
||||||
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
|
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
|
||||||
-- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
|
-- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
|
||||||
|
|
||||||
local newSquad = findNearBySquad(natives, retreatPosition, HALF_CHUNK_SIZE, RETREAT_FILTER)
|
local newSquad = findNearBySquad(natives, retreatPosition, HALF_CHUNK_SIZE, RETREAT_FILTER)
|
||||||
|
|
||||||
if (newSquad == nil) then
|
if not newSquad then
|
||||||
newSquad = createSquad(retreatPosition, surface, natives)
|
newSquad = createSquad(retreatPosition, surface, natives)
|
||||||
newSquad.status = SQUAD_RETREATING
|
newSquad.status = SQUAD_RETREATING
|
||||||
newSquad.cycles = 4
|
newSquad.cycles = 4
|
||||||
end
|
end
|
||||||
|
|
||||||
if (enemiesToSquad ~= nil) then
|
if enemiesToSquad then
|
||||||
membersToSquad(newSquad, enemiesToSquad, false)
|
membersToSquad(newSquad, enemiesToSquad, false)
|
||||||
else
|
else
|
||||||
membersToSquad(newSquad, squad.group.members, true)
|
membersToSquad(newSquad, squad.group.members, true)
|
||||||
|
@@ -4,8 +4,8 @@ local aiPlanning = {}
|
|||||||
|
|
||||||
local constants = require("Constants")
|
local constants = require("Constants")
|
||||||
local mathUtils = require("MathUtils")
|
local mathUtils = require("MathUtils")
|
||||||
local nocturnalUtils = require("NocturnalUtils")
|
local aiPredicates = require("AIPredicates")
|
||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local AI_STATE_PEACEFUL = constants.AI_STATE_PEACEFUL
|
local AI_STATE_PEACEFUL = constants.AI_STATE_PEACEFUL
|
||||||
@@ -26,7 +26,7 @@ local TICKS_A_MINUTE = constants.TICKS_A_MINUTE
|
|||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
local canAttackNocturnal = nocturnalUtils.canAttack
|
local canAttack = aiPredicates.canAttack
|
||||||
|
|
||||||
local randomTickEvent = mathUtils.randomTickEvent
|
local randomTickEvent = mathUtils.randomTickEvent
|
||||||
|
|
||||||
@@ -34,13 +34,22 @@ local mMax = math.max
|
|||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
|
local function isShockwaveReady(evolution_factor, natives, surface, tick, maxPoints)
|
||||||
|
return canAttack(natives, surface) and
|
||||||
|
(tick - natives.lastShakeMessage > TICKS_A_MINUTE * 5) and
|
||||||
|
((evolution_factor > 0.7) and
|
||||||
|
(natives.points > maxPoints * 0.85) and
|
||||||
|
(#natives.squads > AI_MAX_SQUAD_COUNT * 0.35))
|
||||||
|
end
|
||||||
|
|
||||||
function aiPlanning.planning(natives, evolution_factor, tick, surface)
|
function aiPlanning.planning(natives, evolution_factor, tick, surface)
|
||||||
local maxPoints = AI_MAX_POINTS * evolution_factor
|
local maxPoints = AI_MAX_POINTS * evolution_factor
|
||||||
if natives.aiNocturnalMode then
|
if natives.aiNocturnalMode then
|
||||||
maxPoints = maxPoints * 0.85
|
maxPoints = maxPoints * 0.85
|
||||||
end
|
end
|
||||||
if (natives.points < maxPoints) then
|
if (natives.points < maxPoints) then
|
||||||
natives.points = natives.points + math.floor((AI_POINT_GENERATOR_AMOUNT * math.random()) + ((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * natives.aiPointsScaler)
|
natives.points = natives.points + math.floor((AI_POINT_GENERATOR_AMOUNT * math.random()) +
|
||||||
|
((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * natives.aiPointsScaler)
|
||||||
end
|
end
|
||||||
|
|
||||||
if (natives.temperamentTick == tick) then
|
if (natives.temperamentTick == tick) then
|
||||||
@@ -60,7 +69,7 @@ function aiPlanning.planning(natives, evolution_factor, tick, surface)
|
|||||||
natives.stateTick = randomTickEvent(tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
|
natives.stateTick = randomTickEvent(tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((natives.state == AI_STATE_AGGRESSIVE) or canAttackNocturnal(natives, surface)) and (tick - natives.lastShakeMessage > TICKS_A_MINUTE * 5) and ((evolution_factor > 0.7) and (natives.points > maxPoints * 0.85) and (#natives.squads > AI_MAX_SQUAD_COUNT * 0.35)) then
|
if isShockwaveReady(evolution_factor, natives, surface, tick, maxPoints) then
|
||||||
natives.lastShakeMessage = tick
|
natives.lastShakeMessage = tick
|
||||||
surface.print("Rampant: The ground begins to shake")
|
surface.print("Rampant: The ground begins to shake")
|
||||||
end
|
end
|
||||||
|
@@ -5,6 +5,7 @@ local baseUtils = {}
|
|||||||
local mapUtils = require("MapUtils")
|
local mapUtils = require("MapUtils")
|
||||||
local constants = require("Constants")
|
local constants = require("Constants")
|
||||||
local mathUtils = require("MathUtils")
|
local mathUtils = require("MathUtils")
|
||||||
|
|
||||||
local entityUtils = require("EntityUtils")
|
local entityUtils = require("EntityUtils")
|
||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
@@ -13,6 +14,12 @@ local BASE_DISTANCE_THRESHOLD = constants.BASE_DISTANCE_THRESHOLD
|
|||||||
|
|
||||||
local BASE_ALIGNMENT_NEUTRAL = constants.BASE_ALIGNMENT_NEUTRAL
|
local BASE_ALIGNMENT_NEUTRAL = constants.BASE_ALIGNMENT_NEUTRAL
|
||||||
|
|
||||||
|
local NEST_COUNT = constants.NEST_COUNT
|
||||||
|
local WORM_COUNT = constants.WORM_COUNT
|
||||||
|
|
||||||
|
local NEST_BASE = constants.NEST_BASE
|
||||||
|
local WORM_BASE = constants.WORM_BASE
|
||||||
|
|
||||||
local AI_NEST_COST = constants.AI_NEST_COST
|
local AI_NEST_COST = constants.AI_NEST_COST
|
||||||
local AI_WORM_COST = constants.AI_WORM_COST
|
local AI_WORM_COST = constants.AI_WORM_COST
|
||||||
|
|
||||||
@@ -25,34 +32,34 @@ local MAGIC_MAXIMUM_BASE_NUMBER = constants.MAGIC_MAXIMUM_BASE_NUMBER
|
|||||||
|
|
||||||
local euclideanDistancePoints = mapUtils.euclideanDistancePoints
|
local euclideanDistancePoints = mapUtils.euclideanDistancePoints
|
||||||
|
|
||||||
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
local getEntityOverlapChunks = entityUtils.getEntityOverlapChunks
|
||||||
|
|
||||||
local addEnemyBase = entityUtils.addEnemyBase
|
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
function baseUtils.annexNest(natives, position)
|
function baseUtils.findNearbyBase(natives, position)
|
||||||
local bases = natives.bases
|
local bases = natives.bases
|
||||||
local annex = nil
|
local foundBase
|
||||||
local closest = MAGIC_MAXIMUM_NUMBER
|
local closest = MAGIC_MAXIMUM_NUMBER
|
||||||
for i=1,#bases do
|
for i=1,#bases do
|
||||||
local base = bases[i]
|
local base = bases[i]
|
||||||
local distance = euclideanDistancePoints(base.x, base.y, position.x, position.y)
|
local distance = euclideanDistancePoints(base.x, base.y, position.x, position.y)
|
||||||
if (distance <= BASE_DISTANCE_THRESHOLD) and (distance < closest) then
|
if (distance <= BASE_DISTANCE_THRESHOLD) and (distance < closest) then
|
||||||
closest = distance
|
closest = distance
|
||||||
annex = base
|
foundBase = base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return annex
|
return foundBase
|
||||||
end
|
end
|
||||||
|
|
||||||
function baseUtils.buildHive(regionMap, base, surface)
|
function baseUtils.buildHive(regionMap, base, surface)
|
||||||
local valid = false
|
local valid = false
|
||||||
local position = surface.find_non_colliding_position("biter-spawner", {x=base.x, y=base.y}, 2*CHUNK_SIZE, 10)
|
local position = surface.find_non_colliding_position("biter-spawner-hive", {x=base.x, y=base.y}, 2*CHUNK_SIZE, 2)
|
||||||
if position then
|
if position then
|
||||||
local biterSpawner = {name="biter-spawner", position=position}
|
local biterSpawner = {name="biter-spawner-hive", position=position}
|
||||||
base.hive = surface.create_entity(biterSpawner)
|
base.hives[#base.hives+1] = surface.create_entity(biterSpawner)
|
||||||
addEnemyBase(regionMap, base.hive, base)
|
baseUtils.registerEnemyBaseStructure(regionMap, base.hive, base)
|
||||||
valid = true
|
valid = true
|
||||||
end
|
end
|
||||||
return valid
|
return valid
|
||||||
@@ -67,7 +74,7 @@ function baseUtils.buildTendril(natives, base, surface, tick, startPosition, end
|
|||||||
end
|
end
|
||||||
|
|
||||||
function baseUtils.buildOrder(regionMap, natives, base, surface, tick)
|
function baseUtils.buildOrder(regionMap, natives, base, surface, tick)
|
||||||
if not base.hive or (base.upgradePoints < 10) then
|
if (#base.hives == 0) or (base.upgradePoints < 10) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -100,7 +107,7 @@ function baseUtils.buildOrder(regionMap, natives, base, surface, tick)
|
|||||||
y = base.y + (distortion * math.sin(pos))}
|
y = base.y + (distortion * math.sin(pos))}
|
||||||
local biterSpawner = {name=thing, position=nestPosition}
|
local biterSpawner = {name=thing, position=nestPosition}
|
||||||
if surface.can_place_entity(biterSpawner) then
|
if surface.can_place_entity(biterSpawner) then
|
||||||
addEnemyBase(regionMap, surface.create_entity(biterSpawner), base)
|
baseUtils.registerEnemyBaseStructure(regionMap, surface.create_entity(biterSpawner), base)
|
||||||
base.upgradePoints = base.upgradePoints - cost
|
base.upgradePoints = base.upgradePoints - cost
|
||||||
end
|
end
|
||||||
pos = pos + slice
|
pos = pos + slice
|
||||||
@@ -115,7 +122,7 @@ function baseUtils.createBase(regionMap, natives, position, surface, tick)
|
|||||||
y = position.y,
|
y = position.y,
|
||||||
created = tick,
|
created = tick,
|
||||||
alignment = { BASE_ALIGNMENT_NEUTRAL },
|
alignment = { BASE_ALIGNMENT_NEUTRAL },
|
||||||
hive = nil,
|
hives = {},
|
||||||
nests = {},
|
nests = {},
|
||||||
worms = {},
|
worms = {},
|
||||||
eggs = {},
|
eggs = {},
|
||||||
@@ -131,5 +138,93 @@ function baseUtils.createBase(regionMap, natives, position, surface, tick)
|
|||||||
return base
|
return base
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function baseUtils.addEnemyStructureToChunk(chunk, entity, base)
|
||||||
|
local indexChunk
|
||||||
|
local indexBase
|
||||||
|
local countChunk
|
||||||
|
if (entity.type == "unit-spawner") then
|
||||||
|
indexChunk = chunk[NEST_BASE]
|
||||||
|
if base then
|
||||||
|
indexBase = base.nests
|
||||||
|
end
|
||||||
|
countChunk = NEST_COUNT
|
||||||
|
elseif (entity.type == "turret") then
|
||||||
|
indexChunk = chunk[WORM_BASE]
|
||||||
|
if base then
|
||||||
|
indexBase = base.worms
|
||||||
|
end
|
||||||
|
countChunk = WORM_COUNT
|
||||||
|
end
|
||||||
|
chunk[countChunk] = chunk[countChunk] + 1
|
||||||
|
if indexBase then
|
||||||
|
indexChunk[entity.unit_number] = base
|
||||||
|
indexBase[entity.unit_number] = entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function baseUtils.removeEnemyStructureFromChunk(chunk, entity)
|
||||||
|
local indexChunk
|
||||||
|
local countChunk
|
||||||
|
if (entity.type == "unit-spawner") then
|
||||||
|
indexChunk = chunk[NEST_BASE]
|
||||||
|
countChunk = NEST_COUNT
|
||||||
|
elseif (entity.type == "turret") then
|
||||||
|
indexChunk = chunk[WORM_BASE]
|
||||||
|
countChunk = WORM_COUNT
|
||||||
|
end
|
||||||
|
local base = indexChunk[entity.unit_number]
|
||||||
|
local indexBase
|
||||||
|
if base then
|
||||||
|
if (entity.type == "unit-spawner") then
|
||||||
|
indexBase = base.nests
|
||||||
|
elseif (entity.type == "turret") then
|
||||||
|
indexBase = base.worms
|
||||||
|
end
|
||||||
|
indexBase[entity.unit_number] = nil
|
||||||
|
end
|
||||||
|
chunk[countChunk] = chunk[countChunk] - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function baseUtils.registerEnemyBaseStructure(regionMap, entity, base)
|
||||||
|
local entityType = entity.type
|
||||||
|
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
|
||||||
|
local leftTop, rightTop, leftBottom, rightBottom = getEntityOverlapChunks(regionMap, entity)
|
||||||
|
|
||||||
|
if leftTop then
|
||||||
|
baseUtils.addEnemyStructureToChunk(leftTop, entity, base)
|
||||||
|
end
|
||||||
|
if rightTop then
|
||||||
|
baseUtils.addEnemyStructureToChunk(rightTop, entity, base)
|
||||||
|
end
|
||||||
|
if leftBottom then
|
||||||
|
baseUtils.addEnemyStructureToChunk(leftBottom, entity, base)
|
||||||
|
end
|
||||||
|
if rightBottom then
|
||||||
|
baseUtils.addEnemyStructureToChunk(rightBottom, entity, base)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function baseUtils.unregisterEnemyBaseStructure(regionMap, entity)
|
||||||
|
local entityType = entity.type
|
||||||
|
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
|
||||||
|
local leftTop, rightTop, leftBottom, rightBottom = getEntityOverlapChunks(regionMap, entity)
|
||||||
|
|
||||||
|
if leftTop then
|
||||||
|
baseUtils.removeEnemyStructureFromChunk(leftTop, entity)
|
||||||
|
end
|
||||||
|
if rightTop then
|
||||||
|
baseUtils.removeEnemyStructureFromChunk(rightTop, entity)
|
||||||
|
end
|
||||||
|
if leftBottom then
|
||||||
|
baseUtils.removeEnemyStructureFromChunk(leftBottom, entity)
|
||||||
|
end
|
||||||
|
if rightBottom then
|
||||||
|
baseUtils.removeEnemyStructureFromChunk(rightBottom, entity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return baseUtils
|
return baseUtils
|
||||||
|
|
||||||
|
@@ -14,6 +14,8 @@ local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
|||||||
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||||
local NEST_BASE = constants.NEST_BASE
|
local NEST_BASE = constants.NEST_BASE
|
||||||
local WORM_BASE = constants.WORM_BASE
|
local WORM_BASE = constants.WORM_BASE
|
||||||
|
local NEST_COUNT = constants.NEST_COUNT
|
||||||
|
local WORM_COUNT = constants.WORM_COUNT
|
||||||
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
|
|
||||||
@@ -30,13 +32,13 @@ local RALLY_TRIGGERED = constants.RALLY_TRIGGERED
|
|||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
local annexNest = baseUtils.annexNest
|
local findNearbyBase = baseUtils.findNearbyBase
|
||||||
local createBase = baseUtils.createBase
|
local createBase = baseUtils.createBase
|
||||||
|
local addEnemyStructureToChunk = baseUtils.addEnemyStructureToChunk
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
local function checkForDeadendTiles(constantCoordinate, iteratingCoordinate, direction, surface)
|
local function checkForDeadendTiles(constantCoordinate, iteratingCoordinate, direction, get_tile)
|
||||||
local get_tile = surface.get_tile
|
|
||||||
|
|
||||||
for x=iteratingCoordinate, iteratingCoordinate + 31 do
|
for x=iteratingCoordinate, iteratingCoordinate + 31 do
|
||||||
local tile
|
local tile
|
||||||
@@ -53,19 +55,20 @@ local function checkForDeadendTiles(constantCoordinate, iteratingCoordinate, dir
|
|||||||
end
|
end
|
||||||
|
|
||||||
function chunkUtils.checkChunkPassability(chunk, surface)
|
function chunkUtils.checkChunkPassability(chunk, surface)
|
||||||
local x = chunk.pX
|
local x = chunk.x
|
||||||
local y = chunk.pY
|
local y = chunk.y
|
||||||
|
local get_tile = surface.get_tile
|
||||||
|
|
||||||
local passableNorthSouth = false
|
local passableNorthSouth = false
|
||||||
local passableEastWest = false
|
local passableEastWest = false
|
||||||
for xi=x, x + 31 do
|
for xi=x, x + 31 do
|
||||||
if (not checkForDeadendTiles(xi, y, NORTH_SOUTH, surface)) then
|
if (not checkForDeadendTiles(xi, y, NORTH_SOUTH, get_tile)) then
|
||||||
passableNorthSouth = true
|
passableNorthSouth = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for yi=y, y + 31 do
|
for yi=y, y + 31 do
|
||||||
if (not checkForDeadendTiles(yi, x, EAST_WEST, surface)) then
|
if (not checkForDeadendTiles(yi, x, EAST_WEST, get_tile)) then
|
||||||
passableEastWest = true
|
passableEastWest = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -76,77 +79,83 @@ function chunkUtils.checkChunkPassability(chunk, surface)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tick)
|
function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tick)
|
||||||
local x = chunk.pX
|
local x = chunk.x
|
||||||
local y = chunk.pY
|
local y = chunk.y
|
||||||
|
|
||||||
local chunkPosition = {x=x, y=y}
|
|
||||||
local areaBoundingBox = {
|
local areaBoundingBox = {
|
||||||
chunkPosition,
|
chunk,
|
||||||
{x + 32, y + 32}
|
{x + 32, y + 32}
|
||||||
}
|
}
|
||||||
local enemyChunkQuery = {area=areaBoundingBox,
|
local enemyChunkQuery = {area=areaBoundingBox,
|
||||||
force="enemy"}
|
force="enemy"}
|
||||||
local playerChunkQuery = {area=areaBoundingBox,
|
local playerChunkQuery = {area=areaBoundingBox,
|
||||||
force="player"}
|
force="player"}
|
||||||
|
|
||||||
|
local useCustomAI = natives.useCustomAI
|
||||||
local enemies = surface.find_entities_filtered(enemyChunkQuery)
|
local enemies = surface.find_entities_filtered(enemyChunkQuery)
|
||||||
|
|
||||||
local nestsRemoved = 0
|
local nests = 0
|
||||||
local wormsRemoved = 0
|
local worms = 0
|
||||||
local bitersRemoved = 0
|
local biters = 0
|
||||||
|
|
||||||
for i=1, #enemies do
|
for i=1, #enemies do
|
||||||
local entityType = enemies[i].type
|
local entityType = enemies[i].type
|
||||||
if (entityType == "unit-spawner") then
|
if (entityType == "unit-spawner") then
|
||||||
nestsRemoved = nestsRemoved + 3
|
nests = nests + 1
|
||||||
elseif (entityType == "turret") then
|
elseif (entityType == "turret") then
|
||||||
wormsRemoved = wormsRemoved + 2
|
worms = worms + 1
|
||||||
elseif (entityType == "unit") then
|
elseif useCustomAI and (entityType == "unit") then
|
||||||
bitersRemoved = bitersRemoved + 1
|
biters = biters + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
entities = surface.find_entities_filtered(playerChunkQuery)
|
if useCustomAI then
|
||||||
|
if (nests > 0) or (worms > 0) or (biters > 0) then
|
||||||
|
for f=1, #enemies do
|
||||||
|
enemies[f].destroy()
|
||||||
|
end
|
||||||
|
local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
|
||||||
|
if foundBase then
|
||||||
|
foundBase.upgradePoints = foundBase.upgradePoints + (nests*3) + (worms*2) + biters
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i=1, #enemies do
|
||||||
|
local enemy = enemies[i]
|
||||||
|
local enemyType = enemy.type
|
||||||
|
if (enemyType == "unit-spawner") or (enemyType == "turret") then
|
||||||
|
addEnemyStructureToChunk(chunk, enemy, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local safeBuildings = natives.safeBuildings
|
local entities = surface.find_entities_filtered(playerChunkQuery)
|
||||||
|
|
||||||
|
local playerObjects = 0
|
||||||
|
local safeBuildings = natives.safeBuildings
|
||||||
for i=1, #entities do
|
for i=1, #entities do
|
||||||
local entity = entities[i]
|
local entity = entities[i]
|
||||||
local entityType = entity.type
|
local entityType = entity.type
|
||||||
|
|
||||||
if safeBuildings then
|
if safeBuildings then
|
||||||
if natives.safeEntities[entityType] or natives.safeEntityName[entity.name] then
|
if natives.safeEntities[entityType] or natives.safeEntityName[entity.name] then
|
||||||
entity.destructible = false
|
entity.destructible = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (nestsRemoved > 0) or (wormsRemoved > 0) or (bitersRemoved > 0) then
|
local entityScore = BUILDING_PHEROMONES[entityType]
|
||||||
for i=1, #enemies do
|
|
||||||
enemies[i].destroy()
|
|
||||||
end
|
|
||||||
local foundBase = annexNest(natives, chunkPosition) or createBase(regionMap, natives, chunkPosition, surface, tick)
|
|
||||||
if foundBase then
|
|
||||||
foundBase.upgradePoints = foundBase.upgradePoints + nestsRemoved + wormsRemoved + bitersRemoved
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local playerObjects = 0
|
|
||||||
local entities = surface.find_entities_filtered(playerChunkQuery)
|
|
||||||
|
|
||||||
for i=1, #entities do
|
|
||||||
local entityScore = BUILDING_PHEROMONES[entities[i].type]
|
|
||||||
if (entityScore ~= nil) then
|
if (entityScore ~= nil) then
|
||||||
playerObjects = playerObjects + entityScore
|
playerObjects = playerObjects + entityScore
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
chunk[PLAYER_BASE_GENERATOR] = playerObjects
|
chunk[PLAYER_BASE_GENERATOR] = playerObjects
|
||||||
end
|
end
|
||||||
|
|
||||||
function chunkUtils.createChunk(topX, topY)
|
function chunkUtils.createChunk(topX, topY)
|
||||||
local chunk = {
|
local chunk = {
|
||||||
pX = topX,
|
x = topX,
|
||||||
pY = topY,
|
y = topY,
|
||||||
cX = topX * 0.03125,
|
cX = topX * 0.03125,
|
||||||
cY = topY * 0.03125
|
cY = topY * 0.03125
|
||||||
}
|
}
|
||||||
@@ -161,6 +170,8 @@ function chunkUtils.createChunk(topX, topY)
|
|||||||
chunk[RALLY_TRIGGERED] = 0
|
chunk[RALLY_TRIGGERED] = 0
|
||||||
chunk[NEST_BASE] = {}
|
chunk[NEST_BASE] = {}
|
||||||
chunk[WORM_BASE] = {}
|
chunk[WORM_BASE] = {}
|
||||||
|
chunk[NEST_COUNT] = 0
|
||||||
|
chunk[WORM_COUNT] = 0
|
||||||
return chunk
|
return chunk
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@ constants.VERSION_19 = 19
|
|||||||
constants.VERSION_20 = 20
|
constants.VERSION_20 = 20
|
||||||
constants.VERSION_21 = 21
|
constants.VERSION_21 = 21
|
||||||
constants.VERSION_22 = 22
|
constants.VERSION_22 = 22
|
||||||
|
constants.VERSION_23 = 23
|
||||||
|
|
||||||
-- misc
|
-- misc
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX = 0.40
|
|||||||
-- pheromone amounts
|
-- pheromone amounts
|
||||||
|
|
||||||
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||||
constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 30
|
--constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 30
|
||||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 500
|
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||||
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 150
|
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 150
|
||||||
|
|
||||||
@@ -120,6 +121,8 @@ constants.RETREAT_TRIGGERED = 9
|
|||||||
constants.RALLY_TRIGGERED = 10
|
constants.RALLY_TRIGGERED = 10
|
||||||
constants.NEST_BASE = 11
|
constants.NEST_BASE = 11
|
||||||
constants.WORM_BASE = 12
|
constants.WORM_BASE = 12
|
||||||
|
constants.NEST_COUNT = 13
|
||||||
|
constants.WORM_COUNT = 14
|
||||||
|
|
||||||
-- Squad status
|
-- Squad status
|
||||||
|
|
||||||
@@ -132,8 +135,8 @@ constants.SQUAD_RAIDING = 4 -- used when player stuff is close
|
|||||||
|
|
||||||
constants.RETREAT_GRAB_RADIUS = 24
|
constants.RETREAT_GRAB_RADIUS = 24
|
||||||
|
|
||||||
constants.BASE_RALLY_CHANCE = 0.01
|
constants.BASE_RALLY_CHANCE = 0.02
|
||||||
constants.BONUS_RALLY_CHANCE = 0.01
|
constants.BONUS_RALLY_CHANCE = 0.06
|
||||||
|
|
||||||
constants.MAX_RALLY_CRIES = 2
|
constants.MAX_RALLY_CRIES = 2
|
||||||
constants.RALLY_CRY_DISTANCE = 3
|
constants.RALLY_CRY_DISTANCE = 3
|
||||||
|
@@ -11,9 +11,6 @@ local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
|||||||
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
|
|
||||||
local NEST_BASE = constants.NEST_BASE
|
|
||||||
local WORM_BASE = constants.WORM_BASE
|
|
||||||
|
|
||||||
local DEFINES_DIRECTION_EAST = defines.direction.east
|
local DEFINES_DIRECTION_EAST = defines.direction.east
|
||||||
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
|
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
|
||||||
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
|
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
|
||||||
@@ -26,8 +23,8 @@ local mFloor = math.floor
|
|||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
local function getEntityOverlapChunks(regionMap, entity)
|
function entityUtils.getEntityOverlapChunks(regionMap, entity)
|
||||||
local boundingBox = entity.prototype.selection_box;
|
local boundingBox = entity.prototype.selection_box or entity.prototype.collision_box;
|
||||||
|
|
||||||
local leftTopChunk
|
local leftTopChunk
|
||||||
local rightTopChunk
|
local rightTopChunk
|
||||||
@@ -88,102 +85,28 @@ function entityUtils.addRemovePlayerEntity(regionMap, entity, natives, addObject
|
|||||||
if (BUILDING_PHEROMONES[entity.type] ~= nil) and (entity.force.name == "player") then
|
if (BUILDING_PHEROMONES[entity.type] ~= nil) and (entity.force.name == "player") then
|
||||||
entityValue = BUILDING_PHEROMONES[entity.type]
|
entityValue = BUILDING_PHEROMONES[entity.type]
|
||||||
|
|
||||||
leftTop, rightTop, leftBottom, rightBottom = getEntityOverlapChunks(regionMap, entity)
|
leftTop, rightTop, leftBottom, rightBottom = entityUtils.getEntityOverlapChunks(regionMap, entity)
|
||||||
if not addObject then
|
if not addObject then
|
||||||
if creditNatives then
|
if creditNatives then
|
||||||
natives.points = natives.points + entityValue
|
natives.points = natives.points + entityValue
|
||||||
end
|
end
|
||||||
entityValue = -entityValue
|
entityValue = -entityValue
|
||||||
end
|
end
|
||||||
if (leftTop ~= nil) then
|
if leftTop then
|
||||||
leftTop[PLAYER_BASE_GENERATOR] = leftTop[PLAYER_BASE_GENERATOR] + entityValue
|
leftTop[PLAYER_BASE_GENERATOR] = leftTop[PLAYER_BASE_GENERATOR] + entityValue
|
||||||
end
|
end
|
||||||
if (rightTop ~= nil) then
|
if rightTop then
|
||||||
rightTop[PLAYER_BASE_GENERATOR] = rightTop[PLAYER_BASE_GENERATOR] + entityValue
|
rightTop[PLAYER_BASE_GENERATOR] = rightTop[PLAYER_BASE_GENERATOR] + entityValue
|
||||||
end
|
end
|
||||||
if (leftBottom ~= nil) then
|
if leftBottom then
|
||||||
leftBottom[PLAYER_BASE_GENERATOR] = leftBottom[PLAYER_BASE_GENERATOR] + entityValue
|
leftBottom[PLAYER_BASE_GENERATOR] = leftBottom[PLAYER_BASE_GENERATOR] + entityValue
|
||||||
end
|
end
|
||||||
if (rightBottom ~= nil) then
|
if rightBottom then
|
||||||
rightBottom[PLAYER_BASE_GENERATOR] = rightBottom[PLAYER_BASE_GENERATOR] + entityValue
|
rightBottom[PLAYER_BASE_GENERATOR] = rightBottom[PLAYER_BASE_GENERATOR] + entityValue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addBaseToChunk(chunk, entity, base)
|
|
||||||
local indexChunk
|
|
||||||
local indexBase
|
|
||||||
if (entity.type == "unit-spawner") then
|
|
||||||
indexChunk = chunk[NEST_BASE]
|
|
||||||
indexBase = base.nests
|
|
||||||
elseif (entity.type == "turret") then
|
|
||||||
indexChunk = chunk[WORM_BASE]
|
|
||||||
indexBase = base.worms
|
|
||||||
end
|
|
||||||
indexChunk[entity.unit_number] = base
|
|
||||||
indexBase[entity.unit_number] = entity
|
|
||||||
end
|
|
||||||
|
|
||||||
local function removeBaseFromChunk(chunk, entity)
|
|
||||||
local indexChunk
|
|
||||||
if (entity.type == "unit-spawner") then
|
|
||||||
indexChunk = chunk[NEST_BASE]
|
|
||||||
elseif (entity.type == "turret") then
|
|
||||||
indexChunk = chunk[WORM_BASE]
|
|
||||||
end
|
|
||||||
local base = indexChunk[entity.unit_number]
|
|
||||||
local indexBase
|
|
||||||
if base then
|
|
||||||
if (entity.type == "unit-spawner") then
|
|
||||||
indexBase = base.nests
|
|
||||||
elseif (entity.type == "turret") then
|
|
||||||
indexBase = base.worms
|
|
||||||
end
|
|
||||||
indexBase[entity.unit_number] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function entityUtils.addEnemyBase(regionMap, entity, base)
|
|
||||||
local entityType = entity.type
|
|
||||||
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
|
|
||||||
local leftTop, rightTop, leftBottom, rightBottom = getEntityOverlapChunks(regionMap, entity)
|
|
||||||
|
|
||||||
if (leftTop ~= nil) then
|
|
||||||
addBaseToChunk(leftTop, entity, base)
|
|
||||||
end
|
|
||||||
if (rightTop ~= nil) then
|
|
||||||
addBaseToChunk(rightTop, entity, base)
|
|
||||||
end
|
|
||||||
if (leftBottom ~= nil) then
|
|
||||||
addBaseToChunk(leftBottom, entity, base)
|
|
||||||
end
|
|
||||||
if (rightBottom ~= nil) then
|
|
||||||
addBaseToChunk(rightBottom, entity, base)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function entityUtils.removeEnemyBase(regionMap, entity)
|
|
||||||
local entityType = entity.type
|
|
||||||
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
|
|
||||||
local leftTop, rightTop, leftBottom, rightBottom = getEntityOverlapChunks(regionMap, entity)
|
|
||||||
|
|
||||||
if (leftTop ~= nil) then
|
|
||||||
removeBaseFromChunk(leftTop, entity)
|
|
||||||
end
|
|
||||||
if (rightTop ~= nil) then
|
|
||||||
removeBaseFromChunk(rightTop, entity)
|
|
||||||
end
|
|
||||||
if (leftBottom ~= nil) then
|
|
||||||
removeBaseFromChunk(leftBottom, entity)
|
|
||||||
end
|
|
||||||
if (rightBottom ~= nil) then
|
|
||||||
removeBaseFromChunk(rightBottom, entity)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function entityUtils.makeImmortalEntity(surface, entity)
|
function entityUtils.makeImmortalEntity(surface, entity)
|
||||||
local repairPosition = entity.position
|
local repairPosition = entity.position
|
||||||
local repairName = entity.name
|
local repairName = entity.name
|
||||||
|
@@ -23,7 +23,8 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
|
|||||||
local PROCESS_PLAYER_BOUND = constants.PROCESS_PLAYER_BOUND
|
local PROCESS_PLAYER_BOUND = constants.PROCESS_PLAYER_BOUND
|
||||||
local CHUNK_TICK = constants.CHUNK_TICK
|
local CHUNK_TICK = constants.CHUNK_TICK
|
||||||
|
|
||||||
local NEST_BASE = constants.NEST_BASE
|
local NEST_COUNT = constants.NEST_COUNT
|
||||||
|
local WORM_COUNT = constants.WORM_COUNT
|
||||||
|
|
||||||
local AI_MAX_POINTS = constants.AI_MAX_POINTS
|
local AI_MAX_POINTS = constants.AI_MAX_POINTS
|
||||||
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
||||||
@@ -47,6 +48,8 @@ local playerScent = pheromoneUtils.playerScent
|
|||||||
|
|
||||||
local canAttack = aiPredicates.canAttack
|
local canAttack = aiPredicates.canAttack
|
||||||
|
|
||||||
|
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||||
|
|
||||||
local mMin = math.min
|
local mMin = math.min
|
||||||
|
|
||||||
local validPlayer = playerUtils.validPlayer
|
local validPlayer = playerUtils.validPlayer
|
||||||
@@ -140,12 +143,11 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, evolu
|
|||||||
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
|
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
|
||||||
|
|
||||||
if playerChunk then
|
if playerChunk then
|
||||||
local vengence = canAttack(natives, surface) and ((#playerChunk[NEST_BASE] ~= 0) or (playerChunk[MOVEMENT_PHEROMONE] < vengenceThreshold))
|
local vengence = canAttack(natives, surface) and ((playerChunk[NEST_COUNT] ~= 0) or (playerChunk[WORM_COUNT] ~= 0) or (playerChunk[MOVEMENT_PHEROMONE] < vengenceThreshold))
|
||||||
|
|
||||||
for x=playerChunk.cX - PROCESS_PLAYER_BOUND, playerChunk.cX + PROCESS_PLAYER_BOUND do
|
for x=playerChunk.cX - PROCESS_PLAYER_BOUND, playerChunk.cX + PROCESS_PLAYER_BOUND do
|
||||||
for y=playerChunk.cY - PROCESS_PLAYER_BOUND, playerChunk.cY + PROCESS_PLAYER_BOUND do
|
for y=playerChunk.cY - PROCESS_PLAYER_BOUND, playerChunk.cY + PROCESS_PLAYER_BOUND do
|
||||||
local chunk = getChunkByIndex(regionMap, x, y)
|
local chunk = getChunkByIndex(regionMap, x, y)
|
||||||
|
|
||||||
if chunk and (chunk[CHUNK_TICK] ~= tick) then
|
if chunk and (chunk[CHUNK_TICK] ~= tick) then
|
||||||
chunk[CHUNK_TICK] = tick
|
chunk[CHUNK_TICK] = tick
|
||||||
|
|
||||||
@@ -172,11 +174,11 @@ end
|
|||||||
Passive scan to find entities that have been generated outside the factorio event system
|
Passive scan to find entities that have been generated outside the factorio event system
|
||||||
--]]
|
--]]
|
||||||
function mapProcessor.scanMap(regionMap, surface, natives, evolution_factor)
|
function mapProcessor.scanMap(regionMap, surface, natives, evolution_factor)
|
||||||
-- local index = regionMap.scanPointer
|
local index = regionMap.scanPointer
|
||||||
|
|
||||||
local chunkPosition = {x=0,y=0}
|
local chunkBox = {false,
|
||||||
local chunkBox = {chunkPosition,
|
{x=0,
|
||||||
{x=chunkPosition.x + CHUNK_SIZE, y=chunkPosition.y + CHUNK_SIZE}}
|
y=0}}
|
||||||
local playerQuery = {area = chunkBox,
|
local playerQuery = {area = chunkBox,
|
||||||
force = "player"}
|
force = "player"}
|
||||||
local spawnerQuery = {area = chunkBox,
|
local spawnerQuery = {area = chunkBox,
|
||||||
@@ -195,11 +197,10 @@ function mapProcessor.scanMap(regionMap, surface, natives, evolution_factor)
|
|||||||
for x=index,endIndex do
|
for x=index,endIndex do
|
||||||
local chunk = processQueue[x]
|
local chunk = processQueue[x]
|
||||||
|
|
||||||
chunkPosition.x = chunk.pX
|
chunkBox[1] = chunk
|
||||||
chunkPosition.y = chunk.pY
|
|
||||||
|
chunkBox[2].x = chunk.x + CHUNK_SIZE
|
||||||
chunkBox[2].x = chunkPosition.x + CHUNK_SIZE
|
chunkBox[2].y = chunk.y + CHUNK_SIZE
|
||||||
chunkBox[2].y = chunkPosition.y + CHUNK_SIZE
|
|
||||||
|
|
||||||
local entities = surface.find_entities_filtered(playerQuery)
|
local entities = surface.find_entities_filtered(playerQuery)
|
||||||
|
|
||||||
@@ -213,7 +214,7 @@ function mapProcessor.scanMap(regionMap, surface, natives, evolution_factor)
|
|||||||
if (unitCount > 300) then
|
if (unitCount > 300) then
|
||||||
for i=1,#natives.squads do
|
for i=1,#natives.squads do
|
||||||
local squadGroup = natives.squads[i].group
|
local squadGroup = natives.squads[i].group
|
||||||
if squadGroup.valid and (euclideanDistanceNamed(squadGroup.position, chunkPosition) < CHUNK_SIZE * 2) then
|
if squadGroup.valid and (euclideanDistanceNamed(squadGroup.position, chunk) < CHUNK_SIZE * 2) then
|
||||||
closeBy = true
|
closeBy = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -221,7 +222,7 @@ function mapProcessor.scanMap(regionMap, surface, natives, evolution_factor)
|
|||||||
|
|
||||||
if (unitCount > 300) and not closeBy then
|
if (unitCount > 300) and not closeBy then
|
||||||
local weight = AI_UNIT_REFUND * evolution_factor
|
local weight = AI_UNIT_REFUND * evolution_factor
|
||||||
local units = surface.find_enemy_units(chunkPosition, CHUNK_SIZE * 3)
|
local units = surface.find_enemy_units(chunk, CHUNK_SIZE * 3)
|
||||||
|
|
||||||
for i=1,#units do
|
for i=1,#units do
|
||||||
units[i].destroy()
|
units[i].destroy()
|
||||||
@@ -248,7 +249,8 @@ function mapProcessor.scanMap(regionMap, surface, natives, evolution_factor)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
chunk[ENEMY_BASE_GENERATOR] = (spawners * ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT) + worms
|
chunk[NEST_COUNT] = spawners
|
||||||
|
chunk[WORM_COUNT] = worms
|
||||||
chunk[PLAYER_BASE_GENERATOR] = playerBaseGenerator
|
chunk[PLAYER_BASE_GENERATOR] = playerBaseGenerator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -49,21 +49,21 @@ function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY)
|
|||||||
local chunkYRow1 = chunkY - 1
|
local chunkYRow1 = chunkY - 1
|
||||||
local chunkYRow3 = chunkY + 1
|
local chunkYRow3 = chunkY + 1
|
||||||
local xChunks = regionMap[chunkX-1]
|
local xChunks = regionMap[chunkX-1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[1] = xChunks[chunkYRow1]
|
neighbors[1] = xChunks[chunkYRow1]
|
||||||
neighbors[4] = xChunks[chunkY]
|
neighbors[4] = xChunks[chunkY]
|
||||||
neighbors[6] = xChunks[chunkYRow3]
|
neighbors[6] = xChunks[chunkYRow3]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX+1]
|
xChunks = regionMap[chunkX+1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[3] = xChunks[chunkYRow1]
|
neighbors[3] = xChunks[chunkYRow1]
|
||||||
neighbors[5] = xChunks[chunkY]
|
neighbors[5] = xChunks[chunkY]
|
||||||
neighbors[8] = xChunks[chunkYRow3]
|
neighbors[8] = xChunks[chunkYRow3]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX]
|
xChunks = regionMap[chunkX]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[2] = xChunks[chunkYRow1]
|
neighbors[2] = xChunks[chunkYRow1]
|
||||||
neighbors[7] = xChunks[chunkYRow3]
|
neighbors[7] = xChunks[chunkYRow3]
|
||||||
end
|
end
|
||||||
@@ -89,21 +89,21 @@ function mapUtils.getNeighborChunksWithDirection(regionMap, chunkX, chunkY)
|
|||||||
local chunkYRow3 = chunkY + 1
|
local chunkYRow3 = chunkY + 1
|
||||||
|
|
||||||
local xChunks = regionMap[chunkX-1]
|
local xChunks = regionMap[chunkX-1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[1] = xChunks[chunkYRow1]
|
neighbors[1] = xChunks[chunkYRow1]
|
||||||
neighbors[4] = xChunks[chunkY]
|
neighbors[4] = xChunks[chunkY]
|
||||||
neighbors[6] = xChunks[chunkYRow3]
|
neighbors[6] = xChunks[chunkYRow3]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX+1]
|
xChunks = regionMap[chunkX+1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[3] = xChunks[chunkYRow1]
|
neighbors[3] = xChunks[chunkYRow1]
|
||||||
neighbors[5] = xChunks[chunkY]
|
neighbors[5] = xChunks[chunkY]
|
||||||
neighbors[8] = xChunks[chunkYRow3]
|
neighbors[8] = xChunks[chunkYRow3]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX]
|
xChunks = regionMap[chunkX]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[2] = xChunks[chunkYRow1]
|
neighbors[2] = xChunks[chunkYRow1]
|
||||||
neighbors[7] = xChunks[chunkYRow3]
|
neighbors[7] = xChunks[chunkYRow3]
|
||||||
end
|
end
|
||||||
@@ -120,18 +120,18 @@ end
|
|||||||
function mapUtils.getCardinalChunksWithDirection(regionMap, chunkX, chunkY)
|
function mapUtils.getCardinalChunksWithDirection(regionMap, chunkX, chunkY)
|
||||||
local neighbors = {false, false, false, false}
|
local neighbors = {false, false, false, false}
|
||||||
local xChunks = regionMap[chunkX]
|
local xChunks = regionMap[chunkX]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[1] = xChunks[chunkY-1]
|
neighbors[1] = xChunks[chunkY-1]
|
||||||
neighbors[4] = xChunks[chunkY+1]
|
neighbors[4] = xChunks[chunkY+1]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX-1]
|
xChunks = regionMap[chunkX-1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[2] = xChunks[chunkY]
|
neighbors[2] = xChunks[chunkY]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX+1]
|
xChunks = regionMap[chunkX+1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[3] = xChunks[chunkY]
|
neighbors[3] = xChunks[chunkY]
|
||||||
end
|
end
|
||||||
return neighbors
|
return neighbors
|
||||||
@@ -140,18 +140,18 @@ end
|
|||||||
function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY)
|
function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY)
|
||||||
local neighbors = {false,false,false,false}
|
local neighbors = {false,false,false,false}
|
||||||
local xChunks = regionMap[chunkX]
|
local xChunks = regionMap[chunkX]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[1] = xChunks[chunkY-1]
|
neighbors[1] = xChunks[chunkY-1]
|
||||||
neighbors[4] = xChunks[chunkY+1]
|
neighbors[4] = xChunks[chunkY+1]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX-1]
|
xChunks = regionMap[chunkX-1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[2] = xChunks[chunkY]
|
neighbors[2] = xChunks[chunkY]
|
||||||
end
|
end
|
||||||
|
|
||||||
xChunks = regionMap[chunkX+1]
|
xChunks = regionMap[chunkX+1]
|
||||||
if (xChunks ~= nil) then
|
if xChunks then
|
||||||
neighbors[3] = xChunks[chunkY]
|
neighbors[3] = xChunks[chunkY]
|
||||||
end
|
end
|
||||||
return neighbors
|
return neighbors
|
||||||
|
@@ -14,17 +14,14 @@ local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
|||||||
--[[
|
--[[
|
||||||
Expects all neighbors adjacent to a chunk
|
Expects all neighbors adjacent to a chunk
|
||||||
--]]
|
--]]
|
||||||
function neighborUtils.scoreNeighborsWithDirection(chunk, neighborDirectionChunks, validFunction, scoreFunction, squad, surface, position, scoreSelf)
|
function neighborUtils.scoreNeighborsWithDirection(chunk, neighborDirectionChunks, validFunction, scoreFunction, squad, surface, scoreSelf)
|
||||||
local highestChunk
|
local highestChunk
|
||||||
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
||||||
local highestDirection
|
local highestDirection
|
||||||
for x=1,8 do
|
for x=1,8 do
|
||||||
local neighborChunk = neighborDirectionChunks[x]
|
local neighborChunk = neighborDirectionChunks[x]
|
||||||
|
|
||||||
if neighborChunk and validFunction(x, chunk, neighborChunk) then
|
if neighborChunk and validFunction(x, chunk, neighborChunk) then
|
||||||
position.x = neighborChunk.pX
|
local score = scoreFunction(squad, neighborChunk, surface)
|
||||||
position.y = neighborChunk.pY
|
|
||||||
local score = scoreFunction(position, squad, neighborChunk, surface)
|
|
||||||
if (score > highestScore) then
|
if (score > highestScore) then
|
||||||
highestScore = score
|
highestScore = score
|
||||||
highestChunk = neighborChunk
|
highestChunk = neighborChunk
|
||||||
@@ -33,7 +30,7 @@ function neighborUtils.scoreNeighborsWithDirection(chunk, neighborDirectionChunk
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if scoreSelf and scoreFunction(position, squad, chunk, surface) > highestScore then
|
if scoreSelf and scoreFunction(squad, chunk, surface) > highestScore then
|
||||||
return nil, -1
|
return nil, -1
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -44,15 +41,13 @@ end
|
|||||||
--[[
|
--[[
|
||||||
Expects all neighbors adjacent to a chunk
|
Expects all neighbors adjacent to a chunk
|
||||||
--]]
|
--]]
|
||||||
function neighborUtils.scoreNeighbors(chunk, neighborChunks, validFunction, scoreFunction, squad, surface, position, scoreSelf)
|
function neighborUtils.scoreNeighbors(chunk, neighborChunks, validFunction, scoreFunction, squad, surface, scoreSelf)
|
||||||
local highestChunk
|
local highestChunk
|
||||||
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
||||||
for x=1,8 do
|
for x=1,8 do
|
||||||
local neighborChunk = neighborChunks[x]
|
local neighborChunk = neighborChunks[x]
|
||||||
if neighborChunk and validFunction(x, chunk, neighborChunk) then
|
if neighborChunk and validFunction(x, chunk, neighborChunk) then
|
||||||
position.x = neighborChunk.pX
|
local score = scoreFunction(squad, neighborChunk, surface)
|
||||||
position.y = neighborChunk.pY
|
|
||||||
local score = scoreFunction(position, squad, neighborChunk, surface)
|
|
||||||
if (score > highestScore) then
|
if (score > highestScore) then
|
||||||
highestScore = score
|
highestScore = score
|
||||||
highestChunk = neighborChunk
|
highestChunk = neighborChunk
|
||||||
@@ -60,7 +55,7 @@ function neighborUtils.scoreNeighbors(chunk, neighborChunks, validFunction, scor
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if scoreSelf and scoreFunction(position, squad, chunk, surface) > highestScore then
|
if scoreSelf and scoreFunction(squad, chunk, surface) > highestScore then
|
||||||
return nil, -1
|
return nil, -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -12,6 +12,8 @@ local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERAT
|
|||||||
local DEFINES_GROUP_STATE_FINISHED = defines.group_state.finished
|
local DEFINES_GROUP_STATE_FINISHED = defines.group_state.finished
|
||||||
local DEFINES_GROUP_STATE_ATTACKING_TARGET = defines.group_state.attacking_target
|
local DEFINES_GROUP_STATE_ATTACKING_TARGET = defines.group_state.attacking_target
|
||||||
local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
|
local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
|
||||||
|
local DEFINES_COMMAND_GROUP = defines.command.group
|
||||||
|
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
||||||
|
|
||||||
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
||||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||||
@@ -42,7 +44,7 @@ function unitGroupUtils.findNearBySquad(natives, position, distance, filter)
|
|||||||
for i=1,#squads do
|
for i=1,#squads do
|
||||||
local squad = squads[i]
|
local squad = squads[i]
|
||||||
local unitGroup = squad.group
|
local unitGroup = squad.group
|
||||||
if unitGroup.valid and ((filter == nil) or (filter ~= nil and filter[squad.status])) then
|
if unitGroup.valid and (not filter or (filter and filter[squad.status])) then
|
||||||
if (euclideanDistanceNamed(unitGroup.position, position) <= distance) then
|
if (euclideanDistanceNamed(unitGroup.position, position) <= distance) then
|
||||||
return squad
|
return squad
|
||||||
end
|
end
|
||||||
@@ -68,12 +70,12 @@ end
|
|||||||
|
|
||||||
function unitGroupUtils.membersToSquad(squad, members, overwriteGroup)
|
function unitGroupUtils.membersToSquad(squad, members, overwriteGroup)
|
||||||
if (members ~= nil) then
|
if (members ~= nil) then
|
||||||
local cmd = { type = defines.command.group,
|
local cmd = { type = DEFINES_COMMAND_GROUP,
|
||||||
group = squad.group,
|
group = squad.group,
|
||||||
distraction = defines.distraction.none }
|
distraction = DEFINES_DISTRACTION_NONE }
|
||||||
for i=1,#members do
|
for i=1,#members do
|
||||||
local member = members[i]
|
local member = members[i]
|
||||||
if member.valid and (overwriteGroup or (not overwriteGroup and (member.unit_group == nil))) then
|
if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
|
||||||
member.set_command(cmd)
|
member.set_command(cmd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -9,6 +9,8 @@ behemoth-suicide-biter=Behemoth Suicide Biter
|
|||||||
|
|
||||||
small-fire-spitter=Small Fire Spitter
|
small-fire-spitter=Small Fire Spitter
|
||||||
|
|
||||||
|
biter-spawner-hive=Small Hive
|
||||||
|
|
||||||
[entity-description]
|
[entity-description]
|
||||||
tunnel-entrance=This tunnel is used by the biters to bypass player defenses. Fill the hole using landfill.
|
tunnel-entrance=This tunnel is used by the biters to bypass player defenses. Fill the hole using landfill.
|
||||||
|
|
||||||
@@ -19,6 +21,8 @@ behemoth-suicide-biter=These biters will explode at close range
|
|||||||
|
|
||||||
small-fire-spitter=These biters will spit fire
|
small-fire-spitter=These biters will spit fire
|
||||||
|
|
||||||
|
biter-spawner-hive=Small Hive
|
||||||
|
|
||||||
[mod-setting-name]
|
[mod-setting-name]
|
||||||
rampant-useDumbProjectiles=Use Dumb Projectiles
|
rampant-useDumbProjectiles=Use Dumb Projectiles
|
||||||
rampant-useNEUnitLaunchers=Use Natural Evolution Unit Launchers (Needs NE)
|
rampant-useNEUnitLaunchers=Use Natural Evolution Unit Launchers (Needs NE)
|
||||||
@@ -38,6 +42,7 @@ rampant-attackPlayerThreshold=Player score contribution threshold
|
|||||||
rampant-permanentNocturnal=Permanent Nocturnal Mode
|
rampant-permanentNocturnal=Permanent Nocturnal Mode
|
||||||
rampant-aiPointsScaler=Difficulty Scaling
|
rampant-aiPointsScaler=Difficulty Scaling
|
||||||
rampant-addWallResistanceAcid=Increase wall resistance to spitters
|
rampant-addWallResistanceAcid=Increase wall resistance to spitters
|
||||||
|
rampant-useCustomAI=Use Custom AI
|
||||||
|
|
||||||
[mod-setting-description]
|
[mod-setting-description]
|
||||||
rampant-useDumbProjectiles=Turns off homing projectiles for worms and spitters
|
rampant-useDumbProjectiles=Turns off homing projectiles for worms and spitters
|
||||||
@@ -57,4 +62,5 @@ rampant-safeBuildings-trainStops=Make train stops safe from biters
|
|||||||
rampant-attackPlayerThreshold=The score that a chunk must reach for it to contribute to the attack threshold. Increasing reduces player pheromone cloud impact.
|
rampant-attackPlayerThreshold=The score that a chunk must reach for it to contribute to the attack threshold. Increasing reduces player pheromone cloud impact.
|
||||||
rampant-permanentNocturnal=Toggling this will cause Rampant attack waves to spawn at night. DOES NOT turn off vanilla attack groups yet. Works better with Day/Night extender mod.
|
rampant-permanentNocturnal=Toggling this will cause Rampant attack waves to spawn at night. DOES NOT turn off vanilla attack groups yet. Works better with Day/Night extender mod.
|
||||||
rampant-aiPointsScaler=Between 0.0 and 5.0. This scales how many action points the ai gets per logic cycle to perform actions like making attack waves. 0.3 - very easy, 0.75 - easy, 1.0 - medium, 1.25+ - hard
|
rampant-aiPointsScaler=Between 0.0 and 5.0. This scales how many action points the ai gets per logic cycle to perform actions like making attack waves. 0.3 - very easy, 0.75 - easy, 1.0 - medium, 1.25+ - hard
|
||||||
rampant-addWallResistanceAcid=Toggling this will cause a %60 acid resistance to be added to all wall entities to reduce the damage done by spitters to walls back to vanilla levels.
|
rampant-addWallResistanceAcid=Toggling this will cause a %60 acid resistance to be added to all wall entities to reduce the damage done by spitters to walls back to vanilla levels.
|
||||||
|
rampant-useCustomAI=Having this enabled will completely remove the vanilla ai and change how biters build, produce units, and attack.
|
6
make.rkt
6
make.rkt
@@ -77,8 +77,8 @@
|
|||||||
(copyDirectory "prototypes" modFolder)))
|
(copyDirectory "prototypes" modFolder)))
|
||||||
|
|
||||||
(define (run)
|
(define (run)
|
||||||
;; (copyFiles modFolder)
|
(copyFiles modFolder)
|
||||||
;; (copyFiles zipModFolder)
|
(copyFiles zipModFolder)
|
||||||
(makeZip modFolder)
|
;;(makeZip modFolder)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@@ -95,14 +95,14 @@ function spawner_die_animation(variation, tint)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local biter_spawner_powered_tint = {r=1.0, g=1.0, b=1.0, a=1.0}
|
local biter_spawner_powered_tint = {r=1.0, g=0, b=0, a=1.0}
|
||||||
|
|
||||||
data:extend({
|
data:extend({
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
type = "unit-spawner",
|
type = "unit-spawner",
|
||||||
name = "biter-spawner-powered",
|
name = "biter-spawner-hive",
|
||||||
icon = "__base__/graphics/icons/biter-spawner.png",
|
icon = "__base__/graphics/icons/biter-spawner.png",
|
||||||
flags = {"placeable-player", "placeable-enemy", "not-repairable"},
|
flags = {"placeable-player", "placeable-enemy", "not-repairable"},
|
||||||
max_health = 350,
|
max_health = 350,
|
||||||
@@ -148,8 +148,8 @@ data:extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
healing_per_tick = 0.02,
|
healing_per_tick = 0.02,
|
||||||
collision_box = {{-3.2, -2.2}, {2.2, 2.2}},
|
collision_box = {{-6, -6}, {6, 6}},
|
||||||
selection_box = {{-3.5, -2.5}, {2.5, 2.5}},
|
selection_box = {{-6, -6}, {6, 6}},
|
||||||
-- in ticks per 1 pu
|
-- in ticks per 1 pu
|
||||||
pollution_absorbtion_absolute = 20,
|
pollution_absorbtion_absolute = 20,
|
||||||
pollution_absorbtion_proportional = 0.01,
|
pollution_absorbtion_proportional = 0.01,
|
||||||
|
10
settings.lua
10
settings.lua
@@ -172,6 +172,16 @@ data:extend({
|
|||||||
default_value = false,
|
default_value = false,
|
||||||
order = "g[modifier]-a[damage]",
|
order = "g[modifier]-a[damage]",
|
||||||
per_user = false
|
per_user = false
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type = "bool-setting",
|
||||||
|
name = "rampant-useCustomAI",
|
||||||
|
description = "rampant-useCustomAI",
|
||||||
|
setting_type = 'startup',
|
||||||
|
default_value = false,
|
||||||
|
order = "h[total]-a[ai]",
|
||||||
|
per_user = false
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
20
tests.lua
20
tests.lua
@@ -3,6 +3,7 @@ local tests = {}
|
|||||||
local constants = require("libs/Constants")
|
local constants = require("libs/Constants")
|
||||||
local mathUtils = require("libs/MathUtils")
|
local mathUtils = require("libs/MathUtils")
|
||||||
local chunkUtils = require("libs/ChunkUtils")
|
local chunkUtils = require("libs/ChunkUtils")
|
||||||
|
local mapUtils = require("libs/MapUtils")
|
||||||
local baseUtils = require("libs/BaseUtils")
|
local baseUtils = require("libs/BaseUtils")
|
||||||
|
|
||||||
function tests.pheromoneLevels()
|
function tests.pheromoneLevels()
|
||||||
@@ -22,7 +23,7 @@ function tests.pheromoneLevels()
|
|||||||
for i=1,#chunk do
|
for i=1,#chunk do
|
||||||
str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i])
|
str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i])
|
||||||
end
|
end
|
||||||
str = str .. " " .. "p/" .. game.surfaces[1].get_pollution({x=chunk.pX, y=chunk.pY})
|
str = str .. " " .. "p/" .. game.surfaces[1].get_pollution(chunk)
|
||||||
if (chunk.cX == playerChunkX) and (chunk.cY == playerChunkY) then
|
if (chunk.cX == playerChunkX) and (chunk.cY == playerChunkY) then
|
||||||
print("*", chunk.cX, chunk.cY, str)
|
print("*", chunk.cX, chunk.cY, str)
|
||||||
else
|
else
|
||||||
@@ -73,6 +74,14 @@ function tests.findNearestPlayerEnemy()
|
|||||||
print("--")
|
print("--")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function tests.getOffsetChunk(x, y)
|
||||||
|
local playerPosition = game.players[1].position
|
||||||
|
local chunkX = math.floor(playerPosition.x * 0.03125)
|
||||||
|
local chunkY = math.floor(playerPosition.y * 0.03125)
|
||||||
|
local chunk = mapUtils.getChunkByIndex(global.regionMap, chunkX + x, chunkY + y)
|
||||||
|
print(serpent.dump(chunk))
|
||||||
|
end
|
||||||
|
|
||||||
function tests.aiStats()
|
function tests.aiStats()
|
||||||
print(global.natives.points, game.tick, global.natives.state, global.natives.temperament, global.natives.stateTick, global.natives.temperamentTick)
|
print(global.natives.points, game.tick, global.natives.state, global.natives.temperament, global.natives.stateTick, global.natives.temperamentTick)
|
||||||
end
|
end
|
||||||
@@ -99,7 +108,14 @@ function tests.createEnemy(x)
|
|||||||
local playerPosition = game.players[1].position
|
local playerPosition = game.players[1].position
|
||||||
local chunkX = math.floor(playerPosition.x * 0.03125) * 32
|
local chunkX = math.floor(playerPosition.x * 0.03125) * 32
|
||||||
local chunkY = math.floor(playerPosition.y * 0.03125) * 32
|
local chunkY = math.floor(playerPosition.y * 0.03125) * 32
|
||||||
game.surfaces[1].create_entity({name=x, position={chunkX, chunkY}})
|
return game.surfaces[1].create_entity({name=x, position={chunkX, chunkY}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.registeredNest(x)
|
||||||
|
local entity = tests.createEnemy(x)
|
||||||
|
baseUtils.registerEnemyBaseStructure(global.regionMap,
|
||||||
|
entity,
|
||||||
|
nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
function tests.attackOrigin()
|
function tests.attackOrigin()
|
||||||
|
Reference in New Issue
Block a user