mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Artifact assembling changes
This commit is contained in:
		| @@ -264,7 +264,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 | ||||
|   | ||||
| @@ -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); | ||||
| 		} | ||||
|   | ||||
| @@ -244,7 +244,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) | ||||
| @@ -310,26 +310,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(); | ||||
| 		} | ||||
| 	}; | ||||
|   | ||||
| @@ -43,7 +43,7 @@ private: | ||||
| 	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(); | ||||
|   | ||||
| @@ -116,7 +116,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(); | ||||
| @@ -130,23 +130,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) | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -820,12 +820,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; | ||||
|   | ||||
| @@ -260,7 +260,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; | ||||
|   | ||||
| @@ -1907,43 +1907,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()) | ||||
| 	{ | ||||
| 		ArtifactPosition pos = combineEquipped ? artSet->getArtPos(constituent->getId(), true, false) : | ||||
| 			artSet->getArtBackpackPos(constituent->getId()); | ||||
| 		assert(pos != ArtifactPosition::PRE_FIRST); | ||||
| 		CArtifactInstance * constituentInstance = artSet->getArt(pos); | ||||
|  | ||||
| 		//move constituent from hero to be part of new, combined artifact | ||||
| 		constituentInstance->removeFrom(ArtifactLocation(al.artHolder, pos)); | ||||
| 		if(combineEquipped) | ||||
| 	// Find slots for all involved artifacts | ||||
| 	std::vector<ArtifactPosition> slotsInvolved; | ||||
| 	for(const auto constituent : builtArt->getConstituents()) | ||||
| 	{ | ||||
| 		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<>()); | ||||
|  | ||||
| 	// 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); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -2787,7 +2787,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); | ||||
| @@ -2795,23 +2795,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); | ||||
| 	} | ||||
| @@ -2825,7 +2829,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); | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user