Browse Source

IMarket serializeable

SoundSSGood 1 year ago
parent
commit
fd45b5144d

+ 1 - 1
AI/Nullkiller/AIGateway.cpp

@@ -526,7 +526,7 @@ void AIGateway::heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonu
 	NET_EVENT_HANDLER;
 }
 
-void AIGateway::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
+void AIGateway::showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID)
 {
 	LOG_TRACE(logAi);
 	NET_EVENT_HANDLER;

+ 1 - 1
AI/Nullkiller/AIGateway.h

@@ -152,7 +152,7 @@ public:
 	void objectPropertyChanged(const SetObjectProperty * sop) override;
 	void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
 	void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
-	void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
+	void showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID) override;
 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
 	std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;
 

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -594,7 +594,7 @@ void VCAI::heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bo
 	NET_EVENT_HANDLER;
 }
 
-void VCAI::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
+void VCAI::showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID)
 {
 	LOG_TRACE(logAi);
 	NET_EVENT_HANDLER;

+ 1 - 1
AI/VCAI/VCAI.h

@@ -184,7 +184,7 @@ public:
 	void objectPropertyChanged(const SetObjectProperty * sop) override;
 	void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
 	void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
-	void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
+	void showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID) override;
 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
 
 	void battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, BattleSide side, bool replayAllowed) override;

+ 4 - 4
client/CPlayerInterface.cpp

@@ -1632,7 +1632,7 @@ void CPlayerInterface::battleNewRoundFirst(const BattleID & battleID)
 	battleInt->newRoundFirst();
 }
 
-void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)
+void CPlayerInterface::showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	auto onWindowClosed = [this, queryID](){
@@ -1649,13 +1649,13 @@ void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInsta
 	}
 
 	if(market->allowsTrade(EMarketMode::ARTIFACT_EXP) && visitor->getAlignment() != EAlignment::EVIL)
-		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, EMarketMode::ARTIFACT_EXP);
+		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, marketId, onWindowClosed, EMarketMode::ARTIFACT_EXP);
 	else if(market->allowsTrade(EMarketMode::CREATURE_EXP) && visitor->getAlignment() != EAlignment::GOOD)
-		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, EMarketMode::CREATURE_EXP);
+		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, marketId, onWindowClosed, EMarketMode::CREATURE_EXP);
 	else if(market->allowsTrade(EMarketMode::CREATURE_UNDEAD))
 		GH.windows().createAndPushWindow<CTransformerWindow>(market, visitor, onWindowClosed);
 	else if(!market->availableModes().empty())
-		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, market->availableModes().front());
+		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, marketId, onWindowClosed, market->availableModes().front());
 }
 
 void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)

+ 1 - 1
client/CPlayerInterface.h

@@ -120,7 +120,7 @@ protected: // Call-ins from server, should not be called directly, but only via
 	void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
 	void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
 	void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
-	void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID) override;
+	void showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID) override;
 	void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID) override;
 	void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
 	void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override; //called when a hero casts a spell

+ 1 - 1
client/NetPacksClient.cpp

@@ -1010,7 +1010,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 			const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
 			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
 			const auto *market = dynamic_cast<const IMarket*>(obj);
-			callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
+			callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, pack.object, hero, pack.queryID);
 		}
 		break;
 	case EOpenWindowMode::HILL_FORT_WINDOW:

+ 1 - 1
client/adventureMap/AdventureMapShortcuts.cpp

@@ -432,7 +432,7 @@ void AdventureMapShortcuts::showMarketplace()
 	}
 
 	if(townWithMarket) //if any town has marketplace, open window
-		GH.windows().createAndPushWindow<CMarketWindow>(townWithMarket, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
+		GH.windows().createAndPushWindow<CMarketWindow>(townWithMarket, nullptr, townWithMarket->id, nullptr, EMarketMode::RESOURCE_RESOURCE);
 	else //if not - complain
 		LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket"));
 }

+ 1 - 1
client/widgets/MiscWidgets.cpp

