mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	ArtifactPosition::TRANSITION_POS now is simple ArtSlotInfo
This commit is contained in:
		| @@ -126,7 +126,7 @@ size_t CArtifactsOfHeroBackpack::calcRows(size_t slots) | |||||||
| CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const ArtifactPosition filterBySlot) | CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const ArtifactPosition filterBySlot) | ||||||
| 	: CArtifactsOfHeroBackpack(0, 0) | 	: CArtifactsOfHeroBackpack(0, 0) | ||||||
| { | { | ||||||
| 	assert(filterBySlot != ArtifactPosition::FIRST_AVAILABLE); | 	assert(ArtifactUtils::checkIfSlotValid(*getHero(), filterBySlot)); | ||||||
|  |  | ||||||
| 	if(!ArtifactUtils::isSlotEquipment(filterBySlot)) | 	if(!ArtifactUtils::isSlotEquipment(filterBySlot)) | ||||||
| 		return; | 		return; | ||||||
|   | |||||||
| @@ -32,9 +32,9 @@ CArtifactsOfHeroBase::CArtifactsOfHeroBase() | |||||||
| void CArtifactsOfHeroBase::putBackPickedArtifact() | void CArtifactsOfHeroBase::putBackPickedArtifact() | ||||||
| { | { | ||||||
| 	// Artifact located in artifactsTransitionPos should be returned | 	// Artifact located in artifactsTransitionPos should be returned | ||||||
| 	if(getPickedArtifact()) | 	if(const auto art = getPickedArtifact()) | ||||||
| 	{ | 	{ | ||||||
| 		auto slot = ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId()); | 		auto slot = ArtifactUtils::getArtAnyPosition(curHero, art->getTypeId()); | ||||||
| 		if(slot == ArtifactPosition::PRE_FIRST) | 		if(slot == ArtifactPosition::PRE_FIRST) | ||||||
| 		{ | 		{ | ||||||
| 			LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); | 			LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); | ||||||
| @@ -196,10 +196,10 @@ void CArtifactsOfHeroBase::updateSlot(const ArtifactPosition & slot) | |||||||
| const CArtifactInstance * CArtifactsOfHeroBase::getPickedArtifact() | const CArtifactInstance * CArtifactsOfHeroBase::getPickedArtifact() | ||||||
| { | { | ||||||
| 	// Returns only the picked up artifact. Not just highlighted like in the trading window. | 	// Returns only the picked up artifact. Not just highlighted like in the trading window. | ||||||
| 	if(!curHero || curHero->artifactsTransitionPos.empty()) | 	if(curHero) | ||||||
| 		return nullptr; |  | ||||||
| 	else |  | ||||||
| 		return curHero->getArt(ArtifactPosition::TRANSITION_POS); | 		return curHero->getArt(ArtifactPosition::TRANSITION_POS); | ||||||
|  | 	else | ||||||
|  | 		return nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| void CArtifactsOfHeroBase::addGestureCallback(CArtPlace::ClickFunctor callback) | void CArtifactsOfHeroBase::addGestureCallback(CArtPlace::ClickFunctor callback) | ||||||
|   | |||||||
| @@ -222,7 +222,8 @@ void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & | |||||||
| 		assert(tradeSlotsMap.at(altarSlot)); | 		assert(tradeSlotsMap.at(altarSlot)); | ||||||
| 		const auto slot = altarArtifacts->getSlotByInstance(tradeSlotsMap.at(altarSlot)); | 		const auto slot = altarArtifacts->getSlotByInstance(tradeSlotsMap.at(altarSlot)); | ||||||
| 		assert(slot != ArtifactPosition::PRE_FIRST); | 		assert(slot != ArtifactPosition::PRE_FIRST); | ||||||
| 		LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS)); | 		LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), | ||||||
|  | 			ArtifactLocation(hero->id, GH.isKeyboardCtrlDown() ? ArtifactPosition::FIRST_AVAILABLE : ArtifactPosition::TRANSITION_POS)); | ||||||
| 		tradeSlotsMap.erase(altarSlot); | 		tradeSlotsMap.erase(altarSlot); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| #include "render/Canvas.h" | #include "render/Canvas.h" | ||||||
| #include "CPlayerInterface.h" | #include "CPlayerInterface.h" | ||||||
|  |  | ||||||
| CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<CArtifactsOfHeroPtr> & artsSets) | CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<ArtifactsOfHeroVar> & artsSets) | ||||||
| 	: CWindowWithArtifacts(&artsSets) | 	: CWindowWithArtifacts(&artsSets) | ||||||
| { | { | ||||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ class CFilledTexture; | |||||||
| class CHeroBackpackWindow : public CStatusbarWindow, public CWindowWithArtifacts | class CHeroBackpackWindow : public CStatusbarWindow, public CWindowWithArtifacts | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<CArtifactsOfHeroPtr> & artsSets); | 	CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<ArtifactsOfHeroVar> & artsSets); | ||||||
| 	 | 	 | ||||||
| protected: | protected: | ||||||
| 	std::shared_ptr<CArtifactsOfHeroBackpack> arts; | 	std::shared_ptr<CArtifactsOfHeroBackpack> arts; | ||||||
|   | |||||||
| @@ -548,7 +548,7 @@ std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index) | |||||||
| 	switch(index) | 	switch(index) | ||||||
| 	{ | 	{ | ||||||
| 	case 0: | 	case 0: | ||||||
| 		return std::make_shared<CKingdHeroList>(size, [this](const CWindowWithArtifacts::CArtifactsOfHeroPtr & newHeroSet) | 		return std::make_shared<CKingdHeroList>(size, [this](const CWindowWithArtifacts::ArtifactsOfHeroVar & newHeroSet) | ||||||
| 			{ | 			{ | ||||||
| 				addSetAndCallbacks(newHeroSet); | 				addSetAndCallbacks(newHeroSet); | ||||||
| 			}); | 			}); | ||||||
|   | |||||||
| @@ -334,7 +334,7 @@ private: | |||||||
| 	std::shared_ptr<CLabel> skillsLabel; | 	std::shared_ptr<CLabel> skillsLabel; | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	using CreateHeroItemFunctor = std::function<void(const CWindowWithArtifacts::CArtifactsOfHeroPtr)>; | 	using CreateHeroItemFunctor = std::function<void(const CWindowWithArtifacts::ArtifactsOfHeroVar)>; | ||||||
|  |  | ||||||
| 	CKingdHeroList(size_t maxSize, const CreateHeroItemFunctor & onCreateHeroItemCallback); | 	CKingdHeroList(size_t maxSize, const CreateHeroItemFunctor & onCreateHeroItemCallback); | ||||||
| 	void updateGarrisons() override; | 	void updateGarrisons() override; | ||||||
|   | |||||||
| @@ -106,8 +106,6 @@ void CMarketWindow::artifactRemoved(const ArtifactLocation & artLoc) | |||||||
|  |  | ||||||
| void CMarketWindow::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) | void CMarketWindow::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) | ||||||
| { | { | ||||||
| 	if(!getState().has_value()) |  | ||||||
| 		return; |  | ||||||
| 	CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw); | 	CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw); | ||||||
| 	assert(marketWidget); | 	assert(marketWidget); | ||||||
| 	marketWidget->update(); | 	marketWidget->update(); | ||||||
|   | |||||||
| @@ -35,18 +35,18 @@ | |||||||
|  |  | ||||||
| #include "../../CCallback.h" | #include "../../CCallback.h" | ||||||
|  |  | ||||||
| CWindowWithArtifacts::CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets) | CWindowWithArtifacts::CWindowWithArtifacts(const std::vector<ArtifactsOfHeroVar> * artSets) | ||||||
| { | { | ||||||
| 	if(artSets) | 	if(artSets) | ||||||
| 		this->artSets.insert(this->artSets.end(), artSets->begin(), artSets->end()); | 		this->artSets.insert(this->artSets.end(), artSets->begin(), artSets->end()); | ||||||
| } | } | ||||||
|  |  | ||||||
| void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr newArtSet) | void CWindowWithArtifacts::addSet(ArtifactsOfHeroVar newArtSet) | ||||||
| { | { | ||||||
| 	artSets.emplace_back(newArtSet); | 	artSets.emplace_back(newArtSet); | ||||||
| } | } | ||||||
|  |  | ||||||
| void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr newArtSet) | void CWindowWithArtifacts::addSetAndCallbacks(ArtifactsOfHeroVar newArtSet) | ||||||
| { | { | ||||||
| 	addSet(newArtSet); | 	addSet(newArtSet); | ||||||
| 	std::visit([this](auto artSetWeak) | 	std::visit([this](auto artSetWeak) | ||||||
| @@ -65,20 +65,36 @@ void CWindowWithArtifacts::addCloseCallback(const CloseCallback & callback) | |||||||
|  |  | ||||||
| const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact() | const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact() | ||||||
| { | { | ||||||
| 	auto res = getState(); | 	const CGHeroInstance * hero = nullptr; | ||||||
| 	if(res.has_value()) |  | ||||||
| 		return std::get<const CGHeroInstance*>(res.value()); | 	for(auto artSetWeak : artSets) | ||||||
| 	else | 		std::visit([&hero](auto artSetWeak) | ||||||
| 		return nullptr; | 			{ | ||||||
|  | 				if(auto artSetPtr = artSetWeak.lock()) | ||||||
|  | 					if(const auto pickedArt = artSetPtr->getHero()->getArt(ArtifactPosition::TRANSITION_POS)) | ||||||
|  | 					{ | ||||||
|  | 						hero = artSetPtr->getHero(); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 			}, artSetWeak); | ||||||
|  | 	return hero; | ||||||
| } | } | ||||||
|  |  | ||||||
| const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact() | const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact() | ||||||
| { | { | ||||||
| 	auto res = getState(); | 	const CArtifactInstance * art = nullptr; | ||||||
| 	if(res.has_value()) |  | ||||||
| 		return std::get<const CArtifactInstance*>(res.value()); | 	for (auto artSetWeak : artSets) | ||||||
| 	else | 		std::visit([&art](auto artSetWeak) | ||||||
| 		return nullptr; | 			{ | ||||||
|  | 				if(auto artSetPtr = artSetWeak.lock()) | ||||||
|  | 					if(const auto pickedArt = artSetPtr->getHero()->getArt(ArtifactPosition::TRANSITION_POS)) | ||||||
|  | 					{ | ||||||
|  | 						art = pickedArt; | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 			}, artSetWeak); | ||||||
|  | 	return art; | ||||||
| } | } | ||||||
|  |  | ||||||
| void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) | void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) | ||||||
| @@ -151,70 +167,46 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & | |||||||
| 						{ | 						{ | ||||||
| 							assert(artSetPtr->getHero()->getSlotByInstance(art) != ArtifactPosition::PRE_FIRST); | 							assert(artSetPtr->getHero()->getSlotByInstance(art) != ArtifactPosition::PRE_FIRST); | ||||||
|  |  | ||||||
| 							if(GH.isKeyboardCmdDown()) | 							auto srcLoc = ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot); | ||||||
|  | 							auto dstLoc = ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS); | ||||||
|  |  | ||||||
|  | 							if(GH.isKeyboardCtrlDown()) | ||||||
| 							{ | 							{ | ||||||
| 								std::shared_ptr<CArtifactsOfHeroMain> anotherHeroEquipmentPointer = nullptr; | 								std::shared_ptr<CArtifactsOfHeroBase> anotherArtSet = nullptr; | ||||||
|  |  | ||||||
| 								for(auto set : artSets) | 								for(auto set : artSets) | ||||||
| 								{ | 								{ | ||||||
| 									if(std::holds_alternative<std::weak_ptr<CArtifactsOfHeroMain>>(set)) | 									if(std::holds_alternative<std::weak_ptr<CArtifactsOfHeroMain>>(set)) | ||||||
| 									{ | 									{ | ||||||
| 										std::shared_ptr<CArtifactsOfHeroMain> heroEquipmentPointer = std::get<std::weak_ptr<CArtifactsOfHeroMain>>(set).lock(); | 										std::shared_ptr<CArtifactsOfHeroBase> heroEquipmentPointer = std::get<std::weak_ptr<CArtifactsOfHeroMain>>(set).lock(); | ||||||
| 										if(heroEquipmentPointer->getHero()->id != artSetPtr->getHero()->id) | 										if(heroEquipmentPointer->getHero()->id != artSetPtr->getHero()->id) | ||||||
| 										{ | 										{ | ||||||
| 											anotherHeroEquipmentPointer = heroEquipmentPointer; | 											anotherArtSet = heroEquipmentPointer; | ||||||
| 											break; | 											break; | ||||||
| 										} | 										} | ||||||
| 									} | 									} | ||||||
| 								} | 								} | ||||||
|  |  | ||||||
| 								if(anotherHeroEquipmentPointer != nullptr) | 								if(anotherArtSet != nullptr) | ||||||
| 								{ | 								{ | ||||||
| 									ArtifactPosition availablePosition = ArtifactUtils::getArtAnyPosition(anotherHeroEquipmentPointer->getHero(), art->getTypeId()); | 									dstLoc.slot = ArtifactPosition::FIRST_AVAILABLE; | ||||||
| 									if(availablePosition != ArtifactPosition::PRE_FIRST) | 									dstLoc.artHolder = anotherArtSet->getHero()->id; | ||||||
| 									{ |  | ||||||
| 										LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artSetPtr->getHero()->getSlotByInstance(art)), |  | ||||||
| 										ArtifactLocation(anotherHeroEquipmentPointer->getHero()->id, availablePosition)); |  | ||||||
| 									} |  | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 							else if(GH.isKeyboardAltDown()) | 							else if(GH.isKeyboardAltDown()) | ||||||
| 							{ | 							{ | ||||||
| 								ArtifactPosition destinationPosition = ArtifactPosition::PRE_FIRST; |  | ||||||
|  |  | ||||||
| 								if(ArtifactUtils::isSlotEquipment(artPlace.slot)) | 								if(ArtifactUtils::isSlotEquipment(artPlace.slot)) | ||||||
| 								{ | 									dstLoc.slot = ArtifactUtils::getArtBackpackPosition(artSetPtr->getHero(), art->getTypeId()); | ||||||
| 									ArtifactPosition availablePosition = ArtifactUtils::getArtBackpackPosition(artSetPtr->getHero(), art->getTypeId()); |  | ||||||
| 									if(availablePosition != ArtifactPosition::PRE_FIRST) |  | ||||||
| 									{ |  | ||||||
| 										destinationPosition = availablePosition; |  | ||||||
| 									} |  | ||||||
| 								} |  | ||||||
| 								else if(ArtifactUtils::isSlotBackpack(artPlace.slot)) | 								else if(ArtifactUtils::isSlotBackpack(artPlace.slot)) | ||||||
| 								{ | 									dstLoc.slot = ArtifactUtils::getArtEquippedPosition(artSetPtr->getHero(), art->getTypeId()); | ||||||
| 									ArtifactPosition availablePosition = ArtifactUtils::getArtAnyPosition(artSetPtr->getHero(), art->getTypeId()); |  | ||||||
| 									if(availablePosition != ArtifactPosition::PRE_FIRST && availablePosition != ArtifactPosition::BACKPACK_START) |  | ||||||
| 									{ |  | ||||||
| 										destinationPosition = availablePosition; |  | ||||||
| 									} |  | ||||||
| 								} |  | ||||||
|  |  | ||||||
| 								if(destinationPosition != ArtifactPosition::PRE_FIRST) |  | ||||||
| 								{ |  | ||||||
| 									LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot), |  | ||||||
| 										ArtifactLocation(artSetPtr->getHero()->id, destinationPosition)); |  | ||||||
| 								} |  | ||||||
| 							} |  | ||||||
| 							else |  | ||||||
| 							{ |  | ||||||
| 								LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot), |  | ||||||
| 									ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS)); |  | ||||||
| 							} | 							} | ||||||
|  | 							if(dstLoc.slot != ArtifactPosition::PRE_FIRST) | ||||||
|  | 								LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| 						for(const auto artSlot : ArtifactUtils::unmovableSlots()) | 						for(const auto & artSlot : ArtifactUtils::unmovableSlots()) | ||||||
| 							if(artPlace.slot == artSlot) | 							if(artPlace.slot == artSlot) | ||||||
| 							{ | 							{ | ||||||
| 								msg = CGI->generaltexth->allTexts[21]; | 								msg = CGI->generaltexth->allTexts[21]; | ||||||
| @@ -225,7 +217,7 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & | |||||||
|  |  | ||||||
| 				if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroBackpack>>) | 				if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroBackpack>>) | ||||||
| 				{ | 				{ | ||||||
| 					if(!isTransferAllowed && artPlace.getArt() && closeCallback) | 					if(!isTransferAllowed && artPlace.getArt() && !GH.isKeyboardCtrlDown() && !GH.isKeyboardAltDown() && closeCallback) | ||||||
| 						closeCallback(); | 						closeCallback(); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| @@ -354,8 +346,8 @@ void CWindowWithArtifacts::enableArtifactsCostumeSwitcher() const | |||||||
| 			{ | 			{ | ||||||
| 				if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMain>>) | 				if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMain>>) | ||||||
| 				{ | 				{ | ||||||
| 					const auto artSetPtr = artSetWeak.lock(); | 					if(auto artSetPtr = artSetWeak.lock()) | ||||||
| 					artSetPtr->enableArtifactsCostumeSwitcher(); | 						artSetPtr->enableArtifactsCostumeSwitcher(); | ||||||
| 				} | 				} | ||||||
| 			}, artSet); | 			}, artSet); | ||||||
| } | } | ||||||
| @@ -367,16 +359,10 @@ void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc) | |||||||
|  |  | ||||||
| void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) | void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) | ||||||
| { | { | ||||||
| 	auto curState = getState(); | 	const auto pickedArtInst = getPickedArtifact(); | ||||||
| 	if(!curState.has_value()) |  | ||||||
| 		// Transition state. Nothing to do here. Just skip. Need to wait for final state. |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	auto pickedArtInst = std::get<const CArtifactInstance*>(curState.value()); |  | ||||||
| 	auto artifactMovedBody = [this, withRedraw, &destLoc, &pickedArtInst](auto artSetWeak) -> void | 	auto artifactMovedBody = [this, withRedraw, &destLoc, &pickedArtInst](auto artSetWeak) -> void | ||||||
| 	{ | 	{ | ||||||
| 		auto artSetPtr = artSetWeak.lock(); | 		if(auto artSetPtr = artSetWeak.lock()) | ||||||
| 		if(artSetPtr) |  | ||||||
| 		{ | 		{ | ||||||
| 			const auto hero = artSetPtr->getHero(); | 			const auto hero = artSetPtr->getHero(); | ||||||
| 			if(pickedArtInst) | 			if(pickedArtInst) | ||||||
| @@ -446,45 +432,9 @@ void CWindowWithArtifacts::update() const | |||||||
| 		std::visit(updateSlotBody, artSetWeak); | 		std::visit(updateSlotBody, artSetWeak); | ||||||
| } | } | ||||||
|  |  | ||||||
| std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> CWindowWithArtifacts::getState() | std::optional<CWindowWithArtifacts::ArtifactsOfHeroVar> CWindowWithArtifacts::findAOHbyRef(const CArtifactsOfHeroBase & artsInst) | ||||||
| { | { | ||||||
| 	const CArtifactInstance * artInst = nullptr; | 	std::optional<ArtifactsOfHeroVar> res; | ||||||
| 	std::map<const CGHeroInstance*, size_t> pickedCnt; |  | ||||||
|  |  | ||||||
| 	auto getHeroArtBody = [&artInst, &pickedCnt](auto artSetWeak) -> void |  | ||||||
| 	{ |  | ||||||
| 		auto artSetPtr = artSetWeak.lock(); |  | ||||||
| 		if(artSetPtr) |  | ||||||
| 		{ |  | ||||||
| 			if(const auto art = artSetPtr->getPickedArtifact()) |  | ||||||
| 			{ |  | ||||||
| 				const auto hero = artSetPtr->getHero(); |  | ||||||
| 				if(pickedCnt.count(hero) == 0) |  | ||||||
| 				{ |  | ||||||
| 					pickedCnt.insert({ hero, hero->artifactsTransitionPos.size() }); |  | ||||||
| 					artInst = art; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	for(auto artSetWeak : artSets) |  | ||||||
| 		std::visit(getHeroArtBody, artSetWeak); |  | ||||||
|  |  | ||||||
| 	// The state is possible when the hero has placed an artifact in the ArtifactPosition::TRANSITION_POS, |  | ||||||
| 	// and the previous artifact has not yet removed from the ArtifactPosition::TRANSITION_POS. |  | ||||||
| 	// This is a transitional state. Then return nullopt. |  | ||||||
| 	if(std::accumulate(std::begin(pickedCnt), std::end(pickedCnt), 0, [](size_t accum, const auto & value) |  | ||||||
| 		{ |  | ||||||
| 			return accum + value.second; |  | ||||||
| 		}) > 1) |  | ||||||
| 		return std::nullopt; |  | ||||||
| 	else |  | ||||||
| 		return std::make_tuple(pickedCnt.begin()->first, artInst); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| std::optional<CWindowWithArtifacts::CArtifactsOfHeroPtr> CWindowWithArtifacts::findAOHbyRef(const CArtifactsOfHeroBase & artsInst) |  | ||||||
| { |  | ||||||
| 	std::optional<CArtifactsOfHeroPtr> res; |  | ||||||
|  |  | ||||||
| 	auto findAOHBody = [&res, &artsInst](auto & artSetWeak) -> void | 	auto findAOHBody = [&res, &artsInst](auto & artSetWeak) -> void | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
| class CWindowWithArtifacts : virtual public CWindowObject | class CWindowWithArtifacts : virtual public CWindowObject | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	using CArtifactsOfHeroPtr = std::variant< | 	using ArtifactsOfHeroVar = std::variant< | ||||||
| 		std::weak_ptr<CArtifactsOfHeroMarket>, | 		std::weak_ptr<CArtifactsOfHeroMarket>, | ||||||
| 		std::weak_ptr<CArtifactsOfHeroAltar>, | 		std::weak_ptr<CArtifactsOfHeroAltar>, | ||||||
| 		std::weak_ptr<CArtifactsOfHeroKingdom>, | 		std::weak_ptr<CArtifactsOfHeroKingdom>, | ||||||
| @@ -28,12 +28,12 @@ public: | |||||||
| 		std::weak_ptr<CArtifactsOfHeroQuickBackpack>>; | 		std::weak_ptr<CArtifactsOfHeroQuickBackpack>>; | ||||||
| 	using CloseCallback = std::function<void()>; | 	using CloseCallback = std::function<void()>; | ||||||
|  |  | ||||||
| 	std::vector<CArtifactsOfHeroPtr> artSets; | 	std::vector<ArtifactsOfHeroVar> artSets; | ||||||
| 	CloseCallback closeCallback; | 	CloseCallback closeCallback; | ||||||
|  |  | ||||||
| 	explicit CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets = nullptr); | 	explicit CWindowWithArtifacts(const std::vector<ArtifactsOfHeroVar> * artSets = nullptr); | ||||||
| 	void addSet(CArtifactsOfHeroPtr newArtSet); | 	void addSet(ArtifactsOfHeroVar newArtSet); | ||||||
| 	void addSetAndCallbacks(CArtifactsOfHeroPtr newArtSet); | 	void addSetAndCallbacks(ArtifactsOfHeroVar newArtSet); | ||||||
| 	void addCloseCallback(const CloseCallback & callback); | 	void addCloseCallback(const CloseCallback & callback); | ||||||
| 	const CGHeroInstance * getHeroPickedArtifact(); | 	const CGHeroInstance * getHeroPickedArtifact(); | ||||||
| 	const CArtifactInstance * getPickedArtifact(); | 	const CArtifactInstance * getPickedArtifact(); | ||||||
| @@ -51,8 +51,7 @@ public: | |||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	void update() const; | 	void update() const; | ||||||
| 	std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> getState(); | 	std::optional<ArtifactsOfHeroVar> findAOHbyRef(const CArtifactsOfHeroBase & artsInst); | ||||||
| 	std::optional<CArtifactsOfHeroPtr> findAOHbyRef(const CArtifactsOfHeroBase & artsInst); |  | ||||||
| 	void markPossibleSlots(); | 	void markPossibleSlots(); | ||||||
| 	bool checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade) const; | 	bool checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade) const; | ||||||
| 	void setCursorAnimation(const CArtifactInstance & artInst); | 	void setCursorAnimation(const CArtifactInstance & artInst); | ||||||
|   | |||||||
| @@ -19,7 +19,39 @@ | |||||||
|  |  | ||||||
| VCMI_LIB_NAMESPACE_BEGIN | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | DLL_LINKAGE bool ArtifactUtils::checkIfSlotValid(const CArtifactSet & artSet, const ArtifactPosition & slot) | ||||||
|  | { | ||||||
|  | 	if(artSet.bearerType() == ArtBearer::HERO) | ||||||
|  | 	{ | ||||||
|  | 		if(isSlotEquipment(slot) || isSlotBackpack(slot) || slot == ArtifactPosition::TRANSITION_POS) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	else if(artSet.bearerType() == ArtBearer::ALTAR) | ||||||
|  | 	{ | ||||||
|  | 		if(isSlotBackpack(slot)) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	else if(artSet.bearerType() == ArtBearer::COMMANDER) | ||||||
|  | 	{ | ||||||
|  | 		if(vstd::contains(commanderSlots(), slot)) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	else if(artSet.bearerType() == ArtBearer::CREATURE) | ||||||
|  | 	{ | ||||||
|  | 		if(slot == ArtifactPosition::CREATURE_SLOT) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
| DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid) | DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid) | ||||||
|  | { | ||||||
|  | 	if(auto targetSlot = getArtEquippedPosition(target, aid); targetSlot != ArtifactPosition::PRE_FIRST) | ||||||
|  | 		return targetSlot; | ||||||
|  | 	return getArtBackpackPosition(target, aid); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtEquippedPosition(const CArtifactSet * target, const ArtifactID & aid) | ||||||
| { | { | ||||||
| 	const auto * art = aid.toArtifact(); | 	const auto * art = aid.toArtifact(); | ||||||
| 	for(const auto & slot : art->getPossibleSlots().at(target->bearerType())) | 	for(const auto & slot : art->getPossibleSlots().at(target->bearerType())) | ||||||
| @@ -27,7 +59,7 @@ DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet | |||||||
| 		if(art->canBePutAt(target, slot)) | 		if(art->canBePutAt(target, slot)) | ||||||
| 			return slot; | 			return slot; | ||||||
| 	} | 	} | ||||||
| 	return getArtBackpackPosition(target, aid); | 	return ArtifactPosition::PRE_FIRST; | ||||||
| } | } | ||||||
|  |  | ||||||
| DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid) | DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid) | ||||||
|   | |||||||
| @@ -25,8 +25,9 @@ class CMap; | |||||||
|  |  | ||||||
| namespace ArtifactUtils | namespace ArtifactUtils | ||||||
| { | { | ||||||
| 	// Calculates where an artifact gets placed when it gets transferred from one hero to another. | 	DLL_LINKAGE bool checkIfSlotValid(const CArtifactSet & artSet, const ArtifactPosition & slot); | ||||||
| 	DLL_LINKAGE ArtifactPosition getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid); | 	DLL_LINKAGE ArtifactPosition getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid); | ||||||
|  | 	DLL_LINKAGE ArtifactPosition getArtEquippedPosition(const CArtifactSet * target, const ArtifactID & aid); | ||||||
| 	DLL_LINKAGE ArtifactPosition getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid); | 	DLL_LINKAGE ArtifactPosition getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid); | ||||||
| 	// TODO: Make this constexpr when the toolset is upgraded | 	// TODO: Make this constexpr when the toolset is upgraded | ||||||
| 	DLL_LINKAGE const std::vector<ArtifactPosition> & unmovableSlots(); | 	DLL_LINKAGE const std::vector<ArtifactPosition> & unmovableSlots(); | ||||||
|   | |||||||
| @@ -897,13 +897,7 @@ const CArtifactInstance * CArtifactSet::getAssemblyByConstituent(const ArtifactI | |||||||
| const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const | const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const | ||||||
| { | { | ||||||
| 	if(pos == ArtifactPosition::TRANSITION_POS) | 	if(pos == ArtifactPosition::TRANSITION_POS) | ||||||
| 	{ | 		return &artifactsTransitionPos; | ||||||
| 		// Always add to the end. Always take from the beginning. |  | ||||||
| 		if(artifactsTransitionPos.empty()) |  | ||||||
| 			return nullptr; |  | ||||||
| 		else |  | ||||||
| 			return &(*artifactsTransitionPos.begin()); |  | ||||||
| 	} |  | ||||||
| 	if(vstd::contains(artifactsWorn, pos)) | 	if(vstd::contains(artifactsWorn, pos)) | ||||||
| 		return &artifactsWorn.at(pos); | 		return &artifactsWorn.at(pos); | ||||||
| 	if(ArtifactUtils::isSlotBackpack(pos)) | 	if(ArtifactUtils::isSlotBackpack(pos)) | ||||||
| @@ -936,9 +930,7 @@ void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, ConstTransitiveP | |||||||
| 	ArtSlotInfo * slotInfo; | 	ArtSlotInfo * slotInfo; | ||||||
| 	if(slot == ArtifactPosition::TRANSITION_POS) | 	if(slot == ArtifactPosition::TRANSITION_POS) | ||||||
| 	{ | 	{ | ||||||
| 		// Always add to the end. Always take from the beginning. | 		slotInfo = &artifactsTransitionPos; | ||||||
| 		artifactsTransitionPos.emplace_back(); |  | ||||||
| 		slotInfo = &artifactsTransitionPos.back(); |  | ||||||
| 	} | 	} | ||||||
| 	else if(ArtifactUtils::isSlotEquipment(slot)) | 	else if(ArtifactUtils::isSlotEquipment(slot)) | ||||||
| 	{ | 	{ | ||||||
| @@ -957,8 +949,7 @@ void CArtifactSet::eraseArtSlot(const ArtifactPosition & slot) | |||||||
| { | { | ||||||
| 	if(slot == ArtifactPosition::TRANSITION_POS) | 	if(slot == ArtifactPosition::TRANSITION_POS) | ||||||
| 	{ | 	{ | ||||||
| 		assert(!artifactsTransitionPos.empty()); | 		artifactsTransitionPos.artifact = nullptr; | ||||||
| 		artifactsTransitionPos.erase(artifactsTransitionPos.begin()); |  | ||||||
| 	} | 	} | ||||||
| 	else if(ArtifactUtils::isSlotBackpack(slot)) | 	else if(ArtifactUtils::isSlotBackpack(slot)) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -194,7 +194,7 @@ public: | |||||||
|  |  | ||||||
| 	std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag | 	std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag | ||||||
| 	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 | 	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 | ||||||
| 	std::vector<ArtSlotInfo> artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange | 	ArtSlotInfo artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange | ||||||
|  |  | ||||||
| 	void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked); | 	void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked); | ||||||
| 	void eraseArtSlot(const ArtifactPosition & slot); | 	void eraseArtSlot(const ArtifactPosition & slot); | ||||||
|   | |||||||
| @@ -2721,10 +2721,16 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati | |||||||
| 	if(!isAllowedExchange(src.artHolder, dst.artHolder)) | 	if(!isAllowedExchange(src.artHolder, dst.artHolder)) | ||||||
| 		COMPLAIN_RET("That heroes cannot make any exchange!"); | 		COMPLAIN_RET("That heroes cannot make any exchange!"); | ||||||
|  |  | ||||||
|  | 	COMPLAIN_RET_FALSE_IF(!ArtifactUtils::checkIfSlotValid(*srcArtSet, src.slot), "moveArtifact: wrong artifact source slot"); | ||||||
| 	const auto srcArtifact = srcArtSet->getArt(src.slot); | 	const auto srcArtifact = srcArtSet->getArt(src.slot); | ||||||
| 	const auto dstArtifact = dstArtSet->getArt(dst.slot); | 	auto dstSlot = dst.slot; | ||||||
|  | 	if(dstSlot == ArtifactPosition::FIRST_AVAILABLE) | ||||||
|  | 		dstSlot = ArtifactUtils::getArtAnyPosition(dstArtSet, srcArtifact->getTypeId()); | ||||||
|  | 	if(!ArtifactUtils::checkIfSlotValid(*dstArtSet, dstSlot)) | ||||||
|  | 		return true; | ||||||
|  | 	const auto dstArtifact = dstArtSet->getArt(dstSlot); | ||||||
| 	const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtifact != nullptr; | 	const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtifact != nullptr; | ||||||
| 	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false; | 	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dstSlot) : false; | ||||||
|  |  | ||||||
| 	if(srcArtifact == nullptr) | 	if(srcArtifact == nullptr) | ||||||
| 		COMPLAIN_RET("No artifact to move!"); | 		COMPLAIN_RET("No artifact to move!"); | ||||||
| @@ -2733,23 +2739,23 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati | |||||||
|  |  | ||||||
| 	// Check if src/dest slots are appropriate for the artifacts exchanged. | 	// Check if src/dest slots are appropriate for the artifacts exchanged. | ||||||
| 	// Moving to the backpack is always allowed. | 	// Moving to the backpack is always allowed. | ||||||
| 	if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true)) | 	if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dstSlot, true)) | ||||||
| 		COMPLAIN_RET("Cannot move artifact!"); | 		COMPLAIN_RET("Cannot move artifact!"); | ||||||
|  |  | ||||||
| 	auto srcSlotInfo = srcArtSet->getSlot(src.slot); | 	auto srcSlotInfo = srcArtSet->getSlot(src.slot); | ||||||
| 	auto dstSlotInfo = dstArtSet->getSlot(dst.slot); | 	auto dstSlotInfo = dstArtSet->getSlot(dstSlot); | ||||||
|  |  | ||||||
| 	if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked)) | 	if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked)) | ||||||
| 		COMPLAIN_RET("Cannot move artifact locks."); | 		COMPLAIN_RET("Cannot move artifact locks."); | ||||||
|  |  | ||||||
| 	if(isDstSlotBackpack && srcArtifact->artType->isBig()) | 	if(isDstSlotBackpack && srcArtifact->artType->isBig()) | ||||||
| 		COMPLAIN_RET("Cannot put big artifacts in backpack!"); | 		COMPLAIN_RET("Cannot put big artifacts in backpack!"); | ||||||
| 	if(src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4) | 	if(src.slot == ArtifactPosition::MACH4 || dstSlot == ArtifactPosition::MACH4) | ||||||
| 		COMPLAIN_RET("Cannot move catapult!"); | 		COMPLAIN_RET("Cannot move catapult!"); | ||||||
| 	if(isDstSlotBackpack && !ArtifactUtils::isBackpackFreeSlots(dstArtSet)) | 	if(isDstSlotBackpack && !ArtifactUtils::isBackpackFreeSlots(dstArtSet)) | ||||||
| 		COMPLAIN_RET("Backpack is full!"); | 		COMPLAIN_RET("Backpack is full!"); | ||||||
|  |  | ||||||
| 	auto dstSlot = std::min(dst.slot, ArtifactPosition(ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size())); | 	dstSlot = std::min(dstSlot, ArtifactPosition(ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size())); | ||||||
|  |  | ||||||
| 	if(src.slot == dstSlot && src.artHolder == dst.artHolder) | 	if(src.slot == dstSlot && src.artHolder == dst.artHolder) | ||||||
| 		COMPLAIN_RET("Won't move artifact: Dest same as source!"); | 		COMPLAIN_RET("Won't move artifact: Dest same as source!"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user