1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Rmg water support (#745)

* RMG: water support and refactoring
* Fix seers hut bug
This commit is contained in:
Nordsoft91 2022-05-31 12:25:39 +03:00 committed by Andrii Danylchenko
parent b698f32557
commit 5c1a66ab69
15 changed files with 1065 additions and 283 deletions

View File

@ -86,7 +86,6 @@ set(lib_SRCS
rmg/CRmgTemplate.cpp rmg/CRmgTemplate.cpp
rmg/CRmgTemplateStorage.cpp rmg/CRmgTemplateStorage.cpp
rmg/CRmgTemplateZone.cpp rmg/CRmgTemplateZone.cpp
rmg/CZoneGraphGenerator.cpp
rmg/CZonePlacer.cpp rmg/CZonePlacer.cpp
serializer/BinaryDeserializer.cpp serializer/BinaryDeserializer.cpp
@ -292,7 +291,6 @@ set(lib_HEADERS
rmg/CRmgTemplate.h rmg/CRmgTemplate.h
rmg/CRmgTemplateStorage.h rmg/CRmgTemplateStorage.h
rmg/CRmgTemplateZone.h rmg/CRmgTemplateZone.h
rmg/CZoneGraphGenerator.h
rmg/CZonePlacer.h rmg/CZonePlacer.h
rmg/float3.h rmg/float3.h

View File

@ -255,6 +255,7 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain)
allowedTerrains.insert(ETerrainType((si32)i)); allowedTerrains.insert(ETerrainType((si32)i));
allowedTerrains.erase(ETerrainType::ROCK); allowedTerrains.erase(ETerrainType::ROCK);
allowedTerrains.erase(ETerrainType::WATER);
} }
if(withTerrain && allowedTerrains.empty()) if(withTerrain && allowedTerrains.empty())
@ -327,8 +328,8 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const
if(withTerrain) if(withTerrain)
{ {
//assumed that ROCK terrain not included //assumed that ROCK and WATER terrains are not included
if(allowedTerrains.size() < (GameConstants::TERRAIN_TYPES - 1)) if(allowedTerrains.size() < (GameConstants::TERRAIN_TYPES - 2))
{ {
JsonVector & data = node["allowedTerrains"].Vector(); JsonVector & data = node["allowedTerrains"].Vector();

View File

@ -14,6 +14,7 @@
#include "../mapping/CMap.h" #include "../mapping/CMap.h"
#include "CRmgTemplateStorage.h" #include "CRmgTemplateStorage.h"
#include "CRmgTemplate.h" #include "CRmgTemplate.h"
#include "CRandomGenerator.h"
#include "../VCMI_Lib.h" #include "../VCMI_Lib.h"
#include "../CTownHandler.h" #include "../CTownHandler.h"
@ -390,9 +391,39 @@ bool CMapGenOptions::checkOptions() const
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const
{ {
int3 tplSize(width, height, (hasTwoLevels ? 2 : 1)); int3 tplSize(width, height, (hasTwoLevels ? 2 : 1));
auto humanPlayers = countHumanPlayers();
auto templates = VLC->tplh->getTemplates();
vstd::erase_if(templates, [this, &tplSize, humanPlayers](const CRmgTemplate * tmpl)
{
if(!tmpl->matchesSize(tplSize))
return true;
if(!tmpl->isWaterContentAllowed(getWaterContent()))
return true;
if(getPlayerCount() != -1)
{
if (!tmpl->getPlayers().isInRange(getPlayerCount()))
return true;
}
else
{
// Human players shouldn't be banned when playing with random player count
if(humanPlayers > *boost::min_element(tmpl->getPlayers().getNumbers()))
return true;
}
if(compOnlyPlayerCount != -1)
{
if (!tmpl->getCpuPlayers().isInRange(compOnlyPlayerCount))
return true;
}
return false;
});
auto templates = VLC->tplh->getTemplates(tplSize, getPlayerCount(), countHumanPlayers(), compOnlyPlayerCount);
// Select tpl // Select tpl
if(templates.empty()) if(templates.empty())
return nullptr; return nullptr;

View File

@ -11,9 +11,9 @@
#pragma once #pragma once
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../CRandomGenerator.h"
class CRmgTemplate; class CRmgTemplate;
class CRandomGenerator;
namespace EWaterContent namespace EWaterContent
{ {

View File

@ -285,17 +285,41 @@ void CMapGenerator::genZones()
for(const auto & option : tmpl->getZones()) for(const auto & option : tmpl->getZones())
{ {
auto zone = std::make_shared<CRmgTemplateZone>(this); auto zone = std::make_shared<CRmgTemplateZone>(this);
zone->setOptions(option.second.get()); zone->setOptions(*option.second.get());
zones[zone->getId()] = zone; zones[zone->getId()] = zone;
} }
CZonePlacer placer(this); CZonePlacer placer(this);
placer.placeZones(&rand); placer.placeZones(&rand);
placer.assignZones(); placer.assignZones();
//add special zone for water
zoneWater.first = zones.size() + 1;
zoneWater.second = std::make_shared<CRmgTemplateZone>(this);
{
rmg::ZoneOptions options;
options.setId(zoneWater.first);
options.setType(ETemplateZoneType::WATER);
zoneWater.second->setOptions(options);
}
logGlobal->info("Zones generated successfully"); logGlobal->info("Zones generated successfully");
} }
void CMapGenerator::createWaterTreasures()
{
//add treasures on water
getZoneWater().second->addTreasureInfo(CTreasureInfo{100, 1000, 5});
getZoneWater().second->addTreasureInfo(CTreasureInfo{2000, 6000, 1});
}
void CMapGenerator::prepareWaterTiles()
{
for(auto & t : zoneWater.second->getTileInfo())
if(shouldBeBlocked(t))
setOccupied(t, ETileType::POSSIBLE);
}
void CMapGenerator::fillZones() void CMapGenerator::fillZones()
{ {
//init native town count with 0 //init native town count with 0
@ -308,41 +332,67 @@ void CMapGenerator::fillZones()
//we need info about all town types to evaluate dwellings and pandoras with creatures properly //we need info about all town types to evaluate dwellings and pandoras with creatures properly
//place main town in the middle //place main town in the middle
for (auto it : zones) for(auto it : zones)
it.second->initTownType(); it.second->initTownType();
//make sure there are some free tiles in the zone //make sure there are some free tiles in the zone
for (auto it : zones) for(auto it : zones)
it.second->initFreeTiles(); it.second->initFreeTiles();
createDirectConnections(); //direct for(auto it : zones)
//make sure all connections are passable before creating borders
for (auto it : zones)
it.second->createBorder(); //once direct connections are done it.second->createBorder(); //once direct connections are done
#ifdef _BETA
dump(false);
#endif
for(auto it : zones)
it.second->createWater(getMapGenOptions().getWaterContent());
zoneWater.second->waterInitFreeTiles();
#ifdef _BETA
dump(false);
#endif
createDirectConnections(); //direct
createConnections2(); //subterranean gates and monoliths createConnections2(); //subterranean gates and monoliths
for(auto it : zones)
zoneWater.second->waterConnection(*it.second);
createWaterTreasures();
zoneWater.second->initFreeTiles();
zoneWater.second->fill();
std::vector<std::shared_ptr<CRmgTemplateZone>> treasureZones; std::vector<std::shared_ptr<CRmgTemplateZone>> treasureZones;
for (auto it : zones) for(auto it : zones)
{ {
it.second->fill(); it.second->fill();
if (it.second->getType() == ETemplateZoneType::TREASURE) if (it.second->getType() == ETemplateZoneType::TREASURE)
treasureZones.push_back(it.second); treasureZones.push_back(it.second);
} }
#ifdef _BETA
dump(false);
#endif
//set apriopriate free/occupied tiles, including blocked underground rock //set apriopriate free/occupied tiles, including blocked underground rock
createObstaclesCommon1(); createObstaclesCommon1();
//set back original terrain for underground zones //set back original terrain for underground zones
for (auto it : zones) for(auto it : zones)
it.second->createObstacles1(); it.second->createObstacles1();
createObstaclesCommon2(); createObstaclesCommon2();
//place actual obstacles matching zone terrain //place actual obstacles matching zone terrain
for (auto it : zones) for(auto it : zones)
{
it.second->createObstacles2(); it.second->createObstacles2();
}
zoneWater.second->createObstacles2();
#ifdef _BETA
dump(false);
#endif
#define PRINT_MAP_BEFORE_ROADS false #define PRINT_MAP_BEFORE_ROADS false
if (PRINT_MAP_BEFORE_ROADS) //enable to debug if (PRINT_MAP_BEFORE_ROADS) //enable to debug
@ -379,15 +429,15 @@ void CMapGenerator::fillZones()
out << std::endl; out << std::endl;
} }
for (auto it : zones) for(auto it : zones)
{ {
it.second->connectRoads(); //draw roads after everything else has been placed it.second->connectRoads(); //draw roads after everything else has been placed
} }
//find place for Grail //find place for Grail
if (treasureZones.empty()) if(treasureZones.empty())
{ {
for (auto it : zones) for(auto it : zones)
treasureZones.push_back(it.second); treasureZones.push_back(it.second);
} }
auto grailZone = *RandomGeneratorUtil::nextItem(treasureZones, rand); auto grailZone = *RandomGeneratorUtil::nextItem(treasureZones, rand);
@ -503,30 +553,29 @@ void CMapGenerator::findZonesForQuestArts()
void CMapGenerator::createDirectConnections() void CMapGenerator::createDirectConnections()
{ {
bool waterMode = getMapGenOptions().getWaterContent() != EWaterContent::NONE;
for (auto connection : mapGenOptions.getMapTemplate()->getConnections()) for (auto connection : mapGenOptions.getMapTemplate()->getConnections())
{ {
auto zoneA = zones[connection.getZoneA()]; auto zoneA = zones[connection.getZoneA()];
auto zoneB = zones[connection.getZoneB()]; auto zoneB = zones[connection.getZoneB()];
//rearrange tiles in random order //rearrange tiles in random order
auto tilesCopy = zoneA->getTileInfo(); const auto & tiles = zoneA->getTileInfo();
std::vector<int3> tiles(tilesCopy.begin(), tilesCopy.end());
int3 guardPos(-1,-1,-1); int3 guardPos(-1,-1,-1);
auto otherZoneTiles = zoneB->getTileInfo();
int3 posA = zoneA->getPos(); int3 posA = zoneA->getPos();
int3 posB = zoneB->getPos(); int3 posB = zoneB->getPos();
// auto zoneAid = zoneA->getId(); // auto zoneAid = zoneA->getId();
auto zoneBid = zoneB->getId(); auto zoneBid = zoneB->getId();
if (posA.z == posB.z) if (posA.z == posB.z)
{ {
std::vector<int3> middleTiles; std::vector<int3> middleTiles;
for (auto tile : tilesCopy) for (const auto& tile : tiles)
{ {
if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed if (isUsed(tile) || getZoneID(tile)==zoneWater.first) //tiles may be occupied by towns or water
continue; continue;
foreachDirectNeighbour(tile, [tile, &middleTiles, this, zoneBid](int3 & pos) //must be direct since paths also also generated between direct neighbours foreachDirectNeighbour(tile, [tile, &middleTiles, this, zoneBid](int3 & pos) //must be direct since paths also also generated between direct neighbours
{ {
@ -559,8 +608,8 @@ void CMapGenerator::createDirectConnections()
if (guardPos.valid()) if (guardPos.valid())
{ {
//zones can make paths only in their own area //zones can make paths only in their own area
zoneA->connectWithCenter(guardPos, true); zoneA->connectWithCenter(guardPos, true, true);
zoneB->connectWithCenter(guardPos, true); zoneB->connectWithCenter(guardPos, true, true);
bool monsterPresent = zoneA->addMonster(guardPos, connection.getGuardStrength(), false, true); bool monsterPresent = zoneA->addMonster(guardPos, connection.getGuardStrength(), false, true);
zoneB->updateDistances(guardPos); //place next objects away from guard in both zones zoneB->updateDistances(guardPos); //place next objects away from guard in both zones
@ -575,9 +624,12 @@ void CMapGenerator::createDirectConnections()
} }
} }
} }
if (!guardPos.valid()) if (!guardPos.valid())
connectionsLeft.push_back(connection); {
if(!waterMode || posA.z != posB.z || !zoneWater.second->waterKeepConnection(connection.getZoneA(), connection.getZoneB()))
connectionsLeft.push_back(connection);
}
} }
} }
@ -865,3 +917,48 @@ ui32 CMapGenerator::getTotalZoneCount() const
{ {
return zonesTotal; return zonesTotal;
} }
CMapGenerator::Zones::value_type CMapGenerator::getZoneWater() const
{
return zoneWater;
}
void CMapGenerator::dump(bool zoneId)
{
static int id = 0;
std::ofstream out(boost::to_string(boost::format("zone_%d.txt") % id++));
int levels = map->twoLevel ? 2 : 1;
int width = map->width;
int height = map->height;
for (int k = 0; k < levels; k++)
{
for(int j=0; j<height; j++)
{
for (int i=0; i<width; i++)
{
if(zoneId)
{
out << getZoneID(int3(i, j, k));
}
else
{
char t = '?';
switch (getTile(int3(i, j, k)).getTileType())
{
case ETileType::FREE:
t = ' '; break;
case ETileType::BLOCKED:
t = '#'; break;
case ETileType::POSSIBLE:
t = '-'; break;
case ETileType::USED:
t = 'O'; break;
}
out << t;
}
}
out << std::endl;
}
out << std::endl;
}
out << std::endl;
}

View File

@ -26,6 +26,8 @@ class JsonNode;
class CMapGenerator; class CMapGenerator;
class CTileInfo; class CTileInfo;
//#define _BETA
typedef std::vector<JsonNode> JsonVector; typedef std::vector<JsonNode> JsonVector;
class rmgException : public std::exception class rmgException : public std::exception
@ -96,18 +98,26 @@ public:
void registerZone (TFaction faction); void registerZone (TFaction faction);
ui32 getZoneCount(TFaction faction); ui32 getZoneCount(TFaction faction);
ui32 getTotalZoneCount() const; ui32 getTotalZoneCount() const;
Zones::value_type getZoneWater() const;
void createWaterTreasures();
void prepareWaterTiles();
TRmgTemplateZoneId getZoneID(const int3& tile) const; TRmgTemplateZoneId getZoneID(const int3& tile) const;
void setZoneID(const int3& tile, TRmgTemplateZoneId zid); void setZoneID(const int3& tile, TRmgTemplateZoneId zid);
void dump(bool zoneId);
private: private:
int randomSeed; int randomSeed;
CMapGenOptions& mapGenOptions; CMapGenOptions& mapGenOptions;
std::list<rmg::ZoneConnection> connectionsLeft; std::vector<rmg::ZoneConnection> connectionsLeft;
Zones zones; Zones zones;
std::map<TFaction, ui32> zonesPerFaction; std::map<TFaction, ui32> zonesPerFaction;
ui32 zonesTotal; //zones that have their main town only ui32 zonesTotal; //zones that have their main town only
std::pair<Zones::key_type, Zones::mapped_type> zoneWater;
CTileInfo*** tiles; CTileInfo*** tiles;
boost::multi_array<TRmgTemplateZoneId, 3> zoneColouring; //[z][x][y] boost::multi_array<TRmgTemplateZoneId, 3> zoneColouring; //[z][x][y]

View File

@ -39,6 +39,12 @@ CTreasureInfo::CTreasureInfo()
} }
CTreasureInfo::CTreasureInfo(ui32 imin, ui32 imax, ui16 idensity)
: min(imin), max(imax), density(idensity)
{
}
bool CTreasureInfo::operator==(const CTreasureInfo & other) const bool CTreasureInfo::operator==(const CTreasureInfo & other) const
{ {
return (min == other.min) && (max == other.max) && (density == other.density); return (min == other.min) && (max == other.max) && (density == other.density);
@ -196,6 +202,11 @@ ETemplateZoneType::ETemplateZoneType ZoneOptions::getType() const
{ {
return type; return type;
} }
void ZoneOptions::setType(ETemplateZoneType::ETemplateZoneType value)
{
type = value;
}
int ZoneOptions::getSize() const int ZoneOptions::getSize() const
{ {
@ -264,6 +275,11 @@ void ZoneOptions::setTreasureInfo(const std::vector<CTreasureInfo> & value)
{ {
treasureInfo = value; treasureInfo = value;
} }
void ZoneOptions::addTreasureInfo(const CTreasureInfo & value)
{
treasureInfo.push_back(value);
}
const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const
{ {
@ -302,7 +318,8 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
"playerStart", "playerStart",
"cpuStart", "cpuStart",
"treasure", "treasure",
"junction" "junction",
"water"
}; };
handler.serializeEnum("type", type, zoneTypes); handler.serializeEnum("type", type, zoneTypes);
@ -421,6 +438,11 @@ bool CRmgTemplate::matchesSize(const int3 & value) const
return minSquare <= square && square <= maxSquare; return minSquare <= square && square <= maxSquare;
} }
bool CRmgTemplate::isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const
{
return waterContent == EWaterContent::EWaterContent::RANDOM || allowedWaterContent.count(waterContent);
}
void CRmgTemplate::setId(const std::string & value) void CRmgTemplate::setId(const std::string & value)
{ {
id = value; id = value;
@ -623,6 +645,14 @@ void CRmgTemplate::afterLoad()
zone1->addConnection(id2); zone1->addConnection(id2);
zone2->addConnection(id1); zone2->addConnection(id1);
} }
if(allowedWaterContent.empty() || allowedWaterContent.count(EWaterContent::EWaterContent::RANDOM))
{
allowedWaterContent.insert(EWaterContent::EWaterContent::NONE);
allowedWaterContent.insert(EWaterContent::EWaterContent::NORMAL);
allowedWaterContent.insert(EWaterContent::EWaterContent::ISLANDS);
}
allowedWaterContent.erase(EWaterContent::EWaterContent::RANDOM);
} }
void CRmgTemplate::serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName) void CRmgTemplate::serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName)

View File

@ -24,7 +24,8 @@ namespace ETemplateZoneType
PLAYER_START, PLAYER_START,
CPU_START, CPU_START,
TREASURE, TREASURE,
JUNCTION JUNCTION,
WATER
}; };
} }
@ -35,6 +36,7 @@ public:
ui32 max; ui32 max;
ui16 density; ui16 density;
CTreasureInfo(); CTreasureInfo();
CTreasureInfo(ui32 min, ui32 max, ui16 density);
bool operator ==(const CTreasureInfo & other) const; bool operator ==(const CTreasureInfo & other) const;
@ -93,6 +95,8 @@ public:
void setId(TRmgTemplateZoneId value); void setId(TRmgTemplateZoneId value);
ETemplateZoneType::ETemplateZoneType getType() const; ETemplateZoneType::ETemplateZoneType getType() const;
void setType(ETemplateZoneType::ETemplateZoneType value);
int getSize() const; int getSize() const;
void setSize(int value); void setSize(int value);
boost::optional<int> getOwner() const; boost::optional<int> getOwner() const;
@ -110,6 +114,7 @@ public:
std::map<TResource, ui16> getMinesInfo() const; std::map<TResource, ui16> getMinesInfo() const;
void setTreasureInfo(const std::vector<CTreasureInfo> & value); void setTreasureInfo(const std::vector<CTreasureInfo> & value);
void addTreasureInfo(const CTreasureInfo & value);
const std::vector<CTreasureInfo> & getTreasureInfo() const; const std::vector<CTreasureInfo> & getTreasureInfo() const;
TRmgTemplateZoneId getMinesLikeZone() const; TRmgTemplateZoneId getMinesLikeZone() const;
@ -175,6 +180,7 @@ public:
~CRmgTemplate(); ~CRmgTemplate();
bool matchesSize(const int3 & value) const; bool matchesSize(const int3 & value) const;
bool isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const;
void setId(const std::string & value); void setId(const std::string & value);
const std::string & getName() const; const std::string & getName() const;
@ -195,6 +201,7 @@ private:
CPlayerCountRange players, cpuPlayers; CPlayerCountRange players, cpuPlayers;
Zones zones; Zones zones;
std::vector<rmg::ZoneConnection> connections; std::vector<rmg::ZoneConnection> connections;
std::set<EWaterContent::EWaterContent> allowedWaterContent;
void afterLoad(); void afterLoad();
void serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName); void serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName);

View File

@ -68,36 +68,3 @@ std::vector<const CRmgTemplate *> CRmgTemplateStorage::getTemplates() const
} }
return result; return result;
} }
std::vector<const CRmgTemplate *> CRmgTemplateStorage::getTemplates(const int3& filterSize, si8 filterPlayers, si8 filterHumanPlayers, si8 filterCpuPlayers) const
{
std::vector<const CRmgTemplate *> result;
for(auto i=templates.cbegin(); i!=templates.cend(); ++i)
{
auto& tmpl = i->second;
if (!tmpl.matchesSize(filterSize))
continue;
if (filterPlayers != -1)
{
if (!tmpl.getPlayers().isInRange(filterPlayers))
continue;
}
else
{
// Human players shouldn't be banned when playing with random player count
if (filterHumanPlayers > *boost::min_element(tmpl.getPlayers().getNumbers()))
continue;
}
if(filterCpuPlayers != -1)
{
if (!tmpl.getCpuPlayers().isInRange(filterCpuPlayers))
continue;
}
result.push_back(&i->second);
}
return result;
}

View File

@ -29,9 +29,8 @@ public:
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override; virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override;
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override; virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
const CRmgTemplate * getTemplate(const std::string & templateName) const; const CRmgTemplate* getTemplate(const std::string & templateName) const;
std::vector<const CRmgTemplate *> getTemplates() const; std::vector<const CRmgTemplate *> getTemplates() const;
std::vector<const CRmgTemplate *> getTemplates(const int3& filterSize, si8 filterPlayers, si8 filterHumanPlayers, si8 filterCpuPlayers) const;
private: private:
std::map<std::string, CRmgTemplate> templates; std::map<std::string, CRmgTemplate> templates;

