diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 81c5158a4..1653b62e1 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -398,7 +398,10 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero) EVENT_HANDLER_CALLED_BY_CLIENT; LOG_TRACE_PARAMS(logGlobal, "Hero %s killed handler for player %s", hero->getNameTranslated() % playerID); - localState->removeWanderingHero(hero); + // if hero is not in town garrison + if (vstd::contains(localState->getWanderingHeroes(), hero)) + localState->removeWanderingHero(hero); + adventureInt->onHeroChanged(hero); localState->erasePath(hero); @@ -1482,6 +1485,10 @@ void CPlayerInterface::objectRemovedAfter() { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onMapTilesChanged(boost::none); + + // visiting or garrisoned hero removed - recreate castle window + if (castleInt) + openTownWindow(castleInt->town); } void CPlayerInterface::playerBlocked(int reason, bool start) diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index ab1083441..331962d7a 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -326,9 +326,6 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) if(curHero->isMissionCritical()) noDismiss = true; - if (curHero->visitedTown) - noDismiss = true; - dismissButton->block(noDismiss); if(curHero->valOfBonuses(Selector::type()(BonusType::BEFORE_BATTLE_REPOSITION)) == 0) diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index b8368d741..20314d16c 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1132,7 +1132,16 @@ void RemoveObject::applyGs(CGameState *gs) PlayerState * p = gs->getPlayerState(beatenHero->tempOwner); gs->map->heroesOnMap -= beatenHero; p->heroes -= beatenHero; - beatenHero->detachFrom(*beatenHero->whereShouldBeAttachedOnSiege(gs)); + + + auto * siegeNode = beatenHero->whereShouldBeAttachedOnSiege(gs); + + // FIXME: workaround: + // hero should be attached to siegeNode after battle + // however this code might also be called on dismissing hero while in town + if (siegeNode && vstd::contains(beatenHero->getParentNodes(), siegeNode)) + beatenHero->detachFrom(*siegeNode); + beatenHero->tempOwner = PlayerColor::NEUTRAL; //no one owns beaten hero vstd::erase_if(beatenHero->artifactsInBackpack, [](const ArtSlotInfo& asi) {