QuestArtifactPlacer.cpp 4.6 KB

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