CExchangeWindow.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * CExchangeWindow.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 "CExchangeWindow.h"
  12. #include "CHeroBackpackWindow.h"
  13. #include "../CPlayerInterface.h"
  14. #include "../GameEngine.h"
  15. #include "../GameInstance.h"
  16. #include "../gui/CursorHandler.h"
  17. #include "../gui/Shortcut.h"
  18. #include "../gui/WindowHandler.h"
  19. #include "../widgets/CGarrisonInt.h"
  20. #include "../widgets/Images.h"
  21. #include "../widgets/Buttons.h"
  22. #include "../widgets/TextControls.h"
  23. #include "../render/IRenderHandler.h"
  24. #include "../lib/CSkillHandler.h"
  25. #include "../lib/GameLibrary.h"
  26. #include "../lib/callback/CCallback.h"
  27. #include "../lib/entities/hero/CHeroHandler.h"
  28. #include "../lib/filesystem/Filesystem.h"
  29. #include "../lib/mapObjects/CGHeroInstance.h"
  30. #include "../lib/texts/CGeneralTextHandler.h"
  31. #include "../lib/texts/TextOperations.h"
  32. static const std::string QUICK_EXCHANGE_BG = "quick-exchange/TRADEQE";
  33. static bool isQuickExchangeLayoutAvailable()
  34. {
  35. return CResourceHandler::get()->existsResource(ImagePath::builtin("SPRITES/" + QUICK_EXCHANGE_BG));
  36. }
  37. CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID)
  38. : CWindowObject(PLAYER_COLORED | BORDERED, ImagePath::builtin(isQuickExchangeLayoutAvailable() ? QUICK_EXCHANGE_BG : "TRADE2")),
  39. controller(hero1, hero2)
  40. {
  41. const bool qeLayout = isQuickExchangeLayoutAvailable();
  42. OBJECT_CONSTRUCTION;
  43. addUsedEvents(KEYBOARD);
  44. heroInst[0] = GAME->interface()->cb->getHero(hero1);
  45. heroInst[1] = GAME->interface()->cb->getHero(hero2);
  46. auto genTitle = [](const CGHeroInstance * h)
  47. {
  48. boost::format fmt(LIBRARY->generaltexth->allTexts[138]);
  49. fmt % h->getNameTranslated() % h->level % h->getClassNameTranslated();
  50. return boost::str(fmt);
  51. };
  52. titles[0] = std::make_shared<CLabel>(147, qeLayout ? 21 : 25, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, genTitle(heroInst[0]));
  53. titles[1] = std::make_shared<CLabel>(653, qeLayout ? 21 : 25, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, genTitle(heroInst[1]));
  54. for(int g = 0; g < 4; ++g)
  55. {
  56. if (qeLayout)
  57. primSkillImages.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL32"), g, Rect(389, 12 + 26 * g, 22, 22)));
  58. else
  59. primSkillImages.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL32"), g, 0, 385, 19 + 36 * g));
  60. }
  61. for(int leftRight : {0, 1})
  62. {
  63. const CGHeroInstance * hero = heroInst.at(leftRight);
  64. for(int m=0; m<GameConstants::PRIMARY_SKILLS; ++m)
  65. primSkillValues[leftRight].push_back(std::make_shared<CLabel>(352 + (qeLayout ? 96 : 93) * leftRight, (qeLayout ? 22 : 35) + (qeLayout ? 26 : 36) * m, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE));
  66. for(int m=0; m < std::min(static_cast<int>(hero->secSkills.size()), 8); ++m)
  67. secSkills[leftRight].push_back(std::make_shared<CSecSkillPlace>(Point(32 + 36 * m + 454 * leftRight, qeLayout ? 80 : 88), CSecSkillPlace::ImageSize::SMALL,
  68. hero->secSkills[m].first, hero->secSkills[m].second));
  69. specImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("UN32"), hero->getHeroType()->imageIndex, 0, 67 + 490 * leftRight, qeLayout ? 41 : 45);
  70. expImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL32"), 4, 0, 103 + 490 * leftRight, qeLayout ? 41 : 45);
  71. expValues[leftRight] = std::make_shared<CLabel>(119 + 490 * leftRight, qeLayout ? 66 : 71, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
  72. manaImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("PSKIL32"), 5, 0, 139 + 490 * leftRight, qeLayout ? 41 : 45);
  73. manaValues[leftRight] = std::make_shared<CLabel>(155 + 490 * leftRight, qeLayout ? 66 : 71, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
  74. }
  75. artifs[0] = std::make_shared<CArtifactsOfHeroMain>(Point(-334, 151));
  76. artifs[0]->clickPressedCallback = [this, hero = heroInst[0]](const CArtPlace & artPlace, const Point & cursorPosition){clickPressedOnArtPlace(hero, artPlace.slot, true, false, false, cursorPosition);};
  77. artifs[0]->showPopupCallback = [this, heroArts = artifs[0]](CArtPlace & artPlace, const Point & cursorPosition){showArtifactPopup(*heroArts, artPlace, cursorPosition);};
  78. artifs[0]->gestureCallback = [this, hero = heroInst[0]](const CArtPlace & artPlace, const Point & cursorPosition){showQuickBackpackWindow(hero, artPlace.slot, cursorPosition);};
  79. artifs[0]->setHero(heroInst[0]);
  80. artifs[1] = std::make_shared<CArtifactsOfHeroMain>(Point(98, 151));
  81. artifs[1]->clickPressedCallback = [this, hero = heroInst[1]](const CArtPlace & artPlace, const Point & cursorPosition){clickPressedOnArtPlace(hero, artPlace.slot, true, false, false, cursorPosition);};
  82. artifs[1]->showPopupCallback = [this, heroArts = artifs[1]](CArtPlace & artPlace, const Point & cursorPosition){showArtifactPopup(*heroArts, artPlace, cursorPosition);};
  83. artifs[1]->gestureCallback = [this, hero = heroInst[1]](const CArtPlace & artPlace, const Point & cursorPosition){showQuickBackpackWindow(hero, artPlace.slot, cursorPosition);};
  84. artifs[1]->setHero(heroInst[1]);
  85. addSet(artifs[0]);
  86. addSet(artifs[1]);
  87. for(int g=0; g<4; ++g)
  88. {
  89. primSkillAreas.push_back(std::make_shared<LRClickableAreaWTextComp>());
  90. if (qeLayout)
  91. primSkillAreas[g]->pos = Rect(Point(pos.x + 324, pos.y + 12 + 26 * g), Point(152, 22));
  92. else
  93. primSkillAreas[g]->pos = Rect(Point(pos.x + 329, pos.y + 19 + 36 * g), Point(140, 32));
  94. primSkillAreas[g]->text = LIBRARY->generaltexth->arraytxt[2+g];
  95. primSkillAreas[g]->component = Component( ComponentType::PRIM_SKILL, PrimarySkill(g));
  96. primSkillAreas[g]->hoverText = LIBRARY->generaltexth->heroscrn[1];
  97. boost::replace_first(primSkillAreas[g]->hoverText, "%s", LIBRARY->generaltexth->primarySkillNames[g]);
  98. }
  99. //heroes related thing
  100. for(int b=0; b < heroInst.size(); b++)
  101. {
  102. const CGHeroInstance * hero = heroInst.at(b);
  103. heroAreas[b] = std::make_shared<CHeroArea>(257 + 228 * b + (qeLayout ? 1 : 0), qeLayout ? 10 : 13, hero);
  104. heroAreas[b]->addClickCallback([this, hero]() -> void
  105. {
  106. if(getPickedArtifact() == nullptr)
  107. GAME->interface()->openHeroWindow(hero);
  108. });
  109. specialtyAreas[b] = std::make_shared<LRClickableAreaWText>();
  110. specialtyAreas[b]->pos = Rect(Point(pos.x + 69 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32));
  111. specialtyAreas[b]->hoverText = LIBRARY->generaltexth->heroscrn[27];
  112. specialtyAreas[b]->text = hero->getHeroType()->getSpecialtyDescriptionTranslated();
  113. experienceAreas[b] = std::make_shared<LRClickableAreaWText>();
  114. experienceAreas[b]->pos = Rect(Point(pos.x + 105 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32));
  115. experienceAreas[b]->hoverText = LIBRARY->generaltexth->heroscrn[9];
  116. experienceAreas[b]->text = LIBRARY->generaltexth->allTexts[2];
  117. boost::algorithm::replace_first(experienceAreas[b]->text, "%d", std::to_string(hero->level));
  118. boost::algorithm::replace_first(experienceAreas[b]->text, "%d", std::to_string(LIBRARY->heroh->reqExp(hero->level+1)));
  119. boost::algorithm::replace_first(experienceAreas[b]->text, "%d", std::to_string(hero->exp));
  120. spellPointsAreas[b] = std::make_shared<LRClickableAreaWText>();
  121. spellPointsAreas[b]->pos = Rect(Point(pos.x + 141 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32));
  122. spellPointsAreas[b]->hoverText = LIBRARY->generaltexth->heroscrn[22];
  123. spellPointsAreas[b]->text = LIBRARY->generaltexth->allTexts[205];
  124. boost::algorithm::replace_first(spellPointsAreas[b]->text, "%s", hero->getNameTranslated());
  125. boost::algorithm::replace_first(spellPointsAreas[b]->text, "%d", std::to_string(hero->mana));
  126. boost::algorithm::replace_first(spellPointsAreas[b]->text, "%d", std::to_string(hero->manaLimit()));
  127. morale[b] = std::make_shared<MoraleLuckBox>(true, Rect(Point(176 + 490 * b, 39), Point(32, 32)), true);
  128. luck[b] = std::make_shared<MoraleLuckBox>(false, Rect(Point(212 + 490 * b, 39), Point(32, 32)), true);
  129. }
  130. quit = std::make_shared<CButton>(Point(732, 567), AnimationPath::builtin("IOKAY.DEF"), LIBRARY->generaltexth->zelp[600], std::bind(&CExchangeWindow::close, this), EShortcut::GLOBAL_ACCEPT);
  131. if(queryID.getNum() > 0)
  132. quit->addCallback([=](){ GAME->interface()->cb->selectionMade(0, queryID); });
  133. questlogButton[0] = std::make_shared<CButton>(Point( qeLayout ? 8 : 10, qeLayout ? 39 : 44), AnimationPath::builtin("hsbtns4.def"), CButton::tooltip(LIBRARY->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questLogShortcut, this));
  134. questlogButton[1] = std::make_shared<CButton>(Point(740, qeLayout ? 39 : 44), AnimationPath::builtin("hsbtns4.def"), CButton::tooltip(LIBRARY->generaltexth->heroscrn[0]), std::bind(&CExchangeWindow::questLogShortcut, this));
  135. Rect barRect(5, 578, 725, 18);
  136. statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), barRect, 5, 578));
  137. //garrison interface
  138. garr = std::make_shared<CGarrisonInt>(Point(69, qeLayout ? 120 : 131), 4, Point(418,0), heroInst[0], heroInst[1], true, true);
  139. auto splitButtonCallback = [&](){ garr->splitClick(); };
  140. garr->addSplitBtn(std::make_shared<CButton>( Point( 10, qeLayout ? 122 : 132), AnimationPath::builtin("TSBTNS.DEF"), CButton::tooltip(LIBRARY->generaltexth->tcommands[3]), splitButtonCallback, EShortcut::HERO_ARMY_SPLIT));
  141. garr->addSplitBtn(std::make_shared<CButton>( Point(744, qeLayout ? 122 : 132), AnimationPath::builtin("TSBTNS.DEF"), CButton::tooltip(LIBRARY->generaltexth->tcommands[3]), splitButtonCallback, EShortcut::HERO_ARMY_SPLIT));
  142. if(qeLayout)
  143. {
  144. buttonMoveUnitsFromLeftToRight = std::make_shared<CButton>(
  145. Point(325, 118),
  146. AnimationPath::builtin("quick-exchange/armRight.DEF"),
  147. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.moveAllUnits")),
  148. [this](){ this->moveUnitsShortcut(true); });
  149. buttonMoveUnitsFromRightToLeft = std::make_shared<CButton>(
  150. Point(425, 118),
  151. AnimationPath::builtin("quick-exchange/armLeft.DEF"),
  152. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.moveAllUnits")),
  153. [this](){ this->moveUnitsShortcut(false); });
  154. buttonMoveArtifactsFromLeftToRight = std::make_shared<CButton>(
  155. Point(325, 154), AnimationPath::builtin("quick-exchange/artRight.DEF"),
  156. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.moveAllArtifacts")),
  157. [this](){ this->moveArtifactsCallback(true);});
  158. buttonMoveArtifactsFromRightToLeft = std::make_shared<CButton>(
  159. Point(425, 154), AnimationPath::builtin("quick-exchange/artLeft.DEF"),
  160. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.moveAllArtifacts")),
  161. [this](){ this->moveArtifactsCallback(false);});
  162. exchangeUnitsButton = std::make_shared<CButton>(
  163. Point(377, 118),
  164. AnimationPath::builtin("quick-exchange/swapAll.DEF"),
  165. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.swapAllUnits")),
  166. [this](){ controller.swapArmy(); });
  167. exchangeArtifactsButton = std::make_shared<CButton>(
  168. Point(377, 154),
  169. AnimationPath::builtin("quick-exchange/swapAll.DEF"),
  170. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.swapAllArtifacts")),
  171. [this](){ this->swapArtifactsCallback(); });
  172. backpackButtonLeft = std::make_shared<CButton>(
  173. Point(325, 518),
  174. AnimationPath::builtin("heroBackpack"),
  175. CButton::tooltipLocalized("vcmi.heroWindow.openBackpack"),
  176. [this](){ this->backpackShortcut(true); });
  177. backpackButtonRight = std::make_shared<CButton>(
  178. Point(419, 518),
  179. AnimationPath::builtin("heroBackpack"),
  180. CButton::tooltipLocalized("vcmi.heroWindow.openBackpack"),
  181. [this](){ this->backpackShortcut(false); });
  182. backpackButtonLeft->setOverlay(std::make_shared<CPicture>(ImagePath::builtin("heroWindow/backpackButtonIcon")));
  183. backpackButtonRight->setOverlay(std::make_shared<CPicture>(ImagePath::builtin("heroWindow/backpackButtonIcon")));
  184. auto leftHeroBlock = heroInst[0]->tempOwner != GAME->interface()->cb->getPlayerID();
  185. auto rightHeroBlock = heroInst[1]->tempOwner != GAME->interface()->cb->getPlayerID();
  186. buttonMoveUnitsFromLeftToRight->block(leftHeroBlock);
  187. buttonMoveUnitsFromRightToLeft->block(rightHeroBlock);
  188. buttonMoveArtifactsFromLeftToRight->block(leftHeroBlock);
  189. buttonMoveArtifactsFromRightToLeft->block(rightHeroBlock);
  190. exchangeUnitsButton->block(leftHeroBlock || rightHeroBlock);
  191. exchangeArtifactsButton->block(leftHeroBlock || rightHeroBlock);
  192. backpackButtonLeft->block(leftHeroBlock);
  193. backpackButtonRight->block(rightHeroBlock);
  194. for(int i = 0; i < GameConstants::ARMY_SIZE; i++)
  195. {
  196. moveUnitFromRightToLeftButtons.push_back(
  197. std::make_shared<CButton>(
  198. Point(483 + 36 * i, 155),
  199. AnimationPath::builtin("quick-exchange/unitLeft.DEF"),
  200. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.moveUnit")),
  201. [this, i]() { creatureArrowButtonCallback(false, SlotID(i)); }));
  202. moveUnitFromRightToLeftButtons.back()->block(leftHeroBlock);
  203. moveUnitFromLeftToRightButtons.push_back(
  204. std::make_shared<CButton>(
  205. Point(65 + 36 * i, 155),
  206. AnimationPath::builtin("quick-exchange/unitRight.DEF"),
  207. CButton::tooltip(LIBRARY->generaltexth->translate("vcmi.quickExchange.moveUnit")),
  208. [this, i]() { creatureArrowButtonCallback(true, SlotID(i)); }));
  209. moveUnitFromLeftToRightButtons.back()->block(rightHeroBlock);
  210. }
  211. }
  212. CExchangeWindow::updateArtifacts();
  213. }
  214. void CExchangeWindow::creatureArrowButtonCallback(bool leftToRight, SlotID slotId)
  215. {
  216. if (ENGINE->isKeyboardAltDown())
  217. controller.moveArmy(leftToRight, slotId);
  218. else if (ENGINE->isKeyboardCtrlDown())
  219. controller.moveSingleStackCreature(leftToRight, slotId, true);
  220. else if (ENGINE->isKeyboardShiftDown())
  221. controller.moveSingleStackCreature(leftToRight, slotId, false);
  222. else
  223. controller.moveStack(leftToRight, slotId);
  224. }
  225. void CExchangeWindow::moveArtifactsCallback(bool leftToRight)
  226. {
  227. bool moveEquipped = !ENGINE->isKeyboardShiftDown();
  228. bool moveBackpack = !ENGINE->isKeyboardCmdDown();
  229. controller.moveArtifacts(leftToRight, moveEquipped, moveBackpack);
  230. };
  231. void CExchangeWindow::swapArtifactsCallback()
  232. {
  233. bool moveEquipped = !ENGINE->isKeyboardShiftDown();
  234. bool moveBackpack = !ENGINE->isKeyboardCmdDown();
  235. controller.swapArtifacts(moveEquipped, moveBackpack);
  236. }
  237. void CExchangeWindow::moveUnitsShortcut(bool leftToRight)
  238. {
  239. std::optional<SlotID> slotId = std::nullopt;
  240. if(const auto * slot = getSelectedSlotID())
  241. slotId = slot->getSlot();
  242. controller.moveArmy(leftToRight, slotId);
  243. };
  244. void CExchangeWindow::backpackShortcut(bool leftHero)
  245. {
  246. ENGINE->windows().createAndPushWindow<CHeroBackpackWindow>(heroInst[leftHero ? 0 : 1], artSets);
  247. };
  248. void CExchangeWindow::keyPressed(EShortcut key)
  249. {
  250. switch (key)
  251. {
  252. case EShortcut::EXCHANGE_ARMY_TO_LEFT:
  253. moveUnitsShortcut(false);
  254. break;
  255. case EShortcut::EXCHANGE_ARMY_TO_RIGHT:
  256. moveUnitsShortcut(true);
  257. break;
  258. case EShortcut::EXCHANGE_ARMY_SWAP:
  259. controller.swapArmy();
  260. break;
  261. case EShortcut::EXCHANGE_ARTIFACTS_TO_LEFT:
  262. controller.moveArtifacts(false, true, true);
  263. break;
  264. case EShortcut::EXCHANGE_ARTIFACTS_TO_RIGHT:
  265. controller.moveArtifacts(true, true, true);
  266. break;
  267. case EShortcut::EXCHANGE_ARTIFACTS_SWAP:
  268. controller.swapArtifacts(true, true);
  269. break;
  270. case EShortcut::EXCHANGE_EQUIPPED_TO_LEFT:
  271. controller.moveArtifacts(false, true, false);
  272. break;
  273. case EShortcut::EXCHANGE_EQUIPPED_TO_RIGHT:
  274. controller.moveArtifacts(true, true, false);
  275. break;
  276. case EShortcut::EXCHANGE_EQUIPPED_SWAP:
  277. controller.swapArtifacts(true, false);
  278. break;
  279. case EShortcut::EXCHANGE_BACKPACK_TO_LEFT:
  280. controller.moveArtifacts(false, false, true);
  281. break;
  282. case EShortcut::EXCHANGE_BACKPACK_TO_RIGHT:
  283. controller.moveArtifacts(true, false, true);
  284. break;
  285. case EShortcut::EXCHANGE_BACKPACK_SWAP:
  286. controller.swapArtifacts(false, true);
  287. break;
  288. case EShortcut::EXCHANGE_BACKPACK_LEFT:
  289. backpackShortcut(true);
  290. break;
  291. case EShortcut::EXCHANGE_BACKPACK_RIGHT:
  292. backpackShortcut(false);
  293. break;
  294. }
  295. }
  296. const CGarrisonSlot * CExchangeWindow::getSelectedSlotID() const
  297. {
  298. return garr->getSelection();
  299. }
  300. void CExchangeWindow::updateGarrisons()
  301. {
  302. garr->recreateSlots();
  303. updateArtifacts();
  304. }
  305. bool CExchangeWindow::holdsGarrison(const CArmedInstance * army)
  306. {
  307. return garr->upperArmy() == army || garr->lowerArmy() == army;
  308. }
  309. void CExchangeWindow::questLogShortcut()
  310. {
  311. ENGINE->cursor().dragAndDropCursor(nullptr);
  312. GAME->interface()->showQuestLog();
  313. }
  314. void CExchangeWindow::updateArtifacts()
  315. {
  316. const bool qeLayout = isQuickExchangeLayoutAvailable();
  317. OBJECT_CONSTRUCTION;
  318. CWindowWithArtifacts::updateArtifacts();
  319. for(size_t leftRight : {0, 1})
  320. {
  321. const CGHeroInstance * hero = heroInst.at(leftRight);
  322. for(int m=0; m<GameConstants::PRIMARY_SKILLS; ++m)
  323. {
  324. auto value = heroInst[leftRight]->getPrimSkillLevel(static_cast<PrimarySkill>(m));
  325. primSkillValues[leftRight][m]->setText(std::to_string(value));
  326. }
  327. int slots = 8;
  328. bool isMoreSkillsThanSlots = hero->secSkills.size() > slots;
  329. for(int m=0; m < std::min(static_cast<int>(hero->secSkills.size()), 8); ++m)
  330. {
  331. if(m == slots - 1)
  332. {
  333. if(isMoreSkillsThanSlots)
  334. {
  335. Rect r(Point(32 + 36 * m + 454 * leftRight, qeLayout ? 83 : 88), Point(34, 28));
  336. secSkillsFull[leftRight] = std::make_shared<CMultiLineLabel>(r, EFonts::FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, "...");
  337. secSkillsFullArea[leftRight] = std::make_shared<LRClickableAreaWText>(r, LIBRARY->generaltexth->translate("vcmi.kingdomOverview.secSkillOverflow.hover"), LIBRARY->generaltexth->translate("vcmi.kingdomOverview.secSkillOverflow.help"));
  338. secSkills[leftRight][m]->setSkill(SecondarySkill::NONE);
  339. continue;
  340. }
  341. else
  342. {
  343. secSkillsFull[leftRight].reset();
  344. secSkillsFullArea[leftRight].reset();
  345. }
  346. }
  347. int id = hero->secSkills[m].first;
  348. int level = hero->secSkills[m].second;
  349. secSkills[leftRight][m]->setSkill(id, level);
  350. }
  351. expValues[leftRight]->setText(TextOperations::formatMetric(hero->exp, 3));
  352. manaValues[leftRight]->setText(TextOperations::formatMetric(hero->mana, 3));
  353. morale[leftRight]->set(hero);
  354. luck[leftRight]->set(hero);
  355. }
  356. }