Browse Source

- Created config file for true type fonts (disabled by default)
- Implemented buildings with bonuses for defending hero (glyphs of fear, fountain of fortune, some grails)
- Minor fixes

Ivan Savenko 15 năm trước cách đây
mục cha
commit
3aefb896fe

+ 15 - 1
client/CHeroWindow.cpp

@@ -5,6 +5,7 @@
 #include "CGameInfo.h"
 #include "CHeroWindow.h"
 #include "CMessage.h"
+#include "CKingdomInterface.h"
 #include "SDL.h"
 #include "SDL_Extensions.h"
 #include "CBitmapHandler.h"
@@ -258,7 +259,20 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
 
 	artifs->setHero(hero);
 
-	dismissButton->block(!!hero->visitedTown);
+	//if we have exchange window with this hero open
+	bool noDismiss=false;
+	for(std::list<IShowActivable *>::iterator it=GH.listInt.begin() ; it != GH.listInt.end(); it++)
+	{
+		CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>((*it));
+			if(cew)
+				for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
+					if(cew->heroInst[g] == hero)
+						noDismiss = true;
+		CKingdomInterface * cki = dynamic_cast<CKingdomInterface*>((*it));
+			if (cki)
+				noDismiss = true;
+	}
+	dismissButton->block(!!hero->visitedTown || noDismiss);
 	if(hero->getSecSkillLevel(19)==0)
 		gar2button->block(true);
 	else

+ 68 - 42
client/CKingdomInterface.cpp

@@ -66,15 +66,15 @@ CKingdomInterface::CKingdomInterface()
 	slots   = CDefHandler::giveDefEss("OVSLOT.DEF");
 
 	toHeroes = new AdventureMapButton (CGI->generaltexth->overview[11],"",
-		boost::bind(&CKingdomInterface::listToHeroes,this),748,28+size*116,"OVBUTN1.DEF");
+		boost::bind(&CKingdomInterface::listToHeroes,this),748,28+size*116,"OVBUTN1.DEF", SDLK_h);
 	toHeroes->block(2);
 
 	toTowns = new AdventureMapButton (CGI->generaltexth->overview[12],"",
-		boost::bind(&CKingdomInterface::listToTowns,this),748,64+size*116,"OVBUTN6.DEF");
+		boost::bind(&CKingdomInterface::listToTowns,this),748,64+size*116,"OVBUTN6.DEF", SDLK_t);
 	toTowns->block(0);
 
 	exit = new AdventureMapButton (CGI->generaltexth->allTexts[600],"",
-		boost::bind(&CKingdomInterface::close,this),748,99+size*116,"OVBUTN1.DEF");
+		boost::bind(&CKingdomInterface::close,this),748,99+size*116,"OVBUTN1.DEF", SDLK_RETURN);
 	exit->bitmapOffset = 3;
 
 	statusbar = new CStatusBar(pos.x+7,pos.y+91+size*116,"TSTATBAR.bmp",732);
@@ -108,7 +108,7 @@ CKingdomInterface::CKingdomInterface()
 	for (size_t i=0; i<SKILL_PER_HERO; i++)
 	{
 		incomes.push_back(new HoverableArea());//bottom panel with mines
-		incomes[i]->pos = genRect(54,68,pos.x+20+i*80,pos.y+31+size*116);
+		incomes[i]->pos = genRect(57,68,pos.x+20+i*80,pos.y+31+size*116);
 		incomes[i]->hoverText = CGI->generaltexth->mines[i].first;
 	}
 	incomes[7]->pos.w = 136;
@@ -129,7 +129,7 @@ CKingdomInterface::CKingdomInterface()
 	INSERT_MAP (87,0) ,87));//Harbor
 	#undef INSERT_MAP
 
-	for(size_t i = 0; i<CGI->state->map->objects.size(); i++)
+	for(size_t i = 0; i<CGI->state->map->objects.size(); i++)//getting mines and dwelling (in one pass to make it faster)
 	{
 		CGObjectInstance* obj = CGI->state->map->objects[i];//current object
 		if (obj)
@@ -197,7 +197,7 @@ void CKingdomInterface::moveObjectList(int newPos)
 /*Bottom*/	case 3: objPos = bottom;
 			break;
 	}
-	GH.totalRedraw();
+	showAll(screen2);
 }
 
 CKingdomInterface::~CKingdomInterface()
@@ -349,10 +349,6 @@ void CKingdomInterface::deactivate()
 	slider->deactivate();
 }
 
-void CKingdomInterface::keyPressed(const SDL_KeyboardEvent & key)
-{
-}
-
 void CKingdomInterface::recreateHeroList(int pos)
 {
 	std::vector<const CGHeroInstance*> Heroes = LOCPLINT->cb->getHeroesInfo(true);
@@ -371,20 +367,18 @@ void CKingdomInterface::recreateHeroList(int pos)
 	}
 	for (i;i<size;i++)//if we still have empty pieces
 		heroes[i]->setHero(NULL);//empty pic
-	GH.totalRedraw();
 }
 
 void CKingdomInterface::recreateTownList(int pos)
 {
-	std::vector<const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(true);
+	std::vector<const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(false);
 	for(size_t i=0;i<size;i++)
 	{
-		if (i+pos<Towns.size())
+		if (i+pos<LOCPLINT->cb->howManyTowns())
 			towns[i]->setTown(Towns[i+pos]);//replace town
 		else
 			towns[i]->setTown(NULL);//only empty pic
 	}
-	GH.totalRedraw();
 }
 
 void CKingdomInterface::listToTowns()
@@ -401,6 +395,7 @@ void CKingdomInterface::listToTowns()
 		heroes[i]->deactivate();
 		towns[i]->activate();
 	}
+	showAll(screen2);
 }
 
 void CKingdomInterface::listToHeroes()
