فهرست منبع

* adventure map GUI should be properly blocked during AI turn
* battle window will wait till all dialogs are closed
* fixed problems with AI working after the game ended
* fixed problems with overzealous redrawing of infobar

Michał W. Urbańczyk 13 سال پیش
والد
کامیت
e18419f5d2
8فایلهای تغییر یافته به همراه112 افزوده شده و 60 حذف شده
  1. 8 3
      AI/VCAI/VCAI.cpp
  2. 1 0
      AI/VCAI/VCAI.h
  3. 77 42
      client/CAdvmapInterface.cpp
  4. 4 0
      client/CAdvmapInterface.h
  5. 16 15
      client/CPlayerInterface.cpp
  6. 1 0
      client/CPlayerInterface.h
  7. 4 0
      client/Client.cpp
  8. 1 0
      lib/CGameInterface.h

+ 8 - 3
AI/VCAI/VCAI.cpp

@@ -469,8 +469,7 @@ void VCAI::gameOver(ui8 player, bool victory)
 			*(int*)NULL = 666;
 		}
 
-		if(makingTurn)
-			makingTurn->interrupt();
+		finish();
 	}
 }
 
@@ -1257,10 +1256,10 @@ bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h)
 			//tlog0 << "Moving " << h->name << " from " << h->getPosition() << " to " << endpos << std::endl;
 			cb->moveHero(h,CGHeroInstance::convertPosition(endpos, true));
 			waitTillFree(); //movement may cause battle or blocking dialog
+			boost::this_thread::interruption_point();
 			if(h->tempOwner != playerID) //we lost hero
 				break;
 
-			boost::this_thread::interruption_point();
 		}
 		ret = !i;
 	}
@@ -1662,6 +1661,12 @@ void VCAI::recruitHero(const CGTownInstance * t)
 	cb->recruitHero(t, cb->getAvailableHeroes(t).front());
 }
 
+void VCAI::finish()
+{
+	if(makingTurn)
+		makingTurn->interrupt();
+}
+
 AIStatus::AIStatus()
 {
 	battle = NO_BATTLE;

+ 1 - 0
AI/VCAI/VCAI.h

@@ -185,6 +185,7 @@ public:
 	virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) OVERRIDE; //all stacks operations between these objects become allowed, interface has to call onEnd when done
 	virtual void serialize(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving
 	virtual void serialize(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading
+	virtual void finish() OVERRIDE;
 
 	virtual void availableCreaturesChanged(const CGDwelling *town) OVERRIDE;
 	virtual void heroMoved(const TryMoveHero & details) OVERRIDE;

+ 77 - 42
client/CAdvmapInterface.cpp

@@ -962,7 +962,9 @@ void CInfoBar::tick()
 		toNextTick = -1;
 		mode = NOTHING;
 	}
-	redraw();
+
+	if(adventureInt == GH.topInt())
+		redraw();
 }
 
 void CInfoBar::show(SDL_Surface * to)
@@ -1042,6 +1044,7 @@ endTurn(CGI->generaltexth->zelp[302].first,CGI->generaltexth->zelp[302].second,
 heroList(ADVOPT.hlistSize),
 townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlistAD)//(5,&genRect(192,48,747,196),747,196,747,372),
 {
+	duringAITurn = false;
 	state = NA;
 	spellBeingCasted = NULL;
 	pos.x = pos.y = 0;
@@ -1248,55 +1251,65 @@ void CAdvMapInt::activate()
 		tlog1 << "Error: advmapint already active...\n";
 		return;
 	}
+	active |= GENERAL;
+
 	screenBuf = screen;
 	GH.statusbar = &statusbar;
-	activateMouseMove();
+	if(!duringAITurn)
+	{
+		//assert(selection);
+		activateMouseMove();
 
-	kingOverview.activate();
-	underground.activate();
-	questlog.activate();
-	sleepWake.activate();
-	moveHero.activate();
-	spellbook.activate();
-	sysOptions.activate();
-	advOptions.activate();
-	nextHero.activate();
-	endTurn.activate();
-
-	minimap.activate();
-	heroList.activate();
-	townList.activate();
-	terrain.activate();
-	infoBar.activate();
+		kingOverview.activate();
+		underground.activate();
+		questlog.activate();
+		sleepWake.activate();
+		moveHero.activate();
+		spellbook.activate();
+		sysOptions.activate();
+		advOptions.activate();
+		nextHero.activate();
+		endTurn.activate();
 
-	if(!LOCPLINT->cingconsole->active)
-		LOCPLINT->cingconsole->activate();
-	GH.fakeMouseMove(); //to restore the cursor
+		minimap.activate();
+		heroList.activate();
+		townList.activate();
+		terrain.activate();
+		infoBar.activate();
+
+		if(!LOCPLINT->cingconsole->active)
+			LOCPLINT->cingconsole->activate();
+		GH.fakeMouseMove(); //to restore the cursor
+	}
 }
 void CAdvMapInt::deactivate()
 {
-	deactivateMouseMove();
-	scrollingDir = 0;
-
-	CCS->curh->changeGraphic(0,0);
-	kingOverview.deactivate();
-	underground.deactivate();
-	questlog.deactivate();
-	sleepWake.deactivate();
-	moveHero.deactivate();
-	spellbook.deactivate();
-	advOptions.deactivate();
-	sysOptions.deactivate();
-	nextHero.deactivate();
-	endTurn.deactivate();
-	minimap.deactivate();
-	heroList.deactivate();
-	townList.deactivate();
-	terrain.deactivate();
-	infoBar.deactivate();
+	active &= ~GENERAL;
+	if(!duringAITurn)
+	{
+		deactivateMouseMove();
+		scrollingDir = 0;
 
-	if(LOCPLINT->cingconsole->active) //TODO
-		LOCPLINT->cingconsole->deactivate();
+		CCS->curh->changeGraphic(0,0);
+		kingOverview.deactivate();
+		underground.deactivate();
+		questlog.deactivate();
+		sleepWake.deactivate();
+		moveHero.deactivate();
+		spellbook.deactivate();
+		advOptions.deactivate();
+		sysOptions.deactivate();
+		nextHero.deactivate();
+		endTurn.deactivate();
+		minimap.deactivate();
+		heroList.deactivate();
+		townList.deactivate();
+		terrain.deactivate();
+		infoBar.deactivate();
+
+		if(LOCPLINT->cingconsole->active) //TODO
+			LOCPLINT->cingconsole->deactivate();
+	}
 }
 void CAdvMapInt::showAll(SDL_Surface * to)
 {
@@ -1715,6 +1728,10 @@ void CAdvMapInt::setPlayer(int Player)
 void CAdvMapInt::startTurn()
 {
 	state = INGAME;
+	if(LOCPLINT->cb->getCurrentPlayer() == LOCPLINT->playerID)
+	{
+		adjustActiveness(false);
+	}
 }
 
 void CAdvMapInt::endingTurn()
@@ -2086,6 +2103,24 @@ const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *ob
 	return ret;
 }
 
+void CAdvMapInt::aiTurnStarted()
+{
+	adjustActiveness(true);
+	CCS->musich->playMusicFromSet(CCS->musich->aiMusics);
+	adventureInt->minimap.redraw();
+	adventureInt->infoBar.enemyTurn(LOCPLINT->cb->getCurrentPlayer(), 0.5);
+}
+
+void CAdvMapInt::adjustActiveness(bool aiTurnStart)
+{
+	bool wasActive = isActive();
+
+	if(wasActive) 
+		deactivate();
+	adventureInt->duringAITurn = aiTurnStart;
+	if(wasActive) 
+		activate();
+}
 CAdventureOptions::CAdventureOptions()
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;

+ 4 - 0
client/CAdvmapInterface.h

@@ -183,6 +183,7 @@ public:
 	int3 position; //top left corner of visible map part
 	int player;
 
+	bool duringAITurn;
 
 	enum{LEFT=1, RIGHT=2, UP=4, DOWN=8};
 	ui8 scrollingDir; //uses enum: LEFT RIGHT, UP, DOWN
@@ -255,6 +256,9 @@ public:
 	void startHotSeatWait(int Player);
 	void startTurn();
 	void endingTurn();
+	void aiTurnStarted();
+
+	void adjustActiveness(bool aiTurnStart); //should be called everytime at AI/human turn transition; blocks GUI during AI turn
 	void tileLClicked(const int3 &mp);
 	void tileHovered(const int3 &tile);
 	void tileRClicked(const int3 &mp);

+ 16 - 15
client/CPlayerInterface.cpp

@@ -577,11 +577,9 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
 		return;
 	}
 
-	while(showingDialog->get())
-		SDL_Delay(20);
+	waitForAllDialogs();
 
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-
 	GH.pushInt(battleInt);
 }
 
@@ -1258,12 +1256,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
 		return;
 	}
 
-	{
-		boost::unique_lock<boost::mutex> un(showingDialog->mx);
-		while(showingDialog->data)
-			showingDialog->cond.wait(un);
-	}
-
+	waitWhileDialog();
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	while(dialogs.size())
 	{
@@ -1475,7 +1468,7 @@ void CPlayerInterface::update()
 	if(terminate_cond.get())
 		return;
 
-	boost::unique_lock<boost::recursive_mutex> un(*pim, boost::adopt_lock); //create lock from owned mutex (defer_lock)
+	boost::unique_lock<boost::recursive_mutex> un(*pim, boost::adopt_lock); //create lock from already owned mutex
 	//make sure that gamestate won't change when GUI objects may obtain its parts on event processing or drawing request
 	boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex());
 
@@ -2371,13 +2364,21 @@ void CPlayerInterface::playerStartsTurn(ui8 player)
 	{
 		waitWhileDialog();
 		boost::unique_lock<boost::recursive_mutex> un(*pim);
+		adventureInt->aiTurnStarted();
+	}
+}
 
-		adventureInt->minimap.redraw();
-		adventureInt->infoBar.enemyTurn(player, 0.5);
-
-		//TODO AI turn music
-		//TODO block GUI
+void CPlayerInterface::waitForAllDialogs()
+{
+	{
+		boost::unique_lock<boost::recursive_mutex> un(*pim);
+		while(dialogs.size())
+		{
+			auto unlock = vstd::makeUnlockGuard(*pim);
+			SDL_Delay(5);
+		}
 	}
+	waitWhileDialog();
 }
 
 CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()

+ 1 - 0
client/CPlayerInterface.h

@@ -199,6 +199,7 @@ public:
 	void garrisonChanged(const CGObjectInstance * obj, bool updateInfobox = true);
 	void heroKilled(const CGHeroInstance* hero);
 	void waitWhileDialog();
+	void waitForAllDialogs();
 	bool shiftPressed() const; //determines if shift key is pressed (left or right or both)
 	bool ctrlPressed() const; //determines if ctrl key is pressed (left or right or both)
 	bool altPressed() const; //determines if alt key is pressed (left or right or both)

+ 4 - 0
client/Client.cpp

@@ -180,6 +180,10 @@ void CClient::save(const std::string & fname)
 
 void CClient::endGame( bool closeConnection /*= true*/ )
 {
+	//suggest interfaces to finish their stuff (AI should interrupt any bg working threads)
+	BOOST_FOREACH(auto i, playerint)
+		i.second->finish();
+
 	// Game is ending
 	// Tell the network thread to reach a stable state
 	if(closeConnection)

+ 1 - 0
lib/CGameInterface.h

@@ -78,6 +78,7 @@ public:
 	virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
 	virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
 	virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
+	virtual void finish(){}; //if for some reason we want to end
 };
 
 class DLL_LINKAGE CDynLibHandler