mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +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:
parent
76ac9991ed
commit
6fe5f2a7f6
@ -3892,7 +3892,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
BattleAttack bat;
|
||||
prepareAttack(bat, stack, destinationStack, (i ? 0 : distance), ba.additionalInfo); //no distance travelled on second attack
|
||||
//prepareAttack(bat, stack, stackAtEnd, 0, ba.additionalInfo);
|
||||
handleAttackBeforeCasting(bat); //only before first attack
|
||||
handleAttackBeforeCasting(&bat); //only before first attack
|
||||
sendAndApply(&bat);
|
||||
handleAfterAttackCasting(bat);
|
||||
}
|
||||
@ -3936,7 +3936,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
||||
BattleAttack bat;
|
||||
bat.flags |= BattleAttack::SHOT;
|
||||
prepareAttack(bat, stack, destinationStack, 0, ba.destinationTile);
|
||||
handleAttackBeforeCasting(bat);
|
||||
handleAttackBeforeCasting(&bat);
|
||||
sendAndApply(&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);
|
||||
attackCasting(bat, Bonus::SPELL_BEFORE_ATTACK, attacker); //no death stare / acid breath needed?
|
||||
const CStack * attacker = gs->curB->battleGetStackByID(bat->stackAttacking);
|
||||
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)
|
||||
{
|
||||
const CStack * attacker = gs->curB->battleGetStackByID(bat.stackAttacking);
|
||||
if (!attacker) //could be already dead
|
||||
if (!attacker || bat.bsa.empty()) // can be already dead
|
||||
return;
|
||||
|
||||
auto cast = [=](SpellID spellID, int power)
|
||||
|
@ -279,7 +279,7 @@ public:
|
||||
|
||||
void run(bool resume);
|
||||
void newTurn();
|
||||
void handleAttackBeforeCasting (const BattleAttack & bat);
|
||||
void handleAttackBeforeCasting(BattleAttack *bat);
|
||||
void handleAfterAttackCasting (const BattleAttack & bat);
|
||||
void attackCasting(const BattleAttack & bat, Bonus::BonusType attackMode, const CStack * attacker);
|
||||
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ArtifactPosition slot);
|
||||
|
Loading…
Reference in New Issue
Block a user