File diff suppressed because it is too large Load Diff

View File

@ -91,26 +91,29 @@ class DLL_LINKAGE CRmgTemplateZone : public rmg::ZoneOptions
public: public:
CRmgTemplateZone(CMapGenerator * Gen); CRmgTemplateZone(CMapGenerator * Gen);
void setOptions(const rmg::ZoneOptions * options); void setOptions(const rmg::ZoneOptions & options);
bool isUnderground() const; bool isUnderground() const;
float3 getCenter() const; float3 getCenter() const;
void setCenter(const float3 &f); void setCenter(const float3 &f);
int3 getPos() const; int3 getPos() const;
void setPos(const int3 &pos); void setPos(const int3 &pos);
bool isAccessibleFromAnywhere(ObjectTemplate &appearance, int3 &tile) const; bool isAccessibleFromSomewhere(ObjectTemplate & appearance, const int3 & tile) const;
int3 getAccessibleOffset(ObjectTemplate &appearance, int3 &tile) const; int3 getAccessibleOffset(ObjectTemplate & appearance, const int3 & tile) const;
void addTile (const int3 &pos); void addTile (const int3 & pos);
void removeTile(const int3 & pos);
void initFreeTiles (); void initFreeTiles ();
std::set<int3> getTileInfo() const; std::set<int3> getTileInfo() const;
std::set<int3> getPossibleTiles() const; std::set<int3> getPossibleTiles() const;
void discardDistantTiles (float distance); std::set<int3> collectDistantTiles (float distance) const;
void clearTiles(); void clearTiles();
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0); void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0); void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
void addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget); void addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget);
void addObjectAtPosition(CGObjectInstance * obj, const int3 & position, si32 guardStrength=0);
void addToConnectLater(const int3& src); void addToConnectLater(const int3& src);
bool addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false); bool addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
bool createTreasurePile(int3 &pos, float minDistance, const CTreasureInfo& treasureInfo); bool createTreasurePile(int3 &pos, float minDistance, const CTreasureInfo& treasureInfo);
@ -123,21 +126,35 @@ public:
void createBorder(); void createBorder();
void fractalize(); void fractalize();
void connectLater(); void connectLater();
EObjectPlacingResult::EObjectPlacingResult tryToPlaceObjectAndConnectToPath(CGObjectInstance *obj, int3 &pos); //return true if the position cna be connected EObjectPlacingResult::EObjectPlacingResult tryToPlaceObjectAndConnectToPath(CGObjectInstance * obj, const int3 & pos); //return true if the position can be connected
bool createRequiredObjects(); bool createRequiredObjects();
bool createShipyard(const int3 & pos, si32 guardStrength=0);
int3 createShipyard(const std::set<int3> & lake, si32 guardStrength=0);
bool makeBoat(TRmgTemplateZoneId land, const int3 & coast);
int3 makeBoat(TRmgTemplateZoneId land, const std::set<int3> & lake);
void createTreasures(); void createTreasures();
void createWater(EWaterContent::EWaterContent waterContent, bool debug=false);
void waterInitFreeTiles();
void waterConnection(CRmgTemplateZone& dst);
bool waterKeepConnection(TRmgTemplateZoneId zoneA, TRmgTemplateZoneId zoneB);
const std::set<int3>& getCoastTiles() const;
bool isWaterConnected(TRmgTemplateZoneId zone, const int3 & tile) const;
//void computeCoastTiles();
void createObstacles1(); void createObstacles1();
void createObstacles2(); void createObstacles2();
bool crunchPath(const int3 &src, const int3 &dst, bool onlyStraight, std::set<int3>* clearedTiles = nullptr); bool crunchPath(const int3 &src, const int3 &dst, bool onlyStraight, std::set<int3>* clearedTiles = nullptr);
bool connectPath(const int3& src, bool onlyStraight); bool connectPath(const int3& src, bool onlyStraight);
bool connectWithCenter(const int3& src, bool onlyStraight); bool connectWithCenter(const int3& src, bool onlyStraight, bool passTroughBlocked = false);
void updateDistances(const int3 & pos); void updateDistances(const int3 & pos);
std::vector<int3> getAccessibleOffsets (const CGObjectInstance* object); std::vector<int3> getAccessibleOffsets (const CGObjectInstance* object);
bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const; bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, const std::set<int3>& tilesBlockedByObject) const;
void setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone); void setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone);
std::set<int3>* getFreePaths(); std::set<int3>* getFreePaths();
void addFreePath(const int3 &);
ObjectInfo getRandomObject (CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue); ObjectInfo getRandomObject (CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
@ -160,9 +177,20 @@ public:
boost::heap::priority_queue<TDistance, boost::heap::compare<NodeComparer>> createPriorityQueue(); boost::heap::priority_queue<TDistance, boost::heap::compare<NodeComparer>> createPriorityQueue();
private: private:
//subclass to store disconnected parts of water zone
struct Lake
{
std::set<int3> tiles;
std::set<int3> coast;
std::map<int3, int> distance;
std::set<TRmgTemplateZoneId> connectedZones;
std::set<TRmgTemplateZoneId> keepConnections;
};
CMapGenerator * gen; CMapGenerator * gen;
//template info //template info
si32 townType; si32 townType;
ETerrainType terrainType; ETerrainType terrainType;
std::weak_ptr<CRmgTemplateZone> questArtZone; //artifacts required for Seer Huts will be placed here - or not if null std::weak_ptr<CRmgTemplateZone> questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
@ -173,8 +201,10 @@ private:
//content info //content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects; std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects; std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
std::vector<std::pair<CGObjectInstance*, int3>> instantObjects;
std::vector<std::pair<CGObjectInstance*, CGObjectInstance*>> nearbyObjects; std::vector<std::pair<CGObjectInstance*, CGObjectInstance*>> nearbyObjects;
std::vector<CGObjectInstance*> objects; std::vector<CGObjectInstance*> objects;
std::map<CGObjectInstance*, int3> requestedPositions;
//placement info //placement info
int3 pos; int3 pos;
@ -182,11 +212,14 @@ private:
std::set<int3> tileinfo; //irregular area assined to zone std::set<int3> tileinfo; //irregular area assined to zone
std::set<int3> possibleTiles; //optimization purposes for treasure generation std::set<int3> possibleTiles; //optimization purposes for treasure generation
std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
std::set<int3> coastTiles; //tiles bordered to water
std::set<int3> roadNodes; //tiles to be connected with roads std::set<int3> roadNodes; //tiles to be connected with roads
std::set<int3> roads; //all tiles with roads std::set<int3> roads; //all tiles with roads
std::set<int3> tilesToConnectLater; //will be connected after paths are fractalized std::set<int3> tilesToConnectLater; //will be connected after paths are fractalized
std::vector<Lake> lakes; //disconnected parts of zone. Used to work with water zones
std::map<int3, int> lakeMap; //map tile on lakeId which is position of lake in lakes array +1
bool createRoad(const int3 &src, const int3 &dst); bool createRoad(const int3 &src, const int3 &dst);
void drawRoads(); //actually updates tiles void drawRoads(); //actually updates tiles
@ -197,4 +230,6 @@ private:
bool canObstacleBePlacedHere(ObjectTemplate &temp, int3 &pos); bool canObstacleBePlacedHere(ObjectTemplate &temp, int3 &pos);
void setTemplateForObject(CGObjectInstance* obj); void setTemplateForObject(CGObjectInstance* obj);
void checkAndPlaceObject(CGObjectInstance* object, const int3 &pos); void checkAndPlaceObject(CGObjectInstance* object, const int3 &pos);
bool isGuardNeededForTreasure(int value);
}; };

