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; *(int*)NULL = 666;
} }
if(makingTurn) finish();
makingTurn->interrupt();
} }
} }
@ -1257,10 +1256,10 @@ bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h)
//tlog0 << "Moving " << h->name << " from " << h->getPosition() << " to " << endpos << std::endl; //tlog0 << "Moving " << h->name << " from " << h->getPosition() << " to " << endpos << std::endl;
cb->moveHero(h,CGHeroInstance::convertPosition(endpos, true)); cb->moveHero(h,CGHeroInstance::convertPosition(endpos, true));
waitTillFree(); //movement may cause battle or blocking dialog waitTillFree(); //movement may cause battle or blocking dialog
boost::this_thread::interruption_point();
if(h->tempOwner != playerID) //we lost hero if(h->tempOwner != playerID) //we lost hero
break; break;
boost::this_thread::interruption_point();
} }
ret = !i; ret = !i;
} }
@ -1662,6 +1661,12 @@ void VCAI::recruitHero(const CGTownInstance * t)
cb->recruitHero(t, cb->getAvailableHeroes(t).front()); cb->recruitHero(t, cb->getAvailableHeroes(t).front());
} }
void VCAI::finish()
{
if(makingTurn)
makingTurn->interrupt();
}
AIStatus::AIStatus() AIStatus::AIStatus()
{ {
battle = NO_BATTLE; 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 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(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading virtual void serialize(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading
virtual void finish() OVERRIDE;
virtual void availableCreaturesChanged(const CGDwelling *town) OVERRIDE; virtual void availableCreaturesChanged(const CGDwelling *town) OVERRIDE;
virtual void heroMoved(const TryMoveHero & details) OVERRIDE; virtual void heroMoved(const TryMoveHero & details) OVERRIDE;

View File

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

View File

@ -183,6 +183,7 @@ public:
int3 position; //top left corner of visible map part int3 position; //top left corner of visible map part
int player; int player;
bool duringAITurn;
enum{LEFT=1, RIGHT=2, UP=4, DOWN=8}; enum{LEFT=1, RIGHT=2, UP=4, DOWN=8};
ui8 scrollingDir; //uses enum: LEFT RIGHT, UP, DOWN ui8 scrollingDir; //uses enum: LEFT RIGHT, UP, DOWN
@ -255,6 +256,9 @@ public:
void startHotSeatWait(int Player); void startHotSeatWait(int Player);
void startTurn(); void startTurn();
void endingTurn(); 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 tileLClicked(const int3 &mp);
void tileHovered(const int3 &tile); void tileHovered(const int3 &tile);
void tileRClicked(const int3 &mp); void tileRClicked(const int3 &mp);

View File

@ -577,11 +577,9 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
return; return;
} }
while(showingDialog->get()) waitForAllDialogs();
SDL_Delay(20);
boost::unique_lock<boost::recursive_mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
GH.pushInt(battleInt); GH.pushInt(battleInt);
} }
@ -1258,12 +1256,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
return; return;
} }
{ waitWhileDialog();
boost::unique_lock<boost::mutex> un(showingDialog->mx);
while(showingDialog->data)
showingDialog->cond.wait(un);
}
boost::unique_lock<boost::recursive_mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
while(dialogs.size()) while(dialogs.size())
{ {
@ -1475,7 +1468,7 @@ void CPlayerInterface::update()
if(terminate_cond.get()) if(terminate_cond.get())
return; 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 //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()); boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex());
@ -2371,15 +2364,23 @@ void CPlayerInterface::playerStartsTurn(ui8 player)
{ {
waitWhileDialog(); waitWhileDialog();
boost::unique_lock<boost::recursive_mutex> un(*pim); 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() CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
{ {
spellbookLastPageBattle = spellbokLastPageAdvmap = 0; spellbookLastPageBattle = spellbokLastPageAdvmap = 0;

View File

@ -199,6 +199,7 @@ public:
void garrisonChanged(const CGObjectInstance * obj, bool updateInfobox = true); void garrisonChanged(const CGObjectInstance * obj, bool updateInfobox = true);
void heroKilled(const CGHeroInstance* hero); void heroKilled(const CGHeroInstance* hero);
void waitWhileDialog(); void waitWhileDialog();
void waitForAllDialogs();
bool shiftPressed() const; //determines if shift key is pressed (left or right or both) 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 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) 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*/ ) 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 // Game is ending
// Tell the network thread to reach a stable state // Tell the network thread to reach a stable state
if(closeConnection) 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 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(COSer<CSaveFile> &h, const int version){}; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading 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 class DLL_LINKAGE CDynLibHandler