Show [race]help_taxonomy= as "This is a group of units, all of whom are $help_taxonomy" (#5143)

The code comments talk about both Dunefolk and Quenoth Elves - of these two, only the
Dunefolk's data is changed in this commit. All Quenoth unit are race=elf at the moment,
I intend to add [race]id=quenoth in a separate PR.

Draft documentation for the Wiki:

* '''help_taxonomy''': {{DevFeature1.15|?}} in the help browser, show this
race as a group of units from another race; the value of this attribute should
be the other race's '''id''' attribute. This only affects the help browser, for
all other purposes (such as WML filters) the two races are completely separate.

How this is visualised in the help browser is a GUI design decision, this attribute
merely tells the engine that the relationship exists.
This commit is contained in:
Steve Cotton 2020-09-13 15:20:48 +02:00 committed by GitHub
parent e704f11237
commit f3f1407ace
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 7 deletions

View file

@ -209,6 +209,7 @@ The eastern provinces of Wesnoth, known as the Clan Homelands, have a geography
male_name= _"race^Dunefolk Human"
female_name= _"race+female^Dunefolk Human"
plural_name= _"race+plural^Dunefolk"
help_taxonomy=human
description= _"An offshoot of a forgotten nomadic civilization, the Dunefolk lay claim to the river valleys and oases of the Sandy Wastes. How they came to inhabit this far corner of the Great Continent is unknown. Their legends tell of many long and perilous travels through far-flung lands, but the true origin of their people is a topic of endless and heated debate among even the most erudite of their scholars.
Whatever their origin, the Dunefolk have thrived. Bustling cities stand proudly in the largest fertile regions. Skilled artisans, fine smiths, and wealthy merchants form the backbone of the urban economy. Each of these cities also enjoys a degree of independence less common in the more centralized nations to the north, many even maintaining their own standing armies. In times of need, however, each and all rally to a higher authority designated to protect the superior interest of the nation.

View file

@ -10,6 +10,7 @@
{SIMPLE_KEY description t_string}
{SIMPLE_KEY num_traits int}
{SIMPLE_KEY undead_variation string}
{SIMPLE_KEY help_taxonomy string}
{SIMPLE_KEY ignore_global_traits bool}
# Name generation
{SIMPLE_KEY male_names t_string}

View file

@ -18,6 +18,7 @@
#include "actions/attack.hpp" // for time_of_day bonus
#include "display.hpp" // for display
#include "display_context.hpp" // for display_context
#include "formula/string_utils.hpp" // for VGETTEXT
#include "game_config.hpp" // for debug, menu_contract, etc
#include "game_config_manager.hpp" // for game_config_manager
#include "preferences/game.hpp" // for encountered_terrains, etc
@ -958,9 +959,11 @@ std::vector<topic> generate_unit_topics(const bool sort_generated, const std::st
std::string race_id = "..race_"+race;
std::string race_name;
std::string race_description;
std::string race_help_taxonomy;
if (const unit_race *r = unit_types.find_race(race)) {
race_name = r->plural_name();
race_description = r->description();
race_help_taxonomy = r->help_taxonomy();
// if (description.empty()) description = _("No description Available");
for (const config &additional_topic : r->additional_topics())
{
@ -977,6 +980,17 @@ std::vector<topic> generate_unit_topics(const bool sort_generated, const std::st
// description = _("Here put the description of the Miscellaneous race");
}
// Find any other races whose [race]help_taxonomy points to the current race
std::map<std::string, t_string> subgroups;
for (const auto &r : unit_types.races()) {
if (r.second.help_taxonomy() == race) {
if (!r.second.plural_name().empty())
subgroups[r.first] = r.second.plural_name();
else
subgroups[r.first] = r.first;
}
}
std::stringstream text;
if (!race_description.empty()) {
@ -992,9 +1006,40 @@ std::vector<topic> generate_unit_topics(const bool sort_generated, const std::st
text << "\n\n";
}
text << _("<header>text='Units of this race'</header>") << "\n";
for (std::set<std::string, string_less>::iterator u = race_units.begin(); u != race_units.end(); ++u) {
text << font::unicode_bullet << " " << (*u) << "\n";
if (!race_help_taxonomy.empty()) {
utils::string_map symbols;
symbols["topic_id"] = "..race_"+race_help_taxonomy;
if (const unit_race *r = unit_types.find_race(race_help_taxonomy)) {
symbols["help_taxonomy"] = r->plural_name();
} else {
// Fall back to using showing the race id for the race that we couldn't find.
// Not great, but probably useful if UMC has a broken link.
symbols["help_taxonomy"] = race_help_taxonomy;
}
// TRANSLATORS: this is expected to say "[Dunefolk are] a group of units, all of whom are Humans",
// or "[Quenoth Elves are] a group of units, all of whom are Elves".
text << VGETTEXT("This is a group of units, all of whom are <ref>dst='$topic_id' text='$help_taxonomy'</ref>", symbols) << "\n\n";
}
if (!subgroups.empty()) {
if (!race_help_taxonomy.empty()) {
text << _("<header>text='Subgroups of units within this group'</header>") << "\n";
} else {
text << _("<header>text='Groups of units within this race'</header>") << "\n";
}
for (const auto &sg : subgroups) {
text << font::unicode_bullet << " " << make_link(sg.second, "..race_" + sg.first) << "\n";
}
text << "\n";
}
if (!race_help_taxonomy.empty()) {
text << _("<header>text='Units of this group'</header>") << "\n";
} else {
text << _("<header>text='Units of this race'</header>") << "\n";
}
for (const auto &u : race_units) {
text << font::unicode_bullet << " " << u << "\n";
}
topics.emplace_back(race_name, race_id, text.str());
@ -1114,8 +1159,6 @@ void section::clear()
sections.clear();
}
const topic *find_topic(const section &sec, const std::string &id)
{
topic_list::const_iterator tit =
@ -1148,6 +1191,11 @@ const section *find_section(const section &sec, const std::string &id)
return nullptr;
}
section *find_section(section &sec, const std::string &id)
{
return const_cast<section *>(find_section(const_cast<const section &>(sec), id));
}
std::vector<std::string> parse_text(const std::string &text)
{
std::vector<std::string> res;

View file

@ -280,6 +280,7 @@ const topic *find_topic(const section &sec, const std::string &id);
/// and its subsections. Return the found section or nullptr if none could
/// be found.
const section *find_section(const section &sec, const std::string &id);
section *find_section(section &sec, const std::string &id);
/// Parse a text string. Return a vector with the different parts of the
/// text. Each markup item is a separate part while the text between

View file

@ -54,7 +54,8 @@ unit_race::unit_race() :
traits_(empty_traits().child_range("trait")),
topics_(empty_topics().child_range("topic")),
global_traits_(true),
undead_variation_()
undead_variation_(),
help_taxonomy_()
{
for(auto& generator : name_generator_) {
generator.reset(new name_generator());
@ -71,7 +72,8 @@ unit_race::unit_race(const config& cfg) :
traits_(cfg.child_range("trait")),
topics_(cfg.child_range("topic")),
global_traits_(!cfg["ignore_global_traits"].to_bool()),
undead_variation_(cfg["undead_variation"])
undead_variation_(cfg["undead_variation"]),
help_taxonomy_(cfg["help_taxonomy"])
{
if (id_.empty()) {

View file

@ -62,6 +62,8 @@ public:
*/
std::string get_icon_path_stem() const;
const std::string& help_taxonomy() const { return help_taxonomy_; }
/// Dummy race used when a race is not yet known.
static const unit_race null_race;
@ -83,6 +85,7 @@ private:
config::const_child_itors topics_;
bool global_traits_;
std::string undead_variation_;
std::string help_taxonomy_;
};
unit_race::GENDER string_gender(const std::string& str,unit_race::GENDER def=unit_race::MALE);