1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Place quest artifacts after all the treasures are already created.

This commit is contained in:
Tomasz Zieliński 2023-04-23 10:08:16 +02:00
parent 1fde8b588b
commit 80b5c53815
11 changed files with 64 additions and 54 deletions

View File

@ -106,6 +106,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/rmg/ObjectDistributor.cpp ${MAIN_LIB_DIR}/rmg/ObjectDistributor.cpp
${MAIN_LIB_DIR}/rmg/RoadPlacer.cpp ${MAIN_LIB_DIR}/rmg/RoadPlacer.cpp
${MAIN_LIB_DIR}/rmg/TreasurePlacer.cpp ${MAIN_LIB_DIR}/rmg/TreasurePlacer.cpp
${MAIN_LIB_DIR}/rmg/QuestArtifactPlacer.cpp
${MAIN_LIB_DIR}/rmg/RmgMap.cpp ${MAIN_LIB_DIR}/rmg/RmgMap.cpp
${MAIN_LIB_DIR}/rmg/ConnectionsPlacer.cpp ${MAIN_LIB_DIR}/rmg/ConnectionsPlacer.cpp
${MAIN_LIB_DIR}/rmg/WaterAdopter.cpp ${MAIN_LIB_DIR}/rmg/WaterAdopter.cpp
@ -371,6 +372,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/rmg/ObjectDistributor.h ${MAIN_LIB_DIR}/rmg/ObjectDistributor.h
${MAIN_LIB_DIR}/rmg/RoadPlacer.h ${MAIN_LIB_DIR}/rmg/RoadPlacer.h
${MAIN_LIB_DIR}/rmg/TreasurePlacer.h ${MAIN_LIB_DIR}/rmg/TreasurePlacer.h
${MAIN_LIB_DIR}/rmg/QuestArtifactPlacer.h
${MAIN_LIB_DIR}/rmg/RmgMap.h ${MAIN_LIB_DIR}/rmg/RmgMap.h
${MAIN_LIB_DIR}/rmg/ConnectionsPlacer.h ${MAIN_LIB_DIR}/rmg/ConnectionsPlacer.h
${MAIN_LIB_DIR}/rmg/WaterAdopter.h ${MAIN_LIB_DIR}/rmg/WaterAdopter.h

View File

@ -37,6 +37,7 @@ CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) :
rand.setSeed(this->randomSeed); rand.setSeed(this->randomSeed);
mapGenOptions.finalize(rand); mapGenOptions.finalize(rand);
map = std::make_unique<RmgMap>(mapGenOptions); map = std::make_unique<RmgMap>(mapGenOptions);
placer = std::make_shared<CZonePlacer>(*map);
} }
int CMapGenerator::getRandomSeed() const int CMapGenerator::getRandomSeed() const
@ -109,6 +110,7 @@ void CMapGenerator::initPrisonsRemaining()
void CMapGenerator::initQuestArtsRemaining() void CMapGenerator::initQuestArtsRemaining()
{ {
//TODO: Move to QuestArtifactPlacer?
for (auto art : VLC->arth->objects) for (auto art : VLC->arth->objects)
{ {
if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->constituentOf.empty()) //don't use parts of combined artifacts if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->constituentOf.empty()) //don't use parts of combined artifacts
@ -267,14 +269,13 @@ void CMapGenerator::addPlayerInfo()
void CMapGenerator::genZones() void CMapGenerator::genZones()
{ {
CZonePlacer placer(*map); placer->placeZones(&rand);
placer.placeZones(&rand); placer->assignZones(&rand);
placer.assignZones(&rand);
logGlobal->info("Zones generated successfully"); logGlobal->info("Zones generated successfully");
} }
void CMapGenerator::createWaterTreasures() void CMapGenerator::addWaterTreasuresInfo()
{ {
if (!getZoneWater()) if (!getZoneWater())
return; return;
@ -288,8 +289,7 @@ void CMapGenerator::createWaterTreasures()
void CMapGenerator::fillZones() void CMapGenerator::fillZones()
{ {
findZonesForQuestArts(); addWaterTreasuresInfo();
createWaterTreasures();
logGlobal->info("Started filling zones"); logGlobal->info("Started filling zones");
@ -331,28 +331,6 @@ void CMapGenerator::fillZones()
Load::Progress::set(250); Load::Progress::set(250);
} }
void CMapGenerator::findZonesForQuestArts()
{
//we want to place arties in zones that were not yet filled (higher index)
for (auto connection : mapGenOptions.getMapTemplate()->getConnections())
{
auto zoneA = map->getZones()[connection.getZoneA()];
auto zoneB = map->getZones()[connection.getZoneB()];
if (zoneA->getId() > zoneB->getId())
{
if(auto * m = zoneB->getModificator<TreasurePlacer>())
m->setQuestArtZone(zoneA.get());
}
else if (zoneA->getId() < zoneB->getId())
{
if(auto * m = zoneA->getModificator<TreasurePlacer>())
m->setQuestArtZone(zoneB.get());
}
}
}
void CMapGenerator::addHeaderInfo() void CMapGenerator::addHeaderInfo()
{ {
map->map().version = EMapFormat::VCMI; map->map().version = EMapFormat::VCMI;
@ -392,6 +370,11 @@ int CMapGenerator::getPrisonsRemaning() const
return prisonsRemaining; return prisonsRemaining;
} }
std::shared_ptr<CZonePlacer> CMapGenerator::getZonePlacer() const
{
return placer;
}
void CMapGenerator::decreasePrisonsRemaining() void CMapGenerator::decreasePrisonsRemaining()
{ {
prisonsRemaining = std::max (0, prisonsRemaining - 1); prisonsRemaining = std::max (0, prisonsRemaining - 1);

View File

@ -25,6 +25,7 @@ class JsonNode;
class RmgMap; class RmgMap;
class CMap; class CMap;
class Zone; class Zone;
class CZonePlacer;
typedef std::vector<JsonNode> JsonVector; typedef std::vector<JsonNode> JsonVector;
@ -59,16 +60,15 @@ public:
std::unique_ptr<CMap> generate(); std::unique_ptr<CMap> generate();
void findZonesForQuestArts();
int getNextMonlithIndex(); int getNextMonlithIndex();
int getPrisonsRemaning() const; int getPrisonsRemaning() const;
std::shared_ptr<CZonePlacer> getZonePlacer() const;
void decreasePrisonsRemaining(); void decreasePrisonsRemaining();
const std::vector<ArtifactID> & getQuestArtsRemaning() const; const std::vector<ArtifactID> & getQuestArtsRemaning() const;
void banQuestArt(const ArtifactID & id); void banQuestArt(const ArtifactID & id);
Zone * getZoneWater() const; Zone * getZoneWater() const;
void createWaterTreasures(); void addWaterTreasuresInfo();
int getRandomSeed() const; int getRandomSeed() const;
@ -77,6 +77,7 @@ private:
CMapGenOptions& mapGenOptions; CMapGenOptions& mapGenOptions;
Config config; Config config;
std::unique_ptr<RmgMap> map; std::unique_ptr<RmgMap> map;
std::shared_ptr<CZonePlacer> placer;
std::vector<rmg::ZoneConnection> connectionsLeft; std::vector<rmg::ZoneConnection> connectionsLeft;
@ -85,7 +86,7 @@ private:
int prisonsRemaining; int prisonsRemaining;
//int questArtsRemaining; //int questArtsRemaining;
int monolithIndex; int monolithIndex;
std::vector<ArtifactID> questArtifacts; std::vector<ArtifactID> questArtifacts; //TODO: Protect with mutex
/// Generation methods /// Generation methods
void loadConfig(); void loadConfig();

View File

@ -869,4 +869,9 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
logGlobal->info("Finished zone colouring"); logGlobal->info("Finished zone colouring");
} }
const TDistanceMap& CZonePlacer::getDistanceMap()
{
return distancesBetweenZones;
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -26,6 +26,7 @@ typedef std::vector<std::pair<TRmgTemplateZoneId, std::shared_ptr<Zone>>> TZoneV
typedef std::map<TRmgTemplateZoneId, std::shared_ptr<Zone>> TZoneMap; typedef std::map<TRmgTemplateZoneId, std::shared_ptr<Zone>> TZoneMap;
typedef std::map<std::shared_ptr<Zone>, float3> TForceVector; typedef std::map<std::shared_ptr<Zone>, float3> TForceVector;
typedef std::map<std::shared_ptr<Zone>, float> TDistanceVector; typedef std::map<std::shared_ptr<Zone>, float> TDistanceVector;
typedef std::map<int, std::map<int, size_t>> TDistanceMap;
class CZonePlacer class CZonePlacer
{ {
@ -40,6 +41,8 @@ public:
void findPathsBetweenZones(); void findPathsBetweenZones();
void placeOnGrid(CRandomGenerator* rand); void placeOnGrid(CRandomGenerator* rand);
void assignZones(CRandomGenerator * rand); void assignZones(CRandomGenerator * rand);
const TDistanceMap & getDistanceMap();
private: private:
void prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const bool underground, CRandomGenerator * rand); void prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const bool underground, CRandomGenerator * rand);
@ -65,7 +68,7 @@ private:
float bestTotalOverlap; float bestTotalOverlap;
//distance [a][b] = number of zone connections required to travel between the zones //distance [a][b] = number of zone connections required to travel between the zones
std::map<int, std::map<int, size_t>> distancesBetweenZones; TDistanceMap distancesBetweenZones;
std::set<TRmgTemplateZoneId> lastSwappedZones; std::set<TRmgTemplateZoneId> lastSwappedZones;
RmgMap & map; RmgMap & map;
}; };

View File

@ -16,6 +16,8 @@
#include "RoadPlacer.h" #include "RoadPlacer.h"
#include "RiverPlacer.h" #include "RiverPlacer.h"
#include "WaterAdopter.h" #include "WaterAdopter.h"
#include "TreasurePlacer.h"
#include "QuestArtifactPlacer.h"
#include "../CCreatureHandler.h" #include "../CCreatureHandler.h"
#include "../mapObjects/CommonConstructors.h" #include "../mapObjects/CommonConstructors.h"
#include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h #include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h
@ -379,6 +381,21 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
m->areaIsolated().add(instance->getVisitablePosition() + int3(0, -1, 0)); m->areaIsolated().add(instance->getVisitablePosition() + int3(0, -1, 0));
} }
} }
switch (instance->object().ID)
{
case Obj::RANDOM_TREASURE_ART:
case Obj::RANDOM_MINOR_ART: //In OH3 quest artifacts have higher value than normal arts
{
if (auto * qap = zone.getModificator<QuestArtifactPlacer>())
{
qap->rememberPotentialArtifactToReplace(&instance->object());
}
break;
}
default:
break;
}
} }
switch(object.instances().front()->object().ID) switch(object.instances().front()->object().ID)

