1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Fix segfault / assertion failure during battle

The cause of the assertion failure at BattleStackAttacked::applyGs "at"
was shooting and casting some spell in handleAttackBeforeCasting() and
eventually killing the whole stack. Fix: filter dead stacks in the end of
handleAttackBeforeCasting().
This commit is contained in:
Vadim Markovtsev 2016-10-12 17:19:02 +02:00
parent 76ac9991ed
commit 6fe5f2a7f6
2 changed files with 14 additions and 7 deletions

View File

@ -3892,7 +3892,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
BattleAttack bat; BattleAttack bat;
prepareAttack(bat, stack, destinationStack, (i ? 0 : distance), ba.additionalInfo); //no distance travelled on second attack prepareAttack(bat, stack, destinationStack, (i ? 0 : distance), ba.additionalInfo); //no distance travelled on second attack
//prepareAttack(bat, stack, stackAtEnd, 0, ba.additionalInfo); //prepareAttack(bat, stack, stackAtEnd, 0, ba.additionalInfo);
handleAttackBeforeCasting(bat); //only before first attack handleAttackBeforeCasting(&bat); //only before first attack
sendAndApply(&bat); sendAndApply(&bat);
handleAfterAttackCasting(bat); handleAfterAttackCasting(bat);
} }
@ -3936,7 +3936,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
BattleAttack bat; BattleAttack bat;
bat.flags |= BattleAttack::SHOT; bat.flags |= BattleAttack::SHOT;
prepareAttack(bat, stack, destinationStack, 0, ba.destinationTile); prepareAttack(bat, stack, destinationStack, 0, ba.destinationTile);
handleAttackBeforeCasting(bat); handleAttackBeforeCasting(&bat);
sendAndApply(&bat); sendAndApply(&bat);
handleAfterAttackCasting(bat); handleAfterAttackCasting(bat);
} }
@ -5209,16 +5209,23 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
} }
} }
void CGameHandler::handleAttackBeforeCasting (const BattleAttack & bat) void CGameHandler::handleAttackBeforeCasting(BattleAttack *bat)
{ {
const CStack * attacker = gs->curB->battleGetStackByID(bat.stackAttacking); const CStack * attacker = gs->curB->battleGetStackByID(bat->stackAttacking);
attackCasting(bat, Bonus::SPELL_BEFORE_ATTACK, attacker); //no death stare / acid breath needed? attackCasting(*bat, Bonus::SPELL_BEFORE_ATTACK, attacker); //no death stare / acid breath needed?
// filter possibly dead stacks
bat->bsa.erase(std::remove_if(bat->bsa.begin(), bat->bsa.end(),
[this](const BattleStackAttacked &bsa)
{
return battleGetStackByID(bsa.stackAttacked) == nullptr;
}),
bat->bsa.end());
} }
void CGameHandler::handleAfterAttackCasting(const BattleAttack & bat) void CGameHandler::handleAfterAttackCasting(const BattleAttack & bat)
{ {
const CStack * attacker = gs->curB->battleGetStackByID(bat.stackAttacking); const CStack * attacker = gs->curB->battleGetStackByID(bat.stackAttacking);
if (!attacker) //could be already dead if (!attacker || bat.bsa.empty()) // can be already dead
return; return;
auto cast = [=](SpellID spellID, int power) auto cast = [=](SpellID spellID, int power)

View File

@ -279,7 +279,7 @@ public:
void run(bool resume); void run(bool resume);
void newTurn(); void newTurn();
void handleAttackBeforeCasting (const BattleAttack & bat); void handleAttackBeforeCasting(BattleAttack *bat);
void handleAfterAttackCasting (const BattleAttack & bat); void handleAfterAttackCasting (const BattleAttack & bat);
void attackCasting(const BattleAttack & bat, Bonus::BonusType attackMode, const CStack * attacker); void attackCasting(const BattleAttack & bat, Bonus::BonusType attackMode, const CStack * attacker);
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ArtifactPosition slot); bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ArtifactPosition slot);