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()
{
ASSERT_IF_CALLED_WITH_PLAYER
auto playerInt = cl->playerint[*player];
cl->playerint.erase(*player);
cl->battleints.erase(*player);
//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()

View File

@ -649,7 +649,8 @@ void CAdvMapInt::deactivate()
townList.deactivate();
terrain.deactivate();
infoBar.deactivate();
LOCPLINT->cingconsole->deactivate();
if(LOCPLINT)
LOCPLINT->cingconsole->deactivate();
}
}
void CAdvMapInt::showAll(SDL_Surface * to)

View File

@ -129,21 +129,14 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player)
CPlayerInterface::~CPlayerInterface()
{
howManyPeople--;
logGlobal->traceStream() << "\tHuman player interface for player " << playerID << " being destructed";
//howManyPeople--;
//delete pim;
//vstd::clear_pointer(pim);
delete showingDialog;
if(adventureInt)
{
if(adventureInt->active & CIntObject::KEYBOARD)
adventureInt->deactivateKeyboard();
delete adventureInt;
adventureInt = nullptr;
}
delete cingconsole;
LOCPLINT = nullptr;
if(LOCPLINT == this)
LOCPLINT = nullptr;
}
void CPlayerInterface::init(shared_ptr<CCallback> CB)
{
@ -381,6 +374,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
LOG_TRACE_PARAMS(logGlobal, "Hero %s killed handler for player %s", hero->name % playerID);
const CArmedInstance *newSelection = nullptr;
if (makingTurn)
@ -405,9 +399,9 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
paths.erase(hero);
adventureInt->heroList.update(hero);
if (makingTurn)
if (makingTurn && newSelection)
adventureInt->select(newSelection, true);
else
else if(adventureInt->selection == hero)
adventureInt->selection = nullptr;
}
@ -619,14 +613,11 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
cb->registerBattleInterface(autofightingAI);
}
waitForAllDialogs();
if(isAutoFightOn)
GH.topInt()->deactivate();
//Don't wait for dialogs when we are non-active hot-seat player
if(LOCPLINT == this)
waitForAllDialogs();
BATTLE_EVENT_POSSIBLE_RETURN;
GH.pushInt(battleInt);
}
@ -1569,6 +1560,10 @@ void CPlayerInterface::update()
if(terminate_cond.get())
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
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 )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if(LOCPLINT != this)
return;
if(player == playerID)
{
@ -2076,17 +2069,30 @@ void CPlayerInterface::gameOver(PlayerColor player, bool victory )
showInfoDialog(CGI->generaltexth->allTexts[95]);
// else
// showInfoDialog("Placeholder message: you won!");
makingTurn = true;
waitForAllDialogs(); //wait till all dialogs are displayed and closed
makingTurn = false;
if(LOCPLINT == this)
{
GH.curInt = this; //waiting for dialogs requires this to get events
waitForAllDialogs(); //wait till all dialogs are displayed and closed
}
howManyPeople--;
if(!howManyPeople //all human players eliminated
&& 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();
}
if(GH.curInt == this)
GH.curInt = nullptr;
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.";
GH.curInt = nullptr;
LOCPLINT->terminate_cond.setn(true);
{
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
logNetwork->infoStream() << "Ending current game!";
@ -606,9 +605,11 @@ void CClient::battleStarted(const BattleInfo * info)
if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL))
{
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,
(screen->h - 600)/2, 800, 600), att, def);
GH.pushInt(bi);
}
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>
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);
}

View File

@ -5135,6 +5135,12 @@ void CGameHandler::checkLossVictory( PlayerColor player )
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