mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Merge pull request #3298 from vcmi/random_prison_distributor
Fixes to hero / prison distribution
This commit is contained in:
commit
b1bd44de1e
@ -156,6 +156,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/rmg/modificators/ObjectDistributor.cpp
|
||||
${MAIN_LIB_DIR}/rmg/modificators/RoadPlacer.cpp
|
||||
${MAIN_LIB_DIR}/rmg/modificators/TreasurePlacer.cpp
|
||||
${MAIN_LIB_DIR}/rmg/modificators/PrisonHeroPlacer.cpp
|
||||
${MAIN_LIB_DIR}/rmg/modificators/QuestArtifactPlacer.cpp
|
||||
${MAIN_LIB_DIR}/rmg/modificators/ConnectionsPlacer.cpp
|
||||
${MAIN_LIB_DIR}/rmg/modificators/WaterAdopter.cpp
|
||||
@ -526,6 +527,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/rmg/modificators/ObjectDistributor.h
|
||||
${MAIN_LIB_DIR}/rmg/modificators/RoadPlacer.h
|
||||
${MAIN_LIB_DIR}/rmg/modificators/TreasurePlacer.h
|
||||
${MAIN_LIB_DIR}/rmg/modificators/PrisonHeroPlacer.h
|
||||
${MAIN_LIB_DIR}/rmg/modificators/QuestArtifactPlacer.h
|
||||
${MAIN_LIB_DIR}/rmg/modificators/ConnectionsPlacer.h
|
||||
${MAIN_LIB_DIR}/rmg/modificators/WaterAdopter.h
|
||||
|
@ -649,9 +649,18 @@ void CMap::banWaterHeroes()
|
||||
|
||||
void CMap::banHero(const HeroTypeID & id)
|
||||
{
|
||||
if (!vstd::contains(allowedHeroes, id))
|
||||
logGlobal->warn("Attempt to ban hero %s, who is already not allowed", id.encode(id));
|
||||
allowedHeroes.erase(id);
|
||||
}
|
||||
|
||||
void CMap::unbanHero(const HeroTypeID & id)
|
||||
{
|
||||
if (vstd::contains(allowedHeroes, id))
|
||||
logGlobal->warn("Attempt to unban hero %s, who is already allowed", id.encode(id));
|
||||
allowedHeroes.insert(id);
|
||||
}
|
||||
|
||||
void CMap::initTerrain()
|
||||
{
|
||||
terrain.resize(boost::extents[levels()][width][height]);
|
||||
|
@ -112,6 +112,7 @@ public:
|
||||
void banWaterArtifacts();
|
||||
void banWaterHeroes();
|
||||
void banHero(const HeroTypeID& id);
|
||||
void unbanHero(const HeroTypeID & id);
|
||||
void banWaterSpells();
|
||||
void banWaterSkills();
|
||||
void banWaterContent();
|
||||
|
@ -35,7 +35,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) :
|
||||
mapGenOptions(mapGenOptions), randomSeed(RandomSeed),
|
||||
allowedPrisons(0), monolithIndex(0)
|
||||
monolithIndex(0)
|
||||
{
|
||||
loadConfig();
|
||||
rand.setSeed(this->randomSeed);
|
||||
@ -96,12 +96,6 @@ const CMapGenOptions& CMapGenerator::getMapGenOptions() const
|
||||
return mapGenOptions;
|
||||
}
|
||||
|
||||
void CMapGenerator::initPrisonsRemaining()
|
||||
{
|
||||
allowedPrisons = map->getMap(this).allowedHeroes.size();
|
||||
allowedPrisons = std::max<int> (0, allowedPrisons - 16 * mapGenOptions.getHumanOrCpuPlayerCount()); //so at least 16 heroes will be available for every player
|
||||
}
|
||||
|
||||
void CMapGenerator::initQuestArtsRemaining()
|
||||
{
|
||||
//TODO: Move to QuestArtifactPlacer?
|
||||
@ -122,7 +116,6 @@ std::unique_ptr<CMap> CMapGenerator::generate()
|
||||
addHeaderInfo();
|
||||
map->initTiles(*this, rand);
|
||||
Load::Progress::step();
|
||||
initPrisonsRemaining();
|
||||
initQuestArtsRemaining();
|
||||
genZones();
|
||||
Load::Progress::step();
|
||||
@ -468,11 +461,6 @@ int CMapGenerator::getNextMonlithIndex()
|
||||
}
|
||||
}
|
||||
|
||||
int CMapGenerator::getPrisonsRemaning() const
|
||||
{
|
||||
return allowedPrisons;
|
||||
}
|
||||
|
||||
std::shared_ptr<CZonePlacer> CMapGenerator::getZonePlacer() const
|
||||
{
|
||||
return placer;
|
||||
@ -488,6 +476,7 @@ const std::vector<HeroTypeID> CMapGenerator::getAllPossibleHeroes() const
|
||||
auto isWaterMap = map->getMap(this).isWaterMap();
|
||||
//Skip heroes that were banned, including the ones placed in prisons
|
||||
std::vector<HeroTypeID> ret;
|
||||
|
||||
for (HeroTypeID hero : map->getMap(this).allowedHeroes)
|
||||
{
|
||||
auto * h = dynamic_cast<const CHero*>(VLC->heroTypes()->getById(hero));
|
||||
@ -517,14 +506,12 @@ const std::vector<HeroTypeID> CMapGenerator::getAllPossibleHeroes() const
|
||||
|
||||
void CMapGenerator::banQuestArt(const ArtifactID & id)
|
||||
{
|
||||
//TODO: Protect with mutex
|
||||
map->getMap(this).allowedArtifact.erase(id);
|
||||
}
|
||||
|
||||
void CMapGenerator::banHero(const HeroTypeID & id)
|
||||
void CMapGenerator::unbanQuestArt(const ArtifactID & id)
|
||||
{
|
||||
//TODO: Protect with mutex
|
||||
map->getMap(this).banHero(id);
|
||||
map->getMap(this).allowedArtifact.insert(id);
|
||||
}
|
||||
|
||||
Zone * CMapGenerator::getZoneWater() const
|
||||
|
@ -65,8 +65,7 @@ public:
|
||||
const std::vector<ArtifactID> & getAllPossibleQuestArtifacts() const;
|
||||
const std::vector<HeroTypeID> getAllPossibleHeroes() const;
|
||||
void banQuestArt(const ArtifactID & id);
|
||||
void banHero(const HeroTypeID& id);
|
||||
|
||||
void unbanQuestArt(const ArtifactID & id);
|
||||
Zone * getZoneWater() const;
|
||||
void addWaterTreasuresInfo();
|
||||
|
||||
@ -82,7 +81,6 @@ private:
|
||||
|
||||
std::vector<rmg::ZoneConnection> connectionsLeft;
|
||||
|
||||
int allowedPrisons;
|
||||
int monolithIndex;
|
||||
std::vector<ArtifactID> questArtifacts;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "modificators/ObjectManager.h"
|
||||
#include "modificators/RoadPlacer.h"
|
||||
#include "modificators/TreasurePlacer.h"
|
||||
#include "modificators/PrisonHeroPlacer.h"
|
||||
#include "modificators/QuestArtifactPlacer.h"
|
||||
#include "modificators/ConnectionsPlacer.h"
|
||||
#include "modificators/TownPlacer.h"
|
||||
@ -127,6 +128,7 @@ void RmgMap::initTiles(CMapGenerator & generator, CRandomGenerator & rand)
|
||||
void RmgMap::addModificators()
|
||||
{
|
||||
bool hasObjectDistributor = false;
|
||||
bool hasHeroPlacer = false;
|
||||
bool hasRockFiller = false;
|
||||
|
||||
for(auto & z : getZones())
|
||||
@ -139,6 +141,11 @@ void RmgMap::addModificators()
|
||||
zone->addModificator<ObjectDistributor>();
|
||||
hasObjectDistributor = true;
|
||||
}
|
||||
if (!hasHeroPlacer)
|
||||
{
|
||||
zone->addModificator<PrisonHeroPlacer>();
|
||||
hasHeroPlacer = true;
|
||||
}
|
||||
zone->addModificator<TreasurePlacer>();
|
||||
zone->addModificator<ObstaclePlacer>();
|
||||
zone->addModificator<TerrainPainter>();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "../RmgMap.h"
|
||||
#include "../CMapGenerator.h"
|
||||
#include "TreasurePlacer.h"
|
||||
#include "PrisonHeroPlacer.h"
|
||||
#include "QuestArtifactPlacer.h"
|
||||
#include "TownPlacer.h"
|
||||
#include "TerrainPainter.h"
|
||||
@ -75,7 +76,6 @@ void ObjectDistributor::distributeLimitedObjects()
|
||||
|
||||
auto rmgInfo = handler->getRMGInfo();
|
||||
|
||||
// FIXME: Random order of distribution
|
||||
RandomGeneratorUtil::randomShuffle(matchingZones, zone.getRand());
|
||||
for (auto& zone : matchingZones)
|
||||
{
|
||||
@ -146,7 +146,18 @@ void ObjectDistributor::distributePrisons()
|
||||
|
||||
RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
|
||||
|
||||
size_t allowedPrisons = generator.getPrisonsRemaning();
|
||||
// TODO: Some shorthand for unique Modificator
|
||||
PrisonHeroPlacer * prisonHeroPlacer = nullptr;
|
||||
for(auto & z : map.getZones())
|
||||
{
|
||||
prisonHeroPlacer = z.second->getModificator<PrisonHeroPlacer>();
|
||||
if (prisonHeroPlacer)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t allowedPrisons = prisonHeroPlacer->getPrisonsRemaning();
|
||||
for (int i = zones.size() - 1; i >= 0; i--)
|
||||
{
|
||||
auto zone = zones[i].second;
|
||||
|
73
lib/rmg/modificators/PrisonHeroPlacer.cpp
Normal file
73
lib/rmg/modificators/PrisonHeroPlacer.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* PrisonHeroPlacer.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 "PrisonHeroPlacer.h"
|
||||
#include "../CMapGenerator.h"
|
||||
#include "../RmgMap.h"
|
||||
#include "TreasurePlacer.h"
|
||||
#include "../CZonePlacer.h"
|
||||
#include "../../VCMI_Lib.h"
|
||||
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
|
||||
#include "../../mapObjectConstructors/CObjectClassesHandler.h"
|
||||
#include "../../mapObjects/MapObjects.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
void PrisonHeroPlacer::process()
|
||||
{
|
||||
getAllowedHeroes();
|
||||
}
|
||||
|
||||
void PrisonHeroPlacer::init()
|
||||
{
|
||||
// Reserve at least 16 heroes for each player
|
||||
reservedHeroes = 16 * generator.getMapGenOptions().getHumanOrCpuPlayerCount();
|
||||
}
|
||||
|
||||
void PrisonHeroPlacer::getAllowedHeroes()
|
||||
{
|
||||
// TODO: Give each zone unique HeroPlacer with private hero list?
|
||||
|
||||
// Call that only once
|
||||
if (allowedHeroes.empty())
|
||||
{
|
||||
allowedHeroes = generator.getAllPossibleHeroes();
|
||||
}
|
||||
}
|
||||
|
||||
int PrisonHeroPlacer::getPrisonsRemaning() const
|
||||
{
|
||||
return std::max<int>(allowedHeroes.size() - reservedHeroes, 0);
|
||||
}
|
||||
|
||||
HeroTypeID PrisonHeroPlacer::drawRandomHero()
|
||||
{
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
if (getPrisonsRemaning() > 0)
|
||||
{
|
||||
RandomGeneratorUtil::randomShuffle(allowedHeroes, zone.getRand());
|
||||
HeroTypeID ret = allowedHeroes.back();
|
||||
allowedHeroes.pop_back();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw rmgException("No unused heroes left for prisons!");
|
||||
}
|
||||
}
|
||||
|
||||
void PrisonHeroPlacer::restoreDrawnHero(const HeroTypeID & hid)
|
||||
{
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
allowedHeroes.push_back(hid);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
41
lib/rmg/modificators/PrisonHeroPlacer.h
Normal file
41
lib/rmg/modificators/PrisonHeroPlacer.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* PrisonHeroPlacer, 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../Zone.h"
|
||||
#include "../Functions.h"
|
||||
#include "../../mapObjects/ObjectTemplate.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CRandomGenerator;
|
||||
|
||||
class PrisonHeroPlacer : public Modificator
|
||||
{
|
||||
public:
|
||||
MODIFICATOR(PrisonHeroPlacer);
|
||||
|
||||
void process() override;
|
||||
void init() override;
|
||||
|
||||
int getPrisonsRemaning() const;
|
||||
[[nodiscard]] HeroTypeID drawRandomHero();
|
||||
void restoreDrawnHero(const HeroTypeID & hid);
|
||||
|
||||
private:
|
||||
void getAllowedHeroes();
|
||||
size_t reservedHeroes;
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<HeroTypeID> allowedHeroes;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -40,11 +40,18 @@ void QuestArtifactPlacer::addQuestArtZone(std::shared_ptr<Zone> otherZone)
|
||||
|
||||
void QuestArtifactPlacer::addQuestArtifact(const ArtifactID& id)
|
||||
{
|
||||
logGlobal->info("Need to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
logGlobal->info("Need to place quest artifact artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
|
||||
questArtifactsToPlace.emplace_back(id);
|
||||
}
|
||||
|
||||
void QuestArtifactPlacer::removeQuestArtifact(const ArtifactID& id)
|
||||
{
|
||||
logGlobal->info("Will not try to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
vstd::erase_if_present(questArtifactsToPlace, id);
|
||||
}
|
||||
|
||||
void QuestArtifactPlacer::rememberPotentialArtifactToReplace(CGObjectInstance* obj)
|
||||
{
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
@ -131,9 +138,10 @@ ArtifactID QuestArtifactPlacer::drawRandomArtifact()
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
if (!questArtifacts.empty())
|
||||
{
|
||||
RandomGeneratorUtil::randomShuffle(questArtifacts, zone.getRand());
|
||||
ArtifactID ret = questArtifacts.back();
|
||||
questArtifacts.pop_back();
|
||||
RandomGeneratorUtil::randomShuffle(questArtifacts, zone.getRand());
|
||||
generator.banQuestArt(ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
@ -142,10 +150,11 @@ ArtifactID QuestArtifactPlacer::drawRandomArtifact()
|
||||
}
|
||||
}
|
||||
|
||||
void QuestArtifactPlacer::addRandomArtifact(ArtifactID artid)
|
||||
void QuestArtifactPlacer::addRandomArtifact(const ArtifactID & artid)
|
||||
{
|
||||
RecursiveLock lock(externalAccessMutex);
|
||||
questArtifacts.push_back(artid);
|
||||
generator.unbanQuestArt(artid);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -29,14 +29,15 @@ public:
|
||||
void findZonesForQuestArts();
|
||||
|
||||
void addQuestArtifact(const ArtifactID& id);
|
||||
void removeQuestArtifact(const ArtifactID& id);
|
||||
void rememberPotentialArtifactToReplace(CGObjectInstance* obj);
|
||||
std::vector<CGObjectInstance*> getPossibleArtifactsToReplace() const;
|
||||
void placeQuestArtifacts(CRandomGenerator & rand);
|
||||
void dropReplacedArtifact(CGObjectInstance* obj);
|
||||
|
||||
size_t getMaxQuestArtifactCount() const;
|
||||
ArtifactID drawRandomArtifact();
|
||||
void addRandomArtifact(ArtifactID artid);
|
||||
[[nodiscard]] ArtifactID drawRandomArtifact();
|
||||
void addRandomArtifact(const ArtifactID & artid);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "../RmgMap.h"
|
||||
#include "../TileInfo.h"
|
||||
#include "../CZonePlacer.h"
|
||||
#include "PrisonHeroPlacer.h"
|
||||
#include "QuestArtifactPlacer.h"
|
||||
#include "../../ArtifactUtils.h"
|
||||
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
|
||||
@ -32,6 +33,12 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
ObjectInfo::ObjectInfo():
|
||||
destroyObject([](){})
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TreasurePlacer::process()
|
||||
{
|
||||
addAllPossibleObjects();
|
||||
@ -45,6 +52,7 @@ void TreasurePlacer::init()
|
||||
maxPrisons = 0; //Should be in the constructor, but we use macro for that
|
||||
DEPENDENCY(ObjectManager);
|
||||
DEPENDENCY(ConnectionsPlacer);
|
||||
DEPENDENCY_ALL(PrisonHeroPlacer);
|
||||
POSTFUNCTION(RoadPlacer);
|
||||
}
|
||||
|
||||
@ -90,6 +98,16 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
auto prisonTemplates = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0)->getTemplates(zone.getTerrainType());
|
||||
if (!prisonTemplates.empty())
|
||||
{
|
||||
PrisonHeroPlacer * prisonHeroPlacer = nullptr;
|
||||
for(auto & z : map.getZones())
|
||||
{
|
||||
prisonHeroPlacer = z.second->getModificator<PrisonHeroPlacer>();
|
||||
if (prisonHeroPlacer)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//prisons
|
||||
//levels 1, 5, 10, 20, 30
|
||||
static int prisonsLevels = std::min(generator.getConfig().prisonExperience.size(), generator.getConfig().prisonValues.size());
|
||||
@ -97,16 +115,22 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
size_t prisonsLeft = getMaxPrisons();
|
||||
for (int i = prisonsLevels - 1; i >= 0; i--)
|
||||
{
|
||||
ObjectInfo oi; // Create new instance which will hold destructor operation
|
||||
|
||||
oi.value = generator.getConfig().prisonValues[i];
|
||||
if (oi.value > zone.getMaxTreasureValue())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
oi.generateObject = [i, this]() -> CGObjectInstance*
|
||||
oi.generateObject = [i, this, prisonHeroPlacer, &oi]() -> CGObjectInstance*
|
||||
{
|
||||
auto possibleHeroes = generator.getAllPossibleHeroes();
|
||||
HeroTypeID hid = *RandomGeneratorUtil::nextItem(possibleHeroes, zone.getRand());
|
||||
HeroTypeID hid = prisonHeroPlacer->drawRandomHero();
|
||||
oi.destroyObject = [hid, prisonHeroPlacer]()
|
||||
{
|
||||
// Hero can be used again
|
||||
prisonHeroPlacer->restoreDrawnHero(hid);
|
||||
};
|
||||
|
||||
auto factory = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0);
|
||||
auto* obj = dynamic_cast<CGHeroInstance*>(factory->create());
|
||||
@ -114,7 +138,6 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
obj->setHeroType(hid); //will be initialized later
|
||||
obj->exp = generator.getConfig().prisonExperience[i];
|
||||
obj->setOwner(PlayerColor::NEUTRAL);
|
||||
generator.banHero(hid);
|
||||
|
||||
return obj;
|
||||
};
|
||||
@ -441,6 +464,19 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
|
||||
RandomGeneratorUtil::randomShuffle(creatures, zone.getRand());
|
||||
|
||||
auto setRandomArtifact = [qap, &oi](CGSeerHut * obj)
|
||||
{
|
||||
ArtifactID artid = qap->drawRandomArtifact();
|
||||
oi.destroyObject = [artid, qap]()
|
||||
{
|
||||
// Artifact can be used again
|
||||
qap->addRandomArtifact(artid);
|
||||
qap->removeQuestArtifact(artid);
|
||||
};
|
||||
obj->quest->mission.artifacts.push_back(artid);
|
||||
qap->addQuestArtifact(artid);
|
||||
};
|
||||
|
||||
for(int i = 0; i < static_cast<int>(creatures.size()); i++)
|
||||
{
|
||||
auto * creature = creatures[i];
|
||||
@ -451,7 +487,8 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
|
||||
int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType());
|
||||
|
||||
oi.generateObject = [creature, creaturesAmount, randomAppearance, this, qap]() -> CGObjectInstance *
|
||||
// FIXME: Remove duplicated code for gold, exp and creaure reward
|
||||
oi.generateObject = [creature, creaturesAmount, randomAppearance, setRandomArtifact]() -> CGObjectInstance *
|
||||
{
|
||||
auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
|
||||
auto * obj = dynamic_cast<CGSeerHut *>(factory->create());
|
||||
@ -461,11 +498,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
reward.visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
|
||||
obj->configuration.info.push_back(reward);
|
||||
|
||||
ArtifactID artid = qap->drawRandomArtifact();
|
||||
obj->quest->mission.artifacts.push_back(artid);
|
||||
|
||||
generator.banQuestArt(artid);
|
||||
zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
|
||||
setRandomArtifact(obj);
|
||||
|
||||
return obj;
|
||||
};
|
||||
@ -499,7 +532,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
oi.probability = 10;
|
||||
oi.maxPerZone = 1;
|
||||
|
||||
oi.generateObject = [i, randomAppearance, this, qap]() -> CGObjectInstance *
|
||||
oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> CGObjectInstance *
|
||||
{
|
||||
auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
|
||||
auto * obj = dynamic_cast<CGSeerHut *>(factory->create());
|
||||
@ -508,20 +541,16 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
reward.reward.heroExperience = generator.getConfig().questRewardValues[i];
|
||||
reward.visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
|
||||
obj->configuration.info.push_back(reward);
|
||||
|
||||
ArtifactID artid = qap->drawRandomArtifact();
|
||||
obj->quest->mission.artifacts.push_back(artid);
|
||||
|
||||
generator.banQuestArt(artid);
|
||||
zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
|
||||
|
||||
|
||||
setRandomArtifact(obj);
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
if(!oi.templates.empty())
|
||||
possibleSeerHuts.push_back(oi);
|
||||
|
||||
oi.generateObject = [i, randomAppearance, this, qap]() -> CGObjectInstance *
|
||||
oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> CGObjectInstance *
|
||||
{
|
||||
auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
|
||||
auto * obj = dynamic_cast<CGSeerHut *>(factory->create());
|
||||
@ -531,11 +560,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
reward.visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
|
||||
obj->configuration.info.push_back(reward);
|
||||
|
||||
ArtifactID artid = qap->drawRandomArtifact();
|
||||
obj->quest->mission.artifacts.push_back(artid);
|
||||
|
||||
generator.banQuestArt(artid);
|
||||
zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
|
||||
setRandomArtifact(obj);
|
||||
|
||||
return obj;
|
||||
};
|
||||
@ -641,8 +666,14 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
|
||||
}
|
||||
|
||||
auto * object = oi->generateObject();
|
||||
|
||||
if(oi->templates.empty())
|
||||
{
|
||||
logGlobal->warn("Deleting randomized object with no templates: %s", object->getObjectName());
|
||||
oi->destroyObject();
|
||||
delete object;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto templates = object->getObjectHandler()->getMostSpecificTemplates(zone.getTerrainType());
|
||||
|
||||
@ -721,7 +752,7 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
|
||||
instanceAccessibleArea.add(instance.getVisitablePosition());
|
||||
}
|
||||
|
||||
//first object is good
|
||||
//Do not clean up after first object
|
||||
if(rmgObject.instances().size() == 1)
|
||||
break;
|
||||
|
||||
@ -800,10 +831,10 @@ void TreasurePlacer::createTreasures(ObjectManager& manager)
|
||||
{
|
||||
for (auto* oi : treasurePile)
|
||||
{
|
||||
oi->destroyObject();
|
||||
oi->maxPerZone++;
|
||||
}
|
||||
};
|
||||
|
||||
//place biggest treasures first at large distance, place smaller ones inbetween
|
||||
auto treasureInfo = zone.getTreasureInfo();
|
||||
boost::sort(treasureInfo, valueComparator);
|
||||
|
@ -22,12 +22,15 @@ class CRandomGenerator;
|
||||
|
||||
struct ObjectInfo
|
||||
{
|
||||
ObjectInfo();
|
||||
|
||||
std::vector<std::shared_ptr<const ObjectTemplate>> templates;
|
||||
ui32 value = 0;
|
||||
ui16 probability = 0;
|
||||
ui32 maxPerZone = 1;
|
||||
//ui32 maxPerMap; //unused
|
||||
std::function<CGObjectInstance *()> generateObject;
|
||||
std::function<void()> destroyObject;
|
||||
|
||||
void setTemplates(MapObjectID type, MapObjectSubID subtype, TerrainId terrain);
|
||||
};
|
||||
|
@ -131,7 +131,12 @@ void MapController::repairMap(CMap * map) const
|
||||
//fix hero instance
|
||||
if(auto * nih = dynamic_cast<CGHeroInstance*>(obj.get()))
|
||||
{
|
||||
// All heroes present on map or in prisons need to be allowed to rehire them after they are defeated
|
||||
|
||||
// FIXME: How about custom scenarios where defeated hero cannot be hired again?
|
||||
|
||||
map->allowedHeroes.insert(nih->getHeroType());
|
||||
|
||||
auto type = VLC->heroh->objects[nih->subID];
|
||||
assert(type->heroClass);
|
||||
//TODO: find a way to get proper type name
|
||||
@ -198,8 +203,6 @@ void MapController::repairMap(CMap * map) const
|
||||
auto a = ArtifactUtils::createScroll(*RandomGeneratorUtil::nextItem(out, CRandomGenerator::getDefault()));
|
||||
art->storedArtifact = a;
|
||||
}
|
||||
else
|
||||
map->allowedArtifact.insert(art->getArtifact());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user