Reward.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Reward.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 "Reward.h"
  12. #include "../mapObjects/CGHeroInstance.h"
  13. #include "../serializer/JsonSerializeFormat.h"
  14. #include "../constants/StringConstants.h"
  15. #include "../CSkillHandler.h"
  16. VCMI_LIB_NAMESPACE_BEGIN
  17. Rewardable::Reward::Reward()
  18. : heroExperience(0)
  19. , heroLevel(0)
  20. , manaDiff(0)
  21. , manaPercentage(-1)
  22. , movePoints(0)
  23. , movePercentage(-1)
  24. , primary(4, 0)
  25. , removeObject(false)
  26. , spellCast(SpellID::NONE, SecSkillLevel::NONE)
  27. {
  28. }
  29. Rewardable::Reward::~Reward() = default;
  30. si32 Rewardable::Reward::calculateManaPoints(const CGHeroInstance * hero) const
  31. {
  32. si32 manaScaled = hero->mana;
  33. if (manaPercentage >= 0)
  34. manaScaled = hero->manaLimit() * manaPercentage / 100;
  35. si32 manaMissing = std::max(0, hero->manaLimit() - manaScaled);
  36. si32 manaGranted = std::min(manaMissing, manaDiff);
  37. si32 manaOverflow = manaDiff - manaGranted;
  38. si32 manaOverLimit = manaOverflow * manaOverflowFactor / 100;
  39. si32 manaOutput = manaScaled + manaGranted + manaOverLimit;
  40. return manaOutput;
  41. }
  42. Component Rewardable::Reward::getDisplayedComponent(const CGHeroInstance * h) const
  43. {
  44. std::vector<Component> comps;
  45. loadComponents(comps, h);
  46. assert(!comps.empty());
  47. return comps.front();
  48. }
  49. void Rewardable::Reward::loadComponents(std::vector<Component> & comps,
  50. const CGHeroInstance * h) const
  51. {
  52. for (auto comp : extraComponents)
  53. comps.push_back(comp);
  54. if (heroExperience)
  55. {
  56. comps.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(h->calculateXp(heroExperience)), 0);
  57. }
  58. if (heroLevel)
  59. comps.emplace_back(Component::EComponentType::EXPERIENCE, 1, heroLevel, 0);
  60. if (manaDiff || manaPercentage >= 0)
  61. comps.emplace_back(Component::EComponentType::PRIM_SKILL, 5, calculateManaPoints(h) - h->mana, 0);
  62. for (size_t i=0; i<primary.size(); i++)
  63. {
  64. if (primary[i] != 0)
  65. comps.emplace_back(Component::EComponentType::PRIM_SKILL, static_cast<ui16>(i), primary[i], 0);
  66. }
  67. for(const auto & entry : secondary)
  68. comps.emplace_back(Component::EComponentType::SEC_SKILL, entry.first, entry.second, 0);
  69. for(const auto & entry : artifacts)
  70. comps.emplace_back(Component::EComponentType::ARTIFACT, entry, 1, 0);
  71. for(const auto & entry : spells)
  72. comps.emplace_back(Component::EComponentType::SPELL, entry, 1, 0);
  73. for(const auto & entry : creatures)
  74. comps.emplace_back(Component::EComponentType::CREATURE, entry.type->getId(), entry.count, 0);
  75. for (size_t i=0; i<resources.size(); i++)
  76. {
  77. if (resources[i] !=0)
  78. comps.emplace_back(Component::EComponentType::RESOURCE, static_cast<ui16>(i), resources[i], 0);
  79. }
  80. }
  81. void Rewardable::Reward::serializeJson(JsonSerializeFormat & handler)
  82. {
  83. resources.serializeJson(handler, "resources");
  84. handler.serializeBool("removeObject", removeObject);
  85. handler.serializeInt("manaPercentage", manaPercentage);
  86. handler.serializeInt("movePercentage", movePercentage);
  87. handler.serializeInt("heroExperience", heroExperience);
  88. handler.serializeInt("heroLevel", heroLevel);
  89. handler.serializeInt("manaDiff", manaDiff);
  90. handler.serializeInt("manaOverflowFactor", manaOverflowFactor);
  91. handler.serializeInt("movePoints", movePoints);
  92. handler.serializeIdArray("artifacts", artifacts);
  93. handler.serializeIdArray("spells", spells);
  94. handler.enterArray("creatures").serializeStruct(creatures);
  95. {
  96. auto a = handler.enterArray("primary");
  97. a.syncSize(primary);
  98. for(int i = 0; i < primary.size(); ++i)
  99. a.serializeInt(i, primary[i]);
  100. }
  101. {
  102. auto a = handler.enterArray("secondary");
  103. std::vector<std::pair<std::string, std::string>> fieldValue;
  104. if(handler.saving)
  105. {
  106. for(auto & i : secondary)
  107. {
  108. auto key = VLC->skillh->encodeSkill(i.first);
  109. auto value = NSecondarySkill::levels.at(i.second);
  110. fieldValue.emplace_back(key, value);
  111. }
  112. }
  113. a.syncSize(fieldValue);
  114. for(int i = 0; i < fieldValue.size(); ++i)
  115. {
  116. auto e = a.enterStruct(i);
  117. e->serializeString("skill", fieldValue[i].first);
  118. e->serializeString("level", fieldValue[i].second);
  119. }
  120. if(!handler.saving)
  121. {
  122. for(auto & i : fieldValue)
  123. {
  124. const int skillId = VLC->skillh->decodeSkill(i.first);
  125. if(skillId < 0)
  126. {
  127. logGlobal->error("Invalid secondary skill %s", i.first);
  128. continue;
  129. }
  130. const int level = vstd::find_pos(NSecondarySkill::levels, i.second);
  131. if(level < 0)
  132. {
  133. logGlobal->error("Invalid secondary skill level%s", i.second);
  134. continue;
  135. }
  136. secondary[SecondarySkill(skillId)] = level;
  137. }
  138. }
  139. }
  140. {
  141. auto a = handler.enterArray("creaturesChange");
  142. std::vector<std::pair<CreatureID, CreatureID>> fieldValue;
  143. if(handler.saving)
  144. {
  145. for(auto & i : creaturesChange)
  146. fieldValue.push_back(i);
  147. }
  148. a.syncSize(fieldValue);
  149. for(int i = 0; i < fieldValue.size(); ++i)
  150. {
  151. auto e = a.enterStruct(i);
  152. e->serializeId("creature", fieldValue[i].first, CreatureID{});
  153. e->serializeId("amount", fieldValue[i].second, CreatureID{});
  154. }
  155. if(!handler.saving)
  156. {
  157. for(auto & i : fieldValue)
  158. creaturesChange[i.first] = i.second;
  159. }
  160. }
  161. {
  162. auto a = handler.enterStruct("spellCast");
  163. a->serializeId("spell", spellCast.first, SpellID{});
  164. a->serializeInt("level", spellCast.second);
  165. }
  166. }
  167. VCMI_LIB_NAMESPACE_END