Răsfoiți Sursa

Merge pull request #3821 from SoundSSGood/CWindowWithArtifacts-refactoring

CWindowWithArtifacts refactoring
Ivan Savenko 1 an în urmă
părinte
comite
01c2814d35

+ 4 - 4
client/CMakeLists.txt

@@ -104,7 +104,7 @@ set(client_SRCS
 	globalLobby/GlobalLobbyWindow.cpp
 
 	widgets/Buttons.cpp
-	widgets/CArtifactHolder.cpp
+	widgets/CArtPlace.cpp
 	widgets/CComponent.cpp
 	widgets/CExchangeController.cpp
 	widgets/CGarrisonInt.cpp
@@ -123,7 +123,6 @@ set(client_SRCS
 	widgets/CArtifactsOfHeroAltar.cpp
 	widgets/CArtifactsOfHeroMarket.cpp
 	widgets/CArtifactsOfHeroBackpack.cpp
-	widgets/CWindowWithArtifacts.cpp
 	widgets/RadialMenu.cpp
 	widgets/markets/CAltarArtifacts.cpp
 	widgets/markets/CAltarCreatures.cpp
@@ -153,6 +152,7 @@ set(client_SRCS
 	windows/InfoWindows.cpp
 	windows/QuickRecruitmentWindow.cpp
 	windows/CHeroBackpackWindow.cpp
+	windows/CWindowWithArtifacts.cpp
 	windows/settings/GeneralOptionsTab.cpp
 	windows/settings/OtherOptionsTab.cpp
 	windows/settings/SettingsMainWindow.cpp
@@ -295,7 +295,7 @@ set(client_HEADERS
 	globalLobby/GlobalLobbyWindow.h
 
 	widgets/Buttons.h
-	widgets/CArtifactHolder.h
+	widgets/CArtPlace.h
 	widgets/CComponent.h
 	widgets/CExchangeController.h
 	widgets/CGarrisonInt.h
@@ -314,7 +314,6 @@ set(client_HEADERS
 	widgets/CArtifactsOfHeroAltar.h
 	widgets/CArtifactsOfHeroMarket.h
 	widgets/CArtifactsOfHeroBackpack.h
-	widgets/CWindowWithArtifacts.h
 	widgets/RadialMenu.h
 	widgets/markets/CAltarArtifacts.h
 	widgets/markets/CAltarCreatures.h
@@ -344,6 +343,7 @@ set(client_HEADERS
 	windows/InfoWindows.h
 	windows/QuickRecruitmentWindow.h
 	windows/CHeroBackpackWindow.h
+	windows/CWindowWithArtifacts.h
 	windows/settings/GeneralOptionsTab.h
 	windows/settings/OtherOptionsTab.h
 	windows/settings/SettingsMainWindow.h

+ 4 - 4
client/CPlayerInterface.cpp

@@ -1745,7 +1745,7 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	adventureInt->onHeroChanged(cb->getHero(al.artHolder));
 
-	for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
+	for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
 		artWin->artifactRemoved(al);
 
 	waitWhileDialog();
@@ -1765,7 +1765,7 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
 			redraw = false;
 	}
 
-	for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
+	for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
 		artWin->artifactMoved(src, dst, redraw);
 
 	waitWhileDialog();
@@ -1781,7 +1781,7 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	adventureInt->onHeroChanged(cb->getHero(al.artHolder));
 
-	for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
+	for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
 		artWin->artifactAssembled(al);
 }
 
@@ -1790,7 +1790,7 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	adventureInt->onHeroChanged(cb->getHero(al.artHolder));
 
-	for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
+	for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
 		artWin->artifactDisassembled(al);
 }
 

+ 12 - 12
client/widgets/CArtifactHolder.cpp → client/widgets/CArtPlace.cpp

@@ -1,5 +1,5 @@
 /*
- * CArtifactHolder.cpp, part of VCMI engine
+ * CArtPlace.cpp, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *
@@ -8,7 +8,7 @@
  *
  */
 #include "StdInc.h"
-#include "CArtifactHolder.h"
+#include "CArtPlace.h"
 
 #include "../gui/CGuiHandler.h"
 #include "../gui/Shortcut.h"
@@ -92,7 +92,7 @@ CArtPlace::CArtPlace(Point position, const CArtifactInstance * art)
 	image->disable();
 }
 
-const CArtifactInstance * CArtPlace::getArt()
+const CArtifactInstance * CArtPlace::getArt() const
 {
 	return ourArt;
 }
@@ -108,7 +108,7 @@ CCommanderArtPlace::CCommanderArtPlace(Point position, const CGHeroInstance * co
 void CCommanderArtPlace::returnArtToHeroCallback()
 {
 	ArtifactPosition artifactPos = commanderSlotID;
-	ArtifactPosition freeSlot = ArtifactUtils::getArtBackpackPosition(commanderOwner, ourArt->getTypeId());
+	ArtifactPosition freeSlot = ArtifactUtils::getArtBackpackPosition(commanderOwner, getArt()->getTypeId());
 	if(freeSlot == ArtifactPosition::PRE_FIRST)
 	{
 		LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152"));
@@ -119,7 +119,7 @@ void CCommanderArtPlace::returnArtToHeroCallback()
 		src.creature = SlotID::COMMANDER_SLOT_PLACEHOLDER;
 		ArtifactLocation dst(commanderOwner->id, freeSlot);
 
-		if(ourArt->canBePutAt(commanderOwner, freeSlot, true))
+		if(getArt()->canBePutAt(commanderOwner, freeSlot, true))
 		{
 			LOCPLINT->cb->swapArtifacts(src, dst);
 			setArtifact(nullptr);
@@ -130,13 +130,13 @@ void CCommanderArtPlace::returnArtToHeroCallback()
 
 void CCommanderArtPlace::clickPressed(const Point & cursorPosition)
 {
-	if(ourArt && text.size())
+	if(getArt() && text.size())
 		LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this]() { returnArtToHeroCallback(); }, []() {});
 }
 
-void CCommanderArtPlace::showPopupWindow(const Point& cursorPosition)
+void CCommanderArtPlace::showPopupWindow(const Point & cursorPosition)
 {
-	if(ourArt && text.size())
+	if(getArt() && text.size())
 		CArtPlace::showPopupWindow(cursorPosition);
 }
 
@@ -204,22 +204,22 @@ void CArtPlace::setArtifact(const CArtifactInstance * art)
 	}
 }
 
-void CArtPlace::setClickPressedCallback(ClickFunctor callback)
+void CArtPlace::setClickPressedCallback(const ClickFunctor & callback)
 {
 	clickPressedCallback = callback;
 }
 
-void CArtPlace::setShowPopupCallback(ClickFunctor callback)
+void CArtPlace::setShowPopupCallback(const ClickFunctor & callback)
 {
 	showPopupCallback = callback;
 }
 
-void CArtPlace::setGestureCallback(ClickFunctor callback)
+void CArtPlace::setGestureCallback(const ClickFunctor & callback)
 {
 	gestureCallback = callback;
 }
 
-void CHeroArtPlace::addCombinedArtInfo(std::map<const CArtifact*, int> & arts)
+void CHeroArtPlace::addCombinedArtInfo(const std::map<const CArtifact*, int> & arts)
 {
 	for(const auto & combinedArt : arts)
 	{

+ 12 - 27
client/widgets/CArtifactHolder.h → client/widgets/CArtPlace.h

@@ -1,5 +1,5 @@
 /*
- * CArtifactHolder.h, part of VCMI engine
+ * CArtPlace.h, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *
@@ -11,58 +11,43 @@
 
 #include "MiscWidgets.h"
 
-VCMI_LIB_NAMESPACE_BEGIN
-
-struct ArtifactLocation;
-class CArtifactSet;
-
-VCMI_LIB_NAMESPACE_END
-
 class CAnimImage;
 
-class CArtifactHolder
-{
-public:
-	virtual void artifactRemoved(const ArtifactLocation & artLoc)=0;
-	virtual void artifactMoved(const ArtifactLocation & artLoc, const ArtifactLocation & destLoc, bool withRedraw)=0;
-	virtual void artifactDisassembled(const ArtifactLocation & artLoc)=0;
-	virtual void artifactAssembled(const ArtifactLocation & artLoc)=0;
-};
-
 class CArtPlace : public SelectableSlot
 {
 public:
 	using ClickFunctor = std::function<void(CArtPlace&, const Point&)>;
 
 	ArtifactPosition slot;
-
+	
 	CArtPlace(Point position, const CArtifactInstance * art = nullptr);
-	const CArtifactInstance * getArt();
+	const CArtifactInstance * getArt() const;
 	void lockSlot(bool on);
 	bool isLocked() const;
 	void setArtifact(const CArtifactInstance * art);
-	void setClickPressedCallback(ClickFunctor callback);
-	void setShowPopupCallback(ClickFunctor callback);
-	void setGestureCallback(ClickFunctor callback);
+	void setClickPressedCallback(const ClickFunctor & callback);
+	void setShowPopupCallback(const ClickFunctor & callback);
+	void setGestureCallback(const ClickFunctor & callback);
 	void clickPressed(const Point & cursorPosition) override;
 	void showPopupWindow(const Point & cursorPosition) override;
 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
 
-protected:
-	std::shared_ptr<CAnimImage> image;
+private:
 	const CArtifactInstance * ourArt;
-	int imageIndex;
 	bool locked;
+	int imageIndex;
+	std::shared_ptr<CAnimImage> image;
 	ClickFunctor clickPressedCallback;
 	ClickFunctor showPopupCallback;
 	ClickFunctor gestureCallback;
 
+protected:
 	void setInternals(const CArtifactInstance * artInst);
 };
 
 class CCommanderArtPlace : public CArtPlace
 {
-protected:
+private:
 	const CGHeroInstance * commanderOwner;
 	ArtifactPosition commanderSlotID;
 
@@ -78,7 +63,7 @@ class CHeroArtPlace: public CArtPlace
 {
 public:
 	CHeroArtPlace(Point position, const CArtifactInstance * art = nullptr);
-	void addCombinedArtInfo(std::map<const CArtifact*, int> & arts);
+	void addCombinedArtInfo(const std::map<const CArtifact*, int> & arts);
 };
 
 namespace ArtifactUtilsClient

+ 1 - 1
client/widgets/CArtifactsOfHeroBase.h

@@ -9,7 +9,7 @@
  */
 #pragma once
 
-#include "CArtifactHolder.h"
+#include "CArtPlace.h"
 
 class CButton;
 

+ 0 - 1
client/widgets/CComponent.cpp

@@ -10,7 +10,6 @@
 #include "StdInc.h"
 #include "CComponent.h"
 
-#include "CArtifactHolder.h"
 #include "Images.h"
 
 #include <vcmi/spells/Service.h>

+ 1 - 2
client/widgets/CExchangeController.h

@@ -9,8 +9,7 @@
  */
 #pragma once
  
-#include "../windows/CWindowObject.h"
-#include "CWindowWithArtifacts.h"
+#include "../lib/mapObjects/CGHeroInstance.h"
  
 class CCallback;
 

+ 0 - 56
client/widgets/CWindowWithArtifacts.h

@@ -1,56 +0,0 @@
-/*
- * CWindowWithArtifacts.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#pragma once
-
-#include "CArtifactHolder.h"
-#include "CArtifactsOfHeroMain.h"
-#include "CArtifactsOfHeroKingdom.h"
-#include "CArtifactsOfHeroAltar.h"
-#include "CArtifactsOfHeroMarket.h"
-#include "CArtifactsOfHeroBackpack.h"
-
-class CWindowWithArtifacts : public CArtifactHolder
-{
-public:
-	using CArtifactsOfHeroPtr = std::variant<
-		std::weak_ptr<CArtifactsOfHeroMarket>,
-		std::weak_ptr<CArtifactsOfHeroAltar>,
-		std::weak_ptr<CArtifactsOfHeroKingdom>,
-		std::weak_ptr<CArtifactsOfHeroMain>,
-		std::weak_ptr<CArtifactsOfHeroBackpack>,
-		std::weak_ptr<CArtifactsOfHeroQuickBackpack>>;
-	using CloseCallback = std::function<void()>;
-
-	explicit CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets = nullptr);
-	void addSet(CArtifactsOfHeroPtr artSet);
-	void addSetAndCallbacks(CArtifactsOfHeroPtr artSet);
-	void addCloseCallback(CloseCallback callback);
-	const CGHeroInstance * getHeroPickedArtifact();
-	const CArtifactInstance * getPickedArtifact();
-	void clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
-	void showPopupArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
-	void gestureArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
-
-	void artifactRemoved(const ArtifactLocation & artLoc) override;
-	void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) override;
-	void artifactDisassembled(const ArtifactLocation & artLoc) override;
-	void artifactAssembled(const ArtifactLocation & artLoc) override;
-
-protected:
-	std::vector<CArtifactsOfHeroPtr> artSets;
-	CloseCallback closeCallback;
-
-	void updateSlots();
-	std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> getState();
-	std::optional<CArtifactsOfHeroPtr> findAOHbyRef(CArtifactsOfHeroBase & artsInst);
-	void markPossibleSlots();
-	bool checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade);
-	void setCursorAnimation(const CArtifactInstance & artInst);
-};

+ 6 - 6
client/windows/CCastleInterface.cpp

@@ -1183,7 +1183,7 @@ void CTownInfo::showPopupWindow(const Point & cursorPosition)
 }
 
 CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from):
-	CStatusbarWindow(PLAYER_COLORED | BORDERED),
+	CWindowObject(PLAYER_COLORED | BORDERED),
 	town(Town)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@@ -1459,7 +1459,7 @@ void CHallInterface::CBuildingBox::showPopupWindow(const Point & cursorPosition)
 }
 
 CHallInterface::CHallInterface(const CGTownInstance * Town):
-	CStatusbarWindow(PLAYER_COLORED | BORDERED, Town->town->clientInfo.hallBackground),
+	CWindowObject(PLAYER_COLORED | BORDERED, Town->town->clientInfo.hallBackground),
 	town(Town)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@@ -1507,7 +1507,7 @@ CHallInterface::CHallInterface(const CGTownInstance * Town):
 }
 
 CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, EBuildingState state, bool rightClick):
-	CStatusbarWindow(PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0), ImagePath::builtin("TPUBUILD")),
+	CWindowObject(PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0), ImagePath::builtin("TPUBUILD")),
 	town(Town),
 	building(Building)
 {
@@ -1660,7 +1660,7 @@ void LabeledValue::hover(bool on)
 }
 
 CFortScreen::CFortScreen(const CGTownInstance * town):
-	CStatusbarWindow(PLAYER_COLORED | BORDERED, getBgName(town))
+	CWindowObject(PLAYER_COLORED | BORDERED, getBgName(town))
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	ui32 fortSize = static_cast<ui32>(town->creatures.size());
@@ -1849,7 +1849,7 @@ void CFortScreen::RecruitArea::showPopupWindow(const Point & cursorPosition)
 }
 
 CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner, const ImagePath & imagename)
-	: CStatusbarWindow(BORDERED, imagename)
+	: CWindowObject(BORDERED, imagename)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
@@ -1918,7 +1918,7 @@ void CMageGuildScreen::Scroll::hover(bool on)
 }
 
 CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, ArtifactID aid, ObjectInstanceID hid):
-	CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPSMITH"))
+	CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPSMITH"))
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 

+ 1 - 1
client/windows/CCreatureWindow.cpp

@@ -17,7 +17,7 @@
 #include "../CPlayerInterface.h"
 #include "../render/Canvas.h"
 #include "../widgets/Buttons.h"
-#include "../widgets/CArtifactHolder.h"
+#include "../widgets/CArtPlace.h"
 #include "../widgets/CComponent.h"
 #include "../widgets/Images.h"
 #include "../widgets/TextControls.h"

+ 1 - 10
client/windows/CHeroBackpackWindow.cpp

@@ -21,8 +21,7 @@
 #include "CPlayerInterface.h"
 
 CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<CArtifactsOfHeroPtr> & artsSets)
-	: CStatusbarWindow(0)
-	, CWindowWithArtifacts(&artsSets)
+	: CWindowWithArtifacts(&artsSets)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
 
@@ -49,15 +48,7 @@ void CHeroBackpackWindow::showAll(Canvas & to)
 	CMessage::drawBorder(PlayerColor(LOCPLINT->playerID), to, pos.w+28, pos.h+29, pos.x-14, pos.y-15);
 }
 
-void CHeroBackpackWindow::activate()
-{
-	if(const auto art = getPickedArtifact())
-		setCursorAnimation(*art);
-	CIntObject::activate();
-}
-
 CHeroQuickBackpackWindow::CHeroQuickBackpackWindow(const CGHeroInstance * hero, ArtifactPosition targetSlot)
-	: CWindowObject(0)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
 

+ 2 - 4
client/windows/CHeroBackpackWindow.h

@@ -9,8 +9,7 @@
  */
 #pragma once
 
-#include "../widgets/CWindowWithArtifacts.h"
-#include "CWindowObject.h"
+#include "CWindowWithArtifacts.h"
 
 class CFilledTexture;
 
@@ -26,10 +25,9 @@ protected:
 	const int windowMargin = 5;
 
 	void showAll(Canvas & to) override;
-	void activate() override;
 };
 
-class CHeroQuickBackpackWindow : public CWindowObject, public CWindowWithArtifacts
+class CHeroQuickBackpackWindow : public CWindowWithArtifacts
 {
 public:
 	CHeroQuickBackpackWindow(const CGHeroInstance * hero, ArtifactPosition targetSlot);

+ 1 - 8
client/windows/CHeroWindow.cpp

@@ -19,7 +19,6 @@
 #include "../CPlayerInterface.h"
 
 #include "../gui/CGuiHandler.h"
-#include "../gui/CursorHandler.h"
 #include "../gui/TextAlignment.h"
 #include "../gui/Shortcut.h"
 #include "../gui/WindowHandler.h"
@@ -71,7 +70,7 @@ CHeroSwitcher::CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInsta
 }
 
 CHeroWindow::CHeroWindow(const CGHeroInstance * hero)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("HeroScr4"))
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("HeroScr4"))
 {
 	auto & heroscrn = CGI->generaltexth->heroscrn;
 
@@ -360,9 +359,3 @@ bool CHeroWindow::holdsGarrison(const CArmedInstance * army)
 {
 	return army == curHero;
 }
-
-void CHeroWindow::deactivate()
-{
-	CCS->curh->dragAndDropCursor(nullptr);
-	CIntObject::deactivate();
-}

+ 1 - 3
client/windows/CHeroWindow.h

@@ -9,8 +9,7 @@
  */
 #pragma once
 
-#include "../widgets/CWindowWithArtifacts.h"
-#include "CWindowObject.h"
+#include "CWindowWithArtifacts.h"
 
 #include "../../lib/bonuses/IBonusBearer.h"
 
@@ -108,7 +107,6 @@ public:
 	void switchHero(); //changes displayed hero
 	void updateGarrisons() override;
 	bool holdsGarrison(const CArmedInstance * army) override;
-	void deactivate() override;
 	void createBackpackWindow();
 
 	//friends

+ 19 - 53
client/windows/CKingdomInterface.cpp

@@ -19,7 +19,6 @@
 #include "../PlayerLocalState.h"
 #include "../adventureMap/CResDataBar.h"
 #include "../gui/CGuiHandler.h"
-#include "../gui/CursorHandler.h"
 #include "../gui/Shortcut.h"
 #include "../gui/WindowHandler.h"
 #include "../widgets/CComponent.h"
@@ -549,7 +548,10 @@ std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
 	switch(index)
 	{
 	case 0:
-		return std::make_shared<CKingdHeroList>(size);
+		return std::make_shared<CKingdHeroList>(size, [this](const CWindowWithArtifacts::CArtifactsOfHeroPtr & newHeroSet)
+			{
+				addSetAndCallbacks(newHeroSet);
+			});
 	case 1:
 		return std::make_shared<CKingdTownList>(size);
 	default:
@@ -674,31 +676,7 @@ bool CKingdomInterface::holdsGarrison(const CArmedInstance * army)
 	return army->getOwner() == LOCPLINT->playerID;
 }
 
-void CKingdomInterface::artifactAssembled(const ArtifactLocation& artLoc)
-{
-	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
-		arts->artifactAssembled(artLoc);
-}
-
-void CKingdomInterface::artifactDisassembled(const ArtifactLocation& artLoc)
-{
-	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
-		arts->artifactDisassembled(artLoc);
-}
-
-void CKingdomInterface::artifactMoved(const ArtifactLocation& artLoc, const ArtifactLocation& destLoc, bool withRedraw)
-{
-	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
-		arts->artifactMoved(artLoc, destLoc, withRedraw);
-}
-
-void CKingdomInterface::artifactRemoved(const ArtifactLocation& artLoc)
-{
-	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
-		arts->artifactRemoved(artLoc);
-}
-
-CKingdHeroList::CKingdHeroList(size_t maxSize)
+CKingdHeroList::CKingdHeroList(size_t maxSize, const CreateHeroItemFunctor & onCreateHeroItemCallback)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	title = std::make_shared<CPicture>(ImagePath::builtin("OVTITLE"),16,0);
@@ -708,8 +686,20 @@ CKingdHeroList::CKingdHeroList(size_t maxSize)
 
 	ui32 townCount = LOCPLINT->cb->howManyHeroes(false);
 	ui32 size = OVERVIEW_SIZE*116 + 19;
-	heroes = std::make_shared<CListBox>(std::bind(&CKingdHeroList::createHeroItem, this, _1),
-		Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size));
+	heroes = std::make_shared<CListBox>([onCreateHeroItemCallback](size_t idx) -> std::shared_ptr<CIntObject>
+		{
+			auto heroesList = LOCPLINT->localState->getWanderingHeroes();
+			if(idx < heroesList.size())
+			{
+				auto hero = std::make_shared<CHeroItem>(heroesList[idx]);
+				onCreateHeroItemCallback(hero->heroArts);
+				return hero;
+			}
+			else
+			{
+				return std::make_shared<CAnimImage>(AnimationPath::builtin("OVSLOT"), (idx - 2) % GameConstants::KINGDOM_WINDOW_HEROES_SLOTS);
+			}
+		}, Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size));
 }
 
 void CKingdHeroList::updateGarrisons()
