BonusCache.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * BonusCache.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 "BonusSelector.h"
  12. VCMI_LIB_NAMESPACE_BEGIN
  13. enum class BonusCacheMode : int8_t
  14. {
  15. VALUE, // total value of bonus will be cached
  16. PRESENCE, // presence of bonus will be cached
  17. };
  18. /// Internal base class with no own cache
  19. class BonusCacheBase
  20. {
  21. protected:
  22. const IBonusBearer * target;
  23. explicit BonusCacheBase(const IBonusBearer * target):
  24. target(target)
  25. {}
  26. struct BonusCacheEntry
  27. {
  28. std::atomic<int32_t> version = 0;
  29. std::atomic<int32_t> value = 0;
  30. BonusCacheEntry() = default;
  31. BonusCacheEntry(const BonusCacheEntry & other)
  32. : version(other.version.load())
  33. , value(other.value.load())
  34. {
  35. }
  36. BonusCacheEntry & operator =(const BonusCacheEntry & other)
  37. {
  38. version = other.version.load();
  39. value = other.value.load();
  40. return *this;
  41. }
  42. };
  43. int getBonusValueImpl(BonusCacheEntry & currentValue, const CSelector & selector, BonusCacheMode) const;
  44. };
  45. /// Cache that tracks a single query to bonus system
  46. class BonusValueCache : public BonusCacheBase
  47. {
  48. CSelector selector;
  49. mutable BonusCacheEntry value;
  50. public:
  51. BonusValueCache(const IBonusBearer * target, const CSelector & selector);
  52. int getValue() const;
  53. bool hasBonus() const;
  54. };
  55. /// Cache that can track a list of queries to bonus system
  56. template<size_t SIZE>
  57. class BonusValuesArrayCache : public BonusCacheBase
  58. {
  59. public:
  60. using SelectorsArray = std::array<const CSelector, SIZE>;
  61. BonusValuesArrayCache(const IBonusBearer * target, const SelectorsArray * selectors)
  62. : BonusCacheBase(target)
  63. , selectors(selectors)
  64. {}
  65. int getBonusValue(int index) const
  66. {
  67. return getBonusValueImpl(cache[index], (*selectors)[index], BonusCacheMode::VALUE);
  68. }
  69. int hasBonus(int index) const
  70. {
  71. return getBonusValueImpl(cache[index], (*selectors)[index], BonusCacheMode::PRESENCE);
  72. }
  73. private:
  74. using CacheArray = std::array<BonusCacheEntry, SIZE>;
  75. const SelectorsArray * selectors;
  76. mutable CacheArray cache;
  77. };
  78. class UnitBonusValuesProxy
  79. {
  80. public:
  81. enum ECacheKeys : int8_t
  82. {
  83. TOTAL_ATTACKS_MELEE,
  84. TOTAL_ATTACKS_RANGED,
  85. MIN_DAMAGE_MELEE,
  86. MIN_DAMAGE_RANGED,
  87. MAX_DAMAGE_MELEE,
  88. MAX_DAMAGE_RANGED,
  89. ATTACK_MELEE,
  90. ATTACK_RANGED,
  91. DEFENCE_MELEE,
  92. DEFENCE_RANGED,
  93. IN_FRENZY,
  94. HYPNOTIZED,
  95. FORGETFULL,
  96. HAS_FREE_SHOOTING,
  97. STACK_HEALTH,
  98. INVINCIBLE,
  99. CLONE_MARKER,
  100. TOTAL_KEYS,
  101. };
  102. static constexpr size_t KEYS_COUNT = static_cast<size_t>(ECacheKeys::TOTAL_KEYS);
  103. using SelectorsArray = BonusValuesArrayCache<KEYS_COUNT>::SelectorsArray;
  104. UnitBonusValuesProxy(const IBonusBearer * Target):
  105. cache(Target, generateSelectors())
  106. {}
  107. int getBonusValue(ECacheKeys which) const
  108. {
  109. auto index = static_cast<size_t>(which);
  110. return cache.getBonusValue(index);
  111. }
  112. int hasBonus(ECacheKeys which) const
  113. {
  114. auto index = static_cast<size_t>(which);
  115. return cache.hasBonus(index);
  116. }
  117. private:
  118. const SelectorsArray * generateSelectors();
  119. BonusValuesArrayCache<KEYS_COUNT> cache;
  120. };
  121. /// Cache that tracks values of primary skill values in bonus system
  122. class PrimarySkillsCache
  123. {
  124. const IBonusBearer * target;
  125. mutable std::atomic<int32_t> version = 0;
  126. mutable std::array<std::atomic<int32_t>, 4> skills;
  127. void update() const;
  128. public:
  129. PrimarySkillsCache(const IBonusBearer * target);
  130. const std::array<std::atomic<int32_t>, 4> & getSkills() const;
  131. const std::atomic<int32_t> & getSkill(PrimarySkill id) const
  132. {
  133. return getSkills()[id.getNum()];
  134. }
  135. };
  136. /// Cache that tracks values of spell school mastery in bonus system
  137. class MagicSchoolMasteryCache
  138. {
  139. const IBonusBearer * target;
  140. mutable std::atomic<int32_t> version = 0;
  141. mutable std::vector<std::atomic<int32_t>> schools;
  142. void update() const;
  143. public:
  144. MagicSchoolMasteryCache(const IBonusBearer * target);
  145. int32_t getMastery(const SpellSchool & school) const;
  146. };
  147. /// Cache that tracks values for different values of bonus duration
  148. class BonusCachePerTurn : public BonusCacheBase
  149. {
  150. static constexpr int cachedTurns = 8;
  151. const CSelector selector;
  152. mutable TConstBonusListPtr bonusList;
  153. mutable std::mutex bonusListMutex;
  154. mutable std::atomic<int32_t> bonusListVersion = 0;
  155. mutable std::array<BonusCacheEntry, cachedTurns> cache;
  156. const BonusCacheMode mode;
  157. int getValueUncached(int turns) const;
  158. public:
  159. BonusCachePerTurn(const IBonusBearer * target, const CSelector & selector, BonusCacheMode mode)
  160. : BonusCacheBase(target)
  161. , selector(selector)
  162. , mode(mode)
  163. {}
  164. int getValue(int turns) const;
  165. };
  166. VCMI_LIB_NAMESPACE_END