Преглед изворни кода

Refactored access to hero paths in CPlayerInterface

Ivan Savenko пре 2 година
родитељ
комит
600054e001

+ 175 - 93
client/CPlayerInterface.cpp

@@ -120,7 +120,164 @@ struct HeroObjectRetriever : boost::static_visitor<const CGHeroInstance *>
 	}
 };
 
-CPlayerInterface::CPlayerInterface(PlayerColor Player)
+HeroPathStorage::HeroPathStorage(CPlayerInterface & owner):
+	owner(owner)
+{
+}
+
+void HeroPathStorage::setPath(const CGHeroInstance *h, const CGPath & path)
+{
+	paths[h] = path;
+}
+
+const CGPath & HeroPathStorage::getPath(const CGHeroInstance *h) const
+{
+	assert(hasPath(h));
+	return paths.at(h);
+}
+
+bool HeroPathStorage::hasPath(const CGHeroInstance *h) const
+{
+	return paths.count(h) > 0;
+}
+
+bool HeroPathStorage::setPath(const CGHeroInstance *h, const int3 & destination)
+{
+	CGPath path;
+	if (!owner.cb->getPathsInfo(h)->getPath(path, destination))
+		return false;
+
+	setPath(h, path);
+	return true;
+}
+
+void HeroPathStorage::removeLastNode(const CGHeroInstance *h)
+{
+	assert(hasPath(h));
+	if (!hasPath(h))
+		return;
+
+	auto & path = paths[h];
+	path.nodes.pop_back();
+	if (path.nodes.size() < 2)  //if it was the last one, remove entire path and path with only one tile is not a real path
+		erasePath(h);
+}
+
+void HeroPathStorage::erasePath(const CGHeroInstance *h)
+{
+	paths.erase(h);
+	adventureInt->updateMoveHero(h, false);
+
+}
+
+void HeroPathStorage::verifyPath(const CGHeroInstance *h)
+{
+	if (!hasPath(h))
+		return;
+	setPath(h, getPath(h).endPos());
+}
+
+//CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
+//{
+//	if (vstd::contains(paths,h)) //hero has assigned path
+//	{
+//		CGPath &path = paths[h];
+//		if (!path.nodes.size())
+//		{
+//			logGlobal->warn("Warning: empty path found...");
+//			paths.erasePath(h);
+//		}
+//		else
+//		{
+//			assert(h->visitablePos() == path.startPos());
+//			//update the hero path in case of something has changed on map
+//			if (LOCPLINT->cb->getPathsInfo(h)->getPath(path, path.endPos()))
+//				return &path;
+//
+//			paths.erase(h);
+//			return nullptr;
+//		}
+//	}
+//
+//	return nullptr;
+//}
+//
+//CGPath * CPlayerInterface::getPath(const CGHeroInstance * h)
+//{
+//	if (vstd::contains(paths,h)) //hero has assigned path
+//		return &paths[h];
+//
+//	return nullptr;
+//}
+
+//removeLastNode
+
+
+//void HeroPathStorage::setPath(const CGHeroInstance *h, const CGPath & path)
+//{
+//
+//}
+//
+//const CGPath & HeroPathStorage::getPath(const CGHeroInstance *h)
+//{
+//
+//}
+//
+//void HeroPathStorage::verifyPath(const CGHeroInstance *h)
+//{
+//
+//}
+
+//void CPlayerInterface::eraseCurrentPathOf(const CGHeroInstance * ho, bool checkForExistanceOfPath)
+//{
+//	if (checkForExistanceOfPath)
+//	{
+//		assert(vstd::contains(paths, ho));
+//	}
+//	else if (!vstd::contains(paths, ho))
+//	{
+//		return;
+//	}
+//	assert(ho == adventureInt->selection);
+//
+//	paths.erasePath(ho);
+//	adventureInt->updateMoveHero(ho, false);
+//}
+
+template<typename Handler>
+void HeroPathStorage::serialize(Handler & h, int version)
+{
+	std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
+	if (h.saving)
+	{
+		for (auto &p : paths)
+		{
+			if (p.second.nodes.size())
+				pathsMap[p.first] = p.second.endPos();
+			else
+				logGlobal->debug("%s has assigned an empty path! Ignoring it...", p.first->getNameTranslated());
+		}
+		h & pathsMap;
+	}
+	else
+	{
+		h & pathsMap;
+
+		if (owner.cb)
+		{
+			for (auto &p : pathsMap)
+			{
+				CGPath path;
+				owner.cb->getPathsInfo(p.first)->getPath(path, p.second);
+				paths[p.first] = path;
+				logGlobal->trace("Restored path for hero %s leading to %s with %d nodes", p.first->nodeName(), p.second.toString(), path.nodes.size());
+			}
+		}
+	}
+}
+
+CPlayerInterface::CPlayerInterface(PlayerColor Player):
+	paths(*this)
 {
 	logGlobal->trace("\tHuman player interface for player %s being constructed", Player.getStr());
 	destinationTeleport = ObjectInstanceID();
@@ -260,8 +417,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 
 	bool directlyAttackingCreature =
 		details.attackedFrom
-		&& adventureInt->terrain->currentPath					//in case if movement has been canceled in the meantime and path was already erased
-		&& adventureInt->terrain->currentPath->nodes.size() == 3;//FIXME should be 2 but works nevertheless...
+		&& paths.hasPath(hero) //in case if movement has been canceled in the meantime and path was already erased
+		&& paths.getPath(hero).nodes.size() == 3;//FIXME should be 2 but works nevertheless...
 
 	if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
 	{
@@ -271,21 +428,21 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 
 		if(details.result == TryMoveHero::TELEPORTATION)
 		{
-			if(adventureInt->terrain->currentPath)
+			if(paths.hasPath(hero))
 			{
-				assert(adventureInt->terrain->currentPath->nodes.size() >= 2);
-				std::vector<CGPathNode>::const_iterator nodesIt = adventureInt->terrain->currentPath->nodes.end() - 1;
+				assert(paths.getPath(hero).nodes.size() >= 2);
+				auto nodesIt = paths.getPath(hero).nodes.end() - 1;
 
 				if((nodesIt)->coord == hero->convertToVisitablePos(details.start)
 					&& (nodesIt - 1)->coord == hero->convertToVisitablePos(details.end))
 				{
 					//path was between entrance and exit of teleport -> OK, erase node as usual
-					removeLastNodeFromPath(hero);
+					paths.removeLastNode(hero);
 				}
 				else
 				{
 					//teleport was not along current path, it'll now be invalid (hero is somewhere else)
-					eraseCurrentPathOf(hero);
+					paths.erasePath(hero);
 
 				}
 			}
@@ -299,12 +456,12 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 		if(hero->pos != details.end //hero didn't change tile but visit succeeded
 			|| directlyAttackingCreature) // or creature was attacked from endangering tile.
 		{
-			eraseCurrentPathOf(hero, false);
+			paths.erasePath(hero);
 		}
-		else if(adventureInt->terrain->currentPath && hero->pos == details.end) //&& hero is moving
+		else if(paths.hasPath(hero) && hero->pos == details.end) //&& hero is moving
 		{
 			if(details.start != details.end) //so we don't touch path when revisiting with spacebar
-				removeLastNodeFromPath(hero);
+				paths.removeLastNode(hero);
 		}
 	}
 
@@ -444,8 +601,7 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
 	else if (adventureInt->selection == hero)
 		adventureInt->selection = nullptr;
 
-	if (vstd::contains(paths, hero))
-		paths.erase(hero);
+	paths.erasePath(hero);
 }
 
 void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start)
