1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-14 10:12:59 +02:00
vcmi/lib/rmg/modificators/QuestArtifactPlacer.cpp

170 lines
4.5 KiB
C++
Raw Normal View History

2023-04-23 10:12:53 +02:00
/*
* 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"
2023-05-20 10:17:37 +02:00
#include "../CMapGenerator.h"
#include "../RmgMap.h"
2023-04-23 10:12:53 +02:00
#include "TreasurePlacer.h"
2023-05-20 10:17:37 +02:00
#include "../CZonePlacer.h"
#include "../../VCMI_Lib.h"
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
#include "../../mapObjectConstructors/CObjectClassesHandler.h"
#include "../../mapObjects/MapObjects.h"
#include <vstd/RNG.h>
2023-04-23 10:12:53 +02:00
2023-05-20 14:00:03 +02:00
VCMI_LIB_NAMESPACE_BEGIN
2023-04-23 10:12:53 +02:00
void QuestArtifactPlacer::process()
{
findZonesForQuestArts();
2023-05-20 11:46:32 +02:00
placeQuestArtifacts(zone.getRand());
2023-04-23 10:12:53 +02:00
}
void QuestArtifactPlacer::init()
{
DEPENDENCY_ALL(TreasurePlacer);
}
void QuestArtifactPlacer::addQuestArtZone(std::shared_ptr<Zone> otherZone)
{
RecursiveLock lock(externalAccessMutex);
2023-04-23 10:12:53 +02:00
questArtZones.push_back(otherZone);
}
void QuestArtifactPlacer::addQuestArtifact(const ArtifactID& id)
{
2024-02-25 12:40:01 +02:00
logGlobal->trace("Need to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
RecursiveLock lock(externalAccessMutex);
2023-04-23 10:12:53 +02:00
questArtifactsToPlace.emplace_back(id);
}
void QuestArtifactPlacer::removeQuestArtifact(const ArtifactID& id)
{
2024-02-25 12:40:01 +02:00
logGlobal->trace("Will not try to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
RecursiveLock lock(externalAccessMutex);
vstd::erase_if_present(questArtifactsToPlace, id);
}
2023-04-23 10:12:53 +02:00
void QuestArtifactPlacer::rememberPotentialArtifactToReplace(CGObjectInstance* obj)
{
RecursiveLock lock(externalAccessMutex);
2023-04-23 10:12:53 +02:00
artifactsToReplace.push_back(obj);
}
std::vector<CGObjectInstance*> QuestArtifactPlacer::getPossibleArtifactsToReplace() const
{
RecursiveLock lock(externalAccessMutex);
2023-04-23 10:12:53 +02:00
return artifactsToReplace;
}
CGObjectInstance * QuestArtifactPlacer::drawObjectToReplace()
{
RecursiveLock lock(externalAccessMutex);
if (artifactsToReplace.empty())
{
return nullptr;
}
else
{
auto ret = *RandomGeneratorUtil::nextItem(artifactsToReplace, zone.getRand());
vstd::erase_if_present(artifactsToReplace, ret);
return ret;
}
}
2023-04-23 10:12:53 +02:00
void QuestArtifactPlacer::findZonesForQuestArts()
{
const auto& distances = generator.getZonePlacer()->getDistanceMap().at(zone.getId());
2023-04-23 10:12:53 +02:00
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));
}
}
2024-02-25 12:40:01 +02:00
logGlobal->trace("Number of nearby zones suitable for quest artifacts: %d", questArtZones.size());
2023-04-23 10:12:53 +02:00
}
void QuestArtifactPlacer::placeQuestArtifacts(vstd::RNG & rand)
2023-04-23 10:12:53 +02:00
{
for (const auto & artifactToPlace : questArtifactsToPlace)
{
2023-05-20 11:46:32 +02:00
RandomGeneratorUtil::randomShuffle(questArtZones, rand);
2023-04-23 10:12:53 +02:00
for (auto zone : questArtZones)
{
auto* qap = zone->getModificator<QuestArtifactPlacer>();
auto objectToReplace = qap->drawObjectToReplace();
if (!objectToReplace)
2023-04-23 10:12:53 +02:00
continue;
2024-02-25 12:40:01 +02:00
logGlobal->trace("Replacing %s at %s with the quest artifact %s",
objectToReplace->getObjectName(),
objectToReplace->getPosition().toString(),
2023-04-25 16:20:36 +02:00
VLC->artifacts()->getById(artifactToPlace)->getNameTranslated());
2023-04-23 10:12:53 +02:00
//Update appearance. Terrain is irrelevant.
auto handler = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, artifactToPlace);
2024-01-01 16:37:48 +02:00
auto newObj = handler->create(map.mapInstance->cb, nullptr);
2023-04-23 10:12:53 +02:00
auto templates = handler->getTemplates();
2023-08-11 20:13:25 +02:00
//artifactToReplace->appearance = templates.front();
newObj->appearance = templates.front();
newObj->pos = objectToReplace->pos;
2023-08-11 20:13:25 +02:00
mapProxy->insertObject(newObj);
mapProxy->removeObject(objectToReplace);
2023-04-23 10:12:53 +02:00
break;
}
}
}
// TODO: Unused?
2023-04-23 10:12:53 +02:00
void QuestArtifactPlacer::dropReplacedArtifact(CGObjectInstance* obj)
{
RecursiveLock lock(externalAccessMutex);
2023-04-23 10:12:53 +02:00
boost::remove(artifactsToReplace, obj);
}
size_t QuestArtifactPlacer::getMaxQuestArtifactCount() const
{
RecursiveLock lock(externalAccessMutex);
return questArtifacts.size();
}
ArtifactID QuestArtifactPlacer::drawRandomArtifact()
{
RecursiveLock lock(externalAccessMutex);
if (!questArtifacts.empty())
{
RandomGeneratorUtil::randomShuffle(questArtifacts, zone.getRand());
ArtifactID ret = questArtifacts.back();
questArtifacts.pop_back();
generator.banQuestArt(ret);
return ret;
}
else
{
throw rmgException("No quest artifacts left for this zone!");
}
}
void QuestArtifactPlacer::addRandomArtifact(const ArtifactID & artid)
{
RecursiveLock lock(externalAccessMutex);
questArtifacts.push_back(artid);
generator.unbanQuestArt(artid);
}
2023-05-20 14:00:03 +02:00
VCMI_LIB_NAMESPACE_END