浏览代码

* a bit of campaign support

mateuszb 15 年之前
父节点
当前提交
adbc142ff0

+ 1 - 0
client/CAdvmapInterface.cpp

@@ -1629,6 +1629,7 @@ int3 CAdvMapInt::verifyPos(int3 ver)
 
 void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
 {
+	assert(sel);
 	LOCPLINT->cb->setSelection(sel);
 	selection = sel;
 	if(centerView)

+ 6 - 4
client/CMT.cpp

@@ -601,15 +601,17 @@ void startGame(StartInfo * options)
 		setResolution = true;
 
 	client = new CClient;
-	if(options->mode == 0) //new game
+	switch(options->mode) //new game
 	{
+	case 0:
+	case 2:
 		client->newGame(NULL, options);
-	}
-	else //load game
-	{
+		break;
+	case 1:
 		std::string fname = options->mapname;
 		boost::algorithm::erase_last(fname,".vlgm1");
 		client->loadGame(fname);
+		break;
 	}
 
 	CGI->musich->stopMusic();

+ 15 - 4
client/CPreGame.cpp

@@ -2204,7 +2204,7 @@ CBonusSelection::CBonusSelection( const CCampaign * _ourCampaign, int _whichMap
 
 	blitAt(panel, 456, 6, background);
 
-	startB = new AdventureMapButton("", "", 0 /*cb*/, 475, 536, "SCNRBEG.DEF", SDLK_RETURN);
+	startB = new AdventureMapButton("", "", bind(&CBonusSelection::startMap, this), 475, 536, "SCNRBEG.DEF", SDLK_RETURN);
 	backB = new AdventureMapButton("", "", bind(&CBonusSelection::goBack, this), 624, 536, "SCNRBACK.DEF", SDLK_ESCAPE);
 
 	//campaign name
@@ -2320,7 +2320,7 @@ void CBonusSelection::loadPositionsOfGraphics()
 void CBonusSelection::selectMap( int whichOne )
 {
 	sInfo.difficulty = ourCampaign->scenarios[whichOne].difficulty;
-	sInfo.mapname = ourCampaign->header.name;
+	sInfo.mapname = ourCampaign->header.filename;
 	sInfo.mode = 2;
 
 	//get header
@@ -2328,9 +2328,12 @@ void CBonusSelection::selectMap( int whichOne )
 	delete ourHeader;
 	ourHeader = new CMapHeader();
 	ourHeader->initFromMemory((const unsigned char*)ourCampaign->mapPieces[whichOne].c_str(), i);
-	const_cast<CMapInfo *>(curMap)->playerAmnt = ourHeader->players.size();
+	CMapInfo *mapInfo = const_cast<CMapInfo *>(curMap);
+	mapInfo->mapHeader = ourHeader;
+	mapInfo->countPlayers();
+	mapInfo->mapHeader = NULL;
 	
-	CSelectionScreen::updateStartInfo(curMap, *curOpts, ourHeader);
+	CSelectionScreen::updateStartInfo(curMap, sInfo, ourHeader);
 	sInfo.turnTime = 0;
 	sInfo.whichMapInCampaign = whichOne;
 }
@@ -2409,6 +2412,14 @@ void CBonusSelection::updateBonusSelection()
 
 }
 
+void CBonusSelection::startMap()
+{
+	StartInfo *si = new StartInfo(sInfo);
+	GH.popInts(3);
+	curOpts = NULL;
+	::startGame(si);
+}
+
 CBonusSelection::CRegion::CRegion( CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber )
 : owner(_owner), accessible(_accessible), selectable(_selectable), myNumber(_myNumber)
 {

+ 6 - 16
client/Client.cpp

@@ -1,3 +1,4 @@
+#include "../hch/CCampaignHandler.h"
 #include "../CCallback.h"
 #include "../CConsoleHandler.h"
 #include "CGameInfo.h"
@@ -375,32 +376,21 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 
 
 	ui32 seed, sum;
-	std::string mapname;
-	c >> mapname >> sum >> seed;
+	delete si;
+	c >> si	>> sum >> seed;
 	tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
-
-	Mapa * mapa = new Mapa(mapname);
-	tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
-	tlog0 << "\tServer checksum for "<<mapname <<": "<<sum << std::endl;
-	tlog0 << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
-
-	if(mapa->checksum != sum)
-	{
-		tlog1 << "Wrong map checksum!!!" << std::endl;
-		throw std::string("Wrong checksum");
-	}
 	tlog0 << "\tUsing random seed: "<<seed << std::endl;
 
 	gs = CGI->state;
 	gs->scenarioOps = si;
-	gs->init(si,mapa,seed);
+	gs->init(si, sum, seed);
 
 	CGI->mh = new CMapHandler();
 	tlog0 <<"Initializing GameState (together): "<<tmh.getDif()<<std::endl;
-	CGI->mh->map = mapa;
+	CGI->mh->map = gs->map;
 	tlog0 <<"Creating mapHandler: "<<tmh.getDif()<<std::endl;
 	CGI->mh->init();
-	pathInfo = new CPathsInfo(int3(mapa->width, mapa->height, mapa->twoLevel+1));
+	pathInfo = new CPathsInfo(int3(gs->map->width, gs->map->height, gs->map->twoLevel+1));
 	tlog0 <<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
 
 	int humanPlayers = 0;

+ 7 - 3
client/GUIBase.cpp

@@ -75,7 +75,7 @@ void CGuiHandler::popInts( int howMany )
 {
 	if(!howMany) return; //senseless but who knows...
 
-	assert(listInt.size() > howMany);
+	assert(listInt.size() >= howMany);
 	listInt.front()->deactivate();
 	for(int i=0; i < howMany; i++)
 	{
@@ -83,8 +83,12 @@ void CGuiHandler::popInts( int howMany )
 		delete listInt.front();
 		listInt.pop_front();
 	}
-	listInt.front()->activate();
-	totalRedraw();
+
+	if(listInt.size())
+	{
+		listInt.front()->activate();
+		totalRedraw();
+	}
 }
 
 IShowActivable * CGuiHandler::topInt()

+ 2 - 2
client/GUIClasses.cpp

@@ -1504,7 +1504,7 @@ void CHeroList::draw(SDL_Surface * to)
 		blitAt(mana->ourImages[pom].bitmap,posmanx,posmany+i*32,to); //mana
 		SDL_Surface * temp = graphics->portraitSmall[cur->portrait];
 		blitAt(temp,posporx,pospory+i*32,to);
-		if ((selected == iT) && (adventureInt->selection->ID == HEROI_TYPE))
+		if (adventureInt->selection && (selected == iT) && (adventureInt->selection->ID == HEROI_TYPE))
 		{
 			blitAt(selection,posporx,pospory+i*32,to);
 		}
@@ -1745,7 +1745,7 @@ void CTownList::draw(SDL_Surface * to)
 
 		blitAt(graphics->getPic(LOCPLINT->towns[iT]->subID,LOCPLINT->towns[iT]->hasFort(),LOCPLINT->towns[iT]->builded),posporx,pospory+i*32,to);
 
-		if ((selected == iT) && (adventureInt->selection->ID == TOWNI_TYPE))
+		if (adventureInt->selection && (selected == iT) && (adventureInt->selection->ID == TOWNI_TYPE))
 		{
 			blitAt(graphics->getPic(-2),posporx,pospory+i*32,to);
 		}

+ 5 - 0
hch/CCampaignHandler.cpp

@@ -436,3 +436,8 @@ bool CCampaign::conquerable( int whichScenario ) const
 	}
 	return true;
 }
+
+CCampaign::CCampaign()
+{
+
+}

+ 2 - 0
hch/CCampaignHandler.h

@@ -114,6 +114,8 @@ public:
 	}
 
 	bool conquerable(int whichScenario) const;
+
+	CCampaign();
 };
 
 class DLL_EXPORT CCampaignHandler

+ 42 - 2
lib/CGameState.cpp

@@ -1,4 +1,5 @@
 #define VCMI_DLL
+#include "../hch/CCampaignHandler.h"
 #include <algorithm>
 #include <queue>
 #include <fstream>
@@ -1162,6 +1163,7 @@ CGameState::CGameState()
 	scenarioOps = NULL;
 	applierGs = new CGSApplier;
 	objCaller = new CObjectCallersHandler;
+	campaign = NULL;
 }
 CGameState::~CGameState()
 {
@@ -1172,13 +1174,40 @@ CGameState::~CGameState()
 	delete applierGs;
 	delete objCaller;
 }
-void CGameState::init(StartInfo * si, Mapa * map, int Seed)
+void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 {
+
+	switch(si->mode)
+	{
+	case 0:
+		map = new Mapa(si->mapname);
+		break;
+	case 2:
+		campaign = new CCampaignState();
+		campaign->initNewCampaign(*si);
+		std::string &mapContent = campaign->camp->mapPieces[si->whichMapInCampaign];
+		map = new Mapa();
+		map->initFromBytes((const unsigned char*)mapContent.c_str());
+		break;
+	}
+	tlog0 << "Map loaded!" << std::endl;
+
+	//tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
+	if(checksum)
+	{
+		tlog0 << "\tServer checksum for " << si->mapname <<": "<< checksum << std::endl;
+		tlog0 << "\tOur checksum for the map: "<< map->checksum << std::endl;
+		if(map->checksum != checksum)
+		{
+			tlog1 << "Wrong map checksum!!!" << std::endl;
+			throw std::string("Wrong checksum");
+		}
+	}
+
 	day = 0;
 	seed = Seed;
 	ran.seed((boost::int32_t)seed);
 	scenarioOps = si;
-	this->map = map;
 	loadTownDInfos();
 
  	//pick grail location
@@ -3798,3 +3827,14 @@ InfoAboutHero & InfoAboutHero::operator=( const InfoAboutHero & iah )
 	assign(iah);
 	return *this;
 }
