2
0
Эх сурвалжийг харах

Compile fixes, more work on new artifact system.

Michał W. Urbańczyk 15 жил өмнө
parent
commit
471c23ba71

+ 1 - 1
AI/StupidAI/main.cpp

@@ -27,4 +27,4 @@ extern "C" DLL_F_EXPORT CBattleGameInterface* GetNewBattleAI()
 extern "C" DLL_F_EXPORT void ReleaseBattleAI(CBattleGameInterface* i)
 {
 	delete (CStupidAI*)i;
-}
+}

+ 0 - 1
client/CGameInfo.cpp

@@ -18,7 +18,6 @@ CClientState * CCS;
 CGameInfo::CGameInfo()
 {
 	mh = NULL;
-	state = NULL;
 }
 
 void CGameInfo::setFromLib()

+ 1 - 2
client/Client.cpp

@@ -212,8 +212,7 @@ void CClient::endGame( bool closeConnection /*= true*/ )
 	delete CGI->mh;
 	const_cast<CGameInfo*>(CGI)->mh = NULL;
 
-	delete CGI->state;
-	const_cast<CGameInfo*>(CGI)->state = NULL;
+	const_cast<CGameInfo*>(CGI)->state.dellNull();
 	tlog0 << "Deleted mapHandler and gameState." << std::endl;
 
 	LOCPLINT = NULL;

+ 10 - 2
client/Client.h

@@ -112,6 +112,7 @@ public:
 	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb){};
 	void showThievesGuildWindow(int requestingObjId){};
 	void giveResource(int player, int which, int val){};
+
 	void giveCreatures (const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) {};
 	void takeCreatures (int objid, TSlots creatures){};
 	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures){};
@@ -123,11 +124,18 @@ public:
 	bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count){return false;}
 	void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging){}
 	bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1){return false;}
+
+	void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos) OVERRIDE {};
+	void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE {};
+	void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE {}; 
+	void removeArtifact(const ArtifactLocation &al) OVERRIDE {};
+	void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE {};
+
 	void showCompInfo(ShowInInfobox * comp){};
 	void heroVisitCastle(int obj, int heroID){};
 	void stopHeroVisitCastle(int obj, int heroID){};
-	void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
-	void giveNewArtifact(int hid, int position){};
+	//void giveHeroArtifact(int artid, int hid, int position){}; 
+	//void giveNewArtifact(int hid, int position){};
 	bool removeArtifact(const CArtifact* art, int hid){return false;};
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
 	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used

+ 1 - 0
client/GUIClasses.cpp

@@ -49,6 +49,7 @@
 #include "../lib/HeroBonus.h"
 #include "../lib/CCreatureHandler.h"
 #include "CMusicHandler.h"
+#include "../lib/BattleState.h"
 
 /*
  * GUIClasses.cpp, part of VCMI engine

+ 0 - 11
client/GUIClasses.h

@@ -899,17 +899,6 @@ public:
 	void show(SDL_Surface * to);
 };
 
-namespace Arts
-{
-	enum EPos
-	{
-		PRE_FIRST = -1, 
-		HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, RIGHT_RING, LEFT_RING, FEET, MISC1, MISC2, MISC3, MISC4,
-		MACH1, MACH2, MACH3, MACH4, SPELLBOOK, MISC5, 
-		AFTER_LAST
-	};
-}
-
 class CArtPlace: public LRClickableAreaWTextComp
 {
 public:

+ 13 - 0
client/NetPacksClient.cpp

@@ -167,6 +167,19 @@ void RebalanceStacks::applyCl( CClient *cl )
 		INTERFACE_CALL_IF_PRESENT(dst.army->tempOwner,stacksRebalanced, src, dst, count);
 }
 
+void PutArtifact::applyCl( CClient *cl )
+{
+
+}
+
+void EraseArtifact::applyCl( CClient *cl )
+{
+}
+
+void MoveArtifact::applyCl( CClient *cl )
+{
+}
+
 void GiveBonus::applyCl( CClient *cl )
 {
 	switch(who)

+ 23 - 0
global.h

@@ -1,3 +1,4 @@
+#pragma once
 #ifndef __GLOBAL_H__
 #define __GLOBAL_H__
 #include <iostream>
@@ -123,6 +124,8 @@ const int BFIELD_WIDTH = 17;
 const int BFIELD_HEIGHT = 11;
 const int BFIELD_SIZE = BFIELD_WIDTH * BFIELD_HEIGHT;
 
+const int SPELLBOOK_GOLD_COST = 500;
+
 enum EMarketMode
 {
 	RESOURCE_RESOURCE, RESOURCE_PLAYER, CREATURE_RESOURCE, RESOURCE_ARTIFACT, 
@@ -130,6 +133,26 @@ enum EMarketMode
 	MARTKET_AFTER_LAST_PLACEHOLDER
 };
 
+namespace Res
+{
+	enum ERes 
+	{
+		WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL
+	};
+}
+
+namespace Arts
+{
+	enum EPos
+	{
+		PRE_FIRST = -1, 
+		HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, RIGHT_RING, LEFT_RING, FEET, MISC1, MISC2, MISC3, MISC4,
+		MACH1, MACH2, MACH3, MACH4, SPELLBOOK, MISC5, 
+		AFTER_LAST
+	};
+	const ui16 BACKPACK_START = 19;
+}
+
 enum EAlignment
 {
 	GOOD, EVIL, NEUTRAL

+ 69 - 3
lib/CArtHandler.cpp

@@ -13,6 +13,9 @@
 #include <boost/algorithm/string/replace.hpp>
 #include "../lib/VCMI_Lib.h"
 #include "CSpellHandler.h"
+#include "CObjectHandler.h"
+#include "NetPacks.h"
+
 extern CLodHandler *bitmaph;
 using namespace boost::assign;
 
@@ -874,13 +877,13 @@ CArtifactInstance::CArtifactInstance( CArtifact *Art)
 
 void CArtifactInstance::setType( CArtifact *Art )
 {
-	art = Art;
+	artType = Art;
 	attachTo(Art);
 }
 
 std::string CArtifactInstance::nodeName() const
 {
-	return "Artifact instance of " + (art ? art->Name() : std::string("uninitialized")) + " type";
+	return "Artifact instance of " + (artType ? artType->Name() : std::string("uninitialized")) + " type";
 }
 
 CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s)
@@ -893,5 +896,68 @@ CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s)
 
 void CArtifactInstance::init()
 {
-	art = NULL;
+	id = -1;
+}
+
+int CArtifactInstance::firstAvailableSlot(const CGHeroInstance *h) const
+{
+	BOOST_FOREACH(ui16 slot, artType->possibleSlots)
+	{
+		if(artType->fitsAt(h->artifWorn, slot))
+		{
+			//we've found a free suitable slot.
+			return slot;
+		}
+	}
+
+	//if haven't find proper slot, use backpack
+	return firstBackpackSlot(h);
+}
+
+int CArtifactInstance::firstBackpackSlot(const CGHeroInstance *h) const
+{
+	if(!artType->isBig()) //discard big artifact
+		return Arts::BACKPACK_START + h->artifactsInBackpack.size();
+
+	return -1;
+}
+
+bool CArtifactInstance::canBePutAt(const ArtifactLocation &al) const
+{
+	if(!vstd::contains(artType->possibleSlots, al.slot))
+		return false;
+
+	//simple artifact -> test if slot is free [combined artifacts have this function overridden]
+	return al.hero->isPositionFree(al.slot);
+}
+
+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->attachTo(this);
+}
+
+void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
+{
+	assert(h->CArtifactSet::getArt(slot) == this);
+	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?
 }

+ 11 - 2
lib/CArtHandler.h

@@ -18,6 +18,8 @@
  */
 class CDefHandler;
 class CArtifact;
