Browse Source

Merge pull request #2814 from SoundSSGood/arts-counter-impovements

Artifacts counter impovements
Ivan Savenko 2 năm trước cách đây
mục cha
commit
b21a361b99

+ 1 - 1
client/widgets/CArtifactHolder.cpp

@@ -282,7 +282,7 @@ bool ArtifactUtilsClient::askToAssemble(const CGHeroInstance * hero, const Artif
 	if(hero->tempOwner != LOCPLINT->playerID)
 		return false;
 
-	auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), ArtifactUtils::isSlotEquipment(slot));
+	auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId());
 	if(!assemblyPossibilities.empty())
 	{
 		auto askThread = new boost::thread([hero, art, slot, assemblyPossibilities]() -> void

+ 3 - 1
client/widgets/CArtifactsOfHeroBase.cpp

@@ -261,8 +261,10 @@ void CArtifactsOfHeroBase::setSlotData(ArtPlacePtr artPlace, const ArtifactPosit
 			{
 				arts.insert(std::pair(combinedArt, 0));
 				for(const auto part : combinedArt->getConstituents())
-					if(artSet.hasArt(part->getId(), true))
+				{
+					if(artSet.hasArt(part->getId(), false))
 						arts.at(combinedArt)++;
+				}
 			}
 			artPlace->addCombinedArtInfo(arts);
 		}

+ 7 - 10
client/widgets/CWindowWithArtifacts.cpp

@@ -254,7 +254,7 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns
 
 void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
 {
-	updateSlots(artLoc.slot);
+	updateSlots();
 }
 
 void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw)
@@ -329,26 +329,23 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
 
 void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation & artLoc)
 {
-	updateSlots(artLoc.slot);
+	updateSlots();
 }
 
 void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation & artLoc)
 {
 	markPossibleSlots();
-	updateSlots(artLoc.slot);
+	updateSlots();
 }
 
-void CWindowWithArtifacts::updateSlots(const ArtifactPosition & slot)
+void CWindowWithArtifacts::updateSlots()
 {
-	auto updateSlotBody = [slot](auto artSetWeak) -> void
+	auto updateSlotBody = [](auto artSetWeak) -> void
 	{
 		if(const auto artSetPtr = artSetWeak.lock())
 		{
-			if(ArtifactUtils::isSlotEquipment(slot))
-				artSetPtr->updateWornSlots();
-			else if(ArtifactUtils::isSlotBackpack(slot))
-				artSetPtr->updateBackpackSlots();
-
+			artSetPtr->updateWornSlots();
+			artSetPtr->updateBackpackSlots();
 			artSetPtr->redraw();
 		}
 	};

+ 1 - 1
client/widgets/CWindowWithArtifacts.h

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

+ 4 - 17
lib/ArtifactUtils.cpp

@@ -115,7 +115,7 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
 }
 
 DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
-	const CArtifactSet * artSet, const ArtifactID & aid, bool equipped)
+	const CArtifactSet * artSet, const ArtifactID & aid)
 {
 	std::vector<const CArtifact*> arts;
 	const auto * art = aid.toArtifact();
@@ -129,23 +129,10 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
 
 		for(const auto constituent : artifact->getConstituents()) //check if all constituents are available
 		{
-			if(equipped)
+			if(!artSet->hasArt(constituent->getId(), false, false, false))
 			{
-				// Search for equipped arts
-				if(!artSet->hasArt(constituent->getId(), true, false, false))
-				{
-					possible = false;
-					break;
-				}
-			}
-			else
-			{
-				// Search in backpack
-				if(!artSet->hasArtBackpack(constituent->getId()))
-				{
-					possible = false;
-					break;
-				}
+				possible = false;
+				break;
 			}
 		}
 		if(possible)

+ 1 - 1
lib/ArtifactUtils.h

@@ -36,7 +36,7 @@ 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 std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid, bool equipped);
+	DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid);
 	DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid);
 	DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(CArtifact * art);
 	DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid);

+ 0 - 6
lib/CArtHandler.cpp

@@ -819,12 +819,6 @@ ArtifactPosition CArtifactSet::getArtPos(const ArtifactID & aid, bool onlyWorn,
 	return result.empty() ? ArtifactPosition{ArtifactPosition::PRE_FIRST} : result[0];
 }
 
-ArtifactPosition CArtifactSet::getArtBackpackPos(const ArtifactID & aid) const
-{
-	const auto result = getBackpackArtPositions(aid);
-	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;

+ 0 - 1
lib/CArtHandler.h

@@ -262,7 +262,6 @@ public:
 	/// (if more than one such artifact lower ID is returned)
 	ArtifactPosition getArtPos(const ArtifactID & aid, bool onlyWorn = true, bool allowLocked = true) const;
 	ArtifactPosition getArtPos(const CArtifactInstance *art) const;
-	ArtifactPosition getArtBackpackPos(const ArtifactID & aid) 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;

+ 46 - 20
lib/NetPacksLib.cpp

@@ -1920,43 +1920,69 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
 void AssembledArtifact::applyGs(CGameState *gs)
 {
 	CArtifactSet * artSet = al.getHolderArtSet();
-	[[maybe_unused]] const CArtifactInstance *transformedArt = al.getArt();
+	const CArtifactInstance * transformedArt = al.getArt();
 	assert(transformedArt);
-	bool combineEquipped = !ArtifactUtils::isSlotBackpack(al.slot);
-	assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(artSet, transformedArt->artType->getId(), combineEquipped), [=](const CArtifact * art)->bool
+	assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(artSet, transformedArt->getTypeId()), [=](const CArtifact * art)->bool
 		{
 			return art->getId() == builtArt->getId();
 		}));
 
+	const auto transformedArtSlot = artSet->getSlotByInstance(transformedArt);
 	auto * combinedArt = new CArtifactInstance(builtArt);
 	gs->map->addNewArtifactInstance(combinedArt);
-	// Retrieve all constituents
-	for(const CArtifact * constituent : builtArt->getConstituents())
+
+	// Find slots for all involved artifacts
+	std::vector<ArtifactPosition> slotsInvolved;
+	for(const auto constituent : builtArt->getConstituents())
 	{
-		ArtifactPosition pos = combineEquipped ? artSet->getArtPos(constituent->getId(), true, false) :
-			artSet->getArtBackpackPos(constituent->getId());
-		assert(pos != ArtifactPosition::PRE_FIRST);
-		CArtifactInstance * constituentInstance = artSet->getArt(pos);
+		ArtifactPosition slot;
+		if(transformedArt->getTypeId() == constituent->getId())
+			slot = transformedArtSlot;
+		else
+			slot = artSet->getArtPos(constituent->getId(), false, false);
+
+		assert(slot != ArtifactPosition::PRE_FIRST);
+		slotsInvolved.emplace_back(slot);
+	}
+	std::sort(slotsInvolved.begin(), slotsInvolved.end(), std::greater<>());
 
-		//move constituent from hero to be part of new, combined artifact
-		constituentInstance->removeFrom(ArtifactLocation(al.artHolder, pos));
-		if(combineEquipped)
+	// Find a slot for combined artifact
+	al.slot = transformedArtSlot;
+	for(const auto slot : slotsInvolved)
+	{
+		if(ArtifactUtils::isSlotEquipment(transformedArtSlot))
 		{
+
+			if(ArtifactUtils::isSlotBackpack(slot))
+			{
+				al.slot = ArtifactPosition::BACKPACK_START;
+				break;
+			}
+
 			if(!vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), al.slot)
-				&& vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), pos))
-				al.slot = pos;
-			if(al.slot == pos)
-				pos = ArtifactPosition::PRE_FIRST;
+				&& vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), slot))
+				al.slot = slot;
 		}
 		else
 		{
-			al.slot = std::min(al.slot, pos);
-			pos = ArtifactPosition::PRE_FIRST;
+			if(ArtifactUtils::isSlotBackpack(slot))
+				al.slot = std::min(al.slot, slot);
 		}
-		combinedArt->addPart(constituentInstance, pos);
 	}
 
-	//put new combined artifacts
+	// Delete parts from hero
+	for(const auto slot : slotsInvolved)
+	{
+		const auto constituentInstance = artSet->getArt(slot);
+		constituentInstance->removeFrom(ArtifactLocation(al.artHolder, slot));
+
+		if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot)
+			combinedArt->addPart(constituentInstance, slot);
+		else
+			combinedArt->addPart(constituentInstance, ArtifactPosition::PRE_FIRST);
+	}
+
+	// Put new combined artifacts
 	combinedArt->putAt(al);
 }
 

+ 11 - 7
server/CGameHandler.cpp

@@ -2738,7 +2738,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
 		}
 
 		MoveArtifact ma(&src, &dst);
-		if(dst.slot == ArtifactPosition::TRANSITION_POS)
+		if(src.artHolder == dst.artHolder)
 			ma.askAssemble = false;
 		sendAndApply(&ma);
 	}
@@ -2853,7 +2853,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
  * @param assembleTo If assemble is true, this represents the artifact ID of the combination
  * artifact to assemble to. Otherwise it's not used.
  */
-bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)
+bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)
 {
 	const CGHeroInstance * hero = getHero(heroID);
 	const CArtifactInstance * destArtifact = hero->getArt(artifactSlot);
@@ -2861,23 +2861,27 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition
 	if(!destArtifact)
 		COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
 
+	const auto dstLoc = ArtifactLocation(hero, artifactSlot);
 	if(assemble)
 	{
 		CArtifact * combinedArt = VLC->arth->objects[assembleTo];
 		if(!combinedArt->isCombined())
 			COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!");
-		if (!vstd::contains(ArtifactUtils::assemblyPossibilities(hero, destArtifact->getTypeId(),
-			ArtifactUtils::isSlotEquipment(artifactSlot)), combinedArt))
+		if(!vstd::contains(ArtifactUtils::assemblyPossibilities(hero, destArtifact->getTypeId()), combinedArt))
 		{
 			COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
 		}
-
+		if(!destArtifact->canBePutAt(dstLoc)
+			&& !destArtifact->canBePutAt(ArtifactLocation(hero, ArtifactPosition::BACKPACK_START)))
+		{
+			COMPLAIN_RET("assembleArtifacts: It's impossible to give the artholder requested artifact!");
+		}
 		
 		if(ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot))
 			giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
 
 		AssembledArtifact aa;
-		aa.al = ArtifactLocation(hero, artifactSlot);
+		aa.al = dstLoc;
 		aa.builtArt = combinedArt;
 		sendAndApply(&aa);
 	}
@@ -2891,7 +2895,7 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition
 			COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble but backpack is full!");
 
 		DisassembledArtifact da;
-		da.al = ArtifactLocation(hero, artifactSlot);
+		da.al = dstLoc;
 		sendAndApply(&da);
 	}