1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-30 04:30:42 +02:00

Merge pull request #1738 from IvanSavenko/advmap_fixes

Fixes for regressions related to adventure map
This commit is contained in:
Ivan Savenko 2023-03-23 17:31:59 +02:00 committed by GitHub
commit 56a02c240e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 162 additions and 122 deletions

View File

@ -583,6 +583,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
castleInt->garr->setArmy(town->visitingHero, 1); castleInt->garr->setArmy(town->visitingHero, 1);
castleInt->garr->recreateSlots(); castleInt->garr->recreateSlots();
castleInt->heroes->update(); castleInt->heroes->update();
castleInt->redraw();
} }
for (auto isa : GH.listInt) for (auto isa : GH.listInt)
{ {
@ -591,9 +592,9 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
{ {
ki->townChanged(town); ki->townChanged(town);
ki->updateGarrisons(); ki->updateGarrisons();
ki->redraw();
} }
} }
GH.totalRedraw();
} }
void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
{ {
@ -1510,6 +1511,7 @@ void CPlayerInterface::objectRemoved(const CGObjectInstance * obj)
const CGHeroInstance * h = static_cast<const CGHeroInstance *>(obj); const CGHeroInstance * h = static_cast<const CGHeroInstance *>(obj);
heroKilled(h); heroKilled(h);
} }
GH.fakeMouseMove();
} }
void CPlayerInterface::objectRemovedAfter() void CPlayerInterface::objectRemovedAfter()
@ -1559,7 +1561,6 @@ void CPlayerInterface::update()
} }
assert(adventureInt); assert(adventureInt);
assert(adventureInt->selection);
// Handles mouse and key input // Handles mouse and key input
GH.updateTime(); GH.updateTime();
@ -2032,7 +2033,9 @@ bool CPlayerInterface::capturedAllEvents()
return true; return true;
} }
if (ignoreEvents) bool needToLockAdventureMap = adventureInt->active && CGI->mh->hasOngoingAnimations();
if (ignoreEvents || needToLockAdventureMap)
{ {
boost::unique_lock<boost::mutex> un(eventsM); boost::unique_lock<boost::mutex> un(eventsM);
while(!SDLEventsQueue.empty()) while(!SDLEventsQueue.empty())

View File

@ -17,7 +17,7 @@ class CIntObject;
class ClientCommandManager //take mantis #2292 issue about account if thinking about handling cheats from command-line class ClientCommandManager //take mantis #2292 issue about account if thinking about handling cheats from command-line
{ {
bool currentCallFromIngameConsole; bool currentCallFromIngameConsole = false;
void giveTurn(const PlayerColor &color); void giveTurn(const PlayerColor &color);
void printInfoAboutInterfaceObject(const CIntObject *obj, int level); void printInfoAboutInterfaceObject(const CIntObject *obj, int level);

View File

@ -514,6 +514,11 @@ void ApplyClientNetPackVisitor::visitNewStructures(NewStructures & pack)
{ {
callInterfaceIfPresent(cl, town->tempOwner, &IGameEventsReceiver::buildChanged, town, id, 1); callInterfaceIfPresent(cl, town->tempOwner, &IGameEventsReceiver::buildChanged, town, id, 1);
} }
// invalidate section of map view with our object and force an update
CGI->mh->onObjectInstantRemove(town);
CGI->mh->onObjectInstantAdd(town);
} }
void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack) void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack)
{ {
@ -522,6 +527,10 @@ void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack)
{ {
callInterfaceIfPresent(cl, town->tempOwner, &IGameEventsReceiver::buildChanged, town, id, 2); callInterfaceIfPresent(cl, town->tempOwner, &IGameEventsReceiver::buildChanged, town, id, 2);
} }
// invalidate section of map view with our object and force an update
CGI->mh->onObjectInstantRemove(town);
CGI->mh->onObjectInstantAdd(town);
} }
void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures & pack) void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures & pack)
@ -607,7 +616,7 @@ void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
if (pack.what == ObjProperty::OWNER) if (pack.what == ObjProperty::OWNER)
{ {
// invalidate section of map view with our objec and force an update with new flag color // invalidate section of map view with our object and force an update with new flag color
CGI->mh->onObjectInstantRemove(gs.getObjInstance(pack.id)); CGI->mh->onObjectInstantRemove(gs.getObjInstance(pack.id));
CGI->mh->onObjectInstantAdd(gs.getObjInstance(pack.id)); CGI->mh->onObjectInstantAdd(gs.getObjInstance(pack.id));
} }

View File

@ -986,7 +986,6 @@ void CAdvMapInt::initializeNewTurn()
{ {
heroList->update(); heroList->update();
townList->update(); townList->update();
mapAudio->onPlayerTurnStarted();
const CGHeroInstance * heroToSelect = nullptr; const CGHeroInstance * heroToSelect = nullptr;
@ -1017,6 +1016,7 @@ void CAdvMapInt::initializeNewTurn()
updateNextHero(nullptr); updateNextHero(nullptr);
showAll(screen); showAll(screen);
mapAudio->onPlayerTurnStarted();
if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown()) if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())
{ {
@ -1404,6 +1404,7 @@ void CAdvMapInt::aiTurnStarted()
mapAudio->onEnemyTurnStarted(); mapAudio->onEnemyTurnStarted();
adventureInt->minimap->setAIRadar(true); adventureInt->minimap->setAIRadar(true);
adventureInt->infoBar->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer()); adventureInt->infoBar->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
adventureInt->minimap->showAll(screen);//force refresh on inactive object
adventureInt->infoBar->showAll(screen);//force refresh on inactive object adventureInt->infoBar->showAll(screen);//force refresh on inactive object
} }

View File

@ -24,71 +24,85 @@
#include "../../lib/TextOperations.h" #include "../../lib/TextOperations.h"
#include "../../lib/mapObjects/CArmedInstance.h" #include "../../lib/mapObjects/CArmedInstance.h"
#include <SDL_timer.h>
CInGameConsole::CInGameConsole() CInGameConsole::CInGameConsole()
: CIntObject(KEYBOARD | TEXTINPUT), : CIntObject(KEYBOARD | TIME | TEXTINPUT)
prevEntDisp(-1), , prevEntDisp(-1)
defaultTimeout(10000),
maxDisplayedTexts(10)
{ {
type |= REDRAW_PARENT;
}
void CInGameConsole::showAll(SDL_Surface * to)
{
show(to);
} }
void CInGameConsole::show(SDL_Surface * to) void CInGameConsole::show(SDL_Surface * to)
{ {
int number = 0; int number = 0;
std::vector<std::list< std::pair< std::string, uint32_t > >::iterator> toDel;
boost::unique_lock<boost::mutex> lock(texts_mx); boost::unique_lock<boost::mutex> lock(texts_mx);
for(auto it = texts.begin(); it != texts.end(); ++it, ++number) for(auto & text : texts)
{ {
Point leftBottomCorner(0, pos.h); Point leftBottomCorner(0, pos.h);
Point textPosition(leftBottomCorner.x + 50, leftBottomCorner.y - texts.size() * 20 - 80 + number * 20);
graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, it->first, Colors::GREEN, graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, text.text, Colors::GREEN, textPosition );
Point(leftBottomCorner.x + 50, leftBottomCorner.y - (int)texts.size() * 20 - 80 + number*20));
if((int)(SDL_GetTicks() - it->second) > defaultTimeout) number++;
{
toDel.push_back(it);
}
}
for(auto & elem : toDel)
{
texts.erase(elem);
} }
} }
void CInGameConsole::print(const std::string &txt) void CInGameConsole::tick(uint32_t msPassed)
{ {
boost::unique_lock<boost::mutex> lock(texts_mx); size_t sizeBefore = texts.size();
int lineLen = conf.go()->ac.outputLineLength;
if(txt.size() < lineLen)
{ {
texts.push_back(std::make_pair(txt, SDL_GetTicks())); boost::unique_lock<boost::mutex> lock(texts_mx);
if(texts.size() > maxDisplayedTexts)
{
texts.pop_front();
}
}
else
{
assert(lineLen);
for(int g=0; g<txt.size() / lineLen + 1; ++g)
{
std::string part = txt.substr(g * lineLen, lineLen);
if(part.size() == 0)
break;
texts.push_back(std::make_pair(part, SDL_GetTicks())); for(auto & text : texts)
if(texts.size() > maxDisplayedTexts) text.timeOnScreen += msPassed;
vstd::erase_if(
texts,
[&](const auto & value)
{ {
texts.pop_front(); return value.timeOnScreen > defaultTimeout;
}
);
}
if(sizeBefore != texts.size())
GH.totalRedraw(); // FIXME: ingame console has no parent widget set
}
void CInGameConsole::print(const std::string & txt)
{
// boost::unique_lock scope
{
boost::unique_lock<boost::mutex> lock(texts_mx);
int lineLen = conf.go()->ac.outputLineLength;
if(txt.size() < lineLen)
{
texts.push_back({txt, 0});
}
else
{
assert(lineLen);
for(int g = 0; g < txt.size() / lineLen + 1; ++g)
{
std::string part = txt.substr(g * lineLen, lineLen);
if(part.empty())
break;
texts.push_back({part, 0});
} }
} }
while(texts.size() > maxDisplayedTexts)
texts.erase(texts.begin());
} }
GH.totalRedraw(); // FIXME: ingame console has no parent widget set
} }
void CInGameConsole::keyPressed (const SDL_Keycode & key) void CInGameConsole::keyPressed (const SDL_Keycode & key)
@ -136,7 +150,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key)
} }
case SDLK_UP: //up arrow case SDLK_UP: //up arrow
{ {
if(previouslyEntered.size() == 0) if(previouslyEntered.empty())
break; break;
if(prevEntDisp == -1) if(prevEntDisp == -1)
@ -178,7 +192,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key)
void CInGameConsole::textInputed(const std::string & inputtedText) void CInGameConsole::textInputed(const std::string & inputtedText)
{ {
if(!captureAllKeys || enteredText.size() == 0) if(!captureAllKeys || enteredText.empty())
return; return;
enteredText.resize(enteredText.size()-1); enteredText.resize(enteredText.size()-1);

View File

@ -14,20 +14,39 @@
class CInGameConsole : public CIntObject class CInGameConsole : public CIntObject
{ {
private: private:
std::list< std::pair< std::string, uint32_t > > texts; //list<text to show, time of add> struct TextState
boost::mutex texts_mx; // protects texts {
std::vector< std::string > previouslyEntered; //previously entered texts, for up/down arrows to work std::string text;
int prevEntDisp; //displayed entry from previouslyEntered - if none it's -1 uint32_t timeOnScreen;
int defaultTimeout; //timeout for new texts (in ms) };
int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
/// Currently visible texts in the overlay
std::vector<TextState> texts;
/// protects texts
boost::mutex texts_mx;
/// previously entered texts, for up/down arrows to work
std::vector<std::string> previouslyEntered;
/// displayed entry from previouslyEntered - if none it's -1
int prevEntDisp;
/// timeout for new texts (in ms)
static constexpr int defaultTimeout = 10000;
/// how many texts can be displayed simultaneously
static constexpr int maxDisplayedTexts = 10;
std::weak_ptr<IStatusBar> currentStatusBar; std::weak_ptr<IStatusBar> currentStatusBar;
std::string enteredText; std::string enteredText;
public: public:
void print(const std::string &txt); void print(const std::string & txt);
void tick(uint32_t msPassed) override;
void show(SDL_Surface * to) override; void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
void keyPressed(const SDL_Keycode & key) override; void keyPressed(const SDL_Keycode & key) override;
void textInputed(const std::string & enteredText) override; void textInputed(const std::string & enteredText) override;
void textEdited(const std::string & enteredText) override; void textEdited(const std::string & enteredText) override;

View File

@ -254,11 +254,21 @@ void CInfoBar::showSelection()
showGameStatus();//FIXME: may be incorrect but shouldn't happen in general showGameStatus();//FIXME: may be incorrect but shouldn't happen in general
} }
void CInfoBar::tick() void CInfoBar::tick(uint32_t msPassed)
{ {
removeUsedEvents(TIME); assert(timerCounter > 0);
if(GH.topInt() == adventureInt)
popComponents(true); if (msPassed >= timerCounter)
{
timerCounter = 0;
removeUsedEvents(TIME);
if(GH.topInt() == adventureInt)
popComponents(true);
}
else
{
timerCounter -= msPassed;
}
} }
void CInfoBar::clickLeft(tribool down, bool previousState) void CInfoBar::clickLeft(tribool down, bool previousState)
@ -290,6 +300,7 @@ void CInfoBar::hover(bool on)
CInfoBar::CInfoBar(const Rect & position) CInfoBar::CInfoBar(const Rect & position)
: CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()), : CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
timerCounter(0),
state(EMPTY) state(EMPTY)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -302,6 +313,14 @@ CInfoBar::CInfoBar(const Point & position): CInfoBar(Rect(position.x, position.y
{ {
} }
void CInfoBar::setTimer(uint32_t msToTrigger)
{
if (!(active & TIME))
addUsedEvents(TIME);
timerCounter = msToTrigger;
}
void CInfoBar::showDate() void CInfoBar::showDate()
{ {
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
@ -312,7 +331,6 @@ void CInfoBar::showDate()
redraw(); redraw();
} }
void CInfoBar::pushComponents(const std::vector<Component> & components, std::string message, int timer) void CInfoBar::pushComponents(const std::vector<Component> & components, std::string message, int timer)
{ {
auto actualPush = [&](const std::vector<Component> & components, std::string message, int timer, size_t max){ auto actualPush = [&](const std::vector<Component> & components, std::string message, int timer, size_t max){

View File

@ -138,6 +138,7 @@ private:
std::shared_ptr<CVisibleInfo> visibleInfo; std::shared_ptr<CVisibleInfo> visibleInfo;
EState state; EState state;
uint32_t timerCounter;
bool shouldPopAll = false; bool shouldPopAll = false;
std::queue<std::pair<VisibleComponentInfo::Cache, int>> componentsQueue; std::queue<std::pair<VisibleComponentInfo::Cache, int>> componentsQueue;
@ -151,13 +152,14 @@ private:
//removes all information about current state, deactivates timer (if any) //removes all information about current state, deactivates timer (if any)
void reset(); void reset();
void tick() override; void tick(uint32_t msPassed) override;
void clickLeft(tribool down, bool previousState) override; void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override;
void hover(bool on) override; void hover(bool on) override;
void playNewDaySound(); void playNewDaySound();
void setTimer(uint32_t msToTrigger);
public: public:
CInfoBar(const Rect & pos); CInfoBar(const Rect & pos);
CInfoBar(const Point & pos); CInfoBar(const Point & pos);

View File

@ -77,7 +77,7 @@ void CList::CListItem::onSelect(bool on)
if(on) if(on)
selection = genSelection(); selection = genSelection();
select(on); select(on);
GH.totalRedraw(); redraw();
} }
CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create) CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create)

View File

@ -222,10 +222,7 @@ void CMinimap::setAIRadar(bool on)
aiShield->disable(); aiShield->disable();
update(); update();
} }
redraw();
// this may happen during AI turn when this interface is inactive
// force redraw in order to properly update interface
GH.totalRedraw();
} }
void CMinimap::updateTile(const int3 &pos) void CMinimap::updateTile(const int3 &pos)

