Quellcode durchsuchen

* make compatible with boost 1.36.0 (there was breaking change in boost::function)
* randomizing spells in towns
* fixed reading forbidden structures
* support for heroes starting in town garrisons
* hopefully fixed problems with wrong town defs (village/fort/capitol)
* moved CSpellHandler.* to VCMI_Lib (project files must be updated)
* redone reading spell info
* added missing features to the fort screen
* minor improvements

* partially done mage guild screen

Michał W. Urbańczyk vor 17 Jahren
Ursprung
Commit
22ade5efbe

+ 129 - 16
CCastleInterface.cpp

@@ -1,25 +1,26 @@
 #include "stdafx.h"
+#include "AdventureMapButton.h"
+#include "CAdvmapInterface.h"
+#include "CCallback.h"
 #include "CCastleInterface.h"
-#include "hch/CObjectHandler.h"
 #include "CGameInfo.h"
-#include "hch/CLodHandler.h"
+#include "CHeroWindow.h"
+#include "CMessage.h"
 #include "SDL_Extensions.h"
-#include "CAdvmapInterface.h"
-#include "hch/CTownHandler.h"
-#include "AdventureMapButton.h"
+#include "client/CCreatureAnimation.h"
+#include "client/Graphics.h"
 #include "hch/CBuildingHandler.h"
 #include "hch/CDefHandler.h"
-#include <sstream>
-#include "CMessage.h"
 #include "hch/CGeneralTextHandler.h"
-#include "CCallback.h"
-#include "client/Graphics.h"
-#include "client/CCreatureAnimation.h"
-#include "CHeroWindow.h"
+#include "hch/CLodHandler.h"
+#include "hch/CObjectHandler.h"
+#include "hch/CSpellHandler.h"
+#include "hch/CTownHandler.h"
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/assign/std/vector.hpp> 
 #include <cmath>
+#include <sstream>
 using namespace boost::assign;
 using namespace CSDL_Ext;
 
@@ -469,6 +470,12 @@ void CCastleInterface::buildingClicked(int building)
 	{
 		switch(building)
 		{
+		case 0: case 1: case 2: case 3: case 4:
+			{
+				deactivate();
+				(new CMageGuildScreen(this))->activate();
+				break;
+			}
 		case 7: case 8: case 9:
 			{
 				CFortScreen *fs = new CFortScreen(this);
@@ -944,10 +951,6 @@ CHallInterface::CHallInterface(CCastleInterface * owner)
 					}
 
 					//TODO: check if capital is already built, check if there is water for shipyard
-
-
-
-
 					break;
 				}
 			}
@@ -1205,6 +1208,8 @@ void CFortScreen::show( SDL_Surface * to)
 	}
 	anim++;
 	exit->show();
+	resdatabar.show();
+	LOCPLINT->statusbar->show();
 }
 
 void CFortScreen::activate()
@@ -1324,12 +1329,13 @@ void CFortScreen::draw( CCastleInterface * owner, bool first)
 }
 void CFortScreen::RecArea::clickLeft (tribool down)
 {
-	if(!down)
+	if(!down && pressedL)
 	{
 		LOCPLINT->curint->deactivate();
 		CRecrutationWindow *rw = LOCPLINT->castleInt->showRecruitmentWindow(bid);
 		rw->buy->callback += boost::bind(&CFortScreen::draw, static_cast<CFortScreen*>(LOCPLINT->curint), LOCPLINT->castleInt, false);
 	}
+	ClickableL::clickLeft(down);
 }
 void CFortScreen::RecArea::activate()
 {
@@ -1339,3 +1345,110 @@ void CFortScreen::RecArea::deactivate()
 {
 	ClickableL::deactivate();
 }
+
+CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner)
+{
+	bg = BitmapHandler::loadBitmap("TPMAGE.bmp");
+	exit = new AdventureMapButton(CGI->townh->tcommands[8],"",boost::bind(&CMageGuildScreen::close,this),748,556,"TPMAGE1.DEF",false,NULL,false);
+	scrolls = CDefHandler::giveDefEss("SPELLSCR.DEF");
+	scrolls2 = CDefHandler::giveDefEss("TPMAGES.DEF");
+	SDL_Surface *view = BitmapHandler::loadBitmap(graphics->guildBgs[owner->town->subID]);
+	SDL_SetColorKey(view,SDL_SRCCOLORKEY,SDL_MapRGB(view->format,0,255,255));
+	positions.resize(5);
+	positions[0] += genRect(61,83,222,445), genRect(61,83,312,445), genRect(61,83,402,445), genRect(61,83,520,445), genRect(61,83,610,445), genRect(61,83,700,445);
+	positions[1] += genRect(61,83,48,53), genRect(61,83,48,147), genRect(61,83,48,241), genRect(61,83,48,335), genRect(61,83,48,429);
+	positions[2] += genRect(61,83,570,82), genRect(61,83,672,82), genRect(61,83,570,157), genRect(61,83,672,157);
+	positions[3] += genRect(61,83,183,42), genRect(61,83,183,148), genRect(61,83,183,253);
+	positions[4] += genRect(61,83,491,325), genRect(61,83,591,325);
+	blitAt(view,332,76,bg);
+	for(int i=0; i<owner->town->town->mageLevel; i++)
+	{
+		int sp = 5 - i; //how many spells are available at this level
+		if(owner->town->subID==2 && vstd::contains(owner->town->builtBuildings,22)) sp++; //magic library in tower
+		for(int j=0; j<sp; j++)
+		{
+			if(i < owner->town->mageGuildLevel())
+			{
+				spells.push_back(Scroll(&CGI->spellh->spells[owner->town->spells[i][j]]));
+				spells[spells.size()-1].pos = positions[i][j];
+				blitAt(scrolls->ourImages[owner->town->spells[i][j]].bitmap,positions[i][j],bg);
+			}
+			else
+			{
+				blitAt(scrolls2->ourImages[1].bitmap,positions[i][j],bg);
+			}
+		}
+	}
+	SDL_FreeSurface(view);
+	delete scrolls2;
+}
+CMageGuildScreen::~CMageGuildScreen()
+{
+	delete exit;
+	delete scrolls;
+	SDL_FreeSurface(bg);
+}
+void CMageGuildScreen::close()
+{
+	deactivate();
+	delete this;
+	LOCPLINT->castleInt->activate();
+	LOCPLINT->castleInt->showAll();
+}
+void CMageGuildScreen::show(SDL_Surface * to)
+{
+	blitAt(bg,0,0);
+	resdatabar.show();
+	exit->show();
+}
+void CMageGuildScreen::activate()
+{
+	LOCPLINT->objsToBlit += this;
+	LOCPLINT->castleInt->subInt = this;
+	exit->activate();
+	for(int i=0;i<spells.size();i++)
+		spells[i].activate();
+}
+void CMageGuildScreen::deactivate()
+{
+	LOCPLINT->objsToBlit -= this;
+	exit->deactivate();
+	for(int i=0;i<spells.size();i++)
+		spells[i].deactivate();
+}
+void CMageGuildScreen::Scroll::clickLeft (tribool down)
+{
+
+}
+void CMageGuildScreen::Scroll::clickRight (tribool down)
+{
+	if(down)
+	{
+		CInfoPopup *vinya = new CInfoPopup();
+		vinya->free = true;
+		vinya->bitmap = CMessage::drawBoxTextBitmapSub
+			(LOCPLINT->playerID,
+			spell->descriptions[0],
+			static_cast<CMageGuildScreen*>(LOCPLINT->castleInt->subInt)->scrolls->ourImages[spell->id].bitmap,
+			spell->name);
+		vinya->pos.x = screen->w/2 - vinya->bitmap->w/2;
+		vinya->pos.y = screen->h/2 - vinya->bitmap->h/2;
+		vinya->activate();
+	}
+}
+void CMageGuildScreen::Scroll::hover(bool on)
+{
+
+}
+void CMageGuildScreen::Scroll::activate()
+{
+	ClickableL::activate();
+	ClickableR::activate();
+	Hoverable::activate();
+}
+void CMageGuildScreen::Scroll::deactivate()
+{
+	ClickableL::deactivate();
+	ClickableR::deactivate();
+	Hoverable::deactivate();
+}

