Browse Source

* fixed crashbug on loading maps with events giving creatures
* added confirmation window when hero is dismissed
* finished mage guild screen
* fixed some crashbugs with hero window on adventure interface
* fixed giving wrong war machines on start
* added blacksmith functionality

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

+ 12 - 6
AdventureMapButton.cpp

@@ -14,7 +14,7 @@ AdventureMapButton::AdventureMapButton ()
 	active=false;
 	ourObj=NULL;
 	state=0;
-	actOnDown = false;
+	blocked = actOnDown = false;
 }
 //AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ,  std::vector<std::string> * add, bool playerColoredButton)
 //{
@@ -28,14 +28,12 @@ AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, C
 
 void AdventureMapButton::clickLeft (tribool down)
 {
+	if(blocked)
+		return;
 	if (down)
-	{
 		state=1;
-	}
 	else
-	{
 		state=0;
-	}
 	show();
 	if (actOnDown && down)
 	{
@@ -101,7 +99,7 @@ void AdventureMapButton::deactivate()
 void AdventureMapButton::init( CFunctionList<void()> Callback, std::string Name, std::string HelpBox, bool playerColoredButton, std::string defName, std::vector<std::string> * add, int x, int y, bool activ )
 {
 	callback = Callback;
-	actOnDown = false;
+	blocked = actOnDown = false;
 	type=2;
 	abs=true;
 	active=false;
@@ -146,6 +144,14 @@ void AdventureMapButton::init( CFunctionList<void()> Callback, std::string Name,
 		activate();
 }
 
+void AdventureMapButton::block( bool on )
+{
+	blocked = on;
+	state = 0;
+	bitmapOffset = on ? 2 : 0;
+	show();
+}
+
 void CSlider::sliderClicked()
 {
 	if(!moving)

+ 2 - 1
AdventureMapButton.h

@@ -10,12 +10,13 @@ public:
 	std::string helpBox; //for right-click help
 	char key; //key shortcut
 	CFunctionList<void()> callback;
-	bool colorChange,
+	bool colorChange, blocked,
 		actOnDown; //runs when mouse is pressed down over it, not when up
 
 	void clickRight (tribool down);
 	void clickLeft (tribool down);
 	virtual void hover (bool on);
+	virtual void block(bool on); //if button is blocked then it'll change it's graphic to inactive (offset==2) and won't react on l-clicks
 	void keyPressed (SDL_KeyboardEvent & key);
 	void activate(); // makes button active
 	void deactivate(); // makes button inactive (but doesn't delete)

+ 10 - 0
CAdvmapInterface.cpp

@@ -957,6 +957,11 @@ void CAdvMapInt::fendTurn()
 
 void CAdvMapInt::activate()
 {
+	if(subInt == heroWindow)
+	{
+		heroWindow->activate();
+		return;
+	}
 	LOCPLINT->curint = this;
 	LOCPLINT->statusbar = &statusbar;
 	kingOverview.activate();
@@ -978,6 +983,11 @@ void CAdvMapInt::activate()
 }
 void CAdvMapInt::deactivate()
 {
+	if(subInt == heroWindow)
+	{
+		heroWindow->deactivate();
+		return;
+	}
 	hide();
 }
 void CAdvMapInt::show(SDL_Surface *to)

+ 9 - 5
CCallback.cpp

@@ -175,16 +175,16 @@ int CCallback::howManyHeroes()
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[player].heroes.size();
 }
-const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
+const CGHeroInstance * CCallback::getHeroInfo(int val, int mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
 {
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info
-		return NULL;
-	if (!mode)
+	//if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info
+	//	return NULL;
+	if (!mode) //esrial id
 		if(val<gs->players[player].heroes.size())
 			return gs->players[player].heroes[val];
 		else return NULL;
-	else 
+	else if(mode==1) //it's hero type id
 	{
 		for (int i=0; i<gs->players[player].heroes.size();i++)
 		{
@@ -192,6 +192,10 @@ const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) //
 				return gs->players[player].heroes[i];
 		}
 	}
+	else //object id
+	{
+		return static_cast<CGHeroInstance*>(gs->map->objects[val]);
+	}
 	return NULL;
 }
 

+ 2 - 2
CCallback.h

@@ -46,7 +46,7 @@ public:
 	virtual bool verifyPath(CPath * path, bool blockSea)=0;
 	virtual int getDate(int mode=0)=0; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 	virtual std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap()=0; //returns visibility map (TODO: make it const)
-	virtual const CGHeroInstance * getHeroInfo(int player, int val, bool mode)=0; //mode = 0 -> val = serial; mode = 1 -> val = ID
+	virtual const CGHeroInstance * getHeroInfo(int val, int mode=2)=0; //mode = 0 -> val = serial; mode = 1 -> val = ID
 	virtual int getResourceAmount(int type)=0;
 	virtual int howManyHeroes()=0;
 	virtual const CGTownInstance * getTownInfo(int val, bool mode)=0; //mode = 0 -> val = serial; mode = 1 -> val = ID
@@ -120,7 +120,7 @@ public:
 	bool verifyPath(CPath * path, bool blockSea);
 	int getDate(int mode=0); //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 	std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap(); //returns visibility map (TODO: make it const)
-	const CGHeroInstance * getHeroInfo(int player, int val, bool mode); //mode = 0 -> val = serial; mode = 1 -> val = ID
+	const CGHeroInstance * getHeroInfo(int val, int mode=2); //mode = 0 -> val = serial; mode = 1 -> val = ID
 	int getResourceAmount(int type);
 	std::vector<si32> getResourceAmount();
 	int howManyHeroes();

+ 103 - 1
CCastleInterface.cpp

@@ -9,6 +9,7 @@
 #include "SDL_Extensions.h"
 #include "client/CCreatureAnimation.h"
 #include "client/Graphics.h"
+#include "hch/CArtHandler.h"
 #include "hch/CBuildingHandler.h"
 #include "hch/CDefHandler.h"
 #include "hch/CGeneralTextHandler.h"
@@ -269,6 +270,7 @@ void CHeroGSlot::activate()
 }
 void CHeroGSlot::deactivate()
 {
+	highlight = false;
 	ClickableL::deactivate();
 	ClickableR::deactivate();
 	Hoverable::deactivate();
@@ -513,6 +515,25 @@ void CCastleInterface::buildingClicked(int building)
 		case 10: case 11: case 12: case 13:
 			enterHall();
 			break;
+		case 16:
+			{
+				const CGHeroInstance *hero = town->visitingHero;
+				if(!hero)
+				{
+					std::string pom = CGI->generaltexth->allTexts[273];
+					boost::algorithm::replace_first(pom,"%s",CGI->buildh->buildings[town->subID][16]->name);
+					LOCPLINT->showInfoDialog(pom,std::vector<SComponent*>());
+					return;
+				}
+				int aid = town->town->warMachine;
+				int price = CGI->arth->artifacts[aid].price;
+				bool possible = (LOCPLINT->cb->getResourceAmount(6) >= price);
+				if(vstd::contains(hero->artifWorn,ui16(aid+9))) //hero already has machine
+					possible = false;
+				deactivate();
+				(new CBlacksmithDialog(possible,142+aid,aid,hero->id))->activate();
+				break;
+			}
 		default:
 			std::cout<<"This building isn't handled...\n";
 		}
@@ -1441,6 +1462,7 @@ void CMageGuildScreen::show(SDL_Surface * to)
 {
 	blitAt(bg,0,0);
 	resdatabar.show();
+	LOCPLINT->statusbar->show();
 	exit->show();
 }
 void CMageGuildScreen::activate()
@@ -1460,7 +1482,14 @@ void CMageGuildScreen::deactivate()
 }
 void CMageGuildScreen::Scroll::clickLeft (tribool down)
 {
-
+	if(down)
+	{
+		std::vector<SComponent*> comps(1,
+			new CCustomImgComponent(SComponent::spell,spell->id,0,
+			  static_cast<CMageGuildScreen*>(LOCPLINT->castleInt->subInt)->scrolls->ourImages[spell->id].bitmap,false)
+		);
+		LOCPLINT->showInfoDialog(spell->descriptions[0],comps);
+	}
 }
 void CMageGuildScreen::Scroll::clickRight (tribool down)
 {
@@ -1480,6 +1509,11 @@ void CMageGuildScreen::Scroll::clickRight (tribool down)
 }
 void CMageGuildScreen::Scroll::hover(bool on)
 {
+	Hoverable::hover(on);
+	if(on)
+		LOCPLINT->statusbar->print(spell->name);
+	else
+		LOCPLINT->statusbar->clear();
 
 }
 void CMageGuildScreen::Scroll::activate()
@@ -1493,4 +1527,72 @@ void CMageGuildScreen::Scroll::deactivate()
 	ClickableL::deactivate();
 	ClickableR::deactivate();
 	Hoverable::deactivate();
+}
+
+CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, int hid)
+{
+	SDL_Surface *bg2 = BitmapHandler::loadBitmap("TPSMITH.bmp");
+	SDL_SetColorKey(bg2,SDL_SRCCOLORKEY,SDL_MapRGB(bg2->format,0,255,255));
+	graphics->blueToPlayersAdv(bg2,LOCPLINT->playerID);
+	bmp = SDL_ConvertSurface(bg2,screen->format,0); 
+	SDL_FreeSurface(bg2);
+	bg2 = BitmapHandler::loadBitmap("TPSMITBK.bmp");
+	blitAt(bg2,64,50,bmp);
+	SDL_FreeSurface(bg2);
+	CCreatureAnimation cra(CGI->creh->creatures[creMachineID].animDefName);
+	cra.nextFrameMiddle(bmp,165,130,true,false);
+	char pom[75];
+	sprintf(pom,CGI->generaltexth->allTexts[274].c_str(),CGI->creh->creatures[creMachineID].nameSing.c_str()); //build a new ...
+	printAtMiddle(pom,165,28,GEORXX,tytulowy,bmp);
+	printAtMiddle(CGI->generaltexth->jktexts[43],165,218,GEOR16,zwykly,bmp); //resource cost
+	SDL_itoa(CGI->arth->artifacts[aid].price,pom,10);
+	printAtMiddle(pom,165,290,GEOR13,zwykly,bmp);
+	pos.w = bmp->w;
+	pos.h = bmp->h;
+	pos.x = screen->w/2 - pos.w/2;
+	pos.y = screen->h/2 - pos.h/2;
+	buy = new AdventureMapButton("","",boost::bind(&CBlacksmithDialog::close,this),pos.x + 42,pos.y + 312,"IBUY30.DEF");
+	cancel = new AdventureMapButton("","",boost::bind(&CBlacksmithDialog::close,this),pos.x + 224,pos.y + 312,"ICANCEL.DEF");
+	if(possible)
+		buy->callback += boost::bind(&CCallback::buyArtifact,LOCPLINT->cb,LOCPLINT->cb->getHeroInfo(hid,2),aid);
+	else
+		buy->bitmapOffset = 2;
+	blitAt(graphics->resources32->ourImages[6].bitmap,148,244,bmp);
+}
+
+void CBlacksmithDialog::show( SDL_Surface * to/*=NULL*/ )
+{
+	blitAt(bmp,pos);
+	buy->show();
+	cancel->show();
+}
+
+void CBlacksmithDialog::activate()
+{
+	LOCPLINT->objsToBlit += this;
+	if(!buy->bitmapOffset)
+		buy->activate();
+	cancel->activate();
+}
+
+void CBlacksmithDialog::deactivate()
+{
+	LOCPLINT->objsToBlit -= this;
+	if(!buy->bitmapOffset)
+		buy->deactivate();
+	cancel->deactivate();
+}
+
+CBlacksmithDialog::~CBlacksmithDialog()
+{
+	SDL_FreeSurface(bmp);
+	delete cancel;
+	delete buy;
+}
+
+void CBlacksmithDialog::close()
+{
+	deactivate();
+	delete this;
+	LOCPLINT->curint->activate();
 }

