瀏覽代碼

Grail digging and construction.
Minor fixes.

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

+ 3 - 3
AI/GeniusAI/genius.vcproj

@@ -19,7 +19,7 @@
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="$(SolutionDir)\AI"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="2"
 			CharacterSet="1"
 			>
@@ -97,7 +97,7 @@
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="2"
 			CharacterSet="1"
 			WholeProgramOptimization="1"
@@ -177,7 +177,7 @@
 		<Configuration
 			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)\bin\AI"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="2"
 			CharacterSet="1"
 			WholeProgramOptimization="1"

+ 14 - 2
client/CAdvmapInterface.cpp

@@ -1676,7 +1676,8 @@ void CAdvMapInt::activate()
 	terrain.activate();
 	infoBar.activate();
 
-	LOCPLINT->cingconsole->activate();
+	if(!LOCPLINT->cingconsole->active)
+		LOCPLINT->cingconsole->activate();
 	GH.fakeMouseMove(); //to restore the cursor
 }
 void CAdvMapInt::deactivate()
@@ -1701,6 +1702,9 @@ void CAdvMapInt::deactivate()
 	terrain.deactivate();
 	infoBar.deactivate();
 	infoBar.mode=-1;
+
+	if(LOCPLINT->cingconsole->active) //TODO
+		LOCPLINT->cingconsole->deactivate();
 }
 void CAdvMapInt::showAll(SDL_Surface *to)
 {
@@ -2085,8 +2089,16 @@ CAdventureOptions::CAdventureOptions()
 	scenInfo->callback += CAdventureOptions::showScenarioInfo;
 	//viewWorld = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
 
-	puzzle = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 81, "ADVPUZ.DEF");;
+	puzzle = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 81, "ADVPUZ.DEF");
 	puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT);
+
+	const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
+	dig = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 139, "ADVDIG.DEF");
+	if(h)
+		dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h);
+	else
+		dig->block(true);
+
 }
 
 CAdventureOptions::~CAdventureOptions()

+ 18 - 1
client/CCastleInterface.cpp

@@ -555,6 +555,7 @@ void CCastleInterface::buildingClicked(int building)
 	{
 		building = town->town->hordeLvl[1] + 30;
 	}
+
 	if(building >= 30)
 	{
 		showRecruitmentWindow(building);
@@ -613,7 +614,23 @@ void CCastleInterface::buildingClicked(int building)
 				break;
 			}
 		case 10: case 11: case 12: case 13: //hall
-			enterHall();
+			if(town->visitingHero && town->visitingHero->hasArt(2)) //hero has grail
+			{
+				if(!vstd::contains(town->forbiddenBuildings, 26))
+				{
+					LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[597], //Do you wish this to be the permanent home of the Grail?
+												std::vector<SComponent*>(), 
+												boost::bind(&CCallback::buildBuilding, LOCPLINT->cb, town, 26), 
+												boost::bind(&CCastleInterface::enterHall, this), true);
+				}
+				else
+				{
+					LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[673]);
+					(dynamic_cast<CInfoWindow*>(GH.topInt()))->buttons[0]->callback += boost::bind(&CCastleInterface::enterHall, this);
+				}
+			}
+			else
+				enterHall();
 			break;
 		case 14:  //marketplace
 			{

+ 1 - 1
client/CMT.cpp

@@ -96,7 +96,7 @@ void init()
 	tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
 	{
 		//read system options
-		CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin");
+		CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin", false);
 		if(settings.sfile)
 		{
 			settings >> GDefaultOptions;

+ 25 - 2
client/CPlayerInterface.cpp

@@ -163,7 +163,6 @@ void CPlayerInterface::yourTurn()
 		boost::unique_lock<boost::mutex> lock(eventsM); //block handling events until interface is ready
 
 		LOCPLINT = this;
-		makingTurn = true;
 		GH.curInt = this;
 
 		if(firstCall)
@@ -196,6 +195,8 @@ void CPlayerInterface::yourTurn()
 		if(howManyPeople > 1) //hot seat message
 		{
 			adventureInt->startHotSeatWait(playerID);
+
+			makingTurn = true;
 			std::string msg = CGI->generaltexth->allTexts[13];
 			boost::replace_first(msg, "%s", cb->getStartInfo()->playerInfos[serialID].name);
 			std::vector<SComponent*> cmp;
@@ -203,7 +204,10 @@ void CPlayerInterface::yourTurn()
 			showInfoDialog(msg, cmp);
 		}
 		else
+		{
+			makingTurn = true;
 			adventureInt->startTurn();
+		}
 	}
 
 	acceptTurn();
@@ -1708,7 +1712,9 @@ void CPlayerInterface::gameOver(ui8 player, bool victory )
 // 		else
 // 			showInfoDialog("Placeholder message: you won!");
 
-		waitWhileDialog();
+		makingTurn = true;
+		while(showingDialog->get() || dialogs.size()); //wait till all dialogs are displayed and closed
+		makingTurn = false;
 
  		//return to main menu
  		SDL_Event event;
@@ -1872,4 +1878,21 @@ void CPlayerInterface::acceptTurn()
 		adventureInt->select(adventureInt->townList.items[0]);
 
 	adventureInt->showAll(screen);
+}
+
+void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
+{
+	std::string hlp;
+	if(h->movement < h->maxMovePoints(true))
+		showInfoDialog(CGI->generaltexth->allTexts[56]); //"Digging for artifacts requires a whole day, try again tomorrow."
+	else if(cb->getTileInfo(h->getPosition(false))->tertype == TerrainTile::water)
+		showInfoDialog(CGI->generaltexth->allTexts[60]); //Try looking on land!
+	else
+	{
+		CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
+		if(hlp.length())
+			showInfoDialog(CGI->generaltexth->allTexts[97]); //Try searching on clear ground.
+		else
+			cb->dig(h);
+	}
 }

+ 2 - 1
client/CPlayerInterface.h

@@ -216,7 +216,8 @@ public:
 	void finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho ); //finish movement
 	void eraseCurrentPathOf( const CGHeroInstance * ho );
 	CGPath *getAndVerifyPath( const CGHeroInstance * h );
-	void acceptTurn(); //used during hot seat after your turn message is closed
+	void acceptTurn(); //used during hot seat after your turn message is close
+	void tryDiggging(const CGHeroInstance *h);
 
 	CPlayerInterface(int Player, int serial);//c-tor
 	~CPlayerInterface();//d-tor

+ 27 - 15
client/CPreGame.cpp

@@ -71,7 +71,7 @@ static void do_quit()
 
 void CMapInfo::countPlayers()
 {
-	playerAmnt = humenPlayers = 0;
+	actualHumanPlayers = playerAmnt = humenPlayers = 0;
 	for(int i=0;i<PLAYER_LIMIT;i++)
 	{
 		if(mapHeader->players[i].canHumanPlay)
@@ -84,6 +84,11 @@ void CMapInfo::countPlayers()
 			playerAmnt++;
 		}
 	}
+
+	if(scenarioOpts)
+		for (std::vector<PlayerSettings>::const_iterator i = scenarioOpts->playerInfos.begin(); i != scenarioOpts->playerInfos.end(); i++)
+			if(i->human)
+				actualHumanPlayers++;
 }
 
 //CMapInfo::CMapInfo(const std::string &fname, const unsigned char *map )
@@ -93,7 +98,7 @@ void CMapInfo::countPlayers()
 //}
 
 CMapInfo::CMapInfo(bool map)
-: mapHeader(NULL), campaignHeader(NULL)
+: mapHeader(NULL), campaignHeader(NULL), scenarioOpts(NULL)
 {
 }
 
@@ -139,7 +144,7 @@ CMenuScreen::CMenuScreen( EState which )
 	case newGame:
 		{
 			bgAd = new CPicture(BitmapHandler::loadBitmap("ZNEWGAM.bmp"), 114, 312, true);
-			buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, newGame), 545, 4, "ZTSINGL.DEF", SDLK_s);
+			buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, newGame, false), 545, 4, "ZTSINGL.DEF", SDLK_s);
 			buttons[1] = new AdventureMapButton("", CGI->generaltexth->zelp[11].second, &pushIntT<CMultiMode>, 568, 120, "ZTMULTI.DEF", SDLK_m);
 			buttons[2] = new AdventureMapButton("", CGI->generaltexth->zelp[12].second, bind(&CMenuScreen::moveTo, this, ref(CGP->scrs[campaignMain])), 541, 233, "ZTCAMPN.DEF", SDLK_c);
 			buttons[3] = new AdventureMapButton("", CGI->generaltexth->zelp[13].second, 0 /*cb*/, 545, 358, "ZTTUTOR.DEF", SDLK_t);
@@ -149,8 +154,8 @@ CMenuScreen::CMenuScreen( EState which )
 	case loadGame:
 		{
 			bgAd = new CPicture(BitmapHandler::loadBitmap("ZLOADGAM.bmp"), 114, 312, true);
-			buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, loadGame), 545, 4, "ZTSINGL.DEF", SDLK_s);
-			buttons[1] = new AdventureMapButton("", CGI->generaltexth->zelp[11].second, 0 /*cb*/, 568, 120, "ZTMULTI.DEF", SDLK_m);
+			buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, loadGame, false), 545, 4, "ZTSINGL.DEF", SDLK_s);
+			buttons[1] = new AdventureMapButton("", CGI->generaltexth->zelp[11].second, bind(&CGPreGame::openSel, CGP, loadGame, true), 568, 120, "ZTMULTI.DEF", SDLK_m);
 			buttons[2] = new AdventureMapButton("", CGI->generaltexth->zelp[12].second, 0 /*cb*/, 541, 233, "ZTCAMPN.DEF", SDLK_c);
 			buttons[3] = new AdventureMapButton("", CGI->generaltexth->zelp[13].second, 0 /*cb*/, 545, 358, "ZTTUTOR.DEF", SDLK_t);
 			buttons[4] = new AdventureMapButton("", CGI->generaltexth->zelp[14].second, bind(&CMenuScreen::moveTo, this, CGP->scrs[mainMenu]), 582, 464, "ZTBACK.DEF", SDLK_ESCAPE);
@@ -161,7 +166,7 @@ CMenuScreen::CMenuScreen( EState which )
 			buttons[0] = new AdventureMapButton("", "", 0 /*cb*/, 535, 8, "ZSSSOD.DEF", SDLK_s);
 			buttons[1] = new AdventureMapButton("", "", 0 /*cb*/, 494, 117, "ZSSROE.DEF", SDLK_m);
 			buttons[2] = new AdventureMapButton("", "", 0 /*cb*/, 486, 241, "ZSSARM.DEF", SDLK_c);
-			buttons[3] = new AdventureMapButton("", "", bind(&CGPreGame::openSel, CGP, campaignList), 550, 358, "ZSSCUS.DEF", SDLK_t);
+			buttons[3] = new AdventureMapButton("", "", bind(&CGPreGame::openSel, CGP, campaignList, false), 550, 358, "ZSSCUS.DEF", SDLK_t);
 			buttons[4] = new AdventureMapButton("", "", bind(&CMenuScreen::moveTo, this, CGP->scrs[newGame]), 582, 464, "ZSSEXIT.DEF", SDLK_ESCAPE);
 
 		}
@@ -212,10 +217,10 @@ CGPreGame::~CGPreGame()
 		delete scrs[i];
 }
 
-void CGPreGame::openSel( CMenuScreen::EState type )
+void CGPreGame::openSel( CMenuScreen::EState type, bool multi )
 {
 	playerNames.push_back(CGI->generaltexth->allTexts[434]); //we have only one player and his name is "Player"
-	GH.pushInt(new CSelectionScreen(type));
+	GH.pushInt(new CSelectionScreen(type, multi));
 }
 
 void CGPreGame::loadGraphics()
@@ -259,7 +264,8 @@ void CGPreGame::update()
 	GH.handleEvents();
 }
 
-CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type)
+CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer)
+	:multiPlayer(MultiPlayer)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	IShowActivable::type = BLOCK_ADV_HOTKEYS;
@@ -303,7 +309,7 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type)
 		opt = new OptionsTab(type/*, sInfo*/); //scenario options tab
 		opt->recActions = DISPOSE;
 	}
-	sel = new SelectionTab(type, bind(&CSelectionScreen::changeSelection, this, _1)); //scenario selection tab
+	sel = new SelectionTab(type, bind(&CSelectionScreen::changeSelection, this, _1), multiPlayer); //scenario selection tab
 	sel->recActions = DISPOSE;
 
 	switch(type)
@@ -386,7 +392,7 @@ void CSelectionScreen::changeSelection( const CMapInfo *to )
 {
 	curMap = current = to;;
 	if(to && type == CMenuScreen::loadGame)
-		curOpts->difficulty = to->seldiff;
+		curOpts->difficulty = to->scenarioOpts->difficulty;
 	if(type != CMenuScreen::campaignList)
 	{
 		updateStartInfo(to, sInfo, to->mapHeader);
@@ -592,7 +598,7 @@ void SelectionTab::parseMaps(std::vector<FileInfo> &files, int start, int thread
 	}
 }
 
-void SelectionTab::parseGames(std::vector<FileInfo> &files)
+void SelectionTab::parseGames(std::vector<FileInfo> &files, bool multi)
 {
 	for(int i=0; i<files.size(); i++)
 	{
@@ -608,10 +614,16 @@ void SelectionTab::parseGames(std::vector<FileInfo> &files)
 			continue;
 		}
 		allItems[i].mapHeader = new CMapHeader();
-		lf >> *(allItems[i].mapHeader) >> allItems[i].seldiff;
+		lf >> *(allItems[i].mapHeader) >> allItems[i].scenarioOpts;
 		allItems[i].filename = files[i].name;
 		allItems[i].countPlayers();
 		allItems[i].date = std::asctime(std::localtime(&files[i].date));
+
+		if((allItems[i].actualHumanPlayers > 1) != multi) //if multi mode then only multi games, otherwise single
+		{
+			delete allItems[i].mapHeader;
+			allItems[i].mapHeader = NULL;
+		}
 	}
 }
 
@@ -626,7 +638,7 @@ void SelectionTab::parseCampaigns( std::vector<FileInfo> & files )
 	}
 }
 
-SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect)
+SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect, bool MultiPlayer)
 	:onSelect(OnSelect), bg(NULL)
 {
 	OBJ_CONSTRUCTION;
@@ -667,7 +679,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
 	case CMenuScreen::loadGame:
 	case CMenuScreen::saveGame:
 		getFiles(toParse, GVCMIDirs.UserPath + "/Games", "vlgm1"); //get all saves
-		parseGames(toParse);
+		parseGames(toParse, MultiPlayer);
 		if(tabType == CMenuScreen::loadGame)
 		{
 			positions = 18;

+ 10 - 7
client/CPreGame.h

@@ -29,11 +29,13 @@ class CMapInfo
 public:
 	CMapHeader * mapHeader; //may be NULL if campaign
 	CCampaignHeader * campaignHeader; //may be NULL if scenario
-	ui8 seldiff; //selected difficulty (only in saved games)
+	StartInfo *scenarioOpts; //options with which scenario has been started (used only with saved games)
 	std::string filename;
 	bool lodCmpgn; //tells if this campaign is located in Lod file
 	std::string date;
-	int playerAmnt, humenPlayers;
+	int playerAmnt, //players in map
+		humenPlayers; //players ALLOWED to be controlled by human
+	int actualHumanPlayers; // >1 if multiplayer game
 	CMapInfo(bool map = true);
 	~CMapInfo();
 	//CMapInfo(const std::string &fname, const unsigned char *map);
@@ -56,7 +58,7 @@ class CMenuScreen : public CIntObject
 {
 public:
 	enum EState { //where are we?
-		mainMenu, newGame, loadGame, campaignMain, ScenarioList, saveGame, scenarioInfo, campaignList
+		mainMenu, newGame, loadGame, campaignMain, saveGame, scenarioInfo, campaignList
 	};
 
 	CPicture *bgAd;
@@ -100,7 +102,7 @@ private:
 	CDefHandler *format; //map size
 
 	void parseMaps(std::vector<FileInfo> &files, int start = 0, int threads = 1);
-	void parseGames(std::vector<FileInfo> &files);
+	void parseGames(std::vector<FileInfo> &files, bool multi);
 	void parseCampaigns( std::vector<FileInfo> & files );
 	void getFiles(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext);
 	CMenuScreen::EState tabType; 
@@ -135,7 +137,7 @@ public:
 	void wheelScrolled(bool down, bool in);
 	void keyPressed(const SDL_KeyboardEvent & key);
 	void onDoubleClick();
-	SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect);
+	SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect, bool MultiPlayer=false);
 	~SelectionTab();
 };
 
@@ -208,8 +210,9 @@ public:
 	const CMapInfo *current;
 	StartInfo sInfo;
 	CIntObject *curTab;
+	bool multiPlayer;
 
-	CSelectionScreen(CMenuScreen::EState Type);
+	CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer = false);
 	~CSelectionScreen();
 	void toggleTab(CIntObject *tab);
 	void changeSelection(const CMapInfo *to);
@@ -335,7 +338,7 @@ public:
 	~CGPreGame();
 	void update();
 	void run();
-	void openSel(CMenuScreen::EState type);
+	void openSel(CMenuScreen::EState type, bool multi = false);
 	void loadGraphics();
 	void disposeGraphics();
 };

+ 3 - 2
client/Client.cpp

@@ -256,11 +256,12 @@ void CClient::loadGame( const std::string & fname )
 		char sig[8];
 		CMapHeader dum;
 		CGI->mh = new CMapHandler();
+		StartInfo *si;
 
 		CLoadFile lf(fname + ".vlgm1");
-		lf >> sig >> dum >> *sig;
+		lf >> sig >> dum >> si;
 		tlog0 <<"Reading save signature: "<<tmh.getDif()<<std::endl;
-			
+		
 		lf >> *VLC;
 		CGI->setFromLib();
 		tlog0 <<"Reading handlers: "<<tmh.getDif()<<std::endl;

+ 3 - 3
client/VCMI_client.vcproj

@@ -18,7 +18,7 @@
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="$(SolutionDir)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="1"
 			CharacterSet="1"
 			>
@@ -95,7 +95,7 @@
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="1"
 			CharacterSet="1"
 			WholeProgramOptimization="1"
@@ -180,7 +180,7 @@
 		<Configuration
 			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)\bin"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="1"
 			CharacterSet="1"
 			WholeProgramOptimization="1"

+ 7 - 3
hch/CDefObjInfoHandler.cpp

@@ -123,9 +123,13 @@ void CDefObjInfoHandler::load()
 		static const char *holeDefs[] = {"AVLHOLD0.DEF", "AVLHLDS0.DEF", "AVLHOLG0.DEF", "AVLHLSN0.DEF",
 			"AVLHOLS0.DEF", "AVLHOLR0.DEF", "AVLHOLX0.DEF", "AVLHOLL0.DEF"};
 
-		CGDefInfo * tmp = gobjs[124][0];
-		gobjs[124][i] = gobjs[124][0];
-		gobjs[124][i]->name = holeDefs[i];
+		CGDefInfo *& tmp = gobjs[124][i];
+		if(i)
+		{
+			tmp = new CGDefInfo;
+			*tmp = *gobjs[124][0];
+		}
+		tmp->name = holeDefs[i];
 	}
 }
  

+ 1 - 1
hch/CObjectHandler.h

@@ -298,7 +298,7 @@ public:
 	bool needsLastStack()const;
 	unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
 	unsigned int getLowestCreatureSpeed() const;
-	int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
+	int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
 	si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
 	si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
 	bool canWalkOnSea() const;

+ 5 - 2
lib/CGameState.cpp

@@ -1940,8 +1940,11 @@ int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
 	//checking resources
 	CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
 	
-	if(!pom)return 8;
-	if(pom->Name().size()==0||pom->resources.size()==0)return 2;//TODO: why does this happen?
+	if(!pom)
+		return 8;
+
+// 	if(pom->Name().size()==0||pom->resources.size()==0)
+// 		return 2;//TODO: why does this happen?
 
 	for(int res=0;res<pom->resources.size();res++) //TODO: support custom amount of resources
 	{

+ 1 - 1
lib/Connection.h

@@ -21,7 +21,7 @@
 #include <boost/mpl/int.hpp>
 #include <boost/mpl/identity.hpp>
 
-const ui32 version = 717;
+const ui32 version = 718;
 class CConnection;
 class CGObjectInstance;
 class CGameState;

+ 1 - 0
lib/RegisterTypes.cpp

@@ -152,6 +152,7 @@ void registerTypes3(Serializer &s)
 	s.template registerType<QueryReply>();
 	s.template registerType<MakeAction>();
 	s.template registerType<MakeCustomAction>();
+	s.template registerType<DigWithHero>();
 
 	s.template registerType<SaveGame>();
 	s.template registerType<SetSelection>();

+ 3 - 3
lib/VCMI_lib.vcproj

@@ -18,7 +18,7 @@
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="$(SolutionDir)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="2"
 			CharacterSet="2"
 			>
@@ -90,7 +90,7 @@
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="2"
 			CharacterSet="1"
 			WholeProgramOptimization="1"
@@ -172,7 +172,7 @@
 		<Configuration
 			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)\bin"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="2"
 			CharacterSet="1"
 			WholeProgramOptimization="1"

+ 13 - 8
mapHandler.cpp

@@ -1086,6 +1086,8 @@ SDL_Surface * CMapHandler::getVisBitmap(int x, int y, const std::vector< std::ve
 bool CMapHandler::printObject(const CGObjectInstance *obj)
 {
 	const SDL_Surface *bitmap = obj->defInfo->handler->ourImages[0].bitmap;
+	int tilesW = bitmap->w/32,
+		tilesH = bitmap->h/32;
 	for(int fx=0; fx<bitmap->w/32; ++fx)
 	{
 		for(int fy=0; fy<bitmap->h/32; ++fy)
@@ -1098,14 +1100,17 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
 			std::pair<const CGObjectInstance*,SDL_Rect> toAdd = std::make_pair(obj, cr);
 			if((obj->pos.x + fx - bitmap->w/32+1)>=0 && (obj->pos.x + fx - bitmap->w/32+1)<ttiles.size()-frameW && (obj->pos.y + fy - bitmap->h/32+1)>=0 && (obj->pos.y + fy - bitmap->h/32+1)<ttiles[0].size()-frameH)
 			{
-				TerrainTile2 & curt = //TODO use me 
-					ttiles
-					  [obj->pos.x + fx - bitmap->w/32]
-				      [obj->pos.y + fy - bitmap->h/32]
-					  [obj->pos.z];
-
-
-				ttiles[obj->pos.x + fx - bitmap->w/32+1][obj->pos.y + fy - bitmap->h/32+1][obj->pos.z].objects.push_back(toAdd);
+				TerrainTile2 & curt = ttiles[obj->pos.x + fx - bitmap->w/32+1][obj->pos.y + fy - bitmap->h/32+1][obj->pos.z];
+				for(std::vector< std::pair<const CGObjectInstance*,SDL_Rect> >::iterator i = curt.objects.begin(); i != curt.objects.end(); i++)
+				{
+					OCM_HLP cmp;
+					if(cmp(toAdd, *i))
+					{
+						curt.objects.insert(i, toAdd);
+						//curt.objects.push_back(toAdd)
+						break;
+					}
+				}
 			}
 
 		} // for(int fy=0; fy<bitmap->h/32; ++fy)

+ 43 - 5
server/CGameHandler.cpp

@@ -2086,7 +2086,7 @@ void CGameHandler::save( const std::string &fname )
 		tlog0 << "Serializing game info...\n";
 		CSaveFile save(GVCMIDirs.UserPath + "/Games/" + fname + ".vlgm1");
 		char hlp[8] = "VCMISVG";
-		save << hlp << static_cast<CMapHeader&>(*gs->map) << gs->scenarioOps->difficulty << *VLC << gs;
+		save << hlp << static_cast<CMapHeader&>(*gs->map) << gs->scenarioOps << *VLC << gs;
 	}
 
 	{
@@ -2241,9 +2241,20 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid )
 
 	if(gs->canBuildStructure(t,bid) != 7)
 	{
-		complain("Cannot raze that building!");
+		complain("Cannot build that building!");
 		return false;
 	}
+	
+	if(bid == 26) //grail
+	{
+		if(!t->visitingHero || !t->visitingHero->hasArt(2))
+		{
+			complain("Cannot build grail - hero doesn't have it");
+			return false;
+		}
+
+		removeArtifact(2, t->visitingHero->id);
+	}
 
 	NewStructures ns;
 	ns.tid = tid;
@@ -3909,7 +3920,7 @@ bool CGameHandler::dig( const CGHeroInstance *h )
 {
 	for (std::vector<CGObjectInstance*>::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
 	{
-		if((*i)->ID == 124  &&  (*i)->pos == h->getPosition(false))
+		if((*i)->ID == 124  &&  (*i)->pos == h->getPosition())
 		{
 			complain("Cannot dig - there is already a hole under the hero!");
 			return false;
@@ -3918,9 +3929,36 @@ bool CGameHandler::dig( const CGHeroInstance *h )
 
 	NewObject no;
 	no.ID = 124;
-	no.pos = h->getPosition(false);
-	no.subID = 0;
+	no.pos = h->getPosition();
+	no.subID = getTile(no.pos)->tertype;
+
+	if(no.subID >= 8) //no digging on water / rock
+	{
+		complain("Cannot dig - wrong terrain type!");
+		return false;
+	}
 	sendAndApply(&no);
+
+	SetMovePoints smp;
+	smp.hid = h->id;
+	smp.val = 0;
+	sendAndApply(&smp);
+
+	InfoWindow iw;
+	iw.player = h->tempOwner;
+	if(gs->map->grailPos == h->getPosition())
+	{
+		iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
+		iw.soundID = soundBase::ULTIMATEARTIFACT;
+		giveHeroArtifact(2, h->id, -1); //give grail
+	}
+	else
+	{
+		iw.text.addTxt(MetaString::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?"
+		iw.soundID = soundBase::Dig;
+	}
+	sendAndApply(&iw);
+
 	return true;
 }
 

+ 2 - 1
server/CVCMIServer.cpp

@@ -187,9 +187,10 @@ void CVCMIServer::loadGame( CConnection *c )
 		ui32 ver;
 		char sig[8];
 		CMapHeader dum;
+		StartInfo *si;
 
 		CLoadFile lf(fname + ".vlgm1");
-		lf >> sig >> dum >> *sig;
+		lf >> sig >> dum >> si;
 		tlog0 <<"Reading save signature"<<std::endl;
 
 		lf >> *VLC;

+ 3 - 3
server/VCMI_server.vcproj

@@ -18,7 +18,7 @@
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="$(SolutionDir)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="1"
 			CharacterSet="1"
 			>
@@ -90,7 +90,7 @@
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="1"
 			CharacterSet="2"
 			WholeProgramOptimization="1"
@@ -168,7 +168,7 @@
 		<Configuration
 			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)\bin"
-			IntermediateDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)_VC9"
 			ConfigurationType="1"
 			CharacterSet="2"
 			WholeProgramOptimization="1"