+ 33 - 0
CCastleInterface.h

@@ -7,6 +7,7 @@ class CGTownInstance;
 class CTownHandler;
 class CHallInterface;
 struct Structure;
+class CSpell;
 class AdventureMapButton;
 class CBuildingRect : public Hoverable, public MotionInterested, public ClickableL, public ClickableR//, public TimeInterested
 {
@@ -171,4 +172,36 @@ public:
 	void show(SDL_Surface * to=NULL);
 	void activate();
 	void deactivate();
+};
+
+class CMageGuildScreen : public IShowActivable
+{
+public:	
+	class Scroll : public ClickableL, public Hoverable, public ClickableR
+	{
+	public:
+		CSpell *spell;
+
+		Scroll(CSpell *Spell):spell(Spell){};
+		void clickLeft (tribool down);
+		void clickRight (tribool down);
+		void hover(bool on);
+		void activate();
+		void deactivate();
+	};
+	std::vector<std::vector<SDL_Rect> > positions;
+
+	SDL_Surface *bg;
+	CDefEssential *scrolls, *scrolls2;
+	AdventureMapButton *exit;
+	std::vector<Scroll> spells;
+	CMinorResDataBar resdatabar;
+
+
+	CMageGuildScreen(CCastleInterface * owner);
+	~CMageGuildScreen();
+	void close();
+	void show(SDL_Surface * to=NULL);
+	void activate();
+	void deactivate();
 };

+ 5 - 2
CGameInterface.cpp

@@ -34,7 +34,10 @@ CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname)
 	if (!dll)
 	{
 		std::cout << "Cannot open AI library ("<<dllname<<"). Throwing..."<<std::endl;
+	#ifdef _MSC_VER
 		throw new std::exception("Cannot open AI library");
+	#endif
+		throw new std::exception();
 	}
 	//int len = dllname.size()+1;
 	getName = (void(*)(char*))GetProcAddress(dll,"GetAiName");
@@ -43,12 +46,12 @@ CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname)
 	; //TODO: handle AI library on Linux
 #endif
 	char * temp = new char[50];
-#if !defined(__amigaos4__) && !defined(__unix__)
+#if _WIN32
 	getName(temp);
 #endif
 	std::cout << "Loaded .dll with AI named " << temp << std::endl;
 	delete temp;
-#if !defined(__amigaos4__) && !defined(__unix__)
+#if _WIN32
 	ret = getAI();
 	ret->init(cb);
 #else

+ 2 - 2
CGameInterface.h

@@ -54,8 +54,8 @@ public:
 	virtual void tileRevealed(int3 pos){};
 	virtual void tileHidden(int3 pos){};
 	virtual void receivedResource(int type, int val){};
-	virtual void showInfoDialog(std::string &text, std::vector<Component*> &components){};
-	virtual void showSelDialog(std::string &text, std::vector<Component*> &components, ui32 askID){};
+	virtual void showInfoDialog(std::string &text, const std::vector<Component*> &components){};
+	virtual void showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID){};
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
 	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
 	virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id

+ 52 - 2
CGameState.cpp

@@ -7,6 +7,7 @@
 #include "hch/CDefObjInfoHandler.h"
 #include "hch/CArtHandler.h"
 #include "hch/CTownHandler.h"
+#include "hch/CSpellHandler.h"
 #include "hch/CHeroHandler.h"
 #include "hch/CObjectHandler.h"
 #include "hch/CCreatureHandler.h"
@@ -19,6 +20,8 @@
 #include <boost/thread/shared_mutex.hpp>
 boost::rand48 ran;
 
+
+
 CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
 {
 	CGObjectInstance * nobj;
@@ -1018,6 +1021,8 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			vti->town = &VLC->townh->towns[vti->subID];
 		if (vti->name.length()==0) // if town hasn't name we draw it
 			vti->name=vti->town->names[ran()%vti->town->names.size()];
+
+		//init buildings
 		if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
 		{
 			vti->builtBuildings.erase(-50);
@@ -1027,6 +1032,39 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			if(ran()%2)
 				vti->builtBuildings.insert(31);
 		}
+
+		//init spells
+		vti->spells.resize(SPELL_LEVELS);
+		CSpell *s;
+		for(int z=0; z<vti->obligatorySpells.size();z++)
+		{
+			s = &VLC->spellh->spells[vti->obligatorySpells[z]];
+			vti->spells[s->level-1].push_back(s->id);
+			vti->possibleSpells -= s->id;
+		}
+		while(vti->possibleSpells.size())
+		{
+			ui32 total=0, sel=-1;
+			for(int ps=0;ps<vti->possibleSpells.size();ps++)
+				total += VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
+			int r = (total)? ran()%total : -1;
+			for(int ps=0; ps<vti->possibleSpells.size();ps++)
+			{
+				r -= VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
+				if(r<0)
+				{
+					sel = ps;
+					break;
+				}
+			}
+			if(sel<0)
+				sel=0;
+
+			CSpell *s = &VLC->spellh->spells[vti->possibleSpells[sel]];
+			vti->spells[s->level-1].push_back(s->id);
+			vti->possibleSpells -= s->id;
+		}
+		
 		players[vti->getOwner()].towns.push_back(vti);
 	}
 
@@ -1048,7 +1086,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			}
 		}
 
