From 3df5a8e415684fb3f96cc83a195d1f347ff73758 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sun, 30 Apr 2023 22:55:04 +0300 Subject: [PATCH] vcmi: split selectors from HeroBonus.h --- cmake_modules/VCMI_lib.cmake | 2 + lib/bonuses/BonusList.h | 1 + lib/bonuses/BonusParams.cpp | 1 + lib/bonuses/BonusSelector.cpp | 89 +++++++++++++++++ lib/bonuses/BonusSelector.h | 156 ++++++++++++++++++++++++++++++ lib/bonuses/CBonusProxy.h | 1 + lib/bonuses/HeroBonus.cpp | 73 -------------- lib/bonuses/HeroBonus.h | 141 --------------------------- lib/spells/effects/UnitEffect.cpp | 1 + 9 files changed, 251 insertions(+), 214 deletions(-) create mode 100644 lib/bonuses/BonusSelector.cpp create mode 100644 lib/bonuses/BonusSelector.h diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index 9acc95cde..ada7791b4 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -29,6 +29,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/bonuses/BonusList.cpp ${MAIN_LIB_DIR}/bonuses/BonusParams.cpp + ${MAIN_LIB_DIR}/bonuses/BonusSelector.cpp ${MAIN_LIB_DIR}/bonuses/CBonusProxy.cpp ${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.cpp ${MAIN_LIB_DIR}/bonuses/HeroBonus.cpp @@ -311,6 +312,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/bonuses/BonusList.h ${MAIN_LIB_DIR}/bonuses/BonusParams.h + ${MAIN_LIB_DIR}/bonuses/BonusSelector.h ${MAIN_LIB_DIR}/bonuses/CBonusProxy.h ${MAIN_LIB_DIR}/bonuses/CBonusSystemNode.h ${MAIN_LIB_DIR}/bonuses/HeroBonus.h diff --git a/lib/bonuses/BonusList.h b/lib/bonuses/BonusList.h index a633ffa2c..10073e9ee 100644 --- a/lib/bonuses/BonusList.h +++ b/lib/bonuses/BonusList.h @@ -10,6 +10,7 @@ #pragma once #include "HeroBonus.h" +#include "BonusSelector.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/bonuses/BonusParams.cpp b/lib/bonuses/BonusParams.cpp index edb94ffe9..d10a7ee0f 100644 --- a/lib/bonuses/BonusParams.cpp +++ b/lib/bonuses/BonusParams.cpp @@ -11,6 +11,7 @@ #include "StdInc.h" #include "BonusParams.h" +#include "BonusSelector.h" #include "../ResourceSet.h" diff --git a/lib/bonuses/BonusSelector.cpp b/lib/bonuses/BonusSelector.cpp new file mode 100644 index 000000000..7b8fa0253 --- /dev/null +++ b/lib/bonuses/BonusSelector.cpp @@ -0,0 +1,89 @@ +/* + * BonusSelector.cpp, 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 + * + */ + +#include "StdInc.h" +#include "BonusSelector.h" + +VCMI_LIB_NAMESPACE_BEGIN + +namespace Selector +{ + DLL_LINKAGE CSelectFieldEqual & type() + { + static CSelectFieldEqual stype(&Bonus::type); + return stype; + } + + DLL_LINKAGE CSelectFieldEqual & subtype() + { + static CSelectFieldEqual ssubtype(&Bonus::subtype); + return ssubtype; + } + + DLL_LINKAGE CSelectFieldEqual & info() + { + static CSelectFieldEqual sinfo(&Bonus::additionalInfo); + return sinfo; + } + + DLL_LINKAGE CSelectFieldEqual & sourceType() + { + static CSelectFieldEqual ssourceType(&Bonus::source); + return ssourceType; + } + + DLL_LINKAGE CSelectFieldEqual & targetSourceType() + { + static CSelectFieldEqual ssourceType(&Bonus::targetSourceType); + return ssourceType; + } + + DLL_LINKAGE CSelectFieldEqual & effectRange() + { + static CSelectFieldEqual 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)); + } + + CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, const CAddInfo & info) + { + return CSelectFieldEqual(&Bonus::type)(type) + .And(CSelectFieldEqual(&Bonus::subtype)(subtype)) + .And(CSelectFieldEqual(&Bonus::additionalInfo)(info)); + } + + CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID) + { + return CSelectFieldEqual(&Bonus::source)(source) + .And(CSelectFieldEqual(&Bonus::sid)(sourceID)); + } + + CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source) + { + return CSelectFieldEqual(&Bonus::source)(source); + } + + CSelector DLL_LINKAGE valueType(Bonus::ValueType valType) + { + return CSelectFieldEqual(&Bonus::valType)(valType); + } + + DLL_LINKAGE CSelector all([](const Bonus * b){return true;}); + DLL_LINKAGE CSelector none([](const Bonus * b){return false;}); +} + +VCMI_LIB_NAMESPACE_END \ No newline at end of file diff --git a/lib/bonuses/BonusSelector.h b/lib/bonuses/BonusSelector.h new file mode 100644 index 000000000..7d01feddf --- /dev/null +++ b/lib/bonuses/BonusSelector.h @@ -0,0 +1,156 @@ +/* + * BonusSelector.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 "HeroBonus.h" + +VCMI_LIB_NAMESPACE_BEGIN + +class CSelector : std::function +{ + using TBase = std::function; +public: + CSelector() = default; + template + CSelector(const T &t, //SFINAE trick -> include this c-tor in overload resolution only if parameter is class + //(includes functors, lambdas) or function. Without that VC is going mad about ambiguities. + typename std::enable_if < boost::mpl::or_ < std::is_class, std::is_function> ::value>::type *dummy = nullptr) + : TBase(t) + {} + + CSelector(std::nullptr_t) + {} + + CSelector And(CSelector rhs) const + { + //lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer) + auto thisCopy = *this; + return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); }; + } + CSelector Or(CSelector rhs) const + { + auto thisCopy = *this; + return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) || rhs(b); }; + } + + CSelector Not() const + { + auto thisCopy = *this; + return [thisCopy](const Bonus *b) mutable { return !thisCopy(b); }; + } + + bool operator()(const Bonus *b) const + { + return TBase::operator()(b); + } + + operator bool() const + { + return !!static_cast(*this); + } +}; + +template +class CSelectFieldEqual +{ + T Bonus::*ptr; + +public: + CSelectFieldEqual(T Bonus::*Ptr) + : ptr(Ptr) + { + } + + 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; + }; + } +}; + +class DLL_LINKAGE CWillLastTurns +{ +public: + int turnsRequested; + + bool operator()(const Bonus *bonus) const + { + return turnsRequested <= 0 //every present effect will last zero (or "less") turns + || !Bonus::NTurns(bonus) //so do every not expriing after N-turns effect + || bonus->turnsRemain > turnsRequested; + } + CWillLastTurns& operator()(const int &setVal) + { + turnsRequested = setVal; + return *this; + } +}; + +class DLL_LINKAGE CWillLastDays +{ +public: + int daysRequested; + + bool operator()(const Bonus *bonus) const + { + if(daysRequested <= 0 || Bonus::Permanent(bonus) || Bonus::OneBattle(bonus)) + return true; + else if(Bonus::OneDay(bonus)) + return false; + else if(Bonus::NDays(bonus) || Bonus::OneWeek(bonus)) + { + return bonus->turnsRemain > daysRequested; + } + + return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations + } + CWillLastDays& operator()(const int &setVal) + { + daysRequested = setVal; + return *this; + } +}; + + +namespace Selector +{ + extern DLL_LINKAGE CSelectFieldEqual & type(); + extern DLL_LINKAGE CSelectFieldEqual & subtype(); + extern DLL_LINKAGE CSelectFieldEqual & info(); + extern DLL_LINKAGE CSelectFieldEqual & sourceType(); + extern DLL_LINKAGE CSelectFieldEqual & targetSourceType(); + extern DLL_LINKAGE CSelectFieldEqual & effectRange(); + extern DLL_LINKAGE CWillLastTurns turns; + extern DLL_LINKAGE CWillLastDays days; + + CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype); + CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, const CAddInfo & info); + CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID); + CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source); + CSelector DLL_LINKAGE valueType(Bonus::ValueType valType); + + /** + * Selects all bonuses + * Usage example: Selector::all.And().And()...) + */ + extern DLL_LINKAGE CSelector all; + + /** + * Selects nothing + * Usage example: Selector::none.Or().Or()...) + */ + extern DLL_LINKAGE CSelector none; +} + +VCMI_LIB_NAMESPACE_END \ No newline at end of file diff --git a/lib/bonuses/CBonusProxy.h b/lib/bonuses/CBonusProxy.h index 804a33f17..5bed7962e 100644 --- a/lib/bonuses/CBonusProxy.h +++ b/lib/bonuses/CBonusProxy.h @@ -11,6 +11,7 @@ #pragma once #include "HeroBonus.h" +#include "BonusSelector.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/bonuses/HeroBonus.cpp b/lib/bonuses/HeroBonus.cpp index c3d755427..1dc3ed7e3 100644 --- a/lib/bonuses/HeroBonus.cpp +++ b/lib/bonuses/HeroBonus.cpp @@ -354,79 +354,6 @@ std::shared_ptr Bonus::addPropagator(const TPropagatorPtr & Propagator) return this->shared_from_this(); } -namespace Selector -{ - DLL_LINKAGE CSelectFieldEqual & type() - { - static CSelectFieldEqual stype(&Bonus::type); - return stype; - } - - DLL_LINKAGE CSelectFieldEqual & subtype() - { - static CSelectFieldEqual ssubtype(&Bonus::subtype); - return ssubtype; - } - - DLL_LINKAGE CSelectFieldEqual & info() - { - static CSelectFieldEqual sinfo(&Bonus::additionalInfo); - return sinfo; - } - - DLL_LINKAGE CSelectFieldEqual & sourceType() - { - static CSelectFieldEqual ssourceType(&Bonus::source); - return ssourceType; - } - - DLL_LINKAGE CSelectFieldEqual & targetSourceType() - { - static CSelectFieldEqual ssourceType(&Bonus::targetSourceType); - return ssourceType; - } - - DLL_LINKAGE CSelectFieldEqual & effectRange() - { - static CSelectFieldEqual 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)); - } - - CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, const CAddInfo & info) - { - return CSelectFieldEqual(&Bonus::type)(type) - .And(CSelectFieldEqual(&Bonus::subtype)(subtype)) - .And(CSelectFieldEqual(&Bonus::additionalInfo)(info)); - } - - CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID) - { - return CSelectFieldEqual(&Bonus::source)(source) - .And(CSelectFieldEqual(&Bonus::sid)(sourceID)); - } - - CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source) - { - return CSelectFieldEqual(&Bonus::source)(source); - } - - CSelector DLL_LINKAGE valueType(Bonus::ValueType valType) - { - return CSelectFieldEqual(&Bonus::valType)(valType); - } - - DLL_LINKAGE CSelector all([](const Bonus * b){return true;}); - DLL_LINKAGE CSelector none([](const Bonus * b){return false;}); -} - DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus) { for(const auto & i : bonusNameMap) diff --git a/lib/bonuses/HeroBonus.h b/lib/bonuses/HeroBonus.h index 90a159f4f..40198b07e 100644 --- a/lib/bonuses/HeroBonus.h +++ b/lib/bonuses/HeroBonus.h @@ -28,50 +28,6 @@ using TLimiterPtr = std::shared_ptr; using TPropagatorPtr = std::shared_ptr; using TUpdaterPtr = std::shared_ptr; -class CSelector : std::function -{ - using TBase = std::function; -public: - CSelector() = default; - template - CSelector(const T &t, //SFINAE trick -> include this c-tor in overload resolution only if parameter is class - //(includes functors, lambdas) or function. Without that VC is going mad about ambiguities. - typename std::enable_if < boost::mpl::or_ < std::is_class, std::is_function> ::value>::type *dummy = nullptr) - : TBase(t) - {} - - CSelector(std::nullptr_t) - {} - - CSelector And(CSelector rhs) const - { - //lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer) - auto thisCopy = *this; - return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); }; - } - CSelector Or(CSelector rhs) const - { - auto thisCopy = *this; - return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) || rhs(b); }; - } - - CSelector Not() const - { - auto thisCopy = *this; - return [thisCopy](const Bonus *b) mutable { return !thisCopy(b); }; - } - - bool operator()(const Bonus *b) const - { - return TBase::operator()(b); - } - - operator bool() const - { - return !!static_cast(*this); - } -}; - class DLL_LINKAGE CAddInfo : public std::vector { public: @@ -464,103 +420,6 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus); -DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const BonusList &bonusList); - -template -class CSelectFieldEqual -{ - T Bonus::*ptr; - -public: - CSelectFieldEqual(T Bonus::*Ptr) - : ptr(Ptr) - { - } - - 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; - }; - } -}; - -class DLL_LINKAGE CWillLastTurns -{ -public: - int turnsRequested; - - bool operator()(const Bonus *bonus) const - { - return turnsRequested <= 0 //every present effect will last zero (or "less") turns - || !Bonus::NTurns(bonus) //so do every not expriing after N-turns effect - || bonus->turnsRemain > turnsRequested; - } - CWillLastTurns& operator()(const int &setVal) - { - turnsRequested = setVal; - return *this; - } -}; - -class DLL_LINKAGE CWillLastDays -{ -public: - int daysRequested; - - bool operator()(const Bonus *bonus) const - { - if(daysRequested <= 0 || Bonus::Permanent(bonus) || Bonus::OneBattle(bonus)) - return true; - else if(Bonus::OneDay(bonus)) - return false; - else if(Bonus::NDays(bonus) || Bonus::OneWeek(bonus)) - { - return bonus->turnsRemain > daysRequested; - } - - return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations - } - CWillLastDays& operator()(const int &setVal) - { - daysRequested = setVal; - return *this; - } -}; - - -namespace Selector -{ - extern DLL_LINKAGE CSelectFieldEqual & type(); - extern DLL_LINKAGE CSelectFieldEqual & subtype(); - extern DLL_LINKAGE CSelectFieldEqual & info(); - extern DLL_LINKAGE CSelectFieldEqual & sourceType(); - extern DLL_LINKAGE CSelectFieldEqual & targetSourceType(); - extern DLL_LINKAGE CSelectFieldEqual & effectRange(); - extern DLL_LINKAGE CWillLastTurns turns; - extern DLL_LINKAGE CWillLastDays days; - - CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype); - CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, const CAddInfo & info); - CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID); - CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source); - CSelector DLL_LINKAGE valueType(Bonus::ValueType valType); - - /** - * Selects all bonuses - * Usage example: Selector::all.And().And()...) - */ - extern DLL_LINKAGE CSelector all; - - /** - * Selects nothing - * Usage example: Selector::none.Or().Or()...) - */ - extern DLL_LINKAGE CSelector none; -} - extern DLL_LINKAGE const std::map bonusNameMap; extern DLL_LINKAGE const std::map bonusValueMap; extern DLL_LINKAGE const std::map bonusSourceMap; diff --git a/lib/spells/effects/UnitEffect.cpp b/lib/spells/effects/UnitEffect.cpp index 41e1902a6..2fbe4c16e 100644 --- a/lib/spells/effects/UnitEffect.cpp +++ b/lib/spells/effects/UnitEffect.cpp @@ -13,6 +13,7 @@ #include "../ISpellMechanics.h" +#include "../../bonuses/BonusSelector.h" #include "../../NetPacksBase.h" #include "../../battle/CBattleInfoCallback.h" #include "../../battle/Unit.h"