QuestArtifactPlacer.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * QuestArtifact.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 "QuestArtifactPlacer.h"
  12. #include "../CMapGenerator.h"
  13. #include "../RmgMap.h"
  14. #include "TreasurePlacer.h"
  15. #include "../CZonePlacer.h"
  16. #include "../../VCMI_Lib.h"
  17. #include "../../mapObjectConstructors/AObjectTypeHandler.h"
  18. #include "../../mapObjectConstructors/CObjectClassesHandler.h"
  19. #include "../../mapObjects/MapObjects.h"
  20. VCMI_LIB_NAMESPACE_BEGIN
  21. void QuestArtifactPlacer::process()
  22. {
  23. findZonesForQuestArts();
  24. placeQuestArtifacts(zone.getRand());
  25. }
  26. void QuestArtifactPlacer::init()
  27. {
  28. DEPENDENCY_ALL(TreasurePlacer);
  29. }
  30. void QuestArtifactPlacer::addQuestArtZone(std::shared_ptr<Zone> otherZone)
  31. {
  32. RecursiveLock lock(externalAccessMutex);
  33. questArtZones.push_back(otherZone);
  34. }
  35. void QuestArtifactPlacer::addQuestArtifact(const ArtifactID& id)
  36. {
  37. logGlobal->info("Need to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
  38. RecursiveLock lock(externalAccessMutex);
  39. questArtifactsToPlace.emplace_back(id);
  40. }
  41. void QuestArtifactPlacer::removeQuestArtifact(const ArtifactID& id)
  42. {
  43. logGlobal->info("Will not try to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
  44. RecursiveLock lock(externalAccessMutex);
  45. vstd::erase_if_present(questArtifactsToPlace, id);
  46. }
  47. void QuestArtifactPlacer::rememberPotentialArtifactToReplace(CGObjectInstance* obj)
  48. {
  49. RecursiveLock lock(externalAccessMutex);
  50. artifactsToReplace.push_back(obj);
  51. }
  52. std::vector<CGObjectInstance*> QuestArtifactPlacer::getPossibleArtifactsToReplace() const
  53. {
  54. RecursiveLock lock(externalAccessMutex);
  55. return artifactsToReplace;
  56. }
  57. void QuestArtifactPlacer::findZonesForQuestArts()
  58. {
  59. const auto& distances = generator.getZonePlacer()->getDistanceMap().at(zone.getId());
  60. for (auto const& connectedZone : distances)
  61. {
  62. // Choose zones that are 1 or 2 connections away
  63. if (vstd::iswithin(connectedZone.second, 1, 2))
  64. {
  65. addQuestArtZone(map.getZones().at(connectedZone.first));
  66. }
  67. }
  68. logGlobal->info("Number of nearby zones suitable for quest artifacts: %d", questArtZones.size());
  69. }
  70. void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator & rand)
  71. {
  72. for (const auto & artifactToPlace : questArtifactsToPlace)
  73. {
  74. RandomGeneratorUtil::randomShuffle(questArtZones, rand);
  75. for (auto zone : questArtZones)
  76. {
  77. auto* qap = zone->getModificator<QuestArtifactPlacer>();
  78. std::vector<CGObjectInstance *> artifactsToReplace = qap->getPossibleArtifactsToReplace();
  79. if (artifactsToReplace.empty())
  80. continue;
  81. auto artifactToReplace = *RandomGeneratorUtil::nextItem(artifactsToReplace, rand);
  82. logGlobal->info("Replacing %s at %s with the quest artifact %s",
  83. artifactToReplace->getObjectName(),
  84. artifactToReplace->getPosition().toString(),
  85. VLC->artifacts()->getById(artifactToPlace)->getNameTranslated());
  86. //Update appearance. Terrain is irrelevant.
  87. auto handler = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, artifactToPlace);
  88. auto newObj = handler->create();
  89. auto templates = handler->getTemplates();
  90. //artifactToReplace->appearance = templates.front();
  91. newObj->appearance = templates.front();
  92. newObj->pos = artifactToReplace->pos;
  93. mapProxy->insertObject(newObj);
  94. for (auto z : map.getZones())
  95. {
  96. //Every qap has its OWN collection of artifacts
  97. auto * localQap = zone->getModificator<QuestArtifactPlacer>();
  98. if (localQap)
  99. {
  100. localQap->dropReplacedArtifact(artifactToReplace);
  101. }
  102. }
  103. mapProxy->removeObject(artifactToReplace);
  104. break;
  105. }
  106. }
  107. }
  108. void QuestArtifactPlacer::dropReplacedArtifact(CGObjectInstance* obj)
  109. {
  110. RecursiveLock lock(externalAccessMutex);
  111. boost::remove(artifactsToReplace, obj);
  112. }
  113. size_t QuestArtifactPlacer::getMaxQuestArtifactCount() const
  114. {
  115. RecursiveLock lock(externalAccessMutex);
  116. return questArtifacts.size();
  117. }
  118. ArtifactID QuestArtifactPlacer::drawRandomArtifact()
  119. {
  120. RecursiveLock lock(externalAccessMutex);
  121. if (!questArtifacts.empty())
  122. {
  123. RandomGeneratorUtil::randomShuffle(questArtifacts, zone.getRand());
  124. ArtifactID ret = questArtifacts.back();
  125. questArtifacts.pop_back();
  126. generator.banQuestArt(ret);
  127. return ret;
  128. }
  129. else
  130. {
  131. throw rmgException("No quest artifacts left for this zone!");
  132. }
  133. }
  134. void QuestArtifactPlacer::addRandomArtifact(const ArtifactID & artid)
  135. {
  136. RecursiveLock lock(externalAccessMutex);
  137. questArtifacts.push_back(artid);
  138. generator.unbanQuestArt(artid);
  139. }
  140. VCMI_LIB_NAMESPACE_END