Selaa lähdekoodia

fixed missed trader text

SoundSSGood 1 vuosi sitten
vanhempi
sitoutus
2cdf2b4083

+ 2 - 2
client/widgets/CArtifactsOfHeroBackpack.cpp

@@ -56,11 +56,11 @@ void CArtifactsOfHeroBackpack::onSliderMoved(int newVal)
 	redraw();
 }
 
-void CArtifactsOfHeroBackpack::updateBackpackSlots(const std::optional<const ArtifactPosition> & removedSlot)
+void CArtifactsOfHeroBackpack::updateBackpackSlots()
 {
 	if(backpackListBox)
 		backpackListBox->resize(getActiveSlotRowsNum());
-	CArtifactsOfHeroBase::updateBackpackSlots(removedSlot);
+	CArtifactsOfHeroBase::updateBackpackSlots();
 }
 
 size_t CArtifactsOfHeroBackpack::getActiveSlotRowsNum()

+ 1 - 1
client/widgets/CArtifactsOfHeroBackpack.h

@@ -25,7 +25,7 @@ public:
 	CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax);
 	CArtifactsOfHeroBackpack();
 	void onSliderMoved(int newVal);
-	void updateBackpackSlots(const std::optional<const ArtifactPosition> & removedSlot = std::nullopt) override;
+	void updateBackpackSlots() override;
 	size_t getActiveSlotRowsNum();
 	size_t getSlotsNum();
 

+ 1 - 1
client/widgets/CArtifactsOfHeroBase.cpp

@@ -180,7 +180,7 @@ void CArtifactsOfHeroBase::updateWornSlots()
 		updateSlot(place.first);
 }
 
-void CArtifactsOfHeroBase::updateBackpackSlots(const std::optional<const ArtifactPosition> & removedSlot)
+void CArtifactsOfHeroBase::updateBackpackSlots()
 {
 	ArtifactPosition slot = ArtifactPosition::BACKPACK_START;
 	for(const auto & artPlace : backpack)

+ 1 - 1
client/widgets/CArtifactsOfHeroBase.h

@@ -41,7 +41,7 @@ public:
 	virtual void unmarkSlots();
 	virtual ArtPlacePtr getArtPlace(const ArtifactPosition & slot);
 	virtual void updateWornSlots();
-	virtual void updateBackpackSlots(const std::optional<const ArtifactPosition> & removedSlot);
+	virtual void updateBackpackSlots();
 	virtual void updateSlot(const ArtifactPosition & slot);
 	virtual const CArtifactInstance * getPickedArtifact();
 	void addGestureCallback(CArtPlace::ClickFunctor callback);

+ 0 - 18
client/widgets/CArtifactsOfHeroMarket.cpp

@@ -25,21 +25,3 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position, const int
 	for(auto artPlace : backpack)
 		artPlace->setSelectionWidth(selectionWidth);
 };
-
-void CArtifactsOfHeroMarket::scrollBackpack(bool left)
-{
-	CArtifactsOfHeroBase::scrollBackpack(left);
-
-	// We may have highlight on one of backpack artifacts
-	if(selectArtCallback)
-	{
-		for(const auto & artPlace : backpack)
-		{
-			if(artPlace->isSelected())
-			{
-				selectArtCallback(artPlace.get());
-				break;
-			}
-		}
-	}
-}

+ 0 - 1
client/widgets/CArtifactsOfHeroMarket.h

@@ -17,5 +17,4 @@ public:
 	std::function<void(const CArtPlace*)> selectArtCallback;
 
 	CArtifactsOfHeroMarket(const Point & position, const int selectionWidth);
-	void scrollBackpack(bool left) override;
 };

+ 5 - 5
client/widgets/CWindowWithArtifacts.cpp

@@ -277,7 +277,7 @@ void CWindowWithArtifacts::gestureArtPlaceHero(CArtifactsOfHeroBase & artsInst,
 
 void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
 {
-	updateSlots(artLoc.slot);
+	updateSlots();
 }
 
 void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw)
@@ -322,7 +322,7 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
 			if(withRedraw)
 			{
 				artSetPtr->updateWornSlots();
-				artSetPtr->updateBackpackSlots(std::nullopt);
+				artSetPtr->updateBackpackSlots();
 
 				// Update arts bonuses on window.
 				// TODO rework this part when CHeroWindow and CExchangeWindow are reworked
@@ -361,14 +361,14 @@ void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation & artLoc)
 	updateSlots();
 }
 
-void CWindowWithArtifacts::updateSlots(const ArtifactPosition & removedSlot)
+void CWindowWithArtifacts::updateSlots()
 {
-	auto updateSlotBody = [removedSlot](auto artSetWeak) -> void
+	auto updateSlotBody = [](auto artSetWeak) -> void
 	{
 		if(const auto artSetPtr = artSetWeak.lock())
 		{
 			artSetPtr->updateWornSlots();
-			artSetPtr->updateBackpackSlots(removedSlot);
+			artSetPtr->updateBackpackSlots();
 			artSetPtr->redraw();
 		}
 	};

+ 1 - 1
client/widgets/CWindowWithArtifacts.h

@@ -46,7 +46,7 @@ protected:
 	std::vector<CArtifactsOfHeroPtr> artSets;
 	CloseCallback closeCallback;
 
-	void updateSlots(const ArtifactPosition & removedSlot = ArtifactPosition::PRE_FIRST);
+	void updateSlots();
 	std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> getState();
 	std::optional<CArtifactsOfHeroPtr> findAOHbyRef(CArtifactsOfHeroBase & artsInst);
 	void markPossibleSlots();

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

@@ -26,7 +26,7 @@
 #include "../../../lib/mapObjects/CGMarket.h"
 
 CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CAltarArtifacts::getSelectionParams();})
