1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Converted terrainTypeHandler into proper handler class

This commit is contained in:
Ivan Savenko 2022-12-20 16:14:06 +02:00
parent 01811317f9
commit 1468f6aded
43 changed files with 410 additions and 590 deletions

View File

@ -94,30 +94,29 @@ CSoundHandler::CSoundHandler():
//TODO: support custom sounds for new terrains and load from json
horseSounds =
{
{Terrain::DIRT, soundBase::horseDirt},
{Terrain::SAND, soundBase::horseSand},
{Terrain::GRASS, soundBase::horseGrass},
{Terrain::SNOW, soundBase::horseSnow},
{Terrain::SWAMP, soundBase::horseSwamp},
{Terrain::ROUGH, soundBase::horseRough},
{Terrain::SUBTERRANEAN, soundBase::horseSubterranean},
{Terrain::LAVA, soundBase::horseLava},
{Terrain::WATER, soundBase::horseWater},
{Terrain::ROCK, soundBase::horseRock}
{TerrainId::DIRT, soundBase::horseDirt},
{TerrainId::SAND, soundBase::horseSand},
{TerrainId::GRASS, soundBase::horseGrass},
{TerrainId::SNOW, soundBase::horseSnow},
{TerrainId::SWAMP, soundBase::horseSwamp},
{TerrainId::ROUGH, soundBase::horseRough},
{TerrainId::SUBTERRANEAN, soundBase::horseSubterranean},
{TerrainId::LAVA, soundBase::horseLava},
{TerrainId::WATER, soundBase::horseWater},
{TerrainId::ROCK, soundBase::horseRock}
};
}
void CSoundHandler::loadHorseSounds()
{
const auto & terrains = CGI->terrainTypeHandler->terrains();
for(const auto & terrain : terrains)
for(const auto & terrain : CGI->terrainTypeHandler->objects)
{
//since all sounds are hardcoded, let's keep it
if(vstd::contains(horseSounds, terrain.id))
if(vstd::contains(horseSounds, terrain->id))
continue;
//Use already existing horse sound
horseSounds[terrain.id] = horseSounds.at(terrains[terrain.id].horseSoundId);
horseSounds[terrain->id] = horseSounds.at(static_cast<TerrainId>(CGI->terrainTypeHandler->getById(terrain->id)->horseSoundId));
}
}
@ -368,9 +367,9 @@ CMusicHandler::CMusicHandler():
void CMusicHandler::loadTerrainMusicThemes()
{
for (const auto & terrain : CGI->terrainTypeHandler->terrains())
for (const auto & terrain : CGI->terrainTypeHandler->objects)
{
addEntryToSet("terrain_" + terrain.name, "Music/" + terrain.musicFilename);
addEntryToSet("terrain_" + terrain->name, "Music/" + terrain->musicFilename);
}
}

View File

@ -2372,7 +2372,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
for (auto & elem : path.nodes)
elem.coord = h->convertFromVisitablePos(elem.coord);
TerrainId currentTerrain = Terrain::BORDER; // not init yet
TerrainId currentTerrain = TerrainId::BORDER; // not init yet
TerrainId newTerrain;
int sh = -1;

View File

@ -175,17 +175,17 @@ void CMapHandler::initTerrainGraphics()
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())
for(const auto & terrain : VLC->terrainTypeHandler->objects)
{
terrainFiles[terrain.name] = terrain.tilesFilename;
terrainFiles[terrain->name] = terrain->tilesFilename;
}
for(const auto & river : VLC->terrainTypeHandler->rivers())
for(const auto & river : VLC->riverTypeHandler->objects)
{
riverFiles[river.fileName] = river.fileName;
riverFiles[river->fileName] = river->fileName;
}
for(const auto & road : VLC->terrainTypeHandler->roads())
for(const auto & road : VLC->roadTypeHandler->objects)
{
roadFiles[road.fileName] = road.fileName;
roadFiles[road->fileName] = road->fileName;
}
loadFlipped(terrainAnimations, terrainImages, terrainFiles);
@ -1388,8 +1388,8 @@ void CMapHandler::getTerrainDescr(const int3 & pos, std::string & out, bool isRM
break;
}
}
if(!isTile2Terrain || out.empty())
out = CGI->generaltexth->terrainNames[t.terType->id];
VLC->terrainTypeHandler->getById(t.terType->id)->terrainText;
if(t.getDiggingStatus(false) == EDiggingStatus::CAN_DIG)
{

View File

@ -499,25 +499,25 @@ std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
{
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > ret;
for(const auto & terrain : CGI->terrainTypeHandler->terrains())
for(const auto & terrain : CGI->terrainTypeHandler->objects)
{
SDL_Color normal =
{
ui8(terrain.minimapUnblocked[0]),
ui8(terrain.minimapUnblocked[1]),
ui8(terrain.minimapUnblocked[2]),
ui8(terrain->minimapUnblocked[0]),
ui8(terrain->minimapUnblocked[1]),
ui8(terrain->minimapUnblocked[2]),
ui8(255)
};
SDL_Color blocked =
{
ui8(terrain.minimapBlocked[0]),
ui8(terrain.minimapBlocked[1]),
ui8(terrain.minimapBlocked[2]),
ui8(terrain->minimapBlocked[0]),
ui8(terrain->minimapBlocked[1]),
ui8(terrain->minimapBlocked[2]),
ui8(255)
};
ret[terrain.id] = std::make_pair(normal, blocked);
ret[terrain->id] = std::make_pair(normal, blocked);
}
return ret;
}

View File

@ -1,7 +1,7 @@
{
"dirt" :
{
"originalTerrainId": 0,
"index": 0,
"moveCost" : 100,
"minimapUnblocked" : [ 82, 56, 8 ],
"minimapBlocked" : [ 57, 40, 8 ],
@ -15,7 +15,7 @@
},
"sand" :
{
"originalTerrainId": 1,
"index": 1,
"moveCost" : 150,
"minimapUnblocked" : [ 222, 207, 140 ],
"minimapBlocked" : [ 165, 158, 107 ],
@ -30,7 +30,7 @@
},
"grass" :
{
"originalTerrainId": 2,
"index": 2,
"moveCost" : 100,
"minimapUnblocked" : [ 0, 65, 0 ],
"minimapBlocked" : [ 0, 48, 0 ],
@ -43,7 +43,7 @@
},
"snow" :
{
"originalTerrainId": 3,
"index": 3,
"moveCost" : 150,
"minimapUnblocked" : [ 181, 199, 198 ],
"minimapBlocked" : [ 140, 158, 156 ],
@ -56,7 +56,7 @@
},
"swamp" :
{
"originalTerrainId": 4,
"index": 4,
"moveCost" : 175,
"minimapUnblocked" : [ 74, 134, 107 ],
"minimapBlocked" : [ 33, 89, 66 ],
@ -69,7 +69,7 @@
},
"rough" :
{
"originalTerrainId": 5,
"index": 5,
"moveCost" : 125,
"minimapUnblocked" : [ 132, 113, 49 ],
"minimapBlocked" : [ 99, 81, 33 ],
@ -82,7 +82,7 @@
},
"subterra" :
{
"originalTerrainId": 6,
"index": 6,
"moveCost" : 100,
"minimapUnblocked" : [ 132, 48, 0 ],
"minimapBlocked" : [ 90, 8, 0 ],
@ -97,7 +97,7 @@
},
"lava" :
{
"originalTerrainId": 7,
"index": 7,
"moveCost" : 100,
"minimapUnblocked" : [ 74, 73, 74 ],
"minimapBlocked" : [ 41, 40, 41 ],
@ -112,7 +112,7 @@
},
"water" :
{
"originalTerrainId": 8,
"index": 8,
"moveCost" : 100,
"minimapUnblocked" : [ 8, 81, 148 ],
"minimapBlocked" : [ 8, 81, 148 ],
@ -130,7 +130,7 @@
},
"rock" :
{
"originalTerrainId": 9,
"index": 9,
"moveCost" : -1,
"minimapUnblocked" : [ 0, 0, 0 ],
"minimapBlocked" : [ 0, 0, 0 ],

View File

@ -288,7 +288,7 @@ std::string CCreature::nodeName() const
bool CCreature::isItNativeTerrain(TerrainId terrain) const
{
auto native = getNativeTerrain();
return native == terrain || native == Terrain::ANY_TERRAIN;
return native == terrain || native == TerrainId::ANY_TERRAIN;
}
TerrainId CCreature::getNativeTerrain() const
@ -299,7 +299,7 @@ TerrainId CCreature::getNativeTerrain() const
//this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses
//and in the CGHeroInstance::getNativeTerrain() to setup mevement bonuses or/and penalties.
return hasBonus(selectorNoTerrainPenalty, selectorNoTerrainPenalty)
? TerrainId(Terrain::ANY_TERRAIN)
? TerrainId(TerrainId::ANY_TERRAIN)
: (*VLC->townh)[faction]->nativeTerrain;
}

View File

@ -343,7 +343,6 @@ CGeneralTextHandler::CGeneralTextHandler():
advobtxt (*this, "core.advevent" ),
xtrainfo (*this, "core.xtrainfo" ),
restypes (*this, "core.restypes" ),
terrainNames (*this, "core.terrname" ),
randsign (*this, "core.randsign" ),
overview (*this, "core.overview" ),
arraytxt (*this, "core.arraytxt" ),
@ -372,7 +371,6 @@ CGeneralTextHandler::CGeneralTextHandler():
readToVector("core.advevent", "DATA/ADVEVENT.TXT" );
readToVector("core.xtrainfo", "DATA/XTRAINFO.TXT" );
readToVector("core.restypes", "DATA/RESTYPES.TXT" );
readToVector("core.terrname", "DATA/TERRNAME.TXT" );
readToVector("core.randsign", "DATA/RANDSIGN.TXT" );
readToVector("core.overview", "DATA/OVERVIEW.TXT" );
readToVector("core.arraytxt", "DATA/ARRAYTXT.TXT" );

View File

@ -207,7 +207,6 @@ public:
LegacyTextContainer advobtxt;
LegacyTextContainer xtrainfo;
LegacyTextContainer restypes; //names of resources
LegacyTextContainer terrainNames;
LegacyTextContainer randsign;
LegacyTextContainer seerEmpty;
LegacyTextContainer seerNames;

View File

@ -345,11 +345,6 @@ CHeroHandler::~CHeroHandler() = default;
CHeroHandler::CHeroHandler()
{
loadTerrains();
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
{
VLC->modh->identifiers.registerObject(CModHandler::scopeBuiltin(), "terrain", terrain.name, terrain.id);
}
loadBallistics();
loadExperience();
}
@ -972,14 +967,6 @@ ui64 CHeroHandler::reqExp (ui32 level) const
}
}
void CHeroHandler::loadTerrains()
{
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
{
terrCosts[terrain.id] = terrain.moveCost;
}
}
std::vector<bool> CHeroHandler::getDefaultAllowed() const
{
// Look Data/HOTRAITS.txt for reference

View File

@ -260,7 +260,6 @@ class DLL_LINKAGE CHeroHandler : public CHandlerBase<HeroTypeID, HeroType, CHero
void loadExperience();
void loadBallistics();
void loadTerrains();
public:
CHeroClassHandler classes;

View File

@ -465,6 +465,9 @@ void CContentHandler::init()
handlers.insert(std::make_pair("scripts", ContentTypeHandler(VLC->scriptHandler, "script")));
#endif
handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler, "battlefield")));
handlers.insert(std::make_pair("terrains", ContentTypeHandler(VLC->terrainTypeHandler, "terrain")));
handlers.insert(std::make_pair("rivers", ContentTypeHandler(VLC->riverTypeHandler, "river")));
handlers.insert(std::make_pair("roads", ContentTypeHandler(VLC->roadTypeHandler, "road")));
handlers.insert(std::make_pair("obstacles", ContentTypeHandler(VLC->obstacleHandler, "obstacle")));
//TODO: any other types of moddables?
}