+class CGHeroInstance;
+struct ArtifactLocation;
 
 class DLL_EXPORT CArtifact : public CBonusSystemNode //container for artifacts
 {
@@ -62,7 +64,7 @@ class DLL_EXPORT CArtifactInstance : public CBonusSystemNode
 {
 	void init();
 public:
-	ConstTransitivePtr<CArtifact> art; 
+	ConstTransitivePtr<CArtifact> artType; 
 	si32 id; //id of the instance
 
 	CArtifactInstance();
@@ -71,10 +73,17 @@ public:
 	std::string nodeName() const OVERRIDE;
 	void setType(CArtifact *Art);
 
+	int firstAvailableSlot(const CGHeroInstance *h) const;
+	int firstBackpackSlot(const CGHeroInstance *h) const;
+	bool canBePutAt(const ArtifactLocation &al) const;
+
+	void putAt(CGHeroInstance *h, ui16 slot);
+	void removeFrom(CGHeroInstance *h, ui16 slot);
+
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CBonusSystemNode&>(*this);
-		h & art & id;
+		h & artType & id;
 	}
 
 	static CArtifactInstance *createScroll(const CSpell *s);

+ 0 - 4
lib/CGameState.cpp

@@ -759,13 +759,9 @@ int CGameState::getDate(int mode) const
 CGameState::CGameState()
 {
 	mx = new boost::shared_mutex();
-	map = NULL;
-	curB = NULL;
-	scenarioOps = NULL;
 	applierGs = new CApplier<CBaseForGSApply>;
 	registerTypes2(*applierGs);
 	objCaller = new CObjectCallersHandler;
-	campaign = NULL;
 }
 CGameState::~CGameState()
 {

+ 73 - 26
lib/CObjectHandler.cpp

@@ -3593,9 +3593,16 @@ void CGArtifact::initObj()
 {
 	blockVisit = true;
 	if(ID == 5)
+	{
 		hoverName = VLC->arth->artifacts[subID]->Name();
+		if(!storedArtifact->artType)
+			storedArtifact->setType(VLC->arth->artifacts[subID]);
+	}
 	if(ID == 93)
 		subID = 1;
+
+	assert(storedArtifact->artType);
+	assert(storedArtifact->parents.size());
 }
 
 void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
@@ -3618,7 +3625,7 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
 			break;
 			case 93:
 				{
-					int spellID = art->getBonus(Selector::type(Bonus::SPELL))->subtype;
+					int spellID = storedArtifact->getBonus(Selector::type(Bonus::SPELL))->subtype;
 					iw.components.push_back (Component(Component::SPELL, spellID,0,0));
 					iw.text.addTxt (MetaString::ADVOB_TXT,135);
 					iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
@@ -3647,23 +3654,7 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
 
 void CGArtifact::pick(const CGHeroInstance * h) const
 {
-	if (VLC->arth->artifacts[subID]->isModable())
-	{//TODO: create new instance, initialize it
-		if (ID == 93) //scroll
-		{
-			NewArtifact na;
-			//na.value = spell;
-			na.artid = subID;
-			cb->sendAndApply(&na);
-			cb->giveNewArtifact(h->id, -2);
-		}
-		else
-			cb->giveNewArtifact(h->id, -2);; //nothing / zero / empty by default
-	}
-	else
-	{
-		cb->giveHeroArtifact(subID,h->id,-2);
-	}
+	cb->giveHeroArtifact(h, storedArtifact, -2);
 	cb->removeObject(id);
 }
 
@@ -3822,7 +3813,7 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
 				//TODO: what if no space in backpack?
 				iw.components.push_back(Component(4, val2, 1, 0));
 				iw.text.addReplacement(MetaString::ART_NAMES, val2);
-				cb->giveHeroArtifact(val2,h->id,-2);
+				cb->giveHeroNewArtifact(h, VLC->arth->artifacts[val2],-2);
 			}
 			cb->showInfoDialog(&iw);
 			break;
@@ -3836,7 +3827,7 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
 			iw.components.push_back(Component(4,val1,1,0));
 			iw.text.addTxt(MetaString::ADVOB_TXT, 125);
 			iw.text.addReplacement(MetaString::ART_NAMES, val1);
-			cb->giveHeroArtifact(val1,h->id,-2);
+			cb->giveHeroNewArtifact(h, VLC->arth->artifacts[val1],-2);
 			cb->showInfoDialog(&iw);
 			break;
 		}
@@ -3850,7 +3841,7 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
 
 			if(type) //there is an artifact
 			{
-				cb->giveHeroArtifact(val1,h->id,-2);
+				cb->giveHeroNewArtifact(h, VLC->arth->artifacts[val1],-2);
 				InfoWindow iw;
 				iw.soundID = soundBase::treasure;
 				iw.player = h->tempOwner;
@@ -4452,7 +4443,7 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
 			cb->changeSecSkill(h->id, rID, rVal, false);
 			break;
 		case 8: // artifact
-			cb->giveHeroArtifact(rID, h->id, -2);
+			cb->giveHeroNewArtifact(h, VLC->arth->artifacts[rID],-2);
 			break;
 		case 9:// spell
 		{
@@ -5009,7 +5000,7 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 			cb->giveResource(h->getOwner(),i,resources[i]);
 
 	for(int i=0; i<artifacts.size(); i++)
-		cb->giveHeroArtifact(artifacts[i],h->id,-2);
+		cb->giveHeroNewArtifact(h, VLC->arth->artifacts[artifacts[i]],-2);
 
 	iw.components.clear();
 	iw.text.clear();
@@ -5410,7 +5401,7 @@ void CGOnceVisitable::onHeroVisit( const CGHeroInstance * h ) const
 			break;
 		case 1: //art
 			iw.components.push_back(Component(Component::ARTIFACT,bonusType,0,0));
-			cb->giveHeroArtifact(bonusType,h->id,-2);
+			cb->giveHeroNewArtifact(h, VLC->arth->artifacts[bonusType],-2);
 			iw.text.addTxt(MetaString::ADVOB_TXT, txtid);
 			if (ID == 22) //Corpse
 			{
@@ -5532,7 +5523,7 @@ void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
 			iw.components.push_back(Component(Component::ARTIFACT,bonusType,0,0));
 			iw.text.addReplacement(MetaString::ART_NAMES, bonusType);
 
-			cb->giveHeroArtifact(bonusType,h->id,-2);
+			cb->giveHeroNewArtifact(h, VLC->arth->artifacts[bonusType],-2);
 		}		
 		
 		if(!h->hasBonusFrom(Bonus::OBJECT,ID)) //we don't have modifier from this object yet
@@ -5871,7 +5862,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 			iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 			loot << "%s";
 			loot.addReplacement(MetaString::ART_NAMES, *it);
-			cb->giveHeroArtifact (*it, h->id ,-2);
+			cb->giveHeroNewArtifact (h, VLC->arth->artifacts[*it], -2);
 		}
 		//display loot
 		if (!iw.components.empty())
@@ -6935,3 +6926,59 @@ void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
 	ow.window = OpenWindow::UNIVERSITY_WINDOW;
 	cb->sendAndApply(&ow);
 }
+
+const CArtifactInstance* CArtifactSet::getArt(ui16 pos) const
+{
+	if(const ArtSlotInfo *si = getSlot(pos))
+	{
+		if(si->artifact && !si->locked)
+			return si->artifact;
+	}
+
+	return NULL;
+}
+
+si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const
+{
+	for(std::map<ui16, ArtSlotInfo>::const_iterator i = artifactsWorn.begin(); i != artifactsWorn.end(); i++)
+		if(i->second.artifact->artType->id == aid)
+			return i->first;
+
+	if(onlyWorn)
+		return -1;
+
+	for(int i = 0; i < artifactsInBackpack.size(); i++)
+		if(artifactsInBackpack[i].artifact->artType->id == aid)
+			return Arts::BACKPACK_START + i;
+
+	return -1;
+}
+
+bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= true*/) const
+{
+	return getArtPos(aid, onlyWorn) != -1;
+}
+
+const ArtSlotInfo * CArtifactSet::getSlot(ui16 pos) const
+{
+	if(vstd::contains(artifactsWorn, pos))
+		return &artifactsWorn[pos];
+	if(pos >= Arts::AFTER_LAST )
+	{
+		int backpackPos = (int)pos - Arts::BACKPACK_START;
+		if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
+			return NULL;
+		else
+			return &artifactsInBackpack[backpackPos];
+	}
+
+	return NULL;
+}
+
+bool CArtifactSet::isPositionFree(ui16 pos) const
+{
+	if(const ArtSlotInfo *s = getSlot(pos))
+		return !s->artifact && !s->locked;
+
+	return true; //no slot means not used
+}

