瀏覽代碼

Third part of GUI reorganization:
* Rewritten pregame
* FNT fonts support
* Several additions to GUI system.

Changes are significant, some things may be broken.

Michał W. Urbańczyk 16 年之前
父節點
當前提交
b4070c6b3e

+ 7 - 0
StartInfo.h

@@ -40,6 +40,13 @@ struct PlayerSettings
 		h & name;
 		h & human;
 	}
+
+	PlayerSettings()
+	{
+		bonus = brandom;
+		castle = -2;
+		heroPortrait = -1;
+	}
 };
 
 struct StartInfo

+ 254 - 91
client/AdventureMapButton.cpp

@@ -11,6 +11,7 @@
 #include "Graphics.h"
 #include "CBattleInterface.h"
 #include "CPlayerInterface.h"
+#include "CMessage.h"
 
 /*
  * AdevntureMapButton.cpp, part of VCMI engine
@@ -22,11 +23,71 @@
  *
  */
 
+CButtonBase::CButtonBase()
+{
+	bitmapOffset = 0;
+	curimg=0;
+	type=-1;
+	abs=false;
+	//active=false;
+	notFreeButton = false;
+	ourObj=NULL;
+	state=0;
+	text = NULL;
+}
+
+CButtonBase::~CButtonBase()
+{
+	delete text;
+	if(notFreeButton)
+		return;
+	for(int i =0; i<imgs.size();i++)
+		for(int j=0;j<imgs[i].size();j++)
+			SDL_FreeSurface(imgs[i][j]);
+}
+
+void CButtonBase::show(SDL_Surface * to)
+{
+	int img = std::min(state+bitmapOffset,int(imgs[curimg].size()-1));
+	img = std::max(0, img);
+
+	if (abs)
+	{
+		blitAt(imgs[curimg][img],pos.x,pos.y,to);
+		if(text)
+		{
+			CSDL_Ext::printAt(text->text, text->x + pos.x + state, text->y + pos.y + state, text->font, zwykly, to);
+		}
+	}
+	else
+	{
+		blitAt(imgs[curimg][img],pos.x+ourObj->pos.x,pos.y+ourObj->pos.y,to);
+	}
+}
+
+void CButtonBase::showAll( SDL_Surface * to )
+{
+	show(to);
+}
+
+void CButtonBase::addTextOverlay( const std::string Text, EFonts font )
+{
+	text = new TextOverlay;
+	text->text = Text;
+
+	const Font *f = graphics->fonts[font];
+	text->x = pos.w/2 - f->getWidth(Text.c_str())/2;
+	text->y = pos.h/2 - f->height/2;
+	text->font = font;
+}
+
+
 AdventureMapButton::AdventureMapButton ()
 {
 	type=2;
 	abs=true;
-	active=false;
+	hoverable = false;
+	//active=false;
 	ourObj=NULL;
 	state=0;
 	blocked = actOnDown = false;
@@ -81,17 +142,36 @@ void AdventureMapButton::clickLeft(tribool down, bool previousState)
 
 void AdventureMapButton::clickRight(tribool down, bool previousState)
 {
-	if(helpBox.size()) //there is no point to show window with nothing inside...
-		LOCPLINT->adventureInt->handleRightClick(helpBox,down,this);
+	if(down && helpBox.size()) //there is no point to show window with nothing inside...
+		if(LOCPLINT)
+			LOCPLINT->adventureInt->handleRightClick(helpBox,down,this);
+		else
+			GH.pushInt(new CRClickPopupInt(CMessage::genWindow(helpBox, 0),true));
 }
 
 void AdventureMapButton::hover (bool on)
 {
+	if(hoverable)
+	{
+		if(on)
+			state = 2;
+		else
+			state = 0;
+	}
+
+	if(pressedL)
+	{
+		if(on)
+			state = 1;
+		else
+			state = hoverable ? 2 : 0;
+	}
+
 	////Hoverable::hover(on);
 	std::string *name = (vstd::contains(hoverTexts,state)) 
 							? (&hoverTexts[state]) 
 							: (vstd::contains(hoverTexts,0) ? (&hoverTexts[0]) : NULL);
-	if(name && blocked!=1) //if there is no name, there is nohing to display also
+	if(LOCPLINT &&  name && blocked!=1) //if there is no name, there is nohing to display also
 	{
 		if (LOCPLINT->battleInt) //for battle buttons
 		{
@@ -118,8 +198,8 @@ void AdventureMapButton::hover (bool on)
 
 void AdventureMapButton::activate()
 {
-	if (active) return;
-	active=true;
+// 	if (active) return;
+// 	active=true;
 	activateLClick();
 	activateRClick();
 	activateHover();
@@ -127,8 +207,8 @@ void AdventureMapButton::activate()
 }
 void AdventureMapButton::deactivate()
 {
-	if (!active) return;
-	active=false;
+// 	if (!active) return;
+// 	active=false;
 	deactivateLClick();
 	deactivateRClick();
 	deactivateHover();
@@ -141,31 +221,22 @@ void AdventureMapButton::init(const CFunctionList<void()> &Callback, const std::
 	blocked = actOnDown = false;
 	type=2;
 	abs=true;
-	active=false;
+	hoverable = false;
+	//active=false;
 	ourObj=NULL;
 	assignedKeys.insert(key);
 	state=0;
 	hoverTexts = Name;
 	helpBox=HelpBox;
-	//int est = LOCPLINT->playerID; //TODO use me
-	CDefHandler * temp = CDefHandler::giveDef(defName); 
-	temp->notFreeImgs = true;
-	for (size_t 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;
+
+	setDef(defName, playerColoredButton);
+
 	if (add && add->size())
 	{
 		imgs.resize(imgs.size()+add->size());
 		for (size_t i=0; i<add->size();i++)
 		{
-			temp = CDefHandler::giveDef((*add)[i]);
+			CDefHandler *temp = CDefHandler::giveDef((*add)[i]);
 			temp->notFreeImgs = true;
 			for (size_t j=0;j<temp->ourImages.size();j++)
 			{
@@ -179,8 +250,8 @@ void AdventureMapButton::init(const CFunctionList<void()> &Callback, const std::
 		}
 		//delete add;
 	}
-	pos.x=x;
-	pos.y=y;
+	pos.x += x;
+	pos.y += y;
 	pos.w = imgs[curimg][0]->w;
 	pos.h = imgs[curimg][0]->h  -1;
 }
@@ -193,6 +264,21 @@ void AdventureMapButton::block( ui8 on )
 	show(screenBuf);
 }
 
+void AdventureMapButton::setDef(const std::string & defName, bool playerColoredButton)
+{
+	CDefHandler * temp = CDefHandler::giveDef(defName); 
+	temp->notFreeImgs = true;
+	for (size_t 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;
+}
 void CHighlightableButton::select(bool on)
 {
 	selected = on;
@@ -230,6 +316,14 @@ CHighlightableButton::CHighlightableButton( const CFunctionList<void()> &onSelec
 	init(onSelect,Name,HelpBox,playerColoredButton,defName,add,x,y,key);
 }
 
+CHighlightableButton::CHighlightableButton( const std::pair<std::string, std::string> help, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key/*=0*/, std::vector<std::string> * add /*= NULL*/, bool playerColoredButton /*= false */ )
+{
+	ID = myid;
+	std::map<int,std::string> pom;
+	pom[0] = help.first;
+	init(onSelect, pom, help.second, playerColoredButton, defName, add, x, y, key);
+}
+
 void CHighlightableButtonsGroup::addButton(CHighlightableButton* bt)
 {
 	bt->callback += boost::bind(&CHighlightableButtonsGroup::selectionChanged,this,bt->ID);
@@ -311,6 +405,11 @@ void CHighlightableButtonsGroup::show(SDL_Surface * to )
 	}
 }
 
+void CHighlightableButtonsGroup::showAll( SDL_Surface * to )
+{
+	show(to);
+}
+
 void CSlider::sliderClicked()
 {
 	if(!moving)
@@ -322,11 +421,23 @@ void CSlider::sliderClicked()
 
 void CSlider::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 {
-	if(	std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2+40  ||  std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2  ) 
-		return;
-	float v = sEvent.x - pos.x - 24;
-	v*=amount;
-	v/= (pos.w - 48);
+	float v = 0;
+	if(horizontal)
+	{
+		if(	std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2+40  ||  std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2  ) 
+			return;
+		v = sEvent.x - pos.x - 24;
+		v *= positions;
+		v /= (pos.w - 48);
+	}
+	else
+	{
+		if(std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2+40  ||  std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2  ) 
+			return;
+		v = sEvent.y - pos.y - 24;
+		v *= positions;
+		v /= (pos.h - 48);
+	}
 	v += 0.5f;
 	if(v!=value)
 	{
@@ -337,7 +448,7 @@ void CSlider::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 
 void CSlider::redrawSlider()
 {
-	slider.show(screenBuf);
+	slider->show(screenBuf);
 }
 
 void CSlider::moveLeft()
@@ -352,47 +463,60 @@ void CSlider::moveRight()
 
 void CSlider::moveTo(int to)
 {
-	if(to<0)
-		to=0;
-	else if(to>amount)
-		to=amount;
+	amax(to, 0);
+	amin(to, positions);
+
+	//same, old position?
+	if(value == to)
+		return;
+
 	value = to;
-	if(amount)
+	if(horizontal)
 	{
-		float part = (float)to/amount;
-		part*=(pos.w-48);
-		slider.pos.x = part + pos.x + 16;
+		if(positions)
+		{
+			float part = (float)to/positions;
+			part*=(pos.w-48);
+			slider->pos.x = part + pos.x + 16;
+		}
+		else
+			slider->pos.x = pos.x+16;
 	}
 	else
-		slider.pos.x = pos.x+16;
+	{
+		if(positions)
+		{
+			float part = (float)to/positions;
+			part*=(pos.h-48);
+			slider->pos.y = part + pos.y + 16;
+		}
+		else
+			slider->pos.y = pos.y+16;
+	}
 	moved(to);
 }
 
-void CSlider::activate() // makes button active
-{
-	left.activate();
-	right.activate();
-	slider.activate();
-	activateLClick();
-}
-
-void CSlider::deactivate() // makes button inactive (but doesn't delete)
-{
-	left.deactivate();
-	right.deactivate();
-	slider.deactivate();
-	deactivateLClick();
-}
-
 void CSlider::clickLeft(tribool down, bool previousState)
 {
 	if(down)
 	{
-		float pw = GH.current->motion.x-pos.x-24;
-		float rw = pw / ((float)(pos.w-48));
-		if (rw>1) return;
-		if (rw<0) return;
-		moveTo(rw*amount+0.5f);
+		float pw = 0;
+		float rw = 0;
+		if(horizontal)
+		{
+			pw = GH.current->motion.x-pos.x-24;
+			rw = pw / ((float)(pos.w-48));
+		}
+		else
+		{
+			pw = GH.current->motion.y-pos.y-24;
+			rw = pw / ((float)(pos.h-48));
+		}
+		if(pw < -8  ||  pw > (horizontal ? pos.w : pos.h) + 8)
+			return;
+// 		if (rw>1) return;
+// 		if (rw<0) return;
+		moveTo(rw * positions  +  0.5f);
 		return;
 	}
 	if(moving)
@@ -402,46 +526,85 @@ void CSlider::clickLeft(tribool down, bool previousState)
 	}
 }
 
-void CSlider::show(SDL_Surface * to)
-{
-	left.show(to);
-	right.show(to);
-	slider.show(to);
-}
-
 CSlider::~CSlider()
 {
 	delete imgs;
 }
 
-CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal)
-:capacity(Capacity),amount(Amount),value(Value),horizontal(Horizontal), moved(Moved)
+CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, int style)
+:capacity(Capacity),amount(Amount),horizontal(Horizontal), moved(Moved)
 {
+	OBJ_CONSTRUCTION;
+	setAmount(amount);
+
+	used = LCLICK;
 	moving = false;
 	strongInterest = true;
-	imgs = CDefHandler::giveDefEss("IGPCRDIV.DEF");
-
-	left.pos.y = slider.pos.y = right.pos.y = pos.y = y;
-	left.pos.x = pos.x = x;
-	right.pos.x = x + totalw - 16;
-	left.callback = boost::bind(&CSlider::moveLeft,this);
-	right.callback = boost::bind(&CSlider::moveRight,this);
-	slider.callback = boost::bind(&CSlider::sliderClicked,this);
-	left.pos.w = left.pos.h = right.pos.w = right.pos.h = slider.pos.w = slider.pos.h = pos.h = 16;
-	pos.w = totalw;
-	left.imgs.resize(1); right.imgs.resize(1); slider.imgs.resize(1);
-	left.imgs[0].push_back(imgs->ourImages[0].bitmap); left.imgs[0].push_back(imgs->ourImages[1].bitmap);
-	right.imgs[0].push_back(imgs->ourImages[2].bitmap); right.imgs[0].push_back(imgs->ourImages[3].bitmap);
-	slider.imgs[0].push_back(imgs->ourImages[4].bitmap);
-	left.notFreeButton = right.notFreeButton = slider.notFreeButton = true;
-	slider.actOnDown = true;
-
-	moveTo(value);
+
+
+	left = new AdventureMapButton;
+	right = new AdventureMapButton;
+	slider = new AdventureMapButton;
+
+	if(horizontal)
+	{
+		left->pos.y = slider->pos.y = right->pos.y = pos.y = y;
+		left->pos.x = pos.x = x;
+		right->pos.x = x + totalw - 16;
+	}
+	else 
+	{
+		left->pos.x = slider->pos.x = right->pos.x = pos.x = x;
+		left->pos.y = pos.y = y;
+		right->pos.y = y + totalw - 16;
+	}
+
+	left->callback = boost::bind(&CSlider::moveLeft,this);
+	right->callback = boost::bind(&CSlider::moveRight,this);
+	slider->callback = boost::bind(&CSlider::sliderClicked,this);
+	left->pos.w = left->pos.h = right->pos.w = right->pos.h = slider->pos.w = slider->pos.h = 16;
+	if(horizontal)
+	{
+		pos.h = 16;
+		pos.w = totalw;
+	}
+	else
+	{
+		pos.w = 16;
+		pos.h = totalw;
+	}
+
+	if(style == 0)
+	{
+		imgs = CDefHandler::giveDefEss("IGPCRDIV.DEF");
+		left->imgs.resize(1); right->imgs.resize(1); slider->imgs.resize(1);
+		left->imgs[0].push_back(imgs->ourImages[0].bitmap); left->imgs[0].push_back(imgs->ourImages[1].bitmap);
+		right->imgs[0].push_back(imgs->ourImages[2].bitmap); right->imgs[0].push_back(imgs->ourImages[3].bitmap);
+		slider->imgs[0].push_back(imgs->ourImages[4].bitmap);
+		left->notFreeButton = right->notFreeButton = slider->notFreeButton = true;
+	}
+	else
+	{
+		imgs = NULL;
+		left->setDef(horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", false);
+		right->setDef(horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", false);
+		slider->setDef("SCNRBSL.DEF", false);
+	}
+	slider->actOnDown = true;
+
+	value = -1;
+	moveTo(Value);
 }
 
 void CSlider::block( bool on )
 {
-	left.block(on);
-	right.block(on);
-	slider.block(on);
+	left->block(on);
+	right->block(on);
+	slider->block(on);
+}
+
+void CSlider::setAmount( int to )
+{
+	positions = to - capacity;
+	amax(positions, 1);
 }

+ 43 - 8
client/AdventureMapButton.h

@@ -19,14 +19,44 @@ class CDefEssential;
 
 namespace config{struct ButtonInfo;}
 
+
+class CButtonBase : public KeyShortcut//basic buttton class
+{
+public:
+	struct TextOverlay
+	{
+		EFonts font;
+		std::string text;
+		int x, y;
+	} *text;
+	void addTextOverlay(const std::string Text, EFonts font);
+
+	int bitmapOffset; //TODO: comment me
+	int type; //advmapbutton=2 //TODO: comment me
+	bool abs;//TODO: comment me
+	//bool active; //if true, this button is active and can be pressed
+	bool notFreeButton; //TODO: comment me
+	CIntObject * ourObj; // "owner"
+	int state; //TODO: comment me
+	std::vector< std::vector<SDL_Surface*> > imgs; //images for this button
+	int curimg; //curently displayed image from imgs
+	virtual void show(SDL_Surface * to);
+	virtual void showAll(SDL_Surface * to);
+	virtual void activate()=0;
+	virtual void deactivate()=0;
+	CButtonBase(); //c-tor
+	virtual ~CButtonBase(); //d-tor
+};
+
+
 class AdventureMapButton : public CButtonBase
 {
 public:
 	std::map<int,std::string> hoverTexts; //state -> text for statusbar
 	std::string helpBox; //for right-click help
 	CFunctionList<void()> callback;
-	bool colorChange, 
-		actOnDown; //runs when mouse is pressed down over it, not when up
+	bool actOnDown, //runs when mouse is pressed down over it, not when up
+		hoverable; //if true, button will be highlighted when hovered
 	ui8 blocked;
 
 	void clickRight(tribool down, bool previousState);
@@ -44,6 +74,7 @@ public:
 	//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(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key );
+	void setDef(const std::string & defName, bool playerColoredButton);
 };
 
 class CHighlightableButton 
@@ -51,13 +82,14 @@ class CHighlightableButton
 {
 public:
 	CHighlightableButton(const CFunctionList<void()> &onSelect, const CFunctionList<void()> &onDeselect, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key=0);
+	CHighlightableButton(const std::pair<std::string, std::string> help, const CFunctionList<void()> &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
 	bool selected, onlyOn;
 	CFunctionList<void()> callback2; //when disselecting
 	void select(bool on);
 	void clickLeft(tribool down, bool previousState);
 };
 
-class CHighlightableButtonsGroup
+class CHighlightableButtonsGroup : public CIntObject
 {
 public:
 	CFunctionList2<void(int)> onChange; //called when changing selected button with new button's id
@@ -74,15 +106,17 @@ public:
 	void select(int id, bool mode); //mode==0: id is serial; mode==1: id is unique button id
 	void selectionChanged(int to);
 	void show(SDL_Surface * to);
+	void showAll(SDL_Surface * to);
 };
 
 
 class CSlider : public CIntObject
 {
 public:
-	AdventureMapButton left, right, slider; //if vertical then left=up
+	AdventureMapButton *left, *right, *slider; //if vertical then left=up
 	int capacity,//how many elements can be active at same time
 		amount, //how many elements
+		positions, //number of highest position (0 if there is only one)
 		value; //first active element
 	bool horizontal, moving;
 	CDefEssential *imgs ;
@@ -100,11 +134,12 @@ public:
 	void moveRight();
 	void moveTo(int to);
 	void block(bool on);
-	void activate(); // makes button active
-	void deactivate(); // makes button inactive (but doesn't delete)
-	void show(SDL_Surface * to);
+	void setAmount(int to);
+	//void activate(); // makes button active
+	//void deactivate(); // makes button inactive (but doesn't delete)
+	//void show(SDL_Surface * to);
 	CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int Capacity, int Amount, 
-		int Value=0, bool Horizontal=true);
+		int Value=0, bool Horizontal=true, int style = 0); //style 0 - brown, 1 - blue
 	~CSlider();
 };	
 

+ 0 - 4
client/CAdvmapInterface.cpp

@@ -1689,11 +1689,7 @@ void CAdvMapInt::handleRightClick(std::string text, tribool down, CIntObject * c
 {
 	if (down)
 	{
-		//boost::algorithm::erase_all(text,"\"");
 		CSimpleWindow * temp = CMessage::genWindow(text,LOCPLINT->playerID);
-		temp->pos.x=screen->w/2-(temp->pos.w/2);
-		temp->pos.y=screen->h/2-(temp->pos.h/2);
-		temp->owner = client;
 		CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
 		GH.pushInt(rcpi);
 	}

+ 5 - 2
client/CBitmapHandler.cpp

@@ -364,7 +364,10 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
 	CPCXConv cp;
 	cp.openPCX((char*)pcx,e->realSize);
 	SDL_Surface * ret = cp.getSurface();
-	if(setKey)
-		SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
+	if(ret->format->BytesPerPixel == 1  &&  setKey)
+	{
+		const SDL_Color &c = ret->format->palette->colors[0];
+		SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format, c.r, c.g, c.b));
+	}
 	return ret;
 }

+ 1 - 1
client/CBitmapHandler.h

@@ -47,7 +47,7 @@ public:
 };
 namespace BitmapHandler
 {
-	SDL_Surface * loadBitmap(std::string fname, bool setKey=false);
+	SDL_Surface * loadBitmap(std::string fname, bool setKey=true);
 };
 
 #endif // __CBITMAPHANDLER_H__

+ 1 - 0
client/CHeroWindow.h

@@ -62,6 +62,7 @@ public:
 	void activate(); //activates hero window;
 	void deactivate(); //activates hero window;
 	virtual void show(SDL_Surface * to); //shows hero window
+	void showAll(SDL_Surface * to){show(to);};
 	void redrawCurBack(); //redraws curBAck from scratch
 	void dispose(); //free resources not needed after closing windows and reset state
 	void quit(); //stops displaying hero window and disposes

+ 155 - 130
client/CMT.cpp

@@ -60,6 +60,7 @@
 std::string NAME_AFFIX = "client";
 std::string NAME = NAME_VER + std::string(" (") + NAME_AFFIX + ')'; //application name
 CGuiHandler GH;
+CClient *client = NULL;
 SDL_Surface *screen = NULL, //main screen surface 
 	*screen2 = NULL,//and hlp surface (used to store not-active interfaces layer) 
 	*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
@@ -71,10 +72,12 @@ boost::mutex eventsM;
 TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
 static bool gOnlyAI = false;
 
-void processCommand(const std::string &message, CClient *&client);
+void processCommand(const std::string &message);
 static void setScreenRes(int w, int h, int bpp, bool fullscreen);
 void dispose();
 void playIntro();
+void listenForEvents();
+void startGame(StartInfo * options);
 
 void init()
 {
@@ -150,8 +153,8 @@ void init()
 
 	CMessage::init();
 	tlog0<<"Message handler: "<<tmh.getDif()<<std::endl;
-	CPG = new CPreGame(); //main menu and submenus
-	tlog0<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
+	//CPG = new CPreGame(); //main menu and submenus
+	//tlog0<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
 }
 
 #ifndef __GNUC__
@@ -162,11 +165,10 @@ int main(int argc, char** argv)
 {
 	tlog0 << "Starting... " << std::endl;
 	timeHandler total, pomtime;
-	CClient *client = NULL;
 	std::cout.flags(std::ios::unitbuf);
 	logfile = new std::ofstream("VCMI_Client_log.txt");
 	console = new CConsoleHandler;
-	*console->cb = boost::bind(&processCommand, _1, boost::ref(client));
+	*console->cb = boost::bind(&processCommand, _1);
 	console->start();
 	atexit(dispose);
 	tlog0 <<"Creating console and logfile: "<<pomtime.getDif() << std::endl;
@@ -176,124 +178,38 @@ int main(int argc, char** argv)
 	tlog0 << NAME << std::endl;
 
 	srand ( time(NULL) );
-	CPG=NULL;
+	//CPG=NULL;
 	atexit(SDL_Quit);
 	CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
-	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO)==0)
+	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO))
 	{
-		setScreenRes(800,600,conf.cc.bpp,conf.cc.fullscreen);
-		tlog0 <<"\tInitializing screen: "<<pomtime.getDif() << std::endl;
-
-		// Initialize video
-		CGI->videoh = new CVideoPlayer;
-		tlog0<<"\tInitializing video: "<<pomtime.getDif()<<std::endl;
-
-		//we can properly play intro only in the main thread, so we have to move loading to the separate thread
-		boost::thread loading(init);
-		playIntro();
-		SDL_FillRect(screen,NULL,0);
-		SDL_Flip(screen);
-		loading.join();
-		tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;
-
-
-		SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-		CGI->musich->playMusic(musicBase::mainMenu, -1);
-		CPG->showMainMenu();
-		StartInfo *options = new StartInfo(CPG->runLoop());
-
-		if(gOnlyAI)
-		{
-			for (size_t i =0; i < options->playerInfos.size(); i++)
-			{
-				options->playerInfos[i].human = false;
-			}
-		}
-
-		if(screen->w != conf.cc.resx   ||   screen->h != conf.cc.resy)
-		{
-			setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
-		}
-		CClient cl;
-		if(options->mode == 0) //new game
-		{
-			pomtime.getDif();
-			char portc[10];
-			SDL_itoa(conf.cc.port,portc,10);
-			CClient::runServer(portc);
-			tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
-
-			pomtime.getDif();//reset timers
-
-			CConnection *c=NULL;
-			//wait until server is ready
-			tlog0<<"Waiting for server... ";
-			cl.waitForServer();
-			tlog0 << pomtime.getDif()<<std::endl;
-			while(!c)
-			{
-				try
-				{
-					tlog0 << "Establishing connection...\n";
-					c = new CConnection(conf.cc.server,portc,NAME);
-				}
-				catch(...)
-				{
-					tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
-					SDL_Delay(2000);
-				}
-			}
-			THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
-			cl.newGame(c,options);
-			client = &cl;
-			CGI->musich->stopMusic();
-			boost::thread t(boost::bind(&CClient::run,&cl));
-		}
-		else //load game
-		{
-			std::string fname = options->mapname;
-			boost::algorithm::erase_last(fname,".vlgm1");
-			cl.load(fname);
-			client = &cl;
-			CGI->musich->stopMusic();
-			boost::thread t(boost::bind(&CClient::run,&cl));
-		}
-
-		SDL_Event *ev = NULL;
-		while(1) //main SDL events loop
-		{
-			ev = new SDL_Event();
-
-			int ret = SDL_WaitEvent(ev);
-			if(ret == 0 || (ev->type==SDL_QUIT)  ||  (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
-			{
-				LOCPLINT->pim->lock();
-				cl.close();
-				console->end();
-				SDL_Delay(750);
-				tlog0 << "Ending...\n";
-				exit(EXIT_SUCCESS);
-			}
-			else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
-			{
-				boost::unique_lock<boost::recursive_mutex> lock(*LOCPLINT->pim);
-				bool full = !(screen->flags&SDL_FULLSCREEN);
-				setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
-				GH.totalRedraw();
-			}
-			eventsM.lock();
-			events.push(ev);
-			eventsM.unlock();
-		}
-	}
-	else
-	{
-		tlog1<<"Something was wrong: "<<SDL_GetError()<<std::endl;
-		return -1;
+		tlog1<<"Something was wrong: "<< SDL_GetError() << std::endl;
+		exit(-1);
 	}
+
+	setScreenRes(800,600,conf.cc.bpp,conf.cc.fullscreen);
+	tlog0 <<"\tInitializing screen: "<<pomtime.getDif() << std::endl;
+
+	// Initialize video
+	CGI->videoh = new CVideoPlayer;
+	tlog0<<"\tInitializing video: "<<pomtime.getDif()<<std::endl;
+
+	//we can properly play intro only in the main thread, so we have to move loading to the separate thread
+	boost::thread loading(init);
+	playIntro();
+	SDL_FillRect(screen,NULL,0);
+	SDL_Flip(screen);
+	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+	loading.join();
+	tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;
+
+	new CGPreGame; //will set CGP pointer to itself
+	CGI->musich->playMusic(musicBase::mainMenu, -1);
+	boost::thread hhh(&CGPreGame::run, CGP);
+	listenForEvents();
 }
 
-void processCommand(const std::string &message, CClient *&client)
+void processCommand(const std::string &message)
 {
 	std::istringstream readed;
 	readed.str(message);
@@ -326,31 +242,47 @@ void processCommand(const std::string &message, CClient *&client)
 			break;
 		}
 	}
+	else if(cn=="screen")
+	{
+		tlog0 << "Screenbuf points to ";
+
+		if(screenBuf == screen)
+			tlog1 << "screen";
+		else if(screenBuf == screen2)
+			tlog1 << "screen2";
+		else
+			tlog1 << "?!?";
+
+		tlog1 << std::endl;
+
+		SDL_SaveBMP(screen, "Screen_c.bmp");
+		SDL_SaveBMP(screen2, "Screen2_c.bmp");
+	}
 	else if(cn=="save")
 	{
 		std::string fname;
 		readed >> fname;
 		client->save(fname);
 	}
-	else if(cn=="list")
-	{
-		if(CPG)
-			for(int i = 0; i < CPG->ourScenSel->mapsel.ourGames.size(); i++)
-				tlog0 << i << ".\t" << CPG->ourScenSel->mapsel.ourGames[i]->filename << std::endl;
-	}
+	//else if(cn=="list")
+	//{
+	//	if(CPG)
+	//		for(int i = 0; i < CPG->ourScenSel->mapsel.ourGames.size(); i++)
+	//			tlog0 << i << ".\t" << CPG->ourScenSel->mapsel.ourGames[i]->filename << std::endl;
+	//}
 	else if(cn=="load")
 	{
 		std::string fname;
 		readed >> fname;
 		client->load(fname);
 	}
-	else if(cn=="ln")
-	{
-		int num;
-		readed >> num;
-		std::string &name = CPG->ourScenSel->mapsel.ourGames[num]->filename;
-		client->load(name.substr(0, name.size()-6));
-	}
+	//else if(cn=="ln")
+	//{
+	//	int num;
+	//	readed >> num;
+	//	std::string &name = CPG->ourScenSel->mapsel.ourGames[num]->filename;
+	//	client->load(name.substr(0, name.size()-6));
+	//}
 	else if(cn=="resolution")
 	{
 		if(LOCPLINT)
@@ -481,3 +413,96 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen)
 	SDL_WM_SetCaption(NAME.c_str(),""); //set window title
 	SDL_ShowCursor(SDL_DISABLE);
 }
+
+void listenForEvents() 
+{
+	SDL_Event *ev = NULL;
+	while(1) //main SDL events loop
+	{
+		ev = new SDL_Event();
+
+		int ret = SDL_WaitEvent(ev);
+		if(ret == 0 || (ev->type==SDL_QUIT)  ||  (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
+		{
+			LOCPLINT->pim->lock();
+			client->close();
+			console->end();
+			SDL_Delay(750);
+			tlog0 << "Ending...\n";
+			exit(EXIT_SUCCESS);
+		}
+		else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
+		{
+			boost::unique_lock<boost::recursive_mutex> lock(*LOCPLINT->pim);
+			bool full = !(screen->flags&SDL_FULLSCREEN);
+			setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
+			GH.totalRedraw();
+		}
+		eventsM.lock();
+		events.push(ev);
+		eventsM.unlock();
+	}
+}
+
+void startGame(StartInfo * options) 
+{
+	if(gOnlyAI)
+	{
+		for (size_t i =0; i < options->playerInfos.size(); i++)
+		{
+			options->playerInfos[i].human = false;
+		}
+	}
+
+	if(screen->w != conf.cc.resx   ||   screen->h != conf.cc.resy)
+	{
+		setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
+	}
+
+	CClient cl;
+	if(options->mode == 0) //new game
+	{
+		timeHandler pomtime;
+		char portc[10];
+		SDL_itoa(conf.cc.port,portc,10);
+		CClient::runServer(portc);
+		tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
+
+		pomtime.getDif();//reset timers
+
+		CConnection *c=NULL;
+		//wait until server is ready
+		tlog0<<"Waiting for server... ";
+		cl.waitForServer();
+		tlog0 << pomtime.getDif()<<std::endl;
+		while(!c)
+		{
+			try
+			{
+				tlog0 << "Establishing connection...\n";
+				c = new CConnection(conf.cc.server,portc,NAME);
+			}
+			catch(...)
+			{
+				tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
+				SDL_Delay(2000);
+			}
+		}
+		THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
+		cl.newGame(c,options);
+		client = &cl;
+		CGI->musich->stopMusic();
+		client->run();
+		//boost::thread t(boost::bind(&CClient::run,&cl));
+	}
+	else //load game
+	{
+		std::string fname = options->mapname;
+		boost::algorithm::erase_last(fname,".vlgm1");
+		cl.load(fname);
+		client = &cl;
+		CGI->musich->stopMusic();
+		client->run();
+		//boost::thread t(boost::bind(&CClient::run,&cl));
+	}
+}

+ 7 - 3
client/CMessage.cpp

@@ -27,7 +27,9 @@
  *
  */
 
-SDL_Color tytulowy, tlo, zwykly ;
+SDL_Color tytulowy = {229, 215, 123, 0}, 
+	tlo = {66, 44, 24, 0}, 
+	zwykly = {255, 255, 255, 0};
 
 extern SDL_Surface * screen;
 extern TTF_Font * TNRB16, *TNR, *GEOR13;
@@ -316,8 +318,10 @@ CSimpleWindow * CMessage::genWindow(std::string text, int player, int Lmar, int
 	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(brtext, fontHeight);
 	std::pair<int,int> txts = getMaxSizes(txtg, fontHeight);
 	ret->bitmap = drawBox1(txts.first+Lmar+Rmar,txts.second+Tmar+Bmar,player);
-	ret->pos.h=ret->bitmap->h;
-	ret->pos.w=ret->bitmap->w;
+	ret->pos.h = ret->bitmap->h;
+	ret->pos.w = ret->bitmap->w;
+	ret->pos.x = screen->w/2 - (ret->pos.w/2);
+	ret->pos.y = screen->h/2 - (ret->pos.h/2);
 	int curh = ret->bitmap->h/2 - (fontHeight*txtg->size())/2;
 	blitTextOnSur(txtg,fontHeight,curh,ret->bitmap);
 	delete brtext;

文件差異過大導致無法顯示
+ 409 - 766
client/CPreGame.cpp


+ 136 - 252
client/CPreGame.h

@@ -9,6 +9,7 @@
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
 #include <cstdlib>
+#include "GUIBase.h"
 
 /*
  * CPreGame.h, part of VCMI engine
@@ -21,288 +22,171 @@
  */
 
 struct CMusicHandler;
-class CPreGame;
-class CDefHandler;
-extern CPreGame * CPG;
+using boost::bind;
+using boost::ref;
 
-typedef void(CPreGame::*ttt)();
-class CGroup;
-class CPoinGroup ;
-class IntSelBut;
-
-struct HighButton
-{
-	int ID;
-	int type;
-	SDL_Rect pos;
-	CDefHandler* imgs;
-	int state;
-	bool freeimgs;
-	HighButton( SDL_Rect Pos, CDefHandler* Imgs, bool Sel=false, int id=-1);
-	HighButton();
-	virtual ~HighButton();
-	bool selectable, selected;
-	bool highlightable, highlighted;
-	virtual void show();
-	virtual void press(bool down=true);
-	virtual	void hover(bool on=true)=0;
-	virtual void select(bool on=true)=0;
-};
-struct Button: public HighButton
-{
-	CGroup *ourGroup;
-	Button( SDL_Rect Pos, boost::function<void()> Fun,CDefHandler* Imgs, bool Sel=false, CGroup* gr=NULL, int id=-1);
-	Button();
-	boost::function<void()> fun;
-	virtual	void hover(bool on=true);
-	virtual void select(bool on=true);
-};
-struct SetrButton: public Button
-{
-	int key, * poin;
-	virtual void press(bool down=true);
-	SetrButton();
+enum EState { //where are we?
+	mainMenu, newGame, loadGame, ScenarioList, saveGame
 };
 
-class Slider
-{
-public:
-	bool vertical; // false means horizontal
-	SDL_Rect pos; // position
-	Button *up, *down, //or left/right
-		*slider;
-	int positionsAmnt, capacity;// capacity - amount of positions dispplayed at once
-	int whereAreWe; // first displayed thing
-	bool moving;
-	boost::function<void(int)> fun;
-	void clickDown(int x, int y, bool bzgl=true);
-	void clickUp(int x, int y, bool bzgl=true);
-	void mMove(int x, int y, bool bzgl=true);
-	void moveUp();
-	void moveDown();
-	void deactivate();
-	void activate();
-	Slider(int x, int y, int h, int amnt, int cap, bool ver);
-	~Slider();
-	void updateSlid();
-	void handleIt(SDL_Event sev);
-};
 
-struct IntBut: public Button
+class CMenuScreen : public CIntObject
 {
 public:
-	int key;
-	int * what;
-	IntBut();
-	void set();
+	CPicture *bgAd;
+	AdventureMapButton *buttons[5];
+
+	CMenuScreen(EState which);
+	~CMenuScreen();
+	void showAll(SDL_Surface * to);
+	void show(SDL_Surface * to);
+	void moveTo(CMenuScreen *next);
 };
-class CGroup
+
+
+struct FileInfo
 {
-public:
-	Button * selected;
-	int type; // 1=sinsel
-	CGroup():selected(NULL),type(0){};
+	std::string name;
+	std::time_t date;
 };
 
-class CPoinGroup :public CGroup
+class InfoCard : public CIntObject
 {
 public:
-	int * gdzie; //where (po polsku, bo by by�o s�owo kluczowe :/)
-	void setYour(IntSelBut * your);
+	CPicture *bg; 
+	EState type;
+
+	CHighlightableButtonsGroup *difficulty;
+	CDefHandler *sizes, *sFlags;;
+
+	void changeSelection(const CMapInfo *to);
+	void showAll(SDL_Surface * to);
+	InfoCard(EState Type);
+	~InfoCard();
 };
-struct IntSelBut: public Button
+
+class SelectionTab : public CIntObject
 {
 public:
-	CPoinGroup * ourPoinGroup;
-	int key;
-	IntSelBut(){};
-	IntSelBut( SDL_Rect Pos, boost::function<void()> Fun,CDefHandler* Imgs, bool Sel=false, CPoinGroup* gr=NULL, int My=-1);
-	void select(bool on=true);
+	int positions; //how many entries (games/maps) can be shown
+	CPicture *bg; //general bg image
+	CSlider *slider;
+	std::vector<CMapInfo> allItems;
+	std::vector<CMapInfo*> curItems;
+	size_t selectionPos;
+	boost::function<void(CMapInfo *)> onSelect;
+
+	ESortBy sortingBy;
+	bool ascending;
+
+	CDefHandler *format;
+
+	void getFiles(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext);
+	void parseMaps(std::vector<FileInfo> &files, int start = 0, int threads = 1);
+	void parseGames(std::vector<FileInfo> &files);
+	void filter(int size); //0 - all
+	void select(int position); //position: <0 - positions>  position on the screen
+	int getPosition(int x, int y); //convert mouse coords to entry position; -1 means none
+	void sliderMove(int slidPos);
+	void sortBy(int criteria);
+	void sort();
+	void printMaps(SDL_Surface *to);
+
+	void showAll(SDL_Surface * to);
+	void clickLeft(tribool down, bool previousState);
+	SelectionTab(EState Type, const boost::function<void(CMapInfo *)> &OnSelect);
+	~SelectionTab();
 };
-class PreGameTab
+
+class OptionsTab : public CIntObject
 {
 public:
-	bool showed;
-	virtual void init()=0;
-	virtual void show()=0;
-	virtual void hide()=0;
-	PreGameTab();
-};
-class RanSel : public PreGameTab
-{
-	Button horcpl[9], horcte[9], conpl[9], conte[8], water[4], monster[4], //last is random
-			size[4], twoLevel, showRand;
-	CGroup *Ghorcpl, *Ghorcte, *Gconpl, *Gconte, *Gwater, *Gmonster, *Gsize;
-};
-class Options : public PreGameTab
-{
-	bool inited;
-	struct OptionSwitch:public HighButton
+	enum SelType {TOWN, HERO, BONUS};
+	struct SelectedBox : public CIntObject //img with current town/hero/bonus
 	{
-		void hover(bool on=true){};
-		void select(bool on=true){};
-		OptionSwitch( SDL_Rect Pos, CDefHandler* Imgs, bool Left, int Which)
-			:HighButton(Pos,Imgs,false,7),left(Left),which(Which)
-			{selectable=false;highlightable=false;}
-		void press(bool down=true);
-		bool left;
-		int playerID;
-		int serialID;
-		int which; //-1=castle;0=hero;1=bonus
+		SelType which;
+		ui8 player; //serial nr
+		void showAll(SDL_Surface * to);
+		SelectedBox(SelType Which, ui8 Player);
 	};
-	struct PlayerFlag:public HighButton
-	{
-		int color;
-		PlayerFlag(SDL_Rect Pos, CDefHandler* Imgs, int Color)
-			:HighButton(Pos,Imgs,false,7),color(Color)
-			{selectable=false;highlightable=true;}
-		void hover(bool on=true);
-		void press(bool down=true);
-		void select(bool on=true){};
-	};
-	struct PlayerOptions
+
+	struct PlayerOptionsEntry : public CIntObject
 	{
-		PlayerOptions(int serial, int player);
-		Ecolor color;
-		PlayerFlag flag;
-		//SDL_Surface * bg;
-		OptionSwitch Cleft, Cright, Hleft, Hright, Bleft, Bright;
-		int nr;
+		PlayerSettings &s;
+		CPicture *bg;
+		AdventureMapButton *btns[6]; //left and right for town, hero, bonus
+		AdventureMapButton *flag;
+		SelectedBox *town;
+		SelectedBox *hero;
+		SelectedBox *bonus;
+		
+		PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
+		void showAll(SDL_Surface * to);
 	};
-public:
+	CPicture *bg;
+	CSlider *turnDuration;
+
 	std::set<int> usedHeroes;
-	Slider * turnLength;
-	SDL_Surface * bg,
-		* rHero, * rCastle, * nHero, * nCastle;
-	std::vector<SDL_Surface*> bgs;
-	std::vector<CDefHandler*> flags;
-	CDefHandler //* castles, * heroes, * bonus,
-		* left, * right,
-		* bonuses;
-	std::vector<PlayerOptions*> poptions;
-	void show();
-	void hide();
-	void init();
-	void showIcon (int what, int nr, bool abs); //what: -1=castle, 0=hero, 1=bonus, 2=all; abs=true -> nr is absolute
-	bool canUseThisHero(int ID);
-	int nextAllowedHero(int min, int max, int incl, int dir); //incl 0 - wlacznie; incl 1 - wylacznie; min-max - zakres szukania
-	Options(){inited=showed=false;};
-	~Options();
+
+	std::vector<PlayerOptionsEntry *> entries;
+
+	void nextCastle(int player, int dir); //dir == -1 or +1
+	void nextHero(int player, int dir); //dir == -1 or +1
+	void nextBonus(int player, int dir); //dir == -1 or +1
+	void setTurnLength(int npos);
+	void flagPressed(int player);
+
+	void changeSelection(const CMapInfo *to);
+	OptionsTab(EState Type/*, StartInfo &Opts*/);
+	~OptionsTab();
+	void showAll(SDL_Surface * to);
+
+	int nextAllowedHero( int min, int max, int incl, int dir );
+
+	bool canUseThisHero( int ID );
 };
-class MapSel : public PreGameTab
+
+class CSelectionScreen : public CIntObject
 {
 public:
-	ESortBy sortBy;
-	SDL_Surface * bg;
-	CDefHandler * Dtypes, * Dvic;
-	CDefHandler *Dsizes, * Dloss,
-		* sFlags;
-	std::vector<SDL_Surface*> scenImgs;
-
-	std::vector<CMapInfo*> ourMaps; // Maps
-	std::vector<CMapInfo*> ourGames; // Saved games
-	std::vector<CMapInfo*> selMaps;	// (sub)set of either ourMaps or ourGames
-	int selected;				// selected map, relative to selMaps
-
-	IntBut small, medium, large, xlarge, all;
-	SetrButton nrplayer, mapsize, type, name, viccon, loscon;
-	Slider *slid, *descslid;
-	int sizeFilter;
-	void show();
-	void hide();
-	void init();
-	std::string gdiff(std::string ss);
-	void printMaps(int from=0);
-	void select(int which, bool updateMapsList=true, bool forceSettingsUpdate=false);
-	void moveByX(int nlines);
-	void printSelectedInfo();
-	void printFlags();
-	void processMaps(const std::vector<std::string> &pliczkiTemp, int start, int threads);
-	void processGames(const std::vector<std::string> &pliczkiTemp);
-	void updateSelection();
-	MapSel();
-	~MapSel();
+	CPicture *bg; //general bg image
+	AdventureMapButton *start, *back;
+	InfoCard *card;
+	SelectionTab *sel;
+	OptionsTab *opt;
+
+	EState type; //new/save/load#Game
+	const CMapInfo *current;
+	StartInfo sInfo;
+	CIntObject *curTab;
+
+	CSelectionScreen(EState Type);
+	~CSelectionScreen();
+	void toggleTab(CIntObject *tab);
+	void changeSelection(const CMapInfo *to);
+	void updateStartInfo(const CMapInfo * to);
+	void startGame();
+	void difficultyChange(int to);
 };
-class ScenSel
-{
-public:
-	CPoinGroup * difficulty;
-	bool listShowed;
-	//RanSel ransel;
-	MapSel mapsel;
-	SDL_Surface * background, *savenameStrip, *scenInf, *scenList, *randMap, *options ;
-	Button bScens, bOptions, bRandom, bBegin, bLoad, bBack;
-	IntSelBut	bEasy, bNormal, bHard, bExpert, bImpossible;
-	Button * pressed;
-	std::vector<Mapa> maps;
-	int selectedDiff;
-	void initRanSel();
-	void showRanSel();
-	void hideRanSel();
-	void genScenList();
-	ScenSel();
-	~ScenSel();
-} ;
-class CPreGame
+
+class CGPreGame : public CIntObject
 {
 public:
-	std::string playerName;
-	int playerColor;
-	HighButton * highlighted;
-	PreGameTab* currentTab;
-	StartInfo ret;
-	bool run;
-	bool first; //hasn't we showed the scensel
-	std::vector<Slider *> interested;
-	std::vector<HighButton *> btns;
-	SDL_Rect * currentMessage;
-	SDL_Surface * behindCurMes;
-	CDefHandler *ok, *cancel;
-	enum EState { //where are we?
-		mainMenu, newGame, loadGame, ScenarioList, saveGame
-	} state, fromMenu;
-	struct menuItems {
-		menuItems();
-		~menuItems();
-		SDL_Surface * background, *bgAd;
-		CDefHandler *newGame, *loadGame, *highScores,*credits, *quit;
-		SDL_Rect lNewGame, lLoadGame, lHighScores, lCredits, lQuit;
-		ttt fNewGame, fLoadGame, fHighScores, fCredits, fQuit;
-		int highlighted;//0=none; 1=new game; 2=load game; 3=high score; 4=credits; 5=quit
-	} * ourMainMenu, * ourNewMenu, * ourLoadMenu;
-	ScenSel *ourScenSel;
-	Options * ourOptions;
-	std::string map; //selected map
-	CPreGame(); //c-tor
-	~CPreGame();//d-tor
-	std::string buttonText(int which);
-	menuItems * currentItems();
-	void(CPreGame::*handleOther)(SDL_Event&);
-	void scenHandleEv(SDL_Event& sEvent);
-	void begin();
-	void quitAskBox();
-	void quit(){exit(EXIT_SUCCESS);};
-	void initScenSel();
-	void showScenSel();
-	void showScenList();
-	void initOptions();
-	void showOptions();
-	void initNewMenu();
-	void initLoadMenu();
-	void showNewMenu();
-	void showLoadMenu();
-	void showMainMenu();
-	StartInfo runLoop(); // runs mainloop of PreGame
-	void initMainMenu(); //loads components for main menu
-	void highlightButton(int which, int on); //highlights one from 5 main menu buttons
-	void showCenBox (std::string data); //
-	void showAskBox (std::string data, void(*f1)(),void(*f2)());
-	void hideBox ();
-	void printRating();
-	void printMapsFrom(int from);
-	void setTurnLength(int on);
-	void sortMaps();
+	SDL_Surface *mainbg;
+	CMenuScreen *scrs[3];
+
+	SDL_Surface *nHero, *rHero, *nTown, *rTown; // none/random hero/town imgs
+	CDefHandler *bonuses;
+	CDefHandler *victory, *loss;
+
+	CGPreGame();
+	~CGPreGame();
+	void run();
+	void openSel(EState type);
+	void loadGraphics();
+	void disposeGraphics();
 };
 
+extern CGPreGame *CGP;
 
 #endif // __CPREGAME_H__

+ 163 - 38
client/GUIBase.cpp

@@ -31,42 +31,6 @@ void KeyShortcut::keyPressed(const SDL_KeyboardEvent & key)
 }
 
 
-CButtonBase::CButtonBase()
-{
-	bitmapOffset = 0;
-	curimg=0;
-	type=-1;
-	abs=false;
-	active=false;
-	notFreeButton = false;
-	ourObj=NULL;
-	state=0;
-}
-
-CButtonBase::~CButtonBase()
-{
-	if(notFreeButton)
-		return;
-	for(int i =0; i<imgs.size();i++)
-		for(int j=0;j<imgs[i].size();j++)
-			SDL_FreeSurface(imgs[i][j]);
-}
-
-void CButtonBase::show(SDL_Surface * to)
-{
-	int img = std::min(state+bitmapOffset,int(imgs[curimg].size()-1));
-	img = std::max(0, img);
-
-	if (abs)
-	{
-		blitAt(imgs[curimg][img],pos.x,pos.y,to);
-	}
-	else
-	{
-		blitAt(imgs[curimg][img],pos.x+ourObj->pos.x,pos.y+ourObj->pos.y,to);
-	}
-}
-
 void CGuiHandler::popInt( IShowActivable *top )
 {
 	assert(listInt.front() == top);
@@ -425,20 +389,181 @@ void CIntObject::tick()
 
 CIntObject::CIntObject()
 {
-	pressedL = pressedR = hovered = captureAllKeys = strongInterest = toNextTick = active = defActivation = 0;
+	pressedL = pressedR = hovered = captureAllKeys = strongInterest = toNextTick = active = used = 0;
+
+	recActions = defActions = GH.defActionsDef;
+
+	pos.x = 0;
+	pos.y = 0;
+	pos.w = 0;
+	pos.h = 0;
+
+	if(GH.captureChildren)
+	{
+		assert(GH.createdObj.size());
+		parent = GH.createdObj.front();
+		parent->children.push_back(this);
+
+		if(parent->defActions & SHARE_POS)
+		{
+			pos.x = parent->pos.x;
+			pos.y = parent->pos.y;
+		}
+	}
 }
 
 void CIntObject::show( SDL_Surface * to )
 {
+	if(defActions & UPDATE)
+		for(size_t i = 0; i < children.size(); i++)
+			if(children[i]->recActions & UPDATE)
+				children[i]->show(to);
+}
 
+void CIntObject::showAll( SDL_Surface * to )
+{
+	if(defActions & SHOWALL)
+	{
+		for(size_t i = 0; i < children.size(); i++)
+			if(children[i]->recActions & SHOWALL)
+				children[i]->showAll(to);
+
+	}
+	else
+		show(to);
 }
 
 void CIntObject::activate()
 {
-
+	assert(!active);
+	active |= GENERAL;
+	if(used & LCLICK)
+		activateLClick();
+	if(used & RCLICK)
+		activateRClick();
+	if(used & HOVER)
+		activateHover();
+	if(used & MOVE)
+		activateMouseMove();
+	if(used & KEYBOARD)
+		activateKeys();
+	if(used & TIME)
+		activateTimer();
+
+	if(defActions & ACTIVATE)
+		for(size_t i = 0; i < children.size(); i++)
+			if(children[i]->recActions & ACTIVATE)
+				children[i]->activate();
 }
 
 void CIntObject::deactivate()
 {
+	assert(active);
+	active &= ~ GENERAL;
+	if(used & LCLICK)
+		deactivateLClick();
+	if(used & RCLICK)
+		deactivateRClick();
+	if(used & HOVER)
+		deactivateHover();
+	if(used & MOVE)
+		deactivateMouseMove();
+	if(used & KEYBOARD)
+		deactivateKeys();
+	if(used & TIME)
+		deactivateTimer();
 
+	if(defActions & DEACTIVATE)
+		for(size_t i = 0; i < children.size(); i++)
+			if(children[i]->recActions & DEACTIVATE)
+				children[i]->deactivate();
+}
+
+CIntObject::~CIntObject()
+{
+	assert(!active); //do not delete active obj
+
+	if(defActions & DISPOSE)
+		for(size_t i = 0; i < children.size(); i++)
+			if(children[i]->recActions & DISPOSE)
+				delete children[i];
+}
+
+void CIntObject::printAtLoc( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
+{
+	CSDL_Ext::printAt(text, pos.x + x, pos.y + y, font, kolor, dst, refresh);
+}
+
+void CIntObject::printAtMiddleLoc( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
+{
+	CSDL_Ext::printAtMiddle(text, pos.x + x, pos.y + y, font, kolor, dst, refresh);
+}
+
+void CIntObject::blitAtLoc( SDL_Surface * src, int x, int y, SDL_Surface * dst )
+{
+	blitAt(src, pos.x + x, pos.y + y, dst);
+}
+
+void CIntObject::printAtMiddleWBLoc( const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refrsh /*= false*/ )
+{
+	CSDL_Ext::printAtMiddleWB(text, pos.x + x, pos.y + y, font, charpr, kolor, dst, refrsh);
+}
+
+void CIntObject::printToLoc( const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh /*= false*/ )
+{
+	CSDL_Ext::printTo(text, pos.x + x, pos.y + y, font, kolor, dst, refresh);
+}
+
+CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
+{
+	bg = BG; 
+	freeSurf = Free;
+	pos.x += x;
+	pos.y += y;
+	pos.w = BG->w;
+	pos.h = BG->h;
+}
+
+CPicture::~CPicture()
+{
+	if(freeSurf)
+		SDL_FreeSurface(bg);
+}
+
+void CPicture::showAll( SDL_Surface * to )
+{
+	blitAt(bg, pos, to);
+}
+
+ObjectConstruction::ObjectConstruction( CIntObject *obj )
+	:myObj(obj)
+{
+	GH.createdObj.push_front(obj);
+	GH.captureChildren = true;
+}
+
+ObjectConstruction::~ObjectConstruction()
+{
+	assert(GH.createdObj.size());
+	assert(GH.createdObj.front() == myObj);
+	GH.createdObj.pop_front();
+	GH.captureChildren = GH.createdObj.size();
+}
+
+BlockCapture::BlockCapture()
+{
+	previous = GH.captureChildren;
+	GH.captureChildren = false;
+}
+
+BlockCapture::~BlockCapture()
+{
+	GH.captureChildren = previous;
+}
+
+void IShowable::redraw()
+{
+	showAll(screenBuf);
+	if(screenBuf != screen)
+		showAll(screen);
 }

+ 45 - 19
client/GUIBase.h

@@ -55,6 +55,7 @@ class CArmedInstance;
 class CGTownInstance;
 class StackState;
 class CPlayerInterface;
+enum EFonts;
 
 struct Point
 {
@@ -224,6 +225,7 @@ struct Rect : public SDL_Rect
 class IShowable
 {
 public:
+	void redraw();
 	virtual void show(SDL_Surface * to)=0;
 	virtual void showAll(SDL_Surface * to)
 	{
@@ -270,7 +272,7 @@ public:
 	int ID; //object ID, rarely used by some classes for identification / internal info
 
 	CIntObject();
-	virtual ~CIntObject(){}; //d-tor
+	virtual ~CIntObject();; //d-tor
 
 	//l-clicks handling
 	bool pressedL; //for determining if object is L-pressed
@@ -308,15 +310,26 @@ public:
 	void deactivateTimer();
 	virtual void tick();
 
-	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32};
+	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64};
 	ui8 active;
-	ui8 defActivation;
+	ui8 used;
+
+	enum {ACTIVATE=1, DEACTIVATE=2, UPDATE=4, SHOWALL=8, DISPOSE=16, SHARE_POS=32};
+	ui8 defActions; //which calls will be tried to be redirected to children
+	ui8 recActions; //which calls we allow te receive from parent
 
 	void defActivate();
 	void defDeactivate();
 	void activate();
 	void deactivate();
 	void show(SDL_Surface * to);
+	void showAll(SDL_Surface * to);
+
+	void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false);
+	void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false);
+	void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false);
+	void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refrsh = false);
+	void blitAtLoc(SDL_Surface * src, int x, int y, SDL_Surface * dst);
 };
 
 //class for binding keys to left mouse button clicks
@@ -350,23 +363,15 @@ public:
 	void deactivate(){};
 };
 
-class CButtonBase : public KeyShortcut//basic buttton class
+class CPicture : public CIntObject
 {
-public:
-	int bitmapOffset; //TODO: comment me
-	int type; //advmapbutton=2 //TODO: comment me
-	bool abs;//TODO: comment me
-	bool active; //if true, this button is active and can be pressed
-	bool notFreeButton; //TODO: comment me
-	CIntObject * ourObj; // "owner"
-	int state; //TODO: comment me
-	std::vector< std::vector<SDL_Surface*> > imgs; //images for this button
-	int curimg; //curently displayed image from imgs
-	virtual void show(SDL_Surface * to);
-	virtual void activate()=0;
-	virtual void deactivate()=0;
-	CButtonBase(); //c-tor
-	virtual ~CButtonBase(); //d-tor
+public: 
+	SDL_Surface *bg;
+	bool freeSurf;
+
+	CPicture(SDL_Surface *BG, int x, int y, bool Free);
+	~CPicture();
+	void showAll(SDL_Surface * to);
 };
 
 class CGuiHandler
@@ -400,8 +405,29 @@ public:
 	void handleEvent(SDL_Event *sEvent);
 
 	void handleMouseMotion(SDL_Event *sEvent);
+
+	ui8 defActionsDef; //default auto actions
+	ui8 captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
+	std::list<CIntObject *> createdObj; //stack of objs being created
 };
 
 extern CGuiHandler GH; //global gui handler
 
+struct ObjectConstruction
+{
+	CIntObject *myObj;
+	ObjectConstruction(CIntObject *obj);
+	~ObjectConstruction();
+};
+
+struct BlockCapture
+{
+	bool previous;
+	BlockCapture();
+	~BlockCapture();
+};
+
+#define OBJ_CONSTRUCTION ObjectConstruction obj__i(this)
+#define BLOCK_CAPTURING BlockCapture obj__i
+
 #endif //__GUIBASE_H__

+ 11 - 5
client/GUIClasses.cpp

@@ -636,6 +636,12 @@ void CInfoWindow::deactivate()
 	for(int i=0;i<buttons.size();i++)
 		buttons[i]->deactivate();
 }
+
+void CInfoWindow::showAll( SDL_Surface * to )
+{
+	show(to);
+}
+
 void CRClickPopup::clickRight(tribool down, bool previousState)
 {
 	if(down)
@@ -1683,7 +1689,7 @@ void CRecruitmentWindow::clickLeft(tribool down, bool previousState)
 		{
 			which = i;
 			int newAmount = std::min(amounts[i],creatures[i].amount);
-			slider->amount = newAmount;
+			slider->setAmount(newAmount);
 			if(slider->value > newAmount)
 				slider->moveTo(newAmount);
 			else
@@ -1873,7 +1879,7 @@ void CRecruitmentWindow::initCres()
 		}
 	}
 
-	slider->amount = std::min(amounts[which],creatures[which].amount);
+	slider->setAmount(std::min(amounts[which],creatures[which].amount));
 }
 
 void CRecruitmentWindow::cleanCres()
@@ -2676,7 +2682,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
 	if(hLeft && hRight && hLeft->id!= hRight->id)
 	{
 		LOCPLINT->cb->getMarketOffer(hLeft->id,hRight->id,r1,r2,0);
-		slider->amount = LOCPLINT->cb->getResourceAmount(hLeft->id) / r1;
+		slider->setAmount(LOCPLINT->cb->getResourceAmount(hLeft->id) / r1);
 		slider->moveTo(0);
 		max->block(false);
 		deal->block(false);
@@ -2685,7 +2691,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
 	{
 		max->block(true);
 		deal->block(true);
-		slider->amount = 0;
+		slider->setAmount(0);
 		slider->moveTo(0);
 	}
 	if(side && hLeft) //left selection changed, recalculate offers
@@ -3316,7 +3322,7 @@ CRClickPopupInt::~CRClickPopupInt()
 {
 	//workaround for hero window issue - if it's our interface, call dispose to properly reset it's state 
 	//TODO? it might be better to rewrite hero window so it will bee newed/deleted on opening / closing (not effort-worthy now, but on some day...?)
-	if(inner == LOCPLINT->adventureInt->heroWindow)
+	if(LOCPLINT && inner == LOCPLINT->adventureInt->heroWindow)
 		LOCPLINT->adventureInt->heroWindow->dispose();
 
 	if(delInner)

+ 4 - 1
client/GUIClasses.h

@@ -68,7 +68,8 @@ public:
 	std::vector<AdventureMapButton *> buttons;
 	std::vector<SComponent*> components;
 	virtual void close();
-	virtual void show(SDL_Surface * to);
+	void show(SDL_Surface * to);
+	void showAll(SDL_Surface * to);
 	void activate();
 	void deactivate();
 	CInfoWindow(std::string text, int player, int charperline, const std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, bool delComps); //c-tor
@@ -362,6 +363,7 @@ public:
 	void activate();
 	void deactivate();
 	void show(SDL_Surface * to);
+	void showAll(SDL_Surface * to){show(to);};
 	void cleanCres();
 	void initCres();
 	CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const boost::function<void(int,int)> & Recruit); //creatures - pairs<creature_ID,amount> //c-tor
@@ -683,6 +685,7 @@ public:
 	void activate();
 	void deactivate();
 	void show(SDL_Surface * to);
+	void showAll(SDL_Surface * to){show(to);};
 	CGarrisonWindow(const CArmedInstance *up, const CGHeroInstance *down); //c-tor
 	~CGarrisonWindow(); //d-tor
 };

+ 67 - 0
client/Graphics.cpp

@@ -258,6 +258,7 @@ Graphics::Graphics()
 	CDefHandler *smi, *smi2;
 
 	std::vector<Task> tasks; //preparing list of graphics to load
+	tasks += boost::bind(&Graphics::loadFonts,this);
 	tasks += boost::bind(&Graphics::loadPaletteAndColors,this);
 	tasks += boost::bind(&Graphics::loadHeroFlags,this);
 	tasks += boost::bind(&Graphics::loadHeroPortraits,this);
@@ -595,3 +596,69 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, int player)
 		}
 	}
 }