View File

@ -1000,10 +1000,10 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const
TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl)
{
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
for(const auto & terrain : VLC->terrainTypeHandler->objects)
{
noTerrainPenalty.push_back(static_cast<bool>(
bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(terrain.id)))));
bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(terrain->id)))));
}
freeShipBoarding = static_cast<bool>(bl->getFirst(Selector::type()(Bonus::FREE_SHIP_BOARDING)));

View File

@ -333,7 +333,7 @@ bool CStack::canBeHealed() const
bool CStack::isOnNativeTerrain() const
{
//this code is called from CreatureTerrainLimiter::limit on battle start
auto res = nativeTerrain == Terrain::ANY_TERRAIN || nativeTerrain == battle->getTerrainType();
auto res = nativeTerrain == TerrainId::ANY_TERRAIN || nativeTerrain == battle->getTerrainType();
return res;
}

View File

@ -28,9 +28,9 @@ VCMI_LIB_NAMESPACE_BEGIN
const int NAMES_PER_TOWN=16; // number of town names per faction in H3 files. Json can define any number
const TerrainId CTownHandler::defaultGoodTerrain(Terrain::GRASS);
const TerrainId CTownHandler::defaultEvilTerrain(Terrain::LAVA);
const TerrainId CTownHandler::defaultNeutralTerrain(Terrain::ROUGH);
const TerrainId CTownHandler::defaultGoodTerrain(TerrainId::GRASS);
const TerrainId CTownHandler::defaultEvilTerrain(TerrainId::LAVA);
const TerrainId CTownHandler::defaultNeutralTerrain(TerrainId::ROUGH);
const std::map<std::string, CBuilding::EBuildMode> CBuilding::MODES =
{

View File

@ -830,29 +830,6 @@ public:
ID_LIKE_OPERATORS(Obj, Obj::EObj)
namespace Terrain
{
enum ETerrain : si8
{
NATIVE_TERRAIN = -4,
ANY_TERRAIN = -3,
WRONG = -2,
BORDER = -1,
FIRST_REGULAR_TERRAIN = 0,
DIRT = 0,
SAND,
GRASS,
SNOW,
SWAMP,
ROUGH,
SUBTERRANEAN,
LAVA,
WATER,
ROCK,
ORIGINAL_TERRAIN_COUNT
};
}
namespace Road
{
enum ERoad : ui8
@ -1182,6 +1159,49 @@ class BattleField : public BaseForID<BattleField, si32>
DLL_LINKAGE static BattleField fromString(std::string identifier);
};
class TerrainId
{
public:
enum ETerrainID {
NATIVE_TERRAIN = -4,
ANY_TERRAIN = -3,
WRONG = -2,
BORDER = -1,
FIRST_REGULAR_TERRAIN = 0,
DIRT,
SAND,
GRASS,
SNOW,
SWAMP,
ROUGH,
SUBTERRANEAN,
LAVA,
WATER,
ROCK,
ORIGINAL_TERRAIN_COUNT
};
TerrainId(ETerrainID _num = WRONG) : num(_num)
{}
ETerrainID num;
ID_LIKE_CLASS_COMMON(TerrainId, ETerrainID)
DLL_LINKAGE operator std::string() const;
DLL_LINKAGE const TerrainId * getInfo() const;
DLL_LINKAGE static ETerrainID fromString(std::string identifier);
TerrainId & operator++()
{
num = static_cast<ETerrainID>(static_cast<int>(num) + 1);
return *this;
}
};
ID_LIKE_OPERATORS(TerrainId, TerrainId::ETerrainID)
class ObstacleInfo;
class Obstacle : public BaseForID<Obstacle, si32>
{
@ -1239,7 +1259,7 @@ typedef si64 TExpType;
typedef std::pair<si64, si64> TDmgRange;
typedef si32 TBonusSubtype;
typedef si32 TQuantity;
typedef si8 TerrainId;
//typedef si8 TerrainId;
typedef si8 RoadId;
typedef si8 RiverId;

View File

@ -2106,7 +2106,7 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
}
CreatureTerrainLimiter::CreatureTerrainLimiter()
: terrainType(Terrain::NATIVE_TERRAIN)
: terrainType(TerrainId::NATIVE_TERRAIN)
{
}
@ -2120,7 +2120,7 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const
const CStack *stack = retrieveStackBattle(&context.node);
if(stack)
{
if (terrainType == Terrain::NATIVE_TERRAIN)//terrainType not specified = native
if (terrainType == TerrainId::NATIVE_TERRAIN)//terrainType not specified = native
{
return !stack->isOnNativeTerrain();
}
@ -2136,8 +2136,8 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const
std::string CreatureTerrainLimiter::toString() const
{
boost::format fmt("CreatureTerrainLimiter(terrainType=%s)");
auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType].name;
fmt % (terrainType == Terrain::NATIVE_TERRAIN ? "native" : terrainName);
auto terrainName = VLC->terrainTypeHandler->getById(terrainType)->name;
fmt % (terrainType == TerrainId::NATIVE_TERRAIN ? "native" : terrainName);
return fmt.str();
}
@ -2146,7 +2146,7 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
root["type"].String() = "CREATURE_TERRAIN_LIMITER";
auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType].name;
auto terrainName = VLC->terrainTypeHandler->getById(terrainType)->name;
root["parameters"].Vector().push_back(JsonUtils::stringNode(terrainName));
return root;

View File

@ -720,13 +720,13 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs)
DLL_LINKAGE void NewObject::applyGs(CGameState *gs)
{
TerrainId terrainType = Terrain::BORDER;
TerrainId terrainType = TerrainId::BORDER;
if(ID == Obj::BOAT && !gs->isInTheMap(pos)) //special handling for bug #3060 - pos outside map but visitablePos is not
{
CGObjectInstance testObject = CGObjectInstance();
testObject.pos = pos;
testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(Terrain::WATER).front();
testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(TerrainId::WATER).front();
const int3 previousXAxisTile = int3(pos.x - 1, pos.y, pos.z);
assert(gs->isInTheMap(previousXAxisTile) && (testObject.visitablePos() == previousXAxisTile));
@ -743,7 +743,7 @@ DLL_LINKAGE void NewObject::applyGs(CGameState *gs)
{
case Obj::BOAT:
o = new CGBoat();
terrainType = Terrain::WATER; //TODO: either boat should only spawn on water, or all water objects should be handled this way
terrainType = TerrainId::WATER; //TODO: either boat should only spawn on water, or all water objects should be handled this way
break;
case Obj::MONSTER: //probably more options will be needed
o = new CGCreature();

View File

@ -19,6 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN
//("allowedTerrain"\s*:\s*\[.*)9(.*\],\n)
//\1"rock"\2
/*
TerrainTypeHandler::TerrainTypeHandler()
{
auto allConfigs = VLC->modh->getActiveMods();
@ -29,356 +30,161 @@ TerrainTypeHandler::TerrainTypeHandler()
initRoads(allConfigs);
recreateRoadMaps();
initTerrains(allConfigs); //maps will be populated inside
}
}*/
void TerrainTypeHandler::initTerrains(const std::vector<std::string> & allConfigs)
TerrainType * TerrainTypeHandler::loadFromJson( const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index)
{
std::vector<std::function<void()>> resolveLater;
TerrainType * info = new TerrainType;
objects.resize(Terrain::ORIGINAL_TERRAIN_COUNT); //make space for original terrains
info->id = TerrainId(index);
for(auto & mod : allConfigs)
info->moveCost = static_cast<int>(json["moveCost"].Integer());
info->musicFilename = json["music"].String();
info->tilesFilename = json["tiles"].String();
info->horseSoundId = static_cast<int>(json["horseSoundId"].Float());
info->transitionRequired = json["transitionRequired"].Bool();
info->terrainViewPatterns = json["terrainViewPatterns"].String();
info->terrainText = json["text"].String();
const JsonVector & unblockedVec = json["minimapUnblocked"].Vector();
info->minimapUnblocked =
{
if(!CResourceHandler::get(mod)->existsResource(ResourceID("config/terrains.json")))
continue;
ui8(unblockedVec[0].Float()),
ui8(unblockedVec[1].Float()),
ui8(unblockedVec[2].Float())
};
JsonNode terrs(mod, ResourceID("config/terrains.json"));
for(auto & terr : terrs.Struct())
const JsonVector &blockedVec = json["minimapBlocked"].Vector();
info->minimapBlocked =
{
ui8(blockedVec[0].Float()),
ui8(blockedVec[1].Float()),
ui8(blockedVec[2].Float())
};
for(const auto& node : json["type"].Vector())
{
//Set bits
auto s = node.String();
if (s == "LAND") info->passabilityType |= TerrainType::PassabilityType::LAND;
if (s == "WATER") info->passabilityType |= TerrainType::PassabilityType::WATER;
if (s == "ROCK") info->passabilityType |= TerrainType::PassabilityType::ROCK;
if (s == "SURFACE") info->passabilityType |= TerrainType::PassabilityType::SURFACE;
if (s == "SUB") info->passabilityType |= TerrainType::PassabilityType::SUBTERRANEAN;
}
// if(json["river"].isNull())
// info->river = River::NO_RIVER;
// else
// info->river = getRiverByCode(json["river"].String())->id;
info->typeCode = json["code"].String();
assert(info->typeCode.length() == 2);
for(auto & t : json["battleFields"].Vector())
info->battleFields.emplace_back(t.String());
//Update terrain with this id in the future, after all terrain types are populated
for(auto & t : json["prohibitTransitions"].Vector())
{
VLC->modh->identifiers.requestIdentifier("terrain", t, [info](int32_t identifier)
{
TerrainType info(terr.first); //set name
info.moveCost = static_cast<int>(terr.second["moveCost"].Integer());
const JsonVector &unblockedVec = terr.second["minimapUnblocked"].Vector();
info.minimapUnblocked =
{
ui8(unblockedVec[0].Float()),
ui8(unblockedVec[1].Float()),
ui8(unblockedVec[2].Float())
};
const JsonVector &blockedVec = terr.second["minimapBlocked"].Vector();
info.minimapBlocked =
{
ui8(blockedVec[0].Float()),
ui8(blockedVec[1].Float()),
ui8(blockedVec[2].Float())
};
info.musicFilename = terr.second["music"].String();
info.tilesFilename = terr.second["tiles"].String();
if(terr.second["type"].isNull())
{
info.passabilityType = TerrainType::PassabilityType::LAND | TerrainType::PassabilityType::SURFACE;
}
else if (terr.second["type"].getType() == JsonNode::JsonType::DATA_VECTOR)
{
for(const auto& node : terr.second["type"].Vector())
{
//Set bits
auto s = node.String();
if (s == "LAND") info.passabilityType |= TerrainType::PassabilityType::LAND;
if (s == "WATER") info.passabilityType |= TerrainType::PassabilityType::WATER;
if (s == "ROCK") info.passabilityType |= TerrainType::PassabilityType::ROCK;
if (s == "SURFACE") info.passabilityType |= TerrainType::PassabilityType::SURFACE;
if (s == "SUB") info.passabilityType |= TerrainType::PassabilityType::SUBTERRANEAN;
}
}
else //should be string - one option only
{
auto s = terr.second["type"].String();
if (s == "LAND") info.passabilityType = TerrainType::PassabilityType::LAND;
if (s == "WATER") info.passabilityType = TerrainType::PassabilityType::WATER;
if (s == "ROCK") info.passabilityType = TerrainType::PassabilityType::ROCK;
if (s == "SURFACE") info.passabilityType = TerrainType::PassabilityType::SURFACE;
if (s == "SUB") info.passabilityType = TerrainType::PassabilityType::SUBTERRANEAN;
}
if(terr.second["river"].isNull())
{
info.river = River::NO_RIVER;
}
else
{
info.river = getRiverByCode(terr.second["river"].String())->id;
}
if(terr.second["horseSoundId"].isNull())
{
info.horseSoundId = Terrain::ROCK; //rock sound as default
}
else
{
info.horseSoundId = static_cast<int>(terr.second["horseSoundId"].Float());
}
if(!terr.second["text"].isNull())
{
info.terrainText = terr.second["text"].String();
}
if(terr.second["code"].isNull())
{
info.typeCode = terr.first.substr(0, 2);
}
else
{
info.typeCode = terr.second["code"].String();
assert(info.typeCode.length() == 2);
}
if(!terr.second["battleFields"].isNull())
{
for(auto & t : terr.second["battleFields"].Vector())
{
info.battleFields.emplace_back(t.String());
}
}
info.transitionRequired = false;
if(!terr.second["transitionRequired"].isNull())
{
info.transitionRequired = terr.second["transitionRequired"].Bool();
}
info.terrainViewPatterns = "normal";
if(!terr.second["terrainViewPatterns"].isNull())
{
info.terrainViewPatterns = terr.second["terrainViewPatterns"].String();
}
if(!terr.second["originalTerrainId"].isNull())
{
//place in reserved slot
info.id = (TerrainId)(terr.second["originalTerrainId"].Float());
objects[info.id] = info;
}
else
{
//append at the end
info.id = static_cast<TerrainId>(objects.size());
objects.push_back(info);
}
TerrainId id = info.id;
//Update terrain with this id in the future, after all terrain types are populated
if(!terr.second["prohibitTransitions"].isNull())
{
for(auto & t : terr.second["prohibitTransitions"].Vector())
{
std::string prohibitedTerrainName = t.String();
resolveLater.push_back([this, prohibitedTerrainName, id]()
{
//FIXME: is that reference to the element in vector?
objects[id].prohibitTransitions.emplace_back(getInfoByName(prohibitedTerrainName)->id);
});
}
}
if(terr.second["rockTerrain"].isNull())
{
objects[id].rockTerrain = Terrain::ROCK;
}
else
{
auto rockTerrainName = terr.second["rockTerrain"].String();
resolveLater.push_back([this, rockTerrainName, id]()
{
//FIXME: is that reference to the element in vector?
objects[id].rockTerrain = getInfoByName(rockTerrainName)->id;
});
}
}
info->prohibitTransitions.push_back(TerrainId(identifier));
});
}
for(size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ORIGINAL_TERRAIN_COUNT; i++)
info->rockTerrain = TerrainId::ROCK;
if(!json["rockTerrain"].isNull())
{
//Make sure that original terrains are loaded
assert(objects[i].id != Terrain::WRONG);
}
recreateTerrainMaps();
for(auto& functor : resolveLater)
{
functor();
}
}
void TerrainTypeHandler::initRivers(const std::vector<std::string> & allConfigs)
{
riverTypes.resize(River::ORIGINAL_RIVER_COUNT); //make space for original rivers
//First object will be default NO_RIVER
for(auto & mod : allConfigs)
{
if (!CResourceHandler::get(mod)->existsResource(ResourceID("config/rivers.json")))
continue;
JsonNode rivs(mod, ResourceID("config/rivers.json"));
for(auto & river : rivs.Struct())
auto rockTerrainName = json["rockTerrain"].String();
VLC->modh->identifiers.requestIdentifier("terrain", rockTerrainName, [info](int32_t identifier)
{
RiverType info;
info.name = river.first;
info.fileName = river.second["animation"].String();
info.code = river.second["code"].String();
info.deltaName = river.second["delta"].String();
if (!river.second["originalRiverId"].isNull())
{
info.id = static_cast<RiverId>(river.second["originalRiverId"].Float());
riverTypes[info.id] = info;
}
else
{
info.id = static_cast<RiverId>(riverTypes.size());
riverTypes.push_back(info);
}
}
info->rockTerrain = TerrainId(identifier);
});
}
recreateRiverMaps();
return info;
}
void TerrainTypeHandler::initRoads(const std::vector<std::string> & allConfigs)
const std::vector<std::string> & TerrainTypeHandler::getTypeNames() const
{
roadTypes.resize(Road::ORIGINAL_ROAD_COUNT); //make space for original rivers
//first object will be default NO_ROAD
for(auto & mod : allConfigs)
{
if (!CResourceHandler::get(mod)->existsResource(ResourceID("config/roads.json")))
continue;
JsonNode rds(mod, ResourceID("config/roads.json"));
for(auto & road : rds.Struct())
{
RoadType info;
info.name = road.first;
info.fileName = road.second["animation"].String();
info.code = road.second["code"].String();
info.movementCost = static_cast<ui8>(road.second["moveCost"].Float());
if (!road.second["originalRoadId"].isNull())
{
info.id = static_cast<RoadId>(road.second["originalRoadId"].Float());
roadTypes[info.id] = info;
}
else
{
info.id = static_cast<RoadId>(roadTypes.size());
roadTypes.push_back(info);
}
}
}
recreateRoadMaps();
static const std::vector<std::string> typeNames = { "terrain" };
return typeNames;
}
void TerrainTypeHandler::recreateTerrainMaps()
std::vector<JsonNode> TerrainTypeHandler::loadLegacyData(size_t dataSize)
{
//This assumes the vector will never be updated or reallocated in the future
for(size_t i = 0; i < objects.size(); i++)
{
const auto * terrainInfo = &objects[i];
terrainInfoByName[terrainInfo->name] = terrainInfo;
terrainInfoByCode[terrainInfo->typeCode] = terrainInfo;
terrainInfoById[terrainInfo->id] = terrainInfo;
}
return {};
}
void TerrainTypeHandler::recreateRiverMaps()
std::vector<bool> TerrainTypeHandler::getDefaultAllowed() const
{
for(size_t i = River::FIRST_REGULAR_RIVER ; i < riverTypes.size(); i++)
{
const auto * riverInfo = &riverTypes[i];
riverInfoByName[riverInfo->name] = riverInfo;
riverInfoByCode[riverInfo->code] = riverInfo;
riverInfoById[riverInfo->id] = riverInfo;
}
return {};
}
void TerrainTypeHandler::recreateRoadMaps()
RiverType * RiverTypeHandler::loadFromJson(
const std::string & scope,
const JsonNode & json,
const std::string & identifier,
size_t index)
{
for(size_t i = Road::FIRST_REGULAR_ROAD ; i < roadTypes.size(); i++)
{
const auto * roadInfo = &roadTypes[i];
RiverType * info = new RiverType;
roadInfoByName[roadInfo->name] = roadInfo;
roadInfoByCode[roadInfo->code] = roadInfo;
roadInfoById[roadInfo->id] = roadInfo;
}
info->fileName = json["animation"].String();
info->code = json["code"].String();
info->deltaName = json["delta"].String();
return info;
}
const std::vector<TerrainType> & TerrainTypeHandler::terrains() const
const std::vector<std::string> & RiverTypeHandler::getTypeNames() const
{
//FIXME: somehow make it non-copyable? Pointers must point to original data and not its copy
return objects;
static const std::vector<std::string> typeNames = { "river" };
return typeNames;
}
const std::vector<RiverType>& TerrainTypeHandler::rivers() const
std::vector<JsonNode> RiverTypeHandler::loadLegacyData(size_t dataSize)
{
return riverTypes;
return {};
}
const std::vector<RoadType>& TerrainTypeHandler::roads() const
std::vector<bool> RiverTypeHandler::getDefaultAllowed() const
{
return roadTypes;
return {};
}
const TerrainType* TerrainTypeHandler::getInfoByName(const std::string& terrainName) const
RoadType * RoadTypeHandler::loadFromJson(
const std::string & scope,
const JsonNode & json,
const std::string & identifier,
size_t index)
{
return terrainInfoByName.at(terrainName);
RoadType * info = new RoadType;
info->fileName = json["animation"].String();
info->code = json["code"].String();
info->movementCost = json["moveCost"].Integer();
return info;
}
const TerrainType* TerrainTypeHandler::getInfoByCode(const std::string& terrainCode) const
const std::vector<std::string> & RoadTypeHandler::getTypeNames() const
{
return terrainInfoByCode.at(terrainCode);
static const std::vector<std::string> typeNames = { "river" };
return typeNames;
}
const TerrainType* TerrainTypeHandler::getInfoById(TerrainId id) const
std::vector<JsonNode> RoadTypeHandler::loadLegacyData(size_t dataSize)
{
return terrainInfoById.at(id);
return {};
}
const RiverType* TerrainTypeHandler::getRiverByName(const std::string& riverName) const
std::vector<bool> RoadTypeHandler::getDefaultAllowed() const
{
return riverInfoByName.at(riverName);
}
const RiverType* TerrainTypeHandler::getRiverByCode(const std::string& riverCode) const
{
return riverInfoByCode.at(riverCode);
}
const RiverType* TerrainTypeHandler::getRiverById(RiverId 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(RoadId id) const
{
return roadInfoById.at(id);
}
std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType)
{
return os << static_cast<const std::string &>(terrainType);
return {};
}
TerrainType::operator std::string() const
@ -386,20 +192,6 @@ TerrainType::operator std::string() const
return name;
}
TerrainType::TerrainType(const std::string& _name):
minimapBlocked({0,0,0}), //black
minimapUnblocked({ 128,128,128 }), //grey
name(_name),
river(River::NO_RIVER),
id(Terrain::WRONG),
rockTerrain(Terrain::ROCK),
moveCost(GameConstants::BASE_MOVEMENT_COST),
horseSoundId(0),
passabilityType(0),
transitionRequired(false)
{
}
bool TerrainType::operator==(const TerrainType& other)
{
return id == other.id;
@ -455,19 +247,4 @@ bool TerrainType::isTransitionRequired() const
return transitionRequired;
}
RiverType::RiverType(const std::string & fileName, const std::string & code, RiverId id):
fileName(fileName),
code(code),
id(id)
{
}
RoadType::RoadType(const std::string& fileName, const std::string& code, RoadId id):
fileName(fileName),
code(code),
id(id),
movementCost(GameConstants::BASE_MOVEMENT_COST)
{
}
VCMI_LIB_NAMESPACE_END

