1
0
mirror of https://github.com/veden/Rampant.git synced 2025-09-16 09:16:43 +02:00

working adjustments and refactoring

This commit is contained in:
Aaron Veden
2017-11-20 23:27:03 -08:00
parent f6d9c5d02f
commit 4f4945971b
44 changed files with 971 additions and 1834 deletions

View File

@@ -48,7 +48,6 @@ Configure Options not in game menu:
- Pathfinding - Unit groups will use potential fields to perform only single step pathfinding allowing for efficient and dynamic pathing - Pathfinding - Unit groups will use potential fields to perform only single step pathfinding allowing for efficient and dynamic pathing
- Peace mode - If something sets peace mode, Rampant will respect it - Peace mode - If something sets peace mode, Rampant will respect it
- Ion Cannon Reaction - Firing the Ion Cannon will cause nests around the blast site to form into an attack wave and agitate all biters - Ion Cannon Reaction - Firing the Ion Cannon will cause nests around the blast site to form into an attack wave and agitate all biters
- Item Collector + Technology to unlock it - An entity that collects the items on the ground around itself
# Planned Features # Planned Features
@@ -61,6 +60,14 @@ Configure Options not in game menu:
# Version History # Version History
0.15.23 -
- Fixed: Retreat radius being centered on chunk corner instead of on the unit dying
- Fixed: Spitter flamethrower sound fx
- Moved: Item Collector into separate mod
- Balance: Adjusted spitter and worms damages, ranges, and cooldowns to be more inline with vanilla
- Optimization: Reduced memory footprint for faster saving and loading
- Framework: Reorganization of files
0.15.22 - 0.15.22 -
- Contribution - Martok88, Improvement: Added optional attack wave message per player - Contribution - Martok88, Improvement: Added optional attack wave message per player

View File

@@ -8,7 +8,6 @@ local mathUtils = require("libs/MathUtils")
-- constants -- constants
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
local INTERVAL_PROCESS = constants.INTERVAL_PROCESS
-- imported functions -- imported functions
@@ -16,7 +15,7 @@ local roundToNearest = mathUtils.roundToNearest
-- module code -- module code
function upgrade.attempt(natives, world) function upgrade.attempt(natives)
local starting = global.version local starting = global.version
if (global.version == nil) then if (global.version == nil) then
natives.squads = {} natives.squads = {}
@@ -157,25 +156,14 @@ function upgrade.attempt(natives, world)
game.surfaces[1].print("Rampant - Version 0.15.17") game.surfaces[1].print("Rampant - Version 0.15.17")
global.version = constants.VERSION_27 global.version = constants.VERSION_27
end end
if (global.version < constants.VERSION_28) then if (global.version < constants.VERSION_33) then
if (world == nil) then global.world = nil
global.world = {}
world = global.world
end
world.itemCollectorLookup = {}
world.itemCollectorEvents = {}
game.surfaces[1].print("Rampant - Version 0.15.18") game.surfaces[1].print("Rampant - Version 0.15.23")
global.version = constants.VERSION_28 global.version = constants.VERSION_33
end end
if (global.version < constants.VERSION_32) then return starting ~= global.version, natives
game.surfaces[1].print("Rampant - Version 0.15.22")
global.version = constants.VERSION_32
end
return starting ~= global.version, natives, world
end end
function upgrade.compareTable(entities, option, new) function upgrade.compareTable(entities, option, new)

View File

