Selaa lähdekoodia

TerrainTile now uses identifiers instead of pointers to VLC

Ivan Savenko 1 vuosi sitten
vanhempi
sitoutus
08fbcd5239
44 muutettua tiedostoa jossa 237 lisäystä ja 194 poistoa
  1. 1 1
      AI/Nullkiller/AIUtility.cpp
  2. 2 2
      AI/Nullkiller/Pathfinding/AINodeStorage.cpp
  3. 1 1
      AI/VCAI/AIUtility.cpp
  4. 2 2
      AI/VCAI/Pathfinding/AINodeStorage.cpp
  5. 3 5
      client/HeroMovementController.cpp
  6. 3 3
      client/adventureMap/CMinimap.cpp
  7. 1 1
      client/adventureMap/MapAudioPlayer.cpp
  8. 12 12
      client/mapView/MapRenderer.cpp
  9. 1 1
      client/mapView/mapHandler.cpp
  10. 3 3
      client/windows/CMapOverview.cpp
  11. 1 1
      lib/CGameInfoCallback.cpp
  12. 1 1
      lib/IGameCallback.cpp
  13. 10 10
      lib/gameState/CGameState.cpp
  14. 1 1
      lib/mapObjectConstructors/CommonConstructors.cpp
  15. 5 5
      lib/mapObjects/CGHeroInstance.cpp
  16. 3 3
      lib/mapObjects/CGObjectInstance.cpp
  17. 1 1
      lib/mapObjects/CGTownInstance.cpp
  18. 2 2
      lib/mapObjects/IObjectInterface.cpp
  19. 6 6
      lib/mapping/CDrawRoadsOperation.cpp
  20. 69 26
      lib/mapping/CMap.cpp
  21. 22 9
      lib/mapping/CMapDefines.h
  22. 15 15
      lib/mapping/CMapOperation.cpp
  23. 1 1
      lib/mapping/MapEditUtils.cpp
  24. 3 7
      lib/mapping/MapFormatH3M.cpp
  25. 16 16
      lib/mapping/MapFormatJson.cpp
  26. 3 3
      lib/mapping/MapFormatJson.h
  27. 7 13
      lib/pathfinder/CPathfinder.cpp
  28. 2 2
      lib/pathfinder/NodeStorage.cpp
  29. 3 3
      lib/pathfinder/PathfinderUtil.h
  30. 2 2
      lib/pathfinder/PathfindingRules.cpp
  31. 4 4
      lib/rewardable/Interface.cpp
  32. 1 1
      lib/rmg/RmgObject.cpp
  33. 1 1
      lib/rmg/modificators/RoadPlacer.cpp
  34. 1 1
      lib/rmg/modificators/RockFiller.cpp
  35. 2 2
      lib/rmg/modificators/RockPlacer.cpp
  36. 2 2
      lib/rmg/modificators/WaterProxy.cpp
  37. 1 1
      lib/spells/AdventureSpellMechanics.cpp
  38. 1 1
      mapeditor/mainwindow.cpp
  39. 2 2
      mapeditor/mapcontroller.cpp
  40. 8 8
      mapeditor/maphandler.cpp
  41. 1 1
      mapeditor/mapview.cpp
  42. 2 2
      mapeditor/scenelayer.cpp
  43. 8 9
      server/CGameHandler.cpp
  44. 1 1
      server/battles/BattleProcessor.cpp

+ 1 - 1
AI/Nullkiller/AIUtility.cpp