View File

@ -10,15 +10,24 @@
#pragma once
#include <vcmi/EntityService.h>
#include <vcmi/Entity.h>
#include "ConstTransitivePtr.h"
#include "GameConstants.h"
#include "JsonNode.h"
#include "IHandlerBase.h"
VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE TerrainType
class DLL_LINKAGE TerrainType : public EntityT<TerrainId>
{
public:
int32_t getIndex() const override;
int32_t getIconIndex() const override;
const std::string & getName() const override;
const std::string & getJsonKey() const override;
void registerIcons(const IconRegistar & cb) const override;
TerrainId getId() const override;
enum PassabilityType : ui8
{
@ -88,10 +97,16 @@ public:
}
};
class DLL_LINKAGE RiverType
class DLL_LINKAGE RiverType : public EntityT<TerrainId>
{
public:
std::string name;
int32_t getIndex() const override;
int32_t getIconIndex() const override;
const std::string & getName() const override;
const std::string & getJsonKey() const override;
void registerIcons(const IconRegistar & cb) const override;
TerrainId getId() const override;
std::string fileName;
std::string code;
std::string deltaName;
@ -101,10 +116,6 @@ public:
template <typename Handler> void serialize(Handler& h, const int version)
{
if(version >= 806)
{
h & name;
}
h & fileName;
h & code;
h & deltaName;
@ -112,10 +123,16 @@ public:
}
};
class DLL_LINKAGE RoadType
class DLL_LINKAGE RoadType : public EntityT<TerrainId>
{
public:
std::string name;
int32_t getIndex() const override;
int32_t getIconIndex() const override;
const std::string & getName() const override;
const std::string & getJsonKey() const override;
void registerIcons(const IconRegistar & cb) const override;
TerrainId getId() const override;
std::string fileName;
std::string code;
RoadId id;
@ -125,10 +142,6 @@ public:
template <typename Handler> void serialize(Handler& h, const int version)
{
if(version >= 806)
{
h & name;
}
h & fileName;
h & code;
h & id;
@ -136,69 +149,85 @@ public:
}
};
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType);
class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ?
class DLL_LINKAGE TerrainTypeService : public EntityServiceT<TerrainId, TerrainType>
{
public:
};
TerrainTypeHandler();
~TerrainTypeHandler() {};
class DLL_LINKAGE RiverTypeService : public EntityServiceT<TerrainId, RiverType>
{
public:
};
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(TerrainId id) const;
class DLL_LINKAGE RoadTypeService : public EntityServiceT<TerrainId, RoadType>
{
public:
};
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(RiverId id) const;
class DLL_LINKAGE TerrainTypeHandler : public CHandlerBase<TerrainId, TerrainType, TerrainType, TerrainTypeService>
{
public:
virtual TerrainType * loadFromJson(
const std::string & scope,
const JsonNode & json,
const std::string & identifier,
size_t index) override;
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(RoadId id) const;
virtual const std::vector<std::string> & getTypeNames() const override;
virtual std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
virtual std::vector<bool> getDefaultAllowed() const override;
template <typename Handler> void serialize(Handler &h, const int version)
TerrainType * getInfoByCode(const std::string & identifier);
TerrainType * getInfoByName(const std::string & identifier);
template <typename Handler> void serialize(Handler & h, const int version)
{
h & objects;
h & riverTypes;
h & roadTypes;
if (!h.saving)
{
recreateTerrainMaps();
recreateRiverMaps();
recreateRoadMaps();
}
}
};
private:
class DLL_LINKAGE RiverTypeHandler : public CHandlerBase<TerrainId, RiverType, RiverType, RiverTypeService>
{
public:
virtual RiverType * loadFromJson(
const std::string & scope,
const JsonNode & json,
const std::string & identifier,
size_t index) override;
std::vector<TerrainType> objects;
std::vector<RiverType> riverTypes;
std::vector<RoadType> roadTypes;
virtual const std::vector<std::string> & getTypeNames() const override;
virtual std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
virtual std::vector<bool> getDefaultAllowed() const override;
std::unordered_map<std::string, const TerrainType*> terrainInfoByName;
std::unordered_map<std::string, const TerrainType*> terrainInfoByCode;
std::unordered_map<TerrainId, const TerrainType*> terrainInfoById;
RiverType * getInfoByCode(const std::string & identifier);
RiverType * getInfoByName(const std::string & identifier);
std::unordered_map<std::string, const RiverType*> riverInfoByName;
std::unordered_map<std::string, const RiverType*> riverInfoByCode;
std::unordered_map<RiverId, const RiverType*> riverInfoById;
template <typename Handler> void serialize(Handler & h, const int version)
{
h & objects;
}
};
std::unordered_map<std::string, const RoadType*> roadInfoByName;
std::unordered_map<std::string, const RoadType*> roadInfoByCode;
std::unordered_map<RoadId, const RoadType*> roadInfoById;
class DLL_LINKAGE RoadTypeHandler : public CHandlerBase<TerrainId, RoadType, RoadType, RoadTypeService>
{
public:
virtual RoadType * loadFromJson(
const std::string & scope,
const JsonNode & json,
const std::string & identifier,
size_t index) override;
void initTerrains(const std::vector<std::string> & allConfigs);
void initRivers(const std::vector<std::string> & allConfigs);
void initRoads(const std::vector<std::string> & allConfigs);
void recreateTerrainMaps();
void recreateRiverMaps();
void recreateRoadMaps();
virtual const std::vector<std::string> & getTypeNames() const override;
virtual std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
virtual std::vector<bool> getDefaultAllowed() const override;
RoadType * getInfoByCode(const std::string & identifier);
RoadType * getInfoByName(const std::string & identifier);
template <typename Handler> void serialize(Handler & h, const int version)
{
h & objects;
}
};
VCMI_LIB_NAMESPACE_END