@@ -478,7 +478,7 @@ void CInteractableTownTooltip::init(const CGTownInstance * town)
 		{
 			if(town->builtBuildings.count(BuildingID::MARKETPLACE))
 			{
-				GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
+				GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, town->id, nullptr, EMarketMode::RESOURCE_RESOURCE);
 				return;
 			}
 		}

+ 3 - 4
client/widgets/markets/CAltarArtifacts.cpp

@@ -26,14 +26,13 @@
 #include "../../../lib/mapObjects/CGHeroInstance.h"
 #include "../../../lib/mapObjects/CGMarket.h"
 
-CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
+CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero, const ObjectInstanceID & marketId)
 	: CMarketBase(market, hero)
 {
 	OBJECT_CONSTRUCTION;
 
 	assert(dynamic_cast<const CGArtifactsAltar*>(market));
-	auto altarObj = dynamic_cast<const CGArtifactsAltar*>(market);
-	altarArtifacts = altarObj;
+	altarArtifacts = dynamic_cast<const CGArtifactsAltar*>(market);
 
 	deal = std::make_shared<CButton>(Point(269, 520), AnimationPath::builtin("ALTSACR.DEF"),
 		CGI->generaltexth->zelp[585], [this]() {CAltarArtifacts::makeDeal(); }, EShortcut::MARKET_DEAL);
@@ -51,7 +50,7 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
 	// Hero's artifacts
 	heroArts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11));
 	heroArts->setHero(hero);
-	heroArts->altarId = altarObj->id;
+	heroArts->altarId = marketId;
 
 	// Altar
 	offerTradePanel = std::make_shared<ArtifactsAltarPanel>([this](const std::shared_ptr<CTradeableItem> & altarSlot)

+ 1 - 1
client/widgets/markets/CAltarArtifacts.h

@@ -15,7 +15,7 @@
 class CAltarArtifacts : public CExperienceAltar
 {
 public:
-	CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
+	CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero, const ObjectInstanceID & marketId);
 	TExpType calcExpAltarForHero() override;
 	void deselect() override;
 	void makeDeal() override;

+ 2 - 11
client/widgets/markets/CArtifactsBuying.cpp

@@ -11,7 +11,6 @@
 #include "StdInc.h"
 #include "CArtifactsBuying.h"
 
-#include "../../gui/CGuiHandler.h"
 #include "../../gui/Shortcut.h"
 #include "../../widgets/Buttons.h"
 #include "../../widgets/TextControls.h"
@@ -21,24 +20,16 @@
 
 #include "../../../CCallback.h"
 
-#include "../../../lib/entities/building/CBuilding.h"
-#include "../../../lib/entities/faction/CTownHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
-#include "../../../lib/mapObjects/CGMarket.h"
-#include "../../../lib/mapObjects/CGTownInstance.h"
+#include "../../../lib/mapObjects/IMarket.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"
 
-CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero)
+CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero, const std::string & title)
 	: CMarketBase(market, hero)
 	, CResourcesSelling([this](const std::shared_ptr<CTradeableItem> & heroSlot){CArtifactsBuying::onSlotClickPressed(heroSlot, bidTradePanel);})
 {
 	OBJECT_CONSTRUCTION;
 
-	std::string title;
-	if(auto townMarket = dynamic_cast<const CGTownInstance*>(market))
-		title = (*CGI->townh)[townMarket->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated();
-	else
-		title = CGI->generaltexth->allTexts[349];
 	labels.emplace_back(std::make_shared<CLabel>(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, title));
 	deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("TPMRKB.DEF"),
 		CGI->generaltexth->zelp[595], [this](){CArtifactsBuying::makeDeal();}, EShortcut::MARKET_DEAL);

+ 1 - 1
client/widgets/markets/CArtifactsBuying.h

@@ -14,7 +14,7 @@
 class CArtifactsBuying : public CResourcesSelling, public CMarketTraderText
 {
 public:
-	CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero);
+	CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero, const std::string & title);
 	void deselect() override;
 	void makeDeal() override;
 

