1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Fix dragon breath & fire shield

This commit is contained in:
Ivan Savenko 2022-12-21 18:04:54 +02:00
parent d0f259bbf7
commit b423b3fa6b
3 changed files with 18 additions and 28 deletions

View File

@ -415,6 +415,10 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
if (attackedInfo.indirectAttack)
continue;
// Another type of indirect attack - dragon breath
if (!CStack::isMeleeAttackPossible(attackedInfo.attacker, attackedInfo.defender))
continue;
// defender need to face in direction opposited to out attacker
bool needsReverse = shouldAttackFacingRight(attackedInfo.attacker, attackedInfo.defender) == facingRight(attackedInfo.defender);

View File

@ -1376,10 +1376,9 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const battl
AttackableTiles at;
RETURN_IF_NOT_BATTLE(at);
const int WN = GameConstants::BFIELD_WIDTH;
BattleHex hex = (attackerPos != BattleHex::INVALID) ? attackerPos : attacker->getPosition(); //real or hypothetical (cursor) position
auto defender = battleGetUnitByPos(hex, true);
auto defender = battleGetUnitByPos(destinationTile, true);
if (!defender)
return at; // can't attack thin air
@ -1427,34 +1426,17 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const battl
}
else if(attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH))
{
int pos = BattleHex::mutualPosition(destinationTile, hex);
if(pos > -1) //only adjacent hexes are subject of dragon breath calculation
auto direction = BattleHex::mutualPosition(hex, destinationTile);
if(direction != BattleHex::NONE) //only adjacent hexes are subject of dragon breath calculation
{
std::vector<BattleHex> hexes; //only one, in fact
int pseudoVector = destinationTile.hex - hex;
switch(pseudoVector)
{
case 1:
case -1:
BattleHex::checkAndPush(destinationTile.hex + pseudoVector, hexes);
break;
case WN: //17 //left-down or right-down
case -WN: //-17 //left-up or right-up
case WN + 1: //18 //right-down
case -WN + 1: //-16 //right-up
BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : -1), hexes);
break;
case WN - 1: //16 //left-down
case -WN - 1: //-18 //left-up
BattleHex::checkAndPush(destinationTile.hex + pseudoVector + (((hex / WN) % 2) ? 1 : 0), hexes);
break;
}
for(BattleHex tile : hexes)
BattleHex nextHex = destinationTile.cloneInDirection(direction, false);
if (nextHex.isValid())
{
//friendly stacks can also be damaged by Dragon Breath
auto st = battleGetUnitByPos(tile, true);
auto st = battleGetUnitByPos(nextHex, true);
if(st != nullptr)
at.friendlyCreaturePositions.insert(tile);
at.friendlyCreaturePositions.insert(nextHex);
}
}
}

View File

@ -1267,8 +1267,12 @@ int64_t CGameHandler::applyBattleEffects(BattleAttack & bat, std::shared_ptr<bat
bat.bsa.push_back(bsa); //add this stack to the list of victims after drain life has been calculated
//fire shield handling
if(!bat.shot() && !def->isClone() &&
def->hasBonusOfType(Bonus::FIRE_SHIELD) && !attackerState->hasBonusOfType(Bonus::FIRE_IMMUNITY))
if(!bat.shot() &&
!def->isClone() &&
def->hasBonusOfType(Bonus::FIRE_SHIELD) &&
!attackerState->hasBonusOfType(Bonus::FIRE_IMMUNITY) &&
CStack::isMeleeAttackPossible(attackerState.get(), def) // attacked needs to be adjacent to defender for fire shield to trigger (e.g. Dragon Breath attack)
)
{
//TODO: use damage with bonus but without penalties
auto fireShieldDamage = (std::min<int64_t>(def->getAvailableHealth(), bsa.damageAmount) * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100;