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

Renamed MetaString methods to more logical names

This commit is contained in:
Ivan Savenko 2023-06-18 12:18:25 +03:00
parent 2636a0dcc3
commit 56d69e790b
32 changed files with 592 additions and 557 deletions

View File

@ -270,14 +270,14 @@ void CPlayerInterface::acceptTurn()
auto daysWithoutCastle = optDaysWithoutCastle.value(); auto daysWithoutCastle = optDaysWithoutCastle.value();
if (daysWithoutCastle < 6) if (daysWithoutCastle < 6)
{ {
text.addTxt(MetaString::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land. text.appendLocalString(EMetaText::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land.
text.addReplacement(MetaString::COLOR, playerColor.getNum()); text.replaceLocalString(EMetaText::COLOR, playerColor.getNum());
text.addReplacement(7 - daysWithoutCastle); text.replaceNumber(7 - daysWithoutCastle);
} }
else if (daysWithoutCastle == 6) else if (daysWithoutCastle == 6)
{ {
text.addTxt(MetaString::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land. text.appendLocalString(EMetaText::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land.
text.addReplacement(MetaString::COLOR, playerColor.getNum()); text.replaceLocalString(EMetaText::COLOR, playerColor.getNum());
} }
showInfoDialogAndWait(components, text); showInfoDialogAndWait(components, text);
@ -1048,8 +1048,7 @@ void CPlayerInterface::showInfoDialogAndWait(std::vector<Component> & components
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
std::string str; std::string str = text.toString();
text.toString(str);
showInfoDialog(EInfoWindowMode::MODAL, str, components, 0); showInfoDialog(EInfoWindowMode::MODAL, str, components, 0);
waitWhileDialog(); waitWhileDialog();

View File

@ -600,8 +600,7 @@ void ApplyFirstClientNetPackVisitor::visitGiveHero(GiveHero & pack)
void ApplyClientNetPackVisitor::visitInfoWindow(InfoWindow & pack) void ApplyClientNetPackVisitor::visitInfoWindow(InfoWindow & pack)
{ {
std::string str; std::string str = pack.text.toString();
pack.text.toString(str);
if(!callInterfaceIfPresent(cl, pack.player, &CGameInterface::showInfoDialog, pack.type, str, pack.components,(soundBase::soundID)pack.soundID)) if(!callInterfaceIfPresent(cl, pack.player, &CGameInterface::showInfoDialog, pack.type, str, pack.components,(soundBase::soundID)pack.soundID))
logNetwork->warn("We received InfoWindow for not our player..."); logNetwork->warn("We received InfoWindow for not our player...");
@ -643,8 +642,7 @@ void ApplyClientNetPackVisitor::visitCommanderLevelUp(CommanderLevelUp & pack)
void ApplyClientNetPackVisitor::visitBlockingDialog(BlockingDialog & pack) void ApplyClientNetPackVisitor::visitBlockingDialog(BlockingDialog & pack)
{ {
std::string str; std::string str = pack.text.toString();
pack.text.toString(str);
if(!callOnlyThatInterface(cl, pack.player, &CGameInterface::showBlockingDialog, str, pack.components, pack.queryID, (soundBase::soundID)pack.soundID, pack.selection(), pack.cancel())) if(!callOnlyThatInterface(cl, pack.player, &CGameInterface::showBlockingDialog, str, pack.components, pack.queryID, (soundBase::soundID)pack.soundID, pack.selection(), pack.cancel()))
logNetwork->warn("We received YesNoDialog for not our player..."); logNetwork->warn("We received YesNoDialog for not our player...");

View File

@ -167,12 +167,12 @@ void CQuestLog::recreateLabelList()
if (auto seersHut = dynamic_cast<const CGSeerHut *>(quests[i].obj)) if (auto seersHut = dynamic_cast<const CGSeerHut *>(quests[i].obj))
{ {
MetaString toSeer; MetaString toSeer;
toSeer.addRawString(VLC->generaltexth->allTexts[347]); toSeer.appendRawString(VLC->generaltexth->allTexts[347]);
toSeer.addReplacement(seersHut->seerName); toSeer.replaceRawString(seersHut->seerName);
text.addReplacement(toSeer.toString()); text.replaceRawString(toSeer.toString());
} }
else else
text.addReplacement(quests[i].obj->getObjectName()); //get name of the object text.replaceRawString(quests[i].obj->getObjectName()); //get name of the object
} }
auto label = std::make_shared<CQuestLabel>(Rect(13, 195, 149,31), FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, text.toString()); auto label = std::make_shared<CQuestLabel>(Rect(13, 195, 149,31), FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, text.toString());
label->disable(); label->disable();

View File

@ -1,5 +1,5 @@
/* /*
* CGameState.cpp, part of VCMI engine * MetaString.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@ -22,176 +22,202 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
void MetaString::getLocalString(const std::pair<ui8, ui32> & txt, std::string & dst) const void MetaString::appendLocalString(EMetaText type, ui32 serial)
{ {
int type = txt.first; message.push_back(EMessage::APPEND_LOCAL_STRING);
localStrings.emplace_back(type, serial);
}
void MetaString::appendRawString(std::string value)
{
message.push_back(EMessage::APPEND_RAW_STRING);
exactStrings.push_back(value);
}
void MetaString::appendNumber(int64_t value)
{
message.push_back(EMessage::APPEND_NUMBER);
numbers.push_back(value);
}
void MetaString::replaceLocalString(EMetaText type, ui32 serial)
{
message.push_back(EMessage::REPLACE_LOCAL_STRING);
localStrings.emplace_back(type, serial);
}
void MetaString::replaceRawString(const std::string &txt)
{
message.push_back(EMessage::REPLACE_RAW_STRING);
exactStrings.push_back(txt);
}
void MetaString::replaceNumber(int64_t txt)
{
message.push_back(EMessage::REPLACE_NUMBER);
numbers.push_back(txt);
}
void MetaString::replacePositiveNumber(int64_t txt)
{
message.push_back(EMessage::REPLACE_POSITIVE_NUMBER);
numbers.push_back(txt);
}
void MetaString::clear()
{
exactStrings.clear();
localStrings.clear();
message.clear();
numbers.clear();
}
bool MetaString::empty() const
{
return message.empty();
}
std::string MetaString::getLocalString(const std::pair<EMetaText, ui32> & txt) const
{
EMetaText type = txt.first;
int ser = txt.second; int ser = txt.second;
if(type == ART_NAMES) switch(type)
{ {
const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts()); case EMetaText::ART_NAMES:
if(art)
dst = art->getNameTranslated();
else
dst = "#!#";
}
else if(type == ART_DESCR)
{
const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
if(art)
dst = art->getDescriptionTranslated();
else
dst = "#!#";
}
else if (type == ART_EVNTS)
{
const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
if(art)
dst = art->getEventTranslated();
else
dst = "#!#";
}
else if(type == CRE_PL_NAMES)
{
const auto * cre = CreatureID(ser).toCreature(VLC->creatures());
if(cre)
dst = cre->getNamePluralTranslated();
else
dst = "#!#";
}
else if(type == CRE_SING_NAMES)
{
const auto * cre = CreatureID(ser).toCreature(VLC->creatures());
if(cre)
dst = cre->getNameSingularTranslated();
else
dst = "#!#";
}
else if(type == MINE_NAMES)
{
dst = VLC->generaltexth->translate("core.minename", ser);
}
else if(type == MINE_EVNTS)
{
dst = VLC->generaltexth->translate("core.mineevnt", ser);
}
else if(type == SPELL_NAME)
{
const auto * spell = SpellID(ser).toSpell(VLC->spells());
if(spell)
dst = spell->getNameTranslated();
else
dst = "#!#";
}
else if(type == OBJ_NAMES)
{
dst = VLC->objtypeh->getObjectName(ser, 0);
}
else if(type == SEC_SKILL_NAME)
{
dst = VLC->skillh->getByIndex(ser)->getNameTranslated();
}
else
{
switch(type)
{ {
case GENERAL_TXT: const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
dst = VLC->generaltexth->translate("core.genrltxt", ser); if(art)
break; return art->getNameTranslated();
case RES_NAMES: return "#!#";
dst = VLC->generaltexth->translate("core.restypes", ser);
break;
case ARRAY_TXT:
dst = VLC->generaltexth->translate("core.arraytxt", ser);
break;
case CREGENS:
dst = VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR1, ser);
break;
case CREGENS4:
dst = VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR4, ser);
break;
case ADVOB_TXT:
dst = VLC->generaltexth->translate("core.advevent", ser);
break;
case COLOR:
dst = VLC->generaltexth->translate("vcmi.capitalColors", ser);
break;
case JK_TXT:
dst = VLC->generaltexth->translate("core.jktext", ser);
break;
default:
logGlobal->error("Failed string substitution because type is %d", type);
dst = "#@#";
return;
} }
case EMetaText::ART_DESCR:
{
const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
if(art)
return art->getDescriptionTranslated();
return "#!#";
}
case EMetaText::ART_EVNTS:
{
const auto * art = ArtifactID(ser).toArtifact(VLC->artifacts());
if(art)
return art->getEventTranslated();
return "#!#";
}
case EMetaText::CRE_PL_NAMES:
{
const auto * cre = CreatureID(ser).toCreature(VLC->creatures());
if(cre)
return cre->getNamePluralTranslated();
return "#!#";
}
case EMetaText::CRE_SING_NAMES:
{
const auto * cre = CreatureID(ser).toCreature(VLC->creatures());
if(cre)
return cre->getNameSingularTranslated();
return "#!#";
}
case EMetaText::MINE_NAMES:
{
return VLC->generaltexth->translate("core.minename", ser);
}
case EMetaText::MINE_EVNTS:
{
return VLC->generaltexth->translate("core.mineevnt", ser);
}
case EMetaText::SPELL_NAME:
{
const auto * spell = SpellID(ser).toSpell(VLC->spells());
if(spell)
return spell->getNameTranslated();
return "#!#";
}
case EMetaText::OBJ_NAMES:
return VLC->objtypeh->getObjectName(ser, 0);
case EMetaText::SEC_SKILL_NAME:
return VLC->skillh->getByIndex(ser)->getNameTranslated();
case EMetaText::GENERAL_TXT:
return VLC->generaltexth->translate("core.genrltxt", ser);
case EMetaText::RES_NAMES:
return VLC->generaltexth->translate("core.restypes", ser);
case EMetaText::ARRAY_TXT:
return VLC->generaltexth->translate("core.arraytxt", ser);
case EMetaText::CREGENS:
return VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR1, ser);
case EMetaText::CREGENS4:
return VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR4, ser);
case EMetaText::ADVOB_TXT:
return VLC->generaltexth->translate("core.advevent", ser);
case EMetaText::COLOR:
return VLC->generaltexth->translate("vcmi.capitalColors", ser);
case EMetaText::JK_TXT:
return VLC->generaltexth->translate("core.jktext", ser);
default:
logGlobal->error("Failed string substitution because type is %d", static_cast<int>(type));
return "#@#";
} }
} }
DLL_LINKAGE void MetaString::toString(std::string &dst) const DLL_LINKAGE std::string MetaString::toString() const
{ {
std::string dst;
size_t exSt = 0; size_t exSt = 0;
size_t loSt = 0; size_t loSt = 0;
size_t nums = 0; size_t nums = 0;
dst.clear(); dst.clear();
for(const auto & elem : message) for(const auto & elem : message)
{//TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER {
switch(elem) switch(elem)
{ {
case TEXACT_STRING: case EMessage::APPEND_RAW_STRING:
dst += exactStrings[exSt++]; dst += exactStrings[exSt++];
break; break;
case TLOCAL_STRING: case EMessage::APPEND_LOCAL_STRING:
{ {
std::string hlp; std::string hlp = getLocalString(localStrings[loSt++]);
getLocalString(localStrings[loSt++], hlp);
dst += hlp; dst += hlp;
} }
break; break;
case TNUMBER: case EMessage::APPEND_NUMBER:
dst += std::to_string(numbers[nums++]); dst += std::to_string(numbers[nums++]);
break; break;
case TREPLACE_ESTRING: case EMessage::REPLACE_RAW_STRING:
boost::replace_first(dst, "%s", exactStrings[exSt++]); boost::replace_first(dst, "%s", exactStrings[exSt++]);
break; break;
case TREPLACE_LSTRING: case EMessage::REPLACE_LOCAL_STRING:
{ {
std::string hlp; std::string hlp = getLocalString(localStrings[loSt++]);
getLocalString(localStrings[loSt++], hlp);
boost::replace_first(dst, "%s", hlp); boost::replace_first(dst, "%s", hlp);
} }
break; break;
case TREPLACE_NUMBER: case EMessage::REPLACE_NUMBER:
boost::replace_first(dst, "%d", std::to_string(numbers[nums++])); boost::replace_first(dst, "%d", std::to_string(numbers[nums++]));
break; break;
case TREPLACE_PLUSNUMBER: case EMessage::REPLACE_POSITIVE_NUMBER:
boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++])); boost::replace_first(dst, "%+d", '+' + std::to_string(numbers[nums++]));
break; break;
default: default:
logGlobal->error("MetaString processing error! Received message of type %d", int(elem)); logGlobal->error("MetaString processing error! Received message of type %d", static_cast<int>(elem));
assert(0);
break; break;
} }
} }
} return dst;
DLL_LINKAGE std::string MetaString::toString() const
{
std::string ret;
toString(ret);
return ret;
} }
DLL_LINKAGE std::string MetaString::buildList () const DLL_LINKAGE std::string MetaString::buildList () const
///used to handle loot from creature bank
{ {
size_t exSt = 0; size_t exSt = 0;
size_t loSt = 0; size_t loSt = 0;
size_t nums = 0; size_t nums = 0;
std::string lista; std::string lista;
for (int i = 0; i < message.size(); ++i) for (int i = 0; i < message.size(); ++i)
{ {
if (i > 0 && (message[i] == TEXACT_STRING || message[i] == TLOCAL_STRING)) if (i > 0 && (message[i] == EMessage::APPEND_RAW_STRING || message[i] == EMessage::APPEND_LOCAL_STRING))
{ {
if (exSt == exactStrings.size() - 1) if (exSt == exactStrings.size() - 1)
lista += VLC->generaltexth->allTexts[141]; //" and " lista += VLC->generaltexth->allTexts[141]; //" and "
@ -200,30 +226,28 @@ DLL_LINKAGE std::string MetaString::buildList () const
} }
switch (message[i]) switch (message[i])
{ {
case TEXACT_STRING: case EMessage::APPEND_RAW_STRING:
lista += exactStrings[exSt++]; lista += exactStrings[exSt++];
break; break;
case TLOCAL_STRING: case EMessage::APPEND_LOCAL_STRING:
{ {
std::string hlp; std::string hlp = getLocalString (localStrings[loSt++]);
getLocalString (localStrings[loSt++], hlp);
lista += hlp; lista += hlp;
} }
break; break;
case TNUMBER: case EMessage::APPEND_NUMBER:
lista += std::to_string(numbers[nums++]); lista += std::to_string(numbers[nums++]);
break; break;
case TREPLACE_ESTRING: case EMessage::REPLACE_RAW_STRING:
lista.replace (lista.find("%s"), 2, exactStrings[exSt++]); lista.replace (lista.find("%s"), 2, exactStrings[exSt++]);
break; break;
case TREPLACE_LSTRING: case EMessage::REPLACE_LOCAL_STRING:
{ {
std::string hlp; std::string hlp = getLocalString (localStrings[loSt++]);
getLocalString (localStrings[loSt++], hlp);
lista.replace (lista.find("%s"), 2, hlp); lista.replace (lista.find("%s"), 2, hlp);
} }
break; break;
case TREPLACE_NUMBER: case EMessage::REPLACE_NUMBER:
lista.replace (lista.find("%d"), 2, std::to_string(numbers[nums++])); lista.replace (lista.find("%d"), 2, std::to_string(numbers[nums++]));
break; break;
default: default:
@ -234,20 +258,18 @@ DLL_LINKAGE std::string MetaString::buildList () const
return lista; return lista;
} }
void MetaString::addCreReplacement(const CreatureID & id, TQuantity count) //adds sing or plural name; void MetaString::replaceCreatureName(const CreatureID & id, TQuantity count) //adds sing or plural name;
{ {
if (!count) if (count == 1)
addReplacement (CRE_PL_NAMES, id); //no creatures - just empty name (eg. defeat Angels) replaceLocalString (EMetaText::CRE_SING_NAMES, id);
else if (count == 1)
addReplacement (CRE_SING_NAMES, id);
else else
addReplacement (CRE_PL_NAMES, id); replaceLocalString (EMetaText::CRE_PL_NAMES, id);
} }
void MetaString::addReplacement(const CStackBasicDescriptor & stack) void MetaString::replaceCreatureName(const CStackBasicDescriptor & stack)
{ {
assert(stack.type); //valid type assert(stack.type); //valid type
addCreReplacement(stack.type->getId(), stack.count); replaceCreatureName(stack.type->getId(), stack.count);
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -15,20 +15,84 @@ class CreatureID;
class CStackBasicDescriptor; class CStackBasicDescriptor;
using TQuantity = si32; using TQuantity = si32;
enum class EMetaText : uint8_t
{
GENERAL_TXT = 1,
OBJ_NAMES,
RES_NAMES,
ART_NAMES,
ARRAY_TXT,
CRE_PL_NAMES,
CREGENS,
MINE_NAMES,
MINE_EVNTS,
ADVOB_TXT,
ART_EVNTS,
SPELL_NAME,
SEC_SKILL_NAME,
CRE_SING_NAMES,
CREGENS4,
COLOR,
ART_DESCR,
JK_TXT
};
class DLL_LINKAGE MetaString class DLL_LINKAGE MetaString
{ {
private: private:
enum EMessage {TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER, TREPLACE_PLUSNUMBER}; enum class EMessage : uint8_t
public: {
enum {GENERAL_TXT=1, OBJ_NAMES, RES_NAMES, ART_NAMES, ARRAY_TXT, CRE_PL_NAMES, CREGENS, MINE_NAMES, APPEND_RAW_STRING,
MINE_EVNTS, ADVOB_TXT, ART_EVNTS, SPELL_NAME, SEC_SKILL_NAME, CRE_SING_NAMES, CREGENS4, COLOR, ART_DESCR, JK_TXT}; APPEND_LOCAL_STRING,
APPEND_NUMBER,
REPLACE_RAW_STRING,
REPLACE_LOCAL_STRING,
REPLACE_NUMBER,
REPLACE_POSITIVE_NUMBER
};
std::vector<ui8> message; //vector of EMessage std::vector<EMessage> message;
std::vector<std::pair<ui8,ui32> > localStrings; std::vector<std::pair<EMetaText,ui32> > localStrings;
std::vector<std::string> exactStrings; std::vector<std::string> exactStrings;
std::vector<int64_t> numbers; std::vector<int64_t> numbers;
std::string getLocalString(const std::pair<EMetaText, ui32> & txt) const;
public:
/// Appends local string to resulting string
void appendLocalString(EMetaText type, ui32 serial);
/// Appends raw string, without translation to resulting string
void appendRawString(std::string value);
/// Appends specified number to resulting string
void appendNumber(int64_t value);
/// Replaces first '%s' placeholder in string with specified local string
void replaceLocalString(EMetaText type, ui32 serial);
/// Replaces first '%s' placeholder in string with specified fixed, untranslated string
void replaceRawString(const std::string &txt);
/// Replaces first '%d' placeholder in string with specified number
void replaceNumber(int64_t txt);
/// Replaces first '%+d' placeholder in string with specified number using '+' sign as prefix
void replacePositiveNumber(int64_t txt);
/// Replaces first '%s' placeholder with singular or plural name depending on creatures count
void replaceCreatureName(const CreatureID & id, TQuantity count);
/// Replaces first '%s' placeholder with singular or plural name depending on creatures count
void replaceCreatureName(const CStackBasicDescriptor &stack);
/// erases any existing content in the string
void clear();
///used to handle loot from creature bank
std::string buildList () const;
/// Convert all stored values into a single, user-readable string
std::string toString() const;
/// Returns true if current string is empty
bool empty() const;
template <typename Handler> void serialize(Handler & h, const int version) template <typename Handler> void serialize(Handler & h, const int version)
{ {
h & exactStrings; h & exactStrings;
@ -36,55 +100,6 @@ public:
h & message; h & message;
h & numbers; h & numbers;
} }
void addTxt(ui8 type, ui32 serial)
{
message.push_back(TLOCAL_STRING);
localStrings.emplace_back(type, serial);
}
void addRawString(std::string value)
{
message.push_back(TEXACT_STRING);
exactStrings.push_back(value);
}
void appendNumber(int64_t value)
{
message.push_back(TNUMBER);
numbers.push_back(value);
}
void addReplacement(ui8 type, ui32 serial)
{
message.push_back(TREPLACE_LSTRING);
localStrings.emplace_back(type, serial);
}
void addReplacement(const std::string &txt)
{
message.push_back(TREPLACE_ESTRING);
exactStrings.push_back(txt);
}
void addReplacement(int64_t txt)
{
message.push_back(TREPLACE_NUMBER);
numbers.push_back(txt);
}
void addReplacement2(int64_t txt)
{
message.push_back(TREPLACE_PLUSNUMBER);
numbers.push_back(txt);
}
void addCreReplacement(const CreatureID & id, TQuantity count); //adds sing or plural name;
void addReplacement(const CStackBasicDescriptor &stack); //adds sing or plural name;
std::string buildList () const;
void clear()
{
exactStrings.clear();
localStrings.clear();
message.clear();
numbers.clear();
}
void toString(std::string &dst) const;
std::string toString() const;
void getLocalString(const std::pair<ui8, ui32> & txt, std::string & dst) const;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -985,7 +985,7 @@ void GiveBonus::applyGs(CGameState *gs)
std::string &descr = b->description; std::string &descr = b->description;
if(bdescr.message.empty() && (bonus.type == BonusType::LUCK || bonus.type == BonusType::MORALE)) if(bdescr.empty() && (bonus.type == BonusType::LUCK || bonus.type == BonusType::MORALE))
{ {
if (bonus.source == BonusSource::OBJECT) if (bonus.source == BonusSource::OBJECT)
{ {
@ -998,12 +998,12 @@ void GiveBonus::applyGs(CGameState *gs)
} }
else else
{ {
bdescr.toString(descr); descr = bdescr.toString();
} }
} }
else else
{ {
bdescr.toString(descr); descr = bdescr.toString();
} }
// Some of(?) versions of H3 use %s here instead of %d. Try to replace both of them // Some of(?) versions of H3 use %s here instead of %d. Try to replace both of them
boost::replace_first(descr, "%d", std::to_string(std::abs(bonus.val))); boost::replace_first(descr, "%d", std::to_string(std::abs(bonus.val)));

View File

@ -482,10 +482,10 @@ void CUnitState::getCasterName(MetaString & text) const
void CUnitState::getCastDescription(const spells::Spell * spell, const std::vector<const Unit *> & attacked, MetaString & text) const void CUnitState::getCastDescription(const spells::Spell * spell, const std::vector<const Unit *> & attacked, MetaString & text) const
{ {
text.addTxt(MetaString::GENERAL_TXT, 565);//The %s casts %s text.appendLocalString(EMetaText::GENERAL_TXT, 565);//The %s casts %s
//todo: use text 566 for single creature //todo: use text 566 for single creature
getCasterName(text); getCasterName(text);
text.addReplacement(MetaString::SPELL_NAME, spell->getIndex()); text.replaceLocalString(EMetaText::SPELL_NAME, spell->getIndex());
} }
int32_t CUnitState::manaLimit() const int32_t CUnitState::manaLimit() const

View File

@ -173,7 +173,7 @@ BattleHex Unit::occupiedHex(BattleHex assumedPos, bool twoHex, ui8 side)
} }
} }
void Unit::addText(MetaString & text, ui8 type, int32_t serial, const boost::logic::tribool & plural) const void Unit::addText(MetaString & text, EMetaText type, int32_t serial, const boost::logic::tribool & plural) const
{ {
if(boost::logic::indeterminate(plural)) if(boost::logic::indeterminate(plural))
serial = VLC->generaltexth->pluralText(serial, getCount()); serial = VLC->generaltexth->pluralText(serial, getCount());
@ -182,17 +182,17 @@ void Unit::addText(MetaString & text, ui8 type, int32_t serial, const boost::log
else else
serial = VLC->generaltexth->pluralText(serial, 1); serial = VLC->generaltexth->pluralText(serial, 1);
text.addTxt(type, serial); text.appendLocalString(type, serial);
} }
void Unit::addNameReplacement(MetaString & text, const boost::logic::tribool & plural) const void Unit::addNameReplacement(MetaString & text, const boost::logic::tribool & plural) const
{ {
if(boost::logic::indeterminate(plural)) if(boost::logic::indeterminate(plural))
text.addCreReplacement(creatureId(), getCount()); text.replaceCreatureName(creatureId(), getCount());
else if(plural) else if(plural)
text.addReplacement(MetaString::CRE_PL_NAMES, creatureIndex()); text.replaceLocalString(EMetaText::CRE_PL_NAMES, creatureIndex());
else else
text.addReplacement(MetaString::CRE_SING_NAMES, creatureIndex()); text.replaceLocalString(EMetaText::CRE_SING_NAMES, creatureIndex());
} }
std::string Unit::formatGeneralMessage(const int32_t baseTextId) const std::string Unit::formatGeneralMessage(const int32_t baseTextId) const
@ -200,8 +200,8 @@ std::string Unit::formatGeneralMessage(const int32_t baseTextId) const
const int32_t textId = VLC->generaltexth->pluralText(baseTextId, getCount()); const int32_t textId = VLC->generaltexth->pluralText(baseTextId, getCount());
MetaString text; MetaString text;
text.addTxt(MetaString::GENERAL_TXT, textId); text.appendLocalString(EMetaText::GENERAL_TXT, textId);
text.addCreReplacement(creatureId(), getCount()); text.replaceCreatureName(creatureId(), getCount());
return text.toString(); return text.toString();
} }

View File

@ -21,6 +21,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
enum class EMetaText : uint8_t;
class MetaString; class MetaString;
class JsonNode; class JsonNode;
class JsonSerializeFormat; class JsonSerializeFormat;
@ -122,7 +123,7 @@ public:
static BattleHex occupiedHex(BattleHex assumedPos, bool twoHex, ui8 side); static BattleHex occupiedHex(BattleHex assumedPos, bool twoHex, ui8 side);
///MetaStrings ///MetaStrings
void addText(MetaString & text, ui8 type, int32_t serial, const boost::logic::tribool & plural = boost::logic::indeterminate) const; void addText(MetaString & text, EMetaText type, int32_t serial, const boost::logic::tribool & plural = boost::logic::indeterminate) const;
void addNameReplacement(MetaString & text, const boost::logic::tribool & plural = boost::logic::indeterminate) const; void addNameReplacement(MetaString & text, const boost::logic::tribool & plural = boost::logic::indeterminate) const;
std::string formatGeneralMessage(const int32_t baseTextId) const; std::string formatGeneralMessage(const int32_t baseTextId) const;

View File

@ -26,9 +26,9 @@ void ShrineInstanceConstructor::randomizeObject(CGShrine * shrine, CRandomGenera
auto visitTextParameter = parameters["visitText"]; auto visitTextParameter = parameters["visitText"];
if (visitTextParameter.isNumber()) if (visitTextParameter.isNumber())
shrine->visitText.addTxt(MetaString::ADVOB_TXT, static_cast<ui32>(visitTextParameter.Float())); shrine->visitText.appendLocalString(EMetaText::ADVOB_TXT, static_cast<ui32>(visitTextParameter.Float()));
else else
shrine->visitText.addRawString(visitTextParameter.String()); shrine->visitText.appendRawString(visitTextParameter.String());
if(shrine->spell == SpellID::NONE) // shrine has no predefined spell if(shrine->spell == SpellID::NONE) // shrine has no predefined spell
{ {

View File

@ -123,9 +123,9 @@ void CBank::onHeroVisit(const CGHeroInstance * h) const
BlockingDialog bd(true, false); BlockingDialog bd(true, false);
bd.player = h->getOwner(); bd.player = h->getOwner();
bd.soundID = soundBase::invalid; // Sound is handled in json files, else two sounds are played bd.soundID = soundBase::invalid; // Sound is handled in json files, else two sounds are played
bd.text.addTxt(MetaString::ADVOB_TXT, banktext); bd.text.appendLocalString(EMetaText::ADVOB_TXT, banktext);
if (banktext == 32) if (banktext == 32)
bd.text.addReplacement(getObjectName()); bd.text.replaceRawString(getObjectName());
cb->showBlockingDialog(&bd); cb->showBlockingDialog(&bd);
} }
@ -179,15 +179,15 @@ void CBank::doVisit(const CGHeroInstance * hero) const
{ {
case Obj::SHIPWRECK: case Obj::SHIPWRECK:
textID = 123; textID = 123;
gbonus.bdescr.addRawString(VLC->generaltexth->arraytxt[99]); gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[99]);
break; break;
case Obj::DERELICT_SHIP: case Obj::DERELICT_SHIP:
textID = 42; textID = 42;
gbonus.bdescr.addRawString(VLC->generaltexth->arraytxt[101]); gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[101]);
break; break;
case Obj::CRYPT: case Obj::CRYPT:
textID = 120; textID = 120;
gbonus.bdescr.addRawString(VLC->generaltexth->arraytxt[98]); gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[98]);
break; break;
} }
cb->giveHeroBonus(&gbonus); cb->giveHeroBonus(&gbonus);
@ -208,12 +208,12 @@ void CBank::doVisit(const CGHeroInstance * hero) const
case Obj::CREATURE_BANK: case Obj::CREATURE_BANK:
case Obj::DRAGON_UTOPIA: case Obj::DRAGON_UTOPIA:
default: default:
iw.text.addRawString(VLC->generaltexth->advobtxt[33]);// This was X, now is completely empty iw.text.appendRawString(VLC->generaltexth->advobtxt[33]);// This was X, now is completely empty
iw.text.addReplacement(getObjectName()); iw.text.replaceRawString(getObjectName());
} }
if(textID != -1) if(textID != -1)
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, textID); iw.text.appendLocalString(EMetaText::ADVOB_TXT, textID);
} }
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
@ -227,9 +227,9 @@ void CBank::doVisit(const CGHeroInstance * hero) const
if (bc->resources[it] != 0) if (bc->resources[it] != 0)
{ {
iw.components.emplace_back(Component::EComponentType::RESOURCE, it, bc->resources[it], 0); iw.components.emplace_back(Component::EComponentType::RESOURCE, it, bc->resources[it], 0);
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(iw.components.back().val); loot.replaceNumber(iw.components.back().val);
loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype); loot.replaceLocalString(EMetaText::RES_NAMES, iw.components.back().subtype);
cb->giveResource(hero->getOwner(), static_cast<EGameResID>(it), bc->resources[it]); cb->giveResource(hero->getOwner(), static_cast<EGameResID>(it), bc->resources[it]);
} }
} }
@ -237,14 +237,14 @@ void CBank::doVisit(const CGHeroInstance * hero) const
for (auto & elem : bc->artifacts) for (auto & elem : bc->artifacts)
{ {
iw.components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0); iw.components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0);
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(MetaString::ART_NAMES, elem); loot.replaceLocalString(EMetaText::ART_NAMES, elem);
cb->giveHeroNewArtifact(hero, VLC->arth->objects[elem], ArtifactPosition::FIRST_AVAILABLE); cb->giveHeroNewArtifact(hero, VLC->arth->objects[elem], ArtifactPosition::FIRST_AVAILABLE);
} }
//display loot //display loot
if (!iw.components.empty()) if (!iw.components.empty())
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, textID); iw.text.appendLocalString(EMetaText::ADVOB_TXT, textID);
if (textID == 34) if (textID == 34)
{ {
const auto * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b) const auto * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b)
@ -252,8 +252,8 @@ void CBank::doVisit(const CGHeroInstance * hero) const
return a.type->getFightValue() < b.type->getFightValue(); return a.type->getFightValue() < b.type->getFightValue();
})->type; })->type;
iw.text.addReplacement(MetaString::CRE_PL_NAMES, strongest->getId()); iw.text.replaceLocalString(EMetaText::CRE_PL_NAMES, strongest->getId());
iw.text.addReplacement(loot.buildList()); iw.text.replaceRawString(loot.buildList());
} }
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
@ -269,12 +269,12 @@ void CBank::doVisit(const CGHeroInstance * hero) const
bool noWisdom = false; bool noWisdom = false;
if(textID == 106) if(textID == 106)
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, textID); //pyramid iw.text.appendLocalString(EMetaText::ADVOB_TXT, textID); //pyramid
} }
for(const SpellID & spellId : bc->spells) for(const SpellID & spellId : bc->spells)
{ {
const auto * spell = spellId.toSpell(VLC->spells()); const auto * spell = spellId.toSpell(VLC->spells());
iw.text.addTxt(MetaString::SPELL_NAME, spellId); iw.text.appendLocalString(EMetaText::SPELL_NAME, spellId);
if(spell->getLevel() <= hero->maxSpellLevel()) if(spell->getLevel() <= hero->maxSpellLevel())
{ {
if(hero->canLearnSpell(spell)) if(hero->canLearnSpell(spell))
@ -288,9 +288,9 @@ void CBank::doVisit(const CGHeroInstance * hero) const
} }
if (!hero->getArt(ArtifactPosition::SPELLBOOK)) if (!hero->getArt(ArtifactPosition::SPELLBOOK))
iw.text.addTxt(MetaString::ADVOB_TXT, 109); //no spellbook iw.text.appendLocalString(EMetaText::ADVOB_TXT, 109); //no spellbook
else if(noWisdom) else if(noWisdom)
iw.text.addTxt(MetaString::ADVOB_TXT, 108); //no expert Wisdom iw.text.appendLocalString(EMetaText::ADVOB_TXT, 108); //no expert Wisdom
if(!iw.components.empty() || !iw.text.toString().empty()) if(!iw.components.empty() || !iw.text.toString().empty())
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
@ -312,19 +312,19 @@ void CBank::doVisit(const CGHeroInstance * hero) const
for(const auto & elem : ourArmy.Slots()) for(const auto & elem : ourArmy.Slots())
{ {
iw.components.emplace_back(*elem.second); iw.components.emplace_back(*elem.second);
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(*elem.second); loot.replaceCreatureName(*elem.second);
} }
if(ourArmy.stacksCount()) if(ourArmy.stacksCount())
{ {
if(ourArmy.stacksCount() == 1 && ourArmy.Slots().begin()->second->count == 1) if(ourArmy.stacksCount() == 1 && ourArmy.Slots().begin()->second->count == 1)
iw.text.addTxt(MetaString::ADVOB_TXT, 185); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 185);
else else
iw.text.addTxt(MetaString::ADVOB_TXT, 186); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 186);
iw.text.addReplacement(loot.buildList()); iw.text.replaceRawString(loot.buildList());
iw.text.addReplacement(hero->getNameTranslated()); iw.text.replaceRawString(hero->getNameTranslated());
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->giveCreatures(this, hero, ourArmy, false); cb->giveCreatures(this, hero, ourArmy, false);
} }

View File

@ -34,12 +34,12 @@ std::string CGCreature::getHoverText(PlayerColor player) const
CCreature::CreatureQuantityId monsterQuantityId = stacks.begin()->second->getQuantityID(); CCreature::CreatureQuantityId monsterQuantityId = stacks.begin()->second->getQuantityID();
int quantityTextIndex = 172 + 3 * (int)monsterQuantityId; int quantityTextIndex = 172 + 3 * (int)monsterQuantityId;
if(settings["gameTweaks"]["numericCreaturesQuantities"].Bool()) if(settings["gameTweaks"]["numericCreaturesQuantities"].Bool())
ms.addRawString(CCreature::getQuantityRangeStringForId(monsterQuantityId)); ms.appendRawString(CCreature::getQuantityRangeStringForId(monsterQuantityId));
else else
ms.addTxt(MetaString::ARRAY_TXT, quantityTextIndex); ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex);
ms.addRawString(" "); ms.appendRawString(" ");
ms.addTxt(MetaString::CRE_PL_NAMES,subID); ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID);
ms.toString(hoverName); hoverName = ms.toString();
return hoverName; return hoverName;
} }
@ -50,30 +50,30 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
{ {
MetaString ms; MetaString ms;
ms.appendNumber(stacks.begin()->second->count); ms.appendNumber(stacks.begin()->second->count);
ms.addRawString(" "); ms.appendRawString(" ");
ms.addTxt(MetaString::CRE_PL_NAMES,subID); ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID);
ms.addRawString("\n"); ms.appendRawString("\n");
int decision = takenAction(hero, true); int decision = takenAction(hero, true);
switch (decision) switch (decision)
{ {
case FIGHT: case FIGHT:
ms.addTxt(MetaString::GENERAL_TXT,246); ms.appendLocalString(EMetaText::GENERAL_TXT,246);
break; break;
case FLEE: case FLEE:
ms.addTxt(MetaString::GENERAL_TXT,245); ms.appendLocalString(EMetaText::GENERAL_TXT,245);
break; break;
case JOIN_FOR_FREE: case JOIN_FOR_FREE:
ms.addTxt(MetaString::GENERAL_TXT,243); ms.appendLocalString(EMetaText::GENERAL_TXT,243);
break; break;
default: //decision = cost in gold default: //decision = cost in gold
ms.addRawString(boost::to_string(boost::format(VLC->generaltexth->allTexts[244]) % decision)); ms.appendRawString(boost::to_string(boost::format(VLC->generaltexth->allTexts[244]) % decision));
break; break;
} }
ms.toString(hoverName); hoverName = ms.toString();
} }
else else
{ {
@ -118,8 +118,8 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
{ {
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
ynd.text.addTxt(MetaString::ADVOB_TXT, 86); ynd.text.appendLocalString(EMetaText::ADVOB_TXT, 86);
ynd.text.addReplacement(MetaString::CRE_PL_NAMES, subID); ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, subID);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
break; break;
} }
@ -134,7 +134,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
boost::algorithm::replace_first(tmp, "%d", std::to_string(getStackCount(SlotID(0)))); boost::algorithm::replace_first(tmp, "%d", std::to_string(getStackCount(SlotID(0))));
boost::algorithm::replace_first(tmp, "%d", std::to_string(action)); boost::algorithm::replace_first(tmp, "%d", std::to_string(action));
boost::algorithm::replace_first(tmp,"%s",VLC->creh->objects[subID]->getNamePluralTranslated()); boost::algorithm::replace_first(tmp,"%s",VLC->creh->objects[subID]->getNamePluralTranslated());
ynd.text.addRawString(tmp); ynd.text.appendRawString(tmp);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
break; break;
} }
@ -324,7 +324,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
{ {
InfoWindow iw; InfoWindow iw;
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addTxt(1,29); //You don't have enough gold iw.text.appendLocalString(EMetaText::GENERAL_TXT,29); //You don't have enough gold
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
//act as if player refused //act as if player refused
@ -390,8 +390,8 @@ void CGCreature::flee( const CGHeroInstance * h ) const
{ {
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
ynd.text.addTxt(MetaString::ADVOB_TXT,91); ynd.text.appendLocalString(EMetaText::ADVOB_TXT,91);
ynd.text.addReplacement(MetaString::CRE_PL_NAMES, subID); ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, subID);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
} }
@ -529,8 +529,8 @@ void CGCreature::giveReward(const CGHeroInstance * h) const
if(!iw.components.empty()) if(!iw.components.empty())
{ {
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.text.addTxt(MetaString::ADVOB_TXT, 183); // % has found treasure iw.text.appendLocalString(EMetaText::ADVOB_TXT, 183); // % has found treasure
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
} }

View File

@ -167,8 +167,8 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addTxt(MetaString::ADVOB_TXT, 44); //{%s} \n\n The camp is deserted. Perhaps you should try next week. iw.text.appendLocalString(EMetaText::ADVOB_TXT, 44); //{%s} \n\n The camp is deserted. Perhaps you should try next week.
iw.text.addReplacement(MetaString::OBJ_NAMES, ID); iw.text.replaceLocalString(EMetaText::OBJ_NAMES, ID);
cb->sendAndApply(&iw); cb->sendAndApply(&iw);
return; return;
} }
@ -182,13 +182,13 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
{ {
BlockingDialog bd(true,false); BlockingDialog bd(true,false);
bd.player = h->tempOwner; bd.player = h->tempOwner;
bd.text.addTxt(MetaString::GENERAL_TXT, 421); //Much to your dismay, the %s is guarded by %s %s. Do you wish to fight the guards? bd.text.appendLocalString(EMetaText::GENERAL_TXT, 421); //Much to your dismay, the %s is guarded by %s %s. Do you wish to fight the guards?
bd.text.addReplacement(ID == Obj::CREATURE_GENERATOR1 ? MetaString::CREGENS : MetaString::CREGENS4, subID); bd.text.replaceLocalString(ID == Obj::CREATURE_GENERATOR1 ? EMetaText::CREGENS : EMetaText::CREGENS4, subID);
if(settings["gameTweaks"]["numericCreaturesQuantities"].Bool()) if(settings["gameTweaks"]["numericCreaturesQuantities"].Bool())
bd.text.addReplacement(CCreature::getQuantityRangeStringForId(Slots().begin()->second->getQuantityID())); bd.text.replaceRawString(CCreature::getQuantityRangeStringForId(Slots().begin()->second->getQuantityID()));
else else
bd.text.addReplacement(MetaString::ARRAY_TXT, 173 + (int)Slots().begin()->second->getQuantityID()*3); bd.text.replaceLocalString(EMetaText::ARRAY_TXT, 173 + (int)Slots().begin()->second->getQuantityID()*3);
bd.text.addReplacement(*Slots().begin()->second); bd.text.replaceCreatureName(*Slots().begin()->second);
cb->showBlockingDialog(&bd); cb->showBlockingDialog(&bd);
return; return;
} }
@ -203,20 +203,20 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
bd.player = h->tempOwner; bd.player = h->tempOwner;
if(ID == Obj::CREATURE_GENERATOR1 || ID == Obj::CREATURE_GENERATOR4) if(ID == Obj::CREATURE_GENERATOR1 || ID == Obj::CREATURE_GENERATOR4)
{ {
bd.text.addTxt(MetaString::ADVOB_TXT, ID == Obj::CREATURE_GENERATOR1 ? 35 : 36); //{%s} Would you like to recruit %s? / {%s} Would you like to recruit %s, %s, %s, or %s? bd.text.appendLocalString(EMetaText::ADVOB_TXT, ID == Obj::CREATURE_GENERATOR1 ? 35 : 36); //{%s} Would you like to recruit %s? / {%s} Would you like to recruit %s, %s, %s, or %s?
bd.text.addReplacement(ID == Obj::CREATURE_GENERATOR1 ? MetaString::CREGENS : MetaString::CREGENS4, subID); bd.text.replaceLocalString(ID == Obj::CREATURE_GENERATOR1 ? EMetaText::CREGENS : EMetaText::CREGENS4, subID);
for(const auto & elem : creatures) for(const auto & elem : creatures)
bd.text.addReplacement(MetaString::CRE_PL_NAMES, elem.second[0]); bd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, elem.second[0]);
} }
else if(ID == Obj::REFUGEE_CAMP) else if(ID == Obj::REFUGEE_CAMP)
{ {
bd.text.addTxt(MetaString::ADVOB_TXT, 35); //{%s} Would you like to recruit %s? bd.text.appendLocalString(EMetaText::ADVOB_TXT, 35); //{%s} Would you like to recruit %s?
bd.text.addReplacement(MetaString::OBJ_NAMES, ID); bd.text.replaceLocalString(EMetaText::OBJ_NAMES, ID);
for(const auto & elem : creatures) for(const auto & elem : creatures)
bd.text.addReplacement(MetaString::CRE_PL_NAMES, elem.second[0]); bd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, elem.second[0]);
} }
else if(ID == Obj::WAR_MACHINE_FACTORY) else if(ID == Obj::WAR_MACHINE_FACTORY)
bd.text.addTxt(MetaString::ADVOB_TXT, 157); //{War Machine Factory} Would you like to purchase War Machines? bd.text.appendLocalString(EMetaText::ADVOB_TXT, 157); //{War Machine Factory} Would you like to purchase War Machines?
else else
throw std::runtime_error("Illegal dwelling!"); throw std::runtime_error("Illegal dwelling!");
@ -330,8 +330,8 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 425);//The %s would join your hero, but there aren't enough provisions to support them. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 425);//The %s would join your hero, but there aren't enough provisions to support them.
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid); iw.text.replaceLocalString(EMetaText::CRE_PL_NAMES, crid);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
else //give creatures else //give creatures
@ -345,9 +345,9 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 423); //%d %s join your army. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 423); //%d %s join your army.
iw.text.addReplacement(count); iw.text.replaceNumber(count);
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid); iw.text.replaceLocalString(EMetaText::CRE_PL_NAMES, crid);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->sendAndApply(&sac); cb->sendAndApply(&sac);
@ -358,8 +358,8 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
{ {
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.text.addTxt(MetaString::GENERAL_TXT, 422); //There are no %s here to recruit. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 422); //There are no %s here to recruit.
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid); iw.text.replaceLocalString(EMetaText::CRE_PL_NAMES, crid);
iw.player = h->tempOwner; iw.player = h->tempOwner;
cb->sendAndApply(&iw); cb->sendAndApply(&iw);
} }

View File

@ -680,7 +680,7 @@ PlayerColor CGHeroInstance::getCasterOwner() const
void CGHeroInstance::getCasterName(MetaString & text) const void CGHeroInstance::getCasterName(MetaString & text) const
{ {
//FIXME: use local name, MetaString need access to gamestate as hero name is part of map object //FIXME: use local name, MetaString need access to gamestate as hero name is part of map object
text.addReplacement(getNameTranslated()); text.replaceRawString(getNameTranslated());
} }
void CGHeroInstance::getCastDescription(const spells::Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const void CGHeroInstance::getCastDescription(const spells::Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const
@ -688,9 +688,9 @@ void CGHeroInstance::getCastDescription(const spells::Spell * spell, const std::
const bool singleTarget = attacked.size() == 1; const bool singleTarget = attacked.size() == 1;
const int textIndex = singleTarget ? 195 : 196; const int textIndex = singleTarget ? 195 : 196;
text.addTxt(MetaString::GENERAL_TXT, textIndex); text.appendLocalString(EMetaText::GENERAL_TXT, textIndex);
getCasterName(text); getCasterName(text);
text.addReplacement(MetaString::SPELL_NAME, spell->getIndex()); text.replaceLocalString(EMetaText::SPELL_NAME, spell->getIndex());
if(singleTarget) if(singleTarget)
attacked.at(0)->addNameReplacement(text, true); attacked.at(0)->addNameReplacement(text, true);
} }
@ -896,14 +896,14 @@ void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedSta
if (raisedStack.count > 1) // Practicing the dark arts of necromancy, ... (plural) if (raisedStack.count > 1) // Practicing the dark arts of necromancy, ... (plural)
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 145); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 145);
iw.text.addReplacement(raisedStack.count); iw.text.replaceNumber(raisedStack.count);
} }
else // Practicing the dark arts of necromancy, ... (singular) else // Practicing the dark arts of necromancy, ... (singular)
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 146); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 146);
} }
iw.text.addReplacement(raisedStack); iw.text.replaceCreatureName(raisedStack);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }

View File

@ -35,7 +35,7 @@ void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const
{ {
BlockingDialog bd (true, false); BlockingDialog bd (true, false);
bd.player = h->getOwner(); bd.player = h->getOwner();
bd.text.addTxt (MetaString::ADVOB_TXT, 14); bd.text.appendLocalString (EMetaText::ADVOB_TXT, 14);
cb->showBlockingDialog (&bd); cb->showBlockingDialog (&bd);
} }
@ -79,8 +79,8 @@ void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const
{ {
TExpType expVal = h->calculateXp(gainedExp); TExpType expVal = h->calculateXp(gainedExp);
//getText(iw,afterBattle,175,h); //wtf? //getText(iw,afterBattle,175,h); //wtf?
iw.text.addTxt(MetaString::ADVOB_TXT, 175); //%s learns something iw.text.appendLocalString(EMetaText::ADVOB_TXT, 175); //%s learns something
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
if(expVal) if(expVal)
iw.components.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(expVal), 0); iw.components.emplace_back(Component::EComponentType::EXPERIENCE, 0, static_cast<si32>(expVal), 0);
@ -156,13 +156,13 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
{ {
if (spellsToGive.size() > 1) if (spellsToGive.size() > 1)
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, 188); //%s learns spells iw.text.appendLocalString(EMetaText::ADVOB_TXT, 188); //%s learns spells
} }
else else
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, 184); //%s learns a spell iw.text.appendLocalString(EMetaText::ADVOB_TXT, 184); //%s learns a spell
} }
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
cb->changeSpells(h, true, spellsToGive); cb->changeSpells(h, true, spellsToGive);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
@ -227,8 +227,8 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
iw.components.clear(); iw.components.clear();
// getText(iw,afterBattle,183,h); // getText(iw,afterBattle,183,h);
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure iw.text.appendLocalString(EMetaText::ADVOB_TXT, 183); //% has found treasure
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
for(const auto & elem : artifacts) for(const auto & elem : artifacts)
{ {
iw.components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0); iw.components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0);
@ -236,8 +236,8 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
{ {
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
iw.components.clear(); iw.components.clear();
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure - once more? iw.text.appendLocalString(EMetaText::ADVOB_TXT, 183); //% has found treasure - once more?
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
} }
} }
if(!iw.components.empty()) if(!iw.components.empty())
@ -259,24 +259,24 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
for(const auto & elem : creatures.Slots()) for(const auto & elem : creatures.Slots())
{ //build list of joined creatures { //build list of joined creatures
iw.components.emplace_back(*elem.second); iw.components.emplace_back(*elem.second);
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(*elem.second); loot.replaceCreatureName(*elem.second);
} }
if(creatures.stacksCount() == 1 && creatures.Slots().begin()->second->count == 1) if(creatures.stacksCount() == 1 && creatures.Slots().begin()->second->count == 1)
iw.text.addTxt(MetaString::ADVOB_TXT, 185); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 185);
else else
iw.text.addTxt(MetaString::ADVOB_TXT, 186); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 186);
iw.text.addReplacement(loot.buildList()); iw.text.replaceRawString(loot.buildList());
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->giveCreatures(this, h, creatures, false); cb->giveCreatures(this, h, creatures, false);
} }
if(!hasGuardians && !msg.empty()) if(!hasGuardians && !msg.empty())
{ {
iw.text.addRawString(msg); iw.text.appendRawString(msg);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
} }
@ -285,12 +285,12 @@ void CGPandoraBox::getText( InfoWindow &iw, bool &afterBattle, int text, const C
{ {
if(afterBattle || message.empty()) if(afterBattle || message.empty())
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,text);//%s has lost treasure. iw.text.appendLocalString(EMetaText::ADVOB_TXT,text);//%s has lost treasure.
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
} }
else else
{ {
iw.text.addRawString(message); iw.text.appendRawString(message);
afterBattle = true; afterBattle = true;
} }
} }
@ -301,12 +301,12 @@ void CGPandoraBox::getText( InfoWindow &iw, bool &afterBattle, int val, int nega
iw.text.clear(); iw.text.clear();
if(afterBattle || message.empty()) if(afterBattle || message.empty())
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,val < 0 ? negative : positive); //%s's luck takes a turn for the worse / %s's luck increases iw.text.appendLocalString(EMetaText::ADVOB_TXT,val < 0 ? negative : positive); //%s's luck takes a turn for the worse / %s's luck increases
iw.text.addReplacement(h->getNameTranslated()); iw.text.replaceRawString(h->getNameTranslated());
} }
else else
{ {
iw.text.addRawString(message); iw.text.appendRawString(message);
afterBattle = true; afterBattle = true;
} }
} }
@ -461,9 +461,9 @@ void CGEvent::activated( const CGHeroInstance * h ) const
InfoWindow iw; InfoWindow iw;
iw.player = h->tempOwner; iw.player = h->tempOwner;
if(!message.empty()) if(!message.empty())
iw.text.addRawString(message); iw.text.appendRawString(message);
else else
iw.text.addTxt(MetaString::ADVOB_TXT, 16); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 16);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->startBattleI(h, this); cb->startBattleI(h, this);
} }

View File

@ -156,7 +156,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
mp.hid = heroID; mp.hid = heroID;
cb->setMovePoints(&mp); cb->setMovePoints(&mp);
iw.text.addRawString(VLC->generaltexth->allTexts[580]); iw.text.appendRawString(VLC->generaltexth->allTexts[580]);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
break; break;
@ -168,7 +168,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
cb->setManaPoints (heroID, 2 * h->manaLimit()); cb->setManaPoints (heroID, 2 * h->manaLimit());
//TODO: investigate line below //TODO: investigate line below
//cb->setObjProperty (town->id, ObjProperty::VISITED, true); //cb->setObjProperty (town->id, ObjProperty::VISITED, true);
iw.text.addRawString(getVisitingBonusGreeting()); iw.text.appendRawString(getVisitingBonusGreeting());
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
//extra visit penalty if hero alredy had double mana points (or even more?!) //extra visit penalty if hero alredy had double mana points (or even more?!)
town->addHeroToStructureVisitors(h, indexOnTV); town->addHeroToStructureVisitors(h, indexOnTV);
@ -246,7 +246,7 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
if(what != PrimarySkill::NONE) if(what != PrimarySkill::NONE)
{ {
iw.player = cb->getOwner(heroID); iw.player = cb->getOwner(heroID);
iw.text.addRawString(getVisitingBonusGreeting()); iw.text.appendRawString(getVisitingBonusGreeting());
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->changePrimSkill (cb->getHero(heroID), what, val); cb->changePrimSkill (cb->getHero(heroID), what, val);
town->addHeroToStructureVisitors(h, indexOnTV); town->addHeroToStructureVisitors(h, indexOnTV);
@ -278,7 +278,7 @@ void CTownBonus::applyBonuses(CGHeroInstance * h, const BonusList & bonuses) con
addToVisitors = true; addToVisitors = true;
iw.player = cb->getOwner(h->id); iw.player = cb->getOwner(h->id);
iw.text.addRawString(getCustomBonusGreeting(gb.bonus)); iw.text.appendRawString(getCustomBonusGreeting(gb.bonus));
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
if(addToVisitors) if(addToVisitors)

View File

@ -320,7 +320,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
{ {
InfoWindow iw; InfoWindow iw;
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addRawString(h->commander->getName()); iw.text.appendRawString(h->commander->getName());
iw.components.emplace_back(*h->commander); iw.components.emplace_back(*h->commander);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }

View File

@ -188,20 +188,20 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
{ {
isCustom = isCustomFirst; isCustom = isCustomFirst;
text = firstVisitText; text = firstVisitText;
iwText.addRawString(text); iwText.appendRawString(text);
} }
else if(failRequirements) else if(failRequirements)
{ {
isCustom = isCustomNext; isCustom = isCustomNext;
text = nextVisitText; text = nextVisitText;
iwText.addRawString(text); iwText.appendRawString(text);
} }
switch (missionType) switch (missionType)
{ {
case MISSION_LEVEL: case MISSION_LEVEL:
components.emplace_back(Component::EComponentType::EXPERIENCE, 0, m13489val, 0); components.emplace_back(Component::EComponentType::EXPERIENCE, 0, m13489val, 0);
if(!isCustom) if(!isCustom)
iwText.addReplacement(m13489val); iwText.replaceNumber(m13489val);
break; break;
case MISSION_PRIMARY_STAT: case MISSION_PRIMARY_STAT:
{ {
@ -211,13 +211,13 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
if(m2stats[i]) if(m2stats[i])
{ {
components.emplace_back(Component::EComponentType::PRIM_SKILL, i, m2stats[i], 0); components.emplace_back(Component::EComponentType::PRIM_SKILL, i, m2stats[i], 0);
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(m2stats[i]); loot.replaceNumber(m2stats[i]);
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]); loot.replaceRawString(VLC->generaltexth->primarySkillNames[i]);
} }
} }
if (!isCustom) if (!isCustom)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_KILL_HERO: case MISSION_KILL_HERO:
@ -229,7 +229,7 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
//FIXME: portrait may not match hero, if custom portrait was set in map editor //FIXME: portrait may not match hero, if custom portrait was set in map editor
components.emplace_back(Component::EComponentType::HERO_PORTRAIT, VLC->heroh->objects[m13489val]->imageIndex, 0, 0); components.emplace_back(Component::EComponentType::HERO_PORTRAIT, VLC->heroh->objects[m13489val]->imageIndex, 0, 0);
if(!isCustom) if(!isCustom)
iwText.addReplacement(VLC->heroh->objects[m13489val]->getNameTranslated()); iwText.replaceRawString(VLC->heroh->objects[m13489val]->getNameTranslated());
break; break;
case MISSION_KILL_CREATURE: case MISSION_KILL_CREATURE:
{ {
@ -246,11 +246,11 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
for(const auto & elem : m5arts) for(const auto & elem : m5arts)
{ {
components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0); components.emplace_back(Component::EComponentType::ARTIFACT, elem, 0, 0);
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(MetaString::ART_NAMES, elem); loot.replaceLocalString(EMetaText::ART_NAMES, elem);
} }
if(!isCustom) if(!isCustom)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_ARMY: case MISSION_ARMY:
@ -259,11 +259,11 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
for(const auto & elem : m6creatures) for(const auto & elem : m6creatures)
{ {
components.emplace_back(elem); components.emplace_back(elem);
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(elem); loot.replaceCreatureName(elem);
} }
if(!isCustom) if(!isCustom)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_RESOURCES: case MISSION_RESOURCES:
@ -274,19 +274,19 @@ void CQuest::getVisitText(MetaString &iwText, std::vector<Component> &components
if(m7resources[i]) if(m7resources[i])
{ {
components.emplace_back(Component::EComponentType::RESOURCE, i, m7resources[i], 0); components.emplace_back(Component::EComponentType::RESOURCE, i, m7resources[i], 0);
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(m7resources[i]); loot.replaceNumber(m7resources[i]);
loot.addReplacement(MetaString::RES_NAMES, i); loot.replaceLocalString(EMetaText::RES_NAMES, i);
} }
} }
if(!isCustom) if(!isCustom)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_PLAYER: case MISSION_PLAYER:
components.emplace_back(Component::EComponentType::FLAG, m13489val, 0, 0); components.emplace_back(Component::EComponentType::FLAG, m13489val, 0, 0);
if(!isCustom) if(!isCustom)
iwText.addReplacement(VLC->generaltexth->colors[m13489val]); iwText.replaceRawString(VLC->generaltexth->colors[m13489val]);
break; break;
} }
} }
@ -297,17 +297,17 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
assert(missionType != MISSION_NONE); assert(missionType != MISSION_NONE);
if(onHover) if(onHover)
ms.addRawString("\n\n"); ms.appendRawString("\n\n");
std::string questName = missionName(missionType); std::string questName = missionName(missionType);
std::string questState = missionState(onHover ? 3 : 4); std::string questState = missionState(onHover ? 3 : 4);
ms.addRawString(VLC->generaltexth->translate("core.seerhut.quest", questName, questState,textOption)); ms.appendRawString(VLC->generaltexth->translate("core.seerhut.quest", questName, questState,textOption));
switch(missionType) switch(missionType)
{ {
case MISSION_LEVEL: case MISSION_LEVEL:
ms.addReplacement(m13489val); ms.replaceNumber(m13489val);
break; break;
case MISSION_PRIMARY_STAT: case MISSION_PRIMARY_STAT:
{ {
@ -316,29 +316,29 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
{ {
if (m2stats[i]) if (m2stats[i])
{ {
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(m2stats[i]); loot.replaceNumber(m2stats[i]);
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]); loot.replaceRawString(VLC->generaltexth->primarySkillNames[i]);
} }
} }
ms.addReplacement(loot.buildList()); ms.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_KILL_HERO: case MISSION_KILL_HERO:
ms.addReplacement(heroName); ms.replaceRawString(heroName);
break; break;
case MISSION_KILL_CREATURE: case MISSION_KILL_CREATURE:
ms.addReplacement(stackToKill); ms.replaceCreatureName(stackToKill);
break; break;
case MISSION_ART: case MISSION_ART:
{ {
MetaString loot; MetaString loot;
for(const auto & elem : m5arts) for(const auto & elem : m5arts)
{ {
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(MetaString::ART_NAMES, elem); loot.replaceLocalString(EMetaText::ART_NAMES, elem);
} }
ms.addReplacement(loot.buildList()); ms.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_ARMY: case MISSION_ARMY:
@ -346,10 +346,10 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
MetaString loot; MetaString loot;
for(const auto & elem : m6creatures) for(const auto & elem : m6creatures)
{ {
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(elem); loot.replaceCreatureName(elem);
} }
ms.addReplacement(loot.buildList()); ms.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_RESOURCES: case MISSION_RESOURCES:
@ -359,19 +359,19 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
{ {
if (m7resources[i]) if (m7resources[i])
{ {
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(m7resources[i]); loot.replaceNumber(m7resources[i]);
loot.addReplacement(MetaString::RES_NAMES, i); loot.replaceLocalString(EMetaText::RES_NAMES, i);
} }
} }
ms.addReplacement(loot.buildList()); ms.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_HERO: case MISSION_HERO:
ms.addReplacement(VLC->heroh->objects[m13489val]->getNameTranslated()); ms.replaceRawString(VLC->heroh->objects[m13489val]->getNameTranslated());
break; break;
case MISSION_PLAYER: case MISSION_PLAYER:
ms.addReplacement(VLC->generaltexth->colors[m13489val]); ms.replaceRawString(VLC->generaltexth->colors[m13489val]);
break; break;
default: default:
break; break;
@ -380,12 +380,12 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const
void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h) const void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h) const
{ {
iwText.addRawString(completedText); iwText.appendRawString(completedText);
switch(missionType) switch(missionType)
{ {
case CQuest::MISSION_LEVEL: case CQuest::MISSION_LEVEL:
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(m13489val); iwText.replaceNumber(m13489val);
break; break;
case CQuest::MISSION_PRIMARY_STAT: case CQuest::MISSION_PRIMARY_STAT:
if (vstd::contains (completedText,'%')) //there's one case when there's nothing to replace if (vstd::contains (completedText,'%')) //there's one case when there's nothing to replace
@ -395,13 +395,13 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &compo
{ {
if (m2stats[i]) if (m2stats[i])
{ {
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(m2stats[i]); loot.replaceNumber(m2stats[i]);
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]); loot.replaceRawString(VLC->generaltexth->primarySkillNames[i]);
} }
} }
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case CQuest::MISSION_ART: case CQuest::MISSION_ART:
@ -409,11 +409,11 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &compo
MetaString loot; MetaString loot;
for(const auto & elem : m5arts) for(const auto & elem : m5arts)
{ {
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(MetaString::ART_NAMES, elem); loot.replaceLocalString(EMetaText::ART_NAMES, elem);
} }
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case CQuest::MISSION_ARMY: case CQuest::MISSION_ARMY:
@ -421,11 +421,11 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &compo
MetaString loot; MetaString loot;
for(const auto & elem : m6creatures) for(const auto & elem : m6creatures)
{ {
loot.addRawString("%s"); loot.appendRawString("%s");
loot.addReplacement(elem); loot.replaceCreatureName(elem);
} }
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case CQuest::MISSION_RESOURCES: case CQuest::MISSION_RESOURCES:
@ -435,13 +435,13 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &compo
{ {
if (m7resources[i]) if (m7resources[i])
{ {
loot.addRawString("%d %s"); loot.appendRawString("%d %s");
loot.addReplacement(m7resources[i]); loot.replaceNumber(m7resources[i]);
loot.addReplacement(MetaString::RES_NAMES, i); loot.replaceLocalString(EMetaText::RES_NAMES, i);
} }
} }
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(loot.buildList()); iwText.replaceRawString(loot.buildList());
} }
break; break;
case MISSION_KILL_HERO: case MISSION_KILL_HERO:
@ -451,11 +451,11 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &compo
break; break;
case MISSION_HERO: case MISSION_HERO:
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(VLC->heroh->objects[m13489val]->getNameTranslated()); iwText.replaceRawString(VLC->heroh->objects[m13489val]->getNameTranslated());
break; break;
case MISSION_PLAYER: case MISSION_PLAYER:
if (!isCustomComplete) if (!isCustomComplete)
iwText.addReplacement(VLC->generaltexth->colors[m13489val]); iwText.replaceRawString(VLC->generaltexth->colors[m13489val]);
break; break;
} }
} }
@ -596,7 +596,7 @@ void CGSeerHut::getRolloverText(MetaString &text, bool onHover) const
{ {
quest->getRolloverText (text, onHover);//TODO: simplify? quest->getRolloverText (text, onHover);//TODO: simplify?
if(!onHover) if(!onHover)
text.addReplacement(seerName); text.replaceRawString(seerName);
} }
std::string CGSeerHut::getHoverText(PlayerColor player) const std::string CGSeerHut::getHoverText(PlayerColor player) const
@ -622,14 +622,14 @@ void CQuest::addReplacements(MetaString &out, const std::string &base) const
switch(missionType) switch(missionType)
{ {
case MISSION_KILL_CREATURE: case MISSION_KILL_CREATURE:
out.addReplacement(stackToKill); out.replaceCreatureName(stackToKill);
if (std::count(base.begin(), base.end(), '%') == 2) //say where is placed monster if (std::count(base.begin(), base.end(), '%') == 2) //say where is placed monster
{ {
out.addReplacement(VLC->generaltexth->arraytxt[147+stackDirection]); out.replaceRawString(VLC->generaltexth->arraytxt[147+stackDirection]);
} }
break; break;
case MISSION_KILL_HERO: case MISSION_KILL_HERO:
out.addReplacement(heroName); out.replaceRawString(heroName);
break; break;
} }
} }
@ -749,9 +749,9 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
} }
else else
{ {
iw.text.addRawString(VLC->generaltexth->seerEmpty[quest->completedOption]); iw.text.appendRawString(VLC->generaltexth->seerEmpty[quest->completedOption]);
if (ID == Obj::SEER_HUT) if (ID == Obj::SEER_HUT)
iw.text.addReplacement(seerName); iw.text.replaceRawString(seerName);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
} }
@ -1157,16 +1157,16 @@ void CGBorderGuard::initObj(CRandomGenerator & rand)
void CGBorderGuard::getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const void CGBorderGuard::getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const
{ {
text.addTxt(11,18); text.appendLocalString(EMetaText::ADVOB_TXT,18);
} }
void CGBorderGuard::getRolloverText (MetaString &text, bool onHover) const void CGBorderGuard::getRolloverText (MetaString &text, bool onHover) const
{ {
if (!onHover) if (!onHover)
{ {
text.addRawString(VLC->generaltexth->tentColors[subID]); text.appendRawString(VLC->generaltexth->tentColors[subID]);
text.addRawString(" "); text.appendRawString(" ");
text.addRawString(VLC->objtypeh->getObjectName(Obj::KEYMASTER, subID)); text.appendRawString(VLC->objtypeh->getObjectName(Obj::KEYMASTER, subID));
} }
} }
@ -1181,7 +1181,7 @@ void CGBorderGuard::onHeroVisit(const CGHeroInstance * h) const
{ {
BlockingDialog bd (true, false); BlockingDialog bd (true, false);
bd.player = h->getOwner(); bd.player = h->getOwner();
bd.text.addTxt (MetaString::ADVOB_TXT, 17); bd.text.appendLocalString (EMetaText::ADVOB_TXT, 17);
cb->showBlockingDialog (&bd); cb->showBlockingDialog (&bd);
} }
else else

View File

@ -38,7 +38,7 @@ void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInf
iw.soundID = soundID; iw.soundID = soundID;
iw.player = getOwner(); iw.player = getOwner();
iw.type = mode; iw.type = mode;
iw.text.addTxt(MetaString::ADVOB_TXT,txtID); iw.text.appendLocalString(EMetaText::ADVOB_TXT,txtID);
IObjectInterface::cb->sendAndApply(&iw); IObjectInterface::cb->sendAndApply(&iw);
} }
@ -122,16 +122,16 @@ void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visit
switch(shipyardStatus()) switch(shipyardStatus())
{ {
case BOAT_ALREADY_BUILT: case BOAT_ALREADY_BUILT:
out.addTxt(MetaString::GENERAL_TXT, 51); out.appendLocalString(EMetaText::GENERAL_TXT, 51);
break; break;
case TILE_BLOCKED: case TILE_BLOCKED:
if(visitor) if(visitor)
{ {
out.addTxt(MetaString::GENERAL_TXT, 134); out.appendLocalString(EMetaText::GENERAL_TXT, 134);
out.addReplacement(visitor->getNameTranslated()); out.replaceRawString(visitor->getNameTranslated());
} }
else else
out.addTxt(MetaString::ADVOB_TXT, 189); out.appendLocalString(EMetaText::ADVOB_TXT, 189);
break; break;
case NO_WATER: case NO_WATER:
logGlobal->error("Shipyard without water at tile %s! ", getObject()->getPosition().toString()); logGlobal->error("Shipyard without water at tile %s! ", getObject()->getPosition().toString());

View File

@ -82,7 +82,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
{ {
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
ynd.text.addTxt(MetaString::ADVOB_TXT, subID == 7 ? 84 : 187); ynd.text.appendLocalString(EMetaText::ADVOB_TXT, subID == 7 ? 84 : 187);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
return; return;
} }
@ -156,7 +156,7 @@ void CGMine::flagMine(const PlayerColor & player) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.soundID = soundBase::FLAGMINE; iw.soundID = soundBase::FLAGMINE;
iw.text.addTxt(MetaString::MINE_EVNTS, producedResource); //not use subID, abandoned mines uses default mine texts iw.text.appendLocalString(EMetaText::MINE_EVNTS, producedResource); //not use subID, abandoned mines uses default mine texts
iw.player = player; iw.player = player;
iw.components.emplace_back(Component::EComponentType::RESOURCE, producedResource, producedQuantity, -1); iw.components.emplace_back(Component::EComponentType::RESOURCE, producedResource, producedQuantity, -1);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
@ -268,7 +268,7 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const
{ {
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->getOwner(); ynd.player = h->getOwner();
ynd.text.addRawString(message); ynd.text.appendRawString(message);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
} }
else else
@ -288,13 +288,13 @@ void CGResource::collectRes(const PlayerColor & player) const
if(!message.empty()) if(!message.empty())
{ {
sii.type = EInfoWindowMode::AUTO; sii.type = EInfoWindowMode::AUTO;
sii.text.addRawString(message); sii.text.appendRawString(message);
} }
else else
{ {
sii.type = EInfoWindowMode::INFO; sii.type = EInfoWindowMode::INFO;
sii.text.addTxt(MetaString::ADVOB_TXT,113); sii.text.appendLocalString(EMetaText::ADVOB_TXT,113);
sii.text.addReplacement(MetaString::RES_NAMES, subID); sii.text.replaceLocalString(EMetaText::RES_NAMES, subID);
} }
sii.components.emplace_back(Component::EComponentType::RESOURCE,subID,amount,0); sii.components.emplace_back(Component::EComponentType::RESOURCE,subID,amount,0);
sii.soundID = soundBase::pickup01 + CRandomGenerator::getDefault().nextInt(6); sii.soundID = soundBase::pickup01 + CRandomGenerator::getDefault().nextInt(6);
@ -635,7 +635,7 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addTxt(MetaString::ADVOB_TXT, 168); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 168);
iw.components.emplace_back(CStackBasicDescriptor(h->getCreature(targetstack), -countToTake)); iw.components.emplace_back(CStackBasicDescriptor(h->getCreature(targetstack), -countToTake));
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->changeStackCount(StackLocation(h, targetstack), -countToTake); cb->changeStackCount(StackLocation(h, targetstack), -countToTake);
@ -727,9 +727,9 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
{ {
iw.components.emplace_back(Component::EComponentType::ARTIFACT, subID, 0, 0); iw.components.emplace_back(Component::EComponentType::ARTIFACT, subID, 0, 0);
if(message.length()) if(message.length())
iw.text.addRawString(message); iw.text.appendRawString(message);
else else
iw.text.addTxt(MetaString::ART_EVNTS, subID); iw.text.appendLocalString(EMetaText::ART_EVNTS, subID);
} }
break; break;
case Obj::SPELL_SCROLL: case Obj::SPELL_SCROLL:
@ -737,11 +737,11 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
int spellID = storedArtifact->getScrollSpellID(); int spellID = storedArtifact->getScrollSpellID();
iw.components.emplace_back(Component::EComponentType::SPELL, spellID, 0, 0); iw.components.emplace_back(Component::EComponentType::SPELL, spellID, 0, 0);
if(message.length()) if(message.length())
iw.text.addRawString(message); iw.text.appendRawString(message);
else else
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,135); iw.text.appendLocalString(EMetaText::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID); iw.text.replaceLocalString(EMetaText::SPELL_NAME, spellID);
} }
} }
break; break;
@ -749,7 +749,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
} }
else else
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, 2); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 2);
} }
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
pick(h); pick(h);
@ -763,14 +763,14 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->getOwner(); ynd.player = h->getOwner();
if(message.length()) if(message.length())
ynd.text.addRawString(message); ynd.text.appendRawString(message);
else else
{ {
// TODO: Guard text is more complex in H3, see mantis issue 2325 for details // TODO: Guard text is more complex in H3, see mantis issue 2325 for details
ynd.text.addTxt(MetaString::GENERAL_TXT, 420); ynd.text.appendLocalString(EMetaText::GENERAL_TXT, 420);
ynd.text.addReplacement(""); ynd.text.replaceRawString("");
ynd.text.addReplacement(getArmyDescription()); ynd.text.replaceRawString(getArmyDescription());
ynd.text.addReplacement(MetaString::GENERAL_TXT, 43); // creatures ynd.text.replaceLocalString(EMetaText::GENERAL_TXT, 43); // creatures
} }
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
} }
@ -781,7 +781,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
{ {
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->getOwner(); ynd.player = h->getOwner();
ynd.text.addRawString(message); ynd.text.appendRawString(message);
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
} }
else else
@ -878,8 +878,8 @@ void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
cb->changeSecSkill(h, SecondarySkill(ability), 1, true); cb->changeSecSkill(h, SecondarySkill(ability), 1, true);
} }
iw.text.addTxt(MetaString::ADVOB_TXT,txt_id); iw.text.appendLocalString(EMetaText::ADVOB_TXT,txt_id);
iw.text.addReplacement(MetaString::SEC_SKILL_NAME, ability); iw.text.replaceLocalString(EMetaText::SEC_SKILL_NAME, ability);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
} }
@ -940,7 +940,7 @@ void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
case Obj::REDWOOD_OBSERVATORY: case Obj::REDWOOD_OBSERVATORY:
case Obj::PILLAR_OF_FIRE: case Obj::PILLAR_OF_FIRE:
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,98 + (ID==Obj::PILLAR_OF_FIRE)); iw.text.appendLocalString(EMetaText::ADVOB_TXT,98 + (ID==Obj::PILLAR_OF_FIRE));
FoWChange fw; FoWChange fw;
fw.player = h->tempOwner; fw.player = h->tempOwner;
@ -951,7 +951,7 @@ void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
} }
case Obj::COVER_OF_DARKNESS: case Obj::COVER_OF_DARKNESS:
{ {
iw.text.addTxt (MetaString::ADVOB_TXT, 31); iw.text.appendLocalString (EMetaText::ADVOB_TXT, 31);
for (auto & player : cb->gameState()->players) for (auto & player : cb->gameState()->players)
{ {
if (cb->getPlayerStatus(player.first) == EPlayerStatus::INGAME && if (cb->getPlayerStatus(player.first) == EPlayerStatus::INGAME &&
@ -979,20 +979,20 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->getOwner(); iw.player = h->getOwner();
iw.text = visitText; iw.text = visitText;
iw.text.addTxt(MetaString::SPELL_NAME,spell); iw.text.appendLocalString(EMetaText::SPELL_NAME,spell);
iw.text.addRawString("."); iw.text.appendRawString(".");
if(!h->getArt(ArtifactPosition::SPELLBOOK)) if(!h->getArt(ArtifactPosition::SPELLBOOK))
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,131); iw.text.appendLocalString(EMetaText::ADVOB_TXT,131);
} }
else if(h->spellbookContainsSpell(spell))//hero already knows the spell else if(h->spellbookContainsSpell(spell))//hero already knows the spell
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,174); iw.text.appendLocalString(EMetaText::ADVOB_TXT,174);
} }
else if(spell.toSpell()->getLevel() > h->maxSpellLevel()) //it's third level spell and hero doesn't have wisdom else if(spell.toSpell()->getLevel() > h->maxSpellLevel()) //it's third level spell and hero doesn't have wisdom
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,130); iw.text.appendLocalString(EMetaText::ADVOB_TXT,130);
} }
else //give spell else //give spell
{ {
@ -1055,7 +1055,7 @@ void CGSignBottle::onHeroVisit( const CGHeroInstance * h ) const
{ {
InfoWindow iw; InfoWindow iw;
iw.player = h->getOwner(); iw.player = h->getOwner();
iw.text.addRawString(message); iw.text.appendRawString(message);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
if(ID == Obj::OCEAN_BOTTLE) if(ID == Obj::OCEAN_BOTTLE)
@ -1083,7 +1083,7 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->getOwner(); iw.player = h->getOwner();
iw.text.addTxt(MetaString::ADVOB_TXT,115); iw.text.appendLocalString(EMetaText::ADVOB_TXT,115);
switch (type) switch (type)
{ {
@ -1332,7 +1332,7 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
if(h->hasBonusFrom(BonusSource::OBJECT,ID)) //has already visited Sirens if(h->hasBonusFrom(BonusSource::OBJECT,ID)) //has already visited Sirens
{ {
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.text.addTxt(MetaString::ADVOB_TXT,133); iw.text.appendLocalString(EMetaText::ADVOB_TXT,133);
} }
else else
{ {
@ -1358,13 +1358,13 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
if(xp) if(xp)
{ {
xp = h->calculateXp(static_cast<int>(xp)); xp = h->calculateXp(static_cast<int>(xp));
iw.text.addTxt(MetaString::ADVOB_TXT,132); iw.text.appendLocalString(EMetaText::ADVOB_TXT,132);
iw.text.addReplacement(static_cast<int>(xp)); iw.text.replaceNumber(static_cast<int>(xp));
cb->changePrimSkill(h, PrimarySkill::EXPERIENCE, xp, false); cb->changePrimSkill(h, PrimarySkill::EXPERIENCE, xp, false);
} }
else else
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,134); iw.text.appendLocalString(EMetaText::ADVOB_TXT,134);
} }
} }
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
@ -1444,7 +1444,7 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
assert(text); assert(text);
BlockingDialog bd (true, false); BlockingDialog bd (true, false);
bd.player = h->getOwner(); bd.player = h->getOwner();
bd.text.addTxt (MetaString::ADVOB_TXT, text); bd.text.appendLocalString (EMetaText::ADVOB_TXT, text);
cb->showBlockingDialog (&bd); cb->showBlockingDialog (&bd);
} }
else //if he cannot afford else //if he cannot afford
@ -1507,7 +1507,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
if(!wasVisited(team)) if(!wasVisited(team))
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, 96); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 96);
cb->sendAndApply(&iw); cb->sendAndApply(&iw);
// increment general visited obelisks counter // increment general visited obelisks counter
@ -1523,7 +1523,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
} }
else else
{ {
iw.text.addTxt(MetaString::ADVOB_TXT, 97); iw.text.appendLocalString(EMetaText::ADVOB_TXT, 97);
cb->sendAndApply(&iw); cb->sendAndApply(&iw);
} }

View File

@ -34,9 +34,9 @@ namespace {
{ {
MetaString ret; MetaString ret;
if (value.isNumber()) if (value.isNumber())
ret.addTxt(MetaString::ADVOB_TXT, static_cast<ui32>(value.Float())); ret.appendLocalString(EMetaText::ADVOB_TXT, static_cast<ui32>(value.Float()));
else else
ret.addRawString(value.String()); ret.appendRawString(value.String());
return ret; return ret;
} }
@ -191,10 +191,10 @@ void Rewardable::Info::configureRewards(
info.message = loadMessage(reward["message"]); info.message = loadMessage(reward["message"]);
for (const auto & artifact : info.reward.artifacts ) for (const auto & artifact : info.reward.artifacts )
info.message.addReplacement(MetaString::ART_NAMES, artifact.getNum()); info.message.replaceLocalString(EMetaText::ART_NAMES, artifact.getNum());
for (const auto & artifact : info.reward.spells ) for (const auto & artifact : info.reward.spells )
info.message.addReplacement(MetaString::SPELL_NAME, artifact.getNum()); info.message.replaceLocalString(EMetaText::SPELL_NAME, artifact.getNum());
object.info.push_back(info); object.info.push_back(info);
} }

View File

@ -147,7 +147,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 333);//%s is already in boat iw.text.appendLocalString(EMetaText::GENERAL_TXT, 333);//%s is already in boat
parameters.caster->getCasterName(iw.text); parameters.caster->getCasterName(iw.text);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
@ -159,7 +159,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 334);//There is no place to put the boat. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 334);//There is no place to put the boat.
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
} }
@ -171,7 +171,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 336); //%s tried to summon a boat, but failed. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
parameters.caster->getCasterName(iw.text); parameters.caster->getCasterName(iw.text);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::OK; return ESpellCastResult::OK;
@ -208,7 +208,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 335); //There are no boats to summon. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 335); //There are no boats to summon.
env->apply(&iw); env->apply(&iw);
} }
else //create boat else //create boat
@ -236,7 +236,7 @@ ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironmen
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed iw.text.appendLocalString(EMetaText::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
parameters.caster->getCasterName(iw.text); parameters.caster->getCasterName(iw.text);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::OK; return ESpellCastResult::OK;
@ -313,7 +313,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today.
parameters.caster->getCasterName(iw.text); parameters.caster->getCasterName(iw.text);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
@ -328,7 +328,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 70); //Dimension Door failed! iw.text.appendLocalString(EMetaText::GENERAL_TXT, 70); //Dimension Door failed!
env->apply(&iw); env->apply(&iw);
} }
else if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), true)) else if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), true))
@ -376,7 +376,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 123); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 123);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
} }
@ -461,7 +461,7 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 124); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 124);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
} }
@ -472,7 +472,7 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 125); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 125);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
} }
@ -517,14 +517,14 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
{ {
InfoWindow iw; InfoWindow iw;
iw.player = parameters.caster->getCasterOwner(); iw.player = parameters.caster->getCasterOwner();
iw.text.addTxt(MetaString::GENERAL_TXT, 124); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 124);
env->apply(&iw); env->apply(&iw);
return ESpellCastResult::CANCEL; return ESpellCastResult::CANCEL;
} }
request.player = parameters.caster->getCasterOwner(); request.player = parameters.caster->getCasterOwner();
request.title.addTxt(MetaString::JK_TXT, 40); request.title.appendLocalString(EMetaText::JK_TXT, 40);
request.description.addTxt(MetaString::JK_TXT, 41); request.description.appendLocalString(EMetaText::JK_TXT, 41);
request.icon.id = Component::EComponentType::SPELL; request.icon.id = Component::EComponentType::SPELL;
request.icon.subtype = owner->id.toEnum(); request.icon.subtype = owner->id.toEnum();

View File

@ -309,7 +309,7 @@ void BattleSpellMechanics::cast(ServerCallback * server, const Target & target)
{ {
MetaString line; MetaString line;
caster->getCastDescription(owner, affectedUnits, line); caster->getCastDescription(owner, affectedUnits, line);
if(!line.message.empty()) if(!line.empty())
castDescription.lines.push_back(line); castDescription.lines.push_back(line);
} }
break; break;

View File

@ -33,7 +33,7 @@ BonusCaster::~BonusCaster() = default;
void BonusCaster::getCasterName(MetaString & text) const void BonusCaster::getCasterName(MetaString & text) const
{ {
if(!bonus->description.empty()) if(!bonus->description.empty())
text.addReplacement(bonus->description); text.replaceRawString(bonus->description);
else else
actualCaster->getCasterName(text); actualCaster->getCasterName(text);
} }
@ -43,9 +43,9 @@ void BonusCaster::getCastDescription(const Spell * spell, const std::vector<cons
const bool singleTarget = attacked.size() == 1; const bool singleTarget = attacked.size() == 1;
const int textIndex = singleTarget ? 195 : 196; const int textIndex = singleTarget ? 195 : 196;
text.addTxt(MetaString::GENERAL_TXT, textIndex); text.appendLocalString(EMetaText::GENERAL_TXT, textIndex);
getCasterName(text); getCasterName(text);
text.addReplacement(MetaString::SPELL_NAME, spell->getIndex()); text.replaceLocalString(EMetaText::SPELL_NAME, spell->getIndex());
if(singleTarget) if(singleTarget)
attacked.at(0)->addNameReplacement(text, true); attacked.at(0)->addNameReplacement(text, true);
} }

View File

@ -460,7 +460,7 @@ bool BaseMechanics::adaptGenericProblem(Problem & target) const
{ {
MetaString text; MetaString text;
// %s recites the incantations but they seem to have no effect. // %s recites the incantations but they seem to have no effect.
text.addTxt(MetaString::GENERAL_TXT, 541); text.appendLocalString(EMetaText::GENERAL_TXT, 541);
assert(caster); assert(caster);
caster->getCasterName(text); caster->getCasterName(text);
@ -489,14 +489,14 @@ bool BaseMechanics::adaptProblem(ESpellCastProblem::ESpellCastProblem source, Pr
if(b && b->val == 2 && b->source == BonusSource::ARTIFACT) if(b && b->val == 2 && b->source == BonusSource::ARTIFACT)
{ {
//The %s prevents %s from casting 3rd level or higher spells. //The %s prevents %s from casting 3rd level or higher spells.
text.addTxt(MetaString::GENERAL_TXT, 536); text.appendLocalString(EMetaText::GENERAL_TXT, 536);
text.addReplacement(MetaString::ART_NAMES, b->sid); text.replaceLocalString(EMetaText::ART_NAMES, b->sid);
caster->getCasterName(text); caster->getCasterName(text);
target.add(std::move(text), spells::Problem::NORMAL); target.add(std::move(text), spells::Problem::NORMAL);
} }
else if(b && b->source == BonusSource::TERRAIN_OVERLAY && VLC->battlefields()->getByIndex(b->sid)->identifier == "cursed_ground") else if(b && b->source == BonusSource::TERRAIN_OVERLAY && VLC->battlefields()->getByIndex(b->sid)->identifier == "cursed_ground")
{ {
text.addTxt(MetaString::GENERAL_TXT, 537); text.appendLocalString(EMetaText::GENERAL_TXT, 537);
target.add(std::move(text), spells::Problem::NORMAL); target.add(std::move(text), spells::Problem::NORMAL);
} }
else else
@ -510,14 +510,14 @@ bool BaseMechanics::adaptProblem(ESpellCastProblem::ESpellCastProblem source, Pr
case ESpellCastProblem::NO_APPROPRIATE_TARGET: case ESpellCastProblem::NO_APPROPRIATE_TARGET:
{ {
MetaString text; MetaString text;
text.addTxt(MetaString::GENERAL_TXT, 185); text.appendLocalString(EMetaText::GENERAL_TXT, 185);
target.add(std::move(text), spells::Problem::NORMAL); target.add(std::move(text), spells::Problem::NORMAL);
} }
break; break;
case ESpellCastProblem::INVALID: case ESpellCastProblem::INVALID:
{ {
MetaString text; MetaString text;
text.addReplacement("Internal error during check of spell cast."); text.appendRawString("Internal error during check of spell cast.");
target.add(std::move(text), spells::Problem::CRITICAL); target.add(std::move(text), spells::Problem::CRITICAL);
} }
break; break;

View File

@ -135,13 +135,13 @@ void Damage::describeEffect(std::vector<MetaString> & log, const Mechanics * m,
MetaString line; MetaString line;
if(kills > 1) if(kills > 1)
{ {
line.addTxt(MetaString::GENERAL_TXT, 119); //%d %s die under the terrible gaze of the %s. line.appendLocalString(EMetaText::GENERAL_TXT, 119); //%d %s die under the terrible gaze of the %s.
line.addReplacement(kills); line.replaceNumber(kills);
firstTarget->addNameReplacement(line, true); firstTarget->addNameReplacement(line, true);
} }
else else
{ {
line.addTxt(MetaString::GENERAL_TXT, 118); //One %s dies under the terrible gaze of the %s. line.appendLocalString(EMetaText::GENERAL_TXT, 118); //One %s dies under the terrible gaze of the %s.
firstTarget->addNameReplacement(line, false); firstTarget->addNameReplacement(line, false);
} }
m->caster->getCasterName(line); m->caster->getCasterName(line);
@ -151,7 +151,7 @@ void Damage::describeEffect(std::vector<MetaString> & log, const Mechanics * m,
{ {
{ {
MetaString line; MetaString line;
firstTarget->addText(line, MetaString::GENERAL_TXT, -367, true); firstTarget->addText(line, EMetaText::GENERAL_TXT, -367, true);
firstTarget->addNameReplacement(line, true); firstTarget->addNameReplacement(line, true);
log.push_back(line); log.push_back(line);
} }
@ -161,8 +161,8 @@ void Damage::describeEffect(std::vector<MetaString> & log, const Mechanics * m,
//todo: handle newlines in metastring //todo: handle newlines in metastring
std::string text = VLC->generaltexth->allTexts[343]; //Does %d points of damage. std::string text = VLC->generaltexth->allTexts[343]; //Does %d points of damage.
boost::algorithm::trim(text); boost::algorithm::trim(text);
line.addRawString(text); line.appendRawString(text);
line.addReplacement(static_cast<int>(damage)); //no more text afterwards line.replaceNumber(static_cast<int>(damage)); //no more text afterwards
log.push_back(line); log.push_back(line);
} }
} }
@ -170,9 +170,9 @@ void Damage::describeEffect(std::vector<MetaString> & log, const Mechanics * m,
{ {
{ {
MetaString line; MetaString line;
line.addTxt(MetaString::GENERAL_TXT, 376); // Spell %s does %d damage line.appendLocalString(EMetaText::GENERAL_TXT, 376); // Spell %s does %d damage
line.addReplacement(MetaString::SPELL_NAME, m->getSpellIndex()); line.replaceLocalString(EMetaText::SPELL_NAME, m->getSpellIndex());
line.addReplacement(static_cast<int>(damage)); line.replaceNumber(static_cast<int>(damage));
log.push_back(line); log.push_back(line);
} }
@ -183,19 +183,19 @@ void Damage::describeEffect(std::vector<MetaString> & log, const Mechanics * m,
if(kills > 1) if(kills > 1)
{ {
line.addTxt(MetaString::GENERAL_TXT, 379); // %d %s perishes line.appendLocalString(EMetaText::GENERAL_TXT, 379); // %d %s perishes
line.addReplacement(kills); line.replaceNumber(kills);
if(multiple) if(multiple)
line.addReplacement(MetaString::GENERAL_TXT, 43); // creatures line.replaceLocalString(EMetaText::GENERAL_TXT, 43); // creatures
else else
firstTarget->addNameReplacement(line, true); firstTarget->addNameReplacement(line, true);
} }
else // single creature killed else // single creature killed
{ {
line.addTxt(MetaString::GENERAL_TXT, 378); // one %s perishes line.appendLocalString(EMetaText::GENERAL_TXT, 378); // one %s perishes
if(multiple) if(multiple)
line.addReplacement(MetaString::GENERAL_TXT, 42); // creature line.replaceLocalString(EMetaText::GENERAL_TXT, 42); // creature
else else
firstTarget->addNameReplacement(line, false); firstTarget->addNameReplacement(line, false);
} }

View File

@ -43,7 +43,7 @@ void Dispel::apply(ServerCallback * server, const Mechanics * m, const EffectTar
if(describe && positive && !negative && !neutral) if(describe && positive && !negative && !neutral)
{ {
MetaString line; MetaString line;
unit->addText(line, MetaString::GENERAL_TXT, -555, true); unit->addText(line, EMetaText::GENERAL_TXT, -555, true);
unit->addNameReplacement(line, true); unit->addNameReplacement(line, true);
blm.lines.push_back(std::move(line)); blm.lines.push_back(std::move(line));
} }

View File

@ -119,19 +119,19 @@ void Heal::prepareHealEffect(int64_t value, BattleUnitsChanged & pack, BattleLog
// %d %s rise from the dead! // %d %s rise from the dead!
// in the table first comes plural string, then the singular one // in the table first comes plural string, then the singular one
MetaString resurrectText; MetaString resurrectText;
state->addText(resurrectText, MetaString::GENERAL_TXT, 116, resurrectedCount == 1); state->addText(resurrectText, EMetaText::GENERAL_TXT, 116, resurrectedCount == 1);
state->addNameReplacement(resurrectText); state->addNameReplacement(resurrectText);
resurrectText.addReplacement(resurrectedCount); resurrectText.replaceNumber(resurrectedCount);
logMessage.lines.push_back(std::move(resurrectText)); logMessage.lines.push_back(std::move(resurrectText));
} }
else if (unitHPgained > 0 && m->caster->getHeroCaster() == nullptr) //Show text about healed HP if healed by unit else if (unitHPgained > 0 && m->caster->getHeroCaster() == nullptr) //Show text about healed HP if healed by unit
{ {
MetaString healText; MetaString healText;
auto casterUnit = dynamic_cast<const battle::Unit*>(m->caster); auto casterUnit = dynamic_cast<const battle::Unit*>(m->caster);
healText.addTxt(MetaString::GENERAL_TXT, 414); healText.appendLocalString(EMetaText::GENERAL_TXT, 414);
casterUnit->addNameReplacement(healText, false); casterUnit->addNameReplacement(healText, false);
state->addNameReplacement(healText, false); state->addNameReplacement(healText, false);
healText.addReplacement((int)unitHPgained); healText.replaceNumber((int)unitHPgained);
logMessage.lines.push_back(std::move(healText)); logMessage.lines.push_back(std::move(healText));
} }

View File

@ -259,8 +259,8 @@ bool Obstacle::isHexAvailable(const CBattleInfoCallback * cb, const BattleHex &
bool Obstacle::noRoomToPlace(Problem & problem, const Mechanics * m) bool Obstacle::noRoomToPlace(Problem & problem, const Mechanics * m)
{ {
MetaString text; MetaString text;
text.addTxt(MetaString::GENERAL_TXT, 181);//No room to place %s here text.appendLocalString(EMetaText::GENERAL_TXT, 181);//No room to place %s here
text.addReplacement(m->getSpellName()); text.replaceRawString(m->getSpellName());
problem.add(std::move(text)); problem.add(std::move(text));
return false; return false;
} }

View File

@ -58,19 +58,19 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const
const auto *elemental = otherSummoned.front(); const auto *elemental = otherSummoned.front();
MetaString text; MetaString text;
text.addTxt(MetaString::GENERAL_TXT, 538); text.appendLocalString(EMetaText::GENERAL_TXT, 538);
const auto *caster = dynamic_cast<const CGHeroInstance *>(m->caster); const auto *caster = dynamic_cast<const CGHeroInstance *>(m->caster);
if(caster) if(caster)
{ {
text.addReplacement(caster->getNameTranslated()); text.replaceRawString(caster->getNameTranslated());
text.addReplacement(MetaString::CRE_PL_NAMES, elemental->creatureIndex()); text.replaceLocalString(EMetaText::CRE_PL_NAMES, elemental->creatureIndex());
if(caster->type->gender == EHeroGender::FEMALE) if(caster->type->gender == EHeroGender::FEMALE)
text.addReplacement(MetaString::GENERAL_TXT, 540); text.replaceLocalString(EMetaText::GENERAL_TXT, 540);
else else
text.addReplacement(MetaString::GENERAL_TXT, 539); text.replaceLocalString(EMetaText::GENERAL_TXT, 539);
} }
problem.add(std::move(text), Problem::NORMAL); problem.add(std::move(text), Problem::NORMAL);

View File

@ -30,7 +30,7 @@ static void describeEffect(std::vector<MetaString> & log, const Mechanics * m, c
auto addLogLine = [&](const int32_t baseTextID, const boost::logic::tribool & plural) auto addLogLine = [&](const int32_t baseTextID, const boost::logic::tribool & plural)
{ {
MetaString line; MetaString line;
target->addText(line, MetaString::GENERAL_TXT, baseTextID, plural); target->addText(line, EMetaText::GENERAL_TXT, baseTextID, plural);
target->addNameReplacement(line, plural); target->addNameReplacement(line, plural);
log.push_back(std::move(line)); log.push_back(std::move(line));
}; };
@ -78,10 +78,10 @@ static void describeEffect(std::vector<MetaString> & log, const Mechanics * m, c
//"The %s shrivel with age, and lose %d hit points." //"The %s shrivel with age, and lose %d hit points."
MetaString line; MetaString line;
target->addText(line, MetaString::GENERAL_TXT, 551); target->addText(line, EMetaText::GENERAL_TXT, 551);
target->addNameReplacement(line); target->addNameReplacement(line);
line.addReplacement(oldHealth - newHealth); line.replaceNumber(oldHealth - newHealth);
log.push_back(std::move(line)); log.push_back(std::move(line));
return; return;
} }

View File

@ -516,8 +516,8 @@ void CGameHandler::changePrimSkill(const CGHeroInstance * hero, PrimarySkill::Pr
InfoWindow iw; InfoWindow iw;
iw.player = hero->tempOwner; iw.player = hero->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 1); //can gain no more XP iw.text.appendLocalString(EMetaText::GENERAL_TXT, 1); //can gain no more XP
iw.text.addReplacement(hero->getNameTranslated()); iw.text.replaceRawString(hero->getNameTranslated());
sendAndApply(&iw); sendAndApply(&iw);
} }
} }
@ -725,7 +725,7 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
InfoWindow iw; InfoWindow iw;
iw.player = finishingBattle->winnerHero->tempOwner; iw.player = finishingBattle->winnerHero->tempOwner;
iw.text.addTxt (MetaString::GENERAL_TXT, 30); //You have captured enemy artifact iw.text.appendLocalString (EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact
for (auto art : arts) //TODO; separate function to display loot for various ojects? for (auto art : arts) //TODO; separate function to display loot for various ojects?
{ {
@ -751,8 +751,8 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
InfoWindow iw; InfoWindow iw;
iw.player = finishingBattle->winnerHero->tempOwner; iw.player = finishingBattle->winnerHero->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s iw.text.appendLocalString(EMetaText::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s
iw.text.addReplacement(finishingBattle->winnerHero->getNameTranslated()); iw.text.replaceRawString(finishingBattle->winnerHero->getNameTranslated());
std::ostringstream names; std::ostringstream names;
for (int i = 0; i < cs.spells.size(); i++) for (int i = 0; i < cs.spells.size(); i++)
@ -765,14 +765,14 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo)
} }
names << "."; names << ".";
iw.text.addReplacement(names.str()); iw.text.replaceRawString(names.str());
auto it = cs.spells.begin(); auto it = cs.spells.begin();
for (int i = 0; i < cs.spells.size(); i++, it++) for (int i = 0; i < cs.spells.size(); i++, it++)
{ {
iw.text.addReplacement(MetaString::SPELL_NAME, it->toEnum()); iw.text.replaceLocalString(EMetaText::SPELL_NAME, it->toEnum());
if (i == cs.spells.size() - 2) //we just added pre-last name if (i == cs.spells.size() - 2) //we just added pre-last name
iw.text.addReplacement(MetaString::GENERAL_TXT, 141); // " and " iw.text.replaceLocalString(EMetaText::GENERAL_TXT, 141); // " and "
iw.components.emplace_back(Component::EComponentType::SPELL, *it, 0, 0); iw.components.emplace_back(Component::EComponentType::SPELL, *it, 0, 0);
} }
sendAndApply(&iw); sendAndApply(&iw);
@ -1042,9 +1042,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
{ {
MetaString text; MetaString text;
attacker->addText(text, MetaString::GENERAL_TXT, 376); attacker->addText(text, EMetaText::GENERAL_TXT, 376);
attacker->addNameReplacement(text); attacker->addNameReplacement(text);
text.addReplacement(totalDamage); text.replaceNumber(totalDamage);
blm.lines.push_back(text); blm.lines.push_back(text);
} }
@ -1055,9 +1055,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
if(drainedLife > 0) if(drainedLife > 0)
{ {
MetaString text; MetaString text;
attackerState->addText(text, MetaString::GENERAL_TXT, 361); attackerState->addText(text, EMetaText::GENERAL_TXT, 361);
attackerState->addNameReplacement(text, false); attackerState->addNameReplacement(text, false);
text.addReplacement(drainedLife); text.replaceNumber(drainedLife);
defender->addNameReplacement(text, true); defender->addNameReplacement(text, true);
blm.lines.push_back(std::move(text)); blm.lines.push_back(std::move(text));
} }
@ -1105,9 +1105,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
// TODO: this is already implemented in Damage::describeEffect() // TODO: this is already implemented in Damage::describeEffect()
{ {
MetaString text; MetaString text;
text.addTxt(MetaString::GENERAL_TXT, 376); text.appendLocalString(EMetaText::GENERAL_TXT, 376);
text.addReplacement(MetaString::SPELL_NAME, SpellID::FIRE_SHIELD); text.replaceLocalString(EMetaText::SPELL_NAME, SpellID::FIRE_SHIELD);
text.addReplacement(totalDamage); text.replaceNumber(totalDamage);
blm.lines.push_back(std::move(text)); blm.lines.push_back(std::move(text));
} }
addGenericKilledLog(blm, attacker, bsa.killedAmount, false); addGenericKilledLog(blm, attacker, bsa.killedAmount, false);
@ -1216,7 +1216,7 @@ void CGameHandler::addGenericKilledLog(BattleLogMessage & blm, const CStack * de
txt % (multiple ? VLC->generaltexth->allTexts[42] : defender->unitType()->getNameSingularTranslated()); // creature perishes txt % (multiple ? VLC->generaltexth->allTexts[42] : defender->unitType()->getNameSingularTranslated()); // creature perishes
} }
MetaString line; MetaString line;
line.addRawString(txt.str()); line.appendRawString(txt.str());
blm.lines.push_back(std::move(line)); blm.lines.push_back(std::move(line));
} }
} }
@ -1988,36 +1988,36 @@ void CGameHandler::newTurn()
switch (n.specialWeek) switch (n.specialWeek)
{ {
case NewTurn::DOUBLE_GROWTH: case NewTurn::DOUBLE_GROWTH:
iw.text.addTxt(MetaString::ARRAY_TXT, 131); iw.text.appendLocalString(EMetaText::ARRAY_TXT, 131);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid); iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid); iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
break; break;
case NewTurn::PLAGUE: case NewTurn::PLAGUE:
iw.text.addTxt(MetaString::ARRAY_TXT, 132); iw.text.appendLocalString(EMetaText::ARRAY_TXT, 132);
break; break;
case NewTurn::BONUS_GROWTH: case NewTurn::BONUS_GROWTH:
iw.text.addTxt(MetaString::ARRAY_TXT, 134); iw.text.appendLocalString(EMetaText::ARRAY_TXT, 134);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid); iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, n.creatureid); iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, n.creatureid);
break; break;
case NewTurn::DEITYOFFIRE: case NewTurn::DEITYOFFIRE:
iw.text.addTxt(MetaString::ARRAY_TXT, 135); iw.text.appendLocalString(EMetaText::ARRAY_TXT, 135);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, 42); //%s imp iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, 42); //%s imp
iw.text.addReplacement(MetaString::CRE_SING_NAMES, 42); //%s imp iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, 42); //%s imp
iw.text.addReplacement2(15); //%+d 15 iw.text.replacePositiveNumber(15); //%+d 15
iw.text.addReplacement(MetaString::CRE_SING_NAMES, 43); //%s familiar iw.text.replaceLocalString(EMetaText::CRE_SING_NAMES, 43); //%s familiar
iw.text.addReplacement2(15); //%+d 15 iw.text.replacePositiveNumber(15); //%+d 15
break; break;
default: default:
if (newMonth) if (newMonth)
{ {
iw.text.addTxt(MetaString::ARRAY_TXT, (130)); iw.text.appendLocalString(EMetaText::ARRAY_TXT, (130));
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(32, 41)); iw.text.replaceLocalString(EMetaText::ARRAY_TXT, getRandomGenerator().nextInt(32, 41));
} }
else else
{ {
iw.text.addTxt(MetaString::ARRAY_TXT, (133)); iw.text.appendLocalString(EMetaText::ARRAY_TXT, (133));
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(43, 57)); iw.text.replaceLocalString(EMetaText::ARRAY_TXT, getRandomGenerator().nextInt(43, 57));
} }
} }
for (auto & elem : gs->players) for (auto & elem : gs->players)
@ -2496,8 +2496,8 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owne
{ {
InfoWindow iw; InfoWindow iw;
iw.player = oldOwner; iw.player = oldOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated.
iw.text.addReplacement(MetaString::COLOR, oldOwner.getNum()); iw.text.replaceLocalString(EMetaText::COLOR, oldOwner.getNum());
sendAndApply(&iw); sendAndApply(&iw);
} }
} }
@ -2797,57 +2797,57 @@ void CGameHandler::useScholarSkill(ObjectInstanceID fromHero, ObjectInstanceID t
iw.player = h1->tempOwner; iw.player = h1->tempOwner;
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, 18, ScholarSkillLevel, 0); iw.components.emplace_back(Component::EComponentType::SEC_SKILL, 18, ScholarSkillLevel, 0);
iw.text.addTxt(MetaString::GENERAL_TXT, 139);//"%s, who has studied magic extensively, iw.text.appendLocalString(EMetaText::GENERAL_TXT, 139);//"%s, who has studied magic extensively,
iw.text.addReplacement(h1->getNameTranslated()); iw.text.replaceRawString(h1->getNameTranslated());
if (!cs2.spells.empty())//if found new spell - apply if (!cs2.spells.empty())//if found new spell - apply
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 140);//learns iw.text.appendLocalString(EMetaText::GENERAL_TXT, 140);//learns
int size = static_cast<int>(cs2.spells.size()); int size = static_cast<int>(cs2.spells.size());
for (auto it : cs2.spells) for (auto it : cs2.spells)
{ {
iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0); iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0);
iw.text.addTxt(MetaString::SPELL_NAME, it.toEnum()); iw.text.appendLocalString(EMetaText::SPELL_NAME, it.toEnum());
switch (size--) switch (size--)
{ {
case 2: case 2:
iw.text.addTxt(MetaString::GENERAL_TXT, 141); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 141);
case 1: case 1:
break; break;
default: default:
iw.text.addRawString(", "); iw.text.appendRawString(", ");
} }
} }
iw.text.addTxt(MetaString::GENERAL_TXT, 142);//from %s iw.text.appendLocalString(EMetaText::GENERAL_TXT, 142);//from %s
iw.text.addReplacement(h2->getNameTranslated()); iw.text.replaceRawString(h2->getNameTranslated());
sendAndApply(&cs2); sendAndApply(&cs2);
} }
if (!cs1.spells.empty() && !cs2.spells.empty()) if (!cs1.spells.empty() && !cs2.spells.empty())
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 141);//and iw.text.appendLocalString(EMetaText::GENERAL_TXT, 141);//and
} }
if (!cs1.spells.empty()) if (!cs1.spells.empty())
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 147);//teaches iw.text.appendLocalString(EMetaText::GENERAL_TXT, 147);//teaches
int size = static_cast<int>(cs1.spells.size()); int size = static_cast<int>(cs1.spells.size());
for (auto it : cs1.spells) for (auto it : cs1.spells)
{ {
iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0); iw.components.emplace_back(Component::EComponentType::SPELL, it, 1, 0);
iw.text.addTxt(MetaString::SPELL_NAME, it.toEnum()); iw.text.appendLocalString(EMetaText::SPELL_NAME, it.toEnum());
switch (size--) switch (size--)
{ {
case 2: case 2:
iw.text.addTxt(MetaString::GENERAL_TXT, 141); iw.text.appendLocalString(EMetaText::GENERAL_TXT, 141);
case 1: case 1:
break; break;
default: default:
iw.text.addRawString(", "); iw.text.appendRawString(", ");
} }
} }
iw.text.addTxt(MetaString::GENERAL_TXT, 148);//from %s iw.text.appendLocalString(EMetaText::GENERAL_TXT, 148);//from %s
iw.text.addReplacement(h2->getNameTranslated()); iw.text.replaceRawString(h2->getNameTranslated());
sendAndApply(&cs1); sendAndApply(&cs1);
} }
sendAndApply(&iw); sendAndApply(&iw);
@ -4673,9 +4673,9 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
BattleLogMessage message; BattleLogMessage message;
MetaString text; MetaString text;
stack->addText(text, MetaString::GENERAL_TXT, 120); stack->addText(text, EMetaText::GENERAL_TXT, 120);
stack->addNameReplacement(text); stack->addNameReplacement(text);
text.addReplacement(difference); text.replaceNumber(difference);
message.lines.push_back(text); message.lines.push_back(text);
@ -5354,7 +5354,7 @@ void CGameHandler::handleTimeEvents()
//prepare dialog //prepare dialog
InfoWindow iw; InfoWindow iw;
iw.player = color; iw.player = color;
iw.text.addRawString(ev.message); iw.text.appendRawString(ev.message);
for (int i=0; i<ev.resources.size(); i++) for (int i=0; i<ev.resources.size(); i++)
{ {
@ -5405,7 +5405,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
// dialog // dialog
InfoWindow iw; InfoWindow iw;
iw.player = player; iw.player = player;
iw.text.addRawString(ev.message); iw.text.appendRawString(ev.message);
if (ev.resources.nonZero()) if (ev.resources.nonZero())
{ {
@ -5791,10 +5791,10 @@ void CGameHandler::getVictoryLossMessage(PlayerColor player, const EVictoryLossC
{ {
out.player = player; out.player = player;
out.text.clear(); out.text.clear();
out.text.addRawString(VLC->generaltexth->translate(victoryLossCheckResult.messageToOthers)); out.text.appendRawString(VLC->generaltexth->translate(victoryLossCheckResult.messageToOthers));
// hackish, insert one player-specific string, if applicable // hackish, insert one player-specific string, if applicable
if (victoryLossCheckResult.messageToOthers.find("%s") != std::string::npos) if (victoryLossCheckResult.messageToOthers.find("%s") != std::string::npos)
out.text.addReplacement(MetaString::COLOR, player.getNum()); out.text.replaceLocalString(EMetaText::COLOR, player.getNum());
out.components.emplace_back(Component::EComponentType::FLAG, player.getNum(), 0, 0); out.components.emplace_back(Component::EComponentType::FLAG, player.getNum(), 0, 0);
} }
@ -5822,8 +5822,8 @@ bool CGameHandler::dig(const CGHeroInstance *h)
iw.player = h->tempOwner; iw.player = h->tempOwner;
if (gs->map->grailPos == h->visitablePos()) if (gs->map->grailPos == h->visitablePos())
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the " iw.text.appendLocalString(EMetaText::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
iw.text.addTxt(MetaString::ART_NAMES, ArtifactID::GRAIL); iw.text.appendLocalString(EMetaText::ART_NAMES, ArtifactID::GRAIL);
iw.soundID = soundBase::ULTIMATEARTIFACT; iw.soundID = soundBase::ULTIMATEARTIFACT;
giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::FIRST_AVAILABLE); //give grail giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::FIRST_AVAILABLE); //give grail
sendAndApply(&iw); sendAndApply(&iw);
@ -5831,12 +5831,12 @@ bool CGameHandler::dig(const CGHeroInstance *h)
iw.soundID = soundBase::invalid; iw.soundID = soundBase::invalid;
iw.components.emplace_back(Component::EComponentType::ARTIFACT, ArtifactID::GRAIL, 0, 0); iw.components.emplace_back(Component::EComponentType::ARTIFACT, ArtifactID::GRAIL, 0, 0);
iw.text.clear(); iw.text.clear();
iw.text.addTxt(MetaString::ART_DESCR, ArtifactID::GRAIL); iw.text.appendLocalString(EMetaText::ART_DESCR, ArtifactID::GRAIL);
sendAndApply(&iw); sendAndApply(&iw);
} }
else else
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?" iw.text.appendLocalString(EMetaText::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?"
iw.soundID = soundBase::Dig; iw.soundID = soundBase::Dig;
sendAndApply(&iw); sendAndApply(&iw);
} }
@ -7221,7 +7221,7 @@ void CGameHandler::showInfoDialog(const std::string & msg, PlayerColor player)
{ {
InfoWindow iw; InfoWindow iw;
iw.player = player; iw.player = player;
iw.text.addRawString(msg); iw.text.appendRawString(msg);
showInfoDialog(&iw); showInfoDialog(&iw);
} }