From a8a74888f7bf47b1a62ea25310d272a1b181b976 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 24 Apr 2025 20:41:49 +0300 Subject: [PATCH] Fix attaching of hero to bonus system (old bug?) --- lib/gameState/CGameState.cpp | 16 ++++++++++------ lib/networkPacks/NetPacksLib.cpp | 30 ++++++++++++++++-------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 3b94fe0de..3eb25fc6c 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -543,14 +543,18 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy } } - auto handler = LIBRARY->objtypeh->getHandlerFor(Obj::HERO, heroTypeId.toHeroType()->heroClass->getIndex()); - auto object = handler->create(cb, handler->getTemplates().front()); - auto hero = std::dynamic_pointer_cast(object); + auto hero = map->tryTakeFromHeroPool(heroTypeId); + + if (!hero) + { + auto handler = LIBRARY->objtypeh->getHandlerFor(Obj::HERO, heroTypeId.toHeroType()->heroClass->getIndex()); + auto object = handler->create(cb, handler->getTemplates().front()); + hero = std::dynamic_pointer_cast(object); + hero->ID = Obj::HERO; + hero->setHeroType(heroTypeId); + } - hero->ID = Obj::HERO; - hero->setHeroType(heroTypeId); hero->tempOwner = playerColor; - hero->setAnchorPos(townPos + hero->getVisitableOffset()); map->getEditManager()->insertObject(hero); } diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index fdfb65165..a71c1cfbd 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1190,19 +1190,10 @@ void RemoveObject::applyGs(CGameState *gs) if(obj->ID == Obj::HERO) //remove beaten hero { - auto beatenObject = gs->getMap().eraseObject(obj->id); - auto beatenHero = std::dynamic_pointer_cast(beatenObject); + auto beatenHero = dynamic_cast(obj); assert(beatenHero); 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) { return asi.getArt()->getTypeId() == ArtifactID::GRAIL; @@ -1210,17 +1201,21 @@ void RemoveObject::applyGs(CGameState *gs) if(beatenHero->getVisitedTown()) { - if(beatenHero->getVisitedTown()->getGarrisonHero() == beatenHero.get()) + if(beatenHero->getVisitedTown()->getGarrisonHero() == beatenHero) beatenHero->getVisitedTown()->setGarrisonedHero(nullptr); else beatenHero->getVisitedTown()->setVisitingHero(nullptr); beatenHero->setVisitedTown(nullptr, false); } + beatenHero->detachFromBonusSystem(*gs); + beatenHero->tempOwner = PlayerColor::NEUTRAL; //no one owns beaten hero - //return hero to the pool, so he may reappear in tavern - gs->heroesPool->addHeroToPool(beatenHero->getHeroTypeID()); - gs->getMap().addToHeroPool(beatenHero); + // 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); //If hero on Boat is removed, the Boat disappears if(beatenHero->inBoat()) @@ -1229,6 +1224,13 @@ void RemoveObject::applyGs(CGameState *gs) beatenHero->setBoat(nullptr); gs->getMap().eraseObject(boat->id); } + + auto beatenObject = gs->getMap().eraseObject(obj->id); + + //return hero to the pool, so he may reappear in tavern + gs->heroesPool->addHeroToPool(beatenHero->getHeroTypeID()); + gs->getMap().addToHeroPool(std::dynamic_pointer_cast(beatenObject)); + return; }