Browse Source

Add SYNERGY_TARGET and [wip]-SHOOTS_ALL_ADJACENT

Dydzio 8 years ago
parent
commit
4cab76900f

+ 19 - 6
config/bonuses_texts.json

@@ -150,12 +150,13 @@
 		"description": "Immune to all Fire school spells"
 	},
 
-  "FIRE_SHIELD": {
-    "name": "Fire Shield (${val}%)",
-    "description": "Reflects part of melee damage"
-  },
+	"FIRE_SHIELD":
+	{
+		"name": "Fire Shield (${val}%)",
+		"description": "Reflects part of melee damage"
+	},
 
-  "FIRST_STRIKE":
+	"FIRST_STRIKE":
 	{
 		"name": "First Strike",
 		"description": "This creature attacks first instead of retaliating"
@@ -352,6 +353,12 @@
 		"name": "Ranged",
 		"description": "Creature can shoot"
 	},
+
+	"SHOOTS_ALL_ADJACENT":
+	{
+		"name": "Shoot all around",
+		"description": "This creature's ranged attacks strike all targets in a small area"
+	},
 	
 	"SOUL_STEAL":
 	{
@@ -400,13 +407,19 @@
 		"name": "Aura of Resistance",
 		"description": "Nearby stacks get ${val}% resistance"
 	},
-	
+
 	"SUMMON_GUARDIANS":
 	{
 		"name": "Summon guardians",
 		"description": "At battle start summons ${subtype.creature} (${val}%)"
 	},
 
+	"SYNERGY_TARGET":
+	{
+		"name": "Synergizable",
+		"description": "This creature is vulnerable to synergy effect"
+	},
+
 	"TWO_HEX_ATTACK_BREATH":
 	{
 		"name": "Breath",

+ 4 - 2
lib/HeroBonus.h

@@ -235,8 +235,10 @@ private:
 	BONUS_NAME(CATAPULT_EXTRA_SHOTS) /*val - number of additional shots, requires CATAPULT bonus to work*/\
 	BONUS_NAME(RANGED_RETALIATION) /*allows shooters to perform ranged retaliation*/\
 	BONUS_NAME(BLOCKS_RANGED_RETALIATION) /*disallows ranged retaliation for shooter unit, BLOCKS_RETALIATION bonus is for melee retaliation only*/\
-	BONUS_NAME(WIDE_BREATH) /* Kuririn skill */\
-	BONUS_NAME(FIRST_STRIKE) /* Witchking skill */\
+	BONUS_NAME(WIDE_BREATH) /* initial desigh: dragon breath affecting multiple nearby hexes */\
+	BONUS_NAME(FIRST_STRIKE) /* first counterattack, then attack if possible */\
+	BONUS_NAME(SYNERGY_TARGET) /* dummy skill for alternative upgrades mod */\
+	BONUS_NAME(SHOOTS_ALL_ADJACENT) /* H4 Cyclops-like shoot (attacks all hexes neighboring with target) without spell-like mechanics */\
 	/* end of list */
 
 

+ 183 - 172
lib/battle/CBattleInfoCallback.cpp

@@ -186,7 +186,7 @@ std::set<BattleHex> CBattleInfoCallback::battleGetAttackedHexes(const CStack* at
 {
 	std::set<BattleHex> attackedHexes;
 	RETURN_IF_NOT_BATTLE(attackedHexes);
-
+	
 	AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos);
 
 	for (BattleHex tile : at.hostileCreaturePositions)
@@ -1120,7 +1120,7 @@ ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityIn
 	return ret;
 }
 
-AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const
+AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos, bool rangedAttack) const
 {
 	//does not return hex attacked directly
 	//TODO: apply rotation to two-hex attackers
@@ -1129,210 +1129,221 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const CStack
 	AttackableTiles at;
 	RETURN_IF_NOT_BATTLE(at);
 
-	const int WN = GameConstants::BFIELD_WIDTH;
-	BattleHex hex = (attackerPos != BattleHex::INVALID) ? attackerPos.hex : attacker->position.hex; //real or hypothetical (cursor) position
-
-	//FIXME: dragons or cerbers can rotate before attack, making their base hex different (#1124)
-	bool reverse = isToReverse (hex, destinationTile, isAttacker, attacker->doubleWide(), isAttacker);
-	if (reverse && attacker->doubleWide())
-	{
-		hex = attacker->occupiedHex(hex); //the other hex stack stands on
-	}
-	if (attacker->hasBonusOfType(Bonus::ATTACKS_ALL_ADJACENT))
-	{
-		boost::copy (attacker->getSurroundingHexes (attackerPos), vstd::set_inserter (at.hostileCreaturePositions));
-	}
-	if (attacker->hasBonusOfType(Bonus::THREE_HEADED_ATTACK))
+	if(rangedAttack)
 	{
-		std::vector<BattleHex> hexes = attacker->getSurroundingHexes(attackerPos);
-		for (BattleHex tile : hexes)
+		if(attacker->hasBonusOfType(Bonus::SHOOTS_ALL_ADJACENT) && !vstd::contains(attackerPos.neighbouringTiles(), destinationTile))
 		{
-			if ((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition (tile, hex) > -1)) //adjacent both to attacker's head and attacked tile
-			{
-				const CStack * st = battleGetStackByPos(tile, true);
-				if(st && st->owner != attacker->owner) //only hostile stacks - does it work well with Berserk?
-				{
-					at.hostileCreaturePositions.insert(tile);
-				}
-			}
+			std::vector<BattleHex> targetHexes = destinationTile.neighbouringTiles();
+			targetHexes.push_back(destinationTile);
+			boost::copy(targetHexes, vstd::set_inserter(at.hostileCreaturePositions));
 		}
 	}
-	if (attacker->hasBonusOfType(Bonus::WIDE_BREATH))
+
+	else
 	{
-		std::vector<BattleHex> hexes;
 		const int WN = GameConstants::BFIELD_WIDTH;
-		// atack stand
-		if (hex == destinationTile.cloneInDirection(BattleHex::EDir::LEFT, false)) {
-			if (destinationTile.getY() % 2 == 0)
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
-			}
-			else {
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
-			}
+		BattleHex hex = (attackerPos != BattleHex::INVALID) ? attackerPos.hex : attacker->position.hex; //real or hypothetical (cursor) position
 
+		//FIXME: dragons or cerbers can rotate before attack, making their base hex different (#1124)
+		bool reverse = isToReverse(hex, destinationTile, isAttacker, attacker->doubleWide(), isAttacker);
+		if(reverse && attacker->doubleWide())
+		{
+			hex = attacker->occupiedHex(hex); //the other hex stack stands on
 		}
-		if (hex == destinationTile.cloneInDirection(BattleHex::EDir::RIGHT, false)) {
-			if (destinationTile.getY() % 2 == 0)
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
-			}
-			else
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
-				BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
-			}
+		if(attacker->hasBonusOfType(Bonus::ATTACKS_ALL_ADJACENT))
+		{
+			boost::copy(attacker->getSurroundingHexes(attackerPos), vstd::set_inserter(at.hostileCreaturePositions));
 		}
-		// atack down
-		if (hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_LEFT, false)) {
-			if (destinationTile.getY() % 2 == 1)
+		if(attacker->hasBonusOfType(Bonus::THREE_HEADED_ATTACK))
+		{
+			std::vector<BattleHex> hexes = attacker->getSurroundingHexes(attackerPos);
+			for(BattleHex tile : hexes)
 			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile - 1, hexes);
-				BattleHex::checkAndPush(destinationTile - 2, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
-			}
-			else {
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile - 1, hexes);
-				BattleHex::checkAndPush(destinationTile - 2, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+				if((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, hex) > -1)) //adjacent both to attacker's head and attacked tile
+				{
+					const CStack * st = battleGetStackByPos(tile, true);
+					if(st && st->owner != attacker->owner) //only hostile stacks - does it work well with Berserk?
+					{
+						at.hostileCreaturePositions.insert(tile);
+					}
+				}
 			}
 		}