+
+void CCampaignState::initNewCampaign( const StartInfo &si )
+{
+	assert(si.mode == 2);
+	campaignName = si.mapname;
+	currentMap = si.whichMapInCampaign;
+	
+	camp = CCampaignHandler::getCampaign(campaignName, true); //TODO lod???
+	for (ui8 i = 0; i < camp->mapPieces.size(); i++)
+		mapsRemaining.push_back(i);
+}

+ 20 - 2
lib/CGameState.h

@@ -58,6 +58,7 @@ struct CPack;
 class CSpell;
 struct TerrainTile;
 class CHeroClass;
+class CCampaign;
 
 namespace boost
 {
@@ -345,10 +346,27 @@ struct DLL_EXPORT CPathsInfo
 	~CPathsInfo();
 };
 
+class DLL_EXPORT CCampaignState
+{
+public:
+	CCampaign *camp;
+	std::string campaignName; 
+	std::vector<ui8> mapsConquered, mapsRemaining;
+	ui8 currentMap; 
+
+	void initNewCampaign(const StartInfo &si);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & camp & campaignName & mapsRemaining & mapsConquered & currentMap;
+	}
+};
+
 class DLL_EXPORT CGameState
 {
 public:
 	StartInfo* scenarioOps;
+	CCampaignState *campaign;
 	ui32 seed;
 	ui8 currentPlayer; //ID of player currently having turn
 	BattleInfo *curB; //current battle
@@ -375,7 +393,7 @@ public:
 	boost::shared_mutex *mx;
 	PlayerState *getPlayer(ui8 color, bool verbose = true);
 	const PlayerState *getPlayer(ui8 color, bool verbose = true) const;
-	void init(StartInfo * si, Mapa * map, int Seed);
+	void init(StartInfo * si, ui32 checksum, int Seed);
 	void loadTownDInfos();
 	void randomizeObject(CGObjectInstance *cur);
 	std::pair<int,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
@@ -419,7 +437,7 @@ 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
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & scenarioOps & seed & currentPlayer & day & map & players & resVals & hpool & globalEffects;
+		h & scenarioOps & seed & currentPlayer & day & map & players & resVals & hpool & globalEffects & campaign;
 		if(!h.saving)
 		{
 			loadTownDInfos();

+ 1 - 1
lib/Connection.h

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

+ 3 - 4
server/CGameHandler.cpp

@@ -1,3 +1,4 @@
+#include "../hch/CCampaignHandler.h"
 #include "../StartInfo.h"
 #include "../hch/CArtHandler.h"
 #include "../hch/CBuildingHandler.h"
@@ -851,11 +852,9 @@ CGameHandler::~CGameHandler(void)
 
 void CGameHandler::init(StartInfo *si, int Seed)
 {
-	Mapa *map = new Mapa(si->mapname);
-	tlog0 << "Map loaded!" << std::endl;
 	gs = new CGameState();
 	tlog0 << "Gamestate created!" << std::endl;
-	gs->init(si,map,Seed);
+	gs->init(si, 0, Seed);
 	tlog0 << "Gamestate initialized!" << std::endl;
 
 	for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
@@ -1044,7 +1043,7 @@ void CGameHandler::run(bool resume)
 		ui8 quantity, pom;
 		//ui32 seed;
 		if(!resume)
-			(*cc) << gs->scenarioOps->mapname << gs->map->checksum << gs->seed;
+			(*cc) << gs->scenarioOps << gs->map->checksum << gs->seed;
 
 		(*cc) >> quantity; //how many players will be handled at that client
 		for(int i=0;i<quantity;i++)

+ 5 - 2
server/CVCMIServer.cpp

@@ -1,3 +1,4 @@
+#include "../hch/CCampaignHandler.h"
 #include <iostream>
 #include <string>
 #include <boost/asio.hpp>
@@ -71,6 +72,7 @@ void CVCMIServer::newGame(CConnection *c)
 	*c >> clients; //how many clients should be connected - TODO: support more than one
 	*c >> *si; //get start options
 	int problem;
+
 #ifdef _MSC_VER
 	FILE *f;
 	problem = fopen_s(&f,si->mapname.c_str(),"r");
@@ -78,14 +80,15 @@ void CVCMIServer::newGame(CConnection *c)
 	FILE * f = fopen(si->mapname.c_str(),"r");
 	problem = !f;
 #endif
-	if(problem)
+	if(problem && si->mode == 0) //TODO some checking for campaigns
 	{
 		*c << ui8(problem); //WRONG!
 		return;
 	}
 	else
 	{
-		fclose(f);
+		if(f)	
+			fclose(f);
 		*c << ui8(0); //OK!
 	}