Prechádzať zdrojové kódy

Fix: Morale bonus should be shown correctly

Dmitry Orlov 5 rokov pred
rodič
commit
39de2f6435

+ 3 - 0
.gitignore

@@ -42,11 +42,14 @@ VCMI_VS11.opensdf
 *.suo
 *.user
 /AI/*/RD
+/AI/BattleAI/*/RD
 /client/RD
 /launcher/RD
 /lib/RD
 /lib/minizip/RD
+/lib/minizip/*/RD
 /scripting/erm/RD
+/scripting/erm/*/RD
 /server/RD
 /test/RD
 /VCMI_VS11.VC.opendb

+ 1 - 1
AI/BattleAI/AttackPossibility.cpp

@@ -66,7 +66,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo & attackInf
 	auto attacker = attackInfo.attacker;
 	auto defender = attackInfo.defender;
 	const std::string cachingStringBlocksRetaliation = "type_BLOCKS_RETALIATION";
-	static const auto selectorBlocksRetaliation = Selector::type(Bonus::BLOCKS_RETALIATION);
+	static const auto selectorBlocksRetaliation = Selector::type()(Bonus::BLOCKS_RETALIATION);
 	const auto attackerSide = getCbc()->playerToSide(getCbc()->battleGetOwner(attacker));
 	const bool counterAttacksBlocked = attacker->hasBonus(selectorBlocksRetaliation, cachingStringBlocksRetaliation);
 

+ 3 - 3
AI/VCAI/FuzzyEngines.cpp

@@ -52,13 +52,13 @@ armyStructure evaluateArmyStructure(const CArmedInstance * army)
 	double shootersStrength = 0;
 	ui32 maxSpeed = 0;
 
-	static const CSelector selectorSHOOTER = Selector::type(Bonus::SHOOTER);
+	static const CSelector selectorSHOOTER = Selector::type()(Bonus::SHOOTER);
 	static const std::string keySHOOTER = "type_"+std::to_string((int32_t)Bonus::SHOOTER);
 
-	static const CSelector selectorFLYING = Selector::type(Bonus::FLYING);
+	static const CSelector selectorFLYING = Selector::type()(Bonus::FLYING);
 	static const std::string keyFLYING = "type_"+std::to_string((int32_t)Bonus::FLYING);
 
-	static const CSelector selectorSTACKS_SPEED = Selector::type(Bonus::STACKS_SPEED);
+	static const CSelector selectorSTACKS_SPEED = Selector::type()(Bonus::STACKS_SPEED);
 	static const std::string keySTACKS_SPEED = "type_"+std::to_string((int32_t)Bonus::STACKS_SPEED);
 
 	for(auto s : army->Slots())

+ 1 - 1
client/battle/CBattleAnimations.cpp

@@ -493,7 +493,7 @@ bool CMovementAnimation::init()
 	distanceX = endPosition.x - begPosition.x;
 	distanceY = endPosition.y - begPosition.y;
 
-	if (stack->hasBonus(Selector::type(Bonus::FLYING)))
+	if (stack->hasBonus(Selector::type()(Bonus::FLYING)))
 	{
 		float distance = static_cast<float>(sqrt(distanceX * distanceX + distanceY * distanceY));
 

+ 3 - 3
client/battle/CBattleInterface.cpp

@@ -904,7 +904,7 @@ void CBattleInterface::bSpellf()
 	{
 		//TODO: move to spell mechanics, add more information to spell cast problem
 		//Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible
-		auto blockingBonus = currentHero()->getBonusLocalFirst(Selector::type(Bonus::BLOCK_ALL_MAGIC));
+		auto blockingBonus = currentHero()->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_ALL_MAGIC));
 		if (!blockingBonus)
 			return;
 
@@ -1638,8 +1638,8 @@ void CBattleInterface::activateStack()
 	redrawBackgroundWithHexes(activeStack);
 
 	//set casting flag to true if creature can use it to not check it every time
-	const auto spellcaster = s->getBonusLocalFirst(Selector::type(Bonus::SPELLCASTER)),
-		randomSpellcaster = s->getBonusLocalFirst(Selector::type(Bonus::RANDOM_SPELLCASTER));
+	const auto spellcaster = s->getBonusLocalFirst(Selector::type()(Bonus::SPELLCASTER)),
+		randomSpellcaster = s->getBonusLocalFirst(Selector::type()(Bonus::RANDOM_SPELLCASTER));
 	if(s->canCast() && (spellcaster || randomSpellcaster))
 	{
 		stackCanCastSpell = true;

+ 5 - 13
client/widgets/MiscWidgets.cpp

@@ -367,19 +367,11 @@ void MoraleLuckBox::set(const IBonusBearer * node)
 	const int neutralDescr[] = {60, 86}; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat.
 	const int componentType[] = {CComponent::luck, CComponent::morale};
 	const int hoverTextBase[] = {7, 4};
-	const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE};
-	int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal};
-	TConstBonusListPtr modifierList(new BonusList());
+	TConstBonusListPtr modifierList = std::make_shared<const BonusList>();
+	bonusValue = 0;
 
 	if(node)
-	{
-		modifierList = node->getBonuses(Selector::type(bonusType[morale]));
-		bonusValue = (node->*getValue[morale])();
-	}
-	else
-	{
-		bonusValue = 0;
-	}
+		bonusValue = morale ? node->MoraleValAndBonusList(modifierList) : node->LuckValAndBonusList(modifierList);
 
 	int mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good
 	hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt];
@@ -402,13 +394,13 @@ void MoraleLuckBox::set(const IBonusBearer * node)
 	}
 	else if(morale && node && node->hasBonusOfType(Bonus::NO_MORALE))
 	{
-		auto noMorale = node->getBonus(Selector::type(Bonus::NO_MORALE));
+		auto noMorale = node->getBonus(Selector::type()(Bonus::NO_MORALE));
 		text += "\n" + noMorale->Description();
 		bonusValue = 0;
 	}
 	else if (!morale && node && node->hasBonusOfType(Bonus::NO_LUCK))
 	{
-		auto noLuck = node->getBonus(Selector::type(Bonus::NO_LUCK));
+		auto noLuck = node->getBonus(Selector::type()(Bonus::NO_LUCK));
 		text += "\n" + noLuck->Description();
 		bonusValue = 0;
 	}

+ 1 - 1
lib/CArtHandler.cpp

@@ -990,7 +990,7 @@ void CArtifactInstance::deserializationFix()
 
 SpellID CArtifactInstance::getGivenSpellID() const
 {
-	const auto b = getBonusLocalFirst(Selector::type(Bonus::SPELL));
+	const auto b = getBonusLocalFirst(Selector::type()(Bonus::SPELL));
 	if(!b)
 	{
 		logMod->warn("Warning: %s doesn't bear any spell!", nodeName());

+ 1 - 1
lib/CCreatureSet.cpp

@@ -595,7 +595,7 @@ int CStackInstance::getLevel() const
 
 si32 CStackInstance::magicResistance() const
 {
-	si32 val = valOfBonuses(Selector::type(Bonus::MAGIC_RESISTANCE));
+	si32 val = valOfBonuses(Selector::type()(Bonus::MAGIC_RESISTANCE));
 	if (const CGHeroInstance * hero = dynamic_cast<const CGHeroInstance *>(_armyObj))
 	{
 		//resistance skill

+ 3 - 3
lib/CGameState.cpp

@@ -1172,9 +1172,9 @@ void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroRepl
 		{
 			for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
 			{
-				auto sel = Selector::type(Bonus::PRIMARY_SKILL)
-					.And(Selector::subtype(g))
-					.And(Selector::sourceType(Bonus::HERO_BASE_SKILL));
+				auto sel = Selector::type()(Bonus::PRIMARY_SKILL)
+					.And(Selector::subtype()(g))
+					.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL));
 
 				cgh->getBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g];
 			}

+ 8 - 8
lib/CPathfinder.cpp

@@ -1021,14 +1021,14 @@ TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl)
 	for(int i = 0; i < ETerrainType::ROCK; i++)
 	{
 		noTerrainPenalty.push_back(static_cast<bool>(
-				bl->getFirst(Selector::type(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype(i)))));
+				bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(i)))));
 	}
 
-	freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type(Bonus::FREE_SHIP_BOARDING)));
-	flyingMovement = static_cast<bool>(bl->getFirst(Selector::type(Bonus::FLYING_MOVEMENT)));
-	flyingMovementVal = bl->valOfBonuses(Selector::type(Bonus::FLYING_MOVEMENT));
-	waterWalking = static_cast<bool>(bl->getFirst(Selector::type(Bonus::WATER_WALKING)));
-	waterWalkingVal = bl->valOfBonuses(Selector::type(Bonus::WATER_WALKING));
+	freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::FREE_SHIP_BOARDING)));
+	flyingMovement = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::FLYING_MOVEMENT)));
+	flyingMovementVal = bl->valOfBonuses(Selector::type()(Bonus::FLYING_MOVEMENT));
+	waterWalking = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::WATER_WALKING)));
+	waterWalkingVal = bl->valOfBonuses(Selector::type()(Bonus::WATER_WALKING));
 }
 
 TurnInfo::TurnInfo(const CGHeroInstance * Hero, const int turn)
@@ -1074,7 +1074,7 @@ bool TurnInfo::hasBonusOfType(Bonus::BonusType type, int subtype) const
 	}
 
 	return static_cast<bool>(
-			bonuses->getFirst(Selector::type(type).And(Selector::subtype(subtype))));
+			bonuses->getFirst(Selector::type()(type).And(Selector::subtype()(subtype))));
 }
 
 int TurnInfo::valOfBonuses(Bonus::BonusType type, int subtype) const
@@ -1087,7 +1087,7 @@ int TurnInfo::valOfBonuses(Bonus::BonusType type, int subtype) const
 		return bonusCache->waterWalkingVal;
 	}
 
-	return bonuses->valOfBonuses(Selector::type(type).And(Selector::subtype(subtype)));
+	return bonuses->valOfBonuses(Selector::type()(type).And(Selector::subtype()(subtype)));
 }
 
 int TurnInfo::getMaxMovePoints(const EPathfindingLayer layer) const

+ 1 - 1
lib/CStack.cpp

@@ -135,7 +135,7 @@ std::vector<si32> CStack::activeSpells() const
 
 	std::stringstream cachingStr;
 	cachingStr << "!type_" << Bonus::NONE << "source_" << Bonus::SPELL_EFFECT;
-	CSelector selector = Selector::sourceType(Bonus::SPELL_EFFECT)
+	CSelector selector = Selector::sourceType()(Bonus::SPELL_EFFECT)
 						 .And(CSelector([](const Bonus * b)->bool
 	{
 		return b->type != Bonus::NONE;

+ 132 - 60
lib/HeroBonus.cpp

@@ -92,82 +92,80 @@ const std::map<std::string, TUpdaterPtr> bonusUpdaterMap =
 
 ///CBonusProxy
 CBonusProxy::CBonusProxy(const IBonusBearer * Target, CSelector Selector)
-	: cachedLast(0),
+	: bonusListCachedLast(0),
 	target(Target),
 	selector(Selector),
-	data()
+	bonusList()
 {
 
 }
 
 CBonusProxy::CBonusProxy(const CBonusProxy & other)
-	: cachedLast(other.cachedLast),
+	: bonusListCachedLast(other.bonusListCachedLast),
 	target(other.target),
 	selector(other.selector),
-	data(other.data)
+	bonusList(other.bonusList)
 {
 
 }
 
 CBonusProxy::CBonusProxy(CBonusProxy && other)
-	: cachedLast(0),
+	: bonusListCachedLast(0),
 	target(other.target),
 	selector(),
-	data()
+	bonusList()
 {
-	std::swap(cachedLast, other.cachedLast);
+	std::swap(bonusListCachedLast, other.bonusListCachedLast);
 	std::swap(selector, other.selector);
-	std::swap(data, other.data);
+	std::swap(bonusList, other.bonusList);
 }
 
 CBonusProxy & CBonusProxy::operator=(const CBonusProxy & other)
 {
-	cachedLast = other.cachedLast;
+	bonusListCachedLast = other.bonusListCachedLast;
 	selector = other.selector;
-	data = other.data;
+	bonusList = other.bonusList;
 	return *this;
 }
 
 CBonusProxy & CBonusProxy::operator=(CBonusProxy && other)
 {
-	std::swap(cachedLast, other.cachedLast);
+	std::swap(bonusListCachedLast, other.bonusListCachedLast);
 	std::swap(selector, other.selector);
-	std::swap(data, other.data);
+	std::swap(bonusList, other.bonusList);
 	return *this;
 }
 
-TConstBonusListPtr CBonusProxy::get() const
+TConstBonusListPtr CBonusProxy::getBonusList() const
 {
-	if(target->getTreeVersion() != cachedLast || !data)
+	if(target->getTreeVersion() != bonusListCachedLast || !bonusList)
 	{
 		//TODO: support limiters
-		data = target->getAllBonuses(selector, Selector::all);
-		cachedLast = target->getTreeVersion();
+		bonusList = target->getAllBonuses(selector, Selector::all);
+		bonusListCachedLast = target->getTreeVersion();
 	}
-	return data;
+	return bonusList;
 }
 
 const BonusList * CBonusProxy::operator->() const
 {
-	return get().get();
+	return getBonusList().get();
 }
 
 CTotalsProxy::CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue)
-	: target(Target),
-	selector(Selector),
+	: CBonusProxy(Target, Selector),
 	initialValue(InitialValue),
 	meleeCachedLast(0),
 	meleeValue(0),
 	rangedCachedLast(0),
 	rangedValue(0),
 	value(0),
-	cachedLast(0)
+	valueCachedLast(0)
 {
 }
 
 CTotalsProxy::CTotalsProxy(const CTotalsProxy & other)
-	: target(other.target),
-	selector(other.selector),
+	: CBonusProxy(other),
 	initialValue(other.initialValue),
 	meleeCachedLast(other.meleeCachedLast),
 	meleeValue(other.meleeValue),
@@ -178,13 +176,14 @@ CTotalsProxy::CTotalsProxy(const CTotalsProxy & other)
 
 CTotalsProxy & CTotalsProxy::operator=(const CTotalsProxy & other)
 {
+	CBonusProxy::operator=(other);
 	initialValue = other.initialValue;
 	meleeCachedLast = other.meleeCachedLast;
 	meleeValue = other.meleeValue;
 	rangedCachedLast = other.rangedCachedLast;
 	rangedValue = other.rangedValue;
 	value = other.value;
-	cachedLast = other.cachedLast;
+	valueCachedLast = other.valueCachedLast;
 
 	return *this;
 }
@@ -193,20 +192,32 @@ int CTotalsProxy::getValue() const
 {
 	const auto treeVersion = target->getTreeVersion();
 
-	if(treeVersion != cachedLast)
+	if(treeVersion != valueCachedLast)
 	{
-		auto bonuses = target->getBonuses(selector);
+		auto bonuses = getBonusList();
 
 		value = initialValue + bonuses->totalValue();
-		cachedLast = treeVersion;
+		valueCachedLast = treeVersion;
 	}
+	return value;
+}
+
+int CTotalsProxy::getValueAndList(TConstBonusListPtr & outBonusList) const
+{
+	const auto treeVersion = target->getTreeVersion();
+	outBonusList = getBonusList();
 
+	if(treeVersion != valueCachedLast)
+	{
+		value = initialValue + outBonusList->totalValue();
+		valueCachedLast = treeVersion;
+	}
 	return value;
 }
 
 int CTotalsProxy::getMeleeValue() const
 {
-	static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_MELEE_FIGHT));
+	static const auto limit = Selector::effectRange()(Bonus::NO_LIMIT).Or(Selector::effectRange()(Bonus::ONLY_MELEE_FIGHT));
 
 	const auto treeVersion = target->getTreeVersion();
 
@@ -222,7 +233,7 @@ int CTotalsProxy::getMeleeValue() const
 
 int CTotalsProxy::getRangedValue() const
 {
-	static const auto limit = Selector::effectRange(Bonus::NO_LIMIT).Or(Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT));
+	static const auto limit = Selector::effectRange()(Bonus::NO_LIMIT).Or(Selector::effectRange()(Bonus::ONLY_DISTANCE_FIGHT));
 
 	const auto treeVersion = target->getTreeVersion();
 
@@ -582,24 +593,28 @@ void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusLi
 }
 
 CSelector IBonusBearer::anaffectedByMoraleSelector
