Browse Source

Changes towards campaign support.

mateuszb 15 years ago
parent
commit
d681afe1c1

+ 26 - 19
client/CMT.cpp

@@ -553,7 +553,7 @@ static void listenForEvents()
 			(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
 		{
 			if (client)
-				client->stop();
+				client->endGame();
 			if (mainGUIThread) 
 			{
 				GH.terminate = true;
@@ -577,27 +577,34 @@ static void listenForEvents()
 			delete ev;
 			continue;
 		}
-		else if(ev->type == SDL_USEREVENT && ev->user.code == 1)
+		else if(ev->type == SDL_USEREVENT)
 		{
-			tlog0 << "Changing resolution has been requested\n";
-			setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
-			delete ev;
-			continue;
-		}
-		else if (ev->type == SDL_USEREVENT && ev->user.code == 2) //something want to quit to main menu
-		{
-			client->stop();
-			delete client;
-			client = NULL;
+			switch(ev->user.code)
+			{
+			case 1:
+				tlog0 << "Changing resolution has been requested\n";
+				setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
+				break;
+
+			case 2:
+				client->endGame();
+				delete client;
+				client = NULL;
+
+				delete CGI->dobjinfo;
+				CGI->dobjinfo = new CDefObjInfoHandler;
+				CGI->dobjinfo->load();
+
+				GH.curInt = CGP;
+				GH.defActionsDef = 63;
+				break;
+
+			case 3:
+				client->endGame(false);
+				break;
+			}
 
 			delete ev;
-
-			delete CGI->dobjinfo;
-			CGI->dobjinfo = new CDefObjInfoHandler;
-			CGI->dobjinfo->load();
-
-			GH.curInt = CGP;
-			GH.defActionsDef = 63;
 			continue;
 		}
 

+ 13 - 3
client/CPlayerInterface.cpp

@@ -1813,8 +1813,8 @@ void CPlayerInterface::gameOver(ui8 player, bool victory )
 		{
 			if(cb->getStartInfo()->mode != StartInfo::CAMPAIGN)
 				requestReturningToMainMenu();
-			
-			//TODO next campaign scenario
+			else
+				requestStoppingClient();
 		}
 
 	}
@@ -2077,10 +2077,20 @@ void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj)
 }
 
 void CPlayerInterface::requestReturningToMainMenu()
+{
+	sendCustomEvent(2);
+}
+
+void CPlayerInterface::requestStoppingClient()
+{
+	sendCustomEvent(3);
+}
+
+void CPlayerInterface::sendCustomEvent( int code )
 {
 	SDL_Event event;
 	event.type = SDL_USEREVENT;
-	event.user.code = 2;
+	event.user.code = code;
 	SDL_PushEvent(&event);
 }
 

+ 2 - 0
client/CPlayerInterface.h

@@ -245,6 +245,8 @@ public:
 	void tryDiggging(const CGHeroInstance *h);
 	void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard; 
 	void requestReturningToMainMenu();
+	void requestStoppingClient();
+	void sendCustomEvent(int code);
 
 	CPlayerInterface(int Player);//c-tor
 	~CPlayerInterface();//d-tor

+ 22 - 8
client/CPreGame.cpp

@@ -260,8 +260,8 @@ CGPreGame::~CGPreGame()
 
 void CGPreGame::openSel( CMenuScreen::EState type, bool multi )
 {
-	playerNames.clear();
-	playerNames.push_back(CGI->generaltexth->allTexts[434]); //we have only one player and his name is "Player"
+	resetPlayerNames();
+
 	GH.pushInt(new CSelectionScreen(type, multi));
 }
 
@@ -306,6 +306,12 @@ void CGPreGame::update()
 	GH.handleEvents();
 }
 
