CArtifactHolder.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * CArtifactHolder.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 "CArtifactHolder.h"
  12. #include "../gui/CGuiHandler.h"
  13. #include "../gui/Shortcut.h"
  14. #include "CComponent.h"
  15. #include "../windows/GUIClasses.h"
  16. #include "../render/Canvas.h"
  17. #include "../render/Colors.h"
  18. #include "../render/IRenderHandler.h"
  19. #include "../CPlayerInterface.h"
  20. #include "../CGameInfo.h"
  21. #include "../../CCallback.h"
  22. #include "../../lib/CGeneralTextHandler.h"
  23. #include "../../lib/ArtifactUtils.h"
  24. #include "../../lib/mapObjects/CGHeroInstance.h"
  25. #include "../../lib/CConfigHandler.h"
  26. void CArtPlace::setInternals(const CArtifactInstance * artInst)
  27. {
  28. baseType = -1; // By default we don't store any component
  29. ourArt = artInst;
  30. if(!artInst)
  31. {
  32. image->disable();
  33. imageSpell->disable();
  34. text.clear();
  35. hoverText = CGI->generaltexth->allTexts[507];
  36. return;
  37. }
  38. image->enable();
  39. imageSpell->disable();
  40. image->setFrame(artInst->artType->getIconIndex());
  41. if(artInst->getTypeId() == ArtifactID::SPELL_SCROLL)
  42. {
  43. auto spellID = artInst->getScrollSpellID();
  44. if(spellID.num >= 0)
  45. {
  46. // Add spell component info (used to provide a pic in r-click popup)
  47. baseType = CComponent::spell;
  48. type = spellID;
  49. bonusValue = 0;
  50. if(settings["general"]["enableUiEnhancements"].Bool())
  51. {
  52. imageSpell->enable();
  53. image->disable();
  54. imageSpell->setFrame(spellID.num);
  55. }
  56. }
  57. }
  58. else
  59. {
  60. baseType = CComponent::artifact;
  61. type = artInst->getTypeId();
  62. bonusValue = 0;
  63. }
  64. text = artInst->getDescription();
  65. }
  66. CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art)
  67. : ourArt(Art)
  68. {
  69. image = nullptr;
  70. pos += position;
  71. pos.w = pos.h = 44;
  72. }
  73. const CArtifactInstance * CArtPlace::getArt()
  74. {
  75. return ourArt;
  76. }
  77. CCommanderArtPlace::CCommanderArtPlace(Point position, const CGHeroInstance * commanderOwner, ArtifactPosition artSlot, const CArtifactInstance * Art)
  78. : CArtPlace(position, Art),
  79. commanderOwner(commanderOwner),
  80. commanderSlotID(artSlot.num)
  81. {
  82. createImage();
  83. setArtifact(Art);
  84. }
  85. void CCommanderArtPlace::createImage()
  86. {
  87. OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
  88. int imageIndex = 0;
  89. if(ourArt)
  90. imageIndex = ourArt->artType->getIconIndex();
  91. image = std::make_shared<CAnimImage>(AnimationPath::builtin("artifact"), imageIndex);
  92. if(!ourArt)
  93. image->disable();
  94. }
  95. void CCommanderArtPlace::returnArtToHeroCallback()
  96. {
  97. ArtifactPosition artifactPos = commanderSlotID;
  98. ArtifactPosition freeSlot = ArtifactUtils::getArtBackpackPosition(commanderOwner, ourArt->getTypeId());
  99. if(freeSlot == ArtifactPosition::PRE_FIRST)
  100. {
  101. LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152"));
  102. }
  103. else
  104. {
  105. ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
  106. ArtifactLocation dst(commanderOwner, freeSlot);
  107. if(ourArt->canBePutAt(dst, true))
  108. {
  109. LOCPLINT->cb->swapArtifacts(src, dst);
  110. setArtifact(nullptr);
  111. parent->redraw();
  112. }
  113. }
  114. }
  115. void CCommanderArtPlace::clickPressed(const Point & cursorPosition)
  116. {
  117. if(ourArt && text.size())
  118. LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this]() { returnArtToHeroCallback(); }, []() {});
  119. }
  120. void CCommanderArtPlace::showPopupWindow(const Point & cursorPosition)
  121. {
  122. if(ourArt && text.size())
  123. CArtPlace::showPopupWindow(cursorPosition);
  124. }
  125. void CCommanderArtPlace::setArtifact(const CArtifactInstance * art)
  126. {
  127. setInternals(art);
  128. }
  129. CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art)
  130. : CArtPlace(position, Art),
  131. locked(false),
  132. marked(false)
  133. {
  134. createImage();
  135. }
  136. void CHeroArtPlace::lockSlot(bool on)
  137. {
  138. if(locked == on)
  139. return;
  140. locked = on;
  141. if(on)
  142. image->setFrame(ArtifactID::ART_LOCK);
  143. else if(ourArt)
  144. image->setFrame(ourArt->artType->getIconIndex());
  145. else
  146. image->setFrame(0);
  147. }
  148. bool CHeroArtPlace::isLocked()
  149. {
  150. return locked;
  151. }
  152. void CHeroArtPlace::selectSlot(bool on)
  153. {
  154. if(marked == on)
  155. return;
  156. marked = on;
  157. if(on)
  158. selection->enable();
  159. else
  160. selection->disable();
  161. }
  162. bool CHeroArtPlace::isMarked() const
  163. {
  164. return marked;
  165. }
  166. void CHeroArtPlace::clickPressed(const Point & cursorPosition)
  167. {
  168. if(leftClickCallback)
  169. leftClickCallback(*this);
  170. }
  171. void CHeroArtPlace::showPopupWindow(const Point & cursorPosition)
  172. {
  173. if(showPopupCallback)
  174. showPopupCallback(*this);
  175. }
  176. void CHeroArtPlace::showAll(Canvas & to)
  177. {
  178. if(ourArt)
  179. {
  180. CIntObject::showAll(to);
  181. }
  182. if(marked && isActive())
  183. to.drawBorder(pos, Colors::BRIGHT_YELLOW);
  184. }
  185. void CHeroArtPlace::setArtifact(const CArtifactInstance * art)
  186. {
  187. setInternals(art);
  188. if(art)
  189. {
  190. image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->getIconIndex());
  191. if(locked) // Locks should appear as empty.
  192. hoverText = CGI->generaltexth->allTexts[507];
  193. else
  194. hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->getNameTranslated());
  195. }
  196. else
  197. {
  198. lockSlot(false);
  199. }
  200. }
  201. void CHeroArtPlace::addCombinedArtInfo(std::map<const CArtifact*, int> & arts)
  202. {
  203. for(const auto & combinedArt : arts)
  204. {
  205. std::string artList;
  206. text += "\n\n";
  207. text += "{" + combinedArt.first->getNameTranslated() + "}";
  208. if(arts.size() == 1)
  209. {
  210. for(const auto part : combinedArt.first->getConstituents())
  211. artList += "\n" + part->getNameTranslated();
  212. }
  213. text += " (" + boost::str(boost::format("%d") % combinedArt.second) + " / " +
  214. boost::str(boost::format("%d") % combinedArt.first->getConstituents().size()) + ")" + artList;
  215. }
  216. }
  217. void CHeroArtPlace::createImage()
  218. {
  219. OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
  220. si32 imageIndex = 0;
  221. if(locked)
  222. imageIndex = ArtifactID::ART_LOCK;
  223. else if(ourArt)
  224. imageIndex = ourArt->artType->getIconIndex();
  225. imageSpell = std::make_shared<CAnimImage>(GH.renderHandler().loadAnimation(AnimationPath::builtin("spellscr")), 0, Rect(0, 5, 44, 34));
  226. image = std::make_shared<CAnimImage>(AnimationPath::builtin("artifact"), imageIndex);
  227. if(!ourArt)
  228. {
  229. image->disable();
  230. imageSpell->disable();
  231. }
  232. selection = std::make_shared<CAnimImage>(AnimationPath::builtin("artifact"), ArtifactID::ART_SELECTION);
  233. selection->disable();
  234. }
  235. bool ArtifactUtilsClient::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
  236. {
  237. assert(hero);
  238. const auto art = hero->getArt(slot);
  239. assert(art);
  240. if(hero->tempOwner != LOCPLINT->playerID)
  241. return false;
  242. auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), ArtifactUtils::isSlotEquipment(slot));
  243. if(!assemblyPossibilities.empty())
  244. {
  245. auto askThread = new boost::thread([hero, art, slot, assemblyPossibilities]() -> void
  246. {
  247. for(const auto combinedArt : assemblyPossibilities)
  248. {
  249. bool assembleConfirmed = false;
  250. CFunctionList<void()> onYesHandlers([&assembleConfirmed]() -> void {assembleConfirmed = true; });
  251. onYesHandlers += std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combinedArt->getId());
  252. LOCPLINT->showArtifactAssemblyDialog(art->artType, combinedArt, onYesHandlers);
  253. LOCPLINT->waitWhileDialog(false);
  254. if(assembleConfirmed)
  255. break;
  256. }
  257. });
  258. askThread->detach();
  259. return true;
  260. }
  261. return false;
  262. }
  263. bool ArtifactUtilsClient::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
  264. {
  265. assert(hero);
  266. const auto art = hero->getArt(slot);
  267. assert(art);
  268. if(hero->tempOwner != LOCPLINT->playerID)
  269. return false;
  270. if(art->isCombined())
  271. {
  272. if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1))
  273. return false;
  274. LOCPLINT->showArtifactAssemblyDialog(
  275. art->artType,
  276. nullptr,
  277. std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, false, ArtifactID()));
  278. return true;
  279. }
  280. return false;
  281. }