mirror of
https://github.com/vcmi/vcmi.git
synced 2025-12-01 23:12:49 +02:00
Stepping into an obstacle, such as moat will now prevent unit from
attacking
This commit is contained in:
@@ -143,8 +143,8 @@ bool BattleActionProcessor::doWalkAction(const CBattleInfoCallback & battle, con
|
||||
return false;
|
||||
}
|
||||
|
||||
int walkedTiles = moveStack(battle, ba.stackNumber, target.at(0).hexValue); //move
|
||||
if (!walkedTiles)
|
||||
auto movementResult = moveStack(battle, ba.stackNumber, target.at(0).hexValue); //move
|
||||
if (movementResult.invalidRequest)
|
||||
{
|
||||
gameHandler->complain("Stack failed movement!");
|
||||
return false;
|
||||
@@ -229,14 +229,20 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
|
||||
}
|
||||
|
||||
BattleHex startingPos = stack->getPosition();
|
||||
int distance = moveStack(battle, ba.stackNumber, attackPos);
|
||||
const auto movementResult = moveStack(battle, ba.stackNumber, attackPos);
|
||||
|
||||
logGlobal->trace("%s will attack %s", stack->nodeName(), destinationStack->nodeName());
|
||||
|
||||
if(stack->getPosition() != attackPos && !(stack->doubleWide() && (stack->getPosition() == attackPos.cloneInDirection(stack->destShiftDir(), false))) )
|
||||
if (movementResult.invalidRequest)
|
||||
{
|
||||
gameHandler->complain("Stack failed attack - unable to reach target!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(movementResult.obstacleHit)
|
||||
{
|
||||
// we were not able to reach destination tile, nor occupy specified hex
|
||||
// abort attack attempt, but treat this case as legal - we may have stepped onto a quicksands/mine
|
||||
// abort attack attempt, but treat this case as legal - we have stepped onto a quicksands/mine
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -285,7 +291,7 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
|
||||
//move can cause death, eg. by walking into the moat, first strike can cause death or paralysis/petrification
|
||||
if(stack->alive() && !stack->hasBonusOfType(BonusType::NOT_ACTIVE) && destinationStack->alive())
|
||||
{
|
||||
makeAttack(battle, stack, destinationStack, (i ? 0 : distance), destinationTile, i==0, false, false);//no distance travelled on second attack
|
||||
makeAttack(battle, stack, destinationStack, (i ? 0 : movementResult.distance), destinationTile, i==0, false, false);//no distance travelled on second attack
|
||||
|
||||
if(!ferocityApplied && stack->hasBonusOfType(BonusType::FEROCITY))
|
||||
{
|
||||
@@ -615,10 +621,8 @@ bool BattleActionProcessor::makeBattleActionImpl(const CBattleInfoCallback & bat
|
||||
return result;
|
||||
}
|
||||
|
||||
int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int stack, BattleHex dest)
|
||||
BattleActionProcessor::MovementResult BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int stack, BattleHex dest)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
const CStack *curStack = battle.battleGetStackByID(stack);
|
||||
const CStack *stackAtEnd = battle.battleGetStackByPos(dest);
|
||||
|
||||
@@ -632,7 +636,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
|
||||
auto start = curStack->getPosition();
|
||||
if (start == dest)
|
||||
return 0;
|
||||
return { 0, false, false };
|
||||
|
||||
//initing necessary tables
|
||||
auto accessibility = battle.getAccessibility(curStack);
|
||||
@@ -654,7 +658,7 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
if((stackAtEnd && stackAtEnd!=curStack && stackAtEnd->alive()) || !accessibility.accessible(dest, curStack))
|
||||
{
|
||||
gameHandler->complain("Given destination is not accessible!");
|
||||
return 0;
|
||||
return { 0, false, true };
|
||||
}
|
||||
|
||||
bool canUseGate = false;
|
||||
@@ -667,8 +671,8 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
}
|
||||
|
||||
std::pair< BattleHexArray, int > path = battle.getPath(start, dest, curStack);
|
||||
|
||||
ret = path.second;
|
||||
int8_t passedHexes = path.second;
|
||||
bool movementSuccess = true;
|
||||
|
||||
int creSpeed = curStack->getMovementRange(0);
|
||||
|
||||
@@ -805,15 +809,10 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
}
|
||||
}
|
||||
|
||||
bool stackIsMoving = true;
|
||||
|
||||
while(stackIsMoving)
|
||||
while(movementSuccess)
|
||||
{
|
||||
if (v<tilesToMove)
|
||||
{
|
||||
logGlobal->error("Movement terminated abnormally");
|
||||
break;
|
||||
}
|
||||
throw std::runtime_error("Movement terminated abnormally");
|
||||
|
||||
bool gateStateChanging = false;
|
||||
//special handling for opening gate on from starting hex
|
||||
@@ -865,9 +864,9 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
//we don't handle obstacle at the destination tile -> it's handled separately in the if at the end
|
||||
if (curStack->getPosition() != dest)
|
||||
{
|
||||
if(stackIsMoving && start != curStack->getPosition())
|
||||
if(movementSuccess && start != curStack->getPosition())
|
||||
{
|
||||
stackIsMoving = battle.handleObstacleTriggersForUnit(*gameHandler->spellEnv, *curStack, passed);
|
||||
movementSuccess &= battle.handleObstacleTriggersForUnit(*gameHandler->spellEnv, *curStack, passed);
|
||||
passed.insert(curStack->getPosition());
|
||||
if(curStack->doubleWide())
|
||||
passed.insert(curStack->occupiedHex());
|
||||
@@ -894,8 +893,10 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//movement finished normally: we reached destination
|
||||
stackIsMoving = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//handle last hex separately for deviation
|
||||
@@ -908,9 +909,9 @@ int BattleActionProcessor::moveStack(const CBattleInfoCallback & battle, int sta
|
||||
if(dest == start) //If dest is equal to start, then we should handle obstacles for it anyway
|
||||
passed.clear(); //Just empty passed, obstacles will handled automatically
|
||||
//handling obstacle on the final field (separate, because it affects both flying and walking stacks)
|
||||
battle.handleObstacleTriggersForUnit(*gameHandler->spellEnv, *curStack, passed);
|
||||
movementSuccess &= battle.handleObstacleTriggersForUnit(*gameHandler->spellEnv, *curStack, passed);
|
||||
|
||||
return ret;
|
||||
return { passedHexes, !movementSuccess, false };
|
||||
}
|
||||
|
||||
void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const CStack * attacker, const CStack * defender, int distance, const BattleHex & targetHex, bool first, bool ranged, bool counter)
|
||||
|
||||
Reference in New Issue
Block a user