+void CGPreGame::resetPlayerNames()
+{
+	playerNames.clear();
+	playerNames.push_back(CGI->generaltexth->allTexts[434]); //we have only one player and his name is "Player"
+}
+
 CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer)
 	:multiPlayer(MultiPlayer)
 {
@@ -2206,11 +2212,16 @@ CBonusSelection::CBonusSelection( CCampaignState * _ourCampaign )
 : ourCampaign(_ourCampaign), highlightedRegion(NULL), ourHeader(NULL), bonuses(NULL),
 	diffLb(NULL), diffRb(NULL)
 {
-	OBJ_CONSTRUCTION;
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	static const std::string bgNames [] = {"E1_BG.BMP", "G2_BG.BMP", "E2_BG.BMP", "G1_BG.BMP", "G3_BG.BMP", "N1_BG.BMP",
 		"S1_BG.BMP", "BR_BG.BMP", "IS_BG.BMP", "KR_BG.BMP", "NI_BG.BMP", "TA_BG.BMP", "AR_BG.BMP", "HS_BG.BMP",
 		"BB_BG.BMP", "NB_BG.BMP", "EL_BG.BMP", "RN_BG.BMP", "UA_BG.BMP", "SP_BG.BMP"};
 
+	if(ourCampaign->mapsConquered.size())
+	{
+		CGP->resetPlayerNames();
+	}
+
 	loadPositionsOfGraphics();
 
 	background = BitmapHandler::loadBitmap(bgNames[ourCampaign->camp->header.mapVersion]);
@@ -2370,12 +2381,15 @@ void CBonusSelection::selectMap( int whichOne )
 	delete ourHeader;
 	ourHeader = new CMapHeader();
 	ourHeader->initFromMemory((const unsigned char*)ourCampaign->camp->mapPieces.find(whichOne)->second.c_str(), i);
-	CMapInfo *mapInfo = const_cast<CMapInfo *>(curMap);
-	mapInfo->mapHeader = ourHeader;
-	mapInfo->countPlayers();
-	mapInfo->mapHeader = NULL;
+// 	CMapInfo *mapInfo = const_cast<CMapInfo *>(curMap);
+// 	mapInfo->mapHeader = ourHeader;
+// 	mapInfo->countPlayers();
+// 	mapInfo->mapHeader = NULL;
+	CMapInfo dummyInfo(false);
+	dummyInfo.filename = "lala";
+
 	
-	CSelectionScreen::updateStartInfo(curMap, sInfo, ourHeader);
+	CSelectionScreen::updateStartInfo(curMap ? curMap : &dummyInfo, sInfo, ourHeader);
 	sInfo.turnTime = 0;
 	sInfo.whichMapInCampaign = whichOne;
 	sInfo.difficulty = ourCampaign->camp->scenarios[whichOne].difficulty;

+ 2 - 0
client/CPreGame.h

@@ -360,6 +360,8 @@ public:
 	void update();
 	void run();
 	void openSel(CMenuScreen::EState type, bool multi = false);
+
+	void resetPlayerNames();
 	void loadGraphics();
 	void disposeGraphics();
 };

+ 51 - 30
client/Client.cpp

@@ -27,6 +27,7 @@
 #include <boost/thread.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <sstream>
+#include "CPreGame.h"
 
 #undef DLL_EXPORT
 #define DLL_EXPORT
@@ -168,18 +169,6 @@ void CClient::run()
 	}
 }
 
-void CClient::stop()
-{
-	// Game is ending
-	// Tell the network thread to reach a stable state
-	terminate = true;
-	GH.curInt = NULL;
-	LOCPLINT->terminate_cond.setn(true);
-	LOCPLINT->pim->lock();
-	endGame();
-	tlog0 << "Client stopped." << std::endl;
-}
-
 void CClient::save(const std::string & fname)
 {
 	if(gs->curB)
@@ -216,8 +205,14 @@ void initVillagesCapitols(Mapa * map)
 	}
 }
 
