mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +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:
@@ -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;
|
||||||
const BattleHexArray & hexes = attacker->getSurroundingHexes(hex);
|
const auto & hexes = attacker->getSurroundingHexes(hex);
|
||||||
for(BattleHex tile : hexes)
|
for(BattleHex tile : hexes)
|
||||||
{
|
{
|
||||||
auto st = state->battleGetUnitByPos(tile, true);
|
auto st = state->battleGetUnitByPos(tile, true);
|
||||||
|
|||||||
@@ -214,8 +214,8 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
|||||||
bestAttack.attackerState->unitType()->getJsonKey(),
|
bestAttack.attackerState->unitType()->getJsonKey(),
|
||||||
bestAttack.affectedUnits[0]->unitType()->getJsonKey(),
|
bestAttack.affectedUnits[0]->unitType()->getJsonKey(),
|
||||||
bestAttack.affectedUnits[0]->getCount(),
|
bestAttack.affectedUnits[0]->getCount(),
|
||||||
(int)bestAttack.from,
|
bestAttack.from.toInt(),
|
||||||
(int)bestAttack.attack.attacker->getPosition(),
|
bestAttack.attack.attacker->getPosition().toInt(),
|
||||||
bestAttack.attack.chargeDistance,
|
bestAttack.attack.chargeDistance,
|
||||||
bestAttack.attack.attacker->getMovementRange(0),
|
bestAttack.attack.attacker->getMovementRange(0),
|
||||||
bestAttack.defenderDamageReduce,
|
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 reachability = cb->getBattle(battleID)->getReachability(stack);
|
||||||
auto avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(reachability, stack, false);
|
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
|
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();
|
BattleHex bestNeighbour = hexes.front();
|
||||||
|
|
||||||
if(reachability.distances[bestNeighbour] > GameConstants::BFIELD_SIZE)
|
if(reachability.distances[bestNeighbour.toInt()] > GameConstants::BFIELD_SIZE)
|
||||||
{
|
{
|
||||||
logAi->trace("No reachable hexes.");
|
logAi->trace("No reachable hexes.");
|
||||||
return BattleAction::makeDefend(stack);
|
return BattleAction::makeDefend(stack);
|
||||||
@@ -468,7 +468,7 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, BattleHexAr
|
|||||||
return moveOrAttack(stack, currentDest, targets);
|
return moveOrAttack(stack, currentDest, targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDest = reachability.predecessors[currentDest];
|
currentDest = reachability.predecessors[currentDest.toInt()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
bool attemptCastingSpell(const CStack * stack);
|
bool attemptCastingSpell(const CStack * stack);
|
||||||
bool canCastSpell();
|
bool canCastSpell();
|
||||||
std::optional<PossibleSpellcast> findBestCreatureSpell(const CStack * stack);
|
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;
|
std::vector<BattleHex> getBrokenWallMoatHexes() const;
|
||||||
bool hasWorkingTowers() const;
|
bool hasWorkingTowers() const;
|
||||||
void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only
|
void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ ReachabilityInfo getReachabilityWithEnemyBypass(
|
|||||||
|
|
||||||
for(auto & hex : unit->getHexes())
|
for(auto & hex : unit->getHexes())
|
||||||
if(hex.isAvailable()) //towers can have <0 pos; we don't also want to overwrite side columns
|
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;
|
params.bypassEnemyStacks = true;
|
||||||
@@ -415,11 +415,11 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
|
|
||||||
for(BattleHex enemyHex : enemy->getAttackableHexes(activeStack))
|
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);
|
auto defenderToBypass = hb->battleGetUnitByPos(enemyHex);
|
||||||
|
|
||||||
@@ -429,7 +429,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
logAi->trace("Found target to bypass at %d", enemyHex.hex);
|
logAi->trace("Found target to bypass at %d", enemyHex.hex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto attackHex = dists.predecessors[enemyHex];
|
auto attackHex = dists.predecessors[enemyHex.toInt()];
|
||||||
auto baiBypass = BattleAttackInfo(activeStack, defenderToBypass, 0, cb->battleCanShoot(activeStack));
|
auto baiBypass = BattleAttackInfo(activeStack, defenderToBypass, 0, cb->battleCanShoot(activeStack));
|
||||||
auto attackBypass = AttackPossibility::evaluate(baiBypass, attackHex, damageCache, hb);
|
auto attackBypass = AttackPossibility::evaluate(baiBypass, attackHex, damageCache, hb);
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ MoveTarget BattleExchangeEvaluator::findMoveTowardsUnreachable(
|
|||||||
|
|
||||||
auto bypassScore = calculateExchange(
|
auto bypassScore = calculateExchange(
|
||||||
attackBypass,
|
attackBypass,
|
||||||
dists.distances[attackHex],
|
dists.distances[attackHex.toInt()],
|
||||||
targets,
|
targets,
|
||||||
damageCache,
|
damageCache,
|
||||||
hb,
|
hb,
|
||||||
@@ -916,8 +916,7 @@ void BattleExchangeEvaluator::updateReachabilityMap(std::shared_ptr<HypotheticBa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); ++hex)
|
||||||
for(BattleHex hex = BattleHex::TOP_LEFT; hex.isValid(); hex = hex + 1)
|
|
||||||
{
|
{
|
||||||
reachabilityMap[hex] = getOneTurnReachableUnits(0, 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);
|
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);
|
const battle::Unit * hexStack = cb->battleGetUnitByPos(hex);
|
||||||
|
|
||||||
@@ -962,7 +961,7 @@ std::vector<const battle::Unit *> BattleExchangeEvaluator::getOneTurnReachableUn
|
|||||||
{
|
{
|
||||||
for(BattleHex neighbour : hex.getNeighbouringTiles())
|
for(BattleHex neighbour : hex.getNeighbouringTiles())
|
||||||
{
|
{
|
||||||
reachable = unitReachability.distances.at(neighbour) <= radius;
|
reachable = unitReachability.distances.at(neighbour.toInt()) <= radius;
|
||||||
|
|
||||||
if(reachable) break;
|
if(reachable) break;
|
||||||
}
|
}
|
||||||
@@ -1009,12 +1008,12 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
|
|||||||
auto unitReachability = turnBattle.getReachability(unit);
|
auto unitReachability = turnBattle.getReachability(unit);
|
||||||
auto unitSpeed = unit->getMovementRange(turn); // Cached value, to avoid performance hit
|
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 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);
|
const battle::Unit * hexStack = turnBattle.battleGetUnitByPos(hex);
|
||||||
|
|
||||||
@@ -1023,7 +1022,7 @@ bool BattleExchangeEvaluator::checkPositionBlocksOurStacks(HypotheticBattle & hb
|
|||||||
enemyUnit = true;
|
enemyUnit = true;
|
||||||
for(BattleHex neighbour : hex.getNeighbouringTiles())
|
for(BattleHex neighbour : hex.getNeighbouringTiles())
|
||||||
{
|
{
|
||||||
reachable = unitReachability.distances.at(neighbour) <= unitSpeed;
|
reachable = unitReachability.distances.at(neighbour.toInt()) <= unitSpeed;
|
||||||
|
|
||||||
if(reachable) break;
|
if(reachable) break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ PotentialTargets::PotentialTargets(
|
|||||||
|
|
||||||
auto GenerateAttackInfo = [&](bool shooting, BattleHex hex) -> AttackPossibility
|
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);
|
auto bai = BattleAttackInfo(attackerInfo, defender, distance, shooting);
|
||||||
|
|
||||||
return AttackPossibility::evaluate(bai, hex, damageCache, state);
|
return AttackPossibility::evaluate(bai, hex, damageCache, state);
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
|
|||||||
|
|
||||||
std::sort(hexes.begin(), hexes.end(), [&](BattleHex h1, BattleHex h2) -> bool
|
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)
|
for(auto hex : hexes)
|
||||||
@@ -313,7 +313,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
|
|||||||
|
|
||||||
BattleHex bestneighbour = hexes.front();
|
BattleHex bestneighbour = hexes.front();
|
||||||
|
|
||||||
if(reachability.distances[bestneighbour] > GameConstants::BFIELD_SIZE)
|
if(reachability.distances[bestneighbour.toInt()] > GameConstants::BFIELD_SIZE)
|
||||||
{
|
{
|
||||||
return BattleAction::makeDefend(stack);
|
return BattleAction::makeDefend(stack);
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
|
|||||||
return BattleAction::makeMove(stack, currentDest);
|
return BattleAction::makeMove(stack, currentDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDest = reachability.predecessors[currentDest];
|
currentDest = reachability.predecessors[currentDest.toInt()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -522,7 +522,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
|
|||||||
{
|
{
|
||||||
const auto * attacker = owner.stacksController->getActiveStack();
|
const auto * attacker = owner.stacksController->getActiveStack();
|
||||||
BattleHex attackFromHex = owner.fieldController->fromWhichHexAttack(targetHex);
|
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;
|
DamageEstimation retaliation;
|
||||||
BattleAttackInfo attackInfo(attacker, targetStack, distance, false );
|
BattleAttackInfo attackInfo(attacker, targetStack, distance, false );
|
||||||
DamageEstimation estimation = owner.getBattle()->battleEstimateDamage(attackInfo, &retaliation);
|
DamageEstimation estimation = owner.getBattle()->battleEstimateDamage(attackInfo, &retaliation);
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ AttackAnimation::AttackAnimation(BattleInterface & owner, const CStack *attacker
|
|||||||
attackingStack(attacker)
|
attackingStack(attacker)
|
||||||
{
|
{
|
||||||
assert(attackingStack && "attackingStack is nullptr in CBattleAttack::CBattleAttack !\n");
|
assert(attackingStack && "attackingStack is nullptr in CBattleAttack::CBattleAttack !\n");
|
||||||
attackingStackPosBeforeReturn = attackingStack->getPosition();
|
attackingStackPosBeforeReturn = attackingStack->getPosition().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
HittedAnimation::HittedAnimation(BattleInterface & owner, const CStack * stack)
|
HittedAnimation::HittedAnimation(BattleInterface & owner, const CStack * stack)
|
||||||
|
|||||||
@@ -839,7 +839,7 @@ void BattleFieldController::updateAccessibleHexes()
|
|||||||
|
|
||||||
bool BattleFieldController::stackCountOutsideHex(const BattleHex & number) const
|
bool BattleFieldController::stackCountOutsideHex(const BattleHex & number) const
|
||||||
{
|
{
|
||||||
return stackCountOutsideHexes[number];
|
return stackCountOutsideHexes[number.toInt()];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::showAll(Canvas & to)
|
void BattleFieldController::showAll(Canvas & to)
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTo
|
|||||||
|
|
||||||
const CCreature *BattleSiegeController::getTurretCreature(BattleHex position) const
|
const CCreature *BattleSiegeController::getTurretCreature(BattleHex position) const
|
||||||
{
|
{
|
||||||
switch (position)
|
switch (position.toInt())
|
||||||
{
|
{
|
||||||
case BattleHex::CASTLE_CENTRAL_TOWER:
|
case BattleHex::CASTLE_CENTRAL_TOWER:
|
||||||
return town->fortificationsLevel().citadelShooter.toCreature();
|
return town->fortificationsLevel().citadelShooter.toCreature();
|
||||||
@@ -195,14 +195,14 @@ const CCreature *BattleSiegeController::getTurretCreature(BattleHex position) co
|
|||||||
return town->fortificationsLevel().lowerTowerShooter.toCreature();
|
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
|
Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) const
|
||||||
{
|
{
|
||||||
// Turret positions are read out of the config/wall_pos.txt
|
// Turret positions are read out of the config/wall_pos.txt
|
||||||
int posID = 0;
|
int posID = 0;
|
||||||
switch (position)
|
switch (position.toInt())
|
||||||
{
|
{
|
||||||
case BattleHex::CASTLE_CENTRAL_TOWER: // keep creature
|
case BattleHex::CASTLE_CENTRAL_TOWER: // keep creature
|
||||||
posID = EWallVisual::CREATURE_KEEP;
|
posID = EWallVisual::CREATURE_KEEP;
|
||||||
|
|||||||
@@ -252,8 +252,8 @@ BattleHexArray CStack::meleeAttackHexes(const battle::Unit * attacker, const bat
|
|||||||
if (!defenderPos.isValid())
|
if (!defenderPos.isValid())
|
||||||
defenderPos = defender->getPosition();
|
defenderPos = defender->getPosition();
|
||||||
|
|
||||||
BattleHex otherAttackerPos = attackerPos + (attacker->unitSide() == BattleSide::ATTACKER ? -1 : 1);
|
BattleHex otherAttackerPos = attackerPos.toInt() + (attacker->unitSide() == BattleSide::ATTACKER ? -1 : 1);
|
||||||
BattleHex otherDefenderPos = defenderPos + (defender->unitSide() == BattleSide::ATTACKER ? -1 : 1);
|
BattleHex otherDefenderPos = defenderPos.toInt() + (defender->unitSide() == BattleSide::ATTACKER ? -1 : 1);
|
||||||
|
|
||||||
if(BattleHex::mutualPosition(attackerPos, defenderPos) >= 0) //front <=> front
|
if(BattleHex::mutualPosition(attackerPos, defenderPos) >= 0) //front <=> front
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ BattleHexArray ObstacleInfo::getBlocked(BattleHex hex) const
|
|||||||
BattleHexArray ret;
|
BattleHexArray ret;
|
||||||
for(int offset : blockedTiles)
|
for(int offset : blockedTiles)
|
||||||
{
|
{
|
||||||
BattleHex toBlock = hex + offset;
|
BattleHex toBlock = hex.toInt() + offset;
|
||||||
if((hex.getY() & 1) && !(toBlock.getY() & 1))
|
if((hex.getY() & 1) && !(toBlock.getY() & 1))
|
||||||
toBlock += BattleHex::LEFT;
|
toBlock += BattleHex::LEFT;
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
bool AccessibilityInfo::tileAccessibleWithGate(BattleHex tile, BattleSide side) const
|
bool AccessibilityInfo::tileAccessibleWithGate(BattleHex tile, BattleSide side) const
|
||||||
{
|
{
|
||||||
//at(otherHex) != EAccessibility::ACCESSIBLE && (at(otherHex) != EAccessibility::GATE || side != BattleSide::DEFENDER)
|
//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(accessibility == EAccessibility::ALIVE_STACK)
|
||||||
{
|
{
|
||||||
if(!destructibleEnemyTurns)
|
if(!destructibleEnemyTurns)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return destructibleEnemyTurns->at(tile) >= 0;
|
return destructibleEnemyTurns->at(tile.toInt()) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(accessibility != EAccessibility::ACCESSIBLE)
|
if(accessibility != EAccessibility::ACCESSIBLE)
|
||||||
|
|||||||
@@ -32,10 +32,11 @@ enum class EAccessibility
|
|||||||
|
|
||||||
|
|
||||||
using TAccessibilityArray = std::array<EAccessibility, GameConstants::BFIELD_SIZE>;
|
using TAccessibilityArray = std::array<EAccessibility, GameConstants::BFIELD_SIZE>;
|
||||||
|
using TBattlefieldTurnsArray = std::array<int8_t, GameConstants::BFIELD_SIZE>;
|
||||||
|
|
||||||
struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
|
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:
|
public:
|
||||||
bool accessible(BattleHex tile, const battle::Unit * stack) const; //checks for both tiles if stack is double wide
|
bool accessible(BattleHex tile, const battle::Unit * stack) const; //checks for both tiles if stack is double wide
|
||||||
|
|||||||
@@ -48,24 +48,24 @@ BattleHex BattleHex::getClosestTile(BattleSide side, BattleHex initialPos, const
|
|||||||
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
|
return (bestTile != closestTiles.end()) ? *bestTile : BattleHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
const BattleHexArray & BattleHex::getAllNeighbouringTiles() const
|
const BattleHexArray & BattleHex::getAllNeighbouringTiles() const noexcept
|
||||||
{
|
{
|
||||||
return BattleHexArray::getAllNeighbouringTiles(*this);
|
return BattleHexArray::getAllNeighbouringTiles(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BattleHexArray & BattleHex::getNeighbouringTiles() const
|
const BattleHexArray & BattleHex::getNeighbouringTiles() const noexcept
|
||||||
{
|
{
|
||||||
return BattleHexArray::getNeighbouringTiles(*this);
|
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)
|
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
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ namespace GameConstants
|
|||||||
|
|
||||||
class BattleHexArray;
|
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
|
class DLL_LINKAGE BattleHex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -68,10 +69,10 @@ public:
|
|||||||
BOTTOM
|
BOTTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
BattleHex()
|
BattleHex() noexcept
|
||||||
: hex(INVALID)
|
: hex(INVALID)
|
||||||
{}
|
{}
|
||||||
BattleHex(si16 _hex)
|
BattleHex(si16 _hex) noexcept
|
||||||
: hex(_hex)
|
: hex(_hex)
|
||||||
{}
|
{}
|
||||||
BattleHex(si16 x, si16 y)
|
BattleHex(si16 x, si16 y)
|
||||||
@@ -82,17 +83,13 @@ public:
|
|||||||
{
|
{
|
||||||
setXY(xy);
|
setXY(xy);
|
||||||
}
|
}
|
||||||
operator si16() const
|
|
||||||
{
|
|
||||||
return hex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isValid() const
|
[[nodiscard]] bool isValid() const noexcept
|
||||||
{
|
{
|
||||||
return hex >= 0 && hex < GameConstants::BFIELD_SIZE;
|
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;
|
return isValid() && getX() > 0 && getX() < GameConstants::BFIELD_WIDTH - 1;
|
||||||
}
|
}
|
||||||
@@ -123,17 +120,17 @@ public:
|
|||||||
setXY(xy.first, xy.second);
|
setXY(xy.first, xy.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
si16 getX() const
|
[[nodiscard]] si16 getX() const noexcept
|
||||||
{
|
{
|
||||||
return hex % GameConstants::BFIELD_WIDTH;
|
return hex % GameConstants::BFIELD_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
si16 getY() const
|
[[nodiscard]] si16 getY() const noexcept
|
||||||
{
|
{
|
||||||
return hex / GameConstants::BFIELD_WIDTH;
|
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());
|
return std::make_pair(getX(), getY());
|
||||||
}
|
}
|
||||||
@@ -171,24 +168,14 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHex & operator+=(EDir dir)
|
[[nodiscard]] BattleHex cloneInDirection(EDir dir, bool hasToBeValid = true) const
|
||||||
{
|
|
||||||
return moveInDirection(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
BattleHex operator+(EDir dir) const
|
|
||||||
{
|
|
||||||
return cloneInDirection(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
BattleHex cloneInDirection(EDir dir, bool hasToBeValid = true) const
|
|
||||||
{
|
{
|
||||||
BattleHex result(hex);
|
BattleHex result(hex);
|
||||||
result.moveInDirection(dir, hasToBeValid);
|
result.moveInDirection(dir, hasToBeValid);
|
||||||
return result;
|
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 y1 = hex1.getY();
|
||||||
int y2 = hex2.getY();
|
int y2 = hex2.getY();
|
||||||
@@ -205,15 +192,15 @@ public:
|
|||||||
return std::abs(xDst) + std::abs(yDst);
|
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
|
//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};
|
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())
|
for(auto dir : hexagonalDirections())
|
||||||
if(hex2 == hex1.cloneInDirection(dir, false))
|
if(hex2 == hex1.cloneInDirection(dir, false))
|
||||||
@@ -222,13 +209,59 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// get (precomputed) all possible surrounding tiles
|
/// get (precomputed) all possible surrounding tiles
|
||||||
const BattleHexArray & getAllNeighbouringTiles() const;
|
[[nodiscard]] const BattleHexArray & getAllNeighbouringTiles() const noexcept;
|
||||||
|
|
||||||
/// get (precomputed) only valid and available surrounding tiles
|
/// 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
|
/// 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>
|
template <typename Handler>
|
||||||
void serialize(Handler & h)
|
void serialize(Handler & h)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ void BattleHexArray::erase(iterator first, iterator last) noexcept
|
|||||||
{
|
{
|
||||||
for(auto it = first; it != last && it != internalStorage.end(); ++it)
|
for(auto it = first; it != last && it != internalStorage.end(); ++it)
|
||||||
{
|
{
|
||||||
presenceFlags[*it] = 0;
|
presenceFlags[it->toInt()] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internalStorage.erase(first, last);
|
internalStorage.erase(first, last);
|
||||||
@@ -43,7 +43,7 @@ void BattleHexArray::erase(iterator first, iterator last) noexcept
|
|||||||
void BattleHexArray::clear() noexcept
|
void BattleHexArray::clear() noexcept
|
||||||
{
|
{
|
||||||
for(auto hex : internalStorage)
|
for(auto hex : internalStorage)
|
||||||
presenceFlags[hex] = 0;
|
presenceFlags[hex.toInt()] = 0;
|
||||||
|
|
||||||
internalStorage.clear();
|
internalStorage.clear();
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateAllNeighbouri
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringTilesDblWide(BattleSide side)
|
BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringTilesDoubleWide(BattleSide side)
|
||||||
{
|
{
|
||||||
ArrayOfBattleHexArrays ret;
|
ArrayOfBattleHexArrays ret;
|
||||||
|
|
||||||
@@ -123,10 +123,10 @@ BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::precalculateNeighbouringT
|
|||||||
|
|
||||||
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::neighbouringTiles = precalculateNeighbouringTiles();
|
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::neighbouringTiles = precalculateNeighbouringTiles();
|
||||||
const BattleHexArray::ArrayOfBattleHexArrays BattleHexArray::allNeighbouringTiles = precalculateAllNeighbouringTiles();
|
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::ATTACKER, precalculateNeighbouringTilesDoubleWide(BattleSide::ATTACKER) },
|
||||||
{ BattleSide::DEFENDER, precalculateNeighbouringTilesDblWide(BattleSide::DEFENDER) }
|
{ BattleSide::DEFENDER, precalculateNeighbouringTilesDoubleWide(BattleSide::DEFENDER) }
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
{
|
{
|
||||||
if(tile.isAvailable() && !contains(tile))
|
if(tile.isAvailable() && !contains(tile))
|
||||||
{
|
{
|
||||||
presenceFlags[tile] = 1;
|
presenceFlags[tile.toInt()] = true;
|
||||||
internalStorage.emplace_back(tile);
|
internalStorage.emplace_back(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ public:
|
|||||||
if(contains(hex))
|
if(contains(hex))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
presenceFlags[hex] = 1;
|
presenceFlags[hex.toInt()] = true;
|
||||||
internalStorage.emplace_back(hex);
|
internalStorage.emplace_back(hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
if(contains(hex))
|
if(contains(hex))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
presenceFlags[hex] = 1;
|
presenceFlags[hex.toInt()] = true;
|
||||||
internalStorage[index] = hex;
|
internalStorage[index] = hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
if(contains(hex))
|
if(contains(hex))
|
||||||
return pos;
|
return pos;
|
||||||
|
|
||||||
presenceFlags[hex] = 1;
|
presenceFlags[hex.toInt()] = true;
|
||||||
return internalStorage.insert(pos, hex);
|
return internalStorage.insert(pos, hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public:
|
|||||||
void erase(iterator first, iterator last) noexcept;
|
void erase(iterator first, iterator last) noexcept;
|
||||||
inline void pop_back() noexcept
|
inline void pop_back() noexcept
|
||||||
{
|
{
|
||||||
presenceFlags[internalStorage.back()] = 0;
|
presenceFlags[internalStorage.back().toInt()] = false;
|
||||||
internalStorage.pop_back();
|
internalStorage.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,33 +158,33 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// get (precomputed) all possible surrounding tiles
|
/// get (precomputed) all possible surrounding tiles
|
||||||
static const BattleHexArray & getAllNeighbouringTiles(BattleHex hex)
|
static const BattleHexArray & getAllNeighbouringTiles(BattleHex hex) noexcept
|
||||||
{
|
{
|
||||||
assert(hex.isValid());
|
assert(hex.isValid());
|
||||||
|
|
||||||
return allNeighbouringTiles[hex];
|
return allNeighbouringTiles[hex.toInt()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get (precomputed) only valid and available surrounding tiles
|
/// get (precomputed) only valid and available surrounding tiles
|
||||||
static const BattleHexArray & getNeighbouringTiles(BattleHex hex)
|
static const BattleHexArray & getNeighbouringTiles(BattleHex hex) noexcept
|
||||||
{
|
{
|
||||||
assert(hex.isValid());
|
assert(hex.isValid());
|
||||||
|
|
||||||
return neighbouringTiles[hex];
|
return neighbouringTiles[hex.toInt()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get (precomputed) only valid and available surrounding tiles for double wide creatures
|
/// 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));
|
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
|
[[nodiscard]] inline bool contains(BattleHex hex) const noexcept
|
||||||
{
|
{
|
||||||
if(hex.isValid())
|
if(hex.isValid())
|
||||||
return presenceFlags[hex];
|
return presenceFlags[hex.toInt()];
|
||||||
/*
|
/*
|
||||||
if(!isTower(hex))
|
if(!isTower(hex))
|
||||||
logGlobal->warn("BattleHexArray::contains( %d ) - invalid BattleHex!", hex);
|
logGlobal->warn("BattleHexArray::contains( %d ) - invalid BattleHex!", hex);
|
||||||
@@ -198,10 +198,10 @@ public:
|
|||||||
void serialize(Serializer & s)
|
void serialize(Serializer & s)
|
||||||
{
|
{
|
||||||
s & internalStorage;
|
s & internalStorage;
|
||||||
if(!internalStorage.empty() && presenceFlags[internalStorage.front()] == 0)
|
if(!s.saving)
|
||||||
{
|
{
|
||||||
for(auto hex : internalStorage)
|
for(auto hex : internalStorage)
|
||||||
presenceFlags[hex] = 1;
|
presenceFlags[hex.toInt()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,11 +307,11 @@ private:
|
|||||||
|
|
||||||
static const ArrayOfBattleHexArrays neighbouringTiles;
|
static const ArrayOfBattleHexArrays neighbouringTiles;
|
||||||
static const ArrayOfBattleHexArrays allNeighbouringTiles;
|
static const ArrayOfBattleHexArrays allNeighbouringTiles;
|
||||||
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDblWide;
|
static const std::map<BattleSide, ArrayOfBattleHexArrays> neighbouringTilesDoubleWide;
|
||||||
|
|
||||||
static ArrayOfBattleHexArrays precalculateNeighbouringTiles();
|
static ArrayOfBattleHexArrays precalculateNeighbouringTiles();
|
||||||
static ArrayOfBattleHexArrays precalculateAllNeighbouringTiles();
|
static ArrayOfBattleHexArrays precalculateAllNeighbouringTiles();
|
||||||
static ArrayOfBattleHexArrays precalculateNeighbouringTilesDblWide(BattleSide side);
|
static ArrayOfBattleHexArrays precalculateNeighbouringTilesDoubleWide(BattleSide side);
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ CStack * BattleInfo::generateNewStack(uint32_t id, const CStackInstance & base,
|
|||||||
assert(!owner.isValidPlayer() || (base.armyObj && base.armyObj->tempOwner == owner));
|
assert(!owner.isValidPlayer() || (base.armyObj && base.armyObj->tempOwner == owner));
|
||||||
|
|
||||||
auto * ret = new CStack(&base, owner, id, side, slot);
|
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);
|
stacks.push_back(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -264,7 +264,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
|
|||||||
|
|
||||||
for(BattleHex blocked : obi.getBlocked(pos))
|
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;
|
return false;
|
||||||
if(blockedTiles.contains(blocked))
|
if(blockedTiles.contains(blocked))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -43,19 +43,15 @@ static BattleHex lineToWallHex(int line) //returns hex with wall in given line (
|
|||||||
|
|
||||||
static bool sameSideOfWall(BattleHex pos1, BattleHex pos2)
|
static bool sameSideOfWall(BattleHex pos1, BattleHex pos2)
|
||||||
{
|
{
|
||||||
const int wallInStackLine = lineToWallHex(pos1.getY());
|
const bool stackLeft = pos1 < lineToWallHex(pos1.getY());
|
||||||
const int wallInDestLine = lineToWallHex(pos2.getY());
|
const bool destLeft = pos2 < lineToWallHex(pos2.getY());
|
||||||
|
|
||||||
const bool stackLeft = pos1 < wallInStackLine;
|
|
||||||
const bool destLeft = pos2 < wallInDestLine;
|
|
||||||
|
|
||||||
return stackLeft == destLeft;
|
return stackLeft == destLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isInsideWalls(BattleHex pos)
|
static bool isInsideWalls(BattleHex pos)
|
||||||
{
|
{
|
||||||
const int wallInStackLine = lineToWallHex(pos.getY());
|
return lineToWallHex(pos.getY()) < pos;
|
||||||
return wallInStackLine < pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parts of wall
|
// parts of wall
|
||||||
@@ -79,9 +75,10 @@ static const std::pair<int, EWallPart> wallParts[] =
|
|||||||
|
|
||||||
static EWallPart hexToWallPart(BattleHex hex)
|
static EWallPart hexToWallPart(BattleHex hex)
|
||||||
{
|
{
|
||||||
|
si16 hexValue = hex.toInt();
|
||||||
for(const auto & elem : wallParts)
|
for(const auto & elem : wallParts)
|
||||||
{
|
{
|
||||||
if(elem.first == hex)
|
if(elem.first == hexValue)
|
||||||
return elem.second;
|
return elem.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +148,7 @@ std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(BattleHex start, B
|
|||||||
{
|
{
|
||||||
auto reachability = getReachability(stack);
|
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);
|
return std::make_pair(BattleHexArray(), 0);
|
||||||
}
|
}
|
||||||
@@ -162,10 +159,10 @@ std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(BattleHex start, B
|
|||||||
while(curElem != start)
|
while(curElem != start)
|
||||||
{
|
{
|
||||||
path.insert(curElem);
|
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
|
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
|
bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest, bool checkWall, bool checkMoat) const
|
||||||
{
|
{
|
||||||
if (!from.isAvailable() || !dest.isAvailable())
|
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)
|
auto isTileBlocked = [&](BattleHex tile)
|
||||||
{
|
{
|
||||||
@@ -225,7 +222,7 @@ bool CBattleInfoCallback::battleHasPenaltyOnLine(BattleHex from, BattleHex dest,
|
|||||||
|
|
||||||
auto obstacles = battleGetAllObstaclesOnPos(hex, false);
|
auto obstacles = battleGetAllObstaclesOnPos(hex, false);
|
||||||
|
|
||||||
if(hex != BattleHex::GATE_BRIDGE || (battleIsGatePassable()))
|
if(hex.toInt() != BattleHex::GATE_BRIDGE || (battleIsGatePassable()))
|
||||||
for(const auto & obst : obstacles)
|
for(const auto & obst : obstacles)
|
||||||
if(obst->obstacleType == CObstacleInstance::MOAT)
|
if(obst->obstacleType == CObstacleInstance::MOAT)
|
||||||
pathHasMoat |= true;
|
pathHasMoat |= true;
|
||||||
@@ -786,7 +783,7 @@ DamageEstimation CBattleInfoCallback::battleEstimateDamage(const battle::Unit *
|
|||||||
{
|
{
|
||||||
RETURN_IF_NOT_BATTLE({});
|
RETURN_IF_NOT_BATTLE({});
|
||||||
auto reachability = battleGetDistances(attacker, attacker->getPosition());
|
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);
|
return battleEstimateDamage(attacker, defender, movementRange, retaliationDmg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -955,8 +952,8 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
|
|||||||
//removing accessibility for side columns of hexes
|
//removing accessibility for side columns of hexes
|
||||||
for(int y = 0; y < GameConstants::BFIELD_HEIGHT; y++)
|
for(int y = 0; y < GameConstants::BFIELD_HEIGHT; y++)
|
||||||
{
|
{
|
||||||
ret[BattleHex(GameConstants::BFIELD_WIDTH - 1, y)] = EAccessibility::SIDE_COLUMN;
|
ret[BattleHex(GameConstants::BFIELD_WIDTH - 1, y).toInt()] = EAccessibility::SIDE_COLUMN;
|
||||||
ret[BattleHex(0, y)] = EAccessibility::SIDE_COLUMN;
|
ret[BattleHex(0, y).toInt()] = EAccessibility::SIDE_COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
//special battlefields with logically unavailable tiles
|
//special battlefields with logically unavailable tiles
|
||||||
@@ -965,7 +962,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
|
|||||||
if(bFieldType != BattleField::NONE)
|
if(bFieldType != BattleField::NONE)
|
||||||
{
|
{
|
||||||
for(auto hex : bFieldType.getInfo()->impassableHexes)
|
for(auto hex : bFieldType.getInfo()->impassableHexes)
|
||||||
ret[hex] = EAccessibility::UNAVAILABLE;
|
ret[hex.toInt()] = EAccessibility::UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//gate -> should be before stacks
|
//gate -> should be before stacks
|
||||||
@@ -990,14 +987,14 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
|
|||||||
{
|
{
|
||||||
for(auto hex : unit->getHexes())
|
for(auto hex : unit->getHexes())
|
||||||
if(hex.isAvailable()) //towers can have <0 pos; we don't also want to overwrite side columns
|
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
|
//obstacles
|
||||||
for(const auto &obst : battleGetAllObstacles())
|
for(const auto &obst : battleGetAllObstacles())
|
||||||
{
|
{
|
||||||
for(auto hex : obst->getBlockedTiles())
|
for(auto hex : obst->getBlockedTiles())
|
||||||
ret[hex] = EAccessibility::OBSTACLE;
|
ret[hex.toInt()] = EAccessibility::OBSTACLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//walls
|
//walls
|
||||||
@@ -1020,7 +1017,7 @@ AccessibilityInfo CBattleInfoCallback::getAccessibility() const
|
|||||||
for(const auto & elem : lockedIfNotDestroyed)
|
for(const auto & elem : lockedIfNotDestroyed)
|
||||||
{
|
{
|
||||||
if(battleGetWallState(elem.first) != EWallState::DESTROYED)
|
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
|
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.toInt()] = EAccessibility::ACCESSIBLE;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1062,7 +1059,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
|
|||||||
|
|
||||||
//first element
|
//first element
|
||||||
hexq.push(params.startPosition);
|
hexq.push(params.startPosition);
|
||||||
ret.distances[params.startPosition] = 0;
|
ret.distances[params.startPosition.toInt()] = 0;
|
||||||
|
|
||||||
std::array<bool, GameConstants::BFIELD_SIZE> accessibleCache{};
|
std::array<bool, GameConstants::BFIELD_SIZE> accessibleCache{};
|
||||||
for(int hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
for(int hex = 0; hex < GameConstants::BFIELD_SIZE; hex++)
|
||||||
@@ -1077,7 +1074,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
|
|||||||
if(isInObstacle(curHex, obstacles, checkParams))
|
if(isInObstacle(curHex, obstacles, checkParams))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const int costToNeighbour = ret.distances.at(curHex) + 1;
|
const int costToNeighbour = ret.distances.at(curHex.toInt()) + 1;
|
||||||
|
|
||||||
for(BattleHex neighbour : curHex.getNeighbouringTiles())
|
for(BattleHex neighbour : curHex.getNeighbouringTiles())
|
||||||
{
|
{
|
||||||
@@ -1085,7 +1082,7 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo & accessib
|
|||||||
|
|
||||||
if(params.bypassEnemyStacks)
|
if(params.bypassEnemyStacks)
|
||||||
{
|
{
|
||||||
auto enemyToBypass = params.destructibleEnemyTurns.at(neighbour);
|
auto enemyToBypass = params.destructibleEnemyTurns.at(neighbour.toInt());
|
||||||
|
|
||||||
if(enemyToBypass >= 0)
|
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);
|
hexq.push(neighbour);
|
||||||
ret.distances[neighbour] = costToNeighbour + additionalCost;
|
ret.distances[neighbour.toInt()] = costToNeighbour + additionalCost;
|
||||||
ret.predecessors[neighbour] = curHex;
|
ret.predecessors[neighbour.toInt()] = curHex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1181,7 +1178,7 @@ std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(
|
|||||||
for(BattleHex hex : avHexes)
|
for(BattleHex hex : avHexes)
|
||||||
if(CStack::isMeleeAttackPossible(closest, st, hex))
|
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);
|
stackPairs.push_back(hlp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1272,9 +1269,12 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Pa
|
|||||||
return getFlyingReachability(params);
|
return getFlyingReachability(params);
|
||||||
else
|
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);
|
return makeBFS(accessibility, params);
|
||||||
}
|
}
|
||||||
@@ -1283,7 +1283,7 @@ ReachabilityInfo CBattleInfoCallback::getReachability(const ReachabilityInfo::Pa
|
|||||||
ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityInfo::Parameters & params) const
|
ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityInfo::Parameters & params) const
|
||||||
{
|
{
|
||||||
ReachabilityInfo ret;
|
ReachabilityInfo ret;
|
||||||
ret.accessibility = getAccessibility(params.knownAccessible);
|
ret.accessibility = getAccessibility(* params.knownAccessible);
|
||||||
|
|
||||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
||||||
{
|
{
|
||||||
@@ -1326,9 +1326,9 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(
|
|||||||
AttackableTiles at;
|
AttackableTiles at;
|
||||||
RETURN_IF_NOT_BATTLE(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);
|
bool reverse = isToReverse(attacker, defender, attackerPos, defenderPos);
|
||||||
if(reverse && attacker->doubleWide())
|
if(reverse && attacker->doubleWide())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -113,7 +113,9 @@ void CObstacleInstance::serializeJson(JsonSerializeFormat & handler)
|
|||||||
animationYOffset -= 42;
|
animationYOffset -= 42;
|
||||||
|
|
||||||
//We need only a subset of obstacle info for correct render
|
//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.serializeInt("animationYOffset", animationYOffset);
|
||||||
handler.serializeBool("hidden", hidden);
|
handler.serializeBool("hidden", hidden);
|
||||||
handler.serializeBool("needAnimationOffsetFix", needAnimationOffsetFix);
|
handler.serializeBool("needAnimationOffsetFix", needAnimationOffsetFix);
|
||||||
@@ -188,7 +190,9 @@ void SpellCreatedObstacle::fromInfo(const ObstacleChanges & info)
|
|||||||
void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
|
void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
|
||||||
{
|
{
|
||||||
handler.serializeInt("spell", ID);
|
handler.serializeInt("spell", ID);
|
||||||
handler.serializeInt("position", pos);
|
si16 posValue = pos.toInt();
|
||||||
|
handler.serializeInt("position", posValue);
|
||||||
|
pos = posValue;
|
||||||
|
|
||||||
handler.serializeInt("turnsRemaining", turnsRemaining);
|
handler.serializeInt("turnsRemaining", turnsRemaining);
|
||||||
handler.serializeInt("casterSpellPower", casterSpellPower);
|
handler.serializeInt("casterSpellPower", casterSpellPower);
|
||||||
@@ -215,9 +219,9 @@ void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
|
|||||||
JsonArraySerializer customSizeJson = handler.enterArray("customSize");
|
JsonArraySerializer customSizeJson = handler.enterArray("customSize");
|
||||||
customSizeJson.syncSize(customSize, JsonNode::JsonType::DATA_INTEGER);
|
customSizeJson.syncSize(customSize, JsonNode::JsonType::DATA_INTEGER);
|
||||||
|
|
||||||
BattleHex hex;
|
|
||||||
for(size_t index = 0; index < customSizeJson.size(); index++)
|
for(size_t index = 0; index < customSizeJson.size(); index++)
|
||||||
{
|
{
|
||||||
|
si16 hex = customSize.at(index).toInt();
|
||||||
customSizeJson.serializeInt(index, hex);
|
customSizeJson.serializeInt(index, hex);
|
||||||
customSize.set(index, hex);
|
customSize.set(index, hex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -798,7 +798,9 @@ void CUnitState::serializeJson(JsonSerializeFormat & handler)
|
|||||||
|
|
||||||
handler.serializeInt("cloneID", cloneID);
|
handler.serializeInt("cloneID", cloneID);
|
||||||
|
|
||||||
handler.serializeInt("position", position);
|
si16 posValue = position.toInt();
|
||||||
|
handler.serializeInt("position", posValue);
|
||||||
|
position = posValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUnitState::localInit(const IUnitEnvironment * env_)
|
void CUnitState::localInit(const IUnitEnvironment * env_)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ DamageRange DamageCalculator::getBaseDamageSingle() const
|
|||||||
const auto * town = callback.battleGetDefendedTown();
|
const auto * town = callback.battleGetDefendedTown();
|
||||||
assert(town);
|
assert(town);
|
||||||
|
|
||||||
switch(info.attacker->getPosition())
|
switch(info.attacker->getPosition().toInt())
|
||||||
{
|
{
|
||||||
case BattleHex::CASTLE_CENTRAL_TOWER:
|
case BattleHex::CASTLE_CENTRAL_TOWER:
|
||||||
return town->getKeepDamageRange();
|
return town->getKeepDamageRange();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ ReachabilityInfo::ReachabilityInfo()
|
|||||||
|
|
||||||
bool ReachabilityInfo::isReachable(BattleHex hex) const
|
bool ReachabilityInfo::isReachable(BattleHex hex) const
|
||||||
{
|
{
|
||||||
return distances[hex] < INFINITE_DIST;
|
return distances[hex.toInt()] < INFINITE_DIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ReachabilityInfo::distToNearestNeighbour(
|
uint32_t ReachabilityInfo::distToNearestNeighbour(
|
||||||
@@ -46,9 +46,9 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
|
|||||||
{
|
{
|
||||||
for(auto & n : targetHex.getNeighbouringTiles())
|
for(auto & n : targetHex.getNeighbouringTiles())
|
||||||
{
|
{
|
||||||
if(distances[n] < ret)
|
if(distances[n.toInt()] < ret)
|
||||||
{
|
{
|
||||||
ret = distances[n];
|
ret = distances[n.toInt()];
|
||||||
if(chosenHex)
|
if(chosenHex)
|
||||||
*chosenHex = n;
|
*chosenHex = n;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ struct DLL_LINKAGE ReachabilityInfo
|
|||||||
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
|
||||||
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)
|
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
|
BattleHex startPosition; //assumed position of stack
|
||||||
BattleSide perspective = BattleSide::ALL_KNOWING; //some obstacles (eg. quicksands) may be invisible for some side
|
BattleSide perspective = BattleSide::ALL_KNOWING; //some obstacles (eg. quicksands) may be invisible for some side
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const IBonusBearer* Unit::getBonusBearer() const
|
|||||||
|
|
||||||
const 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.toInt() != BattleHex::INVALID) ? assumedPosition : getPosition(); //use hypothetical position
|
||||||
|
|
||||||
return getSurroundingHexes(hex, doubleWide(), unitSide());
|
return getSurroundingHexes(hex, doubleWide(), unitSide());
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ const BattleHexArray & Unit::getSurroundingHexes(BattleHex position, bool twoHex
|
|||||||
if(!twoHex)
|
if(!twoHex)
|
||||||
return position.getNeighbouringTiles();
|
return position.getNeighbouringTiles();
|
||||||
|
|
||||||
return position.getNeighbouringTilesDblWide(side);
|
return position.getNeighbouringTilesDoubleWide(side);
|
||||||
}
|
}
|
||||||
|
|
||||||
BattleHexArray Unit::getAttackableHexes(const Unit * attacker) const
|
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];
|
static BattleHexArray::ArrayOfBattleHexArrays precomputed[4];
|
||||||
int index = side == BattleSide::ATTACKER ? 0 : 2;
|
int index = side == BattleSide::ATTACKER ? 0 : 2;
|
||||||
|
|
||||||
if(!precomputed[index + twoHex][assumedPos].empty())
|
if(!precomputed[index + twoHex][assumedPos.toInt()].empty())
|
||||||
return precomputed[index + twoHex][assumedPos];
|
return precomputed[index + twoHex][assumedPos.toInt()];
|
||||||
|
|
||||||
// first run, compute
|
// first run, compute
|
||||||
|
|
||||||
@@ -123,9 +123,9 @@ const BattleHexArray & Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleS
|
|||||||
if(twoHex)
|
if(twoHex)
|
||||||
hexes.insert(occupiedHex(assumedPos, twoHex, side));
|
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
|
BattleHex Unit::occupiedHex() const
|
||||||
@@ -143,9 +143,9 @@ BattleHex Unit::occupiedHex(BattleHex assumedPos, bool twoHex, BattleSide side)
|
|||||||
if(twoHex)
|
if(twoHex)
|
||||||
{
|
{
|
||||||
if(side == BattleSide::ATTACKER)
|
if(side == BattleSide::ATTACKER)
|
||||||
return assumedPos - 1;
|
return assumedPos.toInt() - 1;
|
||||||
else
|
else
|
||||||
return assumedPos + 1;
|
return assumedPos.toInt() + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -201,7 +201,9 @@ void UnitInfo::serializeJson(JsonSerializeFormat & handler)
|
|||||||
handler.serializeInt("count", count);
|
handler.serializeInt("count", count);
|
||||||
handler.serializeId("type", type, CreatureID(CreatureID::NONE));
|
handler.serializeId("type", type, CreatureID(CreatureID::NONE));
|
||||||
handler.serializeInt("side", side);
|
handler.serializeInt("side", side);
|
||||||
handler.serializeInt("position", position);
|
si16 positionValue = position.toInt();
|
||||||
|
handler.serializeInt("position", positionValue);
|
||||||
|
position = positionValue;
|
||||||
handler.serializeBool("summoned", summoned);
|
handler.serializeBool("summoned", summoned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,11 +84,14 @@ public:
|
|||||||
bool isTurret() const;
|
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 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 isClone() const = 0;
|
||||||
virtual bool hasClone() const = 0;
|
virtual bool hasClone() const = 0;
|
||||||
|
|
||||||
virtual bool canCast() const = 0;
|
virtual bool canCast() const = 0;
|
||||||
virtual bool isCaster() const = 0;
|
virtual bool isCaster() const = 0;
|
||||||
|
virtual bool canShootBlocked() const = 0;
|
||||||
virtual bool canShoot() const = 0;
|
virtual bool canShoot() const = 0;
|
||||||
virtual bool isShooter() const = 0;
|
virtual bool isShooter() const = 0;
|
||||||
|
|
||||||
@@ -112,8 +115,6 @@ public:
|
|||||||
virtual BattleHex getPosition() const = 0;
|
virtual BattleHex getPosition() const = 0;
|
||||||
virtual void setPosition(BattleHex hex) = 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 canMove(int turn = 0) const = 0; //if stack can move
|
||||||
virtual bool defended(int turn = 0) const = 0;
|
virtual bool defended(int turn = 0) const = 0;
|
||||||
virtual bool moved(int turn = 0) const = 0; //if stack was already moved this turn
|
virtual bool moved(int turn = 0) const = 0; //if stack was already moved this turn
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ JsonNode UnitOnHexLimiter::toJsonNode() const
|
|||||||
|
|
||||||
root["type"].String() = "UNIT_ON_HEXES";
|
root["type"].String() = "UNIT_ON_HEXES";
|
||||||
for(auto hex : applicableHexes)
|
for(auto hex : applicableHexes)
|
||||||
root["parameters"].Vector().emplace_back(hex);
|
root["parameters"].Vector().emplace_back(hex.toInt());
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -517,7 +517,7 @@ BattleHexArray BattleSpellMechanics::spellRangeInHexes(BattleHex centralHex) con
|
|||||||
|
|
||||||
for(auto & elem : rng)
|
for(auto & elem : rng)
|
||||||
{
|
{
|
||||||
std::set<ui16> curLayer = getInRange(centralHex, elem, elem);
|
std::set<ui16> curLayer = getInRange(centralHex.toInt(), elem, elem);
|
||||||
//adding obtained hexes
|
//adding obtained hexes
|
||||||
for(const auto & curLayer_it : curLayer)
|
for(const auto & curLayer_it : curLayer)
|
||||||
ret.insert(curLayer_it);
|
ret.insert(curLayer_it);
|
||||||
|
|||||||
@@ -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)
|
std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index)
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ void Catapult::applyMassive(ServerCallback * server, const Mechanics * m) const
|
|||||||
CatapultAttack::AttackInfo newInfo;
|
CatapultAttack::AttackInfo newInfo;
|
||||||
newInfo.damageDealt = getRandomDamage(server);
|
newInfo.damageDealt = getRandomDamage(server);
|
||||||
newInfo.attackedPart = target;
|
newInfo.attackedPart = target;
|
||||||
newInfo.destinationTile = m->battle()->wallPartToBattleHex(target);
|
newInfo.destinationTile = m->battle()->wallPartToBattleHex(target).toInt();
|
||||||
ca.attackedParts.push_back(newInfo);
|
ca.attackedParts.push_back(newInfo);
|
||||||
attackInfo = ca.attackedParts.end() - 1;
|
attackInfo = ca.attackedParts.end() - 1;
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ void Catapult::applyTargeted(ServerCallback * server, const Mechanics * m, const
|
|||||||
|
|
||||||
CatapultAttack::AttackInfo attack;
|
CatapultAttack::AttackInfo attack;
|
||||||
attack.attackedPart = actualTarget;
|
attack.attackedPart = actualTarget;
|
||||||
attack.destinationTile = m->battle()->wallPartToBattleHex(actualTarget);
|
attack.destinationTile = m->battle()->wallPartToBattleHex(actualTarget).toInt();
|
||||||
attack.damageDealt = getRandomDamage(server);
|
attack.damageDealt = getRandomDamage(server);
|
||||||
|
|
||||||
CatapultAttack ca; //package for clients
|
CatapultAttack ca; //package for clients
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ void Clone::apply(ServerCallback * server, const Mechanics * m, const EffectTarg
|
|||||||
if(clonedStack->getCount() < 1)
|
if(clonedStack->getCount() < 1)
|
||||||
continue;
|
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())
|
if(!hex.isValid())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const Effe
|
|||||||
continue;
|
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())
|
if(!hex.isValid())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ static void serializeMoatHexes(JsonSerializeFormat & handler, const std::string
|
|||||||
JsonArraySerializer inner = outer.enterArray(outerIndex);
|
JsonArraySerializer inner = outer.enterArray(outerIndex);
|
||||||
inner.syncSize(moatHexes.at(outerIndex), JsonNode::JsonType::DATA_INTEGER);
|
inner.syncSize(moatHexes.at(outerIndex), JsonNode::JsonType::DATA_INTEGER);
|
||||||
|
|
||||||
BattleHex hex;
|
|
||||||
for(size_t innerIndex = 0; innerIndex < inner.size(); innerIndex++)
|
for(size_t innerIndex = 0; innerIndex < inner.size(); innerIndex++)
|
||||||
{
|
{
|
||||||
|
si16 hex = moatHexes.at(outerIndex).at(innerIndex).toInt();
|
||||||
inner.serializeInt(innerIndex, hex);
|
inner.serializeInt(innerIndex, hex);
|
||||||
moatHexes.at(outerIndex).set(innerIndex, hex);
|
moatHexes.at(outerIndex).set(innerIndex, hex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ EffectTarget UnitEffect::transformTargetByChain(const Mechanics * m, const Targe
|
|||||||
effectTarget.emplace_back();
|
effectTarget.emplace_back();
|
||||||
|
|
||||||
for(auto hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide()))
|
for(auto hex : battle::Unit::getHexes(unit->getPosition(), unit->doubleWide(), unit->unitSide()))
|
||||||
possibleHexes.erase(hex);
|
possibleHexes.erase(hex.toInt());
|
||||||
|
|
||||||
if(possibleHexes.empty())
|
if(possibleHexes.empty())
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ bool LuaSpellEffect::applicable(Problem & problem, const Mechanics * m, const Ef
|
|||||||
for(const auto & dest : target)
|
for(const auto & dest : target)
|
||||||
{
|
{
|
||||||
JsonNode targetData;
|
JsonNode targetData;
|
||||||
targetData.Vector().emplace_back(static_cast<si16>(dest.hexValue));
|
targetData.Vector().emplace_back(dest.hexValue.toInt());
|
||||||
|
|
||||||
if(dest.unitValue)
|
if(dest.unitValue)
|
||||||
targetData.Vector().emplace_back(dest.unitValue->unitId());
|
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)
|
for(const auto & dest : target)
|
||||||
{
|
{
|
||||||
JsonNode targetData;
|
JsonNode targetData;
|
||||||
targetData.Vector().emplace_back(static_cast<si16>(dest.hexValue));
|
targetData.Vector().emplace_back(dest.hexValue.toInt());
|
||||||
|
|
||||||
if(dest.unitValue)
|
if(dest.unitValue)
|
||||||
targetData.Vector().emplace_back(dest.unitValue->unitId());
|
targetData.Vector().emplace_back(dest.unitValue->unitId());
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_ApplicableOnLeftSideOfField)
|
|||||||
BattleHex hex(2,2);
|
BattleHex hex(2,2);
|
||||||
|
|
||||||
JsonNode first;
|
JsonNode first;
|
||||||
first.Vector().emplace_back(static_cast<si16>(hex));
|
first.Vector().emplace_back(hex.toInt());
|
||||||
first.Vector().emplace_back();
|
first.Vector().emplace_back();
|
||||||
|
|
||||||
JsonNode targets;
|
JsonNode targets;
|
||||||
@@ -113,7 +113,7 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_NotApplicableOnRightSideOfField)
|
|||||||
BattleHex hex(11,2);
|
BattleHex hex(11,2);
|
||||||
|
|
||||||
JsonNode first;
|
JsonNode first;
|
||||||
first.Vector().emplace_back(static_cast<si16>(hex));
|
first.Vector().emplace_back(hex.toInt());
|
||||||
first.Vector().emplace_back(-1);
|
first.Vector().emplace_back(-1);
|
||||||
|
|
||||||
JsonNode targets;
|
JsonNode targets;
|
||||||
@@ -138,13 +138,13 @@ TEST_F(LuaSpellEffectAPITest, DISABLED_ApplyMoveUnit)
|
|||||||
BattleHex hex1(11,2);
|
BattleHex hex1(11,2);
|
||||||
|
|
||||||
JsonNode unit;
|
JsonNode unit;
|
||||||
unit.Vector().emplace_back(static_cast<si16>(hex1));
|
unit.Vector().emplace_back(hex1.toInt());
|
||||||
unit.Vector().emplace_back(42);
|
unit.Vector().emplace_back(42);
|
||||||
|
|
||||||
BattleHex hex2(5,4);
|
BattleHex hex2(5,4);
|
||||||
|
|
||||||
JsonNode destination;
|
JsonNode destination;
|
||||||
destination.Vector().emplace_back(static_cast<si16>(hex2));
|
destination.Vector().emplace_back(hex2.toInt());
|
||||||
destination.Vector().emplace_back(-1);
|
destination.Vector().emplace_back(-1);
|
||||||
|
|
||||||
JsonNode targets;
|
JsonNode targets;
|
||||||
|
|||||||
@@ -154,11 +154,11 @@ TEST_F(LuaSpellEffectTest, ApplicableTargetRedirected)
|
|||||||
|
|
||||||
|
|
||||||
JsonNode first;
|
JsonNode first;
|
||||||
first.Vector().emplace_back(static_cast<si16>(hex1));
|
first.Vector().emplace_back(hex1.toInt());
|
||||||
first.Vector().emplace_back(id1);
|
first.Vector().emplace_back(id1);
|
||||||
|
|
||||||
JsonNode second;
|
JsonNode second;
|
||||||
second.Vector().emplace_back(static_cast<si16>(hex2));
|
second.Vector().emplace_back(hex2.toInt());
|
||||||
second.Vector().emplace_back(-1);
|
second.Vector().emplace_back(-1);
|
||||||
|
|
||||||
JsonNode targets;
|
JsonNode targets;
|
||||||
@@ -193,7 +193,7 @@ TEST_F(LuaSpellEffectTest, ApplyRedirected)
|
|||||||
subject->apply(&serverMock, &mechanicsMock, target);
|
subject->apply(&serverMock, &mechanicsMock, target);
|
||||||
|
|
||||||
JsonNode first;
|
JsonNode first;
|
||||||
first.Vector().emplace_back(static_cast<si16>(hex1));
|
first.Vector().emplace_back(hex1.toInt());
|
||||||
first.Vector().emplace_back(id1);
|
first.Vector().emplace_back(id1);
|
||||||
|
|
||||||
JsonNode targets;
|
JsonNode targets;
|
||||||
|
|||||||
Reference in New Issue
Block a user