View File

@ -192,7 +192,7 @@ void CGuiHandler::updateTime()
for (auto & elem : hlp) for (auto & elem : hlp)
{ {
if(!vstd::contains(timeinterested,elem)) continue; if(!vstd::contains(timeinterested,elem)) continue;
(elem)->onTimer(ms); (elem)->tick(ms);
} }
} }

View File

@ -29,7 +29,6 @@ CIntObject::CIntObject(int used_, Point pos_):
active(active_m) active(active_m)
{ {
hovered = captureAllKeys = strongInterest = false; hovered = captureAllKeys = strongInterest = false;
toNextTick = timerDelay = 0;
used = used_; used = used_;
recActions = defActions = GH.defActionsDef; recActions = defActions = GH.defActionsDef;
@ -60,24 +59,6 @@ CIntObject::~CIntObject()
parent_m->removeChild(this); parent_m->removeChild(this);
} }
void CIntObject::setTimer(int msToTrigger)
{
if (!(active & TIME))
activate(TIME);
toNextTick = timerDelay = msToTrigger;
used |= TIME;
}
void CIntObject::onTimer(int timePassed)
{
toNextTick -= timePassed;
if (toNextTick < 0)
{
toNextTick += timerDelay;
tick();
}
}
void CIntObject::show(SDL_Surface * to) void CIntObject::show(SDL_Surface * to)
{ {
if(defActions & UPDATE) if(defActions & UPDATE)

View File

@ -65,14 +65,8 @@ class CIntObject : public IShowActivatable //interface object
{ {
ui16 used;//change via addUsed() or delUsed ui16 used;//change via addUsed() or delUsed
//time handling
int toNextTick;
int timerDelay;
std::map<MouseButton, bool> currentMouseState; std::map<MouseButton, bool> currentMouseState;
void onTimer(int timePassed);
//non-const versions of fields to allow changing them in CIntObject //non-const versions of fields to allow changing them in CIntObject
CIntObject *parent_m; //parent object CIntObject *parent_m; //parent object
ui16 active_m; ui16 active_m;
@ -129,8 +123,7 @@ public:
virtual void mouseMoved (const Point & cursorPosition){} virtual void mouseMoved (const Point & cursorPosition){}
//time handling //time handling
void setTimer(int msToTrigger);//set timer delay and activate timer if needed. virtual void tick(uint32_t msPassed){}
virtual void tick(){}
//mouse wheel //mouse wheel
virtual void wheelScrolled(bool down, bool in){} virtual void wheelScrolled(bool down, bool in){}

View File

@ -60,14 +60,14 @@ BasicMapView::BasicMapView(const Point & offset, const Point & dimensions)
void BasicMapView::render(Canvas & target, bool fullUpdate) void BasicMapView::render(Canvas & target, bool fullUpdate)
{ {
Canvas targetClipped(target, pos); Canvas targetClipped(target, pos);
controller->update(GH.mainFPSmng->getElapsedMilliseconds());
tilesCache->update(controller->getContext()); tilesCache->update(controller->getContext());
tilesCache->render(controller->getContext(), targetClipped, fullUpdate); tilesCache->render(controller->getContext(), targetClipped, fullUpdate);
} }
void BasicMapView::show(SDL_Surface * to) void BasicMapView::show(SDL_Surface * to)
{ {
controller->update(GH.mainFPSmng->getElapsedMilliseconds());
Canvas target(to); Canvas target(to);
CSDL_Ext::CClipRectGuard guard(to, pos); CSDL_Ext::CClipRectGuard guard(to, pos);
render(target, false); render(target, false);
@ -75,6 +75,8 @@ void BasicMapView::show(SDL_Surface * to)
void BasicMapView::showAll(SDL_Surface * to) void BasicMapView::showAll(SDL_Surface * to)
{ {
controller->update(0);
Canvas target(to); Canvas target(to);
CSDL_Ext::CClipRectGuard guard(to, pos); CSDL_Ext::CClipRectGuard guard(to, pos);
render(target, true); render(target, true);

View File

@ -24,7 +24,6 @@
MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel> & model) MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel> & model)
: model(model) : model(model)
, owner(owner) , owner(owner)
, curHoveredTile(-1, -1, -1)
, isSwiping(false) , isSwiping(false)
{ {
pos.w = model->getPixelsVisibleDimensions().x; pos.w = model->getPixelsVisibleDimensions().x;
@ -47,17 +46,6 @@ void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & con
this->context = context; this->context = context;
} }
void MapViewActions::activate()
{
CIntObject::activate();
}
void MapViewActions::deactivate()
{
CIntObject::deactivate();
curHoveredTile = int3(-1, -1, -1); //we lost info about hovered tile when disabling
}
void MapViewActions::clickLeft(tribool down, bool previousState) void MapViewActions::clickLeft(tribool down, bool previousState)
{ {
if(indeterminate(down)) if(indeterminate(down))
@ -159,11 +147,7 @@ void MapViewActions::handleHover(const Point & cursorPosition)
return; return;
} }
if(tile != curHoveredTile) adventureInt->onTileHovered(tile);
{
curHoveredTile = tile;
adventureInt->onTileHovered(tile);
}
} }
void MapViewActions::hover(bool on) void MapViewActions::hover(bool on)

View File

@ -23,8 +23,6 @@ class MapViewActions : public CIntObject
Point swipeInitialViewPos; Point swipeInitialViewPos;
Point swipeInitialRealPos; Point swipeInitialRealPos;
int3 curHoveredTile;
MapView & owner; MapView & owner;
std::shared_ptr<MapViewModel> model; std::shared_ptr<MapViewModel> model;
std::shared_ptr<IMapRendererContext> context; std::shared_ptr<IMapRendererContext> context;
@ -39,8 +37,6 @@ public:
void setContext(const std::shared_ptr<IMapRendererContext> & context); void setContext(const std::shared_ptr<IMapRendererContext> & context);
void activate() override;
void deactivate() override;
void clickLeft(tribool down, bool previousState) override; void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override;
void clickMiddle(tribool down, bool previousState) override; void clickMiddle(tribool down, bool previousState) override;

View File

@ -251,6 +251,26 @@ void MapViewController::fadeInObject(const CGObjectInstance * obj)
void MapViewController::removeObject(const CGObjectInstance * obj) void MapViewController::removeObject(const CGObjectInstance * obj)
{ {
if (obj->ID == Obj::BOAT)
{
auto * boat = dynamic_cast<const CGBoat*>(obj);
if (boat->hero)
{
view->invalidate(context, boat->hero->id);
state->removeObject(boat->hero);
}
}
if (obj->ID == Obj::HERO)
{
auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
if (hero->boat)
{
view->invalidate(context, hero->boat->id);
state->removeObject(hero->boat);
}
}
view->invalidate(context, obj->id); view->invalidate(context, obj->id);
state->removeObject(obj); state->removeObject(obj);
} }
@ -265,7 +285,7 @@ void MapViewController::onBeforeHeroEmbark(const CGHeroInstance * obj, const int
{ {
if(isEventVisible(obj, from, dest)) if(isEventVisible(obj, from, dest))
{ {
onObjectFadeOut(obj); fadeOutObject(obj);
setViewCenter(obj->getSightCenter()); setViewCenter(obj->getSightCenter());
} }
else else
@ -288,7 +308,7 @@ void MapViewController::onAfterHeroDisembark(const CGHeroInstance * obj, const i
{ {
if(isEventVisible(obj, from, dest)) if(isEventVisible(obj, from, dest))
{ {
onObjectFadeIn(obj); fadeInObject(obj);
setViewCenter(obj->getSightCenter()); setViewCenter(obj->getSightCenter());
} }
addObject(obj); addObject(obj);

View File

@ -229,5 +229,6 @@ IMapObjectObserver::IMapObjectObserver()
IMapObjectObserver::~IMapObjectObserver() IMapObjectObserver::~IMapObjectObserver()
{ {
CGI->mh->removeMapObserver(this); if (CGI && CGI->mh)
CGI->mh->removeMapObserver(this);
} }