From 1dc962804e18a59fd2ecae10fb4091e40f80ab22 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 25 Apr 2024 14:04:45 +0300 Subject: [PATCH] Fixed possible crash on having selectable reward with no visual image --- client/adventureMap/CInfoBar.cpp | 1 + client/widgets/CComponent.cpp | 9 ++++++--- lib/rewardable/Reward.cpp | 11 +++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/client/adventureMap/CInfoBar.cpp b/client/adventureMap/CInfoBar.cpp index c7c97481e..68809752a 100644 --- a/client/adventureMap/CInfoBar.cpp +++ b/client/adventureMap/CInfoBar.cpp @@ -386,6 +386,7 @@ void CInfoBar::pushComponents(const std::vector & components, std::st reward_map.at(0).first.push_back(c); reward_map.at(0).second = 8; //At most 8, cannot be more break; + case ComponentType::NONE: case ComponentType::SEC_SKILL: reward_map.at(1).first.push_back(c); reward_map.at(1).second = 4; //At most 4 diff --git a/client/widgets/CComponent.cpp b/client/widgets/CComponent.cpp index d8e7a7d97..eacd5e62a 100644 --- a/client/widgets/CComponent.cpp +++ b/client/widgets/CComponent.cpp @@ -133,6 +133,7 @@ std::vector CComponent::getFileName() const case ComponentType::MANA: case ComponentType::LEVEL: return gen(primSkillsArr); + case ComponentType::NONE: case ComponentType::SEC_SKILL: return gen(secSkillsArr); case ComponentType::RESOURCE: @@ -165,6 +166,8 @@ size_t CComponent::getIndex() const { switch(data.type) { + case ComponentType::NONE: + return 0; case ComponentType::PRIM_SKILL: return data.subType.getNum(); case ComponentType::EXPERIENCE: @@ -216,6 +219,7 @@ std::string CComponent::getDescription() const case ComponentType::RESOURCE: case ComponentType::RESOURCE_PER_DAY: return CGI->generaltexth->allTexts[242]; + case ComponentType::NONE: case ComponentType::CREATURE: return ""; case ComponentType::ARTIFACT: @@ -288,9 +292,10 @@ std::string CComponent::getSubtitle() const case ComponentType::SPELL_SCROLL: case ComponentType::SPELL: return CGI->spells()->getById(data.subType.as())->getNameTranslated(); + case ComponentType::NONE: case ComponentType::MORALE: - return ""; case ComponentType::LUCK: + case ComponentType::HERO_PORTRAIT: return ""; case ComponentType::BUILDING: { @@ -303,8 +308,6 @@ std::string CComponent::getSubtitle() const } return building->getNameTranslated(); } - case ComponentType::HERO_PORTRAIT: - return ""; case ComponentType::FLAG: return CGI->generaltexth->capColors[data.subType.as().getNum()]; default: diff --git a/lib/rewardable/Reward.cpp b/lib/rewardable/Reward.cpp index 17db767b1..a2e54fb80 100644 --- a/lib/rewardable/Reward.cpp +++ b/lib/rewardable/Reward.cpp @@ -63,8 +63,15 @@ Component Rewardable::Reward::getDisplayedComponent(const CGHeroInstance * h) co { std::vector comps; loadComponents(comps, h); - assert(!comps.empty()); - return comps.front(); + + if (!comps.empty()) + return comps.front(); + + // Rewardable requested component that represent such rewards, to be used as button in UI selection dialog, e.g. Chest with its experience / money pick + // However reward is either completely empty OR has no rewards that target hero can receive OR these rewards have no visible component (e.g. movement) + // Such cases are unreachable in H3, however can be reached by mods + logMod->warn("Failed to find displayed component for reward!"); + return Component(ComponentType::NONE, 0); } void Rewardable::Reward::loadComponents(std::vector & comps, const CGHeroInstance * h) const