View File

@ -197,6 +197,8 @@ void LibClasses::init(bool onlyEssential)
createHandler(bth, "Bonus type", pomtime);
createHandler(roadTypeHandler, "Road", pomtime);
createHandler(riverTypeHandler, "River", pomtime);
createHandler(terrainTypeHandler, "Terrain", pomtime);
createHandler(generaltexth, "General text", pomtime);

View File

@ -30,6 +30,8 @@ class BattleFieldHandler;
class IBonusTypeHandler;
class CBonusTypeHandler;
class TerrainTypeHandler;
class RoadTypeHandler;
class RiverTypeHandler;
class ObstacleHandler;
class CTerrainViewPatternConfig;
class CRmgTemplateStorage;
@ -86,7 +88,11 @@ public:
CTownHandler * townh;
CGeneralTextHandler * generaltexth;
CModHandler * modh;
TerrainTypeHandler * terrainTypeHandler;
RoadTypeHandler * roadTypeHandler;
RiverTypeHandler * riverTypeHandler;
CTerrainViewPatternConfig * terviewh;
CRmgTemplateStorage * tplh;
BattleFieldHandler * battlefieldsHandler;
@ -127,6 +133,8 @@ public:
h & skillh;
h & battlefieldsHandler;
h & obstacleHandler;
h & roadTypeHandler;
h & riverTypeHandler;
h & terrainTypeHandler;
if(!h.saving)