@@ -193,7 +193,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
 {
 	// TODO: Such information should be provided by pathfinder
 	// Tile must be free or with unoccupied boat
-	if(!t->blocked)
+	if(!t->blocked())
 	{
 		return true;
 	}

+ 2 - 2
AI/Nullkiller/Pathfinding/AINodeStorage.cpp

@@ -130,10 +130,10 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
 				for(pos.y = 0; pos.y < sizes.y; ++pos.y)
 				{
 					const TerrainTile & tile = gs->map->getTile(pos);
-					if (!tile.terType->isPassable())
+					if (!tile.getTerrain()->isPassable())
 						continue;
 
-					if (tile.terType->isWater())
+					if (tile.isWater())
 					{
 						resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
 						if (useFlying)

+ 1 - 1
AI/VCAI/AIUtility.cpp

@@ -186,7 +186,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
 {
 	// TODO: Such information should be provided by pathfinder
 	// Tile must be free or with unoccupied boat
-	if(!t->blocked)
+	if(!t->blocked())
 	{
 		return true;
 	}

+ 2 - 2
AI/VCAI/Pathfinding/AINodeStorage.cpp

@@ -46,10 +46,10 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
 			for(pos.y=0; pos.y < sizes.y; ++pos.y)
 			{
 				const TerrainTile & tile = gs->map->getTile(pos);
-				if(!tile.terType->isPassable())
+				if(!tile.getTerrain()->isPassable())
 					continue;
 				
-				if(tile.terType->isWater())
+				if(tile.getTerrain()->isWater())
 				{
 					resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
 					if(useFlying)

+ 3 - 5
client/HeroMovementController.cpp

@@ -291,14 +291,12 @@ AudioPath HeroMovementController::getMovementSoundFor(const CGHeroInstance * her
 	auto prevTile = LOCPLINT->cb->getTile(posPrev);
 	auto nextTile = LOCPLINT->cb->getTile(posNext);
 
-	auto prevRoad = prevTile->roadType;
-	auto nextRoad = nextTile->roadType;
-	bool movingOnRoad = prevRoad->getId() != Road::NO_ROAD && nextRoad->getId() != Road::NO_ROAD;
+	bool movingOnRoad = prevTile->hasRoad() && nextTile->hasRoad();
 
 	if(movingOnRoad)
-		return nextTile->terType->horseSound;
+		return nextTile->getTerrain()->horseSound;
 	else
-		return nextTile->terType->horseSoundPenalty;
+		return nextTile->getTerrain()->horseSoundPenalty;
 };
 
 void HeroMovementController::updateMovementSound(const CGHeroInstance * h, int3 posPrev, int3 nextCoord, EPathNodeAction moveType)

+ 3 - 3
client/adventureMap/CMinimap.cpp

@@ -50,10 +50,10 @@ ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
 			return graphics->playerColors[player.getNum()];
 	}
 
-	if (tile->blocked && (!tile->visitable))
-		return tile->terType->minimapBlocked;
+	if (tile->blocked() && !tile->visitable())
+		return tile->getTerrain()->minimapBlocked;
 	else
-		return tile->terType->minimapUnblocked;
+		return tile->getTerrain()->minimapUnblocked;
 }
 
 void CMinimapInstance::refreshTile(const int3 &tile)

+ 1 - 1
client/adventureMap/MapAudioPlayer.cpp

@@ -182,7 +182,7 @@ void MapAudioPlayer::updateMusic()
 		const auto * tile = LOCPLINT->cb->getTile(currentSelection->visitablePos());
 
 		if (tile)
-			CCS->musich->playMusicFromSet("terrain", tile->terType->getJsonKey(), true, false);
+			CCS->musich->playMusicFromSet("terrain", tile->getTerrain()->getJsonKey(), true, false);
 	}
 
 	if(audioPlaying && enemyMakingTurn)

+ 12 - 12
client/mapView/MapRenderer.cpp

@@ -143,7 +143,7 @@ void MapRendererTerrain::renderTile(IMapRendererContext & context, Canvas & targ
 {
 	const TerrainTile & mapTile = context.getMapTile(coordinates);
 
-	int32_t terrainIndex = mapTile.terType->getIndex();
+	int32_t terrainIndex = mapTile.getTerrainID();
 	int32_t imageIndex = mapTile.terView;
 	int32_t rotationIndex = mapTile.extTileFlags % 4;
 
@@ -152,11 +152,11 @@ void MapRendererTerrain::renderTile(IMapRendererContext & context, Canvas & targ
 	assert(image);
 	if (!image)
 	{
-		logGlobal->error("Failed to find image %d for terrain %s on tile %s", imageIndex, mapTile.terType->getNameTranslated(), coordinates.toString());
+		logGlobal->error("Failed to find image %d for terrain %s on tile %s", imageIndex, mapTile.getTerrain()->getNameTranslated(), coordinates.toString());
 		return;
 	}
 
-	for( auto const & element : mapTile.terType->paletteAnimation)
+	for( auto const & element : mapTile.getTerrain()->paletteAnimation)
 		image->shiftPalette(element.start, element.length, context.terrainImageIndex(element.length));
 
 	target.draw(image, Point(0, 0));
@@ -166,7 +166,7 @@ uint8_t MapRendererTerrain::checksum(IMapRendererContext & context, const int3 &
 {
 	const TerrainTile & mapTile = context.getMapTile(coordinates);
 
-	if(!mapTile.terType->paletteAnimation.empty())
+	if(!mapTile.getTerrain()->paletteAnimation.empty())
 		return context.terrainImageIndex(250);
 	return 0xff - 1;
 }
@@ -184,16 +184,16 @@ void MapRendererRiver::renderTile(IMapRendererContext & context, Canvas & target
 {
 	const TerrainTile & mapTile = context.getMapTile(coordinates);
 
-	if(mapTile.riverType->getId() == River::NO_RIVER)
+	if(!mapTile.hasRiver())
 		return;
 
-	int32_t terrainIndex = mapTile.riverType->getIndex();
+	int32_t terrainIndex = mapTile.getRiverID();
 	int32_t imageIndex = mapTile.riverDir;
 	int32_t rotationIndex = (mapTile.extTileFlags >> 2) % 4;
 
 	const auto & image = storage.find(terrainIndex, rotationIndex, imageIndex);
 
-	for( auto const & element : mapTile.riverType->paletteAnimation)
+	for( auto const & element : mapTile.getRiver()->paletteAnimation)
 		image->shiftPalette(element.start, element.length, context.terrainImageIndex(element.length));
 
 	target.draw(image, Point(0, 0));
@@ -203,7 +203,7 @@ uint8_t MapRendererRiver::checksum(IMapRendererContext & context, const int3 & c
 {
 	const TerrainTile & mapTile = context.getMapTile(coordinates);
 
-	if(!mapTile.riverType->paletteAnimation.empty())
+	if(!mapTile.getRiver()->paletteAnimation.empty())
 		return context.terrainImageIndex(250);
 	return 0xff-1;
 }
@@ -224,9 +224,9 @@ void MapRendererRoad::renderTile(IMapRendererContext & context, Canvas & target,
 	if(context.isInMap(coordinatesAbove))
 	{
 		const TerrainTile & mapTileAbove = context.getMapTile(coordinatesAbove);
-		if(mapTileAbove.roadType->getId() != Road::NO_ROAD)
+		if(mapTileAbove.hasRoad())
 		{
-			int32_t terrainIndex = mapTileAbove.roadType->getIndex();
+			int32_t terrainIndex = mapTileAbove.getRoadID();
 			int32_t imageIndex = mapTileAbove.roadDir;
 			int32_t rotationIndex = (mapTileAbove.extTileFlags >> 4) % 4;
 
@@ -236,9 +236,9 @@ void MapRendererRoad::renderTile(IMapRendererContext & context, Canvas & target,
 	}
 
 	const TerrainTile & mapTile = context.getMapTile(coordinates);
-	if(mapTile.roadType->getId() != Road::NO_ROAD)
+	if(mapTile.hasRoad())
 	{
-		int32_t terrainIndex = mapTile.roadType->getIndex();
+		int32_t terrainIndex = mapTile.getRoadID();
 		int32_t imageIndex = mapTile.roadDir;
 		int32_t rotationIndex = (mapTile.extTileFlags >> 4) % 4;
 

+ 1 - 1
client/mapView/mapHandler.cpp

@@ -55,7 +55,7 @@ std::string CMapHandler::getTerrainDescr(const int3 & pos, bool rightClick) cons
 	if(t.hasFavorableWinds())
 		return CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS, 0);
 
-	std::string result = t.terType->getNameTranslated();
+	std::string result = t.getTerrain()->getNameTranslated();
 
 	for(const auto & object : map->objects)
 	{

+ 3 - 3
client/windows/CMapOverview.cpp

@@ -67,9 +67,9 @@ Canvas CMapOverviewWidget::createMinimapForLayer(std::unique_ptr<CMap> & map, in
 		{
 			TerrainTile & tile = map->getTile(int3(x, y, layer));
 
-			ColorRGBA color = tile.terType->minimapUnblocked;
-			if (tile.blocked && (!tile.visitable))
-				color = tile.terType->minimapBlocked;
+			ColorRGBA color = tile.getTerrain()->minimapUnblocked;
+			if (tile.blocked() && !tile.visitable())
+				color = tile.getTerrain()->minimapBlocked;
 
 			if(drawPlayerElements)
 				// if object at tile is owned - it will be colored as its owner

+ 1 - 1
lib/CGameInfoCallback.cpp

@@ -630,7 +630,7 @@ EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, Bu
 	{
 		const TerrainTile *tile = getTile(t->bestLocation(), false);
 
-		if(!tile || !tile->terType->isWater())
+		if(!tile || !tile->isWater())
 			return EBuildingState::NO_WATER; //lack of water
 	}
 

+ 1 - 1
lib/IGameCallback.cpp

@@ -72,7 +72,7 @@ void CPrivilegedInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
 			for (int yd = 0; yd < gs->map->height; yd++)
 			{
 				tinfo = getTile(int3 (xd,yd,zd));
-				if (tinfo->terType->isLand() && tinfo->terType->isPassable() && !tinfo->blocked) //land and free
+				if (tinfo->isLand() && tinfo->getTerrain()->isPassable() && !tinfo->blocked()) //land and free
 					tiles.emplace_back(xd, yd, zd);
 			}
 		}

+ 10 - 10
lib/gameState/CGameState.cpp

@@ -437,10 +437,10 @@ void CGameState::initGrailPosition()
 				for(int y = BORDER_WIDTH; y < map->height - BORDER_WIDTH; y++)
 				{
 					const TerrainTile &t = map->getTile(int3(x, y, z));
-					if(!t.blocked
-						&& !t.visitable
-						&& t.terType->isLand()
-						&& t.terType->isPassable()
+					if(!t.blocked()
+					   && !t.visitable()
+						&& t.isLand()
+						&& t.getTerrain()->isPassable()
 						&& (int)map->grailPos.dist2dSQ(int3(x, y, z)) <= (map->grailRadius * map->grailRadius))
 						allowedPos.emplace_back(x, y, z);
 				}
@@ -608,7 +608,7 @@ void CGameState::initHeroes()
 	{
 		assert(map->isInTheMap(hero->visitablePos()));
 		const auto & tile = map->getTile(hero->visitablePos());
-		if (tile.terType->isWater())
+		if (tile.isWater())
 		{
 			auto handler = VLC->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum());
 			auto boat = dynamic_cast<CGBoat*>(handler->create(callback, nullptr));
@@ -1074,10 +1074,10 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, vstd::RNG & rand)
 	if(map->isCoastalTile(tile)) //coastal tile is always ground
 		return BattleField(*VLC->identifiers()->getIdentifier("core", "battlefield.sand_shore"));
 	
-	if (t.terType->battleFields.empty())
-		throw std::runtime_error("Failed to find battlefield for terrain " + t.terType->getJsonKey());
+	if (t.getTerrain()->battleFields.empty())
+		throw std::runtime_error("Failed to find battlefield for terrain " + t.getTerrain()->getJsonKey());
 
-	return BattleField(*RandomGeneratorUtil::nextItem(t.terType->battleFields, rand));
+	return BattleField(*RandomGeneratorUtil::nextItem(t.getTerrain()->battleFields, rand));
 }
 
 void CGameState::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
@@ -1171,7 +1171,7 @@ std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
 		return guards;
 
 	const TerrainTile &posTile = map->getTile(pos);
-	if (posTile.visitable)
+	if (posTile.visitable())
 	{
 		for (CGObjectInstance* obj : posTile.visitableObjects)
 		{
@@ -1190,7 +1190,7 @@ std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
 			if (map->isInTheMap(pos))
 			{
 				const auto & tile = map->getTile(pos);
-				if (tile.visitable && (tile.isWater() == posTile.isWater()))
+				if (tile.visitable() && (tile.isWater() == posTile.isWater()))
 				{
 					for (CGObjectInstance* obj : tile.visitableObjects)
 					{

+ 1 - 1
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -101,7 +101,7 @@ void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const
 
 void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, vstd::RNG & rng) const
 {
-	auto templ = getOverride(object->cb->getTile(object->pos)->terType->getId(), object);
+	auto templ = getOverride(object->cb->getTile(object->pos)->getTerrainID(), object);
 	if(templ)
 		object->appearance = templ;
 }

+ 5 - 5
lib/mapObjects/CGHeroInstance.cpp

@@ -102,16 +102,16 @@ ui32 CGHeroInstance::getTileMovementCost(const TerrainTile & dest, const Terrain
 	int64_t ret = GameConstants::BASE_MOVEMENT_COST;
 
 	//if there is road both on dest and src tiles - use src road movement cost
-	if(dest.roadType->getId() != Road::NO_ROAD && from.roadType->getId() != Road::NO_ROAD)
+	if(dest.hasRoad() && from.hasRoad())
 	{
-		ret = from.roadType->movementCost;
+		ret = from.getRoad()->movementCost;
 	}
-	else if(ti->nativeTerrain != from.terType->getId() &&//the terrain is not native
+	else if(ti->nativeTerrain != from.getTerrainID() &&//the terrain is not native
 			ti->nativeTerrain != ETerrainId::ANY_TERRAIN && //no special creature bonus
-			!ti->hasBonusOfType(BonusType::NO_TERRAIN_PENALTY, BonusSubtypeID(from.terType->getId()))) //no special movement bonus
+			!ti->hasBonusOfType(BonusType::NO_TERRAIN_PENALTY, BonusSubtypeID(from.getTerrainID()))) //no special movement bonus
 	{
 
-		ret = VLC->terrainTypeHandler->getById(from.terType->getId())->moveCost;
+		ret = VLC->terrainTypeHandler->getById(from.getTerrainID())->moveCost;
 		ret -= ti->valOfBonuses(BonusType::ROUGH_TERRAIN_DISCOUNT);
 		if(ret < GameConstants::BASE_MOVEMENT_COST)
 			ret = GameConstants::BASE_MOVEMENT_COST;

+ 3 - 3
lib/mapObjects/CGObjectInstance.cpp

@@ -128,13 +128,13 @@ void CGObjectInstance::setType(MapObjectID newID, MapObjectSubID newSubID)
 	cb->gameState()->map->removeBlockVisTiles(this, true);
 	auto handler = VLC->objtypeh->getHandlerFor(newID, newSubID);
 
-	if(!handler->getTemplates(tile.terType->getId()).empty())
+	if(!handler->getTemplates(tile.getTerrainID()).empty())
 	{
-		appearance = handler->getTemplates(tile.terType->getId())[0];
+		appearance = handler->getTemplates(tile.getTerrainID())[0];
 	}
 	else
 	{
-		logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", newID, newSubID, visitablePos().toString(), tile.terType->getNameTranslated());
+		logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", newID, newSubID, visitablePos().toString(), tile.getTerrain()->getNameTranslated());
 		appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
 	}
 

+ 1 - 1
lib/mapObjects/CGTownInstance.cpp

@@ -692,7 +692,7 @@ ObjectInstanceID CGTownInstance::getObjInstanceID() const
 
 void CGTownInstance::updateAppearance()
 {
-	auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId();
+	auto terrain = cb->gameState()->getTile(visitablePos())->getTerrainID();
 	//FIXME: not the best way to do this
 	auto app = getObjectHandler()->getOverride(terrain, this);
 	if (app)

+ 2 - 2
lib/mapObjects/IObjectInterface.cpp

@@ -90,10 +90,10 @@ int3 IBoatGenerator::bestLocation() const
 		if(!tile)
 			continue; // tile not visible / outside the map
 
-		if(!tile->terType->isWater())
+		if(!tile->isWater())
 			continue;
 
-		if (tile->blocked)
+		if (tile->blocked())
 		{
 			bool hasBoat = false;
 			for (auto const * object : tile->blockingObjects)

+ 6 - 6
lib/mapping/CDrawRoadsOperation.cpp

@@ -344,12 +344,12 @@ std::string CDrawRiversOperation::getLabel() const
 
 void CDrawRoadsOperation::executeTile(TerrainTile & tile)
 {
-	tile.roadType = const_cast<RoadType*>(VLC->roadTypeHandler->getByIndex(roadType.getNum()));
+	tile.roadType = roadType;
 }
 
 void CDrawRiversOperation::executeTile(TerrainTile & tile)
 {
-	tile.riverType = const_cast<RiverType*>(VLC->riverTypeHandler->getByIndex(riverType.getNum()));
+	tile.riverType = riverType;
 }
 
 bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const
@@ -364,22 +364,22 @@ bool CDrawRiversOperation::canApplyPattern(const LinePattern & pattern) const
 
 bool CDrawRoadsOperation::needUpdateTile(const TerrainTile & tile) const
 {
-	return tile.roadType->getId() != Road::NO_ROAD;
+	return tile.hasRoad();
 }
 
 bool CDrawRiversOperation::needUpdateTile(const TerrainTile & tile) const
 {
-	return tile.riverType->getId() != River::NO_RIVER;
+	return tile.hasRiver();
 }
 
 bool CDrawRoadsOperation::tileHasSomething(const int3& pos) const
 {
-	return map->getTile(pos).roadType->getId() != Road::NO_ROAD;
+	return map->getTile(pos).hasRoad();
 }
 
 bool CDrawRiversOperation::tileHasSomething(const int3& pos) const
 {
-	return map->getTile(pos).riverType->getId() != River::NO_RIVER;
+	return map->getTile(pos).hasRiver();
 }
 
 void CDrawRoadsOperation::updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip)

+ 69 - 26
lib/mapping/CMap.cpp

@@ -131,32 +131,29 @@ void CCastleEvent::serializeJson(JsonSerializeFormat & handler)
 }
 
 TerrainTile::TerrainTile():
-	terType(nullptr),
-	riverType(VLC->riverTypeHandler->getById(River::NO_RIVER)),
-	roadType(VLC->roadTypeHandler->getById(Road::NO_ROAD)),
+	riverType(River::NO_RIVER),
+	roadType(Road::NO_ROAD),
 	terView(0),
 	riverDir(0),
 	roadDir(0),
-	extTileFlags(0),
-	visitable(false),
-	blocked(false)
+	extTileFlags(0)
 {
 }
 
 bool TerrainTile::entrableTerrain(const TerrainTile * from) const
 {
-	return entrableTerrain(from ? from->terType->isLand() : true, from ? from->terType->isWater() : true);
+	return entrableTerrain(from ? from->isLand() : true, from ? from->isWater() : true);
 }
 
 bool TerrainTile::entrableTerrain(bool allowLand, bool allowSea) const
 {
-	return terType->isPassable()
-			&& ((allowSea && terType->isWater())  ||  (allowLand && terType->isLand()));
+	return getTerrain()->isPassable()
+			&& ((allowSea && isWater())  ||  (allowLand && isLand()));
 }
 
 bool TerrainTile::isClear(const TerrainTile * from) const
 {
-	return entrableTerrain(from) && !blocked;
+	return entrableTerrain(from) && !blocked();
 }
 
 Obj TerrainTile::topVisitableId(bool excludeTop) const
@@ -177,7 +174,7 @@ CGObjectInstance * TerrainTile::topVisitableObj(bool excludeTop) const
 
 EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
 {
-	if(terType->isWater() || !terType->isPassable())
+	if(isWater() || !getTerrain()->isPassable())
 		return EDiggingStatus::WRONG_TERRAIN;
 
 	int allowedBlocked = excludeTop ? 1 : 0;
@@ -194,9 +191,65 @@ bool TerrainTile::hasFavorableWinds() const
 
 bool TerrainTile::isWater() const
 {
-	return terType->isWater();
+	return getTerrain()->isWater();
 }
 
+bool TerrainTile::isLand() const
+{
+	return getTerrain()->isLand();
+}
+
+bool TerrainTile::visitable() const
+{
+	return !visitableObjects.empty();
+}
+
+bool TerrainTile::blocked() const
+{
+	return !blockingObjects.empty();
+}
+
+bool TerrainTile::hasRiver() const
+{
+	return getRiverID() != RiverId::NO_RIVER;
+}
+
+bool TerrainTile::hasRoad() const
+{
+	return getRoadID() != RoadId::NO_ROAD;
+}
+
+const TerrainType * TerrainTile::getTerrain() const
+{
+	return terrainType.toEntity(VLC);
+}
+
+const RiverType * TerrainTile::getRiver() const
+{
+	return riverType.toEntity(VLC);
+}
+
+const RoadType * TerrainTile::getRoad() const
+{
+	return roadType.toEntity(VLC);
+}
+
+TerrainId TerrainTile::getTerrainID() const
+{
+	return terrainType;
+}
+
+RiverId TerrainTile::getRiverID() const
+{
+	return riverType;
+}
+
+RoadId TerrainTile::getRoadID() const
+{
+	return roadType;
+}
+
+
 CMap::CMap(IGameCallback * cb)
 	: GameCallbackHolder(cb)
 	, checksum(0)
@@ -243,15 +296,10 @@ void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
 			{
 				TerrainTile & curt = terrain[zVal][xVal][yVal];
 				if(total || obj->visitableAt(int3(xVal, yVal, zVal)))
-				{
 					curt.visitableObjects -= obj;
-					curt.visitable = curt.visitableObjects.size();
-				}
+
 				if(total || obj->blockingAt(int3(xVal, yVal, zVal)))
-				{
 					curt.blockingObjects -= obj;
-					curt.blocked = curt.blockingObjects.size();
-				}
 			}
 		}
 	}
@@ -270,15 +318,10 @@ void CMap::addBlockVisTiles(CGObjectInstance * obj)
 			{
 				TerrainTile & curt = terrain[zVal][xVal][yVal];
 				if(obj->visitableAt(int3(xVal, yVal, zVal)))
-				{
 					curt.visitableObjects.push_back(obj);
-					curt.visitable = true;
-				}
+
 				if(obj->blockingAt(int3(xVal, yVal, zVal)))
-				{
 					curt.blockingObjects.push_back(obj);
-					curt.blocked = true;
-				}
 			}
 		}
 	}
@@ -381,7 +424,7 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
 	if (!isInTheMap(pos))
 		return int3(-1, -1, -1);
 	const TerrainTile &posTile = getTile(pos);
-	if (posTile.visitable)
+	if (posTile.visitable())
 	{
 		for (CGObjectInstance* obj : posTile.visitableObjects)
 		{
@@ -401,7 +444,7 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
 			if (isInTheMap(pos))
 			{
 				const auto & tile = getTile(pos);
-                if (tile.visitable && (tile.isWater() == water))
+				if (tile.visitable() && (tile.isWater() == water))
 				{
 					for (CGObjectInstance* obj : tile.visitableObjects)
 					{

+ 22 - 9
lib/mapping/CMapDefines.h

@@ -104,20 +104,33 @@ struct DLL_LINKAGE TerrainTile
 	Obj topVisitableId(bool excludeTop = false) const;
 	CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
 	bool isWater() const;
-	EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
+	bool isLand() const;
+	EDiggingStatus getDiggingStatus(bool excludeTop = true) const;
 	bool hasFavorableWinds() const;
 
-	const TerrainType * terType;
-	const RiverType * riverType;
-	const RoadType * roadType;
+	bool visitable() const;
+	bool blocked() const;
+
+	const TerrainType * getTerrain() const;
+	const RiverType * getRiver() const;
+	const RoadType * getRoad() const;
+
+	TerrainId getTerrainID() const;
+	RiverId getRiverID() const;
+	RoadId getRoadID() const;
+
+	bool hasRiver() const;
+	bool hasRoad() const;
+
+	TerrainId terrainType;
+	RiverId riverType;
+	RoadId roadType;
 	ui8 terView;
 	ui8 riverDir;
 	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
 	ui8 extTileFlags;
-	bool visitable;
-	bool blocked;
 
 	std::vector<CGObjectInstance *> visitableObjects;
 	std::vector<CGObjectInstance *> blockingObjects;
@@ -125,15 +138,15 @@ struct DLL_LINKAGE TerrainTile
 	template <typename Handler>
 	void serialize(Handler & h)
 	{
-		h & terType;
+		h & terrainType;
 		h & terView;
 		h & riverType;
 		h & riverDir;
 		h & roadType;
 		h & roadDir;
 		h & extTileFlags;
-		h & visitable;
-		h & blocked;
+	//	h & visitable;
+	//	h & blocked;
 		h & visitableObjects;
 		h & blockingObjects;
 	}

+ 15 - 15
lib/mapping/CMapOperation.cpp

@@ -103,7 +103,7 @@ void CDrawTerrainOperation::execute()
 	for(const auto & pos : terrainSel.getSelectedItems())
 	{
 		auto & tile = map->getTile(pos);
-		tile.terType = const_cast<TerrainType*>(VLC->terrainTypeHandler->getById(terType));
+		tile.terrainType = terType;
 		invalidateTerrainViews(pos);
 	}
 
@@ -137,7 +137,7 @@ void CDrawTerrainOperation::updateTerrainTypes()
 		auto tiles = getInvalidTiles(centerPos);
 		auto updateTerrainType = [&](const int3& pos)
 		{
-			map->getTile(pos).terType = centerTile.terType;
+			map->getTile(pos).terrainType = centerTile.terrainType;
 			positions.insert(pos);
 			invalidateTerrainViews(pos);
 			//logGlobal->debug("Set additional terrain tile at pos '%s' to type '%s'", pos, centerTile.terType);
@@ -161,10 +161,10 @@ void CDrawTerrainOperation::updateTerrainTypes()
 			rect.forEach([&](const int3& posToTest)
 				{
 					auto & terrainTile = map->getTile(posToTest);
-					if(centerTile.terType->getId() != terrainTile.terType->getId())
+					if(centerTile.getTerrain() != terrainTile.getTerrain())
 					{
-						const auto * formerTerType = terrainTile.terType;
-						terrainTile.terType = centerTile.terType;
+						const auto formerTerType = terrainTile.terrainType;
+						terrainTile.terrainType = centerTile.terrainType;
 						auto testTile = getInvalidTiles(posToTest);
 
 						int nativeTilesCntNorm = testTile.nativeTiles.empty() ? std::numeric_limits<int>::max() : static_cast<int>(testTile.nativeTiles.size());
@@ -221,7 +221,7 @@ void CDrawTerrainOperation::updateTerrainTypes()
 							suitableTiles.insert(posToTest);
 						}
 
-						terrainTile.terType = formerTerType;
+						terrainTile.terrainType = formerTerType;
 					}
 				});
 
@@ -264,7 +264,7 @@ void CDrawTerrainOperation::updateTerrainViews()
 {
 	for(const auto & pos : invalidatedTerViews)
 	{
-		const auto & patterns = VLC->terviewh->getTerrainViewPatterns(map->getTile(pos).terType->getId());
+		const auto & patterns = VLC->terviewh->getTerrainViewPatterns(map->getTile(pos).getTerrainID());
 
 		// Detect a pattern which fits best
 		int bestPattern = -1;
@@ -340,7 +340,7 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
 
 CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainViewInner(const int3& pos, const TerrainViewPattern& pattern, int recDepth) const
 {
-	const auto * centerTerType = map->getTile(pos).terType;
+	const auto * centerTerType = map->getTile(pos).getTerrain();
 	int totalPoints = 0;
 	std::string transitionReplacement;
 
@@ -372,24 +372,24 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
 			}
 			else if(widthTooHigh)
 			{
-				terType = map->getTile(int3(currentPos.x - 1, currentPos.y, currentPos.z)).terType;
+				terType = map->getTile(int3(currentPos.x - 1, currentPos.y, currentPos.z)).getTerrain();
 			}
 			else if(heightTooHigh)
 			{
-				terType = map->getTile(int3(currentPos.x, currentPos.y - 1, currentPos.z)).terType;
+				terType = map->getTile(int3(currentPos.x, currentPos.y - 1, currentPos.z)).getTerrain();
 			}
 			else if(widthTooLess)
 			{
-				terType = map->getTile(int3(currentPos.x + 1, currentPos.y, currentPos.z)).terType;
+				terType = map->getTile(int3(currentPos.x + 1, currentPos.y, currentPos.z)).getTerrain();
 			}
 			else if(heightTooLess)
 			{
-				terType = map->getTile(int3(currentPos.x, currentPos.y + 1, currentPos.z)).terType;
+				terType = map->getTile(int3(currentPos.x, currentPos.y + 1, currentPos.z)).getTerrain();
 			}
 		}
 		else
 		{
-			terType = map->getTile(currentPos).terType;
+			terType = map->getTile(currentPos).getTerrain();
 			if(terType != centerTerType && (terType->isPassable() || centerTerType->isPassable()))
 			{
 				isAlien = true;
@@ -509,13 +509,13 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
 {
 	//TODO: this is very expensive function for RMG, needs optimization
 	InvalidTiles tiles;
-	const auto * centerTerType = map->getTile(centerPos).terType;
+	const auto * centerTerType = map->getTile(centerPos).getTerrain();
 	auto rect = extendTileAround(centerPos);
 	rect.forEach([&](const int3& pos)
 		{
 			if(map->isInTheMap(pos))
 			{
-				const auto * terType = map->getTile(pos).terType;
+				const auto * terType = map->getTile(pos).getTerrain();
 				auto valid = validateTerrainView(pos, VLC->terviewh->getTerrainTypePatternById("n1")).result;
 
 				// Special validity check for rock & water

+ 1 - 1
lib/mapping/MapEditUtils.cpp

@@ -356,7 +356,7 @@ void CTerrainViewPatternUtils::printDebuggingInfoAboutTile(const CMap * map, con
 			{
 				auto debugTile = map->getTile(debugPos);
 
-				std::string terType = debugTile.terType->shortIdentifier;
+				std::string terType = debugTile.getTerrain()->shortIdentifier;
 				line += terType;
 				line.insert(line.end(), PADDED_LENGTH - terType.size(), ' ');
 			}

+ 3 - 7
lib/mapping/MapFormatH3M.cpp

@@ -988,17 +988,13 @@ void CMapLoaderH3M::readTerrain()
 			for(pos.x = 0; pos.x < map->width; pos.x++)
 			{
 				auto & tile = map->getTile(pos);
-				tile.terType = VLC->terrainTypeHandler->getById(reader->readTerrain());
+				tile.terrainType = reader->readTerrain();
 				tile.terView = reader->readUInt8();
-				tile.riverType = VLC->riverTypeHandler->getById(reader->readRiver());
+				tile.riverType = reader->readRiver();
 				tile.riverDir = reader->readUInt8();
-				tile.roadType = VLC->roadTypeHandler->getById(reader->readRoad());
+				tile.roadType = reader->readRoad();
 				tile.roadDir = reader->readUInt8();
 				tile.extTileFlags = reader->readUInt8();
-				tile.blocked = !tile.terType->isPassable();
-				tile.visitable = false;
-
-				assert(tile.terType->getId() != ETerrainId::NONE);
 			}
 		}
 	}

+ 16 - 16
lib/mapping/MapFormatJson.cpp

@@ -260,34 +260,34 @@ CMapFormatJson::CMapFormatJson():
 
 }
 
-TerrainType * CMapFormatJson::getTerrainByCode(const std::string & code)
+TerrainId CMapFormatJson::getTerrainByCode(const std::string & code)
 {
 	for(const auto & object : VLC->terrainTypeHandler->objects)
 	{
 		if(object->shortIdentifier == code)
-			return const_cast<TerrainType *>(object.get());
+			return object->getId();
 	}
-	return nullptr;
+	return TerrainId::NONE;
 }
 
-RiverType * CMapFormatJson::getRiverByCode(const std::string & code)
+RiverId CMapFormatJson::getRiverByCode(const std::string & code)
 {
 	for(const auto & object : VLC->riverTypeHandler->objects)
 	{
 		if (object->shortIdentifier == code)
-			return const_cast<RiverType *>(object.get());
+			return object->getId();
 	}
-	return nullptr;
+	return RiverId::NO_RIVER;
 }
 
-RoadType * CMapFormatJson::getRoadByCode(const std::string & code)
+RoadId CMapFormatJson::getRoadByCode(const std::string & code)
 {
 	for(const auto & object : VLC->roadTypeHandler->objects)
 	{
 		if (object->shortIdentifier == code)
-			return const_cast<RoadType *>(object.get());
+			return object->getId();
 	}
-	return nullptr;
+	return RoadId::NO_ROAD;
 }
 
 void CMapFormatJson::serializeAllowedFactions(JsonSerializeFormat & handler, std::set<FactionID> & value) const
@@ -890,7 +890,7 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
 		using namespace TerrainDetail;
 		{//terrain type
 			const std::string typeCode = src.substr(0, 2);
-			tile.terType = getTerrainByCode(typeCode);
+			tile.terrainType = getTerrainByCode(typeCode);
 		}
 		int startPos = 2; //0+typeCode fixed length
 		{//terrain view
@@ -920,7 +920,7 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
 			tile.roadType = getRoadByCode(typeCode);
 			if(!tile.roadType) //it's not a road, it's a river
 			{
-				tile.roadType = VLC->roadTypeHandler->getById(Road::NO_ROAD);
+				tile.roadType = Road::NO_ROAD;
 				tile.riverType = getRiverByCode(typeCode);
 				hasRoad = false;
 				if(!tile.riverType)
@@ -1254,13 +1254,13 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile)
 	out.setf(std::ios::dec, std::ios::basefield);
 	out.unsetf(std::ios::showbase);
 
-	out << tile.terType->shortIdentifier << static_cast<int>(tile.terView) << flipCodes[tile.extTileFlags % 4];
+	out << tile.getTerrain()->shortIdentifier << static_cast<int>(tile.terView) << flipCodes[tile.extTileFlags % 4];
 
-	if(tile.roadType->getId() != Road::NO_ROAD)
-		out << tile.roadType->shortIdentifier << static_cast<int>(tile.roadDir) << flipCodes[(tile.extTileFlags >> 4) % 4];
+	if(tile.hasRoad())
+		out << tile.getRoad()->shortIdentifier << static_cast<int>(tile.roadDir) << flipCodes[(tile.extTileFlags >> 4) % 4];
 
-	if(tile.riverType->getId() != River::NO_RIVER)
-		out << tile.riverType->shortIdentifier << static_cast<int>(tile.riverDir) << flipCodes[(tile.extTileFlags >> 2) % 4];
+	if(tile.hasRiver())
+		out << tile.getRiver()->shortIdentifier << static_cast<int>(tile.riverDir) << flipCodes[(tile.extTileFlags >> 2) % 4];
 
 	return out.str();
 }

+ 3 - 3
lib/mapping/MapFormatJson.h

@@ -60,9 +60,9 @@ protected:
 
 	CMapFormatJson();
 
-	static TerrainType * getTerrainByCode(const std::string & code);
-	static RiverType * getRiverByCode(const std::string & code);
-	static RoadType * getRoadByCode(const std::string & code);
+	static TerrainId getTerrainByCode(const std::string & code);
+	static RiverId getRiverByCode(const std::string & code);
+	static RoadId getRoadByCode(const std::string & code);
 
 	void serializeAllowedFactions(JsonSerializeFormat & handler, std::set<FactionID> & value) const;
 

+ 7 - 13
lib/pathfinder/CPathfinder.cpp

@@ -596,25 +596,19 @@ void CPathfinderHelper::getNeighbours(
 			continue;
 
 		const TerrainTile & destTile = map->getTile(destCoord);
-		if(!destTile.terType->isPassable())
+		if(!destTile.getTerrain()->isPassable())
 			continue;
 
-// 		//we cannot visit things from blocked tiles
-// 		if(srcTile.blocked && !srcTile.visitable && destTile.visitable && srcTile.blockingObjects.front()->ID != HEROI_TYPE)
-// 		{
-// 			continue;
-// 		}
-
 		/// Following condition let us avoid diagonal movement over coast when sailing
-		if(srcTile.terType->isWater() && limitCoastSailing && destTile.terType->isWater() && dir.x && dir.y) //diagonal move through water
+		if(srcTile.isWater() && limitCoastSailing && destTile.isWater() && dir.x && dir.y) //diagonal move through water
 		{
 			const int3 horizontalNeighbour = srcCoord + int3{dir.x, 0, 0};
 			const int3 verticalNeighbour = srcCoord + int3{0, dir.y, 0};
-			if(map->getTile(horizontalNeighbour).terType->isLand() || map->getTile(verticalNeighbour).terType->isLand())
+			if(map->getTile(horizontalNeighbour).isLand() || map->getTile(verticalNeighbour).isLand())
 				continue;
 		}
 
-		if(indeterminate(onLand) || onLand == destTile.terType->isLand())
+		if(indeterminate(onLand) || onLand == destTile.isLand())
 		{
 			vec.push_back(destCoord);
 		}
@@ -662,13 +656,13 @@ int CPathfinderHelper::getMovementCost(
 
 	bool isSailLayer;
 	if(indeterminate(isDstSailLayer))
-		isSailLayer = hero->boat && hero->boat->layer == EPathfindingLayer::SAIL && dt->terType->isWater();
+		isSailLayer = hero->boat && hero->boat->layer == EPathfindingLayer::SAIL && dt->isWater();
 	else
 		isSailLayer = static_cast<bool>(isDstSailLayer);
 
 	bool isWaterLayer;
 	if(indeterminate(isDstWaterLayer))
-		isWaterLayer = ((hero->boat && hero->boat->layer == EPathfindingLayer::WATER) || ti->hasBonusOfType(BonusType::WATER_WALKING)) && dt->terType->isWater();
+		isWaterLayer = ((hero->boat && hero->boat->layer == EPathfindingLayer::WATER) || ti->hasBonusOfType(BonusType::WATER_WALKING)) && dt->isWater();
 	else
 		isWaterLayer = static_cast<bool>(isDstWaterLayer);
 	
@@ -703,7 +697,7 @@ int CPathfinderHelper::getMovementCost(
 	{
 		NeighbourTilesVector vec;
 
-		getNeighbours(*dt, dst, vec, ct->terType->isLand(), true);
+		getNeighbours(*dt, dst, vec, ct->isLand(), true);
 		for(const auto & elem : vec)
 		{
 			int fcost = getMovementCost(dst, elem, nullptr, nullptr, left, false);

+ 2 - 2
lib/pathfinder/NodeStorage.cpp

@@ -41,7 +41,7 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState
 			for(pos.y=0; pos.y < sizes.y; ++pos.y)
 			{
 				const TerrainTile & tile = gs->map->getTile(pos);
-				if(tile.terType->isWater())
+				if(tile.isWater())
 				{
 					resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
 					if(useFlying)
@@ -49,7 +49,7 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState
 					if(useWaterWalking)
 						resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs));
 				}
-				if(tile.terType->isLand())
+				if(tile.isLand())
 				{
 					resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs));
 					if(useFlying)

+ 3 - 3
lib/pathfinder/PathfinderUtil.h

@@ -32,7 +32,7 @@ namespace PathfinderUtil
 		{
 		case ELayer::LAND:
 		case ELayer::SAIL:
-			if(tinfo.visitable)
+			if(tinfo.visitable())
 			{
 				if(tinfo.visitableObjects.front()->ID == Obj::SANCTUARY && tinfo.visitableObjects.back()->ID == Obj::HERO && tinfo.visitableObjects.back()->tempOwner != player) //non-owned hero stands on Sanctuary
 				{
@@ -51,7 +51,7 @@ namespace PathfinderUtil
 					}
 				}
 			}
-			else if(tinfo.blocked)
+			else if(tinfo.blocked())
 			{
 				return EPathAccessibility::BLOCKED;
 			}
@@ -64,7 +64,7 @@ namespace PathfinderUtil
 			break;
 
 		case ELayer::WATER:
-			if(tinfo.blocked || tinfo.terType->isLand())
+			if(tinfo.blocked() || tinfo.isLand())
 				return EPathAccessibility::BLOCKED;
 
 			break;

+ 2 - 2
lib/pathfinder/PathfindingRules.cpp

@@ -380,7 +380,7 @@ void LayerTransitionRule::process(
 
 	case EPathfindingLayer::SAIL:
 		// have to disembark first before visiting objects on land
-		if (destination.tile->visitable)
+		if (destination.tile->visitable())
 			destination.blocked = true;
 
 		//can disembark only on accessible tiles or tiles guarded by nearby monster
@@ -397,7 +397,7 @@ void LayerTransitionRule::process(
 				if (destination.node->accessible == EPathAccessibility::BLOCKVIS)
 				{
 					// Can't visit 'blockvisit' objects on coast if hero will end up on water terrain
-					if (source.tile->blocked || !destination.tile->entrableTerrain(source.tile))
+					if (source.tile->blocked() || !destination.tile->entrableTerrain(source.tile))
 						destination.blocked = true;
 				}
 			}

+ 4 - 4
lib/rewardable/Interface.cpp

@@ -63,16 +63,16 @@ void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo
 		const auto functor = [&props](const TerrainTile * tile)
 		{
 			int score = 0;
-			if (tile->terType->isSurface())
+			if (tile->getTerrain()->isSurface())
 				score += props.scoreSurface;
 
-			if (tile->terType->isUnderground())
+			if (tile->getTerrain()->isUnderground())
 				score += props.scoreSubterra;
 
-			if (tile->terType->isWater())
+			if (tile->getTerrain()->isWater())
 				score += props.scoreWater;
 
-			if (tile->terType->isRock())
+			if (tile->getTerrain()->isRock())
 				score += props.scoreRock;
 
 			return score > 0;

+ 1 - 1
lib/rmg/RmgObject.cpp

@@ -484,7 +484,7 @@ void Object::Instance::finalize(RmgMap & map, vstd::RNG & rng)
 	//If no specific template was defined for this object, select any matching
 	if (!dObject.appearance)
 	{
-		const auto * terrainType = map.getTile(getPosition(true)).terType;
+		const auto * terrainType = map.getTile(getPosition(true)).getTerrain();
 		auto templates = dObject.getObjectHandler()->getTemplates(terrainType->getId());
 		if (templates.empty())
 		{

+ 1 - 1
lib/rmg/modificators/RoadPlacer.cpp

@@ -149,7 +149,7 @@ void RoadPlacer::drawRoads(bool secondary)
 	//Do not draw roads on underground rock or water
 	roads.erase_if([this](const int3& pos) -> bool
 	{
-		const auto* terrain = map.getTile(pos).terType;
+		const auto* terrain = map.getTile(pos).getTerrain();
 		return !terrain->isPassable() || !terrain->isLand();
 	});
 

+ 1 - 1
lib/rmg/modificators/RockFiller.cpp

@@ -72,7 +72,7 @@ void RockFiller::init()
 
 char RockFiller::dump(const int3 & t)
 {
-	if(!map.getTile(t).terType->isPassable())
+	if(!map.getTile(t).getTerrain()->isPassable())
 	{
 		return zone.area()->contains(t) ? 'R' : 'E';
 	}

+ 2 - 2
lib/rmg/modificators/RockPlacer.cpp

@@ -60,7 +60,7 @@ void RockPlacer::postProcess()
 		//Finally mark rock tiles as occupied, spawn no obstacles there
 		rockArea = zone.area()->getSubarea([this](const int3 & t)
 		{
-			return !map.getTile(t).terType->isPassable();
+			return !map.getTile(t).getTerrain()->isPassable();
 		});
 
 		// Do not place rock on roads
@@ -96,7 +96,7 @@ void RockPlacer::init()
 
 char RockPlacer::dump(const int3 & t)
 {
-	if(!map.getTile(t).terType->isPassable())
+	if(!map.getTile(t).getTerrain()->isPassable())
 	{
 		return zone.area()->contains(t) ? 'R' : 'E';
 	}

+ 2 - 2
lib/rmg/modificators/WaterProxy.cpp

@@ -51,7 +51,7 @@ void WaterProxy::process()
 	for([[maybe_unused]] const auto & t : area->getTilesVector())
 	{
 		assert(map.isOnMap(t));
-		assert(map.getTile(t).terType->getId() == zone.getTerrainType());
+		assert(map.getTile(t).getTerrainID() == zone.getTerrainType());
 	}
 
 	// FIXME: Possible deadlock for 2 zones
@@ -66,7 +66,7 @@ void WaterProxy::process()
 		auto secondAreaPossible = z.second->areaPossible();
 		for(const auto & t : secondArea->getTilesVector())
 		{
-			if(map.getTile(t).terType->getId() == zone.getTerrainType())
+			if(map.getTile(t).getTerrainID() == zone.getTerrainType())
 			{
 				secondArea->erase(t);
 				secondAreaPossible->erase(t);

+ 1 - 1
lib/spells/AdventureSpellMechanics.cpp

@@ -374,7 +374,7 @@ bool DimensionDoorMechanics::canBeCastAtImpl(spells::Problem & problem, const CG
 	}
 	else
 	{
-		if (dest->blocked)
+		if (dest->blocked())
 			return false;
 	}
 

+ 1 - 1
mapeditor/mainwindow.cpp

@@ -1123,7 +1123,7 @@ void MainWindow::on_actionUpdate_appearance_triggered()
 			continue;
 		}
 		
-		auto * terrain = controller.map()->getTile(obj->visitablePos()).terType;
+		auto * terrain = controller.map()->getTile(obj->visitablePos()).getTerrain();
 		
 		if(handler->isStaticObject())
 		{

+ 2 - 2
mapeditor/mapcontroller.cpp

@@ -429,10 +429,10 @@ void MapController::commitObstacleFill(int level)
 	for(auto & t : selection)
 	{
 		auto tl = _map->getTile(t);
-		if(tl.blocked || tl.visitable)
+		if(tl.blocked() || tl.visitable())
 			continue;
 		
-		auto terrain = tl.terType->getId();
+		auto terrain = tl.getTerrainID();
 		_obstaclePainters[terrain]->addBlockedTile(t);
 	}
 	

+ 8 - 8
mapeditor/maphandler.cpp

@@ -93,7 +93,7 @@ void MapHandler::drawTerrainTile(QPainter & painter, int x, int y, int z)
 	auto & tinfo = map->getTile(int3(x, y, z));
 	ui8 rotation = tinfo.extTileFlags % 4;
 	
-	auto terrainName = tinfo.terType->getJsonKey();
+	auto terrainName = tinfo.getTerrain()->getJsonKey();
 	
 	if(terrainImages.at(terrainName).size() <= tinfo.terView)
 		return;
@@ -110,7 +110,7 @@ void MapHandler::drawRoad(QPainter & painter, int x, int y, int z)
 	
 	if(tinfoUpper && tinfoUpper->roadType)
 	{
-		auto roadName = tinfoUpper->roadType->getJsonKey();
+		auto roadName = tinfoUpper->getRoad()->getJsonKey();
 		QRect source(0, tileSize / 2, tileSize, tileSize / 2);
 		ui8 rotation = (tinfoUpper->extTileFlags >> 4) % 4;
 		bool hflip = (rotation == 1 || rotation == 3);
@@ -123,7 +123,7 @@ void MapHandler::drawRoad(QPainter & painter, int x, int y, int z)
 	
 	if(tinfo.roadType) //print road from this tile
 	{
-		auto roadName = tinfo.roadType->getJsonKey();
+		auto roadName = tinfo.getRoad()->getJsonKey();
 		QRect source(0, 0, tileSize, tileSize / 2);
 		ui8 rotation = (tinfo.extTileFlags >> 4) % 4;
 		bool hflip = (rotation == 1 || rotation == 3);
@@ -139,11 +139,11 @@ void MapHandler::drawRiver(QPainter & painter, int x, int y, int z)
 {
 	auto & tinfo = map->getTile(int3(x, y, z));
 
-	if(tinfo.riverType->getId() == River::NO_RIVER)
+	if(!tinfo.hasRiver())
 		return;
 	
 	//TODO: use ui8 instead of string key
-	auto riverName = tinfo.riverType->getJsonKey();
+	auto riverName = tinfo.getRiver()->getJsonKey();
 
 	if(riverImages.at(riverName).size() <= tinfo.riverDir)
 		return;
@@ -441,9 +441,9 @@ QRgb MapHandler::getTileColor(int x, int y, int z)
 	
 	auto & tile = map->getTile(int3(x, y, z));
 	
-	auto color = tile.terType->minimapUnblocked;
-	if (tile.blocked && (!tile.visitable))
-		color = tile.terType->minimapBlocked;
+	auto color = tile.getTerrain()->minimapUnblocked;
+	if (tile.blocked() && (!tile.visitable()))
+		color = tile.getTerrain()->minimapBlocked;
 	
 	return qRgb(color.r, color.g, color.b);
 }

+ 1 - 1
mapeditor/mapview.cpp

@@ -364,7 +364,7 @@ void MapView::mousePressEvent(QMouseEvent *event)
 						else if(controller->map()->getTile(tile).riverType
 						   && controller->map()->getTile(tile).riverType != controller->map()->getTile(tilen).riverType)
 							continue;
-						else if(controller->map()->getTile(tile).terType != controller->map()->getTile(tilen).terType)
+						else if(controller->map()->getTile(tile).terrainType != controller->map()->getTile(tilen).terrainType)
 							continue;
 					}
 					if(event->button() == Qt::LeftButton && sc->selectionTerrainView.selection().count(tilen))

+ 2 - 2
mapeditor/scenelayer.cpp

@@ -101,9 +101,9 @@ void PassabilityLayer::update()
 			for(int i = 0; i < map->width; ++i)
 			{
 				auto tl = map->getTile(int3(i, j, scene->level));
-				if(tl.blocked || tl.visitable)
+				if(tl.blocked() || tl.visitable())
 				{
-					painter.fillRect(i * 32, j * 32, 31, 31, tl.visitable ? QColor(200, 200, 0, 64) : QColor(255, 0, 0, 64));
+					painter.fillRect(i * 32, j * 32, 31, 31, tl.visitable() ? QColor(200, 200, 0, 64) : QColor(255, 0, 0, 64));
 				}
 			}
 		}

+ 8 - 9
server/CGameHandler.cpp

@@ -830,9 +830,8 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 
 	const bool embarking = !h->boat && objectToVisit && objectToVisit->ID == Obj::BOAT;
 	const bool disembarking = h->boat
-		&& t.terType->isLand()
-		&& (dst == h->pos
-			|| (h->boat->layer == EPathfindingLayer::SAIL && !t.blocked));
+		&& t.isLand()
+		&& (dst == h->pos || (h->boat->layer == EPathfindingLayer::SAIL && !t.blocked()));
 
 	//result structure for start - movement failed, no move points used
 	TryMoveHero tmh;
@@ -850,9 +849,9 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	const bool canWalkOnSea = pathfinderHelper->hasBonusOfType(BonusType::WATER_WALKING) || (h->boat && h->boat->layer == EPathfindingLayer::WATER);
 	const int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movementPointsRemaining());
 
-	const bool movingOntoObstacle = t.blocked && !t.visitable;
+	const bool movingOntoObstacle = t.blocked() && !t.visitable();
 	const bool objectCoastVisitable = objectToVisit && objectToVisit->isCoastVisitable();
-	const bool movingOntoWater = !h->boat && t.terType->isWater() && !objectCoastVisitable;
+	const bool movingOntoWater = !h->boat && t.isWater() && !objectCoastVisitable;
 
 	const auto complainRet = [&](const std::string & message)
 	{
@@ -876,14 +875,14 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 
 	//it's a rock or blocked and not visitable tile
 	//OR hero is on land and dest is water and (there is not present only one object - boat)
-	if (!t.terType->isPassable() || (movingOntoObstacle && !canFly))
+	if (!t.getTerrain()->isPassable() || (movingOntoObstacle && !canFly))
 		return complainRet("Cannot move hero, destination tile is blocked!");
 
 	//hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
 	if(movingOntoWater && !canFly && !canWalkOnSea)
 		return complainRet("Cannot move hero, destination tile is on water!");
 
-	if(h->boat && h->boat->layer == EPathfindingLayer::SAIL && t.terType->isLand() && t.blocked)
+	if(h->boat && h->boat->layer == EPathfindingLayer::SAIL && t.isLand() && t.blocked())
 		return complainRet("Cannot disembark hero, tile is blocked!");
 
 	if(distance(h->pos, dst) >= 1.5 && movementMode == EMovementMode::STANDARD)
@@ -895,7 +894,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	if(h->movementPointsRemaining() < cost && dst != h->pos && movementMode == EMovementMode::STANDARD)
 		return complainRet("Hero doesn't have any movement points left!");
 
-	if (transit && !canFly && !(canWalkOnSea && t.terType->isWater()) && !CGTeleport::isTeleport(objectToVisit))
+	if (transit && !canFly && !(canWalkOnSea && t.isWater()) && !CGTeleport::isTeleport(objectToVisit))
 		return complainRet("Hero cannot transit over this tile!");
 
 	//several generic blocks of code
@@ -1017,7 +1016,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 			if (CGTeleport::isTeleport(objectToVisit))
 				visitDest = DONT_VISIT_DEST;
 
-			if (canFly || (canWalkOnSea && t.terType->isWater()))
+			if (canFly || (canWalkOnSea && t.isWater()))
 			{
 				lookForGuards = IGNORE_GUARDS;
 				visitDest = DONT_VISIT_DEST;

+ 1 - 1
server/battles/BattleProcessor.cpp

@@ -157,7 +157,7 @@ void BattleProcessor::startBattle(const CArmedInstance *army1, const CArmedInsta
 BattleID BattleProcessor::setupBattle(int3 tile, BattleSideArray<const CArmedInstance *> armies, BattleSideArray<const CGHeroInstance *> heroes, const BattleLayout & layout, const CGTownInstance *town)
 {
 	const auto & t = *gameHandler->getTile(tile);
-	TerrainId terrain = t.terType->getId();
+	TerrainId terrain = t.getTerrainID();
 	if (town)
 		terrain = town->getNativeTerrain();
 	else if (gameHandler->gameState()->map->isCoastalTile(tile)) //coastal tile is always ground