@@ -1247,7 +1403,7 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
 	if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain)
 	{
 		//recalculate paths because hero has lost bonus influencing pathfinding
-		eraseCurrentPathOf(hero, false);
+		paths.erasePath(hero);
 	}
 }
 
@@ -1256,33 +1412,7 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
 	h & wanderingHeroes;
 	h & towns;
 	h & sleepingHeroes;
-
-	std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
-	if (h.saving)
-	{
-		for (auto &p : paths)
-		{
-			if (p.second.nodes.size())
-				pathsMap[p.first] = p.second.endPos();
-			else
-				logGlobal->debug("%s has assigned an empty path! Ignoring it...", p.first->getNameTranslated());
-		}
-		h & pathsMap;
-	}
-	else
-	{
-		h & pathsMap;
-
-		if (cb)
-			for (auto &p : pathsMap)
-			{
-				CGPath path;
-				cb->getPathsInfo(p.first)->getPath(path, p.second);
-				paths[p.first] = path;
-				logGlobal->trace("Restored path for hero %s leading to %s with %d nodes", p.first->nodeName(), p.second.toString(), path.nodes.size());
-			}
-	}
-
+	h & paths;
 	h & spellbookSettings;
 }
 
@@ -1299,7 +1429,7 @@ void CPlayerInterface::loadGame( BinaryDeserializer & h, const int version )
 	firstCall = -1;
 }
 
-void CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
+void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path )
 {
 	LOG_TRACE(logGlobal);
 	if (!LOCPLINT->makingTurn)
@@ -1330,7 +1460,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto onEnd = [=](){ cb->selectionMade(0, queryID); };
 
-	if (stillMoveHero.get() == DURING_MOVE  && adventureInt->terrain->currentPath && adventureInt->terrain->currentPath->nodes.size() > 1) //to ignore calls on passing through garrisons
+	if (stillMoveHero.get() == DURING_MOVE  && paths.hasPath(down) && paths.getPath(down).nodes.size() > 1) //to ignore calls on passing through garrisons
 	{
 		onEnd();
 		return;
@@ -1641,7 +1771,7 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
 			bool heroVisibleHere = false;
 			auto & tile = subArr[tileX][tileY];
 
-			for ( auto const & obj : tile.objects)
+			for(const auto & obj : tile.objects)
 			{
 				if (obj.obj == ho)
 				{
@@ -1856,7 +1986,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
 		GH.popInts(1);
 
 	if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
-		eraseCurrentPathOf(caster, false);
+		paths.erasePath(caster);
 
 	const spells::Spell * spell = CGI->spells()->getByIndex(spellID);
 
@@ -1872,54 +2002,6 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
 		CCS->soundh->playSound(castSoundPath);
 }
 
-void CPlayerInterface::eraseCurrentPathOf(const CGHeroInstance * ho, bool checkForExistanceOfPath)
-{
-	if (checkForExistanceOfPath)
-	{
-		assert(vstd::contains(paths, ho));
-	}
-	else if (!vstd::contains(paths, ho))
-	{
-		return;
-	}
-	assert(ho == adventureInt->selection);
-
-	paths.erase(ho);
-	adventureInt->terrain->currentPath = nullptr;
-	adventureInt->updateMoveHero(ho, false);
-}
-
-void CPlayerInterface::removeLastNodeFromPath(const CGHeroInstance *ho)
-{
-	adventureInt->terrain->currentPath->nodes.erase(adventureInt->terrain->currentPath->nodes.end()-1);
-	if (adventureInt->terrain->currentPath->nodes.size() < 2)  //if it was the last one, remove entire path and path with only one tile is not a real path
-		eraseCurrentPathOf(ho);
-}
-
-CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
-{
-	if (vstd::contains(paths,h)) //hero has assigned path
-	{
-		CGPath &path = paths[h];
-		if (!path.nodes.size())
-		{
-			logGlobal->warn("Warning: empty path found...");
-			paths.erase(h);
-		}
-		else
-		{
-			assert(h->visitablePos() == path.startPos());
-			//update the hero path in case of something has changed on map
-			if (LOCPLINT->cb->getPathsInfo(h)->getPath(path, path.endPos()))
-				return &path;
-			else
-				paths.erase(h);
-		}
-	}
-
-	return nullptr;
-}
-
 void CPlayerInterface::acceptTurn()
 {
 	if (settings["session"]["autoSkip"].Bool())

+ 28 - 5
client/CPlayerInterface.h

@@ -64,12 +64,39 @@ namespace boost
 	class recursive_mutex;
 }
 
+class CPlayerInterface;
+
+class HeroPathStorage
+{
+	CPlayerInterface & owner;
+
+	std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
+
+public:
+	explicit HeroPathStorage(CPlayerInterface &owner);
+
+	void setPath(const CGHeroInstance *h, const CGPath & path);
+	bool setPath(const CGHeroInstance *h, const int3 & destination);
+
+	const CGPath & getPath(const CGHeroInstance *h) const;
+	bool hasPath(const CGHeroInstance *h) const;
+
+	void removeLastNode(const CGHeroInstance *h);
+	void erasePath(const CGHeroInstance *h);
+	void verifyPath(const CGHeroInstance *h);
+
+	template <typename Handler>
+	void serialize( Handler &h, int version );
+};
+
 /// Central class for managing user interface logic
 class CPlayerInterface : public CGameInterface, public IUpdateable
 {
 	const CArmedInstance * currentSelection;
 
 public:
+	HeroPathStorage paths;
+
 	std::shared_ptr<Environment> env;
 	ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
 	int3 destinationTeleportPos;
@@ -94,7 +121,6 @@ public:
 
 	std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
 	std::vector<const CGTownInstance *> towns; //our towns on the adventure map
-	std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
 	std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
 
 	//During battle is quick combat mode is used
@@ -229,14 +255,11 @@ public:
 	void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>());
 
 	void stopMovement();
-	void moveHero(const CGHeroInstance *h, CGPath path);
+	void moveHero(const CGHeroInstance *h, const CGPath& path);
 	void initMovement(const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp );//initializing objects and performing first step of move
 	void movementPxStep( const TryMoveHero &details, int i, const int3 &hp, const CGHeroInstance * ho );//performing step of movement
 	void finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho ); //finish movement
-	void eraseCurrentPathOf( const CGHeroInstance * ho, bool checkForExistanceOfPath = true );
 
-	void removeLastNodeFromPath(const CGHeroInstance *ho);
-	CGPath *getAndVerifyPath( const CGHeroInstance * h );
 	void acceptTurn(); //used during hot seat after your turn message is close
 	void tryDiggging(const CGHeroInstance *h);
 	void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard;

+ 25 - 29
client/adventureMap/CAdvMapInt.cpp

@@ -324,10 +324,10 @@ void CAdvMapInt::fsleepWake()
 void CAdvMapInt::fmoveHero()
 {
 	const CGHeroInstance *h = curHero();
-	if (!h || !terrain->currentPath || !CGI->mh->canStartHeroMovement())
+	if (!h || !LOCPLINT->paths.hasPath(h) || !CGI->mh->canStartHeroMovement())
 		return;
 
-	LOCPLINT->moveHero(h, *terrain->currentPath);
+	LOCPLINT->moveHero(h, LOCPLINT->paths.getPath(h));
 }
 
 void CAdvMapInt::fshowSpellbok()
@@ -373,10 +373,18 @@ void CAdvMapInt::fendTurn()
 				// Only show hero reminder if conditions met:
 				// - There still movement points
 				// - Hero don't have a path or there not points for first step on path
-				auto path = LOCPLINT->getAndVerifyPath(hero);
-				if(!path || path->nodes.size() < 2 || !path->nodes[path->nodes.size()-2].turns)
+				LOCPLINT->paths.verifyPath(hero);
+
+				if(!LOCPLINT->paths.hasPath(hero))
 				{
-					LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), nullptr);
+					LOCPLINT->showYesNoDialog( CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), nullptr );
+					return;
+				}
+
+				auto path = LOCPLINT->paths.getPath(hero);
+				if (path.nodes.size() < 2 || path.nodes[path.nodes.size() - 2].turns)
+				{
+					LOCPLINT->showYesNoDialog( CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), nullptr );
 					return;
 				}
 			}
@@ -405,7 +413,7 @@ void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath)
 	}
 	//default value is for everywhere but CPlayerInterface::moveHero, because paths are not updated from there immediately
 	if(boost::logic::indeterminate(hasPath))
-		hasPath = LOCPLINT->paths[h].nodes.size() ? true : false;
+		hasPath = LOCPLINT->paths.hasPath(h);
 
 	moveHero->block(!(bool)hasPath || (h->movement == 0));
 }
@@ -865,14 +873,15 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
 				return;
 			}
 
-			CGPath &path = LOCPLINT->paths[h];
-			terrain->currentPath = &path;
 			int3 dst = h->visitablePos() + int3(direction->x, direction->y, 0);
-			if(dst != verifyPos(dst) || !LOCPLINT->cb->getPathsInfo(h)->getPath(path, dst))
-			{
-				terrain->currentPath = nullptr;
+
+			if(dst != verifyPos(dst))
 				return;
-			}
+
+			if ( !LOCPLINT->paths.setPath(h, dst))
+				return;
+
+			const CGPath & path = LOCPLINT->paths.getPath(h);
 
 			if (path.nodes.size() > 2)
 				updateMoveHero(h);
@@ -938,7 +947,6 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
 	if(centerView)
 		centerOn(sel);
 
-	terrain->currentPath = nullptr;
 	if(sel->ID==Obj::TOWN)
 	{
 		auto town = dynamic_cast<const CGTownInstance*>(sel);
@@ -959,8 +967,6 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
 		heroList->select(hero);
 		townList->select(nullptr);
 
-		terrain->currentPath = LOCPLINT->getAndVerifyPath(hero);
-
 		updateSleepWake(hero);
 		updateMoveHero(hero);
 		updateSpellbook(hero);
@@ -1155,7 +1161,6 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
 	bool isHero = false;
 	if(selection->ID != Obj::HERO) //hero is not selected (presumably town)
 	{
-		assert(!terrain->currentPath); //path can be active only when hero is selected
 		if(selection == topBlocking) //selected town clicked
 			LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(topBlocking));
 		else if(canSelect)
@@ -1178,25 +1183,16 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
 		}
 		else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
 		{
-			if(terrain->currentPath && terrain->currentPath->endPos() == mapPos)//we'll be moving
+			if(LOCPLINT->paths.hasPath(currentHero) &&
+			   LOCPLINT->paths.getPath(currentHero).endPos() == mapPos)//we'll be moving
 			{
 				if(CGI->mh->canStartHeroMovement())
-					LOCPLINT->moveHero(currentHero, *terrain->currentPath);
+					LOCPLINT->moveHero(currentHero, LOCPLINT->paths.getPath(currentHero));
 				return;
 			}
 			else //remove old path and find a new one if we clicked on accessible tile
 			{
-				CGPath &path = LOCPLINT->paths[currentHero];
-				CGPath newpath;
-				bool gotPath = LOCPLINT->cb->getPathsInfo(currentHero)->getPath(newpath, mapPos); //try getting path, erase if failed
-				if(gotPath && newpath.nodes.size())
-					path = newpath;
-
-				if(path.nodes.size())
-					terrain->currentPath = &path;
-				else
-					LOCPLINT->eraseCurrentPathOf(currentHero);
-
+				LOCPLINT->paths.setPath(currentHero, mapPos);
 				updateMoveHero(currentHero);
 			}
 		}

