mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +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:
		| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user