Auto generate sections for all eras and their factions

This fills Feature Request #22107.
This commit is contained in:
Chris Beck 2014-07-20 16:37:29 -04:00
parent 1380842904
commit b5e0684411
2 changed files with 111 additions and 53 deletions

View file

@ -1,7 +1,7 @@
#textdomain wesnoth-help
[help]
[toplevel]
sections=introduction,gameplay,units,abilities_section,traits_section,weapon_specials,factions_section,terrains_section,addons,commands,encyclopedia
sections=introduction,gameplay,units,abilities_section,traits_section,weapon_specials,eras_section,terrains_section,addons,commands,encyclopedia
topics=about,license
[/toplevel]
@ -52,10 +52,12 @@
[/section]
[section]
id=factions_section
title= _ "Factions"
generator=factions
sort_topics=generated
id=eras_section
title= _ "Eras"
sections_generator=eras
sort_sections=generated
sort_topics=yes
topics=..eras_section
[/section]
[section]
@ -95,6 +97,17 @@
generator="contents:generated"
[/topic]
[topic]
id=..eras_section
title= _ "Eras"
text=_"A faction is a collection of units and leaders. Factions are assigned to sides in multiplayer games.
" + _"An era is a collection of factions, intended to be played against one another. Besides the mainline eras that come with the game, many user-made factions are available from add-ons.
"
generator="contents:generated"
[/topic]
[topic]
id=..abilities_section
title= _ "Abilities"
@ -569,7 +582,9 @@ Single-player campaigns are collections of scenarios that fit together to tell a
For gameplay purposes, various races of creatures in the world cooperate with each other in factions. Factions are grouped in balanced sets with a common theme; for example, the main factions of Wesnoth can be found in the included Default Era.
In <italic>text='Multiplayer'</italic> mode, you can choose an era when creating a new game, and players can pick from the available factions for that era when setting up their sides and teams." + _ "
In <italic>text='Multiplayer'</italic> mode, you can choose an era when creating a new game, and players can pick from the available factions for that era when setting up their sides and teams." + _"
You can see what eras you have loaded in the <ref>text='eras' dst='..eras_section'</ref> of the help." + _ "
<header>text='Multiplayer Modifications'</header>" + _ "

View file

@ -48,6 +48,10 @@
static lg::log_domain log_display("display");
#define WRN_DP LOG_STREAM(warn, log_display)
static lg::log_domain log_help("help");
#define WRN_HP LOG_STREAM(warn, log_help)
#define DBG_HP LOG_STREAM(debug, log_help)
namespace help {
help_button::help_button(display& disp, const std::string &help_topic)
@ -542,7 +546,10 @@ enum UNIT_DESCRIPTION_TYPE {FULL_DESCRIPTION, NO_DESCRIPTION, NON_REVEALING_DESC
static UNIT_DESCRIPTION_TYPE description_type(const unit_type &type);
static std::vector<topic> generate_ability_topics(const bool);
static std::vector<topic> generate_weapon_special_topics(const bool);
static std::vector<topic> generate_faction_topics(const bool);
static void generate_era_sections(const config *help_cfg, section &sec, int level);
static std::vector<topic> generate_faction_topics(const config &, const bool);
static std::vector<topic> generate_era_topics(const bool, const std::string & era_id);
/// Parse a help config, return the top level section. Return an empty
/// section if cfg is NULL.
@ -628,6 +635,7 @@ namespace {
const std::string terrain_prefix = "terrain_";
const std::string race_prefix = "race_";
const std::string faction_prefix = "faction_";
const std::string era_prefix = "era_";
const std::string variation_prefix = "variation_";
// id starting with '.' are hidden
@ -1030,12 +1038,14 @@ std::vector<topic> generate_topics(const bool sort_generated,const std::string &
res = generate_ability_topics(sort_generated);
} else if (generator == "weapon_specials") {
res = generate_weapon_special_topics(sort_generated);
} else if (generator == "factions") {
res = generate_faction_topics(sort_generated);
} else {
std::vector<std::string> parts = utils::split(generator, ':', utils::STRIP_SPACES);
if (parts[0] == "units" && parts.size()>1) {
res = generate_unit_topics(sort_generated, parts[1]);
} else if (parts[0] == "era" && parts.size()>1) {
res = generate_era_topics(sort_generated, parts[1]);
} else {
WRN_HP << "Found a topic generator that I didn't recognize: " << generator << "\n";
}
}
@ -1048,10 +1058,15 @@ void generate_sections(const config *help_cfg, const std::string &generator, sec
generate_races_sections(help_cfg, sec, level);
} else if (generator == "terrains") {
generate_terrain_sections(help_cfg, sec, level);
} else if (generator == "eras") {
DBG_HP << "Generating eras...\n";
generate_era_sections(help_cfg, sec, level);
} else {
std::vector<std::string> parts = utils::split(generator, ':', utils::STRIP_SPACES);
if (parts[0] == "units" && parts.size()>1) {
generate_unit_sections(help_cfg, sec, level, true, parts[1]);
} else {
WRN_HP << "Found a section generator that I didn't recognize: " << generator << "\n";
}
}
}
@ -1232,45 +1247,17 @@ std::vector<topic> generate_ability_topics(const bool sort_generated)
return topics;
}
std::vector<topic> generate_faction_topics(const bool sort_generated)
std::vector<topic> generate_era_topics(const bool sort_generated, const std::string & era_id)
{
std::vector<topic> topics;
const config& era = game_cfg->child("era");
if (era) {
const config & era = game_cfg->find_child("era","id", era_id);
if(era) {
topics = generate_faction_topics(era, sort_generated);
std::vector<std::string> faction_links;
BOOST_FOREACH(const config &f, era.child_range("multiplayer_side")) {
const std::string& id = f["id"];
if (id == "Random")
continue;
std::stringstream text;
const config::attribute_value& description = f["description"];
if (!description.empty()) {
text << description.t_str() << "\n";
text << "\n";
}
text << "<header>text='" << _("Leaders:") << "'</header>" << "\n";
const std::vector<std::string> leaders =
make_unit_links_list( utils::split(f["leader"]), true );
BOOST_FOREACH(const std::string &link, leaders) {
text << link << "\n";
}
text << "\n";
text << "<header>text='" << _("Recruits:") << "'</header>" << "\n";
const std::vector<std::string> recruits =
make_unit_links_list( utils::split(f["recruit"]), true );
BOOST_FOREACH(const std::string &link, recruits) {
text << link << "\n";
}
const std::string name = f["name"];
const std::string ref_id = faction_prefix + id;
topics.push_back( topic(name, ref_id, text.str()) );
faction_links.push_back(make_link(name, ref_id));
BOOST_FOREACH(const topic & t, topics) {
faction_links.push_back(make_link(t.title, t.id));
}
std::stringstream text;
@ -1289,12 +1276,49 @@ std::vector<topic> generate_faction_topics(const bool sort_generated)
text << link << "\n";
}
topics.push_back( topic(_("Factions"), "..factions_section", text.str()) );
} else {
topics.push_back( topic( _("Factions"), "..factions_section",
_("Factions are only used in multiplayer")) );
}
topic era_topic(era["name"], ".." + era_prefix + era["id"].str(), text.str());
topics.push_back( era_topic );
}
return topics;
}
std::vector<topic> generate_faction_topics(const config & era, const bool sort_generated)
{
std::vector<topic> topics;
BOOST_FOREACH(const config &f, era.child_range("multiplayer_side")) {
const std::string& id = f["id"];
if (id == "Random")
continue;
std::stringstream text;
const config::attribute_value& description = f["description"];
if (!description.empty()) {
text << description.t_str() << "\n";
text << "\n";
}
text << "<header>text='" << _("Leaders:") << "'</header>" << "\n";
const std::vector<std::string> leaders =
make_unit_links_list( utils::split(f["leader"]), true );
BOOST_FOREACH(const std::string &link, leaders) {
text << link << "\n";
}
text << "\n";
text << "<header>text='" << _("Recruits:") << "'</header>" << "\n";
const std::vector<std::string> recruits =
make_unit_links_list( utils::split(f["recruit"]), true );
BOOST_FOREACH(const std::string &link, recruits) {
text << link << "\n";
}
const std::string name = f["name"];
const std::string ref_id = faction_prefix + id;
topics.push_back( topic(name, ref_id, text.str()) );
}
if (sort_generated)
std::sort(topics.begin(), topics.end(), title_less());
return topics;
@ -1392,7 +1416,7 @@ public:
ss << type_.help_topic_text().str() << "\n";
if (!display::get_singleton()) {
WRN_DP << "When building terrain help topics, the display object was null and we couldn't finish.\n";
WRN_HP << "When building terrain help topics, the display object was null and we couldn't finish.\n";
return ss.str();
} // abort early if we can't get a gamemap object from the display
const gamemap & map = display::get_singleton()->get_disp_context().map();
@ -2021,7 +2045,7 @@ public:
ss << generate_table(table);
} else {
WRN_DP << "When building unit help topics, the display object was null and we couldn't get the terrain info we need.\n";
WRN_HP << "When building unit help topics, the display object was null and we couldn't get the terrain info we need.\n";
}
return ss.str();
}
@ -2108,10 +2132,29 @@ void generate_races_sections(const config *help_cfg, section &sec, int level)
}
}
void generate_era_sections(const config* help_cfg, section & sec, int level)
{
BOOST_FOREACH(const config & era, game_cfg->child_range("era")) {
DBG_HP << "Adding help section: " << era["id"].str() << "\n";
section era_section;
config section_cfg;
section_cfg["id"] = era_prefix + era["id"].str();
section_cfg["title"] = era["name"];
section_cfg["generator"] = "era:" + era["id"].str();
DBG_HP << section_cfg.debug() << "\n";
parse_config_internal(help_cfg, &section_cfg, era_section, level+1);
sec.add_section(era_section);
}
}
void generate_terrain_sections(const config* /*help_cfg*/, section& sec, int /*level*/)
{
if (display::get_singleton() == NULL) {
WRN_DP << "When building terrain help sections, the display object was null, aborting.\n";
WRN_HP << "When building terrain help sections, the display object was null, aborting.\n";
return;
}