瀏覽代碼

CArtifactSet cleanup

SoundSSGood 1 年之前
父節點
當前提交
586a32a616

+ 1 - 1
client/battle/BattleWindow.cpp

@@ -743,7 +743,7 @@ void BattleWindow::bSpellf()
 			const auto artID = blockingBonus->sid.as<ArtifactID>();
 			//If we have artifact, put name of our hero. Otherwise assume it's the enemy.
 			//TODO check who *really* is source of bonus
-			std::string heroName = myHero->hasArt(artID) ? myHero->getNameTranslated() : owner.enemyHero().name;
+			std::string heroName = myHero->hasArt(artID, true) ? myHero->getNameTranslated() : owner.enemyHero().name;
 
 			//%s wields the %s, an ancient artifact which creates a p dead to all magic.
 			LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[683])

+ 1 - 1
client/widgets/CArtifactsOfHeroBase.cpp

@@ -271,7 +271,7 @@ void CArtifactsOfHeroBase::setSlotData(ArtPlacePtr artPlace, const ArtifactPosit
 			arts.try_emplace(combinedArt->getId(), std::vector<ArtifactID>{});
 			for(const auto part : combinedArt->getConstituents())
 			{
-				if(curHero->hasArt(part->getId(), false, false, false))
+				if(curHero->hasArt(part->getId(), false, false))
 					arts.at(combinedArt->getId()).emplace_back(part->getId());
 			}
 		}

+ 1 - 1
lib/ArtifactUtils.cpp

@@ -209,7 +209,7 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
 
 		for(const auto constituent : artifact->getConstituents()) //check if all constituents are available
 		{
-			if(!artSet->hasArt(constituent->getId(), onlyEquiped, false, false))
+			if(!artSet->hasArt(constituent->getId(), onlyEquiped, false))
 			{
 				possible = false;
 				break;

+ 59 - 103
lib/CArtHandler.cpp

@@ -220,7 +220,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b
 				auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId());
 				if(ArtifactUtils::isSlotEquipment(possibleSlot))
 				{
-					fittingSet.setNewArtSlot(possibleSlot, nullptr, true);
+					fittingSet.lockSlot(possibleSlot);
 				}
 				else
 				{
@@ -691,9 +691,7 @@ void CArtHandler::afterLoadFinalization()
 	CBonusSystemNode::treeHasChanged();
 }
 
-CArtifactSet::~CArtifactSet() = default;
-
-const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const
+CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const
 {
 	if(const ArtSlotInfo * si = getSlot(pos))
 	{
@@ -704,56 +702,34 @@ const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, boo
 	return nullptr;
 }
 
-CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked)
-{
-	return const_cast<CArtifactInstance*>((const_cast<const CArtifactSet*>(this))->getArt(pos, excludeLocked));
-}
-
 ArtifactPosition CArtifactSet::getArtPos(const ArtifactID & aid, bool onlyWorn, bool allowLocked) const
 {
-	const auto result = getAllArtPositions(aid, onlyWorn, allowLocked, false);
-	return result.empty() ? ArtifactPosition{ArtifactPosition::PRE_FIRST} : result[0];
-}
-
-std::vector<ArtifactPosition> CArtifactSet::getAllArtPositions(const ArtifactID & aid, bool onlyWorn, bool allowLocked, bool getAll) const
-{
-	std::vector<ArtifactPosition> result;
-	for(const auto & slotInfo : artifactsWorn)
-		if(slotInfo.second.artifact->getTypeId() == aid && (allowLocked || !slotInfo.second.locked))
-			result.push_back(slotInfo.first);
-
-	if(onlyWorn)
-		return result;
-	if(!getAll && !result.empty())
-		return result;
-
-	auto backpackPositions = getBackpackArtPositions(aid);
-	result.insert(result.end(), backpackPositions.begin(), backpackPositions.end());
-	return result;
-}
-
-std::vector<ArtifactPosition> CArtifactSet::getBackpackArtPositions(const ArtifactID & aid) const
-{
-	std::vector<ArtifactPosition> result;
-
-	si32 backpackPosition = ArtifactPosition::BACKPACK_START;
-	for(const auto & artInfo : artifactsInBackpack)
+	for(const auto & [slot, slotInfo] : artifactsWorn)
 	{
-		const auto * art = artInfo.getArt();
-		if(art && art->artType->getId() == aid)
-			result.emplace_back(backpackPosition);
-		backpackPosition++;
+		if(slotInfo.artifact->getTypeId() == aid && (allowLocked || !slotInfo.locked))
+			return slot;
+	}
+	if(!onlyWorn)
+	{
+		size_t backpackPositionIdx = ArtifactPosition::BACKPACK_START;
+		for(const auto & artInfo : artifactsInBackpack)
+		{
+			const auto art = artInfo.getArt();
+			if(art && art->artType->getId() == aid)
+				return ArtifactPosition(backpackPositionIdx);
+			backpackPositionIdx++;
+		}
 	}
-	return result;
+	return ArtifactPosition::PRE_FIRST;
 }
 
 const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const
 {
-	for(auto i : artifactsWorn)
+	for(const auto & i : artifactsWorn)
 		if(i.second.artifact->getId() == artInstId)
 			return i.second.artifact;
 
-	for(auto i : artifactsInBackpack)
+	for(const auto & i : artifactsInBackpack)
 		if(i.artifact->getId() == artInstId)
 			return i.artifact;
 
@@ -779,29 +755,16 @@ ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance * artInst) cons
 	return ArtifactPosition::PRE_FIRST;
 }
 