+ 40 - 6
lib/CObjectHandler.h

@@ -243,7 +243,40 @@ public:
 	}
 };
 
-class DLL_EXPORT CGHeroInstance : public CArmedInstance, public IBoatGenerator
+struct DLL_EXPORT ArtSlotInfo
+{
+	ConstTransitivePtr<CArtifactInstance> artifact;
+	ui8 locked; //if locked, then artifact points to the combined artifact
+
+	ArtSlotInfo()
+	{
+		locked = false;
+	}
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & artifact & locked;
+	}
+};
+
+class DLL_EXPORT CArtifactSet
+{
+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
+
+	const ArtSlotInfo *getSlot(ui16 pos) const;
+	const CArtifactInstance* getArt(ui16 pos) const; //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)
+	bool hasArt(ui32 aid, bool onlyWorn = true) const; //checks if hero possess artifact of given id (either in backack or worn)
+	bool isPositionFree(ui16 pos) const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & artifactsInBackpack & artifactsWorn;
+	}
+};
+
+class DLL_EXPORT CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet
 {
 public:
 	enum SecondarySkill
@@ -276,13 +309,12 @@ public:
 	const CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison
 	const CGBoat *boat; //set to CGBoat when sailing
 	
-	std::vector<const CArtifactInstance*> gartifacts; //hero's artifacts from bag
-	std::map<ui16, const CArtifactInstance*> gartifWorn; //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<const CArtifact*> artifacts; //hero's artifacts from bag
 	std::map<ui16, const CArtifact*> artifWorn; //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::set<ui32> spells; //known spells (spell IDs)
 
+
 	struct DLL_EXPORT Patrol
 	{
 		Patrol(){patrolling=false;patrolRadious=-1;};
@@ -293,6 +325,7 @@ public:
 			h & patrolling & patrolRadious;
 		}
 	} patrol;