+
+Font * Graphics::loadFont( const char * name )
+{
+	int len = 0;
+	unsigned char * hlp = bitmaph->giveFile(name, &len);
+	if(!hlp || !len)
+	{
+		tlog1 << "Error: cannot load font: " << name << std::endl;
+		return NULL;
+	}
+	Font *ret = new Font(hlp);
+	return ret;
+}
+
+void Graphics::loadFonts()
+{
+	static const char *fontnames [] = {"BIGFONT.FNT", "CALLI10R.FNT", "CREDITS.FNT", "HISCORE.FNT", "MEDFONT.FNT",
+								"SMALFONT.FNT", "TIMES08R.FNT", "TINY.FNT", "VERD10B.FNT"} ;
+
+	assert(ARRAY_COUNT(fontnames) == FONTS_NUMBER);
+	for(int i = 0; i < FONTS_NUMBER; i++)
+		fonts[i] = loadFont(fontnames[i]);
+}
+
+Font::Font(unsigned char *Data)
+{
+	data = Data;
+	int i = 0;
+
+	height = data[5];
+
+	i = 32;
+	for(int ci = 0; ci < 256; ci++)
+	{
+		chars[ci].unknown1 = CDefHandler::readNormalNr(i, 4, data); i+=4;
+		chars[ci].width = CDefHandler::readNormalNr(i, 4, data); i+=4;
+		chars[ci].unknown2 = CDefHandler::readNormalNr(i, 4, data); i+=4;
+
+		//if(ci>=30)
+		//	tlog0 << ci << ". (" << (char)ci << "). Width: " << chars[ci].width << " U1/U2:" << chars[ci].unknown1 << "/" << chars[ci].unknown2 << std::endl;
+	}
+	for(int ci = 0; ci < 256; ci++)
+	{
+		chars[ci].offset = CDefHandler::readNormalNr(i, 4, data); i+=4;
+		chars[ci].pixels = data + 4128 + chars[ci].offset;
+	}
+}
+
+Font::~Font()
+{
+	delete [] data;
+}
+
+int Font::getWidth(const char *text ) const
+{
+	int length = std::strlen(text);
+	int ret = 0;
+
+	for(int i = 0; i < length; i++)
+	{
+		unsigned char c = text[i];
+		ret += chars[c].width + chars[c].unknown1 + chars[c].unknown2;
+	}
+
+	return ret;
+}

