瀏覽代碼

A handful of fixes for artifacts, minor for for battles.

Michał W. Urbańczyk 14 年之前
父節點
當前提交
a940daba5e
共有 7 個文件被更改,包括 184 次插入131 次删除
  1. 2 0
      client/CHeroWindow.cpp
  2. 14 3
      client/CMT.cpp
  3. 146 115
      client/GUIClasses.cpp
  4. 6 4
      client/GUIClasses.h
  5. 5 1
      lib/HeroBonus.cpp
  6. 3 1
      lib/NetPacksLib.cpp
  7. 8 7
      server/CGameHandler.cpp

+ 2 - 0
client/CHeroWindow.cpp

@@ -48,6 +48,8 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState)
 	if(!down)
 	{
 		const CGHeroInstance * buf = LOCPLINT->getWHero(id);
+		if(!buf)
+			return;
 		GH.popIntTotally(getOwner());
 		GH.pushInt(new CHeroWindow(buf));
 	}

+ 14 - 3
client/CMT.cpp

@@ -44,6 +44,7 @@
 #include "CMessage.h"
 #include "../lib/CObjectHandler.h"
 #include <boost/program_options.hpp>
+#include "../lib/CArtHandler.h"
 
 #ifdef _WIN32
 #include "SDL_syswm.h"
@@ -306,10 +307,7 @@ void processCommand(const std::string &message)
 	readed.str(message);
 	std::string cn; //command name
 	readed >> cn;
-	int3 src, dst;
 
-//	int heronum;//TODO use me
-	int3 dest;
 
 	if(LOCPLINT && LOCPLINT->cingconsole)
 		LOCPLINT->cingconsole->print(message);
@@ -472,6 +470,19 @@ void processCommand(const std::string &message)
 				tlog4 << typeid(*obj).name() << std::endl;
 		}
 	}
+	else if(cn=="tell")
+	{
+		std::string what;
+		int id1, id2;
+		readed >> what >> id1 >> id2;
+		if(what == "hs")
+		{
+			BOOST_FOREACH(const CGHeroInstance *h, LOCPLINT->cb->getHeroesInfo())
+				if(h->type->ID == id1)
+					if(const CArtifactInstance *a = h->getArt(id2))
+						tlog4 << a->nodeName();
+		}
+	}
 	else if(client && client->serv && client->serv->connected) //send to server
 	{
 		PlayerMessage pm(LOCPLINT->playerID,message);

+ 146 - 115
client/GUIClasses.cpp

@@ -2631,23 +2631,23 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
 			const CArtifactInstance *movedArt = aw->arts->commonInfo->src.art;
 			if(movedArt)
 			{
-				aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this, movedArt->id);
+				aw->moveFromSlotToAltar(aw->arts->commonInfo->src.slotID, this, movedArt);
 			}
 			else if(const CArtifactInstance *art = getArtInstance())
 			{
 				movedArt = art;
 				aw->arts->commonInfo->src.AOH = aw->arts;
 				aw->arts->commonInfo->src.art = movedArt;
-				aw->arts->commonInfo->src.slotID = aw->hero->CArtifactSet::getArtPos(art);// vstd::findPos(aw->hero->artifacts, const_cast<CArtifact*>(movedArt));
+				aw->arts->commonInfo->src.slotID = aw->hero->getArtPos(art);
+				aw->arts->markPossibleSlots(movedArt);
 
-				aw->arts->commonInfo->dst.AOH = aw->arts;
+				//aw->arts->commonInfo->dst.AOH = aw->arts;
 				CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->artType->id].bitmap);
 
+				aw->arts->artifactsOnAltar.erase(movedArt);
 				id = -1;
 				subtitle = "";
-				aw->arts->artifactsOnAltar.erase(movedArt->id);
 				aw->deal->block(!aw->arts->artifactsOnAltar.size());
-				aw->arts->markPossibleSlots(movedArt);
 			}
 
 			aw->calcTotalExp();