-		//init visiting heroes
+		//init visiting and garrisoned heroes
 		for(int l=0; l<k->second.heroes.size();l++)
 		{ 
 			for(int m=0; m<k->second.towns.size();m++)
@@ -1057,9 +1095,21 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 				if(vistile == k->second.heroes[l]->pos)
 				{
 					k->second.towns[m]->visitingHero = k->second.heroes[l];
-					break;
+					k->second.heroes[l]->visitedTown = k->second.towns[m];
+					k->second.heroes[l]->inTownGarrison = false;
+					goto mainplheloop;
+				}
+				else if(k->second.heroes[l]->pos == k->second.towns[m]->pos)
+				{
+					k->second.towns[m]->garrisonHero = k->second.heroes[l];
+					k->second.towns[m]->army = k->second.heroes[l]->army;
+					k->second.heroes[l]->visitedTown = k->second.towns[m];
+					k->second.heroes[l]->inTownGarrison = true;
+					k->second.heroes[l]->pos.x -= 1;
+					goto mainplheloop;
 				}
 			}
+mainplheloop:;
 		}
 	}
 }

+ 2 - 2
CGameState.h

@@ -2,7 +2,7 @@
 #define CGAMESTATE_H
 #include "global.h"
 #ifndef _MSC_VER
-#include "../hch/CCreatureHandler.h"
+#include "hch/CCreatureHandler.h"
 #include "lib/VCMI_Lib.h"
 #endif
 #include <set>
@@ -152,7 +152,7 @@ private:
 	UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos);
 public:
 	int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
-	
+
 	friend class CCallback;
 	friend class CPathfinder;;
 	friend class CLuaCallback;

+ 8 - 16
CHeroWindow.cpp

@@ -8,6 +8,7 @@
 #include "SDL.h"
 #include "SDL_Extensions.h"
 #include "CAdvmapInterface.h"
+#include "CCastleInterface.h"
 #include "hch/CLodHandler.h"
 #include "AdventureMapButton.h"
 #include "hch/CObjectHandler.h"
@@ -39,7 +40,7 @@ CHeroWindow::CHeroWindow(int playerColor):
 	garInt = NULL;
 	ourBar = new CStatusBar(72, 567, "ADROLLVR.bmp", 660);
 
-	quitButton = new AdventureMapButton(CGI->generaltexth->heroscrn[17], std::string(), boost::bind(&CHeroWindow::quit,this), 674, 524, "hsbtns.def", false, NULL, false);
+	quitButton = new AdventureMapButton(CGI->generaltexth->heroscrn[17], std::string(), boost::function<void()>(), 674, 524, "hsbtns.def", false, NULL, false);
 	dismissButton = new AdventureMapButton(std::string(), CGI->generaltexth->heroscrn[28], boost::bind(&CHeroWindow::dismissCurrent,this), 519, 437, "hsbtns2.def", false, NULL, false);
 	questlogButton = new AdventureMapButton(CGI->generaltexth->heroscrn[0], std::string(), boost::bind(&CHeroWindow::questlog,this), 379, 437, "hsbtns4.def", false, NULL, false);
 
@@ -509,24 +510,16 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
 
 void CHeroWindow::quit()
 {
-	for(int i=0; i<LOCPLINT->objsToBlit.size(); ++i)
-	{
-		if( dynamic_cast<CHeroWindow*>( LOCPLINT->objsToBlit[i] ) )
-		{
-			LOCPLINT->objsToBlit.erase(LOCPLINT->objsToBlit.begin()+i);
-		}
-	}
+	LOCPLINT->objsToBlit -= this;
+
 	deactivate();
 
+	if(LOCPLINT->curint == LOCPLINT->castleInt)
+		LOCPLINT->castleInt->subInt = NULL;
 	LOCPLINT->curint->activate();
 
 	SDL_FreeSurface(curBack);
 	curBack = NULL;
-	/*for(int v=0; v<LOCPLINT->lclickable.size(); ++v)
-	{
-		if(dynamic_cast<CArtPlace*>(LOCPLINT->lclickable[v]))
-			LOCPLINT->lclickable.erase(LOCPLINT->lclickable.begin()+v);
-	}*/
 
 	for(int g=0; g<artWorn.size(); ++g)
 	{
@@ -1052,8 +1045,7 @@ void LRClickableAreaWText::clickLeft(boost::logic::tribool down)
 {
 	if(!down)
 	{
-		std::vector<SComponent*> comp;
-		LOCPLINT->showInfoDialog(text, comp);
+		LOCPLINT->showInfoDialog(text, std::vector<SComponent*>());
 	}
 }
 void LRClickableAreaWText::clickRight(boost::logic::tribool down)
@@ -1097,7 +1089,7 @@ void LRClickableAreaWTextComp::clickLeft(boost::logic::tribool down)
 {
 	if((!down) && pressedL)
 	{
-		std::vector<SComponent*> comp(1, new SComponent(SComponent::Etype(baseType), type, bonus));
+		std::vector<SComponent*> comp(1, new SComponent(SComponent::Etype(baseType), type, bonus));
 		LOCPLINT->showInfoDialog(text, comp);
 	}
 	ClickableL::clickLeft(down);

+ 1 - 1
CHeroWindow.h

@@ -80,7 +80,7 @@ public:
 	~CArtPlace();
 };
 
-class CHeroWindow: public IActivable, public IShowable, public virtual CIntObject
+class CHeroWindow: public IShowActivable, public virtual CIntObject
 {
 	SDL_Surface * background, * curBack;
 	const CGHeroInstance * curHero;

+ 1 - 4
CMT.cpp

@@ -101,6 +101,7 @@ int main(int argc, _TCHAR* argv[])
 		CGI->townh = VLC->townh;
 		CGI->heroh = VLC->heroh;
 		CGI->objh = VLC->objh;
+		CGI->spellh = VLC->spellh;
 		CGI->dobjinfo = VLC->dobjinfo;
 		CGI->buildh = VLC->buildh;
 		THC std::cout<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
@@ -139,10 +140,6 @@ int main(int argc, _TCHAR* argv[])
 		boost::thread servthr(boost::bind(system,SERVER_NAME " > server_log.txt")); //runs server executable; 
 												//TODO: will it work on non-windows platforms?
 		THC tmh.getDif();pomtime.getDif();//reset timers
-		CSpellHandler * spellh = new CSpellHandler;
-		spellh->loadSpells();
-		cgi->spellh = spellh;		
-		THC std::cout<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
 		cgi->pathf = new CPathfinder();
 		THC std::cout<<"\tPathfinder: "<<pomtime.getDif()<<std::endl;
 		cgi->consoleh->runConsole();

+ 52 - 31
CPlayerInterface.cpp

@@ -165,13 +165,19 @@ void CGarrisonSlot::clickLeft(tribool down)
 						boost::bind(&CCallback::upgradeCreature,LOCPLINT->cb,getObj(),ID,pom.newID[0]), //if upgrade is possible we'll bind proper function in callback
 						 boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),&pom))
 							->activate();
-					LOCPLINT->curint->deactivate();
 				}
 				else
 				{
 					(new CCreInfoWindow
 						(creature->idNumber,1,count,NULL,0, boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),NULL) )
 						->activate();
+				}
+				if(LOCPLINT->curint == LOCPLINT->castleInt   &&   dynamic_cast<CHeroWindow*>(LOCPLINT->castleInt->subInt))
+				{
+					LOCPLINT->castleInt->subInt->deactivate();
+				}
+				else
+				{
 					LOCPLINT->curint->deactivate();
 				}
 				owner->highlighted = NULL;
@@ -479,7 +485,7 @@ void CGarrisonInt::deactivate()
 	deactiveteSlots();
 }
 
-CInfoWindow::CInfoWindow(std::string text, int player, int charperline, std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons)
+CInfoWindow::CInfoWindow(std::string text, int player, int charperline, const std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons)
 {
 	for(int i=0;i<Buttons.size();i++)
 	{
@@ -1932,7 +1938,7 @@ void CPlayerInterface::receivedResource(int type, int val)
 	adventureInt->resdatabar.draw();
 }
 
-void CPlayerInterface::showSelDialog(std::string &text, std::vector<Component*> &components, ui32 askID)
+void CPlayerInterface::showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID)
 //void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)
 {
 	boost::unique_lock<boost::mutex> un(*pim);
@@ -1970,26 +1976,12 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
 	if(town->garrisonHero)
 	{
 		CGI->mh->hideObject(town->garrisonHero);
-		if(adventureInt->heroList.items.size()==1) //it was the only hero
-			adventureInt->townList.select(0);
-		else
-		{
-			for(int i=0; i<adventureInt->heroList.items.size();i++)
-			{
-				if(adventureInt->heroList.items[i].first == town->garrisonHero)
-				{
-					adventureInt->heroList.items.erase(adventureInt->heroList.items.begin()+i);
-						adventureInt->heroList.selected = adventureInt->heroList.items.size()-1;
-					break;
-				}
-			}
-		}
 	}
 	if(town->visitingHero)
 	{
 		CGI->mh->printObject(town->visitingHero);
-		adventureInt->heroList.items.push_back(std::pair<const CGHeroInstance*, CPath *>(town->visitingHero,NULL));
 	}
+	adventureInt->heroList.updateHList();
 
 	CCastleInterface *c = dynamic_cast<CCastleInterface*>(curint);
 	if(c)
@@ -2039,7 +2031,11 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 			SDL_FreeSurface(graphics->townWins[tt->id]);
 			graphics->townWins[tt->id] = infoWin(tt);
 		}
-
+		if(tt->visitingHero)
+		{
+			SDL_FreeSurface(graphics->heroWins[tt->visitingHero->subID]);
+			graphics->heroWins[tt->visitingHero->subID] = infoWin(tt->visitingHero);
+		}
 		if(LOCPLINT->castleInt)
 		{
 			LOCPLINT->castleInt->garr->highlighted = NULL;
@@ -2049,11 +2045,20 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 }
 void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished
 {
+	boost::unique_lock<boost::mutex> un(*pim);
+	switch (buildingID)
+	{
+	case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 15:
+		{
+			SDL_FreeSurface(graphics->townWins[town->id]);
+			graphics->townWins[town->id] = infoWin(town);
+			break;
+		}
+	}
 	if(curint!=castleInt)
 		return;
 	if(castleInt->town!=town)
 		return;
-	boost::unique_lock<boost::mutex> un(*pim);
 	switch(what)
 	{
 	case 1:
@@ -2156,14 +2161,14 @@ void CPlayerInterface::showComp(SComponent comp)
 	adventureInt->infoBar.showComp(&comp,4000);
 }
 
-void CPlayerInterface::showInfoDialog(std::string &text, std::vector<Component*> &components)
+void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<Component*> &components)
 {
 	std::vector<SComponent*> intComps;
 	for(int i=0;i<components.size();i++)
 		intComps.push_back(new SComponent(*components[i]));
 	showInfoDialog(text,intComps);
 }
-void CPlayerInterface::showInfoDialog(std::string &text, std::vector<SComponent*> & components)
+void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<SComponent*> & components)
 {
 	showingDialog->set(true);
 	curint->deactivate(); //dezaktywacja starego interfejsu
@@ -2176,7 +2181,7 @@ void CPlayerInterface::showInfoDialog(std::string &text, std::vector<SComponent*
 	temp->activate();
 	LOCPLINT->objsToBlit.push_back(temp);
 }
-void CPlayerInterface::showYesNoDialog(std::string &text, std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps)
+void CPlayerInterface::showYesNoDialog(std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps)
 {
 	if(deactivateCur)
 		curint->deactivate(); //dezaktywacja starego interfejsu
@@ -2216,6 +2221,10 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 	adventureInt->heroWindow->setHero(hero);
 	this->objsToBlit.push_back(adventureInt->heroWindow);
 	curint->deactivate();
+	if(curint == castleInt)
+		castleInt->subInt = adventureInt->heroWindow;
+	adventureInt->heroWindow->quitButton->callback.funcs.clear();
+	adventureInt->heroWindow->quitButton->callback += boost::bind(&CHeroWindow::quit,adventureInt->heroWindow);
 	adventureInt->heroWindow->activate();
 }
 CStatusBar::CStatusBar(int x, int y, std::string name, int maxw)
@@ -2318,7 +2327,9 @@ void CHeroList::genList()
 	int howMany = LOCPLINT->cb->howManyHeroes();
 	for (int i=0;i<howMany;i++)
 	{
-		items.push_back(std::pair<const CGHeroInstance *,CPath *>(LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,i,0),NULL));
+		const CGHeroInstance * h = LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,i,0);
+		if(!h->inTownGarrison)
+			items.push_back(std::pair<const CGHeroInstance *,CPath *>(h,NULL));
 	}
 }
 void CHeroList::select(int which)
@@ -2506,15 +2517,16 @@ void CHeroList::draw()
 			blitAt(empty,posporx,pospory+i*32);
 			continue;
 		}
-		int pom = (LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,iT,0)->movement)/100;
+		const CGHeroInstance *cur = items[iT].first;
+		int pom = cur->movement / 100;
 		if (pom>25) pom=25;
 		if (pom<0) pom=0;
 		blitAt(mobile->ourImages[pom].bitmap,posmobx,posmoby+i*32); //move point
-		pom = (LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,iT,0)->mana)/5; //bylo: .../10;
+		pom = cur->mana / 5; //bylo: .../10;
 		if (pom>25) pom=25;
 		if (pom<0) pom=0;
 		blitAt(mana->ourImages[pom].bitmap,posmanx,posmany+i*32); //mana