@@ -1,6 +1,5 @@
-- imports -- imports
local entityUtils = require("libs/EntityUtils")
local mapUtils = require("libs/MapUtils") local mapUtils = require("libs/MapUtils")
local unitGroupUtils = require("libs/UnitGroupUtils") local unitGroupUtils = require("libs/UnitGroupUtils")
local chunkProcessor = require("libs/ChunkProcessor") local chunkProcessor = require("libs/ChunkProcessor")
@@ -14,14 +13,10 @@ local aiAttackWave = require("libs/AIAttackWave")
local aiPlanning = require("libs/AIPlanning") local aiPlanning = require("libs/AIPlanning")
local interop = require("libs/Interop") local interop = require("libs/Interop")
local tests = require("tests") local tests = require("tests")
local chunkUtils = require("libs/ChunkUtils")
local upgrade = require("Upgrade") local upgrade = require("Upgrade")
local baseRegisterUtils = require("libs/BaseRegisterUtils")
local mathUtils = require("libs/MathUtils") local mathUtils = require("libs/MathUtils")
local config = require("config") local config = require("config")
local worldProcessor = require("libs/WorldProcessor")
local inventoryUtils = require("libs/InventoryUtils")
local playerUtils = require("libs/PlayerUtils")
local buildUtils = require("libs/BuildUtils")
-- constants -- constants
@@ -30,12 +25,7 @@ local INTERVAL_PROCESS = constants.INTERVAL_PROCESS
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
local DEFINES_INVENTORY_PLAYER_MAIN = defines.inventory.player_main local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local DEFINES_INVENTORY_GOD_MAIN = defines.inventory.god_main
local DEFINES_INVENTORY_PLAYER_QUICKBAR = defines.inventory.player_quickbar
local DEFINES_INVENTORY_GOD_QUICKBAR = defines.inventory.god_quickbar
local ITEM_COLLECTOR_MAX_QUEUE_SIZE = constants.ITEM_COLLECTOR_MAX_QUEUE_SIZE
local AI_MAX_OVERFLOW_POINTS = constants.AI_MAX_OVERFLOW_POINTS local AI_MAX_OVERFLOW_POINTS = constants.AI_MAX_OVERFLOW_POINTS
@@ -49,17 +39,6 @@ local getChunkByPosition = mapUtils.getChunkByPosition
local processPendingChunks = chunkProcessor.processPendingChunks local processPendingChunks = chunkProcessor.processPendingChunks
local buildComplexEntity = buildUtils.buildComplexEntity
local mineComplexEntity = buildUtils.mineComplexEntity
local getPlayerCursorStack = playerUtils.getPlayerCursorStack
local swapItemStack = inventoryUtils.swapItemStack
local swapItemInventory = inventoryUtils.swapItemInventory
local topOffHand = inventoryUtils.topOffHand
local processWorld = worldProcessor.processWorld
local processMap = mapProcessor.processMap local processMap = mapProcessor.processMap
local processPlayers = mapProcessor.processPlayers local processPlayers = mapProcessor.processPlayers
local scanMap = mapProcessor.scanMap local scanMap = mapProcessor.scanMap
@@ -80,23 +59,22 @@ local squadsBeginAttack = squadAttack.squadsBeginAttack
local retreatUnits = squadDefense.retreatUnits local retreatUnits = squadDefense.retreatUnits
local addRemovePlayerEntity = entityUtils.addRemovePlayerEntity local addRemovePlayerEntity = chunkUtils.addRemovePlayerEntity
local unregisterEnemyBaseStructure = baseRegisterUtils.unregisterEnemyBaseStructure local unregisterEnemyBaseStructure = chunkUtils.unregisterEnemyBaseStructure
local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure
local makeImmortalEntity = entityUtils.makeImmortalEntity local makeImmortalEntity = chunkUtils.makeImmortalEntity
local processBases = baseProcessor.processBases local processBases = baseProcessor.processBases
local mRandom = math.random local mRandom = math.random
local getPlayerInventory = playerUtils.getPlayerInventory local positionToChunkXY = mapUtils.positionToChunkXY
-- local references to global -- local references to global
local regionMap -- manages the chunks that make up the game world local regionMap -- manages the chunks that make up the game world
local natives -- manages the enemy units, structures, and ai local natives -- manages the enemy units, structures, and ai
local pendingChunks -- chunks that have yet to be processed by the mod local pendingChunks -- chunks that have yet to be processed by the mod
local world -- manages the player built structures and any other events in the world
-- hook functions -- hook functions
@@ -110,13 +88,10 @@ local function onIonCannonFired(event)
if (natives.points > AI_MAX_OVERFLOW_POINTS) then if (natives.points > AI_MAX_OVERFLOW_POINTS) then
natives.points = AI_MAX_OVERFLOW_POINTS natives.points = AI_MAX_OVERFLOW_POINTS
end end
local chunk = getChunkByPosition(regionMap, event.position.x, event.position.y) local chunkX, chunkY = positionToChunkXY(event.position)
if chunk then local chunk = getChunkByPosition(regionMap, chunkX, chunkY)
rallyUnits(chunk, if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
regionMap, rallyUnits(chunk, regionMap, surface, natives, event.tick)
surface,
natives,
event.tick)
end end
end end
end end
@@ -134,7 +109,6 @@ local function onLoad()
regionMap = global.regionMap regionMap = global.regionMap
natives = global.natives natives = global.natives
pendingChunks = global.pendingChunks pendingChunks = global.pendingChunks
world = global.world
hookEvents() hookEvents()
end end
@@ -158,9 +132,28 @@ local function rebuildRegionMap()
regionMap.processQueue = {} regionMap.processQueue = {}
regionMap.processIndex = 1 regionMap.processIndex = 1
regionMap.scanIndex = 1 regionMap.scanIndex = 1
regionMap.chunkToHives = {}
regionMap.chunkToNests = {}
regionMap.chunkToWorms = {}
regionMap.chunkToRetreats = {}
regionMap.chunkToRallys = {}
regionMap.chunkToPlayerBase = {}
regionMap.chunkToResource = {}
-- preallocating memory to be used in code, making it fast by reducing garbage generated. -- preallocating memory to be used in code, making it fast by reducing garbage generated.
regionMap.neighbors = { nil, nil, nil, nil, nil, nil, nil, nil } regionMap.neighbors = { SENTINEL_IMPASSABLE_CHUNK,
regionMap.cardinalNeighbors = { nil, nil, nil, nil } SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK }
regionMap.cardinalNeighbors = { SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK,
SENTINEL_IMPASSABLE_CHUNK }
regionMap.chunkTiles = {} regionMap.chunkTiles = {}
regionMap.position = {x=0, regionMap.position = {x=0,
y=0} y=0}
@@ -242,7 +235,7 @@ end
local function onConfigChanged() local function onConfigChanged()
local upgraded local upgraded
upgraded, natives, world = upgrade.attempt(natives, world) upgraded, natives = upgrade.attempt(natives)
if upgraded and onModSettingsChange(nil) then if upgraded and onModSettingsChange(nil) then
rebuildRegionMap() rebuildRegionMap()
end end
@@ -271,8 +264,6 @@ local function onTick(event)
cleanSquads(natives) cleanSquads(natives)
regroupSquads(natives) regroupSquads(natives)
processWorld(surface, world, tick)
processPlayers(players, regionMap, surface, natives, tick) processPlayers(players, regionMap, surface, natives, tick)
if natives.useCustomAI then if natives.useCustomAI then
@@ -288,7 +279,7 @@ local function onTick(event)
end end
local function onBuild(event) local function onBuild(event)
local entity = buildComplexEntity(event.created_entity, world) local entity = event.created_entity
addRemovePlayerEntity(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
@@ -298,24 +289,20 @@ local function onBuild(event)
end end
local function onMine(event) local function onMine(event)
mineComplexEntity(addRemovePlayerEntity(regionMap, addRemovePlayerEntity(regionMap, event.entity, natives, false, false)
event.entity,
natives,
false,
false),
world)
end end
local function onDeath(event) local function onDeath(event)
local entity = event.entity local entity = event.entity
local surface = entity.surface local surface = entity.surface
if (surface.index == 1) then if (surface.index == 1) then
local entityPosition = entity.position
local chunkX, chunkY = positionToChunkXY(entityPosition)
if (entity.force.name == "enemy") then if (entity.force.name == "enemy") then
if (entity.type == "unit") then if (entity.type == "unit") then
local entityPosition = entity.position local deathChunk = getChunkByPosition(regionMap, chunkX, chunkY)
local deathChunk = getChunkByPosition(regionMap, entityPosition.x, entityPosition.y)
if deathChunk then if (deathChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
-- drop death pheromone where unit died -- drop death pheromone where unit died
deathScent(deathChunk) deathScent(deathChunk)
@@ -324,18 +311,14 @@ local function onDeath(event)
retreatUnits(deathChunk, retreatUnits(deathChunk,
entityPosition, entityPosition,
convertUnitGroupToSquad(natives, convertUnitGroupToSquad(natives, entity.unit_group),
entity.unit_group),
regionMap, regionMap,
surface, surface,
natives, natives,
tick) tick)
if (mRandom() < natives.rallyThreshold) and not surface.peaceful_mode then if (mRandom() < natives.rallyThreshold) and not surface.peaceful_mode then
rallyUnits(deathChunk, rallyUnits(deathChunk, regionMap, surface, natives, tick)
regionMap,
surface,
natives,
tick)
end end
end end
end end
@@ -345,32 +328,24 @@ local function onDeath(event)
end end
elseif (entity.force.name == "player") then elseif (entity.force.name == "player") then
local creditNatives = false local creditNatives = false
local entityPosition = entity.position
if (event.force ~= nil) and (event.force.name == "enemy") then if (event.force ~= nil) and (event.force.name == "enemy") then
creditNatives = true creditNatives = true
local victoryChunk = getChunkByPosition(regionMap, entityPosition.x, entityPosition.y) local victoryChunk = getChunkByPosition(regionMap, chunkX, chunkY)
if victoryChunk then if (victoryChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
victoryScent(victoryChunk, entity.type) victoryScent(victoryChunk, entity.type)
end end
end end
if creditNatives and natives.safeBuildings and (natives.safeEntities[entity.type] or natives.safeEntityName[entity.name]) then if creditNatives and natives.safeBuildings and (natives.safeEntities[entity.type] or natives.safeEntityName[entity.name]) then
makeImmortalEntity(surface, entity) makeImmortalEntity(surface, entity)
else else
mineComplexEntity(addRemovePlayerEntity(regionMap, addRemovePlayerEntity(regionMap, entity, natives, false, creditNatives)
entity,
natives,
false,
creditNatives),
world,
true)
end end
end end
end end
end end
local function onEnemyBaseBuild(event) local function onEnemyBaseBuild(event)
local entity = event.entity registerEnemyBaseStructure(regionMap, event.entity, nil)
registerEnemyBaseStructure(regionMap, entity, nil)
end end
local function onSurfaceTileChange(event) local function onSurfaceTileChange(event)
@@ -384,128 +359,30 @@ local function onInit()
global.regionMap = {} global.regionMap = {}
global.pendingChunks = {} global.pendingChunks = {}
global.natives = {} global.natives = {}
global.world = {}
regionMap = global.regionMap regionMap = global.regionMap
natives = global.natives natives = global.natives
pendingChunks = global.pendingChunks pendingChunks = global.pendingChunks
world = global.world
onConfigChanged() onConfigChanged()
hookEvents() hookEvents()
end end
-- local function onBuildingRotated(event)
-- end
local function onCursorChange(event)
if settings.startup["rampant-enableBuildings"].value then
local player = game.players[event.player_index]
swapItemStack(getPlayerCursorStack(player),
"item-collector-base-rampant",
"item-collector-base-overlay-rampant")
local inventory = getPlayerInventory(player,
DEFINES_INVENTORY_PLAYER_QUICKBAR,
DEFINES_INVENTORY_GOD_QUICKBAR)
topOffHand(inventory,
player.cursor_stack,
"item-collector-base-rampant",
"item-collector-base-overlay-rampant")
inventory = getPlayerInventory(player,
DEFINES_INVENTORY_PLAYER_MAIN,
DEFINES_INVENTORY_GOD_MAIN)
topOffHand(inventory,
player.cursor_stack,
"item-collector-base-rampant",
"item-collector-base-overlay-rampant")
end
end
local function onPlayerDropped(event)
if settings.startup["rampant-enableBuildings"].value then
local item = event.entity
if item.valid then
swapItemStack(item.stack,
"item-collector-base-overlay-rampant",
"item-collector-base-rampant")
end
end
end
local function onMainInventoryChanged(event)
if settings.startup["rampant-enableBuildings"].value then
local player = game.players[event.player_index]
local inventory = getPlayerInventory(player,
DEFINES_INVENTORY_PLAYER_MAIN,
DEFINES_INVENTORY_GOD_MAIN)
swapItemInventory(inventory,
"item-collector-base-overlay-rampant",
"item-collector-base-rampant")
end
end
local function onQuickInventoryChanged(event)
if settings.startup["rampant-enableBuildings"].value then
local player = game.players[event.player_index]
local inventory = getPlayerInventory(player,
DEFINES_INVENTORY_PLAYER_QUICKBAR,
DEFINES_INVENTORY_GOD_QUICKBAR)
swapItemInventory(inventory,
"item-collector-base-overlay-rampant",
"item-collector-base-rampant")
topOffHand(inventory,
player.cursor_stack,
"item-collector-base-rampant",
"item-collector-base-overlay-rampant")
end
end
local function onScannedSector(event)
local radar = event.radar
if (radar.name == "item-collector-base-rampant") then
local count = #world.itemCollectorEvents
if (count <= ITEM_COLLECTOR_MAX_QUEUE_SIZE) then
world.itemCollectorEvents[count+1] = radar.unit_number
end
end
end
-- hooks -- hooks
script.on_init(onInit) script.on_init(onInit)
script.on_load(onLoad) script.on_load(onLoad)
script.on_event(defines.events.on_runtime_mod_setting_changed, script.on_event(defines.events.on_runtime_mod_setting_changed, onModSettingsChange)
onModSettingsChange)
script.on_configuration_changed(onConfigChanged) script.on_configuration_changed(onConfigChanged)
-- script.on_event(defines.events.on_player_rotated_entity,
-- onBuildingRotated)
script.on_event(defines.events.on_player_built_tile, onSurfaceTileChange) script.on_event(defines.events.on_player_built_tile, onSurfaceTileChange)
script.on_event(defines.events.on_player_cursor_stack_changed, script.on_event(defines.events.on_biter_base_built, onEnemyBaseBuild)
onCursorChange)
script.on_event(defines.events.on_player_main_inventory_changed,
onMainInventoryChanged)
script.on_event(defines.events.on_player_quickbar_inventory_changed,
onQuickInventoryChanged)
script.on_event(defines.events.on_biter_base_built,
onEnemyBaseBuild)
script.on_event({defines.events.on_player_mined_entity, script.on_event({defines.events.on_player_mined_entity,
defines.events.on_robot_mined_entity}, defines.events.on_robot_mined_entity}, onMine)
onMine)
script.on_event({defines.events.on_built_entity, script.on_event({defines.events.on_built_entity,
defines.events.on_robot_built_entity}, defines.events.on_robot_built_entity}, onBuild)
onBuild)
script.on_event(defines.events.on_player_dropped_item,
onPlayerDropped)
script.on_event(defines.events.on_sector_scanned,
onScannedSector)
script.on_event(defines.events.on_entity_died, onDeath) script.on_event(defines.events.on_entity_died, onDeath)
script.on_event(defines.events.on_tick, onTick) script.on_event(defines.events.on_tick, onTick)
script.on_event(defines.events.on_chunk_generated, onChunkGenerated) script.on_event(defines.events.on_chunk_generated, onChunkGenerated)

View File

@@ -11,8 +11,3 @@ require("prototypes/enemies/UnitFireSpitters")
require("prototypes/enemies/UnitTendril") require("prototypes/enemies/UnitTendril")
if settings.startup["rampant-enableBuildings"].value then
require("prototypes/buildings/ItemCollector")
end

View File

@@ -1,7 +1,7 @@
{ {
"name" : "Rampant", "name" : "Rampant",
"factorio_version" : "0.15", "factorio_version" : "0.15",
"version" : "0.15.22", "version" : "0.15.23",
"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",

View File

@@ -4,8 +4,9 @@ local aiAttackWave = {}
local constants = require("Constants") local constants = require("Constants")
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local chunkUtils = require("ChunkUtils")
local unitGroupUtils = require("UnitGroupUtils") local unitGroupUtils = require("UnitGroupUtils")
local neighborUtils = require("NeighborUtils") local movementUtils = require("MovementUtils")
package.path = "../?.lua;" .. package.path package.path = "../?.lua;" .. package.path
local config = require("config") local config = require("config")
@@ -18,19 +19,21 @@ local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
local AI_SQUAD_COST = constants.AI_SQUAD_COST local AI_SQUAD_COST = constants.AI_SQUAD_COST
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
local RALLY_TRIGGERED = constants.RALLY_TRIGGERED
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE
local PASSABLE = constants.PASSABLE
local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
local CHUNK_SIZE = constants.CHUNK_SIZE
local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE 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 NEST_COUNT = constants.NEST_COUNT local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local PASSABLE = constants.PASSABLE
-- imported functions -- imported functions
@@ -38,9 +41,13 @@ local mRandom = math.random
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
local getNestCount = chunkUtils.getNestCount
local getRallyTick = chunkUtils.getRallyTick
local setRallyTick = chunkUtils.setRallyTick
local getNeighborChunks = mapUtils.getNeighborChunks local getNeighborChunks = mapUtils.getNeighborChunks
local getChunkByIndex = mapUtils.getChunkByIndex local getChunkByPosition = mapUtils.getChunkByPosition
local scoreNeighborsForFormation = neighborUtils.scoreNeighborsForFormation local scoreNeighborsForFormation = movementUtils.scoreNeighborsForFormation
local createSquad = unitGroupUtils.createSquad local createSquad = unitGroupUtils.createSquad
local attackWaveScaling = config.attackWaveScaling local attackWaveScaling = config.attackWaveScaling
@@ -74,21 +81,21 @@ local function scoreUnitGroupLocation(neighborChunk)
return neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] return neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE]
end end
local function validUnitGroupLocation(neighborChunk) local function validUnitGroupLocation(regionMap, neighborChunk)
return (neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS) and (neighborChunk[NEST_COUNT] == 0) return neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS and (getNestCount(regionMap, neighborChunk) == 0)
end end
function aiAttackWave.rallyUnits(chunk, regionMap, surface, natives, tick) function aiAttackWave.rallyUnits(chunk, regionMap, surface, natives, tick)
if ((tick - chunk[RALLY_TRIGGERED] > INTERVAL_LOGIC) and (natives.points >= AI_VENGENCE_SQUAD_COST) and if ((tick - getRallyTick(regionMap, chunk) > INTERVAL_LOGIC) and (natives.points >= AI_VENGENCE_SQUAD_COST) and
(#natives.squads < natives.maxSquads)) then (#natives.squads < natives.maxSquads)) then
chunk[RALLY_TRIGGERED] = tick setRallyTick(regionMap, chunk, tick)
local cX = chunk.cX local cX = chunk.x
local cY = chunk.cY local cY = chunk.y
for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE do for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE, 32 do
for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE do for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE, 32 do
if (x ~= cX) and (y ~= cY) then if (x ~= cX) and (y ~= cY) then
local rallyChunk = getChunkByIndex(regionMap, x, y) local rallyChunk = getChunkByPosition(regionMap, x, y)
if rallyChunk and (rallyChunk[NEST_COUNT] ~= 0) then if (rallyChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (getNestCount(regionMap, rallyChunk) > 0) then
aiAttackWave.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST) aiAttackWave.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST)
if (natives.points < AI_VENGENCE_SQUAD_COST) and (#natives.squads < natives.maxSquads) then if (natives.points < AI_VENGENCE_SQUAD_COST) and (#natives.squads < natives.maxSquads) then
return return
@@ -105,16 +112,17 @@ function aiAttackWave.formSquads(regionMap, surface, natives, chunk, cost)
if valid and (mRandom() < natives.formSquadThreshold) then if valid and (mRandom() < natives.formSquadThreshold) then
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(regionMap, chunk.cX, chunk.cY), local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(regionMap, chunk.x, chunk.y),
validUnitGroupLocation, validUnitGroupLocation,
scoreUnitGroupLocation) scoreUnitGroupLocation,
if squadPath then regionMap)
local squadPosition = surface.find_non_colliding_position("biter-spawner-hive", if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then
local squadPosition = surface.find_non_colliding_position("biter-spawner-hive-rampant",
positionFromDirectionAndChunk(squadDirection, positionFromDirectionAndChunk(squadDirection,
chunk, chunk,
regionMap.position, regionMap.position,
0.98), 0.98),
32, CHUNK_SIZE,
4) 4)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface, natives) local squad = createSquad(squadPosition, surface, natives)

View File

@@ -3,21 +3,28 @@ local aiPredicates = {}
-- imports -- imports
local constants = require("Constants") local constants = require("Constants")
local nocturnalUtils = require("NocturnalUtils")
-- constants -- constants
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
local AI_STATE_NOCTURNAL = constants.AI_STATE_NOCTURNAL
-- imported functions -- imported functions
local canAttackNocturnal = nocturnalUtils.canAttack
-- module code -- module code
function aiPredicates.canAttack(natives, surface) function aiPredicates.canAttack(natives, surface)
return (((natives.state == AI_STATE_AGGRESSIVE) or canAttackNocturnal(natives, surface)) return (((natives.state == AI_STATE_AGGRESSIVE) or aiPredicates.canAttackDark(natives, surface))
and not surface.peaceful_mode and (#natives.squads < natives.maxSquads)) and not surface.peaceful_mode and (#natives.squads < natives.maxSquads))
end end
function aiPredicates.isDark(surface)
return surface.darkness > 0.65
end
function aiPredicates.canAttackDark(natives, surface)
return aiPredicates.isDark(surface) and natives.state == AI_STATE_NOCTURNAL
end
return aiPredicates return aiPredicates

View File

@@ -1,118 +0,0 @@
local baseRegisterUtils = {}
-- imports
local constants = require("Constants")
local entityUtils = require("EntityUtils")
-- constants
local NEST_COUNT = constants.NEST_COUNT
local WORM_COUNT = constants.WORM_COUNT
local NEST_BASE = constants.NEST_BASE
local WORM_BASE = constants.WORM_BASE
-- imported functions
local getEntityOverlapChunks = entityUtils.getEntityOverlapChunks
-- module code
function baseRegisterUtils.addEnemyStructureToChunk(chunk, entity, base)
local indexChunk
local indexBase
local countChunk
if (entity.type == "unit-spawner") then
indexChunk = chunk[NEST_BASE]
if base then
if base.hives[entity.unit_number] then
indexBase = base.hives
else
indexBase = base.nests
end
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 baseRegisterUtils.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
if base.hives[entity.unit_number] then
indexBase = base.hives
else
indexBase = base.nests
end
elseif (entity.type == "turret") then
indexBase = base.worms
end
indexBase[entity.unit_number] = nil
end
chunk[countChunk] = chunk[countChunk] - 1
end
function baseRegisterUtils.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
baseRegisterUtils.addEnemyStructureToChunk(leftTop, entity, base)
end
if rightTop then
baseRegisterUtils.addEnemyStructureToChunk(rightTop, entity, base)
end
if leftBottom then
baseRegisterUtils.addEnemyStructureToChunk(leftBottom, entity, base)
end
if rightBottom then
baseRegisterUtils.addEnemyStructureToChunk(rightBottom, entity, base)
end
end
end
function baseRegisterUtils.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
baseRegisterUtils.removeEnemyStructureFromChunk(leftTop, entity)
end
if rightTop then
baseRegisterUtils.removeEnemyStructureFromChunk(rightTop, entity)
end
if leftBottom then
baseRegisterUtils.removeEnemyStructureFromChunk(leftBottom, entity)
end
if rightBottom then
baseRegisterUtils.removeEnemyStructureFromChunk(rightBottom, entity)
end
end
end
return baseRegisterUtils

View File

@@ -5,7 +5,7 @@ local baseUtils = {}
local mathUtils = require("MathUtils") local mathUtils = require("MathUtils")
local constants = require("Constants") local constants = require("Constants")
local tendrilUtils = require("TendrilUtils") -- local tendrilUtils = require("TendrilUtils")
local nestUtils = require("NestUtils") local nestUtils = require("NestUtils")
@@ -26,7 +26,7 @@ local buildHive = nestUtils.buildHive
local mFloor = math.floor local mFloor = math.floor
local buildTendril = tendrilUtils.buildTendril -- local buildTendril = tendrilUtils.buildTendril
local mRandom = math.random local mRandom = math.random
@@ -68,7 +68,7 @@ function baseUtils.createBase(regionMap, natives, position, surface, tick)
if not buildHive(regionMap, base, surface) then if not buildHive(regionMap, base, surface) then
return nil return nil
end end
buildTendril(regionMap, natives, base, surface, tick) -- buildTendril(regionMap, natives, base, surface, tick)
bases[#bases+1] = base bases[#bases+1] = base
return base return base
end end

View File

@@ -1,78 +0,0 @@
local buildUtils = {}
-- module code
function buildUtils.buildComplexEntity(entity, world)
if (entity.name == "item-collector-base-overlay-rampant") or (entity.name == "item-collector-base-rampant") then
local surface = entity.surface
local x = entity.position.x
local y = entity.position.y
local chest
local position = entity.position
local force = entity.force
if (entity.name == "item-collector-base-overlay-rampant") then
entity.destroy()
chest = surface.create_entity({name = "item-collector-chest-rampant",
position = position,
force = force})
entity = surface.create_entity({name="item-collector-base-rampant",
position = position,
force = force})
else
local ghosts = surface.find_entities_filtered({name="entity-ghost",
area={{x=x-1,
y=y-1},
{x=x+1,
y=y+1}},
limit=1})
if (#ghosts > 0) then
local ghost = ghosts[1]
if (ghost.ghost_name == "item-collector-chest-rampant") then
local conflicts
conflicts, chest = ghost.revive()
end
else
chest = surface.create_entity({name = "item-collector-chest-rampant",
position = position,
force = force})
end
end
if chest and chest.valid then
local pair = { chest, entity }
world.itemCollectorLookup[chest.unit_number] = pair
world.itemCollectorLookup[entity.unit_number] = pair
entity.backer_name = ""
end
end
return entity
end
function buildUtils.mineComplexEntity(entity, world, destroyed)
if (entity.name == "item-collector-chest-rampant") or (entity.name == "item-collector-base-rampant") then
local pair = world.itemCollectorLookup[entity.unit_number]
if pair then
local chest = pair[1]
local dish = pair[2]
if chest and chest.valid then
world.itemCollectorLookup[chest.unit_number] = nil
if destroyed and (entity == chest) then
chest.die()
elseif (entity ~= chest) then
chest.destroy()
end
end
if dish and dish.valid then
world.itemCollectorLookup[dish.unit_number] = nil
if destroyed and (entity ~= dish) then
dish.die()
elseif (entity ~= dish) then
dish.destroy()
end
end
end
end
return entity
end
return buildUtils

View File

@@ -9,6 +9,8 @@ local constants = require("Constants")
local CHUNK_SIZE = constants.CHUNK_SIZE local CHUNK_SIZE = constants.CHUNK_SIZE
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions -- imported functions
local remakeChunk = chunkUtils.remakeChunk local remakeChunk = chunkUtils.remakeChunk
@@ -39,26 +41,31 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin
local x = topLeft.x local x = topLeft.x
local y = topLeft.y local y = topLeft.y
local chunk = createChunk(x, y) local chunk = createChunk(x, y)
areaBoundingBox[1] = chunk
offset[1] = x + CHUNK_SIZE
offset[2] = y + CHUNK_SIZE
local chunkX = chunk.cX chunk = checkChunkPassability(chunkTiles, chunk, surface)
if regionMap[chunkX] == nil then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
regionMap[chunkX] = {}
end areaBoundingBox[1] = chunk
regionMap[chunkX][chunk.cY] = chunk offset[1] = x + CHUNK_SIZE
offset[2] = y + CHUNK_SIZE
checkChunkPassability(chunkTiles, chunk, surface)
if vanillaAI then if vanillaAI then
registerChunkEnemies(chunk, surface, query) registerChunkEnemies(regionMap, chunk, surface, query)
else else
remakeChunk(regionMap, chunk, surface, natives, tick, query) remakeChunk(regionMap, chunk, surface, natives, tick, query)
end
scoreChunk(regionMap, chunk, surface, natives, query)
local chunkX = chunk.x
if regionMap[chunkX] == nil then
regionMap[chunkX] = {}
end
regionMap[chunkX][chunk.y] = chunk
processQueue[#processQueue+1] = chunk
end end
scoreChunk(chunk, surface, natives, query)
processQueue[#processQueue+1] = chunk
end end
end end

View File

@@ -3,31 +3,25 @@ local chunkUtils = {}
-- imports -- imports
local constants = require("Constants") local constants = require("Constants")
local mapUtils = require("MapUtils")
local baseUtils = require("BaseUtils")
local baseRegisterUtils = require("BaseRegisterUtils")
-- constants -- constants
local DEFINES_DIRECTION_EAST = defines.direction.east
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local BASE_PHEROMONE = constants.BASE_PHEROMONE local BASE_PHEROMONE = constants.BASE_PHEROMONE
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
local NEST_BASE = constants.NEST_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 RESOURCE_GENERATOR = constants.RESOURCE_GENERATOR
local CHUNK_NORTH_SOUTH = constants.CHUNK_NORTH_SOUTH local CHUNK_NORTH_SOUTH = constants.CHUNK_NORTH_SOUTH
local CHUNK_EAST_WEST = constants.CHUNK_EAST_WEST local CHUNK_EAST_WEST = constants.CHUNK_EAST_WEST
local PASSABLE = constants.PASSABLE
local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE
@@ -35,14 +29,13 @@ local CHUNK_TICK = constants.CHUNK_TICK
local PATH_RATING = constants.PATH_RATING local PATH_RATING = constants.PATH_RATING
local RETREAT_TRIGGERED = constants.RETREAT_TRIGGERED local PASSABLE = constants.PASSABLE
local RALLY_TRIGGERED = constants.RALLY_TRIGGERED
-- imported functions -- imported functions
local findNearbyBase = baseUtils.findNearbyBase local getChunkByPosition = mapUtils.getChunkByPosition
local createBase = baseUtils.createBase
local addEnemyStructureToChunk = baseRegisterUtils.addEnemyStructureToChunk local mFloor = math.floor
-- module code -- module code
@@ -109,6 +102,126 @@ local function spotCheck(x, y, get_tile)
return valid return valid
end end
local function addEnemyStructureToChunk(regionMap, chunk, entity, base)
local lookup
if (entity.type == "unit-spawner") then
lookup = regionMap.chunkToNests
elseif (entity.type == "turret") then
lookup = regionMap.chunkToWorms
else
return
end
local entityCollection = lookup[chunk]
if not entityCollection then
entityCollection = {}
lookup[chunk] = entityCollection
end
entityCollection[#entityCollection+1] = entity
-- if base then
-- local baseCollection = regionMap.chunkToBases[chunk]
-- if not baseCollection then
-- baseCollection = {}
-- regionMap.chunkToBases[chunk] = baseCollection
-- end
-- baseCollection[base.id] = chunk
-- end
end
local function removeEnemyStructureFromChunk(regionMap, chunk, entity)
local lookup
if (entity.type == "unit-spawner") then
lookup = regionMap.chunkToNests
elseif (entity.type == "turret") then
lookup = regionMap.chunkToWorms
else
return
end
-- local base = indexChunk[entity.unit_number]
-- local indexBase
-- if base then
-- if (entity.type == "unit-spawner") then
-- if base.hives[entity.unit_number] then
-- indexBase = base.hives
-- else
-- indexBase = base.nests
-- end
-- elseif (entity.type == "turret") then
-- indexBase = base.worms
-- end
-- indexBase[entity.unit_number] = nil
-- end
local collection = lookup[chunk]
if collection then
for i=1,#collection do
local e = collection[i]
if e.valid and (e == entity) then
table.remove(collection, i)
break
end
end
end
end
local function getEntityOverlapChunks(regionMap, entity)
local boundingBox = entity.prototype.selection_box or entity.prototype.collision_box;
local leftTopChunk = SENTINEL_IMPASSABLE_CHUNK
local rightTopChunk = SENTINEL_IMPASSABLE_CHUNK
local leftBottomChunk = SENTINEL_IMPASSABLE_CHUNK
local rightBottomChunk = SENTINEL_IMPASSABLE_CHUNK
if (boundingBox ~= nil) then
local center = entity.position
local topXOffset
local topYOffset
local bottomXOffset
local bottomYOffset
if (entity.direction == DEFINES_DIRECTION_EAST) then
topXOffset = boundingBox.left_top.y
topYOffset = boundingBox.left_top.x
bottomXOffset = boundingBox.right_bottom.y
bottomYOffset = boundingBox.right_bottom.x
else
topXOffset = boundingBox.left_top.x
topYOffset = boundingBox.left_top.y
bottomXOffset = boundingBox.right_bottom.x
bottomYOffset = boundingBox.right_bottom.y
end
local leftTopChunkX = mFloor(center.x + topXOffset)
local leftTopChunkY = mFloor(center.y + topYOffset)
-- used to force things on chunk boundary to not spill over 0.0001
local rightTopChunkX = mFloor(center.x + bottomXOffset - 0.0001)
local rightTopChunkY = leftTopChunkY
-- used to force things on chunk boundary to not spill over 0.0001
local leftBottomChunkX = leftTopChunkX
local leftBottomChunkY = mFloor(center.y + bottomYOffset - 0.0001)
local rightBottomChunkX = rightTopChunkX
local rightBottomChunkY = leftBottomChunkY
leftTopChunk = getChunkByPosition(regionMap, leftTopChunkX, leftTopChunkY)
if (leftTopChunkX ~= rightTopChunkX) then
rightTopChunk = getChunkByPosition(regionMap, rightTopChunkX, rightTopChunkY)
end
if (leftTopChunkY ~= leftBottomChunkY) then
leftBottomChunk = getChunkByPosition(regionMap, leftBottomChunkX, leftBottomChunkY)
end
if (leftTopChunkX ~= rightBottomChunkX) and (leftTopChunkY ~= rightBottomChunkY) then
rightBottomChunk = getChunkByPosition(regionMap, rightBottomChunkX, rightBottomChunkY)
end
end
return leftTopChunk, rightTopChunk, leftBottomChunk, rightBottomChunk
end
-- external functions
function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface) function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
local x = chunk.x local x = chunk.x
local y = chunk.y local y = chunk.y
@@ -139,12 +252,17 @@ function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
pass = CHUNK_NORTH_SOUTH pass = CHUNK_NORTH_SOUTH
else else
pass = CHUNK_IMPASSABLE pass = CHUNK_IMPASSABLE
end end
end end
else else
chunk[PATH_RATING] = 1 chunk[PATH_RATING] = 1
end end
chunk[PASSABLE] = pass if (pass == CHUNK_IMPASSABLE) then
return SENTINEL_IMPASSABLE_CHUNK
else
chunk[PASSABLE] = pass
return chunk
end
end end
function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQuery) function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQuery)
@@ -155,7 +273,7 @@ function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQu
for f=1, #enemies do for f=1, #enemies do
local enemy = enemies[f] local enemy = enemies[f]
local entityType = enemies[f].type local entityType = enemies[f].type
if not ((enemy.name == "small-tendril-biter-rampant") or (enemy.name == "biter-spawner-hive")) then if not ((enemy.name == "small-tendril-biter-rampant") or (enemy.name == "biter-spawner-hive-rampant")) then
if (entityType == "unit-spawner") then if (entityType == "unit-spawner") then
points = points + 3 points = points + 3
elseif (entityType == "turret") then elseif (entityType == "turret") then
@@ -166,13 +284,13 @@ function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQu
enemy.destroy() enemy.destroy()
end end
end end
local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick) -- local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
if foundBase then -- if foundBase then
foundBase.upgradePoints = foundBase.upgradePoints + points -- foundBase.upgradePoints = foundBase.upgradePoints + points
end -- end
end end
function chunkUtils.registerChunkEnemies(chunk, surface, tempQuery) function chunkUtils.registerChunkEnemies(regionMap, chunk, surface, tempQuery)
tempQuery.force = "enemy" tempQuery.force = "enemy"
local enemies = surface.find_entities_filtered(tempQuery) local enemies = surface.find_entities_filtered(tempQuery)
@@ -180,15 +298,61 @@ function chunkUtils.registerChunkEnemies(chunk, surface, tempQuery)
local enemy = enemies[i] local enemy = enemies[i]
local enemyType = enemy.type local enemyType = enemy.type
if (enemyType == "unit-spawner") or (enemyType == "turret") then if (enemyType == "unit-spawner") or (enemyType == "turret") then
addEnemyStructureToChunk(chunk, enemy, nil) addEnemyStructureToChunk(regionMap, chunk, enemy, nil)
end end
end end
end end
function chunkUtils.scoreChunk(chunk, surface, natives, tempQuery) function chunkUtils.getNestCount(regionMap, chunk)
local nests = regionMap.chunkToNests[chunk]
return (nests and #nests) or 0
end
function chunkUtils.getWormCount(regionMap, chunk)
local worms = regionMap.chunkToWorms[chunk]
return (worms and #worms) or 0
end
function chunkUtils.getRetreatTick(regionMap, chunk)
return regionMap.chunkToRetreats[chunk] or 0
end
function chunkUtils.getRallyTick(regionMap, chunk)
return regionMap.chunkToRallys[chunk] or 0
end
function chunkUtils.setRallyTick(regionMap, chunk, tick)
regionMap.chunkToRallys[chunk] = tick
end
function chunkUtils.setRetreatTick(regionMap, chunk, tick)
regionMap.chunkToRetreats[chunk] = tick
end
function chunkUtils.setResourceGenerator(regionMap, chunk, playerGenerator)
regionMap.chunkToResource[chunk] = playerGenerator
end
function chunkUtils.getResourceGenerator(regionMap, chunk)
return regionMap.chunkToResource[chunk] or 0
end
function chunkUtils.getPlayerBaseGenerator(regionMap, chunk)
return regionMap.chunkToPlayerBase[chunk] or 0
end
function chunkUtils.setPlayerBaseGenerator(regionMap, chunk, playerGenerator)
regionMap.chunkToPlayerBase[chunk] = playerGenerator
end
function chunkUtils.addPlayerBaseGenerator(regionMap, chunk, playerGenerator)
regionMap.chunkToPlayerBase[chunk] = regionMap.chunkToPlayerBase[chunk] + playerGenerator
end
function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tempQuery)
tempQuery.force = nil tempQuery.force = nil
tempQuery.type = "resource" tempQuery.type = "resource"
chunk[RESOURCE_GENERATOR] = surface.count_entities_filtered(tempQuery) * 0.001 chunkUtils.setResourceGenerator(regionMap, chunk, surface.count_entities_filtered(tempQuery) * 0.001)
tempQuery.type = nil tempQuery.type = nil
tempQuery.force = "player" tempQuery.force = "player"
@@ -207,36 +371,27 @@ function chunkUtils.scoreChunk(chunk, surface, natives, tempQuery)
end end
local entityScore = BUILDING_PHEROMONES[entityType] local entityScore = BUILDING_PHEROMONES[entityType]
if (entityScore ~= nil) then if entityScore then
playerObjects = playerObjects + entityScore playerObjects = playerObjects + entityScore
end end
end end
chunk[PLAYER_BASE_GENERATOR] = playerObjects chunkUtils.setPlayerBaseGenerator(regionMap, chunk, playerObjects)
end end
function chunkUtils.createChunk(topX, topY) function chunkUtils.createChunk(topX, topY)
local chunk = { local chunk = {
x = topX, x = topX,
y = topY, y = topY
cX = topX * 0.03125,
cY = topY * 0.03125
} }
chunk[MOVEMENT_PHEROMONE] = 0 chunk[MOVEMENT_PHEROMONE] = 0
chunk[BASE_PHEROMONE] = 0 chunk[BASE_PHEROMONE] = 0
chunk[PLAYER_PHEROMONE] = 0 chunk[PLAYER_PHEROMONE] = 0
chunk[RESOURCE_PHEROMONE] = 0 chunk[RESOURCE_PHEROMONE] = 0
chunk[PLAYER_BASE_GENERATOR] = 0
chunk[RESOURCE_GENERATOR] = 0
chunk[PASSABLE] = 0 chunk[PASSABLE] = 0
chunk[CHUNK_TICK] = 0 chunk[CHUNK_TICK] = 0
chunk[RETREAT_TRIGGERED] = 0
chunk[RALLY_TRIGGERED] = 0
chunk[NEST_BASE] = {}
chunk[WORM_BASE] = {}
chunk[NEST_COUNT] = 0
chunk[WORM_COUNT] = 0
chunk[PATH_RATING] = 0 chunk[PATH_RATING] = 0
return chunk return chunk
end end
@@ -250,4 +405,109 @@ function chunkUtils.colorChunk(x, y, tileType, surface)
surface.set_tiles(tiles, false) surface.set_tiles(tiles, false)
end end
function chunkUtils.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 ~= SENTINEL_IMPASSABLE_CHUNK) then
addEnemyStructureToChunk(regionMap, leftTop, entity, base)
end
if (rightTop ~= SENTINEL_IMPASSABLE_CHUNK) then
addEnemyStructureToChunk(regionMap, rightTop, entity, base)
end
if (leftBottom ~= SENTINEL_IMPASSABLE_CHUNK) then
addEnemyStructureToChunk(regionMap, leftBottom, entity, base)
end
if (rightBottom ~= SENTINEL_IMPASSABLE_CHUNK) then
addEnemyStructureToChunk(regionMap, rightBottom, entity, base)
end
end
end
function chunkUtils.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 ~= SENTINEL_IMPASSABLE_CHUNK) then
removeEnemyStructureFromChunk(regionMap, leftTop, entity)
end
if (rightTop ~= SENTINEL_IMPASSABLE_CHUNK) then
removeEnemyStructureFromChunk(regionMap, rightTop, entity)
end
if (leftBottom ~= SENTINEL_IMPASSABLE_CHUNK) then
removeEnemyStructureFromChunk(regionMap, leftBottom, entity)
end
if (rightBottom ~= SENTINEL_IMPASSABLE_CHUNK) then
removeEnemyStructureFromChunk(regionMap, rightBottom, entity)
end
end
end
function chunkUtils.addRemovePlayerEntity(regionMap, entity, natives, addObject, creditNatives)
local leftTop, rightTop, leftBottom, rightBottom
local entityValue
if (BUILDING_PHEROMONES[entity.type] ~= nil) and (entity.force.name == "player") then
entityValue = BUILDING_PHEROMONES[entity.type]
leftTop, rightTop, leftBottom, rightBottom = getEntityOverlapChunks(regionMap, entity)
if not addObject then
if creditNatives then
natives.points = natives.points + entityValue
end
entityValue = -entityValue
end
if (leftTop ~= SENTINEL_IMPASSABLE_CHUNK) then
chunkUtils.addPlayerBaseGenerator(regionMap, leftTop, entityValue)
end
if (rightTop ~= SENTINEL_IMPASSABLE_CHUNK) then
chunkUtils.addPlayerBaseGenerator(regionMap, rightTop, entityValue)
end
if (leftBottom ~= SENTINEL_IMPASSABLE_CHUNK) then
chunkUtils.addPlayerBaseGenerator(regionMap, leftBottom, entityValue)
end
if (rightBottom ~= SENTINEL_IMPASSABLE_CHUNK) then
chunkUtils.addPlayerBaseGenerator(regionMap, rightBottom, entityValue)
end
end
return entity
end
function chunkUtils.makeImmortalEntity(surface, entity)
local repairPosition = entity.position
local repairName = entity.name
local repairForce = entity.force
local repairDirection = entity.direction
local wires
if (entity.type == "electric-pole") then
wires = entity.neighbours
end
entity.destroy()
local newEntity = surface.create_entity({position=repairPosition,
name=repairName,
direction=repairDirection,
force=repairForce})
if wires then
for connectType,neighbourGroup in pairs(wires) do
if connectType == "copper" then
for _,v in pairs(neighbourGroup) do
newEntity.connect_neighbour(v);
end
elseif connectType == "red" then
for _,v in pairs(neighbourGroup) do
newEntity.connect_neighbour({wire = DEFINES_WIRE_TYPE_RED, target_entity = v});
end
elseif connectType == "green" then
for _,v in pairs(neighbourGroup) do
newEntity.connect_neighbour({wire = DEFINES_WIRE_TYPE_GREEN, target_entity = v});
end
end
end
end
newEntity.destructible = false
end
return chunkUtils return chunkUtils

View File

@@ -15,10 +15,11 @@ constants.VERSION_25 = 25
constants.VERSION_26 = 26 constants.VERSION_26 = 26
constants.VERSION_27 = 27 constants.VERSION_27 = 27
constants.VERSION_28 = 28 constants.VERSION_28 = 28
constants.VERSION_32 = 32 constants.VERSION_33 = 33
-- misc -- misc
constants.CHUNK_SIZE_DIVIDER = 0.03125
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score
constants.MAGIC_MAXIMUM_BASE_NUMBER = 100000000 constants.MAGIC_MAXIMUM_BASE_NUMBER = 100000000
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL = 10000 constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL = 10000
@@ -28,7 +29,7 @@ constants.SCAN_QUEUE_SIZE = 5
constants.ITEM_COLLECTOR_QUEUE_SIZE = 6 constants.ITEM_COLLECTOR_QUEUE_SIZE = 6
constants.BASE_QUEUE_SIZE = 1 constants.BASE_QUEUE_SIZE = 1
constants.SQUAD_QUEUE_SIZE = 2 constants.SQUAD_QUEUE_SIZE = 2
constants.PROCESS_PLAYER_BOUND = 4 constants.PROCESS_PLAYER_BOUND = 128
constants.ITEM_COLLECTOR_MAX_QUEUE_SIZE = 20 constants.ITEM_COLLECTOR_MAX_QUEUE_SIZE = 20
@@ -42,6 +43,18 @@ constants.PLAYER_PHEROMONE_MULTIPLER = 100
constants.DEV_CUSTOM_AI = false constants.DEV_CUSTOM_AI = false
-- mask
constants.MASK_PASSABLE = 3
constants.MASK_PASSABLE_SIZE = 2
constants.MASK_NEST_COUNT = 511
constants.MASK_NEST_COUNT_SIZE = 9
constants.MASK_WORM_COUNT = 511
constants.MASK_WORM_COUNT_SIZE = 9
constants.MASK_PASSABLE_AND_NEST_COUNT = 2047
constants.MASK_PASSABLE_AND_NEST_COUNT_SIZE = 11
-- item collector -- item collector
constants.ITEM_COLLECTOR_DISTANCE = 50 constants.ITEM_COLLECTOR_DISTANCE = 50
@@ -127,19 +140,11 @@ constants.BASE_PHEROMONE = 2
constants.PLAYER_PHEROMONE = 3 constants.PLAYER_PHEROMONE = 3
constants.RESOURCE_PHEROMONE = 4 constants.RESOURCE_PHEROMONE = 4
constants.PLAYER_BASE_GENERATOR = 5 constants.PASSABLE = 5
constants.RESOURCE_GENERATOR = 6
constants.PASSABLE = 7 constants.CHUNK_TICK = 6
constants.CHUNK_TICK = 8 constants.PATH_RATING = 7
constants.RETREAT_TRIGGERED = 9
constants.RALLY_TRIGGERED = 10
constants.NEST_BASE = 11
constants.WORM_BASE = 12
constants.NEST_COUNT = 13
constants.WORM_COUNT = 14
constants.PATH_RATING = 15
-- Squad status -- Squad status
@@ -155,7 +160,7 @@ constants.RETREAT_GRAB_RADIUS = 24
constants.BASE_RALLY_CHANCE = 0.02 constants.BASE_RALLY_CHANCE = 0.02
constants.BONUS_RALLY_CHANCE = 0.06 constants.BONUS_RALLY_CHANCE = 0.06
constants.RALLY_CRY_DISTANCE = 3 constants.RALLY_CRY_DISTANCE = 96
constants.GROUP_MERGE_DISTANCE = 28 constants.GROUP_MERGE_DISTANCE = 28
@@ -211,6 +216,20 @@ constants.UNIT_GROUP_MAX_SPEED_UP = 1.1
constants.UNIT_GROUP_MAX_SLOWDOWN = 1.0 constants.UNIT_GROUP_MAX_SLOWDOWN = 1.0
constants.UNIT_GROUP_SLOWDOWN_FACTOR = 0.9 constants.UNIT_GROUP_SLOWDOWN_FACTOR = 0.9
-- sentinels
constants.SENTINEL_IMPASSABLE_CHUNK = {}
constants.SENTINEL_IMPASSABLE_CHUNK[constants.MOVEMENT_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
constants.SENTINEL_IMPASSABLE_CHUNK[constants.BASE_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
constants.SENTINEL_IMPASSABLE_CHUNK[constants.PLAYER_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
constants.SENTINEL_IMPASSABLE_CHUNK[constants.RESOURCE_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
constants.SENTINEL_IMPASSABLE_CHUNK[constants.PASSABLE] = constants.CHUNK_IMPASSABLE
constants.SENTINEL_IMPASSABLE_CHUNK[constants.CHUNK_TICK] = 0
constants.SENTINEL_IMPASSABLE_CHUNK[constants.PATH_RATING] = 0
constants.SENTINEL_IMPASSABLE_CHUNK.x = 0
constants.SENTINEL_IMPASSABLE_CHUNK.y = 0
return constants return constants
--[[ --[[

View File

@@ -1,147 +0,0 @@
local entityUtils = {}
-- imports
local mapUtils = require("MapUtils")
local constants = require("Constants")
-- constants
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
local DEFINES_DIRECTION_EAST = defines.direction.east
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
-- imported functions
local getChunkByIndex = mapUtils.getChunkByIndex
local mFloor = math.floor
-- module code
function entityUtils.getEntityOverlapChunks(regionMap, entity)
local boundingBox = entity.prototype.selection_box or entity.prototype.collision_box;
local leftTopChunk
local rightTopChunk
local leftBottomChunk
local rightBottomChunk
if (boundingBox ~= nil) then
local center = entity.position
local topXOffset
local topYOffset
local bottomXOffset
local bottomYOffset
if (entity.direction == DEFINES_DIRECTION_EAST) then
topXOffset = boundingBox.left_top.y
topYOffset = boundingBox.left_top.x
bottomXOffset = boundingBox.right_bottom.y
bottomYOffset = boundingBox.right_bottom.x
else
topXOffset = boundingBox.left_top.x
topYOffset = boundingBox.left_top.y
bottomXOffset = boundingBox.right_bottom.x
bottomYOffset = boundingBox.right_bottom.y
end
local leftTopChunkX = mFloor((center.x + topXOffset) * 0.03125)
local leftTopChunkY = mFloor((center.y + topYOffset) * 0.03125)
-- used to force things on chunk boundary to not spill over 0.0001
local rightTopChunkX = mFloor((center.x + bottomXOffset - 0.0001) * 0.03125)
local rightTopChunkY = leftTopChunkY
-- used to force things on chunk boundary to not spill over 0.0001
local leftBottomChunkX = leftTopChunkX
local leftBottomChunkY = mFloor((center.y + bottomYOffset - 0.0001) * 0.03125)
local rightBottomChunkX = rightTopChunkX
local rightBottomChunkY = leftBottomChunkY
leftTopChunk = getChunkByIndex(regionMap, leftTopChunkX, leftTopChunkY)
if (leftTopChunkX ~= rightTopChunkX) then
rightTopChunk = getChunkByIndex(regionMap, rightTopChunkX, rightTopChunkY)
end
if (leftTopChunkY ~= leftBottomChunkY) then
leftBottomChunk = getChunkByIndex(regionMap, leftBottomChunkX, leftBottomChunkY)
end
if (leftTopChunkX ~= rightBottomChunkX) and (leftTopChunkY ~= rightBottomChunkY) then
rightBottomChunk = getChunkByIndex(regionMap, rightBottomChunkX, rightBottomChunkY)
end
end
return leftTopChunk, rightTopChunk, leftBottomChunk, rightBottomChunk
end
function entityUtils.addRemovePlayerEntity(regionMap, entity, natives, addObject, creditNatives)
local leftTop, rightTop, leftBottom, rightBottom
local entityValue
if (BUILDING_PHEROMONES[entity.type] ~= nil) and (entity.force.name == "player") then
entityValue = BUILDING_PHEROMONES[entity.type]
leftTop, rightTop, leftBottom, rightBottom = entityUtils.getEntityOverlapChunks(regionMap, entity)
if not addObject then
if creditNatives then
natives.points = natives.points + entityValue
end
entityValue = -entityValue
end
if leftTop then
leftTop[PLAYER_BASE_GENERATOR] = leftTop[PLAYER_BASE_GENERATOR] + entityValue
end
if rightTop then
rightTop[PLAYER_BASE_GENERATOR] = rightTop[PLAYER_BASE_GENERATOR] + entityValue
end
if leftBottom then
leftBottom[PLAYER_BASE_GENERATOR] = leftBottom[PLAYER_BASE_GENERATOR] + entityValue
end
if rightBottom then
rightBottom[PLAYER_BASE_GENERATOR] = rightBottom[PLAYER_BASE_GENERATOR] + entityValue
end
end
return entity
end
function entityUtils.makeImmortalEntity(surface, entity)
local repairPosition = entity.position
local repairName = entity.name
local repairForce = entity.force
local repairDirection = entity.direction
local wires
if (entity.type == "electric-pole") then
wires = entity.neighbours
end
entity.destroy()
local newEntity = surface.create_entity({position=repairPosition,
name=repairName,
direction=repairDirection,
force=repairForce})
if wires then
for connectType,neighbourGroup in pairs(wires) do
if connectType == "copper" then
for _,v in pairs(neighbourGroup) do
newEntity.connect_neighbour(v);
end
elseif connectType == "red" then
for _,v in pairs(neighbourGroup) do
newEntity.connect_neighbour({wire = DEFINES_WIRE_TYPE_RED, target_entity = v});
end
elseif connectType == "green" then
for _,v in pairs(neighbourGroup) do
newEntity.connect_neighbour({wire = DEFINES_WIRE_TYPE_GREEN, target_entity = v});
end
end
end
end
newEntity.destructible = false
end
return entityUtils

View File

@@ -1,46 +0,0 @@
local inventoryUtils = {}
-- imported functions
local mMin = math.min
-- modules code
function inventoryUtils.swapItemInventory(inventory, src, dst)
if inventory and inventory.valid then
local itemCount = inventory.get_item_count(src)
if (itemCount > 0) then
inventory.remove({name = src, count = itemCount})
inventory.insert({name = dst, count = itemCount})
end
end
end
function inventoryUtils.topOffHand(inventory, handStack, src, dst)
if inventory and inventory.valid then
local itemCount = inventory.get_item_count(src)
if (itemCount > 0) then
if handStack and handStack.valid and handStack.valid_for_read and (handStack.prototype.name == dst) then
local remaining = mMin(itemCount, handStack.prototype.stack_size - handStack.count)
if (remaining > 0) then
local stack = { name = src, count = remaining + handStack.count }
if (handStack.can_set_stack(stack)) and handStack.set_stack(stack) then
inventory.remove({name = src, count = remaining})
end
end
end
end
end
end
function inventoryUtils.swapItemStack(stack, src, dst)
if stack and stack.valid_for_read and (stack.name == src) then
local item = { name = dst, count = stack.count }
if stack.can_set_stack(item) then
stack.set_stack(item)
end
end
end
return inventoryUtils

View File

@@ -3,14 +3,13 @@ local mapProcessor = {}
-- imports -- imports
local unitGroupUtils = require("UnitGroupUtils") local unitGroupUtils = require("UnitGroupUtils")
local pheromoneUtils = require("PheromoneUtils") local pheromoneUtils = require("PheromoneUtils")
local aiAttackWave = require("AIAttackWave") local aiAttackWave = require("AIAttackWave")
local aiPredicates = require("AIPredicates") local aiPredicates = require("AIPredicates")
local constants = require("Constants") local constants = require("Constants")
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local playerUtils = require("PlayerUtils") local playerUtils = require("PlayerUtils")
local chunkUtils = require("ChunkUtils")
local mathUtils = require("MathUtils") local mathUtils = require("MathUtils")
-- constants -- constants
@@ -26,30 +25,33 @@ local TRIPLE_CHUNK_SIZE = constants.TRIPLE_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_COUNT = constants.NEST_COUNT local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local WORM_COUNT = constants.WORM_COUNT
local AI_SQUAD_COST = constants.AI_SQUAD_COST local AI_SQUAD_COST = constants.AI_SQUAD_COST
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
local RESOURCE_GENERATOR = constants.RESOURCE_GENERATOR
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
-- imported functions -- imported functions
local scents = pheromoneUtils.scents local scents = pheromoneUtils.scents
local processPheromone = pheromoneUtils.processPheromone local processPheromone = pheromoneUtils.processPheromone
local playerScent = pheromoneUtils.playerScent
local formSquads = aiAttackWave.formSquads local formSquads = aiAttackWave.formSquads
local getChunkByIndex = mapUtils.getChunkByIndex
local getChunkByPosition = mapUtils.getChunkByPosition local getChunkByPosition = mapUtils.getChunkByPosition
local positionToChunkXY = mapUtils.positionToChunkXY
local recycleBiters = unitGroupUtils.recycleBiters local recycleBiters = unitGroupUtils.recycleBiters
local playerScent = pheromoneUtils.playerScent local validPlayer = playerUtils.validPlayer
local setResourceGenerator = chunkUtils.setResourceGenerator
local setPlayerBaseGenerator = chunkUtils.setPlayerBaseGenerator
local getNestCount = chunkUtils.getNestCount
local getWormCount = chunkUtils.getWormCount
local canAttack = aiPredicates.canAttack local canAttack = aiPredicates.canAttack
@@ -57,8 +59,6 @@ local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
local mMin = math.min local mMin = math.min
local validPlayer = playerUtils.validPlayer
local mRandom = math.random local mRandom = math.random
-- module code -- module code
@@ -105,12 +105,12 @@ function mapProcessor.processMap(regionMap, surface, natives, tick)
processPheromone(regionMap, chunk) processPheromone(regionMap, chunk)
if squads and (chunk[NEST_COUNT] ~= 0) then if squads and (getNestCount(regionMap, chunk) > 0) then
formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST) formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST)
squads = (natives.points >= AI_SQUAD_COST) and (#natives.squads < natives.maxSquads) squads = (natives.points >= AI_SQUAD_COST) and (#natives.squads < natives.maxSquads)
end end
scents(chunk) scents(regionMap, chunk)
end end
end end
@@ -141,10 +141,10 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick)
for i=1,#playerOrdering do for i=1,#playerOrdering do
local player = players[playerOrdering[i]] local player = players[playerOrdering[i]]
if validPlayer(player) then if validPlayer(player) then
local playerPosition = player.character.position local chunkX, chunkY = positionToChunkXY(player.character.position)
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y) local playerChunk = getChunkByPosition(regionMap, chunkX, chunkY)
if playerChunk then if (playerChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
playerScent(playerChunk) playerScent(playerChunk)
end end
end end
@@ -152,21 +152,24 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick)
for i=1,#playerOrdering do for i=1,#playerOrdering do
local player = players[playerOrdering[i]] local player = players[playerOrdering[i]]
if validPlayer(player) then if validPlayer(player) then
local playerPosition = player.character.position local chunkX, chunkY = positionToChunkXY(player.character.position)
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y) local playerChunk = getChunkByPosition(regionMap, chunkX, chunkY)
if playerChunk then if (playerChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local vengence = allowingAttacks and ((playerChunk[NEST_COUNT] ~= 0) or (playerChunk[WORM_COUNT] ~= 0) or (playerChunk[MOVEMENT_PHEROMONE] < natives.retreatThreshold)) and (natives.points >= AI_VENGENCE_SQUAD_COST) local vengence = (allowingAttacks and
(natives.points >= AI_VENGENCE_SQUAD_COST) and
((getWormCount(regionMap, playerChunk) > 0) or (getNestCount(regionMap, playerChunk) > 0) or (playerChunk[MOVEMENT_PHEROMONE] < natives.retreatThreshold)))
for x=playerChunk.cX - PROCESS_PLAYER_BOUND, playerChunk.cX + PROCESS_PLAYER_BOUND do for x=playerChunk.x - PROCESS_PLAYER_BOUND, playerChunk.x + PROCESS_PLAYER_BOUND, 32 do
for y=playerChunk.cY - PROCESS_PLAYER_BOUND, playerChunk.cY + PROCESS_PLAYER_BOUND do for y=playerChunk.y - PROCESS_PLAYER_BOUND, playerChunk.y + PROCESS_PLAYER_BOUND, 32 do
local chunk = getChunkByIndex(regionMap, x, y) local chunk = getChunkByPosition(regionMap, x, y)
if chunk and (chunk[CHUNK_TICK] ~= tick) then
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (chunk[CHUNK_TICK] ~= tick) then
chunk[CHUNK_TICK] = tick chunk[CHUNK_TICK] = tick
processPheromone(regionMap, chunk) processPheromone(regionMap, chunk)
if (chunk[NEST_COUNT] ~= 0) then if (getNestCount(regionMap, chunk) > 0) then
if squads then if squads then
formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST) formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST)
squads = (natives.points >= AI_SQUAD_COST) and (#natives.squads < natives.maxSquads) squads = (natives.points >= AI_SQUAD_COST) and (#natives.squads < natives.maxSquads)
@@ -177,7 +180,7 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick)
end end
end end
scents(chunk) scents(regionMap, chunk)
end end
end end
end end
@@ -232,7 +235,7 @@ function mapProcessor.scanMap(regionMap, surface, natives)
end end
end end
chunk[RESOURCE_GENERATOR] = surface.count_entities_filtered(resourceQuery) * 0.001 setResourceGenerator(regionMap, chunk, surface.count_entities_filtered(resourceQuery) * 0.001)
local entities = surface.find_entities_filtered(playerQuery) local entities = surface.find_entities_filtered(playerQuery)
local playerBaseGenerator = 0 local playerBaseGenerator = 0
@@ -250,7 +253,7 @@ function mapProcessor.scanMap(regionMap, surface, natives)
end end
end end
chunk[PLAYER_BASE_GENERATOR] = playerBaseGenerator setPlayerBaseGenerator(regionMap, chunk, playerBaseGenerator)
end end
if (endIndex == #processQueue) then if (endIndex == #processQueue) then

View File

@@ -13,10 +13,12 @@ local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
local PASSABLE = constants.PASSABLE local PASSABLE = constants.PASSABLE
local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE
local CHUNK_SIZE = constants.CHUNK_SIZE local CHUNK_SIZE = constants.CHUNK_SIZE
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local CHUNK_SIZE_DIVIDER = constants.CHUNK_SIZE_DIVIDER
-- imported functions -- imported functions
local mFloor = math.floor local mFloor = math.floor
@@ -24,19 +26,17 @@ local mFloor = math.floor
-- module code -- module code
function mapUtils.getChunkByPosition(regionMap, x, y) function mapUtils.getChunkByPosition(regionMap, x, y)
local chunkX = regionMap[mFloor(x * 0.03125)]
if chunkX then
return chunkX[mFloor(y * 0.03125)]
end
return nil
end
function mapUtils.getChunkByIndex(regionMap, x, y)
local chunkX = regionMap[x] local chunkX = regionMap[x]
if chunkX then if chunkX then
return chunkX[y] return chunkX[y] or SENTINEL_IMPASSABLE_CHUNK
end end
return nil return SENTINEL_IMPASSABLE_CHUNK
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
return chunkX, chunkY
end end
--[[ --[[
@@ -46,39 +46,39 @@ end
/|\ /|\
6 7 8 6 7 8
]]-- ]]--
function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY) function mapUtils.getNeighborChunks(regionMap, x, y)
local neighbors = regionMap.neighbors local neighbors = regionMap.neighbors
local chunkYRow1 = chunkY - 1 local chunkYRow1 = y - CHUNK_SIZE
local chunkYRow3 = chunkY + 1 local chunkYRow3 = y + CHUNK_SIZE
local xChunks = regionMap[chunkX-1] local xChunks = regionMap[x-CHUNK_SIZE]
if xChunks then if xChunks then
neighbors[1] = xChunks[chunkYRow1] neighbors[1] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = xChunks[chunkY] neighbors[4] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
neighbors[6] = xChunks[chunkYRow3] neighbors[6] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[1] = nil neighbors[1] = SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = nil neighbors[4] = SENTINEL_IMPASSABLE_CHUNK
neighbors[6] = nil neighbors[6] = SENTINEL_IMPASSABLE_CHUNK
end
xChunks = regionMap[x+CHUNK_SIZE]
if xChunks then
neighbors[3] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK
neighbors[5] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
neighbors[8] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK
else
neighbors[3] = SENTINEL_IMPASSABLE_CHUNK
neighbors[5] = SENTINEL_IMPASSABLE_CHUNK
neighbors[8] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = regionMap[chunkX+1] xChunks = regionMap[x]
if xChunks then if xChunks then
neighbors[3] = xChunks[chunkYRow1] neighbors[2] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK
neighbors[5] = xChunks[chunkY] neighbors[7] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK
neighbors[8] = xChunks[chunkYRow3]
else else
neighbors[3] = nil neighbors[2] = SENTINEL_IMPASSABLE_CHUNK
neighbors[5] = nil neighbors[7] = SENTINEL_IMPASSABLE_CHUNK
neighbors[8] = nil
end
xChunks = regionMap[chunkX]
if xChunks then
neighbors[2] = xChunks[chunkYRow1]
neighbors[7] = xChunks[chunkYRow3]
else
neighbors[2] = nil
neighbors[7] = nil
end end
return neighbors return neighbors
end end
@@ -87,41 +87,41 @@ function mapUtils.canMoveChunkDirection(direction, startChunk, endChunk)
local canMove = false local canMove = false
local startPassable = startChunk[PASSABLE] local startPassable = startChunk[PASSABLE]
local endPassable = endChunk[PASSABLE] local endPassable = endChunk[PASSABLE]
if ((direction == 2) or (direction == 7)) and (startPassable == CHUNK_NORTH_SOUTH) and (endPassable == CHUNK_NORTH_SOUTH) then if (startPassable == CHUNK_ALL_DIRECTIONS) and (endPassable == CHUNK_ALL_DIRECTIONS) then
canMove = true
elseif ((direction == 4) or (direction == 5)) and (startPassable == CHUNK_EAST_WEST) and (endPassable == CHUNK_EAST_WEST) then
canMove = true
elseif (startPassable == CHUNK_ALL_DIRECTIONS) and (endPassable == CHUNK_ALL_DIRECTIONS) then
canMove = true canMove = true
elseif (startPassable ~= CHUNK_IMPASSABLE) and (endPassable == CHUNK_ALL_DIRECTIONS) then elseif ((direction == 2) or (direction == 7)) and (startPassable == CHUNK_NORTH_SOUTH) and (endPassable == CHUNK_NORTH_SOUTH) then
canMove = true
elseif ((direction == 4) or (direction == 5)) and (startPassable == CHUNK_EAST_WEST) and (endPassable == CHUNK_EAST_WEST) then
canMove = true
elseif (startChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (endPassable == CHUNK_ALL_DIRECTIONS) then
canMove = true canMove = true
end end
return canMove return canMove
end end
function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY) function mapUtils.getCardinalChunks(regionMap, x, y)
local neighbors = regionMap.cardinalNeighbors local neighbors = regionMap.cardinalNeighbors
local xChunks = regionMap[chunkX] local xChunks = regionMap[x]
if xChunks then if xChunks then
neighbors[1] = xChunks[chunkY-1] neighbors[1] = xChunks[y-CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = xChunks[chunkY+1] neighbors[4] = xChunks[y+CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[1] = nil neighbors[1] = SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = nil neighbors[4] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = regionMap[chunkX-1] xChunks = regionMap[x-CHUNK_SIZE]
if xChunks then if xChunks then
neighbors[2] = xChunks[chunkY] neighbors[2] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[2] = nil neighbors[2] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = regionMap[chunkX+1] xChunks = regionMap[x+CHUNK_SIZE]
if xChunks then if xChunks then
neighbors[3] = xChunks[chunkY] neighbors[3] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[3] = nil neighbors[3] = SENTINEL_IMPASSABLE_CHUNK
end end
return neighbors return neighbors
end end

View File

@@ -4,7 +4,7 @@ local movementUtils = {}
local constants = require("Constants") local constants = require("Constants")
local unitGroupUtils = require("UnitGroupUtils") local unitGroupUtils = require("UnitGroupUtils")
local mapUtils = require("MapUtils")
local mathUtils = require("MathUtils") local mathUtils = require("MathUtils")
-- constants -- constants
@@ -12,8 +12,16 @@ local mathUtils = require("MathUtils")
local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
local MAX_PENALTY_BEFORE_PURGE = constants.MAX_PENALTY_BEFORE_PURGE local MAX_PENALTY_BEFORE_PURGE = constants.MAX_PENALTY_BEFORE_PURGE
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions -- imported functions
local canMoveChunkDirection = mapUtils.canMoveChunkDirection
local recycleBiters = unitGroupUtils.recycleBiters local recycleBiters = unitGroupUtils.recycleBiters
local tableRemove = table.remove local tableRemove = table.remove
@@ -31,11 +39,11 @@ function movementUtils.findMovementPosition(surface, position, distort)
return (distort and distortPosition(pos)) or pos return (distort and distortPosition(pos)) or pos
end end
function movementUtils.addMovementPenalty(natives, units, chunkX, chunkY) function movementUtils.addMovementPenalty(natives, units, x, y)
local penalties = units.penalties local penalties = units.penalties
for i=1,#penalties do for i=1,#penalties do
local penalty = penalties[i] local penalty = penalties[i]
if (penalty.x == chunkX) and (penalty.y == chunkY) then if (penalty.x == x) and (penalty.y == y) then
penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then
local group = units.group local group = units.group
@@ -53,15 +61,15 @@ function movementUtils.addMovementPenalty(natives, units, chunkX, chunkY)
tableRemove(penalties, 7) tableRemove(penalties, 7)
end end
tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT, tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
x = chunkX, x = x,
y = chunkY }) y = y })
end end
function movementUtils.lookupMovementPenalty(squad, chunkX, chunkY) function movementUtils.lookupMovementPenalty(squad, x, y)
local penalties = squad.penalties local penalties = squad.penalties
for i=1,#penalties do for i=1,#penalties do
local penalty = penalties[i] local penalty = penalties[i]
if (penalty.x == chunkX) and (penalty.y == chunkY) then if (penalty.x == x) and (penalty.y == y) then
return penalty.v return penalty.v
end end
end end
@@ -69,4 +77,101 @@ function movementUtils.lookupMovementPenalty(squad, chunkX, chunkY)
end end
--[[
Expects all neighbors adjacent to a chunk
--]]
function movementUtils.scoreNeighborsForAttack(chunk, neighborDirectionChunks, scoreFunction, squad)
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(x, chunk, neighborChunk) then
local score = scoreFunction(squad, neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
if scoreFunction(squad, chunk) > highestScore then
return SENTINEL_IMPASSABLE_CHUNK, -1
end
return highestChunk, highestDirection
end
--[[
Expects all neighbors adjacent to a chunk
--]]
function movementUtils.scoreNeighborsForResource(chunk, neighborDirectionChunks, scoreFunction, squad, threshold)
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(x, chunk, neighborChunk) and (neighborChunk[RESOURCE_PHEROMONE] > (threshold or 1)) then
local score = scoreFunction(squad, neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
if scoreFunction(squad, chunk) > highestScore then
return SENTINEL_IMPASSABLE_CHUNK, -1
end
return highestChunk, highestDirection
end
--[[
Expects all neighbors adjacent to a chunk
--]]
function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks, scoreFunction, regionMap)
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(x, chunk, neighborChunk) then
local score = scoreFunction(regionMap, neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
return highestChunk, highestDirection
end
--[[
Expects all neighbors adjacent to a chunk
--]]
function movementUtils.scoreNeighborsForFormation(neighborChunks, validFunction, scoreFunction, regionMap)
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and validFunction(regionMap, neighborChunk) then
local score = scoreFunction(neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
return highestChunk, highestDirection
end
return movementUtils return movementUtils

View File

@@ -1,119 +0,0 @@
local neighborUtils = {}
-- imports
local mapUtils = require("MapUtils")
local constants = require("Constants")
-- constants
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
-- imported functions
local canMoveChunkDirection = mapUtils.canMoveChunkDirection
-- module code
--[[
Expects all neighbors adjacent to a chunk
--]]
function neighborUtils.scoreNeighborsForAttack(chunk, neighborDirectionChunks, scoreFunction, squad)
local highestChunk
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if neighborChunk and canMoveChunkDirection(x, chunk, neighborChunk) then
local score = scoreFunction(squad, neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
if scoreFunction(squad, chunk) > highestScore then
return nil, -1
end
return highestChunk, highestDirection
end
--[[
Expects all neighbors adjacent to a chunk
--]]
function neighborUtils.scoreNeighborsForResource(chunk, neighborDirectionChunks, scoreFunction, squad, threshold)
local highestChunk
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if neighborChunk and canMoveChunkDirection(x, chunk, neighborChunk) and (neighborChunk[RESOURCE_PHEROMONE] > (threshold or 1)) then
local score = scoreFunction(squad, neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
if scoreFunction(squad, chunk) > highestScore then
return nil, -1
end
return highestChunk, highestDirection
end
--[[
Expects all neighbors adjacent to a chunk
--]]
function neighborUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks, scoreFunction)
local highestChunk
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if neighborChunk and canMoveChunkDirection(x, chunk, neighborChunk) then
local score = scoreFunction(neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
return highestChunk, highestDirection
end
--[[
Expects all neighbors adjacent to a chunk
--]]
function neighborUtils.scoreNeighborsForFormation(neighborChunks, validFunction, scoreFunction)
local highestChunk
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
for x=1,8 do
local neighborChunk = neighborChunks[x]
if neighborChunk and validFunction(neighborChunk) then
local score = scoreFunction(neighborChunk)
if (score > highestScore) then
highestScore = score
highestChunk = neighborChunk
highestDirection = x
end
end
end
return highestChunk, highestDirection
end
return neighborUtils

View File

@@ -4,10 +4,8 @@ local nestUtils = {}
local constants = require("Constants") local constants = require("Constants")
local mathUtils = require("MathUtils") local mathUtils = require("MathUtils")
local baseRegisterUtils = require("BaseRegisterUtils")
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local chunkUtils = require("ChunkUtils")
-- constants -- constants
@@ -20,9 +18,11 @@ local NEST_COUNT = constants.NEST_COUNT
local DOUBLE_CHUNK_SIZE = constants.DOUBLE_CHUNK_SIZE local DOUBLE_CHUNK_SIZE = constants.DOUBLE_CHUNK_SIZE
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions -- imported functions
local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure
local gaussianRandomRange = mathUtils.gaussianRandomRange local gaussianRandomRange = mathUtils.gaussianRandomRange
local mRandom = math.random local mRandom = math.random
@@ -35,7 +35,7 @@ function nestUtils.buildNest(regionMap, base, surface, targetPosition, name)
local position = surface.find_non_colliding_position(name, targetPosition, DOUBLE_CHUNK_SIZE, 2) local position = surface.find_non_colliding_position(name, targetPosition, DOUBLE_CHUNK_SIZE, 2)
local chunk = getChunkByPosition(regionMap, position.x, position.y) local chunk = getChunkByPosition(regionMap, position.x, position.y)
local nest = nil local nest = nil
if position and chunk and (chunk[NEST_COUNT] < 3) then if position and (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (chunk[NEST_COUNT] < 3) then
local biterSpawner = {name=name, position=position} local biterSpawner = {name=name, position=position}
nest = surface.create_entity(biterSpawner) nest = surface.create_entity(biterSpawner)
registerEnemyBaseStructure(regionMap, nest, base) registerEnemyBaseStructure(regionMap, nest, base)
@@ -45,7 +45,7 @@ end
function nestUtils.buildHive(regionMap, base, surface) function nestUtils.buildHive(regionMap, base, surface)
local valid = false local valid = false
local hive = nestUtils.buildNest(regionMap, base, surface, base, "biter-spawner-hive") local hive = nestUtils.buildNest(regionMap, base, surface, base, "biter-spawner-hive-rampant")
if hive then if hive then
if (#base.hives == 0) then if (#base.hives == 0) then
base.x = hive.position.x base.x = hive.position.x
@@ -101,7 +101,7 @@ function nestUtils.buildOutpost(regionMap, natives, base, surface, tendril)
y = position.y + (distortion * math.sin(pos))} y = position.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
registerEnemyBaseStructure(regionMap, surface.create_entity(biterSpawner), base) registerEnemyBaseStructure(natives, regionMap, surface.create_entity(biterSpawner), base)
base.upgradePoints = base.upgradePoints - cost base.upgradePoints = base.upgradePoints - cost
end end
pos = pos + slice pos = pos + slice
@@ -149,7 +149,7 @@ function nestUtils.buildOrder(regionMap, natives, base, surface)
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
registerEnemyBaseStructure(regionMap, surface.create_entity(biterSpawner), base) registerEnemyBaseStructure(natives, regionMap, surface.create_entity(biterSpawner), base)
base.upgradePoints = base.upgradePoints - cost base.upgradePoints = base.upgradePoints - cost
end end
pos = pos + slice pos = pos + slice

View File

@@ -1,21 +0,0 @@
local nocturnalUtils = {}
-- imports
local constants = require("Constants")
-- constants
local AI_STATE_NOCTURNAL = constants.AI_STATE_NOCTURNAL
-- module code
function nocturnalUtils.isDark(surface)
return surface.darkness > 0.65
end
function nocturnalUtils.canAttack(natives, surface)
return nocturnalUtils.isDark(surface) and natives.state == AI_STATE_NOCTURNAL
end
return nocturnalUtils

View File

@@ -4,6 +4,7 @@ local pheromoneUtils = {}
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local constants = require("Constants") local constants = require("Constants")
local chunkUtils = require("ChunkUtils")
-- constants -- constants
@@ -14,9 +15,6 @@ local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
local RESOURCE_GENERATOR = constants.RESOURCE_GENERATOR
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
@@ -25,63 +23,45 @@ local BASE_PHEROMONE_PERSISTANCE = constants.BASE_PHEROMONE_PERSISTANCE
local PLAYER_PHEROMONE_PERSISTANCE = constants.PLAYER_PHEROMONE_PERSISTANCE local PLAYER_PHEROMONE_PERSISTANCE = constants.PLAYER_PHEROMONE_PERSISTANCE
local RESOURCE_PHEROMONE_PERSISTANCE = constants.RESOURCE_PHEROMONE_PERSISTANCE local RESOURCE_PHEROMONE_PERSISTANCE = constants.RESOURCE_PHEROMONE_PERSISTANCE
local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE
local PASSABLE = constants.PASSABLE
local NEST_COUNT = constants.NEST_COUNT
local PATH_RATING = constants.PATH_RATING local PATH_RATING = constants.PATH_RATING
local IMPASSABLE_TERRAIN_GENERATOR_AMOUNT = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
-- imported functions -- imported functions
local getCardinalChunks = mapUtils.getCardinalChunks local getCardinalChunks = mapUtils.getCardinalChunks
local mMax = math.max local mMax = math.max
local getNestCount = chunkUtils.getNestCount
local getWormCount = chunkUtils.getWormCount
local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator
local getResourceGenerator = chunkUtils.getResourceGenerator
-- module code -- module code
function pheromoneUtils.scents(chunk) function pheromoneUtils.scents(regionMap, chunk)
chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + getPlayerBaseGenerator(regionMap, chunk)
if (chunk[PASSABLE] == CHUNK_IMPASSABLE) then local resourceGenerator = getResourceGenerator(regionMap, chunk)
chunk[BASE_PHEROMONE] = IMPASSABLE_TERRAIN_GENERATOR_AMOUNT; if (resourceGenerator > 0) and (getNestCount(regionMap, chunk) == 0) and (getWormCount(regionMap, chunk) == 0) then
else chunk[RESOURCE_PHEROMONE] = chunk[RESOURCE_PHEROMONE] + mMax(resourceGenerator * 100, 90)
chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + chunk[PLAYER_BASE_GENERATOR]
local resourceGenerator = chunk[RESOURCE_GENERATOR]
if (resourceGenerator > 0) and (chunk[NEST_COUNT] == 0) then
chunk[RESOURCE_PHEROMONE] = chunk[RESOURCE_PHEROMONE] + mMax(resourceGenerator * 100, 90)
end
end end
end end
function pheromoneUtils.victoryScent(chunk, entityType) function pheromoneUtils.victoryScent(chunk, entityType)
local value = BUILDING_PHEROMONES[entityType] local value = BUILDING_PHEROMONES[entityType]
if value and (chunk[PASSABLE] ~= CHUNK_IMPASSABLE) then if value then
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] + (value * 100000) chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] + (value * 100000)
end end
end end
function pheromoneUtils.deathScent(chunk) function pheromoneUtils.deathScent(chunk)
if (chunk[PASSABLE] ~= CHUNK_IMPASSABLE) then chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT
end
end end
function pheromoneUtils.playerScent(playerChunk) function pheromoneUtils.playerScent(playerChunk)
if (playerChunk[PASSABLE] ~= CHUNK_IMPASSABLE) then playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT
playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT
end
end end
function pheromoneUtils.processPheromone(regionMap, chunk) function pheromoneUtils.processPheromone(regionMap, chunk)
if (chunk[PASSABLE] == CHUNK_IMPASSABLE) then
return
end
local chunkMovement = chunk[MOVEMENT_PHEROMONE] local chunkMovement = chunk[MOVEMENT_PHEROMONE]
local chunkBase = chunk[BASE_PHEROMONE] local chunkBase = chunk[BASE_PHEROMONE]
local chunkPlayer = chunk[PLAYER_PHEROMONE] local chunkPlayer = chunk[PLAYER_PHEROMONE]
@@ -93,17 +73,31 @@ function pheromoneUtils.processPheromone(regionMap, chunk)
local totalPlayer = 0 local totalPlayer = 0
local totalResource = 0 local totalResource = 0
local tempNeighbors = getCardinalChunks(regionMap, chunk.cX, chunk.cY) local tempNeighbors = getCardinalChunks(regionMap, chunk.x, chunk.y)
for i=1,4 do local neighborChunk = tempNeighbors[1]
local neighborChunk = tempNeighbors[i] totalMovement = totalMovement + (neighborChunk[MOVEMENT_PHEROMONE] - chunkMovement)
if neighborChunk then totalBase = totalBase + (neighborChunk[BASE_PHEROMONE] - chunkBase)
totalMovement = totalMovement + (neighborChunk[MOVEMENT_PHEROMONE] - chunkMovement) totalPlayer = totalPlayer + (neighborChunk[PLAYER_PHEROMONE] - chunkPlayer)
totalBase = totalBase + (neighborChunk[BASE_PHEROMONE] - chunkBase) totalResource = totalResource + (neighborChunk[RESOURCE_PHEROMONE] - chunkResource)
totalPlayer = totalPlayer + (neighborChunk[PLAYER_PHEROMONE] - chunkPlayer)
totalResource = totalResource + (neighborChunk[RESOURCE_PHEROMONE] - chunkResource) neighborChunk = tempNeighbors[2]
end totalMovement = totalMovement + (neighborChunk[MOVEMENT_PHEROMONE] - chunkMovement)
end totalBase = totalBase + (neighborChunk[BASE_PHEROMONE] - chunkBase)
totalPlayer = totalPlayer + (neighborChunk[PLAYER_PHEROMONE] - chunkPlayer)
totalResource = totalResource + (neighborChunk[RESOURCE_PHEROMONE] - chunkResource)
neighborChunk = tempNeighbors[3]
totalMovement = totalMovement + (neighborChunk[MOVEMENT_PHEROMONE] - chunkMovement)
totalBase = totalBase + (neighborChunk[BASE_PHEROMONE] - chunkBase)
totalPlayer = totalPlayer + (neighborChunk[PLAYER_PHEROMONE] - chunkPlayer)
totalResource = totalResource + (neighborChunk[RESOURCE_PHEROMONE] - chunkResource)
neighborChunk = tempNeighbors[4]
totalMovement = totalMovement + (neighborChunk[MOVEMENT_PHEROMONE] - chunkMovement)
totalBase = totalBase + (neighborChunk[BASE_PHEROMONE] - chunkBase)
totalPlayer = totalPlayer + (neighborChunk[PLAYER_PHEROMONE] - chunkPlayer)
totalResource = totalResource + (neighborChunk[RESOURCE_PHEROMONE] - chunkResource)
chunk[MOVEMENT_PHEROMONE] = (chunkMovement + (0.125 * totalMovement)) * MOVEMENT_PHEROMONE_PERSISTANCE * chunkPathRating chunk[MOVEMENT_PHEROMONE] = (chunkMovement + (0.125 * totalMovement)) * MOVEMENT_PHEROMONE_PERSISTANCE * chunkPathRating
chunk[BASE_PHEROMONE] = (chunkBase + (0.25 * totalBase)) * BASE_PHEROMONE_PERSISTANCE * chunkPathRating chunk[BASE_PHEROMONE] = (chunkBase + (0.25 * totalBase)) * BASE_PHEROMONE_PERSISTANCE * chunkPathRating

View File

@@ -25,24 +25,4 @@ function playerUtils.playersWithinProximityToPosition(players, position, distanc
return false return false
end end
function playerUtils.getPlayerInventory(player, withChar, withoutChar)
local inventory = nil
if player and player.valid and player.connected then
if player.character and player.character.valid then
inventory = player.character.get_inventory(withChar)
else
inventory = player.get_inventory(withoutChar)
end
end
return inventory
end
function playerUtils.getPlayerCursorStack(player)
local result = nil
if player and player.valid then
result = player.cursor_stack
end
return result
end
return playerUtils return playerUtils

View File

@@ -6,9 +6,9 @@ local constants = require("Constants")
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local unitGroupUtils = require("UnitGroupUtils") local unitGroupUtils = require("UnitGroupUtils")
local playerUtils = require("PlayerUtils") local playerUtils = require("PlayerUtils")
local neighborUtils = require("NeighborUtils")
local movementUtils = require("MovementUtils") local movementUtils = require("MovementUtils")
local mathUtils = require("MathUtils") local mathUtils = require("MathUtils")
local chunkUtils = require("ChunkUtils")
-- constants -- constants
@@ -19,7 +19,7 @@ local BASE_PHEROMONE = constants.BASE_PHEROMONE
local SQUAD_RAIDING = constants.SQUAD_RAIDING local SQUAD_RAIDING = constants.SQUAD_RAIDING
local SQUAD_GUARDING = constants.SQUAD_GUARDING local SQUAD_GUARDING = constants.SQUAD_GUARDING
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR local CHUNK_SIZE = constants.CHUNK_SIZE
local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER
@@ -32,6 +32,8 @@ local DEFINES_GROUP_ATTACKING_TARGET = defines.group_state.attacking_target
local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy
local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions -- imported functions
local mRandom = math.random local mRandom = math.random
@@ -48,14 +50,17 @@ local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPosition local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPosition
local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator
local scoreNeighborsForAttack = neighborUtils.scoreNeighborsForAttack local positionToChunkXY = mapUtils.positionToChunkXY
local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack
-- module code -- module code
local function scoreAttackLocation(squad, neighborChunk) local function scoreAttackLocation(squad, neighborChunk)
local damage = (2*neighborChunk[MOVEMENT_PHEROMONE]) + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) local damage = (2*neighborChunk[MOVEMENT_PHEROMONE]) + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
return damage - lookupMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY) return damage - lookupMovementPenalty(squad, neighborChunk.x, neighborChunk.y)
end end
function squadAttack.squadsAttack(regionMap, surface, natives) function squadAttack.squadsAttack(regionMap, surface, natives)
@@ -67,7 +72,7 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
attackPosition = regionMap.position attackPosition = regionMap.position
attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA, attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA,
destination = attackPosition, destination = attackPosition,
radius = 32, radius = CHUNK_SIZE,
distraction = DEFINES_DISTRACTION_BY_ENEMY } distraction = DEFINES_DISTRACTION_BY_ENEMY }
end end
@@ -78,18 +83,17 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
local groupState = group.state local groupState = group.state
if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles == 0)) then if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles == 0)) then
local groupPosition = group.position local groupPosition = group.position
local chunk = getChunkByPosition(regionMap, groupPosition.x, groupPosition.y) local chunkX, chunkY = positionToChunkXY(groupPosition)
if chunk then local chunk = getChunkByPosition(regionMap, chunkX, chunkY)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local attackChunk, attackDirection = scoreNeighborsForAttack(chunk, local attackChunk, attackDirection = scoreNeighborsForAttack(chunk,
getNeighborChunks(regionMap, getNeighborChunks(regionMap, chunkX, chunkY),
chunk.cX,
chunk.cY),
scoreAttackLocation, scoreAttackLocation,
squad) squad)
addMovementPenalty(natives, squad, chunk.cX, chunk.cY) addMovementPenalty(natives, squad, chunkX, chunkY)
if group.valid and attackChunk then if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
if (attackChunk[PLAYER_BASE_GENERATOR] == 0) or local playerBaseGenerator = getPlayerBaseGenerator(regionMap, attackChunk)
((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then if (playerBaseGenerator == 0) or ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then
squad.cycles = ((#squad.group.members > 80) and 6) or 4 squad.cycles = ((#squad.group.members > 80) and 6) or 4
@@ -102,22 +106,18 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end end
local position = findMovementPosition(surface, local position = findMovementPosition(surface, positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.35))
positionFromDirectionAndChunk(attackDirection,
groupPosition,
attackPosition,
1.35))
if position then if position then
attackPosition.x = position.x attackPosition.x = position.x
attackPosition.y = position.y attackPosition.y = position.y
group.set_command(attackCmd) group.set_command(attackCmd)
group.start_moving() group.start_moving()
else else
addMovementPenalty(natives, squad, attackChunk.cX, attackChunk.cY) addMovementPenalty(natives, squad, attackChunk.x, attackChunk.y)
end end
elseif not squad.frenzy and not squad.rabid and elseif not squad.frenzy and not squad.rabid and
((groupState == DEFINES_GROUP_ATTACKING_DISTRACTION) or (groupState == DEFINES_GROUP_ATTACKING_TARGET) or ((groupState == DEFINES_GROUP_ATTACKING_DISTRACTION) or (groupState == DEFINES_GROUP_ATTACKING_TARGET) or
(attackChunk[PLAYER_BASE_GENERATOR] ~= 0)) then (playerBaseGenerator ~= 0)) then
squad.frenzy = true squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y squad.frenzyPosition.y = groupPosition.y

View File

@@ -5,14 +5,13 @@ local aiDefense = {}
local constants = require("Constants") local constants = require("Constants")
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local unitGroupUtils = require("UnitGroupUtils") local unitGroupUtils = require("UnitGroupUtils")
local neighborUtils = require("NeighborUtils")
local movementUtils = require("MovementUtils") local movementUtils = require("MovementUtils")
local chunkUtils = require("ChunkUtils")
-- constants -- constants
local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
local BASE_PHEROMONE = constants.BASE_PHEROMONE local BASE_PHEROMONE = constants.BASE_PHEROMONE
@@ -23,12 +22,9 @@ local SQUAD_RETREATING = constants.SQUAD_RETREATING
local RETREAT_FILTER = constants.RETREAT_FILTER local RETREAT_FILTER = constants.RETREAT_FILTER
local RETREAT_TRIGGERED = constants.RETREAT_TRIGGERED
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
local NEST_COUNT = constants.NEST_COUNT local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local WORM_COUNT = constants.WORM_COUNT
-- imported functions -- imported functions
@@ -38,42 +34,43 @@ local findNearBySquad = unitGroupUtils.findNearBySquad
local addMovementPenalty = movementUtils.addMovementPenalty local addMovementPenalty = movementUtils.addMovementPenalty
local createSquad = unitGroupUtils.createSquad local createSquad = unitGroupUtils.createSquad
local membersToSquad = unitGroupUtils.membersToSquad local membersToSquad = unitGroupUtils.membersToSquad
local scoreNeighborsForRetreat = neighborUtils.scoreNeighborsForRetreat local scoreNeighborsForRetreat = movementUtils.scoreNeighborsForRetreat
local findMovementPosition = movementUtils.findMovementPosition local findMovementPosition = movementUtils.findMovementPosition
local getRetreatTick = chunkUtils.getRetreatTick
local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator
local setRetreatTick = chunkUtils.setRetreatTick
local getNestCount = chunkUtils.getNestCount
local getWormCount = chunkUtils.getWormCount
-- module code -- module code
local function scoreRetreatLocation(neighborChunk) local function scoreRetreatLocation(regionMap, neighborChunk)
return -(neighborChunk[BASE_PHEROMONE] + -neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 100) + (neighborChunk[PLAYER_BASE_GENERATOR] * 20)) return -(neighborChunk[BASE_PHEROMONE] + -neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 100) + (getPlayerBaseGenerator(regionMap, neighborChunk) * 20))
end end
function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, natives, tick) function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, natives, tick)
if (tick - chunk[RETREAT_TRIGGERED] > INTERVAL_LOGIC) and (chunk[NEST_COUNT] == 0) and (chunk[WORM_COUNT] == 0) then if (tick - getRetreatTick(regionMap, chunk) > INTERVAL_LOGIC) and (getNestCount(regionMap, chunk) == 0) and (getWormCount(regionMap, chunk) == 0) then
local performRetreat = false local performRetreat = false
local enemiesToSquad = nil local enemiesToSquad = nil
if not squad then if not squad then
enemiesToSquad = surface.find_enemy_units(chunk, RETREAT_GRAB_RADIUS) enemiesToSquad = surface.find_enemy_units(position, 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
end end
if performRetreat then if performRetreat then
chunk[RETREAT_TRIGGERED] = tick setRetreatTick(regionMap, chunk, tick)
local exitPath,exitDirection = scoreNeighborsForRetreat(chunk, local exitPath,exitDirection = scoreNeighborsForRetreat(chunk,
getNeighborChunks(regionMap, getNeighborChunks(regionMap, chunk.x, chunk.y),
chunk.cX, scoreRetreatLocation,
chunk.cY), regionMap)
scoreRetreatLocation) if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
if exitPath then
local retreatPosition = findMovementPosition(surface, local retreatPosition = findMovementPosition(surface,
positionFromDirectionAndChunk(exitDirection, positionFromDirectionAndChunk(exitDirection, position, regionMap.position, 0.98),
position,
regionMap.position,
0.98),
false) false)
if not retreatPosition then if not retreatPosition then
return return
@@ -100,7 +97,7 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati
newSquad.rabid = true newSquad.rabid = true
end end
end end
addMovementPenalty(natives, newSquad, chunk.cX, chunk.cY) addMovementPenalty(natives, newSquad, chunk.x, chunk.y)
end end
end end
end end

View File

@@ -4,24 +4,18 @@ local tendrilUtils = {}
local constants = require("Constants") local constants = require("Constants")
local mapUtils = require("MapUtils") local mapUtils = require("MapUtils")
local baseRegisterUtils = require("BaseRegisterUtils")
local neighborsUtils = require("NeighborUtils")
local mathUtils = require("MathUtils")
local nestUtils = require("NestUtils") local nestUtils = require("NestUtils")
local mathUtils = require("MathUtils") local movementUtils = require("MovementUtils")
-- constants -- constants
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
local RESOURCE_GENERATOR = constants.RESOURCE_GENERATOR local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
local NEST_COUNT = constants.NEST_COUNT
-- imported functions -- imported functions
local scoreNeighborsForResource = neighborsUtils.scoreNeighborsForResource local scoreNeighborsForResource = movementUtils.scoreNeighborsForResource
local getNeighborChunks = mapUtils.getNeighborChunks local getNeighborChunks = mapUtils.getNeighborChunks
@@ -74,11 +68,9 @@ local function buildTendrilPath(regionMap, tendril, surface, base, tick, natives
end end
local tendrilPosition = tendrilUnit.position local tendrilPosition = tendrilUnit.position
local chunk = getChunkByPosition(regionMap, tendrilPosition.x, tendrilPosition.y) local chunk = getChunkByPosition(regionMap, tendrilPosition.x, tendrilPosition.y)
if chunk then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local tendrilPath,tendrilDirection = scoreNeighborsForResource(chunk, local tendrilPath,tendrilDirection = scoreNeighborsForResource(chunk,
getNeighborChunks(regionMap, getNeighborChunks(regionMap, chunk.x, chunk.y),
chunk.cX,
chunk.cY),
scoreTendrilChunk, scoreTendrilChunk,
nil) nil)
if (tendrilDirection == -1) then if (tendrilDirection == -1) then

View File

@@ -1,83 +0,0 @@
local worldProcessor = {}
-- imports
local constants = require("Constants")
-- constants
local ITEM_COLLECTOR_DISTANCE = constants.ITEM_COLLECTOR_DISTANCE
local ITEM_COLLECTOR_QUEUE_SIZE = constants.ITEM_COLLECTOR_QUEUE_SIZE
-- imported functions
-- module code
function worldProcessor.processWorld(surface, world, tick)
local collectors = world.itemCollectorEvents
if (#collectors > 0) then
local collectorLookup = world.itemCollectorLookup
local inserter = {name="", count=0}
local topLeftPosition = {x = 0, y = 0}
local bottomRightPosition = {x = 0, y = 0}
local boundingArea = {topLeftPosition,
bottomRightPosition}
local count = 0
for index = #collectors, 1, -1 do
count = count + 1
local itemCollectorPair = collectorLookup[collectors[index]]
collectors[index] = nil
if itemCollectorPair then
local chest = itemCollectorPair[1]
local dish = itemCollectorPair[2]
if chest.valid and dish.valid then
local collectorPosition = dish.position
topLeftPosition.x = collectorPosition.x - ITEM_COLLECTOR_DISTANCE
topLeftPosition.y = collectorPosition.y - ITEM_COLLECTOR_DISTANCE
bottomRightPosition.x = collectorPosition.x + ITEM_COLLECTOR_DISTANCE
bottomRightPosition.y = collectorPosition.y + ITEM_COLLECTOR_DISTANCE
local items = surface.find_entities_filtered({area = boundingArea,
name = "item-on-ground"})
local counts = {}
if (#items > 0) then
for x=1,#items do
local item = items[x]
local itemName = item.stack.name
if not counts[itemName] then
counts[itemName] = {item}
else
counts[itemName][#counts[itemName]+1] = item
end
end
for k,a in pairs(counts) do
inserter.name = k
inserter.count = #a
local stored = chest.insert(inserter)
for i=1,stored do
a[i].destroy()
end
end
-- dish.surface.create_entity({name="item-collector-base-particle-rampant",
-- position=dish.position})
end
end
end
if (count >= ITEM_COLLECTOR_QUEUE_SIZE) then
return
end
end
end
end
return worldProcessor

View File

@@ -1,6 +1,6 @@
[entity-name] [entity-name]
tunnel-entrance=Tunnel Entrance tunnel-entrance-rampant=Tunnel Entrance
small-suicide-biter=Small Suicide Biter small-suicide-biter=Small Suicide Biter
medium-suicide-biter=Medium Suicide Biter medium-suicide-biter=Medium Suicide Biter
@@ -9,7 +9,7 @@ behemoth-suicide-biter=Behemoth Suicide Biter
small-fire-spitter=Small Fire Spitter small-fire-spitter=Small Fire Spitter
biter-spawner-hive=Small Hive biter-spawner-hive-rampant=Small Hive
small-tendril-biter-rampant=Small Tendril small-tendril-biter-rampant=Small Tendril
item-collector-base-rampant=Item Collector item-collector-base-rampant=Item Collector
@@ -32,7 +32,7 @@ short-range-electrodynamics-1-rampant=Short-range Electrodynamics
short-range-electrodynamics-1-rampant=Buildings that generate strong electromagnetic fields short-range-electrodynamics-1-rampant=Buildings that generate strong electromagnetic fields
[entity-description] [entity-description]
tunnel-entrance=This tunnel is used by the biters to bypass player defenses. Fill the hole using landfill. tunnel-entrance-rampant=This tunnel is used by the biters to bypass player defenses. Fill the hole using landfill.
small-suicide-biter=These biters will explode at close range small-suicide-biter=These biters will explode at close range
medium-suicide-biter=These biters will explode at close range medium-suicide-biter=These biters will explode at close range
@@ -41,7 +41,7 @@ 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 biter-spawner-hive-rampant=Small Hive
small-tendril-biter-rampant=Small Tendril small-tendril-biter-rampant=Small Tendril
item-collector-base-rampant=Scans the surrounding area for items on the ground, if any items are found they are pulled into the storage chest when the sector is finished scanning. item-collector-base-rampant=Scans the surrounding area for items on the ground, if any items are found they are pulled into the storage chest when the sector is finished scanning.

View File

@@ -36,6 +36,7 @@
(string->path "README.md") (string->path "README.md")
(string->path "NOTICE") (string->path "NOTICE")
(string->path "libs") (string->path "libs")
(string->path "sounds")
(string->path "locale") (string->path "locale")
(string->path "graphics") (string->path "graphics")
(string->path "prototypes"))) (string->path "prototypes")))
@@ -72,12 +73,13 @@
(copyFile "tests.lua" modFolder) (copyFile "tests.lua" modFolder)
(copyDirectory "libs" modFolder) (copyDirectory "libs" modFolder)
(copyDirectory "locale" modFolder) (copyDirectory "locale" modFolder)
(copyDirectory "sounds" modFolder)
(copyDirectory "graphics" modFolder) (copyDirectory "graphics" modFolder)
(copyDirectory "prototypes" modFolder))) (copyDirectory "prototypes" modFolder)))
(define (run) (define (run)
;;(copyFiles modFolder) (copyFiles modFolder)
;;(copyFiles zipModFolder) ;;(copyFiles zipModFolder)
(makeZip modFolder) ;;(makeZip modFolder)
) )
) )

