Browse Source

Initial refactoring to encapsulate adventure map

Ivan Savenko 2 years ago
parent
commit
f1902ab247

+ 50 - 117
client/CPlayerInterface.cpp

@@ -15,7 +15,6 @@
 #include "mapView/mapHandler.h"
 #include "adventureMap/CList.h"
 #include "adventureMap/CInfoBar.h"
-#include "adventureMap/CMinimap.h"
 #include "battle/BattleInterface.h"
 #include "battle/BattleEffectsController.h"
 #include "battle/BattleFieldController.h"
@@ -161,8 +160,7 @@ void HeroPathStorage::removeLastNode(const CGHeroInstance *h)
 void HeroPathStorage::erasePath(const CGHeroInstance *h)
 {
 	paths.erase(h);
-	adventureInt->updateMoveHero(h, false);
-
+	adventureInt->onHeroChanged(h);
 }
 
 void HeroPathStorage::verifyPath(const CGHeroInstance *h)
@@ -258,7 +256,6 @@ void CPlayerInterface::yourTurn()
 
 		LOCPLINT = this;
 		GH.curInt = this;
-		adventureInt->selection = nullptr;
 
 		NotificationHandler::notify("Your turn");
 
@@ -267,7 +264,7 @@ void CPlayerInterface::yourTurn()
 		if (firstCall)
 		{
 			if(CSH->howManyPlayerInterfaces() == 1)
-				adventureInt->setPlayer(playerID);
+				adventureInt->onCurrentPlayerChanged(playerID);
 
 			autosaveCount = getLastIndex(prefix + "Autosave_");
 
@@ -285,7 +282,7 @@ void CPlayerInterface::yourTurn()
 			autosaveCount %= 5;
 		}
 
-		adventureInt->setPlayer(playerID);
+		adventureInt->onCurrentPlayerChanged(playerID);
 
 		if (CSH->howManyPlayerInterfaces() > 1) //hot seat message
 		{
@@ -324,15 +321,15 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 	if (!hero)
 		return;
 
-	adventureInt->infoBar->requestPopAll();
 	if (details.result == TryMoveHero::EMBARK || details.result == TryMoveHero::DISEMBARK)
 	{
 		if(hero->getRemovalSound() && hero->tempOwner == playerID)
 			CCS->soundh->playSound(hero->getRemovalSound().value());
 	}
 
-	adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.start));
-	adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.end));
+
+	adventureInt->onMapTileChanged(hero->convertToVisitablePos(details.start));
+	adventureInt->onMapTileChanged(hero->convertToVisitablePos(details.end));
 
 	bool directlyAttackingCreature = details.attackedFrom && paths.hasPath(hero) && paths.getPath(hero).endPos() == *details.attackedFrom;
 
@@ -375,16 +372,14 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 	if(details.stopMovement()) //hero failed to move
 	{
 		stillMoveHero.setn(STOP_MOVE);
-		adventureInt->heroList->update(hero);
+		adventureInt->onHeroChanged(hero);
 		return;
 	}
 
-	adventureInt->heroList->redraw();
-
 	CGI->mh->waitForOngoingAnimations();
 
 	//move finished
-	adventureInt->heroList->update(hero);
+	adventureInt->onHeroChanged(hero);
 
 	//check if user cancelled movement
 	{
@@ -427,33 +422,8 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	LOG_TRACE_PARAMS(logGlobal, "Hero %s killed handler for player %s", hero->getNameTranslated() % playerID);
-
-	const CArmedInstance *newSelection = nullptr;
-	if (makingTurn)
-	{
-		//find new object for selection: either hero
-		int next = adventureInt->getNextHeroIndex(vstd::find_pos(wanderingHeroes, hero));
-		if (next >= 0)
-			newSelection = wanderingHeroes[next];
-
-		//or town
-		if (!newSelection || newSelection == hero)
-		{
-			if (towns.empty())
-				newSelection = nullptr;
-			else
-				newSelection = towns.front();
-		}
-	}
-
 	wanderingHeroes -= hero;
-
-	adventureInt->heroList->update(hero);
-	if (makingTurn && newSelection)
-		adventureInt->select(newSelection, true);
-	else if (adventureInt->selection == hero)
-		adventureInt->selection = nullptr;
-
+	adventureInt->onHeroChanged(hero);
 	paths.erasePath(hero);
 }
 
@@ -471,7 +441,7 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	wanderingHeroes.push_back(hero);
-	adventureInt->heroList->update(hero);
+	adventureInt->onHeroChanged(hero);
 }
 void CPlayerInterface::openTownWindow(const CGTownInstance * town)
 {
@@ -486,9 +456,7 @@ void CPlayerInterface::openTownWindow(const CGTownInstance * town)
 
 void CPlayerInterface::activateForSpectator()
 {
-	adventureInt->state = CAdvMapInt::INGAME;
 	adventureInt->activate();
-	adventureInt->minimap->activate();
 }
 
 void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val)
@@ -499,8 +467,8 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
 		if (CAltarWindow *ctw = dynamic_cast<CAltarWindow *>(GH.topInt().get()))
 			ctw->setExpToLevel();
 	}
-	else if (which < GameConstants::PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4)
-		updateInfo(hero);
+	else
+		adventureInt->onHeroChanged(hero);
 }
 
 void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val)
@@ -516,15 +484,15 @@ void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, in
 void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 	if (makingTurn && hero->tempOwner == playerID)
-		adventureInt->heroList->update(hero);
+		adventureInt->onHeroChanged(hero);
 }
 void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	if (makingTurn && hero->tempOwner == playerID)
