mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Spawn quest arts in nearby zones.
This commit is contained in:
@@ -241,6 +241,7 @@ void CMapGenerator::fillZones()
|
|||||||
it.second->initFreeTiles(this);
|
it.second->initFreeTiles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findZonesForQuestArts();
|
||||||
createConnections();
|
createConnections();
|
||||||
//make sure all connections are passable before creating borders
|
//make sure all connections are passable before creating borders
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
@@ -270,6 +271,26 @@ void CMapGenerator::fillZones()
|
|||||||
logGlobal->infoStream() << "Zones filled successfully";
|
logGlobal->infoStream() << "Zones filled successfully";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = connection.getZoneA();
|
||||||
|
auto zoneB = connection.getZoneB();
|
||||||
|
|
||||||
|
if (zoneA->getId() > zoneB->getId())
|
||||||
|
{
|
||||||
|
zoneB->setQuestArtZone(zoneA);
|
||||||
|
}
|
||||||
|
else if (zoneA->getId() < zoneB->getId())
|
||||||
|
{
|
||||||
|
zoneA->setQuestArtZone(zoneB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CMapGenerator::createConnections()
|
void CMapGenerator::createConnections()
|
||||||
{
|
{
|
||||||
for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
|
for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
|
||||||
|
@@ -64,6 +64,7 @@ public:
|
|||||||
|
|
||||||
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
|
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
|
||||||
void createConnections();
|
void createConnections();
|
||||||
|
void findZonesForQuestArts();
|
||||||
void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
||||||
|
|
||||||
bool isBlocked(const int3 &tile) const;
|
bool isBlocked(const int3 &tile) const;
|
||||||
|
@@ -144,7 +144,8 @@ CRmgTemplateZone::CRmgTemplateZone() :
|
|||||||
townType(ETownType::NEUTRAL),
|
townType(ETownType::NEUTRAL),
|
||||||
terrainType (ETerrainType::GRASS),
|
terrainType (ETerrainType::GRASS),
|
||||||
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
|
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
|
||||||
minGuardedValue(0)
|
minGuardedValue(0),
|
||||||
|
questArtZone(nullptr)
|
||||||
{
|
{
|
||||||
terrainTypes = getDefaultTerrainTypes();
|
terrainTypes = getDefaultTerrainTypes();
|
||||||
}
|
}
|
||||||
@@ -297,6 +298,11 @@ void CRmgTemplateZone::addConnection(TRmgTemplateZoneId otherZone)
|
|||||||
connections.push_back (otherZone);
|
connections.push_back (otherZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRmgTemplateZone::setQuestArtZone(CRmgTemplateZone * otherZone)
|
||||||
|
{
|
||||||
|
questArtZone = otherZone;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TRmgTemplateZoneId> CRmgTemplateZone::getConnections() const
|
std::vector<TRmgTemplateZoneId> CRmgTemplateZone::getConnections() const
|
||||||
{
|
{
|
||||||
return connections;
|
return connections;
|
||||||
@@ -2259,120 +2265,147 @@ void CRmgTemplateZone::addAllPossibleObjects(CMapGenerator* gen)
|
|||||||
|
|
||||||
//seer huts with creatures or generic rewards
|
//seer huts with creatures or generic rewards
|
||||||
|
|
||||||
static const int genericSeerHuts = 8;
|
if (questArtZone) //we won't be placing seer huts if there is no zone left to place arties
|
||||||
int seerHutsPerType = 0;
|
|
||||||
const int questArtsRemaining = gen->getQuestArtsRemaning().size();
|
|
||||||
|
|
||||||
std::vector<CCreature *> creatures;
|
|
||||||
|
|
||||||
for (auto cre : VLC->creh->creatures)
|
|
||||||
{
|
{
|
||||||
if (cre->faction == townType)
|
static const int genericSeerHuts = 8;
|
||||||
|
int seerHutsPerType = 0;
|
||||||
|
const int questArtsRemaining = gen->getQuestArtsRemaning().size();
|
||||||
|
|
||||||
|
std::vector<CCreature *> creatures;
|
||||||
|
|
||||||
|
for (auto cre : VLC->creh->creatures)
|
||||||
{
|
{
|
||||||
creatures.push_back(cre);
|
if (cre->faction == townType)
|
||||||
|
{
|
||||||
|
creatures.push_back(cre);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//general issue is that not many artifact types are available for quests
|
//general issue is that not many artifact types are available for quests
|
||||||
|
|
||||||
if (questArtsRemaining >= genericSeerHuts + creatures.size())
|
if (questArtsRemaining >= genericSeerHuts + creatures.size())
|
||||||
{
|
|
||||||
seerHutsPerType = questArtsRemaining / (genericSeerHuts + creatures.size());
|
|
||||||
}
|
|
||||||
else if (questArtsRemaining >= genericSeerHuts)
|
|
||||||
{
|
|
||||||
seerHutsPerType = 1;
|
|
||||||
}
|
|
||||||
oi.maxPerZone = seerHutsPerType;
|
|
||||||
|
|
||||||
RandomGeneratorUtil::randomShuffle(creatures, gen->rand);
|
|
||||||
|
|
||||||
for (int i = 0; i < std::min<int>(creatures.size(), questArtsRemaining - genericSeerHuts); i++)
|
|
||||||
{
|
|
||||||
auto creature = creatures[i];
|
|
||||||
int creaturesAmount = creatureToCount(creature);
|
|
||||||
|
|
||||||
if (!creaturesAmount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
|
|
||||||
|
|
||||||
oi.generateObject = [creature, creaturesAmount, randomAppearance, gen]() -> CGObjectInstance *
|
|
||||||
{
|
{
|
||||||
auto obj = new CGSeerHut();
|
seerHutsPerType = questArtsRemaining / (genericSeerHuts + creatures.size());
|
||||||
obj->ID = Obj::SEER_HUT;
|
}
|
||||||
obj->subID = randomAppearance;
|
else if (questArtsRemaining >= genericSeerHuts)
|
||||||
obj->rewardType = CGSeerHut::CREATURE;
|
|
||||||
obj->rID = creature->idNumber;
|
|
||||||
obj->rVal = creaturesAmount;
|
|
||||||
|
|
||||||
obj->quest->missionType = CQuest::MISSION_ART;
|
|
||||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
|
|
||||||
obj->quest->m5arts.push_back(artid);
|
|
||||||
gen->banQuestArt(artid);
|
|
||||||
gen->map->addQuest(obj);
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
//TODO: place required artifact in next zone
|
|
||||||
};
|
|
||||||
oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
|
|
||||||
oi.value = ((2 * (creature->AIValue) * creaturesAmount * (1 + (float)(gen->getZoneCount(creature->faction)) / gen->getTotalZoneCount())) - 4000) / 3;
|
|
||||||
oi.probability = 3;
|
|
||||||
possibleObjects.push_back(oi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int seerExpGold[] = { 5000, 10000, 15000, 20000 };
|
|
||||||
static int seerValues[] = { 2000, 5333, 8666, 12000};
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) //seems that code for exp and gold reward is similiar
|
|
||||||
{
|
|
||||||
int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
|
|
||||||
|
|
||||||
oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
|
|
||||||
oi.value = seerValues[i];
|
|
||||||
oi.probability = 10;
|
|
||||||
|
|
||||||
oi.generateObject = [i, randomAppearance, gen]() -> CGObjectInstance *
|
|
||||||
{
|
{
|
||||||
auto obj = new CGSeerHut();
|
seerHutsPerType = 1;
|
||||||
obj->ID = Obj::SEER_HUT;
|
}
|
||||||
obj->subID = randomAppearance;
|
oi.maxPerZone = seerHutsPerType;
|
||||||
obj->rewardType = CGSeerHut::EXPERIENCE;
|
|
||||||
obj->rID = 0; //unitialized?
|
|
||||||
obj->rVal = seerExpGold[i];
|
|
||||||
|
|
||||||
obj->quest->missionType = CQuest::MISSION_ART;
|
RandomGeneratorUtil::randomShuffle(creatures, gen->rand);
|
||||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
|
|
||||||
obj->quest->m5arts.push_back(artid);
|
|
||||||
gen->banQuestArt(artid);
|
|
||||||
gen->map->addQuest(obj);
|
|
||||||
|
|
||||||
return obj;
|
auto generateArtInfo = [](ArtifactID id) -> ObjectInfo
|
||||||
//TODO: place required artifact in next zone
|
{
|
||||||
|
ObjectInfo artInfo;
|
||||||
|
artInfo.probability = 1e6; //99,9% to spawn that art in first treasure pile
|
||||||
|
artInfo.maxPerZone = 1;
|
||||||
|
artInfo.value = 2000; //treasure art
|
||||||
|
artInfo.generateObject = [id]() -> CGObjectInstance *
|
||||||
|
{
|
||||||
|
auto obj = new CGArtifact;
|
||||||
|
obj->ID = Obj::ARTIFACT;
|
||||||
|
obj->subID = id;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
//TODO: place required artifact in next zone
|
||||||
|
};
|
||||||
|
return artInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
possibleObjects.push_back(oi);
|
for (int i = 0; i < std::min<int>(creatures.size(), questArtsRemaining - genericSeerHuts); i++)
|
||||||
|
|
||||||
oi.generateObject = [i, randomAppearance, gen]() -> CGObjectInstance *
|
|
||||||
{
|
{
|
||||||
auto obj = new CGSeerHut();
|
auto creature = creatures[i];
|
||||||
obj->ID = Obj::SEER_HUT;
|
int creaturesAmount = creatureToCount(creature);
|
||||||
obj->subID = randomAppearance;
|
|
||||||
obj->rewardType = CGSeerHut::RESOURCES;
|
|
||||||
obj->rID = Res::GOLD;
|
|
||||||
obj->rVal = seerExpGold[i];
|
|
||||||
|
|
||||||
obj->quest->missionType = CQuest::MISSION_ART;
|
if (!creaturesAmount)
|
||||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
|
continue;
|
||||||
obj->quest->m5arts.push_back(artid);
|
|
||||||
gen->banQuestArt(artid);
|
|
||||||
gen->map->addQuest(obj);
|
|
||||||
|
|
||||||
return obj;
|
int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
|
||||||
//TODO: place required artifact in next zone
|
|
||||||
};
|
|
||||||
|
|
||||||
possibleObjects.push_back(oi);
|
oi.generateObject = [creature, creaturesAmount, randomAppearance, gen, this, generateArtInfo]() -> CGObjectInstance *
|
||||||
|
{
|
||||||
|
auto obj = new CGSeerHut();
|
||||||
|
obj->ID = Obj::SEER_HUT;
|
||||||
|
obj->subID = randomAppearance;
|
||||||
|
obj->rewardType = CGSeerHut::CREATURE;
|
||||||
|
obj->rID = creature->idNumber;
|
||||||
|
obj->rVal = creaturesAmount;
|
||||||
|
|
||||||
|
obj->quest->missionType = CQuest::MISSION_ART;
|
||||||
|
ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
|
||||||
|
obj->quest->m5arts.push_back(artid);
|
||||||
|
gen->banQuestArt(artid);
|
||||||
|
gen->map->addQuest(obj);
|
||||||
|
|
||||||
|
this->questArtZone->possibleObjects.push_back (generateArtInfo(artid));
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
//TODO: place required artifact in next zone
|
||||||
|
};
|
||||||
|
oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
|
||||||
|
oi.value = ((2 * (creature->AIValue) * creaturesAmount * (1 + (float)(gen->getZoneCount(creature->faction)) / gen->getTotalZoneCount())) - 4000) / 3;
|
||||||
|
oi.probability = 3;
|
||||||
|
possibleObjects.push_back(oi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seerExpGold[] = { 5000, 10000, 15000, 20000 };
|
||||||
|
static int seerValues[] = { 2000, 5333, 8666, 12000 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) //seems that code for exp and gold reward is similiar
|
||||||
|
{
|
||||||
|
int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
|
||||||
|
|
||||||
|
oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
|
||||||
|
oi.value = seerValues[i];
|
||||||
|
oi.probability = 10;
|
||||||
|
|
||||||
|
oi.generateObject = [i, randomAppearance, gen, this, generateArtInfo]() -> CGObjectInstance *
|
||||||
|
{
|
||||||
|
auto obj = new CGSeerHut();
|
||||||
|
obj->ID = Obj::SEER_HUT;
|
||||||
|
obj->subID = randomAppearance;
|
||||||
|
obj->rewardType = CGSeerHut::EXPERIENCE;
|
||||||
|
obj->rID = 0; //unitialized?
|
||||||
|
obj->rVal = seerExpGold[i];
|
||||||
|
|
||||||
|
obj->quest->missionType = CQuest::MISSION_ART;
|
||||||
|
ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
|
||||||
|
obj->quest->m5arts.push_back(artid);
|
||||||
|
gen->banQuestArt(artid);
|
||||||
|
gen->map->addQuest(obj);
|
||||||
|
|
||||||
|
this->questArtZone->possibleObjects.push_back(generateArtInfo(artid));
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
//TODO: place required artifact in next zone
|
||||||
|
};
|
||||||
|
|
||||||
|
possibleObjects.push_back(oi);
|
||||||
|
|
||||||
|
oi.generateObject = [i, randomAppearance, gen, this, generateArtInfo]() -> CGObjectInstance *
|
||||||
|
{
|
||||||
|
auto obj = new CGSeerHut();
|
||||||
|
obj->ID = Obj::SEER_HUT;
|
||||||
|
obj->subID = randomAppearance;
|
||||||
|
obj->rewardType = CGSeerHut::RESOURCES;
|
||||||
|
obj->rID = Res::GOLD;
|
||||||
|
obj->rVal = seerExpGold[i];
|
||||||
|
|
||||||
|
obj->quest->missionType = CQuest::MISSION_ART;
|
||||||
|
ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
|
||||||
|
obj->quest->m5arts.push_back(artid);
|
||||||
|
gen->banQuestArt(artid);
|
||||||
|
gen->map->addQuest(obj);
|
||||||
|
|
||||||
|
this->questArtZone->possibleObjects.push_back(generateArtInfo(artid));
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
//TODO: place required artifact in next zone
|
||||||
|
};
|
||||||
|
|
||||||
|
possibleObjects.push_back(oi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -169,6 +169,7 @@ public:
|
|||||||
std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
|
std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
|
||||||
|
|
||||||
void addConnection(TRmgTemplateZoneId otherZone);
|
void addConnection(TRmgTemplateZoneId otherZone);
|
||||||
|
void setQuestArtZone(CRmgTemplateZone * otherZone);
|
||||||
std::vector<TRmgTemplateZoneId> getConnections() const;
|
std::vector<TRmgTemplateZoneId> getConnections() const;
|
||||||
void addTreasureInfo(CTreasureInfo & info);
|
void addTreasureInfo(CTreasureInfo & info);
|
||||||
std::vector<CTreasureInfo> getTreasureInfo();
|
std::vector<CTreasureInfo> getTreasureInfo();
|
||||||
@@ -194,6 +195,7 @@ private:
|
|||||||
|
|
||||||
si32 townType;
|
si32 townType;
|
||||||
ETerrainType terrainType;
|
ETerrainType terrainType;
|
||||||
|
CRmgTemplateZone * questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
|
||||||
|
|
||||||
EMonsterStrength::EMonsterStrength zoneMonsterStrength;
|
EMonsterStrength::EMonsterStrength zoneMonsterStrength;
|
||||||
std::vector<CTreasureInfo> treasureInfo;
|
std::vector<CTreasureInfo> treasureInfo;
|
||||||
|
Reference in New Issue
Block a user