-void CClient::endGame()
+void CClient::endGame( bool closeConnection /*= true*/ )
 {
+	// Game is ending
+	// Tell the network thread to reach a stable state
+	GH.curInt = NULL;
+	LOCPLINT->terminate_cond.setn(true);
+	LOCPLINT->pim->lock();
+
 	tlog0 << "\n\nEnding current game!" << std::endl;
 	if(GH.topInt())
 		GH.topInt()->deactivate();
@@ -246,24 +241,10 @@ void CClient::endGame()
 	}
 	tlog0 << "Deleted playerInts." << std::endl;
 
-	if (serv) 
-	{
-		tlog0 << "Connection has been requested to be closed.\n";
-		boost::unique_lock<boost::mutex>(*serv->wmx);
-		*serv << &CloseServer();
-		tlog0 << "Sent closing signal to the server\n";
+	if(closeConnection)
+		stopConnection();
 
-		serv->close();
-		delete serv;
-		serv = NULL;
-		tlog3 << "Our socket has been closed." << std::endl;
-	}
-
-	connectionHandler->join();
-	tlog0 << "Connection handler thread joined" << std::endl;
-
-	delete connectionHandler;
-	connectionHandler = NULL;
+	tlog0 << "Client stopped." << std::endl;
 }
 
 void CClient::loadGame( const std::string & fname )
@@ -541,5 +522,45 @@ void CClient::updatePaths()
 	if (h)//if we have selected hero...
 		gs->calculatePaths(h, *pathInfo);
 }
+
+void CClient::finishCampaign( CCampaignState * camp )
+{
+}
+
+void CClient::proposeNextMission( CCampaignState * camp )
+{
+	GH.pushInt(new CBonusSelection(camp));
+	GH.curInt = CGP;
+}
+
+void CClient::stopConnection()
+{
+	terminate = true;
+
+	if (serv) 
+	{
+		tlog0 << "Connection has been requested to be closed.\n";
+		boost::unique_lock<boost::mutex>(*serv->wmx);
+		*serv << &CloseServer();
+		tlog0 << "Sent closing signal to the server\n";
+
+		serv->close();
+		delete serv;
+		serv = NULL;
+		tlog3 << "Our socket has been closed." << std::endl;
+	}
+
+	if(connectionHandler)
+	{
+		if(connectionHandler->get_id() != boost::this_thread::get_id())
+			connectionHandler->join();
+
+		tlog0 << "Connection handler thread joined" << std::endl;
+
+		delete connectionHandler;
+		connectionHandler = NULL;
+	}
+}
+
 template void CClient::serialize( CISer<CLoadFile> &h, const int version );
 template void CClient::serialize( COSer<CSaveFile> &h, const int version );

+ 4 - 2
client/Client.h

@@ -55,11 +55,13 @@ public:
 
 	void init();
 	void newGame(CConnection *con, StartInfo *si); //con - connection to server
-	void endGame();
+	void endGame(bool closeConnection = true);
+	void stopConnection();
 	void save(const std::string & fname);
 	void loadGame(const std::string & fname);
 	void run();
-	void stop();
+	void finishCampaign( CCampaignState * camp );
+	void proposeNextMission( CCampaignState * camp );
 
 	bool terminate;	// tell to terminate
 	boost::thread *connectionHandler; //thread running run() method

+ 12 - 2
client/NetPacksClient.cpp

@@ -22,6 +22,7 @@
 #include "CConfigHandler.h"
 #include "SDL_Extensions.h"
 #include "CBattleInterface.h"
+#include "../hch/CCampaignHandler.h"
 
 //macro to avoid code duplication - calls given method with given arguments if interface for specific player is present
 #define INTERFACE_CALL_IF_PRESENT(player,function,...) 	\
@@ -161,8 +162,8 @@ void PlayerEndsGame::applyCl( CClient *cl )
 		i->second->gameOver(player,	victory);
 
 
-	if(!CPlayerInterface::howManyPeople)
-		cl->terminate = true;
+// 	if(!CPlayerInterface::howManyPeople)
+// 		cl->terminate = true;
 }
 
 void RemoveBonus::applyCl( CClient *cl )