@@ -417,6 +412,7 @@ void CKingdomInterface::listToHeroes()
 		towns[i]->deactivate();
 		heroes[i]->activate();
 	}
+	showAll(screen2);
 }
 
 void CKingdomInterface::sliderMoved(int newpos)
@@ -435,6 +431,7 @@ void CKingdomInterface::sliderMoved(int newpos)
 		recreateTownList(newpos);
 		for (size_t i=0; i<size; i++)
 			towns[i]->activate();
+		showAll(screen2);
 	}
 	else//heroes
 	{
@@ -444,6 +441,7 @@ void CKingdomInterface::sliderMoved(int newpos)
 		recreateHeroList(newpos);
 		for (size_t i=0; i<size; i++)
 			heroes[i]->activate();
+		showAll(screen2);
 	}
 }
 
@@ -459,10 +457,10 @@ CKingdomInterface::CTownItem::CTownItem(int num, CKingdomInterface * Owner)
 	town = NULL;
 	garr = NULL;
 
-	garrHero = new HoverableArea();
+	garrHero = new LRClickableAreaOpenHero();
 	garrHero->pos = genRect(64, 58, pos.x+244, pos.y + 6);
 
-	visitHero = new HoverableArea();
+	visitHero = new LRClickableAreaOpenHero();
 	visitHero->pos = genRect(64, 58, pos.x+476, pos.y + 6);
 
 	for (int i=0; i<CREATURES_PER_TOWN;i++)
@@ -480,7 +478,7 @@ CKingdomInterface::CTownItem::CTownItem(int num, CKingdomInterface * Owner)
 	fortArea = new HoverableArea();
 	fortArea->pos = genRect(38, 38, pos.x+111, pos.y + 31);
 
-	townImage = new HoverableArea();
+	townImage = new LRClickableAreaOpenTown();
 	townImage->pos = genRect(64, 58, pos.x+5, pos.y + 6);
 
 	incomeArea = new HoverableArea();
@@ -506,24 +504,28 @@ void CKingdomInterface::CTownItem::setTown(const CGTownInstance * newTown)
 		return;
 		garr = NULL;
 	}
-	garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),slots->ourImages[owner->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,false,true, 4,Point(-126,37));
-	garr->update = false;
+	garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),slots->ourImages[owner->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,true,true, 4,Point(-126,37));
+	garr->update = true;
 
-	/*for (int i=4; i<7; i++)
-	{
-		garr->sup[0][i][0].pos.x -= 126;
-		garr->sup[0][i][0].pos.y += 37;
-		garr->sdown[0][i][0].pos.x -= 126;
-		garr->sdown[0][i][0].pos.y += 37;
-	}*/
+	char buf[400];
+	if (town->garrisonHero)
+		{
+		garrHero->hero = town->garrisonHero;
+		sprintf(buf, CGI->generaltexth->allTexts[15].c_str(), town->garrisonHero->name.c_str(), town->garrisonHero->type->heroClass->name.c_str());
+		garrHero->hoverText = buf;
+		}
+	if (town->visitingHero)
+		{
+		visitHero->hero = town->visitingHero;
+		sprintf(buf, CGI->generaltexth->allTexts[15].c_str(), town->visitingHero->name.c_str(), town->visitingHero->type->heroClass->name.c_str());
+		visitHero->hoverText = buf;
+		}
 
 	for (int i=0; i<CREATURES_PER_TOWN;i++)
 	{
 		creaCount[i]->town = NULL;
 
 		int crid = -1;
-		if (!vstd::contains(town->builtBuildings,30+i))
-			continue;
 
 		if (vstd::contains(town->builtBuildings,30+i+CREATURES_PER_TOWN))
 			crid = town->town->upgradedCreatures[i];
@@ -541,6 +543,7 @@ void CKingdomInterface::CTownItem::setTown(const CGTownInstance * newTown)
 	}
 
 	townImage->hoverText = town->name;
+	townImage->town = town;
 
 	hallArea->hoverText = CGI->buildh->buildings[town->subID][10+town->hallLevel()]->Name();
 	if (town->hasFort())
@@ -553,7 +556,8 @@ void CKingdomInterface::CTownItem::activate()
 {
 	if (!town)
 		return;
-	garr->activate();
+
+	setTown(town);
 	hallArea->activate();
 	fortArea->activate();
 	incomeArea->activate();
@@ -570,13 +574,14 @@ void CKingdomInterface::CTownItem::activate()
 			creaGrowth[i]->activate();
 			creaCount [i]->activate();
 		}
+	garr->activate();
 }
 
 void CKingdomInterface::CTownItem::deactivate()
 {
 	if (!town)
 		return;
-	garr->deactivate();
+
 	hallArea->deactivate();
 	fortArea->deactivate();
 	incomeArea->deactivate();
@@ -592,7 +597,7 @@ void CKingdomInterface::CTownItem::deactivate()
 		{
 			creaGrowth[i]->deactivate();
 			creaCount [i]->deactivate();
-		}
+		}	garr->deactivate();
 }
 
 void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
@@ -602,7 +607,7 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
 		blitAt(slots->ourImages[numb % owner->PicCount].bitmap,pos.x,pos.y,to);
 		return;
 	}//background
-	blitAt(slots->ourImages[owner->PicCount+2].bitmap,pos.x,pos.y,to);
+	blitAt(slots->ourImages[owner->PicCount+2].bitmap,pos.x,pos.y,to);	garr->show(to);
 	//town pic/name
 	int townPic = town->subID*2;
 	if (!town->hasFort())
@@ -622,9 +627,21 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
 	std::ostringstream oss;
 	oss << town->dailyIncome();
 	CSDL_Ext::printAtMiddle(oss.str(),pos.x+189,pos.y+61,FONT_SMALL,zwykly,to);