+ 11 - 11
client/adventureMap/CTerrainRect.cpp

@@ -35,11 +35,11 @@
 #define ADVOPT (conf.go()->ac)
 
 CTerrainRect::CTerrainRect()
-	: fadeSurface(nullptr),
-	  lastRedrawStatus(EMapAnimRedrawStatus::OK),
-	  fadeAnim(std::make_shared<CFadeAnimation>()),
-	  curHoveredTile(-1,-1,-1),
-	  currentPath(nullptr)
+	: fadeSurface(nullptr)
+	, lastRedrawStatus(EMapAnimRedrawStatus::OK)
+	, fadeAnim(std::make_shared<CFadeAnimation>())
+	, curHoveredTile(-1, -1, -1)
+	, isSwiping(false)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
 
@@ -90,13 +90,12 @@ void CTerrainRect::clickLeft(tribool down, bool previousState)
 		}
 	}
 	else
-	{
 #endif
+	{
 		if(down == false)
 			return;
-#if defined(VCMI_MOBILE)
 	}
-#endif
+
 	int3 mp = whichTileIsIt();
 	if(mp.x < 0 || mp.y < 0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
 		return;
@@ -146,8 +145,8 @@ void CTerrainRect::handleSwipeMove(const Point & cursorPosition)
 	if(!isSwiping)
 	{
 		// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
-		if(abs(cursorPosition.x - swipeInitialRealPos.x) > SwipeTouchSlop ||
-		   abs(cursorPosition.y - swipeInitialRealPos.y) > SwipeTouchSlop)
+		if(std::abs(cursorPosition.x - swipeInitialRealPos.x) > SwipeTouchSlop ||
+		   std::abs(cursorPosition.y - swipeInitialRealPos.y) > SwipeTouchSlop)
 		{
 			isSwiping = true;
 		}
@@ -169,7 +168,8 @@ bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
 		swipeInitialViewPos = getViewCenter();
 		return true;
 	}
-	else if(isSwiping) // only accept this touch if it wasn't a swipe
+
+	if(isSwiping) // only accept this touch if it wasn't a swipe
 	{
 		isSwiping = false;
 		return true;

+ 1 - 1
client/adventureMap/CTerrainRect.h

@@ -51,7 +51,7 @@ class CTerrainRect : public CIntObject
 
 	bool needsAnimUpdate();
 public:
-	CGPath * currentPath;
+	//CGPath * currentPath;
 
 	CTerrainRect();
 	~CTerrainRect();

+ 0 - 1
client/adventureMap/mapHandler.h

@@ -365,7 +365,6 @@ private:
 	int offsetY;
 
 	//terrain graphics
-private:
 	//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
 	typedef std::map<std::string, std::array<std::shared_ptr<CAnimation>, 4>> TFlippedAnimations; //[type, rotation]
 	typedef std::map<std::string, std::vector<std::array<std::shared_ptr<IImage>, 4>>> TFlippedCache;//[type, view type, rotation]

+ 1 - 1
client/windows/CCastleInterface.cpp

@@ -1219,7 +1219,7 @@ void CCastleInterface::castleTeleport(int where)
 	const CGTownInstance * dest = LOCPLINT->cb->getTown(ObjectInstanceID(where));
 	adventureInt->select(town->visitingHero);//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
 	LOCPLINT->cb->teleportHero(town->visitingHero, dest);
-	LOCPLINT->eraseCurrentPathOf(town->visitingHero, false);
+	LOCPLINT->paths.erasePath(town->visitingHero);
 }
 
 void CCastleInterface::townChange()