Browse Source

Added encapsulation for movement points access

Ivan Savenko 2 years ago
parent
commit
08cfbe79cf

+ 2 - 2
AI/Nullkiller/AIGateway.cpp

@@ -802,8 +802,8 @@ void AIGateway::makeTurn()
 		//for debug purpose
 		for (auto h : cb->getHeroesInfo())
 		{
-			if (h->movement)
-				logAi->warn("Hero %s has %d MP left", h->getNameTranslated(), h->movement);
+			if (h->movementPointsRemaining())
+				logAi->warn("Hero %s has %d MP left", h->getNameTranslated(), h->movementPointsRemaining());
 		}
 #if NKAI_TRACE_LEVEL == 0
 	}

+ 1 - 1
AI/Nullkiller/Behaviors/DefenceBehavior.cpp

@@ -187,7 +187,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
 							if(ai->nullkiller->isHeroLocked(existingHero)
 								|| existingHero->getArmyStrength() > hero->getArmyStrength()
 								|| ai->nullkiller->heroManager->getHeroRole(existingHero) == HeroRole::MAIN
-								|| existingHero->movement
+								|| existingHero->movementPointsRemaining()
 								|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
 								continue;
 

+ 1 - 1
AI/Nullkiller/Behaviors/StartupBehavior.cpp

@@ -206,7 +206,7 @@ Goals::TGoalVec StartupBehavior::decompose() const
 		for(const CGTownInstance * town : towns)
 		{
 			if(town->garrisonHero
-				&& town->garrisonHero->movement
+				&& town->garrisonHero->movementPointsRemaining()
 				&& !town->visitingHero
 				&& ai->nullkiller->getHeroLockedReason(town->garrisonHero) != HeroLockedReason::DEFENCE)
 			{

+ 1 - 1
AI/Nullkiller/Engine/PriorityEvaluator.cpp

@@ -790,7 +790,7 @@ public:
 		if(garrisonHero && swapCommand.getLockingReason() == HeroLockedReason::DEFENCE)
 		{
 			auto defenderRole = evaluationContext.evaluator.ai->heroManager->getHeroRole(garrisonHero);
-			auto mpLeft = garrisonHero->movement / (float)garrisonHero->maxMovePoints(true);
+			auto mpLeft = garrisonHero->movementPointsRemaining() / (float)garrisonHero->movementPointsLimit(true);
 
 			evaluationContext.movementCost += mpLeft;
 			evaluationContext.movementCostByRole[defenderRole] += mpLeft;

+ 4 - 4
AI/Nullkiller/Goals/ExecuteHeroChain.cpp

@@ -78,7 +78,7 @@ void ExecuteHeroChain::accept(AIGateway * ai)
 
 		try
 		{
-			if(hero->movement)
+			if(hero->movementPointsRemaining() > 0)
 			{
 				ai->nullkiller->setActive(hero, node.coord);
 
@@ -117,7 +117,7 @@ void ExecuteHeroChain::accept(AIGateway * ai)
 					}
 				}
 
-				if(hero->movement)
+				if(hero->movementPointsRemaining())
 				{
 					try
 					{
@@ -135,14 +135,14 @@ void ExecuteHeroChain::accept(AIGateway * ai)
 							return;
 						}
 
-						if(hero->movement > 0)
+						if(hero->movementPointsRemaining() > 0)
 						{
 							CGPath path;
 							bool isOk = cb->getPathsInfo(hero)->getPath(path, node.coord);
 
 							if(isOk && path.nodes.back().turns > 0)
 							{
-								logAi->warn("Hero %s has %d mp which is not enough to continue his way towards %s.", hero->getNameTranslated(), hero->movement, node.coord.toString());
+								logAi->warn("Hero %s has %d mp which is not enough to continue his way towards %s.", hero->getNameTranslated(), hero->movementPointsRemaining(), node.coord.toString());
 
 								ai->nullkiller->lockHero(hero, HeroLockedReason::HERO_CHAIN);
 								return;

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

@@ -888,7 +888,7 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
 		if(actor->hero->tempOwner != ai->playerID)
 		{
 			bool onLand = !actor->hero->boat || actor->hero->boat->layer != EPathfindingLayer::SAIL;
-			actor->initialMovement = actor->hero->maxMovePoints(onLand);
+			actor->initialMovement = actor->hero->movementPointsLimit(onLand);
 		}
 
 		playerID = actor->hero->tempOwner;
@@ -1053,7 +1053,7 @@ struct TowmPortalFinder
 			return std::nullopt;
 
 		AIPathNode * node = nodeOptional.value();
-		float movementCost = (float)movementNeeded / (float)hero->maxMovePoints(EPathfindingLayer::LAND);
+		float movementCost = (float)movementNeeded / (float)hero->movementPointsLimit(EPathfindingLayer::LAND);
 
 		movementCost += bestNode->getCost();
 

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

@@ -43,7 +43,7 @@ ChainActor::ChainActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t
 {
 	initialPosition = hero->visitablePos();
 	layer = hero->boat ? hero->boat->layer : EPathfindingLayer::LAND;
-	initialMovement = hero->movement;
+	initialMovement = hero->movementPointsRemaining();
 	initialTurn = 0;
 	armyValue = hero->getArmyStrength();
 	heroFightingStrength = hero->getFightingStrength();
@@ -75,7 +75,7 @@ int ChainActor::maxMovePoints(CGPathNode::ELayer layer)
 		throw std::logic_error("Asking movement points for static actor");
 #endif
 
-	return hero->maxMovePointsCached(layer, tiCache.get());
+	return hero->movementPointsLimitCached(layer, tiCache.get());
 }
 
 std::string ChainActor::toString() const

+ 1 - 1
AI/VCAI/Goals/Explore.cpp

@@ -267,7 +267,7 @@ TGoalVec Explore::getAllPossibleSubgoals()
 			if(!ai->isAbleToExplore(h))
 				return true;
 
-			return !h->movement; //saves time, immobile heroes are useless anyway
+			return !h->movementPointsRemaining(); //saves time, immobile heroes are useless anyway
 		});
 	}
 

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

@@ -113,7 +113,7 @@ std::vector<CGPathNode *> AINodeStorage::getInitialNodes()
 	auto initialNode = getOrCreateNode(hpos, hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND, NORMAL_CHAIN).value();
 
 	initialNode->turns = 0;
-	initialNode->moveRemains = hero->movement;
+	initialNode->moveRemains = hero->movementPointsRemaining();
 	initialNode->danger = 0;
 	initialNode->setCost(0.0);
 
@@ -245,7 +245,7 @@ void AINodeStorage::calculateTownPortalTeleportations(
 		auto skillLevel = hero->getSpellSchoolLevel(townPortal);
 		auto movementCost = GameConstants::BASE_MOVEMENT_COST * (skillLevel >= 3 ? 2 : 3);
 
-		if(hero->movement < movementCost)
+		if(hero->movementPointsRemaining() < movementCost)
 		{
 			return;
 		}

+ 9 - 9
AI/VCAI/VCAI.cpp

@@ -813,8 +813,8 @@ void VCAI::makeTurn()
 		//for debug purpose
 		for (auto h : cb->getHeroesInfo())
 		{
-			if (h->movement)
-				logAi->warn("Hero %s has %d MP left", h->getNameTranslated(), h->movement);
+			if (h->movementPointsRemaining())
+				logAi->warn("Hero %s has %d MP left", h->getNameTranslated(), h->movementPointsRemaining());
 		}
 	}
 	catch (boost::thread_interrupted & e)
@@ -949,7 +949,7 @@ void VCAI::mainLoop()
 			if (bestGoal->hero) //lock this hero to fulfill goal
 			{
 				setGoal(bestGoal->hero, bestGoal);
-				if (!bestGoal->hero->movement || vstd::contains(invalidPathHeroes, bestGoal->hero))
+				if (!bestGoal->hero->movementPointsRemaining() || vstd::contains(invalidPathHeroes, bestGoal->hero))
 				{
 					if (!vstd::erase_if_present(possibleGoals, bestGoal))
 					{
@@ -1354,7 +1354,7 @@ void VCAI::wander(HeroPtr h)
 
 	TimeCheck tc("looking for wander destination");
 
-	while(h->movement)
+	while(h->movementPointsRemaining())
 	{
 		validateVisitableObjs();
 		ah->updatePaths(getMyHeroes());
@@ -2031,7 +2031,7 @@ void VCAI::tryRealize(Goals::RecruitHero & g)
 
 void VCAI::tryRealize(Goals::VisitTile & g)
 {
-	if(!g.hero->movement)
+	if(!g.hero->movementPointsRemaining())
 		throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
 	if(g.tile == g.hero->visitablePos() && cb->getVisitableObjs(g.hero->visitablePos()).size() < 2)
 	{
@@ -2047,7 +2047,7 @@ void VCAI::tryRealize(Goals::VisitTile & g)
 void VCAI::tryRealize(Goals::VisitObj & g)
 {
 	auto position = g.tile;
-	if(!g.hero->movement)
+	if(!g.hero->movementPointsRemaining())
 		throw cannotFulfillGoalException("Cannot visit object: hero is out of MPs!");
 	if(position == g.hero->visitablePos() && cb->getVisitableObjs(g.hero->visitablePos()).size() < 2)
 	{
@@ -2062,7 +2062,7 @@ void VCAI::tryRealize(Goals::VisitObj & g)
 
 void VCAI::tryRealize(Goals::VisitHero & g)
 {
-	if(!g.hero->movement)
+	if(!g.hero->movementPointsRemaining())
 		throw cannotFulfillGoalException("Cannot visit target hero: hero is out of MPs!");
 
 	const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid));
@@ -2263,7 +2263,7 @@ bool VCAI::canAct(HeroPtr h) const
 			return false;
 	}
 
-	return h->movement;
+	return h->movementPointsRemaining();
 }
 
 HeroPtr VCAI::primaryHero() const
@@ -2412,7 +2412,7 @@ void VCAI::performTypicalActions()
 		if(!h) //hero might be lost. getUnblockedHeroes() called once on start of turn
 			continue;
 
-		logAi->debug("Hero %s started wandering, MP=%d", h->getNameTranslated(), h->movement);
+		logAi->debug("Hero %s started wandering, MP=%d", h->getNameTranslated(), h->movementPointsRemaining());
 		makePossibleUpgrades(*h);
 		pickBestArtifacts(*h);
 		try

+ 1 - 1
client/ClientCommandManager.cpp

@@ -388,7 +388,7 @@ void ClientCommandManager::handleTellCommand(std::istringstream& singleWordBuffe
 void ClientCommandManager::handleMpCommand()
 {
 	if(const CGHeroInstance* h = LOCPLINT->localState->getCurrentHero())
-		printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
+		printCommandMessage(std::to_string(h->movementPointsRemaining()) + "; max: " + std::to_string(h->movementPointsLimit(true)) + "/" + std::to_string(h->movementPointsLimit(false)) + "\n");
 }
 
 void ClientCommandManager::handleSetCommand(std::istringstream& singleWordBuffer)

+ 1 - 1
client/PlayerLocalState.cpp

@@ -124,7 +124,7 @@ const CGHeroInstance * PlayerLocalState::getNextWanderingHero(const CGHeroInstan
 		if (isHeroSleeping(hero))
 			continue;
 
-		if (hero->movement == 0)
+		if (hero->movementPointsRemaining() == 0)
 			continue;
 
 		if (!firstSuitable)

+ 1 - 1
client/adventureMap/AdventureMapInterface.cpp

@@ -676,7 +676,7 @@ void AdventureMapInterface::onTileHovered(const int3 &mapPos)
 
 void AdventureMapInterface::showMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode)
 {
-	const int maxMovementPointsAtStartOfLastTurn = pathNode.turns > 0 ? hero.maxMovePoints(pathNode.layer == EPathfindingLayer::LAND) : hero.movement;
+	const int maxMovementPointsAtStartOfLastTurn = pathNode.turns > 0 ? hero.movementPointsLimit(pathNode.layer == EPathfindingLayer::LAND) : hero.movementPointsRemaining();
 	const int movementPointsLastTurnCost = maxMovementPointsAtStartOfLastTurn - pathNode.moveRemains;
 	const int remainingPointsAfterMove = pathNode.turns == 0 ? pathNode.moveRemains : 0;
 

+ 2 - 2
client/adventureMap/AdventureMapShortcuts.cpp

@@ -224,7 +224,7 @@ void AdventureMapShortcuts::endTurn()
 	{
 		for(auto hero : LOCPLINT->localState->getWanderingHeroes())
 		{
-			if(!LOCPLINT->localState->isHeroSleeping(hero) && hero->movement > 0)
+			if(!LOCPLINT->localState->isHeroSleeping(hero) && hero->movementPointsRemaining() > 0)
 			{
 				// Only show hero reminder if conditions met:
 				// - There still movement points
@@ -418,7 +418,7 @@ bool AdventureMapShortcuts::optionHeroSelected()
 bool AdventureMapShortcuts::optionHeroCanMove()
 {
 	const auto * hero = LOCPLINT->localState->getCurrentHero();
-	return optionInMapView() && hero && hero->movement != 0 && LOCPLINT->localState->hasPath(hero);
+	return optionInMapView() && hero && hero->movementPointsRemaining() != 0 && LOCPLINT->localState->hasPath(hero);
 }
 
 bool AdventureMapShortcuts::optionHasNextHero()

+ 1 - 1
client/adventureMap/CList.cpp

@@ -234,7 +234,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
 
 void CHeroList::CHeroItem::update()
 {
-	movement->setFrame(std::min<size_t>(movement->size()-1, hero->movement / 100));
+	movement->setFrame(std::min<size_t>(movement->size()-1, hero->movementPointsRemaining() / 100));
 	mana->setFrame(std::min<size_t>(mana->size()-1, hero->mana / 5));
 	redraw();
 }

+ 7 - 9
lib/NetPacksLib.cpp

@@ -903,11 +903,9 @@ void SetMovePoints::applyGs(CGameState * gs) const
 	assert(hero);
 
 	if(absolute)
-		hero->movement = val;
+		hero->setMovementPoints(val);
 	else
-		hero->movement += val;
-
-	vstd::amax(hero->movement, 0); //not less than 0
+		hero->setMovementPoints(hero->movementPointsRemaining() + val);
 }
 
 void FoWChange::applyGs(CGameState *gs)
@@ -1276,7 +1274,7 @@ void TryMoveHero::applyGs(CGameState *gs)
 		return;
 	}
 
-	h->movement = movePoints;
+	h->setMovementPoints(movePoints);
 
 	if((result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK) && start != end)
 	{
@@ -1422,11 +1420,11 @@ void HeroRecruited::applyGs(CGameState * gs) const
 	{ // this is a fresh hero who hasn't appeared yet
 		if (boatId >= 0) //Hero spawns on water
 		{
-			h->movement = h->maxMovePoints(false);
+			h->setMovementPoints(h->movementPointsLimit(false));
 		}
 		else
 		{
-			h->movement = h->maxMovePoints(true);
+			h->setMovementPoints(h->movementPointsLimit(true));
 		}
 	}
 
@@ -1479,7 +1477,7 @@ void GiveHero::applyGs(CGameState * gs) const
 	h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->getIndex())->getTemplates().front();
 
 	h->setOwner(player);
-	h->movement =  h->maxMovePoints(true);
+	h->setMovementPoints(h->movementPointsLimit(true));
 	h->pos = h->convertFromVisitablePos(oldVisitablePos);
 	gs->map->heroesOnMap.emplace_back(h);
 	gs->getPlayerState(h->getOwner())->heroes.emplace_back(h);
@@ -2052,7 +2050,7 @@ void NewTurn::applyGs(CGameState *gs)
 			logGlobal->error("Hero %d not found in NewTurn::applyGs", h.id.getNum());
 			continue;
 		}
-		hero->movement = h.move;
+		hero->setMovementPoints(h.move);
 		hero->mana = h.mana;
 	}
 

+ 17 - 7
lib/mapObjects/CGHeroInstance.cpp

@@ -65,7 +65,7 @@ static int lowestSpeed(const CGHeroInstance * chi)
 	return ret;
 }
 
-ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const
+ui32 CGHeroInstance::getTileMovementCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const
 {
 	int64_t ret = GameConstants::BASE_MOVEMENT_COST;
 
@@ -201,10 +201,20 @@ bool CGHeroInstance::canLearnSkill(const SecondarySkill & which) const
 	return true;
 }
 
-int CGHeroInstance::maxMovePoints(bool onLand) const
+int CGHeroInstance::movementPointsRemaining() const
+{
+	return movement;
+}
+
+void CGHeroInstance::setMovementPoints(int points)
+{
+	movement = std::max(0, points);
+}
+
+int CGHeroInstance::movementPointsLimit(bool onLand) const
 {
 	TurnInfo ti(this);
-	return maxMovePointsCached(onLand, &ti);
+	return movementPointsLimitCached(onLand, &ti);
 }
 
 int CGHeroInstance::getLowestCreatureSpeed() const
@@ -224,7 +234,7 @@ void CGHeroInstance::updateArmyMovementBonus(bool onLand, const TurnInfo * ti) c
 	}
 }
 
-int CGHeroInstance::maxMovePointsCached(bool onLand, const TurnInfo * ti) const
+int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti) const
 {
 	updateArmyMovementBonus(onLand, ti);
 	return ti->valOfBonuses(BonusType::MOVEMENT, !!onLand);
@@ -454,14 +464,14 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 			const auto boatPos = visitablePos();
 			if (cb->gameState()->map->getTile(boatPos).isWater())
 			{
-				smp.val = maxMovePoints(false);
+				smp.val = movementPointsLimit(false);
 				//Create a new boat for hero
 				cb->createObject(boatPos, Obj::BOAT, getBoatType().getNum());
 				boatId = cb->getTopObj(boatPos)->id;
 			}
 			else
 			{
-				smp.val = maxMovePoints(true);
+				smp.val = movementPointsLimit(true);
 			}
 			cb->giveHero(id, h->tempOwner, boatId); //recreates def and adds hero to player
 			cb->setObjProperty(id, ObjProperty::ID, Obj::HERO); //set ID to 34 AFTER hero gets correct flag color
@@ -1170,7 +1180,7 @@ int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool
 
 EDiggingStatus CGHeroInstance::diggingStatus() const
 {
-	if(static_cast<int>(movement) < maxMovePoints(true))
+	if(static_cast<int>(movement) < movementPointsLimit(true))
 		return EDiggingStatus::LACK_OF_MOVEMENT;
 	if(!VLC->arth->objects[ArtifactID::GRAIL]->canBePutAt(this))
 		return EDiggingStatus::BACKPACK_IS_FULL;

+ 8 - 4
lib/mapObjects/CGHeroInstance.h

@@ -49,6 +49,7 @@ class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator,
 private:
 	std::set<SpellID> spells; //known spells (spell IDs)
 	mutable int lowestCreatureSpeed;
+	ui32 movement; //remaining movement points
 
 public:
 
@@ -67,7 +68,6 @@ public:
 	si32 portrait; //may be custom
 	si32 mana; // remaining spell points
 	std::vector<std::pair<SecondarySkill,ui8> > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities
-	ui32 movement; //remaining movement points
 	EHeroGender gender;
 
 	std::string nameCustom;
@@ -155,7 +155,6 @@ public:
 	EAlignment getAlignment() const;
 	bool needsLastStack()const override;
 
-	ui32 getTileCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
 	//INativeTerrainProvider
 	FactionID getFaction() const override;
 	TerrainId getNativeTerrain() const override;
@@ -196,9 +195,14 @@ public:
 	void setSecSkillLevel(const SecondarySkill & which, int val, bool abs); // abs == 0 - changes by value; 1 - sets to value
 	void levelUp(const std::vector<SecondarySkill> & skills);
 
-	int maxMovePoints(bool onLand) const;
+	/// returns base movement cost for movement between specific tiles. Does not accounts for diagonal movement or last tile exception
+	ui32 getTileMovementCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const;
+
+	void setMovementPoints(int points);
+	int movementPointsRemaining() const;
+	int movementPointsLimit(bool onLand) const;
 	//cached version is much faster, TurnInfo construction is costly
-	int maxMovePointsCached(bool onLand, const TurnInfo * ti) const;
+	int movementPointsLimitCached(bool onLand, const TurnInfo * ti) const;
 	//update army movement bonus
 	void updateArmyMovementBonus(bool onLand, const TurnInfo * ti) const;
 

+ 1 - 1
lib/pathfinder/CPathfinder.cpp

@@ -621,7 +621,7 @@ int CPathfinderHelper::getMovementCost(
 	
 	bool isAirLayer = (hero->boat && hero->boat->layer == EPathfindingLayer::AIR) || ti->hasBonusOfType(BonusType::FLYING_MOVEMENT);
 
-	int ret = hero->getTileCost(*dt, *ct, ti);
+	int ret = hero->getTileMovementCost(*dt, *ct, ti);
 	if(isSailLayer)
 	{
 		if(ct->hasFavorableWinds())

+ 1 - 1
lib/pathfinder/NodeStorage.cpp

@@ -123,7 +123,7 @@ std::vector<CGPathNode *> NodeStorage::getInitialNodes()
 	auto * initialNode = getNode(out.hpos, out.hero->boat ? out.hero->boat->layer : EPathfindingLayer::LAND);
 
 	initialNode->turns = 0;
-	initialNode->moveRemains = out.hero->movement;
+	initialNode->moveRemains = out.hero->movementPointsRemaining();
 	initialNode->setCost(0.0);
 
 	if(!initialNode->coord.valid())

+ 2 - 2
lib/pathfinder/TurnInfo.cpp

@@ -107,9 +107,9 @@ int TurnInfo::valOfBonuses(BonusType type, int subtype) const
 int TurnInfo::getMaxMovePoints(const EPathfindingLayer & layer) const
 {
 	if(maxMovePointsLand == -1)
-		maxMovePointsLand = hero->maxMovePointsCached(true, this);
+		maxMovePointsLand = hero->movementPointsLimitCached(true, this);
 	if(maxMovePointsWater == -1)
-		maxMovePointsWater = hero->maxMovePointsCached(false, this);
+		maxMovePointsWater = hero->movementPointsLimitCached(false, this);
 
 	return layer == EPathfindingLayer::SAIL ? maxMovePointsWater : maxMovePointsLand;
 }

+ 2 - 2
lib/rewardable/Interface.cpp

@@ -80,10 +80,10 @@ void Rewardable::Interface::grantRewardAfterLevelup(IGameCallback * cb, const Re
 	{
 		SetMovePoints smp;
 		smp.hid = hero->id;
-		smp.val = hero->movement;
+		smp.val = hero->movementPointsRemaining();
 
 		if (info.reward.movePercentage >= 0) // percent from max
-			smp.val = hero->maxMovePoints(hero->boat && hero->boat->layer == EPathfindingLayer::SAIL) * info.reward.movePercentage / 100;
+			smp.val = hero->movementPointsLimit(hero->boat && hero->boat->layer == EPathfindingLayer::SAIL) * info.reward.movePercentage / 100;
 		smp.val = std::max<si32>(0, smp.val + info.reward.movePoints);
 
 		cb->setMovePoints(&smp);

+ 7 - 7
lib/spells/AdventureSpellMechanics.cpp

@@ -297,7 +297,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
 		return ESpellCastResult::ERROR;
 	}
 
-	if(parameters.caster->getHeroCaster()->movement <= 0) //unlike town portal non-zero MP is enough
+	if(parameters.caster->getHeroCaster()->movementPointsRemaining() <= 0) //unlike town portal non-zero MP is enough
 	{
 		env->complain("Hero needs movement points to cast Dimension Door!");
 		return ESpellCastResult::ERROR;
@@ -335,8 +335,8 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
 	{
 		SetMovePoints smp;
 		smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
-		if(movementCost < static_cast<int>(parameters.caster->getHeroCaster()->movement))
-			smp.val = parameters.caster->getHeroCaster()->movement - movementCost;
+		if(movementCost < static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()))
+			smp.val = parameters.caster->getHeroCaster()->movementPointsRemaining() - movementCost;
 		else
 			smp.val = 0;
 		env->apply(&smp);
@@ -369,7 +369,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
 		if(nullptr == destination)
 			return ESpellCastResult::ERROR;
 
-		if(static_cast<int>(parameters.caster->getHeroCaster()->movement) < moveCost)
+		if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
 			return ESpellCastResult::ERROR;
 
 		if(destination->visitingHero)
@@ -419,7 +419,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
 			return ESpellCastResult::ERROR;
 		}
 
-		if(static_cast<int>(parameters.caster->getHeroCaster()->movement) < moveCost)
+		if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
 		{
 			env->complain("This hero has not enough movement points!");
 			return ESpellCastResult::ERROR;
@@ -441,7 +441,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
 	{
 		SetMovePoints smp;
 		smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
-		smp.val = std::max<ui32>(0, parameters.caster->getHeroCaster()->movement - moveCost);
+		smp.val = std::max<ui32>(0, parameters.caster->getHeroCaster()->movementPointsRemaining() - moveCost);
 		env->apply(&smp);
 	}
 	return ESpellCastResult::OK;
@@ -468,7 +468,7 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
 
 	const int moveCost = movementCost(parameters);
 
-	if(static_cast<int>(parameters.caster->getHeroCaster()->movement) < moveCost)
+	if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
 	{
 		InfoWindow iw;
 		iw.player = parameters.caster->getCasterOwner();

+ 10 - 10
server/CGameHandler.cpp

@@ -1773,9 +1773,9 @@ void CGameHandler::newTurn()
 		if (hero->isInitialized() && hero->stacks.size())
 		{
 			// reset retreated or surrendered heroes
-			auto maxmove = hero->maxMovePoints(true);
+			auto maxmove = hero->movementPointsLimit(true);
 			// if movement is greater than maxmove, we should decrease it
-			if (hero->movement != maxmove || hero->mana < hero->manaLimit())
+			if (hero->movementPointsRemaining() != maxmove || hero->mana < hero->manaLimit())
 			{
 				NewTurn::Hero hth;
 				hth.id = hero->id;
@@ -1864,7 +1864,7 @@ void CGameHandler::newTurn()
 			hth.id = h->id;
 			auto ti = std::make_unique<TurnInfo>(h, 1);
 			// TODO: this code executed when bonuses of previous day not yet updated (this happen in NewTurn::applyGs). See issue 2356
-			hth.move = h->maxMovePointsCached(gs->map->getTile(h->visitablePos()).terType->isLand(), ti.get());
+			hth.move = h->movementPointsLimitCached(gs->map->getTile(h->visitablePos()).terType->isLand(), ti.get());
 			hth.mana = h->getManaNewTurn();
 
 			n.heroes.insert(hth);
@@ -2280,7 +2280,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
 	tmh.start = h->pos;
 	tmh.end = dst;
 	tmh.result = TryMoveHero::FAILED;
-	tmh.movePoints = h->movement;
+	tmh.movePoints = h->movementPointsRemaining();
 
 	//check if destination tile is available
 	auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, h, PathfinderOptions());
@@ -2288,7 +2288,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
 
 	const bool canFly = pathfinderHelper->hasBonusOfType(BonusType::FLYING_MOVEMENT) || (h->boat && h->boat->layer == EPathfindingLayer::AIR);
 	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->movement);
+	const int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movementPointsRemaining());
 
 	//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)
@@ -2302,7 +2302,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
 			&& complain("Tiles are not neighboring!"))
 		|| ((h->inTownGarrison)
 			&& complain("Can not move garrisoned hero!"))
-		|| (((int)h->movement < cost  &&  dst != h->pos  &&  !teleporting)
+		|| (((int)h->movementPointsRemaining() < cost  &&  dst != h->pos  &&  !teleporting)
 			&& complain("Hero doesn't have any movement points left!"))
 		|| ((transit && !canFly && !CGTeleport::isTeleport(t.topVisitableObj()))
 			&& complain("Hero cannot transit over this tile!"))
@@ -2387,14 +2387,14 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
 
 	if (!transit && embarking)
 	{
-		tmh.movePoints = h->movementPointsAfterEmbark(h->movement, cost, false, ti);
+		tmh.movePoints = h->movementPointsAfterEmbark(h->movementPointsRemaining(), cost, false, ti);
 		return doMove(TryMoveHero::EMBARK, IGNORE_GUARDS, DONT_VISIT_DEST, LEAVING_TILE);
 		// In H3 embark ignore guards
 	}
 
 	if (disembarking)
 	{
-		tmh.movePoints = h->movementPointsAfterEmbark(h->movement, cost, true, ti);
+		tmh.movePoints = h->movementPointsAfterEmbark(h->movementPointsRemaining(), cost, true, ti);
 		return doMove(TryMoveHero::DISEMBARK, CHECK_FOR_GUARDS, VISIT_DEST, LEAVING_TILE);
 	}
 
@@ -2420,8 +2420,8 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
 
 	//still here? it is standard movement!
 	{
-		tmh.movePoints = (int)h->movement >= cost
-						? h->movement - cost
+		tmh.movePoints = (int)h->movementPointsRemaining() >= cost
+						? h->movementPointsRemaining() - cost
 						: 0;
 
 		EGuardLook lookForGuards = CHECK_FOR_GUARDS;