-bool CArtifactSet::hasArt(const ArtifactID & aid, bool onlyWorn, bool searchBackpackAssemblies, bool allowLocked) const
-{
-	return getArtPosCount(aid, onlyWorn, searchBackpackAssemblies, allowLocked) > 0;
-}
-
-bool CArtifactSet::hasArtBackpack(const ArtifactID & aid) const
+bool CArtifactSet::hasArt(const ArtifactID & aid, bool onlyWorn, bool searchCombinedParts) const
 {
-	return !getBackpackArtPositions(aid).empty();
-}
-
-unsigned CArtifactSet::getArtPosCount(const ArtifactID & aid, bool onlyWorn, bool searchBackpackAssemblies, bool allowLocked) const
-{
-	const auto allPositions = getAllArtPositions(aid, onlyWorn, allowLocked, true);
-	if(!allPositions.empty())
-		return allPositions.size();
-
-	if(searchBackpackAssemblies && getHiddenArt(aid))
-		return 1;
-
-	return 0;
+	if(searchCombinedParts && getCombinedArtWithPart(aid))
+		return true;
+	if(getArtPos(aid, onlyWorn, searchCombinedParts) != ArtifactPosition::PRE_FIRST)
+		return true;
+	return false;
 }
 
-CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
+CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition & slot, CArtifactInstance * art)
 {
 	ArtPlacementMap resArtPlacement;
 
@@ -827,19 +790,38 @@ CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(ArtifactPosition slot, C
 
 				assert(ArtifactUtils::isSlotEquipment(partSlot));
 				setNewArtSlot(partSlot, part.art, true);
-				resArtPlacement.emplace(std::make_pair(part.art, partSlot));
+				resArtPlacement.emplace(part.art, partSlot);
 			}
 			else
 			{
-				resArtPlacement.emplace(std::make_pair(part.art, part.slot));
+				resArtPlacement.emplace(part.art, part.slot);
 			}
 		}
 	}
 	return resArtPlacement;
 }
 
-void CArtifactSet::removeArtifact(ArtifactPosition slot)
+void CArtifactSet::removeArtifact(const ArtifactPosition & slot)
 {
+	const auto eraseArtSlot = [this](const ArtifactPosition & slotForErase)
+	{
+		if(slotForErase == ArtifactPosition::TRANSITION_POS)
+		{
+			artifactsTransitionPos.artifact = nullptr;
+		}
+		else if(ArtifactUtils::isSlotBackpack(slotForErase))
+		{
+			auto backpackSlot = ArtifactPosition(slotForErase - ArtifactPosition::BACKPACK_START);
+
+			assert(artifactsInBackpack.begin() + backpackSlot < artifactsInBackpack.end());
+			artifactsInBackpack.erase(artifactsInBackpack.begin() + backpackSlot);
+		}
+		else
+		{
+			artifactsWorn.erase(slotForErase);
+		}
+	};
+
 	if(const auto art = getArt(slot, false))
 	{
 		if(art->isCombined())
@@ -858,7 +840,7 @@ void CArtifactSet::removeArtifact(ArtifactPosition slot)
 	}
 }
 
-std::pair<const CArtifactInstance *, const CArtifactInstance *> CArtifactSet::searchForConstituent(const ArtifactID & aid) const
+const CArtifactInstance * CArtifactSet::getCombinedArtWithPart(const ArtifactID & partId) const
 {
 	for(const auto & slot : artifactsInBackpack)
 	{
@@ -867,24 +849,12 @@ std::pair<const CArtifactInstance *, const CArtifactInstance *> CArtifactSet::se
 		{
 			for(auto & ci : art->getPartsInfo())
 			{
-				if(ci.art->getTypeId() == aid)
-				{
-					return {art, ci.art};
-				}
+				if(ci.art->getTypeId() == partId)
+					return art;
 			}
 		}
 	}
-	return {nullptr, nullptr};
-}
-
-const CArtifactInstance * CArtifactSet::getHiddenArt(const ArtifactID & aid) const
-{
-	return searchForConstituent(aid).second;
-}
-
-const CArtifactInstance * CArtifactSet::getAssemblyByConstituent(const ArtifactID & aid) const
-{
-	return searchForConstituent(aid).first;
+	return nullptr;
 }
 
 const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
@@ -905,6 +875,11 @@ const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
 	return nullptr;
 }
 
+void CArtifactSet::lockSlot(const ArtifactPosition & pos)
+{
+	setNewArtSlot(pos, nullptr, true);
+}
+
 bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const
 {
 	if(bearerType() == ArtBearer::ALTAR)
@@ -916,7 +891,7 @@ bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockChe
 	return true; //no slot means not used
 }
 
-void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked)
+void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked)
 {
 	assert(!vstd::contains(artifactsWorn, slot));
 
@@ -932,31 +907,12 @@ void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, ConstTransitiveP
 	else
 	{
 		auto position = artifactsInBackpack.begin() + slot - ArtifactPosition::BACKPACK_START;
-		slotInfo = &(*artifactsInBackpack.emplace(position, ArtSlotInfo()));
+		slotInfo = &(*artifactsInBackpack.emplace(position));
 	}
 	slotInfo->artifact = art;
 	slotInfo->locked = locked;
 }
 
-void CArtifactSet::eraseArtSlot(const ArtifactPosition & slot)
-{
-	if(slot == ArtifactPosition::TRANSITION_POS)
-	{
-		artifactsTransitionPos.artifact = nullptr;
-	}
-	else if(ArtifactUtils::isSlotBackpack(slot))
-	{
-		auto backpackSlot = ArtifactPosition(slot - ArtifactPosition::BACKPACK_START);
-
-		assert(artifactsInBackpack.begin() + backpackSlot < artifactsInBackpack.end());
-		artifactsInBackpack.erase(artifactsInBackpack.begin() + backpackSlot);
-	}
-	else
-	{
-		artifactsWorn.erase(slot);
-	}
-}
-
 void CArtifactSet::artDeserializationFix(CBonusSystemNode *node)
 {
 	for(auto & elem : artifactsWorn)

+ 13 - 24
lib/CArtHandler.h

@@ -175,10 +175,10 @@ private:
 
 struct DLL_LINKAGE ArtSlotInfo
 {
-	ConstTransitivePtr<CArtifactInstance> artifact;
-	ui8 locked; //if locked, then artifact points to the combined artifact
+	CArtifactInstance * artifact;
+	bool locked; //if locked, then artifact points to the combined artifact
 
-	ArtSlotInfo() : locked(false) {}
+	ArtSlotInfo() : artifact(nullptr), locked(false) {}
 	const CArtifactInstance * getArt() const;
 
 	template <typename Handler> void serialize(Handler & h)
@@ -197,32 +197,20 @@ public:
 	std::map<ArtifactPosition, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
 	ArtSlotInfo artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange
 
-	void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked);
-	void eraseArtSlot(const ArtifactPosition & slot);
-
 	const ArtSlotInfo * getSlot(const ArtifactPosition & pos) const;
-	const CArtifactInstance * getArt(const ArtifactPosition & pos, bool excludeLocked = true) const; //nullptr - no artifact
-	CArtifactInstance * getArt(const ArtifactPosition & pos, bool excludeLocked = true); //nullptr - no artifact
-	/// Looks for equipped artifact with given ID and returns its slot ID or -1 if none
-	/// (if more than one such artifact lower ID is returned)
+	void lockSlot(const ArtifactPosition & pos);
+	CArtifactInstance * getArt(const ArtifactPosition & pos, bool excludeLocked = true) const;
+	/// Looks for first artifact with given ID
 	ArtifactPosition getArtPos(const ArtifactID & aid, bool onlyWorn = true, bool allowLocked = true) const;
 	ArtifactPosition getArtPos(const CArtifactInstance * art) const;
-	std::vector<ArtifactPosition> getAllArtPositions(const ArtifactID & aid, bool onlyWorn, bool allowLocked, bool getAll) const;
-	std::vector<ArtifactPosition> getBackpackArtPositions(const ArtifactID & aid) const;
 	const CArtifactInstance * getArtByInstanceId(const ArtifactInstanceID & artInstId) const;
-	/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
-	const CArtifactInstance * getHiddenArt(const ArtifactID & aid) const;
-	const CArtifactInstance * getAssemblyByConstituent(const ArtifactID & aid) const;
-	/// Checks if hero possess artifact of given id (either in backack or worn)
-	bool hasArt(const ArtifactID & aid, bool onlyWorn = false, bool searchBackpackAssemblies = false, bool allowLocked = true) const;
-	bool hasArtBackpack(const ArtifactID & aid) const;
+	bool hasArt(const ArtifactID & aid, bool onlyWorn = false, bool searchCombinedParts = false) const;
 	bool isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck = false) const;
