1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Access to quests texts is now processed via translator

This commit is contained in:
Ivan Savenko 2022-12-27 23:17:41 +02:00
parent bdb8e0ee5c
commit 85d7b470d4
9 changed files with 118 additions and 33 deletions

View File

@ -16,6 +16,7 @@
#include "CConfigHandler.h"
#include "CModHandler.h"
#include "GameConstants.h"
#include "mapObjects/CQuest.h"
#include "VCMI_Lib.h"
#include "Terrain.h"
@ -374,7 +375,10 @@ CGeneralTextHandler::CGeneralTextHandler():
tentColors (*this, "core.tentcolr" ),
levels (*this, "core.skilllev" ),
zelp (*this, "core.help" ),
allTexts (*this, "core.genrltxt" ),
// pseudo-array, that don't have H3 file with same name
seerEmpty (*this, "core.seerhut.empty" ),
seerNames (*this, "core.seerhut.names" ),
capColors (*this, "vcmi.capitalColors" ),
qeModCommands (*this, "vcmi.quickExchange" )
{
@ -416,10 +420,11 @@ CGeneralTextHandler::CGeneralTextHandler():
{
CLegacyConfigParser parser("DATA/GENRLTXT.TXT");
parser.endLine();
size_t index = 0;
do
{
allTexts.push_back(parser.readString());
registerH3String("core.genrltxt", allTexts.size(), allTexts.back());
registerH3String("core.genrltxt", index, parser.readString());
index += 1;
}
while (parser.endLine());
}
@ -458,33 +463,30 @@ CGeneralTextHandler::CGeneralTextHandler():
for (int i = 0; i < 6; ++i)
{
seerEmpty.push_back(parser.readString());
registerH3String("core.seerhut.empty", seerEmpty.size(), seerEmpty.back());
registerH3String("core.seerhut.empty", i, parser.readString());
}
parser.endLine();
quests.resize(10);
for (int i = 0; i < 9; ++i) //9 types of quests
{
quests[i].resize(5);
std::string questName = CQuest::missionName(CQuest::Emission(1+i));
for (int j = 0; j < 5; ++j)
{
std::string questState = CQuest::missionState(j);
parser.readString(); //front description
for (int k = 0; k < 6; ++k)
{
quests[i][j].push_back(parser.readString());
registerH3String("core.seerhut.quest." + std::to_string(i) + "." + std::to_string(j), k, quests[i][j].back());
registerH3String("core.seerhut.quest." + questName + "." + questState, k, parser.readString());
}
parser.endLine();
}
}
quests[9].resize(1);
for (int k = 0; k < 6; ++k) //Time limit
{
quests[9][0].push_back(parser.readString());
registerH3String("core.seerhut.time", k, parser.readString());
}
parser.endLine();
@ -493,7 +495,7 @@ CGeneralTextHandler::CGeneralTextHandler():
for (int i = 0; i < 48; ++i)
{
seerNames.push_back(parser.readString());
registerH3String("core.seerhut.names", i, parser.readString());
parser.endLine();
}
}
@ -569,6 +571,8 @@ CGeneralTextHandler::CGeneralTextHandler():
logGlobal->warn("WoG file ZNPC00.TXT containing commander texts was not found");
}
}
dumpAllTexts();
}
int32_t CGeneralTextHandler::pluralText(const int32_t textIndex, const int32_t count) const
@ -583,6 +587,22 @@ int32_t CGeneralTextHandler::pluralText(const int32_t textIndex, const int32_t c
return textIndex + 1;
}
void CGeneralTextHandler::dumpAllTexts()
{
logGlobal->info("BEGIN TEXT EXPORT");
for ( auto const & entry : stringsLocalizations)
{
auto cleanString = entry.second;
boost::replace_all(cleanString, "\\", "\\\\");
boost::replace_all(cleanString, "\n", "\\n");
boost::replace_all(cleanString, "\r", "\\r");
boost::replace_all(cleanString, "\t", "\\t");
logGlobal->info("\"%s\" : \"%s\",", entry.first, cleanString);
}
logGlobal->info("END TEXT EXPORT");
}
std::vector<std::string> CGeneralTextHandler::findStringsWithPrefix(std::string const & prefix)
{
std::vector<std::string> result;

View File

@ -93,6 +93,7 @@ public:
class CGeneralTextHandler;
/// Small wrapper that provides text access API compatible with old code
class DLL_LINKAGE LegacyTextContainer
{
CGeneralTextHandler & owner;
@ -103,6 +104,7 @@ public:
const std::string & operator[](size_t index) const;
};
/// Small wrapper that provides help text access API compatible with old code
class DLL_LINKAGE LegacyHelpContainer
{
CGeneralTextHandler & owner;
@ -141,7 +143,10 @@ public:
/// converts identifier into user-readable string, may be identical to 'translate' but reserved for serialization calls
const std::string & deserialize(const std::string & identifier) const;
std::vector<std::string> allTexts;
/// Debug methods, dumps all currently known texts into console using Json-like format
void dumpAllTexts();
LegacyTextContainer allTexts;
LegacyTextContainer arraytxt;
LegacyTextContainer primarySkillNames;
@ -171,10 +176,8 @@ public:
LegacyTextContainer restypes; //names of resources
LegacyTextContainer terrainNames;
LegacyTextContainer randsign;
std::vector<std::string> seerEmpty;
std::vector<std::vector<std::vector<std::string>>> quests; //[quest][type][index]
//type: quest, progress, complete, rollover, log OR time limit //index: 0-2 seer hut, 3-5 border guard
std::vector<std::string> seerNames;
LegacyTextContainer seerEmpty;
LegacyTextContainer seerNames;
LegacyTextContainer tentColors;
//sec skills

View File

@ -24,7 +24,7 @@
VCMI_LIB_NAMESPACE_BEGIN
///helpers
static std::string & visitedTxt(const bool visited)
static const std::string & visitedTxt(const bool visited)
{
int id = visited ? 352 : 353;
return VLC->generaltexth->allTexts[id];

View File

@ -56,12 +56,48 @@ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16
showInfoDialog(playerID,txtID,soundID);
}
static std::string & visitedTxt(const bool visited)
static const std::string & visitedTxt(const bool visited)
{
int id = visited ? 352 : 353;
return VLC->generaltexth->allTexts[id];
}
const std::string & CQuest::missionName(CQuest::Emission mission)
{
static const std::array<std::string, 11> names = {
"empty",
"heroLevel",
"primarySkill",
"killHero",
"killCreature",
"bringArt",
"bringCreature",
"bringResources",
"bringHero",
"bringPlayer",
"keymaster,"
};
if (static_cast<size_t>(mission) < names.size())
return names[static_cast<size_t>(mission)];
return names[0];
}
const std::string & CQuest::missionState(int state)
{
static const std::array<std::string, 5> states = {
"receive",
"visit",
"complete",
"hover",
"description",
};
if (state < states.size())
return states[state];
return states[0];
}
bool CQuest::checkMissionArmy(const CQuest * q, const CCreatureSet * army)
{
std::vector<CStackBasicDescriptor>::const_iterator cre;
@ -264,7 +300,10 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
if(onHover)
ms << "\n\n";
ms << VLC->generaltexth->quests[missionType-1][onHover ? 3 : 4][textOption];
std::string questName = missionName(Emission(missionType-1));
std::string questState = missionState(onHover ? 3 : 4);
ms << VLC->generaltexth->translate("core.seerhut.quest." + questName + "." + questState,textOption);
switch(missionType)
{
@ -535,7 +574,9 @@ void CGSeerHut::setObjToKill()
void CGSeerHut::init(CRandomGenerator & rand)
{
seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, rand);
auto names = VLC->generaltexth->findStringsWithPrefix("core.seerhut.names");
seerName = *RandomGeneratorUtil::nextItem(names, rand);
quest->textOption = rand.nextInt(2);
quest->completedOption = rand.nextInt(1, 3);
}
@ -547,12 +588,14 @@ void CGSeerHut::initObj(CRandomGenerator & rand)
quest->progress = CQuest::NOT_ACTIVE;
if(quest->missionType)
{
std::string questName = quest->missionName(CQuest::Emission(quest->missionType-1));
if(!quest->isCustomFirst)
quest->firstVisitText = VLC->generaltexth->quests[quest->missionType-1][0][quest->textOption];
quest->firstVisitText = VLC->generaltexth->translate("core.seerhut.quest." + questName + "." + quest->missionState(0), quest->textOption);
if(!quest->isCustomNext)
quest->nextVisitText = VLC->generaltexth->quests[quest->missionType-1][1][quest->textOption];
quest->nextVisitText = VLC->generaltexth->translate("core.seerhut.quest." + questName + "." + quest->missionState(1), quest->textOption);
if(!quest->isCustomComplete)
quest->completedText = VLC->generaltexth->quests[quest->missionType-1][2][quest->textOption];
quest->completedText = VLC->generaltexth->translate("core.seerhut.quest." + questName + "." + quest->missionState(2), quest->textOption);
}
else
{

View File

@ -24,9 +24,28 @@ class DLL_LINKAGE CQuest final
mutable std::unordered_map<ArtifactID, unsigned, ArtifactID::hash> artifactsRequirements; // artifact ID -> required count
public:
enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4,
MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10};
enum Eprogress {NOT_ACTIVE, IN_PROGRESS, COMPLETE};
enum Emission {
MISSION_NONE = 0,
MISSION_LEVEL = 1,
MISSION_PRIMARY_STAT = 2,
MISSION_KILL_HERO = 3,
MISSION_KILL_CREATURE = 4,
MISSION_ART = 5,
MISSION_ARMY = 6,
MISSION_RESOURCES = 7,
MISSION_HERO = 8,
MISSION_PLAYER = 9,
MISSION_KEYMASTER = 10
};
enum Eprogress {
NOT_ACTIVE,
IN_PROGRESS,
COMPLETE
};
static const std::string & missionName(Emission mission);
static const std::string & missionState(int index);
si32 qid; //unique quest id for serialization / identification

View File

@ -402,7 +402,7 @@ Component CRewardInfo::getDisplayedComponent(const CGHeroInstance * h) const
}
// FIXME: copy-pasted from CObjectHandler
static std::string & visitedTxt(const bool visited)
static const std::string & visitedTxt(const bool visited)
{
int id = visited ? 352 : 353;
return VLC->generaltexth->allTexts[id];

View File

@ -58,7 +58,7 @@ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16
showInfoDialog(playerID,txtID,soundID);
}
static std::string & visitedTxt(const bool visited)
static const std::string & visitedTxt(const bool visited)
{
int id = visited ? 352 : 353;
return VLC->generaltexth->allTexts[id];

View File

@ -179,7 +179,7 @@ void Damage::describeEffect(std::vector<MetaString> & log, const Mechanics * m,
{
MetaString line;
//todo: handle newlines in metastring
std::string text = VLC->generaltexth->allTexts.at(343); //Does %d points of damage.
std::string text = VLC->generaltexth->allTexts[343]; //Does %d points of damage.
boost::algorithm::trim(text);
line << text;
line.addReplacement((int)damage); //no more text afterwards

View File

@ -1300,7 +1300,7 @@ void CGameHandler::addGenericKilledLog(BattleLogMessage & blm, const CStack * de
if(killed > 0)
{
const int32_t txtIndex = (killed > 1) ? 379 : 378;
std::string formatString = VLC->generaltexth->allTexts.at(txtIndex);
std::string formatString = VLC->generaltexth->allTexts[txtIndex];
// these default h3 texts have unnecessary new lines, so get rid of them before displaying (and trim just in case, trimming newlines does not works for some reason)
formatString.erase(std::remove(formatString.begin(), formatString.end(), '\n'), formatString.end());
@ -5209,7 +5209,7 @@ void CGameHandler::playerMessage(PlayerColor player, const std::string &message,
if (cheated)
{
SystemMessage temp_message(VLC->generaltexth->allTexts.at(260));
SystemMessage temp_message(VLC->generaltexth->allTexts[260]);
sendAndApply(&temp_message);
if(!player.isSpectator())