+ 31 - 0
client/Graphics.h

@@ -24,9 +24,38 @@ struct SDL_Color;
 struct InfoAboutHero;
 struct InfoAboutTown;
 
+struct Font
+{
+	struct Char
+	{
+		si32 unknown1, width, unknown2, offset;
+		unsigned char *pixels;
+	};
+
+	Char chars[256];
+	ui8 height;
+
+	unsigned char *data;
+
+
+	Font(unsigned char *Data);
+	~Font();
+	int getWidth(const char *text) const;
+};
+
+enum EFonts
+{
+	FONT_BIG, FONT_CALLI, FONT_CREDITS, FONT_HIGH_SCORE, FONT_MEDIUM, FONT_SMALL, FONT_TIMES, FONT_TINY, FONT_VERD
+};
+
+
 class Graphics
 {
 public:
+	//Fonts
+	static const int FONTS_NUMBER = 9;
+	Font *fonts[FONTS_NUMBER];
+
 	//various graphics
 	SDL_Color * playerColors; //array [8]
 	SDL_Color * neutralColor;
@@ -82,6 +111,8 @@ public:
 	SDL_Surface * drawTownInfoWin(const CGTownInstance * curh);
 	SDL_Surface * getPic(int ID, bool fort=true, bool builded=false); //returns small picture of town: ID=-1 - blank; -2 - border; -3 - random
 	void blueToPlayersAdv(SDL_Surface * sur, int player); //replaces blue interface colour with a color of player
+	void loadFonts();
+	Font *loadFont(const char * name);
 };
 
 extern Graphics * graphics;

+ 80 - 0
client/SDL_Extensions.cpp

@@ -129,6 +129,21 @@ void CSDL_Ext::printAtWB(const std::string & text, int x, int y, TTF_Font * font
 	delete ws;
 }
 
+void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor/*=tytulowy*/, SDL_Surface * dst/*=screen*/, bool refrsh /*= false*/ )
+{
+	const Font *f = graphics->fonts[font];
+	std::vector<std::string> * ws = CMessage::breakText(text,charpr);
+	int totalHeight = ws->size() * f->height;
+
+	int cury = y - totalHeight/2;
+	for (size_t i=0; i < ws->size(); ++i)
+	{
+		printAt((*ws)[i], x - f->getWidth((*ws)[i].c_str())/2, cury, font, kolor, dst, refrsh);
+		cury += f->height;
+	}
+	delete ws;
+}
+
 void CSDL_Ext::printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality, bool refresh)
 {
 	if(text.length()==0) return;
@@ -159,6 +174,15 @@ void CSDL_Ext::printAtMiddle(const std::string & text, int x, int y, TTF_Font *
 	SDL_FreeSurface(temp);
 }
 
+void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
+{
+	const Font *f = graphics->fonts[font];
+	int nx = x - f->getWidth(text.c_str())/2,
+		ny = y - f->height/2;
+
+	printAt(text, nx, ny, font, kolor, dst, refresh);
+}
+
 void CSDL_Ext::printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality, bool refresh)
 {
 	if (text.length()==0)
@@ -190,6 +214,56 @@ void CSDL_Ext::printAt(const std::string & text, int x, int y, TTF_Font * font,
 	SDL_FreeSurface(temp);
 }
 
+void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
+{
+	assert(dst);
+	assert(font < Graphics::FONTS_NUMBER);
+	assert(dst->format->BytesPerPixel == 3   ||   dst->format->BytesPerPixel == 4); //  24/32 bpp dst only
+
+	const Font *f = graphics->fonts[font];
+	const Uint8 bpp = dst->format->BytesPerPixel;
+	Uint8 *px = NULL;
+	Uint8 *src = NULL;
+
+
+	for(int txti = 0; txti < text.size(); txti++)
+	{
+		const unsigned char c = text[txti];
+		src = f->chars[c].pixels;
+		x += f->chars[c].unknown1;
+
+		for(int i = 0; i < f->height  &&  (y + i) < (dst->h - 1); i++)
+		{
+			px = (Uint8*)dst->pixels;
+			px +=  (y+i) * dst->pitch  +  x * bpp;
+			for(int j = 0; j < f->chars[c].width  &&  (j + x) < (dst->w - 1); j++)
+			{
+				switch(*src)
+				{
+				case 1: //black "shadow"
+					memset(px, 0, bpp);
+					break;
+				case 255: //text colour
+					px[0] = kolor.b;
+					px[1] = kolor.g;
+					px[2] = kolor.r;
+					break;
+				}
+				src++;
+				px += bpp;
+			}
+		}
+
+		x += f->chars[c].width;
+		x += f->chars[c].unknown2;
+	}
+
+	if(refresh)
+	{
+		SDL_UpdateRect(dst, x, y, f->getWidth(text.c_str()), f->height);
+	}
+}
+
 void CSDL_Ext::printAtWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality)
 {
 	printAt(text,x,y,font,kolor,dst,quality, true);
@@ -225,6 +299,12 @@ void CSDL_Ext::printTo(const std::string & text, int x, int y, TTF_Font * font,
 	SDL_FreeSurface(temp);
 }
 
+void CSDL_Ext::printTo( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
+{
+	const Font *f = graphics->fonts[font];
+	printAt(text, x - f->getWidth(text.c_str()), y - f->height, font, kolor, dst, refresh);
+}
+
 void CSDL_Ext::printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality)
 {
 	if (text.length()==0)

+ 9 - 0
client/SDL_Extensions.h

@@ -17,6 +17,8 @@
  *
  */
 
+enum EFonts;
+
 extern SDL_Surface * screen, *screen2, *screenBuf;
 extern SDL_Color tytulowy, tlo, zwykly ;
 extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM;
@@ -108,6 +110,7 @@ namespace CSDL_Ext
 	void blitWithRotate3clip(SDL_Surface *src,SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
 	int blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface
 	Uint32 colorToUint32(const SDL_Color * color); //little endian only
+
 	void printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2);// quality: 0 - lowest, 1 - medium, 2 - highest; prints at right bottom corner of specific area. position of corner indicated by (x, y)
 	void printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2);// quality: 0 - lowest, 1 - medium, 2 - highest; prints at right bottom corner of specific area. position of corner indicated by (x, y)
 	void printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2, bool refresh = false); // quality: 0 - lowest, 1 - medium, 2 - highest
@@ -115,6 +118,12 @@ namespace CSDL_Ext
 	void printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen);
 	void printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2, bool refresh = false); // quality: 0 - lowest, 1 - medium, 2 - highest
 	void printAtWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2); // quality: 0 - lowest, 1 - medium, 2 - highest
+
+	void printAt(const std::string & text, int x, int y, EFonts font, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);
+	void printTo(const std::string & text, int x, int y, EFonts font, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);
+	void printAtMiddle(const std::string & text, int x, int y, EFonts font, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);
+	void printAtMiddleWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, bool refrsh = false);
+
 	void update(SDL_Surface * what = screen); //updates whole surface (default - main screen)
 	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, int3 color);
 	void setPlayerColor(SDL_Surface * sur, unsigned char player); //sets correct color of flags; -1 for neutral

+ 1 - 1
hch/CDefHandler.cpp

@@ -219,7 +219,7 @@ void CDefHandler::expand(unsigned char N,unsigned char & BL, unsigned char & BR)
 	BL = (N & 0xE0) >> 5;
 	BR = N & 0x1F;
 }
-int CDefHandler::readNormalNr (int pos, int bytCon, unsigned char * str, bool cyclic)
+int CDefHandler::readNormalNr (int pos, int bytCon, const unsigned char * str, bool cyclic)
 {
 	int ret=0;
 	int amp=1;

+ 1 - 1
hch/CDefHandler.h

@@ -47,7 +47,7 @@ public:
 	CDefHandler(); //c-tor
 	~CDefHandler(); //d-tor
 	static void print (std::ostream & stream, int nr, int bytcon);
-	int readNormalNr (int pos, int bytCon, unsigned char * str=NULL, bool cyclic=false);
+	static int readNormalNr (int pos, int bytCon, const unsigned char * str=NULL, bool cyclic=false);
 	static unsigned char *writeNormalNr (int nr, int bytCon);
 	SDL_Surface * getSprite (int SIndex, unsigned char * FDef, BMPPalette * palette); //zapisuje klatke o zadanym numerze do "testtt.bmp"
 	void openDef(std::string name);

+ 29 - 16
lib/map.cpp

@@ -256,6 +256,19 @@ void CMapHeader::initFromMemory( unsigned char *bufor, int &i )
 			players[rr].team=bufor[i++];
 		}
 	}
