mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Unit.cpp refactor and some other minor changes
This commit is contained in:
parent
e3516120d8
commit
fb9a3da651
@ -280,7 +280,7 @@ int64_t AttackPossibility::evaluateBlockedShootersDmg(
|
|||||||
std::set<uint32_t> checkedUnits;
|
std::set<uint32_t> checkedUnits;
|
||||||
|
|
||||||
auto attacker = attackInfo.attacker;
|
auto attacker = attackInfo.attacker;
|
||||||
auto hexes = attacker->getSurroundingHexes(hex);
|
const BattleHexArray & hexes = attacker->getSurroundingHexes(hex);
|
||||||
for(BattleHex tile : hexes)
|
for(BattleHex tile : hexes)
|
||||||
{
|
{
|
||||||
auto st = state->battleGetUnitByPos(tile, true);
|
auto st = state->battleGetUnitByPos(tile, true);
|
||||||
|
@ -278,7 +278,7 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
|||||||
score = moveTarget.score;
|
score = moveTarget.score;
|
||||||
cachedAttack.ap = moveTarget.cachedAttack;
|
cachedAttack.ap = moveTarget.cachedAttack;
|
||||||
cachedAttack.score = score;
|
cachedAttack.score = score;
|
||||||
cachedAttack.turn = moveTarget.turnsToRich;
|
cachedAttack.turn = moveTarget.turnsToReach;
|
||||||
|
|
||||||
if(stack->waited())
|
if(stack->waited())
|
||||||
{
|
{
|
||||||
@ -390,11 +390,11 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
|
|||||||
return reachability.distances[h1] < reachability.distances[h2];
|
return reachability.distances[h1] < reachability.distances[h2];
|
||||||
});
|
});
|
||||||
|
|
||||||
BattleHex bestNeighbor = targetHexes.front();
|
BattleHex bestNeighbour = hexes.front();
|
||||||
|
|
||||||
if(reachability.distances[bestNeighbor] > GameConstants::BFIELD_SIZE)
|
if(reachability.distances[bestNeighbour] > GameConstants::BFIELD_SIZE)
|
||||||
{
|
{
|
||||||
logAi->trace("No richable hexes.");
|
logAi->trace("No reachable hexes.");
|
||||||
return BattleAction::makeDefend(stack);
|
return BattleAction::makeDefend(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,22 +421,17 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
|
|||||||
{
|
{
|
||||||
BattleHexArray obstacleHexes;
|
BattleHexArray obstacleHexes;
|
||||||
|
|
||||||
auto insertAffected = [](const CObstacleInstance & spellObst, BattleHexArray & obstacleHexes) {
|
|
||||||
auto affectedHexes = spellObst.getAffectedTiles();
|
|
||||||
obstacleHexes.merge(affectedHexes);
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto & obstacles = hb->battleGetAllObstacles();
|
const auto & obstacles = hb->battleGetAllObstacles();
|
||||||
|
|
||||||
for (const auto & obst : obstacles) {
|
for (const auto & obst : obstacles)
|
||||||
|
{
|
||||||
if(obst->triggersEffects())
|
if(obst->triggersEffects())
|
||||||
{
|
{
|
||||||
auto triggerAbility = VLC->spells()->getById(obst->getTrigger());
|
auto triggerAbility = VLC->spells()->getById(obst->getTrigger());
|
||||||
auto triggerIsNegative = triggerAbility->isNegative() || triggerAbility->isDamage();
|
auto triggerIsNegative = triggerAbility->isNegative() || triggerAbility->isDamage();
|
||||||
|
|
||||||
if(triggerIsNegative)
|
if(triggerIsNegative)
|
||||||
insertAffected(*obst, obstacleHexes);
|
obstacleHexes.merge(obst->getAffectedTiles());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flying stack doesn't go hex by hex, so we can't backtrack using predecessors.
|
// Flying stack doesn't go hex by hex, so we can't backtrack using predecessors.
|
||||||
@ -446,7 +441,7 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
|
|||||||
const int NEGATIVE_OBSTACLE_PENALTY = 100; // avoid landing on negative obstacle (moat, fire wall, etc)
|
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
|
const int BLOCKED_STACK_PENALTY = 100; // avoid landing on moat
|
||||||
|
|
||||||
auto distance = BattleHex::getDistance(bestNeighbor, hex);
|
auto distance = BattleHex::getDistance(bestNeighbour, hex);
|
||||||
|
|
||||||
if(vstd::contains(obstacleHexes, hex))
|
if(vstd::contains(obstacleHexes, hex))
|
||||||
distance += NEGATIVE_OBSTACLE_PENALTY;
|
distance += NEGATIVE_OBSTACLE_PENALTY;
|
||||||
@ -458,7 +453,8 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BattleHex currentDest = bestNeighbor;
|
BattleHex currentDest = bestNeighbour;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
if(!currentDest.isValid())
|
if(!currentDest.isValid())
|
||||||
|
@ -21,7 +21,7 @@ AttackerValue::AttackerValue()
|
|||||||
MoveTarget::MoveTarget()
|
MoveTarget::MoveTarget()
|
||||||
: positions(), cachedAttack(), score(EvaluationResult::INEFFECTIVE_SCORE)
|
: positions(), cachedAttack(), score(EvaluationResult::INEFFECTIVE_SCORE)
|
||||||
{
|
{
|
||||||
turnsToRich = 1;
|
turnsToReach = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float BattleExchangeVariant::trackAttack(
|
float BattleExchangeVariant::trackAttack(
|
||||||
@ -361,7 +361,8 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
float penaltyMultiplier = 1.0f; // Default multiplier, no penalty
|
float penaltyMultiplier = 1.0f; // Default multiplier, no penalty
|
||||||
float closestAllyDistance = std::numeric_limits<float>::max();
|
float closestAllyDistance = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
for (const battle::Unit* ally : hb->battleAliveUnits()) {
|
for (const battle::Unit* ally : hb->battleAliveUnits())
|
||||||
|
{
|
||||||
if (ally == activeStack)
|
if (ally == activeStack)
|
||||||
continue;
|
continue;
|
||||||
if (ally->unitSide() != activeStack->unitSide())
|
if (ally->unitSide() != activeStack->unitSide())
|
||||||
@ -375,12 +376,13 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If an ally is closer to the enemy, compute the penaltyMultiplier
|
// If an ally is closer to the enemy, compute the penaltyMultiplier
|
||||||
if (closestAllyDistance < distance) {
|
if (closestAllyDistance < distance)
|
||||||
|
{
|
||||||
penaltyMultiplier = closestAllyDistance / distance; // Ratio of distances
|
penaltyMultiplier = closestAllyDistance / distance; // Ratio of distances
|
||||||
}
|
}
|
||||||
|
|
||||||
auto turnsToRich = (distance - 1) / speed + 1;
|
auto turnsToReach = (distance - 1) / speed + 1;
|
||||||
auto hexes = enemy->getSurroundingHexes();
|
const BattleHexArray & hexes = enemy->getSurroundingHexes();
|
||||||
auto enemySpeed = enemy->getMovementRange();
|
auto enemySpeed = enemy->getMovementRange();
|
||||||
auto speedRatio = speed / static_cast<float>(enemySpeed);
|
auto speedRatio = speed / static_cast<float>(enemySpeed);
|
||||||
auto multiplier = (speedRatio > 1 ? 1 : speedRatio) * penaltyMultiplier;
|
auto multiplier = (speedRatio > 1 ? 1 : speedRatio) * penaltyMultiplier;
|
||||||
@ -393,16 +395,16 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
|
|
||||||
attack.shootersBlockedDmg = 0; // we do not want to count on it, it is not for sure
|
attack.shootersBlockedDmg = 0; // we do not want to count on it, it is not for sure
|
||||||
|
|
||||||
auto score = calculateExchange(attack, turnsToRich, targets, damageCache, hb);
|
auto score = calculateExchange(attack, turnsToReach, targets, damageCache, hb);
|
||||||
|
|
||||||
score.enemyDamageReduce *= multiplier;
|
score.enemyDamageReduce *= multiplier;
|
||||||
|
|
||||||
#if BATTLE_TRACE_LEVEL >= 1
|
#if BATTLE_TRACE_LEVEL >= 1
|
||||||
logAi->trace("Multiplier: %f, turns: %d, current score %f, new score %f", multiplier, turnsToRich, result.score, scoreValue(score));
|
logAi->trace("Multiplier: %f, turns: %d, current score %f, new score %f", multiplier, turnsToReach, result.score, scoreValue(score));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(result.score < scoreValue(score)
|
if(result.score < scoreValue(score)
|
||||||
|| (result.turnsToRich > turnsToRich && vstd::isAlmostEqual(result.score, scoreValue(score))))
|
|| (result.turnsToReach > turnsToReach && vstd::isAlmostEqual(result.score, scoreValue(score))))
|
||||||
{
|
{
|
||||||
result.score = scoreValue(score);
|
result.score = scoreValue(score);
|
||||||
result.positions.clear();
|
result.positions.clear();
|
||||||
@ -411,10 +413,8 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
logAi->trace("New high score");
|
logAi->trace("New high score");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(const BattleHex & initialEnemyHex : enemy->getAttackableHexes(activeStack))
|
for(BattleHex enemyHex : enemy->getAttackableHexes(activeStack))
|
||||||
{
|
{
|
||||||
BattleHex enemyHex = initialEnemyHex;
|
|
||||||
|
|
||||||
while(!flying && dists.distances[enemyHex] > speed && dists.predecessors.at(enemyHex).isValid())
|
while(!flying && dists.distances[enemyHex] > speed && dists.predecessors.at(enemyHex).isValid())
|
||||||
{
|
{
|
||||||
enemyHex = dists.predecessors.at(enemyHex);
|
enemyHex = dists.predecessors.at(enemyHex);
|
||||||
@ -462,7 +462,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.cachedAttack = attack;
|
result.cachedAttack = attack;
|
||||||
result.turnsToRich = turnsToRich;
|
result.turnsToReach = turnsToReach;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,7 +484,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getAdjacentUnits(cons
|
|||||||
queue.pop();
|
queue.pop();
|
||||||
checkedStacks.push_back(stack);
|
checkedStacks.push_back(stack);
|
||||||
|
|
||||||
auto hexes = stack->getSurroundingHexes();
|
auto const & hexes = stack->getSurroundingHexes();
|
||||||
for(auto hex : hexes)
|
for(auto hex : hexes)
|
||||||
{
|
{
|
||||||
auto neighbour = cb->battleGetUnitByPos(hex);
|
auto neighbour = cb->battleGetUnitByPos(hex);
|
||||||
@ -511,7 +511,8 @@ ReachabilityData BattleExchangeEvaluator::getExchangeUnits(
|
|||||||
|
|
||||||
auto hexes = ap.attack.defender->getSurroundingHexes();
|
auto hexes = ap.attack.defender->getSurroundingHexes();
|
||||||
|
|
||||||
if(!ap.attack.shooting) hexes.insert(ap.from);
|
if(!ap.attack.shooting)
|
||||||
|
hexes.insert(ap.from);
|
||||||
|
|
||||||
std::vector<const battle::Unit *> allReachableUnits = additionalUnits;
|
std::vector<const battle::Unit *> allReachableUnits = additionalUnits;
|
||||||
|
|
||||||
@ -959,8 +960,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getOneTurnReachableUn
|
|||||||
|
|
||||||
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||||
{
|
{
|
||||||
const BattleHexArray & neighbours = BattleHexArray::neighbouringTilesCache[hex.hex];
|
for(BattleHex neighbour : BattleHexArray::neighbouringTilesCache[hex.hex])
|
||||||
for(BattleHex neighbour : neighbours)
|
|
||||||
{
|
{
|
||||||
reachable = unitReachability.distances.at(neighbour) <= radius;
|
reachable = unitReachability.distances.at(neighbour) <= radius;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ struct MoveTarget
|
|||||||
float score;
|
float score;
|
||||||
BattleHexArray positions;
|
BattleHexArray positions;
|
||||||
std::optional<AttackPossibility> cachedAttack;
|
std::optional<AttackPossibility> cachedAttack;
|
||||||
uint8_t turnsToRich;
|
uint8_t turnsToReach;
|
||||||
|
|
||||||
MoveTarget();
|
MoveTarget();
|
||||||
};
|
};
|
||||||
|
@ -55,42 +55,11 @@ BattleHex BattleHexArray::getClosestTile(BattleSide side, BattleHex initialPos)
|
|||||||
|
|
||||||
auto bestTile = std::min_element(closestTiles.begin(), closestTiles.end(), compareHorizontal);
|
auto bestTile = std::min_element(closestTiles.begin(), closestTiles.end(), compareHorizontal);
|
||||||
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
|
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
|
||||||
|
|
||||||
//BattleHex initialHex = BattleHex(initialPos);
|
|
||||||
//auto compareDistance = [initialHex](const BattleHex left, const BattleHex right) -> bool
|
|
||||||
//{
|
|
||||||
// return initialHex.getDistance(initialHex, left) < initialHex.getDistance(initialHex, right);
|
|
||||||
//};
|
|
||||||
//BattleHexArray sortedTiles(*this);
|
|
||||||
//boost::sort(sortedTiles, compareDistance); //closest tiles at front
|
|
||||||
//int closestDistance = initialHex.getDistance(initialPos, sortedTiles.front()); //sometimes closest tiles can be many hexes away
|
|
||||||
//auto notClosest = [closestDistance, initialPos](const BattleHex here) -> bool
|
|
||||||
//{
|
|
||||||
// return closestDistance < here.getDistance(initialPos, here);
|
|
||||||
//};
|
|
||||||
//vstd::erase_if(sortedTiles, notClosest); //only closest tiles are interesting
|
|
||||||
//auto compareHorizontal = [side, initialPos](const BattleHex left, const BattleHex right) -> bool
|
|
||||||
//{
|
|
||||||
// if(left.getX() != right.getX())
|
|
||||||
// {
|
|
||||||
// if(side == BattleSide::ATTACKER)
|
|
||||||
// return left.getX() > right.getX(); //find furthest right
|
|
||||||
// else
|
|
||||||
// return left.getX() < right.getX(); //find furthest left
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// //Prefer tiles in the same row.
|
|
||||||
// return std::abs(left.getY() - initialPos.getY()) < std::abs(right.getY() - initialPos.getY());
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
//boost::sort(sortedTiles, compareHorizontal);
|
|
||||||
//return sortedTiles.front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray::NeighbouringTilesCache BattleHexArray::calculateNeighbouringTiles()
|
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::calculateNeighbouringTiles()
|
||||||
{
|
{
|
||||||
BattleHexArray::NeighbouringTilesCache ret;
|
BattleHexArray::ArrayOfBattleHexArrays ret;
|
||||||
|
|
||||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||||
{
|
{
|
||||||
@ -110,50 +79,75 @@ BattleHexArray BattleHexArray::generateNeighbouringTiles(BattleHex hex)
|
|||||||
BattleHexArray ret;
|
BattleHexArray ret;
|
||||||
for(auto dir : BattleHex::hexagonalDirections())
|
for(auto dir : BattleHex::hexagonalDirections())
|
||||||
ret.checkAndPush(hex.cloneInDirection(dir, false));
|
ret.checkAndPush(hex.cloneInDirection(dir, false));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray BattleHexArray::generateAttackerClosestTilesCache()
|
const BattleHexArray & BattleHexArray::getNeighbouringTilesDblWide(BattleHex pos, BattleSide side)
|
||||||
|
{
|
||||||
|
static std::array<ArrayOfBattleHexArrays, 2> ret; // 2 -> only two valid sides: ATTACKER and DEFENDER
|
||||||
|
size_t sideIdx = static_cast<size_t>(side);
|
||||||
|
static bool initialized[2] = { false, false };
|
||||||
|
|
||||||
|
if(!initialized[sideIdx])
|
||||||
|
{
|
||||||
|
// first run, need to initialize
|
||||||
|
|
||||||
|
for(BattleHex hex = 0; hex < GameConstants::BFIELD_SIZE; hex.hex++)
|
||||||
|
{
|
||||||
|
BattleHexArray hexes;
|
||||||
|
|
||||||
|
if(side == BattleSide::ATTACKER)
|
||||||
|
{
|
||||||
|
const BattleHex otherHex = hex - 1;
|
||||||
|
|
||||||
|
for(auto dir = static_cast<BattleHex::EDir>(0); dir <= static_cast<BattleHex::EDir>(4); dir = static_cast<BattleHex::EDir>(dir + 1))
|
||||||
|
hexes.checkAndPush(hex.cloneInDirection(dir, false));
|
||||||
|
|
||||||
|
hexes.checkAndPush(otherHex.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false));
|
||||||
|
hexes.checkAndPush(otherHex.cloneInDirection(BattleHex::EDir::LEFT, false));
|
||||||
|
hexes.checkAndPush(otherHex.cloneInDirection(BattleHex::EDir::TOP_LEFT, false));
|
||||||
|
}
|
||||||
|
else if(side == BattleSide::DEFENDER)
|
||||||
|
{
|
||||||
|
const BattleHex otherHex = hex + 1;
|
||||||
|
|
||||||
|
hexes.checkAndPush(hex.cloneInDirection(BattleHex::EDir::TOP_LEFT, false));
|
||||||
|
|
||||||
|
for(auto dir = static_cast<BattleHex::EDir>(0); dir <= static_cast<BattleHex::EDir>(4); dir = static_cast<BattleHex::EDir>(dir + 1))
|
||||||
|
hexes.checkAndPush(otherHex.cloneInDirection(dir, false));
|
||||||
|
|
||||||
|
hexes.checkAndPush(hex.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false));
|
||||||
|
hexes.checkAndPush(hex.cloneInDirection(BattleHex::EDir::LEFT, false));
|
||||||
|
}
|
||||||
|
ret[sideIdx][hex.hex] = std::move(hexes);
|
||||||
|
}
|
||||||
|
initialized[sideIdx] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret[sideIdx][pos.hex];
|
||||||
|
}
|
||||||
|
|
||||||
|
const BattleHexArray & BattleHexArray::getClosestTilesCache(BattleHex pos, BattleSide side)
|
||||||
{
|
{
|
||||||
assert(!neighbouringTilesCache.empty());
|
assert(!neighbouringTilesCache.empty());
|
||||||
|
|
||||||
BattleHexArray ret;
|
static std::array<BattleHexArray, 2> ret;
|
||||||
|
static bool initialized = false;
|
||||||
|
size_t sideIdx = static_cast<size_t>(side);
|
||||||
|
|
||||||
ret.resize(GameConstants::BFIELD_SIZE);
|
if(!initialized)
|
||||||
|
|
||||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
|
||||||
{
|
{
|
||||||
ret.set(hex, neighbouringTilesCache[hex].getClosestTile(BattleSide::ATTACKER, hex));
|
ret[sideIdx].resize(GameConstants::BFIELD_SIZE);
|
||||||
|
|
||||||
|
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||||
|
{
|
||||||
|
ret[sideIdx].set(hex, neighbouringTilesCache[hex].getClosestTile(BattleSide::ATTACKER, hex));
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret[sideIdx];
|
||||||
}
|
|
||||||
|
|
||||||
BattleHexArray BattleHexArray::generateDefenderClosestTilesCache()
|
|
||||||
{
|
|
||||||
assert(!neighbouringTilesCache.empty());
|
|
||||||
|
|
||||||
BattleHexArray ret;
|
|
||||||
|
|
||||||
ret.resize(GameConstants::BFIELD_SIZE);
|
|
||||||
|
|
||||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
|
||||||
{
|
|
||||||
ret.set(hex, neighbouringTilesCache[hex].getClosestTile(BattleSide::DEFENDER, hex));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
BattleHex BattleHexArray::getClosestTileFromAllPossibleNeighbours(BattleSide side, BattleHex pos)
|
|
||||||
{
|
|
||||||
if(side == BattleSide::ATTACKER)
|
|
||||||
return closestTilesCacheForAttacker[pos.hex];
|
|
||||||
else if(side == BattleSide::DEFENDER)
|
|
||||||
return closestTilesCacheForDefender[pos.hex];
|
|
||||||
else
|
|
||||||
assert(false); // we should never be here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleHexArray::merge(const BattleHexArray & other) noexcept
|
void BattleHexArray::merge(const BattleHexArray & other) noexcept
|
||||||
@ -182,9 +176,6 @@ void BattleHexArray::clear() noexcept
|
|||||||
internalStorage.clear();
|
internalStorage.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const BattleHexArray::NeighbouringTilesCache BattleHexArray::neighbouringTilesCache = calculateNeighbouringTiles();
|
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::neighbouringTilesCache = calculateNeighbouringTiles();
|
||||||
|
|
||||||
const BattleHexArray BattleHexArray::closestTilesCacheForAttacker = generateAttackerClosestTilesCache();
|
|
||||||
const BattleHexArray BattleHexArray::closestTilesCacheForDefender = generateDefenderClosestTilesCache();
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
@ -33,11 +33,9 @@ public:
|
|||||||
using reverse_iterator = typename StorageType::reverse_iterator;
|
using reverse_iterator = typename StorageType::reverse_iterator;
|
||||||
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
||||||
|
|
||||||
using NeighbouringTilesCache = std::array<BattleHexArray, GameConstants::BFIELD_SIZE>;
|
using ArrayOfBattleHexArrays = std::array<BattleHexArray, GameConstants::BFIELD_SIZE>;
|
||||||
|
|
||||||
static const NeighbouringTilesCache neighbouringTilesCache;
|
static const ArrayOfBattleHexArrays neighbouringTilesCache;
|
||||||
static const BattleHexArray closestTilesCacheForAttacker;
|
|
||||||
static const BattleHexArray closestTilesCacheForDefender;
|
|
||||||
|
|
||||||
BattleHexArray() noexcept
|
BattleHexArray() noexcept
|
||||||
{
|
{
|
||||||
@ -130,7 +128,8 @@ public:
|
|||||||
return internalStorage.insert(pos, hex);
|
return internalStorage.insert(pos, hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BattleHex getClosestTileFromAllPossibleNeighbours(BattleSide side, BattleHex pos);
|
static const BattleHexArray & getClosestTilesCache(BattleHex pos, BattleSide side);
|
||||||
|
static const BattleHexArray & getNeighbouringTilesDblWide(BattleHex pos, BattleSide side);
|
||||||
|
|
||||||
BattleHex getClosestTile(BattleSide side, BattleHex initialPos) const;
|
BattleHex getClosestTile(BattleSide side, BattleHex initialPos) const;
|
||||||
|
|
||||||
@ -190,7 +189,7 @@ public:
|
|||||||
logGlobal->warn("BattleHexArray::contains( %d ) - invalid BattleHex!", hex);
|
logGlobal->warn("BattleHexArray::contains( %d ) - invalid BattleHex!", hex);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// return true for invalid hexes
|
// returns true also for invalid hexes
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,10 +297,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// returns all valid neighbouring tiles
|
/// returns all valid neighbouring tiles
|
||||||
static BattleHexArray::NeighbouringTilesCache calculateNeighbouringTiles();
|
static BattleHexArray::ArrayOfBattleHexArrays calculateNeighbouringTiles();
|
||||||
static BattleHexArray generateNeighbouringTiles(BattleHex hex);
|
static BattleHexArray generateNeighbouringTiles(BattleHex hex);
|
||||||
static BattleHexArray generateAttackerClosestTilesCache();
|
|
||||||
static BattleHexArray generateDefenderClosestTilesCache();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -651,7 +651,7 @@ BattleHexArray CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit *
|
|||||||
if(!otherSt->isValidTarget(false))
|
if(!otherSt->isValidTarget(false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BattleHexArray occupied = otherSt->getHexes();
|
const BattleHexArray & occupied = otherSt->getHexes();
|
||||||
|
|
||||||
if(battleCanShoot(unit, otherSt->getPosition()))
|
if(battleCanShoot(unit, otherSt->getPosition()))
|
||||||
{
|
{
|
||||||
@ -964,9 +964,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
|
|||||||
|
|
||||||
if(bFieldType != BattleField::NONE)
|
if(bFieldType != BattleField::NONE)
|
||||||
{
|
{
|
||||||
BattleHexArray impassableHexes = bFieldType.getInfo()->impassableHexes;
|
for(auto hex : bFieldType.getInfo()->impassableHexes)
|
||||||
|
|
||||||
for(auto hex : impassableHexes)
|
|
||||||
ret[hex] = EAccessibility::UNAVAILABLE;
|
ret[hex] = EAccessibility::UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,20 +1029,20 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
|
|||||||
|
|
||||||
AccessibilityInfo CBattleInfoCallback::getAccessibility(const battle::Unit * stack) const
|
AccessibilityInfo CBattleInfoCallback::getAccessibility(const battle::Unit * stack) const
|
||||||
{
|
{
|
||||||
return getAccessibility(battle::Unit::getHexes(stack->getPosition(), stack->doubleWide(), stack->unitSide()));
|
return getAccessibility(& battle::Unit::getHexes(stack->getPosition(), stack->doubleWide(), stack->unitSide()));
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessibilityInfo CBattleInfoCallback::getAccessibility(const BattleHexArray & accessibleHexes) const
|
AccessibilityInfo CBattleInfoCallback::getAccessibility(const BattleHexArray * accessibleHexes) const
|
||||||
{
|
{
|
||||||
auto ret = getAccessibility();
|
auto ret = getAccessibility();
|
||||||
for(auto hex : accessibleHexes)
|
for(auto hex : *accessibleHexes)
|
||||||
if(hex.isValid())
|
if(hex.isValid())
|
||||||
ret[hex] = EAccessibility::ACCESSIBLE;
|
ret[hex] = EAccessibility::ACCESSIBLE;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo &accessibility, const ReachabilityInfo::Parameters & params) const
|
ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessibility, const ReachabilityInfo::Parameters & params) const
|
||||||
{
|
{
|
||||||
ReachabilityInfo ret;
|
ReachabilityInfo ret;
|
||||||
ret.accessibility = accessibility;
|
ret.accessibility = accessibility;
|
||||||
@ -1114,11 +1112,11 @@ bool CBattleInfoCallback::isInObstacle(
|
|||||||
const BattleHexArray & obstacleHexes,
|
const BattleHexArray & obstacleHexes,
|
||||||
const ReachabilityInfo::Parameters & params) const
|
const ReachabilityInfo::Parameters & params) const
|
||||||
{
|
{
|
||||||
auto occupiedHexes = battle::Unit::getHexes(hex, params.doubleWide, params.side);
|
const BattleHexArray & occupiedHexes = battle::Unit::getHexes(hex, params.doubleWide, params.side);
|
||||||
|
|
||||||
for(auto occupiedHex : occupiedHexes)
|
for(auto occupiedHex : occupiedHexes)
|
||||||
{
|
{
|
||||||
if(params.ignoreKnownAccessible && params.knownAccessible.contains(occupiedHex))
|
if(params.ignoreKnownAccessible && params.knownAccessible->contains(occupiedHex))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(obstacleHexes.contains(occupiedHex))
|
if(obstacleHexes.contains(occupiedHex))
|
||||||
@ -1146,7 +1144,7 @@ BattleHexArray CBattleInfoCallback::getStoppers(BattleSide whichSidePerspective)
|
|||||||
if(!battleIsObstacleVisibleForSide(*oi, whichSidePerspective))
|
if(!battleIsObstacleVisibleForSide(*oi, whichSidePerspective))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(const auto & hex : oi->getStoppingTile())
|
for(auto hex : oi->getStoppingTile())
|
||||||
{
|
{
|
||||||
if(hex == BattleHex::GATE_BRIDGE && oi->obstacleType == CObstacleInstance::MOAT)
|
if(hex == BattleHex::GATE_BRIDGE && oi->obstacleType == CObstacleInstance::MOAT)
|
||||||
{
|
{
|
||||||
@ -1162,7 +1160,6 @@ BattleHexArray CBattleInfoCallback::getStoppers(BattleSide whichSidePerspective)
|
|||||||
std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(const battle::Unit * closest) const
|
std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(const battle::Unit * closest) const
|
||||||
{
|
{
|
||||||
auto reachability = getReachability(closest);
|
auto reachability = getReachability(closest);
|
||||||
auto avHexes = battleGetAvailableHexes(reachability, closest, false);
|
|
||||||
|
|
||||||
// I hate std::pairs with their undescriptive member names first / second
|
// I hate std::pairs with their undescriptive member names first / second
|
||||||
struct DistStack
|
struct DistStack
|
||||||
@ -1181,7 +1178,7 @@ std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(
|
|||||||
|
|
||||||
for(const battle::Unit * st : possible)
|
for(const battle::Unit * st : possible)
|
||||||
{
|
{
|
||||||
for(BattleHex hex : avHexes)
|
for(BattleHex hex : battleGetAvailableHexes(reachability, closest, false))
|
||||||
if(CStack::isMeleeAttackPossible(closest, st, hex))
|
if(CStack::isMeleeAttackPossible(closest, st, hex))
|
||||||
{
|
{
|
||||||
DistStack hlp = {reachability.distances[hex], hex, st};
|
DistStack hlp = {reachability.distances[hex], hex, st};
|
||||||
@ -1269,7 +1266,7 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const battle::Unit * unit)
|
|||||||
return getReachability(params);
|
return getReachability(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Parameters ¶ms) const
|
ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Parameters & params) const
|
||||||
{
|
{
|
||||||
if(params.flying)
|
if(params.flying)
|
||||||
return getFlyingReachability(params);
|
return getFlyingReachability(params);
|
||||||
@ -1283,7 +1280,7 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Pa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityInfo::Parameters ¶ms) const
|
ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityInfo::Parameters & params) const
|
||||||
{
|
{
|
||||||
ReachabilityInfo ret;
|
ReachabilityInfo ret;
|
||||||
ret.accessibility = getAccessibility(params.knownAccessible);
|
ret.accessibility = getAccessibility(params.knownAccessible);
|
||||||
@ -1340,11 +1337,11 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
|
|||||||
}
|
}
|
||||||
if(attacker->hasBonusOfType(BonusType::ATTACKS_ALL_ADJACENT))
|
if(attacker->hasBonusOfType(BonusType::ATTACKS_ALL_ADJACENT))
|
||||||
{
|
{
|
||||||
boost::copy(attacker->getSurroundingHexes(attackerPos), vstd::set_inserter(at.hostileCreaturePositions));
|
at.hostileCreaturePositions.merge(attacker->getSurroundingHexes(attackerPos));
|
||||||
}
|
}
|
||||||
if(attacker->hasBonusOfType(BonusType::THREE_HEADED_ATTACK))
|
if(attacker->hasBonusOfType(BonusType::THREE_HEADED_ATTACK))
|
||||||
{
|
{
|
||||||
BattleHexArray hexes = attacker->getSurroundingHexes(attackerPos);
|
const BattleHexArray & hexes = attacker->getSurroundingHexes(attackerPos);
|
||||||
for(BattleHex tile : hexes)
|
for(BattleHex tile : hexes)
|
||||||
{
|
{
|
||||||
if((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, attackOriginHex) > -1)) //adjacent both to attacker's head and attacked tile
|
if((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, attackOriginHex) > -1)) //adjacent both to attacker's head and attacked tile
|
||||||
@ -1432,9 +1429,8 @@ AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::
|
|||||||
|
|
||||||
if(attacker->hasBonusOfType(BonusType::SHOOTS_ALL_ADJACENT) && !BattleHexArray::neighbouringTilesCache[attackerPos].contains(destinationTile))
|
if(attacker->hasBonusOfType(BonusType::SHOOTS_ALL_ADJACENT) && !BattleHexArray::neighbouringTilesCache[attackerPos].contains(destinationTile))
|
||||||
{
|
{
|
||||||
auto targetHexes = BattleHexArray::neighbouringTilesCache[destinationTile];
|
at.hostileCreaturePositions.merge(BattleHexArray::neighbouringTilesCache[destinationTile]);
|
||||||
targetHexes.insert(destinationTile);
|
at.hostileCreaturePositions.insert(destinationTile);
|
||||||
boost::copy(targetHexes, vstd::set_inserter(at.hostileCreaturePositions));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return at;
|
return at;
|
||||||
|
@ -162,7 +162,7 @@ public:
|
|||||||
ReachabilityInfo getReachability(const ReachabilityInfo::Parameters & params) const;
|
ReachabilityInfo getReachability(const ReachabilityInfo::Parameters & params) const;
|
||||||
AccessibilityInfo getAccessibility() const;
|
AccessibilityInfo getAccessibility() const;
|
||||||
AccessibilityInfo getAccessibility(const battle::Unit * stack) const; //Hexes occupied by stack will be marked as accessible.
|
AccessibilityInfo getAccessibility(const battle::Unit * stack) const; //Hexes occupied by stack will be marked as accessible.
|
||||||
AccessibilityInfo getAccessibility(const BattleHexArray & accessibleHexes) const; //given hexes will be marked as accessible
|
AccessibilityInfo getAccessibility(const BattleHexArray * accessibleHexes) const; //given hexes will be marked as accessible
|
||||||
std::pair<const battle::Unit *, BattleHex> getNearestStack(const battle::Unit * closest) const;
|
std::pair<const battle::Unit *, BattleHex> getNearestStack(const battle::Unit * closest) const;
|
||||||
|
|
||||||
BattleHex getAvailableHex(const CreatureID & creID, BattleSide side, int initialPos = -1) const; //find place for adding new stack
|
BattleHex getAvailableHex(const CreatureID & creID, BattleSide side, int initialPos = -1) const; //find place for adding new stack
|
||||||
|
@ -21,7 +21,7 @@ ReachabilityInfo::Parameters::Parameters(const battle::Unit * Stack, BattleHex S
|
|||||||
side(Stack->unitSide()),
|
side(Stack->unitSide()),
|
||||||
flying(Stack->hasBonusOfType(BonusType::FLYING))
|
flying(Stack->hasBonusOfType(BonusType::FLYING))
|
||||||
{
|
{
|
||||||
knownAccessible = battle::Unit::getHexes(startPosition, doubleWide, side);
|
knownAccessible = & battle::Unit::getHexes(startPosition, doubleWide, side);
|
||||||
destructibleEnemyTurns.fill(-1);
|
destructibleEnemyTurns.fill(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ struct DLL_LINKAGE ReachabilityInfo
|
|||||||
bool flying = false;
|
bool flying = false;
|
||||||
bool ignoreKnownAccessible = false; //Ignore obstacles if it is in accessible hexes
|
bool ignoreKnownAccessible = false; //Ignore obstacles if it is in accessible hexes
|
||||||
bool bypassEnemyStacks = false; // in case of true will count amount of turns needed to kill enemy and thus move forward
|
bool bypassEnemyStacks = false; // in case of true will count amount of turns needed to kill enemy and thus move forward
|
||||||
BattleHexArray knownAccessible; //hexes that will be treated as accessible, even if they're occupied by stack (by default - tiles occupied by stack we do reachability for, so it doesn't block itself)
|
const BattleHexArray * knownAccessible; //hexes that will be treated as accessible, even if they're occupied by stack (by default - tiles occupied by stack we do reachability for, so it doesn't block itself)
|
||||||
std::array<int8_t, GameConstants::BFIELD_SIZE> destructibleEnemyTurns; // how many turns it is needed to kill enemy on specific hex (index <=> hex)
|
std::array<int8_t, GameConstants::BFIELD_SIZE> destructibleEnemyTurns; // how many turns it is needed to kill enemy on specific hex (index <=> hex)
|
||||||
|
|
||||||
BattleHex startPosition; //assumed position of stack
|
BattleHex startPosition; //assumed position of stack
|
||||||
|
@ -51,53 +51,26 @@ const IBonusBearer* Unit::getBonusBearer() const
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getSurroundingHexes(BattleHex assumedPosition) const
|
const BattleHexArray & Unit::getSurroundingHexes(BattleHex assumedPosition) const
|
||||||
{
|
{
|
||||||
BattleHex hex = (assumedPosition != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
|
BattleHex hex = (assumedPosition != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
|
||||||
|
|
||||||
return getSurroundingHexes(hex, doubleWide(), unitSide());
|
return getSurroundingHexes(hex, doubleWide(), unitSide());
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side)
|
const BattleHexArray & Unit::getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side)
|
||||||
{
|
{
|
||||||
if(!position.isValid())
|
assert(position.isValid()); // check outside if position isValid
|
||||||
return { };
|
|
||||||
|
if(!twoHex)
|
||||||
BattleHexArray hexes;
|
|
||||||
if(twoHex)
|
|
||||||
{
|
|
||||||
const BattleHex otherHex = occupiedHex(position, twoHex, side);
|
|
||||||
|
|
||||||
if(side == BattleSide::ATTACKER)
|
|
||||||
{
|
|
||||||
for(auto dir = static_cast<BattleHex::EDir>(0); dir <= static_cast<BattleHex::EDir>(4); dir = static_cast<BattleHex::EDir>(dir + 1))
|
|
||||||
hexes.checkAndPush(position.cloneInDirection(dir, false));
|
|
||||||
|
|
||||||
hexes.checkAndPush(otherHex.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false));
|
|
||||||
hexes.checkAndPush(otherHex.cloneInDirection(BattleHex::EDir::LEFT, false));
|
|
||||||
hexes.checkAndPush(otherHex.cloneInDirection(BattleHex::EDir::TOP_LEFT, false));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hexes.checkAndPush(position.cloneInDirection(BattleHex::EDir::TOP_LEFT, false));
|
|
||||||
|
|
||||||
for(auto dir = static_cast<BattleHex::EDir>(0); dir <= static_cast<BattleHex::EDir>(4); dir = static_cast<BattleHex::EDir>(dir + 1))
|
|
||||||
hexes.checkAndPush(otherHex.cloneInDirection(dir, false));
|
|
||||||
|
|
||||||
hexes.checkAndPush(position.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false));
|
|
||||||
hexes.checkAndPush(position.cloneInDirection(BattleHex::EDir::LEFT, false));
|
|
||||||
}
|
|
||||||
return hexes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return BattleHexArray::neighbouringTilesCache[position];
|
return BattleHexArray::neighbouringTilesCache[position];
|
||||||
}
|
|
||||||
|
return BattleHexArray::getNeighbouringTilesDblWide(position, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
||||||
{
|
{
|
||||||
auto defenderHexes = battle::Unit::getHexes(
|
const BattleHexArray & defenderHexes = battle::Unit::getHexes(
|
||||||
getPosition(),
|
getPosition(),
|
||||||
doubleWide(),
|
doubleWide(),
|
||||||
unitSide());
|
unitSide());
|
||||||
@ -126,25 +99,35 @@ bool Unit::coversPos(BattleHex pos) const
|
|||||||
return getPosition() == pos || (doubleWide() && (occupiedHex() == pos));
|
return getPosition() == pos || (doubleWide() && (occupiedHex() == pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getHexes() const
|
const BattleHexArray & Unit::getHexes() const
|
||||||
{
|
{
|
||||||
return getHexes(getPosition(), doubleWide(), unitSide());
|
return getHexes(getPosition(), doubleWide(), unitSide());
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getHexes(BattleHex assumedPos) const
|
const BattleHexArray & Unit::getHexes(BattleHex assumedPos) const
|
||||||
{
|
{
|
||||||
return getHexes(assumedPos, doubleWide(), unitSide());
|
return getHexes(assumedPos, doubleWide(), unitSide());
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleSide side)
|
const BattleHexArray & Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleSide side)
|
||||||
{
|
{
|
||||||
|
static BattleHexArray::ArrayOfBattleHexArrays cache[4];
|
||||||
|
int index = side == BattleSide::ATTACKER ? 0 : 2;
|
||||||
|
|
||||||
|
if(!cache[index + twoHex][assumedPos].empty())
|
||||||
|
return cache[index + twoHex][assumedPos];
|
||||||
|
|
||||||
|
// first run, initialize
|
||||||
|
|
||||||
BattleHexArray hexes;
|
BattleHexArray hexes;
|
||||||
hexes.insert(assumedPos);
|
hexes.insert(assumedPos);
|
||||||
|
|
||||||
if(twoHex)
|
if(twoHex)
|
||||||
hexes.insert(occupiedHex(assumedPos, twoHex, side));
|
hexes.insert(occupiedHex(assumedPos, twoHex, side));
|
||||||
|
|
||||||
return hexes;
|
cache[index + twoHex][assumedPos] = std::move(hexes);
|
||||||
|
|
||||||
|
return cache[index + twoHex][assumedPos];
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHex Unit::occupiedHex() const
|
BattleHex Unit::occupiedHex() const
|
||||||
|
@ -127,15 +127,15 @@ public:
|
|||||||
|
|
||||||
virtual std::string getDescription() const;
|
virtual std::string getDescription() const;
|
||||||
|
|
||||||
BattleHexArray getSurroundingHexes(BattleHex assumedPosition = BattleHex::INVALID) const; // get six or 8 surrounding hexes depending on creature size
|
const BattleHexArray & getSurroundingHexes(BattleHex assumedPosition = BattleHex::INVALID) const; // get six or 8 surrounding hexes depending on creature size
|
||||||
BattleHexArray getAttackableHexes(const Unit * attacker) const;
|
BattleHexArray getAttackableHexes(const Unit * attacker) const;
|
||||||
static BattleHexArray getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side);
|
static const BattleHexArray & getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side);
|
||||||
|
|
||||||
bool coversPos(BattleHex position) const; //checks also if unit is double-wide
|
bool coversPos(BattleHex position) const; //checks also if unit is double-wide
|
||||||
|
|
||||||
BattleHexArray getHexes() const; //up to two occupied hexes, starting from front
|
const BattleHexArray & getHexes() const; //up to two occupied hexes, starting from front
|
||||||
BattleHexArray getHexes(BattleHex assumedPos) const; //up to two occupied hexes, starting from front
|
const BattleHexArray & getHexes(BattleHex assumedPos) const; //up to two occupied hexes, starting from front
|
||||||
static BattleHexArray getHexes(BattleHex assumedPos, bool twoHex, BattleSide side);
|
static const BattleHexArray & getHexes(BattleHex assumedPos, bool twoHex, BattleSide side);
|
||||||
|
|
||||||
BattleHex occupiedHex() const; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1
|
BattleHex occupiedHex() const; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1
|
||||||
BattleHex occupiedHex(BattleHex assumedPos) const; //returns number of occupied hex (not the position) if stack is double wide and would stand on assumedPos; otherwise -1
|
BattleHex occupiedHex(BattleHex assumedPos) const; //returns number of occupied hex (not the position) if stack is double wide and would stand on assumedPos; otherwise -1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user