BonusSelector.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * BonusSelector.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "Bonus.h"
  12. VCMI_LIB_NAMESPACE_BEGIN
  13. class CSelector : std::function<bool(const Bonus*)>
  14. {
  15. using TBase = std::function<bool(const Bonus*)>;
  16. public:
  17. CSelector() = default;
  18. template<typename T>
  19. CSelector(const T &t, //SFINAE trick -> include this c-tor in overload resolution only if parameter is class
  20. //(includes functors, lambdas) or function. Without that VC is going mad about ambiguities.
  21. typename std::enable_if < boost::mpl::or_ < std::is_class<T>, std::is_function<T >> ::value>::type *dummy = nullptr)
  22. : TBase(t)
  23. {}
  24. CSelector(std::nullptr_t)
  25. {}
  26. CSelector And(CSelector rhs) const
  27. {
  28. //lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer)
  29. auto thisCopy = *this;
  30. return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); };
  31. }
  32. CSelector Or(CSelector rhs) const
  33. {
  34. auto thisCopy = *this;
  35. return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) || rhs(b); };
  36. }
  37. CSelector Not() const
  38. {
  39. auto thisCopy = *this;
  40. return [thisCopy](const Bonus *b) mutable { return !thisCopy(b); };
  41. }
  42. bool operator()(const Bonus *b) const
  43. {
  44. return TBase::operator()(b);
  45. }
  46. operator bool() const
  47. {
  48. return !!static_cast<const TBase&>(*this);
  49. }
  50. };
  51. template<typename T>
  52. class CSelectFieldEqual
  53. {
  54. T Bonus::*ptr;
  55. public:
  56. CSelectFieldEqual(T Bonus::*Ptr)
  57. : ptr(Ptr)
  58. {
  59. }
  60. CSelector operator()(const T &valueToCompareAgainst) const
  61. {
  62. auto ptr2 = ptr; //We need a COPY because we don't want to reference this (might be outlived by lambda)
  63. return [ptr2, valueToCompareAgainst](const Bonus *bonus)
  64. {
  65. return bonus->*ptr2 == valueToCompareAgainst;
  66. };
  67. }
  68. };
  69. class DLL_LINKAGE CWillLastTurns
  70. {
  71. public:
  72. int turnsRequested;
  73. bool operator()(const Bonus *bonus) const
  74. {
  75. return turnsRequested <= 0 //every present effect will last zero (or "less") turns
  76. || !Bonus::NTurns(bonus) //so do every not expriing after N-turns effect
  77. || bonus->turnsRemain > turnsRequested;
  78. }
  79. CWillLastTurns& operator()(const int &setVal)
  80. {
  81. turnsRequested = setVal;
  82. return *this;
  83. }
  84. };
  85. class DLL_LINKAGE CWillLastDays
  86. {
  87. public:
  88. int daysRequested;
  89. bool operator()(const Bonus *bonus) const
  90. {
  91. if(daysRequested <= 0 || Bonus::Permanent(bonus) || Bonus::OneBattle(bonus))
  92. return true;
  93. else if(Bonus::OneDay(bonus))
  94. return false;
  95. else if(Bonus::NDays(bonus) || Bonus::OneWeek(bonus))
  96. {
  97. return bonus->turnsRemain > daysRequested;
  98. }
  99. return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations
  100. }
  101. CWillLastDays& operator()(const int &setVal)
  102. {
  103. daysRequested = setVal;
  104. return *this;
  105. }
  106. };
  107. namespace Selector
  108. {
  109. extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> & type();
  110. extern DLL_LINKAGE CSelectFieldEqual<TBonusSubtype> & subtype();
  111. extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info();
  112. extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & sourceType();
  113. extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & targetSourceType();
  114. extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> & effectRange();
  115. extern DLL_LINKAGE CWillLastTurns turns;
  116. extern DLL_LINKAGE CWillLastDays days;
  117. CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype);
  118. CSelector DLL_LINKAGE typeSubtypeInfo(Bonus::BonusType type, TBonusSubtype subtype, const CAddInfo & info);
  119. CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID);
  120. CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source);
  121. CSelector DLL_LINKAGE valueType(Bonus::ValueType valType);
  122. /**
  123. * Selects all bonuses
  124. * Usage example: Selector::all.And(<functor>).And(<functor>)...)
  125. */
  126. extern DLL_LINKAGE CSelector all;
  127. /**
  128. * Selects nothing
  129. * Usage example: Selector::none.Or(<functor>).Or(<functor>)...)
  130. */
  131. extern DLL_LINKAGE CSelector none;
  132. }
  133. VCMI_LIB_NAMESPACE_END