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:
parent
aea5d67f93
commit
61b7e7298b
3 changed files with 234 additions and 170 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue