You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.3 KiB
117 lines
3.3 KiB
|
6 years ago
|
/**
|
||
|
|
* @file textdat.cpp
|
||
|
|
*
|
||
|
|
* Implementation of all dialog texts.
|
||
|
|
*/
|
||
|
2 months ago
|
#include "tables/textdat.h"
|
||
|
7 months ago
|
|
||
|
7 months ago
|
#include <ankerl/unordered_dense.h>
|
||
|
|
#include <fmt/core.h>
|
||
|
7 months ago
|
#include <magic_enum/magic_enum.hpp>
|
||
|
|
|
||
|
7 months ago
|
#include "data/file.hpp"
|
||
|
|
#include "data/record_reader.hpp"
|
||
|
|
#include "effects.h"
|
||
|
5 years ago
|
#include "utils/language.h"
|
||
|
8 years ago
|
|
||
|
5 years ago
|
namespace devilution {
|
||
|
7 years ago
|
|
||
|
8 years ago
|
/* todo: move text out of struct */
|
||
|
|
|
||
|
6 years ago
|
/** Contains the data related to each speech ID. */
|
||
|
7 months ago
|
std::vector<Speech> Speeches;
|
||
|
10 months ago
|
|
||
|
7 months ago
|
/** Contains the mapping between text ID strings and indices, used for parsing additional text data. */
|
||
|
|
ankerl::unordered_dense::map<std::string, int16_t> AdditionalTextIdStringsToIndices;
|
||
|
10 months ago
|
|
||
|
7 months ago
|
tl::expected<_speech_id, std::string> ParseSpeechId(std::string_view value)
|
||
|
|
{
|
||
|
|
if (value.empty()) {
|
||
|
|
return TEXT_NONE;
|
||
|
|
}
|
||
|
|
|
||
|
|
const std::optional<_speech_id> enumValueOpt = magic_enum::enum_cast<_speech_id>(value);
|
||
|
|
if (enumValueOpt.has_value()) {
|
||
|
|
return enumValueOpt.value();
|
||
|
|
}
|
||
|
7 months ago
|
|
||
|
|
const auto findIt = AdditionalTextIdStringsToIndices.find(std::string(value));
|
||
|
|
if (findIt != AdditionalTextIdStringsToIndices.end()) {
|
||
|
|
return static_cast<_speech_id>(findIt->second);
|
||
|
|
}
|
||
|
|
|
||
|
7 months ago
|
return tl::make_unexpected("Invalid value.");
|
||
|
|
}
|
||
|
|
|
||
|
7 months ago
|
namespace {
|
||
|
|
|
||
|
|
void LoadTextDatFromFile(DataFile &dataFile, std::string_view filename, bool grow)
|
||
|
|
{
|
||
|
|
dataFile.skipHeaderOrDie(filename);
|
||
|
|
|
||
|
|
if (grow) {
|
||
|
|
Speeches.reserve(Speeches.size() + dataFile.numRecords());
|
||
|
|
}
|
||
|
|
|
||
|
|
for (DataFileRecord record : dataFile) {
|
||
|
|
RecordReader reader { record, filename };
|
||
|
|
|
||
|
|
std::string txtstrid;
|
||
|
|
reader.readString("txtstrid", txtstrid);
|
||
|
|
|
||
|
|
if (txtstrid.empty()) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
const std::optional<_speech_id> speechIdEnumValueOpt = magic_enum::enum_cast<_speech_id>(txtstrid);
|
||
|
|
|
||
|
|
if (!speechIdEnumValueOpt.has_value()) {
|
||
|
|
const size_t textEntryIndex = Speeches.size();
|
||
|
|
const auto [it, inserted] = AdditionalTextIdStringsToIndices.emplace(txtstrid, static_cast<int16_t>(textEntryIndex));
|
||
|
|
if (!inserted) {
|
||
|
|
DisplayFatalErrorAndExit(_("Loading Text Data Failed"), fmt::format(fmt::runtime(_("A text data entry already exists for ID \"{}\".")), txtstrid));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// for hardcoded speeches, use their predetermined slot; for non-hardcoded ones, use the slots after that
|
||
|
|
Speech &speech = speechIdEnumValueOpt.has_value() ? Speeches[speechIdEnumValueOpt.value()] : Speeches.emplace_back();
|
||
|
|
|
||
|
|
reader.readString("txtstr", speech.txtstr);
|
||
|
|
|
||
|
|
{
|
||
|
|
std::string processed;
|
||
|
|
processed.reserve(speech.txtstr.size());
|
||
|
|
for (size_t i = 0; i < speech.txtstr.size();) {
|
||
|
|
if (i + 1 < speech.txtstr.size() && speech.txtstr[i] == '\\' && speech.txtstr[i + 1] == 'n') {
|
||
|
|
processed.push_back('\n');
|
||
|
|
i += 2;
|
||
|
|
} else {
|
||
|
|
processed.push_back(speech.txtstr[i]);
|
||
|
|
++i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
speech.txtstr = std::move(processed);
|
||
|
|
}
|
||
|
|
|
||
|
|
reader.readBool("scrlltxt", speech.scrlltxt);
|
||
|
|
reader.read("sfxnr", speech.sfxnr, ParseSfxId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
void LoadTextData()
|
||
|
|
{
|
||
|
|
const std::string_view filename = "txtdata\\text\\textdat.tsv";
|
||
|
|
DataFile dataFile = DataFile::loadOrDie(filename);
|
||
|
|
|
||
|
|
Speeches.clear();
|
||
|
|
AdditionalTextIdStringsToIndices.clear();
|
||
|
|
Speeches.resize(NUM_DEFAULT_TEXT_IDS); // ensure the hardcoded text entry slots are filled
|
||
|
|
LoadTextDatFromFile(dataFile, filename, false);
|
||
|
|
|
||
|
|
Speeches.shrink_to_fit();
|
||
|
|
}
|
||
|
|
|
||
|
5 years ago
|
} // namespace devilution
|