View File

@ -86,7 +86,7 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f
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
ti->nativeTerrain != TerrainId::ANY_TERRAIN && //no special creature bonus
!ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType->id)) //no special movement bonus
{
@ -106,18 +106,18 @@ TerrainId CGHeroInstance::getNativeTerrain() const
// will always have best penalty without any influence from player-defined stacks order
// TODO: What should we do if all hero stacks are neutral creatures?
TerrainId nativeTerrain = Terrain::BORDER;
TerrainId nativeTerrain = TerrainId::BORDER;
for(auto stack : stacks)
{
TerrainId stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar.
if(stackNativeTerrain == Terrain::BORDER) //where does this value come from?
if(stackNativeTerrain == TerrainId::BORDER) //where does this value come from?
continue;
if(nativeTerrain == Terrain::BORDER)
if(nativeTerrain == TerrainId::BORDER)
nativeTerrain = stackNativeTerrain;
else if(nativeTerrain != stackNativeTerrain)
return Terrain::BORDER;
return TerrainId::BORDER;
}
return nativeTerrain;
}

View File

@ -157,20 +157,20 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser)
// so these two fields can be interpreted as "strong affinity" and "weak affinity" towards terrains
std::string & terrStr = strings[4]; // allowed terrains, 1 = object can be placed on this terrain
assert(terrStr.size() == Terrain::ROCK); // all terrains but rock - counting from 0
for(TerrainId i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++)
assert(terrStr.size() == TerrainId::ROCK); // all terrains but rock - counting from 0
for(TerrainId i = TerrainId(0); i < TerrainId::ROCK; ++i)
{
if (terrStr[8-i] == '1')
allowedTerrains.insert(i);
}
//assuming that object can be placed on other land terrains
if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain::WATER))
if(allowedTerrains.size() >= 8 && !allowedTerrains.count(TerrainId::WATER))
{
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
for(const auto & terrain : VLC->terrainTypeHandler->objects)
{
if(terrain.isLand() && terrain.isPassable())
allowedTerrains.insert(terrain.id);
if(terrain->isLand() && terrain->isPassable())
allowedTerrains.insert(terrain->id);
}
}
@ -231,19 +231,19 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
reader.readUInt16();
ui16 terrMask = reader.readUInt16();
for(size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++)
for(TerrainId i = TerrainId::FIRST_REGULAR_TERRAIN; i < TerrainId::ORIGINAL_TERRAIN_COUNT; ++i)
{
if (((terrMask >> i) & 1 ) != 0)
allowedTerrains.insert(i);
}
//assuming that object can be placed on other land terrains
if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain::WATER))
if(allowedTerrains.size() >= 8 && !allowedTerrains.count(TerrainId::WATER))
{
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
for(const auto & terrain : VLC->terrainTypeHandler->objects)
{
if(terrain.isLand() && terrain.isPassable())
allowedTerrains.insert(terrain.id);
if(terrain->isLand() && terrain->isPassable())
allowedTerrains.insert(terrain->id);
}
}
@ -299,11 +299,11 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain)
}
else
{
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
for(const auto & terrain : VLC->terrainTypeHandler->objects)
{
if(!terrain.isPassable() || terrain.isWater())
if(!terrain->isPassable() || terrain->isWater())
continue;
allowedTerrains.insert(terrain.id);
allowedTerrains.insert(terrain->id);
}
}
@ -378,14 +378,14 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const
if(withTerrain)
{
//assumed that ROCK and WATER terrains are not included
if(allowedTerrains.size() < (VLC->terrainTypeHandler->terrains().size() - 2))
if(allowedTerrains.size() < (VLC->terrainTypeHandler->objects.size() - 2))
{
JsonVector & data = node["allowedTerrains"].Vector();
for(auto type : allowedTerrains)
{
JsonNode value(JsonNode::JsonType::DATA_STRING);
value.String() = type;
value.String() = VLC->terrainTypeHandler->getById(type)->name;
data.push_back(value);
}
}

View File

@ -338,12 +338,12 @@ std::string CDrawRiversOperation::getLabel() const
void CDrawRoadsOperation::executeTile(TerrainTile & tile)
{
tile.roadType = const_cast<RoadType*>(&VLC->terrainTypeHandler->roads()[roadType]);
tile.roadType = const_cast<RoadType*>(VLC->roadTypeHandler->getByIndex(roadType));
}
void CDrawRiversOperation::executeTile(TerrainTile & tile)
{
tile.riverType = const_cast<RiverType*>(&VLC->terrainTypeHandler->rivers()[riverType]);
tile.riverType = const_cast<RiverType*>(VLC->riverTypeHandler->getByIndex(riverType));
}
bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const

View File

@ -128,9 +128,9 @@ CCastleEvent::CCastleEvent() : town(nullptr)
TerrainTile::TerrainTile():
terType(nullptr),
terView(0),
riverType(const_cast<RiverType*>(&VLC->terrainTypeHandler->rivers()[River::NO_RIVER])),
riverType(nullptr),
riverDir(0),
roadType(const_cast<RoadType*>(&VLC->terrainTypeHandler->roads()[Road::NO_ROAD])),
roadType(nullptr),
roadDir(0),
extTileFlags(0),
visitable(false),

View File

@ -97,7 +97,7 @@ void CDrawTerrainOperation::execute()
for(const auto & pos : terrainSel.getSelectedItems())
{
auto & tile = map->getTile(pos);
tile.terType = const_cast<TerrainType*>(&VLC->terrainTypeHandler->terrains()[terType]);
tile.terType = const_cast<TerrainType*>(VLC->terrainTypeHandler->getById(terType));
invalidateTerrainViews(pos);
}
@ -422,14 +422,14 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
bool nativeTestOk, nativeTestStrongOk;
nativeTestOk = nativeTestStrongOk = (rule.isNativeStrong() || rule.isNativeRule()) && !isAlien;
if(centerTerType->id == Terrain::DIRT)
if(centerTerType->id == TerrainId::DIRT)
{
nativeTestOk = rule.isNativeRule() && !terType->isTransitionRequired();
bool sandTestOk = (rule.isSandRule() || rule.isTransition())
&& terType->isTransitionRequired();
applyValidationRslt(rule.isAnyRule() || sandTestOk || nativeTestOk || nativeTestStrongOk);
}
else if(centerTerType->id == Terrain::SAND)
else if(centerTerType->id == TerrainId::SAND)
{
applyValidationRslt(true);
}
@ -551,12 +551,12 @@ CClearTerrainOperation::CClearTerrainOperation(CMap* map, CRandomGenerator* gen)
{
CTerrainSelection terrainSel(map);
terrainSel.selectRange(MapRect(int3(0, 0, 0), map->width, map->height));
addOperation(std::make_unique<CDrawTerrainOperation>(map, terrainSel, Terrain::WATER, gen));
addOperation(std::make_unique<CDrawTerrainOperation>(map, terrainSel, TerrainId::WATER, gen));
if(map->twoLevel)
{
terrainSel.clearSelection();
terrainSel.selectRange(MapRect(int3(0, 0, 1), map->width, map->height));
addOperation(std::make_unique<CDrawTerrainOperation>(map, terrainSel, Terrain::ROCK, gen));
addOperation(std::make_unique<CDrawTerrainOperation>(map, terrainSel, TerrainId::ROCK, gen));
}
}

View File

@ -272,7 +272,7 @@ CTerrainViewPatternConfig::~CTerrainViewPatternConfig()
const std::vector<CTerrainViewPatternConfig::TVPVector> & CTerrainViewPatternConfig::getTerrainViewPatterns(TerrainId terrain) const
{
auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->terrains()[terrain].terrainViewPatterns);
auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->getById(terrain)->terrainViewPatterns);
if (iter == terrainViewPatterns.end())
return terrainViewPatterns.at("normal");
return iter->second;

