Browse Source

* hero placed in the town starts as visiting hero, not garrisoned
* if hero doesn't have a spell book, he can buy one in a mage guild
* improvements in closing
* fixed crash on picking artifact
* added event message when picking artifact
* fixed problems with disappearing pikemen
* InfoWindow will be properly centered
* hero portraits again visible in PreGame
* fixed problems with handling Pandora's Box
* support for Campfires
* minor changes

Michał W. Urbańczyk 17 years ago
parent
commit
6613955463

+ 4 - 4
AdventureMapButton.cpp

@@ -16,10 +16,10 @@ AdventureMapButton::AdventureMapButton ()
 	state=0;
 	actOnDown = false;
 }
-AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ,  std::vector<std::string> * add, bool playerColoredButton)
-{
-	init(Callback, Name, HelpBox, playerColoredButton, defName, add, x, y, activ);
-}
+//AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ,  std::vector<std::string> * add, bool playerColoredButton)
+//{
+//	init(Callback, Name, HelpBox, playerColoredButton, defName, add, x, y, activ);
+//}
 AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, CFunctionList<void()> Callback, int x, int y, std::string defName, bool activ,  std::vector<std::string> * add, bool playerColoredButton )
 {
 	init(Callback, Name, HelpBox, playerColoredButton, defName, add, x, y, activ);

+ 1 - 1
AdventureMapButton.h

@@ -22,7 +22,7 @@ public:
 
 	AdventureMapButton(); //c-tor
 	AdventureMapButton( std::string Name, std::string HelpBox, CFunctionList<void()> Callback, int x, int y, std::string defName, bool activ=false,  std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
-	AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ=false,  std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
+	//AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ=false,  std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
 
 	void init( CFunctionList<void()> Callback, std::string Name, std::string HelpBox, bool playerColoredButton, std::string defName, std::vector<std::string> * add, int x, int y, bool activ );
 };

+ 1 - 1
CAdvmapInterface.cpp

@@ -980,7 +980,7 @@ void CAdvMapInt::deactivate()
 {
 	hide();
 }
-void CAdvMapInt::show()
+void CAdvMapInt::show(SDL_Surface *to)
 {
 	blitAt(bg,0,0);
 

+ 2 - 2
CAdvmapInterface.h

@@ -98,7 +98,7 @@ public:
 	CDefHandler * getAnim(int mode);
 };
 /*****************************/
-class CAdvMapInt : public IActivable //adventure map interface
+class CAdvMapInt : public CMainInterface //adventure map interface
 {
 public:
 	CAdvMapInt(int Player);
@@ -166,7 +166,7 @@ public:
 	void activate();
 	void deactivate();
 
-	void show(); //shows and activates adv. map interface
+	void show(SDL_Surface * to=NULL); //shows and activates adv. map interface
 	void hide(); //deactivates advmap interface
 	void update(); //redraws terrain
 

+ 1 - 1
CBattleInterface.h

@@ -69,7 +69,7 @@ public:
 	void scrollDown(unsigned int by = 1); //scrolls console up by 'by' positions
 };
 
-class CBattleInterface : public IActivable, public IShowable
+class CBattleInterface : public CMainInterface
 {
 private:
 	SDL_Surface * background, * menu, * amountBasic, * amountNormal;

+ 6 - 0
CCallback.cpp

@@ -512,4 +512,10 @@ void CCallback::swapGarrisonHero( const CGTownInstance *town )
 {
 	if(town->tempOwner != player) return;
 	*cl->serv << ui16(508) << si32(town->id);
+}
+
+void CCallback::buyArtifact(const CGHeroInstance *hero, int aid)
+{
+	if(hero->tempOwner != player) return;
+	*cl->serv << ui16(510) << hero->id << ui32(aid);
 }

+ 2 - 0
CCallback.h

@@ -40,6 +40,7 @@ public:
 	virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made
 	virtual void endTurn()=0;
 	virtual void swapGarrisonHero(const CGTownInstance *town)=0;
+	virtual void buyArtifact(const CGHeroInstance *hero, int aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith)
 
 //get info
 	virtual bool verifyPath(CPath * path, bool blockSea)=0;
@@ -113,6 +114,7 @@ public:
 	bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1);
 	void endTurn();
 	void swapGarrisonHero(const CGTownInstance *town);
+	void buyArtifact(const CGHeroInstance *hero, int aid);
 
 //get info
 	bool verifyPath(CPath * path, bool blockSea);

+ 42 - 13
CCastleInterface.cpp

@@ -233,27 +233,33 @@ void CHeroGSlot::clickRight (boost::logic::tribool down)
 }
 void CHeroGSlot::clickLeft(boost::logic::tribool down)
 {
+	CHeroGSlot *other = upg  ?  &owner->hslotup :  &owner->hslotdown;
 	if(!down)
 	{
-		CHeroGSlot *other = upg  ?  &owner->hslotup :  &owner->hslotdown;
 		if(hero && highlight)
 		{
 			highlight = false;
 			LOCPLINT->openHeroWindow(hero);
 			LOCPLINT->adventureInt->heroWindow->quitButton->callback += boost::bind(&CCastleInterface::showAll,owner,screen,true);
 		}
+		else if(other->hero && other->highlight)
+		{
+			other->highlight = highlight = false;
+			LOCPLINT->cb->swapGarrisonHero(owner->town);
+		}
 		else if(hero)
 		{
 			highlight = true;
+			owner->garr->highlighted = NULL;
 			owner->showAll();
 		}
-		else if(other->hero, other->highlight)
-		{
-			other->highlight = highlight = false;
-			LOCPLINT->cb->swapGarrisonHero(owner->town);
-		}
 		hover(false);hover(true); //refresh statusbar
 	}
+	if(indeterminate(down) && !isItIn(&other->pos,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+	{
+		other->highlight = highlight = false;
+		show();
+	}
 }
 void CHeroGSlot::activate()
 {
@@ -374,7 +380,6 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate)
 	{
 		LOCPLINT->objsToBlit.push_back(this);
 		activate();
-		showAll();
 	}
 
 	std::string defname;
@@ -473,8 +478,28 @@ void CCastleInterface::buildingClicked(int building)
 		{
 		case 0: case 1: case 2: case 3: case 4:
 			{
-				deactivate();
-				(new CMageGuildScreen(this))->activate();
+				if(town->visitingHero && !vstd::contains(town->visitingHero->artifWorn,ui16(17))) //visiting hero doesn't have spellboks
+				{
+					if(LOCPLINT->cb->getResourceAmount(6) < 500) //not enough gold to buy spellbook
+					{
+						LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[213],std::vector<SComponent*>());
+					}
+					else
+					{
+						CFunctionList<void()> fl = boost::bind(&CCallback::buyArtifact,LOCPLINT->cb,town->visitingHero,0);
+						fl += boost::bind(&CCastleInterface::enterMageGuild,this);
+						std::vector<SComponent*> vvv(1,new SComponent(SComponent::artifact,0,0));
+						LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[214],vvv,
+							fl,boost::bind(&CCastleInterface::activate,this),
+							true,true);
+					}
+				}
+				else
+				{ 
+					deactivate();
+					enterMageGuild();
+
+				}
 				break;
 			}
 		case 7: case 8: case 9:
@@ -629,6 +654,8 @@ void CCastleInterface::activate()
 		subInt->activate();
 		return;
 	}
+	else
+		subInt = NULL;
 	showing = true;
 	townlist->activate();
 	garr->activate();
@@ -640,6 +667,7 @@ void CCastleInterface::activate()
 		buildings[i]->activate();
 	hslotdown.activate();
 	hslotup.activate();
+	showAll(0,true);
 }
 void CCastleInterface::deactivate()
 {
@@ -807,6 +835,11 @@ CRecrutationWindow * CCastleInterface::showRecruitmentWindow( int building )
 	rw->activate();	
 	return rw;
 }
+
+void CCastleInterface::enterMageGuild()
+{
+	(new CMageGuildScreen(this))->activate();
+}
 void CHallInterface::CBuildingBox::hover(bool on)
 {
 	Hoverable::hover(on);
@@ -995,7 +1028,6 @@ void CHallInterface::close()
 	deactivate();
 	delete this;
 	LOCPLINT->castleInt->activate();
-	LOCPLINT->castleInt->showAll();
 }
 void CHallInterface::show(SDL_Surface * to)
 {
@@ -1055,7 +1087,6 @@ void CHallInterface::CBuildWindow::Buy()
 	LOCPLINT->cb->buildBuilding(LOCPLINT->castleInt->town,bid);
 	delete this;
 	delete LOCPLINT->castleInt->subInt;
-	LOCPLINT->castleInt->showAll();
 }
 void CHallInterface::CBuildWindow::close()
 {
@@ -1252,7 +1283,6 @@ void CFortScreen::close()
 	deactivate();
 	delete this;
 	LOCPLINT->castleInt->activate();
-	LOCPLINT->castleInt->showAll();
 }
 CFortScreen::CFortScreen( CCastleInterface * owner )
 {
@@ -1406,7 +1436,6 @@ void CMageGuildScreen::close()
 	delete this;
 	LOCPLINT->castleInt->subInt = NULL;
 	LOCPLINT->castleInt->activate();
-	LOCPLINT->castleInt->showAll();
 }
 void CMageGuildScreen::show(SDL_Surface * to)
 {

+ 3 - 4
CCastleInterface.h

@@ -47,7 +47,7 @@ public:
 	~CHeroGSlot();
 };
 
-class CCastleInterface : public IShowable, public IActivable
+class CCastleInterface : public CMainInterface
 {
 public:
 	bool showing;
@@ -56,7 +56,6 @@ public:
 	SDL_Surface * cityBg;
 	const CGTownInstance * town;
 	CStatusBar * statusbar;
-	IShowActivable * subInt;
 	unsigned char animval, count;
 
 	CDefHandler *hall,*fort, *flag;
@@ -76,7 +75,7 @@ public:
 	void show(SDL_Surface * to=NULL);
 	void showAll(SDL_Surface * to=NULL, bool forceTotalRedraw = false);
 	void buildingClicked(int building);
-
+	void enterMageGuild();
 	CRecrutationWindow * showRecruitmentWindow(int building);
 	void enterHall();
 	void close();
@@ -145,7 +144,7 @@ public:
 	void deactivate();
 };
 
-class CFortScreen : public IShowActivable
+class CFortScreen : public CMainInterface
 {
 	class RecArea : public ClickableL
 	{

+ 1 - 0
CGameInterface.h

@@ -46,6 +46,7 @@ public:
 
 	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
+	virtual void heroArtifactSetChanged(const CGHeroInstance*hero){};
 	virtual void heroCreated(const CGHeroInstance*){};
 	virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
 	virtual void heroInGarrisonChange(const CGTownInstance *town){};

+ 25 - 13
CGameState.cpp

@@ -417,7 +417,18 @@ void CGameState::applyNL(IPack * pack)
 		{
 			SetGarrisons * n = static_cast<SetGarrisons*>(pack);
 			for(std::map<ui32,CCreatureSet>::iterator i = n->garrs.begin(); i!=n->garrs.end(); i++)
-				static_cast<CArmedInstance*>(map->objects[i->first])->army = i->second;
+			{
+				CArmedInstance *ai = static_cast<CArmedInstance*>(map->objects[i->first]);
+				ai->army = i->second;
+				if(ai->ID==98 && (static_cast<CGTownInstance*>(ai))->garrisonHero) //if there is a hero in garrison then we must update also his army
+					const_cast<CGHeroInstance*>((static_cast<CGTownInstance*>(ai))->garrisonHero)->army = i->second;
+				else if(ai->ID==34)
+				{
+					CGHeroInstance *h =  static_cast<CGHeroInstance*>(ai);
+					if(h->visitedTown && h->inTownGarrison)
+						h->visitedTown->army = i->second;
+				}
+			}
 			break;
 		}
 	case 503:
@@ -1101,24 +1112,25 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			for(int m=0; m<k->second.towns.size();m++)
 			{
 				int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
-				if(vistile == k->second.heroes[l]->pos)
+				if(vistile == k->second.heroes[l]->pos || k->second.heroes[l]->pos==k->second.towns[m]->pos)
 				{
 					k->second.towns[m]->visitingHero = k->second.heroes[l];
 					k->second.heroes[l]->visitedTown = k->second.towns[m];
 					k->second.heroes[l]->inTownGarrison = false;
-					goto mainplheloop;
-				}
-				else if(k->second.heroes[l]->pos == k->second.towns[m]->pos)
-				{
-					k->second.towns[m]->garrisonHero = k->second.heroes[l];
-					k->second.towns[m]->army = k->second.heroes[l]->army;
-					k->second.heroes[l]->visitedTown = k->second.towns[m];
-					k->second.heroes[l]->inTownGarrison = true;
-					k->second.heroes[l]->pos.x -= 1;
-					goto mainplheloop;
+					if(k->second.heroes[l]->pos==k->second.towns[m]->pos)
+						k->second.heroes[l]->pos.x -= 1;
+					break;
 				}
+				//else if(k->second.heroes[l]->pos == k->second.towns[m]->pos)
+				//{
+				//	k->second.towns[m]->garrisonHero = k->second.heroes[l];
+				//	k->second.towns[m]->army = k->second.heroes[l]->army;
+				//	k->second.heroes[l]->visitedTown = k->second.towns[m];
+				//	k->second.heroes[l]->inTownGarrison = true;
+				//	k->second.heroes[l]->pos.x -= 1;
+				//	goto mainplheloop;
+				//}
 			}
-mainplheloop:;
 		}
 	}
 }

+ 2 - 1
CHeroWindow.cpp

@@ -508,6 +508,7 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
 
 void CHeroWindow::quit()
 {
+	LOCPLINT->curint->subInt = NULL;
 	LOCPLINT->objsToBlit -= this;
 
 	deactivate();
@@ -535,7 +536,7 @@ void CHeroWindow::quit()
 
 void CHeroWindow::activate()
 {
-	//LOCPLINT->curint = this;
+	LOCPLINT->curint->subInt = this;
 	quitButton->activate();
 	dismissButton->activate();
 	questlogButton->activate();

+ 21 - 0
CLua.cpp

@@ -588,6 +588,26 @@ void CPickable::onHeroVisit(int objid, int heroID)
 	case 5: //artifact
 		{
 			cb->giveHeroArtifact(os->subID,heroID,-1); //TODO: na pozycje
+			InfoWindow iw;
+			iw.player = cb->getHeroOwner(heroID);
+			iw.components.push_back(Component(4,os->subID,0,0));
+			iw.text << std::pair<ui8,ui32>(12,os->subID);
+			cb->showInfoDialog(&iw);
+			break;
+		}
+	case 12: //campfire
+		{
+			int val = (rand()%3) + 4, //4 - 6
+				res = rand()%6, 
+				owner = cb->getHeroOwner(heroID);
+			cb->giveResource(owner,res,val); //non-gold resource
+			cb->giveResource(owner,6,val*100);//gold
+			InfoWindow iw;
+			iw.player = owner;
+			iw.components.push_back(Component(2,6,val*100,0));
+			iw.components.push_back(Component(2,res,val,0));
+			iw.text << std::pair<ui8,ui32>(11,23);
+			cb->showInfoDialog(&iw);
 			break;
 		}
 	case 79: //resource
@@ -691,6 +711,7 @@ std::vector<int> CPickable::yourObjects() //returns IDs of objects which are han
 	std::vector<int> ret;
 	ret.push_back(79); //resource
 	ret.push_back(5); //artifact
+	ret.push_back(12); //resource
 	ret.push_back(101); //treasure chest / commander stone
 	return ret;
 }

+ 2 - 1
CMT.cpp

@@ -171,7 +171,8 @@ int main(int argc, _TCHAR* argv[])
 			SDL_WaitEvent(&ev);
 			if(ev.type==SDL_QUIT) 
 			{
-				t.interrupt();
+				cl.close();
+				SDL_Delay(750);
 				exit(0);
 			}
 			eventsM.lock();

+ 1 - 1
CMessage.cpp

@@ -426,7 +426,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int
 	ret->bitmap = drawBox1(txts.first+70,txts.second+70,0);
 	ret->pos.h=ret->bitmap->h;
 	ret->pos.w=ret->bitmap->w;
-	ret->pos.x=300-(ret->pos.w/2);
+	ret->pos.x=400-(ret->pos.w/2);
 	ret->pos.y=300-(ret->pos.h/2);
 	int curh = 30; //gorny margines
 	blitTextOnSur(txtg,curh,ret->bitmap);

+ 33 - 36
CPlayerInterface.cpp

@@ -12,6 +12,7 @@
 #include "hch/CLodHandler.h"
 #include "CPathfinder.h"
 #include <sstream>
+#include "hch/CArtHandler.h"
 #include "hch/CAbilityHandler.h"
 #include "hch/CHeroHandler.h"
 #include "hch/CTownHandler.h"
@@ -172,14 +173,10 @@ void CGarrisonSlot::clickLeft(tribool down)
 						(creature->idNumber,1,count,NULL,0, boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),NULL) )
 						->activate();
 				}
