Limiter.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. handler.enterArray("primary").serializeArray(primary);
  115. {
  116. auto a = handler.enterArray("secondary");
  117. std::vector<std::pair<SecondarySkill, si32>> fieldValue(secondary.begin(), secondary.end());
  118. a.serializeStruct<std::pair<SecondarySkill, si32>>(fieldValue, [](JsonSerializeFormat & h, std::pair<SecondarySkill, si32> & e)
  119. {
  120. h.serializeId("skill", e.first, SecondarySkill{}, VLC->skillh->decodeSkill, VLC->skillh->encodeSkill);
  121. h.serializeId("level", e.second, 0, [](const std::string & i){return vstd::find_pos(NSecondarySkill::levels, i);}, [](si32 i){return NSecondarySkill::levels.at(i);});
  122. });
  123. a.syncSize(fieldValue);
  124. secondary = std::map<SecondarySkill, si32>(fieldValue.begin(), fieldValue.end());
  125. }
  126. //sublimiters
  127. auto serializeSublimitersList = [&handler](const std::string & field, LimitersList & container)
  128. {
  129. auto a = handler.enterArray(field);
  130. a.syncSize(container);
  131. for(int i = 0; i < container.size(); ++i)
  132. {
  133. if(!handler.saving)
  134. container[i] = std::make_shared<Rewardable::Limiter>();
  135. auto e = a.enterStruct(i);
  136. container[i]->serializeJson(handler);
  137. }
  138. };
  139. serializeSublimitersList("allOf", allOf);
  140. serializeSublimitersList("anyOf", anyOf);
  141. serializeSublimitersList("noneOf", noneOf);
  142. }
  143. VCMI_LIB_NAMESPACE_END