From 9e78a3fe927cf54a8717f7cab405f653ab788fde Mon Sep 17 00:00:00 2001 From: Fabio Pedretti Date: Thu, 22 Oct 2026 09:37:19 +0200 Subject: [PATCH] Cache canAttackTarget per template in DefenseArmy.assignUnit For a foe which is not capturable, allowCapture has no effect and the result of canAttackTarget only depends on the template of the unit. Cache it in the foe info, which is rebuilt each turn. --- .../public/simulation/ai/petra/defenseArmy.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/binaries/data/mods/public/simulation/ai/petra/defenseArmy.js b/binaries/data/mods/public/simulation/ai/petra/defenseArmy.js index 3438e5f3b4..4ba951d182 100644 --- a/binaries/data/mods/public/simulation/ai/petra/defenseArmy.js +++ b/binaries/data/mods/public/simulation/ai/petra/defenseArmy.js @@ -29,9 +29,9 @@ function getFoeInfo(gameState, foeEntities) if (orderData && orderData.length && orderData[0].target) attackTarget = orderData[0].target; } - // "heavy" and "access" are filled lazily. + // "heavy", "access" and the entries of "canAttack" are filled lazily. info.push({ "id": id, "ent": eEnt, "position": position, "attackTarget": attackTarget, - "heavy": undefined, "access": undefined }); + "capturable": eEnt.isCapturable(), "canAttack": new Map(), "heavy": undefined, "access": undefined }); } return info; } @@ -346,6 +346,7 @@ export class DefenseArmy const pos = ent.position(); if (!pos) return false; + const template = ent.templateName(); // try to return its resources, and if any, the attack order will be queued const queued = returnResources(gameState, ent); @@ -359,7 +360,15 @@ export class DefenseArmy for (const foe of this.foeInfo) { const eEnt = foe.ent; - if (!ent.canAttackTarget(eEnt, allowCapture(gameState, ent, eEnt))) + // For a foe which is not capturable, allowCapture has no effect, so the result only depends on the template. + let canAttack = foe.canAttack.get(template); + if (canAttack === undefined) + { + canAttack = ent.canAttackTarget(eEnt, allowCapture(gameState, ent, eEnt)); + if (!foe.capturable) + foe.canAttack.set(template, canAttack); + } + if (!canAttack) continue; if (foe.attackTarget === entID)