-	unsigned getArtPosCount(const ArtifactID & aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const;
 
 	virtual ArtBearer::ArtBearer bearerType() const = 0;
-	virtual ArtPlacementMap putArtifact(ArtifactPosition slot, CArtifactInstance * art);
-	virtual void removeArtifact(ArtifactPosition slot);
-	virtual ~CArtifactSet();
+	virtual ArtPlacementMap putArtifact(const ArtifactPosition & slot, CArtifactInstance * art);
+	virtual void removeArtifact(const ArtifactPosition & slot);
+	virtual ~CArtifactSet() = default;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -233,10 +221,11 @@ public:
 	void artDeserializationFix(CBonusSystemNode *node);
 
 	void serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName);
-protected:
-	std::pair<const CArtifactInstance *, const CArtifactInstance *> searchForConstituent(const ArtifactID & aid) const;
+	const CArtifactInstance * getCombinedArtWithPart(const ArtifactID & partId) const;
 
 private:
+	void setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked);
+
 	void serializeJsonHero(JsonSerializeFormat & handler);
 	void serializeJsonCreature(JsonSerializeFormat & handler);
 	void serializeJsonCommander(JsonSerializeFormat & handler);

+ 2 - 2
lib/CCreatureSet.cpp

@@ -863,7 +863,7 @@ ArtBearer::ArtBearer CStackInstance::bearerType() const
 	return ArtBearer::CREATURE;
 }
 
-CStackInstance::ArtPlacementMap CStackInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
+CStackInstance::ArtPlacementMap CStackInstance::putArtifact(const ArtifactPosition & pos, CArtifactInstance * art)
 {
 	assert(!getArt(pos));
 	assert(art->canBePutAt(this, pos));
@@ -872,7 +872,7 @@ CStackInstance::ArtPlacementMap CStackInstance::putArtifact(ArtifactPosition pos
 	return CArtifactSet::putArtifact(pos, art);
 }
 
-void CStackInstance::removeArtifact(ArtifactPosition pos)
+void CStackInstance::removeArtifact(const ArtifactPosition & pos)
 {
 	assert(getArt(pos));
 

+ 2 - 2
lib/CCreatureSet.h

@@ -126,8 +126,8 @@ public:
 	void setArmyObj(const CArmedInstance *ArmyObj);
 	virtual void giveStackExp(TExpType exp);
 	bool valid(bool allowUnrandomized) const;
-	ArtPlacementMap putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;//from CArtifactSet
-	void removeArtifact(ArtifactPosition pos) override;
+	ArtPlacementMap putArtifact(const ArtifactPosition & pos, CArtifactInstance * art) override;//from CArtifactSet
+	void removeArtifact(const ArtifactPosition & pos) override;
 	ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
 	std::string nodeName() const override; //from CBonusSystemnode
 	void deserializationFix();

+ 3 - 3
lib/mapObjects/CGHeroInstance.cpp

@@ -1156,7 +1156,7 @@ std::string CGHeroInstance::getBiographyTextID() const
 	return ""; //for random hero
 }
 
-CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
+CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(const ArtifactPosition & pos, CArtifactInstance * art)
 {
 	assert(art->canBePutAt(this, pos));
 
@@ -1165,7 +1165,7 @@ CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos
 	return CArtifactSet::putArtifact(pos, art);
 }
 
-void CGHeroInstance::removeArtifact(ArtifactPosition pos)
+void CGHeroInstance::removeArtifact(const ArtifactPosition & pos)
 {
 	auto art = getArt(pos);
 	assert(art);
@@ -1201,7 +1201,7 @@ void CGHeroInstance::removeSpellbook()
 
 	if(hasSpellbook())
 	{
-		//VLC->arth->removeArtifactFrom(*this, ArtifactPosition::SPELLBOOK);
+		cb->removeArtifact(ArtifactLocation(this->id, ArtifactPosition::SPELLBOOK));
 	}
 }
 

+ 2 - 2
lib/mapObjects/CGHeroInstance.h

@@ -241,8 +241,8 @@ public:
 	void initHero(vstd::RNG & rand);
 	void initHero(vstd::RNG & rand, const HeroTypeID & SUBID);
 
-	ArtPlacementMap putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
-	void removeArtifact(ArtifactPosition pos) override;
+	ArtPlacementMap putArtifact(const ArtifactPosition & pos, CArtifactInstance * art) override;
+	void removeArtifact(const ArtifactPosition & pos) override;
 	void initExp(vstd::RNG & rand);
 	void initArmy(vstd::RNG & rand, IArmyDescriptor *dst = nullptr);
 	void pushPrimSkill(PrimarySkill which, int val);

+ 1 - 1
lib/mapObjects/CQuest.cpp

@@ -152,7 +152,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const
 		}
 		else
 		{
-			const auto * assembly = h->getAssemblyByConstituent(elem);
+			const auto * assembly = h->getCombinedArtWithPart(elem);
 			assert(assembly);
 			auto parts = assembly->getPartsInfo();
 

+ 1 - 1
lib/mapping/MapFormatH3M.cpp

@@ -917,7 +917,7 @@ void CMapLoaderH3M::loadArtifactsOfHero(CGHeroInstance * hero)
 
 		hero->artifactsInBackpack.clear();
 		while(!hero->artifactsWorn.empty())
-			hero->eraseArtSlot(hero->artifactsWorn.begin()->first);
+			hero->removeArtifact(hero->artifactsWorn.begin()->first);
 	}
 
 	for(int i = 0; i < features.artifactSlotsCount; i++)

