浏览代码

Backpack limit part5. End of battle. Other stuff

SoundSSGood 2 年之前
父节点
当前提交
f0f9eecf97

+ 16 - 10
client/widgets/CArtifactHolder.cpp

@@ -646,7 +646,7 @@ CArtifactsOfHero::~CArtifactsOfHero()
 	if(!curHero->artifactsTransitionPos.empty())
 	{
 		auto artPlace = getArtPlace(
-			ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->artType->getId()));
+			ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId()));
 		if(artPlace)
 		{
 			assert(artPlace->ourOwner);
@@ -1005,16 +1005,22 @@ void CCommanderArtPlace::createImage()
 void CCommanderArtPlace::returnArtToHeroCallback()
 {
 	ArtifactPosition artifactPos = commanderSlotID;
-	ArtifactPosition freeSlot = ourArt->firstBackpackSlot(commanderOwner);
-
-	ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
-	ArtifactLocation dst(commanderOwner, freeSlot);
-
-	if (ourArt->canBePutAt(dst, true))
+	ArtifactPosition freeSlot = ArtifactUtils::getArtBackpackPosition(commanderOwner, ourArt->getTypeId());
+	if(freeSlot == ArtifactPosition::PRE_FIRST)
+	{
+		LOCPLINT->showInfoDialog("no free slots");
+	}
+	else
 	{
-		LOCPLINT->cb->swapArtifacts(src, dst);
-		setArtifact(nullptr);
-		parent->redraw();
+		ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
+		ArtifactLocation dst(commanderOwner, freeSlot);
+
+		if(ourArt->canBePutAt(dst, true))
+		{
+			LOCPLINT->cb->swapArtifacts(src, dst);
+			setArtifact(nullptr);
+			parent->redraw();
+		}
 	}
 }
 

+ 2 - 1
client/widgets/CGarrisonInt.cpp

@@ -204,7 +204,8 @@ bool CGarrisonSlot::highlightOrDropArtifact()
 					{
 						//creature can wear only one active artifact
 						//if we are placing a new one, the old one will be returned to the hero's backpack
-						LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero, dst.getArt()->firstBackpackSlot(srcHero)));
+						LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero,
+							ArtifactUtils::getArtBackpackPosition(srcHero, dst.getArt()->getTypeId())));
 					}
 					LOCPLINT->cb->swapArtifacts(src, dst);
 				}

+ 9 - 5
client/windows/CCreatureWindow.cpp

@@ -948,10 +948,14 @@ void CStackWindow::removeStackArtifact(ArtifactPosition pos)
 		logGlobal->error("Attempt to remove missing artifact");
 		return;
 	}
-	LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner, art->firstBackpackSlot(info->owner)));
-	stackArtifactButton.reset();
-	stackArtifactHelp.reset();
-	stackArtifactIcon.reset();
-	redraw();
+	const auto slot = ArtifactUtils::getArtBackpackPosition(info->owner, art->getTypeId());
+	if(slot != ArtifactPosition::PRE_FIRST)
+	{
+		LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner, slot));
+		stackArtifactButton.reset();
+		stackArtifactHelp.reset();
+		stackArtifactIcon.reset();
+		redraw();
+	}
 }
 

+ 3 - 2
client/windows/CHeroWindow.cpp

@@ -358,7 +358,7 @@ void CHeroWindow::commanderWindow()
 	{
 		const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero();
 		//artSelected = true;
-		ArtifactPosition freeSlot = art->firstAvailableSlot (curHero->commander);
+		const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->commander, art->artType->getId());
 		if(freeSlot < ArtifactPosition::COMMANDER_AFTER_LAST) //we don't want to put it in commander's backpack!
 		{
 			ArtifactLocation src(srcHero, commonInfo->src.slotID);
@@ -368,7 +368,8 @@ void CHeroWindow::commanderWindow()
 			{	//equip clicked stack
 				if(dst.getArt())
 				{
-					LOCPLINT->cb->swapArtifacts (dst, ArtifactLocation(srcHero, dst.getArt()->firstBackpackSlot(srcHero)));
+					LOCPLINT->cb->swapArtifacts (dst, ArtifactLocation(srcHero,
+						ArtifactUtils::getArtBackpackPosition(srcHero, art->getTypeId())));
 				}
 				LOCPLINT->cb->swapArtifacts(src, dst);
 			}

+ 1 - 1
client/windows/CTradeWindow.cpp

@@ -817,7 +817,7 @@ void CMarketplaceWindow::makeDeal()
 			leftIdToSend = hLeft->getArtInstance()->id.getNum();
 			break;
 		case EMarketMode::RESOURCE_ARTIFACT:
-			if(!ArtifactUtils::isPossibleToGetArt(hero, ArtifactID(hRight->id)))
+			if(!ArtifactID(hRight->id).toArtifact()->canBePutAt(hero))
 			{
 				LOCPLINT->showInfoDialog("no available slots");
 				madeTransaction = false;

+ 1 - 1
client/windows/GUIClasses.cpp

@@ -843,7 +843,7 @@ void CExchangeController::moveArtifact(
 {
 	auto srcLocation = ArtifactLocation(source, srcPosition);
 	auto dstLocation = ArtifactLocation(target,
-		ArtifactUtils::getArtAnyPosition(target, source->getArt(srcPosition)->artType->getId()));
+		ArtifactUtils::getArtAnyPosition(target, source->getArt(srcPosition)->getTypeId()));
 
 	cb->swapArtifacts(srcLocation, dstLocation);
 }

+ 53 - 64
lib/CArtHandler.cpp

@@ -146,60 +146,74 @@ bool CArtifact::canBeDisassembled() const
 
 bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const
 {
-	if(slot == ArtifactPosition::TRANSITION_POS)
-		return true;
-
 	auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
 	{
 		if(ArtifactUtils::isSlotBackpack(slot))
 		{
 			if(isBig() || !ArtifactUtils::isBackpackFreeSlots(artSet))
 				return false;
-
 			return true;
 		}
 
-		auto bearerPossibleSlots = possibleSlots.at(artSet->bearerType());
-		if(bearerPossibleSlots.empty())
-		{
-			logMod->warn("Warning: artifact %s doesn't have defined allowed slots for bearer of type %s", getNameTranslated(), artSet->bearerType());
-			return false;
-		}
-		if(!vstd::contains(bearerPossibleSlots, slot))
+		if(!vstd::contains(possibleSlots.at(artSet->bearerType()), slot))
 			return false;
 
 		return artSet->isPositionFree(slot, assumeDestRemoved);
 	};
 
-	if(canBeDisassembled())
+	auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
 	{
-		if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
-			return false;
-		if(ArtifactUtils::isSlotBackpack(slot))
-			return true;
-
-		CArtifactFittingSet fittingSet(artSet->bearerType());
-		fittingSet.artifactsWorn = artSet->artifactsWorn;
-		if(assumeDestRemoved)
-			fittingSet.removeArtifact(slot);
-		assert(constituents);
-		for(const auto art : *constituents)
+		if(canBeDisassembled())
 		{
-			auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId());
-			if(ArtifactUtils::isSlotEquipment(possibleSlot))
-			{
-				fittingSet.setNewArtSlot(possibleSlot, nullptr, true);
-			}
-			else
-			{
+			if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
 				return false;
+			if(ArtifactUtils::isSlotBackpack(slot))
+				return true;
+
+			CArtifactFittingSet fittingSet(artSet->bearerType());
+			fittingSet.artifactsWorn = artSet->artifactsWorn;
+			if(assumeDestRemoved)
+				fittingSet.removeArtifact(slot);
+			assert(constituents);
+			for(const auto art : *constituents)
+			{
+				auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId());
+				if(ArtifactUtils::isSlotEquipment(possibleSlot))
+				{
+					fittingSet.setNewArtSlot(possibleSlot, nullptr, true);
+				}
+				else
+				{
+					return false;
+				}
 			}
+			return true;
+		}
+		else
+		{
+			return simpleArtCanBePutAt(artSet, slot, assumeDestRemoved);
 		}
+	};
+
+	if(slot == ArtifactPosition::TRANSITION_POS)
 		return true;
+
+	if(slot == ArtifactPosition::FIRST_AVAILABLE)
+	{
+		for(const auto & slot : possibleSlots.at(artSet->bearerType()))
+		{
+			if(artCanBePutAt(artSet, slot, assumeDestRemoved))
+				return true;
+		}
+		return artCanBePutAt(artSet, GameConstants::BACKPACK_START, assumeDestRemoved);
+	}
+	else if(ArtifactUtils::isSlotBackpack(slot))
+	{
+		return artCanBePutAt(artSet, GameConstants::BACKPACK_START, assumeDestRemoved);
 	}
 	else
 	{
-		return simpleArtCanBePutAt(artSet, slot, assumeDestRemoved);
+		return artCanBePutAt(artSet, slot, assumeDestRemoved);
 	}
 }
 
@@ -864,24 +878,9 @@ std::string CArtifactInstance::getEffectiveDescription(const CGHeroInstance * he
 	return text;
 }
 
-ArtifactPosition CArtifactInstance::firstAvailableSlot(const CArtifactSet * h) const
+ArtifactID CArtifactInstance::getTypeId() const
 {
-	for(const auto & slot : artType->possibleSlots.at(h->bearerType()))
-	{
-		if(artType->canBePutAt(h, slot))
-			return slot;
-	}
-
-	//if haven't find proper slot, use backpack
-	return firstBackpackSlot(h);
-}
-
-ArtifactPosition CArtifactInstance::firstBackpackSlot(const CArtifactSet *h) const
-{
-	if(!artType->isBig()) //discard big artifact
-		return ArtifactPosition(GameConstants::BACKPACK_START + static_cast<si32>(h->artifactsInBackpack.size()));
-
-	return ArtifactPosition::PRE_FIRST;
+	return artType->getId();
 }
 
 bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const
@@ -1091,7 +1090,7 @@ void CCombinedArtifactInstance::putAt(ArtifactLocation al)
 				const bool suggestedPosValid = ci.art->canBePutAt(suggestedPos);
 
 				if(!(inActiveSlot && suggestedPosValid)) //there is a valid suggestion where to place lock
-					ci.slot = ArtifactUtils::getArtAnyPosition(al.getHolderArtSet(), ci.art->artType->getId());
+					ci.slot = ArtifactUtils::getArtAnyPosition(al.getHolderArtSet(), ci.art->getTypeId());
 
 				assert(ArtifactUtils::isSlotEquipment(ci.slot));
 				al.getHolderArtSet()->setNewArtSlot(ci.slot, ci.art, true); //sets as lock
@@ -1214,7 +1213,7 @@ std::vector<ArtifactPosition> CArtifactSet::getAllArtPositions(const ArtifactID
 {
 	std::vector<ArtifactPosition> result;
 	for(const auto & slotInfo : artifactsWorn)
-		if(slotInfo.second.artifact->artType->getId() == aid && (allowLocked || !slotInfo.second.locked))
+		if(slotInfo.second.artifact->getTypeId() == aid && (allowLocked || !slotInfo.second.locked))
 			result.push_back(slotInfo.first);
 
 	if(onlyWorn)
@@ -1300,7 +1299,7 @@ std::pair<const CCombinedArtifactInstance *, const CArtifactInstance *> CArtifac
 			auto * ass = dynamic_cast<CCombinedArtifactInstance *>(art.get());
 			for(auto& ci : ass->constituentsInfo)
 			{
-				if(ci.art->artType->getId() == aid)
+				if(ci.art->getTypeId() == aid)
 				{
 					return {ass, ci.art};
 				}
@@ -1452,7 +1451,7 @@ void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
 	{
 		backpackTemp.reserve(artifactsInBackpack.size());
 		for(const ArtSlotInfo & info : artifactsInBackpack)
-			backpackTemp.push_back(info.artifact->artType->getId());
+			backpackTemp.push_back(info.artifact->getTypeId());
 	}
 	handler.serializeIdArray(NArtifactPosition::backpack, backpackTemp);
 	if(!handler.saving)
@@ -1487,7 +1486,7 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa
 
 		if(info != nullptr && !info->locked)
 		{
-			artifactID = info->artifact->artType->getId();
+			artifactID = info->artifact->getTypeId();
 			handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
 		}
 	}
@@ -1522,7 +1521,7 @@ void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance *
 	{
 		for(auto & part : dynamic_cast<CCombinedArtifactInstance*>(art)->constituentsInfo)
 		{
-			const auto slot = ArtifactUtils::getArtAnyPosition(this, part.art->artType->getId());
+			const auto slot = ArtifactUtils::getArtAnyPosition(this, part.art->getTypeId());
 			assert(slot != ArtifactPosition::PRE_FIRST);
 			// For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots
 			this->setNewArtSlot(slot, part.art, true);
@@ -1655,14 +1654,4 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
 		return target->artifactsInBackpack.size() + reqSlots <= backpackCap;
 }
 
-DLL_LINKAGE bool ArtifactUtils::isPossibleToGetArt(const CArtifactSet * target, const ArtifactID & aid, ArtifactPosition slot)
-{
-	if(slot == ArtifactPosition::FIRST_AVAILABLE)
-		slot = getArtAnyPosition(target, aid);
-	if(isSlotEquipment(slot) || (isSlotBackpack(slot) && isBackpackFreeSlots(target)))
-		return true;
-	else
-		return false;
-}
-
 VCMI_LIB_NAMESPACE_END

+ 3 - 5
lib/CArtHandler.h

@@ -91,7 +91,8 @@ public:
 	virtual void levelUpArtifact (CArtifactInstance * art){};
 
 	virtual bool canBeDisassembled() const;
-	virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const;
+	virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE,
+		bool assumeDestRemoved = false) const;
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
 
@@ -153,10 +154,9 @@ public:
 	void setType(CArtifact *Art);
 
 	std::string getEffectiveDescription(const CGHeroInstance *hero = nullptr) const;
-	ArtifactPosition firstAvailableSlot(const CArtifactSet *h) const;
-	ArtifactPosition firstBackpackSlot(const CArtifactSet *h) const;
 	SpellID getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none
 
+	ArtifactID getTypeId() const;
 	bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const;  //forwards to the above one
 	virtual bool canBeDisassembled() const;
 	virtual void putAt(ArtifactLocation al);
@@ -390,8 +390,6 @@ namespace ArtifactUtils
 	DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot);
 	DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot);
 	DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1);
-	DLL_LINKAGE bool isPossibleToGetArt(const CArtifactSet * target, const ArtifactID & aid,
-		ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/CGameState.cpp

@@ -1594,7 +1594,7 @@ void CGameState::giveCampaignBonusToHero(CGHeroInstance * hero)
 		case CScenarioTravel::STravelBonus::SPELL_SCROLL:
 			{
 				CArtifactInstance * scroll = CArtifactInstance::createScroll(SpellID(curBonus->info2));
-				const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->artType->getId());
+				const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId());
 				if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
 					scroll->putAt(ArtifactLocation(hero, slot));
 				else

+ 7 - 3
lib/NetPacksLib.cpp

@@ -1693,14 +1693,18 @@ void RebalanceStacks::applyGs(CGameState * gs)
 				if (alDest.getArt())
 				{
 					auto * hero = dynamic_cast<CGHeroInstance *>(src.army.get());
-					if (hero)
+					auto dstSlot = ArtifactUtils::getArtBackpackPosition(hero, alDest.getArt()->getTypeId());
+					if(hero && dstSlot != ArtifactPosition::PRE_FIRST)
 					{
-						artDest->move (alDest, ArtifactLocation (hero, alDest.getArt()->firstBackpackSlot (hero)));
+						artDest->move (alDest, ArtifactLocation (hero, dstSlot));
 					}
 					//else - artifact cna be lost :/
 					else
 					{
-						logNetwork->warn("Artifact is present at destination slot!");
+						EraseArtifact ea;
+						ea.al = alDest;
+						ea.applyGs(gs);
+						logNetwork->warn("Cannot move artifact! No free slots");
 					}
 					artHere->move (alHere, alDest);
 					//TODO: choose from dialog

+ 0 - 5
lib/mapObjects/CGHeroInstance.cpp

@@ -1023,11 +1023,6 @@ void CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance *art)
 	art->putAt(ArtifactLocation(this, pos));
 }
 
-void CGHeroInstance::putInBackpack(CArtifactInstance *art)
-{
-	putArtifact(art->firstBackpackSlot(this), art);
-}
-
 bool CGHeroInstance::hasSpellbook() const
 {
 	return getArt(ArtifactPosition::SPELLBOOK);

+ 0 - 1
lib/mapObjects/CGHeroInstance.h

@@ -234,7 +234,6 @@ public:
 	void initHero(CRandomGenerator & rand, const HeroTypeID & SUBID);
 
 	void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
-	void putInBackpack(CArtifactInstance *art);
 	void initExp(CRandomGenerator & rand);
 	void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr);
 	//void giveArtifact (ui32 aid);

+ 1 - 1
lib/mapObjects/CQuest.cpp

@@ -812,7 +812,7 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
 						// Disassemble this backpack artifact
 						for(const auto & ci : parts)
 						{
-							if(ci.art->artType->getId() != elem)
+							if(ci.art->getTypeId() != elem)
 								cb->giveHeroNewArtifact(h, ci.art->artType, GameConstants::BACKPACK_START);
 						}
 					}

+ 1 - 1
lib/mapObjects/MiscObjects.cpp

@@ -1301,7 +1301,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
 		iw.type = EInfoWindowMode::AUTO;
 		iw.player = h->tempOwner;
 
-		if(ArtifactUtils::isPossibleToGetArt(h, storedArtifact->artType->getId()))
+		if(storedArtifact->artType->canBePutAt(h))
 		{
 			switch (ID)
 			{

+ 19 - 17
server/CGameHandler.cpp

@@ -758,12 +758,15 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance * heroAttacker, con
 	{
 		auto sendMoveArtifact = [&](const CArtifactInstance *art, MoveArtifact *ma)
 		{
-			arts.push_back(art);
-			auto slot = art->firstAvailableSlot(finishingBattle->winnerHero);
-			ma->dst = ArtifactLocation(finishingBattle->winnerHero, slot);
-			if(ArtifactUtils::isSlotBackpack(slot))
-				ma->askAssemble = false;
-			sendAndApply(ma);
+			const auto slot = ArtifactUtils::getArtAnyPosition(finishingBattle->winnerHero, art->artType->getId());
+			if(slot != ArtifactPosition::PRE_FIRST)
+			{
+				arts.push_back(art);
+				ma->dst = ArtifactLocation(finishingBattle->winnerHero, slot);
+				if(ArtifactUtils::isSlotBackpack(slot))
+					ma->askAssemble = false;
+				sendAndApply(ma);
+			}
 		};
 
 		if (finishingBattle->loserHero)
@@ -4007,13 +4010,13 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
 		std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
 	{
 		assert(artifact);
-		auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, artifact->artType->getId());
+		auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, artifact->getTypeId());
 		if(dstSlot != ArtifactPosition::PRE_FIRST)
 		{
 			artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact));
 			slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
 
-			if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact->artType->getId(), dstSlot))
+			if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact->getTypeId(), dstSlot))
 				giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
 		}
 	};
@@ -5875,7 +5878,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
 	if (h->diggingStatus() != EDiggingStatus::CAN_DIG) //checks for terrain and movement
 		COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
 
-	const auto isHeroAbleGet = ArtifactUtils::isPossibleToGetArt(h, ArtifactID::GRAIL);
+	const auto isHeroAbleGet = VLC->arth->objects[ArtifactID::GRAIL]->canBePutAt(h);
 	
 	if(isHeroAbleGet)
 	{
@@ -5903,7 +5906,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
 			iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
 			iw.text.addTxt(MetaString::ART_NAMES, ArtifactID::GRAIL);
 			iw.soundID = soundBase::ULTIMATEARTIFACT;
-			giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::PRE_FIRST); //give grail
+			giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::FIRST_AVAILABLE); //give grail
 			sendAndApply(&iw);
 
 			iw.soundID = soundBase::invalid;
@@ -6837,19 +6840,18 @@ bool CGameHandler::giveHeroArtifact(const CGHeroInstance * h, const CArtifactIns
 
 	if(pos == ArtifactPosition::FIRST_AVAILABLE)
 	{
-		al.slot = ArtifactUtils::getArtAnyPosition(h, a->artType->getId());
+		al.slot = ArtifactUtils::getArtAnyPosition(h, a->getTypeId());
 	}
-	else if(pos == GameConstants::BACKPACK_START)
+	else if(ArtifactUtils::isSlotBackpack(pos))
 	{
-		al.slot = ArtifactUtils::getArtBackpackPosition(h, a->artType->getId());
+		al.slot = ArtifactUtils::getArtBackpackPosition(h, a->getTypeId());
 	}
 	else
 	{
-		if(a->artType->canBePutAt(h, pos, false))
-			al.slot = pos;
+		al.slot = pos;
 	}
 
-	if(ArtifactUtils::isPossibleToGetArt(h, a->artType->getId(), al.slot))
+	if(a->canBePutAt(al))
 		putArtifact(al, a);
 	else
 		return false;
@@ -7041,7 +7043,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
 		///Give hero all artifacts except war machines, spell scrolls and spell book
 		for(int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods
 		{
-			if(ArtifactUtils::isPossibleToGetArt(hero, VLC->arth->objects[g]->getId()))
+			if(VLC->arth->objects[g]->canBePutAt(hero))
 				giveHeroNewArtifact(hero, VLC->arth->objects[g], ArtifactPosition::FIRST_AVAILABLE);
 		}
 	}