+
+	pom = i;
+	allowedHeroes.resize(HEROES_QUANTITY,false);
+	for(i; i<pom+ (version == RoE ? 16 : 20) ; ++i)
+	{
+		unsigned char c = bufor[i];
+		for(int yy=0; yy<8; ++yy)
+			if((i-pom)*8+yy < HEROES_QUANTITY)
+				if(c == (c|((unsigned char)intPow(2, yy))))
+					allowedHeroes[(i-pom)*8+yy] = true;
+	}
+	if(version>RoE) //probably reserved for further heroes
+		i+=4;
 }
 void CMapHeader::loadPlayerInfo( int &pom, unsigned char * bufor, int &i )
 {
@@ -1062,22 +1075,10 @@ void Mapa::readRumors( unsigned char * bufor, int &i)
 void Mapa::readHeader( unsigned char * bufor, int &i)
 {
 	//reading allowed heroes (20 bytes)
-	int ist;
+	int ist = i;
 
 	ist=i; //starting i for loop
 
-	allowedHeroes.resize(HEROES_QUANTITY,false);
-
-	for(i; i<ist+ (version == RoE ? 16 : 20) ; ++i)
-	{
-		unsigned char c = bufor[i];
-		for(int yy=0; yy<8; ++yy)
-			if((i-ist)*8+yy < HEROES_QUANTITY)
-				if(c == (c|((unsigned char)intPow(2, yy))))
-					allowedHeroes[(i-ist)*8+yy] = true;
-	}
-	if(version>RoE) //probably reserved for further heroes
-		i+=4;
 	unsigned char disp = 0;
 	if(version>=SoD)
 	{
@@ -2095,8 +2096,20 @@ void CMapInfo::countPlayers()
 	}
 }
 
-CMapInfo::CMapInfo( std::string fname, unsigned char *map )
-:CMapHeader(map),filename(fname)
+CMapInfo::CMapInfo(const std::string &fname, unsigned char *map )
 {
-	countPlayers();
+	init(fname, map);
 }
+
+CMapInfo::CMapInfo()
+{
+	version = invalid;
+}
+
+void CMapInfo::init(const std::string &fname, unsigned char *map )
+{
+	filename = fname;
+	int i = 0;
+	initFromMemory(map, i);
+	countPlayers();
+}

+ 6 - 5
lib/map.h

@@ -29,7 +29,7 @@ class CGObjectInstance;
 class CGHeroInstance;
 class CQuest;
 class CGTownInstance;
-enum ESortBy{_name, _playerAm, _size, _format, _viccon, _loscon};
+enum ESortBy{_playerAm, _size, _format, _name, _viccon, _loscon};
 enum EDefType {TOWN_DEF, HERO_DEF, CREATURES_DEF, SEERHUT_DEF, RESOURCE_DEF, TERRAINOBJ_DEF, 
 	EVENTOBJ_DEF, SIGN_DEF, GARRISON_DEF, ARTIFACT_DEF, WITCHHUT_DEF, SCHOLAR_DEF, PLAYERONLY_DEF, 
 	SHRINE_DEF, SPELLSCROLL_DEF, PANDORA_DEF, GRAIL_DEF, CREGEN_DEF, CREGEN2_DEF, CREGEN3_DEF, 
@@ -208,7 +208,7 @@ public:
 class DLL_EXPORT CMapHeader
 {
 public:
-	enum Eformat { WoG=0x33, AB=0x15, RoE=0x0e,  SoD=0x1c};
+	enum Eformat {invalid, WoG=0x33, AB=0x15, RoE=0x0e,  SoD=0x1c};
 	Eformat version; // version of map Eformat
 	ui8 areAnyPLayers; // if there are any playable players on map
 	si32 height, width, twoLevel; //sizes
@@ -221,6 +221,7 @@ public:
 	std::vector<PlayerInfo> players; // info about players - size 8
 	std::vector<ui8> teams;  // teams[i] = team of player no i
 	ui8 howManyTeams;
+	std::vector<ui8> allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed
 	void initFromMemory(unsigned char *bufor, int &i);
 	void loadViCLossConditions( unsigned char * bufor, int &i);
 	void loadPlayerInfo( int &pom, unsigned char * bufor, int &i);
@@ -242,9 +243,10 @@ public:
 	std::string filename;
 	std::string date;
 	int playerAmnt, humenPlayers;
-	CMapInfo(){};
+	CMapInfo();
+	CMapInfo(const std::string &fname, unsigned char *map);
+	void init(const std::string &fname, unsigned char *map);
 	void countPlayers();
-	CMapInfo(std::string fname, unsigned char *map);
 };
 
 
@@ -304,7 +306,6 @@ struct DLL_EXPORT Mapa : public CMapHeader
 	std::vector<ui8> allowedSpell; //allowedSpell[spell_ID] - if the spell is allowed
 	std::vector<ui8> allowedArtifact; //allowedArtifact[artifact_ID] - if the artifact is allowed
 	std::vector<ui8> allowedAbilities; //allowedAbilities[ability_ID] - if the ability is allowed
-	std::vector<ui8> allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed
 	std::list<CMapEvent*> events;
 
 	int3 grailPos;

+ 8 - 6
server/CGameHandler.cpp

@@ -894,25 +894,27 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
 	positions.close();
 	//battleStartpos read
 
-	for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
+	int k = 0; //stack serial 
+	for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++, k++)
 	{
 		int pos;
 		if(army1.formation)
-			pos = attackerTight[army1.slots.size()-1][i->first];
+			pos = attackerTight[army1.slots.size()-1][k];
 		else
-			pos = attackerLoose[army1.slots.size()-1][i->first];
+			pos = attackerLoose[army1.slots.size()-1][k];
 
 		CStack * stack = BattleInfo::generateNewStack(hero1, i->second.first, i->second.second, stacks.size(), true, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
 		stacks.push_back(stack);
 	}
 	
-	for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
+	k = 0;
+	for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++, k++)
 	{
 		int pos;
 		if(army2.formation)
-			pos = defenderTight[army2.slots.size()-1][i->first];
+			pos = defenderTight[army2.slots.size()-1][k];
 		else
-			pos = defenderLoose[army2.slots.size()-1][i->first];
+			pos = defenderLoose[army2.slots.size()-1][k];
 
 		CStack * stack = BattleInfo::generateNewStack(hero2, i->second.first, i->second.second, stacks.size(), false, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
 		stacks.push_back(stack);

部分文件因文件數量過多而無法顯示