@@ -730,30 +720,6 @@ bool CKingdHeroList::holdsGarrison(const CArmedInstance * army)
 	return false;
 }
 
-void CKingdHeroList::deactivate()
-{
-	CCS->curh->dragAndDropCursor(nullptr);
-	CIntObject::deactivate();
-}
-
-std::shared_ptr<CIntObject> CKingdHeroList::createHeroItem(size_t index)
-{
-	ui32 picCount = 4; // OVSLOT contains 4 images
-
-	auto heroesList = LOCPLINT->localState->getWanderingHeroes();
-
-	if(index < heroesList.size())
-	{
-		auto hero = std::make_shared<CHeroItem>(heroesList[index]);
-		addSetAndCallbacks(hero->heroArts);
-		return hero;
-	}
-	else
-	{
-		return std::make_shared<CAnimImage>(AnimationPath::builtin("OVSLOT"), (index-2) % picCount );
-	}
-}
-
 CKingdTownList::CKingdTownList(size_t maxSize)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);

+ 5 - 11
client/windows/CKingdomInterface.h

@@ -9,8 +9,7 @@
  */
 #pragma once
 
-#include "../widgets/CWindowWithArtifacts.h"
-#include "CWindowObject.h"
+#include "CWindowWithArtifacts.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 class CGObjectInstance;
@@ -200,7 +199,7 @@ public:
 };
 
 /// Class which holds all parts of kingdom overview window