-		if (hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_RIGHT, false)) {
+		if(attacker->hasBonusOfType(Bonus::WIDE_BREATH))
+		{
+			std::vector<BattleHex> hexes;
+			// attack stand
+			if(hex == destinationTile.cloneInDirection(BattleHex::EDir::LEFT, false)) {
+				if(destinationTile.getY() % 2 == 0)
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
+				}
+				else {
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN) - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
+				}
 
-			if (destinationTile.getY() % 2 == 1)
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + 2, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
 			}
-			else
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + 2, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
+			if(hex == destinationTile.cloneInDirection(BattleHex::EDir::RIGHT, false)) {
+				if(destinationTile.getY() % 2 == 0)
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
+				}
+				else
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN), hexes);
+					BattleHex::checkAndPush(destinationTile + (2 * WN) + 1, hexes);
+				}
+			}
+			// attack down
+			if(hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_LEFT, false)) {
+				if(destinationTile.getY() % 2 == 1)
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile - 1, hexes);
+					BattleHex::checkAndPush(destinationTile - 2, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
+				}
+				else {
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile - 1, hexes);
+					BattleHex::checkAndPush(destinationTile - 2, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+				}
 			}
+			if(hex == destinationTile.cloneInDirection(BattleHex::EDir::TOP_RIGHT, false)) {
+
+				if(destinationTile.getY() % 2 == 1)
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + 2, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+				}
+				else
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + 2, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
+				}
 
-		}
-		// attack up
-		if (hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false)) {
-			if (destinationTile.getY() % 2 == 1)
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
-				BattleHex::checkAndPush(destinationTile - WN, hexes);
-				BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
 			}
-			else {
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
-				BattleHex::checkAndPush(destinationTile - WN, hexes);
-				BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
+			// attack up
+			if(hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_LEFT, false)) {
+				if(destinationTile.getY() % 2 == 1)
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+					BattleHex::checkAndPush(destinationTile - WN, hexes);
+					BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
+				}
+				else {
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN + 2, hexes);
+					BattleHex::checkAndPush(destinationTile - WN, hexes);
+					BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
+				}
 			}
