Browse Source

* version set to 0.62
* almost redone treasure chest
* working gaining levels for heroes (including dialog with skill selection)
* corrected another typo i cr_shots

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

+ 4 - 0
AI/EmptyAI/CEmptyAI.cpp

@@ -20,4 +20,8 @@ void CEmptyAI::heroCreated(const CGHeroInstance *)
 }
 }
 void CEmptyAI::heroMoved(const HeroMoveDetails &)
 void CEmptyAI::heroMoved(const HeroMoveDetails &)
 {
 {
+}
+void CEmptyAI::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)
+{
+	callback(rand()%skills.size());
 }
 }

+ 1 - 0
AI/EmptyAI/CEmptyAI.h

@@ -13,6 +13,7 @@ public:
 	void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID){};
 	void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID){};
 	void tileRevealed(int3 pos){};
 	void tileRevealed(int3 pos){};
 	void tileHidden(int3 pos){};
 	void tileHidden(int3 pos){};
+	void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
 };
 };
 
 
 #define NAME "EmptyAI 0.1"
 #define NAME "EmptyAI 0.1"

+ 0 - 1
AdventureMapButton.cpp

@@ -5,7 +5,6 @@
 #include "hch/CLodHandler.h"
 #include "hch/CLodHandler.h"
 #include "hch/CPreGameTextHandler.h"
 #include "hch/CPreGameTextHandler.h"
 #include "hch/CTownHandler.h"
 #include "hch/CTownHandler.h"
-#include "CLua.h"
 #include "CCallback.h"
 #include "CCallback.h"
 #include "client/Graphics.h"
 #include "client/Graphics.h"
 AdventureMapButton::AdventureMapButton ()
 AdventureMapButton::AdventureMapButton ()

+ 0 - 1
CAdvmapInterface.cpp

@@ -15,7 +15,6 @@
 #include "CMessage.h"
 #include "CMessage.h"
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/replace.hpp>
-#include "CLua.h"
 #include "hch/CHeroHandler.h"
 #include "hch/CHeroHandler.h"
 #include <sstream>
 #include <sstream>
 #include "AdventureMapButton.h"
 #include "AdventureMapButton.h"

+ 1 - 3
CCallback.cpp

@@ -106,9 +106,7 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
 
 
 void CCallback::selectionMade(int selection, int asker)
 void CCallback::selectionMade(int selection, int asker)
 {
 {
-	//todo - jak bedzie multiplayer po sieci, to moze wymagac przerobek zaleznych od obranego modelu
-	//IChosen * ask = (IChosen *)asker;
-	//ask->chosen(selection);
+	*cl->serv << ui16(2001) << ui32(asker) << ui32(selection);
 }
 }
 void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
 void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
 {
 {

+ 3 - 1
CGameInterface.h

@@ -3,6 +3,7 @@
 #include "global.h"
 #include "global.h"
 #include <set>
 #include <set>
 #include <vector>
 #include <vector>
+#include <boost/function.hpp>
 #include "lib/BattleAction.h"
 #include "lib/BattleAction.h"
 BOOST_TRIBOOL_THIRD_STATE(outOfRange)
 BOOST_TRIBOOL_THIRD_STATE(outOfRange)
 
 
@@ -55,9 +56,10 @@ public:
 	virtual void tileHidden(int3 pos){};
 	virtual void tileHidden(int3 pos){};
 	virtual void receivedResource(int type, int val){};
 	virtual void receivedResource(int type, int val){};
 	virtual void showInfoDialog(std::string text, std::vector<Component*> &components){};
 	virtual void showInfoDialog(std::string text, std::vector<Component*> &components){};
-	virtual void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)=0;
+	virtual void showSelDialog(std::string text, std::vector<Component*> &components, ui32 askID){};
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
 	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
 	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
+	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
 	//battle call-ins
 	//battle call-ins
 	virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
 	virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning

+ 30 - 1
CGameState.cpp

@@ -304,6 +304,29 @@ void CGameState::applyNL(IPack * pack)
 			}
 			}
 			break;
 			break;
 		}
 		}
+	case 106:
+		{
+			SetSecSkill *sr = static_cast<SetSecSkill*>(pack);
+			CGHeroInstance *hero = getHero(sr->id);
+			if(hero->getSecSkillLevel(sr->which) < 0)
+			{
+				hero->secSkills.push_back(std::pair<int,int>(sr->which, (sr->abs)? (sr->val) : (sr->val-1)));
+			}
+			else
+			{
+				for(unsigned i=0;i<hero->secSkills.size();i++)
+				{
+					if(hero->secSkills[i].first == sr->which)
+					{
+						if(sr->abs)
+							hero->secSkills[i].second = sr->val;
+						else
+							hero->secSkills[i].second += sr->val;
+					}
+				}
+			}
+			break;
+		}
 	case 500:
 	case 500:
 		{
 		{
 			RemoveHero *rh = static_cast<RemoveHero*>(pack);
 			RemoveHero *rh = static_cast<RemoveHero*>(pack);
@@ -360,7 +383,7 @@ void CGameState::applyNL(IPack * pack)
 	case 1001://set object property
 	case 1001://set object property
 		{
 		{
 			SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
 			SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
-			int CGObjectInstance::*point;
+			ui8 CGObjectInstance::*point;
 			switch(p->what)
 			switch(p->what)
 			{
 			{
 			case 1:
 			case 1:
@@ -373,6 +396,12 @@ void CGameState::applyNL(IPack * pack)
 			map->objects[p->id]->*point = p->val;
 			map->objects[p->id]->*point = p->val;
 			break;
 			break;
 		}
 		}
+	case 2000:
+		{
+			HeroLevelUp * bs = static_cast<HeroLevelUp*>(pack);
+			getHero(bs->heroid)->level = bs->level;
+			break;
+		}
 	case 3000:
 	case 3000:
 		{
 		{
 			BattleStart * bs = static_cast<BattleStart*>(pack);
 			BattleStart * bs = static_cast<BattleStart*>(pack);

+ 8 - 24
CHeroWindow.cpp

@@ -62,7 +62,6 @@ CHeroWindow::CHeroWindow(int playerColor):
 		heroListMi[g]->id = g;
 		heroListMi[g]->id = g;
 	}
 	}
 
 
-	skillpics = CDefHandler::giveDef("pskil42.def");
 	flags = CDefHandler::giveDef("CREST58.DEF");
 	flags = CDefHandler::giveDef("CREST58.DEF");
 	//areas
 	//areas
 	portraitArea = new LRClickableAreaWText();
 	portraitArea = new LRClickableAreaWText();
@@ -126,7 +125,6 @@ CHeroWindow::~CHeroWindow()
 	if(curBack)
 	if(curBack)
 		SDL_FreeSurface(curBack);
 		SDL_FreeSurface(curBack);
 
 
-	delete skillpics;
 	delete flags;
 	delete flags;
 
 
 	delete garInt;
 	delete garInt;
@@ -219,22 +217,8 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
 	{
 	{
 		secSkillAreas[g]->type = hero->secSkills[g].first;
 		secSkillAreas[g]->type = hero->secSkills[g].first;
 		secSkillAreas[g]->bonus = hero->secSkills[g].second;
 		secSkillAreas[g]->bonus = hero->secSkills[g].second;
-		std::string hlp;
-		switch(hero->secSkills[g].second)
-		{
-		case 0: //basic level
-			hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->basicText;
-			secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2);
-			break;
-		case 1: //adv level
-			hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->advText;
-			secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2);
-			break;
-		case 2: //expert level
-			hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->expText;
-			secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2);
-			break;
-		}
+		std::string hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->infoTexts[hero->secSkills[g].second];
+		secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2);
 
 
 		char * hlpp = new char[200];
 		char * hlpp = new char[200];
 		sprintf(hlpp, CGI->generaltexth->heroscrn[21].c_str(), CGI->abilh->levels[hero->secSkills[g].second].c_str(), CGI->abilh->abilities[hero->secSkills[g].first]->name.c_str());
 		sprintf(hlpp, CGI->generaltexth->heroscrn[21].c_str(), CGI->abilh->levels[hero->secSkills[g].second].c_str(), CGI->abilh->abilities[hero->secSkills[g].first]->name.c_str());
@@ -729,12 +713,12 @@ void CHeroWindow::redrawCurBack()
 		SDL_FreeSurface(curBack);
 		SDL_FreeSurface(curBack);
 	curBack = SDL_DisplayFormat(background);
 	curBack = SDL_DisplayFormat(background);
 
 
-	blitAt(skillpics->ourImages[0].bitmap, 32, 111, curBack);
-	blitAt(skillpics->ourImages[1].bitmap, 102, 111, curBack);
-	blitAt(skillpics->ourImages[2].bitmap, 172, 111, curBack);
-	blitAt(skillpics->ourImages[5].bitmap, 242, 111, curBack);
-	blitAt(skillpics->ourImages[4].bitmap, 20, 230, curBack);
-	blitAt(skillpics->ourImages[3].bitmap, 162, 230, curBack);
+	blitAt(graphics->pskillsm->ourImages[0].bitmap, 32, 111, curBack);
+	blitAt(graphics->pskillsm->ourImages[1].bitmap, 102, 111, curBack);
+	blitAt(graphics->pskillsm->ourImages[2].bitmap, 172, 111, curBack);
+	blitAt(graphics->pskillsm->ourImages[5].bitmap, 242, 111, curBack);
+	blitAt(graphics->pskillsm->ourImages[4].bitmap, 20, 230, curBack);
+	blitAt(graphics->pskillsm->ourImages[3].bitmap, 162, 230, curBack);
 
 
 	blitAt(graphics->portraitLarge[curHero->portrait], 19, 19, curBack);
 	blitAt(graphics->portraitLarge[curHero->portrait], 19, 19, curBack);
 
 

+ 1 - 1
CHeroWindow.h

@@ -88,7 +88,7 @@ class CHeroWindow: public IActivable, public IShowable, public virtual CIntObjec
 	CStatusBar * ourBar; //heroWindow's statusBar
 	CStatusBar * ourBar; //heroWindow's statusBar
 
 
 	//general graphics
 	//general graphics
-	CDefHandler * skillpics, *flags;
+	CDefHandler *flags;
 
 
 	//buttons
 	//buttons
 	AdventureMapButton * quitButton, * dismissButton, * questlogButton, //general
 	AdventureMapButton * quitButton, * dismissButton, * questlogButton, //general

+ 51 - 53
CLua.cpp

@@ -1,5 +1,7 @@
 #include "stdafx.h"
 #include "stdafx.h"
 #include <sstream>
 #include <sstream>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include "hch/CHeroHandler.h"
 #include "hch/CHeroHandler.h"
@@ -516,12 +518,12 @@ void CPickable::onHeroVisit(int objid, int heroID)
 	DEFOS;
 	DEFOS;
 	switch(os->ID)
 	switch(os->ID)
 	{
 	{
-	case 5:
+	case 5: //artifact
 		{
 		{
 			cb->giveHeroArtifact(os->subID,heroID,-1); //TODO: na pozycje
 			cb->giveHeroArtifact(os->subID,heroID,-1); //TODO: na pozycje
 			break;
 			break;
 		}
 		}
-	case 79:
+	case 79: //resource
 		{
 		{
 			//TODO: handle guards (when battles are finished)
 			//TODO: handle guards (when battles are finished)
 			CResourceObjInfo * t2 = static_cast<CResourceObjInfo *>(os->info);
 			CResourceObjInfo * t2 = static_cast<CResourceObjInfo *>(os->info);
@@ -561,64 +563,60 @@ void CPickable::onHeroVisit(int objid, int heroID)
 			cb->showCompInfo(&sii);
 			cb->showCompInfo(&sii);
 			break;
 			break;
 		}
 		}
-	case 101:
+	case 101: //treasure chest
 		{
 		{
-			//if (os->subID)
-			//	break; //not OH3 treasure chest
-			//int wyn = rand()%100;
-			//if (wyn<32)
-			//{
-			//	tempStore.push_back(new CSelectableComponent(SComponent::resource,6,1000));
-			//	tempStore.push_back(new CSelectableComponent(SComponent::experience,0,500));
-			//}//1k/0.5k
-			//else if(wyn<64)
-			//{
-			//	tempStore.push_back(new CSelectableComponent(SComponent::resource,6,1500));
-			//	tempStore.push_back(new CSelectableComponent(SComponent::experience,0,1000));
-			//}//1.5k/1k
-			//else if(wyn<95)
-			//{
-			//	tempStore.push_back(new CSelectableComponent(SComponent::resource,6,2000));
-			//	tempStore.push_back(new CSelectableComponent(SComponent::experience,0,1500));
-			//}//2k/1.5k
-			//else
-			//{
-			//	if (1/*TODO: backpack is full*/)
-			//	{
-			//		tempStore.push_back(new CSelectableComponent(SComponent::resource,6,1000));
-			//		tempStore.push_back(new CSelectableComponent(SComponent::experience,0,500));
-			//	}
-			//	else
-			//	{
-			//		//TODO: give treasure artifact
-			//		break;
-			//	}
-			//}//random treasure artifact, or (if backapack is full) 1k/0.5k
-			//tempStore[1]->ID = heroID;
-			//player = cb->getHeroOwner(heroID);
-			//cb->showSelDialog(player,VLC->objh->advobtxt[146],&tempStore,this);
+			if (os->subID) //not OH3 treasure chest
+				break; 
+			int wyn = rand()%100, val=0;
+			if (wyn<32) //1k/0.5k
+			{
+				val = 1000;
+			}
+			else if(wyn<64) //1.5k/1k
+			{
+				val = 1500;
+			}
+			else if(wyn<95) //2k/1.5k
+			{
+				val = 2000;
+			}
+			else //random treasure artifact, or (if backapack is full) 1k/0.5k
+			{
+				if (1/*TODO: backpack is full*/)
+				{
+					val = 1000;
+				}
+				else
+				{
+					//TODO: give treasure artifact
+					break;
+				}
+			}
+			SelectionDialog sd;
+			sd.player = cb->getHeroOwner(heroID);
+			sd.text << std::pair<ui8,ui32>(11,146);
+			sd.components.push_back(Component(2,6,val,0));
+			sd.components.push_back(Component(5,0,val-500,0));
+			boost::function<void(ui32)> fun = boost::bind(&CPickable::chosen,this,_1,heroID,val);
+			cb->showSelectionDialog(&sd,fun);
 			break;
 			break;
 		}
 		}
 	}
 	}
 	//VLC->mh->removeObject(os);
 	//VLC->mh->removeObject(os);
 }
 }
-void CPickable::chosen(int which)
+void CPickable::chosen(ui32 which, int heroid, int val)
 {
 {
-	//switch(tempStore[which]->type)
-	//{
-	//case SComponent::resource:
-	//	cb->giveResource(player,tempStore[which]->subtype,tempStore[which]->val);
-	//	break;
-	//case SComponent::experience:
-	//	cb->changePrimSkill(tempStore[which]->ID,4,tempStore[which]->val);
-	//	break;
-	//default:
-	//	throw new std::exception("Unhandled choice");
-	//	
-	//}
-	//for (int i=0;i<tempStore.size();i++)
-	//	delete tempStore[i];
-	//tempStore.clear();
+	switch(which)
+	{
+	case 0: //player pick gold
+		cb->giveResource(cb->getHeroOwner(heroid),6,val);
+		break;
+	case 1: //player pick exp
+		cb->changePrimSkill(heroid, 4, val-500);
+		break;
+	default:
+		throw std::string("Unhandled choice");
+	}
 }
 }
 
 
 std::vector<int> CPickable::yourObjects() //returns IDs of objects which are handled by script
 std::vector<int> CPickable::yourObjects() //returns IDs of objects which are handled by script

+ 2 - 10
CLua.h

@@ -60,11 +60,6 @@ public:
 	CScript();
 	CScript();
 	virtual ~CScript();
 	virtual ~CScript();
 };
 };
-class IChosen
-{
-public:
-	virtual void chosen(int which)=0;
-};
 class CLua :public CScript
 class CLua :public CScript
 {
 {
 protected:
 protected:
@@ -140,14 +135,11 @@ public:
 	void newTurn ();
 	void newTurn ();
 };
 };
 
 
-class CPickable : public CCPPObjectScript, public IChosen  //pickable - resources, artifacts, etc
+class CPickable : public CCPPObjectScript //pickable - resources, artifacts, etc
 {
 {
 public:
 public:
-	std::vector<CSelectableComponent*> tempStore;
-	int player;
-
 	CPickable(CScriptCallback * CB):CCPPObjectScript(CB){};
 	CPickable(CScriptCallback * CB):CCPPObjectScript(CB){};
-	void chosen(int which);
+	void chosen(ui32 which, int heroid, int val); //val - value of treasure in gold
 	void newObject(int objid);
 	void newObject(int objid);
 	void onHeroVisit(int objid, int heroID);
 	void onHeroVisit(int objid, int heroID);
 	std::vector<int> yourObjects(); //returns IDs of objects which are handled by script
 	std::vector<int> yourObjects(); //returns IDs of objects which are handled by script

+ 0 - 1
CMT.cpp

@@ -22,7 +22,6 @@
 #include "CCallback.h"
 #include "CCallback.h"
 #include "CPlayerInterface.h"
 #include "CPlayerInterface.h"
 #include "CLuaHandler.h"
 #include "CLuaHandler.h"
-#include "CLua.h"
 #include "CAdvmapInterface.h"
 #include "CAdvmapInterface.h"
 #include "hch/CBuildingHandler.h"
 #include "hch/CBuildingHandler.h"
 #include "hch/CVideoHandler.h"
 #include "hch/CVideoHandler.h"

+ 2 - 3
CMessage.cpp

@@ -12,7 +12,6 @@
 #include "CGameInfo.h"
 #include "CGameInfo.h"
 #include "SDL_Extensions.h"
 #include "SDL_Extensions.h"
 #include <sstream>
 #include <sstream>
-#include "CLua.h"
 #include "hch/CGeneralTextHandler.h"
 #include "hch/CGeneralTextHandler.h"
 #include "client/Graphics.h"
 #include "client/Graphics.h"
 SDL_Color tytulowy, tlo, zwykly ;
 SDL_Color tytulowy, tlo, zwykly ;
@@ -464,10 +463,10 @@ SDL_Surface * CMessage::drawBoxTextBitmapSub(int player, std::string text, SDL_S
 CSelWindow * CMessage::genSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> & comps, int owner)
 CSelWindow * CMessage::genSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> & comps, int owner)
 {
 {
 	CSelWindow * ret = new CSelWindow();
 	CSelWindow * ret = new CSelWindow();
-	for(int i=0;i<comps.size();i++)
+	for(unsigned i=0;i<comps.size();i++)
 	{
 	{
 		ret->components.push_back(comps[i]);
 		ret->components.push_back(comps[i]);
-		comps[i]->owner = ret;
+		comps[i]->onSelect = boost::bind(&CSelWindow::selectionChange,ret,i);
 	}
 	}
 	std::vector<std::string> * tekst = breakText(text,charperline);
 	std::vector<std::string> * tekst = breakText(text,charperline);
 	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(tekst);
 	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(tekst);

+ 150 - 27
CPlayerInterface.cpp

@@ -27,7 +27,6 @@
 #include "hch/CObjectHandler.h"
 #include "hch/CObjectHandler.h"
 #include "CBattleInterface.h"
 #include "CBattleInterface.h"
 #include "CGameInfo.h"
 #include "CGameInfo.h"
-#include "CLua.h"
 #include <cmath>
 #include <cmath>
 #include "client/CCreatureAnimation.h"
 #include "client/CCreatureAnimation.h"
 #include "client/Graphics.h"
 #include "client/Graphics.h"
@@ -540,6 +539,10 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 		oss << ((Val>0)?("+"):("-")) << Val << " " << CGI->heroh->pskillsn[Subtype];
 		oss << ((Val>0)?("+"):("-")) << Val << " " << CGI->heroh->pskillsn[Subtype];
 		subtitle = oss.str();
 		subtitle = oss.str();
 		break;
 		break;
+	case secskill44:
+		subtitle += CGI->abilh->levels[Val] + " " + CGI->abilh->abilities[Subtype]->name;
+		description = CGI->abilh->abilities[Subtype]->infoTexts[Val];
+		break;
 	case resource:
 	case resource:
 		description = CGI->generaltexth->allTexts[242];
 		description = CGI->generaltexth->allTexts[242];
 		oss << Val;
 		oss << Val;
@@ -569,13 +572,13 @@ SComponent::SComponent(const Component &c)
 		init(experience,0,c.val);
 		init(experience,0,c.val);
 	else
 	else
 		init((Etype)c.id,c.subtype,c.val);
 		init((Etype)c.id,c.subtype,c.val);
-	switch(c.id)
-	{
-	case resource:
-		if(c.when == -1)
-			subtitle += CGI->generaltexth->allTexts[3].substr(2,CGI->generaltexth->allTexts[3].length()-2);
-		break;
-	}
+
+	if(c.id==2 && c.when==-1)
+		subtitle += CGI->generaltexth->allTexts[3].substr(2,CGI->generaltexth->allTexts[3].length()-2);
+}
+void SComponent::show(SDL_Surface * to)
+{
+	blitAt(getImg(),pos.x,pos.y,to);
 }
 }
 SDL_Surface * SComponent::getImg()
 SDL_Surface * SComponent::getImg()
 {
 {
@@ -584,6 +587,9 @@ SDL_Surface * SComponent::getImg()
 	case primskill:
 	case primskill:
 		return graphics->pskillsb->ourImages[subtype].bitmap;
 		return graphics->pskillsb->ourImages[subtype].bitmap;
 		break;
 		break;
+	case secskill44:
+		return CGI->abilh->abils44->ourImages[subtype*3 + 3 + val].bitmap;
+		break;
 	case secskill:
 	case secskill:
 		return CGI->abilh->abils82->ourImages[subtype*3 + 3 + val].bitmap;
 		return CGI->abilh->abils82->ourImages[subtype*3 + 3 + val].bitmap;
 		break;
 		break;
@@ -613,12 +619,11 @@ void CSelectableComponent::clickLeft(tribool down)
 {
 {
 	if (down)
 	if (down)
 	{
 	{
-		select(true);
-		owner->selectionChange(this);
+		if(onSelect)
+			onSelect();
 	}
 	}
 }
 }
-CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, CSelWindow * Owner, SDL_Surface * Border)
-:SComponent(Type,Sub,Val),owner(Owner)
+void CSelectableComponent::init(SDL_Surface * Border)
 {
 {
 	SDL_Surface * symb = SComponent::getImg();
 	SDL_Surface * symb = SComponent::getImg();
 	myBitmap = CSDL_Ext::newSurface(symb->w+2,symb->h+2,screen);
 	myBitmap = CSDL_Ext::newSurface(symb->w+2,symb->h+2,screen);
@@ -648,6 +653,16 @@ CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, CSelWin
 	}
 	}
 	selected = false;
 	selected = false;
 }
 }
+CSelectableComponent::CSelectableComponent(const Component &c, boost::function<void()> OnSelect, SDL_Surface * Border)
+:SComponent(c),onSelect(OnSelect)
+{
+	init(Border);
+}
+CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect, SDL_Surface * Border)
+:SComponent(Type,Sub,Val),onSelect(OnSelect)
+{
+	init(Border);
+}
 CSelectableComponent::~CSelectableComponent()
 CSelectableComponent::~CSelectableComponent()
 {
 {
 	SDL_FreeSurface(myBitmap);
 	SDL_FreeSurface(myBitmap);
@@ -686,7 +701,11 @@ void CSelectableComponent::select(bool on)
 		return;
 		return;
 	}
 	}
 }
 }
-
+void CSelectableComponent::show(SDL_Surface * to)
+{
+	blitAt(myBitmap,pos.x,pos.y,to);
+	printAtMiddleWB(subtitle,pos.x+pos.w/2,pos.y+pos.h+14,GEOR13,12,zwykly,to);
+}
 void CSimpleWindow::show(SDL_Surface * to)
 void CSimpleWindow::show(SDL_Surface * to)
 {
 {
 	if(!to)
 	if(!to)
@@ -702,22 +721,14 @@ CSimpleWindow::~CSimpleWindow()
 	}
 	}
 }
 }
 
 
-void CSelWindow::selectionChange(CSelectableComponent * to)
+void CSelWindow::selectionChange(unsigned to)
 {
 {
-	blitAt(to->getImg(),to->pos.x-pos.x,to->pos.y-pos.y,bitmap);
-	for (int i=0;i<components.size();i++)
+	for (unsigned i=0;i<components.size();i++)
 	{
 	{
-		if(components[i]==to)
-		{
-			if (to->selected)
-				continue;
-			else
-				to->select(true);
-		}
 		CSelectableComponent * pom = dynamic_cast<CSelectableComponent*>(components[i]);
 		CSelectableComponent * pom = dynamic_cast<CSelectableComponent*>(components[i]);
 		if (!pom)
 		if (!pom)
 			continue;
 			continue;
-		pom->select(false);
+		pom->select(i==to);
 		blitAt(pom->getImg(),pom->pos.x-pos.x,pom->pos.y-pos.y,bitmap);
 		blitAt(pom->getImg(),pom->pos.x-pos.x,pom->pos.y-pos.y,bitmap);
 	}
 	}
 }
 }
@@ -736,6 +747,7 @@ void CSelWindow::close()
 			ret = i;
 			ret = i;
 		}
 		}
 		components[i]->deactivate();
 		components[i]->deactivate();
+		delete components[i];
 	}
 	}
 	components.clear();
 	components.clear();
 	okb.deactivate();
 	okb.deactivate();
@@ -1869,10 +1881,16 @@ void CPlayerInterface::receivedResource(int type, int val)
 	adventureInt->resdatabar.draw();
 	adventureInt->resdatabar.draw();
 }
 }
 
 
-void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)
+void CPlayerInterface::showSelDialog(std::string text, std::vector<Component*> &components, ui32 askID)
+//void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)
 {
 {
+	boost::unique_lock<boost::mutex> un(*pim);
 	adventureInt->hide(); //dezaktywacja starego interfejsu
 	adventureInt->hide(); //dezaktywacja starego interfejsu
-	CSelWindow * temp = CMessage::genSelWindow(text,LOCPLINT->playerID,35,components,playerID);
+	std::vector<CSelectableComponent*> intComps;
+	for(int i=0;i<components.size();i++)
+		intComps.push_back(new CSelectableComponent(*components[i])); //will be deleted by CSelWindow::close
+
+	CSelWindow * temp = CMessage::genSelWindow(text,LOCPLINT->playerID,35,intComps,playerID);
 	LOCPLINT->objsToBlit.push_back(temp);
 	LOCPLINT->objsToBlit.push_back(temp);
 	temp->pos.x=300-(temp->pos.w/2);
 	temp->pos.x=300-(temp->pos.w/2);
 	temp->pos.y=300-(temp->pos.h/2);
 	temp->pos.y=300-(temp->pos.h/2);
@@ -1886,10 +1904,18 @@ void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableCo
 		temp->components[i]->pos.y += temp->pos.y;
 		temp->components[i]->pos.y += temp->pos.y;
 	}
 	}
 	temp->ID = askID;
 	temp->ID = askID;
-	components[0]->clickLeft(true);
+	intComps[0]->clickLeft(true);
+}
+void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16>& skills, boost::function<void(ui32)> &callback)
+{
+	boost::unique_lock<boost::mutex> un(*pim);
+	CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback);
+	curint->deactivate();
+	lw->activate();
 }
 }
 void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
 void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
 {
 {
+	boost::unique_lock<boost::mutex> un(*pim);
 	openTownWindow(town);
 	openTownWindow(town);
 }
 }
 void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
@@ -3087,3 +3113,100 @@ void CCreInfoWindow::deactivate()
 	if(upgrade)
 	if(upgrade)
 		upgrade->deactivate();
 		upgrade->deactivate();
 }
 }
+
+void CLevelWindow::close()
+{
+	deactivate();
+	for(int i=0;i<comps.size();i++)
+	{
+		if(comps[i]->selected)
+		{
+			cb(i);
+			break;
+		}
+	}
+	delete this;
+	LOCPLINT->curint->activate();
+}
+CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)
+{
+	heroType = hero->subID;
+	cb = callback;
+	for(int i=0;i<skills.size();i++)
+		comps.push_back(new CSelectableComponent(SComponent::secskill44,skills[i],hero->getSecSkillLevel(skills[i])+1,boost::bind(&CLevelWindow::selectionChanged,this,i)));
+	bitmap = BitmapHandler::loadBitmap("LVLUPBKG.bmp");
+	graphics->blueToPlayersAdv(bitmap,hero->tempOwner);
+	SDL_SetColorKey(bitmap,SDL_SRCCOLORKEY,SDL_MapRGB(bitmap->format,0,255,255));
+	pos.x = screen->w/2 - bitmap->w/2;
+	pos.y = screen->h/2 - bitmap->h/2;
+	pos.w = bitmap->w;
+	pos.h = bitmap->h;
+	ok = new AdventureMapButton("","",boost::bind(&CLevelWindow::close,this),pos.x+297,pos.y+413,"IOKAY.DEF");
+
+	//draw window
+	char buf[100], buf2[100];
+	strcpy(buf2,CGI->generaltexth->allTexts[444].c_str()); //%s has gained a level.
+	sprintf(buf,buf2,hero->name.c_str());
+	printAtMiddle(buf,192,35,GEOR16,zwykly,bitmap);
+
+	strcpy(buf2,CGI->generaltexth->allTexts[445].c_str()); //%s is now a level %d %s.
+	sprintf(buf,buf2,hero->name.c_str(),hero->level,hero->type->heroClass->name.c_str());
+	printAtMiddle(buf,192,162,GEOR16,zwykly,bitmap);
+
+	blitAt(graphics->pskillsm->ourImages[pskill].bitmap,174,190,bitmap);
+
+	printAtMiddle((CGI->generaltexth->primarySkillNames[pskill] + " +1"),192,252,GEOR16,zwykly,bitmap);
+
+	SDL_Surface * ort = TTF_RenderText_Blended(GEOR16,CGI->generaltexth->allTexts[4].c_str(),zwykly);
+	int curx = bitmap->w/2 - ( skills.size()*44   +   (skills.size()-1)*(36+ort->w) )/2;
+	for(int i=0;i<comps.size();i++)
+	{
+		comps[i]->pos.x = curx+pos.x;
+		comps[i]->pos.y = 326+pos.y;
+		if( i < (comps.size()-1) )
+		{
+			curx += 44 + 18; //skill width + margin to "or"
+			blitAt(ort,curx,346,bitmap);
+			curx += ort->w + 18;
+		}
+	}
+	SDL_FreeSurface(ort);
+
+}
+void CLevelWindow::selectionChanged(unsigned to)
+{
+	for(int i=0;i<comps.size();i++)
+		if(i==to)
+			comps[i]->select(true);
+		else
+			comps[i]->select(false);
+}
+CLevelWindow::~CLevelWindow()
+{
+	delete ok;
+	for(int i=0;i<comps.size();i++)
+		delete comps[i];
+	SDL_FreeSurface(bitmap);
+}
+void CLevelWindow::activate()
+{
+	LOCPLINT->objsToBlit.push_back(this);
+	ok->activate();
+	for(int i=0;i<comps.size();i++)
+		comps[i]->activate();
+}
+void CLevelWindow::deactivate()
+{
+	LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),this));
+	ok->deactivate();
+	for(int i=0;i<comps.size();i++)
+		comps[i]->deactivate();
+}
+void CLevelWindow::show(SDL_Surface * to)
+{
+	blitAt(bitmap,pos.x,pos.y,screen);
+	blitAt(graphics->portraitLarge[heroType],170+pos.x,66+pos.y);
+	ok->show();
+	for(int i=0;i<comps.size();i++)
+		comps[i]->show();
+}

+ 29 - 7
CPlayerInterface.h

@@ -4,7 +4,6 @@
 #include "CGameInterface.h"
 #include "CGameInterface.h"
 #include "SDL_framerate.h"
 #include "SDL_framerate.h"
 #include <map>
 #include <map>
-#include <boost/function.hpp>
 
 
 class CDefEssential;
 class CDefEssential;
 class AdventureMapButton;
 class AdventureMapButton;
@@ -169,9 +168,9 @@ public:
 	virtual ~CInfoWindow();
 	virtual ~CInfoWindow();
 };
 };
 class CSelWindow : public CInfoWindow //component selection window
 class CSelWindow : public CInfoWindow //component selection window
-{ //uwaga - to okno nie usuwa swoich komponentow przy usuwaniu, moga sie one jeszcze przydac skryptowi - tak wiec skrypt korzystajacyz tego okna musi je usunac
+{ //uwaga - to okno usuwa swoje komponenty przy zamykaniu
 public:
 public:
-	void selectionChange(CSelectableComponent * to);
+	void selectionChange(unsigned to);
 	void okClicked(boost::logic::tribool down);
 	void okClicked(boost::logic::tribool down);
 	void close();
 	void close();
 	CSelWindow(){};
 	CSelWindow(){};
@@ -204,7 +203,7 @@ class SComponent : public ClickableR
 public:
 public:
 	enum Etype
 	enum Etype
 	{
 	{
-		primskill, secskill, resource, creature, artifact, experience
+		primskill, secskill, resource, creature, artifact, experience, secskill44
 	} type;
 	} type;
 	int subtype;
 	int subtype;
 	int val;
 	int val;
@@ -218,6 +217,7 @@ public:
 
 
 	void clickRight (boost::logic::tribool down);
 	void clickRight (boost::logic::tribool down);
 	virtual SDL_Surface * getImg();
 	virtual SDL_Surface * getImg();
+	virtual void show(SDL_Surface * to = NULL);
 	virtual void activate();
 	virtual void activate();
 	virtual void deactivate();
 	virtual void deactivate();
 };
 };
@@ -229,12 +229,15 @@ public:
 
 
 	bool customB;
 	bool customB;
 	SDL_Surface * border, *myBitmap;
 	SDL_Surface * border, *myBitmap;
-	CSelWindow * owner;
+	boost::function<void()> onSelect;
 
 
 
 
 	void clickLeft(boost::logic::tribool down);
 	void clickLeft(boost::logic::tribool down);
-	CSelectableComponent(Etype Type, int Sub, int Val, CSelWindow * Owner=NULL, SDL_Surface * Border=NULL);
+	void init(SDL_Surface * Border);
+	CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect = 0, SDL_Surface * Border=NULL);
+	CSelectableComponent(const Component &c, boost::function<void()> OnSelect = 0, SDL_Surface * Border=NULL);
 	~CSelectableComponent();
 	~CSelectableComponent();
+	virtual void show(SDL_Surface * to = NULL);
 	void activate();
 	void activate();
 	void deactivate();
 	void deactivate();
 	void select(bool on);
 	void select(bool on);
@@ -328,10 +331,11 @@ public:
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val);
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val);
 	void receivedResource(int type, int val);
 	void receivedResource(int type, int val);
 	void showInfoDialog(std::string text, std::vector<Component*> &components);
 	void showInfoDialog(std::string text, std::vector<Component*> &components);
-	void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID);
+	void showSelDialog(std::string text, std::vector<Component*> &components, ui32 askID);
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
 	void garrisonChanged(const CGObjectInstance * obj);
 	void garrisonChanged(const CGObjectInstance * obj);
 	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
 	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
+	void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
 	//for battles
 	//for battles
 	void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
 	void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
 	void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
 	void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
@@ -533,6 +537,24 @@ public:
 	void show(SDL_Surface * to = NULL);
 	void show(SDL_Surface * to = NULL);
 };
 };
 
 
+class CLevelWindow : public IShowable, public CIntObject
+{
+public:
+	int heroType;
+	SDL_Surface *bitmap;
+	std::vector<CSelectableComponent *> comps; //skills to select
+	AdventureMapButton *ok;
+	boost::function<void(ui32)> cb;
+	
+	void close();
+	CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
+	~CLevelWindow();
+	void activate();
+	void deactivate();
+	void selectionChanged(unsigned to);
+	void show(SDL_Surface * to = NULL);
+};
+
 extern CPlayerInterface * LOCPLINT;
 extern CPlayerInterface * LOCPLINT;
 
 
 #endif //CPLAYERINTERFACE_H
 #endif //CPLAYERINTERFACE_H

+ 1 - 0
SDL_Extensions.cpp

@@ -44,6 +44,7 @@ void blitAtWR(SDL_Surface * src, int x, int y, SDL_Surface * dst)
 }
 }
 void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst)
 void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst)
 {
 {
+	if(!dst) dst = screen;
 	SDL_Rect pom = genRect(src->h,src->w,x,y);
 	SDL_Rect pom = genRect(src->h,src->w,x,y);
 	SDL_BlitSurface(src,NULL,dst,&pom);
 	SDL_BlitSurface(src,NULL,dst,&pom);
 }
 }

+ 32 - 1
client/Client.cpp

@@ -156,7 +156,7 @@ CClient::CClient(CConnection *con, StartInfo *si)
 			playerint[color]->init(cb);
 			playerint[color]->init(cb);
 		}
 		}
 	}
 	}
-	CGI->consoleh->cb = new CCallback(gs,-1,this);
+	cb = CGI->consoleh->cb = new CCallback(gs,-1,this);
 }
 }
 CClient::~CClient(void)
 CClient::~CClient(void)
 {
 {
@@ -220,6 +220,15 @@ void CClient::process(int what)
 			playerint[gs->getHero(sps.id)->tempOwner]->heroPrimarySkillChanged(gs->getHero(sps.id),sps.which,sps.val);
 			playerint[gs->getHero(sps.id)->tempOwner]->heroPrimarySkillChanged(gs->getHero(sps.id),sps.which,sps.val);
 			break;
 			break;
 		}
 		}
+	case 106:
+		{
+			SetSecSkill sr;
+			*serv >> sr;
+			std::cout << "Changing hero secondary skill"<<std::endl;
+			gs->apply(&sr);
+			//TODO? - maybe inform interfaces
+			break;
+		}
 	case 107:
 	case 107:
 		{
 		{
 			ShowInInfobox sii;
 			ShowInInfobox sii;
@@ -331,6 +340,28 @@ void CClient::process(int what)
 			gs->mx->unlock();
 			gs->mx->unlock();
 			break;
 			break;
 		}
 		}
+	case 2000:
+		{
+			HeroLevelUp  bs;
+			*serv >> bs;
+			std::cout << "Hero levels up!" <<std::endl;
+			gs->apply(&bs);
+			CGHeroInstance *h = gs->getHero(bs.heroid);
+			if(vstd::contains(playerint,h->tempOwner))
+				playerint[h->tempOwner]->heroGotLevel(h,bs.primskill,bs.skills,boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,cb,_1,bs.id)));
+			break;
+		}
+	case 2001:
+		{
+			SelectionDialog sd;
+			*serv >> sd;
+			std::cout << "Showing selection dialog " <<std::endl;
+			std::vector<Component*> comps;
+			for(int i=0;i<sd.components.size();i++)
+				comps.push_back(&sd.components[i]);
+			playerint[sd.player]->showSelDialog(toString(sd.text),comps,sd.id);
+			break;
+		}
 	case 3000:
 	case 3000:
 		{
 		{
 			BattleStart bs;
 			BattleStart bs;

+ 1 - 0
client/Client.h

@@ -35,6 +35,7 @@ struct CSharedCond
 
 
 class CClient
 class CClient
 {
 {
+	CCallback *cb;
 	CGameState *gs;
 	CGameState *gs;
 	std::map<ui8,CGameInterface *> playerint;
 	std::map<ui8,CGameInterface *> playerint;
 	CConnection *serv;
 	CConnection *serv;

+ 1 - 0
client/Graphics.cpp

@@ -174,6 +174,7 @@ Graphics::Graphics()
 	tasks += GET_DEF_ESS(halls,"ITMTLS.DEF");
 	tasks += GET_DEF_ESS(halls,"ITMTLS.DEF");
 	tasks += GET_DEF_ESS(bigTownPic,"ITPT.DEF");
 	tasks += GET_DEF_ESS(bigTownPic,"ITPT.DEF");
 	tasks += GET_DEF(pskillsb,"PSKILL.DEF");
 	tasks += GET_DEF(pskillsb,"PSKILL.DEF");
+	tasks += GET_DEF(pskillsm,"PSKIL42.DEF");
 	tasks += GET_DEF(resources,"RESOUR82.DEF");
 	tasks += GET_DEF(resources,"RESOUR82.DEF");
 	tasks += GET_DEF(un44,"UN44.DEF");
 	tasks += GET_DEF(un44,"UN44.DEF");
 	tasks += GET_DEF(smallIcons,"ITPA.DEF");
 	tasks += GET_DEF(smallIcons,"ITPA.DEF");

+ 1 - 0
client/Graphics.h

@@ -26,6 +26,7 @@ public:
 	std::vector<SDL_Surface *> portraitLarge; //58x64 px portraits of heroes
 	std::vector<SDL_Surface *> portraitLarge; //58x64 px portraits of heroes
 	std::vector<CDefHandler *> flags1, flags2, flags3, flags4; //flags blitted on heroes when ,
 	std::vector<CDefHandler *> flags1, flags2, flags3, flags4; //flags blitted on heroes when ,
 	CDefHandler * pskillsb, *resources; //82x93
 	CDefHandler * pskillsb, *resources; //82x93
+	CDefHandler * pskillsm; //42x42
 	CDefHandler * un44; //many things
 	CDefHandler * un44; //many things
 	CDefHandler * smallIcons, *resources32; //resources 32x32
 	CDefHandler * smallIcons, *resources32; //resources 32x32
 	//creatures
 	//creatures

+ 1 - 0
client/VCMI_client.vcproj

@@ -39,6 +39,7 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
+				AdditionalOptions="/MP2"
 				Optimization="0"
 				Optimization="0"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				GeneratePreprocessedFile="0"
 				GeneratePreprocessedFile="0"

+ 2 - 2
config/cr_shots.txt

@@ -6,8 +6,8 @@
 18 PELFX.DEF 0
 18 PELFX.DEF 0
 19 PELFX.DEF 0
 19 PELFX.DEF 0
 29 CPRGRE.DEF 1
 29 CPRGRE.DEF 1
-34 PMAGX.DEF 1
-35 PMAGX.DEF 1
+34 PMAGEX.DEF 1
+35 PMAGEX.DEF 1
 41 SMBALX.DEF 0
 41 SMBALX.DEF 0
 44 CPRGOGX.DEF 1
 44 CPRGOGX.DEF 1
 45 CPRGOGX.DEF 1
 45 CPRGOGX.DEF 1

+ 6 - 1
global.h

@@ -16,7 +16,7 @@ typedef boost::int8_t si8; //signed int 8 bits (1 byte)
 #define THC
 #define THC
 #endif
 #endif
 
 
-#define NAME_VER ("VCMI \"Altanatse\" 0.7")
+#define NAME_VER ("VCMI 0.62")
 
 
 
 
 #ifdef _WIN32
 #ifdef _WIN32
@@ -97,6 +97,11 @@ namespace vstd
 	{
 	{
 		return std::find(c.begin(),c.end(),i) != c.end();
 		return std::find(c.begin(),c.end(),i) != c.end();
 	}
 	}
+	template <typename V, typename Item>
+	bool contains(const std::map<Item,V> & c, const Item &i)
+	{
+		return c.find(i)!=c.end();
+	}
 	template <typename Container, typename Item>
 	template <typename Container, typename Item>
 	typename Container::iterator find(const Container & c, const Item &i)
 	typename Container::iterator find(const Container & c, const Item &i)
 	{
 	{

+ 4 - 3
hch/CAbilityHandler.cpp

@@ -17,10 +17,11 @@ void CAbilityHandler::loadAbilities()
 	for (int i=0; i<SKILL_QUANTITY; i++)
 	for (int i=0; i<SKILL_QUANTITY; i++)
 	{
 	{
 		CAbility * nab = new CAbility; //new skill, that will be read
 		CAbility * nab = new CAbility; //new skill, that will be read
+		nab->infoTexts.resize(3);
 		loadToIt(nab->name,buf,it,4);
 		loadToIt(nab->name,buf,it,4);
-		loadToIt(nab->basicText,buf,it,4);
-		loadToIt(nab->advText,buf,it,4);
-		loadToIt(nab->expText,buf,it,3);
+		loadToIt(nab->infoTexts[0],buf,it,4);
+		loadToIt(nab->infoTexts[1],buf,it,4);
+		loadToIt(nab->infoTexts[2],buf,it,3);
 		nab->idNumber = abilities.size();
 		nab->idNumber = abilities.size();
 		abilities.push_back(nab);
 		abilities.push_back(nab);
 	}
 	}

+ 1 - 3
hch/CAbilityHandler.h

@@ -10,9 +10,7 @@ class CAbility
 {
 {
 public:
 public:
 	std::string name;
 	std::string name;
-	std::string basicText;
-	std::string advText;
-	std::string expText;
+	std::vector <std::string> infoTexts; //0 - basic; 2 - advanced
 	int idNumber;
 	int idNumber;
 	bool isAllowed; //true if we can use this hero's ability (map information)
 	bool isAllowed; //true if we can use this hero's ability (map information)
 };
 };

+ 2 - 2
hch/CObjectHandler.h

@@ -54,8 +54,8 @@ public:
 	unsigned char animPhaseShift;
 	unsigned char animPhaseShift;
 	std::string hoverName;
 	std::string hoverName;
 
 
-	int tempOwner; //uzywane dla szybkosci, skrypt ma obowiazek aktualizowac te zmienna
-	int blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile
+	ui8 tempOwner; //uzywane dla szybkosci, skrypt ma obowiazek aktualizowac te zmienna
+	ui8 blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile
 
 
 	virtual bool isHero() const;
 	virtual bool isHero() const;
 	int getOwner() const;
 	int getOwner() const;

+ 36 - 4
lib/NetPacks.h

@@ -25,6 +25,11 @@ template <typename T> struct CPack
 	ui16 getType() const{return type;}
 	ui16 getType() const{return type;}
 	T* This(){return static_cast<T*>(this);};
 	T* This(){return static_cast<T*>(this);};
 };
 };
+template <typename T> struct Query
+	:public CPack<T>
+{
+	ui32 id;
+};
 struct SetResources : public CPack<SetResources> //104
 struct SetResources : public CPack<SetResources> //104
 {
 {
 	SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;};
 	SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;};
@@ -60,6 +65,18 @@ struct SetPrimSkill : public CPack<SetPrimSkill> //105
 		h & abs & id & which & val;
 		h & abs & id & which & val;
 	}
 	}
 }; 
 }; 
+struct SetSecSkill : public CPack<SetSecSkill> //106
+{
+	SetSecSkill(){type = 106;};
+	ui8 abs; //0 - changes by value; 1 - sets to value
+	si32 id;
+	ui16 which, val;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & abs & id & which & val;
+	}
+}; 
 struct RemoveHero : public CPack<RemoveHero> //500
 struct RemoveHero : public CPack<RemoveHero> //500
 {
 {
 	RemoveHero(){type = 500;};
 	RemoveHero(){type = 500;};
@@ -239,19 +256,34 @@ struct SetHoverName : public CPack<SetHoverName>//1002
 		h & id & name;
 		h & id & name;
 	}
 	}
 };
 };
-struct HeroLevelUp : public CPack<HeroLevelUp>//2000
+struct HeroLevelUp : public Query<HeroLevelUp>//2000
 {
 {
-	si32 id;
+	si32 heroid;
 	ui8 primskill, level;
 	ui8 primskill, level;
-	std::set<ui16> skills;
+	std::vector<ui16> skills;
 
 
 	HeroLevelUp(){type = 2000;};
 	HeroLevelUp(){type = 2000;};
 	
 	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
-		h & id & primskill & level & skills;
+		h & id & heroid & primskill & level & skills;
 	}
 	}
 };
 };
+
+struct SelectionDialog : public Query<SelectionDialog>//2001
+{
+	MetaString text;
+	std::vector<Component> components;
+	ui8 player;
+
+	SelectionDialog(){type = 2001;};
+	
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & id & text & components & player;
+	}
+};
+
 struct BattleInfo;
 struct BattleInfo;
 struct BattleStart : public CPack<BattleStart>//3000
 struct BattleStart : public CPack<BattleStart>//3000
 {
 {

+ 1 - 0
lib/VCMI_lib.vcproj

@@ -39,6 +39,7 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
+				AdditionalOptions="/MP2"
 				Optimization="0"
 				Optimization="0"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				MinimalRebuild="true"
 				MinimalRebuild="true"

+ 0 - 1
mapHandler.cpp

@@ -7,7 +7,6 @@
 #include "hch/CDefObjInfoHandler.h"
 #include "hch/CDefObjInfoHandler.h"
 #include <algorithm>
 #include <algorithm>
 #include "CGameState.h"
 #include "CGameState.h"
-#include "CLua.h"
 #include "hch/CHeroHandler.h"
 #include "hch/CHeroHandler.h"
 #include "hch/CTownHandler.h"
 #include "hch/CTownHandler.h"
 #include "client/Graphics.h"
 #include "client/Graphics.h"

+ 142 - 28
server/CGameHandler.cpp

@@ -32,14 +32,15 @@ extern bool end2;
 #define NEW_ROUND 		BattleNextRound bnr;\
 #define NEW_ROUND 		BattleNextRound bnr;\
 		bnr.round = gs->curB->round + 1;\
 		bnr.round = gs->curB->round + 1;\
 		sendAndApply(&bnr);
 		sendAndApply(&bnr);
-boost::condition_variable cTurn;
-boost::mutex mTurn;
-boost::shared_mutex gsm;
 
 
+boost::mutex gsm;
+ui32 CGameHandler::QID = 1;
 
 
 CondSh<bool> battleMadeAction;
 CondSh<bool> battleMadeAction;
 CondSh<BattleResult *> battleResult(NULL);
 CondSh<BattleResult *> battleResult(NULL);
 
 
+std::map<ui32, boost::function<void(ui32)> > callbacks; //question id => callback function - for selection dialogs
+
 class CMP_stack
 class CMP_stack
 {
 {
 public:
 public:
@@ -64,7 +65,86 @@ double distance(int3 a, int3 b)
 //	}
 //	}
 //	return false;
 //	return false;
 //}
 //}
-
+PlayerStatus PlayerStatuses::operator[](ui8 player)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	if(players.find(player) != players.end())
+	{
+		return players[player];
+	}
+	else
+	{
+		throw std::string("No such player!");
+	}
+}
+void PlayerStatuses::addPlayer(ui8 player)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	players[player];
+}
+bool PlayerStatuses::hasQueries(ui8 player)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	if(players.find(player) != players.end())
+	{
+		return players[player].queries.size();
+	}
+	else
+	{
+		throw std::string("No such player!");
+	}
+}
+bool PlayerStatuses::checkFlag(ui8 player, bool PlayerStatus::*flag)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	if(players.find(player) != players.end())
+	{
+		return players[player].*flag;
+	}
+	else
+	{
+		throw std::string("No such player!");
+	}
+}
+void PlayerStatuses::setFlag(ui8 player, bool PlayerStatus::*flag, bool val)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	if(players.find(player) != players.end())
+	{
+		players[player].*flag = val;
+	}
+	else
+	{
+		throw std::string("No such player!");
+	}
+	cv.notify_all();
+}
+void PlayerStatuses::addQuery(ui8 player, ui32 id)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	if(players.find(player) != players.end())
+	{
+		players[player].queries.insert(id);
+	}
+	else
+	{
+		throw std::string("No such player!");
+	}
+	cv.notify_all();
+}
+void PlayerStatuses::removeQuery(ui8 player, ui32 id)
+{
+	boost::unique_lock<boost::mutex> l(mx);
+	if(players.find(player) != players.end())
+	{
+		players[player].queries.erase(id);
+	}
+	else
+	{
+		throw std::string("No such player!");
+	}
+	cv.notify_all();
+}
 void CGameHandler::handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script)
 void CGameHandler::handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script)
 {
 {
 	std::vector<int> tempv = script->yourObjects();
 	std::vector<int> tempv = script->yourObjects();
@@ -74,6 +154,21 @@ void CGameHandler::handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObj
 	}
 	}
 	cppscripts.insert(script);
 	cppscripts.insert(script);
 }
 }
+template <typename T>
+void callWith(std::vector<T> args, boost::function<void(T)> fun, ui32 which)
+{
+	fun(args[which]);
+}
+
+void CGameHandler::changeSecSkill(int ID, ui16 which, int val, bool abs)
+{
+	SetSecSkill sps;
+	sps.id = ID;
+	sps.which = which;
+	sps.abs = abs;
+	sps.val = val;
+	sendAndApply(&sps);
+}
 
 
 void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 {
 {
@@ -83,13 +178,11 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 	sps.abs = abs;
 	sps.abs = abs;
 	sps.val = val;
 	sps.val = val;
 	sendAndApply(&sps);
 	sendAndApply(&sps);
-	if(which==4)
+	if(which==4) //only for exp - hero may level up
 	{
 	{
 		CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID]);
 		CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID]);
 		if(hero->exp >= VLC->heroh->reqExp(hero->level+1)) //new level
 		if(hero->exp >= VLC->heroh->reqExp(hero->level+1)) //new level
 		{
 		{
-			//hero->level++;
-
 			//give prim skill
 			//give prim skill
 			std::cout << hero->name <<" got level "<<hero->level<<std::endl;
 			std::cout << hero->name <<" got level "<<hero->level<<std::endl;
 			int r = rand()%100, pom=0, x=0;
 			int r = rand()%100, pom=0, x=0;
@@ -107,10 +200,13 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 			sps.abs = false;
 			sps.abs = false;
 			sps.val = 1;
 			sps.val = 1;
 			sendAndApply(&sps);
 			sendAndApply(&sps);
-			hero->primSkills[x]++;
 
 
-			std::set<ui16> choice;
+			HeroLevelUp hlu;
+			hlu.heroid = ID;
+			hlu.primskill = x;
+			hlu.level = hero->level+1;
 
 
+			//picking sec. skills for choice
 			std::set<int> basicAndAdv, expert, none;
 			std::set<int> basicAndAdv, expert, none;
 			for(int i=0;i<SKILL_QUANTITY;i++) none.insert(i);
 			for(int i=0;i<SKILL_QUANTITY;i++) none.insert(i);
 			for(unsigned i=0;i<hero->secSkills.size();i++)
 			for(unsigned i=0;i<hero->secSkills.size();i++)
@@ -123,25 +219,24 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 			}
 			}
 			if(hero->secSkills.size() < hero->type->heroClass->skillLimit) //free skill slot
 			if(hero->secSkills.size() < hero->type->heroClass->skillLimit) //free skill slot
 			{
 			{
-				choice.insert(hero->type->heroClass->chooseSecSkill(none)); //new skill
+				hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(none)); //new skill
 			}
 			}
 			else
 			else
 			{
 			{
 				int s = hero->type->heroClass->chooseSecSkill(basicAndAdv);
 				int s = hero->type->heroClass->chooseSecSkill(basicAndAdv);
-				choice.insert(s);
+				hlu.skills.push_back(s);
 				basicAndAdv.erase(s);
 				basicAndAdv.erase(s);
 			}
 			}
 			if(basicAndAdv.size())
 			if(basicAndAdv.size())
 			{
 			{
-				choice.insert(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //new skill
+				hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //new skill
 			}
 			}
 			else if(hero->secSkills.size() < hero->type->heroClass->skillLimit)
 			else if(hero->secSkills.size() < hero->type->heroClass->skillLimit)
 			{
 			{
-				choice.insert(hero->type->heroClass->chooseSecSkill(none)); //new skill
+				hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(none)); //new skill
 			}
 			}
-
+			applyAndAsk(&hlu,hero->tempOwner,boost::function<void(ui32)>(boost::bind(callWith<ui16>,hlu.skills,boost::function<void(ui16)>(boost::bind(&CGameHandler::changeSecSkill,this,ID,_1,1,0)),_1))); //call changeSecSkill with appropriate args when client responds
 		}
 		}
-		//TODO - powiadomic interfejsy, sprawdzic czy nie ma awansu itp
 	}
 	}
 }
 }
 
 
@@ -154,10 +249,12 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
 		battleResult.set(NULL);
 		battleResult.set(NULL);
 		std::vector<CStack*> & stacks = (curB->stacks);
 		std::vector<CStack*> & stacks = (curB->stacks);
 
 
+		curB->tile = tile;
+		curB->siege = 0; //TODO: add sieges
 		curB->army1=army1;
 		curB->army1=army1;
 		curB->army2=army2;
 		curB->army2=army2;
 		curB->hero1=(hero1)?(hero1->id):(-1);
 		curB->hero1=(hero1)?(hero1->id):(-1);
-		curB->hero2=(hero1)?(hero1->id):(-1);
+		curB->hero2=(hero2)?(hero2->id):(-1);
 		curB->side1=(hero1)?(hero1->tempOwner):(-1);
 		curB->side1=(hero1)?(hero1->tempOwner):(-1);
 		curB->side2=(hero2)?(hero2->tempOwner):(-1);
 		curB->side2=(hero2)?(hero2->tempOwner):(-1);
 		curB->round = -2;
 		curB->round = -2;
@@ -283,9 +380,9 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
 
 
 		//block engaged players
 		//block engaged players
 		if(hero1->tempOwner<PLAYER_LIMIT)
 		if(hero1->tempOwner<PLAYER_LIMIT)
-			states[hero1->tempOwner] += 10;
+			states.setFlag(hero1->tempOwner,&PlayerStatus::engagedIntoBattle,true);
 		if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
 		if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
-			states[hero2->tempOwner] += 10;
+			states.setFlag(hero2->tempOwner,&PlayerStatus::engagedIntoBattle,true);
 
 
 		//send info about battles
 		//send info about battles
 		BattleStart bs;
 		BattleStart bs;
@@ -329,6 +426,12 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
 		}
 		}
 	}
 	}
 
 
+	//unblock engaged players
+	if(hero1->tempOwner<PLAYER_LIMIT)
+		states.setFlag(hero1->tempOwner,&PlayerStatus::engagedIntoBattle,false);
+	if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
+		states.setFlag(hero2->tempOwner,&PlayerStatus::engagedIntoBattle,false);
+
 	//end battle, remove all info, free memory
 	//end battle, remove all info, free memory
 	sendAndApply(battleResult.data);
 	sendAndApply(battleResult.data);
 	delete battleResult.data;
 	delete battleResult.data;
@@ -380,10 +483,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 			{
 			{
 			case 100: //my interface ended its turn
 			case 100: //my interface ended its turn
 				{
 				{
-					mTurn.lock();
-					states[gs->currentPlayer] = 0;
-					mTurn.unlock();
-					cTurn.notify_all();
+					states.setFlag(gs->currentPlayer,&PlayerStatus::makingTurn,false);
 					break;
 					break;
 				}
 				}
 			case 500:
 			case 500:
@@ -444,7 +544,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 								//if(gs->checkFunc(obj->ID,"heroVisit")) //script function
 								//if(gs->checkFunc(obj->ID,"heroVisit")) //script function
 								//	gs->objscr[obj->ID]["heroVisit"]->onHeroVisit(obj,h->subID);
 								//	gs->objscr[obj->ID]["heroVisit"]->onHeroVisit(obj,h->subID);
 								if(obj->state) //hard-coded function
 								if(obj->state) //hard-coded function
-									obj->state->onHeroVisit(obj->id,h->subID);
+									obj->state->onHeroVisit(obj->id,h->id);
 							}
 							}
 						}
 						}
 						break;
 						break;
@@ -457,7 +557,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 						{
 						{
 							//TODO: allow to handle this in script-languages
 							//TODO: allow to handle this in script-languages
 							if(obj->state) //hard-coded function
 							if(obj->state) //hard-coded function
-								obj->state->onHeroLeave(obj->id,h->subID);
+								obj->state->onHeroLeave(obj->id,h->id);
 						}
 						}
 
 
 						//reveal fog of war
 						//reveal fog of war
@@ -664,6 +764,17 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					sendAndApply(&sg);
 					sendAndApply(&sg);
 					break;
 					break;
 				}
 				}
+			case 2001:
+				{
+					ui32 qid, answer;
+					c >> qid >> answer;
+					gsm.lock();
+					boost::function<void(ui32)> callb = callbacks[qid];
+					callbacks.erase(qid);
+					gsm.unlock();
+					callb(answer);
+					break;
+				}
 			case 3002:
 			case 3002:
 				{			
 				{			
 					BattleAction ba;
 					BattleAction ba;
@@ -949,6 +1060,8 @@ void CGameHandler::run()
 		//if(checkFunc(map->objects[i]->ID,temps))
 		//if(checkFunc(map->objects[i]->ID,temps))
 		//	(*skrypty)[map->objects[i]->ID][temps]->newObject(map->objects[i]);
 		//	(*skrypty)[map->objects[i]->ID][temps]->newObject(map->objects[i]);
 	}
 	}
+	for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
+		states.addPlayer(i->first);
 
 
 	while (!end2)
 	while (!end2)
 	{
 	{
@@ -956,17 +1069,18 @@ void CGameHandler::run()
 		for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
 		for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
 		{
 		{
 			if((i->second.towns.size()==0 && i->second.heroes.size()==0)  || i->second.color<0 || i->first>=PLAYER_LIMIT  ) continue; //players has not towns/castle - loser
 			if((i->second.towns.size()==0 && i->second.heroes.size()==0)  || i->second.color<0 || i->first>=PLAYER_LIMIT  ) continue; //players has not towns/castle - loser
-			states[i->first] = 1;
+			states.setFlag(i->first,&PlayerStatus::makingTurn,true);
 			gs->currentPlayer = i->first;
 			gs->currentPlayer = i->first;
 			*connections[i->first] << ui16(100) << i->first;    
 			*connections[i->first] << ui16(100) << i->first;    
+
 			//wait till turn is done
 			//wait till turn is done
-			boost::unique_lock<boost::mutex> lock(mTurn);
-			while(states[i->first] && !end2)
+			boost::unique_lock<boost::mutex> lock(states.mx);
+			while(states.players[i->first].makingTurn && !end2)
 			{
 			{
 				boost::posix_time::time_duration p;
 				boost::posix_time::time_duration p;
 				p= boost::posix_time::seconds(1);
 				p= boost::posix_time::seconds(1);
 #ifdef _MSC_VER
 #ifdef _MSC_VER
-				cTurn.timed_wait(lock,p); 
+				states.cv.timed_wait(lock,p); 
 #else
 #else
 				boost::xtime time={0,0};
 				boost::xtime time={0,0};
 				time.sec = static_cast<boost::xtime::xtime_sec_t>(p.total_seconds());
 				time.sec = static_cast<boost::xtime::xtime_sec_t>(p.total_seconds());

+ 49 - 5
server/CGameHandler.h

@@ -3,31 +3,54 @@
 #include <set>
 #include <set>
 #include "../CGameState.h"
 #include "../CGameState.h"
 #include "../lib/Connection.h"
 #include "../lib/Connection.h"
-#ifndef _MSC_VER
+#include <boost/function.hpp>
 #include <boost/thread.hpp>
 #include <boost/thread.hpp>
-#endif
 class CVCMIServer;
 class CVCMIServer;
 class CGameState;
 class CGameState;
-//class CConnection;
 struct StartInfo;
 struct StartInfo;
 class CCPPObjectScript;
 class CCPPObjectScript;
 class CScriptCallback;
 class CScriptCallback;
 template <typename T> struct CPack;
 template <typename T> struct CPack;
+template <typename T> struct Query;
 class CGHeroInstance;
 class CGHeroInstance;
+extern std::map<ui32, boost::function<void(ui32)> > callbacks; //question id => callback function - for selection dialogs
+extern boost::mutex gsm;
+
+struct PlayerStatus
+{
+	bool makingTurn, engagedIntoBattle;
+	std::set<ui32> queries;
+	PlayerStatus():makingTurn(false),engagedIntoBattle(false){};
+};
+class PlayerStatuses
+{
+public:
+	std::map<ui8,PlayerStatus> players;
+	boost::mutex mx;
+	boost::condition_variable cv; //notifies when any changes are made
+	void addPlayer(ui8 player);
+	PlayerStatus operator[](ui8 player);
+	bool hasQueries(ui8 player);
+	bool checkFlag(ui8 player, bool PlayerStatus::*flag);
+	void setFlag(ui8 player, bool PlayerStatus::*flag, bool val);
+	void addQuery(ui8 player, ui32 id);
+	void removeQuery(ui8 player, ui32 id);
+};
 class CGameHandler
 class CGameHandler
 {
 {
-
+	static ui32 QID;
 	CGameState *gs;
 	CGameState *gs;
 	std::set<CCPPObjectScript *> cppscripts; //C++ scripts
 	std::set<CCPPObjectScript *> cppscripts; //C++ scripts
 	//std::map<int, std::map<std::string, CObjectScript*> > objscr; //non-C++ scripts 
 	//std::map<int, std::map<std::string, CObjectScript*> > objscr; //non-C++ scripts 
 
 
 	CVCMIServer *s;
 	CVCMIServer *s;
 	std::map<int,CConnection*> connections; //player color -> connection to clinet with interface of that player
 	std::map<int,CConnection*> connections; //player color -> connection to clinet with interface of that player
-	std::map<int,int> states; //player color -> player state
+	PlayerStatuses states; //player color -> player state
 	std::set<CConnection*> conns;
 	std::set<CConnection*> conns;
 
 
 	void handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script);
 	void handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script);
 	void changePrimSkill(int ID, int which, int val, bool abs=false);
 	void changePrimSkill(int ID, int which, int val, bool abs=false);
+	void changeSecSkill(int ID, ui16 which, int val, bool abs=false);
 	void moveStack(int stack, int dest);
 	void moveStack(int stack, int dest);
 	void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero
 	void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero
 
 
@@ -37,6 +60,27 @@ public:
 	~CGameHandler(void);
 	~CGameHandler(void);
 	void init(StartInfo *si, int Seed);
 	void init(StartInfo *si, int Seed);
 	void handleConnection(std::set<int> players, CConnection &c);
 	void handleConnection(std::set<int> players, CConnection &c);
+	template <typename T> void applyAndAsk(Query<T> * sel, ui8 player, boost::function<void(ui32)> &callback)
+	{
+		gsm.lock();
+		sel->id = QID;
+		callbacks[QID] = callback;
+		states.addQuery(player,QID);
+		QID++; 
+		sendAndApply(sel);
+		gsm.unlock();
+	}
+	template <typename T> void ask(Query<T> * sel, ui8 player, boost::function<void(ui32)> &callback)
+	{
+		gsm.lock();
+		sel->id = QID;
+		callbacks[QID] = callback;
+		states.addQuery(player,QID);
+		sendToAllClients(sel);
+		QID++; 
+		gsm.unlock();
+	}
+
 	template <typename T>void sendToAllClients(CPack<T> * info)
 	template <typename T>void sendToAllClients(CPack<T> * info)
 	{
 	{
 		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
 		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)

+ 5 - 22
server/CScriptCallback.cpp

@@ -12,6 +12,8 @@
 #include <boost/bind.hpp>
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
 #include <boost/foreach.hpp>
 #include <boost/thread.hpp>
 #include <boost/thread.hpp>
+
+
 CScriptCallback::CScriptCallback(void)
 CScriptCallback::CScriptCallback(void)
 {
 {
 }
 }
@@ -62,32 +64,13 @@ int CScriptCallback::getHeroOwner(int heroID)
 void CScriptCallback::showInfoDialog(InfoWindow *iw)
 void CScriptCallback::showInfoDialog(InfoWindow *iw)
 {
 {
 	gh->sendToAllClients(iw);
 	gh->sendToAllClients(iw);
-	//TODO: upewniac sie ze mozemy to zrzutowac (przy customowych interfejsach cos moze sie kopnac)
-	//if (player>=0)
-	//{
-	//	CGameInterface * temp = sv->playerint[player];
-	//	if (temp->human)
-	//		((CPlayerInterface*)(temp))->showInfoDialog(text,*components);
-	//	return;
-	//}
-	//else
-	//{
-	//	typedef std::pair<const ui8, CGameInterface*> intf;
-	//	BOOST_FOREACH(intf & i, sv->playerint)
-	//	{
-	//		if (i.second->human)
-	//			((CPlayerInterface*)(i.second))->showInfoDialog(text,*components);
-	//	}
-	//}
 }
 }
 
 
-void CScriptCallback::showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker)
+void CScriptCallback::showSelectionDialog(SelectionDialog *iw, boost::function<void(ui32),std::allocator<void> > &callback)
 {
 {
-	//CGameInterface * temp = sv->playerint[player];
-	//if (temp->human)
-	//	((CPlayerInterface*)(temp))->showSelDialog(text,*components,(int)asker);
-	return;
+	gh->ask(iw,iw->player,callback);
 }
 }
+
 int CScriptCallback::getSelectedHero()
 int CScriptCallback::getSelectedHero()
 {	
 {	
 	//int ret;
 	//int ret;

+ 3 - 1
server/CScriptCallback.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 #include "../global.h"
 #include "../global.h"
 #include <vector>
 #include <vector>
+#include <boost/function.hpp>
 class CVCMIServer;
 class CVCMIServer;
 class CGameHandler;
 class CGameHandler;
 class SComponent;
 class SComponent;
@@ -16,6 +17,7 @@ struct lua_State;
 struct MetaString;
 struct MetaString;
 struct InfoWindow;
 struct InfoWindow;
 struct ShowInInfobox;
 struct ShowInInfobox;
+struct SelectionDialog;
 class CScriptCallback
 class CScriptCallback
 {
 {
 	CScriptCallback(void);
 	CScriptCallback(void);
@@ -38,7 +40,7 @@ public:
 	void setHoverName(int objid, MetaString * name);
 	void setHoverName(int objid, MetaString * name);
 	void changePrimSkill(int ID, int which, int val, bool abs=false);
 	void changePrimSkill(int ID, int which, int val, bool abs=false);
 	void showInfoDialog(InfoWindow *iw);
 	void showInfoDialog(InfoWindow *iw);
-	void showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker);
+	void showSelectionDialog(SelectionDialog *iw, boost::function<void(ui32),std::allocator<void> > &callback); //returns question id
 	void giveResource(int player, int which, int val);
 	void giveResource(int player, int which, int val);
 	void showCompInfo(ShowInInfobox * comp);
 	void showCompInfo(ShowInInfobox * comp);
 	void heroVisitCastle(int obj, int heroID);
 	void heroVisitCastle(int obj, int heroID);

+ 2 - 1
server/VCMI_server.vcproj

@@ -39,8 +39,9 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
+				AdditionalOptions="/MP2"
 				Optimization="0"
 				Optimization="0"
-				MinimalRebuild="true"
+				MinimalRebuild="false"
 				BasicRuntimeChecks="3"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
 				RuntimeLibrary="3"
 				WarningLevel="2"
 				WarningLevel="2"