Prechádzať zdrojové kódy

* next part of campaign support
* a few fixes for .h3c reading

mateuszb 15 rokov pred
rodič
commit
448c2e7225
4 zmenil súbory, kde vykonal 207 pridanie a 35 odobranie
  1. 169 24
      client/CPreGame.cpp
  2. 16 0
      client/CPreGame.h
  3. 18 7
      hch/CCampaignHandler.cpp
  4. 4 4
      hch/CCampaignHandler.h

+ 169 - 24
client/CPreGame.cpp

@@ -268,6 +268,13 @@ CSelectionScreen::CSelectionScreen( CMenuScreen::EState Type, const std::vector<
 	{
 		center(pos);
 	}
+	else if(Type == CMenuScreen::campaignList)
+	{
+		bg = new CPicture(BitmapHandler::loadBitmap("CamCust.bmp"), 0, 0, true);
+
+		pos.x = 3;
+		pos.y = 6;
+	}
 	else
 	{
 		pos.x = 3;
@@ -326,13 +333,24 @@ CSelectionScreen::CSelectionScreen( CMenuScreen::EState Type, const std::vector<
 		break;
 	case CMenuScreen::campaignList:
 		sel->recActions = 255;
-		start  = new AdventureMapButton(std::pair<std::string, std::string>(), 0 /*cb*/, 411, 529, "SCNRBEG.DEF", SDLK_b);
+		start  = new AdventureMapButton(std::pair<std::string, std::string>(), bind(&CSelectionScreen::startCampaign, this), 411, 529, "SCNRLOD.DEF", SDLK_b);
 		break;
 	}
+	
 
 	start->assignedKeys.insert(SDLK_RETURN);
 
-	back = new AdventureMapButton("", CGI->generaltexth->zelp[105].second, bind(&CGuiHandler::popIntTotally, &GH, this), 581, 529, "SCNRBACK.DEF", SDLK_ESCAPE);
+	std::string backName;
+	if(Type == CMenuScreen::campaignList)
+	{
+		backName = "SCNRBACK.DEF";
+	}
+	else
+	{
+		backName = "SCNRBACK.DEF";
+	}
+
+	back = new AdventureMapButton("", CGI->generaltexth->zelp[105].second, bind(&CGuiHandler::popIntTotally, &GH, this), 581, 529, backName, SDLK_ESCAPE);
 }
 
 CSelectionScreen::~CSelectionScreen()
@@ -446,6 +464,12 @@ void CSelectionScreen::updateStartInfo( const CMapInfo * to )
 	}
 }
 
+void CSelectionScreen::startCampaign()
+{
+	CCampaign * ourCampaign = CCampaignHandler::getCampaign(curMap->filename);
+	GH.pushInt( new CBonusSelection(ourCampaign, 0) );
+}
+
 void CSelectionScreen::startGame()
 {
 	if(type != CMenuScreen::saveGame)
@@ -596,7 +620,7 @@ void SelectionTab::parseCampaigns( std::vector<FileInfo> & files )
 }
 
 SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect)
