diff --git a/docs/changelog.txt b/docs/changelog.txt index 0c6b35fab..f819587de 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -57,6 +57,7 @@ Template for new versions: ## Fixes - `autolabor`: now unconditionally re-enables vanilla work details when the fort or the plugin is unloaded +- ``dfhack.TranslateName()``: fixed crash on certain invalid names, which affected `warn-starving` ## Misc Improvements - `dig`: `digtype` command now has options to choose between designating only visible tiles or hidden tiles, as well as "auto" dig mode. Z-level options adjusted to allow choosing z-levels above, below, or the same as the cursor. diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 282039c02..af06eeb49 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -131,6 +131,37 @@ void Translation::setNickname(df::language_name *name, std::string nick) } } +static string translate_word(const df::language_name * name, size_t word_idx) { + CHECK_NULL_POINTER(name); + + auto translation = vector_get(world->raws.language.translations, name->language); + if (!translation) + return ""; + + auto word = vector_get(translation->words, word_idx); + if (!word) + return ""; + + return *word; +} + +static string translate_english_word(const df::language_name * name, size_t part_idx) { + CHECK_NULL_POINTER(name); + + if (part_idx >= 7) + return ""; + + auto words = vector_get(world->raws.language.words, name->words[part_idx]); + if (!words) + return ""; + + df::part_of_speech part = name->parts_of_speech[part_idx]; + if (part < df::part_of_speech::Noun || part > df::part_of_speech::VerbGerund) + return ""; + + return words->forms[part]; +} + string Translation::TranslateName(const df::language_name * name, bool inEnglish, bool onlyLastPart) { CHECK_NULL_POINTER(name); @@ -166,20 +197,20 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish { word.clear(); if (name->words[0] >= 0) - word.append(*world->raws.language.translations[name->language]->words[name->words[0]]); + word.append(translate_word(name, name->words[0])); if (name->words[1] >= 0) - word.append(*world->raws.language.translations[name->language]->words[name->words[1]]); + word.append(translate_word(name, name->words[1])); addNameWord(out, word); } word.clear(); for (int i = 2; i <= 5; i++) if (name->words[i] >= 0) - word.append(*world->raws.language.translations[name->language]->words[name->words[i]]); + word.append(translate_word(name, name->words[i])); addNameWord(out, word); if (name->words[6] >= 0) { word.clear(); - word.append(*world->raws.language.translations[name->language]->words[name->words[6]]); + word.append(translate_word(name, name->words[6])); addNameWord(out, word); } } @@ -189,9 +220,9 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish { word.clear(); if (name->words[0] >= 0) - word.append(world->raws.language.words[name->words[0]]->forms[name->parts_of_speech[0]]); + word.append(translate_english_word(name, 0)); if (name->words[1] >= 0) - word.append(world->raws.language.words[name->words[1]]->forms[name->parts_of_speech[1]]); + word.append(translate_english_word(name, 1)); addNameWord(out, word); } if (name->words[2] >= 0 || name->words[3] >= 0 || name->words[4] >= 0 || name->words[5] >= 0) @@ -201,10 +232,10 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish else out.append("The"); } - for (int i = 2; i <= 5; i++) + for (size_t i = 2; i <= 5; i++) { if (name->words[i] >= 0) - addNameWord(out, world->raws.language.words[name->words[i]]->forms[name->parts_of_speech[i]]); + addNameWord(out, translate_english_word(name, i)); } if (name->words[6] >= 0) { @@ -213,7 +244,7 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish else out.append("Of"); - addNameWord(out, world->raws.language.words[name->words[6]]->forms[name->parts_of_speech[6]]); + addNameWord(out, translate_english_word(name, 6)); } } diff --git a/plugins/autoslab.cpp b/plugins/autoslab.cpp index e78314bfd..82333c822 100644 --- a/plugins/autoslab.cpp +++ b/plugins/autoslab.cpp @@ -151,24 +151,6 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out) return CR_OK; } -// Name functions taken from manipulator.cpp -static std::string get_first_name(df::unit *unit) -{ - return Translation::capitalize(unit->name.first_name); -} - -static std::string get_last_name(df::unit *unit) -{ - df::language_name name = unit->name; - std::string ret = ""; - for (int i = 0; i < 2; i++) - { - if (name.words[i] >= 0) - ret += *world->raws.language.translations[name.language]->words[name.words[i]]; - } - return Translation::capitalize(ret); -} - // Queue up a single order to engrave the slab for the given unit static void createSlabJob(df::unit *unit) { @@ -212,7 +194,7 @@ static void checkslabs(color_ostream &out) ) { createSlabJob(ghost); - auto fullName = get_first_name(ghost) + " " + get_last_name(ghost); + auto fullName = Translation::TranslateName(&ghost->name, false); out.print("Added slab order for ghost %s\n", fullName.c_str()); } }