/* * Bonus.h, 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 * */ #pragma once #include "BonusEnum.h" #include "BonusCustomTypes.h" #include "Limiters.h" #include "../serializer/Serializeable.h" #include "../texts/MetaString.h" #include "../filesystem/ResourcePath.h" VCMI_LIB_NAMESPACE_BEGIN class IBonusBearer; class IPropagator; class IUpdater; class CSelector; class IGameInfoCallback; using TBonusListPtr = std::shared_ptr; using TConstBonusListPtr = std::shared_ptr; using TPropagatorPtr = std::shared_ptr; using TUpdaterPtr = std::shared_ptr; class DLL_LINKAGE CAddInfo final { public: using container = std::vector; using size_type = container::size_type; enum { NONE = -1 }; CAddInfo(); CAddInfo(si32 value); // Inline definitions in the header to avoid missing symbols across TUs bool operator==(const CAddInfo& other) const noexcept { return data_ == other.data_; } bool operator!=(const CAddInfo& other) const noexcept { return !(*this == other); } bool operator==(si32 value) const { switch(data_.size()) { case 0: return value == CAddInfo::NONE; case 1: return data_[0] == value; default: return false; } } bool operator!=(si32 value) const { return !(*this == value); } si32 & operator[](size_type pos) { if(pos >= data_.size()) data_.resize(pos + 1, CAddInfo::NONE); return data_[pos]; } si32 operator[](size_type pos) const { return pos < data_.size() ? data_[pos] : CAddInfo::NONE; } std::string toString() const; JsonNode toJsonNode() const; // Minimal vector-like facade size_type size() const noexcept { return data_.size(); } bool empty() const noexcept { return data_.empty(); } void push_back(si32 v) { data_.push_back(v); } void resize(size_type n, si32 fill = CAddInfo::NONE) { data_.resize(n, fill); } container::iterator begin() noexcept { return data_.begin(); } container::iterator end() noexcept { return data_.end(); } container::const_iterator begin() const noexcept { return data_.begin(); } container::const_iterator end() const noexcept { return data_.end(); } // expose const view for free operators const container& data() const noexcept { return data_; } template void serialize(H& h) { h & data_; } private: container data_; }; /// Struct for handling bonuses of several types. Can be transferred to any hero struct DLL_LINKAGE Bonus : public std::enable_shared_from_this, public Serializeable { BonusDuration::Type duration = BonusDuration::PERMANENT; //uses BonusDuration values - 2 bytes si32 val = 0; si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK BonusValueType valType = BonusValueType::ADDITIVE_VALUE; // 1 byte BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus - 1 byte BonusSource targetSourceType = BonusSource::OTHER;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE. - 1 byte BonusLimitEffect effectRange = BonusLimitEffect::NO_LIMIT; // 1 byte BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 2 bytes BonusSubtypeID subtype; BonusSourceID sid; //source id: id of object/artifact/spell std::string stacking; // bonuses with the same stacking value don't stack (e.g. Angel/Archangel morale bonus) CAddInfo additionalInfo; TLimiterPtr limiter; TPropagatorPtr propagator; TUpdaterPtr updater; TUpdaterPtr propagationUpdater; ImagePath customIconPath; MetaString description; PlayerColor bonusOwner = PlayerColor::CANNOT_DETERMINE; bool hidden = false; Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, BonusValueType ValType); Bonus(const Bonus & inst, const BonusSourceID & sourceId); Bonus() = default; template void serialize(Handler &h) { h & duration; h & type; h & subtype; h & source; h & val; h & sid; h & description; if (h.hasFeature(Handler::Version::CUSTOM_BONUS_ICONS)) h & customIconPath; if (h.hasFeature(Handler::Version::BONUS_HIDDEN)) h & hidden; h & additionalInfo; h & turnsRemain; h & valType; h & stacking; h & effectRange; h & limiter; h & propagator; h & updater; h & propagationUpdater; h & targetSourceType; } template static bool compareByAdditionalInfo(const Ptr& a, const Ptr& b) { return a->additionalInfo < b->additionalInfo; } static bool NDays(const Bonus *hb) { auto set = hb->duration & BonusDuration::N_DAYS; return set != 0; } static bool NTurns(const Bonus *hb) { auto set = hb->duration & BonusDuration::N_TURNS; return set != 0; } static bool OneDay(const Bonus *hb) { auto set = hb->duration & BonusDuration::ONE_DAY; return set != 0; } static bool OneWeek(const Bonus *hb) { auto set = hb->duration & BonusDuration::ONE_WEEK; return set != 0; } static bool OneBattle(const Bonus *hb) { auto set = hb->duration & BonusDuration::ONE_BATTLE; return set != 0; } static bool Permanent(const Bonus *hb) { auto set = hb->duration & BonusDuration::PERMANENT; return set != 0; } static bool UntilGetsTurn(const Bonus *hb) { auto set = hb->duration & BonusDuration::STACK_GETS_TURN; return set != 0; } static bool UntilAttack(const Bonus *hb) { auto set = hb->duration & BonusDuration::UNTIL_ATTACK; return set != 0; } static bool UntilBeingAttacked(const Bonus *hb) { auto set = hb->duration & BonusDuration::UNTIL_BEING_ATTACKED; return set != 0; } static bool UntilCommanderKilled(const Bonus *hb) { auto set = hb->duration & BonusDuration::COMMANDER_KILLED; return set != 0; } static bool UntilOwnAttack(const Bonus *hb) { auto set = hb->duration & BonusDuration::UNTIL_OWN_ATTACK; return set != 0; } inline bool operator == (const BonusType & cf) const { return type == cf; } inline void operator += (const ui32 Val) //no return { val += Val; } std::string Description(const IGameInfoCallback * cb, std::optional customValue = {}) const; JsonNode toJsonNode() const; std::shared_ptr addLimiter(const TLimiterPtr & Limiter); //returns this for convenient chain-calls std::shared_ptr addPropagator(const TPropagatorPtr & Propagator); //returns this for convenient chain-calls std::shared_ptr addUpdater(const TUpdaterPtr & Updater); //returns this for convenient chain-calls }; DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus); VCMI_LIB_NAMESPACE_END