Sfoglia il codice sorgente

* upgrading creatures
* splitted map loading on several functions
* buttons can call multiple functions when pressed
* minor

Michał W. Urbańczyk 17 anni fa
parent
commit
b83b80a71e
19 ha cambiato i file con 1382 aggiunte e 651 eliminazioni
  1. 55 49
      AdventureMapButton.cpp
  2. 5 2
      AdventureMapButton.h
  3. 2 35
      CCallback.cpp
  4. 0 7
      CCallback.h
  5. 3 4
      CGameInterface.h
  6. 37 0
      CGameState.cpp
  7. 9 0
      CGameState.h
  8. 1 0
      CHeroWindow.cpp
  9. 109 111
      CMessage.cpp
  10. 4 4
      CMessage.h
  11. 105 76
      CPlayerInterface.cpp
  12. 14 8
      CPlayerInterface.h
  13. 36 0
      client/FunctionList.h
  14. 4 4
      client/VCMI_client.vcproj
  15. 0 8
      lib/VCMI_lib.vcproj
  16. 788 194
      map.cpp
  17. 13 0
      map.h
  18. 196 148
      server/CGameHandler.cpp
  19. 1 1
      server/CGameHandler.h

+ 55 - 49
AdventureMapButton.cpp

@@ -16,54 +16,13 @@ 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 )
+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)
 {
-	callback = Callback;
-	actOnDown = false;
-	type=2;
-	abs=true;
-	active=false;
-	ourObj=NULL;
-	state=0;
-	name=Name;
-	helpBox=HelpBox;
-	colorChange = playerColoredButton;
-	int est = LOCPLINT->playerID;
-	CDefHandler * temp = CDefHandler::giveDef(defName); 
-	temp->notFreeImgs = true;
-	for (int i=0;i<temp->ourImages.size();i++)
-	{
-		imgs.resize(1);
-		imgs[0].push_back(temp->ourImages[i].bitmap);
-		if(playerColoredButton)
-			graphics->blueToPlayersAdv(imgs[curimg][i],LOCPLINT->playerID);
-	}
-	delete temp;
-	if (add)
-	{
-		imgs.resize(imgs.size()+add->size());
-		for (int i=0; i<add->size();i++)
-		{
-			temp = CDefHandler::giveDef((*add)[i]);
-			temp->notFreeImgs = true;
-			for (int j=0;j<temp->ourImages.size();j++)
-			{
-				imgs[i+1].push_back(temp->ourImages[j].bitmap);
-				if(playerColoredButton)
-					graphics->blueToPlayersAdv(imgs[1+i][j],LOCPLINT->playerID);
-			}
-			delete temp;
-		}
-		delete add;
-	}
-	pos.x=x;
-	pos.y=y;
-	pos.w = imgs[curimg][0]->w;
-	pos.h = imgs[curimg][0]->h  -1;
-	if (activ)
-		activate();
+	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);
 }
 
 
@@ -81,13 +40,13 @@ void AdventureMapButton::clickLeft (tribool down)
 	if (actOnDown && down)
 	{
 		pressedL=state;
-		if(!callback.empty())
+		//if(!callback.empty())
 			callback();
 	}
 	else if (pressedL && (down==false))
 	{
 		pressedL=state;
-		if(!callback.empty())
+		//if(!callback.empty())
 			callback();
 	}
 	else
@@ -139,6 +98,53 @@ void AdventureMapButton::deactivate()
 	KeyInterested::deactivate();
 }
 
+void AdventureMapButton::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 )
+{
+	callback = Callback;
+	actOnDown = false;
+	type=2;
+	abs=true;
+	active=false;
+	ourObj=NULL;
+	state=0;
+	name=Name;
+	helpBox=HelpBox;
+	colorChange = playerColoredButton;
+	int est = LOCPLINT->playerID;
+	CDefHandler * temp = CDefHandler::giveDef(defName); 
+	temp->notFreeImgs = true;
+	for (int i=0;i<temp->ourImages.size();i++)
+	{
+		imgs.resize(1);
+		imgs[0].push_back(temp->ourImages[i].bitmap);
+		if(playerColoredButton)
+			graphics->blueToPlayersAdv(imgs[curimg][i],LOCPLINT->playerID);
+	}
+	delete temp;
+	if (add)
+	{
+		imgs.resize(imgs.size()+add->size());
+		for (int i=0; i<add->size();i++)
+		{
+			temp = CDefHandler::giveDef((*add)[i]);
+			temp->notFreeImgs = true;
+			for (int j=0;j<temp->ourImages.size();j++)
+			{
+				imgs[i+1].push_back(temp->ourImages[j].bitmap);
+				if(playerColoredButton)
+					graphics->blueToPlayersAdv(imgs[1+i][j],LOCPLINT->playerID);
+			}
+			delete temp;
+		}
+		delete add;
+	}
+	pos.x=x;
+	pos.y=y;
+	pos.w = imgs[curimg][0]->w;
+	pos.h = imgs[curimg][0]->h  -1;
+	if (activ)
+		activate();
+}
 
 void CSlider::sliderClicked()
 {

+ 5 - 2
AdventureMapButton.h

@@ -1,6 +1,6 @@
 #pragma once
 #include "CPlayerInterface.h"
-#include <boost/function.hpp>
+#include "client/FunctionList.h"
 #include <boost/bind.hpp>
 class AdventureMapButton 
 	: public ClickableL, public ClickableR, public Hoverable, public KeyInterested, public CButtonBase
@@ -9,7 +9,7 @@ public:
 	std::string name; //for status bar 
 	std::string helpBox; //for right-click help
 	char key; //key shortcut
-	boost::function<void()> callback;
+	CFunctionList<void()> callback;
 	bool colorChange,
 		actOnDown; //runs when mouse is pressed down over it, not when up
 
@@ -21,7 +21,10 @@ public:
 	void deactivate(); // makes button inactive (but doesn't delete)
 
 	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
+
+	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 );
 };
 
 

+ 2 - 35
CCallback.cpp

@@ -124,7 +124,7 @@ bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos)
 }
 bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos, int newID)
 {
-	//TODO: write
+	*cl->serv << ui16(507) << obj->id <<  ui8(stackPos) << ui32(newID);
 	return false;
 }
 void CCallback::endTurn()
@@ -136,40 +136,7 @@ void CCallback::endTurn()
 }
 UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
 {
-	UpgradeInfo ret;
-	CCreature *base = &CGI->creh->creatures[((CArmedInstance *)obj)->army.slots[stackPos].first];
-	if((obj->ID == 98)  ||  ((obj->ID == 34) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
-	{
-		CGTownInstance * t;
-		if(obj->ID == 98)
-			t = static_cast<CGTownInstance *>(const_cast<CArmedInstance *>(obj));
-		else
-			t = static_cast<const CGHeroInstance*>(obj)->visitedTown;
-		for(std::set<si32>::iterator i=t->builtBuildings.begin();  i!=t->builtBuildings.end(); i++)
-		{
-			if( (*i) >= 37   &&   (*i) < 44 ) //upgraded creature dwelling
-			{
-				int nid = t->town->upgradedCreatures[(*i)-37]; //upgrade offered by that building
-				if(base->upgrades.find(nid) != base->upgrades.end()) //possible upgrade
-				{
-					ret.newID.push_back(nid);
-					ret.cost.push_back(std::set<std::pair<int,int> >());
-					for(int j=0;j<RESOURCE_QUANTITY;j++)
-					{
-						int dif = CGI->creh->creatures[nid].cost[j] - base->cost[j];
-						if(dif)
-							ret.cost[ret.cost.size()-1].insert(std::make_pair(j,dif));
-					}
-				}
-			}
-		}//end for
-	}
-	//TODO: check if hero ability makes some upgrades possible
-
-	if(ret.newID.size())
-		ret.oldID = base->idNumber;
-
-	return ret;
+	return gs->getUpgradeInfo(const_cast<CArmedInstance*>(obj),stackPos);
 }
 
 const StartInfo * CCallback::getStartInfo()

+ 0 - 7
CCallback.h

@@ -24,13 +24,6 @@ class CStack;
 struct lua_State;
 class CClient;
 //structure gathering info about upgrade possibilites
-struct UpgradeInfo
-{
-	int oldID; //creature to be upgraded
-	std::vector<int> newID; //possible upgrades
-	std::vector<std::set<std::pair<int,int> > > cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>
-	UpgradeInfo(){oldID = -1;};
-};
 
 class ICallback
 {

+ 3 - 4
CGameInterface.h

@@ -3,9 +3,8 @@
 #include "global.h"
 #include <set>
 #include <vector>
-#include <boost/function.hpp>
 #include "lib/BattleAction.h"
-BOOST_TRIBOOL_THIRD_STATE(outOfRange)
+#include "client/FunctionList.h"
 
 using namespace boost::logic;
 class CCallback;
@@ -55,8 +54,8 @@ public:
 	virtual void tileRevealed(int3 pos){};
 	virtual void tileHidden(int3 pos){};
 	virtual void receivedResource(int type, int val){};
-	virtual void showInfoDialog(std::string text, std::vector<Component*> &components){};
-	virtual void showSelDialog(std::string text, std::vector<Component*> &components, ui32 askID){};
+	virtual void showInfoDialog(std::string &text, std::vector<Component*> &components){};
+	virtual void showSelDialog(std::string &text, std::vector<Component*> &components, ui32 askID){};
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
 	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

+ 37 - 0
CGameState.cpp

@@ -1056,6 +1056,43 @@ int CGameState::battleGetStack(int pos)
 	return -1;
 }
 
+UpgradeInfo CGameState::getUpgradeInfo(CArmedInstance *obj, int stackPos)
+{
+	UpgradeInfo ret;
+	CCreature *base = &VLC->creh->creatures[obj->army.slots[stackPos].first];
+	if((obj->ID == 98)  ||  ((obj->ID == 34) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
+	{
+		CGTownInstance * t;
+		if(obj->ID == 98)
+			t = static_cast<CGTownInstance *>(const_cast<CArmedInstance *>(obj));
+		else
+			t = static_cast<const CGHeroInstance*>(obj)->visitedTown;
+		for(std::set<si32>::iterator i=t->builtBuildings.begin();  i!=t->builtBuildings.end(); i++)
+		{
+			if( (*i) >= 37   &&   (*i) < 44 ) //upgraded creature dwelling
+			{
+				int nid = t->town->upgradedCreatures[(*i)-37]; //upgrade offered by that building
+				if(base->upgrades.find(nid) != base->upgrades.end()) //possible upgrade
+				{
+					ret.newID.push_back(nid);
+					ret.cost.push_back(std::set<std::pair<int,int> >());
+					for(int j=0;j<RESOURCE_QUANTITY;j++)
+					{
+						int dif = VLC->creh->creatures[nid].cost[j] - base->cost[j];
+						if(dif)
+							ret.cost[ret.cost.size()-1].insert(std::make_pair(j,dif));
+					}
+				}
+			}
+		}//end for
+	}
+	//TODO: check if hero ability makes some upgrades possible
+
+	if(ret.newID.size())
+		ret.oldID = base->idNumber;
+
+	return ret;
+}
 int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender)
 {
 	int attackDefenseBonus = attacker->creature->attack - defender->creature->defence;

+ 9 - 0
CGameState.h

@@ -111,6 +111,14 @@ public:
 	}
 };
 
+struct UpgradeInfo
+{
+	int oldID; //creature to be upgraded
+	std::vector<int> newID; //possible upgrades
+	std::vector<std::set<std::pair<int,int> > > cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>
+	UpgradeInfo(){oldID = -1;};
+};
+
 class DLL_EXPORT CGameState
 {
 private:
@@ -141,6 +149,7 @@ private:
 	bool battleAttackCreatureStack(int ID, int dest);
 	bool battleShootCreatureStack(int ID, int dest);
 	int battleGetStack(int pos); //returns ID of stack at given tile
+	UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos);
 public:
 	int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 	

+ 1 - 0
CHeroWindow.cpp

@@ -1,4 +1,5 @@
 #include "stdafx.h"
+#include <cstdlib>
 #include "global.h"
 #include "CHeroWindow.h"
 #include "CGameInfo.h"

+ 109 - 111
CMessage.cpp

@@ -14,6 +14,7 @@
 #include <sstream>
 #include "hch/CGeneralTextHandler.h"
 #include "client/Graphics.h"
+#include "CAdvmapInterface.h"
 SDL_Color tytulowy, tlo, zwykly ;
 SDL_Rect genRect(int hh, int ww, int xx, int yy);
 
@@ -86,7 +87,7 @@ void CMessage::dispose()
 	delete ok;
 	delete cancel;
 }
-SDL_Surface * CMessage::drawBox1(int w, int h, int playerColor)
+SDL_Surface * CMessage::drawBox1(int w, int h, int playerColor) //draws box for window
 {
 	//prepare surface
 	SDL_Surface * ret = SDL_CreateRGBSurface(screen->flags, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
@@ -187,7 +188,7 @@ std::vector<std::string> * CMessage::breakText(std::string text, int line, bool
 	}
 	return ret;
 }
-std::pair<int, int> CMessage::getMaxSizes(std::vector< std::vector<CSelectableComponent*> > * komp)
+std::pair<int, int> CMessage::getMaxSizes(std::vector< std::vector<SComponent*> > * komp)
 {
 	std::pair<int,int> ret;
 	for (int i=0;i<komp->size();i++)
@@ -254,7 +255,6 @@ SDL_Surface * CMessage::blitCompsOnSur(std::vector<SComponent*> & comps, int max
 		brdtext = breakText(comps[0]->subtitle,12,true,true);
 	else
 		brdtext = NULL;
-	curh += 30;
 	comps[0]->pos.x = (ret->w/2) - ((comps[0]->getImg()->w)/2);
 	comps[0]->pos.y = curh;
 	blitAt(comps[0]->getImg(),comps[0]->pos.x,comps[0]->pos.y,ret);
@@ -268,7 +268,7 @@ SDL_Surface * CMessage::blitCompsOnSur(std::vector<SComponent*> & comps, int max
 	}
 	return ret;
 }
-SDL_Surface* CMessage::blitCompsOnSur(SDL_Surface * _or, std::vector< std::vector<CSelectableComponent*> > *  komp, int inter, int &curh, SDL_Surface *ret)
+SDL_Surface* CMessage::blitCompsOnSur(SDL_Surface * _or, std::vector< std::vector<SComponent*> > *  komp, int inter, int &curh, SDL_Surface *ret)
 {
 	for (int i=0;i<komp->size();i++)
 	{
@@ -279,7 +279,11 @@ SDL_Surface* CMessage::blitCompsOnSur(SDL_Surface * _or, std::vector< std::vecto
 			if(maxh<(*komp)[i][j]->getImg()->h)
 				maxh=(*komp)[i][j]->getImg()->h;
 		}
-		totalw += (inter*2+_or->w) * ((*komp)[i].size() - 1);
+		if(_or)
+			totalw += (inter*2+_or->w) * ((*komp)[i].size() - 1);
+		else
+			totalw += (inter) * ((*komp)[i].size() - 1);
+
 		curh+=maxh/2;
 		int curw = (ret->w/2)-(totalw/2);
 		for(int j=0;j<(*komp)[i].size();j++)
@@ -291,13 +295,17 @@ SDL_Surface* CMessage::blitCompsOnSur(SDL_Surface * _or, std::vector< std::vecto
 			curw += (*komp)[i][j]->getImg()->w;
 			if(j<((*komp)[i].size()-1))
 			{
-				curw+=inter;
-				blitAt(_or,curw,curh-(_or->h/2),ret);
-				curw+=_or->w;
+				if(_or)
+				{
+					curw+=inter;
+					blitAt(_or,curw,curh-(_or->h/2),ret);
+					curw+=_or->w;
+				}
 				curw+=inter;
 			}
 		}
 		curh+=maxh/2;
+		curh += 20; //todo: check subtitle length
 	}
 	return ret;
 }
@@ -347,79 +355,21 @@ CSimpleWindow * CMessage::genWindow(std::string text, int player, int Lmar, int
 	ret->bitmap = drawBox1(txts.first+Lmar+Rmar,txts.second+Tmar+Bmar,0);
 	ret->pos.h=ret->bitmap->h;
 	ret->pos.w=ret->bitmap->w;
-	for (int i=0; i<txtg->size();i++)
-	{
-		int lw=0;
-		for (int j=0;j<(*txtg)[i].size();j++)
-			lw+=(*txtg)[i][j]->w;
-		int pw = ret->bitmap->w/2, ph =  ret->bitmap->h/2;
-		//int pw = Tmar, ph = Lmar;
-		pw -= lw/2;
-		ph -= (19*txtg->size())/2;
-
-		int tw = pw;
-		for (int j=0;j<(*txtg)[i].size();j++)
-		{
-				//std::stringstream n;
-				//n <<"temp_"<<i<<"__"<<j<<".bmp";
-			blitAt((*txtg)[i][j],tw,ph+i*19,ret->bitmap);
-				//SDL_SaveBMP(ret->bitmap,n.str().c_str());
-			tw+=(*txtg)[i][j]->w;
-			SDL_FreeSurface((*txtg)[i][j]);
-		}
-	}
-	return ret;
-}
-
-CInfoWindow * CMessage::genIWindow(std::string text, int player, int charperline, std::vector<SComponent*> & comps)
-{
-	//TODO: support for more than one component
-	CInfoWindow * ret = new CInfoWindow();
-	ret->components = comps;
-	std::vector<std::string> * brtext = breakText(text,charperline,true,true);
-	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(brtext);
-	std::pair<int,int> txts = getMaxSizes(txtg);
-	txts.second = txts.second
-		+ ok->ourImages[0].bitmap->h //button
-		+ 15 //after button
-		+ 20; // space between subtitle and button
-	if (comps.size())
-			txts.second = txts.second
-			+ 30 //space to first component
-			+ comps[0]->getImg()->h
-			+ 5 //img <-> subtitle
-			+ 20; //subtitle //!!!!!!!!!!!!!!!!!!!!
-	ret->bitmap = drawBox1(txts.first+70,txts.second+70,0);
-	ret->pos.h=ret->bitmap->h;
-	ret->pos.w=ret->bitmap->w;
-	int curh = 30; //gorny margines
+	int curh = ret->bitmap->h/2 - (19*txtg->size())/2;
 	blitTextOnSur(txtg,curh,ret->bitmap);
-	if (comps.size())
-	{
-		blitCompsOnSur(comps,200,0,curh,ret->bitmap);
-	}
-	curh += 20; //to buttton
-	ret->okb.posr.x = (ret->bitmap->w/2) - (ret->okb.imgs[0][0]->w/2);
-	ret->okb.posr.y = curh;
-	ret->okb.show();
-	curh+=ret->okb.imgs[0][0]->h;
+	delete brtext;
+	delete txtg;
 	return ret;
 }
-std::vector< std::vector<CSelectableComponent*> > * CMessage::breakComps(std::vector<CSelectableComponent*> & comps,int maxw, SDL_Surface* _or)
+std::vector< std::vector<SComponent*> > * CMessage::breakComps(std::vector<SComponent*> & comps,int maxw, SDL_Surface* _or)
 {
-	std::vector< std::vector<CSelectableComponent*> > * ret = new std::vector< std::vector<CSelectableComponent*> >();
+	std::vector< std::vector<SComponent*> > * ret = new std::vector< std::vector<SComponent*> >();
 	ret->resize(1);
-	bool wywalicOr=false;
-	if (!_or)
-	{
-		_or = TTF_RenderText_Blended(GEOR13,CGI->generaltexth->allTexts[4].c_str(),zwykly);
-		wywalicOr=true;
-	}
 	int rvi = 0;
 	int curw = 0;
 	for(int i=0;i<comps.size();i++)
 	{
-		curw += (comps[i]->getImg()->w + 12 + _or->w);
+		curw += (comps[i]->getImg()->w + 12 + (_or ? _or->w : 0));
 		if (curw > maxw)
 		{
 			curw = 0;
@@ -428,10 +378,6 @@ std::vector< std::vector<CSelectableComponent*> > * CMessage::breakComps(std::ve
 		}
 		(*ret)[rvi].push_back(comps[i]);
 	}
-	if (wywalicOr)
-	{
-		SDL_FreeSurface(_or);
-	}
 	return ret;
 }
 
@@ -460,44 +406,96 @@ SDL_Surface * CMessage::drawBoxTextBitmapSub(int player, std::string text, SDL_S
 	return ret;
 }
 
-CSelWindow * CMessage::genSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> & comps, int owner)
+void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int charperline)
 {
-	CSelWindow * ret = new CSelWindow();
-	for(unsigned i=0;i<comps.size();i++)
-	{
-		ret->components.push_back(comps[i]);
-		comps[i]->onSelect = boost::bind(&CSelWindow::selectionChange,ret,i);
-	}
-	std::vector<std::string> * tekst = breakText(text,charperline);
-	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(tekst);
+	std::vector<std::string> * brtext = breakText(text,charperline,true,true);
+	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(brtext);
 	std::pair<int,int> txts = getMaxSizes(txtg);
-	txts.first+=45; //side margins
-	int curh = 50; //top margin
-	SDL_Surface * _or = TTF_RenderText_Blended(GEOR13,CGI->generaltexth->allTexts[4].c_str(),zwykly);
-	std::vector< std::vector<CSelectableComponent*> > * komp = breakComps(comps,500,_or);
-	std::pair<int,int> txts2 = getMaxSizes(komp);
-	ret->pos.h = txts.second //wys. tekstu
-		+ txts2.second //wys komponentow
-		+ 20 //podpis pod komponentami
-		+ 55 //gorny margines
-		+ 60 //text <=> comps
-		+ 20 //comps <=> button
-		+ ok->ourImages[0].bitmap->h //button
-		+ 30; //bottom margin
-	ret->pos.w = std::max(txts.first,txts.second);
-	ret->bitmap = drawBox1(ret->pos.w,ret->pos.h,player);
+	if(ret->buttons.size())
+		txts.second += 20 + //before button
+		ok->ourImages[0].bitmap->h; //button
+	if (ret->components.size())
+		txts.second += 30 //space to first component
+		+ ret->components[0]->getImg()->h
+		+ 5 //img <-> subtitle
+		+ 20; //subtitle //TODO: check how much place will be needed for subtitle
+	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.y=300-(ret->pos.h/2);
+	int curh = 30; //gorny margines
 	blitTextOnSur(txtg,curh,ret->bitmap);
-	curh += 50;
-	blitCompsOnSur(_or,komp,10,curh,ret->bitmap);
-	curh += 30; //to buttton
-	ret->okb.posr.x = (ret->bitmap->w/2) - (ret->okb.imgs[0][0]->w/2);
-	ret->okb.posr.y = curh;
-	ret->okb.show();
-	curh+=ret->okb.imgs[0][0]->h;
-	SDL_FreeSurface(_or);
-	delete komp;
-	delete tekst;
-	return ret;
+	if (ret->components.size())
+	{
+		curh += 30;
+		if(ret->components.size()==1)
+		{
+			blitCompsOnSur(ret->components,200,0,curh,ret->bitmap);
+		}
+		else
+		{
+			SDL_Surface * _or = 0;
+			if(dynamic_cast<CSelWindow*>(ret)) //it's selection window, so we'll blit "or" between components
+				_or = TTF_RenderText_Blended(GEOR13,CGI->generaltexth->allTexts[4].c_str(),zwykly);
+			std::vector< std::vector<SComponent*> > * komp = breakComps(reinterpret_cast<std::vector<SComponent*>&>(ret->components),500,_or);
+			blitCompsOnSur(_or,komp,10,curh,ret->bitmap);
+			delete komp;
+		}
+	}
+	if(ret->buttons.size())
+	{
+		curh += 20; //to buttton
+		int bw = 20*(ret->buttons.size()-1); //total width of buttons - start with distance between them
+		for(int i=0; i<ret->buttons.size(); i++) //and add buttons width
+			bw+=ret->buttons[i]->imgs[0][0]->w; 
+		bw = (ret->bitmap->w/2) - (bw/2);
+		for(int i=0; i<ret->buttons.size(); i++)
+		{
+			ret->buttons[i]->pos.x = bw + ret->pos.x;
+			ret->buttons[i]->pos.y = curh + ret->pos.y;
+			bw += ret->buttons[i]->imgs[0][0]->w + 20;
+		}
+	}
+	for(int i=0; i<ret->components.size(); i++)
+	{
+		ret->components[i]->pos.x += ret->pos.x;
+		ret->components[i]->pos.y += ret->pos.y;
+	}
+	delete brtext;
+	delete txtg;
+}
+CSelWindow * CMessage::genSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> & comps, int owner)
+{
+	//CSelWindow * ret = new CSelWindow();
+	//std::vector<std::string> * tekst = breakText(text,charperline);
+	//std::vector<std::vector<SDL_Surface*> > * txtg = drawText(tekst);
+	//std::pair<int,int> txts = getMaxSizes(txtg);
+	//txts.first+=45; //side margins
+	//int curh = 50; //top margin
+	////std::pair<int,int> txts2 = getMaxSizes(komp);
+	//ret->pos.h = txts.second //wys. tekstu
+	//	//+ txts2.second //wys komponentow
+	//	+ 20 //podpis pod komponentami
+	//	+ 55 //gorny margines
+	//	+ 60 //text <=> comps
+	//	+ 20 //comps <=> button
+	//	+ ok->ourImages[0].bitmap->h //button
+	//	+ 30; //bottom margin
+	//ret->pos.w = std::max(txts.first,txts.second);
+	//ret->bitmap = drawBox1(ret->pos.w,ret->pos.h,player);
+	//blitTextOnSur(txtg,curh,ret->bitmap);
+	//curh += 50;
+	//blitCompsOnSur(_or,komp,10,curh,ret->bitmap);
+	//curh += 30; //to buttton
+	//ret->buttons[0]->pos.x = (ret->bitmap->w/2) - (ret->buttons[0]->imgs[0][0]->w/2);
+	//ret->buttons[0]->pos.y = curh;
+	//ret->buttons[0]->show();
+	//curh += ret->buttons[0]->imgs[0][0]->h;
+	//SDL_FreeSurface(_or);
+	//delete komp;
+	//delete tekst;
+	return NULL;
 }
 
 SDL_Surface * CMessage::genMessage

+ 4 - 4
CMessage.h

@@ -27,13 +27,13 @@ class CMessage
 public:
 
 	static std::pair<int,int> getMaxSizes(std::vector<std::vector<SDL_Surface*> > * txtg);
-	static std::pair<int, int> getMaxSizes(std::vector< std::vector<CSelectableComponent*> > * komp);
+	static std::pair<int, int> getMaxSizes(std::vector< std::vector<SComponent*> > * komp);
 	static std::vector<std::vector<SDL_Surface*> > * drawText(std::vector<std::string> * brtext);
 	static SDL_Surface * blitTextOnSur(std::vector<std::vector<SDL_Surface*> > * txtg, int & curh, SDL_Surface * ret);
 	static SDL_Surface * blitCompsOnSur(std::vector<SComponent*> & comps, int maxw, int inter, int & curh, SDL_Surface * ret);
-	static SDL_Surface * blitCompsOnSur(SDL_Surface *_or, std::vector< std::vector<CSelectableComponent*> > *komp, int inter, int &curh, SDL_Surface *ret);
-	static CInfoWindow * genIWindow(std::string text, int player, int charperline, std::vector<SComponent*> &comps);
-	static std::vector< std::vector<CSelectableComponent*> > * breakComps(std::vector<CSelectableComponent*> &comps, int maxw, SDL_Surface* _or=NULL);
+	static SDL_Surface * blitCompsOnSur(SDL_Surface *_or, std::vector< std::vector<SComponent*> > *komp, int inter, int &curh, SDL_Surface *ret);
+	static void drawIWindow(CInfoWindow * ret, std::string text, int player, int charperline);
+	static std::vector< std::vector<SComponent*> > * breakComps(std::vector<SComponent*> &comps, int maxw, SDL_Surface* _or=NULL);
 	static CSelWindow * genSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> & comps, int owner);
 	static CSimpleWindow * genWindow(std::string text, int player, int Lmar=35, int Rmar=35, int Tmar=35, int Bmar=35);//supports h3 text formatting; player sets color of window, Lmar/Rmar/Tmar/Bmar are Left/Right/Top/Bottom margins
 	static SDL_Surface * genMessage(std::string title, std::string text, EWindowType type=infoOnly,

+ 105 - 76
CPlayerInterface.cpp

@@ -157,11 +157,20 @@ void CGarrisonSlot::clickLeft(tribool down)
 			if(owner->highlighted == this) //view info
 			{
 				UpgradeInfo pom = LOCPLINT->cb->getUpgradeInfo(getObj(),ID);
-				(new CCreInfoWindow
-					(creature->idNumber,1,NULL,
-					(pom.oldID>=0)?(boost::bind(&CCallback::upgradeCreature,LOCPLINT->cb,getObj(),ID,-1)):(boost::function<void()>()), //if upgrade is possible we'll bind proper function in callback
-					 boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID)))
+				if(pom.oldID>=0)
+				{
+					(new CCreInfoWindow
+						(creature->idNumber,1,NULL,
+						boost::bind(&CCallback::upgradeCreature,LOCPLINT->cb,getObj(),ID,pom.newID[0]), //if upgrade is possible we'll bind proper function in callback
+						 boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID)))
+							->activate();
+				}
+				else
+				{
+					(new CCreInfoWindow
+						(creature->idNumber,1,NULL,0, boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID)) )
 						->activate();