View File

@@ -1,197 +0,0 @@
-- overlays
local radar = util.table.deepcopy(data.raw["radar"]["radar"])
radar.name = "item-collector-base-rampant"
radar.icon = "__Rampant__/graphics/icon/itemCollectorIcon.png"
radar.collision_box = {{-0.35, -0.35}, {0.35, 0.35}}
radar.selection_box = {{-0.485, -0.7}, {0.465, -0.1}}
radar.energy_per_sector = "27MJ"
radar.max_distance_of_nearby_sector_revealed = 1
radar.max_distance_of_sector_revealed = 0
radar.energy_per_nearby_scan = "27MJ"
radar.energy_usage = "450KW"
radar.flags[#radar.flags+1] = "not-deconstructable"
radar.pictures = {
filename = "__Rampant__/graphics/entities/chest/itemCollector.png",
priority = "low",
width = 46,
height = 49,
apply_projection = false,
direction_count = 64,
line_length = 8,
shift = {0.1875, -0.24}
}
radar.minable = nil
-- local particle = {
-- type = "explosion",
-- name = "item-collector-base-particle-rampant",
-- flags = {"not-on-map"},
-- animations =
-- {
-- {
-- filename = "__Rampant__/graphics/entities/chest/itemCollectorParticle.png",
-- priority = "extra-high",
-- width = 46,
-- height = 49,
-- frame_count = 16,
-- line_length = 8,
-- animation_speed = 0.2
-- }
-- },
-- light = {intensity = 1, size = 20, color = {r=1.0, g=1.0, b=1.0}},
-- smoke = "smoke-fast",
-- smoke_count = 0,
-- smoke_slow_down_factor = 1,
-- sound =
-- {
-- aggregation =
-- {
-- max_count = 1,
-- remove = true
-- },
-- variations =
-- {
-- {
-- filename = "__base__/sound/fight/small-explosion-1.ogg",
-- volume = 0.75
-- }
-- }
-- }
-- }
local radarOverlay = util.table.deepcopy(radar)
radarOverlay.name = "item-collector-base-overlay-rampant"
radarOverlay.pictures.filename = "__Rampant__/graphics/entities/chest/itemCollectorOverlay2.png"
radarOverlay.pictures.width = 2048
radarOverlay.pictures.height = 2048
radarOverlay.pictures.direction_count = 1
radarOverlay.pictures.line_length = 1
radarOverlay.pictures.shift[2] = 0.07
radarOverlay.pictures.hr_version = {
filename = "__Rampant__/graphics/entities/chest/itemCollectorOverlay2.5.png",
priority = "low",
width = 3200,
height = 3200,
apply_projection = false,
direction_count = 1,
line_length = 1,
shift = {0.1875, -0.24}
}
local chest = util.table.deepcopy(data.raw["container"]["steel-chest"])
chest.name = "item-collector-chest-rampant"
chest.picture = {
filename = "__core__/graphics/empty.png",
priority = "low",
width = 46,
height = 49,
line_length = 1,
shift = {0.1875, -0.2}
}
chest.selection_box = {{-0.485, -0.1}, {0.465, 0.6}}
chest.collision_mask = {}
chest.minable.result = "item-collector-base-rampant"
data:extend({
radar,
radarOverlay,
chest-- ,
-- particle
})
data:extend({
{
type = "recipe",
name = "item-collector-base-rampant",
normal = {
enabled = false,
energy_required = 10,
ingredients = {
{"steel-chest", 1},
{"accumulator", 1},
{"radar", 1}
},
result = "item-collector-base-rampant",
requester_paste_multiplier = 4
},
expensive = {
enabled = false,
energy_required = 10,
ingredients = {
{"steel-chest", 2},
{"accumulator", 2},
{"radar", 2}
},
result = "item-collector-base-rampant",
requester_paste_multiplier = 4
}
},
{
type = "item",
name = "item-collector-base-rampant",
icon = "__Rampant__/graphics/icon/itemCollectorIcon.png",
flags = {"goes-to-quickbar"},
subgroup = "storage",
order = "a[items]-c[steel-collector]",
place_result = "item-collector-base-rampant",
stack_size = 50
},
{
type = "item",
name = "item-collector-base-overlay-rampant",
icon = "__Rampant__/graphics/icon/itemCollectorIcon.png",
flags = {"goes-to-quickbar"},
subgroup = "storage",
order = "a[items]-c[steel-collector]",
place_result = "item-collector-base-overlay-rampant",
stack_size = 50
},
{
type = "item",
name = "item-collector-chest-rampant",
icon = "__Rampant__/graphics/icon/itemCollectorIcon.png",
flags = {"goes-to-quickbar"},
subgroup = "storage",
order = "a[items]-c[steel-collector]",
place_result = "item-collector-chest-rampant",
stack_size = 50
}
})
-- technology insertions
data:extend({
{
type = "technology",
name = "short-range-electrodynamics-1-rampant",
icon = "__Rampant__/graphics/technology/itemCollectorTech.png",
icon_size = 128,
localised_name = {"technology-name.short-range-electrodynamics-1-rampant"},
effects =
{
{
type = "unlock-recipe",
recipe = "item-collector-base-rampant"
}
},
prerequisites = {"electric-energy-accumulators-1"},
unit =
{
count = 200,
ingredients =
{
{"science-pack-1", 1},
{"science-pack-2", 1}
},
time = 22
},
order = "c-e-a",
},
})

View File

@@ -102,7 +102,7 @@ data:extend({
{ {
type = "unit-spawner", type = "unit-spawner",
name = "biter-spawner-hive", name = "biter-spawner-hive-rampant",
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,

View File

@@ -1,7 +1,7 @@
data:extend({ data:extend({
{ {
type = "simple-entity", type = "simple-entity",
name = "tunnel-entrance", name = "tunnel-entrance-rampant",
flags = {"placeable-neutral", "placeable-off-grid", "not-on-map"}, flags = {"placeable-neutral", "placeable-off-grid", "not-on-map"},
icon = "__base__/graphics/icons/small-scorchmark.png", icon = "__base__/graphics/icons/small-scorchmark.png",
subgroup = "grass", subgroup = "grass",

View File

@@ -10,278 +10,95 @@ local makeColor = colorUtils.makeColor
-- dumb acid projectiles -- dumb acid projectiles
makeStream({ local templateDamage = { amount = 4, type = "acid" }
name = "acid-ball", local templateArea = {
particleTint = {r=0, g=1, b=1, a=0.5}, type = "area",
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, perimeter = 1.2,
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1), action_delivery =
actions = { {
{ {
type = "area", type = "instant",
perimeter = 1.5, target_effects =
action_delivery =
{ {
{ {
type = "instant", type = "damage",
target_effects = damage = templateDamage
{
{
type = "damage",
damage = { amount = 15, type = "acid" }
}
}
} }
} }
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
} }
} }
}) }
local templateActions = {
templateArea,
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
local template = {
name = "acid-ball",
particleTint = {r=0, g=1, b=1, a=0.5},
spineAnimationTint = {r=0, g=1, b=1, a=0.5},
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = templateActions
}
makeStream(template)
-- --
makeStream({ template.name = "acid-ball-1"
name = "acid-ball-1", templateDamage.amount = 9
particleTint = {r=0, g=1, b=1, a=0.5}, templateArea.perimeter = 1.3
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, makeStream(template)
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = {
{
type = "area",
perimeter = 1.5,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 22, type = "acid" }
},
{
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
})
-- --
makeStream({ template.name = "acid-ball-2"
name = "acid-ball-2", templateDamage.amount = 14
particleTint = {r=0, g=1, b=1, a=0.5}, templateArea.perimeter = 1.4
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, makeStream(template)
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = {
{
type = "area",
perimeter = 1.5,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 32, type = "acid" }
},
{
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
})
-- --
makeStream({ template.name = "acid-ball-3"
name = "acid-ball-3", templateDamage.amount = 23
particleTint = {r=0, g=1, b=1, a=0.5}, templateArea.perimeter = 1.5
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, makeStream(template)
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = {
{
type = "area",
perimeter = 1.5,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 45, type = "acid" }
},
{
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
})
-- --
makeStream({ template.name = "wide-acid-ball"
name = "wide-acid-ball", templateDamage.amount = 18
particleTint = {r=0, g=1, b=1, a=0.5}, templateArea.perimeter = 3
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, makeStream(template)
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = {
{
type = "area",
perimeter = 3,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 35, type = "acid" }
},
{
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
})
-- --
makeStream({ template.name = "acid-ball-4"
name = "acid-ball-4", templateDamage.amount = 25
particleTint = {r=0, g=1, b=1, a=0.5}, templateArea.perimeter = 1.75
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, makeStream(template)
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = {
{
type = "area",
perimeter = 2,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 95, type = "acid" }
},
{
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
})
-- --
makeStream({ template.name = "acid-ball-5"
name = "acid-ball-5", templateDamage.amount = 50
particleTint = {r=0, g=1, b=1, a=0.5}, templateArea.perimeter = 2
spineAnimationTint = {r=0, g=1, b=1, a=0.5}, makeStream(template)
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = { --
{
type = "area", template.name = "acid-ball-6"
perimeter = 2, templateDamage.amount = 70
action_delivery = templateArea.perimeter = 2.5
{ makeStream(template)
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 145, type = "acid" }
},
{
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
},
{
type = "direct",
action_delivery = {
type = "instant",
target_effects = {
type= "create-entity",
entity_name = "acid-splash-purple"
}
}
}
}
})

View File

@@ -57,57 +57,7 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 35, type = "explosion" } damage = { amount = 25, type = "explosion" }
}
}
}
}
}
})
--
makeStream({
name = "bob-explosive-ball-1",
particleTint = {r=1, g=0.97, b=0.34, a=0.5},
spineAnimationTint = {r=1, g=0.97, b=0.34, a=0.5},
softSmokeTint = makeColor(0.3, 0.75, 0.3, 0.1),
actions = {
{
type = "direct",
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "create-entity",
entity_name = "small-scorchmark",
check_buildability = true
},
{
type = "create-entity",
entity_name = "big-explosion",
check_buildability = true
},
{
type = "create-entity",
entity_name = "small-fire-cloud"
}
}
}
},
{
type = "area",
perimeter = 3,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 55, type = "explosion" }
} }
} }
} }
@@ -166,7 +116,7 @@ makeStream({
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 43, type = "fire" } damage = { amount = 20, type = "fire" }
} }
} }
} }
@@ -214,47 +164,6 @@ makeStream({
} }
}) })
--
makeStream({
name = "bob-poison-ball-1",
particleTint = {r=0.1, g=0.5, b=1, a=0.5},
spineAnimationTint = {r=0, g=0, b=1, a=0.5},
softSmokeTint = makeColor(0.7, 0.4, 0.2, 0.1),
actions = {
{
type = "direct",
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "create-entity",
entity_name = "small-poison-cloud"
}
}
}
},
{
type = "area",
perimeter = 2,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 43, type = "poison" }
}
}
}
}
}
})
-- piercing -- piercing
data:extend({ data:extend({
@@ -318,7 +227,7 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 43, type = "bob-pierce" } damage = { amount = 30, type = "bob-pierce" }
} }
} }
} }
@@ -400,47 +309,7 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 10, type = "electric" } damage = { amount = 25, type = "electric" }
}
}
}
}
}
})
--
makeStream({
name = "bob-electric-ball-1",
particleTint = {r=0, g=0.1, b=1, a=1},
spineAnimationTint = {r=0, g=0.1, b=1, a=1},
softSmokeTint = makeColor(0.7, 0.4, 0.2, 0.1),
actions = {
{
type = "cluster",
cluster_count = 10,
distance = 4,
distance_deviation = 3,
action_delivery =
{
type = "projectile",
projectile = "electric-spike-rampant",
direction_deviation = 0.6,
starting_speed = 0.65,
starting_speed_deviation = 0.0
}
},
{
type = "area",
perimeter = 3,
action_delivery =
{
type = "instant",
target_effects =
{
{
type = "damage",
damage = { amount = 55, type = "electric" }
} }
} }
} }
@@ -465,7 +334,7 @@ makeStream({
{ {
{ {
type = "create-entity", type = "create-entity",
entity_name = "small-poison-cloud" entity_name = "small-fire-cloud"
}, },
{ {
type = "create-entity", type = "create-entity",
@@ -484,19 +353,15 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 15, type = "electric" } damage = { amount = 10, type = "electric" }
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 15, type = "explosion" } damage = { amount = 10, type = "explosion" }
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 15, type = "fire" } damage = { amount = 10, type = "fire" }
},
{
type = "damage",
damage = { amount = 15, type = "poison" }
} }
} }
} }
@@ -615,7 +480,7 @@ makeStream({
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 20, type = "explosion" } damage = { amount = 15, type = "explosion" }
}, },
{ {
type = "damage", type = "damage",
@@ -631,7 +496,7 @@ makeStream({
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 20, type = "acid" } damage = { amount = 15, type = "acid" }
} }
} }
} }

