diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index 5135e5a91..4cfd1a1b5 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/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 } diff --git a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp index ecba2746b..2a1bbf4c5 100644 --- a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp +++ b/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; diff --git a/AI/Nullkiller/Behaviors/StartupBehavior.cpp b/AI/Nullkiller/Behaviors/StartupBehavior.cpp index b9c994299..820beb75f 100644 --- a/AI/Nullkiller/Behaviors/StartupBehavior.cpp +++ b/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) { diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index ce83d3afc..dcff31bbf 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/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; diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp index 820828ea1..41b0d4e49 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp +++ b/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; diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 662446a26..c0d650464 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -888,7 +888,7 @@ void AINodeStorage::setHeroes(std::map 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(); diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index 1a0c708d3..3fd24a222 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/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 diff --git a/AI/VCAI/Goals/Explore.cpp b/AI/VCAI/Goals/Explore.cpp index ec5551a25..777b1a8ae 100644 --- a/AI/VCAI/Goals/Explore.cpp +++ b/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 }); } diff --git a/AI/VCAI/Pathfinding/AINodeStorage.cpp b/AI/VCAI/Pathfinding/AINodeStorage.cpp index a9b32dbb9..eee053ac9 100644 --- a/AI/VCAI/Pathfinding/AINodeStorage.cpp +++ b/AI/VCAI/Pathfinding/AINodeStorage.cpp @@ -113,7 +113,7 @@ std::vector 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; } diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 6f0b92269..97297887e 100644 --- a/AI/VCAI/VCAI.cpp +++ b/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 diff --git a/client/ClientCommandManager.cpp b/client/ClientCommandManager.cpp index 71383e432..3a3c06267 100644 --- a/client/ClientCommandManager.cpp +++ b/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) diff --git a/client/PlayerLocalState.cpp b/client/PlayerLocalState.cpp index 510dd0bb6..e731cff16 100644 --- a/client/PlayerLocalState.cpp +++ b/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) diff --git a/client/adventureMap/AdventureMapInterface.cpp b/client/adventureMap/AdventureMapInterface.cpp index 50ebb5931..55d171dfc 100644 --- a/client/adventureMap/AdventureMapInterface.cpp +++ b/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; diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index b617dc4d8..88414af95 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/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() diff --git a/client/adventureMap/CList.cpp b/client/adventureMap/CList.cpp index db810cac4..c7e169282 100644 --- a/client/adventureMap/CList.cpp +++ b/client/adventureMap/CList.cpp @@ -234,7 +234,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero) void CHeroList::CHeroItem::update() { - movement->setFrame(std::min(movement->size()-1, hero->movement / 100)); + movement->setFrame(std::min(movement->size()-1, hero->movementPointsRemaining() / 100)); mana->setFrame(std::min(mana->size()-1, hero->mana / 5)); redraw(); } diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 019beb076..d3477d247 100644 --- a/lib/NetPacksLib.cpp +++ b/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; } diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index ab8f64cb4..93ab001b7 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/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(movement) < maxMovePoints(true)) + if(static_cast(movement) < movementPointsLimit(true)) return EDiggingStatus::LACK_OF_MOVEMENT; if(!VLC->arth->objects[ArtifactID::GRAIL]->canBePutAt(this)) return EDiggingStatus::BACKPACK_IS_FULL; diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 5d39478b1..8f2bb56fb 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -49,6 +49,7 @@ class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, private: std::set 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 > 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 & 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; diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index 57100071a..681839da6 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/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()) diff --git a/lib/pathfinder/NodeStorage.cpp b/lib/pathfinder/NodeStorage.cpp index 9c4863032..38936dcf5 100644 --- a/lib/pathfinder/NodeStorage.cpp +++ b/lib/pathfinder/NodeStorage.cpp @@ -123,7 +123,7 @@ std::vector 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()) diff --git a/lib/pathfinder/TurnInfo.cpp b/lib/pathfinder/TurnInfo.cpp index fc9cdf2ed..6442a54f8 100644 --- a/lib/pathfinder/TurnInfo.cpp +++ b/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; } diff --git a/lib/rewardable/Interface.cpp b/lib/rewardable/Interface.cpp index b5debacf8..f34aa8055 100644 --- a/lib/rewardable/Interface.cpp +++ b/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(0, smp.val + info.reward.movePoints); cb->setMovePoints(&smp); diff --git a/lib/spells/AdventureSpellMechanics.cpp b/lib/spells/AdventureSpellMechanics.cpp index ccc69c79e..63126b36f 100644 --- a/lib/spells/AdventureSpellMechanics.cpp +++ b/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(parameters.caster->getHeroCaster()->movement)) - smp.val = parameters.caster->getHeroCaster()->movement - movementCost; + if(movementCost < static_cast(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(parameters.caster->getHeroCaster()->movement) < moveCost) + if(static_cast(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(parameters.caster->getHeroCaster()->movement) < moveCost) + if(static_cast(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(0, parameters.caster->getHeroCaster()->movement - moveCost); + smp.val = std::max(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(parameters.caster->getHeroCaster()->movement) < moveCost) + if(static_cast(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost) { InfoWindow iw; iw.player = parameters.caster->getCasterOwner(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index d29c338d2..06a2686dc 100644 --- a/server/CGameHandler.cpp +++ b/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(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(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;