View File

@ -1,33 +0,0 @@
/*
* CZoneGraphGenerator.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 "CZoneGraphGenerator.h"
CZoneCell::CZoneCell(const CRmgTemplateZone * zone)// : zone(zone)
{
}
CZoneGraph::CZoneGraph()
{
}
CZoneGraphGenerator::CZoneGraphGenerator()// : gen(nullptr)
{
}
std::unique_ptr<CZoneGraph> CZoneGraphGenerator::generate(const CMapGenOptions & options, CRandomGenerator * gen)
{
return make_unique<CZoneGraph>();
}

View File

@ -1,47 +0,0 @@
/*
* CZoneGraphGenerator.h, 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
class CRmgTemplateZone;
class CRandomGenerator;
class CMapGenOptions;
class CZoneCell
{
public:
explicit CZoneCell(const CRmgTemplateZone * zone);
private:
//const CRmgTemplateZone * zone;
//TODO additional data
};
class CZoneGraph
{
public:
CZoneGraph();
private:
//TODO zone graph storage
};
class CZoneGraphGenerator
{
public:
CZoneGraphGenerator();
std::unique_ptr<CZoneGraph> generate(const CMapGenOptions & options, CRandomGenerator * gen);
private:
std::unique_ptr<CZoneGraph> graph;
//CRandomGenerator * gen;
};

View File

@ -13,8 +13,7 @@
#include "CZonePlacer.h" #include "CZonePlacer.h"
#include "CRmgTemplateZone.h" #include "CRmgTemplateZone.h"
#include "../mapping/CMap.h" #include "../mapping/CMap.h"
#include "../mapping/CMapEditManager.h"
#include "CZoneGraphGenerator.h"
class CRandomGenerator; class CRandomGenerator;
@ -557,7 +556,11 @@ void CZonePlacer::assignZones()
if (zone.second->isUnderground()) if (zone.second->isUnderground())
{ {
if (!CREATE_FULL_UNDERGROUND) if (!CREATE_FULL_UNDERGROUND)
zone.second->discardDistantTiles((float)(zone.second->getSize() + 1)); {
auto discardTile = zone.second->collectDistantTiles((float)(zone.second->getSize() + 1));
for(auto& t : discardTile)
zone.second->removeTile(t);
}
//make sure that terrain inside zone is not a rock //make sure that terrain inside zone is not a rock
//FIXME: reorder actions? //FIXME: reorder actions?