2017-07-13 10:26:03 +02:00
|
|
|
/*
|
|
|
|
* CGeneralTextHandler.cpp, part of VCMI engine
|
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
2011-12-14 00:23:17 +03:00
|
|
|
#include "StdInc.h"
|
2007-07-08 20:28:08 +03:00
|
|
|
#include "CGeneralTextHandler.h"
|
2011-12-14 00:23:17 +03:00
|
|
|
|
2013-10-26 00:45:14 +03:00
|
|
|
#include <boost/locale.hpp>
|
|
|
|
|
2013-07-28 17:49:50 +03:00
|
|
|
#include "filesystem/Filesystem.h"
|
2013-10-26 00:45:14 +03:00
|
|
|
#include "CConfigHandler.h"
|
2013-04-26 00:50:55 +03:00
|
|
|
#include "CModHandler.h"
|
2013-10-26 00:45:14 +03:00
|
|
|
#include "GameConstants.h"
|
2013-04-26 00:50:55 +03:00
|
|
|
#include "VCMI_Lib.h"
|
2007-07-08 20:28:08 +03:00
|
|
|
|
2014-05-23 19:46:54 +03:00
|
|
|
size_t Unicode::getCharacterSize(char firstByte)
|
2013-10-26 00:45:14 +03:00
|
|
|
{
|
|
|
|
// length of utf-8 character can be determined from 1st byte by counting number of highest bits set to 1:
|
|
|
|
// 0xxxxxxx -> 1 - ASCII chars
|
|
|
|
// 110xxxxx -> 2
|
|
|
|
// 11110xxx -> 4 - last allowed in current standard
|
|
|
|
// 1111110x -> 6 - last allowed in original standard
|
|
|
|
|
2014-05-23 19:46:54 +03:00
|
|
|
if ((ui8)firstByte < 0x80)
|
2013-10-26 00:45:14 +03:00
|
|
|
return 1; // ASCII
|
|
|
|
|
|
|
|
size_t ret = 0;
|
|
|
|
|
|
|
|
for (size_t i=0; i<8; i++)
|
|
|
|
{
|
2014-05-23 19:46:54 +03:00
|
|
|
if (((ui8)firstByte & (0x80 >> i)) != 0)
|
2013-10-26 00:45:14 +03:00
|
|
|
ret++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-05-23 19:46:54 +03:00
|
|
|
bool Unicode::isValidCharacter(const char * character, size_t maxSize)
|
2013-10-26 00:45:14 +03:00
|
|
|
{
|
2014-05-23 19:46:54 +03:00
|
|
|
// can't be first byte in UTF8
|
|
|
|
if ((ui8)character[0] >= 0x80 && (ui8)character[0] < 0xC0)
|
|
|
|
return false;
|
2013-10-26 00:45:14 +03:00
|
|
|
// first character must follow rules checked in getCharacterSize
|
2014-05-23 19:46:54 +03:00
|
|
|
size_t size = getCharacterSize((ui8)character[0]);
|
2013-10-26 00:45:14 +03:00
|
|
|
|
2014-05-23 19:46:54 +03:00
|
|
|
if ((ui8)character[0] > 0xF4)
|
2013-10-26 00:45:14 +03:00
|
|
|
return false; // above maximum allowed in standard (UTF codepoints are capped at 0x0010FFFF)
|
|
|
|
|
|
|
|
if (size > maxSize)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remaining characters must have highest bit set to 1
|
|
|
|
for (size_t i = 1; i < size; i++)
|
|
|
|
{
|
2014-05-23 19:46:54 +03:00
|
|
|
if (((ui8)character[i] & 0x80) == 0)
|
2013-10-26 00:45:14 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Unicode::isValidASCII(const std::string & text)
|
|
|
|
{
|
|
|
|
for (const char & ch : text)
|
|
|
|
if (ui8(ch) >= 0x80 )
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Unicode::isValidASCII(const char * data, size_t size)
|
|
|
|
{
|
|
|
|
for (size_t i=0; i<size; i++)
|
|
|
|
if (ui8(data[i]) >= 0x80 )
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Unicode::isValidString(const std::string & text)
|
|
|
|
{
|
|
|
|
for (size_t i=0; i<text.size(); i += getCharacterSize(text[i]))
|
|
|
|
{
|
2014-05-23 19:46:54 +03:00
|
|
|
if (!isValidCharacter(text.data() + i, text.size() - i))
|
2013-10-26 00:45:14 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Unicode::isValidString(const char * data, size_t size)
|
|
|
|
{
|
|
|
|
for (size_t i=0; i<size; i += getCharacterSize(data[i]))
|
|
|
|
{
|
2014-05-23 19:46:54 +03:00
|
|
|
if (!isValidCharacter(data + i, size - i))
|
2013-10-26 00:45:14 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string getSelectedEncoding()
|
|
|
|
{
|
|
|
|
return settings["general"]["encoding"].String();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Unicode::toUnicode(const std::string &text)
|
|
|
|
{
|
|
|
|
return toUnicode(text, getSelectedEncoding());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Unicode::toUnicode(const std::string &text, const std::string &encoding)
|
|
|
|
{
|
|
|
|
return boost::locale::conv::to_utf<char>(text, encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Unicode::fromUnicode(const std::string & text)
|
|
|
|
{
|
|
|
|
return fromUnicode(text, getSelectedEncoding());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Unicode::fromUnicode(const std::string &text, const std::string &encoding)
|
|
|
|
{
|
|
|
|
return boost::locale::conv::from_utf<char>(text, encoding);
|
|
|
|
}
|
|
|
|
|
2017-07-15 13:08:20 +02:00
|
|
|
void Unicode::trimRight(std::string & text, const size_t amount)
|
2014-07-02 18:16:05 +03:00
|
|
|
{
|
|
|
|
if(text.empty())
|
|
|
|
return;
|
|
|
|
//todo: more efficient algorithm
|
|
|
|
for(int i = 0; i< amount; i++){
|
2016-08-12 11:10:27 +02:00
|
|
|
auto b = text.begin();
|
2014-07-02 18:16:05 +03:00
|
|
|
auto e = text.end();
|
|
|
|
size_t lastLen = 0;
|
|
|
|
size_t len = 0;
|
|
|
|
while (b != e) {
|
|
|
|
lastLen = len;
|
|
|
|
size_t n = getCharacterSize(*b);
|
|
|
|
|
|
|
|
if(!isValidCharacter(&(*b),e-b))
|
2016-08-12 11:10:27 +02:00
|
|
|
{
|
|
|
|
logGlobal->error("Invalid UTF8 sequence");
|
2014-07-02 18:16:05 +03:00
|
|
|
break;//invalid sequence will be trimmed
|
|
|
|
}
|
|
|
|
|
|
|
|
len += n;
|
|
|
|
b += n;
|
2016-08-12 11:10:27 +02:00
|
|
|
}
|
2014-07-02 18:16:05 +03:00
|
|
|
|
|
|
|
text.resize(lastLen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
//Helper for string -> float conversion
|
|
|
|
class LocaleWithComma: public std::numpunct<char>
|
|
|
|
{
|
|
|
|
protected:
|
2015-10-12 15:47:10 +02:00
|
|
|
char do_decimal_point() const override
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
|
|
|
return ',';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
CLegacyConfigParser::CLegacyConfigParser(std::string URI)
|
2008-12-22 19:48:41 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
init(CResourceHandler::get()->load(ResourceID(URI, EResType::TEXT)));
|
2008-12-22 19:48:41 +02:00
|
|
|
}
|
2009-07-03 22:57:14 +03:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
CLegacyConfigParser::CLegacyConfigParser(const std::unique_ptr<CInputStream> & input)
|
2009-07-03 22:57:14 +03:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
init(input);
|
2009-07-03 22:57:14 +03:00
|
|
|
}
|
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
void CLegacyConfigParser::init(const std::unique_ptr<CInputStream> & input)
|
2012-08-01 15:02:54 +03:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
data.reset(new char[input->getSize()]);
|
|
|
|
input->read((ui8*)data.get(), input->getSize());
|
2012-08-01 15:02:54 +03:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
curr = data.get();
|
|
|
|
end = curr + input->getSize();
|
2012-08-01 15:02:54 +03:00
|
|
|
}
|
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
std::string CLegacyConfigParser::extractQuotedPart()
|
2008-11-28 03:36:34 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
assert(*curr == '\"');
|
2008-11-28 03:36:34 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
curr++; // skip quote
|
|
|
|
char * begin = curr;
|
2008-11-28 03:36:34 +02:00
|
|
|
|
2013-01-26 22:39:54 +03:00
|
|
|
while (curr != end && *curr != '\"' && *curr != '\t')
|
2012-08-25 11:44:51 +03:00
|
|
|
curr++;
|
2008-11-28 03:36:34 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
return std::string(begin, curr++); //increment curr to close quote
|
|
|
|
}
|
2008-12-22 19:48:41 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
std::string CLegacyConfigParser::extractQuotedString()
|
|
|
|
{
|
|
|
|
assert(*curr == '\"');
|
2008-12-22 19:48:41 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
std::string ret;
|
|
|
|
while (true)
|
2008-12-22 19:48:41 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
ret += extractQuotedPart();
|
2008-12-22 19:48:41 +02:00
|
|
|
|
2015-09-12 22:03:10 +02:00
|
|
|
// double quote - add it to string and continue quoted part
|
|
|
|
if (curr < end && *curr == '\"')
|
2013-01-26 22:39:54 +03:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
ret += '\"';
|
2013-01-26 22:39:54 +03:00
|
|
|
}
|
2015-09-12 22:03:10 +02:00
|
|
|
//extract normal part
|
|
|
|
else if(curr < end && *curr != '\t' && *curr != '\r')
|
|
|
|
{
|
|
|
|
char * begin = curr;
|
|
|
|
|
|
|
|
while (curr < end && *curr != '\t' && *curr != '\r' && *curr != '\"')//find end of string or next quoted part start
|
2016-08-12 11:10:27 +02:00
|
|
|
curr++;
|
|
|
|
|
2015-09-12 22:03:10 +02:00
|
|
|
ret += std::string(begin, curr);
|
2016-08-12 11:10:27 +02:00
|
|
|
|
2015-09-12 22:03:10 +02:00
|
|
|
if(curr>=end || *curr != '\"')
|
|
|
|
return ret;
|
2016-08-12 11:10:27 +02:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
else // end of string
|
|
|
|
return ret;
|
2008-12-22 19:48:41 +02:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string CLegacyConfigParser::extractNormalString()
|
|
|
|
{
|
|
|
|
char * begin = curr;
|
|
|
|
|
|
|
|
while (curr < end && *curr != '\t' && *curr != '\r')//find end of string
|
|
|
|
curr++;
|
|
|
|
|
|
|
|
return std::string(begin, curr);
|
|
|
|
}
|
|
|
|
|
2013-10-26 00:45:14 +03:00
|
|
|
std::string CLegacyConfigParser::readRawString()
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
|
|
|
if (curr >= end || *curr == '\n')
|
|
|
|
return "";
|
|
|
|
|
|
|
|
std::string ret;
|
|
|
|
|
|
|
|
if (*curr == '\"')
|
|
|
|
ret = extractQuotedString();// quoted text - find closing quote
|
|
|
|
else
|
|
|
|
ret = extractNormalString();//string without quotes - copy till \t or \r
|
|
|
|
|
2018-04-19 15:12:18 +02:00
|
|
|
curr++;
|
2012-08-25 11:44:51 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-10-26 00:45:14 +03:00
|
|
|
std::string CLegacyConfigParser::readString()
|
|
|
|
{
|
|
|
|
// do not convert strings that are already in ASCII - this will only slow down loading process
|
|
|
|
std::string str = readRawString();
|
|
|
|
if (Unicode::isValidASCII(str))
|
|
|
|
return str;
|
|
|
|
return Unicode::toUnicode(str);
|
|
|
|
}
|
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
float CLegacyConfigParser::readNumber()
|
|
|
|
{
|
2013-10-26 00:45:14 +03:00
|
|
|
std::string input = readRawString();
|
2012-08-25 11:44:51 +03:00
|
|
|
|
|
|
|
std::istringstream stream(input);
|
|
|
|
|
2017-07-16 11:58:05 +02:00
|
|
|
if(input.find(',') != std::string::npos) // code to handle conversion with comma as decimal separator
|
|
|
|
stream.imbue(std::locale(std::locale(), new LocaleWithComma()));
|
2012-08-25 11:44:51 +03:00
|
|
|
|
2013-06-09 13:09:28 +03:00
|
|
|
float result;
|
2012-08-25 11:44:51 +03:00
|
|
|
if ( !(stream >> result) )
|
|
|
|
return 0;
|
|
|
|
return result;
|
|
|
|
}
|
2008-12-22 19:48:41 +02:00
|
|
|
|
2013-06-23 22:35:54 +03:00
|
|
|
bool CLegacyConfigParser::isNextEntryEmpty() const
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
2012-09-26 16:13:39 +03:00
|
|
|
char * nextSymbol = curr;
|
|
|
|
while (nextSymbol < end && *nextSymbol == ' ')
|
|
|
|
nextSymbol++; //find next meaningfull symbol
|
|
|
|
|
|
|
|
return nextSymbol >= end || *nextSymbol == '\n' || *nextSymbol == '\r' || *nextSymbol == '\t';
|
2012-08-25 11:44:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CLegacyConfigParser::endLine()
|
|
|
|
{
|
|
|
|
while (curr < end && *curr != '\n')
|
|
|
|
readString();
|
|
|
|
|
2018-04-19 15:12:18 +02:00
|
|
|
curr++;
|
2012-08-25 11:44:51 +03:00
|
|
|
|
|
|
|
return curr < end;
|
|
|
|
}
|
|
|
|
|
2016-10-29 17:00:12 +02:00
|
|
|
void CGeneralTextHandler::readToVector(std::string sourceName, std::vector<std::string> &dest)
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
|
|
|
CLegacyConfigParser parser(sourceName);
|
|
|
|
do
|
2008-12-22 19:48:41 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
dest.push_back(parser.readString());
|
2008-12-22 19:48:41 +02:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
while (parser.endLine());
|
|
|
|
}
|
2008-12-22 19:48:41 +02:00
|
|
|
|
2013-04-21 15:49:26 +03:00
|
|
|
CGeneralTextHandler::CGeneralTextHandler()
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
|
|
|
readToVector("DATA/VCDESC.TXT", victoryConditions);
|
|
|
|
readToVector("DATA/LCDESC.TXT", lossCondtions);
|
|
|
|
readToVector("DATA/TCOMMAND.TXT", tcommands);
|
|
|
|
readToVector("DATA/HALLINFO.TXT", hcommands);
|
|
|
|
readToVector("DATA/CASTINFO.TXT", fcommands);
|
|
|
|
readToVector("DATA/ADVEVENT.TXT", advobtxt);
|
|
|
|
readToVector("DATA/XTRAINFO.TXT", xtrainfo);
|
|
|
|
readToVector("DATA/RESTYPES.TXT", restypes);
|
|
|
|
readToVector("DATA/TERRNAME.TXT", terrainNames);
|
|
|
|
readToVector("DATA/RANDSIGN.TXT", randsign);
|
2013-05-04 16:14:23 +03:00
|
|
|
readToVector("DATA/CRGEN1.TXT", creGens);
|
2012-08-25 11:44:51 +03:00
|
|
|
readToVector("DATA/CRGEN4.TXT", creGens4);
|
|
|
|
readToVector("DATA/OVERVIEW.TXT", overview);
|
|
|
|
readToVector("DATA/ARRAYTXT.TXT", arraytxt);
|
|
|
|
readToVector("DATA/PRISKILL.TXT", primarySkillNames);
|
|
|
|
readToVector("DATA/JKTEXT.TXT", jktexts);
|
|
|
|
readToVector("DATA/TVRNINFO.TXT", tavernInfo);
|
2015-11-30 19:52:15 +02:00
|
|
|
readToVector("DATA/RANDTVRN.TXT", tavernRumors);
|
2012-08-25 11:44:51 +03:00
|
|
|
readToVector("DATA/TURNDUR.TXT", turnDurations);
|
|
|
|
readToVector("DATA/HEROSCRN.TXT", heroscrn);
|
|
|
|
readToVector("DATA/TENTCOLR.TXT", tentColors);
|
|
|
|
readToVector("DATA/SKILLLEV.TXT", levels);
|
|
|
|
|
2021-02-11 21:06:47 +02:00
|
|
|
static const char * HD_MOD_COMMANDS = "DATA/HDCOMMANDS.TXT";
|
|
|
|
if (CResourceHandler::get()->existsResource(ResourceID(HD_MOD_COMMANDS, EResType::TEXT)))
|
|
|
|
readToVector(HD_MOD_COMMANDS, hdModCommands);
|
2020-04-01 00:01:57 +02:00
|
|
|
|
2013-10-27 16:05:01 +03:00
|
|
|
localizedTexts = JsonNode(ResourceID("config/translate.json", EResType::TEXT));
|
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
|
|
|
CLegacyConfigParser parser("DATA/GENRLTXT.TXT");
|
|
|
|
parser.endLine();
|
|
|
|
do
|
2008-12-22 19:48:41 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
allTexts.push_back(parser.readString());
|
2008-12-22 19:48:41 +02:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
while (parser.endLine());
|
2008-12-22 19:48:41 +02:00
|
|
|
}
|
2009-05-22 02:50:45 +03:00
|
|
|
{
|
2013-05-04 16:14:23 +03:00
|
|
|
CLegacyConfigParser parser("DATA/HELP.TXT");
|
2012-08-25 11:44:51 +03:00
|
|
|
do
|
2009-05-22 02:50:45 +03:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
std::string first = parser.readString();
|
|
|
|
std::string second = parser.readString();
|
|
|
|
zelp.push_back(std::make_pair(first, second));
|
2009-05-22 02:50:45 +03:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
while (parser.endLine());
|
2009-05-22 02:50:45 +03:00
|
|
|
}
|
2010-01-25 23:25:14 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
CLegacyConfigParser nameParser("DATA/MINENAME.TXT");
|
|
|
|
CLegacyConfigParser eventParser("DATA/MINEEVNT.TXT");
|
2010-01-25 23:25:14 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
do
|
|
|
|
{
|
|
|
|
std::string name = nameParser.readString();
|
|
|
|
std::string event = eventParser.readString();
|
|
|
|
mines.push_back(std::make_pair(name, event));
|
|
|
|
}
|
|
|
|
while (nameParser.endLine() && eventParser.endLine());
|
2010-02-01 19:07:46 +02:00
|
|
|
}
|
2009-01-11 00:08:18 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
CLegacyConfigParser parser("DATA/PLCOLORS.TXT");
|
|
|
|
do
|
|
|
|
{
|
|
|
|
std::string color = parser.readString();
|
|
|
|
colors.push_back(color);
|
2009-01-11 00:08:18 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
color[0] = toupper(color[0]);
|
|
|
|
capColors.push_back(color);
|
|
|
|
}
|
|
|
|
while (parser.endLine());
|
2009-01-11 00:08:18 +02:00
|
|
|
}
|
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
CLegacyConfigParser parser("DATA/SEERHUT.TXT");
|
2009-01-11 00:08:18 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
//skip header
|
|
|
|
parser.endLine();
|
2009-01-11 00:08:18 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
for (int i = 0; i < 6; ++i)
|
|
|
|
seerEmpty.push_back(parser.readString());
|
2013-07-23 18:03:01 +03:00
|
|
|
parser.endLine();
|
2010-01-30 22:53:47 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
quests.resize(10);
|
|
|
|
for (int i = 0; i < 9; ++i) //9 types of quests
|
2010-01-26 21:43:15 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
quests[i].resize(5);
|
|
|
|
for (int j = 0; j < 5; ++j)
|
2010-01-26 21:43:15 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
parser.readString(); //front description
|
|
|
|
for (int k = 0; k < 6; ++k)
|
|
|
|
quests[i][j].push_back(parser.readString());
|
|
|
|
|
|
|
|
parser.endLine();
|
2010-01-26 21:43:15 +02:00
|
|
|
}
|
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
quests[9].resize(1);
|
2010-01-30 22:53:47 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
for (int k = 0; k < 6; ++k) //Time limit
|
|
|
|
{
|
|
|
|
quests[9][0].push_back(parser.readString());
|
|
|
|
}
|
|
|
|
parser.endLine();
|
|
|
|
|
|
|
|
parser.endLine(); // empty line
|
|
|
|
parser.endLine(); // header
|
|
|
|
|
|
|
|
for (int i = 0; i < 48; ++i)
|
|
|
|
{
|
|
|
|
seerNames.push_back(parser.readString());
|
|
|
|
parser.endLine();
|
|
|
|
}
|
2010-01-30 22:53:47 +02:00
|
|
|
}
|
2012-07-08 19:36:20 +03:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
CLegacyConfigParser parser("DATA/CAMPTEXT.TXT");
|
2012-07-08 19:36:20 +03:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
//skip header
|
|
|
|
parser.endLine();
|
|
|
|
|
|
|
|
std::string text;
|
|
|
|
do
|
2010-02-12 17:04:01 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
text = parser.readString();
|
|
|
|
if (!text.empty())
|
2012-09-18 18:06:29 +03:00
|
|
|
campaignMapNames.push_back(text);
|
2010-02-12 17:04:01 +02:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
while (parser.endLine() && !text.empty());
|
2010-02-12 17:04:01 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
for (size_t i=0; i<campaignMapNames.size(); i++)
|
2010-02-12 17:04:01 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
do // skip empty space and header
|
2010-02-12 17:04:01 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
text = parser.readString();
|
2010-02-12 17:04:01 +02:00
|
|
|
}
|
2012-08-25 11:44:51 +03:00
|
|
|
while (parser.endLine() && text.empty());
|
2011-02-07 16:39:17 +02:00
|
|
|
|
2012-08-25 11:44:51 +03:00
|
|
|
campaignRegionNames.push_back(std::vector<std::string>());
|
|
|
|
do
|
|
|
|
{
|
|
|
|
text = parser.readString();
|
|
|
|
if (!text.empty())
|
2012-09-18 18:06:29 +03:00
|
|
|
campaignRegionNames.back().push_back(text);
|
2012-08-25 11:44:51 +03:00
|
|
|
}
|
|
|
|
while (parser.endLine() && !text.empty());
|
|
|
|
}
|
|
|
|
}
|
2013-04-26 00:50:55 +03:00
|
|
|
if (VLC->modh->modules.STACK_EXP)
|
2011-03-21 10:14:23 +02:00
|
|
|
{
|
2012-08-25 11:44:51 +03:00
|
|
|
CLegacyConfigParser parser("DATA/ZCREXP.TXT");
|
|
|
|
parser.endLine();//header
|
2014-07-04 12:48:09 +03:00
|
|
|
for (size_t iter=0; iter<325; iter++)
|
|
|
|
{
|
|
|
|
parser.readString(); //ignore 1st column with description
|
|
|
|
zcrexp.push_back(parser.readString());
|
|
|
|
parser.endLine();
|
|
|
|
}
|
|
|
|
// line 325 - some weird formatting here
|
|
|
|
zcrexp.push_back(parser.readString());
|
|
|
|
parser.readString();
|
|
|
|
parser.endLine();
|
|
|
|
|
|
|
|
do // rest of file can be read normally
|
2012-08-25 11:44:51 +03:00
|
|
|
{
|
|
|
|
parser.readString(); //ignore 1st column with description
|
|
|
|
zcrexp.push_back(parser.readString());
|
|
|
|
}
|
|
|
|
while (parser.endLine());
|
2011-03-21 10:14:23 +02:00
|
|
|
}
|
2017-05-26 21:58:33 +02:00
|
|
|
if (VLC->modh->modules.COMMANDERS)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
CLegacyConfigParser parser("DATA/ZNPC00.TXT");
|
|
|
|
parser.endLine();//header
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
znpc00.push_back(parser.readString());
|
|
|
|
} while (parser.endLine());
|
|
|
|
}
|
2018-10-29 17:41:54 +02:00
|
|
|
catch (const std::runtime_error &)
|
2017-05-26 21:58:33 +02:00
|
|
|
{
|
|
|
|
logGlobal->warn("WoG file ZNPC00.TXT containing commander texts was not found");
|
|
|
|
}
|
|
|
|
}
|
2009-01-11 00:08:18 +02:00
|
|
|
}
|
2017-07-04 13:24:46 +02:00
|
|
|
|
|
|
|
int32_t CGeneralTextHandler::pluralText(const int32_t textIndex, const int32_t count) const
|
|
|
|
{
|
|
|
|
if(textIndex == 0)
|
|
|
|
return 0;
|
|
|
|
else if(textIndex < 0)
|
|
|
|
return -textIndex;
|
2017-07-08 20:20:38 +02:00
|
|
|
else if(count == 1)
|
2017-07-04 13:24:46 +02:00
|
|
|
return textIndex;
|
|
|
|
else
|
|
|
|
return textIndex + 1;
|
|
|
|
}
|