Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/army.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/ai/petra/army.js +++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/army.js @@ -280,8 +280,69 @@ { while (this.foeEntities.length > 0) this.removeFoe(gameState,this.foeEntities[0]); + + // Go back to our territory, using the nearest (defensive if any) structure. + let armyPos = [0, 0]; + let npos = 0; + for (let entId of this.ownEntities) + { + let ent = gameState.getEntityById(entId); + if (!ent) + continue; + let pos = ent.position(); + if (!pos || gameState.ai.HQ.territoryMap.getOwner(pos) === PlayerID) + continue; + armyPos[0] += pos[0]; + armyPos[1] += pos[1]; + ++npos; + } + let nearestStructurePos; + let defensiveFound; + let distmin; + let radius; + if (npos > 0) + { + armyPos[0] /= npos; + armyPos[1] /= npos; + let armyAccess = gameState.ai.accessibility.getAccessValue(armyPos); + for (let struct of gameState.getOwnStructures().values()) + { + let pos = struct.position(); + if (!pos || gameState.ai.HQ.territoryMap.getOwner(pos) !== PlayerID) + continue; + if (m.getLandAccess(gameState, struct) !== armyAccess) + continue; + let defensiveStruct = struct.hasDefensiveFire(); + if (defensiveFound && !defensiveStruct) + continue; + let dist = API3.SquareVectorDistance(armyPos, pos); + if (distmin && dist > distmin && (defensiveFound || !defensiveStruct)) + continue; + if (defensiveStruct) + defensiveFound = true; + distmin = dist; + nearestStructurePos = pos; + radius = struct.obstructionRadius(); + } + } while (this.ownEntities.length > 0) - this.removeOwn(gameState,this.ownEntities[0]); + { + let entId = this.ownEntities[0]; + this.removeOwn(gameState, entId); + let ent = gameState.getEntityById(entId); + if (ent) + { + if (!ent.position() || + ent.healthLevel() < this.Config.garrisonHealthLevel.low && + gameState.ai.HQ.defenseManager.garrisonAttackedUnit(gameState, ent)) + continue; + + if (nearestStructurePos && gameState.ai.HQ.territoryMap.getOwner(ent.position()) !== PlayerID) + ent.moveToRange(nearestStructurePos[0], nearestStructurePos[1], radius, radius+5); + else + ent.stopMoving(); + } + } this.assignedAgainst = {}; this.assignedTo = {}; Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/defenseManager.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/ai/petra/defenseManager.js +++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/defenseManager.js @@ -566,18 +566,18 @@ let minGarrison = data.min ? data.min : target.garrisonMax(); let typeGarrison = data.type ? data.type : "protection"; if (gameState.ai.HQ.garrisonManager.numberOfGarrisonedUnits(target) >= minGarrison) - return; + return false; if (target.hitpoints() < target.garrisonEjectHealth() * target.maxHitpoints()) - return; + return false; if (data.attacker) { let attackTypes = target.attackTypes(); if (!attackTypes || attackTypes.indexOf("Ranged") === -1) - return; + return false; let dist = API3.SquareVectorDistance(data.attacker.position(), target.position()); let range = target.attackRange("Ranged").max; if (dist >= range*range) - return; + return false; } let index = gameState.ai.accessibility.getAccessValue(target.position()); let garrisonManager = gameState.ai.HQ.garrisonManager; @@ -592,6 +592,7 @@ else allowMelee = true; } + let ret = false; for (let ent of units.values()) { if (garrisonManager.numberOfGarrisonedUnits(target) >= minGarrison) @@ -623,7 +624,9 @@ if (army) army.removeOwn(gameState, ent.id()); garrisonManager.garrison(gameState, ent, target, typeGarrison); + ret = true; } + return ret; }; /** garrison a attacked siege ranged unit inside the nearest fortress */ @@ -650,6 +653,7 @@ }); if (nearest) garrisonManager.garrison(gameState, unit, nearest, "protection"); + return nearest !== undefined; }; /** @@ -683,17 +687,18 @@ nearest = ent; } if (!nearest) - return; + return false; if (!emergency) { garrisonManager.garrison(gameState, unit, nearest, "protection"); - return; + return true; } if (garrisonManager.numberOfGarrisonedUnits(nearest) >= nearest.garrisonMax()) // make room for this ent nearest.unload(nearest.garrisoned()[0]); garrisonManager.garrison(gameState, unit, nearest, nearest.buffHeal() ? "protection" : "emergency"); + return true; }; /**