| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * QuestArtifact.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #include "StdInc.h"
- #include "QuestArtifactPlacer.h"
- #include "CMapGenerator.h"
- #include "RmgMap.h"
- #include "TreasurePlacer.h"
- #include "CZonePlacer.h"
- #include "../VCMI_Lib.h"
- #include "../mapObjects/CObjectHandler.h"
- #include "../mapObjects/CommonConstructors.h"
- #include "../mapObjects/MapObjects.h"
- void QuestArtifactPlacer::process()
- {
- findZonesForQuestArts();
- placeQuestArtifacts(&generator.rand);
- }
- void QuestArtifactPlacer::init()
- {
- DEPENDENCY_ALL(TreasurePlacer);
- }
- void QuestArtifactPlacer::addQuestArtZone(std::shared_ptr<Zone> otherZone)
- {
- Lock lock(externalAccessMutex);
- questArtZones.push_back(otherZone);
- }
- void QuestArtifactPlacer::addQuestArtifact(const ArtifactID& id)
- {
- Lock lock(externalAccessMutex);
- logGlobal->info("Need to place quest artifact artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
- questArtifactsToPlace.emplace_back(id);
- }
- void QuestArtifactPlacer::rememberPotentialArtifactToReplace(CGObjectInstance* obj)
- {
- Lock lock(externalAccessMutex);
- artifactsToReplace.push_back(obj);
- }
- std::vector<CGObjectInstance*> QuestArtifactPlacer::getPossibleArtifactsToReplace() const
- {
- Lock lock(externalAccessMutex);
- return artifactsToReplace;
- }
- void QuestArtifactPlacer::findZonesForQuestArts()
- {
- const auto& distances = generator.getZonePlacer()->getDistanceMap().at(zone.getId());
- for (auto const& connectedZone : distances)
- {
- // Choose zones that are 1 or 2 connections away
- if (vstd::iswithin(connectedZone.second, 1, 2))
- {
- addQuestArtZone(map.getZones().at(connectedZone.first));
- }
- }
- logGlobal->info("Number of nearby zones suitable for quest artifacts: %d", questArtZones.size());
- }
- void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator * rand)
- {
- for (const auto & artifactToPlace : questArtifactsToPlace)
- {
- RandomGeneratorUtil::randomShuffle(questArtZones, *rand);
- for (auto zone : questArtZones)
- {
- auto* qap = zone->getModificator<QuestArtifactPlacer>();
- std::vector<CGObjectInstance *> artifactsToReplace = qap->getPossibleArtifactsToReplace();
- if (artifactsToReplace.empty())
- continue;
- auto artifactToReplace = *RandomGeneratorUtil::nextItem(artifactsToReplace, *rand);
- logGlobal->info("Replacing %s at %s with the quest artifact %s",
- artifactToReplace->getObjectName(),
- artifactToReplace->getPosition().toString(),
- VLC->artifacts()->getById(artifactToPlace)->getNameTranslated());
- artifactToReplace->ID = Obj::ARTIFACT;
- artifactToReplace->subID = artifactToPlace;
- //Update appearance. Terrain is irrelevant.
- auto handler = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, artifactToPlace);
- auto templates = handler->getTemplates();
- artifactToReplace->appearance = templates.front();
- //FIXME: Instance name is still "randomArtifact"
- for (auto z : map.getZones())
- {
- //Every qap has its OWN collection of artifacts
- auto * localQap = zone->getModificator<QuestArtifactPlacer>();
- if (localQap)
- {
- localQap->dropReplacedArtifact(artifactToReplace);
- }
- }
- break;
- }
- }
- }
- void QuestArtifactPlacer::dropReplacedArtifact(CGObjectInstance* obj)
- {
- Lock lock(externalAccessMutex);
- boost::remove(artifactsToReplace, obj);
- }
- size_t QuestArtifactPlacer::getMaxQuestArtifactCount() const
- {
- Lock lock(externalAccessMutex);
- return questArtifacts.size();
- }
- ArtifactID QuestArtifactPlacer::drawRandomArtifact()
- {
- Lock lock(externalAccessMutex);
- if (!questArtifacts.empty())
- {
- ArtifactID ret = questArtifacts.back();
- questArtifacts.pop_back();
- RandomGeneratorUtil::randomShuffle(questArtifacts, generator.rand);
- return ret;
- }
- else
- {
- throw rmgException("No quest artifacts left for this zone!");
- }
- }
- void QuestArtifactPlacer::addRandomArtifact(ArtifactID artid)
- {
- Lock lock(externalAccessMutex);
- questArtifacts.push_back(artid);
- }
|