Bläddra i källkod

move checks for invincible bonus to UnitState & cache

Ivan Savenko 9 månader sedan
förälder
incheckning
48473b18f6

+ 1 - 1
lib/CStack.cpp

@@ -298,7 +298,7 @@ BattleHexArray CStack::meleeAttackHexes(const battle::Unit * attacker, const bat
 
 bool CStack::isMeleeAttackPossible(const battle::Unit * attacker, const battle::Unit * defender, BattleHex attackerPos, BattleHex defenderPos)
 {
-	if(defender->hasBonusOfType(BonusType::INVINCIBLE))
+	if(defender->isInvincible())
 		return false;
 		
 	return !meleeAttackHexes(attacker, defender, attackerPos, defenderPos).empty();

+ 3 - 3
lib/battle/CBattleInfoCallback.cpp

@@ -675,7 +675,7 @@ bool CBattleInfoCallback::battleCanAttack(const battle::Unit * stack, const batt
 	if (!stack || !target)
 		return false;
 
-	if(target->hasBonusOfType(BonusType::INVINCIBLE))
+	if(target->isInvincible())
 		return false;
 
 	if(!battleMatchOwner(stack, target))
@@ -744,7 +744,7 @@ bool CBattleInfoCallback::battleCanShoot(const battle::Unit * attacker, BattleHe
 		if(!defender)
 			return false;
 
-		if(defender->hasBonusOfType(BonusType::INVINCIBLE))
+		if(defender->isInvincible())
 			return false;
 	}
 
@@ -810,7 +810,7 @@ DamageEstimation CBattleInfoCallback::battleEstimateDamage(const BattleAttackInf
 	if (!bai.defender->ableToRetaliate())
 		return ret;
 
-	if (bai.attacker->hasBonusOfType(BonusType::BLOCKS_RETALIATION) || bai.attacker->hasBonusOfType(BonusType::INVINCIBLE))
+	if (bai.attacker->hasBonusOfType(BonusType::BLOCKS_RETALIATION) || bai.attacker->isInvincible())
 		return ret;
 
 	//TODO: rewrite using boost::numeric::interval

+ 5 - 0
lib/battle/CUnitState.cpp

@@ -700,6 +700,11 @@ bool CUnitState::isHypnotized() const
 	return bonusCache.getBonusValue(UnitBonusValuesProxy::HYPNOTIZED);
 }
 
+bool CUnitState::isInvincible() const
+{
+	return bonusCache.getBonusValue(UnitBonusValuesProxy::INVINCIBLE);
+}
+
 int CUnitState::getTotalAttacks(bool ranged) const
 {
 	return 1 + (ranged ?

+ 1 - 0
lib/battle/CUnitState.h

@@ -193,6 +193,7 @@ public:
 	bool isValidTarget(bool allowDead = false) const override;
 
 	bool isHypnotized() const override;
+	bool isInvincible() const override;
 
 	bool isClone() const override;
 	bool hasClone() const override;

+ 1 - 0
lib/battle/Unit.h

@@ -87,6 +87,7 @@ public:
 	virtual bool isValidTarget(bool allowDead = false) const = 0; //non-turret non-ghost stacks (can be attacked or be object of magic effect)
 
 	virtual bool isHypnotized() const = 0;
+	virtual bool isInvincible() const = 0;
 
 	virtual bool isClone() const = 0;
 	virtual bool hasClone() const = 0;

+ 1 - 0
lib/bonuses/BonusCache.cpp

@@ -203,6 +203,7 @@ const UnitBonusValuesProxy::SelectorsArray * UnitBonusValuesProxy::generateSelec
 		Selector::type()(BonusType::FORGETFULL),//FORGETFULL,
 		Selector::type()(BonusType::FREE_SHOOTING).Or(Selector::type()(BonusType::SIEGE_WEAPON)),//HAS_FREE_SHOOTING,
 		Selector::type()(BonusType::STACK_HEALTH),//STACK_HEALTH,
+		Selector::type()(BonusType::INVINCIBLE),//INVINCIBLE,
 		Selector::type()(BonusType::NONE).And(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::CLONE))))
 	};
 

+ 1 - 0
lib/bonuses/BonusCache.h

@@ -116,6 +116,7 @@ public:
 		FORGETFULL,
 		HAS_FREE_SHOOTING,
 		STACK_HEALTH,
+		INVINCIBLE,
 
 		CLONE_MARKER,
 

+ 2 - 2
lib/spells/BattleSpellMechanics.cpp

@@ -231,7 +231,7 @@ bool BattleSpellMechanics::canBeCastAt(const Target & target, Problem & problem)
 		if(mainTarget && mainTarget == caster)
 			return false; // can't cast on self
 
-		if(mainTarget && mainTarget->hasBonusOfType(BonusType::INVINCIBLE) && !getSpell()->getPositiveness())
+		if(mainTarget && mainTarget->isInvincible() && !getSpell()->getPositiveness())
 			return false;
 	}
 	else if(getSpell()->canCastOnlyOnSelf())
@@ -259,7 +259,7 @@ std::vector<const CStack *> BattleSpellMechanics::getAffectedStacks(const Target
 
 	for(const Destination & dest : all)
 	{
-		if(dest.unitValue && !dest.unitValue->hasBonusOfType(BonusType::INVINCIBLE))
+		if(dest.unitValue && !dest.unitValue->isInvincible())
 		{
 			//FIXME: remove and return battle::Unit
 			stacks.insert(battle()->battleGetStackByID(dest.unitValue->unitId(), false));

+ 1 - 1
lib/spells/CSpellHandler.cpp

@@ -434,7 +434,7 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni
 		}
 
 		//invincible
-		if(bearer->hasBonusOfType(BonusType::INVINCIBLE))
+		if(affectedCreature->isInvincible())
 			ret = 0;
 	}
 	ret = caster->getSpellBonus(this, ret, affectedCreature);

+ 2 - 2
server/battles/BattleActionProcessor.cpp

@@ -276,7 +276,7 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
 	for (int i = 0; i < totalAttacks; ++i)
 	{
 		//first strike
-		if(i == 0 && firstStrike && retaliation && !stack->hasBonusOfType(BonusType::BLOCKS_RETALIATION) && !stack->hasBonusOfType(BonusType::INVINCIBLE))
+		if(i == 0 && firstStrike && retaliation && !stack->hasBonusOfType(BonusType::BLOCKS_RETALIATION) && !stack->isInvincible())
 		{
 			makeAttack(battle, destinationStack, stack, 0, stack->getPosition(), true, false, true);
 		}
@@ -303,7 +303,7 @@ bool BattleActionProcessor::doAttackAction(const CBattleInfoCallback & battle, c
 		//we check retaliation twice, so if it unblocked during attack it will work only on next attack
 		if(stack->alive()
 			&& !stack->hasBonusOfType(BonusType::BLOCKS_RETALIATION)
-			&& !stack->hasBonusOfType(BonusType::INVINCIBLE)
+			&& !stack->isInvincible()
 			&& (i == 0 && !firstStrike)
 			&& retaliation && destinationStack->ableToRetaliate())
 		{

+ 5 - 0
test/battle/CBattleInfoCallbackTest.cpp

@@ -76,6 +76,11 @@ public:
 		return hasBonusOfType(BonusType::HYPNOTIZED);
 	}
 
+	bool isInvincible() const override
+	{
+		return hasBonusOfType(BonusType::INVINCIBLE);
+	}
+
 	void redirectBonusesToFake()
 	{
 		ON_CALL(*this, getAllBonuses(_, _, _)).WillByDefault(Invoke(&bonusFake, &BonusBearerMock::getAllBonuses));

+ 1 - 0
test/mock/mock_battle_Unit.h

@@ -58,6 +58,7 @@ public:
 	MOCK_CONST_METHOD1(isValidTarget, bool(bool));
 
 	MOCK_CONST_METHOD0(isHypnotized, bool());
+	MOCK_CONST_METHOD0(isInvincible, bool());
 	MOCK_CONST_METHOD0(isClone, bool());
 	MOCK_CONST_METHOD0(hasClone, bool());
 	MOCK_CONST_METHOD0(canCast, bool());