+				}
 				owner->highlighted = NULL;
 				show();
 				refr = true;
@@ -454,39 +463,57 @@ void CGarrisonInt::deactivate()
 	deactiveteSlots();
 }
 
+CInfoWindow::CInfoWindow(std::string text, int player, int charperline, std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons)
+{
+	for(int i=0;i<Buttons.size();i++)
+	{
+		buttons.push_back(new AdventureMapButton("","",Buttons[i].second,0,0,Buttons[i].first));
+		if(!Buttons[i].second) //if no function, then by default we'll set it to close
+			buttons[i]->callback += boost::bind(&CInfoWindow::close,this);
+	}
+	for(int i=0;i<comps.size();i++)
+	{
+		components.push_back(comps[i]);
+	}
+	CMessage::drawIWindow(this,text,player,charperline);
+}
 CInfoWindow::CInfoWindow()
-:okb(NMessage::ok,NULL,&CInfoWindow::okClicked)
 {
-	okb.ourObj = this;
-	okb.delg = this;
-	okb.notFreeButton=true;
 }
-
-void CInfoWindow::okClicked(tribool down)
+void CInfoWindow::close()
 {
-	if (!down)
-		close();
+	deactivate();
+	delete this;
+}
+void CInfoWindow::show(SDL_Surface * to)
+{
+	CSimpleWindow::show();
+	for(int i=0;i<buttons.size();i++)
+		buttons[i]->show();
 }
 