-class CKingdomInterface : public CWindowObject, public IGarrisonHolder, public CArtifactHolder, public ITownHolder
+class CKingdomInterface : public IGarrisonHolder, public CWindowWithArtifacts, public ITownHolder
 {
 private:
 	struct OwnedObjectInfo
@@ -254,10 +253,6 @@ public:
 	void heroRemoved();
 	void updateGarrisons() override;
 	bool holdsGarrison(const CArmedInstance * army) override;
-	void artifactRemoved(const ArtifactLocation &artLoc) override;
-	void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw) override;
-	void artifactDisassembled(const ArtifactLocation &artLoc) override;
-	void artifactAssembled(const ArtifactLocation &artLoc) override;
 	void buildChanged() override;
 };
 
@@ -330,7 +325,7 @@ public:
 };
 
 /// Tab with all hero-specific data
-class CKingdHeroList : public CIntObject, public IGarrisonHolder, public CWindowWithArtifacts
+class CKingdHeroList : public CIntObject, public IGarrisonHolder
 {
 private:
 	std::shared_ptr<CListBox> heroes;
@@ -338,13 +333,12 @@ private:
 	std::shared_ptr<CLabel> heroLabel;
 	std::shared_ptr<CLabel> skillsLabel;
 
-	std::shared_ptr<CIntObject> createHeroItem(size_t index);
 public:
-	CKingdHeroList(size_t maxSize);
+	using CreateHeroItemFunctor = std::function<void(const CWindowWithArtifacts::CArtifactsOfHeroPtr)>;
 
+	CKingdHeroList(size_t maxSize, const CreateHeroItemFunctor & onCreateHeroItemCallback);
 	void updateGarrisons() override;
 	bool holdsGarrison(const CArmedInstance * army) override;
-	void deactivate() override;
 };
 
 /// Tab with all town-specific data

