CBonusTypeHandler.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * CBonusTypeHandler.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. #define INSTANTIATE_CBonusTypeHandler_HERE
  12. #include "CBonusTypeHandler.h"
  13. #include "filesystem/Filesystem.h"
  14. #include "CCreatureHandler.h"
  15. #include "GameConstants.h"
  16. #include "GameLibrary.h"
  17. #include "modding/ModScope.h"
  18. #include "modding/IdentifierStorage.h"
  19. #include "spells/CSpellHandler.h"
  20. #include "texts/CGeneralTextHandler.h"
  21. #include "json/JsonUtils.h"
  22. VCMI_LIB_NAMESPACE_BEGIN
  23. ///CBonusType
  24. std::string CBonusType::getDescriptionTextID() const
  25. {
  26. return TextIdentifier( "core", "bonus", identifier, "description").get();
  27. }
  28. ///CBonusTypeHandler
  29. CBonusTypeHandler::CBonusTypeHandler()
  30. {
  31. //register predefined bonus types
  32. // MOD COMPATIBILITY FOR 1.6
  33. registerObject(ModScope::scopeBuiltin(), "bonus", "FEAR", JsonNode(), 0);
  34. registerObject(ModScope::scopeBuiltin(), "bonus", "FEARLESS", JsonNode(), 0);
  35. #define BONUS_NAME(x) { #x },
  36. builtinBonusNames = {
  37. BONUS_LIST
  38. };
  39. #undef BONUS_NAME
  40. for (int i = 0; i < builtinBonusNames.size(); ++i)
  41. bonusTypes.push_back(std::make_shared<CBonusType>());
  42. for (int i = 0; i < builtinBonusNames.size(); ++i)
  43. registerObject(ModScope::scopeBuiltin(), "bonus", builtinBonusNames[i], JsonNode(), i);
  44. }
  45. CBonusTypeHandler::~CBonusTypeHandler() = default;
  46. std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer) const
  47. {
  48. if(!bearer)
  49. throw std::runtime_error("CBonusTypeHandler::bonusToString: invalid bonus system node!");
  50. return bonusToString(bonus, bearer->valOfBonuses(bonus->type, bonus->subtype));
  51. }
  52. std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus) const
  53. {
  54. return bonusToString(bonus, bonus->val);
  55. }
  56. std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonus, int bonusValue) const
  57. {
  58. const CBonusType & bt = *bonusTypes.at(vstd::to_underlying(bonus->type));
  59. if(bt.hidden)
  60. return "";
  61. std::string textID = bt.getDescriptionTextID();
  62. std::string text = LIBRARY->generaltexth->translate(textID);
  63. auto subtype = bonus->subtype.getNum();
  64. if (bt.subtypeDescriptions.count(subtype))
  65. {
  66. std::string fullTextID = textID + '.' + bt.subtypeDescriptions.at(subtype);
  67. text = LIBRARY->generaltexth->translate(fullTextID);
  68. }
  69. else if (bt.valueDescriptions.count(bonusValue))
  70. {
  71. std::string fullTextID = textID + '.' + bt.valueDescriptions.at(bonusValue);
  72. text = LIBRARY->generaltexth->translate(fullTextID);
  73. }
  74. if (text.find("${val}") != std::string::npos)
  75. boost::algorithm::replace_all(text, "${val}", std::to_string(bonusValue));
  76. if (text.find("${subtype.creature}") != std::string::npos && bonus->subtype.as<CreatureID>().hasValue())
  77. boost::algorithm::replace_all(text, "${subtype.creature}", bonus->subtype.as<CreatureID>().toCreature()->getNamePluralTranslated());
  78. if (text.find("${subtype.spell}") != std::string::npos && bonus->subtype.as<SpellID>().hasValue())
  79. boost::algorithm::replace_all(text, "${subtype.spell}", bonus->subtype.as<SpellID>().toSpell()->getNameTranslated());
  80. return text;
  81. }
  82. ImagePath CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
  83. {
  84. const CBonusType & bt = *bonusTypes.at(vstd::to_underlying(bonus->type));
  85. if (bonus->type == BonusType::SPELL_IMMUNITY && bonus->subtype.as<SpellID>().hasValue())
  86. {
  87. const CSpell * sp = bonus->subtype.as<SpellID>().toSpell();
  88. return sp->getIconImmune();
  89. }
  90. if (bt.subtypeIcons.count(bonus->subtype.getNum()))
  91. return bt.subtypeIcons.at(bonus->subtype.getNum());
  92. if (bt.valueIcons.count(bonus->val))
  93. return bt.valueIcons.at(bonus->val);
  94. return bt.icon;
  95. }
  96. std::vector<JsonNode> CBonusTypeHandler::loadLegacyData()
  97. {
  98. return {};
  99. }
  100. void CBonusTypeHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
  101. {
  102. if (vstd::contains(builtinBonusNames, name))
  103. {
  104. //h3 bonus
  105. BonusType bonus = static_cast<BonusType>(vstd::find_pos(builtinBonusNames, name));
  106. CBonusType & bt =*bonusTypes.at(vstd::to_underlying(bonus));
  107. loadItem(data, bt, name);
  108. logBonus->trace("Loaded bonus type %s", name);
  109. }
  110. else
  111. {
  112. // new bonus
  113. registerObject(scope, "bonus", name, data, bonusTypes.size());
  114. bonusTypes.push_back(std::make_shared<CBonusType>());
  115. loadItem(data, *bonusTypes.back(), name);
  116. logBonus->trace("New bonus type %s", name);
  117. }
  118. }
  119. void CBonusTypeHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
  120. {
  121. assert(0);
  122. }
  123. void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest, const std::string & name) const
  124. {
  125. dest.identifier = name;
  126. dest.hidden = source["hidden"].Bool(); //Null -> false
  127. dest.creatureNature = source["creatureNature"].Bool(); //Null -> false
  128. dest.blockDescriptionPropagation = source["blockDescriptionPropagation"].Bool(); //Null -> false
  129. if (!dest.hidden)
  130. LIBRARY->generaltexth->registerString( "vcmi", dest.getDescriptionTextID(), source["description"]);
  131. const JsonNode & graphics = source["graphics"];
  132. if(!graphics.isNull())
  133. dest.icon = ImagePath::fromJson(graphics["icon"]);
  134. for (const auto & additionalIcon : graphics["subtypeIcons"].Struct())
  135. {
  136. auto path = ImagePath::fromJson(additionalIcon.second);
  137. LIBRARY->identifiers()->requestIdentifier(additionalIcon.second.getModScope(), additionalIcon.first, [&dest, path](int32_t index)
  138. {
  139. dest.subtypeIcons[index] = path;
  140. });
  141. }
  142. for (const auto & additionalIcon : graphics["valueIcons"].Struct())
  143. {
  144. auto path = ImagePath::fromJson(additionalIcon.second);
  145. int value = std::stoi(additionalIcon.first);
  146. dest.valueIcons[value] = path;
  147. }
  148. for (const auto & additionalDescription : source["subtypeDescriptions"].Struct())
  149. {
  150. LIBRARY->generaltexth->registerString( "vcmi", dest.getDescriptionTextID() + "." + additionalDescription.first, additionalDescription.second);
  151. auto stringID = additionalDescription.first;
  152. LIBRARY->identifiers()->requestIdentifier(additionalDescription.second.getModScope(), additionalDescription.first, [&dest, stringID](int32_t index)
  153. {
  154. dest.subtypeDescriptions[index] = stringID;
  155. });
  156. }
  157. for (const auto & additionalDescription : source["valueDescriptions"].Struct())
  158. {
  159. LIBRARY->generaltexth->registerString( "vcmi", dest.getDescriptionTextID() + "." + additionalDescription.first, additionalDescription.second);
  160. auto stringID = additionalDescription.first;
  161. int value = std::stoi(additionalDescription.first);
  162. dest.valueDescriptions[value] = stringID;
  163. }
  164. }
  165. const std::string & CBonusTypeHandler::bonusToString(BonusType bonus) const
  166. {
  167. return bonusTypes.at(static_cast<int>(bonus))->identifier;
  168. }
  169. bool CBonusTypeHandler::isCreatureNatureBonus(BonusType bonus) const
  170. {
  171. return bonusTypes.at(static_cast<int>(bonus))->creatureNature;
  172. }
  173. bool CBonusTypeHandler::shouldPropagateDescription(BonusType bonus) const
  174. {
  175. return !bonusTypes.at(static_cast<int>(bonus))->blockDescriptionPropagation;
  176. }
  177. std::vector<BonusType> CBonusTypeHandler::getAllObjets() const
  178. {
  179. std::vector<BonusType> ret;
  180. for (int i = 0; i < bonusTypes.size(); ++i)
  181. ret.push_back(static_cast<BonusType>(i));
  182. return ret;
  183. }
  184. VCMI_LIB_NAMESPACE_END