-void CInfoWindow::close()
+CInfoWindow::~CInfoWindow()
 {
 	for (int i=0;i<components.size();i++)
-	{
-		components[i]->deactivate();
 		delete components[i];
-	}
-	components.clear();
-	okb.deactivate();
-	SDL_FreeSurface(bitmap);
-	bitmap = NULL;
-	LOCPLINT->removeObjToBlit(this);
-	LOCPLINT->curint->activate();
-	delete this;
+	for(int i=0;i<buttons.size();i++)
+		delete buttons[i];
 }
-CInfoWindow::~CInfoWindow()
+void CInfoWindow::activate()
 {
+	for (int i=0;i<components.size();i++)
+		components[i]->activate();
+	for(int i=0;i<buttons.size();i++)
+		buttons[i]->activate();
+}
+void CInfoWindow::deactivate()
+{
+	for (int i=0;i<components.size();i++)
+		components[i]->deactivate();
+	for(int i=0;i<buttons.size();i++)
+		buttons[i]->deactivate();
+	LOCPLINT->removeObjToBlit(this);
 }
-
 void CRClickPopup::clickRight (tribool down)
 {
 	if(down)
@@ -733,13 +760,22 @@ void CSelWindow::selectionChange(unsigned to)
 		blitAt(pom->getImg(),pom->pos.x-pos.x,pom->pos.y-pos.y,bitmap);
 	}
 }
