mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
- Unban hero if related Prison is destroyed during map generation
- Move prison counter to PrisonHeroPlacer
This commit is contained in:
@ -650,10 +650,17 @@ void CMap::banWaterHeroes()
|
|||||||
void CMap::banHero(const HeroTypeID & id)
|
void CMap::banHero(const HeroTypeID & id)
|
||||||
{
|
{
|
||||||
if (!vstd::contains(allowedHeroes, id))
|
if (!vstd::contains(allowedHeroes, id))
|
||||||
logGlobal->warn("Attempt to ban hero %d, who is already not allowed", id.encode(id));
|
logGlobal->warn("Attempt to ban hero %s, who is already not allowed", id.encode(id));
|
||||||
allowedHeroes.erase(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()
|
void CMap::initTerrain()
|
||||||
{
|
{
|
||||||
terrain.resize(boost::extents[levels()][width][height]);
|
terrain.resize(boost::extents[levels()][width][height]);
|
||||||
|
@ -112,6 +112,7 @@ public:
|
|||||||
void banWaterArtifacts();
|
void banWaterArtifacts();
|
||||||
void banWaterHeroes();
|
void banWaterHeroes();
|
||||||
void banHero(const HeroTypeID& id);
|
void banHero(const HeroTypeID& id);
|
||||||
|
void unbanHero(const HeroTypeID & id);
|
||||||
void banWaterSpells();
|
void banWaterSpells();
|
||||||
void banWaterSkills();
|
void banWaterSkills();
|
||||||
void banWaterContent();
|
void banWaterContent();
|
||||||
|
@ -35,7 +35,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) :
|
CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) :
|
||||||
mapGenOptions(mapGenOptions), randomSeed(RandomSeed),
|
mapGenOptions(mapGenOptions), randomSeed(RandomSeed),
|
||||||
allowedPrisons(0), monolithIndex(0)
|
monolithIndex(0)
|
||||||
{
|
{
|
||||||
loadConfig();
|
loadConfig();
|
||||||
rand.setSeed(this->randomSeed);
|
rand.setSeed(this->randomSeed);
|
||||||
@ -96,12 +96,6 @@ const CMapGenOptions& CMapGenerator::getMapGenOptions() const
|
|||||||
return mapGenOptions;
|
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()
|
void CMapGenerator::initQuestArtsRemaining()
|
||||||
{
|
{
|
||||||
//TODO: Move to QuestArtifactPlacer?
|
//TODO: Move to QuestArtifactPlacer?
|
||||||
@ -122,7 +116,6 @@ std::unique_ptr<CMap> CMapGenerator::generate()
|
|||||||
addHeaderInfo();
|
addHeaderInfo();
|
||||||
map->initTiles(*this, rand);
|
map->initTiles(*this, rand);
|
||||||
Load::Progress::step();
|
Load::Progress::step();
|
||||||
initPrisonsRemaining();
|
|
||||||
initQuestArtsRemaining();
|
initQuestArtsRemaining();
|
||||||
genZones();
|
genZones();
|
||||||
Load::Progress::step();
|
Load::Progress::step();
|
||||||
@ -468,11 +461,6 @@ int CMapGenerator::getNextMonlithIndex()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CMapGenerator::getPrisonsRemaning() const
|
|
||||||
{
|
|
||||||
return allowedPrisons;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CZonePlacer> CMapGenerator::getZonePlacer() const
|
std::shared_ptr<CZonePlacer> CMapGenerator::getZonePlacer() const
|
||||||
{
|
{
|
||||||
return placer;
|
return placer;
|
||||||
@ -514,6 +502,12 @@ void CMapGenerator::banHero(const HeroTypeID & id)
|
|||||||
map->getMap(this).banHero(id);
|
map->getMap(this).banHero(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMapGenerator::unbanHero(const HeroTypeID & id)
|
||||||
|
{
|
||||||
|
map->getMap(this).unbanHero(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Zone * CMapGenerator::getZoneWater() const
|
Zone * CMapGenerator::getZoneWater() const
|
||||||
{
|
{
|
||||||
for(auto & z : map->getZones())
|
for(auto & z : map->getZones())
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
const std::vector<HeroTypeID> getAllPossibleHeroes() const;
|
const std::vector<HeroTypeID> getAllPossibleHeroes() const;
|
||||||
void banQuestArt(const ArtifactID & id);
|
void banQuestArt(const ArtifactID & id);
|
||||||
void banHero(const HeroTypeID& id);
|
void banHero(const HeroTypeID& id);
|
||||||
|
void unbanHero(const HeroTypeID & id);
|
||||||
|
|
||||||
Zone * getZoneWater() const;
|
Zone * getZoneWater() const;
|
||||||
void addWaterTreasuresInfo();
|
void addWaterTreasuresInfo();
|
||||||
@ -82,7 +83,6 @@ private:
|
|||||||
|
|
||||||
std::vector<rmg::ZoneConnection> connectionsLeft;
|
std::vector<rmg::ZoneConnection> connectionsLeft;
|
||||||
|
|
||||||
int allowedPrisons;
|
|
||||||
int monolithIndex;
|
int monolithIndex;
|
||||||
std::vector<ArtifactID> questArtifacts;
|
std::vector<ArtifactID> questArtifacts;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "../RmgMap.h"
|
#include "../RmgMap.h"
|
||||||
#include "../CMapGenerator.h"
|
#include "../CMapGenerator.h"
|
||||||
#include "TreasurePlacer.h"
|
#include "TreasurePlacer.h"
|
||||||
|
#include "PrisonHeroPlacer.h"
|
||||||
#include "QuestArtifactPlacer.h"
|
#include "QuestArtifactPlacer.h"
|
||||||
#include "TownPlacer.h"
|
#include "TownPlacer.h"
|
||||||
#include "TerrainPainter.h"
|
#include "TerrainPainter.h"
|
||||||
@ -145,7 +146,18 @@ void ObjectDistributor::distributePrisons()
|
|||||||
|
|
||||||
RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
|
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--)
|
for (int i = zones.size() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
auto zone = zones[i].second;
|
auto zone = zones[i].second;
|
||||||
|
@ -28,17 +28,30 @@ void PrisonHeroPlacer::process()
|
|||||||
|
|
||||||
void PrisonHeroPlacer::init()
|
void PrisonHeroPlacer::init()
|
||||||
{
|
{
|
||||||
|
// Reserve at least 16 heroes for each player
|
||||||
|
reservedHeroes = 16 * generator.getMapGenOptions().getHumanOrCpuPlayerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrisonHeroPlacer::getAllowedHeroes()
|
void PrisonHeroPlacer::getAllowedHeroes()
|
||||||
{
|
{
|
||||||
allowedHeroes = generator.getAllPossibleHeroes();
|
// 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()
|
HeroTypeID PrisonHeroPlacer::drawRandomHero()
|
||||||
{
|
{
|
||||||
RecursiveLock lock(externalAccessMutex);
|
RecursiveLock lock(externalAccessMutex);
|
||||||
if (!allowedHeroes.empty())
|
if (getPrisonsRemaning() > 0)
|
||||||
{
|
{
|
||||||
RandomGeneratorUtil::randomShuffle(allowedHeroes, zone.getRand());
|
RandomGeneratorUtil::randomShuffle(allowedHeroes, zone.getRand());
|
||||||
HeroTypeID ret = allowedHeroes.back();
|
HeroTypeID ret = allowedHeroes.back();
|
||||||
@ -53,4 +66,10 @@ HeroTypeID PrisonHeroPlacer::drawRandomHero()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrisonHeroPlacer::unbanHero(const HeroTypeID & hid)
|
||||||
|
{
|
||||||
|
RecursiveLock lock(externalAccessMutex);
|
||||||
|
generator.unbanHero(hid);
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -25,16 +25,17 @@ public:
|
|||||||
void process() override;
|
void process() override;
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
|
int getPrisonsRemaning() const;
|
||||||
HeroTypeID drawRandomHero();
|
HeroTypeID drawRandomHero();
|
||||||
|
void unbanHero(const HeroTypeID & hid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void getAllowedHeroes();
|
void getAllowedHeroes();
|
||||||
|
size_t reservedHeroes;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::vector<HeroTypeID> allowedHeroes;
|
std::vector<HeroTypeID> allowedHeroes;
|
||||||
|
|
||||||
// TODO: Count allowed heroes?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
@ -33,6 +33,12 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
ObjectInfo::ObjectInfo():
|
||||||
|
destroyObject([](){})
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void TreasurePlacer::process()
|
void TreasurePlacer::process()
|
||||||
{
|
{
|
||||||
addAllPossibleObjects();
|
addAllPossibleObjects();
|
||||||
@ -109,17 +115,23 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
size_t prisonsLeft = getMaxPrisons();
|
size_t prisonsLeft = getMaxPrisons();
|
||||||
for (int i = prisonsLevels - 1; i >= 0; i--)
|
for (int i = prisonsLevels - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
ObjectInfo oi; // Create new instance which will hold destructor operation
|
||||||
|
|
||||||
oi.value = generator.getConfig().prisonValues[i];
|
oi.value = generator.getConfig().prisonValues[i];
|
||||||
if (oi.value > zone.getMaxTreasureValue())
|
if (oi.value > zone.getMaxTreasureValue())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
oi.generateObject = [i, this, prisonHeroPlacer]() -> CGObjectInstance*
|
oi.generateObject = [i, this, prisonHeroPlacer, &oi]() -> CGObjectInstance*
|
||||||
{
|
{
|
||||||
auto possibleHeroes = generator.getAllPossibleHeroes();
|
auto possibleHeroes = generator.getAllPossibleHeroes();
|
||||||
|
|
||||||
HeroTypeID hid = prisonHeroPlacer->drawRandomHero();
|
HeroTypeID hid = prisonHeroPlacer->drawRandomHero();
|
||||||
|
oi.destroyObject = [hid, prisonHeroPlacer]()
|
||||||
|
{
|
||||||
|
prisonHeroPlacer->unbanHero(hid);
|
||||||
|
};
|
||||||
|
|
||||||
auto factory = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0);
|
auto factory = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0);
|
||||||
auto* obj = dynamic_cast<CGHeroInstance*>(factory->create());
|
auto* obj = dynamic_cast<CGHeroInstance*>(factory->create());
|
||||||
@ -654,9 +666,8 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
|
|||||||
if(oi->templates.empty())
|
if(oi->templates.empty())
|
||||||
{
|
{
|
||||||
logGlobal->warn("Deleting randomized object with no templates: %s", object->getObjectName());
|
logGlobal->warn("Deleting randomized object with no templates: %s", object->getObjectName());
|
||||||
// Possible memory leak, but this is a weird case in first place
|
oi->destroyObject();
|
||||||
delete object;
|
delete object;
|
||||||
// FIXME: We also lose randomized hero or quest artifact
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,6 +827,7 @@ void TreasurePlacer::createTreasures(ObjectManager& manager)
|
|||||||
{
|
{
|
||||||
for (auto* oi : treasurePile)
|
for (auto* oi : treasurePile)
|
||||||
{
|
{
|
||||||
|
oi->destroyObject();
|
||||||
oi->maxPerZone++;
|
oi->maxPerZone++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -22,12 +22,15 @@ class CRandomGenerator;
|
|||||||
|
|
||||||
struct ObjectInfo
|
struct ObjectInfo
|
||||||
{
|
{
|
||||||
|
ObjectInfo::ObjectInfo();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<const ObjectTemplate>> templates;
|
std::vector<std::shared_ptr<const ObjectTemplate>> templates;
|
||||||
ui32 value = 0;
|
ui32 value = 0;
|
||||||
ui16 probability = 0;
|
ui16 probability = 0;
|
||||||
ui32 maxPerZone = 1;
|
ui32 maxPerZone = 1;
|
||||||
//ui32 maxPerMap; //unused
|
//ui32 maxPerMap; //unused
|
||||||
std::function<CGObjectInstance *()> generateObject;
|
std::function<CGObjectInstance *()> generateObject;
|
||||||
|
std::function<void()> destroyObject;
|
||||||
|
|
||||||
void setTemplates(MapObjectID type, MapObjectSubID subtype, TerrainId terrain);
|
void setTemplates(MapObjectID type, MapObjectSubID subtype, TerrainId terrain);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user