Limiter.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Limiter.cpp, 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. #include "StdInc.h"
  11. #include "Limiter.h"
  12. #include "../IGameCallback.h"
  13. #include "../CPlayerState.h"
  14. #include "../mapObjects/CGHeroInstance.h"
  15. #include "../serializer/JsonSerializeFormat.h"
  16. #include "../constants/StringConstants.h"
  17. #include "../CSkillHandler.h"
  18. VCMI_LIB_NAMESPACE_BEGIN
  19. Rewardable::Limiter::Limiter()
  20. : dayOfWeek(0)
  21. , daysPassed(0)
  22. , heroExperience(0)
  23. , heroLevel(0)
  24. , manaPercentage(0)
  25. , manaPoints(0)
  26. , primary(GameConstants::PRIMARY_SKILLS, 0)
  27. {
  28. }
  29. Rewardable::Limiter::~Limiter() = default;
  30. bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
  31. {
  32. if(dayOfWeek != 0)
  33. {
  34. if (IObjectInterface::cb->getDate(Date::DAY_OF_WEEK) != dayOfWeek)
  35. return false;
  36. }
  37. if(daysPassed != 0)
  38. {
  39. if (IObjectInterface::cb->getDate(Date::DAY) < daysPassed)
  40. return false;
  41. }
  42. for(const auto & reqStack : creatures)
  43. {
  44. size_t count = 0;
  45. for(const auto & slot : hero->Slots())
  46. {
  47. const CStackInstance * heroStack = slot.second;
  48. if (heroStack->type == reqStack.type)
  49. count += heroStack->count;
  50. }
  51. if (count < reqStack.count) //not enough creatures of this kind
  52. return false;
  53. }
  54. if(!IObjectInterface::cb->getPlayerState(hero->tempOwner)->resources.canAfford(resources))
  55. return false;
  56. if(heroLevel > static_cast<si32>(hero->level))
  57. return false;
  58. if(static_cast<TExpType>(heroExperience) > hero->exp)
  59. return false;
  60. if(manaPoints > hero->mana)
  61. return false;
  62. if(manaPercentage > 100 * hero->mana / hero->manaLimit())
  63. return false;
  64. for(size_t i=0; i<primary.size(); i++)
  65. {
  66. if(primary[i] > hero->getPrimSkillLevel(static_cast<PrimarySkill>(i)))
  67. return false;
  68. }
  69. for(const auto & skill : secondary)
  70. {
  71. if (skill.second > hero->getSecSkillLevel(skill.first))
  72. return false;
  73. }
  74. for(const auto & spell : spells)
  75. {
  76. if (!hero->spellbookContainsSpell(spell))
  77. return false;
  78. }
  79. for(const auto & art : artifacts)
  80. {
  81. if (!hero->hasArt(art))
  82. return false;
  83. }
  84. for(const auto & sublimiter : noneOf)
  85. {
  86. if (sublimiter->heroAllowed(hero))
  87. return false;
  88. }
  89. for(const auto & sublimiter : allOf)
  90. {
  91. if (!sublimiter->heroAllowed(hero))
  92. return false;
  93. }
  94. if(anyOf.empty())
  95. return true;
  96. for(const auto & sublimiter : anyOf)
  97. {
  98. if (sublimiter->heroAllowed(hero))
  99. return true;
  100. }
  101. return false;
  102. }
  103. void Rewardable::Limiter::serializeJson(JsonSerializeFormat & handler)
  104. {
  105. handler.serializeInt("dayOfWeek", dayOfWeek);
  106. handler.serializeInt("daysPassed", daysPassed);
  107. resources.serializeJson(handler, "resources");
  108. handler.serializeInt("manaPercentage", manaPercentage);
  109. handler.serializeInt("heroExperience", heroExperience);
  110. handler.serializeInt("heroLevel", heroLevel);
  111. handler.serializeInt("manaPoints", manaPoints);
  112. handler.serializeIdArray("artifacts", artifacts);
  113. handler.enterArray("creatures").serializeStruct(creatures);
  114. {
  115. auto a = handler.enterArray("primary");
  116. a.syncSize(primary);
  117. for(int i = 0; i < primary.size(); ++i)
  118. a.serializeInt(i, primary[i]);
  119. }
  120. {
  121. auto a = handler.enterArray("secondary");
  122. std::vector<std::pair<std::string, std::string>> fieldValue;
  123. if(handler.saving)
  124. {
  125. for(auto & i : secondary)
  126. {
  127. auto key = VLC->skillh->encodeSkill(i.first);
  128. auto value = NSecondarySkill::levels.at(i.second);
  129. fieldValue.emplace_back(key, value);
  130. }
  131. }
  132. a.syncSize(fieldValue);
  133. for(int i = 0; i < fieldValue.size(); ++i)
  134. {
  135. auto e = a.enterStruct(i);
  136. e->serializeString("skill", fieldValue[i].first);
  137. e->serializeString("level", fieldValue[i].second);
  138. }
  139. if(!handler.saving)
  140. {
  141. for(auto & i : fieldValue)
  142. {
  143. const int skillId = VLC->skillh->decodeSkill(i.first);
  144. if(skillId < 0)
  145. {
  146. logGlobal->error("Invalid secondary skill %s", i.first);
  147. continue;
  148. }
  149. const int level = vstd::find_pos(NSecondarySkill::levels, i.second);
  150. if(level < 0)
  151. {
  152. logGlobal->error("Invalid secondary skill level%s", i.second);
  153. continue;
  154. }
  155. secondary[SecondarySkill(skillId)] = level;
  156. }
  157. }
  158. }
  159. //sublimiters
  160. auto serializeSublimitersList = [&handler](const std::string & field, LimitersList & container)
  161. {
  162. auto a = handler.enterArray(field);
  163. a.syncSize(container);
  164. for(int i = 0; i < container.size(); ++i)
  165. {
  166. if(!handler.saving)
  167. container[i] = std::make_shared<Rewardable::Limiter>();
  168. auto e = a.enterStruct(i);
  169. container[i]->serializeJson(handler);
  170. }
  171. };
  172. serializeSublimitersList("allOf", allOf);
  173. serializeSublimitersList("anyOf", anyOf);
  174. serializeSublimitersList("noneOf", noneOf);
  175. }
  176. VCMI_LIB_NAMESPACE_END