-		}
-		if (hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_RIGHT, false)) {
+			if(hex == destinationTile.cloneInDirection(BattleHex::EDir::BOTTOM_RIGHT, false)) {
+
+				if(destinationTile.getY() % 2 == 1)
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
+					BattleHex::checkAndPush(destinationTile - WN, hexes);
+					BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
+				}
+				else
+				{
+					BattleHex::checkAndPush(destinationTile, hexes);
+					BattleHex::checkAndPush(destinationTile - 1, hexes);
+					BattleHex::checkAndPush(destinationTile + WN, hexes);
+					BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
+					BattleHex::checkAndPush(destinationTile - WN, hexes);
+					BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
+				}
 
-			if (destinationTile.getY() % 2 == 1)
-			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 2, hexes);
-				BattleHex::checkAndPush(destinationTile - WN, hexes);
-				BattleHex::checkAndPush(destinationTile - WN - 1, hexes);
 			}
-			else
+
+			for(BattleHex tile : hexes)
 			{
-				BattleHex::checkAndPush(destinationTile, hexes);
-				BattleHex::checkAndPush(destinationTile - 1, hexes);
-				BattleHex::checkAndPush(destinationTile + WN, hexes);
-				BattleHex::checkAndPush(destinationTile + WN - 1, hexes);
-				BattleHex::checkAndPush(destinationTile - WN, hexes);
-				BattleHex::checkAndPush(destinationTile - WN + 1, hexes);
+				//friendly stacks can also be damaged by Dragon Breath
+				if(battleGetStackByPos(tile, true))
+					at.friendlyCreaturePositions.insert(tile);
 			}
-
 		}
 
-		for (BattleHex tile : hexes)
-		{
-			//friendly stacks can also be damaged by Dragon Breath
-			if (battleGetStackByPos(tile, true))
-				at.friendlyCreaturePositions.insert(tile);
-		}
-	}
-
-	else if (attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH) && BattleHex::mutualPosition(destinationTile.hex, hex) > -1) //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)
+		else if(attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH) && BattleHex::mutualPosition(destinationTile.hex, hex) > -1) //only adjacent hexes are subject of dragon breath calculation
 		{
-			//friendly stacks can also be damaged by Dragon Breath
-			if (battleGetStackByPos(tile, true))
-				at.friendlyCreaturePositions.insert(tile);
+			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)
+			{
+				//friendly stacks can also be damaged by Dragon Breath
+				if(battleGetStackByPos(tile, true))
+					at.friendlyCreaturePositions.insert(tile);
+			}
 		}
 	}
-
 	return at;
 }
 
-std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const
+std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, bool rangedAttack, BattleHex attackerPos) const
 {
 	std::set<const CStack*> attackedCres;
 	RETURN_IF_NOT_BATTLE(attackedCres);
 
-	AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos);
+	AttackableTiles at = getPotentiallyAttackableHexes(attacker, destinationTile, attackerPos, rangedAttack);
 	for (BattleHex tile : at.hostileCreaturePositions) //all around & three-headed attack
 	{
 		const CStack * st = battleGetStackByPos(tile, true);

+ 2 - 2
lib/battle/CBattleInfoCallback.h

@@ -92,8 +92,8 @@ public:
 	bool isInTacticRange(BattleHex dest) const;
 	si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
 
-	AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const; //TODO: apply rotation to two-hex attacker
-	std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
+	AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos, bool rangedAttack) const; //TODO: apply rotation to two-hex attacker
+	std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, bool rangedAttack, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
 	bool isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir) const; //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
 	bool isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir) const; //helper for isToReverse
 

+ 8 - 10
server/CGameHandler.cpp

@@ -892,16 +892,14 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
 	// only primary target
 	applyBattleEffects(bat, att, def, distance, false);
 
-	if (!bat.shot()) //multiple-hex attack - only in meele
-	{
-		std::set<const CStack*> attackedCreatures = gs->curB->getAttackedCreatures(att, targetHex); //creatures other than primary target
+	//multiple-hex normal attack
+	std::set<const CStack*> attackedCreatures = gs->curB->getAttackedCreatures(att, targetHex, bat.shot()); //creatures other than primary target
 
-		for (const CStack * stack : attackedCreatures)
+	for (const CStack * stack : attackedCreatures)
+	{
+		if (stack != def) //do not hit same stack twice
 		{
-			if (stack != def) //do not hit same stack twice
-			{
-				applyBattleEffects(bat, att, stack, distance, true);
-			}
+			applyBattleEffects(bat, att, stack, distance, true);
 		}
 	}
 
@@ -914,11 +912,11 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
 
 		//TODO: should spell override creature`s projectile?
 
-		auto attackedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att, bonus->val, targetHex);
+		auto affectedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att, bonus->val, targetHex);
 
 		//TODO: get exact attacked hex for defender
 
-		for (const CStack * stack : attackedCreatures)
+		for (const CStack * stack : affectedCreatures)
 		{
 			if (stack != def) //do not hit same stack twice
 			{