-//	Creature bonuses/ Creature available texts - need to find text wrapper thingy (have "\n" inside text)
-//	CSDL_Ext::printAtWR(CGI->generaltexth->allTexts[265],pos.x,pos.y+80,GEOR13,zwykly,to);
-//	CSDL_Ext::printTo(CGI->generaltexth->allTexts[266],pos.x+350,pos.y+80,GEOR13,zwykly,to);
+
+	std::vector<std::string> * toPrin = CMessage::breakText(CGI->generaltexth->allTexts[265]);
+
+	CSDL_Ext::printAt((*toPrin)[0], pos.x+4, pos.y+76, FONT_SMALL, tytulowy, to);
+	if(toPrin->size()!=1)
+		CSDL_Ext::printAt((*toPrin)[1], pos.x+4, pos.y+92, FONT_SMALL, tytulowy, to);
+
+	delete toPrin;
+	toPrin = CMessage::breakText(CGI->generaltexth->allTexts[266]);
+
+	CSDL_Ext::printAt((*toPrin)[0], pos.x+351, pos.y+76, FONT_SMALL, tytulowy, to);
+	if(toPrin->size()!=1)
+		CSDL_Ext::printAt((*toPrin)[1], pos.x+351, pos.y+92, FONT_SMALL, tytulowy, to);
+	delete toPrin;
+
 	for (int i=0; i<CREATURES_PER_TOWN;i++)
 	{//creatures info
 		int crid = -1;
@@ -651,7 +668,7 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
 		CSDL_Ext::printTo(ostrs.str(),pos.x+440+i*37,pos.y+110,FONT_TINY,zwykly,to);
 	}
 
-	garr->show(to);
+
 	if (town->garrisonHero)
 		blitAt(graphics->portraitLarge[town->garrisonHero->portrait],pos.x+244,pos.y+6,to);
 
@@ -691,7 +708,7 @@ CKingdomInterface::CHeroItem::CHeroItem(int num, CKingdomInterface * Owner)
 	artRight = new AdventureMapButton("", "", boost::bind
 		(&CKingdomInterface::CHeroItem::scrollArts,this,+1), 675, 66, "hsbtns5.def", SDLK_RIGHT);
 
-	portrait = new LRClickableAreaWText();
+	portrait = new LRClickableAreaOpenHero();
 	portrait->pos = genRect(64, 58, pos.x+5, pos.y + 5);
 	char bufor[400];
 	for(int i=0; i<PRIMARY_SKILLS; i++)
@@ -769,8 +786,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
 	artLeft->block(hero->artifacts.size() <= 8);
 	artRight->block(hero->artifacts.size() <= 8);
 	garr = new CGarrisonInt(pos.x+6, pos.y+78, 4, Point(), slots->ourImages[owner->PicCount].bitmap,
-		Point(6,78), hero, NULL, false, true);
-	garr->update = false;
+		Point(6,78), hero, NULL, true, true);
 
 	for (int i=0; i<artifacts.size(); i++)
 	{
@@ -798,7 +814,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
 
 	sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), hero->name.c_str(), hero->type->heroClass->name.c_str());
 	portrait->hoverText = std::string(bufor);
-	portrait->text = hero->getBiography();
+	portrait->hero = hero;
 
 	speciality->text = CGI->generaltexth->hTxts[hero->subID].longBonus;
 
@@ -872,6 +888,7 @@ void CKingdomInterface::CHeroItem::scrollArts(int move)
 			backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type].Name());
 		}
 	}
+	showAll(screen2);
 }
 
 void CKingdomInterface::CHeroItem::showAll(SDL_Surface * to)
@@ -951,11 +968,12 @@ void CKingdomInterface::CHeroItem::onArtChange(int newstate)
 	deactivate();
 	artGroup = newstate;
 	activate();
-	GH.totalRedraw();
+	showAll(screen2);
 }
 
 void CKingdomInterface::CHeroItem::activate()
 {
+	setHero(hero);
 	if (!hero)
 		return;
 	artButtons->activate();
@@ -1077,7 +1095,15 @@ void CKingdomInterface::CTownItem::CCreaPlace::clickLeft(tribool down, bool prev
 
 void CKingdomInterface::CTownItem::CCreaPlace::clickRight(tribool down, bool previousState)
 {
-//TODO
+	if (down && town)
+	{
+		int crid;
+		if (town->builtBuildings.find(30+type+CREATURES_PER_TOWN)!=town->builtBuildings.end())
+			crid = town->town->upgradedCreatures[type];
+		else
+			crid = town->town->basicCreatures[type];
+		GH.pushInt(new CCreInfoWindow(crid, 0, town->creatures[type].first, NULL, 0, 0, NULL));
+	}
 }
 
 void CKingdomInterface::CTownItem::CCreaPlace::deactivate()

+ 5 - 5
client/CKingdomInterface.h

@@ -47,8 +47,8 @@ class CKingdomInterface : public CIntObject
 		CKingdomInterface * owner;
 		int numb;//position on screen (1..size)
 		HoverableArea *hallArea, *fortArea, *incomeArea;//hoverable text for town hall, fort, income
-		HoverableArea * garrHero, *visitHero;//portraits of heroes
-		HoverableArea * townImage;//town image
+		LRClickableAreaOpenHero * garrHero, *visitHero;//portraits of heroes
+		LRClickableAreaOpenTown * townImage;//town image
 		std::vector < HoverableArea * > creaGrowth;
 		std::vector < CCreaPlace * > creaCount;
 		void setTown(const CGTownInstance * newTown);//change town and update info
@@ -70,13 +70,14 @@ class CKingdomInterface : public CIntObject
 			void activate();
 			void deactivate();
 		};
-	public:
+
+		public:
 		const CGHeroInstance * hero;
 		CKingdomInterface * owner;
 		int artGroup,numb;//current art group (0 = equiped, 1 = misc, 2 = backpack)
 		int backpackPos;//first visible artifact in backpack
 		AdventureMapButton * artLeft, * artRight;//buttons for backpack
-		LRClickableAreaWText * portrait;
+		LRClickableAreaOpenHero * portrait;
 		LRClickableAreaWText * experience;
 		LRClickableAreaWTextComp * morale, * luck;
 		LRClickableAreaWText * spellPoints;
@@ -134,7 +135,6 @@ public:
 	void moveObjectList(int newPos);
 	void recreateHeroList(int pos);//recreating heroes list (on slider move)
 	void recreateTownList(int pos);//same for town list
-	void keyPressed(const SDL_KeyboardEvent & key);
 	void listToTowns();//changing list to town view
 	void listToHeroes();//changing list to heroes view
 	void sliderMoved(int newpos);//when we move a slider...

+ 1 - 18
client/CMT.cpp

@@ -9,7 +9,6 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/filesystem/operations.hpp>
 #include <boost/thread.hpp>
-#include <SDL_ttf.h>
 #include <SDL_mixer.h>
 #include "SDL_Extensions.h"
 #include "SDL_framerate.h"
@@ -76,7 +75,6 @@ VCMIDirs GVCMIDirs;
 std::queue<SDL_Event*> events;
 boost::mutex eventsM;
 
-TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
 static bool gOnlyAI = false;
 
 void processCommand(const std::string &message);
@@ -95,21 +93,6 @@ void init()
 #endif
 	CSDL_Ext::std32bppSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, rmask, gmask, bmask, amask);
 	tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
