From 7ae02b7c5a4e00c1844d8c5bea965000d6ce0683 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= <mwu-tow@gazeta.pl>
Date: Tue, 20 Jul 2010 18:34:32 +0000
Subject: [PATCH] Fixed #471. Bonuses from artifacts are now inherited. Some
 work on artifacts set GUI. CArtifactsOfHero now operates on its own hero copy
 when picking artifact. Still more fixes are needed though.

---
 client/CHeroWindow.cpp      |   5 -
 client/CPlayerInterface.cpp |   7 +-
 client/GUIClasses.cpp       | 247 +++++++++++-------------------------
 client/GUIClasses.h         |   9 +-
 client/NetPacksClient.cpp   |  18 +--
 hch/CArtHandler.cpp         |  65 +++-------
 hch/CArtHandler.h           |  13 +-
 hch/CObjectHandler.cpp      |  30 ++---
 hch/CObjectHandler.h        |   7 +-
 lib/CGameState.cpp          |   6 +-
 lib/HeroBonus.h             |   2 +-
 lib/NetPacks.h              |   1 +
 lib/NetPacksLib.cpp         |  57 +++------
 lib/map.cpp                 |  24 ++--
 server/CGameHandler.cpp     |  23 ++--
 15 files changed, 180 insertions(+), 334 deletions(-)

diff --git a/client/CHeroWindow.cpp b/client/CHeroWindow.cpp
index c96f96f76..9f9bfec19 100644
--- a/client/CHeroWindow.cpp
+++ b/client/CHeroWindow.cpp
@@ -171,10 +171,6 @@ CHeroWindow::~CHeroWindow()
 
 	delete garr;
 	delete ourBar;
-
-	artifs->rollback();
-	delete artifs->commonInfo;
-	artifs->commonInfo = NULL; //to prevent heap corruption
 	delete artifs;
 
 	delete portraitArea;
@@ -532,7 +528,6 @@ void CHeroWindow::dispose()
 	curBack = NULL;
 	curHero = NULL;
 
-	artifs->rollback();
 	artifs->dispose();
 }
 
diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp
index 2ea9c8f4e..887177b8f 100644
--- a/client/CPlayerInterface.cpp
+++ b/client/CPlayerInterface.cpp
@@ -945,10 +945,10 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	if(adventureInt->heroWindow->curHero) //hero window is opened
+	if(adventureInt->heroWindow->curHero && adventureInt->heroWindow->curHero->id == hero->id) //hero window is opened
 	{
 		adventureInt->heroWindow->deactivate();
-		adventureInt->heroWindow->setHero(adventureInt->heroWindow->curHero);
+		adventureInt->heroWindow->setHero(hero);
 		adventureInt->heroWindow->activate();
 		return;
 	}
@@ -957,8 +957,9 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
 		cew->deactivate();
 		for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
 		{
-			if(cew->heroInst[g] == hero)
+			if(cew->heroInst[g]->id == hero->id)
 			{
+				cew->heroInst[g] = hero;
 				cew->artifs[g]->updateState = true;
 				cew->artifs[g]->setHero(hero);
 				cew->artifs[g]->updateState = false;
diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp
index 05e02f962..e3d07bf50 100644
--- a/client/GUIClasses.cpp
+++ b/client/GUIClasses.cpp
@@ -4367,10 +4367,12 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 			GH.pushInt(spellWindow);
 		}
 	}
+
 	if (!down && previousState)
 	{
 		if(ourArt && ourArt->id == 0)
 			return; //this is handled separately
+
 		if(!ourOwner->commonInfo->srcAOH) //nothing has been clicked
 		{
 			if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported)
@@ -4431,10 +4433,11 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 				ourOwner->commonInfo->destArtifact = ourArt;
 
 				// Special case when the dest artifact can't be fit into the src slot.
-				//CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
+				CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
 				const CArtifactsOfHero* srcAOH = ourOwner->commonInfo->srcAOH;
 				ui16 srcSlotID = ourOwner->commonInfo->srcSlotID;
-				if (ourArt && srcSlotID < 19 && !ourArt->fitsAt(srcAOH->curHero->artifWorn, srcSlotID)) {
+				if (ourArt && srcSlotID < 19 && !ourArt->fitsAt(srcAOH->curHero->artifWorn, srcSlotID)) 
+				{
 					// Put dest artifact into owner's backpack.
 					ourOwner->commonInfo->srcAOH = ourOwner;
 					ourOwner->commonInfo->srcSlotID = ourOwner->curHero->artifacts.size() + 19;
@@ -4448,19 +4451,14 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 			}
 		}
 	}
-	/*else if(!down && clicked)
-	{
-		if(ourArt && ourArt->id == 0)
-			return; //this is handled separately
-		deselect();
-	}*/
-	//ClickableL::clickLeft(down);
 }
 
 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 (slotID < 19) {
+	if(down && ourArt && !locked() && text.size())  //if there is no description or it's a lock, do nothing ;]
+	{
+		if (slotID < 19) 
+		{
 			selectedNo = false;
 
 			// If the artifact can be assembled, display dialog.
@@ -4480,7 +4478,8 @@ void CArtPlace::clickRight(tribool down, bool previousState)
 			}
 
 			// Otherwise if the artifact can be diasassembled, display dialog.
-			if (ourArt->constituents != NULL) {
+			if (ourArt->constituents != NULL) 
+			{
 				LOCPLINT->showArtifactAssemblyDialog(
 					ourArt->id,
 					0,
@@ -4522,11 +4521,11 @@ void CArtPlace::select ()
 	ourOwner->commonInfo->srcAOH = ourOwner;
 
 	// Temporarily remove artifact from hero.
-	//if (slotID < 19)
-	//	CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
-	//else
-	//	ourOwner->curHero->artifacts.erase(ourOwner->curHero->artifacts.begin() + (slotID - 19));
-	//ourOwner->markPossibleSlots(ourArt);
+	if (slotID < 19)
+		CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID);
+	else
+		ourOwner->curHero->artifacts.erase(ourOwner->curHero->artifacts.begin() + (slotID - 19));
+	ourOwner->markPossibleSlots(ourArt);
 	//ourOwner->curHero->recreateArtBonuses();
 
 	// Update the hero bonuses.
@@ -4548,6 +4547,13 @@ void CArtPlace::select ()
 				cew->artifs[g]->setHero(ourOwner->curHero);
 			}
 		}
+
+		//use our copy of hero to draw window
+		if(cew->heroInst[0]->id == ourOwner->curHero->id)
+			cew->heroInst[0] = ourOwner->curHero;
+		else
+			cew->heroInst[1] = ourOwner->curHero;
+
 		cew->prepareBackground();
 		cew->activate();
 	}
@@ -4694,61 +4700,23 @@ void LRClickableAreaOpenTown::clickRight(tribool down, bool previousState)
 		LOCPLINT->openTownWindow(town);//TODO: popup?
 }
 
-void CArtifactsOfHero::activate()
+void CArtifactsOfHero::SCommonPart::reset()
 {
-	for(size_t f=0; f<artWorn.size(); ++f)
-	{
-		if(artWorn[f])
-			artWorn[f]->activate();
-	}
-	for(size_t f=0; f<backpack.size(); ++f)
-	{
-		if(backpack[f])
-			backpack[f]->activate();
-	}
-	
-	leftArtRoll->activate();
-	rightArtRoll->activate();
-}
-
-void CArtifactsOfHero::deactivate()
-{
-	for(size_t f=0; f<artWorn.size(); ++f)
-	{
-		if(artWorn[f])
-			artWorn[f]->deactivate();
-	}
-	for(size_t f=0; f<backpack.size(); ++f)
-	{
-		if(backpack[f])
-			backpack[f]->deactivate();
-	}
-	
-	leftArtRoll->deactivate();
-	rightArtRoll->deactivate();
-}
-
-void CArtifactsOfHero::show(SDL_Surface * to)
-{
-	for(size_t d=0; d<artWorn.size(); ++d)
-	{
-		artWorn[d]->show(to);
-	}
-	for(size_t d=0; d<backpack.size(); ++d)
-	{
-		backpack[d]->show(to);
-	}
-
-	leftArtRoll->show(to);
-	rightArtRoll->show(to);
+	destAOH = srcAOH = NULL;
+	destArtifact = srcArtifact = NULL;
+	destSlotID = srcSlotID = -1;
 }
 
 void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 {
 	// An update is made, rather than initialization.
-	if (curHero == hero) 
+	if (curHero && curHero->id == hero->id) 
 	{
-		curHero = hero;
+		if(curHero != hero)
+		{
+			delete	curHero;
+			curHero = new CGHeroInstance(*hero);
+		}
 
 		// Compensate backpack pos if an artifact was insertad before it.
 		if (commonInfo->destSlotID >= 19 && commonInfo->destAOH == this
@@ -4757,14 +4725,16 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 			backpackPos++;
 		}
 
-		if (updateState && commonInfo->srcAOH == this) {
+		if (updateState && commonInfo->srcAOH == this) 
+		{
 			// A swap was made, make the replaced artifact the current selected.
-			if (commonInfo->destSlotID < 19 && commonInfo->destArtifact) {
+			if (commonInfo->destSlotID < 19 && commonInfo->destArtifact) 
+			{
 				// Temporarily remove artifact from hero.
-				//if (commonInfo->srcSlotID < 19)
-				//	CGI->arth->unequipArtifact(curHero->artifWorn, commonInfo->srcSlotID);
-				//else
-				//	curHero->artifacts.erase(curHero->artifacts.begin() + (commonInfo->srcSlotID - 19));
+				if (commonInfo->srcSlotID < 19)
+					CGI->arth->unequipArtifact(curHero->artifWorn, commonInfo->srcSlotID);
+				else
+					curHero->artifacts.erase(curHero->artifacts.begin() + (commonInfo->srcSlotID - 19));
 				//curHero->recreateArtBonuses();
 
 				// Source <- Dest
@@ -4775,20 +4745,13 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 				commonInfo->destArtifact = NULL;
 				commonInfo->destSlotID = -1;
 
-				CGI->curh->dragAndDropCursor(
-					graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
+				CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
 				markPossibleSlots(commonInfo->srcArtifact);
 			} 
 			else if (commonInfo->destAOH != NULL) 
 			{
 				// Reset all parameters.
-				commonInfo->srcAOH = NULL;
-				commonInfo->srcArtifact = NULL;
-				commonInfo->srcSlotID = -1;
-				commonInfo->destAOH = NULL;
-				commonInfo->destArtifact = NULL;
-				commonInfo->destSlotID = -1;
-
+				commonInfo->reset();
 				CGI->curh->dragAndDropCursor(NULL);
 				unmarkSlots();
 			}
@@ -4796,10 +4759,14 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 	} 
 	else 
 	{
-		rollback();
+		commonInfo->reset();
 	}
 
-	curHero = const_cast<CGHeroInstance *>(hero);
+	if(hero != curHero)
+	{
+		delete curHero;
+		curHero = new CGHeroInstance(*hero);
+	}
 
 	if (curHero->artifacts.size() > 0)
 		backpackPos %= curHero->artifacts.size();
@@ -4816,67 +4783,16 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 	rightArtRoll->block(curHero->artifacts.size() <= backpack.size());
 }
 
-/**
- * Any held artifacts, marked slots etc. will be restored to it's original way.
- */
-void CArtifactsOfHero::rollback()
-{
-	if (curHero != NULL) 
-	{
-		// Restore any held artifact to it's original position.
-		if (commonInfo->srcArtifact && commonInfo->srcAOH == this) 
-		{
-			if (commonInfo->srcSlotID != -1) {
-				// Put a held artifact back to it's spot.
-				//if (commonInfo->srcSlotID < 19)
-				//	CGI->arth->equipArtifact(curHero->artifWorn, commonInfo->srcSlotID, commonInfo->srcArtifact->id);
-				//else
-				//	curHero->artifacts.insert(curHero->artifacts.begin() + (commonInfo->srcSlotID - 19), commonInfo->srcArtifact->id);
-			} 
-			else  // Held swapped artifact.
-			{
-				// Wear the artifact in a suitable spot.
-				ui16 i = 0;
-				for (; i < 19; i++) 
-				{
-					if (artWorn[i]->fitsHere(commonInfo->srcArtifact) && !vstd::contains(curHero->artifWorn, i)) 
-					{
-						//CGI->arth->equipArtifact(curHero->artifWorn, i, commonInfo->srcArtifact->id);
-						break;
-					}
-				}
-
-				// If it can't be worn, put it in the backpack.
-				if (i == 19)
-					;//curHero->artifacts.push_back(commonInfo->srcArtifact->id);
-			}
-
-			//curHero->recreateArtBonuses();
-		}
-	}
-
-	unmarkSlots();
-	backpackPos = 0;
-
-	commonInfo->srcAOH = NULL;
-	commonInfo->srcArtifact = NULL;
-	commonInfo->srcSlotID = -1;
-	commonInfo->destAOH = NULL;
-	commonInfo->destArtifact = NULL;
-	commonInfo->destSlotID = -1;
-
-	CGI->curh->dragAndDropCursor(NULL);
-}
-
 void CArtifactsOfHero::dispose()
 {
-	curHero = NULL;
+	delNull(curHero);
 }
 
 void CArtifactsOfHero::scrollBackpack(int dir)
 {
 	backpackPos += dir;
-	if (curHero->artifacts.size() > 0) {
+	if (curHero->artifacts.size() > 0) 
+	{
 		if (backpackPos < 0) { // No guarantee of modulus behavior with negative operands.
 			do {
 				backpackPos += curHero->artifacts.size();
@@ -4887,7 +4803,8 @@ void CArtifactsOfHero::scrollBackpack(int dir)
 	}
 
 	//set new data
-	for (size_t s = 0; s < backpack.size(); ++s) {
+	for (size_t s = 0; s < backpack.size(); ++s) 
+	{
 		if (s < curHero->artifacts.size())
 			setSlotData(backpack[s], 19 + (s + backpackPos)%curHero->artifacts.size());
 		else
@@ -4906,7 +4823,8 @@ void CArtifactsOfHero::markPossibleSlots (const CArtifact* art)
 		it != commonInfo->participants.end();
 		++it)
 	{
-		for (int i = 0; i < (*it)->artWorn.size(); i++) {
+		for (int i = 0; i < (*it)->artWorn.size(); i++) 
+		{
 			if ((*it)->artWorn[i]->fitsHere(art))
 				(*it)->artWorn[i]->marked = true;
 			else
@@ -4924,7 +4842,8 @@ void CArtifactsOfHero::unmarkSlots ()
 		it != commonInfo->participants.end();
 		++it)
 	{
-		for (int i = 0; i < (*it)->artWorn.size(); i++) {
+		for (int i = 0; i < (*it)->artWorn.size(); i++) 
+		{
 			(*it)->artWorn[i]->marked = false;
 		}
 	}
@@ -4938,13 +4857,16 @@ void CArtifactsOfHero::setSlotData (CArtPlace* artPlace, int slotID)
 	artPlace->slotID = slotID;
 	artPlace->ourArt = curHero->getArt(slotID);
 
-	if (artPlace->ourArt) {
+	if (artPlace->ourArt) 
+	{
 		artPlace->text = artPlace->ourArt->Description();
 		if (artPlace->locked()) // Locks should appear as empty.
 			artPlace->hoverText = CGI->generaltexth->allTexts[507];
 		else
 			artPlace->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % artPlace->ourArt->Name().c_str());
-	} else {
+	} 
+	else 
+	{
 		eraseSlotData(artPlace, slotID);
 	}
 }
@@ -4961,25 +4883,26 @@ void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, int slotID)
 }
 
 CArtifactsOfHero::CArtifactsOfHero(const Point &position) :
-	backpackPos(0), updateState(false), commonInfo(NULL)
+	backpackPos(0), updateState(false), commonInfo(NULL), curHero(NULL)
 {
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	pos += position;
 	artWorn.resize(19);
 	
-	std::vector<SDL_Rect> slotPos;
-	slotPos += genRect(44,44,pos.x+509,pos.y+30), genRect(44,44,pos.x+567,pos.y+240), genRect(44,44,pos.x+509,pos.y+80), 
-		genRect(44,44,pos.x+383,pos.y+68), genRect(44,44,pos.x+564,pos.y+183), genRect(44,44,pos.x+509,pos.y+130), 
-		genRect(44,44,pos.x+431,pos.y+68), genRect(44,44,pos.x+610,pos.y+183), genRect(44,44,pos.x+515,pos.y+295), 
-		genRect(44,44,pos.x+383,pos.y+143), genRect(44,44,pos.x+399,pos.y+194), genRect(44,44,pos.x+415,pos.y+245),
-		genRect(44,44,pos.x+431,pos.y+296), genRect(44,44,pos.x+564,pos.y+30), genRect(44,44,pos.x+610,pos.y+30), 
-		genRect(44,44,pos.x+610,pos.y+76), genRect(44,44,pos.x+610,pos.y+122), genRect(44,44,pos.x+610,pos.y+310),	
-		genRect(44,44,pos.x+381,pos.y+296);
+	std::vector<Rect> slotPos;
+	slotPos += genRect(44,44,509,30), genRect(44,44,567,240), genRect(44,44,509,80), 
+		genRect(44,44,383,68), genRect(44,44,564,183), genRect(44,44,509,130), 
+		genRect(44,44,431,68), genRect(44,44,610,183), genRect(44,44,515,295), 
+		genRect(44,44,383,143), genRect(44,44,399,194), genRect(44,44,415,245),
+		genRect(44,44,431,296), genRect(44,44,564,30), genRect(44,44,610,30), 
+		genRect(44,44,610,76), genRect(44,44,610,122), genRect(44,44,610,310),	
+		genRect(44,44,381,296);
 
 	// Create slots for worn artifacts.
 	for (int g = 0; g < 19 ; g++)
 	{	
 		artWorn[g] = new CArtPlace(NULL);
-		artWorn[g]->pos = slotPos[g];
+		artWorn[g]->pos = slotPos[g] + pos;
 		artWorn[g]->ourOwner = this;
 		eraseSlotData(artWorn[g], g);
 	}
@@ -4998,28 +4921,14 @@ CArtifactsOfHero::CArtifactsOfHero(const Point &position) :
 		backpack.push_back(add);
 	}
 
-	leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1), pos.x+379, pos.y+364, "hsbtns3.def", SDLK_LEFT);
-	rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1), pos.x+632, pos.y+364, "hsbtns5.def", SDLK_RIGHT);
+	leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1), 379, 364, "hsbtns3.def", SDLK_LEFT);
+	rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1), 632, 364, "hsbtns5.def", SDLK_RIGHT);
 }
 
 CArtifactsOfHero::~CArtifactsOfHero()
 {
 	dispose();
-	for(size_t g=0; g<artWorn.size(); ++g)
-	{
-		delete artWorn[g];
-		artWorn[g] = NULL;
-	}
-	for(size_t g=0; g<backpack.size(); ++g)
-	{
-		delete backpack[g];
-		backpack[g] = NULL;
-	}
-	backpack.clear();
-	artWorn.clear();
-
-	delete leftArtRoll;
-	delete rightArtRoll;
+	CGI->curh->dragAndDropCursor(NULL);
 }
 
 void CExchangeWindow::close()
@@ -5324,8 +5233,6 @@ CExchangeWindow::~CExchangeWindow() //d-tor
 	delete quit;
 
 	//warning: don't experiment with these =NULL lines, they prevent heap corruption!
-	artifs[0]->rollback();
-	artifs[1]->rollback();
 	delete artifs[0]->commonInfo;
 	artifs[0]->commonInfo = NULL;
 	delete artifs[0];
diff --git a/client/GUIClasses.h b/client/GUIClasses.h
index f852ae0fb..b1d2145eb 100644
--- a/client/GUIClasses.h
+++ b/client/GUIClasses.h
@@ -909,7 +909,7 @@ inline bool CArtPlace::locked () const
 
 class CArtifactsOfHero : public CIntObject
 {
-	const CGHeroInstance * curHero;
+	CGHeroInstance * curHero; //local copy of hero on which we operate
 
 	std::vector<CArtPlace *> artWorn; // 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<CArtPlace *> backpack; //hero's visible backpack (only 5 elements!)
@@ -925,19 +925,16 @@ public:
 		const CArtifactsOfHero * destAOH; // For swapping. (i.e. changing what is held)
 		int destSlotID;	                  // Needed to determine what kind of action was last taken in setHero
 		const CArtifact * destArtifact;   // For swapping.
+
+		void reset();
 	} * commonInfo; //when we have more than one CArtifactsOfHero in one window with exchange possibility, we use this (eg. in exchange window); to be provided externally
 
 	bool updateState; // Whether the commonInfo should be updated on setHero or not.
 
 	AdventureMapButton * leftArtRoll, * rightArtRoll;
 
-	void activate();
-	void deactivate();
-	void show(SDL_Surface * to);
-
 	void setHero(const CGHeroInstance * hero);
 	void dispose(); //free resources not needed after closing windows and reset state
-	void rollback();
 	void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
 	void markPossibleSlots (const CArtifact* art);
 	void unmarkSlots ();
diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp
index e825bfce9..175cab7c1 100644
--- a/client/NetPacksClient.cpp
+++ b/client/NetPacksClient.cpp
@@ -326,17 +326,17 @@ void SetHeroArtifacts::applyCl( CClient *cl )
 	if(!player)
 		return;
 
-	h->recreateArtBonuses();
+	//h->recreateArtBonuses();
 	player->heroArtifactSetChanged(h);
 
-	BOOST_FOREACH(Bonus bonus, gained)
-	{
-		player->heroBonusChanged(h,bonus,true);
-	}
-	BOOST_FOREACH(Bonus bonus, lost)
-	{
-		player->heroBonusChanged(h,bonus,false);
-	}
+// 	BOOST_FOREACH(Bonus bonus, gained)
+// 	{
+// 		player->heroBonusChanged(h,bonus,true);
+// 	}
+// 	BOOST_FOREACH(Bonus bonus, lost)
+// 	{
+// 		player->heroBonusChanged(h,bonus,false);
+// 	}
 }
 
 void HeroRecruited::applyCl( CClient *cl )
diff --git a/hch/CArtHandler.cpp b/hch/CArtHandler.cpp
index 6ca8c725a..eeba03456 100644
--- a/hch/CArtHandler.cpp
+++ b/hch/CArtHandler.cpp
@@ -87,7 +87,8 @@ bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) cons
 		}
 
 		// Ensure enough ring slots are free
-		for (int i = 0; i < sizeof(ringSlots)/sizeof(*ringSlots); i++) {
+		for (int i = 0; i < sizeof(ringSlots)/sizeof(*ringSlots); i++) 
+		{
 			if (tempArtifWorn.find(ringSlots[i]) == tempArtifWorn.end() || ringSlots[i] == slotID)
 				rings--;
 		}
@@ -95,7 +96,8 @@ bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) cons
 			return false;
 
 		// Ensure enough misc slots are free.
-		for (int i = 0; i < sizeof(miscSlots)/sizeof(*miscSlots); i++) {
+		for (int i = 0; i < sizeof(miscSlots)/sizeof(*miscSlots); i++) 
+		{
 			if (tempArtifWorn.find(miscSlots[i]) == tempArtifWorn.end() || miscSlots[i] == slotID)
 				misc--;
 		}
@@ -114,10 +116,13 @@ bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 ar
 	const CArtifact &artifact = *VLC->arth->artifacts[artifactID];
 	assert(artifact.constituents);
 
-	BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
+	BOOST_FOREACH(ui32 constituentID, *artifact.constituents) 
+	{
 		bool found = false;
-		for (std::map<ui16, ui32>::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it) {
-			if (it->second == constituentID) {
+		for (std::map<ui16, ui32>::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it) 
+		{
+			if (it->second == constituentID) 
+			{
 				found = true;
 				break;
 			}
@@ -129,43 +134,13 @@ bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 ar
 	return true;
 }
 
-/**
- * Adds all the bonuses of this artifact, including possible constituents, to
- * a bonus list.
- */
-void CArtifact::addBonusesTo (BonusList *otherBonuses) const
+CArtifact::CArtifact()
 {
-	for(std::list<Bonus>::const_iterator i = bonuses.begin(); i != bonuses.end(); i++)
-		otherBonuses->push_back(*i);
-
-	if (constituents != NULL) {
-		BOOST_FOREACH(ui32 artifactID, *constituents) 
-		{
-			VLC->arth->artifacts[artifactID]->addBonusesTo(otherBonuses);
-		}
-	}
+	nodeType = ARTIFACT;
 }
 
-/**
- * Removes all the bonuses of this artifact, including possible constituents, from
- * a bonus list.
- */
-void CArtifact::removeBonusesFrom (BonusList *otherBonuses) const
+CArtifact::~CArtifact()
 {
-	if (constituents != NULL) {
-		BOOST_FOREACH(ui32 artifactID, *constituents) {
-			VLC->arth->artifacts[artifactID]->removeBonusesFrom(otherBonuses);
-		}
-	}
-
-	while (1) {
-		std::list<Bonus>::iterator it = std::find_if(otherBonuses->begin(), otherBonuses->end(),boost::bind(Bonus::IsFrom,_1,Bonus::ARTIFACT,id));
-
-		if (it != otherBonuses->end())
-			otherBonuses->erase(it);
-		else
-			break;
-	}
 }
 
 CArtHandler::CArtHandler()
@@ -709,10 +684,9 @@ void CArtHandler::clear()
  * @param artifWorn A hero's set of worn artifacts.
  * @param bonuses Optional list of bonuses to update.
  */
-void CArtHandler::equipArtifact
-	(std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID, BonusList *bonuses)
+void CArtHandler::equipArtifact(std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID)
 {
-	unequipArtifact(artifWorn, slotID, bonuses);
+	unequipArtifact(artifWorn, slotID);
 
 	const CArtifact &artifact = *artifacts[artifactID];
 
@@ -745,9 +719,6 @@ void CArtHandler::equipArtifact
 			}
 		}
 	}
-
-	if (bonuses != NULL)
-		artifact.addBonusesTo(bonuses);
 }
 
 /**
@@ -756,8 +727,7 @@ void CArtHandler::equipArtifact
  * @param artifWorn A hero's set of worn artifacts.
  * @param bonuses Optional list of bonuses to update.
  */
-void CArtHandler::unequipArtifact
-	(std::map<ui16, ui32> &artifWorn, ui16 slotID, BonusList *bonuses)
+void CArtHandler::unequipArtifact(std::map<ui16, ui32> &artifWorn, ui16 slotID)
 {
 	if (!vstd::contains(artifWorn, slotID))
 		return;
@@ -793,7 +763,4 @@ void CArtHandler::unequipArtifact
 			}
 		}
 	}
-
-	if (bonuses != NULL)
-		artifact.removeBonusesFrom(bonuses);
 }
diff --git a/hch/CArtHandler.h b/hch/CArtHandler.h
index 10312b2ba..0cb64e90b 100644
--- a/hch/CArtHandler.h
+++ b/hch/CArtHandler.h
@@ -18,7 +18,7 @@
  */
 class CDefHandler;
 
-class DLL_EXPORT CArtifact //container for artifacts
+class DLL_EXPORT CArtifact : public CBonusSystemNode //container for artifacts
 {
 	std::string name, description; //set if custom
 public:
@@ -37,12 +37,15 @@ public:
 	std::vector<ui32> * constituentOf; // Reverse map of constituents.
 	EartClass aClass;
 	si32 id;
-	std::list<Bonus> bonuses; //bonuses given by artifact
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & name & description & price & possibleSlots & constituents & constituentOf & aClass & id & bonuses;
+		h & static_cast<CBonusSystemNode&>(*this);;
+		h & name & description & price & possibleSlots & constituents & constituentOf & aClass & id;
 	}
+
+	CArtifact();
+	~CArtifact();
 };
 
 class DLL_EXPORT CArtHandler //handles artifacts
@@ -64,8 +67,8 @@ public:
 	void getAllowed(std::vector<CArtifact*> &out, int flags);
 	void erasePickedArt (si32 id);
 	bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
-	void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID, BonusList *bonuses = NULL);
-	void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, BonusList *bonuses = NULL);
+	void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID);
+	void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID);
 	static int convertMachineID(int id, bool creToArt);
 	CArtHandler();
 	~CArtHandler();
diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp
index a59f760c6..ffa9a5dce 100644
--- a/hch/CObjectHandler.cpp
+++ b/hch/CObjectHandler.cpp
@@ -762,9 +762,9 @@ void CGHeroInstance::initHero()
 
 	if(!vstd::contains(artifWorn, 16) && type->startingSpell >= 0) //no catapult means we haven't read pre-existant set
 	{
-		VLC->arth->equipArtifact(artifWorn, 17, 0, &bonuses); //give spellbook
+		VLC->arth->equipArtifact(artifWorn, 17, 0); //give spellbook
 	}
-	VLC->arth->equipArtifact(artifWorn, 16, 3, &bonuses); //everyone has a catapult
+	VLC->arth->equipArtifact(artifWorn, 16, 3); //everyone has a catapult
 
 	if(portrait < 0 || portrait == 255)
 		portrait = subID;
@@ -800,7 +800,6 @@ void CGHeroInstance::initHero()
 	boost::algorithm::replace_first(hoverName,"%s",name);
 	boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
 
-	recreateArtBonuses();
 	if(mana < 0)
 		mana = manaLimit(); //after all bonuses are taken into account
 }
@@ -833,14 +832,13 @@ void CGHeroInstance::initArmy(CCreatureSet *dst /*= NULL*/)
 			switch (creID)
 			{
 			case 145: //catapult
-				VLC->arth->equipArtifact(artifWorn, 16, 3, &bonuses);
+				VLC->arth->equipArtifact(artifWorn, 16, 3);
 				break;
 			default:
 				VLC->arth->equipArtifact(
 					artifWorn,
 					9+CArtHandler::convertMachineID(creID,true),
-					CArtHandler::convertMachineID(creID,true),
-					&bonuses);
+					  CArtHandler::convertMachineID(creID,true));
 				break;
 			}
 		}
@@ -937,7 +935,7 @@ void CGHeroInstance::initObj()
 	if(!type)
 		return; //TODO support prison
 
-	for (std::vector<specialInfo>::iterator it = type->spec.begin(); it != type->spec.end(); it++)
+	for (std::vector<specialInfo>::const_iterator it = type->spec.begin(); it != type->spec.end(); it++)
 	{
 		bonus.val = it->val;
 		bonus.id = id; //from the hero, speciality has no unique id
@@ -1386,7 +1384,7 @@ void CGHeroInstance::giveArtifact (ui32 aid)
 		{
 			if (!vstd::contains(artifWorn, *it)) 
 			{
-				VLC->arth->equipArtifact(artifWorn, *it, aid, &bonuses);
+				VLC->arth->equipArtifact(artifWorn, *it, aid);
 				break;
 			}
 		}
@@ -1397,17 +1395,6 @@ void CGHeroInstance::giveArtifact (ui32 aid)
 	}
 }
 
-void CGHeroInstance::recreateArtBonuses()
-{
-	//clear all bonuses from artifacts (if present) and give them again
-	bonuses.remove_if(boost::bind(Bonus::IsFrom,_1,Bonus::ARTIFACT,0xffffff));
-	for (std::map<ui16,ui32>::iterator ari = artifWorn.begin(); ari != artifWorn.end(); ari++)
-	{
-		CArtifact &art = *VLC->arth->artifacts[ari->second];
-		art.addBonusesTo(&bonuses);
-	}
-}
-
 bool CGHeroInstance::hasArt( ui32 aid ) const
 {
 	if(vstd::contains(artifacts, aid))
@@ -1455,7 +1442,10 @@ void CGHeroInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= N
 	if((root == this || contains(static_cast<const CStackInstance *>(root))) &&  visitedTown)
 		out.insert(visitedTown);
 
-	out.insert (&speciality);
+	for (std::map<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
+		out.insert(VLC->arth->artifacts[i->second]);
+
+	out.insert(&speciality);
 }
 
 void CGHeroInstance::pushPrimSkill(int which, int val)
diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h
index 13e40d013..57f24d580 100644
--- a/hch/CObjectHandler.h
+++ b/hch/CObjectHandler.h
@@ -275,7 +275,7 @@ public:
 
 	//////////////////////////////////////////////////////////////////////////
 
-	CHero * type;
+	const CHero * type;
 	ui64 exp; //experience points
 	si32 level; //current level of hero
 	std::string name; //may be custom
@@ -286,8 +286,8 @@ public:
 	si32 movement; //remaining movement points
 	ui8 sex;
 	ui8 inTownGarrison; // if hero is in town garrison 
-	CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison
-	CGBoat *boat; //set to CGBoat when sailing
+	const CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison
+	const CGBoat *boat; //set to CGBoat when sailing
 	std::vector<ui32> artifacts; //hero's artifacts from bag
 	std::map<ui16,ui32> 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)
@@ -376,7 +376,6 @@ public:
 	void initHero(); 
 	void initHero(int SUBID); 
 	void initArmy(CCreatureSet *dst = NULL);
-	void recreateArtBonuses();
 	void giveArtifact (ui32 aid);
 	void initHeroDefInfo();
 	void pushPrimSkill(int which, int val);
diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp
index 649883a4a..83006c895 100644
--- a/lib/CGameState.cpp
+++ b/lib/CGameState.cpp
@@ -1484,10 +1484,8 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 
 				CGHeroInstance *hero = k->second.heroes[0];
 				std::vector<ui16>::iterator slot = vstd::findFirstNot (hero->artifWorn, toGive->possibleSlots);
-				if(slot!=toGive->possibleSlots.end())
-				{
-					VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive->id, &hero->bonuses);
-				}
+				if(slot != toGive->possibleSlots.end())
+					VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive->id);
 				else
  					hero->giveArtifact(toGive->id);
 			}
diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h
index 03bba4a5b..b0897d990 100644
--- a/lib/HeroBonus.h
+++ b/lib/HeroBonus.h
@@ -377,7 +377,7 @@ public:
 
 	enum ENodeTypes
 	{
-		UNKNOWN, STACK, SPECIALITY
+		UNKNOWN, STACK, SPECIALITY, ARTIFACT
 	};
 };
 
diff --git a/lib/NetPacks.h b/lib/NetPacks.h
index bfd93c935..5a5c9a755 100644
--- a/lib/NetPacks.h
+++ b/lib/NetPacks.h
@@ -588,6 +588,7 @@ struct SetHeroArtifacts : public CPackForClient //509
 		h & hid & artifacts & artifWorn;
 	}
 
+	std::vector<ui32> equiped, unequiped; //used locally
 	BonusList gained, lost; //used locally as hlp when applying
 };   
 
diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp
index 50e241e1c..e67f8f1c6 100644
--- a/lib/NetPacksLib.cpp
+++ b/lib/NetPacksLib.cpp
@@ -301,12 +301,12 @@ DLL_EXPORT void RemoveObject::applyGs( CGameState *gs )
 		gs->getPlayer(player)->heroes.erase(nitr);
 		h->tempOwner = 255; //no one owns beaten hero
 
-		if(h->visitedTown)
+		if(CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown))
 		{
 			if(h->inTownGarrison)
-				h->visitedTown->garrisonHero = NULL;
+				t->garrisonHero = NULL;
 			else
-				h->visitedTown->visitingHero = NULL;
+				t->visitingHero = NULL;
 			h->visitedTown = NULL;
 		}
 
@@ -382,10 +382,11 @@ void TryMoveHero::applyGs( CGameState *gs )
 	}
 	else if(result == DISEMBARK) //hero leaves boat to dest tile
 	{
-		h->boat->direction = h->moveDir;
-		h->boat->pos = start;
-		h->boat->hero = NULL;
-		gs->map->addBlockVisTiles(h->boat);
+		CGBoat *b = const_cast<CGBoat *>(h->boat);
+		b->direction = h->moveDir;
+		b->pos = start;
+		b->hero = NULL;
+		gs->map->addBlockVisTiles(b);
 		h->boat = NULL;
 	}
 
@@ -393,8 +394,8 @@ void TryMoveHero::applyGs( CGameState *gs )
 	{
 		gs->map->removeBlockVisTiles(h);
 		h->pos = end;
-		if(h->boat)
-			h->boat->pos = end;
+		if(CGBoat *b = const_cast<CGBoat *>(h->boat))
+			b->pos = end;
 		gs->map->addBlockVisTiles(h);
 	}
 
@@ -413,8 +414,9 @@ DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )
 		else if(ai->ID==HEROI_TYPE)
 		{
 			CGHeroInstance *h =  static_cast<CGHeroInstance*>(ai);
-			if(h->visitedTown && h->inTownGarrison)
-				h->visitedTown->setArmy(i->second);
+			CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown);
+			if(t && h->inTownGarrison)
+				t->setArmy(i->second);
 		}
 	}
 }
@@ -470,7 +472,6 @@ DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs )
 DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
 {
 	CGHeroInstance *h = gs->getHero(hid);
-	std::vector<ui32> equiped, unequiped;
 	for(std::map<ui16,ui32>::const_iterator i = h->artifWorn.begin(); i != h->artifWorn.end(); i++)
 		if(!vstd::contains(artifWorn,i->first)  ||  artifWorn[i->first] != i->second)
 			unequiped.push_back(i->second);
@@ -479,37 +480,14 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
 		if(!vstd::contains(h->artifWorn,i->first)  ||  h->artifWorn[i->first] != i->second)
 			equiped.push_back(i->second);
 
-	BOOST_FOREACH(ui32 id, equiped)
-	{
-		//if hero already had equipped at least one artifact of that type, don't give any new bonuses
-		if(h->getArtPos(id) >= 0)
-			continue;
-
-		CArtifact &art = *VLC->arth->artifacts[id];
-		art.addBonusesTo(&h->bonuses);
-		art.addBonusesTo(&gained);
-	}
-
 	//update hero data
 	h->artifacts = artifacts;
 	h->artifWorn = artifWorn;
-
-	//remove bonus from unequipped artifact
-	BOOST_FOREACH(ui32 id, unequiped)
-	{
-		//if hero still has equipped at least one artifact of that type, don't remove bonuses
-		if(h->getArtPos(id) >= 0)
-			continue;
-
-		CArtifact &art = *VLC->arth->artifacts[id];
-		art.removeBonusesFrom(&h->bonuses);
-		art.addBonusesTo(&lost);
-	}
 }
 
 DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art)
 {
-	if(art<0)
+	if(art < 0)
 	{
 		if(pos<19)
 			VLC->arth->unequipArtifact(artifWorn, pos);
@@ -518,9 +496,12 @@ DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art)
 	}
 	else
 	{
-		if (pos < 19) {
+		if (pos < 19) 
+		{
 			VLC->arth->equipArtifact(artifWorn, pos, (ui32) art);
-		} else { // Goes into the backpack.
+		} 
+		else // Goes into the backpack.
+		{ 
 			if(pos - 19 < artifacts.size())
 				artifacts.insert(artifacts.begin() + (pos - 19), art);
 			else
diff --git a/lib/map.cpp b/lib/map.cpp
index 5c391325d..263060a94 100644
--- a/lib/map.cpp
+++ b/lib/map.cpp
@@ -920,39 +920,39 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
 		for(int pom=0;pom<16;pom++)
 		{
 			int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-			if(id!=artmask)
-				VLC->arth->equipArtifact(nhi->artifWorn, pom, id, &nhi->bonuses);
+			if(id != artmask)
+				VLC->arth->equipArtifact(nhi->artifWorn, pom, id);
 		}
 		//misc5 art //17
 		if(version>=SoD)
 		{
 			int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
 			if(id!=artmask)
-				VLC->arth->equipArtifact(nhi->artifWorn, 16, id, &nhi->bonuses);
+				VLC->arth->equipArtifact(nhi->artifWorn, 16, id);
 			else
-				VLC->arth->equipArtifact(nhi->artifWorn, 16, 3, &nhi->bonuses); //catapult by default
+				VLC->arth->equipArtifact(nhi->artifWorn, 16, 3); //catapult by default
 		}
 		//spellbook
 		int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
 		if(id!=artmask)
-			VLC->arth->equipArtifact(nhi->artifWorn, 17, id, &nhi->bonuses);
+			VLC->arth->equipArtifact(nhi->artifWorn, 17, id);
 		//19 //???what is that? gap in file or what? - it's probably fifth slot..
 		if(version>RoE)
 		{
 			id = readNormalNr(bufor,i, artidlen); i+=artidlen;
 			if(id!=artmask)
-				VLC->arth->equipArtifact(nhi->artifWorn, 18, id, &nhi->bonuses);
+				VLC->arth->equipArtifact(nhi->artifWorn, 18, id);
 		}
 		else
 			i+=1;
 		//bag artifacts //20
 		int amount = readNormalNr(bufor,i, 2); i+=2; //number of artifacts in hero's bag
-		if(amount>0)
+		if(amount > 0)
 		{
-			for(int ss=0; ss<amount; ++ss)
+			for(int ss = 0; ss < amount; ++ss)
 			{
 				id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-				if(id!=artmask)
+				if(id != artmask)
 					nhi->giveArtifact(id);
 			}
 		}
@@ -1160,7 +1160,7 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
 					{
 						int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
 						if(id!=artmask)
-							VLC->arth->equipArtifact(cgh->artifWorn, pom, id, &cgh->bonuses);
+							VLC->arth->equipArtifact(cgh->artifWorn, pom, id);
 					}
 					//misc5 art //17
 					if(version>=SoD)
@@ -1173,13 +1173,13 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
 					//spellbook
 					int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
 					if(id!=artmask)
-						VLC->arth->equipArtifact(cgh->artifWorn, 17, id, &cgh->bonuses);
+						VLC->arth->equipArtifact(cgh->artifWorn, 17, id);
 					//19 //???what is that? gap in file or what? - it's probably fifth slot..
 					if(version>RoE)
 					{
 						id = readNormalNr(bufor,i, artidlen); i+=artidlen;
 						if(id!=artmask)
-							VLC->arth->equipArtifact(cgh->artifWorn, 18, id, &cgh->bonuses);
+							VLC->arth->equipArtifact(cgh->artifWorn, 18, id);
 					}
 					else
 						i+=1;
diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp
index 928b54274..71fff8f4b 100644
--- a/server/CGameHandler.cpp
+++ b/server/CGameHandler.cpp
@@ -2926,7 +2926,8 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 	const CArtifact *srcArtifact = srcHero->getArt(srcSlot);
 	const CArtifact *destArtifact = destHero->getArt(destSlot);
 
-	if (srcArtifact == NULL) {
+	if (srcArtifact == NULL)
+	{
 		complain("No artifact to swap!");
 		return false;
 	}
@@ -2937,7 +2938,8 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 	sha.artifWorn = srcHero->artifWorn;
 
 	// Combinational artifacts needs to be removed first so they don't get denied movement because of their own locks.
-	if (srcHeroID == destHeroID && srcSlot < 19 && destSlot < 19) {
+	if (srcHeroID == destHeroID && srcSlot < 19 && destSlot < 19) 
+	{
 		sha.setArtAtPos(srcSlot, -1);
 		if (!vstd::contains(sha.artifWorn, destSlot))
 			destArtifact = NULL;
@@ -2952,17 +2954,20 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 		return false;
 	}
 
-	if ((srcArtifact && srcArtifact->id == 145) || (destArtifact && destArtifact->id == 145)) {
+	if ((srcArtifact && srcArtifact->id == 145) || (destArtifact && destArtifact->id == 145)) 
+	{
 		complain("Cannot move artifact locks.");
 		return false;
 	}
 
-	if (destSlot >= 19 && srcArtifact->isBig()) {
+	if (destSlot >= 19 && srcArtifact->isBig()) 
+	{
 		complain("Cannot put big artifacts in backpack!");
 		return false;
 	}
 
-	if (srcSlot == 16 || destSlot == 16) {
+	if (srcSlot == 16 || destSlot == 16) 
+	{
 		complain("Cannot move catapult!");
 		return false;
 	}
@@ -2979,7 +2984,8 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 		sha.setArtAtPos(srcSlot, destArtifact ? destArtifact->id : -1);
 
 	// Internal hero artifact arrangement.
-	if(srcHero == destHero) {
+	if(srcHero == destHero) 
+	{
 		// Correction for destination from removing source artifact in backpack.
 		if (srcSlot >= 19 && destSlot >= 19 && srcSlot < destSlot)
 			destSlot--;
@@ -2987,7 +2993,8 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
 		sha.setArtAtPos(destSlot, srcHero->getArtAtPos(srcSlot));
 	}
 	sendAndApply(&sha);
-	if (srcHeroID != destHeroID) {
+	if (srcHeroID != destHeroID) 
+	{
 		// Exchange between two different heroes.
 		sha.hid = destHeroID;
 		sha.artifacts = destHero->artifacts;
@@ -3112,7 +3119,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
 bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
 {
 	CGHeroInstance *hero = gs->getHero(hid);
-	CGTownInstance *town = hero->visitedTown;
+	CGTownInstance *town = const_cast<CGTownInstance*>(hero->visitedTown);
 	if(aid==0) //spellbook
 	{
 		if(!vstd::contains(town->builtBuildings,si32(0)) && complain("Cannot buy a spellbook, no mage guild in the town!")