diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index e6613bf4e..bef3f67e3 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -151,7 +151,7 @@ void NodeStorage::resetTile(const int3 & tile, const EPathfindingLayer & layer, std::vector NodeStorage::getInitialNodes() { - auto * initialNode = getNode(out.hpos, out.hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND); + auto * initialNode = getNode(out.hpos, out.hero->boat ? out.hero->boat->layer : EPathfindingLayer::LAND); initialNode->turns = 0; initialNode->moveRemains = out.hero->movement; @@ -1019,12 +1019,18 @@ bool TurnInfo::isLayerAvailable(const EPathfindingLayer & layer) const switch(layer) { case EPathfindingLayer::AIR: - if(!hasBonusOfType(Bonus::FLYING_MOVEMENT)) + if(hero && hero->boat && hero->boat->layer == EPathfindingLayer::AIR) + break; + + if(hasBonusOfType(Bonus::FLYING_MOVEMENT)) return false; break; case EPathfindingLayer::WATER: + if(hero && hero->boat && hero->boat->layer == EPathfindingLayer::WATER) + break; + if(!hasBonusOfType(Bonus::WATER_WALKING)) return false; @@ -1232,15 +1238,17 @@ int CPathfinderHelper::getMovementCost( bool isSailLayer; if(indeterminate(isDstSailLayer)) - isSailLayer = hero->boat != nullptr && dt->terType->isWater(); + isSailLayer = hero->boat && hero->boat->layer == EPathfindingLayer::SAIL && dt->terType->isWater(); else isSailLayer = static_cast(isDstSailLayer); bool isWaterLayer; if(indeterminate(isDstWaterLayer)) - isWaterLayer = dt->terType->isWater(); + isWaterLayer = ((hero->boat && hero->boat->layer == EPathfindingLayer::WATER) || ti->hasBonusOfType(Bonus::WATER_WALKING)) && dt->terType->isWater(); else isWaterLayer = static_cast(isDstWaterLayer); + + bool isAirLayer = (hero->boat && hero->boat->layer == EPathfindingLayer::AIR) || ti->hasBonusOfType(Bonus::FLYING_MOVEMENT); int ret = hero->getTileCost(*dt, *ct, ti); if(isSailLayer) @@ -1248,7 +1256,7 @@ int CPathfinderHelper::getMovementCost( if(ct->hasFavorableWinds()) ret = static_cast(ret * 2.0 / 3); } - else if(ti->hasBonusOfType(Bonus::FLYING_MOVEMENT)) + else if(isAirLayer) vstd::amin(ret, GameConstants::BASE_MOVEMENT_COST + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)); else if(isWaterLayer && ti->hasBonusOfType(Bonus::WATER_WALKING)) ret = static_cast(ret * (100.0 + ti->valOfBonuses(Bonus::WATER_WALKING)) / 100.0); diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 42e6c9f07..9300d9224 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1120,9 +1120,11 @@ int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool if(!ti->hasBonusOfType(Bonus::FREE_SHIP_BOARDING)) return 0; // take all MPs by default + + auto boatLayer = boat ? boat->layer : EPathfindingLayer::SAIL; - int mp1 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL); - int mp2 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND); + int mp1 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::LAND : boatLayer); + int mp2 = ti->getMaxMovePoints(disembark ? boatLayer : EPathfindingLayer::LAND); int ret = static_cast((MPsBefore - basicCost) * static_cast(mp1) / mp2); return ret; } diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index 0674ebfb3..c15c1f3e3 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -19,6 +19,7 @@ #include "../CPlayerState.h" #include "../spells/CSpellHandler.h" #include "../spells/ISpellMechanics.h" +#include "../mapObjects/MiscObjects.h" #include "CObjectClassesHandler.h" @@ -316,7 +317,7 @@ void CRewardableObject::grantRewardAfterLevelup(const CRewardVisitInfo & info, c smp.val = hero->movement; if (info.reward.movePercentage >= 0) // percent from max - smp.val = hero->maxMovePoints(hero->boat != nullptr) * info.reward.movePercentage / 100; + smp.val = hero->maxMovePoints(hero->boat && hero->boat->layer == EPathfindingLayer::SAIL) * info.reward.movePercentage / 100; smp.val = std::max(0, smp.val + info.reward.movePoints); cb->setMovePoints(&smp); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index a483e262f..1d699e2b6 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2264,7 +2264,9 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo const int3 guardPos = gs->guardingCreaturePosition(hmpos); const bool embarking = !h->boat && !t.visitableObjects.empty() && t.visitableObjects.back()->ID == Obj::TRANSPORT; - const bool disembarking = h->boat && t.terType->isLand() && !t.blocked; + const bool disembarking = h->boat + && (h->boat->layer == EPathfindingLayer::SAIL && t.terType->isLand()) + && !t.blocked; //result structure for start - movement failed, no move points used TryMoveHero tmh; @@ -2278,8 +2280,8 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo auto pathfinderHelper = std::make_unique(gs, h, PathfinderOptions()); auto ti = pathfinderHelper->getTurnInfo(); - const bool canFly = pathfinderHelper->hasBonusOfType(Bonus::FLYING_MOVEMENT); - const bool canWalkOnSea = pathfinderHelper->hasBonusOfType(Bonus::WATER_WALKING); + const bool canFly = pathfinderHelper->hasBonusOfType(Bonus::FLYING_MOVEMENT) || (h->boat && h->boat->layer == EPathfindingLayer::AIR); + const bool canWalkOnSea = pathfinderHelper->hasBonusOfType(Bonus::WATER_WALKING) || (h->boat && h->boat->layer == EPathfindingLayer::WATER); const int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movement); //it's a rock or blocked and not visitable tile