diff --git a/client/widgets/CWindowWithArtifacts.cpp b/client/widgets/CWindowWithArtifacts.cpp index 7d6979f5c..a45449b7c 100644 --- a/client/widgets/CWindowWithArtifacts.cpp +++ b/client/widgets/CWindowWithArtifacts.cpp @@ -287,13 +287,7 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const // Transition state. Nothing to do here. Just skip. Need to wait for final state. return; - // When moving one artifact onto another it leads to two art movements: dst->TRANSITION_POS; src->dst - // However after first movement we pick the art from TRANSITION_POS and the second movement coming when - // we have a different artifact may look surprising... but it's valid. - auto pickedArtInst = std::get(curState.value()); - assert(!pickedArtInst || destLoc.artHolder == std::get(curState.value())->id); - auto artifactMovedBody = [this, withRedraw, &destLoc, &pickedArtInst](auto artSetWeak) -> void { auto artSetPtr = artSetWeak.lock(); diff --git a/client/widgets/markets/CArtifactsSelling.cpp b/client/widgets/markets/CArtifactsSelling.cpp index d609d7632..cde332737 100644 --- a/client/widgets/markets/CArtifactsSelling.cpp +++ b/client/widgets/markets/CArtifactsSelling.cpp @@ -34,8 +34,13 @@ CArtifactsSelling::CArtifactsSelling(const IMarket * market, const CGHeroInstanc { OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE); - labels.emplace_back(std::make_shared(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, - (*CGI->townh)[dynamic_cast(market)->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated())); + std::string title; + if(const auto townMarket = dynamic_cast(market)) + title = (*CGI->townh)[townMarket->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated(); + else if(const auto mapMarket = dynamic_cast(market)) + title = mapMarket->title; + + labels.emplace_back(std::make_shared(titlePos.x, titlePos.y, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, title)); labels.push_back(std::make_shared(155, 56, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, boost::str(boost::format(CGI->generaltexth->allTexts[271]) % hero->getNameTranslated()))); deal = std::make_shared(dealButtonPos, AnimationPath::builtin("TPMRKB.DEF"), CGI->generaltexth->zelp[595], [this](){CArtifactsSelling::makeDeal();}); diff --git a/client/windows/CMarketWindow.cpp b/client/windows/CMarketWindow.cpp index 17f9077c6..ce0ce7c2f 100644 --- a/client/windows/CMarketWindow.cpp +++ b/client/windows/CMarketWindow.cpp @@ -202,12 +202,13 @@ void CMarketWindow::createArtifactsSelling(const IMarket * market, const CGHeroI background = createBg(ImagePath::builtin("TPMRKASS.bmp"), PLAYER_COLORED); // Create image that copies part of background containing slot MISC_1 into position of slot MISC_5 - artSlotBack = std::make_shared(background->getSurface(), Rect(20, 187, 47, 47), 18, 339); + artSlotBack = std::make_shared(background->getSurface(), Rect(20, 187, 47, 47), 0, 0); + artSlotBack->moveTo(Point(358, 443)); auto artsSellingMarket = std::make_shared(market, hero); artSets.clear(); addSetAndCallbacks(artsSellingMarket->getAOHset()); 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) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 36c53c832..79ee52d83 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -840,15 +840,18 @@ CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(ArtifactPosition slot, C void CArtifactSet::removeArtifact(ArtifactPosition slot) { - auto art = getArt(slot, false); - if(art) + if(const auto art = getArt(slot, false)) { if(art->isCombined()) { - for(auto & part : art->getPartsInfo()) + for(const auto & part : art->getPartsInfo()) { - if(getArt(part.slot, false)) - eraseArtSlot(part.slot); + if(part.slot != ArtifactPosition::PRE_FIRST) + { + assert(getArt(part.slot, false)); + assert(getArt(part.slot, false) == part.art); + } + eraseArtSlot(part.slot); } } eraseArtSlot(slot); diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index ecb233ff5..0918cfd69 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -757,6 +757,9 @@ bool CGTownInstance::allowsTrade(EMarketMode mode) const case EMarketMode::RESOURCE_SKILL: return hasBuilt(BuildingSubID::MAGIC_UNIVERSITY); + case EMarketMode::CREATURE_EXP: + case EMarketMode::ARTIFACT_EXP: + return false; default: assert(0); return false; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 157ac47fb..f7481887c 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2706,7 +2706,8 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati COMPLAIN_RET("That heroes cannot make any exchange!"); const auto srcArtifact = srcArtSet->getArt(src.slot); - const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtSet->getArt(dst.slot) != nullptr; + const auto dstArtifact = dstArtSet->getArt(dst.slot); + const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtifact != nullptr; const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false; if(srcArtifact == nullptr) @@ -2744,7 +2745,8 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati // Check if dst slot is occupied if(!isDstSlotBackpack && isDstSlotOccupied) { - // Previous artifact must be removed + // Previous artifact must be swapped + COMPLAIN_RET_FALSE_IF(!dstArtifact->canBePutAt(srcArtSet, src.slot, true), "Cannot swap artifacts!"); ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot)); ma.swap = true; }