-		adventureInt->heroList->update(hero);
+		adventureInt->onHeroChanged(hero);
 }
 void CPlayerInterface::receivedResource()
 {
@@ -560,7 +528,6 @@ void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander,
 void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	updateInfo(town);
 
 	if (town->garrisonHero) //wandering hero moved to the garrison
 	{
@@ -573,8 +540,8 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
 		if (town->visitingHero->tempOwner == playerID && !vstd::contains(wanderingHeroes,town->visitingHero)) // our hero
 			wanderingHeroes.push_back(town->visitingHero);
 	}
-	adventureInt->heroList->update();
-	adventureInt->updateNextHero(nullptr);
+	adventureInt->onHeroChanged(nullptr);
+	adventureInt->onTownChanged(town);
 
 	if(castleInt)
 	{
@@ -627,7 +594,15 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	for (auto object : objs)
-		updateInfo(object);
+	{
+		auto * hero = dynamic_cast<const CGHeroInstance*>(object);
+		auto * town = dynamic_cast<const CGTownInstance*>(object);
+
+		if (hero)
+			adventureInt->onHeroChanged(hero);
+		if (town)
+			adventureInt->onTownChanged(town);
+	}
 
 	for (auto & elem : GH.listInt)
 	{
@@ -653,15 +628,6 @@ void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj)
 void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) //what: 1 - built, 2 - demolished
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	switch (buildingID)
-	{
-	case BuildingID::FORT: case BuildingID::CITADEL: case BuildingID::CASTLE:
-	case BuildingID::VILLAGE_HALL: case BuildingID::TOWN_HALL: case BuildingID::CITY_HALL: case BuildingID::CAPITOL:
-	case BuildingID::RESOURCE_SILO:
-		updateInfo(town);
-		break;
-	}
-
 	if (castleInt)
 	{
 		castleInt->townlist->update(town);
@@ -680,7 +646,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
 			}
 		}
 	}
-	adventureInt->townList->update(town);
+	adventureInt->onTownChanged(town);
 }
 
 void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
@@ -709,7 +675,6 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
 		isAutoFightOn = true;
 		cb->registerBattleInterface(autofightingAI);
 		// Player shouldn't be able to move on adventure map if quick combat is going
-		adventureInt->quickCombatLock();
 		allowBattleReplay = true;
 	}
 
@@ -920,7 +885,6 @@ void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
 			// #1490 - during AI turn when quick combat is on, we need to display the message and wait for user to close it.
 			// Otherwise NewTurn causes freeze.
 			waitWhileDialog();
-			adventureInt->quickCombatUnlock();
 			return;
 		}
 	}
@@ -928,7 +892,6 @@ void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
 	BATTLE_EVENT_POSSIBLE_RETURN;
 
 	battleInt->battleFinished(*br, queryID);
-	adventureInt->quickCombatUnlock();
 }
 
 void CPlayerInterface::battleLogMessage(const std::vector<MetaString> & lines)
@@ -1070,7 +1033,7 @@ void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &t
 	if(autoTryHover || type == EInfoWindowMode::INFO)
 	{
 		waitWhileDialog(); //Fix for mantis #98
-		adventureInt->infoBar->pushComponents(components, text, timer);
+		adventureInt->showInfoBoxMessage(components, text, timer);
 
 		if (makingTurn && GH.listInt.size() && LOCPLINT == this)
 			CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
@@ -1235,14 +1198,14 @@ void CPlayerInterface::tileRevealed(const std::unordered_set<int3, ShashInt3> &p
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	//FIXME: wait for dialog? Magi hut/eye would benefit from this but may break other areas
 	for (auto & po : pos)
-		adventureInt->minimap->updateTile(po);
+		adventureInt->onMapTileChanged(po);
 }
 
 void CPlayerInterface::tileHidden(const std::unordered_set<int3, ShashInt3> &pos)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	for (auto & po : pos)
-		adventureInt->minimap->updateTile(po);
+		adventureInt->onMapTileChanged(po);
 }
 
 void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
@@ -1286,7 +1249,7 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
 	if (bonus.type == Bonus::NONE)
 		return;
 
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 	if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain)
 	{
 		//recalculate paths because hero has lost bonus influencing pathfinding
@@ -1330,14 +1293,8 @@ void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path )
 
 	setMovementStatus(true);
 
-	if (adventureInt && adventureInt->isHeroSleeping(h))
-	{
-		adventureInt->sleepWake->clickLeft(true, false);
-		adventureInt->sleepWake->clickLeft(false, true);
-		//could've just called
-		//adventureInt->fsleepWake();
-		//but no authentic button click/sound ;-)
-	}
+	if (adventureInt)
+		adventureInt->onHeroWokeUp(h);
 
 	boost::thread moveHeroTask(std::bind(&CPlayerInterface::doMoveHero,this,h,path));
 }
@@ -1415,6 +1372,7 @@ void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanc
 void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
+
 	//redraw minimap if owner changed
 	if (sop->what == ObjProperty::OWNER)
 	{
@@ -1424,17 +1382,19 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
 		for(auto & po : pos)
 		{
 			if(cb->isVisible(po))
-				adventureInt->minimap->updateTile(po);
+				adventureInt->onMapTileChanged(po);
 		}
 		if(obj->ID == Obj::TOWN)
 		{
+			auto town = static_cast<const CGTownInstance *>(obj);
+
 			if(obj->tempOwner == playerID)
-				towns.push_back(static_cast<const CGTownInstance *>(obj));
+				towns.push_back(town);
 			else
 				towns -= obj;
 
-			adventureInt->townList->update();
-			adventureInt->minimap->update();
+			adventureInt->onTownChanged(town);
+			adventureInt->onMapTilesChanged();
 		}
 		assert(cb->getTownsInfo().size() == towns.size());
 	}