-	= Selector::type(Bonus::NON_LIVING)
-		.Or(Selector::type(Bonus::UNDEAD))
-		.Or(Selector::type(Bonus::NO_MORALE))
-		.Or(Selector::type(Bonus::SIEGE_WEAPON));
+	= Selector::type()(Bonus::NON_LIVING)
+		.Or(Selector::type()(Bonus::UNDEAD))
+		.Or(Selector::type()(Bonus::NO_MORALE))
+		.Or(Selector::type()(Bonus::SIEGE_WEAPON));
 
-CSelector IBonusBearer::moraleSelector = Selector::type(Bonus::MORALE);
-CSelector IBonusBearer::selfMoraleSelector = Selector::type(Bonus::SELF_MORALE);
+CSelector IBonusBearer::moraleSelector = Selector::type()(Bonus::MORALE);
+CSelector IBonusBearer::luckSelector = Selector::type()(Bonus::LUCK);
+CSelector IBonusBearer::selfMoraleSelector = Selector::type()(Bonus::SELF_MORALE);
+CSelector IBonusBearer::selfLuckSelector = Selector::type()(Bonus::SELF_LUCK);
 
 IBonusBearer::IBonusBearer()
 	:anaffectedByMorale(this, anaffectedByMoraleSelector),
 	moraleValue(this, moraleSelector, 0),
-	selfMorale(this, selfMoraleSelector)
+	luckValue(this, luckSelector, 0),
+	selfMorale(this, selfMoraleSelector),
+	selfLuck(this, selfLuckSelector)
 {
 }
 
 int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
 {
-	return valOfBonuses(Selector::type(type).And(selector));
+	return valOfBonuses(Selector::type()(type).And(selector));
 }
 
 int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype) const
@@ -607,9 +622,9 @@ int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype) const
 	boost::format fmt("type_%ds_%d");
 	fmt % (int)type % subtype;
 
-	CSelector s = Selector::type(type);
+	CSelector s = Selector::type()(type);
 	if(subtype != -1)
-		s = s.And(Selector::subtype(subtype));
+		s = s.And(Selector::subtype()(subtype));
 
 	return valOfBonuses(s, fmt.str());
 }
@@ -635,9 +650,9 @@ bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype) const
 	boost::format fmt("type_%ds_%d");
 	fmt % (int)type % subtype;
 
-	CSelector s = Selector::type(type);
+	CSelector s = Selector::type()(type);
 	if(subtype != -1)
-		s = s.And(Selector::subtype(subtype));
+		s = s.And(Selector::subtype()(subtype));
 
 	return hasBonus(s, fmt.str());
 }
@@ -678,9 +693,41 @@ int IBonusBearer::LuckVal() const
 	if(hasBonusOfType(Bonus::NO_LUCK))
 		return 0;
 
-	int ret = valOfBonuses(Bonus::LUCK);
+	int ret = luckValue.getValue();
+
+	if(selfLuck.getHasBonus()) //eg. halfling
+		vstd::amax(ret, +1);
+
+	return vstd::abetween(ret, -3, +3);
+}
+
+int IBonusBearer::MoraleValAndBonusList(TConstBonusListPtr & bonusList) const
+{
+	if(anaffectedByMorale.getHasBonus())
+	{
+		if(!bonusList->empty())
+			bonusList = std::make_shared<const BonusList>();
+		return 0;
+	}
+	int ret = moraleValue.getValueAndList(bonusList);
+
+	if(selfMorale.getHasBonus()) //eg. minotaur
+		vstd::amax(ret, +1);
 
-	if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
+	return vstd::abetween(ret, -3, +3);
+}
+
+int IBonusBearer::LuckValAndBonusList(TConstBonusListPtr & bonusList) const
+{
+	if(hasBonusOfType(Bonus::NO_LUCK))
+	{
+		if(!bonusList->empty())
+			bonusList = std::make_shared<const BonusList>();
+		return 0;
+	}
+	int ret = luckValue.getValueAndList(bonusList);
+
+	if(selfLuck.getHasBonus()) //eg. halfling
 		vstd::amax(ret, +1);
 
 	return vstd::abetween(ret, -3, +3);
@@ -689,7 +736,7 @@ int IBonusBearer::LuckVal() const
 ui32 IBonusBearer::MaxHealth() const
 {
 	const std::string cachingStr = "type_STACK_HEALTH";
-	static const auto selector = Selector::type(Bonus::STACK_HEALTH);
+	static const auto selector = Selector::type()(Bonus::STACK_HEALTH);
 	auto value = valOfBonuses(selector, cachingStr);
 	return std::max(1, value); //never 0
 }
@@ -735,12 +782,12 @@ si32 IBonusBearer::manaLimit() const
 
 int IBonusBearer::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
 {
-	static const CSelector selectorAllSkills = Selector::type(Bonus::PRIMARY_SKILL);
+	static const CSelector selectorAllSkills = Selector::type()(Bonus::PRIMARY_SKILL);
 	static const std::string keyAllSkills = "type_PRIMARY_SKILL";
 
 	auto allSkills = getBonuses(selectorAllSkills, keyAllSkills);
 
-	int ret = allSkills->valOfBonuses(Selector::subtype(id));
+	int ret = allSkills->valOfBonuses(Selector::subtype()(id));
 
 	vstd::amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
 	return ret;
@@ -754,26 +801,26 @@ si32 IBonusBearer::magicResistance() const
 ui32 IBonusBearer::Speed(int turn, bool useBind) const
 {
 	//war machines cannot move
-	if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON).And(Selector::turns(turn))))
+	if(hasBonus(Selector::type()(Bonus::SIEGE_WEAPON).And(Selector::turns(turn))))
 	{
 		return 0;
 	}
 	//bind effect check - doesn't influence stack initiative
-	if(useBind && hasBonus(Selector::type(Bonus::BIND_EFFECT).And(Selector::turns(turn))))
+	if(useBind && hasBonus(Selector::type()(Bonus::BIND_EFFECT).And(Selector::turns(turn))))
 	{
 		return 0;
 	}
 
-	return valOfBonuses(Selector::type(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
+	return valOfBonuses(Selector::type()(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
 }
 
 bool IBonusBearer::isLiving() const //TODO: theoreticaly there exists "LIVING" bonus in stack experience documentation
 {
 	static const std::string cachingStr = "IBonusBearer::isLiving";
-	static const CSelector selector = Selector::type(Bonus::UNDEAD)
-		.Or(Selector::type(Bonus::NON_LIVING))
-		.Or(Selector::type(Bonus::GARGOYLE))
-		.Or(Selector::type(Bonus::SIEGE_WEAPON));
+	static const CSelector selector = Selector::type()(Bonus::UNDEAD)
+		.Or(Selector::type()(Bonus::NON_LIVING))
+		.Or(Selector::type()(Bonus::GARGOYLE))
+		.Or(Selector::type()(Bonus::SIEGE_WEAPON));
 
 	return !hasBonus(selector, cachingStr);
 }
@@ -1561,17 +1608,42 @@ std::shared_ptr<Bonus> Bonus::addPropagator(TPropagatorPtr Propagator)
 
 namespace Selector
 {
-	DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> type(&Bonus::type);
-	DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> subtype(&Bonus::subtype);
-	DLL_LINKAGE CSelectFieldEqual<CAddInfo> info(&Bonus::additionalInfo);
-	DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType(&Bonus::source);
-	DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange(&Bonus::effectRange);
+	DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> & type()
+	{
+		static CSelectFieldEqual<Bonus::BonusType> stype(&Bonus::type);
+		return stype;
+	}
+
+	DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype()
+	{
+		static CSelectFieldEqual<TBonusSubtype> ssubtype(&Bonus::subtype);
+		return ssubtype;
+	}
+
+	DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info()
+	{
+		static CSelectFieldEqual<CAddInfo> sinfo(&Bonus::additionalInfo);
+		return sinfo;
+	}
+
+	DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & sourceType()
+	{
+		static CSelectFieldEqual<Bonus::BonusSource> ssourceType(&Bonus::source);
+		return ssourceType;
+	}
+
+	DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> & effectRange()
+	{
+		static CSelectFieldEqual<Bonus::LimitEffect> seffectRange(&Bonus::effectRange);
+		return seffectRange;
+	}
+
 	DLL_LINKAGE CWillLastTurns turns;
 	DLL_LINKAGE CWillLastDays days;
 
 	CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype)
 	{
-		return type(Type).And(subtype(Subtype));
+		return type()(Type).And(subtype()(Subtype));
 	}
 
 	CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, CAddInfo info)
@@ -1796,7 +1868,7 @@ int HasAnotherBonusLimiter::limit(const BonusLimitationContext &context) const
 {
 	CSelector mySelector = isSubtypeRelevant
 							? Selector::typeSubtype(type, subtype)
-							: Selector::type(type);
+							: Selector::type()(type);
 
 	//if we have a bonus of required type accepted, limiter should accept also this bonus
 	if(context.alreadyAccepted.getFirst(mySelector))

+ 35 - 17
lib/HeroBonus.h

@@ -77,18 +77,17 @@ public:
 
 	CBonusProxy & operator=(CBonusProxy && other);
 	CBonusProxy & operator=(const CBonusProxy & other);
-
-	TConstBonusListPtr get() const;
-
 	const BonusList * operator->() const;
-private:
-	mutable int64_t cachedLast;
-	const IBonusBearer * target;
+	TConstBonusListPtr getBonusList() const;
+
+protected:
 	CSelector selector;
-	mutable TConstBonusListPtr data;
+	const IBonusBearer * target;
+	mutable int64_t bonusListCachedLast;
+	mutable TConstBonusListPtr bonusList;
 };
 
-class DLL_LINKAGE CTotalsProxy
+class DLL_LINKAGE CTotalsProxy : public CBonusProxy
 {
 public:
 	CTotalsProxy(const IBonusBearer * Target, CSelector Selector, int InitialValue);
@@ -101,13 +100,17 @@ public:
 	int getMeleeValue() const;
 	int getRangedValue() const;
 	int getValue() const;
+	/**
+	Returns total value of all selected bonuses and sets bonusList as a pointer to the list of selected bonuses
+	@param bonusList is the out list of all selected bonuses
+	@return total value of all selected bonuses and 0 otherwise
+	*/
+	int getValueAndList(TConstBonusListPtr & bonusList) const;
 
 private:
-	const IBonusBearer * target;
-	CSelector selector;
 	int initialValue;
 
-	mutable int64_t cachedLast;
+	mutable int64_t valueCachedLast;
 	mutable int value;
 
 	mutable int64_t meleeCachedLast;
@@ -692,8 +695,12 @@ private:
 	CCheckProxy anaffectedByMorale;
 	static CSelector moraleSelector;
 	CTotalsProxy moraleValue;
+	static CSelector luckSelector;
+	CTotalsProxy luckValue;
 	static CSelector selfMoraleSelector;
 	CCheckProxy selfMorale;
+	static CSelector selfLuckSelector;
+	CCheckProxy selfLuck;
 
 public:
 	//new bonusing node interface
@@ -726,6 +733,14 @@ public:
 
 	int MoraleVal() const; //range [-3, +3]
 	int LuckVal() const; //range [-3, +3]
+	/**
+	 Returns total value of all morale bonuses and sets bonusList as a pointer to the list of selected bonuses.
+	 @param bonusList is the out param it's list of all selected bonuses
+	 @return total value of all morale in the range [-3, +3] and 0 otherwise
+	*/
+	int MoraleValAndBonusList(TConstBonusListPtr & bonusList) const;
+	int LuckValAndBonusList(TConstBonusListPtr & bonusList) const;
+
 	ui32 MaxHealth() const; //get max HP of stack with all modifiers
 	bool isLiving() const; //non-undead, non-non living or alive
 	virtual si32 magicResistance() const;
@@ -864,7 +879,10 @@ public:
 	CSelector operator()(const T &valueToCompareAgainst) const
 	{
 		auto ptr2 = ptr; //We need a COPY because we don't want to reference this (might be outlived by lambda)
-		return [ptr2, valueToCompareAgainst](const Bonus *bonus) {  return bonus->*ptr2 == valueToCompareAgainst; };
+		return [ptr2, valueToCompareAgainst](const Bonus *bonus)
+		{
+			return bonus->*ptr2 == valueToCompareAgainst;
+		};
 	}
 };
 
@@ -1112,11 +1130,11 @@ public:
 
 namespace Selector
 {
-	extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> type;
-	extern DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> subtype;
-	extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> info;
-	extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType;
-	extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange;
+	extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> & type();
+	extern DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype();
+	extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info();
+	extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & sourceType();
+	extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> & effectRange();
 	extern DLL_LINKAGE CWillLastTurns turns;
 	extern DLL_LINKAGE CWillLastDays days;
 

+ 2 - 2
lib/NetPacksLib.cpp

@@ -1310,7 +1310,7 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs(CGameState *gs)
 	case Bonus::POISON:
 	{
 		auto b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON)
-				.And(Selector::type(Bonus::STACK_HEALTH)));
+				.And(Selector::type()(Bonus::STACK_HEALTH)));
 		if (b)
 			b->val = val;
 		break;
@@ -1601,7 +1601,7 @@ DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState * gs)
 		}
 		case UNBIND:
 		{
-			stack->removeBonusesRecursive(Selector::type(Bonus::BIND_EFFECT));
+			stack->removeBonusesRecursive(Selector::type()(Bonus::BIND_EFFECT));
 			break;
 		}
 		case CLONED:

+ 26 - 26
lib/battle/CBattleInfoCallback.cpp

@@ -164,7 +164,7 @@ bool CBattleInfoCallback::battleHasWallPenalty(const IBonusBearer * shooter, Bat
 		return false;
 
 	const std::string cachingStrNoWallPenalty = "type_NO_WALL_PENALTY";
-	static const auto selectorNoWallPenalty = Selector::type(Bonus::NO_WALL_PENALTY);
+	static const auto selectorNoWallPenalty = Selector::type()(Bonus::NO_WALL_PENALTY);
 
 	if(shooter->hasBonus(selectorNoWallPenalty, cachingStrNoWallPenalty))
 		return false;
@@ -680,10 +680,10 @@ bool CBattleInfoCallback::battleCanShoot(const battle::Unit * attacker) const
 		return false;
 
 	//forgetfulness
-	TConstBonusListPtr forgetfulList = attacker->getBonuses(Selector::type(Bonus::FORGETFULL));
+	TConstBonusListPtr forgetfulList = attacker->getBonuses(Selector::type()(Bonus::FORGETFULL));
 	if (!forgetfulList->empty())
 	{
-		int forgetful = forgetfulList->valOfBonuses(Selector::type(Bonus::FORGETFULL));
+		int forgetful = forgetfulList->valOfBonuses(Selector::type()(Bonus::FORGETFULL));
 
 		//advanced+ level
 		if (forgetful > 1)
@@ -712,10 +712,10 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 {
 	auto battleBonusValue = [&](const IBonusBearer * bearer, CSelector selector) -> int
 	{
-		auto noLimit = Selector::effectRange(Bonus::NO_LIMIT);
+		auto noLimit = Selector::effectRange()(Bonus::NO_LIMIT);
 		auto limitMatches = info.shooting
-							? Selector::effectRange(Bonus::ONLY_DISTANCE_FIGHT)
-							: Selector::effectRange(Bonus::ONLY_MELEE_FIGHT);
+							? Selector::effectRange()(Bonus::ONLY_DISTANCE_FIGHT)
+							: Selector::effectRange()(Bonus::ONLY_MELEE_FIGHT);
 
 		//any regular bonuses or just ones for melee/ranged
 		return bearer->getBonuses(selector, noLimit.Or(limitMatches))->totalValue();
@@ -743,7 +743,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 	}
 
 	const std::string cachingStrSiedgeWeapon = "type_SIEGE_WEAPON";
-	static const auto selectorSiedgeWeapon = Selector::type(Bonus::SIEGE_WEAPON);
+	static const auto selectorSiedgeWeapon = Selector::type()(Bonus::SIEGE_WEAPON);
 
 	if(attackerBonuses->hasBonus(selectorSiedgeWeapon, cachingStrSiedgeWeapon) && info.attacker->creatureIndex() != CreatureID::ARROW_TOWERS) //any siege weapon, but only ballista can attack (second condition - not arrow turret)
 	{ //minDmg and maxDmg are multiplied by hero attack + 1
@@ -760,14 +760,14 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 
 	double attackDefenceDifference = 0.0;
 
-	double multAttackReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type(Bonus::GENERAL_ATTACK_REDUCTION)) / 100.0;
+	double multAttackReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type()(Bonus::GENERAL_ATTACK_REDUCTION)) / 100.0;
 	attackDefenceDifference += info.attacker->getAttack(info.shooting) * multAttackReduction;
 
-	double multDefenceReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type(Bonus::ENEMY_DEFENCE_REDUCTION)) / 100.0;
+	double multDefenceReduction = 1.0 - battleBonusValue(attackerBonuses, Selector::type()(Bonus::ENEMY_DEFENCE_REDUCTION)) / 100.0;
 	attackDefenceDifference -= info.defender->getDefence(info.shooting) * multDefenceReduction;
 
 	const std::string cachingStrSlayer = "type_SLAYER";
-	static const auto selectorSlayer = Selector::type(Bonus::SLAYER);
+	static const auto selectorSlayer = Selector::type()(Bonus::SLAYER);
 
 	//slayer handling //TODO: apply only ONLY_MELEE_FIGHT / DISTANCE_FIGHT?
 	auto slayerEffects = attackerBonuses->getBonuses(selectorSlayer, cachingStrSlayer);
@@ -807,10 +807,10 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 	}
 
 	const std::string cachingStrJousting = "type_JOUSTING";
