From 21463f1c0e1e5f06c6b47d45667cb72fc269f334 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Wed, 1 Feb 2023 10:51:41 +0300 Subject: [PATCH 01/12] fix movement cost with Fly --- lib/CPathfinder.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index a403b6d97..0e79d6a36 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1231,27 +1231,16 @@ int CPathfinderHelper::getMovementCost( dt = hero->cb->getTile(dst); } - /// TODO: by the original game rules hero shouldn't be affected by terrain penalty while flying. - /// Also flying movement only has penalty when player moving over blocked tiles. - /// So if you only have base flying with 40% penalty you can still ignore terrain penalty while having zero flying penalty. int ret = hero->getTileCost(*dt, *ct, ti); - /// Unfortunately this can't be implemented yet as server don't know when player flying and when he's not. - /// Difference in cost calculation on client and server is much worse than incorrect cost. - /// So this one is waiting till server going to use pathfinder rules for path validation. - - if(dt->blocked && ti->hasBonusOfType(Bonus::FLYING_MOVEMENT)) + if(hero->boat != nullptr && dt->terType->isWater()) { - ret = static_cast(ret * (100.0 + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)) / 100.0); - } - else if(dt->terType->isWater()) - { - if(hero->boat && ct->hasFavorableWinds() && dt->hasFavorableWinds()) + if(ct->hasFavorableWinds() && dt->hasFavorableWinds()) ret = static_cast(ret * 0.666); - else if(!hero->boat && ti->hasBonusOfType(Bonus::WATER_WALKING)) - { - ret = static_cast(ret * (100.0 + ti->valOfBonuses(Bonus::WATER_WALKING)) / 100.0); - } } + else if(ti->hasBonusOfType(Bonus::FLYING_MOVEMENT)) + vstd::amin(ret, GameConstants::BASE_MOVEMENT_COST + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)); + else if(hero->boat == nullptr && dt->terType->isWater() && ti->hasBonusOfType(Bonus::WATER_WALKING)) + ret = static_cast(ret * (100.0 + ti->valOfBonuses(Bonus::WATER_WALKING)) / 100.0); if(src.x != dst.x && src.y != dst.y) //it's diagonal move { From 3fbdc3b198ae8087324e341aa0c176f7597be62a Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Wed, 1 Feb 2023 10:53:25 +0300 Subject: [PATCH 02/12] improve code that checks last possible tile --- lib/CPathfinder.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 0e79d6a36..0b5bce4ea 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1247,16 +1247,16 @@ int CPathfinderHelper::getMovementCost( int old = ret; ret = static_cast(ret * M_SQRT2); //diagonal move costs too much but normal move is possible - allow diagonal move for remaining move points + // https://heroes.thelazy.net/index.php/Movement#Diagonal_move_exception if(ret > remainingMovePoints && remainingMovePoints >= old) { return remainingMovePoints; } } - /// TODO: This part need rework in order to work properly with flying and water walking - /// Currently it's only work properly for normal movement or sailing - int left = remainingMovePoints-ret; - if(checkLast && left > 0 && remainingMovePoints-ret < 250) //it might be the last tile - if no further move possible we take all move points + const int left = remainingMovePoints - ret; + constexpr auto maxCostOfOneStep = static_cast(175 * M_SQRT2); // diagonal move on Swamp - 247 MP + if(checkLast && left > 0 && left <= maxCostOfOneStep) //it might be the last tile - if no further move possible we take all move points { std::vector vec; vec.reserve(8); //optimization From 0c7b5ac7935274aba1965c5e31ba7af2a2200c8d Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Wed, 1 Feb 2023 10:53:05 +0300 Subject: [PATCH 03/12] fix movement cost on Favorable Winds --- lib/CPathfinder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 0b5bce4ea..0113bfd0f 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1234,8 +1234,8 @@ int CPathfinderHelper::getMovementCost( int ret = hero->getTileCost(*dt, *ct, ti); if(hero->boat != nullptr && dt->terType->isWater()) { - if(ct->hasFavorableWinds() && dt->hasFavorableWinds()) - ret = static_cast(ret * 0.666); + if(ct->hasFavorableWinds()) + ret = static_cast(ret * 2.0 / 3); } else if(ti->hasBonusOfType(Bonus::FLYING_MOVEMENT)) vstd::amin(ret, GameConstants::BASE_MOVEMENT_COST + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)); From bfb0dc26d573ffd63201e845defec747ade546e5 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 12 Mar 2023 19:01:54 +0300 Subject: [PATCH 04/12] fix movement cost on roads --- lib/mapObjects/CGHeroInstance.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 1b52c444a..d82457a64 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -66,10 +66,10 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f { int64_t ret = GameConstants::BASE_MOVEMENT_COST; - //if there is road both on dest and src tiles - use road movement cost + //if 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) { - ret = std::max(dest.roadType->movementCost, from.roadType->movementCost); + ret = from.roadType->movementCost; } else if(ti->nativeTerrain != from.terType->getId() &&//the terrain is not native ti->nativeTerrain != ETerrainId::ANY_TERRAIN && //no special creature bonus From 68f5c1de79f22407da4dda1ab493cef4b5f12453 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 12 Mar 2023 19:03:20 +0300 Subject: [PATCH 05/12] improve variable names in CPathfinderHelper::getNeighbours() --- lib/CPathfinder.cpp | 29 +++++++++++++---------------- lib/CPathfinder.h | 4 ++-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 0113bfd0f..c3604327a 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1163,8 +1163,8 @@ int CPathfinderHelper::getMaxMovePoints(const EPathfindingLayer & layer) const } void CPathfinderHelper::getNeighbours( - const TerrainTile & srct, - const int3 & tile, + const TerrainTile & srcTile, + const int3 & srcCoord, std::vector & vec, const boost::logic::tribool & onLand, const bool limitCoastSailing) const @@ -1179,35 +1179,32 @@ void CPathfinderHelper::getNeighbours( for(const auto & dir : dirs) { - const int3 hlp = tile + dir; - if(!map->isInTheMap(hlp)) + const int3 destCoord = srcCoord + dir; + if(!map->isInTheMap(destCoord)) continue; - const TerrainTile & hlpt = map->getTile(hlp); - if(!hlpt.terType->isPassable()) + const TerrainTile & destTile = map->getTile(destCoord); + if(!destTile.terType->isPassable()) continue; // //we cannot visit things from blocked tiles -// if(srct.blocked && !srct.visitable && hlpt.visitable && srct.blockingObjects.front()->ID != HEROI_TYPE) +// 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(srct.terType->isWater() && limitCoastSailing && hlpt.terType->isWater() && dir.x && dir.y) //diagonal move through water + if(srcTile.terType->isWater() && limitCoastSailing && destTile.terType->isWater() && dir.x && dir.y) //diagonal move through water { - int3 hlp1 = tile; - int3 hlp2 = tile; - hlp1.x += dir.x; - hlp2.y += dir.y; - - if(map->getTile(hlp1).terType->isLand() || map->getTile(hlp2).terType->isLand()) + 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()) continue; } - if(indeterminate(onLand) || onLand == hlpt.terType->isLand()) + if(indeterminate(onLand) || onLand == destTile.terType->isLand()) { - vec.push_back(hlp); + vec.push_back(destCoord); } } } diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 53b34c4f6..9d482b4cc 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -580,8 +580,8 @@ public: std::vector getTeleportExits(const PathNodeInfo & source) const; void getNeighbours( - const TerrainTile & srct, - const int3 & tile, + const TerrainTile & srcTile, + const int3 & srcCoord, std::vector & vec, const boost::logic::tribool & onLand, const bool limitCoastSailing) const; From 8f843d0bffa2b8324ec505f2c74b8b629948b999 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 12 Mar 2023 19:04:04 +0300 Subject: [PATCH 06/12] fix typos --- lib/CCreatureHandler.cpp | 2 +- lib/CPathfinder.cpp | 8 ++++---- lib/CPathfinder.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index d07d876bc..4d0df5fdd 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -331,7 +331,7 @@ TerrainId CCreature::getNativeTerrain() const static const auto selectorNoTerrainPenalty = Selector::type()(Bonus::NO_TERRAIN_PENALTY); //this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses - //and in the CGHeroInstance::getNativeTerrain() to setup mevement bonuses or/and penalties. + //and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties. return hasBonus(selectorNoTerrainPenalty, selectorNoTerrainPenalty) ? TerrainId(ETerrainId::ANY_TERRAIN) : (*VLC->townh)[faction]->nativeTerrain; diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index c3604327a..86b9833c8 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -117,7 +117,7 @@ std::vector NodeStorage::calculateTeleportations( std::vector CPathfinderHelper::getNeighbourTiles(const PathNodeInfo & source) const { std::vector neighbourTiles; - neighbourTiles.reserve(16); + neighbourTiles.reserve(8); getNeighbours( *source.tile, @@ -721,7 +721,7 @@ PathfinderBlockingRule::BlockingReason MovementAfterDestinationRule::getBlocking switch(destination.action) { /// TODO: Investigate what kind of limitation is possible to apply on movement from visitable tiles - /// Likely in many cases we don't need to add visitable tile to queue when hero don't fly + /// Likely in many cases we don't need to add visitable tile to queue when hero doesn't fly case CGPathNode::VISIT: { /// For now we only add visitable tile into queue when it's teleporter that allow transit @@ -730,7 +730,7 @@ PathfinderBlockingRule::BlockingReason MovementAfterDestinationRule::getBlocking if(pathfinderHelper->isAllowedTeleportEntrance(objTeleport)) { /// For now we'll always allow transit over teleporters - /// Transit over whirlpools only allowed when hero protected + /// Transit over whirlpools only allowed when hero is protected return BlockingReason::NONE; } else if(destination.nodeObject->ID == Obj::GARRISON @@ -1258,7 +1258,7 @@ int CPathfinderHelper::getMovementCost( std::vector vec; vec.reserve(8); //optimization getNeighbours(*dt, dst, vec, ct->terType->isLand(), true); - for(auto & elem : vec) + for(const auto & elem : vec) { int fcost = getMovementCost(dst, elem, nullptr, nullptr, left, false); if(fcost <= left) diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 9d482b4cc..59dc8c6e0 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -65,7 +65,7 @@ struct DLL_LINKAGE CGPathNode VISITABLE, //tile can be entered as the last tile in path BLOCKVIS, //visitable from neighboring tile but not passable FLYABLE, //can only be accessed in air layer - BLOCKED //tile can't be entered nor visited + BLOCKED //tile can be neither entered nor visited }; CGPathNode * theNodeBefore; From c0c19557af8333340a0a85159fbb23ac7209c2e7 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 12 Mar 2023 19:04:27 +0300 Subject: [PATCH 07/12] fix method documentation --- lib/CCreatureHandler.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 3e6175dab..923506609 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -161,9 +161,6 @@ public: bool isItNativeTerrain(TerrainId terrain) const; /** Returns creature native terrain considering some terrain bonuses. - @param considerBonus is used to avoid Dead Lock when this method is called inside getAllBonuses - considerBonus = true is called from Pathfinder and fills actual nativeTerrain considering bonus(es). - considerBonus = false is called on Battle init and returns already prepared nativeTerrain without Bonus system calling. */ TerrainId getNativeTerrain() const; int32_t getIndex() const override; From 3602645a30b6c26aaebb29831eff6ed6edcf63a4 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 12 Mar 2023 19:05:04 +0300 Subject: [PATCH 08/12] improve iterating over EPathfindingLayer --- AI/Nullkiller/Pathfinding/AINodeStorage.cpp | 2 +- AI/VCAI/Pathfinding/AINodeStorage.cpp | 2 +- lib/CPathfinder.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 1880df499..8fd97a975 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -285,7 +285,7 @@ std::vector AINodeStorage::calculateNeighbours( for(auto & neighbour : accessibleNeighbourTiles) { - for(EPathfindingLayer i = EPathfindingLayer::LAND; i <= EPathfindingLayer::AIR; i.advance(1)) + for(EPathfindingLayer i = EPathfindingLayer::LAND; i < EPathfindingLayer::NUM_LAYERS; i.advance(1)) { auto nextNode = getOrCreateNode(neighbour, i, srcNode->actor); diff --git a/AI/VCAI/Pathfinding/AINodeStorage.cpp b/AI/VCAI/Pathfinding/AINodeStorage.cpp index 77f516bf5..719e93903 100644 --- a/AI/VCAI/Pathfinding/AINodeStorage.cpp +++ b/AI/VCAI/Pathfinding/AINodeStorage.cpp @@ -167,7 +167,7 @@ std::vector AINodeStorage::calculateNeighbours( for(auto & neighbour : accessibleNeighbourTiles) { - for(EPathfindingLayer i = EPathfindingLayer::LAND; i <= EPathfindingLayer::AIR; i.advance(1)) + for(EPathfindingLayer i = EPathfindingLayer::LAND; i < EPathfindingLayer::NUM_LAYERS; i.advance(1)) { auto nextNode = getOrCreateNode(neighbour, i, srcNode->chainMask); diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 86b9833c8..c92d98943 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -78,7 +78,7 @@ std::vector NodeStorage::calculateNeighbours( for(auto & neighbour : accessibleNeighbourTiles) { - for(EPathfindingLayer i = EPathfindingLayer::LAND; i <= EPathfindingLayer::AIR; i.advance(1)) + for(EPathfindingLayer i = EPathfindingLayer::LAND; i < EPathfindingLayer::NUM_LAYERS; i.advance(1)) { auto * node = getNode(neighbour, i); From 8f638e7ca6c452b509803a8a09b45973e7e74b45 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 18 Mar 2023 12:08:44 +0300 Subject: [PATCH 09/12] [editor] fix Player Settings crash when random town is added to a map fixes #1714 --- mapeditor/playerparams.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mapeditor/playerparams.cpp b/mapeditor/playerparams.cpp index 573764122..d5b3970a6 100644 --- a/mapeditor/playerparams.cpp +++ b/mapeditor/playerparams.cpp @@ -59,7 +59,10 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent) { auto * ctown = town->town; if(!ctown) + { ctown = VLC->townh->randomTown; + town->town = ctown; + } if(ctown && town->getOwner().getNum() == playerColor) { if(playerInfo.hasMainTown && playerInfo.posOfMainTown == town->pos) From aae9e707718432f32236f67c48c351eb3a4ea8b7 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 19 Mar 2023 12:44:14 +0300 Subject: [PATCH 10/12] remove duplicate call already performed in CPathfinderHelper constructor --- server/CGameHandler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ef583d948..9557e7939 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2342,8 +2342,6 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo //check if destination tile is available auto pathfinderHelper = std::make_unique(gs, h, PathfinderOptions()); - - pathfinderHelper->updateTurnInfo(0); auto ti = pathfinderHelper->getTurnInfo(); const bool canFly = pathfinderHelper->hasBonusOfType(Bonus::FLYING_MOVEMENT); From a0cd69e944903599e3fd1f127e1bb3340f38096a Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 19 Mar 2023 12:45:49 +0300 Subject: [PATCH 11/12] Slight refactoring of CGHeroInstance::movementPointsAfterEmbark() --- lib/mapObjects/CGHeroInstance.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index d82457a64..1726794b6 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1106,22 +1106,19 @@ CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs) int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark, const TurnInfo * ti) const { - int ret = 0; //take all MPs by default - bool localTi = false; + std::unique_ptr turnInfoLocal; if(!ti) { - localTi = true; - ti = new TurnInfo(this); + turnInfoLocal = std::make_unique(this); + ti = turnInfoLocal.get(); } + if(!ti->hasBonusOfType(Bonus::FREE_SHIP_BOARDING)) + return 0; // take all MPs by default + int mp1 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL); int mp2 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND); - if(ti->hasBonusOfType(Bonus::FREE_SHIP_BOARDING)) - ret = static_cast((MPsBefore - basicCost) * static_cast(mp1) / mp2); - - if(localTi) - delete ti; - + int ret = static_cast((MPsBefore - basicCost) * static_cast(mp1) / mp2); return ret; } From 147633bd9d9ea9de21e8ed756e5d9eec3e396ab3 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sun, 19 Mar 2023 17:05:38 +0300 Subject: [PATCH 12/12] compute movement cost using PathNodeInfo layer info when possible --- lib/CPathfinder.cpp | 20 +++++++++++++++++--- lib/CPathfinder.h | 10 +++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index c92d98943..07eec46c9 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1215,7 +1215,9 @@ int CPathfinderHelper::getMovementCost( const TerrainTile * ct, const TerrainTile * dt, const int remainingMovePoints, - const bool checkLast) const + const bool checkLast, + boost::logic::tribool isDstSailLayer, + boost::logic::tribool isDstWaterLayer) const { if(src == dst) //same tile return 0; @@ -1228,15 +1230,27 @@ int CPathfinderHelper::getMovementCost( dt = hero->cb->getTile(dst); } + bool isSailLayer; + if(indeterminate(isDstSailLayer)) + isSailLayer = hero->boat != nullptr && dt->terType->isWater(); + else + isSailLayer = static_cast(isDstSailLayer); + + bool isWaterLayer; + if(indeterminate(isDstWaterLayer)) + isWaterLayer = dt->terType->isWater(); + else + isWaterLayer = static_cast(isDstWaterLayer); + int ret = hero->getTileCost(*dt, *ct, ti); - if(hero->boat != nullptr && dt->terType->isWater()) + if(isSailLayer) { if(ct->hasFavorableWinds()) ret = static_cast(ret * 2.0 / 3); } else if(ti->hasBonusOfType(Bonus::FLYING_MOVEMENT)) vstd::amin(ret, GameConstants::BASE_MOVEMENT_COST + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)); - else if(hero->boat == nullptr && dt->terType->isWater() && ti->hasBonusOfType(Bonus::WATER_WALKING)) + else if(isWaterLayer && ti->hasBonusOfType(Bonus::WATER_WALKING)) ret = static_cast(ret * (100.0 + ti->valOfBonuses(Bonus::WATER_WALKING)) / 100.0); if(src.x != dst.x && src.y != dst.y) //it's diagonal move diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 59dc8c6e0..a34d01032 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -591,8 +591,10 @@ public: const int3 & dst, const TerrainTile * ct, const TerrainTile * dt, - const int remainingMovePoints =- 1, - const bool checkLast = true) const; + const int remainingMovePoints = -1, + const bool checkLast = true, + boost::logic::tribool isDstSailLayer = boost::logic::indeterminate, + boost::logic::tribool isDstWaterLayer = boost::logic::indeterminate) const; int getMovementCost( const PathNodeInfo & src, @@ -606,7 +608,9 @@ public: src.tile, dst.tile, remainingMovePoints, - checkLast + checkLast, + dst.node->layer == EPathfindingLayer::SAIL, + dst.node->layer == EPathfindingLayer::WATER ); }