+ 1 - 8
client/windows/CMarketWindow.cpp

@@ -12,7 +12,6 @@
 #include "CMarketWindow.h"
 
 #include "../gui/CGuiHandler.h"
-#include "../gui/CursorHandler.h"
 #include "../gui/Shortcut.h"
 
 #include "../widgets/Buttons.h"
@@ -34,7 +33,7 @@
 #include "../../lib/mapObjects/CGHeroInstance.h"
 
 CMarketWindow::CMarketWindow(const IMarket * market, const CGHeroInstance * hero, const std::function<void()> & onWindowClosed, EMarketMode mode)
-	: CStatusbarWindow(PLAYER_COLORED)
+	: CWindowObject(PLAYER_COLORED)
 	, windowClosedCallback(onWindowClosed)
 {
 	assert(mode == EMarketMode::RESOURCE_RESOURCE || mode == EMarketMode::RESOURCE_PLAYER || mode == EMarketMode::CREATURE_RESOURCE ||
@@ -262,9 +261,3 @@ void CMarketWindow::createAltarCreatures(const IMarket * market, const CGHeroIns
 	initWidgetInternals(EMarketMode::CREATURE_EXP, CGI->generaltexth->zelp[568]);
 	updateHero();
 }
-
-void CMarketWindow::deactivate()
-{
-	CCS->curh->dragAndDropCursor(nullptr);
-	CIntObject::deactivate();
-}

+ 1 - 3
client/windows/CMarketWindow.h

@@ -10,8 +10,7 @@
 #pragma once
 
 #include "../widgets/markets/CMarketBase.h"
-#include "../widgets/CWindowWithArtifacts.h"
-#include "CWindowObject.h"
+#include "CWindowWithArtifacts.h"
 
 class CMarketWindow : public CStatusbarWindow, public CWindowWithArtifacts, public IGarrisonHolder
 {
@@ -25,7 +24,6 @@ public:
 	bool holdsGarrison(const CArmedInstance * army) override;
 	void artifactRemoved(const ArtifactLocation & artLoc) override;
 	void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) override;
-	void deactivate() override;
 
 private:
 	void createChangeModeButtons(EMarketMode currentMode, const IMarket * market, const CGHeroInstance * hero);

+ 0 - 8
client/windows/CWindowObject.cpp

@@ -239,11 +239,3 @@ bool CWindowObject::isPopupWindow() const
 {
 	return options & RCLICK_POPUP;
 }
-
-CStatusbarWindow::CStatusbarWindow(int options, const ImagePath & imageName, Point centerAt) : CWindowObject(options, imageName, centerAt)
-{
-}
-
-CStatusbarWindow::CStatusbarWindow(int options, const ImagePath & imageName) : CWindowObject(options, imageName)
-{
-}

+ 2 - 5
client/windows/CWindowObject.h

@@ -47,17 +47,14 @@ public:
 	 * centerAt - position of window center. Default - center of the screen
 	*/
 	CWindowObject(int options, const ImagePath & imageName, Point centerAt);
-	CWindowObject(int options, const ImagePath & imageName = {});
+	CWindowObject(int options = 0, const ImagePath & imageName = {});
 	~CWindowObject();
 
 	void showAll(Canvas & to) override;
 };
 
-class CStatusbarWindow : public CWindowObject
+class CStatusbarWindow : virtual public CWindowObject
 {
-public:
-	CStatusbarWindow(int options, const ImagePath & imageName, Point centerAt);
-	CStatusbarWindow(int options, const ImagePath & imageName = {});
 protected:
 	std::shared_ptr<CGStatusBar> statusbar;
 };

+ 44 - 37
client/widgets/CWindowWithArtifacts.cpp → client/windows/CWindowWithArtifacts.cpp

@@ -18,7 +18,7 @@
 #include "../render/CAnimation.h"
 #include "../render/IImage.h"
 
-#include "CComponent.h"
+#include "../widgets/CComponent.h"
 
 #include "../windows/CHeroWindow.h"
 #include "../windows/CSpellWindow.h"
@@ -41,24 +41,24 @@ CWindowWithArtifacts::CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr
 		this->artSets.insert(this->artSets.end(), artSets->begin(), artSets->end());
 }
 