-	static const auto selectorJousting = Selector::type(Bonus::JOUSTING);
+	static const auto selectorJousting = Selector::type()(Bonus::JOUSTING);
 
 	const std::string cachingStrChargeImmunity = "type_CHARGE_IMMUNITY";
-	static const auto selectorChargeImmunity = Selector::type(Bonus::CHARGE_IMMUNITY);
+	static const auto selectorChargeImmunity = Selector::type()(Bonus::CHARGE_IMMUNITY);
 
 	//applying jousting bonus
 	if(info.chargedFields > 0 && attackerBonuses->hasBonus(selectorJousting, cachingStrJousting) && !defenderBonuses->hasBonus(selectorChargeImmunity, cachingStrChargeImmunity))
@@ -836,11 +836,11 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 	//handling hate effect
 	//assume that unit have only few HATE features and cache them all
 	const std::string cachingStrHate = "type_HATE";
-	static const auto selectorHate = Selector::type(Bonus::HATE);
+	static const auto selectorHate = Selector::type()(Bonus::HATE);
 
 	auto allHateEffects = attackerBonuses->getBonuses(selectorHate, cachingStrHate);
 
-	additiveBonus += allHateEffects->valOfBonuses(Selector::subtype(info.defender->creatureIndex())) / 100.0;
+	additiveBonus += allHateEffects->valOfBonuses(Selector::subtype()(info.defender->creatureIndex())) / 100.0;
 
 	const std::string cachingStrMeleeReduction = "type_GENERAL_DAMAGE_REDUCTIONs_0";
 	static const auto selectorMeleeReduction = Selector::typeSubtype(Bonus::GENERAL_DAMAGE_REDUCTION, 0);
@@ -863,7 +863,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 		//todo: set actual percentage in spell bonus configuration instead of just level; requires non trivial backward compatibility handling
 
 		//get list first, total value of 0 also counts
-		TConstBonusListPtr forgetfulList = attackerBonuses->getBonuses(Selector::type(Bonus::FORGETFULL),"type_FORGETFULL");
+		TConstBonusListPtr forgetfulList = attackerBonuses->getBonuses(Selector::type()(Bonus::FORGETFULL),"type_FORGETFULL");
 
 		if(!forgetfulList->empty())
 		{
@@ -878,10 +878,10 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 	}
 
 	const std::string cachingStrForcedMinDamage = "type_ALWAYS_MINIMUM_DAMAGE";
-	static const auto selectorForcedMinDamage = Selector::type(Bonus::ALWAYS_MINIMUM_DAMAGE);
+	static const auto selectorForcedMinDamage = Selector::type()(Bonus::ALWAYS_MINIMUM_DAMAGE);
 
 	const std::string cachingStrForcedMaxDamage = "type_ALWAYS_MAXIMUM_DAMAGE";
-	static const auto selectorForcedMaxDamage = Selector::type(Bonus::ALWAYS_MAXIMUM_DAMAGE);
+	static const auto selectorForcedMaxDamage = Selector::type()(Bonus::ALWAYS_MAXIMUM_DAMAGE);
 
 	TConstBonusListPtr curseEffects = attackerBonuses->getBonuses(selectorForcedMinDamage, cachingStrForcedMinDamage);
 	TConstBonusListPtr blessEffects = attackerBonuses->getBonuses(selectorForcedMaxDamage, cachingStrForcedMaxDamage);