View File

@@ -42,7 +42,7 @@ makeStream({
}, },
{ {
type = "damage", type = "damage",
damage = {amount = 25, type = "poison"} damage = {amount = 24, type = "poison"}
} }
} }
} }
@@ -91,11 +91,11 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 5, type = "explosion" } damage = { amount = 8, type = "explosion" }
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 15, type = "acid" } damage = { amount = 18, type = "acid" }
} }
} }
} }
@@ -135,11 +135,11 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 3, type = "explosion" } damage = { amount = 5, type = "explosion" }
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 7, type = "poison" } damage = { amount = 12, type = "poison" }
} }
} }
} }
@@ -183,11 +183,11 @@ makeStream({
{ {
{ {
type = "damage", type = "damage",
damage = { amount = 7, type = "explosion" } damage = { amount = 5, type = "explosion" }
}, },
{ {
type = "damage", type = "damage",
damage = { amount = 14, type = "acid" } damage = { amount = 12, type = "acid" }
} }
} }
} }

View File

@@ -218,22 +218,50 @@ function biterFunctions.createFireAttack(attributes, fireAttack)
begin_sound = begin_sound =
{ {
{ {
filename = "__base__/sound/fight/flamethrower-start.ogg", filename = "__base__/sound/creatures/spitter-1.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-2.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-3.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-4.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-5.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-6.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-7.ogg",
volume = 0.7
},
{
filename = "__base__/sound/creatures/spitter-8.ogg",
volume = 0.7 volume = 0.7
} }
}, },
middle_sound = middle_sound =
{ {
{ {
filename = "__base__/sound/fight/flamethrower-mid.ogg", filename = attributes.midSound or "__Rampant__/sounds/attacks/acid-mid.ogg",
volume = 0.7 volume = 0.5
} }
}, },
end_sound = end_sound =
{ {
{ {
filename = "__base__/sound/fight/flamethrower-end.ogg", filename = attributes.endSound or "__Rampant__/sounds/attacks/acid-end.ogg",
volume = 0.7 volume = 0.5
} }
} }
} }