@@ -1456,7 +1416,7 @@ void CPlayerInterface::initializeHeroTownList()
 		towns = cb->getTownsInfo();
 
 	if(adventureInt)
-		adventureInt->updateNextHero(nullptr);
+		adventureInt->onHeroChanged(nullptr);
 }
 
 void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level)
@@ -1545,7 +1505,7 @@ void CPlayerInterface::objectRemoved(const CGObjectInstance * obj)
 void CPlayerInterface::objectRemovedAfter()
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	adventureInt->minimap->update();
+	adventureInt->onMapTilesChanged();
 }
 
 void CPlayerInterface::playerBlocked(int reason, bool start)
@@ -1558,8 +1518,7 @@ void CPlayerInterface::playerBlocked(int reason, bool start)
 			boost::unique_lock<boost::mutex> lock(eventsM); //TODO: copied from yourTurn, no idea if it's needed
 			LOCPLINT = this;
 			GH.curInt = this;
-			adventureInt->selection = nullptr;
-			adventureInt->setPlayer(playerID);
+			adventureInt->onCurrentPlayerChanged(playerID);
 			std::string msg = CGI->generaltexth->translate("vcmi.adventureMap.playerAttacked");
 			boost::replace_first(msg, "%s", cb->getStartInfo()->playerInfos.find(playerID)->second.name);
 			std::vector<std::shared_ptr<CComponent>> cmp;
@@ -1810,21 +1769,6 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance * h)
 		showInfoDialog(CGI->generaltexth->allTexts[msgToShow]);
 }
 
-void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
-{
-	bool isHero = dynamic_cast<const CGHeroInstance *>(specific) != nullptr;
-	bool changedHero = dynamic_cast<const CGHeroInstance *>(specific) != adventureInt->curHero();
-	bool isTown = dynamic_cast<const CGTownInstance *>(specific) != nullptr;
-
-	bool update = (isHero && changedHero) || (isTown);
-	// If infobar is showing components and we request an update to hero
-	// do not force infobar tick here, it will prevents us to show components just picked up
-	if(adventureInt->infoBar->showingComponents() && !update)
-		return;
-
-	adventureInt->infoBar->showSelection();
-}
-
 void CPlayerInterface::battleNewRoundFirst( int round )
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
@@ -1933,14 +1877,14 @@ void CPlayerInterface::artifactPut(const ArtifactLocation &al)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 }
 
 void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 	for(auto isa : GH.listInt)
 	{
 		auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@@ -1955,7 +1899,7 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto hero = std::visit(HeroObjectRetriever(), dst.artHolder);
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 
 	bool redraw = true;
 	// If a bulk transfer has arrived, then redrawing only the last art movement.
@@ -1984,7 +1928,7 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 	for(auto isa : GH.listInt)
 	{
 		auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@@ -1997,7 +1941,7 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
-	updateInfo(hero);
+	adventureInt->onHeroChanged(hero);
 	for(auto isa : GH.listInt)
 	{
 		auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
@@ -2016,8 +1960,6 @@ void CPlayerInterface::playerStartsTurn(PlayerColor player)
 	}
 	else
 	{
-		if (player == playerID)
-			adventureInt->infoBar->showSelection();
 		while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.listInt.front().get())) //don't remove dialogs that expect query answer
 			GH.popInts(1);
 	}