@@ -920,7 +920,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 	else
 	{
 		const std::string cachingStrNoMeleePenalty = "type_NO_MELEE_PENALTY";
-		static const auto selectorNoMeleePenalty = Selector::type(Bonus::NO_MELEE_PENALTY);
+		static const auto selectorNoMeleePenalty = Selector::type()(Bonus::NO_MELEE_PENALTY);
 
 		if(info.attacker->isShooter() && !attackerBonuses->hasBonus(selectorNoMeleePenalty, cachingStrNoMeleePenalty))
 			multBonus *= 0.5;
@@ -930,7 +930,7 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
 	if(info.attacker->creatureIndex() == CreatureID::PSYCHIC_ELEMENTAL)
 	{
 		const std::string cachingStrMindImmunity = "type_MIND_IMMUNITY";
-		static const auto selectorMindImmunity = Selector::type(Bonus::MIND_IMMUNITY);
+		static const auto selectorMindImmunity = Selector::type()(Bonus::MIND_IMMUNITY);
 
 		if(defenderBonuses->hasBonus(selectorMindImmunity, cachingStrMindImmunity))
 			multBonus *= 0.5;
@@ -1596,7 +1596,7 @@ bool CBattleInfoCallback::battleHasDistancePenalty(const IBonusBearer * shooter,
 	RETURN_IF_NOT_BATTLE(false);
 
 	const std::string cachingStrNoDistancePenalty = "type_NO_DISTANCE_PENALTY";
-	static const auto selectorNoDistancePenalty = Selector::type(Bonus::NO_DISTANCE_PENALTY);
+	static const auto selectorNoDistancePenalty = Selector::type()(Bonus::NO_DISTANCE_PENALTY);
 
 	if(shooter->hasBonus(selectorNoDistancePenalty, cachingStrNoDistancePenalty))
 		return false;
@@ -1831,9 +1831,9 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(CRandomGenerator & rand, c
 		{
 			auto kingMonster = getAliveEnemy([&](const CStack * stack) -> bool //look for enemy, non-shooting stack
 			{
-				const auto isKing = Selector::type(Bonus::KING1)
-									.Or(Selector::type(Bonus::KING2))
-									.Or(Selector::type(Bonus::KING3));
+				const auto isKing = Selector::type()(Bonus::KING1)
+									.Or(Selector::type()(Bonus::KING2))
+									.Or(Selector::type()(Bonus::KING3));
 
 				return stack->hasBonus(isKing);
 			});
@@ -1860,7 +1860,7 @@ SpellID CBattleInfoCallback::getRandomCastedSpell(CRandomGenerator & rand,const
 {
 	RETURN_IF_NOT_BATTLE(SpellID::NONE);
 
-	TConstBonusListPtr bl = caster->getBonuses(Selector::type(Bonus::SPELLCASTER));
+	TConstBonusListPtr bl = caster->getBonuses(Selector::type()(Bonus::SPELLCASTER));
 	if (!bl->size())
 		return SpellID::NONE;
 	int totalWeight = 0;
@@ -1917,7 +1917,7 @@ si8 CBattleInfoCallback::battleMinSpellLevel(ui8 side) const
 	if(!node)
 		return 0;
 
-	auto b = node->getBonuses(Selector::type(Bonus::BLOCK_MAGIC_BELOW));
+	auto b = node->getBonuses(Selector::type()(Bonus::BLOCK_MAGIC_BELOW));
 	if(b->size())
 		return b->totalValue();
 
@@ -1936,7 +1936,7 @@ si8 CBattleInfoCallback::battleMaxSpellLevel(ui8 side) const
 		return GameConstants::SPELL_LEVELS;
 
 	//We can't "just get value" - it'd be 0 if there are bonuses (and all would be blocked)
-	auto b = node->getBonuses(Selector::type(Bonus::BLOCK_MAGIC_ABOVE));
+	auto b = node->getBonuses(Selector::type()(Bonus::BLOCK_MAGIC_ABOVE));
 	if(b->size())
 		return b->totalValue();
 

+ 1 - 1
lib/battle/CBattleInfoEssentials.cpp

@@ -386,7 +386,7 @@ PlayerColor CBattleInfoEssentials::battleGetOwner(const battle::Unit * unit) con
 
 	PlayerColor initialOwner = getBattle()->getSidePlayer(unit->unitSide());
 
-	static CSelector selector = Selector::type(Bonus::HYPNOTIZED);
+	static CSelector selector = Selector::type()(Bonus::HYPNOTIZED);
 	static std::string cachingString = "type_103s-1";
 
 	if(unit->hasBonus(selector, cachingString))

+ 11 - 11
lib/battle/CUnitState.cpp

@@ -89,8 +89,8 @@ void CAmmo::serializeJson(JsonSerializeFormat & handler)
 
 ///CShots
 CShots::CShots(const battle::Unit * Owner)
-	: CAmmo(Owner, Selector::type(Bonus::SHOTS)),
-	shooter(Owner, Selector::type(Bonus::SHOOTER))
+	: CAmmo(Owner, Selector::type()(Bonus::SHOTS)),
+	shooter(Owner, Selector::type()(Bonus::SHOOTER))
 {
 }
 
@@ -128,7 +128,7 @@ int32_t CShots::total() const
 
 ///CCasts
 CCasts::CCasts(const battle::Unit * Owner):
-	CAmmo(Owner, Selector::type(Bonus::CASTS))
+	CAmmo(Owner, Selector::type()(Bonus::CASTS))
 {
 }
 
@@ -145,10 +145,10 @@ CCasts & CCasts::operator=(const CCasts & other)
 
 ///CRetaliations
 CRetaliations::CRetaliations(const battle::Unit * Owner)
-	: CAmmo(Owner, Selector::type(Bonus::ADDITIONAL_RETALIATION)),
+	: CAmmo(Owner, Selector::type()(Bonus::ADDITIONAL_RETALIATION)),
 	totalCache(0),
-	noRetaliation(Owner, Selector::type(Bonus::SIEGE_WEAPON).Or(Selector::type(Bonus::HYPNOTIZED)).Or(Selector::type(Bonus::NO_RETALIATION))),
-	unlimited(Owner, Selector::type(Bonus::UNLIMITED_RETALIATIONS))
+	noRetaliation(Owner, Selector::type()(Bonus::SIEGE_WEAPON).Or(Selector::type()(Bonus::HYPNOTIZED)).Or(Selector::type()(Bonus::NO_RETALIATION))),
+	unlimited(Owner, Selector::type()(Bonus::UNLIMITED_RETALIATIONS))
 {
 }
 
@@ -388,13 +388,13 @@ CUnitState::CUnitState()
 	counterAttacks(this),
 	health(this),
 	shots(this),
-	totalAttacks(this, Selector::type(Bonus::ADDITIONAL_ATTACK), 1),
+	totalAttacks(this, Selector::type()(Bonus::ADDITIONAL_ATTACK), 1),
 	minDamage(this, Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 1)), 0),
 	maxDamage(this, Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2)), 0),
 	attack(this, Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), 0),
 	defence(this, Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), 0),
-	inFrenzy(this, Selector::type(Bonus::IN_FRENZY)),
-	cloneLifetimeMarker(this, Selector::type(Bonus::NONE).And(Selector::source(Bonus::SPELL_EFFECT, SpellID::CLONE))),
+	inFrenzy(this, Selector::type()(Bonus::IN_FRENZY)),
+	cloneLifetimeMarker(this, Selector::type()(Bonus::NONE).And(Selector::source(Bonus::SPELL_EFFECT, SpellID::CLONE))),
 	cloneID(-1),
 	position()
 {
@@ -618,12 +618,12 @@ void CUnitState::setPosition(BattleHex hex)
 
 int32_t CUnitState::getInitiative(int turn) const
 {
-	return valOfBonuses(Selector::type(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
+	return valOfBonuses(Selector::type()(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
 }
 
 bool CUnitState::canMove(int turn) const
 {
-	return alive() && !hasBonus(Selector::type(Bonus::NOT_ACTIVE).And(Selector::turns(turn))); //eg. Ammo Cart or blinded creature
+	return alive() && !hasBonus(Selector::type()(Bonus::NOT_ACTIVE).And(Selector::turns(turn))); //eg. Ammo Cart or blinded creature
 }
 
 bool CUnitState::defended(int turn) const

+ 3 - 3
lib/mapObjects/CArmedInstance.cpp

@@ -37,7 +37,7 @@ void CArmedInstance::randomizeArmy(int type)
 }
 
 // Take Angelic Alliance troop-mixing freedom of non-evil units into account.
-CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type(Bonus::NONEVIL_ALIGNMENT_MIX);
+CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(Bonus::NONEVIL_ALIGNMENT_MIX);
 
 CArmedInstance::CArmedInstance()
 	:nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector)
@@ -50,7 +50,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
 	if(!validTypes(false)) //object not randomized, don't bother
 		return;
 
-	auto b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
+	auto b = getExportedBonusList().getFirst(Selector::sourceType()(Bonus::ARMY).And(Selector::type()(Bonus::MORALE)));
  	if(!b)
 	{
 		b = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@@ -62,7 +62,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
 	bool hasUndead = false;
 
 	const std::string undeadCacheKey = "type_UNDEAD";
-	static const CSelector undeadSelector = Selector::type(Bonus::UNDEAD);
+	static const CSelector undeadSelector = Selector::type()(Bonus::UNDEAD);
 
 	for(auto slot : Slots())
 	{

+ 10 - 10
lib/mapObjects/CGHeroInstance.cpp

@@ -56,7 +56,7 @@ static int lowestSpeed(const CGHeroInstance * chi)
 	auto i = chi->Slots().begin();
 	//TODO? should speed modifiers (eg from artifacts) affect hero movement?
 
-	static const CSelector selectorSTACKS_SPEED = Selector::type(Bonus::STACKS_SPEED);
+	static const CSelector selectorSTACKS_SPEED = Selector::type()(Bonus::STACKS_SPEED);
 	static const std::string keySTACKS_SPEED = "type_"+std::to_string((si32)Bonus::STACKS_SPEED);
 
 	int ret = (i++)->second->valOfBonuses(selectorSTACKS_SPEED, keySTACKS_SPEED);
@@ -289,7 +289,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
 
 	if(portrait < 0 || portrait == 255)
 		portrait = type->imageIndex;
-	if(!hasBonus(Selector::sourceType(Bonus::HERO_BASE_SKILL)))
+	if(!hasBonus(Selector::sourceType()(Bonus::HERO_BASE_SKILL)))
 	{
 		for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
 		{
@@ -534,7 +534,7 @@ void CGHeroInstance::initObj(CRandomGenerator & rand)
 
 void CGHeroInstance::recreateSecondarySkillsBonuses()
 {
-	auto secondarySkillsBonuses = getBonuses(Selector::sourceType(Bonus::SECONDARY_SKILL));
+	auto secondarySkillsBonuses = getBonuses(Selector::sourceType()(Bonus::SECONDARY_SKILL));
 	for(auto bonus : *secondarySkillsBonuses)
 		removeBonus(bonus);
 
@@ -816,7 +816,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
 		// figure out what to raise - pick strongest creature meeting requirements
 		CreatureID creatureTypeRaised = CreatureID::SKELETON;
 		int requiredCasualtyLevel = 1;
-		TConstBonusListPtr improvedNecromancy = getBonuses(Selector::type(Bonus::IMPROVED_NECROMANCY));
+		TConstBonusListPtr improvedNecromancy = getBonuses(Selector::type()(Bonus::IMPROVED_NECROMANCY));
 		if(!improvedNecromancy->empty())
 		{
 			auto getCreatureID = [necromancyLevel](std::shared_ptr<Bonus> bonus) -> CreatureID
@@ -988,7 +988,7 @@ int CGHeroInstance::getSpellCost(const CSpell * sp) const
 void CGHeroInstance::pushPrimSkill( PrimarySkill::PrimarySkill which, int val )
 {
 	assert(!hasBonus(Selector::typeSubtype(Bonus::PRIMARY_SKILL, which)
-						.And(Selector::sourceType(Bonus::HERO_BASE_SKILL))));
+						.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL))));
 	addNewBonus(std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id.getNum(), which));
 }
 
@@ -1257,9 +1257,9 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si
 {
 	if(primarySkill < PrimarySkill::EXPERIENCE)
 	{
-		auto skill = getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL)
-			.And(Selector::subtype(primarySkill))
-			.And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
+		auto skill = getBonusLocalFirst(Selector::type()(Bonus::PRIMARY_SKILL)
+			.And(Selector::subtype()(primarySkill))
+			.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)));
 		assert(skill);
 
 		if(abs)
@@ -1427,7 +1427,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
 	//primary skills
 	if(handler.saving)
 	{
-		const bool haveSkills = hasBonus(Selector::type(Bonus::PRIMARY_SKILL).And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
+		const bool haveSkills = hasBonus(Selector::type()(Bonus::PRIMARY_SKILL).And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)));
 
 		if(haveSkills)
 		{
@@ -1435,7 +1435,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
 
 			for(int i = 0; i < GameConstants::PRIMARY_SKILLS; ++i)
 			{
-				int value = valOfBonuses(Selector::typeSubtype(Bonus::PRIMARY_SKILL, i).And(Selector::sourceType(Bonus::HERO_BASE_SKILL)));
+				int value = valOfBonuses(Selector::typeSubtype(Bonus::PRIMARY_SKILL, i).And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)));
 
 				handler.serializeInt(PrimarySkill::names[i], value, 0);
 			}

+ 4 - 4
lib/mapObjects/CGTownInstance.cpp

@@ -562,12 +562,12 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
 		ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[591], dwellingBonus));// \nExternal dwellings %+d
 
 	//other *-of-legion-like bonuses (%d to growth cumulative with grail)
-	TConstBonusListPtr bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH).And(Selector::subtype(level)));
+	TConstBonusListPtr bonuses = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH).And(Selector::subtype()(level)));
 	for(const auto & b : *bonuses)
 		ret.entries.push_back(GrowthInfo::Entry(b->val, b->Description()));
 
 	//statue-of-legion-like bonus: % to base+castle
-	TConstBonusListPtr bonuses2 = getBonuses(Selector::type(Bonus::CREATURE_GROWTH_PERCENT));
+	TConstBonusListPtr bonuses2 = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH_PERCENT));
 	for(const auto & b : *bonuses2)
 		ret.entries.push_back(GrowthInfo::Entry(b->val * (base + castleBonus) / 100, b->Description()));
 
@@ -1166,7 +1166,7 @@ void CGTownInstance::deserializationFix()
 
 void CGTownInstance::updateMoraleBonusFromArmy()
 {
-	auto b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
+	auto b = getExportedBonusList().getFirst(Selector::sourceType()(Bonus::ARMY).And(Selector::type()(Bonus::MORALE)));
 	if(!b)
 	{
 		b = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@@ -1187,7 +1187,7 @@ void CGTownInstance::recreateBuildingsBonuses()
 	static TPropagatorPtr playerProp(new CPropagatorNodeType(PLAYER));
 
 	BonusList bl;
-	getExportedBonusList().getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
+	getExportedBonusList().getBonuses(bl, Selector::sourceType()(Bonus::TOWN_STRUCTURE));
 	for(auto b : bl)
 		removeBonus(b);
 

+ 1 - 1
lib/mapObjects/MiscObjects.cpp

@@ -1422,7 +1422,7 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
 
 	if(handler.saving && ID == Obj::SPELL_SCROLL)
 	{
-		const std::shared_ptr<Bonus> b = storedArtifact->getBonusLocalFirst(Selector::type(Bonus::SPELL));
+		const std::shared_ptr<Bonus> b = storedArtifact->getBonusLocalFirst(Selector::type()(Bonus::SPELL));
 		SpellID spellId(b->subtype);
 
 		handler.serializeId("spell", spellId, SpellID::NONE);

+ 2 - 2
lib/mapping/MapFormatH3M.cpp

@@ -1712,8 +1712,8 @@ CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven, const i
 		bool hasCustomPrimSkills = reader.readBool();
 		if(hasCustomPrimSkills)
 		{
-			auto ps = nhi->getAllBonuses(Selector::type(Bonus::PRIMARY_SKILL)
-								.And(Selector::sourceType(Bonus::HERO_BASE_SKILL)), nullptr);
+			auto ps = nhi->getAllBonuses(Selector::type()(Bonus::PRIMARY_SKILL)
+								.And(Selector::sourceType()(Bonus::HERO_BASE_SKILL)), nullptr);
 			if(ps->size())
 			{
 				logGlobal->warn("Hero %s subID=%d has set primary skills twice (in map properties and on adventure map instance). Using the latter set...", nhi->name, nhi->subID);

+ 1 - 1
lib/spells/CSpellHandler.cpp

@@ -437,7 +437,7 @@ int64_t CSpell::adjustRawDamage(const spells::Caster * caster, const battle::Uni
 			}
 		});
 
-		CSelector selector = Selector::type(Bonus::SPELL_DAMAGE_REDUCTION).And(Selector::subtype(-1));
+		CSelector selector = Selector::type()(Bonus::SPELL_DAMAGE_REDUCTION).And(Selector::subtype()(-1));
 
 		//general spell dmg reduction
 		if(bearer->hasBonus(selector))

+ 2 - 2
lib/spells/ISpellMechanics.cpp

@@ -302,7 +302,7 @@ void BattleCast::cast(const SpellCastEnvironment * env)
 	if(tryMagicMirror)
 	{
 		const std::string magicMirrorCacheStr = "type_MAGIC_MIRROR";
-		static const auto magicMirrorSelector = Selector::type(Bonus::MAGIC_MIRROR);
+		static const auto magicMirrorSelector = Selector::type()(Bonus::MAGIC_MIRROR);
 
 		auto rangeGen = env->getRandomGenerator().getInt64Range(0, 99);
 
@@ -534,7 +534,7 @@ bool BaseMechanics::adaptProblem(ESpellCastProblem::ESpellCastProblem source, Pr
 				return adaptGenericProblem(target);
 
 			//Recanter's Cloak or similar effect. Try to retrieve bonus
-			const auto b = hero->getBonusLocalFirst(Selector::type(Bonus::BLOCK_MAGIC_ABOVE));
+			const auto b = hero->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_MAGIC_ABOVE));
 			//TODO what about other values and non-artifact sources?
 			if(b && b->val == 2 && b->source == Bonus::ARTIFACT)
 			{

+ 4 - 4
lib/spells/TargetCondition.cpp

@@ -75,7 +75,7 @@ public:
 protected:
 	bool check(const Mechanics * m, const battle::Unit * target) const override
 	{
-		return target->hasBonus(Selector::type(type));
+		return target->hasBonus(Selector::type()(type));
 	}
 
 private:
@@ -115,7 +115,7 @@ protected:
 		std::stringstream cachingStr;
 		cachingStr << "type_" << Bonus::LEVEL_SPELL_IMMUNITY << "addInfo_1";
 
-		TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY).And(Selector::info(1)), cachingStr.str());
+		TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type()(Bonus::LEVEL_SPELL_IMMUNITY).And(Selector::info()(1)), cachingStr.str());
 		
 		return levelImmunities->size() == 0 ||
 		levelImmunities->totalValue() < m->getSpellLevel() ||
@@ -190,7 +190,7 @@ public:
 protected:
 	bool check(const Mechanics * m, const battle::Unit * target) const override
 	{
-		TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
+		TConstBonusListPtr levelImmunities = target->getBonuses(Selector::type()(Bonus::LEVEL_SPELL_IMMUNITY));
 		return levelImmunities->size() == 0 ||
 		levelImmunities->totalValue() < m->getSpellLevel() ||
 		m->getSpellLevel() <= 0;
@@ -263,7 +263,7 @@ class ReceptiveFeatureCondition : public TargetConditionItemBase
 public:
 	ReceptiveFeatureCondition()
 	{
-		selector = Selector::type(Bonus::RECEPTIVE);
+		selector = Selector::type()(Bonus::RECEPTIVE);
 		cachingString = "type_RECEPTIVE";
 	}
 

+ 1 - 1
lib/spells/effects/Timed.cpp

@@ -120,7 +120,7 @@ void Timed::describeEffect(std::vector<MetaString> & log, const Mechanics * m, c
 			{
 				if(bonus.val < 0)
 				{
-					BonusList unitHealth = *target->getBonuses(Selector::type(Bonus::STACK_HEALTH));
+					BonusList unitHealth = *target->getBonuses(Selector::type()(Bonus::STACK_HEALTH));
 
 					auto oldHealth = unitHealth.totalValue();
 					unitHealth.push_back(std::make_shared<Bonus>(bonus));

+ 16 - 16
server/CGameHandler.cpp

@@ -1016,7 +1016,7 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
 			applyBattleEffects(bat, attackerState, fireShield, stack, distance, true);
 	}
 
-	std::shared_ptr<const Bonus> bonus = attacker->getBonusLocalFirst(Selector::type(Bonus::SPELL_LIKE_ATTACK));
+	std::shared_ptr<const Bonus> bonus = attacker->getBonusLocalFirst(Selector::type()(Bonus::SPELL_LIKE_ATTACK));
 	if(bonus && ranged) //TODO: make it work in melee?
 	{
 		//this is need for displaying hit animation
@@ -1883,7 +1883,7 @@ void CGameHandler::newTurn()
 			{
 				if (getPlayerStatus(player.first) == EPlayerStatus::INGAME &&
 					getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES)
-					changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type(Bonus::DARKNESS))->val, player.first, true);
+					changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type()(Bonus::DARKNESS))->val, player.first, true);
 			}
 		}
 	}