-void CSelWindow::okClicked(tribool down)
+CSelWindow::CSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> &comps, std::vector<std::pair<std::string,boost::function<void()> > > &Buttons)
 {
-	if(!down)
-		close();
+	for(int i=0;i<Buttons.size();i++)
+	{
+		buttons.push_back(new AdventureMapButton("","",(Buttons[i].second)?(Buttons[i].second):(boost::bind(&CInfoWindow::close,this)),0,0,Buttons[i].first));
+	}
+	for(int i=0;i<comps.size();i++)
+	{
+		components.push_back(comps[i]);
+		comps[i]->onSelect = boost::bind(&CSelWindow::selectionChange,this,i);
+	}
+	CMessage::drawIWindow(this,text,player,charperline);
 }
 void CSelWindow::close()
 {
+	deactivate();
 	int ret = -1;
 	for (int i=0;i<components.size();i++)
 	{
@@ -747,14 +783,7 @@ void CSelWindow::close()
 		{
 			ret = i;
 		}
-		components[i]->deactivate();
-		delete components[i];
 	}
-	components.clear();
-	okb.deactivate();
-	SDL_FreeSurface(bitmap);
-	bitmap = NULL;
-	LOCPLINT->removeObjToBlit(this);
 	LOCPLINT->curint->activate();
 	LOCPLINT->cb->selectionMade(ret,ID);
 	delete this;
@@ -1881,7 +1910,7 @@ void CPlayerInterface::receivedResource(int type, int val)
 	adventureInt->resdatabar.draw();
 }
 
-void CPlayerInterface::showSelDialog(std::string text, std::vector<Component*> &components, ui32 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);
@@ -1889,20 +1918,12 @@ void CPlayerInterface::showSelDialog(std::string text, std::vector<Component*> &
 	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
+	std::vector<std::pair<std::string,boost::function<void()> > > pom;
+	pom.push_back(std::pair<std::string,boost::function<void()> >("IOKAY.DEF",0));
 
-	CSelWindow * temp = CMessage::genSelWindow(text,LOCPLINT->playerID,35,intComps,playerID);
+	CSelWindow * temp = new CSelWindow(text,playerID,35,intComps,pom);
 	LOCPLINT->objsToBlit.push_back(temp);
-	temp->pos.x=300-(temp->pos.w/2);
-	temp->pos.y=300-(temp->pos.h/2);
-	temp->okb.pos.x = temp->okb.posr.x + temp->pos.x;
-	temp->okb.pos.y = temp->okb.posr.y + temp->pos.y;
-	temp->okb.activate();
-	for (int i=0;i<temp->components.size();i++)
-	{
-		temp->components[i]->activate();
-		temp->components[i]->pos.x += temp->pos.x;
-		temp->components[i]->pos.y += temp->pos.y;
-	}
+	temp->activate();
 	temp->ID = askID;
 	intComps[0]->clickLeft(true);
 }
@@ -2068,42 +2089,34 @@ void CPlayerInterface::showComp(SComponent comp)
 	adventureInt->infoBar.showComp(&comp,4000);
 }
 
-void CPlayerInterface::showInfoDialog(std::string text, std::vector<Component*> &components)
+void CPlayerInterface::showInfoDialog(std::string &text, std::vector<Component*> &components)
 {
-	curint->deactivate(); //dezaktywacja starego interfejsu
 	std::vector<SComponent*> intComps;
 	for(int i=0;i<components.size();i++)
 		intComps.push_back(new SComponent(*components[i]));
-	CInfoWindow * temp = CMessage::genIWindow(text,LOCPLINT->playerID,32,intComps);
+	showInfoDialog(text,intComps);
+}
+void CPlayerInterface::showInfoDialog(std::string &text, std::vector<SComponent*> & components)
+{
+	curint->deactivate(); //dezaktywacja starego interfejsu
+
+	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
+	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
+	
+	CInfoWindow * temp = new CInfoWindow(text,playerID,32,components,pom);
+	temp->buttons[0]->callback += boost::bind(&IActivable::activate,LOCPLINT->curint);
+	temp->activate();
 	LOCPLINT->objsToBlit.push_back(temp);
-	temp->pos.x=300-(temp->pos.w/2);
-	temp->pos.y=300-(temp->pos.h/2);
-	temp->okb.pos.x = temp->okb.posr.x + temp->pos.x;
-	temp->okb.pos.y = temp->okb.posr.y + temp->pos.y;
-	temp->okb.activate();
-	for (int i=0;i<temp->components.size();i++)
-	{
-		temp->components[i]->activate();
-		temp->components[i]->pos.x += temp->pos.x;
-		temp->components[i]->pos.y += temp->pos.y;
-	}
 }
