CHeroOverview.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * CHeroOverview.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 "CHeroOverview.h"
  12. #include "../CCallback.h"
  13. #include "../CPlayerInterface.h"
  14. #include "../GameEngine.h"
  15. #include "../render/Canvas.h"
  16. #include "../render/Colors.h"
  17. #include "../render/IImage.h"
  18. #include "../renderSDL/RenderHandler.h"
  19. #include "../widgets/CComponentHolder.h"
  20. #include "../widgets/Slider.h"
  21. #include "../widgets/Images.h"
  22. #include "../widgets/TextControls.h"
  23. #include "../widgets/GraphicalPrimitiveCanvas.h"
  24. #include "../eventsSDL/InputHandler.h"
  25. #include "../../lib/IGameSettings.h"
  26. #include "../../lib/entities/hero/CHeroHandler.h"
  27. #include "../../lib/entities/hero/CHeroClass.h"
  28. #include "../../lib/texts/CGeneralTextHandler.h"
  29. #include "../../lib/CCreatureHandler.h"
  30. #include "../../lib/CSkillHandler.h"
  31. #include "../../lib/spells/CSpellHandler.h"
  32. #include "../../lib/VCMI_Lib.h"
  33. CHeroOverview::CHeroOverview(const HeroTypeID & h)
  34. : CWindowObject(BORDERED | RCLICK_POPUP), hero { h }
  35. {
  36. OBJECT_CONSTRUCTION;
  37. heroIdx = hero.getNum();
  38. pos = Rect(0, 0, 600, 485);
  39. genBackground();
  40. genControls();
  41. center();
  42. }
  43. void CHeroOverview::genBackground()
  44. {
  45. backgroundTexture = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
  46. updateShadow();
  47. }
  48. void CHeroOverview::genControls()
  49. {
  50. Rect r = Rect();
  51. labelTitle = std::make_shared<CLabel>(pos.w / 2 + 8, 21, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, VLC->generaltexth->allTexts[77]);
  52. // hero image
  53. r = Rect(borderOffset, borderOffset + yOffset, 58, 64);
  54. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  55. imageHero = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), (*VLC->heroh)[heroIdx]->imageIndex, 0, r.x, r.y);
  56. // hero name
  57. r = Rect(64 + borderOffset, borderOffset + yOffset, 220, 64);
  58. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  59. labelHeroName = std::make_shared<CLabel>(r.x + 110, r.y + 20, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, (*VLC->heroh)[heroIdx]->getNameTranslated());
  60. labelHeroClass = std::make_shared<CLabel>(r.x + 110, r.y + 45, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, (*VLC->heroh)[heroIdx]->heroClass->getNameTranslated());
  61. // vertical line
  62. backgroundLines.push_back(std::make_shared<SimpleLine>(Point(295, borderOffset + yOffset - 1), Point(295, borderOffset + yOffset - 2 + 439), borderColor));
  63. // skills header
  64. r = Rect(borderOffset, 2 * borderOffset + yOffset + 64, 284, 20);
  65. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  66. for(int i = 0; i < 4; i++)
  67. labelSkillHeader.push_back(std::make_shared<CLabel>((r.w / 4) * i + 42, r.y + 10, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, VLC->generaltexth->jktexts[1 + i]));
  68. // skill
  69. const int tmp[] = {0, 1, 2, 5};
  70. for(int i = 0; i < 4; i++)
  71. {
  72. r = Rect((284 / 4) * i + 21, 3 * borderOffset + yOffset + 85, 42, 42);
  73. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  74. imageSkill.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL42"), tmp[i], 0, r.x, r.y));
  75. }
  76. // skills footer
  77. r = Rect(borderOffset, 4 * borderOffset + yOffset + 128, 284, 20);
  78. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  79. for(int i = 0; i < 4; i++)
  80. {
  81. r = Rect((284 / 4) * i + 42, r.y, r.w, r.h);
  82. labelSkillFooter.push_back(std::make_shared<CLabel>(r.x, r.y + 10, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string((*VLC->heroh)[heroIdx]->heroClass->primarySkillInitial[i])));
  83. }
  84. // hero biography
  85. r = Rect(borderOffset, 5 * borderOffset + yOffset + 148, 284, 130);
  86. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  87. labelHeroBiography = std::make_shared<CTextBox>((*VLC->heroh)[heroIdx]->getBiographyTranslated(), r.resize(-borderOffset), CSlider::EStyle::BROWN, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
  88. if(labelHeroBiography->slider && ENGINE->input().getCurrentInputMode() != InputMode::TOUCH)
  89. labelHeroBiography->slider->clearScrollBounds();
  90. // speciality name
  91. r = Rect(2 * borderOffset + 44, 6 * borderOffset + yOffset + 278, 235, 44);
  92. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  93. labelHeroSpeciality = std::make_shared<CLabel>(r.x + borderOffset, r.y + borderOffset, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, VLC->generaltexth->allTexts[78]);
  94. labelSpecialityName = std::make_shared<CLabel>(r.x + borderOffset, r.y + borderOffset + 20, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, (*VLC->heroh)[heroIdx]->getSpecialtyNameTranslated());
  95. // speciality image
  96. r = Rect(borderOffset, 6 * borderOffset + yOffset + 278, 44, 44);
  97. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  98. imageSpeciality = std::make_shared<CAnimImage>(AnimationPath::builtin("UN44"), (*VLC->heroh)[heroIdx]->imageIndex, 0, r.x, r.y);
  99. // speciality description
  100. r = Rect(borderOffset, 7 * borderOffset + yOffset + 322, 284, 85);
  101. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  102. labelSpecialityDescription = std::make_shared<CTextBox>((*VLC->heroh)[heroIdx]->getSpecialtyDescriptionTranslated(), r.resize(-borderOffset), CSlider::EStyle::BROWN, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
  103. if(labelSpecialityDescription->slider && ENGINE->input().getCurrentInputMode() != InputMode::TOUCH)
  104. labelSpecialityDescription->slider->clearScrollBounds();
  105. // army title
  106. r = Rect(302, borderOffset + yOffset, 292, 30);
  107. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  108. labelArmyTitle = std::make_shared<CLabel>(r.x + borderOffset, r.y + borderOffset + 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, VLC->generaltexth->translate("vcmi.heroOverview.startingArmy"));
  109. // army numbers
  110. r = Rect(302, 3 * borderOffset + yOffset + 62, 292, 32);
  111. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  112. auto stacksCountChances = VLC->engineSettings()->getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES);
  113. // army
  114. int space = (260 - 7 * 32) / 6;
  115. for(int i = 0; i < 7; i++)
  116. {
  117. r = Rect(318 + i * (32 + space), 2 * borderOffset + yOffset + 30, 32, 32);
  118. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  119. }
  120. int i = 0;
  121. int iStack = 0;
  122. for(auto & army : (*VLC->heroh)[heroIdx]->initialArmy)
  123. {
  124. if((*VLC->creh)[army.creature]->warMachine == ArtifactID::NONE)
  125. {
  126. imageArmy.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), (*VLC->creh)[army.creature]->getIconIndex(), 0, 302 + i * (32 + space) + 16, 2 * borderOffset + yOffset + 30));
  127. labelArmyCount.push_back(std::make_shared<CLabel>(302 + i * (32 + space) + 32, 3 * borderOffset + yOffset + 72, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, (army.minAmount == army.maxAmount) ? std::to_string(army.minAmount) : std::to_string(army.minAmount) + "-" + std::to_string(army.maxAmount)));
  128. if(iStack<stacksCountChances.size())
  129. labelArmyCount.push_back(std::make_shared<CLabel>(302 + i * (32 + space) + 32, 3 * borderOffset + yOffset + 86, FONT_SMALL, ETextAlignment::CENTER, grayedColor, std::to_string(stacksCountChances[iStack]) + "%"));
  130. i++;
  131. }
  132. iStack++;
  133. }
  134. // war machine title
  135. r = Rect(302, 4 * borderOffset + yOffset + 94, 292, 30);
  136. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  137. labelWarMachineTitle = std::make_shared<CLabel>(r.x + borderOffset, r.y + borderOffset + 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, VLC->generaltexth->translate("vcmi.heroOverview.warMachine"));
  138. // war machine
  139. space = (260 - 4 * 32) / 3;
  140. for(int i = 0; i < 4; i++)
  141. {
  142. r = Rect(318 + i * (32 + space), 5 * borderOffset + yOffset + 124, 32, 32);
  143. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  144. }
  145. i = 0;
  146. iStack = 0;
  147. for(auto & army : (*VLC->heroh)[heroIdx]->initialArmy)
  148. {
  149. if(i == 0)
  150. {
  151. imageWarMachine.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), (*VLC->creh)[army.creature.CATAPULT]->getIconIndex(), 0, 302 + i * (32 + space) + 16, 5 * borderOffset + yOffset + 124));
  152. labelArmyCount.push_back(std::make_shared<CLabel>(302 + i * (32 + space) + 51, 5 * borderOffset + yOffset + 144, FONT_SMALL, ETextAlignment::TOPLEFT, grayedColor, "100%"));
  153. i++;
  154. }
  155. if((*VLC->creh)[army.creature]->warMachine != ArtifactID::NONE)
  156. {
  157. imageWarMachine.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), (*VLC->creh)[army.creature]->getIconIndex(), 0, 302 + i * (32 + space) + 16, 5 * borderOffset + yOffset + 124));
  158. if(iStack<stacksCountChances.size())
  159. labelArmyCount.push_back(std::make_shared<CLabel>(302 + i * (32 + space) + 51, 5 * borderOffset + yOffset + 144, FONT_SMALL, ETextAlignment::TOPLEFT, grayedColor, std::to_string(stacksCountChances[iStack]) + "%"));
  160. i++;
  161. }
  162. iStack++;
  163. }
  164. // secskill title
  165. r = Rect(302, 6 * borderOffset + yOffset + 156, (292 / 2) - 2 * borderOffset, 30);
  166. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  167. labelSecSkillTitle = std::make_shared<CLabel>(r.x + borderOffset, r.y + borderOffset + 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, VLC->generaltexth->translate("vcmi.heroOverview.secondarySkills"));
  168. // vertical line
  169. backgroundLines.push_back(std::make_shared<SimpleLine>(Point(302 + (292 / 2), 6 * borderOffset + yOffset + 156 - 1), Point(302 + (292 / 2), 6 * borderOffset + yOffset + 156 - 2 + 254), borderColor));
  170. // spell title
  171. r = Rect(302 + (292 / 2) + 2 * borderOffset, 6 * borderOffset + yOffset + 156, (292 / 2) - 2 * borderOffset, 30);
  172. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  173. labelSpellTitle = std::make_shared<CLabel>(r.x + borderOffset, r.y + borderOffset + 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, VLC->generaltexth->translate("vcmi.heroOverview.spells"));
  174. // secskill
  175. for(int i = 0; i < 6; i++)
  176. {
  177. r = Rect(302, 7 * borderOffset + yOffset + 186 + i * (32 + borderOffset), 32, 32);
  178. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  179. r = Rect(r.x + 32 + borderOffset, r.y, (292 / 2) - 32 - 3 * borderOffset, r.h);
  180. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  181. }
  182. i = 0;
  183. for(auto & skill : (*VLC->heroh)[heroIdx]->secSkillsInit)
  184. {
  185. secSkills.push_back(std::make_shared<CSecSkillPlace>(Point(302, 7 * borderOffset + yOffset + 186 + i * (32 + borderOffset)),
  186. CSecSkillPlace::ImageSize::SMALL, skill.first, skill.second));
  187. labelSecSkillsNames.push_back(std::make_shared<CLabel>(334 + 2 * borderOffset, 8 * borderOffset + yOffset + 186 + i * (32 + borderOffset) - 5, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, VLC->generaltexth->levels[skill.second - 1]));
  188. labelSecSkillsNames.push_back(std::make_shared<CLabel>(334 + 2 * borderOffset, 8 * borderOffset + yOffset + 186 + i * (32 + borderOffset) + 10, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, (*VLC->skillh)[skill.first]->getNameTranslated()));
  189. i++;
  190. }
  191. // spell
  192. for(int i = 0; i < 6; i++)
  193. {
  194. r = Rect(302 + (292 / 2) + 2 * borderOffset, 7 * borderOffset + yOffset + 186 + i * (32 + borderOffset), 32, 32);
  195. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  196. r = Rect(r.x + 32 + borderOffset, r.y, (292 / 2) - 32 - 3 * borderOffset, r.h);
  197. backgroundRectangles.push_back(std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor));
  198. }
  199. i = 0;
  200. for(auto & spell : (*VLC->heroh)[heroIdx]->spells)
  201. {
  202. if(i == 0)
  203. {
  204. if((*VLC->heroh)[heroIdx]->haveSpellBook)
  205. {
  206. imageSpells.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("ARTIFACT"), 0, Rect(302 + (292 / 2) + 2 * borderOffset, 7 * borderOffset + yOffset + 186 + i * (32 + borderOffset), 32, 32), 0));
  207. }
  208. i++;
  209. }
  210. imageSpells.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SPELLBON"), (*VLC->spellh)[spell]->getIconIndex(), Rect(302 + (292 / 2) + 2 * borderOffset, 7 * borderOffset + yOffset + 186 + i * (32 + borderOffset), 32, 32), 0));
  211. labelSpellsNames.push_back(std::make_shared<CLabel>(302 + (292 / 2) + 3 * borderOffset + 32 + borderOffset, 8 * borderOffset + yOffset + 186 + i * (32 + borderOffset) + 3, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, (*VLC->spellh)[spell]->getNameTranslated()));
  212. i++;
  213. }
  214. }