1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-29 21:56:54 +02:00

Moved roads and rivers to TerrainTypeHandler, by analogy to TerrainType.

This commit is contained in:
Tomasz Zieliński 2022-09-23 16:24:01 +02:00
parent 6aaf77812b
commit ebe45d512d
20 changed files with 392 additions and 190 deletions

@ -135,22 +135,6 @@ EMapAnimRedrawStatus CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface
void CMapHandler::initTerrainGraphics()
{
static const std::map<std::string, std::string> ROAD_FILES =
{
{ROAD_NAMES[1], "dirtrd"},
{ROAD_NAMES[2], "gravrd"},
{ROAD_NAMES[3], "cobbrd"}
};
static const std::map<std::string, std::string> RIVER_FILES =
{
{RIVER_NAMES[1], "clrrvr"},
{RIVER_NAMES[2], "icyrvr"},
{RIVER_NAMES[3], "mudrvr"},
{RIVER_NAMES[4], "lavrvr"}
};
auto loadFlipped = [](TFlippedAnimations & animation, TFlippedCache & cache, const std::map<std::string, std::string> & files)
{
//no rotation and basic setup
@ -190,14 +174,24 @@ void CMapHandler::initTerrainGraphics()
//TODO: use if as a key
std::map<std::string, std::string> terrainFiles;
std::map<std::string, std::string> riverFiles;
std::map<std::string, std::string> roadFiles;
for(const auto * terrain : VLC->terrainTypeHandler->terrains())
{
terrainFiles[terrain->name] = terrain->tilesFilename;
}
for(const auto * river : VLC->terrainTypeHandler->rivers())
{
riverFiles[river->fileName] = river->fileName;
}
for(const auto * road : VLC->terrainTypeHandler->roads())
{
roadFiles[road->fileName] = road->fileName;
}
loadFlipped(terrainAnimations, terrainImages, terrainFiles);
loadFlipped(roadAnimations, roadImages, ROAD_FILES);
loadFlipped(riverAnimations, riverImages, RIVER_FILES);
loadFlipped(riverAnimations, riverImages, riverFiles);
loadFlipped(roadAnimations, roadImages, roadFiles);
// Create enough room for the whole map and its frame
@ -791,21 +785,21 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
void CMapHandler::CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const
{
if (tinfoUpper && tinfoUpper->roadType != ROAD_NAMES[0])
if (tinfoUpper && tinfoUpper->roadType->id != Road::NO_ROAD)
{
ui8 rotation = (tinfoUpper->extTileFlags >> 4) % 4;
Rect source(0, tileSize / 2, tileSize, tileSize / 2);
Rect dest(realPos.x, realPos.y, tileSize, tileSize / 2);
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType][tinfoUpper->roadDir][rotation],
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType->fileName][tinfoUpper->roadDir][rotation],
&source, targetSurf, &dest);
}
if(tinfo.roadType != ROAD_NAMES[0]) //print road from this tile
if(tinfo.roadType->id != Road::NO_ROAD) //print road from this tile
{
ui8 rotation = (tinfo.extTileFlags >> 4) % 4;
Rect source(0, 0, tileSize, halfTileSizeCeil);
Rect dest(realPos.x, realPos.y + tileSize / 2, tileSize, tileSize / 2);
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType][tinfo.roadDir][rotation],
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType->fileName][tinfo.roadDir][rotation],
&source, targetSurf, &dest);
}
}
@ -814,7 +808,7 @@ void CMapHandler::CMapBlitter::drawRiver(SDL_Surface * targetSurf, const Terrain
{
Rect destRect(realTileRect);
ui8 rotation = (tinfo.extTileFlags >> 2) % 4;
drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect);
drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType->fileName][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect);
}
void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const
@ -865,7 +859,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
if(isVisible || info->showAllTerrain)
{
drawTileTerrain(targetSurf, tinfo, tile);
if(tinfo.riverType != RIVER_NAMES[0])
if(tinfo.riverType->id != River::NO_RIVER)
drawRiver(targetSurf, tinfo);
drawRoad(targetSurf, tinfo, tinfoUpper);
}

@ -676,10 +676,6 @@ enum class ETeleportChannelType
MIXED
};
static std::vector<std::string> RIVER_NAMES {"", "rw", "ri", "rm", "rl"};
static std::vector<std::string> ROAD_NAMES {"", "pd", "pg", "pc"};
class Obj
{
public:
@ -855,6 +851,31 @@ namespace Terrain
};
}
namespace Road
{
enum ERoad : ui8
{
NO_ROAD = 0,
DIRT_ROAD = 1,
GRAVEL_ROAD = 2,
COBBLESTONE_ROAD = 3,
ORIGINAL_ROAD_COUNT = COBBLESTONE_ROAD
};
}
namespace River
{
enum ERiver : ui8
{
NO_RIVER = 0,
WATER_RIVER = 1,
ICY_RIVER = 2,
MUD_RIVER = 3,
LAVA_RIVER = 4,
ORIGINAL_RIVER_COUNT = LAVA_RIVER
};
}
namespace SecSkillLevel
{
enum SecSkillLevel
@ -1207,6 +1228,8 @@ typedef std::pair<si64, si64> TDmgRange;
typedef si32 TBonusSubtype;
typedef si32 TQuantity;
typedef si8 TTerrain;
typedef si8 TRoad;
typedef si8 TRiver;
typedef int TRmgTemplateZoneId;

@ -19,6 +19,9 @@
TerrainTypeHandler::TerrainTypeHandler()
{
initRivers();
initRoads();
auto allConfigs = VLC->modh->getActiveMods();
allConfigs.insert(allConfigs.begin(), "core");
@ -97,16 +100,16 @@ TerrainTypeHandler::TerrainTypeHandler()
if(terr.second["river"].isNull())
{
info->river = RIVER_NAMES[0];
info->river = River::NO_RIVER;
}
else
{
info->river = terr.second["river"].String();
info->river = getRiverByCode(terr.second["river"].String())->id;
}
if(terr.second["horseSoundId"].isNull())
{
info->horseSoundId = 9; //rock sound as default
info->horseSoundId = Terrain::ROCK; //rock sound as default
}
else
{
@ -191,6 +194,61 @@ TerrainTypeHandler::TerrainTypeHandler()
}
}
void TerrainTypeHandler::initRivers()
{
//TODO: load from file?
const std::vector<std::string> RIVER_DELTA_TEMPLATE_NAME
{
{""},
{"clrdelt"},
{"icedelt"},
{"muddelt"},
{"lavdelt"}
};
const std::vector<std::pair<std::string, std::string>> RIVER_CONSTANTS =
{
{"", ""},
{"clrrvr", "rw"},
{"icyrvr", "ri"},
{"mudrvr", "rm"},
{"lavrvr", "rl"}
};
for (size_t i = 0; i < std::size(RIVER_CONSTANTS); i++)
{
riverTypes.emplace_back(new RiverType(RIVER_CONSTANTS[i].first, RIVER_CONSTANTS[i].second, i));
riverTypes[i]->deltaName = RIVER_DELTA_TEMPLATE_NAME[i];
}
recreateRiverMaps();
}
void TerrainTypeHandler::initRoads()
{
//TODO: read from config
const std::vector<std::pair<std::string, std::string>> ROAD_CONSTANTS =
{
{"", ""},
{"dirtrd", "pd"},
{"gravrd", "pg"},
{"cobbrd", "pc"}
};
for (size_t i = 0; i < std::size(ROAD_CONSTANTS); i++)
{
roadTypes.emplace_back(new RoadType(ROAD_CONSTANTS[i].first, ROAD_CONSTANTS[i].second, i));
}
roadTypes[1]->movementCost = 75;
roadTypes[2]->movementCost = 65;
roadTypes[3]->movementCost = 50;
recreateRoadMaps();
}
void TerrainTypeHandler::recreateTerrainMaps()
{
for (const TerrainType * terrainInfo : objects)
@ -201,11 +259,41 @@ void TerrainTypeHandler::recreateTerrainMaps()
}
}
void TerrainTypeHandler::recreateRiverMaps()
{
for (const RiverType * riverInfo : riverTypes)
{
riverInfoByName[riverInfo->fileName] = riverInfo;
riverInfoByCode[riverInfo->code] = riverInfo;
riverInfoById[riverInfo->id] = riverInfo;
}
}
void TerrainTypeHandler::recreateRoadMaps()
{
for (const RoadType * roadInfo : roadTypes)
{
roadInfoByName[roadInfo->fileName] = roadInfo;
roadInfoByCode[roadInfo->code] = roadInfo;
roadInfoById[roadInfo->id] = roadInfo;
}
}
const std::vector<TerrainType *> & TerrainTypeHandler::terrains() const
{
return objects;
}
const std::vector<RiverType*>& TerrainTypeHandler::rivers() const
{
return riverTypes;
}
const std::vector<RoadType*>& TerrainTypeHandler::roads() const
{
return roadTypes;
}
const TerrainType* TerrainTypeHandler::getInfoByName(const std::string& terrainName) const
{
return terrainInfoByName.at(terrainName);
@ -221,6 +309,36 @@ const TerrainType* TerrainTypeHandler::getInfoById(TTerrain id) const
return terrainInfoById.at(id);
}
const RiverType* TerrainTypeHandler::getRiverByName(const std::string& riverName) const
{
return riverInfoByName.at(riverName);
}
const RiverType* TerrainTypeHandler::getRiverByCode(const std::string& riverCode) const
{
return riverInfoByCode.at(riverCode);
}
const RiverType* TerrainTypeHandler::getRiverById(TRiver id) const
{
return riverInfoById.at(id);
}
const RoadType* TerrainTypeHandler::getRoadByName(const std::string& roadName) const
{
return roadInfoByName.at(roadName);
}
const RoadType* TerrainTypeHandler::getRoadByCode(const std::string& roadCode) const
{
return roadInfoByCode.at(roadCode);
}
const RoadType* TerrainTypeHandler::getRoadById(TRoad id) const
{
return roadInfoById.at(id);
}
std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType)
{
return os << static_cast<const std::string &>(terrainType);
@ -293,3 +411,18 @@ bool TerrainType::isTransitionRequired() const
{
return transitionRequired;
}
RiverType::RiverType(const std::string & fileName, const std::string & code, TRiver id):
fileName(fileName),
code(code),
id(id)
{
}
RoadType::RoadType(const std::string& fileName, const std::string& code, TRoad id):
fileName(fileName),
code(code),
id(id),
movementCost(GameConstants::BASE_MOVEMENT_COST)
{
}

@ -38,7 +38,7 @@ public:
std::string terrainText;
std::string typeCode;
std::string terrainViewPatterns;
std::string river;
TRiver river;
TTerrain id;
TTerrain rockTerrain;
@ -87,6 +87,45 @@ public:
}
};
class DLL_LINKAGE RiverType
{
public:
std::string fileName;
std::string code;
std::string deltaName;
TRiver id;
RiverType(const std::string & fileName = "", const std::string& code = "", TRiver id = River::NO_RIVER);
template <typename Handler> void serialize(Handler& h, const int version)
{
h & fileName;
h & code;
h & deltaName;
h & id;
}
};
class DLL_LINKAGE RoadType
{
public:
std::string fileName;
std::string code;
TRoad id;
ui8 movementCost;
RoadType(const std::string & fileName = "", const std::string& code = "", TRoad id = Road::NO_ROAD);
template <typename Handler> void serialize(Handler& h, const int version)
{
h & fileName;
h & code;
h & id;
h & movementCost;
}
};
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType);
class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ?
@ -94,32 +133,58 @@ class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ?
public:
TerrainTypeHandler();
void initRivers();
void initRoads();
const std::vector<TerrainType *> & terrains() const;
const TerrainType * getInfoByName(const std::string & terrainName) const;
const TerrainType * getInfoByCode(const std::string & terrainCode) const;
const TerrainType * getInfoById(TTerrain id) const;
//TODO: road, river types?
const std::vector<RiverType *> & rivers() const;
const RiverType * getRiverByName(const std::string & riverName) const;
const RiverType * getRiverByCode(const std::string & riverCode) const;
const RiverType * getRiverById(TRiver id) const;
const std::vector<RoadType *> & roads() const;
const RoadType * getRoadByName(const std::string & roadName) const;
const RoadType * getRoadByCode(const std::string & roadCode) const;
const RoadType * getRoadById(TRoad id) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & objects;
h & riverTypes;
h & roadTypes;
if (!h.saving)
{
recreateTerrainMaps();
recreateRiverMaps();
recreateRoadMaps();
}
}
private:
std::vector<TerrainType *> objects;
std::vector<RiverType *> riverTypes;
std::vector<RoadType *> roadTypes;
std::unordered_map<std::string, const TerrainType*> terrainInfoByName;
std::unordered_map<std::string, const TerrainType*> terrainInfoByCode;
std::unordered_map<TTerrain, const TerrainType*> terrainInfoById;
std::unordered_map<std::string, const RiverType*> riverInfoByName;
std::unordered_map<std::string, const RiverType*> riverInfoByCode;
std::unordered_map<TRiver, const RiverType*> riverInfoById;
std::unordered_map<std::string, const RoadType*> roadInfoByName;
std::unordered_map<std::string, const RoadType*> roadInfoByCode;
std::unordered_map<TRoad, const RoadType*> roadInfoById;
void recreateTerrainMaps();
void recreateRiverMaps();
void recreateRoadMaps();
};

