ArtifactsUIController.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * ArtifactsUIController.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 "ArtifactsUIController.h"
  12. #include "CPlayerInterface.h"
  13. #include "GameEngine.h"
  14. #include "GameInstance.h"
  15. #include "gui/WindowHandler.h"
  16. #include "widgets/CComponent.h"
  17. #include "windows/CWindowWithArtifacts.h"
  18. #include "../lib/GameLibrary.h"
  19. #include "../lib/callback/CCallback.h"
  20. #include "../lib/entities/artifact/ArtifactUtils.h"
  21. #include "../lib/entities/artifact/CArtifact.h"
  22. #include "../lib/mapObjects/CGHeroInstance.h"
  23. #include "../lib/texts/CGeneralTextHandler.h"
  24. ArtifactsUIController::ArtifactsUIController()
  25. {
  26. numOfMovedArts = 0;
  27. numOfArtsAskAssembleSession = 0;
  28. }
  29. bool ArtifactsUIController::askToAssemble(const ArtifactLocation & al, const bool onlyEquipped, const bool checkIgnored)
  30. {
  31. if(auto hero = GAME->interface()->cb->getHero(al.artHolder))
  32. {
  33. if(hero->getArt(al.slot) == nullptr)
  34. {
  35. logGlobal->error("artifact location %d points to nothing", al.slot.num);
  36. return false;
  37. }
  38. return askToAssemble(hero, al.slot, onlyEquipped, checkIgnored);
  39. }
  40. return false;
  41. }
  42. bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot,
  43. const bool onlyEquipped, const bool checkIgnored)
  44. {
  45. assert(hero);
  46. const auto art = hero->getArt(slot);
  47. assert(art);
  48. if(hero->tempOwner != GAME->interface()->playerID)
  49. return false;
  50. if(numOfArtsAskAssembleSession != 0)
  51. numOfArtsAskAssembleSession--;
  52. auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), onlyEquipped);
  53. if(!assemblyPossibilities.empty())
  54. {
  55. auto askThread = new std::thread([this, hero, slot, assemblyPossibilities, checkIgnored]() -> void
  56. {
  57. std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
  58. for(const auto combinedArt : assemblyPossibilities)
  59. {
  60. if(checkIgnored)
  61. {
  62. if(vstd::contains(ignoredArtifacts, combinedArt->getId()))
  63. continue;
  64. ignoredArtifacts.emplace(combinedArt->getId());
  65. }
  66. bool assembleConfirmed = false;
  67. MetaString message = MetaString::createFromTextID(combinedArt->getDescriptionTextID());
  68. message.appendEOL();
  69. message.appendEOL();
  70. if(combinedArt->isFused())
  71. message.appendRawString(LIBRARY->generaltexth->translate("vcmi.heroWindow.fusingArtifact.fusing"));
  72. else
  73. message.appendRawString(LIBRARY->generaltexth->allTexts[732]); // You possess all of the components needed to assemble the
  74. message.replaceName(ArtifactID(combinedArt->getId()));
  75. GAME->interface()->showYesNoDialog(message.toString(), [&assembleConfirmed, hero, slot, combinedArt]()
  76. {
  77. assembleConfirmed = true;
  78. GAME->interface()->cb->assembleArtifacts(hero->id, slot, true, combinedArt->getId());
  79. }, nullptr, {std::make_shared<CComponent>(ComponentType::ARTIFACT, combinedArt->getId())});
  80. GAME->interface()->waitWhileDialog();
  81. if(assembleConfirmed)
  82. break;
  83. }
  84. });
  85. askThread->detach();
  86. return true;
  87. }
  88. return false;
  89. }
  90. bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
  91. {
  92. assert(hero);
  93. const auto art = hero->getArt(slot);
  94. assert(art);
  95. if(hero->tempOwner != GAME->interface()->playerID)
  96. return false;
  97. if(art->hasParts())
  98. {
  99. if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->getType()->getConstituents().size() - 1))
  100. return false;
  101. MetaString message = MetaString::createFromTextID(art->getType()->getDescriptionTextID());
  102. message.appendEOL();
  103. message.appendEOL();
  104. message.appendRawString(LIBRARY->generaltexth->allTexts[733]); // Do you wish to disassemble this artifact?
  105. GAME->interface()->showYesNoDialog(message.toString(), [hero, slot]()
  106. {
  107. GAME->interface()->cb->assembleArtifacts(hero->id, slot, false, ArtifactID());
  108. }, nullptr);
  109. return true;
  110. }
  111. return false;
  112. }
  113. void ArtifactsUIController::artifactRemoved()
  114. {
  115. for(const auto & artWin : ENGINE->windows().findWindows<IArtifactsHolder>())
  116. artWin->updateArtifacts();
  117. GAME->interface()->waitWhileDialog();
  118. }
  119. void ArtifactsUIController::artifactMoved()
  120. {
  121. // If a bulk transfer has arrived, then redrawing only the last art movement.
  122. if(numOfMovedArts != 0)
  123. numOfMovedArts--;
  124. if(numOfMovedArts == 0)
  125. {
  126. for(const auto & artWin : ENGINE->windows().findWindows<IArtifactsHolder>())
  127. artWin->updateArtifacts();
  128. }
  129. GAME->interface()->waitWhileDialog();
  130. }
  131. void ArtifactsUIController::bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts)
  132. {
  133. assert(totalNumOfArts >= possibleAssemblyNumOfArts);
  134. numOfMovedArts = totalNumOfArts;
  135. if(numOfArtsAskAssembleSession == 0)
  136. {
  137. // Do not start the next session until the previous one is finished
  138. numOfArtsAskAssembleSession = possibleAssemblyNumOfArts;
  139. ignoredArtifacts.clear();
  140. }
  141. }
  142. void ArtifactsUIController::artifactAssembled()
  143. {
  144. for(const auto & artWin : ENGINE->windows().findWindows<IArtifactsHolder>())
  145. artWin->updateArtifacts();
  146. }
  147. void ArtifactsUIController::artifactDisassembled()
  148. {
  149. for(const auto & artWin : ENGINE->windows().findWindows<IArtifactsHolder>())
  150. artWin->updateArtifacts();
  151. }