1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-21 19:19:26 +02:00

Changes following review:

- shared_ptr for destructibleEnemyTurns instead of raw pointer
- drop implicit int conversion for BattleHex class
  and implement toInt() instead
- implement necessary operators in BattleHex
- adjust code to work properly with JSON serializer
This commit is contained in:
MichalZr6 2025-01-06 23:05:45 +01:00
parent 4031006317
commit dbe82b94f6
39 changed files with 223 additions and 174 deletions

View File

@ -280,7 +280,7 @@ int64_t AttackPossibility::evaluateBlockedShootersDmg(
std::set<uint32_t> checkedUnits;
auto attacker = attackInfo.attacker;
const BattleHexArray & hexes = attacker->getSurroundingHexes(hex);
const auto & hexes = attacker->getSurroundingHexes(hex);
for(BattleHex tile : hexes)
{
auto st = state->battleGetUnitByPos(tile, true);

View File

@ -214,8 +214,8 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
bestAttack.attackerState->unitType()->getJsonKey(),
bestAttack.affectedUnits[0]->unitType()->getJsonKey(),
bestAttack.affectedUnits[0]->getCount(),
(int)bestAttack.from,
(int)bestAttack.attack.attacker->getPosition(),
bestAttack.from.toInt(),
bestAttack.attack.attacker->getPosition().toInt(),
bestAttack.attack.chargeDistance,
bestAttack.attack.attacker->getMovementRange(0),
bestAttack.defenderDamageReduce,
@ -355,7 +355,7 @@ BattleAction BattleEvaluator::moveOrAttack(const CStack * stack, BattleHex hex,
}
}
BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexArray hexes, const PotentialTargets & targets)
BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const BattleHexArray & hexes, const PotentialTargets & targets)
{
auto reachability = cb->getBattle(battleID)->getReachability(stack);
auto avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(reachability, stack, false);
@ -387,12 +387,12 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
std::sort(targetHexes.begin(), targetHexes.end(), [&](BattleHex h1, BattleHex h2) -> bool
{
return reachability.distances[h1] < reachability.distances[h2];
return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()];
});
BattleHex bestNeighbour = hexes.front();
if(reachability.distances[bestNeighbour] > GameConstants::BFIELD_SIZE)
if(reachability.distances[bestNeighbour.toInt()] > GameConstants::BFIELD_SIZE)
{
logAi->trace("No reachable hexes.");
return BattleAction::makeDefend(stack);
@ -468,7 +468,7 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
return moveOrAttack(stack, currentDest, targets);
}
currentDest = reachability.predecessors[currentDest];
currentDest = reachability.predecessors[currentDest.toInt()];
}
}

View File

@ -51,7 +51,7 @@ public:
bool attemptCastingSpell(const CStack * stack);
bool canCastSpell();
std::optional<PossibleSpellcast> findBestCreatureSpell(const CStack * stack);
BattleAction goTowardsNearest(const CStack * stack, BattleHexArray hexes, const PotentialTargets & targets);
BattleAction goTowardsNearest(const CStack * stack, const BattleHexArray & hexes, const PotentialTargets & targets);
std::vector<BattleHex> getBrokenWallMoatHexes() const;
bool hasWorkingTowers() const;
void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only

View File

@ -310,7 +310,7 @@ ReachabilityInfo getReachabilityWithEnemyBypass(
for(auto & hex : unit->getHexes())
if(hex.isAvailable()) //towers can have <0 pos; we don't also want to overwrite side columns
params.destructibleEnemyTurns[hex] = turnsToKill * unit->getMovementRange();
params.destructibleEnemyTurns[hex.toInt()] = turnsToKill * unit->getMovementRange();
}
params.bypassEnemyStacks = true;
@ -415,11 +415,11 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
for(BattleHex enemyHex : enemy->getAttackableHexes(activeStack))
{
while(!flying && dists.distances[enemyHex] > speed && dists.predecessors.at(enemyHex).isValid())
while(!flying && dists.distances[enemyHex.toInt()] > speed && dists.predecessors.at(enemyHex.toInt()).isValid())
{
enemyHex = dists.predecessors.at(enemyHex);
enemyHex = dists.predecessors.at(enemyHex.toInt());
if(dists.accessibility[enemyHex] == EAccessibility::ALIVE_STACK)
if(dists.accessibility[enemyHex.toInt()] == EAccessibility::ALIVE_STACK)
{
auto defenderToBypass = hb->battleGetUnitByPos(enemyHex);
@ -429,7 +429,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
logAi->trace("Found target to bypass at %d", enemyHex.hex);
#endif
auto attackHex = dists.predecessors[enemyHex];
auto attackHex = dists.predecessors[enemyHex.toInt()];
auto baiBypass = BattleAttackInfo(activeStack, defenderToBypass, 0, cb->battleCanShoot(activeStack));
auto attackBypass = AttackPossibility::evaluate(baiBypass, attackHex, damageCache, hb);
@ -440,7 +440,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
auto bypassScore = calculateExchange(
attackBypass,
dists.distances[attackHex],
dists.distances[attackHex.toInt()],
targets,
damageCache,
hb,
@ -916,8 +916,7 @@ void BattleExchangeEvaluator::updateReachabilityMap(std::shared_ptr<HypotheticBa
}
}
}
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); ++hex)
{
reachabilityMap[hex] = getOneTurnReachableUnits(0, hex);
}
@ -952,9 +951,9 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getOneTurnReachableUn
ReachabilityInfo unitReachability = reachabilityIter != reachabilityCache.end() ? reachabilityIter->second : turnBattle.getReachability(unit);
bool reachable = unitReachability.distances.at(hex) <= radius;
bool reachable = unitReachability.distances.at(hex.toInt()) <= radius;
if(!reachable && unitReachability.accessibility[hex] == EAccessibility::ALIVE_STACK)
if(!reachable && unitReachability.accessibility[hex.toInt()] == EAccessibility::ALIVE_STACK)
{
const battle::Unit * hexStack = cb->battleGetUnitByPos(hex);
@ -962,7 +961,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getOneTurnReachableUn
{
for(BattleHex neighbour : hex.getNeighbouringTiles())
{
reachable = unitReachability.distances.at(neighbour) <= radius;
reachable = unitReachability.distances.at(neighbour.toInt()) <= radius;
if(reachable) break;
}
@ -1009,12 +1008,12 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
auto unitReachability = turnBattle.getReachability(unit);
auto unitSpeed = unit->getMovementRange(turn); // Cached value, to avoid performance hit
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex++)
{
bool enemyUnit = false;
bool reachable = unitReachability.distances.at(hex) <= unitSpeed;
bool reachable = unitReachability.distances.at(hex.toInt()) <= unitSpeed;
if(!reachable && unitReachability.accessibility[hex] == EAccessibility::ALIVE_STACK)
if(!reachable && unitReachability.accessibility[hex.toInt()] == EAccessibility::ALIVE_STACK)
{
const battle::Unit * hexStack = turnBattle.battleGetUnitByPos(hex);
@ -1023,7 +1022,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
enemyUnit = true;
for(BattleHex neighbour : hex.getNeighbouringTiles())
{
reachable = unitReachability.distances.at(neighbour) <= unitSpeed;
reachable = unitReachability.distances.at(neighbour.toInt()) <= unitSpeed;
if(reachable) break;
}

View File

@ -50,7 +50,7 @@ PotentialTargets::PotentialTargets(
auto GenerateAttackInfo = [&](bool shooting, BattleHex hex) -> AttackPossibility
{
int distance = hex.isValid() ? reachability.distances[hex] : 0;
int distance = hex.isValid() ? reachability.distances[hex.toInt()] : 0;
auto bai = BattleAttackInfo(attackerInfo, defender, distance, shooting);
return AttackPossibility::evaluate(bai, hex, damageCache, state);

View File

@ -291,7 +291,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
std::sort(hexes.begin(), hexes.end(), [&](BattleHex h1, BattleHex h2) -> bool
{
return reachability.distances[h1] < reachability.distances[h2];
return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()];
});
for(auto hex : hexes)
@ -313,7 +313,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
BattleHex bestneighbour = hexes.front();
if(reachability.distances[bestneighbour] > GameConstants::BFIELD_SIZE)
if(reachability.distances[bestneighbour.toInt()] > GameConstants::BFIELD_SIZE)
{
return BattleAction::makeDefend(stack);
}
@ -347,7 +347,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
return BattleAction::makeMove(stack, currentDest);
}
currentDest = reachability.predecessors[currentDest];
currentDest = reachability.predecessors[currentDest.toInt()];
}
}
}