@ -79,24 +79,9 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f
int64_t ret = GameConstants::BASE_MOVEMENT_COST;
//if there is road both on dest and src tiles - use road movement cost
if(dest.roadType != ROAD_NAMES[0] && from.roadType != ROAD_NAMES[0])
if(dest.roadType->id && from.roadType->id)
{
int roadPos = std::min(vstd::find_pos(ROAD_NAMES, dest.roadType), vstd::find_pos(ROAD_NAMES, from.roadType)); //used road ID
switch(roadPos)
{
case 1:
ret = 75;
break;
case 2:
ret = 65;
break;
case 3:
ret = 50;
break;
default:
logGlobal->error("Unknown road type: %d", roadPos);
break;
}
ret = std::max(dest.roadType->movementCost, from.roadType->movementCost);
}
else if(ti->nativeTerrain != from.terType->id &&//the terrain is not native
ti->nativeTerrain != Terrain::ANY_TERRAIN && //no special creature bonus

@ -156,14 +156,14 @@ CDrawLinesOperation::CDrawLinesOperation(CMap * map, const CTerrainSelection & t
}
///CDrawRoadsOperation
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen):
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen):
CDrawLinesOperation(map, terrainSel,gen),
roadType(roadType)
{
}
///CDrawRiversOperation
CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & riverType, CRandomGenerator * gen):
CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRiver riverType, CRandomGenerator * gen):
CDrawLinesOperation(map, terrainSel, gen),
riverType(riverType)
{
@ -336,12 +336,12 @@ std::string CDrawRiversOperation::getLabel() const
void CDrawRoadsOperation::executeTile(TerrainTile & tile)
{
tile.roadType = roadType;
tile.roadType = VLC->terrainTypeHandler->roads()[roadType];
}
void CDrawRiversOperation::executeTile(TerrainTile & tile)
{
tile.riverType = riverType;
tile.riverType = VLC->terrainTypeHandler->rivers()[riverType];
}
bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const
@ -356,22 +356,22 @@ bool CDrawRiversOperation::canApplyPattern(const LinePattern & pattern) const
bool CDrawRoadsOperation::needUpdateTile(const TerrainTile & tile) const
{
return tile.roadType != ROAD_NAMES[0];
return tile.roadType->id != Road::NO_ROAD;
}
bool CDrawRiversOperation::needUpdateTile(const TerrainTile & tile) const
{
return tile.riverType != RIVER_NAMES[0];
return tile.riverType->id != River::NO_RIVER;
}
bool CDrawRoadsOperation::tileHasSomething(const int3& pos) const
{
return map->getTile(pos).roadType != ROAD_NAMES[0];
return map->getTile(pos).roadType->id != Road::NO_ROAD;
}
bool CDrawRiversOperation::tileHasSomething(const int3& pos) const
{
return map->getTile(pos).riverType != RIVER_NAMES[0];
return map->getTile(pos).riverType->id != River::NO_RIVER;
}
void CDrawRoadsOperation::updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip)

