1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-21 17:17:06 +02:00

TerrainTile now uses identifiers instead of pointers to VLC

This commit is contained in:
Ivan Savenko 2024-07-13 18:37:13 +00:00
parent a518b76c79
commit 08fbcd5239
44 changed files with 237 additions and 194 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;

View File

@ -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
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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

View File

@ -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(), ' ');
}

View File

@ -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);
}
}
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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())
{

View File

@ -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();
});

View File

@ -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';
}

View File

@ -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';
}

View File

@ -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);

View File

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

View File

@ -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())
{

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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))

View File

@ -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));
}
}
}

View File

@ -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;

View File

@ -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