Bladeren bron

Partially redone combined artifacts.

Michał W. Urbańczyk 14 jaren geleden
bovenliggende
commit
3fde9e45df

+ 2 - 0
CGameInterface.h

@@ -103,6 +103,8 @@ public:
 	//artifacts operations
 	virtual void artifactPut(const ArtifactLocation &al){};
 	virtual void artifactRemoved(const ArtifactLocation &al){};
+	virtual void artifactAssembled(const ArtifactLocation &al){};
+	virtual void artifactDisassembled(const ArtifactLocation &al){};
 	virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){};
 
 	virtual void heroCreated(const CGHeroInstance*){};

+ 10 - 0
client/CPlayerInterface.cpp

@@ -2176,6 +2176,16 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
 				aoh->artifactMoved(src, dst);
 }
 
+void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
+{
+	boost::unique_lock<boost::recursive_mutex> un(*pim);
+}
+
+void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
+{
+	boost::unique_lock<boost::recursive_mutex> un(*pim);
+}
+
 CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
 {
 	spellbookLastPageBattle = spellbokLastPageAdvmap = 0;

+ 2 - 0
client/CPlayerInterface.h

@@ -170,6 +170,8 @@ public:
 	void artifactPut(const ArtifactLocation &al);
 	void artifactRemoved(const ArtifactLocation &al);
 	void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
+	void artifactAssembled(const ArtifactLocation &al);
+	void artifactDisassembled(const ArtifactLocation &al);
 
 	void heroCreated(const CGHeroInstance* hero) OVERRIDE;
 	void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback) OVERRIDE;

+ 16 - 11
client/GUIClasses.cpp

@@ -4532,7 +4532,7 @@ CRClickPopupInt::~CRClickPopupInt()
 }
 
 CArtPlace::CArtPlace(const CArtifactInstance* Art)
-	: marked(false), ourArt(Art), picked(false)
+	: marked(false), ourArt(Art), picked(false), locked(false)
 {
 }
 
@@ -4647,7 +4647,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 
 void CArtPlace::clickRight(tribool down, bool previousState)
 {
-	if(down && ourArt && !locked() && text.size())  //if there is no description or it's a lock, do nothing ;]
+	if(down && ourArt && !locked && text.size())  //if there is no description or it's a lock, do nothing ;]
 	{
 		if (slotID < 19) 
 		{
@@ -4695,7 +4695,7 @@ void CArtPlace::clickRight(tribool down, bool previousState)
  */
 void CArtPlace::select ()
 {
-	if (locked())
+	if (locked)
 		return;
 
 	picked = true;
@@ -4741,7 +4741,10 @@ void CArtPlace::deactivate()
 void CArtPlace::showAll(SDL_Surface *to)
 {
 	if (ourArt && !picked)
-		blitAt(graphics->artDefs->ourImages[ourArt->artType->id].bitmap, pos.x, pos.y, to);
+	{
+		int graphic = locked ? 145 : ourArt->artType->id;
+		blitAt(graphics->artDefs->ourImages[graphic].bitmap, pos.x, pos.y, to);
+	}
 
 	if(marked && active)
 	{
@@ -4779,11 +4782,6 @@ CArtPlace::~CArtPlace()
 	deactivate();
 }
 
-bool CArtPlace::locked() const
-{
-	return ourArt && ourArt->id == 145;
-}
-
 void CArtPlace::setMeAsDest(bool backpackAsVoid /*= true*/)
 {
 	ourOwner->commonInfo->dst.setTo(this, backpackAsVoid);
@@ -4800,7 +4798,7 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
 	else
 	{
 		text = ourArt->artType->Description();
-		if (locked()) // Locks should appear as empty.
+		if (locked) // Locks should appear as empty.
 			hoverText = CGI->generaltexth->allTexts[507];
 		else
 			hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->Name());
@@ -5113,7 +5111,14 @@ void CArtifactsOfHero::setSlotData(CArtPlace* artPlace, int slotID)
 
 	artPlace->picked = false;
 	artPlace->slotID = slotID;
-	artPlace->setArtifact(curHero->getArt(slotID));
+	
+	if(const ArtSlotInfo *asi = curHero->getSlot(slotID))
+	{
+		artPlace->setArtifact(asi->artifact);
+		artPlace->locked = asi->locked;
+	}
+	else
+		artPlace->setArtifact(NULL);
 } 
 
 /**

+ 1 - 1
client/GUIClasses.h

@@ -925,6 +925,7 @@ public:
 
 	bool picked;
 	bool marked;
+	bool locked;
 	CArtifactsOfHero * ourOwner;
 	const CArtifactInstance * ourArt;
 
@@ -937,7 +938,6 @@ public:
 	void deactivate();
 	void showAll(SDL_Surface * to);
 	bool fitsHere (const CArtifactInstance * art) const; //returns true if given artifact can be placed here
-	bool locked () const;
 
 	void setMeAsDest(bool backpackAsVoid = true);
 	void setArtifact(const CArtifactInstance *art);

+ 14 - 0
client/NetPacksClient.cpp

@@ -184,6 +184,20 @@ void MoveArtifact::applyCl( CClient *cl )
 		INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
 }
 
+void AssembledArtifact::applyCl( CClient *cl )
+{
+// 	INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
+// 	if(src.hero->tempOwner != dst.hero->tempOwner)
+// 		INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
+}
+
+void DisassembledArtifact::applyCl( CClient *cl )
+{
+// 	INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
+// 	if(src.hero->tempOwner != dst.hero->tempOwner)
+// 		INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
+}
+
 void GiveBonus::applyCl( CClient *cl )
 {
 	switch(who)

+ 6 - 0
global.h

@@ -547,6 +547,12 @@ t1 & abetw(t1 &a, const t2 &b, const t3 &c) //makes a to fit the range <b, c>
 	return a;
 }
 
+template <typename t1, typename t2, typename t3>
+bool isbetw(const t1 &a, const t2 &b, const t3 &c) //checks if a is between b and c
+{
+	return a > b && a < c;
+}
+
 template <typename T> 
 void delNull(T* &ptr) //deleted pointer and sets it to NULL
 {

+ 94 - 17
lib/CArtHandler.cpp

@@ -951,13 +951,7 @@ void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
 {
 	assert(canBePutAt(ArtifactLocation(h, slot)));
 
-	ArtSlotInfo &asi = slot < Arts::BACKPACK_START 
-						? h->artifactsWorn[slot]
-						: *h->artifactsInBackpack.insert(h->artifactsInBackpack.begin() + (slot - Arts::BACKPACK_START), ArtSlotInfo());
-
-	asi.artifact = this;
-	asi.locked = false;
-
+	h->setNewArtSlot(slot, this, false);
 	if(slot < Arts::BACKPACK_START)
 		h->attachTo(this);
 }
@@ -965,16 +959,9 @@ void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
 void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
 {
 	assert(h->CArtifactSet::getArt(slot) == this);
+	h->eraseArtSlot(slot);
 	if(slot < Arts::BACKPACK_START)
-	{
-		h->artifactsWorn.erase(slot);
 		h->detachFrom(this);
-	}
-	else
-	{
-		slot -= Arts::BACKPACK_START;
-		h->artifactsInBackpack.erase(h->artifactsInBackpack.begin() + slot);
-	}
 
 	//TODO delete me?
 }
@@ -1024,7 +1011,11 @@ CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art)
 	if(!Art->constituents)
 		return new CArtifactInstance(Art);
 	else
-		return new CCombinedArtifactInstance(Art);
+	{
+		CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art);
+		ret->createConstituents();
+		return ret;
+	}
 }
 
 CArtifactInstance * CArtifactInstance::createNewArtifactInstance(int aid)
@@ -1060,10 +1051,96 @@ void CCombinedArtifactInstance::createConstituents()
 
 	BOOST_FOREACH(ui32 a, *artType->constituents)
 	{
-		constituentsInfo.push_back(ConstituentInfo(CArtifactInstance::createNewArtifactInstance(a)));
+		addAsConstituent(CArtifactInstance::createNewArtifactInstance(a), -1);
+	}
+}
+
+void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, int slot)
+{
+	assert(vstd::contains(*artType->constituents, art->artType->id));
+	assert(art->parents.size() == 1  &&  art->parents.front() == art->artType);
+	constituentsInfo.push_back(ConstituentInfo(art, slot));
+	art->attachTo(this);
+}
+
+void CCombinedArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
+{
+	if(slot >= Arts::BACKPACK_START)
+	{
+		CArtifactInstance::putAt(h, slot);
+		BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
+			ci.slot = -1;
+	}
+	else
+	{
+		CArtifactInstance *mainConstituent = figureMainConstituent(slot); //it'll be replaced with combined artifact, not a lock
+
+		BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
+		{
+			if(ci.art != mainConstituent)
+			{
+				int pos = -1;
+				if(isbetw(ci.slot, 0, Arts::BACKPACK_START)  &&  ci.art->canBePutAt(ArtifactLocation(h, ci.slot))) //there is a valid suggestion where to place lock 
+					pos = ci.slot;
+				else
+					ci.slot = pos = ci.art->firstAvailableSlot(h);
+
+				assert(pos < Arts::BACKPACK_START);
+				h->setNewArtSlot(pos, ci.art, true); //sets as lock
+			}
+			else
+			{
+				ci.slot = -1;
+				CArtifactInstance::putAt(h, slot); //puts combined art (this)
+			}
+		}
+	}
+}
+
+void CCombinedArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
+{
+	if(slot >= Arts::BACKPACK_START)
+	{
+		CArtifactInstance::removeFrom(h, slot);
+	}
+	else
+	{
+		BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
+		{
+			if(ci.slot >= 0)
+			{
+				h->eraseArtSlot(ci.slot);
+				ci.slot = -1;
+			}
+			else
+			{
+				//main constituent
+				CArtifactInstance::removeFrom(h, slot);
+			}
+		}
 	}
 }
 
+CArtifactInstance * CCombinedArtifactInstance::figureMainConstituent(ui16 slot)
+{
+	CArtifactInstance *mainConstituent = NULL; //it'll be replaced with combined artifact, not a lock
+	BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
+		if(ci.slot == slot)
+			mainConstituent = ci.art;
+
+	if(!mainConstituent)
+	{
+		BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
+		{
+			if(vstd::contains(ci.art->artType->possibleSlots, slot))
+			{
+				mainConstituent = ci.art;
+			}
+		}
+	}
+
+	return mainConstituent;
+}
 
 CCombinedArtifactInstance::ConstituentInfo::ConstituentInfo(CArtifactInstance *Art /*= NULL*/, ui16 Slot /*= -1*/)
 {

+ 10 - 4
lib/CArtHandler.h

@@ -81,10 +81,10 @@ public:
 
 	virtual bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const;
 	virtual bool canBeDisassembled() const;
-	std::vector<const CArtifact *> assemblyPossibilities(const CGHeroInstance *h) const;
+	virtual void putAt(CGHeroInstance *h, ui16 slot);
+	virtual void removeFrom(CGHeroInstance *h, ui16 slot);
 
-	void putAt(CGHeroInstance *h, ui16 slot);
-	void removeFrom(CGHeroInstance *h, ui16 slot);
+	std::vector<const CArtifact *> assemblyPossibilities(const CGHeroInstance *h) const;
 	void move(ArtifactLocation &src, ArtifactLocation &dst);
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -118,11 +118,17 @@ public:
 
 	bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const OVERRIDE;
 	bool canBeDisassembled() const OVERRIDE;
+	void putAt(CGHeroInstance *h, ui16 slot) OVERRIDE;
+	void removeFrom(CGHeroInstance *h, ui16 slot) OVERRIDE;
 
-	CCombinedArtifactInstance();
 	void createConstituents();
+	void addAsConstituent(CArtifactInstance *art, int slot);
+	CArtifactInstance *figureMainConstituent(ui16 slot); //main constituent is replcaed with us (combined art), not lock
+
+	CCombinedArtifactInstance();
 
 	friend class CArtifactInstance;
+	friend class AssembledArtifact;
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CArtifactInstance&>(*this);

+ 34 - 0
lib/CObjectHandler.cpp

@@ -6940,6 +6940,10 @@ const CArtifactInstance* CArtifactSet::getArt(ui16 pos) const
 	return NULL;
 }
 
+CArtifactInstance* CArtifactSet::getArt(ui16 pos)
+{
+	return const_cast<CArtifactInstance*>((const_cast<const CArtifactSet*>(this))->getArt(pos));
+}
 // if(pos<19)
 // 	if(vstd::contains(artifWorn,pos))
 // 		return artifWorn.find(pos)->second;
@@ -7023,4 +7027,34 @@ si32 CArtifactSet::getArtTypeId(ui16 pos) const
 CArtifactSet::~CArtifactSet()
 {
 
+}
+
+ArtSlotInfo & CArtifactSet::retreiveNewArtSlot(ui16 slot)
+{
+	assert(!vstd::contains(artifactsWorn, slot));
+	ArtSlotInfo &ret = slot < Arts::BACKPACK_START 
+		? artifactsWorn[slot]
+		: *artifactsInBackpack.insert(artifactsInBackpack.begin() + (slot - Arts::BACKPACK_START), ArtSlotInfo());
+
+	return ret;
+}
+
+void CArtifactSet::setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked)
+{
+	ArtSlotInfo &asi = retreiveNewArtSlot(slot);
+	asi.artifact = art;
+	asi.locked = locked;
+}
+
+void CArtifactSet::eraseArtSlot(ui16 slot)
+{
+	if(slot < Arts::BACKPACK_START)
+	{
+		artifactsWorn.erase(slot);
+	}
+	else
+	{
+		slot -= Arts::BACKPACK_START;
+		artifactsInBackpack.erase(artifactsInBackpack.begin() + slot);
+	}
 }

+ 5 - 0
lib/CObjectHandler.h

@@ -265,8 +265,13 @@ public:
 	std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
 	bmap<ui16, 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
 
+	ArtSlotInfo &retreiveNewArtSlot(ui16 slot);
+	void setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked);
+	void eraseArtSlot(ui16 slot);
+
 	const ArtSlotInfo *getSlot(ui16 pos) const;
 	const CArtifactInstance* getArt(ui16 pos) const; //NULL - no artifact
+	CArtifactInstance* getArt(ui16 pos); //NULL - no artifact
 	si32 getArtPos(int aid, bool onlyWorn = true) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
 	si32 getArtPos(const CArtifactInstance *art) const;
 	bool hasArt(ui32 aid, bool onlyWorn = false) const; //checks if hero possess artifact of given id (either in backack or worn)

+ 36 - 3
lib/NetPacks.h

@@ -746,6 +746,10 @@ struct StackLocation
 struct CGarrisonOperationPack : CPackForClient
 {
 };
+struct CArtifactOperationPack : CPackForClient
+{
+};
+
 
 struct ChangeStackCount : CGarrisonOperationPack  //521
 {
@@ -856,7 +860,7 @@ struct ArtifactLocation
 	}
 };
 
-struct PutArtifact : CGarrisonOperationPack  //526
+struct PutArtifact : CArtifactOperationPack  //526
 {
 	ArtifactLocation al;
 	ConstTransitivePtr<CArtifactInstance> art;
@@ -870,7 +874,7 @@ struct PutArtifact : CGarrisonOperationPack  //526
 	}
 };
 
-struct EraseArtifact : CGarrisonOperationPack  //527
+struct EraseArtifact : CArtifactOperationPack  //527
 {
 	ArtifactLocation al;
 
@@ -883,7 +887,7 @@ struct EraseArtifact : CGarrisonOperationPack  //527
 	}
 };
 
-struct MoveArtifact : CGarrisonOperationPack  //528
+struct MoveArtifact : CArtifactOperationPack  //528
 {
 	ArtifactLocation src, dst;
 
@@ -896,6 +900,35 @@ struct MoveArtifact : CGarrisonOperationPack  //528
 	}
 };
 
+struct AssembledArtifact : CArtifactOperationPack  //529
+{
+	ArtifactLocation al; //where assembly will be put
+	CArtifact *builtArt;
+	//std::vector<CArtifactInstance *> constituents;
+
+
+	void applyCl(CClient *cl);
+	DLL_EXPORT void applyGs(CGameState *gs);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & al & builtArt/* & constituents*/;
+	}
+};
+
+struct DisassembledArtifact : CArtifactOperationPack  //530
+{
+	ArtifactLocation al;
+
+	void applyCl(CClient *cl);
+	DLL_EXPORT void applyGs(CGameState *gs);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & al;
+	}
+};
+
 struct NewTurn : public CPackForClient //101
 {
 	enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};