-
-	TTF_Init();
-	atexit(TTF_Quit);
-	TNRB16 = TTF_OpenFont(DATA_DIR "/Fonts/tnrb.ttf",16);
-	GEOR13 = TTF_OpenFont(DATA_DIR "/Fonts/georgia.ttf",13);
-	GEOR16 = TTF_OpenFont(DATA_DIR "/Fonts/georgia.ttf",16);
-	GEORXX = TTF_OpenFont(DATA_DIR "/Fonts/tnrb.ttf",22);
-	GEORM = TTF_OpenFont(DATA_DIR "/Fonts/georgia.ttf",10);
-	if(! (TNRB16 && GEOR16 && GEORXX && GEORM))
-	{
-		tlog1 << "One of the fonts couldn't be loaded!\n";
-		exit(-1);
-	}
-	THC tlog0<<"\tInitializing fonts: "<<pomtime.getDif()<<std::endl;
-
 	{
 		//read system options
 		CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin");
@@ -138,7 +121,7 @@ void init()
 	//CGI->musich->init();
 	//CGI->musich->setVolume(GDefaultOptions.musicVolume);
 	tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
-	tlog0<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
+	tlog0<<"Initializing screen and sound handling: "<<tmh.getDif()<<std::endl;
 
 	initDLL(::console,logfile);
 	CGI->setFromLib();

+ 26 - 13
client/CMessage.cpp

@@ -7,9 +7,6 @@
 #include "../hch/CLodHandler.h"
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
-#include "../hch/CDefHandler.h"
-#include "CGameInfo.h"
-#include "SDL_Extensions.h"
 #include <sstream>
 #include "../hch/CGeneralTextHandler.h"
 #include "Graphics.h"
@@ -33,7 +30,6 @@ SDL_Color tytulowy = {229, 215, 123, 0},
 	darkTitle = {215, 175, 78, 0};
 
 extern SDL_Surface * screen;
-extern TTF_Font * TNRB16, *TNR, *GEOR13;
 
 using namespace NMessage;
 
@@ -264,12 +260,29 @@ SDL_Surface * CMessage::blitTextOnSur(std::vector<std::vector<SDL_Surface*> > *
 
 	return ret;
 }
-std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::string> * brtext, int &fontHeigh, TTF_Font *font)
+
+SDL_Surface * FNT_RenderText (EFonts font, std::string text, SDL_Color kolor= zwykly)
+{
+	if (graphics->fontsTrueType[font])
+		return TTF_RenderText_Blended(graphics->fontsTrueType[font], text.c_str(), kolor);
+	const Font *f = graphics->fonts[font];
+	int w = f->getWidth(text.c_str()),
+	    h = f->height;
+	SDL_Surface * ret = CSDL_Ext::newSurface(w, h, screen);
+	SDL_FillRect (ret, NULL, SDL_MapRGB(ret->format,128,128,128));//if use default black - no shadowing
+	SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,128,128,128));
+	CSDL_Ext::printAt(text.c_str(), 0, 0, font, kolor, ret);
+	return ret;
+}
+
+std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::string> * brtext, int &fontHeigh, EFonts font)
 {
-	if(!font) font = TNRB16;
 	std::vector<std::vector<SDL_Surface*> > * txtg = new std::vector<std::vector<SDL_Surface*> >();
 	txtg->resize(brtext->size());
-	fontHeigh = TTF_FontHeight(font);
+	if (graphics->fontsTrueType[font])
+		fontHeigh = TTF_FontHeight(graphics->fontsTrueType[font]);
+	else
+		fontHeigh = graphics->fonts[font]->height;
 
 	for (size_t i=0; i<brtext->size();i++) //foreach line
 	{
@@ -283,7 +296,7 @@ std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::st
 				z++;
 
 			if (z)
-				(*txtg)[i].push_back(TTF_RenderText_Blended(font, (*brtext)[i].substr(0,z).c_str(), zwykly));
+				(*txtg)[i].push_back(FNT_RenderText(font, (*brtext)[i].substr(0,z), zwykly));
 			(*brtext)[i].erase(0,z);
 
 			if ((*brtext)[i][0] == '{')
@@ -300,7 +313,7 @@ std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::st
 				z++;
 
 			if (z)
-				(*txtg)[i].push_back(TTF_RenderText_Blended(font, (*brtext)[i].substr(0,z).c_str(), tytulowy));
+				(*txtg)[i].push_back(FNT_RenderText(font, (*brtext)[i].substr(0,z), tytulowy));
 			(*brtext)[i].erase(0,z);
 
 			if ((*brtext)[i][0] == '}')
@@ -387,7 +400,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int
 	}
 
 	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);
