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

#1153 and #1395 should be fixed. Terrible, terrible, terrible.

Fixed crash in battles, when attempted to access <0 screen coordinates.
This commit is contained in:
Michał W. Urbańczyk 2013-09-01 22:55:57 +00:00
parent 708b0c6f47
commit 385f4ab7f5
6 changed files with 53 additions and 31 deletions

View File

@ -351,9 +351,17 @@ void CCallback::castSpell(const CGHeroInstance *hero, SpellID spellID, const int
void CCallback::unregisterMyInterface() void CCallback::unregisterMyInterface()
{ {
ASSERT_IF_CALLED_WITH_PLAYER ASSERT_IF_CALLED_WITH_PLAYER
auto playerInt = cl->playerint[*player];
cl->playerint.erase(*player); cl->playerint.erase(*player);
cl->battleints.erase(*player); cl->battleints.erase(*player);
//TODO? should callback be disabled as well? //TODO? should callback be disabled as well?
//Disabled interface will be deleted very soon, so switch LOCPLINT to next player available
if(playerInt == LOCPLINT && cl->playerint.size())
{
LOCPLINT = dynamic_cast<CPlayerInterface*>(cl->playerint.begin()->second.get());
}
} }
void CCallback::validatePaths() void CCallback::validatePaths()

View File

@ -649,6 +649,7 @@ void CAdvMapInt::deactivate()
townList.deactivate(); townList.deactivate();
terrain.deactivate(); terrain.deactivate();
infoBar.deactivate(); infoBar.deactivate();
if(LOCPLINT)
LOCPLINT->cingconsole->deactivate(); LOCPLINT->cingconsole->deactivate();
} }
} }

View File

@ -129,20 +129,13 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player)
CPlayerInterface::~CPlayerInterface() CPlayerInterface::~CPlayerInterface()
{ {
howManyPeople--; logGlobal->traceStream() << "\tHuman player interface for player " << playerID << " being destructed";
//howManyPeople--;
//delete pim; //delete pim;
//vstd::clear_pointer(pim); //vstd::clear_pointer(pim);
delete showingDialog; delete showingDialog;
if(adventureInt)
{
if(adventureInt->active & CIntObject::KEYBOARD)
adventureInt->deactivateKeyboard();
delete adventureInt;
adventureInt = nullptr;
}
delete cingconsole; delete cingconsole;
if(LOCPLINT == this)
LOCPLINT = nullptr; LOCPLINT = nullptr;
} }
void CPlayerInterface::init(shared_ptr<CCallback> CB) void CPlayerInterface::init(shared_ptr<CCallback> CB)
@ -381,6 +374,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
void CPlayerInterface::heroKilled(const CGHeroInstance* hero) void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
LOG_TRACE_PARAMS(logGlobal, "Hero %s killed handler for player %s", hero->name % playerID);
const CArmedInstance *newSelection = nullptr; const CArmedInstance *newSelection = nullptr;
if (makingTurn) if (makingTurn)
@ -405,9 +399,9 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
paths.erase(hero); paths.erase(hero);
adventureInt->heroList.update(hero); adventureInt->heroList.update(hero);
if (makingTurn) if (makingTurn && newSelection)
adventureInt->select(newSelection, true); adventureInt->select(newSelection, true);
else else if(adventureInt->selection == hero)
adventureInt->selection = nullptr; adventureInt->selection = nullptr;
} }
@ -619,14 +613,11 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
cb->registerBattleInterface(autofightingAI); cb->registerBattleInterface(autofightingAI);
} }
//Don't wait for dialogs when we are non-active hot-seat player
if(LOCPLINT == this)
waitForAllDialogs(); waitForAllDialogs();
if(isAutoFightOn)
GH.topInt()->deactivate();
BATTLE_EVENT_POSSIBLE_RETURN; BATTLE_EVENT_POSSIBLE_RETURN;
GH.pushInt(battleInt);
} }
@ -1569,6 +1560,10 @@ void CPlayerInterface::update()
if(terminate_cond.get()) if(terminate_cond.get())
return; return;
//While mutexes were locked away we may be have stopped being the active interface
if(LOCPLINT != this)
return;
//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());
@ -2067,8 +2062,6 @@ void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &h
void CPlayerInterface::gameOver(PlayerColor player, bool victory ) void CPlayerInterface::gameOver(PlayerColor player, bool victory )
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if(LOCPLINT != this)
return;
if(player == playerID) if(player == playerID)
{ {
@ -2076,17 +2069,30 @@ void CPlayerInterface::gameOver(PlayerColor player, bool victory )
showInfoDialog(CGI->generaltexth->allTexts[95]); showInfoDialog(CGI->generaltexth->allTexts[95]);
// else // else
// showInfoDialog("Placeholder message: you won!"); // showInfoDialog("Placeholder message: you won!");
if(LOCPLINT == this)
makingTurn = true; {
GH.curInt = this; //waiting for dialogs requires this to get events
waitForAllDialogs(); //wait till all dialogs are displayed and closed waitForAllDialogs(); //wait till all dialogs are displayed and closed
makingTurn = false; }
howManyPeople--; howManyPeople--;
if(!howManyPeople //all human players eliminated if(!howManyPeople //all human players eliminated
&& cb->getStartInfo()->mode != StartInfo::CAMPAIGN) //campaigns are handled in proposeNextMission && cb->getStartInfo()->mode != StartInfo::CAMPAIGN) //campaigns are handled in proposeNextMission
{ {
if(adventureInt)
{
terminate_cond.setn(true);
adventureInt->deactivate();
if(GH.topInt() == adventureInt)
GH.popInt(adventureInt);
delete adventureInt;
adventureInt = nullptr;
}
requestReturningToMainMenu(); requestReturningToMainMenu();
} }
if(GH.curInt == this)
GH.curInt = nullptr;
cb->unregisterMyInterface(); //we already won/lost, nothing else matters cb->unregisterMyInterface(); //we already won/lost, nothing else matters
} }