-				if(LOCPLINT->curint == LOCPLINT->castleInt   &&   dynamic_cast<CHeroWindow*>(LOCPLINT->castleInt->subInt))
-				{
-					LOCPLINT->castleInt->subInt->deactivate();
-				}
+				if(LOCPLINT->curint->subInt)
+					LOCPLINT->curint->subInt->deactivate();
 				else
-				{
 					LOCPLINT->curint->deactivate();
-				}
 				owner->highlighted = NULL;
 				show();
 				refr = true;
@@ -263,8 +260,8 @@ void CGarrisonSlot::show()
 		printTo(buf,pos.x+56,pos.y+62,GEOR16,zwykly);
 		if(owner->highlighted==this)
 			blitAt(graphics->bigImgs[-1],pos);
-		if(owner->update)
-			updateRect(&pos,screen);
+		//if(owner->update)
+		//	updateRect(&pos,screen);
 		delete [] buf;
 	}
 	else
@@ -273,8 +270,8 @@ void CGarrisonSlot::show()
 		SDL_BlitSurface(owner->sur,&jakis1,screen,&jakis2);
 		if(owner->splitting)
 			blitAt(graphics->bigImgs[-1],pos);
-		if(owner->update)
-			SDL_UpdateRect(screen,pos.x,pos.y,pos.w,pos.h);
+		//if(owner->update)
+		//	SDL_UpdateRect(screen,pos.x,pos.y,pos.w,pos.h);
 	}
 }
 CGarrisonInt::~CGarrisonInt()
@@ -588,6 +585,10 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 	std::ostringstream oss;
 	switch (Type)
 	{
+	case artifact:
+		description = CGI->arth->artifacts[Subtype].description;
+		subtitle = CGI->arth->artifacts[Subtype].name;
+		break;
 	case primskill:
 		description = CGI->generaltexth->arraytxt[2+Subtype];
 		oss << ((Val>0)?("+"):("-")) << Val << " " << CGI->heroh->pskillsn[Subtype];
@@ -645,6 +646,9 @@ SDL_Surface * SComponent::getImg()
 {
 	switch (type)
 	{
+	case artifact:
+		return graphics->artDefs->ourImages[subtype].bitmap;
+		break;
 	case primskill:
 		return graphics->pskillsb->ourImages[subtype].bitmap;
 		break;
@@ -1942,6 +1946,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
 
 void CPlayerInterface::receivedResource(int type, int val)
 {
+	boost::unique_lock<boost::mutex> un(*pim);
 	adventureInt->resdatabar.draw();
 }
 
@@ -2017,13 +2022,13 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 			SDL_FreeSurface(graphics->heroWins[hh->subID]);
 			graphics->heroWins[hh->subID] = infoWin(hh);
 		}
-		CHeroWindow * hw = dynamic_cast<CHeroWindow *>(curint);
+		CHeroWindow * hw = dynamic_cast<CHeroWindow *>(curint->subInt);
 		if(hw)
 		{
 			hw->garInt->recreateSlots();
 			hw->garInt->show();
 		}
-		else if(castleInt) //opened town window - redraw town garrsion slots (change is within hero garr)
+		if(castleInt) //opened town window - redraw town garrsion slots (change is within hero garr)
 		{
 			castleInt->garr->highlighted = NULL;
 			castleInt->garr->recreateSlots();
@@ -2128,9 +2133,9 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
 void CPlayerInterface::battleEnd(BattleResult *br)
 {
 	boost::unique_lock<boost::mutex> un(*pim);
-	dynamic_cast<CBattleInterface*>(curint)->deactivate();
-	LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),dynamic_cast<IShowable*>(curint)));
-	delete dynamic_cast<CBattleInterface*>(curint);
+	curint->deactivate();
+	objsToBlit -= curint;
+	delete curint;
 	curint = adventureInt;
 	adventureInt->activate();
 }