+		_or = FNT_RenderText(FONT_MEDIUM,CGI->generaltexth->allTexts[4],zwykly);
 
 	std::vector<std::string> * brtext = breakText(text, charperline, true, true); //text 
 	std::vector<std::vector<SDL_Surface*> > * txtg = drawText(brtext, fontHeight);
@@ -493,7 +506,7 @@ SDL_Surface * CMessage::genMessage
 
 	if (title.length())
 	{
-		SDL_Surface * titleText = TTF_RenderText_Blended(TNRB16,title.c_str(),tytulowy);
+		SDL_Surface * titleText = FNT_RenderText(FONT_BIG,title,tytulowy);
 
 		//draw title
 		SDL_Rect tytul = genRect(titleText->h,titleText->w,((ret->w/2)-(titleText->w/2)),37);
@@ -505,7 +518,7 @@ SDL_Surface * CMessage::genMessage
 	{
 		int by = 37+i*21;
 		if (title.length()) by+=40;
-		SDL_Surface * tresc = TTF_RenderText_Blended(TNRB16,(*tekst)[i].c_str(),zwykly);
+		SDL_Surface * tresc = FNT_RenderText(FONT_BIG,(*tekst)[i],zwykly);
 		SDL_Rect trescRect = genRect(tresc->h,tresc->w,((ret->w/2)-(tresc->w/2)),by);
 		SDL_BlitSurface(tresc,NULL,ret,&trescRect);
 		SDL_FreeSurface(tresc);
@@ -570,7 +583,7 @@ ComponentResolved::ComponentResolved( SComponent *Comp )
 	comp = Comp;
 	img = comp->getImg();
 	std::vector<std::string> * brtext = CMessage::breakText(comp->subtitle,13,true,true); //text 
-	txt = CMessage::drawText(brtext,txtFontHeight,GEOR13);
+	txt = CMessage::drawText(brtext,txtFontHeight,FONT_MEDIUM);
 	delete brtext;
 
 	//calculate dimensions

+ 2 - 2
client/CMessage.h

@@ -1,8 +1,8 @@
 #ifndef __CMESSAGE_H__
 #define __CMESSAGE_H__
 
+#include "FontBase.h"
 #include "../global.h"
-#include <SDL_ttf.h>
 #include <SDL.h>
 
 /*
@@ -59,7 +59,7 @@ class CMessage
 public:
 
 	static std::pair<int,int> getMaxSizes(std::vector<std::vector<SDL_Surface*> > * txtg, int fontHeight);
-	static std::vector<std::vector<SDL_Surface*> > * drawText(std::vector<std::string> * brtext, int &fontHeigh, TTF_Font *font = NULL);
+	static std::vector<std::vector<SDL_Surface*> > * drawText(std::vector<std::string> * brtext, int &fontHeigh, EFonts font = FONT_MEDIUM);
 	static SDL_Surface * blitTextOnSur(std::vector<std::vector<SDL_Surface*> > * txtg, int fontHeight, int & curh, SDL_Surface * ret, int xCenterPos=-1); //xPos==-1 works as if ret->w/2
 	static void drawIWindow(CInfoWindow * ret, std::string text, int player, int charperline);
 	static CSimpleWindow * genWindow(std::string text, int player, bool centerOnMouse=false, 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

+ 38 - 6
client/GUIClasses.cpp

@@ -3868,6 +3868,30 @@ void LRClickableAreaWTextComp::deactivate()
 	deactivateHover();
 }
 
+void LRClickableAreaOpenHero::clickLeft(tribool down, bool previousState)
+{
+	if((!down) && previousState && hero)
+		LOCPLINT->openHeroWindow(hero);
+}
+
+void LRClickableAreaOpenHero::clickRight(tribool down, bool previousState)
+{
+	if((!down) && previousState && hero)
+		LOCPLINT->openHeroWindow(hero);
+}
+
+void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState)
+{
+	if((!down) && previousState && town)
+		LOCPLINT->openTownWindow(town);
+}
+
+void LRClickableAreaOpenTown::clickRight(tribool down, bool previousState)
+{
+	if((!down) && previousState && town)
+		LOCPLINT->openTownWindow(town);
+}
+
 void CArtifactsOfHero::activate()
 {
 	for(size_t f=0; f<artWorn.size(); ++f)
@@ -4190,7 +4214,9 @@ void CExchangeWindow::activate()
 	quit->activate();
 	garr->activate();
 
+	artifs[0]->setHero(heroInst[0]);
 	artifs[0]->activate();
+	artifs[1]->setHero(heroInst[1]);
 	artifs[1]->activate();
 
 	for(int g=0; g<ARRAY_COUNT(secSkillAreas); g++)
@@ -4424,9 +4450,9 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
 			secSkillAreas[b][g]->hoverText = std::string(bufor);
 		}
 
-		portrait[b] = new LRClickableAreaWText();
+		portrait[b] = new LRClickableAreaOpenHero();
 		portrait[b]->pos = genRect(64, 58, pos.x + 257 + 228*b, pos.y + 13);
-		portrait[b]->text = heroInst[b]->getBiography();
+		portrait[b]->hero = heroInst[b];
 		sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), heroInst[b]->name.c_str(), heroInst[b]->type->heroClass->name.c_str());
 		portrait[b]->hoverText = std::string(bufor);
 
@@ -4461,8 +4487,11 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
 		morale[b]->bonus = mrlv;
 		morale[b]->text = CGI->generaltexth->arraytxt[88];
 		boost::algorithm::replace_first(morale[b]->text,"%s",CGI->generaltexth->arraytxt[86-mrlt]);
-		for(int it=0; it < mrl.size(); it++)
-			morale[b]->text += mrl[it].second;
+		if (!mrl.size())
+			morale[b]->text += CGI->generaltexth->arraytxt[108];
+		else
+			for(int it=0; it < mrl.size(); it++)
+				morale[b]->text += mrl[it].second;
 
 		//setting luck
 		luck[b] = new LRClickableAreaWTextComp();
@@ -4476,8 +4505,11 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
 		luck[b]->bonus = mrlv;
 		luck[b]->text = CGI->generaltexth->arraytxt[62];
 		boost::algorithm::replace_first(luck[b]->text,"%s",CGI->generaltexth->arraytxt[60-mrlt]);
-		for(int it=0; it < mrl.size(); it++)
-			luck[b]->text += mrl[it].second;
+		if (!mrl.size())
+			luck[b]->text += CGI->generaltexth->arraytxt[77];
+		else
+			for(int it=0; it < mrl.size(); it++)
+				luck[b]->text += mrl[it].second;
 	}
 
 	//buttons

+ 18 - 1
client/GUIClasses.h

@@ -644,6 +644,23 @@ public:
 	virtual void clickRight(tribool down, bool previousState);
 };
 
+class LRClickableAreaOpenHero: public LRClickableAreaWTextComp
+{
+public:
+	const CGHeroInstance * hero;
+	void clickLeft(tribool down, bool previousState);
+	void clickRight(tribool down, bool previousState);
+};
+
+
+class LRClickableAreaOpenTown: public LRClickableAreaWTextComp
+{
+public:
+	const CGTownInstance * town;
+	void clickLeft(tribool down, bool previousState);
+	void clickRight(tribool down, bool previousState);
+};
+
 class CArtPlace: public LRClickableAreaWTextComp
 {
 private:
@@ -740,7 +757,7 @@ class CExchangeWindow : public CWindowWithGarrison
 	LRClickableAreaWText *speciality[2];
 	LRClickableAreaWText *experience[2];
 	LRClickableAreaWText *spellPoints[2];
-	LRClickableAreaWText *portrait[2];
+	LRClickableAreaOpenHero *portrait[2];
 
 public:
 

+ 35 - 0
client/Graphics.cpp

@@ -2,6 +2,7 @@
 #include "Graphics.h"
 #include "../hch/CDefHandler.h"
 #include "SDL_Extensions.h"
+#include <SDL_ttf.h>
 #include <boost/assign/std/vector.hpp> 
 #include <sstream>
 #include <iomanip>
@@ -271,6 +272,7 @@ Graphics::Graphics()
 
 	std::vector<Task> tasks; //preparing list of graphics to load
 	tasks += boost::bind(&Graphics::loadFonts,this);
+	tasks += boost::bind(&Graphics::loadTrueType,this);
 	tasks += boost::bind(&Graphics::loadPaletteAndColors,this);
 	tasks += boost::bind(&Graphics::loadHeroFlags,this);
 	tasks += boost::bind(&Graphics::loadHeroPortraits,this);
@@ -612,6 +614,39 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, int player)
 	}
 }
 
+void Graphics::loadTrueType()
+{
+	bool ttfPresent;//was TTF initialised or not
+	for(int i = 0; i < FONTS_NUMBER; i++)
+		fontsTrueType[i] = NULL;
+	std::ifstream ff(DATA_DIR "/config/fonts.txt");
+	while(!ff.eof())
+	{
+		int enabl, fntID, fntSize;
+		std::string fntName;
+
+		ff >> enabl;//enabled font or not
+		if (enabl==-1)
+			break;//end of data
+		ff >> fntID;//what font will be replaced
+		ff >> fntName;//name of truetype font
+		ff >> fntSize;//size of font
+		if (enabl)
+		{
+			if (!ttfPresent)
+			{
+				ttfPresent = true;
+				TTF_Init();
+				atexit(TTF_Quit);
+			};
+			fntName = DATA_DIR + ( "/Fonts/" + fntName);
+			fontsTrueType[fntID] = TTF_OpenFont(fntName.c_str(),fntSize);
+		}
+	}
+	ff.close();
+	ff.clear();
+}
+
 Font * Graphics::loadFont( const char * name )
 {
 	int len = 0;

+ 3 - 1
client/Graphics.h

@@ -1,7 +1,7 @@
 #ifndef __GRAPHICS_H__
 #define __GRAPHICS_H__
 
-
+#include <SDL_ttf.h>
 #include "../global.h"
 #include "FontBase.h"
 
@@ -50,6 +50,7 @@ public:
 	//Fonts
 	static const int FONTS_NUMBER = 9;
 	Font *fonts[FONTS_NUMBER];
+	TTF_Font * fontsTrueType[FONTS_NUMBER];//true type fonts, if some of the fonts not loaded - NULL
 
 	//various graphics
 	SDL_Color * playerColors; //array [8]
@@ -108,6 +109,7 @@ 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 loadTrueType();
 	void loadFonts();
 	Font *loadFont(const char * name);
 };

+ 41 - 18
client/SDL_Extensions.cpp

@@ -78,7 +78,7 @@ void updateRect (SDL_Rect * rect, SDL_Surface * scr)
 	SDL_UpdateRect(scr,rect->x,rect->y,rect->w,rect->h);
 }
 
-/*void CSDL_Ext::printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
+void printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
 {
 	std::vector<std::string> * ws = CMessage::breakText(text,charpr);
 	std::vector<SDL_Surface*> wesu;
@@ -107,9 +107,9 @@ void updateRect (SDL_Rect * rect, SDL_Surface * scr)
 	for (size_t i=0; i < wesu.size(); ++i)
 		SDL_FreeSurface(wesu[i]);
 	delete ws;
-}*/
+}
 
-/*void CSDL_Ext::printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
+void printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
 {
 	std::vector<std::string> * ws = CMessage::breakText(text,charpr);
 	std::vector<SDL_Surface*> wesu;
@@ -128,9 +128,14 @@ void updateRect (SDL_Rect * rect, SDL_Surface * scr)
 		SDL_FreeSurface(wesu[i]);
 	delete ws;
 }
-*/
+
 void CSDL_Ext::printAtWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refresh)
 {
+	if (graphics->fontsTrueType[font])
+	{
+		printAtWB(text,x, y, graphics->fontsTrueType[font], charpr, kolor, dst);
+		return;
+	}
 	const Font *f = graphics->fonts[font];
 	std::vector<std::string> * ws = CMessage::breakText(text,charpr);
 
@@ -146,6 +151,12 @@ void CSDL_Ext::printAtWB(const std::string & text, int x, int y, EFonts font, in
 
 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*/ )
 {
+	if (graphics->fontsTrueType[font])
+	{
+		printAtMiddleWB(text,x, y, graphics->fontsTrueType[font], charpr, kolor, dst);
+		return;
+	}
+
 	const Font *f = graphics->fonts[font];
 	std::vector<std::string> * ws = CMessage::breakText(text,charpr);
 	int totalHeight = ws->size() * f->height;
@@ -159,7 +170,7 @@ void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts f
 	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)
+void printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2, bool refresh=false)
 {
 	if(text.length()==0) return;
 	SDL_Surface * temp;
@@ -187,10 +198,15 @@ void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts f
 	if(refresh)
 		SDL_UpdateRect(dst,x-(temp->w/2),y-(temp->h/2),temp->w,temp->h);
 	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*/ )
 {
+	if (graphics->fontsTrueType[font])
+	{
+		printAtMiddle(text,x, y, graphics->fontsTrueType[font], kolor, dst);
+		return;
+	}
 	const Font *f = graphics->fonts[font];
 	int nx = x - f->getWidth(text.c_str())/2,
 		ny = y - f->height/2;
@@ -198,7 +214,7 @@ void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts fon
 	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)