View File

@ -522,7 +522,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
{
const auto * attacker = owner.stacksController->getActiveStack();
BattleHex attackFromHex = owner.fieldController->fromWhichHexAttack(targetHex);
int distance = attacker->position.isValid() ? owner.getBattle()->battleGetDistances(attacker, attacker->getPosition())[attackFromHex] : 0;
int distance = attacker->position.isValid() ? owner.getBattle()->battleGetDistances(attacker, attacker->getPosition())[attackFromHex.toInt()] : 0;
DamageEstimation retaliation;
BattleAttackInfo attackInfo(attacker, targetStack, distance, false );
DamageEstimation estimation = owner.getBattle()->battleEstimateDamage(attackInfo, &retaliation);

View File

@ -174,7 +174,7 @@ AttackAnimation::AttackAnimation(BattleInterface & owner, const CStack *attacker
attackingStack(attacker)
{
assert(attackingStack && "attackingStack is nullptr in CBattleAttack::CBattleAttack !\n");
attackingStackPosBeforeReturn = attackingStack->getPosition();
attackingStackPosBeforeReturn = attackingStack->getPosition().toInt();
}
HittedAnimation::HittedAnimation(BattleInterface & owner, const CStack * stack)

View File

@ -839,7 +839,7 @@ void BattleFieldController::updateAccessibleHexes()
bool BattleFieldController::stackCountOutsideHex(const BattleHex & number) const
{
return stackCountOutsideHexes[number];
return stackCountOutsideHexes[number.toInt()];
}
void BattleFieldController::showAll(Canvas & to)

View File

@ -185,7 +185,7 @@ BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTo
const CCreature *BattleSiegeController::getTurretCreature(BattleHex position) const
{
switch (position)
switch (position.toInt())
{
case BattleHex::CASTLE_CENTRAL_TOWER:
return town->fortificationsLevel().citadelShooter.toCreature();
@ -195,14 +195,14 @@ 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));
throw std::runtime_error("Unable to select shooter for tower at " + std::to_string(position.toInt()));
}
Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) const
{
// Turret positions are read out of the config/wall_pos.txt
int posID = 0;
switch (position)
switch (position.toInt())
{
case BattleHex::CASTLE_CENTRAL_TOWER: // keep creature
posID = EWallVisual::CREATURE_KEEP;

View File

@ -252,8 +252,8 @@ BattleHexArray CStack::meleeAttackHexes(const battle::Unit * attacker, const bat
if (!defenderPos.isValid())
defenderPos = defender->getPosition();
BattleHex otherAttackerPos = attackerPos + (attacker->unitSide() == BattleSide::ATTACKER ? -1 : 1);
BattleHex otherDefenderPos = defenderPos + (defender->unitSide() == BattleSide::ATTACKER ? -1 : 1);
BattleHex otherAttackerPos = attackerPos.toInt() + (attacker->unitSide() == BattleSide::ATTACKER ? -1 : 1);
BattleHex otherDefenderPos = defenderPos.toInt() + (defender->unitSide() == BattleSide::ATTACKER ? -1 : 1);
if(BattleHex::mutualPosition(attackerPos, defenderPos) >= 0) //front <=> front
{

View File

@ -66,7 +66,7 @@ BattleHexArray ObstacleInfo::getBlocked(BattleHex hex) const
BattleHexArray ret;
for(int offset : blockedTiles)
{
BattleHex toBlock = hex + offset;
BattleHex toBlock = hex.toInt() + offset;
if((hex.getY() & 1) && !(toBlock.getY() & 1))
toBlock += BattleHex::LEFT;

View File

@ -18,14 +18,14 @@ VCMI_LIB_NAMESPACE_BEGIN
bool AccessibilityInfo::tileAccessibleWithGate(BattleHex tile, BattleSide side) const
{
//at(otherHex) != EAccessibility::ACCESSIBLE && (at(otherHex) != EAccessibility::GATE || side != BattleSide::DEFENDER)
const auto & accessibility = at(tile);
const auto & accessibility = at(tile.toInt());
if(accessibility == EAccessibility::ALIVE_STACK)
{
if(!destructibleEnemyTurns)
return false;
return destructibleEnemyTurns->at(tile) >= 0;
return destructibleEnemyTurns->at(tile.toInt()) >= 0;
}
if(accessibility != EAccessibility::ACCESSIBLE)

View File

@ -32,10 +32,11 @@ enum class EAccessibility
using TAccessibilityArray = std::array<EAccessibility, GameConstants::BFIELD_SIZE>;
using TBattlefieldTurnsArray = std::array<int8_t, GameConstants::BFIELD_SIZE>;
struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
{
const std::array<int8_t, GameConstants::BFIELD_SIZE> * destructibleEnemyTurns = nullptr;
std::shared_ptr<const TBattlefieldTurnsArray> destructibleEnemyTurns; //used only as a view for destructibleEnemyTurns from ReachabilityInfo::Parameters
public:
bool accessible(BattleHex tile, const battle::Unit * stack) const; //checks for both tiles if stack is double wide

View File

@ -48,24 +48,24 @@ BattleHex BattleHex::getClosestTile(BattleSide side, BattleHex initialPos, const
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
}
const BattleHexArray & BattleHex::getAllNeighbouringTiles() const
const BattleHexArray & BattleHex::getAllNeighbouringTiles() const noexcept
{
return BattleHexArray::getAllNeighbouringTiles(*this);
}
const BattleHexArray & BattleHex::getNeighbouringTiles() const
const BattleHexArray & BattleHex::getNeighbouringTiles() const noexcept
{
return BattleHexArray::getNeighbouringTiles(*this);
}
const BattleHexArray & BattleHex::getNeighbouringTilesDblWide(BattleSide side) const
const BattleHexArray & BattleHex::getNeighbouringTilesDoubleWide(BattleSide side) const noexcept
{
return BattleHexArray::getNeighbouringTilesDblWide(*this, side);
return BattleHexArray::getNeighbouringTilesDoubleWide(*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() % static_cast<si16>(hex));
return os << boost::str(boost::format("{BattleHex: x '%d', y '%d', hex '%d'}") % hex.getX() % hex.getY() % hex.toInt());
}
VCMI_LIB_NAMESPACE_END

View File

@ -24,7 +24,8 @@ namespace GameConstants
class BattleHexArray;
// for battle stacks' positions
// for battle stacks' positions; valid hexes are from 0 to 186; available are only those not in first and last column
// castle towers are -2, -3 and -4
class DLL_LINKAGE BattleHex
{
public:
@ -68,10 +69,10 @@ public:
BOTTOM
};
BattleHex()
BattleHex() noexcept
: hex(INVALID)
{}
BattleHex(si16 _hex)
BattleHex(si16 _hex) noexcept
: hex(_hex)
{}
BattleHex(si16 x, si16 y)
@ -82,17 +83,13 @@ public:
{
setXY(xy);
}
operator si16() const
{
return hex;
}
inline bool isValid() const
[[nodiscard]] bool isValid() const noexcept
{
return hex >= 0 && hex < GameConstants::BFIELD_SIZE;
}
bool isAvailable() const //valid position not in first or last column
[[nodiscard]] bool isAvailable() const noexcept //valid position not in first or last column
{
return isValid() && getX() > 0 && getX() < GameConstants::BFIELD_WIDTH - 1;
}
@ -123,17 +120,17 @@ public:
setXY(xy.first, xy.second);
}
si16 getX() const
[[nodiscard]] si16 getX() const noexcept
{
return hex % GameConstants::BFIELD_WIDTH;
}
si16 getY() const
[[nodiscard]] si16 getY() const noexcept
{
return hex / GameConstants::BFIELD_WIDTH;
}
std::pair<si16, si16> getXY() const
[[nodiscard]] std::pair<si16, si16> getXY() const noexcept
{
return std::make_pair(getX(), getY());
}
@ -171,24 +168,14 @@ public:
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
[[nodiscard]] BattleHex cloneInDirection(EDir dir, bool hasToBeValid = true) const
{
BattleHex result(hex);
result.moveInDirection(dir, hasToBeValid);
return result;
}
static uint8_t getDistance(BattleHex hex1, BattleHex hex2)
[[nodiscard]] static uint8_t getDistance(BattleHex hex1, BattleHex hex2) noexcept
{
int y1 = hex1.getY();
int y2 = hex2.getY();
@ -205,15 +192,15 @@ public:
return std::abs(xDst) + std::abs(yDst);
}
static BattleHex getClosestTile(BattleSide side, BattleHex initialPos, const BattleHexArray & hexes);
[[nodiscard]] static BattleHex getClosestTile(BattleSide side, BattleHex initialPos, const BattleHexArray & hexes);
//Constexpr defined array with all directions used in battle
static constexpr auto hexagonalDirections()
[[nodiscard]] static constexpr auto hexagonalDirections() noexcept
{
return std::array<EDir,6>{TOP_LEFT, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, LEFT};
}
static EDir mutualPosition(BattleHex hex1, BattleHex hex2)
[[nodiscard]] static EDir mutualPosition(BattleHex hex1, BattleHex hex2)
{
for(auto dir : hexagonalDirections())
if(hex2 == hex1.cloneInDirection(dir, false))
@ -222,13 +209,59 @@ public:
}
/// get (precomputed) all possible surrounding tiles
const BattleHexArray & getAllNeighbouringTiles() const;
[[nodiscard]] const BattleHexArray & getAllNeighbouringTiles() const noexcept;
/// get (precomputed) only valid and available surrounding tiles
const BattleHexArray & getNeighbouringTiles() const;
[[nodiscard]] const BattleHexArray & getNeighbouringTiles() const noexcept;
/// get (precomputed) only valid and available surrounding tiles for double wide creatures
const BattleHexArray & getNeighbouringTilesDblWide(BattleSide side) const;
[[nodiscard]] const BattleHexArray & getNeighbouringTilesDoubleWide(BattleSide side) const noexcept;
/// get integer hex value
[[nodiscard]] si16 toInt() const noexcept
{
return hex;
}
BattleHex & operator+=(EDir dir)
{
return moveInDirection(dir);
}
[[nodiscard]] BattleHex operator+(EDir dir) const
{
return cloneInDirection(dir);
}
// Prefix increment
BattleHex & operator++() noexcept
{
++hex;
return *this;
}
// Postfix increment
BattleHex operator++(int) noexcept
{
BattleHex temp = *this;
++hex;
return temp;
}
[[nodiscard]] bool operator ==(BattleHex other) const noexcept
{
return hex == other.hex;
}
[[nodiscard]] bool operator !=(BattleHex other) const noexcept
{
return hex != other.hex;
}
[[nodiscard]] bool operator <(BattleHex other) const noexcept
{
return hex < other.hex;
}
template <typename Handler>
void serialize(Handler & h)

View File

@ -34,7 +34,7 @@ void BattleHexArray::erase(iterator first, iterator last) noexcept
{
for(auto it = first; it != last && it != internalStorage.end(); ++it)
{
presenceFlags[*it] = 0;
presenceFlags[it->toInt()] = 0;
}
internalStorage.erase(first, last);
@ -43,7 +43,7 @@ void BattleHexArray::erase(iterator first, iterator last) noexcept
void BattleHexArray::clear() noexcept
{
for(auto hex : internalStorage)
presenceFlags[hex] = 0;
presenceFlags[hex.toInt()] = 0;
internalStorage.clear();
}
@ -83,7 +83,7 @@ BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateAllNeighbouri
return ret;
}
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringTilesDblWide(BattleSide side)
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringTilesDoubleWide(BattleSide side)
{
ArrayOfBattleHexArrays ret;
@ -123,10 +123,10 @@ BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringT
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::neighbouringTiles = precalculateNeighbouringTiles();
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::allNeighbouringTiles = precalculateAllNeighbouringTiles();
const std::map<BattleSide, BattleHexArray::ArrayOfBattleHexArrays> BattleHexArray::neighbouringTilesDblWide =
const std::map<BattleSide, BattleHexArray::ArrayOfBattleHexArrays> BattleHexArray::neighbouringTilesDoubleWide =
{
{ BattleSide::ATTACKER, precalculateNeighbouringTilesDblWide(BattleSide::ATTACKER) },
{ BattleSide::DEFENDER, precalculateNeighbouringTilesDblWide(BattleSide::DEFENDER) }
{ BattleSide::ATTACKER, precalculateNeighbouringTilesDoubleWide(BattleSide::ATTACKER) },
{ BattleSide::DEFENDER, precalculateNeighbouringTilesDoubleWide(BattleSide::DEFENDER) }
};
VCMI_LIB_NAMESPACE_END

View File

@ -60,7 +60,7 @@ public:
{
if(tile.isAvailable() && !contains(tile))
{
presenceFlags[tile] = 1;
presenceFlags[tile.toInt()] = true;
internalStorage.emplace_back(tile);
}
}
@ -70,7 +70,7 @@ public:
if(contains(hex))
return;
presenceFlags[hex] = 1;
presenceFlags[hex.toInt()] = true;
internalStorage.emplace_back(hex);
}
@ -87,7 +87,7 @@ public:
if(contains(hex))
return;
presenceFlags[hex] = 1;
presenceFlags[hex.toInt()] = true;
internalStorage[index] = hex;
}
@ -96,7 +96,7 @@ public:
if(contains(hex))
return pos;
presenceFlags[hex] = 1;
presenceFlags[hex.toInt()] = true;
return internalStorage.insert(pos, hex);
}
@ -122,7 +122,7 @@ public:
void erase(iterator first, iterator last) noexcept;
inline void pop_back() noexcept
{
presenceFlags[internalStorage.back()] = 0;
presenceFlags[internalStorage.back().toInt()] = false;
internalStorage.pop_back();
}
@ -158,33 +158,33 @@ public:
}
/// get (precomputed) all possible surrounding tiles
static const BattleHexArray & getAllNeighbouringTiles(BattleHex hex)
static const BattleHexArray & getAllNeighbouringTiles(BattleHex hex) noexcept
{
assert(hex.isValid());
return allNeighbouringTiles[hex];
return allNeighbouringTiles[hex.toInt()];
}
/// get (precomputed) only valid and available surrounding tiles
static const BattleHexArray & getNeighbouringTiles(BattleHex hex)
static const BattleHexArray & getNeighbouringTiles(BattleHex hex) noexcept
{
assert(hex.isValid());
return neighbouringTiles[hex];
return neighbouringTiles[hex.toInt()];
}
/// get (precomputed) only valid and available surrounding tiles for double wide creatures
static const BattleHexArray & getNeighbouringTilesDblWide(BattleHex hex, BattleSide side)
static const BattleHexArray & getNeighbouringTilesDoubleWide(BattleHex hex, BattleSide side) noexcept
{
assert(hex.isValid() && (side == BattleSide::ATTACKER || side == BattleSide::DEFENDER));
return neighbouringTilesDblWide.at(side)[hex];
return neighbouringTilesDoubleWide.at(side)[hex.toInt()];
}
[[nodiscard]] inline bool contains(BattleHex hex) const noexcept
{
if(hex.isValid())
return presenceFlags[hex];
return presenceFlags[hex.toInt()];
/*
if(!isTower(hex))
logGlobal->warn("BattleHexArray::contains( %d ) - invalid BattleHex!", hex);
@ -198,10 +198,10 @@ public:
void serialize(Serializer & s)
{
s & internalStorage;
if(!internalStorage.empty() && presenceFlags[internalStorage.front()] == 0)
if(!s.saving)
{
for(auto hex : internalStorage)
presenceFlags[hex] = 1;
presenceFlags[hex.toInt()] = true;
}
}
@ -307,11 +307,11 @@ private:
static const ArrayOfBattleHexArrays neighbouringTiles;
static const ArrayOfBattleHexArrays allNeighbouringTiles;
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDblWide;
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDoubleWide;
static ArrayOfBattleHexArrays precalculateNeighbouringTiles();
static ArrayOfBattleHexArrays precalculateAllNeighbouringTiles();
static ArrayOfBattleHexArrays precalculateNeighbouringTilesDblWide(BattleSide side);
static ArrayOfBattleHexArrays precalculateNeighbouringTilesDoubleWide(BattleSide side);
};
VCMI_LIB_NAMESPACE_END

View File

@ -46,7 +46,7 @@ CStack * BattleInfo::generateNewStack(uint32_t id, const CStackInstance & base,
assert(!owner.isValidPlayer() || (base.armyObj && base.armyObj->tempOwner == owner));
auto * ret = new CStack(&base, owner, id, side, slot);
ret->initialPosition = getAvailableHex(base.getCreatureID(), side, position); //TODO: what if no free tile on battlefield was found?
ret->initialPosition = getAvailableHex(base.getCreatureID(), side, position.toInt()); //TODO: what if no free tile on battlefield was found?
stacks.push_back(ret);
return ret;
}
@ -264,7 +264,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
for(BattleHex blocked : obi.getBlocked(pos))
{
if(tileAccessibility[blocked] == EAccessibility::UNAVAILABLE) //for ship-to-ship battlefield - exclude hardcoded unavailable tiles
if(tileAccessibility[blocked.toInt()] == EAccessibility::UNAVAILABLE) //for ship-to-ship battlefield - exclude hardcoded unavailable tiles
return false;
if(blockedTiles.contains(blocked))
return false;

View File

@ -43,19 +43,15 @@ static BattleHex lineToWallHex(int line) //returns hex with wall in given line (
static bool sameSideOfWall(BattleHex pos1, BattleHex pos2)
{
const int wallInStackLine = lineToWallHex(pos1.getY());
const int wallInDestLine = lineToWallHex(pos2.getY());
const bool stackLeft = pos1 < wallInStackLine;
const bool destLeft = pos2 < wallInDestLine;
const bool stackLeft = pos1 < lineToWallHex(pos1.getY());
const bool destLeft = pos2 < lineToWallHex(pos2.getY());
return stackLeft == destLeft;
}
static bool isInsideWalls(BattleHex pos)
{
const int wallInStackLine = lineToWallHex(pos.getY());
return wallInStackLine < pos;
return lineToWallHex(pos.getY()) < pos;
}
// parts of wall
@ -79,9 +75,10 @@ static const std::pair<int, EWallPart> wallParts[] =
static EWallPart hexToWallPart(BattleHex hex)
{
si16 hexValue = hex.toInt();
for(const auto & elem : wallParts)
{
if(elem.first == hex)
if(elem.first == hexValue)
return elem.second;
}
@ -151,7 +148,7 @@ std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(BattleHex start, B
{
auto reachability = getReachability(stack);
if(reachability.predecessors[dest] == -1) //cannot reach destination
if(reachability.predecessors[dest.toInt()] == -1) //cannot reach destination
{
return std::make_pair(BattleHexArray(), 0);
}
@ -162,10 +159,10 @@ std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(BattleHex start, B
while(curElem != start)
{
path.insert(curElem);
curElem = reachability.predecessors[curElem];
curElem = reachability.predecessors[curElem.toInt()];
}
return std::make_pair(path, reachability.distances[dest]);
return std::make_pair(path, reachability.distances[dest.toInt()]);
}
bool CBattleInfoCallback::battleIsInsideWalls(BattleHex from) const
@ -176,7 +173,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) + " and " + std::to_string(dest) + ") received in battleHasPenaltyOnLine!" );
throw std::runtime_error("Invalid hex (" + std::to_string(from.toInt()) + " and " + std::to_string(dest.toInt()) + ") received in battleHasPenaltyOnLine!" );
auto isTileBlocked = [&](BattleHex tile)
{
@ -225,7 +222,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
auto obstacles = battleGetAllObstaclesOnPos(hex, false);
if(hex != BattleHex::GATE_BRIDGE || (battleIsGatePassable()))
if(hex.toInt() != BattleHex::GATE_BRIDGE || (battleIsGatePassable()))
for(const auto & obst : obstacles)
if(obst->obstacleType == CObstacleInstance::MOAT)
pathHasMoat |= true;
@ -786,7 +783,7 @@ DamageEstimation CBattleInfoCallback::battleEstimateDamage(const battle::Unit *
{
RETURN_IF_NOT_BATTLE({});
auto reachability = battleGetDistances(attacker, attacker->getPosition());
int movementRange = attackerPosition.isValid() ? reachability[attackerPosition] : 0;
int movementRange = attackerPosition.isValid() ? reachability[attackerPosition.toInt()] : 0;
return battleEstimateDamage(attacker, defender, movementRange, retaliationDmg);
}
@ -955,8 +952,8 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
//removing accessibility for side columns of hexes
for(int y = 0; y < GameConstants::BFIELD_HEIGHT; y++)
{
ret[BattleHex(GameConstants::BFIELD_WIDTH - 1, y)] = EAccessibility::SIDE_COLUMN;
ret[BattleHex(0, y)] = EAccessibility::SIDE_COLUMN;
ret[BattleHex(GameConstants::BFIELD_WIDTH - 1, y).toInt()] = EAccessibility::SIDE_COLUMN;
ret[BattleHex(0, y).toInt()] = EAccessibility::SIDE_COLUMN;
}
//special battlefields with logically unavailable tiles
@ -965,7 +962,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
if(bFieldType != BattleField::NONE)
{
for(auto hex : bFieldType.getInfo()->impassableHexes)
ret[hex] = EAccessibility::UNAVAILABLE;
ret[hex.toInt()] = EAccessibility::UNAVAILABLE;
}
//gate -> should be before stacks
@ -990,14 +987,14 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
{
for(auto hex : unit->getHexes())
if(hex.isAvailable()) //towers can have <0 pos; we don't also want to overwrite side columns
ret[hex] = EAccessibility::ALIVE_STACK;
ret[hex.toInt()] = EAccessibility::ALIVE_STACK;
}
//obstacles
for(const auto &obst : battleGetAllObstacles())
{
for(auto hex : obst->getBlockedTiles())
ret[hex] = EAccessibility::OBSTACLE;
ret[hex.toInt()] = EAccessibility::OBSTACLE;
}
//walls
@ -1020,7 +1017,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
for(const auto & elem : lockedIfNotDestroyed)
{
if(battleGetWallState(elem.first) != EWallState::DESTROYED)
ret[elem.second] = EAccessibility::DESTRUCTIBLE_WALL;
ret[elem.second.toInt()] = EAccessibility::DESTRUCTIBLE_WALL;
}
}
@ -1029,15 +1026,15 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() 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();
for(auto hex : *accessibleHexes)
for(auto hex : accessibleHexes)
if(hex.isValid())
ret[hex] = EAccessibility::ACCESSIBLE;
ret[hex.toInt()] = EAccessibility::ACCESSIBLE;
return ret;
}
@ -1062,7 +1059,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
//first element
hexq.push(params.startPosition);
ret.distances[params.startPosition] = 0;
ret.distances[params.startPosition.toInt()] = 0;
std::array<bool, GameConstants::BFIELD_SIZE> accessibleCache{};
for(int hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
@ -1077,7 +1074,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
if(isInObstacle(curHex, obstacles, checkParams))
continue;
const int costToNeighbour = ret.distances.at(curHex) + 1;
const int costToNeighbour = ret.distances.at(curHex.toInt()) + 1;
for(BattleHex neighbour : curHex.getNeighbouringTiles())
{
@ -1085,7 +1082,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
if(params.bypassEnemyStacks)
{
auto enemyToBypass = params.destructibleEnemyTurns.at(neighbour);
auto enemyToBypass = params.destructibleEnemyTurns.at(neighbour.toInt());
if(enemyToBypass >= 0)
{
@ -1093,13 +1090,13 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
}
}
const int costFoundSoFar = ret.distances[neighbour];
const int costFoundSoFar = ret.distances[neighbour.toInt()];
if(accessibleCache[neighbour] && costToNeighbour + additionalCost < costFoundSoFar)
if(accessibleCache[neighbour.toInt()] && costToNeighbour + additionalCost < costFoundSoFar)
{
hexq.push(neighbour);
ret.distances[neighbour] = costToNeighbour + additionalCost;
ret.predecessors[neighbour] = curHex;
ret.distances[neighbour.toInt()] = costToNeighbour + additionalCost;
ret.predecessors[neighbour.toInt()] = curHex;
}
}
}
@ -1181,7 +1178,7 @@ std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(
for(BattleHex hex : avHexes)
if(CStack::isMeleeAttackPossible(closest, st, hex))
{
DistStack hlp = {reachability.distances[hex], hex, st};
DistStack hlp = {reachability.distances[hex.toInt()], hex, st};
stackPairs.push_back(hlp);
}
}
@ -1272,9 +1269,12 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Pa
return getFlyingReachability(params);
else
{
auto accessibility = getAccessibility(params.knownAccessible);
auto accessibility = getAccessibility(* params.knownAccessible);
accessibility.destructibleEnemyTurns = & params.destructibleEnemyTurns;
accessibility.destructibleEnemyTurns = std::shared_ptr<const TBattlefieldTurnsArray>(
& params.destructibleEnemyTurns,
[](const TBattlefieldTurnsArray *) { }
);
return makeBFS(accessibility, params);
}
@ -1283,7 +1283,7 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Pa
ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityInfo::Parameters & params) const
{
ReachabilityInfo ret;
ret.accessibility = getAccessibility(params.knownAccessible);
ret.accessibility = getAccessibility(* params.knownAccessible);
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
{
@ -1326,9 +1326,9 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
AttackableTiles at;
RETURN_IF_NOT_BATTLE(at);
BattleHex attackOriginHex = (attackerPos != BattleHex::INVALID) ? attackerPos : attacker->getPosition(); //real or hypothetical (cursor) position
BattleHex attackOriginHex = (attackerPos.toInt() != BattleHex::INVALID) ? attackerPos : attacker->getPosition(); //real or hypothetical (cursor) position
defenderPos = (defenderPos != BattleHex::INVALID) ? defenderPos : defender->getPosition(); //real or hypothetical (cursor) position
defenderPos = (defenderPos.toInt() != BattleHex::INVALID) ? defenderPos : defender->getPosition(); //real or hypothetical (cursor) position
bool reverse = isToReverse(attacker, defender, attackerPos, defenderPos);
if(reverse && attacker->doubleWide())

View File

@ -162,7 +162,7 @@ public:
ReachabilityInfo getReachability(const ReachabilityInfo::Parameters & params) const;
AccessibilityInfo getAccessibility() const;
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;
BattleHex getAvailableHex(const CreatureID & creID, BattleSide side, int initialPos = -1) const; //find place for adding new stack

View File

@ -113,7 +113,9 @@ void CObstacleInstance::serializeJson(JsonSerializeFormat & handler)
animationYOffset -= 42;
//We need only a subset of obstacle info for correct render
handler.serializeInt("position", pos);
si16 posValue = pos.toInt();
handler.serializeInt("position", posValue);
pos = posValue;
handler.serializeInt("animationYOffset", animationYOffset);
handler.serializeBool("hidden", hidden);
handler.serializeBool("needAnimationOffsetFix", needAnimationOffsetFix);
@ -188,7 +190,9 @@ void SpellCreatedObstacle::fromInfo(const ObstacleChanges & info)
void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
{
handler.serializeInt("spell", ID);
handler.serializeInt("position", pos);
si16 posValue = pos.toInt();
handler.serializeInt("position", posValue);
pos = posValue;
handler.serializeInt("turnsRemaining", turnsRemaining);
handler.serializeInt("casterSpellPower", casterSpellPower);
@ -215,9 +219,9 @@ void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
JsonArraySerializer customSizeJson = handler.enterArray("customSize");
customSizeJson.syncSize(customSize, JsonNode::JsonType::DATA_INTEGER);
BattleHex hex;
for(size_t index = 0; index < customSizeJson.size(); index++)
{
si16 hex = customSize.at(index).toInt();
customSizeJson.serializeInt(index, hex);
customSize.set(index, hex);
}

View File

@ -798,7 +798,9 @@ void CUnitState::serializeJson(JsonSerializeFormat & handler)
handler.serializeInt("cloneID", cloneID);
handler.serializeInt("position", position);
si16 posValue = position.toInt();
handler.serializeInt("position", posValue);
position = posValue;
}
void CUnitState::localInit(const IUnitEnvironment * env_)

View File

@ -45,7 +45,7 @@ DamageRange DamageCalculator::getBaseDamageSingle() const
const auto * town = callback.battleGetDefendedTown();
assert(town);
switch(info.attacker->getPosition())
switch(info.attacker->getPosition().toInt())
{
case BattleHex::CASTLE_CENTRAL_TOWER:
return town->getKeepDamageRange();

View File

@ -33,7 +33,7 @@ ReachabilityInfo::ReachabilityInfo()
bool ReachabilityInfo::isReachable(BattleHex hex) const
{
return distances[hex] < INFINITE_DIST;
return distances[hex.toInt()] < INFINITE_DIST;
}
uint32_t ReachabilityInfo::distToNearestNeighbour(
@ -46,9 +46,9 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
{
for(auto & n : targetHex.getNeighbouringTiles())
{
if(distances[n] < ret)
if(distances[n.toInt()] < ret)
{
ret = distances[n];
ret = distances[n.toInt()];
if(chosenHex)
*chosenHex = n;
}

View File

@ -33,7 +33,7 @@ struct DLL_LINKAGE ReachabilityInfo
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
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)
TBattlefieldTurnsArray destructibleEnemyTurns; // how many turns it is needed to kill enemy on specific hex (index <=> hex)
BattleHex startPosition; //assumed position of stack
BattleSide perspective = BattleSide::ALL_KNOWING; //some obstacles (eg. quicksands) may be invisible for some side

View File

@ -53,7 +53,7 @@ const IBonusBearer* Unit::getBonusBearer() const
const BattleHexArray & Unit::getSurroundingHexes(BattleHex assumedPosition) const
{
BattleHex hex = (assumedPosition != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
BattleHex hex = (assumedPosition.toInt() != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
return getSurroundingHexes(hex, doubleWide(), unitSide());
}
@ -63,7 +63,7 @@ const BattleHexArray & Unit::getSurroundingHexes(BattleHex position, bool twoHex
if(!twoHex)
return position.getNeighbouringTiles();
return position.getNeighbouringTilesDblWide(side);
return position.getNeighbouringTilesDoubleWide(side);
}
BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
@ -112,8 +112,8 @@ const BattleHexArray & Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleS
static BattleHexArray::ArrayOfBattleHexArrays precomputed[4];
int index = side == BattleSide::ATTACKER ? 0 : 2;
if(!precomputed[index + twoHex][assumedPos].empty())
return precomputed[index + twoHex][assumedPos];
if(!precomputed[index + twoHex][assumedPos.toInt()].empty())
return precomputed[index + twoHex][assumedPos.toInt()];
// first run, compute
@ -123,9 +123,9 @@ const BattleHexArray & Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleS
if(twoHex)
hexes.insert(occupiedHex(assumedPos, twoHex, side));
precomputed[index + twoHex][assumedPos] = std::move(hexes);
precomputed[index + twoHex][assumedPos.toInt()] = std::move(hexes);
return precomputed[index + twoHex][assumedPos];
return precomputed[index + twoHex][assumedPos.toInt()];
}
BattleHex Unit::occupiedHex() const
@ -143,9 +143,9 @@ BattleHex Unit::occupiedHex(BattleHex assumedPos, bool twoHex, BattleSide side)
if(twoHex)
{
if(side == BattleSide::ATTACKER)
return assumedPos - 1;
return assumedPos.toInt() - 1;
else
return assumedPos + 1;
return assumedPos.toInt() + 1;
}
else
{
@ -201,7 +201,9 @@ void UnitInfo::serializeJson(JsonSerializeFormat & handler)
handler.serializeInt("count", count);
handler.serializeId("type", type, CreatureID(CreatureID::NONE));
handler.serializeInt("side", side);
handler.serializeInt("position", position);
si16 positionValue = position.toInt();
handler.serializeInt("position", positionValue);
position = positionValue;
handler.serializeBool("summoned", summoned);
}

View File

@ -84,11 +84,14 @@ public:
bool isTurret() const;
virtual bool isValidTarget(bool allowDead = false) const = 0; //non-turret non-ghost stacks (can be attacked or be object of magic effect)
virtual bool isHypnotized() const = 0;
virtual bool isClone() const = 0;
virtual bool hasClone() const = 0;
virtual bool canCast() const = 0;
virtual bool isCaster() const = 0;
virtual bool canShootBlocked() const = 0;
virtual bool canShoot() const = 0;
virtual bool isShooter() const = 0;
@ -112,8 +115,6 @@ public:
virtual BattleHex getPosition() const = 0;
virtual void setPosition(BattleHex hex) = 0;
virtual int32_t getInitiative(int turn = 0) const = 0;
virtual bool canMove(int turn = 0) const = 0; //if stack can move
virtual bool defended(int turn = 0) const = 0;
virtual bool moved(int turn = 0) const = 0; //if stack was already moved this turn

View File

@ -238,7 +238,7 @@ JsonNode UnitOnHexLimiter::toJsonNode() const
root["type"].String() = "UNIT_ON_HEXES";
for(auto hex : applicableHexes)
root["parameters"].Vector().emplace_back(hex);
root["parameters"].Vector().emplace_back(hex.toInt());
return root;
}

View File

@ -517,7 +517,7 @@ BattleHexArray BattleSpellMechanics::spellRangeInHexes(BattleHex centralHex) con
for(auto & elem : rng)
{
std::set<ui16> curLayer = getInRange(centralHex, elem, elem);
std::set<ui16> curLayer = getInRange(centralHex.toInt(), elem, elem);
//adding obtained hexes
for(const auto & curLayer_it : curLayer)
ret.insert(curLayer_it);

View File

@ -754,7 +754,14 @@ std::vector<int> CSpellHandler::spellRangeInHexes(std::string input) const
}
}
return std::vector<int>(ret.begin(), ret.end());
std::vector<int> result;
result.reserve(ret.size());
std::transform(ret.begin(), ret.end(), std::back_inserter(result),
[](BattleHex hex) { return hex.toInt(); }
);
return result;
}
std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index)

View File

@ -95,7 +95,7 @@ void Catapult::applyMassive(ServerCallback * server, const Mechanics * m) const
CatapultAttack::AttackInfo newInfo;
newInfo.damageDealt = getRandomDamage(server);
newInfo.attackedPart = target;
newInfo.destinationTile = m->battle()->wallPartToBattleHex(target);
newInfo.destinationTile = m->battle()->wallPartToBattleHex(target).toInt();
ca.attackedParts.push_back(newInfo);
attackInfo = ca.attackedParts.end() - 1;
}
@ -137,7 +137,7 @@ void Catapult::applyTargeted(ServerCallback * server, const Mechanics * m, const
CatapultAttack::AttackInfo attack;
attack.attackedPart = actualTarget;
attack.destinationTile = m->battle()->wallPartToBattleHex(actualTarget);
attack.destinationTile = m->battle()->wallPartToBattleHex(actualTarget).toInt();
attack.damageDealt = getRandomDamage(server);
CatapultAttack ca; //package for clients

View File

@ -43,7 +43,7 @@ void Clone::apply(ServerCallback * server, const Mechanics * m, const EffectTarg
if(clonedStack->getCount() < 1)
continue;
auto hex = m->battle()->getAvailableHex(clonedStack->creatureId(), m->casterSide, clonedStack->getPosition());
auto hex = m->battle()->getAvailableHex(clonedStack->creatureId(), m->casterSide, clonedStack->getPosition().toInt());
if(!hex.isValid())
{

View File

@ -65,7 +65,7 @@ void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const Effe
continue;
}
auto hex = m->battle()->getAvailableHex(targetStack->creatureId(), m->casterSide, targetStack->getPosition());
auto hex = m->battle()->getAvailableHex(targetStack->creatureId(), m->casterSide, targetStack->getPosition().toInt());
if(!hex.isValid())
{

View File

@ -43,9 +43,9 @@ static void serializeMoatHexes(JsonSerializeFormat & handler, const std::string
JsonArraySerializer inner = outer.enterArray(outerIndex);
inner.syncSize(moatHexes.at(outerIndex), JsonNode::JsonType::DATA_INTEGER);
BattleHex hex;
for(size_t innerIndex = 0; innerIndex < inner.size(); innerIndex++)
{
si16 hex = moatHexes.at(outerIndex).at(innerIndex).toInt();
inner.serializeInt(innerIndex, hex);
moatHexes.at(outerIndex).set(innerIndex, hex);
}

View File

@ -223,7 +223,7 @@ EffectTarget UnitEffect::transformTargetByChain(const Mechanics * m, const Targe
effectTarget.emplace_back();
for(auto hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide()))
possibleHexes.erase(hex);
possibleHexes.erase(hex.toInt());
if(possibleHexes.empty())
break;

View File

@ -98,7 +98,7 @@ bool LuaSpellEffect::applicable(Problem & problem, const Mechanics * m, const Ef
for(const auto & dest : target)
{
JsonNode targetData;
targetData.Vector().emplace_back(static_cast<si16>(dest.hexValue));
targetData.Vector().emplace_back(dest.hexValue.toInt());
if(dest.unitValue)
targetData.Vector().emplace_back(dest.unitValue->unitId());
@ -141,7 +141,7 @@ void LuaSpellEffect::apply(ServerCallback * server, const Mechanics * m, const E
for(const auto & dest : target)
{
JsonNode targetData;
targetData.Vector().emplace_back(static_cast<si16>(dest.hexValue));
targetData.Vector().emplace_back(dest.hexValue.toInt());
if(dest.unitValue)
targetData.Vector().emplace_back(dest.unitValue->unitId());

View File

@ -84,7 +84,7 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_ApplicableOnLeftSideOfField)
BattleHex hex(2,2);
JsonNode first;
first.Vector().emplace_back(static_cast<si16>(hex));
first.Vector().emplace_back(hex.toInt());
first.Vector().emplace_back();
JsonNode targets;
@ -113,7 +113,7 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_NotApplicableOnRightSideOfField)
BattleHex hex(11,2);
JsonNode first;
first.Vector().emplace_back(static_cast<si16>(hex));
first.Vector().emplace_back(hex.toInt());
first.Vector().emplace_back(-1);
JsonNode targets;
@ -138,13 +138,13 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_ApplyMoveUnit)
BattleHex hex1(11,2);
JsonNode unit;
unit.Vector().emplace_back(static_cast<si16>(hex1));
unit.Vector().emplace_back(hex1.toInt());
unit.Vector().emplace_back(42);
BattleHex hex2(5,4);
JsonNode destination;
destination.Vector().emplace_back(static_cast<si16>(hex2));
destination.Vector().emplace_back(hex2.toInt());
destination.Vector().emplace_back(-1);
JsonNode targets;

View File

@ -154,11 +154,11 @@ TEST_F(LuaSpellEffectTest, ApplicableTargetRedirected)
JsonNode first;
first.Vector().emplace_back(static_cast<si16>(hex1));
first.Vector().emplace_back(hex1.toInt());
first.Vector().emplace_back(id1);
JsonNode second;
second.Vector().emplace_back(static_cast<si16>(hex2));
second.Vector().emplace_back(hex2.toInt());
second.Vector().emplace_back(-1);
JsonNode targets;
@ -193,7 +193,7 @@ TEST_F(LuaSpellEffectTest, ApplyRedirected)
subject->apply(&serverMock, &mechanicsMock, target);
JsonNode first;
first.Vector().emplace_back(static_cast<si16>(hex1));
first.Vector().emplace_back(hex1.toInt());
first.Vector().emplace_back(id1);
JsonNode targets;