mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Refactor BattleHex, remake the use of precomputed neighbouring tiles containers.
- Moved short, frequently used functions to the BattleHex header for inlining - Made BattleHex a class with a private hex value - Moved getClosestTile implementation back to BattleHex - Enabled access to static precomputed data in BattleHexArray via BattleHex (note: circular dependency prevented static precomputed containers being directly placed in BattleHex)
This commit is contained in:
parent
ac8104d56d
commit
dad6437661
AI
client/battle
BattleFieldController.cppBattleInterface.hBattleObstacleController.hBattleSiegeController.cppBattleStacksController.h
lib
battle
AccessibilityInfo.cppBattleHex.cppBattleHex.hBattleHexArray.cppBattleHexArray.hBattleInfo.cppCBattleInfoCallback.cppDestination.hReachabilityInfo.cppUnit.cpp
networkPacks
spells
server/battles
@ -384,7 +384,7 @@ AttackPossibility AttackPossibility::evaluate(
|
||||
affectedUnits = defenderUnits;
|
||||
vstd::concatenate(affectedUnits, retaliatedUnits);
|
||||
|
||||
logAi->trace("Attacked battle units count %d, %d->%d", affectedUnits.size(), hex.hex, defHex.hex);
|
||||
logAi->trace("Attacked battle units count %d, %d->%d", affectedUnits.size(), hex, defHex);
|
||||
|
||||
std::map<uint32_t, std::shared_ptr<battle::CUnitState>> defenderStates;
|
||||
|
||||
|
@ -215,7 +215,7 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
||||
bestAttack.affectedUnits[0]->unitType()->getJsonKey(),
|
||||
bestAttack.affectedUnits[0]->getCount(),
|
||||
(int)bestAttack.from,
|
||||
(int)bestAttack.attack.attacker->getPosition().hex,
|
||||
(int)bestAttack.attack.attacker->getPosition(),
|
||||
bestAttack.attack.chargeDistance,
|
||||
bestAttack.attack.attacker->getMovementRange(0),
|
||||
bestAttack.defenderDamageReduce,
|
||||
@ -252,7 +252,7 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
||||
|
||||
if(siegeDefense)
|
||||
{
|
||||
logAi->trace("Evaluating exchange at %d self-defense", stack->getPosition().hex);
|
||||
logAi->trace("Evaluating exchange at %d self-defense", stack->getPosition());
|
||||
|
||||
BattleAttackInfo bai(stack, stack, 0, false);
|
||||
AttackPossibility apDefend(stack->getPosition(), stack->getPosition(), bai);
|
||||
@ -286,7 +286,7 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
||||
"Moving %s towards hex %s[%d], score: %2f",
|
||||
stack->getDescription(),
|
||||
moveTarget.cachedAttack->attack.defender->getDescription(),
|
||||
moveTarget.cachedAttack->attack.defender->getPosition().hex,
|
||||
moveTarget.cachedAttack->attack.defender->getPosition(),
|
||||
moveTarget.score);
|
||||
|
||||
return goTowardsNearest(stack, moveTarget.positions, *targets);
|
||||
|
@ -960,7 +960,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getOneTurnReachableUn
|
||||
|
||||
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||
{
|
||||
for(BattleHex neighbour : BattleHexArray::neighbouringTilesCache[hex.hex])
|
||||
for(BattleHex neighbour : hex.getNeighbouringTiles())
|
||||
{
|
||||
reachable = unitReachability.distances.at(neighbour) <= radius;
|
||||
|
||||
@ -1021,7 +1021,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
|
||||
if(hexStack && cb->battleMatchOwner(unit, hexStack, false))
|
||||
{
|
||||
enemyUnit = true;
|
||||
for(BattleHex neighbour : BattleHexArray::neighbouringTilesCache[hex.hex])
|
||||
for(BattleHex neighbour : hex.getNeighbouringTiles())
|
||||
{
|
||||
reachable = unitReachability.distances.at(neighbour) <= unitSpeed;
|
||||
|
||||
|
@ -107,7 +107,8 @@ static bool willSecondHexBlockMoreEnemyShooters(std::shared_ptr<CBattleCallback>
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
for (auto neighbour : BattleHexArray::neighbouringTilesCache[i ? h2.hex : h1.hex])
|
||||
BattleHex hex = i ? h2 : h1;
|
||||
for (auto neighbour : hex.getNeighbouringTiles())
|
||||
if(const auto * s = cb->getBattle(battleID)->battleGetUnitByPos(neighbour))
|
||||
if(s->isShooter())
|
||||
shooters[i]++;
|
||||
|
@ -482,7 +482,7 @@ std::vector<std::vector<BattleHex::EDir>> BattleFieldController::getOutsideNeigh
|
||||
{
|
||||
// get all neighbours and their directions
|
||||
|
||||
const BattleHexArray & neighbouringTiles = BattleHexArray::getAllNeighbouringTiles(hex);
|
||||
const BattleHexArray & neighbouringTiles = hex.getAllNeighbouringTiles();
|
||||
|
||||
std::vector<BattleHex::EDir> outsideNeighbourDirections;
|
||||
|
||||
@ -492,9 +492,7 @@ std::vector<std::vector<BattleHex::EDir>> BattleFieldController::getOutsideNeigh
|
||||
if(!neighbouringTiles[direction].isAvailable())
|
||||
continue;
|
||||
|
||||
auto it = std::find(wholeRangeHexes.begin(), wholeRangeHexes.end(), neighbouringTiles[direction]);
|
||||
|
||||
if(it == wholeRangeHexes.end())
|
||||
if(!wholeRangeHexes.contains(neighbouringTiles[direction]))
|
||||
outsideNeighbourDirections.push_back(BattleHex::EDir(direction)); // push direction
|
||||
}
|
||||
|
||||
@ -680,7 +678,7 @@ BattleHex BattleFieldController::getHexAtPosition(Point hoverPos)
|
||||
BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber)
|
||||
{
|
||||
const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
|
||||
const BattleHexArray & neighbours = BattleHexArray::getAllNeighbouringTiles(myNumber);
|
||||
const BattleHexArray & neighbours = myNumber.getAllNeighbouringTiles();
|
||||
// 0 1
|
||||
// 5 x 2
|
||||
// 4 3
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BattleConstants.h"
|
||||
#include "../lib/battle/BattleHex.h"
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../../lib/spells/CSpellHandler.h" //CSpell::TAnimation
|
||||
#include "../ConditionalWait.h"
|
||||
@ -27,7 +28,6 @@ class BattleAction;
|
||||
class CGTownInstance;
|
||||
struct CatapultAttack;
|
||||
struct BattleTriggerEffect;
|
||||
struct BattleHex;
|
||||
struct InfoAboutHero;
|
||||
class ObstacleChanges;
|
||||
class CPlayerBattleCallback;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct BattleHex;
|
||||
class BattleHex;
|
||||
struct CObstacleInstance;
|
||||
class JsonNode;
|
||||
class ObstacleChanges;
|
||||
|
@ -195,7 +195,7 @@ const CCreature *BattleSiegeController::getTurretCreature(BattleHex position) co
|
||||
return town->fortificationsLevel().lowerTowerShooter.toCreature();
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unable to select shooter for tower at " + std::to_string(position.hex));
|
||||
throw std::runtime_error("Unable to select shooter for tower at " + std::to_string(position));
|
||||
}
|
||||
|
||||
Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) const
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct BattleHex;
|
||||
class BattleHex;
|
||||
class BattleHexArray;
|
||||
class BattleAction;
|
||||
class CStack;
|
||||
|
@ -25,7 +25,7 @@ bool AccessibilityInfo::tileAccessibleWithGate(BattleHex tile, BattleSide side)
|
||||
if(!destructibleEnemyTurns)
|
||||
return false;
|
||||
|
||||
return destructibleEnemyTurns->at(tile.hex) >= 0;
|
||||
return destructibleEnemyTurns->at(tile) >= 0;
|
||||
}
|
||||
|
||||
if(accessibility != EAccessibility::ACCESSIBLE)
|
||||
|
@ -9,130 +9,63 @@
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "BattleHex.h"
|
||||
#include "BattleHexArray.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
BattleHex::BattleHex() : hex(INVALID) {}
|
||||
|
||||
BattleHex::BattleHex(si16 _hex) : hex(_hex) {}
|
||||
|
||||
BattleHex::BattleHex(si16 x, si16 y)
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
BattleHex BattleHex::getClosestTile(const BattleHexArray & hexes, BattleSide side, BattleHex initialPos)
|
||||
{
|
||||
setXY(x, y);
|
||||
}
|
||||
if(hexes.empty())
|
||||
return BattleHex();
|
||||
|
||||
BattleHex::BattleHex(std::pair<si16, si16> xy)
|
||||
{
|
||||
setXY(xy);
|
||||
}
|
||||
BattleHex initialHex = BattleHex(initialPos);
|
||||
int closestDistance = std::numeric_limits<int>::max();
|
||||
BattleHexArray closestTiles;
|
||||
|
||||
BattleHex::operator si16() const
|
||||
{
|
||||
return hex;
|
||||
}
|
||||
|
||||
void BattleHex::setX(si16 x)
|
||||
{
|
||||
setXY(x, getY());
|
||||
}
|
||||
|
||||
void BattleHex::setY(si16 y)
|
||||
{
|
||||
setXY(getX(), y);
|
||||
}
|
||||
|
||||
void BattleHex::setXY(si16 x, si16 y, bool hasToBeValid)
|
||||
{
|
||||
if(hasToBeValid)
|
||||
for(auto hex : hexes)
|
||||
{
|
||||
if(x < 0 || x >= GameConstants::BFIELD_WIDTH || y < 0 || y >= GameConstants::BFIELD_HEIGHT)
|
||||
throw std::runtime_error("Valid hex required");
|
||||
int distance = initialHex.getDistance(initialHex, hex);
|
||||
if(distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestTiles.clear();
|
||||
closestTiles.insert(hex);
|
||||
}
|
||||
else if(distance == closestDistance)
|
||||
closestTiles.insert(hex);
|
||||
}
|
||||
|
||||
hex = x + y * GameConstants::BFIELD_WIDTH;
|
||||
}
|
||||
|
||||
void BattleHex::setXY(std::pair<si16, si16> xy)
|
||||
{
|
||||
setXY(xy.first, xy.second);
|
||||
}
|
||||
|
||||
si16 BattleHex::getX() const
|
||||
{
|
||||
return hex % GameConstants::BFIELD_WIDTH;
|
||||
}
|
||||
|
||||
si16 BattleHex::getY() const
|
||||
{
|
||||
return hex / GameConstants::BFIELD_WIDTH;
|
||||
}
|
||||
|
||||
std::pair<si16, si16> BattleHex::getXY() const
|
||||
{
|
||||
return std::make_pair(getX(), getY());
|
||||
}
|
||||
|
||||
BattleHex & BattleHex::moveInDirection(EDir dir, bool hasToBeValid)
|
||||
{
|
||||
si16 x = getX();
|
||||
si16 y = getY();
|
||||
switch(dir)
|
||||
auto compareHorizontal = [side, initialPos](const BattleHex & left, const BattleHex & right)
|
||||
{
|
||||
case TOP_LEFT:
|
||||
setXY((y%2) ? x-1 : x, y-1, hasToBeValid);
|
||||
break;
|
||||
case TOP_RIGHT:
|
||||
setXY((y%2) ? x : x+1, y-1, hasToBeValid);
|
||||
break;
|
||||
case RIGHT:
|
||||
setXY(x+1, y, hasToBeValid);
|
||||
break;
|
||||
case BOTTOM_RIGHT:
|
||||
setXY((y%2) ? x : x+1, y+1, hasToBeValid);
|
||||
break;
|
||||
case BOTTOM_LEFT:
|
||||
setXY((y%2) ? x-1 : x, y+1, hasToBeValid);
|
||||
break;
|
||||
case LEFT:
|
||||
setXY(x-1, y, hasToBeValid);
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Disaster: wrong direction in BattleHex::operator+=!\n");
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
if(left.getX() != right.getX())
|
||||
{
|
||||
return (side == BattleSide::ATTACKER) ? (left.getX() > right.getX()) : (left.getX() < right.getX());
|
||||
}
|
||||
return std::abs(left.getY() - initialPos.getY()) < std::abs(right.getY() - initialPos.getY());
|
||||
};
|
||||
|
||||
auto bestTile = std::min_element(closestTiles.begin(), closestTiles.end(), compareHorizontal);
|
||||
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
|
||||
}
|
||||
|
||||
const BattleHexArray & BattleHex::getAllNeighbouringTiles() const
|
||||
{
|
||||
return BattleHexArray::getAllNeighbouringTiles(*this);
|
||||
}
|
||||
|
||||
BattleHex & BattleHex::operator+=(BattleHex::EDir dir)
|
||||
const BattleHexArray & BattleHex::getNeighbouringTiles() const
|
||||
{
|
||||
return moveInDirection(dir);
|
||||
return BattleHexArray::getNeighbouringTiles(*this);
|
||||
}
|
||||
|
||||
BattleHex BattleHex::cloneInDirection(BattleHex::EDir dir, bool hasToBeValid) const
|
||||
const BattleHexArray & BattleHex::getNeighbouringTilesDblWide(BattleSide side) const
|
||||
{
|
||||
BattleHex result(hex);
|
||||
result.moveInDirection(dir, hasToBeValid);
|
||||
return result;
|
||||
}
|
||||
|
||||
BattleHex BattleHex::operator+(BattleHex::EDir dir) const
|
||||
{
|
||||
return cloneInDirection(dir);
|
||||
}
|
||||
|
||||
BattleHex::EDir BattleHex::mutualPosition(BattleHex hex1, BattleHex hex2)
|
||||
{
|
||||
for(auto dir : hexagonalDirections())
|
||||
if(hex2 == hex1.cloneInDirection(dir, false))
|
||||
return dir;
|
||||
return NONE;
|
||||
}
|
||||
return BattleHexArray::getNeighbouringTilesDblWide(*this, side);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const BattleHex & hex)
|
||||
{
|
||||
return os << boost::str(boost::format("{BattleHex: x '%d', y '%d', hex '%d'}") % hex.getX() % hex.getY() % hex.hex);
|
||||
return os << boost::str(boost::format("{BattleHex: x '%d', y '%d', hex '%d'}") % hex.getX() % hex.getY() % static_cast<si16>(hex));
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -22,9 +22,13 @@ namespace GameConstants
|
||||
const int BFIELD_SIZE = BFIELD_WIDTH * BFIELD_HEIGHT;
|
||||
}
|
||||
|
||||
class BattleHexArray;
|
||||
|
||||
// for battle stacks' positions
|
||||
struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class for better code design
|
||||
class DLL_LINKAGE BattleHex
|
||||
{
|
||||
public:
|
||||
|
||||
// helpers for siege
|
||||
static constexpr si16 CASTLE_CENTRAL_TOWER = -2;
|
||||
static constexpr si16 CASTLE_BOTTOM_TOWER = -3;
|
||||
@ -46,8 +50,8 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
||||
static constexpr si16 GATE_OUTER = 95;
|
||||
static constexpr si16 GATE_INNER = 96;
|
||||
|
||||
si16 hex;
|
||||
static constexpr si16 INVALID = -1;
|
||||
|
||||
enum EDir
|
||||
{
|
||||
NONE = -1,
|
||||
@ -64,11 +68,25 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
BattleHex();
|
||||
BattleHex(si16 _hex);
|
||||
BattleHex(si16 x, si16 y);
|
||||
BattleHex(std::pair<si16, si16> xy);
|
||||
operator si16() const;
|
||||
BattleHex()
|
||||
: hex(INVALID)
|
||||
{}
|
||||
BattleHex(si16 _hex)
|
||||
: hex(_hex)
|
||||
{}
|
||||
BattleHex(si16 x, si16 y)
|
||||
{
|
||||
setXY(x, y);
|
||||
}
|
||||
BattleHex(std::pair<si16, si16> xy)
|
||||
{
|
||||
setXY(xy);
|
||||
}
|
||||
operator si16() const
|
||||
{
|
||||
return hex;
|
||||
}
|
||||
|
||||
inline bool isValid() const
|
||||
{
|
||||
return hex >= 0 && hex < GameConstants::BFIELD_SIZE;
|
||||
@ -79,19 +97,97 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
||||
return isValid() && getX() > 0 && getX() < GameConstants::BFIELD_WIDTH - 1;
|
||||
}
|
||||
|
||||
void setX(si16 x);
|
||||
void setY(si16 y);
|
||||
void setXY(si16 x, si16 y, bool hasToBeValid = true);
|
||||
void setXY(std::pair<si16, si16> xy);
|
||||
si16 getX() const;
|
||||
si16 getY() const;
|
||||
std::pair<si16, si16> getXY() const;
|
||||
BattleHex& moveInDirection(EDir dir, bool hasToBeValid = true);
|
||||
BattleHex& operator+=(EDir dir);
|
||||
BattleHex cloneInDirection(EDir dir, bool hasToBeValid = true) const;
|
||||
BattleHex operator+(EDir dir) const;
|
||||
void setX(si16 x)
|
||||
{
|
||||
setXY(x, getY());
|
||||
}
|
||||
|
||||
void setY(si16 y)
|
||||
{
|
||||
setXY(getX(), y);
|
||||
}
|
||||
|
||||
void setXY(si16 x, si16 y, bool hasToBeValid = true)
|
||||
{
|
||||
if(hasToBeValid)
|
||||
{
|
||||
if(x < 0 || x >= GameConstants::BFIELD_WIDTH || y < 0 || y >= GameConstants::BFIELD_HEIGHT)
|
||||
throw std::runtime_error("Valid hex required");
|
||||
}
|
||||
|
||||
hex = x + y * GameConstants::BFIELD_WIDTH;
|
||||
}
|
||||
|
||||
void setXY(std::pair<si16, si16> xy)
|
||||
{
|
||||
setXY(xy.first, xy.second);
|
||||
}
|
||||
|
||||
si16 getX() const
|
||||
{
|
||||
return hex % GameConstants::BFIELD_WIDTH;
|
||||
}
|
||||
|
||||
si16 getY() const
|
||||
{
|
||||
return hex / GameConstants::BFIELD_WIDTH;
|
||||
}
|
||||
|
||||
std::pair<si16, si16> getXY() const
|
||||
{
|
||||
return std::make_pair(getX(), getY());
|
||||
}
|
||||
|
||||
BattleHex & moveInDirection(EDir dir, bool hasToBeValid = true)
|
||||
{
|
||||
si16 x = getX();
|
||||
si16 y = getY();
|
||||
switch(dir)
|
||||
{
|
||||
case TOP_LEFT:
|
||||
setXY((y % 2) ? x - 1 : x, y - 1, hasToBeValid);
|
||||
break;
|
||||
case TOP_RIGHT:
|
||||
setXY((y % 2) ? x : x + 1, y - 1, hasToBeValid);
|
||||
break;
|
||||
case RIGHT:
|
||||
setXY(x + 1, y, hasToBeValid);
|
||||
break;
|
||||
case BOTTOM_RIGHT:
|
||||
setXY((y % 2) ? x : x + 1, y + 1, hasToBeValid);
|
||||
break;
|
||||
case BOTTOM_LEFT:
|
||||
setXY((y % 2) ? x - 1 : x, y + 1, hasToBeValid);
|
||||
break;
|
||||
case LEFT:
|
||||
setXY(x - 1, y, hasToBeValid);
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Disaster: wrong direction in BattleHex::operator+=!\n");
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
BattleHex & operator+=(EDir dir)
|
||||
{
|
||||
return moveInDirection(dir);
|
||||
}
|
||||
|
||||
BattleHex operator+(EDir dir) const
|
||||
{
|
||||
return cloneInDirection(dir);
|
||||
}
|
||||
|
||||
BattleHex cloneInDirection(EDir dir, bool hasToBeValid = true) const
|
||||
{
|
||||
BattleHex result(hex);
|
||||
result.moveInDirection(dir, hasToBeValid);
|
||||
return result;
|
||||
}
|
||||
|
||||
static EDir mutualPosition(BattleHex hex1, BattleHex hex2);
|
||||
static uint8_t getDistance(BattleHex hex1, BattleHex hex2)
|
||||
{
|
||||
int y1 = hex1.getY();
|
||||
@ -108,17 +204,41 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
||||
|
||||
return std::abs(xDst) + std::abs(yDst);
|
||||
}
|
||||
|
||||
|
||||
static BattleHex getClosestTile(const BattleHexArray & hexes, BattleSide side, BattleHex initialPos);
|
||||
|
||||
//Constexpr defined array with all directions used in battle
|
||||
static constexpr auto hexagonalDirections()
|
||||
{
|
||||
return std::array<EDir,6>{TOP_LEFT, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT};
|
||||
}
|
||||
|
||||
static EDir mutualPosition(BattleHex hex1, BattleHex hex2)
|
||||
{
|
||||
for(auto dir : hexagonalDirections())
|
||||
if(hex2 == hex1.cloneInDirection(dir, false))
|
||||
return dir;
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/// get (precomputed) all possible surrounding tiles
|
||||
const BattleHexArray & getAllNeighbouringTiles() const;
|
||||
|
||||
/// get (precomputed) only valid and available surrounding tiles
|
||||
const BattleHexArray & getNeighbouringTiles() const;
|
||||
|
||||
/// get (precomputed) only valid and available surrounding tiles for double wide creatures
|
||||
const BattleHexArray & getNeighbouringTilesDblWide(BattleSide side) const;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & hex;
|
||||
}
|
||||
|
||||
//Constexpr defined array with all directions used in battle
|
||||
static constexpr auto hexagonalDirections() {
|
||||
return std::array<EDir,6>{BattleHex::TOP_LEFT, BattleHex::TOP_RIGHT, BattleHex::RIGHT, BattleHex::BOTTOM_RIGHT, BattleHex::BOTTOM_LEFT, BattleHex::LEFT};
|
||||
}
|
||||
private:
|
||||
|
||||
si16 hex;
|
||||
};
|
||||
|
||||
DLL_EXPORT std::ostream & operator<<(std::ostream & os, const BattleHex & hex);
|
||||
|
@ -22,104 +22,6 @@ BattleHexArray::BattleHexArray(std::initializer_list<BattleHex> initList) noexce
|
||||
}
|
||||
}
|
||||
|
||||
BattleHex BattleHexArray::getClosestTile(BattleSide side, BattleHex initialPos) const
|
||||
{
|
||||
if(this->empty())
|
||||
return BattleHex();
|
||||
|
||||
BattleHex initialHex = BattleHex(initialPos);
|
||||
int closestDistance = std::numeric_limits<int>::max();
|
||||
BattleHexArray closestTiles;
|
||||
|
||||
for(auto hex : internalStorage)
|
||||
{
|
||||
int distance = initialHex.getDistance(initialHex, hex);
|
||||
if(distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestTiles.clear();
|
||||
closestTiles.insert(hex);
|
||||
}
|
||||
else if(distance == closestDistance)
|
||||
closestTiles.insert(hex);
|
||||
}
|
||||
|
||||
auto compareHorizontal = [side, initialPos](const BattleHex & left, const BattleHex & right)
|
||||
{
|
||||
if(left.getX() != right.getX())
|
||||
{
|
||||
return (side == BattleSide::ATTACKER) ? (left.getX() > right.getX()) : (left.getX() < right.getX());
|
||||
}
|
||||
return std::abs(left.getY() - initialPos.getY()) < std::abs(right.getY() - initialPos.getY());
|
||||
};
|
||||
|
||||
auto bestTile = std::min_element(closestTiles.begin(), closestTiles.end(), compareHorizontal);
|
||||
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
|
||||
}
|
||||
|
||||
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::calculateNeighbouringTiles()
|
||||
{
|
||||
BattleHexArray::ArrayOfBattleHexArrays ret;
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
BattleHexArray hexes = BattleHexArray::generateNeighbouringTiles(hex);
|
||||
|
||||
size_t index = 0;
|
||||
ret[hex].resize(hexes.size());
|
||||
for(auto neighbour : hexes)
|
||||
ret[hex].set(index++, neighbour);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::calculateNeighbouringTilesDblWide(BattleSide side)
|
||||
{
|
||||
ArrayOfBattleHexArrays ret;
|
||||
|
||||
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[hex.hex] = std::move(hexes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray BattleHexArray::generateNeighbouringTiles(BattleHex hex)
|
||||
{
|
||||
BattleHexArray ret;
|
||||
for(auto dir : BattleHex::hexagonalDirections())
|
||||
ret.checkAndPush(hex.cloneInDirection(dir, false));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BattleHexArray::insert(const BattleHexArray & other) noexcept
|
||||
{
|
||||
for(auto hex : other)
|
||||
@ -146,9 +48,85 @@ void BattleHexArray::clear() noexcept
|
||||
internalStorage.clear();
|
||||
}
|
||||
|
||||
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::neighbouringTilesCache = calculateNeighbouringTiles();
|
||||
const std::map<BattleSide, BattleHexArray::ArrayOfBattleHexArrays> BattleHexArray::neighbouringTilesDblWide =
|
||||
{ { BattleSide::ATTACKER, calculateNeighbouringTilesDblWide(BattleSide::ATTACKER) },
|
||||
{ BattleSide::DEFENDER, calculateNeighbouringTilesDblWide(BattleSide::DEFENDER) } };
|
||||
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringTiles()
|
||||
{
|
||||
BattleHexArray::ArrayOfBattleHexArrays ret;
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
BattleHexArray hexes;
|
||||
|
||||
for(auto dir : BattleHex::hexagonalDirections())
|
||||
hexes.checkAndPush(BattleHex(hex).cloneInDirection(dir, false));
|
||||
|
||||
size_t index = 0;
|
||||
ret[hex].resize(hexes.size());
|
||||
for(auto neighbour : hexes)
|
||||
ret[hex].set(index++, neighbour);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateAllNeighbouringTiles()
|
||||
{
|
||||
ArrayOfBattleHexArrays ret;
|
||||
|
||||
for(si16 hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||
{
|
||||
ret[hex].resize(6);
|
||||
|
||||
for(auto dir : BattleHex::hexagonalDirections())
|
||||
ret[hex].set(dir, BattleHex(hex).cloneInDirection(dir, false));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringTilesDblWide(BattleSide side)
|
||||
{
|
||||
ArrayOfBattleHexArrays ret;
|
||||
|
||||
for(si16 h = 0; h < GameConstants::BFIELD_SIZE; h++)
|
||||
{
|
||||
BattleHexArray hexes;
|
||||
BattleHex hex(h);
|
||||
|
||||
if(side == BattleSide::ATTACKER)
|
||||
{
|
||||
const BattleHex otherHex = h - 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 = h + 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[h] = std::move(hexes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::neighbouringTiles = precalculateNeighbouringTiles();
|
||||
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::allNeighbouringTiles = precalculateAllNeighbouringTiles();
|
||||
const std::map<BattleSide, BattleHexArray::ArrayOfBattleHexArrays> BattleHexArray::neighbouringTilesDblWide =
|
||||
{
|
||||
{ BattleSide::ATTACKER, precalculateNeighbouringTilesDblWide(BattleSide::ATTACKER) },
|
||||
{ BattleSide::DEFENDER, precalculateNeighbouringTilesDblWide(BattleSide::DEFENDER) }
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -21,6 +21,7 @@ class DLL_LINKAGE BattleHexArray
|
||||
public:
|
||||
static constexpr uint8_t totalSize = GameConstants::BFIELD_SIZE;
|
||||
using StorageType = boost::container::small_vector<BattleHex, 8>;
|
||||
using ArrayOfBattleHexArrays = std::array<BattleHexArray, totalSize>;
|
||||
|
||||
using value_type = BattleHex;
|
||||
using size_type = StorageType::size_type;
|
||||
@ -34,11 +35,6 @@ public:
|
||||
using reverse_iterator = typename StorageType::reverse_iterator;
|
||||
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
||||
|
||||
using ArrayOfBattleHexArrays = std::array<BattleHexArray, GameConstants::BFIELD_SIZE>;
|
||||
|
||||
static const ArrayOfBattleHexArrays neighbouringTilesCache;
|
||||
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDblWide;
|
||||
|
||||
BattleHexArray() = default;
|
||||
|
||||
template <typename Container, typename = std::enable_if_t<
|
||||
@ -60,28 +56,6 @@ public:
|
||||
|
||||
BattleHexArray(std::initializer_list<BattleHex> initList) noexcept;
|
||||
|
||||
/// returns all tiles, unavailable tiles will be set as invalid
|
||||
/// order of returned tiles matches EDir enum
|
||||
static BattleHexArray getAllNeighbouringTiles(BattleHex hex)
|
||||
{
|
||||
static ArrayOfBattleHexArrays cache;
|
||||
static bool initialized = false;
|
||||
|
||||
if(initialized)
|
||||
return cache[hex.hex];
|
||||
|
||||
for(BattleHex h = 0; h < GameConstants::BFIELD_SIZE; h.hex++)
|
||||
{
|
||||
cache[h].resize(6);
|
||||
|
||||
for(auto dir : BattleHex::hexagonalDirections())
|
||||
cache[h].set(dir, h.cloneInDirection(dir, false));
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
return cache[hex.hex];
|
||||
}
|
||||
|
||||
void checkAndPush(BattleHex tile)
|
||||
{
|
||||
if(tile.isAvailable() && !contains(tile))
|
||||
@ -126,8 +100,6 @@ public:
|
||||
return internalStorage.insert(pos, hex);
|
||||
}
|
||||
|
||||
BattleHex getClosestTile(BattleSide side, BattleHex initialPos) const;
|
||||
|
||||
void insert(const BattleHexArray & other) noexcept;
|
||||
|
||||
template <typename Container, typename = std::enable_if_t<
|
||||
@ -185,6 +157,30 @@ public:
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/// get (precomputed) all possible surrounding tiles
|
||||
static const BattleHexArray & getAllNeighbouringTiles(BattleHex hex)
|
||||
{
|
||||
assert(hex.isValid());
|
||||
|
||||
return allNeighbouringTiles[hex];
|
||||
}
|
||||
|
||||
/// get (precomputed) only valid and available surrounding tiles
|
||||
static const BattleHexArray & getNeighbouringTiles(BattleHex hex)
|
||||
{
|
||||
assert(hex.isValid());
|
||||
|
||||
return neighbouringTiles[hex];
|
||||
}
|
||||
|
||||
/// get (precomputed) only valid and available surrounding tiles for double wide creatures
|
||||
static const BattleHexArray & getNeighbouringTilesDblWide(BattleHex hex, BattleSide side)
|
||||
{
|
||||
assert(hex.isValid() && (side == BattleSide::ATTACKER || BattleSide::DEFENDER));
|
||||
|
||||
return neighbouringTilesDblWide.at(side)[hex];
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool contains(BattleHex hex) const noexcept
|
||||
{
|
||||
if(hex.isValid())
|
||||
@ -301,10 +297,13 @@ private:
|
||||
return hex == BattleHex::CASTLE_CENTRAL_TOWER || hex == BattleHex::CASTLE_UPPER_TOWER || hex == BattleHex::CASTLE_BOTTOM_TOWER;
|
||||
}
|
||||
|
||||
/// returns all valid neighbouring tiles
|
||||
static ArrayOfBattleHexArrays calculateNeighbouringTiles();
|
||||
static ArrayOfBattleHexArrays calculateNeighbouringTilesDblWide(BattleSide side);
|
||||
static BattleHexArray generateNeighbouringTiles(BattleHex hex);
|
||||
static const ArrayOfBattleHexArrays neighbouringTiles;
|
||||
static const ArrayOfBattleHexArrays allNeighbouringTiles;
|
||||
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDblWide;
|
||||
|
||||
static ArrayOfBattleHexArrays precalculateNeighbouringTiles();
|
||||
static ArrayOfBattleHexArrays precalculateAllNeighbouringTiles();
|
||||
static ArrayOfBattleHexArrays precalculateNeighbouringTilesDblWide(BattleSide side);
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -709,7 +709,7 @@ void BattleInfo::setUnitState(uint32_t id, const JsonNode & data, int64_t health
|
||||
|
||||
if(!accessibility.accessible(changedStack->getPosition(), changedStack))
|
||||
{
|
||||
logNetwork->error("Cannot resurrect %s because hex %d is occupied!", changedStack->nodeName(), changedStack->getPosition().hex);
|
||||
logNetwork->error("Cannot resurrect %s because hex %d is occupied!", changedStack->nodeName(), changedStack->getPosition());
|
||||
return; //position is already occupied
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ bool CBattleInfoCallback::battleIsInsideWalls(BattleHex from) const
|
||||
bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest, bool checkWall, bool checkMoat) const
|
||||
{
|
||||
if (!from.isAvailable() || !dest.isAvailable())
|
||||
throw std::runtime_error("Invalid hex (" + std::to_string(from.hex) + " and " + std::to_string(dest.hex) + ") received in battleHasPenaltyOnLine!" );
|
||||
throw std::runtime_error("Invalid hex (" + std::to_string(from) + " and " + std::to_string(dest) + ") received in battleHasPenaltyOnLine!" );
|
||||
|
||||
auto isTileBlocked = [&](BattleHex tile)
|
||||
{
|
||||
@ -204,7 +204,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
|
||||
|
||||
while (next != dest)
|
||||
{
|
||||
next = BattleHexArray::neighbouringTilesCache[next].getClosestTile(direction, dest);
|
||||
next = BattleHex::getClosestTile(next.getNeighbouringTiles(), direction, dest);
|
||||
ret.insert(next);
|
||||
}
|
||||
assert(!ret.empty());
|
||||
@ -1077,9 +1077,9 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
|
||||
if(isInObstacle(curHex, obstacles, checkParams))
|
||||
continue;
|
||||
|
||||
const int costToNeighbour = ret.distances.at(curHex.hex) + 1;
|
||||
const int costToNeighbour = ret.distances.at(curHex) + 1;
|
||||
|
||||
for(BattleHex neighbour : BattleHexArray::neighbouringTilesCache[curHex.hex])
|
||||
for(BattleHex neighbour : curHex.getNeighbouringTiles())
|
||||
{
|
||||
auto additionalCost = 0;
|
||||
|
||||
@ -1093,13 +1093,13 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
|
||||
}
|
||||
}
|
||||
|
||||
const int costFoundSoFar = ret.distances[neighbour.hex];
|
||||
const int costFoundSoFar = ret.distances[neighbour];
|
||||
|
||||
if(accessibleCache[neighbour.hex] && costToNeighbour + additionalCost < costFoundSoFar)
|
||||
if(accessibleCache[neighbour] && costToNeighbour + additionalCost < costFoundSoFar)
|
||||
{
|
||||
hexq.push(neighbour);
|
||||
ret.distances[neighbour.hex] = costToNeighbour + additionalCost;
|
||||
ret.predecessors[neighbour.hex] = curHex;
|
||||
ret.distances[neighbour] = costToNeighbour + additionalCost;
|
||||
ret.predecessors[neighbour] = curHex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1222,7 +1222,7 @@ BattleHex CBattleInfoCallback::getAvailableHex(const CreatureID & creID, BattleS
|
||||
return BattleHex::INVALID; //all tiles are covered
|
||||
}
|
||||
|
||||
return occupyable.getClosestTile(side, pos);
|
||||
return BattleHex::getClosestTile(occupyable, side, pos);
|
||||
}
|
||||
|
||||
si8 CBattleInfoCallback::battleGetTacticDist() const
|
||||
@ -1353,7 +1353,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
|
||||
}
|
||||
if(attacker->hasBonusOfType(BonusType::WIDE_BREATH))
|
||||
{
|
||||
BattleHexArray hexes = BattleHexArray::neighbouringTilesCache[destinationTile];
|
||||
BattleHexArray hexes = destinationTile.getNeighbouringTiles();
|
||||
for(int i = 0; i < hexes.size(); i++)
|
||||
{
|
||||
if(hexes.at(i) == attackOriginHex)
|
||||
@ -1426,9 +1426,9 @@ AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::
|
||||
AttackableTiles at;
|
||||
RETURN_IF_NOT_BATTLE(at);
|
||||
|
||||
if(attacker->hasBonusOfType(BonusType::SHOOTS_ALL_ADJACENT) && !BattleHexArray::neighbouringTilesCache[attackerPos].contains(destinationTile))
|
||||
if(attacker->hasBonusOfType(BonusType::SHOOTS_ALL_ADJACENT) && !attackerPos.getNeighbouringTiles().contains(destinationTile))
|
||||
{
|
||||
at.hostileCreaturePositions.insert(BattleHexArray::neighbouringTilesCache[destinationTile]);
|
||||
at.hostileCreaturePositions.insert(destinationTile.getNeighbouringTiles());
|
||||
at.hostileCreaturePositions.insert(destinationTile);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BattleHexArray.h"
|
||||
#include "BattleHex.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -44,7 +44,7 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
|
||||
|
||||
for(auto targetHex : targetHexes)
|
||||
{
|
||||
for(auto & n : BattleHexArray::neighbouringTilesCache[targetHex])
|
||||
for(auto & n : targetHex.getNeighbouringTiles())
|
||||
{
|
||||
if(distances[n] < ret)
|
||||
{
|
||||
|
@ -60,12 +60,10 @@ const BattleHexArray & Unit::getSurroundingHexes(BattleHex assumedPosition) cons
|
||||
|
||||
const BattleHexArray & Unit::getSurroundingHexes(BattleHex position, bool twoHex, BattleSide side)
|
||||
{
|
||||
assert(position.isValid()); // check outside if position isValid
|
||||
|
||||
if(!twoHex)
|
||||
return BattleHexArray::neighbouringTilesCache[position];
|
||||
return position.getNeighbouringTiles();
|
||||
|
||||
return BattleHexArray::neighbouringTilesDblWide.at(side).at(position);
|
||||
return position.getNeighbouringTilesDblWide(side);
|
||||
}
|
||||
|
||||
BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
||||
@ -88,7 +86,7 @@ BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
||||
hexes.pop_back();
|
||||
|
||||
for(auto hex : hexes)
|
||||
targetableHexes.insert(BattleHexArray::neighbouringTilesCache[hex]);
|
||||
targetableHexes.insert(hex.getNeighbouringTiles());
|
||||
}
|
||||
|
||||
return targetableHexes;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "NetPacksBase.h"
|
||||
#include "BattleChanges.h"
|
||||
#include "../battle/BattleHexArray.h"
|
||||
#include "../battle/BattleAction.h"
|
||||
#include "../texts/MetaString.h"
|
||||
|
||||
@ -22,7 +23,6 @@ class CGHeroInstance;
|
||||
class CArmedInstance;
|
||||
class IBattleState;
|
||||
class BattleInfo;
|
||||
class BattleHexArray;
|
||||
|
||||
struct DLL_LINKAGE BattleStart : public CPackForClient
|
||||
{
|
||||
|
@ -610,7 +610,7 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
|
||||
{
|
||||
hexesToCheck.insert(stack->getPosition());
|
||||
|
||||
for(auto adjacent : BattleHexArray::neighbouringTilesCache[stack->getPosition().hex])
|
||||
for(auto adjacent : stack->getPosition().getNeighbouringTiles())
|
||||
hexesToCheck.insert(adjacent);
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include "../IHandlerBase.h"
|
||||
#include "../ConstTransitivePtr.h"
|
||||
#include "../int3.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "../battle/BattleHexArray.h"
|
||||
#include "../bonuses/Bonus.h"
|
||||
#include "../filesystem/ResourcePath.h"
|
||||
#include "../json/JsonNode.h"
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct BattleHex;
|
||||
class BattleHex;
|
||||
class BattleHexArray;
|
||||
class CBattleInfoCallback;
|
||||
class JsonSerializeFormat;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "LocationEffect.h"
|
||||
#include "../ISpellMechanics.h"
|
||||
#include "battle/BattleHexArray.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -228,7 +228,7 @@ EffectTarget UnitEffect::transformTargetByChain(const Mechanics * m, const Targe
|
||||
if(possibleHexes.empty())
|
||||
break;
|
||||
|
||||
destHex = possibleHexes.getClosestTile(unit->unitSide(), destHex);
|
||||
destHex = BattleHex::getClosestTile(possibleHexes, unit->unitSide(), destHex);
|
||||
}
|
||||
|
||||
return effectTarget;
|
||||
|
@ -16,7 +16,7 @@ struct BattleLogMessage;
|
||||
struct BattleAttack;
|
||||
class BattleAction;
|
||||
class CBattleInfoCallback;
|
||||
struct BattleHex;
|
||||
class BattleHex;
|
||||
class CStack;
|
||||
class PlayerColor;
|
||||
enum class BonusType : uint8_t;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class CStack;
|
||||
struct BattleHex;
|
||||
class BattleHex;
|
||||
class BattleHexArray;
|
||||
class BattleAction;
|
||||
class CBattleInfoCallback;
|
||||
|
Loading…
x
Reference in New Issue
Block a user