+void printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2, bool refresh=false)
 {
 	if (text.length()==0)
 		return;
@@ -227,12 +243,17 @@ void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts fon
 	if(refresh)
 		SDL_UpdateRect(dst,x,y,temp->w,temp->h);
 	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*/ )
 {
 	if(!text.size())
 		return;
+	if (graphics->fontsTrueType[font])
+	{
+		printAt(text,x, y, graphics->fontsTrueType[font], kolor, dst);
+		return;
+	}
 
 	assert(dst);
 	assert(font < Graphics::FONTS_NUMBER);
@@ -250,13 +271,15 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
 	for(int txti = first; txti < beyondEnd; 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;
+	 		src = f->chars[c].pixels;
+			src += i * f->chars[c].width;//if we have reached end of surface in previous line
+
 			for(int j = 0; j < f->chars[c].width  &&  (j + x) < (dst->w - 1); j++)
 			{
 				switch(*src)
@@ -285,12 +308,7 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
 	}
 }
 
-/*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);
-}*/
-
-/*void CSDL_Ext::printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality)
+void printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2)
 {
 	if (text.length()==0)
 		return;
@@ -318,15 +336,20 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
 	SDL_BlitSurface(temp,NULL,dst,&genRect(temp->h,temp->w,x-temp->w,y-temp->h));
 	SDL_UpdateRect(dst,x-temp->w,y-temp->h,temp->w,temp->h);
 	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*/ )
 {
+	if (graphics->fontsTrueType[font])
+	{
+		printTo(text,x, y, graphics->fontsTrueType[font], kolor, dst);
+		return;
+	}
 	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)