+	: CMarketBase(market, hero)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
 
@@ -189,12 +189,12 @@ void CAltarArtifacts::putBackArtifacts()
 		LOCPLINT->cb->bulkMoveArtifacts(altarId, heroArts->getHero()->id, false, true, true);
 }
 
-CMarketBase::SelectionParams CAltarArtifacts::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CAltarArtifacts::getShowcasesParams() const
 {
-	if(offerTradePanel->highlightedSlot)
+	if(offerTradePanel->isHighlighted())
 		return std::make_tuple(
 			std::nullopt,
-			SelectionParamOneSide {std::to_string(offerQty), CGI->artifacts()->getByIndex(offerTradePanel->highlightedSlot->id)->getIconIndex()}
+			ShowcaseParams {std::to_string(offerQty), CGI->artifacts()->getByIndex(offerTradePanel->getSelectedItemId())->getIconIndex()}
 	);
 	return std::make_tuple(std::nullopt, std::nullopt);
 }

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

@@ -33,7 +33,7 @@ private:
 	std::map<std::shared_ptr<CTradeableItem>, const CArtifactInstance*> tradeSlotsMap;
 
 	void updateAltarSlots();
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
 	void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & altarSlot, std::shared_ptr<TradePanelBase> & curPanel) override;
 	TExpType calcExpCost(ArtifactID id) const;
 };

+ 30 - 13
client/widgets/markets/CAltarCreatures.cpp

@@ -25,8 +25,9 @@
 #include "../../../lib/mapObjects/CGMarket.h"
 
 CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CAltarCreatures::getSelectionParams();})
+	: CMarketBase(market, hero)
 	, CMarketSlider(std::bind(&CAltarCreatures::onOfferSliderMoved, this, _1))
+	, CMarketTraderText(Point(28, 31), FONT_MEDIUM, Colors::YELLOW)
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
 
@@ -84,7 +85,7 @@ void CAltarCreatures::readExpValues()
 void CAltarCreatures::highlightingChanged()
 {
 	int sliderAmount = 0;
-	if(bidTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted())
 	{
 		std::optional<SlotID> lastSlot;
 		for(auto slot = SlotID(0); slot.num < GameConstants::ARMY_SIZE; slot++)
@@ -108,10 +109,11 @@ void CAltarCreatures::highlightingChanged()
 	}
 	offerSlider->setAmount(sliderAmount);
 	offerSlider->block(!offerSlider->getAmount());
-	if(bidTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted())
 		offerSlider->scrollTo(unitsOnAltar[bidTradePanel->highlightedSlot->serial]);
 	maxAmount->block(offerSlider->getAmount() == 0);
 	updateShowcases();
+	CMarketTraderText::highlightingChanged();
 }
 
 void CAltarCreatures::update()
@@ -126,6 +128,7 @@ void CAltarCreatures::deselect()
 	CMarketBase::deselect();
 	CExperienceAltar::deselect();
 	CMarketSlider::deselect();
+	CMarketTraderText::deselect();
 }
 
 TExpType CAltarCreatures::calcExpAltarForHero()
@@ -166,14 +169,14 @@ void CAltarCreatures::makeDeal()
 	deselect();
 }
 
-CMarketBase::SelectionParams CAltarCreatures::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CAltarCreatures::getShowcasesParams() const
 {
-	std::optional<SelectionParamOneSide> bidSelected = std::nullopt;
-	std::optional<SelectionParamOneSide> offerSelected = std::nullopt;
-	if(bidTradePanel->highlightedSlot)
-		bidSelected = SelectionParamOneSide {std::to_string(offerSlider->getValue()), CGI->creatures()->getByIndex(bidTradePanel->highlightedSlot->id)->getIconIndex()};
-	if(offerTradePanel->highlightedSlot && offerSlider->getValue() > 0)
-		offerSelected = SelectionParamOneSide { offerTradePanel->highlightedSlot->subtitle->getText(), CGI->creatures()->getByIndex(offerTradePanel->highlightedSlot->id)->getIconIndex()};
+	std::optional<ShowcaseParams> bidSelected = std::nullopt;
+	std::optional<ShowcaseParams> offerSelected = std::nullopt;
+	if(bidTradePanel->isHighlighted())
+		bidSelected = ShowcaseParams {std::to_string(offerSlider->getValue()), CGI->creatures()->getByIndex(bidTradePanel->getSelectedItemId())->getIconIndex()};
+	if(offerTradePanel->isHighlighted() && offerSlider->getValue() > 0)
+		offerSelected = ShowcaseParams { offerTradePanel->highlightedSlot->subtitle->getText(), CGI->creatures()->getByIndex(offerTradePanel->getSelectedItemId())->getIconIndex()};
 	return std::make_tuple(bidSelected, offerSelected);
 }
 
@@ -196,7 +199,7 @@ void CAltarCreatures::sacrificeAll()
 		unitsOnAltar[lastSlot.value().num]--;
 	}
 
-	if(offerTradePanel->highlightedSlot)
+	if(offerTradePanel->isHighlighted())
 		offerSlider->scrollTo(unitsOnAltar[offerTradePanel->highlightedSlot->serial]);
 	offerTradePanel->update();
 	updateShowcases();