-		SDL_Surface * temp = graphics->portraitSmall[LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,iT,0)->portrait];
+		SDL_Surface * temp = graphics->portraitSmall[cur->portrait];
 		blitAt(temp,posporx,pospory+i*32);
 		if ((selected == iT) && (LOCPLINT->adventureInt->selection.type == HEROI_TYPE))
 		{
@@ -2860,7 +2872,7 @@ void CRecrutationWindow::show(SDL_Surface * to)
 	cancel->show();
 	slider->show();
 	char pom[15];
-	SDL_itoa(creatures[which].amount,pom,10); //available
+	SDL_itoa(creatures[which].amount-slider->value,pom,10); //available
 	printAtMiddle(pom,pos.x+205,pos.y+252,GEOR13,zwykly,screen);
 	SDL_itoa(slider->value,pom,10); //recruit
 	printAtMiddle(pom,pos.x+279,pos.y+252,GEOR13,zwykly,screen);
@@ -3228,9 +3240,18 @@ void CCreInfoWindow::close()
 {
 	deactivate();
 	CCastleInterface *c = dynamic_cast<CCastleInterface*>(LOCPLINT->curint);
-	if(c) c->showAll();
-	if(type)
-		LOCPLINT->curint->activate();
+	if(c && dynamic_cast<CHeroWindow*>(c->subInt))
+	{
+		if(type)
+			c->subInt->activate();
+	}
+	else
+	{
+		if(c)
+			c->showAll();
+		if(type)
+			LOCPLINT->curint->activate();
+	}
 	delete this;
 }
 void CCreInfoWindow::clickRight(boost::logic::tribool down)

+ 9 - 9
CPlayerInterface.h

@@ -24,7 +24,7 @@ class CCreatureSet;
 class CGObjectInstance;
 class CSlider;
 struct UpgradeInfo;
-template <typename T> struct CondSh; 
+template <typename T> struct CondSh;
 
 namespace boost
 {
@@ -174,7 +174,7 @@ public:
 	virtual void show(SDL_Surface * to = NULL);
 	void activate();
 	void deactivate();
-	CInfoWindow(std::string text, int player, int charperline, std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons);
+	CInfoWindow(std::string text, int player, int charperline, const std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons);
 	CInfoWindow();
 	~CInfoWindow();
 };
@@ -341,8 +341,8 @@ public:
 	void heroCreated(const CGHeroInstance* hero);
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val);
 	void receivedResource(int type, int val);
-	void showInfoDialog(std::string &text, std::vector<Component*> &components);
-	void showSelDialog(std::string &text, std::vector<Component*> &components, ui32 askID);
+	void showInfoDialog(std::string &text, const std::vector<Component*> &components);
+	void showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID);
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
 	void garrisonChanged(const CGObjectInstance * obj);
 	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
@@ -374,9 +374,9 @@ public:
 	void handleMouseMotion(SDL_Event *sEvent);
 	void init(ICallback * CB);
 	int3 repairScreenPos(int3 pos);
-	void removeObjToBlit(IShowable* obj);	
-	void showInfoDialog(std::string &text, std::vector<SComponent*> & components);
-	void showYesNoDialog(std::string &text, std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
+	void removeObjToBlit(IShowable* obj);
+	void showInfoDialog(std::string &text, const std::vector<SComponent*> & components);
+	void showYesNoDialog(std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
 
 	CPlayerInterface(int Player, int serial);//c-tor
 	~CPlayerInterface();//d-tor
@@ -565,7 +565,7 @@ public:
 	std::vector<CSelectableComponent *> comps; //skills to select
 	AdventureMapButton *ok;
 	boost::function<void(ui32)> cb;
-	
+
 	void close();
 	CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
 	~CLevelWindow();
@@ -586,4 +586,4 @@ public:
 
 extern CPlayerInterface * LOCPLINT;
 
-#endif //CPLAYERINTERFACE_H
+#endif //CPLAYERINTERFACE_H

+ 13 - 2
client/Client.cpp

@@ -323,10 +323,21 @@ void CClient::process(int what)
 		{
 			NewStructures ns;
 			*serv >> ns;
-			std::cout << "New structure(s) in " << ns.tid << " - " << *ns.bid.begin() << std::endl;
+			CGTownInstance *town = static_cast<CGTownInstance*>(gs->map->objects[ns.tid]);
+			std::cout << "New structure(s) in " << ns.tid <<" " << town->name << " - " << *ns.bid.begin() << std::endl;
 			gs->apply(&ns);
 			BOOST_FOREACH(si32 bid, ns.bid)
-				playerint[gs->map->objects[ns.tid]->tempOwner]->buildChanged(static_cast<CGTownInstance*>(gs->map->objects[ns.tid]),bid,1);
+			{
+				if(bid==13) //for or capitol
+				{
+					town->defInfo = gs->capitols[town->subID];
+				}
+				if(bid ==7)
+				{
+					town->defInfo = gs->forts[town->subID];
+				}
+				playerint[town->tempOwner]->buildChanged(town,bid,1);
+			}
 			break;
 		}
 	case 506:

+ 6 - 6
client/FunctionList.h

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

+ 8 - 0
client/Graphics.cpp

@@ -118,6 +118,14 @@ void Graphics::loadPaletteAndColors()
 		playerColors[i].unused = 0;
 	}
 	neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 0x0;//gray
+
+	std::ifstream bback("config/mageBg.txt");
+	while(!bback.eof())
+	{
+		bback >> pals;
+		guildBgs.push_back(pals);
+	}
+	bback.close();
 }	
 void Graphics::initializeBattleGraphics()
 {

+ 1 - 0
client/Graphics.h

@@ -38,6 +38,7 @@ public:
 	//for battles
 	std::vector< std::vector< std::string > > battleBacks; //battleBacks[terType] - vector of possible names for certain terrain type
 	std::vector< std::string > battleHeroes; //battleHeroes[hero type] - name of def that has hero animation for battle
+	std::vector<std::string> guildBgs;// name of bitmaps with imgs for mage guild screen
 	//functions
 	Graphics();	
 	void initializeBattleGraphics();

+ 4 - 8
client/VCMI_client.vcproj

@@ -362,10 +362,6 @@
 				RelativePath="..\hch\CSndHandler.cpp"
 				>
 			</File>
-			<File
-				RelativePath="..\hch\CSpellHandler.cpp"
-				>
-			</File>
 			<File
 				RelativePath="..\CThreadHelper.cpp"
 				>
@@ -512,10 +508,6 @@
 				RelativePath="..\hch\CSndHandler.h"
 				>
 			</File>
-			<File
-				RelativePath="..\hch\CSpellHandler.h"
-				>
-			</File>
 			<File
 				RelativePath="..\CThreadHelper.h"
 				>
@@ -565,6 +557,10 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath=".\ClassDiagram1.cd"
+			>
+		</File>
 	</Files>
 	<Globals>
 	</Globals>

+ 9 - 0
config/mageLevel.txt

@@ -0,0 +1,9 @@
+4
+5
+5
+5
+5
+5
+3
+3
+5

+ 1 - 0
global.h

@@ -61,6 +61,7 @@ const int NEUTRAL_PLAYER=255;
 const int NAMES_PER_TOWN=16;
 const int CREATURES_PER_TOWN = 7; //without upgrades
 const int MAX_BUILDING_PER_TURN = 1;
+const int SPELL_LEVELS = 5;
 
 #define MARK_BLOCKED_POSITIONS false
 #define MARK_VISITABLE_POSITIONS false

+ 0 - 1
hch/CArtHandler.cpp

@@ -5,7 +5,6 @@
 #include <boost/assign/std/vector.hpp>
 #include <boost/assign/list_of.hpp>
 #include "../lib/VCMI_Lib.h"
-void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
 extern CLodHandler *bitmaph;
 using namespace boost::assign;
 CArtHandler::CArtHandler()

+ 15 - 0
hch/CObjectHandler.cpp

@@ -271,6 +271,20 @@ int CGTownInstance::hallLevel() const // -1 - none, 0 - village, 1 - town, 2 - c
 		return 0;
 	return -1;
 }
+int CGTownInstance::mageGuildLevel() const
+{
+	if ((builtBuildings.find(4))!=builtBuildings.end())
+		return 5;
+	if ((builtBuildings.find(3))!=builtBuildings.end())
+		return 4;
+	if ((builtBuildings.find(2))!=builtBuildings.end())
+		return 3;
+	if ((builtBuildings.find(1))!=builtBuildings.end())
+		return 2;
+	if ((builtBuildings.find(0))!=builtBuildings.end())
+		return 1;
+	return 0;
+}
 bool CGTownInstance::creatureDwelling(const int & level, bool upgraded) const
 {
 	return builtBuildings.find(30+level+upgraded*7)!=builtBuildings.end();
@@ -349,6 +363,7 @@ CGObjectInstance::~CGObjectInstance()
 }
 CGHeroInstance::CGHeroInstance()
 {
+	inTownGarrison = false;
 	portrait = level = exp = -1;
 	isStanding = true;
 	moveDir = 4;

+ 3 - 1
hch/CObjectHandler.h

@@ -141,7 +141,8 @@ public:
 	int identifier; //special identifier from h3m (only > RoE maps)
 	int alignment;
 	std::set<si32> forbiddenBuildings, builtBuildings;
-	std::vector<int> possibleSpells, obligatorySpells, availableSpells;
+	std::vector<int> possibleSpells, obligatorySpells;
+	std::vector<std::vector<ui32> > spells; //spells[level] -> vector of spells, first will be available in guild
 
 	struct StrInfo
 	{
@@ -158,6 +159,7 @@ public:
 	int getSightDistance() const; //returns sight distance
 	int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle
 	int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
+	int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
 	bool creatureDwelling(const int & level, bool upgraded=false) const;
 	int getHordeLevel(const int & HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
 	int creatureGrowth(const int & level) const;

+ 44 - 333
hch/CSpellHandler.cpp

@@ -1,359 +1,70 @@
-  #include "../stdafx.h"
+#define VCMI_DLL
+#include "../stdafx.h"
 #include "CSpellHandler.h"
-#include "../CGameInfo.h"
 #include "CLodHandler.h"
-
+#include "../lib/VCMI_Lib.h"
+#include <boost/algorithm/string/replace.hpp>
+extern CLodHandler *bitmaph;
 void CSpellHandler::loadSpells()
 {
-	std::string buf = CGI->bitmaph->getTextFile("SPTRAITS.TXT");
-	int andame = buf.size();
-	int i=0; //buf iterator
-	int hmcr=0;
-	for(i; i<andame; ++i)
-	{
-		if(buf[i]=='\r')
-			++hmcr;
-		if(hmcr==5)
-			break;
-	}
-	i+=2;
+	std::string buf = bitmaph->getTextFile("SPTRAITS.TXT"), pom;
+	int andame = buf.size(), i=0; //buf iterator
+	for(int z=0; z<5; ++z)
+		loadToIt(pom,buf,i,3);
+
 	bool combSpells=false; //true, if we are reading combat spells
 	while(i<andame)
 	{
 		if(spells.size()==81)
 			break;
 		CSpell nsp; //new currently being read spell
-		int befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.name = buf.substr(befi, i-befi);
-		++i;
 
+		loadToIt(nsp.name,buf,i,4);
 		if(nsp.name == std::string(""))
 		{
-			combSpells = true;
-			int hmcr=0;
-			for(i; i<andame; ++i)
-			{
-				if(buf[i]=='\r')
-					++hmcr;
-				if(hmcr==3)
-					break;
-			}
-			++i;
-			++i;
-			befi=i;
-			for(i; i<andame; ++i)
-			{
-				if(buf[i]=='\t')
-					break;
-			}
-			nsp.name = buf.substr(befi, i-befi);
-			++i;
+			for(int z=0; z<3; ++z)
+				loadToIt(pom,buf,i,3);
+			loadToIt(nsp.name,buf,i,4);
 		}
 
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.abbName = buf.substr(befi, i-befi);
-		++i;
+		loadToIt(nsp.abbName,buf,i,4);
+		loadToIt(nsp.level,buf,i,4);
 
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.level = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
+		loadToIt(pom,buf,i,4);
+		nsp.earth = pom[0]=='x' ? true : false;
+		loadToIt(pom,buf,i,4);
+		nsp.water = pom[0]=='x' ? true : false;
+		loadToIt(pom,buf,i,4);
+		nsp.fire = pom[0]=='x' ? true : false;
+		loadToIt(pom,buf,i,4);
+		nsp.air = pom[0]=='x' ? true : false;
 
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.earth = buf.substr(befi, i-befi)[0]=='x' ? true : false;
-		++i;
+		nsp.costs.resize(4);
+		for (int z = 0; z < 4 ; z++)
+			loadToIt(nsp.costs[z],buf,i,4);
+		loadToIt(nsp.power,buf,i,4);
+		nsp.powers.resize(4);
+		for (int z = 0; z < 4 ; z++)
+			loadToIt(nsp.powers[z],buf,i,4);
 
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.water = buf.substr(befi, i-befi)[0]=='x' ? true : false;
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.fire = buf.substr(befi, i-befi)[0]=='x' ? true : false;
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.air = buf.substr(befi, i-befi)[0]=='x' ? true : false;
-		++i;
+		nsp.probabilities.resize(9);
+		for (int z = 0; z < 9 ; z++)
+			loadToIt(nsp.probabilities[z],buf,i,4);
 
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.costNone = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
+		nsp.AIVals.resize(4);
+		for (int z = 0; z < 4 ; z++)
+			loadToIt(nsp.AIVals[z],buf,i,4);
 
-		befi=i;
-		for(i; i<andame; ++i)
+		nsp.descriptions.resize(4);
+		for (int z = 0; z < 4 ; z++)
 		{
-			if(buf[i]=='\t')
-				break;
+			loadToIt(nsp.descriptions[z],buf,i,4);
+			boost::algorithm::replace_all(nsp.descriptions[z],"\"","");
 		}
-		nsp.costBas = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
 
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.costAdv = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.costExp = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.power = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.powerNone = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.powerBas = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.powerAdv = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.powerExp = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.castle = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.rampart = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.tower = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.inferno = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.necropolis = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.dungeon = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.stronghold = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.fortress = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.conflux = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.none2 = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.bas2 = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.adv2 = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.exp2 = atoi(buf.substr(befi, i-befi).c_str());
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.noneTip = buf.substr(befi, i-befi).c_str();
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.basTip = buf.substr(befi, i-befi).c_str();
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.advTip = buf.substr(befi, i-befi).c_str();
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\t')
-				break;
-		}
-		nsp.expTip = buf.substr(befi, i-befi).c_str();
-		++i;
-
-		befi=i;
-		for(i; i<andame; ++i)
-		{
-			if(buf[i]=='\r')
-				break;
-		}
-		nsp.attributes = buf.substr(befi, i-befi).c_str();
-		++i;
-		++i;
-		
+		loadToIt(nsp.attributes,buf,i,3);
+		nsp.id = spells.size();
 		nsp.combatSpell = combSpells;
 		spells.push_back(nsp);
 	}
-}
+}

+ 9 - 15
hch/CSpellHandler.h

@@ -7,31 +7,25 @@
 class CSpell
 {
 public:
-	bool isAllowed; //true if we can use this spell (depends on map)
+	ui32 id;
 	std::string name;
 	std::string abbName; //abbreviated name
-	int level;
+	si32 level;
 	bool earth;
 	bool water;
 	bool fire;
 	bool air;
-	int costNone;
-	int costBas;
-	int costAdv;
-	int costExp;
-	int power; //spell's power
-	int powerNone; //effect without magic ability
-	int powerBas; //efect with basic magic ability
-	int powerAdv; //efect with advanced magic ability
-	int powerExp; //efect with expert magic ability
-	int castle, rampart, tower, inferno, necropolis, dungeon, stronghold, fortress, conflux; //% chance to gain
-	int none2, bas2, adv2, exp2; //AI values
-	std::string noneTip, basTip, advTip, expTip; //descriptions of spell
+	si32 power; //spell's power
+	std::vector<si32> costs; //per skill level: 0 - none, 1 - basic, etc
+	std::vector<si32> powers; //[er skill level: 0 - none, 1 - basic, etc
+	std::vector<si32> probabilities; //% chance to gain for castles 
+	std::vector<si32> AIVals; //AI values: per skill level: 0 - none, 1 - basic, etc
+	std::vector<std::string> descriptions; //descriptions of spell for skill levels: 0 - none, 1 - basic, etc
 	std::string attributes; //reference only attributes
 	bool combatSpell; //is this spell combat (true) or adventure (false)
 };
 
-class CSpellHandler
+class DLL_EXPORT CSpellHandler
 {
 public:
 	std::vector<CSpell> spells;

+ 9 - 0
hch/CTownHandler.cpp

@@ -248,6 +248,15 @@ void CTownHandler::loadNames()
 		of.close();
 		of.clear();
 
+		itr=0;
+		of.open("config/mageLevel.txt");
+		while(!of.eof())
+		{
+			of >> towns[itr++].mageLevel;
+		}
+		of.close();
+		of.clear();
+
 		of.open("config/requirements.txt");
 		while(!of.eof())
 		{

+ 1 - 0
hch/CTownHandler.h

@@ -14,6 +14,7 @@ public:
 	std::vector<int> basicCreatures; //level (from 0) -> ID
 	std::vector<int> upgradedCreatures; //level (from 0) -> ID
 	std::map<int,int> hordeLvl; //[0] - first horde building creature level; [1] - second horde building (-1 if not present)
+	ui32 mageLevel; //max available mage guild level
 	int bonus; //pic number
 	int typeID;
 };

+ 1 - 0
lib/Connection.h

@@ -7,6 +7,7 @@
 #include <boost/type_traits/is_fundamental.hpp>
 #include <boost/type_traits/is_enum.hpp>
 #include <boost/type_traits/is_pointer.hpp> 
+#include <boost/type_traits/is_class.hpp> 
 #include  <boost/type_traits/remove_pointer.hpp>
 
 #include <boost/mpl/eval_if.hpp>

+ 13 - 0
lib/VCMI_Lib.cpp

@@ -8,6 +8,7 @@
 #include "../hch/CObjectHandler.h"
 #include "../hch/CTownHandler.h"
 #include "../hch/CBuildingHandler.h"
+#include "../hch/CSpellHandler.h"
 class CLodHandler;
 LibClasses * VLC = NULL;
 CLodHandler * bitmaph=NULL;
@@ -50,6 +51,11 @@ DLL_EXPORT void initDLL(CLodHandler *b)
 	VLC->buildh = new CBuildingHandler;
 	VLC->buildh->loadBuildings();
 	THC std::cout<<"\tBuilding handler: "<<pomtime.getDif()<<std::endl;
+
+	CSpellHandler * spellh = new CSpellHandler;
+	spellh->loadSpells();
+	VLC->spellh = spellh;		
+	THC std::cout<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
 }
 
 DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode)