@@ -2257,6 +2262,16 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 	adventureInt->heroWindow->quitButton->callback += boost::bind(&CHeroWindow::quit,adventureInt->heroWindow);
 	adventureInt->heroWindow->activate();
 }
+
+void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
+{
+	boost::unique_lock<boost::mutex> un(*pim);
+	if(curint->subInt == adventureInt->heroWindow)
+	{
+		//TODO: update hero window properly
+
+	}
+}
 CStatusBar::CStatusBar(int x, int y, std::string name, int maxw)
 {
 	bg=BitmapHandler::loadBitmap(name);
@@ -2827,9 +2842,6 @@ void CRecrutationWindow::close()
 	deactivate();
 	delete this;
 	LOCPLINT->curint->activate();
-	CCastleInterface *pom;
-	if(pom=dynamic_cast<CCastleInterface*>(LOCPLINT->curint))
-		pom->showAll();
 }
 void CRecrutationWindow::Max()
 {
@@ -3055,9 +3067,6 @@ void CSplitWindow::close()
 	deactivate();
 	delete this;
 	LOCPLINT->curint->activate();
-
-	CCastleInterface *c = dynamic_cast<CCastleInterface*>(LOCPLINT->curint);
-	if(c) c->showAll();
 }
 void CSplitWindow::sliderMoved(int to)
 {
@@ -3210,12 +3219,6 @@ CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount, StackState
 				CFunctionList<void()> fs[2];
 				fs[0] += Upg;
 				fs[0] += boost::bind(&CCreInfoWindow::close,this);
-
-				CCastleInterface *pom;
-				if(pom=dynamic_cast<CCastleInterface*>(LOCPLINT->curint)) //if town screen is opened it needs to be redrawn
-				{
-					fs[1] += boost::bind(&CCastleInterface::showAll,pom,screen,true);
-				}
 				fs[1] += boost::bind(&CCreInfoWindow::activate,this);
 				CFunctionList<void()> cfl;
 				cfl = boost::bind(&CCreInfoWindow::deactivate,this);
@@ -3236,12 +3239,6 @@ CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount, StackState
 			//on dismiss confirmed
 			fs[0] += Dsm; //dismiss
 			fs[0] += boost::bind(&CCreInfoWindow::close,this);//close this window
-
-			CCastleInterface *pom;
-			if(pom=dynamic_cast<CCastleInterface*>(LOCPLINT->curint)) //if town screen is opened it needs to be redrawn
-			{
-				fs[1] += boost::bind(&CCastleInterface::showAll,pom,screen,true);
-			}
 			fs[1] += boost::bind(&CCreInfoWindow::activate,this);
 			CFunctionList<void()> cfl;
 		        cfl = boost::bind(&CCreInfoWindow::deactivate,this);
@@ -3282,14 +3279,14 @@ void CCreInfoWindow::activate()
 void CCreInfoWindow::close()
 {
 	deactivate();
-	CCastleInterface *c = dynamic_cast<CCastleInterface*>(LOCPLINT->curint);
-	if(c && dynamic_cast<CHeroWindow*>(c->subInt))
+	if(dynamic_cast<CHeroWindow*>(LOCPLINT->curint->subInt))
 	{
 		if(type)
-			c->subInt->activate();
+			LOCPLINT->curint->subInt->activate();
 	}
 	else
 	{
+		CCastleInterface *c = dynamic_cast<CCastleInterface*>(LOCPLINT->curint);
 		if(c)
 			c->showAll();
 		if(type)

+ 7 - 1
CPlayerInterface.h

@@ -60,6 +60,11 @@ class IShowActivable : public IShowable, public IActivable
 public:
 	virtual ~IShowActivable(){};
 };
+class CMainInterface : public IShowActivable
+{
+public:
+	IShowActivable *subInt;
+};
 class CIntObject //interface object
 {
 public:
@@ -315,7 +320,7 @@ public:
 	boost::mutex *pim;
 	bool makingTurn;
 	SDL_Event * current;
-	IActivable *curint;
+	CMainInterface *curint;
 	CAdvMapInt * adventureInt;
 	CCastleInterface * castleInt;
 	FPSmanager * mainFPSmng;
@@ -335,6 +340,7 @@ public:
 	//overloaded funcs from CGameInterface
 	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
 	void garrisonChanged(const CGObjectInstance * obj);
+	void heroArtifactSetChanged(const CGHeroInstance*hero);
 	void heroCreated(const CGHeroInstance* hero);
 	void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
 	void heroInGarrisonChange(const CGTownInstance *town);

+ 2 - 4
CPreGame.cpp

@@ -615,8 +615,7 @@ void Options::showIcon (int what, int nr, bool abs) //what: -1=castle, 0=hero, 1
 			{
 				if(ourOpt->heroPortrait>=0)
 				{
-					//TODO: restore drawing hero portrait
-					//blitAtWR(CGI->heroh->heroes[ourOpt->heroPortrait]->portraitSmall,252,130+50*se);
+					blitAtWR(graphics->portraitSmall[ourOpt->heroPortrait],252,130+50*se);
 				}
 				else
 				{
@@ -625,8 +624,7 @@ void Options::showIcon (int what, int nr, bool abs) //what: -1=castle, 0=hero, 1
 			}
 			else
 			{
-				//TODO: restore drawing hero portrait
-				//blitAtWR(CGI->heroh->heroes[pom]->portraitSmall,252,130+50*se);
+				blitAtWR(graphics->portraitSmall[pom],252,130+50*se);
 			}
 			break;
 		}

+ 4 - 1
ChangeLog

@@ -1,7 +1,7 @@
 0.61 -> 0.62
 General:
 * restructured to the server-client model
-* support for heroes starting in town garrisons
+* support for heroes placed in towns
 * upgrading creatures
 * working gaining levels for heroes (including dialog with skill selection)
 * added graphical cursor
@@ -16,6 +16,7 @@ Castles:
 * viewing hero window in the town screen
 * possibility of moving hero into the garrison
 * partially done mage guild screen 
+* if hero doesn't have a spell book, he can buy one in a mage guild
 
 Adventure Interface:
 * hopefully fixed problems with wrong town defs (village/fort/capitol)
@@ -44,6 +45,8 @@ PreGame:
 
 Objects:
 * support for the Tree of knowledge
+* support for Campfires
+* added event message when picking artifact
 
 0.6 -> 0.61 (Jun 15 2008)
 Improvements:

+ 11 - 1
client/Client.cpp

@@ -77,6 +77,10 @@ std::string toString(MetaString &ms)
 					break;
 				case 11:
 					vec = &CGI->objh->advobtxt;
+					break;
+				case 12:
+					vec = &CGI->generaltexth->artifEvents;
+					break;
 				}
 				ret += (*vec)[ser];
 			}
@@ -366,7 +370,9 @@ void CClient::process(int what)
 			*serv >> sha;
 			std::cout << "Setting artifacts of hero " << sha.hid << std::endl;
 			gs->apply(&sha);
-			//TODO: inform interfaces
+			CGHeroInstance *t = gs->getHero(sha.hid);
+			if(vstd::contains(playerint,t->tempOwner))
+				playerint[t->tempOwner]->heroArtifactSetChanged(t);
 			break;
 		}
 	case 1001:
@@ -537,3 +543,7 @@ void CClient::run()
 	} HANDLE_EXCEPTION
 }
 
+void CClient::close()
+{
+	serv->close();
+}

+ 1 - 0
client/Client.h

@@ -46,6 +46,7 @@ public:
 	CClient(CConnection *con, StartInfo *si);
 	~CClient(void);
 
+	void close();
 	void process(int what);
 	void run();
 

+ 10 - 5
client/FunctionList.h

@@ -9,6 +9,11 @@ public:
 
 	CFunctionList(int){};
 	CFunctionList(){};
+	template <typename Functor> 
+	CFunctionList(const Functor &f)
+	{
+		funcs.push_back(boost::function<Signature>(f));
+	}
 	CFunctionList(const boost::function<Signature> &first)
 	{
 		funcs.push_back(first);
@@ -22,11 +27,11 @@ public:
 		funcs.push_back(first);
 		return *this;
 	}
-	const boost::function<Signature> & operator=(const boost::function<Signature> &first)
-	{
-		funcs.push_back(first);
-		return first;
-	}
+	//CFunctionList<Signature> & operator=(const boost::function<Signature> &first)
+	//{
+	//	funcs.push_back(first);
+	//	return first;
+	//}
 	operator bool() const
 	{
 		return funcs.size();

+ 1 - 1
client/Graphics.cpp

@@ -71,7 +71,7 @@ SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh)
 	printAtMiddle(buf,167,70,GEORM,zwykly,ret);
 	for (std::map<si32,std::pair<ui32,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++)
 	{
-		if(!i->second.first)
+		if(!i->second.second)
 			continue;
 		blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
 		SDL_itoa((*i).second.second,buf,10);

+ 11 - 0
global.h

@@ -92,6 +92,17 @@ const int SPELL_LEVELS = 5;
 		delete e;						\
 	}
 
+#define HANDLE_EXCEPTIONC(COMMAND)  \
+	catch (const std::exception& e) {	\
+	COMMAND;							\
+	std::cerr << e.what() << std::endl;	\
+	}									\
+	catch (const std::exception * e)	\
+	{									\
+		COMMAND;						\
+		std::cerr << e->what()<< std::endl;	\
+		delete e;						\
+	}
 
 namespace vstd
 {

+ 0 - 2
hch/CArtHandler.h

@@ -14,7 +14,6 @@ public:
 	std::string name;
 	std::string description;
 	//std::string desc2;
-	std::string eventText;
 	unsigned int price;
 	bool spellBook, warMachine1, warMachine2, warMachine3, warMachine4, misc1, misc2, misc3, misc4, misc5, feet, lRing, rRing, torso, lHand, rHand, neck, shoulders, head;
 	EartClass aClass;
@@ -27,7 +26,6 @@ public:
 	std::vector<CArtifact*> treasures, minors, majors, relics;
 	std::vector<CArtifact> artifacts;
 	void loadArtifacts();
-	bool loadArtEvents();
 	CArtHandler();
 };
 

+ 8 - 5
hch/CGeneralTextHandler.cpp

@@ -6,7 +6,7 @@
 
 void CGeneralTextHandler::load()
 {
-	std::string buf = CGI->bitmaph->getTextFile("GENRLTXT.TXT");
+	std::string buf = CGI->bitmaph->getTextFile("GENRLTXT.TXT"), tmp;
 	int andame = buf.size();
 	int i=0; //buf iterator
 	for(i; i<andame; ++i)
@@ -28,7 +28,6 @@ void CGeneralTextHandler::load()
 	int itr=0;
 	while(itr<strs.length()-1)
 	{
-		std::string tmp;
 		loadToIt(tmp, strs, itr, 3);
 		arraytxt.push_back(tmp);
 	}
@@ -37,7 +36,6 @@ void CGeneralTextHandler::load()
 	std::string strin = CGI->bitmaph->getTextFile("PRISKILL.TXT");
 	for(int hh=0; hh<4; ++hh)
 	{
-		std::string tmp;
 		loadToIt(tmp, strin, itr, 3);
 		primarySkillNames.push_back(tmp);
 	}
@@ -46,7 +44,6 @@ void CGeneralTextHandler::load()
 	std::string strin2 = CGI->bitmaph->getTextFile("JKTEXT.TXT");
 	for(int hh=0; hh<45; ++hh)
 	{
-		std::string tmp;
 		loadToIt(tmp, strin2, itr, 3);
 		jktexts.push_back(tmp);
 	}
@@ -55,8 +52,14 @@ void CGeneralTextHandler::load()
 	std::string strin3 = CGI->bitmaph->getTextFile("HEROSCRN.TXT");
 	for(int hh=0; hh<33; ++hh)
 	{
-		std::string tmp;
 		loadToIt(tmp, strin3, itr, 3);
 		heroscrn.push_back(tmp);
 	}
+
+	strin3 = CGI->bitmaph->getTextFile("ARTEVENT.TXT");
+	for(itr = 0; itr<strin3.size();itr++)
+	{
+		loadToIt(tmp, strin3, itr, 3);
+		artifEvents.push_back(tmp);
+	}
 }

+ 2 - 0
hch/CGeneralTextHandler.h

@@ -13,6 +13,8 @@ public:
 	std::vector<std::string> primarySkillNames;
 	std::vector<std::string> jktexts;
 	std::vector<std::string> heroscrn;
+	std::vector<std::string> artifEvents;
+
 	void load();
 };
 

+ 1 - 1
hch/CObjectHandler.cpp

@@ -257,7 +257,7 @@ void CGHeroInstance::setArtAtPos(ui16 pos, int art)
 		if(pos<19)
 			artifWorn.erase(pos);
 		else
-			artifacts -= artifacts[pos];
+			artifacts -= artifacts[pos-19];
 	}
 	else
 	{

+ 10 - 3
lib/Connection.cpp

@@ -79,14 +79,21 @@ int CConnection::read(void * data, unsigned size)
 }
 CConnection::~CConnection(void)
 {
-	if(socket)
-		socket->close();
-	delete socket;
+	close();
 	delete io_service;
 	delete wmx;
 	delete rmx;
 }
 
+void CConnection::close()
+{
+	if(socket)
+	{
+		socket->close();
+		delete socket;
+		socket = NULL;
+	}
+}
 template <>
 void CConnection::saveSerializable<std::string>(const std::string &data)
 {

+ 1 - 0
lib/Connection.h

@@ -372,6 +372,7 @@ public:
 	int write(const void * data, unsigned size);
 	int read(void * data, unsigned size);
 	int readLine(void * data, unsigned maxSize);
+	void close();
 	~CConnection(void);
 };
 

+ 0 - 2
map.cpp

@@ -2128,8 +2128,6 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
 				}
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
 				spec->creatures = readCreatureSet(bufor,i,gcre,(version>RoE));
-				if(version > RoE)
-					i+=gcre;
 				i+=8;
 				nobj->info = spec;
 				///////end of copied fragment

+ 42 - 34
server/CGameHandler.cpp

@@ -477,9 +477,9 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 						S2->slots[p2].second = S1->slots[p1].second;
 						S1->slots[p1].second = pom2;
 
-						if(!S1->slots[p1].first)
+						if(!S1->slots[p1].second)
 							S1->slots.erase(p1);
-						if(!S2->slots[p2].first)
+						if(!S2->slots[p2].second)
 							S2->slots.erase(p2);
 					}
 					else if(what==2)//merge
@@ -618,7 +618,6 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					{
 						sg.garrs[objid].slots[slot].second += cram;
 					}
-
 					sendAndApply(&sr); 
 					sendAndApply(&sac);
 					sendAndApply(&sg);
@@ -708,28 +707,30 @@ upgend:
 					}
 					else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison
 					{
-						//town will be empty
-						SetGarrisons sg;
-						sg.garrs[tid] = CCreatureSet();
-						sendAndApply(&sg);
-
 						SetHeroesInTown intown;
 						intown.tid = tid;
 						intown.garrison = -1;
 						intown.visiting =  town->garrisonHero->id;
 						sendAndApply(&intown);
+
+						//town will be empty
+						SetGarrisons sg;
+						sg.garrs[tid] = CCreatureSet();
+						sendAndApply(&sg);
 					}
 					else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero
 					{
 						SetGarrisons sg;
 						sg.garrs[town->id] = town->visitingHero->army;
-						sendAndApply(&sg);
+						sg.garrs[town->garrisonHero->id] = town->garrisonHero->army;
+						//sg.garrs[town->visitingHero->id] = town->visitingHero->army;
 
 						SetHeroesInTown intown;
 						intown.tid = tid;
 						intown.garrison = town->visitingHero->id;
 						intown.visiting =  town->garrisonHero->id;
 						sendAndApply(&intown);
+						sendAndApply(&sg);
 					}
 					else
 					{
@@ -737,7 +738,7 @@ upgend:
 					}
 					break;
 				}
-			case 509:
+			case 509: //swap artifacts
 				{
 					si32 hid1, hid2;
 					ui16 slot1, slot2;
@@ -749,28 +750,6 @@ upgend:
 
 					h2->setArtAtPos(slot2,a1);
 					h1->setArtAtPos(slot1,a2);
-// 					if(std::max(slot1,slot2) < 19)
-// 					{
-// 						if(vstd::contains(h1->artifWorn,slot1) && vstd::contains(h1->artifWorn,slot2))
-// 							std::swap(h1->artifWorn[slot1],h2->artifWorn[slot2]);
-// 						if(vstd::contains(h1->artifWorn,slot1))
-// 						{
-// 							h2->artifWorn[slot2] = h1->artifWorn[slot1];
-// 							h1->artifWorn.erase(slot1);
-// 						}
-// 						else if(vstd::contains(h2->artifWorn,slot2))
-// 						{
-// 							h1->artifWorn[slot1] = h2->artifWorn[slot2];
-// 							h2->artifWorn.erase(slot2);
-// 						}
-// 						else
-// 						{
-// 							std::cout << "Warning, wrong artifact swap command!" << std::endl;
-// 						}
-// 					}
-// 					else
-// 					{
-// 					}
 					SetHeroArtifacts sha;
 					sha.hid = hid1;
 					sha.artifacts = h1->artifacts;
@@ -783,6 +762,35 @@ upgend:
 						sha.artifWorn = h2->artifWorn;
 						sendAndApply(&sha);
 					}
+					break;
+				}
+			case 510: //buy artifact
+				{
+					ui32 hid;
+					si32 aid, bid;
+					c >> hid >> aid;
+					CGHeroInstance *hero = gs->getHero(hid);
+					CGTownInstance *town = hero->visitedTown;
+					if(aid==0)
+					{
+						if(!vstd::contains(town->builtBuildings,si32(0)))
+							break;
+						SetResource sr;
+						sr.player = hero->tempOwner;
+						sr.resid = 6;
+						sr.val = gs->players[hero->tempOwner].resources[6] - 500;
+						sendAndApply(&sr);
+
+						SetHeroArtifacts sha;
+						sha.hid = hid;
+						sha.artifacts = hero->artifacts;
+						sha.artifWorn = hero->artifWorn;
+						sha.artifWorn[17] = 0;
+						sendAndApply(&sha);
+					}
+					
+					//TODO: war machines
+					break;
 				}
 			case 2001:
 				{
@@ -1100,12 +1108,12 @@ void CGameHandler::run()
 			while(states.players[i->first].makingTurn && !end2)
 			{
 				boost::posix_time::time_duration p;
-				p= boost::posix_time::seconds(1);
+				p = boost::posix_time::milliseconds(200);
 #ifdef _MSC_VER
 				states.cv.timed_wait(lock,p); 
 #else
 				boost::xtime time={0,0};
-				time.sec = static_cast<boost::xtime::xtime_sec_t>(p.total_seconds());
+				time.nsec = static_cast<boost::xtime::xtime_nsec_t>(p.total_nanoseconds());
 				states.cv.timed_wait(lock,time);
 #endif
 			}

+ 12 - 20
server/CScriptCallback.cpp

@@ -128,28 +128,20 @@ void CScriptCallback::stopHeroVisitCastle(int obj, int heroID)
 }
 void CScriptCallback::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack
 {
-	CGHeroInstance* h = gh->gs->map->getHero(hid,0);
+	const CGHeroInstance* h = getHero(hid);
+
+	SetHeroArtifacts sha;
+	sha.hid = hid;
+	sha.artifacts = h->artifacts;
+	sha.artifWorn = h->artifWorn;
 	if(position<0)
-	{
-		for(unsigned i=0;i<h->artifacts.size();i++)
-		{
-			if(!h->artifacts[i])
-			{
-				h->artifacts[i] = artid;
-				return;
-			}
-		}
-		h->artifacts.push_back(artid);
-		return;
-	}
+		sha.artifacts.push_back(artid);
 	else
-	{
-		if(h->artifWorn[position]) //slot is occupied
-		{
-			giveHeroArtifact(h->artifWorn[position],hid,-1);
-		}
-		h->artifWorn[position] = artid;
-	}
+		if(!vstd::contains(sha.artifWorn,ui16(position)))
+			sha.artifWorn[position] = artid;
+		else
+			sha.artifacts.push_back(artid);
+	gh->sendAndApply(&sha);
 }
 
 void CScriptCallback::startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) //use hero=NULL for no hero

+ 0 - 6
server/VCMI_server.vcproj

@@ -288,12 +288,6 @@
 				>
 			</File>
 		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
-			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
-			>
-		</Filter>
 	</Files>
 	<Globals>
 	</Globals>