@@ -3607,9 +3607,9 @@ void CAltarWindow::makeDeal()
 	}
 	else
 	{
-		BOOST_FOREACH(int artID, arts->artifactsOnAltar) //sacrifice each artifact on the list
+		BOOST_FOREACH(const CArtifactInstance *art, arts->artifactsOnAltar) //sacrifice each artifact on the list
 		{
-			LOCPLINT->cb->trade(market->o, mode, artID, -1, 1, hero);
+			LOCPLINT->cb->trade(market->o, mode, hero->getArtPos(art), -1, 1, hero);
 		}
 		arts->artifactsOnAltar.clear();
 
@@ -3649,10 +3649,10 @@ void CAltarWindow::SacrificeAll()
 	}
 	else
 	{
-		for(std::map<ui16, const CArtifact*>::const_iterator i = hero->artifWorn.begin(); i != hero->artifWorn.end(); i++)
+		for(std::map<ui16, ArtSlotInfo>::const_iterator i = hero->artifactsWorn.begin(); i != hero->artifactsWorn.end(); i++)
 		{
-			if(i->second->id != 145) //ignore locks from assembled artifacts
-				moveFromSlotToAltar(i->first, NULL, i->second->id);
+			if(i->second.artifact->artType->id != 145) //ignore locks from assembled artifacts
+				moveFromSlotToAltar(i->first, NULL, i->second.artifact);
 		}
 
 		SacrificeBackpack();
@@ -3757,11 +3757,11 @@ void CAltarWindow::calcTotalExp()
 	}
 	else
 	{
-		for(std::multiset<int>::const_iterator i = arts->artifactsOnAltar.begin(); i != arts->artifactsOnAltar.end(); i++)
+		BOOST_FOREACH(const CArtifactInstance *art, arts->artifactsOnAltar)
 		{
 			int dmp, valOfArt;
-			market->getOffer(*i, 0, dmp, valOfArt, mode);
-			val += valOfArt * arts->artifactsOnAltar.count(*i);
+			market->getOffer(art->artType->id, 0, dmp, valOfArt, mode);
+			val += valOfArt; //WAS val += valOfArt * arts->artifactsOnAltar.count(*i);
 		}
 	}
 	val *=(100+hero->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0f;
@@ -3801,18 +3801,20 @@ int CAltarWindow::firstFreeSlot()
 
 void CAltarWindow::SacrificeBackpack()
 {
-	std::multiset<int> toOmmit = arts->artifactsOnAltar;
+	std::multiset<const CArtifactInstance *> toOmmit = arts->artifactsOnAltar;
 
-	for (int i = 0; i < hero->artifacts.size(); i++)
+	for (int i = 0; i < hero->artifactsInBackpack.size(); i++)
 	{
-		if(vstd::contains(toOmmit, hero->artifacts[i]->id))
+
+		if(vstd::contains(toOmmit, hero->artifactsInBackpack[i].artifact))
 		{
-			toOmmit -= hero->artifacts[i]->id;
+			toOmmit -= hero->artifactsInBackpack[i].artifact;
 			continue;
 		}
 
-		putOnAltar(NULL, hero->artifacts[i]->id);
+		putOnAltar(NULL, hero->artifactsInBackpack[i].artifact);
 	}
+
 	arts->scrollBackpack(0);
 	calcTotalExp();
 }
@@ -3835,10 +3837,14 @@ void CAltarWindow::showAll(SDL_Surface * to)
 	}
 }
 
-bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, int artID)
+bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art)
 {
+	int artID = art->artType->id;
 	if(artID != 1 && artID < 7) //special art
+	{
+		tlog2 << "Cannot put special artifact on altar!\n";
 		return false;
+	}
 
 	if(!altarSlot)
 	{
@@ -3854,7 +3860,7 @@ bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, int artID)
 	int dmp, val;
 	market->getOffer(artID, 0, dmp, val, ARTIFACT_EXP);
 
-	arts->artifactsOnAltar.insert(artID);
+	arts->artifactsOnAltar.insert(art);
 	altarSlot->id = artID;
 	altarSlot->subtitle = boost::lexical_cast<std::string>(val);
 
@@ -3862,7 +3868,7 @@ bool CAltarWindow::putOnAltar(CTradeableItem* altarSlot, int artID)
 	return true;
 }
 
