QuestArtifactPlacer.cpp 4.5 KB

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