diff --git a/AI/BattleAI/BattleAI.cpp b/AI/BattleAI/BattleAI.cpp index 0b7e41f05..527969bc6 100644 --- a/AI/BattleAI/BattleAI.cpp +++ b/AI/BattleAI/BattleAI.cpp @@ -19,6 +19,7 @@ #include "../../lib/spells/CSpellHandler.h" #include "../../lib/spells/ISpellMechanics.h" #include "../../lib/battle/BattleStateInfoForRetreat.h" +#include "../../lib/battle/CObstacleInstance.h" #include "../../lib/CStack.h" // TODO: remove // Eventually only IBattleInfoCallback and battle::Unit should be used, // CUnitState should be private and CStack should be removed completely @@ -309,25 +310,38 @@ BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vectorhasBonusOfType(Bonus::FLYING)) { - std::set moatHexes; + std::set obstacleHexes; - if(hb.battleGetSiegeLevel() >= BuildingID::CITADEL) - { - auto townMoat = hb.getDefendedTown()->town->moatHexes; + auto insertAffected = [](const CObstacleInstance* spellObst, std::set obstacleHexes) { + auto affectedHexes = spellObst->getAffectedTiles(); + obstacleHexes.insert(affectedHexes.cbegin(), affectedHexes.cend()); + }; - moatHexes = std::set(townMoat.begin(), townMoat.end()); + const auto & obstacles = hb.battleGetAllObstacles(); + + for (const auto & obst: obstacles) { + const auto * spellObst = dynamic_cast(obst.get()); + + if(spellObst && spellObst->trigger) + { + auto triggerAbility = VLC->spells()->getById(SpellID(spellObst->ID)); + auto triggerIsNegative = triggerAbility->isNegative() || triggerAbility->isDamage(); + + if(triggerIsNegative) + insertAffected(spellObst, obstacleHexes); + } } // Flying stack doesn't go hex by hex, so we can't backtrack using predecessors. // We just check all available hexes and pick the one closest to the target. auto nearestAvailableHex = vstd::minElementByFun(avHexes, [&](BattleHex hex) -> int { - const int MOAT_PENALTY = 100; // avoid landing on moat + const int NEGATIVE_OBSTACLE_PENALTY = 100; // avoid landing on negative obstacle (moat, fire wall, etc) const int BLOCKED_STACK_PENALTY = 100; // avoid landing on moat auto distance = BattleHex::getDistance(bestNeighbor, hex); - if(vstd::contains(moatHexes, hex)) - distance += MOAT_PENALTY; + if(vstd::contains(obstacleHexes, hex)) + distance += NEGATIVE_OBSTACLE_PENALTY; return scoreEvaluator.checkPositionBlocksOurStacks(hb, stack, hex) ? BLOCKED_STACK_PENALTY + distance : distance; });