From cd79b0932e54d797b620b4f425c4a0bea4982c34 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:36:50 +0200 Subject: [PATCH] code review --- .../Content/config/translations/english.json | 16 +---- client/render/Canvas.cpp | 4 +- client/render/Canvas.h | 4 +- client/widgets/TextControls.cpp | 2 +- client/windows/CCastleInterface.cpp | 2 +- client/windows/CCreatureWindow.cpp | 2 +- client/windows/CHeroWindow.cpp | 2 +- client/windows/wiki/WikiCreatureContent.cpp | 20 +++--- client/windows/wiki/WikiHeroContent.cpp | 6 +- client/windows/wiki/WikiTownContent.cpp | 12 ++-- client/windows/wiki/WikiWindow.cpp | 71 ++++++++++--------- client/windows/wiki/WikiWindow.h | 5 +- 12 files changed, 67 insertions(+), 79 deletions(-) diff --git a/Mods/vcmi/Content/config/translations/english.json b/Mods/vcmi/Content/config/translations/english.json index 9fecbe829..8693a2520 100644 --- a/Mods/vcmi/Content/config/translations/english.json +++ b/Mods/vcmi/Content/config/translations/english.json @@ -1096,18 +1096,12 @@ "vcmi.tutorialWindow.decription.RadialWheel": "Swiping opens radial wheel for various actions, such as creature/hero management and town ordering.", "vcmi.tutorialWindow.decription.RightClick": "Touch and hold the element on which you want to right-click. Touch the free area to close.", "vcmi.tutorialWindow.title": "Touchscreen Introduction", - "vcmi.wiki.button.back": "Back", "vcmi.wiki.button.close": "Close", "vcmi.wiki.content.placeholder": "Select a category and an entry to view its description.", "vcmi.wiki.header.category": "Category", "vcmi.wiki.header.entry": "Entry", "vcmi.wiki.header.information": "Information", - "vcmi.wiki.search.hint": "Search...", - "vcmi.wiki.stub.body": "Detailed information about \"%s\" will be added here in a future update.", - "vcmi.wiki.stub.category": "[Category: %s]", - "vcmi.wiki.stub.hint": "You can describe stats, background lore, tactical notes, and other relevant information for this entry.", - "vcmi.wiki.stub.intro": "This entry is a stub.", - "vcmi.wiki.title": "Wiki", + "vcmi.wiki.title": "Heroes-o-pedia", "vcmi.wiki.category.glossary": "Glossary", "vcmi.wiki.category.town": "Town", "vcmi.wiki.category.hero": "Hero", @@ -1125,22 +1119,15 @@ "vcmi.wiki.creature.cost": "Cost", "vcmi.wiki.creature.stat.level": "Level", "vcmi.wiki.creature.stat.level.short": "Lv", - "vcmi.wiki.creature.stat.attack": "Attack", "vcmi.wiki.creature.stat.attack.short": "Atk", - "vcmi.wiki.creature.stat.defense": "Defense", "vcmi.wiki.creature.stat.defense.short": "Def", - "vcmi.wiki.creature.stat.damage": "Damage", "vcmi.wiki.creature.stat.damage.short": "Dmg", - "vcmi.wiki.creature.stat.speed": "Speed", "vcmi.wiki.creature.stat.speed.short": "Spd", - "vcmi.wiki.creature.stat.hitpoints": "Hit Points", "vcmi.wiki.creature.stat.hitpoints.short": "HP", - "vcmi.wiki.creature.stat.growth": "Growth", "vcmi.wiki.creature.stat.growth.short": "Gr", "vcmi.wiki.creature.stat.aivalue": "AI Value", "vcmi.wiki.creature.stat.aivalue.short": "AI", "vcmi.wiki.creature.stat.shots": "Shots", - "vcmi.wiki.creature.stat.spellpoints": "Spell Points", "vcmi.wiki.creature.stat.fightvalue": "Fight Value", "vcmi.wiki.creature.stat.hordegrowth": "Horde Growth", "vcmi.wiki.creature.stat.doublewide": "Double Wide", @@ -1153,7 +1140,6 @@ "vcmi.wiki.hero.specialty": "Specialty", "vcmi.wiki.hero.gender.male": "Male", "vcmi.wiki.hero.gender.female": "Female", - "vcmi.wiki.hero.column.creature": "Creature", "vcmi.wiki.hero.column.amount": "Amount", "vcmi.wiki.hero.column.skill": "Skill", "vcmi.wiki.hero.column.level": "Level", diff --git a/client/render/Canvas.cpp b/client/render/Canvas.cpp index 384375606..e238cec2a 100644 --- a/client/render/Canvas.cpp +++ b/client/render/Canvas.cpp @@ -245,11 +245,11 @@ ColorRGBA Canvas::getPixel(const Point & position) const return ColorRGBA(color.r, color.g, color.b, color.a); } -CanvasClipRectGuard::CanvasClipRectGuard(Canvas & canvas, const Rect & rect, bool intersect): surf(canvas.surface) +CanvasClipRectGuard::CanvasClipRectGuard(Canvas & canvas, const Rect & rect): surf(canvas.surface) { CSDL_Ext::getClipRect(surf, oldRect); const Rect scaled = rect * ENGINE->screenHandler().getScalingFactor(); - CSDL_Ext::setClipRect(surf, intersect ? oldRect.intersect(scaled) : scaled); + CSDL_Ext::setClipRect(surf, oldRect.intersect(scaled)); } CanvasClipRectGuard::~CanvasClipRectGuard() diff --git a/client/render/Canvas.h b/client/render/Canvas.h index b88afd199..37d2f0fa4 100644 --- a/client/render/Canvas.h +++ b/client/render/Canvas.h @@ -133,8 +133,6 @@ class CanvasClipRectGuard : boost::noncopyable Rect oldRect; public: - /// @param intersect if true, clips to the intersection of the current clip rect and @p rect - /// instead of replacing it (prevents child widgets from overdrawing a parent clip) - CanvasClipRectGuard(Canvas & canvas, const Rect & rect, bool intersect = false); + CanvasClipRectGuard(Canvas & canvas, const Rect & rect); ~CanvasClipRectGuard(); }; diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 3f5a3fc41..2af289149 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -309,7 +309,7 @@ void CMultiLineLabel::showAll(Canvas & to) Point lineStart = getTextLocation().topLeft() - visibleSize + Point(0, beginLine * fontPtr->getLineHeight()); Point lineSize = Point(getTextLocation().w, fontPtr->getLineHeight()); - CanvasClipRectGuard guard(to, getTextLocation(), true); // intersect with outer (viewport) clip + CanvasClipRectGuard guard(to, getTextLocation()); for(int i = beginLine; i < std::min(totalLines, endLine); i++) { diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 6bf96a9dc..12e818951 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -1686,7 +1686,7 @@ void CCastleInterface::keyPressed(EShortcut key) case EShortcut::ADVENTURE_OPEN_WIKI: ENGINE->windows().createAndPushWindow( WikiWindow::Style::BROWN, - WikiEntryKey{WikiCategory::TOWN, town->getTown()->faction->getNameTranslated()}); + WikiEntryKey{WikiCategory::TOWN, town->getTown()->faction->getJsonKey()}); break; default: break; diff --git a/client/windows/CCreatureWindow.cpp b/client/windows/CCreatureWindow.cpp index 3bce195e8..d6e1cd3c6 100644 --- a/client/windows/CCreatureWindow.cpp +++ b/client/windows/CCreatureWindow.cpp @@ -874,7 +874,7 @@ void CStackWindow::keyPressed(EShortcut key) if(key == EShortcut::ADVENTURE_OPEN_WIKI && info->creature) ENGINE->windows().createAndPushWindow( WikiWindow::Style::BROWN, - WikiEntryKey{WikiCategory::CREATURE, info->creature->getNameSingularTranslated()}); + WikiEntryKey{WikiCategory::CREATURE, info->creature->getJsonKey()}); } void CStackWindow::initBonusesList() diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 25edc020a..03bae80d2 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -192,7 +192,7 @@ void CHeroWindow::keyPressed(EShortcut key) if(key == EShortcut::ADVENTURE_OPEN_WIKI) ENGINE->windows().createAndPushWindow( WikiWindow::Style::BROWN, - WikiEntryKey{WikiCategory::HERO, curHero->getNameTranslated()}); + WikiEntryKey{WikiCategory::HERO, curHero->getHeroType()->getJsonKey()}); } void CHeroWindow::updateArtifacts() diff --git a/client/windows/wiki/WikiCreatureContent.cpp b/client/windows/wiki/WikiCreatureContent.cpp index 22de79d66..6b4113424 100644 --- a/client/windows/wiki/WikiCreatureContent.cpp +++ b/client/windows/wiki/WikiCreatureContent.cpp @@ -227,24 +227,24 @@ std::vector> buildCreatureContent( std::vector stats; stats.push_back({tr("vcmi.wiki.creature.stat.level"), std::to_string(creature->getLevel())}); - stats.push_back({tr("vcmi.wiki.creature.stat.attack"), std::to_string(creature->getBaseAttack())}); - stats.push_back({tr("vcmi.wiki.creature.stat.defense"), std::to_string(creature->getBaseDefense())}); + stats.push_back({tr("core.genrltxt.190"), std::to_string(creature->getBaseAttack())}); + stats.push_back({tr("core.genrltxt.191"), std::to_string(creature->getBaseDefense())}); const int dmgMin = creature->getBaseDamageMin(); const int dmgMax = creature->getBaseDamageMax(); if(dmgMin == dmgMax) - stats.push_back({tr("vcmi.wiki.creature.stat.damage"), std::to_string(dmgMin)}); + stats.push_back({tr("core.genrltxt.199"), std::to_string(dmgMin)}); else - stats.push_back({tr("vcmi.wiki.creature.stat.damage"), std::to_string(dmgMin) + " \xe2\x80\x93 " + std::to_string(dmgMax)}); + stats.push_back({tr("core.genrltxt.199"), std::to_string(dmgMin) + " - " + std::to_string(dmgMax)}); - stats.push_back({tr("vcmi.wiki.creature.stat.speed"), std::to_string(creature->getBaseSpeed())}); - stats.push_back({tr("vcmi.wiki.creature.stat.hitpoints"), std::to_string(creature->getBaseHitPoints())}); - stats.push_back({tr("vcmi.wiki.creature.stat.growth"), std::to_string(creature->getGrowth())}); + stats.push_back({tr("core.genrltxt.193"), std::to_string(creature->getBaseSpeed())}); + stats.push_back({tr("core.help.439.help"), std::to_string(creature->getBaseHitPoints())}); + stats.push_back({tr("core.genrltxt.194"), std::to_string(creature->getGrowth())}); if(creature->getBaseShots() > 0) stats.push_back({tr("vcmi.wiki.creature.stat.shots"), std::to_string(creature->getBaseShots())}); if(creature->getBaseSpellPoints() > 0) - stats.push_back({tr("vcmi.wiki.creature.stat.spellpoints"), std::to_string(creature->getBaseSpellPoints())}); + stats.push_back({tr("core.genrltxt.387"), std::to_string(creature->getBaseSpellPoints())}); if(creature->getHorde() > 0) stats.push_back({tr("vcmi.wiki.creature.stat.hordegrowth"), std::to_string(creature->getHorde())}); if(creature->isDoubleWide()) @@ -367,10 +367,10 @@ std::vector> buildCreatureContent( rel->getNameSingularTranslated())); // Clickable overlay: left-click → navigate, right-click → CStackWindow - const std::string relName = rel->getNameSingularTranslated(); + const std::string relJsonKey = rel->getJsonKey(); std::function lclick; if(navigateCallback) - lclick = [navigateCallback, relName](){ navigateCallback(relName); }; + lclick = [navigateCallback, relJsonKey](){ navigateCallback(relJsonKey); }; const CreatureID relId(rel->getIndex()); widgets.push_back(std::make_shared( Point(MARGIN, curY), tableW, rowH, diff --git a/client/windows/wiki/WikiHeroContent.cpp b/client/windows/wiki/WikiHeroContent.cpp index ff4fd1df6..d25e8ebc5 100644 --- a/client/windows/wiki/WikiHeroContent.cpp +++ b/client/windows/wiki/WikiHeroContent.cpp @@ -343,7 +343,7 @@ std::vector> buildHeroContent( widgets.push_back(std::make_shared( MARGIN + iconW + CELL_L, curY + CELL_T, FONT_TINY, ETextAlignment::TOPLEFT, Colors::YELLOW, - LIBRARY->generaltexth->translate("vcmi.wiki.hero.column.creature"))); + LIBRARY->generaltexth->translate("core.genrltxt.42"))); widgets.push_back(std::make_shared( MARGIN + iconW + nameW + CELL_L, curY + CELL_T, FONT_TINY, ETextAlignment::TOPLEFT, Colors::YELLOW, @@ -508,8 +508,8 @@ std::vector> buildHeroContent( std::function lclick; if(navigateCallback) { - const std::string spName = sp->getNameTranslated(); - lclick = [navigateCallback, spName](){ navigateCallback(WikiCategory::SPELL, spName); }; + const std::string spId = sp->getJsonKey(); + lclick = [navigateCallback, spId](){ navigateCallback(WikiCategory::SPELL, spId); }; } const CSpell * spPtr = sp; widgets.push_back(std::make_shared( diff --git a/client/windows/wiki/WikiTownContent.cpp b/client/windows/wiki/WikiTownContent.cpp index 1d1644d05..ac5ea3f97 100644 --- a/client/windows/wiki/WikiTownContent.cpp +++ b/client/windows/wiki/WikiTownContent.cpp @@ -677,10 +677,10 @@ std::vector> buildTownContent( std::function lclick; if(navigateCallback) { - const std::string crName = row.creature->getNameSingularTranslated(); - lclick = [navigateCallback, crName]() + const std::string crId = row.creature->getJsonKey(); + lclick = [navigateCallback, crId]() { - navigateCallback(WikiCategory::CREATURE, crName); + navigateCallback(WikiCategory::CREATURE, crId); }; } const CCreature * crPtr = row.creature; @@ -798,10 +798,10 @@ curY += 8; // extra padding above section title std::function lclick; if(navigateCallback) { - const std::string hname = h->getNameTranslated(); - lclick = [navigateCallback, hname]() + const std::string heroJsonKey = h->getJsonKey(); + lclick = [navigateCallback, heroJsonKey]() { - navigateCallback(WikiCategory::HERO, hname); + navigateCallback(WikiCategory::HERO, heroJsonKey); }; } const HeroTypeID hId = h->getId(); diff --git a/client/windows/wiki/WikiWindow.cpp b/client/windows/wiki/WikiWindow.cpp index 2b86c8a3f..8e78ee20f 100644 --- a/client/windows/wiki/WikiWindow.cpp +++ b/client/windows/wiki/WikiWindow.cpp @@ -321,7 +321,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini { const std::string name = LIBRARY->generaltexth->translate(e["name"].String()); const std::string desc = LIBRARY->generaltexth->translate(e["description"].String()); - categoryEntries[iGlossary].push_back({ name, desc, std::nullopt }); + categoryEntries[iGlossary].push_back({ name, name, desc, std::nullopt }); } } catch(const std::exception &) {} // file absent → empty glossary @@ -337,7 +337,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini for(const auto & faction : LIBRARY->townh->objects) if(faction && faction->hasTown() && !faction->special) categoryEntries[iTown].push_back({ - faction->getNameTranslated(), "", + faction->getJsonKey(), faction->getNameTranslated(), "", WikiIconInfo{ AnimationPath::builtin("ITPA"), (size_t)(faction->town->clientInfo.icons[1][0] + 2), 0, std::nullopt } }); std::sort(categoryEntries[iTown].begin(), categoryEntries[iTown].end(), @@ -350,7 +350,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini for(const auto & hero : LIBRARY->heroh->objects) if(hero && !hero->special) categoryEntries[iHero].push_back({ - hero->getNameTranslated(), "", + hero->getJsonKey(), hero->getNameTranslated(), "", WikiIconInfo{ AnimationPath::builtin("PortraitsSmall"), (size_t)hero->getIconIndex(), 0, std::nullopt } }); std::sort(categoryEntries[iHero].begin(), categoryEntries[iHero].end(), @@ -372,7 +372,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini const bool isWM = warMachineCreatures.count(CreatureID(creature->getIndex())) > 0; if(!creature->special || isWM) categoryEntries[iCreature].push_back({ - creature->getNameSingularTranslated(), "", + creature->getJsonKey(), creature->getNameSingularTranslated(), "", WikiIconInfo{ AnimationPath::builtin("CPRSMALL"), (size_t)creature->getIconIndex(), 0, std::nullopt } }); } @@ -386,6 +386,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini for(const auto & artifact : LIBRARY->arth->objects) if(artifact && artifact->aClass != EArtifactClass::ART_SPECIAL) categoryEntries[iArtifact].push_back({ + artifact->getJsonKey(), artifact->getNameTranslated(), artifact->getDescriptionTranslated(), WikiIconInfo{ AnimationPath::builtin("Artifact"), (size_t)artifact->getIconIndex(), 0, std::nullopt } @@ -412,6 +413,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini } } categoryEntries[iSpell].push_back({ + spell->getJsonKey(), spell->getNameTranslated(), desc, WikiIconInfo{ AnimationPath::builtin("SpellInt"), (size_t)spell->getIndex() + 1, 0, std::nullopt } }); @@ -438,6 +440,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini } } categoryEntries[iSkill].push_back({ + skill->getJsonKey(), skill->getNameTranslated(), desc, WikiIconInfo{ AnimationPath::builtin("SECSK32"), (size_t)(skill->getIndex() * 3 + 3), 0, std::nullopt } }); @@ -469,7 +472,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini std::string desc; if(!nativeTowns.empty()) desc = "{" + LIBRARY->generaltexth->translate("vcmi.wiki.terrain.nativeTowns") + "}\n\n" + nativeTowns; - categoryEntries[iTerrain].push_back({ terrain->getNameTranslated(), desc, colorIcon }); + categoryEntries[iTerrain].push_back({ terrain->getJsonKey(), terrain->getNameTranslated(), desc, colorIcon }); } std::sort(categoryEntries[iTerrain].begin(), categoryEntries[iTerrain].end(), [](const WikiEntry & a, const WikiEntry & b){ return a.name < b.name; }); @@ -495,7 +498,7 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini searchBoxHint = std::make_shared( sbRect.center().x, sbRect.center().y, FONT_SMALL, ETextAlignment::CENTER, sbHintColor, - LIBRARY->generaltexth->translate("vcmi.wiki.search.hint")); + LIBRARY->generaltexth->translate("vcmi.spellBook.search")); searchBox = std::make_shared( sbRect, FONT_SMALL, ETextAlignment::CENTER, false); searchBox->setCallback([this](const std::string &) { onSearchInput(); }); @@ -546,10 +549,10 @@ WikiWindow::WikiWindow(WikiWindow::Style style_, std::optional ini backButton = std::make_shared( Point(COL1_X, CLOSE_Y), AnimationPath::builtin(style == Style::BLUE ? "buttonBlue80" : "settingsWindow/button80"), - CButton::tooltip("", LIBRARY->generaltexth->translate("vcmi.wiki.button.back")), + CButton::tooltip("", LIBRARY->generaltexth->translate("core.help.561.hover")), std::bind(&WikiWindow::navigateBack, this)); backButton->setOverlay(std::make_shared(0, 0, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, - LIBRARY->generaltexth->translate("vcmi.wiki.button.back"))); + LIBRARY->generaltexth->translate("core.help.561.hover"))); backButton->disable(); // hidden until there is history to go back to // Apply scroll-wheel bounds after center() so pos is finalised @@ -768,21 +771,21 @@ void WikiWindow::updateContent() { if(useTownViewport) { - const std::string & townName = currentDisplayedEntries[activeElementIndex].name; - if(townName != currentTownName) - rebuildTownViewport(townName); + const std::string & townIdentifier = currentDisplayedEntries[activeElementIndex].identifier; + if(townIdentifier != currentTownName) + rebuildTownViewport(townIdentifier); } else if(useCreatureViewport) { - const std::string & creName = currentDisplayedEntries[activeElementIndex].name; - if(creName != currentCreatureName) - rebuildCreatureViewport(creName); + const std::string & creatureIdentifier = currentDisplayedEntries[activeElementIndex].identifier; + if(creatureIdentifier != currentCreatureName) + rebuildCreatureViewport(creatureIdentifier); } else if(useHeroViewport) { - const std::string & heroName = currentDisplayedEntries[activeElementIndex].name; - if(heroName != currentHeroName) - rebuildHeroViewport(heroName); + const std::string & heroIdentifier = currentDisplayedEntries[activeElementIndex].identifier; + if(heroIdentifier != currentHeroName) + rebuildHeroViewport(heroIdentifier); } redraw(); @@ -823,16 +826,16 @@ void WikiWindow::updateContent() contentBox->setText(text); } -void WikiWindow::rebuildTownViewport(const std::string & factionName) +void WikiWindow::rebuildTownViewport(const std::string & factionIdentifier) { - currentTownName = factionName; + currentTownName = factionIdentifier; townContentWidgets.clear(); - // Look up the faction by translated name + // Look up the faction by JSON key const CFaction * faction = nullptr; for(const auto & f : LIBRARY->townh->objects) { - if(f && f->hasTown() && !f->special && f->getNameTranslated() == factionName) + if(f && f->hasTown() && !f->special && f->getJsonKey() == factionIdentifier) { faction = f.get(); break; @@ -869,16 +872,16 @@ void WikiWindow::rebuildTownViewport(const std::string & factionName) applyScrollBounds(); } -void WikiWindow::rebuildCreatureViewport(const std::string & creatureName) +void WikiWindow::rebuildCreatureViewport(const std::string & creatureIdentifier) { - currentCreatureName = creatureName; + currentCreatureName = creatureIdentifier; creatureContentWidgets.clear(); - // Look up the creature by translated name + // Look up the creature by JSON key const CCreature * creature = nullptr; for(const auto & c : LIBRARY->creh->objects) { - if(c && c->getNameSingularTranslated() == creatureName) + if(c && c->getJsonKey() == creatureIdentifier) { creature = c.get(); break; @@ -917,16 +920,16 @@ void WikiWindow::rebuildCreatureViewport(const std::string & creatureName) ENGINE->windows().totalRedraw(); } -void WikiWindow::rebuildHeroViewport(const std::string & heroName) +void WikiWindow::rebuildHeroViewport(const std::string & heroIdentifier) { - currentHeroName = heroName; + currentHeroName = heroIdentifier; heroContentWidgets.clear(); - // Look up the hero by translated name + // Look up the hero by JSON key const CHero * hero = nullptr; for(const auto & h : LIBRARY->heroh->objects) { - if(h && h->getNameTranslated() == heroName) + if(h && h->getJsonKey() == heroIdentifier) { hero = h.get(); break; @@ -985,7 +988,7 @@ void WikiWindow::onElementClicked(int index) && activeElementIndex < (int)currentDisplayedEntries.size()) { WikiCategory curCat = static_cast(activeCategoryIndex); - navHistory.push_back(WikiEntryKey{curCat, currentDisplayedEntries[activeElementIndex].name}); + navHistory.push_back(WikiEntryKey{curCat, currentDisplayedEntries[activeElementIndex].identifier}); } if(backButton) backButton->setEnabled(!navHistory.empty()); @@ -1016,7 +1019,7 @@ void WikiWindow::navigateTo(const WikiEntryKey & key) && activeElementIndex < (int)currentDisplayedEntries.size()) { WikiCategory curCat = static_cast(activeCategoryIndex); - navHistory.push_back(WikiEntryKey{curCat, currentDisplayedEntries[activeElementIndex].name}); + navHistory.push_back(WikiEntryKey{curCat, currentDisplayedEntries[activeElementIndex].identifier}); } if(backButton) backButton->setEnabled(!navHistory.empty()); @@ -1033,10 +1036,10 @@ void WikiWindow::navigateTo(const WikiEntryKey & key) categoryList->scrollTo(activeCategoryIndex); } - // Find the entry by name and select it + // Find the entry by identifier and select it for(int i = 0; i < (int)currentDisplayedEntries.size(); ++i) { - if(currentDisplayedEntries[i].name == key.entryName) + if(currentDisplayedEntries[i].identifier == key.entryName) { activeElementIndex = i; if(elementList) @@ -1093,7 +1096,7 @@ void WikiWindow::navigateBack() for(int i = 0; i < (int)currentDisplayedEntries.size(); ++i) { - if(currentDisplayedEntries[i].name == prev.entryName) + if(currentDisplayedEntries[i].identifier == prev.entryName) { activeElementIndex = i; if(elementList) diff --git a/client/windows/wiki/WikiWindow.h b/client/windows/wiki/WikiWindow.h index f7708d6c8..3f2c55a44 100644 --- a/client/windows/wiki/WikiWindow.h +++ b/client/windows/wiki/WikiWindow.h @@ -47,9 +47,10 @@ struct WikiIconInfo std::optional colorFill; ///< drawn as solid square when set (no CAnimImage) }; -/// A single wiki entry – name (translated), optional description and optional icon +/// A single wiki entry – identifier (JSON key), name (translated), optional description and optional icon struct WikiEntry { + std::string identifier; ///< unique entity identifier / JSON key (used for lookup) std::string name; ///< translated display name (shown in list) std::string description; ///< full description; empty = show auto-stub text std::optional icon; @@ -96,7 +97,7 @@ public: struct WikiEntryKey { WikiCategory category; ///< Which category tab to open - std::string entryName; ///< Translated display name of the entry (used for lookup) + std::string entryName; ///< Entity identifier / JSON key (used for lookup, not a translated string) }; /// In-game Glossary / Wiki - 800x600 stub window