Browse Source

market->getObjInstanceID()

SoundSSGood 1 year ago
parent
commit
2e3e6b1553

+ 1 - 1
AI/Nullkiller/AIGateway.cpp

@@ -1490,7 +1490,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
 				//TODO trade only as much as needed
 				if (toGive) //don't try to sell 0 resources
 				{
-					cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
+					cb->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
 					acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
 					logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
 				}

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -2130,7 +2130,7 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
 				//TODO trade only as much as needed
 				if (toGive) //don't try to sell 0 resources
 				{
-					cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
+					cb->trade(m->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
 					acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
 					logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
 				}

+ 4 - 4
CCallback.cpp

@@ -266,15 +266,15 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, ArtifactID aid)
 	sendRequest(&pack);
 }
 
-void CCallback::trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)
+void CCallback::trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)
 {
-	trade(market, mode, std::vector(1, id1), std::vector(1, id2), std::vector(1, val1), hero);
+	trade(marketId, mode, std::vector(1, id1), std::vector(1, id2), std::vector(1, val1), hero);
 }
 
-void CCallback::trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero)
+void CCallback::trade(const ObjectInstanceID marketId, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero)
 {
 	TradeOnMarketplace pack;
-	pack.marketId = dynamic_cast<const CGObjectInstance *>(market)->id;
+	pack.marketId = marketId;
 	pack.heroId = hero ? hero->id : ObjectInstanceID();
 	pack.mode = mode;
 	pack.r1 = id1;

+ 4 - 5
CCallback.h

@@ -34,7 +34,6 @@ class IBattleEventsReceiver;
 class IGameEventsReceiver;
 struct ArtifactLocation;
 class BattleStateInfoForRetreat;
-class IMarket;
 
 VCMI_LIB_NAMESPACE_END
 
@@ -81,8 +80,8 @@ public:
 	virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
 	virtual void swapGarrisonHero(const CGTownInstance *town)=0;
 
-	virtual void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
-	virtual void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr)=0;
+	virtual void trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
+	virtual void trade(const ObjectInstanceID marketId, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr)=0;
 
 	virtual int selectionMade(int selection, QueryID queryID) =0;
 	virtual int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0;
@@ -190,8 +189,8 @@ public:
 	void endTurn() override;
 	void swapGarrisonHero(const CGTownInstance *town) override;
 	void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override;
-	void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;
-	void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
+	void trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;
+	void trade(const ObjectInstanceID marketId, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
 	void setFormation(const CGHeroInstance * hero, EArmyFormation mode) override;
 	void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero, const HeroTypeID & nextHero=HeroTypeID::NONE) override;
 	void save(const std::string &fname) override;

+ 11 - 2
client/CPlayerInterface.cpp

@@ -1654,8 +1654,17 @@ void CPlayerInterface::showMarketWindow(const IMarket * market, const CGHeroInst
 		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, EMarketMode::CREATURE_EXP);
 	else if(market->allowsTrade(EMarketMode::CREATURE_UNDEAD))
 		GH.windows().createAndPushWindow<CTransformerWindow>(market, visitor, onWindowClosed);
-	else if(vstd::contains(market->availableModes(), EMarketMode::RESOURCE_RESOURCE))
-		GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, EMarketMode::RESOURCE_RESOURCE);
+	else if (!market->availableModes().empty())
+		for(auto mode = EMarketMode::RESOURCE_RESOURCE; mode != EMarketMode::MARKET_AFTER_LAST_PLACEHOLDER; mode = vstd::next(mode, 1))
+		{
+			if(vstd::contains(market->availableModes(), mode))
+			{
+				GH.windows().createAndPushWindow<CMarketWindow>(market, visitor, onWindowClosed, mode);
+				break;
+			}
+		}
+	else
+		onWindowClosed();
 }
 
 void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)

+ 2 - 2
client/NetPacksClient.cpp

@@ -999,7 +999,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 	case EOpenWindowMode::UNIVERSITY_WINDOW:
 		{
 			//displays University window (when hero enters University on adventure map)
-			const auto * market = dynamic_cast<const IMarket*>(cl.getObj(ObjectInstanceID(pack.object)));
+			const auto * market = cl.getMarket(ObjectInstanceID(pack.object));
 			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
 			callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero, pack.queryID);
 		}
@@ -1009,7 +1009,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 			//displays Thieves' Guild window (when hero enters Den of Thieves)
 			const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
 			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
-			const auto *market = dynamic_cast<const IMarket*>(obj);
+			const auto market = cl.getMarket(pack.object);
 			callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
 		}
 		break;

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

@@ -24,7 +24,7 @@
 #include "../../../lib/networkPacks/ArtifactLocation.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
-#include "../../../lib/mapObjects/CGMarket.h"
+#include "../../../lib/mapObjects/IMarket.h"
 
 CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
 	: CMarketBase(market, hero)
@@ -50,9 +50,7 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
 	// Hero's artifacts
 	heroArts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11));
 	heroArts->setHero(hero);
-	const auto mapObj = dynamic_cast<const CGObjectInstance*>(market);
-	assert(mapObj);
-	heroArts->altarId = mapObj->id;
+	heroArts->altarId = market->getObjInstanceID();
 
 	// Altar
 	offerTradePanel = std::make_shared<ArtifactsAltarPanel>([this](const std::shared_ptr<CTradeableItem> & altarSlot)
@@ -105,7 +103,7 @@ void CAltarArtifacts::makeDeal()
 	{
 		positions.push_back(artInst->getId());
 	}
-	LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
+	LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
 	deselect();
 }
 

+ 2 - 2
client/widgets/markets/CAltarCreatures.cpp

@@ -23,7 +23,7 @@
 
 #include "../../../lib/texts/CGeneralTextHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
-#include "../../../lib/mapObjects/CGMarket.h"
+#include "../../../lib/mapObjects/IMarket.h"
 
 CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
 	: CMarketBase(market, hero)
@@ -157,7 +157,7 @@ void CAltarCreatures::makeDeal()
 		}
 	}
 
-	LOCPLINT->cb->trade(market, EMarketMode::CREATURE_EXP, ids, {}, toSacrifice, hero);
+	LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::CREATURE_EXP, ids, {}, toSacrifice, hero);
 
 	for(int & units : unitsOnAltar)
 		units = 0;

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

@@ -68,7 +68,7 @@ void CArtifactsBuying::makeDeal()
 {
 	if(ArtifactID(offerTradePanel->getSelectedItemId()).toArtifact()->canBePutAt(hero))
 	{
-		LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_ARTIFACT, GameResID(bidTradePanel->getSelectedItemId()),
+		LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_ARTIFACT, GameResID(bidTradePanel->getSelectedItemId()),
 			ArtifactID(offerTradePanel->getSelectedItemId()), offerQty, hero);
 		CMarketTraderText::makeDeal();
 		deselect();

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

@@ -78,7 +78,8 @@ void CArtifactsSelling::makeDeal()
 {
 	const auto art = hero->getArt(selectedHeroSlot);
 	assert(art);
-	LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_RESOURCE, art->getId(), GameResID(offerTradePanel->getSelectedItemId()), offerQty, hero);
+	LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::ARTIFACT_RESOURCE, art->getId(),
+		GameResID(offerTradePanel->getSelectedItemId()), offerQty, hero);
 	CMarketTraderText::makeDeal();
 }
 

+ 2 - 2
client/widgets/markets/CFreelancerGuild.cpp

@@ -23,7 +23,7 @@
 
 #include "../../../lib/texts/CGeneralTextHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
-#include "../../../lib/mapObjects/CGMarket.h"
+#include "../../../lib/mapObjects/IMarket.h"
 
 CFreelancerGuild::CFreelancerGuild(const IMarket * market, const CGHeroInstance * hero)
 	: CMarketBase(market, hero)
@@ -69,7 +69,7 @@ void CFreelancerGuild::makeDeal()
 {
 	if(auto toTrade = offerSlider->getValue(); toTrade != 0)
 	{
-		LOCPLINT->cb->trade(market, EMarketMode::CREATURE_RESOURCE, SlotID(bidTradePanel->highlightedSlot->serial), GameResID(offerTradePanel->getSelectedItemId()), bidQty * toTrade, hero);
+		LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::CREATURE_RESOURCE, SlotID(bidTradePanel->highlightedSlot->serial), GameResID(offerTradePanel->getSelectedItemId()), bidQty * toTrade, hero);
 		CMarketTraderText::makeDeal();
 		deselect();
 	}

+ 2 - 2
client/widgets/markets/CMarketResources.cpp

@@ -22,7 +22,7 @@
 #include "../../../CCallback.h"
 
 #include "../../../lib/texts/CGeneralTextHandler.h"
-#include "../../../lib/mapObjects/CGMarket.h"
+#include "../../../lib/mapObjects/IMarket.h"
 
 CMarketResources::CMarketResources(const IMarket * market, const CGHeroInstance * hero)
 	: CMarketBase(market, hero)