@@ -2057,7 +1999,7 @@ CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
 
 bool CPlayerInterface::capturedAllEvents()
 {
-	if (duringMovement)
+	if(duringMovement)
 	{
 		//just inform that we are capturing events. they will be processed by heroMoved() in client thread.
 		return true;
@@ -2065,7 +2007,7 @@ bool CPlayerInterface::capturedAllEvents()
 
 	bool needToLockAdventureMap = adventureInt && adventureInt->active && CGI->mh->hasOngoingAnimations();
 
-	if (ignoreEvents || needToLockAdventureMap)
+	if (ignoreEvents || needToLockAdventureMap || isAutoFightOn)
 	{
 		boost::unique_lock<boost::mutex> un(eventsM);
 		while(!SDLEventsQueue.empty())
@@ -2245,15 +2187,6 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
 	if (!showingDialog->get())
 		GH.fakeMouseMove();
 
-
-	//todo: this should be in main thread
-	if (adventureInt)
-	{
-		// (i == 0) means hero went through all the path
-		adventureInt->updateMoveHero(h, (i != 0));
-		adventureInt->updateNextHero(h);
-	}
-
 	CGI->mh->waitForOngoingAnimations();
 	setMovementStatus(false);
 }

+ 0 - 1
client/CPlayerInterface.h

@@ -240,7 +240,6 @@ public:
 	void redrawHeroWin(const CGHeroInstance * hero);
 	void openTownWindow(const CGTownInstance * town); //shows townscreen
 	void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
-	void updateInfo(const CGObjectInstance * specific);
 	void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
 	void activateForSpectator(); // TODO: spectator probably need own player interface class
 

+ 4 - 4
client/ClientCommandManager.cpp

@@ -387,12 +387,12 @@ void ClientCommandManager::handleBonusesCommand(std::istringstream & singleWordB
 		ss << b;
 		return ss.str();
 	};
-	printCommandMessage("Bonuses of " + adventureInt->curArmy()->getObjectName() + "\n");
-	printCommandMessage(format(adventureInt->curArmy()->getBonusList()) + "\n");
+		printCommandMessage("Bonuses of " + adventureInt->getCurrentArmy()->getObjectName() + "\n");
+		printCommandMessage(format(adventureInt->getCurrentArmy()->getBonusList()) + "\n");
 
 	printCommandMessage("\nInherited bonuses:\n");
 	TCNodes parents;
-	adventureInt->curArmy()->getParents(parents);
+		adventureInt->getCurrentArmy()->getParents(parents);
 	for(const CBonusSystemNode *parent : parents)
 	{
 		printCommandMessage(std::string("\nBonuses from ") + typeid(*parent).name() + "\n" + format(*parent->getAllBonuses(Selector::all, Selector::all)) + "\n");
@@ -416,7 +416,7 @@ void ClientCommandManager::handleTellCommand(std::istringstream& singleWordBuffe
 
 void ClientCommandManager::handleMpCommand()
 {
-	if(const CGHeroInstance* h = adventureInt->curHero())
+	if(const CGHeroInstance* h = adventureInt->getCurrentHero())
 		printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
 }
 

+ 87 - 62
client/adventureMap/CAdvMapInt.cpp

@@ -91,7 +91,7 @@ CAdvMapInt::CAdvMapInt():
 	resdatabar(new CResDataBar),
 	mapAudio(new MapAudioPlayer()),
 	terrain(new MapView(Point(ADVOPT.advmapX, ADVOPT.advmapY), Point(ADVOPT.advmapW, ADVOPT.advmapH))),
-	state(NA),
+	state(EGameStates::NA),
 	spellBeingCasted(nullptr),
 	selection(nullptr),
 	activeMapPanel(nullptr),
@@ -216,7 +216,7 @@ CAdvMapInt::CAdvMapInt():
 	worldViewUnderground = makeButton(294, std::bind(&CAdvMapInt::fswitchLevel,this), worldViewUndergroundConfig, SDLK_u);
 	panelWorldView->addChildColorableButton(worldViewUnderground);
 
-	setPlayer(LOCPLINT->playerID);
+	onCurrentPlayerChanged(LOCPLINT->playerID);
 
 	int iconColorMultiplier = player.getNum() * 19;
 	int wvLeft = heroList->pos.x - 2; // TODO correct drawing position
@@ -259,7 +259,7 @@ void CAdvMapInt::fworldViewBack()
 {
 	exitWorldView();
 
-	auto hero = curHero();
+	auto hero = getCurrentHero();
 	if (hero)
 		centerOnObject(hero);
 }
@@ -318,7 +318,7 @@ void CAdvMapInt::fshowQuestlog()
 
 void CAdvMapInt::fsleepWake()
 {
-	const CGHeroInstance *h = curHero();
+	const CGHeroInstance *h = getCurrentHero();
 	if (!h)
 		return;
 	bool newSleep = !isHeroSleeping(h);
@@ -339,7 +339,7 @@ void CAdvMapInt::fsleepWake()
 
 void CAdvMapInt::fmoveHero()
 {
-	const CGHeroInstance *h = curHero();
+	const CGHeroInstance *h = getCurrentHero();
 	if (!h || !LOCPLINT->paths.hasPath(h) || CGI->mh->hasOngoingAnimations())
 		return;
 
@@ -348,12 +348,12 @@ void CAdvMapInt::fmoveHero()
 
 void CAdvMapInt::fshowSpellbok()
 {
-	if (!curHero()) //checking necessary values
+	if (!getCurrentHero()) //checking necessary values
 		return;
 
 	centerOnObject(selection);
 
-	GH.pushIntT<CSpellWindow>(curHero(), LOCPLINT, false);
+	GH.pushIntT<CSpellWindow>(getCurrentHero(), LOCPLINT, false);
 }
 
 void CAdvMapInt::fadventureOPtions()
@@ -372,7 +372,7 @@ void CAdvMapInt::fnextHero()
 	int next = getNextHeroIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
 	if (next < 0)
 		return;
-	select(LOCPLINT->wanderingHeroes[next], true);
+	setSelection(LOCPLINT->wanderingHeroes[next], true);
 }
 
 void CAdvMapInt::fendTurn()
@@ -420,20 +420,6 @@ void CAdvMapInt::updateSleepWake(const CGHeroInstance *h)
 	sleepWake->assignedKeys.insert(state ? SDLK_w : SDLK_z);
 }
 
-void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath)
-{
-	if(!h)
-	{
-		moveHero->block(true);
-		return;
-	}
-	//default value is for everywhere but CPlayerInterface::moveHero, because paths are not updated from there immediately
-	if(boost::logic::indeterminate(hasPath))
-		hasPath = LOCPLINT->paths.hasPath(h);
-
-	moveHero->block(!(bool)hasPath || (h->movement == 0));
-}
-
 void CAdvMapInt::updateSpellbook(const CGHeroInstance *h)
 {
 	spellbook->block(!h);
@@ -460,8 +446,13 @@ int CAdvMapInt::getNextHeroIndex(int startIndex)
 		return -1;
 }
 
-void CAdvMapInt::updateNextHero(const CGHeroInstance *h)
+void CAdvMapInt::onHeroChanged(const CGHeroInstance *h)
 {
+	heroList->update(h);
+
+	if (h == getCurrentHero())
+		adventureInt->infoBar->showSelection();
+
 	int start = vstd::find_pos(LOCPLINT->wanderingHeroes, h);
 	int next = getNextHeroIndex(start);
 	if (next < 0)
@@ -472,6 +463,27 @@ void CAdvMapInt::updateNextHero(const CGHeroInstance *h)
 	const CGHeroInstance *nextH = LOCPLINT->wanderingHeroes[next];
 	bool noActiveHeroes = (next == start) && ((nextH->movement == 0) || isHeroSleeping(nextH));
 	nextHero->block(noActiveHeroes);
+
+	if(!h)
+	{
+		moveHero->block(true);
+		return;
+	}
+	//default value is for everywhere but CPlayerInterface::moveHero, because paths are not updated from there immediately
+	bool hasPath = LOCPLINT->paths.hasPath(h);
+
+	moveHero->block(!(bool)hasPath || (h->movement == 0));
+}
+
+void CAdvMapInt::onTownChanged(const CGTownInstance * town)
+{
+	townList->update(town);
+	adventureInt->infoBar->showSelection();
+}
+
+void CAdvMapInt::showInfoBoxMessage(const std::vector<Component> & components, std::string message, int timer)
+{
+	infoBar->pushComponents(components, message, timer);
 }
 
 void CAdvMapInt::activate()
@@ -532,7 +544,7 @@ void CAdvMapInt::showAll(SDL_Surface * to)
 {
 	bg->draw(to, 0, 0);
 
-	if(state != INGAME)
+	if(state != EGameStates::INGAME)
 		return;
 
 	switch (mode)
@@ -565,18 +577,30 @@ bool CAdvMapInt::isHeroSleeping(const CGHeroInstance *hero)
 	return vstd::contains(LOCPLINT->sleepingHeroes, hero);
 }
 
+void CAdvMapInt::onHeroWokeUp(const CGHeroInstance * hero)
+{
+	if (!isHeroSleeping(hero))
+		return;
+
+	sleepWake->clickLeft(true, false);
+	sleepWake->clickLeft(false, true);
+	//could've just called
+	//adventureInt->fsleepWake();
+	//but no authentic button click/sound ;-)
+}
+
 void CAdvMapInt::setHeroSleeping(const CGHeroInstance *hero, bool sleep)
 {
 	if (sleep)
 		LOCPLINT->sleepingHeroes.push_back(hero); //FIXME: should we check for existence?
 	else
 		LOCPLINT->sleepingHeroes -= hero;
-	updateNextHero(nullptr);
+	onHeroChanged(nullptr);
 }
 
 void CAdvMapInt::show(SDL_Surface * to)
 {
-	if(state != INGAME)
+	if(state != EGameStates::INGAME)
 		return;
 
 	handleMapScrollingUpdate();
@@ -636,7 +660,7 @@ void CAdvMapInt::selectionChanged()
 {
 	const CGTownInstance *to = LOCPLINT->towns[townList->getSelectedIndex()];
 	if (selection != to)
-		select(to);
+		setSelection(to);
 }
 
 void CAdvMapInt::centerOnTile(int3 on)
@@ -682,8 +706,8 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
 	if (mode != EAdvMapMode::NORMAL)
 		return;
 
-	const CGHeroInstance *h = curHero(); //selected hero
-	const CGTownInstance *t = curTown(); //selected town
+	const CGHeroInstance *h = getCurrentHero(); //selected hero
+	const CGTownInstance *t = getCurrentTown(); //selected town
 
 	switch(key)
 	{
@@ -843,7 +867,7 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
 			const CGPath & path = LOCPLINT->paths.getPath(h);
 
 			if (path.nodes.size() > 2)
-				updateMoveHero(h);
+				onHeroChanged(h);
 			else
 			if(!path.nodes[0].turns)
 				LOCPLINT->moveHero(h, path);
@@ -874,7 +898,7 @@ std::optional<Point> CAdvMapInt::keyToMoveDirection(const SDL_Keycode & key)
 	return std::nullopt;
 }
 
-void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
+void CAdvMapInt::setSelection(const CArmedInstance *sel, bool centerView)
 {
 	assert(sel);
 	if(selection != sel)
@@ -893,7 +917,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
 		heroList->select(nullptr);
 
 		updateSleepWake(nullptr);
-		updateMoveHero(nullptr);
+		onHeroChanged(nullptr);
 		updateSpellbook(nullptr);
 	}
 	else //hero selected
@@ -907,7 +931,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
 		LOCPLINT->paths.verifyPath(hero);
 
 		updateSleepWake(hero);
-		updateMoveHero(hero);
+		onHeroChanged(hero);
 		updateSpellbook(hero);
 	}
 	townList->redraw();
@@ -962,11 +986,23 @@ bool CAdvMapInt::isActive()
 
 void CAdvMapInt::startHotSeatWait(PlayerColor Player)
 {
-	state = WAITING;
+	state = EGameStates::WAITING;
+}
+
+void CAdvMapInt::onMapTileChanged(const int3 & mapPosition)
+{
+	minimap->updateTile(mapPosition);
 }
 
-void CAdvMapInt::setPlayer(PlayerColor Player)
+void CAdvMapInt::onMapTilesChanged()
 {
+	minimap->update();
+}
+
+void CAdvMapInt::onCurrentPlayerChanged(PlayerColor Player)
+{
+	selection = nullptr;
+
 	if (Player == player)
 		return;
 
@@ -981,12 +1017,13 @@ void CAdvMapInt::setPlayer(PlayerColor Player)
 
 void CAdvMapInt::startTurn()
 {
-	state = INGAME;
+	state = EGameStates::INGAME;
 	if(LOCPLINT->cb->getCurrentPlayer() == LOCPLINT->playerID
 		|| settings["session"]["spectate"].Bool())
 	{
 		adjustActiveness(false);
 		minimap->setAIRadar(false);
+		infoBar->showSelection();
 	}
 }
 
@@ -1012,17 +1049,17 @@ void CAdvMapInt::initializeNewTurn()
 	//select first hero if available.
 	if (heroToSelect != nullptr)
 	{
-		select(heroToSelect, centerView);
+		setSelection(heroToSelect, centerView);
 	}
 	else if (LOCPLINT->towns.size())
-		select(LOCPLINT->towns.front(), centerView);
+		setSelection(LOCPLINT->towns.front(), centerView);
 	else
-		select(LOCPLINT->wanderingHeroes.front());
+		setSelection(LOCPLINT->wanderingHeroes.front());
 
 	//show new day animation and sound on infobar
 	infoBar->showDate();
 
-	updateNextHero(nullptr);
+	onHeroChanged(nullptr);
 	showAll(screen);
 	mapAudio->onPlayerTurnStarted();
 
@@ -1103,9 +1140,9 @@ void CAdvMapInt::onTileLeftClicked(const int3 &mapPos)
 		if(selection == topBlocking) //selected town clicked
 			LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(topBlocking));
 		else if(canSelect)
-			select(static_cast<const CArmedInstance*>(topBlocking), false);
+			setSelection(static_cast<const CArmedInstance*>(topBlocking), false);
 	}
-	else if(const CGHeroInstance * currentHero = curHero()) //hero is selected
+	else if(const CGHeroInstance * currentHero = getCurrentHero()) //hero is selected
 	{
 		isHero = true;
 
@@ -1117,7 +1154,7 @@ void CAdvMapInt::onTileLeftClicked(const int3 &mapPos)
 		}
 		else if(canSelect && pn->turns == 255 ) //selectable object at inaccessible tile
 		{
-			select(static_cast<const CArmedInstance*>(topBlocking), false);
+			setSelection(static_cast<const CArmedInstance*>(topBlocking), false);
 			return;
 		}
 		else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
@@ -1132,7 +1169,7 @@ void CAdvMapInt::onTileLeftClicked(const int3 &mapPos)
 			else //remove old path and find a new one if we clicked on accessible tile
 			{
 				LOCPLINT->paths.setPath(currentHero, mapPos);
-				updateMoveHero(currentHero);
+				onHeroChanged(currentHero);
 			}
 		}
 	} //end of hero is selected "case"