@ -61,7 +61,7 @@ protected:
class CDrawRoadsOperation : public CDrawLinesOperation
{
public:
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen);
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen);
std::string getLabel() const override;
protected:
@ -72,13 +72,13 @@ protected:
void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
private:
std::string roadType;
TRoad roadType;
};
class CDrawRiversOperation : public CDrawLinesOperation
{
public:
CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen);
CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen);
std::string getLabel() const override;
protected:
@ -89,5 +89,5 @@ protected:
void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
private:
std::string riverType;
TRiver riverType;
};

@ -126,15 +126,14 @@ CCastleEvent::CCastleEvent() : town(nullptr)
TerrainTile::TerrainTile():
terType(nullptr),
terView(0),
riverType(RIVER_NAMES[0]),
riverDir(0),
roadType(ROAD_NAMES[0]),
roadDir(0),
extTileFlags(0),
visitable(false),
blocked(false)
{
riverType = VLC->terrainTypeHandler->rivers()[0];
roadType = VLC->terrainTypeHandler->roads()[0];
}
bool TerrainTile::entrableTerrain(const TerrainTile * from) const

@ -82,9 +82,9 @@ struct DLL_LINKAGE TerrainTile
TerrainType * terType;
ui8 terView;
std::string riverType;
RiverType * riverType;
ui8 riverDir;
std::string roadType; //TODO: switch to ui8
RoadType * roadType;
ui8 roadDir;
/// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road);
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect

@ -130,13 +130,13 @@ void CMapEditManager::drawTerrain(TTerrain terType, CRandomGenerator * gen)
terrainSel.clearSelection();
}
void CMapEditManager::drawRoad(const std::string & roadType, CRandomGenerator* gen)
void CMapEditManager::drawRoad(TRoad roadType, CRandomGenerator* gen)
{
execute(make_unique<CDrawRoadsOperation>(map, terrainSel, roadType, gen ? gen : &(this->gen)));
terrainSel.clearSelection();
}
void CMapEditManager::drawRiver(const std::string & riverType, CRandomGenerator* gen)
void CMapEditManager::drawRiver(TRiver riverType, CRandomGenerator* gen)
{
execute(make_unique<CDrawRiversOperation>(map, terrainSel, riverType, gen ? gen : &(this->gen)));
terrainSel.clearSelection();

@ -73,10 +73,10 @@ public:
void drawTerrain(TTerrain terType, CRandomGenerator * gen = nullptr);
/// Draws roads at the current terrain selection. The selection will be cleared automatically.
void drawRoad(const std::string & roadType, CRandomGenerator * gen = nullptr);
void drawRoad(TRoad roadType, CRandomGenerator * gen = nullptr);
/// Draws rivers at the current terrain selection. The selection will be cleared automatically.
void drawRiver(const std::string & riverType, CRandomGenerator * gen = nullptr);
void drawRiver(TRiver riverType, CRandomGenerator * gen = nullptr);
void insertObject(CGObjectInstance * obj);
void insertObjects(std::set<CGObjectInstance *> & objects);

@ -922,16 +922,13 @@ void CMapLoaderH3M::readTerrain()
{
map->initTerrain();
const auto terrains = VLC->terrainTypeHandler->terrains();
const auto rivers = VLC->terrainTypeHandler->rivers();
const auto roads = VLC->terrainTypeHandler->roads();
// Read terrain
int3 pos;
for(pos.z = 0; pos.z < 2; ++pos.z)
for(pos.z = 0; pos.z < map->levels(); ++pos.z)
{
if(pos.z == 1 && !map->twoLevel)
{
break;
}
//OH3 format is [z][y][x]
for(pos.y = 0; pos.y < map->height; pos.y++)
{
@ -940,9 +937,9 @@ void CMapLoaderH3M::readTerrain()
auto & tile = map->getTile(pos);
tile.terType = terrains[reader.readUInt8()];
tile.terView = reader.readUInt8();
tile.riverType = RIVER_NAMES[reader.readUInt8()];
tile.riverType = rivers[reader.readUInt8()];
tile.riverDir = reader.readUInt8();
tile.roadType = ROAD_NAMES[reader.readUInt8()];
tile.roadType = roads[reader.readUInt8()];
tile.roadDir = reader.readUInt8();
tile.extTileFlags = reader.readUInt8();
tile.blocked = ((!tile.terType->isPassable() || tile.terType->id == Terrain::BORDER ) ? true : false); //underground tiles are always blocked

@ -942,96 +942,107 @@ void CMapLoaderJson::readHeader(const bool complete)
void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile)
{
using namespace TerrainDetail;
{//terrain type
const std::string typeCode = src.substr(0, 2);
tile.terType = const_cast<TerrainType *>(VLC->terrainTypeHandler->getInfoByCode(typeCode));
}
int startPos = 2; //0+typeCode fixed length
{//terrain view
int pos = startPos;
while(isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if(len<=0)
throw std::runtime_error("Invalid terrain view in "+src);
const std::string rawCode = src.substr(startPos, len);
tile.terView = atoi(rawCode.c_str());
startPos+=len;
}
{//terrain flip
int terrainFlip = vstd::find_pos(flipCodes, src.at(startPos++));
if(terrainFlip < 0)
throw std::runtime_error("Invalid terrain flip in "+src);
else
tile.extTileFlags = terrainFlip;
}
if(startPos >= src.size())
return;
bool hasRoad = true;
{//road type
const std::string typeCode = src.substr(startPos, 2);
startPos+=2;
if(vstd::find_pos(ROAD_NAMES, typeCode) < 0)
{
if(vstd::find_pos(RIVER_NAMES, typeCode) < 0)
throw std::runtime_error("Invalid river type in "+src);
else
{
tile.riverType = typeCode;
hasRoad = false;
}
try
{
using namespace TerrainDetail;
{//terrain type
const std::string typeCode = src.substr(0, 2);
tile.terType = const_cast<TerrainType*>(VLC->terrainTypeHandler->getInfoByCode(typeCode));
}
int startPos = 2; //0+typeCode fixed length
{//terrain view
int pos = startPos;
while (isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if (len <= 0)
throw std::runtime_error("Invalid terrain view in " + src);
const std::string rawCode = src.substr(startPos, len);
tile.terView = atoi(rawCode.c_str());
startPos += len;
}
{//terrain flip
int terrainFlip = vstd::find_pos(flipCodes, src.at(startPos++));
if (terrainFlip < 0)
throw std::runtime_error("Invalid terrain flip in " + src);
else
tile.extTileFlags = terrainFlip;
}
if (startPos >= src.size())
return;
bool hasRoad = true;
//FIXME: check without exceptions?
{//road type
const std::string typeCode = src.substr(startPos, 2);
startPos += 2;
try
{
tile.roadType = const_cast<RoadType*>(VLC->terrainTypeHandler->getRoadByCode(typeCode));
}
catch (const std::exception& e) //it's not a road, it's a river
{
try
{
tile.riverType = const_cast<RiverType*>(VLC->terrainTypeHandler->getRiverByCode(typeCode));
hasRoad = false;
}
catch (const std::exception& e)
{
throw std::runtime_error("Invalid river type in " + src);
}
}
}
if (hasRoad)
{//road dir
int pos = startPos;
while (isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if (len <= 0)
throw std::runtime_error("Invalid road dir in " + src);
const std::string rawCode = src.substr(startPos, len);
tile.roadDir = atoi(rawCode.c_str());
startPos += len;
}
if (hasRoad)
{//road flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if (flip < 0)
throw std::runtime_error("Invalid road flip in " + src);
else
tile.extTileFlags |= (flip << 4);
}
if (startPos >= src.size())
return;
if (hasRoad)
{//river type
const std::string typeCode = src.substr(startPos, 2);
startPos += 2;
tile.riverType = const_cast<RiverType*>(VLC->terrainTypeHandler->getRiverByCode(typeCode));
}
{//river dir
int pos = startPos;
while (isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if (len <= 0)
throw std::runtime_error("Invalid river dir in " + src);
const std::string rawCode = src.substr(startPos, len);
tile.riverDir = atoi(rawCode.c_str());
startPos += len;
}
{//river flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if (flip < 0)
throw std::runtime_error("Invalid road flip in " + src);
else
tile.extTileFlags |= (flip << 2);
}
else
tile.roadType = typeCode;
}
if(hasRoad)
{//road dir
int pos = startPos;
while(isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if(len<=0)
throw std::runtime_error("Invalid road dir in "+src);
const std::string rawCode = src.substr(startPos, len);
tile.roadDir = atoi(rawCode.c_str());
startPos+=len;
}
if(hasRoad)
{//road flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if(flip < 0)
throw std::runtime_error("Invalid road flip in "+src);
else
tile.extTileFlags |= (flip<<4);
}
if(startPos >= src.size())
return;
if(hasRoad)
{//river type
const std::string typeCode = src.substr(startPos, 2);
startPos+=2;
if(vstd::find_pos(RIVER_NAMES, typeCode) < 0)
throw std::runtime_error("Invalid river type in "+src);
tile.riverType = typeCode;
}
{//river dir
int pos = startPos;
while(isdigit(src.at(pos)))
pos++;
int len = pos - startPos;
if(len<=0)
throw std::runtime_error("Invalid river dir in "+src);
const std::string rawCode = src.substr(startPos, len);
tile.riverDir = atoi(rawCode.c_str());
startPos+=len;
}
{//river flip
int flip = vstd::find_pos(flipCodes, src.at(startPos++));
if(flip < 0)
throw std::runtime_error("Invalid road flip in "+src);
else
tile.extTileFlags |= (flip<<2);
catch (const std::exception & e)
{
logGlobal->error("Failed to read terrain tile: %s");
}
}
@ -1278,10 +1289,10 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile)
out << tile.terType->typeCode << (int)tile.terView << flipCodes[tile.extTileFlags % 4];
if(tile.roadType != ROAD_NAMES[0])
if(tile.roadType->id != Road::NO_ROAD)
out << tile.roadType << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4];
if(tile.riverType != RIVER_NAMES[0])
if(tile.riverType->id != River::NO_RIVER)
out << tile.riverType << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4];
return out.str();

@ -135,7 +135,6 @@ void initTerrainType(Zone & zone, CMapGenerator & gen)
}
//Now, replace disallowed terrains on surface and in the underground
//TODO: allow new types of terrain?
const auto* terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()];
if(zone.isUnderground())

@ -22,15 +22,9 @@
#include "WaterProxy.h"
#include "RoadPlacer.h"
//TODO: move to Obj:: ?
const int RIVER_DELTA_ID = 143;
const int RIVER_DELTA_SUBTYPE = 0;
const std::map<std::string, std::string> RIVER_DELTA_TEMPLATE_NAME
{
{RIVER_NAMES[1], "clrdelt"},
{RIVER_NAMES[2], "icedelt"},
{RIVER_NAMES[3], "muddelt"},
{RIVER_NAMES[4], "lavdelt"}
};
const std::array<std::array<int, 25>, 4> deltaTemplates
{
@ -238,7 +232,7 @@ void RiverPlacer::preprocess()
deltaOrientations[p] = templateId + 1;
//specific case: deltas for ice rivers amd mud rivers are messed :(
if(river == RIVER_NAMES[2])
if(river == River::ICY_RIVER)
{
switch(deltaOrientations[p])
{
@ -256,7 +250,7 @@ void RiverPlacer::preprocess()
break;
}
}
if(river == RIVER_NAMES[3])
if(river == River::MUD_RIVER)
{
switch(deltaOrientations[p])
{
@ -326,8 +320,9 @@ void RiverPlacer::preprocess()
void RiverPlacer::connectRiver(const int3 & tile)
{
auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river;
if(river.empty() || river == RIVER_NAMES[0])
auto riverType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river;
auto river = VLC->terrainTypeHandler->rivers()[riverType];
if(river->id == River::NO_RIVER)
return;
rmg::Area roads;
@ -386,7 +381,7 @@ void RiverPlacer::connectRiver(const int3 & tile)
if(tmplates.size() % 4 != 0)
throw rmgException(boost::to_string(boost::format("River templates for (%d,%d) at terrain %s, river %s are incorrect") % RIVER_DELTA_ID % RIVER_DELTA_SUBTYPE % zone.getTerrainType() % river));
std::string targetTemplateName = RIVER_DELTA_TEMPLATE_NAME.at(river) + std::to_string(deltaOrientations[pos]) + ".def";
std::string targetTemplateName = river->deltaName + std::to_string(deltaOrientations[pos]) + ".def";
for(auto & templ : tmplates)
{
if(templ->animationFile == targetTemplateName)

@ -229,7 +229,7 @@ void RmgMap::setOccupied(const int3 &tile, ETileType::ETileType state)
tiles[tile.x][tile.y][tile.z].setOccupied(state);
}
void RmgMap::setRoad(const int3& tile, const std::string & roadType)
void RmgMap::setRoad(const int3& tile, TRoad roadType)
{
assertOnMap(tile);

@ -44,7 +44,7 @@ public:
bool isOnMap(const int3 & tile) const;
void setOccupied(const int3 &tile, ETileType::ETileType state);
void setRoad(const int3 &tile, const std::string & roadType);
void setRoad(const int3 &tile, TRoad roadType);
TileInfo getTile(const int3 & tile) const;

@ -69,7 +69,8 @@ void RoadPlacer::drawRoads(bool secondary)
zone.areaPossible().subtract(roads);
zone.freePaths().unite(roads);
map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector());
std::string roadType = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType);
std::string roadCode = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType);
TRoad roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id;
map.getEditManager()->drawRoad(roadType, &generator.rand);
}

@ -44,7 +44,7 @@ bool TileInfo::isFree() const
bool TileInfo::isRoad() const
{
return roadType != ROAD_NAMES[0];
return roadType != Road::NO_ROAD;
}
bool TileInfo::isUsed() const
@ -71,8 +71,8 @@ void TileInfo::setTerrainType(TTerrain type)
terrain = type;
}
void TileInfo::setRoadType(const std::string & value)
void TileInfo::setRoadType(TRoad type)
{
roadType = value;
roadType = type;
// setOccupied(ETileType::FREE);
}

@ -32,10 +32,10 @@ public:
ETileType::ETileType getTileType() const;
void setTerrainType(TTerrain value);
void setRoadType(const std::string & value);
void setRoadType(TRoad type);
private:
float nearestObjectDistance;
ETileType::ETileType occupied;
TTerrain terrain;
std::string roadType;
TRoad roadType;
};