View File

@ -923,9 +923,6 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
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;
@ -937,14 +934,14 @@ void CMapLoaderH3M::readTerrain()
for(pos.x = 0; pos.x < map->width; pos.x++)
{
auto & tile = map->getTile(pos);
tile.terType = const_cast<TerrainType*>(&terrains[reader.readUInt8()]);
tile.terType = const_cast<TerrainType*>(VLC->terrainTypeHandler->getByIndex(reader.readUInt8()));
tile.terView = reader.readUInt8();
tile.riverType = const_cast<RiverType*>(&rivers[reader.readUInt8()]);
tile.riverType = const_cast<RiverType*>(VLC->riverTypeHandler->getByIndex(reader.readUInt8()));
tile.riverDir = reader.readUInt8();
tile.roadType = const_cast<RoadType*>(&roads[reader.readUInt8()]);
tile.roadType = const_cast<RoadType*>(VLC->roadTypeHandler->getByIndex(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
tile.blocked = ((!tile.terType->isPassable() || tile.terType->id == TerrainId::BORDER ) ? true : false); //underground tiles are always blocked
tile.visitable = 0;
}
}

View File

@ -979,13 +979,13 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
startPos += 2;
try
{
tile.roadType = const_cast<RoadType*>(VLC->terrainTypeHandler->getRoadByCode(typeCode));
tile.roadType = const_cast<RoadType*>(VLC->roadTypeHandler->getInfoByCode(typeCode));
}
catch (const std::exception&) //it's not a road, it's a river
{
try
{
tile.riverType = const_cast<RiverType*>(VLC->terrainTypeHandler->getRiverByCode(typeCode));
tile.riverType = const_cast<RiverType*>(VLC->riverTypeHandler->getInfoByCode(typeCode));
hasRoad = false;
}
catch (const std::exception&)
@ -1021,7 +1021,7 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
{//river type
const std::string typeCode = src.substr(startPos, 2);
startPos += 2;
tile.riverType = const_cast<RiverType*>(VLC->terrainTypeHandler->getRiverByCode(typeCode));
tile.riverType = const_cast<RiverType*>(VLC->riverTypeHandler->getInfoByCode(typeCode));
}
{//river dir
int pos = startPos;

View File

@ -74,8 +74,8 @@ public:
static std::string encode(const si32 index)
{
const auto& terrains = VLC->terrainTypeHandler->terrains();
return (index >=0 && index < terrains.size()) ? terrains[index].name : "<INVALID TERRAIN>";
const auto& terrains = VLC->terrainTypeHandler->objects;
return (index >=0 && index < terrains.size()) ? terrains[index]->name : "<INVALID TERRAIN>";
}
};
@ -152,9 +152,9 @@ ZoneOptions::ZoneOptions()
terrainTypeLikeZone(NO_ZONE),
treasureLikeZone(NO_ZONE)
{
for(const auto & terr : VLC->terrainTypeHandler->terrains())
if(terr.isLand() && terr.isPassable())
terrainTypes.insert(terr.id);
for(const auto & terr : VLC->terrainTypeHandler->objects)
if(terr->isLand() && terr->isPassable())
terrainTypes.insert(terr->id);
}
ZoneOptions & ZoneOptions::operator=(const ZoneOptions & other)
@ -365,7 +365,7 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
for(auto & ttype : terrainTypes)
{
JsonNode n;
n.String() = ttype;
n.String() = VLC->terrainTypeHandler->getById(ttype)->name;
node.Vector().push_back(n);
}
}

View File

@ -194,15 +194,15 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
else
{
auto & tt = (*VLC->townh)[faction]->nativeTerrain;
if(tt == Terrain::DIRT)
if(tt == TerrainId::DIRT)
{
//any / random
zonesToPlace.push_back(zone);
}
else
{
const auto & terrainType = VLC->terrainTypeHandler->terrains()[tt];
if(terrainType.isUnderground() && !terrainType.isSurface())
const auto & terrainType = VLC->terrainTypeHandler->getById(tt);
if(terrainType->isUnderground() && !terrainType->isSurface())
{
//underground only
zonesOnLevel[1]++;
@ -580,7 +580,7 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
//make sure that terrain inside zone is not a rock
//FIXME: reorder actions?
paintZoneTerrain(*zone.second, *rand, map, Terrain::SUBTERRANEAN);
paintZoneTerrain(*zone.second, *rand, map, TerrainId::SUBTERRANEAN);
}
}
logGlobal->info("Finished zone colouring");

View File

@ -84,9 +84,9 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
//1. Try to make direct connection
//Do if it's not prohibited by terrain settings
const auto& terrains = VLC->terrainTypeHandler->terrains();
bool directProhibited = vstd::contains(terrains[zone.getTerrainType()].prohibitTransitions, otherZone->getTerrainType())
|| vstd::contains(terrains[otherZone->getTerrainType()].prohibitTransitions, zone.getTerrainType());
const auto& terrains = VLC->terrainTypeHandler->objects;
bool directProhibited = vstd::contains(terrains[zone.getTerrainType()]->prohibitTransitions, otherZone->getTerrainType())
|| vstd::contains(terrains[otherZone->getTerrainType()]->prohibitTransitions, zone.getTerrainType());
auto directConnectionIterator = dNeighbourZones.find(otherZoneId);
if(!directProhibited && directConnectionIterator != dNeighbourZones.end())
{

View File

@ -119,9 +119,9 @@ void initTerrainType(Zone & zone, CMapGenerator & gen)
{
//collect all water terrain types
std::vector<TerrainId> waterTerrains;
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
if(terrain.isWater())
waterTerrains.push_back(terrain.id);
for(const auto & terrain : VLC->terrainTypeHandler->objects)
if(terrain->isWater())
waterTerrains.push_back(terrain->id);
zone.setTerrainType(*RandomGeneratorUtil::nextItem(waterTerrains, gen.rand));
}
@ -137,20 +137,20 @@ void initTerrainType(Zone & zone, CMapGenerator & gen)
}
//Now, replace disallowed terrains on surface and in the underground
const auto & terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()];
const auto & terrainType = VLC->terrainTypeHandler->getById(zone.getTerrainType());
if(zone.isUnderground())
{
if(!terrainType.isUnderground())
if(!terrainType->isUnderground())
{
zone.setTerrainType(Terrain::SUBTERRANEAN);
zone.setTerrainType(TerrainId::SUBTERRANEAN);
}
}
else
{
if (!terrainType.isSurface())
if (!terrainType->isSurface())
{
zone.setTerrainType(Terrain::DIRT);
zone.setTerrainType(TerrainId::DIRT);
}
}
}

View File

@ -86,7 +86,7 @@ void RiverPlacer::init()
void RiverPlacer::drawRivers()
{
map.getEditManager()->getTerrainSelection().setSelection(rivers.getTilesVector());
map.getEditManager()->drawRiver(VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river, &generator.rand);
map.getEditManager()->drawRiver(VLC->terrainTypeHandler->getById(zone.getTerrainType())->river, &generator.rand);
}
char RiverPlacer::dump(const int3 & t)
@ -195,7 +195,7 @@ void RiverPlacer::preprocess()
//calculate delta positions
if(connectedToWaterZoneId > -1)
{
auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river;
auto river = VLC->terrainTypeHandler->getById(zone.getTerrainType())->river;
auto & a = neighbourZonesTiles[connectedToWaterZoneId];
auto availableArea = zone.areaPossible() + zone.freePaths();
for(auto & tileToProcess : availableArea.getTilesVector())
@ -321,9 +321,9 @@ void RiverPlacer::preprocess()
void RiverPlacer::connectRiver(const int3 & tile)
{
auto riverType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river;
const auto & river = VLC->terrainTypeHandler->rivers()[riverType];
if(river.id == River::NO_RIVER)
auto riverType = VLC->terrainTypeHandler->getById(zone.getTerrainType())->river;
const auto * river = VLC->riverTypeHandler->getByIndex(riverType);
if(river->id == River::NO_RIVER)
return;
rmg::Area roads;
@ -381,9 +381,9 @@ 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.code));
RIVER_DELTA_ID % RIVER_DELTA_SUBTYPE % zone.getTerrainType() % river->code));
std::string targetTemplateName = river.deltaName + 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)