+ 2 - 11
client/widgets/markets/CArtifactsSelling.cpp

@@ -22,14 +22,11 @@
 #include "../../../CCallback.h"
 
 #include "../../../lib/CArtifactInstance.h"
-#include "../../../lib/entities/building/CBuilding.h"
-#include "../../../lib/entities/faction/CTownHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
-#include "../../../lib/mapObjects/CGMarket.h"
-#include "../../../lib/mapObjects/CGTownInstance.h"
+#include "../../../lib/mapObjects/IMarket.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"
 
-CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero)
+CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero, const std::string & title)
 	: CMarketBase(market, hero)
 	, CResourcesBuying(
 		[this](const std::shared_ptr<CTradeableItem> & resSlot){CArtifactsSelling::onSlotClickPressed(resSlot, offerTradePanel);},
@@ -37,12 +34,6 @@ CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstanc
 {
 	OBJECT_CONSTRUCTION;
 
-	std::string title;
-	if(const auto townMarket = dynamic_cast<const CGTownInstance*>(market))
-		title = (*CGI->townh)[townMarket->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated();
-	else if(const auto mapMarket = dynamic_cast<const CGMarket*>(market))
-		title = mapMarket->title;
-
 	labels.emplace_back(std::make_shared<CLabel>(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, title));
 	labels.push_back(std::make_shared<CLabel>(155, 56, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->getNameTranslated())));
 	deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("TPMRKB.DEF"),

+ 1 - 1
client/widgets/markets/CArtifactsSelling.h

@@ -15,7 +15,7 @@
 class CArtifactsSelling : public CResourcesBuying, public CMarketTraderText
 {
 public:
-	CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero);
+	CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero, const std::string & title);
 	void deselect() override;
 	void makeDeal() override;
 	void updateShowcases() override;

+ 5 - 5
client/windows/CCastleInterface.cpp

@@ -729,7 +729,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 		case BuildingID::MARKETPLACE:
 				// can't use allied marketplace
 				if (town->getOwner() == LOCPLINT->playerID)
-					GH.windows().createAndPushWindow<CMarketWindow>(town, town->visitingHero, nullptr, EMarketMode::RESOURCE_RESOURCE);
+					GH.windows().createAndPushWindow<CMarketWindow>(town, town->visitingHero, town->id, nullptr, EMarketMode::RESOURCE_RESOURCE);
 				else
 					enterBuilding(building);
 				break;
@@ -758,7 +758,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 
 				case BuildingSubID::ARTIFACT_MERCHANT:
 						if(town->visitingHero)
-							GH.windows().createAndPushWindow<CMarketWindow>(town, town->visitingHero, nullptr, EMarketMode::RESOURCE_ARTIFACT);
+							GH.windows().createAndPushWindow<CMarketWindow>(town, town->visitingHero, town->id, nullptr, EMarketMode::RESOURCE_ARTIFACT);
 						else
 							LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->getNameTranslated())); //Only visiting heroes may use the %s.
 						break;
@@ -769,7 +769,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 
 				case BuildingSubID::FREELANCERS_GUILD:
 						if(getHero())
-							GH.windows().createAndPushWindow<CMarketWindow>(town, getHero(), nullptr, EMarketMode::CREATURE_RESOURCE);
+							GH.windows().createAndPushWindow<CMarketWindow>(town, getHero(), town->id, nullptr, EMarketMode::CREATURE_RESOURCE);
 						else
 							LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->getNameTranslated())); //Only visiting heroes may use the %s.
 						break;
@@ -1061,7 +1061,7 @@ void CCastleBuildings::enterAnyMarket()
 {
 	if(town->builtBuildings.count(BuildingID::MARKETPLACE))
 	{
-		GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
+		GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, town->id, nullptr, EMarketMode::RESOURCE_RESOURCE);
 		return;
 	}
 
@@ -1070,7 +1070,7 @@ void CCastleBuildings::enterAnyMarket()
 	{
 		if(town->builtBuildings.count(BuildingID::MARKETPLACE))
 		{
-			GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
+			GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, town->id, nullptr, EMarketMode::RESOURCE_RESOURCE);
 			return;
 		}
 	}

+ 1 - 1
client/windows/CKingdomInterface.cpp

@@ -835,7 +835,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
 		{
 			if(town->builtBuildings.count(BuildingID::MARKETPLACE))
 			{
-				GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
+				GH.windows().createAndPushWindow<CMarketWindow>(town, nullptr, town->id, nullptr, EMarketMode::RESOURCE_RESOURCE);
 				return;
 			}
 		}

+ 11 - 5
client/windows/CMarketWindow.cpp

@@ -32,9 +32,13 @@
 #include "../../lib/mapObjects/CGMarket.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 
-CMarketWindow::CMarketWindow(const IMarket * market, const CGHeroInstance * hero, const std::function<void()> & onWindowClosed, EMarketMode mode)
+#include "../../CCallback.h"
+
+CMarketWindow::CMarketWindow(const IMarket * market, const CGHeroInstance * hero, const ObjectInstanceID & marketId,
+	const std::function<void()> & onWindowClosed, EMarketMode mode)
 	: CWindowObject(PLAYER_COLORED)
 	, windowClosedCallback(onWindowClosed)