+
 	struct DLL_EXPORT HeroSpecial : CBonusSystemNode
 	{
 		bool growthsWithLevel;
@@ -310,6 +343,7 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CArmedInstance&>(*this);
+		h & static_cast<CArtifactSet&>(*this);
 		h & exp & level & name & biography & portrait & mana & secSkills & movement
 			& sex & inTownGarrison & artifacts & artifWorn & spells & patrol & moveDir;
 
@@ -777,9 +811,9 @@ public:
 class DLL_EXPORT CGArtifact : public CArmedInstance
 {
 public:
-	CArtifactInstance *art;
-
+	CArtifactInstance *storedArtifact;
 	std::string message;
+
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void fightForArt(ui32 agreed, const CGHeroInstance *h) const;
 	void endBattle(BattleResult *result, const CGHeroInstance *h) const;
@@ -789,7 +823,7 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CArmedInstance&>(*this);
-		h & message & art;
+		h & message & storedArtifact;
 	}
 };
 

+ 11 - 5
lib/Connection.h

@@ -420,11 +420,14 @@ public:
 			typedef typename VectorisedTypeFor<TObjectType>::type VType;
  			if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
  			{
- 				*this << getIdFromVectorItem<VType>(*info, data);
- 				return;
+				si32 id = getIdFromVectorItem<VType>(*info, data);
+				*this << id;
+				if(id != -1) //vector id is enough
+ 					return;
  			}
  		}
 
+
 		if(smartPointerSerialization)
 		{
 			std::map<const void*,ui32>::iterator i = savedPointers.find(data);
@@ -686,10 +689,13 @@ public:
 			typedef typename VectorisedTypeFor<TObjectType>::type VType;									 //eg: CGHeroInstance -> CGobjectInstance
 			if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
 			{
-				ui32 id;
+				si32 id;
 				*this >> id;
-				data = static_cast<T>(getVectorItemFromId(*info, id));
-				return;
+				if(id != -1)
+				{
+					data = static_cast<T>(getVectorItemFromId(*info, id));
+					return;
+				}
 			}
 		}
 

+ 13 - 0
lib/ConstTransitivePtr.h

@@ -1,9 +1,14 @@
 #pragma once
 
+class CGameHandler;
+
 template <typename T>
 class ConstTransitivePtr
 {
 	T *ptr;
+	ConstTransitivePtr(const T *Ptr)
+		: ptr(const_cast<T*>(Ptr)) 
+	{}
 public:
 	ConstTransitivePtr(T *Ptr = NULL)
 		: ptr(Ptr) 
@@ -42,8 +47,16 @@ public:
 		return ptr;
 	}
 
+	void dellNull()
+	{
+		delete ptr;
+		ptr = NULL;
+	}
+
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & ptr;
 	}
+
+	friend CGameHandler;
 };

+ 12 - 3
lib/IGameCallback.h

@@ -38,6 +38,8 @@ struct TerrainTile;
 struct PlayerState;
 class CTown;
 struct StackLocation;
+struct ArtifactLocation;
+class CArtifactInstance;
 
 class DLL_EXPORT IGameCallback
 {
@@ -87,8 +89,8 @@ public:
 	virtual void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
 	virtual void showThievesGuildWindow(int requestingObjId) =0;
 	virtual void giveResource(int player, int which, int val)=0;
+
 	virtual void giveCreatures (const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
-	//virtual void takeCreatures (int objid, TSlots creatures) =0;
 	virtual void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) =0;
 	virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
 	virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
@@ -98,11 +100,18 @@ public:
 	virtual bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) =0; //makes new stack or increases count of already existing
 	virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) =0; //merges army from src do dst or opens a garrison window
 	virtual bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count) = 0;
+
+	virtual void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos) = 0;
+	virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
+	virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
+	virtual void removeArtifact(const ArtifactLocation &al) = 0;
+	virtual void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
+
 	virtual void showCompInfo(ShowInInfobox * comp)=0;
 	virtual void heroVisitCastle(int obj, int heroID)=0;
 	virtual void stopHeroVisitCastle(int obj, int heroID)=0;
-	virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
-	virtual void giveNewArtifact(int hid, int position)=0;
+	//virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
+	//virtual void giveNewArtifact(int hid, int position)=0;
 	virtual bool removeArtifact(const CArtifact* art, int hid) = 0;
 	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
 	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used

+ 9 - 9
lib/NetPacks.h

@@ -27,7 +27,9 @@ class CCampaignState;
 class CArtifact;
 class CSelectionScreen;
 class CGObjectInstance;
+class CArtifactInstance;
 //class CMapInfo;