View File

@ -19,6 +19,7 @@
#include "ObjectManager.h" #include "ObjectManager.h"
#include "RoadPlacer.h" #include "RoadPlacer.h"
#include "TreasurePlacer.h" #include "TreasurePlacer.h"
#include "QuestArtifactPlacer.h"
#include "ConnectionsPlacer.h" #include "ConnectionsPlacer.h"
#include "TownPlacer.h" #include "TownPlacer.h"
#include "MinePlacer.h" #include "MinePlacer.h"
@ -139,6 +140,7 @@ void RmgMap::addModificators()
{ {
zone->addModificator<TownPlacer>(); zone->addModificator<TownPlacer>();
zone->addModificator<MinePlacer>(); zone->addModificator<MinePlacer>();
zone->addModificator<QuestArtifactPlacer>();
zone->addModificator<ConnectionsPlacer>(); zone->addModificator<ConnectionsPlacer>();
zone->addModificator<RoadPlacer>(); zone->addModificator<RoadPlacer>();
zone->addModificator<RiverPlacer>(); zone->addModificator<RiverPlacer>();

View File

@ -17,6 +17,8 @@
#include "ConnectionsPlacer.h" #include "ConnectionsPlacer.h"
#include "RmgMap.h" #include "RmgMap.h"
#include "TileInfo.h" #include "TileInfo.h"
#include "CZonePlacer.h"
#include "QuestArtifactPlacer.h"
#include "../mapObjects/CommonConstructors.h" #include "../mapObjects/CommonConstructors.h"
#include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h #include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h
#include "../CCreatureHandler.h" #include "../CCreatureHandler.h"
@ -41,11 +43,6 @@ void TreasurePlacer::init()
POSTFUNCTION(RoadPlacer); POSTFUNCTION(RoadPlacer);
} }
void TreasurePlacer::setQuestArtZone(Zone * otherZone)
{
questArtZone = otherZone;
}
void TreasurePlacer::addObjectToRandomPool(const ObjectInfo& oi) void TreasurePlacer::addObjectToRandomPool(const ObjectInfo& oi)
{ {
possibleObjects.push_back(oi); possibleObjects.push_back(oi);
@ -389,8 +386,8 @@ void TreasurePlacer::addAllPossibleObjects()
addObjectToRandomPool(oi); addObjectToRandomPool(oi);
//seer huts with creatures or generic rewards //seer huts with creatures or generic rewards
if(questArtZone) //we won't be placing seer huts if there is no zone left to place arties if(zone.getConnections().size()) //Unlikely, but...
{ {
static const int genericSeerHuts = 8; static const int genericSeerHuts = 8;
int seerHutsPerType = 0; int seerHutsPerType = 0;
@ -450,9 +447,7 @@ void TreasurePlacer::addAllPossibleObjects()
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
generator.banQuestArt(artid); generator.banQuestArt(artid);
zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
this->questArtZone->getModificator<TreasurePlacer>()->addObjectToRandomPool(generateArtInfo(artid));
return obj; return obj;
}; };
@ -487,8 +482,7 @@ void TreasurePlacer::addAllPossibleObjects()
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
generator.banQuestArt(artid); generator.banQuestArt(artid);
zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
this->questArtZone->getModificator<TreasurePlacer>()->addObjectToRandomPool(generateArtInfo(artid));
return obj; return obj;
}; };
@ -510,8 +504,7 @@ void TreasurePlacer::addAllPossibleObjects()
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
generator.banQuestArt(artid); generator.banQuestArt(artid);
zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
this->questArtZone->getModificator<TreasurePlacer>()->addObjectToRandomPool(generateArtInfo(artid));
return obj; return obj;
}; };

View File

@ -1,5 +1,5 @@
/* /*
* TreasurePlacer.cpp, part of VCMI engine * TreasurePlacer.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@ -18,6 +18,7 @@ class CGObjectInstance;
class ObjectManager; class ObjectManager;
class RmgMap; class RmgMap;
class CMapGenerator; class CMapGenerator;
class CRandomGenerator;
struct ObjectInfo struct ObjectInfo
{ {
@ -43,8 +44,6 @@ public:
char dump(const int3 &) override; char dump(const int3 &) override;
void createTreasures(ObjectManager & manager); void createTreasures(ObjectManager & manager);
void setQuestArtZone(Zone * otherZone);
void addObjectToRandomPool(const ObjectInfo& oi); void addObjectToRandomPool(const ObjectInfo& oi);
void addAllPossibleObjects(); //add objects, including zone-specific, to possibleObjects void addAllPossibleObjects(); //add objects, including zone-specific, to possibleObjects
@ -56,8 +55,7 @@ protected:
ObjectInfo * getRandomObject(ui32 desiredValue, ui32 currentValue, ui32 maxValue, bool allowLargeObjects); ObjectInfo * getRandomObject(ui32 desiredValue, ui32 currentValue, ui32 maxValue, bool allowLargeObjects);
std::vector<ObjectInfo*> prepareTreasurePile(const CTreasureInfo & treasureInfo); std::vector<ObjectInfo*> prepareTreasurePile(const CTreasureInfo & treasureInfo);
rmg::Object constructTreasurePile(const std::vector<ObjectInfo*> & treasureInfos, bool densePlacement = false); rmg::Object constructTreasurePile(const std::vector<ObjectInfo*> & treasureInfos, bool densePlacement = false);
protected: protected:
std::vector<ObjectInfo> possibleObjects; std::vector<ObjectInfo> possibleObjects;
int minGuardedValue = 0; int minGuardedValue = 0;
@ -65,8 +63,6 @@ protected:
rmg::Area treasureArea; rmg::Area treasureArea;
rmg::Area treasureBlockArea; rmg::Area treasureBlockArea;
rmg::Area guards; rmg::Area guards;
Zone * questArtZone = nullptr; //artifacts required for Seer Huts will be placed here - or not if null
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -95,6 +95,11 @@ rmg::Area & Zone::areaUsed()
return dAreaUsed; return dAreaUsed;
} }
std::vector<int3> Zone::getPossibleQuestArtifactPos() const
{
return possibleQuestArtifactPos;
}
void Zone::clearTiles() void Zone::clearTiles()
{ {
dArea.clear(); dArea.clear();

View File

@ -93,6 +93,8 @@ public:
rmg::Area & areaPossible(); rmg::Area & areaPossible();
rmg::Area & freePaths(); rmg::Area & freePaths();
rmg::Area & areaUsed(); rmg::Area & areaUsed();
std::vector<int3> getPossibleQuestArtifactPos() const;
void initFreeTiles(); void initFreeTiles();
void clearTiles(); void clearTiles();
@ -137,6 +139,7 @@ protected:
rmg::Area dAreaPossible; rmg::Area dAreaPossible;
rmg::Area dAreaFree; //core paths of free tiles that all other objects will be linked to rmg::Area dAreaFree; //core paths of free tiles that all other objects will be linked to
rmg::Area dAreaUsed; rmg::Area dAreaUsed;
std::vector<int3> possibleQuestArtifactPos;
//template info //template info
si32 townType; si32 townType;