StackInfoBasicPanel.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * StackInfoBasicPanel.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 "StackInfoBasicPanel.h"
  12. #include "../widgets/Images.h"
  13. #include "../widgets/TextControls.h"
  14. #include "../../lib/CConfigHandler.h"
  15. #include "../../lib/CStack.h"
  16. #include "../../lib/GameLibrary.h"
  17. #include "../../lib/spells/CSpellHandler.h"
  18. #include "../../lib/texts/CGeneralTextHandler.h"
  19. #include "../../lib/texts/TextOperations.h"
  20. StackInfoBasicPanel::StackInfoBasicPanel(const CStack * stack, bool initializeBackground)
  21. : CIntObject(0)
  22. {
  23. OBJECT_CONSTRUCTION;
  24. if(initializeBackground)
  25. {
  26. background = std::make_shared<CPicture>(ImagePath::builtin("CCRPOP"));
  27. background->pos.y += 37;
  28. background->setPlayerColor(stack->getOwner());
  29. background2 = std::make_shared<CPicture>(ImagePath::builtin("CHRPOP"));
  30. background2->setPlayerColor(stack->getOwner());
  31. }
  32. initializeData(stack);
  33. }
  34. void StackInfoBasicPanel::initializeData(const CStack * stack)
  35. {
  36. OBJECT_CONSTRUCTION;
  37. icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("TWCRPORT"), stack->creatureId().getNum() + 2, 0, 10, 6));
  38. labels.push_back(std::make_shared<CLabel>(10 + 58, 6 + 64, FONT_MEDIUM, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, TextOperations::formatMetric(stack->getCount(), 4)));
  39. int damageMultiplier = 1;
  40. if (stack->hasBonusOfType(BonusType::SIEGE_WEAPON))
  41. {
  42. static const auto bonusSelector =
  43. Selector::sourceTypeSel(BonusSource::ARTIFACT).Or(
  44. Selector::sourceTypeSel(BonusSource::HERO_BASE_SKILL)).And(
  45. Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK)));
  46. damageMultiplier += stack->valOfBonuses(bonusSelector);
  47. }
  48. auto attack = std::to_string(LIBRARY->creatures()->getByIndex(stack->creatureIndex())->getAttack(stack->isShooter())) + "(" + std::to_string(stack->getAttack(stack->isShooter())) + ")";
  49. auto defense = std::to_string(LIBRARY->creatures()->getByIndex(stack->creatureIndex())->getDefense(stack->isShooter())) + "(" + std::to_string(stack->getDefense(stack->isShooter())) + ")";
  50. auto damage = std::to_string(damageMultiplier * stack->getMinDamage(stack->isShooter())) + "-" + std::to_string(damageMultiplier * stack->getMaxDamage(stack->isShooter()));
  51. auto health = stack->getMaxHealth();
  52. auto morale = stack->moraleVal();
  53. auto luck = stack->luckVal();
  54. auto killed = stack->getKilled();
  55. auto healthRemaining = TextOperations::formatMetric(std::max<int64_t>(stack->getAvailableHealth() - static_cast<int64_t>(stack->getCount() - 1) * health, 0), 4);
  56. //primary stats*/
  57. labels.push_back(std::make_shared<CLabel>(9, 75, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[380] + ":"));
  58. labels.push_back(std::make_shared<CLabel>(9, 87, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[381] + ":"));
  59. labels.push_back(std::make_shared<CLabel>(9, 99, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[386] + ":"));
  60. labels.push_back(std::make_shared<CLabel>(9, 111, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[389] + ":"));
  61. labels.push_back(std::make_shared<CLabel>(69, 87, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, attack));
  62. labels.push_back(std::make_shared<CLabel>(69, 99, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, defense));
  63. labels.push_back(std::make_shared<CLabel>(69, 111, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, damage));
  64. labels.push_back(std::make_shared<CLabel>(69, 123, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(health)));
  65. //morale+luck
  66. labels.push_back(std::make_shared<CLabel>(9, 131, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[384] + ":"));
  67. labels.push_back(std::make_shared<CLabel>(9, 143, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[385] + ":"));
  68. icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("IMRL22"), std::clamp(morale + 3, 0, 6), 0, 47, 131));
  69. icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("ILCK22"), std::clamp(luck + 3, 0, 6), 0, 47, 143));
  70. //extra information
  71. labels.push_back(std::make_shared<CLabel>(9, 168, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->translate("vcmi.battleWindow.killed") + ":"));
  72. labels.push_back(std::make_shared<CLabel>(9, 180, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, LIBRARY->generaltexth->allTexts[389] + ":"));
  73. labels.push_back(std::make_shared<CLabel>(69, 180, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(killed)));
  74. labels.push_back(std::make_shared<CLabel>(69, 192, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, healthRemaining));
  75. //spells
  76. static const Point firstPos(15, 206); // position of 1st spell box
  77. static const Point offset(0, 38); // offset of each spell box from previous
  78. for(int i = 0; i < 3; i++)
  79. icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), 78, 0, firstPos.x + offset.x * i, firstPos.y + offset.y * i));
  80. int printed=0; //how many effect pics have been printed
  81. std::vector<SpellID> spells = stack->activeSpells();
  82. for(SpellID effect : spells)
  83. {
  84. //not all effects have graphics (for eg. Acid Breath)
  85. //for modded spells iconEffect is added to SpellInt.def
  86. const bool hasGraphics = (effect < SpellID::THUNDERBOLT) || (effect >= SpellID::AFTER_LAST);
  87. if (hasGraphics)
  88. {
  89. //FIXME: support permanent duration
  90. auto spellBonuses = stack->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)));
  91. if (spellBonuses->empty())
  92. throw std::runtime_error("Failed to find effects for spell " + effect.toSpell()->getJsonKey());
  93. int duration = spellBonuses->front()->turnsRemain;
  94. icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect.getNum() + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed));
  95. if(settings["general"]["enableUiEnhancements"].Bool())
  96. labels.push_back(std::make_shared<CLabel>(firstPos.x + offset.x * printed + 46, firstPos.y + offset.y * printed + 36, EFonts::FONT_TINY, ETextAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(duration)));
  97. ++printed;
  98. if(printed >= 3 || (printed == 2 && spells.size() > 3)) // interface limit reached
  99. break;
  100. }
  101. }
  102. if(spells.empty())
  103. labelsMultiline.push_back(std::make_shared<CMultiLineLabel>(Rect(firstPos.x, firstPos.y, 48, 36), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->allTexts[674]));
  104. if(spells.size() > 3)
  105. labelsMultiline.push_back(std::make_shared<CMultiLineLabel>(Rect(firstPos.x + offset.x * 2, firstPos.y + offset.y * 2 - 4, 48, 36), EFonts::FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, "..."));
  106. }
  107. void StackInfoBasicPanel::update(const CStack * updatedInfo)
  108. {
  109. icons.clear();
  110. labels.clear();
  111. labelsMultiline.clear();
  112. initializeData(updatedInfo);
  113. }
  114. void StackInfoBasicPanel::show(Canvas & to)
  115. {
  116. showAll(to);
  117. CIntObject::show(to);
  118. }