+ 14 - 0
CCastleInterface.h

@@ -203,4 +203,18 @@ public:
 	void show(SDL_Surface * to=NULL);
 	void activate();
 	void deactivate();
+};
+
+class CBlacksmithDialog : public IShowable, public CIntObject
+{
+public:
+	AdventureMapButton *buy, *cancel;
+	SDL_Surface *bmp;
+
+	CBlacksmithDialog(bool possible, int creMachineID, int aid, int hid);
+	~CBlacksmithDialog();
+	void close();
+	void show(SDL_Surface * to=NULL);
+	void activate();
+	void deactivate();
 };

+ 5 - 7
CGameState.cpp

@@ -866,7 +866,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 	}
 	//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
 
-	//giving starting hero
+	/*********give starting hero****************************************/
 	for(int i=0;i<PLAYER_LIMIT;i++)
 	{
 		if((map->players[i].generateHeroAtMainTown && map->players[i].hasMainTown) ||  (map->players[i].hasMainTown && map->version==RoE))
@@ -893,12 +893,10 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 					break;
 				}
 			}
-			//nnn->defInfo->handler = graphics->flags1[0];
 			map->heroes.push_back(nnn);
 			map->objects.push_back(nnn);
 		}
 	}
-	//std::cout<<"\tGiving starting heroes: "<<th.getDif()<<std::endl;
 
 	/*********creating players entries in gs****************************************/
 	for (int i=0; i<scenarioOps->playerInfos.size();i++)
