MetaString.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * CGameState.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 "MetaString.h"
  12. #include "CArtHandler.h"
  13. #include "CCreatureHandler.h"
  14. #include "CCreatureSet.h"
  15. #include "CGeneralTextHandler.h"
  16. #include "CSkillHandler.h"
  17. #include "GameConstants.h"
  18. #include "VCMI_Lib.h"
  19. #include "mapObjectConstructors/CObjectClassesHandler.h"
  20. #include "spells/CSpellHandler.h"
  21. VCMI_LIB_NAMESPACE_BEGIN
  22. void MetaString::getLocalString(const std::pair<ui8, ui32> & txt, std::string & dst) const
  23. {
  24. int type = txt.first;
  25. int ser = txt.second;
  26. if(type == ART_NAMES)
  27. {
  28. const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
  29. if(art)
  30. dst = art->getNameTranslated();
  31. else
  32. dst = "#!#";
  33. }
  34. else if(type == ART_DESCR)
  35. {
  36. const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
  37. if(art)
  38. dst = art->getDescriptionTranslated();
  39. else
  40. dst = "#!#";
  41. }
  42. else if (type == ART_EVNTS)
  43. {
  44. const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
  45. if(art)
  46. dst = art->getEventTranslated();
  47. else
  48. dst = "#!#";
  49. }
  50. else if(type == CRE_PL_NAMES)
  51. {
  52. const auto * cre = CreatureID(ser).toCreature(VLC->creatures());
  53. if(cre)
  54. dst = cre->getNamePluralTranslated();
  55. else
  56. dst = "#!#";
  57. }
  58. else if(type == CRE_SING_NAMES)
  59. {
  60. const auto * cre = CreatureID(ser).toCreature(VLC->creatures());
  61. if(cre)
  62. dst = cre->getNameSingularTranslated();
  63. else
  64. dst = "#!#";
  65. }
  66. else if(type == MINE_NAMES)
  67. {
  68. dst = VLC->generaltexth->translate("core.minename", ser);
  69. }
  70. else if(type == MINE_EVNTS)
  71. {
  72. dst = VLC->generaltexth->translate("core.mineevnt", ser);
  73. }
  74. else if(type == SPELL_NAME)
  75. {
  76. const auto * spell = SpellID(ser).toSpell(VLC->spells());
  77. if(spell)
  78. dst = spell->getNameTranslated();
  79. else
  80. dst = "#!#";
  81. }
  82. else if(type == OBJ_NAMES)
  83. {
  84. dst = VLC->objtypeh->getObjectName(ser, 0);
  85. }
  86. else if(type == SEC_SKILL_NAME)
  87. {
  88. dst = VLC->skillh->getByIndex(ser)->getNameTranslated();
  89. }
  90. else
  91. {
  92. switch(type)
  93. {
  94. case GENERAL_TXT:
  95. dst = VLC->generaltexth->translate("core.genrltxt", ser);
  96. break;
  97. case RES_NAMES:
  98. dst = VLC->generaltexth->translate("core.restypes", ser);
  99. break;
  100. case ARRAY_TXT:
  101. dst = VLC->generaltexth->translate("core.arraytxt", ser);
  102. break;
  103. case CREGENS:
  104. dst = VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR1, ser);
  105. break;
  106. case CREGENS4:
  107. dst = VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR4, ser);
  108. break;
  109. case ADVOB_TXT:
  110. dst = VLC->generaltexth->translate("core.advevent", ser);
  111. break;
  112. case COLOR:
  113. dst = VLC->generaltexth->translate("vcmi.capitalColors", ser);
  114. break;
  115. case JK_TXT:
  116. dst = VLC->generaltexth->translate("core.jktext", ser);
  117. break;
  118. default:
  119. logGlobal->error("Failed string substitution because type is %d", type);
  120. dst = "#@#";
  121. return;
  122. }
  123. }
  124. }
  125. DLL_LINKAGE void MetaString::toString(std::string &dst) const
  126. {
  127. size_t exSt = 0;
  128. size_t loSt = 0;
  129. size_t nums = 0;
  130. dst.clear();
  131. for(const auto & elem : message)
  132. {//TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER
  133. switch(elem)
  134. {
  135. case TEXACT_STRING:
  136. dst += exactStrings[exSt++];
  137. break;
  138. case TLOCAL_STRING:
  139. {
  140. std::string hlp;
  141. getLocalString(localStrings[loSt++], hlp);
  142. dst += hlp;
  143. }
  144. break;
  145. case TNUMBER:
  146. dst += std::to_string(numbers[nums++]);
  147. break;
  148. case TREPLACE_ESTRING:
  149. boost::replace_first(dst, "%s", exactStrings[exSt++]);
  150. break;
  151. case TREPLACE_LSTRING:
  152. {
  153. std::string hlp;
  154. getLocalString(localStrings[loSt++], hlp);
  155. boost::replace_first(dst, "%s", hlp);
  156. }
  157. break;
  158. case TREPLACE_NUMBER:
  159. boost::replace_first(dst, "%d", std::to_string(numbers[nums++]));
  160. break;
  161. case TREPLACE_PLUSNUMBER:
  162. boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++]));
  163. break;
  164. default:
  165. logGlobal->error("MetaString processing error! Received message of type %d", int(elem));
  166. break;
  167. }
  168. }
  169. }
  170. DLL_LINKAGE std::string MetaString::toString() const
  171. {
  172. std::string ret;
  173. toString(ret);
  174. return ret;
  175. }
  176. DLL_LINKAGE std::string MetaString::buildList () const
  177. ///used to handle loot from creature bank
  178. {
  179. size_t exSt = 0;
  180. size_t loSt = 0;
  181. size_t nums = 0;
  182. std::string lista;
  183. for (int i = 0; i < message.size(); ++i)
  184. {
  185. if (i > 0 && (message[i] == TEXACT_STRING || message[i] == TLOCAL_STRING))
  186. {
  187. if (exSt == exactStrings.size() - 1)
  188. lista += VLC->generaltexth->allTexts[141]; //" and "
  189. else
  190. lista += ", ";
  191. }
  192. switch (message[i])
  193. {
  194. case TEXACT_STRING:
  195. lista += exactStrings[exSt++];
  196. break;
  197. case TLOCAL_STRING:
  198. {
  199. std::string hlp;
  200. getLocalString (localStrings[loSt++], hlp);
  201. lista += hlp;
  202. }
  203. break;
  204. case TNUMBER:
  205. lista += std::to_string(numbers[nums++]);
  206. break;
  207. case TREPLACE_ESTRING:
  208. lista.replace (lista.find("%s"), 2, exactStrings[exSt++]);
  209. break;
  210. case TREPLACE_LSTRING:
  211. {
  212. std::string hlp;
  213. getLocalString (localStrings[loSt++], hlp);
  214. lista.replace (lista.find("%s"), 2, hlp);
  215. }
  216. break;
  217. case TREPLACE_NUMBER:
  218. lista.replace (lista.find("%d"), 2, std::to_string(numbers[nums++]));
  219. break;
  220. default:
  221. logGlobal->error("MetaString processing error! Received message of type %d",int(message[i]));
  222. }
  223. }
  224. return lista;
  225. }
  226. void MetaString::addCreReplacement(const CreatureID & id, TQuantity count) //adds sing or plural name;
  227. {
  228. if (!count)
  229. addReplacement (CRE_PL_NAMES, id); //no creatures - just empty name (eg. defeat Angels)
  230. else if (count == 1)
  231. addReplacement (CRE_SING_NAMES, id);
  232. else
  233. addReplacement (CRE_PL_NAMES, id);
  234. }
  235. void MetaString::addReplacement(const CStackBasicDescriptor & stack)
  236. {
  237. assert(stack.type); //valid type
  238. addCreReplacement(stack.type->getId(), stack.count);
  239. }
  240. VCMI_LIB_NAMESPACE_END