+	, marketId(marketId)
 {
 	assert(mode == EMarketMode::RESOURCE_RESOURCE || mode == EMarketMode::RESOURCE_PLAYER || mode == EMarketMode::CREATURE_RESOURCE ||
 		mode == EMarketMode::RESOURCE_ARTIFACT || mode == EMarketMode::ARTIFACT_RESOURCE || mode == EMarketMode::ARTIFACT_EXP ||
@@ -180,7 +184,8 @@ void CMarketWindow::createArtifactsBuying(const IMarket * market, const CGHeroIn
 	OBJECT_CONSTRUCTION;
 
 	background = createBg(ImagePath::builtin("TPMRKABS.bmp"), PLAYER_COLORED);
-	marketWidget = std::make_shared<CArtifactsBuying>(market, hero);
+	marketWidget = std::make_shared<CArtifactsBuying>(market, hero, LOCPLINT->cb->getTown(marketId) ?
+		VLC->generaltexth->translate("building.core.conflux.special1.name") : CGI->generaltexth->allTexts[349]);
 	initWidgetInternals(EMarketMode::RESOURCE_ARTIFACT, CGI->generaltexth->zelp[600]);
 }
 
@@ -192,13 +197,14 @@ void CMarketWindow::createArtifactsSelling(const IMarket * market, const CGHeroI
 	// Create image that copies part of background containing slot MISC_1 into position of slot MISC_5
 	artSlotBack = std::make_shared<CPicture>(background->getSurface(), Rect(20, 187, 47, 47), 0, 0);
 	artSlotBack->moveTo(pos.topLeft() + Point(18, 339));
-	auto artsSellingMarket = std::make_shared<CArtifactsSelling>(market, hero);
+	auto artsSellingMarket = std::make_shared<CArtifactsSelling>(market, hero, LOCPLINT->cb->getTown(marketId) ?
+		VLC->generaltexth->translate("building.core.conflux.special1.name") : LOCPLINT->cb->getObj(marketId)->getObjectName());
 	artSets.clear();
 	const auto heroArts = artsSellingMarket->getAOHset();
 	heroArts->showPopupCallback = [this, heroArts](CArtPlace & artPlace, const Point & cursorPosition){showArifactInfo(*heroArts, artPlace, cursorPosition);};
 	addSet(heroArts);
 	marketWidget = artsSellingMarket;
-	initWidgetInternals(EMarketMode::ARTIFACT_RESOURCE, CGI->generaltexth->zelp[600]);	
+	initWidgetInternals(EMarketMode::ARTIFACT_RESOURCE, CGI->generaltexth->zelp[600]);
 }
 
 void CMarketWindow::createMarketResources(const IMarket * market, const CGHeroInstance * hero)
@@ -233,7 +239,7 @@ void CMarketWindow::createAltarArtifacts(const IMarket * market, const CGHeroIns
 	OBJECT_CONSTRUCTION;
 
 	background = createBg(ImagePath::builtin("ALTRART2.bmp"), PLAYER_COLORED);
-	auto altarArtifacts = std::make_shared<CAltarArtifacts>(market, hero);
+	auto altarArtifacts = std::make_shared<CAltarArtifacts>(market, hero, marketId);
 	marketWidget = altarArtifacts;
 	artSets.clear();
 	const auto heroArts = altarArtifacts->getAOHset();

+ 3 - 1
client/windows/CMarketWindow.h

@@ -15,7 +15,8 @@
 class CMarketWindow final : public CStatusbarWindow, public CWindowWithArtifacts, public IGarrisonHolder, public IMarketHolder
 {
 public:
-	CMarketWindow(const IMarket * market, const CGHeroInstance * hero, const std::function<void()> & onWindowClosed, EMarketMode mode);
+	CMarketWindow(const IMarket * market, const CGHeroInstance * hero, const ObjectInstanceID & marketId,
+		const std::function<void()> & onWindowClosed, EMarketMode mode);
 	void updateResources() override;
 	void updateArtifacts() override;
 	void updateGarrisons() override;
@@ -42,6 +43,7 @@ private:
 	std::function<void()> windowClosedCallback;
 	const Point quitButtonPos = Point(516, 520);
 	std::shared_ptr<CMarketBase> marketWidget;
+	const ObjectInstanceID marketId;
 
 	// This is workaround for bug in H3 files where this slot for ragdoll on this screen is missing
 	std::shared_ptr<CPicture> artSlotBack;

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -109,7 +109,7 @@ public:
 
 	virtual void showPuzzleMap(){};
 	virtual void viewWorldMap(){};
-	virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID){};
+	virtual void showMarketWindow(const IMarket * market, const ObjectInstanceID & marketId, const CGHeroInstance * visitor, QueryID queryID){};
 	virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID){};
 	virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){};
 	virtual void showThievesGuildWindow (const CGObjectInstance * obj){};

+ 9 - 6
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -251,12 +251,15 @@ void MarketInstanceConstructor::initializeObject(CGMarket * market) const
 	market->marketModes = marketModes;
 	market->marketEfficiency = marketEfficiency;
 	
-	market->title = market->getObjectName();
-	if(!title.empty())
-		market->title = VLC->generaltexth->translate(title);
-	
-	if (!speech.empty())
-		market->speech = VLC->generaltexth->translate(speech);
+	if(auto univercity = dynamic_cast<CGUniversity*>(market))
+	{
+		univercity->title = market->getObjectName();
+		if(!title.empty())
+			univercity->title = VLC->generaltexth->translate(title);
+
+		if(!speech.empty())
+			univercity->speech = VLC->generaltexth->translate(speech);
+	}
 }
 
 void MarketInstanceConstructor::randomizeObject(CGMarket * object, vstd::RNG & rng) const

+ 5 - 6
lib/mapObjects/CGMarket.h

@@ -22,10 +22,6 @@ public:
 	std::set<EMarketMode> marketModes;
 	int marketEfficiency;
 	
-	//window variables
-	std::string title;
-	std::string speech; //currently shown only in university
-	
 	CGMarket(IGameCallback *cb);
 	///IObjectInterface
 	void onHeroVisit(const CGHeroInstance * h) const override; //open trading window
@@ -40,10 +36,9 @@ public:
 	template <typename Handler> void serialize(Handler &h)
 	{
 		h & static_cast<CGObjectInstance&>(*this);
+		h & static_cast<IMarket&>(*this);
 		h & marketModes;
 		h & marketEfficiency;
-		h & title;
-		h & speech;
 	}
 };
 
