diff --git a/README.md b/README.md index 171968e..cfe754b 100755 --- a/README.md +++ b/README.md @@ -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 - 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 -- Item Collector + Technology to unlock it - An entity that collects the items on the ground around itself # Planned Features @@ -61,6 +60,14 @@ Configure Options not in game menu: # 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 - - Contribution - Martok88, Improvement: Added optional attack wave message per player diff --git a/Upgrade.lua b/Upgrade.lua index 1823243..50e4070 100755 --- a/Upgrade.lua +++ b/Upgrade.lua @@ -8,7 +8,6 @@ local mathUtils = require("libs/MathUtils") -- constants local INTERVAL_LOGIC = constants.INTERVAL_LOGIC -local INTERVAL_PROCESS = constants.INTERVAL_PROCESS -- imported functions @@ -16,7 +15,7 @@ local roundToNearest = mathUtils.roundToNearest -- module code -function upgrade.attempt(natives, world) +function upgrade.attempt(natives) local starting = global.version if (global.version == nil) then natives.squads = {} @@ -157,25 +156,14 @@ function upgrade.attempt(natives, world) game.surfaces[1].print("Rampant - Version 0.15.17") global.version = constants.VERSION_27 end - if (global.version < constants.VERSION_28) then + if (global.version < constants.VERSION_33) then - if (world == nil) then - global.world = {} - world = global.world - end - - world.itemCollectorLookup = {} - world.itemCollectorEvents = {} + global.world = nil - game.surfaces[1].print("Rampant - Version 0.15.18") - global.version = constants.VERSION_28 + game.surfaces[1].print("Rampant - Version 0.15.23") + global.version = constants.VERSION_33 end - if (global.version < constants.VERSION_32) then - - game.surfaces[1].print("Rampant - Version 0.15.22") - global.version = constants.VERSION_32 - end - return starting ~= global.version, natives, world + return starting ~= global.version, natives end function upgrade.compareTable(entities, option, new) diff --git a/control.lua b/control.lua index 63a0dc5..5b209c6 100755 --- a/control.lua +++ b/control.lua @@ -1,6 +1,5 @@ -- imports -local entityUtils = require("libs/EntityUtils") local mapUtils = require("libs/MapUtils") local unitGroupUtils = require("libs/UnitGroupUtils") local chunkProcessor = require("libs/ChunkProcessor") @@ -14,14 +13,10 @@ local aiAttackWave = require("libs/AIAttackWave") local aiPlanning = require("libs/AIPlanning") local interop = require("libs/Interop") local tests = require("tests") +local chunkUtils = require("libs/ChunkUtils") local upgrade = require("Upgrade") -local baseRegisterUtils = require("libs/BaseRegisterUtils") local mathUtils = require("libs/MathUtils") 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 @@ -30,12 +25,7 @@ local INTERVAL_PROCESS = constants.INTERVAL_PROCESS local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE -local DEFINES_INVENTORY_PLAYER_MAIN = defines.inventory.player_main -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 SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK local AI_MAX_OVERFLOW_POINTS = constants.AI_MAX_OVERFLOW_POINTS @@ -49,17 +39,6 @@ local getChunkByPosition = mapUtils.getChunkByPosition 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 processPlayers = mapProcessor.processPlayers local scanMap = mapProcessor.scanMap @@ -80,23 +59,22 @@ local squadsBeginAttack = squadAttack.squadsBeginAttack local retreatUnits = squadDefense.retreatUnits -local addRemovePlayerEntity = entityUtils.addRemovePlayerEntity -local unregisterEnemyBaseStructure = baseRegisterUtils.unregisterEnemyBaseStructure -local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure -local makeImmortalEntity = entityUtils.makeImmortalEntity +local addRemovePlayerEntity = chunkUtils.addRemovePlayerEntity +local unregisterEnemyBaseStructure = chunkUtils.unregisterEnemyBaseStructure +local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure +local makeImmortalEntity = chunkUtils.makeImmortalEntity local processBases = baseProcessor.processBases local mRandom = math.random -local getPlayerInventory = playerUtils.getPlayerInventory +local positionToChunkXY = mapUtils.positionToChunkXY -- local references to global local regionMap -- manages the chunks that make up the game world local natives -- manages the enemy units, structures, and ai 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 @@ -110,13 +88,10 @@ local function onIonCannonFired(event) if (natives.points > AI_MAX_OVERFLOW_POINTS) then natives.points = AI_MAX_OVERFLOW_POINTS end - local chunk = getChunkByPosition(regionMap, event.position.x, event.position.y) - if chunk then - rallyUnits(chunk, - regionMap, - surface, - natives, - event.tick) + local chunkX, chunkY = positionToChunkXY(event.position) + local chunk = getChunkByPosition(regionMap, chunkX, chunkY) + if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then + rallyUnits(chunk, regionMap, surface, natives, event.tick) end end end @@ -134,7 +109,6 @@ local function onLoad() regionMap = global.regionMap natives = global.natives pendingChunks = global.pendingChunks - world = global.world hookEvents() end @@ -158,9 +132,28 @@ local function rebuildRegionMap() regionMap.processQueue = {} regionMap.processIndex = 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. - regionMap.neighbors = { nil, nil, nil, nil, nil, nil, nil, nil } - regionMap.cardinalNeighbors = { nil, nil, nil, nil } + regionMap.neighbors = { SENTINEL_IMPASSABLE_CHUNK, + 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.position = {x=0, y=0} @@ -242,7 +235,7 @@ end local function onConfigChanged() local upgraded - upgraded, natives, world = upgrade.attempt(natives, world) + upgraded, natives = upgrade.attempt(natives) if upgraded and onModSettingsChange(nil) then rebuildRegionMap() end @@ -271,8 +264,6 @@ local function onTick(event) cleanSquads(natives) regroupSquads(natives) - processWorld(surface, world, tick) - processPlayers(players, regionMap, surface, natives, tick) if natives.useCustomAI then @@ -288,7 +279,7 @@ local function onTick(event) end local function onBuild(event) - local entity = buildComplexEntity(event.created_entity, world) + local entity = event.created_entity addRemovePlayerEntity(regionMap, entity, natives, true, false) if natives.safeBuildings then if natives.safeEntities[entity.type] or natives.safeEntityName[entity.name] then @@ -298,24 +289,20 @@ local function onBuild(event) end local function onMine(event) - mineComplexEntity(addRemovePlayerEntity(regionMap, - event.entity, - natives, - false, - false), - world) + addRemovePlayerEntity(regionMap, event.entity, natives, false, false) end local function onDeath(event) local entity = event.entity local surface = entity.surface if (surface.index == 1) then + local entityPosition = entity.position + local chunkX, chunkY = positionToChunkXY(entityPosition) if (entity.force.name == "enemy") then if (entity.type == "unit") then - local entityPosition = entity.position - local deathChunk = getChunkByPosition(regionMap, entityPosition.x, entityPosition.y) + local deathChunk = getChunkByPosition(regionMap, chunkX, chunkY) - if deathChunk then + if (deathChunk ~= SENTINEL_IMPASSABLE_CHUNK) then -- drop death pheromone where unit died deathScent(deathChunk) @@ -324,18 +311,14 @@ local function onDeath(event) retreatUnits(deathChunk, entityPosition, - convertUnitGroupToSquad(natives, - entity.unit_group), + convertUnitGroupToSquad(natives, entity.unit_group), regionMap, surface, natives, tick) + if (mRandom() < natives.rallyThreshold) and not surface.peaceful_mode then - rallyUnits(deathChunk, - regionMap, - surface, - natives, - tick) + rallyUnits(deathChunk, regionMap, surface, natives, tick) end end end @@ -345,32 +328,24 @@ local function onDeath(event) end elseif (entity.force.name == "player") then local creditNatives = false - local entityPosition = entity.position if (event.force ~= nil) and (event.force.name == "enemy") then creditNatives = true - local victoryChunk = getChunkByPosition(regionMap, entityPosition.x, entityPosition.y) - if victoryChunk then + local victoryChunk = getChunkByPosition(regionMap, chunkX, chunkY) + if (victoryChunk ~= SENTINEL_IMPASSABLE_CHUNK) then victoryScent(victoryChunk, entity.type) end end if creditNatives and natives.safeBuildings and (natives.safeEntities[entity.type] or natives.safeEntityName[entity.name]) then makeImmortalEntity(surface, entity) else - mineComplexEntity(addRemovePlayerEntity(regionMap, - entity, - natives, - false, - creditNatives), - world, - true) + addRemovePlayerEntity(regionMap, entity, natives, false, creditNatives) end end end end local function onEnemyBaseBuild(event) - local entity = event.entity - registerEnemyBaseStructure(regionMap, entity, nil) + registerEnemyBaseStructure(regionMap, event.entity, nil) end local function onSurfaceTileChange(event) @@ -384,128 +359,30 @@ local function onInit() global.regionMap = {} global.pendingChunks = {} global.natives = {} - global.world = {} regionMap = global.regionMap natives = global.natives pendingChunks = global.pendingChunks - world = global.world onConfigChanged() hookEvents() 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 script.on_init(onInit) script.on_load(onLoad) -script.on_event(defines.events.on_runtime_mod_setting_changed, - onModSettingsChange) +script.on_event(defines.events.on_runtime_mod_setting_changed, onModSettingsChange) 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_cursor_stack_changed, - 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_biter_base_built, onEnemyBaseBuild) script.on_event({defines.events.on_player_mined_entity, - defines.events.on_robot_mined_entity}, - onMine) + defines.events.on_robot_mined_entity}, onMine) script.on_event({defines.events.on_built_entity, - defines.events.on_robot_built_entity}, - onBuild) -script.on_event(defines.events.on_player_dropped_item, - onPlayerDropped) + defines.events.on_robot_built_entity}, onBuild) -script.on_event(defines.events.on_sector_scanned, - onScannedSector) script.on_event(defines.events.on_entity_died, onDeath) script.on_event(defines.events.on_tick, onTick) script.on_event(defines.events.on_chunk_generated, onChunkGenerated) diff --git a/data.lua b/data.lua index 811c85c..cb2ce0f 100755 --- a/data.lua +++ b/data.lua @@ -11,8 +11,3 @@ require("prototypes/enemies/UnitFireSpitters") require("prototypes/enemies/UnitTendril") -if settings.startup["rampant-enableBuildings"].value then - require("prototypes/buildings/ItemCollector") -end - - diff --git a/info.json b/info.json index 107f360..c04bad4 100755 --- a/info.json +++ b/info.json @@ -1,7 +1,7 @@ { "name" : "Rampant", "factorio_version" : "0.15", - "version" : "0.15.22", + "version" : "0.15.23", "title" : "Rampant", "author" : "Veden", "homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445", diff --git a/libs/AIAttackWave.lua b/libs/AIAttackWave.lua index ab6a1c0..975b9ec 100755 --- a/libs/AIAttackWave.lua +++ b/libs/AIAttackWave.lua @@ -4,8 +4,9 @@ local aiAttackWave = {} local constants = require("Constants") local mapUtils = require("MapUtils") +local chunkUtils = require("ChunkUtils") local unitGroupUtils = require("UnitGroupUtils") -local neighborUtils = require("NeighborUtils") +local movementUtils = require("MovementUtils") package.path = "../?.lua;" .. package.path local config = require("config") @@ -18,19 +19,21 @@ local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local AI_SQUAD_COST = constants.AI_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 TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE -local PASSABLE = constants.PASSABLE local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS +local CHUNK_SIZE = constants.CHUNK_SIZE + local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE local DEFINES_COMMAND_GROUP = defines.command.group 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 @@ -38,9 +41,13 @@ local mRandom = math.random local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk +local getNestCount = chunkUtils.getNestCount +local getRallyTick = chunkUtils.getRallyTick +local setRallyTick = chunkUtils.setRallyTick + local getNeighborChunks = mapUtils.getNeighborChunks -local getChunkByIndex = mapUtils.getChunkByIndex -local scoreNeighborsForFormation = neighborUtils.scoreNeighborsForFormation +local getChunkByPosition = mapUtils.getChunkByPosition +local scoreNeighborsForFormation = movementUtils.scoreNeighborsForFormation local createSquad = unitGroupUtils.createSquad local attackWaveScaling = config.attackWaveScaling @@ -74,21 +81,21 @@ local function scoreUnitGroupLocation(neighborChunk) return neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] end -local function validUnitGroupLocation(neighborChunk) - return (neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS) and (neighborChunk[NEST_COUNT] == 0) +local function validUnitGroupLocation(regionMap, neighborChunk) + return neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS and (getNestCount(regionMap, neighborChunk) == 0) end 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 - chunk[RALLY_TRIGGERED] = tick - local cX = chunk.cX - local cY = chunk.cY - for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE do - for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE do + setRallyTick(regionMap, chunk, tick) + local cX = chunk.x + local cY = chunk.y + for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE, 32 do + for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE, 32 do if (x ~= cX) and (y ~= cY) then - local rallyChunk = getChunkByIndex(regionMap, x, y) - if rallyChunk and (rallyChunk[NEST_COUNT] ~= 0) then + local rallyChunk = getChunkByPosition(regionMap, x, y) + if (rallyChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (getNestCount(regionMap, rallyChunk) > 0) then aiAttackWave.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST) if (natives.points < AI_VENGENCE_SQUAD_COST) and (#natives.squads < natives.maxSquads) then return @@ -105,16 +112,17 @@ function aiAttackWave.formSquads(regionMap, surface, natives, chunk, cost) 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, - scoreUnitGroupLocation) - if squadPath then - local squadPosition = surface.find_non_colliding_position("biter-spawner-hive", + scoreUnitGroupLocation, + regionMap) + if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then + local squadPosition = surface.find_non_colliding_position("biter-spawner-hive-rampant", positionFromDirectionAndChunk(squadDirection, chunk, regionMap.position, 0.98), - 32, + CHUNK_SIZE, 4) if squadPosition then local squad = createSquad(squadPosition, surface, natives) diff --git a/libs/AIPredicates.lua b/libs/AIPredicates.lua index ca61ef5..6fde0b2 100755 --- a/libs/AIPredicates.lua +++ b/libs/AIPredicates.lua @@ -3,21 +3,28 @@ local aiPredicates = {} -- imports local constants = require("Constants") -local nocturnalUtils = require("NocturnalUtils") -- constants local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE +local AI_STATE_NOCTURNAL = constants.AI_STATE_NOCTURNAL -- imported functions -local canAttackNocturnal = nocturnalUtils.canAttack - -- module code 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)) 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 diff --git a/libs/BaseRegisterUtils.lua b/libs/BaseRegisterUtils.lua deleted file mode 100755 index 3cb7c0d..0000000 --- a/libs/BaseRegisterUtils.lua +++ /dev/null @@ -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 diff --git a/libs/BaseUtils.lua b/libs/BaseUtils.lua index 73a6c65..512c5ac 100755 --- a/libs/BaseUtils.lua +++ b/libs/BaseUtils.lua @@ -5,7 +5,7 @@ local baseUtils = {} local mathUtils = require("MathUtils") local constants = require("Constants") -local tendrilUtils = require("TendrilUtils") +-- local tendrilUtils = require("TendrilUtils") local nestUtils = require("NestUtils") @@ -26,7 +26,7 @@ local buildHive = nestUtils.buildHive local mFloor = math.floor -local buildTendril = tendrilUtils.buildTendril +-- local buildTendril = tendrilUtils.buildTendril local mRandom = math.random @@ -68,7 +68,7 @@ function baseUtils.createBase(regionMap, natives, position, surface, tick) if not buildHive(regionMap, base, surface) then return nil end - buildTendril(regionMap, natives, base, surface, tick) + -- buildTendril(regionMap, natives, base, surface, tick) bases[#bases+1] = base return base end diff --git a/libs/BuildUtils.lua b/libs/BuildUtils.lua deleted file mode 100755 index 854a753..0000000 --- a/libs/BuildUtils.lua +++ /dev/null @@ -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 diff --git a/libs/ChunkProcessor.lua b/libs/ChunkProcessor.lua index 4b821b2..e4edea0 100755 --- a/libs/ChunkProcessor.lua +++ b/libs/ChunkProcessor.lua @@ -9,6 +9,8 @@ local constants = require("Constants") local CHUNK_SIZE = constants.CHUNK_SIZE +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK + -- imported functions local remakeChunk = chunkUtils.remakeChunk @@ -39,26 +41,31 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin local x = topLeft.x local y = topLeft.y local chunk = createChunk(x, y) - - areaBoundingBox[1] = chunk - offset[1] = x + CHUNK_SIZE - offset[2] = y + CHUNK_SIZE - local chunkX = chunk.cX - - if regionMap[chunkX] == nil then - regionMap[chunkX] = {} - end - regionMap[chunkX][chunk.cY] = chunk - - checkChunkPassability(chunkTiles, chunk, surface) - if vanillaAI then - registerChunkEnemies(chunk, surface, query) - else - remakeChunk(regionMap, chunk, surface, natives, tick, query) + chunk = checkChunkPassability(chunkTiles, chunk, surface) + + if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then + + areaBoundingBox[1] = chunk + offset[1] = x + CHUNK_SIZE + offset[2] = y + CHUNK_SIZE + + if vanillaAI then + registerChunkEnemies(regionMap, chunk, surface, query) + else + 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 - scoreChunk(chunk, surface, natives, query) - processQueue[#processQueue+1] = chunk end end diff --git a/libs/ChunkUtils.lua b/libs/ChunkUtils.lua index 33db874..bac91e7 100755 --- a/libs/ChunkUtils.lua +++ b/libs/ChunkUtils.lua @@ -3,31 +3,25 @@ local chunkUtils = {} -- imports local constants = require("Constants") - -local baseUtils = require("BaseUtils") - -local baseRegisterUtils = require("BaseRegisterUtils") +local mapUtils = require("MapUtils") -- 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 PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE 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_EAST_WEST = constants.CHUNK_EAST_WEST -local PASSABLE = constants.PASSABLE - local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE @@ -35,14 +29,13 @@ local CHUNK_TICK = constants.CHUNK_TICK local PATH_RATING = constants.PATH_RATING -local RETREAT_TRIGGERED = constants.RETREAT_TRIGGERED -local RALLY_TRIGGERED = constants.RALLY_TRIGGERED +local PASSABLE = constants.PASSABLE -- imported functions -local findNearbyBase = baseUtils.findNearbyBase -local createBase = baseUtils.createBase -local addEnemyStructureToChunk = baseRegisterUtils.addEnemyStructureToChunk +local getChunkByPosition = mapUtils.getChunkByPosition + +local mFloor = math.floor -- module code @@ -109,6 +102,126 @@ local function spotCheck(x, y, get_tile) return valid 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) local x = chunk.x local y = chunk.y @@ -139,12 +252,17 @@ function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface) pass = CHUNK_NORTH_SOUTH else pass = CHUNK_IMPASSABLE - end + end end else chunk[PATH_RATING] = 1 end - chunk[PASSABLE] = pass + if (pass == CHUNK_IMPASSABLE) then + return SENTINEL_IMPASSABLE_CHUNK + else + chunk[PASSABLE] = pass + return chunk + end end 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 local enemy = enemies[f] 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 points = points + 3 elseif (entityType == "turret") then @@ -166,13 +284,13 @@ function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQu enemy.destroy() end end - local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick) - if foundBase then - foundBase.upgradePoints = foundBase.upgradePoints + points - end + -- local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick) + -- if foundBase then + -- foundBase.upgradePoints = foundBase.upgradePoints + points + -- end end -function chunkUtils.registerChunkEnemies(chunk, surface, tempQuery) +function chunkUtils.registerChunkEnemies(regionMap, chunk, surface, tempQuery) tempQuery.force = "enemy" local enemies = surface.find_entities_filtered(tempQuery) @@ -180,15 +298,61 @@ function chunkUtils.registerChunkEnemies(chunk, surface, tempQuery) local enemy = enemies[i] local enemyType = enemy.type if (enemyType == "unit-spawner") or (enemyType == "turret") then - addEnemyStructureToChunk(chunk, enemy, nil) + addEnemyStructureToChunk(regionMap, chunk, enemy, nil) 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.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.force = "player" @@ -207,36 +371,27 @@ function chunkUtils.scoreChunk(chunk, surface, natives, tempQuery) end local entityScore = BUILDING_PHEROMONES[entityType] - if (entityScore ~= nil) then + if entityScore then playerObjects = playerObjects + entityScore end end - chunk[PLAYER_BASE_GENERATOR] = playerObjects + chunkUtils.setPlayerBaseGenerator(regionMap, chunk, playerObjects) end function chunkUtils.createChunk(topX, topY) local chunk = { x = topX, - y = topY, - cX = topX * 0.03125, - cY = topY * 0.03125 + y = topY } chunk[MOVEMENT_PHEROMONE] = 0 chunk[BASE_PHEROMONE] = 0 chunk[PLAYER_PHEROMONE] = 0 chunk[RESOURCE_PHEROMONE] = 0 - chunk[PLAYER_BASE_GENERATOR] = 0 - chunk[RESOURCE_GENERATOR] = 0 chunk[PASSABLE] = 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 + return chunk end @@ -250,4 +405,109 @@ function chunkUtils.colorChunk(x, y, tileType, surface) surface.set_tiles(tiles, false) 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 diff --git a/libs/Constants.lua b/libs/Constants.lua index 3e86297..8de85f0 100755 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -15,10 +15,11 @@ constants.VERSION_25 = 25 constants.VERSION_26 = 26 constants.VERSION_27 = 27 constants.VERSION_28 = 28 -constants.VERSION_32 = 32 +constants.VERSION_33 = 33 -- 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_BASE_NUMBER = 100000000 constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL = 10000 @@ -28,7 +29,7 @@ constants.SCAN_QUEUE_SIZE = 5 constants.ITEM_COLLECTOR_QUEUE_SIZE = 6 constants.BASE_QUEUE_SIZE = 1 constants.SQUAD_QUEUE_SIZE = 2 -constants.PROCESS_PLAYER_BOUND = 4 +constants.PROCESS_PLAYER_BOUND = 128 constants.ITEM_COLLECTOR_MAX_QUEUE_SIZE = 20 @@ -42,6 +43,18 @@ constants.PLAYER_PHEROMONE_MULTIPLER = 100 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 constants.ITEM_COLLECTOR_DISTANCE = 50 @@ -127,19 +140,11 @@ constants.BASE_PHEROMONE = 2 constants.PLAYER_PHEROMONE = 3 constants.RESOURCE_PHEROMONE = 4 -constants.PLAYER_BASE_GENERATOR = 5 -constants.RESOURCE_GENERATOR = 6 +constants.PASSABLE = 5 -constants.PASSABLE = 7 +constants.CHUNK_TICK = 6 -constants.CHUNK_TICK = 8 -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 +constants.PATH_RATING = 7 -- Squad status @@ -155,7 +160,7 @@ constants.RETREAT_GRAB_RADIUS = 24 constants.BASE_RALLY_CHANCE = 0.02 constants.BONUS_RALLY_CHANCE = 0.06 -constants.RALLY_CRY_DISTANCE = 3 +constants.RALLY_CRY_DISTANCE = 96 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_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 --[[ diff --git a/libs/EntityUtils.lua b/libs/EntityUtils.lua deleted file mode 100755 index 5c185a8..0000000 --- a/libs/EntityUtils.lua +++ /dev/null @@ -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 diff --git a/libs/InventoryUtils.lua b/libs/InventoryUtils.lua deleted file mode 100755 index 6315322..0000000 --- a/libs/InventoryUtils.lua +++ /dev/null @@ -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 diff --git a/libs/MapProcessor.lua b/libs/MapProcessor.lua index 49f3259..41ac5ad 100755 --- a/libs/MapProcessor.lua +++ b/libs/MapProcessor.lua @@ -3,14 +3,13 @@ local mapProcessor = {} -- imports local unitGroupUtils = require("UnitGroupUtils") - local pheromoneUtils = require("PheromoneUtils") local aiAttackWave = require("AIAttackWave") local aiPredicates = require("AIPredicates") local constants = require("Constants") local mapUtils = require("MapUtils") local playerUtils = require("PlayerUtils") - +local chunkUtils = require("ChunkUtils") local mathUtils = require("MathUtils") -- constants @@ -26,30 +25,33 @@ local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE local PROCESS_PLAYER_BOUND = constants.PROCESS_PLAYER_BOUND local CHUNK_TICK = constants.CHUNK_TICK -local NEST_COUNT = constants.NEST_COUNT -local WORM_COUNT = constants.WORM_COUNT +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK local AI_SQUAD_COST = constants.AI_SQUAD_COST local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST 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 -- imported functions local scents = pheromoneUtils.scents local processPheromone = pheromoneUtils.processPheromone +local playerScent = pheromoneUtils.playerScent local formSquads = aiAttackWave.formSquads -local getChunkByIndex = mapUtils.getChunkByIndex local getChunkByPosition = mapUtils.getChunkByPosition +local positionToChunkXY = mapUtils.positionToChunkXY 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 @@ -57,8 +59,6 @@ local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed local mMin = math.min -local validPlayer = playerUtils.validPlayer - local mRandom = math.random -- module code @@ -105,12 +105,12 @@ function mapProcessor.processMap(regionMap, surface, natives, tick) 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) squads = (natives.points >= AI_SQUAD_COST) and (#natives.squads < natives.maxSquads) end - scents(chunk) + scents(regionMap, chunk) end end @@ -141,10 +141,10 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick) for i=1,#playerOrdering do local player = players[playerOrdering[i]] if validPlayer(player) then - local playerPosition = player.character.position - local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y) + local chunkX, chunkY = positionToChunkXY(player.character.position) + local playerChunk = getChunkByPosition(regionMap, chunkX, chunkY) - if playerChunk then + if (playerChunk ~= SENTINEL_IMPASSABLE_CHUNK) then playerScent(playerChunk) end end @@ -152,21 +152,24 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick) for i=1,#playerOrdering do local player = players[playerOrdering[i]] if validPlayer(player) then - local playerPosition = player.character.position - local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y) + local chunkX, chunkY = positionToChunkXY(player.character.position) + local playerChunk = getChunkByPosition(regionMap, chunkX, chunkY) - if playerChunk 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) + if (playerChunk ~= SENTINEL_IMPASSABLE_CHUNK) then + 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 y=playerChunk.cY - PROCESS_PLAYER_BOUND, playerChunk.cY + PROCESS_PLAYER_BOUND do - local chunk = getChunkByIndex(regionMap, x, y) - if chunk and (chunk[CHUNK_TICK] ~= tick) then + for x=playerChunk.x - PROCESS_PLAYER_BOUND, playerChunk.x + PROCESS_PLAYER_BOUND, 32 do + for y=playerChunk.y - PROCESS_PLAYER_BOUND, playerChunk.y + PROCESS_PLAYER_BOUND, 32 do + local chunk = getChunkByPosition(regionMap, x, y) + + if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (chunk[CHUNK_TICK] ~= tick) then chunk[CHUNK_TICK] = tick processPheromone(regionMap, chunk) - if (chunk[NEST_COUNT] ~= 0) then + if (getNestCount(regionMap, chunk) > 0) then if squads then formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST) 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 - scents(chunk) + scents(regionMap, chunk) end end end @@ -232,7 +235,7 @@ function mapProcessor.scanMap(regionMap, surface, natives) 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 playerBaseGenerator = 0 @@ -250,7 +253,7 @@ function mapProcessor.scanMap(regionMap, surface, natives) end end - chunk[PLAYER_BASE_GENERATOR] = playerBaseGenerator + setPlayerBaseGenerator(regionMap, chunk, playerBaseGenerator) end if (endIndex == #processQueue) then diff --git a/libs/MapUtils.lua b/libs/MapUtils.lua index 90fd608..2fab068 100755 --- a/libs/MapUtils.lua +++ b/libs/MapUtils.lua @@ -13,10 +13,12 @@ local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS local PASSABLE = constants.PASSABLE -local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE - local CHUNK_SIZE = constants.CHUNK_SIZE +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK + +local CHUNK_SIZE_DIVIDER = constants.CHUNK_SIZE_DIVIDER + -- imported functions local mFloor = math.floor @@ -24,19 +26,17 @@ local mFloor = math.floor -- module code 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] if chunkX then - return chunkX[y] + return chunkX[y] or SENTINEL_IMPASSABLE_CHUNK 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 --[[ @@ -46,39 +46,39 @@ end /|\ 6 7 8 ]]-- -function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY) +function mapUtils.getNeighborChunks(regionMap, x, y) local neighbors = regionMap.neighbors - local chunkYRow1 = chunkY - 1 - local chunkYRow3 = chunkY + 1 - local xChunks = regionMap[chunkX-1] + local chunkYRow1 = y - CHUNK_SIZE + local chunkYRow3 = y + CHUNK_SIZE + local xChunks = regionMap[x-CHUNK_SIZE] if xChunks then - neighbors[1] = xChunks[chunkYRow1] - neighbors[4] = xChunks[chunkY] - neighbors[6] = xChunks[chunkYRow3] + neighbors[1] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK + neighbors[4] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK + neighbors[6] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK else - neighbors[1] = nil - neighbors[4] = nil - neighbors[6] = nil + neighbors[1] = SENTINEL_IMPASSABLE_CHUNK + neighbors[4] = SENTINEL_IMPASSABLE_CHUNK + 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 - xChunks = regionMap[chunkX+1] + xChunks = regionMap[x] if xChunks then - neighbors[3] = xChunks[chunkYRow1] - neighbors[5] = xChunks[chunkY] - neighbors[8] = xChunks[chunkYRow3] + neighbors[2] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK + neighbors[7] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK else - neighbors[3] = nil - neighbors[5] = nil - 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 + neighbors[2] = SENTINEL_IMPASSABLE_CHUNK + neighbors[7] = SENTINEL_IMPASSABLE_CHUNK end return neighbors end @@ -87,41 +87,41 @@ function mapUtils.canMoveChunkDirection(direction, startChunk, endChunk) local canMove = false local startPassable = startChunk[PASSABLE] local endPassable = endChunk[PASSABLE] - if ((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 (startPassable == CHUNK_ALL_DIRECTIONS) and (endPassable == CHUNK_ALL_DIRECTIONS) then + if (startPassable == CHUNK_ALL_DIRECTIONS) and (endPassable == CHUNK_ALL_DIRECTIONS) then 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 end return canMove end -function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY) +function mapUtils.getCardinalChunks(regionMap, x, y) local neighbors = regionMap.cardinalNeighbors - local xChunks = regionMap[chunkX] + local xChunks = regionMap[x] if xChunks then - neighbors[1] = xChunks[chunkY-1] - neighbors[4] = xChunks[chunkY+1] + neighbors[1] = xChunks[y-CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK + neighbors[4] = xChunks[y+CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK else - neighbors[1] = nil - neighbors[4] = nil + neighbors[1] = SENTINEL_IMPASSABLE_CHUNK + neighbors[4] = SENTINEL_IMPASSABLE_CHUNK end - xChunks = regionMap[chunkX-1] + xChunks = regionMap[x-CHUNK_SIZE] if xChunks then - neighbors[2] = xChunks[chunkY] + neighbors[2] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK else - neighbors[2] = nil + neighbors[2] = SENTINEL_IMPASSABLE_CHUNK end - xChunks = regionMap[chunkX+1] + xChunks = regionMap[x+CHUNK_SIZE] if xChunks then - neighbors[3] = xChunks[chunkY] + neighbors[3] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK else - neighbors[3] = nil + neighbors[3] = SENTINEL_IMPASSABLE_CHUNK end return neighbors end diff --git a/libs/MovementUtils.lua b/libs/MovementUtils.lua index bafb3db..d67628d 100755 --- a/libs/MovementUtils.lua +++ b/libs/MovementUtils.lua @@ -4,7 +4,7 @@ local movementUtils = {} local constants = require("Constants") local unitGroupUtils = require("UnitGroupUtils") - +local mapUtils = require("MapUtils") local mathUtils = require("MathUtils") -- constants @@ -12,8 +12,16 @@ local mathUtils = require("MathUtils") local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT 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 +local canMoveChunkDirection = mapUtils.canMoveChunkDirection + local recycleBiters = unitGroupUtils.recycleBiters local tableRemove = table.remove @@ -31,11 +39,11 @@ function movementUtils.findMovementPosition(surface, position, distort) return (distort and distortPosition(pos)) or pos end -function movementUtils.addMovementPenalty(natives, units, chunkX, chunkY) +function movementUtils.addMovementPenalty(natives, units, x, y) local penalties = units.penalties for i=1,#penalties do 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 if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then local group = units.group @@ -53,15 +61,15 @@ function movementUtils.addMovementPenalty(natives, units, chunkX, chunkY) tableRemove(penalties, 7) end tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT, - x = chunkX, - y = chunkY }) + x = x, + y = y }) end -function movementUtils.lookupMovementPenalty(squad, chunkX, chunkY) +function movementUtils.lookupMovementPenalty(squad, x, y) local penalties = squad.penalties for i=1,#penalties do 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 end end @@ -69,4 +77,101 @@ function movementUtils.lookupMovementPenalty(squad, chunkX, chunkY) 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 diff --git a/libs/NeighborUtils.lua b/libs/NeighborUtils.lua deleted file mode 100755 index 0ea8559..0000000 --- a/libs/NeighborUtils.lua +++ /dev/null @@ -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 diff --git a/libs/NestUtils.lua b/libs/NestUtils.lua index 0d845e5..c77c52b 100755 --- a/libs/NestUtils.lua +++ b/libs/NestUtils.lua @@ -4,10 +4,8 @@ local nestUtils = {} local constants = require("Constants") local mathUtils = require("MathUtils") - -local baseRegisterUtils = require("BaseRegisterUtils") - local mapUtils = require("MapUtils") +local chunkUtils = require("ChunkUtils") -- constants @@ -20,9 +18,11 @@ local NEST_COUNT = constants.NEST_COUNT local DOUBLE_CHUNK_SIZE = constants.DOUBLE_CHUNK_SIZE +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK + -- imported functions -local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure +local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure local gaussianRandomRange = mathUtils.gaussianRandomRange 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 chunk = getChunkByPosition(regionMap, position.x, position.y) 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} nest = surface.create_entity(biterSpawner) registerEnemyBaseStructure(regionMap, nest, base) @@ -45,7 +45,7 @@ end function nestUtils.buildHive(regionMap, base, surface) 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 (#base.hives == 0) then base.x = hive.position.x @@ -101,7 +101,7 @@ function nestUtils.buildOutpost(regionMap, natives, base, surface, tendril) y = position.y + (distortion * math.sin(pos))} local biterSpawner = {name=thing, position=nestPosition} 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 end pos = pos + slice @@ -149,7 +149,7 @@ function nestUtils.buildOrder(regionMap, natives, base, surface) y = base.y + (distortion * math.sin(pos))} local biterSpawner = {name=thing, position=nestPosition} 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 end pos = pos + slice diff --git a/libs/NocturnalUtils.lua b/libs/NocturnalUtils.lua deleted file mode 100755 index 052ba10..0000000 --- a/libs/NocturnalUtils.lua +++ /dev/null @@ -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 diff --git a/libs/PheromoneUtils.lua b/libs/PheromoneUtils.lua index 9dce556..80d25d6 100755 --- a/libs/PheromoneUtils.lua +++ b/libs/PheromoneUtils.lua @@ -4,6 +4,7 @@ local pheromoneUtils = {} local mapUtils = require("MapUtils") local constants = require("Constants") +local chunkUtils = require("ChunkUtils") -- constants @@ -14,9 +15,6 @@ local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE 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 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 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 IMPASSABLE_TERRAIN_GENERATOR_AMOUNT = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT - -- imported functions local getCardinalChunks = mapUtils.getCardinalChunks local mMax = math.max +local getNestCount = chunkUtils.getNestCount +local getWormCount = chunkUtils.getWormCount +local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator +local getResourceGenerator = chunkUtils.getResourceGenerator -- module code -function pheromoneUtils.scents(chunk) - - if (chunk[PASSABLE] == CHUNK_IMPASSABLE) then - chunk[BASE_PHEROMONE] = IMPASSABLE_TERRAIN_GENERATOR_AMOUNT; - else - 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 +function pheromoneUtils.scents(regionMap, chunk) + chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + getPlayerBaseGenerator(regionMap, chunk) + local resourceGenerator = getResourceGenerator(regionMap, chunk) + if (resourceGenerator > 0) and (getNestCount(regionMap, chunk) == 0) and (getWormCount(regionMap, chunk) == 0) then + chunk[RESOURCE_PHEROMONE] = chunk[RESOURCE_PHEROMONE] + mMax(resourceGenerator * 100, 90) end - end function pheromoneUtils.victoryScent(chunk, 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) end end function pheromoneUtils.deathScent(chunk) - if (chunk[PASSABLE] ~= CHUNK_IMPASSABLE) then - chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT - end + chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT end function pheromoneUtils.playerScent(playerChunk) - if (playerChunk[PASSABLE] ~= CHUNK_IMPASSABLE) then - playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT - end + playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT end function pheromoneUtils.processPheromone(regionMap, chunk) - if (chunk[PASSABLE] == CHUNK_IMPASSABLE) then - return - end - local chunkMovement = chunk[MOVEMENT_PHEROMONE] local chunkBase = chunk[BASE_PHEROMONE] local chunkPlayer = chunk[PLAYER_PHEROMONE] @@ -93,17 +73,31 @@ function pheromoneUtils.processPheromone(regionMap, chunk) local totalPlayer = 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[i] - if neighborChunk then - totalMovement = totalMovement + (neighborChunk[MOVEMENT_PHEROMONE] - chunkMovement) - totalBase = totalBase + (neighborChunk[BASE_PHEROMONE] - chunkBase) - totalPlayer = totalPlayer + (neighborChunk[PLAYER_PHEROMONE] - chunkPlayer) - totalResource = totalResource + (neighborChunk[RESOURCE_PHEROMONE] - chunkResource) - end - end + local neighborChunk = tempNeighbors[1] + 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[2] + 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[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[BASE_PHEROMONE] = (chunkBase + (0.25 * totalBase)) * BASE_PHEROMONE_PERSISTANCE * chunkPathRating diff --git a/libs/PlayerUtils.lua b/libs/PlayerUtils.lua index fa47d13..f53db1c 100755 --- a/libs/PlayerUtils.lua +++ b/libs/PlayerUtils.lua @@ -25,24 +25,4 @@ function playerUtils.playersWithinProximityToPosition(players, position, distanc return false 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 diff --git a/libs/SquadAttack.lua b/libs/SquadAttack.lua index dc2b648..7059bc0 100755 --- a/libs/SquadAttack.lua +++ b/libs/SquadAttack.lua @@ -6,9 +6,9 @@ local constants = require("Constants") local mapUtils = require("MapUtils") local unitGroupUtils = require("UnitGroupUtils") local playerUtils = require("PlayerUtils") -local neighborUtils = require("NeighborUtils") local movementUtils = require("MovementUtils") local mathUtils = require("MathUtils") +local chunkUtils = require("ChunkUtils") -- constants @@ -19,7 +19,7 @@ local BASE_PHEROMONE = constants.BASE_PHEROMONE local SQUAD_RAIDING = constants.SQUAD_RAIDING 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 @@ -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_ANYTHING = defines.distraction.by_anything +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK + -- imported functions local mRandom = math.random @@ -48,14 +50,17 @@ local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPosition +local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator -local scoreNeighborsForAttack = neighborUtils.scoreNeighborsForAttack +local positionToChunkXY = mapUtils.positionToChunkXY + +local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack -- module code local function scoreAttackLocation(squad, neighborChunk) 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 function squadAttack.squadsAttack(regionMap, surface, natives) @@ -67,7 +72,7 @@ function squadAttack.squadsAttack(regionMap, surface, natives) attackPosition = regionMap.position attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA, destination = attackPosition, - radius = 32, + radius = CHUNK_SIZE, distraction = DEFINES_DISTRACTION_BY_ENEMY } end @@ -78,18 +83,17 @@ function squadAttack.squadsAttack(regionMap, surface, natives) local groupState = group.state 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 chunk = getChunkByPosition(regionMap, groupPosition.x, groupPosition.y) - if chunk then + local chunkX, chunkY = positionToChunkXY(groupPosition) + local chunk = getChunkByPosition(regionMap, chunkX, chunkY) + if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then local attackChunk, attackDirection = scoreNeighborsForAttack(chunk, - getNeighborChunks(regionMap, - chunk.cX, - chunk.cY), + getNeighborChunks(regionMap, chunkX, chunkY), scoreAttackLocation, squad) - addMovementPenalty(natives, squad, chunk.cX, chunk.cY) - if group.valid and attackChunk then - if (attackChunk[PLAYER_BASE_GENERATOR] == 0) or - ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then + addMovementPenalty(natives, squad, chunkX, chunkY) + if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then + local playerBaseGenerator = getPlayerBaseGenerator(regionMap, attackChunk) + if (playerBaseGenerator == 0) or ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then 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 end - local position = findMovementPosition(surface, - positionFromDirectionAndChunk(attackDirection, - groupPosition, - attackPosition, - 1.35)) + local position = findMovementPosition(surface, positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.35)) if position then attackPosition.x = position.x attackPosition.y = position.y group.set_command(attackCmd) group.start_moving() else - addMovementPenalty(natives, squad, attackChunk.cX, attackChunk.cY) + addMovementPenalty(natives, squad, attackChunk.x, attackChunk.y) end elseif not squad.frenzy and not squad.rabid and ((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.frenzyPosition.x = groupPosition.x squad.frenzyPosition.y = groupPosition.y diff --git a/libs/SquadDefense.lua b/libs/SquadDefense.lua index 17dfdd6..64a7169 100755 --- a/libs/SquadDefense.lua +++ b/libs/SquadDefense.lua @@ -5,14 +5,13 @@ local aiDefense = {} local constants = require("Constants") local mapUtils = require("MapUtils") local unitGroupUtils = require("UnitGroupUtils") -local neighborUtils = require("NeighborUtils") local movementUtils = require("MovementUtils") +local chunkUtils = require("ChunkUtils") -- constants local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS -local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local PLAYER_PHEROMONE = constants.PLAYER_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_TRIGGERED = constants.RETREAT_TRIGGERED - local INTERVAL_LOGIC = constants.INTERVAL_LOGIC -local NEST_COUNT = constants.NEST_COUNT -local WORM_COUNT = constants.WORM_COUNT +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK -- imported functions @@ -38,42 +34,43 @@ local findNearBySquad = unitGroupUtils.findNearBySquad local addMovementPenalty = movementUtils.addMovementPenalty local createSquad = unitGroupUtils.createSquad local membersToSquad = unitGroupUtils.membersToSquad -local scoreNeighborsForRetreat = neighborUtils.scoreNeighborsForRetreat +local scoreNeighborsForRetreat = movementUtils.scoreNeighborsForRetreat 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 -local function scoreRetreatLocation(neighborChunk) - return -(neighborChunk[BASE_PHEROMONE] + -neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 100) + (neighborChunk[PLAYER_BASE_GENERATOR] * 20)) +local function scoreRetreatLocation(regionMap, neighborChunk) + return -(neighborChunk[BASE_PHEROMONE] + -neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 100) + (getPlayerBaseGenerator(regionMap, neighborChunk) * 20)) end 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 enemiesToSquad = nil 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 elseif squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then performRetreat = #squad.group.members > 1 end if performRetreat then - chunk[RETREAT_TRIGGERED] = tick + setRetreatTick(regionMap, chunk, tick) local exitPath,exitDirection = scoreNeighborsForRetreat(chunk, - getNeighborChunks(regionMap, - chunk.cX, - chunk.cY), - scoreRetreatLocation) - if exitPath then + getNeighborChunks(regionMap, chunk.x, chunk.y), + scoreRetreatLocation, + regionMap) + if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then local retreatPosition = findMovementPosition(surface, - positionFromDirectionAndChunk(exitDirection, - position, - regionMap.position, - 0.98), + positionFromDirectionAndChunk(exitDirection, position, regionMap.position, 0.98), false) - if not retreatPosition then return @@ -100,7 +97,7 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati newSquad.rabid = true end end - addMovementPenalty(natives, newSquad, chunk.cX, chunk.cY) + addMovementPenalty(natives, newSquad, chunk.x, chunk.y) end end end diff --git a/libs/TendrilUtils.lua b/libs/TendrilUtils.lua index 499ec1c..4dfc966 100755 --- a/libs/TendrilUtils.lua +++ b/libs/TendrilUtils.lua @@ -4,24 +4,18 @@ local tendrilUtils = {} local constants = require("Constants") local mapUtils = require("MapUtils") -local baseRegisterUtils = require("BaseRegisterUtils") -local neighborsUtils = require("NeighborUtils") -local mathUtils = require("MathUtils") - local nestUtils = require("NestUtils") -local mathUtils = require("MathUtils") +local movementUtils = require("MovementUtils") -- constants local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE -local RESOURCE_GENERATOR = constants.RESOURCE_GENERATOR - -local NEST_COUNT = constants.NEST_COUNT +local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK -- imported functions -local scoreNeighborsForResource = neighborsUtils.scoreNeighborsForResource +local scoreNeighborsForResource = movementUtils.scoreNeighborsForResource local getNeighborChunks = mapUtils.getNeighborChunks @@ -74,11 +68,9 @@ local function buildTendrilPath(regionMap, tendril, surface, base, tick, natives end local tendrilPosition = tendrilUnit.position local chunk = getChunkByPosition(regionMap, tendrilPosition.x, tendrilPosition.y) - if chunk then + if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then local tendrilPath,tendrilDirection = scoreNeighborsForResource(chunk, - getNeighborChunks(regionMap, - chunk.cX, - chunk.cY), + getNeighborChunks(regionMap, chunk.x, chunk.y), scoreTendrilChunk, nil) if (tendrilDirection == -1) then diff --git a/libs/WorldProcessor.lua b/libs/WorldProcessor.lua deleted file mode 100755 index df9594f..0000000 --- a/libs/WorldProcessor.lua +++ /dev/null @@ -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 diff --git a/locale/en/locale.cfg b/locale/en/locale.cfg index 219800b..c3eec16 100755 --- a/locale/en/locale.cfg +++ b/locale/en/locale.cfg @@ -1,6 +1,6 @@ [entity-name] -tunnel-entrance=Tunnel Entrance +tunnel-entrance-rampant=Tunnel Entrance small-suicide-biter=Small Suicide Biter medium-suicide-biter=Medium Suicide Biter @@ -9,7 +9,7 @@ behemoth-suicide-biter=Behemoth Suicide Biter small-fire-spitter=Small Fire Spitter -biter-spawner-hive=Small Hive +biter-spawner-hive-rampant=Small Hive small-tendril-biter-rampant=Small Tendril 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 [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 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 -biter-spawner-hive=Small Hive +biter-spawner-hive-rampant=Small Hive 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. diff --git a/make.rkt b/make.rkt index d8f2ad9..3c6a266 100755 --- a/make.rkt +++ b/make.rkt @@ -36,6 +36,7 @@ (string->path "README.md") (string->path "NOTICE") (string->path "libs") + (string->path "sounds") (string->path "locale") (string->path "graphics") (string->path "prototypes"))) @@ -72,12 +73,13 @@ (copyFile "tests.lua" modFolder) (copyDirectory "libs" modFolder) (copyDirectory "locale" modFolder) + (copyDirectory "sounds" modFolder) (copyDirectory "graphics" modFolder) (copyDirectory "prototypes" modFolder))) (define (run) - ;;(copyFiles modFolder) + (copyFiles modFolder) ;;(copyFiles zipModFolder) - (makeZip modFolder) + ;;(makeZip modFolder) ) ) diff --git a/prototypes/buildings/ItemCollector.lua b/prototypes/buildings/ItemCollector.lua deleted file mode 100755 index 2905858..0000000 --- a/prototypes/buildings/ItemCollector.lua +++ /dev/null @@ -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", - }, -}) - diff --git a/prototypes/buildings/UnitSpawners.lua b/prototypes/buildings/UnitSpawners.lua index 3d9605a..8138769 100755 --- a/prototypes/buildings/UnitSpawners.lua +++ b/prototypes/buildings/UnitSpawners.lua @@ -102,7 +102,7 @@ data:extend({ { type = "unit-spawner", - name = "biter-spawner-hive", + name = "biter-spawner-hive-rampant", icon = "__base__/graphics/icons/biter-spawner.png", flags = {"placeable-player", "placeable-enemy", "not-repairable"}, max_health = 350, diff --git a/prototypes/buildings/tunnel.lua b/prototypes/buildings/tunnel.lua index 0544792..fc34ed3 100755 --- a/prototypes/buildings/tunnel.lua +++ b/prototypes/buildings/tunnel.lua @@ -1,7 +1,7 @@ data:extend({ { type = "simple-entity", - name = "tunnel-entrance", + name = "tunnel-entrance-rampant", flags = {"placeable-neutral", "placeable-off-grid", "not-on-map"}, icon = "__base__/graphics/icons/small-scorchmark.png", subgroup = "grass", diff --git a/prototypes/enemies/AttackAcidBall.lua b/prototypes/enemies/AttackAcidBall.lua index 7ea50eb..6bf3144 100755 --- a/prototypes/enemies/AttackAcidBall.lua +++ b/prototypes/enemies/AttackAcidBall.lua @@ -10,278 +10,95 @@ local makeColor = colorUtils.makeColor -- dumb acid projectiles -makeStream({ - 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 = { +local templateDamage = { amount = 4, type = "acid" } +local templateArea = { + type = "area", + perimeter = 1.2, + action_delivery = + { { - type = "area", - perimeter = 1.5, - action_delivery = + type = "instant", + target_effects = { { - type = "instant", - target_effects = - { - { - type = "damage", - damage = { amount = 15, type = "acid" } - } - } + type = "damage", + damage = templateDamage } } - }, - { - 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({ - name = "acid-ball-1", - 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 = { - { - 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" - } - } - } - } -}) +template.name = "acid-ball-1" +templateDamage.amount = 9 +templateArea.perimeter = 1.3 +makeStream(template) -- -makeStream({ - name = "acid-ball-2", - 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 = { - { - 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" - } - } - } - } -}) +template.name = "acid-ball-2" +templateDamage.amount = 14 +templateArea.perimeter = 1.4 +makeStream(template) -- -makeStream({ - name = "acid-ball-3", - 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 = { - { - 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" - } - } - } - } -}) +template.name = "acid-ball-3" +templateDamage.amount = 23 +templateArea.perimeter = 1.5 +makeStream(template) -- -makeStream({ - name = "wide-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 = { - { - 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" - } - } - } - } -}) +template.name = "wide-acid-ball" +templateDamage.amount = 18 +templateArea.perimeter = 3 +makeStream(template) -- -makeStream({ - name = "acid-ball-4", - 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 = { - { - 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" - } - } - } - } -}) +template.name = "acid-ball-4" +templateDamage.amount = 25 +templateArea.perimeter = 1.75 +makeStream(template) -- -makeStream({ - name = "acid-ball-5", - 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 = { - { - type = "area", - perimeter = 2, - action_delivery = - { - 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" - } - } - } - } -}) +template.name = "acid-ball-5" +templateDamage.amount = 50 +templateArea.perimeter = 2 +makeStream(template) + +-- + +template.name = "acid-ball-6" +templateDamage.amount = 70 +templateArea.perimeter = 2.5 +makeStream(template) diff --git a/prototypes/enemies/AttackBobs.lua b/prototypes/enemies/AttackBobs.lua index b293d8a..1c66e14 100755 --- a/prototypes/enemies/AttackBobs.lua +++ b/prototypes/enemies/AttackBobs.lua @@ -57,57 +57,7 @@ makeStream({ { { type = "damage", - damage = { amount = 35, 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" } + damage = { amount = 25, type = "explosion" } } } } @@ -166,7 +116,7 @@ makeStream({ }, { 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 data:extend({ @@ -318,7 +227,7 @@ makeStream({ { { type = "damage", - damage = { amount = 43, type = "bob-pierce" } + damage = { amount = 30, type = "bob-pierce" } } } } @@ -400,47 +309,7 @@ makeStream({ { { type = "damage", - damage = { amount = 10, 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" } + damage = { amount = 25, type = "electric" } } } } @@ -465,7 +334,7 @@ makeStream({ { { type = "create-entity", - entity_name = "small-poison-cloud" + entity_name = "small-fire-cloud" }, { type = "create-entity", @@ -484,19 +353,15 @@ makeStream({ { { type = "damage", - damage = { amount = 15, type = "electric" } + damage = { amount = 10, type = "electric" } }, { type = "damage", - damage = { amount = 15, type = "explosion" } + damage = { amount = 10, type = "explosion" } }, { type = "damage", - damage = { amount = 15, type = "fire" } - }, - { - type = "damage", - damage = { amount = 15, type = "poison" } + damage = { amount = 10, type = "fire" } } } } @@ -615,7 +480,7 @@ makeStream({ }, { type = "damage", - damage = { amount = 20, type = "explosion" } + damage = { amount = 15, type = "explosion" } }, { type = "damage", @@ -631,7 +496,7 @@ makeStream({ }, { type = "damage", - damage = { amount = 20, type = "acid" } + damage = { amount = 15, type = "acid" } } } } diff --git a/prototypes/enemies/AttackNE.lua b/prototypes/enemies/AttackNE.lua index d6a9279..b051cd8 100755 --- a/prototypes/enemies/AttackNE.lua +++ b/prototypes/enemies/AttackNE.lua @@ -42,7 +42,7 @@ makeStream({ }, { type = "damage", - damage = {amount = 25, type = "poison"} + damage = {amount = 24, type = "poison"} } } } @@ -91,11 +91,11 @@ makeStream({ { { type = "damage", - damage = { amount = 5, type = "explosion" } + damage = { amount = 8, type = "explosion" } }, { type = "damage", - damage = { amount = 15, type = "acid" } + damage = { amount = 18, type = "acid" } } } } @@ -135,11 +135,11 @@ makeStream({ { { type = "damage", - damage = { amount = 3, type = "explosion" } + damage = { amount = 5, type = "explosion" } }, { type = "damage", - damage = { amount = 7, type = "poison" } + damage = { amount = 12, type = "poison" } } } } @@ -183,11 +183,11 @@ makeStream({ { { type = "damage", - damage = { amount = 7, type = "explosion" } + damage = { amount = 5, type = "explosion" } }, { type = "damage", - damage = { amount = 14, type = "acid" } + damage = { amount = 12, type = "acid" } } } } diff --git a/prototypes/enemies/BiterUtils.lua b/prototypes/enemies/BiterUtils.lua index 4c97155..f8dccb6 100755 --- a/prototypes/enemies/BiterUtils.lua +++ b/prototypes/enemies/BiterUtils.lua @@ -218,22 +218,50 @@ function biterFunctions.createFireAttack(attributes, fireAttack) 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 } }, middle_sound = { { - filename = "__base__/sound/fight/flamethrower-mid.ogg", - volume = 0.7 + filename = attributes.midSound or "__Rampant__/sounds/attacks/acid-mid.ogg", + volume = 0.5 } }, end_sound = { { - filename = "__base__/sound/fight/flamethrower-end.ogg", - volume = 0.7 + filename = attributes.endSound or "__Rampant__/sounds/attacks/acid-end.ogg", + volume = 0.5 } } } diff --git a/prototypes/enemies/StreamUtils.lua b/prototypes/enemies/StreamUtils.lua index d1bfd93..6d02a7c 100755 --- a/prototypes/enemies/StreamUtils.lua +++ b/prototypes/enemies/StreamUtils.lua @@ -10,7 +10,8 @@ local makeSmokeSoft = smokeUtils.makeSmokeSoft -- module code -function streamUtils.makeStream(attributes) +function streamUtils.makeStream(info) + local attributes = util.table.deepcopy(info) local softSmokeName = attributes.softSmokeName or makeSmokeSoft(attributes) data:extend( { @@ -79,7 +80,7 @@ function streamUtils.makeStream(attributes) height = 64, frame_count = 32, line_length = 8 - }, + } } } ) diff --git a/prototypes/enemies/UpdatesBobs.lua b/prototypes/enemies/UpdatesBobs.lua index 1c66656..2b3657e 100755 --- a/prototypes/enemies/UpdatesBobs.lua +++ b/prototypes/enemies/UpdatesBobs.lua @@ -7,19 +7,19 @@ function bobsUpdates.useDumbProjectiles() turrets["bob-big-explosive-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 25, + cooldown = 60, + range = 26, min_range = 3, turn_range = 1, fire_penalty = 0, scale = 1.2 }, - "bob-explosive-ball-1-stream-rampant") + "bob-explosive-ball-stream-rampant") turrets["bob-big-fire-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 25, + cooldown = 60, + range = 26, min_range = 3, turn_range = 1, fire_penalty = 0, @@ -29,19 +29,19 @@ function bobsUpdates.useDumbProjectiles() turrets["bob-big-poison-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 25, + cooldown = 60, + range = 26, min_range = 3, turn_range = 1, fire_penalty = 0, scale = 1.2 }, - "bob-poison-ball-1-stream-rampant") + "bob-poison-ball-stream-rampant") turrets["bob-big-piercing-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 25, + cooldown = 60, + range = 26, min_range = 3, turn_range = 1, fire_penalty = 0, @@ -51,44 +51,44 @@ function bobsUpdates.useDumbProjectiles() turrets["bob-big-electric-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 25, + cooldown = 60, + range = 26, min_range = 3, turn_range = 1, fire_penalty = 0, scale = 1.2 }, - "bob-electric-ball-1-stream-rampant") + "bob-electric-ball-stream-rampant") turrets["bob-giant-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, + cooldown = 60, range = 28, min_range = 3, turn_range = 1, fire_penalty = 0, scale = 1.6 }, - "acid-ball-4-stream-rampant") + "acid-ball-5-stream-rampant") turrets["bob-behemoth-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, + cooldown = 60, range = 30, min_range = 3, turn_range = 1, fire_penalty = 0, scale = 2 }, - "acid-ball-5-stream-rampant") + "acid-ball-6-stream-rampant") local units = data.raw["unit"] local unit = units["behemoth-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, turn_range = 1, warmup = 30, @@ -102,10 +102,11 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-big-electric-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, + cooldown = 90, range = 15, min_range = 3, turn_range = 1, + damageModifier = 0.6, warmup = 30, fire_penalty = 0, scale = biterUtils.findRunScale(unit), @@ -117,11 +118,12 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-huge-explosive-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, warmup = 30, turn_range = 1, + damageModifier = 0.8, fire_penalty = 15, scale = biterUtils.findRunScale(unit), tint1 = biterUtils.findTint(unit), @@ -132,8 +134,8 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-huge-acid-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, turn_range = 1, warmup = 30, @@ -147,8 +149,8 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-giant-fire-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, turn_range = 1, warmup = 30, @@ -162,8 +164,8 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-giant-poison-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, turn_range = 1, warmup = 30, @@ -177,8 +179,8 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-titan-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, turn_range = 1, warmup = 30, @@ -192,8 +194,8 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-behemoth-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, turn_range = 1, warmup = 30, @@ -208,8 +210,8 @@ function bobsUpdates.useDumbProjectiles() unit = units["bob-leviathan-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 17, min_range = 3, warmup = 30, turn_range = 1, diff --git a/prototypes/enemies/UpdatesNE.lua b/prototypes/enemies/UpdatesNE.lua index 501bc26..96577f4 100755 --- a/prototypes/enemies/UpdatesNE.lua +++ b/prototypes/enemies/UpdatesNE.lua @@ -7,8 +7,8 @@ function NEUpdates.useNEUnitLaunchers () turrets["medium-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 22, + cooldown = 60, + range = 25, min_range = 3, turn_range = 1, fire_penalty = 0, @@ -19,8 +19,8 @@ function NEUpdates.useNEUnitLaunchers () turrets["big-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 27, + cooldown = 60, + range = 30, min_range = 3, turn_range = 1, fire_penalty = 0, @@ -40,13 +40,13 @@ function NEUpdates.useDumbProjectiles() turret["attack_parameters"].range = 22 turret["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 22, + cooldown = 60, + range = 25, min_range = 3, turn_range = 1, fire_penalty = 0, damageModifier = 4.5, - scale = 1.0 + scale = 1.2 }, "ne-infected-ball-stream-rampant") @@ -54,13 +54,13 @@ function NEUpdates.useDumbProjectiles() turret["attack_parameters"].range = 27 turret["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 27, + cooldown = 60, + range = 30, min_range = 3, turn_range = 1, fire_penalty = 0, damageModifier = 5.5, - scale = 1.2 + scale = 1.6 }, "ne-mutated-ball-stream-rampant") @@ -69,7 +69,7 @@ function NEUpdates.useDumbProjectiles() local unit = units["small-spitter-Mk2"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 150, + cooldown = 100, range = 13, min_range = 3, turn_range = 1, @@ -85,7 +85,7 @@ function NEUpdates.useDumbProjectiles() unit = units["small-spitter-Mk3"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 150, + cooldown = 100, range = 13, min_range = 3, turn_range = 1, @@ -102,7 +102,7 @@ function NEUpdates.useDumbProjectiles() unit = units["medium-spitter-Mk2"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 150, + cooldown = 100, range = 14, min_range = 3, turn_range = 1, @@ -118,7 +118,7 @@ function NEUpdates.useDumbProjectiles() unit = units["medium-spitter-Mk3"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 150, + cooldown = 100, range = 14, min_range = 3, turn_range = 1, @@ -134,7 +134,7 @@ function NEUpdates.useDumbProjectiles() unit = units["big-spitter-Mk2"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 150, + cooldown = 100, range = 15, min_range = 3, turn_range = 1, @@ -151,7 +151,7 @@ function NEUpdates.useDumbProjectiles() unit = units["big-spitter-Mk3"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 150, + cooldown = 100, range = 15, min_range = 3, turn_range = 1, diff --git a/prototypes/enemies/UpdatesVanilla.lua b/prototypes/enemies/UpdatesVanilla.lua index 48a56f0..51d26c6 100755 --- a/prototypes/enemies/UpdatesVanilla.lua +++ b/prototypes/enemies/UpdatesVanilla.lua @@ -7,44 +7,46 @@ function vanillaUpdates.useDumbProjectiles() turrets["small-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 50, - range = 18, + cooldown = 60, + range = 21, min_range = 5, turn_range = 1, fire_penalty = 0, + damageModifier = 0.9, scale = 0.8 }, - "acid-ball-stream-rampant") + "acid-ball-2-stream-rampant") turrets["medium-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 20, + cooldown = 60, + range = 25, min_range = 3, turn_range = 1, fire_penalty = 0, + damageModifier = 0.87, scale = 1 }, - "acid-ball-1-stream-rampant") + "acid-ball-3-stream-rampant") turrets["big-worm-turret"]["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 25, + cooldown = 60, + range = 26, min_range = 3, turn_range = 1, fire_penalty = 0, scale = 1.2 }, - "acid-ball-2-stream-rampant") + "acid-ball-4-stream-rampant") local units = data.raw["unit"]; local unit = units["small-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, + cooldown = 100, range = 13, warmup = 30, min_range = 3, @@ -59,7 +61,7 @@ function vanillaUpdates.useDumbProjectiles() unit = units["medium-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, + cooldown = 95, range = 14, min_range = 3, warmup = 30, @@ -74,7 +76,7 @@ function vanillaUpdates.useDumbProjectiles() unit = units["big-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, + cooldown = 90, range = 15, min_range = 3, warmup = 30, @@ -89,8 +91,8 @@ function vanillaUpdates.useDumbProjectiles() unit = units["behemoth-spitter"] unit["attack_parameters"] = biterUtils.createFireAttack( { - cooldown = 80, - range = 15, + cooldown = 90, + range = 16, min_range = 3, warmup = 30, turn_range = 1, diff --git a/settings.lua b/settings.lua index 980a8cb..230c4a6 100755 --- a/settings.lua +++ b/settings.lua @@ -193,17 +193,6 @@ data:extend({ order = "h[modifier]-a[optimize]", 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", diff --git a/sounds/attacks/acid-end.ogg b/sounds/attacks/acid-end.ogg new file mode 100755 index 0000000..dfc6c07 Binary files /dev/null and b/sounds/attacks/acid-end.ogg differ diff --git a/sounds/attacks/acid-mid.ogg b/sounds/attacks/acid-mid.ogg new file mode 100755 index 0000000..1342c61 Binary files /dev/null and b/sounds/attacks/acid-mid.ogg differ diff --git a/tests.lua b/tests.lua index e2e03f3..0d10722 100755 --- a/tests.lua +++ b/tests.lua @@ -5,22 +5,23 @@ local mathUtils = require("libs/MathUtils") local chunkUtils = require("libs/ChunkUtils") local mapUtils = require("libs/MapUtils") local baseUtils = require("libs/BaseUtils") -local baseRegisterUtils = require("libs/BaseRegisterUtils") -local tendrilUtils = require("libs/TendrilUtils") +-- local tendrilUtils = require("libs/TendrilUtils") function tests.pheromoneLevels(size) local player = game.player.character - local playerChunkX = math.floor(player.position.x / 32) - local playerChunkY = math.floor(player.position.y / 32) + local playerChunkX = math.floor(player.position.x / 32) * constants.CHUNK_SIZE + local playerChunkY = math.floor(player.position.y / 32) * constants.CHUNK_SIZE if not size then - size = 3 + size = 3 * constants.CHUNK_SIZE + else + size = size * constants.CHUNK_SIZE end print("------") print(#global.regionMap.processQueue) print(playerChunkX .. ", " .. playerChunkY) print("--") - for y=playerChunkY-size, playerChunkY+size do - for x=playerChunkX-size, playerChunkX+size do + for y=playerChunkY-size, playerChunkY+size,32 do + for x=playerChunkX-size, playerChunkX+size,32 do if (global.regionMap[x] ~= nil) then local chunk = global.regionMap[x][y] if (chunk ~= nil) then @@ -29,12 +30,12 @@ function tests.pheromoneLevels(size) str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i]) end 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(chunk.cX, chunk.cY, str) + print(chunk.x, chunk.y, str) print("=============") else - print(chunk.cX, chunk.cY, str) + print(chunk.x, chunk.y, str) end -- print(str) print("----") @@ -109,7 +110,7 @@ function tests.tunnelTest() local playerPosition = game.players[1].position local chunkX = math.floor(playerPosition.x * 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 function tests.createEnemy(x) @@ -121,7 +122,7 @@ end function tests.registeredNest(x) local entity = tests.createEnemy(x) - baseRegisterUtils.registerEnemyBaseStructure(global.regionMap, + chunk.registerEnemyBaseStructure(global.regionMap, entity, nil) end @@ -280,9 +281,9 @@ function tests.showMovementGrid() end function tests.stepAdvanceTendrils() - for _, base in pairs(global.natives.bases) do - tendrilUtils.advanceTendrils(global.regionMap, base, game.surfaces[1], {nil,nil,nil,nil,nil,nil,nil,nil}) - end + -- for _, base in pairs(global.natives.bases) do + -- tendrilUtils.advanceTendrils(global.regionMap, base, game.surfaces[1], {nil,nil,nil,nil,nil,nil,nil,nil}) + -- end end return tests