@@ -4463,7 +4463,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 			const CStack * summoner = gs->curB->battleGetStackByID(ba.stackNumber);
 			const CStack * destStack = gs->curB->battleGetStackByPos(target.at(0).hexValue, false);
 
-			CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
+			CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type()(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
 
 			ui64 risedHp = summoner->getCount() * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, summonedType.toEnum());
 			ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;
@@ -4508,7 +4508,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 			const CStack * stack = gs->curB->battleGetStackByID(ba.stackNumber);
 			SpellID spellID = SpellID(ba.actionSubtype);
 
-			std::shared_ptr<const Bonus> randSpellcaster = stack->getBonusLocalFirst(Selector::type(Bonus::RANDOM_SPELLCASTER));
+			std::shared_ptr<const Bonus> randSpellcaster = stack->getBonusLocalFirst(Selector::type()(Bonus::RANDOM_SPELLCASTER));
 			std::shared_ptr<const Bonus> spellcaster = stack->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
 
 			//TODO special bonus for genies ability
@@ -4669,7 +4669,7 @@ bool CGameHandler::makeCustomAction(BattleAction & ba)
 
 void CGameHandler::stackEnchantedTrigger(const CStack * st)
 {
-	auto bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTED)));
+	auto bl = *(st->getBonuses(Selector::type()(Bonus::ENCHANTED)));
 	for(auto b : bl)
 	{
 		const CSpell * sp = SpellID(b->subtype).toSpell();
@@ -4708,10 +4708,10 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
 	if (st->alive())
 	{
 		//unbind
-		if (st->hasBonus(Selector::type(Bonus::BIND_EFFECT)))
+		if (st->hasBonus(Selector::type()(Bonus::BIND_EFFECT)))
 		{
 			bool unbind = true;
-			BonusList bl = *(st->getBonuses(Selector::type(Bonus::BIND_EFFECT)));
+			BonusList bl = *(st->getBonuses(Selector::type()(Bonus::BIND_EFFECT)));
 			auto adjacent = gs->curB->battleAdjacentUnits(st);
 
 			for (auto b : bl)
@@ -4754,7 +4754,7 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
 
 		if (st->hasBonusOfType(Bonus::POISON))
 		{
-			std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON).And(Selector::type(Bonus::STACK_HEALTH)));
+			std::shared_ptr<const Bonus> b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON).And(Selector::type()(Bonus::STACK_HEALTH)));
 			if (b) //TODO: what if not?...
 			{
 				bte.val = std::max (b->val - 10, -(st->valOfBonuses(Bonus::POISON)));
@@ -4802,7 +4802,7 @@ void CGameHandler::stackTurnTrigger(const CStack *st)
 				}
 			}
 		}
-		BonusList bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTER)));
+		BonusList bl = *(st->getBonuses(Selector::type()(Bonus::ENCHANTER)));
 		int side = gs->curB->whatSide(st->owner);
 		if(st->canCast() && gs->curB->battleGetEnchanterCounter(side) == 0)
 		{
@@ -5428,7 +5428,7 @@ void CGameHandler::attackCasting(bool ranged, Bonus::BonusType attackMode, const
 	if(attacker->hasBonusOfType(attackMode))
 	{
 		std::set<SpellID> spellsToCast;
-		TConstBonusListPtr spells = attacker->getBonuses(Selector::type(attackMode));
+		TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
 		for(const auto & sf : *spells)
 		{
 			spellsToCast.insert(SpellID(sf->subtype));
@@ -5538,7 +5538,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
 		return;
 
 	int64_t acidDamage = 0;
-	TConstBonusListPtr acidBreath = attacker->getBonuses(Selector::type(Bonus::ACID_BREATH));
+	TConstBonusListPtr acidBreath = attacker->getBonuses(Selector::type()(Bonus::ACID_BREATH));
 	for(const auto & b : *acidBreath)
 	{
 		if(b->additionalInfo[0] > getRandomGenerator().nextInt(99))
@@ -5569,7 +5569,7 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
 		if(getRandomGenerator().getDoubleRange(0, 1)() > chanceToTrigger)
 			return;
 
-		int bonusAdditionalInfo = attacker->getBonus(Selector::type(Bonus::TRANSMUTATION))->additionalInfo[0];
+		int bonusAdditionalInfo = attacker->getBonus(Selector::type()(Bonus::TRANSMUTATION))->additionalInfo[0];
 
 		if(defender->getCreature()->idNumber == bonusAdditionalInfo ||
 			(bonusAdditionalInfo == CAddInfo::NONE && defender->getCreature()->idNumber == attacker->getCreature()->idNumber))
@@ -5611,13 +5611,13 @@ void CGameHandler::handleAfterAttackCasting(bool ranged, const CStack * attacker
 		if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 0)) //killing by percentage
 		{
 			chanceToTrigger = attacker->valOfBonuses(Bonus::DESTRUCTION, 0) / 100.0f;
-			int percentageToDie = attacker->getBonus(Selector::type(Bonus::DESTRUCTION).And(Selector::subtype(0)))->additionalInfo[0];
+			int percentageToDie = attacker->getBonus(Selector::type()(Bonus::DESTRUCTION).And(Selector::subtype()(0)))->additionalInfo[0];
 			amountToDie = static_cast<int>(defender->getCount() * percentageToDie * 0.01f);
 		}
 		else if(attacker->hasBonusOfType(Bonus::DESTRUCTION, 1)) //killing by count
 		{
 			chanceToTrigger = attacker->valOfBonuses(Bonus::DESTRUCTION, 1) / 100.0f;
-			amountToDie = attacker->getBonus(Selector::type(Bonus::DESTRUCTION).And(Selector::subtype(1)))->additionalInfo[0];
+			amountToDie = attacker->getBonus(Selector::type()(Bonus::DESTRUCTION).And(Selector::subtype()(1)))->additionalInfo[0];
 		}
 
 		vstd::amin(chanceToTrigger, 1); //cap trigger chance at 100%
@@ -5932,7 +5932,7 @@ void CGameHandler::runBattle()
 	{
 		if (stack->hasBonusOfType(Bonus::SUMMON_GUARDIANS))
 		{
-			std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type(Bonus::SUMMON_GUARDIANS));
+			std::shared_ptr<const Bonus> summonInfo = stack->getBonus(Selector::type()(Bonus::SUMMON_GUARDIANS));
 			auto accessibility = getAccesibility();
 			CreatureID creatureData = CreatureID(summonInfo->subtype);
 			std::vector<BattleHex> targetHexes;
@@ -5977,7 +5977,7 @@ void CGameHandler::runBattle()
 		auto h = gs->curB->battleGetFightingHero(i);
 		if (h)
 		{
-			TConstBonusListPtr bl = h->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
+			TConstBonusListPtr bl = h->getBonuses(Selector::type()(Bonus::OPENING_BATTLE_SPELL));
 
 			for (auto b : *bl)
 			{