mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Merge pull request #3656 from SoundSSGood/backpack-management
Backpack management init
This commit is contained in:
		| @@ -180,6 +180,14 @@ void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dst | ||||
| 	sendRequest(&bma); | ||||
| } | ||||
|  | ||||
| void CCallback::scrollBackpackArtifacts(ObjectInstanceID hero, bool left) | ||||
| { | ||||
| 	ManageBackpackArtifacts mba(hero, ManageBackpackArtifacts::ManageCmd::SCROLL_RIGHT); | ||||
| 	if(left) | ||||
| 		mba.cmd = ManageBackpackArtifacts::ManageCmd::SCROLL_LEFT; | ||||
| 	sendRequest(&mba); | ||||
| } | ||||
|  | ||||
| void CCallback::eraseArtifactByClient(const ArtifactLocation & al) | ||||
| { | ||||
| 	EraseArtifactByClient ea(al); | ||||
|   | ||||
| @@ -90,6 +90,7 @@ public: | ||||
| 	virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val)=0;//split creatures from the first stack | ||||
| 	//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes | ||||
| 	virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0; | ||||
| 	virtual void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) = 0; | ||||
| 	virtual void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0; | ||||
| 	virtual void eraseArtifactByClient(const ArtifactLocation & al)=0; | ||||
| 	virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0; | ||||
| @@ -174,6 +175,7 @@ public: | ||||
| 	bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override; | ||||
| 	void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; | ||||
| 	void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override; | ||||
| 	void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) override; | ||||
| 	void eraseArtifactByClient(const ArtifactLocation & al) override; | ||||
| 	bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override; | ||||
| 	void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override; | ||||
|   | ||||
| @@ -191,7 +191,7 @@ public: | ||||
| 	bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) override {return false;} | ||||
| 	bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override {return false;}; | ||||
| 	void removeArtifact(const ArtifactLocation & al) override {}; | ||||
| 	bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;}; | ||||
| 	bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;}; | ||||
|  | ||||
| 	void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {}; | ||||
| 	void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero) override {}; | ||||
|   | ||||
| @@ -290,8 +290,8 @@ void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack) | ||||
| 			callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst); | ||||
| 	}; | ||||
|  | ||||
| 	moveArtifact(cl.getOwner(pack.src.artHolder)); | ||||
| 	if(cl.getOwner(pack.src.artHolder) != cl.getOwner(pack.dst.artHolder)) | ||||
| 	moveArtifact(pack.interfaceOwner); | ||||
| 	if(pack.interfaceOwner != cl.getOwner(pack.dst.artHolder)) | ||||
| 		moveArtifact(cl.getOwner(pack.dst.artHolder)); | ||||
|  | ||||
| 	cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings | ||||
| @@ -305,7 +305,7 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack) | ||||
| 		{ | ||||
| 			auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos); | ||||
| 			auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); | ||||
| 			MoveArtifact ma(&srcLoc, &dstLoc, pack.askAssemble); | ||||
| 			MoveArtifact ma(pack.interfaceOwner, srcLoc, dstLoc, pack.askAssemble); | ||||
| 			visitMoveArtifact(ma); | ||||
| 		} | ||||
| 	}; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position) | ||||
| 		std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), | ||||
| 		std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), | ||||
| 		position, | ||||
| 		std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1)); | ||||
| 		std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1)); | ||||
|  | ||||
| 	// The backpack is in the altar window above and to the right | ||||
| 	for(auto & slot : backpack) | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
| CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax) | ||||
| 	: slotsColumnsMax(slotsColumnsMax) | ||||
| 	, slotsRowsMax(slotsRowsMax) | ||||
| 	, backpackPos(0) | ||||
| { | ||||
| 	setRedrawParent(true); | ||||
| } | ||||
| @@ -41,11 +42,11 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack() | ||||
| 	initAOHbackpack(visibleCapacityMax, backpackCap < 0 || visibleCapacityMax < backpackCap); | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroBackpack::scrollBackpack(int offset) | ||||
| void CArtifactsOfHeroBackpack::onSliderMoved(int newVal) | ||||
| { | ||||
| 	if(backpackListBox) | ||||
| 		backpackListBox->resize(getActiveSlotRowsNum()); | ||||
| 	backpackPos += offset; | ||||
| 	backpackPos += newVal; | ||||
| 	auto slot = ArtifactPosition::BACKPACK_START + backpackPos; | ||||
| 	for(auto artPlace : backpack) | ||||
| 	{ | ||||
| @@ -98,7 +99,7 @@ void CArtifactsOfHeroBackpack::initAOHbackpack(size_t slots, bool slider) | ||||
| 		}; | ||||
| 		CListBoxWithCallback::MovedPosCallback posMoved = [this](size_t pos) -> void | ||||
| 		{ | ||||
| 			scrollBackpack(static_cast<int>(pos) * slotsColumnsMax - backpackPos); | ||||
| 			onSliderMoved(static_cast<int>(pos) * slotsColumnsMax - backpackPos); | ||||
| 		}; | ||||
| 		backpackListBox = std::make_shared<CListBoxWithCallback>( | ||||
| 			posMoved, onCreate, Point(0, 0), Point(0, 0), slotsRowsMax, 0, 0, 1, | ||||
|   | ||||
| @@ -24,7 +24,7 @@ class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase | ||||
| public: | ||||
| 	CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax); | ||||
| 	CArtifactsOfHeroBackpack(); | ||||
| 	void scrollBackpack(int offset) override; | ||||
| 	void onSliderMoved(int newVal); | ||||
| 	void updateBackpackSlots() override; | ||||
| 	size_t getActiveSlotRowsNum(); | ||||
| 	size_t getSlotsNum(); | ||||
| @@ -36,6 +36,7 @@ protected: | ||||
| 	size_t slotsRowsMax; | ||||
| 	const int slotSizeWithMargin = 46; | ||||
| 	const int sliderPosOffsetX = 5; | ||||
| 	int backpackPos; // Position to display artifacts in heroes backpack | ||||
|  | ||||
| 	void initAOHbackpack(size_t slots, bool slider); | ||||
| 	size_t calcRows(size_t slots); | ||||
|   | ||||
| @@ -25,8 +25,7 @@ | ||||
| #include "../../lib/networkPacks/ArtifactLocation.h" | ||||
|  | ||||
| CArtifactsOfHeroBase::CArtifactsOfHeroBase() | ||||
| 	: backpackPos(0), | ||||
| 	curHero(nullptr), | ||||
| 	: curHero(nullptr), | ||||
| 	putBackPickedArtCallback(nullptr) | ||||
| { | ||||
| } | ||||
| @@ -56,10 +55,10 @@ void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCall | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroBase::init( | ||||
| 	CArtPlace::ClickFunctor lClickCallback, | ||||
| 	CArtPlace::ClickFunctor showPopupCallback, | ||||
| 	const CArtPlace::ClickFunctor & onClickPressedCallback, | ||||
| 	const CArtPlace::ClickFunctor & onShowPopupCallback, | ||||
| 	const Point & position, | ||||
| 	BpackScrollFunctor scrollCallback) | ||||
| 	const BpackScrollFunctor & scrollCallback) | ||||
| { | ||||
| 	// CArtifactsOfHeroBase::init may be transform to CArtifactsOfHeroBase::CArtifactsOfHeroBase if OBJECT_CONSTRUCTION_CAPTURING is removed | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | ||||
| @@ -78,17 +77,19 @@ void CArtifactsOfHeroBase::init( | ||||
| 	{ | ||||
| 		artPlace.second->slot = artPlace.first; | ||||
| 		artPlace.second->setArtifact(nullptr); | ||||
| 		artPlace.second->setClickPressedCallback(lClickCallback); | ||||
| 		artPlace.second->setShowPopupCallback(showPopupCallback); | ||||
| 		artPlace.second->setClickPressedCallback(onClickPressedCallback); | ||||
| 		artPlace.second->setShowPopupCallback(onShowPopupCallback); | ||||
| 	} | ||||
| 	for(auto artPlace : backpack) | ||||
| 	{ | ||||
| 		artPlace->setArtifact(nullptr); | ||||
| 		artPlace->setClickPressedCallback(lClickCallback); | ||||
| 		artPlace->setShowPopupCallback(showPopupCallback); | ||||
| 		artPlace->setClickPressedCallback(onClickPressedCallback); | ||||
| 		artPlace->setShowPopupCallback(onShowPopupCallback); | ||||
| 	} | ||||
| 	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(-1);}, EShortcut::MOVE_LEFT); | ||||
| 	rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(+1);}, EShortcut::MOVE_RIGHT); | ||||
| 	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), | ||||
| 		[scrollCallback](){scrollCallback(true);}, EShortcut::MOVE_LEFT); | ||||
| 	rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), | ||||
| 		[scrollCallback](){scrollCallback(false);}, EShortcut::MOVE_RIGHT); | ||||
| 	leftBackpackRoll->block(true); | ||||
| 	rightBackpackRoll->block(true); | ||||
|  | ||||
| @@ -116,16 +117,12 @@ void CArtifactsOfHeroBase::gestureArtPlace(CArtPlace & artPlace, const Point & c | ||||
| void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero) | ||||
| { | ||||
| 	curHero = hero; | ||||
| 	if(curHero->artifactsInBackpack.size() > 0) | ||||
| 		backpackPos %= curHero->artifactsInBackpack.size(); | ||||
| 	else | ||||
| 		backpackPos = 0; | ||||
|  | ||||
| 	for(auto slot : artWorn) | ||||
| 	{ | ||||
| 		setSlotData(slot.second, slot.first); | ||||
| 	} | ||||
| 	scrollBackpack(0); | ||||
| 	updateBackpackSlots(); | ||||
| } | ||||
|  | ||||
| const CGHeroInstance * CArtifactsOfHeroBase::getHero() const | ||||
| @@ -133,48 +130,9 @@ const CGHeroInstance * CArtifactsOfHeroBase::getHero() const | ||||
| 	return curHero; | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroBase::scrollBackpack(int offset) | ||||
| void CArtifactsOfHeroBase::scrollBackpack(bool left) | ||||
| { | ||||
| 	// offset==-1 => to left; offset==1 => to right | ||||
| 	using slotInc = std::function<ArtifactPosition(ArtifactPosition&)>; | ||||
| 	auto artsInBackpack = static_cast<int>(curHero->artifactsInBackpack.size()); | ||||
| 	auto scrollingPossible = artsInBackpack > backpack.size(); | ||||
|  | ||||
| 	slotInc inc_straight = [](ArtifactPosition & slot) -> ArtifactPosition | ||||
| 	{ | ||||
| 		return slot + 1; | ||||
| 	}; | ||||
| 	slotInc inc_ring = [artsInBackpack](ArtifactPosition & slot) -> ArtifactPosition | ||||
| 	{ | ||||
| 		return ArtifactPosition::BACKPACK_START + (slot - ArtifactPosition::BACKPACK_START + 1) % artsInBackpack; | ||||
| 	}; | ||||
| 	slotInc inc; | ||||
| 	if(scrollingPossible) | ||||
| 		inc = inc_ring; | ||||
| 	else | ||||
| 		inc = inc_straight; | ||||
|  | ||||
| 	backpackPos += offset; | ||||
| 	if(backpackPos < 0) | ||||
| 		backpackPos += artsInBackpack; | ||||
|  | ||||
| 	if(artsInBackpack) | ||||
| 		backpackPos %= artsInBackpack; | ||||
|  | ||||
| 	auto slot = ArtifactPosition(ArtifactPosition::BACKPACK_START + backpackPos); | ||||
| 	for(auto artPlace : backpack) | ||||
| 	{ | ||||
| 		setSlotData(artPlace, slot); | ||||
| 		slot = inc(slot); | ||||
| 	} | ||||
|  | ||||
| 	// Blocking scrolling if there is not enough artifacts to scroll | ||||
| 	if(leftBackpackRoll) | ||||
| 		leftBackpackRoll->block(!scrollingPossible); | ||||
| 	if(rightBackpackRoll) | ||||
| 		rightBackpackRoll->block(!scrollingPossible); | ||||
|  | ||||
| 	redraw(); | ||||
| 	LOCPLINT->cb->scrollBackpackArtifacts(curHero->id, left); | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroBase::markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved) | ||||
| @@ -224,9 +182,18 @@ void CArtifactsOfHeroBase::updateWornSlots() | ||||
|  | ||||
| void CArtifactsOfHeroBase::updateBackpackSlots() | ||||
| { | ||||
| 	if(curHero->artifactsInBackpack.size() <= backpack.size() && backpackPos != 0) | ||||
| 		backpackPos = 0; | ||||
| 	scrollBackpack(0); | ||||
| 	ArtifactPosition slot = ArtifactPosition::BACKPACK_START; | ||||
| 	for(const auto & artPlace : backpack) | ||||
| 	{ | ||||
| 		setSlotData(artPlace, slot); | ||||
| 		slot = slot + 1; | ||||
| 	} | ||||
| 	auto scrollingPossible = static_cast<int>(curHero->artifactsInBackpack.size()) > backpack.size(); | ||||
| 	// Blocking scrolling if there is not enough artifacts to scroll | ||||
| 	if(leftBackpackRoll) | ||||
| 		leftBackpackRoll->block(!scrollingPossible); | ||||
| 	if(rightBackpackRoll) | ||||
| 		rightBackpackRoll->block(!scrollingPossible); | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroBase::updateSlot(const ArtifactPosition & slot) | ||||
|   | ||||
| @@ -36,7 +36,7 @@ public: | ||||
| 	virtual void gestureArtPlace(CArtPlace & artPlace, const Point & cursorPosition); | ||||
| 	virtual void setHero(const CGHeroInstance * hero); | ||||
| 	virtual const CGHeroInstance * getHero() const; | ||||
| 	virtual void scrollBackpack(int offset); | ||||
| 	virtual void scrollBackpack(bool left); | ||||
| 	virtual void markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved = true); | ||||
| 	virtual void unmarkSlots(); | ||||
| 	virtual ArtPlacePtr getArtPlace(const ArtifactPosition & slot); | ||||
| @@ -52,7 +52,6 @@ protected: | ||||
| 	std::vector<ArtPlacePtr> backpack; | ||||
| 	std::shared_ptr<CButton> leftBackpackRoll; | ||||
| 	std::shared_ptr<CButton> rightBackpackRoll; | ||||
| 	int backpackPos; // Position to display artifacts in heroes backpack | ||||
| 	PutBackPickedArtCallback putBackPickedArtCallback; | ||||
|  | ||||
| 	const std::vector<Point> slotPos = | ||||
| @@ -66,8 +65,8 @@ protected: | ||||
| 		Point(381,295) //18 | ||||
| 	}; | ||||
|  | ||||
| 	virtual void init(CHeroArtPlace::ClickFunctor lClickCallback, CHeroArtPlace::ClickFunctor showPopupCallback, | ||||
| 		const Point & position, BpackScrollFunctor scrollCallback); | ||||
| 	virtual void init(const CHeroArtPlace::ClickFunctor & lClickCallback, const CHeroArtPlace::ClickFunctor & showPopupCallback, | ||||
| 		const Point & position, const BpackScrollFunctor & scrollCallback); | ||||
| 	// Assigns an artifacts to an artifact place depending on it's new slot ID | ||||
| 	virtual void setSlotData(ArtPlacePtr artPlace, const ArtifactPosition & slot); | ||||
| }; | ||||
|   | ||||
| @@ -18,7 +18,7 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position) | ||||
| 		std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), | ||||
| 		std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), | ||||
| 		position, | ||||
| 		std::bind(&CArtifactsOfHeroMarket::scrollBackpack, this, _1)); | ||||
| 		std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1)); | ||||
|  | ||||
| 	for(const auto & [slot, artPlace] : artWorn) | ||||
| 		artPlace->setSelectionWidth(2); | ||||
| @@ -26,9 +26,9 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position) | ||||
| 		artPlace->setSelectionWidth(2); | ||||
| }; | ||||
|  | ||||
| void CArtifactsOfHeroMarket::scrollBackpack(int offset) | ||||
| void CArtifactsOfHeroMarket::scrollBackpack(bool left) | ||||
| { | ||||
| 	CArtifactsOfHeroBase::scrollBackpack(offset); | ||||
| 	CArtifactsOfHeroBase::scrollBackpack(left); | ||||
|  | ||||
| 	// We may have highlight on one of backpack artifacts | ||||
| 	if(selectArtCallback) | ||||
|   | ||||
| @@ -17,5 +17,5 @@ public: | ||||
| 	std::function<void(CArtPlace*)> selectArtCallback; | ||||
|  | ||||
| 	CArtifactsOfHeroMarket(const Point & position); | ||||
| 	void scrollBackpack(int offset) override; | ||||
| 	void scrollBackpack(bool left) override; | ||||
| }; | ||||
|   | ||||
| @@ -145,7 +145,11 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsI | ||||
| 					if(artSetPtr->getHero()->getOwner() == LOCPLINT->playerID) | ||||
| 					{ | ||||
| 						if(checkSpecialArts(*art, hero, std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroAltar>> ? true : false)) | ||||
| 							LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot), ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS)); | ||||
| 						{ | ||||
| 							assert(artSetPtr->getHero()->getSlotByInstance(art)); | ||||
| 							LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artSetPtr->getHero()->getSlotByInstance(art)), | ||||
| 								ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS)); | ||||
| 						} | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
|   | ||||
| @@ -192,7 +192,7 @@ class DLL_LINKAGE CArtifactSet | ||||
| public: | ||||
| 	using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>; | ||||
|  | ||||
| 	std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag | ||||
| 	std::deque<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::vector<ArtSlotInfo> artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange | ||||
|  | ||||
|   | ||||
| @@ -110,7 +110,7 @@ public: | ||||
| 	virtual bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) = 0; | ||||
| 	virtual bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble = std::nullopt) = 0; | ||||
| 	virtual void removeArtifact(const ArtifactLocation &al) = 0; | ||||
| 	virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0; | ||||
| 	virtual bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) = 0; | ||||
|  | ||||
| 	virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0; | ||||
| 	virtual void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero)=0; | ||||
|   | ||||
| @@ -131,6 +131,7 @@ public: | ||||
| 	virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) {} | ||||
| 	virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) {} | ||||
| 	virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) {} | ||||
| 	virtual void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) {} | ||||
| 	virtual void visitAssembleArtifacts(AssembleArtifacts & pack) {} | ||||
| 	virtual void visitEraseArtifactByClient(EraseArtifactByClient & pack) {} | ||||
| 	virtual void visitBuyArtifact(BuyArtifact & pack) {} | ||||
|   | ||||
| @@ -608,6 +608,11 @@ void BulkExchangeArtifacts::visitTyped(ICPackVisitor & visitor) | ||||
| 	visitor.visitBulkExchangeArtifacts(*this); | ||||
| } | ||||
|  | ||||
| void ManageBackpackArtifacts::visitTyped(ICPackVisitor & visitor) | ||||
| { | ||||
| 	visitor.visitManageBackpackArtifacts(*this); | ||||
| } | ||||
|  | ||||
| void AssembleArtifacts::visitTyped(ICPackVisitor & visitor) | ||||
| { | ||||
| 	visitor.visitAssembleArtifacts(*this); | ||||
|   | ||||
| @@ -1030,10 +1030,11 @@ struct DLL_LINKAGE EraseArtifact : CArtifactOperationPack | ||||
| struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack | ||||
| { | ||||
| 	MoveArtifact() = default; | ||||
| 	MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst, bool askAssemble = true) | ||||
| 		: src(*src), dst(*dst), askAssemble(askAssemble) | ||||
| 	MoveArtifact(const PlayerColor & interfaceOwner, const ArtifactLocation & src, const ArtifactLocation & dst, bool askAssemble = true) | ||||
| 		: interfaceOwner(interfaceOwner), src(src), dst(dst), askAssemble(askAssemble) | ||||
| 	{ | ||||
| 	} | ||||
| 	PlayerColor interfaceOwner; | ||||
| 	ArtifactLocation src; | ||||
| 	ArtifactLocation dst; | ||||
| 	bool askAssemble = true; | ||||
| @@ -1043,6 +1044,7 @@ struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler & h) | ||||
| 	{ | ||||
| 		h & interfaceOwner; | ||||
| 		h & src; | ||||
| 		h & dst; | ||||
| 		h & askAssemble; | ||||
| @@ -1069,13 +1071,15 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	PlayerColor interfaceOwner; | ||||
| 	ObjectInstanceID srcArtHolder; | ||||
| 	ObjectInstanceID dstArtHolder; | ||||
| 	std::optional<SlotID> srcCreature; | ||||
| 	std::optional<SlotID> dstCreature; | ||||
|  | ||||
| 	BulkMoveArtifacts() | ||||
| 		: srcArtHolder(ObjectInstanceID::NONE) | ||||
| 		: interfaceOwner(PlayerColor::NEUTRAL) | ||||
| 		, srcArtHolder(ObjectInstanceID::NONE) | ||||
| 		, dstArtHolder(ObjectInstanceID::NONE) | ||||
| 		, swap(false) | ||||
| 		, askAssemble(false) | ||||
| @@ -1083,9 +1087,10 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack | ||||
| 		, dstCreature(std::nullopt) | ||||
| 	{ | ||||
| 	} | ||||
| 	BulkMoveArtifacts(const ObjectInstanceID srcArtHolder, const ObjectInstanceID dstArtHolder, bool swap) | ||||
| 		: srcArtHolder(std::move(srcArtHolder)) | ||||
| 		, dstArtHolder(std::move(dstArtHolder)) | ||||
| 	BulkMoveArtifacts(const PlayerColor & interfaceOwner, const ObjectInstanceID srcArtHolder, const ObjectInstanceID dstArtHolder, bool swap) | ||||
| 		: interfaceOwner(interfaceOwner) | ||||
| 		, srcArtHolder(srcArtHolder) | ||||
| 		, dstArtHolder(dstArtHolder) | ||||
| 		, swap(swap) | ||||
| 		, askAssemble(false) | ||||
| 		, srcCreature(std::nullopt) | ||||
| @@ -1104,6 +1109,7 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler & h) | ||||
| 	{ | ||||
| 		h & interfaceOwner; | ||||
| 		h & artsPack0; | ||||
| 		h & artsPack1; | ||||
| 		h & srcArtHolder; | ||||
|   | ||||
| @@ -401,6 +401,33 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE ManageBackpackArtifacts : public CPackForServer | ||||
| { | ||||
| 	enum class ManageCmd | ||||
| 	{ | ||||
| 		SCROLL_LEFT, SCROLL_RIGHT, SORT_BY_SLOT, SORT_BY_CLASS, SORT_BY_COST | ||||
| 	}; | ||||
| 	 | ||||
| 	ManageBackpackArtifacts() = default; | ||||
| 	ManageBackpackArtifacts(const ObjectInstanceID & artHolder, const ManageCmd & cmd) | ||||
| 		: artHolder(artHolder) | ||||
| 		, cmd(cmd) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	ObjectInstanceID artHolder; | ||||
| 	ManageCmd cmd; | ||||
|  | ||||
| 	void visitTyped(ICPackVisitor & visitor) override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler & h) | ||||
| 	{ | ||||
| 		h & static_cast<CPackForServer&>(*this); | ||||
| 		h & artHolder; | ||||
| 		h & cmd; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE AssembleArtifacts : public CPackForServer | ||||
| { | ||||
| 	AssembleArtifacts() = default; | ||||
|   | ||||
| @@ -49,6 +49,7 @@ void registerTypesServerPacks(Serializer &s) | ||||
| 	s.template registerType<CPackForServer, BulkSmartSplitStack>(); | ||||
| 	s.template registerType<CPackForServer, BulkMoveArmy>(); | ||||
| 	s.template registerType<CPackForServer, BulkExchangeArtifacts>(); | ||||
| 	s.template registerType < CPackForServer, ManageBackpackArtifacts>(); | ||||
| 	s.template registerType<CPackForServer, EraseArtifactByClient>(); | ||||
| 	s.template registerType<CPackForServer, GamePause>(); | ||||
| } | ||||
|   | ||||
| @@ -218,6 +218,15 @@ public: | ||||
| 			load( data[i]); | ||||
| 	} | ||||
|  | ||||
| 	template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int  > = 0> | ||||
| 	void load(std::deque<T> & data) | ||||
| 	{ | ||||
| 		ui32 length = readAndCheckLength(); | ||||
| 		data.resize(length); | ||||
| 		for(ui32 i = 0; i < length; i++) | ||||
| 			load(data[i]); | ||||
| 	} | ||||
|  | ||||
| 	template < typename T, typename std::enable_if_t < std::is_pointer_v<T>, int  > = 0 > | ||||
| 	void load(T &data) | ||||
| 	{ | ||||
|   | ||||
| @@ -276,6 +276,14 @@ public: | ||||
| 		for(ui32 i=0;i<length;i++) | ||||
| 			save(data[i]); | ||||
| 	} | ||||
| 	template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int  > = 0> | ||||
| 	void save(const std::deque<T> & data) | ||||
| 	{ | ||||
| 		ui32 length = (ui32)data.size(); | ||||
| 		*this & length; | ||||
| 		for(ui32 i = 0; i < length; i++) | ||||
| 			save(data[i]); | ||||
| 	} | ||||
| 	template <typename T, size_t N> | ||||
| 	void save(const std::array<T, N> &data) | ||||
| 	{ | ||||
|   | ||||
| @@ -2690,7 +2690,7 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid) | ||||
|  | ||||
| // With the amount of changes done to the function, it's more like transferArtifacts. | ||||
| // Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced. | ||||
| bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst) | ||||
| bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocation & src, const ArtifactLocation & dst) | ||||
| { | ||||
| 	const auto srcArtSet = getArtSet(src); | ||||
| 	const auto dstArtSet = getArtSet(dst); | ||||
| @@ -2733,7 +2733,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca | ||||
| 	if(src.slot == dstSlot && src.artHolder == dst.artHolder) | ||||
| 		COMPLAIN_RET("Won't move artifact: Dest same as source!"); | ||||
| 	 | ||||
| 	BulkMoveArtifacts ma(src.artHolder, dst.artHolder, false); | ||||
| 	BulkMoveArtifacts ma(player, src.artHolder, dst.artHolder, false); | ||||
| 	ma.srcCreature = src.creature; | ||||
| 	ma.dstCreature = dst.creature; | ||||
| 	 | ||||
| @@ -2756,7 +2756,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack) | ||||
| bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack) | ||||
| { | ||||
| 	// Make sure exchange is even possible between the two heroes. | ||||
| 	if(!isAllowedExchange(srcId, dstId)) | ||||
| @@ -2767,7 +2767,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID ds | ||||
| 	if((!psrcSet) || (!pdstSet)) | ||||
| 		COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID"); | ||||
|  | ||||
| 	BulkMoveArtifacts ma(srcId, dstId, swap); | ||||
| 	BulkMoveArtifacts ma(player, srcId, dstId, swap); | ||||
| 	auto & slotsSrcDst = ma.artsPack0; | ||||
| 	auto & slotsDstSrc = ma.artsPack1; | ||||
|  | ||||
| @@ -2857,6 +2857,25 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID ds | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left) | ||||
| { | ||||
| 	auto artSet = getArtSet(heroID); | ||||
| 	COMPLAIN_RET_FALSE_IF(artSet == nullptr, "scrollBackpackArtifacts: wrong hero's ID"); | ||||
|  | ||||
| 	BulkMoveArtifacts bma(player, heroID, heroID, false); | ||||
|  | ||||
| 	const auto backpackEnd = ArtifactPosition(ArtifactPosition::BACKPACK_START + artSet->artifactsInBackpack.size() - 1); | ||||
| 	if(backpackEnd > ArtifactPosition::BACKPACK_START) | ||||
| 	{ | ||||
| 		if(left) | ||||
| 			bma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(backpackEnd, ArtifactPosition::BACKPACK_START)); | ||||
| 		else | ||||
| 			bma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(ArtifactPosition::BACKPACK_START, backpackEnd)); | ||||
| 		sendAndApply(&bma); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Assembles or disassembles a combination artifact. | ||||
|  * @param heroID ID of hero holding the artifact(s). | ||||
|   | ||||
| @@ -128,8 +128,9 @@ public: | ||||
| 	bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos = ArtifactPosition::FIRST_AVAILABLE) override; | ||||
| 	bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override; | ||||
| 	void removeArtifact(const ArtifactLocation &al) override; | ||||
| 	bool moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst) override; | ||||
| 	bool bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack); | ||||
| 	bool moveArtifact(const PlayerColor & player, const ArtifactLocation & src, const ArtifactLocation & dst) override; | ||||
| 	bool bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack); | ||||
| 	bool scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left); | ||||
| 	bool eraseArtifactByClient(const ArtifactLocation & al); | ||||
| 	void synchronizeArtifactHandlerLists(); | ||||
|  | ||||
|   | ||||
| @@ -136,7 +136,7 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack) | ||||
| { | ||||
| 	if(gh.getHero(pack.src.artHolder)) | ||||
| 		gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally | ||||
| 	result = gh.moveArtifact(pack.src, pack.dst); | ||||
| 	result = gh.moveArtifact(pack.player, pack.src, pack.dst); | ||||
| } | ||||
|  | ||||
| void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) | ||||
| @@ -145,7 +145,28 @@ void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & p | ||||
| 		gh.throwIfWrongOwner(&pack, pack.srcHero); | ||||
| 	if(pack.swap) | ||||
| 		gh.throwIfWrongOwner(&pack, pack.dstHero); | ||||
| 	result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack); | ||||
| 	result = gh.bulkMoveArtifacts(pack.player, pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack); | ||||
| } | ||||
|  | ||||
| void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) | ||||
| { | ||||
| 	if(gh.getPlayerRelations(pack.player, gh.getOwner(pack.artHolder)) != PlayerRelations::ENEMIES) | ||||
| 	{ | ||||
| 		if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SCROLL_LEFT) | ||||
| 			result = gh.scrollBackpackArtifacts(pack.player, pack.artHolder, true); | ||||
| 		else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SCROLL_RIGHT) | ||||
| 			result = gh.scrollBackpackArtifacts(pack.player, pack.artHolder, false); | ||||
| 		else | ||||
| 		{ | ||||
| 			gh.throwIfWrongOwner(&pack, pack.artHolder); | ||||
| 			if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_CLASS) | ||||
| 				result = true; | ||||
| 			else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_COST) | ||||
| 				result = true; | ||||
| 			else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_SLOT) | ||||
| 				result = true; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack) | ||||
|   | ||||
| @@ -46,6 +46,7 @@ public: | ||||
| 	void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) override; | ||||
| 	void visitExchangeArtifacts(ExchangeArtifacts & pack) override; | ||||
| 	void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) override; | ||||
| 	void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) override; | ||||
| 	void visitAssembleArtifacts(AssembleArtifacts & pack) override; | ||||
| 	void visitEraseArtifactByClient(EraseArtifactByClient & pack) override; | ||||
| 	void visitBuyArtifact(BuyArtifact & pack) override; | ||||
|   | ||||
| @@ -128,6 +128,9 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const | ||||
| 	if(auto arts = dynamic_ptr_cast<BulkExchangeArtifacts>(pack)) | ||||
| 		return !vstd::contains(ourIds, arts->srcHero) || !vstd::contains(ourIds, arts->dstHero); | ||||
|  | ||||
| 	if(auto arts = dynamic_ptr_cast<ManageBackpackArtifacts>(pack)) | ||||
| 		return !vstd::contains(ourIds, arts->artHolder); | ||||
|  | ||||
| 	if(auto art = dynamic_ptr_cast<EraseArtifactByClient>(pack)) | ||||
| 	{ | ||||
| 		if(auto id = art->al.artHolder) | ||||
| @@ -203,6 +206,9 @@ bool OpenWindowQuery::blocksPack(const CPack *pack) const | ||||
| 		if(dynamic_ptr_cast<BulkExchangeArtifacts>(pack) != nullptr) | ||||
| 			return false; | ||||
|  | ||||
| 		if(dynamic_ptr_cast<ManageBackpackArtifacts>(pack) != nullptr) | ||||
| 			return false; | ||||
|  | ||||
| 		if(dynamic_ptr_cast<AssembleArtifacts>(pack)) | ||||
| 			return false; | ||||
|  | ||||
|   | ||||
| @@ -70,7 +70,7 @@ public: | ||||
| 	bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) override {return false;} | ||||
| 	bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override {return false;} | ||||
| 	void removeArtifact(const ArtifactLocation &al) override {} | ||||
| 	bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;} | ||||
| 	bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;} | ||||
|  | ||||
| 	void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {} | ||||
| 	void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user