View File

@ -190,7 +190,6 @@ void CClient::endGame( bool closeConnection /*= true*/ )
logNetwork->infoStream() << "Closed connection."; logNetwork->infoStream() << "Closed connection.";
GH.curInt = nullptr; GH.curInt = nullptr;
LOCPLINT->terminate_cond.setn(true);
{ {
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim); boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
logNetwork->infoStream() << "Ending current game!"; logNetwork->infoStream() << "Ending current game!";
@ -606,9 +605,11 @@ void CClient::battleStarted(const BattleInfo * info)
if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL)) if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL))
{ {
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim); boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero,
Rect((screen->w - 800)/2, Rect((screen->w - 800)/2,
(screen->h - 600)/2, 800, 600), att, def); (screen->h - 600)/2, 800, 600), att, def);
GH.pushInt(bi);
} }
auto callBattleStart = [&](PlayerColor color, ui8 side){ auto callBattleStart = [&](PlayerColor color, ui8 side){

View File

@ -401,7 +401,7 @@ ui8 * CCreatureAnimation::getPixelAddr(SDL_Surface * dest, int X, int Y) const
template<int bpp> template<int bpp>
inline void CCreatureAnimation::putPixelAt(SDL_Surface * dest, int X, int Y, size_t index, const std::array<SDL_Color, 8> & special) const inline void CCreatureAnimation::putPixelAt(SDL_Surface * dest, int X, int Y, size_t index, const std::array<SDL_Color, 8> & special) const
{ {
if ( X < pos.x + pos.w && Y < pos.y + pos.h) if ( X < pos.x + pos.w && Y < pos.y + pos.h && X >= 0 && Y >= 0)
putPixel<bpp>(getPixelAddr(dest, X, Y), palette[index], index, special); putPixel<bpp>(getPixelAddr(dest, X, Y), palette[index], index, special);
} }

View File

@ -5135,6 +5135,12 @@ void CGameHandler::checkLossVictory( PlayerColor player )
sendAndApply(&ucs); sendAndApply(&ucs);
} }
} }
//If player making turn has lost his turn must be over as well
if(gs->getPlayer(gs->currentPlayer)->status != EPlayerStatus::INGAME)
{
states.setFlag(gs->currentPlayer, &PlayerStatus::makingTurn, false);
}
} }
void CGameHandler::getLossVicMessage( PlayerColor player, si8 standard, bool victory, InfoWindow &out ) const void CGameHandler::getLossVicMessage( PlayerColor player, si8 standard, bool victory, InfoWindow &out ) const