|
@@ -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::vector<Battl
|
|
|
|
|
|
if(stack->hasBonusOfType(Bonus::FLYING))
|
|
|
{
|
|
|
- std::set<BattleHex> moatHexes;
|
|
|
+ std::set<BattleHex> obstacleHexes;
|
|
|
|
|
|
- if(hb.battleGetSiegeLevel() >= BuildingID::CITADEL)
|
|
|
- {
|
|
|
- auto townMoat = hb.getDefendedTown()->town->moatHexes;
|
|
|
+ auto insertAffected = [](const CObstacleInstance* spellObst, std::set<BattleHex> obstacleHexes) {
|
|
|
+ auto affectedHexes = spellObst->getAffectedTiles();
|
|
|
+ obstacleHexes.insert(affectedHexes.cbegin(), affectedHexes.cend());
|
|
|
+ };
|
|
|
+
|
|
|
+ const auto & obstacles = hb.battleGetAllObstacles();
|
|
|
+
|
|
|
+ for (const auto & obst: obstacles) {
|
|
|
+ const auto * spellObst = dynamic_cast<const SpellCreatedObstacle*>(obst.get());
|
|
|
|
|
|
- moatHexes = std::set<BattleHex>(townMoat.begin(), townMoat.end());
|
|
|
+ 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;
|
|
|
});
|