@@ -60,7 +60,7 @@ void CMarketResources::makeDeal()
 {
 	if(auto toTrade = offerSlider->getValue(); toTrade != 0)
 	{
-		LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_RESOURCE, GameResID(bidTradePanel->getSelectedItemId()),
+		LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_RESOURCE, GameResID(bidTradePanel->getSelectedItemId()),
 			GameResID(offerTradePanel->highlightedSlot->id), bidQty * toTrade, hero);
 		CMarketTraderText::makeDeal();
 		deselect();

+ 2 - 1
client/widgets/markets/CTransferResources.cpp

@@ -22,6 +22,7 @@
 #include "../../../CCallback.h"
 
 #include "../../../lib/texts/CGeneralTextHandler.h"
+#include "../../../lib/mapObjects/IMarket.h"
 #include "../../../lib/texts/MetaString.h"
 
 CTransferResources::CTransferResources(const IMarket * market, const CGHeroInstance * hero)
@@ -63,7 +64,7 @@ void CTransferResources::makeDeal()
 {
 	if(auto toTrade = offerSlider->getValue(); toTrade != 0)
 	{
-		LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_PLAYER, GameResID(bidTradePanel->getSelectedItemId()),
+		LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_PLAYER, GameResID(bidTradePanel->getSelectedItemId()),
 			PlayerColor(offerTradePanel->getSelectedItemId()), toTrade, hero);
 		CMarketTraderText::makeDeal();
 		deselect();

+ 2 - 5
client/windows/CMarketWindow.cpp

@@ -187,9 +187,7 @@ void CMarketWindow::createArtifactsBuying(const IMarket * market, const CGHeroIn
 	OBJECT_CONSTRUCTION;
 
 	background = createBg(ImagePath::builtin("TPMRKABS.bmp"), PLAYER_COLORED);
-	const auto mapObj = dynamic_cast<const CGObjectInstance*>(market);
-	assert(market);
-	marketWidget = std::make_shared<CArtifactsBuying>(market, hero, LOCPLINT->cb->getTown(mapObj->id) ?
+	marketWidget = std::make_shared<CArtifactsBuying>(market, hero, LOCPLINT->cb->getTown(market->getObjInstanceID()) ?
 		VLC->generaltexth->translate("building.core.conflux.special1.name") : CGI->generaltexth->allTexts[349]);
 	initWidgetInternals(EMarketMode::RESOURCE_ARTIFACT, CGI->generaltexth->zelp[600]);
 }
@@ -202,8 +200,7 @@ 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));
-	const auto mapObj = dynamic_cast<const CGObjectInstance*>(market);
-	assert(market);
+	const auto mapObj = LOCPLINT->cb->getObj(market->getObjInstanceID());
 	auto artsSellingMarket = std::make_shared<CArtifactsSelling>(market, hero, LOCPLINT->cb->getTown(mapObj->id) ?
 		VLC->generaltexth->translate("building.core.conflux.special1.name") : mapObj->getObjectName());
 	artSets.clear();

+ 2 - 2
client/windows/GUIClasses.cpp

@@ -819,7 +819,7 @@ void CTransformerWindow::makeDeal()
 	for(auto & elem : items)
 	{
 		if(!elem->left)
-			LOCPLINT->cb->trade(market, EMarketMode::CREATURE_UNDEAD, SlotID(elem->id), {}, {}, hero);
+			LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::CREATURE_UNDEAD, SlotID(elem->id), {}, {}, hero);
 	}
 }
 
@@ -1005,7 +1005,7 @@ void CUniversityWindow::updateSecondarySkills()
 
 void CUniversityWindow::makeDeal(SecondarySkill skill)
 {
-	LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_SKILL, GameResID(GameResID::GOLD), skill, 1, hero);
+	LOCPLINT->cb->trade(market->getObjInstanceID(), EMarketMode::RESOURCE_SKILL, GameResID(GameResID::GOLD), skill, 1, hero);
 }
 
 CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, SecondarySkill SKILL, bool available)

+ 9 - 0
lib/CGameInfoCallback.cpp

@@ -174,6 +174,15 @@ const CGTownInstance* CGameInfoCallback::getTown(ObjectInstanceID objid) const
 		return nullptr;
 }
 
+const IMarket * CGameInfoCallback::getMarket(ObjectInstanceID objid) const
+{
+	const CGObjectInstance * obj = getObj(objid, false);
+	if(obj)
+		return dynamic_cast<const IMarket*>(obj);
+	else
+		return nullptr;
+}
+
 void CGameInfoCallback::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
 {
 	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);

+ 2 - 0
lib/CGameInfoCallback.h

