diff --git a/src/help/help_topic_generators.cpp b/src/help/help_topic_generators.cpp index 8120f88c025c..93b6bb70f404 100644 --- a/src/help/help_topic_generators.cpp +++ b/src/help/help_topic_generators.cpp @@ -230,483 +230,501 @@ static void print_trait_list(std::stringstream & ss, const std::vectorsrc='" << male_type.image() << "~XBRZ(2)' box='no' "; + ss << "src='" << male_type.image() << "~XBRZ(2)' box='no' "; #else - ss << "src='" << male_type.image() << "~RC(" << male_type.flag_rgb() << ">red)~XBRZ(2)' box='no' "; + ss << "src='" << male_type.image() << "~RC(" << male_type.flag_rgb() << ">red)~XBRZ(2)' box='no' "; #endif - if (&female_type != &male_type) + if (&female_type != &male_type) { #ifdef LOW_MEM - ss << "src='" << female_type.image() << "~XBRZ(2)' box='no' "; + ss << "src='" << female_type.image() << "~XBRZ(2)' box='no' "; #else - ss << "src='" << female_type.image() << "~RC(" << female_type.flag_rgb() << ">red)~XBRZ(2)' box='no' "; + ss << "src='" << female_type.image() << "~RC(" << female_type.flag_rgb() << ">red)~XBRZ(2)' box='no' "; #endif + } - const std::string &male_portrait = male_type.small_profile().empty() ? - male_type.big_profile() : male_type.small_profile(); - const std::string &female_portrait = female_type.small_profile().empty() ? - female_type.big_profile() : female_type.small_profile(); ; + const std::string &male_portrait = male_type.small_profile().empty() ? + male_type.big_profile() : male_type.small_profile(); + const std::string &female_portrait = female_type.small_profile().empty() ? + female_type.big_profile() : female_type.small_profile(); - // TODO: figure out why the second checks don't match but the last does - if (!male_portrait.empty() && male_portrait != male_type.image() && male_portrait != "unit_image") { - ss << "src='" << male_portrait << "~FL(horiz)' box='no' align='right' float='yes' "; - } + // TODO: figure out why the second checks don't match but the last does + if (!male_portrait.empty() && male_portrait != male_type.image() && male_portrait != "unit_image") { + ss << "src='" << male_portrait << "~FL(horiz)' box='no' align='right' float='yes' "; + } - ss << "\n\n"; + ss << "\n\n"; - if (!female_portrait.empty() && female_portrait != male_portrait && female_portrait != female_type.image() && female_portrait != "unit_image") { - ss << "src='" << female_portrait << "~FL(horiz)' box='no' align='right' float='yes' "; - } + if (!female_portrait.empty() && female_portrait != male_portrait && female_portrait != female_type.image() && female_portrait != "unit_image") { + ss << "src='" << female_portrait << "~FL(horiz)' box='no' align='right' float='yes' "; + } - ss << "\n"; + ss << "\n"; - // Print cross-references to units that this unit advances from/to. - // Cross reference to the topics containing information about those units. - const bool first_reverse_value = true; - bool reverse = first_reverse_value; - if (variation_.empty()) { - do { - std::vector adv_units = - reverse ? type_.advances_from() : type_.advances_to(); - bool first = true; - - BOOST_FOREACH(const std::string &adv, adv_units) - { - const unit_type *type = unit_types.find(adv, unit_type::HELP_INDEXED); - if (!type || type->hide_help()) continue; - - if (first) { - if (reverse) - ss << _("Advances from: "); - else - ss << _("Advances to: "); - first = false; - } else - ss << ", "; - - std::string lang_unit = type->type_name(); - std::string ref_id; - if (description_type(*type) == FULL_DESCRIPTION) { - const std::string section_prefix = type->show_variations_in_help() ? ".." : ""; - ref_id = section_prefix + unit_prefix + type->id(); - } else { - ref_id = unknown_unit_topic; - lang_unit += " (?)"; - } - ss << make_link(lang_unit, ref_id); + // Print cross-references to units that this unit advances from/to. + // Cross reference to the topics containing information about those units. + const bool first_reverse_value = true; + bool reverse = first_reverse_value; + if (variation_.empty()) { + do { + std::vector adv_units = + reverse ? type_.advances_from() : type_.advances_to(); + bool first = true; + + BOOST_FOREACH(const std::string &adv, adv_units) { + const unit_type *type = unit_types.find(adv, unit_type::HELP_INDEXED); + if (!type || type->hide_help()) { + continue; } - if (!first) ss << "\n"; - reverse = !reverse; //switch direction - } while(reverse != first_reverse_value); // don't restart - } - - const unit_type* parent = variation_.empty() ? &type_ : - unit_types.find(type_.id(), unit_type::HELP_INDEXED); - if (!variation_.empty()) { - ss << _("Base unit: ") << make_link(parent->type_name(), ".." + unit_prefix + type_.id()) << "\n"; - } else { - bool first = true; - BOOST_FOREACH(const std::string& base_id, utils::split(type_.get_cfg()["base_ids"])) { if (first) { - ss << _("Base units: "); + if (reverse) { + ss << _("Advances from: "); + } else { + ss << _("Advances to: "); + } first = false; + } else { + ss << ", "; } - const unit_type* base_type = unit_types.find(base_id, unit_type::HELP_INDEXED); - const std::string section_prefix = base_type->show_variations_in_help() ? ".." : ""; - ss << make_link(base_type->type_name(), section_prefix + unit_prefix + base_id) << "\n"; - } - } - - bool first = true; - BOOST_FOREACH(const std::string &var_id, parent->variations()) { - const unit_type &type = parent->get_variation(var_id); - if(type.hide_help()) { - continue; + std::string lang_unit = type->type_name(); + std::string ref_id; + if (description_type(*type) == FULL_DESCRIPTION) { + const std::string section_prefix = type->show_variations_in_help() ? ".." : ""; + ref_id = section_prefix + unit_prefix + type->id(); + } else { + ref_id = unknown_unit_topic; + lang_unit += " (?)"; + } + ss << make_link(lang_unit, ref_id); + } + if (!first) { + ss << "\n"; } + reverse = !reverse; //switch direction + } while(reverse != first_reverse_value); // don't restart + } + + const unit_type* parent = variation_.empty() ? &type_ : + unit_types.find(type_.id(), unit_type::HELP_INDEXED); + if (!variation_.empty()) { + ss << _("Base unit: ") << make_link(parent->type_name(), ".." + unit_prefix + type_.id()) << "\n"; + } else { + bool first = true; + BOOST_FOREACH(const std::string& base_id, utils::split(type_.get_cfg()["base_ids"])) { if (first) { - ss << _("Variations: "); + ss << _("Base units: "); first = false; - } else - ss << ", "; - - std::string ref_id; - - std::string var_name = type.variation_name(); - if (description_type(type) == FULL_DESCRIPTION) { - ref_id = variation_prefix + type.id() + "_" + var_id; - } else { - ref_id = unknown_unit_topic; - var_name += " (?)"; } + const unit_type* base_type = unit_types.find(base_id, unit_type::HELP_INDEXED); + const std::string section_prefix = base_type->show_variations_in_help() ? ".." : ""; + ss << make_link(base_type->type_name(), section_prefix + unit_prefix + base_id) << "\n"; + } + } - ss << make_link(var_name, ref_id); + bool first = true; + BOOST_FOREACH(const std::string &var_id, parent->variations()) { + const unit_type &type = parent->get_variation(var_id); + + if(type.hide_help()) { + continue; } - ss << "\n"; //added even if empty, to avoid shifting - - // Print the race of the unit, cross-reference it to the - // respective topic. - const std::string race_id = type_.race_id(); - std::string race_name = type_.race()->plural_name(); - if ( race_name.empty() ) { - race_name = _ ("race^Miscellaneous"); + + if (first) { + ss << _("Variations: "); + first = false; + } else { + ss << ", "; } - ss << _("Race: "); - ss << make_link(race_name, "..race_" + race_id); - ss << "\n\n"; - // Print the possible traits of the unit, cross-reference them - // to their respective topics. - config::const_child_itors traits = type_.possible_traits(); - if (traits.first != traits.second && type_.num_traits() > 0) { - std::vector must_have_traits; - std::vector random_traits; - - BOOST_FOREACH(const config & trait, traits) { - const std::string trait_name = trait["male_name"]; - std::string lang_trait_name = translation::gettext(trait_name.c_str()); - const std::string ref_id = "traits_"+trait["id"].str(); - ((trait["availability"].str() == "musthave") ? must_have_traits : random_traits).push_back(std::make_pair(lang_trait_name, ref_id)); - } + std::string ref_id; - bool line1 = !must_have_traits.empty(); - bool line2 = !random_traits.empty() && type_.num_traits() - must_have_traits.size() > 0; + std::string var_name = type.variation_name(); + if (description_type(type) == FULL_DESCRIPTION) { + ref_id = variation_prefix + type.id() + "_" + var_id; + } else { + ref_id = unknown_unit_topic; + var_name += " (?)"; + } - if (line1) { - std::string traits_label = _("Traits"); - ss << traits_label; - if (line2) { - std::stringstream must_have_count; - must_have_count << " (" << must_have_traits.size() << ") : "; - std::stringstream random_count; - random_count << " (" << (type_.num_traits() - must_have_traits.size()) << ") : "; + ss << make_link(var_name, ref_id); + } + ss << "\n"; //added even if empty, to avoid shifting - int second_line_whitespace = font::line_width(traits_label+must_have_count.str(), normal_font_size) - font::line_width(random_count.str(), normal_font_size); // This ensures that the second line is justified so that the ':' characters are aligned. + // Print the race of the unit, cross-reference it to the respective topic. + const std::string race_id = type_.race_id(); + std::string race_name = type_.race()->plural_name(); + if (race_name.empty()) { + race_name = _ ("race^Miscellaneous"); + } + ss << _("Race: "); + ss << make_link(race_name, "..race_" + race_id); + ss << "\n\n"; + + // Print the possible traits of the unit, cross-reference them + // to their respective topics. + config::const_child_itors traits = type_.possible_traits(); + if (traits.first != traits.second && type_.num_traits() > 0) { + std::vector must_have_traits; + std::vector random_traits; + + BOOST_FOREACH(const config & trait, traits) { + const std::string trait_name = trait["male_name"]; + std::string lang_trait_name = translation::gettext(trait_name.c_str()); + const std::string ref_id = "traits_"+trait["id"].str(); + ((trait["availability"].str() == "musthave") ? must_have_traits : random_traits).push_back(std::make_pair(lang_trait_name, ref_id)); + } - ss << must_have_count.str(); - print_trait_list(ss, must_have_traits); - ss << "\n" << jump(second_line_whitespace) << random_count.str(); - print_trait_list(ss, random_traits); - } else { - ss << ": "; - print_trait_list(ss, must_have_traits); - } - ss << "\n\n"; + bool line1 = !must_have_traits.empty(); + bool line2 = !random_traits.empty() && type_.num_traits() - must_have_traits.size() > 0; + + if (line1) { + std::string traits_label = _("Traits"); + ss << traits_label; + if (line2) { + std::stringstream must_have_count; + must_have_count << " (" << must_have_traits.size() << ") : "; + std::stringstream random_count; + random_count << " (" << (type_.num_traits() - must_have_traits.size()) << ") : "; + + int second_line_whitespace = font::line_width(traits_label+must_have_count.str(), normal_font_size) + - font::line_width(random_count.str(), normal_font_size); + // This ensures that the second line is justified so that the ':' characters are aligned. + + ss << must_have_count.str(); + print_trait_list(ss, must_have_traits); + ss << "\n" << jump(second_line_whitespace) << random_count.str(); + print_trait_list(ss, random_traits); } else { - if (line2) { - ss << _("Traits") << " (" << type_.num_traits() << ") : "; - print_trait_list(ss, random_traits); - ss << "\n\n"; - } + ss << ": "; + print_trait_list(ss, must_have_traits); + } + ss << "\n\n"; + } else { + if (line2) { + ss << _("Traits") << " (" << type_.num_traits() << ") : "; + print_trait_list(ss, random_traits); + ss << "\n\n"; } } + } - // Print the abilities the units has, cross-reference them - // to their respective topics. TODO: Update this according to musthave trait effects, similar to movetype below - if (!type_.abilities().empty()) { - ss << _("Abilities: "); - for(std::vector::const_iterator ability_it = type_.abilities().begin(), - ability_end = type_.abilities().end(); - ability_it != ability_end; ++ability_it) { - const std::string ref_id = "ability_" + ability_it->base_str(); - std::string lang_ability = translation::gettext(ability_it->c_str()); - ss << make_link(lang_ability, ref_id); - if (ability_it + 1 != ability_end) - ss << ", "; + // Print the abilities the units has, cross-reference them + // to their respective topics. TODO: Update this according to musthave trait effects, similar to movetype below + if (!type_.abilities().empty()) { + ss << _("Abilities: "); + for(std::vector::const_iterator ability_it = type_.abilities().begin(), + ability_end = type_.abilities().end(); + ability_it != ability_end; ++ability_it) { + const std::string ref_id = "ability_" + ability_it->base_str(); + std::string lang_ability = translation::gettext(ability_it->c_str()); + ss << make_link(lang_ability, ref_id); + if (ability_it + 1 != ability_end) { + ss << ", "; } - ss << "\n\n"; } + ss << "\n\n"; + } - // Print the extra AMLA upgrade abilities, cross-reference them - // to their respective topics. - if (!type_.adv_abilities().empty()) { - ss << _("Ability Upgrades: "); - for(std::vector::const_iterator ability_it = type_.adv_abilities().begin(), - ability_end = type_.adv_abilities().end(); - ability_it != ability_end; ++ability_it) { - const std::string ref_id = "ability_" + ability_it->base_str(); - std::string lang_ability = translation::gettext(ability_it->c_str()); - ss << make_link(lang_ability, ref_id); - if (ability_it + 1 != ability_end) - ss << ", "; + // Print the extra AMLA upgrade abilities, cross-reference them to their respective topics. + if (!type_.adv_abilities().empty()) { + ss << _("Ability Upgrades: "); + for(std::vector::const_iterator ability_it = type_.adv_abilities().begin(), + ability_end = type_.adv_abilities().end(); + ability_it != ability_end; ++ability_it) { + const std::string ref_id = "ability_" + ability_it->base_str(); + std::string lang_ability = translation::gettext(ability_it->c_str()); + ss << make_link(lang_ability, ref_id); + if (ability_it + 1 != ability_end) { + ss << ", "; } - ss << "\n\n"; } + ss << "\n\n"; + } - // Print some basic information such as HP and movement points. - // TODO: Make this info update according to musthave traits, similar to movetype below. - ss << _("HP: ") << type_.hitpoints() << jump(30) - << _("Moves: ") << type_.movement() << jump(30); - if (type_.vision() != type_.movement()) - ss << _("Vision: ") << type_.vision() << jump(30); - if (type_.jamming() > 0) - ss << _("Jamming: ") << type_.jamming() << jump(30); - ss << _("Cost: ") << type_.cost() << jump(30) - << _("Alignment: ") - << make_link(type_.alignment_description(type_.alignment(), type_.genders().front()), "time_of_day") - << jump(30); - if (type_.can_advance()) - ss << _("Required XP: ") << type_.experience_needed(); - - // Print the detailed description about the unit. + // Print some basic information such as HP and movement points. + // TODO: Make this info update according to musthave traits, similar to movetype below. + ss << _("HP: ") << type_.hitpoints() << jump(30) + << _("Moves: ") << type_.movement() << jump(30); + if (type_.vision() != type_.movement()) { + ss << _("Vision: ") << type_.vision() << jump(30); + } + if (type_.jamming() > 0) { + ss << _("Jamming: ") << type_.jamming() << jump(30); + } + ss << _("Cost: ") << type_.cost() << jump(30) + << _("Alignment: ") + << make_link(type_.alignment_description(type_.alignment(), type_.genders().front()), "time_of_day") + << jump(30); + if (type_.can_advance()) { + ss << _("Required XP: ") << type_.experience_needed(); + } + + // Print the detailed description about the unit. ss << "\n\n" << detailed_description; - // Print the different attacks a unit has, if it has any. - std::vector attacks = type_.attacks(); - if (!attacks.empty()) { - // Print headers for the table. - ss << "\n\n
text='" << escape(_("unit help^Attacks")) - << "'
\n\n"; - table_spec table; - - std::vector first_row; - // Dummy element, icons are below. - first_row.push_back(item("", 0)); - push_header(first_row, _("unit help^Name")); - push_header(first_row, _("Type")); - push_header(first_row, _("Strikes")); - push_header(first_row, _("Range")); - push_header(first_row, _("Special")); - table.push_back(first_row); - // Print information about every attack. - for(std::vector::const_iterator attack_it = attacks.begin(), - attack_end = attacks.end(); - attack_it != attack_end; ++attack_it) { - std::string lang_weapon = attack_it->name(); - std::string lang_type = string_table["type_" + attack_it->type()]; - std::vector row; - std::stringstream attack_ss; - attack_ss << "src='" << (*attack_it).icon() << "'"; - row.push_back(std::make_pair(attack_ss.str(), - image_width(attack_it->icon()))); - push_tab_pair(row, lang_weapon); - push_tab_pair(row, lang_type); - attack_ss.str(clear_stringstream); - attack_ss << attack_it->damage() << utils::unicode_en_dash << attack_it->num_attacks() << " " << attack_it->accuracy_parry_description(); - push_tab_pair(row, attack_ss.str()); - attack_ss.str(clear_stringstream); - if ((*attack_it).min_range() > 1 || (*attack_it).max_range() > 1) - attack_ss << (*attack_it).min_range() << "-" << (*attack_it).max_range() << ' '; - attack_ss << string_table["range_" + (*attack_it).range()]; - push_tab_pair(row, attack_ss.str()); - attack_ss.str(clear_stringstream); - // Show this attack's special, if it has any. Cross - // reference it to the section describing the - // special. - std::vector > specials = attack_it->special_tooltips(); - if(!specials.empty()) - { - std::string lang_special = ""; - const size_t specials_size = specials.size(); - for ( size_t i = 0; i != specials_size; ++i) { - const std::string ref_id = std::string("weaponspecial_") - + specials[i].first.base_str(); - lang_special = (specials[i].first); - attack_ss << make_link(lang_special, ref_id); - if ( i+1 != specials_size ) - attack_ss << ", "; //comma placed before next special + // Print the different attacks a unit has, if it has any. + std::vector attacks = type_.attacks(); + if (!attacks.empty()) { + // Print headers for the table. + ss << "\n\n
text='" << escape(_("unit help^Attacks")) + << "'
\n\n"; + table_spec table; + + std::vector first_row; + // Dummy element, icons are below. + first_row.push_back(item("", 0)); + push_header(first_row, _("unit help^Name")); + push_header(first_row, _("Type")); + push_header(first_row, _("Strikes")); + push_header(first_row, _("Range")); + push_header(first_row, _("Special")); + table.push_back(first_row); + // Print information about every attack. + for(std::vector::const_iterator attack_it = attacks.begin(), + attack_end = attacks.end(); + attack_it != attack_end; ++attack_it) { + std::string lang_weapon = attack_it->name(); + std::string lang_type = string_table["type_" + attack_it->type()]; + std::vector row; + std::stringstream attack_ss; + attack_ss << "src='" << (*attack_it).icon() << "'"; + row.push_back(std::make_pair(attack_ss.str(),image_width(attack_it->icon()))); + push_tab_pair(row, lang_weapon); + push_tab_pair(row, lang_type); + attack_ss.str(clear_stringstream); + attack_ss << attack_it->damage() << utils::unicode_en_dash << attack_it->num_attacks() + << " " << attack_it->accuracy_parry_description(); + push_tab_pair(row, attack_ss.str()); + attack_ss.str(clear_stringstream); + if ((*attack_it).min_range() > 1 || (*attack_it).max_range() > 1) { + attack_ss << (*attack_it).min_range() << "-" << (*attack_it).max_range() << ' '; + } + attack_ss << string_table["range_" + (*attack_it).range()]; + push_tab_pair(row, attack_ss.str()); + attack_ss.str(clear_stringstream); + // Show this attack's special, if it has any. Cross + // reference it to the section describing the special. + std::vector > specials = attack_it->special_tooltips(); + if (!specials.empty()) { + std::string lang_special = ""; + const size_t specials_size = specials.size(); + for (size_t i = 0; i != specials_size; ++i) { + const std::string ref_id = std::string("weaponspecial_") + + specials[i].first.base_str(); + lang_special = (specials[i].first); + attack_ss << make_link(lang_special, ref_id); + if (i+1 != specials_size) { + attack_ss << ", "; //comma placed before next special } - row.push_back(std::make_pair(attack_ss.str(), - font::line_width(lang_special, normal_font_size))); } - table.push_back(row); + row.push_back(std::make_pair(attack_ss.str(), + font::line_width(lang_special, normal_font_size))); } - ss << generate_table(table); + table.push_back(row); } + ss << generate_table(table); + } - // Generate the movement type of the unit, with resistance, defense, movement, jamming and vision data updated according to any 'musthave' traits which always apply - movetype movement_type = type_.movement_type(); - traits = type_.possible_traits(); - if (traits.first != traits.second && type_.num_traits() > 0) { - BOOST_FOREACH(const config & t, traits) { - if (t["availability"].str() == "musthave") { - BOOST_FOREACH (const config & effect, t.child_range("effect")) { - if (!effect.child("filter") // If this is musthave but has a unit filter, it might not always apply, so don't apply it in the help. + // Generate the movement type of the unit, with resistance, defense, movement, jamming and vision data updated according to any 'musthave' traits which always apply + movetype movement_type = type_.movement_type(); + traits = type_.possible_traits(); + if (traits.first != traits.second && type_.num_traits() > 0) { + BOOST_FOREACH(const config & t, traits) { + if (t["availability"].str() == "musthave") { + BOOST_FOREACH (const config & effect, t.child_range("effect")) { + if (!effect.child("filter") // If this is musthave but has a unit filter, it might not always apply, so don't apply it in the help. && movetype::effects.find(effect["apply_to"].str()) != movetype::effects.end()) { - movement_type.merge(effect, effect["replace"].to_bool()); - } + movement_type.merge(effect, effect["replace"].to_bool()); } } } } + } - // Print the resistance table of the unit. - ss << "\n\n
text='" << escape(_("Resistances")) - << "'
\n\n"; - table_spec resistance_table; - std::vector first_res_row; - push_header(first_res_row, _("Attack Type")); - push_header(first_res_row, _("Resistance")); - resistance_table.push_back(first_res_row); - utils::string_map dam_tab = movement_type.damage_table(); - for(utils::string_map::const_iterator dam_it = dam_tab.begin(), dam_end = dam_tab.end(); - dam_it != dam_end; ++dam_it) { - std::vector row; - int resistance = 100 - atoi((*dam_it).second.c_str()); - char resi[16]; - snprintf(resi,sizeof(resi),"% 4d%%",resistance); // range: -100% .. +70% - std::string resist = resi; - const size_t pos = resist.find('-'); - if (pos != std::string::npos) - resist.replace(pos, 1, utils::unicode_minus); - std::string color = unit_helper::resistance_color(resistance); - std::string lang_weapon = string_table["type_" + dam_it->first]; - push_tab_pair(row, lang_weapon); - std::stringstream str; - str << "color=\"" << color << "\" text='"<< resist << "'"; - const std::string markup = str.str(); - str.str(clear_stringstream); - str << resist; - row.push_back(std::make_pair(markup, - font::line_width(str.str(), normal_font_size))); - resistance_table.push_back(row); + // Print the resistance table of the unit. + ss << "\n\n
text='" << escape(_("Resistances")) + << "'
\n\n"; + table_spec resistance_table; + std::vector first_res_row; + push_header(first_res_row, _("Attack Type")); + push_header(first_res_row, _("Resistance")); + resistance_table.push_back(first_res_row); + utils::string_map dam_tab = movement_type.damage_table(); + for (utils::string_map::const_iterator dam_it = dam_tab.begin(), dam_end = dam_tab.end(); + dam_it != dam_end; ++dam_it) { + std::vector row; + int resistance = 100 - atoi((*dam_it).second.c_str()); + char resi[16]; + snprintf(resi,sizeof(resi),"% 4d%%",resistance); // range: -100% .. +70% + std::string resist = resi; + const size_t pos = resist.find('-'); + if (pos != std::string::npos) { + resist.replace(pos, 1, utils::unicode_minus); + } + std::string color = unit_helper::resistance_color(resistance); + std::string lang_weapon = string_table["type_" + dam_it->first]; + push_tab_pair(row, lang_weapon); + std::stringstream str; + str << "color=\"" << color << "\" text='"<< resist << "'"; + const std::string markup = str.str(); + str.str(clear_stringstream); + str << resist; + row.push_back(std::make_pair(markup, + font::line_width(str.str(), normal_font_size))); + resistance_table.push_back(row); + } + ss << generate_table(resistance_table); + + if (tdata_cache tdata = load_terrain_types_data()) { + // Print the terrain modifier table of the unit. + ss << "\n\n
text='" << escape(_("Terrain Modifiers")) + << "'
\n\n"; + std::vector first_row; + table_spec table; + push_header(first_row, _("Terrain")); + push_header(first_row, _("Defense")); + push_header(first_row, _("Movement Cost")); + + const bool has_terrain_defense_caps = movement_type.has_terrain_defense_caps(preferences::encountered_terrains()); + if (has_terrain_defense_caps) { + push_header(first_row, _("Defense Cap")); } - ss << generate_table(resistance_table); - - if (tdata_cache tdata = load_terrain_types_data()) { - // Print the terrain modifier table of the unit. - ss << "\n\n
text='" << escape(_("Terrain Modifiers")) - << "'
\n\n"; - std::vector first_row; - table_spec table; - push_header(first_row, _("Terrain")); - push_header(first_row, _("Defense")); - push_header(first_row, _("Movement Cost")); - - const bool has_terrain_defense_caps = movement_type.has_terrain_defense_caps(preferences::encountered_terrains()); - if ( has_terrain_defense_caps ) - push_header(first_row, _("Defense Cap")); - - const bool has_vision = type_.movement_type().has_vision_data(); - if ( has_vision ) - push_header(first_row, _("Vision Cost")); - const bool has_jamming = type_.movement_type().has_jamming_data(); - if ( has_jamming ) - push_header(first_row, _("Jamming Cost")); - - table.push_back(first_row); - std::set::const_iterator terrain_it = - preferences::encountered_terrains().begin(); - - - for (; terrain_it != preferences::encountered_terrains().end(); - ++terrain_it) { - const t_translation::t_terrain terrain = *terrain_it; - if (terrain == t_translation::FOGGED || terrain == t_translation::VOID_TERRAIN || terrain == t_translation::OFF_MAP_USER) - continue; - const terrain_type& info = tdata->get_terrain_info(terrain); - - if (info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) { - std::vector row; - const std::string& name = info.name(); - const std::string& id = info.id(); - const int moves = movement_type.movement_cost(terrain); - const int views = movement_type.vision_cost(terrain); - const int jams = movement_type.jamming_cost(terrain); - - bool high_res = false; - const std::string tc_base = high_res ? "images/buttons/icon-base-32.png" : "images/buttons/icon-base-16.png"; - const std::string terrain_image = "icons/terrain/terrain_type_" + id + (high_res ? "_30.png" : ".png"); - - const std::string final_image = tc_base + "~RC(magenta>" + id + ")~BLIT(" + terrain_image + ")"; - - row.push_back(std::make_pair( "src='" + final_image + "' " + - make_link(name, "..terrain_" + id), - font::line_width(name, normal_font_size) + (high_res ? 32 : 16) )); - - //defense - range: +10 % .. +70 % - const int defense = - 100 - movement_type.defense_modifier(terrain); - std::string color; - if (defense <= 10) - color = "red"; - else if (defense <= 30) - color = "yellow"; - else if (defense <= 50) - color = "white"; - else - color = "green"; - std::stringstream str; - str << "color=" << color << " text='"<< defense << "%'"; - std::string markup = str.str(); - str.str(clear_stringstream); - str << defense << "%"; - row.push_back(std::make_pair(markup, - font::line_width(str.str(), normal_font_size))); + const bool has_vision = type_.movement_type().has_vision_data(); + if (has_vision) { + push_header(first_row, _("Vision Cost")); + } + const bool has_jamming = type_.movement_type().has_jamming_data(); + if (has_jamming) { + push_header(first_row, _("Jamming Cost")); + } + + table.push_back(first_row); + std::set::const_iterator terrain_it = + preferences::encountered_terrains().begin(); + + for (; terrain_it != preferences::encountered_terrains().end(); + ++terrain_it) { + const t_translation::t_terrain terrain = *terrain_it; + if (terrain == t_translation::FOGGED || terrain == t_translation::VOID_TERRAIN || terrain == t_translation::OFF_MAP_USER) { + continue; + } + const terrain_type& info = tdata->get_terrain_info(terrain); + + if (info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) { + std::vector row; + const std::string& name = info.name(); + const std::string& id = info.id(); + const int moves = movement_type.movement_cost(terrain); + const int views = movement_type.vision_cost(terrain); + const int jams = movement_type.jamming_cost(terrain); + + bool high_res = false; + const std::string tc_base = high_res ? "images/buttons/icon-base-32.png" : "images/buttons/icon-base-16.png"; + const std::string terrain_image = "icons/terrain/terrain_type_" + id + (high_res ? "_30.png" : ".png"); + + const std::string final_image = tc_base + "~RC(magenta>" + id + ")~BLIT(" + terrain_image + ")"; + + row.push_back(std::make_pair( "src='" + final_image + "' " + + make_link(name, "..terrain_" + id), + font::line_width(name, normal_font_size) + (high_res ? 32 : 16) )); + + //defense - range: +10 % .. +70 % + const int defense = 100 - movement_type.defense_modifier(terrain); + std::string color; + if (defense <= 10) { + color = "red"; + } else if (defense <= 30) { + color = "yellow"; + } else if (defense <= 50) { + color = "white"; + } else { + color = "green"; + } - //movement - range: 1 .. 5, movetype::UNREACHABLE=impassable + std::stringstream str; + str << "color=" << color << " text='"<< defense << "%'"; + std::string markup = str.str(); + str.str(clear_stringstream); + str << defense << "%"; + row.push_back(std::make_pair(markup, + font::line_width(str.str(), normal_font_size))); + + //movement - range: 1 .. 5, movetype::UNREACHABLE=impassable + str.str(clear_stringstream); + const bool cannot_move = moves > type_.movement(); + if (cannot_move) { // cannot move in this terrain + color = "red"; + } else if (moves > 1) { + color = "yellow"; + } else { + color = "white"; + } + str << "color=" << color << " text='"; + // A 5 MP margin; if the movement costs go above + // the unit's max moves + 5, we replace it with dashes. + if(cannot_move && (moves > type_.movement() + 5)) { + str << utils::unicode_figure_dash; + } else { + str << moves; + } + str << "'"; + markup = str.str(); + str.str(clear_stringstream); + str << moves; + row.push_back(std::make_pair(markup, + font::line_width(str.str(), normal_font_size))); + + //defense cap + if (has_terrain_defense_caps) { str.str(clear_stringstream); - const bool cannot_move = moves > type_.movement(); - if (cannot_move) // cannot move in this terrain - color = "red"; - else if (moves > 1) - color = "yellow"; - else - color = "white"; - str << "color=" << color << " text='"; - // A 5 MP margin; if the movement costs go above - // the unit's max moves + 5, we replace it with dashes. - if(cannot_move && (moves > type_.movement() + 5)) { - str << utils::unicode_figure_dash; + const bool has_cap = movement_type.get_defense().capped(terrain); + if (has_cap) { + str << "color='"<< color <<"' text='" << defense << "%'"; } else { - str << moves; + str << "color=white text='" << utils::unicode_figure_dash << "'"; } - str << "'"; markup = str.str(); str.str(clear_stringstream); - str << moves; - row.push_back(std::make_pair(markup, - font::line_width(str.str(), normal_font_size))); - - //defense cap - if ( has_terrain_defense_caps ) { - str.str(clear_stringstream); - const bool has_cap = movement_type.get_defense().capped(terrain); - if (has_cap) { - str << "color='"<< color <<"' text='" << defense << "%'"; - } else { - str << "color=white text='" << utils::unicode_figure_dash << "'"; - } - markup = str.str(); - str.str(clear_stringstream); - if (has_cap) { - str << defense << '%'; - } else { - str << utils::unicode_figure_dash; - } - row.push_back(std::make_pair(markup, - font::line_width(str.str(), normal_font_size))); + if (has_cap) { + str << defense << '%'; + } else { + str << utils::unicode_figure_dash; } + row.push_back(std::make_pair(markup, + font::line_width(str.str(), normal_font_size))); + } - //vision - if ( has_vision ) { + //vision + if (has_vision) { str.str(clear_stringstream); const bool cannot_view = views > type_.vision(); - if (cannot_view) // cannot view in this terrain + if (cannot_view) { // cannot view in this terrain color = "red"; - else if ( views > moves ) + } else if (views > moves) { color = "yellow"; - else if ( views == moves ) + } else if (views == moves) { color = "white"; - else + } else { color = "green"; + } str << "color=" << color << " text='"; // A 5 MP margin; if the vision costs go above // the unit's vision + 5, we replace it with dashes. @@ -720,43 +738,44 @@ std::string unit_topic_generator::operator()() const { str.str(clear_stringstream); str << views; row.push_back(std::make_pair(markup, - font::line_width(str.str(), normal_font_size))); + font::line_width(str.str(), normal_font_size))); } - //jamming - if ( has_jamming ) { - str.str(clear_stringstream); - const bool cannot_jam = jams > type_.jamming(); - if ( cannot_jam ) // cannot jamm in this terrain - color = "red"; - else if ( jams > views ) - color = "yellow"; - else if ( jams == views ) - color = "white"; - else - color = "green"; - str << "color=" << color << " text='"; - // A 5 MP margin; if the jamming costs go above - // the unit's jamming + 5, we replace it with dashes. - if ( cannot_jam && jams > type_.jamming() + 5 ) { - str << utils::unicode_figure_dash; - } else { - str << jams; - } - str << "'"; - - push_tab_pair(row, str.str()); + //jamming + if (has_jamming) { + str.str(clear_stringstream); + const bool cannot_jam = jams > type_.jamming(); + if (cannot_jam) { // cannot jamm in this terrain + color = "red"; + } else if (jams > views) { + color = "yellow"; + } else if (jams == views) { + color = "white"; + } else { + color = "green"; + } + str << "color=" << color << " text='"; + // A 5 MP margin; if the jamming costs go above + // the unit's jamming + 5, we replace it with dashes. + if ( cannot_jam && jams > type_.jamming() + 5 ) { + str << utils::unicode_figure_dash; + } else { + str << jams; } + str << "'"; - table.push_back(row); + push_tab_pair(row, str.str()); } - } - ss << generate_table(table); - } else { - WRN_HP << "When building unit help topics, the display object was null and we couldn't get the terrain info we need.\n"; + table.push_back(row); + } } - return ss.str(); + + ss << generate_table(table); + } else { + 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(); } } // end namespace help