@@ -909,7 +907,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 		players.insert(ins);
 	}
 	/******************RESOURCES****************************************************/
-	//TODO: zeby komputer dostawal inaczej niz gracz 
+	//TODO: computer player should receive other amount of resource than computer (depending on difficulty)
 	std::vector<int> startres;
 	std::ifstream tis("config/startres.txt");
 	int k;
@@ -988,7 +986,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 						break;
 					default:
 						pom-=145;
-						vhi->artifWorn[13+pom] = 4+pom;
+						vhi->artifWorn[12+pom] = 3+pom;
 						break;
 					}
 					continue;
@@ -1057,7 +1055,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			}
 		case bartifact:
 			{
-				if(!k->second.heroes[0])
+				if(!k->second.heroes.size())
 				{
 					std::cout << "Cannot give starting artifact - no heroes!" << std::endl;
 					break;
@@ -1065,7 +1063,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 				CArtifact *toGive;
 				do 
 				{
-					toGive = VLC->arth->minors[ran() % VLC->arth->minors.size()];
+					toGive = VLC->arth->treasures[ran() % VLC->arth->treasures.size()];
 				} while (!map->allowedArtifact[toGive->id]);
 				CGHeroInstance *hero = k->second.heroes[0];
 				std::vector<ui16>::iterator slot = vstd::findFirstNot(hero->artifWorn,toGive->possibleSlots);

+ 5 - 7
CHeroWindow.cpp

@@ -301,8 +301,6 @@ void CHeroWindow::quit()
 	LOCPLINT->curint->subInt = NULL;
 	LOCPLINT->objsToBlit -= this;
 
-	deactivate();
-
 	if(LOCPLINT->curint == LOCPLINT->castleInt)
 		LOCPLINT->castleInt->subInt = NULL;
 	LOCPLINT->curint->activate();
@@ -415,9 +413,9 @@ void CHeroWindow::deactivate()
 
 void CHeroWindow::dismissCurrent()
 {
-	const CGHeroInstance * ch = curHero;
-	quit();
-	LOCPLINT->cb->dismissHero(ch);
+	CFunctionList<void()> ony = boost::bind(&CHeroWindow::quit,this);
+	ony += boost::bind(&CCallback::dismissHero,LOCPLINT->cb,curHero);
+	LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22],std::vector<SComponent*>(), ony, boost::bind(&CHeroWindow::activate,this), true, false);
 }
 
 void CHeroWindow::questlog()
@@ -567,7 +565,7 @@ void CHeroWindow::redrawCurBack()
 	//hero list blitting
 	for(int g=0; g<LOCPLINT->cb->howManyHeroes(); ++g)
 	{
-		const CGHeroInstance * cur = LOCPLINT->cb->getHeroInfo(player, g, false);
+		const CGHeroInstance * cur = LOCPLINT->cb->getHeroInfo(g, false);
 		blitAt(graphics->portraitSmall[cur->portrait], 611, 87+g*54, curBack);
 		//printing yellow border
 		if(cur->name == curHero->name)
@@ -848,7 +846,7 @@ void LClickableAreaHero::clickLeft(boost::logic::tribool down)
 	if(!down)
 	{
 		owner->deactivate();
-		const CGHeroInstance * buf = LOCPLINT->cb->getHeroInfo(owner->player, id, false);
+		const CGHeroInstance * buf = LOCPLINT->cb->getHeroInfo(id, false);
 		owner->setHero(buf);
 		owner->redrawCurBack();
 		owner->activate();

+ 5 - 0
CLua.cpp

@@ -718,6 +718,11 @@ std::vector<int> CPickable::yourObjects() //returns IDs of objects which are han
 
 void CTownScript::onHeroVisit(int objid, int heroID)
 {
+
+	if(cb->getOwner(objid)!=cb->getOwner(heroID))
+	{
+		return;
+	}
 	cb->heroVisitCastle(objid,heroID);
 }
 

+ 49 - 26
CPlayerInterface.cpp

@@ -1,39 +1,40 @@
 #include "stdafx.h"
-#include <queue>
-#include "CPlayerInterface.h"
 #include "CAdvmapInterface.h"
+#include "CBattleInterface.h"
+#include "CCallback.h"
+#include "CCastleInterface.h"
+#include "CCursorHandler.h"
+#include "CGameInfo.h"
+#include "CHeroWindow.h"
 #include "CMessage.h"
-#include "mapHandler.h"
+#include "CPathfinder.h"
+#include "CPlayerInterface.h"
 #include "SDL_Extensions.h"
-#include "SDL_framerate.h"
-#include "CCursorHandler.h"
-#include "CCallback.h"
 #include "SDL_Extensions.h"
-#include "hch/CLodHandler.h"
-#include "CPathfinder.h"
-#include <sstream>
-#include "hch/CArtHandler.h"
+#include "SDL_framerate.h"
+#include "SDL_framerate.h"
+#include "client/CCreatureAnimation.h"
+#include "client/Graphics.h"
 #include "hch/CAbilityHandler.h"
+#include "hch/CArtHandler.h"
+#include "hch/CGeneralTextHandler.h"
 #include "hch/CHeroHandler.h"
+#include "hch/CLodHandler.h"
+#include "hch/CObjectHandler.h"
+#include "hch/CPreGameTextHandler.h"
+#include "hch/CSpellHandler.h"
 #include "hch/CTownHandler.h"
-#include "SDL_framerate.h"
-#include "hch/CGeneralTextHandler.h"
-#include "CCastleInterface.h"
-#include "CHeroWindow.h"
+#include "lib/CondSh.h"
+#include "lib/NetPacks.h"
+#include "map.h"
+#include "mapHandler.h"
 #include "timeHandler.h"
-#include <boost/thread.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
-#include "hch/CPreGameTextHandler.h"
-#include "hch/CObjectHandler.h"
-#include "CBattleInterface.h"
-#include "CGameInfo.h"
+#include <boost/thread.hpp>
 #include <cmath>
-#include "client/CCreatureAnimation.h"
-#include "client/Graphics.h"
-#include "map.h"
-#include "lib/NetPacks.h"
-#include "lib/CondSh.h"
+#include <queue>
+#include <sstream>
 using namespace CSDL_Ext;
 
 extern TTF_Font * GEOR16;
@@ -603,6 +604,10 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 		oss << Val;
 		subtitle = oss.str();
 		break;
+	case spell:
+		description = CGI->spellh->spells[Subtype].descriptions[Val];
+		subtitle = CGI->spellh->spells[Subtype].name;
+		break;
 	case experience:
 		description = CGI->generaltexth->allTexts[241];
 		oss << Val ;
@@ -619,7 +624,7 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 	type = Type;
 	subtype = Subtype;
 	val = Val;
-	SDL_Surface * temp = getImg();
+	SDL_Surface * temp = this->getImg();
 	pos.w = temp->w;
 	pos.h = temp->h;
 }
@@ -2259,6 +2264,7 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 	if(curint == castleInt)
 		castleInt->subInt = adventureInt->heroWindow;
 	adventureInt->heroWindow->quitButton->callback.funcs.clear();
+	adventureInt->heroWindow->quitButton->callback += boost::bind(&CHeroWindow::deactivate,adventureInt->heroWindow);
 	adventureInt->heroWindow->quitButton->callback += boost::bind(&CHeroWindow::quit,adventureInt->heroWindow);
 	adventureInt->heroWindow->activate();
 }
@@ -2372,7 +2378,7 @@ void CHeroList::genList()
 	int howMany = LOCPLINT->cb->howManyHeroes();
 	for (int i=0;i<howMany;i++)
 	{
-		const CGHeroInstance * h = LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,i,0);
+		const CGHeroInstance * h = LOCPLINT->cb->getHeroInfo(i,0);
 		if(!h->inTownGarrison)
 			items.push_back(std::pair<const CGHeroInstance *,CPath *>(h,NULL));
 	}
@@ -3472,3 +3478,20 @@ CMinorResDataBar::~CMinorResDataBar()
 {
 	SDL_FreeSurface(bg);
 }
+
+SDL_Surface * CCustomImgComponent::getImg()
+{
+	return bmp;
+}
+
+CCustomImgComponent::CCustomImgComponent( Etype Type, int Subtype, int Val, SDL_Surface *sur, bool freeSur )
+:bmp(sur), free(freeSur)
+{
+	init(Type,Subtype,Val);
+}
+
+CCustomImgComponent::~CCustomImgComponent()
+{
+	if(free)
+		SDL_FreeSurface(bmp);
+}

+ 13 - 1
CPlayerInterface.h

@@ -219,7 +219,7 @@ class SComponent : public ClickableR
 public:
 	enum Etype
 	{
-		primskill, secskill, resource, creature, artifact, experience, secskill44
+		primskill, secskill, resource, creature, artifact, experience, secskill44, spell
 	} type;
 	int subtype;
 	int val;
@@ -230,6 +230,8 @@ public:
 	void init(Etype Type, int Subtype, int Val);
 	SComponent(Etype Type, int Subtype, int Val);
 	SComponent(const Component &c);
+	SComponent(){};
+	virtual ~SComponent(){};
 
 	void clickRight (boost::logic::tribool down);
 	virtual SDL_Surface * getImg();
@@ -238,6 +240,16 @@ public:
 	virtual void deactivate();
 };
 
+class CCustomImgComponent :  public SComponent
+{
+public:
+	bool free; //should surface be freed on delete
+	SDL_Surface *bmp;
+	SDL_Surface * getImg();
+	CCustomImgComponent(Etype Type, int Subtype, int Val, SDL_Surface *sur, bool freeSur);
+	~CCustomImgComponent();
+};
+
 class CSelectableComponent : public SComponent, public ClickableL
 {
 public:

+ 4 - 2
ChangeLog

@@ -1,4 +1,4 @@
-0.61 -> 0.62
+0.61 -> 0.62 (Aug 31 2008 hopefully)
 General:
 * restructured to the server-client model
 * support for heroes placed in towns
@@ -6,6 +6,7 @@ General:
 * working gaining levels for heroes (including dialog with skill selection)
 * added graphical cursor
 * showing creature amount in the creature info window
+* giving starting bonus
 
 Castles:
 * icon in infobox showing that there is hero in town garrison
@@ -15,7 +16,8 @@ Castles:
 * randomizing spells in towns
 * viewing hero window in the town screen
 * possibility of moving hero into the garrison
-* partially done mage guild screen 
+* mage guild screen 
+* support for blacksmith
 * if hero doesn't have a spell book, he can buy one in a mage guild
 
 Adventure Interface:

+ 9 - 9
config/mageLevel.txt

@@ -1,13 +1,13 @@
 9
-4	127
-5	4
-5	5
-5	1
-5	127
-5	3
-3	127
-3	127
-5	1
+4	127	4
+5	4	6
+5	5	5
+5	1	5
+5	127	6
+5	3	4
+3	127	5
+3	127	6
+5	1	4
 
 FORMAT:
 #castles

+ 1 - 1
hch/CObjectHandler.cpp

@@ -397,7 +397,7 @@ CGObjectInstance::~CGObjectInstance()
 }
 CGHeroInstance::CGHeroInstance()
 {
-	inTownGarrison = false;
+	tacticFormationEnabled = inTownGarrison = false;
 	portrait = level = exp = -1;
 	isStanding = true;
 	moveDir = 4;

+ 2 - 2
hch/CObjectHandler.h

@@ -82,7 +82,7 @@ public:
 	mutable int moveDir; //format:	123
 					//		8 4
 					//		765
-	mutable bool isStanding;
+	mutable bool isStanding, tacticFormationEnabled;
 	CHero * type;
 	ui32 exp; //experience point
 	int level; //current level of hero
@@ -109,7 +109,7 @@ public:
 
 	std::vector<ui32> artifacts; //hero's artifacts from bag
 	std::map<ui16,ui32> artifWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
-	std::set<int> spells; //known spells (spell IDs)
+	std::set<ui32> spells; //known spells (spell IDs)
 
 	virtual bool isHero() const;
 	unsigned int getTileCost(const EterrainType & ttype, const Eroad & rdtype, const Eriver & rvtype) const;

+ 1 - 1
hch/CTownHandler.cpp

@@ -252,7 +252,7 @@ void CTownHandler::loadNames()
 		of >> si;
 		for(itr=0; itr<si; itr++)
 		{
-			of >> towns[itr].mageLevel >> towns[itr].primaryRes;
+			of >> towns[itr].mageLevel >> towns[itr].primaryRes >> towns[itr].warMachine;
 		}
 		of.close();
 		of.clear();

+ 1 - 1
hch/CTownHandler.h

@@ -16,7 +16,7 @@ public:
 	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
-	ui16 primaryRes;
+	ui16 primaryRes, warMachine;
 	ui8 typeID;
 };
 

