2
0
Эх сурвалжийг харах

Merge pull request #9 from alexvins/issue/1763

Try to fix #1763 and a small refactoring
DjWarmonger 11 жил өмнө
parent
commit
573293d425

+ 36 - 16
lib/CBattleCallback.cpp

@@ -2018,7 +2018,7 @@ ui32 CBattleInfoCallback::calculateSpellDmg( const CSpell * sp, const CGHeroInst
 
 
 std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell * spell, int skillLevel, PlayerColor attackerOwner, BattleHex destinationTile)
 std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell * spell, int skillLevel, PlayerColor attackerOwner, BattleHex destinationTile)
 {
 {
-	std::set<const CStack*> attackedCres; /*std::set to exclude multiple occurrences of two hex creatures*/
+	std::set<const CStack*> attackedCres; //std::set to exclude multiple occurrences of two hex creatures
 
 
 	const ui8 attackerSide = playerToSide(attackerOwner) == 1;
 	const ui8 attackerSide = playerToSide(attackerOwner) == 1;
 	const auto attackedHexes = spell->rangeInHexes(destinationTile, skillLevel, attackerSide);
 	const auto attackedHexes = spell->rangeInHexes(destinationTile, skillLevel, attackerSide);
@@ -2090,32 +2090,52 @@ std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell *
 	}
 	}
 	else if(spell->getTargetType() == CSpell::CREATURE)
 	else if(spell->getTargetType() == CSpell::CREATURE)
 	{
 	{
-		if (ti.massive)
+		//start with all stacks. 
+		TStacks stacks = battleGetAllStacks();
+		
+		//for single target spells remove stacks from other hexes
+		if(!ti.massive)
 		{
 		{
-			TStacks stacks = battleGetAllStacks();
-
-			vstd::erase_if(stacks,[&](const CStack * stack){
-				return ti.smart && spell->isNegative() && stack->owner == attackerOwner;
-			});
-
 			vstd::erase_if(stacks,[&](const CStack * stack){
 			vstd::erase_if(stacks,[&](const CStack * stack){
-				return ti.smart && spell->isPositive() && stack->owner != attackerOwner;
+				return !vstd::contains(stack->getHexes(), destinationTile);
 			});
 			});
+		}
+		
+		//now handle smart targeting and remove invalid targets
+		const bool smartNegative = ti.smart && spell->isNegative();
+		const bool smartPositive = ti.smart && spell->isPositive();
+		
+		vstd::erase_if(stacks,[&](const CStack * stack){
+			const bool negativeToAlly = smartNegative && stack->owner == attackerOwner;
+			const bool positiveToEnemy = smartPositive && stack->owner != attackerOwner;
+			const bool invalidTarget = !stack->isValidTarget(!onlyAlive); //todo: this should be handled by spell class
+			return negativeToAlly || positiveToEnemy || invalidTarget;
+		});
 
 
-			vstd::erase_if(stacks,[&](const CStack * stack){
-				return !stack->isValidTarget(!onlyAlive);
-			});
-			
+		if (ti.massive)
+		{
+			//for massive spells add all remaining targets
 			for (auto stack : stacks)
 			for (auto stack : stacks)
 				attackedCres.insert(stack);
 				attackedCres.insert(stack);
 
 
 		}
 		}
 		else
 		else
 		{
 		{
-			if(const CStack * st = battleGetStackByPos(destinationTile, onlyAlive))
-				attackedCres.insert(st);			
+			//for single target spells we must select one target. Alive stack is preferred (issue #1763)
+			for(auto stack : stacks)
+			{
+				if(stack->alive())
+				{
+					attackedCres.insert(stack);
+					break;
+				}				
+			}	
+			
+			if(attackedCres.empty() && !stacks.empty())
+			{
+				attackedCres.insert(stacks.front());
+			}						
 		}
 		}
-		
 	}
 	}
 	else //custom range from attackedHexes
 	else //custom range from attackedHexes
 	{
 	{