Pārlūkot izejas kodu

Fixed #1130.

Moved isToReverse() function to battleCallback so that creature rotation will be handled by core mechanics and not only GUI.
DjWarmonger 13 gadi atpakaļ
vecāks
revīzija
52242692f1

+ 3 - 45
client/BattleInterface/CBattleAnimations.cpp

@@ -63,48 +63,6 @@ CBattleStackAnimation::CBattleStackAnimation(CBattleInterface * _owner, const CS
 : CBattleAnimation(_owner), stack(_stack) 
 {}
 
-bool CBattleStackAnimation::isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir)
-{
-	int fromMod = hexFrom % GameConstants::BFIELD_WIDTH;
-	int fromDiv = hexFrom / GameConstants::BFIELD_WIDTH;
-	int toMod = hexTo % GameConstants::BFIELD_WIDTH;
-
-	if(curDir && fromMod < toMod)
-		return false;
-	else if(curDir && fromMod > toMod)
-		return true;
-	else if(curDir && fromMod == toMod)
-	{
-		return fromDiv % 2 == 0;
-	}
-	else if(!curDir && fromMod < toMod)
-		return true;
-	else if(!curDir && fromMod > toMod)
-		return false;
-	else if(!curDir && fromMod == toMod)
-	{
-		return fromDiv % 2 == 1;
-	}
-	tlog1 << "Catastrope in CBattleStackAnimation::isToReverse!" << std::endl;
-	return false; //should never happen
-}
-
-bool CBattleStackAnimation::isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir, bool toDoubleWide, bool toDir)
-{
-	if(hexTo < 0) //turret
-		return false;
-
-	if(toDoubleWide)
-	{
-		return isToReverseHlp(hexFrom, hexTo, curDir) &&
-			(toDir ? isToReverseHlp(hexFrom, hexTo-1, curDir) : isToReverseHlp(hexFrom, hexTo+1, curDir) );
-	}
-	else
-	{
-		return isToReverseHlp(hexFrom, hexTo, curDir);
-	}
-}
-
 CCreatureAnimation* CBattleStackAnimation::myAnim()
 {
 	return owner->creAnims[stack->ID];
@@ -197,7 +155,7 @@ bool CDefenceAnimation::init()
 
 
 	//reverse unit if necessary
-	if(attacker && isToReverse(stack->position, attacker->position, owner->creDir[stack->ID], attacker->doubleWide(), owner->creDir[attacker->ID]))
+	if (attacker && owner->curInt->cb->isToReverse(stack->position, attacker->position, owner->creDir[stack->ID], attacker->doubleWide(), owner->creDir[attacker->ID]))
 	{
 		owner->addNewAnim(new CReverseAnimation(owner, stack, stack->position, true));
 		return false;
@@ -313,9 +271,9 @@ bool CMeleeAttackAnimation::init()
 		return false;
 	}
 
-	bool toReverse = isToReverse(attackingStackPosBeforeReturn, dest, owner->creDir[stack->ID], attackedStack->doubleWide(), owner->creDir[attackedStack->ID]);
+	bool toReverse = owner->curInt->cb->isToReverse(attackingStackPosBeforeReturn, dest, owner->creDir[stack->ID], attackedStack->doubleWide(), owner->creDir[attackedStack->ID]);
 
-	if(toReverse)
+	if (toReverse)
 	{
 
 		owner->addNewAnim(new CReverseAnimation(owner, stack, attackingStackPosBeforeReturn, true));

+ 0 - 3
client/BattleInterface/CBattleAnimations.h

@@ -44,9 +44,6 @@ public:
 	const CStack * stack; //id of stack whose animation it is
 
 	CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);
-	
-	static bool isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir); //helper for isToReverse
-	static bool isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir); //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
 
 	CCreatureAnimation * myAnim(); //animation for our stack
 };

+ 1 - 1
client/BattleInterface/CBattleInterface.h

@@ -122,7 +122,7 @@ private:
 	CDefHandler *fireWall;
 	CDefHandler *smallForceField[2], *bigForceField[2]; // [side]
 
-	std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
+	std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
 	ui8 animCount;
 	const CStack * activeStack; //number of active stack; NULL - no one
 	const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; NULL of none

+ 74 - 18
lib/CBattleCallback.cpp

@@ -1282,14 +1282,26 @@ 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) const
 {
+	//TODO: apply rotation to two-hex attackers
+	auto side = playerToSide (attacker->owner);
+
 	AttackableTiles at;
 	RETURN_IF_NOT_BATTLE(at);
 
 	const int WN = GameConstants::BFIELD_WIDTH;
 	ui16 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, side, attacker->doubleWide(), side);
+	if (reverse && attacker->doubleWide())
+	{
+		if (attacker->owner)
+			--hex; //move left
+		else
+			++hex; //move right
+	}
 	if (attacker->hasBonusOfType(Bonus::ATTACKS_ALL_ADJACENT))
 	{
 		boost::copy(attacker->getSurroundingHexes(attackerPos), vstd::set_inserter(at.hostileCreaturePositions));
@@ -1301,7 +1313,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(const CStack*
 		std::vector<BattleHex> hexes = attacker->getSurroundingHexes(attackerPos);
 		BOOST_FOREACH (BattleHex tile, hexes)
 		{
-			if ((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition(tile, hex) > -1) //adjacent both to attacker's head and attacked tile
+			if ((BattleHex::mutualPosition(tile, destinationTile) > -1 && BattleHex::mutualPosition (tile, hex) > -1) //adjacent both to attacker's head and attacked tile
 				|| tile == destinationTile) //or simply attacked directly
 			{
 				const CStack * st = battleGetStackByPos(tile, true);
@@ -1312,7 +1324,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(const CStack*
 			}
 		}
 	}
-	if (attacker->hasBonusOfType(Bonus::TWO_HEX_ATTACK_BREATH))
+	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;
@@ -1320,24 +1332,24 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(const CStack*
 		{
 		case 1:
 		case -1:
-			BattleHex::checkAndPush(destinationTile.hex + pseudoVector, hexes);
+			BattleHex::checkAndPush (destinationTile.hex + pseudoVector, hexes);
 			break;
-		case WN: //17
-		case WN + 1: //18
-		case -WN: //-17
-		case -WN + 1: //-16
-			BattleHex::checkAndPush(destinationTile.hex + pseudoVector + ((hex/WN)%2 ? 1 : -1 ), hexes);
+		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
-		case -WN-1: //-18
-			BattleHex::checkAndPush(destinationTile.hex + pseudoVector + ((hex/WN)%2 ? 1 : 0), hexes);
+		case WN-1: //16 //left-down
+		case -WN-1: //-18 //left-up
+			BattleHex::checkAndPush (destinationTile.hex + pseudoVector + ((hex/WN)%2 ? 1 : 0), hexes);
 			break;
 		}
 		BOOST_FOREACH (BattleHex tile, hexes)
 		{
 			//friendly stacks can also be damaged by Dragon Breath
-			if(battleGetStackByPos(tile, true))
-				at.friendlyCreaturePositions.insert(tile);
+			if (battleGetStackByPos (tile, true))
+				at.friendlyCreaturePositions.insert (tile);
 		}
 	}
 
@@ -1369,6 +1381,48 @@ std::set<const CStack*> CBattleInfoCallback::getAttackedCreatures(const CStack*
 	return attackedCres;
 }
 
+bool CBattleInfoCallback::isToReverseHlp (BattleHex hexFrom, BattleHex hexTo, bool curDir) const //TODO: this should apply also to mechanics and cursor interface
+{
+	int fromMod = hexFrom % GameConstants::BFIELD_WIDTH;
+	int fromDiv = hexFrom / GameConstants::BFIELD_WIDTH;
+	int toMod = hexTo % GameConstants::BFIELD_WIDTH;
+
+	if(curDir && fromMod < toMod)
+		return false;
+	else if(curDir && fromMod > toMod)
+		return true;
+	else if(curDir && fromMod == toMod)
+	{
+		return fromDiv % 2 == 0;
+	}
+	else if(!curDir && fromMod < toMod)
+		return true;
+	else if(!curDir && fromMod > toMod)
+		return false;
+	else if(!curDir && fromMod == toMod)
+	{
+		return fromDiv % 2 == 1;
+	}
+	tlog1 << "Catastrope in CBattleInfoCallback::isToReverse!" << std::endl;
+	return false; //should never happen
+}
+
+bool CBattleInfoCallback::isToReverse (BattleHex hexFrom, BattleHex hexTo, bool curDir, bool toDoubleWide, bool toDir) const //TODO: this should apply also to mechanics and cursor interface
+{
+	if (hexTo < 0) //turret
+		return false;
+
+	if (toDoubleWide)
+	{
+		return (isToReverseHlp (hexFrom, hexTo, curDir)) &&
+			(toDir ? isToReverseHlp (hexFrom, hexTo-1, curDir) : isToReverseHlp (hexFrom, hexTo+1, curDir));
+	}
+	else
+	{
+		return isToReverseHlp(hexFrom, hexTo, curDir);
+	}
+}
+
 ReachabilityInfo::TDistances CBattleInfoCallback::battleGetDistances(const CStack * stack, BattleHex hex /*= BattleHex::INVALID*/, BattleHex * predecessors /*= NULL*/) const
 {
 	ReachabilityInfo::TDistances ret;
@@ -1400,18 +1454,20 @@ si8 CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer *bonusBeare
 	if(bonusBearer->hasBonusOfType(Bonus::NO_DISTANCE_PENALTY))
 		return false;
 
-	if(BattleHex::getDistance(shooterPosition, destHex) <= GameConstants::BATTLE_PENALTY_DISTANCE)
-		return false;
-
 	if(const CStack * dstStack = battleGetStackByPos(destHex, false))
 	{
-		//If on dest hex stands stack that occupies a hex within our distance
+		//If any hex of target creature is within range, there is no penalty
 		BOOST_FOREACH(auto hex, dstStack->getHexes())
 			if(BattleHex::getDistance(shooterPosition, hex) <= GameConstants::BATTLE_PENALTY_DISTANCE)
 				return false;
 
 		//TODO what about two-hex shooters?
 	}
+	else
+	{
+		if (BattleHex::getDistance(shooterPosition, destHex) <= GameConstants::BATTLE_PENALTY_DISTANCE)
+			return false;
+	}
 
 	return true;
 }

+ 3 - 1
lib/CBattleCallback.h

@@ -269,8 +269,10 @@ 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;
+	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
+	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
 
 	ReachabilityInfo getReachability(const CStack *stack) const;
 	ReachabilityInfo getReachability(const ReachabilityInfo::Parameters &params) const;