+void printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2)
 {
 	if (text.length()==0)
 		return;
@@ -353,7 +376,7 @@ void CSDL_Ext::printTo( const std::string & text, int x, int y, EFonts font, SDL
 	}
 	SDL_BlitSurface(temp,NULL,dst,&genRect(temp->h,temp->w,x-temp->w,y-temp->h));
 	SDL_FreeSurface(temp);
-}*/
+}
 
 void CSDL_Ext::SDL_PutPixel(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A)
 {

+ 0 - 9
client/SDL_Extensions.h

@@ -20,7 +20,6 @@
 
 extern SDL_Surface * screen, *screen2, *screenBuf;
 extern SDL_Color tytulowy, tlo, zwykly ;
-extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM;
 void blitAtWR(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
 void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
 void blitAtWR(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst=screen);
@@ -117,14 +116,6 @@ namespace CSDL_Ext
 	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
-	void printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen);
-	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 printAtWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);
 	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);

+ 29 - 0
config/fonts.txt

@@ -0,0 +1,29 @@
+0	0	tnrb.ttf	20
+0	1	georgia.ttf	10
+0	2	tnrb.ttf	13
+0	3	georgia.ttf	13
+0	4	tnrb.ttf	16
+0	5	georgia.ttf	13
+0	6	tnrb.ttf	08
+0	7	georgia.ttf	10
+0	8	georgia.ttf	13
+-1
+
+Format: 
+1 = enabled, 0=disabled
+font numeric ID
+TTF font name
+font size
+
+
+ID of fonts:
+
+0  BIGFONT.FNT //windows titles
+1  CALLI10R.FNT ?
+2  CREDITS.FNT 
+3  HISCORE.FNT 
+4  MEDFONT.FNT //most used font
+5  SMALFONT.FNT //most used font
+6  TIMES08R.FNT ?
+7  TINY.FNT //used for small texts
+8  VERD10B.FNT ?