@@ -214,9 +217,9 @@ void CAltarCreatures::updateAltarSlot(const std::shared_ptr<CTradeableItem> & sl
 
 void CAltarCreatures::onOfferSliderMoved(int newVal)
 {
-	if(bidTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted())
 		unitsOnAltar[bidTradePanel->highlightedSlot->serial] = newVal;
-	if(offerTradePanel->highlightedSlot)
+	if(offerTradePanel->isHighlighted())
 		updateAltarSlot(offerTradePanel->highlightedSlot);
 	deal->block(calcExpAltarForHero() == 0);
 	highlightingChanged();
@@ -248,3 +251,17 @@ void CAltarCreatures::onSlotClickPressed(const std::shared_ptr<CTradeableItem> &
 	highlightingChanged();
 	redraw();
 }
+
+std::string CAltarCreatures::getTraderText()
+{
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
+	{
+		return boost::str(boost::format(
+			CGI->generaltexth->allTexts[484]) %
+			CGI->creh->objects[bidTradePanel->getSelectedItemId()]->getNamePluralTranslated());
+	}
+	else
+	{
+		return "";
+	}
+}

+ 4 - 2
client/widgets/markets/CAltarCreatures.h

@@ -11,7 +11,8 @@
 
 #include "CMarketBase.h"
 
-class CAltarCreatures : public CExperienceAltar, public CCreaturesSelling, public CMarketSlider
+class CAltarCreatures :
+	public CExperienceAltar, public CCreaturesSelling, public CMarketSlider, public CMarketTraderText
 {
 public:
 	CAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
@@ -25,10 +26,11 @@ private:
 	std::vector<int> unitsOnAltar;
 	std::vector<int> expPerUnit;
 
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
 	void updateAltarSlot(const std::shared_ptr<CTradeableItem> & slot);
 	void readExpValues();
 	void highlightingChanged() override;
 	void onOfferSliderMoved(int newVal) override;
 	void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<TradePanelBase> & curPanel) override;
+	std::string getTraderText() override;
 };

+ 35 - 10
client/widgets/markets/CArtifactsBuying.cpp

@@ -25,7 +25,7 @@
 #include "../../../lib/mapObjects/CGTownInstance.h"
 
 CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CArtifactsBuying::getSelectionParams();})
+	: CMarketBase(market, hero)
 	, CResourcesSelling([this](const std::shared_ptr<CTradeableItem> & heroSlot){CArtifactsBuying::onSlotClickPressed(heroSlot, bidTradePanel);})
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
@@ -34,7 +34,7 @@ CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance
 	if(auto townMarket = dynamic_cast<const CGTownInstance*>(market))
 		title = (*CGI->townh)[townMarket->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated();
 	else
-		title = "Black market";	// find string allTexts!!
+		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();});
@@ -60,32 +60,57 @@ CArtifactsBuying::CArtifactsBuying(const IMarket * market, const CGHeroInstance
 	offerTradePanel->moveTo(pos.topLeft() + Point(328, 181));
 
 	CMarketBase::update();
+	CArtifactsBuying::deselect();
+}
+
+void CArtifactsBuying::deselect()
+{
 	CMarketBase::deselect();
+	CMarketTraderText::deselect();
 }
 
 void CArtifactsBuying::makeDeal()
 {
-	LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_ARTIFACT, GameResID(bidTradePanel->highlightedSlot->id),
+	LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_ARTIFACT, GameResID(bidTradePanel->getSelectedItemId()),
 		ArtifactID(offerTradePanel->highlightedSlot->id), offerQty, hero);
+	CMarketTraderText::makeDeal();
 	deselect();
 }
 
-CMarketBase::SelectionParams CArtifactsBuying::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CArtifactsBuying::getShowcasesParams() const
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 		return std::make_tuple(
-			SelectionParamOneSide {std::to_string(deal->isBlocked() ? 0 : bidQty), bidTradePanel->highlightedSlot->id},
-			SelectionParamOneSide {std::to_string(deal->isBlocked() ? 0 : offerQty), CGI->artifacts()->getByIndex(offerTradePanel->highlightedSlot->id)->getIconIndex()});
+			ShowcaseParams {std::to_string(deal->isBlocked() ? 0 : bidQty), bidTradePanel->getSelectedItemId()},
+			ShowcaseParams {std::to_string(deal->isBlocked() ? 0 : offerQty), CGI->artifacts()->getByIndex(offerTradePanel->getSelectedItemId())->getIconIndex()});
 	else
 		return std::make_tuple(std::nullopt, std::nullopt);
 }
 
 void CArtifactsBuying::highlightingChanged()
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 	{
-		market->getOffer(bidTradePanel->highlightedSlot->id, offerTradePanel->highlightedSlot->id, bidQty, offerQty, EMarketMode::RESOURCE_ARTIFACT);
-		deal->block(LOCPLINT->cb->getResourceAmount(GameResID(bidTradePanel->highlightedSlot->id)) >= bidQty ? false : true);
+		market->getOffer(bidTradePanel->getSelectedItemId(), offerTradePanel->getSelectedItemId(), bidQty, offerQty, EMarketMode::RESOURCE_ARTIFACT);
+		deal->block(LOCPLINT->cb->getResourceAmount(GameResID(bidTradePanel->getSelectedItemId())) >= bidQty ? false : true);
 	}
 	CMarketBase::highlightingChanged();
+	CMarketTraderText::highlightingChanged();
+}
+
+std::string CArtifactsBuying::getTraderText()
+{
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
+	{
+		return boost::str(boost::format(
+			CGI->generaltexth->allTexts[267]) %
+			CGI->artifacts()->getByIndex(offerTradePanel->getSelectedItemId())->getNameTranslated() %
+			bidQty %
+			(bidQty == 1 ? CGI->generaltexth->allTexts[161] : CGI->generaltexth->allTexts[160]) %
+			CGI->generaltexth->restypes[bidTradePanel->getSelectedItemId()]);
+	}
+	else
+	{
+		return madeTransaction ? CGI->generaltexth->allTexts[162] : CGI->generaltexth->allTexts[163];
+	}
 }

