浏览代码

Little more work on pregame. Fixed some leaks.
Fixed: #80, #159, #234, #235, #319, #320, #430

Michał W. Urbańczyk 15 年之前
父节点
当前提交
3699786ab0
共有 8 个文件被更改,包括 137 次插入23 次删除
  1. 4 2
      client/AdventureMapButton.cpp
  2. 1 1
      client/CAdvmapInterface.cpp
  3. 1 4
      client/CPlayerInterface.cpp
  4. 100 13
      client/CPreGame.cpp
  5. 13 1
      client/CPreGame.h
  6. 9 1
      client/GUIClasses.cpp
  7. 2 1
      client/GUIClasses.h
  8. 7 0
      global.h

+ 4 - 2
client/AdventureMapButton.cpp

@@ -131,10 +131,12 @@ void AdventureMapButton::clickLeft(tribool down, bool previousState)
 	if (down) 
 	{
 		CGI->soundh->playSound(soundBase::button);
-		state=1;
+		state = 1;
 	} 
+	else if(hoverable && hovered)
+		state = 3;
 	else
-		state=0;
+		state = 0;
 
 	show(screenBuf);
 	if (actOnDown && down)

+ 1 - 1
client/CAdvmapInterface.cpp

@@ -1830,7 +1830,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
 		return;
 	case SDLK_s: 
 		if(isActive())
-			GH.pushInt(new CSelectionScreen(CMenuScreen::saveGame));
+			GH.pushInt(new CSavingScreen);
 		return;
 	case SDLK_d: 
 		{

+ 1 - 4
client/CPlayerInterface.cpp

@@ -852,10 +852,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 	if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement
 		stillMoveHero.setn(STOP_MOVE); //after showing dialog movement will be stopped
 
-	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
-	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
-	CInfoWindow * temp = new CInfoWindow(text,playerID,0,components,pom,false);
-
+	CInfoWindow *temp = CInfoWindow::create(text, playerID, &components);
 	if(makingTurn && GH.listInt.size() && LOCPLINT == this)
 	{
 		CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));

+ 100 - 13
client/CPreGame.cpp

@@ -69,6 +69,28 @@ static void do_quit()
 	SDL_PushEvent(&event);
 }
 
+static CMapInfo *mapInfoFromGame()
+{
+	CMapInfo *ret = new CMapInfo();
+	CMapHeader *headerCopy = new CMapHeader(*LOCPLINT->cb->getMapHeader()); //will be deleted by CMapInfo d-tor
+	ret->setHeader(headerCopy);
+	return ret;
+}
+
+static void setPlayersFromGame()
+{
+	playerColor = LOCPLINT->playerID;
+	playerSerial = LOCPLINT->serialID;
+}
+
+static void clearInfo()
+{
+	delNull(curMap);
+	delNull(curOpts);
+	playerColor = playerSerial = -1;
+	playerNames.clear();
+}
+
 void CMapInfo::countPlayers()
 {
 	actualHumanPlayers = playerAmnt = humenPlayers = 0;
@@ -133,6 +155,11 @@ void CMapInfo::campaignInit()
 	campaignHeader = new CCampaignHeader( CCampaignHandler::getHeader(filename, lodCmpgn) );
 }
 
+void CMapInfo::setHeader(CMapHeader *header)
+{
+	mapHeader = header;
+}
+
 CMenuScreen::CMenuScreen( EState which )
 {
 	OBJ_CONSTRUCTION;
@@ -404,7 +431,7 @@ void CSelectionScreen::changeSelection( const CMapInfo *to )
 
 	if(to && type == CMenuScreen::loadGame)
 		curOpts->difficulty = to->scenarioOpts->difficulty;
-	if(type != CMenuScreen::campaignList)
+	if(type != CMenuScreen::campaignList && type != CMenuScreen::saveGame)
 	{
 		updateStartInfo(to, sInfo, to ? to->mapHeader : NULL);
 	}
@@ -457,7 +484,10 @@ void CSelectionScreen::updateStartInfo( const CMapInfo * to, StartInfo & sInfo,
 		PlayerSettings &pset = sInfo.playerInfos[serialC];
 		pset.color = i;
 		pset.serial = serialC++;
-		setPlayer(pset, placedPlayers++);
+		if(pinfo.canHumanPlay)
+			setPlayer(pset, placedPlayers++);
+		else
+			setPlayer(pset, -1);
 
 		for (int j = 0; j < F_NUMBER  &&  pset.castle != -1; j++) //we start with none and find matching faction. if more than one, then set to random
 		{
@@ -495,6 +525,21 @@ void CSelectionScreen::startCampaign()
 
 void CSelectionScreen::startGame()
 {
+	if(type == CMenuScreen::newGame)
+	{
+		//there must be at least one human player before game can be started
+		std::vector<PlayerSettings>::const_iterator i;
+		for(i = curOpts->playerInfos.begin(); i != curOpts->playerInfos.end(); i++)
+			if(i->human)
+				break;
+
+		if(i == curOpts->playerInfos.end())
+		{
+			GH.pushInt(CInfoWindow::create(CGI->generaltexth->allTexts[530])); //You must position yourself prior to starting the game.
+			return;
+		}
+	}
+
 	if(type != CMenuScreen::saveGame)
 	{
 		if(!current)
@@ -502,8 +547,8 @@ void CSelectionScreen::startGame()
 
 		selectedName = sInfo.mapname;
 		StartInfo *si = new StartInfo(sInfo);
-		GH.popInt(this);
-		GH.popInt(GH.topInt());
+		GH.popIntTotally(this); //delete me
+		GH.popInt(GH.topInt()); //only deactivate main menu screen
 		//curMap = NULL;
 		curOpts = NULL;
 		::startGame(si);
@@ -514,8 +559,22 @@ void CSelectionScreen::startGame()
 			return;
 
 		selectedName = GVCMIDirs.UserPath + "/Games/" + sel->txt->text + ".vlgm1";
-		LOCPLINT->cb->save(sel->txt->text);
-		GH.popInt(this);
+
+		CFunctionList<void()> overWrite;
+		overWrite += bind(&CCallback::save, LOCPLINT->cb, sel->txt->text);
+		overWrite += bind(&CGuiHandler::popIntTotally, &GH, this);
+
+		if(fs::exists(selectedName))
+		{
+			std::string hlp = CGI->generaltexth->allTexts[493]; //%s exists. Overwrite?
+			boost::algorithm::replace_first(hlp, "%s", sel->txt->text);
+			LOCPLINT->showYesNoDialog(hlp, std::vector<SComponent*>(), overWrite, 0, false);
+		}
+		else
+			overWrite();
+
+// 		LOCPLINT->cb->save(sel->txt->text);
+// 		GH.popIntTotally(this);
 	}
 }
 
@@ -787,7 +846,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
 	case CMenuScreen::saveGame:;
 		if(selectedName.size())
 		{
-			if(selectedName[0] == 'M')
+			if(selectedName[2] == 'M') //name starts with ./Maps instead of ./Games => there was nothing to select
 				txt->setText("NEWGAME");
 			else
 				selectFName(selectedName);
@@ -844,6 +903,9 @@ void SelectionTab::select( int position )
 	else if(position >= positions)
 		slider->moveTo(slider->value + position - positions + 1);
 
+	if(txt)
+		txt->setText(fs::basename(curItems[py]->filename));
+
 	onSelect(curItems[py]);
 }
 
@@ -1641,6 +1703,15 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry( OptionsTab *owner, PlayerSet
 	fixedHero = s.hero != -1; //if we doesn't start with "random hero" it must be fixed or none
 	selectButtons(false);
 
+	assert(curMap && curMap->mapHeader);
+	const PlayerInfo &p = curMap->mapHeader->players[s.color];
+	assert(p.canComputerPlay || p.canHumanPlay); //someone must be able to control this player
+	if(p.canHumanPlay && p.canComputerPlay)
+		whoCanPlay = HUMAN_OR_CPU;
+	else if(p.canComputerPlay)
+		whoCanPlay = CPU;
+	else
+		whoCanPlay = HUMAN;
 
 	if(owner->type != CMenuScreen::scenarioInfo  &&  curMap->mapHeader->players[s.color].canHumanPlay)
 	{
@@ -1663,6 +1734,7 @@ void OptionsTab::PlayerOptionsEntry::showAll( SDL_Surface * to )
 {
 	CIntObject::showAll(to);
 	printAtMiddleLoc(s.name, 55, 10, FONT_SMALL, zwykly, to);
+	printAtMiddleWBLoc(CGI->generaltexth->arraytxt[206+whoCanPlay], 28, 34, FONT_TINY, 6, zwykly, to);
 }
 
 void OptionsTab::PlayerOptionsEntry::selectButtons(bool onlyHero)
@@ -1967,7 +2039,7 @@ void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState )
 	GH.pushInt(new CInfoPopup(bmp, true));
 }
 
-CScenarioInfo::CScenarioInfo( const CMapHeader *mapHeader, const StartInfo *startInfo, const CMapInfo * makeItCurrent )
+CScenarioInfo::CScenarioInfo(const CMapHeader *mapHeader, const StartInfo *startInfo)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 
@@ -1984,11 +2056,12 @@ CScenarioInfo::CScenarioInfo( const CMapHeader *mapHeader, const StartInfo *star
 	pos.h = 584;
 	center(pos);
 
-	if(makeItCurrent)
-	{
-		curMap = makeItCurrent;
-	}
-	curOpts = const_cast<StartInfo*>(startInfo); //I hope it's safe
+	assert(LOCPLINT);
+	assert(!curOpts);
+	curOpts = new StartInfo(*LOCPLINT->cb->getStartInfo()); //deleted by clearInfo
+	assert(!curMap);
+	curMap = mapInfoFromGame(); //deleted by clearInfo
+	setPlayersFromGame();
 
 	card = new InfoCard(CMenuScreen::scenarioInfo);
 	opt = new OptionsTab(CMenuScreen::scenarioInfo);
@@ -2000,6 +2073,7 @@ CScenarioInfo::CScenarioInfo( const CMapHeader *mapHeader, const StartInfo *star
 
 CScenarioInfo::~CScenarioInfo()
 {
+	clearInfo();
 }
 
 bool mapSorter::operator()(const CMapInfo *aaa, const CMapInfo *bbb)
@@ -2418,3 +2492,16 @@ void CBonusSelection::CRegion::show( SDL_Surface * to )
 		blitAt(graphics[0], pos.x, pos.y, to);
 	}
 }
+
+CSavingScreen::CSavingScreen()
+ : CSelectionScreen(CMenuScreen::saveGame)
+{
+	ourGame = mapInfoFromGame();
+	sInfo = *LOCPLINT->cb->getStartInfo();
+	setPlayersFromGame();
+}
+
+CSavingScreen::~CSavingScreen()
+{
+
+}

+ 13 - 1
client/CPreGame.h

@@ -39,6 +39,7 @@ public:
 	CMapInfo(bool map = true);
 	~CMapInfo();
 	//CMapInfo(const std::string &fname, const unsigned char *map);
+	void setHeader(CMapHeader *header);
 	void mapInit(const std::string &fname, const unsigned char *map);
 	void campaignInit();
 	void countPlayers();
@@ -169,6 +170,7 @@ public:
 		SelectedBox *hero;
 		SelectedBox *bonus;
 		bool fixedHero;
+		enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay;
 		
 		PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
 		void selectButtons(bool onlyHero = true); //hides unavailable buttons
@@ -222,6 +224,16 @@ public:
 	void difficultyChange(int to);
 };
 
+class CSavingScreen : public CSelectionScreen
+{
+public:
+	const CMapInfo *ourGame; 
+
+
+	CSavingScreen();
+	~CSavingScreen();
+};
+
 class CScenarioInfo : public CIntObject
 {
 public:
@@ -229,7 +241,7 @@ public:
 	InfoCard *card;
 	OptionsTab *opt;
 
-	CScenarioInfo(const CMapHeader *mapHeader, const StartInfo *startInfo, const CMapInfo * makeItCurrent=NULL);
+	CScenarioInfo(const CMapHeader *mapHeader, const StartInfo *startInfo);
 	~CScenarioInfo();
 };
 

+ 9 - 1
client/GUIClasses.cpp

@@ -740,6 +740,14 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector<SC
 	GH.pushInt(temp);
 }
 
+CInfoWindow * CInfoWindow::create(const std::string &text, int playerID /*= 1*/, const std::vector<SComponent*> *components /*= NULL*/)
+{
+	std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
+	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
+	CInfoWindow * ret = new CInfoWindow(text, playerID, 0, components ? *components : std::vector<SComponent*>(), pom, false);
+	return ret;
+}
+
 void CRClickPopup::clickRight(tribool down, bool previousState)
 {
 	if(down)
@@ -3002,7 +3010,7 @@ void CSystemOptionsWindow::bmainmenuf()
 void CSystemOptionsWindow::bsavef()
 {
 	GH.popIntTotally(this);
-	GH.pushInt(new CSelectionScreen(CMenuScreen::saveGame));
+	GH.pushInt(new CSavingScreen);
 	/*using namespace boost::posix_time;
 	std::ostringstream fnameStream;
 	fnameStream << second_clock::local_time();

+ 2 - 1
client/GUIClasses.h

@@ -83,7 +83,8 @@ public:
 	CInfoWindow(); //c-tor
 	~CInfoWindow(); //d-tor
 
-	static void showYesNoDialog( const std::string & text, const std::vector<SComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps, int player); //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
+	static void showYesNoDialog( const std::string & text, const std::vector<SComponent*> *components, const CFunctionList<void( ) > &onYes, const CFunctionList<void()> &onNo, bool DelComps = true, int player = 1); //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then)
+	static CInfoWindow *create(const std::string &text, int playerID = 1, const std::vector<SComponent*> *components = NULL);
 };
 class CSelWindow : public CInfoWindow //component selection window
 { //warning - this window deletes its components by closing!

+ 7 - 0
global.h

@@ -288,6 +288,13 @@ t1 & abetw(t1 &a, const t2 &b, const t3 &c) //makes a to fit the range <b, c>
 	return a;
 }
 
+template <typename T> 
+void delNull(T* &ptr) //deleted pointer and sets it to NULL
+{
+	delete ptr;
+	ptr = NULL;
+}
+
 #include "CConsoleHandler.h"
 extern DLL_EXPORT std::ostream *logfile;
 extern DLL_EXPORT CConsoleHandler *console;