QuestArtifactPlacer.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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->trace("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->trace("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. CGObjectInstance * QuestArtifactPlacer::drawObjectToReplace()
  58. {
  59. RecursiveLock lock(externalAccessMutex);
  60. if (artifactsToReplace.empty())
  61. {
  62. return nullptr;
  63. }
  64. else
  65. {
  66. auto ret = *RandomGeneratorUtil::nextItem(artifactsToReplace, zone.getRand());
  67. vstd::erase_if_present(artifactsToReplace, ret);
  68. return ret;
  69. }
  70. }
  71. void QuestArtifactPlacer::findZonesForQuestArts()
  72. {
  73. const auto& distances = generator.getZonePlacer()->getDistanceMap().at(zone.getId());
  74. for (auto const& connectedZone : distances)
  75. {
  76. // Choose zones that are 1 or 2 connections away
  77. if (vstd::iswithin(connectedZone.second, 1, 2))
  78. {
  79. addQuestArtZone(map.getZones().at(connectedZone.first));
  80. }
  81. }
  82. logGlobal->trace("Number of nearby zones suitable for quest artifacts: %d", questArtZones.size());
  83. }
  84. void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator & rand)
  85. {
  86. for (const auto & artifactToPlace : questArtifactsToPlace)
  87. {
  88. RandomGeneratorUtil::randomShuffle(questArtZones, rand);
  89. for (auto zone : questArtZones)
  90. {
  91. auto* qap = zone->getModificator<QuestArtifactPlacer>();
  92. auto objectToReplace = qap->drawObjectToReplace();
  93. if (!objectToReplace)
  94. continue;
  95. logGlobal->trace("Replacing %s at %s with the quest artifact %s",
  96. objectToReplace->getObjectName(),
  97. objectToReplace->getPosition().toString(),
  98. VLC->artifacts()->getById(artifactToPlace)->getNameTranslated());
  99. //Update appearance. Terrain is irrelevant.
  100. auto handler = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, artifactToPlace);
  101. auto newObj = handler->create(map.mapInstance->cb, nullptr);
  102. auto templates = handler->getTemplates();
  103. //artifactToReplace->appearance = templates.front();
  104. newObj->appearance = templates.front();
  105. newObj->pos = objectToReplace->pos;
  106. mapProxy->insertObject(newObj);
  107. mapProxy->removeObject(objectToReplace);
  108. break;
  109. }
  110. }
  111. }
  112. // TODO: Unused?
  113. void QuestArtifactPlacer::dropReplacedArtifact(CGObjectInstance* obj)
  114. {
  115. RecursiveLock lock(externalAccessMutex);
  116. boost::remove(artifactsToReplace, obj);
  117. }
  118. size_t QuestArtifactPlacer::getMaxQuestArtifactCount() const
  119. {
  120. RecursiveLock lock(externalAccessMutex);
  121. return questArtifacts.size();
  122. }
  123. ArtifactID QuestArtifactPlacer::drawRandomArtifact()
  124. {
  125. RecursiveLock lock(externalAccessMutex);
  126. if (!questArtifacts.empty())
  127. {
  128. RandomGeneratorUtil::randomShuffle(questArtifacts, zone.getRand());
  129. ArtifactID ret = questArtifacts.back();
  130. questArtifacts.pop_back();
  131. generator.banQuestArt(ret);
  132. return ret;
  133. }
  134. else
  135. {
  136. throw rmgException("No quest artifacts left for this zone!");
  137. }
  138. }
  139. void QuestArtifactPlacer::addRandomArtifact(const ArtifactID & artid)
  140. {
  141. RecursiveLock lock(externalAccessMutex);
  142. questArtifacts.push_back(artid);
  143. generator.unbanQuestArt(artid);
  144. }
  145. VCMI_LIB_NAMESPACE_END