+ 4 - 2
client/widgets/markets/CArtifactsBuying.h

@@ -11,13 +11,15 @@
 
 #include "CMarketBase.h"
 
-class CArtifactsBuying : public CResourcesSelling
+class CArtifactsBuying : public CResourcesSelling, public CMarketTraderText
 {
 public:
 	CArtifactsBuying(const IMarket * market, const CGHeroInstance * hero);
+	void deselect() override;
 	void makeDeal() override;
 
 private:
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
 	void highlightingChanged() override;
+	std::string getTraderText() override;
 };

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

@@ -27,10 +27,10 @@
 #include "../../../lib/mapObjects/CGTownInstance.h"
 
 CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CArtifactsSelling::getSelectionParams();})
+	: CMarketBase(market, hero)
 	, CResourcesBuying(
 		[this](const std::shared_ptr<CTradeableItem> & resSlot){CArtifactsSelling::onSlotClickPressed(resSlot, offerTradePanel);},
-		[this](){CMarketBase::updateSubtitlesForBid(EMarketMode::ARTIFACT_RESOURCE, this->hero->getArt(selectedHeroSlot)->getTypeId().num);})
+		[this](){CArtifactsSelling::updateSubtitles();})
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
 
@@ -65,6 +65,7 @@ CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstanc
 void CArtifactsSelling::deselect()
 {
 	CMarketBase::deselect();
+	CMarketTraderText::deselect();
 	selectedHeroSlot = ArtifactPosition::PRE_FIRST;
 	heroArts->unmarkSlots();
 	bidSelectedSlot->clear();
@@ -75,12 +76,13 @@ 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);
+	CMarketTraderText::makeDeal();
 }
 
 void CArtifactsSelling::updateShowcases()
 {
 	const auto art = hero->getArt(selectedHeroSlot);
-	if(art && offerTradePanel->highlightedSlot)
+	if(art && offerTradePanel->isHighlighted())
 	{
 		bidSelectedSlot->image->enable();
 		bidSelectedSlot->setID(art->getTypeId().num);
@@ -99,13 +101,16 @@ void CArtifactsSelling::update()
 	CMarketBase::update();
 	if(selectedHeroSlot != ArtifactPosition::PRE_FIRST)
 	{
-		if(selectedHeroSlot.num >= ArtifactPosition::BACKPACK_START + hero->artifactsInBackpack.size())
+		if(hero->getArt(selectedHeroSlot) == nullptr)
 		{
-			selectedHeroSlot = ArtifactPosition::BACKPACK_START;
 			deselect();
+			selectedHeroSlot = ArtifactPosition::PRE_FIRST;
 		}
-		if(hero->getArt(selectedHeroSlot) == nullptr)
-			deselect();
+		else
+		{
+			heroArts->getArtPlace(selectedHeroSlot)->selectSlot(true);
+		}
+		highlightingChanged();
 	}
 }
 
@@ -114,24 +119,50 @@ std::shared_ptr<CArtifactsOfHeroMarket> CArtifactsSelling::getAOHset() const
 	return heroArts;
 }
 
-CMarketBase::SelectionParams CArtifactsSelling::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CArtifactsSelling::getShowcasesParams() const
 {
-	if(hero->getArt(selectedHeroSlot) && offerTradePanel->highlightedSlot)
+	if(hero->getArt(selectedHeroSlot) && offerTradePanel->isHighlighted())
 		return std::make_tuple(
 			std::nullopt,
-			SelectionParamOneSide {std::to_string(offerQty), offerTradePanel->getSelectedItemId()}
+			ShowcaseParams {std::to_string(offerQty), offerTradePanel->getSelectedItemId()}
 		);
 	else
 		return std::make_tuple(std::nullopt, std::nullopt);
 }
 
+void CArtifactsSelling::updateSubtitles()
+{
+	const auto art = this->hero->getArt(selectedHeroSlot);
+	const int bidId = art == nullptr ? -1 : art->getTypeId().num;
+	CMarketBase::updateSubtitlesForBid(EMarketMode::ARTIFACT_RESOURCE, bidId);
+}
+
 void CArtifactsSelling::highlightingChanged()
 {
 	const auto art = hero->getArt(selectedHeroSlot);
-	if(art && offerTradePanel->highlightedSlot)
+	if(art && offerTradePanel->isHighlighted())
 	{
 		market->getOffer(art->getTypeId(), offerTradePanel->getSelectedItemId(), bidQty, offerQty, EMarketMode::ARTIFACT_RESOURCE);
 		deal->block(false);
 	}
 	CMarketBase::highlightingChanged();
+	CMarketTraderText::highlightingChanged();
+}
+
+std::string CArtifactsSelling::getTraderText()
+{
+	const auto art = hero->getArt(selectedHeroSlot);
+	if(art && offerTradePanel->isHighlighted())
+	{
+		return boost::str(boost::format(
+			CGI->generaltexth->allTexts[268]) %
+			offerQty %
+			(offerQty == 1 ? CGI->generaltexth->allTexts[161] : CGI->generaltexth->allTexts[160]) %
+			CGI->generaltexth->restypes[offerTradePanel->getSelectedItemId()] %
+			CGI->artifacts()->getByIndex(art->getTypeId())->getNameTranslated());
+	}
+	else
+	{
+		return madeTransaction ? CGI->generaltexth->allTexts[162] : CGI->generaltexth->allTexts[163];
+	}
 }

+ 4 - 2
client/widgets/markets/CArtifactsSelling.h

@@ -12,7 +12,7 @@
 #include "../CArtifactsOfHeroMarket.h"
 #include "CMarketBase.h"
 
-class CArtifactsSelling : public CResourcesBuying
+class CArtifactsSelling : public CResourcesBuying, public CMarketTraderText
 {
 public:
 	CArtifactsSelling(const IMarket * market, const CGHeroInstance * hero);
@@ -28,6 +28,8 @@ private:
 	std::shared_ptr<CTradeableItem> bidSelectedSlot;
 	ArtifactPosition selectedHeroSlot;
 
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
+	void updateSubtitles();
 	void highlightingChanged() override;
+	std::string getTraderText() override;
 };

+ 31 - 10
client/widgets/markets/CFreelancerGuild.cpp

@@ -23,10 +23,9 @@
 #include "../../../lib/CGeneralTextHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
 #include "../../../lib/mapObjects/CGMarket.h"
-#include "../../../lib/mapObjects/CGTownInstance.h"
 
 CFreelancerGuild::CFreelancerGuild(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CFreelancerGuild::getSelectionParams();})
+	: CMarketBase(market, hero)
 	, CResourcesBuying(
 		[this](const std::shared_ptr<CTradeableItem> & heroSlot){CFreelancerGuild::onSlotClickPressed(heroSlot, offerTradePanel);},
 		[this](){CMarketBase::updateSubtitlesForBid(EMarketMode::CREATURE_RESOURCE, bidTradePanel->getSelectedItemId());})
@@ -35,7 +34,7 @@ CFreelancerGuild::CFreelancerGuild(const IMarket * market, const CGHeroInstance
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
 
 	labels.emplace_back(std::make_shared<CLabel>(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW,
-		(*CGI->townh)[ETownType::STRONGHOLD]->town->buildings[BuildingID::FREELANCERS_GUILD]->getNameTranslated()));
+		VLC->generaltexth->translate("object.core.freelancersGuild.name")));
 	labels.emplace_back(std::make_shared<CLabel>(155, 103, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE,
 		boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->getNameTranslated())));
 	deal = std::make_shared<CButton>(dealButtonPosWithSlider, AnimationPath::builtin("TPMRKB.DEF"),
@@ -62,32 +61,34 @@ void CFreelancerGuild::deselect()
 {
 	CMarketBase::deselect();
 	CMarketSlider::deselect();
+	CMarketTraderText::deselect();
 }
 
 void CFreelancerGuild::makeDeal()
 {
 	if(auto toTrade = offerSlider->getValue(); toTrade != 0)
 	{
-		LOCPLINT->cb->trade(market, EMarketMode::CREATURE_RESOURCE, SlotID(bidTradePanel->highlightedSlot->serial), GameResID(offerTradePanel->highlightedSlot->id), bidQty * toTrade, hero);
+		LOCPLINT->cb->trade(market, EMarketMode::CREATURE_RESOURCE, SlotID(bidTradePanel->highlightedSlot->serial), GameResID(offerTradePanel->getSelectedItemId()), bidQty * toTrade, hero);
+		CMarketTraderText::makeDeal();
 		deselect();
 	}
 }
 
-CMarketBase::SelectionParams CFreelancerGuild::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CFreelancerGuild::getShowcasesParams() const
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 		return std::make_tuple(
-			SelectionParamOneSide {std::to_string(bidQty * offerSlider->getValue()), CGI->creatures()->getByIndex(bidTradePanel->highlightedSlot->id)->getIconIndex()},
-			SelectionParamOneSide {std::to_string(offerQty * offerSlider->getValue()), offerTradePanel->highlightedSlot->id});
+			ShowcaseParams {std::to_string(bidQty * offerSlider->getValue()), CGI->creatures()->getByIndex(bidTradePanel->getSelectedItemId())->getIconIndex()},
+			ShowcaseParams {std::to_string(offerQty * offerSlider->getValue()), offerTradePanel->getSelectedItemId()});
 	else
 		return std::make_tuple(std::nullopt, std::nullopt);
 }
 
 void CFreelancerGuild::highlightingChanged()
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 	{
-		market->getOffer(bidTradePanel->highlightedSlot->id, offerTradePanel->highlightedSlot->id, bidQty, offerQty, EMarketMode::CREATURE_RESOURCE);
+		market->getOffer(bidTradePanel->getSelectedItemId(), offerTradePanel->getSelectedItemId(), bidQty, offerQty, EMarketMode::CREATURE_RESOURCE);
 		offerSlider->setAmount((hero->getStackCount(SlotID(bidTradePanel->highlightedSlot->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack() ? 1 : 0)) / bidQty);
 		offerSlider->scrollTo(0);
 		offerSlider->block(false);
@@ -95,4 +96,24 @@ void CFreelancerGuild::highlightingChanged()
 		deal->block(false);
 	}
 	CMarketBase::highlightingChanged();
+	CMarketTraderText::highlightingChanged();
+}
+
+std::string CFreelancerGuild::getTraderText()
+{
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
+	{
+		return boost::str(boost::format(
+			CGI->generaltexth->allTexts[269]) %
+			offerQty %
+			(offerQty == 1 ? CGI->generaltexth->allTexts[161] : CGI->generaltexth->allTexts[160]) %
+			CGI->generaltexth->restypes[offerTradePanel->getSelectedItemId()] %
+			bidQty %
+			(bidQty == 1 ? CGI->creh->objects[bidTradePanel->getSelectedItemId()]->getNameSingularTranslated() :
+				CGI->creh->objects[bidTradePanel->getSelectedItemId()]->getNamePluralTranslated()));
+	}
+	else
+	{
+		return madeTransaction ? CGI->generaltexth->allTexts[162] : CGI->generaltexth->allTexts[163];
+	}
 }