View File

@@ -10,7 +10,8 @@ local makeSmokeSoft = smokeUtils.makeSmokeSoft
-- module code -- module code
function streamUtils.makeStream(attributes) function streamUtils.makeStream(info)
local attributes = util.table.deepcopy(info)
local softSmokeName = attributes.softSmokeName or makeSmokeSoft(attributes) local softSmokeName = attributes.softSmokeName or makeSmokeSoft(attributes)
data:extend( data:extend(
{ {
@@ -79,7 +80,7 @@ function streamUtils.makeStream(attributes)
height = 64, height = 64,
frame_count = 32, frame_count = 32,
line_length = 8 line_length = 8
}, }
} }
} }
) )

View File

@@ -7,19 +7,19 @@ function bobsUpdates.useDumbProjectiles()
turrets["bob-big-explosive-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-big-explosive-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 25, range = 26,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
scale = 1.2 scale = 1.2
}, },
"bob-explosive-ball-1-stream-rampant") "bob-explosive-ball-stream-rampant")
turrets["bob-big-fire-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-big-fire-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 25, range = 26,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
@@ -29,19 +29,19 @@ function bobsUpdates.useDumbProjectiles()
turrets["bob-big-poison-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-big-poison-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 25, range = 26,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
scale = 1.2 scale = 1.2
}, },
"bob-poison-ball-1-stream-rampant") "bob-poison-ball-stream-rampant")
turrets["bob-big-piercing-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-big-piercing-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 25, range = 26,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
@@ -51,44 +51,44 @@ function bobsUpdates.useDumbProjectiles()
turrets["bob-big-electric-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-big-electric-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 25, range = 26,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
scale = 1.2 scale = 1.2
}, },
"bob-electric-ball-1-stream-rampant") "bob-electric-ball-stream-rampant")
turrets["bob-giant-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-giant-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 28, range = 28,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
scale = 1.6 scale = 1.6
}, },
"acid-ball-4-stream-rampant") "acid-ball-5-stream-rampant")
turrets["bob-behemoth-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["bob-behemoth-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 30, range = 30,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
scale = 2 scale = 2
}, },
"acid-ball-5-stream-rampant") "acid-ball-6-stream-rampant")
local units = data.raw["unit"] local units = data.raw["unit"]
local unit = units["behemoth-spitter"] local unit = units["behemoth-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
warmup = 30, warmup = 30,
@@ -102,10 +102,11 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-big-electric-spitter"] unit = units["bob-big-electric-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 15,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
damageModifier = 0.6,
warmup = 30, warmup = 30,
fire_penalty = 0, fire_penalty = 0,
scale = biterUtils.findRunScale(unit), scale = biterUtils.findRunScale(unit),
@@ -117,11 +118,12 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-huge-explosive-spitter"] unit = units["bob-huge-explosive-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
warmup = 30, warmup = 30,
turn_range = 1, turn_range = 1,
damageModifier = 0.8,
fire_penalty = 15, fire_penalty = 15,
scale = biterUtils.findRunScale(unit), scale = biterUtils.findRunScale(unit),
tint1 = biterUtils.findTint(unit), tint1 = biterUtils.findTint(unit),
@@ -132,8 +134,8 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-huge-acid-spitter"] unit = units["bob-huge-acid-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
warmup = 30, warmup = 30,
@@ -147,8 +149,8 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-giant-fire-spitter"] unit = units["bob-giant-fire-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
warmup = 30, warmup = 30,
@@ -162,8 +164,8 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-giant-poison-spitter"] unit = units["bob-giant-poison-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
warmup = 30, warmup = 30,
@@ -177,8 +179,8 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-titan-spitter"] unit = units["bob-titan-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
warmup = 30, warmup = 30,
@@ -192,8 +194,8 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-behemoth-spitter"] unit = units["bob-behemoth-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
warmup = 30, warmup = 30,
@@ -208,8 +210,8 @@ function bobsUpdates.useDumbProjectiles()
unit = units["bob-leviathan-spitter"] unit = units["bob-leviathan-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 17,
min_range = 3, min_range = 3,
warmup = 30, warmup = 30,
turn_range = 1, turn_range = 1,

View File

@@ -7,8 +7,8 @@ function NEUpdates.useNEUnitLaunchers ()
turrets["medium-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["medium-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 22, range = 25,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
@@ -19,8 +19,8 @@ function NEUpdates.useNEUnitLaunchers ()
turrets["big-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["big-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 27, range = 30,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
@@ -40,13 +40,13 @@ function NEUpdates.useDumbProjectiles()
turret["attack_parameters"].range = 22 turret["attack_parameters"].range = 22
turret["attack_parameters"] = biterUtils.createFireAttack( turret["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 22, range = 25,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
damageModifier = 4.5, damageModifier = 4.5,
scale = 1.0 scale = 1.2
}, },
"ne-infected-ball-stream-rampant") "ne-infected-ball-stream-rampant")
@@ -54,13 +54,13 @@ function NEUpdates.useDumbProjectiles()
turret["attack_parameters"].range = 27 turret["attack_parameters"].range = 27
turret["attack_parameters"] = biterUtils.createFireAttack( turret["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 27, range = 30,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
damageModifier = 5.5, damageModifier = 5.5,
scale = 1.2 scale = 1.6
}, },
"ne-mutated-ball-stream-rampant") "ne-mutated-ball-stream-rampant")
@@ -69,7 +69,7 @@ function NEUpdates.useDumbProjectiles()
local unit = units["small-spitter-Mk2"] local unit = units["small-spitter-Mk2"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 150, cooldown = 100,
range = 13, range = 13,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
@@ -85,7 +85,7 @@ function NEUpdates.useDumbProjectiles()
unit = units["small-spitter-Mk3"] unit = units["small-spitter-Mk3"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 150, cooldown = 100,
range = 13, range = 13,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
@@ -102,7 +102,7 @@ function NEUpdates.useDumbProjectiles()
unit = units["medium-spitter-Mk2"] unit = units["medium-spitter-Mk2"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 150, cooldown = 100,
range = 14, range = 14,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
@@ -118,7 +118,7 @@ function NEUpdates.useDumbProjectiles()
unit = units["medium-spitter-Mk3"] unit = units["medium-spitter-Mk3"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 150, cooldown = 100,
range = 14, range = 14,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
@@ -134,7 +134,7 @@ function NEUpdates.useDumbProjectiles()
unit = units["big-spitter-Mk2"] unit = units["big-spitter-Mk2"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 150, cooldown = 100,
range = 15, range = 15,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
@@ -151,7 +151,7 @@ function NEUpdates.useDumbProjectiles()
unit = units["big-spitter-Mk3"] unit = units["big-spitter-Mk3"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 150, cooldown = 100,
range = 15, range = 15,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,

View File

@@ -7,44 +7,46 @@ function vanillaUpdates.useDumbProjectiles()
turrets["small-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["small-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 50, cooldown = 60,
range = 18, range = 21,
min_range = 5, min_range = 5,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
damageModifier = 0.9,
scale = 0.8 scale = 0.8
}, },
"acid-ball-stream-rampant") "acid-ball-2-stream-rampant")
turrets["medium-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["medium-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 20, range = 25,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
damageModifier = 0.87,
scale = 1 scale = 1
}, },
"acid-ball-1-stream-rampant") "acid-ball-3-stream-rampant")
turrets["big-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( turrets["big-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 60,
range = 25, range = 26,
min_range = 3, min_range = 3,
turn_range = 1, turn_range = 1,
fire_penalty = 0, fire_penalty = 0,
scale = 1.2 scale = 1.2
}, },
"acid-ball-2-stream-rampant") "acid-ball-4-stream-rampant")
local units = data.raw["unit"]; local units = data.raw["unit"];
local unit = units["small-spitter"] local unit = units["small-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 100,
range = 13, range = 13,
warmup = 30, warmup = 30,
min_range = 3, min_range = 3,
@@ -59,7 +61,7 @@ function vanillaUpdates.useDumbProjectiles()
unit = units["medium-spitter"] unit = units["medium-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 95,
range = 14, range = 14,
min_range = 3, min_range = 3,
warmup = 30, warmup = 30,
@@ -74,7 +76,7 @@ function vanillaUpdates.useDumbProjectiles()
unit = units["big-spitter"] unit = units["big-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 15,
min_range = 3, min_range = 3,
warmup = 30, warmup = 30,
@@ -89,8 +91,8 @@ function vanillaUpdates.useDumbProjectiles()
unit = units["behemoth-spitter"] unit = units["behemoth-spitter"]
unit["attack_parameters"] = biterUtils.createFireAttack( unit["attack_parameters"] = biterUtils.createFireAttack(
{ {
cooldown = 80, cooldown = 90,
range = 15, range = 16,
min_range = 3, min_range = 3,
warmup = 30, warmup = 30,
turn_range = 1, turn_range = 1,

View File

@@ -193,17 +193,6 @@ data:extend({
order = "h[modifier]-a[optimize]", order = "h[modifier]-a[optimize]",
per_user = false per_user = false
}, },
{
type = "bool-setting",
name = "rampant-enableBuildings",
description = "rampant-enableBuildings",
setting_type = "startup",
default_value = true,
order = "i[modifier]-a[buildings]",
per_user = false
},
{ {
type = "bool-setting", type = "bool-setting",

BIN
sounds/attacks/acid-end.ogg Executable file

Binary file not shown.

BIN
sounds/attacks/acid-mid.ogg Executable file

Binary file not shown.

View File

@@ -5,22 +5,23 @@ local mathUtils = require("libs/MathUtils")
local chunkUtils = require("libs/ChunkUtils") local chunkUtils = require("libs/ChunkUtils")
local mapUtils = require("libs/MapUtils") local mapUtils = require("libs/MapUtils")
local baseUtils = require("libs/BaseUtils") local baseUtils = require("libs/BaseUtils")
local baseRegisterUtils = require("libs/BaseRegisterUtils") -- local tendrilUtils = require("libs/TendrilUtils")
local tendrilUtils = require("libs/TendrilUtils")
function tests.pheromoneLevels(size) function tests.pheromoneLevels(size)
local player = game.player.character local player = game.player.character
local playerChunkX = math.floor(player.position.x / 32) local playerChunkX = math.floor(player.position.x / 32) * constants.CHUNK_SIZE
local playerChunkY = math.floor(player.position.y / 32) local playerChunkY = math.floor(player.position.y / 32) * constants.CHUNK_SIZE
if not size then if not size then
size = 3 size = 3 * constants.CHUNK_SIZE
else
size = size * constants.CHUNK_SIZE
end end
print("------") print("------")
print(#global.regionMap.processQueue) print(#global.regionMap.processQueue)
print(playerChunkX .. ", " .. playerChunkY) print(playerChunkX .. ", " .. playerChunkY)
print("--") print("--")
for y=playerChunkY-size, playerChunkY+size do for y=playerChunkY-size, playerChunkY+size,32 do
for x=playerChunkX-size, playerChunkX+size do for x=playerChunkX-size, playerChunkX+size,32 do
if (global.regionMap[x] ~= nil) then if (global.regionMap[x] ~= nil) then
local chunk = global.regionMap[x][y] local chunk = global.regionMap[x][y]
if (chunk ~= nil) then if (chunk ~= nil) then
@@ -29,12 +30,12 @@ function tests.pheromoneLevels(size)
str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i]) str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i])
end end
str = str .. " " .. "p/" .. game.surfaces[1].get_pollution(chunk) str = str .. " " .. "p/" .. game.surfaces[1].get_pollution(chunk)
if (chunk.cX == playerChunkX) and (chunk.cY == playerChunkY) then if (chunk.x == playerChunkX) and (chunk.y == playerChunkY) then
print("=============") print("=============")
print(chunk.cX, chunk.cY, str) print(chunk.x, chunk.y, str)
print("=============") print("=============")
else else
print(chunk.cX, chunk.cY, str) print(chunk.x, chunk.y, str)
end end
-- print(str) -- print(str)
print("----") print("----")
@@ -109,7 +110,7 @@ function tests.tunnelTest()
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="tunnel-entrance", position={chunkX, chunkY}}) game.surfaces[1].create_entity({name="tunnel-entrance-rampant", position={chunkX, chunkY}})
end end
function tests.createEnemy(x) function tests.createEnemy(x)
@@ -121,7 +122,7 @@ end
function tests.registeredNest(x) function tests.registeredNest(x)
local entity = tests.createEnemy(x) local entity = tests.createEnemy(x)
baseRegisterUtils.registerEnemyBaseStructure(global.regionMap, chunk.registerEnemyBaseStructure(global.regionMap,
entity, entity,
nil) nil)
end end
@@ -280,9 +281,9 @@ function tests.showMovementGrid()
end end
function tests.stepAdvanceTendrils() function tests.stepAdvanceTendrils()
for _, base in pairs(global.natives.bases) do -- for _, base in pairs(global.natives.bases) do
tendrilUtils.advanceTendrils(global.regionMap, base, game.surfaces[1], {nil,nil,nil,nil,nil,nil,nil,nil}) -- tendrilUtils.advanceTendrils(global.regionMap, base, game.surfaces[1], {nil,nil,nil,nil,nil,nil,nil,nil})
end -- end
end end
return tests return tests