+ 0 - 2
map.cpp

@@ -1819,8 +1819,6 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
 				}
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
 				spec->creatures = readCreatureSet(bufor,i,gcre,(version>RoE));
-				if(version>RoE)
-					i+=gcre;
 				i+=8;
 				spec->availableFor = readNormalNr(bufor,i, 1); ++i;
 				spec->computerActivate = readNormalNr(bufor,i, 1); ++i;

+ 24 - 2
server/CGameHandler.cpp

@@ -10,6 +10,7 @@
 #include "../map.h"
 #include "../lib/NetPacks.h"
 #include "../lib/Connection.h"
+#include "../hch/CArtHandler.h"
 #include "../hch/CObjectHandler.h"
 #include "../hch/CTownHandler.h"
 #include "../hch/CBuildingHandler.h"
@@ -787,8 +788,29 @@ upgend:
 						sha.artifWorn[17] = 0;
 						sendAndApply(&sha);
 					}
-					
-					//TODO: war machines
+					else if(aid < 7  &&  aid > 3) //war machine
+					{
+						int price = VLC->arth->artifacts[aid].price;
+						if(vstd::contains(hero->artifWorn,ui16(9+aid))  //hero already has this machine
+							|| !vstd::contains(town->builtBuildings,si32(16)) //no blackismith
+							|| gs->players[hero->tempOwner].resources[6] < price //no gold
+							|| town->town->warMachine!= aid ) //this machine is not available here (//TODO: support ballista yard in stronghold)
+						{
+							break;
+						}
+						SetResource sr;
+						sr.player = hero->tempOwner;
+						sr.resid = 6;
+						sr.val = gs->players[hero->tempOwner].resources[6] - price;
+						sendAndApply(&sr);
+
+						SetHeroArtifacts sha;
+						sha.hid = hid;
+						sha.artifacts = hero->artifacts;
+						sha.artifWorn = hero->artifWorn;
+						sha.artifWorn[9+aid] = aid;
+						sendAndApply(&sha);
+					}
 					break;
 				}
 			case 2001: