Przeglądaj źródła

Fix dragon breath & fire shield

Ivan Savenko 2 lat temu
rodzic
commit
b423b3fa6b

+ 4 - 0
client/battle/BattleStacksController.cpp

@@ -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);
 

+ 8 - 26
lib/battle/CBattleInfoCallback.cpp

@@ -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);
 			}
 		}
 	}

+ 6 - 2
server/CGameHandler.cpp

@@ -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;