+ 44 - 1
hch/CObjectHandler.cpp

@@ -1622,6 +1622,49 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
 	return ret;
 }
 
+int CGTownInstance::defenceBonus(int type) const
+{
+	int ret=0;
+	switch (type)
+		{
+/*attack*/		case 0: 
+						if (subID == 6 && vstd::contains(builtBuildings,26))//Stronghold, grail
+							ret += 12;
+						if (subID == 7 && vstd::contains(builtBuildings,26))//Fortress, grail
+							ret += 10;
+						if (subID == 7 && vstd::contains(builtBuildings,22))//Fortress, Blood Obelisk
+							ret += 2;
+							return ret;
+/*defence*/		case 1:
+						if (subID == 7 && vstd::contains(builtBuildings,21))//Fortress, Glyphs of Fear
+							ret += 2;
+						if (subID == 7 && vstd::contains(builtBuildings,26))//Fortress, Grail
+							ret += 10;
+							return ret;
+/*spellpower*/	case 2:
+						if (subID == 3 && vstd::contains(builtBuildings,21))//Inferno, Brimstone Clouds
+							ret += 2;
+						if (subID == 5 && vstd::contains(builtBuildings,26))//Dungeon, Grail
+							ret += 12;
+							return ret;
+/*knowledge*/	case 3:
+						if (subID == 2 && vstd::contains(builtBuildings,26))//Tower, Grail
+							ret += 15;
+							return ret;
+/*morale*/		case 4:
+						if (              vstd::contains(builtBuildings, 5))//Any, Tavern
+							ret += 1;
+						if (subID == 0 && vstd::contains(builtBuildings,22))//Castle, Brotherhood of the sword
+							ret += 1;
+							return ret;
+/*luck*/		case 5:
+						if (subID == 1 && vstd::contains(builtBuildings,21))//Rampart, Fountain of Fortune
+							ret += 2;
+							return ret;
+		}
+		return 0;//Why we are here? wrong type?
+}
+
 bool CGTownInstance::needsLastStack() const
 {
 	if(garrisonHero)
@@ -1700,7 +1743,7 @@ void CGTownInstance::newTurn() const
 {
 	if (cb->getDate(1) == 1) //reset on new week
 	{
-		if (vstd::contains(builtBuildings,17) && subID == 1 && cb->getDate(0) && (tempOwner < PLAYER_LIMIT) )//give resources for Rampart, Mystic Pond
+		if (vstd::contains(builtBuildings,17) && subID == 1 && cb->getDate(0) != 1 && (tempOwner < PLAYER_LIMIT) )//give resources for Rampart, Mystic Pond
 		{
 			int resID = rand()%4+2;//bonus to random rare resource
 			resID = (resID==2)?1:resID;

+ 1 - 0
hch/CObjectHandler.h

@@ -493,6 +493,7 @@ public:
 	int dailyIncome() const; //calculates daily income of this town
 	int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
 	void removeCapitols (ui8 owner, bool me) const;
+	int defenceBonus(int type) const;//bonuses for defending hero, 0..3 - primary skills, 4 = morale, 5 = luck
 
 	CGTownInstance();
 	virtual ~CGTownInstance();

+ 31 - 1
server/CGameHandler.cpp

@@ -1265,6 +1265,35 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
 		}
 	}
 
+	//giving building bonuses, if siege and we have harrisoned hero
+	if (town)
+	{
+		if (hero2)
+			for (int i=0; i<4; i++)
+			{
+				int val = town->defenceBonus(i);
+				if (val)
+				{
+					GiveBonus gs;
+					gs.bonus = HeroBonus(HeroBonus::ONE_BATTLE, HeroBonus::PRIMARY_SKILL, HeroBonus::OBJECT, val, -1, "", i);
+					gs.hid = hero2->id;
+					sendAndApply(&gs);
+				}
+			}
+
+		int bonuseValue = town->defenceBonus(4);//morale
+		if (bonuseValue)
+			for(int g=0; g<stacks.size(); ++g)
+				if (!stacks[g]->attackerOwned)//garrisoned stack
+					stacks[g]->features.push_back(makeFeature(StackFeature::MORALE_BONUS, StackFeature::WHOLE_BATTLE, 0, bonuseValue, StackFeature::OTHER_SOURCE));
+
+		bonuseValue = town->defenceBonus(5);//luck
+		if (bonuseValue)
+			for(int g=0; g<stacks.size(); ++g)
+				if (!stacks[g]->attackerOwned)//garrisoned stack
+					stacks[g]->features.push_back(makeFeature(StackFeature::LUCK_BONUS, StackFeature::WHOLE_BATTLE, 0, bonuseValue, StackFeature::OTHER_SOURCE));
+	}
+
 	//giving terrain premies for heroes & stacks
 
 	int bonusSubtype = -1;
@@ -2555,7 +2584,8 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
 		if(vstd::contains(hero->artifWorn,ui16(9+aid)) && complain("Hero already has this machine!")
 			|| !vstd::contains(town->builtBuildings,si32(16)) && complain("No blackismith!")
 			|| gs->getPlayer(hero->getOwner())->resources[6] < price  && complain("Not enough gold!")  //no gold
-			|| town->town->warMachine!= aid  &&  complain("This machine is unavailable here!") ) //TODO: ballista yard in Stronghold
+			|| (!(town->subID == 6 && vstd::contains(town->builtBuildings,si32(22) ) )
+			&& town->town->warMachine!= aid ) &&  complain("This machine is unavailable here!") ) 
 		{
 			return false;
 		}