+ 4 - 2
client/widgets/markets/CFreelancerGuild.h

@@ -11,7 +11,8 @@
 
 #include "CMarketBase.h"
 
-class CFreelancerGuild : public CCreaturesSelling , public CResourcesBuying, public CMarketSlider
+class CFreelancerGuild :
+	public CCreaturesSelling , public CResourcesBuying, public CMarketSlider, public CMarketTraderText
 {
 public:
 	CFreelancerGuild(const IMarket * market, const CGHeroInstance * hero);
@@ -19,6 +20,7 @@ public:
 	void makeDeal() override;
 
 private:
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
 	void highlightingChanged() override;
+	std::string getTraderText() override;
 };

+ 26 - 5
client/widgets/markets/CMarketBase.cpp

@@ -27,10 +27,9 @@
 #include "../../../lib/CHeroHandler.h"
 #include "../../../lib/mapObjects/CGMarket.h"
 
-CMarketBase::CMarketBase(const IMarket * market, const CGHeroInstance * hero, const SelectionParamsFunctor & getParamsCallback)
+CMarketBase::CMarketBase(const IMarket * market, const CGHeroInstance * hero)
 	: market(market)
 	, hero(hero)
-	, selectionParamsCallback(getParamsCallback)
 {
 }
 
@@ -93,7 +92,7 @@ void CMarketBase::updateSubtitlesForBid(EMarketMode marketMode, int bidId)
 
 void CMarketBase::updateShowcases()
 {
-	const auto updateSelectedBody = [](const std::shared_ptr<TradePanelBase> & tradePanel, const std::optional<const SelectionParamOneSide> & params)
+	const auto updateSelectedBody = [](const std::shared_ptr<TradePanelBase> & tradePanel, const std::optional<const ShowcaseParams> & params)
 	{
 		if(params.has_value())
 		{
@@ -107,8 +106,7 @@ void CMarketBase::updateShowcases()
 		}
 	};
 
-	assert(selectionParamsCallback);
-	const auto params = selectionParamsCallback();
+	const auto params = getShowcasesParams();
 	if(bidTradePanel)
 		updateSelectedBody(bidTradePanel, std::get<0>(params));
 	if(offerTradePanel)
@@ -221,3 +219,26 @@ void CMarketSlider::onOfferSliderMoved(int newVal)
 		redraw();
 	}
 }
+
+CMarketTraderText::CMarketTraderText(const Point & pos, const EFonts & font, const ColorRGBA & color)
+	: madeTransaction(false)
+{
+	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
+
+	traderText = std::make_shared<CTextBox>("", Rect(pos, traderTextDimensions), 0, font, ETextAlignment::CENTER, color);
+}
+
+void CMarketTraderText::deselect()
+{
+	highlightingChanged();
+}
+
+void CMarketTraderText::makeDeal()
+{
+	madeTransaction = true;
+}
+
+void CMarketTraderText::highlightingChanged()
+{
+	traderText->setText(getTraderText());
+}

+ 23 - 10
client/widgets/markets/CMarketBase.h

@@ -11,27 +11,25 @@
 
 #include "TradePanels.h"
 #include "../../widgets/Slider.h"
+#include "../../render/EFont.h"
+#include "../../render/Colors.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
 class IMarket;
-class CGHeroInstance;
 
 VCMI_LIB_NAMESPACE_END
 
-class CButton;
-class CSlider;
-
 class CMarketBase : public CIntObject
 {
 public:
-	struct SelectionParamOneSide
+	struct ShowcaseParams
 	{
 		std::string text;
 		int imageIndex;
 	};
-	using SelectionParams = std::tuple<std::optional<const SelectionParamOneSide>, std::optional<const SelectionParamOneSide>>;
-	using SelectionParamsFunctor = std::function<const SelectionParams()>;
+	using MarketShowcasesParams = std::tuple<std::optional<const ShowcaseParams>, std::optional<const ShowcaseParams>>;
+	using ShowcasesParamsFunctor = std::function<const MarketShowcasesParams()>;
 
 	const IMarket * market;
 	const CGHeroInstance * hero;
@@ -42,13 +40,12 @@ public:
 	std::shared_ptr<CButton> deal;
 	std::vector<std::shared_ptr<CLabel>> labels;
 	std::vector<std::shared_ptr<CTextBox>> texts;
-	SelectionParamsFunctor selectionParamsCallback;
 	int bidQty;
 	int offerQty;
 	const Point dealButtonPos = Point(270, 520);
 	const Point titlePos = Point(299, 27);
 
-	CMarketBase(const IMarket * market, const CGHeroInstance * hero, const SelectionParamsFunctor & getParamsCallback);
+	CMarketBase(const IMarket * market, const CGHeroInstance * hero);
 	virtual void makeDeal() = 0;
 	virtual void deselect();
 	virtual void update();
@@ -57,7 +54,7 @@ protected:
 	virtual void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<TradePanelBase> & curPanel);
 	virtual void updateSubtitlesForBid(EMarketMode marketMode, int bidId);
 	virtual void updateShowcases();
-	virtual SelectionParams getSelectionParams() const = 0;
+	virtual MarketShowcasesParams getShowcasesParams() const = 0;
 	virtual void highlightingChanged();
 };
 
@@ -109,3 +106,19 @@ public:
 	void deselect() override;
 	virtual void onOfferSliderMoved(int newVal);
 };