-void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet)
+void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr newArtSet)
 {
-	artSets.emplace_back(artSet);
+	artSets.emplace_back(newArtSet);
 }
 
-void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr artSet)
+void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr newArtSet)
 {
-	addSet(artSet);
+	addSet(newArtSet);
 	std::visit([this](auto artSetWeak)
 		{
 			auto artSet = artSetWeak.lock();
 			artSet->clickPressedCallback = std::bind(&CWindowWithArtifacts::clickPressedArtPlaceHero, this, _1, _2, _3);
 			artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::showPopupArtPlaceHero, this, _1, _2, _3);
 			artSet->gestureCallback = std::bind(&CWindowWithArtifacts::gestureArtPlaceHero, this, _1, _2, _3);
-		}, artSet);
+		}, newArtSet);
 }
 
-void CWindowWithArtifacts::addCloseCallback(CloseCallback callback)
+void CWindowWithArtifacts::addCloseCallback(const CloseCallback & callback)
 {
 	closeCallback = callback;
 }
@@ -81,10 +81,10 @@ const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact()
 		return nullptr;
 }
 
-void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
+void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
 {
-	const auto artSet = findAOHbyRef(artsInst);
-	assert(artSet.has_value());
+	const auto currentArtSet = findAOHbyRef(artsInst);
+	assert(currentArtSet.has_value());
 
 	if(artPlace.isLocked())
 		return;
@@ -222,11 +222,8 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsI
 
 				if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroBackpack>>)
 				{
-					if(!isTransferAllowed && artPlace.getArt())
-					{
-						if(closeCallback)
-							closeCallback();
-					}
+					if(!isTransferAllowed && artPlace.getArt() && closeCallback)
+						closeCallback();
 				}
 				else
 				{
@@ -259,13 +256,13 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsI
 				if(closeCallback)
 					closeCallback();
 			}
-		}, artSet.value());
+		}, currentArtSet.value());
 }
 
-void CWindowWithArtifacts::showPopupArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
+void CWindowWithArtifacts::showPopupArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
 {
-	const auto artSetWeak = findAOHbyRef(artsInst);
-	assert(artSetWeak.has_value());
+	const auto currentArtSet = findAOHbyRef(artsInst);
+	assert(currentArtSet.has_value());
 
 	if(artPlace.isLocked())
 		return;
@@ -304,13 +301,13 @@ void CWindowWithArtifacts::showPopupArtPlaceHero(CArtifactsOfHeroBase & artsInst
 				if(artPlace.getArt() && artPlace.text.size())
 					artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
 			}
-		}, artSetWeak.value());
+		}, currentArtSet.value());
 }
 
-void CWindowWithArtifacts::gestureArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
+void CWindowWithArtifacts::gestureArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
 {
-	const auto artSetWeak = findAOHbyRef(artsInst);
-	assert(artSetWeak.has_value());
+	const auto currentArtSet = findAOHbyRef(artsInst);
+	assert(currentArtSet.has_value());
 	if(artPlace.isLocked())
 		return;
 
@@ -330,12 +327,25 @@ void CWindowWithArtifacts::gestureArtPlaceHero(CArtifactsOfHeroBase & artsInst,
 				backpackWindow->moveTo(cursorPosition - Point(1, 1));
 				backpackWindow->fitToScreen(15);
 			}
-		}, artSetWeak.value());
+		}, currentArtSet.value());
+}
+
+void CWindowWithArtifacts::activate()
+{
+	if(const auto art = getPickedArtifact())
+		setCursorAnimation(*art);
+	CWindowObject::activate();
+}
+
+void CWindowWithArtifacts::deactivate()
+{
+	CCS->curh->dragAndDropCursor(nullptr);
+	CWindowObject::deactivate();
 }
 
 void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
 {
-	updateSlots();
+	update();
 }
 
 void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw)
@@ -394,16 +404,16 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
 
 void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation & artLoc)
 {
-	updateSlots();
+	update();
 }
 
 void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation & artLoc)
 {
 	markPossibleSlots();
-	updateSlots();
+	update();
 }
 
-void CWindowWithArtifacts::updateSlots()
+void CWindowWithArtifacts::update() const
 {
 	auto updateSlotBody = [](auto artSetWeak) -> void
 	{
@@ -455,7 +465,7 @@ std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> CWind
 		return std::make_tuple(pickedCnt.begin()->first, artInst);
 }
 
-std::optional<CWindowWithArtifacts::CArtifactsOfHeroPtr> CWindowWithArtifacts::findAOHbyRef(CArtifactsOfHeroBase & artsInst)
+std::optional<CWindowWithArtifacts::CArtifactsOfHeroPtr> CWindowWithArtifacts::findAOHbyRef(const CArtifactsOfHeroBase & artsInst)
 {
 	std::optional<CArtifactsOfHeroPtr> res;
 
@@ -497,7 +507,7 @@ void CWindowWithArtifacts::markPossibleSlots()
 	}
 }
 
-bool CWindowWithArtifacts::checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade)
+bool CWindowWithArtifacts::checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade) const
 {
 	const auto artId = artInst.getTypeId();
 	
@@ -513,14 +523,11 @@ bool CWindowWithArtifacts::checkSpecialArts(const CArtifactInstance & artInst, c
 			std::vector<std::shared_ptr<CComponent>>(1, std::make_shared<CComponent>(ComponentType::ARTIFACT, ArtifactID(ArtifactID::CATAPULT))));
 		return false;
 	}
-	if(isTrade)
+	if(isTrade && !artInst.artType->isTradable())
 	{
-		if(!artInst.artType->isTradable())
-		{
-			LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[21],
-				std::vector<std::shared_ptr<CComponent>>(1, std::make_shared<CComponent>(ComponentType::ARTIFACT, artId)));
-			return false;
-		}
+		LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[21],
+			std::vector<std::shared_ptr<CComponent>>(1, std::make_shared<CComponent>(ComponentType::ARTIFACT, artId)));
+		return false;
 	}
 	return true;
 }

+ 58 - 0
client/windows/CWindowWithArtifacts.h

