Browse Source

vcmi: morale and luck now also IFactionMember

Not all bonus bearers have morale and luck, only faction members
Konstantin 2 years ago
parent
commit
a2d4c72016

+ 7 - 7
client/widgets/MiscWidgets.cpp

@@ -372,7 +372,7 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town)
 	init(InfoAboutTown(town, true));
 }
 
-void MoraleLuckBox::set(const IBonusBearer * node)
+void MoraleLuckBox::set(const IFactionMember * node)
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 
@@ -393,21 +393,21 @@ void MoraleLuckBox::set(const IBonusBearer * node)
 	text = CGI->generaltexth->arraytxt[textId[morale]];
 	boost::algorithm::replace_first(text,"%s",CGI->generaltexth->arraytxt[neutralDescr[morale]-mrlt]);
 
-	if (morale && node && (node->hasBonusOfType(Bonus::UNDEAD)
-			|| node->hasBonusOfType(Bonus::NON_LIVING)))
+	if (morale && node && (node->getBonusBearer()->hasBonusOfType(Bonus::UNDEAD)
+			|| node->getBonusBearer()->hasBonusOfType(Bonus::NON_LIVING)))
 	{
 		text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
 		bonusValue = 0;
 	}
-	else if(morale && node && node->hasBonusOfType(Bonus::NO_MORALE))
+	else if(morale && node && node->getBonusBearer()->hasBonusOfType(Bonus::NO_MORALE))
 	{
-		auto noMorale = node->getBonus(Selector::type()(Bonus::NO_MORALE));
+		auto noMorale = node->getBonusBearer()->getBonus(Selector::type()(Bonus::NO_MORALE));
 		text += "\n" + noMorale->Description();
 		bonusValue = 0;
 	}
-	else if (!morale && node && node->hasBonusOfType(Bonus::NO_LUCK))
+	else if (!morale && node && node->getBonusBearer()->hasBonusOfType(Bonus::NO_LUCK))
 	{
-		auto noLuck = node->getBonus(Selector::type()(Bonus::NO_LUCK));
+		auto noLuck = node->getBonusBearer()->getBonus(Selector::type()(Bonus::NO_LUCK));
 		text += "\n" + noLuck->Description();
 		bonusValue = 0;
 	}

+ 2 - 2
client/widgets/MiscWidgets.h

@@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class CGGarrison;
 struct InfoAboutArmy;
 class CArmedInstance;
-class IBonusBearer;
+class IFactionMember;
 
 VCMI_LIB_NAMESPACE_END
 
@@ -170,7 +170,7 @@ public:
 	bool morale; //true if morale, false if luck
 	bool small;
 
-	void set(const IBonusBearer *node);
+	void set(const IFactionMember *node);
 
 	MoraleLuckBox(bool Morale, const Rect &r, bool Small=false);
 };

+ 14 - 0
include/vcmi/FactionMember.h

@@ -14,6 +14,8 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+class BonusList;
+
 namespace PrimarySkill
 {
     enum PrimarySkill : int8_t;
@@ -50,6 +52,18 @@ public:
 	 Returns primskill of creature or hero.
 	*/
 	int getPrimSkillLevel(PrimarySkill::PrimarySkill id) const;
+	/**
+	 Returns morale or luck of creature or hero.
+	*/
+	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(std::shared_ptr<const BonusList> & bonusList) const;
+	int LuckValAndBonusList(std::shared_ptr<const BonusList> & bonusList) const;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 50 - 1
lib/BasicTypes.cpp

@@ -88,6 +88,55 @@ int IFactionMember::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
 	return std::max(ret, minSkillValue); //otherwise, some artifacts may cause negative skill value effect, sp=0 works in old saves
 }
 
+int IFactionMember::MoraleValAndBonusList(TConstBonusListPtr & bonusList) const
+{
+	static const auto unaffectedByMoraleSelector = Selector::type()(Bonus::NON_LIVING).Or(Selector::type()(Bonus::UNDEAD))
+													.Or(Selector::type()(Bonus::SIEGE_WEAPON)).Or(Selector::type()(Bonus::NO_MORALE));
+
+	static const std::string cachingStrUn = "IFactionMember::unaffectedByMoraleSelector";
+	auto unaffected = getBonusBearer()->hasBonus(unaffectedByMoraleSelector, cachingStrUn);
+	if(unaffected)
+	{
+		if(bonusList && !bonusList->empty())
+			bonusList = std::make_shared<const BonusList>();
+		return 0;
+	}
+
+	static const auto moraleSelector = Selector::type()(Bonus::MORALE);
+	static const std::string cachingStrMor = "type_MORALE";
+	bonusList = getBonusBearer()->getBonuses(moraleSelector, cachingStrMor);
+
+	return std::clamp(bonusList->totalValue(), -3, +3);
+}
+
+int IFactionMember::LuckValAndBonusList(TConstBonusListPtr & bonusList) const
+{
+	if(getBonusBearer()->hasBonusOfType(Bonus::NO_LUCK))
+	{
+		if(bonusList && !bonusList->empty())
+			bonusList = std::make_shared<const BonusList>();
+		return 0;
+	}
+
+	static const auto luckSelector = Selector::type()(Bonus::LUCK);
+	static const std::string cachingStrLuck = "type_LUCK";
+	bonusList = getBonusBearer()->getBonuses(luckSelector, cachingStrLuck);
+
+	return std::clamp(bonusList->totalValue(), -3, +3);
+}
+
+int IFactionMember::MoraleVal() const
+{
+	TConstBonusListPtr tmp = nullptr;
+	return MoraleValAndBonusList(tmp);
+}
+
+int IFactionMember::LuckVal() const
+{
+	TConstBonusListPtr tmp = nullptr;
+	return LuckValAndBonusList(tmp);
+}
+
 ui32 ICreature::MaxHealth() const
 {
 	const std::string cachingStr = "type_STACK_HEALTH";
@@ -114,7 +163,7 @@ ui32 ICreature::Speed(int turn, bool useBind) const
 
 bool ICreature::isLiving() const //TODO: theoreticaly there exists "LIVING" bonus in stack experience documentation
 {
-	static const std::string cachingStr = "IBonusBearer::isLiving";
+	static const std::string cachingStr = "ICreature::isLiving";
 	static const CSelector selector = Selector::type()(Bonus::UNDEAD)
 		.Or(Selector::type()(Bonus::NON_LIVING))
 		.Or(Selector::type()(Bonus::GARGOYLE))

+ 0 - 57
lib/bonuses/HeroBonus.cpp

@@ -606,22 +606,6 @@ void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusLi
 	changed();
 }
 
-CSelector IBonusBearer::anaffectedByMoraleSelector =
-Selector::type()(Bonus::NON_LIVING)
-.Or(Selector::type()(Bonus::UNDEAD))
-.Or(Selector::type()(Bonus::SIEGE_WEAPON))
-.Or(Selector::type()(Bonus::NO_MORALE));
-
-CSelector IBonusBearer::moraleSelector = Selector::type()(Bonus::MORALE);
-CSelector IBonusBearer::luckSelector = Selector::type()(Bonus::LUCK);
-
-IBonusBearer::IBonusBearer()
-	:anaffectedByMorale(this, anaffectedByMoraleSelector),
-	moraleValue(this, moraleSelector, 0),
-	luckValue(this, luckSelector, 0)
-{
-}
-
 int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
 {
 	return valOfBonuses(Selector::type()(type).And(selector));
@@ -685,47 +669,6 @@ bool IBonusBearer::hasBonusFrom(Bonus::BonusSource source, ui32 sourceID) const
 
 	return hasBonus(Selector::source(source,sourceID), fmt.str());
 }
-
-int IBonusBearer::MoraleVal() const
-{
-	if(anaffectedByMorale.getHasBonus())
-		return 0;
-
-	return std::clamp(moraleValue.getValue(), -3, +3);
-}
-
-int IBonusBearer::LuckVal() const
-{
-	if(hasBonusOfType(Bonus::NO_LUCK))
-		return 0;
-
-	return std::clamp(luckValue.getValue(), -3, +3);
-}
-
-int IBonusBearer::MoraleValAndBonusList(TConstBonusListPtr & bonusList) const
-{
-	if(anaffectedByMorale.getHasBonus())
-	{
-		if(!bonusList->empty())
-			bonusList = std::make_shared<const BonusList>();
-		return 0;
-	}
-
-	return std::clamp(moraleValue.getValueAndList(bonusList), -3, +3);
-}
-
-int IBonusBearer::LuckValAndBonusList(TConstBonusListPtr & bonusList) const
-{
-	if(hasBonusOfType(Bonus::NO_LUCK))
-	{
-		if(!bonusList->empty())
-			bonusList = std::make_shared<const BonusList>();
-		return 0;
-	}
-
-	return std::clamp(luckValue.getValueAndList(bonusList), -3, +3);
-}
-
 std::shared_ptr<const Bonus> IBonusBearer::getBonus(const CSelector &selector) const
 {
 	auto bonuses = getAllBonuses(selector, Selector::all);

+ 1 - 22
lib/bonuses/HeroBonus.h

@@ -663,20 +663,12 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusL
 
 class DLL_LINKAGE IBonusBearer
 {
-private:
-	static CSelector anaffectedByMoraleSelector;
-	CCheckProxy anaffectedByMorale;
-	static CSelector moraleSelector;
-	CTotalsProxy moraleValue;
-	static CSelector luckSelector;
-	CTotalsProxy luckValue;
-
 public:
 	//new bonusing node interface
 	// * selector is predicate that tests if HeroBonus matches our criteria
 	// * root is node on which call was made (nullptr will be replaced with this)
 	//interface
-	IBonusBearer();
+	IBonusBearer() = default;
 	virtual ~IBonusBearer() = default;
 	virtual TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const = 0;
 	int valOfBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
@@ -693,19 +685,6 @@ public:
 	bool hasBonusOfType(Bonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype)
 	bool hasBonusFrom(Bonus::BonusSource source, ui32 sourceID) const;
 
-	//various hlp functions for non-trivial values
-	//used for stacks and creatures only
-
-	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;
-
 	virtual int64_t getTreeVersion() const = 0;
 };