From fc252bb9ebd71386d97cbcb9541c2ff4afc9df96 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 19 Feb 2024 00:36:08 +0200 Subject: [PATCH] Random town names are now guaranteed to be unique on the map --- lib/CTownHandler.cpp | 5 --- lib/CTownHandler.h | 1 - lib/constants/EntityIdentifiers.cpp | 5 +++ lib/constants/EntityIdentifiers.h | 2 ++ lib/gameState/CGameState.cpp | 56 ++++++++++++++++++++++++----- lib/gameState/CGameState.h | 1 + 6 files changed, 56 insertions(+), 14 deletions(-) diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index df3e33f57..2544c4a9c 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -243,11 +243,6 @@ CTown::~CTown() str.dellNull(); } -std::string CTown::getRandomNameTranslated(size_t index) const -{ - return VLC->generaltexth->translate(getRandomNameTextID(index)); -} - std::string CTown::getRandomNameTextID(size_t index) const { return TextIdentifier("faction", faction->modScope, faction->identifier, "randomName", index).get(); diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 97bfa325f..5af1d661b 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -217,7 +217,6 @@ public: void setGreeting(BuildingSubID::EBuildingSubID subID, const std::string & message) const; //may affect only mutable field BuildingID getBuildingType(BuildingSubID::EBuildingSubID subID) const; - std::string getRandomNameTranslated(size_t index) const; std::string getRandomNameTextID(size_t index) const; size_t getRandomNamesCount() const; diff --git a/lib/constants/EntityIdentifiers.cpp b/lib/constants/EntityIdentifiers.cpp index 8fb932e2e..d1d2b66c6 100644 --- a/lib/constants/EntityIdentifiers.cpp +++ b/lib/constants/EntityIdentifiers.cpp @@ -458,6 +458,11 @@ std::string FactionID::entityType() return "faction"; } +const CFaction * FactionID::toFaction() const +{ + return dynamic_cast(toEntity(VLC)); +} + const Faction * FactionID::toEntity(const Services * service) const { return service->factions()->getByIndex(num); diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index 070d26492..387994014 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -24,6 +24,7 @@ class CHero; class CHeroClass; class HeroClass; class HeroTypeService; +class CFaction; class Faction; class Skill; class RoadType; @@ -261,6 +262,7 @@ public: static si32 decode(const std::string& identifier); static std::string encode(const si32 index); + const CFaction * toFaction() const; const Faction * toEntity(const Services * service) const; static std::string entityType(); diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index cfa55c4d7..36a92a96f 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -222,6 +222,7 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, Load::Prog initHeroes(); initStartingBonus(); initTowns(); + initTownNames(); placeHeroesInTowns(); initMapObjects(); buildBonusSystemTree(); @@ -763,6 +764,51 @@ void CGameState::initStartingBonus() } } +void CGameState::initTownNames() +{ + std::map> availableNames; + for (auto const & faction : VLC->townh->getDefaultAllowed()) + { + std::vector potentialNames; + if (faction.toFaction()->town->getRandomNamesCount() > 0) + { + for (int i = 0; i < faction.toFaction()->town->getRandomNamesCount(); ++i) + potentialNames.push_back(i); + + availableNames[faction] = potentialNames; + } + } + + for (auto & elem : map->towns) + { + CGTownInstance * vti =(elem); + assert(vti->town); + + if(!vti->getNameTextID().empty()) + continue; + + FactionID faction = vti->getFaction(); + + if (availableNames.empty()) + { + logGlobal->warn("Failed to find available name for a random town!"); + vti->setNameTextId("core.genrltxt.508"); // Unnamed + continue; + } + + // If town has no available names (for example - all were picked) - pick names from some other faction that still has names available + if (!availableNames.count(faction)) + faction = RandomGeneratorUtil::nextItem(availableNames, getRandomGenerator())->first; + + auto nameIt = RandomGeneratorUtil::nextItem(availableNames[faction], getRandomGenerator()); + vti->setNameTextId(faction.toFaction()->town->getRandomNameTextID(*nameIt)); + + availableNames[faction].erase(nameIt); + if (availableNames[faction].empty()) + availableNames.erase(faction); + } +} + void CGameState::initTowns() { logGlobal->debug("\tTowns"); @@ -777,15 +823,9 @@ void CGameState::initTowns() map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC)); for (auto & elem : map->towns) - { - CGTownInstance * vti =(elem); - assert(vti->town); - - if(vti->getNameTextID().empty()) { - size_t nameID = getRandomGenerator().nextInt(vti->getTown()->getRandomNamesCount() - 1); - vti->setNameTextId(vti->getTown()->getRandomNameTextID(nameID)); - } + CGTownInstance * vti =(elem); + assert(vti->town); static const BuildingID basicDwellings[] = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7 }; static const BuildingID upgradedDwellings[] = { BuildingID::DWELL_UP_FIRST, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP, BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP }; diff --git a/lib/gameState/CGameState.h b/lib/gameState/CGameState.h index f3de9cdd7..ce2a4b102 100644 --- a/lib/gameState/CGameState.h +++ b/lib/gameState/CGameState.h @@ -212,6 +212,7 @@ private: void initFogOfWar(); void initStartingBonus(); void initTowns(); + void initTownNames(); void initMapObjects(); void initVisitingAndGarrisonedHeroes(); void initCampaign();