-void CPlayerInterface::showInfoDialog(std::string text, std::vector<SComponent*> & components)
+void CPlayerInterface::showYesNoDialog(std::string &text, std::vector<SComponent*> & components, CFunctionList<void()> funcs[2])
 {
 	curint->deactivate(); //dezaktywacja starego interfejsu
-	CInfoWindow * temp = CMessage::genIWindow(text,LOCPLINT->playerID,32,components);
+	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
+	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",funcs[0]));
+	pom.push_back(std::pair<std::string,CFunctionList<void()> >("ICANCEL.DEF",funcs[1]));
+	CInfoWindow * temp = new CInfoWindow(text,playerID,32,components,pom);
+	temp->activate();
 	LOCPLINT->objsToBlit.push_back(temp);
-	temp->pos.x=300-(temp->pos.w/2);
-	temp->pos.y=300-(temp->pos.h/2);
-	temp->okb.pos.x = temp->okb.posr.x + temp->pos.x;
-	temp->okb.pos.y = temp->okb.posr.y + temp->pos.y;
-	temp->okb.activate();
-	for (int i=0;i<temp->components.size();i++)
-	{
-		temp->components[i]->activate();
-		temp->components[i]->pos.x += temp->pos.x;
-		temp->components[i]->pos.y += temp->pos.y;
-	}
 }
 void CPlayerInterface::removeObjToBlit(IShowable* obj)
 {
@@ -2960,7 +2973,7 @@ void CCreInfoWindow::show(SDL_Surface * to)
 
 CCreInfoWindow::CCreInfoWindow
 		(int Cid, int Type, StackState *State, boost::function<void()> Upg, boost::function<void()> Dsm)
-:ok(0),dismiss(0),upgrade(0),type(Type),dsm(Dsm)
+:ok(0),dismiss(0),upgrade(0),type(Type),dsm(Dsm),dependant(0)
 {
 	c = &CGI->creh->creatures[Cid];
 	bitmap = BitmapHandler::loadBitmap("CRSTKPU.bmp");
@@ -3045,7 +3058,10 @@ CCreInfoWindow::CCreInfoWindow
 	if(type)
 	{
 		if(Upg)
+		{
 			upgrade = new AdventureMapButton("",CGI->preth->zelp[446].second,Upg,pos.x+76,pos.y+237,"IVIEWCR.DEF");
+			upgrade->callback += boost::bind(&CCreInfoWindow::close,this);
+		}
 		if(Dsm)
 			dismiss = new AdventureMapButton("",CGI->preth->zelp[445].second,boost::bind(&CCreInfoWindow::dismissF,this),pos.x+21,pos.y+237,"IVIEWCR2.DEF");
 		ok = new AdventureMapButton("",CGI->preth->zelp[445].second,boost::bind(&CCreInfoWindow::close,this),pos.x+216,pos.y+237,"IOKAY.DEF");
@@ -3114,6 +3130,19 @@ void CCreInfoWindow::deactivate()
 		upgrade->deactivate();
 }
 
+void CCreInfoWindow::onUpgradeYes()
+{
+	dependant->close();
+	dependant->deactivate();
+	delete dependant;
+ 
+	LOCPLINT->curint->activate();
+}
+
+void CCreInfoWindow::onUpgradeNo()
+{
+
+}
 void CLevelWindow::close()
 {
 	deactivate();

+ 14 - 8
CPlayerInterface.h

@@ -23,7 +23,6 @@ class CSelectableComponent;
 class CCreatureSet;
 class CGObjectInstance;
 class CSlider;
-
 namespace boost
 {
 	class mutex;
@@ -160,19 +159,22 @@ public:
 class CInfoWindow : public CSimpleWindow //text + comp. + ok button
 { //window deletes its components when closed
 public:
-	CSCButton<CInfoWindow> okb;
+	std::vector<AdventureMapButton *> buttons;
 	std::vector<SComponent*> components;
-	virtual void okClicked(boost::logic::tribool down);
 	virtual void close();
+	virtual void show(SDL_Surface * to = NULL);
+	void activate();
+	void deactivate();
+	CInfoWindow(std::string text, int player, int charperline, std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons);
 	CInfoWindow();
-	virtual ~CInfoWindow();
+	~CInfoWindow();
 };
 class CSelWindow : public CInfoWindow //component selection window
 { //uwaga - to okno usuwa swoje komponenty przy zamykaniu
 public:
 	void selectionChange(unsigned to);
-	void okClicked(boost::logic::tribool down);
 	void close();
+	CSelWindow(std::string text, int player, int charperline, std::vector<CSelectableComponent*> &comps, std::vector<std::pair<std::string,boost::function<void()> > > &Buttons);
 	CSelWindow(){};
 };
 
@@ -330,8 +332,8 @@ public:
 	void heroCreated(const CGHeroInstance* hero);
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val);
 	void receivedResource(int type, int val);
-	void showInfoDialog(std::string text, std::vector<Component*> &components);
-	void showSelDialog(std::string text, std::vector<Component*> &components, ui32 askID);
+	void showInfoDialog(std::string &text, std::vector<Component*> &components);
+	void showSelDialog(std::string &text, std::vector<Component*> &components, ui32 askID);
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
 	void garrisonChanged(const CGObjectInstance * obj);
 	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
@@ -363,7 +365,8 @@ public:
 	void init(ICallback * CB);
 	int3 repairScreenPos(int3 pos);
 	void removeObjToBlit(IShowable* obj);	
-	void showInfoDialog(std::string text, std::vector<SComponent*> & components);
+	void showInfoDialog(std::string &text, std::vector<SComponent*> & components);
+	void showYesNoDialog(std::string &text, std::vector<SComponent*> & components, CFunctionList<void()> funcs[2]);
 
 	CPlayerInterface(int Player, int serial);//c-tor
 	~CPlayerInterface();//d-tor
@@ -524,6 +527,7 @@ public:
 	boost::function<void()> dsm;
 	CCreaturePic *anim;
 	CCreature *c;
+	CInfoWindow *dependant; //it may be dialog asking whther upgrade/dismiss stack (if opened)
 
 	AdventureMapButton *dismiss, *upgrade, *ok;
 	CCreInfoWindow(int Cid, int Type, StackState *State, boost::function<void()> Upg, boost::function<void()> Dsm);
@@ -535,6 +539,8 @@ public:
 	void keyPressed (SDL_KeyboardEvent & key);
 	void deactivate();
 	void show(SDL_Surface * to = NULL);
+	void onUpgradeYes();
+	void onUpgradeNo();
 };
 
 class CLevelWindow : public IShowable, public CIntObject

+ 36 - 0
client/FunctionList.h

@@ -0,0 +1,36 @@
+#pragma  once
+#include <boost/function.hpp>
+
+template<typename Signature, typename Allocator = std::allocator<void> >
+class CFunctionList
+{
+public:
+	std::vector<boost::function<Signature,Allocator> > funcs;
+
+	CFunctionList(int){};
+	CFunctionList(){};
+	CFunctionList(const boost::function<Signature,Allocator> &first)
+	{
+		funcs.push_back(first);
+	}
+	CFunctionList & operator+=(const boost::function<Signature,Allocator> &first)
+	{
+		funcs.push_back(first);
+		return *this;
+	}
+	const boost::function<Signature,Allocator> & operator=(const boost::function<Signature,Allocator> &first)
+	{
+		funcs.push_back(first);
+		return first;
+	}
+	operator bool() const
+	{
+		return funcs.size();
+	}
+	void operator()() const
+	{
+		std::vector<boost::function<Signature,Allocator> > funcs2 = funcs; //backup
+		for(int i=0;i<funcs2.size(); i++)
+			funcs2[i]();
+	}
+};

+ 4 - 4
client/VCMI_client.vcproj

@@ -444,10 +444,6 @@
 				RelativePath=".\CCreatureAnimation.h"
 				>
 			</File>
-			<File
-				RelativePath="..\hch\CCreatureHandler.h"
-				>
-			</File>
 			<File
 				RelativePath="..\CCursorHandler.h"
 				>
@@ -524,6 +520,10 @@
 				RelativePath="..\CThreadHelper.h"
 				>
 			</File>
+			<File
+				RelativePath=".\FunctionList.h"
+				>
+			</File>
 			<File
 				RelativePath="..\global.h"
 				>

+ 0 - 8
lib/VCMI_lib.vcproj

@@ -258,10 +258,6 @@
 		<Filter
 			Name="Source Files"
 			>
-			<File
-				RelativePath="..\hch\CAmbarCendamo.cpp"
-				>
-			</File>
 			<File
 				RelativePath="..\hch\CArtHandler.cpp"
 				>
@@ -324,10 +320,6 @@
 				RelativePath=".\BattleAction.h"
 				>
 			</File>
-			<File
-				RelativePath="..\hch\CAmbarCendamo.h"
-				>
-			</File>
 			<File
 				RelativePath="..\hch\CArtHandler.h"
 				>

File diff suppressed because it is too large
+ 788 - 194
map.cpp


+ 13 - 0
map.h

@@ -485,6 +485,19 @@ struct DLL_EXPORT Mapa
 	std::vector<CGTownInstance*> towns;
 
 	void initFromBytes(unsigned char * bufor); //creates map from decompressed .h3m data
+
+	void readEvents( unsigned char * bufor, int &i);
+	void readObjects( unsigned char * bufor, int &i);
+	void readDefInfo( unsigned char * bufor, int &i);
+	void readTerrain( unsigned char * bufor, int &i);
+	void readPredefinedHeroes( unsigned char * bufor, int &i);
+	void readHeader( unsigned char * bufor, int &i);
+	void readRumors( unsigned char * bufor, int &i);
+	void loadViCLossConditions( unsigned char * bufor, int &i);
+	void loadPlayerInfo( int &pom, unsigned char * bufor, int &i);
+	void loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i);
+	void loadTown( CGObjectInstance * &nobj, unsigned char * bufor, int &i);
+	int loadSeerHut( unsigned char * bufor, int i, CGObjectInstance * nobj);
 	void addBlockVisTiles(CGObjectInstance * obj);
 	void removeBlockVisTiles(CGObjectInstance * obj);
 	Mapa(std::string filename); //creates map structure from .h3m file

+ 196 - 148
server/CGameHandler.cpp

@@ -10,7 +10,6 @@
 #include "../map.h"
 #include "../lib/NetPacks.h"
 #include "../lib/Connection.h"
-#include "../CLua.h"
 #include "../hch/CObjectHandler.h"
 #include "../hch/CTownHandler.h"
 #include "../hch/CBuildingHandler.h"
@@ -244,153 +243,9 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
 {
 
 	BattleInfo *curB = new BattleInfo;
-	//battle start
-	{
-		battleResult.set(NULL);
-		std::vector<CStack*> & stacks = (curB->stacks);
-
-		curB->tile = tile;
-		curB->siege = 0; //TODO: add sieges
-		curB->army1=army1;
-		curB->army2=army2;
-		curB->hero1=(hero1)?(hero1->id):(-1);
-		curB->hero2=(hero2)?(hero2->id):(-1);
-		curB->side1=(hero1)?(hero1->tempOwner):(-1);
-		curB->side2=(hero2)?(hero2->tempOwner):(-1);
-		curB->round = -2;
-		curB->activeStack = -1;
-		for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
-		{
-			stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true));
-			stacks[stacks.size()-1]->ID = stacks.size()-1;
-		}
-		//initialization of positions
-		switch(army1.slots.size()) //for attacker
-		{
-		case 0:
-			break;
-		case 1:
-			stacks[0]->position = 86; //6
-			break;
-		case 2:
-			stacks[0]->position = 35; //3
-			stacks[1]->position = 137; //9
-			break;
-		case 3:
-			stacks[0]->position = 35; //3
-			stacks[1]->position = 86; //6
-			stacks[2]->position = 137; //9
-			break;
-		case 4:
-			stacks[0]->position = 1; //1
-			stacks[1]->position = 69; //5
-			stacks[2]->position = 103; //7
-			stacks[3]->position = 171; //11
-			break;
-		case 5:
-			stacks[0]->position = 1; //1
-			stacks[1]->position = 35; //3
-			stacks[2]->position = 86; //6
-			stacks[3]->position = 137; //9
-			stacks[4]->position = 171; //11
-			break;
-		case 6:
-			stacks[0]->position = 1; //1
-			stacks[1]->position = 35; //3
-			stacks[2]->position = 69; //5
-			stacks[3]->position = 103; //7
-			stacks[4]->position = 137; //9
-			stacks[5]->position = 171; //11
-			break;
-		case 7:
-			stacks[0]->position = 1; //1
-			stacks[1]->position = 35; //3
-			stacks[2]->position = 69; //5
-			stacks[3]->position = 86; //6
-			stacks[4]->position = 103; //7
-			stacks[5]->position = 137; //9
-			stacks[6]->position = 171; //11
-			break;
-		default: //fault
-			break;
-		}
-		for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
-			stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false));
-		switch(army2.slots.size()) //for defender
-		{
-		case 0:
-			break;
-		case 1:
-			stacks[0+army1.slots.size()]->position = 100; //6
-			break;
-		case 2:
-			stacks[0+army1.slots.size()]->position = 49; //3
-			stacks[1+army1.slots.size()]->position = 151; //9
-			break;
-		case 3:
-			stacks[0+army1.slots.size()]->position = 49; //3
-			stacks[1+army1.slots.size()]->position = 100; //6
-			stacks[2+army1.slots.size()]->position = 151; //9
-			break;
-		case 4:
-			stacks[0+army1.slots.size()]->position = 15; //1
-			stacks[1+army1.slots.size()]->position = 83; //5
-			stacks[2+army1.slots.size()]->position = 117; //7
-			stacks[3+army1.slots.size()]->position = 185; //11
-			break;
-		case 5:
-			stacks[0+army1.slots.size()]->position = 15; //1
-			stacks[1+army1.slots.size()]->position = 49; //3
-			stacks[2+army1.slots.size()]->position = 100; //6
-			stacks[3+army1.slots.size()]->position = 151; //9
-			stacks[4+army1.slots.size()]->position = 185; //11
-			break;
-		case 6:
-			stacks[0+army1.slots.size()]->position = 15; //1
-			stacks[1+army1.slots.size()]->position = 49; //3
-			stacks[2+army1.slots.size()]->position = 83; //5
-			stacks[3+army1.slots.size()]->position = 117; //7
-			stacks[4+army1.slots.size()]->position = 151; //9
-			stacks[5+army1.slots.size()]->position = 185; //11
-			break;
-		case 7:
-			stacks[0+army1.slots.size()]->position = 15; //1
-			stacks[1+army1.slots.size()]->position = 49; //3
-			stacks[2+army1.slots.size()]->position = 83; //5
-			stacks[3+army1.slots.size()]->position = 100; //6
-			stacks[4+army1.slots.size()]->position = 117; //7
-			stacks[5+army1.slots.size()]->position = 151; //9
-			stacks[6+army1.slots.size()]->position = 185; //11
-			break;
-		default: //fault
-			break;
-		}
-		for(unsigned g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
-		{
-			if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
-			{
-				stacks[g]->position += 1;
-			}
-			else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
-			{
-				stacks[g]->position -= 1;
-			}
-		}
-		std::stable_sort(stacks.begin(),stacks.end(),cmpst);
+	setupBattle(curB, tile, army1, army2, hero1, hero2); //battle start
+	NEW_ROUND;
 
-		//block engaged players
-		if(hero1->tempOwner<PLAYER_LIMIT)
-			states.setFlag(hero1->tempOwner,&PlayerStatus::engagedIntoBattle,true);
-		if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
-			states.setFlag(hero2->tempOwner,&PlayerStatus::engagedIntoBattle,true);
-
-		//send info about battles
-		BattleStart bs;
-		bs.info = curB;
-		sendAndApply(&bs);
-
-		NEW_ROUND;
-	}
 
 	//tactic round
 	{
@@ -764,6 +619,53 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					sendAndApply(&sg);
 					break;
 				}
+			case 507://upgrade creature
+				{
+					ui32 objid, upgID;
+					ui8 pos;
+					c >> objid >> pos >> upgID;
+					CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
+					UpgradeInfo ui = gs->getUpgradeInfo(obj,pos);
+					int player = obj->tempOwner;
+					int crQuantity = obj->army.slots[pos].second;
+
+					//check if upgrade is possible
+					if(ui.oldID<0 || !vstd::contains(ui.newID,upgID)) 
+						break;
+
+					//check if player has enough resources
+					for(int i=0;i<ui.cost.size();i++)
+					{
+						for (std::set<std::pair<int,int> >::iterator j=ui.cost[i].begin(); j!=ui.cost[i].end(); j++)
+						{
+							if(gs->players[player].resources[j->first] < j->second*crQuantity)
+								goto upgend;
+						}
+					}
+
+					//take resources
+					for(int i=0;i<ui.cost.size();i++)
+					{
+						for (std::set<std::pair<int,int> >::iterator j=ui.cost[i].begin(); j!=ui.cost[i].end(); j++)
+						{
+							SetResource sr;
+							sr.player = player;
+							sr.resid = j->first;
+							sr.val = gs->players[player].resources[j->first] - j->second*crQuantity;
+							sendAndApply(&sr);
+						}
+					}
+
+					{
+						//upgrade creature
+						SetGarrisons sg;
+						sg.garrs[objid] = obj->army;
+						sg.garrs[objid].slots[pos].first = upgID;
+						sendAndApply(&sg);	
+					}		
+upgend:
+					break;
+				}
 			case 2001:
 				{
 					ui32 qid, answer;
@@ -1015,7 +917,7 @@ void CGameHandler::run()
 			gsm.unlock();
 		}	
 	}
-
+	
 	for(std::set<CConnection*>::iterator i = conns.begin(); i!=conns.end();i++)
 	{
 		std::set<int> pom;
@@ -1090,3 +992,149 @@ void CGameHandler::run()
 		}
 	}
 }
+
+void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 )
+{
+	battleResult.set(NULL);
+	std::vector<CStack*> & stacks = (curB->stacks);
+
+	curB->tile = tile;
+	curB->siege = 0; //TODO: add sieges
+	curB->army1=army1;
+	curB->army2=army2;
+	curB->hero1=(hero1)?(hero1->id):(-1);
+	curB->hero2=(hero2)?(hero2->id):(-1);
+	curB->side1=(hero1)?(hero1->tempOwner):(-1);
+	curB->side2=(hero2)?(hero2->tempOwner):(-1);
+	curB->round = -2;
+	curB->activeStack = -1;
+	for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
+	{
+		stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true));
+		stacks[stacks.size()-1]->ID = stacks.size()-1;
+	}
+	//initialization of positions
+	switch(army1.slots.size()) //for attacker
+	{
+	case 0:
+		break;
+	case 1:
+		stacks[0]->position = 86; //6
+		break;
+	case 2:
+		stacks[0]->position = 35; //3
+		stacks[1]->position = 137; //9
+		break;
+	case 3:
+		stacks[0]->position = 35; //3
+		stacks[1]->position = 86; //6
+		stacks[2]->position = 137; //9
+		break;
+	case 4:
+		stacks[0]->position = 1; //1
+		stacks[1]->position = 69; //5
+		stacks[2]->position = 103; //7
+		stacks[3]->position = 171; //11
+		break;
+	case 5:
+		stacks[0]->position = 1; //1
+		stacks[1]->position = 35; //3
+		stacks[2]->position = 86; //6
+		stacks[3]->position = 137; //9
+		stacks[4]->position = 171; //11
+		break;
+	case 6:
+		stacks[0]->position = 1; //1
+		stacks[1]->position = 35; //3
+		stacks[2]->position = 69; //5
+		stacks[3]->position = 103; //7
+		stacks[4]->position = 137; //9
+		stacks[5]->position = 171; //11
+		break;
+	case 7:
+		stacks[0]->position = 1; //1
+		stacks[1]->position = 35; //3
+		stacks[2]->position = 69; //5
+		stacks[3]->position = 86; //6
+		stacks[4]->position = 103; //7
+		stacks[5]->position = 137; //9
+		stacks[6]->position = 171; //11
+		break;
+	default: //fault
+		break;
+	}
+	for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
+		stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false));
+	switch(army2.slots.size()) //for defender
+	{
+	case 0:
+		break;
+	case 1:
+		stacks[0+army1.slots.size()]->position = 100; //6
+		break;
+	case 2:
+		stacks[0+army1.slots.size()]->position = 49; //3
+		stacks[1+army1.slots.size()]->position = 151; //9
+		break;
+	case 3:
+		stacks[0+army1.slots.size()]->position = 49; //3
+		stacks[1+army1.slots.size()]->position = 100; //6
+		stacks[2+army1.slots.size()]->position = 151; //9
+		break;
+	case 4:
+		stacks[0+army1.slots.size()]->position = 15; //1
+		stacks[1+army1.slots.size()]->position = 83; //5
+		stacks[2+army1.slots.size()]->position = 117; //7
+		stacks[3+army1.slots.size()]->position = 185; //11
+		break;
+	case 5:
+		stacks[0+army1.slots.size()]->position = 15; //1
+		stacks[1+army1.slots.size()]->position = 49; //3
+		stacks[2+army1.slots.size()]->position = 100; //6
+		stacks[3+army1.slots.size()]->position = 151; //9
+		stacks[4+army1.slots.size()]->position = 185; //11
+		break;
+	case 6:
+		stacks[0+army1.slots.size()]->position = 15; //1
+		stacks[1+army1.slots.size()]->position = 49; //3
+		stacks[2+army1.slots.size()]->position = 83; //5
+		stacks[3+army1.slots.size()]->position = 117; //7
+		stacks[4+army1.slots.size()]->position = 151; //9
+		stacks[5+army1.slots.size()]->position = 185; //11
+		break;
+	case 7:
+		stacks[0+army1.slots.size()]->position = 15; //1
+		stacks[1+army1.slots.size()]->position = 49; //3
+		stacks[2+army1.slots.size()]->position = 83; //5
+		stacks[3+army1.slots.size()]->position = 100; //6
+		stacks[4+army1.slots.size()]->position = 117; //7
+		stacks[5+army1.slots.size()]->position = 151; //9
+		stacks[6+army1.slots.size()]->position = 185; //11
+		break;
+	default: //fault
+		break;
+	}
+	for(unsigned g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
+	{
+		if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
+		{
+			stacks[g]->position += 1;
+		}
+		else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
+		{
+			stacks[g]->position -= 1;
+		}
+	}
+	std::stable_sort(stacks.begin(),stacks.end(),cmpst);
+
+	//block engaged players
+	if(hero1->tempOwner<PLAYER_LIMIT)
+		states.setFlag(hero1->tempOwner,&PlayerStatus::engagedIntoBattle,true);
+	if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
+		states.setFlag(hero2->tempOwner,&PlayerStatus::engagedIntoBattle,true);
+
+	//send info about battles
+	BattleStart bs;
+	bs.info = curB;
+	sendAndApply(&bs);
+}

+ 1 - 1
server/CGameHandler.h

@@ -53,7 +53,7 @@ class CGameHandler
 	void changeSecSkill(int ID, ui16 which, int val, bool abs=false);
 	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 setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 );
 
 public:
 	CGameHandler(void);

Some files were not shown because too many files changed in this diff