@@ -68,6 +63,8 @@ class DLL_LINKAGE CGUniversity : public CGMarket
 {
 public:
 	using CGMarket::CGMarket;
+	std::string speech; //currently shown only in university
+	std::string title;
 
 	std::vector<TradeItemBuy> skills; //available skills
 
@@ -78,6 +75,8 @@ public:
 	{
 		h & static_cast<CGMarket&>(*this);
 		h & skills;
+		h & speech;
+		h & title;
 	}
 };
 

+ 1 - 0
lib/mapObjects/CGTownInstance.h

@@ -76,6 +76,7 @@ public:
 	template <typename Handler> void serialize(Handler &h)
 	{
 		h & static_cast<CGDwelling&>(*this);
+		h & static_cast<IMarket&>(*this);
 		h & nameTextId;
 		h & built;
 		h & destroyed;

+ 2 - 11
lib/mapObjects/IMarket.cpp

@@ -122,12 +122,7 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode)
 	return true;
 }
 
-bool IMarket::allowsTrade(EMarketMode mode) const
-{
-	return false;
-}
-
-int IMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
+int IMarket::availableUnits(const EMarketMode mode, const int marketItemSerial) const
 {
 	switch(mode)
 	{
@@ -140,7 +135,7 @@ int IMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
 	}
 }
 
-std::vector<TradeItemBuy> IMarket::availableItemsIds(EMarketMode mode) const
+std::vector<TradeItemBuy> IMarket::availableItemsIds(const EMarketMode mode) const
 {
 	std::vector<TradeItemBuy> ret;
 	switch(mode)
@@ -154,10 +149,6 @@ std::vector<TradeItemBuy> IMarket::availableItemsIds(EMarketMode mode) const
 	return ret;
 }
 
-IMarket::IMarket()
-{
-}
-
 std::vector<EMarketMode> IMarket::availableModes() const
 {
 	std::vector<EMarketMode> ret;

+ 20 - 8
lib/mapObjects/IMarket.h

@@ -11,24 +11,36 @@
 
 #include "../networkPacks/TradeItem.h"
 #include "../constants/Enumerations.h"
+#include "../CArtHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class CGObjectInstance;
-
-class DLL_LINKAGE IMarket
+class DLL_LINKAGE IMarket : public virtual Serializeable
 {
 public:
-	IMarket();
-	virtual ~IMarket() {}
+	class CArtifactSetAltar : public CArtifactSet
+	{
+	public:
+		ArtBearer::ArtBearer bearerType() const override {return ArtBearer::ALTAR;};
+	};
 
 	virtual int getMarketEfficiency() const = 0;
-	virtual bool allowsTrade(EMarketMode mode) const;
-	virtual int availableUnits(EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
-	virtual std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const;
+	virtual bool allowsTrade(const EMarketMode mode) const = 0;
+	virtual int availableUnits(const EMarketMode mode, const int marketItemSerial) const; //-1 if unlimited
+	virtual std::vector<TradeItemBuy> availableItemsIds(const EMarketMode mode) const;
 
 	bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
 	std::vector<EMarketMode> availableModes() const;
+
+	template <typename Handler> void serialize(Handler & h)
+	{
+		if(h.loadingGamestate)
+		{
+		}
+	}
+
+private:
+	std::shared_ptr<CArtifactSetAltar> altarArtifacts;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/registerTypes/RegisterTypesMapObjects.h

@@ -51,7 +51,7 @@ void registerTypesMapObjects(Serializer &s)
 	s.template registerType<CGObjectInstance, CGLighthouse>();
 	s.template registerType<CGObjectInstance, CGTerrainPatch>();
 	s.template registerType<CGObjectInstance, HillFort>();
-	s.template registerType<CGObjectInstance, CGMarket>();
+	s.template registerType<CGObjectInstance, CGMarket>(); s.template registerType<IMarket, CGMarket>();
 		s.template registerType<CGMarket, CGBlackMarket>();
 		s.template registerType<CGMarket, CGUniversity>();
 	s.template registerType<CGObjectInstance, CGHeroPlaceholder>();