-void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, int artID)
+void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, const CArtifactInstance *art)
 {
 	if(arts->commonInfo->src.art)
 	{
@@ -3870,7 +3876,7 @@ void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, in
 		arts->commonInfo->dst.AOH = arts;
 	}
 
-	if(putOnAltar(altarSlot, artID))
+	if(putOnAltar(altarSlot, art))
 		LOCPLINT->cb->swapArtifacts(hero, slotID, hero, 65500);
 }
 
@@ -4521,7 +4527,7 @@ CRClickPopupInt::~CRClickPopupInt()
 }
 
 CArtPlace::CArtPlace(const CArtifactInstance* Art)
-	: marked(false), ourArt(Art)
+	: marked(false), ourArt(Art), picked(false)
 {
 }
 
@@ -4536,6 +4542,9 @@ void CArtPlace::activate()
 void CArtPlace::clickLeft(tribool down, bool previousState)
 {
 	//LRClickableAreaWTextComp::clickLeft(down);
+	bool inBackpack = slotID >= Arts::BACKPACK_START, 
+		srcInBackpack = ourOwner->commonInfo->src.slotID >= Arts::BACKPACK_START,
+		srcInSameHero = ourOwner->commonInfo->src.AOH == ourOwner;
 	
 	// If clicked on spellbook, open it only if no artifact is held at the moment.
 	if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH)
@@ -4557,7 +4566,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 			if(ourArt  //to prevent selecting empty slots (bugfix to what GrayFace reported)
 				&&  ourOwner->curHero->tempOwner == LOCPLINT->playerID)//can't take art from another player
 			{
-				if(ourArt->id == 3) //catapult cannot be highlighted
+				if(ourArt->artType->id == 3) //catapult cannot be highlighted
 				{
 					std::vector<SComponent *> catapult(1, new SComponent(SComponent::artifact, 3, 0));
 					LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped.
@@ -4570,34 +4579,39 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 		{
 			deselect();
 		}
-		else //perform artifact substitution
+		else //perform artifact transition
 		{
-			if (slotID >= 19) // Backpack destination.
+			if(inBackpack) // Backpack destination.
 			{
-				const CArtifact * const cur = ourOwner->commonInfo->src.art->artType;
-
-				switch(cur->id)
+				if(slotID == ourOwner->commonInfo->src.slotID + 1) //next slot (our is not visible, so visually same as "old" place) to the art -> make nothing, return artifact to slot
 				{
-				case 3:
-					//should not happen, catapult cannot be selected
-					assert(cur->id != 3);
-					break;
-				case 4: case 5: case 6: //war machines cannot go to backpack
-					LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % cur->Name()));
-					break;
-				default:
-					setMeAsDest();
-					amin(ourOwner->commonInfo->dst.slotID, ourOwner->curHero->artifactsInBackpack.size() + Arts::BACKPACK_START);
-// 
-// 					// Correction for backpack position when src lies before dest.
-// 					int correction = (ourOwner->commonInfo->srcAOH == ourOwner
-// 						&& ourOwner->commonInfo->srcSlotID >= 19
-// 						&& ourOwner->commonInfo->srcSlotID <= slotID);
-// 					ourOwner->commonInfo->destSlotID += correction;
-						
+					deselect();
+				}
+				else
+				{
+					const CArtifact * const cur = ourOwner->commonInfo->src.art->artType;
 
-					ourOwner->realizeCurrentTransaction();
-					break;
+					switch(cur->id)
+					{
+					case 3:
+						//should not happen, catapult cannot be selected
+						assert(cur->id != 3);
+						break;
+					case 4: case 5: case 6: //war machines cannot go to backpack
+						LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % cur->Name()));
+						break;
+					default:
+						setMeAsDest();
+						amin(ourOwner->commonInfo->dst.slotID, ourOwner->curHero->artifactsInBackpack.size() + Arts::BACKPACK_START);
+						if(!ourArt && srcInBackpack && srcInSameHero) //cannot move from backpack to AFTER backpack
+							ourOwner->commonInfo->dst.slotID--;		  //combined with amin above it will guarantee that dest is at most the last artifact
+						
+						if(srcInSameHero && ourOwner->commonInfo->dst.slotID == ourOwner->commonInfo->src.slotID) //we came to src == dst
+							deselect();
+						else
+							ourOwner->realizeCurrentTransaction();
+						break;
+					}
 				}
 			}
 			//check if swap is possible