@@ -48,6 +48,7 @@ class CGHeroInstance;
 class CGDwelling;
 class CGTeleport;
 class CGTownInstance;
+class IMarket;
 
 class DLL_LINKAGE IGameInfoCallback : boost::noncopyable
 {
@@ -189,6 +190,7 @@ public:
 	virtual std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
 	virtual const CGObjectInstance * getTopObj (int3 pos) const;
 	virtual PlayerColor getOwner(ObjectInstanceID heroID) const;
+	virtual const IMarket * getMarket(ObjectInstanceID objid) const;
 
 	//map
 	virtual int3 guardingCreaturePosition (int3 pos) const;

+ 1 - 1
lib/IGameCallback.cpp

@@ -287,7 +287,7 @@ CArtifactSet * CNonConstInfoCallback::getArtSet(const ArtifactLocation & loc)
 			return hero;
 		}
 	}
-	else if(auto market = dynamic_cast<IMarket*>(getObjInstance(loc.artHolder)))
+	else if(auto market = getMarket(loc.artHolder))
 	{
 		if(auto artSet = market->getArtifactsStorage())
 			return artSet.get();

+ 5 - 9
lib/mapObjects/CGMarket.cpp

@@ -23,6 +23,11 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+ObjectInstanceID CGMarket::getObjInstanceID() const
+{
+	return id;
+}
+
 void CGMarket::initObj(vstd::RNG & rand)
 {
 	getObjectHandler()->configureObject(this, rand);
@@ -43,13 +48,6 @@ int CGMarket::availableUnits(EMarketMode mode, int marketItemSerial) const
 	return -1;
 }
 
-std::vector<TradeItemBuy> CGMarket::availableItemsIds(EMarketMode mode) const
-{
-	if(allowsTrade(mode))
-		return IMarket::availableItemsIds(mode);
-	return std::vector<TradeItemBuy>();
-}
-
 CGMarket::CGMarket(IGameCallback *cb):
 	CGObjectInstance(cb)
 {}
@@ -58,8 +56,6 @@ std::vector<TradeItemBuy> CGBlackMarket::availableItemsIds(EMarketMode mode) con
 {
 	switch(mode)
 	{
-	case EMarketMode::ARTIFACT_RESOURCE:
-		return IMarket::availableItemsIds(mode);
 	case EMarketMode::RESOURCE_ARTIFACT:
 		{
 			std::vector<TradeItemBuy> ret;

+ 1 - 1
lib/mapObjects/CGMarket.h

@@ -26,9 +26,9 @@ public:
 	void initObj(vstd::RNG & rand) override;//set skills for trade
 
 	///IMarket
+	ObjectInstanceID getObjInstanceID() const override;
 	int getMarketEfficiency() const override;
 	int availableUnits(EMarketMode mode, int marketItemSerial) const override; //-1 if unlimited
-	std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 5 - 0
lib/mapObjects/CGTownInstance.cpp

@@ -710,6 +710,11 @@ std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) co
 		return IMarket::availableItemsIds(mode);
 }
 
+ObjectInstanceID CGTownInstance::getObjInstanceID() const
+{
+	return id;
+}
+
 void CGTownInstance::updateAppearance()
 {
 	auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId();

+ 1 - 1
lib/mapObjects/CGTownInstance.h

@@ -155,7 +155,7 @@ public:
 	const IObjectInterface * getObject() const override;
 	int getMarketEfficiency() const override; //=market count
 	std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
-
+	ObjectInstanceID getObjInstanceID() const override;
 	void updateAppearance();
 
 	//////////////////////////////////////////////////////////////////////////

+ 2 - 2
lib/mapObjects/IMarket.cpp

@@ -22,7 +22,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 bool IMarket::allowsTrade(const EMarketMode mode) const
 {
-	return marketModes.count(mode) > 0;
+	return vstd::contains(marketModes, mode);
 }
 
 bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const
@@ -180,7 +180,7 @@ std::vector<TradeItemBuy> IMarket::availableItemsIds(const EMarketMode mode) con
 	case EMarketMode::RESOURCE_RESOURCE:
 	case EMarketMode::ARTIFACT_RESOURCE:
 	case EMarketMode::CREATURE_RESOURCE:
-		for (auto res : GameResID::ALL_RESOURCES())
+		for(const auto & res : GameResID::ALL_RESOURCES())
 			ret.push_back(res);
 	}
 	return ret;

+ 1 - 0
lib/mapObjects/IMarket.h

@@ -24,6 +24,7 @@ public:
 		ArtBearer::ArtBearer bearerType() const override {return ArtBearer::ALTAR;};
 	};
 
+	virtual ObjectInstanceID getObjInstanceID() const = 0;	// The market is always an object on the map
 	virtual int getMarketEfficiency() const = 0;
 	virtual bool allowsTrade(const EMarketMode mode) const;
 	virtual int availableUnits(const EMarketMode mode, const int marketItemSerial) const; //-1 if unlimited

+ 4 - 6
server/CGameHandler.cpp

@@ -3560,9 +3560,9 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
 				return true;
 		}
 