+struct ArtSlotInfo;
 
 struct CPack
 {
@@ -708,12 +710,11 @@ struct NewArtifact : public CPackForClient //520
 	//void applyCl(CClient *cl);
 	DLL_EXPORT void applyGs(CGameState *gs);
 
-	si32 artid;
-	si32 value; //initializing parameter
+	ConstTransitivePtr<CArtifactInstance> art;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & artid & value;
+		h & art;
 	}
 };
 
@@ -724,7 +725,6 @@ struct StackLocation
 
 	StackLocation()
 	{
-		army = NULL;
 		slot = -1;
 	}
 	StackLocation(const CArmedInstance *Army, TSlot Slot)
@@ -827,7 +827,6 @@ struct RebalanceStacks : CGarrisonOperationPack  //526
 	}
 };
 
-typedef CArtifact TTempArtInstance;
 typedef si32 TArtPos;
 
 struct ArtifactLocation
@@ -837,7 +836,6 @@ struct ArtifactLocation
 
 	ArtifactLocation()
 	{
-		hero = NULL;
 		slot = -1;
 	}
 	ArtifactLocation(const CGHeroInstance *Hero, TArtPos Slot)
@@ -845,7 +843,9 @@ struct ArtifactLocation
 		hero = const_cast<CGHeroInstance*>(Hero); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
 		slot = Slot;
 	}
-	DLL_EXPORT const TTempArtInstance *getArt();
+	DLL_EXPORT const CArtifactInstance *getArt() const;
+	DLL_EXPORT CArtifactInstance *getArt();
+	DLL_EXPORT const ArtSlotInfo *getSlot() const;
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & hero & slot;
@@ -855,14 +855,14 @@ struct ArtifactLocation
 struct PutArtifact : CGarrisonOperationPack  //526
 {
 	ArtifactLocation al;
-	TTempArtInstance *art;
+	ConstTransitivePtr<CArtifactInstance> art;
 
 	void applyCl(CClient *cl);
 	DLL_EXPORT void applyGs(CGameState *gs);
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & src & dst & count;
+		h & al & art;
 	}
 };
 

+ 45 - 26
lib/NetPacksLib.cpp

@@ -178,7 +178,7 @@ DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
 
 	for (int i = 0; i < AVAILABLE_HEROES_PER_PLAYER; i++)
 	{
-		CGHeroInstance *h = (hid[i]>=0 ?  gs->hpool.heroesPool[hid[i]] : NULL);
+		CGHeroInstance *h = (hid[i]>=0 ?  (CGHeroInstance*)gs->hpool.heroesPool[hid[i]] : NULL);
 		if(h && army[i])
 			h->setToArmy(*army[i]);
 		p->availableHeroes.push_back(h);
@@ -294,7 +294,7 @@ DLL_EXPORT void RemoveObject::applyGs( CGameState *gs )
 		CGCreature *cre = static_cast<CGCreature*>(obj);
 		gs->map->monsters[cre->identifier]->pos = int3 (-1,-1,-1);	//use nonexistent monster for quest :>
 	}
-	gs->map->objects[id] = NULL;
+	gs->map->objects[id].dellNull();
 }
 
 static int getDir(int3 src, int3 dst)
@@ -583,28 +583,12 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
 }
 DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
 {
-// 	IModableArt * art;
-// 
-// 	std::map<ui32,ui8>::iterator itr = VLC->arth->modableArtifacts.find(artid);
-// 	switch (itr->second)
-// 	{
-// 			case 1:
-// 				art = new CScroll;
-// 				break;
-// 			case 2:
-// 				art = new CCustomizableArt;
-// 				break;
-// 			case 3:
-// 				art = new CCommanderArt;
-// 				break;
-// 			default:
-// 				tlog1<<"unhandled customizable artifact!\n";
-// 	};
-// 	*art = *static_cast<IModableArt*>(+VLC->arth->artifacts[artid]); //copy properties
-// 	art->ID = gs->map->artInstances.size();
-// 	art->SetProperty (value); //init scroll, banner, commander art
-// 	art->Init(); //set bonuses for new instance
-// 	gs->map->artInstances.push_back(art);
+	assert(!vstd::contains(gs->map->artInstances, art));
+	art->id = gs->map->artInstances.size();
+	gs->map->artInstances.push_back(art);
+
+	assert(!art->parents.size());
+	art->attachTo(art->artType);
 }
 
 DLL_EXPORT const CStackInstance * StackLocation::getStack()
@@ -617,6 +601,24 @@ DLL_EXPORT const CStackInstance * StackLocation::getStack()
 	return &army->getStack(slot);
 }
 
+DLL_EXPORT const CArtifactInstance *ArtifactLocation::getArt() const
+{
+	const ArtSlotInfo *s = getSlot();
+	if(s && !s->locked && s->artifact)
+		return s->artifact;
+}
+
+DLL_EXPORT CArtifactInstance *ArtifactLocation::getArt()
+{
+	const ArtifactLocation *t = this;
+	return const_cast<CArtifactInstance*>(t->getArt());
+}
+
+DLL_EXPORT const ArtSlotInfo *ArtifactLocation::getSlot() const
+{
+	return hero->getSlot(slot);
+}
+
 DLL_EXPORT void ChangeStackCount::applyGs( CGameState *gs )
 {
 	if(absoluteValue)
@@ -685,6 +687,24 @@ DLL_EXPORT void RebalanceStacks::applyGs( CGameState *gs )
 	}
 }
 
+DLL_EXPORT void PutArtifact::applyGs( CGameState *gs )
+{
+	assert(art->canBePutAt(al));
+	art->putAt(al.hero, al.slot);
+}
+
+DLL_EXPORT void EraseArtifact::applyGs( CGameState *gs )
+{
+	CArtifactInstance *a = al.getArt();
+	assert(a);
+	a->removeFrom(al.hero, al.slot);
+}
+
+DLL_EXPORT void MoveArtifact::applyGs( CGameState *gs )
+{
+
+}
+
 DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
 {
 	if(id >= 0)
@@ -904,8 +924,7 @@ void BattleResult::applyGs( CGameState *gs )
 		h->bonuses.remove_if(Bonus::OneBattle);
 
 	gs->curB->belligerents[0]->battle = gs->curB->belligerents[1]->battle = NULL;
-	delete gs->curB;
-	gs->curB = NULL;
+	gs->curB.dellNull();
 }
 
 void BattleStackMoved::applyGs( CGameState *gs )

+ 3 - 0
lib/RegisterTypes.cpp

@@ -149,6 +149,9 @@ void registerTypes2(Serializer &s)
 	s.template registerType<InsertNewStack>();
 	s.template registerType<RebalanceStacks>();
 	s.template registerType<SetAvailableArtifacts>();
+	s.template registerType<PutArtifact>();
+	s.template registerType<EraseArtifact>();
+	s.template registerType<MoveArtifact>();
 
 	s.template registerType<SaveGame>();
 	s.template registerType<SetSelection>();

+ 1 - 1
lib/map.cpp

@@ -1584,7 +1584,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				{
 					innerArt = new CArtifactInstance();
 				}
-				art->art = innerArt;
+				art->storedArtifact = innerArt;
 				addNewArtifactInstance(innerArt);
 				break;
 			}

+ 77 - 103
server/CGameHandler.cpp

@@ -1609,98 +1609,7 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID)
 	vc.tid = obj;
 	sendAndApply(&vc);
 }
-void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack
-{
-	const CGHeroInstance* h = getHero(hid);
-	CArtifact * const art = VLC->arth->artifacts[artid];
-
-	SetHeroArtifacts sha;
-	sha.hid = hid;
-	sha.artifacts = h->artifacts;
-	sha.artifWorn = h->artifWorn;
-
-	if(position<0)
-	{
-		if(position == -2)
-		{
-			int i;
-			for(i=0; i<art->possibleSlots.size(); i++) //try to put artifact into first available slot
-			{
-				if(art->fitsAt(sha.artifWorn, art->possibleSlots[i]))
-				{
-					//we've found a free suitable slot.
-					VLC->arth->equipArtifact(sha.artifWorn, art->possibleSlots[i], VLC->arth->artifacts[artid]);
-					break;
-				}
-			}
-			if(i == art->possibleSlots.size() && !art->isBig()) //if haven't find proper slot, use backpack or discard big artifact
-				sha.artifacts.push_back(art);
-		}
-		else if (!art->isBig()) //should be -1 => put artifact into backpack
-		{
-			sha.artifacts.push_back(art);
-		}
-	}
-	else
-	{
-		if(art->fitsAt(sha.artifWorn, ui16(position)))
-		{
-			VLC->arth->equipArtifact(sha.artifWorn, position, art);
-		}
-		else if (!art->isBig())
-		{
-			sha.artifacts.push_back(art);
-		}
-	}
 
-	sendAndApply(&sha);
-}
-void CGameHandler::giveNewArtifact(int hid, int position)
-{
-// 	const CGHeroInstance* h = getHero(hid);
-// 	CArtifact * art = gs->map->artInstances.back(); //we use it only to immediatelly equip new artifact
-// 
-// 	SetHeroArtifacts sha;
-// 	sha.hid = hid;
-// 	sha.artifacts = h->artifacts;
-// 	sha.artifWorn = h->artifWorn;
-// 
-// 	if(position<0)
-// 	{
-// 		if(position == -2)
-// 		{
-// 			int i;
-// 			for(i=0; i<art->possibleSlots.size(); i++) //try to put artifact into first available slot
-// 			{
-// 				if( !vstd::contains(sha.artifWorn, art->possibleSlots[i]) )
-// 				{
-// 					//we've found a free suitable slot
-// 					VLC->arth->equipArtifact(sha.artifWorn, art->possibleSlots[i], art);
-// 					break;
-// 				}
-// 			}
-// 			if(i == art->possibleSlots.size() && !art->isBig()) //if haven't find proper slot, use backpack or discard big artifact
-// 				sha.artifacts.push_back(art);
-// 		}
-// 		else if (!art->isBig()) //should be -1 => put artifact into backpack
-// 		{
-// 			sha.artifacts.push_back(art);
-// 		}
-// 	}
-// 	else
-// 	{
-// 		if(!vstd::contains(sha.artifWorn,ui16(position)))
-// 		{
-// 			VLC->arth->equipArtifact(sha.artifWorn, position, art);
-// 		}
-// 		else if (!art->isBig())
-// 		{
-// 			sha.artifacts.push_back(art);
-// 		}
-// 	}
-// 
-// 	sendAndApply(&sha);
-}
 bool CGameHandler::removeArtifact(const CArtifact* art, int hid)
 {
 	const CGHeroInstance* h = getHero(hid);
@@ -1735,6 +1644,10 @@ bool CGameHandler::removeArtifact(const CArtifact* art, int hid)
 	return true;
 }
 