View File

@ -84,7 +84,7 @@ void RmgMap::initTiles(CMapGenerator & generator)
getEditManager()->clearTerrain(&generator.rand);
getEditManager()->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions.getWidth(), mapGenOptions.getHeight()));
getEditManager()->drawTerrain(Terrain::GRASS, &generator.rand);
getEditManager()->drawTerrain(TerrainId::GRASS, &generator.rand);
auto tmpl = mapGenOptions.getMapTemplate();
zones.clear();

View File

@ -121,7 +121,7 @@ void Object::Instance::setTemplate(TerrainId terrain)
auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain);
if (templates.empty())
{
auto terrainName = VLC->terrainTypeHandler->terrains()[terrain].name;
auto terrainName = VLC->terrainTypeHandler->getById(terrain)->name;
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % terrainName));
}
dObject.appearance = templates.front();

View File

@ -78,8 +78,10 @@ void RoadPlacer::drawRoads(bool secondary)
zone.areaPossible().subtract(roads);
zone.freePaths().unite(roads);
map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector());
std::string roadName = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType);
RoadId roadType = VLC->terrainTypeHandler->getRoadByName(roadName)->id;
RoadId roadType = VLC->roadTypeHandler->getInfoByName(roadName)->id;
map.getEditManager()->drawRoad(roadType, &generator.rand);
}

View File

@ -24,8 +24,8 @@ VCMI_LIB_NAMESPACE_BEGIN
void RockPlacer::process()
{
rockTerrain = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].rockTerrain;
assert(!VLC->terrainTypeHandler->terrains()[rockTerrain].isPassable());
rockTerrain = VLC->terrainTypeHandler->getById(zone.getTerrainType())->rockTerrain;
assert(!VLC->terrainTypeHandler->getById(rockTerrain)->isPassable());
accessibleArea = zone.freePaths() + zone.areaUsed();
if(auto * m = zone.getModificator<ObjectManager>())

View File

@ -28,7 +28,7 @@ std::function<bool(const int3 &)> AREA_NO_FILTER = [](const int3 & t)
Zone::Zone(RmgMap & map, CMapGenerator & generator)
: ZoneOptions(),
townType(ETownType::NEUTRAL),
terrainType(Terrain::GRASS),
terrainType(TerrainId::GRASS),
map(map),
generator(generator)
{

View File

@ -542,32 +542,32 @@ void MainWindow::loadObjectsTree()
{
ui->terrainFilterCombo->addItem("");
//adding terrains
for(auto & terrain : VLC->terrainTypeHandler->terrains())
for(auto & terrain : VLC->terrainTypeHandler->objects)
{
QPushButton *b = new QPushButton(QString::fromStdString(terrain.name));
QPushButton *b = new QPushButton(QString::fromStdString(terrain->name));
ui->terrainLayout->addWidget(b);
connect(b, &QPushButton::clicked, this, [this, terrain]{ terrainButtonClicked(terrain.id); });
connect(b, &QPushButton::clicked, this, [this, terrain]{ terrainButtonClicked(terrain->id); });
//filter
ui->terrainFilterCombo->addItem(QString::fromStdString(terrain));
ui->terrainFilterCombo->addItem(QString::fromStdString(terrain->name));
}
//add spacer to keep terrain button on the top
ui->terrainLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
//adding roads
for(auto & road : VLC->terrainTypeHandler->roads())
for(auto & road : VLC->roadTypeHandler->objects)
{
QPushButton *b = new QPushButton(QString::fromStdString(road.fileName));
QPushButton *b = new QPushButton(QString::fromStdString(road->fileName));
ui->roadLayout->addWidget(b);
connect(b, &QPushButton::clicked, this, [this, road]{ roadOrRiverButtonClicked(road.id, true); });
connect(b, &QPushButton::clicked, this, [this, road]{ roadOrRiverButtonClicked(road->id, true); });
}
//add spacer to keep terrain button on the top
ui->roadLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
//adding rivers
for(auto & river : VLC->terrainTypeHandler->rivers())
for(auto & river : VLC->riverTypeHandler->objects)
{
QPushButton *b = new QPushButton(QString::fromStdString(river.fileName));
QPushButton *b = new QPushButton(QString::fromStdString(river->fileName));
ui->riverLayout->addWidget(b);
connect(b, &QPushButton::clicked, this, [this, river]{ roadOrRiverButtonClicked(river.id, false); });
connect(b, &QPushButton::clicked, this, [this, river]{ roadOrRiverButtonClicked(river->id, false); });
}
//add spacer to keep terrain button on the top
ui->riverLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
@ -914,7 +914,7 @@ void MainWindow::on_terrainFilterCombo_currentTextChanged(const QString &arg1)
if(!objectBrowser)
return;
objectBrowser->terrain = arg1.isEmpty() ? TerrainId(Terrain::ANY_TERRAIN) : VLC->terrainTypeHandler->getInfoByName(arg1.toStdString())->id;
objectBrowser->terrain = arg1.isEmpty() ? TerrainId(TerrainId::ANY_TERRAIN) : VLC->terrainTypeHandler->getInfoByName(arg1.toStdString())->id;
objectBrowser->invalidate();
objectBrowser->sort(0);
}

View File

@ -78,17 +78,17 @@ void MapHandler::initTerrainGraphics()
std::map<std::string, std::string> terrainFiles;
std::map<std::string, std::string> roadFiles;
std::map<std::string, std::string> riverFiles;
for(const auto & terrain : VLC->terrainTypeHandler->terrains())
for(const auto & terrain : VLC->terrainTypeHandler->objects)
{
terrainFiles[terrain.name] = terrain.tilesFilename;
terrainFiles[terrain->name] = terrain->tilesFilename;
}
for(const auto & river : VLC->terrainTypeHandler->rivers())
for(const auto & river : VLC->riverTypeHandler->objects)
{
riverFiles[river.fileName] = river.fileName;
riverFiles[river->fileName] = river->fileName;
}
for(const auto & road : VLC->terrainTypeHandler->roads())
for(const auto & road : VLC->roadTypeHandler->objects)
{
roadFiles[road.fileName] = road.fileName;
roadFiles[road->fileName] = road->fileName;
}
loadFlipped(terrainAnimations, terrainImages, terrainFiles);

View File

@ -13,7 +13,7 @@
#include "../lib/mapObjects/CObjectClassesHandler.h"
ObjectBrowserProxyModel::ObjectBrowserProxyModel(QObject *parent)
: QSortFilterProxyModel{parent}, terrain(Terrain::ANY_TERRAIN)
: QSortFilterProxyModel{parent}, terrain(TerrainId::ANY_TERRAIN)
{
}
@ -33,7 +33,7 @@ bool ObjectBrowserProxyModel::filterAcceptsRow(int source_row, const QModelIndex
if(!filterAcceptsRowText(source_row, source_parent))
return false;
if(terrain == Terrain::ANY_TERRAIN)
if(terrain == TerrainId::ANY_TERRAIN)
return result;
auto data = item->data().toJsonObject();

View File

@ -2244,7 +2244,7 @@ void CGameHandler::setupBattle(int3 tile, const CArmedInstance *armies[2], const
const auto & t = *getTile(tile);
TerrainId terrain = t.terType->id;
if (gs->map->isCoastalTile(tile)) //coastal tile is always ground
terrain = Terrain::SAND;
terrain = TerrainId::SAND;
BattleField terType = gs->battleGetBattlefieldType(tile, getRandomGenerator());
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)