@@ -4676,19 +4690,15 @@ void CArtPlace::select ()
 	if (locked())
 		return;
 
-	int backpackCorrection = -(slotID - 19 < ourOwner->backpackPos);
+	picked = true;
+	//int backpackCorrection = -(slotID - 19 < ourOwner->backpackPos);
 
 	CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->artType->id].bitmap);
-
 	ourOwner->commonInfo->src.setTo(this, false);
-
-	// Temporarily remove artifact from hero.
 	ourOwner->markPossibleSlots(ourArt);
-// 
-// 	if (slotID >= 19)
-// 		ourOwner->scrollBackpack(backpackCorrection);
-// 	else
-		ourOwner->eraseSlotData(this, slotID);
+
+	if(slotID >= Arts::BACKPACK_START)
+		ourOwner->scrollBackpack(0); //will update slots
 
 	// Update the hero bonuses.
 	ourOwner->updateParentWindow();
@@ -4700,10 +4710,13 @@ void CArtPlace::select ()
  */
 void CArtPlace::deselect ()
 {
+	picked = false;
 	CCS->curh->dragAndDropCursor(NULL);
 	ourOwner->unmarkSlots();
-
 	ourOwner->commonInfo->src.clear();
+	if(slotID >= Arts::BACKPACK_START)
+		ourOwner->scrollBackpack(0); //will update slots
+
 
 	ourOwner->updateParentWindow();
 	ourOwner->safeRedraw();
@@ -4719,7 +4732,7 @@ void CArtPlace::deactivate()
 
 void CArtPlace::showAll(SDL_Surface *to)
 {
-	if (ourArt)
+	if (ourArt && !picked)
 		blitAt(graphics->artDefs->ourImages[ourArt->artType->id].bitmap, pos.x, pos.y, to);
 
 	if(marked && active)
@@ -4768,6 +4781,24 @@ void CArtPlace::setMeAsDest(bool backpackAsVoid /*= true*/)
 	ourOwner->commonInfo->dst.setTo(this, backpackAsVoid);
 }
 
+void CArtPlace::setArtifact(const CArtifactInstance *art)
+{
+	ourArt = art;
+	if(!art)
+	{
+		text = std::string();
+		hoverText = CGI->generaltexth->allTexts[507];
+	}
+	else
+	{
+		text = ourArt->artType->Description();
+		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());
+	}
+}
+
 void HoverableArea::hover (bool on)
 {
 	if (on)
@@ -4978,54 +5009,50 @@ void CArtifactsOfHero::dispose()
 
 void CArtifactsOfHero::scrollBackpack(int dir)
 {
+	int artsInBackpack = curHero->artifactsInBackpack.size();
 	backpackPos += dir;
-	if (curHero->artifactsInBackpack.size() > 0) 
-	{
-		if (backpackPos < 0) // No guarantee of modulus behavior with negative operands.
-		{ 
-			do 
-			{
-				backpackPos += curHero->artifactsInBackpack.size();
-			} while (backpackPos < 0);
-		} 
-		else 
-		{
-			backpackPos %= curHero->artifactsInBackpack.size();
-		}
-	}
+	if(backpackPos < 0)// No guarantee of modulus behavior with negative operands -> we keep it positive
+		backpackPos += artsInBackpack;
 
-	std::multiset<int> toOmmit = artifactsOnAltar;
-	int ommited = 0;
+	if(artsInBackpack)
+		backpackPos %= artsInBackpack;
+
+	std::multiset<const CArtifactInstance *> toOmit = artifactsOnAltar;
+	if(commonInfo->src.art) //if we picked an art from backapck, its slot has to be omitted
+		toOmit.insert(commonInfo->src.art);
+	
+	int omitedSoFar = 0;
 
 	//set new data
 	size_t s = 0;
-	for( ; s < curHero->artifactsInBackpack.size(); ++s) 
+	for( ; s < artsInBackpack; ++s) 
 	{
 
-		if (s < curHero->artifactsInBackpack.size())
+		if (s < artsInBackpack)
 		{
-			int slotID = 19 + (s + backpackPos)%curHero->artifactsInBackpack.size();
+			int slotID = 19 + (s + backpackPos)%artsInBackpack;
 			const CArtifactInstance *art = curHero->getArt(slotID);
 			assert(art);
-			if(!vstd::contains(toOmmit, art->artType->id))
-			{
-				if(s - ommited < 5)
-					setSlotData(backpack[s-ommited], slotID);
+			if(!vstd::contains(toOmit, art))
+			{ 
+				if(s - omitedSoFar < 5)
+					setSlotData(backpack[s-omitedSoFar], slotID);
 			}
 			else
 			{
-				toOmmit -= art->artType->id;
-				ommited ++;
+				toOmit -= art;
+				omitedSoFar++;
 				continue;
 			}
 		}
 	}
-	for( ; s - ommited < 5; s++)
-		eraseSlotData(backpack[s-ommited], 19 + s);
+	for( ; s - omitedSoFar < 5; s++)
+		eraseSlotData(backpack[s-omitedSoFar], 19 + s);
 
 	//blocking scrolling if there is not enough artifacts to scroll
-	leftArtRoll->block(curHero->artifactsInBackpack.size() - ommited <= backpack.size());
-	rightArtRoll->block(curHero->artifactsInBackpack.size() - ommited <= backpack.size());
+	bool scrollingPossible = artsInBackpack - omitedSoFar > backpack.size();
+	leftArtRoll->block(!scrollingPossible);
+	rightArtRoll->block(!scrollingPossible);
 
 	safeRedraw();
 
@@ -5050,9 +5077,17 @@ void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
  */
 void CArtifactsOfHero::unmarkSlots(bool withRedraw /*= true*/)
 {
-	BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
-		BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
+	if(commonInfo)
+	{
+		BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
+			BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
+			place->marked = false;
+	}
+	else
+	{
+		BOOST_FOREACH(CArtPlace *place, artWorn)
 			place->marked = false;
+	}
 
 	if(withRedraw)
 		safeRedraw();
@@ -5063,32 +5098,24 @@ void CArtifactsOfHero::unmarkSlots(bool withRedraw /*= true*/)
  */
 void CArtifactsOfHero::setSlotData(CArtPlace* artPlace, int slotID)
 {
-	artPlace->slotID = slotID;
-	artPlace->ourArt = curHero->CArtifactSet::getArt(slotID);
-
-	if (artPlace->ourArt) 
+	if(!artPlace && slotID >= Arts::BACKPACK_START) //spurious call from artifactMoved in attempt to update hidden backpack slot
 	{
-		artPlace->text = artPlace->ourArt->artType->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]) % artPlace->ourArt->artType->Name());
-	} 
-	else 
-	{
-		eraseSlotData(artPlace, slotID);
+		return;
 	}
-}
+
+	artPlace->picked = false;
+	artPlace->slotID = slotID;
+	artPlace->setArtifact(curHero->getArt(slotID));
+} 
 
 /**
  * Makes given artifact slot appear as empty with a certain slot ID.
  */
 void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, int slotID)
 {
+	artPlace->picked = false;
 	artPlace->slotID = slotID;
-	artPlace->ourArt = NULL;
-	artPlace->text = std::string();
-	artPlace->hoverText = CGI->generaltexth->allTexts[507];
+	artPlace->setArtifact(NULL);
 }
 
 CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart /*= false*/)
@@ -5199,13 +5226,11 @@ void CArtifactsOfHero::realizeCurrentTransaction()
 
 void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
 {
-	BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants) //update affected slots
-	{
-		if(src.hero == aoh->curHero)
-			setSlotData(aoh->getArtPlace(src.slot), src.slot);
-		if(dst.hero == aoh->curHero)
-			setSlotData(aoh->getArtPlace(dst.slot), dst.slot);
-	}
+	if(src.hero == curHero)
+		setSlotData(getArtPlace(src.slot), src.slot);
+	if(dst.hero == curHero)
+		setSlotData(getArtPlace(dst.slot), dst.slot);
+
 	updateParentWindow();
 
 	if(commonInfo->src == src) //artifact was taken from us
@@ -5247,6 +5272,10 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
 	{
 		tlog1 << "Unexpected artifact movement...\n";
 	}
+
+	if( src.hero == curHero && src.slot >= Arts::BACKPACK_START
+	 || dst.hero == curHero && dst.slot >= Arts::BACKPACK_START)
+		scrollBackpack(0); //update backpack slots
 }
 
 CArtPlace * CArtifactsOfHero::getArtPlace(int slot)
@@ -5466,7 +5495,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
 	pos.w = screen->w;
 	pos.h = screen->h;
 
-
+	
 	artifs[0] = new CArtifactsOfHero(Point(pos.x + -334, pos.y + 150));
 	artifs[0]->commonInfo = new CArtifactsOfHero::SCommonPart;
 	artifs[0]->commonInfo->participants.insert(artifs[0]);
@@ -5476,6 +5505,8 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
 	artifs[1]->commonInfo->participants.insert(artifs[1]);
 	artifs[1]->setHero(heroInst[1]);
 
+	artSets.push_back(artifs[0]);
+	artSets.push_back(artifs[1]);
 
 	//primary skills
 	for(int g=0; g<4; ++g)

+ 6 - 4
client/GUIClasses.h

@@ -700,7 +700,7 @@ public:
 	void SacrificeBackpack();
 
 	void putOnAltar(int backpackIndex);
-	bool putOnAltar(CTradeableItem* altarSlot, int artID);
+	bool putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art);
 	void makeDeal();
 	void showAll(SDL_Surface * to);
 
@@ -719,7 +719,7 @@ public:
 
 	void artifactPicked();
 	int firstFreeSlot();
-	void moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, int artID);
+	void moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, const CArtifactInstance *art);
 };
 
 class CSystemOptionsWindow : public CIntObject
@@ -922,6 +922,7 @@ class CArtPlace: public LRClickableAreaWTextComp
 public:
 	int slotID; //0   	head	1 	shoulders		2 	neck		3 	right hand		4 	left hand		5 	torso		6 	right ring		7 	left ring		8 	feet		9 	misc. slot 1		10 	misc. slot 2		11 	misc. slot 3		12 	misc. slot 4		13 	ballista (war machine 1)		14 	ammo cart (war machine 2)		15 	first aid tent (war machine 3)		16 	catapult		17 	spell book		18 	misc. slot 5		19+ 	backpack slots
 
+	bool picked;
 	bool marked;
 	CArtifactsOfHero * ourOwner;
 	const CArtifactInstance * ourArt;
@@ -938,6 +939,7 @@ public:
 	bool locked () const;
 
 	void setMeAsDest(bool backpackAsVoid = true);
+	void setArtifact(const CArtifactInstance *art);
 
 	~CArtPlace(); //d-tor
 };
@@ -974,7 +976,7 @@ public:
 
 	AdventureMapButton * leftArtRoll, * rightArtRoll;
 	bool allowedAssembling;
-	std::multiset<int> artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be ommited in backpack slots
+	std::multiset<const CArtifactInstance*> artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be ommited in backpack slots
 
 	void realizeCurrentTransaction(); //calls callback with parameters stored in commonInfo
 	void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
@@ -1011,7 +1013,7 @@ public:
 	~CGarrisonWindow(); //d-tor
 };
 
-class CExchangeWindow : public CWindowWithGarrison
+class CExchangeWindow : public CWindowWithGarrison, public CWindowWithArtifacts
 {
 	CStatusBar * ourBar; //internal statusbar
 

+ 5 - 1
lib/HeroBonus.cpp

@@ -10,6 +10,7 @@
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/bind.hpp>
 #include "CHeroHandler.h"
+#include "CGeneralTextHandler.h"
 
 #define FOREACH_CONST_PARENT(pname) 	TCNodes parents; getParents(parents); BOOST_FOREACH(const CBonusSystemNode *pname, parents)
 #define FOREACH_PARENT(pname) 	TNodes parents; getParents(parents); BOOST_FOREACH(CBonusSystemNode *pname, parents)
@@ -171,7 +172,7 @@ const Bonus * CBonusSystemNode::getBonus( const CSelector &selector ) const
 
 void CBonusSystemNode::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
 {
-	getModifiersWDescr(out, Selector::typeSybtype(type, subtype));
+	getModifiersWDescr(out, subtype != -1 ? Selector::typeSybtype(type, subtype) : Selector::type(type));
 }
 
 void CBonusSystemNode::getModifiersWDescr(TModDescr &out, const CSelector &selector) const
@@ -491,6 +492,9 @@ std::string Bonus::Description() const
 	case CREATURE_ABILITY:
 		str << VLC->creh->creatures[id]->namePl;
 		break;
+	case SECONDARY_SKILL:
+		str << VLC->generaltexth->skillName[id] << " secondary skill";
+		break;
 	}
 
 	return str.str();

+ 3 - 1
lib/NetPacksLib.cpp

@@ -713,8 +713,10 @@ DLL_EXPORT void EraseArtifact::applyGs( CGameState *gs )
 
 DLL_EXPORT void MoveArtifact::applyGs( CGameState *gs )
 {
-	assert(!dst.getArt());
 	CArtifactInstance *a = src.getArt();
+	if(dst.slot < Arts::BACKPACK_START)
+		assert(!dst.getArt());
+
 	a->removeFrom(src.hero, src.slot);
 	a->putAt(dst.hero, dst.slot);
 }

+ 8 - 7
server/CGameHandler.cpp

@@ -2499,9 +2499,9 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
 	if(dst.slot >= Arts::BACKPACK_START)
 		amin(dst.slot, Arts::BACKPACK_START + dst.hero->artifactsInBackpack.size());
 
- 	// Correction for destination from removing source artifact in backpack.
- 	if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot)
- 		dst.slot--;
+//  	// Correction for destination from removing source artifact in backpack.
+//  	if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot)
+//  		dst.slot--;
 
 	if (src.slot == dst.slot)
 		COMPLAIN_RET("Won't move artifact: Dest same as source!");
@@ -3089,9 +3089,10 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 
 			if( !CStack::isMeleeAttackPossible(curStack, stackAtEnd) )
 			{
-				tlog3 << "Attack cannot be performed!";
+				complain("Attack cannot be performed!");
 				sendAndApply(&EndAction());
 				ok = false;
+				break;
 			}
 
 			//attack
@@ -4979,12 +4980,12 @@ void CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
 
 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
+	CArtifactInstance *a = new CArtifactInstance();
+	a->artType = artType; //*NOT* via settype -> all bonus-related stuff must be done by NewArtifact apply
 	
 	NewArtifact na;
 	na.art = a;
-	sendAndApply(&na); // -> updates a!!!
+	sendAndApply(&na); // -> updates a!!!, will create a on other machines
 
 	giveHeroArtifact(h, a, pos);
 }