+void CGameHandler::removeArtifact(const ArtifactLocation &al)
+{
+
+}
 void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town) //use hero=NULL for no hero
 {
 	engageIntoBattle(army1->tempOwner);
@@ -1976,6 +1889,7 @@ void CGameHandler::sendToAllClients( CPackForClient * info )
 
 void CGameHandler::sendAndApply( CPackForClient * info )
 {
+	//TODO? mutex
 	sendToAllClients(info);
 	gs->apply(info);
 }
@@ -2370,16 +2284,20 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
 	
 	if(warMachine)
 	{
+		const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(dst);
+		if(!h)
+			COMPLAIN_RET("Only hero can buy war machines");
+
 		switch(crid)
 		{
 		case 146:
-			giveHeroArtifact(4, dst->id, 13);
+			giveHeroNewArtifact(h, VLC->arth->artifacts[4], Arts::MACH1);
 			break;
 		case 147:
-			giveHeroArtifact(6, dst->id, 15);
+			giveHeroNewArtifact(h, VLC->arth->artifacts[6], Arts::MACH3);
 			break;
 		case 148:
-			giveHeroArtifact(5, dst->id, 14);
+			giveHeroNewArtifact(h, VLC->arth->artifacts[5], Arts::MACH2);
 			break;
 		default:
 			complain("This war machine cannot be recruited!");
@@ -2770,13 +2688,14 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
 	if(aid==0) //spellbook
 	{
 		if(!vstd::contains(town->builtBuildings,si32(0)) && complain("Cannot buy a spellbook, no mage guild in the town!")
-			|| getResource(hero->getOwner(),6)<500 && complain("Cannot buy a spellbook, not enough gold!") 
-			|| hero->getArt(17) && complain("Cannot buy a spellbook, hero already has a one!")
+			|| getResource(hero->getOwner(), Res::GOLD) < SPELLBOOK_GOLD_COST && complain("Cannot buy a spellbook, not enough gold!") 
+			|| hero->getArt(Arts::SPELLBOOK) && complain("Cannot buy a spellbook, hero already has a one!")
 			)
 			return false;
 
-		giveResource(hero->getOwner(),6,-500);
-		giveHeroArtifact(0,hid,17);
+		giveResource(hero->getOwner(),Res::GOLD,-SPELLBOOK_GOLD_COST);
+		giveHeroNewArtifact(hero, VLC->arth->artifacts[0], Arts::SPELLBOOK);
+		assert(hero->getArt(Arts::SPELLBOOK));
 		giveSpells(town,hero);
 		return true;
 	}
@@ -2785,7 +2704,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
 		int price = VLC->arth->artifacts[aid]->price;
 		if(vstd::contains(hero->artifWorn,ui16(9+aid)) && complain("Hero already has this machine!")
 			|| !vstd::contains(town->builtBuildings,si32(16)) && complain("No blackismith!")
-			|| gs->getPlayer(hero->getOwner())->resources[6] < price  && complain("Not enough gold!")  //no gold
+			|| gs->getPlayer(hero->getOwner())->resources[Res::GOLD] < price  && complain("Not enough gold!")  //no gold
 			|| (!(town->subID == 6 && vstd::contains(town->builtBuildings,si32(22) ) )
 			&& town->town->warMachine!= aid ) &&  complain("This machine is unavailable here!") ) 
 		{
@@ -2793,7 +2712,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
 		}
 
 		giveResource(hero->getOwner(),6,-price);
-		giveHeroArtifact(aid,hid,9+aid);
+		giveHeroNewArtifact(hero, VLC->arth->artifacts[aid], 9+aid);
 		return true;
 	}
 	return false;
@@ -2847,7 +2766,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, int ri
 
 	sendAndApply(&saa);
 
-	giveHeroArtifact(aid, h->id, -2);
+	giveHeroNewArtifact(h, VLC->arth->artifacts[aid], -2);
 	return true;
 }
 
@@ -4347,7 +4266,7 @@ bool CGameHandler::dig( const CGHeroInstance *h )
 		iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
 		iw.text.addTxt(MetaString::ART_NAMES, 2);
 		iw.soundID = soundBase::ULTIMATEARTIFACT;
-		giveHeroArtifact(2, h->id, -1); //give grail
+		giveHeroNewArtifact(h, VLC->arth->artifacts[2], -1); //give grail
 		sendAndApply(&iw);
 
 		iw.text.clear();
@@ -5018,6 +4937,61 @@ void CGameHandler::runBattle()
 
 	endBattle(gs->curB->tile, gs->curB->heroes[0], gs->curB->heroes[1]);
 }
+
+void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos)
+{
+	assert(a->artType);
+	ArtifactLocation al;
+	al.hero = h;
+
+	int slot = -1;
+	if(pos < 0)
+	{
+		if(pos == -2)
+			slot = a->firstAvailableSlot(h);
+		else
+			slot = a->firstBackpackSlot(h);
+	}
+	else
+	{
+		slot = pos;
+	}
+
+	al.slot = slot;
+
+	if(slot < 0 || !a->canBePutAt(al))
+	{	
+		complain("Cannot put artifact in that slot!");
+		return;
+	}
+
+	putArtifact(al, a);
+}
+void CGameHandler::putArtifact(const ArtifactLocation &al, const CArtifactInstance *a)
+{
+	PutArtifact pa;
+	pa.art = a;
+	pa.al = al;
+	sendAndApply(&pa);
+}
+
+void CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2)
+{
+
+}
+
+void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos)
+{
+	CArtifactInstance *a = NULL;
+	a->artType = artType; //NOT via settype -> all bonus-related stuff must be done by NewArtifact apply
+	
+	NewArtifact na;
+	na.art = a;
+	sendAndApply(&na);
+
+	giveHeroArtifact(h, a, pos);
+}
+
 CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
 {
 	int color = army->tempOwner;
@@ -5026,7 +5000,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
 
 	BOOST_FOREACH(CStack *st, bat->stacks)
 	{
-		if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks
+		if(vstd::contains(st->state, SUMMONED)) //don't take into account summoned stacks
 			continue;
 
 		if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))

+ 56 - 49
server/CGameHandler.h

@@ -128,60 +128,67 @@ public:
 	//////////////////////////////////////////////////////////////////////////
 	//from IGameCallback
 	//get info
-	int getCurrentPlayer();
-	int getSelectedHero();
+	int getCurrentPlayer() OVERRIDE;
+	int getSelectedHero() OVERRIDE;
 
 
 	//do sth