+
+class CMarketTraderText : virtual public CMarketBase
+{
+public:
+	CMarketTraderText(const Point & pos = Point(316, 48), const EFonts & font = EFonts::FONT_SMALL, const ColorRGBA & Color = Colors::WHITE);
+	void deselect() override;
+	void makeDeal() override;
+
+	const Point traderTextDimensions = Point(260, 75);
+	std::shared_ptr<CTextBox> traderText;
+	bool madeTransaction;
+
+protected:
+	void highlightingChanged() override;
+	virtual std::string getTraderText() = 0;
+};

+ 29 - 6
client/widgets/markets/CMarketResources.cpp

@@ -24,7 +24,7 @@
 #include "../../../lib/mapObjects/CGMarket.h"
 
 CMarketResources::CMarketResources(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CMarketResources::getSelectionParams();})
+	: CMarketBase(market, hero)
 	, CResourcesSelling([this](const std::shared_ptr<CTradeableItem> & heroSlot){CMarketResources::onSlotClickPressed(heroSlot, bidTradePanel);})
 	, CResourcesBuying(
 		[this](const std::shared_ptr<CTradeableItem> & resSlot){CMarketResources::onSlotClickPressed(resSlot, offerTradePanel);},
@@ -52,6 +52,7 @@ void CMarketResources::deselect()
 {
 	CMarketBase::deselect();
 	CMarketSlider::deselect();
+	CMarketTraderText::deselect();
 }
 
 void CMarketResources::makeDeal()
@@ -60,25 +61,26 @@ void CMarketResources::makeDeal()
 	{
 		LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_RESOURCE, GameResID(bidTradePanel->getSelectedItemId()),
 			GameResID(offerTradePanel->highlightedSlot->id), bidQty * toTrade, hero);
+		CMarketTraderText::makeDeal();
 		deselect();
 	}
 }
 
-CMarketBase::SelectionParams CMarketResources::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CMarketResources::getShowcasesParams() const
 {
 	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot && bidTradePanel->getSelectedItemId() != offerTradePanel->getSelectedItemId())
 		return std::make_tuple(
-			SelectionParamOneSide {std::to_string(bidQty * offerSlider->getValue()), bidTradePanel->getSelectedItemId()},
-			SelectionParamOneSide {std::to_string(offerQty * offerSlider->getValue()), offerTradePanel->getSelectedItemId()});
+			ShowcaseParams {std::to_string(bidQty * offerSlider->getValue()), bidTradePanel->getSelectedItemId()},
+			ShowcaseParams {std::to_string(offerQty * offerSlider->getValue()), offerTradePanel->getSelectedItemId()});
 	else
 		return std::make_tuple(std::nullopt, std::nullopt);
 }
 
 void CMarketResources::highlightingChanged()
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 	{
-		market->getOffer(bidTradePanel->getSelectedItemId(), offerTradePanel->highlightedSlot->id, bidQty, offerQty, EMarketMode::RESOURCE_RESOURCE);
+		market->getOffer(bidTradePanel->getSelectedItemId(), offerTradePanel->getSelectedItemId(), bidQty, offerQty, EMarketMode::RESOURCE_RESOURCE);
 		offerSlider->setAmount(LOCPLINT->cb->getResourceAmount(GameResID(bidTradePanel->getSelectedItemId())) / bidQty);
 		offerSlider->scrollTo(0);
 		const bool isControlsBlocked = bidTradePanel->getSelectedItemId() != offerTradePanel->getSelectedItemId() ? false : true;
@@ -87,6 +89,7 @@ void CMarketResources::highlightingChanged()
 		deal->block(isControlsBlocked);
 	}
 	CMarketBase::highlightingChanged();
+	CMarketTraderText::highlightingChanged();
 }
 
 void CMarketResources::updateSubtitles()
@@ -95,3 +98,23 @@ void CMarketResources::updateSubtitles()
 	if(bidTradePanel->highlightedSlot)
 		offerTradePanel->slots[bidTradePanel->highlightedSlot->serial]->subtitle->setText(CGI->generaltexth->allTexts[164]); // n/a
 }
+
+std::string CMarketResources::getTraderText()
+{
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted() &&
+		bidTradePanel->getSelectedItemId() != offerTradePanel->getSelectedItemId())
+	{
+		return boost::str(boost::format(
+			CGI->generaltexth->allTexts[157]) %
+			offerQty %
+			(offerQty == 1 ? CGI->generaltexth->allTexts[161] : CGI->generaltexth->allTexts[160]) %
+			CGI->generaltexth->restypes[bidTradePanel->getSelectedItemId()] %
+			bidQty %
+			(bidQty == 1 ? CGI->generaltexth->allTexts[161] : CGI->generaltexth->allTexts[160]) %
+			CGI->generaltexth->restypes[offerTradePanel->getSelectedItemId()]);
+	}
+	else
+	{
+		return madeTransaction ? CGI->generaltexth->allTexts[162] : CGI->generaltexth->allTexts[163];
+	}
+}

+ 4 - 2
client/widgets/markets/CMarketResources.h

@@ -11,7 +11,8 @@
 
 #include "CMarketBase.h"
 
-class CMarketResources : public CResourcesSelling, public CResourcesBuying, public CMarketSlider
+class CMarketResources :
+	public CResourcesSelling, public CResourcesBuying, public CMarketSlider, public CMarketTraderText
 {
 public:
 	CMarketResources(const IMarket * market, const CGHeroInstance * hero);
@@ -19,7 +20,8 @@ public:
 	void makeDeal() override;
 
 private:
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
 	void highlightingChanged() override;
 	void updateSubtitles();
+	std::string getTraderText() override;
 };

+ 26 - 7
client/widgets/markets/CTransferResources.cpp

@@ -23,9 +23,10 @@
 #include "../../../lib/CGeneralTextHandler.h"
 
 CTransferResources::CTransferResources(const IMarket * market, const CGHeroInstance * hero)
-	: CMarketBase(market, hero, [this](){return CTransferResources::getSelectionParams();})
+	: CMarketBase(market, hero)
 	, CResourcesSelling([this](const std::shared_ptr<CTradeableItem> & heroSlot){CTransferResources::onSlotClickPressed(heroSlot, bidTradePanel);})
 	, CMarketSlider([this](int newVal){CMarketSlider::onOfferSliderMoved(newVal);})
+	, CMarketTraderText(Point(28, 48))
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
 
@@ -53,6 +54,7 @@ void CTransferResources::deselect()
 {
 	CMarketBase::deselect();
 	CMarketSlider::deselect();
+	CMarketTraderText::deselect();
 }
 
 void CTransferResources::makeDeal()
@@ -60,24 +62,25 @@ void CTransferResources::makeDeal()
 	if(auto toTrade = offerSlider->getValue(); toTrade != 0)
 	{
 		LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_PLAYER, GameResID(bidTradePanel->getSelectedItemId()),
-			PlayerColor(offerTradePanel->highlightedSlot->id), toTrade, hero);
+			PlayerColor(offerTradePanel->getSelectedItemId()), toTrade, hero);
+		CMarketTraderText::makeDeal();
 		deselect();
 	}
 }
 
-CMarketBase::SelectionParams CTransferResources::getSelectionParams() const
+CMarketBase::MarketShowcasesParams CTransferResources::getShowcasesParams() const
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 		return std::make_tuple(
-			SelectionParamOneSide {std::to_string(offerSlider->getValue()), bidTradePanel->getSelectedItemId()},
-			SelectionParamOneSide {CGI->generaltexth->capColors[offerTradePanel->highlightedSlot->id], offerTradePanel->getSelectedItemId()});
+			ShowcaseParams {std::to_string(offerSlider->getValue()), bidTradePanel->getSelectedItemId()},
+			ShowcaseParams {CGI->generaltexth->capColors[offerTradePanel->getSelectedItemId()], offerTradePanel->getSelectedItemId()});
 	else
 		return std::make_tuple(std::nullopt, std::nullopt);
 }
 
 void CTransferResources::highlightingChanged()
 {
-	if(bidTradePanel->highlightedSlot && offerTradePanel->highlightedSlot)
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
 	{
 		offerSlider->setAmount(LOCPLINT->cb->getResourceAmount(GameResID(bidTradePanel->getSelectedItemId())));
 		offerSlider->scrollTo(0);
@@ -86,4 +89,20 @@ void CTransferResources::highlightingChanged()
 		deal->block(false);
 	}
 	CMarketBase::highlightingChanged();
+	CMarketTraderText::highlightingChanged();
+}
+
+std::string CTransferResources::getTraderText()
+{
+	if(bidTradePanel->isHighlighted() && offerTradePanel->isHighlighted())
+	{
+		return boost::str(boost::format(
+			CGI->generaltexth->allTexts[165]) %
+			CGI->generaltexth->restypes[bidTradePanel->getSelectedItemId()] %
+			CGI->generaltexth->capColors[offerTradePanel->getSelectedItemId()]);
+	}
+	else
+	{
+		return madeTransaction ? CGI->generaltexth->allTexts[166] : CGI->generaltexth->allTexts[167];
+	}
 }

+ 3 - 2
client/widgets/markets/CTransferResources.h

@@ -11,7 +11,7 @@
 
 #include "CMarketBase.h"
 
-class CTransferResources : public CResourcesSelling, public CMarketSlider
+class CTransferResources : public CResourcesSelling, public CMarketSlider, public CMarketTraderText
 {
 public:
 	CTransferResources(const IMarket * market, const CGHeroInstance * hero);
@@ -19,6 +19,7 @@ public:
 	void makeDeal() override;
 
 private:
-	CMarketBase::SelectionParams getSelectionParams() const override;
+	CMarketBase::MarketShowcasesParams getShowcasesParams() const override;
 	void highlightingChanged() override;
+	std::string getTraderText() override;
 };

+ 6 - 1
client/widgets/markets/TradePanels.cpp

@@ -160,7 +160,7 @@ void CTradeableItem::clickPressed(const Point & cursorPosition)
 
 void CTradeableItem::hover(bool on)
 {
-	if(!on)
+	if(!on || id == -1)
 	{
 		GH.statusbar()->clear();
 		return;
@@ -261,6 +261,11 @@ void TradePanelBase::onSlotClickPressed(const std::shared_ptr<CTradeableItem> &
 	newSlot->selectSlot(true);
 }
 
+bool TradePanelBase::isHighlighted() const
+{
+	return getSelectedItemId() != -1;
+}
+
 ResourcesPanel::ResourcesPanel(const CTradeableItem::ClickPressedFunctor & clickPressedCallback,
 	const UpdateSlotsFunctor & updateSubtitles)
 {

+ 1 - 0
client/widgets/markets/TradePanels.h

@@ -63,6 +63,7 @@ public:
 	void setShowcaseSubtitle(const std::string & text);
 	int getSelectedItemId() const;
 	void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot);
+	bool isHighlighted() const;
 };
 
 class ResourcesPanel : public TradePanelBase

+ 1 - 1
client/windows/CMarketWindow.cpp

@@ -108,9 +108,9 @@ void CMarketWindow::artifactMoved(const ArtifactLocation & srcLoc, const Artifac
 {
 	if(!getState().has_value())
 		return;
+	CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw);
 	assert(marketWidget);
 	marketWidget->update();
-	CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw);
 }
 
 void CMarketWindow::createChangeModeButtons(EMarketMode currentMode, const IMarket * market, const CGHeroInstance * hero)