@@ -184,6 +185,15 @@ void RemoveBonus::applyCl( CClient *cl )
 	}
 }
 
+void UpdateCampaignState::applyCl( CClient *cl )
+{
+	cl->stopConnection();
+	if(camp->mapsRemaining.size())
+		cl->proposeNextMission(camp);
+	else
+		cl->finishCampaign(camp);
+}
+
 void RemoveObject::applyFirstCl( CClient *cl )
 {
 	const CGObjectInstance *o = cl->getObj(id);

+ 7 - 0
hch/CCampaignHandler.cpp

@@ -481,3 +481,10 @@ void CCampaignState::initNewCampaign( const StartInfo &si )
 	for (ui8 i = 0; i < camp->mapPieces.size(); i++)
 		mapsRemaining.push_back(i);
 }
+
+void CCampaignState::mapConquered()
+{
+	mapsConquered.push_back(currentMap);
+	mapsRemaining -= currentMap;
+	camp->scenarios[currentMap].conquered = true;
+}

+ 1 - 0
hch/CCampaignHandler.h

@@ -133,6 +133,7 @@ public:
 	ui8 currentMap; 
 
 	void initNewCampaign(const StartInfo &si);
+	void mapConquered();
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 1 - 2
lib/CGameState.cpp

@@ -1275,9 +1275,9 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 		break;
 	case StartInfo::CAMPAIGN:
 		{
-			assert(vstd::contains(campaign->camp->mapPieces, si->whichMapInCampaign));
 			campaign = new CCampaignState();
 			campaign->initNewCampaign(*si);
+			assert(vstd::contains(campaign->camp->mapPieces, si->whichMapInCampaign));
 
 			std::string &mapContent = campaign->camp->mapPieces[si->whichMapInCampaign];
 			map = new Mapa();
@@ -2250,7 +2250,6 @@ int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
 void CGameState::apply(CPack *pack)
 {
 	ui16 typ = typeList.getTypeID(pack);
-	assert(typ >= 0);
 	applierGs->apps[typ]->applyOnGS(this,pack);
 }
 

+ 17 - 1
lib/NetPacks.h

@@ -21,7 +21,7 @@ class CClient;
 class CGameState;
 class CGameHandler;
 class CConnection;
-
+class CCampaignState;
 class CArtifact;
 
 struct CPack
@@ -462,6 +462,22 @@ struct RemoveBonus :  public CPackForClient //118
 	}
 };
 
+struct UpdateCampaignState : public CPackForClient //119
+{
+	UpdateCampaignState()
+	{
+		type = 119;
+	}
+
+	CCampaignState *camp;
+	void applyCl(CClient *cl);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & camp;
+	}
+};
+
 struct RemoveObject : public CPackForClient //500
 {
 	RemoveObject(){type = 500;};

+ 1 - 0
lib/RegisterTypes.cpp

@@ -92,6 +92,7 @@ void registerTypes2(Serializer &s)
 	s.template registerType<ChangeObjPos>();
 	s.template registerType<PlayerEndsGame>();
 	s.template registerType<RemoveBonus>();
+	s.template registerType<UpdateCampaignState>();
 	s.template registerType<RemoveObject>();
 	s.template registerType<TryMoveHero>();
 	s.template registerType<SetGarrisons>();

+ 11 - 0
server/CGameHandler.cpp

@@ -4668,7 +4668,18 @@ void CGameHandler::checkLossVictory( ui8 player )
 	}
 
 	if(vic)
+	{
 		end2 = true;
+
+		if(gs->campaign)
+		{
+			gs->campaign->mapConquered();
+
+			UpdateCampaignState ucs;
+			ucs.camp = gs->campaign;
+			sendAndApply(&ucs);
+		}
+	}
 }
 
 void CGameHandler::getLossVicMessage( ui8 player, ui8 standard, bool victory, InfoWindow &out ) const