@@ -0,0 +1,58 @@
+/*
+ * CWindowWithArtifacts.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../widgets/CArtifactsOfHeroMain.h"
+#include "../widgets/CArtifactsOfHeroKingdom.h"
+#include "../widgets/CArtifactsOfHeroAltar.h"
+#include "../widgets/CArtifactsOfHeroMarket.h"
+#include "../widgets/CArtifactsOfHeroBackpack.h"
+#include "CWindowObject.h"
+
+class CWindowWithArtifacts : virtual public CWindowObject
+{
+public:
+	using CArtifactsOfHeroPtr = std::variant<
+		std::weak_ptr<CArtifactsOfHeroMarket>,
+		std::weak_ptr<CArtifactsOfHeroAltar>,
+		std::weak_ptr<CArtifactsOfHeroKingdom>,
+		std::weak_ptr<CArtifactsOfHeroMain>,
+		std::weak_ptr<CArtifactsOfHeroBackpack>,
+		std::weak_ptr<CArtifactsOfHeroQuickBackpack>>;
+	using CloseCallback = std::function<void()>;
+
+	std::vector<CArtifactsOfHeroPtr> artSets;
+	CloseCallback closeCallback;
+
+	explicit CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets = nullptr);
+	void addSet(CArtifactsOfHeroPtr newArtSet);
+	void addSetAndCallbacks(CArtifactsOfHeroPtr newArtSet);
+	void addCloseCallback(const CloseCallback & callback);
+	const CGHeroInstance * getHeroPickedArtifact();
+	const CArtifactInstance * getPickedArtifact();
+	void clickPressedArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
+	void showPopupArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
+	void gestureArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
+	void activate() override;
+	void deactivate() override;
+
+	virtual void artifactRemoved(const ArtifactLocation & artLoc);
+	virtual void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw);
+	virtual void artifactDisassembled(const ArtifactLocation & artLoc);
+	virtual void artifactAssembled(const ArtifactLocation & artLoc);
+
+protected:
+	void update() const;
+	std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> getState();
+	std::optional<CArtifactsOfHeroPtr> findAOHbyRef(const CArtifactsOfHeroBase & artsInst);
+	void markPossibleSlots();
+	bool checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade) const;
+	void setCursorAnimation(const CArtifactInstance & artInst);
+};

+ 9 - 15
client/windows/GUIClasses.cpp

@@ -204,7 +204,7 @@ void CRecruitmentWindow::showAll(Canvas & to)
 }
 
 CRecruitmentWindow::CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, const std::function<void()> & onClose, int y_offset):
-	CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPRCRT")),
+	CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPRCRT")),
 	onRecruit(Recruit),
 	onClose(onClose),
 	level(Level),
@@ -445,7 +445,7 @@ CLevelWindow::~CLevelWindow()
 }
 
 CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPTAVERN")),
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPTAVERN")),
 	onWindowClosed(onWindowClosed),
 	tavernObj(TavernObj),
 	heroToInvite(nullptr)
@@ -692,7 +692,7 @@ static bool isQuickExchangeLayoutAvailable()
 }
 
 CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID)
-	: CStatusbarWindow(PLAYER_COLORED | BORDERED, ImagePath::builtin(isQuickExchangeLayoutAvailable() ? QUICK_EXCHANGE_BG : "TRADE2")),
+	: CWindowObject(PLAYER_COLORED | BORDERED, ImagePath::builtin(isQuickExchangeLayoutAvailable() ? QUICK_EXCHANGE_BG : "TRADE2")),
 	controller(hero1, hero2),
 	moveStackLeftButtons(),
 	moveStackRightButtons()
@@ -934,12 +934,6 @@ bool CExchangeWindow::holdsGarrison(const CArmedInstance * army)
 	return garr->upperArmy() == army || garr->lowerArmy() == army;
 }
 
-void CExchangeWindow::deactivate()
-{
-	CCS->curh->dragAndDropCursor(nullptr);
-	CIntObject::deactivate();
-}
-
 void CExchangeWindow::questlog(int whichHero)
 {
 	CCS->curh->dragAndDropCursor(nullptr);
@@ -975,7 +969,7 @@ void CExchangeWindow::updateWidgets()
 }
 
 CShipyardWindow::CShipyardWindow(const TResources & cost, int state, BoatId boatType, const std::function<void()> & onBuy)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPSHIP"))
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPSHIP"))
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
@@ -1093,7 +1087,7 @@ bool CTransformerWindow::holdsGarrison(const CArmedInstance * army)
 }
 
 CTransformerWindow::CTransformerWindow(const IMarket * _market, const CGHeroInstance * _hero, const std::function<void()> & onWindowClosed)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("SKTRNBK")),
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("SKTRNBK")),
 	hero(_hero),
 	onWindowClosed(onWindowClosed),
 	market(_market)
@@ -1192,7 +1186,7 @@ void CUniversityWindow::CItem::showAll(Canvas & to)
 }
 
 CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market, const std::function<void()> & onWindowClosed)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("UNIVERS1")),
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("UNIVERS1")),
 	hero(_hero),
 	onWindowClosed(onWindowClosed),
 	market(_market)
@@ -1254,7 +1248,7 @@ void CUniversityWindow::makeDeal(SecondarySkill skill)
 
 
 CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, SecondarySkill SKILL, bool available)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("UNIVERS2.PCX")),
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("UNIVERS2.PCX")),
 	owner(owner_)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@@ -1341,7 +1335,7 @@ bool CGarrisonWindow::holdsGarrison(const CArmedInstance * army)
 }
 
 CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectInstance * object)
-	: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("APHLFTBK")),
+	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("APHLFTBK")),
 	fort(object),
 	hero(visitor)
 {
@@ -1545,7 +1539,7 @@ int CHillFortWindow::getState(SlotID slot)
 }
 
 CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner):
-	CStatusbarWindow(PLAYER_COLORED | BORDERED, ImagePath::builtin("TpRank")),
+	CWindowObject(PLAYER_COLORED | BORDERED, ImagePath::builtin("TpRank")),
 	owner(_owner)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);

+ 1 - 2
client/windows/GUIClasses.h

@@ -11,8 +11,8 @@
 
 #include "../lib/ResourceSet.h"
 #include "../widgets/CExchangeController.h"
-#include "../widgets/CWindowWithArtifacts.h"
 #include "../widgets/Images.h"
+#include "CWindowWithArtifacts.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -325,7 +325,6 @@ public:
 
 	void updateGarrisons() override;
 	bool holdsGarrison(const CArmedInstance * army) override;
-	void deactivate() override;
 
 	void questlog(int whichHero); //questlog button callback; whichHero: 0 - left, 1 - right
 

+ 1 - 0
lib/constants/NumericConstants.h

@@ -53,6 +53,7 @@ namespace GameConstants
 	constexpr int64_t PLAYER_RESOURCES_CAP = 1000 * 1000 * 1000;
 	constexpr int ALTAR_ARTIFACTS_SLOTS = 22;
 	constexpr int TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD = 144*144*2; //map tiles count threshold for 2 dimension door casts with tournament rules
+	constexpr int KINGDOM_WINDOW_HEROES_SLOTS = 4;
 }
 
 VCMI_LIB_NAMESPACE_END