-	:onSelect(OnSelect)
+	:onSelect(OnSelect), bg(NULL)
 {
 	OBJ_CONSTRUCTION;
 	selectionPos = 0;
@@ -605,16 +629,12 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
 	txt = NULL;
 	tabType = Type;
 
-	if (Type == CMenuScreen::campaignList)
-	{
-		bg = new CPicture(BitmapHandler::loadBitmap("CamCust.bmp"), 0, 0, true);
-	} 
-	else
-	{
+// 	if (Type != CMenuScreen::campaignList)
+	/*{*/
 		bg = new CPicture(BitmapHandler::loadBitmap("SCSELBCK.bmp"), 0, 0, true);
-	}
-	pos.w = bg->pos.w;
-	pos.h = bg->pos.h;
+		pos.w = bg->pos.w;
+		pos.h = bg->pos.h;
+	/*}*/
 
 	std::vector<FileInfo> toParse;
 	switch(tabType)
@@ -643,6 +663,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
 	case CMenuScreen::campaignList:
 		getFiles(toParse, DATA_DIR "/Maps", "h3c"); //get all campaigns
 		parseCampaigns(toParse);
+		positions = 18;
 		break;
 
 	default:
@@ -786,13 +807,13 @@ void SelectionTab::printMaps(SDL_Surface *to)
 	{
 		CMapInfo* curMap = curItems[elemIdx];
 
+		if (elemIdx == selectionPos)
+			itemColor=tytulowy;
+		else 
+			itemColor=zwykly;
+
 		if(tabType != CMenuScreen::campaignList)
 		{
-			if (elemIdx == selectionPos)
-				itemColor=tytulowy;
-			else 
-				itemColor=zwykly;
-
 			//amount of players
 			std::ostringstream ostr(std::ostringstream::out);
 			ostr << curMap->playerAmnt << "/" << curMap->humenPlayers;
@@ -853,6 +874,13 @@ void SelectionTab::printMaps(SDL_Surface *to)
 				temp=curMap->mapHeader->lossCondition.typeOfLossCon;
 			blitAt(CGP->loss->ourImages[temp].bitmap, POS(339, 117), to);
 		}
+		else //if campaign
+		{
+			//number of maps in campaign
+			std::ostringstream ostr(std::ostringstream::out);
+			ostr << CGI->generaltexth->campaignRegionNames[ curMap->campaignHeader->mapVersion ].size();
+			CSDL_Ext::printAt(ostr.str(), POS(29, 120), FONT_SMALL, itemColor, to);
+		}
 
 		std::string name;
 		if(tabType != CMenuScreen::campaignList)
@@ -867,7 +895,7 @@ void SelectionTab::printMaps(SDL_Surface *to)
 		}
 
 		//print name
-		if (tabType == CMenuScreen::newGame) {
+		if (tabType == CMenuScreen::newGame || tabType == CMenuScreen::campaignList) {
 			
 			CSDL_Ext::printAtMiddle(name, POS(213, 128), FONT_SMALL, itemColor, to);
 		} else
@@ -899,7 +927,10 @@ void SelectionTab::showAll( SDL_Surface * to )
 	}
 
 	CSDL_Ext::printAtMiddle(title, pos.x+205, pos.y+28, FONT_MEDIUM, tytulowy, to); //Select a Scenario to Play
-	CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[510], pos.x+87, pos.y+62, FONT_SMALL, tytulowy, to); //Map sizes
+	if(tabType != CMenuScreen::campaignList)
+	{
+		CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[510], pos.x+87, pos.y+62, FONT_SMALL, tytulowy, to); //Map sizes
+	}
 }
 
 void SelectionTab::clickLeft( tribool down, bool previousState )
@@ -990,19 +1021,25 @@ void SelectionTab::selectFName( const std::string &fname )
 
 
 InfoCard::InfoCard( CMenuScreen::EState Type )
-: difficulty(NULL), sizes(NULL), sFlags(NULL)
+: difficulty(NULL), sizes(NULL), sFlags(NULL), bg(NULL)
 {
 	OBJ_CONSTRUCTION;
 	pos.x += 393;
 	used = RCLICK;
 
 	type = Type;
-	bg = new CPicture(BitmapHandler::loadBitmap("GSELPOP1.bmp"), 0, 0, true);
-	pos.w = bg->pos.w;
-	pos.h = bg->pos.h;
 
-	if(type != CMenuScreen::campaignList)
+	if(type == CMenuScreen::campaignList)
 	{
+		/*bg = new CPicture(BitmapHandler::loadBitmap("CamCust.bmp"), 0, 0, true);
+		bg->pos.x = 0;
+		bg->pos.y = 0;*/
+	}
+	else
+	{
+		bg = new CPicture(BitmapHandler::loadBitmap("GSELPOP1.bmp"), 0, 0, true);
+		pos.w = bg->pos.w;
+		pos.h = bg->pos.h;
 		sizes = CDefHandler::giveDef("SCNRMPSZ.DEF");
 		sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
 
@@ -1104,6 +1141,8 @@ void InfoCard::showAll( SDL_Surface * to )
 				break;
 			}
 			blitAtLoc(sizes->ourImages[temp].bitmap, 318, 22, to);
+
+			//conditions
 			temp = curMap->mapHeader->victoryCondition.condition;
 			if (temp>12) temp=11;
 			blitAtLoc(CGP->victory->ourImages[temp].bitmap, 24, 302, to); //victory cond descr
@@ -1928,4 +1967,110 @@ void CHotSeatPlayers::enterSelectionScreen()
 
 	GH.popInts(2);
 	GH.pushInt(new CSelectionScreen(CMenuScreen::newGame, playerNames));
+}
+
+CBonusSelection::CBonusSelection( const CCampaign * ourCampaign, int whichMap )
+{
+	OBJ_CONSTRUCTION;
+	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"};
+	
+	background = BitmapHandler::loadBitmap(bgNames[ourCampaign->header.mapVersion]);
+
+	SDL_Surface * panel = BitmapHandler::loadBitmap("CAMPBRF.BMP");
+
+	blitAt(panel, 456, 6, background);
+
+	startB = new AdventureMapButton("", "", 0 /*cb*/, 475, 536, "SCNRBEG.DEF", SDLK_RETURN);
+	backB = new AdventureMapButton("", "", boost::bind(&CBonusSelection::goBack, this), 624, 536, "SCNRBACK.DEF", SDLK_ESCAPE);
+
+	CMapHeader ourHeader;
+	int _it=0;
+	ourHeader.initFromMemory((const unsigned char*)ourCampaign->mapPieces[whichMap].c_str(), _it);
+
+	//campaign name
+	if (ourCampaign->header.name.length())
+		printAtLoc(ourCampaign->header.name, 481, 28, FONT_BIG, tytulowy, background);
+	else 
+		printAtLoc("Unnamed", 481, 28, FONT_BIG, tytulowy, background);
+
+	//map size icon
+	CDefHandler *sizes = CDefHandler::giveDef("SCNRMPSZ.DEF");
+	int temp;
+	switch (ourHeader.width)
+	{
+	case 36:
+		temp=0;
+		break;
+	case 72:
+		temp=1;
+		break;
+	case 108:
+		temp=2;
+		break;
+	case 144:
+		temp=3;
+		break;
+	default:
+		temp=4;
+		break;
+	}
+	blitAtLoc(sizes->ourImages[temp].bitmap, 735, 26, background);
+	delete sizes;
+
+	//campaign description
+	printAtLoc(CGI->generaltexth->allTexts[38], 481, 63, FONT_SMALL, tytulowy, background);
+
+	std::vector<std::string> *desc = CMessage::breakText(ourCampaign->header.description, 45);
+	for (int i=0; i<desc->size() ;i++)
+		printAtLoc((*desc)[i], 481, 86 + i*16, FONT_SMALL, zwykly, background);
+	delete desc;
+
+	//map name
+	std::string mapDesc = ourHeader.description, mapName = ourHeader.name;
+
+	if (mapName.length())
+		printAtLoc(mapName, 481, 219, FONT_BIG, tytulowy, background);
+	else 
+		printAtLoc("Unnamed", 481, 219, FONT_BIG, tytulowy, background);
+
+	//map description
+	printAtLoc(CGI->generaltexth->allTexts[496], 481, 253, FONT_SMALL, tytulowy, background);
+
+	desc = CMessage::breakText(mapDesc, 45);
+	for (int i=0; i<desc->size(); i++)
+		printAtLoc((*desc)[i], 481, 281 + i*16, FONT_SMALL, zwykly, background);
+	delete desc;
+
+	//allies / enemies
+	printAtLoc(CGI->generaltexth->allTexts[390] + ":", 486, 407, FONT_SMALL, zwykly, background); //Allies
+	printAtLoc(CGI->generaltexth->allTexts[391] + ":", 619, 407, FONT_SMALL, zwykly, background); //Enemies
+	int fx=64, ex=244, myT;
+	myT = ourHeader.players[playerColor].team;
+	/*for (std::vector<PlayerSettings>::const_iterator i = curOpts->playerInfos.begin(); i != curOpts->playerInfos.end(); i++)
+	{
+		int *myx = ((i->color == playerColor  ||  ourHeader.players[i->color].team == myT) ? &fx : &ex);
+		blitAtLoc(sFlags->ourImages[i->color].bitmap, *myx, 399, to);
+		*myx += sFlags->ourImages[i->color].bitmap->w;
+	}*/
+
+	SDL_FreeSurface(panel);
+	
+}
+
+CBonusSelection::~CBonusSelection()
+{
+	SDL_FreeSurface(background);
+}
+
+void CBonusSelection::goBack()
+{
+	GH.popIntTotally(this);
+}
+
+void CBonusSelection::showAll( SDL_Surface * to )
+{
+	CIntObject::showAll(to);
+	blitAt(background, pos.x, pos.y, to);
 }

+ 16 - 0
client/CPreGame.h

@@ -21,6 +21,7 @@ struct CMusicHandler;
 class CMapHeader;
 class CCampaignHeader;
 class CTextInput;
+class CCampaign;
 class CGStatusBar;
 
 class CMapInfo
@@ -212,6 +213,7 @@ public:
 	void toggleTab(CIntObject *tab);
 	void changeSelection(const CMapInfo *to);
 	void updateStartInfo(const CMapInfo * to);
+	void startCampaign();
 	void startGame();
 	void difficultyChange(int to);
 };
@@ -251,6 +253,20 @@ public:
 	void enterSelectionScreen();
 };
 