-	void changeSpells(int hid, bool give, const std::set<ui32> &spells);
-	bool removeObject(int objid);
-	void setBlockVis(int objid, bool bv);
-	void setOwner(int objid, ui8 owner);
-	void setHoverName(int objid, MetaString * name);
-	void setObjProperty(int objid, int prop, si64 val);
-	void levelUpHero(int ID, int skill);//handle client respond and send one more request if needed 
-	void levelUpHero(int ID);//initial call - check if hero have remaining levelups & handle them
-	void changePrimSkill(int ID, int which, si64 val, bool abs=false);
-	void changeSecSkill(int ID, int which, int val, bool abs=false); 
-	void showInfoDialog(InfoWindow *iw);
-	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback);
-	ui32 showBlockingDialog(BlockingDialog *iw); //synchronous version of above
-	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb);
-	void showThievesGuildWindow(int requestingObjId); //TODO: make something more general?
-	void giveResource(int player, int which, int val);
-	void giveCreatures (const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove);
-	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures);
-	bool changeStackType(const StackLocation &sl, CCreature *c);
-	bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false);
-	bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count);
-	bool eraseStack(const StackLocation &sl, bool forceRemoval = false);
-	bool swapStacks(const StackLocation &sl1, const StackLocation &sl2);
-	bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count);
-	void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging);
-	bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1);
-	void showCompInfo(ShowInInfobox * comp);
-	void heroVisitCastle(int obj, int heroID);
-	void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
-	void stopHeroVisitCastle(int obj, int heroID);
-	void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
-	void giveNewArtifact(int hid, int position);
-	bool removeArtifact(const CArtifact* art, int hid);
-	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL); //use hero=NULL for no hero
-	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used
-	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
-	void setAmount(int objid, ui32 val);
-	bool teleportHero(si32 hid, si32 dstid, ui8 source, ui8 asker = 255);
-	bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);
-	bool tryAttackingGuard(const int3 &guardPos, const CGHeroInstance * h);
-	void visitObjectOnTile(const TerrainTile &t, const CGHeroInstance * h);
-	void giveHeroBonus(GiveBonus * bonus);
-	void setMovePoints(SetMovePoints * smp);
-	void setManaPoints(int hid, int val);
-	void giveHero(int id, int player);
-	void changeObjPos(int objid, int3 newPos, ui8 flags);
+	void changeSpells(int hid, bool give, const std::set<ui32> &spells) OVERRIDE;
+	bool removeObject(int objid) OVERRIDE;
+	void setBlockVis(int objid, bool bv) OVERRIDE;
+	void setOwner(int objid, ui8 owner) OVERRIDE;
+	void setHoverName(int objid, MetaString * name) OVERRIDE;
+	void setObjProperty(int objid, int prop, si64 val) OVERRIDE;
+	void changePrimSkill(int ID, int which, si64 val, bool abs=false) OVERRIDE;
+	void changeSecSkill(int ID, int which, int val, bool abs=false) OVERRIDE; 
+	void showInfoDialog(InfoWindow *iw) OVERRIDE;
+	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE;
+	ui32 showBlockingDialog(BlockingDialog *iw) OVERRIDE; //synchronous version of above
+	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE;
+	void showThievesGuildWindow(int requestingObjId) OVERRIDE; //TODO: make something more general?
+	void giveResource(int player, int which, int val) OVERRIDE;
+
+	void giveCreatures (const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE;
+	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) OVERRIDE;
+	bool changeStackType(const StackLocation &sl, CCreature *c) OVERRIDE;
+	bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) OVERRIDE;
+	bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE;
+	bool eraseStack(const StackLocation &sl, bool forceRemoval = false) OVERRIDE;
+	bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) OVERRIDE;
+	bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE;
+	void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) OVERRIDE;
+	bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1) OVERRIDE;
+
+	void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos) OVERRIDE;
+	void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE;
+	void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE; 
+	void removeArtifact(const ArtifactLocation &al) OVERRIDE;
+	void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE;
+
+	void showCompInfo(ShowInInfobox * comp) OVERRIDE;
+	void heroVisitCastle(int obj, int heroID) OVERRIDE;
+	void stopHeroVisitCastle(int obj, int heroID) OVERRIDE;
+	bool removeArtifact(const CArtifact* art, int hid) OVERRIDE;
+	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL) OVERRIDE; //use hero=NULL for no hero
+	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used
+	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) OVERRIDE; //for hero<=>neutral army
+	void setAmount(int objid, ui32 val) OVERRIDE;
+	bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255) OVERRIDE;
+	void giveHeroBonus(GiveBonus * bonus) OVERRIDE;
+	void setMovePoints(SetMovePoints * smp) OVERRIDE;
+	void setManaPoints(int hid, int val) OVERRIDE;
+	void giveHero(int id, int player) OVERRIDE;
+	void changeObjPos(int objid, int3 newPos, ui8 flags) OVERRIDE;
+	void heroExchange(si32 hero1, si32 hero2) OVERRIDE;
+	//////////////////////////////////////////////////////////////////////////
 	void useScholarSkill(si32 hero1, si32 hero2);
-	void heroExchange(si32 hero1, si32 hero2);
 	void setPortalDwelling(const CGTownInstance * town, bool forced, bool clear);
+	bool tryAttackingGuard(const int3 &guardPos, const CGHeroInstance * h);
+	void visitObjectOnTile(const TerrainTile &t, const CGHeroInstance * h);
+	bool teleportHero(si32 hid, si32 dstid, ui8 source, ui8 asker = 255);
+	void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
+	void levelUpHero(int ID, int skill);//handle client respond and send one more request if needed 
+	void levelUpHero(int ID);//initial call - check if hero have remaining levelups & handle them
 	//////////////////////////////////////////////////////////////////////////
 
 	void init(StartInfo *si, int Seed);

+ 1 - 0
server/stdafx.h

@@ -22,3 +22,4 @@
 #include <boost/asio.hpp>
 #include <boost/thread.hpp>
 #include <boost/foreach.hpp>
+