diff --git a/binaries/data/mods/public/simulation/ai/petra/attackManager.js b/binaries/data/mods/public/simulation/ai/petra/attackManager.js index 4ee3536f3e..bfa331bb72 100644 --- a/binaries/data/mods/public/simulation/ai/petra/attackManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/attackManager.js @@ -244,21 +244,8 @@ m.AttackManager.prototype.update = function(gameState, queues, events) break; target = undefined; } - if (target) - { - // prepare a raid against this target - let data = { "target": target }; - let attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, "Raid", data); - if (!attackPlan.failed) - { - if (this.Config.debug > 1) - API3.warn("Headquarters: Raiding plan " + this.totalNumber); - this.totalNumber++; - attackPlan.init(gameState); - this.upcomingAttacks.Raid.push(attackPlan); - } - this.raidNumber++; - } + if (target) // prepare a raid against this target + this.raidTargetEntity(gameState, target); } }; @@ -501,6 +488,21 @@ m.AttackManager.prototype.cancelAttacksAgainstPlayer = function(gameState, playe } }; +m.AttackManager.prototype.raidTargetEntity = function(gameState, ent) +{ + let data = { "target": ent }; + let attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, "Raid", data); + if (!attackPlan.failed) + { + if (this.Config.debug > 1) + API3.warn("Headquarters: Raiding plan " + this.totalNumber); + this.totalNumber++; + attackPlan.init(gameState); + this.upcomingAttacks.Raid.push(attackPlan); + } + this.raidNumber++; +}; + m.AttackManager.prototype.Serialize = function() { let properties = { diff --git a/binaries/data/mods/public/simulation/ai/petra/attackPlan.js b/binaries/data/mods/public/simulation/ai/petra/attackPlan.js index 339a32352c..d675b67336 100644 --- a/binaries/data/mods/public/simulation/ai/petra/attackPlan.js +++ b/binaries/data/mods/public/simulation/ai/petra/attackPlan.js @@ -798,7 +798,8 @@ m.AttackPlan.prototype.getNearestTarget = function(gameState, position, sameLand let minDist = Math.min(); for (let ent of targets.values()) { - if (this.targetPlayer === 0 && gameState.getGameType() === "capture_the_relic" && !ent.hasClass("Relic")) + if (this.targetPlayer === 0 && gameState.getGameType() === "capture_the_relic" && + (!ent.hasClass("Relic") || gameState.ai.HQ.gameTypeManager.targetedGaiaRelics.has(ent.id()))) continue; if (!ent.position()) continue; @@ -822,6 +823,8 @@ m.AttackPlan.prototype.getNearestTarget = function(gameState, position, sameLand if (!target) return undefined; + if (this.targetPlayer === 0 && gameState.getGameType() === "capture_the_relic" && target.hasClass("Relic")) + gameState.ai.HQ.gameTypeManager.targetedGaiaRelics.add(target.id()); // Rushes can change their enemy target if nothing found with the preferred enemy // Obstruction also can change the enemy target this.targetPlayer = target.owner(); diff --git a/binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js b/binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js index 8fbf424a36..e32e63c796 100644 --- a/binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js @@ -15,6 +15,10 @@ m.GameTypeManager = function(Config) this.healersPerCriticalEnt = 2 + Math.round(this.Config.personality.defensive * 2); this.tryCaptureGaiaRelic = false; this.tryCaptureGaiaRelicLapseTime = -1; + this.tryCaptureGaiaRelicLocal = false; + this.tryCaptureGaiaRelicLocalLapseTime = -1; + // Gaia relics which we are targeting currently and have not captured yet + this.targetedGaiaRelics = new Set(); }; /** @@ -236,6 +240,9 @@ m.GameTypeManager.prototype.checkEvents = function(gameState, events) this.removeGuardsFromCriticalEnt(gameState, evt.entity); continue; } + if (evt.from === 0 && this.targetedGaiaRelics.has(evt.entity)) + this.targetedGaiaRelics.delete(evt.entity); + if (evt.to !== PlayerID) continue; @@ -251,6 +258,8 @@ m.GameTypeManager.prototype.checkEvents = function(gameState, events) if (evt.from === 0) gameState.ai.HQ.attackManager.cancelAttacksAgainstPlayer(gameState, evt.from); } + if (ent.hasClass("Relic")) + this.targetedGaiaRelics.delete(ent.id()); } } }; @@ -540,6 +549,25 @@ m.GameTypeManager.prototype.update = function(gameState, events, queues) this.manageCriticalEntGuards(gameState); if (!this.tryCaptureGaiaRelic && gameState.ai.elapsedTime > this.tryCaptureGaiaRelicLapseTime) this.tryCaptureGaiaRelic = true; + + // Look for some relic that may be on our territory at game-start or if our territory boundaries change + if (!this.tryCaptureGaiaRelicLocal && gameState.ai.elapsedTime > this.tryCaptureGaiaRelicLocalLapseTime) + { + let allRelics = gameState.updatingGlobalCollection("allRelics", API3.Filters.byClass("Relic")); + for (let relic of allRelics.values()) + { + let relicPosition = relic.position(); + if (this.targetedGaiaRelics.has(relic.id()) || relic.owner() !== 0 || + !relicPosition || gameState.ai.HQ.territoryMap.getOwner(relicPosition) !== PlayerID) + continue; + + gameState.ai.HQ.attackManager.raidTargetEntity(gameState, relic); + this.targetedGaiaRelics.add(relic.id()); + this.tryCaptureGaiaRelicLocal = false; + this.tryCaptureGaiaRelicLocalLapseTime = gameState.ai.elapsedTime + 60 - 30 * (this.Config.difficulty - 3); + break; + } + } } }; @@ -550,7 +578,10 @@ m.GameTypeManager.prototype.Serialize = function() "guardEnts": this.guardEnts, "healersPerCriticalEnt": this.healersPerCriticalEnt, "tryCaptureGaiaRelic": this.tryCaptureGaiaRelic, - "tryCaptureGaiaRelicLapseTime": this.tryCaptureGaiaRelicLapseTime + "tryCaptureGaiaRelicLapseTime": this.tryCaptureGaiaRelicLapseTime, + "tryCaptureGaiaRelicLocal": this.tryCaptureGaiaRelicLocal, + "tryCaptureGaiaRelicLocalLapseTime": this.tryCaptureGaiaRelicLocalLapseTime, + "targetedGaiaRelics": this.targetedGaiaRelics }; };