+class CBonusSelection : public CIntObject
+{
+	SDL_Surface * background;
+	AdventureMapButton * startB, * backB;
+public:
+	CBonusSelection(const CCampaign * ourCampaign, int whichMap);
+	~CBonusSelection();
+
+	void showAll(SDL_Surface * to);
+
+	void goBack();
+	void startMap();
+};
+
 class CGPreGame : public CIntObject, public IUpdateable
 {
 public:

+ 18 - 7
hch/CCampaignHandler.cpp

@@ -73,7 +73,7 @@ CCampaign * CCampaignHandler::getCampaign( const std::string & name )
 	int howManyScenarios = VLC->generaltexth->campaignRegionNames[ret->header.mapVersion].size();
 	for(int g=0; g<howManyScenarios; ++g)
 	{
-		CCampaignScenario sc = readScenarioFromMemory(cmpgn, it);
+		CCampaignScenario sc = readScenarioFromMemory(cmpgn, it, ret->header.version);
 		ret->scenarios.push_back(sc);
 	}
 
@@ -109,6 +109,7 @@ CCampaignHeader CCampaignHandler::readHeaderFromMemory( const unsigned char *buf
 	CCampaignHeader ret;
 	ret.version = readNormalNr(buffer, outIt); outIt+=4;
 	ret.mapVersion = readChar(buffer, outIt);
+	ret.mapVersion -= 1; //change range of it from [1, 20] to [0, 19]
 	ret.name = readString(buffer, outIt);
 	ret.description = readString(buffer, outIt);
 	ret.difficultyChoosenByPlayer = readChar(buffer, outIt);
@@ -121,7 +122,7 @@ CCampaignHeader CCampaignHandler::readHeaderFromMemory( const unsigned char *buf
 	return ret;
 }
 
-CCampaignScenario CCampaignHandler::readScenarioFromMemory( const unsigned char *buffer, int & outIt )
+CCampaignScenario CCampaignHandler::readScenarioFromMemory( const unsigned char *buffer, int & outIt, int version )
 {
 	struct HLP
 	{
@@ -149,20 +150,30 @@ CCampaignScenario CCampaignHandler::readScenarioFromMemory( const unsigned char
 	ret.prolog = HLP::prologEpilogReader(buffer, outIt);
 	ret.epilog = HLP::prologEpilogReader(buffer, outIt);
 
-	ret.travelOptions = readScenarioTravelFromMemory(buffer, outIt);
+	ret.travelOptions = readScenarioTravelFromMemory(buffer, outIt, version);
 
 	return ret;
 }
 
-CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const unsigned char * buffer, int & outIt )
+CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const unsigned char * buffer, int & outIt , int version )
 {
 	CScenarioTravel ret;
 
 	ret.whatHeroKeeps = buffer[outIt++];
 	memcpy(ret.monstersKeptByHero, buffer+outIt, ARRAY_COUNT(ret.monstersKeptByHero));
 	outIt += ARRAY_COUNT(ret.monstersKeptByHero);
-	memcpy(ret.artifsKeptByHero, buffer+outIt, ARRAY_COUNT(ret.artifsKeptByHero));
-	outIt += ARRAY_COUNT(ret.artifsKeptByHero);
+	int artifBytes;
+	if (version == 5) //AB
+	{
+		artifBytes = 17;
+		ret.artifsKeptByHero[17] = 0;
+	} 
+	else //SoD+
+	{
+		artifBytes = 18;
+	}
+	memcpy(ret.artifsKeptByHero, buffer+outIt, artifBytes);
+	outIt += artifBytes;
 
 	ret.startOptions = buffer[outIt++];
 	
@@ -205,7 +216,7 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const unsigned c
 				case 4: //spell scroll
 					{
 						bonus.info1 = readNormalNr(buffer, outIt, 2); outIt += 2; //hero
-						bonus.info2 = readNormalNr(buffer, outIt, 2); outIt += 2; //spell ID
+						bonus.info2 = buffer[outIt++]; //spell ID
 						break;
 					}
 				case 5: //prim skill

+ 4 - 4
hch/CCampaignHandler.h

@@ -112,15 +112,15 @@ public:
 class DLL_EXPORT CCampaignHandler
 {
 	static CCampaignHeader readHeaderFromMemory( const unsigned char *buffer, int & outIt );
-	static CCampaignScenario readScenarioFromMemory( const unsigned char *buffer, int & outIt );
-	static CScenarioTravel readScenarioTravelFromMemory( const unsigned char * buffer, int & outIt );
+	static CCampaignScenario readScenarioFromMemory( const unsigned char *buffer, int & outIt, int version );
+	static CScenarioTravel readScenarioTravelFromMemory( const unsigned char * buffer, int & outIt , int version);
 	static std::vector<ui32> locateH3mStarts(const unsigned char * buffer, int start, int size);
 	static bool startsAt( const unsigned char * buffer, int size, int pos ); //a simple heuristic that checks if a h3m starts at given pos
 public:
 	static std::vector<CCampaignHeader> getCampaignHeaders();
-	static CCampaignHeader getHeader( const std::string & name );
+	static CCampaignHeader getHeader( const std::string & name ); //name - name of appropriate file
 
-	static CCampaign * getCampaign(const std::string & name);
+	static CCampaign * getCampaign(const std::string & name); //name - name of appropriate file
 };