/* * 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 "../constants/VariantIdentifier.h" #include "../constants/EntityIdentifiers.h" VCMI_LIB_NAMESPACE_BEGIN struct Bonus; class IBonusBearer; class CBonusSystemNode; class ILimiter; class IPropagator; class IUpdater; class BonusList; class CSelector; using BonusSubtypeID = VariantIdentifier; using BonusSourceID = VariantIdentifier; using TBonusListPtr = std::shared_ptr; using TConstBonusListPtr = std::shared_ptr; using TLimiterPtr = std::shared_ptr; using TPropagatorPtr = std::shared_ptr; using TUpdaterPtr = std::shared_ptr; class DLL_LINKAGE CAddInfo : public std::vector { public: enum { NONE = -1 }; CAddInfo(); CAddInfo(si32 value); bool operator==(si32 value) const; bool operator!=(si32 value) const; si32 & operator[](size_type pos); si32 operator[](size_type pos) const; std::string toString() const; JsonNode toJsonNode() const; }; #define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix(); /// Struct for handling bonuses of several types. Can be transferred to any hero struct DLL_LINKAGE Bonus : public std::enable_shared_from_this { BonusDuration::Type duration = BonusDuration::PERMANENT; //uses BonusDuration values si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 1 byte BonusSubtypeID subtype; BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus BonusSource targetSourceType;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE. si32 val = 0; BonusSourceID sid; //source id: id of object/artifact/spell BonusValueType valType = BonusValueType::ADDITIVE_VALUE; std::string stacking; // bonuses with the same stacking value don't stack (e.g. Angel/Archangel morale bonus) CAddInfo additionalInfo; BonusLimitEffect effectRange = BonusLimitEffect::NO_LIMIT; TLimiterPtr limiter; TPropagatorPtr propagator; TUpdaterPtr updater; TUpdaterPtr propagationUpdater; std::string description; Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, std::string Desc); 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, std::string Desc); Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, BonusValueType ValType); Bonus() = default; template void serialize(Handler &h) { h & duration; h & type; h & subtype; h & source; h & val; h & sid; h & description; h & additionalInfo; h & turnsRemain; h & valType; h & stacking; h & effectRange; h & limiter; h & propagator; h & updater; h & propagationUpdater; h & targetSourceType; if (h.version < Handler::Version::MANA_LIMIT && type == BonusType::MANA_PER_KNOWLEDGE_PERCENTAGE) { if (valType == BonusValueType::ADDITIVE_VALUE || valType == BonusValueType::BASE_NUMBER) val *= 100; } } 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.any(); } static bool NTurns(const Bonus *hb) { auto set = hb->duration & BonusDuration::N_TURNS; return set.any(); } static bool OneDay(const Bonus *hb) { auto set = hb->duration & BonusDuration::ONE_DAY; return set.any(); } static bool OneWeek(const Bonus *hb) { auto set = hb->duration & BonusDuration::ONE_WEEK; return set.any(); } static bool OneBattle(const Bonus *hb) { auto set = hb->duration & BonusDuration::ONE_BATTLE; return set.any(); } static bool Permanent(const Bonus *hb) { auto set = hb->duration & BonusDuration::PERMANENT; return set.any(); } static bool UntilGetsTurn(const Bonus *hb) { auto set = hb->duration & BonusDuration::STACK_GETS_TURN; return set.any(); } static bool UntilAttack(const Bonus *hb) { auto set = hb->duration & BonusDuration::UNTIL_ATTACK; return set.any(); } static bool UntilBeingAttacked(const Bonus *hb) { auto set = hb->duration & BonusDuration::UNTIL_BEING_ATTACKED; return set.any(); } static bool UntilCommanderKilled(const Bonus *hb) { auto set = hb->duration & BonusDuration::COMMANDER_KILLED; return set.any(); } static bool UntilOwnAttack(const Bonus *hb) { auto set = hb->duration & BonusDuration::UNTIL_OWN_ATTACK; return set.any(); } inline bool operator == (const BonusType & cf) const { return type == cf; } inline void operator += (const ui32 Val) //no return { val += Val; } std::string Description(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