-		auto market = dynamic_cast<const IMarket*>(o1);
+		auto market = getMarket(id1);
 		if(market == nullptr)
-			market = dynamic_cast<const IMarket*>(o2);
+			market = getMarket(id2);
 		if(market)
 			return market->allowsTrade(EMarketMode::ARTIFACT_EXP);
 
@@ -3917,9 +3917,7 @@ bool CGameHandler::sacrificeArtifact(const IMarket * market, const CGHeroInstanc
 		COMPLAIN_RET("Evil hero can't sacrifice artifact!");
 
 	assert(market);
-	const auto mapObj = dynamic_cast<const CGObjectInstance*>(market);
-	assert(mapObj);
-	const auto artSet = getArtSet(mapObj->id);
+	const auto artSet = market->getArtifactsStorage();
 
 	int expSum = 0;
 	auto finish = [this, &hero, &expSum]()
@@ -3937,7 +3935,7 @@ bool CGameHandler::sacrificeArtifact(const IMarket * market, const CGHeroInstanc
 				int expToGive;
 				market->getOffer(art->getTypeId(), 0, dmp, expToGive, EMarketMode::ARTIFACT_EXP);
 				expSum += expToGive;
-				removeArtifact(ArtifactLocation(mapObj->id, artSet->getArtPos(art)));
+				removeArtifact(ArtifactLocation(market->getObjInstanceID(), artSet->getArtPos(art)));
 			}
 			else
 			{

+ 2 - 2
server/NetPacksServer.cpp

@@ -184,7 +184,7 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
 
 void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
 {
-	if(dynamic_cast<const IMarket*>(gh.getObj(pack.srcHero)) == nullptr)
+	if(gh.getMarket(pack.srcHero) == nullptr)
 		gh.throwIfWrongOwner(&pack, pack.srcHero);
 	if(pack.swap)
 		gh.throwIfWrongOwner(&pack, pack.dstHero);
@@ -250,7 +250,7 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
 {
 	const CGObjectInstance * object = gh.getObj(pack.marketId);
 	const CGHeroInstance * hero = gh.getHero(pack.heroId);
-	const auto * market = dynamic_cast<const IMarket*>(object);
+	const auto * market = gh.getMarket(pack.marketId);
 
 	gh.throwIfWrongPlayer(&pack);
 	gh.throwIfPlayerNotActive(&pack);

+ 3 - 3
test/spells/effects/CatapultTest.cpp

@@ -64,7 +64,7 @@ TEST_F(CatapultTest, NotApplicableInVillage)
 TEST_F(CatapultTest, NotApplicableForDefenderIfSmart)
 {
 	auto fakeTown = std::make_shared<CGTownInstance>(nullptr);
-	fakeTown->builtBuildings.insert(BuildingID::FORT);
+	fakeTown->addBuilding(BuildingID::FORT);
 	mechanicsMock.casterSide = BattleSide::DEFENDER;
 
 	EXPECT_CALL(*battleFake, getDefendedTown()).WillRepeatedly(Return(fakeTown.get()));
@@ -78,7 +78,7 @@ TEST_F(CatapultTest, NotApplicableForDefenderIfSmart)
 TEST_F(CatapultTest, DISABLED_ApplicableInTown)
 {
 	auto fakeTown = std::make_shared<CGTownInstance>(nullptr);
-	fakeTown->builtBuildings.insert(BuildingID::FORT);
+	fakeTown->addBuilding(BuildingID::FORT);
 
 	EXPECT_CALL(*battleFake, getDefendedTown()).WillRepeatedly(Return(fakeTown.get()));
 	EXPECT_CALL(mechanicsMock, adaptProblem(_, _)).Times(0);
@@ -108,7 +108,7 @@ protected:
 	{
 		EffectFixture::setUp();
 		fakeTown = std::make_shared<CGTownInstance>(nullptr);
-		fakeTown->builtBuildings.insert(BuildingID::FORT);
+		fakeTown->addBuilding(BuildingID::FORT);
 	}
 private:
 	std::shared_ptr<CGTownInstance> fakeTown;