AlexVinS 10 years ago
parent
commit
466ddb37b3
4 changed files with 33 additions and 10 deletions
  1. 1 1
      AI/BattleAI/BattleAI.cpp
  2. 20 5
      lib/BattleState.cpp
  3. 9 2
      lib/BattleState.h
  4. 3 2
      lib/NetPacksLib.cpp

+ 1 - 1
AI/BattleAI/BattleAI.cpp

@@ -643,7 +643,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo &AttackInfo
 	auto attacker = AttackInfo.attacker;
 	auto enemy = AttackInfo.defender;
 
-	const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacks);
+	const int remainingCounterAttacks = getValOr(state.counterAttacksLeft, enemy, enemy->counterAttacksRemaining());
 	const bool counterAttacksBlocked = attacker->hasBonusOfType(Bonus::BLOCKS_RETALIATION) || enemy->hasBonusOfType(Bonus::NO_RETALIATION);
 	const int totalAttacks = 1 + AttackInfo.attackerBonuses->getBonuses(Selector::type(Bonus::ADDITIONAL_ATTACK), (Selector::effectRange (Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT))))->totalValue();
 

+ 20 - 5
lib/BattleState.cpp

@@ -763,7 +763,7 @@ CGHeroInstance * BattleInfo::battleGetFightingHero(ui8 side) const
 
 CStack::CStack(const CStackInstance *Base, PlayerColor O, int I, bool AO, SlotID S)
 	: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
-	counterAttacks(1)
+	counterAttacksPerformed(0),counterAttacksTotalCache(0)
 {
 	assert(base);
 	type = base->type;
@@ -776,7 +776,7 @@ CStack::CStack()
 	setNodeType(STACK_BATTLE);
 }
 CStack::CStack(const CStackBasicDescriptor *stack, PlayerColor O, int I, bool AO, SlotID S)
-	: base(nullptr), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacks(1)
+	: base(nullptr), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacksPerformed(0)
 {
 	type = stack->type;
 	count = baseAmount = stack->count;
@@ -794,7 +794,8 @@ void CStack::init()
 	slot = SlotID(255);
 	attackerOwned = false;
 	position = BattleHex();
-	counterAttacks = -1;
+	counterAttacksPerformed = 0;
+	counterAttacksTotalCache = 0;
 }
 
 void CStack::postInit()
@@ -804,7 +805,8 @@ void CStack::postInit()
 
 	firstHPleft = MaxHealth();
 	shots = getCreature()->valOfBonuses(Bonus::SHOTS);
-	counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
+	counterAttacksPerformed = 0;
+	counterAttacksTotalCache = 0;
 	casts = valOfBonuses(Bonus::CASTS);
 	resurrected = 0;
 }
@@ -1129,12 +1131,25 @@ bool CStack::isMeleeAttackPossible(const CStack * attacker, const CStack * defen
 bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed
 {
 	return alive()
-		&& (counterAttacks > 0 || hasBonusOfType(Bonus::UNLIMITED_RETALIATIONS))
+		&& (counterAttacksPerformed < counterAttacksTotal() || hasBonusOfType(Bonus::UNLIMITED_RETALIATIONS))
 		&& !hasBonusOfType(Bonus::SIEGE_WEAPON)
 		&& !hasBonusOfType(Bonus::HYPNOTIZED)
 		&& !hasBonusOfType(Bonus::NO_RETALIATION);
 }
 
+ui8 CStack::counterAttacksTotal() const
+{
+	//after dispell bonus should remain during current round 
+	ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
+	vstd::amax(counterAttacksTotalCache, val);
+	return counterAttacksTotalCache;
+}
+
+si8 CStack::counterAttacksRemaining() const
+{
+	return counterAttacksTotal() - counterAttacksPerformed;
+}
+
 std::string CStack::getName() const
 {
 	return (count > 1) ? type->namePl : type->nameSing; //War machines can't use base

+ 9 - 2
lib/BattleState.h

@@ -171,7 +171,10 @@ public:
 	SlotID slot;  //slot - position in garrison (may be 255 for neutrals/called creatures)
 	bool attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
 	BattleHex position; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
-	ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
+	///how many times this stack has been counterattacked this round
+	ui8 counterAttacksPerformed;
+	///cached total count of counterattacks; should be cleared each round;do not serialize
+	mutable ui8 counterAttacksTotalCache;
 	si16 shots; //how many shots left
 	ui8 casts; //how many casts left
 	TQuantity resurrected; // these units will be taken back after battle is over
@@ -191,6 +194,10 @@ public:
 	std::string getName() const; //plural or singular
 	bool willMove(int turn = 0) const; //if stack has remaining move this turn
 	bool ableToRetaliate() const; //if stack can retaliate after attacked
+	///how many times this stack can counterattack in one round
+	ui8 counterAttacksTotal() const;
+	///how many times this stack can counterattack in one round more
+	si8 counterAttacksRemaining() const;
 	bool moved(int turn = 0) const; //if stack was already moved this turn
 	bool waited(int turn = 0) const;
 	bool canMove(int turn = 0) const; //if stack can move
@@ -231,7 +238,7 @@ public:
 		assert(isIndependentNode());
 		h & static_cast<CBonusSystemNode&>(*this);
 		h & static_cast<CStackBasicDescriptor&>(*this);
-		h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
+		h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacksPerformed
 			& shots & casts & count & resurrected;
 
 		const CArmedInstance *army = (base ? base->armyObj : nullptr);

+ 3 - 2
lib/NetPacksLib.cpp

@@ -1095,7 +1095,8 @@ DLL_LINKAGE void BattleNextRound::applyGs( CGameState *gs )
 		s->state -= EBattleStackState::HAD_MORALE;
 		s->state -= EBattleStackState::FEAR;
 		s->state -= EBattleStackState::DRAINED_MANA;
-		s->counterAttacks = 1 + s->valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
+		s->counterAttacksPerformed = 0;
+		s->counterAttacksTotalCache = 0;
 		// new turn effects
 		s->battleTurnPassed();
 	}
@@ -1255,7 +1256,7 @@ DLL_LINKAGE void BattleAttack::applyGs( CGameState *gs )
 {
 	CStack *attacker = gs->curB->getStack(stackAttacking);
 	if(counter())
-		attacker->counterAttacks--;
+		attacker->counterAttacksPerformed++;
 
 	if(shot())
 	{