@@ -1164,7 +1201,7 @@ void CAdvMapInt::onTileHovered(const int3 &mapPos)
 	if(objAtTile)
 	{
 		objRelations = LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner);
-		std::string text = curHero() ? objAtTile->getHoverText(curHero()) : objAtTile->getHoverText(LOCPLINT->playerID);
+		std::string text = getCurrentHero() ? objAtTile->getHoverText(getCurrentHero()) : objAtTile->getHoverText(LOCPLINT->playerID);
 		boost::replace_all(text,"\n"," ");
 		statusbar->write(text);
 	}
@@ -1211,7 +1248,7 @@ void CAdvMapInt::onTileHovered(const int3 &mapPos)
 		else
 			CCS->curh->set(Cursor::Map::POINTER);
 	}
-	else if(const CGHeroInstance * hero = curHero())
+	else if(const CGHeroInstance * hero = getCurrentHero())
 	{
 		std::array<Cursor::Map, 4> cursorMove      = { Cursor::Map::T1_MOVE,       Cursor::Map::T2_MOVE,       Cursor::Map::T3_MOVE,       Cursor::Map::T4_MOVE,       };
 		std::array<Cursor::Map, 4> cursorAttack    = { Cursor::Map::T1_ATTACK,     Cursor::Map::T2_ATTACK,     Cursor::Map::T3_ATTACK,     Cursor::Map::T4_ATTACK,     };
@@ -1357,12 +1394,12 @@ void CAdvMapInt::leaveCastingMode(bool cast, int3 dest)
 	activate();
 
 	if(cast)
-		LOCPLINT->cb->castSpell(curHero(), id, dest);
+		LOCPLINT->cb->castSpell(getCurrentHero(), id, dest);
 	else
 		LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[731]); //Spell cancelled
 }
 
-const CGHeroInstance * CAdvMapInt::curHero() const
+const CGHeroInstance * CAdvMapInt::getCurrentHero() const
 {
 	if(selection && selection->ID == Obj::HERO)
 		return dynamic_cast<const CGHeroInstance *>(selection);
@@ -1370,7 +1407,7 @@ const CGHeroInstance * CAdvMapInt::curHero() const
 		return nullptr;
 }
 
-const CGTownInstance * CAdvMapInt::curTown() const
+const CGTownInstance * CAdvMapInt::getCurrentTown() const
 {
 	if(selection && selection->ID == Obj::TOWN)
 		return dynamic_cast<const CGTownInstance *>(selection);
@@ -1378,7 +1415,7 @@ const CGTownInstance * CAdvMapInt::curTown() const
 		return nullptr;
 }
 
-const CArmedInstance * CAdvMapInt::curArmy() const
+const CArmedInstance * CAdvMapInt::getCurrentArmy() const
 {
 	if (selection)
 		return dynamic_cast<const CArmedInstance *>(selection);
@@ -1427,18 +1464,6 @@ void CAdvMapInt::adjustActiveness(bool aiTurnStart)
 		activate();
 }
 
-void CAdvMapInt::quickCombatLock()
-{
-	if(!duringAITurn)
-		deactivate();
-}
-
-void CAdvMapInt::quickCombatUnlock()
-{
-	if(!duringAITurn)
-		activate();
-}
-
 void CAdvMapInt::exitWorldView()
 {
 	mode = EAdvMapMode::NORMAL;

+ 48 - 26
client/adventureMap/CAdvMapInt.h

@@ -23,6 +23,7 @@ class CArmedInstance;
 class IShipyard;
 struct CGPathNode;
 struct ObjectPosInfo;
+struct Component;
 
 VCMI_LIB_NAMESPACE_END
 
@@ -54,12 +55,9 @@ enum class EAdvMapMode
 /// can get to the towns and heroes.
 class CAdvMapInt : public CIntObject
 {
-	//TODO: remove
-	friend class CPlayerInterface;
-
 private:
 	enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8};
-	enum EGameStates {NA, INGAME, WAITING};
+	enum class EGameStates {NA, INGAME, WAITING};
 
 	EGameStates state;
 	EAdvMapMode mode;
@@ -145,6 +143,11 @@ private:
 
 	std::optional<Point> keyToMoveDirection(const SDL_Keycode & key);
 
+	bool isHeroSleeping(const CGHeroInstance *hero);
+	void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
+	int getNextHeroIndex(int startIndex); //for Next Hero button - cycles awake heroes with movement only
+	void endingTurn();
+
 public:
 	CAdvMapInt();
 
@@ -162,9 +165,28 @@ public:
 
 	// public interface
 
-	/// called by MapView whenever currently visible area changes
-	/// visibleArea describen now visible map section measured in tiles
-	void onMapViewMoved(const Rect & visibleArea, int mapLevel);
+	void startHotSeatWait(PlayerColor Player);
+	void startTurn();
+	void initializeNewTurn();
+	void aiTurnStarted();
+
+	/// Called by PlayerInterface when hero is forced to wake up, e.g. on moving sleeping hero
+	void onHeroWokeUp(const CGHeroInstance * hero);
+
+	/// Called by PlayerInterface when current player changes in hotseat
+	void onCurrentPlayerChanged(PlayerColor Player);
+
+	/// Called by PlayerInterface when specific map tile changed and must be updated on minimap
+	void onMapTileChanged(const int3 & mapPosition);
+
+	/// Called by PlayerInterface when unknown number of tiles changed and minimap should redraw
+	void onMapTilesChanged();
+
+	/// Called by PlayerInterface when hero state changed and hero list must be updated
+	void onHeroChanged(const CGHeroInstance * hero);
+
+	/// Called by PlayerInterface when town state changed and town list must be updated
+	void onTownChanged(const CGTownInstance * town);
 
 	/// Called when map audio should be paused, e.g. on combat or town scren access
 	void onAudioPaused();
@@ -172,36 +194,35 @@ public:
 	/// Called when map audio should be resume, opposite to onPaused
 	void onAudioResumed();
 
-	void select(const CArmedInstance *sel, bool centerView = true);
-	void centerOnTile(int3 on);
-	void centerOnObject(const CGObjectInstance *obj);
+	/// Requests to display provided information inside infobox
+	void showInfoBoxMessage(const std::vector<Component> & components, std::string message, int timer);
 
-	bool isHeroSleeping(const CGHeroInstance *hero);
-	void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
-	int getNextHeroIndex(int startIndex); //for Next Hero button - cycles awake heroes with movement only
+	/// Changes currently selected object
+	void setSelection(const CArmedInstance *sel, bool centerView = true);
 
-	void setPlayer(PlayerColor Player);
-	void startHotSeatWait(PlayerColor Player);
-	void startTurn();
-	void initializeNewTurn();
-	void endingTurn();
-	void aiTurnStarted();
+	/// Changes position on map to center selected location
+	void centerOnTile(int3 on);
+	void centerOnObject(const CGObjectInstance *obj);
 
-	void quickCombatLock(); //should be called when quick battle started
-	void quickCombatUnlock();
+	/// called by MapView whenever currently visible area changes
+	/// visibleArea describes now visible map section measured in tiles
+	void onMapViewMoved(const Rect & visibleArea, int mapLevel);
 
+	/// called by MapView whenever tile is clicked
 	void onTileLeftClicked(const int3 & mapPos);
+
+	/// called by MapView whenever tile is hovered
 	void onTileHovered(const int3 & mapPos);
+
+	/// called by MapView whenever tile is clicked
 	void onTileRightClicked(const int3 & mapPos);
 
 	void enterCastingMode(const CSpell * sp);
 	void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1));
-	const CGHeroInstance * curHero() const;
-	const CGTownInstance * curTown() const;
-	const CArmedInstance * curArmy() const;
 
-	void updateMoveHero(const CGHeroInstance *h, tribool hasPath = boost::logic::indeterminate);
-	void updateNextHero(const CGHeroInstance *h);
+	const CGHeroInstance * getCurrentHero() const;
+	const CGTownInstance * getCurrentTown() const;
+	const CArmedInstance * getCurrentArmy() const;
 
 	/// returns area of screen covered by terrain (main game area)
 	Rect terrainAreaPixels() const;
@@ -217,6 +238,7 @@ public:
 
 	/// opens world view with specific info, e.g. after View Earth/Air is shown
 	void openWorldView(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain);
+
 };
 
 extern std::shared_ptr<CAdvMapInt> adventureInt;

+ 1 - 1
client/adventureMap/CAdventureOptions.cpp

@@ -41,7 +41,7 @@ CAdventureOptions::CAdventureOptions()
 	puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
 
 	dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
-	if(const CGHeroInstance *h = adventureInt->curHero())
+	if(const CGHeroInstance *h = adventureInt->getCurrentHero())
 		dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
 	else
 		dig->block(true);

+ 1 - 1
client/adventureMap/CInGameConsole.cpp

@@ -259,7 +259,7 @@ void CInGameConsole::endEnteringText(bool processEnteredText)
 			clientCommandThread.detach();
 		}
 		else
-			LOCPLINT->cb->sendMessage(txt, adventureInt->curArmy());
+			LOCPLINT->cb->sendMessage(txt, adventureInt->getCurrentArmy());
 	}
 	enteredText.clear();
 

+ 4 - 4
client/adventureMap/CInfoBar.cpp

@@ -237,15 +237,15 @@ void CInfoBar::reset()
 void CInfoBar::showSelection()
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
-	if(adventureInt->curHero())
+	if(adventureInt->getCurrentHero())
 	{
-		showHeroSelection(adventureInt->curHero());
+		showHeroSelection(adventureInt->getCurrentHero());
 		return;
 	}
 
-	if(adventureInt->curTown())
+	if(adventureInt->getCurrentTown())
 	{
-		showTownSelection(adventureInt->curTown());
+		showTownSelection(adventureInt->getCurrentTown());
 		return;
 	}
 

+ 8 - 8
client/adventureMap/CList.cpp

@@ -203,8 +203,8 @@ std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
 
 void CHeroList::CHeroItem::select(bool on)
 {
-	if(on && adventureInt->curHero() != hero)
-		adventureInt->select(hero);
+	if(on && adventureInt->getCurrentHero() != hero)
+		adventureInt->setSelection(hero);
 }
 
 void CHeroList::CHeroItem::open()
@@ -254,8 +254,8 @@ void CHeroList::update(const CGHeroInstance * hero)
 	//simplest solution for now: reset list and restore selection
 
 	listBox->resize(LOCPLINT->wanderingHeroes.size());
-	if (adventureInt->curHero())
-		select(adventureInt->curHero());
+	if (adventureInt->getCurrentHero())
+		select(adventureInt->getCurrentHero());
 
 	CList::update();
 }
@@ -292,8 +292,8 @@ void CTownList::CTownItem::update()
 
 void CTownList::CTownItem::select(bool on)
 {
-	if (on && adventureInt->curTown() != town)
-		adventureInt->select(town);
+	if (on && adventureInt->getCurrentTown() != town)
+		adventureInt->setSelection(town);
 }
 
 void CTownList::CTownItem::open()
@@ -326,8 +326,8 @@ void CTownList::update(const CGTownInstance *)
 	//simplest solution for now: reset list and restore selection
 
 	listBox->resize(LOCPLINT->towns.size());
-	if (adventureInt->curTown())
-		select(adventureInt->curTown());
+	if (adventureInt->getCurrentTown())
+		select(adventureInt->getCurrentTown());
 
 	CList::update();
 }

+ 3 - 3
client/mapView/MapRendererContext.cpp

@@ -73,9 +73,9 @@ bool MapRendererBaseContext::isActiveHero(const CGObjectInstance * obj) const
 	if(obj->ID == Obj::HERO)
 	{
 		assert(dynamic_cast<const CGHeroInstance *>(obj) != nullptr);
-		if(adventureInt->curHero() != nullptr)
+		if(adventureInt->getCurrentHero() != nullptr)
 		{
-			if(obj->id == adventureInt->curHero()->id)
+			if(obj->id == adventureInt->getCurrentHero()->id)
 				return true;
 		}
 	}
@@ -206,7 +206,7 @@ MapRendererAdventureContext::MapRendererAdventureContext(const MapRendererContex
 
 const CGPath * MapRendererAdventureContext::currentPath() const
 {
-	const auto * hero = adventureInt->curHero();
+	const auto * hero = adventureInt->getCurrentHero();
 
 	if(!hero)
 		return nullptr;

+ 3 - 3
client/windows/CCastleInterface.cpp

@@ -1229,9 +1229,9 @@ void CCastleInterface::close()
 	if(town->tempOwner == LOCPLINT->playerID) //we may have opened window for an allied town
 	{
 		if(town->visitingHero && town->visitingHero->tempOwner == LOCPLINT->playerID)
-			adventureInt->select(town->visitingHero);
+			adventureInt->setSelection(town->visitingHero);
 		else
-			adventureInt->select(town);
+			adventureInt->setSelection(town);
 	}
 	CWindowObject::close();
 }
@@ -1239,7 +1239,7 @@ void CCastleInterface::close()
 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
+	adventureInt->setSelection(town->visitingHero);//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
 	LOCPLINT->cb->teleportHero(town->visitingHero, dest);
 	LOCPLINT->paths.erasePath(town->visitingHero);
 }

+ 5 - 5
client/windows/InfoWindows.cpp

@@ -332,8 +332,8 @@ void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p,
 	}
 	else
 	{
-		if(adventureInt->curHero())
-			CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
+		if(adventureInt->getCurrentHero())
+			CRClickPopup::createAndPush(obj->getHoverText(adventureInt->getCurrentHero()));
 		else
 			CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
 	}
@@ -376,7 +376,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
 	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
 {
 	InfoAboutTown iah;
-	LOCPLINT->cb->getTownInfo(town, iah, adventureInt->curTown()); //todo: should this be nearest hero?
+	LOCPLINT->cb->getTownInfo(town, iah, adventureInt->getCurrentTown()); //todo: should this be nearest hero?
 
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
@@ -386,7 +386,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
 	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
 {
 	InfoAboutHero iah;
-	LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->curHero());//todo: should this be nearest hero?
+	LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->getCurrentHero());//todo: should this be nearest hero?
 
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
@@ -405,7 +405,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
 std::shared_ptr<WindowBase> CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
 {
 	if(nullptr == specific)
-		specific = adventureInt->curArmy();
+		specific = adventureInt->getCurrentArmy();
 
 	if(nullptr == specific)
 	{

+ 1 - 1
lib/NetPacksLib.cpp

@@ -1915,7 +1915,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
 	[[maybe_unused]] const CArtifactInstance *transformedArt = al.getArt();
 	assert(transformedArt);
 	bool combineEquipped = !ArtifactUtils::isSlotBackpack(al.slot);
-	assert(vstd::contains_if(transformedArt->assemblyPossibilities(artSet, combineEquipped), [=](const CArtifact * art)->bool
+	assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(artSet, transformedArt->artType->getId(), combineEquipped), [=](const CArtifact * art)->bool
 		{
 			return art->getId() == builtArt->getId();
 		}));