1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

vcmi: morale and luck now also IFactionMember

Not all bonus bearers have morale and luck, only faction members
This commit is contained in:
Konstantin 2023-04-30 15:04:54 +03:00
parent e37f798a68
commit a2d4c72016
6 changed files with 74 additions and 89 deletions

View File

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

View File

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

View File

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

View File

@ -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 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 ui32 ICreature::MaxHealth() const
{ {
const std::string cachingStr = "type_STACK_HEALTH"; 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 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) static const CSelector selector = Selector::type()(Bonus::UNDEAD)
.Or(Selector::type()(Bonus::NON_LIVING)) .Or(Selector::type()(Bonus::NON_LIVING))
.Or(Selector::type()(Bonus::GARGOYLE)) .Or(Selector::type()(Bonus::GARGOYLE))

View File

@ -606,22 +606,6 @@ void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusLi
changed(); 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 int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
{ {
return valOfBonuses(Selector::type()(type).And(selector)); 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()); 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 std::shared_ptr<const Bonus> IBonusBearer::getBonus(const CSelector &selector) const
{ {
auto bonuses = getAllBonuses(selector, Selector::all); auto bonuses = getAllBonuses(selector, Selector::all);

View File

@ -663,20 +663,12 @@ DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusL
class DLL_LINKAGE IBonusBearer class DLL_LINKAGE IBonusBearer
{ {
private:
static CSelector anaffectedByMoraleSelector;
CCheckProxy anaffectedByMorale;
static CSelector moraleSelector;
CTotalsProxy moraleValue;
static CSelector luckSelector;
CTotalsProxy luckValue;
public: public:
//new bonusing node interface //new bonusing node interface
// * selector is predicate that tests if HeroBonus matches our criteria // * selector is predicate that tests if HeroBonus matches our criteria
// * root is node on which call was made (nullptr will be replaced with this) // * root is node on which call was made (nullptr will be replaced with this)
//interface //interface
IBonusBearer(); IBonusBearer() = default;
virtual ~IBonusBearer() = default; virtual ~IBonusBearer() = default;
virtual TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const = 0; 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; 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 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; 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; virtual int64_t getTreeVersion() const = 0;
}; };