+ 1 - 1
lib/networkPacks/PacksForClient.h

@@ -966,7 +966,7 @@ struct DLL_LINKAGE PutArtifact : CArtifactOperationPack
 {
 	PutArtifact() = default;
 	explicit PutArtifact(const ArtifactInstanceID & id, const ArtifactLocation & dst, bool askAssemble = true)
-		: id(id), al(dst), askAssemble(askAssemble)
+		: al(dst), askAssemble(askAssemble), id(id)
 	{
 	}
 

+ 21 - 3
lib/rewardable/Limiter.cpp

@@ -143,10 +143,28 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 		for(const auto & elem : artifactsRequirements)
 		{
 			// check required amount of artifacts
-			if(hero->getArtPosCount(elem.first, false, true, true) < elem.second)
+			size_t artCnt = 0;
+			for(const auto & [slot, slotInfo] : hero->artifactsWorn)
+				if(slotInfo.artifact->getTypeId() == elem.first)
+					artCnt++;
+
+			for(auto & slotInfo : hero->artifactsInBackpack)
+				if(slotInfo.artifact->getTypeId() == elem.first)
+				{
+					artCnt++;
+				}
+				else if(slotInfo.artifact->isCombined())
+				{
+					for(const auto & partInfo : slotInfo.artifact->getPartsInfo())
+						if(partInfo.art->getTypeId() == elem.first)
+							artCnt++;
+				}
+
+			if(artCnt < elem.second)
 				return false;
-			if(!hero->hasArt(elem.first))
-				reqSlots += hero->getAssemblyByConstituent(elem.first)->getPartsInfo().size() - 2;
+			// Check if art has no own slot. (As part of combined in backpack)
+			if(hero->getArtPos(elem.first, false) == ArtifactPosition::PRE_FIRST)
+				reqSlots += hero->getCombinedArtWithPart(elem.first)->getPartsInfo().size() - 2;
 		}
 		if(!ArtifactUtils::isBackpackFreeSlots(hero, reqSlots))
 			return false;

+ 4 - 4
server/CGameHandler.cpp

@@ -2718,15 +2718,15 @@ bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const Obje
 		// Second, find the necessary artifacts for the costume
 		for(const auto & artPos : costumeArtMap)
 		{
-			if(const auto availableArts = artFittingSet.getAllArtPositions(artPos.second, false, false, false); !availableArts.empty())
+			if(const auto slot = artFittingSet.getArtPos(artPos.second, false, false); slot != ArtifactPosition::PRE_FIRST)
 			{
 				bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots
 					{
-						artSet->getArtPos(artFittingSet.getArt(availableArts.front())),
+						artSet->getArtPos(artFittingSet.getArt(slot)),
 						artPos.first
 					});
-				artFittingSet.removeArtifact(availableArts.front());
-				if(ArtifactUtils::isSlotBackpack(availableArts.front()))
+				artFittingSet.removeArtifact(slot);
+				if(ArtifactUtils::isSlotBackpack(slot))
 					estimateBackpackSize--;
 			}
 		}