@@ -159,3 +165,10 @@ DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mod
 	}
 }
 
+
+DLL_EXPORT void loadToIt(si32 &dest, std::string &src, int &iter, int mode)
+{
+	std::string pom;
+	loadToIt(pom,src,iter,mode);
+	dest = atol(pom.c_str());
+}

+ 4 - 20
lib/VCMI_Lib.h

@@ -3,13 +3,11 @@
 #include "../global.h"
 
 class CLodHandler;
-//class CMapHandler;
 class CArtHandler;
 class CHeroHandler;
 class CCreatureHandler;
 //class CAbilityHandler;
-//class CSpellHandler;
-//class CAmbarCendamo;
+class CSpellHandler;
 //class CPreGameTextHandler;
 class CBuildingHandler;
 class CObjectHandler;
@@ -20,13 +18,7 @@ class CTownHandler;
 //class CGeneralTextHandler;
 //class CConsoleHandler;
 //class CPathfinder;
-//class CCursorHandler;
-//class CScreenHandler;
 //class CGameState;
-//class CMapHandler;
-//class CGameInterface;
-//class CPreGame;
-//class CDefHandler;
 
 class LibClasses
 {
@@ -36,29 +28,21 @@ public:
 	CHeroHandler * heroh;
 	CCreatureHandler * creh;
 	//CAbilityHandler * abilh;
-	//CSpellHandler * spellh;
-	//CMapHandler * mh;
+	CSpellHandler * spellh;
 	//CPreGameTextHandler * preth;
 	CBuildingHandler * buildh;
 	CObjectHandler * objh;
-	//CMusicHandler * mush;
-	//CSemiLodHandler * sspriteh;
 	CDefObjInfoHandler * dobjinfo;
 	CTownHandler * townh;
 	//CGeneralTextHandler * generaltexth;
 	//CConsoleHandler * consoleh;
 	//CPathfinder * pathf;
-	//CCursorHandler * curh;
-	//CScreenHandler * screenh;
-	//int localPlayer;
-	//std::vector<CGameInterface *> playerint;
-	//std::vector<SDL_Color> playerColors;
-	//SDL_Color neutralColor;
-	//StartInfo scenarioOps;
 };
 
 extern DLL_EXPORT LibClasses * VLC;
 
+DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
+DLL_EXPORT void loadToIt(si32 &dest, std::string &src, int &iter, int mode);
 
 DLL_EXPORT void initDLL(CLodHandler *b);
 

+ 8 - 0
lib/VCMI_lib.vcproj

@@ -294,6 +294,10 @@
 				RelativePath=".\Connection.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\hch\CSpellHandler.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\hch\CTownHandler.cpp"
 				>
@@ -360,6 +364,10 @@
 				RelativePath=".\Connection.h"
 				>
 			</File>
+			<File
+				RelativePath="..\hch\CSpellHandler.h"
+				>
+			</File>
 			<File
 				RelativePath="..\hch\CTownHandler.h"
 				>

+ 1 - 1
map.cpp

@@ -900,7 +900,7 @@ void Mapa::loadTown( CGObjectInstance * &nobj, unsigned char * bufor, int &i )
 		{
 			for(int bit=0;bit<8;bit++)
 				if(bufor[i] & (1<<bit))
-					nt->forbiddenBuildings.insert(byte*8+bit);
+					nt->forbiddenBuildings.insert((byte-6)*8+bit);
 			i++;
 		}
 		nt->builtBuildings = convertBuildings(nt->builtBuildings,nt->subID);

+ 3 - 6
mapHandler.cpp

@@ -413,9 +413,8 @@ void CMapHandler::initObjectRects()
 	//initializing objects / rects
 	for(int f=0; f<map->objects.size(); ++f)
 	{
-		/*map->objects[f]->pos.x+=1;
-		map->objects[f]->pos.y+=1;*/
-		if(!map->objects[f]->defInfo)
+		if((map->objects[f]->ID==34 && static_cast<CGHeroInstance*>(map->objects[f])->inTownGarrison)
+			|| !map->objects[f]->defInfo)
 		{
 			continue;
 		}
@@ -489,7 +488,7 @@ void processDef (CGDefInfo* def)
 	def->width = def->handler->ourImages[0].bitmap->w/32;
 	def->height = def->handler->ourImages[0].bitmap->h/32;
 	CGDefInfo* pom = CGI->dobjinfo->gobjs[def->id][def->subid];
-	if(pom)
+	if(pom && def->id!=98)
 	{
 		pom->handler = def->handler;
 		pom->width = pom->handler->ourImages[0].bitmap->w/32;
@@ -566,8 +565,6 @@ void CMapHandler::init()
 	std::cout<<"\tPreparing FoW, roads, rivers,borders: "<<th.getDif()<<std::endl;
 	initObjectRects();
 	std::cout<<"\tMaking object rects: "<<th.getDif()<<std::endl;
-	calculateBlockedPos();
-	std::cout<<"\tCalculating blockmap: "<<th.getDif()<<std::endl;
 }
 
 SDL_Surface * CMapHandler::terrainRect(int x, int y, int dx, int dy, int level, unsigned char anim, std::vector< std::vector< std::vector<unsigned char> > > * visibilityMap, bool otherHeroAnim, unsigned char heroAnim, SDL_Surface * extSurf, SDL_Rect * extRect)

+ 1 - 1
nodrze.h

@@ -189,7 +189,7 @@ template <typename T> void nodrze<T>::wypiszObficie(std::ostream & strum)
 template <typename T, class X> T* operator%(nodrze<T> & drzewko, X co)
 {
 	CLOG ("Szukam " <<co <<std::endl);
-#if !defined(__amigaos4__) && !defined(__unix__)
+#ifdef _MSC_VER
 	drzewko.wypiszObficie(*C->gl->loguj);
 #endif
 	wezel<T> * w = drzewko.korzen;

+ 1 - 2
server/CGameHandler.cpp

@@ -168,7 +168,6 @@ void CGameHandler::changeSecSkill(int ID, ui16 which, int val, bool abs)
 	sps.val = val;
 	sendAndApply(&sps);
 }
-
 void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 {
 	SetPrimSkill sps;
@@ -677,7 +676,7 @@ upgend:
 						CCreatureSet csn = town->visitingHero->army, cso = town->army;
 						while(!cso.slots.empty())//while there are unmoved creatures
 						{
-							int pos = csn.getSlotFor(cso.slots.begin()->first);
+							int pos = csn.getSlotFor(cso.slots.begin()->second.first);
 							if(pos<0)
 								goto handleConEnd;
 							if(csn.slots.find(pos)!=csn.slots.end()) //add creatures to the existing stack

+ 1 - 1
server/CScriptCallback.cpp

@@ -73,7 +73,7 @@ void CScriptCallback::showInfoDialog(InfoWindow *iw)
 	gh->sendToAllClients(iw);
 }
 
-void CScriptCallback::showSelectionDialog(SelectionDialog *iw, boost::function<void(ui32),std::allocator<void> > &callback)
+void CScriptCallback::showSelectionDialog(SelectionDialog *iw, boost::function<void(ui32)> &callback)
 {
 	gh->ask(iw,iw->player,callback);
 }

+ 1 - 1
server/CScriptCallback.h

@@ -41,7 +41,7 @@ public:
 	void setHoverName(int objid, MetaString * name);
 	void changePrimSkill(int ID, int which, int val, bool abs=false);
 	void showInfoDialog(InfoWindow *iw);
-	void showSelectionDialog(SelectionDialog *iw, boost::function<void(ui32),std::allocator<void> > &callback); //returns question id
+	void showSelectionDialog(SelectionDialog *iw, boost::function<void(ui32)> &callback); //returns question id
 	void giveResource(int player, int which, int val);
 	void showCompInfo(ShowInInfobox * comp);
 	void heroVisitCastle(int obj, int heroID);