+ 32 - 5
lib/NetPacksLib.cpp

@@ -124,10 +124,10 @@ DLL_EXPORT void ChangeSpells::applyGs( CGameState *gs )
 
 	if(learn)
 		BOOST_FOREACH(ui32 sid, spells)
-		hero->spells.insert(sid);
+			hero->spells.insert(sid);
 	else
 		BOOST_FOREACH(ui32 sid, spells)
-		hero->spells.erase(sid);
+			hero->spells.erase(sid);
 }
 
 DLL_EXPORT void SetMana::applyGs( CGameState *gs )
@@ -586,8 +586,7 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
 DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
 {
 	assert(!vstd::contains(gs->map->artInstances, art));
-	art->id = gs->map->artInstances.size();
-	gs->map->artInstances.push_back(art);
+	gs->map->addNewArtifactInstance(art);
 
 	assert(!art->parents.size());
 	art->setType(art->artType);
@@ -718,10 +717,38 @@ DLL_EXPORT void MoveArtifact::applyGs( CGameState *gs )
 	CArtifactInstance *a = src.getArt();
 	if(dst.slot < Arts::BACKPACK_START)
 		assert(!dst.getArt());
-	
+
 	a->move(src, dst);
 }
 
+DLL_EXPORT void AssembledArtifact::applyGs( CGameState *gs )
+{
+	CGHeroInstance *h = al.hero;
+	const CArtifactInstance *transformedArt = al.getArt();
+	assert(transformedArt);
+	assert(vstd::contains(transformedArt->assemblyPossibilities(al.hero), builtArt));
+
+	CCombinedArtifactInstance *combinedArt = new CCombinedArtifactInstance(builtArt);
+	//retreive all constituents
+	BOOST_FOREACH(si32 constituentID, *builtArt->constituents)
+	{
+		int pos = h->getArtPos(constituentID);
+		assert(pos >= 0);
+		CArtifactInstance *constituentInstance = h->getArt(pos);
+
+		//move constituent from hero to be part of new, combined artifact
+		constituentInstance->removeFrom(h, pos);
+		combinedArt->addAsConstituent(constituentInstance, pos);
+	}
+
+	//put new combined artifacts
+	combinedArt->putAt(h, al.slot);
+}
+
+DLL_EXPORT void DisassembledArtifact::applyGs( CGameState *gs )
+{
+}
+
 DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
 {
 	if(id >= 0)

+ 2 - 0
lib/RegisterTypes.cpp

@@ -155,6 +155,8 @@ void registerTypes2(Serializer &s)
 	s.template registerType<PutArtifact>();
 	s.template registerType<EraseArtifact>();
 	s.template registerType<MoveArtifact>();
+	s.template registerType<AssembledArtifact>();
+	s.template registerType<DisassembledArtifact>();
 
 	s.template registerType<SaveGame>();
 	s.template registerType<SetSelection>();

+ 12 - 3
lib/map.cpp

@@ -12,6 +12,7 @@
 #include <boost/bind.hpp>
 #include <assert.h>
 #include "CSpellHandler.h"
+#include <boost/foreach.hpp>
 
 /*
  * map.cpp, part of VCMI engine
@@ -1490,9 +1491,9 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					i+=4;
 					innerArt = CArtifactInstance::createScroll(VLC->spellh->spells[spellID]);
 				}
-				else if(art->ID == 5) //specific artifact
+				else if(defInfo->id == 5) //specific artifact
 				{
-					innerArt = createArt(art->subID);
+					innerArt = createArt(defInfo->subid);
 				}
 				else
 				{
@@ -2084,7 +2085,15 @@ CArtifactInstance * Mapa::createArt(int aid)
 	else
 		a = new CArtifactInstance();
 
-	this->addNewArtifactInstance(a);
+	addNewArtifactInstance(a);
+	if(a->artType && a->artType->constituents) //TODO make it nicer
+	{
+		CCombinedArtifactInstance *comb = dynamic_cast<CCombinedArtifactInstance*>(a);
+		BOOST_FOREACH(CCombinedArtifactInstance::ConstituentInfo &ci, comb->constituentsInfo)
+		{
+			addNewArtifactInstance(ci.art);
+		}
+	}
 	return a;
 }
 

+ 15 - 4
server/CGameHandler.cpp

@@ -2565,13 +2565,24 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
  */
 bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assemble, ui32 assembleTo)
 {
-	if (artifactSlot < 0 || artifactSlot > 18) {
-		complain("Illegal artifact slot.");
-		return false;
-	}
 
 	CGHeroInstance *hero = gs->getHero(heroID);
 	const CArtifactInstance *destArtifact = hero->getArt(artifactSlot);
+
+	if(!destArtifact)
+		COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
+
+	CArtifact *combinedArt = VLC->arth->artifacts[assembleTo];
+	if(!combinedArt->constituents)
+		COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!");
+	if(!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt))
+		COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
+
+	AssembledArtifact aa;
+	aa.al = ArtifactLocation(hero, artifactSlot);
+	aa.builtArt = combinedArt;
+
+	CCombinedArtifactInstance *assembliedArt = new CCombinedArtifactInstance();
 	/*
 	SetHeroArtifacts sha;
 	sha.hid = heroID;