2
0
Эх сурвалжийг харах

Gui cleanup3 - UI refactoring to use smart pointers (#440)

* Changed most gui classes to use shared pointers
* Store and use IImage as shared_ptr
* CSpellWindow redesign
* AdventureMapClasses cleanup
* CLabel: store background as smart pointer
* Store CObjectList items as smart pointers
* Removed destroy function of list item
* Store toggle buttons as smart pointers
* Use CComponent as smart pointer
* Attempt to fix artifact merchant drawing
Alexander Shishkin 7 жил өмнө
parent
commit
5c09f751b3
73 өөрчлөгдсөн 4033 нэмэгдсэн , 3871 устгасан
  1. 1 1
      AI/VCAI/VCAI.cpp
  2. 1 1
      AI/VCAI/VCAI.h
  3. 1 1
      client/CMT.cpp
  4. 16 22
      client/CMessage.cpp
  5. 38 86
      client/CPlayerInterface.cpp
  6. 4 5
      client/CPlayerInterface.h
  7. 18 21
      client/CreatureCostBox.cpp
  8. 10 3
      client/CreatureCostBox.h
  9. 38 1
      client/Graphics.cpp
  10. 1 6
      client/NetPacksClient.cpp
  11. 7 8
      client/battle/CBattleInterface.cpp
  12. 2 2
      client/battle/CBattleInterface.h
  13. 176 153
      client/battle/CBattleInterfaceClasses.cpp
  14. 30 19
      client/battle/CBattleInterfaceClasses.h
  15. 1 1
      client/battle/CCreatureAnimation.cpp
  16. 17 45
      client/gui/CAnimation.cpp
  17. 5 11
      client/gui/CAnimation.h
  18. 2 3
      client/gui/CGuiHandler.h
  19. 23 20
      client/gui/CIntObject.cpp
  20. 1 1
      client/gui/CIntObject.h
  21. 1 1
      client/lobby/CBonusSelection.cpp
  22. 1 1
      client/lobby/CLobbyScreen.cpp
  23. 1 1
      client/lobby/CSavingScreen.cpp
  24. 1 1
      client/lobby/CSelectionBase.cpp
  25. 2 2
      client/lobby/OptionsTab.cpp
  26. 3 4
      client/lobby/RandomMapTab.cpp
  27. 12 12
      client/mainmenu/CMainMenu.cpp
  28. 1 1
      client/mainmenu/CMainMenu.h
  29. 21 22
      client/mapHandler.cpp
  30. 21 21
      client/mapHandler.h
  31. 234 248
      client/widgets/AdventureMapClasses.cpp
  32. 101 59
      client/widgets/AdventureMapClasses.h
  33. 47 51
      client/widgets/Buttons.cpp
  34. 17 11
      client/widgets/Buttons.h
  35. 104 67
      client/widgets/CArtifactHolder.cpp
  36. 37 27
      client/widgets/CArtifactHolder.h
  37. 25 39
      client/widgets/CComponent.cpp
  38. 12 10
      client/widgets/CComponent.h
  39. 59 102
      client/widgets/CGarrisonInt.cpp
  40. 25 44
      client/widgets/CGarrisonInt.h
  41. 5 14
      client/widgets/Images.cpp
  42. 0 1
      client/widgets/Images.h
  43. 88 79
      client/widgets/MiscWidgets.cpp
  44. 33 18
      client/widgets/MiscWidgets.h
  45. 46 51
      client/widgets/ObjectLists.cpp
  46. 13 15
      client/widgets/ObjectLists.h
  47. 41 41
      client/widgets/TextControls.cpp
  48. 10 11
      client/widgets/TextControls.h
  49. 52 49
      client/windows/CAdvmapInterface.cpp
  50. 27 23
      client/windows/CAdvmapInterface.h
  51. 373 368
      client/windows/CCastleInterface.cpp
  52. 113 81
      client/windows/CCastleInterface.h
  53. 477 551
      client/windows/CCreatureWindow.cpp
  54. 112 36
      client/windows/CCreatureWindow.h
  55. 128 135
      client/windows/CHeroWindow.cpp
  56. 57 33
      client/windows/CHeroWindow.h
  57. 217 233
      client/windows/CKingdomInterface.cpp
  58. 73 68
      client/windows/CKingdomInterface.h
  59. 41 43
      client/windows/CQuestLog.cpp
  60. 13 16
      client/windows/CQuestLog.h
  61. 48 62
      client/windows/CSpellWindow.cpp
  62. 16 14
      client/windows/CSpellWindow.h
  63. 163 188
      client/windows/CTradeWindow.cpp
  64. 49 35
      client/windows/CTradeWindow.h
  65. 39 34
      client/windows/CWindowObject.cpp
  66. 6 6
      client/windows/CWindowObject.h
  67. 0 1
      client/windows/CreaturePurchaseCard.cpp
  68. 360 313
      client/windows/GUIClasses.cpp
  69. 258 136
      client/windows/GUIClasses.h
  70. 40 61
      client/windows/InfoWindows.cpp
  71. 17 19
      client/windows/InfoWindows.h
  72. 0 1
      lib/CGameInterface.h
  73. 1 1
      lib/IGameEventsReceiver.h

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -447,7 +447,7 @@ void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID)
 	NET_EVENT_HANDLER;
 }
 
-void VCAI::showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID)
+void VCAI::showInfoDialog(const std::string &text, const std::vector<Component> &components, int soundID)
 {
 	LOG_TRACE_PARAMS(logAi, "soundID '%i'", soundID);
 	NET_EVENT_HANDLER;

+ 1 - 1
AI/VCAI/VCAI.h

@@ -231,7 +231,7 @@ public:
 	virtual void playerBonusChanged(const Bonus &bonus, bool gain) override;
 	virtual void heroCreated(const CGHeroInstance*) override;
 	virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
-	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
+	virtual void showInfoDialog(const std::string &text, const std::vector<Component> &components, int soundID) override;
 	virtual void requestRealized(PackageApplied *pa) override;
 	virtual void receivedResource() override;
 	virtual void objectRemoved(const CGObjectInstance *obj) override;

+ 1 - 1
client/CMT.cpp

@@ -1341,7 +1341,7 @@ void handleQuit(bool ask)
 	if(CSH->client && LOCPLINT && ask)
 	{
 		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
-		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, 0);
+		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr);
 	}
 	else
 	{

+ 16 - 22
client/CMessage.cpp

@@ -39,30 +39,30 @@ template <typename T, typename U> std::pair<T,U> max(const std::pair<T,U> &x, co
 class ComponentResolved : public CIntObject
 {
 public:
-	CComponent *comp;
+	std::shared_ptr<CComponent> comp;
 
 	//blit component with image centered at this position
 	void showAll(SDL_Surface * to) override;
 
 	//ComponentResolved();
-	ComponentResolved(CComponent *Comp);
+	ComponentResolved(std::shared_ptr<CComponent> Comp);
 	~ComponentResolved();
 };
 // Full set of components for blitting on dialog box
 struct ComponentsToBlit
 {
-	std::vector< std::vector<ComponentResolved*> > comps;
+	std::vector< std::vector<std::shared_ptr<ComponentResolved>>> comps;
 	int w, h;
 
 	void blitCompsOnSur(bool blitOr, int inter, int &curh, SDL_Surface *ret);
-	ComponentsToBlit(std::vector<CComponent*> & SComps, int maxw, bool blitOr);
+	ComponentsToBlit(std::vector<std::shared_ptr<CComponent>> & SComps, int maxw, bool blitOr);
 	~ComponentsToBlit();
 };
 
 namespace
 {
 	std::array<std::unique_ptr<CAnimation>, PlayerColor::PLAYER_LIMIT_I> dialogBorders;
-	std::array<std::vector<const IImage*>, PlayerColor::PLAYER_LIMIT_I> piecesOfBox;
+	std::array<std::vector<std::shared_ptr<IImage>>, PlayerColor::PLAYER_LIMIT_I> piecesOfBox;
 
 	SDL_Surface * background = nullptr;//todo: should be CFilledTexture
 }
@@ -298,7 +298,7 @@ void CMessage::drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int
 {
 	if(playerColor.isSpectator())
 		playerColor = PlayerColor(1);
-	std::vector<const IImage*> &box = piecesOfBox.at(playerColor.getNum());
+	auto & box = piecesOfBox.at(playerColor.getNum());
 
 	// Note: this code assumes that the corner dimensions are all the same.
 
@@ -358,7 +358,7 @@ void CMessage::drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int
 	box[3]->draw(ret, &dstR, nullptr);
 }
 
-ComponentResolved::ComponentResolved( CComponent *Comp ):
+ComponentResolved::ComponentResolved(std::shared_ptr<CComponent> Comp):
 	comp(Comp)
 {
 	//Temporary assign ownership on comp
@@ -367,10 +367,10 @@ ComponentResolved::ComponentResolved( CComponent *Comp ):
 	if (comp->parent)
 	{
 		comp->parent->addChild(this);
-		comp->parent->removeChild(comp);
+		comp->parent->removeChild(comp.get());
 	}
 
-	addChild(comp);
+	addChild(comp.get());
 	defActions = 255 - DISPOSE;
 	pos.x = pos.y = 0;
 
@@ -382,8 +382,8 @@ ComponentResolved::~ComponentResolved()
 {
 	if (parent)
 	{
-		removeChild(comp);
-		parent->addChild(comp);
+		removeChild(comp.get());
+		parent->addChild(comp.get());
 	}
 }
 
@@ -393,15 +393,9 @@ void ComponentResolved::showAll(SDL_Surface *to)
 	comp->showAll(to);
 }
 
-ComponentsToBlit::~ComponentsToBlit()
-{
-	for(auto & elem : comps)
-		for(size_t j = 0; j < elem.size(); j++)
-			delete elem[j];
-
-}
+ComponentsToBlit::~ComponentsToBlit() = default;
 
-ComponentsToBlit::ComponentsToBlit(std::vector<CComponent*> & SComps, int maxw, bool blitOr)
+ComponentsToBlit::ComponentsToBlit(std::vector<std::shared_ptr<CComponent>> & SComps, int maxw, bool blitOr)
 {
 	int orWidth = graphics->fonts[FONT_MEDIUM]->getStringWidth(CGI->generaltexth->allTexts[4]);
 
@@ -415,7 +409,7 @@ ComponentsToBlit::ComponentsToBlit(std::vector<CComponent*> & SComps, int maxw,
 
 	for(auto & SComp : SComps)
 	{
-		auto  cur = new ComponentResolved(SComp);
+		auto cur = std::make_shared<ComponentResolved>(SComp);
 
 		int toadd = (cur->pos.w + BETWEEN_COMPS + (blitOr ? orWidth : 0));
 		if (curw + toadd > maxw)
@@ -453,7 +447,7 @@ void ComponentsToBlit::blitCompsOnSur( bool blitOr, int inter, int &curh, SDL_Su
 		int totalw=0, maxHeight=0;
 		for(size_t j=0;j<elem.size();j++)//find max height & total width in this row
 		{
-			ComponentResolved *cur = elem[j];
+			auto cur = elem[j];
 			totalw += cur->pos.w;
 			vstd::amax(maxHeight, cur->pos.h);
 		}
@@ -469,7 +463,7 @@ void ComponentsToBlit::blitCompsOnSur( bool blitOr, int inter, int &curh, SDL_Su
 
 		for(size_t j=0;j<elem.size();j++)
 		{
-			ComponentResolved *cur = elem[j];
+			auto cur = elem[j];
 			cur->moveTo(Point(curw, curh));
 
 			//blit component

+ 38 - 86
client/CPlayerInterface.cpp

@@ -196,8 +196,8 @@ void CPlayerInterface::yourTurn()
 			makingTurn = true;
 			std::string msg = CGI->generaltexth->allTexts[13];
 			boost::replace_first(msg, "%s", cb->getStartInfo()->playerInfos.find(playerID)->second.name);
-			std::vector<CComponent*> cmp;
-			cmp.push_back(new CComponent(CComponent::flag, playerID.getNum(), 0));
+			std::vector<std::shared_ptr<CComponent>> cmp;
+			cmp.push_back(std::make_shared<CComponent>(CComponent::flag, playerID.getNum(), 0));
 			showInfoDialog(msg, cmp);
 		}
 		else
@@ -363,9 +363,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
 			GH.mainFPSmng->framerateDelay(); //for animation purposes
 			logGlobal->trace("after [un]locks in %s", __FUNCTION__);
 		}
-		//CSDL_Ext::update(screen);
 
-	} //for (int i=1; i<32; i+=4)
+	}
 	//main moving done
 
 	//finishing move
@@ -905,8 +904,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br)
 
 		if (!battleInt)
 		{
-			SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
-			auto   resWindow = new CBattleResultWindow(*br, temp_rect, *this);
+			auto resWindow = new CBattleResultWindow(*br, *this);
 			GH.pushInt(resWindow);
 			// #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.
@@ -1100,29 +1098,29 @@ void CPlayerInterface::showComp(const Component &comp, std::string message)
 	adventureInt->infoBar.showComponent(comp, message);
 }
 
-void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID)
+void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component> & components, int soundID)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	if (settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed())
 	{
 		return;
 	}
-	std::vector<CComponent*> intComps;
+	std::vector<std::shared_ptr<CComponent>> intComps;
 	for (auto & component : components)
-		intComps.push_back(new CComponent(*component));
+		intComps.push_back(std::make_shared<CComponent>(component));
 	showInfoDialog(text,intComps,soundID);
 
 }
 
-void CPlayerInterface::showInfoDialog(const std::string &text, CComponent * component)
+void CPlayerInterface::showInfoDialog(const std::string & text, std::shared_ptr<CComponent> component)
 {
-	std::vector<CComponent*> intComps;
+	std::vector<std::shared_ptr<CComponent>> intComps;
 	intComps.push_back(component);
 
-	showInfoDialog(text, intComps, soundBase::sound_todo, true);
+	showInfoDialog(text, intComps, soundBase::sound_todo);
 }
 
-void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<CComponent*> & components, int soundID, bool delComps)
+void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components, int soundID)
 {
 	LOG_TRACE_PARAMS(logGlobal, "player=%s, text=%s, is LOCPLINT=%d", playerID % text % (this==LOCPLINT));
 	waitWhileDialog();
@@ -1131,8 +1129,8 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 	{
 		return;
 	}
-	CInfoWindow *temp = CInfoWindow::create(text, playerID, &components);
-	temp->setDelComps(delComps);
+	CInfoWindow *temp = CInfoWindow::create(text, playerID, components);
+
 	if (makingTurn && GH.listInt.size() && LOCPLINT == this)
 	{
 		CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
@@ -1149,46 +1147,37 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 void CPlayerInterface::showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
-	std::vector<Component*> comps;
-	for (auto & elem : components)
-	{
-		comps.push_back(&elem);
-	}
+
 	std::string str;
 	text.toString(str);
 
-	showInfoDialog(str,comps, 0);
+	showInfoDialog(str, components, 0);
 	waitWhileDialog();
 }
 
-void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps, const std::vector<CComponent*> & components)
+void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 
 	stopMovement();
 	LOCPLINT->showingDialog->setn(true);
-	CInfoWindow::showYesNoDialog(text, &components, onYes, onNo, DelComps, playerID);
+	CInfoWindow::showYesNoDialog(text, components, onYes, onNo, playerID);
 }
 
 void CPlayerInterface::showOkDialog(std::vector<Component> & components, const MetaString & text, const std::function<void()> & onOk)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 
-	std::vector<Component*> comps;
-	for (auto & elem : components)
-	{
-		comps.push_back(&elem);
-	}
 	std::string str;
 	text.toString(str);
 
 	stopMovement();
 	showingDialog->setn(true);
 
-	std::vector<CComponent*> intComps;
-	for (auto & component : comps)
-		intComps.push_back(new CComponent(*component));
-	CInfoWindow::showOkDialog(str, &intComps, onOk, true, playerID);
+	std::vector<std::shared_ptr<CComponent>> intComps;
+	for (auto & component : components)
+		intComps.push_back(std::make_shared<CComponent>(component));
+	CInfoWindow::showOkDialog(str, intComps, onOk, playerID);
 }
 
 void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel )
@@ -1201,17 +1190,17 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
 
 	if (!selection && cancel) //simple yes/no dialog
 	{
-		std::vector<CComponent*> intComps;
+		std::vector<std::shared_ptr<CComponent>> intComps;
 		for (auto & component : components)
-			intComps.push_back(new CComponent(component)); //will be deleted by close in window
+			intComps.push_back(std::make_shared<CComponent>(component)); //will be deleted by close in window
 
-		showYesNoDialog(text, [=](){ cb->selectionMade(1, askID); }, [=](){ cb->selectionMade(0, askID); }, true, intComps);
+		showYesNoDialog(text, [=](){ cb->selectionMade(1, askID); }, [=](){ cb->selectionMade(0, askID); }, intComps);
 	}
 	else if (selection)
 	{
-		std::vector<CSelectableComponent*> intComps;
+		std::vector<std::shared_ptr<CSelectableComponent>> intComps;
 		for (auto & component : components)
-			intComps.push_back(new CSelectableComponent(component)); //will be deleted by CSelWindow::close
+			intComps.push_back(std::make_shared<CSelectableComponent>(component)); //will be deleted by CSelWindow::close
 
 		std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
 		pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
@@ -1269,8 +1258,8 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component
 
 	CComponent * localIconC = new CComponent(icon);
 
-	CIntObject * localIcon = localIconC->image;
-	localIconC->removeChild(localIcon, false);
+	std::shared_ptr<CIntObject> localIcon = localIconC->image;
+	localIconC->removeChild(localIcon.get(), false);
 	delete localIconC;
 
 	CObjectListWindow * wnd = new CObjectListWindow(tempList, localIcon, localTitle, localDescription, selectCallback);
@@ -1302,46 +1291,6 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	GH.pushInt(new CHeroWindow(hero));
 }
-/*
-void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
-{
-	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	if (adventureInt->heroWindow->curHero && adventureInt->heroWindow->curHero->id == hero->id) //hero window is opened
-	{
-		adventureInt->heroWindow->deactivate();
-		adventureInt->heroWindow->setHero(hero);
-		adventureInt->heroWindow->activate();
-	}
-	else if (CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt())) //exchange window is open
-	{
-		cew->deactivate();
-		for (int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
-		{
-			if (cew->heroInst[g]->id == hero->id)
-			{
-				cew->heroInst[g] = hero;
-				cew->artifs[g]->updateState = true;
-				cew->artifs[g]->setHero(hero);
-				cew->artifs[g]->updateState = false;
-			}
-		}
-		cew->prepareBackground();
-		cew->activate();
-	}
-	else if (CTradeWindow *caw = dynamic_cast<CTradeWindow*>(GH.topInt()))
-	{
-		if (caw->arts)
-		{
-			caw->deactivate();
-			caw->arts->updateState = true;
-			caw->arts->setHero(hero);
-			caw->arts->updateState = false;
-			caw->activate();
-		}
-	}
-
-	updateInfo(hero);
-}*/
 
 void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
 {
@@ -1504,25 +1453,28 @@ void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembl
 	const CArtifact &artifact = *CGI->arth->artifacts[artifactID];
 	std::string text = artifact.Description();
 	text += "\n\n";
-	std::vector<CComponent*> scs;
+	std::vector<std::shared_ptr<CComponent>> scs;
 
-	if (assemble) {
+	if(assemble)
+	{
 		const CArtifact &assembledArtifact = *CGI->arth->artifacts[assembleTo];
 
 		// You possess all of the components to...
 		text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact.Name());
 
 		// Picture of assembled artifact at bottom.
-		auto   sc = new CComponent(CComponent::artifact, assembledArtifact.id, 0);
+		auto sc = std::make_shared<CComponent>(CComponent::artifact, assembledArtifact.id, 0);
 		//sc->description = assembledArtifact.Description();
 		//sc->subtitle = assembledArtifact.Name();
 		scs.push_back(sc);
-	} else {
+	}
+	else
+	{
 		// Do you wish to disassemble this artifact?
 		text += CGI->generaltexth->allTexts[733];
 	}
 
-	showYesNoDialog(text, onYes, onNo, true, scs);
+	showYesNoDialog(text, onYes, onNo, scs);
 }
 
 void CPlayerInterface::requestRealized( PackageApplied *pa )
@@ -2230,7 +2182,7 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul
 		{
 			std::string str = victoryLossCheckResult.messageToSelf;
 			boost::algorithm::replace_first(str, "%s", CGI->generaltexth->capColors[player.getNum()]);
-			showInfoDialog(str, std::vector<CComponent*>(1, new CComponent(CComponent::flag, player.getNum(), 0)));
+			showInfoDialog(str, std::vector<std::shared_ptr<CComponent>>(1, std::make_shared<CComponent>(CComponent::flag, player.getNum(), 0)));
 		}
 	}
 }
@@ -2661,7 +2613,7 @@ void CPlayerInterface::waitForAllDialogs(bool unlockPim)
 
 void CPlayerInterface::proposeLoadingGame()
 {
-	showYesNoDialog(CGI->generaltexth->allTexts[68], [this](){ sendCustomEvent(EUserEvent::RETURN_TO_MENU_LOAD); }, 0, false);
+	showYesNoDialog(CGI->generaltexth->allTexts[68], [this](){ sendCustomEvent(EUserEvent::RETURN_TO_MENU_LOAD); }, nullptr);
 }
 
 CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()

+ 4 - 5
client/CPlayerInterface.h

@@ -39,7 +39,6 @@ class CSlider;
 struct UpgradeInfo;
 template <typename T> struct CondSh;
 class CInGameConsole;
-class CGarrisonInt;
 class CInGameConsole;
 union SDL_Event;
 class CInfoWindow;
@@ -139,7 +138,7 @@ public:
 	void heroMovePointsChanged(const CGHeroInstance * hero) override;
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
 	void receivedResource() override;
-	void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
+	void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
 	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
 	void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
 	void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
@@ -215,11 +214,11 @@ public:
 	void activateForSpectator(); // TODO: spectator probably need own player interface class
 
 	// show dialogs
-	void showInfoDialog(const std::string &text, CComponent * component);
-	void showInfoDialog(const std::string &text, const std::vector<CComponent*> & components = std::vector<CComponent*>(), int soundID = 0, bool delComps = false);
+	void showInfoDialog(const std::string &text, std::shared_ptr<CComponent> component);
+	void showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>(), int soundID = 0);
 	void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text);
 	void showOkDialog(std::vector<Component> & components, const MetaString & text, const std::function<void()> & onOk);
-	void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps = false, const std::vector<CComponent*> & components = std::vector<CComponent*>()); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
+	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);

+ 18 - 21
client/CreatureCostBox.cpp

@@ -9,9 +9,19 @@
  */
 #include "StdInc.h"
 #include "CreatureCostBox.h"
-#include "windows/CAdvmapInterface.h"
+#include "widgets/Images.h"
+#include "widgets/TextControls.h"
 #include "gui/CGuiHandler.h"
 
+CreatureCostBox::CreatureCostBox(Rect position, std::string titleText)
+{
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
+	type |= REDRAW_PARENT;
+	pos = position + pos;
+
+	title = std::make_shared<CLabel>(pos.w/2, 10, FONT_SMALL, CENTER, Colors::WHITE, titleText);
+}
 
 void CreatureCostBox::set(TResources res)
 {
@@ -19,40 +29,27 @@ void CreatureCostBox::set(TResources res)
 		item.second.first->setText(boost::lexical_cast<std::string>(res[item.first]));
 }
 
-CreatureCostBox::CreatureCostBox(Rect position, std::string title)
-{
-	type |= REDRAW_PARENT;
-	pos = position + pos;
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CLabel(pos.w/2, 10, FONT_SMALL, CENTER, Colors::WHITE, title);
-}
-
 void CreatureCostBox::createItems(TResources res)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-
-	for(auto & curr : resources)
-	{
-		delete curr.second.first;
-		delete curr.second.second;
-	}
 	resources.clear();
 
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
 	TResources::nziterator iter(res);
-	while (iter.valid())
+	while(iter.valid())
 	{
-		CAnimImage * image = new CAnimImage("RESOURCE", iter->resType);
-		CLabel * text = new CLabel(15, 43, FONT_SMALL, CENTER, Colors::WHITE, "0");
+		ImagePtr image = std::make_shared<CAnimImage>("RESOURCE", iter->resType);
+		LabelPtr text = std::make_shared<CLabel>(15, 43, FONT_SMALL, CENTER, Colors::WHITE, "0");
 
 		resources.insert(std::make_pair(iter->resType, std::make_pair(text, image)));
 		iter++;
 	}
 
-	if (!resources.empty())
+	if(!resources.empty())
 	{
 		int curx = pos.w / 2 - (16 * resources.size()) - (8 * (resources.size() - 1));
 		//reverse to display gold as first resource
-		for (auto & res : boost::adaptors::reverse(resources))
+		for(auto & res : boost::adaptors::reverse(resources))
 		{
 			res.second.first->moveBy(Point(curx, 22));
 			res.second.second->moveBy(Point(curx, 22));

+ 10 - 3
client/CreatureCostBox.h

@@ -9,15 +9,22 @@
  */
 #pragma once
 
-#include "widgets/Images.h"
 #include "../lib/ResourceSet.h"
+#include "gui/CIntObject.h"
+
+class CLabel;
+class CAnimImage;
 
 class CreatureCostBox : public CIntObject
 {
 public:
 	void set(TResources res);
-	CreatureCostBox(Rect position, std::string title);
+	CreatureCostBox(Rect position, std::string titleText);
 	void createItems(TResources res);
 private:
-	std::map<int, std::pair<CLabel *, CAnimImage * > > resources;
+	using LabelPtr = std::shared_ptr<CLabel>;
+	using ImagePtr = std::shared_ptr<CAnimImage>;
+
+	LabelPtr title;
+	std::map<int, std::pair<LabelPtr, ImagePtr>> resources;
 };

+ 38 - 1
client/Graphics.cpp

@@ -264,7 +264,7 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
 {
 	if(sur->format->palette)
 	{
-		SDL_Color *palette = nullptr;
+		SDL_Color * palette = nullptr;
 		if(player < PlayerColor::PLAYER_LIMIT)
 		{
 			palette = playerColorPalette + 32*player.getNum();
@@ -278,7 +278,44 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
 			logGlobal->error("Wrong player id in blueToPlayersAdv (%s)!", player.getStr());
 			return;
 		}
+//FIXME: not all player colored images have player palette at last 32 indexes
+//NOTE: following code is much more correct but still not perfect (bugged with status bar)
+
 		SDL_SetColors(sur, palette, 224, 32);
+
+
+#if 0
+
+		SDL_Color * bluePalette = playerColorPalette + 32;
+
+		SDL_Palette * oldPalette = sur->format->palette;
+
+		SDL_Palette * newPalette = SDL_AllocPalette(256);
+
+		for(size_t destIndex = 0; destIndex < 256; destIndex++)
+		{
+			SDL_Color old = oldPalette->colors[destIndex];
+
+			bool found = false;
+
+			for(size_t srcIndex = 0; srcIndex < 32; srcIndex++)
+			{
+				if(old.b == bluePalette[srcIndex].b && old.g == bluePalette[srcIndex].g && old.r == bluePalette[srcIndex].r)
+				{
+					found = true;
+					newPalette->colors[destIndex] = palette[srcIndex];
+					break;
+				}
+			}
+			if(!found)
+				newPalette->colors[destIndex] = old;
+		}
+
+		SDL_SetSurfacePalette(sur, newPalette);
+
+		SDL_FreePalette(newPalette);
+
+#endif // 0
 	}
 	else
 	{

+ 1 - 6
client/NetPacksClient.cpp

@@ -534,15 +534,10 @@ void GiveHero::applyFirstCl(CClient *cl)
 
 void InfoWindow::applyCl(CClient *cl)
 {
-	std::vector<Component*> comps;
-	for(auto & elem : components)
-	{
-		comps.push_back(&elem);
-	}
 	std::string str;
 	text.toString(str);
 
-	if(!callInterfaceIfPresent(cl, player, &CGameInterface::showInfoDialog, str,comps,(soundBase::soundID)soundID))
+	if(!callInterfaceIfPresent(cl, player, &CGameInterface::showInfoDialog, str,components,(soundBase::soundID)soundID))
 		logNetwork->warn("We received InfoWindow for not our player...");
 }
 

+ 7 - 8
client/battle/CBattleInterface.cpp

@@ -803,7 +803,7 @@ void CBattleInterface::bSurrenderf()
 			enemyHeroName = "#ENEMY#"; //TODO: should surrendering without enemy hero be enabled?
 
 		std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold."
-		curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, 0, false);
+		curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, nullptr);
 	}
 }
 
@@ -815,11 +815,11 @@ void CBattleInterface::bFleef()
 	if ( curInt->cb->battleCanFlee() )
 	{
 		CFunctionList<void()> ony = std::bind(&CBattleInterface::reallyFlee,this);
-		curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, 0, false); //Are you sure you want to retreat?
+		curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat?
 	}
 	else
 	{
-		std::vector<CComponent*> comps;
+		std::vector<std::shared_ptr<CComponent>> comps;
 		std::string heroName;
 		//calculating fleeing hero's name
 		if (attackingHeroInstance)
@@ -1280,8 +1280,7 @@ void CBattleInterface::displayBattleFinished()
 		return;
 	}
 
-	SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
-	resWindow = new CBattleResultWindow(*bresult, temp_rect, *this->curInt);
+	resWindow = new CBattleResultWindow(*bresult, *this->curInt);
 	GH.pushInt(resWindow);
 	curInt->waitWhileDialog(); // Avoid freeze when AI end turn after battle. Check bug #1897
 }
@@ -3637,7 +3636,7 @@ void CBattleInterface::updateBattleAnimations()
 	}
 }
 
-IImage * CBattleInterface::getObstacleImage(const CObstacleInstance & oi)
+std::shared_ptr<IImage> CBattleInterface::getObstacleImage(const CObstacleInstance & oi)
 {
 	int frameIndex = (animCount+1) *25 / getAnimSpeed();
 	std::shared_ptr<CAnimation> animation;
@@ -3650,7 +3649,7 @@ IImage * CBattleInterface::getObstacleImage(const CObstacleInstance & oi)
 	{
 		const SpellCreatedObstacle * spellObstacle = dynamic_cast<const SpellCreatedObstacle *>(&oi);
 		if(!spellObstacle)
-			return nullptr;
+			return std::shared_ptr<IImage>();
 
 		std::string animationName = spellObstacle->animation;
 
@@ -3679,7 +3678,7 @@ IImage * CBattleInterface::getObstacleImage(const CObstacleInstance & oi)
 	return nullptr;
 }
 
-Point CBattleInterface::getObstaclePosition(IImage * image, const CObstacleInstance & obstacle)
+Point CBattleInterface::getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle)
 {
 	int offset = obstacle.getAnimationYOffset(image->height());
 

+ 2 - 2
client/battle/CBattleInterface.h

@@ -254,9 +254,9 @@ private:
 	BattleObjectsByHex sortObjectsByHex();
 	void updateBattleAnimations();
 
-	IImage * getObstacleImage(const CObstacleInstance & oi);
+	std::shared_ptr<IImage> getObstacleImage(const CObstacleInstance & oi);
 
-	Point getObstaclePosition(IImage * image, const CObstacleInstance & obstacle);
+	Point getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle);
 
 	void redrawBackgroundWithHexes(const CStack *activeStack);
 	/** End of battle screen blitting methods */

+ 176 - 153
client/battle/CBattleInterfaceClasses.cpp

@@ -277,55 +277,111 @@ CBattleHero::CBattleHero(const std::string & animationPath, bool flipG, PlayerCo
 
 CBattleHero::~CBattleHero() = default;
 
+CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero & hero, Point * position)
+	: CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
+{
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	if (position != nullptr)
+		moveTo(*position);
+	background->colorize(hero.owner); //maybe add this functionality to base class?
+
+	auto attack = hero.details->primskills[0];
+	auto defense = hero.details->primskills[1];
+	auto power = hero.details->primskills[2];
+	auto knowledge = hero.details->primskills[3];
+	auto morale = hero.details->morale;
+	auto luck = hero.details->luck;
+	auto currentSpellPoints = hero.details->mana;
+	auto maxSpellPoints = hero.details->manaLimit;
+
+	icons.push_back(std::make_shared<CAnimImage>("PortraitsLarge", hero.portrait, 0, 10, 6));
+
+	//primary stats
+	labels.push_back(std::make_shared<CLabel>(9, 75, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":"));
+	labels.push_back(std::make_shared<CLabel>(9, 87, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[381] + ":"));
+	labels.push_back(std::make_shared<CLabel>(9, 99, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[382] + ":"));
+	labels.push_back(std::make_shared<CLabel>(9, 111, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[383] + ":"));
+
+	labels.push_back(std::make_shared<CLabel>(69, 87, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(attack)));
+	labels.push_back(std::make_shared<CLabel>(69, 99, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(defense)));
+	labels.push_back(std::make_shared<CLabel>(69, 111, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(power)));
+	labels.push_back(std::make_shared<CLabel>(69, 123, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(knowledge)));
+
+	//morale+luck
+	labels.push_back(std::make_shared<CLabel>(9, 131, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":"));
+	labels.push_back(std::make_shared<CLabel>(9, 143, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":"));
+
+	icons.push_back(std::make_shared<CAnimImage>("IMRL22", morale + 3, 0, 47, 131));
+	icons.push_back(std::make_shared<CAnimImage>("ILCK22", luck + 3, 0, 47, 143));
+
+	//spell points
+	labels.push_back(std::make_shared<CLabel>(39, 174, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387]));
+	labels.push_back(std::make_shared<CLabel>(39, 186, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints)));
+}
+
 CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	pos = position;
-	background = new CPicture("comopbck.bmp");
+
+	background = std::make_shared<CPicture>("comopbck.bmp");
 	background->colorize(owner->getCurrentPlayerInterface()->playerID);
 
-	viewGrid = new CToggleButton(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [=](bool on){owner->setPrintCellBorders(on);} );
+	auto viewGrid = std::make_shared<CToggleButton>(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [=](bool on){owner->setPrintCellBorders(on);} );
 	viewGrid->setSelected(settings["battle"]["cellBorders"].Bool());
-	movementShadow = new CToggleButton(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [=](bool on){owner->setPrintStackRange(on);});
+	toggles.push_back(viewGrid);
+
+	auto movementShadow = std::make_shared<CToggleButton>(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [=](bool on){owner->setPrintStackRange(on);});
 	movementShadow->setSelected(settings["battle"]["stackRange"].Bool());
-	mouseShadow = new CToggleButton(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [=](bool on){owner->setPrintMouseShadow(on);});
+	toggles.push_back(movementShadow);
+
+	auto mouseShadow = std::make_shared<CToggleButton>(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [=](bool on){owner->setPrintMouseShadow(on);});
 	mouseShadow->setSelected(settings["battle"]["mouseShadow"].Bool());
+	toggles.push_back(mouseShadow);
+
+	animSpeeds = std::make_shared<CToggleGroup>([=](int value){ owner->setAnimSpeed(value);});
+
+	std::shared_ptr<CToggleButton> toggle;
+	toggle = std::make_shared<CToggleButton>(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422]);
+	animSpeeds->addToggle(40, toggle);
+
+	toggle = std::make_shared<CToggleButton>(Point( 92, 225), "sysob10.def", CGI->generaltexth->zelp[423]);
+	animSpeeds->addToggle(63, toggle);
+
+	toggle = std::make_shared<CToggleButton>(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424]);
+	animSpeeds->addToggle(100, toggle);
 
-	animSpeeds = new CToggleGroup([=](int value){ owner->setAnimSpeed(value);});
-	animSpeeds->addToggle(40,  new CToggleButton(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422]));
-	animSpeeds->addToggle(63,  new CToggleButton(Point( 92, 225), "sysob10.def", CGI->generaltexth->zelp[423]));
-	animSpeeds->addToggle(100, new CToggleButton(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424]));
 	animSpeeds->setSelected(owner->getAnimSpeed());
 
-	setToDefault = new CButton (Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&](){ bDefaultf(); });
+	setToDefault = std::make_shared<CButton>(Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&](){ bDefaultf(); });
 	setToDefault->setImageOrder(1, 0, 2, 3);
-	exit = new CButton (Point(357, 359), "soretrn.def", CGI->generaltexth->zelp[392], [&](){ bExitf();}, SDLK_RETURN);
+	exit = std::make_shared<CButton>(Point(357, 359), "soretrn.def", CGI->generaltexth->zelp[392], [&](){ bExitf();}, SDLK_RETURN);
 	exit->setImageOrder(1, 0, 2, 3);
 
 	//creating labels
-	labels.push_back(new CLabel(242,  32, FONT_BIG,    CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[392]));//window title
-	labels.push_back(new CLabel(122, 214, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[393]));//animation speed
-	labels.push_back(new CLabel(122, 293, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[394]));//music volume
-	labels.push_back(new CLabel(122, 359, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[395]));//effects' volume
-	labels.push_back(new CLabel(353,  66, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[396]));//auto - combat options
-	labels.push_back(new CLabel(353, 265, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[397]));//creature info
+	labels.push_back(std::make_shared<CLabel>(242,  32, FONT_BIG,    CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[392]));//window title
+	labels.push_back(std::make_shared<CLabel>(122, 214, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[393]));//animation speed
+	labels.push_back(std::make_shared<CLabel>(122, 293, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[394]));//music volume
+	labels.push_back(std::make_shared<CLabel>(122, 359, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[395]));//effects' volume
+	labels.push_back(std::make_shared<CLabel>(353,  66, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[396]));//auto - combat options
+	labels.push_back(std::make_shared<CLabel>(353, 265, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[397]));//creature info
 
 	//auto - combat options
-	labels.push_back(new CLabel(283,  86, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[398]));//creatures
-	labels.push_back(new CLabel(283, 116, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[399]));//spells
-	labels.push_back(new CLabel(283, 146, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[400]));//catapult
-	labels.push_back(new CLabel(283, 176, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[151]));//ballista
-	labels.push_back(new CLabel(283, 206, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[401]));//first aid tent
+	labels.push_back(std::make_shared<CLabel>(283,  86, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[398]));//creatures
+	labels.push_back(std::make_shared<CLabel>(283, 116, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[399]));//spells
+	labels.push_back(std::make_shared<CLabel>(283, 146, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[400]));//catapult
+	labels.push_back(std::make_shared<CLabel>(283, 176, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[151]));//ballista
+	labels.push_back(std::make_shared<CLabel>(283, 206, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[401]));//first aid tent
 
 	//creature info
-	labels.push_back(new CLabel(283, 285, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[402]));//all stats
-	labels.push_back(new CLabel(283, 315, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[403]));//spells only
+	labels.push_back(std::make_shared<CLabel>(283, 285, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[402]));//all stats
+	labels.push_back(std::make_shared<CLabel>(283, 315, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[403]));//spells only
 
 	//general options
-	labels.push_back(new CLabel(61,  57, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[404]));
-	labels.push_back(new CLabel(61,  90, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[405]));
-	labels.push_back(new CLabel(61, 123, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[406]));
-	labels.push_back(new CLabel(61, 156, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[407]));
+	labels.push_back(std::make_shared<CLabel>(61,  57, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[404]));
+	labels.push_back(std::make_shared<CLabel>(61,  90, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[405]));
+	labels.push_back(std::make_shared<CLabel>(61, 123, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[406]));
+	labels.push_back(std::make_shared<CLabel>(61, 156, FONT_MEDIUM, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[407]));
 }
 
 void CBattleOptionsWindow::bDefaultf()
@@ -338,31 +394,32 @@ void CBattleOptionsWindow::bExitf()
 	GH.popIntTotally(this);
 }
 
-CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CPlayerInterface &_owner)
-: owner(_owner)
+CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner)
+	: owner(_owner)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	this->pos = pos;
-	CPicture * bg = new CPicture("CPRESULT");
-	bg->colorize(owner.playerID);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
+	pos = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
+	background = std::make_shared<CPicture>("CPRESULT");
+	background->colorize(owner.playerID);
 
-	exit = new CButton (Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, SDLK_RETURN);
+	exit = std::make_shared<CButton>(Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, SDLK_RETURN);
 	exit->setBorderColor(Colors::METALLIC_GOLD);
 
 	if(br.winner==0) //attacker won
 	{
-		new CLabel( 59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410]);
-		new CLabel(408, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411]);
+		labels.push_back(std::make_shared<CLabel>(59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410]));
+		labels.push_back(std::make_shared<CLabel>(408, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411]));
 	}
 	else //if(br.winner==1)
 	{
-		new CLabel( 59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411]);
-		new CLabel(412, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410]);
+		labels.push_back(std::make_shared<CLabel>(59, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[411]));
+		labels.push_back(std::make_shared<CLabel>(412, 124, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[410]));
 	}
 
-	new CLabel(232, 302, FONT_BIG, CENTER, Colors::YELLOW,  CGI->generaltexth->allTexts[407]);
-	new CLabel(232, 332, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[408]);
-	new CLabel(232, 428, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[409]);
+	labels.push_back(std::make_shared<CLabel>(232, 302, FONT_BIG, CENTER, Colors::YELLOW,  CGI->generaltexth->allTexts[407]));
+	labels.push_back(std::make_shared<CLabel>(232, 332, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[408]));
+	labels.push_back(std::make_shared<CLabel>(232, 428, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[409]));
 
 	std::string sideNames[2] = {"N/A", "N/A"};
 
@@ -373,45 +430,51 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 
 		if(heroInfo.portrait >= 0) //attacking hero
 		{
-			new CAnimImage("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38);
+			icons.push_back(std::make_shared<CAnimImage>("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38));
 			sideNames[i] = heroInfo.name;
 		}
 		else
 		{
 			auto stacks = owner.cb->battleGetAllStacks();
-			vstd::erase_if(stacks, [i](const CStack *stack) //erase stack of other side and not coming from garrison
-				{ return stack->side != i  ||  !stack->base; });
+			vstd::erase_if(stacks, [i](const CStack * stack) //erase stack of other side and not coming from garrison
+			{
+				return stack->side != i || !stack->base;
+			});
+
+			auto best = vstd::maxElementByFun(stacks, [](const CStack * stack)
+			{
+				return stack->type->AIValue;
+			});
 
-			auto best = vstd::maxElementByFun(stacks, [](const CStack *stack){ return stack->type->AIValue; });
 			if(best != stacks.end()) //should be always but to be safe...
 			{
-				new CAnimImage("TWCRPORT", (*best)->type->idNumber+2, 0, xs[i], 38);
+				icons.push_back(std::make_shared<CAnimImage>("TWCRPORT", (*best)->type->idNumber+2, 0, xs[i], 38));
 				sideNames[i] = CGI->creh->creatures[(*best)->type->idNumber]->namePl;
 			}
 		}
 	}
 
 	//printing attacker and defender's names
-	new CLabel( 89, 37, FONT_SMALL, TOPLEFT, Colors::WHITE, sideNames[0]);
-	new CLabel( 381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, sideNames[1]);
+	labels.push_back(std::make_shared<CLabel>(89, 37, FONT_SMALL, TOPLEFT, Colors::WHITE, sideNames[0]));
+	labels.push_back(std::make_shared<CLabel>(381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::WHITE, sideNames[1]));
 
 	//printing casualties
 	for(int step = 0; step < 2; ++step)
 	{
 		if(br.casualties[step].size()==0)
 		{
-			new CLabel( 235, 360 + 97*step, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[523]);
+			labels.push_back(std::make_shared<CLabel>(235, 360 + 97 * step, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[523]));
 		}
 		else
 		{
 			int xPos = 235 - (br.casualties[step].size()*32 + (br.casualties[step].size() - 1)*10)/2; //increment by 42 with each picture
-			int yPos = 344 + step*97;
+			int yPos = 344 + step * 97;
 			for(auto & elem : br.casualties[step])
 			{
-				new CAnimImage("CPRSMALL", CGI->creh->creatures[elem.first]->iconIndex, 0, xPos, yPos);
+				icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", CGI->creh->creatures[elem.first]->iconIndex, 0, xPos, yPos));
 				std::ostringstream amount;
 				amount<<elem.second;
-				new CLabel( xPos+16, yPos + 42, FONT_SMALL, CENTER, Colors::WHITE, amount.str());
+				labels.push_back(std::make_shared<CLabel>(xPos + 16, yPos + 42, FONT_SMALL, CENTER, Colors::WHITE, amount.str()));
 				xPos += 42;
 			}
 		}
@@ -420,12 +483,20 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 	bool weAreAttacker = !(owner.cb->battleGetMySide());
 	if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
 	{
-		int text=-1;
+		int text = 304;
 		switch(br.result)
 		{
-		case BattleResult::NORMAL: text = 304; break;
-		case BattleResult::ESCAPE: text = 303; break;
-		case BattleResult::SURRENDER: text = 302; break;
+		case BattleResult::NORMAL:
+			break;
+		case BattleResult::ESCAPE:
+			text = 303;
+			break;
+		case BattleResult::SURRENDER:
+			text = 302;
+			break;
+		default:
+			logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast<int>(br.result));
+			break;
 		}
 
 		CCS->musich->playMusic("Music/Win Battle", false);
@@ -436,44 +507,43 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 		if (ourHero)
 		{
 			str += CGI->generaltexth->allTexts[305];
-			boost::algorithm::replace_first(str,"%s",ourHero->name);
-			boost::algorithm::replace_first(str,"%d",boost::lexical_cast<std::string>(br.exp[weAreAttacker?0:1]));
+			boost::algorithm::replace_first(str, "%s", ourHero->name);
+			boost::algorithm::replace_first(str, "%d", boost::lexical_cast<std::string>(br.exp[weAreAttacker ? 0 : 1]));
 		}
 
-		new CTextBox(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
+		description = std::make_shared<CTextBox>(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
 	}
 	else // we lose
 	{
+		int text = 311;
+		std::string musicName = "Music/LoseCombat";
+		std::string videoName = "LBSTART.BIK";
 		switch(br.result)
 		{
 		case BattleResult::NORMAL:
-			{
-				CCS->musich->playMusic("Music/LoseCombat", false);
-				CCS->videoh->open("LBSTART.BIK");
-				new CLabel(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[311]);
-				break;
-			}
-		case BattleResult::ESCAPE: //flee
-			{
-				CCS->musich->playMusic("Music/Retreat Battle", false);
-				CCS->videoh->open("RTSTART.BIK");
-				new CLabel(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[310]);
-				break;
-			}
+			break;
+		case BattleResult::ESCAPE:
+			musicName = "Music/Retreat Battle";
+			videoName = "RTSTART.BIK";
+			text = 310;
+			break;
 		case BattleResult::SURRENDER:
-			{
-				CCS->musich->playMusic("Music/Surrender Battle", false);
-				CCS->videoh->open("SURRENDER.BIK");
-				new CLabel(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[309]);
-				break;
-			}
+			musicName = "Music/Surrender Battle";
+			videoName = "SURRENDER.BIK";
+			text = 309;
+			break;
+		default:
+			logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast<int>(br.result));
+			break;
 		}
+		CCS->musich->playMusic(musicName, false);
+		CCS->videoh->open(videoName);
+
+		labels.push_back(std::make_shared<CLabel>(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text]));
 	}
 }
 
-CBattleResultWindow::~CBattleResultWindow()
-{
-}
+CBattleResultWindow::~CBattleResultWindow() = default;
 
 void CBattleResultWindow::activate()
 {
@@ -628,52 +698,11 @@ void CClickableHex::clickRight(tribool down, bool previousState)
 	}
 }
 
-CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero &hero, Point *position) : CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
-{
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	if (position != nullptr)
-		moveTo(*position);
-	background->colorize(hero.owner); //maybe add this functionality to base class?
-
-	int attack = hero.details->primskills[0];
-	int defense = hero.details->primskills[1];
-	int power = hero.details->primskills[2];
-	int knowledge = hero.details->primskills[3];
-	int morale = hero.details->morale;
-	int luck = hero.details->luck;
-	int currentSpellPoints = hero.details->mana;
-	int maxSpellPoints = hero.details->manaLimit;
-
-	new CAnimImage("PortraitsLarge", hero.portrait, 0, 10, 6);
-
-	//primary stats
-	new CLabel(9, 75, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":");
-	new CLabel(9, 87, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[381] + ":");
-	new CLabel(9, 99, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[382] + ":");
-	new CLabel(9, 111, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[383] + ":");
-
-	new CLabel(69, 87, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(attack));
-	new CLabel(69, 99, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(defense));
-	new CLabel(69, 111, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(power));
-	new CLabel(69, 123, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(knowledge));
-
-	//morale+luck
-	new CLabel(9, 131, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":");
-	new CLabel(9, 143, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":");
-
-	new CAnimImage("IMRL22", morale + 3, 0, 47, 131);
-	new CAnimImage("ILCK22", luck + 3, 0, 47, 143);
-
-	//spell points
-	new CLabel(39, 174, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387]);
-	new CLabel(39, 186, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints));
-}
-
 CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner)
 	: embedded(Embedded),
 	owner(_owner)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	if(embedded)
 	{
 		pos.w = QUEUE_SIZE * 37;
@@ -689,7 +718,7 @@ CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner)
 		pos.w = 800;
 		pos.h = 85;
 
-		new CFilledTexture("DIBOXBCK", Rect(0,0, pos.w, pos.h));
+		background = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, 0, pos.w, pos.h));
 
 		icons = std::make_shared<CAnimation>("TWCRPORT");
 		stateIcons = std::make_shared<CAnimation>("VCMI/BATTLEQUEUE/STATESSMALL");
@@ -701,14 +730,12 @@ CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner)
 	stackBoxes.resize(QUEUE_SIZE);
 	for (int i = 0; i < stackBoxes.size(); i++)
 	{
-		stackBoxes[i] = new StackBox(this);
-		stackBoxes[i]->moveBy(Point(1 + (embedded ? 36 : 80)*i, 0));
+		stackBoxes[i] = std::make_shared<StackBox>(this);
+		stackBoxes[i]->moveBy(Point(1 + (embedded ? 36 : 80) * i, 0));
 	}
 }
 
-CStackQueue::~CStackQueue()
-{
-}
+CStackQueue::~CStackQueue() = default;
 
 void CStackQueue::update()
 {
@@ -721,60 +748,56 @@ void CStackQueue::update()
 	for(size_t turn = 0; turn < queueData.size() && boxIndex < stackBoxes.size(); turn++)
 	{
 		for(size_t unitIndex = 0; unitIndex < queueData[turn].size() && boxIndex < stackBoxes.size(); boxIndex++, unitIndex++)
-			stackBoxes[boxIndex]->setStack(queueData[turn][unitIndex], turn);
+			stackBoxes[boxIndex]->setUnit(queueData[turn][unitIndex], turn);
 	}
 
 	for(; boxIndex < stackBoxes.size(); boxIndex++)
-		stackBoxes[boxIndex]->setStack(nullptr);
+		stackBoxes[boxIndex]->setUnit(nullptr);
 }
 
 CStackQueue::StackBox::StackBox(CStackQueue * owner)
-	: bg(nullptr),
-	icon(nullptr),
-	amount(nullptr),
-	stateIcon(nullptr)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	bg = new CPicture(owner->embedded ? "StackQueueSmall" : "StackQueueLarge" );
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CPicture>(owner->embedded ? "StackQueueSmall" : "StackQueueLarge");
 
-	pos.w = bg->pos.w;
-	pos.h = bg->pos.h;
+	pos.w = background->pos.w;
+	pos.h = background->pos.h;
 
 	if(owner->embedded)
 	{
-		icon = new CAnimImage(owner->icons, 0, 0, 5, 2);
-		amount = new CLabel(pos.w/2, pos.h - 7, FONT_SMALL, CENTER, Colors::WHITE);
+		icon = std::make_shared<CAnimImage>(owner->icons, 0, 0, 5, 2);
+		amount = std::make_shared<CLabel>(pos.w/2, pos.h - 7, FONT_SMALL, CENTER, Colors::WHITE);
 	}
 	else
 	{
-		icon = new CAnimImage(owner->icons, 0, 0, 9, 1);
-		amount = new CLabel(pos.w/2, pos.h - 8, FONT_MEDIUM, CENTER, Colors::WHITE);
+		icon = std::make_shared<CAnimImage>(owner->icons, 0, 0, 9, 1);
+		amount = std::make_shared<CLabel>(pos.w/2, pos.h - 8, FONT_MEDIUM, CENTER, Colors::WHITE);
 
 		int icon_x = pos.w - 17;
 		int icon_y = pos.h - 18;
 
-		stateIcon = new CAnimImage(owner->stateIcons, 0, 0, icon_x, icon_y);
+		stateIcon = std::make_shared<CAnimImage>(owner->stateIcons, 0, 0, icon_x, icon_y);
 		stateIcon->visible = false;
 	}
 }
 
-void CStackQueue::StackBox::setStack(const battle::Unit * nStack, size_t turn)
+void CStackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn)
 {
-	if(nStack)
+	if(unit)
 	{
-		bg->colorize(nStack->unitOwner());
+		background->colorize(unit->unitOwner());
 		icon->visible = true;
-		icon->setFrame(nStack->creatureIconIndex());
-		amount->setText(makeNumberShort(nStack->getCount()));
+		icon->setFrame(unit->creatureIconIndex());
+		amount->setText(makeNumberShort(unit->getCount()));
 
 		if(stateIcon)
 		{
-			if(nStack->defended(turn) || (turn > 0 && nStack->defended(turn - 1)))
+			if(unit->defended(turn) || (turn > 0 && unit->defended(turn - 1)))
 			{
 				stateIcon->setFrame(0, 0);
 				stateIcon->visible = true;
 			}
-			else if(nStack->waited(turn))
+			else if(unit->waited(turn))
 			{
 				stateIcon->setFrame(1, 0);
 				stateIcon->visible = true;
@@ -787,7 +810,7 @@ void CStackQueue::StackBox::setStack(const battle::Unit * nStack, size_t turn)
 	}
 	else
 	{
-		bg->colorize(PlayerColor::NEUTRAL);
+		background->colorize(PlayerColor::NEUTRAL);
 		icon->visible = false;
 		icon->setFrame(0);
 		amount->setText("");

+ 30 - 19
client/battle/CBattleInterfaceClasses.h

@@ -17,10 +17,12 @@ struct SDL_Surface;
 class CGHeroInstance;
 class CBattleInterface;
 class CPicture;
+class CFilledTexture;
 class CButton;
 class CToggleButton;
 class CToggleGroup;
 class CLabel;
+class CTextBox;
 struct BattleResult;
 class CStack;
 namespace battle
@@ -79,22 +81,25 @@ public:
 
 class CHeroInfoWindow : public CWindowObject
 {
+private:
+	std::vector<std::shared_ptr<CLabel>> labels;
+	std::vector<std::shared_ptr<CAnimImage>> icons;
 public:
-	CHeroInfoWindow(const InfoAboutHero &hero, Point *position);
+	CHeroInfoWindow(const InfoAboutHero & hero, Point * position);
 };
 
 /// Class which manages the battle options window
 class CBattleOptionsWindow : public CIntObject
 {
 private:
-	CPicture * background;
-	CButton * setToDefault, * exit;
-	CToggleButton * viewGrid, * movementShadow, * mouseShadow;
-	CToggleGroup * animSpeeds;
-
-	std::vector<CLabel*> labels;
+	std::shared_ptr<CPicture> background;
+	std::shared_ptr<CButton> setToDefault;
+	std::shared_ptr<CButton> exit;
+	std::shared_ptr<CToggleGroup> animSpeeds;
+	std::vector<std::shared_ptr<CLabel>> labels;
+	std::vector<std::shared_ptr<CToggleButton>> toggles;
 public:
-	CBattleOptionsWindow(const SDL_Rect &position, CBattleInterface *owner);
+	CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface * owner);
 
 	void bDefaultf(); //default button callback
 	void bExitf(); //exit button callback
@@ -104,10 +109,14 @@ public:
 class CBattleResultWindow : public CIntObject
 {
 private:
-	CButton *exit;
-	CPlayerInterface &owner;
+	std::shared_ptr<CPicture> background;
+	std::vector<std::shared_ptr<CLabel>> labels;
+	std::shared_ptr<CButton> exit;
+	std::vector<std::shared_ptr<CAnimImage>> icons;
+	std::shared_ptr<CTextBox> description;
+	CPlayerInterface & owner;
 public:
-	CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CPlayerInterface &_owner);
+	CBattleResultWindow(const BattleResult & br, CPlayerInterface & _owner);
 	~CBattleResultWindow();
 
 	void bExitf(); //exit button callback
@@ -143,24 +152,26 @@ class CStackQueue : public CIntObject
 	class StackBox : public CIntObject
 	{
 	public:
-		CPicture * bg;
-		CAnimImage * icon;
-		CLabel * amount;
-		CAnimImage * stateIcon;
+		std::shared_ptr<CPicture> background;
+		std::shared_ptr<CAnimImage> icon;
+		std::shared_ptr<CLabel> amount;
+		std::shared_ptr<CAnimImage> stateIcon;
 
-		void setStack(const battle::Unit * nStack, size_t turn = 0);
+		void setUnit(const battle::Unit * unit, size_t turn = 0);
 		StackBox(CStackQueue * owner);
 	};
 
-public:
 	static const int QUEUE_SIZE = 10;
-	const bool embedded;
-	std::vector<StackBox *> stackBoxes;
+	std::shared_ptr<CFilledTexture> background;
+	std::vector<std::shared_ptr<StackBox>> stackBoxes;
 	CBattleInterface * owner;
 
 	std::shared_ptr<CAnimation> icons;
 	std::shared_ptr<CAnimation> stateIcons;
 
+public:
+	const bool embedded;
+
 	CStackQueue(bool Embedded, CBattleInterface * _owner);
 	~CStackQueue();
 	void update();

+ 1 - 1
client/battle/CCreatureAnimation.cpp

@@ -286,7 +286,7 @@ void CCreatureAnimation::nextFrame(SDL_Surface * dest, bool attacker)
 {
 	size_t frame = floor(currentFrame);
 
-	IImage * image = nullptr;
+	std::shared_ptr<IImage> image;
 
 	if(attacker)
 		image = forward->getImage(frame, type);

+ 17 - 45
client/gui/CAnimation.cpp

@@ -90,7 +90,7 @@ public:
 
 	void draw(SDL_Surface * where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
 	void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
-	std::unique_ptr<IImage> scaleFast(float scale) const override;
+	std::shared_ptr<IImage> scaleFast(float scale) const override;
 	void exportBitmap(const boost::filesystem::path & path) const override;
 	void playerColored(PlayerColor player) override;
 	void setFlagColor(PlayerColor player) override;
@@ -148,7 +148,7 @@ public:
 	void draw(SDL_Surface  *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
 	void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
 
-	std::unique_ptr<IImage> scaleFast(float scale) const override;
+	std::shared_ptr<IImage> scaleFast(float scale) const override;
 
 	void exportBitmap(const boost::filesystem::path & path) const override;
 
@@ -801,22 +801,9 @@ CompImageLoader::~CompImageLoader()
  *  Classes for images, support loading from file and drawing on surface *
  *************************************************************************/
 
-IImage::IImage():
-	refCount(1)
-{
-
-}
-
-bool IImage::decreaseRef()
-{
-	refCount--;
-	return refCount <= 0;
-}
+IImage::IImage() = default;
+IImage::~IImage() = default;
 
-void IImage::increaseRef()
-{
-	refCount++;
-}
 
 SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group, bool compressed)
 	: surf(nullptr),
@@ -957,7 +944,7 @@ void SDLImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha
 	}
 }
 
-std::unique_ptr<IImage> SDLImage::scaleFast(float scale) const
+std::shared_ptr<IImage> SDLImage::scaleFast(float scale) const
 {
 	auto scaled = CSDL_Ext::scaleSurfaceFast(surf, surf->w * scale, surf->h * scale);
 
@@ -976,7 +963,7 @@ std::unique_ptr<IImage> SDLImage::scaleFast(float scale) const
 	ret->margins.x = (int) round((float)margins.x * scale);
 	ret->margins.y = (int) round((float)margins.y * scale);
 
-	return std::unique_ptr<IImage>(ret);
+	return std::shared_ptr<IImage>(ret);
 }
 
 void SDLImage::exportBitmap(const boost::filesystem::path& path) const
@@ -1156,7 +1143,7 @@ void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alph
 }
 
 
-std::unique_ptr<IImage> CompImage::scaleFast(float scale) const
+std::shared_ptr<IImage> CompImage::scaleFast(float scale) const
 {
 	//todo: CompImage::scaleFast
 
@@ -1331,7 +1318,7 @@ void CompImage::exportBitmap(const boost::filesystem::path & path) const
  *  CAnimation for animations handling, can load part of file if needed  *
  *************************************************************************/
 
-IImage * CAnimation::getFromExtraDef(std::string filename)
+std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
 {
 	size_t pos = filename.find(':');
 	if (pos == -1)
@@ -1364,7 +1351,6 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
 	auto image = getImage(frame, group, false);
 	if(image)
 	{
-		image->increaseRef();
 		return true;
 	}
 
@@ -1378,22 +1364,22 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
 			if(vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present
 			{
 				if(compressed)
-					images[group][frame] = new CompImage(defFile, frame, group);
+					images[group][frame] = std::make_shared<CompImage>(defFile, frame, group);
 				else
-					images[group][frame] = new SDLImage(defFile, frame, group);
+					images[group][frame] = std::make_shared<SDLImage>(defFile, frame, group);
 				return true;
 			}
 		}
 		// still here? image is missing
 
 		printError(frame, group, "LoadFrame");
-		images[group][frame] = new SDLImage("DEFAULT", compressed);
+		images[group][frame] = std::make_shared<SDLImage>("DEFAULT", compressed);
 	}
 	else //load from separate file
 	{
 		auto img = getFromExtraDef(source[group][frame]["file"].String());
 		if(!img)
-			img = new SDLImage(source[group][frame]);
+			img = std::make_shared<SDLImage>(source[group][frame]);
 
 		images[group][frame] = img;
 		return true;
@@ -1404,15 +1390,11 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
 bool CAnimation::unloadFrame(size_t frame, size_t group)
 {
 	auto image = getImage(frame, group, false);
-	if (image)
+	if(image)
 	{
-		//decrease ref count for image and delete if needed
-		if (image->decreaseRef())
-		{
-			delete image;
-			images[group].erase(frame);
-		}
-		if (images[group].empty())
+		images[group].erase(frame);
+
+		if(images[group].empty())
 			images.erase(group);
 		return true;
 	}
@@ -1558,16 +1540,6 @@ CAnimation::CAnimation():
 
 CAnimation::~CAnimation()
 {
-	if(preloaded)
-		unload();
-
-	if(!images.empty())
-	{
-		logGlobal->warn("Warning: not all frames were unloaded from %s", name);
-		for (auto & elem : images)
-			for (auto & _image : elem.second)
-				delete _image.second;
-	}
 	if(defFile)
 		delete defFile;
 }
@@ -1599,7 +1571,7 @@ void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
 	//FIXME: update image if already loaded
 }
 
-IImage * CAnimation::getImage(size_t frame, size_t group, bool verbose) const
+std::shared_ptr<IImage> CAnimation::getImage(size_t frame, size_t group, bool verbose) const
 {
 	auto groupIter = images.find(group);
 	if (groupIter != images.end())

+ 5 - 11
client/gui/CAnimation.h

@@ -22,7 +22,6 @@ class CDefFile;
  */
 class IImage
 {
-	int refCount;
 public:
 	using BorderPallete = std::array<SDL_Color, 3>;
 
@@ -30,14 +29,10 @@ public:
 	virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, Rect * src = nullptr, ui8 alpha = 255) const=0;
 	virtual void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha = 255) const = 0;
 
-	virtual std::unique_ptr<IImage> scaleFast(float scale) const = 0;
+	virtual std::shared_ptr<IImage> scaleFast(float scale) const = 0;
 
 	virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
 
-	//decrease ref count, returns true if image can be deleted (refCount <= 0)
-	bool decreaseRef();
-	void increaseRef();
-
 	//Change palette to specific player
 	virtual void playerColored(PlayerColor player)=0;
 
@@ -57,7 +52,7 @@ public:
 	virtual void verticalFlip() = 0;
 
 	IImage();
-	virtual ~IImage() {};
+	virtual ~IImage();
 };
 
 /// Class for handling animation
@@ -68,7 +63,7 @@ private:
 	std::map<size_t, std::vector <JsonNode> > source;
 
 	//bitmap[group][position], store objects with loaded bitmaps
-	std::map<size_t, std::map<size_t, IImage* > > images;
+	std::map<size_t, std::map<size_t, std::shared_ptr<IImage> > > images;
 
 	//animation file name
 	std::string name;
@@ -95,7 +90,7 @@ private:
 
 	//not a very nice method to get image from another def file
 	//TODO: remove after implementing resource manager
-	IImage * getFromExtraDef(std::string filename);
+	std::shared_ptr<IImage> getFromExtraDef(std::string filename);
 
 public:
 	CAnimation(std::string Name, bool Compressed = false);
@@ -109,8 +104,7 @@ public:
 	//add custom surface to the selected position.
 	void setCustom(std::string filename, size_t frame, size_t group=0);
 
-	//get pointer to image from specific group, nullptr if not found
-	IImage * getImage(size_t frame, size_t group=0, bool verbose=true) const;
+	std::shared_ptr<IImage> getImage(size_t frame, size_t group=0, bool verbose=true) const;
 
 	void exportBitmaps(const boost::filesystem::path & path) const;
 

+ 2 - 3
client/gui/CGuiHandler.h

@@ -150,7 +150,6 @@ struct SSetCaptureState
 
 #define OBJ_CONSTRUCTION SObjectConstruction obj__i(this)
 #define OBJECT_CONSTRUCTION_CAPTURING(actions) defActions = actions; SSetCaptureState obj__i1(true, actions); SObjectConstruction obj__i(this)
-#define OBJ_CONSTRUCTION_CAPTURING_ALL defActions = 255; SSetCaptureState obj__i1(true, 255); SObjectConstruction obj__i(this)
+#define OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(actions) SSetCaptureState obj__i1(true, actions); SObjectConstruction obj__i(this)
+
 #define OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE defActions = 255 - DISPOSE; SSetCaptureState obj__i1(true, 255 - DISPOSE); SObjectConstruction obj__i(this)
-#define BLOCK_CAPTURING SSetCaptureState obj__i(false, 0)
-#define BLOCK_CAPTURING_DONT_TOUCH_REC_ACTIONS SSetCaptureState obj__i(false, GH.defActionsDef)

+ 23 - 20
client/gui/CIntObject.cpp

@@ -40,6 +40,23 @@ CIntObject::CIntObject(int used_, Point pos_):
 		GH.createdObj.front()->addChild(this, true);
 }
 
+CIntObject::~CIntObject()
+{
+	if(active_m)
+		deactivate();
+
+	while(!children.empty())
+	{
+		if((defActions & DISPOSE) && (children.front()->recActions & DISPOSE))
+			delete children.front();
+		else
+			removeChild(children.front());
+	}
+
+	if(parent_m)
+		parent_m->removeChild(this);
+}
+
 void CIntObject::setTimer(int msToTrigger)
 {
 	if (!(active & TIME))
@@ -125,24 +142,6 @@ void CIntObject::deactivate(ui16 what)
 	GH.handleElementDeActivate(this, what);
 }
 
-CIntObject::~CIntObject()
-{
-	if (active_m)
-		deactivate();
-
-	if(defActions & DISPOSE)
-	{
-		while (!children.empty())
-			if(children.front()->recActions & DISPOSE)
-				delete children.front();
-			else
-				removeChild(children.front());
-	}
-
-	if(parent_m)
-		parent_m->removeChild(this);
-}
-
 void CIntObject::click(EIntObjMouseBtnType btn, tribool down, bool previousState)
 {
 	switch(btn)
@@ -291,8 +290,12 @@ void CIntObject::removeChild(CIntObject * child, bool adjustPosition)
 	if (!child)
 		return;
 
-	assert(vstd::contains(children, child));
-	assert(child->parent_m == this);
+	if(!vstd::contains(children, child))
+		throw std::runtime_error("Wrong child object");
+
+	if(child->parent_m != this)
+		throw std::runtime_error("Wrong child object");
+
 	children -= child;
 	child->parent_m = nullptr;
 	if(adjustPosition)

+ 1 - 1
client/gui/CIntObject.h

@@ -66,7 +66,6 @@ enum class EIntObjMouseBtnType { LEFT, MIDDLE, RIGHT };
 // Base UI element
 class CIntObject : public IShowActivatable //interface object
 {
-
 	ui16 used;//change via addUsed() or delUsed
 
 	//time handling
@@ -80,6 +79,7 @@ class CIntObject : public IShowActivatable //interface object
 	//non-const versions of fields to allow changing them in CIntObject
 	CIntObject *parent_m; //parent object
 	ui16 active_m;
+
 protected:
 	//activate or deactivate specific action (LCLICK, RCLICK...)
 	void activate(ui16 what);

+ 1 - 1
client/lobby/CBonusSelection.cpp

@@ -323,7 +323,7 @@ void CBonusSelection::createBonusesIcons()
 			break;
 		}
 
-		CToggleButton * bonusButton = new CToggleButton(Point(475 + i * 68, 455), "", CButton::tooltip(desc, desc));
+		std::shared_ptr<CToggleButton> bonusButton = std::make_shared<CToggleButton>(Point(475 + i * 68, 455), "", CButton::tooltip(desc, desc));
 
 		if(picNumber != -1)
 			picName += ":" + boost::lexical_cast<std::string>(picNumber);

+ 1 - 1
client/lobby/CLobbyScreen.cpp

@@ -134,7 +134,7 @@ void CLobbyScreen::startScenario(bool allowOnlyAI)
 	catch(ExceptionNoHuman & e)
 	{
 		// You must position yourself prior to starting the game.
-		CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), nullptr, 0, std::bind(&CLobbyScreen::startScenario, this, true), false, PlayerColor(1));
+		CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), 0, std::bind(&CLobbyScreen::startScenario, this, true), PlayerColor(1));
 	}
 	catch(ExceptionNoTemplate & e)
 	{

+ 1 - 1
client/lobby/CSavingScreen.cpp

@@ -88,7 +88,7 @@ void CSavingScreen::saveGame()
 	{
 		std::string hlp = CGI->generaltexth->allTexts[493]; //%s exists. Overwrite?
 		boost::algorithm::replace_first(hlp, "%s", tabSel->inputName->text);
-		LOCPLINT->showYesNoDialog(hlp, overWrite, 0, false);
+		LOCPLINT->showYesNoDialog(hlp, overWrite, nullptr);
 	}
 	else
 	{

+ 1 - 1
client/lobby/CSelectionBase.cpp

@@ -148,7 +148,7 @@ InfoCard::InfoCard()
 
 			for(int i = 0; i < 5; i++)
 			{
-				auto button = new CToggleButton(Point(110 + i * 32, 450), difButns[i], CGI->generaltexth->zelp[24 + i]);
+				auto button = std::make_shared<CToggleButton>(Point(110 + i * 32, 450), difButns[i], CGI->generaltexth->zelp[24 + i]);
 
 				iconDifficulty->addToggle(i, button);
 				if(SEL->screenType != ESelectionScreen::newGame)

+ 2 - 2
client/lobby/OptionsTab.cpp

@@ -367,12 +367,12 @@ void OptionsTab::CPlayerOptionTooltipBox::genTownWindow()
 	genHeader();
 	labelAssociatedCreatures = std::make_shared<CLabel>(pos.w / 2 + 8, 122, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[79]);
 
-	std::vector<CComponent *> components;
+	std::vector<std::shared_ptr<CComponent>> components;
 	const CTown * town = CGI->townh->factions[settings.castle]->town;
 	for(auto & elem : town->creatures)
 	{
 		if(!elem.empty())
-			components.push_back(new CComponent(CComponent::creature, elem.front(), 0, CComponent::tiny));
+			components.push_back(std::make_shared<CComponent>(CComponent::creature, elem.front(), 0, CComponent::tiny));
 	}
 	boxAssociatedCreatures = std::make_shared<CComponentBox>(components, Rect(10, 140, pos.w - 20, 140));
 }

+ 3 - 4
client/lobby/RandomMapTab.cpp

@@ -219,7 +219,7 @@ void RandomMapTab::addButtonsWithRandToGroup(CToggleGroup * group, const std::ve
 	// Buttons are relative to button group, TODO better solution?
 	SObjectConstruction obj__i(group);
 	const std::string RANDOM_DEF = "RANRAND";
-	group->addToggle(CMapGenOptions::RANDOM_SIZE, new CToggleButton(Point(256, 0), RANDOM_DEF, CGI->generaltexth->zelp[helpRandIndex]));
+	group->addToggle(CMapGenOptions::RANDOM_SIZE, std::make_shared<CToggleButton>(Point(256, 0), RANDOM_DEF, CGI->generaltexth->zelp[helpRandIndex]));
 	group->setSelected(CMapGenOptions::RANDOM_SIZE);
 }
 
@@ -230,10 +230,9 @@ void RandomMapTab::addButtonsToGroup(CToggleGroup * group, const std::vector<std
 	int cnt = nEnd - nStart + 1;
 	for(int i = 0; i < cnt; ++i)
 	{
-		auto button = new CToggleButton(Point(i * btnWidth, 0), defs[i + nStart], CGI->generaltexth->zelp[helpStartIndex + i]);
+		auto button = std::make_shared<CToggleButton>(Point(i * btnWidth, 0), defs[i + nStart], CGI->generaltexth->zelp[helpStartIndex + i]);
 		// For blocked state we should use pressed image actually
 		button->setImageOrder(0, 1, 1, 3);
-
 		group->addToggle(i + nStart, button);
 	}
 }
@@ -243,7 +242,7 @@ void RandomMapTab::deactivateButtonsFrom(CToggleGroup * group, int startId)
 	logGlobal->debug("Blocking buttons from %d", startId);
 	for(auto toggle : group->buttons)
 	{
-		if(auto button = dynamic_cast<CToggleButton *>(toggle.second))
+		if(auto button = std::dynamic_pointer_cast<CToggleButton>(toggle.second))
 		{
 			if(startId == CMapGenOptions::RANDOM_SIZE || toggle.first < startId)
 			{

+ 12 - 12
client/mainmenu/CMainMenu.cpp

@@ -94,16 +94,16 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
 	//Hardcoded entry
 	menuNameToEntry.push_back("credits");
 
-	tabs = std::make_shared<CTabbedInt>(std::bind(&CMenuScreen::createTab, this, _1), CTabbedInt::DestroyFunc());
+	tabs = std::make_shared<CTabbedInt>(std::bind(&CMenuScreen::createTab, this, _1));
 	tabs->type |= REDRAW_PARENT;
 }
 
-CIntObject * CMenuScreen::createTab(size_t index)
+std::shared_ptr<CIntObject> CMenuScreen::createTab(size_t index)
 {
 	if(config["items"].Vector().size() == index)
-		return new CreditsScreen();
-
-	return new CMenuEntry(this, config["items"].Vector()[index]);
+		return std::make_shared<CreditsScreen>();
+	else
+		return std::make_shared<CMenuEntry>(this, config["items"].Vector()[index]);
 }
 
 void CMenuScreen::show(SDL_Surface * to)
@@ -175,7 +175,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
 				case 2:
 					return std::bind(CMainMenu::openLobby, ESelectionScreen::campaignList, true, nullptr, ELoadMode::NONE);
 				case 3:
-					return std::bind(CInfoWindow::showInfoDialog, "Sorry, tutorial is not implemented yet\n", (const std::vector<CComponent *> *)nullptr, false, PlayerColor(1));
+					return std::bind(CInfoWindow::showInfoDialog, "Sorry, tutorial is not implemented yet\n", std::vector<std::shared_ptr<CComponent>>(), PlayerColor(1));
 				}
 				break;
 			}
@@ -190,18 +190,18 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
 				case 2:
 					return std::bind(CMainMenu::openLobby, ESelectionScreen::loadGame, true, nullptr, ELoadMode::CAMPAIGN);
 				case 3:
-					return std::bind(CInfoWindow::showInfoDialog, "Sorry, tutorial is not implemented yet\n", (const std::vector<CComponent *> *)nullptr, false, PlayerColor(1));
+					return std::bind(CInfoWindow::showInfoDialog, "Sorry, tutorial is not implemented yet\n", std::vector<std::shared_ptr<CComponent>>(), PlayerColor(1));
 				}
 			}
 			break;
 			case 4: //exit
 			{
-				return std::bind(CInfoWindow::showYesNoDialog, std::ref(CGI->generaltexth->allTexts[69]), (const std::vector<CComponent *> *)nullptr, do_quit, 0, false, PlayerColor(1));
+				return std::bind(CInfoWindow::showYesNoDialog, std::ref(CGI->generaltexth->allTexts[69]), std::vector<std::shared_ptr<CComponent>>(), do_quit, 0, PlayerColor(1));
 			}
 			break;
 			case 5: //highscores
 			{
-				return std::bind(CInfoWindow::showInfoDialog, "Sorry, high scores menu is not implemented yet\n", (const std::vector<CComponent *> *)nullptr, false, PlayerColor(1));
+				return std::bind(CInfoWindow::showInfoDialog, "Sorry, high scores menu is not implemented yet\n", std::vector<std::shared_ptr<CComponent>>(), PlayerColor(1));
 			}
 			}
 		}
@@ -383,7 +383,7 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
 	blitAt(CPicture("MUMAP.bmp"), 16, 77, *background);
 	pos = background->center(); //center, window has size of bg graphic
 
-	statusBar = std::make_shared<CGStatusBar>(new CPicture(Rect(7, 465, 440, 18), 0)); //226, 472
+	statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(Rect(7, 465, 440, 18), 0)); //226, 472
 	playerName = std::make_shared<CTextInput>(Rect(19, 436, 334, 16), *background);
 	playerName->setText(settings["general"]["playerName"].String());
 	playerName->cb += std::bind(&CMultiMode::onNameChange, this, _1);
@@ -431,7 +431,7 @@ CMultiPlayers::CMultiPlayers(const std::string & firstPlayer, ESelectionScreen S
 
 	buttonOk = std::make_shared<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), SDLK_RETURN);
 	buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, std::ref(GH), this), SDLK_ESCAPE);
-	statusBar = std::make_shared<CGStatusBar>(new CPicture(Rect(7, 381, 348, 18), 0)); //226, 472
+	statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(Rect(7, 381, 348, 18), 0)); //226, 472
 
 	inputNames[0]->setText(firstPlayer, true);
 	inputNames[0]->giveFocus();
@@ -489,7 +489,7 @@ CSimpleJoinScreen::CSimpleJoinScreen(bool host)
 	inputPort->setText(CServerHandler::getDefaultPortStr(), true);
 
 	buttonCancel = std::make_shared<CButton>(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), SDLK_ESCAPE);
-	statusBar = std::make_shared<CGStatusBar>(new CPicture(Rect(7, 186, 218, 18), 0));
+	statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(Rect(7, 186, 218, 18), 0));
 }
 
 void CSimpleJoinScreen::connectToServer()

+ 1 - 1
client/mainmenu/CMainMenu.h

@@ -42,7 +42,7 @@ class CMenuScreen : public CWindowObject
 	std::shared_ptr<CPicture> background;
 	std::vector<std::shared_ptr<CPicture>> images;
 
-	CIntObject * createTab(size_t index);
+	std::shared_ptr<CIntObject> createTab(size_t index);
 
 public:
 	std::vector<std::string> menuNameToEntry;

+ 21 - 22
client/mapHandler.cpp

@@ -398,7 +398,7 @@ CMapHandler::CMapBlitter *CMapHandler::resolveBlitter(const MapDrawingInfo * inf
 	return normalBlitter;
 }
 
-void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const
+void CMapHandler::CMapNormalBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const
 {
 	source->draw(targetSurf, destRect, sourceRect);
 }
@@ -470,7 +470,7 @@ CMapHandler::CMapNormalBlitter::CMapNormalBlitter(CMapHandler * parent)
 	defaultTileRect = Rect(0, 0, tileSize, tileSize);
 }
 
-IImage * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
+std::shared_ptr<IImage> CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
 {
 	int ownerIndex = 0;
 	if(owner < PlayerColor::PLAYER_LIMIT)
@@ -501,7 +501,7 @@ IImage * CMapHandler::CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, Pla
 	case Obj::RESOURCE:
 		return info->icons->getImage((int)EWorldViewIcon::RES_WOOD + subId + ownerIndex);
 	}
-	return nullptr;
+	return std::shared_ptr<IImage>();
 }
 
 void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
@@ -536,7 +536,7 @@ void CMapHandler::CMapWorldViewBlitter::calculateWorldViewCameraPos()
 		topTile.y = parent->sizes.y - tileCount.y;
 }
 
-void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const
+void CMapHandler::CMapWorldViewBlitter::drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const
 {
 	auto scaled = parent->cache.requestWorldViewCacheOrCreate(cacheType, source);
 
@@ -604,7 +604,7 @@ void CMapHandler::CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
 	}
 }
 
-void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
+void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
 {
 	if (moving)
 		return;
@@ -612,7 +612,7 @@ void CMapHandler::CMapWorldViewBlitter::drawHeroFlag(SDL_Surface * targetSurf, c
 	CMapBlitter::drawHeroFlag(targetSurf, source, sourceRect, destRect, false);
 }
 
-void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const
+void CMapHandler::CMapWorldViewBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const
 {
 	if (moving)
 		return;
@@ -729,12 +729,12 @@ void CMapHandler::CMapBlitter::drawOverlayEx(SDL_Surface * targetSurf)
 //nothing to do here
 }
 
-void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
+void CMapHandler::CMapBlitter::drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const
 {
 	drawElement(EMapCacheType::HERO_FLAGS, source, sourceRect, targetSurf, destRect);
 }
 
-void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const
+void CMapHandler::CMapBlitter::drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const
 {
 	Rect dstRect(realTileRect);
 	drawElement(EMapCacheType::OBJECTS, source, sourceRect, targetSurf, &dstRect);
@@ -830,7 +830,7 @@ void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const
 	if (retBitmapID < 0)
 		retBitmapID = - parent->hideBitmap[pos.x][pos.y][pos.z] - 1; //fully hidden
 
-	const IImage * image = nullptr;
+	std::shared_ptr<IImage> image;
 
 	if (retBitmapID >= 0)
 		image = parent->FoWpartialHide.at(retBitmapID);
@@ -1006,22 +1006,22 @@ CMapHandler::AnimBitmapHolder CMapHandler::CMapBlitter::findBoatBitmap(const CGB
 		return CMapHandler::AnimBitmapHolder();
 }
 
-IImage * CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
+std::shared_ptr<IImage> CMapHandler::CMapBlitter::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
 {
-	if (!hero)
-		return nullptr;
+	if(!hero)
+		return std::shared_ptr<IImage>();
 
-	if (hero->boat)
+	if(hero->boat)
 		return findBoatFlagBitmap(hero->boat, anim, color, group, hero->moveDir);
 	return findHeroFlagBitmap(hero, anim, color, group);
 }
 
-IImage * CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
+std::shared_ptr<IImage> CMapHandler::CMapBlitter::findHeroFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor * color, int group) const
 {
 	return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color->getNum()), anim, group, hero->moveDir, !hero->isStanding);
 }
 
-IImage * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const
+std::shared_ptr<IImage> CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int anim, const PlayerColor * color, int group, ui8 dir) const
 {
 	int boatType = boat->subID;
 	if(boatType < 0 || boatType >= graphics->boatFlagAnimations.size())
@@ -1043,7 +1043,7 @@ IImage * CMapHandler::CMapBlitter::findBoatFlagBitmap(const CGBoat * boat, int a
 	return findFlagBitmapInternal(subtypeFlags.at(colorIndex), anim, group, dir, false);
 }
 
-IImage * CMapHandler::CMapBlitter::findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const
+std::shared_ptr<IImage> CMapHandler::CMapBlitter::findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const
 {
 	size_t groupSize = animation->size(group);
 	if(groupSize == 0)
@@ -1438,22 +1438,21 @@ void CMapHandler::CMapCache::updateWorldViewScale(float scale)
 	worldViewCachedScale = scale;
 }
 
-IImage * CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, const IImage * fullSurface)
+std::shared_ptr<IImage> CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CMapHandler::EMapCacheType type, std::shared_ptr<IImage> fullSurface)
 {
-	intptr_t key = (intptr_t) fullSurface;
+	intptr_t key = (intptr_t) (fullSurface.get());
 	auto & cache = data[(ui8)type];
 
 	auto iter = cache.find(key);
 	if(iter == cache.end())
 	{
 		auto scaled = fullSurface->scaleFast(worldViewCachedScale);
-		IImage * ret = scaled.get();
-		cache[key] = std::move(scaled);
-		return ret;
+		cache[key] = scaled;
+		return scaled;
 	}
 	else
 	{
-		return (*iter).second.get();
+		return (*iter).second;
 	}
 }
 

+ 21 - 21
client/mapHandler.h

@@ -159,7 +159,7 @@ class CMapHandler
 	/// temporarily caches rescaled frames for map world view redrawing
 	class CMapCache
 	{
-		std::array< std::map<intptr_t, std::unique_ptr<IImage>>, (ui8)EMapCacheType::AFTER_LAST> data;
+		std::array< std::map<intptr_t, std::shared_ptr<IImage>>, (ui8)EMapCacheType::AFTER_LAST> data;
 		float worldViewCachedScale;
 	public:
 		CMapCache();
@@ -168,17 +168,17 @@ class CMapHandler
 		/// updates scale and determines if currently cached data is still valid
 		void updateWorldViewScale(float scale);
 		/// asks for cached data; @returns cached data if found, new scaled surface otherwise, may return nullptr in case of scaling error
-		IImage * requestWorldViewCacheOrCreate(EMapCacheType type, const IImage * fullSurface);
+		std::shared_ptr<IImage> requestWorldViewCacheOrCreate(EMapCacheType type, std::shared_ptr<IImage> fullSurface);
 	};
 
 	/// helper struct to pass around resolved bitmaps of an object; images can be nullptr if object doesn't have bitmap of that type
 	struct AnimBitmapHolder
 	{
-		IImage * objBitmap; // main object bitmap
-		IImage * flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
+		std::shared_ptr<IImage> objBitmap; // main object bitmap
+		std::shared_ptr<IImage> flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
 		bool isMoving; // indicates if the object is moving (again, heroes/boats only)
 
-		AnimBitmapHolder(IImage * objBitmap_ = nullptr, IImage * flagBitmap_ = nullptr, bool moving = false)
+		AnimBitmapHolder(std::shared_ptr<IImage> objBitmap_ = nullptr, std::shared_ptr<IImage> flagBitmap_ = nullptr, bool moving = false)
 			: objBitmap(objBitmap_),
 			  flagBitmap(flagBitmap_),
 			  isMoving(moving)
@@ -202,7 +202,7 @@ class CMapHandler
 		const MapDrawingInfo * info; // data for drawing passed from outside
 
 		/// general drawing method, called internally by more specialized ones
-		virtual void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0;
+		virtual void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const = 0;
 
 		// first drawing pass
 
@@ -214,8 +214,8 @@ class CMapHandler
 		virtual void drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const;
 		/// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
 		virtual void drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const;
-		virtual void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const;
-		virtual void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const;
+		virtual void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const;
+		virtual void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const;
 
 		// second drawing pass
 
@@ -249,10 +249,10 @@ class CMapHandler
 		// internal helper methods to choose correct bitmap(s) for object; called internally by findObjectBitmap
 		AnimBitmapHolder findHeroBitmap(const CGHeroInstance * hero, int anim) const;
 		AnimBitmapHolder findBoatBitmap(const CGBoat * hero, int anim) const;
-		IImage * findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
-		IImage * findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
-		IImage * findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const;
-		IImage * findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const;
+		std::shared_ptr<IImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
+		std::shared_ptr<IImage> findHeroFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor * color, int group) const;
+		std::shared_ptr<IImage> findBoatFlagBitmap(const CGBoat * obj, int anim, const PlayerColor * color, int group, ui8 dir) const;
+		std::shared_ptr<IImage> findFlagBitmapInternal(std::shared_ptr<CAnimation> animation, int anim, int group, ui8 dir, bool moving) const;
 
 	public:
 		CMapBlitter(CMapHandler * p);
@@ -265,7 +265,7 @@ class CMapHandler
 	class CMapNormalBlitter : public CMapBlitter
 	{
 	protected:
-		void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
+		void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
 		void drawTileOverlay(SDL_Surface * targetSurf,const TerrainTile2 & tile) const override {}
 		void init(const MapDrawingInfo * info) override;
 		SDL_Rect clip(SDL_Surface * targetSurf) const override;
@@ -277,12 +277,12 @@ class CMapHandler
 	class CMapWorldViewBlitter : public CMapBlitter
 	{
 	private:
-		IImage * objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
+		std::shared_ptr<IImage> objectToIcon(Obj id, si32 subId, PlayerColor owner) const;
 	protected:
-		void drawElement(EMapCacheType cacheType, const IImage * source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
+		void drawElement(EMapCacheType cacheType, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Surface * targetSurf, SDL_Rect * destRect) const override;
 		void drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const override;
-		void drawHeroFlag(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
-		void drawObject(SDL_Surface * targetSurf, const IImage * source, SDL_Rect * sourceRect, bool moving) const override;
+		void drawHeroFlag(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
+		void drawObject(SDL_Surface * targetSurf, std::shared_ptr<IImage> source, SDL_Rect * sourceRect, bool moving) const override;
 		void drawFrame(SDL_Surface * targetSurf) const override {}
 		void drawOverlayEx(SDL_Surface * targetSurf) override;
 		void init(const MapDrawingInfo * info) override;
@@ -347,7 +347,7 @@ public:
 
 	//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
 	typedef std::vector<std::array<std::shared_ptr<CAnimation>, 4>> TFlippedAnimations; //[type, rotation]
-	typedef std::vector<std::vector<std::array<IImage *, 4>>> TFlippedCache;//[type, view type, rotation]
+	typedef std::vector<std::vector<std::array<std::shared_ptr<IImage>, 4>>> TFlippedCache;//[type, view type, rotation]
 
 	TFlippedAnimations terrainAnimations;//[terrain type, rotation]
 	TFlippedCache terrainImages;//[terrain type, view type, rotation]
@@ -359,14 +359,14 @@ public:
 	TFlippedCache riverImages;//[river type, view type, rotation]
 
 	//Fog of War cache (not owned)
-	std::vector<const IImage *> FoWfullHide;
+	std::vector<std::shared_ptr<IImage>> FoWfullHide;
 	std::vector<std::vector<std::vector<ui8> > > hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile
 
-	std::vector<const IImage *> FoWpartialHide;
+	std::vector<std::shared_ptr<IImage>> FoWpartialHide;
 
 	//edge graphics
 	std::unique_ptr<CAnimation> egdeAnimation;
-	std::vector<const IImage *> egdeImages;//cache of links to egdeAnimation (for faster access)
+	std::vector<std::shared_ptr<IImage>> egdeImages;//cache of links to egdeAnimation (for faster access)
 	PseudoV< PseudoV< PseudoV <ui8> > > edgeFrames; //frame indexes (in egdeImages) of tile outside of map
 
 	mutable std::map<const CGObjectInstance*, ui8> animationPhase;

+ 234 - 248
client/widgets/AdventureMapClasses.cpp

@@ -48,18 +48,16 @@
 #include "../../lib/NetPacksBase.h"
 #include "../../lib/StringConstants.h"
 
-CList::CListItem::CListItem(CList * Parent):
-	CIntObject(LCLICK | RCLICK | HOVER),
+CList::CListItem::CListItem(CList * Parent)
+	: CIntObject(LCLICK | RCLICK | HOVER),
 	parent(Parent),
-	selection(nullptr)
+	selection()
 {
+	defActions = 255-DISPOSE;
 }
 
 CList::CListItem::~CListItem()
 {
-	// select() method in this was already destroyed so we can't safely call method in parent
-	if (parent->selected == this)
-		parent->selected = nullptr;
 }
 
 void CList::CListItem::clickRight(tribool down, bool previousState)
@@ -70,15 +68,17 @@ void CList::CListItem::clickRight(tribool down, bool previousState)
 
 void CList::CListItem::clickLeft(tribool down, bool previousState)
 {
-	if (down == true)
+	if(down == true)
 	{
 		//second click on already selected item
-		if (parent->selected == this)
+		if(parent->selected == this->shared_from_this())
+		{
 			open();
+		}
 		else
 		{
 			//first click - switch selection
-			parent->select(this);
+			parent->select(this->shared_from_this());
 		}
 	}
 }
@@ -93,53 +93,54 @@ void CList::CListItem::hover(bool on)
 
 void CList::CListItem::onSelect(bool on)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	vstd::clear_pointer(selection);
-	if (on)
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	selection.reset();
+	if(on)
 		selection = genSelection();
 	select(on);
 	GH.totalRedraw();
 }
 
-CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount,
-			 int helpUp, int helpDown, CListBox::CreateFunc create, CListBox::DestroyFunc destroy):
-	CIntObject(0, position),
+CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create)
+	: CIntObject(0, position),
 	size(Size),
 	selected(nullptr)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	scrollUp = new CButton(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]);
-	list = new CListBox(create, destroy, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	scrollUp = std::make_shared<CButton>(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]);
+	scrollDown = std::make_shared<CButton>(Point(0, scrollUp->pos.h + 32*size), btnDown, CGI->generaltexth->zelp[helpDown]);
+
+	listBox = std::make_shared<CListBox>(create, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
 
 	//assign callback only after list was created
-	scrollUp->addCallback(std::bind(&CListBox::moveToPrev, list));
-	scrollDown = new CButton(Point(0, scrollUp->pos.h + 32*size), btnDown, CGI->generaltexth->zelp[helpDown], std::bind(&CListBox::moveToNext, list));
+	scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
+	scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox));
 
-	scrollDown->addCallback(std::bind(&CList::update, this));
 	scrollUp->addCallback(std::bind(&CList::update, this));
+	scrollDown->addCallback(std::bind(&CList::update, this));
 
 	update();
 }
 
 void CList::update()
 {
-	bool onTop = list->getPos() == 0;
-	bool onBottom = list->getPos() + size >= list->size();
+	bool onTop = listBox->getPos() == 0;
+	bool onBottom = listBox->getPos() + size >= listBox->size();
 
 	scrollUp->block(onTop);
 	scrollDown->block(onBottom);
 }
 
-void CList::select(CListItem *which)
+void CList::select(std::shared_ptr<CListItem> which)
 {
-	if (selected == which)
+	if(selected == which)
 		return;
 
-	if (selected)
+	if(selected)
 		selected->onSelect(false);
 
 	selected = which;
-	if (which)
+	if(which)
 	{
 		which->onSelect(true);
 		onSelect();
@@ -148,28 +149,28 @@ void CList::select(CListItem *which)
 
 int CList::getSelectedIndex()
 {
-	return list->getIndexOf(selected);
+	return listBox->getIndexOf(selected);
 }
 
 void CList::selectIndex(int which)
 {
-	if (which < 0)
+	if(which < 0)
 	{
-		if (selected)
+		if(selected)
 			select(nullptr);
 	}
 	else
 	{
-		list->scrollTo(which);
+		listBox->scrollTo(which);
 		update();
-		select(dynamic_cast<CListItem*>(list->getItem(which)));
+		select(std::dynamic_pointer_cast<CListItem>(listBox->getItem(which)));
 	}
 }
 
 void CList::selectNext()
 {
 	int index = getSelectedIndex() + 1;
-	if (index >= list->size())
+	if(index >= listBox->size())
 		index = 0;
 	selectIndex(index);
 }
@@ -177,7 +178,7 @@ void CList::selectNext()
 void CList::selectPrev()
 {
 	int index = getSelectedIndex();
-	if (index <= 0)
+	if(index <= 0)
 		selectIndex(0);
 	else
 		selectIndex(index-1);
@@ -185,23 +186,23 @@ void CList::selectPrev()
 
 CHeroList::CEmptyHeroItem::CEmptyHeroItem()
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	auto move = new CAnimImage("IMOBIL", 0, 0, 0, 1);
-	auto img  = new CPicture("HPSXXX", move->pos.w + 1);
-	auto mana = new CAnimImage("IMANA", 0, 0, move->pos.w + img->pos.w + 2, 1 );
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
+	portrait = std::make_shared<CPicture>("HPSXXX", movement->pos.w + 1);
+	mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
 
 	pos.w = mana->pos.w + mana->pos.x - pos.x;
-	pos.h = std::max(std::max<SDLX_Size>(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
+	pos.h = std::max(std::max<SDLX_Size>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
 }
 
-CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero):
-	CListItem(parent),
+CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
+	: CListItem(parent),
 	hero(Hero)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	movement = new CAnimImage("IMOBIL", 0, 0, 0, 1);
-	portrait = new CAnimImage("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1);
-	mana     = new CAnimImage("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
+	portrait = std::make_shared<CAnimImage>("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1);
+	mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
 
 	pos.w = mana->pos.w + mana->pos.x - pos.x;
 	pos.h = std::max(std::max<SDLX_Size>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
@@ -216,15 +217,15 @@ void CHeroList::CHeroItem::update()
 	redraw();
 }
 
-CIntObject * CHeroList::CHeroItem::genSelection()
+std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
 {
-	return new CPicture("HPSYYY", movement->pos.w + 1);
+	return std::make_shared<CPicture>("HPSYYY", movement->pos.w + 1);
 }
 
 void CHeroList::CHeroItem::select(bool on)
 {
-	if (on && adventureInt->selection != hero)
-			adventureInt->select(hero);
+	if(on && adventureInt->selection != hero)
+		adventureInt->select(hero);
 }
 
 void CHeroList::CHeroItem::open()
@@ -242,11 +243,11 @@ std::string CHeroList::CHeroItem::getHoverText()
 	return boost::str(boost::format(CGI->generaltexth->allTexts[15]) % hero->name % hero->type->heroClass->name);
 }
 
-CIntObject * CHeroList::createHeroItem(size_t index)
+std::shared_ptr<CIntObject> CHeroList::createHeroItem(size_t index)
 {
 	if (LOCPLINT->wanderingHeroes.size() > index)
-		return new CHeroItem(this, LOCPLINT->wanderingHeroes[index]);
-	return new CEmptyHeroItem();
+		return std::make_shared<CHeroItem>(this, LOCPLINT->wanderingHeroes[index]);
+	return std::make_shared<CEmptyHeroItem>();
 }
 
 CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
@@ -262,10 +263,10 @@ void CHeroList::select(const CGHeroInstance * hero)
 void CHeroList::update(const CGHeroInstance * hero)
 {
 	//this hero is already present, update its status
-	for (auto & elem : list->getItems())
+	for(auto & elem : listBox->getItems())
 	{
-		auto item = dynamic_cast<CHeroItem*>(elem);
-		if (item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
+		auto item = std::dynamic_pointer_cast<CHeroItem>(elem);
+		if(item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
 		{
 			item->update();
 			return;
@@ -273,7 +274,7 @@ void CHeroList::update(const CGHeroInstance * hero)
 	}
 	//simplest solution for now: reset list and restore selection
 
-	list->resize(LOCPLINT->wanderingHeroes.size());
+	listBox->resize(LOCPLINT->wanderingHeroes.size());
 	if (adventureInt->selection)
 	{
 		auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
@@ -283,26 +284,26 @@ void CHeroList::update(const CGHeroInstance * hero)
 	CList::update();
 }
 
-CIntObject * CTownList::createTownItem(size_t index)
+std::shared_ptr<CIntObject> CTownList::createTownItem(size_t index)
 {
 	if (LOCPLINT->towns.size() > index)
-		return new CTownItem(this, LOCPLINT->towns[index]);
-	return new CAnimImage("ITPA", 0);
+		return std::make_shared<CTownItem>(this, LOCPLINT->towns[index]);
+	return std::make_shared<CAnimImage>("ITPA", 0);
 }
 
 CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
 	CListItem(parent),
 	town(Town)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	picture = new CAnimImage("ITPA", 0);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	picture = std::make_shared<CAnimImage>("ITPA", 0);
 	pos = picture->pos;
 	update();
 }
 
-CIntObject * CTownList::CTownItem::genSelection()
+std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
 {
-	return new CAnimImage("ITPA", 1);
+	return std::make_shared<CAnimImage>("ITPA", 1);
 }
 
 void CTownList::CTownItem::update()
@@ -348,7 +349,7 @@ void CTownList::update(const CGTownInstance *)
 {
 	//simplest solution for now: reset list and restore selection
 
-	list->resize(LOCPLINT->towns.size());
+	listBox->resize(LOCPLINT->towns.size());
 	if (adventureInt->selection)
 	{
 		auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
@@ -475,7 +476,7 @@ CMinimapInstance::~CMinimapInstance()
 	SDL_FreeSurface(minimap);
 }
 
-void CMinimapInstance::showAll(SDL_Surface *to)
+void CMinimapInstance::showAll(SDL_Surface * to)
 {
 	blitAtLoc(minimap, 0, 0, to);
 
@@ -484,7 +485,7 @@ void CMinimapInstance::showAll(SDL_Surface *to)
 	for(auto & hero : heroes)
 	{
 		int3 position = hero->getPosition(false);
-		if (position.z == level)
+		if(position.z == level)
 		{
 			const SDL_Color & color = graphics->playerColors[hero->getOwner().getNum()];
 			blitTileWithColor(color, position, to, pos.x, pos.y);
@@ -531,15 +532,17 @@ std::map<int, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors(std::string
 	return ret;
 }
 
-CMinimap::CMinimap(const Rect &position):
-	CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
-	aiShield(nullptr),
-	minimap(nullptr),
+CMinimap::CMinimap(const Rect & position)
+	: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
 	level(0),
 	colors(loadColors("config/terrains.json"))
 {
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	pos.w = position.w;
 	pos.h = position.h;
+
+	aiShield = std::make_shared<CPicture>("AIShield");
+	aiShield->disable();
 }
 
 int3 CMinimap::translateMousePosition()
@@ -567,7 +570,7 @@ void CMinimap::moveAdvMapSelection()
 
 void CMinimap::clickLeft(tribool down, bool previousState)
 {
-	if (down)
+	if(down)
 		moveAdvMapSelection();
 }
 
@@ -578,7 +581,7 @@ void CMinimap::clickRight(tribool down, bool previousState)
 
 void CMinimap::hover(bool on)
 {
-	if (on)
+	if(on)
 		GH.statusbar->setText(CGI->generaltexth->zelp[291].first);
 	else
 		GH.statusbar->clear();
@@ -593,7 +596,7 @@ void CMinimap::mouseMoved(const SDL_MouseMotionEvent & sEvent)
 void CMinimap::showAll(SDL_Surface * to)
 {
 	CIntObject::showAll(to);
-	if (minimap)
+	if(minimap)
 	{
 		int3 mapSizes = LOCPLINT->cb->getMapSize();
 		int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
@@ -608,13 +611,13 @@ void CMinimap::showAll(SDL_Surface * to)
 			ui16(tileCountOnScreen.y * pos.h / mapSizes.y)
 		};
 
-		if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
+		if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
 		{
 			// adjusts radar so that it doesn't go out of map in world view mode (since there's no frame)
 			radar.x = std::min<int>(std::max(pos.x, radar.x), pos.x + pos.w - radar.w);
 			radar.y = std::min<int>(std::max(pos.y, radar.y), pos.y + pos.h - radar.h);
 
-			if (radar.x < pos.x && radar.y < pos.y)
+			if(radar.x < pos.x && radar.y < pos.y)
 				return; // whole map is visible at once, no point in redrawing border
 		}
 
@@ -627,12 +630,11 @@ void CMinimap::showAll(SDL_Surface * to)
 
 void CMinimap::update()
 {
-	if (aiShield) //AI turn is going on. There is no need to update minimap
+	if(aiShield->recActions & UPDATE) //AI turn is going on. There is no need to update minimap
 		return;
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	vstd::clear_pointer(minimap);
-	minimap = new CMinimapInstance(this, level);
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	minimap = std::make_shared<CMinimapInstance>(this, level);
 	redraw();
 }
 
@@ -644,16 +646,14 @@ void CMinimap::setLevel(int newLevel)
 
 void CMinimap::setAIRadar(bool on)
 {
-	if (on)
+	if(on)
 	{
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		vstd::clear_pointer(minimap);
-		if (!aiShield)
-			aiShield = new CPicture("AIShield");
+		aiShield->enable();
+		minimap.reset();
 	}
 	else
 	{
-		vstd::clear_pointer(aiShield);
+		aiShield->disable();
 		update();
 	}
 	// this my happen during AI turn when this interface is inactive
@@ -663,123 +663,98 @@ void CMinimap::setAIRadar(bool on)
 
 void CMinimap::hideTile(const int3 &pos)
 {
-	if (minimap)
+	if(minimap)
 		minimap->refreshTile(pos);
 }
 
 void CMinimap::showTile(const int3 &pos)
 {
-	if (minimap)
+	if(minimap)
 		minimap->refreshTile(pos);
 }
 
-CInfoBar::CVisibleInfo::CVisibleInfo(Point position):
-	CIntObject(0, position),
-	aiProgress(nullptr)
+CInfoBar::CVisibleInfo::CVisibleInfo()
+	: CIntObject(0, Point(8, 12))
 {
-
 }
 
-void CInfoBar::CVisibleInfo::show(SDL_Surface *to)
+void CInfoBar::CVisibleInfo::show(SDL_Surface * to)
 {
 	CIntObject::show(to);
 	for(auto object : forceRefresh)
 		object->showAll(to);
 }
 
-void CInfoBar::CVisibleInfo::loadHero(const CGHeroInstance * hero)
-{
-	assert(children.empty()); // visible info should be re-created to change type
-
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CPicture("ADSTATHR");
-	new CHeroTooltip(Point(0,0), hero);
-}
-
-void CInfoBar::CVisibleInfo::loadTown(const CGTownInstance *town)
+CInfoBar::EmptyVisibleInfo::EmptyVisibleInfo()
 {
-	assert(children.empty()); // visible info should be re-created to change type
-
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CPicture("ADSTATCS");
-	new CTownTooltip(Point(0,0), town);
 }
 
-void CInfoBar::CVisibleInfo::playNewDaySound()
+CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero)
 {
-	if (LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week
-		CCS->soundh->playSound(soundBase::newDay);
-	else
-	if (LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month
-		CCS->soundh->playSound(soundBase::newWeek);
-	else
-	if (LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month
-		CCS->soundh->playSound(soundBase::newMonth);
-	else
-		CCS->soundh->playSound(soundBase::newDay);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CPicture>("ADSTATHR");
+	heroTooltip = std::make_shared<CHeroTooltip>(Point(0,0), hero);
 }
 
-std::string CInfoBar::CVisibleInfo::getNewDayName()
+CInfoBar::VisibleTownInfo::VisibleTownInfo(const CGTownInstance * town)
 {
-	if (LOCPLINT->cb->getDate(Date::DAY) == 1)
-		return "NEWDAY";
-
-	if (LOCPLINT->cb->getDate(Date::DAY) != 1)
-		return "NEWDAY";
-
-	switch(LOCPLINT->cb->getDate(Date::WEEK))
-	{
-	case 1:  return "NEWWEEK1";
-	case 2:  return "NEWWEEK2";
-	case 3:  return "NEWWEEK3";
-	case 4:  return "NEWWEEK4";
-	default: assert(0); return "";
-	}
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CPicture>("ADSTATCS");
+	townTooltip = std::make_shared<CTownTooltip>(Point(0,0), town);
 }
 
-void CInfoBar::CVisibleInfo::loadDay()
+CInfoBar::VisibleDateInfo::VisibleDateInfo()
 {
-	assert(children.empty()); // visible info should be re-created first to change type
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	playNewDaySound();
-
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CShowableAnim(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE);
+	animation = std::make_shared<CShowableAnim>(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE);
 
 	std::string labelText;
-	if (LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) == 1 && LOCPLINT->cb->getDate(Date::DAY) != 1) // monday of any week but first - show new week info
+	if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) == 1 && LOCPLINT->cb->getDate(Date::DAY) != 1) // monday of any week but first - show new week info
 		labelText = CGI->generaltexth->allTexts[63] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK));
 	else
 		labelText = CGI->generaltexth->allTexts[64] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK));
 
-	forceRefresh.push_back(new CLabel(95, 31, FONT_MEDIUM, CENTER, Colors::WHITE, labelText));
+	label = std::make_shared<CLabel>(95, 31, FONT_MEDIUM, CENTER, Colors::WHITE, labelText);
+
+	forceRefresh.push_back(label);
 }
 
-void CInfoBar::CVisibleInfo::loadEnemyTurn(PlayerColor player)
+std::string CInfoBar::VisibleDateInfo::getNewDayName()
 {
-	assert(children.empty()); // visible info should be re-created to change type
+	if(LOCPLINT->cb->getDate(Date::DAY) == 1)
+		return "NEWDAY";
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CPicture("ADSTATNX");
-	new CAnimImage("CREST58", player.getNum(), 0, 20, 51);
-	new CShowableAnim(99, 51, "HOURSAND");
+	if(LOCPLINT->cb->getDate(Date::DAY) != 1)
+		return "NEWDAY";
 
-	// FIXME: currently there is no way to get progress from VCAI
-	// if this will change at some point switch this ifdef to enable correct code
-#if 0
-	//prepare hourglass for updating AI turn
-	aiProgress = new CAnimImage("HOURGLAS", 0, 0, 99, 51);
-	forceRefresh.push_back(aiProgress);
-#else
-	//create hourglass that will be always animated ignoring AI status
-	new CShowableAnim(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 40);
-#endif
+	switch(LOCPLINT->cb->getDate(Date::WEEK))
+	{
+	case 1:
+		return "NEWWEEK1";
+	case 2:
+		return "NEWWEEK2";
+	case 3:
+		return "NEWWEEK3";
+	case 4:
+		return "NEWWEEK4";
+	default:
+		return "";
+	}
 }
 
-void CInfoBar::CVisibleInfo::loadGameStatus()
+CInfoBar::VisibleEnemyTurnInfo::VisibleEnemyTurnInfo(PlayerColor player)
 {
-	assert(children.empty()); // visible info should be re-created to change type
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CPicture>("ADSTATNX");
+	banner = std::make_shared<CAnimImage>("CREST58", player.getNum(), 0, 20, 51);
+	sand = std::make_shared<CShowableAnim>(99, 51, "HOURSAND");
+	glass = std::make_shared<CShowableAnim>(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 40);
+}
 
+CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
+{
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	//get amount of halls of each level
 	std::vector<int> halls(4, 0);
 	for(auto town : LOCPLINT->towns)
@@ -797,83 +772,84 @@ void CInfoBar::CVisibleInfo::loadGameStatus()
 	{
 		if(LOCPLINT->cb->getPlayerStatus(PlayerColor(i), false) == EPlayerStatus::INGAME)
 		{
-			if (LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, PlayerColor(i)) != PlayerRelations::ENEMIES)
+			if(LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, PlayerColor(i)) != PlayerRelations::ENEMIES)
 				allies.push_back(PlayerColor(i));
 			else
 				enemies.push_back(PlayerColor(i));
 		}
 	}
 
-	//generate component
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CPicture("ADSTATIN");
-	auto allyLabel  = new CLabel(10, 106, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":");
-	auto enemyLabel = new CLabel(10, 136, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":");
+	//generate widgets
+	background = std::make_shared<CPicture>("ADSTATIN");
+	allyLabel = std::make_shared<CLabel>(10, 106, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":");
+	enemyLabel = std::make_shared<CLabel>(10, 136, FONT_SMALL, TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":");
 
 	int posx = allyLabel->pos.w + allyLabel->pos.x - pos.x + 4;
 	for(PlayerColor & player : allies)
 	{
-		auto image = new CAnimImage("ITGFLAGS", player.getNum(), 0, posx, 102);
+		auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 102);
 		posx += image->pos.w;
+		flags.push_back(image);
 	}
 
 	posx = enemyLabel->pos.w + enemyLabel->pos.x - pos.x + 4;
 	for(PlayerColor & player : enemies)
 	{
-		auto image = new CAnimImage("ITGFLAGS", player.getNum(), 0, posx, 132);
+		auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 132);
 		posx += image->pos.w;
+		flags.push_back(image);
 	}
 
-	for (size_t i=0; i<halls.size(); i++)
+	for(size_t i=0; i<halls.size(); i++)
 	{
-		new CAnimImage("itmtl", i, 0, 6 + 42 * i , 11);
-		if (halls[i])
-			new CLabel( 26 + 42 * i, 64, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(halls[i]));
+		hallIcons.push_back(std::make_shared<CAnimImage>("itmtl", i, 0, 6 + 42 * i , 11));
+		if(halls[i])
+			hallLabels.push_back(std::make_shared<CLabel>( 26 + 42 * i, 64, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(halls[i])));
 	}
 }
 
-void CInfoBar::CVisibleInfo::loadComponent(const Component & compToDisplay, std::string message)
+CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const Component & compToDisplay, std::string message)
 {
-	assert(children.empty()); // visible info should be re-created to change type
-
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	new CPicture("ADSTATOT", 1);
+	background = std::make_shared<CPicture>("ADSTATOT", 1);
 
-	auto   comp = new CComponent(compToDisplay);
+	comp = std::make_shared<CComponent>(compToDisplay);
 	comp->moveTo(Point(pos.x+47, pos.y+50));
 
-	new CTextBox(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, CENTER, Colors::WHITE);
+	text = std::make_shared<CTextBox>(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, CENTER, Colors::WHITE);
 }
 
-void CInfoBar::CVisibleInfo::updateEnemyTurn(double progress)
+void CInfoBar::playNewDaySound()
 {
-	if (aiProgress)
-	aiProgress->setFrame((aiProgress->size() - 1) * progress);
+	if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week
+		CCS->soundh->playSound(soundBase::newDay);
+	else if(LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month
+		CCS->soundh->playSound(soundBase::newWeek);
+	else if(LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month
+		CCS->soundh->playSound(soundBase::newMonth);
+	else
+		CCS->soundh->playSound(soundBase::newDay);
 }
 
-void CInfoBar::reset(EState newState = EMPTY)
+void CInfoBar::reset()
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-
-	vstd::clear_pointer(visibleInfo);
-	currentObject = nullptr;
-	state = newState;
-	visibleInfo = new CVisibleInfo(Point(8, 12));
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	state = EMPTY;
+	visibleInfo = std::make_shared<EmptyVisibleInfo>();
 }
 
 void CInfoBar::showSelection()
 {
-	if (adventureInt->selection)
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	if(adventureInt->selection)
 	{
-		auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
-		if (hero)
+		if(auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
 		{
 			showHeroSelection(hero);
 			return;
 		}
-		auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
-		if (town)
+		else if(auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection))
 		{
 			showTownSelection(town);
 			return;
@@ -891,11 +867,11 @@ void CInfoBar::tick()
 
 void CInfoBar::clickLeft(tribool down, bool previousState)
 {
-	if (down)
+	if(down)
 	{
-		if (state == HERO || state == TOWN)
+		if(state == HERO || state == TOWN)
 			showGameStatus();
-		else if (state == GAME)
+		else if(state == GAME)
 			showDate();
 		else
 			showSelection();
@@ -909,83 +885,96 @@ void CInfoBar::clickRight(tribool down, bool previousState)
 
 void CInfoBar::hover(bool on)
 {
-	if (on)
+	if(on)
 		GH.statusbar->setText(CGI->generaltexth->zelp[292].first);
 	else
 		GH.statusbar->clear();
 }
 
-CInfoBar::CInfoBar(const Rect &position):
-	CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
-	visibleInfo(nullptr),
-	state(EMPTY),
-	currentObject(nullptr)
+CInfoBar::CInfoBar(const Rect & position)
+	: CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
+	state(EMPTY)
 {
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	pos.w = position.w;
 	pos.h = position.h;
-	//FIXME: enable some mode? Should be done by advMap::select() when game starts but just in case?
+	reset();
 }
 
 void CInfoBar::showDate()
 {
-	reset(DATE);
-	visibleInfo->loadDay();
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	playNewDaySound();
+	state = DATE;
+	visibleInfo = std::make_shared<VisibleDateInfo>();
 	setTimer(3000);
 	redraw();
 }
 
 void CInfoBar::showComponent(const Component & comp, std::string message)
 {
-	reset(COMPONENT);
-	visibleInfo->loadComponent(comp, message);
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	state = COMPONENT;
+	visibleInfo = std::make_shared<VisibleComponentInfo>(comp, message);
 	setTimer(3000);
 	redraw();
 }
 
 void CInfoBar::startEnemyTurn(PlayerColor color)
 {
-	reset(AITURN);
-	visibleInfo->loadEnemyTurn(color);
-	redraw();
-}
-
-void CInfoBar::updateEnemyTurn(double progress)
-{
-	assert(state == AITURN);
-	visibleInfo->updateEnemyTurn(progress);
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	state = AITURN;
+	visibleInfo = std::make_shared<VisibleEnemyTurnInfo>(color);
 	redraw();
 }
 
 void CInfoBar::showHeroSelection(const CGHeroInstance * hero)
 {
-	if (!hero)
-		return;
-
-	reset(HERO);
-	currentObject = hero;
-	visibleInfo->loadHero(hero);
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	if(!hero)
+	{
+		reset();
+	}
+	else
+	{
+		state = HERO;
+		visibleInfo = std::make_shared<VisibleHeroInfo>(hero);
+	}
 	redraw();
 }
 
 void CInfoBar::showTownSelection(const CGTownInstance * town)
 {
-	if (!town)
-		return;
-
-	reset(TOWN);
-	currentObject = town;
-	visibleInfo->loadTown(town);
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	if(!town)
+	{
+		reset();
+	}
+	else
+	{
+		state = TOWN;
+		visibleInfo = std::make_shared<VisibleTownInfo>(town);
+	}
 	redraw();
 }
 
 void CInfoBar::showGameStatus()
 {
-	reset(GAME);
-	visibleInfo->loadGameStatus();
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	state = GAME;
+	visibleInfo = std::make_shared<VisibleGameStatusInfo>();
 	setTimer(3000);
 	redraw();
 }
 
+CInGameConsole::CInGameConsole()
+	: CIntObject(KEYBOARD | TEXTINPUT),
+	prevEntDisp(-1),
+	defaultTimeout(10000),
+	maxDisplayedTexts(10)
+{
+}
+
 void CInGameConsole::show(SDL_Surface * to)
 {
 	int number = 0;
@@ -1207,11 +1196,6 @@ void CInGameConsole::refreshEnteredText()
 	}
 }
 
-CInGameConsole::CInGameConsole() : prevEntDisp(-1), defaultTimeout(10000), maxDisplayedTexts(10)
-{
-	addUsedEvents(KEYBOARD | TEXTINPUT);
-}
-
 CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
 	: CIntObject(),
 	  background(bg)
@@ -1233,32 +1217,34 @@ CAdvMapPanel::~CAdvMapPanel()
 		SDL_FreeSurface(background);
 }
 
-void CAdvMapPanel::addChildColorableButton(CButton * btn)
+void CAdvMapPanel::addChildColorableButton(std::shared_ptr<CButton> button)
 {
-	buttons.push_back(btn);
-	addChildToPanel(btn, ACTIVATE | DEACTIVATE);
+	colorableButtons.push_back(button);
+	addChildToPanel(button, ACTIVATE | DEACTIVATE);
 }
 
 void CAdvMapPanel::setPlayerColor(const PlayerColor & clr)
 {
-	for (auto &btn : buttons)
+	for(auto & button : colorableButtons)
 	{
-		btn->setPlayerColor(clr);
+		button->setPlayerColor(clr);
 	}
 }
 
 void CAdvMapPanel::showAll(SDL_Surface * to)
 {
-	if (background)
+	if(background)
 		blitAt(background, pos.x, pos.y, to);
 
 	CIntObject::showAll(to);
 }
 
-void CAdvMapPanel::addChildToPanel(CIntObject * obj, ui8 actions)
+void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
 {
+	otherObjects.push_back(obj);
 	obj->recActions |= actions | SHOWALL;
-	addChild(obj, false);
+	obj->recActions &= ~DISPOSE;
+	addChild(obj.get(), false);
 }
 
 CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color)
@@ -1280,7 +1266,7 @@ CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel()
 		SDL_FreeSurface(tmpBackgroundFiller);
 }
 
-void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffset)
+void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset)
 {
 	assert(iconsData.size() == currentIcons.size());
 
@@ -1290,9 +1276,9 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffs
 		currentIcons[idx]->setFrame(data.first + indexOffset);
 	}
 
-	if (fillerHeight > 0)
+	if(fillerHeight > 0)
 	{
-		if (tmpBackgroundFiller)
+		if(tmpBackgroundFiller)
 			SDL_FreeSurface(tmpBackgroundFiller);
 		tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color);
 	}
@@ -1300,9 +1286,9 @@ void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, int indexOffs
 
 void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 	iconsData.push_back(data);
-	currentIcons.push_back(new CAnimImage(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
+	currentIcons.push_back(std::make_shared<CAnimImage>(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
 }
 
 void CAdvMapWorldViewPanel::showAll(SDL_Surface * to)

+ 101 - 59
client/widgets/AdventureMapClasses.h

@@ -22,18 +22,22 @@ class CGHeroInstance;
 class CGTownInstance;
 class CButton;
 struct Component;
+class CComponent;
 struct InfoAboutArmy;
 struct InfoAboutHero;
 struct InfoAboutTown;
+class CHeroTooltip;
+class CTownTooltip;
+class CTextBox;
 
 /// Base UI Element for hero\town lists
 class CList : public CIntObject
 {
 protected:
-	class CListItem : public CIntObject
+	class CListItem : public CIntObject, public std::enable_shared_from_this<CListItem>
 	{
 		CList * parent;
-		CIntObject * selection;
+		std::shared_ptr<CIntObject> selection;
 	public:
 		CListItem(CList * parent);
 		~CListItem();
@@ -44,7 +48,7 @@ protected:
 		void onSelect(bool on);
 
 		/// create object with selection rectangle
-		virtual CIntObject * genSelection()=0;
+		virtual std::shared_ptr<CIntObject> genSelection()=0;
 		/// reaction on item selection (e.g. enable selection border)
 		/// NOTE: item may be deleted in selected state
 		virtual void select(bool on)=0;
@@ -56,7 +60,7 @@ protected:
 		virtual std::string getHoverText()=0;
 	};
 
-	CListBox * list;
+	std::shared_ptr<CListBox> listBox;
 	const size_t size;
 
 	/**
@@ -71,22 +75,20 @@ protected:
 	 * @param create - function for creating items in listbox
 	 * @param destroy - function for deleting items in listbox
 	 */
-	CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown,
-		  CListBox::CreateFunc create, CListBox::DestroyFunc destroy = CListBox::DestroyFunc());
+	CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create);
 
 	//for selection\deselection
-	CListItem *selected;
-	void select(CListItem * which);
+	std::shared_ptr<CListItem> selected;
+	void select(std::shared_ptr<CListItem> which);
 	friend class CListItem;
 
+	std::shared_ptr<CButton> scrollUp;
+	std::shared_ptr<CButton> scrollDown;
+
 	/// should be called when list is invalidated
 	void update();
 
 public:
-
-	CButton * scrollUp;
-	CButton * scrollDown;
-
 	/// functions that will be called when selection changes
 	CFunctionList<void()> onSelect;
 
@@ -105,21 +107,24 @@ class CHeroList	: public CList
 	/// Empty hero item used as placeholder for unused entries in list
 	class CEmptyHeroItem : public CIntObject
 	{
+		std::shared_ptr<CAnimImage> movement;
+		std::shared_ptr<CAnimImage> mana;
+		std::shared_ptr<CPicture> portrait;
 	public:
 		CEmptyHeroItem();
 	};
 
 	class CHeroItem : public CListItem
 	{
-		CAnimImage * movement;
-		CAnimImage * mana;
-		CAnimImage * portrait;
+		std::shared_ptr<CAnimImage> movement;
+		std::shared_ptr<CAnimImage> mana;
+		std::shared_ptr<CAnimImage> portrait;
 	public:
 		const CGHeroInstance * const hero;
 
-		CHeroItem(CHeroList *parent, const CGHeroInstance * hero);
+		CHeroItem(CHeroList * parent, const CGHeroInstance * hero);
 
-		CIntObject * genSelection() override;
+		std::shared_ptr<CIntObject> genSelection() override;
 		void update();
 		void select(bool on) override;
 		void open() override;
@@ -127,7 +132,7 @@ class CHeroList	: public CList
 		std::string getHoverText() override;
 	};
 
-	CIntObject * createHeroItem(size_t index);
+	std::shared_ptr<CIntObject> createHeroItem(size_t index);
 public:
 	/**
 	 * @brief CHeroList
@@ -147,13 +152,13 @@ class CTownList	: public CList
 {
 	class CTownItem : public CListItem
 	{
-		CAnimImage * picture;
+		std::shared_ptr<CAnimImage> picture;
 	public:
 		const CGTownInstance * const town;
 
 		CTownItem(CTownList *parent, const CGTownInstance * town);
 
-		CIntObject * genSelection() override;
+		std::shared_ptr<CIntObject> genSelection() override;
 		void update();
 		void select(bool on) override;
 		void open() override;
@@ -161,7 +166,7 @@ class CTownList	: public CList
 		std::string getHoverText() override;
 	};
 
-	CIntObject * createTownItem(size_t index);
+	std::shared_ptr<CIntObject> createTownItem(size_t index);
 public:
 	/**
 	 * @brief CTownList
@@ -180,14 +185,14 @@ class CMinimap;
 
 class CMinimapInstance : public CIntObject
 {
-	CMinimap *parent;
+	CMinimap * parent;
 	SDL_Surface * minimap;
 	int level;
 
 	//get color of selected tile on minimap
 	const SDL_Color & getTileColor(const int3 & pos);
 
-	void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface *to, int x, int y);
+	void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y);
 
 	//draw minimap already scaled.
 	//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
@@ -196,19 +201,17 @@ public:
 	CMinimapInstance(CMinimap * parent, int level);
 	~CMinimapInstance();
 
-	void showAll(SDL_Surface *to) override;
-	void tileToPixels (const int3 &tile, int &x, int &y,int toX = 0, int toY = 0);
-
-	void refreshTile(const int3 &pos);
+	void showAll(SDL_Surface * to) override;
+	void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0);
+	void refreshTile(const int3 & pos);
 };
 
 /// Minimap which is displayed at the right upper corner of adventure map
 class CMinimap : public CIntObject
 {
 protected:
-
-	CPicture *aiShield; //the graphic displayed during AI turn
-	CMinimapInstance * minimap;
+	std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
+	std::shared_ptr<CMinimapInstance> minimap;
 	int level;
 
 	//to initialize colors
@@ -245,30 +248,73 @@ class CInfoBar : public CIntObject
 	//all visible information located in one object - for ease of replacing
 	class CVisibleInfo : public CIntObject
 	{
-		//list of objects that must be redrawed on each frame on a top of animation
-		std::list<CIntObject *> forceRefresh;
+	public:
+		void show(SDL_Surface * to) override;
+
+	protected:
+		std::shared_ptr<CPicture> background;
+		std::list<std::shared_ptr<CIntObject>> forceRefresh;
+
+		CVisibleInfo();
+	};
+
+	class EmptyVisibleInfo : public CVisibleInfo
+	{
+	public:
+		EmptyVisibleInfo();
+	};
+
+	class VisibleHeroInfo : public CVisibleInfo
+	{
+		std::shared_ptr<CHeroTooltip> heroTooltip;
+	public:
+		VisibleHeroInfo(const CGHeroInstance * hero);
+	};
+
+	class VisibleTownInfo : public CVisibleInfo
+	{
+		std::shared_ptr<CTownTooltip> townTooltip;
+	public:
+		VisibleTownInfo(const CGTownInstance * town);
+	};
 
-		//the only part of gui we need to know about for updating - AI progress
-		CAnimImage *aiProgress;
+	class VisibleDateInfo : public CVisibleInfo
+	{
+		std::shared_ptr<CShowableAnim> animation;
+		std::shared_ptr<CLabel> label;
 
 		std::string getNewDayName();
-		void playNewDaySound();
+	public:
+		VisibleDateInfo();
+	};
 
+	class VisibleEnemyTurnInfo : public CVisibleInfo
+	{
+		std::shared_ptr<CAnimImage> banner;
+		std::shared_ptr<CShowableAnim> glass;
+		std::shared_ptr<CShowableAnim> sand;
 	public:
-		CVisibleInfo(Point position);
+		VisibleEnemyTurnInfo(PlayerColor player);
+	};
 
-		void show(SDL_Surface *to) override;
+	class VisibleGameStatusInfo : public CVisibleInfo
+	{
+		std::shared_ptr<CLabel> allyLabel;
+		std::shared_ptr<CLabel> enemyLabel;
 
-		//functions that must be called only once
-		void loadHero(const CGHeroInstance * hero);
-		void loadTown(const CGTownInstance * town);
-		void loadDay();
-		void loadEnemyTurn(PlayerColor player);
-		void loadGameStatus();
-		void loadComponent(const Component &comp, std::string message);
+		std::vector<std::shared_ptr<CAnimImage>> flags;
+		std::vector<std::shared_ptr<CAnimImage>> hallIcons;
+		std::vector<std::shared_ptr<CLabel>> hallLabels;
+	public:
+		VisibleGameStatusInfo();
+	};
 
-		//can be called multiple times
-		void updateEnemyTurn(double progress);
+	class VisibleComponentInfo : public CVisibleInfo
+	{
+		std::shared_ptr<CComponent> comp;
+		std::shared_ptr<CTextBox> text;
+	public:
+		VisibleComponentInfo(const Component & compToDisplay, std::string message);
 	};
 
 	enum EState
@@ -276,13 +322,11 @@ class CInfoBar : public CIntObject
 		EMPTY, HERO, TOWN, DATE, GAME, AITURN, COMPONENT
 	};
 
-	CVisibleInfo * visibleInfo;
+	std::shared_ptr<CVisibleInfo> visibleInfo;
 	EState state;
-	//currently displayed object. May be null if state is not hero or town
-	const CGObjectInstance * currentObject;
 
 	//removes all information about current state, deactivates timer (if any)
-	void reset(EState newState);
+	void reset();
 
 	void tick() override;
 
@@ -290,6 +334,7 @@ class CInfoBar : public CIntObject
 	void clickRight(tribool down, bool previousState) override;
 	void hover(bool on) override;
 
+	void playNewDaySound();
 public:
 	CInfoBar(const Rect & pos);
 
@@ -301,9 +346,6 @@ public:
 
 	/// print enemy turn progress
 	void startEnemyTurn(PlayerColor color);
-	/// updates enemy turn.
-	/// NOTE: currently DISABLED. Check comments in CInfoBar::CVisibleInfo::loadEnemyTurn()
-	void updateEnemyTurn(double progress);
 
 	/// reset to default view - selected object
 	void showSelection();
@@ -319,16 +361,16 @@ public:
 /// simple panel that contains other displayable elements; used to separate groups of controls
 class CAdvMapPanel : public CIntObject
 {
-	/// ptrs to child-buttons that can be recolored with setPlayerColor()
-	std::vector<CButton *> buttons;
+	std::vector<std::shared_ptr<CButton>> colorableButtons;
+	std::vector<std::shared_ptr<CIntObject>> otherObjects;
 	/// the surface passed to this obj will be freed in dtor
 	SDL_Surface * background;
 public:
 	CAdvMapPanel(SDL_Surface * bg, Point position);
 	virtual ~CAdvMapPanel();
 
-	void addChildToPanel(CIntObject * obj, ui8 actions = 0);
-	void addChildColorableButton(CButton * btn);
+	void addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions = 0);
+	void addChildColorableButton(std::shared_ptr<CButton> button);
 	/// recolors all buttons to given player color
 	void setPlayerColor(const PlayerColor & clr);
 
@@ -341,7 +383,7 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
 	/// data that allows reconstruction of panel info icons
 	std::vector<std::pair<int, Point>> iconsData;
 	/// ptrs to child-pictures constructed from iconsData
-	std::vector<CAnimImage *> currentIcons;
+	std::vector<std::shared_ptr<CAnimImage>> currentIcons;
 	/// temporary surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
 	SDL_Surface * tmpBackgroundFiller;
 	int fillerHeight;
@@ -352,7 +394,7 @@ public:
 
 	void addChildIcon(std::pair<int, Point> data, int indexOffset);
 	/// recreates all pictures from given def to recolor them according to current player color
-	void recolorIcons(const PlayerColor &color, int indexOffset);
+	void recolorIcons(const PlayerColor & color, int indexOffset);
 	void showAll(SDL_Surface * to) override;
 };
 

+ 47 - 51
client/widgets/Buttons.cpp

@@ -74,18 +74,17 @@ void CButton::addCallback(std::function<void()> callback)
 	this->callback += callback;
 }
 
-void CButton::addTextOverlay( const std::string &Text, EFonts font, SDL_Color color)
+void CButton::addTextOverlay(const std::string & Text, EFonts font, SDL_Color color)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	addOverlay(new CLabel(pos.w/2, pos.h/2, font, CENTER, color, Text));
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	addOverlay(std::make_shared<CLabel>(pos.w/2, pos.h/2, font, CENTER, color, Text));
 	update();
 }
 
-void CButton::addOverlay(CIntObject *newOverlay)
+void CButton::addOverlay(std::shared_ptr<CIntObject> newOverlay)
 {
-	delete overlay;
 	overlay = newOverlay;
-	addChild(newOverlay);
+	addChild(newOverlay.get());
 	overlay->moveTo(overlay->pos.centerIn(pos).topLeft());
 	update();
 }
@@ -235,6 +234,7 @@ CButton::CButton(Point position, const std::string &defName, const std::pair<std
     CKeyShortcut(key),
     callback(Callback)
 {
+	defActions = 255-DISPOSE;
 	addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD);
 
 	stateToIndex[0] = 0;
@@ -243,8 +243,6 @@ CButton::CButton(Point position, const std::string &defName, const std::pair<std
 	stateToIndex[3] = 3;
 
 	state=NORMAL;
-	image = nullptr;
-	overlay = nullptr;
 
 	currentImage = -1;
 	hoverable = actOnDown = soundDisabled = false;
@@ -272,9 +270,9 @@ void CButton::setIndex(size_t index, bool playerColoredButton)
 
 void CButton::setImage(std::shared_ptr<CAnimation> anim, bool playerColoredButton, int animFlags)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 
-	image = new CAnimImage(anim, getState(), 0, 0, 0, animFlags);
+	image = std::make_shared<CAnimImage>(anim, getState(), 0, 0, 0, animFlags);
 	if (playerColoredButton)
 		image->playerColored(LOCPLINT->playerID);
 	pos = image->pos;
@@ -317,9 +315,7 @@ CToggleBase::CToggleBase(CFunctionList<void (bool)> callback):
 {
 }
 
-CToggleBase::~CToggleBase()
-{
-}
+CToggleBase::~CToggleBase() = default;
 
 void CToggleBase::doSelect(bool on)
 {
@@ -399,25 +395,30 @@ void CToggleGroup::addCallback(std::function<void(int)> callback)
 	onChange += callback;
 }
 
-void CToggleGroup::addToggle(int identifier, CToggleBase* bt)
+void CToggleGroup::resetCallback()
+{
+	onChange.clear();
+}
+
+void CToggleGroup::addToggle(int identifier, std::shared_ptr<CToggleBase> button)
 {
-	if (auto intObj = dynamic_cast<CIntObject*>(bt)) // hack-ish workagound to avoid diamond problem with inheritance
+	if(auto intObj = std::dynamic_pointer_cast<CIntObject>(button)) // hack-ish workagound to avoid diamond problem with inheritance
 	{
-		if (intObj->parent)
-			intObj->parent->removeChild(intObj);
-		addChild(intObj);
+		addChild(intObj.get());
 	}
 
-	bt->addCallback([=] (bool on) { if (on) selectionChanged(identifier);});
-	bt->allowDeselection = false;
+	button->addCallback([=] (bool on) { if (on) selectionChanged(identifier);});
+	button->allowDeselection = false;
 
-	assert(buttons[identifier] == nullptr);
-	buttons[identifier] = bt;
+	if(buttons.count(identifier)>0)
+		logAnim->error("Duplicated toggle button id %d", identifier);
+	buttons[identifier] = button;
 }
 
 CToggleGroup::CToggleGroup(const CFunctionList<void(int)> &OnChange)
-: onChange(OnChange), selectedID(-2)
-{}
+	: onChange(OnChange), selectedID(-2)
+{
+}
 
 void CToggleGroup::setSelected(int id)
 {
@@ -443,15 +444,13 @@ void CToggleGroup::selectionChanged(int to)
 		parent->redraw();
 }
 
-CVolumeSlider::CVolumeSlider(const Point &position, const std::string &defName, const int value,
-                             const std::pair<std::string, std::string> * const help) :
+CVolumeSlider::CVolumeSlider(const Point & position, const std::string & defName, const int value, const std::pair<std::string, std::string> * const help)
+	: CIntObject(LCLICK | RCLICK | WHEEL),
 	value(value),
 	helpHandlers(help)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	animImage = new CAnimImage(std::make_shared<CAnimation>(defName), 0, 0, position.x, position.y),
-	assert(!defName.empty());
-	addUsedEvents(LCLICK | RCLICK | WHEEL);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	animImage = std::make_shared<CAnimImage>(std::make_shared<CAnimation>(defName), 0, 0, position.x, position.y),
 	pos.x += position.x;
 	pos.y += position.y;
 	pos.w = (animImage->pos.w + 1) * animImage->size();
@@ -658,25 +657,20 @@ void CSlider::clickLeft(tribool down, bool previousState)
 		removeUsedEvents(MOVE);
 }
 
-CSlider::~CSlider()
-{
-
-}
-
-CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style):
-    capacity(Capacity),
-    horizontal(Horizontal),
-    amount(Amount),
-    value(Value),
-    scrollStep(1),
-    moved(Moved)
+CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style)
+	: CIntObject(LCLICK | RCLICK | WHEEL),
+	capacity(Capacity),
+	horizontal(Horizontal),
+	amount(Amount),
+	value(Value),
+	scrollStep(1),
+	moved(Moved)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	setAmount(amount);
 	vstd::amax(value, 0);
 	vstd::amin(value, positions);
 
-	addUsedEvents(LCLICK | KEYBOARD | WHEEL);
 	strongInterest = true;
 
 	pos.x += position.x;
@@ -684,12 +678,12 @@ CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int
 
 	if(style == BROWN)
 	{
-		std::string name = horizontal?"IGPCRDIV.DEF":"OVBUTN2.DEF";
+		std::string name = horizontal ? "IGPCRDIV.DEF" : "OVBUTN2.DEF";
 		//NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...)
 
-		left =   new CButton(Point(), name, CButton::tooltip());
-		right =  new CButton(Point(), name, CButton::tooltip());
-		slider = new CButton(Point(), name, CButton::tooltip());
+		left = std::make_shared<CButton>(Point(), name, CButton::tooltip());
+		right = std::make_shared<CButton>(Point(), name, CButton::tooltip());
+		slider = std::make_shared<CButton>(Point(), name, CButton::tooltip());
 
 		left->setImageOrder(0, 1, 1, 1);
 		right->setImageOrder(2, 3, 3, 3);
@@ -697,9 +691,9 @@ CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int
 	}
 	else
 	{
-		left = new CButton(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip());
-		right = new CButton(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip());
-		slider = new CButton(Point(), "SCNRBSL.DEF", CButton::tooltip());
+		left = std::make_shared<CButton>(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip());
+		right = std::make_shared<CButton>(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip());
+		slider = std::make_shared<CButton>(Point(), "SCNRBSL.DEF", CButton::tooltip());
 	}
 	slider->actOnDown = true;
 	slider->soundDisabled = true;
@@ -729,6 +723,8 @@ CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int
 	updateSliderPos();
 }
 
+CSlider::~CSlider() = default;
+
 void CSlider::block( bool on )
 {
 	left->block(on);

+ 17 - 11
client/widgets/Buttons.h

@@ -50,8 +50,8 @@ private:
 	std::array<boost::optional<SDL_Color>, 4> stateToBorderColor; // mapping of button state to border color
 	std::string helpBox; //for right-click help
 
-	CAnimImage * image; //image for this button
-	CIntObject * overlay;//object-overlay, can be null
+	std::shared_ptr<CAnimImage> image; //image for this button
+	std::shared_ptr<CIntObject> overlay;//object-overlay, can be null
 	bool animateLonelyFrame = false;
 protected:
 	void onButtonClicked(); // calls callback
@@ -80,8 +80,8 @@ public:
 	void addCallback(std::function<void()> callback);
 
 	/// adds overlay on top of button image. Only one overlay can be active at once
-	void addOverlay(CIntObject * newOverlay);
-	void addTextOverlay(const std::string &Text, EFonts font, SDL_Color color = Colors::WHITE);
+	void addOverlay(std::shared_ptr<CIntObject> newOverlay);
+	void addTextOverlay(const std::string & Text, EFonts font, SDL_Color color = Colors::WHITE);
 
 	void addImage(std::string filename);
 	void addHoverText(ButtonState state, std::string text);
@@ -95,7 +95,7 @@ public:
 	bool isHighlighted();
 
 	/// Constructor
-	CButton(Point position, const std::string &defName, const std::pair<std::string, std::string> &help,
+	CButton(Point position, const std::string & defName, const std::pair<std::string, std::string> & help,
 	        CFunctionList<void()> Callback = 0, int key=0, bool playerColoredButton = false );
 
 	/// Appearance modifiers
@@ -162,14 +162,15 @@ class CToggleGroup : public CIntObject
 	int selectedID;
 	void selectionChanged(int to);
 public:
-	std::map<int, CToggleBase*> buttons;
+	std::map<int, std::shared_ptr<CToggleBase>> buttons;
 
 	CToggleGroup(const CFunctionList<void(int)> & OnChange);
 
 	void addCallback(std::function<void(int)> callback);
+	void resetCallback();
 
 	/// add one toggle/button into group
-	void addToggle(int index, CToggleBase * button);
+	void addToggle(int index, std::shared_ptr<CToggleBase> button);
 	/// Changes selection to specific value. Will select toggle with this ID, if present
 	void setSelected(int id);
 };
@@ -179,7 +180,7 @@ class CVolumeSlider : public CIntObject
 {
 	int value;
 	CFunctionList<void(int)> onChange;
-	CAnimImage * animImage;
+	std::shared_ptr<CAnimImage> animImage;
 	const std::pair<std::string, std::string> * const helpHandlers;
 	void setVolume(const int v);
 public:
@@ -188,7 +189,7 @@ public:
 	/// @param defName name of def animation for slider
 	/// @param value initial value for volume
 	/// @param help pointer to first helptext of slider
-	CVolumeSlider(const Point &position, const std::string &defName, const int value,
+	CVolumeSlider(const Point & position, const std::string & defName, const int value,
 	              const std::pair<std::string, std::string> * const help);
 
 	void moveTo(int id);
@@ -203,7 +204,11 @@ public:
 /// A typical slider which can be orientated horizontally/vertically.
 class CSlider : public CIntObject
 {
-	CButton *left, *right, *slider; //if vertical then left=up
+	//if vertical then left=up
+	std::shared_ptr<CButton> left;
+	std::shared_ptr<CButton> right;
+	std::shared_ptr<CButton> slider;
+
 	int capacity;//how many elements can be active at same time (e.g. hero list = 5)
 	int positions; //number of highest position (0 if there is only one)
 	bool horizontal;
@@ -216,7 +221,8 @@ class CSlider : public CIntObject
 	void sliderClicked();
 
 public:
-	enum EStyle {
+	enum EStyle
+	{
 		BROWN,
 		BLUE
 	};

+ 104 - 67
client/widgets/CArtifactHolder.cpp

@@ -30,27 +30,31 @@
 
 #include "../../lib/mapObjects/CGHeroInstance.h"
 
-CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art): CArtPlace(position, Art),
-	locked(false), picked(false), marked(false), ourOwner(nullptr)
+CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art)
+	: CArtPlace(position, Art),
+	locked(false),
+	picked(false),
+	marked(false),
+	ourOwner(nullptr)
 {
 	createImage();
 }
 
 void CHeroArtPlace::createImage()
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	int imageIndex = 0;
-	if (ourArt)
+	si32 imageIndex = 0;
+	if(ourArt)
 		imageIndex = ourArt->artType->iconIndex;
-	if (locked)
+	if(locked)
 		imageIndex = ArtifactID::ART_LOCK;
 
-	image = new CAnimImage("artifact", imageIndex);
-	if (!ourArt)
+	image = std::make_shared<CAnimImage>("artifact", imageIndex);
+	if(!ourArt)
 		image->disable();
 
-	selection = new CAnimImage("artifact", ArtifactID::ART_SELECTION);
+	selection = std::make_shared<CAnimImage>("artifact", ArtifactID::ART_SELECTION);
 	selection->disable();
 }
 
@@ -137,7 +141,7 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState)
 			{
 				if(ourArt->artType->id == ArtifactID::CATAPULT) //catapult cannot be highlighted
 				{
-					std::vector<CComponent *> catapult(1, new CComponent(CComponent::artifact, 3, 0));
+					std::vector<std::shared_ptr<CComponent>> catapult(1, std::make_shared<CComponent>(CComponent::artifact, 3, 0));
 					LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped.
 					return;
 				}
@@ -284,8 +288,8 @@ void CHeroArtPlace::select ()
 	{
 		for(int i = 0; i < GameConstants::BACKPACK_START; i++)
 		{
-			CHeroArtPlace * ap = ourOwner->getArtPlace(i);
-			if(nullptr != ap)//getArtPlace may return null
+			auto ap = ourOwner->getArtPlace(i);
+			if(ap)//getArtPlace may return null
 				ap->pickSlot(ourArt->isPart(ap->ourArt));
 		}
 	}
@@ -492,7 +496,7 @@ void CArtifactsOfHero::scrollBackpack(int dir)
 		{
 			if(elem->marked)
 			{
-				highlightModeCallback(elem);
+				highlightModeCallback(elem.get());
 				break;
 			}
 		}
@@ -504,7 +508,6 @@ void CArtifactsOfHero::scrollBackpack(int dir)
 	rightArtRoll->block(!scrollingPossible);
 
 	safeRedraw();
-
 }
 
 /**
@@ -538,9 +541,10 @@ void CArtifactsOfHero::unmarkSlots(bool withRedraw)
 
 void CArtifactsOfHero::unmarkLocalSlots(bool withRedraw)
 {
-	for(auto p : artWorn)
+	for(auto & p : artWorn)
 		p.second->selectSlot(false);
-	for(CHeroArtPlace *place : backpack)
+
+	for(auto & place : backpack)
 		place->selectSlot(false);
 
 	if(withRedraw)
@@ -550,7 +554,7 @@ void CArtifactsOfHero::unmarkLocalSlots(bool withRedraw)
 /**
  * Assigns an artifacts to an artifact place depending on it's new slot ID.
  */
-void CArtifactsOfHero::setSlotData(CHeroArtPlace* artPlace, ArtifactPosition slotID)
+void CArtifactsOfHero::setSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID)
 {
 	if(!artPlace && slotID >= GameConstants::BACKPACK_START) //spurious call from artifactMoved in attempt to update hidden backpack slot
 	{
@@ -572,21 +576,25 @@ void CArtifactsOfHero::setSlotData(CHeroArtPlace* artPlace, ArtifactPosition slo
 /**
  * Makes given artifact slot appear as empty with a certain slot ID.
  */
-void CArtifactsOfHero::eraseSlotData (CHeroArtPlace* artPlace, ArtifactPosition slotID)
+void CArtifactsOfHero::eraseSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID)
 {
 	artPlace->pickSlot(false);
 	artPlace->slotID = slotID;
 	artPlace->setArtifact(nullptr);
 }
 
-CArtifactsOfHero::CArtifactsOfHero(std::map<ArtifactPosition, CHeroArtPlace *> ArtWorn, std::vector<CHeroArtPlace *> Backpack,
-	CButton *leftScroll, CButton *rightScroll, bool createCommonPart):
-
-	curHero(nullptr),
-	artWorn(ArtWorn), backpack(Backpack),
-	backpackPos(0), commonInfo(nullptr), updateState(false),
-	leftArtRoll(leftScroll), rightArtRoll(rightScroll),
-	allowedAssembling(true), highlightModeCallback(nullptr)
+CArtifactsOfHero::CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector<ArtPlacePtr> Backpack,
+		std::shared_ptr<CButton> leftScroll, std::shared_ptr<CButton> rightScroll, bool createCommonPart)
+	: curHero(nullptr),
+	artWorn(ArtWorn),
+	backpack(Backpack),
+	backpackPos(0),
+	commonInfo(nullptr),
+	updateState(false),
+	leftArtRoll(leftScroll),
+	rightArtRoll(rightScroll),
+	allowedAssembling(true),
+	highlightModeCallback(nullptr)
 {
 	if(createCommonPart)
 	{
@@ -595,7 +603,7 @@ CArtifactsOfHero::CArtifactsOfHero(std::map<ArtifactPosition, CHeroArtPlace *> A
 	}
 
 	// Init slots for worn artifacts.
-	for (auto p : artWorn)
+	for(auto p : artWorn)
 	{
 		p.second->ourOwner = this;
 		eraseSlotData(p.second, p.first);
@@ -608,12 +616,17 @@ CArtifactsOfHero::CArtifactsOfHero(std::map<ArtifactPosition, CHeroArtPlace *> A
 		eraseSlotData(backpack[s], ArtifactPosition(GameConstants::BACKPACK_START + s));
 	}
 
-	leftArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack,this,-1));
-	rightArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack,this,+1));
+	leftArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack, this,-1));
+	rightArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack, this,+1));
 }
 
-CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart)
- : curHero(nullptr), backpackPos(0), commonInfo(nullptr), updateState(false), allowedAssembling(true), highlightModeCallback(nullptr)
+CArtifactsOfHero::CArtifactsOfHero(const Point & position, bool createCommonPart)
+	: curHero(nullptr),
+	backpackPos(0),
+	commonInfo(nullptr),
+	updateState(false),
+	allowedAssembling(true),
+	highlightModeCallback(nullptr)
 {
 	if(createCommonPart)
 	{
@@ -621,7 +634,7 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart)
 		commonInfo->participants.insert(this);
 	}
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	pos += position;
 
 	std::vector<Point> slotPos =
@@ -636,9 +649,9 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart)
 	};
 
 	// Create slots for worn artifacts.
-	for (size_t g = 0; g < GameConstants::BACKPACK_START ; g++)
+	for(size_t g = 0; g < GameConstants::BACKPACK_START; g++)
 	{
-		artWorn[ArtifactPosition(g)] = new CHeroArtPlace(slotPos[g]);
+		artWorn[ArtifactPosition(g)] = std::make_shared<CHeroArtPlace>(slotPos[g]);
 		artWorn[ArtifactPosition(g)]->ourOwner = this;
 		eraseSlotData(artWorn[ArtifactPosition(g)], ArtifactPosition(g));
 	}
@@ -646,7 +659,7 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart)
 	// Create slots for the backpack.
 	for(size_t s=0; s<5; ++s)
 	{
-		auto add = new CHeroArtPlace(Point(403 + 46 * s, 365));
+		auto add = std::make_shared<CHeroArtPlace>(Point(403 + 46 * s, 365));
 
 		add->ourOwner = this;
 		eraseSlotData(add, ArtifactPosition(GameConstants::BACKPACK_START + s));
@@ -654,8 +667,8 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart)
 		backpack.push_back(add);
 	}
 
-	leftArtRoll =  new CButton(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [&](){ scrollBackpack(-1);}, SDLK_LEFT);
-	rightArtRoll = new CButton(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [&](){ scrollBackpack(+1);}, SDLK_RIGHT);
+	leftArtRoll = std::make_shared<CButton>(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [&](){ scrollBackpack(-1);}, SDLK_LEFT);
+	rightArtRoll = std::make_shared<CButton>(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [&](){ scrollBackpack(+1);}, SDLK_RIGHT);
 }
 
 CArtifactsOfHero::~CArtifactsOfHero()
@@ -674,7 +687,6 @@ void CArtifactsOfHero::updateParentWindow()
 	}
 	else if(CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt()))
 	{
-
 		//use our copy of hero to draw window
 		if(cew->heroInst[0]->id == curHero->id)
 			cew->heroInst[0] = curHero;
@@ -684,16 +696,7 @@ void CArtifactsOfHero::updateParentWindow()
 		if(!updateState)
 		{
 			cew->deactivate();
-// 			for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
-// 			{
-// 				if(cew->heroInst[g] == curHero)
-// 				{
-// 					cew->artifs[g]->setHero(curHero);
-// 				}
-// 			}
-
-
-			cew->prepareBackground();
+			cew->updateWidgets();
 			cew->redraw();
 			cew->activate();
 		}
@@ -746,7 +749,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
 		assert(dst.slot >= GameConstants::BACKPACK_START);
 		commonInfo->reset();
 
-		CHeroArtPlace *ap = nullptr;
+		CArtifactsOfHero::ArtPlacePtr ap;
 		for(CArtifactsOfHero *aoh : commonInfo->participants)
 		{
 			if(dst.isHolder(aoh->curHero))
@@ -811,7 +814,7 @@ void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al)
 	}
 }
 
-CHeroArtPlace * CArtifactsOfHero::getArtPlace(int slot)
+CArtifactsOfHero::ArtPlacePtr CArtifactsOfHero::getArtPlace(int slot)
 {
 	if(slot < GameConstants::BACKPACK_START)
 	{
@@ -825,7 +828,7 @@ CHeroArtPlace * CArtifactsOfHero::getArtPlace(int slot)
 	}
 	else
 	{
-		for(CHeroArtPlace *ap : backpack)
+		for(ArtPlacePtr ap : backpack)
 			if(ap->slotID == slot)
 				return ap;
 		return nullptr;
@@ -867,21 +870,47 @@ CArtifactHolder::CArtifactHolder()
 {
 }
 
+void CWindowWithArtifacts::addSet(std::shared_ptr<CArtifactsOfHero> artSet)
+{
+	artSets.emplace_back(artSet);
+}
+
+std::shared_ptr<CArtifactsOfHero::SCommonPart> CWindowWithArtifacts::getCommonPart()
+{
+	for(auto artSetWeak : artSets)
+	{
+		std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
+		if(realPtr)
+			return realPtr->commonInfo;
+	}
+
+	return std::shared_ptr<CArtifactsOfHero::SCommonPart>();
+}
+
 void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation &artLoc)
 {
-	for(CArtifactsOfHero *aoh : artSets)
-		aoh->artifactRemoved(artLoc);
+	for(auto artSetWeak : artSets)
+	{
+		std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
+		if(realPtr)
+			realPtr->artifactRemoved(artLoc);
+	}
 }
 
 void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc)
 {
-	CArtifactsOfHero *destaoh = nullptr;
-	for(CArtifactsOfHero *aoh : artSets)
+	CArtifactsOfHero * destaoh = nullptr;
+
+	for(auto artSetWeak : artSets)
 	{
-		aoh->artifactMoved(artLoc, destLoc);
-		aoh->redraw();
-		if(destLoc.isHolder(aoh->getHero()))
-			destaoh = aoh;
+		std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
+		if(realPtr)
+		{
+			realPtr->artifactMoved(artLoc, destLoc);
+			realPtr->redraw();
+			if(destLoc.isHolder(realPtr->getHero()))
+				destaoh = realPtr.get();
+		}
 	}
 
 	//Make sure the status bar is updated so it does not display old text
@@ -893,14 +922,22 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const A
 
 void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation &artLoc)
 {
-	for(CArtifactsOfHero *aoh : artSets)
-		aoh->artifactDisassembled(artLoc);
+	for(auto artSetWeak : artSets)
+	{
+		std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
+		if(realPtr)
+			realPtr->artifactDisassembled(artLoc);
+	}
 }
 
 void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation &artLoc)
 {
-	for(CArtifactsOfHero *aoh : artSets)
-		aoh->artifactAssembled(artLoc);
+	for(auto artSetWeak : artSets)
+	{
+		std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
+		if(realPtr)
+			realPtr->artifactAssembled(artLoc);
+	}
 }
 
 void CArtifactsOfHero::SCommonPart::Artpos::clear()
@@ -979,14 +1016,14 @@ void CCommanderArtPlace::clickRight(tribool down, bool previousState)
 
 void CCommanderArtPlace::createImage()
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
 	int imageIndex = 0;
-	if (ourArt)
+	if(ourArt)
 		imageIndex = ourArt->artType->iconIndex;
 
-	image = new CAnimImage("artifact", imageIndex);
-	if (!ourArt)
+	image = std::make_shared<CAnimImage>("artifact", imageIndex);
+	if(!ourArt)
 		image->disable();
 }
 

+ 37 - 27
client/widgets/CArtifactHolder.h

@@ -9,7 +9,6 @@
  */
 #pragma once
 
-//#include "CComponent.h"
 #include "MiscWidgets.h"
 
 class CArtifactsOfHero;
@@ -29,21 +28,10 @@ public:
 	virtual void artifactAssembled(const ArtifactLocation &artLoc)=0;
 };
 
-class CWindowWithArtifacts : public CArtifactHolder
-{
-public:
-	std::vector<CArtifactsOfHero *> artSets;
-
-	void artifactRemoved(const ArtifactLocation &artLoc) override;
-	void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override;
-	void artifactDisassembled(const ArtifactLocation &artLoc) override;
-	void artifactAssembled(const ArtifactLocation &artLoc) override;
-};
-
 class CArtPlace : public LRClickableAreaWTextComp
 {
 protected:
-	CAnimImage *image;
+	std::shared_ptr<CAnimImage> image;
 	virtual void createImage()=0;
 public:
 	const CArtifactInstance * ourArt; // should be changed only with setArtifact()
@@ -75,7 +63,7 @@ public:
 /// Artifacts can be placed there. Gets shown at the hero window
 class CHeroArtPlace: public CArtPlace
 {
-	CAnimImage *selection;
+	std::shared_ptr<CAnimImage> selection;
 
 	void createImage() override;
 
@@ -111,14 +99,10 @@ public:
 /// Contains artifacts of hero. Distincts which artifacts are worn or backpacked
 class CArtifactsOfHero : public CIntObject
 {
-	const CGHeroInstance * curHero;
-
-	std::map<ArtifactPosition, CHeroArtPlace *> artWorn;
-
-	std::vector<CHeroArtPlace *> backpack; //hero's visible backpack (only 5 elements!)
-	int backpackPos; //number of first art visible in backpack (in hero's vector)
-
 public:
+	using ArtPlacePtr = std::shared_ptr<CHeroArtPlace>;
+	using ArtPlaceMap = std::map<ArtifactPosition, ArtPlacePtr>;
+
 	struct SCommonPart
 	{
 		struct Artpos
@@ -142,8 +126,10 @@ public:
 
 	bool updateState; // Whether the commonInfo should be updated on setHero or not.
 
-	CButton * leftArtRoll, * rightArtRoll;
+	std::shared_ptr<CButton> leftArtRoll;
+	std::shared_ptr<CButton> rightArtRoll;
 	bool allowedAssembling;
+
 	std::multiset<const CArtifactInstance*> artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be omitted in backpack slots
 	std::function<void(CHeroArtPlace*)> highlightModeCallback; //if set, clicking on art place doesn't pick artifact but highlights the slot and calls this function
 
@@ -152,7 +138,7 @@ public:
 	void artifactRemoved(const ArtifactLocation &al);
 	void artifactAssembled(const ArtifactLocation &al);
 	void artifactDisassembled(const ArtifactLocation &al);
-	CHeroArtPlace *getArtPlace(int slot);//may return null
+	ArtPlacePtr getArtPlace(int slot);//may return null
 
 	void setHero(const CGHeroInstance * hero);
 	const CGHeroInstance *getHero() const;
@@ -163,17 +149,41 @@ public:
 	void markPossibleSlots(const CArtifactInstance* art);
 	void unmarkSlots(bool withRedraw = true); //unmarks slots in all visible AOHs
 	void unmarkLocalSlots(bool withRedraw = true); //unmarks slots in that particular AOH
-	void setSlotData (CHeroArtPlace* artPlace, ArtifactPosition slotID);
 	void updateWornSlots (bool redrawParent = true);
 
 	void updateSlot(ArtifactPosition i);
-	void eraseSlotData (CHeroArtPlace* artPlace, ArtifactPosition slotID);
 
 	CArtifactsOfHero(const Point& position, bool createCommonPart = false);
 	//Alternative constructor, used if custom artifacts positioning required (Kingdom interface)
-	CArtifactsOfHero(std::map<ArtifactPosition, CHeroArtPlace *> ArtWorn, std::vector<CHeroArtPlace *> Backpack,
-		CButton *leftScroll, CButton *rightScroll, bool createCommonPart = false);
+	CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector<ArtPlacePtr> Backpack,
+		std::shared_ptr<CButton> leftScroll, std::shared_ptr<CButton> rightScroll, bool createCommonPart = false);
 	~CArtifactsOfHero();
 	void updateParentWindow();
 	friend class CHeroArtPlace;
+
+private:
+
+	const CGHeroInstance * curHero;
+
+	ArtPlaceMap artWorn;
+
+	std::vector<ArtPlacePtr> backpack; //hero's visible backpack (only 5 elements!)
+	int backpackPos; //number of first art visible in backpack (in hero's vector)
+
+	void eraseSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID);
+	void setSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID);
+};
+
+class CWindowWithArtifacts : public CArtifactHolder
+{
+	std::vector<std::weak_ptr<CArtifactsOfHero>> artSets;
+public:
+	void addSet(std::shared_ptr<CArtifactsOfHero> artSet);
+
+	std::shared_ptr<CArtifactsOfHero::SCommonPart> getCommonPart();
+
+	void artifactRemoved(const ArtifactLocation &artLoc) override;
+	void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override;
+	void artifactDisassembled(const ArtifactLocation &artLoc) override;
+	void artifactAssembled(const ArtifactLocation &artLoc) override;
 };

+ 25 - 39
client/widgets/CComponent.cpp

@@ -27,29 +27,26 @@
 #include "../../lib/CGeneralTextHandler.h"
 #include "../../lib/NetPacksBase.h"
 
-CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize):
-	image(nullptr),
-	perDay(false)
+CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize)
+	: perDay(false)
 {
-	addUsedEvents(RCLICK);
 	init(Type, Subtype, Val, imageSize);
 }
 
-CComponent::CComponent(const Component &c, ESize imageSize):
-	image(nullptr),
-	perDay(false)
+CComponent::CComponent(const Component & c, ESize imageSize)
+	: perDay(false)
 {
-	addUsedEvents(RCLICK);
-
 	if(c.id == Component::RESOURCE && c.when==-1)
 		perDay = true;
 
-	init((Etype)c.id,c.subtype,c.val, imageSize);
+	init((Etype)c.id, c.subtype, c.val, imageSize);
 }
 
 void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
+	addUsedEvents(RCLICK);
 
 	compType = Type;
 	subtype = Subtype;
@@ -74,14 +71,15 @@ void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize)
 	for(auto & line : textLines)
 	{
 		int height = graphics->fonts[font]->getLineHeight();
-		auto   label = new CLabel(pos.w/2, pos.h + height/2, font, CENTER, Colors::WHITE, line);
+		auto label = std::make_shared<CLabel>(pos.w/2, pos.h + height/2, font, CENTER, Colors::WHITE, line);
 
 		pos.h += height;
-		if (label->pos.w > pos.w)
+		if(label->pos.w > pos.w)
 		{
 			pos.x -= (label->pos.w - pos.w)/2;
 			pos.w = label->pos.w;
 		}
+		lines.push_back(label);
 	}
 }
 
@@ -232,9 +230,8 @@ std::string CComponent::getSubtitleInternal()
 
 void CComponent::setSurface(std::string defName, int imgPos)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	vstd::clear_pointer(image);
-	image = new CAnimImage(defName, imgPos);
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	image = std::make_shared<CAnimImage>(defName, imgPos);
 }
 
 void CComponent::clickRight(tribool down, bool previousState)
@@ -291,7 +288,7 @@ void CSelectableComponent::showAll(SDL_Surface * to)
 	}
 }
 
-void CComponentBox::selectionChanged(CSelectableComponent * newSelection)
+void CComponentBox::selectionChanged(std::shared_ptr<CSelectableComponent> newSelection)
 {
 	if (newSelection == selected)
 		return;
@@ -339,14 +336,14 @@ void CComponentBox::placeComponents(bool selectable)
 {
 	static const int betweenRows = 22;
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	if (components.empty())
 		return;
 
 	//prepare components
 	for(auto & comp : components)
 	{
-		addChild(comp);
+		addChild(comp.get());
 		comp->moveTo(Point(pos.x, pos.y));
 	}
 
@@ -362,14 +359,14 @@ void CComponentBox::placeComponents(bool selectable)
 	rows.push_back (RowData (0,0,0));
 
 	//split components in rows
-	CComponent * prevComp = nullptr;
+	std::shared_ptr<CComponent> prevComp;
 
-	for(CComponent * comp : components)
+	for(std::shared_ptr<CComponent> comp : components)
 	{
 		//make sure that components are smaller than our width
 		//assert(pos.w == 0 || pos.w < comp->pos.w);
 
-		const int distance = prevComp ? getDistance(prevComp, comp) : 0;
+		const int distance = prevComp ? getDistance(prevComp.get(), comp.get()) : 0;
 
 		//start next row
 		if ((pos.w != 0 && rows.back().width + comp->pos.w + distance > pos.w) // row is full
@@ -421,11 +418,11 @@ void CComponentBox::placeComponents(bool selectable)
 			{
 				if (selectable)
 				{
-					Point orPos = Point(currentX - freeSpace, currentY) + getOrTextPos(prevComp, *iter);
+					Point orPos = Point(currentX - freeSpace, currentY) + getOrTextPos(prevComp.get(), iter->get());
 
-					new CLabel(orPos.x, orPos.y, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[4]);
+					orLabels.push_back(std::make_shared<CLabel>(orPos.x, orPos.y, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[4]));
 				}
-				currentX += getDistance(prevComp, *iter);
+				currentX += getDistance(prevComp.get(), iter->get());
 			}
 
 			(*iter)->moveBy(Point(currentX, currentY));
@@ -438,27 +435,16 @@ void CComponentBox::placeComponents(bool selectable)
 	}
 }
 
-CComponentBox::CComponentBox(CComponent * _components, Rect position):
-	components(1, _components),
-	selected(nullptr)
-{
-	type |= REDRAW_PARENT;
-	pos = position + pos;
-	placeComponents(false);
-}
-
-CComponentBox::CComponentBox(std::vector<CComponent *> _components, Rect position):
-	components(_components),
-	selected(nullptr)
+CComponentBox::CComponentBox(std::vector<std::shared_ptr<CComponent>> _components, Rect position):
+	components(_components)
 {
 	type |= REDRAW_PARENT;
 	pos = position + pos;
 	placeComponents(false);
 }
 
-CComponentBox::CComponentBox(std::vector<CSelectableComponent *> _components, Rect position, std::function<void(int newID)> _onSelect):
+CComponentBox::CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> _components, Rect position, std::function<void(int newID)> _onSelect):
 	components(_components.begin(), _components.end()),
-	selected(nullptr),
 	onSelect(_onSelect)
 {
 	type |= REDRAW_PARENT;

+ 12 - 10
client/widgets/CComponent.h

@@ -13,6 +13,7 @@
 
 struct Component;
 class CAnimImage;
+class CLabel;
 
 /// common popup window component
 class CComponent : public virtual CIntObject
@@ -34,6 +35,8 @@ public:
 	};
 
 private:
+	std::vector<std::shared_ptr<CLabel>> lines;
+
 	size_t getIndex();
 	const std::vector<std::string> getFileName();
 	void setSurface(std::string defName, int imgPos);
@@ -42,7 +45,7 @@ private:
 	void init(Etype Type, int Subtype, int Val, ESize imageSize);
 
 public:
-	CAnimImage *image; //our image
+	std::shared_ptr<CAnimImage> image;
 
 	Etype compType; //component type
 	ESize size; //component size.
@@ -72,19 +75,21 @@ public:
 
 	void clickLeft(tribool down, bool previousState) override; //call-in
 	CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function<void()> OnSelect = nullptr);
-	CSelectableComponent(const Component &c, std::function<void()> OnSelect = nullptr);
+	CSelectableComponent(const Component & c, std::function<void()> OnSelect = nullptr);
 };
 
 /// box with multiple components (up to 8?)
 /// will take ownership on components and delete them afterwards
 class CComponentBox : public CIntObject
 {
-	std::vector<CComponent *> components;
+	std::vector<std::shared_ptr<CComponent>> components;
+
+	std::vector<std::shared_ptr<CLabel>> orLabels;
 
-	CSelectableComponent * selected;
+	std::shared_ptr<CSelectableComponent> selected;
 	std::function<void(int newID)> onSelect;
 
-	void selectionChanged(CSelectableComponent * newSelection);
+	void selectionChanged(std::shared_ptr<CSelectableComponent> newSelection);
 
 	//get position of "or" text between these comps
 	//it will place "or" equidistant to both images
@@ -98,14 +103,11 @@ public:
 	/// return index of selected item
 	int selectedIndex();
 
-	/// constructor for quite common 1-components popups
-	/// if position width or height are 0 then it will be determined automatically
-	CComponentBox(CComponent * components, Rect position);
 	/// constructor for non-selectable components
-	CComponentBox(std::vector<CComponent *> components, Rect position);
+	CComponentBox(std::vector<std::shared_ptr<CComponent>> components, Rect position);
 
 	/// constructor for selectable components
 	/// will also create "or" labels between components
 	/// onSelect - optional function that will be called every time on selection change
-	CComponentBox(std::vector<CSelectableComponent *> components, Rect position, std::function<void(int newID)> onSelect = nullptr);
+	CComponentBox(std::vector<std::shared_ptr<CSelectableComponent>> components, Rect position, std::function<void(int newID)> onSelect = nullptr);
 };

+ 59 - 102
client/widgets/CGarrisonInt.cpp

@@ -172,8 +172,12 @@ bool CGarrisonSlot::highlightOrDropArtifact()
 	bool artSelected = false;
 	if (CWindowWithArtifacts* chw = dynamic_cast<CWindowWithArtifacts*>(GH.topInt())) //dirty solution
 	{
-		const std::shared_ptr<CArtifactsOfHero::SCommonPart> commonInfo = chw->artSets.front()->commonInfo;
-		if (const CArtifactInstance *art = commonInfo->src.art)
+		const std::shared_ptr<CArtifactsOfHero::SCommonPart> commonInfo = chw->getCommonPart();
+		const CArtifactInstance * art = nullptr;
+		if(commonInfo)
+			art = commonInfo->src.art;
+
+		if(art)
 		{
 			const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero();
 			artSelected = true;
@@ -335,7 +339,7 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
 
 void CGarrisonSlot::update()
 {
-	if (getObj() != nullptr)
+	if(getObj() != nullptr)
 	{
 		addUsedEvents(LCLICK | RCLICK | HOVER);
 		myStack = getObj()->getStackPtr(ID);
@@ -348,7 +352,7 @@ void CGarrisonSlot::update()
 		creature = nullptr;
 	}
 
-	if (creature)
+	if(creature)
 	{
 		creatureImage->enable();
 		creatureImage->setFrame(creature->iconIndex);
@@ -363,26 +367,24 @@ void CGarrisonSlot::update()
 	}
 }
 
-CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * Creature):
-    ID(IID),
-    owner(Owner),
-    myStack(Creature),
-    creature(Creature ? Creature->type : nullptr),
-    upg(Upg)
+CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * Creature)
+	: ID(IID),
+	owner(Owner),
+	myStack(Creature),
+	creature(nullptr),
+	upg(Upg)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	if (getObj())
-		addUsedEvents(LCLICK | RCLICK | HOVER);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
 	pos.x += x;
 	pos.y += y;
 
 	std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT";
 
-	creatureImage = new CAnimImage(imgName, creature ? creature->iconIndex : 0);
-	if (!creature)
-		creatureImage->disable();
+	creatureImage =  std::make_shared<CAnimImage>(imgName, 0);
+	creatureImage->disable();
 
-	selectionImage = new CAnimImage(imgName, 1);
+	selectionImage = std::make_shared<CAnimImage>(imgName, 1);
 	selectionImage->disable();
 
 	if(Owner->smallIcons)
@@ -396,11 +398,9 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, CGar
 		pos.h = 64;
 	}
 
-	stackCount = new CLabel(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE);
-	if (!creature)
-		stackCount->disable();
-	else
-		stackCount->setText(boost::lexical_cast<std::string>(myStack->count));
+	stackCount = std::make_shared<CLabel>(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE);
+
+	update();
 }
 
 void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount, int maxOfSplittedSlots)
@@ -419,8 +419,9 @@ void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount
 void CGarrisonSlot::handleSplittingShortcuts()
 {
 	const Uint8 * state = SDL_GetKeyboardState(NULL);
-	if(owner->getSelection() && owner->getEmptySlots(owner->getSelection()->upg).size() && owner->getSelection()->myStack->count > 1){
-		if (state[SDL_SCANCODE_LCTRL] && state[SDL_SCANCODE_LSHIFT])
+	if(owner->getSelection() && owner->getEmptySlots(owner->getSelection()->upg).size() && owner->getSelection()->myStack->count > 1)
+	{
+		if(state[SDL_SCANCODE_LCTRL] && state[SDL_SCANCODE_LSHIFT])
 			splitIntoParts(owner->getSelection()->upg, 1, 7);
 		else if(state[SDL_SCANCODE_LCTRL])
 			splitIntoParts(owner->getSelection()->upg, 1, 1);
@@ -432,39 +433,38 @@ void CGarrisonSlot::handleSplittingShortcuts()
 	}
 }
 
-void CGarrisonInt::addSplitBtn(CButton * button)
+void CGarrisonInt::addSplitBtn(std::shared_ptr<CButton> button)
 {
-	addChild(button);
-	button->recActions = defActions;
+	addChild(button.get());
+	button->recActions &= ~DISPOSE;
 	splitButtons.push_back(button);
 	button->block(getSelection() == nullptr);
 }
 
 void CGarrisonInt::createSlots()
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	int distance = interx + (smallIcons? 32 : 58);
+	int distance = interx + (smallIcons ? 32 : 58);
 	for(int i=0; i<2; i++)
 	{
-		std::vector<CGarrisonSlot*> garrisonSlots;
+		std::vector<std::shared_ptr<CGarrisonSlot>> garrisonSlots;
 		garrisonSlots.resize(7);
-		if (armedObjs[i])
+		if(armedObjs[i])
 		{
 			for(auto & elem : armedObjs[i]->Slots())
 			{
-				garrisonSlots[elem.first.getNum()] = new CGarrisonSlot(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast<CGarrisonSlot::EGarrisonType>(i), elem.second);
+				garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast<CGarrisonSlot::EGarrisonType>(i), elem.second);
 			}
 		}
 		for(int j=0; j<7; j++)
 		{
 			if(!garrisonSlots[j])
-				garrisonSlots[j] = new CGarrisonSlot(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast<CGarrisonSlot::EGarrisonType>(i), nullptr);
-			if (twoRows && j>=4)
+				garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast<CGarrisonSlot::EGarrisonType>(i), nullptr);
+			if(twoRows && j>=4)
 			{
 				garrisonSlots[j]->moveBy(Point(-126, 37));
 			}
 		}
-		std::copy(garrisonSlots.begin(), garrisonSlots.end(), std::back_inserter(availableSlots));
+		vstd::concatenate(availableSlots, garrisonSlots);
 	}
 }
 
@@ -476,10 +476,8 @@ void CGarrisonInt::recreateSlots()
 	for(auto & elem : splitButtons)
 		elem->block(true);
 
-
-	for(CGarrisonSlot * slot : availableSlots)
+	for(auto slot : availableSlots)
 		slot->update();
-
 }
 
 void CGarrisonInt::splitClick()
@@ -494,19 +492,20 @@ void CGarrisonInt::splitStacks(int, int amountRight)
 	LOCPLINT->cb->splitStack(armedObjs[getSelection()->upg], armedObjs[pb], getSelection()->ID, p2, amountRight);
 }
 
-CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset,
-                           SDL_Surface *pomsur, const Point& SurOffset,
-                           const CArmedInstance *s1, const CArmedInstance *s2,
-                           bool _removableUnits, bool smallImgs, bool _twoRows ) :
-    highlighted(nullptr),
-    inSplittingMode(false),
-    interx(inx),
-    garOffset(garsOffset),
-    pb(false),
-    smallIcons(smallImgs),
-    removableUnits(_removableUnits),
-    twoRows(_twoRows)
+CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset,
+		const CArmedInstance * s1, const CArmedInstance * s2,
+		bool _removableUnits, bool smallImgs, bool _twoRows)
+	: highlighted(nullptr),
+	inSplittingMode(false),
+	interx(inx),
+	garOffset(garsOffset),
+	pb(false),
+	smallIcons(smallImgs),
+	removableUnits(_removableUnits),
+	twoRows(_twoRows)
 {
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
 	setArmy(s1, false);
 	setArmy(s2, true);
 	pos.x += x;
@@ -521,16 +520,16 @@ const CGarrisonSlot * CGarrisonInt::getSelection()
 
 void CGarrisonInt::selectSlot(CGarrisonSlot *slot)
 {
-	if (slot != highlighted)
+	if(slot != highlighted)
 	{
-		if (highlighted)
+		if(highlighted)
 			highlighted->setHighlight(false);
 
 		highlighted = slot;
-		for (auto button : splitButtons)
+		for(auto button : splitButtons)
 			button->block(highlighted == nullptr || !slot->our());
 
-		if (highlighted)
+		if(highlighted)
 			highlighted->setHighlight(true);
 	}
 }
@@ -539,11 +538,11 @@ void CGarrisonInt::setSplittingMode(bool on)
 {
 	assert(on == false || highlighted != nullptr); //can't be in splitting mode without selection
 
-	if (inSplittingMode || on)
+	if(inSplittingMode || on)
 	{
-		for(CGarrisonSlot * slot : availableSlots)
+		for(auto slot : availableSlots)
 		{
-			if(slot!=getSelection())
+			if(slot.get() != getSelection())
 				slot->setHighlight( ( on && (slot->our() || slot->ally()) && (slot->creature == nullptr || slot->creature == getSelection()->creature)));
 		}
 		inSplittingMode = on;
@@ -558,58 +557,16 @@ bool CGarrisonInt::getSplittingMode()
 std::vector<CGarrisonSlot *> CGarrisonInt::getEmptySlots(CGarrisonSlot::EGarrisonType type)
 {
 	std::vector<CGarrisonSlot *> emptySlots;
-	for(CGarrisonSlot * slot : availableSlots)
+	for(auto slot : availableSlots)
 	{
 		if(type == slot->upg && ((slot->our() || slot->ally()) && slot->creature == nullptr))
-			emptySlots.push_back(slot);
+			emptySlots.push_back(slot.get());
 	}
 	return emptySlots;
 }
 
-void CGarrisonInt::setArmy(const CArmedInstance *army, bool bottomGarrison)
+void CGarrisonInt::setArmy(const CArmedInstance * army, bool bottomGarrison)
 {
 	owned[bottomGarrison] =  army ? (army->tempOwner == LOCPLINT->playerID || army->tempOwner == PlayerColor::UNFLAGGABLE) : false;
 	armedObjs[bottomGarrison] = army;
 }
-
-CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits ):
-	CWindowObject(PLAYER_COLORED, "GARRISON")
-{
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-
-	garr = new CGarrisonInt(92, 127, 4, Point(0,96), background->bg, Point(93,127), up, down, removableUnits);
-	{
-		CButton *split = new CButton(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } );
-		removeChild(split);
-		garr->addSplitBtn(split);
-	}
-	quit = new CButton(Point(399, 314), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[8], ""), [&](){ close(); }, SDLK_RETURN);
-
-	std::string titleText;
-	if (down->tempOwner == up->tempOwner)
-		titleText = CGI->generaltexth->allTexts[709];
-	else
-	{
-		//assume that this is joining monsters dialog
-		if(up->Slots().size() > 0)
-		{
-			titleText = CGI->generaltexth->allTexts[35];
-			boost::algorithm::replace_first(titleText, "%s", up->Slots().begin()->second->type->namePl);
-		}
-		else
-			logGlobal->error("Invalid armed instance for garrison window.");
-	}
-	new CLabel(275, 30, FONT_BIG, CENTER, Colors::YELLOW, titleText);
-
-	new CAnimImage("CREST58", up->getOwner().getNum(), 0, 28, 124);
-	new CAnimImage("PortraitsLarge", down->portrait, 0, 29, 222);
-}
-
-CGarrisonHolder::CGarrisonHolder()
-{
-}
-
-void CWindowWithGarrison::updateGarrisons()
-{
-	garr->recreateSlots();
-}

+ 25 - 44
client/widgets/CGarrisonInt.h

@@ -25,8 +25,8 @@ class CGarrisonSlot : public CIntObject
 {
 	SlotID ID; //for identification
 	CGarrisonInt *owner;
-	const CStackInstance *myStack; //nullptr if slot is empty
-	const CCreature *creature;
+	const CStackInstance * myStack; //nullptr if slot is empty
+	const CCreature * creature;
 
 	/// Type of Garrison for slot (up or down)
 	enum EGarrisonType
@@ -35,9 +35,9 @@ class CGarrisonSlot : public CIntObject
 		DOWN,  ///< 1 - down garrison (Visiting)
 	} upg; ///< Flag indicating if it is the up or down garrison
 
-	CAnimImage * creatureImage;
-	CAnimImage * selectionImage; // image for selection, not always visible
-	CLabel * stackCount;
+	std::shared_ptr<CAnimImage> creatureImage;
+	std::shared_ptr<CAnimImage> selectionImage; // image for selection, not always visible
+	std::shared_ptr<CLabel> stackCount;
 
 	bool viewInfo();
 	bool highlightOrDropArtifact();
@@ -65,19 +65,15 @@ public:
 class CGarrisonInt :public CIntObject
 {
 	/// Chosen slot. Should be changed only via selectSlot.
-	CGarrisonSlot *highlighted;
+	CGarrisonSlot * highlighted;
 	bool inSplittingMode;
+	std::vector<std::shared_ptr<CGarrisonSlot>> availableSlots;  ///< Slots of upper and lower garrison
 
+	void createSlots();
 public:
-	void selectSlot(CGarrisonSlot * slot); ///< @param slot null = deselect
-	const CGarrisonSlot * getSelection();
-
-	void setSplittingMode(bool on);
-	bool getSplittingMode();
-
 	int interx;  ///< Space between slots
 	Point garOffset;  ///< Offset between garrisons (not used if only one hero)
-	std::vector<CButton *> splitButtons;  ///< May be empty if no buttons
+	std::vector<std::shared_ptr<CButton>> splitButtons;  ///< May be empty if no buttons
 
 	SlotID p2; ///< TODO: comment me
 	bool pb,
@@ -86,15 +82,19 @@ public:
 		 twoRows,         ///< slots Will be placed in 2 rows
 		 owned[2];        ///< player Owns up or down army ([0] upper, [1] lower)
 
-	std::vector<CGarrisonSlot *> availableSlots;  ///< Slots of upper and lower garrison
+	void selectSlot(CGarrisonSlot * slot); ///< @param slot null = deselect
+	const CGarrisonSlot * getSelection();
+
+	void setSplittingMode(bool on);
+	bool getSplittingMode();
+
 	std::vector<CGarrisonSlot *> getEmptySlots(CGarrisonSlot::EGarrisonType type);
 
-	const CArmedInstance *armedObjs[2];  ///< [0] is upper, [1] is down
+	const CArmedInstance * armedObjs[2];  ///< [0] is upper, [1] is down
 
-	void setArmy(const CArmedInstance *army, bool bottomGarrison);
-	void addSplitBtn(CButton * button);
+	void setArmy(const CArmedInstance * army, bool bottomGarrison);
+	void addSplitBtn(std::shared_ptr<CButton> button);
 
-	void createSlots();
 	void recreateSlots();
 
 	void splitClick();  ///< handles click on split button
@@ -104,40 +104,21 @@ public:
 	/// @param x, y Position
 	/// @param inx Distance between slots;
 	/// @param garsOffset
-	/// @param pomsur, SurOffset UNUSED
 	/// @param s1, s2 Top and bottom armies
 	/// @param _removableUnits You can take units from top
 	/// @param smallImgs Units images size 64x58 or 32x32
 	/// @param _twoRows Display slots in 2 row (1st row = 4 slots, 2nd = 3 slots)
-	CGarrisonInt(int x, int y,
-	             int inx,
-	             const Point &garsOffset,
-	             SDL_Surface *pomsur, const Point &SurOffset,
-	             const CArmedInstance *s1, const CArmedInstance *s2=nullptr,
-	             bool _removableUnits = true,
-	             bool smallImgs = false,
-	             bool _twoRows=false);
+	CGarrisonInt(int x, int y, int inx,
+			 const Point & garsOffset,
+			 const CArmedInstance * s1, const CArmedInstance * s2 = nullptr,
+			 bool _removableUnits = true,
+			 bool smallImgs = false,
+			 bool _twoRows = false);
 };
 
 class CGarrisonHolder
 {
 public:
-	CGarrisonHolder();
-	virtual void updateGarrisons()=0;
+	virtual void updateGarrisons() = 0;
 };
 
-class CWindowWithGarrison : public virtual CGarrisonHolder
-{
-public:
-	CGarrisonInt *garr;
-	virtual void updateGarrisons() override;
-};
-
-/// Garrison window where you can take creatures out of the hero to place it on the garrison
-class CGarrisonWindow : public CWindowObject, public CWindowWithGarrison
-{
-public:
-	CButton * quit;
-
-	CGarrisonWindow(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits);
-};

+ 5 - 14
client/widgets/Images.cpp

@@ -179,13 +179,6 @@ void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color)
 	freeSurf = true;
 }
 
-void CPicture::colorizeAndConvert(PlayerColor player)
-{
-	assert(bg);
-	colorize(player);
-	convertToScreenBPP();
-}
-
 void CPicture::colorize(PlayerColor player)
 {
 	assert(bg);
@@ -257,9 +250,6 @@ void CAnimImage::init()
 
 CAnimImage::~CAnimImage()
 {
-	anim->unload(frame, group);
-	if (flags & CShowableAnim::BASE)
-		anim->unload(0,group);
 }
 
 void CAnimImage::showAll(SDL_Surface * to)
@@ -281,7 +271,6 @@ void CAnimImage::setFrame(size_t Frame, size_t Group)
 		return;
 	if (anim->size(Group) > Frame)
 	{
-		anim->unload(frame, group);
 		anim->load(Frame, Group);
 		frame = Frame;
 		group = Group;
@@ -348,8 +337,9 @@ bool CShowableAnim::set(size_t Group, size_t from, size_t to)
 	if (max < from || max == 0)
 		return false;
 
-	anim->load(Group);
-	anim->unload(group);
+	anim->unloadGroup(group);
+	anim->loadGroup(Group);
+
 	group = Group;
 	frame = first = from;
 	last = max;
@@ -363,8 +353,9 @@ bool CShowableAnim::set(size_t Group)
 		return false;
 	if (group != Group)
 	{
-		anim->loadGroup(Group);
 		anim->unloadGroup(group);
+		anim->loadGroup(Group);
+
 		first = 0;
 		group = Group;
 		last = anim->size(Group);

+ 0 - 1
client/widgets/Images.h

@@ -50,7 +50,6 @@ public:
 	void show(SDL_Surface * to) override;
 	void showAll(SDL_Surface * to) override;
 	void convertToScreenBPP();
-	void colorizeAndConvert(PlayerColor player);
 	void colorize(PlayerColor player);
 };
 

+ 88 - 79
client/widgets/MiscWidgets.cpp

@@ -87,7 +87,7 @@ void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState)
 {
 	if((!down) && previousState)
 	{
-		std::vector<CComponent*> comp(1, createComponent());
+		std::vector<std::shared_ptr<CComponent>> comp(1, createComponent());
 		LOCPLINT->showInfoDialog(text, comp);
 	}
 }
@@ -98,19 +98,19 @@ LRClickableAreaWTextComp::LRClickableAreaWTextComp(const Rect &Pos, int BaseType
 	type = -1;
 }
 
-CComponent * LRClickableAreaWTextComp::createComponent() const
+std::shared_ptr<CComponent> LRClickableAreaWTextComp::createComponent() const
 {
 	if(baseType >= 0)
-		return new CComponent(CComponent::Etype(baseType), type, bonusValue);
+		return std::make_shared<CComponent>(CComponent::Etype(baseType), type, bonusValue);
 	else
-		return nullptr;
+		return std::shared_ptr<CComponent>();
 }
 
 void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState)
 {
 	if(down)
 	{
-		if(CComponent *comp = createComponent())
+		if(auto comp = createComponent())
 		{
 			CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
 			return;
@@ -120,16 +120,19 @@ void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState)
 	LRClickableAreaWText::clickRight(down, previousState); //only if with-component variant not occurred
 }
 
-CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero):hero(_hero)
+CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero)
+	: CIntObject(LCLICK | RCLICK | HOVER),
+	hero(_hero)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	addUsedEvents(LCLICK | RCLICK | HOVER);
-	pos.x += x;	pos.w = 58;
-	pos.y += y;	pos.h = 64;
+	pos.x += x;
+	pos.w = 58;
+	pos.y += y;
+	pos.h = 64;
 
-	if (hero)
-		new CAnimImage("PortraitsLarge", hero->portrait);
+	if(hero)
+		portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait);
 }
 
 void CHeroArea::clickLeft(tribool down, bool previousState)
@@ -181,7 +184,8 @@ void CMinorResDataBar::show(SDL_Surface * to)
 
 void CMinorResDataBar::showAll(SDL_Surface * to)
 {
-	blitAt(bg,pos.x,pos.y,to);
+	CIntObject::showAll(to);
+
 	for (Res::ERes i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1))
 	{
 		std::string text = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i));
@@ -202,34 +206,34 @@ void CMinorResDataBar::showAll(SDL_Surface * to)
 
 CMinorResDataBar::CMinorResDataBar()
 {
-	bg = BitmapHandler::loadBitmap("KRESBAR.bmp");
-	CSDL_Ext::setDefaultColorKey(bg);
-	graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
 	pos.x = 7;
 	pos.y = 575;
-	pos.w = bg->w;
-	pos.h = bg->h;
-}
 
-CMinorResDataBar::~CMinorResDataBar()
-{
-	SDL_FreeSurface(bg);
+	background = std::make_shared<CPicture>("KRESBAR.bmp");
+	background->colorize(LOCPLINT->playerID);
+
+	pos.w = background->pos.w;
+	pos.h = background->pos.h;
 }
 
+CMinorResDataBar::~CMinorResDataBar() = default;
+
 void CArmyTooltip::init(const InfoAboutArmy &army)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	new CLabel(66, 2, FONT_SMALL, TOPLEFT, Colors::WHITE, army.name);
+	title = std::make_shared<CLabel>(66, 2, FONT_SMALL, TOPLEFT, Colors::WHITE, army.name);
 
 	std::vector<Point> slotsPos;
-	slotsPos.push_back(Point(36,73));
-	slotsPos.push_back(Point(72,73));
-	slotsPos.push_back(Point(108,73));
-	slotsPos.push_back(Point(18,122));
-	slotsPos.push_back(Point(54,122));
-	slotsPos.push_back(Point(90,122));
-	slotsPos.push_back(Point(126,122));
+	slotsPos.push_back(Point(36, 73));
+	slotsPos.push_back(Point(72, 73));
+	slotsPos.push_back(Point(108, 73));
+	slotsPos.push_back(Point(18, 122));
+	slotsPos.push_back(Point(54, 122));
+	slotsPos.push_back(Point(90, 122));
+	slotsPos.push_back(Point(126, 122));
 
 	for(auto & slot : army.army)
 	{
@@ -239,24 +243,26 @@ void CArmyTooltip::init(const InfoAboutArmy &army)
 			continue;
 		}
 
-		new CAnimImage("CPRSMALL", slot.second.type->iconIndex, 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y);
+		icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", slot.second.type->iconIndex, 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y));
 
 		std::string subtitle;
 		if(army.army.isDetailed)
+		{
 			subtitle = boost::lexical_cast<std::string>(slot.second.count);
+		}
 		else
 		{
 			//if =0 - we have no information about stack size at all
-			if (slot.second.count)
+			if(slot.second.count)
 				subtitle = CGI->generaltexth->arraytxt[171 + 3*(slot.second.count)];
 		}
 
-		new CLabel(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 41, FONT_TINY, CENTER, Colors::WHITE, subtitle);
+		subtitles.push_back(std::make_shared<CLabel>(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 41, FONT_TINY, CENTER, Colors::WHITE, subtitle));
 	}
 
 }
 
-CArmyTooltip::CArmyTooltip(Point pos, const InfoAboutArmy &army):
+CArmyTooltip::CArmyTooltip(Point pos, const InfoAboutArmy & army):
 	CIntObject(0, pos)
 {
 	init(army);
@@ -268,22 +274,21 @@ CArmyTooltip::CArmyTooltip(Point pos, const CArmedInstance * army):
 	init(InfoAboutArmy(army, true));
 }
 
-void CHeroTooltip::init(const InfoAboutHero &hero)
+void CHeroTooltip::init(const InfoAboutHero & hero)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CAnimImage("PortraitsLarge", hero.portrait, 0, 3, 2);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero.portrait, 0, 3, 2);
 
 	if(hero.details)
 	{
-		for (size_t i = 0; i < hero.details->primskills.size(); i++)
-			new CLabel(75 + 28 * i, 58, FONT_SMALL, CENTER, Colors::WHITE,
-					   boost::lexical_cast<std::string>(hero.details->primskills[i]));
+		for(size_t i = 0; i < hero.details->primskills.size(); i++)
+			labels.push_back(std::make_shared<CLabel>(75 + 28 * i, 58, FONT_SMALL, CENTER, Colors::WHITE,
+					   boost::lexical_cast<std::string>(hero.details->primskills[i])));
 
-		new CLabel(158, 98, FONT_TINY, CENTER, Colors::WHITE,
-				   boost::lexical_cast<std::string>(hero.details->mana));
+		labels.push_back(std::make_shared<CLabel>(158, 98, FONT_TINY, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(hero.details->mana)));
 
-		new CAnimImage("IMRL22", hero.details->morale + 3, 0, 5, 74);
-		new CAnimImage("ILCK22", hero.details->luck + 3, 0, 5, 91);
+		morale = std::make_shared<CAnimImage>("IMRL22", hero.details->morale + 3, 0, 5, 74);
+		luck = std::make_shared<CAnimImage>("ILCK22", hero.details->luck + 3, 0, 5, 91);
 	}
 }
 
@@ -299,61 +304,64 @@ CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero):
 	init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED));
 }
 
-void CTownTooltip::init(const InfoAboutTown &town)
+void CTownTooltip::init(const InfoAboutTown & town)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
 	//order of icons in def: fort, citadel, castle, no fort
 	size_t fortIndex = town.fortLevel ? town.fortLevel - 1 : 3;
 
-	new CAnimImage("ITMCLS", fortIndex, 0, 105, 31);
+	fort = std::make_shared<CAnimImage>("ITMCLS", fortIndex, 0, 105, 31);
 
 	assert(town.tType);
 
 	size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->modh->settings.MAX_BUILDING_PER_TURN];
 
-	new CAnimImage("itpt", iconIndex, 0, 3, 2);
+	build = std::make_shared<CAnimImage>("itpt", iconIndex, 0, 3, 2);
 
 	if(town.details)
 	{
-		new CAnimImage("ITMTLS", town.details->hallLevel, 0, 67, 31);
+		fort = std::make_shared<CAnimImage>("ITMTLS", town.details->hallLevel, 0, 67, 31);
 
-		if (town.details->goldIncome)
-			new CLabel(157, 58, FONT_TINY, CENTER, Colors::WHITE,
+		if(town.details->goldIncome)
+		{
+			income = std::make_shared<CLabel>(157, 58, FONT_TINY, CENTER, Colors::WHITE,
 					   boost::lexical_cast<std::string>(town.details->goldIncome));
-
+		}
 		if(town.details->garrisonedHero) //garrisoned hero icon
-			new CPicture("TOWNQKGH", 149, 76);
+			garrisonedHero = std::make_shared<CPicture>("TOWNQKGH", 149, 76);
 
 		if(town.details->customRes)//silo is built
 		{
-			if (town.tType->primaryRes == Res::WOOD_AND_ORE )// wood & ore
+			if(town.tType->primaryRes == Res::WOOD_AND_ORE )// wood & ore
 			{
-				new CAnimImage("SMALRES", Res::WOOD, 0, 7, 75);
-				new CAnimImage("SMALRES", Res::ORE , 0, 7, 88);
+				res1 = std::make_shared<CAnimImage>("SMALRES", Res::WOOD, 0, 7, 75);
+				res2 = std::make_shared<CAnimImage>("SMALRES", Res::ORE , 0, 7, 88);
 			}
 			else
-				new CAnimImage("SMALRES", town.tType->primaryRes, 0, 7, 81);
+			{
+				res1 = std::make_shared<CAnimImage>("SMALRES", town.tType->primaryRes, 0, 7, 81);
+			}
 		}
 	}
 }
 
-CTownTooltip::CTownTooltip(Point pos, const InfoAboutTown &town):
-	CArmyTooltip(pos, town)
+CTownTooltip::CTownTooltip(Point pos, const InfoAboutTown & town)
+	: CArmyTooltip(pos, town)
 {
 	init(town);
 }
 
-CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town):
-	CArmyTooltip(pos, InfoAboutTown(town, true))
+CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town)
+	: CArmyTooltip(pos, InfoAboutTown(town, true))
 {
 	init(InfoAboutTown(town, true));
 }
 
-
-void MoraleLuckBox::set(const IBonusBearer *node)
+void MoraleLuckBox::set(const IBonusBearer * node)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+
 	const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:}
 	const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck
 	const int neutralDescr[] = {60, 86}; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat.
@@ -363,13 +371,15 @@ void MoraleLuckBox::set(const IBonusBearer *node)
 	int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal};
 	TBonusListPtr modifierList(new BonusList());
 
-	if (node)
+	if(node)
 	{
 		modifierList = node->getBonuses(Selector::type(bonusType[morale]));
 		bonusValue = (node->*getValue[morale])();
 	}
 	else
+	{
 		bonusValue = 0;
+	}
 
 	int mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good
 	hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt];
@@ -420,23 +430,22 @@ void MoraleLuckBox::set(const IBonusBearer *node)
 	else
 		imageName = morale ? "IMRL42" : "ILCK42";
 
-	delete image;
-	image = new CAnimImage(imageName, bonusValue + 3);
+	image = std::make_shared<CAnimImage>(imageName, bonusValue + 3);
 	image->moveBy(Point(pos.w/2 - image->pos.w/2, pos.h/2 - image->pos.h/2));//center icon
 }
 
-MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small):
-	image(nullptr),
-	morale(Morale),
+MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small)
+	: morale(Morale),
 	small(Small)
 {
 	bonusValue = 0;
 	pos = r + pos;
+	defActions = 255-DISPOSE;
 }
 
-CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool Animated)
+CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool Animated)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	pos.x+=x;
 	pos.y+=y;
 
@@ -445,20 +454,20 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool An
 	assert(CGI->townh->factions.size() > faction);
 
 	if(Big)
-		bg = new CPicture(CGI->townh->factions[faction]->creatureBg130);
+		bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg130);
 	else
-		bg = new CPicture(CGI->townh->factions[faction]->creatureBg120);
-	anim = new CCreatureAnim(0, 0, cre->animDefName, Rect());
+		bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg120);
+	anim = std::make_shared<CCreatureAnim>(0, 0, cre->animDefName, Rect());
 	anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h);
 	anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON));
 
-	amount = new CLabel(bg->pos.w, bg->pos.h, FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE);
+	amount = std::make_shared<CLabel>(bg->pos.w, bg->pos.h, FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE);
 
 	pos.w = bg->pos.w;
 	pos.h = bg->pos.h;
 }
 
-void CCreaturePic::show(SDL_Surface *to)
+void CCreaturePic::show(SDL_Surface * to)
 {
 	// redraw everything in a proper order
 	bg->showAll(to);
@@ -468,7 +477,7 @@ void CCreaturePic::show(SDL_Surface *to)
 
 void CCreaturePic::setAmount(int newAmount)
 {
-	if (newAmount != 0)
+	if(newAmount != 0)
 		amount->setText(boost::lexical_cast<std::string>(newAmount));
 	else
 		amount->setText("");

+ 33 - 18
client/widgets/MiscWidgets.h

@@ -15,7 +15,6 @@ class CLabel;
 class CCreatureAnim;
 class CComponent;
 class CGGarrison;
-class CSelectableComponent;
 struct InfoAboutArmy;
 class CArmedInstance;
 class IBonusBearer;
@@ -40,7 +39,7 @@ public:
 	std::string text;
 
 	LRClickableAreaWText();
-	LRClickableAreaWText(const Rect &Pos, const std::string &HoverText = "", const std::string &ClickText = "");
+	LRClickableAreaWText(const Rect & Pos, const std::string & HoverText = "", const std::string & ClickText = "");
 	virtual ~LRClickableAreaWText();
 	void init();
 
@@ -51,9 +50,12 @@ public:
 /// base class for hero/town/garrison tooltips
 class CArmyTooltip : public CIntObject
 {
-	void init(const InfoAboutArmy &army);
+	std::shared_ptr<CLabel> title;
+	std::vector<std::shared_ptr<CAnimImage>> icons;
+	std::vector<std::shared_ptr<CLabel>> subtitles;
+	void init(const InfoAboutArmy & army);
 public:
-	CArmyTooltip(Point pos, const InfoAboutArmy &army);
+	CArmyTooltip(Point pos, const InfoAboutArmy & army);
 	CArmyTooltip(Point pos, const CArmedInstance * army);
 };
 
@@ -62,9 +64,14 @@ public:
 /// background for tooltip: HEROQVBK
 class CHeroTooltip : public CArmyTooltip
 {
-	void init(const InfoAboutHero &hero);
+	std::shared_ptr<CAnimImage> portrait;
+	std::vector<std::shared_ptr<CLabel>> labels;
+	std::shared_ptr<CAnimImage> morale;
+	std::shared_ptr<CAnimImage> luck;
+
+	void init(const InfoAboutHero & hero);
 public:
-	CHeroTooltip(Point pos, const InfoAboutHero &hero);
+	CHeroTooltip(Point pos, const InfoAboutHero & hero);
 	CHeroTooltip(Point pos, const CGHeroInstance * hero);
 };
 
@@ -73,9 +80,17 @@ public:
 /// background for tooltip: TOWNQVBK
 class CTownTooltip : public CArmyTooltip
 {
-	void init(const InfoAboutTown &town);
+	std::shared_ptr<CAnimImage> fort;
+	std::shared_ptr<CAnimImage> hall;
+	std::shared_ptr<CAnimImage> build;
+	std::shared_ptr<CLabel> income;
+	std::shared_ptr<CPicture> garrisonedHero;
+	std::shared_ptr<CAnimImage> res1;
+	std::shared_ptr<CAnimImage> res2;
+
+	void init(const InfoAboutTown & town);
 public:
-	CTownTooltip(Point pos, const InfoAboutTown &town);
+	CTownTooltip(Point pos, const InfoAboutTown & town);
 	CTownTooltip(Point pos, const CGTownInstance * town);
 };
 
@@ -83,22 +98,21 @@ public:
 class CCreaturePic : public CIntObject
 {
 private:
-	CPicture *bg;
-	CCreatureAnim *anim; //displayed animation
-	CLabel * amount;
+	std::shared_ptr<CPicture> bg;
+	std::shared_ptr<CCreatureAnim> anim; //displayed animation
+	std::shared_ptr<CLabel> amount;
 
-	void show(SDL_Surface *to) override;
+	void show(SDL_Surface * to) override;
 public:
-	CCreaturePic(int x, int y, const CCreature *cre, bool Big=true, bool Animated=true);
-
+	CCreaturePic(int x, int y, const CCreature * cre, bool Big=true, bool Animated=true);
 	void setAmount(int newAmount);
 };
 
 /// Resource bar like that at the bottom of the adventure map screen
 class CMinorResDataBar : public CIntObject
 {
+	std::shared_ptr<CPicture> background;
 public:
-	SDL_Surface *bg; //background bitmap
 	void show(SDL_Surface * to) override;
 	void showAll(SDL_Surface * to) override;
 	CMinorResDataBar();
@@ -109,8 +123,9 @@ public:
 class CHeroArea: public CIntObject
 {
 	const CGHeroInstance * hero;
-public:
+	std::shared_ptr<CAnimImage> portrait;
 
+public:
 	CHeroArea(int x, int y, const CGHeroInstance * _hero);
 
 	void clickLeft(tribool down, bool previousState) override;
@@ -128,7 +143,7 @@ public:
 	virtual void clickRight(tribool down, bool previousState) override;
 
 	LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
-	CComponent * createComponent() const;
+	std::shared_ptr<CComponent> createComponent() const;
 };
 
 /// Opens town screen by left-clicking on it
@@ -143,7 +158,7 @@ public:
 
 class MoraleLuckBox : public LRClickableAreaWTextComp
 {
-	CAnimImage *image;
+	std::shared_ptr<CAnimImage> image;
 public:
 	bool morale; //true if morale, false if luck
 	bool small;

+ 46 - 51
client/widgets/ObjectLists.cpp

@@ -13,53 +13,45 @@
 #include "../gui/CGuiHandler.h"
 #include "Buttons.h"
 
-
-static void intDeleter(CIntObject* object)
-{
-	delete object;
-}
-
-CObjectList::CObjectList(CreateFunc create, DestroyFunc destroy):
-createObject(create),
-destroyObject(destroy)
+CObjectList::CObjectList(CreateFunc create)
+	: createObject(create)
 {
-	if (!destroyObject)
-		destroyObject = intDeleter;
 }
 
-void CObjectList::deleteItem(CIntObject* item)
+void CObjectList::deleteItem(std::shared_ptr<CIntObject> item)
 {
-	if (!item)
+	if(!item)
 		return;
-	removeChild(item);
-	destroyObject(item);
+	item->deactivate();
+	removeChild(item.get());
 }
 
-CIntObject* CObjectList::createItem(size_t index)
+std::shared_ptr<CIntObject> CObjectList::createItem(size_t index)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	CIntObject * item = createObject(index);
-	if (item == nullptr)
-		item = new CIntObject();
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	std::shared_ptr<CIntObject> item = createObject(index);
+	if(!item)
+		item = std::make_shared<CIntObject>();
 
 	item->recActions = defActions;
-
-	addChild(item);
+	addChild(item.get());
+	item->activate();
 	return item;
 }
 
-CTabbedInt::CTabbedInt(CreateFunc create, DestroyFunc destroy, Point position, size_t ActiveID):
-CObjectList(create, destroy),
-activeTab(nullptr),
-activeID(ActiveID)
+CTabbedInt::CTabbedInt(CreateFunc create, Point position, size_t ActiveID)
+	: CObjectList(create),
+	activeTab(nullptr),
+	activeID(ActiveID)
 {
+	defActions &= ~DISPOSE;
 	pos += position;
 	reset();
 }
 
 void CTabbedInt::setActive(size_t which)
 {
-	if (which != activeID)
+	if(which != activeID)
 	{
 		activeID = which;
 		reset();
@@ -72,30 +64,29 @@ void CTabbedInt::reset()
 	activeTab = createItem(activeID);
 	activeTab->moveTo(pos.topLeft());
 
-	if (active)
+	if(active)
 		redraw();
 }
 
-CIntObject * CTabbedInt::getItem()
+std::shared_ptr<CIntObject> CTabbedInt::getItem()
 {
 	return activeTab;
 }
 
-CListBox::CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize,
-				   size_t TotalSize, size_t InitialPos, int Slider, Rect SliderPos):
-	CObjectList(create, destroy),
+CListBox::CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize,
+		size_t TotalSize, size_t InitialPos, int Slider, Rect SliderPos)
+	: CObjectList(create),
 	first(InitialPos),
 	totalSize(TotalSize),
-	itemOffset(ItemOffset),
-    slider(nullptr)
+	itemOffset(ItemOffset)
 {
 	pos += Pos;
 	items.resize(VisibleSize, nullptr);
 
-	if (Slider & 1)
+	if(Slider & 1)
 	{
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		slider = new CSlider(SliderPos.topLeft(), SliderPos.w, std::bind(&CListBox::moveToPos, this, _1),
+		OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+		slider = std::make_shared<CSlider>(SliderPos.topLeft(), SliderPos.w, std::bind(&CListBox::moveToPos, this, _1),
 			VisibleSize, TotalSize, InitialPos, Slider & 2, Slider & 4 ? CSlider::BLUE : CSlider::BROWN);
 	}
 	reset();
@@ -142,22 +133,22 @@ size_t CListBox::size()
 	return totalSize;
 }
 
-CIntObject * CListBox::getItem(size_t which)
+std::shared_ptr<CIntObject> CListBox::getItem(size_t which)
 {
-	if (which < first || which > first + items.size() || which > totalSize)
-		return nullptr;
+	if(which < first || which > first + items.size() || which > totalSize)
+		return std::shared_ptr<CIntObject>();
 
 	size_t i=first;
 	for (auto iter = items.begin(); iter != items.end(); iter++, i++)
 		if( i == which)
 			return *iter;
-	return nullptr;
+	return std::shared_ptr<CIntObject>();
 }
 
-size_t CListBox::getIndexOf(CIntObject *item)
+size_t CListBox::getIndexOf(std::shared_ptr<CIntObject> item)
 {
 	size_t i=first;
-	for (auto iter = items.begin(); iter != items.end(); iter++, i++)
+	for(auto iter = items.begin(); iter != items.end(); iter++, i++)
 		if(*iter == item)
 			return i;
 	return size_t(-1);
@@ -166,7 +157,7 @@ size_t CListBox::getIndexOf(CIntObject *item)
 void CListBox::scrollTo(size_t which)
 {
 	//scroll up
-	if (first > which)
+	if(first > which)
 		moveToPos(which);
 	//scroll down
 	else if (first + items.size() <= which && which < totalSize)
@@ -177,7 +168,7 @@ void CListBox::moveToPos(size_t which)
 {
 	//Calculate new position
 	size_t maxPossible;
-	if (totalSize > items.size())
+	if(totalSize > items.size())
 		maxPossible = totalSize - items.size();
 	else
 		maxPossible = 0;
@@ -185,11 +176,15 @@ void CListBox::moveToPos(size_t which)
 	size_t newPos = std::min(which, maxPossible);
 
 	//If move distance is 1 (most of calls from Slider) - use faster shifts instead of resetting all items
-	if (first - newPos == 1)
+	if(first - newPos == 1)
+	{
 		moveToPrev();
-	else if (newPos - first == 1)
+	}
+	else if(newPos - first == 1)
+	{
 		moveToNext();
-	else if (newPos != first)
+	}
+	else if(newPos != first)
 	{
 		first = newPos;
 		reset();
@@ -199,7 +194,7 @@ void CListBox::moveToPos(size_t which)
 void CListBox::moveToNext()
 {
 	//Remove front item and insert new one to end
-	if (first + items.size() < totalSize)
+	if(first + items.size() < totalSize)
 	{
 		first++;
 		deleteItem(items.front());
@@ -212,7 +207,7 @@ void CListBox::moveToNext()
 void CListBox::moveToPrev()
 {
 	//Remove last item and insert new one at start
-	if (first)
+	if(first)
 	{
 		first--;
 		deleteItem(items.back());
@@ -227,7 +222,7 @@ size_t CListBox::getPos()
 	return first;
 }
 
-const std::list<CIntObject *> &CListBox::getItems()
+const std::list<std::shared_ptr<CIntObject>> & CListBox::getItems()
 {
 	return items;
 }

+ 13 - 15
client/widgets/ObjectLists.h

@@ -22,52 +22,50 @@ class CAnimation;
 class CObjectList : public CIntObject
 {
 public:
-	typedef std::function<CIntObject* (size_t)> CreateFunc;
-	typedef std::function<void(CIntObject *)> DestroyFunc;
+	typedef std::function<std::shared_ptr<CIntObject>(size_t)> CreateFunc;
 
 private:
 	CreateFunc createObject;
-	DestroyFunc destroyObject;
 
 protected:
 	//Internal methods for safe creation of items (Children capturing and activation/deactivation if needed)
-	void deleteItem(CIntObject* item);
-	CIntObject* createItem(size_t index);
+	void deleteItem(std::shared_ptr<CIntObject> item);
+	std::shared_ptr<CIntObject> createItem(size_t index);
 
-	CObjectList(CreateFunc create, DestroyFunc destroy = DestroyFunc());//Protected constructor
+	CObjectList(CreateFunc create);
 };
 
 /// Window element with multiple tabs
 class CTabbedInt : public CObjectList
 {
 private:
-	CIntObject * activeTab;
+	std::shared_ptr<CIntObject> activeTab;
 	size_t activeID;
 
 public:
 	//CreateFunc, DestroyFunc - see CObjectList
 	//Pos - position of object, all tabs will be moved to this position
 	//ActiveID - ID of initially active tab
-	CTabbedInt(CreateFunc create, DestroyFunc destroy = DestroyFunc(), Point position=Point(), size_t ActiveID=0);
+	CTabbedInt(CreateFunc create, Point position=Point(), size_t ActiveID=0);
 
 	void setActive(size_t which);
 	//recreate active tab
 	void reset();
 
 	//return currently active item
-	CIntObject * getItem();
+	std::shared_ptr<CIntObject> getItem();
 };
 
 /// List of IntObjects with optional slider
 class CListBox : public CObjectList
 {
 private:
-	std::list< CIntObject* > items;
+	std::list<std::shared_ptr<CIntObject>> items;
 	size_t first;
 	size_t totalSize;
 
 	Point itemOffset;
-	CSlider * slider;
+	std::shared_ptr<CSlider> slider;
 
 	void updatePositions();
 public:
@@ -78,7 +76,7 @@ public:
 	//TotalSize
 	//Slider - slider style, bit field: 1 = present(disabled), 2=horisontal(vertical), 4=blue(brown)
 	//SliderPos - position of slider, if present
-	CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize,
+	CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize,
 		size_t TotalSize, size_t InitialPos=0, int Slider=0, Rect SliderPos=Rect() );
 
 	//recreate all visible items
@@ -89,13 +87,13 @@ public:
 	size_t size();
 
 	//return item with index which or null if not present
-	CIntObject * getItem(size_t which);
+	std::shared_ptr<CIntObject> getItem(size_t which);
 
 	//return currently active items
-	const std::list< CIntObject * > & getItems();
+	const std::list<std::shared_ptr<CIntObject>> & getItems();
 
 	//get index of this item. -1 if not found
-	size_t getIndexOf(CIntObject * item);
+	size_t getIndexOf(std::shared_ptr<CIntObject> item);
 
 	//scroll list to make item which visible
 	void scrollTo(size_t which);

+ 41 - 41
client/widgets/TextControls.cpp

@@ -36,17 +36,16 @@ void CLabel::showAll(SDL_Surface * to)
 
 }
 
-CLabel::CLabel(int x, int y, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text)
-:CTextContainer(Align, Font, Color), text(Text)
+CLabel::CLabel(int x, int y, EFonts Font, EAlignment Align, const SDL_Color & Color, const std::string & Text)
+	: CTextContainer(Align, Font, Color), text(Text)
 {
 	type |= REDRAW_PARENT;
 	autoRedraw = true;
 	pos.x += x;
 	pos.y += y;
 	pos.w = pos.h = 0;
-	bg = nullptr;
 
-	if (alignment == TOPLEFT) // causes issues for MIDDLE
+	if(alignment == TOPLEFT) // causes issues for MIDDLE
 	{
 		pos.w = graphics->fonts[font]->getStringWidth(visibleText().c_str());
 		pos.h = graphics->fonts[font]->getLineHeight();
@@ -73,7 +72,7 @@ void CLabel::setText(const std::string &Txt)
 	text = Txt;
 	if(autoRedraw)
 	{
-		if(bg || !parent)
+		if(background || !parent)
 			redraw();
 		else
 			parent->redraw();
@@ -85,7 +84,7 @@ void CLabel::setColor(const SDL_Color & Color)
 	color = Color;
 	if(autoRedraw)
 	{
-		if(bg || !parent)
+		if(background || !parent)
 			redraw();
 		else
 			parent->redraw();
@@ -259,14 +258,16 @@ Rect CMultiLineLabel::getTextLocation()
 	return Rect();
 }
 
-CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color &Color):
-	font(Font), align(Align), color(Color)
-{}
+CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color & Color)
+	: font(Font), align(Align), color(Color)
+{
+	defActions = 255-DISPOSE;
+}
 
 void CLabelGroup::add(int x, int y, const std::string &text)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	labels.push_back(new CLabel(x, y, font, align, color, text));
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	labels.push_back(std::make_shared<CLabel>(x, y, font, align, color, text));
 }
 
 size_t CLabelGroup::currentSize() const
@@ -278,8 +279,8 @@ CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts F
 	sliderStyle(SliderStyle),
 	slider(nullptr)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	label = new CMultiLineLabel(rect, Font, Align, Color);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	label = std::make_shared<CMultiLineLabel>(rect, Font, Align, Color);
 
 	type |= REDRAW_PARENT;
 	pos.x += rect.x;
@@ -302,9 +303,8 @@ void CTextBox::resize(Point newSize)
 	pos.h = newSize.y;
 	label->pos.w = pos.w;
 	label->pos.h = pos.h;
-	if (slider)
-		vstd::clear_pointer(slider); // will be recreated if needed later
 
+	slider.reset();
 	setText(label->getText()); // force refresh
 }
 
@@ -315,7 +315,7 @@ void CTextBox::setText(const std::string &text)
 	if(label->textSize.y <= label->pos.h && slider)
 	{
 		// slider is no longer needed
-		vstd::clear_pointer(slider);
+		slider.reset();
 	}
 	else if(slider)
 	{
@@ -330,8 +330,8 @@ void CTextBox::setText(const std::string &text)
 		label->pos.w = pos.w - 32;
 		label->setText(text);
 
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		slider = new CSlider(Point(pos.w - 32, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1),
+		OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+		slider = std::make_shared<CSlider>(Point(pos.w - 32, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1),
 		                     label->pos.h, label->textSize.y, 0, false, CSlider::EStyle(sliderStyle));
 		slider->setScrollStep(graphics->fonts[label->font]->getLineHeight());
 	}
@@ -348,28 +348,28 @@ void CGStatusBar::clear()
 	setText("");
 }
 
-CGStatusBar::CGStatusBar(CPicture *BG, EFonts Font, EAlignment Align, const SDL_Color &Color)
-: CLabel(BG->pos.x, BG->pos.y, Font, Align, Color, "")
+CGStatusBar::CGStatusBar(std::shared_ptr<CPicture> background_, EFonts Font, EAlignment Align, const SDL_Color & Color)
+	: CLabel(background_->pos.x, background_->pos.y, Font, Align, Color, "")
 {
 	init();
-	bg = BG;
-	addChild(bg);
-	pos = bg->pos;
+	background = background_;
+	addChild(background.get());
+	pos = background->pos;
 	getBorderSize();
 	textLock = false;
 }
 
 CGStatusBar::CGStatusBar(int x, int y, std::string name, int maxw)
-: CLabel(x, y, FONT_SMALL, CENTER)
+	: CLabel(x, y, FONT_SMALL, CENTER)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	init();
-	bg = new CPicture(name);
-	pos = bg->pos;
+	background = std::make_shared<CPicture>(name);
+	pos = background->pos;
 	if((unsigned int)maxw < pos.w)
 	{
 		vstd::amin(pos.w, maxw);
-		bg->srcRect = new Rect(0, 0, maxw, pos.h);
+		background->srcRect = new Rect(0, 0, maxw, pos.h);
 	}
 	textLock = false;
 }
@@ -410,8 +410,8 @@ void CGStatusBar::lock(bool shouldLock)
 	textLock = shouldLock;
 }
 
-CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB):
-	CLabel(Pos.x, Pos.y, font, CENTER),
+CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB)
+	: CLabel(Pos.x, Pos.y, font, CENTER),
 	cb(CB)
 {
 	type |= REDRAW_PARENT;
@@ -419,38 +419,38 @@ CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(co
 	pos.h = Pos.h;
 	pos.w = Pos.w;
 	captureAllKeys = true;
-	bg = nullptr;
+	background.reset();
 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
 	giveFocus();
 }
 
-CTextInput::CTextInput( const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB )
-:cb(CB)
+CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB)
+	:cb(CB)
 {
 	focus = false;
 	pos += Pos;
 	captureAllKeys = true;
 	OBJ_CONSTRUCTION;
-	bg = new CPicture(bgName, bgOffset.x, bgOffset.y);
+	background = std::make_shared<CPicture>(bgName, bgOffset.x, bgOffset.y);
 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
 	giveFocus();
 }
 
-CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
+CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf)
 {
 	focus = false;
 	pos += Pos;
 	captureAllKeys = true;
 	OBJ_CONSTRUCTION;
-	bg = new CPicture(Pos, 0, true);
+	background = std::make_shared<CPicture>(Pos, 0, true);
 	Rect hlp = Pos;
 	if(srf)
-		CSDL_Ext::blitSurface(srf, &hlp, *bg, nullptr);
+		CSDL_Ext::blitSurface(srf, &hlp, *background.get(), nullptr);
 	else
-		SDL_FillRect(*bg, nullptr, 0);
-	pos.w = bg->pos.w;
-	pos.h = bg->pos.h;
-	bg->pos = pos;
+		SDL_FillRect(*background.get(), nullptr, 0);
+	pos.w = background->pos.w;
+	pos.h = background->pos.h;
+	background->pos = pos;
 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
 	giveFocus();
 }

+ 10 - 11
client/widgets/TextControls.h

@@ -40,7 +40,7 @@ protected:
 	Point getBorderSize() override;
 	virtual std::string visibleText();
 
-	CPicture *bg;
+	std::shared_ptr<CPicture> background;
 public:
 
 	std::string text;
@@ -60,7 +60,7 @@ public:
 /// Small helper class to manage group of similar labels
 class CLabelGroup : public CIntObject
 {
-	std::list<CLabel*> labels;
+	std::vector<std::shared_ptr<CLabel>> labels;
 	EFonts font;
 	EAlignment align;
 	SDL_Color color;
@@ -103,13 +103,13 @@ class CTextBox : public CIntObject
 {
 	int sliderStyle;
 public:
-	CMultiLineLabel * label;
-	CSlider *slider;
+	std::shared_ptr<CMultiLineLabel> label;
+	std::shared_ptr<CSlider> slider;
 
-	CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE);
+	CTextBox(std::string Text, const Rect & rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color & Color = Colors::WHITE);
 
 	void resize(Point newSize);
-	void setText(const std::string &Txt);
+	void setText(const std::string & Txt);
 	void sliderMoved(int to);
 };
 
@@ -119,19 +119,18 @@ class CGStatusBar : public CLabel
 	bool textLock; //Used for blocking changes to the text
 	void init();
 
-	CGStatusBar *oldStatusBar;
+	CGStatusBar * oldStatusBar;
 protected:
 	Point getBorderSize() override;
 
 public:
-
 	void clear();//clears statusbar and refreshes
 	void setText(const std::string & Text) override; //prints text and refreshes statusbar
 
 	void show(SDL_Surface * to) override; //shows statusbar (with current text)
 
-	CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar
-	CGStatusBar(int x, int y, std::string name, int maxw=-1);
+	CGStatusBar(std::shared_ptr<CPicture> background_, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color & Color = Colors::WHITE);
+	CGStatusBar(int x, int y, std::string name, int maxw = -1);
 	~CGStatusBar();
 
 	void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called
@@ -180,7 +179,7 @@ public:
 	void clickLeft(tribool down, bool previousState) override;
 	void keyPressed(const SDL_KeyboardEvent & key) override;
 	bool captureThisEvent(const SDL_KeyboardEvent & key) override;
-	
+
 	void textInputed(const SDL_TextInputEvent & event) override;
 	void textEdited(const SDL_TextEditingEvent & event) override;
 

+ 52 - 49
client/windows/CAdvmapInterface.cpp

@@ -90,7 +90,7 @@ static void setScrollingCursor(ui8 direction)
 CTerrainRect::CTerrainRect()
 	: fadeSurface(nullptr),
 	  lastRedrawStatus(EMapAnimRedrawStatus::OK),
-	  fadeAnim(new CFadeAnimation()),
+	  fadeAnim(std::make_shared<CFadeAnimation>()),
 	  curHoveredTile(-1,-1,-1),
 	  currentPath(nullptr)
 {
@@ -106,9 +106,8 @@ CTerrainRect::CTerrainRect()
 
 CTerrainRect::~CTerrainRect()
 {
-	if (fadeSurface)
+	if(fadeSurface)
 		SDL_FreeSurface(fadeSurface);
-	delete fadeAnim;
 }
 
 void CTerrainRect::deactivate()
@@ -475,12 +474,16 @@ void CResDataBar::clickRight(tribool down, bool previousState)
 {
 }
 
-CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist)
+CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
 {
-	bg = BitmapHandler::loadBitmap(defname);
-	CSDL_Ext::setDefaultColorKey(bg);
-	graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
-	pos = genRect(bg->h, bg->w, pos.x+x, pos.y+y);
+	pos.x += x;
+	pos.y += y;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CPicture>(defname, 0, 0);
+	background->colorize(LOCPLINT->playerID);
+
+	pos.w = background->bg->w;
+	pos.h = background->bg->h;
 
 	txtpos.resize(8);
 	for (int i = 0; i < 8 ; i++)
@@ -496,10 +499,15 @@ CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int
 
 CResDataBar::CResDataBar()
 {
-	bg = BitmapHandler::loadBitmap(ADVOPT.resdatabarG);
-	CSDL_Ext::setDefaultColorKey(bg);
-	graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
-	pos = genRect(bg->h,bg->w,ADVOPT.resdatabarX,ADVOPT.resdatabarY);
+	pos.x += ADVOPT.resdatabarX;
+	pos.y += ADVOPT.resdatabarY;
+
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
+	background->colorize(LOCPLINT->playerID);
+
+	pos.w = background->bg->w;
+	pos.h = background->bg->h;
 
 	txtpos.resize(8);
 	for (int i = 0; i < 8 ; i++)
@@ -512,13 +520,11 @@ CResDataBar::CResDataBar()
 				+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
 }
 
-CResDataBar::~CResDataBar()
-{
-	SDL_FreeSurface(bg);
-}
+CResDataBar::~CResDataBar() = default;
+
 void CResDataBar::draw(SDL_Surface * to)
 {
-	blitAt(bg,pos.x,pos.y,to);
+	//TODO: all this should be labels, but they require proper text update on change
 	for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1))
 	{
 		std::string text = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i));
@@ -541,6 +547,7 @@ void CResDataBar::show(SDL_Surface * to)
 
 void CResDataBar::showAll(SDL_Surface * to)
 {
+	CIntObject::showAll(to);
 	draw(to);
 }
 
@@ -552,13 +559,13 @@ CAdvMapInt::CAdvMapInt():
 	heroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD),
 	townList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD),
 	infoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192)), state(NA),
-  spellBeingCasted(nullptr), position(int3(0, 0, 0)), selection(nullptr),
-  updateScreen(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0),
+	spellBeingCasted(nullptr), position(int3(0, 0, 0)), selection(nullptr),
+	updateScreen(false), anim(0), animValHitCount(0), heroAnim(0), heroAnimValHitCount(0),
 	activeMapPanel(nullptr), duringAITurn(false), scrollingDir(0), scrollingState(false),
 	swipeEnabled(settings["general"]["swipe"].Bool()), swipeMovementRequested(false),
 	swipeTargetPosition(int3(-1, -1, -1))
 {
-  adventureInt = this;
+	adventureInt = this;
 	pos.x = pos.y = 0;
 	pos.w = screen->w;
 	pos.h = screen->h;
@@ -580,18 +587,17 @@ CAdvMapInt::CAdvMapInt():
 	}
 
 	worldViewIcons = std::make_shared<CAnimation>("VwSymbol");//todo: customize with ADVOPT
-	//preload all for faster map drawing
-	worldViewIcons->load();//TODO: make special method in CAnimation fro that
+	worldViewIcons->preload();
 
-	for (int g=0; g<ADVOPT.gemG.size(); ++g)
+	for(int g = 0; g < ADVOPT.gemG.size(); ++g)
 	{
-		gems.push_back(new CAnimImage(ADVOPT.gemG[g], 0, 0, ADVOPT.gemX[g], ADVOPT.gemY[g]));
+		gems.push_back(std::make_shared<CAnimImage>(ADVOPT.gemG[g], 0, 0, ADVOPT.gemX[g], ADVOPT.gemY[g]));
 	}
 
-	auto makeButton = [&] (int textID, std::function<void()> callback, config::ButtonInfo info, int key) -> CButton *
+	auto makeButton = [&](int textID, std::function<void()> callback, config::ButtonInfo info, int key) -> std::shared_ptr<CButton>
 	{
-		auto button = new CButton(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured);
-		for (auto image : info.additionalDefs)
+		auto button = std::make_shared<CButton>(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured);
+		for(auto image : info.additionalDefs)
 			button->addImage(image);
 		return button;
 	};
@@ -609,9 +615,9 @@ CAdvMapInt::CAdvMapInt():
 
 	int panelSpaceBottom = screen->h - resdatabar.pos.h - 4;
 
-	panelMain = new CAdvMapPanel(nullptr, Point(0, 0));
+	panelMain = std::make_shared<CAdvMapPanel>(nullptr, Point(0, 0));
 	// TODO correct drawing position
-	panelWorldView = new CAdvMapWorldViewPanel(worldViewIcons, bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
+	panelWorldView = std::make_shared<CAdvMapWorldViewPanel>(worldViewIcons, bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
 
 	panelMain->addChildColorableButton(kingOverview);
 	panelMain->addChildColorableButton(underground);
@@ -640,7 +646,7 @@ CAdvMapInt::CAdvMapInt():
 	worldViewPuzzleConfig.y = 343 + 195;
 	worldViewPuzzleConfig.playerColoured = false;
 	panelWorldView->addChildToPanel( // no help text for this one
-		new CButton(Point(worldViewPuzzleConfig.x, worldViewPuzzleConfig.y), worldViewPuzzleConfig.defName, std::pair<std::string, std::string>(),
+		std::make_shared<CButton>(Point(worldViewPuzzleConfig.x, worldViewPuzzleConfig.y), worldViewPuzzleConfig.defName, std::pair<std::string, std::string>(),
 				std::bind(&CPlayerInterface::showPuzzleMap,LOCPLINT), SDLK_p, worldViewPuzzleConfig.playerColoured), ACTIVATE | DEACTIVATE);
 
 	config::ButtonInfo worldViewScale1xConfig = config::ButtonInfo();
@@ -684,19 +690,19 @@ CAdvMapInt::CAdvMapInt():
 	for (int i = 0; i < 5; ++i)
 	{
 		panelWorldView->addChildIcon(std::pair<int, Point>(i, Point(5, 58 + i * 20)), iconColorMultiplier);
-		panelWorldView->addChildToPanel(new CLabel(wvLeft + 45, 263 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
+		panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft + 45, 263 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
 												Colors::WHITE, CGI->generaltexth->allTexts[612 + i]));
 	}
 	for (int i = 0; i < 7; ++i)
 	{
 		panelWorldView->addChildIcon(std::pair<int, Point>(i +  5, Point(5, 182 + i * 20)), iconColorMultiplier);
 		panelWorldView->addChildIcon(std::pair<int, Point>(i + 12, Point(160, 182 + i * 20)), iconColorMultiplier);
-		panelWorldView->addChildToPanel(new CLabel(wvLeft + 45, 387 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
+		panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft + 45, 387 + i * 20, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
 												Colors::WHITE, CGI->generaltexth->allTexts[619 + i]));
 	}
-	panelWorldView->addChildToPanel(new CLabel(wvLeft +   5, 367, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
+	panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft +   5, 367, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
 											Colors::WHITE, CGI->generaltexth->allTexts[617]));
-	panelWorldView->addChildToPanel(new CLabel(wvLeft + 185, 387, EFonts::FONT_SMALL, EAlignment::BOTTOMRIGHT,
+	panelWorldView->addChildToPanel(std::make_shared<CLabel>(wvLeft + 45, 367, EFonts::FONT_SMALL, EAlignment::TOPLEFT,
 											Colors::WHITE, CGI->generaltexth->allTexts[618]));
 
 	activeMapPanel = panelMain;
@@ -713,8 +719,6 @@ CAdvMapInt::CAdvMapInt():
 CAdvMapInt::~CAdvMapInt()
 {
 	SDL_FreeSurface(bg);
-
-	worldViewIcons->unload();
 }
 
 void CAdvMapInt::fshowOverview()
@@ -846,7 +850,7 @@ void CAdvMapInt::fendTurn()
 				auto path = LOCPLINT->getAndVerifyPath(hero);
 				if(!path || path->nodes.size() < 2 || !path->nodes[path->nodes.size()-2].turns)
 				{
-					LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), 0, false);
+					LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::bind(&CAdvMapInt::endingTurn, this), nullptr);
 					return;
 				}
 			}
@@ -996,7 +1000,7 @@ void CAdvMapInt::showAll(SDL_Surface * to)
 	show(to);
 
 
-	resdatabar.draw(to);
+	resdatabar.showAll(to);
 
 	statusbar.show(to);
 
@@ -1240,8 +1244,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
 		if(isActive() && LOCPLINT->ctrlPressed())
 		{
 			LOCPLINT->showYesNoDialog("Are you sure you want to restart game?",
-				[](){ LOCPLINT->sendCustomEvent(EUserEvent::RESTART_GAME); },
-				[](){}, true);
+				[](){ LOCPLINT->sendCustomEvent(EUserEvent::RESTART_GAME); }, nullptr);
 		}
 		return;
 	case SDLK_SPACE: //space - try to revisit current object with selected hero
@@ -1503,7 +1506,7 @@ void CAdvMapInt::setPlayer(PlayerColor Player)
 	panelMain->setPlayerColor(player);
 	panelWorldView->setPlayerColor(player);
 	panelWorldView->recolorIcons(player, player.getNum() * 19);
-	graphics->blueToPlayersAdv(resdatabar.bg,player);
+	resdatabar.background->colorize(player);
 }
 
 void CAdvMapInt::startTurn()
@@ -1926,24 +1929,24 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale)
 	}
 }
 
-CAdventureOptions::CAdventureOptions():
-	CWindowObject(PLAYER_COLORED, "ADVOPTS")
+CAdventureOptions::CAdventureOptions()
+	: CWindowObject(PLAYER_COLORED, "ADVOPTS")
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	viewWorld = new CButton(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v);
+	viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v);
 	viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT));
 
-	exit = new CButton(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
+	exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
 	exit->assignedKeys.insert(SDLK_ESCAPE);
 
-	scenInfo = new CButton(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i);
+	scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i);
 	scenInfo->addCallback(CAdventureOptions::showScenarioInfo);
 
-	puzzle = new CButton(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p);
+	puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p);
 	puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
 
-	dig = new CButton(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
+	dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
 	if(const CGHeroInstance *h = adventureInt->curHero())
 		dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
 	else

+ 27 - 23
client/windows/CAdvmapInterface.h

@@ -38,23 +38,27 @@ enum class EAdvMapMode
 	WORLD_VIEW
 };
 
-/// Adventure options dialogue where you can view the world, dig, play the replay of the last turn,...
+/// Adventure options dialog where you can view the world, dig, play the replay of the last turn,...
 class CAdventureOptions : public CWindowObject
 {
 public:
-	CButton *exit, *viewWorld, *puzzle, *dig, *scenInfo/*, *replay*/;
+	std::shared_ptr<CButton> exit;
+	std::shared_ptr<CButton> viewWorld;
+	std::shared_ptr<CButton> puzzle;
+	std::shared_ptr<CButton> dig;
+	std::shared_ptr<CButton> scenInfo;
+	/*std::shared_ptr<CButton> replay*/
 
 	CAdventureOptions();
 	static void showScenarioInfo();
 };
 
 /// Holds information about which tiles of the terrain are shown/not shown at the screen
-class CTerrainRect
-	:  public CIntObject
+class CTerrainRect : public CIntObject
 {
 	SDL_Surface * fadeSurface;
 	EMapAnimRedrawStatus lastRedrawStatus;
-	CFadeAnimation * fadeAnim;
+	std::shared_ptr<CFadeAnimation> fadeAnim;
 
 	int3 swipeInitialMapPos;
 	int3 swipeInitialRealPos;
@@ -69,10 +73,10 @@ public:
 	int tilesw, tilesh; //width and height of terrain to blit in tiles
 	int3 curHoveredTile;
 	int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
+	CGPath * currentPath;
 
 	CTerrainRect();
 	virtual ~CTerrainRect();
-	CGPath * currentPath;
 	void deactivate() override;
 	void clickLeft(tribool down, bool previousState) override;
 	void clickRight(tribool down, bool previousState) override;
@@ -90,7 +94,6 @@ public:
 	/// animates view by caching current surface and crossfading it with normal screen
 	void fadeFromCurrentView();
 	bool needsAnimUpdate();
-
 };
 
 /// Resources bar which shows information about how many gold, crystals,... you have
@@ -98,7 +101,8 @@ public:
 class CResDataBar : public CIntObject
 {
 public:
-	SDL_Surface * bg;
+	std::shared_ptr<CPicture> background;
+
 	std::vector<std::pair<int,int> > txtpos;
 	std::string datetext;
 
@@ -162,22 +166,22 @@ public:
 
 	SDL_Surface * bg;
 	SDL_Surface * bgWorldView;
-	std::vector<CAnimImage *> gems;
+	std::vector<std::shared_ptr<CAnimImage>> gems;
 	CMinimap minimap;
 	CGStatusBar statusbar;
 
-	CButton * kingOverview;
-	CButton * underground;
-	CButton * questlog;
-	CButton * sleepWake;
-	CButton * moveHero;
-	CButton * spellbook;
-	CButton * advOptions;
-	CButton * sysOptions;
-	CButton * nextHero;
-	CButton * endTurn;
+	std::shared_ptr<CButton> kingOverview;
+	std::shared_ptr<CButton> underground;
+	std::shared_ptr<CButton> questlog;
+	std::shared_ptr<CButton> sleepWake;
+	std::shared_ptr<CButton> moveHero;
+	std::shared_ptr<CButton> spellbook;
+	std::shared_ptr<CButton> advOptions;
+	std::shared_ptr<CButton> sysOptions;
+	std::shared_ptr<CButton> nextHero;
+	std::shared_ptr<CButton> endTurn;
 
-	CButton * worldViewUnderground;
+	std::shared_ptr<CButton> worldViewUnderground;
 
 	CTerrainRect terrain; //visible terrain
 	CResDataBar resdatabar;
@@ -185,9 +189,9 @@ public:
 	CTownList townList;
 	CInfoBar infoBar;
 
-	CAdvMapPanel *panelMain; // panel that holds all right-side buttons in normal view
-	CAdvMapWorldViewPanel *panelWorldView; // panel that holds all buttons and other ui in world view
-	CAdvMapPanel *activeMapPanel; // currently active panel (either main or world view, depending on current mode)
+	std::shared_ptr<CAdvMapPanel> panelMain; // panel that holds all right-side buttons in normal view
+	std::shared_ptr<CAdvMapWorldViewPanel> panelWorldView; // panel that holds all buttons and other ui in world view
+	std::shared_ptr<CAdvMapPanel> activeMapPanel; // currently active panel (either main or world view, depending on current mode)
 
 	std::shared_ptr<CAnimation> worldViewIcons;// images for world view overlay
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 373 - 368
client/windows/CCastleInterface.cpp


+ 113 - 81
client/windows/CCastleInterface.h

@@ -29,6 +29,8 @@ struct CStructure;
 class CGHeroInstance;
 class CGarrisonInt;
 class CCreature;
+class CComponent;
+class CComponentBox;
 
 /// Building "button"
 class CBuildingRect : public CShowableAnim
@@ -60,38 +62,43 @@ public:
 /// Dwelling info box - right-click screen for dwellings
 class CDwellingInfoBox : public CWindowObject
 {
-	CLabel *title;
-	CCreaturePic *animation;
-	CLabel *available;
-	CLabel *costPerTroop;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CCreaturePic> animation;
+	std::shared_ptr<CLabel> available;
+	std::shared_ptr<CLabel> costPerTroop;
 
-	std::vector<CAnimImage *> resPicture;
-	std::vector<CLabel *> resAmount;
+	std::vector<std::shared_ptr<CAnimImage>> resPicture;
+	std::vector<std::shared_ptr<CLabel>> resAmount;
 public:
-	CDwellingInfoBox(int centerX, int centerY, const CGTownInstance *Town, int level);
+	CDwellingInfoBox(int centerX, int centerY, const CGTownInstance * Town, int level);
+	~CDwellingInfoBox();
 };
 
 class HeroSlots;
 /// Hero icon slot
 class CHeroGSlot : public CIntObject
 {
-public:
-	HeroSlots *owner;
-	const CGHeroInstance *hero;
+	std::shared_ptr<CAnimImage> portrait;
+	std::shared_ptr<CAnimImage> flag;
+	std::shared_ptr<CAnimImage> selection; //selection border. nullptr if not selected
+
+	HeroSlots * owner;
+	const CGHeroInstance * hero;
 	int upg; //0 - up garrison, 1 - down garrison
 
-	CAnimImage *image;
-	CAnimImage *selection; //selection border. nullptr if not selected
+public:
+	CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner);
+	~CHeroGSlot();
+
+	bool isSelected() const;
 
 	void setHighlight(bool on);
-	void set(const CGHeroInstance *newHero);
+	void set(const CGHeroInstance * newHero);
 
 	void hover (bool on) override;
 	void clickLeft(tribool down, bool previousState) override;
 	void clickRight(tribool down, bool previousState) override;
 	void deactivate() override;
-	CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner);
-	~CHeroGSlot();
 };
 
 /// Two hero slots that can interact with each other
@@ -101,11 +108,12 @@ public:
 	bool showEmpty;
 	const CGTownInstance * town;
 
-	CGarrisonInt *garr;
-	CHeroGSlot * garrisonedHero;
-	CHeroGSlot * visitingHero;
+	std::shared_ptr<CGarrisonInt> garr;
+	std::shared_ptr<CHeroGSlot> garrisonedHero;
+	std::shared_ptr<CHeroGSlot> visitingHero;
 
-	HeroSlots(const CGTownInstance * town, Point garrPos, Point visitPos, CGarrisonInt *Garrison, bool ShowEmpty);
+	HeroSlots(const CGTownInstance * town, Point garrPos, Point visitPos, std::shared_ptr<CGarrisonInt> Garrison, bool ShowEmpty);
+	~HeroSlots();
 
 	void splitClicked(); //for hero meeting only (splitting stacks is handled by garrison int)
 	void update();
@@ -115,11 +123,11 @@ public:
 /// Class for town screen management (town background and structures)
 class CCastleBuildings : public CIntObject
 {
-	CPicture *background;
+	std::shared_ptr<CPicture> background;
 	//List of buildings and structures that can represent them
-	std::map< BuildingID, std::vector<const CStructure*> > groups;
+	std::map<BuildingID, std::vector<const CStructure *> > groups;
 	// actual IntObject's visible on screen
-	std::vector< CBuildingRect * > buildings;
+	std::vector<std::shared_ptr<CBuildingRect>> buildings;
 
 	const CGTownInstance * town;
 
@@ -139,7 +147,7 @@ class CCastleBuildings : public CIntObject
 public:
 	CBuildingRect * selectedBuilding;
 
-	CCastleBuildings(const CGTownInstance* town);
+	CCastleBuildings(const CGTownInstance * town);
 	~CCastleBuildings();
 
 	void enterDwelling(int level);
@@ -157,18 +165,17 @@ public:
 class CCreaInfo : public CIntObject
 {
 	const CGTownInstance * town;
-	const CCreature *creature;
+	const CCreature * creature;
 	int level;
 	bool showAvailable;
 
-	CAnimImage *picture;
-	CLabel * label;
+	std::shared_ptr<CAnimImage> picture;
+	std::shared_ptr<CLabel> label;
 
-	int AddToString(std::string from, std::string & to, int numb);
 	std::string genGrowthText();
 
 public:
-	CCreaInfo(Point position, const CGTownInstance *Town, int Level, bool compact=false, bool showAvailable=false);
+	CCreaInfo(Point position, const CGTownInstance * Town, int Level, bool compact=false, bool showAvailable=false);
 
 	void update();
 	void hover(bool on) override;
@@ -179,48 +186,53 @@ public:
 /// Town hall and fort icons for town screen
 class CTownInfo : public CIntObject
 {
-	const CGTownInstance *town;
-	const CBuilding *building;
+	const CGTownInstance * town;
+	const CBuilding * building;
 public:
-	CAnimImage * picture;
+	std::shared_ptr<CAnimImage> picture;
 	//if (townHall) hall-capital else fort - castle
-	CTownInfo(int posX, int posY, const CGTownInstance* town, bool townHall);
+	CTownInfo(int posX, int posY, const CGTownInstance * town, bool townHall);
 
 	void hover(bool on) override;
 	void clickRight(tribool down, bool previousState) override;
 };
 
 /// Class which manages the castle window
-class CCastleInterface : public CWindowObject, public CWindowWithGarrison
+class CCastleInterface : public CWindowObject, public CGarrisonHolder
 {
-	CLabel *title;
-	CLabel *income;
-	CAnimImage *icon;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CLabel> income;
+	std::shared_ptr<CAnimImage> icon;
 
-	CPicture * panel;
-	CResDataBar *resdatabar;
-	CGStatusBar * statusbar;
+	std::shared_ptr<CPicture> panel;
+	std::shared_ptr<CResDataBar> resdatabar;
+	std::shared_ptr<CGStatusBar> statusbar;
 
-	CTownInfo *hall, *fort;
+	std::shared_ptr<CTownInfo> hall;
+	std::shared_ptr<CTownInfo> fort;
 
-	CButton *exit;
-	CButton *split;
-	CButton * fastArmyPurhase;
+	std::shared_ptr<CButton> exit;
+	std::shared_ptr<CButton> split;
+	std::shared_ptr<CButton> fastArmyPurhase;
 
-	std::vector<CCreaInfo*> creainfo;//small icons of creatures (bottom-left corner);
+	std::vector<std::shared_ptr<CCreaInfo>> creainfo;//small icons of creatures (bottom-left corner);
 
 public:
-	CTownList * townlist;
+	std::shared_ptr<CTownList> townlist;
 
 	//TODO: move to private
 	const CGTownInstance * town;
-	HeroSlots *heroes;
-	CCastleBuildings *builds;
+	std::shared_ptr<HeroSlots> heroes;
+	std::shared_ptr<CCastleBuildings> builds;
+
+	std::shared_ptr<CGarrisonInt> garr;
 
 	//from - previously selected castle (if any)
 	CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from = nullptr);
 	~CCastleInterface();
 
+	virtual void updateGarrisons() override;
+
 	void castleTeleport(int where);
 	void townChange();
 	void keyPressed(const SDL_KeyboardEvent & key) override;
@@ -233,13 +245,17 @@ public:
 /// Hall window where you can build things
 class CHallInterface : public CWindowObject
 {
-	/// Building box from town hall (building icon + subtitle)
 	class CBuildingBox : public CIntObject
 	{
 		const CGTownInstance * town;
 		const CBuilding * building;
 
 		ui32 state;//Buildings::EBuildStructure enum
+
+		std::shared_ptr<CAnimImage> header;
+		std::shared_ptr<CAnimImage> icon;
+		std::shared_ptr<CAnimImage> mark;
+		std::shared_ptr<CLabel> name;
 	public:
 		CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building);
 		void hover(bool on) override;
@@ -248,11 +264,11 @@ class CHallInterface : public CWindowObject
 	};
 	const CGTownInstance * town;
 
-	std::vector< std::vector<CBuildingBox*> >boxes;
-	CLabel *title;
-	CGStatusBar *statusBar;
-	CMinorResDataBar * resdatabar;
-	CButton *exit;
+	std::vector<std::vector<std::shared_ptr<CBuildingBox>>> boxes;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CMinorResDataBar> resdatabar;
+	std::shared_ptr<CGStatusBar> statusbar;
+	std::shared_ptr<CButton> exit;
 
 public:
 	CHallInterface(const CGTownInstance * Town);
@@ -261,8 +277,18 @@ public:
 ///  Window where you can decide to buy a building or not
 class CBuildWindow: public CWindowObject
 {
-	const CGTownInstance *town;
-	const CBuilding *building;
+	const CGTownInstance * town;
+	const CBuilding * building;
+
+	std::shared_ptr<CAnimImage> icon;
+	std::shared_ptr<CGStatusBar> statusbar;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CTextBox> description;
+	std::shared_ptr<CTextBox> stateText;
+	std::shared_ptr<CComponentBox> cost;
+
+	std::shared_ptr<CButton> buy;
+	std::shared_ptr<CButton> cancel;
 
 	std::string getTextForState(int state);
 	void buyFunc();
@@ -274,8 +300,8 @@ public:
 class LabeledValue : public CIntObject
 {
 	std::string hoverText;
-	CLabel *name;
-	CLabel *value;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CLabel> value;
 	void init(std::string name, std::string descr, int min, int max);
 
 public:
@@ -289,14 +315,16 @@ class CFortScreen : public CWindowObject
 {
 	class RecruitArea : public CIntObject
 	{
-		const CGTownInstance *town;
+		const CGTownInstance * town;
 		int level;
 
 		std::string hoverText;
-		CLabel * availableCount;
+		std::shared_ptr<CLabel> availableCount;
 
-		std::vector<LabeledValue*> values;
-		CPicture *icons;
+		std::vector<std::shared_ptr<LabeledValue>> values;
+		std::shared_ptr<CPicture> icons;
+		std::shared_ptr<CAnimImage> buildingIcon;
+		std::shared_ptr<CLabel> buildingName;
 
 		const CCreature * getMyCreature();
 		const CBuilding * getMyBuilding();
@@ -308,13 +336,13 @@ class CFortScreen : public CWindowObject
 		void clickLeft(tribool down, bool previousState) override;
 		void clickRight(tribool down, bool previousState) override;
 	};
-	CLabel *title;
-	std::vector<RecruitArea*> recAreas;
-	CMinorResDataBar * resdatabar;
-	CGStatusBar *statusBar;
-	CButton *exit;
+	std::shared_ptr<CLabel> title;
+	std::vector<std::shared_ptr<RecruitArea>> recAreas;
+	std::shared_ptr<CMinorResDataBar> resdatabar;
+	std::shared_ptr<CGStatusBar> statusbar;
+	std::shared_ptr<CButton> exit;
 
-	std::string getBgName(const CGTownInstance *town);
+	std::string getBgName(const CGTownInstance * town);
 
 public:
 	CFortScreen(const CGTownInstance * town);
@@ -327,8 +355,8 @@ class CMageGuildScreen : public CWindowObject
 {
 	class Scroll : public CIntObject
 	{
-		const CSpell *spell;
-		CAnimImage *image;
+		const CSpell * spell;
+		std::shared_ptr<CAnimImage> image;
 
 	public:
 		Scroll(Point position, const CSpell *Spell);
@@ -336,11 +364,13 @@ class CMageGuildScreen : public CWindowObject
 		void clickRight(tribool down, bool previousState) override;
 		void hover(bool on) override;
 	};
-	CPicture *window;
-	CButton *exit;
-	std::vector<Scroll *> spells;
-	CMinorResDataBar * resdatabar;
-	CGStatusBar *statusBar;
+	std::shared_ptr<CPicture> window;
+	std::shared_ptr<CButton> exit;
+	std::vector<std::shared_ptr<Scroll>> spells;
+	std::vector<std::shared_ptr<CAnimImage>> emptyScrolls;
+
+	std::shared_ptr<CMinorResDataBar> resdatabar;
+	std::shared_ptr<CGStatusBar> statusbar;
 
 public:
 	CMageGuildScreen(CCastleInterface * owner,std::string image);
@@ -349,13 +379,15 @@ public:
 /// The blacksmith window where you can buy available in town war machine
 class CBlacksmithDialog : public CWindowObject
 {
-	CButton *buy, *cancel;
-	CPicture *animBG;
-	CCreatureAnim * anim;
-	CLabel * title;
-	CLabel * costText;
-	CLabel * costValue;
-	CGStatusBar *statusBar;
+	std::shared_ptr<CButton> buy;
+	std::shared_ptr<CButton> cancel;
+	std::shared_ptr<CPicture> animBG;
+	std::shared_ptr<CCreatureAnim> anim;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CAnimImage> costIcon;
+	std::shared_ptr<CLabel> costText;
+	std::shared_ptr<CLabel> costValue;
+	std::shared_ptr<CGStatusBar> statusbar;
 
 public:
 	CBlacksmithDialog(bool possible, CreatureID creMachineID, ArtifactID aid, ObjectInstanceID hid);

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 477 - 551
client/windows/CCreatureWindow.cpp


+ 112 - 36
client/windows/CCreatureWindow.h

@@ -13,26 +13,29 @@
 #include "../widgets/MiscWidgets.h"
 #include "CWindowObject.h"
 
-struct StackWindowInfo;
+class UnitView;
 class CCommanderInstance;
 class CStackInstance;
 class CStack;
 struct UpgradeInfo;
 class CTabbedInt;
 class CButton;
+class CMultiLineLabel;
+class CListBox;
+class CCommanderArtPlace;
 
 class CCommanderSkillIcon : public LRClickableAreaWText //TODO: maybe bring commander skill button initialization logic inside?
 {
-	CIntObject * object; // passive object that will be used to determine clickable area
+	std::shared_ptr<CIntObject> object; // passive object that will be used to determine clickable area
 public:
-	CCommanderSkillIcon(CIntObject * object, std::function<void()> callback);
+	CCommanderSkillIcon(std::shared_ptr<CIntObject> object_, std::function<void()> callback);
 
 	std::function<void()> callback;
 
 	void clickLeft(tribool down, bool previousState) override;
 	void clickRight(tribool down, bool previousState) override;
 
-	void setObject(CIntObject * object);
+	void setObject(std::shared_ptr<CIntObject> object);
 };
 
 class CStackWindow : public CWindowObject
@@ -46,48 +49,123 @@ class CStackWindow : public CWindowObject
 
 	class CWindowSection : public CIntObject
 	{
-		CStackWindow *parent;
+	private:
+		std::shared_ptr<CPicture> background;
+	protected:
+		CStackWindow * parent;
+	public:
+		CWindowSection(CStackWindow * parent, std::string backgroundPath, int yOffset);
+	};
 
-		void createBackground(std::string path);
-		void createBonusItem(size_t index, Point position);
+	class ActiveSpellsSection : public CWindowSection
+	{
+		std::vector<std::shared_ptr<CAnimImage>> spellIcons;
+		std::vector<std::shared_ptr<LRClickableAreaWText>> clickableAreas;
+	public:
+		ActiveSpellsSection(CStackWindow * owner, int yOffset);
+	};
+
+	class BonusLineSection : public CWindowSection
+	{
+		std::array<std::shared_ptr<CPicture>, 2> icon;
+		std::array<std::shared_ptr<CLabel>, 2> name;
+		std::array<std::shared_ptr<CMultiLineLabel>, 2> description;
+	public:
+		BonusLineSection(CStackWindow * owner, size_t lineIndex);
+	};
 
-		void printStatString(int index, std::string name, std::string value);
-		void printStatRange(int index, std::string name, int min, int max);
-		void printStatBase(int index, std::string name, int base, int current);
-		void printStat(int index, std::string name, int value);
+	class BonusesSection : public CWindowSection
+	{
+		std::shared_ptr<CListBox> lines;
 	public:
-		void createStackInfo(bool showExp, bool showArt);
-		void createActiveSpells();
-		void createCommanderSection();
-		void createCommander();
-		void createCommanderAbilities();
-		void createBonuses(boost::optional<size_t> size = boost::optional<size_t>());
-		void createBonusEntry(size_t index);
-		void createButtonPanel();
-
-		CWindowSection(CStackWindow * parent);
+		BonusesSection(CStackWindow * owner, int yOffset, boost::optional<size_t> preferredSize = boost::optional<size_t>());
 	};
 
-	std::unique_ptr<CAnimImage> stackArtifactIcon;
-	std::unique_ptr<LRClickableAreaWTextComp> stackArtifactHelp;
-	std::unique_ptr<CButton> stackArtifactButton;
-	CAnimImage *expRankIcon;
-	LRClickableAreaWText *expArea;
-	CLabel *expLabel;
+	class ButtonsSection : public CWindowSection
+	{
+		std::shared_ptr<CButton> dismiss;
+		std::array<std::shared_ptr<CButton>, 3> upgrade;// no more than 3 buttons - space limit
+		std::shared_ptr<CButton> exit;
+	public:
+		ButtonsSection(CStackWindow * owner, int yOffset);
+	};
 
-	std::unique_ptr<StackWindowInfo> info;
+	class CommanderMainSection : public CWindowSection
+	{
+		std::vector<std::shared_ptr<CCommanderSkillIcon>> skillIcons;
+		std::vector<std::shared_ptr<CCommanderArtPlace>> artifacts;
+
+		std::shared_ptr<CPicture> abilitiesBackground;
+		std::shared_ptr<CListBox> abilities;
+
+		std::shared_ptr<CButton> leftBtn;
+		std::shared_ptr<CButton> rightBtn;
+	public:
+		CommanderMainSection(CStackWindow * owner, int yOffset);
+	};
+
+	class MainSection : public CWindowSection
+	{
+		enum class EStat : size_t
+		{
+			ATTACK,
+			DEFENCE,
+			SHOTS,
+			DAMAGE,
+			HEALTH,
+			HEALTH_LEFT,
+			SPEED,
+			MANA,
+			AFTER_LAST
+		};
+
+		std::shared_ptr<CCreaturePic> animation;
+		std::shared_ptr<CLabel> name;
+		std::shared_ptr<CPicture> icons;
+		std::shared_ptr<MoraleLuckBox> morale;
+		std::shared_ptr<MoraleLuckBox> luck;
+
+		std::vector<std::shared_ptr<CLabel>> stats;
+
+		std::shared_ptr<CAnimImage> expRankIcon;
+		std::shared_ptr<LRClickableAreaWText> expArea;
+		std::shared_ptr<CLabel> expLabel;
+
+		void addStatLabel(EStat index, int64_t value1, int64_t value2);
+		void addStatLabel(EStat index, int64_t value);
+
+		static std::string getBackgroundName(bool showExp, bool showArt);
+
+		std::array<std::string, 8> statNames;
+		std::array<std::string, 8> statFormats;
+	public:
+		MainSection(CStackWindow * owner, int yOffset, bool showExp, bool showArt);
+	};
+
+	std::shared_ptr<CAnimImage> stackArtifactIcon;
+	std::shared_ptr<LRClickableAreaWTextComp> stackArtifactHelp;
+	std::shared_ptr<CButton> stackArtifactButton;
+
+
+	std::shared_ptr<UnitView> info;
 	std::vector<BonusInfo> activeBonuses;
 	size_t activeTab;
-	CTabbedInt *commanderTab;
+	std::shared_ptr<CTabbedInt> commanderTab;
+
+	std::map<size_t, std::shared_ptr<CButton>> switchButtons;
 
-	std::map<int, CButton *> switchButtons;
+	std::shared_ptr<CWindowSection> mainSection;
+	std::shared_ptr<CWindowSection> activeSpellsSection;
+	std::shared_ptr<CWindowSection> commanderMainSection;
+	std::shared_ptr<CWindowSection> commanderBonusesSection;
+	std::shared_ptr<CWindowSection> bonusesSection;
+	std::shared_ptr<CWindowSection> buttonsSection;
 
-	void setSelection(si32 newSkill, CCommanderSkillIcon * newIcon);
-	CCommanderSkillIcon * selectedIcon;
+	std::shared_ptr<CCommanderSkillIcon> selectedIcon;
 	si32 selectedSkill;
 
-	CIntObject * createBonusEntry(size_t index);
-	CIntObject * switchTab(size_t index);
+	void setSelection(si32 newSkill, std::shared_ptr<CCommanderSkillIcon> newIcon);
+	std::shared_ptr<CIntObject> switchTab(size_t index);
 
 	void removeStackArtifact(ArtifactPosition pos);
 
@@ -98,8 +176,6 @@ class CStackWindow : public CWindowObject
 
 	std::string generateStackExpDescription();
 
-	CIntObject * createSkillEntry(int index);
-
 public:
 	// for battles
 	CStackWindow(const CStack * stack, bool popup);

+ 128 - 135
client/windows/CHeroWindow.cpp

@@ -40,17 +40,15 @@
 #include "../mapHandler.h"
 
 
-const TBonusListPtr CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root, const std::string & cachingStr) const
+const TBonusListPtr CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector & selector, const CSelector & limit, const CBonusSystemNode * root, const std::string & cachingStr) const
 {
 	TBonusListPtr out(new BonusList());
-	TBonusListPtr heroBonuses = hero->getAllBonuses(selector, limit, hero);
+	TBonusListPtr heroBonuses = hero->getAllBonuses(selector, limit, hero, cachingStr);
 	TBonusListPtr bonusesFromPickedUpArtifact;
 
-	std::shared_ptr<CArtifactsOfHero::SCommonPart> cp = cww->artSets.size() ? cww->artSets.front()->commonInfo : nullptr;
+	std::shared_ptr<CArtifactsOfHero::SCommonPart> cp = cww->getCommonPart();
 	if(cp && cp->src.art && cp->src.valid() && cp->src.AOH && cp->src.AOH->getHero() == hero)
-	{
 		bonusesFromPickedUpArtifact = cp->src.art->getAllBonuses(selector, limit, hero);
-	}
 	else
 		bonusesFromPickedUpArtifact = TBonusListPtr(new BonusList());
 
@@ -66,8 +64,8 @@ int64_t CHeroWithMaybePickedArtifact::getTreeVersion() const
 	return hero->getTreeVersion();  //this assumes that hero and artifact belongs to main bonus tree
 }
 
-CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero)
-	:  hero(Hero), cww(Cww)
+CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts * Cww, const CGHeroInstance * Hero)
+	: hero(Hero), cww(Cww)
 {
 }
 
@@ -75,114 +73,128 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState)
 {
 	if(!down)
 	{
+		//TODO: do not recreate window
+		#if 0
+		owner->update(hero, true);
+		#else
 		const CGHeroInstance * buf = hero;
 		GH.popIntTotally(parent);
 		GH.pushInt(new CHeroWindow(buf));
+		#endif // 0
 	}
 }
 
-CHeroSwitcher::CHeroSwitcher(Point _pos, const CGHeroInstance * _hero):
-	hero(_hero)
+CHeroSwitcher::CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_)
+	: CIntObject(LCLICK),
+	owner(owner_),
+	hero(hero_)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	pos += _pos;
-	addUsedEvents(LCLICK);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	pos += pos_;
 
-	image = new CAnimImage("PortraitsSmall", hero->portrait);
+	image = std::make_shared<CAnimImage>("PortraitsSmall", hero->portrait);
 	pos.w = image->pos.w;
 	pos.h = image->pos.h;
 }
 
-CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
-    CWindowObject(PLAYER_COLORED, "HeroScr4"),
+CHeroWindow::CHeroWindow(const CGHeroInstance * hero)
+	: CWindowObject(PLAYER_COLORED, "HeroScr4"),
 	heroWArt(this, hero)
 {
 	auto & heroscrn = CGI->generaltexth->heroscrn;
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	garr = nullptr;
-	tacticsButton = nullptr;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	curHero = hero;
-	listSelection = nullptr;
 
-	new CAnimImage("CREST58", LOCPLINT->playerID.getNum(), 0, 606, 8);
+	banner = std::make_shared<CAnimImage>("CREST58", LOCPLINT->playerID.getNum(), 0, 606, 8);
+	name = std::make_shared<CLabel>(190, 38, EFonts::FONT_BIG, EAlignment::CENTER, Colors::YELLOW);
+	title = std::make_shared<CLabel>(190, 65, EFonts::FONT_MEDIUM, EAlignment::CENTER, Colors::WHITE);
 
-	//artifs = new CArtifactsOfHero(pos.topLeft(), true);
-	ourBar = new CGStatusBar(7, 559, "ADROLLVR.bmp", 660); // new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660);
+	statusBar = std::make_shared<CGStatusBar>(7, 559, "ADROLLVR.bmp", 660);
 
-	quitButton = new CButton(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [&](){ close(); }, SDLK_RETURN);
+	quitButton = std::make_shared<CButton>(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [=](){ close(); }, SDLK_RETURN);
 	quitButton->assignedKeys.insert(SDLK_ESCAPE);
-	dismissButton = new CButton(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [&](){ dismissCurrent(); }, SDLK_d);
-	questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q);
 
-	formations = new CToggleGroup(0);
-	formations->addToggle(0, new CToggleButton(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t));
-	formations->addToggle(1, new CToggleButton(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, SDLK_l));
+	dismissLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE);
+	dismissButton = std::make_shared<CButton>(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, SDLK_d);
+
+	questlogLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE);
+	questlogButton = std::make_shared<CButton>(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q);
 
-	if (hero->commander)
+	formations = std::make_shared<CToggleGroup>(0);
+	formations->addToggle(0, std::make_shared<CToggleButton>(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t));
+	formations->addToggle(1, std::make_shared<CToggleButton>(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, SDLK_l));
+
+	if(hero->commander)
 	{
 		auto texts = CGI->generaltexth->localizedTexts["heroWindow"]["openCommander"];
-		commanderButton = new CButton (Point(317, 18), "buttons/commander", CButton::tooltip(texts), [&](){ commanderWindow(); }, SDLK_c);
+		commanderButton = std::make_shared<CButton>(Point(317, 18), "buttons/commander", CButton::tooltip(texts), [&](){ commanderWindow(); }, SDLK_c);
 	}
 
 	//right list of heroes
 	for(int i=0; i < std::min(LOCPLINT->cb->howManyHeroes(false), 8); i++)
-		heroList.push_back(new CHeroSwitcher(Point(612, 87 + i * 54), LOCPLINT->cb->getHeroBySerial(i, false)));
+		heroList.push_back(std::make_shared<CHeroSwitcher>(this, Point(612, 87 + i * 54), LOCPLINT->cb->getHeroBySerial(i, false)));
 
 	//areas
-	portraitArea = new LRClickableAreaWText(Rect(18, 18, 58, 64));
-	portraitImage = new CAnimImage("PortraitsLarge", 0, 0, 19, 19);
+	portraitArea = std::make_shared<LRClickableAreaWText>(Rect(18, 18, 58, 64));
+	portraitImage = std::make_shared<CAnimImage>("PortraitsLarge", 0, 0, 19, 19);
 
-	for(int v=0; v<GameConstants::PRIMARY_SKILLS; ++v)
+	for(int v = 0; v < GameConstants::PRIMARY_SKILLS; ++v)
 	{
-		auto  area = new LRClickableAreaWTextComp(Rect(30 + 70*v, 109, 42, 64), CComponent::primskill);
+		auto area = std::make_shared<LRClickableAreaWTextComp>(Rect(30 + 70 * v, 109, 42, 64), CComponent::primskill);
 		area->text = CGI->generaltexth->arraytxt[2+v];
 		area->type = v;
 		area->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % CGI->generaltexth->primarySkillNames[v]);
 		primSkillAreas.push_back(area);
+
+		auto value = std::make_shared<CLabel>(53 + 70 * v, 166, FONT_SMALL, CENTER);
+		primSkillValues.push_back(value);
 	}
 
-	specImage = new CAnimImage("UN44", 0, 0, 18, 180);
+	auto primSkills = std::make_shared<CAnimation>("PSKIL42");
+	primSkills->preload();
+	primSkillImages.push_back(std::make_shared<CAnimImage>(primSkills, 0, 0, 32, 111));
+	primSkillImages.push_back(std::make_shared<CAnimImage>(primSkills, 1, 0, 102, 111));
+	primSkillImages.push_back(std::make_shared<CAnimImage>(primSkills, 2, 0, 172, 111));
+	primSkillImages.push_back(std::make_shared<CAnimImage>(primSkills, 3, 0, 162, 230));
+	primSkillImages.push_back(std::make_shared<CAnimImage>(primSkills, 4, 0, 20, 230));
+	primSkillImages.push_back(std::make_shared<CAnimImage>(primSkills, 5, 0, 242, 111));
+
+	specImage = std::make_shared<CAnimImage>("UN44", 0, 0, 18, 180);
+	specArea = std::make_shared<LRClickableAreaWText>(Rect(18, 180, 136, 42), CGI->generaltexth->heroscrn[27]);
+	specName = std::make_shared<CLabel>(69, 205);
+
+	expArea = std::make_shared<LRClickableAreaWText>(Rect(18, 228, 136, 42), CGI->generaltexth->heroscrn[9]);
+	morale = std::make_shared<MoraleLuckBox>(true, Rect(175, 179, 53, 45));
+	luck = std::make_shared<MoraleLuckBox>(false, Rect(233, 179, 53, 45));
+	spellPointsArea = std::make_shared<LRClickableAreaWText>(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
 
-	specArea = new LRClickableAreaWText(Rect(18, 180, 136, 42), CGI->generaltexth->heroscrn[27]);
-	expArea = new LRClickableAreaWText(Rect(18, 228, 136, 42), CGI->generaltexth->heroscrn[9]);
-	morale = new MoraleLuckBox(true, Rect(175,179,53,45));
-	luck = new MoraleLuckBox(false, Rect(233,179,53,45));
-	spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
+	expValue = std::make_shared<CLabel>(68, 252);
+	manaValue = std::make_shared<CLabel>(211, 252);
 
 	auto secSkills = std::make_shared<CAnimation>("SECSKILL");
 	for(int i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
 	{
 		Rect r = Rect(i%2 == 0  ?  18  :  162,  276 + 48 * (i/2),  136,  42);
-		secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill));
-		secSkillImages.push_back(new CAnimImage(secSkills, 0, 0, r.x, r.y));
-	}
-
-	//dismiss / quest log
-	new CTextBox(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE);
-	new CTextBox(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, TOPLEFT, Colors::WHITE);
+		secSkillAreas.push_back(std::make_shared<LRClickableAreaWTextComp>(r, CComponent::secskill));
+		secSkillImages.push_back(std::make_shared<CAnimImage>(secSkills, 0, 0, r.x, r.y));
 
-	//////////////////////////////////////////////////////////////////////////???????????????
+		int x = (i % 2) ? 212 : 68;
+		int y = 280 + 48 * (i/2);
 
-	//primary skills & exp and mana
-	auto primSkills = std::make_shared<CAnimation>("PSKIL42");
-	primSkills->preload();
-	new CAnimImage(primSkills, 0, 0, 32, 111);
-	new CAnimImage(primSkills, 1, 0, 102, 111);
-	new CAnimImage(primSkills, 2, 0, 172, 111);
-	new CAnimImage(primSkills, 3, 0, 162, 230);
-	new CAnimImage(primSkills, 4, 0, 20, 230);
-	new CAnimImage(primSkills, 5, 0, 242, 111);
+		secSkillValues.push_back(std::make_shared<CLabel>(x, y, FONT_SMALL, TOPLEFT));
+		secSkillNames.push_back(std::make_shared<CLabel>(x, y+20, FONT_SMALL, TOPLEFT));
+	}
 
 	// various texts
-	new CLabel( 52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1]);
-	new CLabel(123, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[2]);
-	new CLabel(193, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[3]);
-	new CLabel(262, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[4]);
+	labels.push_back(std::make_shared<CLabel>(52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1]));
+	labels.push_back(std::make_shared<CLabel>(123, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[2]));
+	labels.push_back(std::make_shared<CLabel>(193, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[3]));
+	labels.push_back(std::make_shared<CLabel>(262, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[4]));
 
-	new CLabel( 69, 183, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[5]);
-	new CLabel( 69, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[6]);
-	new CLabel(213, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[7]);
+	labels.push_back(std::make_shared<CLabel>(69, 183, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[5]));
+	labels.push_back(std::make_shared<CLabel>(69, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[6]));
+	labels.push_back(std::make_shared<CLabel>(213, 232, FONT_SMALL, TOPLEFT, Colors::YELLOW, CGI->generaltexth->jktexts[7]));
 
 	update(hero);
 }
@@ -199,11 +211,14 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
 
 	assert(hero == curHero);
 
+	name->setText(curHero->name);
+	title->setText((boost::format(CGI->generaltexth->allTexts[342]) % curHero->level % curHero->type->heroClass->name).str());
+
 	specArea->text = curHero->type->specDescr;
 	specImage->setFrame(curHero->type->imageIndex);
+	specName->setText(curHero->type->specName);
 
-	delete tacticsButton;
-	tacticsButton = new CToggleButton(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, SDLK_b);
+	tacticsButton = std::make_shared<CToggleButton>(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, SDLK_b);
 	tacticsButton->addHoverText(CButton::HIGHLIGHTED, CGI->generaltexth->heroscrn[25]);
 
 	dismissButton->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name));
@@ -212,49 +227,62 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
 	portraitImage->setFrame(curHero->portrait);
 
 	{
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
+		OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 		if(!garr)
 		{
 			std::string helpBox = heroscrn[32];
 			boost::algorithm::replace_first(helpBox, "%s", CGI->generaltexth->allTexts[43]);
 
-			garr = new CGarrisonInt(15, 485, 8, Point(), background->bg, Point(15,485), curHero);
-			auto split = new CButton(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); });
-
+			garr = std::make_shared<CGarrisonInt>(15, 485, 8, Point(), curHero);
+			auto split = std::make_shared<CButton>(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); });
 			garr->addSplitBtn(split);
 		}
-		if(!artSets.size())
+		if(!arts)
 		{
-			auto  arts = new CArtifactsOfHero(Point(-65, -8), true);
+			arts = std::make_shared<CArtifactsOfHero>(Point(-65, -8), true);
 			arts->setHero(curHero);
-			artSets.push_back(arts);
+			addSet(arts);
 		}
 
 		int serial = LOCPLINT->cb->getHeroSerial(curHero, false);
 
-		vstd::clear_pointer(listSelection);
-		if (serial >= 0)
-			listSelection = new CPicture("HPSYYY", 612, 33 + serial * 54);
+		listSelection.reset();
+		if(serial >= 0)
+			listSelection = std::make_shared<CPicture>("HPSYYY", 612, 33 + serial * 54);
 	}
 
 	//primary skills support
 	for(size_t g=0; g<primSkillAreas.size(); ++g)
 	{
 		primSkillAreas[g]->bonusValue = heroWArt.getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(g));
+		primSkillValues[g]->setText(boost::lexical_cast<std::string>(primSkillAreas[g]->bonusValue));
 	}
 
 	//secondary skills support
 	for(size_t g=0; g< secSkillAreas.size(); ++g)
 	{
-		int skill = curHero->secSkills[g].first,
-			level = curHero->getSecSkillLevel(SecondarySkill(curHero->secSkills[g].first));
+		int skill = curHero->secSkills[g].first;
+		int	level = curHero->getSecSkillLevel(SecondarySkill(curHero->secSkills[g].first));
+		std::string skillName = CGI->skillh->skillName(skill);
+		std::string skillValue = CGI->generaltexth->levels[level-1];
+
 		secSkillAreas[g]->type = skill;
 		secSkillAreas[g]->bonusValue = level;
 		secSkillAreas[g]->text = CGI->skillh->skillInfo(skill, level);
-		secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->skillh->skillName(skill));
+		secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % skillValue % skillName);
 		secSkillImages[g]->setFrame(skill*3 + level + 2);
+		secSkillNames[g]->setText(skillName);
+		secSkillValues[g]->setText(skillValue);
 	}
 
+	std::ostringstream expstr;
+	expstr << curHero->exp;
+	expValue->setText(expstr.str());
+
+	std::ostringstream manastr;
+	manastr << curHero->mana << '/' << heroWArt.manaLimit();
+	manaValue->setText(manastr.str());
+
 	//printing experience - original format does not support ui64
 	expArea->text = CGI->generaltexth->allTexts[2];
 	boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(curHero->level));
@@ -269,14 +297,16 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
 
 	//if we have exchange window with this curHero open
 	bool noDismiss=false;
-	for(IShowActivatable *isa : GH.listInt)
+	for(IShowActivatable * isa : GH.listInt)
 	{
 		if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa))
-			for(int g=0; g < ARRAY_COUNT(cew->heroInst); ++g)
+		{
+			for(int g=0; g < cew->heroInst.size(); ++g)
 				if(cew->heroInst[g] == curHero)
 					noDismiss = true;
+		}
 
-		if (dynamic_cast<CKingdomInterface*>(isa))
+		if(dynamic_cast<CKingdomInterface*>(isa))
 			noDismiss = true;
 	}
 	//if player only have one hero and no towns
@@ -289,17 +319,19 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
 	dismissButton->block(!!curHero->visitedTown || noDismiss);
 
 	if(curHero->getSecSkillLevel(SecondarySkill::TACTICS) == 0)
+	{
 		tacticsButton->block(true);
+	}
 	else
 	{
 		tacticsButton->block(false);
-		tacticsButton->addCallback( [&](bool on) {curHero->tacticFormationEnabled = on;});
-
+		tacticsButton->addCallback([&](bool on){curHero->tacticFormationEnabled = on;});
 	}
 
+	formations->resetCallback();
 	//setting formations
 	formations->setSelected(curHero->formation);
-	formations->addCallback([&] (int value) { LOCPLINT->cb->setFormation(curHero, value); });
+	formations->addCallback([=](int value){ LOCPLINT->cb->setFormation(curHero, value);});
 
 	morale->set(&heroWArt);
 	luck->set(&heroWArt);
@@ -312,26 +344,25 @@ void CHeroWindow::dismissCurrent()
 {
 	CFunctionList<void()> ony = [=](){ close(); };
 	ony += [=](){ LOCPLINT->cb->dismissHero(curHero); };
-	LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, 0, false);
+	LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, nullptr);
 }
 
 void CHeroWindow::commanderWindow()
 {
-	//TODO: allow equipping commander artifacts by drag / drop
 	//bool artSelected = false;
-	const std::shared_ptr<CArtifactsOfHero::SCommonPart> commonInfo = artSets.front()->commonInfo;
+	const std::shared_ptr<CArtifactsOfHero::SCommonPart> commonInfo = getCommonPart();
 
-	if (const CArtifactInstance *art = commonInfo->src.art)
+	if(const CArtifactInstance *art = commonInfo->src.art)
 	{
 		const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero();
 		//artSelected = true;
 		ArtifactPosition freeSlot = art->firstAvailableSlot (curHero->commander);
-		if (freeSlot < ArtifactPosition::COMMANDER_AFTER_LAST) //we don't want to put it in commander's backpack!
+		if(freeSlot < ArtifactPosition::COMMANDER_AFTER_LAST) //we don't want to put it in commander's backpack!
 		{
-			ArtifactLocation src (srcHero, commonInfo->src.slotID);
-			ArtifactLocation dst (curHero->commander.get(), freeSlot);
+			ArtifactLocation src(srcHero, commonInfo->src.slotID);
+			ArtifactLocation dst(curHero->commander.get(), freeSlot);
 
-			if (art->canBePutAt(dst, true))
+			if(art->canBePutAt(dst, true))
 			{	//equip clicked stack
 				if(dst.getArt())
 				{
@@ -342,51 +373,13 @@ void CHeroWindow::commanderWindow()
 		}
 	}
 	else
+	{
 		GH.pushInt(new CStackWindow(curHero->commander, false));
-
+	}
 }
 
 void CHeroWindow::updateGarrisons()
 {
-	CWindowWithGarrison::updateGarrisons();
+	garr->recreateSlots();
 	morale->set(&heroWArt);
 }
-
-void CHeroWindow::showAll(SDL_Surface * to)
-{
-	CIntObject::showAll(to);
-
-	//printing hero's name
-	printAtMiddleLoc(curHero->name, 190, 38, FONT_BIG, Colors::YELLOW, to);
-
-	//printing hero's level
-	std::string secondLine= CGI->generaltexth->allTexts[342];
-	boost::algorithm::replace_first(secondLine,"%d",boost::lexical_cast<std::string>(curHero->level));
-	boost::algorithm::replace_first(secondLine,"%s",curHero->type->heroClass->name);
-	printAtMiddleLoc(secondLine, 190, 65, FONT_MEDIUM, Colors::WHITE, to);
-
-	//printing primary skills' amounts
-	for(int m=0; m<4; ++m)
-	{
-	 	std::ostringstream primarySkill;
-	 	primarySkill << primSkillAreas[m]->bonusValue;
-	 	printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, Colors::WHITE, to);
-	}
-
-	//secondary skills
-	for(size_t v=0; v<std::min(secSkillAreas.size(), curHero->secSkills.size()); ++v)
-	{
-	 	printAtLoc(CGI->generaltexth->levels[curHero->secSkills[v].second-1], (v%2) ? 212 : 68, 280 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to);
-		printAtLoc(CGI->skillh->skillName(curHero->secSkills[v].first), (v%2) ? 212 : 68, 300 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to);
-	}
-
-	//printing special ability
-	printAtLoc(curHero->type->specName, 69, 205, FONT_SMALL, Colors::WHITE, to);
-	std::ostringstream expstr;
-	expstr << curHero->exp;
-	printAtLoc(expstr.str(), 68, 252, FONT_SMALL, Colors::WHITE, to);
-
-	std::ostringstream manastr;
-	manastr << curHero->mana << '/' << heroWArt.manaLimit();
-	printAtLoc(manastr.str(), 211, 252, FONT_SMALL, Colors::WHITE, to);
-}

+ 57 - 33
client/windows/CHeroWindow.h

@@ -26,71 +26,95 @@ class MoraleLuckBox;
 class CToggleButton;
 class CToggleGroup;
 class CGStatusBar;
+class CTextBox;
 
 /// Button which switches hero selection
 class CHeroSwitcher : public CIntObject
 {
 	const CGHeroInstance * hero;
-	CAnimImage *image;
+	std::shared_ptr<CAnimImage> image;
+	CHeroWindow * owner;
 public:
-	virtual void clickLeft(tribool down, bool previousState) override;
+	void clickLeft(tribool down, bool previousState) override;
 
-	CHeroSwitcher(Point pos, const CGHeroInstance * hero);
+	CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_);
 };
 
 //helper class for calculating values of hero bonuses without bonuses from picked up artifact
 class CHeroWithMaybePickedArtifact : public virtual IBonusBearer
 {
 public:
-	const CGHeroInstance *hero;
-	CWindowWithArtifacts *cww;
+	const CGHeroInstance * hero;
+	CWindowWithArtifacts * cww;
 
-	CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero);
-	const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const override;
+	CHeroWithMaybePickedArtifact(CWindowWithArtifacts * Cww, const CGHeroInstance * Hero);
+	const TBonusListPtr getAllBonuses(const CSelector & selector, const CSelector & limit, const CBonusSystemNode * root = nullptr, const std::string & cachingStr = "") const override;
 
 	int64_t getTreeVersion() const override;
 };
 
-class CHeroWindow: public CWindowObject, public CWindowWithGarrison, public CWindowWithArtifacts
+class CHeroWindow : public CWindowObject, public CGarrisonHolder, public CWindowWithArtifacts
 {
-	CGStatusBar * ourBar; //heroWindow's statusBar
-
-	//buttons
-	//CButton * gar4button; //splitting
-	std::vector<CHeroSwitcher *> heroList; //list of heroes
-	CPicture * listSelection; //selection border
-
-	//clickable areas
-	LRClickableAreaWText * portraitArea;
-	CAnimImage * portraitImage;
-
-	std::vector<LRClickableAreaWTextComp *> primSkillAreas;
-	LRClickableAreaWText * expArea;
-	LRClickableAreaWText * spellPointsArea;
-	LRClickableAreaWText * specArea;//specialty
-	CAnimImage *specImage;
-	MoraleLuckBox * morale, * luck;
-	std::vector<LRClickableAreaWTextComp *> secSkillAreas;
-	std::vector<CAnimImage *> secSkillImages;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CLabel> title;
+
+	std::shared_ptr<CAnimImage> banner;
+	std::shared_ptr<CGStatusBar> statusBar;
+
+	std::vector<std::shared_ptr<CHeroSwitcher>> heroList;
+	std::shared_ptr<CPicture> listSelection;
+
+	std::shared_ptr<LRClickableAreaWText> portraitArea;
+	std::shared_ptr<CAnimImage> portraitImage;
+
+	std::vector<std::shared_ptr<LRClickableAreaWTextComp>> primSkillAreas;
+	std::vector<std::shared_ptr<CAnimImage>> primSkillImages;
+	std::vector<std::shared_ptr<CLabel>> primSkillValues;
+
+	std::shared_ptr<CLabel> expValue;
+	std::shared_ptr<LRClickableAreaWText> expArea;
+
+	std::shared_ptr<CLabel> manaValue;
+	std::shared_ptr<LRClickableAreaWText> spellPointsArea;
+
+	std::shared_ptr<LRClickableAreaWText> specArea;
+	std::shared_ptr<CAnimImage> specImage;
+	std::shared_ptr<CLabel> specName;
+	std::shared_ptr<MoraleLuckBox> morale;
+	std::shared_ptr<MoraleLuckBox> luck;
+	std::vector<std::shared_ptr<LRClickableAreaWTextComp>> secSkillAreas;
+	std::vector<std::shared_ptr<CAnimImage>> secSkillImages;
+	std::vector<std::shared_ptr<CLabel>> secSkillNames;
+	std::vector<std::shared_ptr<CLabel>> secSkillValues;
+
 	CHeroWithMaybePickedArtifact heroWArt;
 
-	CButton * quitButton, * dismissButton, * questlogButton, * commanderButton; //general
+	std::shared_ptr<CButton> quitButton;
+	std::shared_ptr<CTextBox> dismissLabel;
+	std::shared_ptr<CButton> dismissButton;
+	std::shared_ptr<CTextBox> questlogLabel;
+	std::shared_ptr<CButton> questlogButton;
+	std::shared_ptr<CButton> commanderButton;
+
+	std::shared_ptr<CToggleButton> tacticsButton;
+	std::shared_ptr<CToggleGroup> formations;
+
+	std::shared_ptr<CGarrisonInt> garr;
+	std::shared_ptr<CArtifactsOfHero> arts;
 
-	CToggleButton *tacticsButton; //garrison / formation handling;
-	CToggleGroup *formations;
+	std::vector<std::shared_ptr<CLabel>> labels;
 
 public:
 	const CGHeroInstance * curHero;
 
-	CHeroWindow(const CGHeroInstance *hero);
+	CHeroWindow(const CGHeroInstance * hero);
 
 	void update(const CGHeroInstance * hero, bool redrawNeeded = false); //sets main displayed hero
-	void showAll(SDL_Surface * to) override;
 
 	void dismissCurrent(); //dissmissed currently displayed hero (curHero)
 	void commanderWindow();
 	void switchHero(); //changes displayed hero
-	virtual void updateGarrisons() override;  //updates the morale widget and calls the parent
+	void updateGarrisons() override;
 
 	//friends
 	friend void CHeroArtPlace::clickLeft(tribool down, bool previousState);

+ 217 - 233
client/windows/CKingdomInterface.cpp

@@ -34,7 +34,7 @@
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/mapObjects/MiscObjects.h"
 
-InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data):
+InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IInfoBoxData> Data):
 	size(Size),
 	infoPos(Pos),
 	data(Data),
@@ -45,52 +45,51 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data)
 	addUsedEvents(LCLICK | RCLICK);
 	EFonts font = (size < SIZE_MEDIUM)? FONT_SMALL: FONT_MEDIUM;
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	pos+=position;
 
-	image = new CAnimImage(data->getImageName(size), data->getImageIndex());
+	image = std::make_shared<CAnimImage>(data->getImageName(size), data->getImageIndex());
 	pos = image->pos;
 
-	if (infoPos == POS_CORNER)
-		value = new CLabel(pos.w, pos.h, font, BOTTOMRIGHT, Colors::WHITE, data->getValueText());
-
-	if (infoPos == POS_INSIDE)
-		value = new CLabel(pos.w/2, pos.h-6, font, CENTER, Colors::WHITE, data->getValueText());
-
-	if (infoPos == POS_UP_DOWN || infoPos == POS_DOWN)
-		value = new CLabel(pos.w/2, pos.h+8, font, CENTER, Colors::WHITE, data->getValueText());
-
-	if (infoPos == POS_UP_DOWN)
-		name = new CLabel(pos.w/2, -12, font, CENTER, Colors::WHITE, data->getNameText());
-
-	if (infoPos == POS_RIGHT)
-	{
-		name = new CLabel(pos.w+6, 6, font, TOPLEFT, Colors::WHITE, data->getNameText());
-		value = new CLabel(pos.w+6, pos.h-16, font, TOPLEFT, Colors::WHITE, data->getValueText());
-	}
-	pos = image->pos;
-	if (name)
+	switch(infoPos)
+	{
+	case POS_CORNER:
+		value = std::make_shared<CLabel>(pos.w, pos.h, font, BOTTOMRIGHT, Colors::WHITE, data->getValueText());
+		break;
+	case POS_INSIDE:
+		value = std::make_shared<CLabel>(pos.w/2, pos.h-6, font, CENTER, Colors::WHITE, data->getValueText());
+		break;
+	case POS_UP_DOWN:
+		name = std::make_shared<CLabel>(pos.w/2, -12, font, CENTER, Colors::WHITE, data->getNameText());
+		FALLTHROUGH;
+	case POS_DOWN:
+		value = std::make_shared<CLabel>(pos.w/2, pos.h+8, font, CENTER, Colors::WHITE, data->getValueText());
+		break;
+	case POS_RIGHT:
+		name = std::make_shared<CLabel>(pos.w+6, 6, font, TOPLEFT, Colors::WHITE, data->getNameText());
+		value = std::make_shared<CLabel>(pos.w+6, pos.h-16, font, TOPLEFT, Colors::WHITE, data->getValueText());
+		break;
+	}
+
+	if(name)
 		pos = pos | name->pos;
-	if (value)
+	if(value)
 		pos = pos | value->pos;
 
-	hover = new CHoverableArea();
+	hover = std::make_shared<CHoverableArea>();
 	hover->hoverText = data->getHoverText();
 	hover->pos = pos;
 }
 
-InfoBox::~InfoBox()
-{
-	delete data;
-}
+InfoBox::~InfoBox() = default;
 
 void InfoBox::clickRight(tribool down, bool previousState)
 {
 	if (down)
 	{
-		CComponent *comp = nullptr;
+		std::shared_ptr<CComponent> comp;
 		std::string text;
-		data->prepareMessage(text, &comp);
+		data->prepareMessage(text, comp);
 		if (comp)
 			CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
 		else if (!text.empty())
@@ -102,16 +101,12 @@ void InfoBox::clickLeft(tribool down, bool previousState)
 {
 	if((!down) && previousState)
 	{
-		CComponent *comp = nullptr;
+		std::shared_ptr<CComponent> comp;
 		std::string text;
-		data->prepareMessage(text, &comp);
+		data->prepareMessage(text, comp);
 
-		std::vector<CComponent*> compVector;
-		if (comp)
-		{
-			compVector.push_back(comp);
-			LOCPLINT->showInfoDialog(text, compVector);
-		}
+		if(comp)
+			LOCPLINT->showInfoDialog(text, CInfoWindow::TCompsInfo(1, comp));
 	}
 }
 
@@ -123,13 +118,13 @@ void InfoBox::update()
 }
 */
 
-IInfoBoxData::IInfoBoxData(InfoType Type):
-	type(Type)
+IInfoBoxData::IInfoBoxData(InfoType Type)
+	: type(Type)
 {
 }
 
-InfoBoxAbstractHeroData::InfoBoxAbstractHeroData(InfoType Type):
-	IInfoBoxData(Type)
+InfoBoxAbstractHeroData::InfoBoxAbstractHeroData(InfoType Type)
+	: IInfoBoxData(Type)
 {
 }
 
@@ -255,40 +250,37 @@ size_t InfoBoxAbstractHeroData::getImageIndex()
 	}
 }
 
-bool InfoBoxAbstractHeroData::prepareMessage(std::string &text, CComponent **comp)
+void InfoBoxAbstractHeroData::prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp)
 {
+	comp.reset();
 	switch (type)
 	{
 	case HERO_SPECIAL:
 		text = CGI->heroh->heroes[getSubID()]->specDescr;
-		*comp = nullptr;
-		return true;
+		break;
 	case HERO_PRIMARY_SKILL:
 		text = CGI->generaltexth->arraytxt[2+getSubID()];
-		*comp =new CComponent(CComponent::primskill, getSubID(), getValue());
-		return true;
+		comp = std::make_shared<CComponent>(CComponent::primskill, getSubID(), getValue());
+		break;
 	case HERO_MANA:
 		text = CGI->generaltexth->allTexts[149];
-		*comp = nullptr;
-		return true;
+		break;
 	case HERO_EXPERIENCE:
 		text = CGI->generaltexth->allTexts[241];
-		*comp = nullptr;
-		return true;
+		break;
 	case HERO_SECONDARY_SKILL:
 		{
 			si64 value = getValue();
 			int  subID = getSubID();
-			if (!value)
-				return false;
-
-			text = CGI->skillh->skillInfo(subID, value);
-			*comp = new CComponent(CComponent::secskill, subID, value);
-			return true;
+			if(value)
+			{
+				text = CGI->skillh->skillInfo(subID, value);
+				comp = std::make_shared<CComponent>(CComponent::secskill, subID, value);
+			}
+			break;
 		}
 	default:
-		assert(0);
-		return false;
+		break;
 	}
 }
 
@@ -388,8 +380,9 @@ std::string InfoBoxHeroData::getValueText()
 	return InfoBoxAbstractHeroData::getValueText();
 }
 
-bool InfoBoxHeroData::prepareMessage(std::string &text, CComponent**comp)
+void InfoBoxHeroData::prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp)
 {
+	comp.reset();
 	switch(type)
 	{
 	case HERO_MANA:
@@ -397,19 +390,16 @@ bool InfoBoxHeroData::prepareMessage(std::string &text, CComponent**comp)
 		boost::replace_first(text, "%s", boost::lexical_cast<std::string>(hero->name));
 		boost::replace_first(text, "%d", boost::lexical_cast<std::string>(hero->mana));
 		boost::replace_first(text, "%d", boost::lexical_cast<std::string>(hero->manaLimit()));
-		*comp = nullptr;
-		return true;
-
+		break;
 	case HERO_EXPERIENCE:
 		text = CGI->generaltexth->allTexts[2];
 		boost::replace_first(text, "%d", boost::lexical_cast<std::string>(hero->level));
 		boost::replace_first(text, "%d", boost::lexical_cast<std::string>(CGI->heroh->reqExp(hero->level+1)));
 		boost::replace_first(text, "%d", boost::lexical_cast<std::string>(hero->exp));
-		*comp = nullptr;
-		return true;
-
+		break;
 	default:
-		return InfoBoxAbstractHeroData::prepareMessage(text, comp);
+		InfoBoxAbstractHeroData::prepareMessage(text, comp);
+		break;
 	}
 }
 
@@ -465,26 +455,25 @@ std::string InfoBoxCustom::getValueText()
 	return valueText;
 }
 
-bool InfoBoxCustom::prepareMessage(std::string &text, CComponent **comp)
+void InfoBoxCustom::prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp)
 {
-	return false;
 }
 
-CKingdomInterface::CKingdomInterface():
-    CWindowObject(PLAYER_COLORED | BORDERED, conf.go()->ac.overviewBg)
+CKingdomInterface::CKingdomInterface()
+	: CWindowObject(PLAYER_COLORED | BORDERED, conf.go()->ac.overviewBg)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	ui32 footerPos = conf.go()->ac.overviewSize * 116;
 
-	tabArea = new CTabbedInt(std::bind(&CKingdomInterface::createMainTab, this, _1), CTabbedInt::DestroyFunc(), Point(4,4));
+	tabArea = std::make_shared<CTabbedInt>(std::bind(&CKingdomInterface::createMainTab, this, _1), Point(4,4));
 
 	std::vector<const CGObjectInstance * > ownedObjects = LOCPLINT->cb->getMyObjects();
 	generateObjectsList(ownedObjects);
 	generateMinesList(ownedObjects);
 	generateButtons();
 
-	statusbar = new CGStatusBar(new CPicture("KSTATBAR", 10,pos.h - 45));
-	resdatabar= new CResDataBar("KRESBAR", 3, 111+footerPos, 32, 2, 76, 76);
+	statusbar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>("KSTATBAR", 10,pos.h - 45));
+	resdatabar = std::make_shared<CResDataBar>("KRESBAR", 3, 111+footerPos, 32, 2, 76, 76);
 }
 
 void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInstance * > &ownedObjects)
@@ -508,10 +497,10 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
 	for(const CGObjectInstance * object : ownedObjects)
 	{
 		//Dwellings
-		if ( object->ID == Obj::CREATURE_GENERATOR1 )
+		if(object->ID == Obj::CREATURE_GENERATOR1)
 		{
-			OwnedObjectInfo &info = visibleObjects[object->subID];
-			if (info.count++ == 0)
+			OwnedObjectInfo & info = visibleObjects[object->subID];
+			if(info.count++ == 0)
 			{
 				info.hoverText = object->getObjectName();
 				info.imageID = object->subID;
@@ -519,10 +508,10 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
 		}
 		//Special objects from idToImage map that should be displayed in objects list
 		auto iter = idToImage.find(std::make_pair(object->ID, object->subID));
-		if (iter != idToImage.end())
+		if(iter != idToImage.end())
 		{
-			OwnedObjectInfo &info = visibleObjects[iter->second];
-			if (info.count++ == 0)
+			OwnedObjectInfo & info = visibleObjects[iter->second];
+			if(info.count++ == 0)
 			{
 				info.hoverText = object->getObjectName();
 				info.imageID = iter->second;
@@ -535,34 +524,37 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
 	{
 		objects.push_back(element.second);
 	}
-	dwellingsList = new CListBox(std::bind(&CKingdomInterface::createOwnedObject, this, _1), CListBox::DestroyFunc(),
-	                             Point(740,44), Point(0,57), dwellSize, visibleObjects.size());
+	dwellingsList = std::make_shared<CListBox>(std::bind(&CKingdomInterface::createOwnedObject, this, _1),
+		Point(740,44), Point(0,57), dwellSize, visibleObjects.size());
 }
 
-CIntObject* CKingdomInterface::createOwnedObject(size_t index)
+std::shared_ptr<CIntObject> CKingdomInterface::createOwnedObject(size_t index)
 {
-	if (index < objects.size())
+	if(index < objects.size())
 	{
-		OwnedObjectInfo &obj = objects[index];
+		OwnedObjectInfo & obj = objects[index];
 		std::string value = boost::lexical_cast<std::string>(obj.count);
-		return new InfoBox(Point(), InfoBox::POS_CORNER, InfoBox::SIZE_SMALL,
-			   new InfoBoxCustom(value,"", "FLAGPORT", obj.imageID, obj.hoverText));
+		auto data = std::make_shared<InfoBoxCustom>(value, "", "FLAGPORT", obj.imageID, obj.hoverText);
+		return std::make_shared<InfoBox>(Point(), InfoBox::POS_CORNER, InfoBox::SIZE_SMALL, data);
 	}
-	return nullptr;
+	return std::shared_ptr<CIntObject>();
 }
 
-CIntObject * CKingdomInterface::createMainTab(size_t index)
+std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
 {
 	size_t size = conf.go()->ac.overviewSize;
-	switch (index)
+	switch(index)
 	{
-	case 0: return new CKingdHeroList(size);
-	case 1: return new CKingdTownList(size);
-	default:return nullptr;
+	case 0:
+		return std::make_shared<CKingdHeroList>(size);
+	case 1:
+		return std::make_shared<CKingdTownList>(size);
+	default:
+		return std::shared_ptr<CIntObject>();
 	}
 }
 
-void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstance * > &ownedObjects)
+void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstance *> & ownedObjects)
 {
 	ui32 footerPos = conf.go()->ac.overviewSize * 116;
 	std::vector<int> minesCount(GameConstants::RESOURCE_QUANTITY, 0);
@@ -573,7 +565,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
 		//Mines
 		if(object->ID == Obj::MINE || object->ID == Obj::ABANDONED_MINE)
 		{
-			const CGMine *mine = dynamic_cast<const CGMine*>(object);
+			const CGMine * mine = dynamic_cast<const CGMine *>(object);
 			assert(mine);
 			minesCount[mine->producedResource]++;
 
@@ -596,18 +588,17 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
 	{
 		totalIncome += town->dailyIncome()[Res::GOLD];
 	}
-	for (int i=0; i<7; i++)
+	for(int i=0; i<7; i++)
 	{
 		std::string value = boost::lexical_cast<std::string>(minesCount[i]);
-		minesBox[i] = new InfoBox(Point(20+i*80, 31+footerPos), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL,
-		              new InfoBoxCustom(value, "", "OVMINES", i, CGI->generaltexth->mines[i].first));
-
+		auto data = std::make_shared<InfoBoxCustom>(value, "", "OVMINES", i, CGI->generaltexth->mines[i].first);
+		minesBox[i] = std::make_shared<InfoBox>(Point(20+i*80, 31+footerPos), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data);
 		minesBox[i]->removeUsedEvents(LCLICK|RCLICK); //fixes #890 - mines boxes ignore clicks
 	}
-	incomeArea = new CHoverableArea();
+	incomeArea = std::make_shared<CHoverableArea>();
 	incomeArea->pos = Rect(pos.x+580, pos.y+31+footerPos, 136, 68);
 	incomeArea->hoverText = CGI->generaltexth->allTexts[255];
-	incomeAmount = new CLabel(628, footerPos + 70, FONT_SMALL, TOPLEFT, Colors::WHITE, boost::lexical_cast<std::string>(totalIncome));
+	incomeAmount = std::make_shared<CLabel>(628, footerPos + 70, FONT_SMALL, TOPLEFT, Colors::WHITE, boost::lexical_cast<std::string>(totalIncome));
 }
 
 void CKingdomInterface::generateButtons()
@@ -615,28 +606,28 @@ void CKingdomInterface::generateButtons()
 	ui32 footerPos = conf.go()->ac.overviewSize * 116;
 
 	//Main control buttons
-	btnHeroes = new CButton (Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]),
-	                         std::bind(&CKingdomInterface::activateTab, this, 0), SDLK_h);
+	btnHeroes = std::make_shared<CButton>(Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]),
+		std::bind(&CKingdomInterface::activateTab, this, 0), SDLK_h);
 	btnHeroes->block(true);
 
-	btnTowns = new CButton (Point(748, 64+footerPos), "OVBUTN6.DEF", CButton::tooltip(CGI->generaltexth->overview[12], CGI->generaltexth->overview[7]),
-	                        std::bind(&CKingdomInterface::activateTab, this, 1), SDLK_t);
+	btnTowns = std::make_shared<CButton>(Point(748, 64+footerPos), "OVBUTN6.DEF", CButton::tooltip(CGI->generaltexth->overview[12], CGI->generaltexth->overview[7]),
+		std::bind(&CKingdomInterface::activateTab, this, 1), SDLK_t);
 
-	btnExit = new CButton (Point(748,99+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[600]),
-	                       std::bind(&CKingdomInterface::close, this), SDLK_RETURN);
+	btnExit = std::make_shared<CButton>(Point(748,99+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[600]),
+		std::bind(&CKingdomInterface::close, this), SDLK_RETURN);
 	btnExit->assignedKeys.insert(SDLK_ESCAPE);
 	btnExit->setImageOrder(3, 4, 5, 6);
 
 	//Object list control buttons
-	dwellTop = new CButton (Point(733, 4), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(0);});
+	dwellTop = std::make_shared<CButton>(Point(733, 4), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(0);});
 
-	dwellBottom = new CButton (Point(733, footerPos+2), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(-1); });
+	dwellBottom = std::make_shared<CButton>(Point(733, footerPos+2), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPos(-1); });
 	dwellBottom->setImageOrder(2, 3, 4, 5);
 
-	dwellUp = new CButton (Point(733, 24), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPrev(); });
+	dwellUp = std::make_shared<CButton>(Point(733, 24), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToPrev(); });
 	dwellUp->setImageOrder(4, 5, 6, 7);
 
-	dwellDown = new CButton (Point(733, footerPos-18), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToNext(); });
+	dwellDown = std::make_shared<CButton>(Point(733, footerPos-18), "OVBUTN4.DEF", CButton::tooltip(), [&](){ dwellingsList->moveToNext(); });
 	dwellDown->setImageOrder(6, 7, 8, 9);
 }
 
@@ -649,160 +640,148 @@ void CKingdomInterface::activateTab(size_t which)
 
 void CKingdomInterface::townChanged(const CGTownInstance *town)
 {
-	if (CKingdTownList * townList = dynamic_cast<CKingdTownList*>(tabArea->getItem()))
+	if(auto townList = std::dynamic_pointer_cast<CKingdTownList>(tabArea->getItem()))
 		townList->townChanged(town);
 }
 
 void CKingdomInterface::updateGarrisons()
 {
-	if (CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(tabArea->getItem()))
+	if(auto garrison = std::dynamic_pointer_cast<CGarrisonHolder>(tabArea->getItem()))
 		garrison->updateGarrisons();
 }
 
 void CKingdomInterface::artifactAssembled(const ArtifactLocation& artLoc)
 {
-	if (CArtifactHolder * arts = dynamic_cast<CArtifactHolder*>(tabArea->getItem()))
+	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
 		arts->artifactAssembled(artLoc);
 }
 
 void CKingdomInterface::artifactDisassembled(const ArtifactLocation& artLoc)
 {
-	if (CArtifactHolder * arts = dynamic_cast<CArtifactHolder*>(tabArea->getItem()))
+	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
 		arts->artifactDisassembled(artLoc);
 }
 
 void CKingdomInterface::artifactMoved(const ArtifactLocation& artLoc, const ArtifactLocation& destLoc)
 {
-	if (CArtifactHolder * arts = dynamic_cast<CArtifactHolder*>(tabArea->getItem()))
+	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
 		arts->artifactMoved(artLoc, destLoc);
 }
 
 void CKingdomInterface::artifactRemoved(const ArtifactLocation& artLoc)
 {
-	if (CArtifactHolder * arts = dynamic_cast<CArtifactHolder*>(tabArea->getItem()))
+	if(auto arts = std::dynamic_pointer_cast<CArtifactHolder>(tabArea->getItem()))
 		arts->artifactRemoved(artLoc);
 }
 
 CKingdHeroList::CKingdHeroList(size_t maxSize)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	title = new CPicture("OVTITLE",16,0);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	title = std::make_shared<CPicture>("OVTITLE",16,0);
 	title->colorize(LOCPLINT->playerID);
-	heroLabel =   new CLabel(150, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[0]);
-	skillsLabel = new CLabel(500, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[1]);
+	heroLabel = std::make_shared<CLabel>(150, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[0]);
+	skillsLabel = std::make_shared<CLabel>(500, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[1]);
 
 	ui32 townCount = LOCPLINT->cb->howManyHeroes(false);
 	ui32 size = conf.go()->ac.overviewSize*116 + 19;
-	heroes = new CListBox(std::bind(&CKingdHeroList::createHeroItem, this, _1), std::bind(&CKingdHeroList::destroyHeroItem, this, _1),
-	                      Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size) );
+	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));
 }
 
 void CKingdHeroList::updateGarrisons()
 {
-	std::list<CIntObject*> list = heroes->getItems();
-	for(CIntObject* object : list)
+	for(std::shared_ptr<CIntObject> object : heroes->getItems())
 	{
-		if (CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object) )
+		if(CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object.get()))
 			garrison->updateGarrisons();
 	}
 }
 
-CIntObject* CKingdHeroList::createHeroItem(size_t index)
+std::shared_ptr<CIntObject> CKingdHeroList::createHeroItem(size_t index)
 {
 	ui32 picCount = conf.go()->ac.overviewPics;
 	size_t heroesCount = LOCPLINT->cb->howManyHeroes(false);
 
-	if (index < heroesCount)
+	if(index < heroesCount)
 	{
-		auto   hero = new CHeroItem(LOCPLINT->cb->getHeroBySerial(index, false));
-		artSets.push_back(hero->heroArts);
+		auto hero = std::make_shared<CHeroItem>(LOCPLINT->cb->getHeroBySerial(index, false));
+		addSet(hero->heroArts);
 		return hero;
 	}
 	else
 	{
-		return new CAnimImage("OVSLOT", (index-2) % picCount );
+		return std::make_shared<CAnimImage>("OVSLOT", (index-2) % picCount );
 	}
 }
 
-void CKingdHeroList::destroyHeroItem(CIntObject *object)
-{
-	if (CHeroItem * hero = dynamic_cast<CHeroItem*>(object))
-	{
-		artSets.erase(std::find(artSets.begin(), artSets.end(), hero->heroArts));
-	}
-	delete object;
-}
-
 CKingdTownList::CKingdTownList(size_t maxSize)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	title = new CPicture("OVTITLE",16,0);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	title = std::make_shared<CPicture>("OVTITLE", 16, 0);
 	title->colorize(LOCPLINT->playerID);
-	townLabel   = new CLabel(146,10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[3]);
-	garrHeroLabel  = new CLabel(375,10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[4]);
-	visitHeroLabel = new CLabel(608,10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[5]);
+	townLabel = std::make_shared<CLabel>(146, 10,FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[3]);
+	garrHeroLabel = std::make_shared<CLabel>(375, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[4]);
+	visitHeroLabel = std::make_shared<CLabel>(608, 10, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->overview[5]);
 
 	ui32 townCount = LOCPLINT->cb->howManyTowns();
 	ui32 size = conf.go()->ac.overviewSize*116 + 19;
-	towns = new CListBox(std::bind(&CKingdTownList::createTownItem, this, _1), CListBox::DestroyFunc(),
-	                     Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size) );
+	towns = std::make_shared<CListBox>(std::bind(&CKingdTownList::createTownItem, this, _1),
+		Point(19,21), Point(0,116), maxSize, townCount, 0, 1, Rect(-19, -21, size, size));
 }
 
-void CKingdTownList::townChanged(const CGTownInstance *town)
+void CKingdTownList::townChanged(const CGTownInstance * town)
 {
-	std::list<CIntObject*> list = towns->getItems();
-	for(CIntObject* object : list)
+	for(std::shared_ptr<CIntObject> object : towns->getItems())
 	{
-		CTownItem * townItem = dynamic_cast<CTownItem*>(object);
-		if ( townItem && townItem->town == town)
+		CTownItem * townItem = dynamic_cast<CTownItem *>(object.get());
+		if(townItem && townItem->town == town)
 			townItem->update();
 	}
 }
 
 void CKingdTownList::updateGarrisons()
 {
-	std::list<CIntObject*> list = towns->getItems();
-	for(CIntObject* object : list)
+	for(std::shared_ptr<CIntObject> object : towns->getItems())
 	{
-		if (CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object) )
+		if(CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object.get()))
 			garrison->updateGarrisons();
 	}
 }
 
-CIntObject* CKingdTownList::createTownItem(size_t index)
+std::shared_ptr<CIntObject> CKingdTownList::createTownItem(size_t index)
 {
 	ui32 picCount = conf.go()->ac.overviewPics;
 	size_t townsCount = LOCPLINT->cb->howManyTowns();
 
-	if (index < townsCount)
-		return new CTownItem(LOCPLINT->cb->getTownBySerial(index));
+	if(index < townsCount)
+		return std::make_shared<CTownItem>(LOCPLINT->cb->getTownBySerial(index));
 	else
-		return new CAnimImage("OVSLOT", (index-2) % picCount );
+		return std::make_shared<CAnimImage>("OVSLOT", (index-2) % picCount );
 }
 
-CTownItem::CTownItem(const CGTownInstance* Town):
-	town(Town)
+CTownItem::CTownItem(const CGTownInstance * Town)
+	: town(Town)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	background =  new CAnimImage("OVSLOT", 6);
-	name = new CLabel(74, 8, FONT_SMALL, TOPLEFT, Colors::WHITE, town->name);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	background = std::make_shared<CAnimImage>("OVSLOT", 6);
+	name = std::make_shared<CLabel>(74, 8, FONT_SMALL, TOPLEFT, Colors::WHITE, town->name);
 
-	income = new CLabel( 190, 60, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(town->dailyIncome()[Res::GOLD]));
-	hall = new CTownInfo( 69, 31, town, true);
-	fort = new CTownInfo(111, 31, town, false);
+	income = std::make_shared<CLabel>( 190, 60, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(town->dailyIncome()[Res::GOLD]));
+	hall = std::make_shared<CTownInfo>( 69, 31, town, true);
+	fort = std::make_shared<CTownInfo>(111, 31, town, false);
 
-	garr = new CGarrisonInt(313, 3, 4, Point(232,0),  nullptr, Point(313,2), town->getUpperArmy(), town->visitingHero, true, true, true);
-	heroes = new HeroSlots(town, Point(244,6), Point(475,6), garr, false);
+	garr = std::make_shared<CGarrisonInt>(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, true);
+	heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
 
 	size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN];
 
-	picture = new CAnimImage("ITPT", iconIndex, 0, 5, 6);
-	new LRClickableAreaOpenTown(Rect(5, 6, 58, 64), town);
+	picture = std::make_shared<CAnimImage>("ITPT", iconIndex, 0, 5, 6);
+	openTown = std::make_shared<LRClickableAreaOpenTown>(Rect(5, 6, 58, 64), town);
 
-	for (size_t i=0; i<town->creatures.size(); i++)
+	for(size_t i=0; i<town->creatures.size(); i++)
 	{
-		growth.push_back(new CCreaInfo(Point(401+37*i, 78), town, i, true, true));
-		available.push_back(new CCreaInfo(Point(48+37*i, 78), town, i, true, false));
+		growth.push_back(std::make_shared<CCreaInfo>(Point(401+37*i, 78), town, i, true, true));
+		available.push_back(std::make_shared<CCreaInfo>(Point(48+37*i, 78), town, i, true, false));
 	}
 }
 
@@ -832,62 +811,62 @@ void CTownItem::update()
 class ArtSlotsTab : public CIntObject
 {
 public:
-	CAnimImage * background;
-	std::vector<CHeroArtPlace*> arts;
+	std::shared_ptr<CAnimImage> background;
+	std::vector<std::shared_ptr<CHeroArtPlace>> arts;
 
 	ArtSlotsTab()
 	{
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		background = new CAnimImage("OVSLOT", 4);
+		OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+		background = std::make_shared<CAnimImage>("OVSLOT", 4);
 		pos = background->pos;
-		for (size_t i=0; i<9; i++)
-			arts.push_back(new CHeroArtPlace(Point(270+i*48, 65)));
+		for(size_t i=0; i<9; i++)
+			arts.push_back(std::make_shared<CHeroArtPlace>(Point(270+i*48, 65)));
 	}
 };
 
 class BackpackTab : public CIntObject
 {
 public:
-	CAnimImage * background;
-	std::vector<CHeroArtPlace*> arts;
-	CButton *btnLeft;
-	CButton *btnRight;
+	std::shared_ptr<CAnimImage> background;
+	std::vector<std::shared_ptr<CHeroArtPlace>> arts;
+	std::shared_ptr<CButton> btnLeft;
+	std::shared_ptr<CButton> btnRight;
 
 	BackpackTab()
 	{
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		background = new CAnimImage("OVSLOT", 5);
+		OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+		background = std::make_shared<CAnimImage>("OVSLOT", 5);
 		pos = background->pos;
-		btnLeft = new CButton(Point(269, 66), "HSBTNS3", CButton::tooltip(), 0);
-		btnRight = new CButton(Point(675, 66), "HSBTNS5", CButton::tooltip(), 0);
-		for (size_t i=0; i<8; i++)
-			arts.push_back(new CHeroArtPlace(Point(295+i*48, 65)));
+		btnLeft = std::make_shared<CButton>(Point(269, 66), "HSBTNS3", CButton::tooltip(), 0);
+		btnRight = std::make_shared<CButton>(Point(675, 66), "HSBTNS5", CButton::tooltip(), 0);
+		for(size_t i=0; i<8; i++)
+			arts.push_back(std::make_shared<CHeroArtPlace>(Point(295+i*48, 65)));
 	}
 };
 
-CHeroItem::CHeroItem(const CGHeroInstance* Hero):
-	hero(Hero)
+CHeroItem::CHeroItem(const CGHeroInstance * Hero)
+	: hero(Hero)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
 	artTabs.resize(3);
-	auto arts1 = new ArtSlotsTab();
-	auto arts2 = new ArtSlotsTab();
-	auto backpack = new BackpackTab();
+	auto arts1 = std::make_shared<ArtSlotsTab>();
+	auto arts2 = std::make_shared<ArtSlotsTab>();
+	auto backpack = std::make_shared<BackpackTab>();
 	artTabs[0] = arts1;
 	artTabs[1] = arts2;
 	artTabs[2] = backpack;
-	arts1->recActions = DISPOSE | SHARE_POS;
-	arts2->recActions = DISPOSE | SHARE_POS;
-	backpack->recActions = DISPOSE | SHARE_POS;
+	arts1->recActions = SHARE_POS;
+	arts2->recActions = SHARE_POS;
+	backpack->recActions = SHARE_POS;
 
-	name = new CLabel(75, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name);
+	name = std::make_shared<CLabel>(75, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name);
 
 	//layout is not trivial: MACH4 - catapult - excluded, MISC[x] rearranged
 	assert(arts1->arts.size() == 9);
 	assert(arts2->arts.size() == 9);
 
-	std::map<ArtifactPosition, CHeroArtPlace*> arts =
+	CArtifactsOfHero::ArtPlaceMap arts =
 	{
 		{ArtifactPosition::HEAD, arts1->arts[0]},
 		{ArtifactPosition::SHOULDERS,arts1->arts[1]},
@@ -911,20 +890,20 @@ CHeroItem::CHeroItem(const CGHeroInstance* Hero):
 	};
 
 
-	heroArts = new CArtifactsOfHero(arts, backpack->arts, backpack->btnLeft, backpack->btnRight, true);
+	heroArts = std::make_shared<CArtifactsOfHero>(arts, backpack->arts, backpack->btnLeft, backpack->btnRight, true);
 	heroArts->setHero(hero);
 
-	artsTabs = new CTabbedInt(std::bind(&CHeroItem::onTabSelected, this, _1), std::bind(&CHeroItem::onTabDeselected, this, _1));
+	artsTabs = std::make_shared<CTabbedInt>(std::bind(&CHeroItem::onTabSelected, this, _1));
 
-	artButtons = new CToggleGroup(0);
-	for (size_t it = 0; it<3; it++)
+	artButtons = std::make_shared<CToggleGroup>(0);
+	for(size_t it = 0; it<3; it++)
 	{
 		int stringID[3] = {259, 261, 262};
 
 		std::string hover = CGI->generaltexth->overview[13+it];
 		std::string overlay = CGI->generaltexth->overview[8+it];
 
-		auto button = new CToggleButton(Point(364+it*112, 46), "OVBUTN3", CButton::tooltip(hover, overlay), 0);
+		auto button = std::make_shared<CToggleButton>(Point(364+it*112, 46), "OVBUTN3", CButton::tooltip(hover, overlay), 0);
 		button->addTextOverlay(CGI->generaltexth->allTexts[stringID[it]], FONT_SMALL, Colors::YELLOW);
 		artButtons->addToggle(it, button);
 	}
@@ -932,53 +911,58 @@ CHeroItem::CHeroItem(const CGHeroInstance* Hero):
 	artButtons->addCallback(std::bind(&CHeroItem::onArtChange, this, _1));
 	artButtons->setSelected(0);
 
-	garr = new CGarrisonInt(6, 78, 4, Point(), nullptr, Point(), hero, nullptr, true, true);
+	garr = std::make_shared<CGarrisonInt>(6, 78, 4, Point(), hero, nullptr, true, true);
 
-	portrait = new CAnimImage("PortraitsLarge", hero->portrait, 0, 5, 6);
-	heroArea = new CHeroArea(5, 6, hero);
+	portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait, 0, 5, 6);
+	heroArea = std::make_shared<CHeroArea>(5, 6, hero);
 
-	name = new CLabel(73, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name);
-	artsText = new CLabel(320, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->overview[2]);
+	name = std::make_shared<CLabel>(73, 7, FONT_SMALL, TOPLEFT, Colors::WHITE, hero->name);
+	artsText = std::make_shared<CLabel>(320, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->overview[2]);
 
-	for (size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
-		heroInfo.push_back(new InfoBox(Point(78+i*36, 26), InfoBox::POS_DOWN, InfoBox::SIZE_SMALL,
-		                   new InfoBoxHeroData(IInfoBoxData::HERO_PRIMARY_SKILL, hero, i)));
+	for(size_t i=0; i<GameConstants::PRIMARY_SKILLS; i++)
+	{
+		auto data = std::make_shared<InfoBoxHeroData>(IInfoBoxData::HERO_PRIMARY_SKILL, hero, i);
+		heroInfo.push_back(std::make_shared<InfoBox>(Point(78+i*36, 26), InfoBox::POS_DOWN, InfoBox::SIZE_SMALL, data));
+	}
 
-	for (size_t i=0; i<GameConstants::SKILL_PER_HERO; i++)
-		heroInfo.push_back(new InfoBox(Point(410+i*36, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL,
-		                   new InfoBoxHeroData(IInfoBoxData::HERO_SECONDARY_SKILL, hero, i)));
+	for(size_t i=0; i<GameConstants::SKILL_PER_HERO; i++)
+	{
+		auto data = std::make_shared<InfoBoxHeroData>(IInfoBoxData::HERO_SECONDARY_SKILL, hero, i);
+		heroInfo.push_back(std::make_shared<InfoBox>(Point(410+i*36, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL, data));
+	}
 
-	heroInfo.push_back(new InfoBox(Point(375, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL,
-	                   new InfoBoxHeroData(IInfoBoxData::HERO_SPECIAL, hero)));
+	{
+		auto data = std::make_shared<InfoBoxHeroData>(IInfoBoxData::HERO_SPECIAL, hero);
+		heroInfo.push_back(std::make_shared<InfoBox>(Point(375, 5), InfoBox::POS_NONE, InfoBox::SIZE_SMALL, data));
 
-	heroInfo.push_back(new InfoBox(Point(330, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL,
-	                   new InfoBoxHeroData(IInfoBoxData::HERO_EXPERIENCE, hero)));
+		data = std::make_shared<InfoBoxHeroData>(IInfoBoxData::HERO_EXPERIENCE, hero);
+		heroInfo.push_back(std::make_shared<InfoBox>(Point(330, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data));
 
-	heroInfo.push_back(new InfoBox(Point(280, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL,
-	                   new InfoBoxHeroData(IInfoBoxData::HERO_MANA, hero)));
+		data = std::make_shared<InfoBoxHeroData>(IInfoBoxData::HERO_MANA, hero);
+		heroInfo.push_back(std::make_shared<InfoBox>(Point(280, 5), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data));
+	}
 
-	morale = new MoraleLuckBox(true, Rect(225, 53, 30, 22), true);
-	luck  = new MoraleLuckBox(false, Rect(225, 28, 30, 22), true);
+	morale = std::make_shared<MoraleLuckBox>(true, Rect(225, 53, 30, 22), true);
+	luck = std::make_shared<MoraleLuckBox>(false, Rect(225, 28, 30, 22), true);
 
 	morale->set(hero);
 	luck->set(hero);
 }
 
-CIntObject * CHeroItem::onTabSelected(size_t index)
+
+void CHeroItem::updateGarrisons()
 {
-	return artTabs[index];
+	garr->recreateSlots();
 }
 
-void CHeroItem::onTabDeselected(CIntObject *object)
+std::shared_ptr<CIntObject> CHeroItem::onTabSelected(size_t index)
 {
-	addChild(object, false);
-	object->deactivate();
-	object->recActions = DISPOSE | SHARE_POS;
+	return artTabs.at(index);
 }
 
 void CHeroItem::onArtChange(int tabIndex)
 {
 	//redraw item after background change
-	if (active)
+	if(active)
 		redraw();
 }

+ 73 - 68
client/windows/CKingdomInterface.h

@@ -61,16 +61,16 @@ public:
 
 private:
 	InfoSize size;
-	InfoPos  infoPos;
-	IInfoBoxData *data;
+	InfoPos infoPos;
+	std::shared_ptr<IInfoBoxData> data;
 
-	CLabel * value;
-	CLabel * name;
-	CAnimImage * image;
-	CHoverableArea *hover;
+	std::shared_ptr<CLabel> value;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CAnimImage> image;
+	std::shared_ptr<CHoverableArea> hover;
 
 public:
-	InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data);
+	InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IInfoBoxData> Data);
 	~InfoBox();
 
 	void clickRight(tribool down, bool previousState) override;
@@ -106,7 +106,7 @@ public:
 	virtual size_t getImageIndex()=0;
 
 	//TODO: replace with something better
-	virtual bool prepareMessage(std::string &text, CComponent **comp)=0;
+	virtual void prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp)=0;
 
 	virtual ~IInfoBoxData(){};
 };
@@ -126,7 +126,7 @@ public:
 	std::string getHoverText() override;
 	size_t getImageIndex() override;
 
-	bool prepareMessage(std::string &text, CComponent **comp) override;
+	void prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp) override;
 };
 
 class InfoBoxHeroData : public InfoBoxAbstractHeroData
@@ -144,7 +144,7 @@ public:
 	std::string getHoverText() override;
 	std::string getValueText() override;
 
-	bool prepareMessage(std::string &text, CComponent **comp) override;
+	void prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp) override;
 };
 
 class InfoBoxCustomHeroData : public InfoBoxAbstractHeroData
@@ -176,7 +176,7 @@ public:
 	std::string getHoverText() override;
 	size_t getImageIndex() override;
 
-	bool prepareMessage(std::string &text, CComponent **comp) override;
+	void prepareMessage(std::string & text, std::shared_ptr<CComponent> & comp) override;
 };
 
 //TODO!!!
@@ -197,8 +197,6 @@ public:
 	size_t getImageIndex() override;
 };
 
-////////////////////////////////////////////////////////////////////////////////
-
 /// Class which holds all parts of kingdom overview window
 class CKingdomInterface : public CWindowObject, public CGarrisonHolder, public CArtifactHolder
 {
@@ -215,25 +213,27 @@ private:
 	};
 	std::vector<OwnedObjectInfo> objects;
 
-	CListBox * dwellingsList;
-	CTabbedInt * tabArea;
+	std::shared_ptr<CListBox> dwellingsList;
+	std::shared_ptr<CTabbedInt> tabArea;
 
 	//Main buttons
-	CButton *btnTowns;
-	CButton *btnHeroes;
-	CButton *btnExit;
+	std::shared_ptr<CButton> btnTowns;
+	std::shared_ptr<CButton> btnHeroes;
+	std::shared_ptr<CButton> btnExit;
 
 	//Buttons for scrolling dwellings list
-	CButton *dwellUp, *dwellDown;
-	CButton *dwellTop, *dwellBottom;
+	std::shared_ptr<CButton> dwellUp;
+	std::shared_ptr<CButton> dwellDown;
+	std::shared_ptr<CButton> dwellTop;
+	std::shared_ptr<CButton> dwellBottom;
 
-	InfoBox * minesBox[7];
+	std::array<std::shared_ptr<InfoBox>, 7> minesBox;
 
-	CHoverableArea * incomeArea;
-	CLabel * incomeAmount;
+	std::shared_ptr<CHoverableArea> incomeArea;
+	std::shared_ptr<CLabel> incomeAmount;
 
-	CGStatusBar * statusbar;
-	CResDataBar *resdatabar;
+	std::shared_ptr<CGStatusBar> statusbar;
+	std::shared_ptr<CResDataBar> resdatabar;
 
 	void activateTab(size_t which);
 
@@ -242,8 +242,8 @@ private:
 	void generateObjectsList(const std::vector<const CGObjectInstance * > &ownedObjects);
 	void generateMinesList(const std::vector<const CGObjectInstance * > &ownedObjects);
 
-	CIntObject* createOwnedObject(size_t index);
-	CIntObject* createMainTab(size_t index);
+	std::shared_ptr<CIntObject> createOwnedObject(size_t index);
+	std::shared_ptr<CIntObject> createMainTab(size_t index);
 
 public:
 	CKingdomInterface();
@@ -259,67 +259,73 @@ public:
 /// List item with town
 class CTownItem : public CIntObject, public CGarrisonHolder
 {
-	CAnimImage *background;
-	CAnimImage *picture;
-	CLabel *name;
-	CLabel *income;
-	CGarrisonInt *garr;
+	std::shared_ptr<CAnimImage> background;
+	std::shared_ptr<CAnimImage> picture;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CLabel> income;
+	std::shared_ptr<CGarrisonInt> garr;
+
+	std::shared_ptr<HeroSlots> heroes;
+	std::shared_ptr<CTownInfo> hall;
+	std::shared_ptr<CTownInfo> fort;
+
+	std::vector<std::shared_ptr<CCreaInfo>> available;
+	std::vector<std::shared_ptr<CCreaInfo>> growth;
 
-	HeroSlots *heroes;
-	CTownInfo *hall, *fort;
-	std::vector<CCreaInfo*> available;
-	std::vector<CCreaInfo*> growth;
+	std::shared_ptr<LRClickableAreaOpenTown> openTown;
 
 public:
 	const CGTownInstance * town;
 
-	CTownItem(const CGTownInstance* town);
+	CTownItem(const CGTownInstance * Town);
 
 	void updateGarrisons() override;
 	void update();
 };
 
 /// List item with hero
-class CHeroItem : public CIntObject, public CWindowWithGarrison
+class CHeroItem : public CIntObject, public CGarrisonHolder
 {
 	const CGHeroInstance * hero;
 
-	std::vector<CIntObject *> artTabs;
+	std::vector<std::shared_ptr<CIntObject>> artTabs;
 
-	CAnimImage *portrait;
-	CLabel *name;
-	CHeroArea *heroArea;
+	std::shared_ptr<CAnimImage> portrait;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CHeroArea> heroArea;
 
-	CLabel *artsText;
-	CTabbedInt *artsTabs;
+	std::shared_ptr<CLabel> artsText;
+	std::shared_ptr<CTabbedInt> artsTabs;
 
-	CToggleGroup *artButtons;
-	std::vector<InfoBox*> heroInfo;
-	MoraleLuckBox * morale, * luck;
+	std::shared_ptr<CToggleGroup> artButtons;
+	std::vector<std::shared_ptr<InfoBox>> heroInfo;
+	std::shared_ptr<MoraleLuckBox> morale;
+	std::shared_ptr<MoraleLuckBox> luck;
+
+	std::shared_ptr<CGarrisonInt> garr;
 
 	void onArtChange(int tabIndex);
 
-	CIntObject * onTabSelected(size_t index);
-	void onTabDeselected(CIntObject *object);
+	std::shared_ptr<CIntObject> onTabSelected(size_t index);
 
 public:
-	CArtifactsOfHero *heroArts;
+ 	std::shared_ptr<CArtifactsOfHero> heroArts;
 
-	CHeroItem(const CGHeroInstance* hero);
+	void updateGarrisons() override;
+
+	CHeroItem(const CGHeroInstance * hero);
 };
 
 /// Tab with all hero-specific data
 class CKingdHeroList : public CIntObject, public CGarrisonHolder, public CWindowWithArtifacts
 {
 private:
-	std::vector<CHeroItem*> heroItems;
-	CListBox * heroes;
-	CPicture * title;
-	CLabel * heroLabel;
-	CLabel * skillsLabel;
-
-	CIntObject* createHeroItem(size_t index);
-	void destroyHeroItem(CIntObject *item);
+	std::shared_ptr<CListBox> heroes;
+	std::shared_ptr<CPicture> title;
+	std::shared_ptr<CLabel> heroLabel;
+	std::shared_ptr<CLabel> skillsLabel;
+
+	std::shared_ptr<CIntObject> createHeroItem(size_t index);
 public:
 	CKingdHeroList(size_t maxSize);
 
@@ -330,17 +336,16 @@ public:
 class CKingdTownList : public CIntObject, public CGarrisonHolder
 {
 private:
-	std::vector<CTownItem*> townItems;
-	CListBox * towns;
-	CPicture * title;
-	CLabel * townLabel;
-	CLabel * garrHeroLabel;
-	CLabel * visitHeroLabel;
-
-	CIntObject* createTownItem(size_t index);
+	std::shared_ptr<CListBox> towns;
+	std::shared_ptr<CPicture> title;
+	std::shared_ptr<CLabel> townLabel;
+	std::shared_ptr<CLabel> garrHeroLabel;
+	std::shared_ptr<CLabel> visitHeroLabel;
+
+	std::shared_ptr<CIntObject> createTownItem(size_t index);
 public:
 	CKingdTownList(size_t maxSize);
 
-	void townChanged(const CGTownInstance *town);
+	void townChanged(const CGTownInstance * town);
 	void updateGarrisons() override;
 };

+ 41 - 43
client/windows/CQuestLog.cpp

@@ -62,15 +62,15 @@ void CQuestIcon::showAll(SDL_Surface * to)
 	CAnimImage::showAll(to);
 }
 
-CQuestMinimap::CQuestMinimap (const Rect & position) :
-CMinimap (position),
-	currentQuest (nullptr)
+CQuestMinimap::CQuestMinimap(const Rect & position)
+	: CMinimap(position),
+	currentQuest(nullptr)
 {
 }
 
 void CQuestMinimap::addQuestMarks (const QuestInfo * q)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	icons.clear();
 
 	int3 tile;
@@ -96,13 +96,13 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
 void CQuestMinimap::update()
 {
 	CMinimap::update();
-	if (currentQuest)
-		addQuestMarks (currentQuest);
+	if(currentQuest)
+		addQuestMarks(currentQuest);
 }
 
 void CQuestMinimap::iconClicked()
 {
-	if (currentQuest->obj)
+	if(currentQuest->obj)
 		adventureInt->centerOn (currentQuest->obj->pos);
 	//moveAdvMapSelection();
 }
@@ -110,44 +110,38 @@ void CQuestMinimap::iconClicked()
 void CQuestMinimap::showAll(SDL_Surface * to)
 {
 	CIntObject::showAll(to); // blitting IntObject directly to hide radar
-	for (auto pic : icons)
-		pic->showAll(to);
+//	for (auto pic : icons)
+//		pic->showAll(to);
 }
 
-CQuestLog::CQuestLog (const std::vector<QuestInfo> & Quests) :
-	CWindowObject(PLAYER_COLORED | BORDERED, "questDialog"),
+CQuestLog::CQuestLog (const std::vector<QuestInfo> & Quests)
+	: CWindowObject(PLAYER_COLORED | BORDERED, "questDialog"),
 	questIndex(0),
 	currentQuest(nullptr),
-	componentsBox(nullptr),
 	hideComplete(false),
-	quests(Quests),
-	slider(nullptr)
+	quests(Quests)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	init();
-}
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-void CQuestLog::init()
-{
 	const JsonNode & texts = CGI->generaltexth->localizedTexts["questLog"];
 
-	minimap = new CQuestMinimap (Rect (12, 12, 169, 169));
+	minimap = std::make_shared<CQuestMinimap>(Rect(12, 12, 169, 169));
 	// TextBox have it's own 4 pixel padding from top at least for English. To achieve 10px from both left and top only add 6px margin
-	description = new CTextBox ("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, TOPLEFT, Colors::WHITE);
-	ok = new CButton(Point(539, 398), "IOKAY.DEF", CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close,this), SDLK_RETURN);
+	description = std::make_shared<CTextBox>("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, TOPLEFT, Colors::WHITE);
+	ok = std::make_shared<CButton>(Point(539, 398), "IOKAY.DEF", CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close, this), SDLK_RETURN);
 	// Both button and lable are shifted to -2px by x and y to not make them actually look like they're on same line with quests list and ok button
-	hideCompleteButton = new CToggleButton(Point(10, 396), "sysopchk.def", CButton::tooltip(texts["hideComplete"]), std::bind(&CQuestLog::toggleComplete, this, _1));
-	hideCompleteLabel = new CLabel(46, 398, FONT_MEDIUM, TOPLEFT, Colors::WHITE, texts["hideComplete"]["label"].String());
-	slider = new CSlider(Point(166, 195), 191, std::bind(&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, 0, false, CSlider::BROWN);
+	hideCompleteButton = std::make_shared<CToggleButton>(Point(10, 396), "sysopchk.def", CButton::tooltip(texts["hideComplete"]), std::bind(&CQuestLog::toggleComplete, this, _1));
+	hideCompleteLabel = std::make_shared<CLabel>(46, 398, FONT_MEDIUM, TOPLEFT, Colors::WHITE, texts["hideComplete"]["label"].String());
+	slider = std::make_shared<CSlider>(Point(166, 195), 191, std::bind(&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, 0, false, CSlider::BROWN);
 
 	recreateLabelList();
-	recreateQuestList (0);
+	recreateQuestList(0);
 }
 
 void CQuestLog::recreateLabelList()
 {
-	if (labels.size())
-		labels.clear();
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	labels.clear();
 
 	bool completeMissing = true;
 	int currentLabel = 0;
@@ -209,8 +203,8 @@ void CQuestLog::recreateLabelList()
 
 void CQuestLog::showAll(SDL_Surface * to)
 {
-	CWindowObject::showAll (to);
-	if (labels.size() && labels[questIndex]->active)
+	CWindowObject::showAll(to);
+	if(labels.size() && labels[questIndex]->active)
 	{
 		Rect rect = Rect::around(labels[questIndex]->pos);
 		rect.x -= 2; // Adjustment needed as we want selection box on top of border in graphics
@@ -232,7 +226,7 @@ void CQuestLog::recreateQuestList (int newpos)
 	minimap->update();
 }
 
-void CQuestLog::selectQuest (int which, int labelId)
+void CQuestLog::selectQuest(int which, int labelId)
 {
 	questIndex = labelId;
 	currentQuest = &quests[which];
@@ -241,14 +235,15 @@ void CQuestLog::selectQuest (int which, int labelId)
 	MetaString text;
 	std::vector<Component> components;
 	currentQuest->quest->getVisitText (text, components, currentQuest->quest->isCustomFirst, true);
-	if (description->slider)
+	if(description->slider)
 		description->slider->moveToMin(); // scroll text to start position
-	description->setText (text.toString()); //TODO: use special log entry text
+	description->setText(text.toString()); //TODO: use special log entry text
+
+	componentsBox.reset();
 
-	vstd::clear_pointer(componentsBox);
 	int componentsSize = components.size();
 	int descriptionHeight = DESCRIPTION_HEIGHT_MAX;
-	if (componentsSize)
+	if(componentsSize)
 	{
 		descriptionHeight -= 15;
 		CComponent::ESize imageSize = CComponent::large;
@@ -290,12 +285,16 @@ void CQuestLog::selectQuest (int which, int labelId)
 				break;
 		}
 
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		std::vector<CComponent *> comps;
-		for (auto & component : components)
-			comps.push_back(new CComponent(component, imageSize));
+		OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+
+		std::vector<std::shared_ptr<CComponent>> comps;
+		for(auto & component : components)
+		{
+			auto c = std::make_shared<CComponent>(component, imageSize);
+			comps.push_back(c);
+		}
 
-		componentsBox = new CComponentBox(comps, Rect(202, 20+descriptionHeight+15, 391, DESCRIPTION_HEIGHT_MAX-(20+descriptionHeight)));
+		componentsBox = std::make_shared<CComponentBox>(comps, Rect(202, 20+descriptionHeight+15, 391, DESCRIPTION_HEIGHT_MAX-(20+descriptionHeight)));
 	}
 	description->resize(Point(385, descriptionHeight));
 
@@ -303,15 +302,14 @@ void CQuestLog::selectQuest (int which, int labelId)
 	redraw();
 }
 
-void CQuestLog::sliderMoved (int newpos)
+void CQuestLog::sliderMoved(int newpos)
 {
-	recreateQuestList (newpos); //move components
+	recreateQuestList(newpos); //move components
 	redraw();
 }
 
 void CQuestLog::toggleComplete(bool on)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	hideComplete = on;
 	recreateLabelList();
 	recreateQuestList(0);

+ 13 - 16
client/windows/CQuestLog.h

@@ -38,7 +38,7 @@ class CQuestLabel : public LRClickableAreaWText, public CMultiLineLabel
 public:
 	std::function<void()> callback;
 
-	CQuestLabel (Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "")
+	CQuestLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "")
 		: CMultiLineLabel (position, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){};
 	void clickLeft(tribool down, bool previousState) override;
 	void showAll(SDL_Surface * to) override;
@@ -49,7 +49,7 @@ class CQuestIcon : public CAnimImage
 public:
 	std::function<void()> callback; //TODO: merge with other similar classes?
 
-	CQuestIcon (const std::string &defname, int index, int x=0, int y=0);
+	CQuestIcon(const std::string &defname, int index, int x=0, int y=0);
 
 	void clickLeft(tribool down, bool previousState) override;
 	void showAll(SDL_Surface * to) override;
@@ -57,17 +57,16 @@ public:
 
 class CQuestMinimap : public CMinimap
 {
-	std::vector <std::shared_ptr<CQuestIcon>> icons;
+	std::vector<std::shared_ptr<CQuestIcon>> icons;
 
 	void clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface
 	void iconClicked();
 	void mouseMoved (const SDL_MouseMotionEvent & sEvent) override{};
 
 public:
-
 	const QuestInfo * currentQuest;
 
-	CQuestMinimap (const Rect & position);
+	CQuestMinimap(const Rect & position);
 	//should be called to invalidate whole map - different player or level
 	void update();
 	void addQuestMarks (const QuestInfo * q);
@@ -79,22 +78,20 @@ class CQuestLog : public CWindowObject
 {
 	int questIndex;
 	const QuestInfo * currentQuest;
-	CComponentBox * componentsBox;
+	std::shared_ptr<CComponentBox> componentsBox;
 	bool hideComplete;
-	CToggleButton * hideCompleteButton;
-	CLabel * hideCompleteLabel;
+	std::shared_ptr<CToggleButton> hideCompleteButton;
+	std::shared_ptr<CLabel> hideCompleteLabel;
 
 	const std::vector<QuestInfo> quests;
-	std::vector <std::shared_ptr<CQuestLabel>> labels;
-	CTextBox * description;
-	CQuestMinimap * minimap;
-	CSlider * slider; //scrolls quests
-	CButton *ok;
+	std::vector<std::shared_ptr<CQuestLabel>> labels;
+	std::shared_ptr<CTextBox> description;
+	std::shared_ptr<CQuestMinimap> minimap;
+	std::shared_ptr<CSlider> slider; //scrolls quests
+	std::shared_ptr<CButton> ok;
 
-	void init ();
 public:
-
-	CQuestLog (const std::vector<QuestInfo> & Quests);
+	CQuestLog(const std::vector<QuestInfo> & Quests);
 
 	~CQuestLog(){};
 

+ 48 - 62
client/windows/CSpellWindow.cpp

@@ -102,7 +102,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 	myHero(_myHero),
 	myInt(_myInt)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	//initializing castable spells
 	mySpells.reserve(CGI->spellh->objects.size());
 	for(const CSpell * spell : CGI->spellh->objects)
@@ -168,13 +168,13 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 
 	//numbers of spell pages computed
 
-	leftCorner = new CPicture("SpelTrnL.bmp", 97, 77);
-	rightCorner = new CPicture("SpelTrnR.bmp", 487, 72);
+	leftCorner = std::make_shared<CPicture>("SpelTrnL.bmp", 97, 77);
+	rightCorner = std::make_shared<CPicture>("SpelTrnR.bmp", 487, 72);
 
-	spells = std::make_shared<CAnimation>("Spells");
+	spellIcons = std::make_shared<CAnimation>("Spells");
 
-	spellTab = new CAnimImage("SpelTab", selectedTab, 0, 524, 88);
-	schools = new CAnimImage("Schools",0,0,117,74);
+	schoolTab = std::make_shared<CAnimImage>("SpelTab", selectedTab, 0, 524, 88);
+	schoolPicture = std::make_shared<CAnimImage>("Schools", 0, 0, 117, 74);
 
 	schoolBorders[0] = std::make_shared<CAnimation>("SplevA.def");
 	schoolBorders[1] = std::make_shared<CAnimation>("SplevF.def");
@@ -182,34 +182,34 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 	schoolBorders[3] = std::make_shared<CAnimation>("SplevE.def");
 
 	for(auto item : schoolBorders)
-		item->load();
-	mana = new CLabel(435, 426, FONT_SMALL, CENTER, Colors::YELLOW, boost::lexical_cast<std::string>(myHero->mana));
-	statusBar = new CGStatusBar(7, 569, "Spelroll.bmp");
+		item->preload();
+	mana = std::make_shared<CLabel>(435, 426, FONT_SMALL, CENTER, Colors::YELLOW, boost::lexical_cast<std::string>(myHero->mana));
+	statusBar = std::make_shared<CGStatusBar>(7, 569, "Spelroll.bmp");
 
 	SDL_Rect temp_rect = genRect(45, 35, 479 + pos.x, 405 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fexitb, this), 460, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fexitb, this), 460, this));
 	temp_rect = genRect(45, 35, 221 + pos.x, 405 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fbattleSpellsb, this), 453, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fbattleSpellsb, this), 453, this));
 	temp_rect = genRect(45, 35, 355 + pos.x, 405 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fadvSpellsb, this), 452, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fadvSpellsb, this), 452, this));
 	temp_rect = genRect(45, 35, 418 + pos.x, 405 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fmanaPtsb, this), 459, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fmanaPtsb, this), 459, this));
 
 	temp_rect = genRect(36, 56, 549 + pos.x, 94 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 0), 454, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 0), 454, this));
 	temp_rect = genRect(36, 56, 549 + pos.x, 151 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 3), 457, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 3), 457, this));
 	temp_rect = genRect(36, 56, 549 + pos.x, 210 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 1), 455, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 1), 455, this));
 	temp_rect = genRect(36, 56, 549 + pos.x, 270 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 2), 456, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 2), 456, this));
 	temp_rect = genRect(36, 56, 549 + pos.x, 330 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 4), 458, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::selectSchool, this, 4), 458, this));
 
 	temp_rect = genRect(leftCorner->bg->h, leftCorner->bg->w, 97 + pos.x, 77 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fLcornerb, this), 450, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fLcornerb, this), 450, this));
 	temp_rect = genRect(rightCorner->bg->h, rightCorner->bg->w, 487 + pos.x, 72 + pos.y);
-	new InteractiveArea(temp_rect, std::bind(&CSpellWindow::fRcornerb, this), 451, this);
+	interactiveAreas.push_back(std::make_shared<InteractiveArea>(temp_rect, std::bind(&CSpellWindow::fRcornerb, this), 451, this));
 
 	//areas for spells
 	int xpos = 117 + pos.x, ypos = 90 + pos.y;
@@ -217,7 +217,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 	for(int v=0; v<12; ++v)
 	{
 		temp_rect = genRect(65, 78, xpos, ypos);
-		spellAreas[v] = new SpellArea(temp_rect, this);
+		spellAreas[v] = std::make_shared<SpellArea>(temp_rect, this);
 
 		if(v == 5) //to right page
 		{
@@ -237,7 +237,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 	}
 
 	selectedTab = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap;
-	spellTab->setFrame(selectedTab, 0);
+	schoolTab->setFrame(selectedTab, 0);
 	int cp = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap;
 	// spellbook last page battle index is not reset after battle, so this needs to stay here
 	vstd::abetween(cp, 0, std::max(0, pagesWithinCurrentTab() - 1));
@@ -248,9 +248,6 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 
 CSpellWindow::~CSpellWindow()
 {
-	for(auto item : schoolBorders)
-		item->unload();
-	spells->unload();
 }
 
 void CSpellWindow::fexitb()
@@ -263,7 +260,7 @@ void CSpellWindow::fexitb()
 
 void CSpellWindow::fadvSpellsb()
 {
-	if (battleSpellsOnly == true)
+	if(battleSpellsOnly == true)
 	{
 		turnPageRight();
 		battleSpellsOnly = false;
@@ -274,7 +271,7 @@ void CSpellWindow::fadvSpellsb()
 
 void CSpellWindow::fbattleSpellsb()
 {
-	if (battleSpellsOnly == false)
+	if(battleSpellsOnly == false)
 	{
 		turnPageLeft();
 		battleSpellsOnly = true;
@@ -289,14 +286,14 @@ void CSpellWindow::fmanaPtsb()
 
 void CSpellWindow::selectSchool(int school)
 {
-	if (selectedTab != school)
+	if(selectedTab != school)
 	{
-		if (selectedTab < school)
+		if(selectedTab < school)
 			turnPageLeft();
 		else
 			turnPageRight();
 		selectedTab = school;
-		spellTab->setFrame(selectedTab, 0);
+		schoolTab->setFrame(selectedTab, 0);
 		setCurrentPage(0);
 	}
 	computeSpellsPerArea();
@@ -405,9 +402,9 @@ void CSpellWindow::computeSpellsPerArea()
 void CSpellWindow::setCurrentPage(int value)
 {
 	currentPage = value;
-	schools->visible = selectedTab!=4 && currentPage == 0;
+	schoolPicture->visible = selectedTab!=4 && currentPage == 0;
 	if(selectedTab != 4)
-		schools->setFrame(selectedTab, 0);
+		schoolPicture->setFrame(selectedTab, 0);
 	leftCorner->visible = currentPage != 0;
 	rightCorner->visible = (currentPage+1) < pagesWithinCurrentTab();
 
@@ -416,13 +413,13 @@ void CSpellWindow::setCurrentPage(int value)
 
 void CSpellWindow::turnPageLeft()
 {
-	if (settings["video"]["spellbookAnimation"].Bool())
+	if(settings["video"]["spellbookAnimation"].Bool())
 		CCS->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen);
 }
 
 void CSpellWindow::turnPageRight()
 {
-	if (settings["video"]["spellbookAnimation"].Bool())
+	if(settings["video"]["spellbookAnimation"].Bool())
 		CCS->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen);
 }
 
@@ -503,27 +500,23 @@ CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)
 	this->owner = owner;
 	addUsedEvents(LCLICK | RCLICK | HOVER);
 
-	spellCost = whichSchool = schoolLevel = -1;
+	schoolLevel = -1;
 	mySpell = nullptr;
-	schoolBorder = nullptr;
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
-	image = new CAnimImage(owner->spells, 0, 0);
+	image = std::make_shared<CAnimImage>(owner->spellIcons, 0, 0);
 	image->visible = false;
 
-	name  = new CLabel(39, 70, FONT_TINY, CENTER);
-	level = new CLabel(39, 82, FONT_TINY, CENTER);
-	cost  = new CLabel(39, 94, FONT_TINY, CENTER);
+	name = std::make_shared<CLabel>(39, 70, FONT_TINY, CENTER);
+	level = std::make_shared<CLabel>(39, 82, FONT_TINY, CENTER);
+	cost = std::make_shared<CLabel>(39, 94, FONT_TINY, CENTER);
 
 	for(auto l : {name, level, cost})
 		l->autoRedraw = false;
 }
 
-CSpellWindow::SpellArea::~SpellArea()
-{
-
-}
+CSpellWindow::SpellArea::~SpellArea() = default;
 
 void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 {
@@ -551,7 +544,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 		//battle spell on adv map or adventure map spell during combat => display infowindow, not cast
 		if((combatSpell ^ inCombat) || inCastle)
 		{
-			std::vector<CComponent*> hlp(1, new CComponent(CComponent::spell, mySpell->id, 0));
+			std::vector<std::shared_ptr<CComponent>> hlp(1, std::make_shared<CComponent>(CComponent::spell, mySpell->id, 0));
 			owner->myInt->showInfoDialog(mySpell->getLevelInfo(schoolLevel).description, hlp);
 		}
 		else if(combatSpell)
@@ -607,8 +600,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
 			boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast<std::string>(causedDmg));
 		}
 
-		CRClickPopup::createAndPush(mySpell->getLevelInfo(schoolLevel).description + dmgInfo,
-		                            new CComponent(CComponent::spell, mySpell->id));
+		CRClickPopup::createAndPush(mySpell->getLevelInfo(schoolLevel).description + dmgInfo, std::make_shared<CComponent>(CComponent::spell, mySpell->id));
 	}
 }
 
@@ -623,20 +615,9 @@ void CSpellWindow::SpellArea::hover(bool on)
 	}
 }
 
-void CSpellWindow::SpellArea::showAll(SDL_Surface * to)
-{
-	if(mySpell)
-	{
-		//printing border (indicates level of magic school)
-		if(schoolBorder)
-			schoolBorder->draw(to, pos.x, pos.y);
-		CIntObject::showAll(to);
-	}
-}
-
 void CSpellWindow::SpellArea::setSpell(const CSpell * spell)
 {
-	schoolBorder = nullptr;
+	schoolBorder.reset();
 	image->visible = false;
 	name->setText("");
 	level->setText("");
@@ -644,12 +625,17 @@ void CSpellWindow::SpellArea::setSpell(const CSpell * spell)
 	mySpell = spell;
 	if(mySpell)
 	{
+		int whichSchool = 0; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
 		schoolLevel = owner->myHero->getSpellSchoolLevel(mySpell, &whichSchool);
-		spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
+		auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
 
 		image->setFrame(mySpell->id);
 		image->visible = true;
-		schoolBorder = owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab]->getImage(schoolLevel,0);
+
+		{
+			OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+			schoolBorder = std::make_shared<CAnimImage>(owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab], schoolLevel);
+		}
 
 		SDL_Color firstLineColor, secondLineColor;
 		if(spellCost > owner->myHero->mana) //hero cannot cast this spell

+ 16 - 14
client/windows/CSpellWindow.h

@@ -30,12 +30,12 @@ class CSpellWindow : public CWindowObject
 	{
 		const CSpell * mySpell;
 		int schoolLevel; //range: 0 none, 3 - expert
-		int whichSchool; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
-		int spellCost;
 		CSpellWindow * owner;
-		CAnimImage * image;
-		IImage * schoolBorder;
-		CLabel * name, * level, * cost;
+		std::shared_ptr<CAnimImage> image;
+		std::shared_ptr<CAnimImage> schoolBorder;
+		std::shared_ptr<CLabel> name;
+		std::shared_ptr<CLabel> level;
+		std::shared_ptr<CLabel> cost;
 	public:
 		SpellArea(SDL_Rect pos, CSpellWindow * owner);
 		~SpellArea();
@@ -44,7 +44,6 @@ class CSpellWindow : public CWindowObject
 		void clickLeft(tribool down, bool previousState) override;
 		void clickRight(tribool down, bool previousState) override;
 		void hover(bool on) override;
-		void showAll(SDL_Surface * to) override;
 	};
 
 	class InteractiveArea : public CIntObject
@@ -62,17 +61,20 @@ class CSpellWindow : public CWindowObject
 		InteractiveArea(const SDL_Rect & myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner);
 	};
 
-	CPicture * leftCorner, * rightCorner;
+	std::shared_ptr<CAnimation> spellIcons;
+	std::array<std::shared_ptr<CAnimation>, 4> schoolBorders; //[0]: air, [1]: fire, [2]: water, [3]: earth
 
-	std::shared_ptr<CAnimation> spells; //pictures of spells
+	std::shared_ptr<CPicture> leftCorner;
+	std::shared_ptr<CPicture> rightCorner;
 
-	CAnimImage * spellTab; //school select
-	CAnimImage * schools; //schools' pictures
-	std::array< std::shared_ptr<CAnimation>, 4> schoolBorders; //schools' 'borders': [0]: air, [1]: fire, [2]: water, [3]: earth
+	std::shared_ptr<CAnimImage> schoolTab;
+	std::shared_ptr<CAnimImage> schoolPicture;
 
-	SpellArea * spellAreas[12];
-	CLabel * mana;
-	CGStatusBar * statusBar;
+	std::array<std::shared_ptr<SpellArea>, 12> spellAreas;
+	std::shared_ptr<CLabel> mana;
+	std::shared_ptr<CGStatusBar> statusBar;
+
+	std::vector<std::shared_ptr<InteractiveArea>> interactiveAreas;
 
 	int sitesPerTabAdv[5];
 	int sitesPerTabBattle[5];

+ 163 - 188
client/windows/CTradeWindow.cpp

@@ -31,34 +31,35 @@
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/mapObjects/CGMarket.h"
 
-CTradeWindow::CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial):
-	CIntObject(LCLICK | HOVER | RCLICK, pos),
+CTradeWindow::CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial)
+	: CIntObject(LCLICK | HOVER | RCLICK, pos),
 	type(EType(-1)),// set to invalid, will be corrected in setType
 	id(ID),
 	serial(Serial),
 	left(Left)
 {
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	downSelection = false;
 	hlp = nullptr;
-	image = nullptr;
 	setType(Type);
 }
 
 void CTradeWindow::CTradeableItem::setType(EType newType)
 {
-	if (type != newType)
+	if(type != newType)
 	{
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
+		OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 		type = newType;
-		delete image;
 
-		if (getIndex() < 0)
+		if(getIndex() < 0)
 		{
-			image = new CAnimImage(getFilename(), 0);
+			image = std::make_shared<CAnimImage>(getFilename(), 0);
 			image->disable();
 		}
 		else
-			image = new CAnimImage(getFilename(), getIndex());
+		{
+			image = std::make_shared<CAnimImage>(getFilename(), getIndex());
+		}
 	}
 }
 
@@ -177,11 +178,11 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
 			CAltarWindow *aw = static_cast<CAltarWindow *>(mw);
 			if(const CArtifactInstance *movedArt = aw->arts->commonInfo->src.art)
 			{
-				aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this, movedArt);
+				aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this->shared_from_this(), movedArt);
 			}
 			else if(const CArtifactInstance *art = getArtInstance())
 			{
-				aw->arts->commonInfo->src.AOH = aw->arts;
+				aw->arts->commonInfo->src.AOH = aw->arts.get();
 				aw->arts->commonInfo->src.art = art;
 				aw->arts->commonInfo->src.slotID = aw->hero->getArtPos(art);
 				aw->arts->markPossibleSlots(art);
@@ -200,15 +201,15 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
 		}
 		if(left)
 		{
-			if(mw->hLeft != this)
-				mw->hLeft = this;
+			if(mw->hLeft != this->shared_from_this())
+				mw->hLeft = this->shared_from_this();
 			else
 				return;
 		}
 		else
 		{
-			if(mw->hRight != this)
-				mw->hRight = this;
+			if(mw->hRight != this->shared_from_this())
+				mw->hRight = this->shared_from_this();
 			else
 				return;
 		}
@@ -301,7 +302,7 @@ const CArtifactInstance * CTradeWindow::CTradeableItem::getArtInstance() const
 	{
 	case ARTIFACT_PLACEHOLDER:
 	case ARTIFACT_INSTANCE:
-		return (const CArtifactInstance *)hlp;
+		return hlp;
 	default:
 		return nullptr;
 	}
@@ -321,15 +322,10 @@ CTradeWindow::CTradeWindow(std::string bgName, const IMarket *Market, const CGHe
 	CWindowObject(PLAYER_COLORED, bgName),
 	market(Market),
 	hero(Hero),
-	arts(nullptr),
-	hLeft(nullptr),
-	hRight(nullptr),
-	ok(nullptr),
-	max(nullptr),
-	deal(nullptr),
-	slider(nullptr),
 	readyToTrade(false)
 {
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
 	type |= BLOCK_ADV_HOTKEYS;
 	mode = Mode;
 	initTypes();
@@ -372,6 +368,8 @@ void CTradeWindow::initTypes()
 
 void CTradeWindow::initItems(bool Left)
 {
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+
 	if(Left && (itemsType[1] == ARTIFACT_TYPE || itemsType[1] == ARTIFACT_INSTANCE))
 	{
 		int xOffset = 0, yOffset = 0;
@@ -380,9 +378,9 @@ void CTradeWindow::initItems(bool Left)
 			xOffset = -361;
 			yOffset = +46;
 
-			auto  hlp = new CTradeableItem(Point(137, 469), itemsType[Left], -1, 1, 0);
-			hlp->recActions &= ~(UPDATE | SHOWALL);
-			items[Left].push_back(hlp);
+			auto item = std::make_shared<CTradeableItem>(Point(137, 469), itemsType[Left], -1, 1, 0);
+			item->recActions &= ~(UPDATE | SHOWALL);
+			items[Left].push_back(item);
 		}
 		else //ARTIFACT_EXP
 		{
@@ -390,47 +388,44 @@ void CTradeWindow::initItems(bool Left)
 			yOffset = -12;
 		}
 
-		BLOCK_CAPTURING;
-		arts = new CArtifactsOfHero(Point(pos.x+xOffset, pos.y+yOffset));
-		arts->commonInfo = std::make_shared<CArtifactsOfHero::SCommonPart>();
-		arts->commonInfo->participants.insert(arts);
-		arts->recActions = 255;
+		arts = std::make_shared<CArtifactsOfHero>(Point(xOffset, yOffset), true);
+		arts->recActions = 255-DISPOSE;
 		arts->setHero(hero);
 		arts->allowedAssembling = false;
-		addChild(arts);
-		artSets.push_back(arts);
+		addSet(arts);
 
 		if(mode == EMarketMode::ARTIFACT_RESOURCE)
 			arts->highlightModeCallback = std::bind(&CTradeWindow::artifactSelected, this, _1);
-		return;
 	}
+	else
+	{
+		std::vector<int> *ids = getItemsIds(Left);
+		std::vector<Rect> pos;
+		int amount = -1;
 
-	std::vector<int> *ids = getItemsIds(Left);
-	std::vector<Rect> pos;
-	int amount = -1;
-
-	getPositionsFor(pos, Left, itemsType[Left]);
+		getPositionsFor(pos, Left, itemsType[Left]);
 
-	if(Left || !ids)
-		amount = 7;
-	else
-		amount = ids->size();
+		if(Left || !ids)
+			amount = 7;
+		else
+			amount = ids->size();
 
-	if(ids)
-		vstd::amin(amount, ids->size());
+		if(ids)
+			vstd::amin(amount, ids->size());
 
-	for(int j=0; j<amount; j++)
-	{
-		int id = (ids && ids->size()>j) ? (*ids)[j] : j;
-		if(id < 0 && mode != EMarketMode::ARTIFACT_EXP)  //when sacrificing artifacts we need to prepare empty slots
-			continue;
+		for(int j=0; j<amount; j++)
+		{
+			int id = (ids && ids->size()>j) ? (*ids)[j] : j;
+			if(id < 0 && mode != EMarketMode::ARTIFACT_EXP)  //when sacrificing artifacts we need to prepare empty slots
+				continue;
 
-		auto  hlp = new CTradeableItem(pos[j].topLeft(), itemsType[Left], id, Left, j);
-		hlp->pos = pos[j] + this->pos.topLeft();
-		items[Left].push_back(hlp);
+			auto item = std::make_shared<CTradeableItem>(pos[j].topLeft(), itemsType[Left], id, Left, j);
+			item->pos = pos[j] + this->pos.topLeft();
+			items[Left].push_back(item);
+		}
+		vstd::clear_pointer(ids);
+		initSubs(Left);
 	}
-	vstd::clear_pointer(ids);
-	initSubs(Left);
 }
 
 std::vector<int> *CTradeWindow::getItemsIds(bool Left)
@@ -523,17 +518,17 @@ void CTradeWindow::getPositionsFor(std::vector<Rect> &poss, bool Left, EType typ
 
 void CTradeWindow::initSubs(bool Left)
 {
-	for(CTradeableItem *t : items[Left])
+	for(auto item : items[Left])
 	{
 		if(Left)
 		{
 			switch(itemsType[1])
 			{
 			case CREATURE:
-				t->subtitle = boost::lexical_cast<std::string>(hero->getStackCount(SlotID(t->serial)));
+				item->subtitle = boost::lexical_cast<std::string>(hero->getStackCount(SlotID(item->serial)));
 				break;
 			case RESOURCE:
-				t->subtitle = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(t->serial)));
+				item->subtitle = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(item->serial)));
 				break;
 			}
 		}
@@ -541,25 +536,25 @@ void CTradeWindow::initSubs(bool Left)
 		{
 			if(itemsType[0] == PLAYER)
 			{
-				t->subtitle = CGI->generaltexth->capColors[t->id];
+				item->subtitle = CGI->generaltexth->capColors[item->id];
 			}
 			else if(hLeft)//artifact, creature
 			{
 				int h1, h2; //hlp variables for getting offer
-				market->getOffer(hLeft->id, t->id, h1, h2, mode);
-				if(t->id != hLeft->id || mode != EMarketMode::RESOURCE_RESOURCE) //don't allow exchanging same resources
+				market->getOffer(hLeft->id, item->id, h1, h2, mode);
+				if(item->id != hLeft->id || mode != EMarketMode::RESOURCE_RESOURCE) //don't allow exchanging same resources
 				{
 					std::ostringstream oss;
 					oss << h2;
 					if(h1!=1)
 						oss << "/" << h1;
-					t->subtitle = oss.str();
+					item->subtitle = oss.str();
 				}
 				else
-					t->subtitle = CGI->generaltexth->allTexts[164]; // n/a
+					item->subtitle = CGI->generaltexth->allTexts[164]; // n/a
 			}
 			else
-				t->subtitle = "";
+				item->subtitle = "";
 		}
 	}
 }
@@ -569,9 +564,9 @@ void CTradeWindow::showAll(SDL_Surface * to)
 	CWindowObject::showAll(to);
 
 	if(hRight)
-		CSDL_Ext::drawBorder(to,hRight->pos.x-1,hRight->pos.y-1,hRight->pos.w+2,hRight->pos.h+2,int3(255,231,148));
+		CSDL_Ext::drawBorder(to, hRight->pos.x-1, hRight->pos.y-1, hRight->pos.w+2, hRight->pos.h+2, int3(255,231,148));
 	if(hLeft && hLeft->type != ARTIFACT_INSTANCE)
-		CSDL_Ext::drawBorder(to,hLeft->pos.x-1,hLeft->pos.y-1,hLeft->pos.w+2,hLeft->pos.h+2,int3(255,231,148));
+		CSDL_Ext::drawBorder(to, hLeft->pos.x-1, hLeft->pos.y-1, hLeft->pos.w+2, hLeft->pos.h+2, int3(255,231,148));
 
 	if(readyToTrade)
 	{
@@ -582,29 +577,28 @@ void CTradeWindow::showAll(SDL_Surface * to)
 	}
 }
 
-void CTradeWindow::removeItems(const std::set<CTradeableItem *> &toRemove)
+void CTradeWindow::removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove)
 {
-	for(CTradeableItem *t : toRemove)
-		removeItem(t);
+	for(auto item : toRemove)
+		removeItem(item);
 }
 
-void CTradeWindow::removeItem(CTradeableItem * t)
+void CTradeWindow::removeItem(std::shared_ptr<CTradeableItem> item)
 {
-	items[t->left] -= t;
-	delete t;
+	items[item->left] -= item;
 
-	if(hRight == t)
+	if(hRight == item)
 	{
-		hRight = nullptr;
+		hRight.reset();
 		selectionChanged(false);
 	}
 }
 
-void CTradeWindow::getEmptySlots(std::set<CTradeableItem *> &toRemove)
+void CTradeWindow::getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove)
 {
-	for(CTradeableItem *t : items[1])
-		if(!hero->getStackCount(SlotID(t->serial)))
-			toRemove.insert(t);
+	for(auto item : items[1])
+		if(!hero->getStackCount(SlotID(item->serial)))
+			toRemove.insert(item);
 }
 
 void CTradeWindow::setMode(EMarketMode::EMarketMode Mode)
@@ -660,35 +654,36 @@ std::string CMarketplaceWindow::getBackgroundForMode(EMarketMode::EMarketMode mo
 	return "";
 }
 
-CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode)
+CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode)
 	: CTradeWindow(getBackgroundForMode(Mode), Market, Hero, Mode)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
 	madeTransaction = false;
 	bool sliderNeeded = true;
 
-	new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
+	statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
 
 	std::string title;
 
-	if (market->o->ID == Obj::TOWN)
+	if(market->o->ID == Obj::TOWN)
 	{
 		switch (mode)
 		{
-		break; case EMarketMode::CREATURE_RESOURCE:
+		case EMarketMode::CREATURE_RESOURCE:
 			title = CGI->townh->factions[ETownType::STRONGHOLD]->town->buildings[BuildingID::FREELANCERS_GUILD]->Name();
-
-		break; case EMarketMode::RESOURCE_ARTIFACT:
+			break;
+		case EMarketMode::RESOURCE_ARTIFACT:
 			title = CGI->townh->factions[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name();
 			sliderNeeded = false;
-
-		break; case EMarketMode::ARTIFACT_RESOURCE:
+			break;
+		case EMarketMode::ARTIFACT_RESOURCE:
 			title = CGI->townh->factions[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name();
 			sliderNeeded = false;
-
-		break; default:
+			break;
+		default:
 			title = CGI->generaltexth->allTexts[158];
+			break;
 		}
 	}
 	else
@@ -707,55 +702,51 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan
 			break;
 		default:
 			title = market->o->getObjectName();
+			break;
 		}
 	}
 
-	new CLabel(300, 27, FONT_BIG, CENTER, Colors::YELLOW, title);
+	titleLabel = std::make_shared<CLabel>(300, 27, FONT_BIG, CENTER, Colors::YELLOW, title);
 
 	initItems(false);
 	initItems(true);
 
-	ok = new CButton(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&](){ close(); }, SDLK_RETURN);
+	ok = std::make_shared<CButton>(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&](){ close(); }, SDLK_RETURN);
 	ok->assignedKeys.insert(SDLK_ESCAPE);
-	deal = new CButton(Point(307, 520), "TPMRKB.DEF", CGI->generaltexth->zelp[595], [&](){ makeDeal(); } );
+	deal = std::make_shared<CButton>(Point(307, 520), "TPMRKB.DEF", CGI->generaltexth->zelp[595], [&](){ makeDeal(); } );
 	deal->block(true);
 
 	if(sliderNeeded)
 	{
-		slider = new CSlider(Point(231, 490),137, std::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0);
-		max = new CButton(Point(229, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[596], [&](){ setMax(); });
+		slider = std::make_shared<CSlider>(Point(231, 490),137, std::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0);
+		max = std::make_shared<CButton>(Point(229, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[596], [&](){ setMax(); });
 		max->block(true);
 	}
 	else
 	{
-		slider = nullptr;
-		max = nullptr;
 		deal->moveBy(Point(-30, 0));
 	}
 
-	Rect traderTextRect;
-
 	//left side
 	switch(Mode)
 	{
 	case EMarketMode::RESOURCE_RESOURCE:
 	case EMarketMode::RESOURCE_PLAYER:
 	case EMarketMode::RESOURCE_ARTIFACT:
-		new CLabel(154, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[270]);
+		labels.push_back(std::make_shared<CLabel>(154, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[270]));
 		break;
-
 	case EMarketMode::CREATURE_RESOURCE:
 		//%s's Creatures
-		new CLabel(152, 102, FONT_SMALL, CENTER, Colors::WHITE,
-		           boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name));
+		labels.push_back(std::make_shared<CLabel>(152, 102, FONT_SMALL, CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name)));
 		break;
 	case EMarketMode::ARTIFACT_RESOURCE:
 		//%s's Artifacts
-		new CLabel(152, 56, FONT_SMALL, CENTER, Colors::WHITE,
-		           boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->name));
+		labels.push_back(std::make_shared<CLabel>(152, 56, FONT_SMALL, CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->name)));
 		break;
 	}
 
+	Rect traderTextRect;
+
 	//right side
 	switch(Mode)
 	{
@@ -763,45 +754,33 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan
 	case EMarketMode::CREATURE_RESOURCE:
 	case EMarketMode::RESOURCE_ARTIFACT:
 	case EMarketMode::ARTIFACT_RESOURCE:
-		new CLabel(445, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[168]);
+		labels.push_back(std::make_shared<CLabel>(445, 148, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[168]));
 		traderTextRect = Rect(316, 48, 260, 75);
 		break;
 	case EMarketMode::RESOURCE_PLAYER:
-		new CLabel(445, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[169]);
+		labels.push_back(std::make_shared<CLabel>(445, 55, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[169]));
 		traderTextRect = Rect(28, 48, 260, 75);
 		break;
 	}
 
-	traderText = new CTextBox("", traderTextRect, 0, FONT_SMALL, CENTER);
+	traderText = std::make_shared<CTextBox>("", traderTextRect, 0, FONT_SMALL, CENTER);
 	int specialOffset = mode == EMarketMode::ARTIFACT_RESOURCE ? 35 : 0; //in selling artifacts mode we need to move res-res and art-res buttons down
 
 	if(printButtonFor(EMarketMode::RESOURCE_PLAYER))
-		new CButton(Point(18, 520),"TPMRKBU1.DEF", CGI->generaltexth->zelp[612], [&](){ setMode(EMarketMode::RESOURCE_PLAYER);});
+		buttons.push_back(std::make_shared<CButton>(Point(18, 520),"TPMRKBU1.DEF", CGI->generaltexth->zelp[612], [&](){ setMode(EMarketMode::RESOURCE_PLAYER);}));
 	if(printButtonFor(EMarketMode::RESOURCE_RESOURCE))
-		new CButton(Point(516, 450 + specialOffset),"TPMRKBU5.DEF", CGI->generaltexth->zelp[605], [&](){ setMode(EMarketMode::RESOURCE_RESOURCE);});
+		buttons.push_back(std::make_shared<CButton>(Point(516, 450 + specialOffset),"TPMRKBU5.DEF", CGI->generaltexth->zelp[605], [&](){ setMode(EMarketMode::RESOURCE_RESOURCE);}));
 	if(printButtonFor(EMarketMode::CREATURE_RESOURCE))
-		new CButton(Point(516, 485),"TPMRKBU4.DEF", CGI->generaltexth->zelp[599], [&](){ setMode(EMarketMode::CREATURE_RESOURCE);});
+		buttons.push_back(std::make_shared<CButton>(Point(516, 485),"TPMRKBU4.DEF", CGI->generaltexth->zelp[599], [&](){ setMode(EMarketMode::CREATURE_RESOURCE);}));
 	if(printButtonFor(EMarketMode::RESOURCE_ARTIFACT))
-		new CButton(Point(18, 450 + specialOffset),"TPMRKBU2.DEF", CGI->generaltexth->zelp[598], [&](){ setMode(EMarketMode::RESOURCE_ARTIFACT);});
+		buttons.push_back(std::make_shared<CButton>(Point(18, 450 + specialOffset),"TPMRKBU2.DEF", CGI->generaltexth->zelp[598], [&](){ setMode(EMarketMode::RESOURCE_ARTIFACT);}));
 	if(printButtonFor(EMarketMode::ARTIFACT_RESOURCE))
-		new CButton(Point(18, 485),"TPMRKBU3.DEF", CGI->generaltexth->zelp[613], [&](){ setMode(EMarketMode::ARTIFACT_RESOURCE);});
+		buttons.push_back(std::make_shared<CButton>(Point(18, 485),"TPMRKBU3.DEF", CGI->generaltexth->zelp[613], [&](){ setMode(EMarketMode::ARTIFACT_RESOURCE);}));
 
 	updateTraderText();
 }
 
-CMarketplaceWindow::~CMarketplaceWindow()
-{
-	hLeft = hRight = nullptr;
-	for(auto & elem : items[1])
-		delete elem;
-	for(auto & elem : items[0])
-		delete elem;
-
-	items[1].clear();
-	items[0].clear();
-}
-
-
+CMarketplaceWindow::~CMarketplaceWindow() = default;
 
 void CMarketplaceWindow::setMax()
 {
@@ -918,10 +897,8 @@ void CMarketplaceWindow::garrisonChanged()
 	if(mode != EMarketMode::CREATURE_RESOURCE)
 		return;
 
-	std::set<CTradeableItem *> toRemove;
+	std::set<std::shared_ptr<CTradeableItem>> toRemove;
 	getEmptySlots(toRemove);
-
-
 	removeItems(toRemove);
 	initSubs(true);
 }
@@ -933,10 +910,10 @@ void CMarketplaceWindow::artifactsChanged(bool Left)
 		return;
 
 	std::vector<int> available = market->availableItemsIds(mode);
-	std::set<CTradeableItem *> toRemove;
-	for(CTradeableItem *t : items[0])
-		if(!vstd::contains(available, t->id))
-			toRemove.insert(t);
+	std::set<std::shared_ptr<CTradeableItem>> toRemove;
+	for(auto item : items[0])
+		if(!vstd::contains(available, item->id))
+			toRemove.insert(item);
 
 	removeItems(toRemove);
 	redraw();
@@ -1113,93 +1090,88 @@ void CMarketplaceWindow::updateTraderText()
 }
 
 CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode)
-	:CTradeWindow((Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, Mode)
+	: CTradeWindow((Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, Mode)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+
 	if(Mode == EMarketMode::CREATURE_EXP)
 	{
 		//%s's Creatures
-		new CLabel(155, 30, FONT_SMALL, CENTER, Colors::YELLOW,
-		           boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name));
+		labels.push_back(std::make_shared<CLabel>(155, 30, FONT_SMALL, CENTER, Colors::YELLOW,
+		           boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->name)));
 
 		//Altar of Sacrifice
-		new CLabel(450, 30, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479]);
+		labels.push_back(std::make_shared<CLabel>(450, 30, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479]));
 
 		 //To sacrifice creatures, move them from your army on to the Altar and click Sacrifice
 		new CTextBox(CGI->generaltexth->allTexts[480], Rect(320, 56, 256, 40), 0, FONT_SMALL, CENTER, Colors::YELLOW);
 
-		slider = new CSlider(Point(231,481),137,std::bind(&CAltarWindow::sliderMoved,this,_1),0,0);
-		max = new CButton(Point(147, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[578], std::bind(&CSlider::moveToMax, slider));
+		slider = std::make_shared<CSlider>(Point(231,481),137,std::bind(&CAltarWindow::sliderMoved,this,_1),0,0);
+		max = std::make_shared<CButton>(Point(147, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[578], std::bind(&CSlider::moveToMax, slider));
 
 		sacrificedUnits.resize(GameConstants::ARMY_SIZE, 0);
-		sacrificeAll = new CButton(Point(393, 520), "ALTARMY.DEF", CGI->generaltexth->zelp[579], std::bind(&CAltarWindow::SacrificeAll,this));
-		sacrificeBackpack = nullptr;
+		sacrificeAll = std::make_shared<CButton>(Point(393, 520), "ALTARMY.DEF", CGI->generaltexth->zelp[579], std::bind(&CAltarWindow::SacrificeAll,this));
 
 		initItems(true);
 		mimicCres();
-		artIcon = nullptr;
 	}
 	else
 	{
 		//Sacrifice artifacts for experience
-		new CLabel(450, 34, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]);
+		labels.push_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]));
 		//%s's Creatures
-		new CLabel(302, 423, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]);
+		labels.push_back(std::make_shared<CLabel>(302, 423, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]));
 
-		sacrificeAll = new CButton(Point(393, 520), "ALTFILL.DEF", CGI->generaltexth->zelp[571], std::bind(&CAltarWindow::SacrificeAll,this));
+		sacrificeAll = std::make_shared<CButton>(Point(393, 520), "ALTFILL.DEF", CGI->generaltexth->zelp[571], std::bind(&CAltarWindow::SacrificeAll,this));
 		sacrificeAll->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty());
-		sacrificeBackpack = new CButton(Point(147, 520), "ALTEMBK.DEF", CGI->generaltexth->zelp[570], std::bind(&CAltarWindow::SacrificeBackpack,this));
+		sacrificeBackpack = std::make_shared<CButton>(Point(147, 520), "ALTEMBK.DEF", CGI->generaltexth->zelp[570], std::bind(&CAltarWindow::SacrificeBackpack,this));
 		sacrificeBackpack->block(hero->artifactsInBackpack.empty());
 
-		slider = nullptr;
-		max = nullptr;
-
 		initItems(true);
 		initItems(false);
-		artIcon = new CAnimImage("ARTIFACT", 0, 0, 281, 442);
+		artIcon = std::make_shared<CAnimImage>("ARTIFACT", 0, 0, 281, 442);
 		artIcon->disable();
 	}
 
 	//Experience needed to reach next level
-	new CTextBox(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, CENTER, Colors::YELLOW);
+	texts.push_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, CENTER, Colors::YELLOW));
 	//Total experience on the Altar
-	new CTextBox(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, CENTER, Colors::YELLOW);
+	texts.push_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, CENTER, Colors::YELLOW));
 
-	new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
+	statusBar = std::make_shared<CGStatusBar>(std::make_shared<CPicture>(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
 
-	ok = new CButton(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&](){ close();}, SDLK_RETURN);
+	ok = std::make_shared<CButton>(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&](){ close();}, SDLK_RETURN);
 	ok->assignedKeys.insert(SDLK_ESCAPE);
 
-	deal = new CButton(Point(269, 520), "ALTSACR.DEF", CGI->generaltexth->zelp[585], std::bind(&CAltarWindow::makeDeal,this));
+	deal = std::make_shared<CButton>(Point(269, 520), "ALTSACR.DEF", CGI->generaltexth->zelp[585], std::bind(&CAltarWindow::makeDeal,this));
 
 	if(Mode == EMarketMode::CREATURE_EXP)
 	{
-		CButton *changeMode = new CButton(Point(516, 421), "ALTART.DEF", CGI->generaltexth->zelp[580], std::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP));
-		if (Hero->getAlignment() == ::EAlignment::EVIL)
+		auto changeMode = std::make_shared<CButton>(Point(516, 421), "ALTART.DEF", CGI->generaltexth->zelp[580], std::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP));
+		if(Hero->getAlignment() == ::EAlignment::EVIL)
 			changeMode->block(true);
+		buttons.push_back(changeMode);
 	}
-	if(Mode == EMarketMode::ARTIFACT_EXP)
+	else if(Mode == EMarketMode::ARTIFACT_EXP)
 	{
-		CButton *changeMode = new CButton(Point(516, 421), "ALTSACC.DEF", CGI->generaltexth->zelp[572], std::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP));
-		if (Hero->getAlignment() == ::EAlignment::GOOD)
+		auto changeMode = std::make_shared<CButton>(Point(516, 421), "ALTSACC.DEF", CGI->generaltexth->zelp[572], std::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP));
+		if(Hero->getAlignment() == ::EAlignment::GOOD)
 			changeMode->block(true);
+		buttons.push_back(changeMode);
 	}
 
 	expPerUnit.resize(GameConstants::ARMY_SIZE, 0);
 	getExpValues();
 
-	expToLevel = new CLabel(73, 475, FONT_SMALL, CENTER);
-	expOnAltar = new CLabel(73, 543, FONT_SMALL, CENTER);
+	expToLevel = std::make_shared<CLabel>(73, 475, FONT_SMALL, CENTER);
+	expOnAltar = std::make_shared<CLabel>(73, 543, FONT_SMALL, CENTER);
 
 	setExpToLevel();
 	calcTotalExp();
 	blockTrade();
 }
 
-CAltarWindow::~CAltarWindow()
-{
-
-}
+CAltarWindow::~CAltarWindow() = default;
 
 void CAltarWindow::getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const
 {
@@ -1248,10 +1220,10 @@ void CAltarWindow::makeDeal()
 		for(int& val : sacrificedUnits)
 			val = 0;
 
-		for(CTradeableItem *t : items[0])
+		for(auto item : items[0])
 		{
-			t->setType(CREATURE_PLACEHOLDER);
-			t->subtitle = "";
+			item->setType(CREATURE_PLACEHOLDER);
+			item->subtitle = "";
 		}
 	}
 	else
@@ -1265,10 +1237,10 @@ void CAltarWindow::makeDeal()
 		LOCPLINT->cb->trade(market->o, mode, positions, {}, {}, hero);
 		arts->artifactsOnAltar.clear();
 
-		for(CTradeableItem *t : items[0])
+		for(auto item : items[0])
 		{
-			t->setID(-1);
-			t->subtitle = "";
+			item->setID(-1);
+			item->subtitle = "";
 		}
 
 		arts->commonInfo->reset();
@@ -1284,15 +1256,15 @@ void CAltarWindow::SacrificeAll()
 	if(mode == EMarketMode::CREATURE_EXP)
 	{
 		bool movedAnything = false;
-		for(CTradeableItem *t : items[1])
-			sacrificedUnits[t->serial] = hero->getStackCount(SlotID(t->serial));
+		for(auto item : items[1])
+			sacrificedUnits[item->serial] = hero->getStackCount(SlotID(item->serial));
 
 		sacrificedUnits[items[1].front()->serial]--;
 
-		for(CTradeableItem *t : items[0])
+		for(auto item : items[0])
 		{
-			updateRight(t);
-			if(t->type == CREATURE)
+			updateRight(item);
+			if(item->type == CREATURE)
 				movedAnything = true;
 		}
 
@@ -1350,13 +1322,14 @@ void CAltarWindow::selectOppositeItem(bool side)
 
 void CAltarWindow::mimicCres()
 {
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 	std::vector<Rect> positions;
 	getPositionsFor(positions, false, CREATURE);
 
-	for(CTradeableItem *t : items[1])
+	for(auto item : items[1])
 	{
-		auto  hlp = new CTradeableItem(positions[t->serial].topLeft(), CREATURE_PLACEHOLDER, t->id, false, t->serial);
-		hlp->pos = positions[t->serial] + this->pos.topLeft();
+		auto hlp = std::make_shared<CTradeableItem>(positions[item->serial].topLeft(), CREATURE_PLACEHOLDER, item->id, false, item->serial);
+		hlp->pos = positions[item->serial] + this->pos.topLeft();
 		items[0].push_back(hlp);
 	}
 }
@@ -1389,7 +1362,7 @@ void CAltarWindow::garrisonChanged()
 	if(mode != EMarketMode::CREATURE_EXP)
 		return;
 
-	std::set<CTradeableItem *> empty;
+	std::set<std::shared_ptr<CTradeableItem>> empty;
 	getEmptySlots(empty);
 
 	removeItems(empty);
@@ -1401,9 +1374,11 @@ void CAltarWindow::garrisonChanged()
 void CAltarWindow::getExpValues()
 {
 	int dump;
-	for(CTradeableItem *t : items[1])
-		if(t->id >= 0)
-			market->getOffer(t->id, 0, dump, expPerUnit[t->serial], EMarketMode::CREATURE_EXP);
+	for(auto item : items[1])
+	{
+		if(item->id >= 0)
+			market->getOffer(item->id, 0, dump, expPerUnit[item->serial], EMarketMode::CREATURE_EXP);
+	}
 }
 
 void CAltarWindow::calcTotalExp()
@@ -1446,7 +1421,7 @@ void CAltarWindow::blockTrade()
 	deal->block(true);
 }
 
-void CAltarWindow::updateRight(CTradeableItem *toUpdate)
+void CAltarWindow::updateRight(std::shared_ptr<CTradeableItem> toUpdate)
 {
 	int val = sacrificedUnits[toUpdate->serial];
 	toUpdate->setType(val ? CREATURE : CREATURE_PLACEHOLDER);
@@ -1500,7 +1475,7 @@ void CAltarWindow::showAll(SDL_Surface * to)
 	}
 }
 
-bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art)
+bool CAltarWindow::putOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance *art)
 {
 	if(!art->artType->isTradable()) //special art
 	{
@@ -1531,13 +1506,13 @@ bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance
 	return true;
 }
 
-void CAltarWindow::moveFromSlotToAltar(ArtifactPosition slotID, CTradeableItem* altarSlot, const CArtifactInstance *art)
+void CAltarWindow::moveFromSlotToAltar(ArtifactPosition slotID, std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance *art)
 {
 	auto freeBackpackSlot = ArtifactPosition(hero->artifactsInBackpack.size() + GameConstants::BACKPACK_START);
 	if(arts->commonInfo->src.art)
 	{
 		arts->commonInfo->dst.slotID = freeBackpackSlot;
-		arts->commonInfo->dst.AOH = arts;
+		arts->commonInfo->dst.AOH = arts.get();
 	}
 
 	if(putOnAltar(altarSlot, art))

+ 49 - 35
client/windows/CTradeWindow.h

@@ -16,6 +16,7 @@
 class IMarket;
 class CSlider;
 class CTextBox;
+class CGStatusBar;
 
 class CTradeWindow : public CWindowObject, public CWindowWithArtifacts //base for markets and altar of sacrifice
 {
@@ -24,14 +25,14 @@ public:
 	{
 		RESOURCE, PLAYER, ARTIFACT_TYPE, CREATURE, CREATURE_PLACEHOLDER, ARTIFACT_PLACEHOLDER, ARTIFACT_INSTANCE
 	};
-	class CTradeableItem : public CIntObject
-	{
-		CAnimImage * image;
 
+	class CTradeableItem : public CIntObject, public std::enable_shared_from_this<CTradeableItem>
+	{
+		std::shared_ptr<CAnimImage> image;
 		std::string getFilename();
 		int getIndex();
 	public:
-		const CArtifactInstance *hlp; //holds ptr to artifact instance id type artifact
+		const CArtifactInstance * hlp; //holds ptr to artifact instance id type artifact
 		EType type;
 		int id;
 		const int serial;
@@ -41,37 +42,43 @@ public:
 		void setType(EType newType);
 		void setID(int newID);
 
-		const CArtifactInstance *getArtInstance() const;
-		void setArtInstance(const CArtifactInstance *art);
+		const CArtifactInstance * getArtInstance() const;
+		void setArtInstance(const CArtifactInstance * art);
 
 		CFunctionList<void()> callback;
 		bool downSelection;
 
-		void showAllAt(const Point &dstPos, const std::string &customSub, SDL_Surface * to);
+		void showAllAt(const Point & dstPos, const std::string & customSub, SDL_Surface * to);
 
 		void clickRight(tribool down, bool previousState) override;
-		void hover (bool on) override;
+		void hover(bool on) override;
 		void showAll(SDL_Surface * to) override;
 		void clickLeft(tribool down, bool previousState) override;
 		std::string getName(int number = -1) const;
 		CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial);
 	};
 
-	const IMarket *market;
-	const CGHeroInstance *hero;
+	const IMarket * market;
+	const CGHeroInstance * hero;
 
-	CArtifactsOfHero *arts;
+	std::shared_ptr<CArtifactsOfHero> arts;
 	//all indexes: 1 = left, 0 = right
-	std::vector<CTradeableItem*> items[2];
-	CTradeableItem *hLeft, *hRight; //highlighted items (nullptr if no highlight)
+	std::array<std::vector<std::shared_ptr<CTradeableItem>>, 2> items;
+
+	//highlighted items (nullptr if no highlight)
+	std::shared_ptr<CTradeableItem> hLeft;
+	std::shared_ptr<CTradeableItem> hRight;
 	EType itemsType[2];
 
-	EMarketMode::EMarketMode mode;//0 - res<->res; 1 - res<->plauer; 2 - buy artifact; 3 - sell artifact
-	CButton *ok, *max, *deal;
-	CSlider *slider; //for choosing amount to be exchanged
+	EMarketMode::EMarketMode mode;
+	std::shared_ptr<CButton> ok;
+	std::shared_ptr<CButton> max;
+	std::shared_ptr<CButton> deal;
+
+	std::shared_ptr<CSlider> slider; //for choosing amount to be exchanged
 	bool readyToTrade;
 
-	CTradeWindow(std::string bgName, const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode); //c
+	CTradeWindow(std::string bgName, const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode); //c
 
 	void showAll(SDL_Surface * to) override;
 
@@ -80,9 +87,9 @@ public:
 	void initItems(bool Left);
 	std::vector<int> *getItemsIds(bool Left); //nullptr if default
 	void getPositionsFor(std::vector<Rect> &poss, bool Left, EType type) const;
-	void removeItems(const std::set<CTradeableItem *> &toRemove);
-	void removeItem(CTradeableItem * t);
-	void getEmptySlots(std::set<CTradeableItem *> &toRemove);
+	void removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove);
+	void removeItem(std::shared_ptr<CTradeableItem> item);
+	void getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove);
 	void setMode(EMarketMode::EMarketMode Mode); //mode setter
 
 	void artifactSelected(CHeroArtPlace *slot); //used when selling artifacts -> called when user clicked on artifact slot
@@ -93,29 +100,35 @@ public:
 	virtual std::string selectionSubtitle(bool Left) const = 0;
 	virtual void garrisonChanged() = 0;
 	virtual void artifactsChanged(bool left) = 0;
+protected:
+	std::shared_ptr<CGStatusBar> statusBar;
+	std::vector<std::shared_ptr<CLabel>> labels;
+	std::vector<std::shared_ptr<CButton>> buttons;
+	std::vector<std::shared_ptr<CTextBox>> texts;
 };
 
 class CMarketplaceWindow : public CTradeWindow
 {
+	std::shared_ptr<CLabel> titleLabel;
+
 	bool printButtonFor(EMarketMode::EMarketMode M) const;
 
 	std::string getBackgroundForMode(EMarketMode::EMarketMode mode);
 public:
 	int r1, r2; //suggested amounts of traded resources
 	bool madeTransaction; //if player made at least one transaction
-	CTextBox *traderText;
+	std::shared_ptr<CTextBox> traderText;
 
 	void setMax();
 	void sliderMoved(int to);
 	void makeDeal();
 	void selectionChanged(bool side) override; //true == left
-	CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero = nullptr, EMarketMode::EMarketMode Mode = EMarketMode::RESOURCE_RESOURCE);
+	CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero = nullptr, EMarketMode::EMarketMode Mode = EMarketMode::RESOURCE_RESOURCE);
 	~CMarketplaceWindow();
 
 	Point selectionOffset(bool Left) const override;
 	std::string selectionSubtitle(bool Left) const override;
 
-
 	void garrisonChanged() override; //removes creatures with count 0 from the list (apparently whole stack has been sold)
 	void artifactsChanged(bool left) override;
 	void resourceChanged();
@@ -126,19 +139,20 @@ public:
 
 class CAltarWindow : public CTradeWindow
 {
-	CAnimImage * artIcon;
+	std::shared_ptr<CAnimImage> artIcon;
 public:
-	CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode);
+	std::vector<int> sacrificedUnits; //[slot_nr] -> how many creatures from that slot will be sacrificed
+	std::vector<int> expPerUnit;
 
-	void getExpValues();
-	~CAltarWindow();
-
-	std::vector<int> sacrificedUnits, //[slot_nr] -> how many creatures from that slot will be sacrificed
-		expPerUnit;
+	std::shared_ptr<CButton> sacrificeAll;
+	std::shared_ptr<CButton> sacrificeBackpack;
+	std::shared_ptr<CLabel> expToLevel;
+	std::shared_ptr<CLabel> expOnAltar;
 
-	CButton *sacrificeAll, *sacrificeBackpack;
-	CLabel *expToLevel, *expOnAltar;
+	CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode);
+	~CAltarWindow();
 
+	void getExpValues();
 
 	void selectionChanged(bool side) override; //true == left
 	void selectOppositeItem(bool side);
@@ -146,7 +160,7 @@ public:
 	void SacrificeBackpack();
 
 	void putOnAltar(int backpackIndex);
-	bool putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art);
+	bool putOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art);
 	void makeDeal();
 	void showAll(SDL_Surface * to) override;
 
@@ -161,9 +175,9 @@ public:
 	void artifactsChanged(bool left) override;
 	void calcTotalExp();
 	void setExpToLevel();
-	void updateRight(CTradeableItem *toUpdate);
+	void updateRight(std::shared_ptr<CTradeableItem> toUpdate);
 
 	void artifactPicked();
 	int firstFreeSlot();
-	void moveFromSlotToAltar(ArtifactPosition slotID, CTradeableItem* altarSlot, const CArtifactInstance *art);
+	void moveFromSlotToAltar(ArtifactPosition slotID, std::shared_ptr<CTradeableItem>, const CArtifactInstance * art);
 };

+ 39 - 34
client/windows/CWindowObject.cpp

@@ -34,13 +34,15 @@
 #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
 
 CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
-    CIntObject(getUsedEvents(options_), Point()),
-    shadow(nullptr),
-    options(options_),
-    background(createBg(imageName, options & PLAYER_COLORED))
+	CIntObject(getUsedEvents(options_), Point()),
+	shadow(nullptr),
+	options(options_),
+	background(createBg(imageName, options & PLAYER_COLORED))
 {
 	assert(parent == nullptr); //Safe to remove, but windows should not have parent
 
+	defActions = 255-DISPOSE;
+
 	if (options & RCLICK_POPUP)
 		CCS->curh->hide();
 
@@ -54,51 +56,48 @@ CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt
 }
 
 CWindowObject::CWindowObject(int options_, std::string imageName):
-    CIntObject(getUsedEvents(options_), Point()),
-    shadow(nullptr),
-    options(options_),
-    background(createBg(imageName, options & PLAYER_COLORED))
+	CIntObject(getUsedEvents(options_), Point()),
+	options(options_),
+	background(createBg(imageName, options_ & PLAYER_COLORED))
 {
 	assert(parent == nullptr); //Safe to remove, but windows should not have parent
 
-	if (options & RCLICK_POPUP)
+	defActions = 255-DISPOSE;
+
+	if(options & RCLICK_POPUP)
 		CCS->curh->hide();
 
-	if (background)
+	if(background)
 		pos = background->center();
 	else
 		center(Point(screen->w/2, screen->h/2));
 
-	if (!(options & SHADOW_DISABLED))
+	if(!(options & SHADOW_DISABLED))
 		setShadow(true);
 }
 
-CWindowObject::~CWindowObject()
-{
-	setShadow(false);
-}
+CWindowObject::~CWindowObject() = default;
 
-CPicture * CWindowObject::createBg(std::string imageName, bool playerColored)
+std::shared_ptr<CPicture> CWindowObject::createBg(std::string imageName, bool playerColored)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 
-	if (imageName.empty())
+	if(imageName.empty())
 		return nullptr;
 
-	auto  image = new CPicture(imageName);
-	if (playerColored)
+	auto image = std::make_shared<CPicture>(imageName);
+	if(playerColored)
 		image->colorize(LOCPLINT->playerID);
 	return image;
 }
 
 void CWindowObject::setBackground(std::string filename)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
 
-	delete background;
 	background = createBg(filename, options & PLAYER_COLORED);
 
-	if (background)
+	if(background)
 		pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y));
 
 	updateShadow();
@@ -123,16 +122,16 @@ void CWindowObject::setShadow(bool on)
 	//size of shadow
 	static const int size = 8;
 
-	if (on == bool(shadow))
+	if(on == bool(shadow))
 		return;
 
-	vstd::clear_pointer(shadow);
+	shadow.reset();
 
 	//object too small to cast shadow
-	if (pos.h <= size || pos.w <= size)
+	if(pos.h <= size || pos.w <= size)
 		return;
 
-	if (on)
+	if(on)
 	{
 
 		//helper to set last row
@@ -164,7 +163,7 @@ void CWindowObject::setShadow(bool on)
 		static SDL_Surface * shadowRightTempl = nullptr;
 
 		//one-time initialization
-		if (!shadowCornerTempl)
+		if(!shadowCornerTempl)
 		{
 			//create "template" surfaces
 			shadowCornerTempl = CSDL_Ext::createSurfaceWithBpp<4>(size, size);
@@ -185,8 +184,6 @@ void CWindowObject::setShadow(bool on)
 			blitAlphaRow(shadowCornerTempl, size-1);
 		}
 
-		OBJ_CONSTRUCTION_CAPTURING_ALL;
-
 		//FIXME: do something with this points
 		Point shadowStart;
 		if (options & BORDERED)
@@ -215,10 +212,18 @@ void CWindowObject::setShadow(bool on)
 		blitAlphaRow(shadowRight, 0);
 
 		//generate "shadow" object with these 3 pieces in it
-		shadow = new CIntObject();
-		shadow->addChild(new CPicture(shadowCorner, shadowPos.x, shadowPos.y));
-		shadow->addChild(new CPicture(shadowRight,  shadowPos.x, shadowStart.y));
-		shadow->addChild(new CPicture(shadowBottom, shadowStart.x, shadowPos.y));
+		{
+			OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+			shadow = std::make_shared<CIntObject>();
+		}
+
+		{
+			OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255);
+
+			shadow->addChild(new CPicture(shadowCorner, shadowPos.x, shadowPos.y));
+			shadow->addChild(new CPicture(shadowRight, shadowPos.x, shadowStart.y));
+			shadow->addChild(new CPicture(shadowBottom, shadowStart.x, shadowPos.y));
+		}
 	}
 }
 

+ 6 - 6
client/windows/CWindowObject.h

@@ -14,26 +14,24 @@
 /// Basic class for windows
 class CWindowObject : public CIntObject
 {
-	CPicture * createBg(std::string imageName, bool playerColored);
+	std::shared_ptr<CPicture> createBg(std::string imageName, bool playerColored);
 	int getUsedEvents(int options);
 
-	CIntObject *shadow;
+	std::shared_ptr<CIntObject> shadow;
 	void setShadow(bool on);
 
 	int options;
 
 protected:
-	CPicture * background;
+	std::shared_ptr<CPicture> background;
 
 	//Simple function with call to GH.popInt
 	void close();
 	//Used only if RCLICK_POPUP was set
 	void clickRight(tribool down, bool previousState) override;
 	//To display border
-	void showAll(SDL_Surface *to) override;
-	//change or set background image
-	void setBackground(std::string filename);
 	void updateShadow();
+	void setBackground(std::string filename);
 public:
 	enum EOptions
 	{
@@ -51,4 +49,6 @@ public:
 	CWindowObject(int options, std::string imageName, Point centerAt);
 	CWindowObject(int options, std::string imageName = "");
 	~CWindowObject();
+
+	void showAll(SDL_Surface * to) override;
 };

+ 0 - 1
client/windows/CreaturePurchaseCard.cpp

@@ -75,7 +75,6 @@ void CreaturePurchaseCard::initCostBox()
 	cost->createItems(creatureOnTheCard->cost);
 }
 
-
 void CreaturePurchaseCard::sliderMoved(int to)
 {
 	updateAmountInfo(to);

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 360 - 313
client/windows/GUIClasses.cpp


+ 258 - 136
client/windows/GUIClasses.h

@@ -33,53 +33,62 @@ class CToggleButton;
 class CToggleGroup;
 class CVolumeSlider;
 class CGStatusBar;
+class CTextBox;
+class CResDataBar;
+class CHeroWithMaybePickedArtifact;
 
 /// Recruitment window where you can recruit creatures
 class CRecruitmentWindow : public CWindowObject
 {
-	class CCreatureCard : public CIntObject
+	class CCreatureCard : public CIntObject, public std::enable_shared_from_this<CCreatureCard>
 	{
 		CRecruitmentWindow * parent;
-		CCreaturePic *pic; //creature's animation
+		std::shared_ptr<CCreaturePic> animation;
 		bool selected;
 
-		void clickLeft(tribool down, bool previousState) override;
-		void clickRight(tribool down, bool previousState) override;
-		void showAll(SDL_Surface *to) override;
 	public:
 		const CCreature * creature;
 		si32 amount;
 
 		void select(bool on);
 
-		CCreatureCard(CRecruitmentWindow * window, const CCreature *crea, int totalAmount);
+		CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount);
+
+		void clickLeft(tribool down, bool previousState) override;
+		void clickRight(tribool down, bool previousState) override;
+		void showAll(SDL_Surface * to) override;
 	};
 
 	std::function<void(CreatureID,int)> onRecruit; //void (int ID, int amount) <-- call to recruit creatures
 
 	int level;
-	const CArmedInstance *dst;
-
-	CCreatureCard * selected;
-	std::vector<CCreatureCard *> cards;
-
-	CSlider *slider; //for selecting amount
-	CButton *maxButton, *buyButton, *cancelButton;
-	//labels for visible values
-	CLabel * title;
-	CLabel * availableValue;
-	CLabel * toRecruitValue;
-	CreatureCostBox * costPerTroopValue;
-	CreatureCostBox * totalCostValue;
-
-	void select(CCreatureCard * card);
+	const CArmedInstance * dst;
+
+	std::shared_ptr<CGStatusBar> statusBar;
+
+	std::shared_ptr<CCreatureCard> selected;
+	std::vector<std::shared_ptr<CCreatureCard>> cards;
+
+	std::shared_ptr<CSlider> slider;
+	std::shared_ptr<CButton> maxButton;
+	std::shared_ptr<CButton> buyButton;
+	std::shared_ptr<CButton> cancelButton;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CLabel> availableValue;
+	std::shared_ptr<CLabel> toRecruitValue;
+	std::shared_ptr<CLabel> availableTitle;
+	std::shared_ptr<CLabel> toRecruitTitle;
+	std::shared_ptr<CreatureCostBox> costPerTroopValue;
+	std::shared_ptr<CreatureCostBox> totalCostValue;
+
+	void select(std::shared_ptr<CCreatureCard> card);
 	void buy();
 	void sliderMoved(int to);
 
-	void showAll(SDL_Surface *to) override;
+	void showAll(SDL_Surface * to) override;
 public:
 	const CGDwelling * const dwelling;
-	CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const std::function<void(CreatureID,int)> & Recruit, int y_offset = 0); //creatures - pairs<creature_ID,amount> //c-tor
+	CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, int y_offset = 0);
 	void availableCreaturesChanged();
 };
 
@@ -92,12 +101,15 @@ class CSplitWindow : public CWindowObject
 
 	int leftMin;
 	int rightMin;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CSlider> slider;
+	std::shared_ptr<CCreaturePic> animLeft;
+	std::shared_ptr<CCreaturePic> animRight;
+	std::shared_ptr<CButton> ok;
+	std::shared_ptr<CButton> cancel;
+	std::shared_ptr<CTextInput> leftInput;
+	std::shared_ptr<CTextInput> rightInput;
 
-	CSlider *slider;
-	CCreaturePic *animLeft, *animRight; //creature's animation
-	CButton *ok, *cancel;
-
-	CTextInput *leftInput, *rightInput;
 	void setAmountText(std::string text, bool left);
 	void setAmount(int value, bool left);
 	void sliderMoved(int value);
@@ -110,22 +122,27 @@ public:
 	 * leftMin, rightMin - minimal amount of creatures in each stack
 	 * leftAmount, rightAmount - amount of creatures in each stack
 	 */
-	CSplitWindow(const CCreature * creature, std::function<void(int, int)> callback,
-	             int leftMin, int rightMin, int leftAmount, int rightAmount);
+	CSplitWindow(const CCreature * creature, std::function<void(int, int)> callback, int leftMin, int rightMin, int leftAmount, int rightAmount);
 };
 
-/// Raised up level windowe where you can select one out of two skills
+/// Raised up level window where you can select one out of two skills
 class CLevelWindow : public CWindowObject
 {
-	CComponentBox * box; //skills to select
+	std::shared_ptr<CAnimImage> portrait;
+	std::shared_ptr<CButton> ok;
+	std::shared_ptr<CLabel> mainTitle;
+	std::shared_ptr<CLabel> levelTitle;
+	std::shared_ptr<CAnimImage> skillIcon;
+	std::shared_ptr<CLabel> skillValue;
+
+	std::shared_ptr<CComponentBox> box; //skills to select
 	std::function<void(ui32)> cb;
 
 	void selectionChanged(unsigned to);
-public:
 
+public:
 	CLevelWindow(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, std::function<void(ui32)> callback);
 	~CLevelWindow();
-
 };
 
 /// Town portal, castle gate window
@@ -133,27 +150,29 @@ class CObjectListWindow : public CWindowObject
 {
 	class CItem : public CIntObject
 	{
-		CObjectListWindow *parent;
-		CLabel *text;
-		CPicture *border;
+		CObjectListWindow * parent;
+		std::shared_ptr<CLabel> text;
+		std::shared_ptr<CPicture> border;
 	public:
 		const size_t index;
-		CItem(CObjectListWindow *parent, size_t id, std::string text);
+		CItem(CObjectListWindow * parent, size_t id, std::string text);
 
 		void select(bool on);
 		void clickLeft(tribool down, bool previousState) override;
 	};
 
 	std::function<void(int)> onSelect;//called when OK button is pressed, returns id of selected item.
-	CLabel * title;
-	CLabel * descr;
+	std::shared_ptr<CIntObject> titleWidget;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CLabel> descr;
 
-	CListBox * list;
-	CButton *ok, *exit;
+	std::shared_ptr<CListBox> list;
+	std::shared_ptr<CButton> ok;
+	std::shared_ptr<CButton> exit;
 
 	std::vector< std::pair<int, std::string> > items;//all items present in list
 
-	void init(CIntObject * titlePic, std::string _title, std::string _descr);
+	void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr);
 	void exitPressed();
 public:
 	size_t selected;//index of currently selected item
@@ -163,13 +182,10 @@ public:
 	/// Callback will be called when OK button is pressed, returns id of selected item. initState = initially selected item
 	/// Image can be nullptr
 	///item names will be taken from map objects
-	CObjectListWindow(const std::vector<int> &_items, CIntObject * titlePic, std::string _title, std::string _descr,
-                      std::function<void(int)> Callback);
-
-	CObjectListWindow(const std::vector<std::string> &_items, CIntObject * titlePic, std::string _title, std::string _descr,
-                      std::function<void(int)> Callback);
+	CObjectListWindow(const std::vector<int> &_items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback);
+	CObjectListWindow(const std::vector<std::string> &_items, std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, std::function<void(int)> Callback);
 
-	CIntObject *genItem(size_t index);
+	std::shared_ptr<CIntObject> genItem(size_t index);
 	void elementSelected();//call callback and close this window
 	void changeSelection(size_t which);
 	void keyPressed (const SDL_KeyboardEvent & key) override;
@@ -178,23 +194,28 @@ public:
 class CSystemOptionsWindow : public CWindowObject
 {
 private:
-	CLabel *title;
-	CLabelGroup *leftGroup;
-	CLabelGroup *rightGroup;
-	CButton *load, *save, *restart, *mainMenu, *quitGame, *backToMap; //load and restart are not used yet
-	CToggleGroup * heroMoveSpeed;
-	CToggleGroup * enemyMoveSpeed;
-	CToggleGroup * mapScrollSpeed;
-	CVolumeSlider * musicVolume, * effectsVolume;
-
-	//CHighlightableButton * showPath;
-	CToggleButton * showReminder;
-	CToggleButton * quickCombat;
-	CToggleButton * spellbookAnim;
-	CToggleButton * fullscreen;
-
-	CButton *gameResButton;
-	CLabel *gameResLabel;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CLabelGroup> leftGroup;
+	std::shared_ptr<CLabelGroup> rightGroup;
+	std::shared_ptr<CButton> load;
+	std::shared_ptr<CButton> save;
+	std::shared_ptr<CButton> restart;
+	std::shared_ptr<CButton> mainMenu;
+	std::shared_ptr<CButton> quitGame;
+	std::shared_ptr<CButton> backToMap; //load and restart are not used yet
+	std::shared_ptr<CToggleGroup> heroMoveSpeed;
+	std::shared_ptr<CToggleGroup> enemyMoveSpeed;
+	std::shared_ptr<CToggleGroup> mapScrollSpeed;
+	std::shared_ptr<CVolumeSlider> musicVolume;
+	std::shared_ptr<CVolumeSlider> effectsVolume;
+
+	std::shared_ptr<CToggleButton> showReminder;
+	std::shared_ptr<CToggleButton> quickCombat;
+	std::shared_ptr<CToggleButton> spellbookAnim;
+	std::shared_ptr<CToggleButton> fullscreen;
+
+	std::shared_ptr<CButton> gameResButton;
+	std::shared_ptr<CLabel> gameResLabel;
 
 	SettingsListener onFullscreenChanged;
 
@@ -222,26 +243,39 @@ public:
 	public:
 		std::string hoverName;
 		std::string description; // "XXX is a level Y ZZZ with N artifacts"
-		const CGHeroInstance *h;
+		const CGHeroInstance * h;
 
 		void clickLeft(tribool down, bool previousState) override;
 		void clickRight(tribool down, bool previousState) override;
 		void hover (bool on) override;
-		HeroPortrait(int &sel, int id, int x, int y, const CGHeroInstance *H);
+		HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H);
 
 	private:
 		int *_sel;
 		const int _id;
 
-	} *h1, *h2; //recruitable heroes
+		std::shared_ptr<CAnimImage> portrait;
+	};
+
+	//recruitable heroes
+	std::shared_ptr<HeroPortrait> h1;
+	std::shared_ptr<HeroPortrait> h2; //recruitable heroes
 
 	int selected;//0 (left) or 1 (right)
 	int oldSelected;//0 (left) or 1 (right)
 
-	CButton *thiefGuild, *cancel, *recruit;
-	const CGObjectInstance *tavernObj;
+	std::shared_ptr<CButton> thiefGuild;
+	std::shared_ptr<CButton> cancel;
+	std::shared_ptr<CButton> recruit;
+
+	const CGObjectInstance * tavernObj;
+
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CLabel> cost;
+	std::shared_ptr<CTextBox> rumor;
+	std::shared_ptr<CGStatusBar> statusBar;
 
-	CTavernWindow(const CGObjectInstance *TavernObj);
+	CTavernWindow(const CGObjectInstance * TavernObj);
 	~CTavernWindow();
 
 	void recruitb();
@@ -249,29 +283,47 @@ public:
 	void show(SDL_Surface * to) override;
 };
 
-class CExchangeWindow : public CWindowObject, public CWindowWithGarrison, public CWindowWithArtifacts
+class CExchangeWindow : public CWindowObject, public CGarrisonHolder, public CWindowWithArtifacts
 {
-	CGStatusBar * ourBar; //internal statusbar
+	std::array<std::shared_ptr<CHeroWithMaybePickedArtifact>, 2> herosWArt;
 
-	CButton * quit, * questlogButton[2];
+	std::array<std::shared_ptr<CLabel>, 2> titles;
+	std::vector<std::shared_ptr<CAnimImage>> primSkillImages;//shared for both heroes
+	std::array<std::vector<std::shared_ptr<CLabel>>, 2> primSkillValues;
+	std::array<std::vector<std::shared_ptr<CAnimImage>>, 2> secSkillIcons;
+	std::array<std::shared_ptr<CAnimImage>, 2> specImages;
+	std::array<std::shared_ptr<CAnimImage>, 2> expImages;
+	std::array<std::shared_ptr<CLabel>, 2> expValues;
+	std::array<std::shared_ptr<CAnimImage>, 2> manaImages;
+	std::array<std::shared_ptr<CLabel>, 2> manaValues;
+	std::array<std::shared_ptr<CAnimImage>, 2> portraits;
 
-	std::vector<LRClickableAreaWTextComp *> secSkillAreas[2], primSkillAreas;
+	std::vector<std::shared_ptr<LRClickableAreaWTextComp>> primSkillAreas;
+	std::array<std::vector<std::shared_ptr<LRClickableAreaWTextComp>>, 2> secSkillAreas;
 
-	MoraleLuckBox *morale[2], *luck[2];
+	std::array<std::shared_ptr<CHeroArea>, 2> heroAreas;
+	std::array<std::shared_ptr<LRClickableAreaWText>, 2> specialtyAreas;
+	std::array<std::shared_ptr<LRClickableAreaWText>, 2> experienceAreas;
+	std::array<std::shared_ptr<LRClickableAreaWText>, 2> spellPointsAreas;
 
-	LRClickableAreaWText *specialty[2];
-	LRClickableAreaWText *experience[2];
-	LRClickableAreaWText *spellPoints[2];
-	CHeroArea *portrait[2];
+	std::array<std::shared_ptr<MoraleLuckBox>, 2> morale;
+	std::array<std::shared_ptr<MoraleLuckBox>, 2> luck;
+
+	std::shared_ptr<CButton> quit;
+	std::array<std::shared_ptr<CButton>, 2> questlogButton;
+
+	std::shared_ptr<CGStatusBar> statusBar;
+	std::shared_ptr<CGarrisonInt> garr;
 
 public:
+	std::array<const CGHeroInstance *, 2> heroInst;
+	std::array<std::shared_ptr<CArtifactsOfHero>, 2> artifs;
 
-	const CGHeroInstance* heroInst[2];
-	CArtifactsOfHero * artifs[2];
+	void updateGarrisons() override;
 
 	void questlog(int whichHero); //questlog button callback; whichHero: 0 - left, 1 - right
 
-	void prepareBackground(); //prepares or redraws bg
+	void updateWidgets();
 
 	CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID);
 	~CExchangeWindow();
@@ -280,22 +332,23 @@ public:
 /// Here you can buy ships
 class CShipyardWindow : public CWindowObject
 {
-public:
-	CGStatusBar *bar;
-	CPicture *bgWater;
+	std::shared_ptr<CPicture> bgWater;
+	std::shared_ptr<CAnimImage> bgShip;
 
-	CLabel *title;
-	CLabel *costLabel;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CLabel> costLabel;
 
-	CAnimImage *woodPic, *goldPic;
-	CLabel *woodCost, *goldCost;
+	std::shared_ptr<CAnimImage> woodPic;
+	std::shared_ptr<CAnimImage> goldPic;
+	std::shared_ptr<CLabel> woodCost;
+	std::shared_ptr<CLabel> goldCost;
 
-	CAnimImage *bgShip;
-	CButton *build, *quit;
+	std::shared_ptr<CButton> build;
+	std::shared_ptr<CButton> quit;
 
-	CGStatusBar * statusBar;
-
-	CShipyardWindow(const std::vector<si32> &cost, int state, int boatType, const std::function<void()> &onBuy);
+	std::shared_ptr<CGStatusBar> statusBar;
+public:
+	CShipyardWindow(const std::vector<si32> & cost, int state, int boatType, const std::function<void()> & onBuy);
 };
 
 /// Puzzle screen which gets uncovered when you visit obilisks
@@ -303,23 +356,25 @@ class CPuzzleWindow : public CWindowObject
 {
 private:
 	int3 grailPos;
+	std::shared_ptr<CPicture> logo;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CButton> quitb;
+	std::shared_ptr<CResDataBar> resDataBar;
 
-	CButton * quitb;
-
-	std::vector<CPicture * > piecesToRemove;
+	std::vector<std::shared_ptr<CPicture>> piecesToRemove;
+	std::vector<std::shared_ptr<CPicture>> visiblePieces;
 	ui8 currentAlpha;
 
 public:
 	void showAll(SDL_Surface * to) override;
 	void show(SDL_Surface * to) override;
 
-	CPuzzleWindow(const int3 &grailPos, double discoveredRatio);
+	CPuzzleWindow(const int3 & grailPos, double discoveredRatio);
 };
 
 /// Creature transformer window
 class CTransformerWindow : public CWindowObject, public CGarrisonHolder
 {
-public:
 	class CItem : public CIntObject
 	{
 	public:
@@ -327,7 +382,8 @@ public:
 		bool left;//position of the item
 		int size; //size of creature stack
 		CTransformerWindow * parent;
-		CAnimImage *icon;
+		std::shared_ptr<CAnimImage> icon;
+		std::shared_ptr<CLabel> count;
 
 		void move();
 		void clickLeft(tribool down, bool previousState) override;
@@ -335,13 +391,23 @@ public:
 		CItem(CTransformerWindow * parent, int size, int id);
 	};
 
-	const CArmedInstance *army;//object with army for transforming (hero or town)
-	const CGHeroInstance *hero;//only if we have hero in town
-	const CGTownInstance *town;//market, town garrison is used if hero == nullptr
-	std::vector<CItem*> items;
+	const CArmedInstance * army;//object with army for transforming (hero or town)
+	const CGHeroInstance * hero;//only if we have hero in town
+	const CGTownInstance * town;//market, town garrison is used if hero == nullptr
+
+	std::shared_ptr<CLabel> titleLeft;
+	std::shared_ptr<CLabel> titleRight;
+	std::shared_ptr<CTextBox> helpLeft;
+	std::shared_ptr<CTextBox> helpRight;
+
+	std::vector<std::shared_ptr<CItem>> items;
+
+	std::shared_ptr<CButton> all;
+	std::shared_ptr<CButton> convert;
+	std::shared_ptr<CButton> cancel;
+	std::shared_ptr<CGStatusBar> statusBar;
+public:
 
-	CButton *all, *convert, *cancel;
-	CGStatusBar *bar;
 	void makeDeal();
 	void addAll();
 	void updateGarrisons() override;
@@ -350,8 +416,13 @@ public:
 
 class CUniversityWindow : public CWindowObject
 {
-	class CItem : public CAnimImage
+	class CItem : public CIntObject
 	{
+		std::shared_ptr<CAnimImage> icon;
+		std::shared_ptr<CAnimImage> topBar;
+		std::shared_ptr<CAnimImage> bottomBar;
+		std::shared_ptr<CLabel> name;
+		std::shared_ptr<CLabel> level;
 	public:
 		int ID;//id of selected skill
 		CUniversityWindow * parent;
@@ -364,33 +435,66 @@ class CUniversityWindow : public CWindowObject
 		CItem(CUniversityWindow * _parent, int _ID, int X, int Y);
 	};
 
-public:
-	const CGHeroInstance *hero;
+	const CGHeroInstance * hero;
 	const IMarket * market;
 
-	CPicture * green, * yellow, * red;//colored bars near skills
-	std::vector<CItem*> items;
+	std::shared_ptr<CAnimation> bars;
 
-	CButton *cancel;
-	CGStatusBar *bar;
+	std::vector<std::shared_ptr<CItem>> items;
 
+	std::shared_ptr<CButton> cancel;
+	std::shared_ptr<CGStatusBar> statusBar;
+	std::shared_ptr<CIntObject> titlePic;
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CTextBox> clerkSpeech;
+
+public:
 	CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market);
+
+	void makeDeal(int skill);
 };
 
 /// Confirmation window for University
 class CUnivConfirmWindow : public CWindowObject
 {
-public:
-	CUniversityWindow * parent;
-	CGStatusBar *bar;
-	CButton *confirm, *cancel;
+	std::shared_ptr<CTextBox> clerkSpeech;
+	std::shared_ptr<CLabel> name;
+	std::shared_ptr<CLabel> level;
+	std::shared_ptr<CAnimImage> icon;
+
+	CUniversityWindow * owner;
+	std::shared_ptr<CGStatusBar> statusBar;
+	std::shared_ptr<CButton> confirm;
+	std::shared_ptr<CButton> cancel;
+
+	std::shared_ptr<CAnimImage> costIcon;
+	std::shared_ptr<CLabel> cost;
 
-	CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available);
 	void makeDeal(int skill);
+
+public:
+	CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available);
+};
+
+/// Garrison window where you can take creatures out of the hero to place it on the garrison
+class CGarrisonWindow : public CWindowObject, public CGarrisonHolder
+{
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CAnimImage> banner;
+	std::shared_ptr<CAnimImage> portrait;
+
+	std::shared_ptr<CGarrisonInt> garr;
+
+public:
+	std::shared_ptr<CButton> quit;
+
+	CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits);
+
+	void updateGarrisons() override;
 };
 
 /// Hill fort is the building where you can upgrade units
-class CHillFortWindow : public CWindowObject, public CWindowWithGarrison
+class CHillFortWindow : public CWindowObject, public CGarrisonHolder
 {
 private:
 	static const int slotsCount = 7;
@@ -400,23 +504,29 @@ private:
 	const CGObjectInstance * fort;
 	const CGHeroInstance * hero;
 
-	CGStatusBar * bar;
-	CHeroArea * heroPic;//clickable hero image
-	CButton * quit;//closes window
-	CButton * upgradeAll;//upgrade all creatures
+	std::shared_ptr<CLabel> title;
+	std::shared_ptr<CHeroArea> heroPic;
+
+	std::array<std::shared_ptr<CAnimImage>, resCount> totalIcons;
+	std::array<std::shared_ptr<CLabel>, resCount> totalLabels;
 
-	std::array<CButton *, slotsCount> upgrade;//upgrade single creature
+	std::array<std::shared_ptr<CButton>, slotsCount> upgrade;//upgrade single creature
 	std::array<int, slotsCount + 1> currState;//current state of slot - to avoid calls to getState or updating buttons
 
 	//there is a place for only 2 resources per slot
-	std::array< std::array<CAnimImage *, 2>, slotsCount> slotIcons;
-	std::array< std::array<CLabel *, 2>, slotsCount> slotLabels;
+	std::array< std::array<std::shared_ptr<CAnimImage>, 2>, slotsCount> slotIcons;
+	std::array< std::array<std::shared_ptr<CLabel>, 2>, slotsCount> slotLabels;
+
+	std::shared_ptr<CButton> upgradeAll;
+	std::shared_ptr<CButton> quit;
+
+	std::shared_ptr<CGarrisonInt> garr;
 
-	std::array<CAnimImage *, resCount> totalIcons;
-	std::array<CLabel *, resCount> totalLabels;
+	std::shared_ptr<CGStatusBar> statusBar;
+
+	std::string getDefForSlot(SlotID slot);
+	std::string getTextForSlot(SlotID slot);
 
-	std::string getDefForSlot(SlotID slot);//return def name for this slot
-	std::string getTextForSlot(SlotID slot);//return hover text for this slot
 	void makeDeal(SlotID slot);//-1 for upgrading all creatures
 	int getState(SlotID slot); //-1 = no creature 0=can't upgrade, 1=upgraded, 2=can upgrade
 public:
@@ -428,10 +538,22 @@ class CThievesGuildWindow : public CWindowObject
 {
 	const CGObjectInstance * owner;
 
-	CGStatusBar * statusBar;
-	CButton * exitb;
-	CMinorResDataBar * resdatabar;
-
+	std::shared_ptr<CGStatusBar> statusBar;
+	std::shared_ptr<CButton> exitb;
+	std::shared_ptr<CMinorResDataBar> resdatabar;
+
+	std::vector<std::shared_ptr<CLabel>> rowHeaders;
+	std::vector<std::shared_ptr<CAnimImage>> columnBackgrounds;
+	std::vector<std::shared_ptr<CLabel>> columnHeaders;
+	std::vector<std::shared_ptr<CAnimImage>> cells;
+
+	std::vector<std::shared_ptr<CPicture>> banners;
+	std::vector<std::shared_ptr<CAnimImage>> bestHeroes;
+	std::vector<std::shared_ptr<CTextBox>> primSkillHeaders;
+	std::vector<std::shared_ptr<CLabel>> primSkillValues;
+	std::vector<std::shared_ptr<CAnimImage>> bestCreatures;
+	std::vector<std::shared_ptr<CLabel>> personalities;
 public:
 	CThievesGuildWindow(const CGObjectInstance * _owner);
 };
+

+ 40 - 61
client/windows/InfoWindows.cpp

@@ -57,7 +57,7 @@ void CSelWindow::selectionChange(unsigned to)
 {
 	for (unsigned i=0;i<components.size();i++)
 	{
-		CSelectableComponent * pom = dynamic_cast<CSelectableComponent*>(components[i]);
+		auto pom = std::dynamic_pointer_cast<CSelectableComponent>(components[i]);
 		if (!pom)
 			continue;
 		pom->select(i==to);
@@ -65,19 +65,19 @@ void CSelWindow::selectionChange(unsigned to)
 	redraw();
 }
 
-CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector<CSelectableComponent*> &comps, const std::vector<std::pair<std::string, CFunctionList<void()> > > &Buttons, QueryID askID)
+CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<std::string, CFunctionList<void()> > > &Buttons, QueryID askID)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	ID = askID;
 	for (int i = 0; i < Buttons.size(); i++)
 	{
-		buttons.push_back(new CButton(Point(0, 0), Buttons[i].first, CButton::tooltip(), Buttons[i].second));
+		buttons.push_back(std::make_shared<CButton>(Point(0, 0), Buttons[i].first, CButton::tooltip(), Buttons[i].second));
 		if (!i  &&  askID.getNum() >= 0)
 			buttons.back()->addCallback(std::bind(&CSelWindow::madeChoice, this));
 		buttons[i]->addCallback(std::bind(&CInfoWindow::close, this)); //each button will close the window apart from call-defined actions
 	}
 
-	text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
+	text = std::make_shared<CTextBox>(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
 
 	buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
 	buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
@@ -92,8 +92,8 @@ CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperl
 
 	for(int i=0;i<comps.size();i++)
 	{
-		comps[i]->recActions = 255;
-		addChild(comps[i]);
+		comps[i]->recActions = 255-DISPOSE;
+		addChild(comps[i].get());
 		components.push_back(comps[i]);
 		comps[i]->onSelect = std::bind(&CSelWindow::selectionChange,this,i);
 		if(i<9)
@@ -109,7 +109,7 @@ void CSelWindow::madeChoice()
 	int ret = -1;
 	for (int i=0;i<components.size();i++)
 	{
-		if(dynamic_cast<CSelectableComponent*>(components[i])->selected)
+		if(std::dynamic_pointer_cast<CSelectableComponent>(components[i])->selected)
 		{
 			ret = i;
 		}
@@ -117,21 +117,21 @@ void CSelWindow::madeChoice()
 	LOCPLINT->cb->selectionMade(ret+1,ID);
 }
 
-CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps, const TButtonsInfo &Buttons, bool delComps)
+CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo & comps, const TButtonsInfo & Buttons)
 {
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 
 	type |= BLOCK_ADV_HOTKEYS;
 	ID = QueryID(-1);
 	for(auto & Button : Buttons)
 	{
-		CButton *button = new CButton(Point(0,0), Button.first, CButton::tooltip(), std::bind(&CInfoWindow::close,this));
+		std::shared_ptr<CButton> button = std::make_shared<CButton>(Point(0,0), Button.first, CButton::tooltip(), std::bind(&CInfoWindow::close, this));
 		button->setBorderColor(Colors::METALLIC_GOLD);
 		button->addCallback(Button.second); //each button will close the window apart from call-defined actions
 		buttons.push_back(button);
 	}
 
-	text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
+	text = std::make_shared<CTextBox>(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE);
 	if(!text->slider)
 	{
 		text->resize(text->label->textSize);
@@ -145,20 +145,18 @@ CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo
 
 	for(auto & comp : comps)
 	{
-		comp->recActions = 0xff;
-		addChild(comp);
+		comp->recActions = 0xff & ~DISPOSE;
+		addChild(comp.get());
 		comp->recActions &= ~(SHOWALL | UPDATE);
 		components.push_back(comp);
 	}
-	setDelComps(delComps);
+
 	CMessage::drawIWindow(this,Text,player);
 }
 
 CInfoWindow::CInfoWindow()
 {
 	ID = QueryID(-1);
-	setDelComps(false);
-	text = nullptr;
 }
 
 void CInfoWindow::close()
@@ -173,14 +171,7 @@ void CInfoWindow::show(SDL_Surface * to)
 	CIntObject::show(to);
 }
 
-CInfoWindow::~CInfoWindow()
-{
-	if(!delComps)
-	{
-		for (auto & elem : components)
-			removeChild(elem);
-	}
-}
+CInfoWindow::~CInfoWindow() = default;
 
 void CInfoWindow::showAll(SDL_Surface * to)
 {
@@ -188,19 +179,19 @@ void CInfoWindow::showAll(SDL_Surface * to)
 	CIntObject::showAll(to);
 }
 
-void CInfoWindow::showInfoDialog(const std::string &text, const std::vector<CComponent *> *components, bool DelComps, PlayerColor player)
+void CInfoWindow::showInfoDialog(const std::string &text, const TCompsInfo & components, PlayerColor player)
 {
-	CInfoWindow * window = CInfoWindow::create(text, player, components, DelComps);
+	CInfoWindow * window = CInfoWindow::create(text, player, components);
 	GH.pushInt(window);
 }
 
-void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps, PlayerColor player)
+void CInfoWindow::showYesNoDialog(const std::string & text, const TCompsInfo & components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, PlayerColor player)
 {
 	assert(!LOCPLINT || LOCPLINT->showingDialog->get());
 	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("ICANCEL.DEF",0));
-	CInfoWindow * temp = new CInfoWindow(text, player, components ? *components : std::vector<CComponent*>(), pom, DelComps);
+	CInfoWindow * temp = new CInfoWindow(text, player, components, pom);
 
 	temp->buttons[0]->addCallback( onYes );
 	temp->buttons[1]->addCallback( onNo );
@@ -208,21 +199,21 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector<CC
 	GH.pushInt(temp);
 }
 
-void CInfoWindow::showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const std::function<void()> & onOk, bool delComps, PlayerColor player)
+void CInfoWindow::showOkDialog(const std::string & text, const TCompsInfo & components, const std::function<void()> & onOk, PlayerColor player)
 {
 	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
-	CInfoWindow * temp = new CInfoWindow(text, player, *components, pom, delComps);
+	CInfoWindow * temp = new CInfoWindow(text, player, components, pom);
 	temp->buttons[0]->addCallback(onOk);
 
 	GH.pushInt(temp);
 }
 
-CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID, const std::vector<CComponent*> *components, bool DelComps)
+CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID, const TCompsInfo & components)
 {
 	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
-	CInfoWindow * ret = new CInfoWindow(text, playerID, components ? *components : std::vector<CComponent*>(), pom, DelComps);
+	CInfoWindow * ret = new CInfoWindow(text, playerID, components, pom);
 	return ret;
 }
 
@@ -231,18 +222,6 @@ std::string CInfoWindow::genText(std::string title, std::string description)
 	return std::string("{") + title + "}" + "\n\n" + description;
 }
 
-void CInfoWindow::setDelComps(bool DelComps)
-{
-	delComps = DelComps;
-	for(CComponent *comp : components)
-	{
-		if(delComps)
-			comp->recActions |= DISPOSE;
-		else
-			comp->recActions &= ~DISPOSE;
-	}
-}
-
 CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free)
  :free(Free),bitmap(Bitmap)
 {
@@ -344,7 +323,7 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom
 	GH.pushInt(rcpi);
 }
 
-void CRClickPopup::createAndPush(const std::string &txt, CComponent * component)
+void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr<CComponent> component)
 {
 	CInfoWindow::TCompsInfo intComps;
 	intComps.push_back(component);
@@ -408,47 +387,47 @@ Point CInfoBoxPopup::toScreen(Point p)
 	return p;
 }
 
-CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town):
-	CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
+CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
+	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
 {
 	InfoAboutTown iah;
 	LOCPLINT->cb->getTownInfo(town, iah, adventureInt->selection); //todo: should this be nearest hero?
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CTownTooltip(Point(9, 10), iah);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
 }
 
-CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero):
-	CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
+CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
+	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
 {
 	InfoAboutHero iah;
 	LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->selection);//todo: should this be nearest hero?
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CHeroTooltip(Point(9, 10), iah);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
 }
 
-CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr):
-	CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
+CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
+	: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
 {
 	InfoAboutTown iah;
 	LOCPLINT->cb->getTownInfo(garr, iah);
 
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	new CArmyTooltip(Point(9, 10), iah);
+	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
+	tooltip = std::make_shared<CArmyTooltip>(Point(9, 10), iah);
 }
 
 CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
 {
 	if(nullptr == specific)
 		specific = adventureInt->selection;
-	
+
 	if(nullptr == specific)
 	{
 		logGlobal->error("createInfoWin: no object to describe");
 		return nullptr;
-	}	
-	
+	}
+
 	switch(specific->ID)
 	{
 	case Obj::HERO:

+ 17 - 19
client/windows/InfoWindows.h

@@ -10,7 +10,6 @@
 #pragma once
 
 #include "CWindowObject.h"
-//#include "../gui/SDL_Extensions.h"
 #include "../../lib/FunctionList.h"
 
 struct SDL_Surface;
@@ -24,6 +23,7 @@ class CGGarrison;
 class CTextBox;
 class CButton;
 class CSlider;
+class CArmyTooltip;
 
 // Window GUI class
 class CSimpleWindow : public CIntObject
@@ -37,33 +37,30 @@ public:
 
 /// text + comp. + ok button
 class CInfoWindow : public CSimpleWindow
-{ //window able to delete its components when closed
-	bool delComps; //whether comps will be deleted
-
+{
 public:
-	typedef std::vector<std::pair<std::string,CFunctionList<void()> > > TButtonsInfo;
-	typedef std::vector<CComponent*> TCompsInfo;
+	typedef std::vector<std::pair<std::string, CFunctionList<void()> > > TButtonsInfo;
+	typedef std::vector<std::shared_ptr<CComponent>> TCompsInfo;
 	QueryID ID; //for identification
-	CTextBox *text;
-	std::vector<CButton *> buttons;
-	std::vector<CComponent*> components;
+	std::shared_ptr<CTextBox> text;
+	std::vector<std::shared_ptr<CButton>> buttons;
+	TCompsInfo components;
 
-	void setDelComps(bool DelComps);
 	virtual void close();
 
 	void show(SDL_Surface * to) override;
 	void showAll(SDL_Surface * to) override;
 	void sliderMoved(int to);
 
-	CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true);
+	CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo & comps = TCompsInfo(), const TButtonsInfo & Buttons = TButtonsInfo());
 	CInfoWindow();
 	~CInfoWindow();
 
 	//use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
-	static void showInfoDialog( const std::string & text, const std::vector<CComponent*> *components, bool DelComps = true, PlayerColor player = PlayerColor(1));
-	static void showOkDialog(const std::string & text, const std::vector<CComponent*> *components, const std::function<void()> & onOk, bool delComps = true, PlayerColor player = PlayerColor(1));
-	static void showYesNoDialog( const std::string & text, const std::vector<CComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps = true, PlayerColor player = PlayerColor(1));
-	static CInfoWindow *create(const std::string &text, PlayerColor playerID = PlayerColor(1), const std::vector<CComponent*> *components = nullptr, bool DelComps = false);
+	static void showInfoDialog( const std::string & text, const TCompsInfo & components, PlayerColor player = PlayerColor(1));
+	static void showOkDialog(const std::string & text, const TCompsInfo & components, const std::function<void()> & onOk, PlayerColor player = PlayerColor(1));
+	static void showYesNoDialog( const std::string & text, const TCompsInfo & components, const CFunctionList<void()> & onYes, const CFunctionList<void()> & onNo, PlayerColor player = PlayerColor(1));
+	static CInfoWindow * create(const std::string & text, PlayerColor playerID = PlayerColor(1), const TCompsInfo & components = TCompsInfo());
 
 	/// create text from title and description: {title}\n\n description
 	static std::string genText(std::string title, std::string description);
@@ -80,9 +77,9 @@ public:
 	virtual ~CRClickPopup();
 
 	static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific);
-	static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());
-	static void createAndPush(const std::string &txt, CComponent * component);
-	static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
+	static void createAndPush(const std::string & txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());
+	static void createAndPush(const std::string & txt, std::shared_ptr<CComponent> component);
+	static void createAndPush(const CGObjectInstance * obj, const Point & p, EAlignment alignment = BOTTOMRIGHT);
 };
 
 /// popup displayed on R-click
@@ -116,6 +113,7 @@ public:
 /// popup on adventure map for town\hero objects
 class CInfoBoxPopup : public CWindowObject
 {
+	std::shared_ptr<CArmyTooltip> tooltip;
 	Point toScreen(Point pos);
 public:
 	CInfoBoxPopup(Point position, const CGTownInstance * town);
@@ -129,7 +127,7 @@ class CSelWindow : public CInfoWindow
 public:
 	void selectionChange(unsigned to);
 	void madeChoice(); //looks for selected component and calls callback
-	CSelWindow(const std::string& text, PlayerColor player, int charperline ,const std::vector<CSelectableComponent*> &comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID);
+	CSelWindow(const std::string & text, PlayerColor player, int charperline ,const std::vector<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, QueryID askID);
 	CSelWindow(){};
 	//notification - this class inherits important destructor from CInfoWindow
 };

+ 0 - 1
lib/CGameInterface.h

@@ -23,7 +23,6 @@ class CBattleCallback;
 class ICallback;
 class CGlobalAI;
 struct Component;
-class CSelectableComponent;
 struct TryMoveHero;
 class CGHeroInstance;
 class CGTownInstance;

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -99,7 +99,7 @@ public:
 	virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement
 	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
 	virtual void receivedResource(){};
-	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){};
+	virtual void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID){};
 	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
 	virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
 

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно