1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* 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
This commit is contained in:
Michał W. Urbańczyk 2012-02-22 13:41:27 +00:00
parent 08417cd42a
commit e18419f5d2
8 changed files with 111 additions and 59 deletions

View File

@ -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;

View File

@ -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;

View File

@ -962,6 +962,8 @@ void CInfoBar::tick()
toNextTick = -1;
mode = NOTHING;
}
if(adventureInt == GH.topInt())
redraw();
}
@ -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,8 +1251,13 @@ void CAdvMapInt::activate()
tlog1 << "Error: advmapint already active...\n";
return;
}
active |= GENERAL;
screenBuf = screen;
GH.statusbar = &statusbar;
if(!duringAITurn)
{
//assert(selection);
activateMouseMove();
kingOverview.activate();
@ -1273,7 +1281,11 @@ void CAdvMapInt::activate()
LOCPLINT->cingconsole->activate();
GH.fakeMouseMove(); //to restore the cursor
}
}
void CAdvMapInt::deactivate()
{
active &= ~GENERAL;
if(!duringAITurn)
{
deactivateMouseMove();
scrollingDir = 0;
@ -1298,6 +1310,7 @@ void CAdvMapInt::deactivate()
if(LOCPLINT->cingconsole->active) //TODO
LOCPLINT->cingconsole->deactivate();
}
}
void CAdvMapInt::showAll(SDL_Surface * to)
{
blitAt(bg,0,0,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;

View File

@ -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);

View File

@ -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,15 +2364,23 @@ void CPlayerInterface::playerStartsTurn(ui8 player)
{
waitWhileDialog();
boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->minimap.redraw();
adventureInt->infoBar.enemyTurn(player, 0.5);
//TODO AI turn music
//TODO block GUI
adventureInt->aiTurnStarted();
}
}
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()
{
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;

View File

@ -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)

View File

@ -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)

View File

@ -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