| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- /*
- * BattleHexTest.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #include "StdInc.h"
- #include "../lib/bonuses/CBonusSystemNode.h"
- #include "../lib/bonuses/BonusEnum.h"
- #include "../lib/bonuses/Limiters.h"
- #include "../lib/bonuses/Propagators.h"
- #include "../lib/bonuses/Updaters.h"
- namespace test
- {
- using namespace ::testing;
- class TestBonusSystemNode : public CBonusSystemNode
- {
- public:
- using CBonusSystemNode::CBonusSystemNode;
- MOCK_CONST_METHOD0(getOwner, PlayerColor());
- void setPlayer(PlayerColor player)
- {
- EXPECT_CALL(*this, getOwner()).WillRepeatedly(Return(player));
- }
- void giveIntimidationSkill()
- {
- auto intimidationBonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::SECONDARY_SKILL, -1, SecondarySkill(0));
- intimidationBonus->propagator = std::make_shared<CPropagatorNodeType>(BonusNodeType::BATTLE_WIDE);
- intimidationBonus->propagationUpdater = std::make_shared<OwnerUpdater>();
- intimidationBonus->limiter = std::make_shared<OppositeSideLimiter>();
- addNewBonus(intimidationBonus);
- }
- };
- class BonusSystemTest : public Test
- {
- protected:
- CBonusSystemNode global{BonusNodeType::GLOBAL_EFFECTS};
- CBonusSystemNode battle{BonusNodeType::BATTLE_WIDE};
- TestBonusSystemNode playerRed{BonusNodeType::PLAYER};
- TestBonusSystemNode playerBlue{BonusNodeType::PLAYER};
- TestBonusSystemNode heroAine{BonusNodeType::HERO};
- TestBonusSystemNode heroBron{BonusNodeType::HERO};
- CBonusSystemNode artifactTypeRing{BonusNodeType::ARTIFACT};
- CBonusSystemNode artifactTypeSword{BonusNodeType::ARTIFACT};
- CBonusSystemNode artifactTypeArmor{BonusNodeType::ARTIFACT};
- CBonusSystemNode artifactTypeOrb{BonusNodeType::ARTIFACT};
- CBonusSystemNode artifactTypeLegion{BonusNodeType::ARTIFACT};
- CBonusSystemNode creatureAngel{BonusNodeType::CREATURE};
- CBonusSystemNode creatureDevil{BonusNodeType::CREATURE};
- CBonusSystemNode creaturePikeman{BonusNodeType::CREATURE};
- void startBattle()
- {
- heroAine.attachTo(battle);
- heroBron.attachTo(battle);
- }
- void SetUp() override
- {
- playerRed.attachTo(global);
- playerBlue.attachTo(global);
- heroAine.attachTo(playerRed);
- heroBron.attachTo(playerBlue);
- playerRed.setPlayer(PlayerColor(0));
- playerBlue.setPlayer(PlayerColor(1));
- heroAine.setPlayer(PlayerColor(0));
- heroBron.setPlayer(PlayerColor(1));
- auto spellpowerBonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::ARTIFACT, 1, ArtifactID(0), PrimarySkill::SPELL_POWER);
- auto spellpowerBonus4 = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::ARTIFACT, 4, ArtifactID(1), PrimarySkill::SPELL_POWER);
- auto attackBonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::PRIMARY_SKILL, BonusSource::ARTIFACT, 1, ArtifactID(2), PrimarySkill::ATTACK);
- auto blockMagicBonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::BLOCK_ALL_MAGIC, BonusSource::ARTIFACT, 1, ArtifactID(3));
- auto legionBonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::CREATURE_GROWTH, BonusSource::ARTIFACT, 4, ArtifactID(4), BonusCustomSubtype::creatureLevel(3));
- auto luckBonusEnemies = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::LUCK, BonusSource::CREATURE_ABILITY, -1, CreatureID(0));
- auto moraleBonusAllies = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::CREATURE_ABILITY, 1, CreatureID(1));
- luckBonusEnemies->propagator = std::make_shared<CPropagatorNodeType>(BonusNodeType::BATTLE_WIDE);
- luckBonusEnemies->propagationUpdater = std::make_shared<OwnerUpdater>();
- luckBonusEnemies->limiter = std::make_shared<OppositeSideLimiter>();
- luckBonusEnemies->stacking = "devil";
- moraleBonusAllies->propagator = std::make_shared<CPropagatorNodeType>(BonusNodeType::ARMY);
- moraleBonusAllies->stacking = "angel";
- blockMagicBonus->propagator = std::make_shared<CPropagatorNodeType>(BonusNodeType::BATTLE_WIDE);
- legionBonus->propagator = std::make_shared<CPropagatorNodeType>(BonusNodeType::TOWN_AND_VISITOR);
- artifactTypeRing.addNewBonus(spellpowerBonus);
- artifactTypeSword.addNewBonus(attackBonus);
- artifactTypeArmor.addNewBonus(spellpowerBonus4);
- artifactTypeOrb.addNewBonus(blockMagicBonus);
- artifactTypeLegion.addNewBonus(legionBonus);
- creatureAngel.addNewBonus(moraleBonusAllies);
- creatureDevil.addNewBonus(luckBonusEnemies);
- }
- };
- TEST_F(BonusSystemTest, multipleBonusSources)
- {
- CBonusSystemNode ring1{BonusNodeType::ARTIFACT_INSTANCE};
- CBonusSystemNode ring2{BonusNodeType::ARTIFACT_INSTANCE};
- CBonusSystemNode armor{BonusNodeType::ARTIFACT_INSTANCE};
- ring1.attachToSource(artifactTypeRing);
- ring2.attachToSource(artifactTypeRing);
- armor.attachToSource(artifactTypeArmor);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::PRIMARY_SKILL, PrimarySkill::SPELL_POWER), 0);
- // single bonus produces single effect
- heroAine.attachToSource(ring1);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::PRIMARY_SKILL, PrimarySkill::SPELL_POWER), 1);
- // same bonus applied twice produces single effect
- heroAine.attachToSource(ring2);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::PRIMARY_SKILL, PrimarySkill::SPELL_POWER), 1);
- // different bonuses stack
- heroAine.attachToSource(armor);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::PRIMARY_SKILL, PrimarySkill::SPELL_POWER), 1+4);
- heroAine.detachFromSource(ring1);
- heroAine.detachFromSource(ring2);
- heroAine.detachFromSource(armor);
- }
- TEST_F(BonusSystemTest, battlewidePropagationToAllies)
- {
- CBonusSystemNode angel1{BonusNodeType::STACK_INSTANCE};
- CBonusSystemNode angel2{BonusNodeType::STACK_INSTANCE};
- CBonusSystemNode pikemanAlly{BonusNodeType::STACK_INSTANCE};
- CBonusSystemNode pikemanEnemy{BonusNodeType::STACK_INSTANCE};
- angel1.attachToSource(creatureAngel);
- angel2.attachToSource(creatureAngel);
- pikemanAlly.attachToSource(creaturePikeman);
- pikemanEnemy.attachToSource(creaturePikeman);
- pikemanAlly.attachTo(heroAine);
- pikemanEnemy.attachTo(heroBron);
- startBattle();
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::MORALE), 0);
- angel1.attachTo(heroAine);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::MORALE), 1);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::MORALE), 1);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::MORALE), 0);
- angel2.attachTo(heroAine);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::MORALE), 1);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::MORALE), 1);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::MORALE), 0);
- }
- TEST_F(BonusSystemTest, battlewidePropagationToAll)
- {
- CBonusSystemNode orb{BonusNodeType::ARTIFACT_INSTANCE};
- orb.attachToSource(artifactTypeOrb);
- heroAine.attachToSource(orb);
- startBattle();
- EXPECT_TRUE(heroAine.hasBonusOfType(BonusType::BLOCK_ALL_MAGIC));
- EXPECT_TRUE(heroBron.hasBonusOfType(BonusType::BLOCK_ALL_MAGIC));
- heroAine.detachFromSource(orb);
- }
- TEST_F(BonusSystemTest, battlewidePropagationToEnemies)
- {
- TestBonusSystemNode devil1{BonusNodeType::STACK_INSTANCE};
- TestBonusSystemNode devil2{BonusNodeType::STACK_INSTANCE};
- TestBonusSystemNode pikemanAlly{BonusNodeType::STACK_INSTANCE};
- TestBonusSystemNode pikemanEnemy{BonusNodeType::STACK_INSTANCE};
- devil1.setPlayer(PlayerColor(0));
- devil2.setPlayer(PlayerColor(0));
- pikemanAlly.setPlayer(PlayerColor(0));
- pikemanEnemy.setPlayer(PlayerColor(1));
- devil1.attachToSource(creatureDevil);
- devil2.attachToSource(creatureDevil);
- pikemanAlly.attachToSource(creaturePikeman);
- pikemanEnemy.attachToSource(creaturePikeman);
- pikemanAlly.attachTo(heroAine);
- pikemanEnemy.attachTo(heroBron);
- startBattle();
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::LUCK), 0);
- devil1.attachTo(heroAine);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::LUCK), -1);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::LUCK), -1);
- devil2.attachTo(heroAine);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::LUCK), -1);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::LUCK), -1);
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::LUCK), -1);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::LUCK), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::LUCK), -1);
- }
- TEST_F(BonusSystemTest, battlewideSkillPropagationToEnemies)
- {
- TestBonusSystemNode pikemanAlly{BonusNodeType::STACK_INSTANCE};
- TestBonusSystemNode pikemanEnemy{BonusNodeType::STACK_INSTANCE};
- // #5975 - skill that affects only enemies in battle is broken,
- // but only if hero has *any* artifact (including obligatory catapult/spellbook, so always)
- CBonusSystemNode armor{BonusNodeType::ARTIFACT_INSTANCE};
- armor.attachToSource(artifactTypeArmor);
- heroAine.attachToSource(armor);
- pikemanAlly.setPlayer(PlayerColor(0));
- pikemanEnemy.setPlayer(PlayerColor(1));
- pikemanAlly.attachToSource(creaturePikeman);
- pikemanEnemy.attachToSource(creaturePikeman);
- heroAine.giveIntimidationSkill();
- pikemanAlly.attachTo(heroAine);
- pikemanEnemy.attachTo(heroBron);
- startBattle();
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::MORALE), -1);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::MORALE), -1);
- heroAine.nodeHasChanged();
- EXPECT_EQ(heroAine.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(heroBron.valOfBonuses(BonusType::MORALE), -1);
- EXPECT_EQ(pikemanAlly.valOfBonuses(BonusType::MORALE), 0);
- EXPECT_EQ(pikemanEnemy.valOfBonuses(BonusType::MORALE), -1);
- }
- TEST_F(BonusSystemTest, legionPieces)
- {
- TestBonusSystemNode townAndVisitor{BonusNodeType::TOWN_AND_VISITOR};
- TestBonusSystemNode town{BonusNodeType::TOWN_AND_VISITOR};
- town.attachTo(townAndVisitor);
- CBonusSystemNode legion{BonusNodeType::ARTIFACT_INSTANCE};
- legion.attachToSource(artifactTypeLegion);
- heroAine.attachToSource(legion);
- heroAine.attachTo(townAndVisitor);
- EXPECT_EQ(town.valOfBonuses(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(3)), 4);
- heroAine.detachFromSource(legion);
- EXPECT_EQ(town.valOfBonuses(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(3)), 0);
- heroAine.attachToSource(legion);
- EXPECT_EQ(town.valOfBonuses(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(3)), 4);
- heroAine.detachFrom(townAndVisitor);
- EXPECT_EQ(town.valOfBonuses(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(3)), 0);
- heroAine.detachFromSource(legion);
- }
- }
|