mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Saving costume
This commit is contained in:
		| @@ -193,6 +193,14 @@ void CCallback::scrollBackpackArtifacts(ObjectInstanceID hero, bool left) | ||||
| 	sendRequest(&mba); | ||||
| } | ||||
|  | ||||
| void CCallback::manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) | ||||
| { | ||||
| 	assert(costumeIndex < GameConstants::HERO_COSTUMES_ARTIFACTS); | ||||
|  | ||||
| 	ManageEquippedArtifacts mea(hero, costumeIndex, saveCostume); | ||||
| 	sendRequest(&mea); | ||||
| } | ||||
|  | ||||
| void CCallback::eraseArtifactByClient(const ArtifactLocation & al) | ||||
| { | ||||
| 	EraseArtifactByClient ea(al); | ||||
|   | ||||
| @@ -92,6 +92,7 @@ public: | ||||
| 	//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 manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) = 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; | ||||
| @@ -178,6 +179,7 @@ public: | ||||
| 	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 manageHeroCostume(ObjectInstanceID hero, size_t costumeIdx, bool saveCostume) 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; | ||||
|   | ||||
| @@ -158,6 +158,16 @@ enum class EShortcut | ||||
| 	HERO_TIGHT_FORMATION, | ||||
| 	HERO_TOGGLE_TACTICS, // b | ||||
| 	HERO_BACKPACK, | ||||
| 	HERO_COSTUME_0, | ||||
| 	HERO_COSTUME_1, | ||||
| 	HERO_COSTUME_2, | ||||
| 	HERO_COSTUME_3, | ||||
| 	HERO_COSTUME_4, | ||||
| 	HERO_COSTUME_5, | ||||
| 	HERO_COSTUME_6, | ||||
| 	HERO_COSTUME_7, | ||||
| 	HERO_COSTUME_8, | ||||
| 	HERO_COSTUME_9, | ||||
|  | ||||
| 	// Spellbook screen | ||||
| 	SPELLBOOK_TAB_ADVENTURE, | ||||
|   | ||||
| @@ -180,6 +180,16 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const | ||||
| 		{"heroLooseFormation",       EShortcut::HERO_LOOSE_FORMATION      }, | ||||
| 		{"heroTightFormation",       EShortcut::HERO_TIGHT_FORMATION      }, | ||||
| 		{"heroToggleTactics",        EShortcut::HERO_TOGGLE_TACTICS       }, | ||||
| 		{"heroCostume0",             EShortcut::HERO_COSTUME_0            }, | ||||
| 		{"heroCostume1",             EShortcut::HERO_COSTUME_1            }, | ||||
| 		{"heroCostume2",             EShortcut::HERO_COSTUME_2            }, | ||||
| 		{"heroCostume3",             EShortcut::HERO_COSTUME_3            }, | ||||
| 		{"heroCostume4",             EShortcut::HERO_COSTUME_4            }, | ||||
| 		{"heroCostume5",             EShortcut::HERO_COSTUME_5            }, | ||||
| 		{"heroCostume6",             EShortcut::HERO_COSTUME_6            }, | ||||
| 		{"heroCostume7",             EShortcut::HERO_COSTUME_7            }, | ||||
| 		{"heroCostume8",             EShortcut::HERO_COSTUME_8            }, | ||||
| 		{"heroCostume9",             EShortcut::HERO_COSTUME_9            }, | ||||
| 		{"spellbookTabAdventure",    EShortcut::SPELLBOOK_TAB_ADVENTURE   }, | ||||
| 		{"spellbookTabCombat",       EShortcut::SPELLBOOK_TAB_COMBAT      } | ||||
| 	}; | ||||
|   | ||||
| @@ -10,13 +10,15 @@ | ||||
| #include "StdInc.h" | ||||
| #include "CArtifactsOfHeroMain.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
|  | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../../lib/mapObjects/CGHeroInstance.h" | ||||
|  | ||||
| #include "../../CCallback.h" | ||||
| #include "../../lib/networkPacks/ArtifactLocation.h" | ||||
|  | ||||
| CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position) | ||||
| CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position, bool costumesEnabled) | ||||
| { | ||||
| 	init( | ||||
| 		std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), | ||||
| @@ -24,9 +26,41 @@ CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position) | ||||
| 		position, | ||||
| 		std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1)); | ||||
| 	addGestureCallback(std::bind(&CArtifactsOfHeroBase::gestureArtPlace, this, _1, _2)); | ||||
|  | ||||
| 	if(costumesEnabled) | ||||
| 	{ | ||||
| 		size_t costumeIndex = 0; | ||||
| 		for(const auto & hotkey : hotkeys) | ||||
| 		{ | ||||
| 			auto keyProc = costumesSwitchers.emplace_back(std::make_shared<CKeyShortcutWrapper>(hotkey, | ||||
| 				[this, hotkey, costumeIndex]() | ||||
| 				{ | ||||
| 					CArtifactsOfHeroMain::onCostumeSelect(costumeIndex); | ||||
| 				})); | ||||
| 			keyProc->addUsedEvents(AEventsReceiver::KEYBOARD); | ||||
| 			costumeIndex++; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CArtifactsOfHeroMain::~CArtifactsOfHeroMain() | ||||
| { | ||||
| 	CArtifactsOfHeroBase::putBackPickedArtifact(); | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroMain::onCostumeSelect(const size_t costumeIndex) | ||||
| { | ||||
| 	LOCPLINT->cb->manageHeroCostume(getHero()->id, costumeIndex, GH.isKeyboardCtrlDown()); | ||||
| } | ||||
|  | ||||
| CArtifactsOfHeroMain::CKeyShortcutWrapper::CKeyShortcutWrapper(const EShortcut & key, const KeyPressedFunctor & onCostumeSelect) | ||||
| 	: CKeyShortcut(key) | ||||
| 	, onCostumeSelect(onCostumeSelect) | ||||
| { | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHeroMain::CKeyShortcutWrapper::clickPressed(const Point & cursorPosition) | ||||
| { | ||||
| 	if(onCostumeSelect) | ||||
| 		onCostumeSelect(); | ||||
| } | ||||
|   | ||||
| @@ -11,15 +11,42 @@ | ||||
|  | ||||
| #include "CArtifactsOfHeroBase.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| struct ArtifactLocation; | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
| #include "../gui/Shortcut.h" | ||||
|  | ||||
| class CArtifactsOfHeroMain : public CArtifactsOfHeroBase | ||||
| { | ||||
| public: | ||||
| 	CArtifactsOfHeroMain(const Point & position); | ||||
| 	CArtifactsOfHeroMain(const Point & position, bool costumesEnabled = false); | ||||
| 	~CArtifactsOfHeroMain() override; | ||||
|  | ||||
| private: | ||||
| 	// TODO may be removed if CKeyShortcut supports callbacks | ||||
| 	class CKeyShortcutWrapper : public CKeyShortcut | ||||
| 	{ | ||||
| 	public: | ||||
| 		using KeyPressedFunctor = std::function<void()>; | ||||
|  | ||||
| 		CKeyShortcutWrapper(const EShortcut & key, const KeyPressedFunctor & onCostumeSelect); | ||||
| 		void clickPressed(const Point & cursorPosition) override; | ||||
|  | ||||
| 	private: | ||||
| 		KeyPressedFunctor onCostumeSelect; | ||||
| 	}; | ||||
|  | ||||
| 	const std::array<EShortcut, GameConstants::HERO_COSTUMES_ARTIFACTS> hotkeys = | ||||
| 	{ | ||||
| 		EShortcut::HERO_COSTUME_0, | ||||
| 		EShortcut::HERO_COSTUME_1, | ||||
| 		EShortcut::HERO_COSTUME_2, | ||||
| 		EShortcut::HERO_COSTUME_3, | ||||
| 		EShortcut::HERO_COSTUME_4, | ||||
| 		EShortcut::HERO_COSTUME_5, | ||||
| 		EShortcut::HERO_COSTUME_6, | ||||
| 		EShortcut::HERO_COSTUME_7, | ||||
| 		EShortcut::HERO_COSTUME_8, | ||||
| 		EShortcut::HERO_COSTUME_9 | ||||
| 	}; | ||||
| 	std::vector<std::shared_ptr<CKeyShortcutWrapper>> costumesSwitchers; | ||||
|  | ||||
| 	void onCostumeSelect(const size_t costumeIndex); | ||||
| }; | ||||
|   | ||||
| @@ -218,7 +218,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) | ||||
| 		} | ||||
| 		if(!arts) | ||||
| 		{ | ||||
| 			arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8)); | ||||
| 			arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8), true); | ||||
| 			arts->setHero(curHero); | ||||
| 			addSetAndCallbacks(arts); | ||||
| 		} | ||||
|   | ||||
| @@ -125,6 +125,16 @@ | ||||
| 		"heroTightFormation":       "T", | ||||
| 		"heroToggleTactics":        "B", | ||||
| 		"spellbookTabAdventure":    "A", | ||||
| 		"spellbookTabCombat":       "C" | ||||
| 		"spellbookTabCombat":       "C", | ||||
| 		"heroCostume0":             "0", | ||||
| 		"heroCostume1":             "1", | ||||
| 		"heroCostume2":             "2", | ||||
| 		"heroCostume3":             "3", | ||||
| 		"heroCostume4":             "4", | ||||
| 		"heroCostume5":             "5", | ||||
| 		"heroCostume6":             "6", | ||||
| 		"heroCostume7":             "7", | ||||
| 		"heroCostume8":             "8", | ||||
| 		"heroCostume9":             "9" | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -63,6 +63,7 @@ public: | ||||
| 	std::vector<ConstTransitivePtr<CGDwelling> > dwellings; //used for town growth | ||||
| 	std::vector<QuestInfo> quests; //store info about all received quests | ||||
| 	std::vector<Bonus> battleBonuses; //additional bonuses to be added during battle with neutrals | ||||
| 	std::map<size_t, std::map<ArtifactPosition, ArtifactID>> costumesArtifacts; | ||||
|  | ||||
| 	bool cheated; | ||||
| 	bool enteredWinningCheatCode, enteredLosingCheatCode; //if true, this player has entered cheat codes for loss / victory | ||||
| @@ -111,6 +112,7 @@ public: | ||||
| 		h & daysWithoutCastle; | ||||
| 		h & cheated; | ||||
| 		h & battleBonuses; | ||||
| 		h & costumesArtifacts; | ||||
| 		h & enteredLosingCheatCode; | ||||
| 		h & enteredWinningCheatCode; | ||||
| 		h & static_cast<CBonusSystemNode&>(*this); | ||||
|   | ||||
| @@ -87,6 +87,7 @@ public: | ||||
| 	virtual void visitInfoWindow(InfoWindow & pack) {} | ||||
| 	virtual void visitSetObjectProperty(SetObjectProperty & pack) {} | ||||
| 	virtual void visitChangeObjectVisitors(ChangeObjectVisitors & pack) {} | ||||
| 	virtual void visitChangeArtifactsCostume(ChangeArtifactsCostume & pack) {} | ||||
| 	virtual void visitHeroLevelUp(HeroLevelUp & pack) {} | ||||
| 	virtual void visitCommanderLevelUp(CommanderLevelUp & pack) {} | ||||
| 	virtual void visitBlockingDialog(BlockingDialog & pack) {} | ||||
| @@ -132,6 +133,7 @@ public: | ||||
| 	virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) {} | ||||
| 	virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) {} | ||||
| 	virtual void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) {} | ||||
| 	virtual void visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) {} | ||||
| 	virtual void visitAssembleArtifacts(AssembleArtifacts & pack) {} | ||||
| 	virtual void visitEraseArtifactByClient(EraseArtifactByClient & pack) {} | ||||
| 	virtual void visitBuyArtifact(BuyArtifact & pack) {} | ||||
|   | ||||
| @@ -383,6 +383,11 @@ void ChangeObjectVisitors::visitTyped(ICPackVisitor & visitor) | ||||
| 	visitor.visitChangeObjectVisitors(*this); | ||||
| } | ||||
|  | ||||
| void ChangeArtifactsCostume::visitTyped(ICPackVisitor & visitor) | ||||
| { | ||||
| 	visitor.visitChangeArtifactsCostume(*this); | ||||
| } | ||||
|  | ||||
| void HeroLevelUp::visitTyped(ICPackVisitor & visitor) | ||||
| { | ||||
| 	visitor.visitHeroLevelUp(*this); | ||||
| @@ -613,6 +618,11 @@ void ManageBackpackArtifacts::visitTyped(ICPackVisitor & visitor) | ||||
| 	visitor.visitManageBackpackArtifacts(*this); | ||||
| } | ||||
|  | ||||
| void ManageEquippedArtifacts::visitTyped(ICPackVisitor & visitor) | ||||
| { | ||||
| 	visitor.visitManageEquippedArtifacts(*this); | ||||
| } | ||||
|  | ||||
| void AssembleArtifacts::visitTyped(ICPackVisitor & visitor) | ||||
| { | ||||
| 	visitor.visitAssembleArtifacts(*this); | ||||
| @@ -1062,6 +1072,15 @@ void ChangeObjectVisitors::applyGs(CGameState * gs) const | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void ChangeArtifactsCostume::applyGs(CGameState * gs) const | ||||
| { | ||||
| 	auto & allCostumes = gs->getPlayerState(player)->costumesArtifacts; | ||||
| 	if(auto & costume = allCostumes.find(costumeIdx); costume != allCostumes.end()) | ||||
| 		costume->second = costumeSet; | ||||
| 	else | ||||
| 		allCostumes.emplace(costumeIdx, costumeSet); | ||||
| } | ||||
|  | ||||
| void PlayerEndsGame::applyGs(CGameState * gs) const | ||||
| { | ||||
| 	PlayerState *p = gs->getPlayerState(player); | ||||
|   | ||||
| @@ -1288,6 +1288,30 @@ struct DLL_LINKAGE ChangeObjectVisitors : public CPackForClient | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE ChangeArtifactsCostume : public CPackForClient | ||||
| { | ||||
| 	std::map<ArtifactPosition, ArtifactID> costumeSet; | ||||
| 	size_t costumeIdx; | ||||
| 	const PlayerColor player; | ||||
|  | ||||
| 	void applyGs(CGameState * gs) const; | ||||
| 	void visitTyped(ICPackVisitor & visitor) override; | ||||
|  | ||||
| 	ChangeArtifactsCostume() = default; | ||||
| 	ChangeArtifactsCostume(const PlayerColor & player, const size_t costumeIdx) | ||||
| 		: costumeIdx(costumeIdx) | ||||
| 		, player(player) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler & h) | ||||
| 	{ | ||||
| 		h & costumeSet; | ||||
| 		h & costumeIdx; | ||||
| 		h & player; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE HeroLevelUp : public Query | ||||
| { | ||||
| 	PlayerColor player; | ||||
|   | ||||
| @@ -429,6 +429,31 @@ struct DLL_LINKAGE ManageBackpackArtifacts : public CPackForServer | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE ManageEquippedArtifacts : public CPackForServer | ||||
| { | ||||
| 	ManageEquippedArtifacts() = default; | ||||
| 	ManageEquippedArtifacts(const ObjectInstanceID & artHolder, const size_t costumeIdx, bool saveCostume = false) | ||||
| 		: artHolder(artHolder) | ||||
| 		, costumeIdx(costumeIdx) | ||||
| 		, saveCostume(saveCostume) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	ObjectInstanceID artHolder; | ||||
| 	size_t costumeIdx; | ||||
| 	bool saveCostume; | ||||
|  | ||||
| 	void visitTyped(ICPackVisitor & visitor) override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler & h) | ||||
| 	{ | ||||
| 		h & static_cast<CPackForServer&>(*this); | ||||
| 		h & artHolder; | ||||
| 		h & costumeIdx; | ||||
| 		h & saveCostume; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE AssembleArtifacts : public CPackForServer | ||||
| { | ||||
| 	AssembleArtifacts() = default; | ||||
|   | ||||
| @@ -67,6 +67,7 @@ void registerTypesClientPacks(Serializer &s) | ||||
| 	s.template registerType<CPackForClient, HeroVisit>(); | ||||
| 	s.template registerType<CPackForClient, SetCommanderProperty>(); | ||||
| 	s.template registerType<CPackForClient, ChangeObjectVisitors>(); | ||||
| 	s.template registerType<CPackForClient, ChangeArtifactsCostume>(); | ||||
| 	s.template registerType<CPackForClient, ShowWorldViewEx>(); | ||||
| 	s.template registerType<CPackForClient, EntitiesChanged>(); | ||||
| 	s.template registerType<CPackForClient, BattleStart>(); | ||||
|   | ||||
| @@ -49,7 +49,8 @@ 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, ManageBackpackArtifacts>(); | ||||
| 	s.template registerType<CPackForServer, ManageEquippedArtifacts>(); | ||||
| 	s.template registerType<CPackForServer, EraseArtifactByClient>(); | ||||
| 	s.template registerType<CPackForServer, GamePause>(); | ||||
| } | ||||
|   | ||||
| @@ -2892,6 +2892,24 @@ bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const Obj | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool CGameHandler::saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx) | ||||
| { | ||||
| 	auto artSet = getArtSet(heroID); | ||||
| 	COMPLAIN_RET_FALSE_IF(artSet == nullptr, "saveArtifactsCostume: wrong hero's ID"); | ||||
| 	COMPLAIN_RET_FALSE_IF(costumeIdx >= GameConstants::HERO_COSTUMES_ARTIFACTS, "saveArtifactsCostume: wrong costume index"); | ||||
|  | ||||
| 	ChangeArtifactsCostume costume(player, costumeIdx); | ||||
| 	for(const auto & slot : ArtifactUtils::constituentWornSlots()) | ||||
| 	{ | ||||
| 		if(const auto & slotInfo = artSet->getSlot(slot)) | ||||
| 			if(!slotInfo->locked) | ||||
| 				costume.costumeSet.emplace(slot, slotInfo->getArt()->getTypeId()); | ||||
| 	} | ||||
|  | ||||
| 	sendAndApply(&costume); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Assembles or disassembles a combination artifact. | ||||
|  * @param heroID ID of hero holding the artifact(s). | ||||
|   | ||||
| @@ -130,6 +130,7 @@ public: | ||||
| 	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 saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx); | ||||
| 	bool eraseArtifactByClient(const ArtifactLocation & al); | ||||
| 	void synchronizeArtifactHandlerLists(); | ||||
|  | ||||
|   | ||||
| @@ -179,6 +179,14 @@ void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) | ||||
| { | ||||
| 	gh.throwIfWrongOwner(&pack, pack.artHolder); | ||||
| 	if(pack.saveCostume) | ||||
| 		gh.saveArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx); | ||||
| 	result = true; | ||||
| } | ||||
|  | ||||
| void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack) | ||||
| { | ||||
| 	gh.throwIfWrongOwner(&pack, pack.heroID); | ||||
|   | ||||
| @@ -47,6 +47,7 @@ public: | ||||
| 	void visitExchangeArtifacts(ExchangeArtifacts & pack) override; | ||||
| 	void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) override; | ||||
| 	void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) override; | ||||
| 	void visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) override; | ||||
| 	void visitAssembleArtifacts(AssembleArtifacts & pack) override; | ||||
| 	void visitEraseArtifactByClient(EraseArtifactByClient & pack) override; | ||||
| 	void visitBuyArtifact(BuyArtifact & pack) override; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user