diff --git a/Upgrade.lua b/Upgrade.lua index 90f86de..2c7f5bc 100644 --- a/Upgrade.lua +++ b/Upgrade.lua @@ -428,8 +428,8 @@ function upgrade.attempt(universe) universe.maxPoints = 0 end - if global.version < 201 then - global.version = 201 + if global.version < 202 then + global.version = 202 addCommandSet(universe) universe.eventId = 0 @@ -460,8 +460,10 @@ function upgrade.attempt(universe) universe.processActiveSpawnerIterator = nil universe.processActiveRaidSpawnerIterator = nil universe.processMigrationIterator = nil + universe.chunkToDrainedIterator = nil universe.chunkToActiveNest = {} universe.chunkToActiveRaidNest = {} + universe.chunkToDrained = {} game.print("Rampant - Version 2.0.0") end @@ -535,7 +537,6 @@ function upgrade.prepMap(universe, surface) map.chunkToPassable = {} map.chunkToPathRating = {} map.chunkToDeathGenerator = {} - map.chunkToDrained = {} map.chunkToPassScanIterator = nil map.recycleBaseIterator = nil diff --git a/changelog.txt b/changelog.txt index 04d3816..566bfe7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -73,6 +73,7 @@ Date: 23. 11. 2021 - Added debug mod settings for showing enemy structures being upgraded in place - Moved config methods into relevant code files - Removed unnecessary unregisterResource called on onMine event + - Cleaned up energy thief code in control Removals: - Removed map deadzones as they were breaking regional bases - Removed make building safe mod option, now each individual toggle works as people are expecting diff --git a/control.lua b/control.lua index 6b0aa18..b3b71ab 100644 --- a/control.lua +++ b/control.lua @@ -33,12 +33,6 @@ local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS local RETREAT_SPAWNER_GRAB_RADIUS = constants.RETREAT_SPAWNER_GRAB_RADIUS -local DEFINES_WIRE_TYPE_RED = defines.wire_type.red -local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green - -local ENERGY_THIEF_CONVERSION_TABLE = constants.ENERGY_THIEF_CONVERSION_TABLE -local ENERGY_THIEF_LOOKUP = constants.ENERGY_THIEF_LOOKUP - -- imported functions local nextMap = mapUtils.nextMap @@ -56,8 +50,6 @@ local isRampantSetting = stringUtils.isRampantSetting local processPendingUpgrades = chunkProcessor.processPendingUpgrades local canMigrate = aiPredicates.canMigrate -local convertTypeToDrainCrystal = unitUtils.convertTypeToDrainCrystal - local squadDispatch = squadAttack.squadDispatch local cleanUpMapTables = mapProcessor.cleanUpMapTables @@ -100,6 +92,13 @@ local findNearbyBase = baseUtils.findNearbyBase local processActiveNests = mapProcessor.processActiveNests +local removeDrainPylons = chunkPropertyUtils.removeDrainPylons +local getDrainPylonPair = chunkPropertyUtils.getDrainPylonPair + +local createDrainPylon = unitUtils.createDrainPylon + +local isDrained = chunkPropertyUtils.isDrained +local setDrainedTick = chunkPropertyUtils.setDrainedTick local getDeathGenerator = chunkPropertyUtils.getDeathGenerator local retreatUnits = squadDefense.retreatUnits @@ -430,27 +429,8 @@ local function onDeath(event) end end - elseif map.drainPylons[entity.unit_number] then - local entityUnitNumber = entity.unit_number - local pair = map.drainPylons[entityUnitNumber] - if pair then - local target = pair[1] - local pole = pair[2] - if target.unit_number == entityUnitNumber then - map.drainPylons[entityUnitNumber] = nil - if pole.valid then - map.drainPylons[pole.unit_number] = nil - pole.die() - end - elseif (pole.unit_number == entityUnitNumber) then - map.drainPylons[entityUnitNumber] = nil - if target.valid then - map.drainPylons[target.unit_number] = nil - target.destroy() - end - end - end - + elseif getDrainPylonPair(map, entity.unit_number) then + removeDrainPylons(map, entity.unit_number) else if event.force and (event.force.name ~= "enemy") then local rally = false @@ -491,60 +471,14 @@ local function onDeath(event) local creditNatives = false if (event.force ~= nil) and (event.force.name == "enemy") then creditNatives = true - local drained + local drained = false if (chunk ~= -1) then victoryScent(map, chunk, entityType) - drained = (entityType == "electric-turret") and map.chunkToDrained[chunk.id] + drained = (entityType == "electric-turret") and isDrained(map, chunk, tick) end - if cause or (drained and (drained - tick) > 0) then - if ((cause and ENERGY_THIEF_LOOKUP[cause.name]) or (not cause)) then - local conversion = ENERGY_THIEF_CONVERSION_TABLE[entityType] - if conversion then - local newEntity = surface.create_entity({ - position=entity.position, - name=convertTypeToDrainCrystal(entity.force.evolution_factor, conversion), - direction=entity.direction - }) - if (conversion == "pole") then - local targetEntity = surface.create_entity({ - position=entity.position, - name="pylon-target-rampant", - direction=entity.direction - }) - targetEntity.backer_name = "" - local pair = {targetEntity, newEntity} - map.drainPylons[targetEntity.unit_number] = pair - map.drainPylons[newEntity.unit_number] = pair - local wires = entity.neighbours - if wires then - for _,v in pairs(wires.copper) do - if (v.valid) then - newEntity.connect_neighbour(v); - end - end - for _,v in pairs(wires.red) do - if (v.valid) then - newEntity.connect_neighbour({ - wire = DEFINES_WIRE_TYPE_RED, - target_entity = v - }); - end - end - for _,v in pairs(wires.green) do - if (v.valid) then - newEntity.connect_neighbour({ - wire = DEFINES_WIRE_TYPE_GREEN, - target_entity = v - }); - end - end - end - elseif newEntity.backer_name then - newEntity.backer_name = "" - end - end - end + if cause or drained then + createDrainPylon(map, cause, entity, entityType) end end if creditNatives and (universe.safeEntities[entityType] or universe.safeEntities[entity.name]) @@ -738,7 +672,7 @@ local function onTriggerEntityCreated(event) end local chunk = getChunkByPosition(map, entity.position) if (chunk ~= -1) then - map.chunkToDrained[chunk.id] = event.tick + 60 + setDrainedTick(map, chunk, event.tick) end end end diff --git a/libs/ChunkPropertyUtils.lua b/libs/ChunkPropertyUtils.lua index b6cf7ba..493d436 100644 --- a/libs/ChunkPropertyUtils.lua +++ b/libs/ChunkPropertyUtils.lua @@ -7,6 +7,8 @@ local constants = require("Constants") -- constants +local COOLDOWN_DRAIN = constants.COOLDOWN_DRAIN + local RAIDING_MINIMUM_BASE_THRESHOLD = constants.RAIDING_MINIMUM_BASE_THRESHOLD local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE @@ -200,6 +202,58 @@ function chunkPropertyUtils.getEnemyStructureCount(map, chunk) (map.chunkToUtilities[chunk.id] or 0) + (map.chunkToHives[chunk.id] or 0) end +function chunkPropertyUtils.setDrainPylons(map, entity1, entity2) + local pair = {entity1, entity2} + map.drainPylons[entity1.unit_number] = pair + map.drainPylons[entity2.unit_number] = pair +end + +function chunkPropertyUtils.removeDrainPylons(map, unitNumber) + local pair = map.drainPylons[unitNumber] + if pair then + local target = pair[1] + local pole = pair[2] + if target.unit_number == unitNumber then + map.drainPylons[unitNumber] = nil + if pole.valid then + map.drainPylons[pole.unit_number] = nil + pole.die() + end + elseif (pole.unit_number == unitNumber) then + map.drainPylons[unitNumber] = nil + if target.valid then + map.drainPylons[target.unit_number] = nil + target.destroy() + end + end + end +end + +function chunkPropertyUtils.getDrainPylonPair(map, unitNumber) + return map.drainPylons[unitNumber] +end + +function chunkPropertyUtils.isDrained(map, chunk, tick) + local pack = map.universe.chunkToDrained[chunk.id] + if not pack then + return false + end + return (tick - pack.tick) < COOLDOWN_DRAIN +end + +function chunkPropertyUtils.setDrainedTick(map, chunk, tick) + local chunkId = chunk.id + local pack = map.universe.chunkToDrained[chunkId] + if not pack then + pack = { + map = map, + tick = 0 + } + map.universe.chunkToDrained[chunkId] = pack + end + pack.tick = tick +end + function chunkPropertyUtils.getRetreatTick(map, chunk) return map.chunkToRetreats[chunk.id] or 0 end diff --git a/libs/Constants.lua b/libs/Constants.lua index f891add..195a04b 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -62,6 +62,7 @@ constants.CHUNK_PASS_THRESHOLD = 0.2 constants.COOLDOWN_RALLY = constants.TICKS_A_SECOND * 10 constants.COOLDOWN_RETREAT = constants.TICKS_A_SECOND * 10 +constants.COOLDOWN_DRAIN = constants.TICKS_A_SECOND * 1 constants.RESOURCE_NORMALIZER = 1 / 1024 diff --git a/libs/MapProcessor.lua b/libs/MapProcessor.lua index 845db91..a6ea163 100644 --- a/libs/MapProcessor.lua +++ b/libs/MapProcessor.lua @@ -42,6 +42,7 @@ local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE local AI_STATE_PEACEFUL = constants.AI_STATE_PEACEFUL local AI_STATE_MIGRATING = constants.AI_STATE_MIGRATING +local COOLDOWN_DRAIN = constants.COOLDOWN_DRAIN local COOLDOWN_RALLY = constants.COOLDOWN_RALLY local COOLDOWN_RETREAT = constants.COOLDOWN_RETREAT @@ -265,12 +266,31 @@ function mapProcessor.processPlayers(players, universe, tick) end end +local function processCleanUp(universe, chunks, iterator, tick, duration) + local chunkId = universe[iterator] + local chunkPack + if not chunkId then + chunkId, chunkPack = next(chunks, nil) + else + chunkPack = chunks[chunkId] + end + if not chunkId then + universe[iterator] = nil + else + universe[iterator] = next(chunks, chunkId) + if (tick - chunkPack.tick) > duration then + chunks[chunkId] = nil + end + end +end + function mapProcessor.cleanUpMapTables(map, tick) local index = map.cleanupIndex + local universe = map.universe local retreats = map.chunkToRetreats local rallys = map.chunkToRallys - local drained = map.chunkToDrained + local drained = map.universe.chunkToDrained local processQueue = map.processQueue local processQueueLength = #processQueue @@ -293,10 +313,7 @@ function mapProcessor.cleanUpMapTables(map, tick) rallys[chunk] = nil end - local drainTick = drained[chunk] - if drainTick and ((tick - drainTick) > 0) then - drained[chunk] = nil - end + processCleanUp(universe, drained, "chunkToDrainedIterator", tick, COOLDOWN_DRAIN) end if (endIndex == processQueueLength) then diff --git a/libs/UnitUtils.lua b/libs/UnitUtils.lua index d612c58..3e9ab6c 100644 --- a/libs/UnitUtils.lua +++ b/libs/UnitUtils.lua @@ -6,16 +6,25 @@ local unitUtils = {} -- imports local constants = require("Constants") +local chunkPropertyUtils = require("ChunkPropertyUtils") -- constants +local DEFINES_WIRE_TYPE_RED = defines.wire_type.red +local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green + +local ENERGY_THIEF_CONVERSION_TABLE = constants.ENERGY_THIEF_CONVERSION_TABLE +local ENERGY_THIEF_LOOKUP = constants.ENERGY_THIEF_LOOKUP + local ENERGY_THIEF_DRAIN_CRYSTALS = constants.ENERGY_THIEF_DRAIN_CRYSTALS -- imported functions +local setDrainPylons = chunkPropertyUtils.setDrainPylons + -- module code -function unitUtils.convertTypeToDrainCrystal(evolutionFactor, entity) +local function convertTypeToDrainCrystal(evolutionFactor, entity) if (entity == "pole") then return "crystal-drain-pole-rampant" else @@ -53,5 +62,53 @@ function unitUtils.convertTypeToDrainCrystal(evolutionFactor, entity) end end +function unitUtils.createDrainPylon(map, cause, entity, entityType) + if ((cause and ENERGY_THIEF_LOOKUP[cause.name]) or (not cause)) then + local conversion = ENERGY_THIEF_CONVERSION_TABLE[entityType] + if conversion then + local newEntity = map.surface.create_entity({ + position=entity.position, + name=convertTypeToDrainCrystal(entity.force.evolution_factor, conversion), + direction=entity.direction + }) + if (conversion == "pole") then + local targetEntity = map.surface.create_entity({ + position=entity.position, + name="pylon-target-rampant", + direction=entity.direction + }) + targetEntity.backer_name = "" + local wires = entity.neighbours + if wires then + for _,v in pairs(wires.copper) do + if (v.valid) then + newEntity.connect_neighbour(v); + end + end + for _,v in pairs(wires.red) do + if (v.valid) then + newEntity.connect_neighbour({ + wire = DEFINES_WIRE_TYPE_RED, + target_entity = v + }); + end + end + for _,v in pairs(wires.green) do + if (v.valid) then + newEntity.connect_neighbour({ + wire = DEFINES_WIRE_TYPE_GREEN, + target_entity = v + }); + end + end + end + setDrainPylons(map, targetEntity, newEntity) + elseif newEntity.backer_name then + newEntity.backer_name = "" + end + end + end +end + unitUtilsG = unitUtils return unitUtils