Sort the movement costs in the tooltip in ascending order (#3305)

Sort movement costs in tooltip, unit preview pane, and unit description alphabetically.
This commit is contained in:
lilinitsy 2018-07-22 16:49:53 -05:00 committed by Jyrki Vesterinen
parent aea5d67f93
commit 61b7e7298b
3 changed files with 234 additions and 170 deletions

View file

@ -144,6 +144,13 @@ static inline std::string get_hp_tooltip(const utils::string_map& res, const std
static inline std::string get_mp_tooltip(int total_movement, std::function<int (t_translation::terrain_code)> get)
{
auto movement_compare = [](std::pair<t_string, int> a, std::pair<t_string, int> b)
{
return translation::icompare(a.first, b.first) < 0;
};
// terrain_moves pair: first: name, second: movement_cost
std::set<std::pair<t_string, int>, decltype(movement_compare)> terrain_moves(movement_compare);
std::ostringstream tooltip;
tooltip << "<big>" << _("Movement Costs:") << "</big>";
@ -160,37 +167,42 @@ static inline std::string get_mp_tooltip(int total_movement, std::function<int (
const terrain_type& info = tdata->get_terrain_info(terrain);
if(info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) {
const std::string& name = info.name();
const int moves = get(terrain);
tooltip << '\n' << font::unicode_bullet << " " << name << ": ";
// movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
const bool cannot_move = moves > total_movement;
std::string color;
if(cannot_move) {
// cannot move in this terrain
color = "red";
} else if(moves > 1) {
color = "yellow";
} else {
color = "white";
}
tooltip << "\t<span color='" << color << "'>";
// 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 > total_movement + 5)) {
tooltip << font::unicode_figure_dash;
} else {
tooltip << moves;
}
tooltip << "</span>";
terrain_moves.emplace(info.name(), get(terrain));
}
}
for(const std::pair<t_string, int> tm: terrain_moves)
{
const std::string name = tm.first;
const int moves = tm.second;
tooltip << '\n' << font::unicode_bullet << " " << name << ": ";
// movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
const bool cannot_move = moves > total_movement;
std::string color;
if(cannot_move) {
// cannot move in this terrain
color = "red";
} else if(moves > 1) {
color = "yellow";
} else {
color = "white";
}
tooltip << "<span color='" << color << "'>";
// 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 > total_movement + 5)) {
tooltip << font::unicode_figure_dash;
} else {
tooltip << moves;
}
tooltip << "</span>";
}
return tooltip.str();
}

View file

@ -49,6 +49,17 @@ namespace help
{
namespace
{
struct terrain_movement_info
{
const t_string name;
const t_string id;
const int defense;
const int movement_cost;
const int vision_cost;
const int jamming_cost;
const bool defense_cap;
};
std::string yes_no_str(bool value)
{
// TODO: do we want these translated?
@ -296,6 +307,12 @@ static void print_trait_list(std::ostringstream & ss, const std::vector<trait_da
std::string unit_topic_generator::generate() const
{
#if 0
// Used for sorting terrain_movement_info terrain_moves. Needs to be declared before terrain_moves.
auto movement_compare = [](terrain_movement_info a, terrain_movement_info b)
{
return translation::icompare(a.name, b.name) < 0;
};
// Force the lazy loading to build this unit.
unit_types.build_unit_type(type_, unit_type::FULL);
@ -709,7 +726,10 @@ std::string unit_topic_generator::generate() const
table.push_back(first_row);
std::set<t_translation::terrain_code>::const_iterator terrain_it = preferences::encountered_terrains().begin();
for(; terrain_it != preferences::encountered_terrains().end(); ++terrain_it) {
std::set<terrain_movement_info, decltype(movement_compare)> terrain_moves(movement_compare);
for (; terrain_it != preferences::encountered_terrains().end();
++terrain_it) {
const t_translation::terrain_code terrain = *terrain_it;
if(terrain == t_translation::FOGGED || terrain == t_translation::VOID_TERRAIN
|| t_translation::terrain_matches(terrain, t_translation::ALL_OFF_MAP)) {
@ -722,143 +742,163 @@ std::string unit_topic_generator::generate() const
continue;
}
if(info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) {
std::vector<item> row;
const std::string& name = info.name();
const std::string& id = info.id();
const int views = movement_type.vision_cost(terrain);
const int jams = movement_type.jamming_cost(terrain);
if (info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) {
terrain_movement_info movement_info =
{
info.name(),
info.id(),
100 - movement_type.defense_modifier(terrain),
moves,
movement_type.vision_cost(terrain),
movement_type.jamming_cost(terrain),
movement_type.get_defense().capped(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");
terrain_moves.insert(movement_info);
}
}
const std::string final_image = tc_base + "~RC(magenta>" + id + ")~BLIT(" + terrain_image + ")";
for(const terrain_movement_info &terr_move : terrain_moves)
{
std::vector<item> row;
const std::string& name = terr_move.name;
const std::string& id = terr_move.id;
const int defense = terr_move.defense;
const int moves = terr_move.movement_cost;
const int views = terr_move.vision_cost;
const int jams = terr_move.jamming_cost;
const bool has_cap = terr_move.defense_cap;
const bool cannot_move = moves > type_.movement();
row.emplace_back("<img>src='" + final_image + "'</img> " + 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) {
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.emplace_back("<img>src='" + final_image + "'</img> " +
make_link(name, "..terrain_" + id),
font::line_width(name, normal_font_size) + (high_res ? 32 : 16) );
//defense - range: +10 % .. +70 %
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 << "<format>color=" << color << " text='"<< defense << "%'</format>";
std::string markup = str.str();
str.str(clear_stringstream);
str << defense << "%";
row.emplace_back(markup, font::line_width(str.str(), normal_font_size));
//movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
str.str(clear_stringstream);
if (cannot_move) { // cannot move in this terrain
color = "red";
} else if (moves > 1) {
color = "yellow";
} else {
color = "white";
}
str << "<format>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 << font::unicode_figure_dash;
} else {
str << moves;
}
str << "'</format>";
markup = str.str();
str.str(clear_stringstream);
str << moves;
row.emplace_back(markup, font::line_width(str.str(), normal_font_size));
//defense cap
if (has_terrain_defense_caps) {
str.str(clear_stringstream);
if (has_cap) {
str << "<format>color='"<< color <<"' text='" << defense << "%'</format>";
} else {
str << "<format>color=white text='" << font::unicode_figure_dash << "'</format>";
}
markup = str.str();
str.str(clear_stringstream);
if (has_cap) {
str << defense << '%';
} else {
str << font::unicode_figure_dash;
}
row.emplace_back(markup, font::line_width(str.str(), normal_font_size));
}
//vision
if (has_vision) {
str.str(clear_stringstream);
const bool cannot_view = views > type_.vision();
if (cannot_view) { // cannot view in this terrain
color = "red";
} else if(defense <= 30) {
} else if (views > moves) {
color = "yellow";
} else if(defense <= 50) {
} else if (views == moves) {
color = "white";
} else {
color = "green";
}
std::ostringstream str;
str << "<format>color=" << color << " text='" << defense << "%'</format>";
std::string markup = str.str();
str.str(clear_stringstream);
str << defense << "%";
row.emplace_back(markup, font::line_width(str.str(), normal_font_size));
// movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
str.str(clear_stringstream);
if(cannot_move) { // cannot move in this terrain
color = "red";
} else if(moves > 1) {
color = "yellow";
} else {
color = "white";
}
str << "<format>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)) {
// A 5 MP margin; if the vision costs go above
// the unit's vision + 5, we replace it with dashes.
if(cannot_view && (views > type_.vision() + 5)) {
str << font::unicode_figure_dash;
} else {
str << moves;
str << views;
}
str << "'</format>";
markup = str.str();
str.str(clear_stringstream);
str << moves;
str << views;
row.emplace_back(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 << "<format>color='" << color << "' text='" << defense << "%'</format>";
} else {
str << "<format>color=white text='" << font::unicode_figure_dash << "'</format>";
}
markup = str.str();
str.str(clear_stringstream);
if(has_cap) {
str << defense << '%';
} else {
str << font::unicode_figure_dash;
}
row.emplace_back(markup, font::line_width(str.str(), normal_font_size));
}
// vision
if(has_vision) {
str.str(clear_stringstream);
const bool cannot_view = views > type_.vision();
if(cannot_view) { // cannot view in this terrain
color = "red";
} else if(views > moves) {
color = "yellow";
} else if(views == moves) {
color = "white";
} else {
color = "green";
}
str << "<format>color=" << color << " text='";
// A 5 MP margin; if the vision costs go above
// the unit's vision + 5, we replace it with dashes.
if(cannot_view && (views > type_.vision() + 5)) {
str << font::unicode_figure_dash;
} else {
str << views;
}
str << "'</format>";
markup = str.str();
str.str(clear_stringstream);
str << views;
row.emplace_back(markup, 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 << "<format>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 << font::unicode_figure_dash;
} else {
str << jams;
}
str << "'</format>";
push_tab_pair(row, str.str());
}
table.push_back(row);
}
}
//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 << "<format>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 << font::unicode_figure_dash;
} else {
str << jams;
}
str << "'</format>";
push_tab_pair(row, str.str());
}
table.push_back(row);
}
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 "

View file

@ -581,6 +581,15 @@ static config unit_moves(reports::context & rc, const unit* u)
if (!u) return config();
std::ostringstream str, tooltip;
double movement_frac = 1.0;
auto movement_compare = [](std::pair<t_string, int> a, std::pair<t_string, int> b)
{
return translation::icompare(a.first, b.first) < 0;
};
// terrain_moves pair: first: name, second: movement_cost
std::set<std::pair<t_string, int>, decltype(movement_compare)> terrain_moves(movement_compare);
if (u->side() == rc.screen().playing_side()) {
movement_frac = static_cast<double>(u->movement_left()) / std::max<int>(1, u->total_movement());
if (movement_frac > 1.0)
@ -600,33 +609,36 @@ static config unit_moves(reports::context & rc, const unit* u)
const terrain_type& info = rc.map().get_terrain_info(terrain);
if (info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) {
const std::string& name = info.name();
const int moves = u->movement_cost(terrain);
tooltip << name << ": ";
std::string color;
//movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
const bool cannot_move = moves > u->total_movement();
if (cannot_move) // cannot move in this terrain
color = "red";
else if (moves > 1)
color = "yellow";
else
color = "white";
tooltip << "<span foreground=\"" << color << "\">";
// 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 > u->total_movement() + 5)) {
tooltip << font::unicode_figure_dash;
} else {
tooltip << moves;
}
tooltip << naps << '\n';
terrain_moves.emplace(info.name(), u->movement_cost(terrain));
}
}
for(const std::pair<t_string, int> tm : terrain_moves)
{
const std::string name = tm.first;
const int moves = tm.second;
tooltip << name << ": ";
std::string color;
//movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
const bool cannot_move = moves > u->total_movement();
if (cannot_move) // cannot move in this terrain
color = "red";
else if (moves > 1)
color = "yellow";
else
color = "white";
tooltip << "<span foreground=\"" << color << "\">";
// 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 > u->total_movement() + 5)) {
tooltip << font::unicode_figure_dash;
} else {
tooltip << moves;
}
tooltip << naps << '\n';
}
int grey = 128 + static_cast<int>((255 - 128) * movement_frac);
color_t c = color_t(grey, grey, grey);
str << span_color(c) << u->movement_left() << '/' << u->total_movement() << naps;